diff options
Diffstat (limited to 'src/systemctl/systemctl.c')
-rw-r--r-- | src/systemctl/systemctl.c | 231 |
1 files changed, 79 insertions, 152 deletions
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index 420a246be1..51b82d57db 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -37,6 +37,7 @@ #include "sd-daemon.h" #include "sd-login.h" +#include "alloc-util.h" #include "bus-common-errors.h" #include "bus-error.h" #include "bus-message.h" @@ -48,32 +49,42 @@ #include "efivars.h" #include "env-util.h" #include "exit-status.h" +#include "fd-util.h" #include "fileio.h" #include "formats-util.h" +#include "fs-util.h" +#include "glob-util.h" #include "hostname-util.h" #include "initreq.h" #include "install.h" +#include "io-util.h" #include "list.h" +#include "locale-util.h" #include "log.h" #include "logs-show.h" #include "macro.h" #include "mkdir.h" #include "pager.h" +#include "parse-util.h" #include "path-lookup.h" #include "path-util.h" #include "process-util.h" +#include "rlimit-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 "stat-util.h" #include "strv.h" #include "terminal-util.h" #include "unit-name.h" +#include "user-util.h" #include "util.h" #include "utmp-wtmp.h" #include "verbs.h" +#include "virt.h" static char **arg_types = NULL; static char **arg_states = NULL; @@ -107,7 +118,7 @@ static UnitFilePresetMode arg_preset_mode = UNIT_FILE_PRESET_FULL; static char **arg_wall = NULL; static const char *arg_kill_who = NULL; static int arg_signal = SIGTERM; -static const char *arg_root = NULL; +static char *arg_root = NULL; static usec_t arg_when = 0; static enum action { _ACTION_INVALID, @@ -285,6 +296,10 @@ static bool install_client_side(void) { if (arg_scope == UNIT_FILE_GLOBAL) return true; + /* Unsupported environment variable, mostly for debugging purposes */ + if (getenv_bool("SYSTEMCTL_INSTALL_CLIENT_SIDE") > 0) + return true; + return false; } @@ -1320,7 +1335,7 @@ static void output_unit_file_list(const UnitFileList *units, unsigned c) { UNIT_FILE_MASKED, UNIT_FILE_MASKED_RUNTIME, UNIT_FILE_DISABLED, - UNIT_FILE_INVALID)) { + UNIT_FILE_BAD)) { on = ansi_highlight_red(); off = ansi_normal(); } else if (u->state == UNIT_FILE_ENABLED) { @@ -1488,16 +1503,12 @@ static int list_dependencies_get_dependencies(sd_bus *bus, const char *name, cha static const char *dependencies[_DEPENDENCY_MAX] = { [DEPENDENCY_FORWARD] = "Requires\0" - "RequiresOverridable\0" "Requisite\0" - "RequisiteOverridable\0" "Wants\0" "ConsistsOf\0" "BindsTo\0", [DEPENDENCY_REVERSE] = "RequiredBy\0" - "RequiredByOverridable\0" "RequisiteOf\0" - "RequisiteOfOverridable\0" "WantedBy\0" "PartOf\0" "BoundBy\0", @@ -2171,7 +2182,7 @@ static int list_jobs(int argc, char *argv[], void *userdata) { return bus_log_parse_error(r); output_jobs_list(jobs, c, skipped); - return r; + return 0; } static int cancel_job(int argc, char *argv[], void *userdata) { @@ -3475,7 +3486,8 @@ static void print_status_info( dir = mfree(dir); - if (path_get_parent(*dropin, &dir) < 0) { + dir = dirname_malloc(*dropin); + if (!dir) { log_oom(); return; } @@ -4889,102 +4901,6 @@ static int set_property(int argc, char *argv[], void *userdata) { return 0; } -static int snapshot(int argc, char *argv[], void *userdata) { - _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; - _cleanup_bus_message_unref_ sd_bus_message *reply = NULL; - _cleanup_free_ char *n = NULL, *id = NULL; - const char *path; - sd_bus *bus; - int r; - - polkit_agent_open_if_enabled(); - - if (argc > 1) { - r = unit_name_mangle_with_suffix(argv[1], UNIT_NAME_NOGLOB, ".snapshot", &n); - if (r < 0) - return log_error_errno(r, "Failed to generate unit name: %m"); - } else { - n = strdup(""); - if (!n) - return log_oom(); - } - - r = acquire_bus(BUS_MANAGER, &bus); - if (r < 0) - return r; - - r = sd_bus_call_method( - bus, - "org.freedesktop.systemd1", - "/org/freedesktop/systemd1", - "org.freedesktop.systemd1.Manager", - "CreateSnapshot", - &error, - &reply, - "sb", n, false); - if (r < 0) - return log_error_errno(r, "Failed to create snapshot: %s", bus_error_message(&error, r)); - - r = sd_bus_message_read(reply, "o", &path); - if (r < 0) - return bus_log_parse_error(r); - - r = sd_bus_get_property_string( - bus, - "org.freedesktop.systemd1", - path, - "org.freedesktop.systemd1.Unit", - "Id", - &error, - &id); - if (r < 0) - return log_error_errno(r, "Failed to get ID of snapshot: %s", bus_error_message(&error, r)); - - if (!arg_quiet) - puts(id); - - return 0; -} - -static int delete_snapshot(int argc, char *argv[], void *userdata) { - _cleanup_strv_free_ char **names = NULL; - sd_bus *bus; - char **name; - int r; - - polkit_agent_open_if_enabled(); - - r = acquire_bus(BUS_MANAGER, &bus); - if (r < 0) - return r; - - r = expand_names(bus, strv_skip(argv, 1), ".snapshot", &names); - if (r < 0) - return log_error_errno(r, "Failed to expand names: %m"); - - STRV_FOREACH(name, names) { - _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; - int q; - - q = sd_bus_call_method( - bus, - "org.freedesktop.systemd1", - "/org/freedesktop/systemd1", - "org.freedesktop.systemd1.Manager", - "RemoveSnapshot", - &error, - NULL, - "s", *name); - if (q < 0) { - log_error_errno(q, "Failed to remove snapshot %s: %s", *name, bus_error_message(&error, q)); - if (r == 0) - r = q; - } - } - - return r; -} - static int daemon_reload(int argc, char *argv[], void *userdata) { _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; const char *method; @@ -5305,6 +5221,9 @@ static int enable_sysv_units(const char *verb, char **args) { if (arg_scope != UNIT_FILE_SYSTEM) return 0; + if (getenv_bool("SYSTEMCTL_SKIP_SYSV") > 0) + return 0; + if (!STR_IN_SET(verb, "enable", "disable", @@ -5514,10 +5433,10 @@ static int enable_unit(int argc, char *argv[], void *userdata) { else assert_not_reached("Unknown verb"); - if (r < 0) { - log_error_errno(r, "Operation failed: %m"); - goto finish; - } + if (r == -ESHUTDOWN) + return log_error_errno(r, "Unit file is masked."); + if (r < 0) + return log_error_errno(r, "Operation failed: %m"); if (!arg_quiet) dump_unit_file_changes(changes, n_changes); @@ -5634,7 +5553,7 @@ static int enable_unit(int argc, char *argv[], void *userdata) { r = acquire_bus(BUS_MANAGER, &bus); if (r < 0) - return r; + goto finish; new_args[0] = (char*) (streq(argv[0], "enable") ? "start" : "stop"); for (i = 0; i < n_changes; i++) @@ -5680,7 +5599,8 @@ static int add_dependency(int argc, char *argv[], void *userdata) { unsigned n_changes = 0; r = unit_file_add_dependency(arg_scope, arg_runtime, arg_root, names, target, dep, arg_force, &changes, &n_changes); - + if (r == -ESHUTDOWN) + return log_error_errno(r, "Unit file is masked."); if (r < 0) return log_error_errno(r, "Can't add dependency: %m"); @@ -5817,8 +5737,8 @@ static int unit_is_enabled(int argc, char *argv[], void *userdata) { STRV_FOREACH(name, names) { UnitFileState state; - state = unit_file_get_state(arg_scope, arg_root, *name); - if (state < 0) + r = unit_file_get_state(arg_scope, arg_root, *name, &state); + if (r < 0) return log_error_errno(state, "Failed to get unit file state for %s: %m", *name); if (IN_SET(state, @@ -6362,9 +6282,6 @@ static void systemctl_help(void) { "Job Commands:\n" " list-jobs [PATTERN...] List jobs\n" " cancel [JOB...] Cancel all, one, or more jobs\n\n" - "Snapshot Commands:\n" - " snapshot [NAME] Create a snapshot\n" - " delete NAME... Remove one or more snapshots\n\n" "Environment Commands:\n" " show-environment Dump environment\n" " set-environment NAME=VALUE... Set one or more environment variables\n" @@ -6507,11 +6424,6 @@ static void help_states(void) { puts(slice_state_to_string(i)); if (!arg_no_legend) - puts("\nAvailable snapshot unit substates:"); - for (i = 0; i < _SNAPSHOT_STATE_MAX; i++) - puts(snapshot_state_to_string(i)); - - if (!arg_no_legend) puts("\nAvailable socket unit substates:"); for (i = 0; i < _SOCKET_STATE_MAX; i++) puts(socket_state_to_string(i)); @@ -6612,7 +6524,8 @@ static int systemctl_parse_argv(int argc, char *argv[]) { {} }; - int c; + const char *p; + int c, r; assert(argc >= 0); assert(argv); @@ -6632,15 +6545,19 @@ static int systemctl_parse_argv(int argc, char *argv[]) { return version(); case 't': { - const char *word, *state; - size_t size; + if (isempty(optarg)) + return log_error_errno(r, "--type requires arguments."); - FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) { - _cleanup_free_ char *type; + p = optarg; + for(;;) { + _cleanup_free_ char *type = NULL; - type = strndup(word, size); - if (!type) - return -ENOMEM; + r = extract_first_word(&p, &type, ",", 0); + if (r < 0) + return log_error_errno(r, "Failed to parse type: %s", optarg); + + if (r == 0) + break; if (streq(type, "help")) { help_types(); @@ -6681,18 +6598,21 @@ static int systemctl_parse_argv(int argc, char *argv[]) { if (!arg_properties) return log_oom(); } else { - const char *word, *state; - size_t size; + p = optarg; + for(;;) { + _cleanup_free_ char *prop = NULL; - FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) { - char *prop; + r = extract_first_word(&p, &prop, ",", 0); + if (r < 0) + return log_error_errno(r, "Failed to parse property: %s", optarg); - prop = strndup(word, size); - if (!prop) - return log_oom(); + if (r == 0) + break; - if (strv_consume(&arg_properties, prop) < 0) + if (strv_push(&arg_properties, prop) < 0) return log_oom(); + + prop = NULL; } } @@ -6769,7 +6689,9 @@ static int systemctl_parse_argv(int argc, char *argv[]) { break; case ARG_ROOT: - arg_root = optarg; + r = parse_path_argument_and_warn(optarg, true, &arg_root); + if (r < 0) + return r; break; case 'l': @@ -6856,15 +6778,19 @@ static int systemctl_parse_argv(int argc, char *argv[]) { break; case ARG_STATE: { - const char *word, *state; - size_t size; + if (isempty(optarg)) + return log_error_errno(r, "--signal requires arguments."); - FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) { + p = optarg; + for(;;) { _cleanup_free_ char *s = NULL; - s = strndup(word, size); - if (!s) - return log_oom(); + r = extract_first_word(&p, &s, ",", 0); + if (r < 0) + return log_error_errno(r, "Failed to parse signal: %s", optarg); + + if (r == 0) + break; if (streq(s, "help")) { help_states(); @@ -7399,14 +7325,14 @@ static int talk_initctl(void) { static int systemctl_main(int argc, char *argv[]) { static const Verb verbs[] = { - { "list-units", VERB_ANY, 1, VERB_DEFAULT, list_units }, - { "list-unit-files", VERB_ANY, 1, 0, list_unit_files }, - { "list-sockets", VERB_ANY, 1, 0, list_sockets }, - { "list-timers", VERB_ANY, 1, 0, list_timers }, - { "list-jobs", VERB_ANY, 1, 0, list_jobs }, - { "list-machines", VERB_ANY, 1, 0, list_machines }, + { "list-units", VERB_ANY, VERB_ANY, VERB_DEFAULT, list_units }, + { "list-unit-files", VERB_ANY, VERB_ANY, 0, list_unit_files }, + { "list-sockets", VERB_ANY, VERB_ANY, 0, list_sockets }, + { "list-timers", VERB_ANY, VERB_ANY, 0, list_timers }, + { "list-jobs", VERB_ANY, VERB_ANY, 0, list_jobs }, + { "list-machines", VERB_ANY, VERB_ANY, 0, list_machines }, { "clear-jobs", VERB_ANY, 1, 0, daemon_reload }, - { "cancel", 2, VERB_ANY, 0, cancel_job }, + { "cancel", VERB_ANY, VERB_ANY, 0, cancel_job }, { "start", 2, VERB_ANY, 0, start_unit }, { "stop", 2, VERB_ANY, 0, start_unit }, { "condstop", 2, VERB_ANY, 0, start_unit }, /* For compatibility with ALTLinux */ @@ -7427,8 +7353,6 @@ static int systemctl_main(int argc, char *argv[]) { { "cat", 2, VERB_ANY, 0, cat }, { "status", VERB_ANY, VERB_ANY, 0, show }, { "help", VERB_ANY, VERB_ANY, 0, show }, - { "snapshot", VERB_ANY, 2, 0, snapshot }, - { "delete", 2, VERB_ANY, 0, delete_snapshot }, { "daemon-reload", VERB_ANY, 1, 0, daemon_reload }, { "daemon-reexec", VERB_ANY, 1, 0, daemon_reload }, { "show-environment", VERB_ANY, 1, 0, show_environment }, @@ -7778,8 +7702,11 @@ finish: strv_free(arg_properties); strv_free(arg_wall); + free(arg_root); release_busses(); + /* Note that we return r here, not EXIT_SUCCESS, so that we can implement the LSB-like return codes */ + return r < 0 ? EXIT_FAILURE : r; } |