]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - sbin/init/init.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / sbin / init / init.c
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
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 4. Neither the name of the University nor the names of its contributors
17  *    may be used to endorse or promote products derived from this software
18  *    without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  */
32
33 #ifndef lint
34 static const char copyright[] =
35 "@(#) Copyright (c) 1991, 1993\n\
36         The Regents of the University of California.  All rights reserved.\n";
37 #endif /* not lint */
38
39 #ifndef lint
40 #if 0
41 static char sccsid[] = "@(#)init.c      8.1 (Berkeley) 7/15/93";
42 #endif
43 static const char rcsid[] =
44   "$FreeBSD$";
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>
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>
67 #include <ttyent.h>
68 #include <unistd.h>
69 #include <utmpx.h>
70 #include <sys/reboot.h>
71 #include <err.h>
72
73 #include <stdarg.h>
74
75 #ifdef SECURE
76 #include <pwd.h>
77 #endif
78
79 #ifdef LOGIN_CAP
80 #include <login_cap.h>
81 #endif
82
83 #include "pathnames.h"
84
85 /*
86  * Sleep times; used to prevent thrashing.
87  */
88 #define GETTY_SPACING            5      /* N secs minimum getty spacing */
89 #define GETTY_SLEEP             30      /* sleep N secs after spacing problem */
90 #define GETTY_NSPACE             3      /* max. spacing count to bring reaction */
91 #define WINDOW_WAIT              3      /* wait N secs after starting window */
92 #define STALL_TIMEOUT           30      /* wait N secs after warning */
93 #define DEATH_WATCH             10      /* wait N secs for procs to die */
94 #define DEATH_SCRIPT            120     /* wait for 2min for /etc/rc.shutdown */
95 #define RESOURCE_RC             "daemon"
96 #define RESOURCE_WINDOW         "default"
97 #define RESOURCE_GETTY          "default"
98
99 static void handle(sig_t, ...);
100 static void delset(sigset_t *, ...);
101
102 static void stall(const char *, ...) __printflike(1, 2);
103 static void warning(const char *, ...) __printflike(1, 2);
104 static void emergency(const char *, ...) __printflike(1, 2);
105 static void disaster(int);
106 static void badsys(int);
107 static int  runshutdown(void);
108 static char *strk(char *);
109
110 /*
111  * We really need a recursive typedef...
112  * The following at least guarantees that the return type of (*state_t)()
113  * is sufficiently wide to hold a function pointer.
114  */
115 typedef long (*state_func_t)(void);
116 typedef state_func_t (*state_t)(void);
117
118 static state_func_t single_user(void);
119 static state_func_t runcom(void);
120 static state_func_t read_ttys(void);
121 static state_func_t multi_user(void);
122 static state_func_t clean_ttys(void);
123 static state_func_t catatonia(void);
124 static state_func_t death(void);
125 static state_func_t death_single(void);
126
127 static state_func_t run_script(const char *);
128
129 enum { AUTOBOOT, FASTBOOT } runcom_mode = AUTOBOOT;
130 #define FALSE   0
131 #define TRUE    1
132
133 int Reboot = FALSE;
134 int howto = RB_AUTOBOOT;
135
136 int devfs;
137
138 static void transition(state_t);
139 static state_t requested_transition;
140 static state_t current_state = death_single;
141
142 static void open_console(void);
143 static const char *get_shell(void);
144 static void write_stderr(const char *message);
145
146 typedef struct init_session {
147         int     se_index;               /* index of entry in ttys file */
148         pid_t   se_process;             /* controlling process */
149         time_t  se_started;             /* used to avoid thrashing */
150         int     se_flags;               /* status of session */
151 #define SE_SHUTDOWN     0x1             /* session won't be restarted */
152 #define SE_PRESENT      0x2             /* session is in /etc/ttys */
153         int     se_nspace;              /* spacing count */
154         char    *se_device;             /* filename of port */
155         char    *se_getty;              /* what to run on that port */
156         char    *se_getty_argv_space;   /* pre-parsed argument array space */
157         char    **se_getty_argv;        /* pre-parsed argument array */
158         char    *se_window;             /* window system (started only once) */
159         char    *se_window_argv_space;  /* pre-parsed argument array space */
160         char    **se_window_argv;       /* pre-parsed argument array */
161         char    *se_type;               /* default terminal type */
162         struct  init_session *se_prev;
163         struct  init_session *se_next;
164 } session_t;
165
166 static void free_session(session_t *);
167 static session_t *new_session(session_t *, int, struct ttyent *);
168 static session_t *sessions;
169
170 static char **construct_argv(char *);
171 static void start_window_system(session_t *);
172 static void collect_child(pid_t);
173 static pid_t start_getty(session_t *);
174 static void transition_handler(int);
175 static void alrm_handler(int);
176 static void setsecuritylevel(int);
177 static int getsecuritylevel(void);
178 static int setupargv(session_t *, struct ttyent *);
179 #ifdef LOGIN_CAP
180 static void setprocresources(const char *);
181 #endif
182 static int clang;
183
184 static void clear_session_logs(session_t *);
185
186 static int start_session_db(void);
187 static void add_session(session_t *);
188 static void del_session(session_t *);
189 static session_t *find_session(pid_t);
190 static DB *session_db;
191
192 /*
193  * The mother of all processes.
194  */
195 int
196 main(int argc, char *argv[])
197 {
198         state_t initial_transition = runcom;
199         char kenv_value[PATH_MAX];
200         int c;
201         struct sigaction sa;
202         sigset_t mask;
203
204         /* Dispose of random users. */
205         if (getuid() != 0)
206                 errx(1, "%s", strerror(EPERM));
207
208         /* System V users like to reexec init. */
209         if (getpid() != 1) {
210 #ifdef COMPAT_SYSV_INIT
211                 /* So give them what they want */
212                 if (argc > 1) {
213                         if (strlen(argv[1]) == 1) {
214                                 char runlevel = *argv[1];
215                                 int sig;
216
217                                 switch (runlevel) {
218                                 case '0': /* halt + poweroff */
219                                         sig = SIGUSR2;
220                                         break;
221                                 case '1': /* single-user */
222                                         sig = SIGTERM;
223                                         break;
224                                 case '6': /* reboot */
225                                         sig = SIGINT;
226                                         break;
227                                 case 'c': /* block further logins */
228                                         sig = SIGTSTP;
229                                         break;
230                                 case 'q': /* rescan /etc/ttys */
231                                         sig = SIGHUP;
232                                         break;
233                                 default:
234                                         goto invalid;
235                                 }
236                                 kill(1, sig);
237                                 _exit(0);
238                         } else
239 invalid:
240                                 errx(1, "invalid run-level ``%s''", argv[1]);
241                 } else
242 #endif
243                         errx(1, "already running");
244         }
245         /*
246          * Note that this does NOT open a file...
247          * Does 'init' deserve its own facility number?
248          */
249         openlog("init", LOG_CONS|LOG_ODELAY, LOG_AUTH);
250
251         /*
252          * Create an initial session.
253          */
254         if (setsid() < 0)
255                 warning("initial setsid() failed: %m");
256
257         /*
258          * Establish an initial user so that programs running
259          * single user do not freak out and die (like passwd).
260          */
261         if (setlogin("root") < 0)
262                 warning("setlogin() failed: %m");
263
264         /*
265          * This code assumes that we always get arguments through flags,
266          * never through bits set in some random machine register.
267          */
268         while ((c = getopt(argc, argv, "dsf")) != -1)
269                 switch (c) {
270                 case 'd':
271                         devfs = 1;
272                         break;
273                 case 's':
274                         initial_transition = single_user;
275                         break;
276                 case 'f':
277                         runcom_mode = FASTBOOT;
278                         break;
279                 default:
280                         warning("unrecognized flag '-%c'", c);
281                         break;
282                 }
283
284         if (optind != argc)
285                 warning("ignoring excess arguments");
286
287         /*
288          * We catch or block signals rather than ignore them,
289          * so that they get reset on exec.
290          */
291         handle(badsys, SIGSYS, 0);
292         handle(disaster, SIGABRT, SIGFPE, SIGILL, SIGSEGV, SIGBUS, SIGXCPU,
293             SIGXFSZ, 0);
294         handle(transition_handler, SIGHUP, SIGINT, SIGTERM, SIGTSTP, SIGUSR1,
295             SIGUSR2, 0);
296         handle(alrm_handler, SIGALRM, 0);
297         sigfillset(&mask);
298         delset(&mask, SIGABRT, SIGFPE, SIGILL, SIGSEGV, SIGBUS, SIGSYS,
299             SIGXCPU, SIGXFSZ, SIGHUP, SIGINT, SIGTERM, SIGTSTP, SIGALRM,
300             SIGUSR1, SIGUSR2, 0);
301         sigprocmask(SIG_SETMASK, &mask, (sigset_t *) 0);
302         sigemptyset(&sa.sa_mask);
303         sa.sa_flags = 0;
304         sa.sa_handler = SIG_IGN;
305         sigaction(SIGTTIN, &sa, (struct sigaction *)0);
306         sigaction(SIGTTOU, &sa, (struct sigaction *)0);
307
308         /*
309          * Paranoia.
310          */
311         close(0);
312         close(1);
313         close(2);
314
315         if (kenv(KENV_GET, "init_script", kenv_value, sizeof(kenv_value)) > 0) {
316                 state_func_t next_transition;
317
318                 if ((next_transition = run_script(kenv_value)) != 0)
319                         initial_transition = (state_t) next_transition;
320         }
321
322         if (kenv(KENV_GET, "init_chroot", kenv_value, sizeof(kenv_value)) > 0) {
323                 if (chdir(kenv_value) != 0 || chroot(".") != 0)
324                         warning("Can't chroot to %s: %m", kenv_value);
325         }
326
327         /*
328          * Additional check if devfs needs to be mounted:
329          * If "/" and "/dev" have the same device number,
330          * then it hasn't been mounted yet.
331          */
332         if (!devfs) {
333                 struct stat stst;
334                 dev_t root_devno;
335
336                 stat("/", &stst);
337                 root_devno = stst.st_dev;
338                 if (stat("/dev", &stst) != 0)
339                         warning("Can't stat /dev: %m");
340                 else if (stst.st_dev == root_devno)
341                         devfs++;
342         }
343
344         if (devfs) {
345                 struct iovec iov[4];
346                 char *s;
347                 int i;
348
349                 char _fstype[]  = "fstype";
350                 char _devfs[]   = "devfs";
351                 char _fspath[]  = "fspath";
352                 char _path_dev[]= _PATH_DEV;
353
354                 iov[0].iov_base = _fstype;
355                 iov[0].iov_len = sizeof(_fstype);
356                 iov[1].iov_base = _devfs;
357                 iov[1].iov_len = sizeof(_devfs);
358                 iov[2].iov_base = _fspath;
359                 iov[2].iov_len = sizeof(_fspath);
360                 /*
361                  * Try to avoid the trailing slash in _PATH_DEV.
362                  * Be *very* defensive.
363                  */
364                 s = strdup(_PATH_DEV);
365                 if (s != NULL) {
366                         i = strlen(s);
367                         if (i > 0 && s[i - 1] == '/')
368                                 s[i - 1] = '\0';
369                         iov[3].iov_base = s;
370                         iov[3].iov_len = strlen(s) + 1;
371                 } else {
372                         iov[3].iov_base = _path_dev;
373                         iov[3].iov_len = sizeof(_path_dev);
374                 }
375                 nmount(iov, 4, 0);
376                 if (s != NULL)
377                         free(s);
378         }
379
380         /*
381          * Start the state machine.
382          */
383         transition(initial_transition);
384
385         /*
386          * Should never reach here.
387          */
388         return 1;
389 }
390
391 /*
392  * Associate a function with a signal handler.
393  */
394 static void
395 handle(sig_t handler, ...)
396 {
397         int sig;
398         struct sigaction sa;
399         sigset_t mask_everything;
400         va_list ap;
401         va_start(ap, handler);
402
403         sa.sa_handler = handler;
404         sigfillset(&mask_everything);
405
406         while ((sig = va_arg(ap, int)) != 0) {
407                 sa.sa_mask = mask_everything;
408                 /* XXX SA_RESTART? */
409                 sa.sa_flags = sig == SIGCHLD ? SA_NOCLDSTOP : 0;
410                 sigaction(sig, &sa, (struct sigaction *) 0);
411         }
412         va_end(ap);
413 }
414
415 /*
416  * Delete a set of signals from a mask.
417  */
418 static void
419 delset(sigset_t *maskp, ...)
420 {
421         int sig;
422         va_list ap;
423         va_start(ap, maskp);
424
425         while ((sig = va_arg(ap, int)) != 0)
426                 sigdelset(maskp, sig);
427         va_end(ap);
428 }
429
430 /*
431  * Log a message and sleep for a while (to give someone an opportunity
432  * to read it and to save log or hardcopy output if the problem is chronic).
433  * NB: should send a message to the session logger to avoid blocking.
434  */
435 static void
436 stall(const char *message, ...)
437 {
438         va_list ap;
439         va_start(ap, message);
440
441         vsyslog(LOG_ALERT, message, ap);
442         va_end(ap);
443         sleep(STALL_TIMEOUT);
444 }
445
446 /*
447  * Like stall(), but doesn't sleep.
448  * If cpp had variadic macros, the two functions could be #defines for another.
449  * NB: should send a message to the session logger to avoid blocking.
450  */
451 static void
452 warning(const char *message, ...)
453 {
454         va_list ap;
455         va_start(ap, message);
456
457         vsyslog(LOG_ALERT, message, ap);
458         va_end(ap);
459 }
460
461 /*
462  * Log an emergency message.
463  * NB: should send a message to the session logger to avoid blocking.
464  */
465 static void
466 emergency(const char *message, ...)
467 {
468         va_list ap;
469         va_start(ap, message);
470
471         vsyslog(LOG_EMERG, message, ap);
472         va_end(ap);
473 }
474
475 /*
476  * Catch a SIGSYS signal.
477  *
478  * These may arise if a system does not support sysctl.
479  * We tolerate up to 25 of these, then throw in the towel.
480  */
481 static void
482 badsys(int sig)
483 {
484         static int badcount = 0;
485
486         if (badcount++ < 25)
487                 return;
488         disaster(sig);
489 }
490
491 /*
492  * Catch an unexpected signal.
493  */
494 static void
495 disaster(int sig)
496 {
497
498         emergency("fatal signal: %s",
499             (unsigned)sig < NSIG ? sys_siglist[sig] : "unknown signal");
500
501         sleep(STALL_TIMEOUT);
502         _exit(sig);             /* reboot */
503 }
504
505 /*
506  * Get the security level of the kernel.
507  */
508 static int
509 getsecuritylevel(void)
510 {
511 #ifdef KERN_SECURELVL
512         int name[2], curlevel;
513         size_t len;
514
515         name[0] = CTL_KERN;
516         name[1] = KERN_SECURELVL;
517         len = sizeof curlevel;
518         if (sysctl(name, 2, &curlevel, &len, NULL, 0) == -1) {
519                 emergency("cannot get kernel security level: %s",
520                     strerror(errno));
521                 return (-1);
522         }
523         return (curlevel);
524 #else
525         return (-1);
526 #endif
527 }
528
529 /*
530  * Set the security level of the kernel.
531  */
532 static void
533 setsecuritylevel(int newlevel)
534 {
535 #ifdef KERN_SECURELVL
536         int name[2], curlevel;
537
538         curlevel = getsecuritylevel();
539         if (newlevel == curlevel)
540                 return;
541         name[0] = CTL_KERN;
542         name[1] = KERN_SECURELVL;
543         if (sysctl(name, 2, NULL, NULL, &newlevel, sizeof newlevel) == -1) {
544                 emergency(
545                     "cannot change kernel security level from %d to %d: %s",
546                     curlevel, newlevel, strerror(errno));
547                 return;
548         }
549 #ifdef SECURE
550         warning("kernel security level changed from %d to %d",
551             curlevel, newlevel);
552 #endif
553 #endif
554 }
555
556 /*
557  * Change states in the finite state machine.
558  * The initial state is passed as an argument.
559  */
560 static void
561 transition(state_t s)
562 {
563
564         current_state = s;
565         for (;;)
566                 current_state = (state_t) (*current_state)();
567 }
568
569 /*
570  * Close out the accounting files for a login session.
571  * NB: should send a message to the session logger to avoid blocking.
572  */
573 static void
574 clear_session_logs(session_t *sp __unused)
575 {
576
577         /*
578          * XXX: Use getutxline() and call pututxline() for each entry.
579          * Is this safe to do this here?  Is it really required anyway?
580          */
581 }
582
583 /*
584  * Start a session and allocate a controlling terminal.
585  * Only called by children of init after forking.
586  */
587 static void
588 open_console(void)
589 {
590         int fd;
591
592         /*
593          * Try to open /dev/console.  Open the device with O_NONBLOCK to
594          * prevent potential blocking on a carrier.
595          */
596         revoke(_PATH_CONSOLE);
597         if ((fd = open(_PATH_CONSOLE, O_RDWR | O_NONBLOCK)) != -1) {
598                 (void)fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) & ~O_NONBLOCK);
599                 if (login_tty(fd) == 0)
600                         return;
601                 close(fd);
602         }
603
604         /* No luck.  Log output to file if possible. */
605         if ((fd = open(_PATH_DEVNULL, O_RDWR)) == -1) {
606                 stall("cannot open null device.");
607                 _exit(1);
608         }
609         if (fd != STDIN_FILENO) {
610                 dup2(fd, STDIN_FILENO);
611                 close(fd);
612         }
613         fd = open(_PATH_INITLOG, O_WRONLY | O_APPEND | O_CREAT, 0644);
614         if (fd == -1)
615                 dup2(STDIN_FILENO, STDOUT_FILENO);
616         else if (fd != STDOUT_FILENO) {
617                 dup2(fd, STDOUT_FILENO);
618                 close(fd);
619         }
620         dup2(STDOUT_FILENO, STDERR_FILENO);
621 }
622
623 static const char *
624 get_shell(void)
625 {
626         static char kenv_value[PATH_MAX];
627
628         if (kenv(KENV_GET, "init_shell", kenv_value, sizeof(kenv_value)) > 0)
629                 return kenv_value;
630         else
631                 return _PATH_BSHELL;
632 }
633
634 static void
635 write_stderr(const char *message)
636 {
637
638         write(STDERR_FILENO, message, strlen(message));
639 }
640
641 /*
642  * Bring the system up single user.
643  */
644 static state_func_t
645 single_user(void)
646 {
647         pid_t pid, wpid;
648         int status;
649         sigset_t mask;
650         const char *shell;
651         char *argv[2];
652 #ifdef SECURE
653         struct ttyent *typ;
654         struct passwd *pp;
655         static const char banner[] =
656                 "Enter root password, or ^D to go multi-user\n";
657         char *clear, *password;
658 #endif
659 #ifdef DEBUGSHELL
660         char altshell[128];
661 #endif
662
663         if (Reboot) {
664                 /* Instead of going single user, let's reboot the machine */
665                 sync();
666                 alarm(2);
667                 pause();
668                 reboot(howto);
669                 _exit(0);
670         }
671
672         shell = get_shell();
673
674         if ((pid = fork()) == 0) {
675                 /*
676                  * Start the single user session.
677                  */
678                 open_console();
679
680 #ifdef SECURE
681                 /*
682                  * Check the root password.
683                  * We don't care if the console is 'on' by default;
684                  * it's the only tty that can be 'off' and 'secure'.
685                  */
686                 typ = getttynam("console");
687                 pp = getpwnam("root");
688                 if (typ && (typ->ty_status & TTY_SECURE) == 0 &&
689                     pp && *pp->pw_passwd) {
690                         write_stderr(banner);
691                         for (;;) {
692                                 clear = getpass("Password:");
693                                 if (clear == 0 || *clear == '\0')
694                                         _exit(0);
695                                 password = crypt(clear, pp->pw_passwd);
696                                 bzero(clear, _PASSWORD_LEN);
697                                 if (strcmp(password, pp->pw_passwd) == 0)
698                                         break;
699                                 warning("single-user login failed\n");
700                         }
701                 }
702                 endttyent();
703                 endpwent();
704 #endif /* SECURE */
705
706 #ifdef DEBUGSHELL
707                 {
708                         char *cp = altshell;
709                         int num;
710
711 #define SHREQUEST "Enter full pathname of shell or RETURN for "
712                         write_stderr(SHREQUEST);
713                         write_stderr(shell);
714                         write_stderr(": ");
715                         while ((num = read(STDIN_FILENO, cp, 1)) != -1 &&
716                             num != 0 && *cp != '\n' && cp < &altshell[127])
717                                 cp++;
718                         *cp = '\0';
719                         if (altshell[0] != '\0')
720                                 shell = altshell;
721                 }
722 #endif /* DEBUGSHELL */
723
724                 /*
725                  * Unblock signals.
726                  * We catch all the interesting ones,
727                  * and those are reset to SIG_DFL on exec.
728                  */
729                 sigemptyset(&mask);
730                 sigprocmask(SIG_SETMASK, &mask, (sigset_t *) 0);
731
732                 /*
733                  * Fire off a shell.
734                  * If the default one doesn't work, try the Bourne shell.
735                  */
736
737                 char name[] = "-sh";
738
739                 argv[0] = name;
740                 argv[1] = 0;
741                 execv(shell, argv);
742                 emergency("can't exec %s for single user: %m", shell);
743                 execv(_PATH_BSHELL, argv);
744                 emergency("can't exec %s for single user: %m", _PATH_BSHELL);
745                 sleep(STALL_TIMEOUT);
746                 _exit(1);
747         }
748
749         if (pid == -1) {
750                 /*
751                  * We are seriously hosed.  Do our best.
752                  */
753                 emergency("can't fork single-user shell, trying again");
754                 while (waitpid(-1, (int *) 0, WNOHANG) > 0)
755                         continue;
756                 return (state_func_t) single_user;
757         }
758
759         requested_transition = 0;
760         do {
761                 if ((wpid = waitpid(-1, &status, WUNTRACED)) != -1)
762                         collect_child(wpid);
763                 if (wpid == -1) {
764                         if (errno == EINTR)
765                                 continue;
766                         warning("wait for single-user shell failed: %m; restarting");
767                         return (state_func_t) single_user;
768                 }
769                 if (wpid == pid && WIFSTOPPED(status)) {
770                         warning("init: shell stopped, restarting\n");
771                         kill(pid, SIGCONT);
772                         wpid = -1;
773                 }
774         } while (wpid != pid && !requested_transition);
775
776         if (requested_transition)
777                 return (state_func_t) requested_transition;
778
779         if (!WIFEXITED(status)) {
780                 if (WTERMSIG(status) == SIGKILL) {
781                         /*
782                          *  reboot(8) killed shell?
783                          */
784                         warning("single user shell terminated.");
785                         sleep(STALL_TIMEOUT);
786                         _exit(0);
787                 } else {
788                         warning("single user shell terminated, restarting");
789                         return (state_func_t) single_user;
790                 }
791         }
792
793         runcom_mode = FASTBOOT;
794         return (state_func_t) runcom;
795 }
796
797 /*
798  * Run the system startup script.
799  */
800 static state_func_t
801 runcom(void)
802 {
803         struct utmpx utx;
804         state_func_t next_transition;
805
806         if ((next_transition = run_script(_PATH_RUNCOM)) != 0)
807                 return next_transition;
808
809         runcom_mode = AUTOBOOT;         /* the default */
810         /* NB: should send a message to the session logger to avoid blocking. */
811         utx.ut_type = BOOT_TIME;
812         gettimeofday(&utx.ut_tv, NULL);
813         pututxline(&utx);
814         return (state_func_t) read_ttys;
815 }
816
817 /*
818  * Run a shell script.
819  * Returns 0 on success, otherwise the next transition to enter:
820  *  - single_user if fork/execv/waitpid failed, or if the script
821  *    terminated with a signal or exit code != 0.
822  *  - death_single if a SIGTERM was delivered to init(8).
823  */
824 static state_func_t
825 run_script(const char *script)
826 {
827         pid_t pid, wpid;
828         int status;
829         char *argv[4];
830         const char *shell;
831         struct sigaction sa;
832
833         shell = get_shell();
834
835         if ((pid = fork()) == 0) {
836                 sigemptyset(&sa.sa_mask);
837                 sa.sa_flags = 0;
838                 sa.sa_handler = SIG_IGN;
839                 sigaction(SIGTSTP, &sa, (struct sigaction *)0);
840                 sigaction(SIGHUP, &sa, (struct sigaction *)0);
841
842                 open_console();
843
844                 char _sh[]              = "sh";
845                 char _autoboot[]        = "autoboot";
846
847                 argv[0] = _sh;
848                 argv[1] = __DECONST(char *, script);
849                 argv[2] = runcom_mode == AUTOBOOT ? _autoboot : 0;
850                 argv[3] = 0;
851
852                 sigprocmask(SIG_SETMASK, &sa.sa_mask, (sigset_t *) 0);
853
854 #ifdef LOGIN_CAP
855                 setprocresources(RESOURCE_RC);
856 #endif
857                 execv(shell, argv);
858                 stall("can't exec %s for %s: %m", shell, script);
859                 _exit(1);       /* force single user mode */
860         }
861
862         if (pid == -1) {
863                 emergency("can't fork for %s on %s: %m", shell, script);
864                 while (waitpid(-1, (int *) 0, WNOHANG) > 0)
865                         continue;
866                 sleep(STALL_TIMEOUT);
867                 return (state_func_t) single_user;
868         }
869
870         /*
871          * Copied from single_user().  This is a bit paranoid.
872          */
873         requested_transition = 0;
874         do {
875                 if ((wpid = waitpid(-1, &status, WUNTRACED)) != -1)
876                         collect_child(wpid);
877                 if (wpid == -1) {
878                         if (requested_transition == death_single)
879                                 return (state_func_t) death_single;
880                         if (errno == EINTR)
881                                 continue;
882                         warning("wait for %s on %s failed: %m; going to "
883                             "single user mode", shell, script);
884                         return (state_func_t) single_user;
885                 }
886                 if (wpid == pid && WIFSTOPPED(status)) {
887                         warning("init: %s on %s stopped, restarting\n",
888                             shell, script);
889                         kill(pid, SIGCONT);
890                         wpid = -1;
891                 }
892         } while (wpid != pid);
893
894         if (WIFSIGNALED(status) && WTERMSIG(status) == SIGTERM &&
895             requested_transition == catatonia) {
896                 /* /etc/rc executed /sbin/reboot; wait for the end quietly */
897                 sigset_t s;
898
899                 sigfillset(&s);
900                 for (;;)
901                         sigsuspend(&s);
902         }
903
904         if (!WIFEXITED(status)) {
905                 warning("%s on %s terminated abnormally, going to single "
906                     "user mode", shell, script);
907                 return (state_func_t) single_user;
908         }
909
910         if (WEXITSTATUS(status))
911                 return (state_func_t) single_user;
912
913         return (state_func_t) 0;
914 }
915
916 /*
917  * Open the session database.
918  *
919  * NB: We could pass in the size here; is it necessary?
920  */
921 static int
922 start_session_db(void)
923 {
924         if (session_db && (*session_db->close)(session_db))
925                 emergency("session database close: %s", strerror(errno));
926         if ((session_db = dbopen(NULL, O_RDWR, 0, DB_HASH, NULL)) == 0) {
927                 emergency("session database open: %s", strerror(errno));
928                 return (1);
929         }
930         return (0);
931
932 }
933
934 /*
935  * Add a new login session.
936  */
937 static void
938 add_session(session_t *sp)
939 {
940         DBT key;
941         DBT data;
942
943         key.data = &sp->se_process;
944         key.size = sizeof sp->se_process;
945         data.data = &sp;
946         data.size = sizeof sp;
947
948         if ((*session_db->put)(session_db, &key, &data, 0))
949                 emergency("insert %d: %s", sp->se_process, strerror(errno));
950 }
951
952 /*
953  * Delete an old login session.
954  */
955 static void
956 del_session(session_t *sp)
957 {
958         DBT key;
959
960         key.data = &sp->se_process;
961         key.size = sizeof sp->se_process;
962
963         if ((*session_db->del)(session_db, &key, 0))
964                 emergency("delete %d: %s", sp->se_process, strerror(errno));
965 }
966
967 /*
968  * Look up a login session by pid.
969  */
970 static session_t *
971 find_session(pid_t pid)
972 {
973         DBT key;
974         DBT data;
975         session_t *ret;
976
977         key.data = &pid;
978         key.size = sizeof pid;
979         if ((*session_db->get)(session_db, &key, &data, 0) != 0)
980                 return 0;
981         bcopy(data.data, (char *)&ret, sizeof(ret));
982         return ret;
983 }
984
985 /*
986  * Construct an argument vector from a command line.
987  */
988 static char **
989 construct_argv(char *command)
990 {
991         int argc = 0;
992         char **argv = (char **) malloc(((strlen(command) + 1) / 2 + 1)
993                                                 * sizeof (char *));
994
995         if ((argv[argc++] = strk(command)) == 0) {
996                 free(argv);
997                 return (NULL);
998         }
999         while ((argv[argc++] = strk((char *) 0)) != NULL)
1000                 continue;
1001         return argv;
1002 }
1003
1004 /*
1005  * Deallocate a session descriptor.
1006  */
1007 static void
1008 free_session(session_t *sp)
1009 {
1010         free(sp->se_device);
1011         if (sp->se_getty) {
1012                 free(sp->se_getty);
1013                 free(sp->se_getty_argv_space);
1014                 free(sp->se_getty_argv);
1015         }
1016         if (sp->se_window) {
1017                 free(sp->se_window);
1018                 free(sp->se_window_argv_space);
1019                 free(sp->se_window_argv);
1020         }
1021         if (sp->se_type)
1022                 free(sp->se_type);
1023         free(sp);
1024 }
1025
1026 /*
1027  * Allocate a new session descriptor.
1028  * Mark it SE_PRESENT.
1029  */
1030 static session_t *
1031 new_session(session_t *sprev, int session_index, struct ttyent *typ)
1032 {
1033         session_t *sp;
1034         int fd;
1035
1036         if ((typ->ty_status & TTY_ON) == 0 ||
1037             typ->ty_name == 0 ||
1038             typ->ty_getty == 0)
1039                 return 0;
1040
1041         sp = (session_t *) calloc(1, sizeof (session_t));
1042
1043         sp->se_index = session_index;
1044         sp->se_flags |= SE_PRESENT;
1045
1046         sp->se_device = malloc(sizeof(_PATH_DEV) + strlen(typ->ty_name));
1047         sprintf(sp->se_device, "%s%s", _PATH_DEV, typ->ty_name);
1048
1049         /*
1050          * Attempt to open the device, if we get "device not configured"
1051          * then don't add the device to the session list.
1052          */
1053         if ((fd = open(sp->se_device, O_RDONLY | O_NONBLOCK, 0)) < 0) {
1054                 if (errno == ENXIO) {
1055                         free_session(sp);
1056                         return (0);
1057                 }
1058         } else
1059                 close(fd);
1060
1061         if (setupargv(sp, typ) == 0) {
1062                 free_session(sp);
1063                 return (0);
1064         }
1065
1066         sp->se_next = 0;
1067         if (sprev == 0) {
1068                 sessions = sp;
1069                 sp->se_prev = 0;
1070         } else {
1071                 sprev->se_next = sp;
1072                 sp->se_prev = sprev;
1073         }
1074
1075         return sp;
1076 }
1077
1078 /*
1079  * Calculate getty and if useful window argv vectors.
1080  */
1081 static int
1082 setupargv(session_t *sp, struct ttyent *typ)
1083 {
1084
1085         if (sp->se_getty) {
1086                 free(sp->se_getty);
1087                 free(sp->se_getty_argv_space);
1088                 free(sp->se_getty_argv);
1089         }
1090         sp->se_getty = malloc(strlen(typ->ty_getty) + strlen(typ->ty_name) + 2);
1091         sprintf(sp->se_getty, "%s %s", typ->ty_getty, typ->ty_name);
1092         sp->se_getty_argv_space = strdup(sp->se_getty);
1093         sp->se_getty_argv = construct_argv(sp->se_getty_argv_space);
1094         if (sp->se_getty_argv == 0) {
1095                 warning("can't parse getty for port %s", sp->se_device);
1096                 free(sp->se_getty);
1097                 free(sp->se_getty_argv_space);
1098                 sp->se_getty = sp->se_getty_argv_space = 0;
1099                 return (0);
1100         }
1101         if (sp->se_window) {
1102                 free(sp->se_window);
1103                 free(sp->se_window_argv_space);
1104                 free(sp->se_window_argv);
1105         }
1106         sp->se_window = sp->se_window_argv_space = 0;
1107         sp->se_window_argv = 0;
1108         if (typ->ty_window) {
1109                 sp->se_window = strdup(typ->ty_window);
1110                 sp->se_window_argv_space = strdup(sp->se_window);
1111                 sp->se_window_argv = construct_argv(sp->se_window_argv_space);
1112                 if (sp->se_window_argv == 0) {
1113                         warning("can't parse window for port %s",
1114                             sp->se_device);
1115                         free(sp->se_window_argv_space);
1116                         free(sp->se_window);
1117                         sp->se_window = sp->se_window_argv_space = 0;
1118                         return (0);
1119                 }
1120         }
1121         if (sp->se_type)
1122                 free(sp->se_type);
1123         sp->se_type = typ->ty_type ? strdup(typ->ty_type) : 0;
1124         return (1);
1125 }
1126
1127 /*
1128  * Walk the list of ttys and create sessions for each active line.
1129  */
1130 static state_func_t
1131 read_ttys(void)
1132 {
1133         int session_index = 0;
1134         session_t *sp, *snext;
1135         struct ttyent *typ;
1136
1137         /*
1138          * Destroy any previous session state.
1139          * There shouldn't be any, but just in case...
1140          */
1141         for (sp = sessions; sp; sp = snext) {
1142                 if (sp->se_process)
1143                         clear_session_logs(sp);
1144                 snext = sp->se_next;
1145                 free_session(sp);
1146         }
1147         sessions = 0;
1148         if (start_session_db())
1149                 return (state_func_t) single_user;
1150
1151         /*
1152          * Allocate a session entry for each active port.
1153          * Note that sp starts at 0.
1154          */
1155         while ((typ = getttyent()) != NULL)
1156                 if ((snext = new_session(sp, ++session_index, typ)) != NULL)
1157                         sp = snext;
1158
1159         endttyent();
1160
1161         return (state_func_t) multi_user;
1162 }
1163
1164 /*
1165  * Start a window system running.
1166  */
1167 static void
1168 start_window_system(session_t *sp)
1169 {
1170         pid_t pid;
1171         sigset_t mask;
1172         char term[64], *env[2];
1173         int status;
1174
1175         if ((pid = fork()) == -1) {
1176                 emergency("can't fork for window system on port %s: %m",
1177                     sp->se_device);
1178                 /* hope that getty fails and we can try again */
1179                 return;
1180         }
1181         if (pid) {
1182                 waitpid(-1, &status, 0);
1183                 return;
1184         }
1185
1186         /* reparent window process to the init to not make a zombie on exit */
1187         if ((pid = fork()) == -1) {
1188                 emergency("can't fork for window system on port %s: %m",
1189                     sp->se_device);
1190                 _exit(1);
1191         }
1192         if (pid)
1193                 _exit(0);
1194
1195         sigemptyset(&mask);
1196         sigprocmask(SIG_SETMASK, &mask, (sigset_t *) 0);
1197
1198         if (setsid() < 0)
1199                 emergency("setsid failed (window) %m");
1200
1201 #ifdef LOGIN_CAP
1202         setprocresources(RESOURCE_WINDOW);
1203 #endif
1204         if (sp->se_type) {
1205                 /* Don't use malloc after fork */
1206                 strcpy(term, "TERM=");
1207                 strncat(term, sp->se_type, sizeof(term) - 6);
1208                 env[0] = term;
1209                 env[1] = 0;
1210         }
1211         else
1212                 env[0] = 0;
1213         execve(sp->se_window_argv[0], sp->se_window_argv, env);
1214         stall("can't exec window system '%s' for port %s: %m",
1215                 sp->se_window_argv[0], sp->se_device);
1216         _exit(1);
1217 }
1218
1219 /*
1220  * Start a login session running.
1221  */
1222 static pid_t
1223 start_getty(session_t *sp)
1224 {
1225         pid_t pid;
1226         sigset_t mask;
1227         time_t current_time = time((time_t *) 0);
1228         int too_quick = 0;
1229         char term[64], *env[2];
1230
1231         if (current_time >= sp->se_started &&
1232             current_time - sp->se_started < GETTY_SPACING) {
1233                 if (++sp->se_nspace > GETTY_NSPACE) {
1234                         sp->se_nspace = 0;
1235                         too_quick = 1;
1236                 }
1237         } else
1238                 sp->se_nspace = 0;
1239
1240         /*
1241          * fork(), not vfork() -- we can't afford to block.
1242          */
1243         if ((pid = fork()) == -1) {
1244                 emergency("can't fork for getty on port %s: %m", sp->se_device);
1245                 return -1;
1246         }
1247
1248         if (pid)
1249                 return pid;
1250
1251         if (too_quick) {
1252                 warning("getty repeating too quickly on port %s, sleeping %d secs",
1253                     sp->se_device, GETTY_SLEEP);
1254                 sleep((unsigned) GETTY_SLEEP);
1255         }
1256
1257         if (sp->se_window) {
1258                 start_window_system(sp);
1259                 sleep(WINDOW_WAIT);
1260         }
1261
1262         sigemptyset(&mask);
1263         sigprocmask(SIG_SETMASK, &mask, (sigset_t *) 0);
1264
1265 #ifdef LOGIN_CAP
1266         setprocresources(RESOURCE_GETTY);
1267 #endif
1268         if (sp->se_type) {
1269                 /* Don't use malloc after fork */
1270                 strcpy(term, "TERM=");
1271                 strncat(term, sp->se_type, sizeof(term) - 6);
1272                 env[0] = term;
1273                 env[1] = 0;
1274         } else
1275                 env[0] = 0;
1276         execve(sp->se_getty_argv[0], sp->se_getty_argv, env);
1277         stall("can't exec getty '%s' for port %s: %m",
1278                 sp->se_getty_argv[0], sp->se_device);
1279         _exit(1);
1280 }
1281
1282 /*
1283  * Collect exit status for a child.
1284  * If an exiting login, start a new login running.
1285  */
1286 static void
1287 collect_child(pid_t pid)
1288 {
1289         session_t *sp, *sprev, *snext;
1290
1291         if (! sessions)
1292                 return;
1293
1294         if (! (sp = find_session(pid)))
1295                 return;
1296
1297         clear_session_logs(sp);
1298         del_session(sp);
1299         sp->se_process = 0;
1300
1301         if (sp->se_flags & SE_SHUTDOWN) {
1302                 if ((sprev = sp->se_prev) != NULL)
1303                         sprev->se_next = sp->se_next;
1304                 else
1305                         sessions = sp->se_next;
1306                 if ((snext = sp->se_next) != NULL)
1307                         snext->se_prev = sp->se_prev;
1308                 free_session(sp);
1309                 return;
1310         }
1311
1312         if ((pid = start_getty(sp)) == -1) {
1313                 /* serious trouble */
1314                 requested_transition = clean_ttys;
1315                 return;
1316         }
1317
1318         sp->se_process = pid;
1319         sp->se_started = time((time_t *) 0);
1320         add_session(sp);
1321 }
1322
1323 /*
1324  * Catch a signal and request a state transition.
1325  */
1326 static void
1327 transition_handler(int sig)
1328 {
1329
1330         switch (sig) {
1331         case SIGHUP:
1332                 if (current_state == read_ttys || current_state == multi_user ||
1333                     current_state == clean_ttys || current_state == catatonia)
1334                         requested_transition = clean_ttys;
1335                 break;
1336         case SIGUSR2:
1337                 howto = RB_POWEROFF;
1338         case SIGUSR1:
1339                 howto |= RB_HALT;
1340         case SIGINT:
1341                 Reboot = TRUE;
1342         case SIGTERM:
1343                 if (current_state == read_ttys || current_state == multi_user ||
1344                     current_state == clean_ttys || current_state == catatonia)
1345                         requested_transition = death;
1346                 else
1347                         requested_transition = death_single;
1348                 break;
1349         case SIGTSTP:
1350                 if (current_state == runcom || current_state == read_ttys ||
1351                     current_state == clean_ttys ||
1352                     current_state == multi_user || current_state == catatonia)
1353                         requested_transition = catatonia;
1354                 break;
1355         default:
1356                 requested_transition = 0;
1357                 break;
1358         }
1359 }
1360
1361 /*
1362  * Take the system multiuser.
1363  */
1364 static state_func_t
1365 multi_user(void)
1366 {
1367         pid_t pid;
1368         session_t *sp;
1369
1370         requested_transition = 0;
1371
1372         /*
1373          * If the administrator has not set the security level to -1
1374          * to indicate that the kernel should not run multiuser in secure
1375          * mode, and the run script has not set a higher level of security
1376          * than level 1, then put the kernel into secure mode.
1377          */
1378         if (getsecuritylevel() == 0)
1379                 setsecuritylevel(1);
1380
1381         for (sp = sessions; sp; sp = sp->se_next) {
1382                 if (sp->se_process)
1383                         continue;
1384                 if ((pid = start_getty(sp)) == -1) {
1385                         /* serious trouble */
1386                         requested_transition = clean_ttys;
1387                         break;
1388                 }
1389                 sp->se_process = pid;
1390                 sp->se_started = time((time_t *) 0);
1391                 add_session(sp);
1392         }
1393
1394         while (!requested_transition)
1395                 if ((pid = waitpid(-1, (int *) 0, 0)) != -1)
1396                         collect_child(pid);
1397
1398         return (state_func_t) requested_transition;
1399 }
1400
1401 /*
1402  * This is an (n*2)+(n^2) algorithm.  We hope it isn't run often...
1403  */
1404 static state_func_t
1405 clean_ttys(void)
1406 {
1407         session_t *sp, *sprev;
1408         struct ttyent *typ;
1409         int session_index = 0;
1410         int devlen;
1411         char *old_getty, *old_window, *old_type;
1412
1413         /*
1414          * mark all sessions for death, (!SE_PRESENT)
1415          * as we find or create new ones they'll be marked as keepers,
1416          * we'll later nuke all the ones not found in /etc/ttys
1417          */
1418         for (sp = sessions; sp != NULL; sp = sp->se_next)
1419                 sp->se_flags &= ~SE_PRESENT;
1420
1421         devlen = sizeof(_PATH_DEV) - 1;
1422         while ((typ = getttyent()) != NULL) {
1423                 ++session_index;
1424
1425                 for (sprev = 0, sp = sessions; sp; sprev = sp, sp = sp->se_next)
1426                         if (strcmp(typ->ty_name, sp->se_device + devlen) == 0)
1427                                 break;
1428
1429                 if (sp) {
1430                         /* we want this one to live */
1431                         sp->se_flags |= SE_PRESENT;
1432                         if (sp->se_index != session_index) {
1433                                 warning("port %s changed utmp index from %d to %d",
1434                                        sp->se_device, sp->se_index,
1435                                        session_index);
1436                                 sp->se_index = session_index;
1437                         }
1438                         if ((typ->ty_status & TTY_ON) == 0 ||
1439                             typ->ty_getty == 0) {
1440                                 sp->se_flags |= SE_SHUTDOWN;
1441                                 kill(sp->se_process, SIGHUP);
1442                                 continue;
1443                         }
1444                         sp->se_flags &= ~SE_SHUTDOWN;
1445                         old_getty = sp->se_getty ? strdup(sp->se_getty) : 0;
1446                         old_window = sp->se_window ? strdup(sp->se_window) : 0;
1447                         old_type = sp->se_type ? strdup(sp->se_type) : 0;
1448                         if (setupargv(sp, typ) == 0) {
1449                                 warning("can't parse getty for port %s",
1450                                         sp->se_device);
1451                                 sp->se_flags |= SE_SHUTDOWN;
1452                                 kill(sp->se_process, SIGHUP);
1453                         }
1454                         else if (   !old_getty
1455                                  || (!old_type && sp->se_type)
1456                                  || (old_type && !sp->se_type)
1457                                  || (!old_window && sp->se_window)
1458                                  || (old_window && !sp->se_window)
1459                                  || (strcmp(old_getty, sp->se_getty) != 0)
1460                                  || (old_window && strcmp(old_window, sp->se_window) != 0)
1461                                  || (old_type && strcmp(old_type, sp->se_type) != 0)
1462                                 ) {
1463                                 /* Don't set SE_SHUTDOWN here */
1464                                 sp->se_nspace = 0;
1465                                 sp->se_started = 0;
1466                                 kill(sp->se_process, SIGHUP);
1467                         }
1468                         if (old_getty)
1469                                 free(old_getty);
1470                         if (old_window)
1471                                 free(old_window);
1472                         if (old_type)
1473                                 free(old_type);
1474                         continue;
1475                 }
1476
1477                 new_session(sprev, session_index, typ);
1478         }
1479
1480         endttyent();
1481
1482         /*
1483          * sweep through and kill all deleted sessions
1484          * ones who's /etc/ttys line was deleted (SE_PRESENT unset)
1485          */
1486         for (sp = sessions; sp != NULL; sp = sp->se_next) {
1487                 if ((sp->se_flags & SE_PRESENT) == 0) {
1488                         sp->se_flags |= SE_SHUTDOWN;
1489                         kill(sp->se_process, SIGHUP);
1490                 }
1491         }
1492
1493         return (state_func_t) multi_user;
1494 }
1495
1496 /*
1497  * Block further logins.
1498  */
1499 static state_func_t
1500 catatonia(void)
1501 {
1502         session_t *sp;
1503
1504         for (sp = sessions; sp; sp = sp->se_next)
1505                 sp->se_flags |= SE_SHUTDOWN;
1506
1507         return (state_func_t) multi_user;
1508 }
1509
1510 /*
1511  * Note SIGALRM.
1512  */
1513 static void
1514 alrm_handler(int sig)
1515 {
1516
1517         (void)sig;
1518         clang = 1;
1519 }
1520
1521 /*
1522  * Bring the system down to single user.
1523  */
1524 static state_func_t
1525 death(void)
1526 {
1527         struct utmpx utx;
1528         session_t *sp;
1529
1530         /* NB: should send a message to the session logger to avoid blocking. */
1531         utx.ut_type = SHUTDOWN_TIME;
1532         gettimeofday(&utx.ut_tv, NULL);
1533         pututxline(&utx);
1534
1535         /*
1536          * Also revoke the TTY here.  Because runshutdown() may reopen
1537          * the TTY whose getty we're killing here, there is no guarantee
1538          * runshutdown() will perform the initial open() call, causing
1539          * the terminal attributes to be misconfigured.
1540          */
1541         for (sp = sessions; sp; sp = sp->se_next) {
1542                 sp->se_flags |= SE_SHUTDOWN;
1543                 kill(sp->se_process, SIGHUP);
1544                 revoke(sp->se_device);
1545         }
1546
1547         /* Try to run the rc.shutdown script within a period of time */
1548         runshutdown();
1549
1550         return (state_func_t) death_single;
1551 }
1552
1553 /*
1554  * Do what is necessary to reinitialize single user mode or reboot
1555  * from an incomplete state.
1556  */
1557 static state_func_t
1558 death_single(void)
1559 {
1560         int i;
1561         pid_t pid;
1562         static const int death_sigs[2] = { SIGTERM, SIGKILL };
1563
1564         revoke(_PATH_CONSOLE);
1565
1566         for (i = 0; i < 2; ++i) {
1567                 if (kill(-1, death_sigs[i]) == -1 && errno == ESRCH)
1568                         return (state_func_t) single_user;
1569
1570                 clang = 0;
1571                 alarm(DEATH_WATCH);
1572                 do
1573                         if ((pid = waitpid(-1, (int *)0, 0)) != -1)
1574                                 collect_child(pid);
1575                 while (clang == 0 && errno != ECHILD);
1576
1577                 if (errno == ECHILD)
1578                         return (state_func_t) single_user;
1579         }
1580
1581         warning("some processes would not die; ps axl advised");
1582
1583         return (state_func_t) single_user;
1584 }
1585
1586 /*
1587  * Run the system shutdown script.
1588  *
1589  * Exit codes:      XXX I should document more
1590  * -2       shutdown script terminated abnormally
1591  * -1       fatal error - can't run script
1592  * 0        good.
1593  * >0       some error (exit code)
1594  */
1595 static int
1596 runshutdown(void)
1597 {
1598         pid_t pid, wpid;
1599         int status;
1600         int shutdowntimeout;
1601         size_t len;
1602         char *argv[4];
1603         const char *shell;
1604         struct sigaction sa;
1605         struct stat sb;
1606
1607         /*
1608          * rc.shutdown is optional, so to prevent any unnecessary
1609          * complaints from the shell we simply don't run it if the
1610          * file does not exist. If the stat() here fails for other
1611          * reasons, we'll let the shell complain.
1612          */
1613         if (stat(_PATH_RUNDOWN, &sb) == -1 && errno == ENOENT)
1614                 return 0;
1615
1616         shell = get_shell();
1617
1618         if ((pid = fork()) == 0) {
1619                 sigemptyset(&sa.sa_mask);
1620                 sa.sa_flags = 0;
1621                 sa.sa_handler = SIG_IGN;
1622                 sigaction(SIGTSTP, &sa, (struct sigaction *)0);
1623                 sigaction(SIGHUP, &sa, (struct sigaction *)0);
1624
1625                 open_console();
1626
1627                 char _sh[]      = "sh";
1628                 char _reboot[]  = "reboot";
1629                 char _single[]  = "single";
1630                 char _path_rundown[] = _PATH_RUNDOWN;
1631
1632                 argv[0] = _sh;
1633                 argv[1] = _path_rundown;
1634                 argv[2] = Reboot ? _reboot : _single;
1635                 argv[3] = 0;
1636
1637                 sigprocmask(SIG_SETMASK, &sa.sa_mask, (sigset_t *) 0);
1638
1639 #ifdef LOGIN_CAP
1640                 setprocresources(RESOURCE_RC);
1641 #endif
1642                 execv(shell, argv);
1643                 warning("can't exec %s for %s: %m", shell, _PATH_RUNDOWN);
1644                 _exit(1);       /* force single user mode */
1645         }
1646
1647         if (pid == -1) {
1648                 emergency("can't fork for %s on %s: %m", shell, _PATH_RUNDOWN);
1649                 while (waitpid(-1, (int *) 0, WNOHANG) > 0)
1650                         continue;
1651                 sleep(STALL_TIMEOUT);
1652                 return -1;
1653         }
1654
1655         len = sizeof(shutdowntimeout);
1656         if (sysctlbyname("kern.init_shutdown_timeout", &shutdowntimeout, &len,
1657             NULL, 0) == -1 || shutdowntimeout < 2)
1658                 shutdowntimeout = DEATH_SCRIPT;
1659         alarm(shutdowntimeout);
1660         clang = 0;
1661         /*
1662          * Copied from single_user().  This is a bit paranoid.
1663          * Use the same ALRM handler.
1664          */
1665         do {
1666                 if ((wpid = waitpid(-1, &status, WUNTRACED)) != -1)
1667                         collect_child(wpid);
1668                 if (clang == 1) {
1669                         /* we were waiting for the sub-shell */
1670                         kill(wpid, SIGTERM);
1671                         warning("timeout expired for %s on %s: %m; going to "
1672                             "single user mode", shell, _PATH_RUNDOWN);
1673                         return -1;
1674                 }
1675                 if (wpid == -1) {
1676                         if (errno == EINTR)
1677                                 continue;
1678                         warning("wait for %s on %s failed: %m; going to "
1679                             "single user mode", shell, _PATH_RUNDOWN);
1680                         return -1;
1681                 }
1682                 if (wpid == pid && WIFSTOPPED(status)) {
1683                         warning("init: %s on %s stopped, restarting\n",
1684                                 shell, _PATH_RUNDOWN);
1685                         kill(pid, SIGCONT);
1686                         wpid = -1;
1687                 }
1688         } while (wpid != pid && !clang);
1689
1690         /* Turn off the alarm */
1691         alarm(0);
1692
1693         if (WIFSIGNALED(status) && WTERMSIG(status) == SIGTERM &&
1694             requested_transition == catatonia) {
1695                 /*
1696                  * /etc/rc.shutdown executed /sbin/reboot;
1697                  * wait for the end quietly
1698                  */
1699                 sigset_t s;
1700
1701                 sigfillset(&s);
1702                 for (;;)
1703                         sigsuspend(&s);
1704         }
1705
1706         if (!WIFEXITED(status)) {
1707                 warning("%s on %s terminated abnormally, going to "
1708                     "single user mode", shell, _PATH_RUNDOWN);
1709                 return -2;
1710         }
1711
1712         if ((status = WEXITSTATUS(status)) != 0)
1713                 warning("%s returned status %d", _PATH_RUNDOWN, status);
1714
1715         return status;
1716 }
1717
1718 static char *
1719 strk(char *p)
1720 {
1721         static char *t;
1722         char *q;
1723         int c;
1724
1725         if (p)
1726                 t = p;
1727         if (!t)
1728                 return 0;
1729
1730         c = *t;
1731         while (c == ' ' || c == '\t' )
1732                 c = *++t;
1733         if (!c) {
1734                 t = 0;
1735                 return 0;
1736         }
1737         q = t;
1738         if (c == '\'') {
1739                 c = *++t;
1740                 q = t;
1741                 while (c && c != '\'')
1742                         c = *++t;
1743                 if (!c)  /* unterminated string */
1744                         q = t = 0;
1745                 else
1746                         *t++ = 0;
1747         } else {
1748                 while (c && c != ' ' && c != '\t' )
1749                         c = *++t;
1750                 *t++ = 0;
1751                 if (!c)
1752                         t = 0;
1753         }
1754         return q;
1755 }
1756
1757 #ifdef LOGIN_CAP
1758 static void
1759 setprocresources(const char *cname)
1760 {
1761         login_cap_t *lc;
1762         if ((lc = login_getclassbyname(cname, NULL)) != NULL) {
1763                 setusercontext(lc, (struct passwd*)NULL, 0,
1764                     LOGIN_SETPRIORITY | LOGIN_SETRESOURCES);
1765                 login_close(lc);
1766         }
1767 }
1768 #endif