check in for bill
[unix-history] / usr / src / sbin / shutdown / shutdown.c
index 6715a51..e400a3f 100644 (file)
@@ -1,4 +1,4 @@
-/*     @(#)shutdown.c  4.1 (Berkeley/Melbourne) 81/02/07       */
+static char *sccsid = "@(#)shutdown.c  4.15 (Berkeley) 83/01/16";
 
 #include <stdio.h>
 #include <ctype.h>
 
 #include <stdio.h>
 #include <ctype.h>
  *     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
  */
  */
+#ifdef DEBUG
+#define LOGFILE "shutdown.log"
+#else
+#define LOGFILE "/usr/adm/shutdownlog"
+#endif
 #define        REBOOT  "/etc/reboot"
 #define        HALT    "/etc/halt"
 #define MAXINTS 20
 #define        HOURS   *3600
 #define MINUTES        *60
 #define SECONDS
 #define        REBOOT  "/etc/reboot"
 #define        HALT    "/etc/halt"
 #define MAXINTS 20
 #define        HOURS   *3600
 #define MINUTES        *60
 #define SECONDS
-#define NLOG           20              /* no of lines possible for message */
+#define NLOG           20              /* no of args possible for message */
 #define        NOLOGTIME       5 MINUTES
 #define        NOLOGTIME       5 MINUTES
+#define IGNOREUSER     "sleeper"
+
+char   hostname[32];
 
 int    do_nothing();
 time_t getsdt();
 
 int    do_nothing();
 time_t getsdt();
@@ -51,7 +54,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;
@@ -61,10 +65,15 @@ struct interval {
        1 HOURS,        15 MINUTES,
        30 MINUTES,     10 MINUTES,
        15 MINUTES,     5 MINUTES,
        1 HOURS,        15 MINUTES,
        30 MINUTES,     10 MINUTES,
        15 MINUTES,     5 MINUTES,
-       10 MINUTES,     2 MINUTES,
-       2 MINUTES,      30 SECONDS,
+       10 MINUTES,     5 MINUTES,
+       5 MINUTES,      3 MINUTES,
+       2 MINUTES,      1 MINUTES,
+       1 MINUTES,      30 SECONDS,
        0 SECONDS,      0 SECONDS
 };
        0 SECONDS,      0 SECONDS
 };
+
+char *shutter, *getlogin();
+
 main(argc,argv)
        int argc;
        char **argv;
 main(argc,argv)
        int argc;
        char **argv;
@@ -72,11 +81,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;
 
        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) {
@@ -96,10 +107,15 @@ main(argc,argv)
                argc--, argv++;
        }
        if (argc < 1) {
                argc--, argv++;
        }
        if (argc < 1) {
-               printf("Usage: %s [-krd] shutdowntime [nologmessage]\n",
+               printf("Usage: %s [ -krh ] shutdowntime [ message ]\n",
                    argv[0]);
                finish();
        }
                    argv[0]);
                finish();
        }
+       if (geteuid()) {
+               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;
@@ -107,16 +123,14 @@ 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;
        ts = ctime(&sdt);
        m = ((stogo = sdt - nowtime) + 30)/60;
        h = m/60; 
        m %= 60;
        ts = ctime(&sdt);
-       printf("Shutdown at %5.5s\n", ts+11);
-       printf("ie. in ");
+       printf("Shutdown at %5.5s (in ", ts+11);
        if (h > 0)
                printf("%d hour%s ", h, h != 1 ? "s" : "");
        if (h > 0)
                printf("%d hour%s ", h, h != 1 ? "s" : "");
-       printf("%d minute%s\n", m, m != 1 ? "s" : "");
+       printf("%d minute%s", m, m != 1 ? "s" : "");
 #ifndef DEBUG
        signal(SIGHUP, SIG_IGN);
        signal(SIGQUIT, SIG_IGN);
 #ifndef DEBUG
        signal(SIGHUP, SIG_IGN);
        signal(SIGQUIT, SIG_IGN);
@@ -125,54 +139,80 @@ main(argc,argv)
        signal(SIGTERM, finish);
        signal(SIGALRM, do_nothing);
        nice(-20);
        signal(SIGTERM, finish);
        signal(SIGALRM, do_nothing);
        nice(-20);
+       fflush(stdout);
+#ifndef DEBUG
        if (i = fork()) {
        if (i = fork()) {
-               printf("%d\n", i);
+               printf("[pid %d]\n", i);
                exit(0);
        }
                exit(0);
        }
+#else
+       putc('\n', stdout);
+#endif
        sint = 1 HOURS;
        f = "";
        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);
 #ifdef DEBUG
                        strcpy(term, tpath);
                        strncat(term, utmp.ut_line, sizeof utmp.ut_line);
                        alarm(3);
 #ifdef DEBUG
