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