]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
systemctl: convert shutdown_parse_argv to OPTION macros
authorZbigniew Jędrzejewski-Szmek <zbyszek@amutable.com>
Wed, 13 May 2026 21:02:48 +0000 (23:02 +0200)
committerZbigniew Jędrzejewski-Szmek <zbyszek@amutable.com>
Thu, 14 May 2026 07:15:48 +0000 (09:15 +0200)
Co-developed-by: Claude Opus 4.7 <noreply@anthropic.com>
src/systemctl/systemctl-compat-shutdown.c

index cfc917073ae0e70a05fc3865eb5e262e035c2368..f4dbd80473aada4998118c7f22cb013caa05b18f 100644 (file)
@@ -1,11 +1,11 @@
 /* SPDX-License-Identifier: LGPL-2.1-or-later */
 
-#include <getopt.h>
-
-#include "alloc-util.h"
+#include "ansi-color.h"
+#include "format-table.h"
+#include "help-util.h"
 #include "log.h"
+#include "options.h"
 #include "parse-util.h"
-#include "pretty-print.h"
 #include "reboot-util.h"
 #include "string-util.h"
 #include "strv.h"
 #include "time-util.h"
 
 static int shutdown_help(void) {
-        _cleanup_free_ char *link = NULL;
+        _cleanup_(table_unrefp) Table *options = NULL;
         int r;
 
-        r = terminal_urlify_man("shutdown", "8", &link);
+        r = option_parser_get_help_table_ns("shutdown", &options);
         if (r < 0)
-                return log_oom();
+                return r;
 
         /* Note: if you are tempted to add new command line switches here, please do not. Let this
          * compatibility command rest in peace. Its interface is not even owned by us as much as it is by
          * sysvinit. If you add something new, add it to "systemctl halt", "systemctl reboot", "systemctl
          * poweroff" instead. */
 
-        printf("%s [OPTIONS...] [TIME] [WALL...]\n"
-               "\n%sShut down the system.%s\n"
-               "\nOptions:\n"
-               "     --help      Show this help\n"
-               "  -H --halt      Halt the machine\n"
-               "  -P --poweroff  Power-off the machine\n"
-               "  -r --reboot    Reboot the machine\n"
-               "  -h             Equivalent to --poweroff, overridden by --halt\n"
-               "  -k             Don't halt/power-off/reboot, just send warnings\n"
-               "     --no-wall   Don't send wall message before halt/power-off/reboot\n"
-               "  -c             Cancel a pending shutdown\n"
-               "     --show      Show pending shutdown\n"
-               "\n%sThis is a compatibility interface, please use the more powerful 'systemctl halt',\n"
-               "'systemctl poweroff', 'systemctl reboot' commands instead.%s\n"
-               "\nSee the %s for details.\n",
-               program_invocation_short_name,
-               ansi_highlight(), ansi_normal(),
-               ansi_highlight_red(), ansi_normal(),
-               link);
+        help_cmdline("[OPTIONS…] [TIME] [WALL…]");
+        help_abstract("Shut down the system.");
+
+        help_section("Options");
+        r = table_print_or_warn(options);
+        if (r < 0)
+                return r;
+
+        printf("\n%sThis is a compatibility interface, please use the more powerful 'systemctl halt',\n"
+               "'systemctl poweroff', 'systemctl reboot' commands instead.%s\n",
+               ansi_highlight_red(), ansi_normal());
 
+        help_man_page_reference("shutdown", "8");
         return 0;
 }
 
