make both 'q' and 'x' exit the interactive mode
[unix-history] / usr / src / sbin / shutdown / shutdown.c
index c9dce40..82dd9a7 100644 (file)
@@ -1,10 +1,13 @@
-static char *sccsid = "@(#)shutdown.c  4.8 (Berkeley) 81/06/11";
+#ifndef lint
+static char *sccsid = "@(#)shutdown.c  4.19 (Berkeley) 83/06/17";
+#endif
 
 #include <stdio.h>
 #include <ctype.h>
 #include <signal.h>
 #include <utmp.h>
 
 #include <stdio.h>
 #include <ctype.h>
 #include <signal.h>
 #include <utmp.h>
-#include <time.h>
+#include <sys/time.h>
+#include <sys/resource.h>
 #include <sys/types.h>
 /*
  *     /etc/shutdown when [messages]
 #include <sys/types.h>
 /*
  *     /etc/shutdown when [messages]
@@ -13,12 +16,6 @@ static       char *sccsid = "@(#)shutdown.c  4.8 (Berkeley) 81/06/11";
  *     of iminent shutdown of unix
  *     and shut it down automatically
  *     and even reboot or halt the machine if they desire
  *     of iminent shutdown of unix
  *     and shut it down automatically
  *     and even reboot or halt the machine if they desire
- *
- *             Ian Johnstone, Sydney, 1977
- *             Robert Elz, Melbourne, 1978
- *             Peter Lamb, Melbourne, 1980
- *             William Joy, Berkeley, 1981
- *             Michael Toy, Berkeley, 1981
  */
 #ifdef DEBUG
 #define LOGFILE "shutdown.log"
  */
 #ifdef DEBUG
 #define LOGFILE "shutdown.log"
@@ -33,6 +30,9 @@ static        char *sccsid = "@(#)shutdown.c  4.8 (Berkeley) 81/06/11";
 #define SECONDS
 #define NLOG           20              /* no of args possible for message */
 #define        NOLOGTIME       5 MINUTES
 #define SECONDS
 #define NLOG           20              /* no of args possible for message */
 #define        NOLOGTIME       5 MINUTES
+#define IGNOREUSER     "sleeper"
+
+char   hostname[32];
 
 int    do_nothing();
 time_t getsdt();
 
 int    do_nothing();
 time_t getsdt();
@@ -57,7 +57,8 @@ char  nologin[] = "nologin";
 #else
 char   nologin[] = "/etc/nologin";
 #endif
 #else
 char   nologin[] = "/etc/nologin";
 #endif
