xref: /openbsd-src/sbin/init/init.c (revision ae3cb403620ab940fbaabb3055fac045a63d56b7)
1 /*	$OpenBSD: init.c,v 1.66 2018/01/06 16:26:12 millert Exp $	*/
2 /*	$NetBSD: init.c,v 1.22 1996/05/15 23:29:33 jtc Exp $	*/
3 
4 /*-
5  * Copyright (c) 1991, 1993
6  *	The Regents of the University of California.  All rights reserved.
7  *
8  * This code is derived from software contributed to Berkeley by
9  * Donn Seeley at Berkeley Software Design, Inc.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  * 3. Neither the name of the University nor the names of its contributors
20  *    may be used to endorse or promote products derived from this software
21  *    without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33  * SUCH DAMAGE.
34  */
35 
36 #include <sys/types.h>
37 #include <sys/reboot.h>
38 #include <sys/sysctl.h>
39 #include <sys/time.h>
40 #include <sys/tree.h>
41 #include <sys/wait.h>
42 #include <machine/cpu.h>
43 
44 #include <err.h>
45 #include <errno.h>
46 #include <fcntl.h>
47 #include <limits.h>
48 #include <login_cap.h>
49 #include <signal.h>
50 #include <stdarg.h>
51 #include <stdio.h>
52 #include <stdlib.h>
53 #include <string.h>
54 #include <syslog.h>
55 #include <time.h>
56 #include <ttyent.h>
57 #include <unistd.h>
58 #include <util.h>
59 
60 #ifdef SECURE
61 #include <pwd.h>
62 #include <readpassphrase.h>
63 #endif
64 
65 #include "pathnames.h"
66 
67 /*
68  * Sleep times; used to prevent thrashing.
69  */
70 #define	GETTY_SPACING		 5	/* N secs minimum getty spacing */
71 #define	GETTY_SLEEP		30	/* sleep N secs after spacing problem */
72 #define	WINDOW_WAIT		 3	/* wait N secs after starting window */
73 #define	STALL_TIMEOUT		30	/* wait N secs after warning */
74 #define	DEATH_WATCH		10	/* wait N secs for procs to die */
75 
76 /*
77  * User-based resource limits.
78  */
79 #define RESOURCE_RC		"daemon"
80 #define RESOURCE_WINDOW		"default"
81 #define RESOURCE_GETTY		"default"
82 
83 #ifndef DEFAULT_STATE
84 #define DEFAULT_STATE		runcom
85 #endif
86 
87 void handle(sig_t, ...);
88 void delset(sigset_t *, ...);
89 
90 void stall(char *, ...);
91 void warning(char *, ...);
92 void emergency(char *, ...);
93 void disaster(int);
94 void badsys(int);
95 
96 typedef enum {
97 	invalid_state,
98 	single_user,
99 	runcom,
100 	read_ttys,
101 	multi_user,
102 	clean_ttys,
103 	catatonia,
104 	death,
105 	do_reboot,
106 	hard_death,
107 	nice_death
108 } state_t;
109 typedef state_t (*state_func_t)(void);
110 
111 state_t f_single_user(void);
112 state_t f_runcom(void);
113 state_t f_read_ttys(void);
114 state_t f_multi_user(void);
115 state_t f_clean_ttys(void);
116 state_t f_catatonia(void);
117 state_t f_death(void);
118 state_t f_do_reboot(void);
119 state_t f_hard_death(void);
120 state_t f_nice_death(void);
121 
122 state_func_t state_funcs[] = {
123 	NULL,
124 	f_single_user,
125 	f_runcom,
126 	f_read_ttys,
127 	f_multi_user,
128 	f_clean_ttys,
129 	f_catatonia,
130 	f_death,
131 	f_do_reboot,
132 	f_hard_death,
133 	f_nice_death
134 };
135 
136 enum { AUTOBOOT, FASTBOOT } runcom_mode = AUTOBOOT;
137 
138 void transition(state_t);
139 volatile sig_atomic_t requested_transition = DEFAULT_STATE;
140 
141 void setctty(char *);
142 
143 typedef 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 */
150 #define	SE_DEVEXISTS	0x4		/* open does not result in ENODEV */
151 	char	*se_device;		/* filename of port */
152 	char	*se_getty;		/* what to run on that port */
153 	char	**se_getty_argv;	/* pre-parsed argument array */
154 	char	*se_window;		/* window system (started only once) */
155 	char	**se_window_argv;	/* pre-parsed argument array */
156 	struct	init_session *se_prev;
157 	struct	init_session *se_next;
158 	RB_ENTRY(init_session) se_entry;
159 } session_t;
160 
161 static int cmp_sessions(session_t *, session_t *);
162 RB_HEAD(session_tree, init_session) session_tree = RB_INITIALIZER(session_tree);
163 RB_PROTOTYPE(session_tree, init_session, se_entry, cmp_sessions);
164 RB_GENERATE(session_tree, init_session, se_entry, cmp_sessions);
165 
166 void free_session(session_t *);
167 session_t *new_session(session_t *, int, struct ttyent *);
168 session_t *sessions;
169 
170 char **construct_argv(char *);
171 void start_window_system(session_t *);
172 void collect_child(pid_t);
173 pid_t start_getty(session_t *);
174 void transition_handler(int);
175 void alrm_handler(int);
176 void setsecuritylevel(int);
177 void setprocresources(char *);
178 int getsecuritylevel(void);
179 int setupargv(session_t *, struct ttyent *);
180 int clang;
181 
182 void clear_session_logs(session_t *);
183 
184 void add_session(session_t *);
185 void del_session(session_t *);
186 session_t *find_session(pid_t);
187 
188 /*
189  * The mother of all processes.
190  */
191 int
192 main(int argc, char *argv[])
193 {
194 	int c, fd;
195 	struct sigaction sa;
196 	sigset_t mask;
197 
198 	/* Dispose of random users. */
199 	if (getuid() != 0) {
200 		(void)fprintf(stderr, "init: %s\n", strerror(EPERM));
201 		exit (1);
202 	}
203 
204 	/* System V users like to reexec init. */
205 	if (getpid() != 1) {
206 		(void)fprintf(stderr, "init: already running\n");
207 		exit (1);
208 	}
209 
210 	/*
211 	 * Paranoia.
212 	 */
213 	if ((fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) {
214 		(void)dup2(fd, STDIN_FILENO);
215 		(void)dup2(fd, STDOUT_FILENO);
216 		(void)dup2(fd, STDERR_FILENO);
217 		if (fd > 2)
218 			(void)close(fd);
219 	}
220 
221 	/*
222 	 * Note that this does NOT open a file...
223 	 * Does 'init' deserve its own facility number?
224 	 */
225 	openlog("init", LOG_CONS|LOG_ODELAY, LOG_AUTH);
226 
227 	/*
228 	 * Create an initial session.
229 	 */
230 	if (setsid() < 0)
231 		warning("initial setsid() failed: %m");
232 
233 	/*
234 	 * Establish an initial user so that programs running
235 	 * single user do not freak out and die (like passwd).
236 	 */
237 	if (setlogin("root") < 0)
238 		warning("setlogin() failed: %m");
239 
240 	/*
241 	 * This code assumes that we always get arguments through flags,
242 	 * never through bits set in some random machine register.
243 	 */
244 	while ((c = getopt(argc, argv, "sf")) != -1)
245 		switch (c) {
246 		case 's':
247 			requested_transition = single_user;
248 			break;
249 		case 'f':
250 			runcom_mode = FASTBOOT;
251 			break;
252 		default:
253 			warning("unrecognized flag '-%c'", c);
254 			break;
255 		}
256 
257 	if (optind != argc)
258 		warning("ignoring excess arguments");
259 
260 	/*
261 	 * We catch or block signals rather than ignore them,
262 	 * so that they get reset on exec.
263 	 */
264 	handle(badsys, SIGSYS, 0);
265 	handle(disaster, SIGABRT, SIGFPE, SIGILL, SIGSEGV,
266 	    SIGBUS, SIGXCPU, SIGXFSZ, 0);
267 	handle(transition_handler, SIGHUP, SIGINT, SIGTERM, SIGTSTP,
268             SIGUSR1, SIGUSR2, 0);
269 	handle(alrm_handler, SIGALRM, 0);
270 	sigfillset(&mask);
271 	delset(&mask, SIGABRT, SIGFPE, SIGILL, SIGSEGV, SIGBUS, SIGSYS,
272 	    SIGXCPU, SIGXFSZ, SIGHUP, SIGINT, SIGTERM, SIGUSR1, SIGUSR2,
273 	    SIGTSTP, SIGALRM, 0);
274 	sigprocmask(SIG_SETMASK, &mask, NULL);
275 	memset(&sa, 0, sizeof sa);
276 	sigemptyset(&sa.sa_mask);
277 	sa.sa_flags = 0;
278 	sa.sa_handler = SIG_IGN;
279 	(void) sigaction(SIGTTIN, &sa, NULL);
280 	(void) sigaction(SIGTTOU, &sa, NULL);
281 
282 	/*
283 	 * Start the state machine.
284 	 */
285 	transition(requested_transition);
286 
287 	/*
288 	 * Should never reach here.
289 	 */
290 	exit(1);
291 }
292 
293 /*
294  * Associate a function with a signal handler.
295  */
296 void
297 handle(sig_t handler, ...)
298 {
299 	int sig;
300 	struct sigaction sa;
301 	sigset_t mask_everything;
302 	va_list ap;
303 
304 	va_start(ap, handler);
305 
306 	memset(&sa, 0, sizeof sa);
307 	sa.sa_handler = handler;
308 	sigfillset(&mask_everything);
309 
310 	while ((sig = va_arg(ap, int))) {
311 		sa.sa_mask = mask_everything;
312 		/* XXX SA_RESTART? */
313 		sa.sa_flags = sig == SIGCHLD ? SA_NOCLDSTOP : 0;
314 		sigaction(sig, &sa, NULL);
315 	}
316 	va_end(ap);
317 }
318 
319 /*
320  * Delete a set of signals from a mask.
321  */
322 void
323 delset(sigset_t *maskp, ...)
324 {
325 	int sig;
326 	va_list ap;
327 
328 	va_start(ap, maskp);
329 	while ((sig = va_arg(ap, int)))
330 		sigdelset(maskp, sig);
331 	va_end(ap);
332 }
333 
334 /*
335  * Log a message and sleep for a while (to give someone an opportunity
336  * to read it and to save log or hardcopy output if the problem is chronic).
337  * NB: should send a message to the session logger to avoid blocking.
338  */
339 void
340 stall(char *message, ...)
341 {
342 	va_list ap;
343 
344 	va_start(ap, message);
345 	vsyslog(LOG_ALERT, message, ap);
346 	va_end(ap);
347 	closelog();
348 	sleep(STALL_TIMEOUT);
349 }
350 
351 /*
352  * Like stall(), but doesn't sleep.
353  * If cpp had variadic macros, the two functions could be #defines for another.
354  * NB: should send a message to the session logger to avoid blocking.
355  */
356 void
357 warning(char *message, ...)
358 {
359 	va_list ap;
360 
361 	va_start(ap, message);
362 	vsyslog(LOG_ALERT, message, ap);
363 	va_end(ap);
364 	closelog();
365 }
366 
367 /*
368  * Log an emergency message.
369  * NB: should send a message to the session logger to avoid blocking.
370  */
371 void
372 emergency(char *message, ...)
373 {
374 	struct syslog_data sdata = SYSLOG_DATA_INIT;
375 	va_list ap;
376 
377 	va_start(ap, message);
378 	vsyslog_r(LOG_EMERG, &sdata, message, ap);
379 	va_end(ap);
380 }
381 
382 /*
383  * Catch a SIGSYS signal.
384  *
385  * These may arise if a system does not support sysctl.
386  * We tolerate up to 25 of these, then throw in the towel.
387  */
388 void
389 badsys(int sig)
390 {
391 	static int badcount = 0;
392 
393 	if (badcount++ < 25)
394 		return;
395 	disaster(sig);
396 }
397 
398 /*
399  * Catch an unexpected signal.
400  */
401 void
402 disaster(int sig)
403 {
404 	emergency("fatal signal: %s", strsignal(sig));
405 
406 	sleep(STALL_TIMEOUT);
407 	_exit(sig);		/* reboot */
408 }
409 
410 /*
411  * Get the security level of the kernel.
412  */
413 int
414 getsecuritylevel(void)
415 {
416 #ifdef KERN_SECURELVL
417 	int name[2], curlevel;
418 	size_t len;
419 
420 	name[0] = CTL_KERN;
421 	name[1] = KERN_SECURELVL;
422 	len = sizeof curlevel;
423 	if (sysctl(name, 2, &curlevel, &len, NULL, 0) == -1) {
424 		emergency("cannot get kernel security level: %s",
425 		    strerror(errno));
426 		return (-1);
427 	}
428 	return (curlevel);
429 #else
430 	return (-1);
431 #endif
432 }
433 
434 /*
435  * Set the security level of the kernel.
436  */
437 void
438 setsecuritylevel(int newlevel)
439 {
440 #ifdef KERN_SECURELVL
441 	int name[2], curlevel;
442 
443 	curlevel = getsecuritylevel();
444 	if (newlevel == curlevel)
445 		return;
446 	name[0] = CTL_KERN;
447 	name[1] = KERN_SECURELVL;
448 	if (sysctl(name, 2, NULL, NULL, &newlevel, sizeof newlevel) == -1) {
449 		emergency(
450 		    "cannot change kernel security level from %d to %d: %s",
451 		    curlevel, newlevel, strerror(errno));
452 		return;
453 	}
454 #ifdef SECURE
455 	warning("kernel security level changed from %d to %d",
456 	    curlevel, newlevel);
457 #endif
458 #endif
459 }
460 
461 /*
462  * Change states in the finite state machine.
463  * The initial state is passed as an argument.
464  */
465 void
466 transition(state_t s)
467 {
468 	for (;;)
469 		s = (*state_funcs[s])();
470 }
471 
472 /*
473  * Close out the accounting files for a login session.
474  * NB: should send a message to the session logger to avoid blocking.
475  */
476 void
477 clear_session_logs(session_t *sp)
478 {
479 	char *line = sp->se_device + sizeof(_PATH_DEV) - 1;
480 
481 	if (logout(line))
482 		logwtmp(line, "", "");
483 }
484 
485 /*
486  * Start a session and allocate a controlling terminal.
487  * Only called by children of init after forking.
488  */
489 void
490 setctty(char *name)
491 {
492 	int fd;
493 
494 	(void) revoke(name);
495 	sleep(2);			/* leave DTR low */
496 	if ((fd = open(name, O_RDWR)) == -1) {
497 		stall("can't open %s: %m", name);
498 		_exit(1);
499 	}
500 	if (login_tty(fd) == -1) {
501 		stall("can't get %s for controlling terminal: %m", name);
502 		_exit(1);
503 	}
504 }
505 
506 /*
507  * Bring the system up single user.
508  */
509 state_t
510 f_single_user(void)
511 {
512 	pid_t pid, wpid;
513 	int status;
514 	sigset_t mask;
515 	char shell[PATH_MAX];		/* Allocate space here */
516 	char name[PATH_MAX];		/* Name (argv[0]) of shell */
517 	char *argv[2];
518 #ifdef SECURE
519 	struct ttyent *typ;
520 	struct passwd *pp;
521 	static const char banner[] =
522 		"Enter root password, or ^D to go multi-user\n";
523 	char *clear;
524 	char pbuf[1024];
525 #endif
526 
527 	/* Init shell and name */
528 	strlcpy(shell, _PATH_BSHELL, sizeof shell);
529 	strlcpy(name, "-sh", sizeof name);
530 
531 	/*
532 	 * If the kernel is in secure mode, downgrade it to insecure mode.
533 	 */
534 	if (getsecuritylevel() > 0)
535 		setsecuritylevel(0);
536 
537 	if ((pid = fork()) == 0) {
538 		/*
539 		 * Start the single user session.
540 		 */
541 		setctty(_PATH_CONSOLE);
542 
543 #ifdef SECURE
544 		/*
545 		 * Check the root password.
546 		 * We don't care if the console is 'on' by default;
547 		 * it's the only tty that can be 'off' and 'secure'.
548 		 */
549 		typ = getttynam("console");
550 		pp = getpwnam_shadow("root");
551 		if (typ && (typ->ty_status & TTY_SECURE) == 0 && pp &&
552 		    *pp->pw_passwd) {
553 			write(STDERR_FILENO, banner, sizeof banner - 1);
554 			for (;;) {
555 				int ok = 0;
556 				clear = readpassphrase("Password:", pbuf,
557 				    sizeof(pbuf), RPP_ECHO_OFF);
558 				if (clear == NULL || *clear == '\0')
559 					_exit(0);
560 				if (crypt_checkpass(clear, pp->pw_passwd) == 0)
561 					ok = 1;
562 				explicit_bzero(pbuf, sizeof(pbuf));
563 				if (ok)
564 					break;
565 				warning("single-user login failed\n");
566 			}
567 		}
568 		endttyent();
569 		endpwent();
570 #endif /* SECURE */
571 
572 #ifdef DEBUGSHELL
573 		{
574 			char altshell[128], *cp = altshell;
575 			int num;
576 
577 #define	SHREQUEST \
578 	"Enter pathname of shell or RETURN for sh: "
579 
580 			(void)write(STDERR_FILENO,
581 			    SHREQUEST, sizeof(SHREQUEST) - 1);
582 			while ((num = read(STDIN_FILENO, cp, 1)) != -1 &&
583 			    num != 0 && *cp != '\n' && cp < &altshell[127])
584 				cp++;
585 			*cp = '\0';
586 
587 			/* Copy in alternate shell */
588 			if (altshell[0] != '\0'){
589 				char *p;
590 
591 				/* Binary to exec */
592 				strlcpy(shell, altshell, sizeof shell);
593 
594 				/* argv[0] */
595 				p = strrchr(altshell, '/');
596 				if(p == NULL) p = altshell;
597 				else p++;
598 
599 				name[0] = '-';
600 				strlcpy(&name[1], p, sizeof name -1);
601 			}
602 		}
603 #endif /* DEBUGSHELL */
604 
605 		/*
606 		 * Unblock signals.
607 		 * We catch all the interesting ones,
608 		 * and those are reset to SIG_DFL on exec.
609 		 */
610 		sigemptyset(&mask);
611 		sigprocmask(SIG_SETMASK, &mask, NULL);
612 
613 		/*
614 		 * Fire off a shell.
615 		 * If the default one doesn't work, try the Bourne shell.
616 		 */
617 		argv[0] = name;
618 		argv[1] = NULL;
619 		setenv("PATH", _PATH_STDPATH, 1);
620 		execv(shell, argv);
621 		emergency("can't exec %s for single user: %m", shell);
622 
623 		argv[0] = "-sh";
624 		argv[1] = NULL;
625 		execv(_PATH_BSHELL, argv);
626 		emergency("can't exec %s for single user: %m", _PATH_BSHELL);
627 		sleep(STALL_TIMEOUT);
628 		_exit(1);
629 	}
630 
631 	if (pid == -1) {
632 		/*
633 		 * We are seriously hosed.  Do our best.
634 		 */
635 		emergency("can't fork single-user shell, trying again");
636 		while (waitpid(-1, NULL, WNOHANG) > 0)
637 			continue;
638 		return single_user;
639 	}
640 
641 	requested_transition = 0;
642 	do {
643 		if ((wpid = waitpid(-1, &status, WUNTRACED)) != -1)
644 			collect_child(wpid);
645 		if (wpid == -1) {
646 			if (errno == EINTR)
647 				continue;
648 			warning("wait for single-user shell failed: %m; restarting");
649 			return single_user;
650 		}
651 		if (wpid == pid && WIFSTOPPED(status)) {
652 			warning("init: shell stopped, restarting\n");
653 			kill(pid, SIGCONT);
654 			wpid = -1;
655 		}
656 	} while (wpid != pid && !requested_transition);
657 
658 	if (requested_transition)
659 		return requested_transition;
660 
661 	if (!WIFEXITED(status)) {
662 		if (WTERMSIG(status) == SIGKILL) {
663 			/*
664 			 *  reboot(8) killed shell?
665 			 */
666 			warning("single user shell terminated.");
667 			sleep(STALL_TIMEOUT);
668 			_exit(0);
669 		} else {
670 			warning("single user shell terminated, restarting");
671 			return single_user;
672 		}
673 	}
674 
675 	runcom_mode = FASTBOOT;
676 	return runcom;
677 }
678 
679 /*
680  * Run the system startup script.
681  */
682 state_t
683 f_runcom(void)
684 {
685 	pid_t pid, wpid;
686 	int status;
687 	char *argv[4];
688 	struct sigaction sa;
689 
690 	if ((pid = fork()) == 0) {
691 		memset(&sa, 0, sizeof sa);
692 		sigemptyset(&sa.sa_mask);
693 		sa.sa_flags = 0;
694 		sa.sa_handler = SIG_IGN;
695 		(void) sigaction(SIGTSTP, &sa, NULL);
696 		(void) sigaction(SIGHUP, &sa, NULL);
697 
698 		setctty(_PATH_CONSOLE);
699 
700 		argv[0] = "sh";
701 		argv[1] = _PATH_RUNCOM;
702 		argv[2] = runcom_mode == AUTOBOOT ? "autoboot" : NULL;
703 		argv[3] = NULL;
704 
705 		sigprocmask(SIG_SETMASK, &sa.sa_mask, NULL);
706 
707 		setprocresources(RESOURCE_RC);
708 
709 		execv(_PATH_BSHELL, argv);
710 		stall("can't exec %s for %s: %m", _PATH_BSHELL, _PATH_RUNCOM);
711 		_exit(1);	/* force single user mode */
712 	}
713 
714 	if (pid == -1) {
715 		emergency("can't fork for %s on %s: %m",
716 			_PATH_BSHELL, _PATH_RUNCOM);
717 		while (waitpid(-1, NULL, WNOHANG) > 0)
718 			continue;
719 		sleep(STALL_TIMEOUT);
720 		return single_user;
721 	}
722 
723 	/*
724 	 * Copied from single_user().  This is a bit paranoid.
725 	 */
726 	do {
727 		if ((wpid = waitpid(-1, &status, WUNTRACED)) != -1)
728 			collect_child(wpid);
729 		if (wpid == -1) {
730 			if (errno == EINTR)
731 				continue;
732 			warning("wait for %s on %s failed: %m; going to single user mode",
733 			    _PATH_BSHELL, _PATH_RUNCOM);
734 			return single_user;
735 		}
736 		if (wpid == pid && WIFSTOPPED(status)) {
737 			warning("init: %s on %s stopped, restarting\n",
738 			    _PATH_BSHELL, _PATH_RUNCOM);
739 			kill(pid, SIGCONT);
740 			wpid = -1;
741 		}
742 	} while (wpid != pid);
743 
744 	if (WIFSIGNALED(status) && WTERMSIG(status) == SIGTERM &&
745 	    requested_transition == catatonia) {
746 		/* /etc/rc executed /sbin/reboot; wait for the end quietly */
747 		sigset_t s;
748 
749 		sigfillset(&s);
750 		for (;;)
751 			sigsuspend(&s);
752 	}
753 
754 	if (!WIFEXITED(status)) {
755 		warning("%s on %s terminated abnormally, going to single user mode",
756 		    _PATH_BSHELL, _PATH_RUNCOM);
757 		return single_user;
758 	}
759 
760 	if (WEXITSTATUS(status))
761 		return single_user;
762 
763 	runcom_mode = AUTOBOOT;		/* the default */
764 	/* NB: should send a message to the session logger to avoid blocking. */
765 	logwtmp("~", "reboot", "");
766 	return read_ttys;
767 }
768 
769 /*
770  * Compare session keys.
771  */
772 static int
773 cmp_sessions(session_t *sp1, session_t *sp2)
774 {
775 	if (sp1->se_process < sp2->se_process)
776 		return (-1);
777 	if (sp1->se_process > sp2->se_process)
778 		return (1);
779 	return (0);
780 }
781 
782 /*
783  * Add a new login session.
784  */
785 void
786 add_session(session_t *sp)
787 {
788 	if (RB_INSERT(session_tree, &session_tree, sp) != NULL)
789 		emergency("insert %d: %s", sp->se_process, strerror(errno));
790 }
791 
792 /*
793  * Delete an old login session.
794  */
795 void
796 del_session(session_t *sp)
797 {
798 	RB_REMOVE(session_tree, &session_tree, sp);
799 }
800 
801 /*
802  * Look up a login session by pid.
803  */
804 session_t *
805 find_session(pid_t pid)
806 {
807 	struct init_session s;
808 
809 	s.se_process = pid;
810 	return (RB_FIND(session_tree, &session_tree, &s));
811 }
812 
813 /*
814  * Construct an argument vector from a command line.
815  */
816 char **
817 construct_argv(char *command)
818 {
819 	int argc = 0;
820 	char **argv = calloc((strlen(command) + 1) / 2 + 1, sizeof (char *));
821 	static const char separators[] = " \t";
822 
823 	if (argv == NULL)
824 		return (0);
825 
826 	if ((argv[argc++] = strtok(command, separators)) == 0) {
827 		free(argv);
828 		return (0);
829 	}
830 	while ((argv[argc++] = strtok(NULL, separators)))
831 		continue;
832 	return (argv);
833 }
834 
835 /*
836  * Deallocate a session descriptor.
837  */
838 void
839 free_session(session_t *sp)
840 {
841 	free(sp->se_device);
842 	if (sp->se_getty) {
843 		free(sp->se_getty);
844 		free(sp->se_getty_argv);
845 	}
846 	if (sp->se_window) {
847 		free(sp->se_window);
848 		free(sp->se_window_argv);
849 	}
850 	free(sp);
851 }
852 
853 /*
854  * Allocate a new session descriptor.
855  */
856 session_t *
857 new_session(session_t *sprev, int session_index, struct ttyent *typ)
858 {
859 	session_t *sp;
860 
861 	if ((typ->ty_status & TTY_ON) == 0 ||
862 	    typ->ty_name == 0 ||
863 	    typ->ty_getty == 0)
864 		return (0);
865 
866 	sp = calloc(1, sizeof (session_t));
867 	if (sp == NULL)
868 		err(1, "calloc");
869 
870 	sp->se_flags = SE_PRESENT;
871 	sp->se_index = session_index;
872 
873 	if (asprintf(&sp->se_device, "%s%s", _PATH_DEV, typ->ty_name) == -1)
874 		err(1, "asprintf");
875 
876 	if (setupargv(sp, typ) == 0) {
877 		free_session(sp);
878 		return (0);
879 	}
880 
881 	sp->se_next = NULL;
882 	if (sprev == NULL) {
883 		sessions = sp;
884 		sp->se_prev = NULL;
885 	} else {
886 		sprev->se_next = sp;
887 		sp->se_prev = sprev;
888 	}
889 
890 	return (sp);
891 }
892 
893 /*
894  * Calculate getty and if useful window argv vectors.
895  */
896 int
897 setupargv(session_t *sp, struct ttyent *typ)
898 {
899 	if (sp->se_getty) {
900 		free(sp->se_getty);
901 		free(sp->se_getty_argv);
902 	}
903 	if (asprintf(&sp->se_getty, "%s %s", typ->ty_getty, typ->ty_name) == -1)
904 		err(1, "asprintf");
905 	sp->se_getty_argv = construct_argv(sp->se_getty);
906 	if (sp->se_getty_argv == 0) {
907 		warning("can't parse getty for port %s", sp->se_device);
908 		free(sp->se_getty);
909 		sp->se_getty = NULL;
910 		return (0);
911 	}
912 	if (typ->ty_window) {
913 		free(sp->se_window);
914 		sp->se_window = strdup(typ->ty_window);
915 		if (sp->se_window == NULL) {
916 			warning("can't allocate window");
917 			return (0);
918 		}
919 		sp->se_window_argv = construct_argv(sp->se_window);
920 		if (sp->se_window_argv == NULL) {
921 			warning("can't parse window for port %s",
922 			    sp->se_device);
923 			free(sp->se_window);
924 			sp->se_window = NULL;
925 			return (0);
926 		}
927 	}
928 	return (1);
929 }
930 
931 /*
932  * Walk the list of ttys and create sessions for each active line.
933  */
934 state_t
935 f_read_ttys(void)
936 {
937 	int session_index = 0;
938 	session_t *sp, *snext;
939 	struct ttyent *typ;
940 
941 	/*
942 	 * Destroy any previous session state.
943 	 * There shouldn't be any, but just in case...
944 	 */
945 	for (sp = sessions; sp; sp = snext) {
946 		if (sp->se_process)
947 			clear_session_logs(sp);
948 		snext = sp->se_next;
949 		free_session(sp);
950 	}
951 	sessions = NULL;
952 
953 	/*
954 	 * Allocate a session entry for each active port.
955 	 * Note that sp starts at 0.
956 	 */
957 	while ((typ = getttyent()))
958 		if ((snext = new_session(sp, ++session_index, typ)))
959 			sp = snext;
960 
961 	endttyent();
962 
963 	return multi_user;
964 }
965 
966 /*
967  * Start a window system running.
968  */
969 void
970 start_window_system(session_t *sp)
971 {
972 	pid_t pid;
973 	sigset_t mask;
974 
975 	if ((pid = fork()) == -1) {
976 		emergency("can't fork for window system on port %s: %m",
977 		    sp->se_device);
978 		/* hope that getty fails and we can try again */
979 		return;
980 	}
981 
982 	if (pid)
983 		return;
984 
985 	sigemptyset(&mask);
986 	sigprocmask(SIG_SETMASK, &mask, NULL);
987 
988 	if (setsid() < 0)
989 		emergency("setsid failed (window) %m");
990 
991 	setprocresources(RESOURCE_WINDOW);
992 
993 	execv(sp->se_window_argv[0], sp->se_window_argv);
994 	stall("can't exec window system '%s' for port %s: %m",
995 	    sp->se_window_argv[0], sp->se_device);
996 	_exit(1);
997 }
998 
999 /*
1000  * Start a login session running.
1001  * For first open, man-handle tty directly to determine if it
1002  * really exists. It is not efficient to spawn gettys on devices
1003  * that do not exist.
1004  */
1005 pid_t
1006 start_getty(session_t *sp)
1007 {
1008 	pid_t pid;
1009 	sigset_t mask;
1010 	time_t current_time = time(NULL);
1011 	int p[2], new = 1;
1012 
1013 	if (sp->se_flags & SE_DEVEXISTS)
1014 		new = 0;
1015 
1016 	if (new) {
1017 		if (pipe(p) == -1)
1018 			return (-1);
1019 	}
1020 
1021 	/*
1022 	 * fork(), not vfork() -- we can't afford to block.
1023 	 */
1024 	if ((pid = fork()) == -1) {
1025 		emergency("can't fork for getty on port %s: %m", sp->se_device);
1026 		return (-1);
1027 	}
1028 
1029 	if (pid) {
1030 		if (new) {
1031 			char c;
1032 
1033 			close(p[1]);
1034 			if (read(p[0], &c, 1) != 1) {
1035 				close(p[0]);
1036 				return (-1);
1037 			}
1038 			close(p[0]);
1039 			if (c == '1')
1040 				sp->se_flags |= SE_DEVEXISTS;
1041 			else
1042 				sp->se_flags |= SE_SHUTDOWN;
1043 		}
1044 		return (pid);
1045 	}
1046 	if (new) {
1047 		int fd;
1048 
1049 		close(p[0]);
1050 		fd = open(sp->se_device, O_RDONLY | O_NONBLOCK, 0666);
1051 		if (fd == -1 && (errno == ENXIO || errno == ENOENT ||
1052 		    errno == EISDIR)) {
1053 			(void)write(p[1], "0", 1);
1054 			close(p[1]);
1055 			_exit(1);
1056 		}
1057 		(void)write(p[1], "1", 1);
1058 		close(p[1]);
1059 		close(fd);
1060 		sleep(1);
1061 	}
1062 
1063 	if (current_time > sp->se_started &&
1064 	    current_time - sp->se_started < GETTY_SPACING) {
1065 		warning("getty repeating too quickly on port %s, sleeping",
1066 		    sp->se_device);
1067 		sleep(GETTY_SLEEP);
1068 	}
1069 
1070 	if (sp->se_window) {
1071 		start_window_system(sp);
1072 		sleep(WINDOW_WAIT);
1073 	}
1074 
1075 	sigemptyset(&mask);
1076 	sigprocmask(SIG_SETMASK, &mask, NULL);
1077 
1078 	setprocresources(RESOURCE_GETTY);
1079 
1080 	execv(sp->se_getty_argv[0], sp->se_getty_argv);
1081 	stall("can't exec getty '%s' for port %s: %m",
1082 	    sp->se_getty_argv[0], sp->se_device);
1083 	_exit(1);
1084 }
1085 
1086 /*
1087  * Collect exit status for a child.
1088  * If an exiting login, start a new login running.
1089  */
1090 void
1091 collect_child(pid_t pid)
1092 {
1093 	session_t *sp, *sprev, *snext;
1094 
1095 	if (sessions == NULL)
1096 		return;
1097 
1098 	if ((sp = find_session(pid)) == NULL)
1099 		return;
1100 
1101 	clear_session_logs(sp);
1102 	login_fbtab(sp->se_device + sizeof(_PATH_DEV) - 1, 0, 0);
1103 	del_session(sp);
1104 	sp->se_process = 0;
1105 
1106 	if (sp->se_flags & SE_SHUTDOWN) {
1107 		if ((sprev = sp->se_prev))
1108 			sprev->se_next = sp->se_next;
1109 		else
1110 			sessions = sp->se_next;
1111 		if ((snext = sp->se_next))
1112 			snext->se_prev = sp->se_prev;
1113 		free_session(sp);
1114 		return;
1115 	}
1116 
1117 	if ((pid = start_getty(sp)) == -1) {
1118 		/* serious trouble */
1119 		requested_transition = clean_ttys;
1120 		return;
1121 	}
1122 
1123 	sp->se_process = pid;
1124 	sp->se_started = time(NULL);
1125 	add_session(sp);
1126 }
1127 
1128 /*
1129  * Catch a signal and request a state transition.
1130  */
1131 void
1132 transition_handler(int sig)
1133 {
1134 
1135 	switch (sig) {
1136 	case SIGHUP:
1137 		requested_transition = clean_ttys;
1138 		break;
1139 	case SIGINT:
1140 		requested_transition = do_reboot;
1141 		break;
1142 	case SIGTERM:
1143 		requested_transition = death;
1144 		break;
1145 	case SIGUSR1:
1146 		requested_transition = nice_death;
1147 		break;
1148 	case SIGUSR2:
1149 		requested_transition = hard_death;
1150 		break;
1151 	case SIGTSTP:
1152 		requested_transition = catatonia;
1153 		break;
1154 	default:
1155 		requested_transition = 0;
1156 		break;
1157 	}
1158 }
1159 
1160 /*
1161  * Take the system multiuser.
1162  */
1163 state_t
1164 f_multi_user(void)
1165 {
1166 	pid_t pid;
1167 	session_t *sp;
1168 
1169 	/*
1170 	 * If the administrator has not set the security level to -1
1171 	 * to indicate that the kernel should not run multiuser in secure
1172 	 * mode, and the run script has not set a higher level of security
1173 	 * than level 1, then put the kernel into secure mode.
1174 	 */
1175 	if (requested_transition != catatonia) {
1176 		if (getsecuritylevel() == 0)
1177 			setsecuritylevel(1);
1178 	}
1179 
1180 	requested_transition = 0;
1181 
1182 	for (sp = sessions; sp; sp = sp->se_next) {
1183 		if (sp->se_process)
1184 			continue;
1185 		if ((pid = start_getty(sp)) == -1) {
1186 			/* serious trouble */
1187 			requested_transition = clean_ttys;
1188 			break;
1189 		}
1190 		sp->se_process = pid;
1191 		sp->se_started = time(NULL);
1192 		add_session(sp);
1193 	}
1194 
1195 	while (!requested_transition)
1196 		if ((pid = waitpid(-1, NULL, 0)) != -1)
1197 			collect_child(pid);
1198 
1199 	return requested_transition;
1200 }
1201 
1202 /*
1203  * This is an n-squared algorithm.  We hope it isn't run often...
1204  */
1205 state_t
1206 f_clean_ttys(void)
1207 {
1208 	session_t *sp, *sprev;
1209 	struct ttyent *typ;
1210 	int session_index = 0;
1211 	int devlen;
1212 
1213 	for (sp = sessions; sp; sp = sp->se_next)
1214 		sp->se_flags &= ~SE_PRESENT;
1215 
1216 	devlen = sizeof(_PATH_DEV) - 1;
1217 	while ((typ = getttyent())) {
1218 		++session_index;
1219 
1220 		for (sprev = NULL, sp = sessions; sp; sprev = sp, sp = sp->se_next)
1221 			if (strcmp(typ->ty_name, sp->se_device + devlen) == 0)
1222 				break;
1223 
1224 		if (sp) {
1225 			sp->se_flags |= SE_PRESENT;
1226 			if (sp->se_index != session_index) {
1227 				warning("port %s changed utmp index from %d to %d",
1228 				    sp->se_device, sp->se_index,
1229 				    session_index);
1230 				sp->se_index = session_index;
1231 			}
1232 			if ((typ->ty_status & TTY_ON) == 0 ||
1233 			    typ->ty_getty == 0) {
1234 				sp->se_flags |= SE_SHUTDOWN;
1235 				kill(sp->se_process, SIGHUP);
1236 				continue;
1237 			}
1238 			sp->se_flags &= ~SE_SHUTDOWN;
1239 			if (setupargv(sp, typ) == 0) {
1240 				warning("can't parse getty for port %s",
1241 				    sp->se_device);
1242 				sp->se_flags |= SE_SHUTDOWN;
1243 				kill(sp->se_process, SIGHUP);
1244 			}
1245 			continue;
1246 		}
1247 
1248 		new_session(sprev, session_index, typ);
1249 	}
1250 
1251 	endttyent();
1252 
1253 	for (sp = sessions; sp; sp = sp->se_next)
1254 		if ((sp->se_flags & SE_PRESENT) == 0) {
1255 			sp->se_flags |= SE_SHUTDOWN;
1256 			kill(sp->se_process, SIGHUP);
1257 		}
1258 
1259 	return multi_user;
1260 }
1261 
1262 /*
1263  * Block further logins.
1264  */
1265 state_t
1266 f_catatonia(void)
1267 {
1268 	session_t *sp;
1269 
1270 	for (sp = sessions; sp; sp = sp->se_next)
1271 		sp->se_flags |= SE_SHUTDOWN;
1272 
1273 	return multi_user;
1274 }
1275 
1276 /*
1277  * Note SIGALRM.
1278  */
1279 void
1280 alrm_handler(int sig)
1281 {
1282 	clang = 1;
1283 }
1284 
1285 int death_howto = RB_HALT;
1286 
1287 /*
1288  * Reboot the system.
1289  */
1290 state_t
1291 f_do_reboot(void)
1292 {
1293 	death_howto = RB_AUTOBOOT;
1294 	return nice_death;
1295 }
1296 
1297 /*
1298  * Bring the system down nicely, then we must powerdown because something
1299  * is very wrong.
1300  */
1301 state_t
1302 f_hard_death(void)
1303 {
1304 	death_howto |= RB_POWERDOWN;
1305 	return nice_death;
1306 }
1307 
1308 /*
1309  * Bring the system down to single user nicely, after run the shutdown script.
1310  */
1311 state_t
1312 f_nice_death(void)
1313 {
1314 	session_t *sp;
1315 	int i;
1316 	pid_t pid;
1317 	static const int death_sigs[3] = { SIGHUP, SIGTERM, SIGKILL };
1318 	int status;
1319 
1320 #ifdef CPU_LIDACTION
1321 	int mib[] = {CTL_MACHDEP, CPU_LIDACTION};
1322 	int lidaction = 0;
1323 
1324 	if ((death_howto & RB_POWERDOWN) &&
1325 	    (sysctl(mib, 2, NULL, NULL, &lidaction,
1326 		    sizeof(lidaction)) == -1) && (errno != EOPNOTSUPP))
1327 			warning("cannot disable lid action");
1328 #endif
1329 
1330 	for (sp = sessions; sp; sp = sp->se_next) {
1331 		sp->se_flags &= ~SE_PRESENT;
1332 		sp->se_flags |= SE_SHUTDOWN;
1333 		kill(sp->se_process, SIGHUP);
1334 	}
1335 
1336 	/* terminate the accounting process */
1337 	acct(NULL);
1338 
1339 	/* NB: should send a message to the session logger to avoid blocking. */
1340 	logwtmp("~", "shutdown", "");
1341 
1342 	if (access(_PATH_RUNCOM, R_OK) != -1) {
1343 		struct sigaction sa;
1344 
1345 		switch ((pid = fork())) {
1346 		case -1:
1347 			break;
1348 		case 0:
1349 
1350 			memset(&sa, 0, sizeof sa);
1351 			sigemptyset(&sa.sa_mask);
1352 			sa.sa_flags = 0;
1353 			sa.sa_handler = SIG_IGN;
1354 			(void) sigaction(SIGTSTP, &sa, NULL);
1355 			(void) sigaction(SIGHUP, &sa, NULL);
1356 
1357 			setctty(_PATH_CONSOLE);
1358 
1359 			sigprocmask(SIG_SETMASK, &sa.sa_mask, NULL);
1360 
1361 			execl(_PATH_BSHELL, "sh", _PATH_RUNCOM, "shutdown",
1362 			    (char *)NULL);
1363 			stall("can't exec %s for %s %s: %m", _PATH_BSHELL,
1364 			    _PATH_RUNCOM, "shutdown");
1365 			_exit(1);
1366 		default:
1367 			waitpid(pid, &status, 0);
1368 			if (WIFEXITED(status) && WEXITSTATUS(status) == 2)
1369 				death_howto |= RB_POWERDOWN;
1370 		}
1371 	}
1372 
1373 	for (i = 0; i < 3; ++i) {
1374 		if (kill(-1, death_sigs[i]) == -1 && errno == ESRCH)
1375 			goto die;
1376 
1377 		clang = 0;
1378 		alarm(DEATH_WATCH);
1379 		do {
1380 			if ((pid = waitpid(-1, NULL, 0)) != -1)
1381 				collect_child(pid);
1382 		} while (clang == 0 && errno != ECHILD);
1383 
1384 		if (errno == ECHILD)
1385 			goto die;
1386 	}
1387 
1388 	warning("some processes would not die; ps axl advised");
1389 
1390 die:
1391 	reboot(death_howto);
1392 
1393 	/* ... and if that fails.. oh well */
1394 	return single_user;
1395 }
1396 
1397 /*
1398  * Bring the system down to single user.
1399  */
1400 state_t
1401 f_death(void)
1402 {
1403 	session_t *sp;
1404 	int i;
1405 	pid_t pid;
1406 	static const int death_sigs[3] = { SIGHUP, SIGTERM, SIGKILL };
1407 
1408 	/* terminate the accounting process */
1409 	acct(NULL);
1410 
1411 	for (sp = sessions; sp; sp = sp->se_next)
1412 		sp->se_flags |= SE_SHUTDOWN;
1413 
1414 	/* NB: should send a message to the session logger to avoid blocking. */
1415 	logwtmp("~", "shutdown", "");
1416 
1417 	for (i = 0; i < 3; ++i) {
1418 		if (kill(-1, death_sigs[i]) == -1 && errno == ESRCH)
1419 			return single_user;
1420 
1421 		clang = 0;
1422 		alarm(DEATH_WATCH);
1423 		do {
1424 			if ((pid = waitpid(-1, NULL, 0)) != -1)
1425 				collect_child(pid);
1426 		} while (clang == 0 && errno != ECHILD);
1427 
1428 		if (errno == ECHILD)
1429 			return single_user;
1430 	}
1431 
1432 	warning("some processes would not die; ps axl advised");
1433 
1434 	return single_user;
1435 }
1436 
1437 void
1438 setprocresources(char *class)
1439 {
1440 	login_cap_t *lc;
1441 
1442 	if ((lc = login_getclass(class)) != NULL) {
1443 		setusercontext(lc, NULL, 0,
1444 		    LOGIN_SETPRIORITY|LOGIN_SETRESOURCES|LOGIN_SETUMASK);
1445 		login_close(lc);
1446 	}
1447 }
1448