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