BSD 4_4 release
[unix-history] / usr / src / sbin / shutdown / shutdown.c
index 605a41c..79cdfd9 100644 (file)
-/*     @(#)shutdown.c  4.3 (Berkeley/Melbourne) 81/04/03       */
-
-#include <stdio.h>
-#include <ctype.h>
-#include <signal.h>
-#include <utmp.h>
-#include <time.h>
-#include <sys/types.h>
 /*
 /*
- *     /etc/shutdown when [messages]
+ * Copyright (c) 1988, 1990, 1993
+ *     The Regents of the University of California.  All rights reserved.
  *
  *
- *     allow super users to tell users and remind users
- *     of iminent shutdown of unix
- *     and shut it down automatically
- *     and even reboot or halt the machine if they desire
+ * 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.
  *
  *
- *             Ian Johnstone, Sydney, 1977
- *             Robert Elz, Melbourne, 1978
- *             Peter Lamb, Melbourne, 1980
- *             William Joy, Berkeley, 1981
- *             Michael Toy, Berkeley, 1981
+ * 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
+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
+static char sccsid[] = "@(#)shutdown.c 8.1 (Berkeley) 6/5/93";
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/file.h>
+#include <sys/resource.h>
+#include <sys/syslog.h>
+#include <sys/signal.h>
+#include <setjmp.h>
+#include <tzfile.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <ctype.h>
+#include "pathnames.h"
+
 #ifdef DEBUG
 #ifdef DEBUG
-#define LOGFILE "shutdown.log"
-#else
-#define LOGFILE "/usr/adm/shutdownlog"
+#undef _PATH_NOLOGIN
+#define        _PATH_NOLOGIN   "./nologin"
+#undef _PATH_FASTBOOT
+#define        _PATH_FASTBOOT  "./fastboot"
 #endif
 #endif
-#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        NOLOGTIME       5 MINUTES
-
-int    do_nothing();
-time_t getsdt();
-
-extern char *ctime();
-extern struct tm *localtime();
-
-struct utmp utmp;
-int    sint;
-int    stogo;
-char   tpath[] =       "/dev/";
-int    nlflag = 1;             /* nolog yet to be done */
-int    killflg = 1;
-int    reboot = 0;
-int    halt = 0;
-char   term[sizeof tpath + sizeof utmp.ut_line];
-char   tbuf[BUFSIZ];
-char   nolog1[] = "\n\nNO LOGINS: System going down at %5.5s\n\n";
-char   *nolog2[NLOG+1];
-#ifdef DEBUG
-char   nologin[] = "nologin";
-#else
-char   nologin[] = "/etc/nologin";
-#endif
-int slots;
+
+#define        H               *60*60
+#define        M               *60
+#define        S               *1
+#define        NOLOG_TIME      5*60
 struct interval {
 struct interval {
-       int stogo;
-       int sint;
-} interval[] = {
-       4 HOURS,        1 HOURS,
-       2 HOURS,        30 MINUTES,
-       1 HOURS,        15 MINUTES,
-       30 MINUTES,     10 MINUTES,
-       15 MINUTES,     5 MINUTES,
-       10 MINUTES,     5 MINUTES,
-       5 MINUTES,      3 MINUTES,
-       2 MINUTES,      30 SECONDS,
-       0 SECONDS,      0 SECONDS
-};
-char *shutter, *getlogin();
-main(argc,argv)
+       int timeleft, timetowait;
+} tlist[] = {
+       10 H,  5 H,      5 H,  3 H,      2 H,  1 H,     1 H, 30 M,
+       30 M, 10 M,     20 M, 10 M,     10 M,  5 M,     5 M,  3 M,
+        2 M,  1 M,      1 M, 30 S,     30 S, 30 S,
+        0, 0,
+}, *tp = tlist;
+#undef H
+#undef M
+#undef S
+
+static time_t offset, shuttime;
+static int dofast, dohalt, doreboot, killflg, mbuflen;
+static char *nosync, *whom, mbuf[BUFSIZ];
+
+main(argc, argv)
        int argc;
        char **argv;
 {
        int argc;
        char **argv;
 {
-       register i, ufd;
-       register char **mess, *f;
-       char *ts;
-       long sdt;
-       int h, m;
-       long nowtime;
-       FILE *termf;
-
-       shutter = getlogin();
-       argc--, argv++;
-       while (argc > 0 && (f = argv[0], *f++ == '-')) {
-               while (i = *f++) switch (i) {
+       extern int optind;
+       register char *p, *endp;
+       int arglen, ch, len, readstdin;
+       struct passwd *pw;
+       char *strcat(), *getlogin();
+       uid_t geteuid();
+
+#ifndef DEBUG
+       if (geteuid()) {
+               (void)fprintf(stderr, "shutdown: NOT super-user\n");
+               exit(1);
+       }
+#endif
+       nosync = NULL;
+       readstdin = 0;
+       while ((ch = getopt(argc, argv, "-fhknr")) != EOF)
+               switch (ch) {
+               case '-':
+                       readstdin = 1;
+                       break;
+               case 'f':
+                       dofast = 1;
+                       break;
+               case 'h':
+                       dohalt = 1;
+                       break;
                case 'k':
                case 'k':
-                       killflg = 0;
-                       continue;
+                       killflg = 1;
+                       break;
+               case 'n':
+                       nosync = "-n";
+                       break;
                case 'r':
                case 'r':
-                       reboot = 1;
-                       continue;
-               case 'h':
-                       halt = 1;
-                       continue;
+                       doreboot = 1;
+                       break;
+               case '?':
                default:
                default:
-                       fprintf(stderr, "shutdown: '%c' - unknown flag\n", i);
-                       exit(1);
+                       usage();
                }
                }
-               argc--, argv++;
+       argc -= optind;
+       argv += optind;
+
+       if (argc < 1)
+               usage();
+
+       if (dofast && nosync) {
+               (void)fprintf(stderr,
+                   "shutdown: incompatible switches -f and -n.\n");
+               usage();
        }
        }
-       if (argc < 1) {
-               printf("Usage: %s [-krd] shutdowntime [nologmessage]\n",
-                   argv[0]);
-               finish();
+       if (doreboot && dohalt) {
+               (void)fprintf(stderr,
+                   "shutdown: incompatible switches -h and -r.\n");
+               usage();
        }
        }
-       sdt = getsdt(argv[0]);
-       argc--, argv++;
-       i = 0;
-       while (argc-- > 0)
-               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);
-       printf("Shutdown at %5.5s (in ", ts+11);
-       if (h > 0)
-               printf("%d hour%s ", h, h != 1 ? "s" : "");
-       printf("%d minute%s) ", m, m != 1 ? "s" : "");
-#ifndef DEBUG
-       signal(SIGHUP, SIG_IGN);
-       signal(SIGQUIT, SIG_IGN);
-       signal(SIGINT, SIG_IGN);
-#endif
-       signal(SIGTERM, finish);
-       signal(SIGALRM, do_nothing);
-       nice(-20);
-#ifndef DEBUG
-       if (i = fork()) {
-               printf("[pid %d]\n", i);
-               exit(0);
+       getoffset(*argv++);
+
+       if (*argv) {
+               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';
        }
        }
-#endif
-       sint = 1 HOURS;
-       f = "";
-       for (;;) {
-               for (i = 0; stogo <= interval[i].stogo && interval[i].sint; i++)
-                       sint = interval[i].sint;
-               if (stogo <= NOLOGTIME && nlflag) {
-                       nlflag = 0;
-                       nolog(sdt);
+
+       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;
+                       }
                }
                }
