init.c revision 217750
1/*-
2 * Copyright (c) 1991, 1993
3 *	The Regents of the University of California.  All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Donn Seeley at Berkeley Software Design, Inc.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 * 4. Neither the name of the University nor the names of its contributors
17 *    may be used to endorse or promote products derived from this software
18 *    without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33#ifndef lint
34static const char copyright[] =
35"@(#) Copyright (c) 1991, 1993\n\
36	The Regents of the University of California.  All rights reserved.\n";
37#endif /* not lint */
38
39#ifndef lint
40#if 0
41static char sccsid[] = "@(#)init.c	8.1 (Berkeley) 7/15/93";
42#endif
43static const char rcsid[] =
44  "$FreeBSD: head/sbin/init/init.c 217750 2011-01-23 14:22:26Z jilles $";
45#endif /* not lint */
46
47#include <sys/param.h>
48#include <sys/ioctl.h>
49#include <sys/mount.h>
50#include <sys/sysctl.h>
51#include <sys/wait.h>
52#include <sys/stat.h>
53#include <sys/uio.h>
54
55#include <db.h>
56#include <errno.h>
57#include <fcntl.h>
58#include <kenv.h>
59#include <libutil.h>
60#include <paths.h>
61#include <signal.h>
62#include <stdio.h>
63#include <stdlib.h>
64#include <string.h>
65#include <syslog.h>
66#include <time.h>
67#include <ttyent.h>
68#include <unistd.h>
69#include <utmpx.h>
70#include <sys/reboot.h>
71#include <err.h>
72
73#include <stdarg.h>
74
75#ifdef SECURE
76#include <pwd.h>
77#endif
78
79#ifdef LOGIN_CAP
80#include <login_cap.h>
81#endif
82
83#include "pathnames.h"
84
85/*
86 * Sleep times; used to prevent thrashing.
87 */
88#define	GETTY_SPACING		 5	/* N secs minimum getty spacing */
89#define	GETTY_SLEEP		30	/* sleep N secs after spacing problem */
90#define	GETTY_NSPACE             3      /* max. spacing count to bring reaction */
91#define	WINDOW_WAIT		 3	/* wait N secs after starting window */
92#define	STALL_TIMEOUT		30	/* wait N secs after warning */
93#define	DEATH_WATCH		10	/* wait N secs for procs to die */
94#define	DEATH_SCRIPT		120	/* wait for 2min for /etc/rc.shutdown */
95#define	RESOURCE_RC		"daemon"
96#define	RESOURCE_WINDOW 	"default"
97#define	RESOURCE_GETTY		"default"
98
99static void handle(sig_t, ...);
100static void delset(sigset_t *, ...);
101
102static void stall(const char *, ...) __printflike(1, 2);
103static void warning(const char *, ...) __printflike(1, 2);
104static void emergency(const char *, ...) __printflike(1, 2);
105static void disaster(int);
106static void badsys(int);
107static int  runshutdown(void);
108static char *strk(char *);
109
110/*
111 * We really need a recursive typedef...
112 * The following at least guarantees that the return type of (*state_t)()
113 * is sufficiently wide to hold a function pointer.
114 */
115typedef long (*state_func_t)(void);
116typedef state_func_t (*state_t)(void);
117
118static state_func_t single_user(void);
119static state_func_t runcom(void);
120static state_func_t read_ttys(void);
121static state_func_t multi_user(void);
122static state_func_t clean_ttys(void);
123static state_func_t catatonia(void);
124static state_func_t death(void);
125static state_func_t death_single(void);
126
127static state_func_t run_script(const char *);
128
129enum { AUTOBOOT, FASTBOOT } runcom_mode = AUTOBOOT;
130#define FALSE	0
131#define TRUE	1
132
133int Reboot = FALSE;
134int howto = RB_AUTOBOOT;
135
136int devfs;
137
138static void transition(state_t);
139static state_t requested_transition;
140static state_t current_state = death_single;
141
142static void setctty(const char *);
143static const char *get_shell(void);
144static void write_stderr(const char *message);
145
146typedef struct init_session {
147	int	se_index;		/* index of entry in ttys file */
148	pid_t	se_process;		/* controlling process */
149	time_t	se_started;		/* used to avoid thrashing */
150	int	se_flags;		/* status of session */
151#define	SE_SHUTDOWN	0x1		/* session won't be restarted */
152#define	SE_PRESENT	0x2		/* session is in /etc/ttys */
153	int     se_nspace;              /* spacing count */
154	char	*se_device;		/* filename of port */
155	char	*se_getty;		/* what to run on that port */
156	char    *se_getty_argv_space;   /* pre-parsed argument array space */
157	char	**se_getty_argv;	/* pre-parsed argument array */
158	char	*se_window;		/* window system (started only once) */
159	char    *se_window_argv_space;  /* pre-parsed argument array space */
160	char	**se_window_argv;	/* pre-parsed argument array */
161	char    *se_type;               /* default terminal type */
162	struct	init_session *se_prev;
163	struct	init_session *se_next;
164} session_t;
165
166static void free_session(session_t *);
167static session_t *new_session(session_t *, int, struct ttyent *);
168static session_t *sessions;
169
170static char **construct_argv(char *);
171static void start_window_system(session_t *);
172static void collect_child(pid_t);
173static pid_t start_getty(session_t *);
174static void transition_handler(int);
175static void alrm_handler(int);
176static void setsecuritylevel(int);
177static int getsecuritylevel(void);
178static int setupargv(session_t *, struct ttyent *);
179#ifdef LOGIN_CAP
180static void setprocresources(const char *);
181#endif
182static int clang;
183
184static void clear_session_logs(session_t *);
185
186static int start_session_db(void);
187static void add_session(session_t *);
188static void del_session(session_t *);
189static session_t *find_session(pid_t);
190static DB *session_db;
191
192/*
193 * The mother of all processes.
194 */
195int
196main(int argc, char *argv[])
197{
198	state_t initial_transition = runcom;
199	char kenv_value[PATH_MAX];
200	int c;
201	struct sigaction sa;
202	sigset_t mask;
203
204	/* Dispose of random users. */
205	if (getuid() != 0)
206		errx(1, "%s", strerror(EPERM));
207
208	/* System V users like to reexec init. */
209	if (getpid() != 1) {
210#ifdef COMPAT_SYSV_INIT
211		/* So give them what they want */
212		if (argc > 1) {
213			if (strlen(argv[1]) == 1) {
214				char runlevel = *argv[1];
215				int sig;
216
217				switch (runlevel) {
218				case '0': /* halt + poweroff */
219					sig = SIGUSR2;
220					break;
221				case '1': /* single-user */
222					sig = SIGTERM;
223					break;
224				case '6': /* reboot */
225					sig = SIGINT;
226					break;
227				case 'c': /* block further logins */
228					sig = SIGTSTP;
229					break;
230				case 'q': /* rescan /etc/ttys */
231					sig = SIGHUP;
232					break;
233				default:
234					goto invalid;
235				}
236				kill(1, sig);
237				_exit(0);
238			} else
239invalid:
240				errx(1, "invalid run-level ``%s''", argv[1]);
241		} else
242#endif
243			errx(1, "already running");
244	}
245	/*
246	 * Note that this does NOT open a file...
247	 * Does 'init' deserve its own facility number?
248	 */
249	openlog("init", LOG_CONS|LOG_ODELAY, LOG_AUTH);
250
251	/*
252	 * Create an initial session.
253	 */
254	if (setsid() < 0)
255		warning("initial setsid() failed: %m");
256
257	/*
258	 * Establish an initial user so that programs running
259	 * single user do not freak out and die (like passwd).
260	 */
261	if (setlogin("root") < 0)
262		warning("setlogin() failed: %m");
263
264	/*
265	 * This code assumes that we always get arguments through flags,
266	 * never through bits set in some random machine register.
267	 */
268	while ((c = getopt(argc, argv, "dsf")) != -1)
269		switch (c) {
270		case 'd':
271			devfs = 1;
272			break;
273		case 's':
274			initial_transition = single_user;
275			break;
276		case 'f':
277			runcom_mode = FASTBOOT;
278			break;
279		default:
280			warning("unrecognized flag '-%c'", c);
281			break;
282		}
283
284	if (optind != argc)
285		warning("ignoring excess arguments");
286
287	/*
288	 * We catch or block signals rather than ignore them,
289	 * so that they get reset on exec.
290	 */
291	handle(badsys, SIGSYS, 0);
292	handle(disaster, SIGABRT, SIGFPE, SIGILL, SIGSEGV, SIGBUS, SIGXCPU,
293	    SIGXFSZ, 0);
294	handle(transition_handler, SIGHUP, SIGINT, SIGTERM, SIGTSTP, SIGUSR1,
295	    SIGUSR2, 0);
296	handle(alrm_handler, SIGALRM, 0);
297	sigfillset(&mask);
298	delset(&mask, SIGABRT, SIGFPE, SIGILL, SIGSEGV, SIGBUS, SIGSYS,
299	    SIGXCPU, SIGXFSZ, SIGHUP, SIGINT, SIGTERM, SIGTSTP, SIGALRM,
300	    SIGUSR1, SIGUSR2, 0);
301	sigprocmask(SIG_SETMASK, &mask, (sigset_t *) 0);
302	sigemptyset(&sa.sa_mask);
303	sa.sa_flags = 0;
304	sa.sa_handler = SIG_IGN;
305	sigaction(SIGTTIN, &sa, (struct sigaction *)0);
306	sigaction(SIGTTOU, &sa, (struct sigaction *)0);
307
308	/*
309	 * Paranoia.
310	 */
311	close(0);
312	close(1);
313	close(2);
314
315	if (kenv(KENV_GET, "init_script", kenv_value, sizeof(kenv_value)) > 0) {
316		state_func_t next_transition;
317
318		if ((next_transition = run_script(kenv_value)) != 0)
319			initial_transition = (state_t) next_transition;
320	}
321
322	if (kenv(KENV_GET, "init_chroot", kenv_value, sizeof(kenv_value)) > 0) {
323		if (chdir(kenv_value) != 0 || chroot(".") != 0)
324			warning("Can't chroot to %s: %m", kenv_value);
325	}
326
327	/*
328	 * Additional check if devfs needs to be mounted:
329	 * If "/" and "/dev" have the same device number,
330	 * then it hasn't been mounted yet.
331	 */
332	if (!devfs) {
333		struct stat stst;
334		dev_t root_devno;
335
336		stat("/", &stst);
337		root_devno = stst.st_dev;
338		if (stat("/dev", &stst) != 0)
339			warning("Can't stat /dev: %m");
340		else if (stst.st_dev == root_devno)
341			devfs++;
342	}
343
344	if (devfs) {
345		struct iovec iov[4];
346		char *s;
347		int i;
348
349		char _fstype[]	= "fstype";
350		char _devfs[]	= "devfs";
351		char _fspath[]	= "fspath";
352		char _path_dev[]= _PATH_DEV;
353
354		iov[0].iov_base = _fstype;
355		iov[0].iov_len = sizeof(_fstype);
356		iov[1].iov_base = _devfs;
357		iov[1].iov_len = sizeof(_devfs);
358		iov[2].iov_base = _fspath;
359		iov[2].iov_len = sizeof(_fspath);
360		/*
361		 * Try to avoid the trailing slash in _PATH_DEV.
362		 * Be *very* defensive.
363		 */
364		s = strdup(_PATH_DEV);
365		if (s != NULL) {
366			i = strlen(s);
367			if (i > 0 && s[i - 1] == '/')
368				s[i - 1] = '\0';
369			iov[3].iov_base = s;
370			iov[3].iov_len = strlen(s) + 1;
371		} else {
372			iov[3].iov_base = _path_dev;
373			iov[3].iov_len = sizeof(_path_dev);
374		}
375		nmount(iov, 4, 0);
376		if (s != NULL)
377			free(s);
378	}
379
380	/*
381	 * Start the state machine.
382	 */
383	transition(initial_transition);
384
385	/*
386	 * Should never reach here.
387	 */
388	return 1;
389}
390
391/*
392 * Associate a function with a signal handler.
393 */
394static void
395handle(sig_t handler, ...)
396{
397	int sig;
398	struct sigaction sa;
399	sigset_t mask_everything;
400	va_list ap;
401	va_start(ap, handler);
402
403	sa.sa_handler = handler;
404	sigfillset(&mask_everything);
405
406	while ((sig = va_arg(ap, int)) != 0) {
407		sa.sa_mask = mask_everything;
408		/* XXX SA_RESTART? */
409		sa.sa_flags = sig == SIGCHLD ? SA_NOCLDSTOP : 0;
410		sigaction(sig, &sa, (struct sigaction *) 0);
411	}
412	va_end(ap);
413}
414
415/*
416 * Delete a set of signals from a mask.
417 */
418static void
419delset(sigset_t *maskp, ...)
420{
421	int sig;
422	va_list ap;
423	va_start(ap, maskp);
424
425	while ((sig = va_arg(ap, int)) != 0)
426		sigdelset(maskp, sig);
427	va_end(ap);
428}
429
430/*
431 * Log a message and sleep for a while (to give someone an opportunity
432 * to read it and to save log or hardcopy output if the problem is chronic).
433 * NB: should send a message to the session logger to avoid blocking.
434 */
435static void
436stall(const char *message, ...)
437{
438	va_list ap;
439	va_start(ap, message);
440
441	vsyslog(LOG_ALERT, message, ap);
442	va_end(ap);
443	sleep(STALL_TIMEOUT);
444}
445
446/*
447 * Like stall(), but doesn't sleep.
448 * If cpp had variadic macros, the two functions could be #defines for another.
449 * NB: should send a message to the session logger to avoid blocking.
450 */
451static void
452warning(const char *message, ...)
453{
454	va_list ap;
455	va_start(ap, message);
456
457	vsyslog(LOG_ALERT, message, ap);
458	va_end(ap);
459}
460
461/*
462 * Log an emergency message.
463 * NB: should send a message to the session logger to avoid blocking.
464 */
465static void
466emergency(const char *message, ...)
467{
468	va_list ap;
469	va_start(ap, message);
470
471	vsyslog(LOG_EMERG, message, ap);
472	va_end(ap);
473}
474
475/*
476 * Catch a SIGSYS signal.
477 *
478 * These may arise if a system does not support sysctl.
479 * We tolerate up to 25 of these, then throw in the towel.
480 */
481static void
482badsys(int sig)
483{
484	static int badcount = 0;
485
486	if (badcount++ < 25)
487		return;
488	disaster(sig);
489}
490
491/*
492 * Catch an unexpected signal.
493 */
494static void
495disaster(int sig)
496{
497
498	emergency("fatal signal: %s",
499	    (unsigned)sig < NSIG ? sys_siglist[sig] : "unknown signal");
500
501	sleep(STALL_TIMEOUT);
502	_exit(sig);		/* reboot */
503}
504
505/*
506 * Get the security level of the kernel.
507 */
508static int
509getsecuritylevel(void)
510{
511#ifdef KERN_SECURELVL
512	int name[2], curlevel;
513	size_t len;
514
515	name[0] = CTL_KERN;
516	name[1] = KERN_SECURELVL;
517	len = sizeof curlevel;
518	if (sysctl(name, 2, &curlevel, &len, NULL, 0) == -1) {
519		emergency("cannot get kernel security level: %s",
520		    strerror(errno));
521		return (-1);
522	}
523	return (curlevel);
524#else
525	return (-1);
526#endif
527}
528
529/*
530 * Set the security level of the kernel.
531 */
532static void
533setsecuritylevel(int newlevel)
534{
535#ifdef KERN_SECURELVL
536	int name[2], curlevel;
537
538	curlevel = getsecuritylevel();
539	if (newlevel == curlevel)
540		return;
541	name[0] = CTL_KERN;
542	name[1] = KERN_SECURELVL;
543	if (sysctl(name, 2, NULL, NULL, &newlevel, sizeof newlevel) == -1) {
544		emergency(
545		    "cannot change kernel security level from %d to %d: %s",
546		    curlevel, newlevel, strerror(errno));
547		return;
548	}
549#ifdef SECURE
550	warning("kernel security level changed from %d to %d",
551	    curlevel, newlevel);
552#endif
553#endif
554}
555
556/*
557 * Change states in the finite state machine.
558 * The initial state is passed as an argument.
559 */
560static void
561transition(state_t s)
562{
563
564	current_state = s;
565	for (;;)
566		current_state = (state_t) (*current_state)();
567}
568
569/*
570 * Close out the accounting files for a login session.
571 * NB: should send a message to the session logger to avoid blocking.
572 */
573static void
574clear_session_logs(session_t *sp __unused)
575{
576
577	/*
578	 * XXX: Use getutxline() and call pututxline() for each entry.
579	 * Is this safe to do this here?  Is it really required anyway?
580	 */
581}
582
583/*
584 * Start a session and allocate a controlling terminal.
585 * Only called by children of init after forking.
586 */
587static void
588setctty(const char *name)
589{
590	int fd;
591
592	revoke(name);
593	if ((fd = open(name, O_RDWR)) == -1) {
594		stall("can't open %s: %m", name);
595		_exit(1);
596	}
597	if (login_tty(fd) == -1) {
598		stall("can't get %s for controlling terminal: %m", name);
599		_exit(1);
600	}
601}
602
603static const char *
604get_shell(void)
605{
606	static char kenv_value[PATH_MAX];
607
608	if (kenv(KENV_GET, "init_shell", kenv_value, sizeof(kenv_value)) > 0)
609		return kenv_value;
610	else
611		return _PATH_BSHELL;
612}
613
614static void
615write_stderr(const char *message)
616{
617
618	write(STDERR_FILENO, message, strlen(message));
619}
620
621/*
622 * Bring the system up single user.
623 */
624static state_func_t
625single_user(void)
626{
627	pid_t pid, wpid;
628	int status;
629	sigset_t mask;
630	const char *shell;
631	char *argv[2];
632#ifdef SECURE
633	struct ttyent *typ;
634	struct passwd *pp;
635	static const char banner[] =
636		"Enter root password, or ^D to go multi-user\n";
637	char *clear, *password;
638#endif
639#ifdef DEBUGSHELL
640	char altshell[128];
641#endif
642
643	if (Reboot) {
644		/* Instead of going single user, let's reboot the machine */
645		sync();
646		alarm(2);
647		pause();
648		reboot(howto);
649		_exit(0);
650	}
651
652	shell = get_shell();
653
654	if ((pid = fork()) == 0) {
655		/*
656		 * Start the single user session.
657		 */
658		setctty(_PATH_CONSOLE);
659
660#ifdef SECURE
661		/*
662		 * Check the root password.
663		 * We don't care if the console is 'on' by default;
664		 * it's the only tty that can be 'off' and 'secure'.
665		 */
666		typ = getttynam("console");
667		pp = getpwnam("root");
668		if (typ && (typ->ty_status & TTY_SECURE) == 0 &&
669		    pp && *pp->pw_passwd) {
670			write_stderr(banner);
671			for (;;) {
672				clear = getpass("Password:");
673				if (clear == 0 || *clear == '\0')
674					_exit(0);
675				password = crypt(clear, pp->pw_passwd);
676				bzero(clear, _PASSWORD_LEN);
677				if (strcmp(password, pp->pw_passwd) == 0)
678					break;
679				warning("single-user login failed\n");
680			}
681		}
682		endttyent();
683		endpwent();
684#endif /* SECURE */
685
686#ifdef DEBUGSHELL
687		{
688			char *cp = altshell;
689			int num;
690
691#define	SHREQUEST "Enter full pathname of shell or RETURN for "
692			write_stderr(SHREQUEST);
693			write_stderr(shell);
694			write_stderr(": ");
695			while ((num = read(STDIN_FILENO, cp, 1)) != -1 &&
696			    num != 0 && *cp != '\n' && cp < &altshell[127])
697				cp++;
698			*cp = '\0';
699			if (altshell[0] != '\0')
700				shell = altshell;
701		}
702#endif /* DEBUGSHELL */
703
704		/*
705		 * Unblock signals.
706		 * We catch all the interesting ones,
707		 * and those are reset to SIG_DFL on exec.
708		 */
709		sigemptyset(&mask);
710		sigprocmask(SIG_SETMASK, &mask, (sigset_t *) 0);
711
712		/*
713		 * Fire off a shell.
714		 * If the default one doesn't work, try the Bourne shell.
715		 */
716
717		char name[] = "-sh";
718
719		argv[0] = name;
720		argv[1] = 0;
721		execv(shell, argv);
722		emergency("can't exec %s for single user: %m", shell);
723		execv(_PATH_BSHELL, argv);
724		emergency("can't exec %s for single user: %m", _PATH_BSHELL);
725		sleep(STALL_TIMEOUT);
726		_exit(1);
727	}
728
729	if (pid == -1) {
730		/*
731		 * We are seriously hosed.  Do our best.
732		 */
733		emergency("can't fork single-user shell, trying again");
734		while (waitpid(-1, (int *) 0, WNOHANG) > 0)
735			continue;
736		return (state_func_t) single_user;
737	}
738
739	requested_transition = 0;
740	do {
741		if ((wpid = waitpid(-1, &status, WUNTRACED)) != -1)
742			collect_child(wpid);
743		if (wpid == -1) {
744			if (errno == EINTR)
745				continue;
746			warning("wait for single-user shell failed: %m; restarting");
747			return (state_func_t) single_user;
748		}
749		if (wpid == pid && WIFSTOPPED(status)) {
750			warning("init: shell stopped, restarting\n");
751			kill(pid, SIGCONT);
752			wpid = -1;
753		}
754	} while (wpid != pid && !requested_transition);
755
756	if (requested_transition)
757		return (state_func_t) requested_transition;
758
759	if (!WIFEXITED(status)) {
760		if (WTERMSIG(status) == SIGKILL) {
761			/*
762			 *  reboot(8) killed shell?
763			 */
764			warning("single user shell terminated.");
765			sleep(STALL_TIMEOUT);
766			_exit(0);
767		} else {
768			warning("single user shell terminated, restarting");
769			return (state_func_t) single_user;
770		}
771	}
772
773	runcom_mode = FASTBOOT;
774	return (state_func_t) runcom;
775}
776
777/*
778 * Run the system startup script.
779 */
780static state_func_t
781runcom(void)
782{
783	struct utmpx utx;
784	state_func_t next_transition;
785
786	if ((next_transition = run_script(_PATH_RUNCOM)) != 0)
787		return next_transition;
788
789	runcom_mode = AUTOBOOT;		/* the default */
790	/* NB: should send a message to the session logger to avoid blocking. */
791	utx.ut_type = BOOT_TIME;
792	gettimeofday(&utx.ut_tv, NULL);
793	pututxline(&utx);
794	return (state_func_t) read_ttys;
795}
796
797/*
798 * Run a shell script.
799 * Returns 0 on success, otherwise the next transition to enter:
800 *  - single_user if fork/execv/waitpid failed, or if the script
801 *    terminated with a signal or exit code != 0.
802 *  - death_single if a SIGTERM was delivered to init(8).
803 */
804static state_func_t
805run_script(const char *script)
806{
807	pid_t pid, wpid;
808	int status;
809	char *argv[4];
810	const char *shell;
811	struct sigaction sa;
812
813	shell = get_shell();
814
815	if ((pid = fork()) == 0) {
816		sigemptyset(&sa.sa_mask);
817		sa.sa_flags = 0;
818		sa.sa_handler = SIG_IGN;
819		sigaction(SIGTSTP, &sa, (struct sigaction *)0);
820		sigaction(SIGHUP, &sa, (struct sigaction *)0);
821
822		setctty(_PATH_CONSOLE);
823
824		char _sh[]	 	= "sh";
825		char _autoboot[]	= "autoboot";
826
827		argv[0] = _sh;
828		argv[1] = __DECONST(char *, script);
829		argv[2] = runcom_mode == AUTOBOOT ? _autoboot : 0;
830		argv[3] = 0;
831
832		sigprocmask(SIG_SETMASK, &sa.sa_mask, (sigset_t *) 0);
833
834#ifdef LOGIN_CAP
835		setprocresources(RESOURCE_RC);
836#endif
837		execv(shell, argv);
838		stall("can't exec %s for %s: %m", shell, script);
839		_exit(1);	/* force single user mode */
840	}
841
842	if (pid == -1) {
843		emergency("can't fork for %s on %s: %m", shell, script);
844		while (waitpid(-1, (int *) 0, WNOHANG) > 0)
845			continue;
846		sleep(STALL_TIMEOUT);
847		return (state_func_t) single_user;
848	}
849
850	/*
851	 * Copied from single_user().  This is a bit paranoid.
852	 */
853	requested_transition = 0;
854	do {
855		if ((wpid = waitpid(-1, &status, WUNTRACED)) != -1)
856			collect_child(wpid);
857		if (wpid == -1) {
858			if (requested_transition == death_single)
859				return (state_func_t) death_single;
860			if (errno == EINTR)
861				continue;
862			warning("wait for %s on %s failed: %m; going to "
863			    "single user mode", shell, script);
864			return (state_func_t) single_user;
865		}
866		if (wpid == pid && WIFSTOPPED(status)) {
867			warning("init: %s on %s stopped, restarting\n",
868			    shell, script);
869			kill(pid, SIGCONT);
870			wpid = -1;
871		}
872	} while (wpid != pid);
873
874	if (WIFSIGNALED(status) && WTERMSIG(status) == SIGTERM &&
875	    requested_transition == catatonia) {
876		/* /etc/rc executed /sbin/reboot; wait for the end quietly */
877		sigset_t s;
878
879		sigfillset(&s);
880		for (;;)
881			sigsuspend(&s);
882	}
883
884	if (!WIFEXITED(status)) {
885		warning("%s on %s terminated abnormally, going to single "
886		    "user mode", shell, script);
887		return (state_func_t) single_user;
888	}
889
890	if (WEXITSTATUS(status))
891		return (state_func_t) single_user;
892
893	return (state_func_t) 0;
894}
895
896/*
897 * Open the session database.
898 *
899 * NB: We could pass in the size here; is it necessary?
900 */
901static int
902start_session_db(void)
903{
904	if (session_db && (*session_db->close)(session_db))
905		emergency("session database close: %s", strerror(errno));
906	if ((session_db = dbopen(NULL, O_RDWR, 0, DB_HASH, NULL)) == 0) {
907		emergency("session database open: %s", strerror(errno));
908		return (1);
909	}
910	return (0);
911
912}
913
914/*
915 * Add a new login session.
916 */
917static void
918add_session(session_t *sp)
919{
920	DBT key;
921	DBT data;
922
923	key.data = &sp->se_process;
924	key.size = sizeof sp->se_process;
925	data.data = &sp;
926	data.size = sizeof sp;
927
928	if ((*session_db->put)(session_db, &key, &data, 0))
929		emergency("insert %d: %s", sp->se_process, strerror(errno));
930}
931
932/*
933 * Delete an old login session.
934 */
935static void
936del_session(session_t *sp)
937{
938	DBT key;
939
940	key.data = &sp->se_process;
941	key.size = sizeof sp->se_process;
942
943	if ((*session_db->del)(session_db, &key, 0))
944		emergency("delete %d: %s", sp->se_process, strerror(errno));
945}
946
947/*
948 * Look up a login session by pid.
949 */
950static session_t *
951find_session(pid_t pid)
952{
953	DBT key;
954	DBT data;
955	session_t *ret;
956
957	key.data = &pid;
958	key.size = sizeof pid;
959	if ((*session_db->get)(session_db, &key, &data, 0) != 0)
960		return 0;
961	bcopy(data.data, (char *)&ret, sizeof(ret));
962	return ret;
963}
964
965/*
966 * Construct an argument vector from a command line.
967 */
968static char **
969construct_argv(char *command)
970{
971	int argc = 0;
972	char **argv = (char **) malloc(((strlen(command) + 1) / 2 + 1)
973						* sizeof (char *));
974
975	if ((argv[argc++] = strk(command)) == 0) {
976		free(argv);
977		return (NULL);
978	}
979	while ((argv[argc++] = strk((char *) 0)) != NULL)
980		continue;
981	return argv;
982}
983
984/*
985 * Deallocate a session descriptor.
986 */
987static void
988free_session(session_t *sp)
989{
990	free(sp->se_device);
991	if (sp->se_getty) {
992		free(sp->se_getty);
993		free(sp->se_getty_argv_space);
994		free(sp->se_getty_argv);
995	}
996	if (sp->se_window) {
997		free(sp->se_window);
998		free(sp->se_window_argv_space);
999		free(sp->se_window_argv);
1000	}
1001	if (sp->se_type)
1002		free(sp->se_type);
1003	free(sp);
1004}
1005
1006/*
1007 * Allocate a new session descriptor.
1008 * Mark it SE_PRESENT.
1009 */
1010static session_t *
1011new_session(session_t *sprev, int session_index, struct ttyent *typ)
1012{
1013	session_t *sp;
1014	int fd;
1015
1016	if ((typ->ty_status & TTY_ON) == 0 ||
1017	    typ->ty_name == 0 ||
1018	    typ->ty_getty == 0)
1019		return 0;
1020
1021	sp = (session_t *) calloc(1, sizeof (session_t));
1022
1023	sp->se_index = session_index;
1024	sp->se_flags |= SE_PRESENT;
1025
1026	sp->se_device = malloc(sizeof(_PATH_DEV) + strlen(typ->ty_name));
1027	sprintf(sp->se_device, "%s%s", _PATH_DEV, typ->ty_name);
1028
1029	/*
1030	 * Attempt to open the device, if we get "device not configured"
1031	 * then don't add the device to the session list.
1032	 */
1033	if ((fd = open(sp->se_device, O_RDONLY | O_NONBLOCK, 0)) < 0) {
1034		if (errno == ENXIO) {
1035			free_session(sp);
1036			return (0);
1037		}
1038	} else
1039		close(fd);
1040
1041	if (setupargv(sp, typ) == 0) {
1042		free_session(sp);
1043		return (0);
1044	}
1045
1046	sp->se_next = 0;
1047	if (sprev == 0) {
1048		sessions = sp;
1049		sp->se_prev = 0;
1050	} else {
1051		sprev->se_next = sp;
1052		sp->se_prev = sprev;
1053	}
1054
1055	return sp;
1056}
1057
1058/*
1059 * Calculate getty and if useful window argv vectors.
1060 */
1061static int
1062setupargv(session_t *sp, struct ttyent *typ)
1063{
1064
1065	if (sp->se_getty) {
1066		free(sp->se_getty);
1067		free(sp->se_getty_argv_space);
1068		free(sp->se_getty_argv);
1069	}
1070	sp->se_getty = malloc(strlen(typ->ty_getty) + strlen(typ->ty_name) + 2);
1071	sprintf(sp->se_getty, "%s %s", typ->ty_getty, typ->ty_name);
1072	sp->se_getty_argv_space = strdup(sp->se_getty);
1073	sp->se_getty_argv = construct_argv(sp->se_getty_argv_space);
1074	if (sp->se_getty_argv == 0) {
1075		warning("can't parse getty for port %s", sp->se_device);
1076		free(sp->se_getty);
1077		free(sp->se_getty_argv_space);
1078		sp->se_getty = sp->se_getty_argv_space = 0;
1079		return (0);
1080	}
1081	if (sp->se_window) {
1082		free(sp->se_window);
1083		free(sp->se_window_argv_space);
1084		free(sp->se_window_argv);
1085	}
1086	sp->se_window = sp->se_window_argv_space = 0;
1087	sp->se_window_argv = 0;
1088	if (typ->ty_window) {
1089		sp->se_window = strdup(typ->ty_window);
1090		sp->se_window_argv_space = strdup(sp->se_window);
1091		sp->se_window_argv = construct_argv(sp->se_window_argv_space);
1092		if (sp->se_window_argv == 0) {
1093			warning("can't parse window for port %s",
1094			    sp->se_device);
1095			free(sp->se_window_argv_space);
1096			free(sp->se_window);
1097			sp->se_window = sp->se_window_argv_space = 0;
1098			return (0);
1099		}
1100	}
1101	if (sp->se_type)
1102		free(sp->se_type);
1103	sp->se_type = typ->ty_type ? strdup(typ->ty_type) : 0;
1104	return (1);
1105}
1106
1107/*
1108 * Walk the list of ttys and create sessions for each active line.
1109 */
1110static state_func_t
1111read_ttys(void)
1112{
1113	int session_index = 0;
1114	session_t *sp, *snext;
1115	struct ttyent *typ;
1116
1117	/*
1118	 * Destroy any previous session state.
1119	 * There shouldn't be any, but just in case...
1120	 */
1121	for (sp = sessions; sp; sp = snext) {
1122		if (sp->se_process)
1123			clear_session_logs(sp);
1124		snext = sp->se_next;
1125		free_session(sp);
1126	}
1127	sessions = 0;
1128	if (start_session_db())
1129		return (state_func_t) single_user;
1130
1131	/*
1132	 * Allocate a session entry for each active port.
1133	 * Note that sp starts at 0.
1134	 */
1135	while ((typ = getttyent()) != NULL)
1136		if ((snext = new_session(sp, ++session_index, typ)) != NULL)
1137			sp = snext;
1138
1139	endttyent();
1140
1141	return (state_func_t) multi_user;
1142}
1143
1144/*
1145 * Start a window system running.
1146 */
1147static void
1148start_window_system(session_t *sp)
1149{
1150	pid_t pid;
1151	sigset_t mask;
1152	char term[64], *env[2];
1153	int status;
1154
1155	if ((pid = fork()) == -1) {
1156		emergency("can't fork for window system on port %s: %m",
1157		    sp->se_device);
1158		/* hope that getty fails and we can try again */
1159		return;
1160	}
1161	if (pid) {
1162		waitpid(-1, &status, 0);
1163		return;
1164	}
1165
1166	/* reparent window process to the init to not make a zombie on exit */
1167	if ((pid = fork()) == -1) {
1168		emergency("can't fork for window system on port %s: %m",
1169		    sp->se_device);
1170		_exit(1);
1171	}
1172	if (pid)
1173		_exit(0);
1174
1175	sigemptyset(&mask);
1176	sigprocmask(SIG_SETMASK, &mask, (sigset_t *) 0);
1177
1178	if (setsid() < 0)
1179		emergency("setsid failed (window) %m");
1180
1181#ifdef LOGIN_CAP
1182	setprocresources(RESOURCE_WINDOW);
1183#endif
1184	if (sp->se_type) {
1185		/* Don't use malloc after fork */
1186		strcpy(term, "TERM=");
1187		strncat(term, sp->se_type, sizeof(term) - 6);
1188		env[0] = term;
1189		env[1] = 0;
1190	}
1191	else
1192		env[0] = 0;
1193	execve(sp->se_window_argv[0], sp->se_window_argv, env);
1194	stall("can't exec window system '%s' for port %s: %m",
1195		sp->se_window_argv[0], sp->se_device);
1196	_exit(1);
1197}
1198
1199/*
1200 * Start a login session running.
1201 */
1202static pid_t
1203start_getty(session_t *sp)
1204{
1205	pid_t pid;
1206	sigset_t mask;
1207	time_t current_time = time((time_t *) 0);
1208	int too_quick = 0;
1209	char term[64], *env[2];
1210
1211	if (current_time >= sp->se_started &&
1212	    current_time - sp->se_started < GETTY_SPACING) {
1213		if (++sp->se_nspace > GETTY_NSPACE) {
1214			sp->se_nspace = 0;
1215			too_quick = 1;
1216		}
1217	} else
1218		sp->se_nspace = 0;
1219
1220	/*
1221	 * fork(), not vfork() -- we can't afford to block.
1222	 */
1223	if ((pid = fork()) == -1) {
1224		emergency("can't fork for getty on port %s: %m", sp->se_device);
1225		return -1;
1226	}
1227
1228	if (pid)
1229		return pid;
1230
1231	if (too_quick) {
1232		warning("getty repeating too quickly on port %s, sleeping %d secs",
1233		    sp->se_device, GETTY_SLEEP);
1234		sleep((unsigned) GETTY_SLEEP);
1235	}
1236
1237	if (sp->se_window) {
1238		start_window_system(sp);
1239		sleep(WINDOW_WAIT);
1240	}
1241
1242	sigemptyset(&mask);
1243	sigprocmask(SIG_SETMASK, &mask, (sigset_t *) 0);
1244
1245#ifdef LOGIN_CAP
1246	setprocresources(RESOURCE_GETTY);
1247#endif
1248	if (sp->se_type) {
1249		/* Don't use malloc after fork */
1250		strcpy(term, "TERM=");
1251		strncat(term, sp->se_type, sizeof(term) - 6);
1252		env[0] = term;
1253		env[1] = 0;
1254	} else
1255		env[0] = 0;
1256	execve(sp->se_getty_argv[0], sp->se_getty_argv, env);
1257	stall("can't exec getty '%s' for port %s: %m",
1258		sp->se_getty_argv[0], sp->se_device);
1259	_exit(1);
1260}
1261
1262/*
1263 * Collect exit status for a child.
1264 * If an exiting login, start a new login running.
1265 */
1266static void
1267collect_child(pid_t pid)
1268{
1269	session_t *sp, *sprev, *snext;
1270
1271	if (! sessions)
1272		return;
1273
1274	if (! (sp = find_session(pid)))
1275		return;
1276
1277	clear_session_logs(sp);
1278	del_session(sp);
1279	sp->se_process = 0;
1280
1281	if (sp->se_flags & SE_SHUTDOWN) {
1282		if ((sprev = sp->se_prev) != NULL)
1283			sprev->se_next = sp->se_next;
1284		else
1285			sessions = sp->se_next;
1286		if ((snext = sp->se_next) != NULL)
1287			snext->se_prev = sp->se_prev;
1288		free_session(sp);
1289		return;
1290	}
1291
1292	if ((pid = start_getty(sp)) == -1) {
1293		/* serious trouble */
1294		requested_transition = clean_ttys;
1295		return;
1296	}
1297
1298	sp->se_process = pid;
1299	sp->se_started = time((time_t *) 0);
1300	add_session(sp);
1301}
1302
1303/*
1304 * Catch a signal and request a state transition.
1305 */
1306static void
1307transition_handler(int sig)
1308{
1309
1310	switch (sig) {
1311	case SIGHUP:
1312		if (current_state == read_ttys || current_state == multi_user ||
1313		    current_state == clean_ttys || current_state == catatonia)
1314			requested_transition = clean_ttys;
1315		break;
1316	case SIGUSR2:
1317		howto = RB_POWEROFF;
1318	case SIGUSR1:
1319		howto |= RB_HALT;
1320	case SIGINT:
1321		Reboot = TRUE;
1322	case SIGTERM:
1323		if (current_state == read_ttys || current_state == multi_user ||
1324		    current_state == clean_ttys || current_state == catatonia)
1325			requested_transition = death;
1326		else
1327			requested_transition = death_single;
1328		break;
1329	case SIGTSTP:
1330		if (current_state == runcom || current_state == read_ttys ||
1331		    current_state == clean_ttys ||
1332		    current_state == multi_user || current_state == catatonia)
1333			requested_transition = catatonia;
1334		break;
1335	default:
1336		requested_transition = 0;
1337		break;
1338	}
1339}
1340
1341/*
1342 * Take the system multiuser.
1343 */
1344static state_func_t
1345multi_user(void)
1346{
1347	pid_t pid;
1348	session_t *sp;
1349
1350	requested_transition = 0;
1351
1352	/*
1353	 * If the administrator has not set the security level to -1
1354	 * to indicate that the kernel should not run multiuser in secure
1355	 * mode, and the run script has not set a higher level of security
1356	 * than level 1, then put the kernel into secure mode.
1357	 */
1358	if (getsecuritylevel() == 0)
1359		setsecuritylevel(1);
1360
1361	for (sp = sessions; sp; sp = sp->se_next) {
1362		if (sp->se_process)
1363			continue;
1364		if ((pid = start_getty(sp)) == -1) {
1365			/* serious trouble */
1366			requested_transition = clean_ttys;
1367			break;
1368		}
1369		sp->se_process = pid;
1370		sp->se_started = time((time_t *) 0);
1371		add_session(sp);
1372	}
1373
1374	while (!requested_transition)
1375		if ((pid = waitpid(-1, (int *) 0, 0)) != -1)
1376			collect_child(pid);
1377
1378	return (state_func_t) requested_transition;
1379}
1380
1381/*
1382 * This is an (n*2)+(n^2) algorithm.  We hope it isn't run often...
1383 */
1384static state_func_t
1385clean_ttys(void)
1386{
1387	session_t *sp, *sprev;
1388	struct ttyent *typ;
1389	int session_index = 0;
1390	int devlen;
1391	char *old_getty, *old_window, *old_type;
1392
1393	/*
1394	 * mark all sessions for death, (!SE_PRESENT)
1395	 * as we find or create new ones they'll be marked as keepers,
1396	 * we'll later nuke all the ones not found in /etc/ttys
1397	 */
1398	for (sp = sessions; sp != NULL; sp = sp->se_next)
1399		sp->se_flags &= ~SE_PRESENT;
1400
1401	devlen = sizeof(_PATH_DEV) - 1;
1402	while ((typ = getttyent()) != NULL) {
1403		++session_index;
1404
1405		for (sprev = 0, sp = sessions; sp; sprev = sp, sp = sp->se_next)
1406			if (strcmp(typ->ty_name, sp->se_device + devlen) == 0)
1407				break;
1408
1409		if (sp) {
1410			/* we want this one to live */
1411			sp->se_flags |= SE_PRESENT;
1412			if (sp->se_index != session_index) {
1413				warning("port %s changed utmp index from %d to %d",
1414				       sp->se_device, sp->se_index,
1415				       session_index);
1416				sp->se_index = session_index;
1417			}
1418			if ((typ->ty_status & TTY_ON) == 0 ||
1419			    typ->ty_getty == 0) {
1420				sp->se_flags |= SE_SHUTDOWN;
1421				kill(sp->se_process, SIGHUP);
1422				continue;
1423			}
1424			sp->se_flags &= ~SE_SHUTDOWN;
1425			old_getty = sp->se_getty ? strdup(sp->se_getty) : 0;
1426			old_window = sp->se_window ? strdup(sp->se_window) : 0;
1427			old_type = sp->se_type ? strdup(sp->se_type) : 0;
1428			if (setupargv(sp, typ) == 0) {
1429				warning("can't parse getty for port %s",
1430					sp->se_device);
1431				sp->se_flags |= SE_SHUTDOWN;
1432				kill(sp->se_process, SIGHUP);
1433			}
1434			else if (   !old_getty
1435				 || (!old_type && sp->se_type)
1436				 || (old_type && !sp->se_type)
1437				 || (!old_window && sp->se_window)
1438				 || (old_window && !sp->se_window)
1439				 || (strcmp(old_getty, sp->se_getty) != 0)
1440				 || (old_window && strcmp(old_window, sp->se_window) != 0)
1441				 || (old_type && strcmp(old_type, sp->se_type) != 0)
1442				) {
1443				/* Don't set SE_SHUTDOWN here */
1444				sp->se_nspace = 0;
1445				sp->se_started = 0;
1446				kill(sp->se_process, SIGHUP);
1447			}
1448			if (old_getty)
1449				free(old_getty);
1450			if (old_window)
1451				free(old_window);
1452			if (old_type)
1453				free(old_type);
1454			continue;
1455		}
1456
1457		new_session(sprev, session_index, typ);
1458	}
1459
1460	endttyent();
1461
1462	/*
1463	 * sweep through and kill all deleted sessions
1464	 * ones who's /etc/ttys line was deleted (SE_PRESENT unset)
1465	 */
1466	for (sp = sessions; sp != NULL; sp = sp->se_next) {
1467		if ((sp->se_flags & SE_PRESENT) == 0) {
1468			sp->se_flags |= SE_SHUTDOWN;
1469			kill(sp->se_process, SIGHUP);
1470		}
1471	}
1472
1473	return (state_func_t) multi_user;
1474}
1475
1476/*
1477 * Block further logins.
1478 */
1479static state_func_t
1480catatonia(void)
1481{
1482	session_t *sp;
1483
1484	for (sp = sessions; sp; sp = sp->se_next)
1485		sp->se_flags |= SE_SHUTDOWN;
1486
1487	return (state_func_t) multi_user;
1488}
1489
1490/*
1491 * Note SIGALRM.
1492 */
1493static void
1494alrm_handler(int sig)
1495{
1496
1497	(void)sig;
1498	clang = 1;
1499}
1500
1501/*
1502 * Bring the system down to single user.
1503 */
1504static state_func_t
1505death(void)
1506{
1507	struct utmpx utx;
1508	session_t *sp;
1509
1510	/* NB: should send a message to the session logger to avoid blocking. */
1511	utx.ut_type = SHUTDOWN_TIME;
1512	gettimeofday(&utx.ut_tv, NULL);
1513	pututxline(&utx);
1514
1515	/*
1516	 * Also revoke the TTY here.  Because runshutdown() may reopen
1517	 * the TTY whose getty we're killing here, there is no guarantee
1518	 * runshutdown() will perform the initial open() call, causing
1519	 * the terminal attributes to be misconfigured.
1520	 */
1521	for (sp = sessions; sp; sp = sp->se_next) {
1522		sp->se_flags |= SE_SHUTDOWN;
1523		kill(sp->se_process, SIGHUP);
1524		revoke(sp->se_device);
1525	}
1526
1527	/* Try to run the rc.shutdown script within a period of time */
1528	runshutdown();
1529
1530	return (state_func_t) death_single;
1531}
1532
1533/*
1534 * Do what is necessary to reinitialize single user mode or reboot
1535 * from an incomplete state.
1536 */
1537static state_func_t
1538death_single(void)
1539{
1540	int i;
1541	pid_t pid;
1542	static const int death_sigs[2] = { SIGTERM, SIGKILL };
1543
1544	revoke(_PATH_CONSOLE);
1545
1546	for (i = 0; i < 2; ++i) {
1547		if (kill(-1, death_sigs[i]) == -1 && errno == ESRCH)
1548			return (state_func_t) single_user;
1549
1550		clang = 0;
1551		alarm(DEATH_WATCH);
1552		do
1553			if ((pid = waitpid(-1, (int *)0, 0)) != -1)
1554				collect_child(pid);
1555		while (clang == 0 && errno != ECHILD);
1556
1557		if (errno == ECHILD)
1558			return (state_func_t) single_user;
1559	}
1560
1561	warning("some processes would not die; ps axl advised");
1562
1563	return (state_func_t) single_user;
1564}
1565
1566/*
1567 * Run the system shutdown script.
1568 *
1569 * Exit codes:      XXX I should document more
1570 * -2       shutdown script terminated abnormally
1571 * -1       fatal error - can't run script
1572 * 0        good.
1573 * >0       some error (exit code)
1574 */
1575static int
1576runshutdown(void)
1577{
1578	pid_t pid, wpid;
1579	int status;
1580	int shutdowntimeout;
1581	size_t len;
1582	char *argv[4];
1583	const char *shell;
1584	struct sigaction sa;
1585	struct stat sb;
1586
1587	/*
1588	 * rc.shutdown is optional, so to prevent any unnecessary
1589	 * complaints from the shell we simply don't run it if the
1590	 * file does not exist. If the stat() here fails for other
1591	 * reasons, we'll let the shell complain.
1592	 */
1593	if (stat(_PATH_RUNDOWN, &sb) == -1 && errno == ENOENT)
1594		return 0;
1595
1596	shell = get_shell();
1597
1598	if ((pid = fork()) == 0) {
1599		sigemptyset(&sa.sa_mask);
1600		sa.sa_flags = 0;
1601		sa.sa_handler = SIG_IGN;
1602		sigaction(SIGTSTP, &sa, (struct sigaction *)0);
1603		sigaction(SIGHUP, &sa, (struct sigaction *)0);
1604
1605		setctty(_PATH_CONSOLE);
1606
1607		char _sh[]	= "sh";
1608		char _reboot[]	= "reboot";
1609		char _single[]	= "single";
1610		char _path_rundown[] = _PATH_RUNDOWN;
1611
1612		argv[0] = _sh;
1613		argv[1] = _path_rundown;
1614		argv[2] = Reboot ? _reboot : _single;
1615		argv[3] = 0;
1616
1617		sigprocmask(SIG_SETMASK, &sa.sa_mask, (sigset_t *) 0);
1618
1619#ifdef LOGIN_CAP
1620		setprocresources(RESOURCE_RC);
1621#endif
1622		execv(shell, argv);
1623		warning("can't exec %s for %s: %m", shell, _PATH_RUNDOWN);
1624		_exit(1);	/* force single user mode */
1625	}
1626
1627	if (pid == -1) {
1628		emergency("can't fork for %s on %s: %m", shell, _PATH_RUNDOWN);
1629		while (waitpid(-1, (int *) 0, WNOHANG) > 0)
1630			continue;
1631		sleep(STALL_TIMEOUT);
1632		return -1;
1633	}
1634
1635	len = sizeof(shutdowntimeout);
1636	if (sysctlbyname("kern.init_shutdown_timeout", &shutdowntimeout, &len,
1637	    NULL, 0) == -1 || shutdowntimeout < 2)
1638		shutdowntimeout = DEATH_SCRIPT;
1639	alarm(shutdowntimeout);
1640	clang = 0;
1641	/*
1642	 * Copied from single_user().  This is a bit paranoid.
1643	 * Use the same ALRM handler.
1644	 */
1645	do {
1646		if ((wpid = waitpid(-1, &status, WUNTRACED)) != -1)
1647			collect_child(wpid);
1648		if (clang == 1) {
1649			/* we were waiting for the sub-shell */
1650			kill(wpid, SIGTERM);
1651			warning("timeout expired for %s on %s: %m; going to "
1652			    "single user mode", shell, _PATH_RUNDOWN);
1653			return -1;
1654		}
1655		if (wpid == -1) {
1656			if (errno == EINTR)
1657				continue;
1658			warning("wait for %s on %s failed: %m; going to "
1659			    "single user mode", shell, _PATH_RUNDOWN);
1660			return -1;
1661		}
1662		if (wpid == pid && WIFSTOPPED(status)) {
1663			warning("init: %s on %s stopped, restarting\n",
1664				shell, _PATH_RUNDOWN);
1665			kill(pid, SIGCONT);
1666			wpid = -1;
1667		}
1668	} while (wpid != pid && !clang);
1669
1670	/* Turn off the alarm */
1671	alarm(0);
1672
1673	if (WIFSIGNALED(status) && WTERMSIG(status) == SIGTERM &&
1674	    requested_transition == catatonia) {
1675		/*
1676		 * /etc/rc.shutdown executed /sbin/reboot;
1677		 * wait for the end quietly
1678		 */
1679		sigset_t s;
1680
1681		sigfillset(&s);
1682		for (;;)
1683			sigsuspend(&s);
1684	}
1685
1686	if (!WIFEXITED(status)) {
1687		warning("%s on %s terminated abnormally, going to "
1688		    "single user mode", shell, _PATH_RUNDOWN);
1689		return -2;
1690	}
1691
1692	if ((status = WEXITSTATUS(status)) != 0)
1693		warning("%s returned status %d", _PATH_RUNDOWN, status);
1694
1695	return status;
1696}
1697
1698static char *
1699strk(char *p)
1700{
1701	static char *t;
1702	char *q;
1703	int c;
1704
1705	if (p)
1706		t = p;
1707	if (!t)
1708		return 0;
1709
1710	c = *t;
1711	while (c == ' ' || c == '\t' )
1712		c = *++t;
1713	if (!c) {
1714		t = 0;
1715		return 0;
1716	}
1717	q = t;
1718	if (c == '\'') {
1719		c = *++t;
1720		q = t;
1721		while (c && c != '\'')
1722			c = *++t;
1723		if (!c)  /* unterminated string */
1724			q = t = 0;
1725		else
1726			*t++ = 0;
1727	} else {
1728		while (c && c != ' ' && c != '\t' )
1729			c = *++t;
1730		*t++ = 0;
1731		if (!c)
1732			t = 0;
1733	}
1734	return q;
1735}
1736
1737#ifdef LOGIN_CAP
1738static void
1739setprocresources(const char *cname)
1740{
1741	login_cap_t *lc;
1742	if ((lc = login_getclassbyname(cname, NULL)) != NULL) {
1743		setusercontext(lc, (struct passwd*)NULL, 0,
1744		    LOGIN_SETPRIORITY | LOGIN_SETRESOURCES);
1745		login_close(lc);
1746	}
1747}
1748#endif
1749