BSD 4_4 release
[unix-history] / usr / src / sbin / shutdown / shutdown.c
index 86c9c1e..79cdfd9 100644 (file)
@@ -1,28 +1,44 @@
 /*
 /*
- * Copyright (c) 1988 Regents of the University of California.
- * All rights reserved.
+ * Copyright (c) 1988, 1990, 1993
+ *     The Regents of the University of California.  All rights reserved.
  *
  *
- * Redistribution and use in source and binary forms are permitted
- * provided that the above copyright notice and this paragraph are
- * duplicated in all such forms and that any documentation,
- * advertising materials, and other materials related to such
- * distribution and use acknowledge that the software was developed
- * by the University of California, Berkeley.  The name of the
- * University may not be used to endorse or promote products derived
- * from this software without specific prior written permission.
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-char copyright[] =
-"@(#) Copyright (c) 1988 Regents of the University of California.\n\
- All rights reserved.\n";
+static char copyright[] =
+"@(#) Copyright (c) 1988, 1990, 1993\n\
      The Regents of the University of California.  All rights reserved.\n";
 #endif /* not lint */
 
 #ifndef lint
 #endif /* not lint */
 
 #ifndef lint
-static char sccsid[] = "@(#)shutdown.c 5.8 (Berkeley) %G%";
+static char sccsid[] = "@(#)shutdown.c 8.1 (Berkeley) 6/5/93";
 #endif /* not lint */
 
 #include <sys/param.h>
 #endif /* not lint */
 
 #include <sys/param.h>
@@ -30,22 +46,19 @@ static char sccsid[] = "@(#)shutdown.c      5.8 (Berkeley) %G%";
 #include <sys/file.h>
 #include <sys/resource.h>
 #include <sys/syslog.h>
 #include <sys/file.h>
 #include <sys/resource.h>
 #include <sys/syslog.h>
-#include <signal.h>
+#include <sys/signal.h>
 #include <setjmp.h>
 #include <tzfile.h>
 #include <pwd.h>
 #include <stdio.h>
 #include <ctype.h>
 #include <setjmp.h>
 #include <tzfile.h>
 #include <pwd.h>
 #include <stdio.h>
 #include <ctype.h>
-
-#define        REBOOT          "/etc/reboot"
-#define        HALT            "/etc/halt"
+#include "pathnames.h"
 
 #ifdef DEBUG
 
 #ifdef DEBUG
-#define        NOLOGIN         "./nologin"
-#define        FASTBOOT        "./fastboot"
-#else
-#define        NOLOGIN         "/etc/nologin"
-#define        FASTBOOT        "/fastboot"
+#undef _PATH_NOLOGIN
+#define        _PATH_NOLOGIN   "./nologin"
+#undef _PATH_FASTBOOT
+#define        _PATH_FASTBOOT  "./fastboot"
 #endif
 
 #define        H               *60*60
 #endif
 
 #define        H               *60*60
