update for new file system
[unix-history] / usr / src / sbin / init / init.c
index 98baebc..89ccfff 100644 (file)
@@ -1,8 +1,10 @@
-static char *sccsid = "@(#)init.c      4.1 (Berkeley) %G%";
+static char *sccsid = "@(#)init.c      4.10 (Berkeley) %G%";
 #include <signal.h>
 #include <sys/types.h>
 #include <utmp.h>
 #include <setjmp.h>
 #include <signal.h>
 #include <sys/types.h>
 #include <utmp.h>
 #include <setjmp.h>
+#include <sys/reboot.h>
+#include <errno.h>
 
 #define        LINSIZ  sizeof(wtmp.ut_line)
 #define        TABSIZ  100
 
 #define        LINSIZ  sizeof(wtmp.ut_line)
 #define        TABSIZ  100
@@ -12,7 +14,7 @@ static char *sccsid = "@(#)init.c     4.1 (Berkeley) %G%";
 #define SCMPN(a, b)    strncmp(a, b, sizeof(a))
 
 char   shell[] = "/bin/sh";
 #define SCMPN(a, b)    strncmp(a, b, sizeof(a))
 
 char   shell[] = "/bin/sh";
-char   getty[]  = "/etc/getty.vm";
+char   getty[]  = "/etc/getty";
 char   minus[] = "-";
 char   runc[]  = "/etc/rc";
 char   ifile[] = "/etc/ttys";
 char   minus[] = "-";
 char   runc[]  = "/etc/rc";
 char   ifile[] = "/etc/ttys";
@@ -34,34 +36,75 @@ struct      tab
        char    comn;
        char    xflag;
        int     pid;
        char    comn;
        char    xflag;
        int     pid;
+       time_t  gettytime;
+       int     gettycnt;
 } itab[TABSIZ];
 
 int    fi;
 int    mergflag;
 char   tty[20];
 } itab[TABSIZ];
 
 int    fi;
 int    mergflag;
 char   tty[20];
-jmp_buf        sjbuf;
+jmp_buf        sjbuf, shutpass;
+time_t time0;
 
 int    reset();
 
 int    reset();
+int    idle();
 char   *strcpy(), *strcat();
 long   lseek();
 
 char   *strcpy(), *strcat();
 long   lseek();
 
