1*12682Ssam #ifndef lint 2*12682Ssam static char *sccsid = "@(#)init.c 4.11 (Berkeley) 05/22/83"; 3*12682Ssam #endif 4*12682Ssam 51029Sbill #include <signal.h> 61029Sbill #include <sys/types.h> 71029Sbill #include <utmp.h> 81029Sbill #include <setjmp.h> 91403Sbill #include <sys/reboot.h> 102821Swnj #include <errno.h> 111029Sbill 121029Sbill #define LINSIZ sizeof(wtmp.ut_line) 131029Sbill #define TABSIZ 100 141029Sbill #define ALL p = &itab[0]; p < &itab[TABSIZ]; p++ 151029Sbill #define EVER ;; 161029Sbill #define SCPYN(a, b) strncpy(a, b, sizeof(a)) 171029Sbill #define SCMPN(a, b) strncmp(a, b, sizeof(a)) 181029Sbill 191029Sbill char shell[] = "/bin/sh"; 201403Sbill char getty[] = "/etc/getty"; 211029Sbill char minus[] = "-"; 221029Sbill char runc[] = "/etc/rc"; 231029Sbill char ifile[] = "/etc/ttys"; 241029Sbill char utmp[] = "/etc/utmp"; 251029Sbill char wtmpf[] = "/usr/adm/wtmp"; 261029Sbill char ctty[] = "/dev/console"; 271029Sbill char dev[] = "/dev/"; 281029Sbill 291029Sbill struct utmp wtmp; 301029Sbill struct 311029Sbill { 321029Sbill char line[LINSIZ]; 331029Sbill char comn; 341029Sbill char flag; 351029Sbill } line; 361029Sbill struct tab 371029Sbill { 381029Sbill char line[LINSIZ]; 391029Sbill char comn; 401029Sbill char xflag; 411029Sbill int pid; 425971Sroot time_t gettytime; 435971Sroot int gettycnt; 441029Sbill } itab[TABSIZ]; 451029Sbill 461029Sbill int fi; 471029Sbill int mergflag; 481029Sbill char tty[20]; 491429Sbill jmp_buf sjbuf, shutpass; 502821Swnj time_t time0; 511029Sbill 521029Sbill int reset(); 532821Swnj int idle(); 541029Sbill char *strcpy(), *strcat(); 551029Sbill long lseek(); 561029Sbill 579869Spugs #ifndef sun 581029Sbill main() 591029Sbill { 601403Sbill register int r11; /* passed thru from boot */ 619869Spugs #else sun 629869Spugs main(argc, argv) 639869Spugs char **argv; 649869Spugs { 659869Spugs #endif sun 661403Sbill int howto, oldhowto; 671403Sbill 682821Swnj time0 = time(0); 699869Spugs #ifndef sun 701403Sbill howto = r11; 719869Spugs #else sun 729869Spugs if (argc > 1 && argv[1][0] == '-') { 739869Spugs char *cp; 749869Spugs 759869Spugs howto = 0; 769869Spugs cp = &argv[1][1]; 779869Spugs while (*cp) switch (*cp++) { 789869Spugs case 'a': 799869Spugs howto |= RB_ASKNAME; 809869Spugs break; 819869Spugs case 's': 829869Spugs howto |= RB_SINGLE; 839869Spugs break; 849869Spugs } 859869Spugs } else { 869869Spugs howto = RB_SINGLE; 879869Spugs } 889869Spugs #endif sun 891029Sbill setjmp(sjbuf); 901029Sbill signal(SIGTERM, reset); 912821Swnj signal(SIGTSTP, idle); 921029Sbill signal(SIGSTOP, SIG_IGN); 931029Sbill signal(SIGTTIN, SIG_IGN); 941029Sbill signal(SIGTTOU, SIG_IGN); 951029Sbill for(EVER) { 961403Sbill oldhowto = howto; 971403Sbill howto = RB_SINGLE; 981429Sbill if (setjmp(shutpass) == 0) 991429Sbill shutdown(); 1001403Sbill if (oldhowto & RB_SINGLE) 1011403Sbill single(); 1021403Sbill if (runcom(oldhowto) == 0) 1031403Sbill continue; 1041029Sbill merge(); 1051029Sbill multiple(); 1061029Sbill } 1071029Sbill } 1081029Sbill 1091429Sbill int shutreset(); 1101429Sbill 1111029Sbill shutdown() 1121029Sbill { 1131029Sbill register i; 1141029Sbill register struct tab *p; 1151029Sbill 1161029Sbill close(creat(utmp, 0644)); 1171029Sbill signal(SIGHUP, SIG_IGN); 1181029Sbill for(ALL) { 1191029Sbill term(p); 1201029Sbill p->line[0] = 0; 1211029Sbill } 1221429Sbill signal(SIGALRM, shutreset); 1231429Sbill alarm(30); 1241029Sbill for(i=0; i<5; i++) 1251029Sbill kill(-1, SIGKILL); 1261029Sbill while(wait((int *)0) != -1) 1271029Sbill ; 1281029Sbill alarm(0); 1291429Sbill shutend(); 1301429Sbill } 1311429Sbill 1321429Sbill char shutfailm[] = "WARNING: Something is hung (wont die); ps axl advised\n"; 1331429Sbill 1341429Sbill shutreset() 1351429Sbill { 1361429Sbill int status; 1371429Sbill 1381429Sbill if (fork() == 0) { 1391429Sbill int ct = open(ctty, 1); 1401429Sbill write(ct, shutfailm, sizeof (shutfailm)); 1411429Sbill sleep(5); 1421429Sbill exit(1); 1431429Sbill } 1441429Sbill sleep(5); 1451429Sbill shutend(); 1461429Sbill longjmp(shutpass, 1); 1471429Sbill } 1481429Sbill 1491429Sbill shutend() 1501429Sbill { 1512821Swnj register i, f; 1521429Sbill 1532821Swnj acct(0); 1541029Sbill signal(SIGALRM, SIG_DFL); 1551029Sbill for(i=0; i<10; i++) 1561029Sbill close(i); 1572821Swnj f = open(wtmpf, 1); 1582821Swnj if (f >= 0) { 1592821Swnj lseek(f, 0L, 2); 1602821Swnj SCPYN(wtmp.ut_line, "~"); 1612821Swnj SCPYN(wtmp.ut_name, "shutdown"); 162*12682Ssam SCPYN(wtmp.ut_host, ""); 1632821Swnj time(&wtmp.ut_time); 1642821Swnj write(f, (char *)&wtmp, sizeof(wtmp)); 1652821Swnj close(f); 1662821Swnj } 1672821Swnj return(1); 1681029Sbill } 1691029Sbill 1701029Sbill single() 1711029Sbill { 1721029Sbill register pid; 1732821Swnj register xpid; 1742821Swnj extern errno; 1751029Sbill 1762821Swnj do { 1771029Sbill pid = fork(); 1781029Sbill if(pid == 0) { 1791029Sbill /* 1801029Sbill alarm(300); 1811029Sbill */ 1821029Sbill signal(SIGTERM, SIG_DFL); 1831029Sbill signal(SIGHUP, SIG_DFL); 1841029Sbill signal(SIGALRM, SIG_DFL); 1851029Sbill open(ctty, 2); 1861029Sbill dup(0); 1871029Sbill dup(0); 1881029Sbill execl(shell, minus, (char *)0); 1891029Sbill exit(0); 1901029Sbill } 1912821Swnj while((xpid = wait((int *)0)) != pid) 1922821Swnj if (xpid == -1 && errno == ECHILD) 1932821Swnj break; 1942821Swnj } while (xpid == -1); 1951029Sbill } 1961029Sbill 1971403Sbill runcom(oldhowto) 1981403Sbill int oldhowto; 1991029Sbill { 2001029Sbill register pid, f; 2011403Sbill int status; 2021029Sbill 2031029Sbill pid = fork(); 2041029Sbill if(pid == 0) { 2051029Sbill open("/", 0); 2061029Sbill dup(0); 2071029Sbill dup(0); 2081403Sbill if (oldhowto & RB_SINGLE) 2091403Sbill execl(shell, shell, runc, (char *)0); 2101403Sbill else 2111403Sbill execl(shell, shell, runc, "autoboot", (char *)0); 2121403Sbill exit(1); 2131029Sbill } 2141403Sbill while(wait(&status) != pid) 2151029Sbill ; 2161403Sbill if(status) 2171403Sbill return(0); 2181029Sbill f = open(wtmpf, 1); 2191029Sbill if (f >= 0) { 2201029Sbill lseek(f, 0L, 2); 2211029Sbill SCPYN(wtmp.ut_line, "~"); 2221029Sbill SCPYN(wtmp.ut_name, "reboot"); 223*12682Ssam SCPYN(wtmp.ut_host, ""); 2242821Swnj if (time0) { 2252821Swnj wtmp.ut_time = time0; 2262821Swnj time0 = 0; 2272821Swnj } else 2282821Swnj time(&wtmp.ut_time); 2291029Sbill write(f, (char *)&wtmp, sizeof(wtmp)); 2301029Sbill close(f); 2311029Sbill } 2321403Sbill return(1); 2331029Sbill } 2341029Sbill 2351029Sbill setmerge() 2361029Sbill { 2371029Sbill 2381029Sbill signal(SIGHUP, setmerge); 2391029Sbill mergflag = 1; 2401029Sbill } 2411029Sbill 2421029Sbill multiple() 2431029Sbill { 2441029Sbill register struct tab *p; 2451029Sbill register pid; 2461029Sbill 2471029Sbill loop: 2481029Sbill mergflag = 0; 2491029Sbill signal(SIGHUP, setmerge); 2501029Sbill for(EVER) { 2511029Sbill pid = wait((int *)0); 2521029Sbill if(mergflag) { 2531029Sbill merge(); 2541029Sbill goto loop; 2551029Sbill } 2561029Sbill if(pid == -1) 2571029Sbill return; 2581029Sbill for(ALL) 2591029Sbill if(p->pid == pid || p->pid == -1) { 2601029Sbill rmut(p); 2611029Sbill dfork(p); 2621029Sbill } 2631029Sbill } 2641029Sbill } 2651029Sbill 2661029Sbill term(p) 2671029Sbill register struct tab *p; 2681029Sbill { 2691029Sbill 2701029Sbill if(p->pid != 0) { 2711029Sbill rmut(p); 2721029Sbill kill(p->pid, SIGKILL); 2731029Sbill } 2741029Sbill p->pid = 0; 2751029Sbill } 2761029Sbill 2771029Sbill rline() 2781029Sbill { 2791029Sbill register c, i; 2801029Sbill 2811029Sbill loop: 2821029Sbill c = get(); 2831029Sbill if(c < 0) 2841029Sbill return(0); 2851029Sbill if(c == 0) 2861029Sbill goto loop; 2871029Sbill line.flag = c; 2881029Sbill c = get(); 2891029Sbill if(c <= 0) 2901029Sbill goto loop; 2911029Sbill line.comn = c; 2921029Sbill SCPYN(line.line, ""); 2931029Sbill for (i=0; i<LINSIZ; i++) { 2941029Sbill c = get(); 2951029Sbill if(c <= 0) 2961029Sbill break; 2971029Sbill line.line[i] = c; 2981029Sbill } 2991029Sbill while(c > 0) 3001029Sbill c = get(); 3011029Sbill if(line.line[0] == 0) 3021029Sbill goto loop; 3031029Sbill if(line.flag == '0') 3041029Sbill goto loop; 3051029Sbill strcpy(tty, dev); 3061029Sbill strncat(tty, line.line, LINSIZ); 3071029Sbill if(access(tty, 06) < 0) 3081029Sbill goto loop; 3091029Sbill return(1); 3101029Sbill } 3111029Sbill 3121029Sbill get() 3131029Sbill { 3141029Sbill char b; 3151029Sbill 3161029Sbill if(read(fi, &b, 1) != 1) 3171029Sbill return(-1); 3181029Sbill if(b == '\n') 3191029Sbill return(0); 3201029Sbill return(b); 3211029Sbill } 3221029Sbill 3231029Sbill #define FOUND 1 3241029Sbill #define CHANGE 2 3251029Sbill 3261029Sbill merge() 3271029Sbill { 3281029Sbill register struct tab *p; 3291029Sbill 3301029Sbill fi = open(ifile, 0); 3311029Sbill if(fi < 0) 3321029Sbill return; 3331029Sbill for(ALL) 3341029Sbill p->xflag = 0; 3351029Sbill while(rline()) { 3361029Sbill for(ALL) { 3371029Sbill if (SCMPN(p->line, line.line)) 3381029Sbill continue; 3391029Sbill p->xflag |= FOUND; 3401029Sbill if(line.comn != p->comn) { 3411029Sbill p->xflag |= CHANGE; 3421029Sbill p->comn = line.comn; 3431029Sbill } 3441029Sbill goto contin1; 3451029Sbill } 3461029Sbill for(ALL) { 3471029Sbill if(p->line[0] != 0) 3481029Sbill continue; 3491029Sbill SCPYN(p->line, line.line); 3501029Sbill p->xflag |= FOUND|CHANGE; 3511029Sbill p->comn = line.comn; 3521029Sbill goto contin1; 3531029Sbill } 3541029Sbill contin1: 3551029Sbill ; 3561029Sbill } 3571029Sbill close(fi); 3581029Sbill for(ALL) { 3591029Sbill if((p->xflag&FOUND) == 0) { 3601029Sbill term(p); 3611029Sbill p->line[0] = 0; 3621029Sbill } 3631029Sbill if((p->xflag&CHANGE) != 0) { 3641029Sbill term(p); 3651029Sbill dfork(p); 3661029Sbill } 3671029Sbill } 3681029Sbill } 3691029Sbill 3706816Ssam #include <sys/ioctl.h> 3716816Ssam 3721029Sbill dfork(p) 3731029Sbill struct tab *p; 3741029Sbill { 3751029Sbill register pid; 3765971Sroot time_t t; 3775971Sroot int dowait = 0; 3789579Spugs extern char *sys_errlist[]; 3791029Sbill 3805971Sroot time(&t); 3815971Sroot p->gettycnt++; 3825971Sroot if ((t - p->gettytime) >= 60) { 3835971Sroot p->gettytime = t; 3845971Sroot p->gettycnt = 1; 3855971Sroot } else { 3865971Sroot if (p->gettycnt >= 5) { 3875971Sroot dowait = 1; 3885971Sroot p->gettytime = t; 3895971Sroot p->gettycnt = 1; 3905971Sroot } 3915971Sroot } 3921029Sbill pid = fork(); 3931029Sbill if(pid == 0) { 3946816Ssam int oerrno, f; 3956816Ssam extern int errno; 3966816Ssam 3976816Ssam signal(SIGTERM, SIG_DFL); 3986816Ssam signal(SIGHUP, SIG_IGN); 3999579Spugs strcpy(tty, dev); 4009579Spugs strncat(tty, p->line, LINSIZ); 4015971Sroot if (dowait) { 4026816Ssam f = open("/dev/console", 1); 4035971Sroot write(f, "init: ", 6); 4045971Sroot write(f, tty, strlen(tty)); 4055971Sroot write(f, ": getty failing, sleeping\n\r", 27); 4065971Sroot close(f); 4075971Sroot sleep(30); 4086816Ssam if ((f = open("/dev/tty", 2)) >= 0) { 4096816Ssam ioctl(f, TIOCNOTTY, 0); 4106816Ssam close(f); 4116816Ssam } 4125971Sroot } 4131029Sbill chown(tty, 0, 0); 4141029Sbill chmod(tty, 0622); 4153608Swnj if (open(tty, 2) < 0) { 4163608Swnj int repcnt = 0; 4173608Swnj do { 4186816Ssam oerrno = errno; 4193608Swnj if (repcnt % 10 == 0) { 4206816Ssam f = open("/dev/console", 1); 4213608Swnj write(f, "init: ", 6); 4229579Spugs write(f, tty, strlen(tty)); 4239579Spugs write(f, ": ", 2); 4249579Spugs write(f, sys_errlist[oerrno], 4259579Spugs strlen(sys_errlist[oerrno])); 4269579Spugs write(f, "\n", 1); 4273608Swnj close(f); 4286816Ssam if ((f = open("/dev/tty", 2)) >= 0) { 4296816Ssam ioctl(f, TIOCNOTTY, 0); 4306816Ssam close(f); 4316816Ssam } 4323608Swnj } 4333608Swnj repcnt++; 4343608Swnj sleep(60); 4353608Swnj } while (open(tty, 2) < 0); 4363608Swnj exit(0); /* have wrong control tty, start over */ 4373608Swnj } 4381029Sbill vhangup(); 4391029Sbill signal(SIGHUP, SIG_DFL); 4401029Sbill open(tty, 2); 4411029Sbill close(0); 4421029Sbill dup(1); 4431029Sbill dup(0); 4441029Sbill tty[0] = p->comn; 4451029Sbill tty[1] = 0; 4461029Sbill execl(getty, minus, tty, (char *)0); 4471029Sbill exit(0); 4481029Sbill } 4491029Sbill p->pid = pid; 4501029Sbill } 4511029Sbill 4521029Sbill rmut(p) 4531029Sbill register struct tab *p; 4541029Sbill { 4551029Sbill register f; 4563608Swnj int found = 0; 4571029Sbill 4581029Sbill f = open(utmp, 2); 4591029Sbill if(f >= 0) { 4601029Sbill while(read(f, (char *)&wtmp, sizeof(wtmp)) == sizeof(wtmp)) { 4613608Swnj if (SCMPN(wtmp.ut_line, p->line) || wtmp.ut_name[0]==0) 4621029Sbill continue; 4631029Sbill lseek(f, -(long)sizeof(wtmp), 1); 4641029Sbill SCPYN(wtmp.ut_name, ""); 465*12682Ssam SCPYN(wtmp.ut_host, ""); 4661029Sbill time(&wtmp.ut_time); 4671029Sbill write(f, (char *)&wtmp, sizeof(wtmp)); 4683608Swnj found++; 4691029Sbill } 4701029Sbill close(f); 4711029Sbill } 4723608Swnj if (found) { 4733608Swnj f = open(wtmpf, 1); 4743608Swnj if (f >= 0) { 4753608Swnj SCPYN(wtmp.ut_line, p->line); 4763608Swnj SCPYN(wtmp.ut_name, ""); 477*12682Ssam SCPYN(wtmp.ut_host, ""); 4783608Swnj time(&wtmp.ut_time); 4793608Swnj lseek(f, (long)0, 2); 4803608Swnj write(f, (char *)&wtmp, sizeof(wtmp)); 4813608Swnj close(f); 4823608Swnj } 4831029Sbill } 4841029Sbill } 4851029Sbill 4861029Sbill reset() 4871029Sbill { 4881029Sbill longjmp(sjbuf, 1); 4891029Sbill } 4902821Swnj 4912821Swnj idle() 4922821Swnj { 4932821Swnj register struct tab *p; 4942821Swnj register pid; 4952821Swnj 4962821Swnj signal(SIGTSTP, idle); 4972821Swnj for (;;) { 4982821Swnj pid = wait((int *) 0); 4992821Swnj if (mergflag) 5002821Swnj return; 5012821Swnj if (pid == -1) 5022821Swnj pause(); 5032821Swnj else { 5042821Swnj for (ALL) 5052821Swnj if (p->pid == pid) { 5062821Swnj rmut(p); 5072821Swnj p->pid = -1; 5082821Swnj } 5092821Swnj } 5102821Swnj } 5112821Swnj } 512