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[] = "from: @(#)init.c 8.1 (Berkeley) 7/15/93";*/ 45 static char *rcsid = "$Id: init.c,v 1.17 1994/08/06 06:26:44 deraadt Exp $"; 46 #endif /* not lint */ 47 48 #include <sys/param.h> 49 #include <sys/sysctl.h> 50 #include <sys/wait.h> 51 52 #include <db.h> 53 #include <errno.h> 54 #include <fcntl.h> 55 #include <signal.h> 56 #include <stdio.h> 57 #include <stdlib.h> 58 #include <string.h> 59 #include <syslog.h> 60 #include <time.h> 61 #include <ttyent.h> 62 #include <unistd.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 WINDOW_WAIT 3 /* wait N secs after starting window */ 89 #define STALL_TIMEOUT 30 /* wait N secs after warning */ 90 #define DEATH_WATCH 10 /* wait N secs for procs to die */ 91 92 void handle __P((sig_t, ...)); 93 void delset __P((sigset_t *, ...)); 94 95 void stall __P((char *, ...)); 96 void warning __P((char *, ...)); 97 void emergency __P((char *, ...)); 98 void disaster __P((int)); 99 void badsys __P((int)); 100 101 /* 102 * We really need a recursive typedef... 103 * The following at least guarantees that the return type of (*state_t)() 104 * is sufficiently wide to hold a function pointer. 105 */ 106 typedef long (*state_func_t) __P((void)); 107 typedef state_func_t (*state_t) __P((void)); 108 109 state_func_t single_user __P((void)); 110 state_func_t runcom __P((void)); 111 state_func_t read_ttys __P((void)); 112 state_func_t multi_user __P((void)); 113 state_func_t clean_ttys __P((void)); 114 state_func_t catatonia __P((void)); 115 state_func_t death __P((void)); 116 117 enum { AUTOBOOT, FASTBOOT } runcom_mode = AUTOBOOT; 118 119 void transition __P((state_t)); 120 #ifndef LETS_GET_SMALL 121 state_t requested_transition = runcom; 122 #else /* LETS_GET_SMALL */ 123 state_t requested_transition = single_user; 124 #endif /* LETS_GET_SMALL */ 125 126 void setctty __P((char *)); 127 128 typedef struct init_session { 129 int se_index; /* index of entry in ttys file */ 130 pid_t se_process; /* controlling process */ 131 time_t se_started; /* used to avoid thrashing */ 132 int se_flags; /* status of session */ 133 #define SE_SHUTDOWN 0x1 /* session won't be restarted */ 134 char *se_device; /* filename of port */ 135 char *se_getty; /* what to run on that port */ 136 char **se_getty_argv; /* pre-parsed argument array */ 137 char *se_window; /* window system (started only once) */ 138 char **se_window_argv; /* pre-parsed argument array */ 139 struct init_session *se_prev; 140 struct init_session *se_next; 141 } session_t; 142 143 void free_session __P((session_t *)); 144 session_t *new_session __P((session_t *, int, struct ttyent *)); 145 session_t *sessions; 146 147 char **construct_argv __P((char *)); 148 void start_window_system __P((session_t *)); 149 void collect_child __P((pid_t)); 150 pid_t start_getty __P((session_t *)); 151 void transition_handler __P((int)); 152 void alrm_handler __P((int)); 153 void setsecuritylevel __P((int)); 154 int getsecuritylevel __P((void)); 155 int setupargv __P((session_t *, struct ttyent *)); 156 int clang; 157 158 void clear_session_logs __P((session_t *)); 159 160 int start_session_db __P((void)); 161 void add_session __P((session_t *)); 162 void del_session __P((session_t *)); 163 session_t *find_session __P((pid_t)); 164 DB *session_db; 165 166 /* 167 * The mother of all processes. 168 */ 169 int 170 main(argc, argv) 171 int argc; 172 char **argv; 173 { 174 int c; 175 struct sigaction sa; 176 sigset_t mask; 177 178 #ifndef LETS_GET_SMALL 179 /* Dispose of random users. */ 180 if (getuid() != 0) { 181 (void)fprintf(stderr, "init: %s\n", strerror(EPERM)); 182 exit (1); 183 } 184 185 /* System V users like to reexec init. */ 186 if (getpid() != 1) { 187 (void)fprintf(stderr, "init: already running\n"); 188 exit (1); 189 } 190 191 /* 192 * Note that this does NOT open a file... 193 * Does 'init' deserve its own facility number? 194 */ 195 openlog("init", LOG_CONS|LOG_ODELAY, LOG_AUTH); 196 #endif /* LETS_GET_SMALL */ 197 198 /* 199 * Create an initial session. 200 */ 201 if (setsid() < 0) 202 warning("initial setsid() failed: %m"); 203 204 /* 205 * Establish an initial user so that programs running 206 * single user do not freak out and die (like passwd). 207 */ 208 if (setlogin("root") < 0) 209 warning("setlogin() failed: %m"); 210 211 #ifndef LETS_GET_SMALL 212 /* 213 * This code assumes that we always get arguments through flags, 214 * never through bits set in some random machine register. 215 */ 216 while ((c = getopt(argc, argv, "sf")) != -1) 217 switch (c) { 218 case 's': 219 requested_transition = single_user; 220 break; 221 case 'f': 222 runcom_mode = FASTBOOT; 223 break; 224 default: 225 warning("unrecognized flag '-%c'", c); 226 break; 227 } 228 229 if (optind != argc) 230 warning("ignoring excess arguments"); 231 #else /* LETS_GET_SMALL */ 232 requested_transition = single_user; 233 #endif /* LETS_GET_SMALL */ 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, 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, 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 sleep (2); /* leave DTR low */ 539 if ((fd = open(name, O_RDWR)) == -1) { 540 stall("can't open %s: %m", name); 541 _exit(1); 542 } 543 if (login_tty(fd) == -1) { 544 stall("can't get %s for controlling terminal: %m", name); 545 _exit(1); 546 } 547 } 548 549 /* 550 * Bring the system up single user. 551 */ 552 state_func_t 553 single_user() 554 { 555 pid_t pid, wpid; 556 int status; 557 sigset_t mask; 558 char *shell = _PATH_BSHELL; 559 char *argv[2]; 560 #ifdef SECURE 561 struct ttyent *typ; 562 struct passwd *pp; 563 static const char banner[] = 564 "Enter root password, or ^D to go multi-user\n"; 565 char *clear, *password; 566 #endif 567 568 /* 569 * If the kernel is in secure mode, downgrade it to insecure mode. 570 */ 571 if (getsecuritylevel() > 0) 572 setsecuritylevel(0); 573 574 if ((pid = fork()) == 0) { 575 /* 576 * Start the single user session. 577 */ 578 setctty(_PATH_CONSOLE); 579 580 #ifdef SECURE 581 /* 582 * Check the root password. 583 * We don't care if the console is 'on' by default; 584 * it's the only tty that can be 'off' and 'secure'. 585 */ 586 typ = getttynam("console"); 587 pp = getpwnam("root"); 588 if (typ && (typ->ty_status & TTY_SECURE) == 0 && pp) { 589 write(2, banner, sizeof banner - 1); 590 for (;;) { 591 clear = getpass("Password:"); 592 if (clear == 0 || *clear == '\0') 593 _exit(0); 594 password = crypt(clear, pp->pw_passwd); 595 bzero(clear, _PASSWORD_LEN); 596 if (strcmp(password, pp->pw_passwd) == 0) 597 break; 598 warning("single-user login failed\n"); 599 } 600 } 601 endttyent(); 602 endpwent(); 603 #endif /* SECURE */ 604 605 #ifdef DEBUGSHELL 606 { 607 char altshell[128], *cp = altshell; 608 int num; 609 610 #define SHREQUEST \ 611 "Enter pathname of shell or RETURN for sh: " 612 (void)write(STDERR_FILENO, 613 SHREQUEST, sizeof(SHREQUEST) - 1); 614 while ((num = read(STDIN_FILENO, cp, 1)) != -1 && 615 num != 0 && *cp != '\n' && cp < &altshell[127]) 616 cp++; 617 *cp = '\0'; 618 if (altshell[0] != '\0') 619 shell = altshell; 620 } 621 #endif /* DEBUGSHELL */ 622 623 /* 624 * Unblock signals. 625 * We catch all the interesting ones, 626 * and those are reset to SIG_DFL on exec. 627 */ 628 sigemptyset(&mask); 629 sigprocmask(SIG_SETMASK, &mask, (sigset_t *) 0); 630 631 /* 632 * Fire off a shell. 633 * If the default one doesn't work, try the Bourne shell. 634 */ 635 argv[0] = "-sh"; 636 argv[1] = 0; 637 setenv("PATH", _PATH_STDPATH, 1); 638 execv(shell, argv); 639 emergency("can't exec %s for single user: %m", shell); 640 execv(_PATH_BSHELL, argv); 641 emergency("can't exec %s for single user: %m", _PATH_BSHELL); 642 sleep(STALL_TIMEOUT); 643 _exit(1); 644 } 645 646 if (pid == -1) { 647 /* 648 * We are seriously hosed. Do our best. 649 */ 650 emergency("can't fork single-user shell, trying again"); 651 while (waitpid(-1, (int *) 0, WNOHANG) > 0) 652 continue; 653 return (state_func_t) single_user; 654 } 655 656 requested_transition = 0; 657 do { 658 if ((wpid = waitpid(-1, &status, WUNTRACED)) != -1) 659 collect_child(wpid); 660 if (wpid == -1) { 661 if (errno == EINTR) 662 continue; 663 warning("wait for single-user shell failed: %m; restarting"); 664 return (state_func_t) single_user; 665 } 666 if (wpid == pid && WIFSTOPPED(status)) { 667 warning("init: shell stopped, restarting\n"); 668 kill(pid, SIGCONT); 669 wpid = -1; 670 } 671 } while (wpid != pid && !requested_transition); 672 673 if (requested_transition) 674 return (state_func_t) requested_transition; 675 676 if (!WIFEXITED(status)) { 677 if (WTERMSIG(status) == SIGKILL) { 678 /* 679 * reboot(8) killed shell? 680 */ 681 warning("single user shell terminated."); 682 sleep(STALL_TIMEOUT); 683 _exit(0); 684 } else { 685 warning("single user shell terminated, restarting"); 686 return (state_func_t) single_user; 687 } 688 } 689 690 runcom_mode = FASTBOOT; 691 #ifndef LETS_GET_SMALL 692 return (state_func_t) runcom; 693 #else /* LETS_GET_SMALL */ 694 return (state_func_t) single_user; 695 #endif /* LETS_GET_SMALL */ 696 } 697 698 #ifndef LETS_GET_SMALL 699 /* 700 * Run the system startup script. 701 */ 702 state_func_t 703 runcom() 704 { 705 pid_t pid, wpid; 706 int status; 707 char *argv[4]; 708 struct sigaction sa; 709 710 if ((pid = fork()) == 0) { 711 sigemptyset(&sa.sa_mask); 712 sa.sa_flags = 0; 713 sa.sa_handler = SIG_IGN; 714 (void) sigaction(SIGTSTP, &sa, (struct sigaction *)0); 715 (void) sigaction(SIGHUP, &sa, (struct sigaction *)0); 716 717 setctty(_PATH_CONSOLE); 718 719 argv[0] = "sh"; 720 argv[1] = _PATH_RUNCOM; 721 argv[2] = runcom_mode == AUTOBOOT ? "autoboot" : 0; 722 argv[3] = 0; 723 724 sigprocmask(SIG_SETMASK, &sa.sa_mask, (sigset_t *) 0); 725 726 execv(_PATH_BSHELL, argv); 727 stall("can't exec %s for %s: %m", _PATH_BSHELL, _PATH_RUNCOM); 728 _exit(1); /* force single user mode */ 729 } 730 731 if (pid == -1) { 732 emergency("can't fork for %s on %s: %m", 733 _PATH_BSHELL, _PATH_RUNCOM); 734 while (waitpid(-1, (int *) 0, WNOHANG) > 0) 735 continue; 736 sleep(STALL_TIMEOUT); 737 return (state_func_t) single_user; 738 } 739 740 /* 741 * Copied from single_user(). This is a bit paranoid. 742 */ 743 do { 744 if ((wpid = waitpid(-1, &status, WUNTRACED)) != -1) 745 collect_child(wpid); 746 if (wpid == -1) { 747 if (errno == EINTR) 748 continue; 749 warning("wait for %s on %s failed: %m; going to single user mode", 750 _PATH_BSHELL, _PATH_RUNCOM); 751 return (state_func_t) single_user; 752 } 753 if (wpid == pid && WIFSTOPPED(status)) { 754 warning("init: %s on %s stopped, restarting\n", 755 _PATH_BSHELL, _PATH_RUNCOM); 756 kill(pid, SIGCONT); 757 wpid = -1; 758 } 759 } while (wpid != pid); 760 761 if (WIFSIGNALED(status) && WTERMSIG(status) == SIGTERM && 762 requested_transition == catatonia) { 763 /* /etc/rc executed /sbin/reboot; wait for the end quietly */ 764 sigset_t s; 765 766 sigfillset(&s); 767 for (;;) 768 sigsuspend(&s); 769 } 770 771 if (!WIFEXITED(status)) { 772 warning("%s on %s terminated abnormally, going to single user mode", 773 _PATH_BSHELL, _PATH_RUNCOM); 774 return (state_func_t) single_user; 775 } 776 777 if (WEXITSTATUS(status)) 778 return (state_func_t) single_user; 779 780 runcom_mode = AUTOBOOT; /* the default */ 781 /* NB: should send a message to the session logger to avoid blocking. */ 782 logwtmp("~", "reboot", ""); 783 return (state_func_t) read_ttys; 784 } 785 786 /* 787 * Open the session database. 788 * 789 * NB: We could pass in the size here; is it necessary? 790 */ 791 int 792 start_session_db() 793 { 794 if (session_db && (*session_db->close)(session_db)) 795 emergency("session database close: %s", strerror(errno)); 796 if ((session_db = dbopen(NULL, O_RDWR, 0, DB_HASH, NULL)) == 0) { 797 emergency("session database open: %s", strerror(errno)); 798 return (1); 799 } 800 return (0); 801 802 } 803 804 /* 805 * Add a new login session. 806 */ 807 void 808 add_session(sp) 809 session_t *sp; 810 { 811 DBT key; 812 DBT data; 813 814 key.data = &sp->se_process; 815 key.size = sizeof sp->se_process; 816 data.data = &sp; 817 data.size = sizeof sp; 818 819 if ((*session_db->put)(session_db, &key, &data, 0)) 820 emergency("insert %d: %s", sp->se_process, strerror(errno)); 821 } 822 823 /* 824 * Delete an old login session. 825 */ 826 void 827 del_session(sp) 828 session_t *sp; 829 { 830 DBT key; 831 832 key.data = &sp->se_process; 833 key.size = sizeof sp->se_process; 834 835 if ((*session_db->del)(session_db, &key, 0)) 836 emergency("delete %d: %s", sp->se_process, strerror(errno)); 837 } 838 839 /* 840 * Look up a login session by pid. 841 */ 842 session_t * 843 #ifdef __STDC__ 844 find_session(pid_t pid) 845 #else 846 find_session(pid) 847 pid_t pid; 848 #endif 849 { 850 DBT key; 851 DBT data; 852 session_t *ret; 853 854 key.data = &pid; 855 key.size = sizeof pid; 856 if ((*session_db->get)(session_db, &key, &data, 0) != 0) 857 return 0; 858 bcopy(data.data, (char *)&ret, sizeof(ret)); 859 return ret; 860 } 861 862 /* 863 * Construct an argument vector from a command line. 864 */ 865 char ** 866 construct_argv(command) 867 char *command; 868 { 869 register int argc = 0; 870 register char **argv = (char **) malloc(((strlen(command) + 1) / 2 + 1) 871 * sizeof (char *)); 872 static const char separators[] = " \t"; 873 874 if ((argv[argc++] = strtok(command, separators)) == 0) 875 return 0; 876 while (argv[argc++] = strtok((char *) 0, separators)) 877 continue; 878 return argv; 879 } 880 881 /* 882 * Deallocate a session descriptor. 883 */ 884 void 885 free_session(sp) 886 register session_t *sp; 887 { 888 free(sp->se_device); 889 if (sp->se_getty) { 890 free(sp->se_getty); 891 free(sp->se_getty_argv); 892 } 893 if (sp->se_window) { 894 free(sp->se_window); 895 free(sp->se_window_argv); 896 } 897 free(sp); 898 } 899 900 /* 901 * Allocate a new session descriptor. 902 */ 903 session_t * 904 new_session(sprev, session_index, typ) 905 session_t *sprev; 906 int session_index; 907 register struct ttyent *typ; 908 { 909 register session_t *sp; 910 911 if ((typ->ty_status & TTY_ON) == 0 || 912 typ->ty_name == 0 || 913 typ->ty_getty == 0) 914 return 0; 915 916 sp = (session_t *) malloc(sizeof (session_t)); 917 bzero(sp, sizeof *sp); 918 919 sp->se_index = session_index; 920 921 sp->se_device = malloc(sizeof(_PATH_DEV) + strlen(typ->ty_name)); 922 (void) sprintf(sp->se_device, "%s%s", _PATH_DEV, typ->ty_name); 923 924 if (setupargv(sp, typ) == 0) { 925 free_session(sp); 926 return (0); 927 } 928 929 sp->se_next = 0; 930 if (sprev == 0) { 931 sessions = sp; 932 sp->se_prev = 0; 933 } else { 934 sprev->se_next = sp; 935 sp->se_prev = sprev; 936 } 937 938 return sp; 939 } 940 941 /* 942 * Calculate getty and if useful window argv vectors. 943 */ 944 int 945 setupargv(sp, typ) 946 session_t *sp; 947 struct ttyent *typ; 948 { 949 950 if (sp->se_getty) { 951 free(sp->se_getty); 952 free(sp->se_getty_argv); 953 } 954 sp->se_getty = malloc(strlen(typ->ty_getty) + strlen(typ->ty_name) + 2); 955 (void) sprintf(sp->se_getty, "%s %s", typ->ty_getty, typ->ty_name); 956 sp->se_getty_argv = construct_argv(sp->se_getty); 957 if (sp->se_getty_argv == 0) { 958 warning("can't parse getty for port %s", sp->se_device); 959 free(sp->se_getty); 960 sp->se_getty = 0; 961 return (0); 962 } 963 if (typ->ty_window) { 964 if (sp->se_window) 965 free(sp->se_window); 966 sp->se_window = strdup(typ->ty_window); 967 sp->se_window_argv = construct_argv(sp->se_window); 968 if (sp->se_window_argv == 0) { 969 warning("can't parse window for port %s", 970 sp->se_device); 971 free(sp->se_window); 972 sp->se_window = 0; 973 return (0); 974 } 975 } 976 return (1); 977 } 978 979 /* 980 * Walk the list of ttys and create sessions for each active line. 981 */ 982 state_func_t 983 read_ttys() 984 { 985 int session_index = 0; 986 register session_t *sp, *snext; 987 register struct ttyent *typ; 988 989 /* 990 * Destroy any previous session state. 991 * There shouldn't be any, but just in case... 992 */ 993 for (sp = sessions; sp; sp = snext) { 994 if (sp->se_process) 995 clear_session_logs(sp); 996 snext = sp->se_next; 997 free_session(sp); 998 } 999 sessions = 0; 1000 if (start_session_db()) 1001 return (state_func_t) single_user; 1002 1003 /* 1004 * Allocate a session entry for each active port. 1005 * Note that sp starts at 0. 1006 */ 1007 while (typ = getttyent()) 1008 if (snext = new_session(sp, ++session_index, typ)) 1009 sp = snext; 1010 1011 endttyent(); 1012 1013 return (state_func_t) multi_user; 1014 } 1015 1016 /* 1017 * Start a window system running. 1018 */ 1019 void 1020 start_window_system(sp) 1021 session_t *sp; 1022 { 1023 pid_t pid; 1024 sigset_t mask; 1025 1026 if ((pid = fork()) == -1) { 1027 emergency("can't fork for window system on port %s: %m", 1028 sp->se_device); 1029 /* hope that getty fails and we can try again */ 1030 return; 1031 } 1032 1033 if (pid) 1034 return; 1035 1036 sigemptyset(&mask); 1037 sigprocmask(SIG_SETMASK, &mask, (sigset_t *) 0); 1038 1039 if (setsid() < 0) 1040 emergency("setsid failed (window) %m"); 1041 1042 execv(sp->se_window_argv[0], sp->se_window_argv); 1043 stall("can't exec window system '%s' for port %s: %m", 1044 sp->se_window_argv[0], sp->se_device); 1045 _exit(1); 1046 } 1047 1048 /* 1049 * Start a login session running. 1050 */ 1051 pid_t 1052 start_getty(sp) 1053 session_t *sp; 1054 { 1055 pid_t pid; 1056 sigset_t mask; 1057 time_t current_time = time((time_t *) 0); 1058 1059 /* 1060 * fork(), not vfork() -- we can't afford to block. 1061 */ 1062 if ((pid = fork()) == -1) { 1063 emergency("can't fork for getty on port %s: %m", sp->se_device); 1064 return -1; 1065 } 1066 1067 if (pid) 1068 return pid; 1069 1070 if (current_time > sp->se_started && 1071 current_time - sp->se_started < GETTY_SPACING) { 1072 warning("getty repeating too quickly on port %s, sleeping", 1073 sp->se_device); 1074 sleep((unsigned) GETTY_SLEEP); 1075 } 1076 1077 if (sp->se_window) { 1078 start_window_system(sp); 1079 sleep(WINDOW_WAIT); 1080 } 1081 1082 sigemptyset(&mask); 1083 sigprocmask(SIG_SETMASK, &mask, (sigset_t *) 0); 1084 1085 execv(sp->se_getty_argv[0], sp->se_getty_argv); 1086 stall("can't exec getty '%s' for port %s: %m", 1087 sp->se_getty_argv[0], sp->se_device); 1088 _exit(1); 1089 } 1090 #endif /* LETS_GET_SMALL */ 1091 1092 /* 1093 * Collect exit status for a child. 1094 * If an exiting login, start a new login running. 1095 */ 1096 void 1097 #ifdef __STDC__ 1098 collect_child(pid_t pid) 1099 #else 1100 collect_child(pid) 1101 pid_t pid; 1102 #endif 1103 { 1104 #ifndef LETS_GET_SMALL 1105 register session_t *sp, *sprev, *snext; 1106 1107 if (! sessions) 1108 return; 1109 1110 if (! (sp = find_session(pid))) 1111 return; 1112 1113 clear_session_logs(sp); 1114 del_session(sp); 1115 sp->se_process = 0; 1116 1117 if (sp->se_flags & SE_SHUTDOWN) { 1118 if (sprev = sp->se_prev) 1119 sprev->se_next = sp->se_next; 1120 else 1121 sessions = sp->se_next; 1122 if (snext = sp->se_next) 1123 snext->se_prev = sp->se_prev; 1124 free_session(sp); 1125 return; 1126 } 1127 1128 if ((pid = start_getty(sp)) == -1) { 1129 /* serious trouble */ 1130 requested_transition = clean_ttys; 1131 return; 1132 } 1133 1134 sp->se_process = pid; 1135 sp->se_started = time((time_t *) 0); 1136 add_session(sp); 1137 #endif /* LETS_GET_SMALL */ 1138 } 1139 1140 /* 1141 * Catch a signal and request a state transition. 1142 */ 1143 void 1144 transition_handler(sig) 1145 int sig; 1146 { 1147 1148 switch (sig) { 1149 #ifndef LETS_GET_SMALL 1150 case SIGHUP: 1151 requested_transition = clean_ttys; 1152 break; 1153 case SIGTERM: 1154 requested_transition = death; 1155 break; 1156 case SIGTSTP: 1157 requested_transition = catatonia; 1158 break; 1159 #endif /* LETS_GET_SMALL */ 1160 default: 1161 requested_transition = 0; 1162 break; 1163 } 1164 } 1165 1166 #ifndef LETS_GET_SMALL 1167 /* 1168 * Take the system multiuser. 1169 */ 1170 state_func_t 1171 multi_user() 1172 { 1173 pid_t pid; 1174 register session_t *sp; 1175 1176 requested_transition = 0; 1177 1178 /* 1179 * If the administrator has not set the security level to -1 1180 * to indicate that the kernel should not run multiuser in secure 1181 * mode, and the run script has not set a higher level of security 1182 * than level 1, then put the kernel into secure mode. 1183 */ 1184 if (getsecuritylevel() == 0) 1185 setsecuritylevel(1); 1186 1187 for (sp = sessions; sp; sp = sp->se_next) { 1188 if (sp->se_process) 1189 continue; 1190 if ((pid = start_getty(sp)) == -1) { 1191 /* serious trouble */ 1192 requested_transition = clean_ttys; 1193 break; 1194 } 1195 sp->se_process = pid; 1196 sp->se_started = time((time_t *) 0); 1197 add_session(sp); 1198 } 1199 1200 while (!requested_transition) 1201 if ((pid = waitpid(-1, (int *) 0, 0)) != -1) 1202 collect_child(pid); 1203 1204 return (state_func_t) requested_transition; 1205 } 1206 1207 /* 1208 * This is an n-squared algorithm. We hope it isn't run often... 1209 */ 1210 state_func_t 1211 clean_ttys() 1212 { 1213 register session_t *sp, *sprev; 1214 register struct ttyent *typ; 1215 register int session_index = 0; 1216 register int devlen; 1217 1218 devlen = sizeof(_PATH_DEV) - 1; 1219 while (typ = getttyent()) { 1220 ++session_index; 1221 1222 for (sprev = 0, sp = sessions; sp; sprev = sp, sp = sp->se_next) 1223 if (strcmp(typ->ty_name, sp->se_device + devlen) == 0) 1224 break; 1225 1226 if (sp) { 1227 if (sp->se_index != session_index) { 1228 warning("port %s changed utmp index from %d to %d", 1229 sp->se_device, sp->se_index, 1230 session_index); 1231 sp->se_index = session_index; 1232 } 1233 if ((typ->ty_status & TTY_ON) == 0 || 1234 typ->ty_getty == 0) { 1235 sp->se_flags |= SE_SHUTDOWN; 1236 kill(sp->se_process, SIGHUP); 1237 continue; 1238 } 1239 sp->se_flags &= ~SE_SHUTDOWN; 1240 if (setupargv(sp, typ) == 0) { 1241 warning("can't parse getty for port %s", 1242 sp->se_device); 1243 sp->se_flags |= SE_SHUTDOWN; 1244 kill(sp->se_process, SIGHUP); 1245 } 1246 continue; 1247 } 1248 1249 new_session(sprev, session_index, typ); 1250 } 1251 1252 endttyent(); 1253 1254 return (state_func_t) multi_user; 1255 } 1256 1257 /* 1258 * Block further logins. 1259 */ 1260 state_func_t 1261 catatonia() 1262 { 1263 register session_t *sp; 1264 1265 for (sp = sessions; sp; sp = sp->se_next) 1266 sp->se_flags |= SE_SHUTDOWN; 1267 1268 return (state_func_t) multi_user; 1269 } 1270 #endif /* LETS_GET_SMALL */ 1271 1272 /* 1273 * Note SIGALRM. 1274 */ 1275 void 1276 alrm_handler(sig) 1277 int sig; 1278 { 1279 clang = 1; 1280 } 1281 1282 #ifndef LETS_GET_SMALL 1283 /* 1284 * Bring the system down to single user. 1285 */ 1286 state_func_t 1287 death() 1288 { 1289 register session_t *sp; 1290 register int i; 1291 pid_t pid; 1292 static const int death_sigs[3] = { SIGHUP, SIGTERM, SIGKILL }; 1293 1294 for (sp = sessions; sp; sp = sp->se_next) 1295 sp->se_flags |= SE_SHUTDOWN; 1296 1297 /* NB: should send a message to the session logger to avoid blocking. */ 1298 logwtmp("~", "shutdown", ""); 1299 1300 for (i = 0; i < 3; ++i) { 1301 if (kill(-1, death_sigs[i]) == -1 && errno == ESRCH) 1302 return (state_func_t) single_user; 1303 1304 clang = 0; 1305 alarm(DEATH_WATCH); 1306 do 1307 if ((pid = waitpid(-1, (int *)0, 0)) != -1) 1308 collect_child(pid); 1309 while (clang == 0 && errno != ECHILD); 1310 1311 if (errno == ECHILD) 1312 return (state_func_t) single_user; 1313 } 1314 1315 warning("some processes would not die; ps axl advised"); 1316 1317 return (state_func_t) single_user; 1318 } 1319 #endif /* LETS_GET_SMALL */ 1320