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