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