init.c revision 1.66 1 /* $NetBSD: init.c,v 1.66 2004/08/13 17:19:15 mycroft 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.66 2004/08/13 17:19:15 mycroft 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 const struct timespec dtrtime = {.tv_sec = 0, .tv_nsec = 250000};
94
95 #if defined(RESCUEDIR)
96 #define INIT_BSHELL RESCUEDIR "/sh"
97 #define INIT_MOUNT_MFS RESCUEDIR "/mount_mfs"
98 #define INIT_PATH RESCUEDIR ":" _PATH_STDPATH
99 #else
100 #define INIT_BSHELL _PATH_BSHELL
101 #define INIT_MOUNT_MFS "/sbin/mount_mfs"
102 #define INIT_PATH _PATH_STDPATH
103 #endif
104
105 int main(int, char *[]);
106
107 void handle(sig_t, ...);
108 void delset(sigset_t *, ...);
109
110 void stall(const char *, ...)
111 __attribute__((__format__(__printf__,1,2)));
112 void warning(const char *, ...)
113 __attribute__((__format__(__printf__,1,2)));
114 void emergency(const char *, ...)
115 __attribute__((__format__(__printf__,1,2)));
116 void disaster(int);
117 void badsys(int);
118
119 /*
120 * We really need a recursive typedef...
121 * The following at least guarantees that the return type of (*state_t)()
122 * is sufficiently wide to hold a function pointer.
123 */
124 typedef long (*state_func_t)(void);
125 typedef state_func_t (*state_t)(void);
126
127 state_func_t single_user(void);
128 state_func_t runcom(void);
129 state_func_t read_ttys(void);
130 state_func_t multi_user(void);
131 state_func_t clean_ttys(void);
132 state_func_t catatonia(void);
133 state_func_t death(void);
134
135 enum { AUTOBOOT, FASTBOOT } runcom_mode = AUTOBOOT;
136
137 void transition(state_t);
138 #ifndef LETS_GET_SMALL
139 state_t requested_transition = runcom;
140 #else /* LETS_GET_SMALL */
141 state_t requested_transition = single_user;
142 #endif /* LETS_GET_SMALL */
143
144 void setctty(const char *);
145
146 typedef struct init_session {
147 int se_index; /* index of entry in ttys file */
148 pid_t se_process; /* controlling process */
149 time_t se_started; /* used to avoid thrashing */
150 int se_flags; /* status of session */
151 #define SE_SHUTDOWN 0x1 /* session won't be restarted */
152 #define SE_PRESENT 0x2 /* session is in /etc/ttys */
153 char *se_device; /* filename of port */
154 char *se_getty; /* what to run on that port */
155 char **se_getty_argv; /* pre-parsed argument array */
156 char *se_window; /* window system (started only once) */
157 char **se_window_argv; /* pre-parsed argument array */
158 struct init_session *se_prev;
159 struct init_session *se_next;
160 } session_t;
161
162 void free_session(session_t *);
163 session_t *new_session(session_t *, int, struct ttyent *);
164 session_t *sessions;
165
166 char **construct_argv(char *);
167 void start_window_system(session_t *);
168 void collect_child(pid_t, int);
169 pid_t start_getty(session_t *);
170 void transition_handler(int);
171 void alrm_handler(int);
172 void setsecuritylevel(int);
173 int getsecuritylevel(void);
174 int setupargv(session_t *, struct ttyent *);
175 int clang;
176
177 #ifndef LETS_GET_SMALL
178 void clear_session_logs(session_t *, int);
179 #endif
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
189 #define NINODE 896
190 #define FSSIZE ((8192 /* boot area */ \
191 + 2 * 8192 /* two copies of superblock */ \
192 + 4096 /* cylinder group info */ \
193 + NINODE * (128 + 18) /* inode and directory entry */ \
194 + mfile[0].len /* size of MAKEDEV file */ \
195 + 2 * 4096) / 512) /* some slack */
196
197 struct mappedfile {
198 const char *path;
199 char *buf;
200 int len;
201 } mfile[] = {
202 { "/dev/MAKEDEV", NULL, 0 },
203 { "/dev/MAKEDEV.local", NULL, 0 }
204 };
205
206 static int mfs_dev(void);
207 static void mapfile(struct mappedfile *);
208 static void writefile(struct mappedfile *);
209
210 #endif
211
212 /*
213 * The mother of all processes.
214 */
215 int
216 main(int argc, char **argv)
217 {
218 struct sigaction sa;
219 sigset_t mask;
220 #ifndef LETS_GET_SMALL
221 int c;
222
223 /* Dispose of random users. */
224 if (getuid() != 0) {
225 errno = EPERM;
226 err(1, NULL);
227 }
228
229 /* System V users like to reexec init. */
230 if (getpid() != 1)
231 errx(1, "already running");
232 #endif
233
234 /*
235 * Create an initial session.
236 */
237 if (setsid() < 0)
238 warn("initial setsid() failed");
239
240 /*
241 * Establish an initial user so that programs running
242 * single user do not freak out and die (like passwd).
243 */
244 if (setlogin("root") < 0)
245 warn("setlogin() failed");
246
247
248 #ifdef MFS_DEV_IF_NO_CONSOLE
249 if (mfs_dev() == -1)
250 requested_transition = single_user;
251 #endif
252
253 #ifndef LETS_GET_SMALL
254 /*
255 * Note that this does NOT open a file...
256 * Does 'init' deserve its own facility number?
257 */
258 openlog("init", LOG_CONS, LOG_AUTH);
259 #endif /* LETS_GET_SMALL */
260
261
262 #ifndef LETS_GET_SMALL
263 /*
264 * This code assumes that we always get arguments through flags,
265 * never through bits set in some random machine register.
266 */
267 while ((c = getopt(argc, argv, "sf")) != -1)
268 switch (c) {
269 case 's':
270 requested_transition = single_user;
271 break;
272 case 'f':
273 runcom_mode = FASTBOOT;
274 break;
275 default:
276 warning("unrecognized flag '-%c'", c);
277 break;
278 }
279
280 if (optind != argc)
281 warning("ignoring excess arguments");
282 #else /* LETS_GET_SMALL */
283 requested_transition = single_user;
284 #endif /* LETS_GET_SMALL */
285
286 /*
287 * We catch or block signals rather than ignore them,
288 * so that they get reset on exec.
289 */
290 handle(badsys, SIGSYS, 0);
291 handle(disaster, SIGABRT, SIGFPE, SIGILL, SIGSEGV,
292 SIGBUS, SIGXCPU, SIGXFSZ, 0);
293 handle(transition_handler, SIGHUP, SIGTERM, SIGTSTP, 0);
294 handle(alrm_handler, SIGALRM, 0);
295 (void)sigfillset(&mask);
296 delset(&mask, SIGABRT, SIGFPE, SIGILL, SIGSEGV, SIGBUS, SIGSYS,
297 SIGXCPU, SIGXFSZ, SIGHUP, SIGTERM, SIGTSTP, SIGALRM, 0);
298 (void)sigprocmask(SIG_SETMASK, &mask, NULL);
299 (void)sigemptyset(&sa.sa_mask);
300 sa.sa_flags = 0;
301 sa.sa_handler = SIG_IGN;
302 (void)sigaction(SIGTTIN, &sa, NULL);
303 (void)sigaction(SIGTTOU, &sa, NULL);
304
305 /*
306 * Paranoia.
307 */
308 (void)close(0);
309 (void)close(1);
310 (void)close(2);
311
312 /*
313 * Start the state machine.
314 */
315 transition(requested_transition);
316
317 /*
318 * Should never reach here.
319 */
320 return 1;
321 }
322
323 /*
324 * Associate a function with a signal handler.
325 */
326 void
327 handle(sig_t handler, ...)
328 {
329 int sig;
330 struct sigaction sa;
331 sigset_t mask_everything;
332 va_list ap;
333
334 va_start(ap, handler);
335
336 sa.sa_handler = handler;
337 (void)sigfillset(&mask_everything);
338
339 while ((sig = va_arg(ap, int)) != 0) {
340 sa.sa_mask = mask_everything;
341 /* XXX SA_RESTART? */
342 sa.sa_flags = sig == SIGCHLD ? SA_NOCLDSTOP : 0;
343 (void)sigaction(sig, &sa, NULL);
344 }
345 va_end(ap);
346 }
347
348 /*
349 * Delete a set of signals from a mask.
350 */
351 void
352 delset(sigset_t *maskp, ...)
353 {
354 int sig;
355 va_list ap;
356
357 va_start(ap, maskp);
358
359 while ((sig = va_arg(ap, int)) != 0)
360 (void)sigdelset(maskp, sig);
361 va_end(ap);
362 }
363
364 /*
365 * Log a message and sleep for a while (to give someone an opportunity
366 * to read it and to save log or hardcopy output if the problem is chronic).
367 * NB: should send a message to the session logger to avoid blocking.
368 */
369 void
370 stall(const char *message, ...)
371 {
372 va_list ap;
373
374 va_start(ap, message);
375 vsyslog(LOG_ALERT, message, ap);
376 va_end(ap);
377 closelog();
378 (void)sleep(STALL_TIMEOUT);
379 }
380
381 /*
382 * Like stall(), but doesn't sleep.
383 * If cpp had variadic macros, the two functions could be #defines for another.
384 * NB: should send a message to the session logger to avoid blocking.
385 */
386 void
387 warning(const char *message, ...)
388 {
389 va_list ap;
390
391 va_start(ap, message);
392 vsyslog(LOG_ALERT, message, ap);
393 va_end(ap);
394 closelog();
395 }
396
397 /*
398 * Log an emergency message.
399 * NB: should send a message to the session logger to avoid blocking.
400 */
401 void
402 emergency(const char *message, ...)
403 {
404 va_list ap;
405
406 va_start(ap, message);
407 vsyslog(LOG_EMERG, message, ap);
408 va_end(ap);
409 closelog();
410 }
411
412 /*
413 * Catch a SIGSYS signal.
414 *
415 * These may arise if a system does not support sysctl.
416 * We tolerate up to 25 of these, then throw in the towel.
417 */
418 void
419 badsys(int sig)
420 {
421 static int badcount = 0;
422
423 if (badcount++ < 25)
424 return;
425 disaster(sig);
426 }
427
428 /*
429 * Catch an unexpected signal.
430 */
431 void
432 disaster(int sig)
433 {
434
435 emergency("fatal signal: %s", strsignal(sig));
436 (void)sleep(STALL_TIMEOUT);
437 _exit(sig); /* reboot */
438 }
439
440 /*
441 * Get the security level of the kernel.
442 */
443 int
444 getsecuritylevel(void)
445 {
446 #ifdef KERN_SECURELVL
447 int name[2], curlevel;
448 size_t len;
449
450 name[0] = CTL_KERN;
451 name[1] = KERN_SECURELVL;
452 len = sizeof curlevel;
453 if (sysctl(name, 2, &curlevel, &len, NULL, 0) == -1) {
454 emergency("cannot get kernel security level: %m");
455 return (-1);
456 }
457 return (curlevel);
458 #else
459 return (-1);
460 #endif
461 }
462
463 /*
464 * Set the security level of the kernel.
465 */
466 void
467 setsecuritylevel(int newlevel)
468 {
469 #ifdef KERN_SECURELVL
470 int name[2], curlevel;
471
472 curlevel = getsecuritylevel();
473 if (newlevel == curlevel)
474 return;
475 name[0] = CTL_KERN;
476 name[1] = KERN_SECURELVL;
477 if (sysctl(name, 2, NULL, NULL, &newlevel, sizeof newlevel) == -1) {
478 emergency( "cannot change kernel security level from"
479 " %d to %d: %m", curlevel, newlevel);
480 return;
481 }
482 #ifdef SECURE
483 warning("kernel security level changed from %d to %d",
484 curlevel, newlevel);
485 #endif
486 #endif
487 }
488
489 /*
490 * Change states in the finite state machine.
491 * The initial state is passed as an argument.
492 */
493 void
494 transition(state_t s)
495 {
496
497 if (s == NULL)
498 return;
499 for (;;)
500 s = (state_t)(*s)();
501 }
502
503 #ifndef LETS_GET_SMALL
504 /*
505 * Close out the accounting files for a login session.
506 * NB: should send a message to the session logger to avoid blocking.
507 */
508 void
509 clear_session_logs(session_t *sp, int status)
510 {
511 char *line = sp->se_device + sizeof(_PATH_DEV) - 1;
512
513 #ifdef SUPPORT_UTMPX
514 if (logoutx(line, status, DEAD_PROCESS))
515 logwtmpx(line, "", "", status, DEAD_PROCESS);
516 #endif
517 #ifdef SUPPORT_UTMP
518 if (logout(line))
519 logwtmp(line, "", "");
520 #endif
521 }
522 #endif
523
524 /*
525 * Start a session and allocate a controlling terminal.
526 * Only called by children of init after forking.
527 */
528 void
529 setctty(const char *name)
530 {
531 int fd;
532
533 (void) revoke(name);
534 nanosleep(&dtrtime, NULL); /* leave DTR low for a bit */
535 if ((fd = open(name, O_RDWR)) == -1) {
536 stall("can't open %s: %m", name);
537 _exit(1);
538 }
539 if (login_tty(fd) == -1) {
540 stall("can't get %s for controlling terminal: %m", name);
541 _exit(1);
542 }
543 }
544
545 /*
546 * Bring the system up single user.
547 */
548 state_func_t
549 single_user(void)
550 {
551 pid_t pid, wpid;
552 int status;
553 int from_securitylevel;
554 sigset_t mask;
555 struct sigaction sa, satstp, sahup;
556 #ifdef ALTSHELL
557 const char *shell = INIT_BSHELL;
558 #endif
559 char *argv[2];
560 #ifdef SECURE
561 struct ttyent *typ;
562 struct passwd *pp;
563 char *clear, *password;
564 #endif
565 #ifdef ALTSHELL
566 char altshell[128];
567 #endif /* ALTSHELL */
568
569 /*
570 * If the kernel is in secure mode, downgrade it to insecure mode.
571 */
572 from_securitylevel = getsecuritylevel();
573 if (from_securitylevel > 0)
574 setsecuritylevel(0);
575
576 (void)sigemptyset(&sa.sa_mask);
577 sa.sa_flags = 0;
578 sa.sa_handler = SIG_IGN;
579 (void)sigaction(SIGTSTP, &sa, &satstp);
580 (void)sigaction(SIGHUP, &sa, &sahup);
581 if ((pid = fork()) == 0) {
582 /*
583 * Start the single user session.
584 */
585 if (access(_PATH_CONSTTY, F_OK) == 0)
586 setctty(_PATH_CONSTTY);
587 else
588 setctty(_PATH_CONSOLE);
589
590 #ifdef SECURE
591 /*
592 * Check the root password.
593 * We don't care if the console is 'on' by default;
594 * it's the only tty that can be 'off' and 'secure'.
595 */
596 typ = getttynam("console");
597 pp = getpwnam("root");
598 if (typ && (from_securitylevel >=2 || (typ->ty_status
599 & TTY_SECURE) == 0) && pp && *pp->pw_passwd != '\0') {
600 (void)fprintf(stderr,
601 "Enter root password, or ^D to go multi-user\n");
602 for (;;) {
603 clear = getpass("Password:");
604 if (clear == 0 || *clear == '\0')
605 _exit(0);
606 password = crypt(clear, pp->pw_passwd);
607 (void)memset(clear, 0, _PASSWORD_LEN);
608 if (strcmp(password, pp->pw_passwd) == 0)
609 break;
610 warning("single-user login failed\n");
611 }
612 }
613 endttyent();
614 endpwent();
615 #endif /* SECURE */
616
617 #ifdef ALTSHELL
618 (void)fprintf(stderr,
619 "Enter pathname of shell or RETURN for %s: ", shell);
620 if (fgets(altshell, sizeof(altshell), stdin) == NULL) {
621 altshell[0] = '\0';
622 } else {
623 /* nuke \n */
624 char *p;
625
626 if ((p = strchr(altshell, '\n')) != NULL)
627 *p = '\0';
628 }
629
630 if (altshell[0])
631 shell = altshell;
632 #endif /* ALTSHELL */
633
634 /*
635 * Unblock signals.
636 * We catch all the interesting ones,
637 * and those are reset to SIG_DFL on exec.
638 */
639 (void)sigemptyset(&mask);
640 (void)sigprocmask(SIG_SETMASK, &mask, NULL);
641
642 /*
643 * Fire off a shell.
644 * If the default one doesn't work, try the Bourne shell.
645 */
646 argv[0] = "-sh";
647 argv[1] = 0;
648 setenv("PATH", INIT_PATH, 1);
649 #ifdef ALTSHELL
650 if (altshell[0])
651 argv[0] = altshell;
652 (void)execv(shell, argv);
653 emergency("can't exec %s for single user: %m", shell);
654 argv[0] = "-sh";
655 #endif /* ALTSHELL */
656 (void)execv(INIT_BSHELL, argv);
657 emergency("can't exec %s for single user: %m", INIT_BSHELL);
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