]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/systemctl/systemctl.c
Add SPDX license identifiers to source files under the LGPL
[thirdparty/systemd.git] / src / systemctl / systemctl.c
index 897fc48b9895e06242fc01378aa645f2daf93c2a..930fd3ac772d234f4e716df870b2c8915d596bc0 100644 (file)
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
 /***
   This file is part of systemd.
 
@@ -216,6 +217,12 @@ static int acquire_bus(BusFocus focus, sd_bus **ret) {
 
                 user = arg_scope != UNIT_FILE_SYSTEM;
 
+                if (!user && sd_booted() <= 0) {
+                        /* Print a friendly message when the local system is actually not running systemd as PID 1. */
+                        log_error("System has not been booted with systemd as init system (PID 1). Can't operate.");
+                        return -EHOSTDOWN;
+                }
+
                 if (focus == BUS_MANAGER)
                         r = bus_connect_transport_systemd(arg_transport, arg_host, user, &busses[focus]);
                 else
@@ -268,27 +275,19 @@ static void ask_password_agent_open_if_enabled(void) {
         ask_password_agent_open();
 }
 
-static void polkit_agent_open_if_enabled(void) {
-
+static void polkit_agent_open_maybe(void) {
         /* Open the polkit agent as a child process if necessary */
 
-        if (!arg_ask_password)
-                return;
-
         if (arg_scope != UNIT_FILE_SYSTEM)
                 return;
 
-        if (arg_transport != BUS_TRANSPORT_LOCAL)
-                return;
-
-        polkit_agent_open();
+        polkit_agent_open_if_enabled(arg_transport, arg_ask_password);
 }
 
 static OutputFlags get_output_flags(void) {
         return
                 arg_all * OUTPUT_SHOW_ALL |
-                arg_full * OUTPUT_FULL_WIDTH |
-                (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
+                (arg_full || !on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
                 colors_enabled() * OUTPUT_COLOR |
                 !arg_quiet * OUTPUT_WARN_CUTOFF;
 }
@@ -2163,7 +2162,7 @@ static int set_default(int argc, char *argv[], void *userdata) {
                 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
                 sd_bus *bus;
 
-                polkit_agent_open_if_enabled();
+                polkit_agent_open_maybe();
 
                 r = acquire_bus(BUS_MANAGER, &bus);
                 if (r < 0)
@@ -2391,7 +2390,7 @@ static int cancel_job(int argc, char *argv[], void *userdata) {
         if (r < 0)
                 return r;
 
-        polkit_agent_open_if_enabled();
+        polkit_agent_open_maybe();
 
         STRV_FOREACH(name, strv_skip(argv, 1)) {
                 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
@@ -3099,7 +3098,7 @@ static int start_unit(int argc, char *argv[], void *userdata) {
                 return r;
 
         ask_password_agent_open_if_enabled();
-        polkit_agent_open_if_enabled();
+        polkit_agent_open_maybe();
 
         if (arg_action == ACTION_SYSTEMCTL) {
                 enum action action;
@@ -3219,7 +3218,7 @@ static int start_unit(int argc, char *argv[], void *userdata) {
         return r;
 }
 
-#ifdef ENABLE_LOGIND
+#if ENABLE_LOGIND
 static int logind_set_wall_message(void) {
         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         sd_bus *bus;
@@ -3255,7 +3254,7 @@ static int logind_set_wall_message(void) {
 /* Ask systemd-logind, which might grant access to unprivileged users
  * through PolicyKit */
 static int logind_reboot(enum action a) {
-#ifdef ENABLE_LOGIND
+#if ENABLE_LOGIND
         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         const char *method, *description;
         sd_bus *bus;
@@ -3267,14 +3266,19 @@ static int logind_reboot(enum action a) {
 
         switch (a) {
 
+        case ACTION_POWEROFF:
+                method = "PowerOff";
+                description = "power off system";
+                break;
+
         case ACTION_REBOOT:
                 method = "Reboot";
                 description = "reboot system";
                 break;
 
-        case ACTION_POWEROFF:
-                method = "PowerOff";
-                description = "power off system";
+        case ACTION_HALT:
+                method = "Halt";
+                description = "halt system";
                 break;
 
         case ACTION_SUSPEND:
@@ -3296,7 +3300,7 @@ static int logind_reboot(enum action a) {
                 return -EINVAL;
         }
 
-        polkit_agent_open_if_enabled();
+        polkit_agent_open_maybe();
         (void) logind_set_wall_message();
 
         r = sd_bus_call_method(
@@ -3318,7 +3322,7 @@ static int logind_reboot(enum action a) {
 }
 
 static int logind_check_inhibitors(enum action a) {
-#ifdef ENABLE_LOGIND
+#if ENABLE_LOGIND
         _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
         _cleanup_strv_free_ char **sessions = NULL;
         const char *what, *who, *why, *mode;
@@ -3376,7 +3380,7 @@ static int logind_check_inhibitors(enum action a) {
                         return log_oom();
 
                 if (!pid_is_valid((pid_t) pid)) {
-                        log_error("Invalid PID %" PRIu32 ".", pid);
+                        log_error("Invalid PID "PID_FMT".", (pid_t) pid);
                         return -ERANGE;
                 }
 
@@ -3414,7 +3418,7 @@ static int logind_check_inhibitors(enum action a) {
                 if (sd_session_get_class(*s, &class) < 0 || !streq(class, "user"))
                         continue;
 
-                if (sd_session_get_type(*s, &type) < 0 || !STR_IN_SET(type, "x11", "tty"))
+                if (sd_session_get_type(*s, &type) < 0 || !STR_IN_SET(type, "x11", "wayland", "tty", "mir"))
                         continue;
 
                 sd_session_get_tty(*s, &tty);
@@ -3439,7 +3443,7 @@ static int logind_check_inhibitors(enum action a) {
 }
 
 static int logind_prepare_firmware_setup(void) {
-#ifdef ENABLE_LOGIND
+#if ENABLE_LOGIND
         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         sd_bus *bus;
         int r;
@@ -3568,6 +3572,7 @@ static int start_special(int argc, char *argv[], void *userdata) {
                 if (IN_SET(a,
                            ACTION_POWEROFF,
                            ACTION_REBOOT,
+                           ACTION_HALT,
                            ACTION_SUSPEND,
                            ACTION_HIBERNATE,
                            ACTION_HYBRID_SLEEP)) {
@@ -3579,8 +3584,16 @@ static int start_special(int argc, char *argv[], void *userdata) {
                                 /* requested operation is not supported or already in progress */
                                 return r;
 
-                        /* On all other errors, try low-level operation */
-                }
+                        /* On all other errors, try low-level operation. In order to minimize the difference between
+                         * operation with and without logind, we explicitly enable non-blocking mode for this, as
+                         * logind's shutdown operations are always non-blocking. */
+
+                        arg_no_block = true;
+
+                } else if (IN_SET(a, ACTION_EXIT, ACTION_KEXEC))
+                        /* Since exit/kexec are so close in behaviour to power-off/reboot, let's also make them
+                         * asynchronous, in order to not confuse the user needlessly with unexpected behaviour. */
+                        arg_no_block = true;
 
                 r = start_unit(argc, argv, userdata);
         }
@@ -3659,7 +3672,7 @@ static int kill_unit(int argc, char *argv[], void *userdata) {
         if (r < 0)
                 return r;
 
-        polkit_agent_open_if_enabled();
+        polkit_agent_open_maybe();
 
         if (!arg_kill_who)
                 arg_kill_who = "all";
@@ -5225,11 +5238,13 @@ static int show_system_status(sd_bus *bus) {
         if (streq_ptr(mi.state, "degraded")) {
                 on = ansi_highlight_red();
                 off = ansi_normal();
-        } else if (!streq_ptr(mi.state, "running")) {
+        } else if (streq_ptr(mi.state, "running")) {
+                on = ansi_highlight_green();
+                off = ansi_normal();
+        } else {
                 on = ansi_highlight_yellow();
                 off = ansi_normal();
-        } else
-                on = off = "";
+        }
 
         printf("%s%s%s %s\n", on, special_glyph(BLACK_CIRCLE), off, arg_host ? arg_host : hn);
 
@@ -5470,7 +5485,7 @@ static int set_property(int argc, char *argv[], void *userdata) {
         if (r < 0)
                 return r;
 
-        polkit_agent_open_if_enabled();
+        polkit_agent_open_maybe();
 
         r = sd_bus_message_new_method_call(
                         bus,
@@ -5520,7 +5535,7 @@ static int daemon_reload(int argc, char *argv[], void *userdata) {
         if (r < 0)
                 return r;
 
-        polkit_agent_open_if_enabled();
+        polkit_agent_open_maybe();
 
         switch (arg_action) {
 
@@ -5580,7 +5595,7 @@ static int trivial_method(int argc, char *argv[], void *userdata) {
         if (r < 0)
                 return r;
 
-        polkit_agent_open_if_enabled();
+        polkit_agent_open_maybe();
 
         method =
                 streq(argv[0], "clear-jobs")    ||
@@ -5623,7 +5638,7 @@ static int reset_failed(int argc, char *argv[], void *userdata) {
         if (r < 0)
                 return r;
 
-        polkit_agent_open_if_enabled();
+        polkit_agent_open_maybe();
 
         r = expand_names(bus, strv_skip(argv, 1), NULL, &names);
         if (r < 0)
@@ -5808,7 +5823,7 @@ static int set_environment(int argc, char *argv[], void *userdata) {
         if (r < 0)
                 return r;
 
-        polkit_agent_open_if_enabled();
+        polkit_agent_open_maybe();
 
         method = streq(argv[0], "set-environment")
                 ? "SetEnvironment"
@@ -5845,7 +5860,7 @@ static int import_environment(int argc, char *argv[], void *userdata) {
         if (r < 0)
                 return r;
 
-        polkit_agent_open_if_enabled();
+        polkit_agent_open_maybe();
 
         r = sd_bus_message_new_method_call(
                         bus,
@@ -5903,7 +5918,7 @@ static int import_environment(int argc, char *argv[], void *userdata) {
 static int enable_sysv_units(const char *verb, char **args) {
         int r = 0;
 
-#if defined(HAVE_SYSV_COMPAT)
+#if HAVE_SYSV_COMPAT
         _cleanup_lookup_paths_free_ LookupPaths paths = {};
         unsigned f = 0;
 
@@ -6270,7 +6285,7 @@ static int enable_unit(int argc, char *argv[], void *userdata) {
                 if (r < 0)
                         return r;
 
-                polkit_agent_open_if_enabled();
+                polkit_agent_open_maybe();
 
                 if (streq(verb, "enable")) {
                         method = "EnableUnitFiles";
@@ -6440,7 +6455,7 @@ static int add_dependency(int argc, char *argv[], void *userdata) {
                 if (r < 0)
                         return r;
 
-                polkit_agent_open_if_enabled();
+                polkit_agent_open_maybe();
 
                 r = sd_bus_message_new_method_call(
                                 bus,
@@ -6502,7 +6517,7 @@ static int preset_all(int argc, char *argv[], void *userdata) {
                 if (r < 0)
                         return r;
 
-                polkit_agent_open_if_enabled();
+                polkit_agent_open_maybe();
 
                 r = sd_bus_call_method(
                                 bus,
@@ -7139,12 +7154,14 @@ static void systemctl_help(void) {
                "     --no-pager       Do not pipe output into a pager\n"
                "     --no-ask-password\n"
                "                      Do not ask for system passwords\n"
-               "     --global         Enable/disable unit files globally\n"
-               "     --runtime        Enable unit files only temporarily until next reboot\n"
+               "     --global         Enable/disable/mask unit files globally\n"
+               "     --runtime        Enable/disable/mask unit files temporarily until next\n"
+               "                      reboot\n"
                "  -f --force          When enabling unit files, override existing symlinks\n"
                "                      When shutting down, execute action immediately\n"
                "     --preset-mode=   Apply only enable, only disable, or all presets\n"
-               "     --root=PATH      Enable unit files in the specified root directory\n"
+               "     --root=PATH      Enable/disable/mask unit files in the specified root\n"
+               "                      directory\n"
                "  -n --lines=INTEGER  Number of journal entries to show\n"
                "  -o --output=STRING  Change journal output mode (short, short-precise,\n"
                "                             short-iso, short-iso-precise, short-full,\n"
@@ -7815,7 +7832,7 @@ static int halt_parse_argv(int argc, char *argv[]) {
         assert(argv);
 
         if (utmp_get_runlevel(&runlevel, NULL) >= 0)
-                if (runlevel == '0' || runlevel == '6')
+                if (IN_SET(runlevel, '0', '6'))
                         arg_force = 2;
 
         while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0)
@@ -8211,7 +8228,7 @@ static int parse_argv(int argc, char *argv[]) {
         return systemctl_parse_argv(argc, argv);
 }
 
-#ifdef HAVE_SYSV_COMPAT
+#if HAVE_SYSV_COMPAT
 _pure_ static int action_to_runlevel(void) {
 
         static const char table[_ACTION_MAX] = {
@@ -8232,7 +8249,7 @@ _pure_ static int action_to_runlevel(void) {
 #endif
 
 static int talk_initctl(void) {
-#ifdef HAVE_SYSV_COMPAT
+#if HAVE_SYSV_COMPAT
         struct init_request request = {
                 .magic = INIT_MAGIC,
                 .sleeptime  = 0,
@@ -8426,7 +8443,7 @@ static int halt_now(enum action a) {
 
 static int logind_schedule_shutdown(void) {
 
-#ifdef ENABLE_LOGIND
+#if ENABLE_LOGIND
         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         char date[FORMAT_TIMESTAMP_MAX];
         const char *action;
@@ -8503,7 +8520,7 @@ static int halt_main(void) {
                 /* Try logind if we are a normal user and no special
                  * mode applies. Maybe PolicyKit allows us to shutdown
                  * the machine. */
-                if (IN_SET(arg_action, ACTION_POWEROFF, ACTION_REBOOT)) {
+                if (IN_SET(arg_action, ACTION_POWEROFF, ACTION_REBOOT, ACTION_HALT)) {
                         r = logind_reboot(arg_action);
                         if (r >= 0)
                                 return r;
@@ -8555,7 +8572,7 @@ static int runlevel_main(void) {
 }
 
 static int logind_cancel_shutdown(void) {
-#ifdef ENABLE_LOGIND
+#if ENABLE_LOGIND
         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         sd_bus *bus;
         int r;