From 2743a49d916e96e72761bf82ce2c34750a4beae1 Mon Sep 17 00:00:00 2001 From: Joachim Nilsson Date: Sun, 14 Aug 2016 12:27:52 +0200 Subject: [PATCH] reboot: Add halt/poweroff/suspend and force cmd This patch is a complete rewrite of the Finit reboot command. Not only does it bring it up to speed with the new signal model, but it also adds new features like poweroff, halt, and suspend -- including a forced mode that goes for reboot(2) immediately. Signed-off-by: Joachim Nilsson --- reboot.c | 172 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 168 insertions(+), 4 deletions(-) diff --git a/reboot.c b/reboot.c index c2d29c69..b75ea604 100644 --- a/reboot.c +++ b/reboot.c @@ -1,6 +1,6 @@ -/* reboot for finit +/* reboot, halt, poweroff, shutdown, suspend for finit * - * Copyright (c) 2009-2012 Joachim Nilsson + * Copyright (c) 2009-2016 Joachim Nilsson * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -21,11 +21,175 @@ * THE SOFTWARE. */ +#include +#include #include +#include +#include +#include +#include -int main (void) +typedef enum { + CMD_UNKNOWN = -1, + CMD_REBOOT = 0, + CMD_HALT, + CMD_POWEROFF, + CMD_SUSPEND, +} cmd_t; + +static cmd_t cmd = CMD_UNKNOWN; +static char *msg = NULL; +extern char *__progname; + +static void translate(void) { - return !!kill(1, SIGINT); + if (cmd == CMD_UNKNOWN) { + if (!strcmp(__progname, "halt") || !strcmp(__progname, "shutdown")) + cmd = CMD_HALT; + else if (!strcmp(__progname, "poweroff")) + cmd = CMD_POWEROFF; + else if (!strcmp(__progname, "suspend")) + cmd = CMD_SUSPEND; + else + cmd = CMD_REBOOT; + } + + switch (cmd) { + case CMD_REBOOT: + msg = "reboot"; + break; + + case CMD_HALT: + msg = "halt"; + break; + + case CMD_POWEROFF: + msg = "power-off"; + break; + + case CMD_SUSPEND: + msg = "suspend"; + break; + + case CMD_UNKNOWN: + cmd = CMD_REBOOT; + msg = "reboot"; + break; + } +} + +static int usage(int rc) +{ + fprintf(stderr, "Usage: %s [OPTIONS]\n\n" + "Options:\n" + " -h, --help This help text\n" + " -f, --force Force unsafe %s now\n" + " --halt Halt system, regardless of how the command is called.\n" + " -p, --poweroff Power-off system, regardless of how the command is called.\n" + " --reboot Reboot system, regardless of how the command is called.\n" + "\n", __progname, msg); + + return rc; +} + +int main(int argc, char *argv[]) +{ + int c, force = 0; + struct option long_options[] = { + {"help", 0, NULL, 'h'}, + {"force", 0, NULL, 'f'}, + {"halt", 0, NULL, 'H'}, + {"poweroff", 0, NULL, 'p'}, + {"reboot", 0, NULL, 'r'}, + {NULL, 0, NULL, 0} + }; + + /* Initial command taken from program name */ + translate(); + + while ((c = getopt_long(argc, argv, "h?fHpr", long_options, NULL)) != EOF) { + switch(c) { + case 'h': + case '?': + return usage(0); + + case 'f': + force = 1; + break; + + case 'H': + cmd = CMD_HALT; + break; + + case 'p': + cmd = CMD_POWEROFF; + break; + + case 'r': + cmd = CMD_REBOOT; + break; + + default: + return usage(1); + } + } + + /* Check for any overrides */ + translate(); + + if (force) { + sync(); + + switch (cmd) { + case CMD_REBOOT: + c = reboot(RB_AUTOBOOT); + break; + + case CMD_HALT: + c = reboot(RB_HALT_SYSTEM); + break; + + case CMD_POWEROFF: + c = reboot(RB_POWER_OFF); + break; + + case CMD_SUSPEND: + c = reboot(RB_SW_SUSPEND); + break; + + case CMD_UNKNOWN: + errx(1, "Invalid command"); + break; + } + + if (c) + warn("Failed forced %s", msg); + else + return 0; + } + + switch (cmd) { + case CMD_REBOOT: + c = kill(1, SIGTERM); + break; + + case CMD_HALT: + c = kill(1, SIGUSR1); + break; + + case CMD_POWEROFF: + c = kill(1, SIGUSR2); + break; + + case CMD_UNKNOWN: + errx(1, "Invalid command"); + break; + } + + if (c) + err(1, "Failed signalling init to %s", msg); + + return 0; } /**