]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/systemctl/systemctl.c
shared: add process-util.[ch]
[thirdparty/systemd.git] / src / systemctl / systemctl.c
index 4e90f68622069fa211a0efc74a4a1ea118437e56..04b7e7bbda00ece4db9b06c8cd717fbfd4da1182 100644 (file)
@@ -68,6 +68,9 @@
 #include "bus-common-errors.h"
 #include "mkdir.h"
 #include "dropin.h"
+#include "efivars.h"
+#include "formats-util.h"
+#include "process-util.h"
 
 static char **arg_types = NULL;
 static char **arg_states = NULL;
@@ -132,6 +135,7 @@ static char *arg_host = NULL;
 static unsigned arg_lines = 10;
 static OutputMode arg_output = OUTPUT_SHORT;
 static bool arg_plain = false;
+static bool arg_firmware_setup = false;
 
 static bool original_stdout_is_tty;
 
@@ -2618,7 +2622,7 @@ static int expand_names(sd_bus *bus, char **names, const char* suffix, char ***r
                 _cleanup_free_ UnitInfo *unit_infos = NULL;
 
                 if (!bus)
-                        return log_error_errno(ENOTSUP, "Unit name globbing without bus is not implemented.");
+                        return log_error_errno(EOPNOTSUPP, "Unit name globbing without bus is not implemented.");
 
                 r = get_unit_list(bus, NULL, globs, &unit_infos, 0, &reply);
                 if (r < 0)
@@ -2851,6 +2855,9 @@ static int check_inhibitors(sd_bus *bus, enum action a) {
                 if (!sv)
                         return log_oom();
 
+                if ((pid_t) pid < 0)
+                        return log_error_errno(ERANGE, "Bad PID %"PRIu32": %m", pid);
+
                 if (!strv_contains(sv,
                                   a == ACTION_HALT ||
                                   a == ACTION_POWEROFF ||
@@ -2862,7 +2869,7 @@ static int check_inhibitors(sd_bus *bus, enum action a) {
                 user = uid_to_name(uid);
 
                 log_warning("Operation inhibited by \"%s\" (PID "PID_FMT" \"%s\", user %s), reason is \"%s\".",
-                            who, pid, strna(comm), strna(user), why);
+                            who, (pid_t) pid, strna(comm), strna(user), why);
 
                 c++;
         }
@@ -2908,6 +2915,46 @@ static int check_inhibitors(sd_bus *bus, enum action a) {
 #endif
 }
 
+static int prepare_firmware_setup(sd_bus *bus) {
+#ifdef HAVE_LOGIND
+        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+#endif
+        int r;
+
+        if (!arg_firmware_setup)
+                return 0;
+
+        if (arg_transport == BUS_TRANSPORT_LOCAL) {
+
+                r = efi_set_reboot_to_firmware(true);
+                if (r < 0)
+                        log_debug_errno(r, "Cannot indicate to EFI to boot into setup mode, will retry via logind: %m");
+                else
+                        return r;
+        }
+
+#ifdef HAVE_LOGIND
+        r = sd_bus_call_method(
+                        bus,
+                        "org.freedesktop.login1",
+                        "/org/freedesktop/login1",
+                        "org.freedesktop.login1.Manager",
+                        "SetRebootToFirmwareSetup",
+                        &error,
+                        NULL,
+                        "b", true);
+        if (r < 0) {
+                log_error("Cannot indicate to EFI to boot into setup mode: %s", bus_error_message(&error, r));
+                return r;
+        }
+
+        return 0;
+#else
+        log_error("Cannot remotely indicate to EFI to boot into setup mode.");
+        return -EINVAL;
+#endif
+}
+
 static int start_special(sd_bus *bus, char **args) {
         enum action a;
         int r;
@@ -2925,6 +2972,10 @@ static int start_special(sd_bus *bus, char **args) {
                 return -EPERM;
         }
 
+        r = prepare_firmware_setup(bus);
+        if (r < 0)
+                return r;
+
         if (a == ACTION_REBOOT && args[1]) {
                 r = update_reboot_param_file(args[1]);
                 if (r < 0)
@@ -2953,7 +3004,7 @@ static int start_special(sd_bus *bus, char **args) {
              a == ACTION_HIBERNATE ||
              a == ACTION_HYBRID_SLEEP)) {
                 r = reboot_with_logind(bus, a);
-                if (r >= 0 || IN_SET(r, -ENOTSUP, -EINPROGRESS))
+                if (r >= 0 || IN_SET(r, -EOPNOTSUPP, -EINPROGRESS))
                         return r;
         }
 
@@ -3192,6 +3243,7 @@ typedef struct UnitStatusInfo {
         /* CGroup */
         uint64_t memory_current;
         uint64_t memory_limit;
+        uint64_t cpu_usage_nsec;
 
         LIST_HEAD(ExecStatusInfo, exec);
 } UnitStatusInfo;
@@ -3462,6 +3514,11 @@ static void print_status_info(
                         printf("\n");
         }
 
+        if (i->cpu_usage_nsec != (uint64_t) -1) {
+                char buf[FORMAT_TIMESPAN_MAX];
+                printf("      CPU: %s\n", format_timespan(buf, sizeof(buf), i->cpu_usage_nsec / NSEC_PER_USEC, USEC_PER_MSEC));
+        }
+
         if (i->control_group &&
             (i->main_pid > 0 || i->control_pid > 0 ||
              ((arg_transport != BUS_TRANSPORT_LOCAL && arg_transport != BUS_TRANSPORT_MACHINE) || cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, i->control_group, false) == 0))) {
@@ -3680,6 +3737,8 @@ static int status_property(const char *name, sd_bus_message *m, UnitStatusInfo *
                         i->memory_current = u;
                 else if (streq(name, "MemoryLimit"))
                         i->memory_limit = u;
+                else if (streq(name, "CPUUsageNSec"))
+                        i->cpu_usage_nsec = u;
 
                 break;
         }
@@ -4153,6 +4212,7 @@ static int show_one(
         UnitStatusInfo info = {
                 .memory_current = (uint64_t) -1,
                 .memory_limit = (uint64_t) -1,
+                .cpu_usage_nsec = (uint64_t) -1,
         };
         ExecStatusInfo *p;
         int r;
@@ -4511,6 +4571,23 @@ static int init_home_and_lookup_paths(char **user_home, char **user_runtime, Loo
         return 0;
 }
 
+static int cat_file(const char *filename, bool newline) {
+        _cleanup_close_ int fd;
+
+        fd = open(filename, O_RDONLY|O_CLOEXEC|O_NOCTTY);
+        if (fd < 0)
+                return -errno;
+
+        printf("%s%s# %s%s\n",
+               newline ? "\n" : "",
+               ansi_highlight_blue(),
+               filename,
+               ansi_highlight_off());
+        fflush(stdout);
+
+        return copy_bytes(fd, STDOUT_FILENO, (off_t) -1, false);
+}
+
 static int cat(sd_bus *bus, char **args) {
         _cleanup_free_ char *user_home = NULL;
         _cleanup_free_ char *user_runtime = NULL;
@@ -4518,7 +4595,7 @@ static int cat(sd_bus *bus, char **args) {
         _cleanup_strv_free_ char **names = NULL;
         char **name;
         bool first = true, avoid_bus_cache;
-        int r = 0;
+        int r;
 
         assert(args);
 
@@ -4556,36 +4633,19 @@ static int cat(sd_bus *bus, char **args) {
                         puts("");
 
                 if (fragment_path) {
-                        printf("%s# %s%s\n",
-                               ansi_highlight_blue(),
-                               fragment_path,
-                               ansi_highlight_off());
-                        fflush(stdout);
-
-                        r = copy_file_fd(fragment_path, STDOUT_FILENO, false);
-                        if (r < 0) {
-                                log_warning_errno(r, "Failed to cat %s: %m", fragment_path);
-                                continue;
-                        }
+                        r = cat_file(fragment_path, false);
+                        if (r < 0)
+                                return log_warning_errno(r, "Failed to cat %s: %m", fragment_path);
                 }
 
                 STRV_FOREACH(path, dropin_paths) {
-                        printf("%s%s# %s%s\n",
-                               isempty(fragment_path) && path == dropin_paths ? "" : "\n",
-                               ansi_highlight_blue(),
-                               *path,
-                               ansi_highlight_off());
-                        fflush(stdout);
-
-                        r = copy_file_fd(*path, STDOUT_FILENO, false);
-                        if (r < 0) {
-                                log_warning_errno(r, "Failed to cat %s: %m", *path);
-                                continue;
-                        }
+                        r = cat_file(*path, path == dropin_paths);
+                        if (r < 0)
+                                return log_warning_errno(r, "Failed to cat %s: %m", *path);
                 }
         }
 
-        return r < 0 ? r : 0;
+        return 0;
 }
 
 static int set_property(sd_bus *bus, char **args) {
@@ -5959,6 +6019,7 @@ static void systemctl_help(void) {
                "  -o --output=STRING  Change journal output mode (short, short-iso,\n"
                "                              short-precise, short-monotonic, verbose,\n"
                "                              export, json, json-pretty, json-sse, cat)\n"
+               "     --firmware-setup Tell the firmware to show the setup menu on next boot\n"
                "     --plain          Print unit dependencies as a list instead of a tree\n\n"
                "Unit Commands:\n"
                "  list-units [PATTERN...]         List loaded units\n"
@@ -6138,6 +6199,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
                 ARG_STATE,
                 ARG_JOB_MODE,
                 ARG_PRESET_MODE,
+                ARG_FIRMWARE_SETUP,
         };
 
         static const struct option options[] = {
@@ -6180,6 +6242,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
                 { "state",               required_argument, NULL, ARG_STATE               },
                 { "recursive",           no_argument,       NULL, 'r'                     },
                 { "preset-mode",         required_argument, NULL, ARG_PRESET_MODE         },
+                { "firmware-setup",      no_argument,       NULL, ARG_FIRMWARE_SETUP      },
                 {}
         };
 
@@ -6420,6 +6483,10 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
                         arg_plain = true;
                         break;
 
+                case ARG_FIRMWARE_SETUP:
+                        arg_firmware_setup = true;
+                        break;
+
                 case ARG_STATE: {
                         const char *word, *state;
                         size_t size;
@@ -7096,6 +7163,11 @@ found:
                 }
         }
 
+        /* Increase max number of open files to 16K if we can, we
+         * might needs this when browsing journal files, which might
+         * be split up into many files. */
+        setrlimit_closest(RLIMIT_NOFILE, &RLIMIT_MAKE_CONST(16384));
+
         return verb->dispatch(bus, argv + optind);
 }
 
@@ -7345,11 +7417,6 @@ int main(int argc, char*argv[]) {
                 goto finish;
         }
 
-        /* Increase max number of open files to 16K if we can, we
-         * might needs this when browsing journal files, which might
-         * be split up into many files. */
-        setrlimit_closest(RLIMIT_NOFILE, &RLIMIT_MAKE_CONST(16384));
-
         if (!avoid_bus())
                 r = bus_open_transport_systemd(arg_transport, arg_host, arg_scope != UNIT_FILE_SYSTEM, &bus);