X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fsystemctl%2Fsystemctl.c;h=f7b2fb40190e61bc0ee73c3f36723e2d463a1450;hb=e93c33d4aadb41427f215d43545e7fadc6bcec6f;hp=84826a3829d829983c7d41497cc04cc0fea6a52b;hpb=718db96199eb307751264e4163555662c9a389fa;p=elogind.git diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index 84826a382..f7b2fb401 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -137,6 +137,8 @@ static bool arg_plain = false; static int daemon_reload(sd_bus *bus, char **args); static int halt_now(enum action a); +static int check_one_unit(sd_bus *bus, const char *name, const char *good_states, bool quiet); + static void pager_open_if_enabled(void) { if (arg_no_pager) @@ -1309,6 +1311,8 @@ static int list_dependencies_one( qsort_safe(deps, strv_length(deps), sizeof (char*), list_dependencies_compare); STRV_FOREACH(c, deps) { + int state; + if (strv_contains(u, *c)) { if (!arg_plain) { r = list_dependencies_print("...", level + 1, (branches << 1) | (c[1] == NULL ? 0 : 1), 1); @@ -1318,6 +1322,12 @@ static int list_dependencies_one( continue; } + state = check_one_unit(bus, *c, "activating\0active\0reloading\0", true); + if (state > 0) + printf("%s%s%s", ansi_highlight_green(), draw_special_char(DRAW_BLACK_CIRCLE), ansi_highlight_off()); + else + printf("%s%s%s", ansi_highlight_red(), draw_special_char(DRAW_BLACK_CIRCLE), ansi_highlight_off()); + r = list_dependencies_print(*c, level, branches, c[1] == NULL); if (r < 0) return r; @@ -1711,7 +1721,7 @@ typedef struct WaitData { char *result; } WaitData; -static int wait_filter(sd_bus *bus, sd_bus_message *m, void *data) { +static int wait_filter(sd_bus *bus, sd_bus_message *m, void *data, sd_bus_error *error) { WaitData *d = data; assert(bus); @@ -1764,7 +1774,7 @@ static int wait_filter(sd_bus *bus, sd_bus_message *m, void *data) { } #endif - log_error("Failed to parse message."); + bus_log_parse_error(r); } return 0; @@ -3594,16 +3604,13 @@ static int show_one( return r; } -static int show_one_by_pid( - const char *verb, +static int get_unit_dbus_path_by_pid( sd_bus *bus, uint32_t pid, - bool *new_line, - bool *ellipsized) { + char **unit) { _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_bus_message_unref_ sd_bus_message *reply = NULL; - const char *path = NULL; int r; r = sd_bus_call_method( @@ -3620,11 +3627,11 @@ static int show_one_by_pid( return r; } - r = sd_bus_message_read(reply, "o", &path); + r = sd_bus_message_read(reply, "o", unit); if (r < 0) return bus_log_parse_error(r); - return show_one(verb, bus, path, false, new_line, ellipsized); + return 0; } static int show_all( @@ -3644,6 +3651,8 @@ static int show_all( if (r < 0) return r; + pager_open_if_enabled(); + c = (unsigned) r; qsort_safe(unit_infos, c, sizeof(UnitInfo), compare_unit_info); @@ -3658,8 +3667,6 @@ static int show_all( if (!p) return log_oom(); - printf("%s -> '%s'\n", u->id, p); - r = show_one(verb, bus, p, show_properties, new_line, ellipsized); if (r != 0) return r; @@ -3668,6 +3675,107 @@ static int show_all( return 0; } +static int cat(sd_bus *bus, char **args) { + int r = 0; + char **name; + + _cleanup_free_ char *unit = NULL, *n = NULL; + + assert(bus); + assert(args); + + pager_open_if_enabled(); + + STRV_FOREACH(name, args+1) { + _cleanup_free_ char *fragment_path = NULL; + _cleanup_strv_free_ char **dropin_paths = NULL; + sd_bus_error error; + FILE *stdout; + char **path; + + n = unit_name_mangle(*name); + if (!n) + return log_oom(); + + unit = unit_dbus_path_from_name(n); + if (!unit) + return log_oom(); + + if (need_daemon_reload(bus, n) > 0) + log_warning("Unit file of %s changed on disk. Run 'systemctl%s daemon-reload'.", + n, arg_scope == UNIT_FILE_SYSTEM ? "" : " --user"); + + r = sd_bus_get_property_string( + bus, + "org.freedesktop.systemd1", + unit, + "org.freedesktop.systemd1.Unit", + "FragmentPath", + &error, + &fragment_path); + if (r < 0) { + log_warning("Failed to get FragmentPath: %s", bus_error_message(&error, r)); + continue; + } + + if (isempty(fragment_path)) { + free(fragment_path); + fragment_path = NULL; + + if (sd_bus_get_property_string( + bus, + "org.freedesktop.systemd1", + unit, + "org.freedesktop.systemd1.Unit", + "SourcePath", + &error, + &fragment_path) < 0) { + log_warning("Failed to get SourcePath: %s", bus_error_message(&error, r)); + continue; + } + } + + r = sd_bus_get_property_strv( + bus, + "org.freedesktop.systemd1", + unit, + "org.freedesktop.systemd1.Unit", + "DropInPaths", + &error, + &dropin_paths); + if (r < 0) { + log_warning("Failed to get DropInPaths: %s", bus_error_message(&error, r)); + continue; + } + + stdout = fdopen(STDOUT_FILENO, "a"); + + if (!isempty(fragment_path)) { + fprintf(stdout, "# %s\n", fragment_path); + fflush(stdout); + r = sendfile_full(STDOUT_FILENO, fragment_path); + if (r < 0) { + log_warning("Failed to cat %s: %s", fragment_path, strerror(-r)); + continue; + } + } + + STRV_FOREACH(path, dropin_paths) { + fprintf(stdout, "%s# %s\n", + isempty(fragment_path) && path == dropin_paths ? "" : "\n", + *path); + fflush(stdout); + r = sendfile_full(STDOUT_FILENO, *path); + if (r < 0) { + log_warning("Failed to cat %s: %s", *path, strerror(-r)); + continue; + } + } + } + + return r; +} + static int show(sd_bus *bus, char **args) { int r, ret = 0; bool show_properties, show_status, new_line = false; @@ -3692,41 +3800,34 @@ static int show(sd_bus *bus, char **args) { ret = show_all(args[0], bus, false, &new_line, &ellipsized); else STRV_FOREACH(name, args+1) { + _cleanup_free_ char *unit = NULL; uint32_t id; if (safe_atou32(*name, &id) < 0) { - _cleanup_free_ char *p = NULL, *n = NULL; + _cleanup_free_ char *n = NULL; /* Interpret as unit name */ n = unit_name_mangle(*name); if (!n) return log_oom(); - p = unit_dbus_path_from_name(n); - if (!p) + unit = unit_dbus_path_from_name(n); + if (!unit) return log_oom(); - r = show_one(args[0], bus, p, show_properties, &new_line, &ellipsized); - if (r != 0) - ret = r; - } else if (show_properties) { - _cleanup_free_ char *p = NULL; - /* Interpret as job id */ - if (asprintf(&p, "/org/freedesktop/systemd1/job/%u", id) < 0) + if (asprintf(&unit, "/org/freedesktop/systemd1/job/%u", id) < 0) return log_oom(); - r = show_one(args[0], bus, p, show_properties, &new_line, &ellipsized); - if (r != 0) - ret = r; - } else { /* Interpret as PID */ - r = show_one_by_pid(args[0], bus, id, &new_line, &ellipsized); - if (r != 0) + r = get_unit_dbus_path_by_pid(bus, id, &unit); + if (r < 0) ret = r; } + + show_one(args[0], bus, unit, show_properties, &new_line, &ellipsized); } if (ellipsized && !arg_quiet) @@ -4539,7 +4640,7 @@ static int enable_unit(sd_bus *bus, char **args) { return bus_log_parse_error(r); } - r = deserialize_and_dump_unit_file_changes(m); + r = deserialize_and_dump_unit_file_changes(reply); if (r < 0) return r; @@ -4661,14 +4762,10 @@ static int systemctl_help(void) { " -a --all Show all loaded units/properties, including dead/empty\n" " ones. To list all units installed on the system, use\n" " the 'list-unit-files' command instead.\n" - " --reverse Show reverse dependencies with 'list-dependencies'\n" " -l --full Don't ellipsize unit names on output\n" - " --fail When queueing a new job, fail if conflicting jobs are\n" - " pending\n" - " --irreversible When queueing a new job, make sure it cannot be implicitly\n" - " cancelled\n" - " --ignore-dependencies\n" - " When queueing a new job, ignore all its dependencies\n" + " --reverse Show reverse dependencies with 'list-dependencies'\n" + " --job-mode=MODE Specify how to deal with already queued jobs, when\n" + " queueing a new job\n" " --show-types When showing sockets, explicitly show their type\n" " -i --ignore-inhibitors\n" " When shutting down or sleeping, ignore inhibitors\n" @@ -4711,6 +4808,7 @@ static int systemctl_help(void) { " status [NAME...|PID...] Show runtime status of one or more units\n" " show [NAME...|JOB...] Show properties of one or more\n" " units/jobs or the manager\n" + " cat [NAME...] Show files and drop-ins of one or more units\n" " set-property [NAME] [ASSIGNMENT...]\n" " Sets one or more properties of a unit\n" " help [NAME...|PID...] Show manual for one or more units\n" @@ -4870,7 +4968,8 @@ static int systemctl_parse_argv(int argc, char *argv[]) { ARG_RUNTIME, ARG_FORCE, ARG_PLAIN, - ARG_STATE + ARG_STATE, + ARG_JOB_MODE }; static const struct option options[] = { @@ -4885,9 +4984,10 @@ static int systemctl_parse_argv(int argc, char *argv[]) { { "show-types", no_argument, NULL, ARG_SHOW_TYPES }, { "failed", no_argument, NULL, ARG_FAILED }, /* compatibility only */ { "full", no_argument, NULL, 'l' }, - { "fail", no_argument, NULL, ARG_FAIL }, - { "irreversible", no_argument, NULL, ARG_IRREVERSIBLE }, - { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES }, + { "job-mode", required_argument, NULL, ARG_JOB_MODE }, + { "fail", no_argument, NULL, ARG_FAIL }, /* compatibility only */ + { "irreversible", no_argument, NULL, ARG_IRREVERSIBLE }, /* compatibility only */ + { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES }, /* compatibility only */ { "ignore-inhibitors", no_argument, NULL, 'i' }, { "user", no_argument, NULL, ARG_USER }, { "system", no_argument, NULL, ARG_SYSTEM }, @@ -5025,6 +5125,10 @@ static int systemctl_parse_argv(int argc, char *argv[]) { arg_show_types = true; break; + case ARG_JOB_MODE: + arg_job_mode = optarg; + break; + case ARG_FAIL: arg_job_mode = "fail"; break; @@ -5688,6 +5792,7 @@ static int systemctl_main(sd_bus *bus, int argc, char *argv[], int bus_error) { { "check", MORE, 2, check_unit_active }, { "is-failed", MORE, 2, check_unit_failed }, { "show", MORE, 1, show }, + { "cat", MORE, 2, cat }, { "status", MORE, 1, show }, { "help", MORE, 2, show }, { "snapshot", LESS, 2, snapshot },