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