1 /* $NetBSD: init.c,v 1.73 2006/04/18 11:40:26 salo 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.73 2006/04/18 11:40:26 salo 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@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 | CTLFLAG_READONLY1 | 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 CTLFLAG_READONLY1 | 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