1*9869Spugs static char *sccsid = "@(#)init.c 4.10 (Berkeley) 12/22/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; 395971Sroot time_t gettytime; 405971Sroot 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 54*9869Spugs #ifndef sun 551029Sbill main() 561029Sbill { 571403Sbill register int r11; /* passed thru from boot */ 58*9869Spugs #else sun 59*9869Spugs main(argc, argv) 60*9869Spugs char **argv; 61*9869Spugs { 62*9869Spugs #endif sun 631403Sbill int howto, oldhowto; 641403Sbill 652821Swnj time0 = time(0); 66*9869Spugs #ifndef sun 671403Sbill howto = r11; 68*9869Spugs #else sun 69*9869Spugs if (argc > 1 && argv[1][0] == '-') { 70*9869Spugs char *cp; 71*9869Spugs 72*9869Spugs howto = 0; 73*9869Spugs cp = &argv[1][1]; 74*9869Spugs while (*cp) switch (*cp++) { 75*9869Spugs case 'a': 76*9869Spugs howto |= RB_ASKNAME; 77*9869Spugs break; 78*9869Spugs case 's': 79*9869Spugs howto |= RB_SINGLE; 80*9869Spugs break; 81*9869Spugs } 82*9869Spugs } else { 83*9869Spugs howto = RB_SINGLE; 84*9869Spugs } 85*9869Spugs #endif sun 861029Sbill setjmp(sjbuf); 871029Sbill signal(SIGTERM, reset); 882821Swnj signal(SIGTSTP, idle); 891029Sbill signal(SIGSTOP, SIG_IGN); 901029Sbill signal(SIGTTIN, SIG_IGN); 911029Sbill signal(SIGTTOU, SIG_IGN); 921029Sbill for(EVER) { 931403Sbill oldhowto = howto; 941403Sbill howto = RB_SINGLE; 951429Sbill if (setjmp(shutpass) == 0) 961429Sbill shutdown(); 971403Sbill if (oldhowto & RB_SINGLE) 981403Sbill single(); 991403Sbill if (runcom(oldhowto) == 0) 1001403Sbill continue; 1011029Sbill merge(); 1021029Sbill multiple(); 1031029Sbill } 1041029Sbill } 1051029Sbill 1061429Sbill int shutreset(); 1071429Sbill 1081029Sbill shutdown() 1091029Sbill { 1101029Sbill register i; 1111029Sbill register struct tab *p; 1121029Sbill 1131029Sbill close(creat(utmp, 0644)); 1141029Sbill signal(SIGHUP, SIG_IGN); 1151029Sbill for(ALL) { 1161029Sbill term(p); 1171029Sbill p->line[0] = 0; 1181029Sbill } 1191429Sbill signal(SIGALRM, shutreset); 1201429Sbill alarm(30); 1211029Sbill for(i=0; i<5; i++) 1221029Sbill kill(-1, SIGKILL); 1231029Sbill while(wait((int *)0) != -1) 1241029Sbill ; 1251029Sbill alarm(0); 1261429Sbill shutend(); 1271429Sbill } 1281429Sbill 1291429Sbill char shutfailm[] = "WARNING: Something is hung (wont die); ps axl advised\n"; 1301429Sbill 1311429Sbill shutreset() 1321429Sbill { 1331429Sbill int status; 1341429Sbill 1351429Sbill if (fork() == 0) { 1361429Sbill int ct = open(ctty, 1); 1371429Sbill write(ct, shutfailm, sizeof (shutfailm)); 1381429Sbill sleep(5); 1391429Sbill exit(1); 1401429Sbill } 1411429Sbill sleep(5); 1421429Sbill shutend(); 1431429Sbill longjmp(shutpass, 1); 1441429Sbill } 1451429Sbill 1461429Sbill shutend() 1471429Sbill { 1482821Swnj register i, f; 1491429Sbill 1502821Swnj acct(0); 1511029Sbill signal(SIGALRM, SIG_DFL); 1521029Sbill for(i=0; i<10; i++) 1531029Sbill close(i); 1542821Swnj f = open(wtmpf, 1); 1552821Swnj if (f >= 0) { 1562821Swnj lseek(f, 0L, 2); 1572821Swnj SCPYN(wtmp.ut_line, "~"); 1582821Swnj SCPYN(wtmp.ut_name, "shutdown"); 1592821Swnj time(&wtmp.ut_time); 1602821Swnj write(f, (char *)&wtmp, sizeof(wtmp)); 1612821Swnj close(f); 1622821Swnj } 1632821Swnj return(1); 1641029Sbill } 1651029Sbill 1661029Sbill single() 1671029Sbill { 1681029Sbill register pid; 1692821Swnj register xpid; 1702821Swnj extern errno; 1711029Sbill 1722821Swnj do { 1731029Sbill pid = fork(); 1741029Sbill if(pid == 0) { 1751029Sbill /* 1761029Sbill alarm(300); 1771029Sbill */ 1781029Sbill signal(SIGTERM, SIG_DFL); 1791029Sbill signal(SIGHUP, SIG_DFL); 1801029Sbill signal(SIGALRM, SIG_DFL); 1811029Sbill open(ctty, 2); 1821029Sbill dup(0); 1831029Sbill dup(0); 1841029Sbill execl(shell, minus, (char *)0); 1851029Sbill exit(0); 1861029Sbill } 1872821Swnj while((xpid = wait((int *)0)) != pid) 1882821Swnj if (xpid == -1 && errno == ECHILD) 1892821Swnj break; 1902821Swnj } while (xpid == -1); 1911029Sbill } 1921029Sbill 1931403Sbill runcom(oldhowto) 1941403Sbill int oldhowto; 1951029Sbill { 1961029Sbill register pid, f; 1971403Sbill int status; 1981029Sbill 1991029Sbill pid = fork(); 2001029Sbill if(pid == 0) { 2011029Sbill open("/", 0); 2021029Sbill dup(0); 2031029Sbill dup(0); 2041403Sbill if (oldhowto & RB_SINGLE) 2051403Sbill execl(shell, shell, runc, (char *)0); 2061403Sbill else 2071403Sbill execl(shell, shell, runc, "autoboot", (char *)0); 2081403Sbill exit(1); 2091029Sbill } 2101403Sbill while(wait(&status) != pid) 2111029Sbill ; 2121403Sbill if(status) 2131403Sbill return(0); 2141029Sbill f = open(wtmpf, 1); 2151029Sbill if (f >= 0) { 2161029Sbill lseek(f, 0L, 2); 2171029Sbill SCPYN(wtmp.ut_line, "~"); 2181029Sbill SCPYN(wtmp.ut_name, "reboot"); 2192821Swnj if (time0) { 2202821Swnj wtmp.ut_time = time0; 2212821Swnj time0 = 0; 2222821Swnj } else 2232821Swnj time(&wtmp.ut_time); 2241029Sbill write(f, (char *)&wtmp, sizeof(wtmp)); 2251029Sbill close(f); 2261029Sbill } 2271403Sbill return(1); 2281029Sbill } 2291029Sbill 2301029Sbill setmerge() 2311029Sbill { 2321029Sbill 2331029Sbill signal(SIGHUP, setmerge); 2341029Sbill mergflag = 1; 2351029Sbill } 2361029Sbill 2371029Sbill multiple() 2381029Sbill { 2391029Sbill register struct tab *p; 2401029Sbill register pid; 2411029Sbill 2421029Sbill loop: 2431029Sbill mergflag = 0; 2441029Sbill signal(SIGHUP, setmerge); 2451029Sbill for(EVER) { 2461029Sbill pid = wait((int *)0); 2471029Sbill if(mergflag) { 2481029Sbill merge(); 2491029Sbill goto loop; 2501029Sbill } 2511029Sbill if(pid == -1) 2521029Sbill return; 2531029Sbill for(ALL) 2541029Sbill if(p->pid == pid || p->pid == -1) { 2551029Sbill rmut(p); 2561029Sbill dfork(p); 2571029Sbill } 2581029Sbill } 2591029Sbill } 2601029Sbill 2611029Sbill term(p) 2621029Sbill register struct tab *p; 2631029Sbill { 2641029Sbill 2651029Sbill if(p->pid != 0) { 2661029Sbill rmut(p); 2671029Sbill kill(p->pid, SIGKILL); 2681029Sbill } 2691029Sbill p->pid = 0; 2701029Sbill } 2711029Sbill 2721029Sbill rline() 2731029Sbill { 2741029Sbill register c, i; 2751029Sbill 2761029Sbill loop: 2771029Sbill c = get(); 2781029Sbill if(c < 0) 2791029Sbill return(0); 2801029Sbill if(c == 0) 2811029Sbill goto loop; 2821029Sbill line.flag = c; 2831029Sbill c = get(); 2841029Sbill if(c <= 0) 2851029Sbill goto loop; 2861029Sbill line.comn = c; 2871029Sbill SCPYN(line.line, ""); 2881029Sbill for (i=0; i<LINSIZ; i++) { 2891029Sbill c = get(); 2901029Sbill if(c <= 0) 2911029Sbill break; 2921029Sbill line.line[i] = c; 2931029Sbill } 2941029Sbill while(c > 0) 2951029Sbill c = get(); 2961029Sbill if(line.line[0] == 0) 2971029Sbill goto loop; 2981029Sbill if(line.flag == '0') 2991029Sbill goto loop; 3001029Sbill strcpy(tty, dev); 3011029Sbill strncat(tty, line.line, LINSIZ); 3021029Sbill if(access(tty, 06) < 0) 3031029Sbill goto loop; 3041029Sbill return(1); 3051029Sbill } 3061029Sbill 3071029Sbill get() 3081029Sbill { 3091029Sbill char b; 3101029Sbill 3111029Sbill if(read(fi, &b, 1) != 1) 3121029Sbill return(-1); 3131029Sbill if(b == '\n') 3141029Sbill return(0); 3151029Sbill return(b); 3161029Sbill } 3171029Sbill 3181029Sbill #define FOUND 1 3191029Sbill #define CHANGE 2 3201029Sbill 3211029Sbill merge() 3221029Sbill { 3231029Sbill register struct tab *p; 3241029Sbill 3251029Sbill fi = open(ifile, 0); 3261029Sbill if(fi < 0) 3271029Sbill return; 3281029Sbill for(ALL) 3291029Sbill p->xflag = 0; 3301029Sbill while(rline()) { 3311029Sbill for(ALL) { 3321029Sbill if (SCMPN(p->line, line.line)) 3331029Sbill continue; 3341029Sbill p->xflag |= FOUND; 3351029Sbill if(line.comn != p->comn) { 3361029Sbill p->xflag |= CHANGE; 3371029Sbill p->comn = line.comn; 3381029Sbill } 3391029Sbill goto contin1; 3401029Sbill } 3411029Sbill for(ALL) { 3421029Sbill if(p->line[0] != 0) 3431029Sbill continue; 3441029Sbill SCPYN(p->line, line.line); 3451029Sbill p->xflag |= FOUND|CHANGE; 3461029Sbill p->comn = line.comn; 3471029Sbill goto contin1; 3481029Sbill } 3491029Sbill contin1: 3501029Sbill ; 3511029Sbill } 3521029Sbill close(fi); 3531029Sbill for(ALL) { 3541029Sbill if((p->xflag&FOUND) == 0) { 3551029Sbill term(p); 3561029Sbill p->line[0] = 0; 3571029Sbill } 3581029Sbill if((p->xflag&CHANGE) != 0) { 3591029Sbill term(p); 3601029Sbill dfork(p); 3611029Sbill } 3621029Sbill } 3631029Sbill } 3641029Sbill 3656816Ssam #include <sys/ioctl.h> 3666816Ssam 3671029Sbill dfork(p) 3681029Sbill struct tab *p; 3691029Sbill { 3701029Sbill register pid; 3715971Sroot time_t t; 3725971Sroot int dowait = 0; 3739579Spugs extern char *sys_errlist[]; 3741029Sbill 3755971Sroot time(&t); 3765971Sroot p->gettycnt++; 3775971Sroot if ((t - p->gettytime) >= 60) { 3785971Sroot p->gettytime = t; 3795971Sroot p->gettycnt = 1; 3805971Sroot } else { 3815971Sroot if (p->gettycnt >= 5) { 3825971Sroot dowait = 1; 3835971Sroot p->gettytime = t; 3845971Sroot p->gettycnt = 1; 3855971Sroot } 3865971Sroot } 3871029Sbill pid = fork(); 3881029Sbill if(pid == 0) { 3896816Ssam int oerrno, f; 3906816Ssam extern int errno; 3916816Ssam 3926816Ssam signal(SIGTERM, SIG_DFL); 3936816Ssam signal(SIGHUP, SIG_IGN); 3949579Spugs strcpy(tty, dev); 3959579Spugs strncat(tty, p->line, LINSIZ); 3965971Sroot if (dowait) { 3976816Ssam f = open("/dev/console", 1); 3985971Sroot write(f, "init: ", 6); 3995971Sroot write(f, tty, strlen(tty)); 4005971Sroot write(f, ": getty failing, sleeping\n\r", 27); 4015971Sroot close(f); 4025971Sroot sleep(30); 4036816Ssam if ((f = open("/dev/tty", 2)) >= 0) { 4046816Ssam ioctl(f, TIOCNOTTY, 0); 4056816Ssam close(f); 4066816Ssam } 4075971Sroot } 4081029Sbill chown(tty, 0, 0); 4091029Sbill chmod(tty, 0622); 4103608Swnj if (open(tty, 2) < 0) { 4113608Swnj int repcnt = 0; 4123608Swnj do { 4136816Ssam oerrno = errno; 4143608Swnj if (repcnt % 10 == 0) { 4156816Ssam f = open("/dev/console", 1); 4163608Swnj write(f, "init: ", 6); 4179579Spugs write(f, tty, strlen(tty)); 4189579Spugs write(f, ": ", 2); 4199579Spugs write(f, sys_errlist[oerrno], 4209579Spugs strlen(sys_errlist[oerrno])); 4219579Spugs write(f, "\n", 1); 4223608Swnj close(f); 4236816Ssam if ((f = open("/dev/tty", 2)) >= 0) { 4246816Ssam ioctl(f, TIOCNOTTY, 0); 4256816Ssam close(f); 4266816Ssam } 4273608Swnj } 4283608Swnj repcnt++; 4293608Swnj sleep(60); 4303608Swnj } while (open(tty, 2) < 0); 4313608Swnj exit(0); /* have wrong control tty, start over */ 4323608Swnj } 4331029Sbill vhangup(); 4341029Sbill signal(SIGHUP, SIG_DFL); 4351029Sbill open(tty, 2); 4361029Sbill close(0); 4371029Sbill dup(1); 4381029Sbill dup(0); 4391029Sbill tty[0] = p->comn; 4401029Sbill tty[1] = 0; 4411029Sbill execl(getty, minus, tty, (char *)0); 4421029Sbill exit(0); 4431029Sbill } 4441029Sbill p->pid = pid; 4451029Sbill } 4461029Sbill 4471029Sbill rmut(p) 4481029Sbill register struct tab *p; 4491029Sbill { 4501029Sbill register f; 4513608Swnj int found = 0; 4521029Sbill 4531029Sbill f = open(utmp, 2); 4541029Sbill if(f >= 0) { 4551029Sbill while(read(f, (char *)&wtmp, sizeof(wtmp)) == sizeof(wtmp)) { 4563608Swnj if (SCMPN(wtmp.ut_line, p->line) || wtmp.ut_name[0]==0) 4571029Sbill continue; 4581029Sbill lseek(f, -(long)sizeof(wtmp), 1); 4591029Sbill SCPYN(wtmp.ut_name, ""); 4601029Sbill time(&wtmp.ut_time); 4611029Sbill write(f, (char *)&wtmp, sizeof(wtmp)); 4623608Swnj found++; 4631029Sbill } 4641029Sbill close(f); 4651029Sbill } 4663608Swnj if (found) { 4673608Swnj f = open(wtmpf, 1); 4683608Swnj if (f >= 0) { 4693608Swnj SCPYN(wtmp.ut_line, p->line); 4703608Swnj SCPYN(wtmp.ut_name, ""); 4713608Swnj time(&wtmp.ut_time); 4723608Swnj lseek(f, (long)0, 2); 4733608Swnj write(f, (char *)&wtmp, sizeof(wtmp)); 4743608Swnj close(f); 4753608Swnj } 4761029Sbill } 4771029Sbill } 4781029Sbill 4791029Sbill reset() 4801029Sbill { 4811029Sbill longjmp(sjbuf, 1); 4821029Sbill } 4832821Swnj 4842821Swnj idle() 4852821Swnj { 4862821Swnj register struct tab *p; 4872821Swnj register pid; 4882821Swnj 4892821Swnj signal(SIGTSTP, idle); 4902821Swnj for (;;) { 4912821Swnj pid = wait((int *) 0); 4922821Swnj if (mergflag) 4932821Swnj return; 4942821Swnj if (pid == -1) 4952821Swnj pause(); 4962821Swnj else { 4972821Swnj for (ALL) 4982821Swnj if (p->pid == pid) { 4992821Swnj rmut(p); 5002821Swnj p->pid = -1; 5012821Swnj } 5022821Swnj } 5032821Swnj } 5042821Swnj } 505