diff options
Diffstat (limited to 'src/systemctl/systemctl.c')
-rw-r--r-- | src/systemctl/systemctl.c | 215 |
1 files changed, 134 insertions, 81 deletions
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index 74d7fc2b3b..d21ba9a566 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -20,59 +20,60 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ -#include <sys/reboot.h> -#include <linux/reboot.h> -#include <stdio.h> +#include <errno.h> +#include <fcntl.h> #include <getopt.h> +#include <linux/reboot.h> #include <locale.h> #include <stdbool.h> +#include <stddef.h> +#include <stdio.h> #include <string.h> -#include <errno.h> -#include <unistd.h> -#include <fcntl.h> +#include <sys/reboot.h> #include <sys/socket.h> -#include <stddef.h> +#include <unistd.h> +#include "sd-bus.h" #include "sd-daemon.h" #include "sd-login.h" -#include "sd-bus.h" -#include "log.h" -#include "util.h" -#include "macro.h" -#include "set.h" -#include "utmp-wtmp.h" -#include "special.h" -#include "initreq.h" -#include "path-util.h" -#include "strv.h" + +#include "build.h" +#include "bus-common-errors.h" +#include "bus-error.h" +#include "bus-message.h" +#include "bus-util.h" #include "cgroup-show.h" #include "cgroup-util.h" -#include "list.h" -#include "path-lookup.h" -#include "exit-status.h" -#include "build.h" -#include "unit-name.h" -#include "pager.h" -#include "spawn-ask-password-agent.h" -#include "spawn-polkit-agent.h" -#include "install.h" -#include "logs-show.h" -#include "socket-util.h" -#include "fileio.h" #include "copy.h" -#include "env-util.h" -#include "bus-util.h" -#include "bus-message.h" -#include "bus-error.h" -#include "bus-common-errors.h" -#include "mkdir.h" #include "dropin.h" #include "efivars.h" +#include "env-util.h" +#include "exit-status.h" +#include "fileio.h" #include "formats-util.h" -#include "process-util.h" -#include "terminal-util.h" #include "hostname-util.h" +#include "initreq.h" +#include "install.h" +#include "list.h" +#include "log.h" +#include "logs-show.h" +#include "macro.h" +#include "mkdir.h" +#include "pager.h" +#include "path-lookup.h" +#include "path-util.h" +#include "process-util.h" +#include "set.h" #include "signal-util.h" +#include "socket-util.h" +#include "spawn-ask-password-agent.h" +#include "spawn-polkit-agent.h" +#include "special.h" +#include "strv.h" +#include "terminal-util.h" +#include "unit-name.h" +#include "util.h" +#include "utmp-wtmp.h" static char **arg_types = NULL; static char **arg_states = NULL; @@ -100,7 +101,7 @@ static bool arg_quiet = false; static bool arg_full = false; static bool arg_recursive = false; static int arg_force = 0; -static bool arg_ask_password = true; +static bool arg_ask_password = false; static bool arg_runtime = false; static UnitFilePresetMode arg_preset_mode = UNIT_FILE_PRESET_FULL; static char **arg_wall = NULL; @@ -1299,10 +1300,11 @@ static void output_unit_file_list(const UnitFileList *units, unsigned c) { const char *on, *off; const char *id; - if (u->state == UNIT_FILE_MASKED || - u->state == UNIT_FILE_MASKED_RUNTIME || - u->state == UNIT_FILE_DISABLED || - u->state == UNIT_FILE_INVALID) { + if (IN_SET(u->state, + UNIT_FILE_MASKED, + UNIT_FILE_MASKED_RUNTIME, + UNIT_FILE_DISABLED, + UNIT_FILE_INVALID)) { on = ansi_highlight_red(); off = ansi_highlight_off(); } else if (u->state == UNIT_FILE_ENABLED) { @@ -1476,6 +1478,8 @@ static int list_dependencies_get_dependencies(sd_bus *bus, const char *name, cha "BindsTo\0", [DEPENDENCY_REVERSE] = "RequiredBy\0" "RequiredByOverridable\0" + "RequisiteOf\0" + "RequisiteOfOverridable\0" "WantedBy\0" "PartOf\0" "BoundBy\0", @@ -2762,7 +2766,7 @@ static int start_unit(sd_bus *bus, char **args) { static int reboot_with_logind(sd_bus *bus, enum action a) { #ifdef HAVE_LOGIND _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; - const char *method; + const char *method, *description; int r; if (!bus) @@ -2774,22 +2778,27 @@ static int reboot_with_logind(sd_bus *bus, enum action a) { case ACTION_REBOOT: method = "Reboot"; + description = "reboot system"; break; case ACTION_POWEROFF: method = "PowerOff"; + description = "power off system"; break; case ACTION_SUSPEND: method = "Suspend"; + description = "suspend system"; break; case ACTION_HIBERNATE: method = "Hibernate"; + description = "hibernate system"; break; case ACTION_HYBRID_SLEEP: method = "HybridSleep"; + description = "put system into hybrid sleep"; break; default: @@ -2833,7 +2842,7 @@ static int reboot_with_logind(sd_bus *bus, enum action a) { NULL, "b", arg_ask_password); if (r < 0) - log_error("Failed to execute operation: %s", bus_error_message(&error, r)); + log_error("Failed to %s via logind: %s", description, bus_error_message(&error, r)); return r; #else @@ -2898,10 +2907,11 @@ static int check_inhibitors(sd_bus *bus, enum action a) { return log_error_errno(ERANGE, "Bad PID %"PRIu32": %m", pid); if (!strv_contains(sv, - a == ACTION_HALT || - a == ACTION_POWEROFF || - a == ACTION_REBOOT || - a == ACTION_KEXEC ? "shutdown" : "sleep")) + IN_SET(a, + ACTION_HALT, + ACTION_POWEROFF, + ACTION_REBOOT, + ACTION_KEXEC) ? "shutdown" : "sleep")) continue; get_process_comm(pid, &comm); @@ -3022,29 +3032,36 @@ static int start_special(sd_bus *bus, char **args) { } if (arg_force >= 2 && - (a == ACTION_HALT || - a == ACTION_POWEROFF || - a == ACTION_REBOOT)) + IN_SET(a, + ACTION_HALT, + ACTION_POWEROFF, + ACTION_REBOOT)) return halt_now(a); if (arg_force >= 1 && - (a == ACTION_HALT || - a == ACTION_POWEROFF || - a == ACTION_REBOOT || - a == ACTION_KEXEC || - a == ACTION_EXIT)) + IN_SET(a, + ACTION_HALT, + ACTION_POWEROFF, + ACTION_REBOOT, + ACTION_KEXEC, + ACTION_EXIT)) return daemon_reload(bus, args); /* first try logind, to allow authentication with polkit */ if (geteuid() != 0 && - (a == ACTION_POWEROFF || - a == ACTION_REBOOT || - a == ACTION_SUSPEND || - a == ACTION_HIBERNATE || - a == ACTION_HYBRID_SLEEP)) { + IN_SET(a, + ACTION_POWEROFF, + ACTION_REBOOT, + ACTION_SUSPEND, + ACTION_HIBERNATE, + ACTION_HYBRID_SLEEP)) { r = reboot_with_logind(bus, a); - if (r >= 0 || IN_SET(r, -EOPNOTSUPP, -EINPROGRESS)) + if (r >= 0) + return r; + if (IN_SET(r, -EOPNOTSUPP, -EINPROGRESS)) + /* requested operation is not supported or already in progress */ return r; + /* on all other errors, try low-level operation */ } r = start_unit(bus, args); @@ -3283,6 +3300,8 @@ typedef struct UnitStatusInfo { uint64_t memory_current; uint64_t memory_limit; uint64_t cpu_usage_nsec; + uint64_t tasks_current; + uint64_t tasks_max; LIST_HEAD(ExecStatusInfo, exec); } UnitStatusInfo; @@ -3541,6 +3560,15 @@ static void print_status_info( if (i->status_errno > 0) printf(" Error: %i (%s)\n", i->status_errno, strerror(i->status_errno)); + if (i->tasks_current != (uint64_t) -1) { + printf(" Tasks: %" PRIu64, i->tasks_current); + + if (i->tasks_max != (uint64_t) -1) + printf(" (limit: %" PRIi64 ")\n", i->tasks_max); + else + printf("\n"); + } + if (i->memory_current != (uint64_t) -1) { char buf[FORMAT_BYTES_MAX]; @@ -3559,12 +3587,14 @@ static void print_status_info( 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) == 0))) { + (!IN_SET(arg_transport, BUS_TRANSPORT_LOCAL, BUS_TRANSPORT_MACHINE) || cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, i->control_group) == 0))) { unsigned c; printf(" CGroup: %s\n", i->control_group); - if (arg_transport == BUS_TRANSPORT_LOCAL || arg_transport == BUS_TRANSPORT_MACHINE) { + if (IN_SET(arg_transport, + BUS_TRANSPORT_LOCAL, + BUS_TRANSPORT_MACHINE)) { unsigned k = 0; pid_t extra[2]; static const char prefix[] = " "; @@ -3774,6 +3804,10 @@ 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, "TasksCurrent")) + i->tasks_current = u; + else if (streq(name, "TasksMax")) + i->tasks_max = u; else if (streq(name, "CPUUsageNSec")) i->cpu_usage_nsec = u; @@ -4250,6 +4284,8 @@ static int show_one( .memory_current = (uint64_t) -1, .memory_limit = (uint64_t) -1, .cpu_usage_nsec = (uint64_t) -1, + .tasks_current = (uint64_t) -1, + .tasks_max = (uint64_t) -1, }; ExecStatusInfo *p; int r; @@ -4467,7 +4503,9 @@ static int show_system_status(sd_bus *bus) { format_timestamp_relative(since1, sizeof(since1), mi.timestamp)); printf(" CGroup: %s\n", mi.control_group ?: "/"); - if (arg_transport == BUS_TRANSPORT_LOCAL || arg_transport == BUS_TRANSPORT_MACHINE) { + if (IN_SET(arg_transport, + BUS_TRANSPORT_LOCAL, + BUS_TRANSPORT_MACHINE)) { static const char prefix[] = " "; unsigned c; @@ -4623,7 +4661,7 @@ static int cat_file(const char *filename, bool newline) { ansi_highlight_off()); fflush(stdout); - return copy_bytes(fd, STDOUT_FILENO, (off_t) -1, false); + return copy_bytes(fd, STDOUT_FILENO, (uint64_t) -1, false); } static int cat(sd_bus *bus, char **args) { @@ -5134,9 +5172,10 @@ static int enable_sysv_units(const char *verb, char **args) { if (arg_scope != UNIT_FILE_SYSTEM) return 0; - if (!streq(verb, "enable") && - !streq(verb, "disable") && - !streq(verb, "is-enabled")) + if (!STR_IN_SET(verb, + "enable", + "disable", + "is-enabled")) return 0; /* Processes all SysV units, and reshuffles the array so that @@ -5636,10 +5675,11 @@ static int unit_is_enabled(sd_bus *bus, char **args) { if (state < 0) return log_error_errno(state, "Failed to get unit file state for %s: %m", *name); - if (state == UNIT_FILE_ENABLED || - state == UNIT_FILE_ENABLED_RUNTIME || - state == UNIT_FILE_STATIC || - state == UNIT_FILE_INDIRECT) + if (IN_SET(state, + UNIT_FILE_ENABLED, + UNIT_FILE_ENABLED_RUNTIME, + UNIT_FILE_STATIC, + UNIT_FILE_INDIRECT)) enabled = true; if (!arg_quiet) @@ -6340,6 +6380,9 @@ static int systemctl_parse_argv(int argc, char *argv[]) { assert(argc >= 0); assert(argv); + /* we default to allowing interactive authorization only in systemctl (not in the legacy commands) */ + arg_ask_password = true; + while ((c = getopt_long(argc, argv, "ht:p:alqfs:H:M:n:o:ir", options, NULL)) >= 0) switch (c) { @@ -7353,21 +7396,27 @@ static int halt_main(sd_bus *bus) { return r; if (geteuid() != 0) { + if (arg_when > 0 || + arg_dry || + arg_force > 0) { + log_error("Must be root."); + return -EPERM; + } + /* Try logind if we are a normal user and no special * mode applies. Maybe PolicyKit allows us to shutdown * the machine. */ - - if (arg_when <= 0 && - arg_force <= 0 && - (arg_action == ACTION_POWEROFF || - arg_action == ACTION_REBOOT)) { + if (IN_SET(arg_action, + ACTION_POWEROFF, + ACTION_REBOOT)) { r = reboot_with_logind(bus, arg_action); if (r >= 0) return r; + if (IN_SET(r, -EOPNOTSUPP, -EINPROGRESS)) + /* requested operation is not supported or already in progress */ + return r; + /* on all other errors, try low-level operation */ } - - log_error("Must be root."); - return -EPERM; } if (arg_when > 0) { @@ -7376,6 +7425,8 @@ static int halt_main(sd_bus *bus) { _cleanup_free_ char *m = NULL; const char *action; + assert(geteuid() == 0); + if (avoid_bus()) { log_error("Unable to perform operation without bus connection."); return -ENOSYS; @@ -7451,6 +7502,8 @@ static int halt_main(sd_bus *bus) { if (!arg_dry && !arg_force) return start_with_fallback(bus); + assert(geteuid() == 0); + if (!arg_no_wtmp) { if (sd_booted() > 0) log_debug("Not writing utmp record, assuming that systemd-update-utmp is used."); |