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