-               if (sint >= stogo || sint == 0)
-                       f = "FINAL ";
-               ufd = open("/etc/utmp",0);
-               nowtime = time((long *) 0);
-               while (read(ufd,&utmp,sizeof utmp)==sizeof utmp)
-               if (utmp.ut_name[0]) {
-                       strcpy(term, tpath);
-                       strncat(term, utmp.ut_line, sizeof utmp.ut_line);
-                       alarm(3);
-#ifdef DEBUG
-                       if ((termf = stdout) != NULL)
-#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)
-                                       for (mess = nolog2; *mess; mess++)
-                                               fprintf(termf, "%s ", *mess);
-                               fputc('\n', termf);
-                               alarm(5);
+       }
+       mbuflen = strlen(mbuf);
+
+       if (offset)
+               (void)printf("Shutdown at %.24s.\n", ctime(&shuttime));
+       else
+               (void)printf("Shutdown NOW!\n");
+
+       if (!(whom = getlogin()))
+               whom = (pw = getpwuid(getuid())) ? pw->pw_name : "???";
+
 #ifdef DEBUG
 #ifdef DEBUG
-                               fflush(termf);
+       (void)putc('\n', stdout);
 #else
 #else
-                               fclose(termf);
-#endif
-                               alarm(0);
-                       }
+       (void)setpriority(PRIO_PROCESS, 0, PRIO_MIN);
+       {
+               int forkpid;
+
+               forkpid = fork();
+               if (forkpid == -1) {
+                       perror("shutdown: fork");
+                       exit(1);
                }
                }
