|
|
1.1 ! root 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: #ifndef lint ! 8: static char sccsid[] = "@(#)init.c 5.6 (Berkeley) 5/26/86"; ! 9: #endif not lint ! 10: ! 11: #include <signal.h> ! 12: #include <sys/types.h> ! 13: #include <utmp.h> ! 14: #include <setjmp.h> ! 15: #include <sys/reboot.h> ! 16: #include <errno.h> ! 17: #include <sys/file.h> ! 18: #include <ttyent.h> ! 19: #include <sys/syslog.h> ! 20: #include <sys/stat.h> ! 21: ! 22: #define LINSIZ sizeof(wtmp.ut_line) ! 23: #define CMDSIZ 200 /* max string length for getty or window command*/ ! 24: #define ALL p = itab; p ; p = p->next ! 25: #define EVER ;; ! 26: #define SCPYN(a, b) strncpy(a, b, sizeof(a)) ! 27: #define SCMPN(a, b) strncmp(a, b, sizeof(a)) ! 28: ! 29: char shell[] = "/bin/sh"; ! 30: char minus[] = "-"; ! 31: char runc[] = "/etc/rc"; ! 32: char utmpf[] = "/etc/utmp"; ! 33: char wtmpf[] = "/usr/adm/wtmp"; ! 34: char ctty[] = "/dev/console"; ! 35: ! 36: struct utmp wtmp; ! 37: struct tab ! 38: { ! 39: char line[LINSIZ]; ! 40: char comn[CMDSIZ]; ! 41: char xflag; ! 42: int pid; ! 43: int wpid; /* window system pid for SIGHUP */ ! 44: char wcmd[CMDSIZ]; /* command to start window system process */ ! 45: time_t gettytime; ! 46: int gettycnt; ! 47: time_t windtime; ! 48: int windcnt; ! 49: struct tab *next; ! 50: } *itab; ! 51: ! 52: int fi; ! 53: int mergflag; ! 54: char tty[20]; ! 55: jmp_buf sjbuf, shutpass; ! 56: time_t time0; ! 57: ! 58: int reset(); ! 59: int idle(); ! 60: char *strcpy(), *strcat(); ! 61: long lseek(); ! 62: ! 63: struct sigvec rvec = { reset, sigmask(SIGHUP), 0 }; ! 64: ! 65: ! 66: #ifdef vax ! 67: main() ! 68: { ! 69: register int r11; /* passed thru from boot */ ! 70: #else ! 71: main(argc, argv) ! 72: char **argv; ! 73: { ! 74: #endif ! 75: int howto, oldhowto; ! 76: ! 77: time0 = time(0); ! 78: #ifdef vax ! 79: howto = r11; ! 80: #else ! 81: if (argc > 1 && argv[1][0] == '-') { ! 82: char *cp; ! 83: ! 84: howto = 0; ! 85: cp = &argv[1][1]; ! 86: while (*cp) switch (*cp++) { ! 87: case 'a': ! 88: howto |= RB_ASKNAME; ! 89: break; ! 90: case 's': ! 91: howto |= RB_SINGLE; ! 92: break; ! 93: } ! 94: } else { ! 95: howto = RB_SINGLE; ! 96: } ! 97: #endif ! 98: openlog("init", LOG_CONS|LOG_ODELAY, LOG_AUTH); ! 99: sigvec(SIGTERM, &rvec, (struct sigvec *)0); ! 100: signal(SIGTSTP, idle); ! 101: signal(SIGSTOP, SIG_IGN); ! 102: signal(SIGTTIN, SIG_IGN); ! 103: signal(SIGTTOU, SIG_IGN); ! 104: (void) setjmp(sjbuf); ! 105: for (EVER) { ! 106: oldhowto = howto; ! 107: howto = RB_SINGLE; ! 108: if (setjmp(shutpass) == 0) ! 109: shutdown(); ! 110: if (oldhowto & RB_SINGLE) ! 111: single(); ! 112: if (runcom(oldhowto) == 0) ! 113: continue; ! 114: merge(); ! 115: multiple(); ! 116: } ! 117: } ! 118: ! 119: int shutreset(); ! 120: ! 121: shutdown() ! 122: { ! 123: register i; ! 124: register struct tab *p, *p1; ! 125: ! 126: close(creat(utmpf, 0644)); ! 127: signal(SIGHUP, SIG_IGN); ! 128: for (p = itab; p ; ) { ! 129: term(p); ! 130: p1 = p->next; ! 131: free(p); ! 132: p = p1; ! 133: } ! 134: itab = (struct tab *)0; ! 135: signal(SIGALRM, shutreset); ! 136: (void) kill(-1, SIGTERM); /* one chance to catch it */ ! 137: sleep(5); ! 138: alarm(30); ! 139: for (i = 0; i < 5; i++) ! 140: kill(-1, SIGKILL); ! 141: while (wait((int *)0) != -1) ! 142: ; ! 143: alarm(0); ! 144: shutend(); ! 145: } ! 146: ! 147: char shutfailm[] = "WARNING: Something is hung (wont die); ps axl advised\n"; ! 148: ! 149: shutreset() ! 150: { ! 151: int status; ! 152: ! 153: if (fork() == 0) { ! 154: int ct = open(ctty, 1); ! 155: write(ct, shutfailm, sizeof (shutfailm)); ! 156: sleep(5); ! 157: exit(1); ! 158: } ! 159: sleep(5); ! 160: shutend(); ! 161: longjmp(shutpass, 1); ! 162: } ! 163: ! 164: shutend() ! 165: { ! 166: register i, f; ! 167: ! 168: acct(0); ! 169: signal(SIGALRM, SIG_DFL); ! 170: for (i = 0; i < 10; i++) ! 171: close(i); ! 172: f = open(wtmpf, O_WRONLY|O_APPEND); ! 173: if (f >= 0) { ! 174: SCPYN(wtmp.ut_line, "~"); ! 175: SCPYN(wtmp.ut_name, "shutdown"); ! 176: SCPYN(wtmp.ut_host, ""); ! 177: time(&wtmp.ut_time); ! 178: write(f, (char *)&wtmp, sizeof(wtmp)); ! 179: close(f); ! 180: } ! 181: return (1); ! 182: } ! 183: ! 184: single() ! 185: { ! 186: register pid; ! 187: register xpid; ! 188: extern errno; ! 189: ! 190: do { ! 191: pid = fork(); ! 192: if (pid == 0) { ! 193: signal(SIGTERM, SIG_DFL); ! 194: signal(SIGHUP, SIG_DFL); ! 195: signal(SIGALRM, SIG_DFL); ! 196: signal(SIGTSTP, SIG_IGN); ! 197: (void) open(ctty, O_RDWR); ! 198: dup2(0, 1); ! 199: dup2(0, 2); ! 200: execl(shell, minus, (char *)0); ! 201: exit(0); ! 202: } ! 203: while ((xpid = wait((int *)0)) != pid) ! 204: if (xpid == -1 && errno == ECHILD) ! 205: break; ! 206: } while (xpid == -1); ! 207: } ! 208: ! 209: runcom(oldhowto) ! 210: int oldhowto; ! 211: { ! 212: register pid, f; ! 213: int status; ! 214: ! 215: pid = fork(); ! 216: if (pid == 0) { ! 217: (void) open("/", O_RDONLY); ! 218: dup2(0, 1); ! 219: dup2(0, 2); ! 220: if (oldhowto & RB_SINGLE) ! 221: execl(shell, shell, runc, (char *)0); ! 222: else ! 223: execl(shell, shell, runc, "autoboot", (char *)0); ! 224: exit(1); ! 225: } ! 226: while (wait(&status) != pid) ! 227: ; ! 228: if (status) ! 229: return (0); ! 230: f = open(wtmpf, O_WRONLY|O_APPEND); ! 231: if (f >= 0) { ! 232: SCPYN(wtmp.ut_line, "~"); ! 233: SCPYN(wtmp.ut_name, "reboot"); ! 234: SCPYN(wtmp.ut_host, ""); ! 235: if (time0) { ! 236: wtmp.ut_time = time0; ! 237: time0 = 0; ! 238: } else ! 239: time(&wtmp.ut_time); ! 240: write(f, (char *)&wtmp, sizeof(wtmp)); ! 241: close(f); ! 242: } ! 243: return (1); ! 244: } ! 245: ! 246: struct sigvec mvec = { merge, sigmask(SIGTERM), 0 }; ! 247: /* ! 248: * Multi-user. Listen for users leaving, SIGHUP's ! 249: * which indicate ttys has changed, and SIGTERM's which ! 250: * are used to shutdown the system. ! 251: */ ! 252: multiple() ! 253: { ! 254: register struct tab *p; ! 255: register pid; ! 256: int omask; ! 257: ! 258: sigvec(SIGHUP, &mvec, (struct sigvec *)0); ! 259: for (EVER) { ! 260: pid = wait((int *)0); ! 261: if (pid == -1) ! 262: return; ! 263: omask = sigblock(SIGHUP); ! 264: for (ALL) { ! 265: /* must restart window system BEFORE emulator */ ! 266: if (p->wpid == pid || p->wpid == -1) ! 267: wstart(p); ! 268: if (p->pid == pid || p->pid == -1) { ! 269: /* disown the window system */ ! 270: if (p->wpid) ! 271: kill(p->wpid, SIGHUP); ! 272: rmut(p); ! 273: dfork(p); ! 274: } ! 275: } ! 276: sigsetmask(omask); ! 277: } ! 278: } ! 279: ! 280: /* ! 281: * Merge current contents of ttys file ! 282: * into in-core table of configured tty lines. ! 283: * Entered as signal handler for SIGHUP. ! 284: */ ! 285: #define FOUND 1 ! 286: #define CHANGE 2 ! 287: #define WCHANGE 4 ! 288: ! 289: merge() ! 290: { ! 291: register struct tab *p; ! 292: register struct ttyent *t; ! 293: register struct tab *p1; ! 294: ! 295: for (ALL) ! 296: p->xflag = 0; ! 297: setttyent(); ! 298: while (t = getttyent()) { ! 299: if ((t->ty_status & TTY_ON) == 0) ! 300: continue; ! 301: for (ALL) { ! 302: if (SCMPN(p->line, t->ty_name)) ! 303: continue; ! 304: p->xflag |= FOUND; ! 305: if (SCMPN(p->comn, t->ty_getty)) { ! 306: p->xflag |= CHANGE; ! 307: SCPYN(p->comn, t->ty_getty); ! 308: } ! 309: if (SCMPN(p->wcmd, t->ty_window)) { ! 310: p->xflag |= WCHANGE|CHANGE; ! 311: SCPYN(p->wcmd, t->ty_window); ! 312: } ! 313: goto contin1; ! 314: } ! 315: ! 316: /* ! 317: * Make space for a new one ! 318: */ ! 319: p1 = (struct tab *)calloc(1, sizeof(*p1)); ! 320: if (!p1) { ! 321: syslog(LOG_ERR, "no space for '%s' !?!", t->ty_name); ! 322: goto contin1; ! 323: } ! 324: /* ! 325: * Put new terminal at the end of the linked list. ! 326: */ ! 327: if (itab) { ! 328: for (p = itab; p->next ; p = p->next) ! 329: ; ! 330: p->next = p1; ! 331: } else ! 332: itab = p1; ! 333: ! 334: p = p1; ! 335: SCPYN(p->line, t->ty_name); ! 336: p->xflag |= FOUND|CHANGE; ! 337: SCPYN(p->comn, t->ty_getty); ! 338: if (strcmp(t->ty_window, "") != 0) { ! 339: p->xflag |= WCHANGE; ! 340: SCPYN(p->wcmd, t->ty_window); ! 341: } ! 342: contin1: ! 343: ; ! 344: } ! 345: endttyent(); ! 346: p1 = (struct tab *)0; ! 347: for (ALL) { ! 348: if ((p->xflag&FOUND) == 0) { ! 349: term(p); ! 350: wterm(p); ! 351: if (p1) ! 352: p1->next = p->next; ! 353: else ! 354: itab = p->next; ! 355: free(p); ! 356: p = p1 ? p1 : itab; ! 357: } else { ! 358: /* window system should be started first */ ! 359: if (p->xflag&WCHANGE) { ! 360: wterm(p); ! 361: wstart(p); ! 362: } ! 363: if (p->xflag&CHANGE) { ! 364: term(p); ! 365: dfork(p); ! 366: } ! 367: } ! 368: p1 = p; ! 369: } ! 370: } ! 371: ! 372: term(p) ! 373: register struct tab *p; ! 374: { ! 375: ! 376: if (p->pid != 0) { ! 377: rmut(p); ! 378: kill(p->pid, SIGKILL); ! 379: } ! 380: p->pid = 0; ! 381: /* send SIGHUP to get rid of connections */ ! 382: if (p->wpid > 0) ! 383: kill(p->wpid, SIGHUP); ! 384: } ! 385: ! 386: #include <sys/ioctl.h> ! 387: ! 388: dfork(p) ! 389: struct tab *p; ! 390: { ! 391: register pid; ! 392: time_t t; ! 393: int dowait = 0; ! 394: ! 395: time(&t); ! 396: p->gettycnt++; ! 397: if ((t - p->gettytime) >= 60) { ! 398: p->gettytime = t; ! 399: p->gettycnt = 1; ! 400: } else if (p->gettycnt >= 5) { ! 401: dowait = 1; ! 402: p->gettytime = t; ! 403: p->gettycnt = 1; ! 404: } ! 405: pid = fork(); ! 406: if (pid == 0) { ! 407: signal(SIGTERM, SIG_DFL); ! 408: signal(SIGHUP, SIG_IGN); ! 409: sigsetmask(0); /* since can be called from masked code */ ! 410: if (dowait) { ! 411: syslog(LOG_ERR, "'%s %s' failing, sleeping", p->comn, p->line); ! 412: closelog(); ! 413: sleep(30); ! 414: } ! 415: execit(p->comn, p->line); ! 416: exit(0); ! 417: } ! 418: p->pid = pid; ! 419: } ! 420: ! 421: /* ! 422: * Remove utmp entry. ! 423: */ ! 424: rmut(p) ! 425: register struct tab *p; ! 426: { ! 427: register f; ! 428: int found = 0; ! 429: static unsigned utmpsize; ! 430: static struct utmp *utmp; ! 431: register struct utmp *u; ! 432: int nutmp; ! 433: struct stat statbf; ! 434: ! 435: f = open(utmpf, O_RDWR); ! 436: if (f >= 0) { ! 437: fstat(f, &statbf); ! 438: if (utmpsize < statbf.st_size) { ! 439: utmpsize = statbf.st_size + 10 * sizeof(struct utmp); ! 440: if (utmp) ! 441: utmp = (struct utmp *)realloc(utmp, utmpsize); ! 442: else ! 443: utmp = (struct utmp *)malloc(utmpsize); ! 444: if (!utmp) ! 445: syslog(LOG_ERR, "utmp malloc failed"); ! 446: } ! 447: if (statbf.st_size && utmp) { ! 448: nutmp = read(f, utmp, statbf.st_size); ! 449: nutmp /= sizeof(struct utmp); ! 450: for (u = utmp ; u < &utmp[nutmp] ; u++) { ! 451: if (SCMPN(u->ut_line, p->line) || ! 452: u->ut_name[0]==0) ! 453: continue; ! 454: lseek(f, ((long)u)-((long)utmp), L_SET); ! 455: SCPYN(u->ut_name, ""); ! 456: SCPYN(u->ut_host, ""); ! 457: time(&u->ut_time); ! 458: write(f, (char *)u, sizeof(*u)); ! 459: found++; ! 460: } ! 461: } ! 462: close(f); ! 463: } ! 464: if (found) { ! 465: f = open(wtmpf, O_WRONLY|O_APPEND); ! 466: if (f >= 0) { ! 467: SCPYN(wtmp.ut_line, p->line); ! 468: SCPYN(wtmp.ut_name, ""); ! 469: SCPYN(wtmp.ut_host, ""); ! 470: time(&wtmp.ut_time); ! 471: write(f, (char *)&wtmp, sizeof(wtmp)); ! 472: close(f); ! 473: } ! 474: /* ! 475: * After a proper login force reset ! 476: * of error detection code in dfork. ! 477: */ ! 478: p->gettytime = 0; ! 479: p->windtime = 0; ! 480: } ! 481: } ! 482: ! 483: reset() ! 484: { ! 485: ! 486: longjmp(sjbuf, 1); ! 487: } ! 488: ! 489: jmp_buf idlebuf; ! 490: ! 491: idlehup() ! 492: { ! 493: ! 494: longjmp(idlebuf, 1); ! 495: } ! 496: ! 497: idle() ! 498: { ! 499: register struct tab *p; ! 500: register pid; ! 501: ! 502: signal(SIGHUP, idlehup); ! 503: for (EVER) { ! 504: if (setjmp(idlebuf)) ! 505: return; ! 506: pid = wait((int *) 0); ! 507: if (pid == -1) { ! 508: sigpause(0); ! 509: continue; ! 510: } ! 511: for (ALL) { ! 512: /* if window system dies, mark it for restart */ ! 513: if (p->wpid == pid) ! 514: p->wpid = -1; ! 515: if (p->pid == pid) { ! 516: rmut(p); ! 517: p->pid = -1; ! 518: } ! 519: } ! 520: } ! 521: } ! 522: ! 523: wterm(p) ! 524: register struct tab *p; ! 525: { ! 526: if (p->wpid != 0) { ! 527: kill(p->wpid, SIGKILL); ! 528: } ! 529: p->wpid = 0; ! 530: } ! 531: ! 532: wstart(p) ! 533: register struct tab *p; ! 534: { ! 535: register pid; ! 536: time_t t; ! 537: int dowait = 0; ! 538: ! 539: time(&t); ! 540: p->windcnt++; ! 541: if ((t - p->windtime) >= 60) { ! 542: p->windtime = t; ! 543: p->windcnt = 1; ! 544: } else if (p->windcnt >= 5) { ! 545: dowait = 1; ! 546: p->windtime = t; ! 547: p->windcnt = 1; ! 548: } ! 549: ! 550: pid = fork(); ! 551: ! 552: if (pid == 0) { ! 553: signal(SIGTERM, SIG_DFL); ! 554: signal(SIGHUP, SIG_IGN); ! 555: sigsetmask(0); /* since can be called from masked code */ ! 556: if (dowait) { ! 557: syslog(LOG_ERR, "'%s %s' failing, sleeping", p->wcmd, p->line); ! 558: closelog(); ! 559: sleep(30); ! 560: } ! 561: execit(p->wcmd, p->line); ! 562: exit(0); ! 563: } ! 564: p->wpid = pid; ! 565: } ! 566: ! 567: #define NARGS 20 /* must be at least 4 */ ! 568: #define ARGLEN 512 /* total size for all the argument strings */ ! 569: ! 570: execit(s, arg) ! 571: char *s; ! 572: char *arg; /* last argument on line */ ! 573: { ! 574: char *argv[NARGS], args[ARGLEN], *envp[1]; ! 575: register char *sp = s; ! 576: register char *ap = args; ! 577: register char c; ! 578: register int i; ! 579: ! 580: /* ! 581: * First we have to set up the argument vector. ! 582: * "prog arg1 arg2" maps to exec("prog", "-", "arg1", "arg2"). ! 583: */ ! 584: for (i = 1; i < NARGS - 2; i++) { ! 585: argv[i] = ap; ! 586: for (EVER) { ! 587: if ((c = *sp++) == '\0' || ap >= &args[ARGLEN-1]) { ! 588: *ap = '\0'; ! 589: goto done; ! 590: } ! 591: if (c == ' ') { ! 592: *ap++ = '\0'; ! 593: while (*sp == ' ') ! 594: sp++; ! 595: if (*sp == '\0') ! 596: goto done; ! 597: break; ! 598: } ! 599: *ap++ = c; ! 600: } ! 601: } ! 602: done: ! 603: argv[0] = argv[1]; ! 604: argv[1] = "-"; ! 605: argv[i+1] = arg; ! 606: argv[i+2] = 0; ! 607: envp[0] = 0; ! 608: execve(argv[0], &argv[1], envp); ! 609: /* report failure of exec */ ! 610: syslog(LOG_ERR, "%s: %m", argv[0]); ! 611: closelog(); ! 612: sleep(10); /* prevent failures from eating machine */ ! 613: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.