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