X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Fsystemctl%2Fsystemctl.c;h=3e4cefec7689d5784ec54b91906a640aff0253e3;hp=e6bd855c15eb2b0501e193c93d73fe6bafe368ed;hb=7085053a437456ab87d726f3697002dd811fdf7a;hpb=571bfc6c56962dfc926e9bbc1600c511fc8565d1;ds=sidebyside diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index e6bd855c1..3e4cefec7 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -129,7 +129,8 @@ static enum transport { TRANSPORT_SSH, TRANSPORT_POLKIT } arg_transport = TRANSPORT_NORMAL; -static const char *arg_host = NULL; +static char *arg_host = NULL; +static char *arg_user = NULL; static unsigned arg_lines = 10; static OutputMode arg_output = OUTPUT_SHORT; static bool arg_plain = false; @@ -1177,6 +1178,59 @@ static int list_dependencies(DBusConnection *bus, char **args) { return list_dependencies_one(bus, u, 0, &units, 0); } +static int get_default(DBusConnection *bus, char **args) { + char *path = NULL; + _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL; + int r; + _cleanup_dbus_error_free_ DBusError error; + + dbus_error_init(&error); + + if (!bus || avoid_bus()) { + r = unit_file_get_default(arg_scope, arg_root, &path); + + if (r < 0) { + log_error("Operation failed: %s", strerror(-r)); + goto finish; + } + + r = 0; + } else { + r = bus_method_call_with_reply( + bus, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "GetDefaultTarget", + &reply, + NULL, + DBUS_TYPE_INVALID); + + if (r < 0) { + log_error("Operation failed: %s", strerror(-r)); + goto finish; + } + + if (!dbus_message_get_args(reply, &error, + DBUS_TYPE_STRING, &path, + DBUS_TYPE_INVALID)) { + log_error("Failed to parse reply: %s", bus_error_message(&error)); + dbus_error_free(&error); + return -EIO; + } + } + + if (path) + printf("%s\n", path); + +finish: + if ((!bus || avoid_bus()) && path) + free(path); + + return r; + +} + struct job_info { uint32_t id; char *name, *type, *state; @@ -1860,8 +1914,8 @@ static int start_unit_one( } if (need_daemon_reload(bus, n)) - log_warning("Warning: Unit file of %s changed on disk, 'systemctl %s daemon-reload' recommended.", - n, arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user"); + log_warning("Warning: Unit file of %s changed on disk, 'systemctl %sdaemon-reload' recommended.", + n, arg_scope == UNIT_FILE_SYSTEM ? "" : "--user "); if (s) { char *p; @@ -2647,20 +2701,10 @@ static void print_status_info(UnitStatusInfo *i) { on_tty() * OUTPUT_COLOR | !arg_quiet * OUTPUT_WARN_CUTOFF | arg_full * OUTPUT_FULL_WIDTH; - int maxlen = 8; /* a value that'll suffice most of the time */ char **t, **t2; assert(i); - STRV_FOREACH_PAIR(t, t2, i->listen) - maxlen = MAX(maxlen, (int)(sizeof("Listen") - 1 + strlen(*t))); - if (i->accept) - maxlen = MAX(maxlen, (int)sizeof("Accept") - 1); - if (i->main_pid > 0) - maxlen = MAX(maxlen, (int)sizeof("Main PID") - 1); - else if (i->control_pid > 0) - maxlen = MAX(maxlen, (int)sizeof("Control") - 1); - /* This shows pretty information about a unit. See * print_property() for a low-level property printer */ @@ -2672,7 +2716,7 @@ static void print_status_info(UnitStatusInfo *i) { printf("\n"); if (i->following) - printf(" %*s: unit currently follows state of %s\n", maxlen, "Follow", i->following); + printf(" Follow: unit currently follows state of %s\n", i->following); if (streq_ptr(i->load_state, "error")) { on = ansi_highlight_red(true); @@ -2683,17 +2727,17 @@ static void print_status_info(UnitStatusInfo *i) { path = i->source_path ? i->source_path : i->fragment_path; if (i->load_error) - printf(" %*s: %s%s%s (Reason: %s)\n", - maxlen, "Loaded", on, strna(i->load_state), off, i->load_error); + printf(" Loaded: %s%s%s (Reason: %s)\n", + on, strna(i->load_state), off, i->load_error); else if (path && i->unit_file_state) - printf(" %*s: %s%s%s (%s; %s)\n", - maxlen, "Loaded", on, strna(i->load_state), off, path, i->unit_file_state); + printf(" Loaded: %s%s%s (%s; %s)\n", + on, strna(i->load_state), off, path, i->unit_file_state); else if (path) - printf(" %*s: %s%s%s (%s)\n", - maxlen, "Loaded", on, strna(i->load_state), off, path); + printf(" Loaded: %s%s%s (%s)\n", + on, strna(i->load_state), off, path); else - printf(" %*s: %s%s%s\n", - maxlen, "Loaded", on, strna(i->load_state), off); + printf(" Loaded: %s%s%s\n", + on, strna(i->load_state), off); if (!strv_isempty(i->dropin_paths)) { char ** dropin; @@ -2702,7 +2746,7 @@ static void print_status_info(UnitStatusInfo *i) { STRV_FOREACH(dropin, i->dropin_paths) { if (! dir || last) { - printf(" %*s ", maxlen, dir ? "" : "Drop-In:"); + printf(dir ? " " : " Drop-In: "); free(dir); @@ -2711,7 +2755,7 @@ static void print_status_info(UnitStatusInfo *i) { return; } - printf("%s\n %*s %s", dir, maxlen, "", + printf("%s\n %s", dir, draw_special_char(DRAW_TREE_RIGHT)); } @@ -2735,11 +2779,11 @@ static void print_status_info(UnitStatusInfo *i) { on = off = ""; if (ss) - printf(" %*s: %s%s (%s)%s", - maxlen, "Active", on, strna(i->active_state), ss, off); + printf(" Active: %s%s (%s)%s", + on, strna(i->active_state), ss, off); else - printf(" %*s: %s%s%s", - maxlen, "Active", on, strna(i->active_state), off); + printf(" Active: %s%s%s", + on, strna(i->active_state), off); if (!isempty(i->result) && !streq(i->result, "success")) printf(" (Result: %s)", i->result); @@ -2766,26 +2810,26 @@ static void print_status_info(UnitStatusInfo *i) { s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp); if (s1) - printf(" %*s start condition failed at %s; %s\n", maxlen, "", s2, s1); + printf(" start condition failed at %s; %s\n", s2, s1); else if (s2) - printf(" %*s start condition failed at %s\n", maxlen, "", s2); + printf(" start condition failed at %s\n", s2); } if (i->sysfs_path) - printf(" %*s: %s\n", maxlen, "Device", i->sysfs_path); + printf(" Device: %s\n", i->sysfs_path); if (i->where) - printf(" %*s: %s\n", maxlen, "Where", i->where); + printf(" Where: %s\n", i->where); if (i->what) - printf(" %*s: %s\n", maxlen, "What", i->what); + printf(" What: %s\n", i->what); STRV_FOREACH(t, i->documentation) - printf(" %*s %s\n", maxlen+1, t == i->documentation ? "Docs:" : "", *t); + printf(" %*s %s\n", 9, t == i->documentation ? "Docs:" : "", *t); STRV_FOREACH_PAIR(t, t2, i->listen) - printf(" %*s %s (%s)\n", maxlen+1, t == i->listen ? "Listen:" : "", *t2, *t); + printf(" %*s %s (%s)\n", 9, t == i->listen ? "Listen:" : "", *t2, *t); if (i->accept) - printf(" %*s: %u; Connected: %u\n", maxlen, "Accepted", i->n_accepted, i->n_connections); + printf(" Accepted: %u; Connected: %u\n", i->n_accepted, i->n_connections); LIST_FOREACH(exec, p, i->exec) { _cleanup_free_ char *argv = NULL; @@ -2796,7 +2840,7 @@ static void print_status_info(UnitStatusInfo *i) { continue; argv = strv_join(p->argv, " "); - printf(" %*s: %u %s=%s ", maxlen, "Process", p->pid, p->name, strna(argv)); + printf(" Process: %u %s=%s ", p->pid, p->name, strna(argv)); good = is_clean_exit_lsb(p->code, p->status, NULL); if (!good) { @@ -2833,7 +2877,7 @@ static void print_status_info(UnitStatusInfo *i) { if (i->main_pid > 0 || i->control_pid > 0) { if (i->main_pid > 0) { - printf(" %*s: %u", maxlen, "Main PID", (unsigned) i->main_pid); + printf(" Main PID: %u", (unsigned) i->main_pid); if (i->running) { _cleanup_free_ char *comm = NULL; @@ -2864,7 +2908,7 @@ static void print_status_info(UnitStatusInfo *i) { if (i->control_pid > 0) { _cleanup_free_ char *c = NULL; - printf(" %*s: %u", i->main_pid ? 0 : maxlen, "Control", (unsigned) i->control_pid); + printf(" %8s: %u", i->main_pid ? "" : " Control", (unsigned) i->control_pid); get_process_comm(i->control_pid, &c); if (c) @@ -2875,20 +2919,18 @@ static void print_status_info(UnitStatusInfo *i) { } if (i->status_text) - printf(" %*s: \"%s\"\n", maxlen, "Status", i->status_text); + printf(" Status: \"%s\"\n", i->status_text); if (i->default_control_group && (i->main_pid > 0 || i->control_pid > 0 || cg_is_empty_by_spec(i->default_control_group, false) == 0)) { unsigned c; - printf(" %*s: %s\n", maxlen, "CGroup", i->default_control_group); + printf(" CGroup: %s\n", i->default_control_group); if (arg_transport != TRANSPORT_SSH) { unsigned k = 0; pid_t extra[2]; - char prefix[maxlen + 4]; - memset(prefix, ' ', sizeof(prefix) - 1); - prefix[sizeof(prefix) - 1] = '\0'; + char prefix[] = " "; c = columns(); if (c > sizeof(prefix) - 1) @@ -2921,10 +2963,10 @@ static void print_status_info(UnitStatusInfo *i) { } if (i->need_daemon_reload) - printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %s daemon-reload' recommended.\n", + printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %sdaemon-reload' recommended.\n", ansi_highlight_red(true), ansi_highlight_red(false), - arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user"); + arg_scope == UNIT_FILE_SYSTEM ? "" : "--user "); } static void show_unit_help(UnitStatusInfo *i) { @@ -4221,24 +4263,30 @@ static int enable_unit(DBusConnection *bus, char **args) { if (!args[1]) return 0; + r = mangle_names(args+1, &mangled_names); + if (r < 0) + goto finish; + if (!bus || avoid_bus()) { if (streq(verb, "enable")) { - r = unit_file_enable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes); + r = unit_file_enable(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes); carries_install_info = r; } else if (streq(verb, "disable")) - r = unit_file_disable(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes); + r = unit_file_disable(arg_scope, arg_runtime, arg_root, mangled_names, &changes, &n_changes); else if (streq(verb, "reenable")) { - r = unit_file_reenable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes); + r = unit_file_reenable(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes); carries_install_info = r; } else if (streq(verb, "link")) - r = unit_file_link(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes); + r = unit_file_link(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes); else if (streq(verb, "preset")) { - r = unit_file_preset(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes); + r = unit_file_preset(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes); carries_install_info = r; } else if (streq(verb, "mask")) - r = unit_file_mask(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes); + r = unit_file_mask(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes); else if (streq(verb, "unmask")) - r = unit_file_unmask(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes); + r = unit_file_unmask(arg_scope, arg_runtime, arg_root, mangled_names, &changes, &n_changes); + else if (streq(verb, "set-default")) + r = unit_file_set_default(arg_scope, arg_root, args[1], &changes, &n_changes); else assert_not_reached("Unknown verb"); @@ -4282,6 +4330,8 @@ static int enable_unit(DBusConnection *bus, char **args) { else if (streq(verb, "unmask")) { method = "UnmaskUnitFiles"; send_force = false; + } else if (streq(verb, "set-default")) { + method = "SetDefaultTarget"; } else assert_not_reached("Unknown verb"); @@ -4297,10 +4347,6 @@ static int enable_unit(DBusConnection *bus, char **args) { dbus_message_iter_init_append(m, &iter); - r = mangle_names(args+1, &mangled_names); - if(r < 0) - goto finish; - r = bus_append_strv_iter(&iter, mangled_names); if (r < 0) { log_error("Failed to append unit files."); @@ -4405,6 +4451,51 @@ finish: return r; } +static int set_log_level(DBusConnection *bus, char **args) { + _cleanup_dbus_error_free_ DBusError error; + _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL; + DBusMessageIter iter, sub; + const char* property = "LogLevel"; + const char* interface = "org.freedesktop.systemd1.Manager"; + const char* value; + + assert(bus); + assert(args); + + value = args[1]; + dbus_error_init(&error); + + m = dbus_message_new_method_call("org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.DBus.Properties", + "Set"); + if (!m) + return log_oom(); + + dbus_message_iter_init_append(m, &iter); + + if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &interface) || + !dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &property) || + !dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT, "s", &sub)) + return log_oom(); + + if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &value)) { + dbus_message_iter_abandon_container(&iter, &sub); + return log_oom(); + } + + if (!dbus_message_iter_close_container(&iter, &sub)) + return log_oom(); + + reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error); + if (!reply) { + log_error("Failed to issue method call: %s", bus_error_message(&error)); + return -EIO; + } + + return 0; +} + static int unit_is_enabled(DBusConnection *bus, char **args) { _cleanup_dbus_error_free_ DBusError error; int r; @@ -4543,6 +4634,7 @@ static int systemctl_help(void) { " verbose, export, json, json-pretty, json-sse, cat)\n\n" "Unit Commands:\n" " list-units List loaded units\n" + " list-sockets List loaded sockets ordered by address\n" " start [NAME...] Start (activate) one or more units\n" " stop [NAME...] Stop (deactivate) one or more units\n" " reload [NAME...] Reload one or more units\n" @@ -4585,6 +4677,8 @@ static int systemctl_help(void) { " unmask [NAME...] Unmask one or more units\n" " link [PATH...] Link one or more units files into\n" " the search path\n" + " get-default Get the name of the default target\n" + " set-default NAME Set the default target\n" " is-enabled [NAME...] Check whether unit files are enabled\n\n" "Job Commands:\n" " list-jobs List jobs\n" @@ -4597,7 +4691,8 @@ static int systemctl_help(void) { "Environment Commands:\n" " show-environment Dump environment\n" " set-environment [NAME=VALUE...] Set one or more environment variables\n" - " unset-environment [NAME...] Unset one or more environment variables\n\n" + " unset-environment [NAME...] Unset one or more environment variables\n" + " set-log-level LEVEL Set logging threshold for systemd\n\n" "Manager Lifecycle Commands:\n" " daemon-reload Reload systemd manager configuration\n" " daemon-reexec Reexecute systemd manager\n\n" @@ -4971,7 +5066,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) { case 'H': arg_transport = TRANSPORT_SSH; - arg_host = optarg; + parse_user_at_host(optarg, &arg_user, &arg_host); break; case ARG_RUNTIME: @@ -5646,6 +5741,9 @@ static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError { "link", MORE, 2, enable_unit }, { "switch-root", MORE, 2, switch_root }, { "list-dependencies", LESS, 2, list_dependencies }, + { "set-default", EQUAL, 2, enable_unit }, + { "get-default", LESS, 1, get_default }, + { "set-log-level", EQUAL, 2, set_log_level }, }; int left; @@ -5717,7 +5815,9 @@ static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError !streq(verbs[i].verb, "preset") && !streq(verbs[i].verb, "mask") && !streq(verbs[i].verb, "unmask") && - !streq(verbs[i].verb, "link")) { + !streq(verbs[i].verb, "link") && + !streq(verbs[i].verb, "set-default") && + !streq(verbs[i].verb, "get-default")) { if (running_in_chroot() > 0) { log_info("Running in chroot, ignoring request."); @@ -5987,7 +6087,7 @@ int main(int argc, char*argv[]) { bus_connect_system_polkit(&bus, &error); private_bus = false; } else if (arg_transport == TRANSPORT_SSH) { - bus_connect_system_ssh(NULL, arg_host, &bus, &error); + bus_connect_system_ssh(arg_user, arg_host, &bus, &error); private_bus = false; } else assert_not_reached("Uh, invalid transport...");