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

Diff of /trunk/src/rc.c

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

Revision 2564 Revision 2569
4 and the running of daemons on a Gentoo system. 4 and the running of daemons on a Gentoo system.
5 5
6 Also a multicall binary for various commands that can be used in shell 6 Also a multicall binary for various commands that can be used in shell
7 scripts to query service state, mark service state and provide the 7 scripts to query service state, mark service state and provide the
8 Gentoo einfo family of informational functions. 8 Gentoo einfo family of informational functions.
9 9
10 Copyright 2007 Gentoo Foundation 10 Copyright 2007 Gentoo Foundation
11 Released under the GPLv2 11 Released under the GPLv2
12 */ 12 */
13 13
14#include <sys/types.h> 14#include <sys/types.h>
121 strcmp (applet, "ewend") == 0 || 121 strcmp (applet, "ewend") == 0 ||
122 strcmp (applet, "veend") == 0 || 122 strcmp (applet, "veend") == 0 ||
123 strcmp (applet, "vweend") == 0) 123 strcmp (applet, "vweend") == 0)
124 { 124 {
125 if (argc > 0) 125 if (argc > 0)
126 { 126 {
127 errno = 0; 127 errno = 0;
128 retval = strtol (argv[0], NULL, 0); 128 retval = strtol (argv[0], NULL, 0);
129 if (errno != 0) 129 if (errno != 0)
130 retval = EXIT_FAILURE; 130 retval = EXIT_FAILURE;
131 else 131 else
132 { 132 {
133 argc--; 133 argc--;
134 argv++; 134 argv++;
135 } 135 }
136 } 136 }
137 else 137 else
138 retval = EXIT_FAILURE; 138 retval = EXIT_FAILURE;
139 } 139 }
140 140
141 if (argc > 0) 141 if (argc > 0)
142 { 142 {
143 for (i = 0; i < argc; i++) 143 for (i = 0; i < argc; i++)
144 l += strlen (argv[i]) + 1; 144 l += strlen (argv[i]) + 1;
145 145
146 message = rc_xmalloc (l); 146 message = rc_xmalloc (l);
147 p = message; 147 p = message;
148 148
149 for (i = 0; i < argc; i++) 149 for (i = 0; i < argc; i++)
150 { 150 {
151 if (i > 0) 151 if (i > 0)
152 *p++ = ' '; 152 *p++ = ' ';
153 memcpy (p, argv[i], strlen (argv[i])); 153 memcpy (p, argv[i], strlen (argv[i]));
154 p += strlen (argv[i]); 154 p += strlen (argv[i]);
155 } 155 }
156 *p = 0; 156 *p = 0;
157 } 157 }
158 158
159 if (message) 159 if (message)
160 fmt = strdup ("%s"); 160 fmt = strdup ("%s");
243 ok = rc_service_state (argv[0], rc_service_wasinactive); 243 ok = rc_service_state (argv[0], rc_service_wasinactive);
244 else if (strcmp (applet, "service_started_daemon") == 0) 244 else if (strcmp (applet, "service_started_daemon") == 0)
245 { 245 {
246 int idx = 0; 246 int idx = 0;
247 if (argc > 2) 247 if (argc > 2)
248 sscanf (argv[2], "%d", &idx); 248 sscanf (argv[2], "%d", &idx);
249 exit (rc_service_started_daemon (argv[0], argv[1], idx) 249 exit (rc_service_started_daemon (argv[0], argv[1], idx)
250 ? 0 : 1); 250 ? 0 : 1);
251 } 251 }
252 else 252 else
253 eerrorx ("%s: unknown applet", applet); 253 eerrorx ("%s: unknown applet", applet);
254 254
255 return (ok ? EXIT_SUCCESS : EXIT_FAILURE); 255 return (ok ? EXIT_SUCCESS : EXIT_FAILURE);
286 char *mtime; 286 char *mtime;
287 pid_t pid = 0; 287 pid_t pid = 0;
288 int l; 288 int l;
289 289
290 if (runscript_pid && sscanf (runscript_pid, "%d", &pid) == 1) 290 if (runscript_pid && sscanf (runscript_pid, "%d", &pid) == 1)
291 if (kill (pid, SIGHUP) != 0) 291 if (kill (pid, SIGHUP) != 0)
292 eerror ("%s: failed to signal parent %d: %s", 292 eerror ("%s: failed to signal parent %d: %s",
293 applet, pid, strerror (errno)); 293 applet, pid, strerror (errno));
294 294
295 /* Remove the exclsive time test. This ensures that it's not 295 /* Remove the exclsive time test. This ensures that it's not
296 in control as well */ 296 in control as well */
297 l = strlen (RC_SVCDIR "exclusive") + 297 l = strlen (RC_SVCDIR "exclusive") +
298 strlen (svcname) + 298 strlen (svcname) +
299 strlen (runscript_pid) + 299 strlen (runscript_pid) +
300 4; 300 4;
301 mtime = rc_xmalloc (l); 301 mtime = rc_xmalloc (l);
302 snprintf (mtime, l, RC_SVCDIR "exclusive/%s.%s", 302 snprintf (mtime, l, RC_SVCDIR "exclusive/%s.%s",
303 svcname, runscript_pid); 303 svcname, runscript_pid);
304 if (rc_exists (mtime) && unlink (mtime) != 0) 304 if (rc_exists (mtime) && unlink (mtime) != 0)
305 eerror ("%s: unlink: %s", applet, strerror (errno)); 305 eerror ("%s: unlink: %s", applet, strerror (errno));
306 free (mtime); 306 free (mtime);
307 } 307 }
308 308
309 return (ok ? EXIT_SUCCESS : EXIT_FAILURE); 309 return (ok ? EXIT_SUCCESS : EXIT_FAILURE);
310} 310}
324 { 324 {
325 char buffer[1024]; 325 char buffer[1024];
326 memset (buffer, 0, 1024); 326 memset (buffer, 0, 1024);
327 ok = rc_get_service_option (service, argv[0], buffer); 327 ok = rc_get_service_option (service, argv[0], buffer);
328 if (ok) 328 if (ok)
329 printf ("%s", buffer); 329 printf ("%s", buffer);
330 } 330 }
331 else if (strcmp (applet, "save_options") == 0) 331 else if (strcmp (applet, "save_options") == 0)
332 ok = rc_set_service_option (service, argv[0], argv[1]); 332 ok = rc_set_service_option (service, argv[0], argv[1]);
333 else 333 else
334 eerrorx ("%s: unknown applet", applet); 334 eerrorx ("%s: unknown applet", applet);
390 { 390 {
391 int status = 0; 391 int status = 0;
392 pid_t pid = fork(); 392 pid_t pid = fork();
393 393
394 if (pid == -1) 394 if (pid == -1)
395 eerrorx ("%s: fork: %s", applet, strerror (errno)); 395 eerrorx ("%s: fork: %s", applet, strerror (errno));
396 if (pid == 0) 396 if (pid == 0)
397 { 397 {
398 newenv = rc_filter_env (); 398 newenv = rc_filter_env ();
399 mycmd = rc_xstrdup ("/sbin/sulogin"); 399 mycmd = rc_xstrdup ("/sbin/sulogin");
400 myarg = rc_xstrdup (getenv ("CONSOLE")); 400 myarg = rc_xstrdup (getenv ("CONSOLE"));
401 execle (mycmd, mycmd, myarg, (char *) NULL, newenv); 401 execle (mycmd, mycmd, myarg, (char *) NULL, newenv);
402 eerrorx ("%s: unable to exec `/sbin/sulogin': %s", applet, strerror (errno)); 402 eerrorx ("%s: unable to exec `/sbin/sulogin': %s", applet, strerror (errno));
403 } 403 }
404 waitpid (pid, &status, 0); 404 waitpid (pid, &status, 0);
405 } 405 }
406 else 406 else
407 { 407 {
408 408
427 strcmp (runlevel, RC_LEVEL_BOOT) == 0 || 427 strcmp (runlevel, RC_LEVEL_BOOT) == 0 ||
428 strcmp (runlevel, RC_LEVEL_SINGLE) == 0 || 428 strcmp (runlevel, RC_LEVEL_SINGLE) == 0 ||
429 strcmp (runlevel, RC_LEVEL_SYSINIT) == 0) 429 strcmp (runlevel, RC_LEVEL_SYSINIT) == 0)
430 { 430 {
431 if (rc_exists (RC_SVCDIR "ksoftlevel") && 431 if (rc_exists (RC_SVCDIR "ksoftlevel") &&
432 unlink (RC_SVCDIR "ksoftlevel") != 0) 432 unlink (RC_SVCDIR "ksoftlevel") != 0)
433 eerror ("unlink `%s': %s", RC_SVCDIR "ksoftlevel", strerror (errno)); 433 eerror ("unlink `%s': %s", RC_SVCDIR "ksoftlevel", strerror (errno));
434 return; 434 return;
435 } 435 }
436 436
437 if (! (fp = fopen (RC_SVCDIR "ksoftlevel", "w"))) 437 if (! (fp = fopen (RC_SVCDIR "ksoftlevel", "w")))
438 { 438 {
439 eerror ("fopen `%s': %s", RC_SVCDIR "ksoftlevel", strerror (errno)); 439 eerror ("fopen `%s': %s", RC_SVCDIR "ksoftlevel", strerror (errno));
440 return; 440 return;
441 } 441 }
442 442
443 fprintf (fp, "%s", runlevel); 443 fprintf (fp, "%s", runlevel);
444 fclose (fp); 444 fclose (fp);
445} 445}
446 446
447static void wait_for_services () 447static void wait_for_services ()
463 463
464 switch (sig) 464 switch (sig)
465 { 465 {
466 case SIGINT: 466 case SIGINT:
467 if (! signame[0]) 467 if (! signame[0])
468 snprintf (signame, sizeof (signame), "SIGINT"); 468 snprintf (signame, sizeof (signame), "SIGINT");
469 case SIGTERM: 469 case SIGTERM:
470 if (! signame[0]) 470 if (! signame[0])
471 snprintf (signame, sizeof (signame), "SIGTERM"); 471 snprintf (signame, sizeof (signame), "SIGTERM");
472 case SIGQUIT: 472 case SIGQUIT:
473 if (! signame[0]) 473 if (! signame[0])
474 snprintf (signame, sizeof (signame), "SIGQUIT"); 474 snprintf (signame, sizeof (signame), "SIGQUIT");
475 eerrorx ("%s: caught %s, aborting", applet, signame); 475 eerrorx ("%s: caught %s, aborting", applet, signame);
476 476
477 default: 477 default:
478 eerror ("%s: caught unknown signal %d", applet, sig); 478 eerror ("%s: caught unknown signal %d", applet, sig);
479 } 479 }
552 { 552 {
553 char *p; 553 char *p;
554 554
555#ifdef __linux__ 555#ifdef __linux__
556 /* clearenv isn't portable, but there's no harm in using it 556 /* clearenv isn't portable, but there's no harm in using it
557 if we have it */ 557 if we have it */
558 clearenv (); 558 clearenv ();
559#else 559#else
560 char *var; 560 char *var;
561 /* No clearenv present here then. 561 /* No clearenv present here then.
562 We could manipulate environ directly ourselves, but it seems that 562 We could manipulate environ directly ourselves, but it seems that
563 some kernels bitch about this according to the environ man pages 563 some kernels bitch about this according to the environ man pages
564 so we walk though environ and call unsetenv for each value. */ 564 so we walk though environ and call unsetenv for each value. */
565 while (environ[0]) 565 while (environ[0])
566 { 566 {
567 tmp = rc_xstrdup (environ[0]); 567 tmp = rc_xstrdup (environ[0]);
568 p = tmp; 568 p = tmp;
569 var = strsep (&p, "="); 569 var = strsep (&p, "=");
570 unsetenv (var); 570 unsetenv (var);
571 free (tmp); 571 free (tmp);
572 } 572 }
573 tmp = NULL; 573 tmp = NULL;
574#endif 574#endif
575 575
576 STRLIST_FOREACH (env, p, i) 576 STRLIST_FOREACH (env, p, i)
577 if (strcmp (p, "RC_SOFTLEVEL") != 0 && strcmp (p, "SOFTLEVEL") != 0) 577 if (strcmp (p, "RC_SOFTLEVEL") != 0 && strcmp (p, "SOFTLEVEL") != 0)
578 putenv (p); 578 putenv (p);
579 579
580 /* We don't free our list as that would be null in environ */ 580 /* We don't free our list as that would be null in environ */
581 } 581 }
582 582
583 /* Enable logging */ 583 /* Enable logging */
593 PREVLEVEL = getenv ("PREVLEVEL"); 593 PREVLEVEL = getenv ("PREVLEVEL");
594 594
595 if (RUNLEVEL && newlevel) 595 if (RUNLEVEL && newlevel)
596 { 596 {
597 if (strcmp (RUNLEVEL, "S") == 0 || strcmp (RUNLEVEL, "1") == 0) 597 if (strcmp (RUNLEVEL, "S") == 0 || strcmp (RUNLEVEL, "1") == 0)
598 { 598 {
599 /* OK, we're either in runlevel 1 or single user mode */ 599 /* OK, we're either in runlevel 1 or single user mode */
600 if (strcmp (newlevel, RC_LEVEL_SYSINIT) == 0) 600 if (strcmp (newlevel, RC_LEVEL_SYSINIT) == 0)
601 { 601 {
602 struct utsname uts; 602 struct utsname uts;
603 pid_t pid; 603 pid_t pid;
604 pid_t wpid; 604 pid_t wpid;
605 int status = 0; 605 int status = 0;
606#ifdef __linux__ 606#ifdef __linux__
607 FILE *fp; 607 FILE *fp;
608#endif 608#endif
609 609
610 uname (&uts); 610 uname (&uts);
611 611
612 printf ("\n"); 612 printf ("\n");
613 PEINFO_GOOD; 613 PEINFO_GOOD;
614 printf (" Gentoo/%s; ", uts.sysname); 614 printf (" Gentoo/%s; ", uts.sysname);
615 PEINFO_BRACKET; 615 PEINFO_BRACKET;
616 printf ("http://www.gentoo.org/"); 616 printf ("http://www.gentoo.org/");
617 PEINFO_NORMAL; 617 PEINFO_NORMAL;
618 printf ("\n Copyright 1999-2007 Gentoo Foundation; " 618 printf ("\n Copyright 1999-2007 Gentoo Foundation; "
619 "Distributed under the GPLv2\n\n"); 619 "Distributed under the GPLv2\n\n");
620 620
621 printf ("Press "); 621 printf ("Press ");
622 PEINFO_GOOD; 622 PEINFO_GOOD;
623 printf ("I"); 623 printf ("I");
624 PEINFO_NORMAL; 624 PEINFO_NORMAL;
625 printf (" to enter interactive boot mode\n\n"); 625 printf (" to enter interactive boot mode\n\n");
626 626
627 setenv ("RC_SOFTLEVEL", newlevel, 1); 627 setenv ("RC_SOFTLEVEL", newlevel, 1);
628 rc_plugin_run (rc_hook_runlevel_start_in, newlevel); 628 rc_plugin_run (rc_hook_runlevel_start_in, newlevel);
629 629
630 if ((pid = fork ()) == -1) 630 if ((pid = fork ()) == -1)
631 eerrorx ("%s: fork: %s", applet, strerror (errno)); 631 eerrorx ("%s: fork: %s", applet, strerror (errno));
632 632
633 if (pid == 0) 633 if (pid == 0)
634 { 634 {
635 mycmd = rc_xstrdup (INITSH); 635 mycmd = rc_xstrdup (INITSH);
636 execl (mycmd, mycmd, (char *) NULL); 636 execl (mycmd, mycmd, (char *) NULL);
637 eerrorx ("%s: unable to exec `" INITSH "': %s", 637 eerrorx ("%s: unable to exec `" INITSH "': %s",
638 applet, strerror (errno)); 638 applet, strerror (errno));
639 } 639 }
640 640
641 do 641 do
642 { 642 {
643 wpid = waitpid (pid, &status, 0); 643 wpid = waitpid (pid, &status, 0);
644 if (wpid < 1) 644 if (wpid < 1)
645 eerror ("waitpid: %s", strerror (errno)); 645 eerror ("waitpid: %s", strerror (errno));
646 } while (! WIFEXITED (status) && ! WIFSIGNALED (status)); 646 } while (! WIFEXITED (status) && ! WIFSIGNALED (status));
647 647
648 if (! WIFEXITED (status) || ! WEXITSTATUS (status) == 0) 648 if (! WIFEXITED (status) || ! WEXITSTATUS (status) == 0)
649 exit (EXIT_FAILURE); 649 exit (EXIT_FAILURE);
650 650
651 /* If we requested a softlevel, save it now */ 651 /* If we requested a softlevel, save it now */
652#ifdef __linux__ 652#ifdef __linux__
653 set_ksoftlevel (NULL); 653 set_ksoftlevel (NULL);
654 654
655 if ((fp = fopen ("/proc/cmdline", "r"))) 655 if ((fp = fopen ("/proc/cmdline", "r")))
656 { 656 {
657 char buffer[RC_LINEBUFFER]; 657 char buffer[RC_LINEBUFFER];
658 char *soft; 658 char *soft;
659 659
660 memset (buffer, 0, sizeof (buffer)); 660 memset (buffer, 0, sizeof (buffer));
661 if (fgets (buffer, RC_LINEBUFFER, fp) && 661 if (fgets (buffer, RC_LINEBUFFER, fp) &&
662 (soft = strstr (buffer, "softlevel="))) 662 (soft = strstr (buffer, "softlevel=")))
663 { 663 {
664 i = soft - buffer; 664 i = soft - buffer;
665 if (i == 0 || buffer[i - 1] == ' ') 665 if (i == 0 || buffer[i - 1] == ' ')
666 { 666 {
667 char *level; 667 char *level;
668 668
669 /* Trim the trailing carriage return if present */ 669 /* Trim the trailing carriage return if present */
670 i = strlen (buffer) - 1; 670 i = strlen (buffer) - 1;
671 if (buffer[i] == '\n') 671 if (buffer[i] == '\n')
672 buffer[i] = 0; 672 buffer[i] = 0;
673 673
674 soft += strlen ("softlevel="); 674 soft += strlen ("softlevel=");
675 level = strsep (&soft, " "); 675 level = strsep (&soft, " ");
676 set_ksoftlevel (level); 676 set_ksoftlevel (level);
677 } 677 }
678 } 678 }
679 fclose (fp); 679 fclose (fp);
680 } 680 }
681#endif 681#endif
682 rc_plugin_run (rc_hook_runlevel_start_out, newlevel); 682 rc_plugin_run (rc_hook_runlevel_start_out, newlevel);
683 683
684 if (want_interactive ()) 684 if (want_interactive ())
685 mark_interactive (); 685 mark_interactive ();
686 686
687 exit (EXIT_SUCCESS); 687 exit (EXIT_SUCCESS);
688 } 688 }
689 689
690#ifdef __linux__ 690#ifdef __linux__
691 /* Parse the inittab file so we can work out the level to telinit */ 691 /* Parse the inittab file so we can work out the level to telinit */
692 if (strcmp (newlevel, RC_LEVEL_BOOT) != 0 && 692 if (strcmp (newlevel, RC_LEVEL_BOOT) != 0 &&
693 strcmp (newlevel, RC_LEVEL_SINGLE) != 0) 693 strcmp (newlevel, RC_LEVEL_SINGLE) != 0)
694 { 694 {
695 char **inittab = rc_get_list (NULL, "/etc/inittab"); 695 char **inittab = rc_get_list (NULL, "/etc/inittab");
696 char *line; 696 char *line;
697 char *p; 697 char *p;
698 char *token; 698 char *token;
699 char lvl[2] = {0, 0}; 699 char lvl[2] = {0, 0};
700 700
701 STRLIST_FOREACH (inittab, line, i) 701 STRLIST_FOREACH (inittab, line, i)
702 { 702 {
703 p = line; 703 p = line;
704 token = strsep (&p, ":"); 704 token = strsep (&p, ":");
705 if (! token || token[0] != 'l') 705 if (! token || token[0] != 'l')
706 continue; 706 continue;
707 707
708 if ((token = strsep (&p, ":")) == NULL) 708 if ((token = strsep (&p, ":")) == NULL)
709 continue; 709 continue;
710 710
711 /* Snag the level */ 711 /* Snag the level */
712 lvl[0] = token[0]; 712 lvl[0] = token[0];
713 713
714 /* The name is spaced after this */ 714 /* The name is spaced after this */
715 if ((token = strsep (&p, " ")) == NULL) 715 if ((token = strsep (&p, " ")) == NULL)
716 continue; 716 continue;
717 717
718 if ((token = strsep (&p, " ")) == NULL) 718 if ((token = strsep (&p, " ")) == NULL)
719 continue; 719 continue;
720 720
721 if (strcmp (token, newlevel) == 0) 721 if (strcmp (token, newlevel) == 0)
722 break; 722 break;
723 } 723 }
724 rc_strlist_free (inittab); 724 rc_strlist_free (inittab);
725 725
726 /* We have a level, so telinit into it */ 726 /* We have a level, so telinit into it */
727 if (lvl[0] == 0) 727 if (lvl[0] == 0)
728 { 728 {
729 eerrorx ("%s: couldn't find a runlevel called `%s'", 729 eerrorx ("%s: couldn't find a runlevel called `%s'",
730 applet, newlevel); 730 applet, newlevel);
731 } 731 }
732 else 732 else
733 { 733 {
734 mycmd = rc_xstrdup ("/sbin/telinit"); 734 mycmd = rc_xstrdup ("/sbin/telinit");
735 myarg = rc_xstrdup (lvl); 735 myarg = rc_xstrdup (lvl);
736 execl (mycmd, mycmd, myarg, (char *) NULL); 736 execl (mycmd, mycmd, myarg, (char *) NULL);
737 eerrorx ("%s: unable to exec `/sbin/telinit': %s", 737 eerrorx ("%s: unable to exec `/sbin/telinit': %s",
738 applet, strerror (errno)); 738 applet, strerror (errno));
739 } 739 }
740 } 740 }
741#endif 741#endif
742 } 742 }
743 } 743 }
744 744
745 /* Check we're in the runlevel requested, ie from 745 /* Check we're in the runlevel requested, ie from
746 rc single 746 rc single
747 rc shutdown 747 rc shutdown
748 rc reboot 748 rc reboot
749 */ 749 */
750 if (newlevel) 750 if (newlevel)
751 { 751 {
752 if (myarg) 752 if (myarg)
753 { 753 {
754 free (myarg); 754 free (myarg);
755 myarg = NULL; 755 myarg = NULL;
756 } 756 }
757 757
758 if (strcmp (newlevel, RC_LEVEL_SINGLE) == 0) 758 if (strcmp (newlevel, RC_LEVEL_SINGLE) == 0)
759 { 759 {
760 if (! RUNLEVEL || 760 if (! RUNLEVEL ||
761 (strcmp (RUNLEVEL, "S") != 0 && 761 (strcmp (RUNLEVEL, "S") != 0 &&
762 strcmp (RUNLEVEL, "1") != 0)) 762 strcmp (RUNLEVEL, "1") != 0))
763 { 763 {
764 /* Remember the current runlevel for when we come back */ 764 /* Remember the current runlevel for when we come back */
765 set_ksoftlevel (runlevel); 765 set_ksoftlevel (runlevel);
766#ifdef __linux__ 766#ifdef __linux__
767 mycmd = rc_xstrdup ("/sbin/telinit"); 767 mycmd = rc_xstrdup ("/sbin/telinit");
768 myarg = rc_xstrdup ("S"); 768 myarg = rc_xstrdup ("S");
769 execl (mycmd, mycmd, myarg, (char *) NULL); 769 execl (mycmd, mycmd, myarg, (char *) NULL);
770 eerrorx ("%s: unable to exec `/%s': %s", 770 eerrorx ("%s: unable to exec `/%s': %s",
771 mycmd, applet, strerror (errno)); 771 mycmd, applet, strerror (errno));
772#else 772#else
773 if (kill (1, SIGTERM) != 0) 773 if (kill (1, SIGTERM) != 0)
774 eerrorx ("%s: unable to send SIGTERM to init (pid 1): %s", 774 eerrorx ("%s: unable to send SIGTERM to init (pid 1): %s",
775 applet, strerror (errno)); 775 applet, strerror (errno));
776 exit (EXIT_SUCCESS); 776 exit (EXIT_SUCCESS);
777#endif 777#endif
778 } 778 }
779 } 779 }
780 else if (strcmp (newlevel, RC_LEVEL_REBOOT) == 0) 780 else if (strcmp (newlevel, RC_LEVEL_REBOOT) == 0)
781 { 781 {
782 if (! RUNLEVEL || 782 if (! RUNLEVEL ||
783 strcmp (RUNLEVEL, "6") != 0) 783 strcmp (RUNLEVEL, "6") != 0)
784 { 784 {
785 mycmd = rc_xstrdup ("/sbin/shutdown"); 785 mycmd = rc_xstrdup ("/sbin/shutdown");
786 myarg = rc_xstrdup ("-r"); 786 myarg = rc_xstrdup ("-r");
787 tmp = rc_xstrdup ("now"); 787 tmp = rc_xstrdup ("now");
788 execl (mycmd, mycmd, myarg, tmp, (char *) NULL); 788 execl (mycmd, mycmd, myarg, tmp, (char *) NULL);
789 eerrorx ("%s: unable to exec `%s': %s", 789 eerrorx ("%s: unable to exec `%s': %s",
790 mycmd, applet, strerror (errno)); 790 mycmd, applet, strerror (errno));
791 } 791 }
792 } 792 }
793 else if (strcmp (newlevel, RC_LEVEL_SHUTDOWN) == 0) 793 else if (strcmp (newlevel, RC_LEVEL_SHUTDOWN) == 0)
794 { 794 {
795 if (! RUNLEVEL || 795 if (! RUNLEVEL ||
796 strcmp (RUNLEVEL, "0") != 0) 796 strcmp (RUNLEVEL, "0") != 0)
797 { 797 {
798 mycmd = rc_xstrdup ("/sbin/shutdown"); 798 mycmd = rc_xstrdup ("/sbin/shutdown");
799#ifdef __linux__ 799#ifdef __linux__
800 myarg = rc_xstrdup ("-h"); 800 myarg = rc_xstrdup ("-h");
801#else 801#else
802 myarg = rc_xstrdup ("-p"); 802 myarg = rc_xstrdup ("-p");
803#endif 803#endif
804 tmp = rc_xstrdup ("now"); 804 tmp = rc_xstrdup ("now");
805 execl (mycmd, mycmd, myarg, tmp, (char *) NULL); 805 execl (mycmd, mycmd, myarg, tmp, (char *) NULL);
806 eerrorx ("%s: unable to exec `%s': %s", 806 eerrorx ("%s: unable to exec `%s': %s",
807 mycmd, applet, strerror (errno)); 807 mycmd, applet, strerror (errno));
808 } 808 }
809 } 809 }
810 } 810 }
811 811
812 /* Export our current softlevel */ 812 /* Export our current softlevel */
813 runlevel = rc_get_runlevel (); 813 runlevel = rc_get_runlevel ();
814 814
817 if (newlevel && 817 if (newlevel &&
818 rc_exists (RC_SVCDIR "ksoftlevel") && 818 rc_exists (RC_SVCDIR "ksoftlevel") &&
819 strcmp (newlevel, RC_LEVEL_DEFAULT) == 0) 819 strcmp (newlevel, RC_LEVEL_DEFAULT) == 0)
820 { 820 {
821 /* We should only use ksoftlevel if we were in single user mode 821 /* We should only use ksoftlevel if we were in single user mode
822 If not, we need to erase ksoftlevel now. */ 822 If not, we need to erase ksoftlevel now. */
823 if (PREVLEVEL && 823 if (PREVLEVEL &&
824 (strcmp (PREVLEVEL, "1") == 0 || 824 (strcmp (PREVLEVEL, "1") == 0 ||
825 strcmp (PREVLEVEL, "S") == 0 || 825 strcmp (PREVLEVEL, "S") == 0 ||
826 strcmp (PREVLEVEL, "N") == 0)) 826 strcmp (PREVLEVEL, "N") == 0))
827 { 827 {
828 FILE *fp; 828 FILE *fp;
829 829
830 if (! (fp = fopen (RC_SVCDIR "ksoftlevel", "r"))) 830 if (! (fp = fopen (RC_SVCDIR "ksoftlevel", "r")))
831 eerror ("fopen `%s': %s", RC_SVCDIR "ksoftlevel", 831 eerror ("fopen `%s': %s", RC_SVCDIR "ksoftlevel",
832 strerror (errno)); 832 strerror (errno));
833 else 833 else
834 { 834 {
835 if (fgets (ksoftbuffer, sizeof (ksoftbuffer), fp)) 835 if (fgets (ksoftbuffer, sizeof (ksoftbuffer), fp))
836 { 836 {
837 i = strlen (ksoftbuffer) - 1; 837 i = strlen (ksoftbuffer) - 1;
838 if (ksoftbuffer[i] == '\n') 838 if (ksoftbuffer[i] == '\n')
839 ksoftbuffer[i] = 0; 839 ksoftbuffer[i] = 0;
840 newlevel = ksoftbuffer; 840 newlevel = ksoftbuffer;
841 } 841 }
842 fclose (fp); 842 fclose (fp);
843 } 843 }
844 } 844 }
845 else 845 else
846 set_ksoftlevel (NULL); 846 set_ksoftlevel (NULL);
847 } 847 }
848 848
849 if (newlevel && 849 if (newlevel &&
850 (strcmp (newlevel, RC_LEVEL_REBOOT) == 0 || 850 (strcmp (newlevel, RC_LEVEL_REBOOT) == 0 ||
851 strcmp (newlevel, RC_LEVEL_SHUTDOWN) == 0 || 851 strcmp (newlevel, RC_LEVEL_SHUTDOWN) == 0 ||
864 /* Check if runlevel is valid if we're changing */ 864 /* Check if runlevel is valid if we're changing */
865 if (newlevel && strcmp (runlevel, newlevel) != 0 && ! going_down) 865 if (newlevel && strcmp (runlevel, newlevel) != 0 && ! going_down)
866 { 866 {
867 tmp = rc_strcatpaths (RC_RUNLEVELDIR, newlevel, (char *) NULL); 867 tmp = rc_strcatpaths (RC_RUNLEVELDIR, newlevel, (char *) NULL);
868 if (! rc_is_dir (tmp)) 868 if (! rc_is_dir (tmp))
869 eerrorx ("%s: is not a valid runlevel", newlevel); 869 eerrorx ("%s: is not a valid runlevel", newlevel);
870 CHAR_FREE (tmp); 870 CHAR_FREE (tmp);
871 } 871 }
872 872
873 /* Load our deptree now */ 873 /* Load our deptree now */
874 if ((deptree = rc_load_deptree ()) == NULL) 874 if ((deptree = rc_load_deptree ()) == NULL)
890 start_services = rc_ls_dir (NULL, DEVBOOT, RC_LS_INITD); 890 start_services = rc_ls_dir (NULL, DEVBOOT, RC_LS_INITD);
891 rc_rm_dir (DEVBOOT, true); 891 rc_rm_dir (DEVBOOT, true);
892 892
893 STRLIST_FOREACH (start_services, service, i) 893 STRLIST_FOREACH (start_services, service, i)
894 if (rc_allow_plug (service)) 894 if (rc_allow_plug (service))
895 rc_mark_service (service, rc_service_coldplugged); 895 rc_mark_service (service, rc_service_coldplugged);
896 /* We need to dump this list now. 896 /* We need to dump this list now.
897 This may seem redunant, but only Linux needs this and saves on 897 This may seem redunant, but only Linux needs this and saves on
898 code bloat. */ 898 code bloat. */
899 rc_strlist_free (start_services); 899 rc_strlist_free (start_services);
900 start_services = NULL; 900 start_services = NULL;
901 } 901 }
902#else 902#else
903 /* BSD's on the other hand populate /dev automagically and use devd. 903 /* BSD's on the other hand populate /dev automagically and use devd.
910 rc_is_env ("RC_COLDPLUG", "yes")) 910 rc_is_env ("RC_COLDPLUG", "yes"))
911 { 911 {
912 /* The net interfaces are easy - they're all in net /dev/net :) */ 912 /* The net interfaces are easy - they're all in net /dev/net :) */
913 start_services = rc_ls_dir (NULL, "/dev/net", 0); 913 start_services = rc_ls_dir (NULL, "/dev/net", 0);
914 STRLIST_FOREACH (start_services, service, i) 914 STRLIST_FOREACH (start_services, service, i)
915 { 915 {
916 j = (strlen ("net.") + strlen (service) + 1); 916 j = (strlen ("net.") + strlen (service) + 1);
917 tmp = rc_xmalloc (sizeof (char *) * j); 917 tmp = rc_xmalloc (sizeof (char *) * j);
918 snprintf (tmp, j, "net.%s", service); 918 snprintf (tmp, j, "net.%s", service);
919 if (rc_service_exists (tmp) && rc_allow_plug (tmp)) 919 if (rc_service_exists (tmp) && rc_allow_plug (tmp))
920 rc_mark_service (tmp, rc_service_coldplugged); 920 rc_mark_service (tmp, rc_service_coldplugged);
921 CHAR_FREE (tmp); 921 CHAR_FREE (tmp);
922 } 922 }
923 rc_strlist_free (start_services); 923 rc_strlist_free (start_services);
924 924
925 /* The mice are a little more tricky. 925 /* The mice are a little more tricky.
926 If we coldplug anything else, we'll probably do it here. */ 926 If we coldplug anything else, we'll probably do it here. */
927 start_services = rc_ls_dir (NULL, "/dev", 0); 927 start_services = rc_ls_dir (NULL, "/dev", 0);
928 STRLIST_FOREACH (start_services, service, i) 928 STRLIST_FOREACH (start_services, service, i)
929 { 929 {
930 if (strncmp (service, "psm", 3) == 0 || 930 if (strncmp (service, "psm", 3) == 0 ||
931 strncmp (service, "ums", 3) == 0) 931 strncmp (service, "ums", 3) == 0)
932 { 932 {
933 char *p = service + 3; 933 char *p = service + 3;
934 if (p && isdigit (*p)) 934 if (p && isdigit (*p))
935 { 935 {
936 j = (strlen ("moused.") + strlen (service) + 1); 936 j = (strlen ("moused.") + strlen (service) + 1);
937 tmp = rc_xmalloc (sizeof (char *) * j); 937 tmp = rc_xmalloc (sizeof (char *) * j);
938 snprintf (tmp, j, "moused.%s", service); 938 snprintf (tmp, j, "moused.%s", service);
939 if (rc_service_exists (tmp) && rc_allow_plug (tmp)) 939 if (rc_service_exists (tmp) && rc_allow_plug (tmp))
940 rc_mark_service (tmp, rc_service_coldplugged); 940 rc_mark_service (tmp, rc_service_coldplugged);
941 CHAR_FREE (tmp); 941 CHAR_FREE (tmp);
942 } 942 }
943 } 943 }
944 } 944 }
945 rc_strlist_free (start_services); 945 rc_strlist_free (start_services);
946 start_services = NULL; 946 start_services = NULL;
947 } 947 }
948#endif 948#endif
949 949
955 955
956 types = rc_strlist_add (NULL, "ineed"); 956 types = rc_strlist_add (NULL, "ineed");
957 types = rc_strlist_add (types, "iuse"); 957 types = rc_strlist_add (types, "iuse");
958 types = rc_strlist_add (types, "iafter"); 958 types = rc_strlist_add (types, "iafter");
959 deporder = rc_get_depends (deptree, types, stop_services, 959 deporder = rc_get_depends (deptree, types, stop_services,
960 runlevel, depoptions); 960 runlevel, depoptions);
961 rc_strlist_free (stop_services); 961 rc_strlist_free (stop_services);
962 rc_strlist_free (types); 962 rc_strlist_free (types);
963 stop_services = deporder; 963 stop_services = deporder;
964 deporder = NULL; 964 deporder = NULL;
965 types = NULL; 965 types = NULL;
966 rc_strlist_reverse (stop_services); 966 rc_strlist_reverse (stop_services);
967 967
968 /* Load our list of coldplugged services */ 968 /* Load our list of coldplugged services */
969 coldplugged_services = rc_ls_dir (coldplugged_services, 969 coldplugged_services = rc_ls_dir (coldplugged_services,
970 RC_SVCDIR_COLDPLUGGED, RC_LS_INITD); 970 RC_SVCDIR_COLDPLUGGED, RC_LS_INITD);
971 971
972 /* Load our start services now. 972 /* Load our start services now.
973 We have different rules dependent on runlevel. */ 973 We have different rules dependent on runlevel. */
974 if (newlevel && strcmp (newlevel, RC_LEVEL_BOOT) == 0) 974 if (newlevel && strcmp (newlevel, RC_LEVEL_BOOT) == 0)
975 { 975 {
976 if (coldplugged_services) 976 if (coldplugged_services)
977 { 977 {
978 einfon ("Device initiated services:"); 978 einfon ("Device initiated services:");
979 STRLIST_FOREACH (coldplugged_services, service, i) 979 STRLIST_FOREACH (coldplugged_services, service, i)
980 { 980 {
981 printf (" %s", service); 981 printf (" %s", service);
982 start_services = rc_strlist_add (start_services, service); 982 start_services = rc_strlist_add (start_services, service);
983 } 983 }
984 printf ("\n"); 984 printf ("\n");
985 } 985 }
986 tmp = rc_strcatpaths (RC_RUNLEVELDIR, newlevel ? newlevel : runlevel, 986 tmp = rc_strcatpaths (RC_RUNLEVELDIR, newlevel ? newlevel : runlevel,
987 (char *) NULL); 987 (char *) NULL);
988 start_services = rc_ls_dir (start_services, tmp, RC_LS_INITD); 988 start_services = rc_ls_dir (start_services, tmp, RC_LS_INITD);
989 CHAR_FREE (tmp); 989 CHAR_FREE (tmp);
990 } 990 }
991 else 991 else
992 { 992 {
993 /* Store our list of coldplugged services */ 993 /* Store our list of coldplugged services */
994 coldplugged_services = rc_ls_dir (coldplugged_services, RC_SVCDIR_COLDPLUGGED, 994 coldplugged_services = rc_ls_dir (coldplugged_services, RC_SVCDIR_COLDPLUGGED,
995 RC_LS_INITD); 995 RC_LS_INITD);
996 if (strcmp (newlevel ? newlevel : runlevel, RC_LEVEL_SINGLE) != 0 && 996 if (strcmp (newlevel ? newlevel : runlevel, RC_LEVEL_SINGLE) != 0 &&
997 strcmp (newlevel ? newlevel : runlevel, RC_LEVEL_SHUTDOWN) != 0 && 997 strcmp (newlevel ? newlevel : runlevel, RC_LEVEL_SHUTDOWN) != 0 &&
998 strcmp (newlevel ? newlevel : runlevel, RC_LEVEL_REBOOT) != 0) 998 strcmp (newlevel ? newlevel : runlevel, RC_LEVEL_REBOOT) != 0)
999 { 999 {
1000 /* We need to include the boot runlevel services if we're not in it */ 1000 /* We need to include the boot runlevel services if we're not in it */
1001 start_services = rc_ls_dir (start_services, RC_RUNLEVELDIR RC_LEVEL_BOOT, 1001 start_services = rc_ls_dir (start_services, RC_RUNLEVELDIR RC_LEVEL_BOOT,
1002 RC_LS_INITD); 1002 RC_LS_INITD);
1003 STRLIST_FOREACH (coldplugged_services, service, i) 1003 STRLIST_FOREACH (coldplugged_services, service, i)
1004 start_services = rc_strlist_add (start_services, service); 1004 start_services = rc_strlist_add (start_services, service);
1005 1005
1006 tmp = rc_strcatpaths (RC_RUNLEVELDIR, 1006 tmp = rc_strcatpaths (RC_RUNLEVELDIR,
1007 newlevel ? newlevel : runlevel, (char *) NULL); 1007 newlevel ? newlevel : runlevel, (char *) NULL);
1008 start_services = rc_ls_dir (start_services, tmp, RC_LS_INITD); 1008 start_services = rc_ls_dir (start_services, tmp, RC_LS_INITD);
1009 CHAR_FREE (tmp); 1009 CHAR_FREE (tmp);
1010 } 1010 }
1011 } 1011 }
1012 1012
1013 /* Save out softlevel now */ 1013 /* Save out softlevel now */
1014 if (going_down) 1014 if (going_down)
1015 rc_set_runlevel (newlevel); 1015 rc_set_runlevel (newlevel);
1025 char *svc1 = NULL; 1025 char *svc1 = NULL;
1026 char *svc2 = NULL; 1026 char *svc2 = NULL;
1027 int k; 1027 int k;
1028 1028
1029 if (rc_service_state (service, rc_service_stopped)) 1029 if (rc_service_state (service, rc_service_stopped))
1030 continue; 1030 continue;
1031 1031
1032 /* We always stop the service when in these runlevels */ 1032 /* We always stop the service when in these runlevels */
1033 if (going_down) 1033 if (going_down)
1034 { 1034 {
1035 rc_stop_service (service); 1035 rc_stop_service (service);
1036 continue; 1036 continue;
1037 } 1037 }
1038 1038
1039 /* If we're in the start list then don't bother stopping us */ 1039 /* If we're in the start list then don't bother stopping us */
1040 STRLIST_FOREACH (start_services, svc1, j) 1040 STRLIST_FOREACH (start_services, svc1, j)
1041 if (strcmp (svc1, service) == 0) 1041 if (strcmp (svc1, service) == 0)
1042 { 1042 {
1043 found = true; 1043 found = true;
1044 break; 1044 break;
1045 } 1045 }
1046 1046
1047 /* Unless we would use a different config file */ 1047 /* Unless we would use a different config file */
1048 if (found) 1048 if (found)
1049 { 1049 {
1050 int len; 1050 int len;
1051 if (! newlevel) 1051 if (! newlevel)
1052 continue; 1052 continue;
1053 1053
1054 len = strlen (service) + strlen (runlevel) + 2;
1055 tmp = rc_xmalloc (sizeof (char *) * len);
1056 snprintf (tmp, len, "%s.%s", service, runlevel);
1057 conf = rc_strcatpaths (RC_CONFDIR, tmp, (char *) NULL);
1058 found = rc_exists (conf);
1059 CHAR_FREE (conf);
1060 CHAR_FREE (tmp);
1061 if (! found)
1062 {
1063 len = strlen (service) + strlen (newlevel) + 2; 1054 len = strlen (service) + strlen (runlevel) + 2;
1064 tmp = rc_xmalloc (sizeof (char *) * len); 1055 tmp = rc_xmalloc (sizeof (char *) * len);
1065 snprintf (tmp, len, "%s.%s", service, newlevel); 1056 snprintf (tmp, len, "%s.%s", service, runlevel);
1066 conf = rc_strcatpaths (RC_CONFDIR, tmp, (char *) NULL); 1057 conf = rc_strcatpaths (RC_CONFDIR, tmp, (char *) NULL);
1067 found = rc_exists (conf); 1058 found = rc_exists (conf);
1068 CHAR_FREE (conf); 1059 CHAR_FREE (conf);
1069 CHAR_FREE (tmp); 1060 CHAR_FREE (tmp);
1070 if (!found) 1061 if (! found)
1071 continue; 1062 {
1072 } 1063 len = strlen (service) + strlen (newlevel) + 2;
1073 } 1064 tmp = rc_xmalloc (sizeof (char *) * len);
1065 snprintf (tmp, len, "%s.%s", service, newlevel);
1066 conf = rc_strcatpaths (RC_CONFDIR, tmp, (char *) NULL);
1067 found = rc_exists (conf);
1068 CHAR_FREE (conf);
1069 CHAR_FREE (tmp);
1070 if (!found)
1071 continue;
1072 }
1073 }
1074 else 1074 else
1075 /* Allow coldplugged services not to be in the runlevels list */ 1075 /* Allow coldplugged services not to be in the runlevels list */
1076 { 1076 {
1077 if (rc_service_state (service, rc_service_coldplugged)) 1077 if (rc_service_state (service, rc_service_coldplugged))
1078 continue; 1078 continue;
1079 } 1079 }
1080 1080
1081 /* We got this far! Or last check is to see if any any service that 1081 /* We got this far! Or last check is to see if any any service that
1082 going to be started depends on us */ 1082 going to be started depends on us */
1083 stopdeps = rc_strlist_add (stopdeps, service); 1083 stopdeps = rc_strlist_add (stopdeps, service);
1084 deporder = rc_get_depends (deptree, types, stopdeps, 1084 deporder = rc_get_depends (deptree, types, stopdeps,
1085 runlevel, RC_DEP_STRICT); 1085 runlevel, RC_DEP_STRICT);
1086 rc_strlist_free (stopdeps); 1086 rc_strlist_free (stopdeps);
1087 stopdeps = NULL; 1087 stopdeps = NULL;
1088 found = false; 1088 found = false;
1089 STRLIST_FOREACH (deporder, svc1, j) 1089 STRLIST_FOREACH (deporder, svc1, j)
1090 { 1090 {
1091 STRLIST_FOREACH (start_services, svc2, k) 1091 STRLIST_FOREACH (start_services, svc2, k)
1092 if (strcmp (svc1, svc2) == 0) 1092 if (strcmp (svc1, svc2) == 0)
1093 { 1093 {
1094 found = true; 1094 found = true;
1095 break;
1096 }
1097 if (found)
1095 break; 1098 break;
1096 } 1099 }
1097 if (found)
1098 break;
1099 }
1100 rc_strlist_free (deporder); 1100 rc_strlist_free (deporder);
1101 deporder = NULL; 1101 deporder = NULL;
1102 1102
1103 /* After all that we can finally stop the blighter! */ 1103 /* After all that we can finally stop the blighter! */
1104 if (! found) 1104 if (! found)
1105 rc_stop_service (service); 1105 rc_stop_service (service);
1106 } 1106 }
1107 rc_strlist_free (types); 1107 rc_strlist_free (types);
1108 types = NULL; 1108 types = NULL;
1109 1109
1110 /* Wait for our services to finish */ 1110 /* Wait for our services to finish */
1130 { 1130 {
1131 mycmd = rc_xstrdup (HALTSH); 1131 mycmd = rc_xstrdup (HALTSH);
1132 myarg = rc_xstrdup (runlevel); 1132 myarg = rc_xstrdup (runlevel);
1133 execl (mycmd, mycmd, myarg, (char *) NULL); 1133 execl (mycmd, mycmd, myarg, (char *) NULL);
1134 eerrorx ("%s: unable to exec `%s': %s", 1134 eerrorx ("%s: unable to exec `%s': %s",
1135 applet, HALTSH, strerror (errno)); 1135 applet, HALTSH, strerror (errno));
1136 } 1136 }
1137 1137
1138 /* Single user is done now */ 1138 /* Single user is done now */
1139 if (strcmp (runlevel, RC_LEVEL_SINGLE) == 0) 1139 if (strcmp (runlevel, RC_LEVEL_SINGLE) == 0)
1140 { 1140 {
1141 if (rc_exists (INTERACTIVE)) 1141 if (rc_exists (INTERACTIVE))
1142 unlink (INTERACTIVE); 1142 unlink (INTERACTIVE);
1143 sulogin (false); 1143 sulogin (false);
1144 } 1144 }
1145 1145
1146 mkdir (RC_SVCDIR "softscripts.old", 0755); 1146 mkdir (RC_SVCDIR "softscripts.old", 0755);
1147 rc_plugin_run (rc_hook_runlevel_start_in, runlevel); 1147 rc_plugin_run (rc_hook_runlevel_start_in, runlevel);
1153 /* Order the services to start */ 1153 /* Order the services to start */
1154 types = rc_strlist_add (NULL, "ineed"); 1154 types = rc_strlist_add (NULL, "ineed");
1155 types = rc_strlist_add (types, "iuse"); 1155 types = rc_strlist_add (types, "iuse");
1156 types = rc_strlist_add (types, "iafter"); 1156 types = rc_strlist_add (types, "iafter");
1157 deporder = rc_get_depends (deptree, types, start_services, 1157 deporder = rc_get_depends (deptree, types, start_services,
1158 runlevel, depoptions); 1158 runlevel, depoptions);
1159 rc_strlist_free (types); 1159 rc_strlist_free (types);
1160 types = NULL; 1160 types = NULL;
1161 rc_strlist_free (start_services); 1161 rc_strlist_free (start_services);
1162 start_services = deporder; 1162 start_services = deporder;
1163 deporder = NULL; 1163 deporder = NULL;
1164 1164
1165 STRLIST_FOREACH (start_services, service, i) 1165 STRLIST_FOREACH (start_services, service, i)
1166 { 1166 {
1167 if (rc_service_state (service, rc_service_stopped)) 1167 if (rc_service_state (service, rc_service_stopped))
1168 { 1168 {
1169 if (! interactive) 1169 if (! interactive)
1170 interactive = want_interactive (); 1170 interactive = want_interactive ();
1171 1171
1172 if (interactive) 1172 if (interactive)
1173 { 1173 {
1174interactive_retry: 1174interactive_retry:
1175 printf ("\n"); 1175 printf ("\n");
1176 einfo ("About to start the service %s", service); 1176 einfo ("About to start the service %s", service);
1177 eindent (); 1177 eindent ();
1178 einfo ("1) Start the service\t\t2) Skip the service"); 1178 einfo ("1) Start the service\t\t2) Skip the service");
1179 einfo ("3) Continue boot process\t\t4) Exit to shell"); 1179 einfo ("3) Continue boot process\t\t4) Exit to shell");
1180 eoutdent (); 1180 eoutdent ();
1181interactive_option: 1181interactive_option:
1182 switch (read_key (true)) 1182 switch (read_key (true))
1183 { 1183 {
1184 case '1': break; 1184 case '1': break;
1185 case '2': continue; 1185 case '2': continue;
1186 case '3': interactive = false; break; 1186 case '3': interactive = false; break;
1187 case '4': sulogin (true); goto interactive_retry; 1187 case '4': sulogin (true); goto interactive_retry;
1188 default: goto interactive_option; 1188 default: goto interactive_option;
1189 } 1189 }
1190 } 1190 }
1191 rc_start_service (service); 1191 rc_start_service (service);
1192 } 1192 }
1193 } 1193 }
1194 1194
1195 /* Wait for our services to finish */ 1195 /* Wait for our services to finish */
1196 if (rc_is_env ("RC_PARALLEL_STARTUP", "yes")) 1196 if (rc_is_env ("RC_PARALLEL_STARTUP", "yes"))
1197 wait_for_services (); 1197 wait_for_services ();
1202 if (interactive && strcmp (runlevel, RC_LEVEL_BOOT) == 0) 1202 if (interactive && strcmp (runlevel, RC_LEVEL_BOOT) == 0)
1203 mark_interactive (); 1203 mark_interactive ();
1204 else 1204 else
1205 { 1205 {
1206 if (rc_exists (INTERACTIVE)) 1206 if (rc_exists (INTERACTIVE))
1207 unlink (INTERACTIVE); 1207 unlink (INTERACTIVE);
1208 } 1208 }
1209 1209
1210 return (EXIT_SUCCESS); 1210 return (EXIT_SUCCESS);
1211} 1211}
1212 1212

Legend:
Removed from v.2564  
changed lines
  Added in v.2569

  ViewVC Help
Powered by ViewVC 1.1.20