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