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

Diff of /trunk/src/rc.c

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

Revision 2967 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"
68static char **newenv = NULL; 70static char **newenv = NULL;
69static char **coldplugged_services = NULL; 71static char **coldplugged_services = NULL;
70static char **stop_services = NULL; 72static char **stop_services = NULL;
71static char **start_services = NULL; 73static char **start_services = NULL;
72static rc_depinfo_t *deptree = NULL; 74static rc_depinfo_t *deptree = NULL;
73static char **types = NULL;
74static char *tmp = NULL; 75static char *tmp = NULL;
75 76
76struct termios *termios_orig = NULL; 77struct termios *termios_orig = NULL;
77 78
78typedef struct pidlist 79typedef struct pidlist
79{ 80{
80 pid_t pid; 81 pid_t pid;
81 struct pidlist *next; 82 struct pidlist *next;
82} pidlist_t; 83} pidlist_t;
83static 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 };
84 88
85static void cleanup (void) 89static void cleanup (void)
86{ 90{
87 if (applet && strcmp (applet, "rc") == 0) { 91 if (applet && strcmp (applet, "rc") == 0) {
88 pidlist_t *pl = service_pids; 92 pidlist_t *pl = service_pids;
104 rc_strlist_free (newenv); 108 rc_strlist_free (newenv);
105 rc_strlist_free (coldplugged_services); 109 rc_strlist_free (coldplugged_services);
106 rc_strlist_free (stop_services); 110 rc_strlist_free (stop_services);
107 rc_strlist_free (start_services); 111 rc_strlist_free (start_services);
108 rc_deptree_free (deptree); 112 rc_deptree_free (deptree);
109 rc_strlist_free (types);
110 113
111 /* Clean runlevel start, stop markers */ 114 /* Clean runlevel start, stop markers */
112 if (! rc_in_plugin) { 115 if (! rc_in_plugin) {
113 if (rc_is_dir (RC_STARTING))
114 rc_rm_dir (RC_STARTING, true); 116 rmdir (RC_STARTING);
115 if (rc_is_dir (RC_STOPPING))
116 rc_rm_dir (RC_STOPPING, true); 117 rmdir (RC_STOPPING);
117 } 118 }
118 119
119 free (runlevel); 120 free (runlevel);
120 } 121 }
121 122
191 192
192 if (argc > 0) { 193 if (argc > 0) {
193 for (i = 0; i < argc; i++) 194 for (i = 0; i < argc; i++)
194 l += strlen (argv[i]) + 1; 195 l += strlen (argv[i]) + 1;
195 196
196 message = rc_xmalloc (l); 197 message = xmalloc (l);
197 p = message; 198 p = message;
198 199
199 for (i = 0; i < argc; i++) { 200 for (i = 0; i < argc; i++) {
200 if (i > 0) 201 if (i > 0)
201 *p++ = ' '; 202 *p++ = ' ';
204 } 205 }
205 *p = 0; 206 *p = 0;
206 } 207 }
207 208
208 if (message) 209 if (message)
209 fmt = rc_xstrdup ("%s"); 210 fmt = xstrdup ("%s");
210 211
211 if (strcmp (applet, "einfo") == 0) 212 if (strcmp (applet, "einfo") == 0)
212 einfo (fmt, message); 213 einfo (fmt, message);
213 else if (strcmp (applet, "einfon") == 0) 214 else if (strcmp (applet, "einfon") == 0)
214 einfon (fmt, message); 215 einfon (fmt, message);
315 ok = rc_service_mark (argv[0], RC_SERVICE_STOPPING); 316 ok = rc_service_mark (argv[0], RC_SERVICE_STOPPING);
316 else if (strcmp (applet, "mark_service_stopping") == 0) 317 else if (strcmp (applet, "mark_service_stopping") == 0)
317 ok = rc_service_mark (argv[0], RC_SERVICE_STOPPING); 318 ok = rc_service_mark (argv[0], RC_SERVICE_STOPPING);
318 else if (strcmp (applet, "mark_service_coldplugged") == 0) 319 else if (strcmp (applet, "mark_service_coldplugged") == 0)
319 ok = rc_service_mark (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);
320 else 323 else
321 eerrorx ("%s: unknown applet", applet); 324 eerrorx ("%s: unknown applet", applet);
322 325
323 /* 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
324 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 */
331 if (runscript_pid && sscanf (runscript_pid, "%d", &pid) == 1) 334 if (runscript_pid && sscanf (runscript_pid, "%d", &pid) == 1)
332 if (kill (pid, SIGHUP) != 0) 335 if (kill (pid, SIGHUP) != 0)
333 eerror ("%s: failed to signal parent %d: %s", 336 eerror ("%s: failed to signal parent %d: %s",
334 applet, pid, strerror (errno)); 337 applet, pid, strerror (errno));
335 338
336 /* Remove the exclsive time test. This ensures that it's not 339 /* Remove the exclusive time test. This ensures that it's not
337 in control as well */ 340 in control as well */
338 l = strlen (RC_SVCDIR "exclusive") + 341 l = strlen (RC_SVCDIR "exclusive") +
339 strlen (svcname) + 342 strlen (svcname) +
340 strlen (runscript_pid) + 343 strlen (runscript_pid) +
341 4; 344 4;
342 mtime = rc_xmalloc (l); 345 mtime = xmalloc (l);
343 snprintf (mtime, l, RC_SVCDIR "exclusive/%s.%s", 346 snprintf (mtime, l, RC_SVCDIR "exclusive/%s.%s",
344 svcname, runscript_pid); 347 svcname, runscript_pid);
345 if (rc_exists (mtime) && unlink (mtime) != 0) 348 if (exists (mtime) && unlink (mtime) != 0)
346 eerror ("%s: unlink: %s", applet, strerror (errno)); 349 eerror ("%s: unlink: %s", applet, strerror (errno));
347 free (mtime); 350 free (mtime);
348 } 351 }
349 352
350 return (ok ? EXIT_SUCCESS : EXIT_FAILURE); 353 return (ok ? EXIT_SUCCESS : EXIT_FAILURE);
360 363
361 if (argc < 1 || ! argv[0] || strlen (argv[0]) == 0) 364 if (argc < 1 || ! argv[0] || strlen (argv[0]) == 0)
362 eerrorx ("%s: no option specified", applet); 365 eerrorx ("%s: no option specified", applet);
363 366
364 if (strcmp (applet, "get_options") == 0) { 367 if (strcmp (applet, "get_options") == 0) {
365 char *option = rc_service_option_get (service, argv[0]); 368 char *option = rc_service_value_get (service, argv[0]);
366 if (option) { 369 if (option) {
367 printf ("%s", option); 370 printf ("%s", option);
368 free (option); 371 free (option);
369 ok = true; 372 ok = true;
370 } 373 }
371 } else if (strcmp (applet, "save_options") == 0) 374 } else if (strcmp (applet, "save_options") == 0)
372 ok = rc_service_option_set (service, argv[0], argv[1]); 375 ok = rc_service_value_set (service, argv[0], argv[1]);
373 else 376 else
374 eerrorx ("%s: unknown applet", applet); 377 eerrorx ("%s: unknown applet", applet);
375 378
376 return (ok ? EXIT_SUCCESS : EXIT_FAILURE); 379 return (ok ? EXIT_SUCCESS : EXIT_FAILURE);
377} 380}
378 381
379#ifdef __linux__ 382#ifdef __linux__
380static char *proc_getent (const char *ent) 383static char *proc_getent (const char *ent)
381{ 384{
382 FILE *fp; 385 FILE *fp;
383 char buffer[RC_LINEBUFFER]; 386 char *buffer;
384 char *p; 387 char *p;
385 char *value = NULL; 388 char *value = NULL;
386 int i; 389 int i;
387 390
388 if (! rc_exists ("/proc/cmdline")) 391 if (! exists ("/proc/cmdline"))
389 return (NULL); 392 return (NULL);
390 393
391 if (! (fp = fopen ("/proc/cmdline", "r"))) { 394 if (! (fp = fopen ("/proc/cmdline", "r"))) {
392 eerror ("failed to open `/proc/cmdline': %s", strerror (errno)); 395 eerror ("failed to open `/proc/cmdline': %s", strerror (errno));
393 return (NULL); 396 return (NULL);
394 } 397 }
395 398
396 memset (buffer, 0, sizeof (buffer)); 399 buffer = xmalloc (sizeof (char) * RC_LINEBUFFER);
400 memset (buffer, 0, RC_LINEBUFFER);
397 if (fgets (buffer, RC_LINEBUFFER, fp) && 401 if (fgets (buffer, RC_LINEBUFFER, fp) &&
398 (p = strstr (buffer, ent))) 402 (p = strstr (buffer, ent)))
399 { 403 {
400 i = p - buffer; 404 i = p - buffer;
401 if (i == '\0' || buffer[i - 1] == ' ') { 405 if (i == '\0' || buffer[i - 1] == ' ') {
405 buffer[i] = 0; 409 buffer[i] = 0;
406 410
407 p += strlen (ent); 411 p += strlen (ent);
408 if (*p == '=') 412 if (*p == '=')
409 p++; 413 p++;
410 value = strdup (strsep (&p, " ")); 414 value = xstrdup (strsep (&p, " "));
411 } 415 }
412 } else 416 } else
413 errno = ENOENT; 417 errno = ENOENT;
418 free (buffer);
414 fclose (fp); 419 fclose (fp);
415 420
416 return (value); 421 return (value);
417} 422}
418#endif 423#endif
420static char read_key (bool block) 425static char read_key (bool block)
421{ 426{
422 struct termios termios; 427 struct termios termios;
423 char c = 0; 428 char c = 0;
424 int fd = fileno (stdin); 429 int fd = fileno (stdin);
425 430
426 if (! isatty (fd)) 431 if (! isatty (fd))
427 return (false); 432 return (false);
428 433
429 /* 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
430 will be changing it for non-blocking reads for Interactive */ 435 will be changing it for non-blocking reads for Interactive */
431 if (! termios_orig) { 436 if (! termios_orig) {
432 termios_orig = rc_xmalloc (sizeof (struct termios)); 437 termios_orig = xmalloc (sizeof (struct termios));
433 tcgetattr (fd, termios_orig); 438 tcgetattr (fd, termios_orig);
434 } 439 }
435 440
436 tcgetattr (fd, &termios); 441 tcgetattr (fd, &termios);
437 termios.c_lflag &= ~(ICANON | ECHO); 442 termios.c_lflag &= ~(ICANON | ECHO);
484 execl ("/sbin/halt", "/sbin/halt", "-f", (char *) NULL); 489 execl ("/sbin/halt", "/sbin/halt", "-f", (char *) NULL);
485 eerrorx ("%s: unable to exec `/sbin/halt': %s", applet, strerror (errno)); 490 eerrorx ("%s: unable to exec `/sbin/halt': %s", applet, strerror (errno));
486 } 491 }
487#endif 492#endif
488 493
489 newenv = rc_filter_env (); 494 newenv = env_filter ();
490 495
491 if (cont) { 496 if (cont) {
492 int status = 0; 497 int status = 0;
493#ifdef __linux__ 498#ifdef __linux__
494 char *tty = ttyname (fileno (stdout)); 499 char *tty = ttyname (fileno (stdout));
546 if (! level || 551 if (! level ||
547 strcmp (level, getenv ("RC_BOOTLEVEL")) == 0 || 552 strcmp (level, getenv ("RC_BOOTLEVEL")) == 0 ||
548 strcmp (level, RC_LEVEL_SINGLE) == 0 || 553 strcmp (level, RC_LEVEL_SINGLE) == 0 ||
549 strcmp (level, RC_LEVEL_SYSINIT) == 0) 554 strcmp (level, RC_LEVEL_SYSINIT) == 0)
550 { 555 {
551 if (rc_exists (RC_KSOFTLEVEL) && 556 if (exists (RC_KSOFTLEVEL) &&
552 unlink (RC_KSOFTLEVEL) != 0) 557 unlink (RC_KSOFTLEVEL) != 0)
553 eerror ("unlink `%s': %s", RC_KSOFTLEVEL, strerror (errno)); 558 eerror ("unlink `%s': %s", RC_KSOFTLEVEL, strerror (errno));
554 return; 559 return;
555 } 560 }
556 561
566static int get_ksoftlevel (char *buffer, int buffer_len) 571static int get_ksoftlevel (char *buffer, int buffer_len)
567{ 572{
568 FILE *fp; 573 FILE *fp;
569 int i = 0; 574 int i = 0;
570 575
571 if (! rc_exists (RC_KSOFTLEVEL)) 576 if (! exists (RC_KSOFTLEVEL))
572 return (0); 577 return (0);
573 578
574 if (! (fp = fopen (RC_KSOFTLEVEL, "r"))) { 579 if (! (fp = fopen (RC_KSOFTLEVEL, "r"))) {
575 eerror ("fopen `%s': %s", RC_KSOFTLEVEL, strerror (errno)); 580 eerror ("fopen `%s': %s", RC_KSOFTLEVEL, strerror (errno));
576 return (-1); 581 return (-1);
596{ 601{
597 pidlist_t *sp = service_pids; 602 pidlist_t *sp = service_pids;
598 if (sp) { 603 if (sp) {
599 while (sp->next) 604 while (sp->next)
600 sp = sp->next; 605 sp = sp->next;
601 sp->next = rc_xmalloc (sizeof (pidlist_t)); 606 sp->next = xmalloc (sizeof (pidlist_t));
602 sp = sp->next; 607 sp = sp->next;
603 } else 608 } else
604 sp = service_pids = rc_xmalloc (sizeof (pidlist_t)); 609 sp = service_pids = xmalloc (sizeof (pidlist_t));
605 memset (sp, 0, sizeof (pidlist_t)); 610 memset (sp, 0, sizeof (pidlist_t));
606 sp->pid = pid; 611 sp->pid = pid;
607} 612}
608 613
609static void remove_pid (pid_t pid) 614static void remove_pid (pid_t pid)
620 free (pl); 625 free (pl);
621 break; 626 break;
622 } 627 }
623 last = pl; 628 last = pl;
624 } 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);
625} 645}
626 646
627static void handle_signal (int sig) 647static void handle_signal (int sig)
628{ 648{
629 int serrno = errno; 649 int serrno = errno;
714 734
715#include "_usage.h" 735#include "_usage.h"
716#define getoptstring getoptstring_COMMON 736#define getoptstring getoptstring_COMMON
717static struct option longopts[] = { 737static struct option longopts[] = {
718 longopts_COMMON 738 longopts_COMMON
719 { NULL, 0, NULL, 0}
720}; 739};
721static const char * const longopts_help[] = { 740static const char * const longopts_help[] = {
722 longopts_help_COMMON 741 longopts_help_COMMON
723}; 742};
724#include "_usage.c" 743#include "_usage.c"
736 bool interactive = false; 755 bool interactive = false;
737 int depoptions = RC_DEP_STRICT | RC_DEP_TRACE; 756 int depoptions = RC_DEP_STRICT | RC_DEP_TRACE;
738 char ksoftbuffer [PATH_MAX]; 757 char ksoftbuffer [PATH_MAX];
739 char pidstr[6]; 758 char pidstr[6];
740 int opt; 759 int opt;
760 DIR *dp;
761 struct dirent *d;
741 762
742 atexit (cleanup); 763 atexit (cleanup);
743 if (argv[0]) 764 if (argv[0])
744 applet = rc_xstrdup (basename (argv[0])); 765 applet = xstrdup (basename (argv[0]));
745 766
746 if (! applet) 767 if (! applet)
747 eerrorx ("arguments required"); 768 eerrorx ("arguments required");
748 769
749 /* 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
821 signal (SIGTERM, handle_signal); 842 signal (SIGTERM, handle_signal);
822 signal (SIGUSR1, handle_signal); 843 signal (SIGUSR1, handle_signal);
823 844
824 /* Ensure our environment is pure 845 /* Ensure our environment is pure
825 Also, add our configuration to it */ 846 Also, add our configuration to it */
826 env = rc_filter_env (); 847 env = env_filter ();
827 tmplist = rc_make_env (); 848 tmplist = env_config ();
828 rc_strlist_join (&env, tmplist); 849 rc_strlist_join (&env, tmplist);
829 rc_strlist_free (tmplist); 850 rc_strlist_free (tmplist);
830 851
831 if (env) { 852 if (env) {
832 char *p; 853 char *p;
840 /* No clearenv present here then. 861 /* No clearenv present here then.
841 We could manipulate environ directly ourselves, but it seems that 862 We could manipulate environ directly ourselves, but it seems that
842 some kernels bitch about this according to the environ man pages 863 some kernels bitch about this according to the environ man pages
843 so we walk though environ and call unsetenv for each value. */ 864 so we walk though environ and call unsetenv for each value. */
844 while (environ[0]) { 865 while (environ[0]) {
845 tmp = rc_xstrdup (environ[0]); 866 tmp = xstrdup (environ[0]);
846 p = tmp; 867 p = tmp;
847 var = strsep (&p, "="); 868 var = strsep (&p, "=");
848 unsetenv (var); 869 unsetenv (var);
849 free (tmp); 870 free (tmp);
850 } 871 }
880 901
881 /* Export our PID */ 902 /* Export our PID */
882 snprintf (pidstr, sizeof (pidstr), "%d", getpid ()); 903 snprintf (pidstr, sizeof (pidstr), "%d", getpid ());
883 setenv ("RC_PID", pidstr, 1); 904 setenv ("RC_PID", pidstr, 1);
884 905
885 interactive = rc_exists (INTERACTIVE); 906 interactive = exists (INTERACTIVE);
886 rc_plugin_load (); 907 rc_plugin_load ();
887 908
888 /* Load current softlevel */ 909 /* Load current softlevel */
889 bootlevel = getenv ("RC_BOOTLEVEL"); 910 bootlevel = getenv ("RC_BOOTLEVEL");
890 runlevel = rc_runlevel_get (); 911 runlevel = rc_runlevel_get ();
907#endif 928#endif
908 929
909 /* exec init-early.sh if it exists 930 /* exec init-early.sh if it exists
910 * This should just setup the console to use the correct 931 * This should just setup the console to use the correct
911 * font. Maybe it should setup the keyboard too? */ 932 * font. Maybe it should setup the keyboard too? */
912 if (rc_exists (INITEARLYSH)) 933 if (exists (INITEARLYSH))
913 run_script (INITEARLYSH); 934 run_script (INITEARLYSH);
914 935
915 uname (&uts); 936 uname (&uts);
916 937
917 printf ("\n"); 938 printf ("\n");
1014 rc_plugin_run (RC_HOOK_RUNLEVEL_STOP_IN, runlevel); 1035 rc_plugin_run (RC_HOOK_RUNLEVEL_STOP_IN, runlevel);
1015 } 1036 }
1016 1037
1017 /* Check if runlevel is valid if we're changing */ 1038 /* Check if runlevel is valid if we're changing */
1018 if (newlevel && strcmp (runlevel, newlevel) != 0 && ! going_down) { 1039 if (newlevel && strcmp (runlevel, newlevel) != 0 && ! going_down) {
1019 tmp = rc_strcatpaths (RC_RUNLEVELDIR, newlevel, (char *) NULL); 1040 if (! rc_runlevel_exists (newlevel))
1020 if (! rc_is_dir (tmp))
1021 eerrorx ("%s: is not a valid runlevel", newlevel); 1041 eerrorx ("%s: is not a valid runlevel", newlevel);
1022 CHAR_FREE (tmp);
1023 } 1042 }
1024 1043
1025 /* Load our deptree now */ 1044 /* Load our deptree now */
1026 if ((deptree = _rc_deptree_load ()) == NULL) 1045 if ((deptree = _rc_deptree_load ()) == NULL)
1027 eerrorx ("failed to load deptree"); 1046 eerrorx ("failed to load deptree");
1028 1047
1029 /* Clean the failed services state dir now */ 1048 /* Clean the failed services state dir now */
1030 if (rc_is_dir (RC_SVCDIR "/failed")) 1049 if ((dp = opendir (RC_SVCDIR "/failed"))) {
1031 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 }
1032 1066
1033 mkdir (RC_STOPPING, 0755); 1067 mkdir (RC_STOPPING, 0755);
1034 1068
1035#ifdef __linux__ 1069#ifdef __linux__
1036 /* 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
1037 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
1038 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
1039 here when we are ready for them */ 1073 here when we are ready for them */
1040 if (rc_is_dir (DEVBOOT)) { 1074 if ((dp = opendir (DEVBOOT))) {
1041 start_services = rc_ls_dir (DEVBOOT, RC_LS_INITD); 1075 while ((d = readdir (dp))) {
1042 rc_rm_dir (DEVBOOT, true); 1076 if (d->d_name[0] == '.' &&
1077 (d->d_name[1] == '\0' ||
1078 (d->d_name[1] == '.' && d->d_name[2] == '\0')))
1079 continue;
1043 1080
1044 STRLIST_FOREACH (start_services, service, i) 1081 if (rc_service_exists (d->d_name) &&
1045 if (rc_service_plugable (service)) 1082 rc_service_plugable (d->d_name))
1046 rc_service_mark (service, RC_SERVICE_COLDPLUGGED); 1083 rc_service_mark (d->d_name, RC_SERVICE_COLDPLUGGED);
1047 /* We need to dump this list now. 1084
1048 This may seem redunant, but only Linux needs this and saves on 1085 asprintf (&tmp, DEVBOOT "/%s", d->d_name);
1049 code bloat. */ 1086 if (tmp) {
1050 rc_strlist_free (start_services); 1087 if (unlink (tmp))
1051 start_services = NULL; 1088 eerror ("%s: unlink `%s': %s", applet, tmp,
1089 strerror (errno));
1090 free (tmp);
1091 }
1092 }
1093 closedir (dp);
1094 rmdir (DEVBOOT);
1052 } 1095 }
1053#else 1096#else
1054 /* 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.
1055 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
1056 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
1060 strcmp (runlevel, RC_LEVEL_SYSINIT) == 0) && 1103 strcmp (runlevel, RC_LEVEL_SYSINIT) == 0) &&
1061 rc_env_bool ("RC_COLDPLUG")) 1104 rc_env_bool ("RC_COLDPLUG"))
1062 { 1105 {
1063#if defined(__DragonFly__) || defined(__FreeBSD__) 1106#if defined(__DragonFly__) || defined(__FreeBSD__)
1064 /* 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 :) */
1065 start_services = rc_ls_dir ("/dev/net", 0); 1108 if ((dp = opendir ("/dev/net"))) {
1066 STRLIST_FOREACH (start_services, service, i) { 1109 while ((d = readdir (dp))) {
1067 j = (strlen ("net.") + strlen (service) + 1); 1110 i = (strlen ("net.") + strlen (d->d_name) + 1);
1068 tmp = rc_xmalloc (sizeof (char *) * j); 1111 tmp = xmalloc (sizeof (char) * i);
1069 snprintf (tmp, j, "net.%s", service); 1112 snprintf (tmp, i, "net.%s", d->d_name);
1070 if (rc_service_exists (tmp) && rc_service_plugable (tmp)) 1113 if (rc_service_exists (tmp) &&
1114 rc_service_plugable (tmp))
1071 rc_service_mark (tmp, RC_SERVICE_COLDPLUGGED); 1115 rc_service_mark (tmp, RC_SERVICE_COLDPLUGGED);
1072 CHAR_FREE (tmp); 1116 CHAR_FREE (tmp);
1073 } 1117 }
1074 rc_strlist_free (start_services); 1118 closedir (dp);
1119 }
1075#endif 1120#endif
1076 1121
1077 /* The mice are a little more tricky. 1122 /* The mice are a little more tricky.
1078 If we coldplug anything else, we'll probably do it here. */ 1123 If we coldplug anything else, we'll probably do it here. */
1079 start_services = rc_ls_dir ("/dev", 0); 1124 if ((dp == opendir ("/dev"))) {
1080 STRLIST_FOREACH (start_services, service, i) { 1125 while ((d = readdir (dp))) {
1081 if (strncmp (service, "psm", 3) == 0 || 1126 if (strncmp (d->d_name, "psm", 3) == 0 ||
1082 strncmp (service, "ums", 3) == 0) 1127 strncmp (d->d_name, "ums", 3) == 0)
1083 { 1128 {
1084 char *p = service + 3; 1129 char *p = d->d_name + 3;
1085 if (p && isdigit (*p)) { 1130 if (p && isdigit (*p)) {
1086 j = (strlen ("moused.") + strlen (service) + 1); 1131 i = (strlen ("moused.") + strlen (d->d_name) + 1);
1087 tmp = rc_xmalloc (sizeof (char *) * j); 1132 tmp = xmalloc (sizeof (char) * i);
1088 snprintf (tmp, j, "moused.%s", service); 1133 snprintf (tmp, i, "moused.%s", d->d_name);
1089 if (rc_service_exists (tmp) && rc_allow_plug (tmp)) 1134 if (rc_service_exists (tmp) && rc_service_plugable (tmp))
1090 rc_service_mark (tmp, RC_SERVICE_COLDPLUGGED); 1135 rc_service_mark (tmp, RC_SERVICE_COLDPLUGGED);
1091 CHAR_FREE (tmp); 1136 CHAR_FREE (tmp);
1137 }
1092 } 1138 }
1093 } 1139 }
1140 closedir (dp);
1094 } 1141 }
1095 rc_strlist_free (start_services);
1096 start_services = NULL;
1097 } 1142 }
1098#endif 1143#endif
1099 1144
1100 /* 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
1101 correct order for stopping them */ 1146 correct order for stopping them */
1102 stop_services = rc_ls_dir (RC_SVCDIR_STARTING, RC_LS_INITD); 1147 stop_services = rc_services_in_state (RC_SERVICE_STARTING);
1103 1148
1104 tmplist = rc_ls_dir (RC_SVCDIR_INACTIVE, RC_LS_INITD); 1149 tmplist = rc_services_in_state (RC_SERVICE_INACTIVE);
1105 rc_strlist_join (&stop_services, tmplist); 1150 rc_strlist_join (&stop_services, tmplist);
1106 rc_strlist_free (tmplist); 1151 rc_strlist_free (tmplist);
1107 1152
1108 tmplist = rc_ls_dir (RC_SVCDIR_STARTED, RC_LS_INITD); 1153 tmplist = rc_services_in_state (RC_SERVICE_STARTED);
1109 rc_strlist_join (&stop_services, tmplist); 1154 rc_strlist_join (&stop_services, tmplist);
1110 rc_strlist_free (tmplist); 1155 rc_strlist_free (tmplist);
1111 1156
1112 types = NULL;
1113 rc_strlist_add (&types, "ineed");
1114 rc_strlist_add (&types, "iuse");
1115 rc_strlist_add (&types, "iafter");
1116
1117 deporder = rc_deptree_depends (deptree, types, stop_services, 1157 deporder = rc_deptree_depends (deptree, types_nua,
1158 (const char **) stop_services,
1118 runlevel, depoptions | RC_DEP_STOP); 1159 runlevel, depoptions | RC_DEP_STOP);
1119 1160
1120 rc_strlist_free (stop_services); 1161 rc_strlist_free (stop_services);
1121 rc_strlist_free (types);
1122 types = NULL;
1123 stop_services = deporder; 1162 stop_services = deporder;
1124 deporder = NULL; 1163 deporder = NULL;
1125 rc_strlist_reverse (stop_services); 1164 rc_strlist_reverse (stop_services);
1126 1165
1127 /* Load our list of coldplugged services */ 1166 /* Load our list of coldplugged services */
1128 coldplugged_services = rc_ls_dir (RC_SVCDIR_COLDPLUGGED, RC_LS_INITD); 1167 coldplugged_services = rc_services_in_state (RC_SERVICE_COLDPLUGGED);
1129 1168
1130 /* Load our start services now. 1169 /* Load our start services now.
1131 We have different rules dependent on runlevel. */ 1170 We have different rules dependent on runlevel. */
1132 if (newlevel && strcmp (newlevel, bootlevel) == 0) { 1171 if (newlevel && strcmp (newlevel, bootlevel) == 0) {
1133 if (coldplugged_services) { 1172 if (coldplugged_services) {
1136 printf (" %s", service); 1175 printf (" %s", service);
1137 rc_strlist_add (&start_services, service); 1176 rc_strlist_add (&start_services, service);
1138 } 1177 }
1139 printf ("\n"); 1178 printf ("\n");
1140 } 1179 }
1141 tmp = rc_strcatpaths (RC_RUNLEVELDIR, newlevel ? newlevel : runlevel, 1180 tmplist = rc_services_in_runlevel (newlevel ? newlevel : runlevel);
1142 (char *) NULL);
1143 tmplist = rc_ls_dir (tmp, RC_LS_INITD);
1144 rc_strlist_join (&start_services, tmplist); 1181 rc_strlist_join (&start_services, tmplist);
1145 rc_strlist_free (tmplist); 1182 rc_strlist_free (tmplist);
1146 CHAR_FREE (tmp);
1147 } else { 1183 } else {
1148 /* Store our list of coldplugged services */ 1184 /* Store our list of coldplugged services */
1149 tmplist = rc_ls_dir (RC_SVCDIR_COLDPLUGGED, RC_LS_INITD); 1185 tmplist = rc_services_in_state (RC_SERVICE_COLDPLUGGED);
1150 rc_strlist_join (&coldplugged_services, tmplist); 1186 rc_strlist_join (&coldplugged_services, tmplist);
1151 rc_strlist_free (tmplist); 1187 rc_strlist_free (tmplist);
1152 if (strcmp (newlevel ? newlevel : runlevel, RC_LEVEL_SINGLE) != 0 && 1188 if (strcmp (newlevel ? newlevel : runlevel, RC_LEVEL_SINGLE) != 0 &&
1153 strcmp (newlevel ? newlevel : runlevel, RC_LEVEL_SHUTDOWN) != 0 && 1189 strcmp (newlevel ? newlevel : runlevel, RC_LEVEL_SHUTDOWN) != 0 &&
1154 strcmp (newlevel ? newlevel : runlevel, RC_LEVEL_REBOOT) != 0) 1190 strcmp (newlevel ? newlevel : runlevel, RC_LEVEL_REBOOT) != 0)
1158 rc_strlist_join (&start_services, tmplist); 1194 rc_strlist_join (&start_services, tmplist);
1159 rc_strlist_free (tmplist); 1195 rc_strlist_free (tmplist);
1160 tmplist = rc_services_in_runlevel (newlevel ? newlevel : runlevel); 1196 tmplist = rc_services_in_runlevel (newlevel ? newlevel : runlevel);
1161 rc_strlist_join (&start_services, tmplist); 1197 rc_strlist_join (&start_services, tmplist);
1162 rc_strlist_free (tmplist); 1198 rc_strlist_free (tmplist);
1163 1199
1164 STRLIST_FOREACH (coldplugged_services, service, i) 1200 STRLIST_FOREACH (coldplugged_services, service, i)
1165 rc_strlist_add (&start_services, service); 1201 rc_strlist_add (&start_services, service);
1166 1202
1167 } 1203 }
1168 } 1204 }
1169 1205
1170 /* Save out softlevel now */ 1206 /* Save out softlevel now */
1171 if (going_down) 1207 if (going_down)
1172 rc_runlevel_set (newlevel); 1208 rc_runlevel_set (newlevel);
1173 1209
1174 types = NULL;
1175 rc_strlist_add (&types, "needsme");
1176 /* Now stop the services that shouldn't be running */ 1210 /* Now stop the services that shouldn't be running */
1177 STRLIST_FOREACH (stop_services, service, i) { 1211 STRLIST_FOREACH (stop_services, service, i) {
1178 bool found = false; 1212 bool found = false;
1179 char *conf = NULL; 1213 char *conf = NULL;
1180 char **stopdeps = NULL; 1214 char **stopdeps = NULL;
1187 1221
1188 /* We always stop the service when in these runlevels */ 1222 /* We always stop the service when in these runlevels */
1189 if (going_down) { 1223 if (going_down) {
1190 pid_t pid = rc_service_stop (service); 1224 pid_t pid = rc_service_stop (service);
1191 if (pid > 0 && ! rc_env_bool ("RC_PARALLEL")) 1225 if (pid > 0 && ! rc_env_bool ("RC_PARALLEL"))
1192 rc_waitpid (pid); 1226 wait_pid (pid);
1193 continue; 1227 continue;
1194 } 1228 }
1195 1229
1196 /* 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 */
1197 STRLIST_FOREACH (start_services, svc1, j) 1231 STRLIST_FOREACH (start_services, svc1, j)
1205 int len; 1239 int len;
1206 if (! newlevel) 1240 if (! newlevel)
1207 continue; 1241 continue;
1208 1242
1209 len = strlen (service) + strlen (runlevel) + 2; 1243 len = strlen (service) + strlen (runlevel) + 2;
1210 tmp = rc_xmalloc (sizeof (char *) * len); 1244 tmp = xmalloc (sizeof (char) * len);
1211 snprintf (tmp, len, "%s.%s", service, runlevel); 1245 snprintf (tmp, len, "%s.%s", service, runlevel);
1212 conf = rc_strcatpaths (RC_CONFDIR, tmp, (char *) NULL); 1246 conf = rc_strcatpaths (RC_CONFDIR, tmp, (char *) NULL);
1213 found = rc_exists (conf); 1247 found = exists (conf);
1214 CHAR_FREE (conf); 1248 CHAR_FREE (conf);
1215 CHAR_FREE (tmp); 1249 CHAR_FREE (tmp);
1216 if (! found) { 1250 if (! found) {
1217 len = strlen (service) + strlen (newlevel) + 2; 1251 len = strlen (service) + strlen (newlevel) + 2;
1218 tmp = rc_xmalloc (sizeof (char *) * len); 1252 tmp = xmalloc (sizeof (char) * len);
1219 snprintf (tmp, len, "%s.%s", service, newlevel); 1253 snprintf (tmp, len, "%s.%s", service, newlevel);
1220 conf = rc_strcatpaths (RC_CONFDIR, tmp, (char *) NULL); 1254 conf = rc_strcatpaths (RC_CONFDIR, tmp, (char *) NULL);
1221 found = rc_exists (conf); 1255 found = exists (conf);
1222 CHAR_FREE (conf); 1256 CHAR_FREE (conf);
1223 CHAR_FREE (tmp); 1257 CHAR_FREE (tmp);
1224 if (!found) 1258 if (!found)
1225 continue; 1259 continue;
1226 } 1260 }
1231 } 1265 }
1232 1266
1233 /* 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
1234 going to be started depends on us */ 1268 going to be started depends on us */
1235 rc_strlist_add (&stopdeps, service); 1269 rc_strlist_add (&stopdeps, service);
1236 deporder = rc_deptree_depends (deptree, types, stopdeps, 1270 deporder = rc_deptree_depends (deptree, types_n,
1271 (const char **) stopdeps,
1237 runlevel, RC_DEP_STRICT); 1272 runlevel, RC_DEP_STRICT);
1238 rc_strlist_free (stopdeps); 1273 rc_strlist_free (stopdeps);
1239 stopdeps = NULL; 1274 stopdeps = NULL;
1240 found = false; 1275 found = false;
1241 STRLIST_FOREACH (deporder, svc1, j) { 1276 STRLIST_FOREACH (deporder, svc1, j) {
1242 STRLIST_FOREACH (start_services, svc2, k) 1277 STRLIST_FOREACH (start_services, svc2, k)
1252 1287
1253 /* After all that we can finally stop the blighter! */ 1288 /* After all that we can finally stop the blighter! */
1254 if (! found) { 1289 if (! found) {
1255 pid_t pid = rc_service_stop (service); 1290 pid_t pid = rc_service_stop (service);
1256 if (pid > 0 && ! rc_env_bool ("RC_PARALLEL")) 1291 if (pid > 0 && ! rc_env_bool ("RC_PARALLEL"))
1257 rc_waitpid (pid); 1292 wait_pid (pid);
1258 }
1259 } 1293 }
1260 rc_strlist_free (types); 1294 }
1261 types = NULL;
1262 1295
1263 /* Wait for our services to finish */ 1296 /* Wait for our services to finish */
1264 wait_for_services (); 1297 wait_for_services ();
1265 1298
1266 /* Notify the plugins we have finished */ 1299 /* Notify the plugins we have finished */
1270 1303
1271 /* Store the new runlevel */ 1304 /* Store the new runlevel */
1272 if (newlevel) { 1305 if (newlevel) {
1273 rc_runlevel_set (newlevel); 1306 rc_runlevel_set (newlevel);
1274 free (runlevel); 1307 free (runlevel);
1275 runlevel = rc_xstrdup (newlevel); 1308 runlevel = xstrdup (newlevel);
1276 setenv ("RC_SOFTLEVEL", runlevel, 1); 1309 setenv ("RC_SOFTLEVEL", runlevel, 1);
1277 } 1310 }
1278 1311
1279 /* Run the halt script if needed */ 1312 /* Run the halt script if needed */
1280 if (strcmp (runlevel, RC_LEVEL_SHUTDOWN) == 0 || 1313 if (strcmp (runlevel, RC_LEVEL_SHUTDOWN) == 0 ||
1285 applet, HALTSH, strerror (errno)); 1318 applet, HALTSH, strerror (errno));
1286 } 1319 }
1287 1320
1288 /* Single user is done now */ 1321 /* Single user is done now */
1289 if (strcmp (runlevel, RC_LEVEL_SINGLE) == 0) { 1322 if (strcmp (runlevel, RC_LEVEL_SINGLE) == 0) {
1290 if (rc_exists (INTERACTIVE)) 1323 if (exists (INTERACTIVE))
1291 unlink (INTERACTIVE); 1324 unlink (INTERACTIVE);
1292 sulogin (false); 1325 sulogin (false);
1293 } 1326 }
1294 1327
1295 mkdir (RC_STARTING, 0755); 1328 mkdir (RC_STARTING, 0755);
1298 /* Re-add our coldplugged services if they stopped */ 1331 /* Re-add our coldplugged services if they stopped */
1299 STRLIST_FOREACH (coldplugged_services, service, i) 1332 STRLIST_FOREACH (coldplugged_services, service, i)
1300 rc_service_mark (service, RC_SERVICE_COLDPLUGGED); 1333 rc_service_mark (service, RC_SERVICE_COLDPLUGGED);
1301 1334
1302 /* Order the services to start */ 1335 /* Order the services to start */
1303 rc_strlist_add (&types, "ineed");
1304 rc_strlist_add (&types, "iuse");
1305 rc_strlist_add (&types, "iafter");
1306 deporder = rc_deptree_depends (deptree, types, start_services, 1336 deporder = rc_deptree_depends (deptree, types_nua,
1337 (const char **) start_services,
1307 runlevel, depoptions | RC_DEP_START); 1338 runlevel, depoptions | RC_DEP_START);
1308 rc_strlist_free (types);
1309 types = NULL;
1310 rc_strlist_free (start_services); 1339 rc_strlist_free (start_services);
1311 start_services = deporder; 1340 start_services = deporder;
1312 deporder = NULL; 1341 deporder = NULL;
1313 1342
1314#ifdef __linux__ 1343#ifdef __linux__
1354 /* Remember the pid if we're running in parallel */ 1383 /* Remember the pid if we're running in parallel */
1355 if ((pid = rc_service_start (service))) 1384 if ((pid = rc_service_start (service)))
1356 add_pid (pid); 1385 add_pid (pid);
1357 1386
1358 if (! rc_env_bool ("RC_PARALLEL")) { 1387 if (! rc_env_bool ("RC_PARALLEL")) {
1359 rc_waitpid (pid); 1388 wait_pid (pid);
1360 remove_pid (pid); 1389 remove_pid (pid);
1361 } 1390 }
1362 } 1391 }
1363 } 1392 }
1364 1393
1383 1412
1384 /* Store our interactive status for boot */ 1413 /* Store our interactive status for boot */
1385 if (interactive && strcmp (runlevel, bootlevel) == 0) 1414 if (interactive && strcmp (runlevel, bootlevel) == 0)
1386 mark_interactive (); 1415 mark_interactive ();
1387 else { 1416 else {
1388 if (rc_exists (INTERACTIVE)) 1417 if (exists (INTERACTIVE))
1389 unlink (INTERACTIVE); 1418 unlink (INTERACTIVE);
1390 } 1419 }
1391 1420
1392 return (EXIT_SUCCESS); 1421 return (EXIT_SUCCESS);
1393} 1422}

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

  ViewVC Help
Powered by ViewVC 1.1.20