-               if (stogo < 0) {
-       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
-                       if (reboot)
-                               execle(REBOOT, "reboot", 0, 0);
-                       if (halt)
-                               execle(HALT, "halt", 0, 0);
-                       kill(1, SIGTERM);       /* sync */
-                       kill(1, SIGTERM);       /* sync */
-                       sleep(20);
-#else
-                       printf("EXTERMINATE EXTERMINATE\n");
-#endif
-                       finish();
+               if (forkpid) {
+                       (void)printf("shutdown: [pid %d]\n", forkpid);
+                       exit(0);
                }
                }
-               stogo = sdt - time((long *) 0);
-               if (stogo > 0)
-                       sleep(sint<stogo ? sint : stogo);
-               stogo -= sint;
        }
        }
+#endif
+       openlog("shutdown", LOG_CONS, LOG_AUTH);
+       loop();
+       /*NOTREACHED*/
 }
 
 }
 
-time_t
-getsdt(s)
-register char *s;
+loop()
 {
 {
-       time_t t, t1, tim;
-       register char c;
-       struct tm *lt;
+       u_int sltime;
+       int logged;
 
 
-       if (*s == '+') {
-               ++s; 
-               t = 0;
-               for (;;) {
-                       c = *s++;
-                       if (!isdigit(c))
-                               break;
-                       t = t * 10 + c - '0';
+       if (offset <= NOLOG_TIME) {
+               logged = 1;
+               nolog();
+       }
+       else
+               logged = 0;
+       tp = tlist;
+       if (tp->timeleft < offset)
+               (void)sleep((u_int)(offset - tp->timeleft));
+       else {
+               while (offset < tp->timeleft)
+                       ++tp;
+               /*
+                * warn now, if going to sleep more than a fifth of
+                * the next wait time.
+                */
+               if (sltime = offset - tp->timeleft) {
+                       if (sltime > tp->timetowait / 5)
+                               warn();
+                       (void)sleep(sltime);
                }
                }
-               if (t <= 0)
-                       t = 5;
-               t *= 60;
-               tim = time((long *) 0) + t;
-               return(tim);
        }
        }
-       t = 0;
-       while (strlen(s) > 2 && isdigit(*s))
-               t = t * 10 + *s++ - '0';
-       if (*s == ':')
-               s++;
-       if (t > 23)
-               goto badform;
-       tim = t*60;
-       t = 0;
-       while (isdigit(*s))
-               t = t * 10 + *s++ - '0';
-       if (t > 59)
-               goto badform;
-       tim += t; 
-       tim *= 60;
-       t1 = time((long *) 0);
-       lt = localtime(&t1);
-       t = lt->tm_sec + lt->tm_min*60 + lt->tm_hour*3600;
-       if (tim < t || tim >= (24*3600)) {
-               /* before now or after midnight */
-               printf("That must be tomorrow\nCan't you wait till then?\n");
-               finish();
+       for (;; ++tp) {
+               warn();
+               if (!logged && tp->timeleft <= NOLOG_TIME) {
+                       logged = 1;
+                       nolog();
+               }
+               (void)sleep((u_int)tp->timetowait);
+               if (!tp->timeleft)
+                       break;
        }
        }
-       return (t1 + tim -t);
-badform:
-       printf("Bad time format\n");
-       finish();
+       die_you_gravy_sucking_pig_dog();
 }
 
 }
 
