112682Ssam #ifndef lint 2*13021Ssam static char *sccsid = "@(#)init.c 4.12 (Berkeley) 06/12/83"; 312682Ssam #endif 412682Ssam 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> 11*13021Ssam #include <sys/file.h> 121029Sbill 131029Sbill #define LINSIZ sizeof(wtmp.ut_line) 141029Sbill #define TABSIZ 100 151029Sbill #define ALL p = &itab[0]; p < &itab[TABSIZ]; p++ 161029Sbill #define EVER ;; 171029Sbill #define SCPYN(a, b) strncpy(a, b, sizeof(a)) 181029Sbill #define SCMPN(a, b) strncmp(a, b, sizeof(a)) 19*13021Ssam #define mask(s) (1 << ((s)-1)) 201029Sbill 211029Sbill char shell[] = "/bin/sh"; 221403Sbill char getty[] = "/etc/getty"; 231029Sbill char minus[] = "-"; 241029Sbill char runc[] = "/etc/rc"; 251029Sbill char ifile[] = "/etc/ttys"; 261029Sbill char utmp[] = "/etc/utmp"; 271029Sbill char wtmpf[] = "/usr/adm/wtmp"; 281029Sbill char ctty[] = "/dev/console"; 291029Sbill char dev[] = "/dev/"; 301029Sbill 311029Sbill struct utmp wtmp; 321029Sbill struct 331029Sbill { 341029Sbill char line[LINSIZ]; 351029Sbill char comn; 361029Sbill char flag; 371029Sbill } line; 381029Sbill struct tab 391029Sbill { 401029Sbill char line[LINSIZ]; 411029Sbill char comn; 421029Sbill char xflag; 431029Sbill int pid; 445971Sroot time_t gettytime; 455971Sroot int gettycnt; 461029Sbill } itab[TABSIZ]; 471029Sbill 481029Sbill int fi; 491029Sbill int mergflag; 501029Sbill char tty[20]; 511429Sbill jmp_buf sjbuf, shutpass; 522821Swnj time_t time0; 531029Sbill 541029Sbill int reset(); 552821Swnj int idle(); 561029Sbill char *strcpy(), *strcat(); 571029Sbill long lseek(); 581029Sbill 59*13021Ssam struct sigvec rvec = { reset, mask(SIGHUP), 0 }; 60*13021Ssam 61*13021Ssam #ifdef vax 621029Sbill main() 631029Sbill { 641403Sbill register int r11; /* passed thru from boot */ 65*13021Ssam #else 669869Spugs main(argc, argv) 679869Spugs char **argv; 689869Spugs { 69*13021Ssam #endif 701403Sbill int howto, oldhowto; 711403Sbill 722821Swnj time0 = time(0); 73*13021Ssam #ifdef vax 741403Sbill howto = r11; 75*13021Ssam #else 769869Spugs if (argc > 1 && argv[1][0] == '-') { 779869Spugs char *cp; 789869Spugs 799869Spugs howto = 0; 809869Spugs cp = &argv[1][1]; 819869Spugs while (*cp) switch (*cp++) { 829869Spugs case 'a': 839869Spugs howto |= RB_ASKNAME; 849869Spugs break; 859869Spugs case 's': 869869Spugs howto |= RB_SINGLE; 879869Spugs break; 889869Spugs } 899869Spugs } else { 909869Spugs howto = RB_SINGLE; 919869Spugs } 92*13021Ssam #endif 93*13021Ssam sigvec(SIGTERM, &rvec, (struct sigvec *)0); 942821Swnj signal(SIGTSTP, idle); 951029Sbill signal(SIGSTOP, SIG_IGN); 961029Sbill signal(SIGTTIN, SIG_IGN); 971029Sbill signal(SIGTTOU, SIG_IGN); 98*13021Ssam (void) setjmp(sjbuf); 99*13021Ssam for (EVER) { 1001403Sbill oldhowto = howto; 1011403Sbill howto = RB_SINGLE; 1021429Sbill if (setjmp(shutpass) == 0) 1031429Sbill shutdown(); 1041403Sbill if (oldhowto & RB_SINGLE) 1051403Sbill single(); 1061403Sbill if (runcom(oldhowto) == 0) 1071403Sbill continue; 1081029Sbill merge(); 1091029Sbill multiple(); 1101029Sbill } 1111029Sbill } 1121029Sbill 1131429Sbill int shutreset(); 1141429Sbill 1151029Sbill shutdown() 1161029Sbill { 1171029Sbill register i; 1181029Sbill register struct tab *p; 1191029Sbill 1201029Sbill close(creat(utmp, 0644)); 1211029Sbill signal(SIGHUP, SIG_IGN); 122*13021Ssam for (ALL) { 1231029Sbill term(p); 1241029Sbill p->line[0] = 0; 1251029Sbill } 1261429Sbill signal(SIGALRM, shutreset); 1271429Sbill alarm(30); 128*13021Ssam for (i = 0; i < 5; i++) 1291029Sbill kill(-1, SIGKILL); 130*13021Ssam while (wait((int *)0) != -1) 1311029Sbill ; 1321029Sbill alarm(0); 1331429Sbill shutend(); 1341429Sbill } 1351429Sbill 1361429Sbill char shutfailm[] = "WARNING: Something is hung (wont die); ps axl advised\n"; 1371429Sbill 1381429Sbill shutreset() 1391429Sbill { 1401429Sbill int status; 1411429Sbill 1421429Sbill if (fork() == 0) { 1431429Sbill int ct = open(ctty, 1); 1441429Sbill write(ct, shutfailm, sizeof (shutfailm)); 1451429Sbill sleep(5); 1461429Sbill exit(1); 1471429Sbill } 1481429Sbill sleep(5); 1491429Sbill shutend(); 1501429Sbill longjmp(shutpass, 1); 1511429Sbill } 1521429Sbill 1531429Sbill shutend() 1541429Sbill { 1552821Swnj register i, f; 1561429Sbill 1572821Swnj acct(0); 1581029Sbill signal(SIGALRM, SIG_DFL); 159*13021Ssam for (i = 0; i < 10; i++) 1601029Sbill close(i); 161*13021Ssam f = open(wtmpf, O_WRONLY|O_APPEND); 1622821Swnj if (f >= 0) { 1632821Swnj SCPYN(wtmp.ut_line, "~"); 1642821Swnj SCPYN(wtmp.ut_name, "shutdown"); 16512682Ssam SCPYN(wtmp.ut_host, ""); 1662821Swnj time(&wtmp.ut_time); 1672821Swnj write(f, (char *)&wtmp, sizeof(wtmp)); 1682821Swnj close(f); 1692821Swnj } 170*13021Ssam return (1); 1711029Sbill } 1721029Sbill 1731029Sbill single() 1741029Sbill { 1751029Sbill register pid; 1762821Swnj register xpid; 1772821Swnj extern errno; 1781029Sbill 179*13021Ssam do { 180*13021Ssam pid = fork(); 181*13021Ssam if (pid == 0) { 182*13021Ssam signal(SIGTERM, SIG_DFL); 183*13021Ssam signal(SIGHUP, SIG_DFL); 184*13021Ssam signal(SIGALRM, SIG_DFL); 185*13021Ssam (void) open(ctty, O_RDWR); 186*13021Ssam dup2(0, 1); 187*13021Ssam dup2(0, 2); 188*13021Ssam execl(shell, minus, (char *)0); 189*13021Ssam exit(0); 190*13021Ssam } 191*13021Ssam while ((xpid = wait((int *)0)) != pid) 192*13021Ssam if (xpid == -1 && errno == ECHILD) 193*13021Ssam break; 194*13021Ssam } while (xpid == -1); 1951029Sbill } 1961029Sbill 1971403Sbill runcom(oldhowto) 1981403Sbill int oldhowto; 1991029Sbill { 2001029Sbill register pid, f; 2011403Sbill int status; 2021029Sbill 2031029Sbill pid = fork(); 204*13021Ssam if (pid == 0) { 205*13021Ssam (void) open("/", O_RDONLY); 206*13021Ssam dup2(0, 1); 207*13021Ssam dup2(0, 2); 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 } 214*13021Ssam while (wait(&status) != pid) 2151029Sbill ; 216*13021Ssam if (status) 217*13021Ssam return (0); 218*13021Ssam f = open(wtmpf, O_WRONLY|O_APPEND); 2191029Sbill if (f >= 0) { 2201029Sbill SCPYN(wtmp.ut_line, "~"); 2211029Sbill SCPYN(wtmp.ut_name, "reboot"); 22212682Ssam SCPYN(wtmp.ut_host, ""); 2232821Swnj if (time0) { 2242821Swnj wtmp.ut_time = time0; 2252821Swnj time0 = 0; 2262821Swnj } else 2272821Swnj time(&wtmp.ut_time); 2281029Sbill write(f, (char *)&wtmp, sizeof(wtmp)); 2291029Sbill close(f); 2301029Sbill } 231*13021Ssam return (1); 2321029Sbill } 2331029Sbill 234*13021Ssam struct sigvec mvec = { merge, mask(SIGTERM), 0 }; 235*13021Ssam /* 236*13021Ssam * Multi-user. Listen for users leaving, SIGHUP's 237*13021Ssam * which indicate ttys has changed, and SIGTERM's which 238*13021Ssam * are used to shutdown the system. 239*13021Ssam */ 2401029Sbill multiple() 2411029Sbill { 2421029Sbill register struct tab *p; 2431029Sbill register pid; 2441029Sbill 245*13021Ssam sigvec(SIGHUP, &mvec, (struct sigvec *)0); 246*13021Ssam for (EVER) { 2471029Sbill pid = wait((int *)0); 248*13021Ssam if (pid == -1) 2491029Sbill return; 250*13021Ssam for (ALL) 251*13021Ssam if (p->pid == pid || p->pid == -1) { 2521029Sbill rmut(p); 2531029Sbill dfork(p); 2541029Sbill } 2551029Sbill } 2561029Sbill } 2571029Sbill 258*13021Ssam /* 259*13021Ssam * Merge current contents of ttys file 260*13021Ssam * into in-core table of configured tty lines. 261*13021Ssam * Entered as signal handler for SIGHUP. 262*13021Ssam */ 263*13021Ssam #define FOUND 1 264*13021Ssam #define CHANGE 2 265*13021Ssam 266*13021Ssam merge() 267*13021Ssam { 268*13021Ssam register struct tab *p; 269*13021Ssam 270*13021Ssam fi = open(ifile, 0); 271*13021Ssam if (fi < 0) 272*13021Ssam return; 273*13021Ssam for (ALL) 274*13021Ssam p->xflag = 0; 275*13021Ssam while (rline()) { 276*13021Ssam for (ALL) { 277*13021Ssam if (SCMPN(p->line, line.line)) 278*13021Ssam continue; 279*13021Ssam p->xflag |= FOUND; 280*13021Ssam if (line.comn != p->comn) { 281*13021Ssam p->xflag |= CHANGE; 282*13021Ssam p->comn = line.comn; 283*13021Ssam } 284*13021Ssam goto contin1; 285*13021Ssam } 286*13021Ssam for (ALL) { 287*13021Ssam if (p->line[0] != 0) 288*13021Ssam continue; 289*13021Ssam SCPYN(p->line, line.line); 290*13021Ssam p->xflag |= FOUND|CHANGE; 291*13021Ssam p->comn = line.comn; 292*13021Ssam goto contin1; 293*13021Ssam } 294*13021Ssam contin1: 295*13021Ssam ; 296*13021Ssam } 297*13021Ssam close(fi); 298*13021Ssam for (ALL) { 299*13021Ssam if ((p->xflag&FOUND) == 0) { 300*13021Ssam term(p); 301*13021Ssam p->line[0] = 0; 302*13021Ssam } 303*13021Ssam if (p->xflag&CHANGE) { 304*13021Ssam term(p); 305*13021Ssam dfork(p); 306*13021Ssam } 307*13021Ssam } 308*13021Ssam } 309*13021Ssam 3101029Sbill term(p) 311*13021Ssam register struct tab *p; 3121029Sbill { 3131029Sbill 314*13021Ssam if (p->pid != 0) { 3151029Sbill rmut(p); 3161029Sbill kill(p->pid, SIGKILL); 3171029Sbill } 3181029Sbill p->pid = 0; 3191029Sbill } 3201029Sbill 3211029Sbill rline() 3221029Sbill { 3231029Sbill register c, i; 3241029Sbill 3251029Sbill loop: 3261029Sbill c = get(); 327*13021Ssam if (c < 0) 3281029Sbill return(0); 329*13021Ssam if (c == 0) 3301029Sbill goto loop; 3311029Sbill line.flag = c; 3321029Sbill c = get(); 333*13021Ssam if (c <= 0) 3341029Sbill goto loop; 3351029Sbill line.comn = c; 3361029Sbill SCPYN(line.line, ""); 337*13021Ssam for (i = 0; i < LINSIZ; i++) { 3381029Sbill c = get(); 339*13021Ssam if (c <= 0) 3401029Sbill break; 3411029Sbill line.line[i] = c; 3421029Sbill } 343*13021Ssam while (c > 0) 3441029Sbill c = get(); 345*13021Ssam if (line.line[0] == 0) 3461029Sbill goto loop; 347*13021Ssam if (line.flag == '0') 3481029Sbill goto loop; 3491029Sbill strcpy(tty, dev); 3501029Sbill strncat(tty, line.line, LINSIZ); 351*13021Ssam if (access(tty, 06) < 0) 3521029Sbill goto loop; 353*13021Ssam return (1); 3541029Sbill } 3551029Sbill 3561029Sbill get() 3571029Sbill { 3581029Sbill char b; 3591029Sbill 360*13021Ssam if (read(fi, &b, 1) != 1) 361*13021Ssam return (-1); 362*13021Ssam if (b == '\n') 363*13021Ssam return (0); 364*13021Ssam return (b); 3651029Sbill } 3661029Sbill 3676816Ssam #include <sys/ioctl.h> 3686816Ssam 3691029Sbill dfork(p) 370*13021Ssam struct tab *p; 3711029Sbill { 3721029Sbill register pid; 3735971Sroot time_t t; 3745971Sroot int dowait = 0; 3759579Spugs extern char *sys_errlist[]; 3761029Sbill 3775971Sroot time(&t); 3785971Sroot p->gettycnt++; 3795971Sroot if ((t - p->gettytime) >= 60) { 3805971Sroot p->gettytime = t; 3815971Sroot p->gettycnt = 1; 3825971Sroot } else { 3835971Sroot if (p->gettycnt >= 5) { 3845971Sroot dowait = 1; 3855971Sroot p->gettytime = t; 3865971Sroot p->gettycnt = 1; 3875971Sroot } 3885971Sroot } 3891029Sbill pid = fork(); 390*13021Ssam if (pid == 0) { 3916816Ssam int oerrno, f; 3926816Ssam extern int errno; 3936816Ssam 3946816Ssam signal(SIGTERM, SIG_DFL); 3956816Ssam signal(SIGHUP, SIG_IGN); 3969579Spugs strcpy(tty, dev); 3979579Spugs strncat(tty, p->line, LINSIZ); 3985971Sroot if (dowait) { 399*13021Ssam f = open("/dev/console", O_WRONLY); 4005971Sroot write(f, "init: ", 6); 4015971Sroot write(f, tty, strlen(tty)); 4025971Sroot write(f, ": getty failing, sleeping\n\r", 27); 4035971Sroot close(f); 4045971Sroot sleep(30); 405*13021Ssam if ((f = open("/dev/tty", O_RDWR)) >= 0) { 4066816Ssam ioctl(f, TIOCNOTTY, 0); 4076816Ssam close(f); 4086816Ssam } 4095971Sroot } 4101029Sbill chown(tty, 0, 0); 4111029Sbill chmod(tty, 0622); 412*13021Ssam if (open(tty, O_RDWR) < 0) { 4133608Swnj int repcnt = 0; 4143608Swnj do { 4156816Ssam oerrno = errno; 4163608Swnj if (repcnt % 10 == 0) { 417*13021Ssam f = open("/dev/console", O_WRONLY); 4183608Swnj write(f, "init: ", 6); 4199579Spugs write(f, tty, strlen(tty)); 4209579Spugs write(f, ": ", 2); 4219579Spugs write(f, sys_errlist[oerrno], 4229579Spugs strlen(sys_errlist[oerrno])); 4239579Spugs write(f, "\n", 1); 4243608Swnj close(f); 4256816Ssam if ((f = open("/dev/tty", 2)) >= 0) { 4266816Ssam ioctl(f, TIOCNOTTY, 0); 4276816Ssam close(f); 4286816Ssam } 4293608Swnj } 4303608Swnj repcnt++; 4313608Swnj sleep(60); 432*13021Ssam } while (open(tty, O_RDWR) < 0); 4333608Swnj exit(0); /* have wrong control tty, start over */ 4343608Swnj } 4351029Sbill vhangup(); 4361029Sbill signal(SIGHUP, SIG_DFL); 437*13021Ssam (void) open(tty, O_RDWR); 4381029Sbill close(0); 4391029Sbill dup(1); 4401029Sbill dup(0); 4411029Sbill tty[0] = p->comn; 4421029Sbill tty[1] = 0; 4431029Sbill execl(getty, minus, tty, (char *)0); 4441029Sbill exit(0); 4451029Sbill } 4461029Sbill p->pid = pid; 4471029Sbill } 4481029Sbill 449*13021Ssam /* 450*13021Ssam * Remove utmp entry. 451*13021Ssam */ 4521029Sbill rmut(p) 453*13021Ssam register struct tab *p; 4541029Sbill { 4551029Sbill register f; 4563608Swnj int found = 0; 4571029Sbill 458*13021Ssam f = open(utmp, O_RDWR); 459*13021Ssam if (f >= 0) { 460*13021Ssam 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, ""); 46512682Ssam 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) { 473*13021Ssam f = open(wtmpf, O_WRONLY|O_APPEND); 4743608Swnj if (f >= 0) { 4753608Swnj SCPYN(wtmp.ut_line, p->line); 4763608Swnj SCPYN(wtmp.ut_name, ""); 47712682Ssam SCPYN(wtmp.ut_host, ""); 4783608Swnj time(&wtmp.ut_time); 4793608Swnj write(f, (char *)&wtmp, sizeof(wtmp)); 4803608Swnj close(f); 4813608Swnj } 4821029Sbill } 4831029Sbill } 4841029Sbill 4851029Sbill reset() 4861029Sbill { 487*13021Ssam 4881029Sbill longjmp(sjbuf, 1); 4891029Sbill } 4902821Swnj 491*13021Ssam jmp_buf idlebuf; 492*13021Ssam 493*13021Ssam idlehup() 494*13021Ssam { 495*13021Ssam 496*13021Ssam longjmp(idlebuf, 1); 497*13021Ssam } 498*13021Ssam 4992821Swnj idle() 5002821Swnj { 5012821Swnj register struct tab *p; 5022821Swnj register pid; 5032821Swnj 504*13021Ssam signal(SIGHUP, idlehup); 5052821Swnj for (;;) { 506*13021Ssam if (setjmp(idlebuf)) 507*13021Ssam return; 5082821Swnj pid = wait((int *) 0); 509*13021Ssam if (pid == -1) { 510*13021Ssam sigpause(0); 511*13021Ssam continue; 5122821Swnj } 513*13021Ssam for (ALL) 514*13021Ssam if (p->pid == pid) { 515*13021Ssam rmut(p); 516*13021Ssam p->pid = -1; 517*13021Ssam } 5182821Swnj } 5192821Swnj } 520