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