@@ -124,104 +117,86 @@ static int parse_shutdown_time_spec(const char *t, usec_t *ret) {
 }
 
 int shutdown_parse_argv(int argc, char *argv[]) {
-        enum {
-                ARG_HELP = 0x100,
-                ARG_NO_WALL,
-                ARG_SHOW
-        };
-
-        static const struct option options[] = {
-                { "help",      no_argument,       NULL, ARG_HELP    },
-                { "halt",      no_argument,       NULL, 'H'         },
-                { "poweroff",  no_argument,       NULL, 'P'         },
-                { "reboot",    no_argument,       NULL, 'r'         },
-                { "kexec",     no_argument,       NULL, 'K'         }, /* not documented extension */
-                { "no-wall",   no_argument,       NULL, ARG_NO_WALL },
-                { "show",      no_argument,       NULL, ARG_SHOW    },
-                {}
-        };
-
-        char **wall = NULL;
-        int c, r;
+        int r;
 
         assert(argc >= 0);
         assert(argv);
 
-        while ((c = getopt_long(argc, argv, "HPrhkKat:fFc", options, NULL)) >= 0)
+        OptionParser opts = { argc, argv, .namespace = "shutdown" };
+
+        FOREACH_OPTION_OR_RETURN(c, &opts)
                 switch (c) {
 
-                case ARG_HELP:
+                OPTION_NAMESPACE("shutdown"): {}
+
+                OPTION_LONG("help", NULL, "Show this help"):
                         return shutdown_help();
 
-                case 'H':
+                OPTION('H', "halt", NULL, "Halt the machine"):
                         arg_action = ACTION_HALT;
                         break;
 
-                case 'P':
+                OPTION('P', "poweroff", NULL, "Power-off the machine"):
                         arg_action = ACTION_POWEROFF;
                         break;
 
-                case 'r':
+                OPTION('r', "reboot", NULL, "Reboot the machine"):
                         if (kexec_loaded())
                                 arg_action = ACTION_KEXEC;
                         else
                                 arg_action = ACTION_REBOOT;
                         break;
 
-                case 'K':
-                        arg_action = ACTION_KEXEC;
-                        break;
-
-                case 'h':
+                OPTION_SHORT('h', NULL, "Equivalent to --poweroff, overridden by --halt"):
                         if (arg_action != ACTION_HALT)
                                 arg_action = ACTION_POWEROFF;
                         break;
 
-                case 'k':
+                OPTION_SHORT('k', NULL, "Don't halt/power-off/reboot, just send warnings"):
                         arg_dry_run = true;
                         break;
 
-                case ARG_NO_WALL:
+                OPTION_LONG("no-wall", NULL, "Don't send wall message before halt/power-off/reboot"):
                         arg_no_wall = true;
                         break;
 
-                case 'a':
-                case 't': /* Note that we also ignore any passed argument to -t, not just the -t itself */
-                case 'f':
-                case 'F':
-                        /* Compatibility nops */
-                        break;
-
-                case 'c':
+                OPTION_SHORT('c', NULL, "Cancel a pending shutdown"):
                         arg_action = ACTION_CANCEL_SHUTDOWN;
                         break;
 
-                case ARG_SHOW:
+                OPTION_LONG("show", NULL, "Show pending shutdown"):
                         arg_action = ACTION_SHOW_SHUTDOWN;
                         break;
 
-                case '?':
-                        return -EINVAL;
+                /* Hidden compat options. */
+                OPTION('K', "kexec", NULL, /* help= */ NULL):
+                        arg_action = ACTION_KEXEC;
+                        break;
 
-                default:
-                        assert_not_reached();
+                OPTION_SHORT('a', NULL,  /* help= */ NULL): {}   /* compatibility noops */
+                OPTION_SHORT('f', NULL,  /* help= */ NULL): {}
+                OPTION_SHORT('F', NULL,  /* help= */ NULL): {}
+                OPTION_SHORT('t', "ARG", /* help= */ NULL):
+                        break;
                 }
 
-        if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) {
-                r = parse_shutdown_time_spec(argv[optind], &arg_when);
-                if (r < 0) {
-                        log_error("Failed to parse time specification: %s", argv[optind]);
-                        return r;
-                }
+        char **args = option_parser_get_args(&opts);
+        size_t n_args = option_parser_get_n_args(&opts);
+
+        if (n_args > 0 && arg_action != ACTION_CANCEL_SHUTDOWN) {
+                r = parse_shutdown_time_spec(args[0], &arg_when);
+                if (r < 0)
+                        return log_error_errno(r, "Failed to parse time specification: %s", args[0]);
         } else
                 arg_when = USEC_INFINITY; /* logind chooses on server side */
 
-        if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN)
+        char **wall = NULL;
+        if (n_args > 0 && arg_action == ACTION_CANCEL_SHUTDOWN)
                 /* No time argument for shutdown cancel */
-                wall = argv + optind;
-        else if (argc > optind + 1)
+                wall = args;
+        else if (n_args > 1)
                 /* We skip the time argument */
-                wall = argv + optind + 1;
+                wall = args + 1;
 
         if (wall) {
                 char **copy = strv_copy(wall);
@@ -230,7 +205,5 @@ int shutdown_parse_argv(int argc, char *argv[]) {
                 strv_free_and_replace(arg_wall, copy);
         }
 
-        optind = argc;
-
         return 1;
 }