1 /* $NetBSD: init.c,v 1.56 2003/05/26 09:34:55 lukem 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. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the University of 21 * California, Berkeley and its contributors. 22 * 4. Neither the name of the University nor the names of its contributors 23 * may be used to endorse or promote products derived from this software 24 * without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * SUCH DAMAGE. 37 */ 38 39 #include <sys/cdefs.h> 40 #ifndef lint 41 __COPYRIGHT("@(#) Copyright (c) 1991, 1993\n" 42 " The Regents of the University of California. All rights reserved.\n"); 43 #endif /* not lint */ 44 45 #ifndef lint 46 #if 0 47 static char sccsid[] = "@(#)init.c 8.2 (Berkeley) 4/28/95"; 48 #else 49 __RCSID("$NetBSD: init.c,v 1.56 2003/05/26 09:34:55 lukem Exp $"); 50 #endif 51 #endif /* not lint */ 52 53 #include <sys/param.h> 54 #include <sys/sysctl.h> 55 #include <sys/wait.h> 56 #include <sys/mman.h> 57 #include <sys/stat.h> 58 #include <sys/mount.h> 59 #ifdef DEBUG 60 #include <sys/sysctl.h> 61 #include <machine/cpu.h> 62 #endif 63 64 #include <db.h> 65 #include <errno.h> 66 #include <fcntl.h> 67 #include <signal.h> 68 #include <stdio.h> 69 #include <stdlib.h> 70 #include <string.h> 71 #include <syslog.h> 72 #include <time.h> 73 #include <ttyent.h> 74 #include <unistd.h> 75 #include <util.h> 76 #include <paths.h> 77 #include <err.h> 78 79 #include <stdarg.h> 80 81 #ifdef SECURE 82 #include <pwd.h> 83 #endif 84 85 #include "pathnames.h" 86 87 /* 88 * Sleep times; used to prevent thrashing. 89 */ 90 #define GETTY_SPACING 5 /* N secs minimum getty spacing */ 91 #define GETTY_SLEEP 30 /* sleep N secs after spacing problem */ 92 #define WINDOW_WAIT 3 /* wait N secs after starting window */ 93 #define STALL_TIMEOUT 30 /* wait N secs after warning */ 94 #define DEATH_WATCH 10 /* wait N secs for procs to die */ 95 96 97 #if defined(RESCUEDIR) 98 #define INIT_BSHELL RESCUEDIR "/sh" 99 #define INIT_MOUNT_MFS RESCUEDIR "/mount_mfs" 100 #define INIT_PATH RESCUEDIR ":" _PATH_STDPATH 101 #else 102 #define INIT_BSHELL _PATH_BSHELL 103 #define INIT_MOUNT_MFS "/sbin/mount_mfs" 104 #define INIT_PATH _PATH_STDPATH 105 #endif 106 107 int main(int, char *[]); 108 109 void handle(sig_t, ...); 110 void delset(sigset_t *, ...); 111 112 void stall(const char *, ...) 113 __attribute__((__format__(__printf__,1,2))); 114 void warning(const char *, ...) 115 __attribute__((__format__(__printf__,1,2))); 116 void emergency(const char *, ...) 117 __attribute__((__format__(__printf__,1,2))); 118 void disaster(int); 119 void badsys(int); 120 121 /* 122 * We really need a recursive typedef... 123 * The following at least guarantees that the return type of (*state_t)() 124 * is sufficiently wide to hold a function pointer. 125 */ 126 typedef long (*state_func_t)(void); 127 typedef state_func_t (*state_t)(void); 128 129 state_func_t single_user(void); 130 state_func_t runcom(void); 131 state_func_t read_ttys(void); 132 state_func_t multi_user(void); 133 state_func_t clean_ttys(void); 134 state_func_t catatonia(void); 135 state_func_t death(void); 136 137 enum { AUTOBOOT, FASTBOOT } runcom_mode = AUTOBOOT; 138 139 void transition(state_t); 140 #ifndef LETS_GET_SMALL 141 state_t requested_transition = runcom; 142 #else /* LETS_GET_SMALL */ 143 state_t requested_transition = single_user; 144 #endif /* LETS_GET_SMALL */ 145 146 void setctty(const char *); 147 148 typedef struct init_session { 149 int se_index; /* index of entry in ttys file */ 150 pid_t se_process; /* controlling process */ 151 time_t se_started; /* used to avoid thrashing */ 152 int se_flags; /* status of session */ 153 #define SE_SHUTDOWN 0x1 /* session won't be restarted */ 154 #define SE_PRESENT 0x2 /* session is in /etc/ttys */ 155 char *se_device; /* filename of port */ 156 char *se_getty; /* what to run on that port */ 157 char **se_getty_argv; /* pre-parsed argument array */ 158 char *se_window; /* window system (started only once) */ 159 char **se_window_argv; /* pre-parsed argument array */ 160 struct init_session *se_prev; 161 struct init_session *se_next; 162 } session_t; 163 164 void free_session(session_t *); 165 session_t *new_session(session_t *, int, struct ttyent *); 166 session_t *sessions; 167 168 char **construct_argv(char *); 169 void start_window_system(session_t *); 170 void collect_child(pid_t, int); 171 pid_t start_getty(session_t *); 172 void transition_handler(int); 173 void alrm_handler(int); 174 void setsecuritylevel(int); 175 int getsecuritylevel(void); 176 int setupargv(session_t *, struct ttyent *); 177 int clang; 178 179 void clear_session_logs(session_t *, int); 180 181 int start_session_db(void); 182 void add_session(session_t *); 183 void del_session(session_t *); 184 session_t *find_session(pid_t); 185 DB *session_db; 186 187 #ifdef MFS_DEV_IF_NO_CONSOLE 188 static int mfs_dev(void); 189 #endif 190 191 /* 192 * The mother of all processes. 193 */ 194 int 195 main(int argc, char **argv) 196 { 197 struct sigaction sa; 198 sigset_t mask; 199 #ifndef LETS_GET_SMALL 200 int c; 201 202 /* Dispose of random users. */ 203 if (getuid() != 0) { 204 errno = EPERM; 205 err(1, NULL); 206 } 207 208 /* System V users like to reexec init. */ 209 if (getpid() != 1) 210 errx(1, "already running"); 211 #endif 212 213 /* 214 * Create an initial session. 215 */ 216 if (setsid() < 0) 217 warn("initial setsid() failed"); 218 219 /* 220 * Establish an initial user so that programs running 221 * single user do not freak out and die (like passwd). 222 */ 223 if (setlogin("root") < 0) 224 warn("setlogin() failed"); 225 226 227 #ifdef MFS_DEV_IF_NO_CONSOLE 228 if (mfs_dev() == -1) 229 requested_transition = single_user; 230 #endif 231 232 #ifndef LETS_GET_SMALL 233 /* 234 * Note that this does NOT open a file... 235 * Does 'init' deserve its own facility number? 236 */ 237 openlog("init", LOG_CONS, LOG_AUTH); 238 #endif /* LETS_GET_SMALL */ 239 240 241 #ifndef LETS_GET_SMALL 242 /* 243 * This code assumes that we always get arguments through flags, 244 * never through bits set in some random machine register. 245 */ 246 while ((c = getopt(argc, argv, "sf")) != -1) 247 switch (c) { 248 case 's': 249 requested_transition = single_user; 250 break; 251 case 'f': 252 runcom_mode = FASTBOOT; 253 break; 254 default: 255 warning("unrecognized flag '-%c'", c); 256 break; 257 } 258 259 if (optind != argc) 260 warning("ignoring excess arguments"); 261 #else /* LETS_GET_SMALL */ 262 requested_transition = single_user; 263 #endif /* LETS_GET_SMALL */ 264 265 /* 266 * We catch or block signals rather than ignore them, 267 * so that they get reset on exec. 268 */ 269 handle(badsys, SIGSYS, 0); 270 handle(disaster, SIGABRT, SIGFPE, SIGILL, SIGSEGV, 271 SIGBUS, SIGXCPU, SIGXFSZ, 0); 272 handle(transition_handler, SIGHUP, SIGTERM, SIGTSTP, 0); 273 handle(alrm_handler, SIGALRM, 0); 274 (void)sigfillset(&mask); 275 delset(&mask, SIGABRT, SIGFPE, SIGILL, SIGSEGV, SIGBUS, SIGSYS, 276 SIGXCPU, SIGXFSZ, SIGHUP, SIGTERM, SIGTSTP, SIGALRM, 0); 277 (void)sigprocmask(SIG_SETMASK, &mask, NULL); 278 (void)sigemptyset(&sa.sa_mask); 279 sa.sa_flags = 0; 280 sa.sa_handler = SIG_IGN; 281 (void)sigaction(SIGTTIN, &sa, NULL); 282 (void)sigaction(SIGTTOU, &sa, NULL); 283 284 /* 285 * Paranoia. 286 */ 287 (void)close(0); 288 (void)close(1); 289 (void)close(2); 290 291 /* 292 * Start the state machine. 293 */ 294 transition(requested_transition); 295 296 /* 297 * Should never reach here. 298 */ 299 return 1; 300 } 301 302 /* 303 * Associate a function with a signal handler. 304 */ 305 void 306 handle(sig_t handler, ...) 307 { 308 int sig; 309 struct sigaction sa; 310 sigset_t mask_everything; 311 va_list ap; 312 313 va_start(ap, handler); 314 315 sa.sa_handler = handler; 316 (void)sigfillset(&mask_everything); 317 318 while ((sig = va_arg(ap, int)) != 0) { 319 sa.sa_mask = mask_everything; 320 /* XXX SA_RESTART? */ 321 sa.sa_flags = sig == SIGCHLD ? SA_NOCLDSTOP : 0; 322 (void)sigaction(sig, &sa, NULL); 323 } 324 va_end(ap); 325 } 326 327 /* 328 * Delete a set of signals from a mask. 329 */ 330 void 331 delset(sigset_t *maskp, ...) 332 { 333 int sig; 334 va_list ap; 335 336 va_start(ap, maskp); 337 338 while ((sig = va_arg(ap, int)) != 0) 339 (void)sigdelset(maskp, sig); 340 va_end(ap); 341 } 342 343 /* 344 * Log a message and sleep for a while (to give someone an opportunity 345 * to read it and to save log or hardcopy output if the problem is chronic). 346 * NB: should send a message to the session logger to avoid blocking. 347 */ 348 void 349 stall(const char *message, ...) 350 { 351 va_list ap; 352 353 va_start(ap, message); 354 vsyslog(LOG_ALERT, message, ap); 355 va_end(ap); 356 closelog(); 357 (void)sleep(STALL_TIMEOUT); 358 } 359 360 /* 361 * Like stall(), but doesn't sleep. 362 * If cpp had variadic macros, the two functions could be #defines for another. 363 * NB: should send a message to the session logger to avoid blocking. 364 */ 365 void 366 warning(const char *message, ...) 367 { 368 va_list ap; 369 370 va_start(ap, message); 371 vsyslog(LOG_ALERT, message, ap); 372 va_end(ap); 373 closelog(); 374 } 375 376 /* 377 * Log an emergency message. 378 * NB: should send a message to the session logger to avoid blocking. 379 */ 380 void 381 emergency(const char *message, ...) 382 { 383 va_list ap; 384 385 va_start(ap, message); 386 vsyslog(LOG_EMERG, message, ap); 387 va_end(ap); 388 closelog(); 389 } 390 391 /* 392 * Catch a SIGSYS signal. 393 * 394 * These may arise if a system does not support sysctl. 395 * We tolerate up to 25 of these, then throw in the towel. 396 */ 397 void 398 badsys(int sig) 399 { 400 static int badcount = 0; 401 402 if (badcount++ < 25) 403 return; 404 disaster(sig); 405 } 406 407 /* 408 * Catch an unexpected signal. 409 */ 410 void 411 disaster(int sig) 412 { 413 414 emergency("fatal signal: %s", strsignal(sig)); 415 (void)sleep(STALL_TIMEOUT); 416 _exit(sig); /* reboot */ 417 } 418 419 /* 420 * Get the security level of the kernel. 421 */ 422 int 423 getsecuritylevel(void) 424 { 425 #ifdef KERN_SECURELVL 426 int name[2], curlevel; 427 size_t len; 428 429 name[0] = CTL_KERN; 430 name[1] = KERN_SECURELVL; 431 len = sizeof curlevel; 432 if (sysctl(name, 2, &curlevel, &len, NULL, 0) == -1) { 433 emergency("cannot get kernel security level: %m"); 434 return (-1); 435 } 436 return (curlevel); 437 #else 438 return (-1); 439 #endif 440 } 441 442 /* 443 * Set the security level of the kernel. 444 */ 445 void 446 setsecuritylevel(int newlevel) 447 { 448 #ifdef KERN_SECURELVL 449 int name[2], curlevel; 450 451 curlevel = getsecuritylevel(); 452 if (newlevel == curlevel) 453 return; 454 name[0] = CTL_KERN; 455 name[1] = KERN_SECURELVL; 456 if (sysctl(name, 2, NULL, NULL, &newlevel, sizeof newlevel) == -1) { 457 emergency( "cannot change kernel security level from" 458 " %d to %d: %m", curlevel, newlevel); 459 return; 460 } 461 #ifdef SECURE 462 warning("kernel security level changed from %d to %d", 463 curlevel, newlevel); 464 #endif 465 #endif 466 } 467 468 /* 469 * Change states in the finite state machine. 470 * The initial state is passed as an argument. 471 */ 472 void 473 transition(state_t s) 474 { 475 476 if (s == NULL) 477 return; 478 for (;;) 479 s = (state_t)(*s)(); 480 } 481 482 /* 483 * Close out the accounting files for a login session. 484 * NB: should send a message to the session logger to avoid blocking. 485 */ 486 void 487 clear_session_logs(session_t *sp, int status) 488 { 489 char *line = sp->se_device + sizeof(_PATH_DEV) - 1; 490 491 #ifdef SUPPORT_UTMPX 492 if (logoutx(line, status, DEAD_PROCESS)) 493 logwtmpx(line, "", "", status, DEAD_PROCESS); 494 #endif 495 #ifdef SUPPORT_UTMP 496 if (logout(line)) 497 logwtmp(line, "", ""); 498 #endif 499 } 500 501 /* 502 * Start a session and allocate a controlling terminal. 503 * Only called by children of init after forking. 504 */ 505 void 506 setctty(const char *name) 507 { 508 int fd; 509 510 (void) revoke(name); 511 sleep(2); /* leave DTR low */ 512 if ((fd = open(name, O_RDWR)) == -1) { 513 stall("can't open %s: %m", name); 514 _exit(1); 515 } 516 if (login_tty(fd) == -1) { 517 stall("can't get %s for controlling terminal: %m", name); 518 _exit(1); 519 } 520 } 521 522 /* 523 * Bring the system up single user. 524 */ 525 state_func_t 526 single_user(void) 527 { 528 pid_t pid, wpid; 529 int status; 530 int from_securitylevel; 531 sigset_t mask; 532 struct sigaction sa, satstp, sahup; 533 #ifdef ALTSHELL 534 const char *shell = INIT_BSHELL; 535 #endif 536 char *argv[2]; 537 #ifdef SECURE 538 struct ttyent *typ; 539 struct passwd *pp; 540 char *clear, *password; 541 #endif 542 #ifdef ALTSHELL 543 char altshell[128]; 544 #endif /* ALTSHELL */ 545 546 /* 547 * If the kernel is in secure mode, downgrade it to insecure mode. 548 */ 549 from_securitylevel = getsecuritylevel(); 550 if (from_securitylevel > 0) 551 setsecuritylevel(0); 552 553 (void)sigemptyset(&sa.sa_mask); 554 sa.sa_flags = 0; 555 sa.sa_handler = SIG_IGN; 556 (void)sigaction(SIGTSTP, &sa, &satstp); 557 (void)sigaction(SIGHUP, &sa, &sahup); 558 if ((pid = fork()) == 0) { 559 /* 560 * Start the single user session. 561 */ 562 setctty(_PATH_CONSOLE); 563 564 #ifdef SECURE 565 /* 566 * Check the root password. 567 * We don't care if the console is 'on' by default; 568 * it's the only tty that can be 'off' and 'secure'. 569 */ 570 typ = getttynam("console"); 571 pp = getpwnam("root"); 572 if (typ && (from_securitylevel >=2 || (typ->ty_status 573 & TTY_SECURE) == 0) && pp && *pp->pw_passwd != '\0') { 574 (void)fprintf(stderr, 575 "Enter root password, or ^D to go multi-user\n"); 576 for (;;) { 577 clear = getpass("Password:"); 578 if (clear == 0 || *clear == '\0') 579 _exit(0); 580 password = crypt(clear, pp->pw_passwd); 581 (void)memset(clear, 0, _PASSWORD_LEN); 582 if (strcmp(password, pp->pw_passwd) == 0) 583 break; 584 warning("single-user login failed\n"); 585 } 586 } 587 endttyent(); 588 endpwent(); 589 #endif /* SECURE */ 590 591 #ifdef ALTSHELL 592 (void)fprintf(stderr, 593 "Enter pathname of shell or RETURN for %s: ", shell); 594 if (fgets(altshell, sizeof(altshell), stdin) == NULL) { 595 altshell[0] = '\0'; 596 } else { 597 /* nuke \n */ 598 char *p; 599 600 if ((p = strchr(altshell, '\n')) != NULL) 601 *p = '\0'; 602 } 603 604 if (altshell[0]) 605 shell = altshell; 606 #endif /* ALTSHELL */ 607 608 /* 609 * Unblock signals. 610 * We catch all the interesting ones, 611 * and those are reset to SIG_DFL on exec. 612 */ 613 (void)sigemptyset(&mask); 614 (void)sigprocmask(SIG_SETMASK, &mask, NULL); 615 616 /* 617 * Fire off a shell. 618 * If the default one doesn't work, try the Bourne shell. 619 */ 620 argv[0] = "-sh"; 621 argv[1] = 0; 622 setenv("PATH", INIT_PATH, 1); 623 #ifdef ALTSHELL 624 if (altshell[0]) 625 argv[0] = altshell; 626 (void)execv(shell, argv); 627 emergency("can't exec %s for single user: %m", shell); 628 argv[0] = "-sh"; 629 #endif /* ALTSHELL */ 630 (void)execv(INIT_BSHELL, argv); 631 emergency("can't exec %s for single user: %m", INIT_BSHELL); 632 (void)sleep(STALL_TIMEOUT); 633 _exit(1); 634 } 635 636 if (pid == -1) { 637 /* 638 * We are seriously hosed. Do our best. 639 */ 640 emergency("can't fork single-user shell, trying again"); 641 while (waitpid(-1, NULL, WNOHANG) > 0) 642 continue; 643 (void)sigaction(SIGTSTP, &satstp, NULL); 644 (void)sigaction(SIGHUP, &sahup, NULL); 645 return (state_func_t) single_user; 646 } 647 648 requested_transition = 0; 649 do { 650 if ((wpid = waitpid(-1, &status, WUNTRACED)) != -1) 651 collect_child(wpid, status); 652 if (wpid == -1) { 653 if (errno == EINTR) 654 continue; 655 warning("wait for single-user shell failed: %m; " 656 "restarting"); 657 return (state_func_t)single_user; 658 } 659 if (wpid == pid && WIFSTOPPED(status)) { 660 warning("init: shell stopped, restarting\n"); 661 kill(pid, SIGCONT); 662 wpid = -1; 663 } 664 } while (wpid != pid && !requested_transition); 665 666 if (requested_transition) { 667 (void)sigaction(SIGTSTP, &satstp, NULL); 668 (void)sigaction(SIGHUP, &sahup, NULL); 669 return (state_func_t)requested_transition; 670 } 671 672 if (WIFSIGNALED(status)) { 673 if (WTERMSIG(status) == SIGKILL) { 674 /* executed /sbin/reboot; wait for the end quietly */ 675 sigset_t s; 676 677 (void)sigfillset(&s); 678 for (;;) 679 (void)sigsuspend(&s); 680 } else { 681 warning("single user shell terminated, restarting"); 682 (void)sigaction(SIGTSTP, &satstp, NULL); 683 (void)sigaction(SIGHUP, &sahup, NULL); 684 return (state_func_t) single_user; 685 } 686 } 687 688 runcom_mode = FASTBOOT; 689 (void)sigaction(SIGTSTP, &satstp, NULL); 690 (void)sigaction(SIGHUP, &sahup, NULL); 691 #ifndef LETS_GET_SMALL 692 return (state_func_t) runcom; 693 #else /* LETS_GET_SMALL */ 694 return (state_func_t) single_user; 695 #endif /* LETS_GET_SMALL */ 696 } 697 698 #ifndef LETS_GET_SMALL 699 /* 700 * Run the system startup script. 701 */ 702 state_func_t 703 runcom(void) 704 { 705 pid_t pid, wpid; 706 int status; 707 char *argv[4]; 708 struct sigaction sa; 709 710 switch ((pid = fork())) { 711 case 0: 712 (void)sigemptyset(&sa.sa_mask); 713 sa.sa_flags = 0; 714 sa.sa_handler = SIG_IGN; 715 (void)sigaction(SIGTSTP, &sa, NULL); 716 (void)sigaction(SIGHUP, &sa, NULL); 717 718 setctty(_PATH_CONSOLE); 719 720 argv[0] = "sh"; 721 argv[1] = _PATH_RUNCOM; 722 argv[2] = runcom_mode == AUTOBOOT ? "autoboot" : 0; 723 argv[3] = 0; 724 725 (void)sigprocmask(SIG_SETMASK, &sa.sa_mask, NULL); 726 727 (void)execv(INIT_BSHELL, argv); 728 stall("can't exec %s for %s: %m", INIT_BSHELL, _PATH_RUNCOM); 729 _exit(1); /* force single user mode */ 730 /*NOTREACHED*/ 731 case -1: 732 emergency("can't fork for %s on %s: %m", INIT_BSHELL, 733 _PATH_RUNCOM); 734 while (waitpid(-1, NULL, WNOHANG) > 0) 735 continue; 736 (void)sleep(STALL_TIMEOUT); 737 return (state_func_t)single_user; 738 default: 739 break; 740 } 741 742 /* 743 * Copied from single_user(). This is a bit paranoid. 744 */ 745 do { 746 if ((wpid = waitpid(-1, &status, WUNTRACED)) != -1) 747 collect_child(wpid, status); 748 if (wpid == -1) { 749 if (errno == EINTR) 750 continue; 751 warning("wait for %s on %s failed: %m; going to " 752 "single user mode", INIT_BSHELL, _PATH_RUNCOM); 753 return (state_func_t)single_user; 754 } 755 if (wpid == pid && WIFSTOPPED(status)) { 756 warning("init: %s on %s stopped, restarting\n", 757 INIT_BSHELL, _PATH_RUNCOM); 758 (void)kill(pid, SIGCONT); 759 wpid = -1; 760 } 761 } while (wpid != pid); 762 763 if (WIFSIGNALED(status) && WTERMSIG(status) == SIGTERM && 764 requested_transition == catatonia) { 765 /* /etc/rc executed /sbin/reboot; wait for the end quietly */ 766 sigset_t s; 767 768 (void)sigfillset(&s); 769 for (;;) 770 (void)sigsuspend(&s); 771 } 772 773 if (!WIFEXITED(status)) { 774 warning("%s on %s terminated abnormally, going to " 775 "single user mode", INIT_BSHELL, _PATH_RUNCOM); 776 return (state_func_t)single_user; 777 } 778 779 if (WEXITSTATUS(status)) 780 return (state_func_t)single_user; 781 782 runcom_mode = AUTOBOOT; /* the default */ 783 /* NB: should send a message to the session logger to avoid blocking. */ 784 #ifdef SUPPORT_UTMPX 785 logwtmpx("~", "reboot", "", 0, INIT_PROCESS); 786 #endif 787 #ifdef SUPPORT_UTMP 788 logwtmp("~", "reboot", ""); 789 #endif 790 return (state_func_t) read_ttys; 791 } 792 793 /* 794 * Open the session database. 795 * 796 * NB: We could pass in the size here; is it necessary? 797 */ 798 int 799 start_session_db(void) 800 { 801 802 if (session_db && (*session_db->close)(session_db)) 803 emergency("session database close: %m"); 804 if ((session_db = dbopen(NULL, O_RDWR, 0, DB_HASH, NULL)) == 0) { 805 emergency("session database open: %m"); 806 return (1); 807 } 808 return (0); 809 810 } 811 812 /* 813 * Add a new login session. 814 */ 815 void 816 add_session(session_t *sp) 817 { 818 DBT key; 819 DBT data; 820 821 if (session_db == NULL) 822 return; 823 824 key.data = &sp->se_process; 825 key.size = sizeof sp->se_process; 826 data.data = &sp; 827 data.size = sizeof sp; 828 829 if ((*session_db->put)(session_db, &key, &data, 0)) 830 emergency("insert %d: %m", sp->se_process); 831 } 832 833 /* 834 * Delete an old login session. 835 */ 836 void 837 del_session(session_t *sp) 838 { 839 DBT key; 840 841 key.data = &sp->se_process; 842 key.size = sizeof sp->se_process; 843 844 if ((*session_db->del)(session_db, &key, 0)) 845 emergency("delete %d: %m", sp->se_process); 846 } 847 848 /* 849 * Look up a login session by pid. 850 */ 851 session_t * 852 find_session(pid_t pid) 853 { 854 DBT key; 855 DBT data; 856 session_t *ret; 857 858 if (session_db == NULL) 859 return NULL; 860 861 key.data = &pid; 862 key.size = sizeof pid; 863 if ((*session_db->get)(session_db, &key, &data, 0) != 0) 864 return 0; 865 (void)memmove(&ret, data.data, sizeof(ret)); 866 return ret; 867 } 868 869 /* 870 * Construct an argument vector from a command line. 871 */ 872 char ** 873 construct_argv(char *command) 874 { 875 int argc = 0; 876 char **argv = malloc(((strlen(command) + 1) / 2 + 1) * sizeof (char *)); 877 static const char separators[] = " \t"; 878 879 if ((argv[argc++] = strtok(command, separators)) == 0) 880 return (NULL); 881 while ((argv[argc++] = strtok(NULL, separators)) != NULL) 882 continue; 883 return (argv); 884 } 885 886 /* 887 * Deallocate a session descriptor. 888 */ 889 void 890 free_session(session_t *sp) 891 { 892 893 free(sp->se_device); 894 if (sp->se_getty) { 895 free(sp->se_getty); 896 free(sp->se_getty_argv); 897 } 898 if (sp->se_window) { 899 free(sp->se_window); 900 free(sp->se_window_argv); 901 } 902 free(sp); 903 } 904 905 /* 906 * Allocate a new session descriptor. 907 */ 908 session_t * 909 new_session(session_t *sprev, int session_index, struct ttyent *typ) 910 { 911 session_t *sp; 912 913 if ((typ->ty_status & TTY_ON) == 0 || typ->ty_name == NULL || 914 typ->ty_getty == NULL) 915 return (NULL); 916 917 sp = malloc(sizeof (session_t)); 918 if (sp == NULL) 919 return NULL; 920 memset(sp, 0, sizeof *sp); 921 922 sp->se_flags = SE_PRESENT; 923 sp->se_index = session_index; 924 925 sp->se_device = malloc(sizeof(_PATH_DEV) + strlen(typ->ty_name)); 926 (void)sprintf(sp->se_device, "%s%s", _PATH_DEV, typ->ty_name); 927 928 if (setupargv(sp, typ) == 0) { 929 free_session(sp); 930 return (NULL); 931 } 932 933 sp->se_next = NULL; 934 if (sprev == NULL) { 935 sessions = sp; 936 sp->se_prev = NULL; 937 } else { 938 sprev->se_next = sp; 939 sp->se_prev = sprev; 940 } 941 942 return (sp); 943 } 944 945 /* 946 * Calculate getty and if useful window argv vectors. 947 */ 948 int 949 setupargv(session_t *sp, struct ttyent *typ) 950 { 951 952 if (sp->se_getty) { 953 free(sp->se_getty); 954 free(sp->se_getty_argv); 955 } 956 sp->se_getty = malloc(strlen(typ->ty_getty) + strlen(typ->ty_name) + 2); 957 (void) sprintf(sp->se_getty, "%s %s", typ->ty_getty, typ->ty_name); 958 sp->se_getty_argv = construct_argv(sp->se_getty); 959 if (sp->se_getty_argv == NULL) { 960 warning("can't parse getty for port %s", sp->se_device); 961 free(sp->se_getty); 962 sp->se_getty = NULL; 963 return (0); 964 } 965 if (typ->ty_window) { 966 if (sp->se_window) 967 free(sp->se_window); 968 sp->se_window = strdup(typ->ty_window); 969 sp->se_window_argv = construct_argv(sp->se_window); 970 if (sp->se_window_argv == NULL) { 971 warning("can't parse window for port %s", 972 sp->se_device); 973 free(sp->se_window); 974 sp->se_window = NULL; 975 return (0); 976 } 977 } 978 return (1); 979 } 980 981 /* 982 * Walk the list of ttys and create sessions for each active line. 983 */ 984 state_func_t 985 read_ttys(void) 986 { 987 int session_index = 0; 988 session_t *sp, *snext; 989 struct ttyent *typ; 990 991 /* 992 * Destroy any previous session state. 993 * There shouldn't be any, but just in case... 994 */ 995 for (sp = sessions; sp; sp = snext) { 996 if (sp->se_process) 997 clear_session_logs(sp, 0); 998 snext = sp->se_next; 999 free_session(sp); 1000 } 1001 sessions = NULL; 1002 if (start_session_db()) 1003 return (state_func_t)single_user; 1004 1005 /* 1006 * Allocate a session entry for each active port. 1007 * Note that sp starts at 0. 1008 */ 1009 while ((typ = getttyent()) != NULL) 1010 if ((snext = new_session(sp, ++session_index, typ)) != NULL) 1011 sp = snext; 1012 1013 endttyent(); 1014 1015 return (state_func_t)multi_user; 1016 } 1017 1018 /* 1019 * Start a window system running. 1020 */ 1021 void 1022 start_window_system(session_t *sp) 1023 { 1024 pid_t pid; 1025 sigset_t mask; 1026 1027 if ((pid = fork()) == -1) { 1028 emergency("can't fork for window system on port %s: %m", 1029 sp->se_device); 1030 /* hope that getty fails and we can try again */ 1031 return; 1032 } 1033 1034 if (pid) 1035 return; 1036 1037 sigemptyset(&mask); 1038 sigprocmask(SIG_SETMASK, &mask, NULL); 1039 1040 if (setsid() < 0) 1041 emergency("setsid failed (window) %m"); 1042 1043 (void)execv(sp->se_window_argv[0], sp->se_window_argv); 1044 stall("can't exec window system '%s' for port %s: %m", 1045 sp->se_window_argv[0], sp->se_device); 1046 _exit(1); 1047 } 1048 1049 /* 1050 * Start a login session running. 1051 */ 1052 pid_t 1053 start_getty(session_t *sp) 1054 { 1055 pid_t pid; 1056 sigset_t mask; 1057 time_t current_time = time(NULL); 1058 1059 /* 1060 * fork(), not vfork() -- we can't afford to block. 1061 */ 1062 if ((pid = fork()) == -1) { 1063 emergency("can't fork for getty on port %s: %m", sp->se_device); 1064 return -1; 1065 } 1066 1067 if (pid) 1068 return pid; 1069 1070 if (current_time > sp->se_started && 1071 current_time - sp->se_started < GETTY_SPACING) { 1072 warning("getty repeating too quickly on port %s, sleeping", 1073 sp->se_device); 1074 (void)sleep(GETTY_SLEEP); 1075 } 1076 1077 if (sp->se_window) { 1078 start_window_system(sp); 1079 (void)sleep(WINDOW_WAIT); 1080 } 1081 1082 (void)sigemptyset(&mask); 1083 (void)sigprocmask(SIG_SETMASK, &mask, (sigset_t *) 0); 1084 1085 (void)execv(sp->se_getty_argv[0], sp->se_getty_argv); 1086 stall("can't exec getty '%s' for port %s: %m", 1087 sp->se_getty_argv[0], sp->se_device); 1088 _exit(1); 1089 /*NOTREACHED*/ 1090 } 1091 #endif /* LETS_GET_SMALL */ 1092 1093 /* 1094 * Collect exit status for a child. 1095 * If an exiting login, start a new login running. 1096 */ 1097 void 1098 collect_child(pid_t pid, int status) 1099 { 1100 #ifndef LETS_GET_SMALL 1101 session_t *sp, *sprev, *snext; 1102 1103 if (! sessions) 1104 return; 1105 1106 if ((sp = find_session(pid)) == NULL) 1107 return; 1108 1109 clear_session_logs(sp, status); 1110 del_session(sp); 1111 sp->se_process = 0; 1112 1113 if (sp->se_flags & SE_SHUTDOWN) { 1114 if ((sprev = sp->se_prev) != NULL) 1115 sprev->se_next = sp->se_next; 1116 else 1117 sessions = sp->se_next; 1118 if ((snext = sp->se_next) != NULL) 1119 snext->se_prev = sp->se_prev; 1120 free_session(sp); 1121 return; 1122 } 1123 1124 if ((pid = start_getty(sp)) == -1) { 1125 /* serious trouble */ 1126 requested_transition = clean_ttys; 1127 return; 1128 } 1129 1130 sp->se_process = pid; 1131 sp->se_started = time(NULL); 1132 add_session(sp); 1133 #endif /* LETS_GET_SMALL */ 1134 } 1135 1136 /* 1137 * Catch a signal and request a state transition. 1138 */ 1139 void 1140 transition_handler(int sig) 1141 { 1142 1143 switch (sig) { 1144 #ifndef LETS_GET_SMALL 1145 case SIGHUP: 1146 requested_transition = clean_ttys; 1147 break; 1148 case SIGTERM: 1149 requested_transition = death; 1150 break; 1151 case SIGTSTP: 1152 requested_transition = catatonia; 1153 break; 1154 #endif /* LETS_GET_SMALL */ 1155 default: 1156 requested_transition = 0; 1157 break; 1158 } 1159 } 1160 1161 #ifndef LETS_GET_SMALL 1162 /* 1163 * Take the system multiuser. 1164 */ 1165 state_func_t 1166 multi_user(void) 1167 { 1168 pid_t pid; 1169 int status; 1170 session_t *sp; 1171 1172 requested_transition = 0; 1173 1174 /* 1175 * If the administrator has not set the security level to -1 1176 * to indicate that the kernel should not run multiuser in secure 1177 * mode, and the run script has not set a higher level of security 1178 * than level 1, then put the kernel into secure mode. 1179 */ 1180 if (getsecuritylevel() == 0) 1181 setsecuritylevel(1); 1182 1183 for (sp = sessions; sp; sp = sp->se_next) { 1184 if (sp->se_process) 1185 continue; 1186 if ((pid = start_getty(sp)) == -1) { 1187 /* serious trouble */ 1188 requested_transition = clean_ttys; 1189 break; 1190 } 1191 sp->se_process = pid; 1192 sp->se_started = time(NULL); 1193 add_session(sp); 1194 } 1195 1196 while (!requested_transition) 1197 if ((pid = waitpid(-1, &status, 0)) != -1) 1198 collect_child(pid, status); 1199 1200 return (state_func_t)requested_transition; 1201 } 1202 1203 /* 1204 * This is an n-squared algorithm. We hope it isn't run often... 1205 */ 1206 state_func_t 1207 clean_ttys(void) 1208 { 1209 session_t *sp, *sprev; 1210 struct ttyent *typ; 1211 int session_index = 0; 1212 int devlen; 1213 1214 for (sp = sessions; sp; sp = sp->se_next) 1215 sp->se_flags &= ~SE_PRESENT; 1216 1217 devlen = sizeof(_PATH_DEV) - 1; 1218 while ((typ = getttyent()) != NULL) { 1219 ++session_index; 1220 1221 for (sprev = 0, sp = sessions; sp; sprev = sp, sp = sp->se_next) 1222 if (strcmp(typ->ty_name, sp->se_device + devlen) == 0) 1223 break; 1224 1225 if (sp) { 1226 sp->se_flags |= SE_PRESENT; 1227 if (sp->se_index != session_index) { 1228 warning("port %s changed utmp index from " 1229 "%d to %d", sp->se_device, sp->se_index, 1230 session_index); 1231 sp->se_index = session_index; 1232 } 1233 if ((typ->ty_status & TTY_ON) == 0 || 1234 typ->ty_getty == 0) { 1235 sp->se_flags |= SE_SHUTDOWN; 1236 if (sp->se_process != 0) 1237 (void)kill(sp->se_process, SIGHUP); 1238 continue; 1239 } 1240 sp->se_flags &= ~SE_SHUTDOWN; 1241 if (setupargv(sp, typ) == 0) { 1242 warning("can't parse getty for port %s", 1243 sp->se_device); 1244 sp->se_flags |= SE_SHUTDOWN; 1245 if (sp->se_process != 0) 1246 (void)kill(sp->se_process, SIGHUP); 1247 } 1248 continue; 1249 } 1250 1251 new_session(sprev, session_index, typ); 1252 } 1253 1254 endttyent(); 1255 1256 for (sp = sessions; sp; sp = sp->se_next) 1257 if ((sp->se_flags & SE_PRESENT) == 0) { 1258 sp->se_flags |= SE_SHUTDOWN; 1259 if (sp->se_process != 0) 1260 (void)kill(sp->se_process, SIGHUP); 1261 } 1262 1263 return (state_func_t)multi_user; 1264 } 1265 1266 /* 1267 * Block further logins. 1268 */ 1269 state_func_t 1270 catatonia(void) 1271 { 1272 session_t *sp; 1273 1274 for (sp = sessions; sp; sp = sp->se_next) 1275 sp->se_flags |= SE_SHUTDOWN; 1276 1277 return (state_func_t)multi_user; 1278 } 1279 #endif /* LETS_GET_SMALL */ 1280 1281 /* 1282 * Note SIGALRM. 1283 */ 1284 void 1285 /*ARGSUSED*/ 1286 alrm_handler(int sig) 1287 { 1288 1289 clang = 1; 1290 } 1291 1292 #ifndef LETS_GET_SMALL 1293 /* 1294 * Bring the system down to single user. 1295 */ 1296 state_func_t 1297 death(void) 1298 { 1299 session_t *sp; 1300 int i, status; 1301 pid_t pid; 1302 static const int death_sigs[3] = { SIGHUP, SIGTERM, SIGKILL }; 1303 1304 for (sp = sessions; sp; sp = sp->se_next) 1305 sp->se_flags |= SE_SHUTDOWN; 1306 1307 /* NB: should send a message to the session logger to avoid blocking. */ 1308 #ifdef SUPPORT_UTMPX 1309 logwtmpx("~", "shutdown", "", 0, INIT_PROCESS); 1310 #endif 1311 #ifdef SUPPORT_UTMP 1312 logwtmp("~", "shutdown", ""); 1313 #endif 1314 1315 for (i = 0; i < 3; ++i) { 1316 if (kill(-1, death_sigs[i]) == -1 && errno == ESRCH) 1317 return (state_func_t)single_user; 1318 1319 clang = 0; 1320 alarm(DEATH_WATCH); 1321 do 1322 if ((pid = waitpid(-1, &status, 0)) != -1) 1323 collect_child(pid, status); 1324 while (clang == 0 && errno != ECHILD); 1325 1326 if (errno == ECHILD) 1327 return (state_func_t)single_user; 1328 } 1329 1330 warning("some processes would not die; ps axl advised"); 1331 1332 return (state_func_t)single_user; 1333 } 1334 #endif /* LETS_GET_SMALL */ 1335 1336 #ifdef MFS_DEV_IF_NO_CONSOLE 1337 1338 static int 1339 mfs_dev(void) 1340 { 1341 /* 1342 * We cannot print errors so we bail out silently... 1343 */ 1344 int fd; 1345 struct stat st; 1346 pid_t pid; 1347 int status; 1348 void *makedev = 0; 1349 void *makedev_local = 0; 1350 size_t makedev_size; 1351 size_t makedev_local_size; 1352 dev_t dev; 1353 #ifdef CPU_CONSDEV 1354 static int name[2] = { CTL_MACHDEP, CPU_CONSDEV }; 1355 size_t olen; 1356 #endif 1357 1358 1359 /* If we have /dev/console, assume all is OK */ 1360 if (access(_PATH_CONSOLE, F_OK) != -1) 1361 return(0); 1362 1363 /* Grab the contents of MAKEDEV */ 1364 if ((fd = open("/dev/MAKEDEV", O_RDONLY)) != -1) { 1365 if (fstat(fd, &st) != -1 && (makedev = mmap(0, 1366 (size_t)st.st_size, PROT_READ, MAP_FILE|MAP_SHARED, fd, 1367 (off_t)0)) != MAP_FAILED) 1368 makedev_size = (size_t)st.st_size; 1369 else 1370 makedev = 0; 1371 (void)close(fd); 1372 } 1373 1374 /* Grab the contents of MAKEDEV.local */ 1375 if ((fd = open("/dev/MAKEDEV.local", O_RDONLY)) != -1) { 1376 if (fstat(fd, &st) != -1 && (makedev_local = mmap(0, 1377 (size_t)st.st_size, PROT_READ, MAP_FILE|MAP_SHARED, fd, 1378 (off_t)0)) != MAP_FAILED) 1379 makedev_local_size = (size_t)st.st_size; 1380 else 1381 makedev_local = 0; 1382 (void)close(fd); 1383 } 1384 1385 /* Mount an mfs over /dev so we can create devices */ 1386 switch ((pid = fork())) { 1387 case 0: 1388 (void)execl(INIT_MOUNT_MFS, "mount_mfs", "-i", "192", 1389 "-s", "768", "-b", "4096", "-f", "512", "swap", "/dev", 1390 NULL); 1391 _exit(1); 1392 /*NOTREACHED*/ 1393 1394 case -1: 1395 return(-1); 1396 1397 default: 1398 if (waitpid(pid, &status, 0) == -1) 1399 return(-1); 1400 if (status != 0) 1401 return(-1); 1402 break; 1403 } 1404 1405 #ifdef CPU_CONSDEV 1406 olen = sizeof(dev); 1407 if (sysctl(name, sizeof(name) / sizeof(name[0]), &dev, &olen, 1408 NULL, 0) == -1) 1409 #endif 1410 dev = makedev(0, 0); 1411 1412 /* Make a console for us, so we can see things happening */ 1413 if (mknod(_PATH_CONSOLE, 0666 | S_IFCHR, dev) == -1) 1414 return(-1); 1415 1416 (void)freopen(_PATH_CONSOLE, "a", stderr); 1417 1418 warnx("Creating mfs /dev"); 1419 1420 /* Create a MAKEDEV script in the mfs /dev */ 1421 if (makedev && (fd = open("/dev/MAKEDEV", O_WRONLY|O_CREAT|O_TRUNC, 1422 0755)) != -1) { 1423 (void)write(fd, makedev, makedev_size); 1424 (void)munmap(makedev, makedev_size); 1425 (void)close(fd); 1426 } 1427 1428 /* Create a MAKEDEV.local script in the mfs /dev */ 1429 if (makedev_local && (fd = open("/dev/MAKEDEV.local", 1430 O_WRONLY|O_CREAT|O_TRUNC, 0755)) != -1) { 1431 (void)write(fd, makedev_local, makedev_local_size); 1432 (void)munmap(makedev_local, makedev_local_size); 1433 (void)close(fd); 1434 } 1435 1436 /* Run the makedev script to create devices */ 1437 switch ((pid = fork())) { 1438 case 0: 1439 if (chdir("/dev") == -1) 1440 goto fail; 1441 (void)execl(INIT_BSHELL, "sh", "./MAKEDEV", "init", NULL); 1442 goto fail; 1443 1444 case -1: 1445 goto fail; 1446 1447 default: 1448 if (waitpid(pid, &status, 0) == -1) 1449 goto fail; 1450 if (status != 0) { 1451 errno = EINVAL; 1452 goto fail; 1453 } 1454 break; 1455 } 1456 return(0); 1457 fail: 1458 warn("Unable to run MAKEDEV"); 1459 return(-1); 1460 } 1461 #endif 1462