1 /*- 2 * Copyright (c) 1991 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Donn Seeley at Berkeley Software Design, Inc. 7 * 8 * %sccs.include.redist.c% 9 */ 10 11 #ifndef lint 12 char copyright[] = 13 "@(#) Copyright (c) 1991 The Regents of the University of California.\n\ 14 All rights reserved.\n"; 15 #endif /* not lint */ 16 17 #ifndef lint 18 static char sccsid[] = "@(#)init.c 6.22 (Berkeley) 06/02/93"; 19 #endif /* not lint */ 20 21 #include <sys/param.h> 22 #include <sys/sysctl.h> 23 #include <sys/wait.h> 24 25 #include <db.h> 26 #include <errno.h> 27 #include <fcntl.h> 28 #include <signal.h> 29 #include <stdio.h> 30 #include <stdlib.h> 31 #include <string.h> 32 #include <syslog.h> 33 #include <time.h> 34 #include <ttyent.h> 35 #include <unistd.h> 36 37 #ifdef __STDC__ 38 #include <stdarg.h> 39 #else 40 #include <varargs.h> 41 #endif 42 43 #ifdef SECURE 44 #include <pwd.h> 45 #endif 46 47 #include "pathnames.h" 48 49 /* 50 * Until the mythical util.h arrives... 51 */ 52 extern int login_tty __P((int)); 53 extern int logout __P((const char *)); 54 extern void logwtmp __P((const char *, const char *, const char *)); 55 56 /* 57 * Sleep times; used to prevent thrashing. 58 */ 59 #define GETTY_SPACING 10 /* fork getty on a port every N secs */ 60 #define WINDOW_WAIT 3 /* wait N secs after starting window */ 61 #define STALL_TIMEOUT 30 /* wait N secs after warning */ 62 #define DEATH_WATCH 10 /* wait N secs for procs to die */ 63 64 void handle __P((sig_t, ...)); 65 void delset __P((sigset_t *, ...)); 66 67 void stall __P((char *, ...)); 68 void warning __P((char *, ...)); 69 void emergency __P((char *, ...)); 70 void disaster __P((int)); 71 void badsys __P((int)); 72 73 /* 74 * We really need a recursive typedef... 75 * The following at least guarantees that the return type of (*state_t)() 76 * is sufficiently wide to hold a function pointer. 77 */ 78 typedef long (*state_func_t) __P((void)); 79 typedef state_func_t (*state_t) __P((void)); 80 81 state_func_t single_user __P((void)); 82 state_func_t runcom __P((void)); 83 state_func_t read_ttys __P((void)); 84 state_func_t multi_user __P((void)); 85 state_func_t clean_ttys __P((void)); 86 state_func_t catatonia __P((void)); 87 state_func_t death __P((void)); 88 89 enum { AUTOBOOT, FASTBOOT } runcom_mode = AUTOBOOT; 90 91 void transition __P((state_t)); 92 state_t requested_transition = runcom; 93 94 void setctty __P((char *)); 95 96 typedef struct init_session { 97 int se_index; /* index of entry in ttys file */ 98 pid_t se_process; /* controlling process */ 99 time_t se_started; /* used to avoid thrashing */ 100 int se_flags; /* status of session */ 101 #define SE_SHUTDOWN 0x1 /* session won't be restarted */ 102 char *se_device; /* filename of port */ 103 char *se_getty; /* what to run on that port */ 104 char **se_getty_argv; /* pre-parsed argument array */ 105 char *se_window; /* window system (started only once) */ 106 char **se_window_argv; /* pre-parsed argument array */ 107 struct init_session *se_prev; 108 struct init_session *se_next; 109 } session_t; 110 111 void free_session __P((session_t *)); 112 session_t *new_session __P((session_t *, int, struct ttyent *)); 113 session_t *sessions; 114 115 char **construct_argv __P((char *)); 116 void start_window_system __P((session_t *)); 117 void collect_child __P((pid_t)); 118 pid_t start_getty __P((session_t *)); 119 void transition_handler __P((int)); 120 void alrm_handler __P((int)); 121 void setsecuritylevel __P((int)); 122 int getsecuritylevel __P((void)); 123 int setupargv __P((session_t *, struct ttyent *)); 124 int clang; 125 126 void clear_session_logs __P((session_t *)); 127 128 int start_session_db __P((void)); 129 void add_session __P((session_t *)); 130 void del_session __P((session_t *)); 131 session_t *find_session __P((pid_t)); 132 DB *session_db; 133 134 /* 135 * The mother of all processes. 136 */ 137 int 138 main(argc, argv) 139 int argc; 140 char **argv; 141 { 142 int c; 143 struct sigaction sa; 144 sigset_t mask; 145 146 147 /* Dispose of random users. */ 148 if (getuid() != 0) { 149 (void)fprintf(stderr, "init: %s\n", strerror(EPERM)); 150 exit (1); 151 } 152 153 /* System V users like to reexec init. */ 154 if (getpid() != 1) { 155 (void)fprintf(stderr, "init: already running\n"); 156 exit (1); 157 } 158 159 /* 160 * Note that this does NOT open a file... 161 * Does 'init' deserve its own facility number? 162 */ 163 openlog("init", LOG_CONS|LOG_ODELAY, LOG_AUTH); 164 165 /* 166 * Create an initial session. 167 */ 168 if (setsid() < 0) 169 warning("initial setsid() failed: %m"); 170 171 /* 172 * This code assumes that we always get arguments through flags, 173 * never through bits set in some random machine register. 174 */ 175 while ((c = getopt(argc, argv, "sf")) != -1) 176 switch (c) { 177 case 's': 178 requested_transition = single_user; 179 break; 180 case 'f': 181 runcom_mode = FASTBOOT; 182 break; 183 default: 184 warning("unrecognized flag '-%c'", c); 185 break; 186 } 187 188 if (optind != argc) 189 warning("ignoring excess arguments"); 190 191 /* 192 * We catch or block signals rather than ignore them, 193 * so that they get reset on exec. 194 */ 195 handle(badsys, SIGSYS, 0); 196 handle(disaster, SIGABRT, SIGFPE, SIGILL, SIGSEGV, 197 SIGBUS, SIGXCPU, SIGXFSZ, 0); 198 handle(transition_handler, SIGHUP, SIGTERM, SIGTSTP, 0); 199 handle(alrm_handler, SIGALRM, 0); 200 sigfillset(&mask); 201 delset(&mask, SIGABRT, SIGFPE, SIGILL, SIGSEGV, SIGBUS, SIGSYS, 202 SIGXCPU, SIGXFSZ, SIGHUP, SIGTERM, SIGTSTP, SIGALRM, 0); 203 sigprocmask(SIG_SETMASK, &mask, (sigset_t *) 0); 204 sigemptyset(&sa.sa_mask); 205 sa.sa_flags = 0; 206 sa.sa_handler = SIG_IGN; 207 (void) sigaction(SIGTTIN, &sa, (struct sigaction *)0); 208 (void) sigaction(SIGTTOU, &sa, (struct sigaction *)0); 209 210 /* 211 * Paranoia. 212 */ 213 close(0); 214 close(1); 215 close(2); 216 217 /* 218 * Start the state machine. 219 */ 220 transition(requested_transition); 221 222 /* 223 * Should never reach here. 224 */ 225 return 1; 226 } 227 228 /* 229 * Associate a function with a signal handler. 230 */ 231 void 232 #ifdef __STDC__ 233 handle(sig_t handler, ...) 234 #else 235 handle(va_alist) 236 va_dcl 237 #endif 238 { 239 int sig; 240 struct sigaction sa; 241 int mask_everything; 242 va_list ap; 243 #ifndef __STDC__ 244 sig_t handler; 245 246 va_start(ap); 247 handler = va_arg(ap, sig_t); 248 #else 249 va_start(ap, handler); 250 #endif 251 252 sa.sa_handler = handler; 253 sigfillset(&mask_everything); 254 255 while (sig = va_arg(ap, int)) { 256 sa.sa_mask = mask_everything; 257 /* XXX SA_RESTART? */ 258 sa.sa_flags = sig == SIGCHLD ? SA_NOCLDSTOP : 0; 259 sigaction(sig, &sa, (struct sigaction *) 0); 260 } 261 } 262 263 /* 264 * Delete a set of signals from a mask. 265 */ 266 void 267 #ifdef __STDC__ 268 delset(sigset_t *maskp, ...) 269 #else 270 delset(va_alist) 271 va_dcl 272 #endif 273 { 274 int sig; 275 va_list ap; 276 #ifndef __STDC__ 277 sigset_t *maskp; 278 279 va_start(ap); 280 maskp = va_arg(ap, sigset_t *); 281 #else 282 va_start(ap, maskp); 283 #endif 284 285 while (sig = va_arg(ap, int)) 286 sigdelset(maskp, sig); 287 } 288 289 /* 290 * Log a message and sleep for a while (to give someone an opportunity 291 * to read it and to save log or hardcopy output if the problem is chronic). 292 * NB: should send a message to the session logger to avoid blocking. 293 */ 294 void 295 #ifdef __STDC__ 296 stall(char *message, ...) 297 #else 298 stall(va_alist) 299 va_dcl 300 #endif 301 { 302 va_list ap; 303 #ifndef __STDC__ 304 char *message; 305 306 va_start(ap); 307 message = va_arg(ap, char *); 308 #else 309 va_start(ap, message); 310 #endif 311 312 vsyslog(LOG_ALERT, message, ap); 313 va_end(ap); 314 sleep(STALL_TIMEOUT); 315 } 316 317 /* 318 * Like stall(), but doesn't sleep. 319 * If cpp had variadic macros, the two functions could be #defines for another. 320 * NB: should send a message to the session logger to avoid blocking. 321 */ 322 void 323 #ifdef __STDC__ 324 warning(char *message, ...) 325 #else 326 warning(va_alist) 327 va_dcl 328 #endif 329 { 330 va_list ap; 331 #ifndef __STDC__ 332 char *message; 333 334 va_start(ap); 335 message = va_arg(ap, char *); 336 #else 337 va_start(ap, message); 338 #endif 339 340 vsyslog(LOG_ALERT, message, ap); 341 va_end(ap); 342 } 343 344 /* 345 * Log an emergency message. 346 * NB: should send a message to the session logger to avoid blocking. 347 */ 348 void 349 #ifdef __STDC__ 350 emergency(char *message, ...) 351 #else 352 emergency(va_alist) 353 va_dcl 354 #endif 355 { 356 va_list ap; 357 #ifndef __STDC__ 358 char *message; 359 360 va_start(ap); 361 message = va_arg(ap, char *); 362 #else 363 va_start(ap, message); 364 #endif 365 366 vsyslog(LOG_EMERG, message, ap); 367 va_end(ap); 368 } 369 370 /* 371 * Catch a SIGSYS signal. 372 * 373 * These may arise if a system does not support sysctl. 374 * We tolerate up to 25 of these, then throw in the towel. 375 */ 376 void 377 badsys(sig) 378 int sig; 379 { 380 static int badcount = 0; 381 382 if (badcount++ < 25) 383 return; 384 disaster(sig); 385 } 386 387 /* 388 * Catch an unexpected signal. 389 */ 390 void 391 disaster(sig) 392 int sig; 393 { 394 emergency("fatal signal: %s", 395 sig < (unsigned) NSIG ? sys_siglist[sig] : "unknown signal"); 396 397 sleep(STALL_TIMEOUT); 398 _exit(sig); /* reboot */ 399 } 400 401 /* 402 * Get the security level of the kernel. 403 */ 404 int 405 getsecuritylevel() 406 { 407 int name[2], curlevel; 408 size_t len; 409 extern int errno; 410 411 name[0] = CTL_KERN; 412 name[1] = KERN_SECURELVL; 413 len = sizeof curlevel; 414 if (sysctl(name, 2, &curlevel, &len, NULL, 0) == -1) { 415 emergency("cannot get kernel security level: %s", 416 strerror(errno)); 417 return (-1); 418 } 419 return (curlevel); 420 } 421 422 /* 423 * Set the security level of the kernel. 424 */ 425 void 426 setsecuritylevel(newlevel) 427 int newlevel; 428 { 429 int name[2], curlevel; 430 extern int errno; 431 432 curlevel = getsecuritylevel(); 433 if (newlevel == curlevel) 434 return; 435 name[0] = CTL_KERN; 436 name[1] = KERN_SECURELVL; 437 if (sysctl(name, 2, NULL, NULL, &newlevel, sizeof newlevel) == -1) { 438 emergency( 439 "cannot change kernel security level from %d to %d: %s", 440 curlevel, newlevel, strerror(errno)); 441 return; 442 } 443 #ifdef SECURE 444 warning("kernel security level changed from %d to %d", 445 curlevel, newlevel); 446 #endif 447 } 448 449 /* 450 * Change states in the finite state machine. 451 * The initial state is passed as an argument. 452 */ 453 void 454 transition(s) 455 state_t s; 456 { 457 for (;;) 458 s = (state_t) (*s)(); 459 } 460 461 /* 462 * Close out the accounting files for a login session. 463 * NB: should send a message to the session logger to avoid blocking. 464 */ 465 void 466 clear_session_logs(sp) 467 session_t *sp; 468 { 469 char *line = sp->se_device + sizeof(_PATH_DEV) - 1; 470 471 if (logout(line)) 472 logwtmp(line, "", ""); 473 } 474 475 /* 476 * Start a session and allocate a controlling terminal. 477 * Only called by children of init after forking. 478 */ 479 void 480 setctty(name) 481 char *name; 482 { 483 int fd; 484 485 (void) revoke(name); 486 sleep (2); /* leave DTR low */ 487 if ((fd = open(name, O_RDWR)) == -1) { 488 stall("can't open %s: %m", name); 489 _exit(1); 490 } 491 if (login_tty(fd) == -1) { 492 stall("can't get %s for controlling terminal: %m", name); 493 _exit(1); 494 } 495 } 496 497 /* 498 * Bring the system up single user. 499 */ 500 state_func_t 501 single_user() 502 { 503 pid_t pid, wpid; 504 int status; 505 sigset_t mask; 506 char *shell = _PATH_BSHELL; 507 char *argv[2]; 508 #ifdef SECURE 509 struct ttyent *typ; 510 struct passwd *pp; 511 static const char banner[] = 512 "Enter root password, or ^D to go multi-user\n"; 513 char *clear, *password; 514 #endif 515 516 /* 517 * If the kernel is in secure mode, downgrade it to insecure mode. 518 */ 519 if (getsecuritylevel() > 0) 520 setsecuritylevel(0); 521 522 if ((pid = fork()) == 0) { 523 /* 524 * Start the single user session. 525 */ 526 setctty(_PATH_CONSOLE); 527 528 #ifdef SECURE 529 /* 530 * Check the root password. 531 * We don't care if the console is 'on' by default; 532 * it's the only tty that can be 'off' and 'secure'. 533 */ 534 typ = getttynam("console"); 535 pp = getpwnam("root"); 536 if (typ && (typ->ty_status & TTY_SECURE) == 0 && pp) { 537 write(2, banner, sizeof banner - 1); 538 for (;;) { 539 clear = getpass("Password:"); 540 if (clear == 0 || *clear == '\0') 541 _exit(0); 542 password = crypt(clear, pp->pw_passwd); 543 bzero(clear, _PASSWORD_LEN); 544 if (strcmp(password, pp->pw_passwd) == 0) 545 break; 546 warning("single-user login failed\n"); 547 } 548 } 549 endttyent(); 550 endpwent(); 551 #endif /* SECURE */ 552 553 #ifdef DEBUGSHELL 554 { 555 char altshell[128], *cp = altshell; 556 int num; 557 558 #define SHREQUEST \ 559 "Enter pathname of shell or RETURN for sh: " 560 (void)write(STDERR_FILENO, 561 SHREQUEST, sizeof(SHREQUEST) - 1); 562 while ((num = read(STDIN_FILENO, cp, 1)) != -1 && 563 num != 0 && *cp != '\n' && cp < &altshell[127]) 564 cp++; 565 *cp = '\0'; 566 if (altshell[0] != '\0') 567 shell = altshell; 568 } 569 #endif /* DEBUGSHELL */ 570 571 /* 572 * Unblock signals. 573 * We catch all the interesting ones, 574 * and those are reset to SIG_DFL on exec. 575 */ 576 sigemptyset(&mask); 577 sigprocmask(SIG_SETMASK, &mask, (sigset_t *) 0); 578 579 /* 580 * Fire off a shell. 581 * If the default one doesn't work, try the Bourne shell. 582 */ 583 argv[0] = "-sh"; 584 argv[1] = 0; 585 execv(shell, argv); 586 emergency("can't exec %s for single user: %m", shell); 587 execv(_PATH_BSHELL, argv); 588 emergency("can't exec %s for single user: %m", _PATH_BSHELL); 589 sleep(STALL_TIMEOUT); 590 _exit(1); 591 } 592 593 if (pid == -1) { 594 /* 595 * We are seriously hosed. Do our best. 596 */ 597 emergency("can't fork single-user shell, trying again"); 598 while (waitpid(-1, (int *) 0, WNOHANG) > 0) 599 continue; 600 return (state_func_t) single_user; 601 } 602 603 requested_transition = 0; 604 do { 605 if ((wpid = waitpid(-1, &status, WUNTRACED)) != -1) 606 collect_child(wpid); 607 if (wpid == -1) { 608 if (errno == EINTR) 609 continue; 610 warning("wait for single-user shell failed: %m; restarting"); 611 return (state_func_t) single_user; 612 } 613 if (wpid == pid && WIFSTOPPED(status)) { 614 warning("init: shell stopped, restarting\n"); 615 kill(pid, SIGCONT); 616 wpid = -1; 617 } 618 } while (wpid != pid && !requested_transition); 619 620 if (requested_transition) 621 return (state_func_t) requested_transition; 622 623 if (!WIFEXITED(status)) { 624 if (WTERMSIG(status) == SIGKILL) { 625 /* 626 * reboot(8) killed shell? 627 */ 628 warning("single user shell terminated."); 629 sleep(STALL_TIMEOUT); 630 _exit(0); 631 } else { 632 warning("single user shell terminated, restarting"); 633 return (state_func_t) single_user; 634 } 635 } 636 637 runcom_mode = FASTBOOT; 638 return (state_func_t) runcom; 639 } 640 641 /* 642 * Run the system startup script. 643 */ 644 state_func_t 645 runcom() 646 { 647 pid_t pid, wpid; 648 int status; 649 char *argv[4]; 650 struct sigaction sa; 651 652 if ((pid = fork()) == 0) { 653 sigemptyset(&sa.sa_mask); 654 sa.sa_flags = 0; 655 sa.sa_handler = SIG_IGN; 656 (void) sigaction(SIGTSTP, &sa, (struct sigaction *)0); 657 (void) sigaction(SIGHUP, &sa, (struct sigaction *)0); 658 659 setctty(_PATH_CONSOLE); 660 661 argv[0] = "sh"; 662 argv[1] = _PATH_RUNCOM; 663 argv[2] = runcom_mode == AUTOBOOT ? "autoboot" : 0; 664 argv[3] = 0; 665 666 sigprocmask(SIG_SETMASK, &sa.sa_mask, (sigset_t *) 0); 667 668 execv(_PATH_BSHELL, argv); 669 stall("can't exec %s for %s: %m", _PATH_BSHELL, _PATH_RUNCOM); 670 _exit(1); /* force single user mode */ 671 } 672 673 if (pid == -1) { 674 emergency("can't fork for %s on %s: %m", 675 _PATH_BSHELL, _PATH_RUNCOM); 676 while (waitpid(-1, (int *) 0, WNOHANG) > 0) 677 continue; 678 sleep(STALL_TIMEOUT); 679 return (state_func_t) single_user; 680 } 681 682 /* 683 * Copied from single_user(). This is a bit paranoid. 684 */ 685 do { 686 if ((wpid = waitpid(-1, &status, WUNTRACED)) != -1) 687 collect_child(wpid); 688 if (wpid == -1) { 689 if (errno == EINTR) 690 continue; 691 warning("wait for %s on %s failed: %m; going to single user mode", 692 _PATH_BSHELL, _PATH_RUNCOM); 693 return (state_func_t) single_user; 694 } 695 if (wpid == pid && WIFSTOPPED(status)) { 696 warning("init: %s on %s stopped, restarting\n", 697 _PATH_BSHELL, _PATH_RUNCOM); 698 kill(pid, SIGCONT); 699 wpid = -1; 700 } 701 } while (wpid != pid); 702 703 if (WIFSIGNALED(status) && WTERMSIG(status) == SIGTERM && 704 requested_transition == catatonia) { 705 /* /etc/rc executed /sbin/reboot; wait for the end quietly */ 706 sigset_t s; 707 708 sigfillset(&s); 709 for (;;) 710 sigsuspend(&s); 711 } 712 713 if (!WIFEXITED(status)) { 714 warning("%s on %s terminated abnormally, going to single user mode", 715 _PATH_BSHELL, _PATH_RUNCOM); 716 return (state_func_t) single_user; 717 } 718 719 if (WEXITSTATUS(status)) 720 return (state_func_t) single_user; 721 722 runcom_mode = AUTOBOOT; /* the default */ 723 /* NB: should send a message to the session logger to avoid blocking. */ 724 logwtmp("~", "reboot", ""); 725 return (state_func_t) read_ttys; 726 } 727 728 /* 729 * Open the session database. 730 * 731 * NB: We could pass in the size here; is it necessary? 732 */ 733 int 734 start_session_db() 735 { 736 if (session_db && (*session_db->close)(session_db)) 737 emergency("session database close: %s", strerror(errno)); 738 if ((session_db = dbopen(NULL, O_RDWR, 0, DB_HASH, NULL)) == 0) { 739 emergency("session database open: %s", strerror(errno)); 740 return (1); 741 } 742 return (0); 743 744 } 745 746 /* 747 * Add a new login session. 748 */ 749 void 750 add_session(sp) 751 session_t *sp; 752 { 753 DBT key; 754 DBT data; 755 756 key.data = &sp->se_process; 757 key.size = sizeof sp->se_process; 758 data.data = &sp; 759 data.size = sizeof sp; 760 761 if ((*session_db->put)(session_db, &key, &data, 0)) 762 emergency("insert %d: %s", sp->se_process, strerror(errno)); 763 } 764 765 /* 766 * Delete an old login session. 767 */ 768 void 769 del_session(sp) 770 session_t *sp; 771 { 772 DBT key; 773 774 key.data = &sp->se_process; 775 key.size = sizeof sp->se_process; 776 777 if ((*session_db->del)(session_db, &key, 0)) 778 emergency("delete %d: %s", sp->se_process, strerror(errno)); 779 } 780 781 /* 782 * Look up a login session by pid. 783 */ 784 session_t * 785 #ifdef __STDC__ 786 find_session(pid_t pid) 787 #else 788 find_session(pid) 789 pid_t pid; 790 #endif 791 { 792 DBT key; 793 DBT data; 794 session_t *ret; 795 796 key.data = &pid; 797 key.size = sizeof pid; 798 if ((*session_db->get)(session_db, &key, &data, 0) != 0) 799 return 0; 800 bcopy(data.data, (char *)&ret, sizeof(ret)); 801 return ret; 802 } 803 804 /* 805 * Construct an argument vector from a command line. 806 */ 807 char ** 808 construct_argv(command) 809 char *command; 810 { 811 register int argc = 0; 812 register char **argv = (char **) malloc(((strlen(command) + 1) / 2 + 1) 813 * sizeof (char *)); 814 static const char separators[] = " \t"; 815 816 if ((argv[argc++] = strtok(command, separators)) == 0) 817 return 0; 818 while (argv[argc++] = strtok((char *) 0, separators)) 819 continue; 820 return argv; 821 } 822 823 /* 824 * Deallocate a session descriptor. 825 */ 826 void 827 free_session(sp) 828 register session_t *sp; 829 { 830 free(sp->se_device); 831 if (sp->se_getty) { 832 free(sp->se_getty); 833 free(sp->se_getty_argv); 834 } 835 if (sp->se_window) { 836 free(sp->se_window); 837 free(sp->se_window_argv); 838 } 839 free(sp); 840 } 841 842 /* 843 * Allocate a new session descriptor. 844 */ 845 session_t * 846 new_session(sprev, session_index, typ) 847 session_t *sprev; 848 int session_index; 849 register struct ttyent *typ; 850 { 851 register session_t *sp; 852 853 if ((typ->ty_status & TTY_ON) == 0 || 854 typ->ty_name == 0 || 855 typ->ty_getty == 0) 856 return 0; 857 858 sp = (session_t *) malloc(sizeof (session_t)); 859 bzero(sp, sizeof *sp); 860 861 sp->se_index = session_index; 862 863 sp->se_device = malloc(sizeof(_PATH_DEV) + strlen(typ->ty_name)); 864 (void) sprintf(sp->se_device, "%s%s", _PATH_DEV, typ->ty_name); 865 866 if (setupargv(sp, typ) == 0) { 867 free_session(sp); 868 return (0); 869 } 870 871 sp->se_next = 0; 872 if (sprev == 0) { 873 sessions = sp; 874 sp->se_prev = 0; 875 } else { 876 sprev->se_next = sp; 877 sp->se_prev = sprev; 878 } 879 880 return sp; 881 } 882 883 /* 884 * Calculate getty and if useful window argv vectors. 885 */ 886 int 887 setupargv(sp, typ) 888 session_t *sp; 889 struct ttyent *typ; 890 { 891 892 if (sp->se_getty) { 893 free(sp->se_getty); 894 free(sp->se_getty_argv); 895 } 896 sp->se_getty = malloc(strlen(typ->ty_getty) + strlen(typ->ty_name) + 2); 897 (void) sprintf(sp->se_getty, "%s %s", typ->ty_getty, typ->ty_name); 898 sp->se_getty_argv = construct_argv(sp->se_getty); 899 if (sp->se_getty_argv == 0) { 900 warning("can't parse getty for port %s", sp->se_device); 901 free(sp->se_getty); 902 sp->se_getty = 0; 903 return (0); 904 } 905 if (typ->ty_window) { 906 if (sp->se_window) 907 free(sp->se_window); 908 sp->se_window = strdup(typ->ty_window); 909 sp->se_window_argv = construct_argv(sp->se_window); 910 if (sp->se_window_argv == 0) { 911 warning("can't parse window for port %s", 912 sp->se_device); 913 free(sp->se_window); 914 sp->se_window = 0; 915 return (0); 916 } 917 } 918 return (1); 919 } 920 921 /* 922 * Walk the list of ttys and create sessions for each active line. 923 */ 924 state_func_t 925 read_ttys() 926 { 927 int session_index = 0; 928 register session_t *sp, *snext; 929 register struct ttyent *typ; 930 931 /* 932 * Destroy any previous session state. 933 * There shouldn't be any, but just in case... 934 */ 935 for (sp = sessions; sp; sp = snext) { 936 if (sp->se_process) 937 clear_session_logs(sp); 938 snext = sp->se_next; 939 free_session(sp); 940 } 941 sessions = 0; 942 if (start_session_db()) 943 return (state_func_t) single_user; 944 945 /* 946 * Allocate a session entry for each active port. 947 * Note that sp starts at 0. 948 */ 949 while (typ = getttyent()) 950 if (snext = new_session(sp, ++session_index, typ)) 951 sp = snext; 952 953 endttyent(); 954 955 return (state_func_t) multi_user; 956 } 957 958 /* 959 * Start a window system running. 960 */ 961 void 962 start_window_system(sp) 963 session_t *sp; 964 { 965 pid_t pid; 966 sigset_t mask; 967 968 if ((pid = fork()) == -1) { 969 emergency("can't fork for window system on port %s: %m", 970 sp->se_device); 971 /* hope that getty fails and we can try again */ 972 return; 973 } 974 975 if (pid) 976 return; 977 978 sigemptyset(&mask); 979 sigprocmask(SIG_SETMASK, &mask, (sigset_t *) 0); 980 981 if (setsid() < 0) 982 emergency("setsid failed (window) %m"); 983 984 execv(sp->se_window_argv[0], sp->se_window_argv); 985 stall("can't exec window system '%s' for port %s: %m", 986 sp->se_window_argv[0], sp->se_device); 987 _exit(1); 988 } 989 990 /* 991 * Start a login session running. 992 */ 993 pid_t 994 start_getty(sp) 995 session_t *sp; 996 { 997 pid_t pid; 998 sigset_t mask; 999 time_t current_time = time((time_t *) 0); 1000 1001 /* 1002 * fork(), not vfork() -- we can't afford to block. 1003 */ 1004 if ((pid = fork()) == -1) { 1005 emergency("can't fork for getty on port %s: %m", sp->se_device); 1006 return -1; 1007 } 1008 1009 if (pid) 1010 return pid; 1011 1012 if (current_time > sp->se_started && 1013 current_time - sp->se_started < GETTY_SPACING) { 1014 warning("getty repeating too quickly on port %s, sleeping", 1015 sp->se_device); 1016 sleep((unsigned) GETTY_SPACING + 1 - 1017 (current_time - sp->se_started)); 1018 } 1019 1020 if (sp->se_window) { 1021 start_window_system(sp); 1022 sleep(WINDOW_WAIT); 1023 } 1024 1025 sigemptyset(&mask); 1026 sigprocmask(SIG_SETMASK, &mask, (sigset_t *) 0); 1027 1028 execv(sp->se_getty_argv[0], sp->se_getty_argv); 1029 stall("can't exec getty '%s' for port %s: %m", 1030 sp->se_getty_argv[0], sp->se_device); 1031 _exit(1); 1032 } 1033 1034 /* 1035 * Collect exit status for a child. 1036 * If an exiting login, start a new login running. 1037 */ 1038 void 1039 collect_child(pid) 1040 pid_t pid; 1041 { 1042 register session_t *sp, *sprev, *snext; 1043 1044 if (! sessions) 1045 return; 1046 1047 if (! (sp = find_session(pid))) 1048 return; 1049 1050 clear_session_logs(sp); 1051 del_session(sp); 1052 sp->se_process = 0; 1053 1054 if (sp->se_flags & SE_SHUTDOWN) { 1055 if (sprev = sp->se_prev) 1056 sprev->se_next = sp->se_next; 1057 else 1058 sessions = sp->se_next; 1059 if (snext = sp->se_next) 1060 snext->se_prev = sp->se_prev; 1061 free_session(sp); 1062 return; 1063 } 1064 1065 if ((pid = start_getty(sp)) == -1) { 1066 /* serious trouble */ 1067 requested_transition = clean_ttys; 1068 return; 1069 } 1070 1071 sp->se_process = pid; 1072 sp->se_started = time((time_t *) 0); 1073 add_session(sp); 1074 } 1075 1076 /* 1077 * Catch a signal and request a state transition. 1078 */ 1079 void 1080 transition_handler(sig) 1081 int sig; 1082 { 1083 1084 switch (sig) { 1085 case SIGHUP: 1086 requested_transition = clean_ttys; 1087 break; 1088 case SIGTERM: 1089 requested_transition = death; 1090 break; 1091 case SIGTSTP: 1092 requested_transition = catatonia; 1093 break; 1094 default: 1095 requested_transition = 0; 1096 break; 1097 } 1098 } 1099 1100 /* 1101 * Take the system multiuser. 1102 */ 1103 state_func_t 1104 multi_user() 1105 { 1106 pid_t pid; 1107 register session_t *sp; 1108 1109 requested_transition = 0; 1110 1111 /* 1112 * If the administrator has not set the security level to -1 1113 * to indicate that the kernel should not run multiuser in secure 1114 * mode, and the run script has not set a higher level of security 1115 * than level 1, then put the kernel into secure mode. 1116 */ 1117 if (getsecuritylevel() == 0) 1118 setsecuritylevel(1); 1119 1120 for (sp = sessions; sp; sp = sp->se_next) { 1121 if (sp->se_process) 1122 continue; 1123 if ((pid = start_getty(sp)) == -1) { 1124 /* serious trouble */ 1125 requested_transition = clean_ttys; 1126 break; 1127 } 1128 sp->se_process = pid; 1129 sp->se_started = time((time_t *) 0); 1130 add_session(sp); 1131 } 1132 1133 while (!requested_transition) 1134 if ((pid = waitpid(-1, (int *) 0, 0)) != -1) 1135 collect_child(pid); 1136 1137 return (state_func_t) requested_transition; 1138 } 1139 1140 /* 1141 * This is an n-squared algorithm. We hope it isn't run often... 1142 */ 1143 state_func_t 1144 clean_ttys() 1145 { 1146 register session_t *sp, *sprev; 1147 register struct ttyent *typ; 1148 register int session_index = 0; 1149 register int devlen; 1150 1151 if (! sessions) 1152 return (state_func_t) multi_user; 1153 1154 devlen = sizeof(_PATH_DEV) - 1; 1155 while (typ = getttyent()) { 1156 ++session_index; 1157 1158 for (sprev = 0, sp = sessions; sp; sprev = sp, sp = sp->se_next) 1159 if (strcmp(typ->ty_name, sp->se_device + devlen) == 0) 1160 break; 1161 1162 if (sp) { 1163 if (sp->se_index != session_index) { 1164 warning("port %s changed utmp index from %d to %d", 1165 sp->se_device, sp->se_index, 1166 session_index); 1167 sp->se_index = session_index; 1168 } 1169 if ((typ->ty_status & TTY_ON) == 0 || 1170 typ->ty_getty == 0) { 1171 sp->se_flags |= SE_SHUTDOWN; 1172 kill(sp->se_process, SIGHUP); 1173 continue; 1174 } 1175 sp->se_flags &= ~SE_SHUTDOWN; 1176 if (setupargv(sp, typ) == 0) { 1177 warning("can't parse getty for port %s", 1178 sp->se_device); 1179 sp->se_flags |= SE_SHUTDOWN; 1180 kill(sp->se_process, SIGHUP); 1181 } 1182 continue; 1183 } 1184 1185 new_session(sprev, session_index, typ); 1186 } 1187 1188 endttyent(); 1189 1190 return (state_func_t) multi_user; 1191 } 1192 1193 /* 1194 * Block further logins. 1195 */ 1196 state_func_t 1197 catatonia() 1198 { 1199 register session_t *sp; 1200 1201 for (sp = sessions; sp; sp = sp->se_next) 1202 sp->se_flags |= SE_SHUTDOWN; 1203 1204 return (state_func_t) multi_user; 1205 } 1206 1207 /* 1208 * Note SIGALRM. 1209 */ 1210 void 1211 alrm_handler(sig) 1212 int sig; 1213 { 1214 clang = 1; 1215 } 1216 1217 /* 1218 * Bring the system down to single user. 1219 */ 1220 state_func_t 1221 death() 1222 { 1223 register session_t *sp; 1224 register int i; 1225 pid_t pid; 1226 static const int death_sigs[3] = { SIGHUP, SIGTERM, SIGKILL }; 1227 1228 for (sp = sessions; sp; sp = sp->se_next) 1229 sp->se_flags |= SE_SHUTDOWN; 1230 1231 /* NB: should send a message to the session logger to avoid blocking. */ 1232 logwtmp("~", "shutdown", ""); 1233 1234 for (i = 0; i < 3; ++i) { 1235 if (kill(-1, death_sigs[i]) == -1 && errno == ESRCH) 1236 return (state_func_t) single_user; 1237 1238 clang = 0; 1239 alarm(DEATH_WATCH); 1240 do 1241 if ((pid = waitpid(-1, (int *)0, 0)) != -1) 1242 collect_child(pid); 1243 while (clang == 0 && errno != ECHILD); 1244 1245 if (errno == ECHILD) 1246 return (state_func_t) single_user; 1247 } 1248 1249 warning("some processes would not die; ps axl advised"); 1250 1251 return (state_func_t) single_user; 1252 } 1253