X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/abf0db3c98127e2e5e7bb05300a64c2d72cd6134..a936c74edcf473626804be598fbf0044a07da2b2:/usr/src/old/init/init.c diff --git a/usr/src/old/init/init.c b/usr/src/old/init/init.c index 589979e587..6dd6295bce 100644 --- a/usr/src/old/init/init.c +++ b/usr/src/old/init/init.c @@ -1,11 +1,25 @@ -static char *sccsid = "@(#)init.c 4.3 (Berkeley) %G%"; +/* + * Copyright (c) 1980 Regents of the University of California. + * All rights reserved. The Berkeley software License Agreement + * specifies the terms and conditions for redistribution. + */ + +#ifndef lint +static char sccsid[] = "@(#)init.c 5.2 (Berkeley) %G%"; +#endif not lint + #include #include #include #include #include +#include +#include +#include +#include #define LINSIZ sizeof(wtmp.ut_line) +#define CMDSIZ 70 /* max string length for getty or window command*/ #define TABSIZ 100 #define ALL p = &itab[0]; p < &itab[TABSIZ]; p++ #define EVER ;; @@ -13,52 +27,80 @@ static char *sccsid = "@(#)init.c 4.3 (Berkeley) %G%"; #define SCMPN(a, b) strncmp(a, b, sizeof(a)) char shell[] = "/bin/sh"; -char getty[] = "/etc/getty"; char minus[] = "-"; char runc[] = "/etc/rc"; -char ifile[] = "/etc/ttys"; char utmp[] = "/etc/utmp"; char wtmpf[] = "/usr/adm/wtmp"; char ctty[] = "/dev/console"; -char dev[] = "/dev/"; struct utmp wtmp; -struct -{ - char line[LINSIZ]; - char comn; - char flag; -} line; struct tab { char line[LINSIZ]; - char comn; + char comn[CMDSIZ]; char xflag; int pid; + int wpid; /* window system pid for SIGHUP */ + char wcmd[CMDSIZ]; /* command to start window system process */ + time_t gettytime; + int gettycnt; + time_t windtime; + int windcnt; } itab[TABSIZ]; int fi; int mergflag; char tty[20]; jmp_buf sjbuf, shutpass; +time_t time0; int reset(); +int idle(); char *strcpy(), *strcat(); long lseek(); +struct sigvec rvec = { reset, sigmask(SIGHUP), 0 }; + +#ifdef vax main() { register int r11; /* passed thru from boot */ +#else +main(argc, argv) + char **argv; +{ +#endif int howto, oldhowto; + time0 = time(0); +#ifdef vax howto = r11; - setjmp(sjbuf); - signal(SIGTERM, reset); +#else + if (argc > 1 && argv[1][0] == '-') { + char *cp; + + howto = 0; + cp = &argv[1][1]; + while (*cp) switch (*cp++) { + case 'a': + howto |= RB_ASKNAME; + break; + case 's': + howto |= RB_SINGLE; + break; + } + } else { + howto = RB_SINGLE; + } +#endif + openlog("init", LOG_CONS|LOG_ODELAY, 0); + sigvec(SIGTERM, &rvec, (struct sigvec *)0); + signal(SIGTSTP, idle); signal(SIGSTOP, SIG_IGN); - signal(SIGTSTP, SIG_IGN); signal(SIGTTIN, SIG_IGN); signal(SIGTTOU, SIG_IGN); - for(EVER) { + (void) setjmp(sjbuf); + for (EVER) { oldhowto = howto; howto = RB_SINGLE; if (setjmp(shutpass) == 0) @@ -81,15 +123,15 @@ shutdown() close(creat(utmp, 0644)); signal(SIGHUP, SIG_IGN); - for(ALL) { + for (ALL) { term(p); p->line[0] = 0; } signal(SIGALRM, shutreset); alarm(30); - for(i=0; i<5; i++) + for (i = 0; i < 5; i++) kill(-1, SIGKILL); - while(wait((int *)0) != -1) + while (wait((int *)0) != -1) ; alarm(0); shutend(); @@ -114,33 +156,47 @@ shutreset() shutend() { - register i; + register i, f; + acct(0); signal(SIGALRM, SIG_DFL); - for(i=0; i<10; i++) + for (i = 0; i < 10; i++) close(i); + f = open(wtmpf, O_WRONLY|O_APPEND); + if (f >= 0) { + SCPYN(wtmp.ut_line, "~"); + SCPYN(wtmp.ut_name, "shutdown"); + SCPYN(wtmp.ut_host, ""); + time(&wtmp.ut_time); + write(f, (char *)&wtmp, sizeof(wtmp)); + close(f); + } + return (1); } single() { register pid; - - pid = fork(); - if(pid == 0) { -/* - alarm(300); -*/ - signal(SIGTERM, SIG_DFL); - signal(SIGHUP, SIG_DFL); - signal(SIGALRM, SIG_DFL); - open(ctty, 2); - dup(0); - dup(0); - execl(shell, minus, (char *)0); - exit(0); - } - while(wait((int *)0) != pid) - ; + register xpid; + extern errno; + + do { + pid = fork(); + if (pid == 0) { + signal(SIGTERM, SIG_DFL); + signal(SIGHUP, SIG_DFL); + signal(SIGALRM, SIG_DFL); + signal(SIGTSTP, SIG_IGN); + (void) open(ctty, O_RDWR); + dup2(0, 1); + dup2(0, 2); + execl(shell, minus, (char *)0); + exit(0); + } + while ((xpid = wait((int *)0)) != pid) + if (xpid == -1 && errno == ECHILD) + break; + } while (xpid == -1); } runcom(oldhowto) @@ -150,224 +206,355 @@ runcom(oldhowto) int status; pid = fork(); - if(pid == 0) { - open("/", 0); - dup(0); - dup(0); + if (pid == 0) { + (void) open("/", O_RDONLY); + dup2(0, 1); + dup2(0, 2); if (oldhowto & RB_SINGLE) execl(shell, shell, runc, (char *)0); else execl(shell, shell, runc, "autoboot", (char *)0); exit(1); } - while(wait(&status) != pid) + while (wait(&status) != pid) ; - if(status) - return(0); - f = open(wtmpf, 1); + if (status) + return (0); + f = open(wtmpf, O_WRONLY|O_APPEND); if (f >= 0) { - lseek(f, 0L, 2); SCPYN(wtmp.ut_line, "~"); SCPYN(wtmp.ut_name, "reboot"); - time(&wtmp.ut_time); + SCPYN(wtmp.ut_host, ""); + if (time0) { + wtmp.ut_time = time0; + time0 = 0; + } else + time(&wtmp.ut_time); write(f, (char *)&wtmp, sizeof(wtmp)); close(f); } - return(1); -} - -setmerge() -{ - - signal(SIGHUP, setmerge); - mergflag = 1; + return (1); } +struct sigvec mvec = { merge, sigmask(SIGTERM), 0 }; +/* + * Multi-user. Listen for users leaving, SIGHUP's + * which indicate ttys has changed, and SIGTERM's which + * are used to shutdown the system. + */ multiple() { register struct tab *p; register pid; -loop: - mergflag = 0; - signal(SIGHUP, setmerge); - for(EVER) { + sigvec(SIGHUP, &mvec, (struct sigvec *)0); + for (EVER) { pid = wait((int *)0); - if(mergflag) { - merge(); - goto loop; - } - if(pid == -1) + if (pid == -1) return; - for(ALL) - if(p->pid == pid || p->pid == -1) { + for (ALL) { + /* must restart window system BEFORE emulator */ + if (p->wpid == pid || p->wpid == -1) + wstart(p); + if (p->pid == pid || p->pid == -1) { + /* disown the window system */ + if (p->wpid) + kill(p->wpid, SIGHUP); rmut(p); dfork(p); } + } } } -term(p) -register struct tab *p; -{ - - if(p->pid != 0) { - rmut(p); - kill(p->pid, SIGKILL); - } - p->pid = 0; -} - -rline() -{ - register c, i; - -loop: - c = get(); - if(c < 0) - return(0); - if(c == 0) - goto loop; - line.flag = c; - c = get(); - if(c <= 0) - goto loop; - line.comn = c; - SCPYN(line.line, ""); - for (i=0; i 0) - c = get(); - if(line.line[0] == 0) - goto loop; - if(line.flag == '0') - goto loop; - strcpy(tty, dev); - strncat(tty, line.line, LINSIZ); - if(access(tty, 06) < 0) - goto loop; - return(1); -} - -get() -{ - char b; - - if(read(fi, &b, 1) != 1) - return(-1); - if(b == '\n') - return(0); - return(b); -} - +/* + * Merge current contents of ttys file + * into in-core table of configured tty lines. + * Entered as signal handler for SIGHUP. + */ #define FOUND 1 #define CHANGE 2 +#define WCHANGE 4 merge() { register struct tab *p; + register struct ttyent *t; - fi = open(ifile, 0); - if(fi < 0) - return; - for(ALL) + for (ALL) p->xflag = 0; - while(rline()) { - for(ALL) { - if (SCMPN(p->line, line.line)) + setttyent(); + while (t = getttyent()) { + if ((t->ty_status & TTY_ON) == 0) + continue; + for (ALL) { + if (SCMPN(p->line, t->ty_name)) continue; p->xflag |= FOUND; - if(line.comn != p->comn) { + if (SCMPN(p->comn, t->ty_getty)) { p->xflag |= CHANGE; - p->comn = line.comn; + SCPYN(p->comn, t->ty_getty); + } + if (SCMPN(p->wcmd, t->ty_window)) { + p->xflag |= WCHANGE|CHANGE; + SCPYN(p->wcmd, t->ty_window); } goto contin1; } - for(ALL) { - if(p->line[0] != 0) + + for (ALL) { + if (p->line[0] != 0) continue; - SCPYN(p->line, line.line); + SCPYN(p->line, t->ty_name); p->xflag |= FOUND|CHANGE; - p->comn = line.comn; + SCPYN(p->comn, t->ty_getty); + if (strcmp(t->ty_window, "") != 0) { + p->xflag |= WCHANGE; + SCPYN(p->wcmd, t->ty_window); + } goto contin1; } contin1: ; } - close(fi); - for(ALL) { - if((p->xflag&FOUND) == 0) { + endttyent(); + for (ALL) { + if ((p->xflag&FOUND) == 0) { term(p); p->line[0] = 0; + wterm(p); } - if((p->xflag&CHANGE) != 0) { + /* window system should be started first */ + if (p->xflag&WCHANGE) { + wterm(p); + wstart(p); + } + if (p->xflag&CHANGE) { term(p); dfork(p); } } } +term(p) + register struct tab *p; +{ + + if (p->pid != 0) { + rmut(p); + kill(p->pid, SIGKILL); + } + p->pid = 0; + /* send SIGHUP to get rid of connections */ + if (p->wpid > 0) + kill(p->wpid, SIGHUP); +} + +#include + dfork(p) -struct tab *p; + struct tab *p; { register pid; - + time_t t; + int dowait = 0; + + time(&t); + p->gettycnt++; + if ((t - p->gettytime) >= 60) { + p->gettytime = t; + p->gettycnt = 1; + } else if (p->gettycnt >= 5) { + dowait = 1; + p->gettytime = t; + p->gettycnt = 1; + } pid = fork(); - if(pid == 0) { + if (pid == 0) { signal(SIGTERM, SIG_DFL); signal(SIGHUP, SIG_IGN); - strcpy(tty, dev); - strncat(tty, p->line, LINSIZ); - chown(tty, 0, 0); - chmod(tty, 0622); - open(tty, 2); - vhangup(); - signal(SIGHUP, SIG_DFL); - open(tty, 2); - close(0); - dup(1); - dup(0); - tty[0] = p->comn; - tty[1] = 0; - execl(getty, minus, tty, (char *)0); + sigsetmask(0); /* since can be called from masked code */ + if (dowait) { + syslog(LOG_ERR, "'%s %s' failing, sleeping", p->comn, p->line); + closelog(); + sleep(30); + } + execit(p->comn, p->line); exit(0); } p->pid = pid; } +/* + * Remove utmp entry. + */ rmut(p) -register struct tab *p; + register struct tab *p; { register f; + int found = 0; - f = open(utmp, 2); - if(f >= 0) { - while(read(f, (char *)&wtmp, sizeof(wtmp)) == sizeof(wtmp)) { - if (SCMPN(wtmp.ut_line, p->line)) + f = open(utmp, O_RDWR); + if (f >= 0) { + while (read(f, (char *)&wtmp, sizeof(wtmp)) == sizeof(wtmp)) { + if (SCMPN(wtmp.ut_line, p->line) || wtmp.ut_name[0]==0) continue; lseek(f, -(long)sizeof(wtmp), 1); SCPYN(wtmp.ut_name, ""); + SCPYN(wtmp.ut_host, ""); time(&wtmp.ut_time); write(f, (char *)&wtmp, sizeof(wtmp)); + found++; } close(f); } - f = open(wtmpf, 1); - if (f >= 0) { - SCPYN(wtmp.ut_line, p->line); - SCPYN(wtmp.ut_name, ""); - time(&wtmp.ut_time); - lseek(f, (long)0, 2); - write(f, (char *)&wtmp, sizeof(wtmp)); - close(f); + if (found) { + f = open(wtmpf, O_WRONLY|O_APPEND); + if (f >= 0) { + SCPYN(wtmp.ut_line, p->line); + SCPYN(wtmp.ut_name, ""); + SCPYN(wtmp.ut_host, ""); + time(&wtmp.ut_time); + write(f, (char *)&wtmp, sizeof(wtmp)); + close(f); + } + /* + * After a proper login force reset + * of error detection code in dfork. + */ + p->gettytime = 0; + p->windtime = 0; } } reset() { + longjmp(sjbuf, 1); } + +jmp_buf idlebuf; + +idlehup() +{ + + longjmp(idlebuf, 1); +} + +idle() +{ + register struct tab *p; + register pid; + + signal(SIGHUP, idlehup); + for (EVER) { + if (setjmp(idlebuf)) + return; + pid = wait((int *) 0); + if (pid == -1) { + sigpause(0); + continue; + } + for (ALL) { + /* if window system dies, mark it for restart */ + if (p->wpid == pid) + p->wpid = -1; + if (p->pid == pid) { + rmut(p); + p->pid = -1; + } + } + } +} + +wterm(p) + register struct tab *p; +{ + if (p->wpid != 0) { + kill(p->wpid, SIGKILL); + } + p->wpid = 0; +} + +wstart(p) + register struct tab *p; +{ + register pid; + time_t t; + int dowait = 0; + + time(&t); + p->windcnt++; + if ((t - p->windtime) >= 60) { + p->windtime = t; + p->windcnt = 1; + } else if (p->windcnt >= 5) { + dowait = 1; + p->windtime = t; + p->windcnt = 1; + } + + pid = fork(); + + if (pid == 0) { + signal(SIGTERM, SIG_DFL); + signal(SIGHUP, SIG_IGN); + sigsetmask(0); /* since can be called from masked code */ + if (dowait) { + syslog(LOG_ERR, "'%s %s' failing, sleeping", p->wcmd, p->line); + closelog(); + sleep(30); + } + execit(p->wcmd, p->line); + exit(0); + } + p->wpid = pid; +} + +#define NARGS 20 /* must be at least 4 */ +#define ARGLEN 512 /* total size for all the argument strings */ + +execit(s, arg) + char *s; + char *arg; /* last argument on line */ +{ + char *argv[NARGS], args[ARGLEN], *envp[1]; + register char *sp = s; + register char *ap = args; + register char c; + register int i; + + /* + * First we have to set up the argument vector. + * "prog arg1 arg2" maps to exec("prog", "-", "arg1", "arg2"). + */ + for (i = 1; i < NARGS - 2; i++) { + argv[i] = ap; + for (EVER) { + if ((c = *sp++) == '\0' || ap >= &args[ARGLEN-1]) { + *ap = '\0'; + goto done; + } + if (c == ' ') { + *ap++ = '\0'; + while (*sp == ' ') + sp++; + if (*sp == '\0') + goto done; + break; + } + *ap++ = c; + } + } +done: + argv[0] = argv[1]; + argv[1] = "-"; + argv[i+1] = arg; + argv[i+2] = 0; + envp[0] = 0; + execve(argv[0], &argv[1], envp); + /* report failure of exec */ + syslog(LOG_ERR, "%s: %m", argv[0]); + closelog(); + sleep(10); /* prevent failures from eating machine */ +}