/[baselayout]/trunk/src/rc.c
Gentoo

Diff of /trunk/src/rc.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

Revision 2834 Revision 3040
18#include <sys/types.h> 18#include <sys/types.h>
19#include <sys/stat.h> 19#include <sys/stat.h>
20#include <sys/utsname.h> 20#include <sys/utsname.h>
21#include <sys/wait.h> 21#include <sys/wait.h>
22#include <errno.h> 22#include <errno.h>
23#include <dirent.h>
23#include <ctype.h> 24#include <ctype.h>
24#include <getopt.h> 25#include <getopt.h>
25#include <libgen.h> 26#include <libgen.h>
26#include <limits.h> 27#include <limits.h>
27#include <stdbool.h> 28#include <stdbool.h>
28#include <stdio.h> 29#include <stdio.h>
29#include <stdlib.h> 30#include <stdlib.h>
30#include <signal.h> 31#include <signal.h>
31#include <string.h> 32#include <string.h>
33#include <strings.h>
32#include <syslog.h> 34#include <syslog.h>
33#include <termios.h> 35#include <termios.h>
34#include <unistd.h> 36#include <unistd.h>
35 37
36#include "builtins.h" 38#include "builtins.h"
41#include "strlist.h" 43#include "strlist.h"
42 44
43#define INITSH RC_LIBDIR "/sh/init.sh" 45#define INITSH RC_LIBDIR "/sh/init.sh"
44#define INITEARLYSH RC_LIBDIR "/sh/init-early.sh" 46#define INITEARLYSH RC_LIBDIR "/sh/init-early.sh"
45#define HALTSH RC_INITDIR "/halt.sh" 47#define HALTSH RC_INITDIR "/halt.sh"
48
49#define SHUTDOWN "/sbin/shutdown"
46#define SULOGIN "/sbin/sulogin" 50#define SULOGIN "/sbin/sulogin"
47 51
48#define INTERACTIVE RC_SVCDIR "/interactive" 52#define INTERACTIVE RC_SVCDIR "/interactive"
49 53
50#define DEVBOOT "/dev/.rcboot" 54#define DEVBOOT "/dev/.rcboot"
59 63
60static char *RUNLEVEL = NULL; 64static char *RUNLEVEL = NULL;
61static char *PREVLEVEL = NULL; 65static char *PREVLEVEL = NULL;
62 66
63static char *applet = NULL; 67static char *applet = NULL;
68static char *runlevel = NULL;
64static char **env = NULL; 69static char **env = NULL;
65static char **newenv = NULL; 70static char **newenv = NULL;
66static char **coldplugged_services = NULL; 71static char **coldplugged_services = NULL;
67static char **stop_services = NULL; 72static char **stop_services = NULL;
68static char **start_services = NULL; 73static char **start_services = NULL;
69static rc_depinfo_t *deptree = NULL; 74static rc_depinfo_t *deptree = NULL;
70static char **types = NULL;
71static char *tmp = NULL; 75static char *tmp = NULL;
72 76
73struct termios *termios_orig = NULL; 77struct termios *termios_orig = NULL;
74 78
75typedef struct pidlist 79typedef struct pidlist
76{ 80{
77 pid_t pid; 81 pid_t pid;
78 struct pidlist *next; 82 struct pidlist *next;
79} pidlist_t; 83} pidlist_t;
80static pidlist_t *service_pids = NULL; 84static pidlist_t *service_pids = NULL;
85
86static const char *types_n[] = { "needsme", NULL };
87static const char *types_nua[] = { "ineed", "iuse", "iafter", NULL };
81 88
82static void cleanup (void) 89static void cleanup (void)
83{ 90{
84 if (applet && strcmp (applet, "rc") == 0) { 91 if (applet && strcmp (applet, "rc") == 0) {
85 pidlist_t *pl = service_pids; 92 pidlist_t *pl = service_pids;
100 rc_strlist_free (env); 107 rc_strlist_free (env);
101 rc_strlist_free (newenv); 108 rc_strlist_free (newenv);
102 rc_strlist_free (coldplugged_services); 109 rc_strlist_free (coldplugged_services);
103 rc_strlist_free (stop_services); 110 rc_strlist_free (stop_services);
104 rc_strlist_free (start_services); 111 rc_strlist_free (start_services);
105 rc_free_deptree (deptree); 112 rc_deptree_free (deptree);
106 rc_strlist_free (types);
107 113
108 /* Clean runlevel start, stop markers */ 114 /* Clean runlevel start, stop markers */
109 if (! rc_in_plugin) { 115 if (! rc_in_plugin) {
110 if (rc_is_dir (RC_SVCDIR "softscripts.new")) 116 rmdir (RC_STARTING);
111 rc_rm_dir (RC_SVCDIR "softscripts.new", true); 117 rmdir (RC_STOPPING);
112 if (rc_is_dir (RC_SVCDIR "softscripts.old"))
113 rc_rm_dir (RC_SVCDIR "softscripts.old", true);
114 } 118 }
119
120 free (runlevel);
115 } 121 }
116 122
117 free (applet); 123 free (applet);
118} 124}
119 125
141 char *fmt = NULL; 147 char *fmt = NULL;
142 int level = 0; 148 int level = 0;
143 149
144 if (strcmp (applet, "eval_ecolors") == 0) { 150 if (strcmp (applet, "eval_ecolors") == 0) {
145 printf ("GOOD='%s'\nWARN='%s'\nBAD='%s'\nHILITE='%s'\nBRACKET='%s'\nNORMAL='%s'\n", 151 printf ("GOOD='%s'\nWARN='%s'\nBAD='%s'\nHILITE='%s'\nBRACKET='%s'\nNORMAL='%s'\n",
146 ecolor (ecolor_good), 152 ecolor (ECOLOR_GOOD),
147 ecolor (ecolor_warn), 153 ecolor (ECOLOR_WARN),
148 ecolor (ecolor_bad), 154 ecolor (ECOLOR_BAD),
149 ecolor (ecolor_hilite), 155 ecolor (ECOLOR_HILITE),
150 ecolor (ecolor_bracket), 156 ecolor (ECOLOR_BRACKET),
151 ecolor (ecolor_normal)); 157 ecolor (ECOLOR_NORMAL));
152 exit (EXIT_SUCCESS); 158 exit (EXIT_SUCCESS);
153 } 159 }
154 160
155 if (argc > 0) { 161 if (argc > 0) {
156 162
170 } else if (strcmp (applet, "esyslog") == 0 || 176 } else if (strcmp (applet, "esyslog") == 0 ||
171 strcmp (applet, "elog") == 0) { 177 strcmp (applet, "elog") == 0) {
172 char *dot = strchr (argv[0], '.'); 178 char *dot = strchr (argv[0], '.');
173 if ((level = syslog_decode (dot + 1, prioritynames)) == -1) 179 if ((level = syslog_decode (dot + 1, prioritynames)) == -1)
174 eerrorx ("%s: invalid log level `%s'", applet, argv[0]); 180 eerrorx ("%s: invalid log level `%s'", applet, argv[0]);
181
182 if (argc < 3)
183 eerrorx ("%s: not enough arguments", applet);
184
185 unsetenv ("RC_ELOG");
186 setenv ("RC_ELOG", argv[1], 1);
187
175 argc--; 188 argc -= 2;
176 argv++; 189 argv += 2;
177 }
178 } 190 }
179 191 }
180 192
181 if (argc > 0) { 193 if (argc > 0) {
182 for (i = 0; i < argc; i++) 194 for (i = 0; i < argc; i++)
183 l += strlen (argv[i]) + 1; 195 l += strlen (argv[i]) + 1;
184 196
185 message = rc_xmalloc (l); 197 message = xmalloc (l);
186 p = message; 198 p = message;
187 199
188 for (i = 0; i < argc; i++) { 200 for (i = 0; i < argc; i++) {
189 if (i > 0) 201 if (i > 0)
190 *p++ = ' '; 202 *p++ = ' ';
193 } 205 }
194 *p = 0; 206 *p = 0;
195 } 207 }
196 208
197 if (message) 209 if (message)
198 fmt = rc_xstrdup ("%s"); 210 fmt = xstrdup ("%s");
199 211
200 if (strcmp (applet, "einfo") == 0) 212 if (strcmp (applet, "einfo") == 0)
201 einfo (fmt, message); 213 einfo (fmt, message);
202 else if (strcmp (applet, "einfon") == 0) 214 else if (strcmp (applet, "einfon") == 0)
203 einfon (fmt, message); 215 einfon (fmt, message);
259 271
260 if (argc < 1 || ! argv[0] || strlen (argv[0]) == 0) 272 if (argc < 1 || ! argv[0] || strlen (argv[0]) == 0)
261 eerrorx ("%s: no service specified", applet); 273 eerrorx ("%s: no service specified", applet);
262 274
263 if (strcmp (applet, "service_started") == 0) 275 if (strcmp (applet, "service_started") == 0)
264 ok = rc_service_state (argv[0], rc_service_started); 276 ok = (rc_service_state (argv[0]) & RC_SERVICE_STARTED);
265 else if (strcmp (applet, "service_stopped") == 0) 277 else if (strcmp (applet, "service_stopped") == 0)
266 ok = rc_service_state (argv[0], rc_service_stopped); 278 ok = (rc_service_state (argv[0]) & RC_SERVICE_STOPPED);
267 else if (strcmp (applet, "service_inactive") == 0) 279 else if (strcmp (applet, "service_inactive") == 0)
268 ok = rc_service_state (argv[0], rc_service_inactive); 280 ok = (rc_service_state (argv[0]) & RC_SERVICE_INACTIVE);
269 else if (strcmp (applet, "service_starting") == 0) 281 else if (strcmp (applet, "service_starting") == 0)
270 ok = rc_service_state (argv[0], rc_service_starting); 282 ok = (rc_service_state (argv[0]) & RC_SERVICE_STOPPING);
271 else if (strcmp (applet, "service_stopping") == 0) 283 else if (strcmp (applet, "service_stopping") == 0)
272 ok = rc_service_state (argv[0], rc_service_stopping); 284 ok = (rc_service_state (argv[0]) & RC_SERVICE_STOPPING);
273 else if (strcmp (applet, "service_coldplugged") == 0) 285 else if (strcmp (applet, "service_coldplugged") == 0)
274 ok = rc_service_state (argv[0], rc_service_coldplugged); 286 ok = (rc_service_state (argv[0]) & RC_SERVICE_COLDPLUGGED);
275 else if (strcmp (applet, "service_wasinactive") == 0) 287 else if (strcmp (applet, "service_wasinactive") == 0)
276 ok = rc_service_state (argv[0], rc_service_wasinactive); 288 ok = (rc_service_state (argv[0]) & RC_SERVICE_WASINACTIVE);
277 else if (strcmp (applet, "service_started_daemon") == 0) { 289 else if (strcmp (applet, "service_started_daemon") == 0) {
278 int idx = 0; 290 int idx = 0;
279 if (argc > 2) 291 if (argc > 2)
280 sscanf (argv[2], "%d", &idx); 292 sscanf (argv[2], "%d", &idx);
281 exit (rc_service_started_daemon (argv[0], argv[1], idx) 293 exit (rc_service_started_daemon (argv[0], argv[1], idx)
293 305
294 if (argc < 1 || ! argv[0] || strlen (argv[0]) == 0) 306 if (argc < 1 || ! argv[0] || strlen (argv[0]) == 0)
295 eerrorx ("%s: no service specified", applet); 307 eerrorx ("%s: no service specified", applet);
296 308
297 if (strcmp (applet, "mark_service_started") == 0) 309 if (strcmp (applet, "mark_service_started") == 0)
298 ok = rc_mark_service (argv[0], rc_service_started); 310 ok = rc_service_mark (argv[0], RC_SERVICE_STARTED);
299 else if (strcmp (applet, "mark_service_stopped") == 0) 311 else if (strcmp (applet, "mark_service_stopped") == 0)
300 ok = rc_mark_service (argv[0], rc_service_stopped); 312 ok = rc_service_mark (argv[0], RC_SERVICE_STOPPED);
301 else if (strcmp (applet, "mark_service_inactive") == 0) 313 else if (strcmp (applet, "mark_service_inactive") == 0)
302 ok = rc_mark_service (argv[0], rc_service_inactive); 314 ok = rc_service_mark (argv[0], RC_SERVICE_INACTIVE);
303 else if (strcmp (applet, "mark_service_starting") == 0) 315 else if (strcmp (applet, "mark_service_starting") == 0)
304 ok = rc_mark_service (argv[0], rc_service_starting); 316 ok = rc_service_mark (argv[0], RC_SERVICE_STOPPING);
305 else if (strcmp (applet, "mark_service_stopping") == 0) 317 else if (strcmp (applet, "mark_service_stopping") == 0)
306 ok = rc_mark_service (argv[0], rc_service_stopping); 318 ok = rc_service_mark (argv[0], RC_SERVICE_STOPPING);
307 else if (strcmp (applet, "mark_service_coldplugged") == 0) 319 else if (strcmp (applet, "mark_service_coldplugged") == 0)
308 ok = rc_mark_service (argv[0], rc_service_coldplugged); 320 ok = rc_service_mark (argv[0], RC_SERVICE_COLDPLUGGED);
321 else if (strcmp (applet, "mark_service_failed") == 0)
322 ok = rc_service_mark (argv[0], RC_SERVICE_FAILED);
309 else 323 else
310 eerrorx ("%s: unknown applet", applet); 324 eerrorx ("%s: unknown applet", applet);
311 325
312 /* If we're marking ourselves then we need to inform our parent runscript 326 /* If we're marking ourselves then we need to inform our parent runscript
313 process so they do not mark us based on our exit code */ 327 process so they do not mark us based on our exit code */
320 if (runscript_pid && sscanf (runscript_pid, "%d", &pid) == 1) 334 if (runscript_pid && sscanf (runscript_pid, "%d", &pid) == 1)
321 if (kill (pid, SIGHUP) != 0) 335 if (kill (pid, SIGHUP) != 0)
322 eerror ("%s: failed to signal parent %d: %s", 336 eerror ("%s: failed to signal parent %d: %s",
323 applet, pid, strerror (errno)); 337 applet, pid, strerror (errno));
324 338
325 /* Remove the exclsive time test. This ensures that it's not 339 /* Remove the exclusive time test. This ensures that it's not
326 in control as well */ 340 in control as well */
327 l = strlen (RC_SVCDIR "exclusive") + 341 l = strlen (RC_SVCDIR "exclusive") +
328 strlen (svcname) + 342 strlen (svcname) +
329 strlen (runscript_pid) + 343 strlen (runscript_pid) +
330 4; 344 4;
331 mtime = rc_xmalloc (l); 345 mtime = xmalloc (l);
332 snprintf (mtime, l, RC_SVCDIR "exclusive/%s.%s", 346 snprintf (mtime, l, RC_SVCDIR "exclusive/%s.%s",
333 svcname, runscript_pid); 347 svcname, runscript_pid);
334 if (rc_exists (mtime) && unlink (mtime) != 0) 348 if (exists (mtime) && unlink (mtime) != 0)
335 eerror ("%s: unlink: %s", applet, strerror (errno)); 349 eerror ("%s: unlink: %s", applet, strerror (errno));
336 free (mtime); 350 free (mtime);
337 } 351 }
338 352
339 return (ok ? EXIT_SUCCESS : EXIT_FAILURE); 353 return (ok ? EXIT_SUCCESS : EXIT_FAILURE);
349 363
350 if (argc < 1 || ! argv[0] || strlen (argv[0]) == 0) 364 if (argc < 1 || ! argv[0] || strlen (argv[0]) == 0)
351 eerrorx ("%s: no option specified", applet); 365 eerrorx ("%s: no option specified", applet);
352 366
353 if (strcmp (applet, "get_options") == 0) { 367 if (strcmp (applet, "get_options") == 0) {
354 char buffer[1024]; 368 char *option = rc_service_value_get (service, argv[0]);
355 memset (buffer, 0, 1024); 369 if (option) {
356 ok = rc_get_service_option (service, argv[0], buffer);
357 if (ok)
358 printf ("%s", buffer); 370 printf ("%s", option);
371 free (option);
372 ok = true;
373 }
359 } else if (strcmp (applet, "save_options") == 0) 374 } else if (strcmp (applet, "save_options") == 0)
360 ok = rc_set_service_option (service, argv[0], argv[1]); 375 ok = rc_service_value_set (service, argv[0], argv[1]);
361 else 376 else
362 eerrorx ("%s: unknown applet", applet); 377 eerrorx ("%s: unknown applet", applet);
363 378
364 return (ok ? EXIT_SUCCESS : EXIT_FAILURE); 379 return (ok ? EXIT_SUCCESS : EXIT_FAILURE);
365} 380}
366 381
367#ifdef __linux__ 382#ifdef __linux__
368static char *proc_getent (const char *ent) 383static char *proc_getent (const char *ent)
369{ 384{
370 FILE *fp; 385 FILE *fp;
371 char buffer[RC_LINEBUFFER]; 386 char *buffer;
372 char *p; 387 char *p;
373 char *value = NULL; 388 char *value = NULL;
374 int i; 389 int i;
375 390
391 if (! exists ("/proc/cmdline"))
392 return (NULL);
393
376 if (! (fp = fopen ("/proc/cmdline", "r"))) { 394 if (! (fp = fopen ("/proc/cmdline", "r"))) {
377 eerror ("failed to open `/proc/cmdline': %s", strerror (errno)); 395 eerror ("failed to open `/proc/cmdline': %s", strerror (errno));
378 return (NULL); 396 return (NULL);
379 } 397 }
380 398
381 memset (buffer, 0, sizeof (buffer)); 399 buffer = xmalloc (sizeof (char) * RC_LINEBUFFER);
400 memset (buffer, 0, RC_LINEBUFFER);
382 if (fgets (buffer, RC_LINEBUFFER, fp) && 401 if (fgets (buffer, RC_LINEBUFFER, fp) &&
383 (p = strstr (buffer, ent))) 402 (p = strstr (buffer, ent)))
384 { 403 {
385 i = p - buffer; 404 i = p - buffer;
386 if (i == '\0' || buffer[i - 1] == ' ') { 405 if (i == '\0' || buffer[i - 1] == ' ') {
390 buffer[i] = 0; 409 buffer[i] = 0;
391 410
392 p += strlen (ent); 411 p += strlen (ent);
393 if (*p == '=') 412 if (*p == '=')
394 p++; 413 p++;
395 value = strdup (strsep (&p, " ")); 414 value = xstrdup (strsep (&p, " "));
396 } 415 }
397 } else 416 } else
398 errno = ENOENT; 417 errno = ENOENT;
418 free (buffer);
399 fclose (fp); 419 fclose (fp);
400 420
401 return (value); 421 return (value);
402} 422}
403#endif 423#endif
405static char read_key (bool block) 425static char read_key (bool block)
406{ 426{
407 struct termios termios; 427 struct termios termios;
408 char c = 0; 428 char c = 0;
409 int fd = fileno (stdin); 429 int fd = fileno (stdin);
410 430
411 if (! isatty (fd)) 431 if (! isatty (fd))
412 return (false); 432 return (false);
413 433
414 /* Now save our terminal settings. We need to restore them at exit as we 434 /* Now save our terminal settings. We need to restore them at exit as we
415 will be changing it for non-blocking reads for Interactive */ 435 will be changing it for non-blocking reads for Interactive */
416 if (! termios_orig) { 436 if (! termios_orig) {
417 termios_orig = rc_xmalloc (sizeof (struct termios)); 437 termios_orig = xmalloc (sizeof (struct termios));
418 tcgetattr (fd, termios_orig); 438 tcgetattr (fd, termios_orig);
419 } 439 }
420 440
421 tcgetattr (fd, &termios); 441 tcgetattr (fd, &termios);
422 termios.c_lflag &= ~(ICANON | ECHO); 442 termios.c_lflag &= ~(ICANON | ECHO);
443 strcmp (PREVLEVEL, "N") != 0 && 463 strcmp (PREVLEVEL, "N") != 0 &&
444 strcmp (PREVLEVEL, "S") != 0 && 464 strcmp (PREVLEVEL, "S") != 0 &&
445 strcmp (PREVLEVEL, "1") != 0) 465 strcmp (PREVLEVEL, "1") != 0)
446 return (false); 466 return (false);
447 467
448 if (! rc_is_env ("RC_INTERACTIVE", "yes")) 468 if (! rc_env_bool ("RC_INTERACTIVE"))
449 return (false); 469 return (false);
450 470
451 c = read_key (false); 471 c = read_key (false);
452 return ((c == 'I' || c == 'i') ? true : false); 472 return ((c == 'I' || c == 'i') ? true : false);
453} 473}
469 execl ("/sbin/halt", "/sbin/halt", "-f", (char *) NULL); 489 execl ("/sbin/halt", "/sbin/halt", "-f", (char *) NULL);
470 eerrorx ("%s: unable to exec `/sbin/halt': %s", applet, strerror (errno)); 490 eerrorx ("%s: unable to exec `/sbin/halt': %s", applet, strerror (errno));
471 } 491 }
472#endif 492#endif
473 493
474 newenv = rc_filter_env (); 494 newenv = env_filter ();
475 495
476 if (cont) { 496 if (cont) {
477 int status = 0; 497 int status = 0;
478#ifdef __linux__ 498#ifdef __linux__
479 char *tty = ttyname (fileno (stdout)); 499 char *tty = ttyname (fileno (stdout));
499#endif 519#endif
500 _exit (EXIT_FAILURE); 520 _exit (EXIT_FAILURE);
501 } 521 }
502 waitpid (pid, &status, 0); 522 waitpid (pid, &status, 0);
503 } else { 523 } else {
504#ifdef __linux 524#ifdef __linux__
505 execle ("/sbin/sulogin", "/sbin/sulogin", (char *) NULL, newenv); 525 execle ("/sbin/sulogin", "/sbin/sulogin", (char *) NULL, newenv);
506 eerrorx ("%s: unable to exec `/sbin/sulogin': %s", applet, strerror (errno)); 526 eerrorx ("%s: unable to exec `/sbin/sulogin': %s", applet, strerror (errno));
507#else 527#else
508 exit (EXIT_SUCCESS); 528 exit (EXIT_SUCCESS);
509#endif 529#endif
522 applet, strerror (errno)); 542 applet, strerror (errno));
523 exit (EXIT_SUCCESS); 543 exit (EXIT_SUCCESS);
524#endif 544#endif
525} 545}
526 546
527static void set_ksoftlevel (const char *runlevel) 547static void set_ksoftlevel (const char *level)
528{ 548{
529 FILE *fp; 549 FILE *fp;
530 550
531 if (! runlevel || 551 if (! level ||
532 strcmp (runlevel, getenv ("RC_BOOTLEVEL")) == 0 || 552 strcmp (level, getenv ("RC_BOOTLEVEL")) == 0 ||
533 strcmp (runlevel, RC_LEVEL_SINGLE) == 0 || 553 strcmp (level, RC_LEVEL_SINGLE) == 0 ||
534 strcmp (runlevel, RC_LEVEL_SYSINIT) == 0) 554 strcmp (level, RC_LEVEL_SYSINIT) == 0)
535 { 555 {
536 if (rc_exists (RC_SVCDIR "ksoftlevel") && 556 if (exists (RC_KSOFTLEVEL) &&
537 unlink (RC_SVCDIR "ksoftlevel") != 0) 557 unlink (RC_KSOFTLEVEL) != 0)
538 eerror ("unlink `%s': %s", RC_SVCDIR "ksoftlevel", strerror (errno)); 558 eerror ("unlink `%s': %s", RC_KSOFTLEVEL, strerror (errno));
539 return; 559 return;
540 } 560 }
541 561
542 if (! (fp = fopen (RC_SVCDIR "ksoftlevel", "w"))) { 562 if (! (fp = fopen (RC_KSOFTLEVEL, "w"))) {
543 eerror ("fopen `%s': %s", RC_SVCDIR "ksoftlevel", strerror (errno)); 563 eerror ("fopen `%s': %s", RC_KSOFTLEVEL, strerror (errno));
544 return; 564 return;
545 } 565 }
546 566
547 fprintf (fp, "%s", runlevel); 567 fprintf (fp, "%s", level);
548 fclose (fp); 568 fclose (fp);
549} 569}
550 570
551static int get_ksoftlevel (char *buffer, int buffer_len) 571static int get_ksoftlevel (char *buffer, int buffer_len)
552{ 572{
553 FILE *fp; 573 FILE *fp;
554 int i = 0; 574 int i = 0;
555 575
556 if (! rc_exists (RC_SVCDIR "ksoftlevel")) 576 if (! exists (RC_KSOFTLEVEL))
557 return 0; 577 return (0);
558 578
559 if (! (fp = fopen (RC_SVCDIR "ksoftlevel", "r"))) { 579 if (! (fp = fopen (RC_KSOFTLEVEL, "r"))) {
560 eerror ("fopen `%s': %s", RC_SVCDIR "ksoftlevel", 580 eerror ("fopen `%s': %s", RC_KSOFTLEVEL, strerror (errno));
561 strerror (errno));
562 return -1; 581 return (-1);
563 } 582 }
564 583
565 if (fgets (buffer, buffer_len, fp)) { 584 if (fgets (buffer, buffer_len, fp)) {
566 i = strlen (buffer) - 1; 585 i = strlen (buffer) - 1;
567 if (buffer[i] == '\n') 586 if (buffer[i] == '\n')
568 buffer[i] = 0; 587 buffer[i] = 0;
569 } 588 }
570 589
571 fclose (fp); 590 fclose (fp);
572 return i; 591 return (i);
573} 592}
574 593
575static void wait_for_services () 594static void wait_for_services ()
576{ 595{
577 int status = 0; 596 int status = 0;
582{ 601{
583 pidlist_t *sp = service_pids; 602 pidlist_t *sp = service_pids;
584 if (sp) { 603 if (sp) {
585 while (sp->next) 604 while (sp->next)
586 sp = sp->next; 605 sp = sp->next;
587 sp->next = rc_xmalloc (sizeof (pidlist_t)); 606 sp->next = xmalloc (sizeof (pidlist_t));
588 sp = sp->next; 607 sp = sp->next;
589 } else 608 } else
590 sp = service_pids = rc_xmalloc (sizeof (pidlist_t)); 609 sp = service_pids = xmalloc (sizeof (pidlist_t));
591 memset (sp, 0, sizeof (pidlist_t)); 610 memset (sp, 0, sizeof (pidlist_t));
592 sp->pid = pid; 611 sp->pid = pid;
593} 612}
594 613
595static void remove_pid (pid_t pid) 614static void remove_pid (pid_t pid)
606 free (pl); 625 free (pl);
607 break; 626 break;
608 } 627 }
609 last = pl; 628 last = pl;
610 } 629 }
630}
631
632static int wait_pid (pid_t pid)
633{
634 int status = 0;
635 pid_t savedpid = pid;
636 int retval = -1;
637
638 errno = 0;
639 while ((pid = waitpid (savedpid, &status, 0)) > 0) {
640 if (pid == savedpid)
641 retval = WIFEXITED (status) ? WEXITSTATUS (status) : EXIT_FAILURE;
642 }
643
644 return (retval);
611} 645}
612 646
613static void handle_signal (int sig) 647static void handle_signal (int sig)
614{ 648{
615 int serrno = errno; 649 int serrno = errno;
651 signal (SIGCHLD, SIG_IGN); 685 signal (SIGCHLD, SIG_IGN);
652 for (pl = service_pids; pl; pl = pl->next) 686 for (pl = service_pids; pl; pl = pl->next)
653 kill (pl->pid, SIGTERM); 687 kill (pl->pid, SIGTERM);
654 688
655 /* Notify plugins we are aborting */ 689 /* Notify plugins we are aborting */
656 rc_plugin_run (rc_hook_abort, NULL); 690 rc_plugin_run (RC_HOOK_ABORT, NULL);
657 691
658 /* Only drop into single user mode if we're booting */ 692 /* Only drop into single user mode if we're booting */
659 if ((PREVLEVEL && 693 if ((PREVLEVEL &&
660 (strcmp (PREVLEVEL, "S") == 0 || 694 (strcmp (PREVLEVEL, "S") == 0 ||
661 strcmp (PREVLEVEL, "1") == 0)) || 695 strcmp (PREVLEVEL, "1") == 0)) ||
697 if (! WIFEXITED (status) || ! WEXITSTATUS (status) == 0) 731 if (! WIFEXITED (status) || ! WEXITSTATUS (status) == 0)
698 eerrorx ("%s: failed to exec `%s'", applet, script); 732 eerrorx ("%s: failed to exec `%s'", applet, script);
699} 733}
700 734
701#include "_usage.h" 735#include "_usage.h"
702#define getoptstring getoptstring_COMMON 736#define getoptstring getoptstring_COMMON
703static struct option longopts[] = { 737static struct option longopts[] = {
704 longopts_COMMON 738 longopts_COMMON
705 { NULL, 0, NULL, 0} 739};
740static const char * const longopts_help[] = {
741 longopts_help_COMMON
706}; 742};
707#include "_usage.c" 743#include "_usage.c"
708 744
709int main (int argc, char **argv) 745int main (int argc, char **argv)
710{ 746{
711 char *runlevel = NULL;
712 const char *bootlevel = NULL; 747 const char *bootlevel = NULL;
713 char *newlevel = NULL; 748 char *newlevel = NULL;
714 char *service = NULL; 749 char *service = NULL;
715 char **deporder = NULL; 750 char **deporder = NULL;
751 char **tmplist;
716 int i = 0; 752 int i = 0;
717 int j = 0; 753 int j = 0;
718 bool going_down = false; 754 bool going_down = false;
719 bool interactive = false; 755 bool interactive = false;
720 int depoptions = RC_DEP_STRICT | RC_DEP_TRACE; 756 int depoptions = RC_DEP_STRICT | RC_DEP_TRACE;
721 char ksoftbuffer [PATH_MAX]; 757 char ksoftbuffer [PATH_MAX];
722 char pidstr[6]; 758 char pidstr[6];
723 int opt; 759 int opt;
760 DIR *dp;
761 struct dirent *d;
724 762
725 atexit (cleanup); 763 atexit (cleanup);
726 if (argv[0]) 764 if (argv[0])
727 applet = rc_xstrdup (basename (argv[0])); 765 applet = xstrdup (basename (argv[0]));
728 766
729 if (! applet) 767 if (! applet)
730 eerrorx ("arguments required"); 768 eerrorx ("arguments required");
731 769
732 /* These used to be programs in their own right, so we shouldn't 770 /* These used to be programs in their own right, so we shouldn't
746 exit (rc_update (argc, argv)); 784 exit (rc_update (argc, argv));
747 else if (strcmp (applet, "runscript") == 0) 785 else if (strcmp (applet, "runscript") == 0)
748 exit (runscript (argc, argv)); 786 exit (runscript (argc, argv));
749 else if (strcmp (applet, "start-stop-daemon") == 0) 787 else if (strcmp (applet, "start-stop-daemon") == 0)
750 exit (start_stop_daemon (argc, argv)); 788 exit (start_stop_daemon (argc, argv));
789 else if (strcmp (applet, "checkown") == 0)
790 exit (checkown (argc, argv));
751 791
752 argc--; 792 argc--;
753 argv++; 793 argv++;
754 794
755 /* Handle multicall stuff */ 795 /* Handle multicall stuff */
802 signal (SIGTERM, handle_signal); 842 signal (SIGTERM, handle_signal);
803 signal (SIGUSR1, handle_signal); 843 signal (SIGUSR1, handle_signal);
804 844
805 /* Ensure our environment is pure 845 /* Ensure our environment is pure
806 Also, add our configuration to it */ 846 Also, add our configuration to it */
807 env = rc_filter_env (); 847 env = env_filter ();
808 env = rc_config_env (env); 848 tmplist = env_config ();
849 rc_strlist_join (&env, tmplist);
850 rc_strlist_free (tmplist);
809 851
810 if (env) { 852 if (env) {
811 char *p; 853 char *p;
812 854
813#ifdef __linux__ 855#ifdef __linux__
819 /* No clearenv present here then. 861 /* No clearenv present here then.
820 We could manipulate environ directly ourselves, but it seems that 862 We could manipulate environ directly ourselves, but it seems that
821 some kernels bitch about this according to the environ man pages 863 some kernels bitch about this according to the environ man pages
822 so we walk though environ and call unsetenv for each value. */ 864 so we walk though environ and call unsetenv for each value. */
823 while (environ[0]) { 865 while (environ[0]) {
824 tmp = rc_xstrdup (environ[0]); 866 tmp = xstrdup (environ[0]);
825 p = tmp; 867 p = tmp;
826 var = strsep (&p, "="); 868 var = strsep (&p, "=");
827 unsetenv (var); 869 unsetenv (var);
828 free (tmp); 870 free (tmp);
829 } 871 }
859 901
860 /* Export our PID */ 902 /* Export our PID */
861 snprintf (pidstr, sizeof (pidstr), "%d", getpid ()); 903 snprintf (pidstr, sizeof (pidstr), "%d", getpid ());
862 setenv ("RC_PID", pidstr, 1); 904 setenv ("RC_PID", pidstr, 1);
863 905
864 interactive = rc_exists (INTERACTIVE); 906 interactive = exists (INTERACTIVE);
865 rc_plugin_load (); 907 rc_plugin_load ();
866 908
867 /* Load current softlevel */ 909 /* Load current softlevel */
868 bootlevel = getenv ("RC_BOOTLEVEL"); 910 bootlevel = getenv ("RC_BOOTLEVEL");
869 runlevel = rc_get_runlevel (); 911 runlevel = rc_runlevel_get ();
870 912
871 /* Check we're in the runlevel requested, ie from 913 /* Check we're in the runlevel requested, ie from
872 rc single 914 rc single
873 rc shutdown 915 rc shutdown
874 rc reboot 916 rc reboot
886#endif 928#endif
887 929
888 /* exec init-early.sh if it exists 930 /* exec init-early.sh if it exists
889 * This should just setup the console to use the correct 931 * This should just setup the console to use the correct
890 * font. Maybe it should setup the keyboard too? */ 932 * font. Maybe it should setup the keyboard too? */
891 if (rc_exists (INITEARLYSH)) 933 if (exists (INITEARLYSH))
892 run_script (INITEARLYSH); 934 run_script (INITEARLYSH);
893 935
894 uname (&uts); 936 uname (&uts);
895 937
896 printf ("\n"); 938 printf ("\n");
897 printf (" %sGentoo/%s; %shttp://www.gentoo.org/%s" 939 printf (" %sGentoo/%s; %shttp://www.gentoo.org/%s"
898 "\n Copyright 1999-2007 Gentoo Foundation; " 940 "\n Copyright 1999-2007 Gentoo Foundation; "
899 "Distributed under the GPLv2\n\n", 941 "Distributed under the GPLv2\n\n",
900 ecolor (ecolor_good), uts.sysname, ecolor (ecolor_bracket), 942 ecolor (ECOLOR_GOOD), uts.sysname, ecolor (ECOLOR_BRACKET),
901 ecolor (ecolor_normal)); 943 ecolor (ECOLOR_NORMAL));
902 944
903 if (rc_is_env ("RC_INTERACTIVE", "yes")) 945 if (rc_env_bool ("RC_INTERACTIVE"))
904 printf ("Press %sI%s to enter interactive boot mode\n\n", 946 printf ("Press %sI%s to enter interactive boot mode\n\n",
905 ecolor (ecolor_good), ecolor (ecolor_normal)); 947 ecolor (ECOLOR_GOOD), ecolor (ECOLOR_NORMAL));
906 948
907 setenv ("RC_SOFTLEVEL", newlevel, 1); 949 setenv ("RC_SOFTLEVEL", newlevel, 1);
908 rc_plugin_run (rc_hook_runlevel_start_in, newlevel); 950 rc_plugin_run (RC_HOOK_RUNLEVEL_START_IN, newlevel);
909 run_script (INITSH); 951 run_script (INITSH);
910 952
911#ifdef __linux__ 953#ifdef __linux__
912 /* If we requested a softlevel, save it now */ 954 /* If we requested a softlevel, save it now */
913 set_ksoftlevel (NULL); 955 set_ksoftlevel (NULL);
915 set_ksoftlevel (cmd); 957 set_ksoftlevel (cmd);
916 free (cmd); 958 free (cmd);
917 } 959 }
918 960
919#endif 961#endif
920 rc_plugin_run (rc_hook_runlevel_start_out, newlevel); 962 rc_plugin_run (RC_HOOK_RUNLEVEL_START_OUT, newlevel);
921 963
922 if (want_interactive ()) 964 if (want_interactive ())
923 mark_interactive (); 965 mark_interactive ();
924 966
925 exit (EXIT_SUCCESS); 967 exit (EXIT_SUCCESS);
934 } 976 }
935 } else if (strcmp (newlevel, RC_LEVEL_REBOOT) == 0) { 977 } else if (strcmp (newlevel, RC_LEVEL_REBOOT) == 0) {
936 if (! RUNLEVEL || 978 if (! RUNLEVEL ||
937 strcmp (RUNLEVEL, "6") != 0) 979 strcmp (RUNLEVEL, "6") != 0)
938 { 980 {
939 execl ("/sbin/shutdown", "/sbin/shutdown", "-r", "now", (char *) NULL); 981 execl (SHUTDOWN, SHUTDOWN, "-r", "now", (char *) NULL);
940 eerrorx ("%s: unable to exec `/sbin/shutdown': %s", 982 eerrorx ("%s: unable to exec `" SHUTDOWN "': %s",
941 applet, strerror (errno)); 983 applet, strerror (errno));
942 } 984 }
943 } else if (strcmp (newlevel, RC_LEVEL_SHUTDOWN) == 0) { 985 } else if (strcmp (newlevel, RC_LEVEL_SHUTDOWN) == 0) {
944 if (! RUNLEVEL || 986 if (! RUNLEVEL ||
945 strcmp (RUNLEVEL, "0") != 0) 987 strcmp (RUNLEVEL, "0") != 0)
946 { 988 {
947 execl ("/sbin/shutdown", "/sbin/shutdown", 989 execl (SHUTDOWN, SHUTDOWN,
948#ifdef __linux 990#ifdef __linux__
949 "-h", 991 "-h",
950#else 992#else
951 "-p", 993 "-p",
952#endif 994#endif
953 "now", (char *) NULL); 995 "now", (char *) NULL);
954 eerrorx ("%s: unable to exec `/sbin/shutdown': %s", 996 eerrorx ("%s: unable to exec `" SHUTDOWN "': %s",
955 applet, strerror (errno)); 997 applet, strerror (errno));
956 } 998 }
957 } 999 }
958 } 1000 }
959 1001
965 if (PREVLEVEL && 1007 if (PREVLEVEL &&
966 (strcmp (PREVLEVEL, "1") == 0 || 1008 (strcmp (PREVLEVEL, "1") == 0 ||
967 strcmp (PREVLEVEL, "S") == 0 || 1009 strcmp (PREVLEVEL, "S") == 0 ||
968 strcmp (PREVLEVEL, "N") == 0)) 1010 strcmp (PREVLEVEL, "N") == 0))
969 { 1011 {
1012 /* Try not to join boot and ksoftlevels together */
1013 if (! newlevel ||
1014 strcmp (newlevel, getenv ("RC_BOOTLEVEL")) != 0)
970 if (get_ksoftlevel (ksoftbuffer, sizeof (ksoftbuffer))) 1015 if (get_ksoftlevel (ksoftbuffer, sizeof (ksoftbuffer)))
971 newlevel = ksoftbuffer; 1016 newlevel = ksoftbuffer;
972 } else if (! RUNLEVEL || 1017 } else if (! RUNLEVEL ||
973 (strcmp (RUNLEVEL, "1") != 0 && 1018 (strcmp (RUNLEVEL, "1") != 0 &&
974 strcmp (RUNLEVEL, "S") != 0 && 1019 strcmp (RUNLEVEL, "S") != 0 &&
975 strcmp (RUNLEVEL, "N") != 0)) 1020 strcmp (RUNLEVEL, "N") != 0))
976 { 1021 {
981 (strcmp (newlevel, RC_LEVEL_REBOOT) == 0 || 1026 (strcmp (newlevel, RC_LEVEL_REBOOT) == 0 ||
982 strcmp (newlevel, RC_LEVEL_SHUTDOWN) == 0 || 1027 strcmp (newlevel, RC_LEVEL_SHUTDOWN) == 0 ||
983 strcmp (newlevel, RC_LEVEL_SINGLE) == 0)) 1028 strcmp (newlevel, RC_LEVEL_SINGLE) == 0))
984 { 1029 {
985 going_down = true; 1030 going_down = true;
986 rc_set_runlevel (newlevel); 1031 rc_runlevel_set (newlevel);
987 setenv ("RC_SOFTLEVEL", newlevel, 1); 1032 setenv ("RC_SOFTLEVEL", newlevel, 1);
988 rc_plugin_run (rc_hook_runlevel_stop_in, newlevel); 1033 rc_plugin_run (RC_HOOK_RUNLEVEL_STOP_IN, newlevel);
989 } else { 1034 } else {
990 rc_plugin_run (rc_hook_runlevel_stop_in, runlevel); 1035 rc_plugin_run (RC_HOOK_RUNLEVEL_STOP_IN, runlevel);
991 } 1036 }
992 1037
993 /* Check if runlevel is valid if we're changing */ 1038 /* Check if runlevel is valid if we're changing */
994 if (newlevel && strcmp (runlevel, newlevel) != 0 && ! going_down) { 1039 if (newlevel && strcmp (runlevel, newlevel) != 0 && ! going_down) {
995 tmp = rc_strcatpaths (RC_RUNLEVELDIR, newlevel, (char *) NULL); 1040 if (! rc_runlevel_exists (newlevel))
996 if (! rc_is_dir (tmp))
997 eerrorx ("%s: is not a valid runlevel", newlevel); 1041 eerrorx ("%s: is not a valid runlevel", newlevel);
998 CHAR_FREE (tmp);
999 } 1042 }
1000 1043
1001 /* Load our deptree now */ 1044 /* Load our deptree now */
1002 if ((deptree = rc_load_deptree ()) == NULL) 1045 if ((deptree = _rc_deptree_load ()) == NULL)
1003 eerrorx ("failed to load deptree"); 1046 eerrorx ("failed to load deptree");
1004 1047
1005 /* Clean the failed services state dir now */ 1048 /* Clean the failed services state dir now */
1006 if (rc_is_dir (RC_SVCDIR "failed")) 1049 if ((dp = opendir (RC_SVCDIR "/failed"))) {
1007 rc_rm_dir (RC_SVCDIR "failed", false); 1050 while ((d = readdir (dp))) {
1051 if (d->d_name[0] == '.' &&
1052 (d->d_name[1] == '\0' ||
1053 (d->d_name[1] == '.' && d->d_name[2] == '\0')))
1054 continue;
1008 1055
1009 mkdir (RC_SVCDIR "/softscripts.new", 0755); 1056 asprintf (&tmp, RC_SVCDIR "/failed/%s", d->d_name);
1057 if (tmp) {
1058 if (unlink (tmp))
1059 eerror ("%s: unlink `%s': %s", applet, tmp,
1060 strerror (errno));
1061 free (tmp);
1062 }
1063 }
1064 closedir (dp);
1065 }
1066
1067 mkdir (RC_STOPPING, 0755);
1010 1068
1011#ifdef __linux__ 1069#ifdef __linux__
1012 /* udev likes to start services before we're ready when it does 1070 /* udev likes to start services before we're ready when it does
1013 its coldplugging thing. runscript knows when we're not ready so it 1071 its coldplugging thing. runscript knows when we're not ready so it
1014 stores a list of coldplugged services in DEVBOOT for us to pick up 1072 stores a list of coldplugged services in DEVBOOT for us to pick up
1015 here when we are ready for them */ 1073 here when we are ready for them */
1016 if (rc_is_dir (DEVBOOT)) { 1074 if ((dp = opendir (DEVBOOT))) {
1017 start_services = rc_ls_dir (NULL, DEVBOOT, RC_LS_INITD); 1075 while ((d = readdir (dp))) {
1076 if (d->d_name[0] == '.' &&
1077 (d->d_name[1] == '\0' ||
1078 (d->d_name[1] == '.' && d->d_name[2] == '\0')))
1079 continue;
1080
1081 if (rc_service_exists (d->d_name) &&
1082 rc_service_plugable (d->d_name))
1083 rc_service_mark (d->d_name, RC_SERVICE_COLDPLUGGED);
1084
1085 asprintf (&tmp, DEVBOOT "/%s", d->d_name);
1086 if (tmp) {
1087 if (unlink (tmp))
1088 eerror ("%s: unlink `%s': %s", applet, tmp,
1089 strerror (errno));
1090 free (tmp);
1091 }
1092 }
1093 closedir (dp);
1018 rc_rm_dir (DEVBOOT, true); 1094 rmdir (DEVBOOT);
1019
1020 STRLIST_FOREACH (start_services, service, i)
1021 if (rc_allow_plug (service))
1022 rc_mark_service (service, rc_service_coldplugged);
1023 /* We need to dump this list now.
1024 This may seem redunant, but only Linux needs this and saves on
1025 code bloat. */
1026 rc_strlist_free (start_services);
1027 start_services = NULL;
1028 } 1095 }
1029#else 1096#else
1030 /* BSD's on the other hand populate /dev automagically and use devd. 1097 /* BSD's on the other hand populate /dev automagically and use devd.
1031 The only downside of this approach and ours is that we have to hard code 1098 The only downside of this approach and ours is that we have to hard code
1032 the device node to the init script to simulate the coldplug into 1099 the device node to the init script to simulate the coldplug into
1033 runlevel for our dependency tree to work. */ 1100 runlevel for our dependency tree to work. */
1034 if (newlevel && strcmp (newlevel, bootlevel) == 0 && 1101 if (newlevel && strcmp (newlevel, bootlevel) == 0 &&
1035 (strcmp (runlevel, RC_LEVEL_SINGLE) == 0 || 1102 (strcmp (runlevel, RC_LEVEL_SINGLE) == 0 ||
1036 strcmp (runlevel, RC_LEVEL_SYSINIT) == 0) && 1103 strcmp (runlevel, RC_LEVEL_SYSINIT) == 0) &&
1037 rc_is_env ("RC_COLDPLUG", "yes")) 1104 rc_env_bool ("RC_COLDPLUG"))
1038 { 1105 {
1039#if defined(__DragonFly__) || defined(__FreeBSD__) 1106#if defined(__DragonFly__) || defined(__FreeBSD__)
1040 /* The net interfaces are easy - they're all in net /dev/net :) */ 1107 /* The net interfaces are easy - they're all in net /dev/net :) */
1041 start_services = rc_ls_dir (NULL, "/dev/net", 0); 1108 if ((dp = opendir ("/dev/net"))) {
1042 STRLIST_FOREACH (start_services, service, i) { 1109 while ((d = readdir (dp))) {
1043 j = (strlen ("net.") + strlen (service) + 1); 1110 i = (strlen ("net.") + strlen (d->d_name) + 1);
1044 tmp = rc_xmalloc (sizeof (char *) * j); 1111 tmp = xmalloc (sizeof (char) * i);
1045 snprintf (tmp, j, "net.%s", service); 1112 snprintf (tmp, i, "net.%s", d->d_name);
1046 if (rc_service_exists (tmp) && rc_allow_plug (tmp)) 1113 if (rc_service_exists (tmp) &&
1047 rc_mark_service (tmp, rc_service_coldplugged); 1114 rc_service_plugable (tmp))
1115 rc_service_mark (tmp, RC_SERVICE_COLDPLUGGED);
1048 CHAR_FREE (tmp); 1116 CHAR_FREE (tmp);
1049 } 1117 }
1050 rc_strlist_free (start_services); 1118 closedir (dp);
1119 }
1051#endif 1120#endif
1052 1121
1053 /* The mice are a little more tricky. 1122 /* The mice are a little more tricky.
1054 If we coldplug anything else, we'll probably do it here. */ 1123 If we coldplug anything else, we'll probably do it here. */
1055 start_services = rc_ls_dir (NULL, "/dev", 0); 1124 if ((dp == opendir ("/dev"))) {
1056 STRLIST_FOREACH (start_services, service, i) { 1125 while ((d = readdir (dp))) {
1057 if (strncmp (service, "psm", 3) == 0 || 1126 if (strncmp (d->d_name, "psm", 3) == 0 ||
1058 strncmp (service, "ums", 3) == 0) 1127 strncmp (d->d_name, "ums", 3) == 0)
1059 { 1128 {
1060 char *p = service + 3; 1129 char *p = d->d_name + 3;
1061 if (p && isdigit (*p)) { 1130 if (p && isdigit (*p)) {
1062 j = (strlen ("moused.") + strlen (service) + 1); 1131 i = (strlen ("moused.") + strlen (d->d_name) + 1);
1063 tmp = rc_xmalloc (sizeof (char *) * j); 1132 tmp = xmalloc (sizeof (char) * i);
1064 snprintf (tmp, j, "moused.%s", service); 1133 snprintf (tmp, i, "moused.%s", d->d_name);
1065 if (rc_service_exists (tmp) && rc_allow_plug (tmp)) 1134 if (rc_service_exists (tmp) && rc_service_plugable (tmp))
1066 rc_mark_service (tmp, rc_service_coldplugged); 1135 rc_service_mark (tmp, RC_SERVICE_COLDPLUGGED);
1067 CHAR_FREE (tmp); 1136 CHAR_FREE (tmp);
1137 }
1068 } 1138 }
1069 } 1139 }
1140 closedir (dp);
1070 } 1141 }
1071 rc_strlist_free (start_services);
1072 start_services = NULL;
1073 } 1142 }
1074#endif 1143#endif
1075 1144
1076 /* Build a list of all services to stop and then work out the 1145 /* Build a list of all services to stop and then work out the
1077 correct order for stopping them */ 1146 correct order for stopping them */
1078 stop_services = rc_ls_dir (stop_services, RC_SVCDIR_STARTING, RC_LS_INITD); 1147 stop_services = rc_services_in_state (RC_SERVICE_STARTING);
1079 stop_services = rc_ls_dir (stop_services, RC_SVCDIR_INACTIVE, RC_LS_INITD);
1080 stop_services = rc_ls_dir (stop_services, RC_SVCDIR_STARTED, RC_LS_INITD);
1081 1148
1082 types = rc_strlist_add (NULL, "ineed"); 1149 tmplist = rc_services_in_state (RC_SERVICE_INACTIVE);
1083 types = rc_strlist_add (types, "iuse"); 1150 rc_strlist_join (&stop_services, tmplist);
1084 types = rc_strlist_add (types, "iafter"); 1151 rc_strlist_free (tmplist);
1152
1153 tmplist = rc_services_in_state (RC_SERVICE_STARTED);
1154 rc_strlist_join (&stop_services, tmplist);
1155 rc_strlist_free (tmplist);
1156
1085 deporder = rc_get_depends (deptree, types, stop_services, 1157 deporder = rc_deptree_depends (deptree, types_nua,
1158 (const char **) stop_services,
1086 runlevel, depoptions | RC_DEP_STOP); 1159 runlevel, depoptions | RC_DEP_STOP);
1160
1087 rc_strlist_free (stop_services); 1161 rc_strlist_free (stop_services);
1088 rc_strlist_free (types);
1089 stop_services = deporder; 1162 stop_services = deporder;
1090 deporder = NULL; 1163 deporder = NULL;
1091 types = NULL;
1092 rc_strlist_reverse (stop_services); 1164 rc_strlist_reverse (stop_services);
1093 1165
1094 /* Load our list of coldplugged services */ 1166 /* Load our list of coldplugged services */
1095 coldplugged_services = rc_ls_dir (coldplugged_services, 1167 coldplugged_services = rc_services_in_state (RC_SERVICE_COLDPLUGGED);
1096 RC_SVCDIR_COLDPLUGGED, RC_LS_INITD);
1097 1168
1098 /* Load our start services now. 1169 /* Load our start services now.
1099 We have different rules dependent on runlevel. */ 1170 We have different rules dependent on runlevel. */
1100 if (newlevel && strcmp (newlevel, bootlevel) == 0) { 1171 if (newlevel && strcmp (newlevel, bootlevel) == 0) {
1101 if (coldplugged_services) { 1172 if (coldplugged_services) {
1102 einfon ("Device initiated services:"); 1173 einfon ("Device initiated services:");
1103 STRLIST_FOREACH (coldplugged_services, service, i) { 1174 STRLIST_FOREACH (coldplugged_services, service, i) {
1104 printf (" %s", service); 1175 printf (" %s", service);
1105 start_services = rc_strlist_add (start_services, service); 1176 rc_strlist_add (&start_services, service);
1106 } 1177 }
1107 printf ("\n"); 1178 printf ("\n");
1108 } 1179 }
1109 tmp = rc_strcatpaths (RC_RUNLEVELDIR, newlevel ? newlevel : runlevel, 1180 tmplist = rc_services_in_runlevel (newlevel ? newlevel : runlevel);
1110 (char *) NULL); 1181 rc_strlist_join (&start_services, tmplist);
1111 start_services = rc_ls_dir (start_services, tmp, RC_LS_INITD); 1182 rc_strlist_free (tmplist);
1112 CHAR_FREE (tmp);
1113 } else { 1183 } else {
1114 /* Store our list of coldplugged services */ 1184 /* Store our list of coldplugged services */
1115 coldplugged_services = rc_ls_dir (coldplugged_services, RC_SVCDIR_COLDPLUGGED, 1185 tmplist = rc_services_in_state (RC_SERVICE_COLDPLUGGED);
1116 RC_LS_INITD); 1186 rc_strlist_join (&coldplugged_services, tmplist);
1187 rc_strlist_free (tmplist);
1117 if (strcmp (newlevel ? newlevel : runlevel, RC_LEVEL_SINGLE) != 0 && 1188 if (strcmp (newlevel ? newlevel : runlevel, RC_LEVEL_SINGLE) != 0 &&
1118 strcmp (newlevel ? newlevel : runlevel, RC_LEVEL_SHUTDOWN) != 0 && 1189 strcmp (newlevel ? newlevel : runlevel, RC_LEVEL_SHUTDOWN) != 0 &&
1119 strcmp (newlevel ? newlevel : runlevel, RC_LEVEL_REBOOT) != 0) 1190 strcmp (newlevel ? newlevel : runlevel, RC_LEVEL_REBOOT) != 0)
1120 { 1191 {
1121 /* We need to include the boot runlevel services if we're not in it */ 1192 /* We need to include the boot runlevel services if we're not in it */
1122 char **services = rc_services_in_runlevel (bootlevel); 1193 tmplist = rc_services_in_runlevel (bootlevel);
1123 1194 rc_strlist_join (&start_services, tmplist);
1124 start_services = rc_strlist_join (start_services, services); 1195 rc_strlist_free (tmplist);
1125 services = rc_services_in_runlevel (newlevel ? newlevel : runlevel); 1196 tmplist = rc_services_in_runlevel (newlevel ? newlevel : runlevel);
1126 start_services = rc_strlist_join (start_services, services); 1197 rc_strlist_join (&start_services, tmplist);
1127 services = NULL; 1198 rc_strlist_free (tmplist);
1128 1199
1129 STRLIST_FOREACH (coldplugged_services, service, i) 1200 STRLIST_FOREACH (coldplugged_services, service, i)
1130 start_services = rc_strlist_add (start_services, service); 1201 rc_strlist_add (&start_services, service);
1131 1202
1132 } 1203 }
1133 } 1204 }
1134 1205
1135 /* Save out softlevel now */ 1206 /* Save out softlevel now */
1136 if (going_down) 1207 if (going_down)
1137 rc_set_runlevel (newlevel); 1208 rc_runlevel_set (newlevel);
1138 1209
1139 types = rc_strlist_add (NULL, "needsme");
1140 types = rc_strlist_add (types, "usesme");
1141 /* Now stop the services that shouldn't be running */ 1210 /* Now stop the services that shouldn't be running */
1142 STRLIST_FOREACH (stop_services, service, i) { 1211 STRLIST_FOREACH (stop_services, service, i) {
1143 bool found = false; 1212 bool found = false;
1144 char *conf = NULL; 1213 char *conf = NULL;
1145 char **stopdeps = NULL; 1214 char **stopdeps = NULL;
1146 char *svc1 = NULL; 1215 char *svc1 = NULL;
1147 char *svc2 = NULL; 1216 char *svc2 = NULL;
1148 int k; 1217 int k;
1149 1218
1150 if (rc_service_state (service, rc_service_stopped)) 1219 if (rc_service_state (service) & RC_SERVICE_STOPPED)
1151 continue; 1220 continue;
1152 1221
1153 /* We always stop the service when in these runlevels */ 1222 /* We always stop the service when in these runlevels */
1154 if (going_down) { 1223 if (going_down) {
1155 pid_t pid = rc_stop_service (service); 1224 pid_t pid = rc_service_stop (service);
1156 if (pid > 0 && ! rc_is_env ("RC_PARALLEL", "yes")) 1225 if (pid > 0 && ! rc_env_bool ("RC_PARALLEL"))
1157 rc_waitpid (pid); 1226 wait_pid (pid);
1158 continue; 1227 continue;
1159 } 1228 }
1160 1229
1161 /* If we're in the start list then don't bother stopping us */ 1230 /* If we're in the start list then don't bother stopping us */
1162 STRLIST_FOREACH (start_services, svc1, j) 1231 STRLIST_FOREACH (start_services, svc1, j)
1170 int len; 1239 int len;
1171 if (! newlevel) 1240 if (! newlevel)
1172 continue; 1241 continue;
1173 1242
1174 len = strlen (service) + strlen (runlevel) + 2; 1243 len = strlen (service) + strlen (runlevel) + 2;
1175 tmp = rc_xmalloc (sizeof (char *) * len); 1244 tmp = xmalloc (sizeof (char) * len);
1176 snprintf (tmp, len, "%s.%s", service, runlevel); 1245 snprintf (tmp, len, "%s.%s", service, runlevel);
1177 conf = rc_strcatpaths (RC_CONFDIR, tmp, (char *) NULL); 1246 conf = rc_strcatpaths (RC_CONFDIR, tmp, (char *) NULL);
1178 found = rc_exists (conf); 1247 found = exists (conf);
1179 CHAR_FREE (conf); 1248 CHAR_FREE (conf);
1180 CHAR_FREE (tmp); 1249 CHAR_FREE (tmp);
1181 if (! found) { 1250 if (! found) {
1182 len = strlen (service) + strlen (newlevel) + 2; 1251 len = strlen (service) + strlen (newlevel) + 2;
1183 tmp = rc_xmalloc (sizeof (char *) * len); 1252 tmp = xmalloc (sizeof (char) * len);
1184 snprintf (tmp, len, "%s.%s", service, newlevel); 1253 snprintf (tmp, len, "%s.%s", service, newlevel);
1185 conf = rc_strcatpaths (RC_CONFDIR, tmp, (char *) NULL); 1254 conf = rc_strcatpaths (RC_CONFDIR, tmp, (char *) NULL);
1186 found = rc_exists (conf); 1255 found = exists (conf);
1187 CHAR_FREE (conf); 1256 CHAR_FREE (conf);
1188 CHAR_FREE (tmp); 1257 CHAR_FREE (tmp);
1189 if (!found) 1258 if (!found)
1190 continue; 1259 continue;
1191 } 1260 }
1192 } else { 1261 } else {
1193 /* Allow coldplugged services not to be in the runlevels list */ 1262 /* Allow coldplugged services not to be in the runlevels list */
1194 if (rc_service_state (service, rc_service_coldplugged)) 1263 if (rc_service_state (service) & RC_SERVICE_COLDPLUGGED)
1195 continue; 1264 continue;
1196 } 1265 }
1197 1266
1198 /* We got this far! Or last check is to see if any any service that 1267 /* We got this far! Or last check is to see if any any service that
1199 going to be started depends on us */ 1268 going to be started depends on us */
1200 stopdeps = rc_strlist_add (stopdeps, service); 1269 rc_strlist_add (&stopdeps, service);
1201 deporder = rc_get_depends (deptree, types, stopdeps, 1270 deporder = rc_deptree_depends (deptree, types_n,
1271 (const char **) stopdeps,
1202 runlevel, RC_DEP_STRICT); 1272 runlevel, RC_DEP_STRICT);
1203 rc_strlist_free (stopdeps); 1273 rc_strlist_free (stopdeps);
1204 stopdeps = NULL; 1274 stopdeps = NULL;
1205 found = false; 1275 found = false;
1206 STRLIST_FOREACH (deporder, svc1, j) { 1276 STRLIST_FOREACH (deporder, svc1, j) {
1207 STRLIST_FOREACH (start_services, svc2, k) 1277 STRLIST_FOREACH (start_services, svc2, k)
1215 rc_strlist_free (deporder); 1285 rc_strlist_free (deporder);
1216 deporder = NULL; 1286 deporder = NULL;
1217 1287
1218 /* After all that we can finally stop the blighter! */ 1288 /* After all that we can finally stop the blighter! */
1219 if (! found) { 1289 if (! found) {
1220 pid_t pid = rc_stop_service (service); 1290 pid_t pid = rc_service_stop (service);
1221 if (pid > 0 && ! rc_is_env ("RC_PARALLEL", "yes")) 1291 if (pid > 0 && ! rc_env_bool ("RC_PARALLEL"))
1222 rc_waitpid (pid); 1292 wait_pid (pid);
1223 }
1224 } 1293 }
1225 rc_strlist_free (types); 1294 }
1226 types = NULL;
1227 1295
1228 /* Wait for our services to finish */ 1296 /* Wait for our services to finish */
1229 wait_for_services (); 1297 wait_for_services ();
1230 1298
1231 /* Notify the plugins we have finished */ 1299 /* Notify the plugins we have finished */
1232 rc_plugin_run (rc_hook_runlevel_stop_out, runlevel); 1300 rc_plugin_run (RC_HOOK_RUNLEVEL_STOP_OUT, runlevel);
1233 1301
1234 rmdir (RC_SVCDIR "/softscripts.new"); 1302 rmdir (RC_STOPPING);
1235 1303
1236 /* Store the new runlevel */ 1304 /* Store the new runlevel */
1237 if (newlevel) { 1305 if (newlevel) {
1238 rc_set_runlevel (newlevel); 1306 rc_runlevel_set (newlevel);
1307 free (runlevel);
1239 runlevel = newlevel; 1308 runlevel = xstrdup (newlevel);
1240 setenv ("RC_SOFTLEVEL", runlevel, 1); 1309 setenv ("RC_SOFTLEVEL", runlevel, 1);
1241 } 1310 }
1242 1311
1243 /* Run the halt script if needed */ 1312 /* Run the halt script if needed */
1244 if (strcmp (runlevel, RC_LEVEL_SHUTDOWN) == 0 || 1313 if (strcmp (runlevel, RC_LEVEL_SHUTDOWN) == 0 ||
1249 applet, HALTSH, strerror (errno)); 1318 applet, HALTSH, strerror (errno));
1250 } 1319 }
1251 1320
1252 /* Single user is done now */ 1321 /* Single user is done now */
1253 if (strcmp (runlevel, RC_LEVEL_SINGLE) == 0) { 1322 if (strcmp (runlevel, RC_LEVEL_SINGLE) == 0) {
1254 if (rc_exists (INTERACTIVE)) 1323 if (exists (INTERACTIVE))
1255 unlink (INTERACTIVE); 1324 unlink (INTERACTIVE);
1256 sulogin (false); 1325 sulogin (false);
1257 } 1326 }
1258 1327
1259 mkdir (RC_SVCDIR "softscripts.old", 0755); 1328 mkdir (RC_STARTING, 0755);
1260 rc_plugin_run (rc_hook_runlevel_start_in, runlevel); 1329 rc_plugin_run (RC_HOOK_RUNLEVEL_START_IN, runlevel);
1261 1330
1262 /* Re-add our coldplugged services if they stopped */ 1331 /* Re-add our coldplugged services if they stopped */
1263 STRLIST_FOREACH (coldplugged_services, service, i) 1332 STRLIST_FOREACH (coldplugged_services, service, i)
1264 rc_mark_service (service, rc_service_coldplugged); 1333 rc_service_mark (service, RC_SERVICE_COLDPLUGGED);
1265 1334
1266 /* Order the services to start */ 1335 /* Order the services to start */
1267 types = rc_strlist_add (NULL, "ineed");
1268 types = rc_strlist_add (types, "iuse");
1269 types = rc_strlist_add (types, "iafter");
1270 deporder = rc_get_depends (deptree, types, start_services, 1336 deporder = rc_deptree_depends (deptree, types_nua,
1337 (const char **) start_services,
1271 runlevel, depoptions | RC_DEP_START); 1338 runlevel, depoptions | RC_DEP_START);
1272 rc_strlist_free (types);
1273 types = NULL;
1274 rc_strlist_free (start_services); 1339 rc_strlist_free (start_services);
1275 start_services = deporder; 1340 start_services = deporder;
1276 deporder = NULL; 1341 deporder = NULL;
1277 1342
1278#ifdef __linux__ 1343#ifdef __linux__
1281 if ((service = proc_getent ("noinitd"))) { 1346 if ((service = proc_getent ("noinitd"))) {
1282 char *p = service; 1347 char *p = service;
1283 char *token; 1348 char *token;
1284 1349
1285 while ((token = strsep (&p, ","))) 1350 while ((token = strsep (&p, ",")))
1286 rc_mark_service (token, rc_service_started); 1351 rc_service_mark (token, RC_SERVICE_STARTED);
1287 free (service); 1352 free (service);
1288 } 1353 }
1289 } 1354 }
1290#endif 1355#endif
1291 1356
1292 1357
1293 STRLIST_FOREACH (start_services, service, i) { 1358 STRLIST_FOREACH (start_services, service, i) {
1294 if (rc_service_state (service, rc_service_stopped)) { 1359 if (rc_service_state (service) & RC_SERVICE_STOPPED) {
1295 pid_t pid; 1360 pid_t pid;
1296 1361
1297 if (! interactive) 1362 if (! interactive)
1298 interactive = want_interactive (); 1363 interactive = want_interactive ();
1299 1364
1314 default: goto interactive_option; 1379 default: goto interactive_option;
1315 } 1380 }
1316 } 1381 }
1317 1382
1318 /* Remember the pid if we're running in parallel */ 1383 /* Remember the pid if we're running in parallel */
1319 if ((pid = rc_start_service (service))) 1384 if ((pid = rc_service_start (service)))
1320 add_pid (pid); 1385 add_pid (pid);
1321 1386
1322 if (! rc_is_env ("RC_PARALLEL", "yes")) { 1387 if (! rc_env_bool ("RC_PARALLEL")) {
1323 rc_waitpid (pid); 1388 wait_pid (pid);
1324 remove_pid (pid); 1389 remove_pid (pid);
1325 } 1390 }
1326 } 1391 }
1327 } 1392 }
1328 1393
1329 /* Wait for our services to finish */ 1394 /* Wait for our services to finish */
1330 wait_for_services (); 1395 wait_for_services ();
1331 1396
1332 rc_plugin_run (rc_hook_runlevel_start_out, runlevel); 1397 rc_plugin_run (RC_HOOK_RUNLEVEL_START_OUT, runlevel);
1333 1398
1334#ifdef __linux__ 1399#ifdef __linux__
1335 /* mark any services skipped as stopped */ 1400 /* mark any services skipped as stopped */
1336 if (PREVLEVEL && strcmp (PREVLEVEL, "N") == 0) { 1401 if (PREVLEVEL && strcmp (PREVLEVEL, "N") == 0) {
1337 if ((service = proc_getent ("noinitd"))) { 1402 if ((service = proc_getent ("noinitd"))) {
1338 char *p = service; 1403 char *p = service;
1339 char *token; 1404 char *token;
1340 1405
1341 while ((token = strsep (&p, ","))) 1406 while ((token = strsep (&p, ",")))
1342 rc_mark_service (token, rc_service_stopped); 1407 rc_service_mark (token, RC_SERVICE_STOPPED);
1343 free (service); 1408 free (service);
1344 } 1409 }
1345 } 1410 }
1346#endif 1411#endif
1347 1412
1348 /* Store our interactive status for boot */ 1413 /* Store our interactive status for boot */
1349 if (interactive && strcmp (runlevel, bootlevel) == 0) 1414 if (interactive && strcmp (runlevel, bootlevel) == 0)
1350 mark_interactive (); 1415 mark_interactive ();
1351 else { 1416 else {
1352 if (rc_exists (INTERACTIVE)) 1417 if (exists (INTERACTIVE))
1353 unlink (INTERACTIVE); 1418 unlink (INTERACTIVE);
1354 } 1419 }
1355 1420
1356 return (EXIT_SUCCESS); 1421 return (EXIT_SUCCESS);
1357} 1422}

Legend:
Removed from v.2834  
changed lines
  Added in v.3040

  ViewVC Help
Powered by ViewVC 1.1.20