@@ -73,21 +86,25 @@ main(argc, argv)
        char **argv;
 {
        extern int optind;
        char **argv;
 {
        extern int optind;
-       register char *p;
-       int arglen, ch, len;
-       struct passwd *pw, *getpwuid();
+       register char *p, *endp;
+       int arglen, ch, len, readstdin;
+       struct passwd *pw;
        char *strcat(), *getlogin();
        uid_t geteuid();
 
 #ifndef DEBUG
        if (geteuid()) {
        char *strcat(), *getlogin();
        uid_t geteuid();
 
 #ifndef DEBUG
        if (geteuid()) {
-               fprintf(stderr, "shutdown: NOT super-user\n");
+               (void)fprintf(stderr, "shutdown: NOT super-user\n");
                exit(1);
        }
 #endif
                exit(1);
        }
 #endif
-       nosync = "";
-       while ((ch = getopt(argc, argv, "fhknr")) != EOF)
-               switch((char)ch) {
+       nosync = NULL;
+       readstdin = 0;
+       while ((ch = getopt(argc, argv, "-fhknr")) != EOF)
+               switch (ch) {
+               case '-':
+                       readstdin = 1;
+                       break;
                case 'f':
                        dofast = 1;
                        break;
                case 'f':
                        dofast = 1;
                        break;
@@ -113,36 +130,52 @@ main(argc, argv)
        if (argc < 1)
                usage();
 
        if (argc < 1)
                usage();
 
-       if (dofast && *nosync) {
-               fprintf(stderr,
+       if (dofast && nosync) {
+               (void)fprintf(stderr,
                    "shutdown: incompatible switches -f and -n.\n");
                usage();
        }
        if (doreboot && dohalt) {
                    "shutdown: incompatible switches -f and -n.\n");
                usage();
        }
        if (doreboot && dohalt) {
-               fprintf(stderr, 
+               (void)fprintf(stderr,
                    "shutdown: incompatible switches -h and -r.\n");
                usage();
        }
        getoffset(*argv++);
                    "shutdown: incompatible switches -h and -r.\n");
                usage();
        }
        getoffset(*argv++);
+
        if (*argv) {
        if (*argv) {
-               do {
-                       (void)strcat(mbuf, *argv);
-                       (void)strcat(mbuf, " ");
-               } while(*++argv);
-               (void)strcat(mbuf, "\n");
+               for (p = mbuf, len = sizeof(mbuf); *argv; ++argv) {
+                       arglen = strlen(*argv);
+                       if ((len -= arglen) <= 2)
+                               break;
+                       if (p != mbuf)
+                               *p++ = ' ';
+                       bcopy(*argv, p, arglen);
+                       p += arglen;
+               }
+               *p = '\n';
+               *++p = '\0';
        }
        }
-       else for (len = sizeof(mbuf), p = mbuf; fgets(p, len, stdin);) {
-               arglen = strlen(p);
-               if (!(len -= arglen))
-                       break;
-               p += arglen;
+
+       if (readstdin) {
+               p = mbuf;
+               endp = mbuf + sizeof(mbuf) - 2;
+               for (;;) {
+                       if (!fgets(p, endp - p + 1, stdin))
+                               break;
+                       for (; *p &&  p < endp; ++p);
+                       if (p == endp) {
+                               *p = '\n';
+                               *++p = '\0';
+                               break;
+                       }
+               }
        }
        mbuflen = strlen(mbuf);
 
        if (offset)
        }
        mbuflen = strlen(mbuf);
 
        if (offset)
-               printf("Shutdown at %.24s.", ctime(&shuttime));
+               (void)printf("Shutdown at %.24s.\n", ctime(&shuttime));
        else
        else
-               printf("Shutdown NOW!\n");
+               (void)printf("Shutdown NOW!\n");
 
        if (!(whom = getlogin()))
                whom = (pw = getpwuid(getuid())) ? pw->pw_name : "???";
 
        if (!(whom = getlogin()))
                whom = (pw = getpwuid(getuid())) ? pw->pw_name : "???";
@@ -160,7 +193,7 @@ main(argc, argv)
                        exit(1);
                }
                if (forkpid) {
                        exit(1);
                }
                if (forkpid) {
-                       printf("shutdown: [pid %d]\n", forkpid);
+                       (void)printf("shutdown: [pid %d]\n", forkpid);
                        exit(0);
                }
        }
                        exit(0);
                }
        }
@@ -170,8 +203,6 @@ main(argc, argv)
        /*NOTREACHED*/
 }
 
        /*NOTREACHED*/
 }
 
