diff options
Diffstat (limited to 'src/systemctl/systemctl.c')
-rw-r--r-- | src/systemctl/systemctl.c | 173 |
1 files changed, 119 insertions, 54 deletions
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index d3f437411a..6a0ed79a53 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -224,6 +224,21 @@ static void release_busses(void) { busses[w] = sd_bus_flush_close_unref(busses[w]); } +static int map_string_no_copy(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) { + char *s; + const char **p = userdata; + int r; + + r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &s); + if (r < 0) + return r; + + if (!isempty(s)) + *p = s; + + return 0; +} + static void ask_password_agent_open_if_enabled(void) { /* Open the password agent as a child process if necessary */ @@ -1820,12 +1835,12 @@ static const struct bus_properties_map machine_info_property_map[] = { }; static void machine_info_clear(struct machine_info *info) { - if (info) { - free(info->name); - free(info->state); - free(info->control_group); - zero(*info); - } + assert(info); + + free(info->name); + free(info->state); + free(info->control_group); + zero(*info); } static void free_machines_list(struct machine_info *machine_infos, int n) { @@ -3033,6 +3048,9 @@ static int logind_check_inhibitors(enum action a) { if (!on_tty()) return 0; + if (arg_transport != BUS_TRANSPORT_LOCAL) + return 0; + r = acquire_bus(BUS_FULL, &bus); if (r < 0) return r; @@ -3455,6 +3473,27 @@ static int exec_status_info_deserialize(sd_bus_message *m, ExecStatusInfo *i) { return 1; } +typedef struct UnitCondition { + char *name; + char *param; + bool trigger; + bool negate; + int tristate; + + LIST_FIELDS(struct UnitCondition, conditions); +} UnitCondition; + +static void unit_condition_free(UnitCondition *c) { + if (!c) + return; + + free(c->name); + free(c->param); + free(c); +} + +DEFINE_TRIVIAL_CLEANUP_FUNC(UnitCondition*, unit_condition_free); + typedef struct UnitStatusInfo { const char *id; const char *load_state; @@ -3501,10 +3540,7 @@ typedef struct UnitStatusInfo { usec_t condition_timestamp; bool condition_result; - bool failed_condition_trigger; - bool failed_condition_negate; - const char *failed_condition; - const char *failed_condition_parameter; + LIST_HEAD(UnitCondition, conditions); usec_t assert_timestamp; bool assert_result; @@ -3543,6 +3579,25 @@ typedef struct UnitStatusInfo { LIST_HEAD(ExecStatusInfo, exec); } UnitStatusInfo; +static void unit_status_info_free(UnitStatusInfo *info) { + ExecStatusInfo *p; + UnitCondition *c; + + strv_free(info->documentation); + strv_free(info->dropin_paths); + strv_free(info->listen); + + while ((c = info->conditions)) { + LIST_REMOVE(conditions, info->conditions, c); + unit_condition_free(c); + } + + while ((p = info->exec)) { + LIST_REMOVE(exec, info->exec, p); + exec_status_info_free(p); + } +} + static void print_status_info( sd_bus *bus, UnitStatusInfo *i, @@ -3664,19 +3719,28 @@ static void print_status_info( printf("\n"); if (!i->condition_result && i->condition_timestamp > 0) { + UnitCondition *c; + int n = 0; + s1 = format_timestamp_relative(since1, sizeof(since1), i->condition_timestamp); s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp); printf("Condition: start %scondition failed%s at %s%s%s\n", ansi_highlight_yellow(), ansi_normal(), s2, s1 ? "; " : "", strempty(s1)); - if (i->failed_condition_trigger) - printf(" none of the trigger conditions were met\n"); - else if (i->failed_condition) - printf(" %s=%s%s was not met\n", - i->failed_condition, - i->failed_condition_negate ? "!" : "", - i->failed_condition_parameter); + + LIST_FOREACH(conditions, c, i->conditions) + if (c->tristate < 0) + n++; + + LIST_FOREACH(conditions, c, i->conditions) + if (c->tristate < 0) + printf(" %s %s=%s%s%s was not met\n", + --n ? special_glyph(TREE_BRANCH) : special_glyph(TREE_RIGHT), + c->name, + c->trigger ? "|" : "", + c->negate ? "!" : "", + c->param); } if (!i->assert_result && i->assert_timestamp > 0) { @@ -3761,7 +3825,7 @@ static void print_status_info( if (i->running) { _cleanup_free_ char *comm = NULL; - get_process_comm(i->main_pid, &comm); + (void) get_process_comm(i->main_pid, &comm); if (comm) printf(" (%s)", comm); } else if (i->exit_code > 0) { @@ -3780,17 +3844,19 @@ static void print_status_info( printf("signal=%s", signal_to_string(i->exit_status)); printf(")"); } - - if (i->control_pid > 0) - printf(";"); } if (i->control_pid > 0) { _cleanup_free_ char *c = NULL; - printf(" %8s: "PID_FMT, i->main_pid ? "" : " Control", i->control_pid); + if (i->main_pid > 0) + fputs("; Control PID: ", stdout); + else + fputs("Cntrl PID: ", stdout); /* if first in column, abbreviated so it fits alignment */ - get_process_comm(i->control_pid, &c); + printf(PID_FMT, i->control_pid); + + (void) get_process_comm(i->control_pid, &c); if (c) printf(" (%s)", c); } @@ -3807,7 +3873,7 @@ static void print_status_info( printf(" Tasks: %" PRIu64, i->tasks_current); if (i->tasks_max != (uint64_t) -1) - printf(" (limit: %" PRIi64 ")\n", i->tasks_max); + printf(" (limit: %" PRIu64 ")\n", i->tasks_max); else printf("\n"); } @@ -4169,13 +4235,25 @@ static int status_property(const char *name, sd_bus_message *m, UnitStatusInfo * return bus_log_parse_error(r); while ((r = sd_bus_message_read(m, "(sbbsi)", &cond, &trigger, &negate, ¶m, &state)) > 0) { - log_debug("%s %d %d %s %d", cond, trigger, negate, param, state); - if (state < 0 && (!trigger || !i->failed_condition)) { - i->failed_condition = cond; - i->failed_condition_trigger = trigger; - i->failed_condition_negate = negate; - i->failed_condition_parameter = param; - } + _cleanup_(unit_condition_freep) UnitCondition *c = NULL; + + log_debug("%s trigger=%d negate=%d %s →%d", cond, trigger, negate, param, state); + + c = new0(UnitCondition, 1); + if (!c) + return log_oom(); + + c->name = strdup(cond); + c->param = strdup(param); + if (!c->name || !c->param) + return log_oom(); + + c->trigger = trigger; + c->negate = negate; + c->tristate = state; + + LIST_PREPEND(conditions, i->conditions, c); + c = NULL; } if (r < 0) return bus_log_parse_error(r); @@ -4565,15 +4643,15 @@ static int show_one( bool *ellipsized) { static const struct bus_properties_map property_map[] = { - { "LoadState", "s", NULL, offsetof(UnitStatusInfo, load_state) }, - { "ActiveState", "s", NULL, offsetof(UnitStatusInfo, active_state) }, + { "LoadState", "s", map_string_no_copy, offsetof(UnitStatusInfo, load_state) }, + { "ActiveState", "s", map_string_no_copy, offsetof(UnitStatusInfo, active_state) }, {} }; _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_set_free_ Set *found_properties = NULL; - UnitStatusInfo info = { + _cleanup_(unit_status_info_free) UnitStatusInfo info = { .memory_current = (uint64_t) -1, .memory_high = CGROUP_LIMIT_MAX, .memory_max = CGROUP_LIMIT_MAX, @@ -4582,7 +4660,6 @@ static int show_one( .tasks_current = (uint64_t) -1, .tasks_max = (uint64_t) -1, }; - ExecStatusInfo *p; int r; assert(path); @@ -4676,16 +4753,15 @@ static int show_one( return bus_log_parse_error(r); r = 0; - if (show_properties) { char **pp; - STRV_FOREACH(pp, arg_properties) { + STRV_FOREACH(pp, arg_properties) if (!set_contains(found_properties, *pp)) { log_warning("Property %s does not exist.", *pp); r = -ENXIO; } - } + } else if (streq(verb, "help")) show_unit_help(&info); else if (streq(verb, "status")) { @@ -4697,15 +4773,6 @@ static int show_one( r = EXIT_PROGRAM_RUNNING_OR_SERVICE_OK; } - strv_free(info.documentation); - strv_free(info.dropin_paths); - strv_free(info.listen); - - while ((p = info.exec)) { - LIST_REMOVE(exec, info.exec, p); - exec_status_info_free(p); - } - return r; } @@ -5532,10 +5599,8 @@ static int enable_sysv_units(const char *verb, char **args) { } j = wait_for_terminate(pid, &status); - if (j < 0) { - log_error_errno(j, "Failed to wait for child: %m"); - return j; - } + if (j < 0) + return log_error_errno(j, "Failed to wait for child: %m"); if (status.si_code == CLD_EXITED) { if (streq(verb, "is-enabled")) { @@ -5610,8 +5675,8 @@ static int unit_exists(const char *unit) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_free_ char *path = NULL; static const struct bus_properties_map property_map[] = { - { "LoadState", "s", NULL, offsetof(UnitStatusInfo, load_state) }, - { "ActiveState", "s", NULL, offsetof(UnitStatusInfo, active_state)}, + { "LoadState", "s", map_string_no_copy, offsetof(UnitStatusInfo, load_state) }, + { "ActiveState", "s", map_string_no_copy, offsetof(UnitStatusInfo, active_state)}, {}, }; UnitStatusInfo info = {}; @@ -6530,7 +6595,7 @@ static void systemctl_help(void) { " unit is required or wanted\n\n" "Unit File Commands:\n" " list-unit-files [PATTERN...] List installed unit files\n" - " enable NAME... Enable one or more unit files\n" + " enable [NAME...|PATH...] Enable one or more unit files\n" " disable NAME... Disable one or more unit files\n" " reenable NAME... Reenable one or more unit files\n" " preset NAME... Enable/disable one or more unit files\n" |