diff --git a/man/openrc-shutdown.8 b/man/openrc-shutdown.8 index d0e95e24..5d81c4af 100644 --- a/man/openrc-shutdown.8 +++ b/man/openrc-shutdown.8 @@ -27,6 +27,9 @@ is the utility that communicates with openrc-init(8) to bring down the system or instruct openrc-init to re-execute itself. It supports the following options: .Bl -tag -width "poweroff" +.It Fl d , -dry-run +Print the action that would be taken without executing it. This is to +allow testing. .It Fl H , -halt Stop all services, kill all remaining processes and halt the system. .It Fl k , -kexec diff --git a/src/rc/openrc-shutdown.c b/src/rc/openrc-shutdown.c index 0ed77445..ecb251a8 100644 --- a/src/rc/openrc-shutdown.c +++ b/src/rc/openrc-shutdown.c @@ -35,8 +35,9 @@ const char *applet = NULL; const char *extraopts = NULL; -const char *getoptstring = "HkpRr" getoptstring_COMMON; +const char *getoptstring = "dHkpRr" getoptstring_COMMON; const struct option longopts[] = { + { "dry-run", no_argument, NULL, 'd'}, { "halt", no_argument, NULL, 'H'}, { "kexec", no_argument, NULL, 'k'}, { "poweroff", no_argument, NULL, 'p'}, @@ -45,6 +46,7 @@ const struct option longopts[] = { longopts_COMMON }; const char * const longopts_help[] = { + "print actions instead of executing them", "halt the system", "reboot the system using kexec", "power off the system", @@ -56,13 +58,16 @@ const char *usagestring = NULL; const char *exclusive = "Select one of " "--halt, --kexec, --poweroff, --reexec or --reboot"; -static void send_cmd(const char *cmd) +static void send_cmd(const char *cmd, bool dryrun) { FILE *fifo; size_t ignored; + if (dryrun) { + einfo("Would send %s to init", cmd); + return; + } fifo = fopen(RC_INIT_FIFO, "w"); - if (!fifo) { perror("fopen"); return; @@ -78,6 +83,7 @@ int main(int argc, char **argv) { int opt; int cmd_count = 0; + bool do_dryrun = false; bool do_halt = false; bool do_kexec = false; bool do_poweroff = false; @@ -85,12 +91,13 @@ int main(int argc, char **argv) bool do_reexec = false; applet = basename_c(argv[0]); -if (geteuid() != 0) - eerrorx("%s: you must be root\n", applet); while ((opt = getopt_long(argc, argv, getoptstring, longopts, (int *) 0)) != -1) { switch (opt) { + case 'd': + do_dryrun = true; + break; case 'H': do_halt = true; cmd_count++; @@ -114,21 +121,23 @@ if (geteuid() != 0) case_RC_COMMON_GETOPT } } +if (geteuid() != 0 && ! do_dryrun) + eerrorx("%s: you must be root\n", applet); if (cmd_count > 1) { eerror("%s: %s\n", applet, exclusive); usage(EXIT_FAILURE); } if (do_halt) - send_cmd("halt"); + send_cmd("halt", do_dryrun); else if (do_kexec) - send_cmd("kexec"); + send_cmd("kexec", do_dryrun); else if (do_poweroff) - send_cmd("poweroff"); + send_cmd("poweroff", do_dryrun); else if (do_reboot) - send_cmd("reboot"); + send_cmd("reboot", do_dryrun); else if (do_reexec) - send_cmd("reexec"); + send_cmd("reexec", do_dryrun); else - send_cmd("single"); + send_cmd("single", do_dryrun); return 0; }