-                       if ((termf = fopen("/dev/tty", "w")) != NULL)
+                       if ((termf = stdout) != NULL)
 #else
                        if ((termf = fopen(term, "w")) != NULL)
 #endif
                        {
                                alarm(0);
                                setbuf(termf, tbuf);
 #else
                        if ((termf = fopen(term, "w")) != NULL)
 #endif
                        {
                                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);
                                fputc('\n', termf);
+                               alarm(5);
+#ifdef DEBUG
+                               fflush(termf);
+#else
                                fclose(termf);
                                fclose(termf);
+#endif
                                alarm(0);
                        }
                }
                                alarm(0);
                        }
                }
-               if (stogo < 0) {
+               if (stogo <= 0) {
        printf("\n\007\007System shutdown time has arrived\007\007\n");
        printf("\n\007\007System shutdown time has arrived\007\007\n");
+                       log_entry(sdt);
                        unlink(nologin);
                        if (!killflg) {
                                printf("but you'll have to do it yourself\n");
                                finish();
                        }
 #ifndef DEBUG
                        unlink(nologin);
                        if (!killflg) {
                                printf("but you'll have to do it yourself\n");
                                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)
@@ -185,21 +225,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;
@@ -212,7 +255,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;
@@ -230,7 +273,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)) {
@@ -238,41 +281,59 @@ 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 = sdt - now;
+
+       if (delay > 8)
+               while (delay % 5)
+                       delay++;
+
+       if (shutter)
+               fprintf(term,
+           "\007\007\t*** %sSystem shutdown message from %s!%s ***\r\n\n",
+                   type, hostname, shutter);
+       else
+               fprintf(term,
+                   "\007\007\t*** %sSystem shutdown message (%s) ***\r\n\n",
+                   type, hostname);
 
        ts = ctime(&sdt);
 
        ts = ctime(&sdt);
-       if (sdt - nowtime > 10 MINUTES)
-               fprintf(term, "System going down at %5.5s\n", ts+11);
-       else if ( sdt - nowtime > 60 SECONDS ) {
-               fprintf(term, "System going down in %d minute%s\n",
-               (sdt-nowtime+30)/60, (sdt-nowtime+30)/60 != 1 ? "s" : "");
-       } else if ( sdt - nowtime > 0 ) {
-               fprintf(term, "System going down in %d seconds\n",
-               sdt-nowtime, sdt-nowtime != 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);
        if ((nologf = fopen(nologin, "w")) != NULL) {
                fprintf(nologf, nolog1, (ctime(&sdt)) + 11);
+               putc('\t', nologf);
                for (mess = nolog2; *mess; mess++)
                for (mess = nolog2; *mess; mess++)
-                       fprintf(nologf, "\t%s\n", *mess);
+                       fprintf(nologf, " %s", *mess);
+               putc('\n', nologf);
                fclose(nologf);
        }
 }
                fclose(nologf);
        }
 }
@@ -289,3 +350,41 @@ do_nothing()
 
        signal(SIGALRM, do_nothing);
 }
 
        signal(SIGALRM, do_nothing);
 }
+
+/*
+ * make an entry in the shutdown log
+ */
+
+char *days[] = {
+       "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
+};
+
+char *months[] = {
+       "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep",
+       "Oct", "Nov", "Dec"
+};
+
+log_entry(now)
+       time_t now;
+{
+       register FILE *fp;
+       register char **mess;
+       struct tm *tm, *localtime();
+
+       tm = localtime(&now);
+       fp = fopen(LOGFILE, "a");
+       if (fp == NULL) {
+               printf("Shutdown: log entry failed\n");
+               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],
+               tm->tm_mday, tm->tm_year + 1900);
+       for (mess = nolog2; *mess; mess++)
+               fprintf(fp, " %s", *mess);
+       if (shutter)
+               fprintf(fp, " (by %s!%s)", hostname, shutter);
+       fputc('\n', fp);
+       fclose(fp);
+}