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