Deleted Added
full compact
init.c (159402) init.c (166484)
1/*-
2 * Copyright (c) 1991, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Donn Seeley at Berkeley Software Design, Inc.
7 *
8 * Redistribution and use in source and binary forms, with or without

--- 27 unchanged lines hidden (view full) ---

36 The Regents of the University of California. All rights reserved.\n";
37#endif /* not lint */
38
39#ifndef lint
40#if 0
41static char sccsid[] = "@(#)init.c 8.1 (Berkeley) 7/15/93";
42#endif
43static const char rcsid[] =
1/*-
2 * Copyright (c) 1991, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Donn Seeley at Berkeley Software Design, Inc.
7 *
8 * Redistribution and use in source and binary forms, with or without

--- 27 unchanged lines hidden (view full) ---

36 The Regents of the University of California. All rights reserved.\n";
37#endif /* not lint */
38
39#ifndef lint
40#if 0
41static char sccsid[] = "@(#)init.c 8.1 (Berkeley) 7/15/93";
42#endif
43static const char rcsid[] =
44 "$FreeBSD: head/sbin/init/init.c 159402 2006-06-08 14:04:36Z kib $";
44 "$FreeBSD: head/sbin/init/init.c 166484 2007-02-04 06:33:13Z imp $";
45#endif /* not lint */
46
47#include <sys/param.h>
48#include <sys/ioctl.h>
49#include <sys/mount.h>
50#include <sys/sysctl.h>
51#include <sys/wait.h>
52#include <sys/stat.h>
53#include <sys/uio.h>
54
55#include <db.h>
56#include <errno.h>
57#include <fcntl.h>
45#endif /* not lint */
46
47#include <sys/param.h>
48#include <sys/ioctl.h>
49#include <sys/mount.h>
50#include <sys/sysctl.h>
51#include <sys/wait.h>
52#include <sys/stat.h>
53#include <sys/uio.h>
54
55#include <db.h>
56#include <errno.h>
57#include <fcntl.h>
58#include <kenv.h>
58#include <libutil.h>
59#include <paths.h>
60#include <signal.h>
61#include <stdio.h>
62#include <stdlib.h>
63#include <string.h>
64#include <syslog.h>
65#include <time.h>

--- 50 unchanged lines hidden (view full) ---

116state_func_t single_user(void);
117state_func_t runcom(void);
118state_func_t read_ttys(void);
119state_func_t multi_user(void);
120state_func_t clean_ttys(void);
121state_func_t catatonia(void);
122state_func_t death(void);
123
59#include <libutil.h>
60#include <paths.h>
61#include <signal.h>
62#include <stdio.h>
63#include <stdlib.h>
64#include <string.h>
65#include <syslog.h>
66#include <time.h>

--- 50 unchanged lines hidden (view full) ---

