if (!n)
return log_oom();
- r = bus_method_call_with_reply (
+ r = bus_method_call_with_reply(
bus,
"org.freedesktop.systemd1",
"/org/freedesktop/systemd1",
return 0;
}
+static const struct {
+ const char *target;
+ const char *verb;
+ const char *mode;
+} action_table[_ACTION_MAX] = {
+ [ACTION_HALT] = { SPECIAL_HALT_TARGET, "halt", "replace-irreversibly" },
+ [ACTION_POWEROFF] = { SPECIAL_POWEROFF_TARGET, "poweroff", "replace-irreversibly" },
+ [ACTION_REBOOT] = { SPECIAL_REBOOT_TARGET, "reboot", "replace-irreversibly" },
+ [ACTION_KEXEC] = { SPECIAL_KEXEC_TARGET, "kexec", "replace-irreversibly" },
+ [ACTION_RUNLEVEL2] = { SPECIAL_RUNLEVEL2_TARGET, NULL, "isolate" },
+ [ACTION_RUNLEVEL3] = { SPECIAL_RUNLEVEL3_TARGET, NULL, "isolate" },
+ [ACTION_RUNLEVEL4] = { SPECIAL_RUNLEVEL4_TARGET, NULL, "isolate" },
+ [ACTION_RUNLEVEL5] = { SPECIAL_RUNLEVEL5_TARGET, NULL, "isolate" },
+ [ACTION_RESCUE] = { SPECIAL_RESCUE_TARGET, "rescue", "isolate" },
+ [ACTION_EMERGENCY] = { SPECIAL_EMERGENCY_TARGET, "emergency", "isolate" },
+ [ACTION_DEFAULT] = { SPECIAL_DEFAULT_TARGET, "default", "isolate" },
+ [ACTION_EXIT] = { SPECIAL_EXIT_TARGET, "exit", "replace-irreversibly" },
+ [ACTION_SUSPEND] = { SPECIAL_SUSPEND_TARGET, "suspend", "replace-irreversibly" },
+ [ACTION_HIBERNATE] = { SPECIAL_HIBERNATE_TARGET, "hibernate", "replace-irreversibly" },
+ [ACTION_HYBRID_SLEEP] = { SPECIAL_HYBRID_SLEEP_TARGET, "hybrid-sleep", "replace-irreversibly" },
+};
+
static enum action verb_to_action(const char *verb) {
- if (streq(verb, "halt"))
- return ACTION_HALT;
- else if (streq(verb, "poweroff"))
- return ACTION_POWEROFF;
- else if (streq(verb, "reboot"))
- return ACTION_REBOOT;
- else if (streq(verb, "kexec"))
- return ACTION_KEXEC;
- else if (streq(verb, "rescue"))
- return ACTION_RESCUE;
- else if (streq(verb, "emergency"))
- return ACTION_EMERGENCY;
- else if (streq(verb, "default"))
- return ACTION_DEFAULT;
- else if (streq(verb, "exit"))
- return ACTION_EXIT;
- else if (streq(verb, "suspend"))
- return ACTION_SUSPEND;
- else if (streq(verb, "hibernate"))
- return ACTION_HIBERNATE;
- else if (streq(verb, "hybrid-sleep"))
- return ACTION_HYBRID_SLEEP;
- else
- return ACTION_INVALID;
+ enum action i;
+
+ for (i = ACTION_INVALID; i < _ACTION_MAX; i++)
+ if (action_table[i].verb && streq(verb, action_table[i].verb))
+ return i;
+ return ACTION_INVALID;
}
static int start_unit(DBusConnection *bus, char **args) {
- static const char * const table[_ACTION_MAX] = {
- [ACTION_HALT] = SPECIAL_HALT_TARGET,
- [ACTION_POWEROFF] = SPECIAL_POWEROFF_TARGET,
- [ACTION_REBOOT] = SPECIAL_REBOOT_TARGET,
- [ACTION_KEXEC] = SPECIAL_KEXEC_TARGET,
- [ACTION_RUNLEVEL2] = SPECIAL_RUNLEVEL2_TARGET,
- [ACTION_RUNLEVEL3] = SPECIAL_RUNLEVEL3_TARGET,
- [ACTION_RUNLEVEL4] = SPECIAL_RUNLEVEL4_TARGET,
- [ACTION_RUNLEVEL5] = SPECIAL_RUNLEVEL5_TARGET,
- [ACTION_RESCUE] = SPECIAL_RESCUE_TARGET,
- [ACTION_EMERGENCY] = SPECIAL_EMERGENCY_TARGET,
- [ACTION_DEFAULT] = SPECIAL_DEFAULT_TARGET,
- [ACTION_EXIT] = SPECIAL_EXIT_TARGET,
- [ACTION_SUSPEND] = SPECIAL_SUSPEND_TARGET,
- [ACTION_HIBERNATE] = SPECIAL_HIBERNATE_TARGET,
- [ACTION_HYBRID_SLEEP] = SPECIAL_HYBRID_SLEEP_TARGET
- };
-
int r, ret = 0;
const char *method, *mode, *one_name;
Set _cleanup_set_free_free_ *s = NULL;
ask_password_agent_open_if_enabled();
if (arg_action == ACTION_SYSTEMCTL) {
+ enum action action;
method =
streq(args[0], "stop") ||
streq(args[0], "condstop") ? "StopUnit" :
streq(args[0], "force-reload") ? "ReloadOrTryRestartUnit" :
"StartUnit";
+ action = verb_to_action(args[0]);
- mode =
- (streq(args[0], "isolate") ||
- streq(args[0], "rescue") ||
- streq(args[0], "emergency")) ? "isolate" : arg_job_mode;
+ mode = streq(args[0], "isolate") ? "isolate" :
+ action_table[action].mode ?: arg_job_mode;
- one_name = table[verb_to_action(args[0])];
+ one_name = action_table[action].target;
} else {
- assert(arg_action < ELEMENTSOF(table));
- assert(table[arg_action]);
+ assert(arg_action < ELEMENTSOF(action_table));
+ assert(action_table[arg_action].target);
method = "StartUnit";
- mode = (arg_action == ACTION_EMERGENCY ||
- arg_action == ACTION_RESCUE ||
- arg_action == ACTION_RUNLEVEL2 ||
- arg_action == ACTION_RUNLEVEL3 ||
- arg_action == ACTION_RUNLEVEL4 ||
- arg_action == ACTION_RUNLEVEL5) ? "isolate" : "replace";
-
- one_name = table[arg_action];
+ mode = action_table[arg_action].mode;
+ one_name = action_table[arg_action].target;
}
if (!arg_no_block) {
return 0;
log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'systemctl %s -i'.",
- a == ACTION_HALT ? "halt" :
- a == ACTION_POWEROFF ? "poweroff" :
- a == ACTION_REBOOT ? "reboot" :
- a == ACTION_KEXEC ? "kexec" :
- a == ACTION_SUSPEND ? "suspend" :
- a == ACTION_HIBERNATE ? "hibernate" : "hybrid-sleep");
+ action_table[a].verb);
return -EPERM;
#else
}
static int set_cgroup(DBusConnection *bus, char **args) {
- _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
- DBusError error;
- const char *method;
- DBusMessageIter iter;
- int r;
_cleanup_free_ char *n = NULL;
- const char *runtime;
+ const char *method, *runtime;
+ char **argument;
+ int r;
assert(bus);
assert(args);
- dbus_error_init(&error);
-
method =
- streq(args[0], "set-cgroup") ? "SetUnitControlGroups" :
- streq(args[0], "unset-group") ? "UnsetUnitControlGroups"
- : "UnsetUnitControlGroupAttributes";
+ streq(args[0], "set-cgroup") ? "SetUnitControlGroup" :
+ streq(args[0], "unset-cgroup") ? "UnsetUnitControlGroup"
+ : "UnsetUnitControlGroupAttribute";
+
+ runtime = arg_runtime ? "runtime" : "persistent";
n = unit_name_mangle(args[1]);
if (!n)
return log_oom();
- m = dbus_message_new_method_call(
- "org.freedesktop.systemd1",
- "/org/freedesktop/systemd1",
- "org.freedesktop.systemd1.Manager",
- method);
- if (!m)
- return log_oom();
-
- dbus_message_iter_init_append(m, &iter);
- if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &n))
- return log_oom();
+ STRV_FOREACH(argument, args + 2) {
- r = bus_append_strv_iter(&iter, args + 2);
- if (r < 0)
- return log_oom();
-
- runtime = arg_runtime ? "runtime" : "persistent";
- if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &runtime))
- 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));
- dbus_error_free(&error);
- return -EIO;
+ r = bus_method_call_with_reply(
+ bus,
+ "org.freedesktop.systemd1",
+ "/org/freedesktop/systemd1",
+ "org.freedesktop.systemd1.Manager",
+ method,
+ NULL,
+ NULL,
+ DBUS_TYPE_STRING, &n,
+ DBUS_TYPE_STRING, argument,
+ DBUS_TYPE_STRING, &runtime,
+ DBUS_TYPE_INVALID);
+ if (r < 0)
+ return r;
}
return 0;
static int set_cgroup_attr(DBusConnection *bus, char **args) {
_cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
DBusError error;
- DBusMessageIter iter, sub, sub2;
- char **x, **y;
+ DBusMessageIter iter;
_cleanup_free_ char *n = NULL;
const char *runtime;
+ int r;
assert(bus);
assert(args);
dbus_error_init(&error);
- if (strv_length(args) % 2 != 0) {
- log_error("Expecting an uneven number of arguments!");
- return -EINVAL;
- }
+ runtime = arg_runtime ? "runtime" : "persistent";
n = unit_name_mangle(args[1]);
if (!n)
"org.freedesktop.systemd1",
"/org/freedesktop/systemd1",
"org.freedesktop.systemd1.Manager",
- "SetUnitControlGroupAttributes");
+ "SetUnitControlGroupAttribute");
if (!m)
return log_oom();
dbus_message_iter_init_append(m, &iter);
if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &n) ||
- !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(ss)", &sub))
+ !dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &args[2]))
return log_oom();
- STRV_FOREACH_PAIR(x, y, args + 2) {
- if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
- !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, x) ||
- !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, y) ||
- !dbus_message_iter_close_container(&sub, &sub2))
- return log_oom();
- }
+ r = bus_append_strv_iter(&iter, args + 3);
+ if (r < 0)
+ return log_oom();
- runtime = arg_runtime ? "runtime" : "persistent";
- if (!dbus_message_iter_close_container(&iter, &sub) ||
- !dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &runtime))
+ if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &runtime))
return log_oom();
reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
static int get_cgroup_attr(DBusConnection *bus, char **args) {
_cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
- DBusError error;
- DBusMessageIter iter;
- int r;
_cleanup_free_ char *n = NULL;
- _cleanup_strv_free_ char **list = NULL;
- char **a;
+ char **argument;
+ int r;
assert(bus);
assert(args);
- dbus_error_init(&error);
-
n = unit_name_mangle(args[1]);
if (!n)
return log_oom();
- m = dbus_message_new_method_call(
- "org.freedesktop.systemd1",
- "/org/freedesktop/systemd1",
- "org.freedesktop.systemd1.Manager",
- "GetUnitControlGroupAttributes");
- if (!m)
- return log_oom();
-
- dbus_message_iter_init_append(m, &iter);
- if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &n))
- return log_oom();
+ STRV_FOREACH(argument, args + 2) {
+ _cleanup_strv_free_ char **list = NULL;
+ DBusMessageIter iter;
+ char **a;
- r = bus_append_strv_iter(&iter, args + 2);
- if (r < 0)
- return log_oom();
+ r = bus_method_call_with_reply(
+ bus,
+ "org.freedesktop.systemd1",
+ "/org/freedesktop/systemd1",
+ "org.freedesktop.systemd1.Manager",
+ "GetUnitControlGroupAttribute",
+ &reply,
+ NULL,
+ DBUS_TYPE_STRING, &n,
+ DBUS_TYPE_STRING, argument,
+ DBUS_TYPE_INVALID);
+ if (r < 0)
+ return r;
- 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));
- dbus_error_free(&error);
- return -EIO;
- }
+ if (!dbus_message_iter_init(reply, &iter)) {
+ log_error("Failed to initialize iterator.");
+ return -EIO;
+ }
- dbus_message_iter_init(reply, &iter);
- r = bus_parse_strv_iter(&iter, &list);
- if (r < 0) {
- log_error("Failed to parse value list.");
- return r;
- }
+ r = bus_parse_strv_iter(&iter, &list);
+ if (r < 0) {
+ log_error("Failed to parse value list.");
+ return r;
+ }
- STRV_FOREACH(a, list) {
- if (endswith(*a, "\n"))
- fputs(*a, stdout);
- else
- puts(*a);
+ STRV_FOREACH(a, list) {
+ if (endswith(*a, "\n"))
+ fputs(*a, stdout);
+ else
+ puts(*a);
+ }
}
return 0;
}
if (carries_install_info == 0)
- log_warning(
-"The unit files have no [Install] section. They are not meant to be enabled\n"
-"using systemctl.\n"
-"Possible reasons for having this kind of units are:\n"
-"1) A unit may be statically enabled by being symlinked from another unit's\n"
-" .wants/ or .requires/ directory.\n"
-"2) A unit's purpose may be to act as a helper for some other unit which has\n"
-" a requirement dependency on it.\n"
-"3) A unit may be started when needed via activation (socket, path, timer,\n"
-" D-Bus, udev, scripted systemctl call, ...).\n");
+ log_warning("The unit files have no [Install] section. They are not meant to be enabled\n"
+ "using systemctl.\n"
+ "Possible reasons for having this kind of units are:\n"
+ "1) A unit may be statically enabled by being symlinked from another unit's\n"
+ " .wants/ or .requires/ directory.\n"
+ "2) A unit's purpose may be to act as a helper for some other unit which has\n"
+ " a requirement dependency on it.\n"
+ "3) A unit may be started when needed via activation (socket, path, timer,\n"
+ " D-Bus, udev, scripted systemctl call, ...).\n");
finish:
unit_file_changes_free(changes, n_changes);
enum {
ARG_FAIL = 0x100,
+ ARG_IRREVERSIBLE,
ARG_IGNORE_DEPENDENCIES,
ARG_VERSION,
ARG_USER,
{ "failed", no_argument, NULL, ARG_FAILED },
{ "full", no_argument, NULL, ARG_FULL },
{ "fail", no_argument, NULL, ARG_FAIL },
+ { "irreversible", no_argument, NULL, ARG_IRREVERSIBLE },
{ "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES },
{ "ignore-inhibitors", no_argument, NULL, 'i' },
{ "user", no_argument, NULL, ARG_USER },
arg_job_mode = "fail";
break;
+ case ARG_IRREVERSIBLE:
+ arg_job_mode = "replace-irreversibly";
+ break;
+
case ARG_IGNORE_DEPENDENCIES:
arg_job_mode = "ignore-dependencies";
break;
{ "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
{ "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
{ "isolate", EQUAL, 2, start_unit },
- { "set-cgroup", MORE, 2, set_cgroup },
- { "unset-cgroup", MORE, 2, set_cgroup },
- { "get-cgroup-attr", MORE, 2, get_cgroup_attr },
- { "set-cgroup-attr", MORE, 2, set_cgroup_attr },
- { "unset-cgroup-attr", MORE, 2, set_cgroup },
+ { "set-cgroup", MORE, 3, set_cgroup },
+ { "unset-cgroup", MORE, 3, set_cgroup },
+ { "get-cgroup-attr", MORE, 3, get_cgroup_attr },
+ { "set-cgroup-attr", MORE, 4, set_cgroup_attr },
+ { "unset-cgroup-attr", MORE, 3, set_cgroup },
{ "kill", MORE, 2, kill_unit },
{ "is-active", MORE, 2, check_unit_active },
{ "check", MORE, 2, check_unit_active },