-int slots;
+time_t nowtime;
+
 struct interval {
        int stogo;
        int sint;
 struct interval {
        int stogo;
        int sint;
@@ -69,11 +70,13 @@ struct interval {
        15 MINUTES,     5 MINUTES,
        10 MINUTES,     5 MINUTES,
        5 MINUTES,      3 MINUTES,
        15 MINUTES,     5 MINUTES,
        10 MINUTES,     5 MINUTES,
        5 MINUTES,      3 MINUTES,
-       2 MINUTES,      30 SECONDS,
-       40 SECONDS,     10 SECONDS,
+       2 MINUTES,      1 MINUTES,
+       1 MINUTES,      30 SECONDS,
        0 SECONDS,      0 SECONDS
 };
        0 SECONDS,      0 SECONDS
 };
+
 char *shutter, *getlogin();
 char *shutter, *getlogin();
+
 main(argc,argv)
        int argc;
        char **argv;
 main(argc,argv)
        int argc;
        char **argv;
@@ -81,12 +84,13 @@ main(argc,argv)
        register i, ufd;
        register char **mess, *f;
        char *ts;
        register i, ufd;
        register char **mess, *f;
        char *ts;
-       long sdt;
+       time_t sdt;
        int h, m;
        int h, m;
-       long nowtime;
+       int first;
        FILE *termf;
 
        shutter = getlogin();
        FILE *termf;
 
        shutter = getlogin();
+       gethostname(hostname, sizeof (hostname));
        argc--, argv++;
        while (argc > 0 && (f = argv[0], *f++ == '-')) {
                while (i = *f++) switch (i) {
        argc--, argv++;
        while (argc > 0 && (f = argv[0], *f++ == '-')) {
                while (i = *f++) switch (i) {
@@ -114,6 +118,7 @@ main(argc,argv)
                fprintf(stderr, "NOT super-user\n");
                finish();
        }
                fprintf(stderr, "NOT super-user\n");
                finish();
        }
+       nowtime = time((time_t *)0);
        sdt = getsdt(argv[0]);
        argc--, argv++;
        i = 0;
        sdt = getsdt(argv[0]);
        argc--, argv++;
        i = 0;
@@ -121,7 +126,6 @@ main(argc,argv)
                if (i < NLOG)
                        nolog2[i++] = *argv++;
        nolog2[i] = NULL;
                if (i < NLOG)
                        nolog2[i++] = *argv++;
        nolog2[i] = NULL;
-       nowtime = time((long *)0);
        m = ((stogo = sdt - nowtime) + 30)/60;
        h = m/60; 
        m %= 60;
        m = ((stogo = sdt - nowtime) + 30)/60;
        h = m/60; 
        m %= 60;
@@ -135,31 +139,43 @@ main(argc,argv)
        signal(SIGQUIT, SIG_IGN);
        signal(SIGINT, SIG_IGN);
 #endif
        signal(SIGQUIT, SIG_IGN);
        signal(SIGINT, SIG_IGN);
 #endif
+       signal(SIGTTOU, SIG_IGN);
        signal(SIGTERM, finish);
        signal(SIGALRM, do_nothing);
        signal(SIGTERM, finish);
        signal(SIGALRM, do_nothing);
-       nice(-20);
+       setpriority(PRIO_PROCESS, 0, PRIO_MIN);
        fflush(stdout);
 #ifndef DEBUG
        if (i = fork()) {
                printf("[pid %d]\n", i);
                exit(0);
        }
        fflush(stdout);
 #ifndef DEBUG
        if (i = fork()) {
                printf("[pid %d]\n", i);
                exit(0);
        }
+#else
+       putc('\n', stdout);
 #endif
        sint = 1 HOURS;
        f = "";
 #endif
        sint = 1 HOURS;
        f = "";
+       ufd = open("/etc/utmp",0);
+       if (ufd < 0) {
+               perror("shutdown: /etc/utmp");
+               exit(1);
+       }
+       first = 1;
        for (;;) {
                for (i = 0; stogo <= interval[i].stogo && interval[i].sint; i++)
                        sint = interval[i].sint;
        for (;;) {
                for (i = 0; stogo <= interval[i].stogo && interval[i].sint; i++)
                        sint = interval[i].sint;
+               if (stogo > 0 && (stogo-sint) < interval[i].stogo)
+                       sint = stogo - interval[i].stogo;
                if (stogo <= NOLOGTIME && nlflag) {
                        nlflag = 0;
                        nolog(sdt);
                }
                if (sint >= stogo || sint == 0)
                        f = "FINAL ";
                if (stogo <= NOLOGTIME && nlflag) {
                        nlflag = 0;
                        nolog(sdt);
                }
                if (sint >= stogo || sint == 0)
                        f = "FINAL ";
-               ufd = open("/etc/utmp",0);
-               nowtime = time((long *) 0);
+               nowtime = time((time_t *) 0);
+               lseek(ufd, 0L, 0);
                while (read(ufd,&utmp,sizeof utmp)==sizeof utmp)
                while (read(ufd,&utmp,sizeof utmp)==sizeof utmp)
-               if (utmp.ut_name[0]) {
+               if (utmp.ut_name[0] &&
+                   strncmp(utmp.ut_name, IGNOREUSER, sizeof(utmp.ut_name))) {
                        strcpy(term, tpath);
                        strncat(term, utmp.ut_line, sizeof utmp.ut_line);
                        alarm(3);
                        strcpy(term, tpath);
                        strncat(term, utmp.ut_line, sizeof utmp.ut_line);
                        alarm(3);
@@ -171,11 +187,15 @@ main(argc,argv)
                        {
                                alarm(0);
                                setbuf(termf, tbuf);
                        {
                                alarm(0);
                                setbuf(termf, tbuf);
-                               fprintf(termf, "\n\n");
-                               warn(termf, sdt, nowtime);
-                               if (sdt - nowtime > 1 MINUTES)
+                               fprintf(termf, "\n\r\n");
+                               warn(termf, sdt, nowtime, f);
+                               if (first || sdt - nowtime > 1 MINUTES) {
+                                       if (*nolog2)
+                                               fprintf(termf, "\t...");
                                        for (mess = nolog2; *mess; mess++)
                                        for (mess = nolog2; *mess; mess++)
-                                               fprintf(termf, "%s ", *mess);
+                                               fprintf(termf, " %s", *mess);
+                               }
+                               fputc('\r', termf);
                                fputc('\n', termf);
                                alarm(5);
 #ifdef DEBUG
                                fputc('\n', termf);
                                alarm(5);
 #ifdef DEBUG
@@ -186,7 +206,7 @@ main(argc,argv)
                                alarm(0);
                        }
                }
                                alarm(0);
                        }
                }
-               if (stogo < 0) {
+               if (stogo <= 0) {
        printf("\n\007\007System shutdown time has arrived\007\007\n");
                        log_entry(sdt);
                        unlink(nologin);
        printf("\n\007\007System shutdown time has arrived\007\007\n");
                        log_entry(sdt);
                        unlink(nologin);
@@ -195,6 +215,8 @@ main(argc,argv)
                                finish();
                        }
 #ifndef DEBUG
                                finish();
                        }
 #ifndef DEBUG
+                       kill(-1, SIGTERM);      /* terminate everyone */
+                       sleep(5);               /* & wait while they die */
                        if (reboot)
                                execle(REBOOT, "reboot", 0, 0);
                        if (halt)
                        if (reboot)
                                execle(REBOOT, "reboot", 0, 0);
                        if (halt)
@@ -207,21 +229,24 @@ main(argc,argv)
 #endif
                        finish();
                }
 #endif
                        finish();
                }
-               stogo = sdt - time((long *) 0);
-               if (stogo > 0)
+               stogo = sdt - time((time_t *) 0);
+               if (stogo > 0 && sint > 0)
                        sleep(sint<stogo ? sint : stogo);
                stogo -= sint;
                        sleep(sint<stogo ? sint : stogo);
                stogo -= sint;
+               first = 0;
        }
 }
 
 time_t
 getsdt(s)
        }
 }
 
 time_t
 getsdt(s)
