From e60baa725230ed256b04bfe82488ae46fa770a5c Mon Sep 17 00:00:00 2001 From: Warner Losh Date: Wed, 25 Oct 2017 15:30:30 +0000 Subject: [PATCH] Add power cycle support (-c) to shutdown. Sponsored by: Netflix --- sbin/shutdown/shutdown.8 | 17 ++++++++++++++--- sbin/shutdown/shutdown.c | 29 +++++++++++++++++++++-------- 2 files changed, 35 insertions(+), 11 deletions(-) diff --git a/sbin/shutdown/shutdown.8 b/sbin/shutdown/shutdown.8 index 1b7c6e19bdf6..b388aaf92fe9 100644 --- a/sbin/shutdown/shutdown.8 +++ b/sbin/shutdown/shutdown.8 @@ -28,7 +28,7 @@ .\" @(#)shutdown.8 8.2 (Berkeley) 4/27/95 .\" $FreeBSD$ .\" -.Dd September 21, 2016 +.Dd October 23, 2017 .Dt SHUTDOWN 8 .Os .Sh NAME @@ -39,7 +39,7 @@ .Nm .Op Fl .Oo -.Fl h | Fl p | +.Fl c | Fl h | Fl p | .Fl r | Fl k .Oc .Oo @@ -59,12 +59,22 @@ would otherwise not bother with such niceties. .Pp The following options are available: .Bl -tag -width indent +.It Fl c +The system is power cycled (power turned off and then back on) +at the specified time. +If the hardware doesn't support power cycle, the system will be +halted. +At the present time, only systems with BMC supported by the +.Xr ipmi 4 +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 h The system is halted at the specified .Ar time . .It Fl p The system is halted and the power is turned off -(hardware support required) +(hardware support required, otherwise the system is halted) at the specified .Ar time . .It Fl r @@ -79,6 +89,7 @@ does not actually halt the system, but leaves the system multi-user with logins disabled (for all but super-user). .It Fl o If one of the +.Fl c , .Fl h , .Fl p or diff --git a/sbin/shutdown/shutdown.c b/sbin/shutdown/shutdown.c index 6c24e4b2a580..7a878257a736 100644 --- a/sbin/shutdown/shutdown.c +++ b/sbin/shutdown/shutdown.c @@ -89,7 +89,7 @@ static struct interval { #undef S static time_t offset, shuttime; -static int dohalt, dopower, doreboot, killflg, mbuflen, oflag; +static int docycle, dohalt, dopower, doreboot, killflg, mbuflen, oflag; static char mbuf[BUFSIZ]; static const char *nosync, *whom; @@ -141,11 +141,14 @@ main(int argc, char **argv) goto poweroff; } - while ((ch = getopt(argc, argv, "-hknopr")) != -1) + while ((ch = getopt(argc, argv, "-chknopr")) != -1) switch (ch) { case '-': readstdin = 1; break; + case 'c': + docycle = 1; + break; case 'h': dohalt = 1; break; @@ -174,11 +177,11 @@ main(int argc, char **argv) if (argc < 1) usage((char *)NULL); - if (killflg + doreboot + dohalt + dopower > 1) - usage("incompatible switches -h, -k, -p and -r"); + if (killflg + doreboot + dohalt + dopower + docycle > 1) + usage("incompatible switches -c, -h, -k, -p and -r"); - if (oflag && !(dohalt || dopower || doreboot)) - usage("-o requires -h, -p or -r"); + if (oflag && !(dohalt || dopower || doreboot || docycle)) + usage("-o requires -c, -h, -p or -r"); if (nosync != NULL && !oflag) usage("-n requires -o"); @@ -356,8 +359,8 @@ die_you_gravy_sucking_pig_dog(void) char *empty_environ[] = { NULL }; syslog(LOG_NOTICE, "%s by %s: %s", - doreboot ? "reboot" : dohalt ? "halt" : dopower ? "power-down" : - "shutdown", whom, mbuf); + doreboot ? "reboot" : dohalt ? "halt" : dopower ? "power-down" : + docycle ? "power-cycle" : "shutdown", whom, mbuf); (void)printf("\r\nSystem shutdown time has arrived\007\007\r\n"); if (killflg) { @@ -367,6 +370,8 @@ die_you_gravy_sucking_pig_dog(void) #ifdef DEBUG if (doreboot) (void)printf("reboot"); + else if (docycle) + (void)printf("power-cycle"); else if (dohalt) (void)printf("halt"); else if (dopower) @@ -379,6 +384,7 @@ die_you_gravy_sucking_pig_dog(void) (void)kill(1, doreboot ? SIGINT : /* reboot */ dohalt ? SIGUSR1 : /* halt */ dopower ? SIGUSR2 : /* power-down */ + docycle ? SIGWINCH : /* power-cycle */ SIGTERM); /* single-user */ } else { if (doreboot) { @@ -402,6 +408,13 @@ die_you_gravy_sucking_pig_dog(void) _PATH_HALT); warn(_PATH_HALT); } + else if (docycle) { + execle(_PATH_HALT, "halt", "-l", "-c", nosync, + (char *)NULL, empty_environ); + syslog(LOG_ERR, "shutdown: can't exec %s: %m.", + _PATH_HALT); + warn(_PATH_HALT); + } (void)kill(1, SIGTERM); /* to single-user */ } #endif