]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
hibernate-resume: add options handling
authorMike Yuan <me@yhndnzj.com>
Sun, 31 Mar 2024 11:47:34 +0000 (19:47 +0800)
committerMike Yuan <me@yhndnzj.com>
Wed, 3 Apr 2024 13:59:59 +0000 (21:59 +0800)
src/hibernate-resume/hibernate-resume.c

index 27411faa7f44a0f24b0866f8c747850eec8335fa..cd92d8bdf199d3899158692e23ef7f186acce154 100644 (file)
@@ -1,8 +1,10 @@
 /* SPDX-License-Identifier: LGPL-2.1-or-later */
 
 #include <errno.h>
+#include <getopt.h>
 #include <sys/stat.h>
 
+#include "build.h"
 #include "devnum-util.h"
 #include "hibernate-resume-config.h"
 #include "hibernate-util.h"
 #include "log.h"
 #include "main-func.h"
 #include "parse-util.h"
+#include "pretty-print.h"
 #include "static-destruct.h"
+#include "terminal-util.h"
 
 static HibernateInfo arg_info = {};
 
 STATIC_DESTRUCTOR_REGISTER(arg_info, hibernate_info_done);
 
+static int help(void) {
+        _cleanup_free_ char *link = NULL;
+        int r;
+
+        r = terminal_urlify_man("systemd-hibernate-resume", "8", &link);
+        if (r < 0)
+                return log_oom();
+
+        printf("%s [OPTIONS...] [DEVICE [OFFSET]]\n"
+               "\n%sInitiate resume from hibernation.%s\n\n"
+               "  -h --help            Show this help\n"
+               "     --version         Show package version\n"
+               "\nSee the %s for details.\n",
+               program_invocation_short_name,
+               ansi_highlight(),
+               ansi_normal(),
+               link);
+
+        return 0;
+}
+
+static int parse_argv(int argc, char *argv[]) {
+
+        enum {
+                ARG_VERSION = 0x100,
+        };
+
+        static const struct option options[] = {
+                { "help",      no_argument,       NULL, 'h'           },
+                { "version",   no_argument,       NULL, ARG_VERSION   },
+                {}
+        };
+
+        int c;
+
+        assert(argc >= 0);
+        assert(argv);
+
+        while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
+
+                switch (c) {
+
+                case 'h':
+                        return help();
+
+                case ARG_VERSION:
+                        return version();
+
+                case '?':
+                        return -EINVAL;
+
+                default:
+                        assert_not_reached();
+                }
+
+        return 1;
+}
+
 static int setup_hibernate_info_and_warn(void) {
         int r;
 
@@ -38,7 +100,11 @@ static int run(int argc, char *argv[]) {
 
         log_setup();
 
-        if (argc < 1 || argc > 3)
+        r = parse_argv(argc, argv);
+        if (r <= 0)
+                return r;
+
+        if (argc - optind > 2)
                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "This program expects zero, one, or two arguments.");
 
         umask(0022);
@@ -46,21 +112,21 @@ static int run(int argc, char *argv[]) {
         if (!in_initrd())
                 return 0;
 
-        if (argc > 1) {
-                arg_info.device = argv[1];
-
-                if (argc == 3) {
-                        r = safe_atou64(argv[2], &arg_info.offset);
-                        if (r < 0)
-                                return log_error_errno(r, "Failed to parse resume offset %s: %m", argv[2]);
-                }
-        } else {
+        if (argc <= optind) {
                 r = setup_hibernate_info_and_warn();
                 if (r <= 0)
                         return r;
 
                 if (arg_info.efi)
                         (void) clear_efi_hibernate_location_and_warn();
+        } else {
+                arg_info.device = ASSERT_PTR(argv[optind]);
+
+                if (argc - optind == 2) {
+                        r = safe_atou64(argv[optind + 1], &arg_info.offset);
+                        if (r < 0)
+                                return log_error_errno(r, "Failed to parse resume offset %s: %m", argv[optind + 1]);
+                }
         }
 
         if (stat(arg_info.device, &st) < 0)