1: /* 2: * Copyright (c) 1980,1986 Regents of the University of California. 3: * All rights reserved. The Berkeley software License Agreement 4: * specifies the terms and conditions for redistribution. 5: */ 6: 7: #if defined(DOSCCS) && !defined(lint) 8: static char sccsid[] = "@(#)init.c 5.6.4 (2.11BSD) 1999/2/23"; 9: #endif 10: 11: #include <sys/param.h> 12: #include <sys/sysctl.h> 13: #include <signal.h> 14: #include <utmp.h> 15: #include <setjmp.h> 16: #include <sys/reboot.h> 17: #include <errno.h> 18: #include <sys/file.h> 19: #include <ttyent.h> 20: #include <sys/syslog.h> 21: #include <sys/stat.h> 22: #include <paths.h> 23: 24: #define LINSIZ sizeof(wtmp.ut_line) 25: #define CMDSIZ 200 /* max string length for getty or window command*/ 26: #define ALL p = itab; p ; p = p->next 27: #define EVER ;; 28: #define SCPYN(a, b) strncpy(a, b, sizeof(a)) 29: #define SCMPN(a, b) strncmp(a, b, sizeof(a)) 30: 31: char shell[] = _PATH_BSHELL; 32: char minus[] = "-"; 33: char runc[] = "/etc/rc"; 34: char utmpf[] = _PATH_UTMP; 35: char wtmpf[] = _PATH_WTMP; 36: char ctty[] = _PATH_CONSOLE; 37: 38: struct utmp wtmp; 39: struct tab 40: { 41: char line[LINSIZ]; 42: char comn[CMDSIZ]; 43: char xflag; 44: int pid; 45: int wpid; /* window system pid for SIGHUP */ 46: char wcmd[CMDSIZ]; /* command to start window system process */ 47: time_t gettytime; 48: int gettycnt; 49: time_t windtime; 50: int windcnt; 51: struct tab *next; 52: } *itab; 53: 54: int fi; 55: int mergflag; 56: char tty[20]; 57: jmp_buf sjbuf, shutpass; 58: time_t time0; 59: 60: int reset(); 61: int idle(); 62: char *strcpy(), *strcat(); 63: long lseek(); 64: time_t time(); 65: void setsecuritylevel(); 66: int getsecuritylevel(); 67: int badsys(); 68: extern int errno; 69: 70: struct sigvec rvec = { reset, sigmask(SIGHUP), 0 }; 71: 72: 73: #ifdef vax 74: main() 75: { 76: register int r11; /* passed thru from boot */ 77: #else 78: main(argc, argv) 79: char **argv; 80: { 81: #endif 82: int howto, oldhowto; 83: 84: time0 = time(0); 85: #ifdef vax 86: howto = r11; 87: #else 88: #ifdef pdp11 89: if (argc > 1 && argv[1][0] == '-') { 90: howto = atoi(argv[1]+1); 91: bzero(argv[1], strlen(argv[1])); /* keep ps output clean ... */ 92: } else 93: howto = RB_SINGLE; 94: #else 95: if (argc > 1 && argv[1][0] == '-') { 96: char *cp; 97: 98: howto = 0; 99: cp = &argv[1][1]; 100: while (*cp) switch (*cp++) { 101: case 'a': 102: howto |= RB_ASKNAME; 103: break; 104: case 's': 105: howto |= RB_SINGLE; 106: break; 107: } 108: } else { 109: howto = RB_SINGLE; 110: } 111: #endif 112: #endif 113: if (getuid() != 0) 114: exit(1); 115: if (getpid() != 1) 116: exit(1); 117: 118: openlog("init", LOG_CONS|LOG_ODELAY, LOG_AUTH); 119: #ifdef pdp11 120: if (autoconfig(howto) == 0) 121: howto = RB_SINGLE | (howto & RB_AUTODEBUG); 122: #endif 123: signal(SIGSYS, badsys); 124: sigvec(SIGTERM, &rvec, (struct sigvec *)0); 125: signal(SIGTSTP, idle); 126: signal(SIGSTOP, SIG_IGN); 127: signal(SIGTTIN, SIG_IGN); 128: signal(SIGTTOU, SIG_IGN); 129: (void) setjmp(sjbuf); 130: for (EVER) { 131: oldhowto = howto; 132: howto = RB_SINGLE; 133: if (setjmp(shutpass) == 0) 134: shutdown(); 135: if (oldhowto & RB_SINGLE) 136: single(); 137: if (runcom(oldhowto) == 0) 138: continue; 139: merge(); 140: multiple(); 141: } 142: } 143: 144: int shutreset(); 145: 146: shutdown() 147: { 148: register i; 149: register struct tab *p, *p1; 150: 151: close(creat(utmpf, 0644)); 152: signal(SIGHUP, SIG_IGN); 153: for (p = itab; p ; ) { 154: term(p); 155: p1 = p->next; 156: free(p); 157: p = p1; 158: } 159: itab = (struct tab *)0; 160: signal(SIGALRM, shutreset); 161: (void) kill(-1, SIGTERM); /* one chance to catch it */ 162: sleep(5); 163: alarm(30); 164: for (i = 0; i < 5; i++) 165: kill(-1, SIGKILL); 166: while (wait((int *)0) != -1) 167: ; 168: alarm(0); 169: shutend(); 170: } 171: 172: char shutfailm[] = "WARNING: Something is hung (wont die); ps axl advised\n"; 173: 174: shutreset() 175: { 176: int status; 177: 178: if (fork() == 0) { 179: int ct = open(ctty, 1); 180: write(ct, shutfailm, sizeof (shutfailm)); 181: sleep(5); 182: exit(1); 183: } 184: sleep(5); 185: shutend(); 186: longjmp(shutpass, 1); 187: } 188: 189: shutend() 190: { 191: register i, f; 192: 193: signal(SIGALRM, SIG_DFL); 194: for (i = 0; i < 10; i++) 195: close(i); 196: f = open(wtmpf, O_WRONLY|O_APPEND); 197: if (f >= 0) { 198: SCPYN(wtmp.ut_line, "~"); 199: SCPYN(wtmp.ut_name, "shutdown"); 200: SCPYN(wtmp.ut_host, ""); 201: time(&wtmp.ut_time); 202: write(f, (char *)&wtmp, sizeof(wtmp)); 203: close(f); 204: } 205: return (1); 206: } 207: 208: /* 209: * Catch a SIGSYS signal. 210: * 211: * These may arise if a system does not support sysctl. 212: * We tolerate up to 25 of these, then throw in the towel. 213: */ 214: int 215: badsys(sig) 216: int sig; 217: { 218: static int badcount = 0; 219: 220: if (badcount++ < 25) 221: return; 222: syslog(LOG_EMERG, "fatal signal: %d", sig); 223: sleep(30); 224: _exit(sig); 225: } 226: 227: /* 228: * Get the security level of the kernel. 229: */ 230: int 231: getsecuritylevel() 232: { 233: #ifdef KERN_SECURELVL 234: int name[2], curlevel; 235: size_t len; 236: 237: name[0] = CTL_KERN; 238: name[1] = KERN_SECURELVL; 239: len = sizeof curlevel; 240: if (sysctl(name, 2, &curlevel, &len, NULL, 0) == -1) { 241: syslog(LOG_EMERG, "cannot get kernel security level: %s", 242: strerror(errno)); 243: return (-1); 244: } 245: return (curlevel); 246: #else 247: return (-1); 248: #endif 249: } 250: 251: /* 252: * Set the security level of the kernel. 253: */ 254: void 255: setsecuritylevel(newlevel) 256: int newlevel; 257: { 258: #ifdef KERN_SECURELVL 259: int name[2], curlevel; 260: 261: curlevel = getsecuritylevel(); 262: if (newlevel == curlevel) 263: return; 264: name[0] = CTL_KERN; 265: name[1] = KERN_SECURELVL; 266: if (sysctl(name, 2, NULL, NULL, &newlevel, sizeof newlevel) == -1) { 267: syslog(LOG_EMERG, 268: "cannot change kernel security level from %d to %d: %s", 269: curlevel, newlevel, strerror(errno)); 270: return; 271: } 272: syslog(LOG_ALERT, "kernel security level changed from %d to %d", 273: curlevel, newlevel); 274: #endif 275: } 276: 277: single() 278: { 279: register pid; 280: register xpid; 281: int fd; 282: 283: /* 284: * If the kernel is in secure mode, downgrade it to insecure mode. 285: */ 286: if (getsecuritylevel() > 0) 287: setsecuritylevel(0); 288: 289: do { 290: pid = fork(); 291: if (pid == 0) { 292: signal(SIGTERM, SIG_DFL); 293: signal(SIGHUP, SIG_DFL); 294: signal(SIGALRM, SIG_DFL); 295: signal(SIGTSTP, SIG_IGN); 296: fd = open(ctty, O_RDWR, 0); 297: if (fd) 298: dup2(fd, 0); 299: dup2(0, 1); 300: dup2(0, 2); 301: execl(shell, minus, (char *)0); 302: perror(shell); 303: exit(0); 304: } 305: while ((xpid = wait((int *)0)) != pid) 306: if (xpid == -1 && errno == ECHILD) 307: break; 308: } while (xpid == -1); 309: } 310: 311: runcom(oldhowto) 312: int oldhowto; 313: { 314: register pid, f; 315: int status; 316: char *arg1, *arg2; 317: 318: pid = fork(); 319: if (pid == 0) { 320: f = open("/", O_RDONLY); 321: if (f) 322: dup2(f, 0); 323: dup2(0, 1); 324: dup2(0, 2); 325: #ifdef pdp11 326: if (oldhowto & (RB_SINGLE|RB_NOFSCK)) 327: arg1 = "fastboot"; 328: else 329: arg1 = "autoboot"; 330: if (oldhowto & RB_POWRFAIL) 331: arg2 = "powerfail"; 332: else 333: arg2 = (char *)0; 334: execl(shell, shell, runc, arg1, arg2, (char *)0); 335: #else 336: if (oldhowto & RB_SINGLE) 337: execl(shell, shell, runc, (char *)0); 338: else 339: execl(shell, shell, runc, "autoboot", (char *)0); 340: #endif 341: exit(1); 342: } 343: while (wait(&status) != pid) 344: ; 345: if (status) 346: return (0); 347: f = open(wtmpf, O_WRONLY|O_APPEND); 348: if (f >= 0) { 349: SCPYN(wtmp.ut_line, "~"); 350: SCPYN(wtmp.ut_name, "reboot"); 351: SCPYN(wtmp.ut_host, ""); 352: if (time0) { 353: wtmp.ut_time = time0; 354: time0 = 0; 355: } else 356: time(&wtmp.ut_time); 357: write(f, (char *)&wtmp, sizeof(wtmp)); 358: close(f); 359: } 360: return (1); 361: } 362: 363: #ifdef pdp11 364: int merge(); 365: #endif 366: struct sigvec mvec = { merge, sigmask(SIGTERM), 0 }; 367: /* 368: * Multi-user. Listen for users leaving, SIGHUP's 369: * which indicate ttys has changed, and SIGTERM's which 370: * are used to shutdown the system. 371: */ 372: multiple() 373: { 374: register struct tab *p; 375: register pid; 376: long omask; 377: 378: /* 379: * If the administrator has not set the security level to -1 380: * to indicate that the kernel should not run multiuser in secure 381: * mode, and the run script has not set a higher level of security 382: * than level 1, then put the kernel into secure mode. 383: */ 384: if (getsecuritylevel() == 0) 385: setsecuritylevel(1); 386: 387: sigvec(SIGHUP, &mvec, (struct sigvec *)0); 388: for (EVER) { 389: pid = wait((int *)0); 390: if (pid == -1) 391: return; 392: omask = sigblock(sigmask(SIGHUP)); 393: for (ALL) { 394: /* must restart window system BEFORE emulator */ 395: if (p->wpid == pid || p->wpid == -1) 396: wstart(p); 397: if (p->pid == pid || p->pid == -1) { 398: /* disown the window system */ 399: if (p->wpid) 400: kill(p->wpid, SIGHUP); 401: rmut(p); 402: dfork(p); 403: } 404: } 405: sigsetmask(omask); 406: } 407: } 408: 409: /* 410: * Merge current contents of ttys file 411: * into in-core table of configured tty lines. 412: * Entered as signal handler for SIGHUP. 413: */ 414: #define FOUND 1 415: #define CHANGE 2 416: #define WCHANGE 4 417: 418: merge() 419: { 420: register struct tab *p; 421: register struct ttyent *t; 422: register struct tab *p1; 423: 424: for (ALL) 425: p->xflag = 0; 426: setttyent(); 427: while (t = getttyent()) { 428: if ((t->ty_status & TTY_ON) == 0) 429: continue; 430: for (ALL) { 431: if (SCMPN(p->line, t->ty_name)) 432: continue; 433: p->xflag |= FOUND; 434: if (SCMPN(p->comn, t->ty_getty)) { 435: p->xflag |= CHANGE; 436: SCPYN(p->comn, t->ty_getty); 437: } 438: if (SCMPN(p->wcmd, t->ty_window ? t->ty_window : "")) { 439: p->xflag |= WCHANGE|CHANGE; 440: SCPYN(p->wcmd, t->ty_window); 441: } 442: goto contin1; 443: } 444: 445: /* 446: * Make space for a new one 447: */ 448: p1 = (struct tab *)calloc(1, sizeof(*p1)); 449: if (!p1) { 450: syslog(LOG_ERR, "no space for '%s' !?!", t->ty_name); 451: goto contin1; 452: } 453: /* 454: * Put new terminal at the end of the linked list. 455: */ 456: if (itab) { 457: for (p = itab; p->next ; p = p->next) 458: ; 459: p->next = p1; 460: } else 461: itab = p1; 462: 463: p = p1; 464: SCPYN(p->line, t->ty_name); 465: p->xflag |= FOUND|CHANGE; 466: SCPYN(p->comn, t->ty_getty); 467: if (t->ty_window && strcmp(t->ty_window, "") != 0) { 468: p->xflag |= WCHANGE; 469: SCPYN(p->wcmd, t->ty_window); 470: } 471: contin1: 472: ; 473: } 474: endttyent(); 475: p1 = (struct tab *)0; 476: for (ALL) { 477: if ((p->xflag&FOUND) == 0) { 478: term(p); 479: wterm(p); 480: if (p1) 481: p1->next = p->next; 482: else 483: itab = p->next; 484: free(p); 485: p = p1 ? p1 : itab; 486: } else { 487: /* window system should be started first */ 488: if (p->xflag&WCHANGE) { 489: wterm(p); 490: wstart(p); 491: } 492: if (p->xflag&CHANGE) { 493: term(p); 494: dfork(p); 495: } 496: } 497: p1 = p; 498: } 499: } 500: 501: term(p) 502: register struct tab *p; 503: { 504: 505: if (p->pid != 0) { 506: rmut(p); 507: kill(p->pid, SIGKILL); 508: } 509: p->pid = 0; 510: /* send SIGHUP to get rid of connections */ 511: if (p->wpid > 0) 512: kill(p->wpid, SIGHUP); 513: } 514: 515: dfork(p) 516: struct tab *p; 517: { 518: register pid; 519: time_t t; 520: int dowait = 0; 521: 522: time(&t); 523: p->gettycnt++; 524: if ((t - p->gettytime) >= 60) { 525: p->gettytime = t; 526: p->gettycnt = 1; 527: } else if (p->gettycnt >= 5) { 528: dowait = 1; 529: p->gettytime = t; 530: p->gettycnt = 1; 531: } 532: pid = fork(); 533: if (pid == 0) { 534: signal(SIGTERM, SIG_DFL); 535: signal(SIGHUP, SIG_IGN); 536: sigsetmask(0L); /* since can be called from masked code */ 537: if (dowait) { 538: syslog(LOG_ERR, "'%s %s' failing, sleeping", p->comn, p->line); 539: closelog(); 540: sleep(30); 541: } 542: execit(p->comn, p->line); 543: exit(0); 544: } 545: p->pid = pid; 546: } 547: 548: /* 549: * Remove utmp entry. 550: */ 551: rmut(p) 552: register struct tab *p; 553: { 554: register f; 555: int found = 0; 556: static unsigned utmpsize; 557: static struct utmp *utmp; 558: register struct utmp *u; 559: int nutmp; 560: struct stat statbf; 561: 562: f = open(utmpf, O_RDWR); 563: if (f >= 0) { 564: fstat(f, &statbf); 565: if (utmpsize < statbf.st_size) { 566: utmpsize = statbf.st_size + 10 * sizeof(struct utmp); 567: if (utmp) 568: utmp = (struct utmp *)realloc(utmp, utmpsize); 569: else 570: utmp = (struct utmp *)malloc(utmpsize); 571: if (!utmp) 572: syslog(LOG_ERR, "utmp malloc failed"); 573: } 574: if (statbf.st_size && utmp) { 575: nutmp = read(f, utmp, (int)statbf.st_size); 576: nutmp /= sizeof(struct utmp); 577: for (u = utmp ; u < &utmp[nutmp] ; u++) { 578: if (SCMPN(u->ut_line, p->line) || 579: u->ut_name[0]==0) 580: continue; 581: lseek(f, ((long)u)-((long)utmp), L_SET); 582: SCPYN(u->ut_name, ""); 583: SCPYN(u->ut_host, ""); 584: time(&u->ut_time); 585: write(f, (char *)u, sizeof(*u)); 586: found++; 587: } 588: } 589: close(f); 590: } 591: if (found) { 592: f = open(wtmpf, O_WRONLY|O_APPEND); 593: if (f >= 0) { 594: SCPYN(wtmp.ut_line, p->line); 595: SCPYN(wtmp.ut_name, ""); 596: SCPYN(wtmp.ut_host, ""); 597: time(&wtmp.ut_time); 598: write(f, (char *)&wtmp, sizeof(wtmp)); 599: close(f); 600: } 601: /* 602: * After a proper login force reset 603: * of error detection code in dfork. 604: */ 605: p->gettytime = 0; 606: p->windtime = 0; 607: } 608: } 609: 610: reset() 611: { 612: 613: longjmp(sjbuf, 1); 614: } 615: 616: jmp_buf idlebuf; 617: 618: idlehup() 619: { 620: 621: longjmp(idlebuf, 1); 622: } 623: 624: idle() 625: { 626: register struct tab *p; 627: register pid; 628: 629: signal(SIGHUP, idlehup); 630: for (EVER) { 631: if (setjmp(idlebuf)) 632: return; 633: pid = wait((int *) 0); 634: if (pid == -1) { 635: sigpause(0L); 636: continue; 637: } 638: for (ALL) { 639: /* if window system dies, mark it for restart */ 640: if (p->wpid == pid) 641: p->wpid = -1; 642: if (p->pid == pid) { 643: rmut(p); 644: p->pid = -1; 645: } 646: } 647: } 648: } 649: 650: wterm(p) 651: register struct tab *p; 652: { 653: if (p->wpid != 0) { 654: kill(p->wpid, SIGKILL); 655: } 656: p->wpid = 0; 657: } 658: 659: wstart(p) 660: register struct tab *p; 661: { 662: register pid; 663: time_t t; 664: int dowait = 0; 665: 666: time(&t); 667: p->windcnt++; 668: if ((t - p->windtime) >= 60) { 669: p->windtime = t; 670: p->windcnt = 1; 671: } else if (p->windcnt >= 5) { 672: dowait = 1; 673: p->windtime = t; 674: p->windcnt = 1; 675: } 676: 677: pid = fork(); 678: 679: if (pid == 0) { 680: signal(SIGTERM, SIG_DFL); 681: signal(SIGHUP, SIG_IGN); 682: sigsetmask(0L); /* since can be called from masked code */ 683: if (dowait) { 684: syslog(LOG_ERR, "'%s %s' failing, sleeping", p->wcmd, p->line); 685: closelog(); 686: sleep(30); 687: } 688: execit(p->wcmd, p->line); 689: exit(0); 690: } 691: p->wpid = pid; 692: } 693: 694: #define NARGS 20 /* must be at least 4 */ 695: #define ARGLEN 512 /* total size for all the argument strings */ 696: 697: execit(s, arg) 698: char *s; 699: char *arg; /* last argument on line */ 700: { 701: char *argv[NARGS], args[ARGLEN], *envp[1]; 702: register char *sp = s; 703: register char *ap = args; 704: register char c; 705: register int i; 706: 707: /* 708: * First we have to set up the argument vector. 709: * "prog arg1 arg2" maps to exec("prog", "-", "arg1", "arg2"). 710: */ 711: for (i = 1; i < NARGS - 2; i++) { 712: argv[i] = ap; 713: for (EVER) { 714: if ((c = *sp++) == '\0' || ap >= &args[ARGLEN-1]) { 715: *ap = '\0'; 716: goto done; 717: } 718: if (c == ' ') { 719: *ap++ = '\0'; 720: while (*sp == ' ') 721: sp++; 722: if (*sp == '\0') 723: goto done; 724: break; 725: } 726: *ap++ = c; 727: } 728: } 729: done: 730: argv[0] = argv[1]; 731: argv[1] = "-"; 732: argv[i+1] = arg; 733: argv[i+2] = 0; 734: envp[0] = 0; 735: execve(argv[0], &argv[1], envp); 736: /* report failure of exec */ 737: syslog(LOG_ERR, "%s: %m", argv[0]); 738: closelog(); 739: sleep(10); /* prevent failures from eating machine */ 740: } 741: 742: #ifdef pdp11 743: #include <machine/autoconfig.h> 744: 745: autoconfig(howto) 746: int howto; 747: { 748: int pid, status, f; 749: static char config[]= "/etc/autoconfig"; 750: 751: if (!(pid = fork())) { 752: syslog(LOG_NOTICE, "configure system\n"); 753: f = open(ctty, O_RDWR, 0); 754: if (f) 755: dup2(f, 0); 756: dup2(0, 1); 757: dup2(0, 2); 758: execl(config, "autoconfig", 759: howto & RB_AUTODEBUG ? "-vcd" : "-vc", 0); 760: syslog(LOG_ERR, "init: couldn't exec %s\n", config); 761: exit(AC_SETUP); 762: } 763: while (wait(&status) != pid); 764: if ((status & 0377) == 0) 765: status >>= 8; 766: else 767: status = AC_SINGLE; 768: switch (status) { 769: case AC_SETUP: 770: syslog(LOG_ERR, "configuration setup error\n"); 771: return (0); 772: case AC_SINGLE: 773: syslog(LOG_ERR, "SERIOUS CONFIGURATION ERROR\7\7\7\n"); 774: return (0); 775: case AC_OK: 776: return (1); 777: default: 778: syslog(LOG_ERR, "unrecognized return from configure\n"); 779: return (0); 780: } 781: } 782: #endif