shutdown.c revision 1.36
1199989Srdivacky/* $OpenBSD: shutdown.c,v 1.36 2009/12/24 10:06:35 sobrado Exp $ */ 2199989Srdivacky/* $NetBSD: shutdown.c,v 1.9 1995/03/18 15:01:09 cgd Exp $ */ 3199989Srdivacky 4199989Srdivacky/* 5199989Srdivacky * Copyright (c) 1988, 1990, 1993 6199989Srdivacky * The Regents of the University of California. All rights reserved. 7199989Srdivacky * 8199989Srdivacky * Redistribution and use in source and binary forms, with or without 9199989Srdivacky * modification, are permitted provided that the following conditions 10199989Srdivacky * are met: 11199989Srdivacky * 1. Redistributions of source code must retain the above copyright 12199989Srdivacky * notice, this list of conditions and the following disclaimer. 13199989Srdivacky * 2. Redistributions in binary form must reproduce the above copyright 14199989Srdivacky * notice, this list of conditions and the following disclaimer in the 15199989Srdivacky * documentation and/or other materials provided with the distribution. 16199989Srdivacky * 3. Neither the name of the University nor the names of its contributors 17199989Srdivacky * may be used to endorse or promote products derived from this software 18199989Srdivacky * without specific prior written permission. 19199989Srdivacky * 20199989Srdivacky * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21199989Srdivacky * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22199989Srdivacky * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23199989Srdivacky * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 24199989Srdivacky * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25199989Srdivacky * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26199989Srdivacky * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27199989Srdivacky * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28199989Srdivacky * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29199989Srdivacky * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30199989Srdivacky * SUCH DAMAGE. 31199989Srdivacky */ 32199989Srdivacky 33199989Srdivacky#include <sys/param.h> 34199989Srdivacky#include <sys/resource.h> 35199989Srdivacky#include <sys/syslog.h> 36199989Srdivacky#include <sys/types.h> 37199989Srdivacky#include <sys/wait.h> 38199989Srdivacky 39207618Srdivacky#include <ctype.h> 40199989Srdivacky#include <fcntl.h> 41199989Srdivacky#include <sys/termios.h> 42199989Srdivacky#include <pwd.h> 43199989Srdivacky#include <setjmp.h> 44199989Srdivacky#include <signal.h> 45199989Srdivacky#include <stdio.h> 46199989Srdivacky#include <stdlib.h> 47199989Srdivacky#include <string.h> 48199989Srdivacky#include <time.h> 49199989Srdivacky#include <tzfile.h> 50199989Srdivacky#include <unistd.h> 51199989Srdivacky#include <errno.h> 52199989Srdivacky#include <err.h> 53199989Srdivacky 54199989Srdivacky#include "pathnames.h" 55199989Srdivacky 56199989Srdivacky#ifdef DEBUG 57199989Srdivacky#undef _PATH_NOLOGIN 58199989Srdivacky#define _PATH_NOLOGIN "./nologin" 59199989Srdivacky#undef _PATH_FASTBOOT 60199989Srdivacky#define _PATH_FASTBOOT "./fastboot" 61199989Srdivacky#endif 62207618Srdivacky 63199989Srdivacky#define H *60*60 64199989Srdivacky#define M *60 65199989Srdivacky#define S *1 66199989Srdivacky#define NOLOG_TIME 5*60 67199989Srdivackystruct interval { 68199989Srdivacky int timeleft, timetowait; 69199989Srdivacky} tlist[] = { 70199989Srdivacky { 10 H, 5 H }, 71199989Srdivacky { 5 H, 3 H }, 72199989Srdivacky { 2 H, 1 H }, 73199989Srdivacky { 1 H, 30 M }, 74199989Srdivacky { 30 M, 10 M }, 75199989Srdivacky { 20 M, 10 M }, 76199989Srdivacky { 10 M, 5 M }, 77199989Srdivacky { 5 M, 3 M }, 78199989Srdivacky { 2 M, 1 M }, 79199989Srdivacky { 1 M, 30 S }, 80199989Srdivacky { 30 S, 30 S }, 81199989Srdivacky { 0, 0 } 82199989Srdivacky}; 83199989Srdivacky#undef H 84199989Srdivacky#undef M 85199989Srdivacky#undef S 86199989Srdivacky 87199989Srdivackystatic time_t offset, shuttime; 88199989Srdivackystatic int dofast, dohalt, doreboot, dopower, dodump, mbuflen, nosync; 89199989Srdivackystatic sig_atomic_t killflg; 90199989Srdivackystatic char *whom, mbuf[BUFSIZ]; 91199989Srdivacky 92201360Srdivackyvoid badtime(void); 93199989Srdivackyvoid __dead die_you_gravy_sucking_pig_dog(void); 94199989Srdivackyvoid doitfast(void); 95199989Srdivackyvoid __dead finish(int); 96199989Srdivackyvoid getoffset(char *); 97199989Srdivackyvoid __dead loop(void); 98201360Srdivackyvoid nolog(void); 99199989Srdivackyvoid timeout(int); 100199989Srdivackyvoid timewarn(int); 101199989Srdivackyvoid usage(void); 102199989Srdivacky 103199989Srdivackyint 104199989Srdivackymain(int argc, char *argv[]) 105199989Srdivacky{ 106199989Srdivacky int arglen, ch, len, readstdin = 0; 107201360Srdivacky struct passwd *pw; 108201360Srdivacky char *p, *endp; 109201360Srdivacky pid_t forkpid; 110201360Srdivacky 111199989Srdivacky#ifndef DEBUG 112199989Srdivacky if (geteuid()) 113199989Srdivacky errx(1, "NOT super-user"); 114199989Srdivacky#endif 115199989Srdivacky while ((ch = getopt(argc, argv, "dfhknpr-")) != -1) 116199989Srdivacky switch (ch) { 117199989Srdivacky case '-': 118199989Srdivacky readstdin = 1; 119199989Srdivacky break; 120199989Srdivacky case 'd': 121199989Srdivacky dodump = 1; 122199989Srdivacky break; 123199989Srdivacky case 'f': 124199989Srdivacky dofast = 1; 125199989Srdivacky break; 126199989Srdivacky case 'h': 127199989Srdivacky dohalt = 1; 128199989Srdivacky break; 129199989Srdivacky case 'k': 130199989Srdivacky killflg = 1; 131199989Srdivacky break; 132199989Srdivacky case 'n': 133199989Srdivacky nosync = 1; 134199989Srdivacky break; 135199989Srdivacky case 'p': 136199989Srdivacky dopower = 1; 137199989Srdivacky break; 138199989Srdivacky case 'r': 139199989Srdivacky doreboot = 1; 140199989Srdivacky break; 141199989Srdivacky default: 142199989Srdivacky usage(); 143199989Srdivacky } 144199989Srdivacky argc -= optind; 145207618Srdivacky argv += optind; 146207618Srdivacky 147199989Srdivacky if (argc < 1) 148199989Srdivacky usage(); 149199989Srdivacky 150199989Srdivacky if (dofast && nosync) { 151199989Srdivacky (void)fprintf(stderr, 152199989Srdivacky "shutdown: incompatible switches -f and -n.\n"); 153207618Srdivacky usage(); 154207618Srdivacky } 155199989Srdivacky if (doreboot && dohalt) { 156199989Srdivacky (void)fprintf(stderr, 157199989Srdivacky "shutdown: incompatible switches -h and -r.\n"); 158199989Srdivacky usage(); 159199989Srdivacky } 160199989Srdivacky if (dopower && !dohalt) { 161199989Srdivacky (void)fprintf(stderr, 162199989Srdivacky "shutdown: switch -p must be used with -h.\n"); 163199989Srdivacky usage(); 164199989Srdivacky } 165202375Srdivacky getoffset(*argv++); 166199989Srdivacky 167199989Srdivacky if (*argv) { 168199989Srdivacky for (p = mbuf, len = sizeof(mbuf); *argv; ++argv) { 169199989Srdivacky arglen = strlen(*argv); 170199989Srdivacky if ((len -= arglen) <= 2) 171199989Srdivacky break; 172199989Srdivacky if (p != mbuf) 173199989Srdivacky *p++ = ' '; 174202375Srdivacky memcpy(p, *argv, arglen); 175199989Srdivacky p += arglen; 176199989Srdivacky } 177199989Srdivacky *p = '\n'; 178199989Srdivacky *++p = '\0'; 179202375Srdivacky } 180199989Srdivacky 181199989Srdivacky if (readstdin) { 182199989Srdivacky p = mbuf; 183199989Srdivacky endp = mbuf + sizeof(mbuf) - 2; 184199989Srdivacky for (;;) { 185207618Srdivacky if (!fgets(p, endp - p + 1, stdin)) 186207618Srdivacky break; 187199989Srdivacky for (; *p && p < endp; ++p) 188199989Srdivacky ; 189199989Srdivacky if (p == endp) { 190199989Srdivacky *p = '\n'; 191199989Srdivacky *++p = '\0'; 192199989Srdivacky break; 193199989Srdivacky } 194199989Srdivacky } 195199989Srdivacky } 196207618Srdivacky mbuflen = strlen(mbuf); 197199989Srdivacky 198199989Srdivacky if (offset) 199199989Srdivacky (void)printf("Shutdown at %.24s.\n", ctime(&shuttime)); 200199989Srdivacky else 201199989Srdivacky (void)printf("Shutdown NOW!\n"); 202199989Srdivacky 203199989Srdivacky if (!(whom = getlogin())) 204199989Srdivacky whom = (pw = getpwuid(getuid())) ? pw->pw_name : "???"; 205199989Srdivacky 206199989Srdivacky#ifdef DEBUG 207199989Srdivacky (void)putc('\n', stdout); 208199989Srdivacky#else 209199989Srdivacky (void)setpriority(PRIO_PROCESS, 0, PRIO_MIN); 210199989Srdivacky 211199989Srdivacky forkpid = fork(); 212199989Srdivacky if (forkpid == -1) 213199989Srdivacky err(1, "fork"); 214199989Srdivacky if (forkpid) { 215199989Srdivacky (void)printf("shutdown: [pid %ld]\n", (long)forkpid); 216199989Srdivacky exit(0); 217199989Srdivacky } 218207618Srdivacky setsid(); 219199989Srdivacky#endif 220199989Srdivacky openlog("shutdown", LOG_CONS, LOG_AUTH); 221199989Srdivacky loop(); 222199989Srdivacky /* NOTREACHED */ 223207618Srdivacky} 224199989Srdivacky 225199989Srdivackyvoid 226199989Srdivackyloop(void) 227199989Srdivacky{ 228199989Srdivacky struct interval *tp; 229199989Srdivacky u_int sltime; 230199989Srdivacky int logged; 231199989Srdivacky 232199989Srdivacky if (offset <= NOLOG_TIME) { 233202375Srdivacky logged = 1; 234202375Srdivacky nolog(); 235199989Srdivacky } else 236199989Srdivacky logged = 0; 237199989Srdivacky tp = tlist; 238199989Srdivacky if (tp->timeleft < offset) 239199989Srdivacky (void)sleep((u_int)(offset - tp->timeleft)); 240207618Srdivacky else { 241199989Srdivacky while (offset < tp->timeleft) 242199989Srdivacky ++tp; 243199989Srdivacky /* 244199989Srdivacky * Warn now, if going to sleep more than a fifth of 245199989Srdivacky * the next wait time. 246199989Srdivacky */ 247199989Srdivacky if ((sltime = offset - tp->timeleft)) { 248207618Srdivacky if (sltime > tp->timetowait / 5) 249199989Srdivacky timewarn(offset); 250199989Srdivacky (void)sleep(sltime); 251199989Srdivacky } 252199989Srdivacky } 253199989Srdivacky for (;; ++tp) { 254199989Srdivacky timewarn(tp->timeleft); 255199989Srdivacky if (!logged && tp->timeleft <= NOLOG_TIME) { 256199989Srdivacky logged = 1; 257199989Srdivacky nolog(); 258199989Srdivacky } 259199989Srdivacky (void)sleep((u_int)tp->timetowait); 260207618Srdivacky if (!tp->timeleft) 261207618Srdivacky break; 262199989Srdivacky } 263199989Srdivacky die_you_gravy_sucking_pig_dog(); 264199989Srdivacky} 265199989Srdivacky 266199989Srdivackystatic jmp_buf alarmbuf; 267199989Srdivacky 268199989Srdivackystatic char *restricted_environ[] = { 269199989Srdivacky "PATH=" _PATH_STDPATH, 270199989Srdivacky NULL 271199989Srdivacky}; 272199989Srdivacky 273199989Srdivackyvoid 274199989Srdivackytimewarn(int timeleft) 275199989Srdivacky{ 276199989Srdivacky static char hostname[MAXHOSTNAMELEN]; 277199989Srdivacky char wcmd[MAXPATHLEN + 4]; 278207618Srdivacky extern char **environ; 279199989Srdivacky static int first; 280199989Srdivacky FILE *pf; 281199989Srdivacky 282199989Srdivacky if (!first++) 283199989Srdivacky (void)gethostname(hostname, sizeof(hostname)); 284199989Srdivacky 285199989Srdivacky /* undoc -n option to wall suppresses normal wall banner */ 286199989Srdivacky (void)snprintf(wcmd, sizeof(wcmd), "%s -n", _PATH_WALL); 287199989Srdivacky environ = restricted_environ; 288199989Srdivacky if (!(pf = popen(wcmd, "w"))) { 289199989Srdivacky syslog(LOG_ERR, "shutdown: can't find %s: %m", _PATH_WALL); 290199989Srdivacky return; 291199989Srdivacky } 292199989Srdivacky 293199989Srdivacky (void)fprintf(pf, 294199989Srdivacky "\007*** %sSystem shutdown message from %s@%s ***\007\n", 295199989Srdivacky timeleft ? "": "FINAL ", whom, hostname); 296199989Srdivacky 297199989Srdivacky if (timeleft > 10*60) 298199989Srdivacky (void)fprintf(pf, "System going down at %5.5s\n\n", 299207618Srdivacky ctime(&shuttime) + 11); 300199989Srdivacky else if (timeleft > 59) 301207618Srdivacky (void)fprintf(pf, "System going down in %d minute%s\n\n", 302207618Srdivacky timeleft / 60, (timeleft > 60) ? "s" : ""); 303206124Srdivacky else if (timeleft) 304199989Srdivacky (void)fprintf(pf, "System going down in 30 seconds\n\n"); 305199989Srdivacky else 306199989Srdivacky (void)fprintf(pf, "System going down IMMEDIATELY\n\n"); 307199989Srdivacky 308207618Srdivacky if (mbuflen) 309199989Srdivacky (void)fwrite(mbuf, sizeof(*mbuf), mbuflen, pf); 310199989Srdivacky 311199989Srdivacky /* 312199989Srdivacky * play some games, just in case wall doesn't come back 313199989Srdivacky * probably unnecessary, given that wall is careful. 314199989Srdivacky */ 315199989Srdivacky if (!setjmp(alarmbuf)) { 316199989Srdivacky (void)signal(SIGALRM, timeout); 317199989Srdivacky (void)alarm((u_int)30); 318199989Srdivacky (void)pclose(pf); 319199989Srdivacky (void)alarm((u_int)0); 320199989Srdivacky (void)signal(SIGALRM, SIG_DFL); 321199989Srdivacky } 322199989Srdivacky} 323199989Srdivacky 324199989Srdivackyvoid 325199989Srdivackytimeout(int signo) 326199989Srdivacky{ 327199989Srdivacky longjmp(alarmbuf, 1); /* XXX signal/longjmp resource leaks */ 328199989Srdivacky} 329199989Srdivacky 330199989Srdivackyvoid 331201360Srdivackydie_you_gravy_sucking_pig_dog(void) 332201360Srdivacky{ 333207618Srdivacky 334199989Srdivacky syslog(LOG_NOTICE, "%s by %s: %s", 335203954Srdivacky doreboot ? "reboot" : dohalt ? "halt" : "shutdown", whom, mbuf); 336203954Srdivacky (void)sleep(2); 337203954Srdivacky 338203954Srdivacky (void)printf("\r\nSystem shutdown time has arrived\007\007\r\n"); 339203954Srdivacky if (killflg) { 340207618Srdivacky (void)printf("\rbut you'll have to do it yourself\r\n"); 341199989Srdivacky finish(0); 342207618Srdivacky } 343199989Srdivacky if (dofast) 344199989Srdivacky doitfast(); 345199989Srdivacky#ifdef DEBUG 346199989Srdivacky if (doreboot) 347199989Srdivacky (void)printf("reboot"); 348199989Srdivacky else if (dohalt) 349199989Srdivacky (void)printf("halt"); 350199989Srdivacky if (nosync) 351199989Srdivacky (void)printf(" no sync"); 352199989Srdivacky if (dofast) 353199989Srdivacky (void)printf(" no fsck"); 354199989Srdivacky if (dodump) 355199989Srdivacky (void)printf(" with dump"); 356207618Srdivacky (void)printf("\nkill -HUP 1\n"); 357199989Srdivacky#else 358207618Srdivacky if (doreboot) { 359207618Srdivacky execle(_PATH_REBOOT, "reboot", "-l", 360199989Srdivacky (nosync ? "-n" : (dodump ? "-d" : NULL)), 361207618Srdivacky (dodump ? "-d" : NULL), (char *)NULL, (char *)NULL); 362207618Srdivacky syslog(LOG_ERR, "shutdown: can't exec %s: %m.", _PATH_REBOOT); 363199989Srdivacky warn(_PATH_REBOOT); 364207618Srdivacky } 365207618Srdivacky else if (dohalt) { 366207618Srdivacky execle(_PATH_HALT, "halt", "-l", 367207618Srdivacky (dopower ? "-p" : (nosync ? "-n" : (dodump ? "-d" : NULL))), 368199989Srdivacky (nosync ? "-n" : (dodump ? "-d" : NULL)), 369199989Srdivacky (dodump ? "-d" : NULL), (char *)NULL, (char *)NULL); 370199989Srdivacky syslog(LOG_ERR, "shutdown: can't exec %s: %m.", _PATH_HALT); 371199989Srdivacky warn(_PATH_HALT); 372207618Srdivacky } 373207618Srdivacky if (access(_PATH_RC, R_OK) != -1) { 374207618Srdivacky pid_t pid; 375207618Srdivacky struct termios t; 376207618Srdivacky int fd; 377199989Srdivacky 378199989Srdivacky switch ((pid = fork())) { 379199989Srdivacky case -1: 380199989Srdivacky break; 381207618Srdivacky case 0: 382207618Srdivacky if (revoke(_PATH_CONSOLE) == -1) 383207618Srdivacky perror("revoke"); 384199989Srdivacky if (setsid() == -1) 385199989Srdivacky perror("setsid"); 386207618Srdivacky fd = open(_PATH_CONSOLE, O_RDWR); 387207618Srdivacky if (fd == -1) 388207618Srdivacky perror("open"); 389199989Srdivacky dup2(fd, 0); 390199989Srdivacky dup2(fd, 1); 391207618Srdivacky dup2(fd, 2); 392207618Srdivacky if (fd > 2) 393207618Srdivacky close(fd); 394199989Srdivacky 395199989Srdivacky /* At a minimum... */ 396207618Srdivacky tcgetattr(0, &t); 397207618Srdivacky t.c_oflag |= (ONLCR | OPOST); 398207618Srdivacky tcsetattr(0, TCSANOW, &t); 399199989Srdivacky 400207618Srdivacky execl(_PATH_BSHELL, "sh", _PATH_RC, "shutdown", (char *)NULL); 401207618Srdivacky _exit(1); 402207618Srdivacky default: 403199989Srdivacky waitpid(pid, NULL, 0); 404199989Srdivacky } 405207618Srdivacky } 406207618Srdivacky (void)kill(1, SIGTERM); /* to single user */ 407199989Srdivacky#endif 408207618Srdivacky finish(0); 409207618Srdivacky} 410199989Srdivacky 411199989Srdivacky#define ATOI2(p) (p[0] - '0') * 10 + (p[1] - '0'); p += 2; 412199989Srdivacky 413207618Srdivackyvoid 414207618Srdivackygetoffset(char *timearg) 415199989Srdivacky{ 416207618Srdivacky struct tm *lt; 417207618Srdivacky int this_year; 418207618Srdivacky time_t now; 419207618Srdivacky char *p; 420207618Srdivacky 421207618Srdivacky if (!strcasecmp(timearg, "now")) { /* now */ 422207618Srdivacky offset = 0; 423207618Srdivacky return; 424207618Srdivacky } 425207618Srdivacky 426207618Srdivacky (void)time(&now); 427207618Srdivacky if (*timearg == '+') { /* +minutes */ 428207618Srdivacky if (!isdigit(*++timearg)) 429207618Srdivacky badtime(); 430207618Srdivacky offset = atoi(timearg) * 60; 431207618Srdivacky shuttime = now + offset; 432207618Srdivacky return; 433207618Srdivacky } 434207618Srdivacky 435207618Srdivacky /* handle hh:mm by getting rid of the colon */ 436207618Srdivacky for (p = timearg; *p; ++p) { 437207618Srdivacky if (!isascii(*p) || !isdigit(*p)) { 438199989Srdivacky if (*p == ':' && strlen(p) == 3) { 439207618Srdivacky p[0] = p[1]; 440207618Srdivacky p[1] = p[2]; 441207618Srdivacky p[2] = '\0'; 442207618Srdivacky } else 443207618Srdivacky badtime(); 444207618Srdivacky } 445207618Srdivacky } 446207618Srdivacky 447207618Srdivacky unsetenv("TZ"); /* OUR timezone */ 448207618Srdivacky lt = localtime(&now); /* current time val */ 449207618Srdivacky 450207618Srdivacky switch (strlen(timearg)) { 451199989Srdivacky case 10: 452207618Srdivacky this_year = lt->tm_year; 453207618Srdivacky lt->tm_year = ATOI2(timearg); 454207618Srdivacky /* 455199989Srdivacky * check if the specified year is in the next century. 456207618Srdivacky * allow for one year of user error as many people will 457207618Srdivacky * enter n - 1 at the start of year n. 458199989Srdivacky */ 459207618Srdivacky if (lt->tm_year < (this_year % 100) - 1) 460207618Srdivacky lt->tm_year += 100; 461199989Srdivacky /* adjust for the year 2000 and beyond */ 462207618Srdivacky lt->tm_year += (this_year - (this_year % 100)); 463207618Srdivacky /* FALLTHROUGH */ 464207618Srdivacky case 8: 465207618Srdivacky lt->tm_mon = ATOI2(timearg); 466207618Srdivacky if (--lt->tm_mon < 0 || lt->tm_mon > 11) 467207618Srdivacky badtime(); 468201360Srdivacky /* FALLTHROUGH */ 469207618Srdivacky case 6: 470207618Srdivacky lt->tm_mday = ATOI2(timearg); 471207618Srdivacky if (lt->tm_mday < 1 || lt->tm_mday > 31) 472199989Srdivacky badtime(); 473207618Srdivacky /* FALLTHROUGH */ 474207618Srdivacky case 4: 475207618Srdivacky lt->tm_hour = ATOI2(timearg); 476207618Srdivacky if (lt->tm_hour < 0 || lt->tm_hour > 23) 477207618Srdivacky badtime(); 478207618Srdivacky lt->tm_min = ATOI2(timearg); 479199989Srdivacky if (lt->tm_min < 0 || lt->tm_min > 59) 480207618Srdivacky badtime(); 481207618Srdivacky lt->tm_sec = 0; 482207618Srdivacky if ((shuttime = mktime(lt)) == -1) 483207618Srdivacky badtime(); 484199989Srdivacky if ((offset = shuttime - now) < 0) 485207618Srdivacky errx(1, "that time is already past."); 486199989Srdivacky break; 487199989Srdivacky default: 488207618Srdivacky badtime(); 489199989Srdivacky } 490199989Srdivacky} 491199989Srdivacky 492207618Srdivacky#define FSMSG "fastboot file for fsck\n" 493207618Srdivackyvoid 494207618Srdivackydoitfast(void) 495207618Srdivacky{ 496207618Srdivacky int fastfd; 497207618Srdivacky 498207618Srdivacky if ((fastfd = open(_PATH_FASTBOOT, O_WRONLY|O_CREAT|O_TRUNC, 499207618Srdivacky 0664)) >= 0) { 500207618Srdivacky (void)write(fastfd, FSMSG, sizeof(FSMSG) - 1); 501207618Srdivacky (void)close(fastfd); 502207618Srdivacky } 503207618Srdivacky} 504199989Srdivacky 505199989Srdivacky#define NOMSG "\n\nNO LOGINS: System going down at " 506199989Srdivackyvoid 507199989Srdivackynolog(void) 508199989Srdivacky{ 509 int logfd; 510 char *ct; 511 512 (void)unlink(_PATH_NOLOGIN); /* in case linked to another file */ 513 (void)signal(SIGINT, finish); 514 (void)signal(SIGHUP, finish); 515 (void)signal(SIGQUIT, finish); 516 (void)signal(SIGTERM, finish); 517 if ((logfd = open(_PATH_NOLOGIN, O_WRONLY|O_CREAT|O_TRUNC, 518 0664)) >= 0) { 519 (void)write(logfd, NOMSG, sizeof(NOMSG) - 1); 520 ct = ctime(&shuttime); 521 (void)write(logfd, ct + 11, 5); 522 (void)write(logfd, "\n\n", 2); 523 (void)write(logfd, mbuf, strlen(mbuf)); 524 (void)close(logfd); 525 } 526} 527 528void 529finish(int signo) 530{ 531 if (!killflg) 532 (void)unlink(_PATH_NOLOGIN); 533 if (signo == 0) 534 exit(0); 535 else 536 _exit(0); 537} 538 539void 540badtime(void) 541{ 542 errx(1, "bad time format."); 543} 544 545void 546usage(void) 547{ 548 fprintf(stderr, "usage: shutdown [-] [-dfhknpr] time [warning-message ...]\n"); 549 exit(1); 550} 551