-#define        WALL_CMD        "/bin/wall"
-
 loop()
 {
        u_int sltime;
 loop()
 {
        u_int sltime;
@@ -217,48 +248,54 @@ static jmp_buf alarmbuf;
 warn()
 {
        static int first;
 warn()
 {
        static int first;
-       static char hostname[MAXHOSTNAMELEN];
+       static char hostname[MAXHOSTNAMELEN + 1];
+       char wcmd[MAXPATHLEN + 4];
        FILE *pf;
        char *ctime();
        FILE *pf;
        char *ctime();
-       int timeout();
+       void timeout();
 
 
-       if (!first++) {
-               (void)signal(SIGALRM, timeout);
+       if (!first++)
                (void)gethostname(hostname, sizeof(hostname));
                (void)gethostname(hostname, sizeof(hostname));
-       }
 
 
-       if (!(pf = popen(WALL_CMD, "w"))) {
-               syslog(LOG_ERR, "shutdown: can't find %s: %m", WALL_CMD);
+       /* undoc -n option to wall suppresses normal wall banner */
+       (void)sprintf(wcmd, "%s -n", _PATH_WALL);
+       if (!(pf = popen(wcmd, "w"))) {
+               syslog(LOG_ERR, "shutdown: can't find %s: %m", _PATH_WALL);
                return;
        }
 
                return;
        }
 
-       fprintf(pf, "*** %sSystem shutdown message ***\n",
-           tp->timeleft ? "": "FINAL ");
+       (void)fprintf(pf,
+           "\007*** %sSystem shutdown message from %s@%s ***\007\n",
+           tp->timeleft ? "": "FINAL ", whom, hostname);
 
        if (tp->timeleft > 10*60)
 
        if (tp->timeleft > 10*60)
-               fprintf(pf, "System going down at %5.5s\n\n",
+               (void)fprintf(pf, "System going down at %5.5s\n\n",
                    ctime(&shuttime) + 11);
        else if (tp->timeleft > 59)
                    ctime(&shuttime) + 11);
        else if (tp->timeleft > 59)
-               fprintf(pf, "System going down in %d minute%s\n\n",
+               (void)fprintf(pf, "System going down in %d minute%s\n\n",
                    tp->timeleft / 60, (tp->timeleft > 60) ? "s" : "");
        else if (tp->timeleft)
                    tp->timeleft / 60, (tp->timeleft > 60) ? "s" : "");
        else if (tp->timeleft)
-               fprintf(pf, "System going down in 30 seconds\n\n");
+               (void)fprintf(pf, "System going down in 30 seconds\n\n");
        else
        else
-               fprintf(pf, "System going down IMMEDIATELY\n\n");
+               (void)fprintf(pf, "System going down IMMEDIATELY\n\n");
 
 
-       (void)fwrite(mbuf, sizeof(*mbuf), mbuflen, pf);
+       if (mbuflen)
+               (void)fwrite(mbuf, sizeof(*mbuf), mbuflen, pf);
 
        /*
         * play some games, just in case wall doesn't come back
         * probably unecessary, given that wall is careful.
         */
        if (!setjmp(alarmbuf)) {
 
        /*
         * play some games, just in case wall doesn't come back
         * probably unecessary, given that wall is careful.
         */
        if (!setjmp(alarmbuf)) {
+               (void)signal(SIGALRM, timeout);
                (void)alarm((u_int)30);
                (void)pclose(pf);
                (void)alarm((u_int)0);
                (void)alarm((u_int)30);
                (void)pclose(pf);
                (void)alarm((u_int)0);
+               (void)signal(SIGALRM, SIG_DFL);
        }
 }
 
        }
 }
 
+void
 timeout()
 {
        longjmp(alarmbuf, 1);
 timeout()
 {
        longjmp(alarmbuf, 1);
@@ -266,36 +303,38 @@ timeout()
 
 die_you_gravy_sucking_pig_dog()
 {
 
 die_you_gravy_sucking_pig_dog()
 {
+       void finish();
+
        syslog(LOG_NOTICE, "%s by %s: %s",
            doreboot ? "reboot" : dohalt ? "halt" : "shutdown", whom, mbuf);
        (void)sleep(2);
 
        syslog(LOG_NOTICE, "%s by %s: %s",
            doreboot ? "reboot" : dohalt ? "halt" : "shutdown", whom, mbuf);
        (void)sleep(2);
 
-       printf("\r\nSystem shutdown time has arrived\007\007\r\n");
+       (void)printf("\r\nSystem shutdown time has arrived\007\007\r\n");
        if (killflg) {
        if (killflg) {
-               printf("\rbut you'll have to do it yourself\r\n");
+               (void)printf("\rbut you'll have to do it yourself\r\n");
                finish();
        }
        if (dofast)
                doitfast();
 #ifdef DEBUG
        if (doreboot)
                finish();
        }
        if (dofast)
                doitfast();
 #ifdef DEBUG
        if (doreboot)
-               printf("REBOOT");
-       if (dohalt)
-               printf(" HALT");
+               (void)printf("reboot");
+       else if (dohalt)
+               (void)printf("halt");
+       if (nosync)
+               (void)printf(" no sync");
        if (dofast)
        if (dofast)
-               printf(" -l %s (without fsck's)\n", nosync);
-       else
-               printf(" -l %s\n", nosync);
-       printf("kill -HUP 1\n");
+               (void)printf(" no fsck");
+       (void)printf("\nkill -HUP 1\n");
 #else
        if (doreboot) {
 #else
        if (doreboot) {
-               execle(REBOOT, "reboot", "-l", nosync, 0, 0);
-               syslog(LOG_ERR, "shutdown: can't exec %s: %m.", REBOOT);
+               execle(_PATH_REBOOT, "reboot", "-l", nosync, 0);
+               syslog(LOG_ERR, "shutdown: can't exec %s: %m.", _PATH_REBOOT);
                perror("shutdown");
        }
        else if (dohalt) {
                perror("shutdown");
        }
        else if (dohalt) {
-               execle(HALT, "halt", "-l", nosync, 0, 0);
-               syslog(LOG_ERR, "shutdown: can't exec %s: %m.", HALT);
+               execle(_PATH_HALT, "halt", "-l", nosync, 0);
+               syslog(LOG_ERR, "shutdown: can't exec %s: %m.", _PATH_HALT);
                perror("shutdown");
        }
        (void)kill(1, SIGTERM);         /* to single user */
                perror("shutdown");
        }
        (void)kill(1, SIGTERM);         /* to single user */
@@ -304,8 +343,6 @@ die_you_gravy_sucking_pig_dog()
 }
 
 #define        ATOI2(p)        (p[0] - '0') * 10 + (p[1] - '0'); p += 2;
 }
 
 #define        ATOI2(p)        (p[0] - '0') * 10 + (p[1] - '0'); p += 2;
-static int dmsize[] =
-       { -1, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
 
 getoffset(timearg)
        register char *timearg;
 
 getoffset(timearg)
        register char *timearg;
@@ -313,7 +350,6 @@ getoffset(timearg)
        register struct tm *lt;
        register char *p;
        time_t now, time();
        register struct tm *lt;
        register char *p;
        time_t now, time();
-       int year, month, day, hour, min;
 
        if (!strcasecmp(timearg, "now")) {              /* now */
                offset = 0;
 
        if (!strcasecmp(timearg, "now")) {              /* now */
                offset = 0;
@@ -323,9 +359,8 @@ getoffset(timearg)
        (void)time(&now);
        if (*timearg == '+') {                          /* +minutes */
                if (!isdigit(*++timearg))
        (void)time(&now);
        if (*timearg == '+') {                          /* +minutes */
                if (!isdigit(*++timearg))
-                       goto badtime;
-               min = atoi(timearg);
-               offset = min * 60;
+                       badtime();
+               offset = atoi(timearg) * 60;
                shuttime = now + offset;
                return;
        }
                shuttime = now + offset;
                return;
        }
@@ -339,51 +374,43 @@ getoffset(timearg)
                                p[2] = '\0';
                        }
                        else
                                p[2] = '\0';
                        }
                        else
-                               goto badtime;
+                               badtime();
 
        unsetenv("TZ");                                 /* OUR timezone */
 
        unsetenv("TZ");                                 /* OUR timezone */
-       lt = localtime(&now);                           /* [yymmdd]hhmm */
-       year = lt->tm_year;
-       month = lt->tm_mon + 1;
-       day = lt->tm_mday;
+       lt = localtime(&now);                           /* current time val */
 
        switch(strlen(timearg)) {
        case 10:
 
        switch(strlen(timearg)) {
        case 10:
-               year = ATOI2(timearg);
+               lt->tm_year = ATOI2(timearg);
                /* FALLTHROUGH */
        case 8:
                /* FALLTHROUGH */
        case 8:
-               month = ATOI2(timearg);
+               lt->tm_mon = ATOI2(timearg);
+               if (--lt->tm_mon < 0 || lt->tm_mon > 11)
+                       badtime();
                /* FALLTHROUGH */
        case 6:
                /* FALLTHROUGH */
        case 6:
-               day = ATOI2(timearg);
+               lt->tm_mday = ATOI2(timearg);
+               if (lt->tm_mday < 1 || lt->tm_mday > 31)
+                       badtime();
                /* FALLTHROUGH */
        case 4:
                /* FALLTHROUGH */
        case 4:
-               hour = ATOI2(timearg);
-               min = ATOI2(timearg);
-               if (month < 1 || month > 12 || day < 1 || day > 31 ||
-                   hour < 0 || hour > 23 || min < 0 || min > 59)
-                       goto badtime;
-               shuttime = 0;
-               year += TM_YEAR_BASE;
-               if (isleap(year) && month > 2)
-                       ++shuttime;
-               for (--year; year >= EPOCH_YEAR; --year)
-                       shuttime += isleap(year) ?
-                           DAYS_PER_LYEAR : DAYS_PER_NYEAR;
-               while (--month)
-                       shuttime += dmsize[month];
-               shuttime += day - 1;
-               shuttime = HOURS_PER_DAY * shuttime + hour;
-               shuttime = MINS_PER_HOUR * shuttime + min;
-               shuttime *= SECS_PER_MIN;
-               shuttime -= lt->tm_gmtoff;
-               if ((offset = shuttime - now) >= 0)
-                       break;
-               /* FALLTHROUGH */
+               lt->tm_hour = ATOI2(timearg);
+               if (lt->tm_hour < 0 || lt->tm_hour > 23)
+                       badtime();
+               lt->tm_min = ATOI2(timearg);
+               if (lt->tm_min < 0 || lt->tm_min > 59)
+                       badtime();
+               lt->tm_sec = 0;
+               if ((shuttime = mktime(lt)) == -1)
+                       badtime();
+               if ((offset = shuttime - now) < 0) {
+                       (void)fprintf(stderr,
+                           "shutdown: that time is already past.\n");
+                       exit(1);
+               }
+               break;
        default:
        default:
-badtime:       fprintf(stderr,
-                   "shutdown: bad time format, or already past.\n");
-               exit(1);
+               badtime();
        }
 }
 
        }
 }
 
@@ -392,7 +419,8 @@ doitfast()
 {
        int fastfd;
 
 {
        int fastfd;
 
-       if ((fastfd = open(FASTBOOT, O_WRONLY|O_CREAT|O_TRUNC, 0664)) >= 0) {
+       if ((fastfd = open(_PATH_FASTBOOT, O_WRONLY|O_CREAT|O_TRUNC,
+           0664)) >= 0) {
                (void)write(fastfd, FSMSG, sizeof(FSMSG) - 1);
                (void)close(fastfd);
        }
                (void)write(fastfd, FSMSG, sizeof(FSMSG) - 1);
                (void)close(fastfd);
        }
@@ -401,15 +429,17 @@ doitfast()
 #define        NOMSG   "\n\nNO LOGINS: System going down at "
 nolog()
 {
 #define        NOMSG   "\n\nNO LOGINS: System going down at "
 nolog()
 {
-       int logfd, finish();
+       int logfd;
        char *ct, *ctime();
        char *ct, *ctime();
+       void finish();
 
 
-       (void)unlink(NOLOGIN);          /* in case linked to another file */
+       (void)unlink(_PATH_NOLOGIN);    /* in case linked to another file */
        (void)signal(SIGINT, finish);
        (void)signal(SIGHUP, finish);
        (void)signal(SIGQUIT, finish);
        (void)signal(SIGTERM, finish);
        (void)signal(SIGINT, finish);
        (void)signal(SIGHUP, finish);
        (void)signal(SIGQUIT, finish);
        (void)signal(SIGTERM, finish);
-       if ((logfd = open(NOLOGIN, O_WRONLY|O_CREAT|O_TRUNC, 0664)) >= 0) {
+       if ((logfd = open(_PATH_NOLOGIN, O_WRONLY|O_CREAT|O_TRUNC,
+           0664)) >= 0) {
                (void)write(logfd, NOMSG, sizeof(NOMSG) - 1);
                ct = ctime(&shuttime);
                (void)write(logfd, ct + 11, 5);
                (void)write(logfd, NOMSG, sizeof(NOMSG) - 1);
                ct = ctime(&shuttime);
                (void)write(logfd, ct + 11, 5);
@@ -419,12 +449,19 @@ nolog()
        }
 }
 
        }
 }
 
+void
 finish()
 {
 finish()
 {
-       (void)unlink(NOLOGIN);
+       (void)unlink(_PATH_NOLOGIN);
        exit(0);
 }
 
        exit(0);
 }
 
+badtime()
+{
+       (void)fprintf(stderr, "shutdown: bad time format.\n");
+       exit(1);
+}
+
 usage()
 {
        fprintf(stderr, "usage: shutdown [-fhknr] shutdowntime [ message ]\n");
 usage()
 {
        fprintf(stderr, "usage: shutdown [-fhknr] shutdowntime [ message ]\n");