117state_func_t single_user(void);
118state_func_t runcom(void);
119state_func_t read_ttys(void);
120state_func_t multi_user(void);
121state_func_t clean_ttys(void);
122state_func_t catatonia(void);
123state_func_t death(void);
124
125state_func_t run_script(const char *);
126
124enum { AUTOBOOT, FASTBOOT } runcom_mode = AUTOBOOT;
125#define FALSE 0
126#define TRUE 1
127
128int Reboot = FALSE;
129int howto = RB_AUTOBOOT;
130
131int devfs;
132
133void transition(state_t);
127enum { AUTOBOOT, FASTBOOT } runcom_mode = AUTOBOOT;
128#define FALSE 0
129#define TRUE 1
130
131int Reboot = FALSE;
132int howto = RB_AUTOBOOT;
133
134int devfs;
135
136void transition(state_t);
134state_t requested_transition = runcom;
137state_t requested_transition;
135
136void setctty(const char *);
138
139void setctty(const char *);
140const char *get_shell(void);
141void write_stderr(const char *message);
137
138typedef struct init_session {
139 int se_index; /* index of entry in ttys file */
140 pid_t se_process; /* controlling process */
141 time_t se_started; /* used to avoid thrashing */
142 int se_flags; /* status of session */
143#define SE_SHUTDOWN 0x1 /* session won't be restarted */
144#define SE_PRESENT 0x2 /* session is in /etc/ttys */

--- 37 unchanged lines hidden (view full) ---

182DB *session_db;
183
184/*
185 * The mother of all processes.
186 */
187int
188main(int argc, char *argv[])
189{
142
143typedef struct init_session {
144 int se_index; /* index of entry in ttys file */
145 pid_t se_process; /* controlling process */
146 time_t se_started; /* used to avoid thrashing */
147 int se_flags; /* status of session */
148#define SE_SHUTDOWN 0x1 /* session won't be restarted */
149#define SE_PRESENT 0x2 /* session is in /etc/ttys */

--- 37 unchanged lines hidden (view full) ---

187DB *session_db;
188
189/*
190 * The mother of all processes.
191 */
192int
193main(int argc, char *argv[])
194{
195 state_t initial_transition = runcom;
196 char kenv_value[PATH_MAX];
190 int c;
191 struct sigaction sa;
192 sigset_t mask;
193
194
195 /* Dispose of random users. */
196 if (getuid() != 0)
197 errx(1, "%s", strerror(EPERM));

--- 59 unchanged lines hidden (view full) ---

257 * never through bits set in some random machine register.
258 */
259 while ((c = getopt(argc, argv, "dsf")) != -1)
260 switch (c) {
261 case 'd':
262 devfs = 1;
263 break;
264 case 's':
197 int c;
198 struct sigaction sa;
199 sigset_t mask;
200
201
202 /* Dispose of random users. */
203 if (getuid() != 0)
204 errx(1, "%s", strerror(EPERM));

--- 59 unchanged lines hidden (view full) ---

264 * never through bits set in some random machine register.
265 */
266 while ((c = getopt(argc, argv, "dsf")) != -1)
267 switch (c) {
268 case 'd':
269 devfs = 1;
270 break;
271 case 's':
265 requested_transition = single_user;
272 initial_transition = single_user;
266 break;
267 case 'f':
268 runcom_mode = FASTBOOT;
269 break;
270 default:
271 warning("unrecognized flag '-%c'", c);
272 break;
273 }
274
275 if (optind != argc)
276 warning("ignoring excess arguments");
277
273 break;
274 case 'f':
275 runcom_mode = FASTBOOT;
276 break;
277 default:
278 warning("unrecognized flag '-%c'", c);
279 break;
280 }
281
282 if (optind != argc)
283 warning("ignoring excess arguments");
284
285 /*
286 * We catch or block signals rather than ignore them,
287 * so that they get reset on exec.
288 */
289 handle(badsys, SIGSYS, 0);
290 handle(disaster, SIGABRT, SIGFPE, SIGILL, SIGSEGV,
291 SIGBUS, SIGXCPU, SIGXFSZ, 0);
292 handle(transition_handler, SIGHUP, SIGINT, SIGTERM, SIGTSTP,
293 SIGUSR1, SIGUSR2, 0);
294 handle(alrm_handler, SIGALRM, 0);
295 sigfillset(&mask);
296 delset(&mask, SIGABRT, SIGFPE, SIGILL, SIGSEGV, SIGBUS, SIGSYS,
297 SIGXCPU, SIGXFSZ, SIGHUP, SIGINT, SIGTERM, SIGTSTP, SIGALRM,
298 SIGUSR1, SIGUSR2, 0);
299 sigprocmask(SIG_SETMASK, &mask, (sigset_t *) 0);
300 sigemptyset(&sa.sa_mask);
301 sa.sa_flags = 0;
302 sa.sa_handler = SIG_IGN;
303 (void) sigaction(SIGTTIN, &sa, (struct sigaction *)0);
304 (void) sigaction(SIGTTOU, &sa, (struct sigaction *)0);
305
306 /*
307 * Paranoia.
308 */
309 close(0);
310 close(1);
311 close(2);
312
313 if (kenv(KENV_GET, "init_script", kenv_value, sizeof(kenv_value)) > 0) {
314 state_func_t next_transition;
315
316 if ((next_transition = run_script(kenv_value)) != 0)
317 initial_transition = (state_t) next_transition;
318 }
319
320 if (kenv(KENV_GET, "init_chroot", kenv_value, sizeof(kenv_value)) > 0) {
321 if (chdir(kenv_value) != 0 || chroot(".") != 0)
322 warning("Can't chroot to %s: %m", kenv_value);
323 }
324
325 /*
326 * Additional check if devfs needs to be mounted:
327 * If "/" and "/dev" have the same device number,
328 * then it hasn't been mounted yet.
329 */
330 if (!devfs) {
331 struct stat stst;
332 dev_t root_devno;
333
334 stat("/", &stst);
335 root_devno = stst.st_dev;
336 if (stat("/dev", &stst) != 0)
337 warning("Can't stat /dev: %m");
338 else if (stst.st_dev == root_devno)
339 devfs++;
340 }
341
278 if (devfs) {
279 struct iovec iov[4];
280 char *s;
281 int i;
282
283 char _fstype[] = "fstype";
284 char _devfs[] = "devfs";
285 char _fspath[] = "fspath";

--- 21 unchanged lines hidden (view full) ---

307 iov[3].iov_len = sizeof(_path_dev);
308 }
309 nmount(iov, 4, 0);
310 if (s != NULL)
311 free(s);
312 }
313
314 /*
342 if (devfs) {
343 struct iovec iov[4];
344 char *s;
345 int i;
346
347 char _fstype[] = "fstype";
348 char _devfs[] = "devfs";
349 char _fspath[] = "fspath";

--- 21 unchanged lines hidden (view full) ---

371 iov[3].iov_len = sizeof(_path_dev);
372 }
373 nmount(iov, 4, 0);
374 if (s != NULL)
375 free(s);
376 }
377
378 /*
315 * We catch or block signals rather than ignore them,
316 * so that they get reset on exec.
317 */
318 handle(badsys, SIGSYS, 0);
319 handle(disaster, SIGABRT, SIGFPE, SIGILL, SIGSEGV,
320 SIGBUS, SIGXCPU, SIGXFSZ, 0);
321 handle(transition_handler, SIGHUP, SIGINT, SIGTERM, SIGTSTP,
322 SIGUSR1, SIGUSR2, 0);
323 handle(alrm_handler, SIGALRM, 0);
324 sigfillset(&mask);
325 delset(&mask, SIGABRT, SIGFPE, SIGILL, SIGSEGV, SIGBUS, SIGSYS,
326 SIGXCPU, SIGXFSZ, SIGHUP, SIGINT, SIGTERM, SIGTSTP, SIGALRM,
327 SIGUSR1, SIGUSR2, 0);
328 sigprocmask(SIG_SETMASK, &mask, (sigset_t *) 0);
329 sigemptyset(&sa.sa_mask);
330 sa.sa_flags = 0;
331 sa.sa_handler = SIG_IGN;
332 (void) sigaction(SIGTTIN, &sa, (struct sigaction *)0);
333 (void) sigaction(SIGTTOU, &sa, (struct sigaction *)0);
334
335 /*
336 * Paranoia.
337 */
338 close(0);
339 close(1);
340 close(2);
341
342 /*
343 * Start the state machine.
344 */
379 * Start the state machine.
380 */
345 transition(requested_transition);
381 transition(initial_transition);
346
347 /*
348 * Should never reach here.
349 */
350 return 1;
351}
352
353/*

--- 199 unchanged lines hidden (view full) ---

553 _exit(1);
554 }
555 if (login_tty(fd) == -1) {
556 stall("can't get %s for controlling terminal: %m", name);
557 _exit(1);
558 }
559}
560
382
383 /*
384 * Should never reach here.
385 */
386 return 1;
387}
388
389/*

--- 199 unchanged lines hidden (view full) ---

589 _exit(1);
590 }
591 if (login_tty(fd) == -1) {
592 stall("can't get %s for controlling terminal: %m", name);
593 _exit(1);
594 }
595}
596
597const char *
598get_shell(void)
599{
600 static char kenv_value[PATH_MAX];
601
602 if (kenv(KENV_GET, "init_shell", kenv_value, sizeof(kenv_value)) > 0)
603 return kenv_value;
604 else
605 return _PATH_BSHELL;
606}
607
608void
609write_stderr(const char *message)
610{
611 write(STDERR_FILENO, message, strlen(message));
612}
613
561/*
562 * Bring the system up single user.
563 */
564state_func_t
565single_user(void)
566{
567 pid_t pid, wpid;
568 int status;
569 sigset_t mask;
614/*
615 * Bring the system up single user.
616 */
617state_func_t
618single_user(void)
619{
620 pid_t pid, wpid;
621 int status;
622 sigset_t mask;
570 const char *shell = _PATH_BSHELL;
623 const char *shell;
571 char *argv[2];
572#ifdef SECURE
573 struct ttyent *typ;
574 struct passwd *pp;
575 static const char banner[] =
576 "Enter root password, or ^D to go multi-user\n";
577 char *clear, *password;
578#endif

--- 5 unchanged lines hidden (view full) ---

584 /* Instead of going single user, let's reboot the machine */
585 sync();
586 alarm(2);
587 pause();
588 reboot(howto);
589 _exit(0);
590 }
591
624 char *argv[2];
625#ifdef SECURE
626 struct ttyent *typ;
627 struct passwd *pp;
628 static const char banner[] =
629 "Enter root password, or ^D to go multi-user\n";
630 char *clear, *password;
631#endif

--- 5 unchanged lines hidden (view full) ---

637 /* Instead of going single user, let's reboot the machine */
638 sync();
639 alarm(2);
640 pause();
641 reboot(howto);
642 _exit(0);
643 }
644
645 shell = get_shell();
646
592 if ((pid = fork()) == 0) {
593 /*
594 * Start the single user session.
595 */
596 setctty(_PATH_CONSOLE);
597
598#ifdef SECURE
599 /*
600 * Check the root password.
601 * We don't care if the console is 'on' by default;
602 * it's the only tty that can be 'off' and 'secure'.
603 */
604 typ = getttynam("console");
605 pp = getpwnam("root");
606 if (typ && (typ->ty_status & TTY_SECURE) == 0 &&
607 pp && *pp->pw_passwd) {
647 if ((pid = fork()) == 0) {
648 /*
649 * Start the single user session.
650 */
651 setctty(_PATH_CONSOLE);
652
653#ifdef SECURE
654 /*
655 * Check the root password.
656 * We don't care if the console is 'on' by default;
657 * it's the only tty that can be 'off' and 'secure'.
658 */
659 typ = getttynam("console");
660 pp = getpwnam("root");
661 if (typ && (typ->ty_status & TTY_SECURE) == 0 &&
662 pp && *pp->pw_passwd) {
608 write(STDERR_FILENO, banner, sizeof banner - 1);
663 write_stderr(banner);
609 for (;;) {
610 clear = getpass("Password:");
611 if (clear == 0 || *clear == '\0')
612 _exit(0);
613 password = crypt(clear, pp->pw_passwd);
614 bzero(clear, _PASSWORD_LEN);
615 if (strcmp(password, pp->pw_passwd) == 0)
616 break;

--- 4 unchanged lines hidden (view full) ---

621 endpwent();
622#endif /* SECURE */
623
624#ifdef DEBUGSHELL
625 {
626 char *cp = altshell;
627 int num;
628
664 for (;;) {
665 clear = getpass("Password:");
666 if (clear == 0 || *clear == '\0')
667 _exit(0);
668 password = crypt(clear, pp->pw_passwd);
669 bzero(clear, _PASSWORD_LEN);
670 if (strcmp(password, pp->pw_passwd) == 0)
671 break;

--- 4 unchanged lines hidden (view full) ---

676 endpwent();
677#endif /* SECURE */
678
679#ifdef DEBUGSHELL
680 {
681 char *cp = altshell;
682 int num;
683
629#define SHREQUEST \
630 "Enter full pathname of shell or RETURN for " _PATH_BSHELL ": "
631 (void)write(STDERR_FILENO,
632 SHREQUEST, sizeof(SHREQUEST) - 1);
684#define SHREQUEST "Enter full pathname of shell or RETURN for "
685 write_stderr(SHREQUEST);
686 write_stderr(shell);
687 write_stderr(": ");
633 while ((num = read(STDIN_FILENO, cp, 1)) != -1 &&
634 num != 0 && *cp != '\n' && cp < &altshell[127])
635 cp++;
636 *cp = '\0';
637 if (altshell[0] != '\0')
638 shell = altshell;
639 }
640#endif /* DEBUGSHELL */

--- 72 unchanged lines hidden (view full) ---

713}
714
715/*
716 * Run the system startup script.
717 */
718state_func_t
719runcom(void)
720{
688 while ((num = read(STDIN_FILENO, cp, 1)) != -1 &&
689 num != 0 && *cp != '\n' && cp < &altshell[127])
690 cp++;
691 *cp = '\0';
692 if (altshell[0] != '\0')
693 shell = altshell;
694 }
695#endif /* DEBUGSHELL */

--- 72 unchanged lines hidden (view full) ---

768}
769
770/*
771 * Run the system startup script.
772 */
773state_func_t
774runcom(void)
775{
776 state_func_t next_transition;
777
778 if ((next_transition = run_script(_PATH_RUNCOM)) != 0)
779 return next_transition;
780
781 runcom_mode = AUTOBOOT; /* the default */
782 /* NB: should send a message to the session logger to avoid blocking. */
783 logwtmp("~", "reboot", "");
784 return (state_func_t) read_ttys;
785}
786
787/*
788 * Run a shell script.
789 * Returns 0 on success, otherwise the next transition to enter:
790 * - single_user if fork/execv/waitpid failed, or if the script
791 * terminated with a signal or exit code != 0.
792 * - death if a SIGTERM was delivered to init(8).
793 */
794state_func_t
795run_script(const char *script)
796{
721 pid_t pid, wpid;
722 int status;
723 char *argv[4];
797 pid_t pid, wpid;
798 int status;
799 char *argv[4];
800 const char *shell;
724 struct sigaction sa;
725
801 struct sigaction sa;
802
803 shell = get_shell();
804
726 if ((pid = fork()) == 0) {
727 sigemptyset(&sa.sa_mask);
728 sa.sa_flags = 0;
729 sa.sa_handler = SIG_IGN;
730 (void) sigaction(SIGTSTP, &sa, (struct sigaction *)0);
731 (void) sigaction(SIGHUP, &sa, (struct sigaction *)0);
732
733 setctty(_PATH_CONSOLE);
734
735 char _sh[] = "sh";
805 if ((pid = fork()) == 0) {
806 sigemptyset(&sa.sa_mask);
807 sa.sa_flags = 0;
808 sa.sa_handler = SIG_IGN;
809 (void) sigaction(SIGTSTP, &sa, (struct sigaction *)0);
810 (void) sigaction(SIGHUP, &sa, (struct sigaction *)0);
811
812 setctty(_PATH_CONSOLE);
813
814 char _sh[] = "sh";
736 char _path_runcom[] = _PATH_RUNCOM;
737 char _autoboot[] = "autoboot";
738
739 argv[0] = _sh;
815 char _autoboot[] = "autoboot";
816
817 argv[0] = _sh;
740 argv[1] = _path_runcom;
818 argv[1] = __DECONST(char *, script);
741 argv[2] = runcom_mode == AUTOBOOT ? _autoboot : 0;
742 argv[3] = 0;
743
744 sigprocmask(SIG_SETMASK, &sa.sa_mask, (sigset_t *) 0);
745
746#ifdef LOGIN_CAP
747 setprocresources(RESOURCE_RC);
748#endif
819 argv[2] = runcom_mode == AUTOBOOT ? _autoboot : 0;
820 argv[3] = 0;
821
822 sigprocmask(SIG_SETMASK, &sa.sa_mask, (sigset_t *) 0);
823
824#ifdef LOGIN_CAP
825 setprocresources(RESOURCE_RC);
826#endif
749 execv(_PATH_BSHELL, argv);
750 stall("can't exec %s for %s: %m", _PATH_BSHELL, _PATH_RUNCOM);
827 execv(shell, argv);
828 stall("can't exec %s for %s: %m", shell, script);
751 _exit(1); /* force single user mode */
752 }
753
754 if (pid == -1) {
829 _exit(1); /* force single user mode */
830 }
831
832 if (pid == -1) {
755 emergency("can't fork for %s on %s: %m",
756 _PATH_BSHELL, _PATH_RUNCOM);
833 emergency("can't fork for %s on %s: %m", shell, script);
757 while (waitpid(-1, (int *) 0, WNOHANG) > 0)
758 continue;
759 sleep(STALL_TIMEOUT);
760 return (state_func_t) single_user;
761 }
762
763 /*
764 * Copied from single_user(). This is a bit paranoid.
765 */
766 requested_transition = 0;
767 do {
768 if ((wpid = waitpid(-1, &status, WUNTRACED)) != -1)
769 collect_child(wpid);
770 if (wpid == -1) {
771 if (requested_transition == death)
772 return (state_func_t) death;
773 if (errno == EINTR)
774 continue;
834 while (waitpid(-1, (int *) 0, WNOHANG) > 0)
835 continue;
836 sleep(STALL_TIMEOUT);
837 return (state_func_t) single_user;
838 }
839
840 /*
841 * Copied from single_user(). This is a bit paranoid.
842 */
843 requested_transition = 0;
844 do {
845 if ((wpid = waitpid(-1, &status, WUNTRACED)) != -1)
846 collect_child(wpid);
847 if (wpid == -1) {
848 if (requested_transition == death)
849 return (state_func_t) death;
850 if (errno == EINTR)
851 continue;
775 warning("wait for %s on %s failed: %m; going to single user mode",
776 _PATH_BSHELL, _PATH_RUNCOM);
852 warning("wait for %s on %s failed: %m; going to "
853 "single user mode", shell, script);
777 return (state_func_t) single_user;
778 }
779 if (wpid == pid && WIFSTOPPED(status)) {
780 warning("init: %s on %s stopped, restarting\n",
854 return (state_func_t) single_user;
855 }
856 if (wpid == pid && WIFSTOPPED(status)) {
857 warning("init: %s on %s stopped, restarting\n",
781 _PATH_BSHELL, _PATH_RUNCOM);
858 shell, script);
782 kill(pid, SIGCONT);
783 wpid = -1;
784 }
785 } while (wpid != pid);
786
787 if (WIFSIGNALED(status) && WTERMSIG(status) == SIGTERM &&
788 requested_transition == catatonia) {
789 /* /etc/rc executed /sbin/reboot; wait for the end quietly */
790 sigset_t s;
791
792 sigfillset(&s);
793 for (;;)
794 sigsuspend(&s);
795 }
796
797 if (!WIFEXITED(status)) {
859 kill(pid, SIGCONT);
860 wpid = -1;
861 }
862 } while (wpid != pid);
863
864 if (WIFSIGNALED(status) && WTERMSIG(status) == SIGTERM &&
865 requested_transition == catatonia) {
866 /* /etc/rc executed /sbin/reboot; wait for the end quietly */
867 sigset_t s;
868
869 sigfillset(&s);
870 for (;;)
871 sigsuspend(&s);
872 }
873
874 if (!WIFEXITED(status)) {
798 warning("%s on %s terminated abnormally, going to single user mode",
799 _PATH_BSHELL, _PATH_RUNCOM);
875 warning("%s on %s terminated abnormally, going to single "
876 "user mode", shell, script);
800 return (state_func_t) single_user;
801 }
802
803 if (WEXITSTATUS(status))
804 return (state_func_t) single_user;
805
877 return (state_func_t) single_user;
878 }
879
880 if (WEXITSTATUS(status))
881 return (state_func_t) single_user;
882
806 runcom_mode = AUTOBOOT; /* the default */
807 /* NB: should send a message to the session logger to avoid blocking. */
808 logwtmp("~", "reboot", "");
809 return (state_func_t) read_ttys;
883 return (state_func_t) 0;
810}
811
812/*
813 * Open the session database.
814 *
815 * NB: We could pass in the size here; is it necessary?
816 */
817int

--- 642 unchanged lines hidden (view full) ---

1460int
1461runshutdown(void)
1462{
1463 pid_t pid, wpid;
1464 int status;
1465 int shutdowntimeout;
1466 size_t len;
1467 char *argv[4];
884}
885
886/*
887 * Open the session database.
888 *
889 * NB: We could pass in the size here; is it necessary?
890 */
891int

--- 642 unchanged lines hidden (view full) ---

1534int
1535runshutdown(void)
1536{
1537 pid_t pid, wpid;
1538 int status;
1539 int shutdowntimeout;
1540 size_t len;
1541 char *argv[4];
1542 const char *shell;
1468 struct sigaction sa;
1469 struct stat sb;
1470
1471 /*
1472 * rc.shutdown is optional, so to prevent any unnecessary
1473 * complaints from the shell we simply don't run it if the
1474 * file does not exist. If the stat() here fails for other
1475 * reasons, we'll let the shell complain.
1476 */
1477 if (stat(_PATH_RUNDOWN, &sb) == -1 && errno == ENOENT)
1478 return 0;
1479
1543 struct sigaction sa;
1544 struct stat sb;
1545
1546 /*
1547 * rc.shutdown is optional, so to prevent any unnecessary
1548 * complaints from the shell we simply don't run it if the
1549 * file does not exist. If the stat() here fails for other
1550 * reasons, we'll let the shell complain.
1551 */
1552 if (stat(_PATH_RUNDOWN, &sb) == -1 && errno == ENOENT)
1553 return 0;
1554
1555 shell = get_shell();
1556
1480 if ((pid = fork()) == 0) {
1481 int fd;
1482
1483 /* Assume that init already grab console as ctty before */
1484
1485 sigemptyset(&sa.sa_mask);
1486 sa.sa_flags = 0;
1487 sa.sa_handler = SIG_IGN;

--- 24 unchanged lines hidden (view full) ---

1512 argv[2] = Reboot ? _reboot : _single;
1513 argv[3] = 0;
1514
1515 sigprocmask(SIG_SETMASK, &sa.sa_mask, (sigset_t *) 0);
1516
1517#ifdef LOGIN_CAP
1518 setprocresources(RESOURCE_RC);
1519#endif
1557 if ((pid = fork()) == 0) {
1558 int fd;
1559
1560 /* Assume that init already grab console as ctty before */
1561
1562 sigemptyset(&sa.sa_mask);
1563 sa.sa_flags = 0;
1564 sa.sa_handler = SIG_IGN;

--- 24 unchanged lines hidden (view full) ---

1589 argv[2] = Reboot ? _reboot : _single;
1590 argv[3] = 0;
1591
1592 sigprocmask(SIG_SETMASK, &sa.sa_mask, (sigset_t *) 0);
1593
1594#ifdef LOGIN_CAP
1595 setprocresources(RESOURCE_RC);
1596#endif
1520 execv(_PATH_BSHELL, argv);
1521 warning("can't exec %s for %s: %m", _PATH_BSHELL, _PATH_RUNDOWN);
1597 execv(shell, argv);
1598 warning("can't exec %s for %s: %m", shell, _PATH_RUNDOWN);
1522 _exit(1); /* force single user mode */
1523 }
1524
1525 if (pid == -1) {
1599 _exit(1); /* force single user mode */
1600 }
1601
1602 if (pid == -1) {
1526 emergency("can't fork for %s on %s: %m",
1527 _PATH_BSHELL, _PATH_RUNDOWN);
1603 emergency("can't fork for %s on %s: %m", shell, _PATH_RUNDOWN);
1528 while (waitpid(-1, (int *) 0, WNOHANG) > 0)
1529 continue;
1530 sleep(STALL_TIMEOUT);
1531 return -1;
1532 }
1533
1534 len = sizeof(shutdowntimeout);
1535 if (sysctlbyname("kern.init_shutdown_timeout",

--- 7 unchanged lines hidden (view full) ---

1543 * Use the same ALRM handler.
1544 */
1545 do {
1546 if ((wpid = waitpid(-1, &status, WUNTRACED)) != -1)
1547 collect_child(wpid);
1548 if (clang == 1) {
1549 /* we were waiting for the sub-shell */
1550 kill(wpid, SIGTERM);
1604 while (waitpid(-1, (int *) 0, WNOHANG) > 0)
1605 continue;
1606 sleep(STALL_TIMEOUT);
1607 return -1;
1608 }
1609
1610 len = sizeof(shutdowntimeout);
1611 if (sysctlbyname("kern.init_shutdown_timeout",

--- 7 unchanged lines hidden (view full) ---

1619 * Use the same ALRM handler.
1620 */
1621 do {
1622 if ((wpid = waitpid(-1, &status, WUNTRACED)) != -1)
1623 collect_child(wpid);
1624 if (clang == 1) {
1625 /* we were waiting for the sub-shell */
1626 kill(wpid, SIGTERM);
1551 warning("timeout expired for %s on %s: %m; going to single user mode",
1552 _PATH_BSHELL, _PATH_RUNDOWN);
1627 warning("timeout expired for %s on %s: %m; going to "
1628 "single user mode", shell, _PATH_RUNDOWN);
1553 return -1;
1554 }
1555 if (wpid == -1) {
1556 if (errno == EINTR)
1557 continue;
1629 return -1;
1630 }
1631 if (wpid == -1) {
1632 if (errno == EINTR)
1633 continue;
1558 warning("wait for %s on %s failed: %m; going to single user mode",
1559 _PATH_BSHELL, _PATH_RUNDOWN);
1634 warning("wait for %s on %s failed: %m; going to "
1635 "single user mode", shell, _PATH_RUNDOWN);
1560 return -1;
1561 }
1562 if (wpid == pid && WIFSTOPPED(status)) {
1563 warning("init: %s on %s stopped, restarting\n",
1636 return -1;
1637 }
1638 if (wpid == pid && WIFSTOPPED(status)) {
1639 warning("init: %s on %s stopped, restarting\n",
1564 _PATH_BSHELL, _PATH_RUNDOWN);
1640 shell, _PATH_RUNDOWN);
1565 kill(pid, SIGCONT);
1566 wpid = -1;
1567 }
1568 } while (wpid != pid && !clang);
1569
1570 /* Turn off the alarm */
1571 alarm(0);
1572

--- 6 unchanged lines hidden (view full) ---

1579 sigset_t s;
1580
1581 sigfillset(&s);
1582 for (;;)
1583 sigsuspend(&s);
1584 }
1585
1586 if (!WIFEXITED(status)) {
1641 kill(pid, SIGCONT);
1642 wpid = -1;
1643 }
1644 } while (wpid != pid && !clang);
1645
1646 /* Turn off the alarm */
1647 alarm(0);
1648

--- 6 unchanged lines hidden (view full) ---

1655 sigset_t s;
1656
1657 sigfillset(&s);
1658 for (;;)
1659 sigsuspend(&s);
1660 }
1661
1662 if (!WIFEXITED(status)) {
1587 warning("%s on %s terminated abnormally, going to single user mode",
1588 _PATH_BSHELL, _PATH_RUNDOWN);
1663 warning("%s on %s terminated abnormally, going to "
1664 "single user mode", shell, _PATH_RUNDOWN);
1589 return -2;
1590 }
1591
1592 if ((status = WEXITSTATUS(status)) != 0)
1593 warning("%s returned status %d", _PATH_RUNDOWN, status);
1594
1595 return status;
1596}

--- 51 unchanged lines hidden ---
1665 return -2;
1666 }
1667
1668 if ((status = WEXITSTATUS(status)) != 0)
1669 warning("%s returned status %d", _PATH_RUNDOWN, status);
1670
1671 return status;
1672}

--- 51 unchanged lines hidden ---