init.c revision 1.75 1 /* $NetBSD: init.c,v 1.75 2006/07/30 19:53:20 elad 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.75 2006/07/30 19:53:20 elad 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 void setctty(const char *);
139
140 typedef struct init_session {
141 int se_index; /* index of entry in ttys file */
142 pid_t se_process; /* controlling process */
143 time_t se_started; /* used to avoid thrashing */
144 int se_flags; /* status of session */
145 #define SE_SHUTDOWN 0x1 /* session won't be restarted */
146 #define SE_PRESENT 0x2 /* session is in /etc/ttys */
147 char *se_device; /* filename of port */
148 char *se_getty; /* what to run on that port */
149 char **se_getty_argv; /* pre-parsed argument array */
150 char *se_window; /* window system (started only once) */
151 char **se_window_argv; /* pre-parsed argument array */
152 struct init_session *se_prev;
153 struct init_session *se_next;
154 } session_t;
155
156 void free_session(session_t *);
157 session_t *new_session(session_t *, int, struct ttyent *);
158 session_t *sessions;
159
160 char **construct_argv(char *);
161 void start_window_system(session_t *);
162 void collect_child(pid_t, int);
163 pid_t start_getty(session_t *);
164 void transition_handler(int);
165 void alrm_handler(int);
166 void setsecuritylevel(int);
167 int getsecuritylevel(void);
168 int setupargv(session_t *, struct ttyent *);
169 int clang;
170
171 int start_session_db(void);
172 void add_session(session_t *);
173 void del_session(session_t *);
174 session_t *find_session(pid_t);
175 DB *session_db;
176
177 int do_setttyent(void);
178
179 #ifndef LETS_GET_SMALL
180 state_t requested_transition = runcom;
181
182 void clear_session_logs(session_t *, int);
183 state_func_t runetcrc(int);
184
185 #ifdef CHROOT
186 int did_multiuser_chroot = 0;
187 char rootdir[PATH_MAX];
188 int shouldchroot(void);
189 int createsysctlnode(void);
190 #endif /* CHROOT */
191
192 #else /* LETS_GET_SMALL */
193 state_t requested_transition = single_user;
194 #endif /* !LETS_GET_SMALL */
195
196 #ifdef MFS_DEV_IF_NO_CONSOLE
197
198 #define NINODE 1024
199 #define FSSIZE ((8192 /* boot area */ \
200 + 2 * 8192 /* two copies of superblock */ \
201 + 4096 /* cylinder group info */ \
202 + NINODE * (128 + 18) /* inode and directory entry */ \
203 + mfile[0].len /* size of MAKEDEV file */ \
204 + 2 * 4096) / 512) /* some slack */
205
206 struct mappedfile {
207 const char *path;
208 char *buf;
209 int len;
210 } mfile[] = {
211 { "/dev/MAKEDEV", NULL, 0 },
212 { "/dev/MAKEDEV.local", NULL, 0 }
213 };
214
215 static int mfs_dev(void);
216 static void mapfile(struct mappedfile *);
217 static void writefile(struct mappedfile *);
218
219 #endif
220
221 /*
222 * The mother of all processes.
223 */
224 int
225 main(int argc, char **argv)
226 {
227 struct sigaction sa;
228 sigset_t mask;
229 #ifndef LETS_GET_SMALL
230 int c;
231
232 /* Dispose of random users. */
233 if (getuid() != 0) {
234 errno = EPERM;
235 err(1, NULL);
236 }
237
238 /* System V users like to reexec init. */
239 if (getpid() != 1)
240 errx(1, "already running");
241 #endif
242
243 /*
244 * Create an initial session.
245 */
246 if (setsid() < 0)
247 warn("initial setsid() failed");
248
249 /*
250 * Establish an initial user so that programs running
251 * single user do not freak out and die (like passwd).
252 */
253 if (setlogin("root") < 0)
254 warn("setlogin() failed");
255
256
257 #ifdef MFS_DEV_IF_NO_CONSOLE
258 if (mfs_dev() == -1)
259 requested_transition = single_user;
260 #endif
261
262 #ifndef LETS_GET_SMALL
263 /*
264 * Note that this does NOT open a file...
265 * Does 'init' deserve its own facility number?
266 */
267 openlog("init", LOG_CONS, LOG_AUTH);
268 #endif /* LETS_GET_SMALL */
269
270
271 #ifndef LETS_GET_SMALL
272 /*
273 * This code assumes that we always get arguments through flags,
274 * never through bits set in some random machine register.
275 */
276 while ((c = getopt(argc, argv, "sf")) != -1)
277 switch (c) {
278 case 's':
279 requested_transition = single_user;
280 break;
281 case 'f':
282 runcom_mode = FASTBOOT;
283 break;
284 default:
285 warning("unrecognized flag '-%c'", c);
286 break;
287 }
288
289 if (optind != argc)
290 warning("ignoring excess arguments");
291 #else /* LETS_GET_SMALL */
292 requested_transition = single_user;
293 #endif /* LETS_GET_SMALL */
294
295 /*
296 * We catch or block signals rather than ignore them,
297 * so that they get reset on exec.
298 */
299 handle(badsys, SIGSYS, 0);
300 handle(disaster, SIGABRT, SIGFPE, SIGILL, SIGSEGV,
301 SIGBUS, SIGXCPU, SIGXFSZ, 0);
302 handle(transition_handler, SIGHUP, SIGTERM, SIGTSTP, 0);
303 handle(alrm_handler, SIGALRM, 0);
304 (void)sigfillset(&mask);
305 delset(&mask, SIGABRT, SIGFPE, SIGILL, SIGSEGV, SIGBUS, SIGSYS,
306 SIGXCPU, SIGXFSZ, SIGHUP, SIGTERM, SIGTSTP, SIGALRM, 0);
307 (void)sigprocmask(SIG_SETMASK, &mask, NULL);
308 (void)sigemptyset(&sa.sa_mask);
309 sa.sa_flags = 0;
310 sa.sa_handler = SIG_IGN;
311 (void)sigaction(SIGTTIN, &sa, NULL);
312 (void)sigaction(SIGTTOU, &sa, NULL);
313
314 /*
315 * Paranoia.
316 */
317 (void)close(0);
318 (void)close(1);
319 (void)close(2);
320
321 #if !defined(LETS_GET_SMALL) && defined(CHROOT)
322 /* Create "init.root" sysctl node. */
323 createsysctlnode();
324 #endif /* !LETS_GET_SMALL && CHROOT*/
325
326 /*
327 * Start the state machine.
328 */
329 transition(requested_transition);
330
331 /*
332 * Should never reach here.
333 */
334 return 1;
335 }
336
337 /*
338 * Associate a function with a signal handler.
339 */
340 void
341 handle(sig_t handler, ...)
342 {
343 int sig;
344 struct sigaction sa;
345 sigset_t mask_everything;
346 va_list ap;
347
348 va_start(ap, handler);
349
350 sa.sa_handler = handler;
351 (void)sigfillset(&mask_everything);
352
353 while ((sig = va_arg(ap, int)) != 0) {
354 sa.sa_mask = mask_everything;
355 /* XXX SA_RESTART? */
356 sa.sa_flags = sig == SIGCHLD ? SA_NOCLDSTOP : 0;
357 (void)sigaction(sig, &sa, NULL);
358 }
359 va_end(ap);
360 }
361
362 /*
363 * Delete a set of signals from a mask.
364 */
365 void
366 delset(sigset_t *maskp, ...)
367 {
368 int sig;
369 va_list ap;
370
371 va_start(ap, maskp);
372
373 while ((sig = va_arg(ap, int)) != 0)
374 (void)sigdelset(maskp, sig);
375 va_end(ap);
376 }
377
378 /*
379 * Log a message and sleep for a while (to give someone an opportunity
380 * to read it and to save log or hardcopy output if the problem is chronic).
381 * NB: should send a message to the session logger to avoid blocking.
382 */
383 void
384 stall(const char *message, ...)
385 {
386 va_list ap;
387
388 va_start(ap, message);
389 vsyslog(LOG_ALERT, message, ap);
390 va_end(ap);
391 closelog();
392 (void)sleep(STALL_TIMEOUT);
393 }
394
395 /*
396 * Like stall(), but doesn't sleep.
397 * If cpp had variadic macros, the two functions could be #defines for another.
398 * NB: should send a message to the session logger to avoid blocking.
399 */
400 void
401 warning(const char *message, ...)
402 {
403 va_list ap;
404
405 va_start(ap, message);
406 vsyslog(LOG_ALERT, message, ap);
407 va_end(ap);
408 closelog();
409
410 #if 0
411 /*
412 * XXX: syslog seems to just plain not work in console-only
413 * XXX: situation... that should be fixed. Let's leave this
414 * XXX: note + code here in case someone gets in trouble and
415 * XXX: wants to debug. -- Jachym Holecek <freza (at) liberouter.org>
416 */
417 {
418 char errbuf[1024];
419 int fd, len;
420
421 /* We can't do anything on errors, anyway... */
422 fd = open(_PATH_CONSOLE, O_WRONLY);
423 if (fd == -1)
424 return ;
425
426 /* %m will get lost... */
427 len = vsnprintf(errbuf, sizeof(errbuf), message, ap);
428 (void)write(fd, (void *)errbuf, len);
429 (void)close(fd);
430 }
431 #endif
432 }
433
434 /*
435 * Log an emergency message.
436 * NB: should send a message to the session logger to avoid blocking.
437 */
438 void
439 emergency(const char *message, ...)
440 {
441 va_list ap;
442
443 va_start(ap, message);
444 vsyslog(LOG_EMERG, message, ap);
445 va_end(ap);
446 closelog();
447 }
448
449 /*
450 * Catch a SIGSYS signal.
451 *
452 * These may arise if a system does not support sysctl.
453 * We tolerate up to 25 of these, then throw in the towel.
454 */
455 void
456 badsys(int sig)
457 {
458 static int badcount = 0;
459
460 if (badcount++ < 25)
461 return;
462 disaster(sig);
463 }
464
465 /*
466 * Catch an unexpected signal.
467 */
468 void
469 disaster(int sig)
470 {
471
472 emergency("fatal signal: %s", strsignal(sig));
473 (void)sleep(STALL_TIMEOUT);
474 _exit(sig); /* reboot */
475 }
476
477 /*
478 * Get the security level of the kernel.
479 */
480 int
481 getsecuritylevel(void)
482 {
483 #ifdef KERN_SECURELVL
484 int name[2], curlevel;
485 size_t len;
486
487 name[0] = CTL_KERN;
488 name[1] = KERN_SECURELVL;
489 len = sizeof curlevel;
490 if (sysctl(name, 2, &curlevel, &len, NULL, 0) == -1) {
491 emergency("cannot get kernel security level: %m");
492 return (-1);
493 }
494 return (curlevel);
495 #else
496 return (-1);
497 #endif
498 }
499
500 /*
501 * Set the security level of the kernel.
502 */
503 void
504 setsecuritylevel(int newlevel)
505 {
506 #ifdef KERN_SECURELVL
507 int name[2], curlevel;
508
509 curlevel = getsecuritylevel();
510 if (newlevel == curlevel)
511 return;
512 name[0] = CTL_KERN;
513 name[1] = KERN_SECURELVL;
514 if (sysctl(name, 2, NULL, NULL, &newlevel, sizeof newlevel) == -1) {
515 emergency( "cannot change kernel security level from"
516 " %d to %d: %m", curlevel, newlevel);
517 return;
518 }
519 #ifdef SECURE
520 warning("kernel security level changed from %d to %d",
521 curlevel, newlevel);
522 #endif
523 #endif
524 }
525
526 /*
527 * Change states in the finite state machine.
528 * The initial state is passed as an argument.
529 */
530 void
531 transition(state_t s)
532 {
533
534 if (s == NULL)
535 return;
536 for (;;)
537 s = (state_t)(*s)();
538 }
539
540 #ifndef LETS_GET_SMALL
541 /*
542 * Close out the accounting files for a login session.
543 * NB: should send a message to the session logger to avoid blocking.
544 */
545 void
546 clear_session_logs(session_t *sp, int status)
547 {
548 char *line = sp->se_device + sizeof(_PATH_DEV) - 1;
549
550 #ifdef SUPPORT_UTMPX
551 if (logoutx(line, status, DEAD_PROCESS))
552 logwtmpx(line, "", "", status, DEAD_PROCESS);
553 #endif
554 #ifdef SUPPORT_UTMP
555 if (logout(line))
556 logwtmp(line, "", "");
557 #endif
558 }
559 #endif
560
561 /*
562 * Start a session and allocate a controlling terminal.
563 * Only called by children of init after forking.
564 */
565 void
566 setctty(const char *name)
567 {
568 int fd;
569
570 (void) revoke(name);
571 nanosleep(&dtrtime, NULL); /* leave DTR low for a bit */
572 if ((fd = open(name, O_RDWR)) == -1) {
573 stall("can't open %s: %m", name);
574 _exit(1);
575 }
576 if (login_tty(fd) == -1) {
577 stall("can't get %s for controlling terminal: %m", name);
578 _exit(1);
579 }
580 }
581
582 /*
583 * Bring the system up single user.
584 */
585 state_func_t
586 single_user(void)
587 {
588 pid_t pid, wpid;
589 int status;
590 int from_securitylevel;
591 sigset_t mask;
592 struct sigaction sa, satstp, sahup;
593 #ifdef ALTSHELL
594 const char *shell = INIT_BSHELL;
595 #endif
596 const char *argv[2];
597 #ifdef SECURE
598 struct ttyent *typ;
599 struct passwd *pp;
600 char *clear, *password;
601 #endif
602 #ifdef ALTSHELL
603 char altshell[128];
604 #endif /* ALTSHELL */
605
606 #if !defined(LETS_GET_SMALL) && defined(CHROOT)
607 /* Clear previous idea, just in case. */
608 did_multiuser_chroot = 0;
609 #endif /* !LETS_GET_SMALL && CHROOT */
610
611 /*
612 * If the kernel is in secure mode, downgrade it to insecure mode.
613 */
614 from_securitylevel = getsecuritylevel();
615 if (from_securitylevel > 0)
616 setsecuritylevel(0);
617
618 (void)sigemptyset(&sa.sa_mask);
619 sa.sa_flags = 0;
620 sa.sa_handler = SIG_IGN;
621 (void)sigaction(SIGTSTP, &sa, &satstp);
622 (void)sigaction(SIGHUP, &sa, &sahup);
623 if ((pid = fork()) == 0) {
624 /*
625 * Start the single user session.
626 */
627 if (access(_PATH_CONSTTY, F_OK) == 0)
628 setctty(_PATH_CONSTTY);
629 else
630 setctty(_PATH_CONSOLE);
631
632 #ifdef SECURE
633 /*
634 * Check the root password.
635 * We don't care if the console is 'on' by default;
636 * it's the only tty that can be 'off' and 'secure'.
637 */
638 typ = getttynam("console");
639 pp = getpwnam("root");
640 if (typ && (from_securitylevel >=2 || (typ->ty_status
641 & TTY_SECURE) == 0) && pp && *pp->pw_passwd != '\0') {
642 (void)fprintf(stderr,
643 "Enter root password, or ^D to go multi-user\n");
644 for (;;) {
645 clear = getpass("Password:");
646 if (clear == 0 || *clear == '\0')
647 _exit(0);
648 password = crypt(clear, pp->pw_passwd);
649 (void)memset(clear, 0, _PASSWORD_LEN);
650 if (strcmp(password, pp->pw_passwd) == 0)
651 break;
652 warning("single-user login failed\n");
653 }
654 }
655 endttyent();
656 endpwent();
657 #endif /* SECURE */
658
659 #ifdef ALTSHELL
660 (void)fprintf(stderr,
661 "Enter pathname of shell or RETURN for %s: ", shell);
662 if (fgets(altshell, sizeof(altshell), stdin) == NULL) {
663 altshell[0] = '\0';
664 } else {
665 /* nuke \n */
666 char *p;
667
668 if ((p = strchr(altshell, '\n')) != NULL)
669 *p = '\0';
670 }
671
672 if (altshell[0])
673 shell = altshell;
674 #endif /* ALTSHELL */
675
676 /*
677 * Unblock signals.
678 * We catch all the interesting ones,
679 * and those are reset to SIG_DFL on exec.
680 */
681 (void)sigemptyset(&mask);
682 (void)sigprocmask(SIG_SETMASK, &mask, NULL);
683
684 /*
685 * Fire off a shell.
686 * If the default one doesn't work, try the Bourne shell.
687 */
688 argv[0] = "-sh";
689 argv[1] = 0;
690 setenv("PATH", INIT_PATH, 1);
691 #ifdef ALTSHELL
692 if (altshell[0])
693 argv[0] = altshell;
694 (void)execv(shell, __UNCONST(argv));
695 emergency("can't exec %s for single user: %m", shell);
696 argv[0] = "-sh";
697 #endif /* ALTSHELL */
698 (void)execv(INIT_BSHELL, __UNCONST(argv));
699 emergency("can't exec %s for single user: %m", INIT_BSHELL);
700 (void)sleep(STALL_TIMEOUT);
701 _exit(1);
702 }
703
704 if (pid == -1) {
705 /*
706 * We are seriously hosed. Do our best.
707 */
708 emergency("can't fork single-user shell, trying again");
709 while (waitpid(-1, NULL, WNOHANG) > 0)
710 continue;
711 (void)sigaction(SIGTSTP, &satstp, NULL);
712 (void)sigaction(SIGHUP, &sahup, NULL);
713 return (state_func_t) single_user;
714 }
715
716 requested_transition = 0;
717 do {
718 if ((wpid = waitpid(-1, &status, WUNTRACED)) != -1)
719 collect_child(wpid, status);
720 if (wpid == -1) {
721 if (errno == EINTR)
722 continue;
723 warning("wait for single-user shell failed: %m; "
724 "restarting");
725 return (state_func_t)single_user;
726 }
727 if (wpid == pid && WIFSTOPPED(status)) {
728 warning("init: shell stopped, restarting\n");
729 kill(pid, SIGCONT);
730 wpid = -1;
731 }
732 } while (wpid != pid && !requested_transition);
733
734 if (requested_transition) {
735 (void)sigaction(SIGTSTP, &satstp, NULL);
736 (void)sigaction(SIGHUP, &sahup, NULL);
737 return (state_func_t)requested_transition;
738 }
739
740 if (WIFSIGNALED(status)) {
741 if (WTERMSIG(status) == SIGKILL) {
742 /* executed /sbin/reboot; wait for the end quietly */
743 sigset_t s;
744
745 (void)sigfillset(&s);
746 for (;;)
747 (void)sigsuspend(&s);
748 } else {
749 warning("single user shell terminated, restarting");
750 (void)sigaction(SIGTSTP, &satstp, NULL);
751 (void)sigaction(SIGHUP, &sahup, NULL);
752 return (state_func_t) single_user;
753 }
754 }
755
756 runcom_mode = FASTBOOT;
757 (void)sigaction(SIGTSTP, &satstp, NULL);
758 (void)sigaction(SIGHUP, &sahup, NULL);
759 #ifndef LETS_GET_SMALL
760 return (state_func_t) runcom;
761 #else /* LETS_GET_SMALL */
762 return (state_func_t) single_user;
763 #endif /* LETS_GET_SMALL */
764 }
765
766 #ifndef LETS_GET_SMALL
767
768 /* ARGSUSED */
769 state_func_t
770 runetcrc(int trychroot)
771 {
772 pid_t pid, wpid;
773 int status;
774 const char *argv[4];
775 struct sigaction sa;
776
777 switch ((pid = fork())) {
778 case 0:
779 (void)sigemptyset(&sa.sa_mask);
780 sa.sa_flags = 0;
781 sa.sa_handler = SIG_IGN;
782 (void)sigaction(SIGTSTP, &sa, NULL);
783 (void)sigaction(SIGHUP, &sa, NULL);
784
785 setctty(_PATH_CONSOLE);
786
787 argv[0] = "sh";
788 argv[1] = _PATH_RUNCOM;
789 argv[2] = (runcom_mode == AUTOBOOT ? "autoboot" : 0);
790 argv[3] = 0;
791
792 (void)sigprocmask(SIG_SETMASK, &sa.sa_mask, NULL);
793
794 #ifdef CHROOT
795 if (trychroot)
796 if (chroot(rootdir) != 0) {
797 warning("failed to chroot to %s, error: %m",
798 rootdir);
799 _exit(1); /* force single user mode */
800 }
801 #endif /* CHROOT */
802
803 (void)execv(INIT_BSHELL, __UNCONST(argv));
804 stall("can't exec %s for %s: %m", INIT_BSHELL, _PATH_RUNCOM);
805 _exit(1); /* force single user mode */
806 /*NOTREACHED*/
807 case -1:
808 emergency("can't fork for %s on %s: %m", INIT_BSHELL,
809 _PATH_RUNCOM);
810 while (waitpid(-1, NULL, WNOHANG) > 0)
811 continue;
812 (void)sleep(STALL_TIMEOUT);
813 return (state_func_t)single_user;
814 default:
815 break;
816 }
817
818 /*
819 * Copied from single_user(). This is a bit paranoid.
820 */
821 do {
822 if ((wpid = waitpid(-1, &status, WUNTRACED)) != -1)
823 collect_child(wpid, status);
824 if (wpid == -1) {
825 if (errno == EINTR)
826 continue;
827 warning("wait for %s on %s failed: %m; going to "
828 "single user mode", INIT_BSHELL, _PATH_RUNCOM);
829 return (state_func_t)single_user;
830 }
831 if (wpid == pid && WIFSTOPPED(status)) {
832 warning("init: %s on %s stopped, restarting\n",
833 INIT_BSHELL, _PATH_RUNCOM);
834 (void)kill(pid, SIGCONT);
835 wpid = -1;
836 }
837 } while (wpid != pid);
838
839 if (WIFSIGNALED(status) && WTERMSIG(status) == SIGTERM &&
840 requested_transition == catatonia) {
841 /* /etc/rc executed /sbin/reboot; wait for the end quietly */
842 sigset_t s;
843
844 (void)sigfillset(&s);
845 for (;;)
846 (void)sigsuspend(&s);
847 }
848
849 if (!WIFEXITED(status)) {
850 warning("%s on %s terminated abnormally, going to "
851 "single user mode", INIT_BSHELL, _PATH_RUNCOM);
852 return (state_func_t)single_user;
853 }
854
855 if (WEXITSTATUS(status))
856 return (state_func_t)single_user;
857
858 return (state_func_t) read_ttys;
859 }
860
861 /*
862 * Run the system startup script.
863 */
864 state_func_t
865 runcom(void)
866 {
867 state_func_t next_step;
868
869 /* Run /etc/rc and choose next state depending on the result. */
870 next_step = runetcrc(0);
871 if (next_step != (state_func_t) read_ttys)
872 return (state_func_t) next_step;
873
874 #ifdef CHROOT
875 /*
876 * If init.root sysctl does not point to "/", we'll chroot and run
877 * The Real(tm) /etc/rc now. Global variable rootdir will tell us
878 * where to go.
879 */
880 if (shouldchroot()) {
881 next_step = runetcrc(1);
882 if (next_step != (state_func_t) read_ttys)
883 return (state_func_t) next_step;
884
885 did_multiuser_chroot = 1;
886 } else {
887 did_multiuser_chroot = 0;
888 }
889 #endif /* CHROOT */
890
891 /*
892 * Regardless of whether in chroot or not, we booted successfuly.
893 * It's time to spawn gettys (ie. next_step's value at this point).
894 */
895 runcom_mode = AUTOBOOT; /* the default */
896 /* NB: should send a message to the session logger to avoid blocking. */
897 #ifdef SUPPORT_UTMPX
898 logwtmpx("~", "reboot", "", 0, INIT_PROCESS);
899 #endif
900 #ifdef SUPPORT_UTMP
901 logwtmp("~", "reboot", "");
902 #endif
903 return (state_func_t) read_ttys;
904 }
905
906 /*
907 * Open the session database.
908 *
909 * NB: We could pass in the size here; is it necessary?
910 */
911 int
912 start_session_db(void)
913 {
914
915 if (session_db && (*session_db->close)(session_db))
916 emergency("session database close: %m");
917 if ((session_db = dbopen(NULL, O_RDWR, 0, DB_HASH, NULL)) == 0) {
918 emergency("session database open: %m");
919 return (1);
920 }
921 return (0);
922
923 }
924
925 /*
926 * Add a new login session.
927 */
928 void
929 add_session(session_t *sp)
930 {
931 DBT key;
932 DBT data;
933
934 if (session_db == NULL)
935 return;
936
937 key.data = &sp->se_process;
938 key.size = sizeof sp->se_process;
939 data.data = &sp;
940 data.size = sizeof sp;
941
942 if ((*session_db->put)(session_db, &key, &data, 0))
943 emergency("insert %d: %m", sp->se_process);
944 }
945
946 /*
947 * Delete an old login session.
948 */
949 void
950 del_session(session_t *sp)
951 {
952 DBT key;
953
954 key.data = &sp->se_process;
955 key.size = sizeof sp->se_process;
956
957 if ((*session_db->del)(session_db, &key, 0))
958 emergency("delete %d: %m", sp->se_process);
959 }
960
961 /*
962 * Look up a login session by pid.
963 */
964 session_t *
965 find_session(pid_t pid)
966 {
967 DBT key;
968 DBT data;
969 session_t *ret;
970
971 if (session_db == NULL)
972 return NULL;
973
974 key.data = &pid;
975 key.size = sizeof pid;
976 if ((*session_db->get)(session_db, &key, &data, 0) != 0)
977 return 0;
978 (void)memmove(&ret, data.data, sizeof(ret));
979 return ret;
980 }
981
982 /*
983 * Construct an argument vector from a command line.
984 */
985 char **
986 construct_argv(char *command)
987 {
988 int argc = 0;
989 char **argv = malloc(((strlen(command) + 1) / 2 + 1) * sizeof (char *));
990 static const char separators[] = " \t";
991
992 if (argv == NULL)
993 return (NULL);
994
995 if ((argv[argc++] = strtok(command, separators)) == 0) {
996 free(argv);
997 return (NULL);
998 }
999 while ((argv[argc++] = strtok(NULL, separators)) != NULL)
1000 continue;
1001 return (argv);
1002 }
1003
1004 /*
1005 * Deallocate a session descriptor.
1006 */
1007 void
1008 free_session(session_t *sp)
1009 {
1010
1011 free(sp->se_device);
1012 if (sp->se_getty) {
1013 free(sp->se_getty);
1014 free(sp->se_getty_argv);
1015 }
1016 if (sp->se_window) {
1017 free(sp->se_window);
1018 free(sp->se_window_argv);
1019 }
1020 free(sp);
1021 }
1022
1023 /*
1024 * Allocate a new session descriptor.
1025 */
1026 session_t *
1027 new_session(session_t *sprev, int session_index, struct ttyent *typ)
1028 {
1029 session_t *sp;
1030
1031 if ((typ->ty_status & TTY_ON) == 0 || typ->ty_name == NULL ||
1032 typ->ty_getty == NULL)
1033 return (NULL);
1034
1035 sp = malloc(sizeof (session_t));
1036 if (sp == NULL)
1037 return NULL;
1038 memset(sp, 0, sizeof *sp);
1039
1040 sp->se_flags = SE_PRESENT;
1041 sp->se_index = session_index;
1042
1043 (void)asprintf(&sp->se_device, "%s%s", _PATH_DEV, typ->ty_name);
1044 if (!sp->se_device)
1045 return NULL;
1046
1047 if (setupargv(sp, typ) == 0) {
1048 free_session(sp);
1049 return (NULL);
1050 }
1051
1052 sp->se_next = NULL;
1053 if (sprev == NULL) {
1054 sessions = sp;
1055 sp->se_prev = NULL;
1056 } else {
1057 sprev->se_next = sp;
1058 sp->se_prev = sprev;
1059 }
1060
1061 return (sp);
1062 }
1063
1064 /*
1065 * Calculate getty and if useful window argv vectors.
1066 */
1067 int
1068 setupargv(session_t *sp, struct ttyent *typ)
1069 {
1070
1071 if (sp->se_getty) {
1072 free(sp->se_getty);
1073 free(sp->se_getty_argv);
1074 }
1075 (void)asprintf(&sp->se_getty, "%s %s", typ->ty_getty, typ->ty_name);
1076 if (!sp->se_getty)
1077 return (0);
1078 sp->se_getty_argv = construct_argv(sp->se_getty);
1079 if (sp->se_getty_argv == NULL) {
1080 warning("can't parse getty for port %s", sp->se_device);
1081 free(sp->se_getty);
1082 sp->se_getty = NULL;
1083 return (0);
1084 }
1085 if (typ->ty_window) {
1086 if (sp->se_window)
1087 free(sp->se_window);
1088 sp->se_window = strdup(typ->ty_window);
1089 sp->se_window_argv = construct_argv(sp->se_window);
1090 if (sp->se_window_argv == NULL) {
1091 warning("can't parse window for port %s",
1092 sp->se_device);
1093 free(sp->se_window);
1094 sp->se_window = NULL;
1095 return (0);
1096 }
1097 }
1098 return (1);
1099 }
1100
1101 /*
1102 * Walk the list of ttys and create sessions for each active line.
1103 */
1104 state_func_t
1105 read_ttys(void)
1106 {
1107 int session_index = 0;
1108 session_t *sp, *snext;
1109 struct ttyent *typ;
1110
1111 /*
1112 * Destroy any previous session state.
1113 * There shouldn't be any, but just in case...
1114 */
1115 for (sp = sessions; sp; sp = snext) {
1116 #ifndef LETS_GET_SMALL
1117 if (sp->se_process)
1118 clear_session_logs(sp, 0);
1119 #endif
1120 snext = sp->se_next;
1121 free_session(sp);
1122 }
1123 sessions = NULL;
1124
1125 if (start_session_db()) {
1126 warning("read_ttys: start_session_db failed, death\n");
1127 #ifdef CHROOT
1128 /* If /etc/rc ran in chroot, we want to kill any survivors. */
1129 if (did_multiuser_chroot)
1130 return (state_func_t)death;
1131 else
1132 #endif /* CHROOT */
1133 return (state_func_t)single_user;
1134 }
1135
1136 do_setttyent();
1137
1138 /*
1139 * Allocate a session entry for each active port.
1140 * Note that sp starts at 0.
1141 */
1142 while ((typ = getttyent()) != NULL)
1143 if ((snext = new_session(sp, ++session_index, typ)) != NULL)
1144 sp = snext;
1145 endttyent();
1146
1147 return (state_func_t)multi_user;
1148 }
1149
1150 /*
1151 * Start a window system running.
1152 */
1153 void
1154 start_window_system(session_t *sp)
1155 {
1156 pid_t pid;
1157 sigset_t mask;
1158
1159 if ((pid = fork()) == -1) {
1160 emergency("can't fork for window system on port %s: %m",
1161 sp->se_device);
1162 /* hope that getty fails and we can try again */
1163 return;
1164 }
1165
1166 if (pid)
1167 return;
1168
1169 sigemptyset(&mask);
1170 sigprocmask(SIG_SETMASK, &mask, NULL);
1171
1172 if (setsid() < 0)
1173 emergency("setsid failed (window) %m");
1174
1175 (void)execv(sp->se_window_argv[0], sp->se_window_argv);
1176 stall("can't exec window system '%s' for port %s: %m",
1177 sp->se_window_argv[0], sp->se_device);
1178 _exit(1);
1179 }
1180
1181 /*
1182 * Start a login session running.
1183 */
1184 pid_t
1185 start_getty(session_t *sp)
1186 {
1187 pid_t pid;
1188 sigset_t mask;
1189 time_t current_time = time(NULL);
1190
1191 /*
1192 * fork(), not vfork() -- we can't afford to block.
1193 */
1194 if ((pid = fork()) == -1) {
1195 emergency("can't fork for getty on port %s: %m", sp->se_device);
1196 return -1;
1197 }
1198
1199 if (pid)
1200 return pid;
1201
1202 #ifdef CHROOT
1203 /* If /etc/rc did proceed inside chroot, we have to try as well. */
1204 if (did_multiuser_chroot)
1205 if (chroot(rootdir) != 0) {
1206 stall("can't chroot getty '%s' inside %s: %m",
1207 sp->se_getty_argv[0], rootdir);
1208 _exit(1);
1209 }
1210 #endif /* CHROOT */
1211
1212 if (current_time > sp->se_started &&
1213 current_time - sp->se_started < GETTY_SPACING) {
1214 warning("getty repeating too quickly on port %s, sleeping",
1215 sp->se_device);
1216 (void)sleep(GETTY_SLEEP);
1217 }
1218
1219 if (sp->se_window) {
1220 start_window_system(sp);
1221 (void)sleep(WINDOW_WAIT);
1222 }
1223
1224 (void)sigemptyset(&mask);
1225 (void)sigprocmask(SIG_SETMASK, &mask, (sigset_t *) 0);
1226
1227 (void)execv(sp->se_getty_argv[0], sp->se_getty_argv);
1228 stall("can't exec getty '%s' for port %s: %m",
1229 sp->se_getty_argv[0], sp->se_device);
1230 _exit(1);
1231 /*NOTREACHED*/
1232 }
1233 #endif /* LETS_GET_SMALL */
1234
1235 /*
1236 * Collect exit status for a child.
1237 * If an exiting login, start a new login running.
1238 */
1239 void
1240 collect_child(pid_t pid, int status)
1241 {
1242 #ifndef LETS_GET_SMALL
1243 session_t *sp, *sprev, *snext;
1244
1245 if (! sessions)
1246 return;
1247
1248 if ((sp = find_session(pid)) == NULL)
1249 return;
1250
1251 clear_session_logs(sp, status);
1252 del_session(sp);
1253 sp->se_process = 0;
1254
1255 if (sp->se_flags & SE_SHUTDOWN) {
1256 if ((sprev = sp->se_prev) != NULL)
1257 sprev->se_next = sp->se_next;
1258 else
1259 sessions = sp->se_next;
1260 if ((snext = sp->se_next) != NULL)
1261 snext->se_prev = sp->se_prev;
1262 free_session(sp);
1263 return;
1264 }
1265
1266 if ((pid = start_getty(sp)) == -1) {
1267 /* serious trouble */
1268 requested_transition = clean_ttys;
1269 return;
1270 }
1271
1272 sp->se_process = pid;
1273 sp->se_started = time(NULL);
1274 add_session(sp);
1275 #endif /* LETS_GET_SMALL */
1276 }
1277
1278 /*
1279 * Catch a signal and request a state transition.
1280 */
1281 void
1282 transition_handler(int sig)
1283 {
1284
1285 switch (sig) {
1286 #ifndef LETS_GET_SMALL
1287 case SIGHUP:
1288 requested_transition = clean_ttys;
1289 break;
1290 case SIGTERM:
1291 requested_transition = death;
1292 break;
1293 case SIGTSTP:
1294 requested_transition = catatonia;
1295 break;
1296 #endif /* LETS_GET_SMALL */
1297 default:
1298 requested_transition = 0;
1299 break;
1300 }
1301 }
1302
1303 #ifndef LETS_GET_SMALL
1304 /*
1305 * Take the system multiuser.
1306 */
1307 state_func_t
1308 multi_user(void)
1309 {
1310 pid_t pid;
1311 int status;
1312 session_t *sp;
1313
1314 requested_transition = 0;
1315
1316 /*
1317 * If the administrator has not set the security level to -1
1318 * to indicate that the kernel should not run multiuser in secure
1319 * mode, and the run script has not set a higher level of security
1320 * than level 1, then put the kernel into secure mode.
1321 */
1322 if (getsecuritylevel() == 0)
1323 setsecuritylevel(1);
1324
1325 for (sp = sessions; sp; sp = sp->se_next) {
1326 if (sp->se_process)
1327 continue;
1328 if ((pid = start_getty(sp)) == -1) {
1329 /* serious trouble */
1330 requested_transition = clean_ttys;
1331 break;
1332 }
1333 sp->se_process = pid;
1334 sp->se_started = time(NULL);
1335 add_session(sp);
1336 }
1337
1338 while (!requested_transition)
1339 if ((pid = waitpid(-1, &status, 0)) != -1)
1340 collect_child(pid, status);
1341
1342 return (state_func_t)requested_transition;
1343 }
1344
1345 /*
1346 * This is an n-squared algorithm. We hope it isn't run often...
1347 */
1348 state_func_t
1349 clean_ttys(void)
1350 {
1351 session_t *sp, *sprev;
1352 struct ttyent *typ;
1353 int session_index = 0;
1354 int devlen;
1355
1356 for (sp = sessions; sp; sp = sp->se_next)
1357 sp->se_flags &= ~SE_PRESENT;
1358
1359 do_setttyent();
1360
1361 devlen = sizeof(_PATH_DEV) - 1;
1362 while ((typ = getttyent()) != NULL) {
1363 ++session_index;
1364
1365 for (sprev = 0, sp = sessions; sp; sprev = sp, sp = sp->se_next)
1366 if (strcmp(typ->ty_name, sp->se_device + devlen) == 0)
1367 break;
1368
1369 if (sp) {
1370 sp->se_flags |= SE_PRESENT;
1371 if (sp->se_index != session_index) {
1372 warning("port %s changed utmp index from "
1373 "%d to %d", sp->se_device, sp->se_index,
1374 session_index);
1375 sp->se_index = session_index;
1376 }
1377 if ((typ->ty_status & TTY_ON) == 0 ||
1378 typ->ty_getty == 0) {
1379 sp->se_flags |= SE_SHUTDOWN;
1380 if (sp->se_process != 0)
1381 (void)kill(sp->se_process, SIGHUP);
1382 continue;
1383 }
1384 sp->se_flags &= ~SE_SHUTDOWN;
1385 if (setupargv(sp, typ) == 0) {
1386 warning("can't parse getty for port %s",
1387 sp->se_device);
1388 sp->se_flags |= SE_SHUTDOWN;
1389 if (sp->se_process != 0)
1390 (void)kill(sp->se_process, SIGHUP);
1391 }
1392 continue;
1393 }
1394
1395 new_session(sprev, session_index, typ);
1396 }
1397
1398 endttyent();
1399
1400 for (sp = sessions; sp; sp = sp->se_next)
1401 if ((sp->se_flags & SE_PRESENT) == 0) {
1402 sp->se_flags |= SE_SHUTDOWN;
1403 if (sp->se_process != 0)
1404 (void)kill(sp->se_process, SIGHUP);
1405 }
1406
1407 return (state_func_t)multi_user;
1408 }
1409
1410 /*
1411 * Block further logins.
1412 */
1413 state_func_t
1414 catatonia(void)
1415 {
1416 session_t *sp;
1417
1418 for (sp = sessions; sp; sp = sp->se_next)
1419 sp->se_flags |= SE_SHUTDOWN;
1420
1421 return (state_func_t)multi_user;
1422 }
1423 #endif /* LETS_GET_SMALL */
1424
1425 /*
1426 * Note SIGALRM.
1427 */
1428 void
1429 /*ARGSUSED*/
1430 alrm_handler(int sig)
1431 {
1432
1433 clang = 1;
1434 }
1435
1436 #ifndef LETS_GET_SMALL
1437 /*
1438 * Bring the system down to single user.
1439 */
1440 state_func_t
1441 death(void)
1442 {
1443 session_t *sp;
1444 int i, status;
1445 pid_t pid;
1446 static const int death_sigs[3] = { SIGHUP, SIGTERM, SIGKILL };
1447
1448 for (sp = sessions; sp; sp = sp->se_next)
1449 sp->se_flags |= SE_SHUTDOWN;
1450
1451 /* NB: should send a message to the session logger to avoid blocking. */
1452 #ifdef SUPPORT_UTMPX
1453 logwtmpx("~", "shutdown", "", 0, INIT_PROCESS);
1454 #endif
1455 #ifdef SUPPORT_UTMP
1456 logwtmp("~", "shutdown", "");
1457 #endif
1458
1459 for (i = 0; i < 3; ++i) {
1460 if (kill(-1, death_sigs[i]) == -1 && errno == ESRCH)
1461 return (state_func_t)single_user;
1462
1463 clang = 0;
1464 alarm(DEATH_WATCH);
1465 do
1466 if ((pid = waitpid(-1, &status, 0)) != -1)
1467 collect_child(pid, status);
1468 while (clang == 0 && errno != ECHILD);
1469
1470 if (errno == ECHILD)
1471 return (state_func_t)single_user;
1472 }
1473
1474 warning("some processes would not die; ps axl advised");
1475
1476 return (state_func_t)single_user;
1477 }
1478 #endif /* LETS_GET_SMALL */
1479
1480 #ifdef MFS_DEV_IF_NO_CONSOLE
1481
1482 static void
1483 mapfile(struct mappedfile *mf)
1484 {
1485 int fd;
1486 struct stat st;
1487
1488 if (lstat(mf->path, &st) == -1)
1489 return;
1490
1491 if ((st.st_mode & S_IFMT) == S_IFLNK) {
1492 mf->buf = malloc(st.st_size + 1);
1493 if (mf->buf == NULL)
1494 return;
1495 mf->buf[st.st_size] = 0;
1496 if (readlink(mf->path, mf->buf, st.st_size) != st.st_size)
1497 return;
1498 mf->len = -1;
1499 return;
1500 }
1501
1502 if ((fd = open(mf->path, O_RDONLY)) == -1)
1503 return;
1504 mf->buf = mmap(0, (size_t)st.st_size, PROT_READ,
1505 MAP_FILE|MAP_SHARED, fd, (off_t)0);
1506 (void)close(fd);
1507 if (mf->buf == MAP_FAILED)
1508 return;
1509 mf->len = st.st_size;
1510 }
1511
1512 static void
1513 writefile(struct mappedfile *mf)
1514 {
1515 int fd;
1516
1517 if (mf->len == -1) {
1518 symlink(mf->buf, mf->path);
1519 free(mf->buf);
1520 return;
1521 }
1522
1523 if (mf->len == 0)
1524 return;
1525 fd = open(mf->path, O_WRONLY | O_CREAT | O_TRUNC, 0755);
1526 if (fd == -1)
1527 return;
1528 (void)write(fd, mf->buf, mf->len);
1529 (void)munmap(mf->buf, mf->len);
1530 (void)close(fd);
1531 }
1532
1533 static int
1534 mfs_dev(void)
1535 {
1536 /*
1537 * We cannot print errors so we bail out silently...
1538 */
1539 pid_t pid;
1540 int status;
1541 dev_t dev;
1542 char *fs_size;
1543 #ifdef CPU_CONSDEV
1544 static int name[2] = { CTL_MACHDEP, CPU_CONSDEV };
1545 size_t olen;
1546 #endif
1547
1548 /* If we have /dev/console, assume all is OK */
1549 if (access(_PATH_CONSOLE, F_OK) != -1)
1550 return(0);
1551
1552 /* Grab the contents of MAKEDEV */
1553 mapfile(&mfile[0]);
1554
1555 /* Grab the contents of MAKEDEV.local */
1556 mapfile(&mfile[1]);
1557
1558 /* Mount an mfs over /dev so we can create devices */
1559 switch ((pid = fork())) {
1560 case 0:
1561 asprintf(&fs_size, "%d", FSSIZE);
1562 if (fs_size == NULL)
1563 return(-1);
1564 (void)execl(INIT_MOUNT_MFS, "mount_mfs",
1565 "-b", "4096", "-f", "512",
1566 "-s", fs_size, "-n", STR(NINODE),
1567 "-p", "0755",
1568 "swap", "/dev", NULL);
1569 _exit(1);
1570 /*NOTREACHED*/
1571
1572 case -1:
1573 return(-1);
1574
1575 default:
1576 if (waitpid(pid, &status, 0) == -1)
1577 return(-1);
1578 if (status != 0)
1579 return(-1);
1580 break;
1581 }
1582
1583 #ifdef CPU_CONSDEV
1584 olen = sizeof(dev);
1585 if (sysctl(name, sizeof(name) / sizeof(name[0]), &dev, &olen,
1586 NULL, 0) == -1)
1587 #endif
1588 dev = makedev(0, 0);
1589
1590 /* Make a console for us, so we can see things happening */
1591 if (mknod(_PATH_CONSOLE, 0666 | S_IFCHR, dev) == -1)
1592 return(-1);
1593
1594 (void)freopen(_PATH_CONSOLE, "a", stderr);
1595
1596 warnx("Creating mfs /dev (%d blocks, %d inodes)", FSSIZE, NINODE);
1597
1598 /* Create a MAKEDEV script in the mfs /dev */
1599 writefile(&mfile[0]);
1600
1601 /* Create a MAKEDEV.local script in the mfs /dev */
1602 writefile(&mfile[1]);
1603
1604 /* Run the makedev script to create devices */
1605 switch ((pid = fork())) {
1606 case 0:
1607 dup2(2, 1); /* Give the script stdout */
1608 if (chdir("/dev") == 0)
1609 (void)execl(INIT_BSHELL, "sh",
1610 mfile[0].len ? "./MAKEDEV" : "/etc/MAKEDEV",
1611 "init", NULL);
1612 _exit(1);
1613 /* NOTREACHED */
1614
1615 case -1:
1616 break;
1617
1618 default:
1619 if (waitpid(pid, &status, 0) == -1)
1620 break;
1621 if (status != 0) {
1622 errno = EINVAL;
1623 break;
1624 }
1625 return 0;
1626 }
1627 warn("Unable to run MAKEDEV");
1628 return (-1);
1629 }
1630 #endif
1631
1632 int
1633 do_setttyent(void)
1634 {
1635 endttyent();
1636 #ifdef CHROOT
1637 if (did_multiuser_chroot) {
1638 char path[PATH_MAX];
1639
1640 snprintf(path, sizeof(path), "%s/%s", rootdir, _PATH_TTYS);
1641
1642 return setttyentpath(path);
1643 } else
1644 #endif /* CHROOT */
1645 return setttyent();
1646 }
1647
1648 #if !defined(LETS_GET_SMALL) && defined(CHROOT)
1649
1650 int
1651 createsysctlnode()
1652 {
1653 struct sysctlnode node;
1654 int mib[2];
1655 size_t len;
1656
1657 /*
1658 * Create top-level dynamic sysctl node. Its child nodes will only
1659 * be readable by the superuser, since regular mortals should not
1660 * care ("Sssh, it's a secret!"). Additionally, both nodes become
1661 * read-only at securelevel 1.
1662 */
1663 len = sizeof(struct sysctlnode);
1664 mib[0] = CTL_CREATE;
1665
1666 memset(&node, 0, len);
1667 node.sysctl_flags = SYSCTL_VERSION | CTLFLAG_READWRITE |
1668 CTLFLAG_PRIVATE | CTLTYPE_NODE;
1669 node.sysctl_num = CTL_CREATE;
1670 snprintf(node.sysctl_name, SYSCTL_NAMELEN, "init");
1671 if (sysctl(&mib[0], 1, &node, &len, &node, len) == -1) {
1672 warning("could not create init node, error = %d", errno);
1673 return (-1);
1674 }
1675
1676 /*
1677 * Create second level dynamic node capable of holding pathname.
1678 * Provide "/" as the default value.
1679 */
1680 len = sizeof(struct sysctlnode);
1681 mib[0] = node.sysctl_num;
1682 mib[1] = CTL_CREATE;
1683
1684 memset(&node, 0, len);
1685 node.sysctl_flags = SYSCTL_VERSION | CTLFLAG_READWRITE |
1686 CTLTYPE_STRING | CTLFLAG_OWNDATA;
1687 node.sysctl_size = _POSIX_PATH_MAX;
1688 node.sysctl_data = __UNCONST("/");
1689 node.sysctl_num = CTL_CREATE;
1690 snprintf(node.sysctl_name, SYSCTL_NAMELEN, "root");
1691 if (sysctl(&mib[0], 2, NULL, NULL, &node, len) == -1) {
1692 warning("could not create init.root node, error = %d", errno);
1693 return (-1);
1694 }
1695
1696 return (0);
1697 }
1698
1699 int
1700 shouldchroot()
1701 {
1702 struct sysctlnode node;
1703 size_t len, cnt;
1704 int mib;
1705
1706 len = sizeof(struct sysctlnode);
1707
1708 if (sysctlbyname("init.root", rootdir, &len, NULL, 0) == -1) {
1709 warning("could not read init.root, error = %d", errno);
1710
1711 /* Child killed our node. Recreate it. */
1712 if (errno == ENOENT) {
1713 /* Destroy whatever is left, recreate from scratch. */
1714 if (sysctlnametomib("init", &mib, &cnt) != -1) {
1715 memset(&node, 0, sizeof(node));
1716 node.sysctl_flags = SYSCTL_VERSION;
1717 node.sysctl_num = mib;
1718 mib = CTL_DESTROY;
1719
1720 (void)sysctl(&mib, 1, NULL, NULL, &node,
1721 sizeof(node));
1722 }
1723
1724 createsysctlnode();
1725 }
1726
1727 /* We certainly won't chroot. */
1728 return (0);
1729 }
1730
1731 if (rootdir[len] != '\0' || strlen(rootdir) != len - 1) {
1732 warning("init.root is not a string");
1733 return (0);
1734 }
1735
1736 if (strcmp(rootdir, "/") == 0)
1737 return (0);
1738
1739 return (1);
1740 }
1741
1742 #endif /* !LETS_GET_SMALL && CHROOT */
1743