-register char *s;
+       register char *s;
 {
        time_t t, t1, tim;
        register char c;
        struct tm *lt;
 
 {
        time_t t, t1, tim;
        register char c;
        struct tm *lt;
 
+       if (strcmp(s, "now") == 0)
+               return(nowtime);
        if (*s == '+') {
                ++s; 
                t = 0;
        if (*s == '+') {
                ++s; 
                t = 0;
@@ -234,7 +259,7 @@ register char *s;
                if (t <= 0)
                        t = 5;
                t *= 60;
                if (t <= 0)
                        t = 5;
                t *= 60;
-               tim = time((long *) 0) + t;
+               tim = time((time_t *) 0) + t;
                return(tim);
        }
        t = 0;
                return(tim);
        }
        t = 0;
@@ -252,7 +277,7 @@ register char *s;
                goto badform;
        tim += t; 
        tim *= 60;
                goto badform;
        tim += t; 
        tim *= 60;
-       t1 = time((long *) 0);
+       t1 = time((time_t *) 0);
        lt = localtime(&t1);
        t = lt->tm_sec + lt->tm_min*60 + lt->tm_hour*3600;
        if (tim < t || tim >= (24*3600)) {
        lt = localtime(&t1);
        t = lt->tm_sec + lt->tm_min*60 + lt->tm_hour*3600;
        if (tim < t || tim >= (24*3600)) {
@@ -260,18 +285,19 @@ register char *s;
                printf("That must be tomorrow\nCan't you wait till then?\n");
                finish();
        }
                printf("That must be tomorrow\nCan't you wait till then?\n");
                finish();
        }
-       return (t1 + tim -t);
+       return (t1 + tim - t);
 badform:
        printf("Bad time format\n");
        finish();
 }
 
 badform:
        printf("Bad time format\n");
        finish();
 }
 
-warn(term, sdt, nowtime)
+warn(term, sdt, now, type)
        FILE *term;
        FILE *term;
