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