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