xref: /openbsd-src/sbin/init/init.c (revision 50b7afb2c2c0993b0894d4e34bf857cb13ed9c80)
1 /*	$OpenBSD: init.c,v 1.50 2014/04/22 20:40:37 tedu 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/param.h>
37 #include <sys/sysctl.h>
38 #include <sys/wait.h>
39 #include <sys/reboot.h>
40 #include <machine/cpu.h>
41 
42 #include <db.h>
43 #include <err.h>
44 #include <errno.h>
45 #include <fcntl.h>
46 #include <signal.h>
47 #include <stdarg.h>
48 #include <stdio.h>
49 #include <stdlib.h>
50 #include <string.h>
51 #include <syslog.h>
52 #include <time.h>
53 #include <ttyent.h>
54 #include <unistd.h>
55 #include <util.h>
56 
57 #ifdef SECURE
58 #include <pwd.h>
59 #endif
60 
61 #ifdef LOGIN_CAP
62 #include <login_cap.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 /*
97  * We really need a recursive typedef...
98  * The following at least guarantees that the return type of (*state_t)()
99  * is sufficiently wide to hold a function pointer.
100  */
101 typedef long (*state_func_t)(void);
102 typedef state_func_t (*state_t)(void);
103 
104 state_func_t single_user(void);
105 state_func_t runcom(void);
106 state_func_t read_ttys(void);
107 state_func_t multi_user(void);
108 state_func_t clean_ttys(void);
109 state_func_t catatonia(void);
110 state_func_t death(void);
111 state_func_t do_reboot(void);
112 state_func_t hard_death(void);
113 state_func_t nice_death(void);
114 
115 enum { AUTOBOOT, FASTBOOT } runcom_mode = AUTOBOOT;
116 
117 void transition(state_t);
118 state_t requested_transition = DEFAULT_STATE;
119 
120 void setctty(char *);
121 
122 typedef struct init_session {
123 	int	se_index;		/* index of entry in ttys file */
124 	pid_t	se_process;		/* controlling process */
125 	time_t	se_started;		/* used to avoid thrashing */
126 	int	se_flags;		/* status of session */
127 #define	SE_SHUTDOWN	0x1		/* session won't be restarted */
128 #define	SE_PRESENT	0x2		/* session is in /etc/ttys */
129 #define	SE_DEVEXISTS	0x4		/* open does not result in ENODEV */
130 	char	*se_device;		/* filename of port */
131 	char	*se_getty;		/* what to run on that port */
132 	char	**se_getty_argv;	/* pre-parsed argument array */
133 	char	*se_window;		/* window system (started only once) */
134 	char	**se_window_argv;	/* pre-parsed argument array */
135 	struct	init_session *se_prev;
136 	struct	init_session *se_next;
137 } session_t;
138 
139 void free_session(session_t *);
140 session_t *new_session(session_t *, int, struct ttyent *);
141 session_t *sessions;
142 
143 char **construct_argv(char *);
144 void start_window_system(session_t *);
145 void collect_child(pid_t);
146 pid_t start_getty(session_t *);
147 void transition_handler(int);
148 void alrm_handler(int);
149 void setsecuritylevel(int);
150 int getsecuritylevel(void);
151 int setupargv(session_t *, struct ttyent *);
152 int clang;
153 
154 #ifdef LOGIN_CAP
155 void setprocresources(char *);
156 #else
157 #define setprocresources(p)
158 #endif
159 
160 void clear_session_logs(session_t *);
161 
162 int start_session_db(void);
163 void add_session(session_t *);
164 void del_session(session_t *);
165 session_t *find_session(pid_t);
166 DB *session_db;
167 
168 /*
169  * The mother of all processes.
170  */
171 int
172 main(int argc, char *argv[])
173 {
174 	int c;
175 	struct sigaction sa;
176 	sigset_t mask;
177 
178 	/* Dispose of random users. */
179 	if (getuid() != 0) {
180 		(void)fprintf(stderr, "init: %s\n", strerror(EPERM));
181 		exit (1);
182 	}
183 
184 	/* System V users like to reexec init. */
185 	if (getpid() != 1) {
186 		(void)fprintf(stderr, "init: already running\n");
187 		exit (1);
188 	}
189 
190 	/*
191 	 * Note that this does NOT open a file...
192 	 * Does 'init' deserve its own facility number?
193 	 */
194 	openlog("init", LOG_CONS|LOG_ODELAY, LOG_AUTH);
195 
196 	/*
197 	 * Create an initial session.
198 	 */
199 	if (setsid() < 0)
200 		warning("initial setsid() failed: %m");
201 
202 	/*
203 	 * Establish an initial user so that programs running
204 	 * single user do not freak out and die (like passwd).
205 	 */
206 	if (setlogin("root") < 0)
207 		warning("setlogin() failed: %m");
208 
209 	/*
210 	 * This code assumes that we always get arguments through flags,
211 	 * never through bits set in some random machine register.
212 	 */
213 	while ((c = getopt(argc, argv, "sf")) != -1)
214 		switch (c) {
215 		case 's':
216 			requested_transition = single_user;
217 			break;
218 		case 'f':
219 			runcom_mode = FASTBOOT;
220 			break;
221 		default:
222 			warning("unrecognized flag '-%c'", c);
223 			break;
224 		}
225 
226 	if (optind != argc)
227 		warning("ignoring excess arguments");
228 
229 	/*
230 	 * We catch or block signals rather than ignore them,
231 	 * so that they get reset on exec.
232 	 */
233 	handle(badsys, SIGSYS, 0);
234 	handle(disaster, SIGABRT, SIGFPE, SIGILL, SIGSEGV,
235 	    SIGBUS, SIGXCPU, SIGXFSZ, 0);
236 	handle(transition_handler, SIGHUP, SIGINT, SIGTERM, SIGTSTP,
237             SIGUSR1, SIGUSR2, 0);
238 	handle(alrm_handler, SIGALRM, 0);
239 	sigfillset(&mask);
240 	delset(&mask, SIGABRT, SIGFPE, SIGILL, SIGSEGV, SIGBUS, SIGSYS,
241 	    SIGXCPU, SIGXFSZ, SIGHUP, SIGINT, SIGTERM, SIGUSR1, SIGUSR2,
242 	    SIGTSTP, SIGALRM, 0);
243 	sigprocmask(SIG_SETMASK, &mask, NULL);
244 	memset(&sa, 0, sizeof sa);
245 	sigemptyset(&sa.sa_mask);
246 	sa.sa_flags = 0;
247 	sa.sa_handler = SIG_IGN;
248 	(void) sigaction(SIGTTIN, &sa, NULL);
249 	(void) sigaction(SIGTTOU, &sa, NULL);
250 
251 	/*
252 	 * Paranoia.
253 	 */
254 	close(STDIN_FILENO);
255 	close(STDOUT_FILENO);
256 	close(STDERR_FILENO);
257 
258 	/*
259 	 * Start the state machine.
260 	 */
261 	transition(requested_transition);
262 
263 	/*
264 	 * Should never reach here.
265 	 */
266 	exit(1);
267 }
268 
269 /*
270  * Associate a function with a signal handler.
271  */
272 void
273 handle(sig_t handler, ...)
274 {
275 	int sig;
276 	struct sigaction sa;
277 	sigset_t mask_everything;
278 	va_list ap;
279 
280 	va_start(ap, handler);
281 
282 	memset(&sa, 0, sizeof sa);
283 	sa.sa_handler = handler;
284 	sigfillset(&mask_everything);
285 
286 	while ((sig = va_arg(ap, int))) {
287 		sa.sa_mask = mask_everything;
288 		/* XXX SA_RESTART? */
289 		sa.sa_flags = sig == SIGCHLD ? SA_NOCLDSTOP : 0;
290 		sigaction(sig, &sa, NULL);
291 	}
292 	va_end(ap);
293 }
294 
295 /*
296  * Delete a set of signals from a mask.
297  */
298 void
299 delset(sigset_t *maskp, ...)
300 {
301 	int sig;
302 	va_list ap;
303 
304 	va_start(ap, maskp);
305 	while ((sig = va_arg(ap, int)))
306 		sigdelset(maskp, sig);
307 	va_end(ap);
308 }
309 
310 /*
311  * Log a message and sleep for a while (to give someone an opportunity
312  * to read it and to save log or hardcopy output if the problem is chronic).
313  * NB: should send a message to the session logger to avoid blocking.
314  */
315 void
316 stall(char *message, ...)
317 {
318 	va_list ap;
319 
320 	va_start(ap, message);
321 	vsyslog(LOG_ALERT, message, ap);
322 	va_end(ap);
323 	closelog();
324 	sleep(STALL_TIMEOUT);
325 }
326 
327 /*
328  * Like stall(), but doesn't sleep.
329  * If cpp had variadic macros, the two functions could be #defines for another.
330  * NB: should send a message to the session logger to avoid blocking.
331  */
332 void
333 warning(char *message, ...)
334 {
335 	va_list ap;
336 
337 	va_start(ap, message);
338 	vsyslog(LOG_ALERT, message, ap);
339 	va_end(ap);
340 	closelog();
341 }
342 
343 /*
344  * Log an emergency message.
345  * NB: should send a message to the session logger to avoid blocking.
346  */
347 void
348 emergency(char *message, ...)
349 {
350 	struct syslog_data sdata = SYSLOG_DATA_INIT;
351 	va_list ap;
352 
353 	va_start(ap, message);
354 	vsyslog_r(LOG_EMERG, &sdata, message, ap);
355 	va_end(ap);
356 }
357 
358 /*
359  * Catch a SIGSYS signal.
360  *
361  * These may arise if a system does not support sysctl.
362  * We tolerate up to 25 of these, then throw in the towel.
363  */
364 void
365 badsys(int sig)
366 {
367 	static int badcount = 0;
368 
369 	if (badcount++ < 25)
370 		return;
371 	disaster(sig);
372 }
373 
374 /*
375  * Catch an unexpected signal.
376  */
377 void
378 disaster(int sig)
379 {
380 	emergency("fatal signal: %s", strsignal(sig));
381 
382 	sleep(STALL_TIMEOUT);
383 	_exit(sig);		/* reboot */
384 }
385 
386 /*
387  * Get the security level of the kernel.
388  */
389 int
390 getsecuritylevel(void)
391 {
392 #ifdef KERN_SECURELVL
393 	int name[2], curlevel;
394 	size_t len;
395 
396 	name[0] = CTL_KERN;
397 	name[1] = KERN_SECURELVL;
398 	len = sizeof curlevel;
399 	if (sysctl(name, 2, &curlevel, &len, NULL, 0) == -1) {
400 		emergency("cannot get kernel security level: %s",
401 		    strerror(errno));
402 		return (-1);
403 	}
404 	return (curlevel);
405 #else
406 	return (-1);
407 #endif
408 }
409 
410 /*
411  * Set the security level of the kernel.
412  */
413 void
414 setsecuritylevel(int newlevel)
415 {
416 #ifdef KERN_SECURELVL
417 	int name[2], curlevel;
418 
419 	curlevel = getsecuritylevel();
420 	if (newlevel == curlevel)
421 		return;
422 	name[0] = CTL_KERN;
423 	name[1] = KERN_SECURELVL;
424 	if (sysctl(name, 2, NULL, NULL, &newlevel, sizeof newlevel) == -1) {
425 		emergency(
426 		    "cannot change kernel security level from %d to %d: %s",
427 		    curlevel, newlevel, strerror(errno));
428 		return;
429 	}
430 #ifdef SECURE
431 	warning("kernel security level changed from %d to %d",
432 	    curlevel, newlevel);
433 #endif
434 #endif
435 }
436 
437 /*
438  * Change states in the finite state machine.
439  * The initial state is passed as an argument.
440  */
441 void
442 transition(state_t s)
443 {
444 	for (;;)
445 		s = (state_t) (*s)();
446 }
447 
448 /*
449  * Close out the accounting files for a login session.
450  * NB: should send a message to the session logger to avoid blocking.
451  */
452 void
453 clear_session_logs(session_t *sp)
454 {
455 	char *line = sp->se_device + sizeof(_PATH_DEV) - 1;
456 
457 	if (logout(line))
458 		logwtmp(line, "", "");
459 }
460 
461 /*
462  * Start a session and allocate a controlling terminal.
463  * Only called by children of init after forking.
464  */
465 void
466 setctty(char *name)
467 {
468 	int fd;
469 
470 	(void) revoke(name);
471 	sleep(2);			/* leave DTR low */
472 	if ((fd = open(name, O_RDWR)) == -1) {
473 		stall("can't open %s: %m", name);
474 		_exit(1);
475 	}
476 	if (login_tty(fd) == -1) {
477 		stall("can't get %s for controlling terminal: %m", name);
478 		_exit(1);
479 	}
480 }
481 
482 /*
483  * Bring the system up single user.
484  */
485 state_func_t
486 single_user(void)
487 {
488 	pid_t pid, wpid;
489 	int status;
490 	sigset_t mask;
491 	char shell[MAXPATHLEN];		/* Allocate space here */
492 	char name[MAXPATHLEN];		/* Name (argv[0]) of shell */
493 	char *argv[2];
494 #ifdef SECURE
495 	struct ttyent *typ;
496 	struct passwd *pp;
497 	static const char banner[] =
498 		"Enter root password, or ^D to go multi-user\n";
499 	char *clear, *password;
500 #endif
501 
502 	/* Init shell and name */
503 	strlcpy(shell, _PATH_BSHELL, sizeof shell);
504 	strlcpy(name, "-sh", sizeof name);
505 
506 	/*
507 	 * If the kernel is in secure mode, downgrade it to insecure mode.
508 	 */
509 	if (getsecuritylevel() > 0)
510 		setsecuritylevel(0);
511 
512 	if ((pid = fork()) == 0) {
513 		/*
514 		 * Start the single user session.
515 		 */
516 		setctty(_PATH_CONSOLE);
517 
518 #ifdef SECURE
519 		/*
520 		 * Check the root password.
521 		 * We don't care if the console is 'on' by default;
522 		 * it's the only tty that can be 'off' and 'secure'.
523 		 */
524 		typ = getttynam("console");
525 		pp = getpwnam("root");
526 		if (typ && (typ->ty_status & TTY_SECURE) == 0 && pp &&
527 		    *pp->pw_passwd) {
528 			write(STDERR_FILENO, banner, sizeof banner - 1);
529 			for (;;) {
530 				clear = getpass("Password:");
531 				if (clear == 0 || *clear == '\0')
532 					_exit(0);
533 				password = crypt(clear, pp->pw_passwd);
534 				memset(clear, 0, _PASSWORD_LEN);
535 				if (strcmp(password, pp->pw_passwd) == 0)
536 					break;
537 				warning("single-user login failed\n");
538 			}
539 		}
540 		endttyent();
541 		endpwent();
542 #endif /* SECURE */
543 
544 #ifdef DEBUGSHELL
545 		{
546 			char altshell[128], *cp = altshell;
547 			int num;
548 
549 #define	SHREQUEST \
550 	"Enter pathname of shell or RETURN for sh: "
551 
552 			(void)write(STDERR_FILENO,
553 			    SHREQUEST, sizeof(SHREQUEST) - 1);
554 			while ((num = read(STDIN_FILENO, cp, 1)) != -1 &&
555 			    num != 0 && *cp != '\n' && cp < &altshell[127])
556 				cp++;
557 			*cp = '\0';
558 
559 			/* Copy in alternate shell */
560 			if (altshell[0] != '\0'){
561 				char *p;
562 
563 				/* Binary to exec */
564 				strlcpy(shell, altshell, sizeof shell);
565 
566 				/* argv[0] */
567 				p = strrchr(altshell, '/');
568 				if(p == NULL) p = altshell;
569 				else p++;
570 
571 				name[0] = '-';
572 				strlcpy(&name[1], p, sizeof name -1);
573 			}
574 		}
575 #endif /* DEBUGSHELL */
576 
577 		/*
578 		 * Unblock signals.
579 		 * We catch all the interesting ones,
580 		 * and those are reset to SIG_DFL on exec.
581 		 */
582 		sigemptyset(&mask);
583 		sigprocmask(SIG_SETMASK, &mask, NULL);
584 
585 		/*
586 		 * Fire off a shell.
587 		 * If the default one doesn't work, try the Bourne shell.
588 		 */
589 		argv[0] = name;
590 		argv[1] = NULL;
591 		setenv("PATH", _PATH_STDPATH, 1);
592 		execv(shell, argv);
593 		emergency("can't exec %s for single user: %m", shell);
594 
595 		argv[0] = "-sh";
596 		argv[1] = NULL;
597 		execv(_PATH_BSHELL, argv);
598 		emergency("can't exec %s for single user: %m", _PATH_BSHELL);
599 		sleep(STALL_TIMEOUT);
600 		_exit(1);
601 	}
602 
603 	if (pid == -1) {
604 		/*
605 		 * We are seriously hosed.  Do our best.
606 		 */
607 		emergency("can't fork single-user shell, trying again");
608 		while (waitpid(-1, NULL, WNOHANG) > 0)
609 			continue;
610 		return (state_func_t) single_user;
611 	}
612 
613 	requested_transition = 0;
614 	do {
615 		if ((wpid = waitpid(-1, &status, WUNTRACED)) != -1)
616 			collect_child(wpid);
617 		if (wpid == -1) {
618 			if (errno == EINTR)
619 				continue;
620 			warning("wait for single-user shell failed: %m; restarting");
621 			return (state_func_t) single_user;
622 		}
623 		if (wpid == pid && WIFSTOPPED(status)) {
624 			warning("init: shell stopped, restarting\n");
625 			kill(pid, SIGCONT);
626 			wpid = -1;
627 		}
628 	} while (wpid != pid && !requested_transition);
629 
630 	if (requested_transition)
631 		return (state_func_t) requested_transition;
632 
633 	if (!WIFEXITED(status)) {
634 		if (WTERMSIG(status) == SIGKILL) {
635 			/*
636 			 *  reboot(8) killed shell?
637 			 */
638 			warning("single user shell terminated.");
639 			sleep(STALL_TIMEOUT);
640 			_exit(0);
641 		} else {
642 			warning("single user shell terminated, restarting");
643 			return (state_func_t) single_user;
644 		}
645 	}
646 
647 	runcom_mode = FASTBOOT;
648 	return (state_func_t) runcom;
649 }
650 
651 /*
652  * Run the system startup script.
653  */
654 state_func_t
655 runcom(void)
656 {
657 	pid_t pid, wpid;
658 	int status;
659 	char *argv[4];
660 	struct sigaction sa;
661 
662 	if ((pid = fork()) == 0) {
663 		memset(&sa, 0, sizeof sa);
664 		sigemptyset(&sa.sa_mask);
665 		sa.sa_flags = 0;
666 		sa.sa_handler = SIG_IGN;
667 		(void) sigaction(SIGTSTP, &sa, NULL);
668 		(void) sigaction(SIGHUP, &sa, NULL);
669 
670 		setctty(_PATH_CONSOLE);
671 
672 		argv[0] = "sh";
673 		argv[1] = _PATH_RUNCOM;
674 		argv[2] = runcom_mode == AUTOBOOT ? "autoboot" : 0;
675 		argv[3] = 0;
676 
677 		sigprocmask(SIG_SETMASK, &sa.sa_mask, NULL);
678 
679 		setprocresources(RESOURCE_RC);
680 
681 		execv(_PATH_BSHELL, argv);
682 		stall("can't exec %s for %s: %m", _PATH_BSHELL, _PATH_RUNCOM);
683 		_exit(1);	/* force single user mode */
684 	}
685 
686 	if (pid == -1) {
687 		emergency("can't fork for %s on %s: %m",
688 			_PATH_BSHELL, _PATH_RUNCOM);
689 		while (waitpid(-1, NULL, WNOHANG) > 0)
690 			continue;
691 		sleep(STALL_TIMEOUT);
692 		return (state_func_t) single_user;
693 	}
694 
695 	/*
696 	 * Copied from single_user().  This is a bit paranoid.
697 	 */
698 	do {
699 		if ((wpid = waitpid(-1, &status, WUNTRACED)) != -1)
700 			collect_child(wpid);
701 		if (wpid == -1) {
702 			if (errno == EINTR)
703 				continue;
704 			warning("wait for %s on %s failed: %m; going to single user mode",
705 			    _PATH_BSHELL, _PATH_RUNCOM);
706 			return (state_func_t) single_user;
707 		}
708 		if (wpid == pid && WIFSTOPPED(status)) {
709 			warning("init: %s on %s stopped, restarting\n",
710 			    _PATH_BSHELL, _PATH_RUNCOM);
711 			kill(pid, SIGCONT);
712 			wpid = -1;
713 		}
714 	} while (wpid != pid);
715 
716 	if (WIFSIGNALED(status) && WTERMSIG(status) == SIGTERM &&
717 	    requested_transition == catatonia) {
718 		/* /etc/rc executed /sbin/reboot; wait for the end quietly */
719 		sigset_t s;
720 
721 		sigfillset(&s);
722 		for (;;)
723 			sigsuspend(&s);
724 	}
725 
726 	if (!WIFEXITED(status)) {
727 		warning("%s on %s terminated abnormally, going to single user mode",
728 		    _PATH_BSHELL, _PATH_RUNCOM);
729 		return (state_func_t) single_user;
730 	}
731 
732 	if (WEXITSTATUS(status))
733 		return (state_func_t) single_user;
734 
735 	runcom_mode = AUTOBOOT;		/* the default */
736 	/* NB: should send a message to the session logger to avoid blocking. */
737 	logwtmp("~", "reboot", "");
738 	return (state_func_t) read_ttys;
739 }
740 
741 /*
742  * Open the session database.
743  *
744  * NB: We could pass in the size here; is it necessary?
745  */
746 int
747 start_session_db(void)
748 {
749 	if (session_db && (*session_db->close)(session_db))
750 		emergency("session database close: %s", strerror(errno));
751 	if ((session_db = dbopen(NULL, O_RDWR, 0, DB_HASH, NULL)) == 0) {
752 		emergency("session database open: %s", strerror(errno));
753 		return (1);
754 	}
755 	return (0);
756 }
757 
758 /*
759  * Add a new login session.
760  */
761 void
762 add_session(session_t *sp)
763 {
764 	DBT key;
765 	DBT data;
766 
767 	key.data = &sp->se_process;
768 	key.size = sizeof sp->se_process;
769 	data.data = &sp;
770 	data.size = sizeof sp;
771 
772 	if ((*session_db->put)(session_db, &key, &data, 0))
773 		emergency("insert %d: %s", sp->se_process, strerror(errno));
774 }
775 
776 /*
777  * Delete an old login session.
778  */
779 void
780 del_session(session_t *sp)
781 {
782 	DBT key;
783 
784 	key.data = &sp->se_process;
785 	key.size = sizeof sp->se_process;
786 
787 	if ((*session_db->del)(session_db, &key, 0))
788 		emergency("delete %d: %s", sp->se_process, strerror(errno));
789 }
790 
791 /*
792  * Look up a login session by pid.
793  */
794 session_t *
795 find_session(pid_t pid)
796 {
797 	DBT key;
798 	DBT data;
799 	session_t *ret;
800 
801 	key.data = &pid;
802 	key.size = sizeof pid;
803 	if ((*session_db->get)(session_db, &key, &data, 0) != 0)
804 		return (0);
805 	memcpy(&ret, data.data, sizeof(ret));
806 	return (ret);
807 }
808 
809 /*
810  * Construct an argument vector from a command line.
811  */
812 char **
813 construct_argv(char *command)
814 {
815 	int argc = 0;
816 	char **argv = (char **) calloc((strlen(command) + 1) / 2 + 1,
817 	    sizeof (char *));
818 	static const char separators[] = " \t";
819 
820 	if (argv == NULL)
821 		return (0);
822 
823 	if ((argv[argc++] = strtok(command, separators)) == 0) {
824 		free(argv);
825 		return (0);
826 	}
827 	while ((argv[argc++] = strtok(NULL, separators)))
828 		continue;
829 	return (argv);
830 }
831 
832 /*
833  * Deallocate a session descriptor.
834  */
835 void
836 free_session(session_t *sp)
837 {
838 	free(sp->se_device);
839 	if (sp->se_getty) {
840 		free(sp->se_getty);
841 		free(sp->se_getty_argv);
842 	}
843 	if (sp->se_window) {
844 		free(sp->se_window);
845 		free(sp->se_window_argv);
846 	}
847 	free(sp);
848 }
849 
850 /*
851  * Allocate a new session descriptor.
852  */
853 session_t *
854 new_session(session_t *sprev, int session_index, struct ttyent *typ)
855 {
856 	session_t *sp;
857 
858 	if ((typ->ty_status & TTY_ON) == 0 ||
859 	    typ->ty_name == 0 ||
860 	    typ->ty_getty == 0)
861 		return (0);
862 
863 	sp = calloc(1, sizeof (session_t));
864 	if (sp == NULL)
865 		err(1, "calloc");
866 
867 	sp->se_flags = SE_PRESENT;
868 	sp->se_index = session_index;
869 
870 	if (asprintf(&sp->se_device, "%s%s", _PATH_DEV, typ->ty_name) == -1)
871 		err(1, "asprintf");
872 
873 	if (setupargv(sp, typ) == 0) {
874 		free_session(sp);
875 		return (0);
876 	}
877 
878 	sp->se_next = 0;
879 	if (sprev == 0) {
880 		sessions = sp;
881 		sp->se_prev = 0;
882 	} else {
883 		sprev->se_next = sp;
884 		sp->se_prev = sprev;
885 	}
886 
887 	return (sp);
888 }
889 
890 /*
891  * Calculate getty and if useful window argv vectors.
892  */
893 int
894 setupargv(session_t *sp, struct ttyent *typ)
895 {
896 	if (sp->se_getty) {
897 		free(sp->se_getty);
898 		free(sp->se_getty_argv);
899 	}
900 	if (asprintf(&sp->se_getty, "%s %s", typ->ty_getty, typ->ty_name) == -1)
901 		err(1, "asprintf");
902 	sp->se_getty_argv = construct_argv(sp->se_getty);
903 	if (sp->se_getty_argv == 0) {
904 		warning("can't parse getty for port %s", sp->se_device);
905 		free(sp->se_getty);
906 		sp->se_getty = 0;
907 		return (0);
908 	}
909 	if (typ->ty_window) {
910 		if (sp->se_window)
911 			free(sp->se_window);
912 		sp->se_window = strdup(typ->ty_window);
913 		if (sp->se_window == NULL) {
914 			warning("can't allocate window");
915 			return (0);
916 		}
917 		sp->se_window_argv = construct_argv(sp->se_window);
918 		if (sp->se_window_argv == NULL) {
919 			warning("can't parse window for port %s",
920 			    sp->se_device);
921 			free(sp->se_window);
922 			sp->se_window = NULL;
923 			return (0);
924 		}
925 	}
926 	return (1);
927 }
928 
929 /*
930  * Walk the list of ttys and create sessions for each active line.
931  */
932 state_func_t
933 read_ttys(void)
934 {
935 	int session_index = 0;
936 	session_t *sp, *snext;
937 	struct ttyent *typ;
938 
939 	/*
940 	 * Destroy any previous session state.
941 	 * There shouldn't be any, but just in case...
942 	 */
943 	for (sp = sessions; sp; sp = snext) {
944 		if (sp->se_process)
945 			clear_session_logs(sp);
946 		snext = sp->se_next;
947 		free_session(sp);
948 	}
949 	sessions = 0;
950 	if (start_session_db())
951 		return (state_func_t) single_user;
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 (state_func_t) 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_func_t
1164 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 (state_func_t) requested_transition;
1200 }
1201 
1202 /*
1203  * This is an n-squared algorithm.  We hope it isn't run often...
1204  */
1205 state_func_t
1206 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 = 0, 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 (state_func_t) multi_user;
1260 }
1261 
1262 /*
1263  * Block further logins.
1264  */
1265 state_func_t
1266 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 (state_func_t) 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_func_t
1291 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_func_t
1302 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_func_t
1312 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_LIDSUSPEND
1321 	int lidsuspend_mib[] = {CTL_MACHDEP, CPU_LIDSUSPEND};
1322 	int dontsuspend = 0;
1323 
1324 	if ((death_howto & RB_POWERDOWN) &&
1325 	    (sysctl(lidsuspend_mib, 2, NULL, NULL, &dontsuspend,
1326 		    sizeof(dontsuspend)) == -1) && (errno != EOPNOTSUPP))
1327 			warning("cannot disable lid suspend");
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 		pid_t pid;
1344 		struct sigaction sa;
1345 
1346 		switch ((pid = fork())) {
1347 		case -1:
1348 			break;
1349 		case 0:
1350 
1351 			memset(&sa, 0, sizeof sa);
1352 			sigemptyset(&sa.sa_mask);
1353 			sa.sa_flags = 0;
1354 			sa.sa_handler = SIG_IGN;
1355 			(void) sigaction(SIGTSTP, &sa, NULL);
1356 			(void) sigaction(SIGHUP, &sa, NULL);
1357 
1358 			setctty(_PATH_CONSOLE);
1359 
1360 			sigprocmask(SIG_SETMASK, &sa.sa_mask, NULL);
1361 
1362 			execl(_PATH_BSHELL, "sh", _PATH_RUNCOM, "shutdown",
1363 			    (char *)NULL);
1364 			stall("can't exec %s for %s %s: %m", _PATH_BSHELL,
1365 			    _PATH_RUNCOM, "shutdown");
1366 			_exit(1);
1367 		default:
1368 			waitpid(pid, &status, 0);
1369 			if (WIFEXITED(status) && WEXITSTATUS(status) == 2)
1370 				death_howto |= RB_POWERDOWN;
1371 		}
1372 	}
1373 
1374 	for (i = 0; i < 3; ++i) {
1375 		if (kill(-1, death_sigs[i]) == -1 && errno == ESRCH)
1376 			goto die;
1377 
1378 		clang = 0;
1379 		alarm(DEATH_WATCH);
1380 		do {
1381 			if ((pid = waitpid(-1, NULL, 0)) != -1)
1382 				collect_child(pid);
1383 		} while (clang == 0 && errno != ECHILD);
1384 
1385 		if (errno == ECHILD)
1386 			goto die;
1387 	}
1388 
1389 	warning("some processes would not die; ps axl advised");
1390 
1391 die:
1392 	reboot(death_howto);
1393 
1394 	/* ... and if that fails.. oh well */
1395 	return (state_func_t) single_user;
1396 }
1397 
1398 /*
1399  * Bring the system down to single user.
1400  */
1401 state_func_t
1402 death(void)
1403 {
1404 	session_t *sp;
1405 	int i;
1406 	pid_t pid;
1407 	static const int death_sigs[3] = { SIGHUP, SIGTERM, SIGKILL };
1408 
1409 	/* terminate the accounting process */
1410 	acct(NULL);
1411 
1412 	for (sp = sessions; sp; sp = sp->se_next)
1413 		sp->se_flags |= SE_SHUTDOWN;
1414 
1415 	/* NB: should send a message to the session logger to avoid blocking. */
1416 	logwtmp("~", "shutdown", "");
1417 
1418 	for (i = 0; i < 3; ++i) {
1419 		if (kill(-1, death_sigs[i]) == -1 && errno == ESRCH)
1420 			return (state_func_t) single_user;
1421 
1422 		clang = 0;
1423 		alarm(DEATH_WATCH);
1424 		do {
1425 			if ((pid = waitpid(-1, NULL, 0)) != -1)
1426 				collect_child(pid);
1427 		} while (clang == 0 && errno != ECHILD);
1428 
1429 		if (errno == ECHILD)
1430 			return (state_func_t) single_user;
1431 	}
1432 
1433 	warning("some processes would not die; ps axl advised");
1434 
1435 	return (state_func_t) single_user;
1436 }
1437 
1438 #ifdef LOGIN_CAP
1439 void
1440 setprocresources(char *class)
1441 {
1442 	login_cap_t *lc;
1443 
1444 	if ((lc = login_getclass(class)) != NULL) {
1445 		setusercontext(lc, NULL, 0,
1446 		    LOGIN_SETPRIORITY|LOGIN_SETRESOURCES|LOGIN_SETUMASK);
1447 		login_close(lc);
1448 	}
1449 }
1450 #endif
1451