diff --git a/include/paths.h b/include/paths.h --- a/include/paths.h +++ b/include/paths.h @@ -81,6 +81,7 @@ #define _PATH_MOUNT "/sbin/mount" #define _PATH_NEWFS "/sbin/newfs" #define _PATH_NOLOGIN "/var/run/nologin" +#define _PATH_NOSHUTDOWN "/var/run/noshutdown" #define _PATH_RCP "/bin/rcp" #define _PATH_REBOOT "/sbin/reboot" #define _PATH_RLOGIN "/usr/bin/rlogin" diff --git a/libexec/rc/rc.conf b/libexec/rc/rc.conf --- a/libexec/rc/rc.conf +++ b/libexec/rc/rc.conf @@ -29,6 +29,8 @@ rc_info="NO" # Enables display of informational messages at boot. rc_startmsgs="YES" # Show "Starting foo:" messages at boot rcshutdown_timeout="90" # Seconds to wait before terminating rc.shutdown +precious_machine="NO" # Set to YES to get some guards against mis-directed + # shutdown(8) commands early_late_divider="FILESYSTEMS" # Script that separates early/late # stages of the boot process. Make sure you know # the ramifications if you change this. diff --git a/libexec/rc/rc.d/Makefile b/libexec/rc/rc.d/Makefile --- a/libexec/rc/rc.d/Makefile +++ b/libexec/rc/rc.d/Makefile @@ -64,6 +64,7 @@ nfsd \ nfsuserd \ nisdomain \ + noshutdown \ ${_nscd} \ ${_opensm} \ os-release \ diff --git a/libexec/rc/rc.d/noshutdown b/libexec/rc/rc.d/noshutdown new file mode 100755 --- /dev/null +++ b/libexec/rc/rc.d/noshutdown @@ -0,0 +1,31 @@ +#!/bin/sh +# +# + +# PROVIDE: noshutdown +# REQUIRE: var +# BEFORE: LOGIN + +. /etc/rc.subr + +name="noshutdown" +desc="Disable shutdown(8) for precious machines" +rcvar="precious_machine" +start_cmd="noshutdown_start" +stop_cmd="noshutdown_stop" + +: ${noshutdown_file:="/var/run/noshutdown"} + +noshutdown_start() +{ + touch $noshutdown_file +} + +noshutdown_stop() +{ + rm -f $noshutdown_file +} + +load_rc_config $name + +run_rc_command "$1" diff --git a/sbin/shutdown/shutdown.8 b/sbin/shutdown/shutdown.8 --- a/sbin/shutdown/shutdown.8 +++ b/sbin/shutdown/shutdown.8 @@ -36,7 +36,7 @@ .Nm .Op Fl .Oo -.Fl c | Fl h | Fl p | +.Fl c | Fl f | Fl h | Fl p | .Fl r | Fl k .Oc .Oo @@ -71,6 +71,12 @@ driver that implement this functionality support this flag. The amount of time the system is off is dependent on the device that implements this feature. +.It Fl f +The +.Nm +ignores the presence of the +.Pa /var/run/noshutdown +file. .It Fl h The system is halted at the specified .Ar time . @@ -206,6 +212,12 @@ .Nm created will be removed automatically. .Pp +If the +.Pa /var/run/noshutdown +file is present, +.Nm +exits without executing any action on the system. +.Pp When run without options, the .Nm utility will place the system into single user mode at the @@ -219,11 +231,18 @@ shutdown -p now .Ed .Sh FILES -.Bl -tag -width /var/run/nologin -compact +.Bl -tag -width /var/run/noshutdown -compact .It Pa /var/run/nologin tells .Xr login 1 not to let anyone log in +.It Pa /var/run/noshutdown +prevents +.Nm +from initiating an action on the system. +Can be overridden with the +.Fl f +option. .El .Sh EXAMPLES Reboot the system in 30 minutes and display a warning message on the terminals diff --git a/sbin/shutdown/shutdown.c b/sbin/shutdown/shutdown.c --- a/sbin/shutdown/shutdown.c +++ b/sbin/shutdown/shutdown.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -79,7 +80,8 @@ #undef S static time_t offset, shuttime; -static int docycle, dohalt, dopower, doreboot, killflg, mbuflen, oflag; +static int docycle, dohalt, dopower, doreboot, ign_noshutdown, + killflg, mbuflen, oflag; static char mbuf[BUFSIZ]; static const char *nosync, *whom; @@ -100,6 +102,7 @@ { char *p, *endp; struct passwd *pw; + struct stat st; int arglen, ch, len, readstdin; bool dowarn; @@ -133,7 +136,7 @@ goto poweroff; } - while ((ch = getopt(argc, argv, "-chknopqr")) != -1) + while ((ch = getopt(argc, argv, "-cfhknopqr")) != -1) switch (ch) { case '-': readstdin = 1; @@ -141,6 +144,9 @@ case 'c': docycle = 1; break; + case 'f': + ign_noshutdown = 1; + break; case 'h': dohalt = 1; break; @@ -216,6 +222,12 @@ } mbuflen = strlen(mbuf); + if (!ign_noshutdown && stat(_PATH_NOSHUTDOWN, &st) == 0) { + (void)printf("Shutdown cannot be done, " _PATH_NOSHUTDOWN + " is present\n"); + exit(2); + } + if (offset) { BOOTTRACE("Shutdown at %s", ctime(&shuttime)); (void)printf("Shutdown at %.24s.\n", ctime(&shuttime)); @@ -593,7 +605,7 @@ if (cp != NULL) warnx("%s", cp); (void)fprintf(stderr, - "usage: shutdown [-] [-c | -h | -p | -r | -k] [-o [-n]] [-q] time [warning-message ...]\n" + "usage: shutdown [-] [-c | -f | -h | -p | -r | -k] [-o [-n]] [-q] time [warning-message ...]\n" " poweroff\n"); exit(1); }