-warn(term, sdt, nowtime)
-       FILE *term;
-       long sdt, nowtime;
+static jmp_buf alarmbuf;
+
+warn()
 {
 {
-       char *ts;
-
-       fprintf(term, "\007\007*** System shutdown message from %s ***\n", shutter);
-       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 second%s\n",
-               sdt-nowtime, sdt-nowtime != 1 ? "s" : "");
-       } else
-               fprintf(term, "System going down IMMEDIATELY\n");
+       static int first;
+       static char hostname[MAXHOSTNAMELEN + 1];
+       char wcmd[MAXPATHLEN + 4];
+       FILE *pf;
+       char *ctime();
+       void timeout();
+
+       if (!first++)
+               (void)gethostname(hostname, sizeof(hostname));
+
+       /* 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;
+       }
+
+       (void)fprintf(pf,
+           "\007*** %sSystem shutdown message from %s@%s ***\007\n",
+           tp->timeleft ? "": "FINAL ", whom, hostname);
+
+       if (tp->timeleft > 10*60)
+               (void)fprintf(pf, "System going down at %5.5s\n\n",
+                   ctime(&shuttime) + 11);
+       else if (tp->timeleft > 59)
+               (void)fprintf(pf, "System going down in %d minute%s\n\n",
+                   tp->timeleft / 60, (tp->timeleft > 60) ? "s" : "");
+       else if (tp->timeleft)
+               (void)fprintf(pf, "System going down in 30 seconds\n\n");
+       else
+               (void)fprintf(pf, "System going down IMMEDIATELY\n\n");
+
+       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)) {
+               (void)signal(SIGALRM, timeout);
+               (void)alarm((u_int)30);
+               (void)pclose(pf);
+               (void)alarm((u_int)0);
+               (void)signal(SIGALRM, SIG_DFL);
+       }
 }
 
 }
 
-nolog(sdt)
-       long sdt;
+void
+timeout()
 {
 {
-       FILE *nologf;
-       register char **mess;
-
-       if ((nologf = fopen(nologin, "w")) != NULL) {
-               fprintf(nologf, nolog1, (ctime(&sdt)) + 11);
-               for (mess = nolog2; *mess; mess++)
-                       fprintf(nologf, "\t%s\n", *mess);
-               fclose(nologf);
+       longjmp(alarmbuf, 1);
+}
+
+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);
+
+       (void)printf("\r\nSystem shutdown time has arrived\007\007\r\n");
+       if (killflg) {
+               (void)printf("\rbut you'll have to do it yourself\r\n");
+               finish();
        }
        }
+       if (dofast)
+               doitfast();
+#ifdef DEBUG
+       if (doreboot)
+               (void)printf("reboot");
+       else if (dohalt)
+               (void)printf("halt");
+       if (nosync)
+               (void)printf(" no sync");
+       if (dofast)
+               (void)printf(" no fsck");
+       (void)printf("\nkill -HUP 1\n");
+#else
+       if (doreboot) {
+               execle(_PATH_REBOOT, "reboot", "-l", nosync, 0);
+               syslog(LOG_ERR, "shutdown: can't exec %s: %m.", _PATH_REBOOT);
+               perror("shutdown");
+       }
+       else if (dohalt) {
+               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 */
+#endif
+       finish();
 }
 
 }
 