+#ifndef sun
 main()
 {
 main()
 {
+       register int r11;               /* passed thru from boot */
+#else sun
+main(argc, argv)
+       char **argv;
+{
+#endif sun
+       int howto, oldhowto;
+
+       time0 = time(0);
+#ifndef sun
+       howto = r11;
+#else sun
+       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 sun
        setjmp(sjbuf);
        signal(SIGTERM, reset);
        setjmp(sjbuf);
        signal(SIGTERM, reset);
+       signal(SIGTSTP, idle);
        signal(SIGSTOP, SIG_IGN);
        signal(SIGSTOP, SIG_IGN);
-       signal(SIGTSTP, SIG_IGN);
        signal(SIGTTIN, SIG_IGN);
        signal(SIGTTOU, SIG_IGN);
        for(EVER) {
        signal(SIGTTIN, SIG_IGN);
        signal(SIGTTOU, SIG_IGN);
        for(EVER) {
-               shutdown();
-               single();
-               runcom();
+               oldhowto = howto;
+               howto = RB_SINGLE;
+               if (setjmp(shutpass) == 0)
+                       shutdown();
+               if (oldhowto & RB_SINGLE)
+                       single();
+               if (runcom(oldhowto) == 0) 
+                       continue;
                merge();
                multiple();
        }
 }
 
                merge();
                multiple();
        }
 }
 
+int    shutreset();
+
 shutdown()
 {
        register i;
 shutdown()
 {
        register i;
@@ -73,22 +116,60 @@ shutdown()
                term(p);
                p->line[0] = 0;
        }
                term(p);
                p->line[0] = 0;
        }
-       signal(SIGALRM, reset);
-       alarm(60);
+       signal(SIGALRM, shutreset);
+       alarm(30);
        for(i=0; i<5; i++)
                kill(-1, SIGKILL);
        while(wait((int *)0) != -1)
                ;
        alarm(0);
        for(i=0; i<5; i++)
                kill(-1, SIGKILL);
        while(wait((int *)0) != -1)
                ;
        alarm(0);
+       shutend();
+}
+
+char shutfailm[] = "WARNING: Something is hung (wont die); ps axl advised\n";
+
+shutreset()
+{
+       int status;
+
+       if (fork() == 0) {
+               int ct = open(ctty, 1);
+               write(ct, shutfailm, sizeof (shutfailm));
+               sleep(5);
+               exit(1);
+       }
+       sleep(5);
+       shutend();
+       longjmp(shutpass, 1);
+}
+
+shutend()
+{
+       register i, f;
+
+       acct(0);
        signal(SIGALRM, SIG_DFL);
        for(i=0; i<10; i++)
                close(i);
        signal(SIGALRM, SIG_DFL);
        for(i=0; i<10; i++)
                close(i);
+       f = open(wtmpf, 1);
+       if (f >= 0) {
+               lseek(f, 0L, 2);
+               SCPYN(wtmp.ut_line, "~");
+               SCPYN(wtmp.ut_name, "shutdown");
+               time(&wtmp.ut_time);
+               write(f, (char *)&wtmp, sizeof(wtmp));
+               close(f);
+       }
+       return(1);
 }
 
 single()
 {
        register pid;
 }
 
 single()
 {
        register pid;
+       register xpid;
+       extern  errno;
 
 
+   do {
        pid = fork();
        if(pid == 0) {
 /*
        pid = fork();
        if(pid == 0) {
 /*
@@ -103,33 +184,47 @@ single()
                execl(shell, minus, (char *)0);
                exit(0);
        }
                execl(shell, minus, (char *)0);
                exit(0);
        }
-       while(wait((int *)0) != pid)
-               ;
+       while((xpid = wait((int *)0)) != pid)
+               if (xpid == -1 && errno == ECHILD)
+                       break;
+   } while (xpid == -1);
 }
 
 }
 
-runcom()
+runcom(oldhowto)
+       int oldhowto;
 {
        register pid, f;
 {
        register pid, f;
+       int status;
 
        pid = fork();
        if(pid == 0) {
                open("/", 0);
                dup(0);
                dup(0);
 
        pid = fork();
        if(pid == 0) {
                open("/", 0);
                dup(0);
                dup(0);
-               execl(shell, shell, runc, (char *)0);
-               exit(0);
+               if (oldhowto & RB_SINGLE)
+                       execl(shell, shell, runc, (char *)0);
+               else
+                       execl(shell, shell, runc, "autoboot", (char *)0);
+               exit(1);
        }
        }
-       while(wait((int *)0) != pid)
+       while(wait(&status) != pid)
                ;
                ;
+       if(status)
+               return(0);
        f = open(wtmpf, 1);
        if (f >= 0) {
                lseek(f, 0L, 2);
                SCPYN(wtmp.ut_line, "~");
                SCPYN(wtmp.ut_name, "reboot");
        f = open(wtmpf, 1);
        if (f >= 0) {
                lseek(f, 0L, 2);
                SCPYN(wtmp.ut_line, "~");
                SCPYN(wtmp.ut_name, "reboot");
-               time(&wtmp.ut_time);
+               if (time0) {
+                       wtmp.ut_time = time0;
+                       time0 = 0;
+               } else
+                       time(&wtmp.ut_time);
                write(f, (char *)&wtmp, sizeof(wtmp));
                close(f);
        }
                write(f, (char *)&wtmp, sizeof(wtmp));
                close(f);
        }
+       return(1);
 }
 
 setmerge()
 }
 
 setmerge()
@@ -267,20 +362,74 @@ merge()
        }
 }
 
        }
 }
 
+#include <sys/ioctl.h>
+
 dfork(p)
 struct tab *p;
 {
        register pid;
 dfork(p)
 struct tab *p;
 {
        register pid;
-
+       time_t t;
+       int dowait = 0;
+       extern char *sys_errlist[];
+
+       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) {
        pid = fork();
        if(pid == 0) {
+               int oerrno, f;
+               extern int errno;
+
                signal(SIGTERM, SIG_DFL);
                signal(SIGHUP, SIG_IGN);
                strcpy(tty, dev);
                strncat(tty, p->line, LINSIZ);
                signal(SIGTERM, SIG_DFL);
                signal(SIGHUP, SIG_IGN);
                strcpy(tty, dev);
                strncat(tty, p->line, LINSIZ);
+               if (dowait) {
+                       f = open("/dev/console", 1);
+                       write(f, "init: ", 6);
+                       write(f, tty, strlen(tty));
+                       write(f, ": getty failing, sleeping\n\r", 27);
+                       close(f);
+                       sleep(30);
+                       if ((f = open("/dev/tty", 2)) >= 0) {
+                               ioctl(f, TIOCNOTTY, 0);
+                               close(f);
+                       }
+               }
                chown(tty, 0, 0);
                chmod(tty, 0622);
                chown(tty, 0, 0);
                chmod(tty, 0622);
-               open(tty, 2);
+               if (open(tty, 2) < 0) {
+                       int repcnt = 0;
+                       do {
+                               oerrno = errno;
+                               if (repcnt % 10 == 0) {
+                                       f = open("/dev/console", 1);
+                                       write(f, "init: ", 6);
+                                       write(f, tty, strlen(tty));
+                                       write(f, ": ", 2);
+                                       write(f, sys_errlist[oerrno],
+                                               strlen(sys_errlist[oerrno]));
+                                       write(f, "\n", 1);
+                                       close(f);
+                                       if ((f = open("/dev/tty", 2)) >= 0) {
+                                               ioctl(f, TIOCNOTTY, 0);
+                                               close(f);
+                                       }
+                               }
+                               repcnt++;
+                               sleep(60);
+                       } while (open(tty, 2) < 0);
+                       exit(0);        /* have wrong control tty, start over */
+               }
                vhangup();
                signal(SIGHUP, SIG_DFL);
                open(tty, 2);
                vhangup();
                signal(SIGHUP, SIG_DFL);
                open(tty, 2);
@@ -299,27 +448,31 @@ rmut(p)
 register struct tab *p;
 {
        register f;
 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)) {
 
        f = open(utmp, 2);
        if(f >= 0) {
                while(read(f, (char *)&wtmp, sizeof(wtmp)) == sizeof(wtmp)) {
-                       if (SCMPN(wtmp.ut_line, p->line))
+                       if (SCMPN(wtmp.ut_line, p->line) || wtmp.ut_name[0]==0)
                                continue;
                        lseek(f, -(long)sizeof(wtmp), 1);
                        SCPYN(wtmp.ut_name, "");
                        time(&wtmp.ut_time);
                        write(f, (char *)&wtmp, sizeof(wtmp));
                                continue;
                        lseek(f, -(long)sizeof(wtmp), 1);
                        SCPYN(wtmp.ut_name, "");
                        time(&wtmp.ut_time);
                        write(f, (char *)&wtmp, sizeof(wtmp));
+                       found++;
                }
                close(f);
        }
                }
                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, 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);
+               }
        }
 }
 
        }
 }
 
@@ -328,4 +481,24 @@ reset()
        longjmp(sjbuf, 1);
 }
 
        longjmp(sjbuf, 1);
 }
 
+idle()
+{
+       register struct tab *p;
+       register pid;
 
 
+       signal(SIGTSTP, idle);
+       for (;;) {
+               pid = wait((int *) 0);
+               if (mergflag)
+                       return;
+               if (pid == -1)
+                       pause();
+               else {
+                       for (ALL)
+                               if (p->pid == pid) {
+                                       rmut(p);
+                                       p->pid = -1;
+                               }
+               }
+       }
+}