]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
systemctl: split out some SysV compat stuff into its own C file
authorLennart Poettering <lennart@poettering.net>
Fri, 22 Mar 2019 19:05:08 +0000 (20:05 +0100)
committerLennart Poettering <lennart@poettering.net>
Mon, 25 Mar 2019 14:23:08 +0000 (15:23 +0100)
systemctl.c is way to large already. Let's split out some stuff out that
is easy to split out.

meson.build
src/systemctl/systemctl.c
src/systemctl/sysv-compat.c [new file with mode: 0644]
src/systemctl/sysv-compat.h [new file with mode: 0644]

index d242888f37f0368d034eb20c89de9900e460dc93..20bcb9d8b1af04645369c1c7df303aa115e31089 100644 (file)
@@ -1950,7 +1950,10 @@ else
                                libbasic_gcrypt]
 endif
 
-exe = executable('systemctl', 'src/systemctl/systemctl.c',
+exe = executable('systemctl',
+                 'src/systemctl/systemctl.c',
+                 'src/systemctl/sysv-compat.h',
+                 'src/systemctl/sysv-compat.c',
                  include_directories : includes,
                  link_with : systemctl_link_with,
                  dependencies : [threads,
index 948dacd1900963cc4650ea4daf675b4d3371038a..b948ebe8cae7f242b57100ca9f38704dfcb9dce2 100644 (file)
@@ -75,6 +75,7 @@
 #include "stat-util.h"
 #include "string-table.h"
 #include "strv.h"
+#include "sysv-compat.h"
 #include "terminal-util.h"
 #include "tmpfile-util.h"
 #include "unit-def.h"
 #include "verbs.h"
 #include "virt.h"
 
-/* The init script exit status codes
-   0       program is running or service is OK
-   1       program is dead and /var/run pid file exists
-   2       program is dead and /var/lock lock file exists
-   3       program is not running
-   4       program or service status is unknown
-   5-99    reserved for future LSB use
-   100-149 reserved for distribution use
-   150-199 reserved for application use
-   200-254 reserved
-*/
-enum {
-        EXIT_PROGRAM_RUNNING_OR_SERVICE_OK        = 0,
-        EXIT_PROGRAM_DEAD_AND_PID_EXISTS          = 1,
-        EXIT_PROGRAM_DEAD_AND_LOCK_FILE_EXISTS    = 2,
-        EXIT_PROGRAM_NOT_RUNNING                  = 3,
-        EXIT_PROGRAM_OR_SERVICES_STATUS_UNKNOWN   = 4,
-};
-
 static char **arg_types = NULL;
 static char **arg_states = NULL;
 static char **arg_properties = NULL;
@@ -8465,56 +8447,6 @@ static int halt_parse_argv(int argc, char *argv[]) {
         return 1;
 }
 
-static int parse_shutdown_time_spec(const char *t, usec_t *_u) {
-        assert(t);
-        assert(_u);
-
-        if (streq(t, "now"))
-                *_u = 0;
-        else if (!strchr(t, ':')) {
-                uint64_t u;
-
-                if (safe_atou64(t, &u) < 0)
-                        return -EINVAL;
-
-                *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
-        } else {
-                char *e = NULL;
-                long hour, minute;
-                struct tm tm = {};
-                time_t s;
-                usec_t n;
-
-                errno = 0;
-                hour = strtol(t, &e, 10);
-                if (errno > 0 || *e != ':' || hour < 0 || hour > 23)
-                        return -EINVAL;
-
-                minute = strtol(e+1, &e, 10);
-                if (errno > 0 || *e != 0 || minute < 0 || minute > 59)
-                        return -EINVAL;
-
-                n = now(CLOCK_REALTIME);
-                s = (time_t) (n / USEC_PER_SEC);
-
-                assert_se(localtime_r(&s, &tm));
-
-                tm.tm_hour = (int) hour;
-                tm.tm_min = (int) minute;
-                tm.tm_sec = 0;
-
-                s = mktime(&tm);
-                assert(s >= 0);
-
-                *_u = (usec_t) s * USEC_PER_SEC;
-
-                while (*_u <= n)
-                        *_u += USEC_PER_DAY;
-        }
-
-        return 0;
-}
-
 static int shutdown_parse_argv(int argc, char *argv[]) {
         enum {
                 ARG_HELP = 0x100,
@@ -8820,47 +8752,6 @@ _pure_ static int action_to_runlevel(void) {
 }
 #endif
 
-static int talk_initctl(void) {
-#if HAVE_SYSV_COMPAT
-        struct init_request request = {
-                .magic = INIT_MAGIC,
-                .sleeptime  = 0,
-                .cmd = INIT_CMD_RUNLVL
-        };
-
-        _cleanup_close_ int fd = -1;
-        char rl;
-        int r;
-        const char *p;
-
-        rl = action_to_runlevel();
-        if (!rl)
-                return 0;
-
-        request.runlevel = rl;
-
-        FOREACH_STRING(p, "/run/initctl", "/dev/initctl") {
-                fd = open(p, O_WRONLY|O_NONBLOCK|O_CLOEXEC|O_NOCTTY);
-                if (fd >= 0 || errno != ENOENT)
-                        break;
-        }
-        if (fd < 0) {
-                if (errno == ENOENT)
-                        return 0;
-
-                return log_error_errno(errno, "Failed to open initctl fifo: %m");
-        }
-
-        r = loop_write(fd, &request, sizeof(request), false);
-        if (r < 0)
-                return log_error_errno(r, "Failed to write to %s: %m", p);
-
-        return 1;
-#else
-        return 0;
-#endif
-}
-
 static int systemctl_main(int argc, char *argv[]) {
         static const Verb verbs[] = {
                 { "list-units",            VERB_ANY, VERB_ANY, VERB_DEFAULT|VERB_ONLINE_ONLY, list_units },
@@ -8956,7 +8847,7 @@ static int start_with_fallback(void) {
                 return 0;
 
         /* Nothing else worked, so let's try /dev/initctl */
-        if (talk_initctl() > 0)
+        if (talk_initctl(action_to_runlevel()) > 0)
                 return 0;
 
         return log_error_errno(SYNTHETIC_ERRNO(EIO),
diff --git a/src/systemctl/sysv-compat.c b/src/systemctl/sysv-compat.c
new file mode 100644 (file)
index 0000000..72a2f57
--- /dev/null
@@ -0,0 +1,100 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include "fd-util.h"
+#include "initreq.h"
+#include "io-util.h"
+#include "parse-util.h"
+#include "strv.h"
+#include "sysv-compat.h"
+
+int talk_initctl(char rl) {
+#if HAVE_SYSV_COMPAT
+        struct init_request request;
+        _cleanup_close_ int fd = -1;
+        const char *p;
+        int r;
+
+        /* Try to switch to the specified SysV runlevel. Returns == 0 if the operation does not apply on this
+         * system, and > 0 on success. */
+
+        if (rl == 0)
+                return 0;
+
+        FOREACH_STRING(p, "/run/initctl", "/dev/initctl") {
+                fd = open(p, O_WRONLY|O_NONBLOCK|O_CLOEXEC|O_NOCTTY);
+                if (fd >= 0 || errno != ENOENT)
+                        break;
+        }
+        if (fd < 0) {
+                if (errno == ENOENT)
+                        return 0;
+
+                return log_error_errno(errno, "Failed to open initctl fifo: %m");
+        }
+
+        request = (struct init_request) {
+                .magic = INIT_MAGIC,
+                .sleeptime = 0,
+                .cmd = INIT_CMD_RUNLVL,
+                .runlevel = rl,
+        };
+
+        r = loop_write(fd, &request, sizeof(request), false);
+        if (r < 0)
+                return log_error_errno(r, "Failed to write to %s: %m", p);
+
+        return 1;
+#else
+        return 0;
+#endif
+}
+
+int parse_shutdown_time_spec(const char *t, usec_t *ret) {
+        assert(t);
+        assert(ret);
+
+        if (streq(t, "now"))
+                *ret = 0;
+        else if (!strchr(t, ':')) {
+                uint64_t u;
+
+                if (safe_atou64(t, &u) < 0)
+                        return -EINVAL;
+
+                *ret = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
+        } else {
+                char *e = NULL;
+                long hour, minute;
+                struct tm tm = {};
+                time_t s;
+                usec_t n;
+
+                errno = 0;
+                hour = strtol(t, &e, 10);
+                if (errno > 0 || *e != ':' || hour < 0 || hour > 23)
+                        return -EINVAL;
+
+                minute = strtol(e+1, &e, 10);
+                if (errno > 0 || *e != 0 || minute < 0 || minute > 59)
+                        return -EINVAL;
+
+                n = now(CLOCK_REALTIME);
+                s = (time_t) (n / USEC_PER_SEC);
+
+                assert_se(localtime_r(&s, &tm));
+
+                tm.tm_hour = (int) hour;
+                tm.tm_min = (int) minute;
+                tm.tm_sec = 0;
+
+                s = mktime(&tm);
+                assert(s >= 0);
+
+                *ret = (usec_t) s * USEC_PER_SEC;
+
+                while (*ret <= n)
+                        *ret += USEC_PER_DAY;
+        }
+
+        return 0;
+}
diff --git a/src/systemctl/sysv-compat.h b/src/systemctl/sysv-compat.h
new file mode 100644 (file)
index 0000000..73329ec
--- /dev/null
@@ -0,0 +1,30 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+#include "time-util.h"
+
+int talk_initctl(char runlevel);
+int parse_shutdown_time_spec(const char *t, usec_t *ret);
+
+/* The init script exit codes for the LSB 'status' verb. (This is different from the 'start' verb, whose exit
+   codes are defined in exit-status.h.)
+
+   0       program is running or service is OK
+   1       program is dead and /var/run pid file exists
+   2       program is dead and /var/lock lock file exists
+   3       program is not running
+   4       program or service status is unknown
+   5-99    reserved for future LSB use
+   100-149 reserved for distribution use
+   150-199 reserved for application use
+   200-254 reserved
+
+   https://refspecs.linuxbase.org/LSB_5.0.0/LSB-Core-generic/LSB-Core-generic/iniscrptact.html
+*/
+enum {
+        EXIT_PROGRAM_RUNNING_OR_SERVICE_OK        = 0,
+        EXIT_PROGRAM_DEAD_AND_PID_EXISTS          = 1,
+        EXIT_PROGRAM_DEAD_AND_LOCK_FILE_EXISTS    = 2,
+        EXIT_PROGRAM_NOT_RUNNING                  = 3,
+        EXIT_PROGRAM_OR_SERVICES_STATUS_UNKNOWN   = 4,
+};