-finish()
+#define        ATOI2(p)        (p[0] - '0') * 10 + (p[1] - '0'); p += 2;
+
+getoffset(timearg)
+       register char *timearg;
 {
 {
-       signal(SIGTERM, SIG_IGN);
-       unlink(nologin);
-       exit(0);
+       register struct tm *lt;
+       register char *p;
+       time_t now, time();
+
+       if (!strcasecmp(timearg, "now")) {              /* now */
+               offset = 0;
+               return;
+       }
+
+       (void)time(&now);
+       if (*timearg == '+') {                          /* +minutes */
+               if (!isdigit(*++timearg))
+                       badtime();
+               offset = atoi(timearg) * 60;
+               shuttime = now + offset;
+               return;
+       }
+
+       /* handle hh:mm by getting rid of the colon */
+       for (p = timearg; *p; ++p)
+               if (!isascii(*p) || !isdigit(*p))
+                       if (*p == ':' && strlen(p) == 3) {
+                               p[0] = p[1];
+                               p[1] = p[2];
+                               p[2] = '\0';
+                       }
+                       else
+                               badtime();
+
+       unsetenv("TZ");                                 /* OUR timezone */
+       lt = localtime(&now);                           /* current time val */
+
+       switch(strlen(timearg)) {
+       case 10:
+               lt->tm_year = ATOI2(timearg);
+               /* FALLTHROUGH */
+       case 8:
+               lt->tm_mon = ATOI2(timearg);
+               if (--lt->tm_mon < 0 || lt->tm_mon > 11)
+                       badtime();
+               /* FALLTHROUGH */
+       case 6:
+               lt->tm_mday = ATOI2(timearg);
+               if (lt->tm_mday < 1 || lt->tm_mday > 31)
+                       badtime();
+               /* FALLTHROUGH */
+       case 4:
+               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:
+               badtime();
+       }
 }
 
 }
 
-do_nothing()
+#define        FSMSG   "fastboot file for fsck\n"
+doitfast()
 {
 {
+       int fastfd;
 
 
-       signal(SIGALRM, do_nothing);
+       if ((fastfd = open(_PATH_FASTBOOT, O_WRONLY|O_CREAT|O_TRUNC,
+           0664)) >= 0) {
+               (void)write(fastfd, FSMSG, sizeof(FSMSG) - 1);
+               (void)close(fastfd);
+       }
 }
 
 }
 
-/*
- * make an entry in the shutdown log
- */
+#define        NOMSG   "\n\nNO LOGINS: System going down at "
+nolog()
+{
+       int logfd;
+       char *ct, *ctime();
+       void finish();
 
 
-char *days[] = {
-       "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
-};
+       (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);
+       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, "\n\n", 2);
+               (void)write(logfd, mbuf, strlen(mbuf));
+               (void)close(logfd);
+       }
+}
 
 
-char *months[] = {
-       "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep",
-       "Oct", "Nov", "Dec"
-};
+void
+finish()
+{
+       (void)unlink(_PATH_NOLOGIN);
+       exit(0);
+}
+
+badtime()
+{
+       (void)fprintf(stderr, "shutdown: bad time format.\n");
+       exit(1);
+}
 
 
-log_entry(now)
-time_t now;
+usage()
 {
 {
-       register FILE *fp;
-       register char **mess;
-       struct tm *tm, *localtime();
-
-       tm = localtime(&now);
-       fp = fopen(LOGFILE, "a");
-       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);
-       fputc('\n', fp);
-       fclose(fp);
+       fprintf(stderr, "usage: shutdown [-fhknr] shutdowntime [ message ]\n");
+       exit(1);
 }
 }