|
|
1.1 ! root 1: #ifndef lint ! 2: static char *sccsid = "@(#)init.c 4.12 (Berkeley) 6/12/83"; ! 3: #endif ! 4: ! 5: #include <signal.h> ! 6: #include <sys/types.h> ! 7: #include <utmp.h> ! 8: #include <setjmp.h> ! 9: #include <sys/reboot.h> ! 10: #include <errno.h> ! 11: #include <sys/file.h> ! 12: ! 13: #define LINSIZ sizeof(wtmp.ut_line) ! 14: #define TABSIZ 100 ! 15: #define ALL p = &itab[0]; p < &itab[TABSIZ]; p++ ! 16: #define EVER ;; ! 17: #define SCPYN(a, b) strncpy(a, b, sizeof(a)) ! 18: #define SCMPN(a, b) strncmp(a, b, sizeof(a)) ! 19: #define mask(s) (1 << ((s)-1)) ! 20: ! 21: char shell[] = "/bin/sh"; ! 22: char getty[] = "/etc/getty"; ! 23: char minus[] = "-"; ! 24: char runc[] = "/etc/rc"; ! 25: char ifile[] = "/etc/ttys"; ! 26: char utmp[] = "/etc/utmp"; ! 27: char wtmpf[] = "/usr/adm/wtmp"; ! 28: char ctty[] = "/dev/console"; ! 29: char dev[] = "/dev/"; ! 30: ! 31: struct utmp wtmp; ! 32: struct ! 33: { ! 34: char line[LINSIZ]; ! 35: char comn; ! 36: char flag; ! 37: } line; ! 38: struct tab ! 39: { ! 40: char line[LINSIZ]; ! 41: char comn; ! 42: char xflag; ! 43: int pid; ! 44: time_t gettytime; ! 45: int gettycnt; ! 46: } itab[TABSIZ]; ! 47: ! 48: int fi; ! 49: int mergflag; ! 50: char tty[20]; ! 51: jmp_buf sjbuf, shutpass; ! 52: time_t time0; ! 53: ! 54: int reset(); ! 55: int idle(); ! 56: char *strcpy(), *strcat(); ! 57: long lseek(); ! 58: ! 59: struct sigvec rvec = { reset, mask(SIGHUP), 0 }; ! 60: ! 61: #ifdef vax ! 62: main() ! 63: { ! 64: register int r11; /* passed thru from boot */ ! 65: #else ! 66: main(argc, argv) ! 67: char **argv; ! 68: { ! 69: #endif ! 70: int howto, oldhowto; ! 71: ! 72: time0 = time(0); ! 73: #ifdef vax ! 74: howto = r11; ! 75: #else ! 76: if (argc > 1 && argv[1][0] == '-') { ! 77: char *cp; ! 78: ! 79: howto = 0; ! 80: cp = &argv[1][1]; ! 81: while (*cp) switch (*cp++) { ! 82: case 'a': ! 83: howto |= RB_ASKNAME; ! 84: break; ! 85: case 's': ! 86: howto |= RB_SINGLE; ! 87: break; ! 88: } ! 89: } else { ! 90: howto = RB_SINGLE; ! 91: } ! 92: #endif ! 93: sigvec(SIGTERM, &rvec, (struct sigvec *)0); ! 94: signal(SIGTSTP, idle); ! 95: signal(SIGSTOP, SIG_IGN); ! 96: signal(SIGTTIN, SIG_IGN); ! 97: signal(SIGTTOU, SIG_IGN); ! 98: (void) setjmp(sjbuf); ! 99: for (EVER) { ! 100: oldhowto = howto; ! 101: howto = RB_SINGLE; ! 102: if (setjmp(shutpass) == 0) ! 103: shutdown(); ! 104: if (oldhowto & RB_SINGLE) ! 105: single(); ! 106: if (runcom(oldhowto) == 0) ! 107: continue; ! 108: merge(); ! 109: multiple(); ! 110: } ! 111: } ! 112: ! 113: int shutreset(); ! 114: ! 115: shutdown() ! 116: { ! 117: register i; ! 118: register struct tab *p; ! 119: ! 120: close(creat(utmp, 0644)); ! 121: signal(SIGHUP, SIG_IGN); ! 122: for (ALL) { ! 123: term(p); ! 124: p->line[0] = 0; ! 125: } ! 126: signal(SIGALRM, shutreset); ! 127: alarm(30); ! 128: for (i = 0; i < 5; i++) ! 129: kill(-1, SIGKILL); ! 130: while (wait((int *)0) != -1) ! 131: ; ! 132: alarm(0); ! 133: shutend(); ! 134: } ! 135: ! 136: char shutfailm[] = "WARNING: Something is hung (wont die); ps axl advised\n"; ! 137: ! 138: shutreset() ! 139: { ! 140: int status; ! 141: ! 142: if (fork() == 0) { ! 143: int ct = open(ctty, 1); ! 144: write(ct, shutfailm, sizeof (shutfailm)); ! 145: sleep(5); ! 146: exit(1); ! 147: } ! 148: sleep(5); ! 149: shutend(); ! 150: longjmp(shutpass, 1); ! 151: } ! 152: ! 153: shutend() ! 154: { ! 155: register i, f; ! 156: ! 157: acct(0); ! 158: signal(SIGALRM, SIG_DFL); ! 159: for (i = 0; i < 10; i++) ! 160: close(i); ! 161: f = open(wtmpf, O_WRONLY|O_APPEND); ! 162: if (f >= 0) { ! 163: SCPYN(wtmp.ut_line, "~"); ! 164: SCPYN(wtmp.ut_name, "shutdown"); ! 165: SCPYN(wtmp.ut_host, ""); ! 166: time(&wtmp.ut_time); ! 167: write(f, (char *)&wtmp, sizeof(wtmp)); ! 168: close(f); ! 169: } ! 170: return (1); ! 171: } ! 172: ! 173: single() ! 174: { ! 175: register pid; ! 176: register xpid; ! 177: extern errno; ! 178: ! 179: do { ! 180: pid = fork(); ! 181: if (pid == 0) { ! 182: signal(SIGTERM, SIG_DFL); ! 183: signal(SIGHUP, SIG_DFL); ! 184: signal(SIGALRM, SIG_DFL); ! 185: (void) open(ctty, O_RDWR); ! 186: dup2(0, 1); ! 187: dup2(0, 2); ! 188: execl(shell, minus, (char *)0); ! 189: exit(0); ! 190: } ! 191: while ((xpid = wait((int *)0)) != pid) ! 192: if (xpid == -1 && errno == ECHILD) ! 193: break; ! 194: } while (xpid == -1); ! 195: } ! 196: ! 197: runcom(oldhowto) ! 198: int oldhowto; ! 199: { ! 200: register pid, f; ! 201: int status; ! 202: ! 203: pid = fork(); ! 204: if (pid == 0) { ! 205: (void) open("/", O_RDONLY); ! 206: dup2(0, 1); ! 207: dup2(0, 2); ! 208: if (oldhowto & RB_SINGLE) ! 209: execl(shell, shell, runc, (char *)0); ! 210: else ! 211: execl(shell, shell, runc, "autoboot", (char *)0); ! 212: exit(1); ! 213: } ! 214: while (wait(&status) != pid) ! 215: ; ! 216: if (status) ! 217: return (0); ! 218: f = open(wtmpf, O_WRONLY|O_APPEND); ! 219: if (f >= 0) { ! 220: SCPYN(wtmp.ut_line, "~"); ! 221: SCPYN(wtmp.ut_name, "reboot"); ! 222: SCPYN(wtmp.ut_host, ""); ! 223: if (time0) { ! 224: wtmp.ut_time = time0; ! 225: time0 = 0; ! 226: } else ! 227: time(&wtmp.ut_time); ! 228: write(f, (char *)&wtmp, sizeof(wtmp)); ! 229: close(f); ! 230: } ! 231: return (1); ! 232: } ! 233: ! 234: struct sigvec mvec = { merge, mask(SIGTERM), 0 }; ! 235: /* ! 236: * Multi-user. Listen for users leaving, SIGHUP's ! 237: * which indicate ttys has changed, and SIGTERM's which ! 238: * are used to shutdown the system. ! 239: */ ! 240: multiple() ! 241: { ! 242: register struct tab *p; ! 243: register pid; ! 244: ! 245: sigvec(SIGHUP, &mvec, (struct sigvec *)0); ! 246: for (EVER) { ! 247: pid = wait((int *)0); ! 248: if (pid == -1) ! 249: return; ! 250: for (ALL) ! 251: if (p->pid == pid || p->pid == -1) { ! 252: rmut(p); ! 253: dfork(p); ! 254: } ! 255: } ! 256: } ! 257: ! 258: /* ! 259: * Merge current contents of ttys file ! 260: * into in-core table of configured tty lines. ! 261: * Entered as signal handler for SIGHUP. ! 262: */ ! 263: #define FOUND 1 ! 264: #define CHANGE 2 ! 265: ! 266: merge() ! 267: { ! 268: register struct tab *p; ! 269: ! 270: fi = open(ifile, 0); ! 271: if (fi < 0) ! 272: return; ! 273: for (ALL) ! 274: p->xflag = 0; ! 275: while (rline()) { ! 276: for (ALL) { ! 277: if (SCMPN(p->line, line.line)) ! 278: continue; ! 279: p->xflag |= FOUND; ! 280: if (line.comn != p->comn) { ! 281: p->xflag |= CHANGE; ! 282: p->comn = line.comn; ! 283: } ! 284: goto contin1; ! 285: } ! 286: for (ALL) { ! 287: if (p->line[0] != 0) ! 288: continue; ! 289: SCPYN(p->line, line.line); ! 290: p->xflag |= FOUND|CHANGE; ! 291: p->comn = line.comn; ! 292: goto contin1; ! 293: } ! 294: contin1: ! 295: ; ! 296: } ! 297: close(fi); ! 298: for (ALL) { ! 299: if ((p->xflag&FOUND) == 0) { ! 300: term(p); ! 301: p->line[0] = 0; ! 302: } ! 303: if (p->xflag&CHANGE) { ! 304: term(p); ! 305: dfork(p); ! 306: } ! 307: } ! 308: } ! 309: ! 310: term(p) ! 311: register struct tab *p; ! 312: { ! 313: ! 314: if (p->pid != 0) { ! 315: rmut(p); ! 316: kill(p->pid, SIGKILL); ! 317: } ! 318: p->pid = 0; ! 319: } ! 320: ! 321: rline() ! 322: { ! 323: register c, i; ! 324: ! 325: loop: ! 326: c = get(); ! 327: if (c < 0) ! 328: return(0); ! 329: if (c == 0) ! 330: goto loop; ! 331: line.flag = c; ! 332: c = get(); ! 333: if (c <= 0) ! 334: goto loop; ! 335: line.comn = c; ! 336: SCPYN(line.line, ""); ! 337: for (i = 0; i < LINSIZ; i++) { ! 338: c = get(); ! 339: if (c <= 0) ! 340: break; ! 341: line.line[i] = c; ! 342: } ! 343: while (c > 0) ! 344: c = get(); ! 345: if (line.line[0] == 0) ! 346: goto loop; ! 347: if (line.flag == '0') ! 348: goto loop; ! 349: strcpy(tty, dev); ! 350: strncat(tty, line.line, LINSIZ); ! 351: if (access(tty, 06) < 0) ! 352: goto loop; ! 353: return (1); ! 354: } ! 355: ! 356: get() ! 357: { ! 358: char b; ! 359: ! 360: if (read(fi, &b, 1) != 1) ! 361: return (-1); ! 362: if (b == '\n') ! 363: return (0); ! 364: return (b); ! 365: } ! 366: ! 367: #include <sys/ioctl.h> ! 368: ! 369: dfork(p) ! 370: struct tab *p; ! 371: { ! 372: register pid; ! 373: time_t t; ! 374: int dowait = 0; ! 375: extern char *sys_errlist[]; ! 376: ! 377: time(&t); ! 378: p->gettycnt++; ! 379: if ((t - p->gettytime) >= 60) { ! 380: p->gettytime = t; ! 381: p->gettycnt = 1; ! 382: } else { ! 383: if (p->gettycnt >= 5) { ! 384: dowait = 1; ! 385: p->gettytime = t; ! 386: p->gettycnt = 1; ! 387: } ! 388: } ! 389: pid = fork(); ! 390: if (pid == 0) { ! 391: int oerrno, f; ! 392: extern int errno; ! 393: ! 394: signal(SIGTERM, SIG_DFL); ! 395: signal(SIGHUP, SIG_IGN); ! 396: strcpy(tty, dev); ! 397: strncat(tty, p->line, LINSIZ); ! 398: if (dowait) { ! 399: f = open("/dev/console", O_WRONLY); ! 400: write(f, "init: ", 6); ! 401: write(f, tty, strlen(tty)); ! 402: write(f, ": getty failing, sleeping\n\r", 27); ! 403: close(f); ! 404: sleep(30); ! 405: if ((f = open("/dev/tty", O_RDWR)) >= 0) { ! 406: ioctl(f, TIOCNOTTY, 0); ! 407: close(f); ! 408: } ! 409: } ! 410: chown(tty, 0, 0); ! 411: chmod(tty, 0622); ! 412: if (open(tty, O_RDWR) < 0) { ! 413: int repcnt = 0; ! 414: do { ! 415: oerrno = errno; ! 416: if (repcnt % 10 == 0) { ! 417: f = open("/dev/console", O_WRONLY); ! 418: write(f, "init: ", 6); ! 419: write(f, tty, strlen(tty)); ! 420: write(f, ": ", 2); ! 421: write(f, sys_errlist[oerrno], ! 422: strlen(sys_errlist[oerrno])); ! 423: write(f, "\n", 1); ! 424: close(f); ! 425: if ((f = open("/dev/tty", 2)) >= 0) { ! 426: ioctl(f, TIOCNOTTY, 0); ! 427: close(f); ! 428: } ! 429: } ! 430: repcnt++; ! 431: sleep(60); ! 432: } while (open(tty, O_RDWR) < 0); ! 433: exit(0); /* have wrong control tty, start over */ ! 434: } ! 435: vhangup(); ! 436: signal(SIGHUP, SIG_DFL); ! 437: (void) open(tty, O_RDWR); ! 438: close(0); ! 439: dup(1); ! 440: dup(0); ! 441: tty[0] = p->comn; ! 442: tty[1] = 0; ! 443: execl(getty, minus, tty, (char *)0); ! 444: exit(0); ! 445: } ! 446: p->pid = pid; ! 447: } ! 448: ! 449: /* ! 450: * Remove utmp entry. ! 451: */ ! 452: rmut(p) ! 453: register struct tab *p; ! 454: { ! 455: register f; ! 456: int found = 0; ! 457: ! 458: f = open(utmp, O_RDWR); ! 459: if (f >= 0) { ! 460: while (read(f, (char *)&wtmp, sizeof(wtmp)) == sizeof(wtmp)) { ! 461: if (SCMPN(wtmp.ut_line, p->line) || wtmp.ut_name[0]==0) ! 462: continue; ! 463: lseek(f, -(long)sizeof(wtmp), 1); ! 464: SCPYN(wtmp.ut_name, ""); ! 465: SCPYN(wtmp.ut_host, ""); ! 466: time(&wtmp.ut_time); ! 467: write(f, (char *)&wtmp, sizeof(wtmp)); ! 468: found++; ! 469: } ! 470: close(f); ! 471: } ! 472: if (found) { ! 473: f = open(wtmpf, O_WRONLY|O_APPEND); ! 474: if (f >= 0) { ! 475: SCPYN(wtmp.ut_line, p->line); ! 476: SCPYN(wtmp.ut_name, ""); ! 477: SCPYN(wtmp.ut_host, ""); ! 478: time(&wtmp.ut_time); ! 479: write(f, (char *)&wtmp, sizeof(wtmp)); ! 480: close(f); ! 481: } ! 482: } ! 483: } ! 484: ! 485: reset() ! 486: { ! 487: ! 488: longjmp(sjbuf, 1); ! 489: } ! 490: ! 491: jmp_buf idlebuf; ! 492: ! 493: idlehup() ! 494: { ! 495: ! 496: longjmp(idlebuf, 1); ! 497: } ! 498: ! 499: idle() ! 500: { ! 501: register struct tab *p; ! 502: register pid; ! 503: ! 504: signal(SIGHUP, idlehup); ! 505: for (;;) { ! 506: if (setjmp(idlebuf)) ! 507: return; ! 508: pid = wait((int *) 0); ! 509: if (pid == -1) { ! 510: sigpause(0); ! 511: continue; ! 512: } ! 513: for (ALL) ! 514: if (p->pid == pid) { ! 515: rmut(p); ! 516: p->pid = -1; ! 517: } ! 518: } ! 519: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.