-       long sdt, nowtime;
+       time_t sdt, now;
+       char *type;
 {
        char *ts;
 {
        char *ts;
-       register delay = std - nowtime;
+       register delay = sdt - now;
 
        if (delay > 8)
                while (delay % 5)
 
        if (delay > 8)
                while (delay % 5)
@@ -279,30 +305,33 @@ warn(term, sdt, nowtime)
 
        if (shutter)
                fprintf(term,
 
        if (shutter)
                fprintf(term,
-                   "\007\007*** System shutdown message from %s ***\n",
-                   shutter);
+           "\007\007\t*** %sSystem shutdown message from %s@%s ***\r\n\n",
+                   type, shutter, hostname);
        else
                fprintf(term,
        else
                fprintf(term,
-                   "\007\007*** System shutdown message ***\n");
+                   "\007\007\t*** %sSystem shutdown message (%s) ***\r\n\n",
+                   type, hostname);
+
        ts = ctime(&sdt);
        ts = ctime(&sdt);
-       if (delay> 10 MINUTES)
-               fprintf(term, "System going down at %5.5s\n", ts+11);
-       else if ( delay > 60 SECONDS ) {
-               fprintf(term, "System going down in %d minute%s\n",
-               (delay+30)/60, (delay+30)/60 != 1 ? "s" : "");
-       } else if ( delay > 0 ) {
-               fprintf(term, "System going down in %d second%s\n",
-               delay, delay != 1 ? "s" : "");
+       if (delay > 10 MINUTES)
+               fprintf(term, "System going down at %5.5s\r\n", ts+11);
+       else if (delay > 95 SECONDS) {
+               fprintf(term, "System going down in %d minute%s\r\n",
+                   (delay+30)/60, (delay+30)/60 != 1 ? "s" : "");
+       } else if (delay > 0) {
+               fprintf(term, "System going down in %d second%s\r\n",
+                   delay, delay != 1 ? "s" : "");
        } else
        } else
-               fprintf(term, "System going down IMMEDIATELY\n");
+               fprintf(term, "System going down IMMEDIATELY\r\n");
 }
 
 nolog(sdt)
 }
 
 nolog(sdt)
-       long sdt;
+       time_t sdt;
 {
        FILE *nologf;
        register char **mess;
 
 {
        FILE *nologf;
        register char **mess;
 
+       unlink(nologin);                        /* in case linked to std file */
        if ((nologf = fopen(nologin, "w")) != NULL) {
                fprintf(nologf, nolog1, (ctime(&sdt)) + 11);
                putc('\t', nologf);
        if ((nologf = fopen(nologin, "w")) != NULL) {
                fprintf(nologf, nolog1, (ctime(&sdt)) + 11);
                putc('\t', nologf);
@@ -340,7 +369,7 @@ char *months[] = {
 };
 
 log_entry(now)
 };
 
 log_entry(now)
-time_t now;
+       time_t now;
 {
        register FILE *fp;
        register char **mess;
 {
        register FILE *fp;
        register char **mess;
@@ -348,8 +377,10 @@ time_t now;
 
        tm = localtime(&now);
        fp = fopen(LOGFILE, "a");
 
        tm = localtime(&now);
        fp = fopen(LOGFILE, "a");
-       if (fp==0)
+       if (fp == NULL) {
+               printf("Shutdown: log entry failed\n");
                return;
                return;
+       }
        fseek(fp, 0L, 2);
        fprintf(fp, "%02d:%02d  %s %s %2d, %4d.  Shutdown:", tm->tm_hour,
                tm->tm_min, days[tm->tm_wday], months[tm->tm_mon],
        fseek(fp, 0L, 2);
        fprintf(fp, "%02d:%02d  %s %s %2d, %4d.  Shutdown:", tm->tm_hour,
                tm->tm_min, days[tm->tm_wday], months[tm->tm_mon],
@@ -357,7 +388,7 @@ time_t now;
        for (mess = nolog2; *mess; mess++)
                fprintf(fp, " %s", *mess);
        if (shutter)
        for (mess = nolog2; *mess; mess++)
                fprintf(fp, " %s", *mess);
        if (shutter)
-               fprintf(fp, " (by %s)", shutter);
+               fprintf(fp, " (by %s!%s)", hostname, shutter);
        fputc('\n', fp);
        fclose(fp);
 }
        fputc('\n', fp);
        fclose(fp);
 }