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