1*6816Ssam static char *sccsid = "@(#)init.c 4.6 (Berkeley) 2/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; 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 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 340*6816Ssam #include <sys/ioctl.h> 341*6816Ssam 3421029Sbill dfork(p) 3431029Sbill struct tab *p; 3441029Sbill { 3451029Sbill register pid; 3465971Sroot time_t t; 3475971Sroot int dowait = 0; 3481029Sbill 3495971Sroot time(&t); 3505971Sroot p->gettycnt++; 3515971Sroot if ((t - p->gettytime) >= 60) { 3525971Sroot p->gettytime = t; 3535971Sroot p->gettycnt = 1; 3545971Sroot } else { 3555971Sroot if (p->gettycnt >= 5) { 3565971Sroot dowait = 1; 3575971Sroot p->gettytime = t; 3585971Sroot p->gettycnt = 1; 3595971Sroot } 3605971Sroot } 3611029Sbill pid = fork(); 3621029Sbill if(pid == 0) { 363*6816Ssam int oerrno, f; 364*6816Ssam extern int errno; 365*6816Ssam 366*6816Ssam signal(SIGTERM, SIG_DFL); 367*6816Ssam signal(SIGHUP, SIG_IGN); 3685971Sroot if (dowait) { 369*6816Ssam f = open("/dev/console", 1); 3705971Sroot write(f, "init: ", 6); 3715971Sroot write(f, tty, strlen(tty)); 3725971Sroot write(f, ": getty failing, sleeping\n\r", 27); 3735971Sroot close(f); 3745971Sroot sleep(30); 375*6816Ssam if ((f = open("/dev/tty", 2)) >= 0) { 376*6816Ssam ioctl(f, TIOCNOTTY, 0); 377*6816Ssam close(f); 378*6816Ssam } 3795971Sroot } 3801029Sbill strcpy(tty, dev); 3811029Sbill strncat(tty, p->line, LINSIZ); 3821029Sbill chown(tty, 0, 0); 3831029Sbill chmod(tty, 0622); 3843608Swnj if (open(tty, 2) < 0) { 3853608Swnj int repcnt = 0; 3863608Swnj do { 387*6816Ssam oerrno = errno; 3883608Swnj if (repcnt % 10 == 0) { 389*6816Ssam f = open("/dev/console", 1); 3903608Swnj write(f, "init: ", 6); 391*6816Ssam errno = oerrno, perror(tty); 3923608Swnj close(f); 393*6816Ssam if ((f = open("/dev/tty", 2)) >= 0) { 394*6816Ssam ioctl(f, TIOCNOTTY, 0); 395*6816Ssam close(f); 396*6816Ssam } 3973608Swnj } 3983608Swnj repcnt++; 3993608Swnj sleep(60); 4003608Swnj } while (open(tty, 2) < 0); 4013608Swnj exit(0); /* have wrong control tty, start over */ 4023608Swnj } 4031029Sbill vhangup(); 4041029Sbill signal(SIGHUP, SIG_DFL); 4051029Sbill open(tty, 2); 4061029Sbill close(0); 4071029Sbill dup(1); 4081029Sbill dup(0); 4091029Sbill tty[0] = p->comn; 4101029Sbill tty[1] = 0; 4111029Sbill execl(getty, minus, tty, (char *)0); 4121029Sbill exit(0); 4131029Sbill } 4141029Sbill p->pid = pid; 4151029Sbill } 4161029Sbill 4171029Sbill rmut(p) 4181029Sbill register struct tab *p; 4191029Sbill { 4201029Sbill register f; 4213608Swnj int found = 0; 4221029Sbill 4231029Sbill f = open(utmp, 2); 4241029Sbill if(f >= 0) { 4251029Sbill while(read(f, (char *)&wtmp, sizeof(wtmp)) == sizeof(wtmp)) { 4263608Swnj if (SCMPN(wtmp.ut_line, p->line) || wtmp.ut_name[0]==0) 4271029Sbill continue; 4281029Sbill lseek(f, -(long)sizeof(wtmp), 1); 4291029Sbill SCPYN(wtmp.ut_name, ""); 4301029Sbill time(&wtmp.ut_time); 4311029Sbill write(f, (char *)&wtmp, sizeof(wtmp)); 4323608Swnj found++; 4331029Sbill } 4341029Sbill close(f); 4351029Sbill } 4363608Swnj if (found) { 4373608Swnj f = open(wtmpf, 1); 4383608Swnj if (f >= 0) { 4393608Swnj SCPYN(wtmp.ut_line, p->line); 4403608Swnj SCPYN(wtmp.ut_name, ""); 4413608Swnj time(&wtmp.ut_time); 4423608Swnj lseek(f, (long)0, 2); 4433608Swnj write(f, (char *)&wtmp, sizeof(wtmp)); 4443608Swnj close(f); 4453608Swnj } 4461029Sbill } 4471029Sbill } 4481029Sbill 4491029Sbill reset() 4501029Sbill { 4511029Sbill longjmp(sjbuf, 1); 4521029Sbill } 4532821Swnj 4542821Swnj idle() 4552821Swnj { 4562821Swnj register struct tab *p; 4572821Swnj register pid; 4582821Swnj 4592821Swnj signal(SIGTSTP, idle); 4602821Swnj for (;;) { 4612821Swnj pid = wait((int *) 0); 4622821Swnj if (mergflag) 4632821Swnj return; 4642821Swnj if (pid == -1) 4652821Swnj pause(); 4662821Swnj else { 4672821Swnj for (ALL) 4682821Swnj if (p->pid == pid) { 4692821Swnj rmut(p); 4702821Swnj p->pid = -1; 4712821Swnj } 4722821Swnj } 4732821Swnj } 4742821Swnj } 475