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

Diff of /trunk/src/rc.c

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

Revision 2856 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"
61 63
62static char *RUNLEVEL = NULL; 64static char *RUNLEVEL = NULL;
63static char *PREVLEVEL = NULL; 65static char *PREVLEVEL = NULL;
64 66
65static char *applet = NULL; 67static char *applet = NULL;
68static char *runlevel = NULL;
66static char **env = NULL; 69static char **env = NULL;
67static char **newenv = NULL; 70static char **newenv = NULL;
68static char **coldplugged_services = NULL; 71static char **coldplugged_services = NULL;
69static char **stop_services = NULL; 72static char **stop_services = NULL;
70static char **start_services = NULL; 73static char **start_services = NULL;
71static rc_depinfo_t *deptree = NULL; 74static rc_depinfo_t *deptree = NULL;
72static char **types = NULL;
73static char *tmp = NULL; 75static char *tmp = NULL;
74 76
75struct termios *termios_orig = NULL; 77struct termios *termios_orig = NULL;
76 78
77typedef struct pidlist 79typedef struct pidlist
78{ 80{
79 pid_t pid; 81 pid_t pid;
80 struct pidlist *next; 82 struct pidlist *next;
81} pidlist_t; 83} pidlist_t;
82static 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 };
83 88
84static void cleanup (void) 89static void cleanup (void)
85{ 90{
86 if (applet && strcmp (applet, "rc") == 0) { 91 if (applet && strcmp (applet, "rc") == 0) {
87 pidlist_t *pl = service_pids; 92 pidlist_t *pl = service_pids;
102 rc_strlist_free (env); 107 rc_strlist_free (env);
103 rc_strlist_free (newenv); 108 rc_strlist_free (newenv);
104 rc_strlist_free (coldplugged_services); 109 rc_strlist_free (coldplugged_services);
105 rc_strlist_free (stop_services); 110 rc_strlist_free (stop_services);
106 rc_strlist_free (start_services); 111 rc_strlist_free (start_services);
107 rc_free_deptree (deptree); 112 rc_deptree_free (deptree);
108 rc_strlist_free (types);
109 113
110 /* Clean runlevel start, stop markers */ 114 /* Clean runlevel start, stop markers */
111 if (! rc_in_plugin) { 115 if (! rc_in_plugin) {
112 if (rc_is_dir (RC_STARTING))
113 rc_rm_dir (RC_STARTING, true); 116 rmdir (RC_STARTING);
114 if (rc_is_dir (RC_STOPPING))
115 rc_rm_dir (RC_STOPPING, true); 117 rmdir (RC_STOPPING);
116 } 118 }
119
120 free (runlevel);
117 } 121 }
118 122
119 free (applet); 123 free (applet);
120} 124}
121 125
143 char *fmt = NULL; 147 char *fmt = NULL;
144 int level = 0; 148 int level = 0;
145 149
146 if (strcmp (applet, "eval_ecolors") == 0) { 150 if (strcmp (applet, "eval_ecolors") == 0) {
147 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",
148 ecolor (ecolor_good), 152 ecolor (ECOLOR_GOOD),
149 ecolor (ecolor_warn), 153 ecolor (ECOLOR_WARN),
150 ecolor (ecolor_bad), 154 ecolor (ECOLOR_BAD),
151 ecolor (ecolor_hilite), 155 ecolor (ECOLOR_HILITE),
152 ecolor (ecolor_bracket), 156 ecolor (ECOLOR_BRACKET),
153 ecolor (ecolor_normal)); 157 ecolor (ECOLOR_NORMAL));
154 exit (EXIT_SUCCESS); 158 exit (EXIT_SUCCESS);
155 } 159 }
156 160
157 if (argc > 0) { 161 if (argc > 0) {
158 162
188 192
189 if (argc > 0) { 193 if (argc > 0) {
190 for (i = 0; i < argc; i++) 194 for (i = 0; i < argc; i++)
191 l += strlen (argv[i]) + 1; 195 l += strlen (argv[i]) + 1;
192 196
193 message = rc_xmalloc (l); 197 message = xmalloc (l);
194 p = message; 198 p = message;
195 199
196 for (i = 0; i < argc; i++) { 200 for (i = 0; i < argc; i++) {
197 if (i > 0) 201 if (i > 0)
198 *p++ = ' '; 202 *p++ = ' ';
201 } 205 }
202 *p = 0; 206 *p = 0;
203 } 207 }
204 208
205 if (message) 209 if (message)
206 fmt = rc_xstrdup ("%s"); 210 fmt = xstrdup ("%s");
207 211
208 if (strcmp (applet, "einfo") == 0) 212 if (strcmp (applet, "einfo") == 0)
209 einfo (fmt, message); 213 einfo (fmt, message);
210 else if (strcmp (applet, "einfon") == 0) 214 else if (strcmp (applet, "einfon") == 0)
211 einfon (fmt, message); 215 einfon (fmt, message);
267 271
268 if (argc < 1 || ! argv[0] || strlen (argv[0]) == 0) 272 if (argc < 1 || ! argv[0] || strlen (argv[0]) == 0)
269 eerrorx ("%s: no service specified", applet); 273 eerrorx ("%s: no service specified", applet);
270 274
271 if (strcmp (applet, "service_started") == 0) 275 if (strcmp (applet, "service_started") == 0)
272 ok = rc_service_state (argv[0], rc_service_started); 276 ok = (rc_service_state (argv[0]) & RC_SERVICE_STARTED);
273 else if (strcmp (applet, "service_stopped") == 0) 277 else if (strcmp (applet, "service_stopped") == 0)
274 ok = rc_service_state (argv[0], rc_service_stopped); 278 ok = (rc_service_state (argv[0]) & RC_SERVICE_STOPPED);
275 else if (strcmp (applet, "service_inactive") == 0) 279 else if (strcmp (applet, "service_inactive") == 0)
276 ok = rc_service_state (argv[0], rc_service_inactive); 280 ok = (rc_service_state (argv[0]) & RC_SERVICE_INACTIVE);
277 else if (strcmp (applet, "service_starting") == 0) 281 else if (strcmp (applet, "service_starting") == 0)
278 ok = rc_service_state (argv[0], rc_service_starting); 282 ok = (rc_service_state (argv[0]) & RC_SERVICE_STOPPING);
279 else if (strcmp (applet, "service_stopping") == 0) 283 else if (strcmp (applet, "service_stopping") == 0)
280 ok = rc_service_state (argv[0], rc_service_stopping); 284 ok = (rc_service_state (argv[0]) & RC_SERVICE_STOPPING);
281 else if (strcmp (applet, "service_coldplugged") == 0) 285 else if (strcmp (applet, "service_coldplugged") == 0)
282 ok = rc_service_state (argv[0], rc_service_coldplugged); 286 ok = (rc_service_state (argv[0]) & RC_SERVICE_COLDPLUGGED);
283 else if (strcmp (applet, "service_wasinactive") == 0) 287 else if (strcmp (applet, "service_wasinactive") == 0)
284 ok = rc_service_state (argv[0], rc_service_wasinactive); 288 ok = (rc_service_state (argv[0]) & RC_SERVICE_WASINACTIVE);
285 else if (strcmp (applet, "service_started_daemon") == 0) { 289 else if (strcmp (applet, "service_started_daemon") == 0) {
286 int idx = 0; 290 int idx = 0;
287 if (argc > 2) 291 if (argc > 2)
288 sscanf (argv[2], "%d", &idx); 292 sscanf (argv[2], "%d", &idx);
289 exit (rc_service_started_daemon (argv[0], argv[1], idx) 293 exit (rc_service_started_daemon (argv[0], argv[1], idx)
301 305
302 if (argc < 1 || ! argv[0] || strlen (argv[0]) == 0) 306 if (argc < 1 || ! argv[0] || strlen (argv[0]) == 0)
303 eerrorx ("%s: no service specified", applet); 307 eerrorx ("%s: no service specified", applet);
304 308
305 if (strcmp (applet, "mark_service_started") == 0) 309 if (strcmp (applet, "mark_service_started") == 0)
306 ok = rc_mark_service (argv[0], rc_service_started); 310 ok = rc_service_mark (argv[0], RC_SERVICE_STARTED);
307 else if (strcmp (applet, "mark_service_stopped") == 0) 311 else if (strcmp (applet, "mark_service_stopped") == 0)
308 ok = rc_mark_service (argv[0], rc_service_stopped); 312 ok = rc_service_mark (argv[0], RC_SERVICE_STOPPED);
309 else if (strcmp (applet, "mark_service_inactive") == 0) 313 else if (strcmp (applet, "mark_service_inactive") == 0)
310 ok = rc_mark_service (argv[0], rc_service_inactive); 314 ok = rc_service_mark (argv[0], RC_SERVICE_INACTIVE);
311 else if (strcmp (applet, "mark_service_starting") == 0) 315 else if (strcmp (applet, "mark_service_starting") == 0)
312 ok = rc_mark_service (argv[0], rc_service_starting); 316 ok = rc_service_mark (argv[0], RC_SERVICE_STOPPING);
313 else if (strcmp (applet, "mark_service_stopping") == 0) 317 else if (strcmp (applet, "mark_service_stopping") == 0)
314 ok = rc_mark_service (argv[0], rc_service_stopping); 318 ok = rc_service_mark (argv[0], RC_SERVICE_STOPPING);
315 else if (strcmp (applet, "mark_service_coldplugged") == 0) 319 else if (strcmp (applet, "mark_service_coldplugged") == 0)
316 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);
317 else 323 else
318 eerrorx ("%s: unknown applet", applet); 324 eerrorx ("%s: unknown applet", applet);
319 325
320 /* 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
321 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 */
328 if (runscript_pid && sscanf (runscript_pid, "%d", &pid) == 1) 334 if (runscript_pid && sscanf (runscript_pid, "%d", &pid) == 1)
329 if (kill (pid, SIGHUP) != 0) 335 if (kill (pid, SIGHUP) != 0)
330 eerror ("%s: failed to signal parent %d: %s", 336 eerror ("%s: failed to signal parent %d: %s",
331 applet, pid, strerror (errno)); 337 applet, pid, strerror (errno));
332 338
333 /* Remove the exclsive time test. This ensures that it's not 339 /* Remove the exclusive time test. This ensures that it's not
334 in control as well */ 340 in control as well */
335 l = strlen (RC_SVCDIR "exclusive") + 341 l = strlen (RC_SVCDIR "exclusive") +
336 strlen (svcname) + 342 strlen (svcname) +
337 strlen (runscript_pid) + 343 strlen (runscript_pid) +
338 4; 344 4;
339 mtime = rc_xmalloc (l); 345 mtime = xmalloc (l);
340 snprintf (mtime, l, RC_SVCDIR "exclusive/%s.%s", 346 snprintf (mtime, l, RC_SVCDIR "exclusive/%s.%s",
341 svcname, runscript_pid); 347 svcname, runscript_pid);
342 if (rc_exists (mtime) && unlink (mtime) != 0) 348 if (exists (mtime) && unlink (mtime) != 0)
343 eerror ("%s: unlink: %s", applet, strerror (errno)); 349 eerror ("%s: unlink: %s", applet, strerror (errno));
344 free (mtime); 350 free (mtime);
345 } 351 }
346 352
347 return (ok ? EXIT_SUCCESS : EXIT_FAILURE); 353 return (ok ? EXIT_SUCCESS : EXIT_FAILURE);
357 363
358 if (argc < 1 || ! argv[0] || strlen (argv[0]) == 0) 364 if (argc < 1 || ! argv[0] || strlen (argv[0]) == 0)
359 eerrorx ("%s: no option specified", applet); 365 eerrorx ("%s: no option specified", applet);
360 366
361 if (strcmp (applet, "get_options") == 0) { 367 if (strcmp (applet, "get_options") == 0) {
362 char buffer[1024]; 368 char *option = rc_service_value_get (service, argv[0]);
363 memset (buffer, 0, 1024); 369 if (option) {
364 ok = rc_get_service_option (service, argv[0], buffer);
365 if (ok)
366 printf ("%s", buffer); 370 printf ("%s", option);
371 free (option);
372 ok = true;
373 }
367 } else if (strcmp (applet, "save_options") == 0) 374 } else if (strcmp (applet, "save_options") == 0)
368 ok = rc_set_service_option (service, argv[0], argv[1]); 375 ok = rc_service_value_set (service, argv[0], argv[1]);
369 else 376 else
370 eerrorx ("%s: unknown applet", applet); 377 eerrorx ("%s: unknown applet", applet);
371 378
372 return (ok ? EXIT_SUCCESS : EXIT_FAILURE); 379 return (ok ? EXIT_SUCCESS : EXIT_FAILURE);
373} 380}
374 381
375#ifdef __linux__ 382#ifdef __linux__
376static char *proc_getent (const char *ent) 383static char *proc_getent (const char *ent)
377{ 384{
378 FILE *fp; 385 FILE *fp;
379 char buffer[RC_LINEBUFFER]; 386 char *buffer;
380 char *p; 387 char *p;
381 char *value = NULL; 388 char *value = NULL;
382 int i; 389 int i;
383 390
384 if (! rc_exists ("/proc/cmdline")) 391 if (! exists ("/proc/cmdline"))
385 return (NULL); 392 return (NULL);
386 393
387 if (! (fp = fopen ("/proc/cmdline", "r"))) { 394 if (! (fp = fopen ("/proc/cmdline", "r"))) {
388 eerror ("failed to open `/proc/cmdline': %s", strerror (errno)); 395 eerror ("failed to open `/proc/cmdline': %s", strerror (errno));
389 return (NULL); 396 return (NULL);
390 } 397 }
391 398
392 memset (buffer, 0, sizeof (buffer)); 399 buffer = xmalloc (sizeof (char) * RC_LINEBUFFER);
400 memset (buffer, 0, RC_LINEBUFFER);
393 if (fgets (buffer, RC_LINEBUFFER, fp) && 401 if (fgets (buffer, RC_LINEBUFFER, fp) &&
394 (p = strstr (buffer, ent))) 402 (p = strstr (buffer, ent)))
395 { 403 {
396 i = p - buffer; 404 i = p - buffer;
397 if (i == '\0' || buffer[i - 1] == ' ') { 405 if (i == '\0' || buffer[i - 1] == ' ') {
401 buffer[i] = 0; 409 buffer[i] = 0;
402 410
403 p += strlen (ent); 411 p += strlen (ent);
404 if (*p == '=') 412 if (*p == '=')
405 p++; 413 p++;
406 value = strdup (strsep (&p, " ")); 414 value = xstrdup (strsep (&p, " "));
407 } 415 }
408 } else 416 } else
409 errno = ENOENT; 417 errno = ENOENT;
418 free (buffer);
410 fclose (fp); 419 fclose (fp);
411 420
412 return (value); 421 return (value);
413} 422}
414#endif 423#endif
416static char read_key (bool block) 425static char read_key (bool block)
417{ 426{
418 struct termios termios; 427 struct termios termios;
419 char c = 0; 428 char c = 0;
420 int fd = fileno (stdin); 429 int fd = fileno (stdin);
421 430
422 if (! isatty (fd)) 431 if (! isatty (fd))
423 return (false); 432 return (false);
424 433
425 /* 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
426 will be changing it for non-blocking reads for Interactive */ 435 will be changing it for non-blocking reads for Interactive */
427 if (! termios_orig) { 436 if (! termios_orig) {
428 termios_orig = rc_xmalloc (sizeof (struct termios)); 437 termios_orig = xmalloc (sizeof (struct termios));
429 tcgetattr (fd, termios_orig); 438 tcgetattr (fd, termios_orig);
430 } 439 }
431 440
432 tcgetattr (fd, &termios); 441 tcgetattr (fd, &termios);
433 termios.c_lflag &= ~(ICANON | ECHO); 442 termios.c_lflag &= ~(ICANON | ECHO);
454 strcmp (PREVLEVEL, "N") != 0 && 463 strcmp (PREVLEVEL, "N") != 0 &&
455 strcmp (PREVLEVEL, "S") != 0 && 464 strcmp (PREVLEVEL, "S") != 0 &&
456 strcmp (PREVLEVEL, "1") != 0) 465 strcmp (PREVLEVEL, "1") != 0)
457 return (false); 466 return (false);
458 467
459 if (! rc_is_env ("RC_INTERACTIVE", "yes")) 468 if (! rc_env_bool ("RC_INTERACTIVE"))
460 return (false); 469 return (false);
461 470
462 c = read_key (false); 471 c = read_key (false);
463 return ((c == 'I' || c == 'i') ? true : false); 472 return ((c == 'I' || c == 'i') ? true : false);
464} 473}
480 execl ("/sbin/halt", "/sbin/halt", "-f", (char *) NULL); 489 execl ("/sbin/halt", "/sbin/halt", "-f", (char *) NULL);
481 eerrorx ("%s: unable to exec `/sbin/halt': %s", applet, strerror (errno)); 490 eerrorx ("%s: unable to exec `/sbin/halt': %s", applet, strerror (errno));
482 } 491 }
483#endif 492#endif
484 493
485 newenv = rc_filter_env (); 494 newenv = env_filter ();
486 495
487 if (cont) { 496 if (cont) {
488 int status = 0; 497 int status = 0;
489#ifdef __linux__ 498#ifdef __linux__
490 char *tty = ttyname (fileno (stdout)); 499 char *tty = ttyname (fileno (stdout));
533 applet, strerror (errno)); 542 applet, strerror (errno));
534 exit (EXIT_SUCCESS); 543 exit (EXIT_SUCCESS);
535#endif 544#endif
536} 545}
537 546
538static void set_ksoftlevel (const char *runlevel) 547static void set_ksoftlevel (const char *level)
539{ 548{
540 FILE *fp; 549 FILE *fp;
541 550
542 if (! runlevel || 551 if (! level ||
543 strcmp (runlevel, getenv ("RC_BOOTLEVEL")) == 0 || 552 strcmp (level, getenv ("RC_BOOTLEVEL")) == 0 ||
544 strcmp (runlevel, RC_LEVEL_SINGLE) == 0 || 553 strcmp (level, RC_LEVEL_SINGLE) == 0 ||
545 strcmp (runlevel, RC_LEVEL_SYSINIT) == 0) 554 strcmp (level, RC_LEVEL_SYSINIT) == 0)
546 { 555 {
547 if (rc_exists (RC_KSOFTLEVEL) && 556 if (exists (RC_KSOFTLEVEL) &&
548 unlink (RC_KSOFTLEVEL) != 0) 557 unlink (RC_KSOFTLEVEL) != 0)
549 eerror ("unlink `%s': %s", RC_KSOFTLEVEL, strerror (errno)); 558 eerror ("unlink `%s': %s", RC_KSOFTLEVEL, strerror (errno));
550 return; 559 return;
551 } 560 }
552 561
553 if (! (fp = fopen (RC_KSOFTLEVEL, "w"))) { 562 if (! (fp = fopen (RC_KSOFTLEVEL, "w"))) {
554 eerror ("fopen `%s': %s", RC_KSOFTLEVEL, strerror (errno)); 563 eerror ("fopen `%s': %s", RC_KSOFTLEVEL, strerror (errno));
555 return; 564 return;
556 } 565 }
557 566
558 fprintf (fp, "%s", runlevel); 567 fprintf (fp, "%s", level);
559 fclose (fp); 568 fclose (fp);
560} 569}
561 570
562static int get_ksoftlevel (char *buffer, int buffer_len) 571static int get_ksoftlevel (char *buffer, int buffer_len)
563{ 572{
564 FILE *fp; 573 FILE *fp;
565 int i = 0; 574 int i = 0;
566 575
567 if (! rc_exists (RC_KSOFTLEVEL)) 576 if (! exists (RC_KSOFTLEVEL))
568 return (0); 577 return (0);
569 578
570 if (! (fp = fopen (RC_KSOFTLEVEL, "r"))) { 579 if (! (fp = fopen (RC_KSOFTLEVEL, "r"))) {
571 eerror ("fopen `%s': %s", RC_KSOFTLEVEL, strerror (errno)); 580 eerror ("fopen `%s': %s", RC_KSOFTLEVEL, strerror (errno));
572 return (-1); 581 return (-1);
592{ 601{
593 pidlist_t *sp = service_pids; 602 pidlist_t *sp = service_pids;
594 if (sp) { 603 if (sp) {
595 while (sp->next) 604 while (sp->next)
596 sp = sp->next; 605 sp = sp->next;
597 sp->next = rc_xmalloc (sizeof (pidlist_t)); 606 sp->next = xmalloc (sizeof (pidlist_t));
598 sp = sp->next; 607 sp = sp->next;
599 } else 608 } else
600 sp = service_pids = rc_xmalloc (sizeof (pidlist_t)); 609 sp = service_pids = xmalloc (sizeof (pidlist_t));
601 memset (sp, 0, sizeof (pidlist_t)); 610 memset (sp, 0, sizeof (pidlist_t));
602 sp->pid = pid; 611 sp->pid = pid;
603} 612}
604 613
605static void remove_pid (pid_t pid) 614static void remove_pid (pid_t pid)
616 free (pl); 625 free (pl);
617 break; 626 break;
618 } 627 }
619 last = pl; 628 last = pl;
620 } 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);
621} 645}
622 646
623static void handle_signal (int sig) 647static void handle_signal (int sig)
624{ 648{
625 int serrno = errno; 649 int serrno = errno;
661 signal (SIGCHLD, SIG_IGN); 685 signal (SIGCHLD, SIG_IGN);
662 for (pl = service_pids; pl; pl = pl->next) 686 for (pl = service_pids; pl; pl = pl->next)
663 kill (pl->pid, SIGTERM); 687 kill (pl->pid, SIGTERM);
664 688
665 /* Notify plugins we are aborting */ 689 /* Notify plugins we are aborting */
666 rc_plugin_run (rc_hook_abort, NULL); 690 rc_plugin_run (RC_HOOK_ABORT, NULL);
667 691
668 /* Only drop into single user mode if we're booting */ 692 /* Only drop into single user mode if we're booting */
669 if ((PREVLEVEL && 693 if ((PREVLEVEL &&
670 (strcmp (PREVLEVEL, "S") == 0 || 694 (strcmp (PREVLEVEL, "S") == 0 ||
671 strcmp (PREVLEVEL, "1") == 0)) || 695 strcmp (PREVLEVEL, "1") == 0)) ||
707 if (! WIFEXITED (status) || ! WEXITSTATUS (status) == 0) 731 if (! WIFEXITED (status) || ! WEXITSTATUS (status) == 0)
708 eerrorx ("%s: failed to exec `%s'", applet, script); 732 eerrorx ("%s: failed to exec `%s'", applet, script);
709} 733}
710 734
711#include "_usage.h" 735#include "_usage.h"
712#define getoptstring getoptstring_COMMON 736#define getoptstring getoptstring_COMMON
713static struct option longopts[] = { 737static struct option longopts[] = {
714 longopts_COMMON 738 longopts_COMMON
715 { NULL, 0, NULL, 0} 739};
740static const char * const longopts_help[] = {
741 longopts_help_COMMON
716}; 742};
717#include "_usage.c" 743#include "_usage.c"
718 744
719int main (int argc, char **argv) 745int main (int argc, char **argv)
720{ 746{
721 char *runlevel = NULL;
722 const char *bootlevel = NULL; 747 const char *bootlevel = NULL;
723 char *newlevel = NULL; 748 char *newlevel = NULL;
724 char *service = NULL; 749 char *service = NULL;
725 char **deporder = NULL; 750 char **deporder = NULL;
751 char **tmplist;
726 int i = 0; 752 int i = 0;
727 int j = 0; 753 int j = 0;
728 bool going_down = false; 754 bool going_down = false;
729 bool interactive = false; 755 bool interactive = false;
730 int depoptions = RC_DEP_STRICT | RC_DEP_TRACE; 756 int depoptions = RC_DEP_STRICT | RC_DEP_TRACE;
731 char ksoftbuffer [PATH_MAX]; 757 char ksoftbuffer [PATH_MAX];
732 char pidstr[6]; 758 char pidstr[6];
733 int opt; 759 int opt;
760 DIR *dp;
761 struct dirent *d;
734 762
735 atexit (cleanup); 763 atexit (cleanup);
736 if (argv[0]) 764 if (argv[0])
737 applet = rc_xstrdup (basename (argv[0])); 765 applet = xstrdup (basename (argv[0]));
738 766
739 if (! applet) 767 if (! applet)
740 eerrorx ("arguments required"); 768 eerrorx ("arguments required");
741 769
742 /* 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
756 exit (rc_update (argc, argv)); 784 exit (rc_update (argc, argv));
757 else if (strcmp (applet, "runscript") == 0) 785 else if (strcmp (applet, "runscript") == 0)
758 exit (runscript (argc, argv)); 786 exit (runscript (argc, argv));
759 else if (strcmp (applet, "start-stop-daemon") == 0) 787 else if (strcmp (applet, "start-stop-daemon") == 0)
760 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));
761 791
762 argc--; 792 argc--;
763 argv++; 793 argv++;
764 794
765 /* Handle multicall stuff */ 795 /* Handle multicall stuff */
812 signal (SIGTERM, handle_signal); 842 signal (SIGTERM, handle_signal);
813 signal (SIGUSR1, handle_signal); 843 signal (SIGUSR1, handle_signal);
814 844
815 /* Ensure our environment is pure 845 /* Ensure our environment is pure
816 Also, add our configuration to it */ 846 Also, add our configuration to it */
817 env = rc_filter_env (); 847 env = env_filter ();
818 env = rc_config_env (env); 848 tmplist = env_config ();
849 rc_strlist_join (&env, tmplist);
850 rc_strlist_free (tmplist);
819 851
820 if (env) { 852 if (env) {
821 char *p; 853 char *p;
822 854
823#ifdef __linux__ 855#ifdef __linux__
829 /* No clearenv present here then. 861 /* No clearenv present here then.
830 We could manipulate environ directly ourselves, but it seems that 862 We could manipulate environ directly ourselves, but it seems that
831 some kernels bitch about this according to the environ man pages 863 some kernels bitch about this according to the environ man pages
832 so we walk though environ and call unsetenv for each value. */ 864 so we walk though environ and call unsetenv for each value. */
833 while (environ[0]) { 865 while (environ[0]) {
834 tmp = rc_xstrdup (environ[0]); 866 tmp = xstrdup (environ[0]);
835 p = tmp; 867 p = tmp;
836 var = strsep (&p, "="); 868 var = strsep (&p, "=");
837 unsetenv (var); 869 unsetenv (var);
838 free (tmp); 870 free (tmp);
839 } 871 }
869 901
870 /* Export our PID */ 902 /* Export our PID */
871 snprintf (pidstr, sizeof (pidstr), "%d", getpid ()); 903 snprintf (pidstr, sizeof (pidstr), "%d", getpid ());
872 setenv ("RC_PID", pidstr, 1); 904 setenv ("RC_PID", pidstr, 1);
873 905
874 interactive = rc_exists (INTERACTIVE); 906 interactive = exists (INTERACTIVE);
875 rc_plugin_load (); 907 rc_plugin_load ();
876 908
877 /* Load current softlevel */ 909 /* Load current softlevel */
878 bootlevel = getenv ("RC_BOOTLEVEL"); 910 bootlevel = getenv ("RC_BOOTLEVEL");
879 runlevel = rc_get_runlevel (); 911 runlevel = rc_runlevel_get ();
880 912
881 /* Check we're in the runlevel requested, ie from 913 /* Check we're in the runlevel requested, ie from
882 rc single 914 rc single
883 rc shutdown 915 rc shutdown
884 rc reboot 916 rc reboot
896#endif 928#endif
897 929
898 /* exec init-early.sh if it exists 930 /* exec init-early.sh if it exists
899 * This should just setup the console to use the correct 931 * This should just setup the console to use the correct
900 * font. Maybe it should setup the keyboard too? */ 932 * font. Maybe it should setup the keyboard too? */
901 if (rc_exists (INITEARLYSH)) 933 if (exists (INITEARLYSH))
902 run_script (INITEARLYSH); 934 run_script (INITEARLYSH);
903 935
904 uname (&uts); 936 uname (&uts);
905 937
906 printf ("\n"); 938 printf ("\n");
907 printf (" %sGentoo/%s; %shttp://www.gentoo.org/%s" 939 printf (" %sGentoo/%s; %shttp://www.gentoo.org/%s"
908 "\n Copyright 1999-2007 Gentoo Foundation; " 940 "\n Copyright 1999-2007 Gentoo Foundation; "
909 "Distributed under the GPLv2\n\n", 941 "Distributed under the GPLv2\n\n",
910 ecolor (ecolor_good), uts.sysname, ecolor (ecolor_bracket), 942 ecolor (ECOLOR_GOOD), uts.sysname, ecolor (ECOLOR_BRACKET),
911 ecolor (ecolor_normal)); 943 ecolor (ECOLOR_NORMAL));
912 944
913 if (rc_is_env ("RC_INTERACTIVE", "yes")) 945 if (rc_env_bool ("RC_INTERACTIVE"))
914 printf ("Press %sI%s to enter interactive boot mode\n\n", 946 printf ("Press %sI%s to enter interactive boot mode\n\n",
915 ecolor (ecolor_good), ecolor (ecolor_normal)); 947 ecolor (ECOLOR_GOOD), ecolor (ECOLOR_NORMAL));
916 948
917 setenv ("RC_SOFTLEVEL", newlevel, 1); 949 setenv ("RC_SOFTLEVEL", newlevel, 1);
918 rc_plugin_run (rc_hook_runlevel_start_in, newlevel); 950 rc_plugin_run (RC_HOOK_RUNLEVEL_START_IN, newlevel);
919 run_script (INITSH); 951 run_script (INITSH);
920 952
921#ifdef __linux__ 953#ifdef __linux__
922 /* If we requested a softlevel, save it now */ 954 /* If we requested a softlevel, save it now */
923 set_ksoftlevel (NULL); 955 set_ksoftlevel (NULL);
925 set_ksoftlevel (cmd); 957 set_ksoftlevel (cmd);
926 free (cmd); 958 free (cmd);
927 } 959 }
928 960
929#endif 961#endif
930 rc_plugin_run (rc_hook_runlevel_start_out, newlevel); 962 rc_plugin_run (RC_HOOK_RUNLEVEL_START_OUT, newlevel);
931 963
932 if (want_interactive ()) 964 if (want_interactive ())
933 mark_interactive (); 965 mark_interactive ();
934 966
935 exit (EXIT_SUCCESS); 967 exit (EXIT_SUCCESS);
994 (strcmp (newlevel, RC_LEVEL_REBOOT) == 0 || 1026 (strcmp (newlevel, RC_LEVEL_REBOOT) == 0 ||
995 strcmp (newlevel, RC_LEVEL_SHUTDOWN) == 0 || 1027 strcmp (newlevel, RC_LEVEL_SHUTDOWN) == 0 ||
996 strcmp (newlevel, RC_LEVEL_SINGLE) == 0)) 1028 strcmp (newlevel, RC_LEVEL_SINGLE) == 0))
997 { 1029 {
998 going_down = true; 1030 going_down = true;
999 rc_set_runlevel (newlevel); 1031 rc_runlevel_set (newlevel);
1000 setenv ("RC_SOFTLEVEL", newlevel, 1); 1032 setenv ("RC_SOFTLEVEL", newlevel, 1);
1001 rc_plugin_run (rc_hook_runlevel_stop_in, newlevel); 1033 rc_plugin_run (RC_HOOK_RUNLEVEL_STOP_IN, newlevel);
1002 } else { 1034 } else {
1003 rc_plugin_run (rc_hook_runlevel_stop_in, runlevel); 1035 rc_plugin_run (RC_HOOK_RUNLEVEL_STOP_IN, runlevel);
1004 } 1036 }
1005 1037
1006 /* Check if runlevel is valid if we're changing */ 1038 /* Check if runlevel is valid if we're changing */
1007 if (newlevel && strcmp (runlevel, newlevel) != 0 && ! going_down) { 1039 if (newlevel && strcmp (runlevel, newlevel) != 0 && ! going_down) {
1008 tmp = rc_strcatpaths (RC_RUNLEVELDIR, newlevel, (char *) NULL); 1040 if (! rc_runlevel_exists (newlevel))
1009 if (! rc_is_dir (tmp))
1010 eerrorx ("%s: is not a valid runlevel", newlevel); 1041 eerrorx ("%s: is not a valid runlevel", newlevel);
1011 CHAR_FREE (tmp);
1012 } 1042 }
1013 1043
1014 /* Load our deptree now */ 1044 /* Load our deptree now */
1015 if ((deptree = rc_load_deptree ()) == NULL) 1045 if ((deptree = _rc_deptree_load ()) == NULL)
1016 eerrorx ("failed to load deptree"); 1046 eerrorx ("failed to load deptree");
1017 1047
1018 /* Clean the failed services state dir now */ 1048 /* Clean the failed services state dir now */
1019 if (rc_is_dir (RC_SVCDIR "failed")) 1049 if ((dp = opendir (RC_SVCDIR "/failed"))) {
1020 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;
1055
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 }
1021 1066
1022 mkdir (RC_STOPPING, 0755); 1067 mkdir (RC_STOPPING, 0755);
1023 1068
1024#ifdef __linux__ 1069#ifdef __linux__
1025 /* 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
1026 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
1027 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
1028 here when we are ready for them */ 1073 here when we are ready for them */
1029 if (rc_is_dir (DEVBOOT)) { 1074 if ((dp = opendir (DEVBOOT))) {
1030 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);
1031 rc_rm_dir (DEVBOOT, true); 1094 rmdir (DEVBOOT);
1032
1033 STRLIST_FOREACH (start_services, service, i)
1034 if (rc_allow_plug (service))
1035 rc_mark_service (service, rc_service_coldplugged);
1036 /* We need to dump this list now.
1037 This may seem redunant, but only Linux needs this and saves on
1038 code bloat. */
1039 rc_strlist_free (start_services);
1040 start_services = NULL;
1041 } 1095 }
1042#else 1096#else
1043 /* 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.
1044 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
1045 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
1046 runlevel for our dependency tree to work. */ 1100 runlevel for our dependency tree to work. */
1047 if (newlevel && strcmp (newlevel, bootlevel) == 0 && 1101 if (newlevel && strcmp (newlevel, bootlevel) == 0 &&
1048 (strcmp (runlevel, RC_LEVEL_SINGLE) == 0 || 1102 (strcmp (runlevel, RC_LEVEL_SINGLE) == 0 ||
1049 strcmp (runlevel, RC_LEVEL_SYSINIT) == 0) && 1103 strcmp (runlevel, RC_LEVEL_SYSINIT) == 0) &&
1050 rc_is_env ("RC_COLDPLUG", "yes")) 1104 rc_env_bool ("RC_COLDPLUG"))
1051 { 1105 {
1052#if defined(__DragonFly__) || defined(__FreeBSD__) 1106#if defined(__DragonFly__) || defined(__FreeBSD__)
1053 /* 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 :) */
1054 start_services = rc_ls_dir (NULL, "/dev/net", 0); 1108 if ((dp = opendir ("/dev/net"))) {
1055 STRLIST_FOREACH (start_services, service, i) { 1109 while ((d = readdir (dp))) {
1056 j = (strlen ("net.") + strlen (service) + 1); 1110 i = (strlen ("net.") + strlen (d->d_name) + 1);
1057 tmp = rc_xmalloc (sizeof (char *) * j); 1111 tmp = xmalloc (sizeof (char) * i);
1058 snprintf (tmp, j, "net.%s", service); 1112 snprintf (tmp, i, "net.%s", d->d_name);
1059 if (rc_service_exists (tmp) && rc_allow_plug (tmp)) 1113 if (rc_service_exists (tmp) &&
1060 rc_mark_service (tmp, rc_service_coldplugged); 1114 rc_service_plugable (tmp))
1115 rc_service_mark (tmp, RC_SERVICE_COLDPLUGGED);
1061 CHAR_FREE (tmp); 1116 CHAR_FREE (tmp);
1062 } 1117 }
1063 rc_strlist_free (start_services); 1118 closedir (dp);
1119 }
1064#endif 1120#endif
1065 1121
1066 /* The mice are a little more tricky. 1122 /* The mice are a little more tricky.
1067 If we coldplug anything else, we'll probably do it here. */ 1123 If we coldplug anything else, we'll probably do it here. */
1068 start_services = rc_ls_dir (NULL, "/dev", 0); 1124 if ((dp == opendir ("/dev"))) {
1069 STRLIST_FOREACH (start_services, service, i) { 1125 while ((d = readdir (dp))) {
1070 if (strncmp (service, "psm", 3) == 0 || 1126 if (strncmp (d->d_name, "psm", 3) == 0 ||
1071 strncmp (service, "ums", 3) == 0) 1127 strncmp (d->d_name, "ums", 3) == 0)
1072 { 1128 {
1073 char *p = service + 3; 1129 char *p = d->d_name + 3;
1074 if (p && isdigit (*p)) { 1130 if (p && isdigit (*p)) {
1075 j = (strlen ("moused.") + strlen (service) + 1); 1131 i = (strlen ("moused.") + strlen (d->d_name) + 1);
1076 tmp = rc_xmalloc (sizeof (char *) * j); 1132 tmp = xmalloc (sizeof (char) * i);
1077 snprintf (tmp, j, "moused.%s", service); 1133 snprintf (tmp, i, "moused.%s", d->d_name);
1078 if (rc_service_exists (tmp) && rc_allow_plug (tmp)) 1134 if (rc_service_exists (tmp) && rc_service_plugable (tmp))
1079 rc_mark_service (tmp, rc_service_coldplugged); 1135 rc_service_mark (tmp, RC_SERVICE_COLDPLUGGED);
1080 CHAR_FREE (tmp); 1136 CHAR_FREE (tmp);
1137 }
1081 } 1138 }
1082 } 1139 }
1140 closedir (dp);
1083 } 1141 }
1084 rc_strlist_free (start_services);
1085 start_services = NULL;
1086 } 1142 }
1087#endif 1143#endif
1088 1144
1089 /* 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
1090 correct order for stopping them */ 1146 correct order for stopping them */
1091 stop_services = rc_ls_dir (stop_services, RC_SVCDIR_STARTING, RC_LS_INITD); 1147 stop_services = rc_services_in_state (RC_SERVICE_STARTING);
1092 stop_services = rc_ls_dir (stop_services, RC_SVCDIR_INACTIVE, RC_LS_INITD);
1093 stop_services = rc_ls_dir (stop_services, RC_SVCDIR_STARTED, RC_LS_INITD);
1094 1148
1095 types = rc_strlist_add (NULL, "ineed"); 1149 tmplist = rc_services_in_state (RC_SERVICE_INACTIVE);
1096 types = rc_strlist_add (types, "iuse"); 1150 rc_strlist_join (&stop_services, tmplist);
1097 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
1098 deporder = rc_get_depends (deptree, types, stop_services, 1157 deporder = rc_deptree_depends (deptree, types_nua,
1158 (const char **) stop_services,
1099 runlevel, depoptions | RC_DEP_STOP); 1159 runlevel, depoptions | RC_DEP_STOP);
1160
1100 rc_strlist_free (stop_services); 1161 rc_strlist_free (stop_services);
1101 rc_strlist_free (types);
1102 stop_services = deporder; 1162 stop_services = deporder;
1103 deporder = NULL; 1163 deporder = NULL;
1104 types = NULL;
1105 rc_strlist_reverse (stop_services); 1164 rc_strlist_reverse (stop_services);
1106 1165
1107 /* Load our list of coldplugged services */ 1166 /* Load our list of coldplugged services */
1108 coldplugged_services = rc_ls_dir (coldplugged_services, 1167 coldplugged_services = rc_services_in_state (RC_SERVICE_COLDPLUGGED);
1109 RC_SVCDIR_COLDPLUGGED, RC_LS_INITD);
1110 1168
1111 /* Load our start services now. 1169 /* Load our start services now.
1112 We have different rules dependent on runlevel. */ 1170 We have different rules dependent on runlevel. */
1113 if (newlevel && strcmp (newlevel, bootlevel) == 0) { 1171 if (newlevel && strcmp (newlevel, bootlevel) == 0) {
1114 if (coldplugged_services) { 1172 if (coldplugged_services) {
1115 einfon ("Device initiated services:"); 1173 einfon ("Device initiated services:");
1116 STRLIST_FOREACH (coldplugged_services, service, i) { 1174 STRLIST_FOREACH (coldplugged_services, service, i) {
1117 printf (" %s", service); 1175 printf (" %s", service);
1118 start_services = rc_strlist_add (start_services, service); 1176 rc_strlist_add (&start_services, service);
1119 } 1177 }
1120 printf ("\n"); 1178 printf ("\n");
1121 } 1179 }
1122 tmp = rc_strcatpaths (RC_RUNLEVELDIR, newlevel ? newlevel : runlevel, 1180 tmplist = rc_services_in_runlevel (newlevel ? newlevel : runlevel);
1123 (char *) NULL); 1181 rc_strlist_join (&start_services, tmplist);
1124 start_services = rc_ls_dir (start_services, tmp, RC_LS_INITD); 1182 rc_strlist_free (tmplist);
1125 CHAR_FREE (tmp);
1126 } else { 1183 } else {
1127 /* Store our list of coldplugged services */ 1184 /* Store our list of coldplugged services */
1128 coldplugged_services = rc_ls_dir (coldplugged_services, RC_SVCDIR_COLDPLUGGED, 1185 tmplist = rc_services_in_state (RC_SERVICE_COLDPLUGGED);
1129 RC_LS_INITD); 1186 rc_strlist_join (&coldplugged_services, tmplist);
1187 rc_strlist_free (tmplist);
1130 if (strcmp (newlevel ? newlevel : runlevel, RC_LEVEL_SINGLE) != 0 && 1188 if (strcmp (newlevel ? newlevel : runlevel, RC_LEVEL_SINGLE) != 0 &&
1131 strcmp (newlevel ? newlevel : runlevel, RC_LEVEL_SHUTDOWN) != 0 && 1189 strcmp (newlevel ? newlevel : runlevel, RC_LEVEL_SHUTDOWN) != 0 &&
1132 strcmp (newlevel ? newlevel : runlevel, RC_LEVEL_REBOOT) != 0) 1190 strcmp (newlevel ? newlevel : runlevel, RC_LEVEL_REBOOT) != 0)
1133 { 1191 {
1134 /* 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 */
1135 char **services = rc_services_in_runlevel (bootlevel); 1193 tmplist = rc_services_in_runlevel (bootlevel);
1136 1194 rc_strlist_join (&start_services, tmplist);
1137 start_services = rc_strlist_join (start_services, services); 1195 rc_strlist_free (tmplist);
1138 services = rc_services_in_runlevel (newlevel ? newlevel : runlevel); 1196 tmplist = rc_services_in_runlevel (newlevel ? newlevel : runlevel);
1139 start_services = rc_strlist_join (start_services, services); 1197 rc_strlist_join (&start_services, tmplist);
1140 services = NULL; 1198 rc_strlist_free (tmplist);
1141 1199
1142 STRLIST_FOREACH (coldplugged_services, service, i) 1200 STRLIST_FOREACH (coldplugged_services, service, i)
1143 start_services = rc_strlist_add (start_services, service); 1201 rc_strlist_add (&start_services, service);
1144 1202
1145 } 1203 }
1146 } 1204 }
1147 1205
1148 /* Save out softlevel now */ 1206 /* Save out softlevel now */
1149 if (going_down) 1207 if (going_down)
1150 rc_set_runlevel (newlevel); 1208 rc_runlevel_set (newlevel);
1151 1209
1152 types = rc_strlist_add (NULL, "needsme");
1153 /* Now stop the services that shouldn't be running */ 1210 /* Now stop the services that shouldn't be running */
1154 STRLIST_FOREACH (stop_services, service, i) { 1211 STRLIST_FOREACH (stop_services, service, i) {
1155 bool found = false; 1212 bool found = false;
1156 char *conf = NULL; 1213 char *conf = NULL;
1157 char **stopdeps = NULL; 1214 char **stopdeps = NULL;
1158 char *svc1 = NULL; 1215 char *svc1 = NULL;
1159 char *svc2 = NULL; 1216 char *svc2 = NULL;
1160 int k; 1217 int k;
1161 1218
1162 if (rc_service_state (service, rc_service_stopped)) 1219 if (rc_service_state (service) & RC_SERVICE_STOPPED)
1163 continue; 1220 continue;
1164 1221
1165 /* We always stop the service when in these runlevels */ 1222 /* We always stop the service when in these runlevels */
1166 if (going_down) { 1223 if (going_down) {
1167 pid_t pid = rc_stop_service (service); 1224 pid_t pid = rc_service_stop (service);
1168 if (pid > 0 && ! rc_is_env ("RC_PARALLEL", "yes")) 1225 if (pid > 0 && ! rc_env_bool ("RC_PARALLEL"))
1169 rc_waitpid (pid); 1226 wait_pid (pid);
1170 continue; 1227 continue;
1171 } 1228 }
1172 1229
1173 /* 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 */
1174 STRLIST_FOREACH (start_services, svc1, j) 1231 STRLIST_FOREACH (start_services, svc1, j)
1182 int len; 1239 int len;
1183 if (! newlevel) 1240 if (! newlevel)
1184 continue; 1241 continue;
1185 1242
1186 len = strlen (service) + strlen (runlevel) + 2; 1243 len = strlen (service) + strlen (runlevel) + 2;
1187 tmp = rc_xmalloc (sizeof (char *) * len); 1244 tmp = xmalloc (sizeof (char) * len);
1188 snprintf (tmp, len, "%s.%s", service, runlevel); 1245 snprintf (tmp, len, "%s.%s", service, runlevel);
1189 conf = rc_strcatpaths (RC_CONFDIR, tmp, (char *) NULL); 1246 conf = rc_strcatpaths (RC_CONFDIR, tmp, (char *) NULL);
1190 found = rc_exists (conf); 1247 found = exists (conf);
1191 CHAR_FREE (conf); 1248 CHAR_FREE (conf);
1192 CHAR_FREE (tmp); 1249 CHAR_FREE (tmp);
1193 if (! found) { 1250 if (! found) {
1194 len = strlen (service) + strlen (newlevel) + 2; 1251 len = strlen (service) + strlen (newlevel) + 2;
1195 tmp = rc_xmalloc (sizeof (char *) * len); 1252 tmp = xmalloc (sizeof (char) * len);
1196 snprintf (tmp, len, "%s.%s", service, newlevel); 1253 snprintf (tmp, len, "%s.%s", service, newlevel);
1197 conf = rc_strcatpaths (RC_CONFDIR, tmp, (char *) NULL); 1254 conf = rc_strcatpaths (RC_CONFDIR, tmp, (char *) NULL);
1198 found = rc_exists (conf); 1255 found = exists (conf);
1199 CHAR_FREE (conf); 1256 CHAR_FREE (conf);
1200 CHAR_FREE (tmp); 1257 CHAR_FREE (tmp);
1201 if (!found) 1258 if (!found)
1202 continue; 1259 continue;
1203 } 1260 }
1204 } else { 1261 } else {
1205 /* Allow coldplugged services not to be in the runlevels list */ 1262 /* Allow coldplugged services not to be in the runlevels list */
1206 if (rc_service_state (service, rc_service_coldplugged)) 1263 if (rc_service_state (service) & RC_SERVICE_COLDPLUGGED)
1207 continue; 1264 continue;
1208 } 1265 }
1209 1266
1210 /* 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
1211 going to be started depends on us */ 1268 going to be started depends on us */
1212 stopdeps = rc_strlist_add (stopdeps, service); 1269 rc_strlist_add (&stopdeps, service);
1213 deporder = rc_get_depends (deptree, types, stopdeps, 1270 deporder = rc_deptree_depends (deptree, types_n,
1271 (const char **) stopdeps,
1214 runlevel, RC_DEP_STRICT); 1272 runlevel, RC_DEP_STRICT);
1215 rc_strlist_free (stopdeps); 1273 rc_strlist_free (stopdeps);
1216 stopdeps = NULL; 1274 stopdeps = NULL;
1217 found = false; 1275 found = false;
1218 STRLIST_FOREACH (deporder, svc1, j) { 1276 STRLIST_FOREACH (deporder, svc1, j) {
1219 STRLIST_FOREACH (start_services, svc2, k) 1277 STRLIST_FOREACH (start_services, svc2, k)
1227 rc_strlist_free (deporder); 1285 rc_strlist_free (deporder);
1228 deporder = NULL; 1286 deporder = NULL;
1229 1287
1230 /* After all that we can finally stop the blighter! */ 1288 /* After all that we can finally stop the blighter! */
1231 if (! found) { 1289 if (! found) {
1232 pid_t pid = rc_stop_service (service); 1290 pid_t pid = rc_service_stop (service);
1233 if (pid > 0 && ! rc_is_env ("RC_PARALLEL", "yes")) 1291 if (pid > 0 && ! rc_env_bool ("RC_PARALLEL"))
1234 rc_waitpid (pid); 1292 wait_pid (pid);
1235 }
1236 } 1293 }
1237 rc_strlist_free (types); 1294 }
1238 types = NULL;
1239 1295
1240 /* Wait for our services to finish */ 1296 /* Wait for our services to finish */
1241 wait_for_services (); 1297 wait_for_services ();
1242 1298
1243 /* Notify the plugins we have finished */ 1299 /* Notify the plugins we have finished */
1244 rc_plugin_run (rc_hook_runlevel_stop_out, runlevel); 1300 rc_plugin_run (RC_HOOK_RUNLEVEL_STOP_OUT, runlevel);
1245 1301
1246 rmdir (RC_STOPPING); 1302 rmdir (RC_STOPPING);
1247 1303
1248 /* Store the new runlevel */ 1304 /* Store the new runlevel */
1249 if (newlevel) { 1305 if (newlevel) {
1250 rc_set_runlevel (newlevel); 1306 rc_runlevel_set (newlevel);
1307 free (runlevel);
1251 runlevel = newlevel; 1308 runlevel = xstrdup (newlevel);
1252 setenv ("RC_SOFTLEVEL", runlevel, 1); 1309 setenv ("RC_SOFTLEVEL", runlevel, 1);
1253 } 1310 }
1254 1311
1255 /* Run the halt script if needed */ 1312 /* Run the halt script if needed */
1256 if (strcmp (runlevel, RC_LEVEL_SHUTDOWN) == 0 || 1313 if (strcmp (runlevel, RC_LEVEL_SHUTDOWN) == 0 ||
1261 applet, HALTSH, strerror (errno)); 1318 applet, HALTSH, strerror (errno));
1262 } 1319 }
1263 1320
1264 /* Single user is done now */ 1321 /* Single user is done now */
1265 if (strcmp (runlevel, RC_LEVEL_SINGLE) == 0) { 1322 if (strcmp (runlevel, RC_LEVEL_SINGLE) == 0) {
1266 if (rc_exists (INTERACTIVE)) 1323 if (exists (INTERACTIVE))
1267 unlink (INTERACTIVE); 1324 unlink (INTERACTIVE);
1268 sulogin (false); 1325 sulogin (false);
1269 } 1326 }
1270 1327
1271 mkdir (RC_STARTING, 0755); 1328 mkdir (RC_STARTING, 0755);
1272 rc_plugin_run (rc_hook_runlevel_start_in, runlevel); 1329 rc_plugin_run (RC_HOOK_RUNLEVEL_START_IN, runlevel);
1273 1330
1274 /* Re-add our coldplugged services if they stopped */ 1331 /* Re-add our coldplugged services if they stopped */
1275 STRLIST_FOREACH (coldplugged_services, service, i) 1332 STRLIST_FOREACH (coldplugged_services, service, i)
1276 rc_mark_service (service, rc_service_coldplugged); 1333 rc_service_mark (service, RC_SERVICE_COLDPLUGGED);
1277 1334
1278 /* Order the services to start */ 1335 /* Order the services to start */
1279 types = rc_strlist_add (NULL, "ineed");
1280 types = rc_strlist_add (types, "iuse");
1281 types = rc_strlist_add (types, "iafter");
1282 deporder = rc_get_depends (deptree, types, start_services, 1336 deporder = rc_deptree_depends (deptree, types_nua,
1337 (const char **) start_services,
1283 runlevel, depoptions | RC_DEP_START); 1338 runlevel, depoptions | RC_DEP_START);
1284 rc_strlist_free (types);
1285 types = NULL;
1286 rc_strlist_free (start_services); 1339 rc_strlist_free (start_services);
1287 start_services = deporder; 1340 start_services = deporder;
1288 deporder = NULL; 1341 deporder = NULL;
1289 1342
1290#ifdef __linux__ 1343#ifdef __linux__
1293 if ((service = proc_getent ("noinitd"))) { 1346 if ((service = proc_getent ("noinitd"))) {
1294 char *p = service; 1347 char *p = service;
1295 char *token; 1348 char *token;
1296 1349
1297 while ((token = strsep (&p, ","))) 1350 while ((token = strsep (&p, ",")))
1298 rc_mark_service (token, rc_service_started); 1351 rc_service_mark (token, RC_SERVICE_STARTED);
1299 free (service); 1352 free (service);
1300 } 1353 }
1301 } 1354 }
1302#endif 1355#endif
1303 1356
1304 1357
1305 STRLIST_FOREACH (start_services, service, i) { 1358 STRLIST_FOREACH (start_services, service, i) {
1306 if (rc_service_state (service, rc_service_stopped)) { 1359 if (rc_service_state (service) & RC_SERVICE_STOPPED) {
1307 pid_t pid; 1360 pid_t pid;
1308 1361
1309 if (! interactive) 1362 if (! interactive)
1310 interactive = want_interactive (); 1363 interactive = want_interactive ();
1311 1364
1326 default: goto interactive_option; 1379 default: goto interactive_option;
1327 } 1380 }
1328 } 1381 }
1329 1382
1330 /* Remember the pid if we're running in parallel */ 1383 /* Remember the pid if we're running in parallel */
1331 if ((pid = rc_start_service (service))) 1384 if ((pid = rc_service_start (service)))
1332 add_pid (pid); 1385 add_pid (pid);
1333 1386
1334 if (! rc_is_env ("RC_PARALLEL", "yes")) { 1387 if (! rc_env_bool ("RC_PARALLEL")) {
1335 rc_waitpid (pid); 1388 wait_pid (pid);
1336 remove_pid (pid); 1389 remove_pid (pid);
1337 } 1390 }
1338 } 1391 }
1339 } 1392 }
1340 1393
1341 /* Wait for our services to finish */ 1394 /* Wait for our services to finish */
1342 wait_for_services (); 1395 wait_for_services ();
1343 1396
1344 rc_plugin_run (rc_hook_runlevel_start_out, runlevel); 1397 rc_plugin_run (RC_HOOK_RUNLEVEL_START_OUT, runlevel);
1345 1398
1346#ifdef __linux__ 1399#ifdef __linux__
1347 /* mark any services skipped as stopped */ 1400 /* mark any services skipped as stopped */
1348 if (PREVLEVEL && strcmp (PREVLEVEL, "N") == 0) { 1401 if (PREVLEVEL && strcmp (PREVLEVEL, "N") == 0) {
1349 if ((service = proc_getent ("noinitd"))) { 1402 if ((service = proc_getent ("noinitd"))) {
1350 char *p = service; 1403 char *p = service;
1351 char *token; 1404 char *token;
1352 1405
1353 while ((token = strsep (&p, ","))) 1406 while ((token = strsep (&p, ",")))
1354 rc_mark_service (token, rc_service_stopped); 1407 rc_service_mark (token, RC_SERVICE_STOPPED);
1355 free (service); 1408 free (service);
1356 } 1409 }
1357 } 1410 }
1358#endif 1411#endif
1359 1412
1360 /* Store our interactive status for boot */ 1413 /* Store our interactive status for boot */
1361 if (interactive && strcmp (runlevel, bootlevel) == 0) 1414 if (interactive && strcmp (runlevel, bootlevel) == 0)
1362 mark_interactive (); 1415 mark_interactive ();
1363 else { 1416 else {
1364 if (rc_exists (INTERACTIVE)) 1417 if (exists (INTERACTIVE))
1365 unlink (INTERACTIVE); 1418 unlink (INTERACTIVE);
1366 } 1419 }
1367 1420
1368 return (EXIT_SUCCESS); 1421 return (EXIT_SUCCESS);
1369} 1422}

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

  ViewVC Help
Powered by ViewVC 1.1.20