1331722Seadler/* 21558Srgrimes * Copyright (c) 1988, 1990, 1993 31558Srgrimes * The Regents of the University of California. All rights reserved. 41558Srgrimes * 51558Srgrimes * Redistribution and use in source and binary forms, with or without 61558Srgrimes * modification, are permitted provided that the following conditions 71558Srgrimes * are met: 81558Srgrimes * 1. Redistributions of source code must retain the above copyright 91558Srgrimes * notice, this list of conditions and the following disclaimer. 101558Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111558Srgrimes * notice, this list of conditions and the following disclaimer in the 121558Srgrimes * documentation and/or other materials provided with the distribution. 131558Srgrimes * 4. Neither the name of the University nor the names of its contributors 141558Srgrimes * may be used to endorse or promote products derived from this software 151558Srgrimes * without specific prior written permission. 161558Srgrimes * 171558Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 181558Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 191558Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 201558Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 211558Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 221558Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 231558Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 241558Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 251558Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 261558Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 271558Srgrimes * SUCH DAMAGE. 281558Srgrimes */ 291558Srgrimes 30114589Sobrien#if 0 311558Srgrimes#ifndef lint 3238036Scharnierstatic const char copyright[] = 331558Srgrimes"@(#) Copyright (c) 1988, 1990, 1993\n\ 341558Srgrimes The Regents of the University of California. All rights reserved.\n"; 351558Srgrimes#endif /* not lint */ 361558Srgrimes 371558Srgrimes#ifndef lint 3841684Sbdestatic char sccsid[] = "@(#)shutdown.c 8.4 (Berkeley) 4/28/95"; 39114589Sobrien#endif /* not lint */ 4038036Scharnier#endif 41114589Sobrien#include <sys/cdefs.h> 42114589Sobrien__FBSDID("$FreeBSD$"); 431558Srgrimes 441558Srgrimes#include <sys/param.h> 451558Srgrimes#include <sys/time.h> 461558Srgrimes#include <sys/resource.h> 471558Srgrimes#include <sys/syslog.h> 481558Srgrimes 491558Srgrimes#include <ctype.h> 5038036Scharnier#include <err.h> 51275818Sgleb#include <errno.h> 521558Srgrimes#include <fcntl.h> 53114763Sobrien#include <paths.h> 541558Srgrimes#include <pwd.h> 551558Srgrimes#include <setjmp.h> 561558Srgrimes#include <signal.h> 571558Srgrimes#include <stdio.h> 581558Srgrimes#include <stdlib.h> 591558Srgrimes#include <string.h> 601558Srgrimes#include <unistd.h> 611558Srgrimes 621558Srgrimes#ifdef DEBUG 631558Srgrimes#undef _PATH_NOLOGIN 641558Srgrimes#define _PATH_NOLOGIN "./nologin" 651558Srgrimes#endif 661558Srgrimes 671558Srgrimes#define H *60*60 681558Srgrimes#define M *60 691558Srgrimes#define S *1 701558Srgrimes#define NOLOG_TIME 5*60 71227081Sedstatic struct interval { 721558Srgrimes int timeleft, timetowait; 731558Srgrimes} tlist[] = { 7432399Salex { 10 H, 5 H }, 7532399Salex { 5 H, 3 H }, 7632399Salex { 2 H, 1 H }, 7732399Salex { 1 H, 30 M }, 7832399Salex { 30 M, 10 M }, 7932399Salex { 20 M, 10 M }, 8032399Salex { 10 M, 5 M }, 8132399Salex { 5 M, 3 M }, 8232399Salex { 2 M, 1 M }, 8332399Salex { 1 M, 30 S }, 8432399Salex { 30 S, 30 S }, 8532399Salex { 0 , 0 } 861558Srgrimes}; 871558Srgrimes#undef H 881558Srgrimes#undef M 891558Srgrimes#undef S 901558Srgrimes 911558Srgrimesstatic time_t offset, shuttime; 9248078Srustatic int dohalt, dopower, doreboot, killflg, mbuflen, oflag; 9379749Sddstatic char mbuf[BUFSIZ]; 9479749Sddstatic const char *nosync, *whom; 951558Srgrimes 96197560Sdelphijstatic void badtime(void); 97238968Sdesstatic void die_you_gravy_sucking_pig_dog(void); 98197560Sdelphijstatic void finish(int); 99197560Sdelphijstatic void getoffset(char *); 100197560Sdelphijstatic void loop(void); 101197560Sdelphijstatic void nolog(void); 102197560Sdelphijstatic void timeout(int); 103197560Sdelphijstatic void timewarn(int); 104197560Sdelphijstatic void usage(const char *); 1051558Srgrimes 106140796Sdelphijextern const char **environ; 107140796Sdelphij 1081558Srgrimesint 109140796Sdelphijmain(int argc, char **argv) 1101558Srgrimes{ 11179749Sdd char *p, *endp; 1121558Srgrimes struct passwd *pw; 1131558Srgrimes int arglen, ch, len, readstdin; 1141558Srgrimes 1151558Srgrimes#ifndef DEBUG 11626737Scharnier if (geteuid()) 11726737Scharnier errx(1, "NOT super-user"); 1181558Srgrimes#endif 119216823Spjd 1201558Srgrimes nosync = NULL; 1211558Srgrimes readstdin = 0; 122216823Spjd 123216823Spjd /* 124216823Spjd * Test for the special case where the utility is called as 125216823Spjd * "poweroff", for which it runs 'shutdown -p now'. 126216823Spjd */ 127229403Sed if ((p = strrchr(argv[0], '/')) == NULL) 128216823Spjd p = argv[0]; 129216823Spjd else 130216823Spjd ++p; 131216823Spjd if (strcmp(p, "poweroff") == 0) { 132216823Spjd if (getopt(argc, argv, "") != -1) 133216823Spjd usage((char *)NULL); 134216823Spjd argc -= optind; 135216823Spjd argv += optind; 136216823Spjd if (argc != 0) 137216823Spjd usage((char *)NULL); 138216823Spjd dopower = 1; 139216823Spjd offset = 0; 140216823Spjd (void)time(&shuttime); 141216823Spjd goto poweroff; 142216823Spjd } 143216823Spjd 14448078Sru while ((ch = getopt(argc, argv, "-hknopr")) != -1) 1451558Srgrimes switch (ch) { 1461558Srgrimes case '-': 1471558Srgrimes readstdin = 1; 1481558Srgrimes break; 1491558Srgrimes case 'h': 1501558Srgrimes dohalt = 1; 1511558Srgrimes break; 1521558Srgrimes case 'k': 1531558Srgrimes killflg = 1; 1541558Srgrimes break; 1551558Srgrimes case 'n': 1561558Srgrimes nosync = "-n"; 1571558Srgrimes break; 15848078Sru case 'o': 15948078Sru oflag = 1; 16048078Sru break; 16141666Smsmith case 'p': 16241666Smsmith dopower = 1; 16341666Smsmith break; 1641558Srgrimes case 'r': 1651558Srgrimes doreboot = 1; 1661558Srgrimes break; 1671558Srgrimes case '?': 1681558Srgrimes default: 16948078Sru usage((char *)NULL); 1701558Srgrimes } 1711558Srgrimes argc -= optind; 1721558Srgrimes argv += optind; 1731558Srgrimes 1741558Srgrimes if (argc < 1) 17548078Sru usage((char *)NULL); 1761558Srgrimes 17748078Sru if (killflg + doreboot + dohalt + dopower > 1) 17848078Sru usage("incompatible switches -h, -k, -p and -r"); 17948062Sjkoshy 18048078Sru if (oflag && !(dohalt || dopower || doreboot)) 18148078Sru usage("-o requires -h, -p or -r"); 18248062Sjkoshy 18348078Sru if (nosync != NULL && !oflag) 18448078Sru usage("-n requires -o"); 18548078Sru 1861558Srgrimes getoffset(*argv++); 1871558Srgrimes 188216823Spjdpoweroff: 1891558Srgrimes if (*argv) { 1901558Srgrimes for (p = mbuf, len = sizeof(mbuf); *argv; ++argv) { 1911558Srgrimes arglen = strlen(*argv); 1921558Srgrimes if ((len -= arglen) <= 2) 1931558Srgrimes break; 1941558Srgrimes if (p != mbuf) 1951558Srgrimes *p++ = ' '; 19641684Sbde memmove(p, *argv, arglen); 1971558Srgrimes p += arglen; 1981558Srgrimes } 1991558Srgrimes *p = '\n'; 2001558Srgrimes *++p = '\0'; 2011558Srgrimes } 2021558Srgrimes 2031558Srgrimes if (readstdin) { 2041558Srgrimes p = mbuf; 2051558Srgrimes endp = mbuf + sizeof(mbuf) - 2; 2061558Srgrimes for (;;) { 2071558Srgrimes if (!fgets(p, endp - p + 1, stdin)) 2081558Srgrimes break; 2091558Srgrimes for (; *p && p < endp; ++p); 2101558Srgrimes if (p == endp) { 2111558Srgrimes *p = '\n'; 2121558Srgrimes *++p = '\0'; 2131558Srgrimes break; 2141558Srgrimes } 2151558Srgrimes } 2161558Srgrimes } 2171558Srgrimes mbuflen = strlen(mbuf); 2181558Srgrimes 2191558Srgrimes if (offset) 2201558Srgrimes (void)printf("Shutdown at %.24s.\n", ctime(&shuttime)); 2211558Srgrimes else 2221558Srgrimes (void)printf("Shutdown NOW!\n"); 2231558Srgrimes 2241558Srgrimes if (!(whom = getlogin())) 2251558Srgrimes whom = (pw = getpwuid(getuid())) ? pw->pw_name : "???"; 2261558Srgrimes 2271558Srgrimes#ifdef DEBUG 2281558Srgrimes (void)putc('\n', stdout); 2291558Srgrimes#else 2301558Srgrimes (void)setpriority(PRIO_PROCESS, 0, PRIO_MIN); 2311558Srgrimes { 2321558Srgrimes int forkpid; 2331558Srgrimes 2341558Srgrimes forkpid = fork(); 23526737Scharnier if (forkpid == -1) 23626737Scharnier err(1, "fork"); 23726737Scharnier if (forkpid) 23826737Scharnier errx(0, "[pid %d]", forkpid); 2391558Srgrimes } 24028613Sjoerg setsid(); 2411558Srgrimes#endif 2421558Srgrimes openlog("shutdown", LOG_CONS, LOG_AUTH); 2431558Srgrimes loop(); 24438036Scharnier return(0); 2451558Srgrimes} 2461558Srgrimes 247197560Sdelphijstatic void 248197560Sdelphijloop(void) 2491558Srgrimes{ 2501558Srgrimes struct interval *tp; 2511558Srgrimes u_int sltime; 2521558Srgrimes int logged; 2531558Srgrimes 2541558Srgrimes if (offset <= NOLOG_TIME) { 2551558Srgrimes logged = 1; 2561558Srgrimes nolog(); 2571558Srgrimes } 2581558Srgrimes else 2591558Srgrimes logged = 0; 2601558Srgrimes tp = tlist; 2611558Srgrimes if (tp->timeleft < offset) 2621558Srgrimes (void)sleep((u_int)(offset - tp->timeleft)); 2631558Srgrimes else { 26448004Sru while (tp->timeleft && offset < tp->timeleft) 2651558Srgrimes ++tp; 2661558Srgrimes /* 2671558Srgrimes * Warn now, if going to sleep more than a fifth of 2681558Srgrimes * the next wait time. 2691558Srgrimes */ 27032399Salex if ((sltime = offset - tp->timeleft)) { 27179749Sdd if (sltime > (u_int)(tp->timetowait / 5)) 2721558Srgrimes timewarn(offset); 2731558Srgrimes (void)sleep(sltime); 2741558Srgrimes } 2751558Srgrimes } 2761558Srgrimes for (;; ++tp) { 2771558Srgrimes timewarn(tp->timeleft); 2781558Srgrimes if (!logged && tp->timeleft <= NOLOG_TIME) { 2791558Srgrimes logged = 1; 2801558Srgrimes nolog(); 2811558Srgrimes } 2821558Srgrimes (void)sleep((u_int)tp->timetowait); 2831558Srgrimes if (!tp->timeleft) 2841558Srgrimes break; 2851558Srgrimes } 286238968Sdes die_you_gravy_sucking_pig_dog(); 2871558Srgrimes} 2881558Srgrimes 2891558Srgrimesstatic jmp_buf alarmbuf; 2901558Srgrimes 29179749Sddstatic const char *restricted_environ[] = { 29232399Salex "PATH=" _PATH_STDPATH, 29332399Salex NULL 29432399Salex}; 29532399Salex 296197560Sdelphijstatic void 297140797Sdelphijtimewarn(int timeleft) 2981558Srgrimes{ 2991558Srgrimes static int first; 3001558Srgrimes static char hostname[MAXHOSTNAMELEN + 1]; 3011558Srgrimes FILE *pf; 3021558Srgrimes char wcmd[MAXPATHLEN + 4]; 3031558Srgrimes 3041558Srgrimes if (!first++) 3051558Srgrimes (void)gethostname(hostname, sizeof(hostname)); 3061558Srgrimes 3071558Srgrimes /* undoc -n option to wall suppresses normal wall banner */ 3081558Srgrimes (void)snprintf(wcmd, sizeof(wcmd), "%s -n", _PATH_WALL); 30932399Salex environ = restricted_environ; 3101558Srgrimes if (!(pf = popen(wcmd, "w"))) { 3111558Srgrimes syslog(LOG_ERR, "shutdown: can't find %s: %m", _PATH_WALL); 3121558Srgrimes return; 3131558Srgrimes } 3141558Srgrimes 3151558Srgrimes (void)fprintf(pf, 3161558Srgrimes "\007*** %sSystem shutdown message from %s@%s ***\007\n", 3171558Srgrimes timeleft ? "": "FINAL ", whom, hostname); 3181558Srgrimes 3191558Srgrimes if (timeleft > 10*60) 3201558Srgrimes (void)fprintf(pf, "System going down at %5.5s\n\n", 3211558Srgrimes ctime(&shuttime) + 11); 3221558Srgrimes else if (timeleft > 59) 3231558Srgrimes (void)fprintf(pf, "System going down in %d minute%s\n\n", 3241558Srgrimes timeleft / 60, (timeleft > 60) ? "s" : ""); 3251558Srgrimes else if (timeleft) 326275818Sgleb (void)fprintf(pf, "System going down in %s30 seconds\n\n", 327275818Sgleb (offset > 0 && offset < 30 ? "less than " : "")); 3281558Srgrimes else 3291558Srgrimes (void)fprintf(pf, "System going down IMMEDIATELY\n\n"); 3301558Srgrimes 3311558Srgrimes if (mbuflen) 3321558Srgrimes (void)fwrite(mbuf, sizeof(*mbuf), mbuflen, pf); 3331558Srgrimes 3341558Srgrimes /* 3351558Srgrimes * play some games, just in case wall doesn't come back 33638036Scharnier * probably unnecessary, given that wall is careful. 3371558Srgrimes */ 3381558Srgrimes if (!setjmp(alarmbuf)) { 3391558Srgrimes (void)signal(SIGALRM, timeout); 3401558Srgrimes (void)alarm((u_int)30); 3411558Srgrimes (void)pclose(pf); 3421558Srgrimes (void)alarm((u_int)0); 3431558Srgrimes (void)signal(SIGALRM, SIG_DFL); 3441558Srgrimes } 3451558Srgrimes} 3461558Srgrimes 347197560Sdelphijstatic void 348140797Sdelphijtimeout(int signo __unused) 3491558Srgrimes{ 3501558Srgrimes longjmp(alarmbuf, 1); 3511558Srgrimes} 3521558Srgrimes 353197560Sdelphijstatic void 354238968Sdesdie_you_gravy_sucking_pig_dog(void) 3551558Srgrimes{ 35632399Salex char *empty_environ[] = { NULL }; 3571558Srgrimes 3581558Srgrimes syslog(LOG_NOTICE, "%s by %s: %s", 35941666Smsmith doreboot ? "reboot" : dohalt ? "halt" : dopower ? "power-down" : 36041666Smsmith "shutdown", whom, mbuf); 3611558Srgrimes 3621558Srgrimes (void)printf("\r\nSystem shutdown time has arrived\007\007\r\n"); 3631558Srgrimes if (killflg) { 3641558Srgrimes (void)printf("\rbut you'll have to do it yourself\r\n"); 3654844Sats exit(0); 3661558Srgrimes } 3671558Srgrimes#ifdef DEBUG 3681558Srgrimes if (doreboot) 3691558Srgrimes (void)printf("reboot"); 3701558Srgrimes else if (dohalt) 3711558Srgrimes (void)printf("halt"); 37241666Smsmith else if (dopower) 37341666Smsmith (void)printf("power-down"); 37448078Sru if (nosync != NULL) 3751558Srgrimes (void)printf(" no sync"); 3761558Srgrimes (void)printf("\nkill -HUP 1\n"); 3771558Srgrimes#else 37848078Sru if (!oflag) { 37948078Sru (void)kill(1, doreboot ? SIGINT : /* reboot */ 38048078Sru dohalt ? SIGUSR1 : /* halt */ 38148078Sru dopower ? SIGUSR2 : /* power-down */ 38248078Sru SIGTERM); /* single-user */ 38348078Sru } else { 38448078Sru if (doreboot) { 38548078Sru execle(_PATH_REBOOT, "reboot", "-l", nosync, 38648078Sru (char *)NULL, empty_environ); 38748078Sru syslog(LOG_ERR, "shutdown: can't exec %s: %m.", 38848078Sru _PATH_REBOOT); 38948078Sru warn(_PATH_REBOOT); 39048078Sru } 39148078Sru else if (dohalt) { 39248078Sru execle(_PATH_HALT, "halt", "-l", nosync, 39348078Sru (char *)NULL, empty_environ); 39448078Sru syslog(LOG_ERR, "shutdown: can't exec %s: %m.", 39548078Sru _PATH_HALT); 39648078Sru warn(_PATH_HALT); 39748078Sru } 39848078Sru else if (dopower) { 39948078Sru execle(_PATH_HALT, "halt", "-l", "-p", nosync, 40048078Sru (char *)NULL, empty_environ); 40148078Sru syslog(LOG_ERR, "shutdown: can't exec %s: %m.", 40248078Sru _PATH_HALT); 40348078Sru warn(_PATH_HALT); 40448078Sru } 40548078Sru (void)kill(1, SIGTERM); /* to single-user */ 4061558Srgrimes } 4071558Srgrimes#endif 4081558Srgrimes finish(0); 4091558Srgrimes} 4101558Srgrimes 4111558Srgrimes#define ATOI2(p) (p[0] - '0') * 10 + (p[1] - '0'); p += 2; 4121558Srgrimes 413197560Sdelphijstatic void 414140797Sdelphijgetoffset(char *timearg) 4151558Srgrimes{ 41679749Sdd struct tm *lt; 41779749Sdd char *p; 4181558Srgrimes time_t now; 41932328Salex int this_year; 420275818Sgleb char *timeunit; 4211558Srgrimes 42248062Sjkoshy (void)time(&now); 42348062Sjkoshy 4241558Srgrimes if (!strcasecmp(timearg, "now")) { /* now */ 4251558Srgrimes offset = 0; 42648062Sjkoshy shuttime = now; 4271558Srgrimes return; 4281558Srgrimes } 4291558Srgrimes 4301558Srgrimes if (*timearg == '+') { /* +minutes */ 4311558Srgrimes if (!isdigit(*++timearg)) 4321558Srgrimes badtime(); 433275818Sgleb errno = 0; 434275818Sgleb offset = strtol(timearg, &timeunit, 10); 435275818Sgleb if (offset < 0 || offset == LONG_MAX || errno != 0) 43648004Sru badtime(); 437275818Sgleb if (timeunit[0] == '\0' || strcasecmp(timeunit, "m") == 0 || 438275818Sgleb strcasecmp(timeunit, "min") == 0 || 439275818Sgleb strcasecmp(timeunit, "mins") == 0) { 440275818Sgleb offset *= 60; 441275818Sgleb } else if (strcasecmp(timeunit, "h") == 0 || 442275818Sgleb strcasecmp(timeunit, "hour") == 0 || 443275818Sgleb strcasecmp(timeunit, "hours") == 0) { 444275818Sgleb offset *= 60 * 60; 445275818Sgleb } else if (strcasecmp(timeunit, "s") == 0 || 446275818Sgleb strcasecmp(timeunit, "sec") == 0 || 447275818Sgleb strcasecmp(timeunit, "secs") == 0) { 448275818Sgleb offset *= 1; 449275818Sgleb } else { 450275818Sgleb badtime(); 451275818Sgleb } 4521558Srgrimes shuttime = now + offset; 4531558Srgrimes return; 4541558Srgrimes } 4551558Srgrimes 4561558Srgrimes /* handle hh:mm by getting rid of the colon */ 4571558Srgrimes for (p = timearg; *p; ++p) 45848956Sbillf if (!isascii(*p) || !isdigit(*p)) { 4591558Srgrimes if (*p == ':' && strlen(p) == 3) { 4601558Srgrimes p[0] = p[1]; 4611558Srgrimes p[1] = p[2]; 4621558Srgrimes p[2] = '\0'; 4631558Srgrimes } 4641558Srgrimes else 4651558Srgrimes badtime(); 46648956Sbillf } 4671558Srgrimes 4681558Srgrimes unsetenv("TZ"); /* OUR timezone */ 4691558Srgrimes lt = localtime(&now); /* current time val */ 4701558Srgrimes 4711558Srgrimes switch(strlen(timearg)) { 4721558Srgrimes case 10: 47332328Salex this_year = lt->tm_year; 4741558Srgrimes lt->tm_year = ATOI2(timearg); 47532328Salex /* 47632328Salex * check if the specified year is in the next century. 47732328Salex * allow for one year of user error as many people will 47832328Salex * enter n - 1 at the start of year n. 47932328Salex */ 48032328Salex if (lt->tm_year < (this_year % 100) - 1) 48132328Salex lt->tm_year += 100; 48232329Salex /* adjust for the year 2000 and beyond */ 48332328Salex lt->tm_year += (this_year - (this_year % 100)); 4841558Srgrimes /* FALLTHROUGH */ 4851558Srgrimes case 8: 4861558Srgrimes lt->tm_mon = ATOI2(timearg); 4871558Srgrimes if (--lt->tm_mon < 0 || lt->tm_mon > 11) 4881558Srgrimes badtime(); 4891558Srgrimes /* FALLTHROUGH */ 4901558Srgrimes case 6: 4911558Srgrimes lt->tm_mday = ATOI2(timearg); 4921558Srgrimes if (lt->tm_mday < 1 || lt->tm_mday > 31) 4931558Srgrimes badtime(); 4941558Srgrimes /* FALLTHROUGH */ 4951558Srgrimes case 4: 4961558Srgrimes lt->tm_hour = ATOI2(timearg); 4971558Srgrimes if (lt->tm_hour < 0 || lt->tm_hour > 23) 4981558Srgrimes badtime(); 4991558Srgrimes lt->tm_min = ATOI2(timearg); 5001558Srgrimes if (lt->tm_min < 0 || lt->tm_min > 59) 5011558Srgrimes badtime(); 5021558Srgrimes lt->tm_sec = 0; 5031558Srgrimes if ((shuttime = mktime(lt)) == -1) 5041558Srgrimes badtime(); 50526737Scharnier if ((offset = shuttime - now) < 0) 50626737Scharnier errx(1, "that time is already past."); 5071558Srgrimes break; 5081558Srgrimes default: 5091558Srgrimes badtime(); 5101558Srgrimes } 5111558Srgrimes} 5121558Srgrimes 5131558Srgrimes#define NOMSG "\n\nNO LOGINS: System going down at " 514197560Sdelphijstatic void 515197560Sdelphijnolog(void) 5161558Srgrimes{ 5171558Srgrimes int logfd; 5181558Srgrimes char *ct; 5191558Srgrimes 5201558Srgrimes (void)unlink(_PATH_NOLOGIN); /* in case linked to another file */ 5211558Srgrimes (void)signal(SIGINT, finish); 5221558Srgrimes (void)signal(SIGHUP, finish); 5231558Srgrimes (void)signal(SIGQUIT, finish); 5241558Srgrimes (void)signal(SIGTERM, finish); 5251558Srgrimes if ((logfd = open(_PATH_NOLOGIN, O_WRONLY|O_CREAT|O_TRUNC, 5261558Srgrimes 0664)) >= 0) { 5271558Srgrimes (void)write(logfd, NOMSG, sizeof(NOMSG) - 1); 5281558Srgrimes ct = ctime(&shuttime); 5291558Srgrimes (void)write(logfd, ct + 11, 5); 5301558Srgrimes (void)write(logfd, "\n\n", 2); 5311558Srgrimes (void)write(logfd, mbuf, strlen(mbuf)); 5321558Srgrimes (void)close(logfd); 5331558Srgrimes } 5341558Srgrimes} 5351558Srgrimes 536197560Sdelphijstatic void 537140797Sdelphijfinish(int signo __unused) 5381558Srgrimes{ 53941684Sbde if (!killflg) 54041684Sbde (void)unlink(_PATH_NOLOGIN); 5411558Srgrimes exit(0); 5421558Srgrimes} 5431558Srgrimes 544197560Sdelphijstatic void 545201180Sedbadtime(void) 5461558Srgrimes{ 54738036Scharnier errx(1, "bad time format"); 5481558Srgrimes} 5491558Srgrimes 550197560Sdelphijstatic void 551140797Sdelphijusage(const char *cp) 5521558Srgrimes{ 55348078Sru if (cp != NULL) 55448078Sru warnx("%s", cp); 55548078Sru (void)fprintf(stderr, 556216823Spjd "usage: shutdown [-] [-h | -p | -r | -k] [-o [-n]] time [warning-message ...]\n" 557216823Spjd " poweroff\n"); 5581558Srgrimes exit(1); 5591558Srgrimes} 560