1/* $NetBSD: init.c,v 1.102 2011/08/28 10:13:03 christos 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. Neither the name of the University nor the names of its contributors 19 * may be used to endorse or promote products derived from this software 20 * without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 */ 34 35#include <sys/cdefs.h> 36#ifndef lint 37__COPYRIGHT("@(#) Copyright (c) 1991, 1993\ 38 The Regents of the University of California. All rights reserved."); 39#endif /* not lint */ 40 41#ifndef lint 42#if 0 43static char sccsid[] = "@(#)init.c 8.2 (Berkeley) 4/28/95"; 44#else 45__RCSID("$NetBSD: init.c,v 1.102 2011/08/28 10:13:03 christos Exp $"); 46#endif 47#endif /* not lint */ 48 49#include <sys/param.h> 50#include <sys/sysctl.h> 51#include <sys/wait.h> 52#include <sys/mman.h> 53#include <sys/stat.h> 54#include <sys/mount.h> 55#include <machine/cpu.h> 56 57#include <db.h> 58#include <errno.h> 59#include <fcntl.h> 60#include <signal.h> 61#include <stdio.h> 62#include <stdlib.h> 63#include <string.h> 64#include <syslog.h> 65#include <time.h> 66#include <ttyent.h> 67#include <unistd.h> 68#include <util.h> 69#include <paths.h> 70#include <err.h> 71 72#include <stdarg.h> 73 74#ifdef SECURE 75#include <pwd.h> 76#endif 77 78#include "pathnames.h" 79 80#define XSTR(x) #x 81#define STR(x) XSTR(x) 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 92static const struct timespec dtrtime = {.tv_sec = 0, .tv_nsec = 250000}; 93 94#if defined(RESCUEDIR) 95#define INIT_BSHELL RESCUEDIR "/sh" 96#define INIT_MOUNT_MFS RESCUEDIR "/mount_mfs" 97#define INIT_PATH RESCUEDIR ":" _PATH_STDPATH 98#else 99#define INIT_BSHELL _PATH_BSHELL 100#define INIT_MOUNT_MFS "/sbin/mount_mfs" 101#define INIT_PATH _PATH_STDPATH 102#endif 103 104static void handle(sig_t, ...); 105static void delset(sigset_t *, ...); 106 107static void stall(const char *, ...) __printflike(1, 2); 108static void warning(const char *, ...) __printflike(1, 2); 109static void emergency(const char *, ...) __printflike(1, 2); 110__dead static void disaster(int); 111static void badsys(int); 112 113/* 114 * We really need a recursive typedef... 115 * The following at least guarantees that the return type of (*state_t)() 116 * is sufficiently wide to hold a function pointer. 117 */ 118typedef long (*state_func_t)(void); 119typedef state_func_t (*state_t)(void); 120 121#define DEATH 'd' 122#define SINGLE_USER 's' 123#define RUNCOM 'r' 124#define READ_TTYS 't' 125#define MULTI_USER 'm' 126#define CLEAN_TTYS 'T' 127#define CATATONIA 'c' 128 129static state_func_t single_user(void); 130#ifndef LETS_GET_SMALL 131static state_func_t runcom(void); 132static state_func_t read_ttys(void); 133static state_func_t multi_user(void); 134static state_func_t clean_ttys(void); 135static state_func_t catatonia(void); 136static state_func_t death(void); 137#endif 138 139static enum { AUTOBOOT, FASTBOOT } runcom_mode = AUTOBOOT; 140 141static void transition(state_t); 142static void setctty(const char *); 143 144typedef struct init_session { 145 int se_index; /* index of entry in ttys file */ 146 pid_t se_process; /* controlling process */ 147 struct timeval se_started; /* used to avoid thrashing */ 148 int se_flags; /* status of session */ 149#define SE_SHUTDOWN 0x1 /* session won't be restarted */ 150#define SE_PRESENT 0x2 /* session is in /etc/ttys */ 151 char *se_device; /* filename of port */ 152 char *se_getty; /* what to run on that port */ 153 char **se_getty_argv; /* pre-parsed argument array */ 154 char *se_window; /* window system (started only once) */ 155 char **se_window_argv; /* pre-parsed argument array */ 156 struct init_session *se_prev; 157 struct init_session *se_next; 158} session_t; 159 160static void collect_child(pid_t, int); 161static int clang; 162static void transition_handler(int); 163static void alrm_handler(int); 164static int has_securelevel(void); 165static int securelevel_present; 166 167#ifndef LETS_GET_SMALL 168static int do_setttyent(void); 169static void start_window_system(session_t *); 170static char **construct_argv(char *); 171static int setupargv(session_t *, struct ttyent *); 172static pid_t start_getty(session_t *); 173static void free_session(session_t *); 174static session_t *new_session(session_t *, int, struct ttyent *); 175static session_t *sessions; 176static void setsecuritylevel(int); 177static int getsecuritylevel(void); 178static int start_session_db(void); 179static void add_session(session_t *); 180static void del_session(session_t *); 181static session_t *find_session(pid_t); 182static DB *session_db; 183static state_t requested_transition = runcom; 184 185static void clear_session_logs(session_t *, int); 186static state_func_t runetcrc(int); 187#ifdef SUPPORT_UTMPX 188static struct timeval boot_time; 189static state_t current_state = death; 190static void session_utmpx(const session_t *, int); 191static void make_utmpx(const char *, const char *, int, pid_t, 192 const struct timeval *, int); 193static char get_runlevel(const state_t); 194static void utmpx_set_runlevel(char, char); 195#endif 196 197#ifdef CHROOT 198static int did_multiuser_chroot = 0; 199static char rootdir[PATH_MAX]; 200static int shouldchroot(void); 201static int createsysctlnode(void); 202#endif /* CHROOT */ 203 204#else /* LETS_GET_SMALL */ 205static state_t requested_transition = single_user; 206#endif /* !LETS_GET_SMALL */ 207 208#ifdef MFS_DEV_IF_NO_CONSOLE 209 210static int mfs_dev(void); 211 212#endif 213 214/* 215 * The mother of all processes. 216 */ 217int 218main(int argc, char **argv) 219{ 220 struct sigaction sa; 221 sigset_t mask; 222#ifndef LETS_GET_SMALL 223 int c; 224 225#ifdef SUPPORT_UTMPX 226 (void)gettimeofday(&boot_time, NULL); 227#endif /* SUPPORT_UTMPX */ 228 229 /* Dispose of random users. */ 230 if (getuid() != 0) { 231 errno = EPERM; 232 err(1, NULL); 233 } 234 235 /* System V users like to reexec init. */ 236 if (getpid() != 1) 237 errx(1, "already running"); 238#endif 239 240 /* 241 * Create an initial session. 242 */ 243 if (setsid() < 0) 244 warn("initial setsid() failed"); 245 246 /* 247 * Establish an initial user so that programs running 248 * single user do not freak out and die (like passwd). 249 */ 250 if (setlogin("root") < 0) 251 warn("setlogin() failed"); 252 253 254#ifdef MFS_DEV_IF_NO_CONSOLE 255 if (mfs_dev() == -1) 256 requested_transition = single_user; 257#endif 258 259#ifndef LETS_GET_SMALL 260 /* 261 * Note that this does NOT open a file... 262 * Does 'init' deserve its own facility number? 263 */ 264 openlog("init", LOG_CONS, LOG_AUTH); 265#endif /* LETS_GET_SMALL */ 266 267 268#ifndef LETS_GET_SMALL 269 /* 270 * This code assumes that we always get arguments through flags, 271 * never through bits set in some random machine register. 272 */ 273 while ((c = getopt(argc, argv, "sf")) != -1) 274 switch (c) { 275 case 's': 276 requested_transition = single_user; 277 break; 278 case 'f': 279 runcom_mode = FASTBOOT; 280 break; 281 default: 282 warning("unrecognized flag `%c'", c); 283 break; 284 } 285 286 if (optind != argc) 287 warning("ignoring excess arguments"); 288#else /* LETS_GET_SMALL */ 289 requested_transition = single_user; 290#endif /* LETS_GET_SMALL */ 291 292 /* 293 * We catch or block signals rather than ignore them, 294 * so that they get reset on exec. 295 */ 296 handle(badsys, SIGSYS, 0); 297 handle(disaster, SIGABRT, SIGFPE, SIGILL, SIGSEGV, 298 SIGBUS, SIGXCPU, SIGXFSZ, 0); 299 handle(transition_handler, SIGHUP, SIGTERM, SIGTSTP, 0); 300 handle(alrm_handler, SIGALRM, 0); 301 (void)sigfillset(&mask); 302 delset(&mask, SIGABRT, SIGFPE, SIGILL, SIGSEGV, SIGBUS, SIGSYS, 303 SIGXCPU, SIGXFSZ, SIGHUP, SIGTERM, SIGTSTP, SIGALRM, 0); 304 (void)sigprocmask(SIG_SETMASK, &mask, NULL); 305 (void)sigemptyset(&sa.sa_mask); 306 sa.sa_flags = 0; 307 sa.sa_handler = SIG_IGN; 308 (void)sigaction(SIGTTIN, &sa, NULL); 309 (void)sigaction(SIGTTOU, &sa, NULL); 310 311 /* 312 * Paranoia. 313 */ 314 (void)close(0); 315 (void)close(1); 316 (void)close(2); 317 318#if !defined(LETS_GET_SMALL) && defined(CHROOT) 319 /* Create "init.root" sysctl node. */ 320 (void)createsysctlnode(); 321#endif /* !LETS_GET_SMALL && CHROOT*/ 322 323 /* 324 * Securelevel might not be supported by the kernel. Query for it, and 325 * set a variable indicating whether we should attempt anything with it 326 * or not. 327 */ 328 securelevel_present = has_securelevel(); 329 330 /* 331 * Start the state machine. 332 */ 333 transition(requested_transition); 334 335 /* 336 * Should never reach here. 337 */ 338 return 1; 339} 340 341/* 342 * Associate a function with a signal handler. 343 */ 344static void 345handle(sig_t handler, ...) 346{ 347 int sig; 348 struct sigaction sa; 349 sigset_t mask_everything; 350 va_list ap; 351 352 va_start(ap, handler); 353 354 sa.sa_handler = handler; 355 (void)sigfillset(&mask_everything); 356 357 while ((sig = va_arg(ap, int)) != 0) { 358 sa.sa_mask = mask_everything; 359 /* XXX SA_RESTART? */ 360 sa.sa_flags = sig == SIGCHLD ? SA_NOCLDSTOP : 0; 361 (void)sigaction(sig, &sa, NULL); 362 } 363 va_end(ap); 364} 365 366/* 367 * Delete a set of signals from a mask. 368 */ 369static void 370delset(sigset_t *maskp, ...) 371{ 372 int sig; 373 va_list ap; 374 375 va_start(ap, maskp); 376 377 while ((sig = va_arg(ap, int)) != 0) 378 (void)sigdelset(maskp, sig); 379 va_end(ap); 380} 381 382#if 0 /* Enable to get error messages from init ! */ 383#define vsyslog(level, fmt, ap) print_console(level, fmt, ap) 384#define closelog() 385 386static void 387print_console(int level, const char *message, va_list ap) 388{ 389 /* 390 * XXX: syslog seems to just plain not work in console-only 391 * XXX: situation... that should be fixed. Let's leave this 392 * XXX: note + code here in case someone gets in trouble and 393 * XXX: wants to debug. -- Jachym Holecek <freza@liberouter.org> 394 */ 395 char errbuf[1024]; 396 int fd, len; 397 398 /* We can't do anything on errors, anyway... */ 399 fd = open(_PATH_CONSOLE, O_WRONLY); 400 if (fd == -1) 401 return ; 402 403 /* %m will get lost... */ 404 len = vsnprintf(errbuf, sizeof(errbuf), message, ap); 405 (void)write(fd, (void *)errbuf, len); 406 (void)close(fd); 407} 408#endif 409 410/* 411 * Log a message and sleep for a while (to give someone an opportunity 412 * to read it and to save log or hardcopy output if the problem is chronic). 413 * NB: should send a message to the session logger to avoid blocking. 414 */ 415static void 416stall(const char *message, ...) 417{ 418 va_list ap; 419 420 va_start(ap, message); 421 vsyslog(LOG_ALERT, message, ap); 422 va_end(ap); 423 closelog(); 424 (void)sleep(STALL_TIMEOUT); 425} 426 427/* 428 * Like stall(), but doesn't sleep. 429 * If cpp had variadic macros, the two functions could be #defines for another. 430 * NB: should send a message to the session logger to avoid blocking. 431 */ 432static void 433warning(const char *message, ...) 434{ 435 va_list ap; 436 437 va_start(ap, message); 438 vsyslog(LOG_ALERT, message, ap); 439 va_end(ap); 440 closelog(); 441} 442 443/* 444 * Log an emergency message. 445 * NB: should send a message to the session logger to avoid blocking. 446 */ 447static void 448emergency(const char *message, ...) 449{ 450 va_list ap; 451 452 va_start(ap, message); 453 vsyslog(LOG_EMERG, message, ap); 454 va_end(ap); 455 closelog(); 456} 457 458/* 459 * Catch a SIGSYS signal. 460 * 461 * These may arise if a system does not support sysctl. 462 * We tolerate up to 25 of these, then throw in the towel. 463 */ 464static void 465badsys(int sig) 466{ 467 static int badcount = 0; 468 469 if (badcount++ < 25) 470 return; 471 disaster(sig); 472} 473 474/* 475 * Catch an unexpected signal. 476 */ 477static void 478disaster(int sig) 479{ 480 481 emergency("fatal signal: %s", strsignal(sig)); 482 (void)sleep(STALL_TIMEOUT); 483 _exit(sig); /* reboot */ 484} 485 486/* 487 * Check if securelevel is present. 488 */ 489static int 490has_securelevel(void) 491{ 492#ifdef KERN_SECURELVL 493 int name[2], curlevel; 494 size_t len; 495 496 name[0] = CTL_KERN; 497 name[1] = KERN_SECURELVL; 498 len = sizeof curlevel; 499 if (sysctl(name, 2, &curlevel, &len, NULL, 0) == -1) { 500 /* If it doesn't exist, it's okay. */ 501 if (errno == ENOENT) 502 return 0; 503 } 504 return 1; 505#else 506 return 0; 507#endif 508} 509 510/* 511 * Get the security level of the kernel. 512 */ 513static int 514getsecuritylevel(void) 515{ 516#ifdef KERN_SECURELVL 517 int name[2], curlevel; 518 size_t len; 519 520 if (!securelevel_present) 521 return -1; 522 523 name[0] = CTL_KERN; 524 name[1] = KERN_SECURELVL; 525 len = sizeof curlevel; 526 if (sysctl(name, 2, &curlevel, &len, NULL, 0) == -1) { 527 emergency("cannot get kernel security level: %m"); 528 return -1; 529 } 530 return curlevel; 531#else 532 return -1; 533#endif 534} 535 536/* 537 * Set the security level of the kernel. 538 */ 539static void 540setsecuritylevel(int newlevel) 541{ 542#ifdef KERN_SECURELVL 543 int name[2], curlevel; 544 545 if (!securelevel_present) 546 return; 547 548 curlevel = getsecuritylevel(); 549 if (newlevel == curlevel) 550 return; 551 name[0] = CTL_KERN; 552 name[1] = KERN_SECURELVL; 553 if (sysctl(name, 2, NULL, NULL, &newlevel, sizeof newlevel) == -1) { 554 emergency("cannot change kernel security level from" 555 " %d to %d: %m", curlevel, newlevel); 556 return; 557 } 558#ifdef SECURE 559 warning("kernel security level changed from %d to %d", 560 curlevel, newlevel); 561#endif 562#endif 563} 564 565/* 566 * Change states in the finite state machine. 567 * The initial state is passed as an argument. 568 */ 569static void 570transition(state_t s) 571{ 572 573 if (s == NULL) 574 return; 575 for (;;) { 576#ifdef SUPPORT_UTMPX 577#ifndef LETS_GET_SMALL 578 utmpx_set_runlevel(get_runlevel(current_state), 579 get_runlevel(s)); 580 current_state = s; 581#endif 582#endif 583 s = (state_t)(*s)(); 584 } 585} 586 587#ifndef LETS_GET_SMALL 588/* 589 * Close out the accounting files for a login session. 590 * NB: should send a message to the session logger to avoid blocking. 591 */ 592static void 593clear_session_logs(session_t *sp, int status) 594{ 595#if defined(SUPPORT_UTMP) || defined(SUPPORT_UTMPX) 596 char *line = sp->se_device + sizeof(_PATH_DEV) - 1; 597#endif 598 599#ifdef SUPPORT_UTMPX 600 if (logoutx(line, status, DEAD_PROCESS)) 601 logwtmpx(line, "", "", status, DEAD_PROCESS); 602#endif 603#ifdef SUPPORT_UTMP 604 if (logout(line)) 605 logwtmp(line, "", ""); 606#endif 607} 608#endif 609 610/* 611 * Start a session and allocate a controlling terminal. 612 * Only called by children of init after forking. 613 */ 614static void 615setctty(const char *name) 616{ 617 int fd; 618 619 (void)revoke(name); 620 (void)nanosleep(&dtrtime, NULL); /* leave DTR low for a bit */ 621 if ((fd = open(name, O_RDWR)) == -1) { 622 stall("can't open %s: %m", name); 623 _exit(1); 624 } 625 if (login_tty(fd) == -1) { 626 stall("can't get %s for controlling terminal: %m", name); 627 _exit(2); 628 } 629} 630 631/* 632 * Bring the system up single user. 633 */ 634static state_func_t 635single_user(void) 636{ 637 pid_t pid, wpid; 638 int status; 639 int from_securitylevel; 640 sigset_t mask; 641 struct sigaction sa, satstp, sahup; 642#ifdef ALTSHELL 643 const char *shell = INIT_BSHELL; 644#endif 645 const char *argv[2]; 646#ifdef SECURE 647 struct ttyent *typ; 648 struct passwd *pp; 649 char *clear, *password; 650#endif 651#ifdef ALTSHELL 652 char altshell[128]; 653#endif /* ALTSHELL */ 654 655#if !defined(LETS_GET_SMALL) && defined(CHROOT) 656 /* Clear previous idea, just in case. */ 657 did_multiuser_chroot = 0; 658#endif /* !LETS_GET_SMALL && CHROOT */ 659 660 /* 661 * If the kernel is in secure mode, downgrade it to insecure mode. 662 */ 663 from_securitylevel = getsecuritylevel(); 664 if (from_securitylevel > 0) 665 setsecuritylevel(0); 666 667 (void)sigemptyset(&sa.sa_mask); 668 sa.sa_flags = 0; 669 sa.sa_handler = SIG_IGN; 670 (void)sigaction(SIGTSTP, &sa, &satstp); 671 (void)sigaction(SIGHUP, &sa, &sahup); 672 if ((pid = fork()) == 0) { 673 /* 674 * Start the single user session. 675 */ 676 if (access(_PATH_CONSTTY, F_OK) == 0) 677 setctty(_PATH_CONSTTY); 678 else 679 setctty(_PATH_CONSOLE); 680 681#ifdef SECURE 682 /* 683 * Check the root password. 684 * We don't care if the console is 'on' by default; 685 * it's the only tty that can be 'off' and 'secure'. 686 */ 687 typ = getttynam("console"); 688 pp = getpwnam("root"); 689 if (typ && (from_securitylevel >=2 || (typ->ty_status 690 & TTY_SECURE) == 0) && pp && *pp->pw_passwd != '\0') { 691 (void)fprintf(stderr, 692 "Enter root password, or ^D to go multi-user\n"); 693 for (;;) { 694 clear = getpass("Password:"); 695 if (clear == 0 || *clear == '\0') 696 _exit(0); 697 password = crypt(clear, pp->pw_passwd); 698 (void)memset(clear, 0, _PASSWORD_LEN); 699 if (strcmp(password, pp->pw_passwd) == 0) 700 break; 701 warning("single-user login failed"); 702 } 703 } 704 (void)endttyent(); 705 endpwent(); 706#endif /* SECURE */ 707 708#ifdef ALTSHELL 709 (void)fprintf(stderr, 710 "Enter pathname of shell or RETURN for %s: ", shell); 711 if (fgets(altshell, sizeof(altshell), stdin) == NULL) { 712 altshell[0] = '\0'; 713 } else { 714 /* nuke \n */ 715 char *p; 716 717 if ((p = strchr(altshell, '\n')) != NULL) 718 *p = '\0'; 719 } 720 721 if (altshell[0]) 722 shell = altshell; 723#endif /* ALTSHELL */ 724 725 /* 726 * Unblock signals. 727 * We catch all the interesting ones, 728 * and those are reset to SIG_DFL on exec. 729 */ 730 (void)sigemptyset(&mask); 731 (void)sigprocmask(SIG_SETMASK, &mask, NULL); 732 733 /* 734 * Fire off a shell. 735 * If the default one doesn't work, try the Bourne shell. 736 */ 737 argv[0] = "-sh"; 738 argv[1] = 0; 739 (void)setenv("PATH", INIT_PATH, 1); 740#ifdef ALTSHELL 741 if (altshell[0]) 742 argv[0] = altshell; 743 (void)execv(shell, __UNCONST(argv)); 744 emergency("can't exec `%s' for single user: %m", shell); 745 argv[0] = "-sh"; 746#endif /* ALTSHELL */ 747 (void)execv(INIT_BSHELL, __UNCONST(argv)); 748 emergency("can't exec `%s' for single user: %m", INIT_BSHELL); 749 (void)sleep(STALL_TIMEOUT); 750 _exit(3); 751 } 752 753 if (pid == -1) { 754 /* 755 * We are seriously hosed. Do our best. 756 */ 757 emergency("can't fork single-user shell: %m, trying again"); 758 while (waitpid(-1, NULL, WNOHANG) > 0) 759 continue; 760 (void)sigaction(SIGTSTP, &satstp, NULL); 761 (void)sigaction(SIGHUP, &sahup, NULL); 762 return (state_func_t)single_user; 763 } 764 765 requested_transition = 0; 766 do { 767 if ((wpid = waitpid(-1, &status, WUNTRACED)) != -1) 768 collect_child(wpid, status); 769 if (wpid == -1) { 770 if (errno == EINTR) 771 continue; 772 warning("wait for single-user shell failed: %m; " 773 "restarting"); 774 return (state_func_t)single_user; 775 } 776 if (wpid == pid && WIFSTOPPED(status)) { 777 warning("shell stopped, restarting"); 778 (void)kill(pid, SIGCONT); 779 wpid = -1; 780 } 781 } while (wpid != pid && !requested_transition); 782 783 if (requested_transition) { 784 (void)sigaction(SIGTSTP, &satstp, NULL); 785 (void)sigaction(SIGHUP, &sahup, NULL); 786 return (state_func_t)requested_transition; 787 } 788 789 if (WIFSIGNALED(status)) { 790 if (WTERMSIG(status) == SIGKILL) { 791 /* executed /sbin/reboot; wait for the end quietly */ 792 sigset_t s; 793 794 (void)sigfillset(&s); 795 for (;;) 796 (void)sigsuspend(&s); 797 } else { 798 warning("single user shell terminated (%x), restarting", 799 status); 800 (void)sigaction(SIGTSTP, &satstp, NULL); 801 (void)sigaction(SIGHUP, &sahup, NULL); 802 return (state_func_t)single_user; 803 } 804 } 805 806 runcom_mode = FASTBOOT; 807 (void)sigaction(SIGTSTP, &satstp, NULL); 808 (void)sigaction(SIGHUP, &sahup, NULL); 809#ifndef LETS_GET_SMALL 810 return (state_func_t)runcom; 811#else /* LETS_GET_SMALL */ 812 return (state_func_t)single_user; 813#endif /* LETS_GET_SMALL */ 814} 815 816#ifndef LETS_GET_SMALL 817 818/* ARGSUSED */ 819static state_func_t 820runetcrc(int trychroot) 821{ 822 pid_t pid, wpid; 823 int status; 824 const char *argv[4]; 825 struct sigaction sa; 826 827 switch ((pid = fork())) { 828 case 0: 829 (void)sigemptyset(&sa.sa_mask); 830 sa.sa_flags = 0; 831 sa.sa_handler = SIG_IGN; 832 (void)sigaction(SIGTSTP, &sa, NULL); 833 (void)sigaction(SIGHUP, &sa, NULL); 834 835 setctty(_PATH_CONSOLE); 836 837 argv[0] = "sh"; 838 argv[1] = _PATH_RUNCOM; 839 argv[2] = (runcom_mode == AUTOBOOT ? "autoboot" : 0); 840 argv[3] = 0; 841 842 (void)sigprocmask(SIG_SETMASK, &sa.sa_mask, NULL); 843 844#ifdef CHROOT 845 if (trychroot) 846 if (chroot(rootdir) != 0) { 847 warning("failed to chroot to `%s': %m", 848 rootdir); 849 _exit(4); /* force single user mode */ 850 } 851#endif /* CHROOT */ 852 853 (void)execv(INIT_BSHELL, __UNCONST(argv)); 854 stall("can't exec `%s' for `%s': %m", INIT_BSHELL, _PATH_RUNCOM); 855 _exit(5); /* force single user mode */ 856 /*NOTREACHED*/ 857 case -1: 858 emergency("can't fork for `%s' on `%s': %m", INIT_BSHELL, 859 _PATH_RUNCOM); 860 while (waitpid(-1, NULL, WNOHANG) > 0) 861 continue; 862 (void)sleep(STALL_TIMEOUT); 863 return (state_func_t)single_user; 864 default: 865 break; 866 } 867 868 /* 869 * Copied from single_user(). This is a bit paranoid. 870 */ 871 do { 872 if ((wpid = waitpid(-1, &status, WUNTRACED)) != -1) 873 collect_child(wpid, status); 874 if (wpid == -1) { 875 if (errno == EINTR) 876 continue; 877 warning("wait for `%s' on `%s' failed: %m; going to " 878 "single user mode", INIT_BSHELL, _PATH_RUNCOM); 879 return (state_func_t)single_user; 880 } 881 if (wpid == pid && WIFSTOPPED(status)) { 882 warning("`%s' on `%s' stopped, restarting", 883 INIT_BSHELL, _PATH_RUNCOM); 884 (void)kill(pid, SIGCONT); 885 wpid = -1; 886 } 887 } while (wpid != pid); 888 889 if (WIFSIGNALED(status) && WTERMSIG(status) == SIGTERM && 890 requested_transition == catatonia) { 891 /* /etc/rc executed /sbin/reboot; wait for the end quietly */ 892 sigset_t s; 893 894 (void)sigfillset(&s); 895 for (;;) 896 (void)sigsuspend(&s); 897 } 898 899 if (!WIFEXITED(status)) { 900 warning("`%s' on `%s' terminated abnormally, going to " 901 "single user mode", INIT_BSHELL, _PATH_RUNCOM); 902 return (state_func_t)single_user; 903 } 904 905 if (WEXITSTATUS(status)) 906 return (state_func_t)single_user; 907 908 return (state_func_t)read_ttys; 909} 910 911/* 912 * Run the system startup script. 913 */ 914static state_func_t 915runcom(void) 916{ 917 state_func_t next_step; 918 919 /* Run /etc/rc and choose next state depending on the result. */ 920 next_step = runetcrc(0); 921 if (next_step != (state_func_t)read_ttys) 922 return (state_func_t)next_step; 923 924#ifdef CHROOT 925 /* 926 * If init.root sysctl does not point to "/", we'll chroot and run 927 * The Real(tm) /etc/rc now. Global variable rootdir will tell us 928 * where to go. 929 */ 930 if (shouldchroot()) { 931 next_step = runetcrc(1); 932 if (next_step != (state_func_t)read_ttys) 933 return (state_func_t)next_step; 934 935 did_multiuser_chroot = 1; 936 } else { 937 did_multiuser_chroot = 0; 938 } 939#endif /* CHROOT */ 940 941 /* 942 * Regardless of whether in chroot or not, we booted successfuly. 943 * It's time to spawn gettys (ie. next_step's value at this point). 944 */ 945 runcom_mode = AUTOBOOT; /* the default */ 946 /* NB: should send a message to the session logger to avoid blocking. */ 947#ifdef SUPPORT_UTMPX 948 logwtmpx("~", "reboot", "", 0, INIT_PROCESS); 949#endif 950#ifdef SUPPORT_UTMP 951 logwtmp("~", "reboot", ""); 952#endif 953 return (state_func_t)read_ttys; 954} 955 956/* 957 * Open the session database. 958 * 959 * NB: We could pass in the size here; is it necessary? 960 */ 961static int 962start_session_db(void) 963{ 964 965 if (session_db && (*session_db->close)(session_db)) 966 emergency("session database close: %m"); 967 if ((session_db = dbopen(NULL, O_RDWR, 0, DB_HASH, NULL)) == 0) { 968 emergency("session database open: %m"); 969 return 1; 970 } 971 return 0; 972 973} 974 975/* 976 * Add a new login session. 977 */ 978static void 979add_session(session_t *sp) 980{ 981 DBT key; 982 DBT data; 983 984 if (session_db == NULL) 985 return; 986 987 key.data = &sp->se_process; 988 key.size = sizeof sp->se_process; 989 data.data = &sp; 990 data.size = sizeof sp; 991 992 if ((*session_db->put)(session_db, &key, &data, 0)) 993 emergency("insert %d: %m", sp->se_process); 994#ifdef SUPPORT_UTMPX 995 session_utmpx(sp, 1); 996#endif 997} 998 999/* 1000 * Delete an old login session. 1001 */ 1002static void 1003del_session(session_t *sp) 1004{ 1005 DBT key; 1006 1007 key.data = &sp->se_process; 1008 key.size = sizeof sp->se_process; 1009 1010 if ((*session_db->del)(session_db, &key, 0)) 1011 emergency("delete %d: %m", sp->se_process); 1012#ifdef SUPPORT_UTMPX 1013 session_utmpx(sp, 0); 1014#endif 1015} 1016 1017/* 1018 * Look up a login session by pid. 1019 */ 1020static session_t * 1021find_session(pid_t pid) 1022{ 1023 DBT key; 1024 DBT data; 1025 session_t *ret; 1026 1027 if (session_db == NULL) 1028 return NULL; 1029 1030 key.data = &pid; 1031 key.size = sizeof pid; 1032 if ((*session_db->get)(session_db, &key, &data, 0) != 0) 1033 return 0; 1034 (void)memmove(&ret, data.data, sizeof(ret)); 1035 return ret; 1036} 1037 1038/* 1039 * Construct an argument vector from a command line. 1040 */ 1041static char ** 1042construct_argv(char *command) 1043{ 1044 int argc = 0; 1045 char **argv = malloc(((strlen(command) + 1) / 2 + 1) * sizeof (char *)); 1046 static const char separators[] = " \t"; 1047 1048 if (argv == NULL) 1049 return NULL; 1050 1051 if ((argv[argc++] = strtok(command, separators)) == 0) { 1052 free(argv); 1053 return NULL; 1054 } 1055 while ((argv[argc++] = strtok(NULL, separators)) != NULL) 1056 continue; 1057 return argv; 1058} 1059 1060/* 1061 * Deallocate a session descriptor. 1062 */ 1063static void 1064free_session(session_t *sp) 1065{ 1066 1067 free(sp->se_device); 1068 if (sp->se_getty) { 1069 free(sp->se_getty); 1070 free(sp->se_getty_argv); 1071 } 1072 if (sp->se_window) { 1073 free(sp->se_window); 1074 free(sp->se_window_argv); 1075 } 1076 free(sp); 1077} 1078 1079/* 1080 * Allocate a new session descriptor. 1081 */ 1082static session_t * 1083new_session(session_t *sprev, int session_index, struct ttyent *typ) 1084{ 1085 session_t *sp; 1086 1087 if ((typ->ty_status & TTY_ON) == 0 || typ->ty_name == NULL || 1088 typ->ty_getty == NULL) 1089 return NULL; 1090 1091 sp = malloc(sizeof (session_t)); 1092 if (sp == NULL) 1093 return NULL; 1094 (void)memset(sp, 0, sizeof *sp); 1095 1096 sp->se_flags = SE_PRESENT; 1097 sp->se_index = session_index; 1098 1099 (void)asprintf(&sp->se_device, "%s%s", _PATH_DEV, typ->ty_name); 1100 if (!sp->se_device) { 1101 free(sp); 1102 return NULL; 1103 } 1104 1105 if (setupargv(sp, typ) == 0) { 1106 free_session(sp); 1107 return NULL; 1108 } 1109 1110 sp->se_next = NULL; 1111 if (sprev == NULL) { 1112 sessions = sp; 1113 sp->se_prev = NULL; 1114 } else { 1115 sprev->se_next = sp; 1116 sp->se_prev = sprev; 1117 } 1118 1119 return sp; 1120} 1121 1122/* 1123 * Calculate getty and if useful window argv vectors. 1124 */ 1125static int 1126setupargv(session_t *sp, struct ttyent *typ) 1127{ 1128 1129 if (sp->se_getty) { 1130 free(sp->se_getty); 1131 free(sp->se_getty_argv); 1132 } 1133 (void)asprintf(&sp->se_getty, "%s %s", typ->ty_getty, typ->ty_name); 1134 if (!sp->se_getty) 1135 return 0; 1136 sp->se_getty_argv = construct_argv(sp->se_getty); 1137 if (sp->se_getty_argv == NULL) { 1138 warning("can't parse getty for port `%s'", sp->se_device); 1139 free(sp->se_getty); 1140 sp->se_getty = NULL; 1141 return 0; 1142 } 1143 if (typ->ty_window) { 1144 if (sp->se_window) 1145 free(sp->se_window); 1146 sp->se_window = strdup(typ->ty_window); 1147 sp->se_window_argv = construct_argv(sp->se_window); 1148 if (sp->se_window_argv == NULL) { 1149 warning("can't parse window for port `%s'", 1150 sp->se_device); 1151 free(sp->se_window); 1152 sp->se_window = NULL; 1153 return 0; 1154 } 1155 } 1156 return 1; 1157} 1158 1159/* 1160 * Walk the list of ttys and create sessions for each active line. 1161 */ 1162static state_func_t 1163read_ttys(void) 1164{ 1165 int session_index = 0; 1166 session_t *sp, *snext; 1167 struct ttyent *typ; 1168 1169#ifdef SUPPORT_UTMPX 1170 if (sessions == NULL) { 1171 struct stat st; 1172 1173 make_utmpx("", BOOT_MSG, BOOT_TIME, 0, &boot_time, 0); 1174 1175 /* 1176 * If wtmpx is not empty, pick the down time from there 1177 */ 1178 if (stat(_PATH_WTMPX, &st) != -1 && st.st_size != 0) { 1179 struct timeval down_time; 1180 1181 TIMESPEC_TO_TIMEVAL(&down_time, 1182 st.st_atime > st.st_mtime ? 1183 &st.st_atimespec : &st.st_mtimespec); 1184 make_utmpx("", DOWN_MSG, DOWN_TIME, 0, &down_time, 0); 1185 } 1186 } 1187#endif 1188 /* 1189 * Destroy any previous session state. 1190 * There shouldn't be any, but just in case... 1191 */ 1192 for (sp = sessions; sp; sp = snext) { 1193#ifndef LETS_GET_SMALL 1194 if (sp->se_process) 1195 clear_session_logs(sp, 0); 1196#endif 1197 snext = sp->se_next; 1198 free_session(sp); 1199 } 1200 sessions = NULL; 1201 1202 if (start_session_db()) { 1203 warning("start_session_db failed, death"); 1204#ifdef CHROOT 1205 /* If /etc/rc ran in chroot, we want to kill any survivors. */ 1206 if (did_multiuser_chroot) 1207 return (state_func_t)death; 1208 else 1209#endif /* CHROOT */ 1210 return (state_func_t)single_user; 1211 } 1212 1213 (void)do_setttyent(); 1214 1215 /* 1216 * Allocate a session entry for each active port. 1217 * Note that sp starts at 0. 1218 */ 1219 while ((typ = getttyent()) != NULL) 1220 if ((snext = new_session(sp, ++session_index, typ)) != NULL) 1221 sp = snext; 1222 (void)endttyent(); 1223 1224 return (state_func_t)multi_user; 1225} 1226 1227/* 1228 * Start a window system running. 1229 */ 1230static void 1231start_window_system(session_t *sp) 1232{ 1233 pid_t pid; 1234 sigset_t mask; 1235 1236 if ((pid = fork()) == -1) { 1237 emergency("can't fork for window system on port `%s': %m", 1238 sp->se_device); 1239 /* hope that getty fails and we can try again */ 1240 return; 1241 } 1242 1243 if (pid) 1244 return; 1245 1246 (void)sigemptyset(&mask); 1247 (void)sigprocmask(SIG_SETMASK, &mask, NULL); 1248 1249 if (setsid() < 0) 1250 emergency("setsid failed (window): %m"); 1251 1252 (void)execv(sp->se_window_argv[0], sp->se_window_argv); 1253 stall("can't exec window system `%s' for port `%s': %m", 1254 sp->se_window_argv[0], sp->se_device); 1255 _exit(6); 1256} 1257 1258/* 1259 * Start a login session running. 1260 */ 1261static pid_t 1262start_getty(session_t *sp) 1263{ 1264 pid_t pid; 1265 sigset_t mask; 1266 time_t current_time = time(NULL); 1267 1268 /* 1269 * fork(), not vfork() -- we can't afford to block. 1270 */ 1271 if ((pid = fork()) == -1) { 1272 emergency("can't fork for getty on port `%s': %m", 1273 sp->se_device); 1274 return -1; 1275 } 1276 1277 if (pid) 1278 return pid; 1279 1280#ifdef CHROOT 1281 /* If /etc/rc did proceed inside chroot, we have to try as well. */ 1282 if (did_multiuser_chroot) 1283 if (chroot(rootdir) != 0) { 1284 stall("can't chroot getty `%s' inside `%s': %m", 1285 sp->se_getty_argv[0], rootdir); 1286 _exit(7); 1287 } 1288#endif /* CHROOT */ 1289 1290 if (current_time > sp->se_started.tv_sec && 1291 current_time - sp->se_started.tv_sec < GETTY_SPACING) { 1292 warning("getty repeating too quickly on port `%s', sleeping", 1293 sp->se_device); 1294 (void)sleep(GETTY_SLEEP); 1295 } 1296 1297 if (sp->se_window) { 1298 start_window_system(sp); 1299 (void)sleep(WINDOW_WAIT); 1300 } 1301 1302 (void)sigemptyset(&mask); 1303 (void)sigprocmask(SIG_SETMASK, &mask, (sigset_t *) 0); 1304 1305 (void)execv(sp->se_getty_argv[0], sp->se_getty_argv); 1306 stall("can't exec getty `%s' for port `%s': %m", 1307 sp->se_getty_argv[0], sp->se_device); 1308 _exit(8); 1309 /*NOTREACHED*/ 1310} 1311#ifdef SUPPORT_UTMPX 1312static void 1313session_utmpx(const session_t *sp, int add) 1314{ 1315 const char *name = sp->se_getty ? sp->se_getty : 1316 (sp->se_window ? sp->se_window : ""); 1317 const char *line = sp->se_device + sizeof(_PATH_DEV) - 1; 1318 1319 make_utmpx(name, line, add ? LOGIN_PROCESS : DEAD_PROCESS, 1320 sp->se_process, &sp->se_started, sp->se_index); 1321} 1322 1323static void 1324make_utmpx(const char *name, const char *line, int type, pid_t pid, 1325 const struct timeval *tv, int session) 1326{ 1327 struct utmpx ut; 1328 const char *eline; 1329 1330 (void)memset(&ut, 0, sizeof(ut)); 1331 (void)strlcpy(ut.ut_name, name, sizeof(ut.ut_name)); 1332 ut.ut_type = type; 1333 (void)strlcpy(ut.ut_line, line, sizeof(ut.ut_line)); 1334 ut.ut_pid = pid; 1335 if (tv) 1336 ut.ut_tv = *tv; 1337 else 1338 (void)gettimeofday(&ut.ut_tv, NULL); 1339 ut.ut_session = session; 1340 1341 eline = line + strlen(line); 1342 if ((size_t)(eline - line) >= sizeof(ut.ut_id)) 1343 line = eline - sizeof(ut.ut_id); 1344 (void)strncpy(ut.ut_id, line, sizeof(ut.ut_id)); 1345 1346 if (pututxline(&ut) == NULL) 1347 warning("can't add utmpx record for `%s': %m", ut.ut_line); 1348 endutxent(); 1349} 1350 1351static char 1352get_runlevel(const state_t s) 1353{ 1354 if (s == (state_t)single_user) 1355 return SINGLE_USER; 1356 if (s == (state_t)runcom) 1357 return RUNCOM; 1358 if (s == (state_t)read_ttys) 1359 return READ_TTYS; 1360 if (s == (state_t)multi_user) 1361 return MULTI_USER; 1362 if (s == (state_t)clean_ttys) 1363 return CLEAN_TTYS; 1364 if (s == (state_t)catatonia) 1365 return CATATONIA; 1366 return DEATH; 1367} 1368 1369static void 1370utmpx_set_runlevel(char old, char new) 1371{ 1372 struct utmpx ut; 1373 1374 /* 1375 * Don't record any transitions until we did the first transition 1376 * to read ttys, which is when we are guaranteed to have a read-write 1377 * /var. Perhaps use a different variable for this? 1378 */ 1379 if (sessions == NULL) 1380 return; 1381 1382 (void)memset(&ut, 0, sizeof(ut)); 1383 (void)snprintf(ut.ut_line, sizeof(ut.ut_line), RUNLVL_MSG, new); 1384 ut.ut_type = RUN_LVL; 1385 (void)gettimeofday(&ut.ut_tv, NULL); 1386 ut.ut_exit.e_exit = old; 1387 ut.ut_exit.e_termination = new; 1388 if (pututxline(&ut) == NULL) 1389 warning("can't add utmpx record for `runlevel': %m"); 1390 endutxent(); 1391} 1392#endif /* SUPPORT_UTMPX */ 1393 1394#endif /* LETS_GET_SMALL */ 1395 1396/* 1397 * Collect exit status for a child. 1398 * If an exiting login, start a new login running. 1399 */ 1400static void 1401collect_child(pid_t pid, int status) 1402{ 1403#ifndef LETS_GET_SMALL 1404 session_t *sp, *sprev, *snext; 1405 1406 if (! sessions) 1407 return; 1408 1409 if ((sp = find_session(pid)) == NULL) 1410 return; 1411 1412 clear_session_logs(sp, status); 1413 del_session(sp); 1414 sp->se_process = 0; 1415 1416 if (sp->se_flags & SE_SHUTDOWN) { 1417 if ((sprev = sp->se_prev) != NULL) 1418 sprev->se_next = sp->se_next; 1419 else 1420 sessions = sp->se_next; 1421 if ((snext = sp->se_next) != NULL) 1422 snext->se_prev = sp->se_prev; 1423 free_session(sp); 1424 return; 1425 } 1426 1427 if ((pid = start_getty(sp)) == -1) { 1428 /* serious trouble */ 1429 requested_transition = clean_ttys; 1430 return; 1431 } 1432 1433 sp->se_process = pid; 1434 (void)gettimeofday(&sp->se_started, NULL); 1435 add_session(sp); 1436#endif /* LETS_GET_SMALL */ 1437} 1438 1439/* 1440 * Catch a signal and request a state transition. 1441 */ 1442static void 1443transition_handler(int sig) 1444{ 1445 1446 switch (sig) { 1447#ifndef LETS_GET_SMALL 1448 case SIGHUP: 1449 requested_transition = clean_ttys; 1450 break; 1451 case SIGTERM: 1452 requested_transition = death; 1453 break; 1454 case SIGTSTP: 1455 requested_transition = catatonia; 1456 break; 1457#endif /* LETS_GET_SMALL */ 1458 default: 1459 requested_transition = 0; 1460 break; 1461 } 1462} 1463 1464#ifndef LETS_GET_SMALL 1465/* 1466 * Take the system multiuser. 1467 */ 1468static state_func_t 1469multi_user(void) 1470{ 1471 pid_t pid; 1472 int status; 1473 session_t *sp; 1474 1475 requested_transition = 0; 1476 1477 /* 1478 * If the administrator has not set the security level to -1 1479 * to indicate that the kernel should not run multiuser in secure 1480 * mode, and the run script has not set a higher level of security 1481 * than level 1, then put the kernel into secure mode. 1482 */ 1483 if (getsecuritylevel() == 0) 1484 setsecuritylevel(1); 1485 1486 for (sp = sessions; sp; sp = sp->se_next) { 1487 if (sp->se_process) 1488 continue; 1489 if ((pid = start_getty(sp)) == -1) { 1490 /* serious trouble */ 1491 requested_transition = clean_ttys; 1492 break; 1493 } 1494 sp->se_process = pid; 1495 (void)gettimeofday(&sp->se_started, NULL); 1496 add_session(sp); 1497 } 1498 1499 while (!requested_transition) 1500 if ((pid = waitpid(-1, &status, 0)) != -1) 1501 collect_child(pid, status); 1502 1503 return (state_func_t)requested_transition; 1504} 1505 1506/* 1507 * This is an n-squared algorithm. We hope it isn't run often... 1508 */ 1509static state_func_t 1510clean_ttys(void) 1511{ 1512 session_t *sp, *sprev; 1513 struct ttyent *typ; 1514 int session_index = 0; 1515 int devlen; 1516 1517 for (sp = sessions; sp; sp = sp->se_next) 1518 sp->se_flags &= ~SE_PRESENT; 1519 1520 (void)do_setttyent(); 1521 1522 devlen = sizeof(_PATH_DEV) - 1; 1523 while ((typ = getttyent()) != NULL) { 1524 ++session_index; 1525 1526 for (sprev = 0, sp = sessions; sp; sprev = sp, sp = sp->se_next) 1527 if (strcmp(typ->ty_name, sp->se_device + devlen) == 0) 1528 break; 1529 1530 if (sp) { 1531 sp->se_flags |= SE_PRESENT; 1532 if (sp->se_index != session_index) { 1533 warning("port `%s' changed utmp index from " 1534 "%d to %d", sp->se_device, sp->se_index, 1535 session_index); 1536 sp->se_index = session_index; 1537 } 1538 if ((typ->ty_status & TTY_ON) == 0 || 1539 typ->ty_getty == 0) { 1540 sp->se_flags |= SE_SHUTDOWN; 1541 if (sp->se_process != 0) 1542 (void)kill(sp->se_process, SIGHUP); 1543 continue; 1544 } 1545 sp->se_flags &= ~SE_SHUTDOWN; 1546 if (setupargv(sp, typ) == 0) { 1547 warning("can't parse getty for port `%s'", 1548 sp->se_device); 1549 sp->se_flags |= SE_SHUTDOWN; 1550 if (sp->se_process != 0) 1551 (void)kill(sp->se_process, SIGHUP); 1552 } 1553 continue; 1554 } 1555 1556 (void)new_session(sprev, session_index, typ); 1557 } 1558 1559 (void)endttyent(); 1560 1561 for (sp = sessions; sp; sp = sp->se_next) 1562 if ((sp->se_flags & SE_PRESENT) == 0) { 1563 sp->se_flags |= SE_SHUTDOWN; 1564 if (sp->se_process != 0) 1565 (void)kill(sp->se_process, SIGHUP); 1566 } 1567 1568 return (state_func_t)multi_user; 1569} 1570 1571/* 1572 * Block further logins. 1573 */ 1574static state_func_t 1575catatonia(void) 1576{ 1577 session_t *sp; 1578 1579 for (sp = sessions; sp; sp = sp->se_next) 1580 sp->se_flags |= SE_SHUTDOWN; 1581 1582 return (state_func_t)multi_user; 1583} 1584#endif /* LETS_GET_SMALL */ 1585 1586/* 1587 * Note SIGALRM. 1588 */ 1589static void 1590/*ARGSUSED*/ 1591alrm_handler(int sig) 1592{ 1593 1594 clang = 1; 1595} 1596 1597#ifndef LETS_GET_SMALL 1598/* 1599 * Bring the system down to single user. 1600 */ 1601static state_func_t 1602death(void) 1603{ 1604 session_t *sp; 1605 int i, status; 1606 pid_t pid; 1607 static const int death_sigs[3] = { SIGHUP, SIGTERM, SIGKILL }; 1608 1609 for (sp = sessions; sp; sp = sp->se_next) 1610 sp->se_flags |= SE_SHUTDOWN; 1611 1612 /* NB: should send a message to the session logger to avoid blocking. */ 1613#ifdef SUPPORT_UTMPX 1614 logwtmpx("~", "shutdown", "", 0, INIT_PROCESS); 1615#endif 1616#ifdef SUPPORT_UTMP 1617 logwtmp("~", "shutdown", ""); 1618#endif 1619 1620 for (i = 0; i < 3; ++i) { 1621 if (kill(-1, death_sigs[i]) == -1 && errno == ESRCH) 1622 return (state_func_t)single_user; 1623 1624 clang = 0; 1625 (void)alarm(DEATH_WATCH); 1626 do 1627 if ((pid = waitpid(-1, &status, 0)) != -1) 1628 collect_child(pid, status); 1629 while (clang == 0 && errno != ECHILD); 1630 1631 if (errno == ECHILD) 1632 return (state_func_t)single_user; 1633 } 1634 1635 warning("some processes would not die; ps axl advised"); 1636 1637 return (state_func_t)single_user; 1638} 1639#endif /* LETS_GET_SMALL */ 1640 1641#ifdef MFS_DEV_IF_NO_CONSOLE 1642 1643static int 1644mfs_dev(void) 1645{ 1646 /* 1647 * We cannot print errors so we bail out silently... 1648 */ 1649 pid_t pid; 1650 int status; 1651 1652 /* If we have /dev/console, assume all is OK */ 1653 if (access(_PATH_CONSOLE, F_OK) == 0) 1654 return 0; 1655 1656#if 0 /* Useful for testing MAKEDEV */ 1657 /* Mount an mfs over /mnt so we can create a console entry */ 1658 switch ((pid = fork())) { 1659 case 0: 1660 (void)execl(INIT_MOUNT_MFS, "mount_mfs", 1661 "-b", "4096", "-f", "512", 1662 "-s", 64, "-n", 10, 1663 "-p", "0755", 1664 "swap", "/mnt", NULL); 1665 _exit(9); 1666 /*NOTREACHED*/ 1667 1668 case -1: 1669 return(-1); 1670 1671 default: 1672 if (waitpid(pid, &status, 0) == -1) 1673 return(-1); 1674 if (status != 0) 1675 return(-1); 1676 break; 1677 } 1678 1679 { 1680 dev_t dev; 1681#ifdef CPU_CONSDEV 1682 static int name[2] = { CTL_MACHDEP, CPU_CONSDEV }; 1683 size_t olen; 1684 olen = sizeof(dev); 1685 if (sysctl(name, sizeof(name) / sizeof(name[0]), &dev, &olen, 1686 NULL, 0) == -1) 1687#endif 1688 dev = makedev(0, 0); 1689 1690 /* Make a console for us, so we can see things happening */ 1691 if (mknod("/mnt/console", 0666 | S_IFCHR, dev) == -1) 1692 return(-1); 1693 (void)freopen("/mnt/console", "a", stderr); 1694 } 1695 1696#endif 1697 1698 /* Run the makedev script to create devices */ 1699 switch ((pid = fork())) { 1700 case 0: 1701 (void)dup2(2, 1); /* Give the script stdout */ 1702 if (chdir("/dev") == 0) 1703 (void)execl(INIT_BSHELL, "sh", 1704 access("./MAKEDEV", X_OK) == 0 1705 ? "./MAKEDEV" : "/etc/MAKEDEV", 1706 "-MM", "init", NULL); 1707 _exit(10); 1708 /* NOTREACHED */ 1709 1710 case -1: 1711 break; 1712 1713 default: 1714 if (waitpid(pid, &status, 0) == -1) 1715 break; 1716 if (status != 0) 1717 warn("MAKEDEV exit status %d\n", status); 1718 /* 1719 * If /dev/console got created, then return 0 1720 * regardless of MAKEDEV exit status. 1721 */ 1722 if (access(_PATH_CONSOLE, F_OK) == 0) 1723 return 0; 1724 _exit(11); 1725 } 1726 warn("Unable to run MAKEDEV"); 1727 _exit(12); 1728} 1729#endif 1730 1731#ifndef LETS_GET_SMALL 1732static int 1733do_setttyent(void) 1734{ 1735 (void)endttyent(); 1736#ifdef CHROOT 1737 if (did_multiuser_chroot) { 1738 char path[PATH_MAX]; 1739 1740 (void)snprintf(path, sizeof(path), "%s/%s", rootdir, _PATH_TTYS); 1741 1742 return setttyentpath(path); 1743 } else 1744#endif /* CHROOT */ 1745 return setttyent(); 1746} 1747#endif 1748 1749#if !defined(LETS_GET_SMALL) && defined(CHROOT) 1750 1751static int 1752createsysctlnode() 1753{ 1754 struct sysctlnode node; 1755 int mib[2]; 1756 size_t len; 1757 1758 /* 1759 * Create top-level dynamic sysctl node. Its child nodes will only 1760 * be readable by the superuser, since regular mortals should not 1761 * care ("Sssh, it's a secret!"). 1762 */ 1763 len = sizeof(struct sysctlnode); 1764 mib[0] = CTL_CREATE; 1765 1766 (void)memset(&node, 0, len); 1767 node.sysctl_flags = SYSCTL_VERSION | CTLFLAG_READWRITE | 1768 CTLFLAG_PRIVATE | CTLTYPE_NODE; 1769 node.sysctl_num = CTL_CREATE; 1770 (void)snprintf(node.sysctl_name, SYSCTL_NAMELEN, "init"); 1771 if (sysctl(&mib[0], 1, &node, &len, &node, len) == -1) { 1772 warning("could not create init node: %m"); 1773 return -1; 1774 } 1775 1776 /* 1777 * Create second level dynamic node capable of holding pathname. 1778 * Provide "/" as the default value. 1779 */ 1780 len = sizeof(struct sysctlnode); 1781 mib[0] = node.sysctl_num; 1782 mib[1] = CTL_CREATE; 1783 1784 (void)memset(&node, 0, len); 1785 node.sysctl_flags = SYSCTL_VERSION | CTLFLAG_READWRITE | 1786 CTLTYPE_STRING | CTLFLAG_OWNDATA; 1787 node.sysctl_size = _POSIX_PATH_MAX; 1788 node.sysctl_data = __UNCONST("/"); 1789 node.sysctl_num = CTL_CREATE; 1790 (void)snprintf(node.sysctl_name, SYSCTL_NAMELEN, "root"); 1791 if (sysctl(&mib[0], 2, NULL, NULL, &node, len) == -1) { 1792 warning("could not create init.root node: %m"); 1793 return -1; 1794 } 1795 1796 return 0; 1797} 1798 1799static int 1800shouldchroot(void) 1801{ 1802 struct sysctlnode node; 1803 size_t len, cnt; 1804 int mib; 1805 1806 len = sizeof(struct sysctlnode); 1807 1808 if (sysctlbyname("init.root", rootdir, &len, NULL, 0) == -1) { 1809 warning("could not read init.root: %m"); 1810 1811 /* Child killed our node. Recreate it. */ 1812 if (errno == ENOENT) { 1813 /* Destroy whatever is left, recreate from scratch. */ 1814 if (sysctlnametomib("init", &mib, &cnt) != -1) { 1815 (void)memset(&node, 0, sizeof(node)); 1816 node.sysctl_flags = SYSCTL_VERSION; 1817 node.sysctl_num = mib; 1818 mib = CTL_DESTROY; 1819 1820 (void)sysctl(&mib, 1, NULL, NULL, &node, 1821 sizeof(node)); 1822 } 1823 1824 (void)createsysctlnode(); 1825 } 1826 1827 /* We certainly won't chroot. */ 1828 return 0; 1829 } 1830 1831 if (rootdir[len] != '\0' || strlen(rootdir) != len - 1) { 1832 warning("init.root is not a string"); 1833 return 0; 1834 } 1835 1836 if (strcmp(rootdir, "/") == 0) 1837 return 0; 1838 1839 return 1; 1840} 1841 1842#endif /* !LETS_GET_SMALL && CHROOT */ 1843