1*3608Swnj static char *sccsid = "@(#)init.c 4.5 (Berkeley) 04/26/81"; 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; 391029Sbill } itab[TABSIZ]; 401029Sbill 411029Sbill int fi; 421029Sbill int mergflag; 431029Sbill char tty[20]; 441429Sbill jmp_buf sjbuf, shutpass; 452821Swnj time_t time0; 461029Sbill 471029Sbill int reset(); 482821Swnj int idle(); 491029Sbill char *strcpy(), *strcat(); 501029Sbill long lseek(); 511029Sbill 521029Sbill main() 531029Sbill { 541403Sbill register int r11; /* passed thru from boot */ 551403Sbill int howto, oldhowto; 561403Sbill 572821Swnj time0 = time(0); 581403Sbill howto = r11; 591029Sbill setjmp(sjbuf); 601029Sbill signal(SIGTERM, reset); 612821Swnj signal(SIGTSTP, idle); 621029Sbill signal(SIGSTOP, SIG_IGN); 631029Sbill signal(SIGTTIN, SIG_IGN); 641029Sbill signal(SIGTTOU, SIG_IGN); 651029Sbill for(EVER) { 661403Sbill oldhowto = howto; 671403Sbill howto = RB_SINGLE; 681429Sbill if (setjmp(shutpass) == 0) 691429Sbill shutdown(); 701403Sbill if (oldhowto & RB_SINGLE) 711403Sbill single(); 721403Sbill if (runcom(oldhowto) == 0) 731403Sbill continue; 741029Sbill merge(); 751029Sbill multiple(); 761029Sbill } 771029Sbill } 781029Sbill 791429Sbill int shutreset(); 801429Sbill 811029Sbill shutdown() 821029Sbill { 831029Sbill register i; 841029Sbill register struct tab *p; 851029Sbill 861029Sbill close(creat(utmp, 0644)); 871029Sbill signal(SIGHUP, SIG_IGN); 881029Sbill for(ALL) { 891029Sbill term(p); 901029Sbill p->line[0] = 0; 911029Sbill } 921429Sbill signal(SIGALRM, shutreset); 931429Sbill alarm(30); 941029Sbill for(i=0; i<5; i++) 951029Sbill kill(-1, SIGKILL); 961029Sbill while(wait((int *)0) != -1) 971029Sbill ; 981029Sbill alarm(0); 991429Sbill shutend(); 1001429Sbill } 1011429Sbill 1021429Sbill char shutfailm[] = "WARNING: Something is hung (wont die); ps axl advised\n"; 1031429Sbill 1041429Sbill shutreset() 1051429Sbill { 1061429Sbill int status; 1071429Sbill 1081429Sbill if (fork() == 0) { 1091429Sbill int ct = open(ctty, 1); 1101429Sbill write(ct, shutfailm, sizeof (shutfailm)); 1111429Sbill sleep(5); 1121429Sbill exit(1); 1131429Sbill } 1141429Sbill sleep(5); 1151429Sbill shutend(); 1161429Sbill longjmp(shutpass, 1); 1171429Sbill } 1181429Sbill 1191429Sbill shutend() 1201429Sbill { 1212821Swnj register i, f; 1221429Sbill 1232821Swnj acct(0); 1241029Sbill signal(SIGALRM, SIG_DFL); 1251029Sbill for(i=0; i<10; i++) 1261029Sbill close(i); 1272821Swnj f = open(wtmpf, 1); 1282821Swnj if (f >= 0) { 1292821Swnj lseek(f, 0L, 2); 1302821Swnj SCPYN(wtmp.ut_line, "~"); 1312821Swnj SCPYN(wtmp.ut_name, "shutdown"); 1322821Swnj time(&wtmp.ut_time); 1332821Swnj write(f, (char *)&wtmp, sizeof(wtmp)); 1342821Swnj close(f); 1352821Swnj } 1362821Swnj return(1); 1371029Sbill } 1381029Sbill 1391029Sbill single() 1401029Sbill { 1411029Sbill register pid; 1422821Swnj register xpid; 1432821Swnj extern errno; 1441029Sbill 1452821Swnj do { 1461029Sbill pid = fork(); 1471029Sbill if(pid == 0) { 1481029Sbill /* 1491029Sbill alarm(300); 1501029Sbill */ 1511029Sbill signal(SIGTERM, SIG_DFL); 1521029Sbill signal(SIGHUP, SIG_DFL); 1531029Sbill signal(SIGALRM, SIG_DFL); 1541029Sbill open(ctty, 2); 1551029Sbill dup(0); 1561029Sbill dup(0); 1571029Sbill execl(shell, minus, (char *)0); 1581029Sbill exit(0); 1591029Sbill } 1602821Swnj while((xpid = wait((int *)0)) != pid) 1612821Swnj if (xpid == -1 && errno == ECHILD) 1622821Swnj break; 1632821Swnj } while (xpid == -1); 1641029Sbill } 1651029Sbill 1661403Sbill runcom(oldhowto) 1671403Sbill int oldhowto; 1681029Sbill { 1691029Sbill register pid, f; 1701403Sbill int status; 1711029Sbill 1721029Sbill pid = fork(); 1731029Sbill if(pid == 0) { 1741029Sbill open("/", 0); 1751029Sbill dup(0); 1761029Sbill dup(0); 1771403Sbill if (oldhowto & RB_SINGLE) 1781403Sbill execl(shell, shell, runc, (char *)0); 1791403Sbill else 1801403Sbill execl(shell, shell, runc, "autoboot", (char *)0); 1811403Sbill exit(1); 1821029Sbill } 1831403Sbill while(wait(&status) != pid) 1841029Sbill ; 1851403Sbill if(status) 1861403Sbill return(0); 1871029Sbill f = open(wtmpf, 1); 1881029Sbill if (f >= 0) { 1891029Sbill lseek(f, 0L, 2); 1901029Sbill SCPYN(wtmp.ut_line, "~"); 1911029Sbill SCPYN(wtmp.ut_name, "reboot"); 1922821Swnj if (time0) { 1932821Swnj wtmp.ut_time = time0; 1942821Swnj time0 = 0; 1952821Swnj } else 1962821Swnj time(&wtmp.ut_time); 1971029Sbill write(f, (char *)&wtmp, sizeof(wtmp)); 1981029Sbill close(f); 1991029Sbill } 2001403Sbill return(1); 2011029Sbill } 2021029Sbill 2031029Sbill setmerge() 2041029Sbill { 2051029Sbill 2061029Sbill signal(SIGHUP, setmerge); 2071029Sbill mergflag = 1; 2081029Sbill } 2091029Sbill 2101029Sbill multiple() 2111029Sbill { 2121029Sbill register struct tab *p; 2131029Sbill register pid; 2141029Sbill 2151029Sbill loop: 2161029Sbill mergflag = 0; 2171029Sbill signal(SIGHUP, setmerge); 2181029Sbill for(EVER) { 2191029Sbill pid = wait((int *)0); 2201029Sbill if(mergflag) { 2211029Sbill merge(); 2221029Sbill goto loop; 2231029Sbill } 2241029Sbill if(pid == -1) 2251029Sbill return; 2261029Sbill for(ALL) 2271029Sbill if(p->pid == pid || p->pid == -1) { 2281029Sbill rmut(p); 2291029Sbill dfork(p); 2301029Sbill } 2311029Sbill } 2321029Sbill } 2331029Sbill 2341029Sbill term(p) 2351029Sbill register struct tab *p; 2361029Sbill { 2371029Sbill 2381029Sbill if(p->pid != 0) { 2391029Sbill rmut(p); 2401029Sbill kill(p->pid, SIGKILL); 2411029Sbill } 2421029Sbill p->pid = 0; 2431029Sbill } 2441029Sbill 2451029Sbill rline() 2461029Sbill { 2471029Sbill register c, i; 2481029Sbill 2491029Sbill loop: 2501029Sbill c = get(); 2511029Sbill if(c < 0) 2521029Sbill return(0); 2531029Sbill if(c == 0) 2541029Sbill goto loop; 2551029Sbill line.flag = c; 2561029Sbill c = get(); 2571029Sbill if(c <= 0) 2581029Sbill goto loop; 2591029Sbill line.comn = c; 2601029Sbill SCPYN(line.line, ""); 2611029Sbill for (i=0; i<LINSIZ; i++) { 2621029Sbill c = get(); 2631029Sbill if(c <= 0) 2641029Sbill break; 2651029Sbill line.line[i] = c; 2661029Sbill } 2671029Sbill while(c > 0) 2681029Sbill c = get(); 2691029Sbill if(line.line[0] == 0) 2701029Sbill goto loop; 2711029Sbill if(line.flag == '0') 2721029Sbill goto loop; 2731029Sbill strcpy(tty, dev); 2741029Sbill strncat(tty, line.line, LINSIZ); 2751029Sbill if(access(tty, 06) < 0) 2761029Sbill goto loop; 2771029Sbill return(1); 2781029Sbill } 2791029Sbill 2801029Sbill get() 2811029Sbill { 2821029Sbill char b; 2831029Sbill 2841029Sbill if(read(fi, &b, 1) != 1) 2851029Sbill return(-1); 2861029Sbill if(b == '\n') 2871029Sbill return(0); 2881029Sbill return(b); 2891029Sbill } 2901029Sbill 2911029Sbill #define FOUND 1 2921029Sbill #define CHANGE 2 2931029Sbill 2941029Sbill merge() 2951029Sbill { 2961029Sbill register struct tab *p; 2971029Sbill 2981029Sbill fi = open(ifile, 0); 2991029Sbill if(fi < 0) 3001029Sbill return; 3011029Sbill for(ALL) 3021029Sbill p->xflag = 0; 3031029Sbill while(rline()) { 3041029Sbill for(ALL) { 3051029Sbill if (SCMPN(p->line, line.line)) 3061029Sbill continue; 3071029Sbill p->xflag |= FOUND; 3081029Sbill if(line.comn != p->comn) { 3091029Sbill p->xflag |= CHANGE; 3101029Sbill p->comn = line.comn; 3111029Sbill } 3121029Sbill goto contin1; 3131029Sbill } 3141029Sbill for(ALL) { 3151029Sbill if(p->line[0] != 0) 3161029Sbill continue; 3171029Sbill SCPYN(p->line, line.line); 3181029Sbill p->xflag |= FOUND|CHANGE; 3191029Sbill p->comn = line.comn; 3201029Sbill goto contin1; 3211029Sbill } 3221029Sbill contin1: 3231029Sbill ; 3241029Sbill } 3251029Sbill close(fi); 3261029Sbill for(ALL) { 3271029Sbill if((p->xflag&FOUND) == 0) { 3281029Sbill term(p); 3291029Sbill p->line[0] = 0; 3301029Sbill } 3311029Sbill if((p->xflag&CHANGE) != 0) { 3321029Sbill term(p); 3331029Sbill dfork(p); 3341029Sbill } 3351029Sbill } 3361029Sbill } 3371029Sbill 3381029Sbill dfork(p) 3391029Sbill struct tab *p; 3401029Sbill { 3411029Sbill register pid; 3421029Sbill 3431029Sbill pid = fork(); 3441029Sbill if(pid == 0) { 3451029Sbill signal(SIGTERM, SIG_DFL); 3461029Sbill signal(SIGHUP, SIG_IGN); 3471029Sbill strcpy(tty, dev); 3481029Sbill strncat(tty, p->line, LINSIZ); 3491029Sbill chown(tty, 0, 0); 3501029Sbill chmod(tty, 0622); 351*3608Swnj if (open(tty, 2) < 0) { 352*3608Swnj int repcnt = 0; 353*3608Swnj do { 354*3608Swnj if (repcnt % 10 == 0) { 355*3608Swnj int f = open("/dev/console", 1); 356*3608Swnj write(f, "init: ", 6); 357*3608Swnj write(f, tty, strlen(tty)); 358*3608Swnj write(f, ": cannot open\n\r", 15); 359*3608Swnj close(f); 360*3608Swnj } 361*3608Swnj repcnt++; 362*3608Swnj sleep(60); 363*3608Swnj } while (open(tty, 2) < 0); 364*3608Swnj exit(0); /* have wrong control tty, start over */ 365*3608Swnj } 3661029Sbill vhangup(); 3671029Sbill signal(SIGHUP, SIG_DFL); 3681029Sbill open(tty, 2); 3691029Sbill close(0); 3701029Sbill dup(1); 3711029Sbill dup(0); 3721029Sbill tty[0] = p->comn; 3731029Sbill tty[1] = 0; 3741029Sbill execl(getty, minus, tty, (char *)0); 3751029Sbill exit(0); 3761029Sbill } 3771029Sbill p->pid = pid; 3781029Sbill } 3791029Sbill 3801029Sbill rmut(p) 3811029Sbill register struct tab *p; 3821029Sbill { 3831029Sbill register f; 384*3608Swnj int found = 0; 3851029Sbill 3861029Sbill f = open(utmp, 2); 3871029Sbill if(f >= 0) { 3881029Sbill while(read(f, (char *)&wtmp, sizeof(wtmp)) == sizeof(wtmp)) { 389*3608Swnj if (SCMPN(wtmp.ut_line, p->line) || wtmp.ut_name[0]==0) 3901029Sbill continue; 3911029Sbill lseek(f, -(long)sizeof(wtmp), 1); 3921029Sbill SCPYN(wtmp.ut_name, ""); 3931029Sbill time(&wtmp.ut_time); 3941029Sbill write(f, (char *)&wtmp, sizeof(wtmp)); 395*3608Swnj found++; 3961029Sbill } 3971029Sbill close(f); 3981029Sbill } 399*3608Swnj if (found) { 400*3608Swnj f = open(wtmpf, 1); 401*3608Swnj if (f >= 0) { 402*3608Swnj SCPYN(wtmp.ut_line, p->line); 403*3608Swnj SCPYN(wtmp.ut_name, ""); 404*3608Swnj time(&wtmp.ut_time); 405*3608Swnj lseek(f, (long)0, 2); 406*3608Swnj write(f, (char *)&wtmp, sizeof(wtmp)); 407*3608Swnj close(f); 408*3608Swnj } 4091029Sbill } 4101029Sbill } 4111029Sbill 4121029Sbill reset() 4131029Sbill { 4141029Sbill longjmp(sjbuf, 1); 4151029Sbill } 4162821Swnj 4172821Swnj idle() 4182821Swnj { 4192821Swnj register struct tab *p; 4202821Swnj register pid; 4212821Swnj 4222821Swnj signal(SIGTSTP, idle); 4232821Swnj for (;;) { 4242821Swnj pid = wait((int *) 0); 4252821Swnj if (mergflag) 4262821Swnj return; 4272821Swnj if (pid == -1) 4282821Swnj pause(); 4292821Swnj else { 4302821Swnj for (ALL) 4312821Swnj if (p->pid == pid) { 4322821Swnj rmut(p); 4332821Swnj p->pid = -1; 4342821Swnj } 4352821Swnj } 4362821Swnj } 4372821Swnj } 438