init.c revision 1.68 1 /* $NetBSD: init.c,v 1.68 2004/10/12 10:08:09 dan 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.68 2004/10/12 10:08:09 dan 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 (void)sleep(STALL_TIMEOUT);
659 _exit(1);
660 }
661
662 if (pid == -1) {
663 /*
664 * We are seriously hosed. Do our best.
665 */
666 emergency("can't fork single-user shell, trying again");
667 while (waitpid(-1, NULL, WNOHANG) > 0)
668 continue;
669 (void)sigaction(SIGTSTP, &satstp, NULL);
670 (void)sigaction(SIGHUP, &sahup, NULL);
671 return (state_func_t) single_user;
672 }
673
674 requested_transition = 0;
675 do {
676 if ((wpid = waitpid(-1, &status, WUNTRACED)) != -1)
677 collect_child(wpid, status);
678 if (wpid == -1) {
679 if (errno == EINTR)
680 continue;
681 warning("wait for single-user shell failed: %m; "
682 "restarting");
683 return (state_func_t)single_user;
684 }
685 if (wpid == pid && WIFSTOPPED(status)) {
686 warning("init: shell stopped, restarting\n");
687 kill(pid, SIGCONT);
688 wpid = -1;
689 }
690 } while (wpid != pid && !requested_transition);
691
692 if (requested_transition) {
693 (void)sigaction(SIGTSTP, &satstp, NULL);
694 (void)sigaction(SIGHUP, &sahup, NULL);
695 return (state_func_t)requested_transition;
696 }
697
698 if (WIFSIGNALED(status)) {
699 if (WTERMSIG(status) == SIGKILL) {
700 /* executed /sbin/reboot; wait for the end quietly */
701 sigset_t s;
702
703 (void)sigfillset(&s);
704 for (;;)
705 (void)sigsuspend(&s);
706 } else {
707 warning("single user shell terminated, restarting");
708 (void)sigaction(SIGTSTP, &satstp, NULL);
709 (void)sigaction(SIGHUP, &sahup, NULL);
710 return (state_func_t) single_user;
711 }
712 }
713
714 runcom_mode = FASTBOOT;
715 (void)sigaction(SIGTSTP, &satstp, NULL);
716 (void)sigaction(SIGHUP, &sahup, NULL);
717 #ifndef LETS_GET_SMALL
718 return (state_func_t) runcom;
719 #else /* LETS_GET_SMALL */
720 return (state_func_t) single_user;
721 #endif /* LETS_GET_SMALL */
722 }
723
724 #ifndef LETS_GET_SMALL
725 /*
726 * Run the system startup script.
727 */
728 state_func_t
729 runcom(void)
730 {
731 pid_t pid, wpid;
732 int status;
733 char *argv[4];
734 struct sigaction sa;
735
736 switch ((pid = fork())) {
737 case 0:
738 (void)sigemptyset(&sa.sa_mask);
739 sa.sa_flags = 0;
740 sa.sa_handler = SIG_IGN;
741 (void)sigaction(SIGTSTP, &sa, NULL);
742 (void)sigaction(SIGHUP, &sa, NULL);
743
744 setctty(_PATH_CONSOLE);
745
746 argv[0] = "sh";
747 argv[1] = _PATH_RUNCOM;
748 argv[2] = runcom_mode == AUTOBOOT ? "autoboot" : 0;
749 argv[3] = 0;
750
751 (void)sigprocmask(SIG_SETMASK, &sa.sa_mask, NULL);
752
753 (void)execv(INIT_BSHELL, argv);
754 stall("can't exec %s for %s: %m", INIT_BSHELL, _PATH_RUNCOM);
755 _exit(1); /* force single user mode */
756 /*NOTREACHED*/
757 case -1:
758 emergency("can't fork for %s on %s: %m", INIT_BSHELL,
759 _PATH_RUNCOM);
760 while (waitpid(-1, NULL, WNOHANG) > 0)
761 continue;
762 (void)sleep(STALL_TIMEOUT);
763 return (state_func_t)single_user;
764 default:
765 break;
766 }
767
768 /*
769 * Copied from single_user(). This is a bit paranoid.
770 */
771 do {
772 if ((wpid = waitpid(-1, &status, WUNTRACED)) != -1)
773 collect_child(wpid, status);
774 if (wpid == -1) {
775 if (errno == EINTR)
776 continue;
777 warning("wait for %s on %s failed: %m; going to "
778 "single user mode", INIT_BSHELL, _PATH_RUNCOM);
779 return (state_func_t)single_user;
780 }
781 if (wpid == pid && WIFSTOPPED(status)) {
782 warning("init: %s on %s stopped, restarting\n",
783 INIT_BSHELL, _PATH_RUNCOM);
784 (void)kill(pid, SIGCONT);
785 wpid = -1;
786 }
787 } while (wpid != pid);
788
789 if (WIFSIGNALED(status) && WTERMSIG(status) == SIGTERM &&
790 requested_transition == catatonia) {
791 /* /etc/rc executed /sbin/reboot; wait for the end quietly */
792 sigset_t s;
793
794 (void)sigfillset(&s);
795 for (;;)
796 (void)sigsuspend(&s);
797 }
798
799 if (!WIFEXITED(status)) {
800 warning("%s on %s terminated abnormally, going to "
801 "single user mode", INIT_BSHELL, _PATH_RUNCOM);
802 return (state_func_t)single_user;
803 }
804
805 if (WEXITSTATUS(status))
806 return (state_func_t)single_user;
807
808 runcom_mode = AUTOBOOT; /* the default */
809 /* NB: should send a message to the session logger to avoid blocking. */
810 #ifdef SUPPORT_UTMPX
811 logwtmpx("~", "reboot", "", 0, INIT_PROCESS);
812 #endif
813 #ifdef SUPPORT_UTMP
814 logwtmp("~", "reboot", "");
815 #endif
816 return (state_func_t) read_ttys;
817 }
818
819 /*
820 * Open the session database.
821 *
822 * NB: We could pass in the size here; is it necessary?
823 */
824 int
825 start_session_db(void)
826 {
827
828 if (session_db && (*session_db->close)(session_db))
829 emergency("session database close: %m");
830 if ((session_db = dbopen(NULL, O_RDWR, 0, DB_HASH, NULL)) == 0) {
831 emergency("session database open: %m");
832 return (1);
833 }
834 return (0);
835
836 }
837
838 /*
839 * Add a new login session.
840 */
841 void
842 add_session(session_t *sp)
843 {
844 DBT key;
845 DBT data;
846
847 if (session_db == NULL)
848 return;
849
850 key.data = &sp->se_process;
851 key.size = sizeof sp->se_process;
852 data.data = &sp;
853 data.size = sizeof sp;
854
855 if ((*session_db->put)(session_db, &key, &data, 0))
856 emergency("insert %d: %m", sp->se_process);
857 }
858
859 /*
860 * Delete an old login session.
861 */
862 void
863 del_session(session_t *sp)
864 {
865 DBT key;
866
867 key.data = &sp->se_process;
868 key.size = sizeof sp->se_process;
869
870 if ((*session_db->del)(session_db, &key, 0))
871 emergency("delete %d: %m", sp->se_process);
872 }
873
874 /*
875 * Look up a login session by pid.
876 */
877 session_t *
878 find_session(pid_t pid)
879 {
880 DBT key;
881 DBT data;
882 session_t *ret;
883
884 if (session_db == NULL)
885 return NULL;
886
887 key.data = &pid;
888 key.size = sizeof pid;
889 if ((*session_db->get)(session_db, &key, &data, 0) != 0)
890 return 0;
891 (void)memmove(&ret, data.data, sizeof(ret));
892 return ret;
893 }
894
895 /*
896 * Construct an argument vector from a command line.
897 */
898 char **
899 construct_argv(char *command)
900 {
901 int argc = 0;
902 char **argv = malloc(((strlen(command) + 1) / 2 + 1) * sizeof (char *));
903 static const char separators[] = " \t";
904
905 if ((argv[argc++] = strtok(command, separators)) == 0)
906 return (NULL);
907 while ((argv[argc++] = strtok(NULL, separators)) != NULL)
908 continue;
909 return (argv);
910 }
911
912 /*
913 * Deallocate a session descriptor.
914 */
915 void
916 free_session(session_t *sp)
917 {
918
919 free(sp->se_device);
920 if (sp->se_getty) {
921 free(sp->se_getty);
922 free(sp->se_getty_argv);
923 }
924 if (sp->se_window) {
925 free(sp->se_window);
926 free(sp->se_window_argv);
927 }
928 free(sp);
929 }
930
931 /*
932 * Allocate a new session descriptor.
933 */
934 session_t *
935 new_session(session_t *sprev, int session_index, struct ttyent *typ)
936 {
937 session_t *sp;
938
939 if ((typ->ty_status & TTY_ON) == 0 || typ->ty_name == NULL ||
940 typ->ty_getty == NULL)
941 return (NULL);
942
943 sp = malloc(sizeof (session_t));
944 if (sp == NULL)
945 return NULL;
946 memset(sp, 0, sizeof *sp);
947
948 sp->se_flags = SE_PRESENT;
949 sp->se_index = session_index;
950
951 (void)asprintf(&sp->se_device, "%s%s", _PATH_DEV, typ->ty_name);
952 if (!sp->se_device)
953 return NULL;
954
955 if (setupargv(sp, typ) == 0) {
956 free_session(sp);
957 return (NULL);
958 }
959
960 sp->se_next = NULL;
961 if (sprev == NULL) {
962 sessions = sp;
963 sp->se_prev = NULL;
964 } else {
965 sprev->se_next = sp;
966 sp->se_prev = sprev;
967 }
968
969 return (sp);
970 }
971
972 /*
973 * Calculate getty and if useful window argv vectors.
974 */
975 int
976 setupargv(session_t *sp, struct ttyent *typ)
977 {
978
979 if (sp->se_getty) {
980 free(sp->se_getty);
981 free(sp->se_getty_argv);
982 }
983 (void)asprintf(&sp->se_getty, "%s %s", typ->ty_getty, typ->ty_name);
984 if (!sp->se_getty)
985 return (0);
986 sp->se_getty_argv = construct_argv(sp->se_getty);
987 if (sp->se_getty_argv == NULL) {
988 warning("can't parse getty for port %s", sp->se_device);
989 free(sp->se_getty);
990 sp->se_getty = NULL;
991 return (0);
992 }
993 if (typ->ty_window) {
994 if (sp->se_window)
995 free(sp->se_window);
996 sp->se_window = strdup(typ->ty_window);
997 sp->se_window_argv = construct_argv(sp->se_window);
998 if (sp->se_window_argv == NULL) {
999 warning("can't parse window for port %s",
1000 sp->se_device);
1001 free(sp->se_window);
1002 sp->se_window = NULL;
1003 return (0);
1004 }
1005 }
1006 return (1);
1007 }
1008
1009 /*
1010 * Walk the list of ttys and create sessions for each active line.
1011 */
1012 state_func_t
1013 read_ttys(void)
1014 {
1015 int session_index = 0;
1016 session_t *sp, *snext;
1017 struct ttyent *typ;
1018
1019 /*
1020 * Destroy any previous session state.
1021 * There shouldn't be any, but just in case...
1022 */
1023 for (sp = sessions; sp; sp = snext) {
1024 #ifndef LETS_GET_SMALL
1025 if (sp->se_process)
1026 clear_session_logs(sp, 0);
1027 #endif
1028 snext = sp->se_next;
1029 free_session(sp);
1030 }
1031 sessions = NULL;
1032 if (start_session_db())
1033 return (state_func_t)single_user;
1034
1035 /*
1036 * Allocate a session entry for each active port.
1037 * Note that sp starts at 0.
1038 */
1039 while ((typ = getttyent()) != NULL)
1040 if ((snext = new_session(sp, ++session_index, typ)) != NULL)
1041 sp = snext;
1042
1043 endttyent();
1044
1045 return (state_func_t)multi_user;
1046 }
1047
1048 /*
1049 * Start a window system running.
1050 */
1051 void
1052 start_window_system(session_t *sp)
1053 {
1054 pid_t pid;
1055 sigset_t mask;
1056
1057 if ((pid = fork()) == -1) {
1058 emergency("can't fork for window system on port %s: %m",
1059 sp->se_device);
1060 /* hope that getty fails and we can try again */
1061 return;
1062 }
1063
1064 if (pid)
1065 return;
1066
1067 sigemptyset(&mask);
1068 sigprocmask(SIG_SETMASK, &mask, NULL);
1069
1070 if (setsid() < 0)
1071 emergency("setsid failed (window) %m");
1072
1073 (void)execv(sp->se_window_argv[0], sp->se_window_argv);
1074 stall("can't exec window system '%s' for port %s: %m",
1075 sp->se_window_argv[0], sp->se_device);
1076 _exit(1);
1077 }
1078
1079 /*
1080 * Start a login session running.
1081 */
1082 pid_t
1083 start_getty(session_t *sp)
1084 {
1085 pid_t pid;
1086 sigset_t mask;
1087 time_t current_time = time(NULL);
1088
1089 /*
1090 * fork(), not vfork() -- we can't afford to block.
1091 */
1092 if ((pid = fork()) == -1) {
1093 emergency("can't fork for getty on port %s: %m", sp->se_device);
1094 return -1;
1095 }
1096
1097 if (pid)
1098 return pid;
1099
1100 if (current_time > sp->se_started &&
1101 current_time - sp->se_started < GETTY_SPACING) {
1102 warning("getty repeating too quickly on port %s, sleeping",
1103 sp->se_device);
1104 (void)sleep(GETTY_SLEEP);
1105 }
1106
1107 if (sp->se_window) {
1108 start_window_system(sp);
1109 (void)sleep(WINDOW_WAIT);
1110 }
1111
1112 (void)sigemptyset(&mask);
1113 (void)sigprocmask(SIG_SETMASK, &mask, (sigset_t *) 0);
1114
1115 (void)execv(sp->se_getty_argv[0], sp->se_getty_argv);
1116 stall("can't exec getty '%s' for port %s: %m",
1117 sp->se_getty_argv[0], sp->se_device);
1118 _exit(1);
1119 /*NOTREACHED*/
1120 }
1121 #endif /* LETS_GET_SMALL */
1122
1123 /*
1124 * Collect exit status for a child.
1125 * If an exiting login, start a new login running.
1126 */
1127 void
1128 collect_child(pid_t pid, int status)
1129 {
1130 #ifndef LETS_GET_SMALL
1131 session_t *sp, *sprev, *snext;
1132
1133 if (! sessions)
1134 return;
1135
1136 if ((sp = find_session(pid)) == NULL)
1137 return;
1138
1139 clear_session_logs(sp, status);
1140 del_session(sp);
1141 sp->se_process = 0;
1142
1143 if (sp->se_flags & SE_SHUTDOWN) {
1144 if ((sprev = sp->se_prev) != NULL)
1145 sprev->se_next = sp->se_next;
1146 else
1147 sessions = sp->se_next;
1148 if ((snext = sp->se_next) != NULL)
1149 snext->se_prev = sp->se_prev;
1150 free_session(sp);
1151 return;
1152 }
1153
1154 if ((pid = start_getty(sp)) == -1) {
1155 /* serious trouble */
1156 requested_transition = clean_ttys;
1157 return;
1158 }
1159
1160 sp->se_process = pid;
1161 sp->se_started = time(NULL);
1162 add_session(sp);
1163 #endif /* LETS_GET_SMALL */
1164 }
1165
1166 /*
1167 * Catch a signal and request a state transition.
1168 */
1169 void
1170 transition_handler(int sig)
1171 {
1172
1173 switch (sig) {
1174 #ifndef LETS_GET_SMALL
1175 case SIGHUP:
1176 requested_transition = clean_ttys;
1177 break;
1178 case SIGTERM:
1179 requested_transition = death;
1180 break;
1181 case SIGTSTP:
1182 requested_transition = catatonia;
1183 break;
1184 #endif /* LETS_GET_SMALL */
1185 default:
1186 requested_transition = 0;
1187 break;
1188 }
1189 }
1190
1191 #ifndef LETS_GET_SMALL
1192 /*
1193 * Take the system multiuser.
1194 */
1195 state_func_t
1196 multi_user(void)
1197 {
1198 pid_t pid;
1199 int status;
1200 session_t *sp;
1201
1202 requested_transition = 0;
1203
1204 /*
1205 * If the administrator has not set the security level to -1
1206 * to indicate that the kernel should not run multiuser in secure
1207 * mode, and the run script has not set a higher level of security
1208 * than level 1, then put the kernel into secure mode.
1209 */
1210 if (getsecuritylevel() == 0)
1211 setsecuritylevel(1);
1212
1213 for (sp = sessions; sp; sp = sp->se_next) {
1214 if (sp->se_process)
1215 continue;
1216 if ((pid = start_getty(sp)) == -1) {
1217 /* serious trouble */
1218 requested_transition = clean_ttys;
1219 break;
1220 }
1221 sp->se_process = pid;
1222 sp->se_started = time(NULL);
1223 add_session(sp);
1224 }
1225
1226 while (!requested_transition)
1227 if ((pid = waitpid(-1, &status, 0)) != -1)
1228 collect_child(pid, status);
1229
1230 return (state_func_t)requested_transition;
1231 }
1232
1233 /*
1234 * This is an n-squared algorithm. We hope it isn't run often...
1235 */
1236 state_func_t
1237 clean_ttys(void)
1238 {
1239 session_t *sp, *sprev;
1240 struct ttyent *typ;
1241 int session_index = 0;
1242 int devlen;
1243
1244 for (sp = sessions; sp; sp = sp->se_next)
1245 sp->se_flags &= ~SE_PRESENT;
1246
1247 devlen = sizeof(_PATH_DEV) - 1;
1248 while ((typ = getttyent()) != NULL) {
1249 ++session_index;
1250
1251 for (sprev = 0, sp = sessions; sp; sprev = sp, sp = sp->se_next)
1252 if (strcmp(typ->ty_name, sp->se_device + devlen) == 0)
1253 break;
1254
1255 if (sp) {
1256 sp->se_flags |= SE_PRESENT;
1257 if (sp->se_index != session_index) {
1258 warning("port %s changed utmp index from "
1259 "%d to %d", sp->se_device, sp->se_index,
1260 session_index);
1261 sp->se_index = session_index;
1262 }
1263 if ((typ->ty_status & TTY_ON) == 0 ||
1264 typ->ty_getty == 0) {
1265 sp->se_flags |= SE_SHUTDOWN;
1266 if (sp->se_process != 0)
1267 (void)kill(sp->se_process, SIGHUP);
1268 continue;
1269 }
1270 sp->se_flags &= ~SE_SHUTDOWN;
1271 if (setupargv(sp, typ) == 0) {
1272 warning("can't parse getty for port %s",
1273 sp->se_device);
1274 sp->se_flags |= SE_SHUTDOWN;
1275 if (sp->se_process != 0)
1276 (void)kill(sp->se_process, SIGHUP);
1277 }
1278 continue;
1279 }
1280
1281 new_session(sprev, session_index, typ);
1282 }
1283
1284 endttyent();
1285
1286 for (sp = sessions; sp; sp = sp->se_next)
1287 if ((sp->se_flags & SE_PRESENT) == 0) {
1288 sp->se_flags |= SE_SHUTDOWN;
1289 if (sp->se_process != 0)
1290 (void)kill(sp->se_process, SIGHUP);
1291 }
1292
1293 return (state_func_t)multi_user;
1294 }
1295
1296 /*
1297 * Block further logins.
1298 */
1299 state_func_t
1300 catatonia(void)
1301 {
1302 session_t *sp;
1303
1304 for (sp = sessions; sp; sp = sp->se_next)
1305 sp->se_flags |= SE_SHUTDOWN;
1306
1307 return (state_func_t)multi_user;
1308 }
1309 #endif /* LETS_GET_SMALL */
1310
1311 /*
1312 * Note SIGALRM.
1313 */
1314 void
1315 /*ARGSUSED*/
1316 alrm_handler(int sig)
1317 {
1318
1319 clang = 1;
1320 }
1321
1322 #ifndef LETS_GET_SMALL
1323 /*
1324 * Bring the system down to single user.
1325 */
1326 state_func_t
1327 death(void)
1328 {
1329 session_t *sp;
1330 int i, status;
1331 pid_t pid;
1332 static const int death_sigs[3] = { SIGHUP, SIGTERM, SIGKILL };
1333
1334 for (sp = sessions; sp; sp = sp->se_next)
1335 sp->se_flags |= SE_SHUTDOWN;
1336
1337 /* NB: should send a message to the session logger to avoid blocking. */
1338 #ifdef SUPPORT_UTMPX
1339 logwtmpx("~", "shutdown", "", 0, INIT_PROCESS);
1340 #endif
1341 #ifdef SUPPORT_UTMP
1342 logwtmp("~", "shutdown", "");
1343 #endif
1344
1345 for (i = 0; i < 3; ++i) {
1346 if (kill(-1, death_sigs[i]) == -1 && errno == ESRCH)
1347 return (state_func_t)single_user;
1348
1349 clang = 0;
1350 alarm(DEATH_WATCH);
1351 do
1352 if ((pid = waitpid(-1, &status, 0)) != -1)
1353 collect_child(pid, status);
1354 while (clang == 0 && errno != ECHILD);
1355
1356 if (errno == ECHILD)
1357 return (state_func_t)single_user;
1358 }
1359
1360 warning("some processes would not die; ps axl advised");
1361
1362 return (state_func_t)single_user;
1363 }
1364 #endif /* LETS_GET_SMALL */
1365
1366 #ifdef MFS_DEV_IF_NO_CONSOLE
1367
1368 static void
1369 mapfile(struct mappedfile *mf)
1370 {
1371 int fd;
1372 struct stat st;
1373
1374 if (lstat(mf->path, &st) == -1)
1375 return;
1376
1377 if ((st.st_mode & S_IFMT) == S_IFLNK) {
1378 mf->buf = malloc(st.st_size + 1);
1379 mf->buf[st.st_size] = 0;
1380 if (readlink(mf->path, mf->buf, st.st_size) != st.st_size)
1381 return;
1382 mf->len = -1;
1383 return;
1384 }
1385
1386 if ((fd = open(mf->path, O_RDONLY)) == -1)
1387 return;
1388 mf->buf = mmap(0, (size_t)st.st_size, PROT_READ,
1389 MAP_FILE|MAP_SHARED, fd, (off_t)0);
1390 (void)close(fd);
1391 if (mf->buf == MAP_FAILED)
1392 return;
1393 mf->len = st.st_size;
1394 }
1395
1396 static void
1397 writefile(struct mappedfile *mf)
1398 {
1399 int fd;
1400
1401 if (mf->len == -1) {
1402 symlink(mf->buf, mf->path);
1403 free(mf->buf);
1404 return;
1405 }
1406
1407 if (mf->len == 0)
1408 return;
1409 fd = open(mf->path, O_WRONLY | O_CREAT | O_TRUNC, 0755);
1410 if (fd == -1)
1411 return;
1412 (void)write(fd, mf->buf, mf->len);
1413 (void)munmap(mf->buf, mf->len);
1414 (void)close(fd);
1415 }
1416
1417 static int
1418 mfs_dev(void)
1419 {
1420 /*
1421 * We cannot print errors so we bail out silently...
1422 */
1423 pid_t pid;
1424 int status;
1425 dev_t dev;
1426 char *fs_size;
1427 #ifdef CPU_CONSDEV
1428 static int name[2] = { CTL_MACHDEP, CPU_CONSDEV };
1429 size_t olen;
1430 #endif
1431
1432 /* If we have /dev/console, assume all is OK */
1433 if (access(_PATH_CONSOLE, F_OK) != -1)
1434 return(0);
1435
1436 /* Grab the contents of MAKEDEV */
1437 mapfile(&mfile[0]);
1438
1439 /* Grab the contents of MAKEDEV.local */
1440 mapfile(&mfile[1]);
1441
1442 /* Mount an mfs over /dev so we can create devices */
1443 switch ((pid = fork())) {
1444 case 0:
1445 asprintf(&fs_size, "%d", FSSIZE);
1446 (void)execl(INIT_MOUNT_MFS, "mount_mfs",
1447 "-b", "4096", "-f", "512",
1448 "-s", fs_size, "-n", STR(NINODE),
1449 "-p", "0755",
1450 "swap", "/dev", NULL);
1451 _exit(1);
1452 /*NOTREACHED*/
1453
1454 case -1:
1455 return(-1);
1456
1457 default:
1458 if (waitpid(pid, &status, 0) == -1)
1459 return(-1);
1460 if (status != 0)
1461 return(-1);
1462 break;
1463 }
1464
1465 #ifdef CPU_CONSDEV
1466 olen = sizeof(dev);
1467 if (sysctl(name, sizeof(name) / sizeof(name[0]), &dev, &olen,
1468 NULL, 0) == -1)
1469 #endif
1470 dev = makedev(0, 0);
1471
1472 /* Make a console for us, so we can see things happening */
1473 if (mknod(_PATH_CONSOLE, 0666 | S_IFCHR, dev) == -1)
1474 return(-1);
1475
1476 (void)freopen(_PATH_CONSOLE, "a", stderr);
1477
1478 warnx("Creating mfs /dev (%d blocks, %d inodes)", FSSIZE, NINODE);
1479
1480 /* Create a MAKEDEV script in the mfs /dev */
1481 writefile(&mfile[0]);
1482
1483 /* Create a MAKEDEV.local script in the mfs /dev */
1484 writefile(&mfile[1]);
1485
1486 /* Run the makedev script to create devices */
1487 switch ((pid = fork())) {
1488 case 0:
1489 dup2(2, 1); /* Give the script stdout */
1490 if (chdir("/dev") == 0)
1491 (void)execl(INIT_BSHELL, "sh",
1492 mfile[0].len ? "./MAKEDEV" : "/etc/MAKEDEV",
1493 "init", NULL);
1494 _exit(1);
1495
1496 case -1:
1497 break;
1498
1499 default:
1500 if (waitpid(pid, &status, 0) == -1)
1501 break;
1502 if (status != 0) {
1503 errno = EINVAL;
1504 break;
1505 }
1506 return 0;
1507 }
1508 warn("Unable to run MAKEDEV");
1509 return (-1);
1510 }
1511 #endif
1512