1*5971Sroot static char *sccsid = "@(#)init.c 4.6 (Berkeley) 02/26/82"; 21029Sbill #include <signal.h> 31029Sbill #include <sys/types.h> 41029Sbill #include <utmp.h> 51029Sbill #include <setjmp.h> 61403Sbill #include <sys/reboot.h> 72821Swnj #include <errno.h> 81029Sbill 91029Sbill #define LINSIZ sizeof(wtmp.ut_line) 101029Sbill #define TABSIZ 100 111029Sbill #define ALL p = &itab[0]; p < &itab[TABSIZ]; p++ 121029Sbill #define EVER ;; 131029Sbill #define SCPYN(a, b) strncpy(a, b, sizeof(a)) 141029Sbill #define SCMPN(a, b) strncmp(a, b, sizeof(a)) 151029Sbill 161029Sbill char shell[] = "/bin/sh"; 171403Sbill char getty[] = "/etc/getty"; 181029Sbill char minus[] = "-"; 191029Sbill char runc[] = "/etc/rc"; 201029Sbill char ifile[] = "/etc/ttys"; 211029Sbill char utmp[] = "/etc/utmp"; 221029Sbill char wtmpf[] = "/usr/adm/wtmp"; 231029Sbill char ctty[] = "/dev/console"; 241029Sbill char dev[] = "/dev/"; 251029Sbill 261029Sbill struct utmp wtmp; 271029Sbill struct 281029Sbill { 291029Sbill char line[LINSIZ]; 301029Sbill char comn; 311029Sbill char flag; 321029Sbill } line; 331029Sbill struct tab 341029Sbill { 351029Sbill char line[LINSIZ]; 361029Sbill char comn; 371029Sbill char xflag; 381029Sbill int pid; 39*5971Sroot time_t gettytime; 40*5971Sroot int gettycnt; 411029Sbill } itab[TABSIZ]; 421029Sbill 431029Sbill int fi; 441029Sbill int mergflag; 451029Sbill char tty[20]; 461429Sbill jmp_buf sjbuf, shutpass; 472821Swnj time_t time0; 481029Sbill 491029Sbill int reset(); 502821Swnj int idle(); 511029Sbill char *strcpy(), *strcat(); 521029Sbill long lseek(); 531029Sbill 541029Sbill main() 551029Sbill { 561403Sbill register int r11; /* passed thru from boot */ 571403Sbill int howto, oldhowto; 581403Sbill 592821Swnj time0 = time(0); 601403Sbill howto = r11; 611029Sbill setjmp(sjbuf); 621029Sbill signal(SIGTERM, reset); 632821Swnj signal(SIGTSTP, idle); 641029Sbill signal(SIGSTOP, SIG_IGN); 651029Sbill signal(SIGTTIN, SIG_IGN); 661029Sbill signal(SIGTTOU, SIG_IGN); 671029Sbill for(EVER) { 681403Sbill oldhowto = howto; 691403Sbill howto = RB_SINGLE; 701429Sbill if (setjmp(shutpass) == 0) 711429Sbill shutdown(); 721403Sbill if (oldhowto & RB_SINGLE) 731403Sbill single(); 741403Sbill if (runcom(oldhowto) == 0) 751403Sbill continue; 761029Sbill merge(); 771029Sbill multiple(); 781029Sbill } 791029Sbill } 801029Sbill 811429Sbill int shutreset(); 821429Sbill 831029Sbill shutdown() 841029Sbill { 851029Sbill register i; 861029Sbill register struct tab *p; 871029Sbill 881029Sbill close(creat(utmp, 0644)); 891029Sbill signal(SIGHUP, SIG_IGN); 901029Sbill for(ALL) { 911029Sbill term(p); 921029Sbill p->line[0] = 0; 931029Sbill } 941429Sbill signal(SIGALRM, shutreset); 951429Sbill alarm(30); 961029Sbill for(i=0; i<5; i++) 971029Sbill kill(-1, SIGKILL); 981029Sbill while(wait((int *)0) != -1) 991029Sbill ; 1001029Sbill alarm(0); 1011429Sbill shutend(); 1021429Sbill } 1031429Sbill 1041429Sbill char shutfailm[] = "WARNING: Something is hung (wont die); ps axl advised\n"; 1051429Sbill 1061429Sbill shutreset() 1071429Sbill { 1081429Sbill int status; 1091429Sbill 1101429Sbill if (fork() == 0) { 1111429Sbill int ct = open(ctty, 1); 1121429Sbill write(ct, shutfailm, sizeof (shutfailm)); 1131429Sbill sleep(5); 1141429Sbill exit(1); 1151429Sbill } 1161429Sbill sleep(5); 1171429Sbill shutend(); 1181429Sbill longjmp(shutpass, 1); 1191429Sbill } 1201429Sbill 1211429Sbill shutend() 1221429Sbill { 1232821Swnj register i, f; 1241429Sbill 1252821Swnj acct(0); 1261029Sbill signal(SIGALRM, SIG_DFL); 1271029Sbill for(i=0; i<10; i++) 1281029Sbill close(i); 1292821Swnj f = open(wtmpf, 1); 1302821Swnj if (f >= 0) { 1312821Swnj lseek(f, 0L, 2); 1322821Swnj SCPYN(wtmp.ut_line, "~"); 1332821Swnj SCPYN(wtmp.ut_name, "shutdown"); 1342821Swnj time(&wtmp.ut_time); 1352821Swnj write(f, (char *)&wtmp, sizeof(wtmp)); 1362821Swnj close(f); 1372821Swnj } 1382821Swnj return(1); 1391029Sbill } 1401029Sbill 1411029Sbill single() 1421029Sbill { 1431029Sbill register pid; 1442821Swnj register xpid; 1452821Swnj extern errno; 1461029Sbill 1472821Swnj do { 1481029Sbill pid = fork(); 1491029Sbill if(pid == 0) { 1501029Sbill /* 1511029Sbill alarm(300); 1521029Sbill */ 1531029Sbill signal(SIGTERM, SIG_DFL); 1541029Sbill signal(SIGHUP, SIG_DFL); 1551029Sbill signal(SIGALRM, SIG_DFL); 1561029Sbill open(ctty, 2); 1571029Sbill dup(0); 1581029Sbill dup(0); 1591029Sbill execl(shell, minus, (char *)0); 1601029Sbill exit(0); 1611029Sbill } 1622821Swnj while((xpid = wait((int *)0)) != pid) 1632821Swnj if (xpid == -1 && errno == ECHILD) 1642821Swnj break; 1652821Swnj } while (xpid == -1); 1661029Sbill } 1671029Sbill 1681403Sbill runcom(oldhowto) 1691403Sbill int oldhowto; 1701029Sbill { 1711029Sbill register pid, f; 1721403Sbill int status; 1731029Sbill 1741029Sbill pid = fork(); 1751029Sbill if(pid == 0) { 1761029Sbill open("/", 0); 1771029Sbill dup(0); 1781029Sbill dup(0); 1791403Sbill if (oldhowto & RB_SINGLE) 1801403Sbill execl(shell, shell, runc, (char *)0); 1811403Sbill else 1821403Sbill execl(shell, shell, runc, "autoboot", (char *)0); 1831403Sbill exit(1); 1841029Sbill } 1851403Sbill while(wait(&status) != pid) 1861029Sbill ; 1871403Sbill if(status) 1881403Sbill return(0); 1891029Sbill f = open(wtmpf, 1); 1901029Sbill if (f >= 0) { 1911029Sbill lseek(f, 0L, 2); 1921029Sbill SCPYN(wtmp.ut_line, "~"); 1931029Sbill SCPYN(wtmp.ut_name, "reboot"); 1942821Swnj if (time0) { 1952821Swnj wtmp.ut_time = time0; 1962821Swnj time0 = 0; 1972821Swnj } else 1982821Swnj time(&wtmp.ut_time); 1991029Sbill write(f, (char *)&wtmp, sizeof(wtmp)); 2001029Sbill close(f); 2011029Sbill } 2021403Sbill return(1); 2031029Sbill } 2041029Sbill 2051029Sbill setmerge() 2061029Sbill { 2071029Sbill 2081029Sbill signal(SIGHUP, setmerge); 2091029Sbill mergflag = 1; 2101029Sbill } 2111029Sbill 2121029Sbill multiple() 2131029Sbill { 2141029Sbill register struct tab *p; 2151029Sbill register pid; 2161029Sbill 2171029Sbill loop: 2181029Sbill mergflag = 0; 2191029Sbill signal(SIGHUP, setmerge); 2201029Sbill for(EVER) { 2211029Sbill pid = wait((int *)0); 2221029Sbill if(mergflag) { 2231029Sbill merge(); 2241029Sbill goto loop; 2251029Sbill } 2261029Sbill if(pid == -1) 2271029Sbill return; 2281029Sbill for(ALL) 2291029Sbill if(p->pid == pid || p->pid == -1) { 2301029Sbill rmut(p); 2311029Sbill dfork(p); 2321029Sbill } 2331029Sbill } 2341029Sbill } 2351029Sbill 2361029Sbill term(p) 2371029Sbill register struct tab *p; 2381029Sbill { 2391029Sbill 2401029Sbill if(p->pid != 0) { 2411029Sbill rmut(p); 2421029Sbill kill(p->pid, SIGKILL); 2431029Sbill } 2441029Sbill p->pid = 0; 2451029Sbill } 2461029Sbill 2471029Sbill rline() 2481029Sbill { 2491029Sbill register c, i; 2501029Sbill 2511029Sbill loop: 2521029Sbill c = get(); 2531029Sbill if(c < 0) 2541029Sbill return(0); 2551029Sbill if(c == 0) 2561029Sbill goto loop; 2571029Sbill line.flag = c; 2581029Sbill c = get(); 2591029Sbill if(c <= 0) 2601029Sbill goto loop; 2611029Sbill line.comn = c; 2621029Sbill SCPYN(line.line, ""); 2631029Sbill for (i=0; i<LINSIZ; i++) { 2641029Sbill c = get(); 2651029Sbill if(c <= 0) 2661029Sbill break; 2671029Sbill line.line[i] = c; 2681029Sbill } 2691029Sbill while(c > 0) 2701029Sbill c = get(); 2711029Sbill if(line.line[0] == 0) 2721029Sbill goto loop; 2731029Sbill if(line.flag == '0') 2741029Sbill goto loop; 2751029Sbill strcpy(tty, dev); 2761029Sbill strncat(tty, line.line, LINSIZ); 2771029Sbill if(access(tty, 06) < 0) 2781029Sbill goto loop; 2791029Sbill return(1); 2801029Sbill } 2811029Sbill 2821029Sbill get() 2831029Sbill { 2841029Sbill char b; 2851029Sbill 2861029Sbill if(read(fi, &b, 1) != 1) 2871029Sbill return(-1); 2881029Sbill if(b == '\n') 2891029Sbill return(0); 2901029Sbill return(b); 2911029Sbill } 2921029Sbill 2931029Sbill #define FOUND 1 2941029Sbill #define CHANGE 2 2951029Sbill 2961029Sbill merge() 2971029Sbill { 2981029Sbill register struct tab *p; 2991029Sbill 3001029Sbill fi = open(ifile, 0); 3011029Sbill if(fi < 0) 3021029Sbill return; 3031029Sbill for(ALL) 3041029Sbill p->xflag = 0; 3051029Sbill while(rline()) { 3061029Sbill for(ALL) { 3071029Sbill if (SCMPN(p->line, line.line)) 3081029Sbill continue; 3091029Sbill p->xflag |= FOUND; 3101029Sbill if(line.comn != p->comn) { 3111029Sbill p->xflag |= CHANGE; 3121029Sbill p->comn = line.comn; 3131029Sbill } 3141029Sbill goto contin1; 3151029Sbill } 3161029Sbill for(ALL) { 3171029Sbill if(p->line[0] != 0) 3181029Sbill continue; 3191029Sbill SCPYN(p->line, line.line); 3201029Sbill p->xflag |= FOUND|CHANGE; 3211029Sbill p->comn = line.comn; 3221029Sbill goto contin1; 3231029Sbill } 3241029Sbill contin1: 3251029Sbill ; 3261029Sbill } 3271029Sbill close(fi); 3281029Sbill for(ALL) { 3291029Sbill if((p->xflag&FOUND) == 0) { 3301029Sbill term(p); 3311029Sbill p->line[0] = 0; 3321029Sbill } 3331029Sbill if((p->xflag&CHANGE) != 0) { 3341029Sbill term(p); 3351029Sbill dfork(p); 3361029Sbill } 3371029Sbill } 3381029Sbill } 3391029Sbill 3401029Sbill dfork(p) 3411029Sbill struct tab *p; 3421029Sbill { 3431029Sbill register pid; 344*5971Sroot time_t t; 345*5971Sroot int dowait = 0; 3461029Sbill 347*5971Sroot time(&t); 348*5971Sroot p->gettycnt++; 349*5971Sroot if ((t - p->gettytime) >= 60) { 350*5971Sroot p->gettytime = t; 351*5971Sroot p->gettycnt = 1; 352*5971Sroot } else { 353*5971Sroot if (p->gettycnt >= 5) { 354*5971Sroot dowait = 1; 355*5971Sroot p->gettytime = t; 356*5971Sroot p->gettycnt = 1; 357*5971Sroot } 358*5971Sroot } 3591029Sbill pid = fork(); 3601029Sbill if(pid == 0) { 361*5971Sroot if (dowait) { 362*5971Sroot int f = open("/dev/console", 1); 363*5971Sroot write(f, "init: ", 6); 364*5971Sroot write(f, tty, strlen(tty)); 365*5971Sroot write(f, ": getty failing, sleeping\n\r", 27); 366*5971Sroot close(f); 367*5971Sroot sleep(30); 368*5971Sroot } 3691029Sbill signal(SIGTERM, SIG_DFL); 3701029Sbill signal(SIGHUP, SIG_IGN); 3711029Sbill strcpy(tty, dev); 3721029Sbill strncat(tty, p->line, LINSIZ); 3731029Sbill chown(tty, 0, 0); 3741029Sbill chmod(tty, 0622); 3753608Swnj if (open(tty, 2) < 0) { 3763608Swnj int repcnt = 0; 3773608Swnj do { 3783608Swnj if (repcnt % 10 == 0) { 3793608Swnj int f = open("/dev/console", 1); 3803608Swnj write(f, "init: ", 6); 3813608Swnj write(f, tty, strlen(tty)); 3823608Swnj write(f, ": cannot open\n\r", 15); 3833608Swnj close(f); 3843608Swnj } 3853608Swnj repcnt++; 3863608Swnj sleep(60); 3873608Swnj } while (open(tty, 2) < 0); 3883608Swnj exit(0); /* have wrong control tty, start over */ 3893608Swnj } 3901029Sbill vhangup(); 3911029Sbill signal(SIGHUP, SIG_DFL); 3921029Sbill open(tty, 2); 3931029Sbill close(0); 3941029Sbill dup(1); 3951029Sbill dup(0); 3961029Sbill tty[0] = p->comn; 3971029Sbill tty[1] = 0; 3981029Sbill execl(getty, minus, tty, (char *)0); 3991029Sbill exit(0); 4001029Sbill } 4011029Sbill p->pid = pid; 4021029Sbill } 4031029Sbill 4041029Sbill rmut(p) 4051029Sbill register struct tab *p; 4061029Sbill { 4071029Sbill register f; 4083608Swnj int found = 0; 4091029Sbill 4101029Sbill f = open(utmp, 2); 4111029Sbill if(f >= 0) { 4121029Sbill while(read(f, (char *)&wtmp, sizeof(wtmp)) == sizeof(wtmp)) { 4133608Swnj if (SCMPN(wtmp.ut_line, p->line) || wtmp.ut_name[0]==0) 4141029Sbill continue; 4151029Sbill lseek(f, -(long)sizeof(wtmp), 1); 4161029Sbill SCPYN(wtmp.ut_name, ""); 4171029Sbill time(&wtmp.ut_time); 4181029Sbill write(f, (char *)&wtmp, sizeof(wtmp)); 4193608Swnj found++; 4201029Sbill } 4211029Sbill close(f); 4221029Sbill } 4233608Swnj if (found) { 4243608Swnj f = open(wtmpf, 1); 4253608Swnj if (f >= 0) { 4263608Swnj SCPYN(wtmp.ut_line, p->line); 4273608Swnj SCPYN(wtmp.ut_name, ""); 4283608Swnj time(&wtmp.ut_time); 4293608Swnj lseek(f, (long)0, 2); 4303608Swnj write(f, (char *)&wtmp, sizeof(wtmp)); 4313608Swnj close(f); 4323608Swnj } 4331029Sbill } 4341029Sbill } 4351029Sbill 4361029Sbill reset() 4371029Sbill { 4381029Sbill longjmp(sjbuf, 1); 4391029Sbill } 4402821Swnj 4412821Swnj idle() 4422821Swnj { 4432821Swnj register struct tab *p; 4442821Swnj register pid; 4452821Swnj 4462821Swnj signal(SIGTSTP, idle); 4472821Swnj for (;;) { 4482821Swnj pid = wait((int *) 0); 4492821Swnj if (mergflag) 4502821Swnj return; 4512821Swnj if (pid == -1) 4522821Swnj pause(); 4532821Swnj else { 4542821Swnj for (ALL) 4552821Swnj if (p->pid == pid) { 4562821Swnj rmut(p); 4572821Swnj p->pid = -1; 4582821Swnj } 4592821Swnj } 4602821Swnj } 4612821Swnj } 462