From d038e02fd667ab6c02875840105798aaa7029504 Mon Sep 17 00:00:00 2001 From: rgrimes Date: Thu, 26 May 1994 06:35:07 +0000 Subject: BSD 4.4 Lite sbin Sources Note: XNSrouted and routed NOT imported here, they shall be imported with usr.sbin. --- sbin/shutdown/Makefile | 9 + sbin/shutdown/pathnames.h | 41 ++++ sbin/shutdown/shutdown.8 | 162 +++++++++++++++ sbin/shutdown/shutdown.c | 492 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 704 insertions(+) create mode 100644 sbin/shutdown/Makefile create mode 100644 sbin/shutdown/pathnames.h create mode 100644 sbin/shutdown/shutdown.8 create mode 100644 sbin/shutdown/shutdown.c (limited to 'sbin/shutdown') diff --git a/sbin/shutdown/Makefile b/sbin/shutdown/Makefile new file mode 100644 index 0000000..19122f2 --- /dev/null +++ b/sbin/shutdown/Makefile @@ -0,0 +1,9 @@ +# @(#)Makefile 8.1 (Berkeley) 6/5/93 + +PROG= shutdown +MAN8= shutdown.0 +BINOWN= root +BINGRP= operator +BINMODE=4550 + +.include diff --git a/sbin/shutdown/pathnames.h b/sbin/shutdown/pathnames.h new file mode 100644 index 0000000..9d05838 --- /dev/null +++ b/sbin/shutdown/pathnames.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * 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. + * + * @(#)pathnames.h 8.1 (Berkeley) 6/5/93 + */ + +#include + +#define _PATH_FASTBOOT "/fastboot" +#define _PATH_HALT "/sbin/halt" +#define _PATH_REBOOT "/sbin/reboot" +#define _PATH_WALL "/usr/bin/wall" diff --git a/sbin/shutdown/shutdown.8 b/sbin/shutdown/shutdown.8 new file mode 100644 index 0000000..d582569 --- /dev/null +++ b/sbin/shutdown/shutdown.8 @@ -0,0 +1,162 @@ +.\" Copyright (c) 1988, 1991, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" 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. +.\" +.\" @(#)shutdown.8 8.1 (Berkeley) 6/5/93 +.\" +.Dd June 5, 1993 +.Dt SHUTDOWN 8 +.Os BSD 4 +.Sh NAME +.Nm shutdown +.Nd "close down the system at a given time" +.Sh SYNOPSIS +.Nm shutdown +.Op Fl +.Op Fl fhkrn +.Ar time +.Op Ar warning-message ... +.Sh DESCRIPTION +.Nm Shutdown +provides an automated shutdown procedure for super-users +to nicely notify users when the system is shutting down, +saving them from system administrators, hackers, and gurus, who +would otherwise not bother with such niceties. +.Pp +Available friendlinesses: +.Bl -tag -width time +.It Fl f +.Nm Shutdown +arranges, in the manner of +.Xr fastboot 8 , +for the file systems +.Em not to be +checked on reboot. +.It Fl h +The system is halted at the specified +.Ar time +when +.Nm shutdown +execs +.Xr halt 8 . +.It Fl k +Kick every body off. +The +.Fl k +option +does not actually halt the system, but leaves the +system multi-user with logins disabled (for all but super-user). +.It Fl n +Prevent the normal +.Xr sync 2 +before stopping. +.It Fl r +.Nm Shutdown +execs +.Xr reboot 8 +at the specified +.Ar time . +.It Ar time +.Ar Time +is the time at which +.Nm shutdown +will bring the system down and +may be the word +.Ar now +(indicating an immediate shutdown) or +specify a future time in one of two formats: +.Ar +number , +or +.Ar yymmddhhmm , +where the year, month, and day may be defaulted +to the current system values. The first form brings the system down in +.Ar number +minutes and the second at the absolute time specified. +.It Ar warning-message +Any other arguments comprise the warning message that is broadcast +to users currently logged into the system. +.It Fl +If +.Ql Fl +is supplied as an option, the warning message is read from the standard +input. +.El +.Pp +At intervals, becoming more frequent as apocalypse approaches +and starting at ten hours before shutdown, warning messages are displayed +on the terminals of all users logged in. Five minutes before +shutdown, or immediately if shutdown is in less than 5 minutes, +logins are disabled by creating +.Pa /etc/nologin +and copying the +warning message there. If this file exists when a user attempts to +log in, +.Xr login 1 +prints its contents and exits. The file is +removed just before +.Nm shutdown +exits. +.Pp +At shutdown time a message is written in the system log, containing the +time of shutdown, who initiated the shutdown and the reason. +A terminate +signal is then sent to +.Xr init +to bring the system down to single-user state (depending on above +options). +The time of the shutdown and the warning message +are placed in +.Pa /etc/nologin +and should be used to +inform the users about when the system will be back up +and why it is going down (or anything else). +.Sh FILES +.Bl -tag -width /etc/nologin -compact +.It Pa /etc/nologin +tells login not to let anyone log in +.It Pa /fastboot +tells +.Xr rc 8 +not to run fsck when rebooting +.El +.Sh SEE ALSO +.Xr login 1 , +.Xr wall 1 , +.Xr fastboot 8 , +.Xr halt 8 , +.Xr reboot 8 +.Sh BACKWARD COMPATIBILITY +The hours and minutes in the second time format may be separated by +a colon (``:'') for backward compatibility. +.Sh HISTORY +The +.Nm +command appeared in +.Bx 4.0 . diff --git a/sbin/shutdown/shutdown.c b/sbin/shutdown/shutdown.c new file mode 100644 index 0000000..c63ba65 --- /dev/null +++ b/sbin/shutdown/shutdown.c @@ -0,0 +1,492 @@ +/* + * Copyright (c) 1988, 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * 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 +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.2 (Berkeley) 2/16/94"; +#endif /* not lint */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "pathnames.h" + +#ifdef DEBUG +#undef _PATH_NOLOGIN +#define _PATH_NOLOGIN "./nologin" +#undef _PATH_FASTBOOT +#define _PATH_FASTBOOT "./fastboot" +#endif + +#define H *60*60 +#define M *60 +#define S *1 +#define NOLOG_TIME 5*60 +struct interval { + 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, +}; +#undef H +#undef M +#undef S + +static time_t offset, shuttime; +static int dofast, dohalt, doreboot, killflg, mbuflen; +static char *nosync, *whom, mbuf[BUFSIZ]; + +void badtime __P((void)); +void die_you_gravy_sucking_pig_dog __P((void)); +void doitfast __P((void)); +void finish __P((int)); +void getoffset __P((char *)); +void loop __P((void)); +void nolog __P((void)); +void timeout __P((int)); +void timewarn __P((int)); +void usage __P((void)); + +int +main(argc, argv) + int argc; + char *argv[]; +{ + extern int optind; + register char *p, *endp; + struct passwd *pw; + int arglen, ch, len, readstdin; + +#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': + killflg = 1; + break; + case 'n': + nosync = "-n"; + break; + case 'r': + doreboot = 1; + break; + case '?': + default: + usage(); + } + argc -= optind; + argv += optind; + + if (argc < 1) + usage(); + + if (dofast && nosync) { + (void)fprintf(stderr, + "shutdown: incompatible switches -f and -n.\n"); + usage(); + } + if (doreboot && dohalt) { + (void)fprintf(stderr, + "shutdown: incompatible switches -h and -r.\n"); + usage(); + } + 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'; + } + + 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) + (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 + (void)putc('\n', stdout); +#else + (void)setpriority(PRIO_PROCESS, 0, PRIO_MIN); + { + int forkpid; + + forkpid = fork(); + if (forkpid == -1) { + perror("shutdown: fork"); + exit(1); + } + if (forkpid) { + (void)printf("shutdown: [pid %d]\n", forkpid); + exit(0); + } + } +#endif + openlog("shutdown", LOG_CONS, LOG_AUTH); + loop(); + /* NOTREACHED */ +} + +void +loop() +{ + struct interval *tp; + u_int sltime; + int logged; + + 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) + timewarn(offset); + (void)sleep(sltime); + } + } + for (;; ++tp) { + timewarn(tp->timeleft); + if (!logged && tp->timeleft <= NOLOG_TIME) { + logged = 1; + nolog(); + } + (void)sleep((u_int)tp->timetowait); + if (!tp->timeleft) + break; + } + die_you_gravy_sucking_pig_dog(); +} + +static jmp_buf alarmbuf; + +void +timewarn(timeleft) + int timeleft; +{ + static int first; + static char hostname[MAXHOSTNAMELEN + 1]; + FILE *pf; + char wcmd[MAXPATHLEN + 4]; + + if (!first++) + (void)gethostname(hostname, sizeof(hostname)); + + /* undoc -n option to wall suppresses normal wall banner */ + (void)snprintf(wcmd, sizeof(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", + timeleft ? "": "FINAL ", whom, hostname); + + if (timeleft > 10*60) + (void)fprintf(pf, "System going down at %5.5s\n\n", + ctime(&shuttime) + 11); + else if (timeleft > 59) + (void)fprintf(pf, "System going down in %d minute%s\n\n", + timeleft / 60, (timeleft > 60) ? "s" : ""); + else if (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); + } +} + +void +timeout(signo) + int signo; +{ + longjmp(alarmbuf, 1); +} + +void +die_you_gravy_sucking_pig_dog() +{ + + 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(0); + } + 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(0); +} + +#define ATOI2(p) (p[0] - '0') * 10 + (p[1] - '0'); p += 2; + +void +getoffset(timearg) + register char *timearg; +{ + register struct tm *lt; + register char *p; + time_t now; + + 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(); + } +} + +#define FSMSG "fastboot file for fsck\n" +void +doitfast() +{ + int fastfd; + + if ((fastfd = open(_PATH_FASTBOOT, O_WRONLY|O_CREAT|O_TRUNC, + 0664)) >= 0) { + (void)write(fastfd, FSMSG, sizeof(FSMSG) - 1); + (void)close(fastfd); + } +} + +#define NOMSG "\n\nNO LOGINS: System going down at " +void +nolog() +{ + int logfd; + char *ct; + + (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); + } +} + +void +finish(signo) + int signo; +{ + (void)unlink(_PATH_NOLOGIN); + exit(0); +} + +void +badtime() +{ + (void)fprintf(stderr, "shutdown: bad time format.\n"); + exit(1); +} + +void +usage() +{ + fprintf(stderr, "usage: shutdown [-fhknr] shutdowntime [ message ]\n"); + exit(1); +} -- cgit v1.1