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