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