#include <sys/reboot.h>
#include <stdio.h>
#include <getopt.h>
+#include <locale.h>
#include <stdbool.h>
#include <string.h>
#include <errno.h>
#include <systemd/sd-daemon.h>
#include <systemd/sd-shutdown.h>
+#include <systemd/sd-login.h>
#include "log.h"
#include "util.h"
static bool arg_no_wtmp = false;
static bool arg_no_wall = false;
static bool arg_no_reload = false;
+static bool arg_ignore_inhibitors = false;
static bool arg_dry = false;
static bool arg_quiet = false;
static bool arg_full = false;
return;
if (arg_wall) {
- char *p;
+ _cleanup_free_ char *p;
p = strv_join(arg_wall, " ");
if (!p) {
- log_error("Failed to join strings.");
+ log_oom();
return;
}
if (*p) {
utmp_wall(p, NULL);
- free(p);
return;
}
-
- free(p);
}
if (!table[a])
if (d1 && d2) {
int r;
- if ((r = strcasecmp(d1, d2)) != 0)
+ r = strcasecmp(d1, d2);
+ if (r != 0)
return r;
}
static void output_units_list(const struct unit_info *unit_infos, unsigned c) {
unsigned id_len, max_id_len, active_len, sub_len, job_len, desc_len, n_shown = 0;
const struct unit_info *u;
+ int job_count = 0;
max_id_len = sizeof("UNIT")-1;
active_len = sizeof("ACTIVE")-1;
max_id_len = MAX(max_id_len, strlen(u->id));
active_len = MAX(active_len, strlen(u->active_state));
sub_len = MAX(sub_len, strlen(u->sub_state));
- if (u->job_id != 0)
+ if (u->job_id != 0) {
job_len = MAX(job_len, strlen(u->job_type));
+ job_count++;
+ }
}
if (!arg_full) {
unsigned basic_len;
id_len = MIN(max_id_len, 25);
- basic_len = 5 + id_len + 6 + active_len + sub_len + job_len;
+ basic_len = 5 + id_len + 5 + active_len + sub_len;
+ if (job_count)
+ basic_len += job_len + 1;
if (basic_len < (unsigned) columns()) {
unsigned extra_len, incr;
extra_len = columns() - basic_len;
continue;
if (!n_shown && !arg_no_legend) {
- printf("%-*s %-6s %-*s %-*s %-*s ", id_len, "UNIT", "LOAD",
- active_len, "ACTIVE", sub_len, "SUB", job_len, "JOB");
+ printf("%-*s %-6s %-*s %-*s ", id_len, "UNIT", "LOAD",
+ active_len, "ACTIVE", sub_len, "SUB");
+ if (job_count)
+ printf("%-*s ", job_len, "JOB");
if (!arg_full && arg_no_pager)
printf("%.*s\n", desc_len, "DESCRIPTION");
else
e = arg_full ? NULL : ellipsize(u->id, id_len, 33);
- printf("%-*s %s%-6s%s %s%-*s %-*s%s %-*s ",
+ printf("%-*s %s%-6s%s %s%-*s %-*s%s %-*s",
id_len, e ? e : u->id,
on_loaded, u->load_state, off_loaded,
on_active, active_len, u->active_state,
sub_len, u->sub_state, off_active,
- job_len, u->job_id ? u->job_type : "");
+ job_count ? job_len + 1 : 0, u->job_id ? u->job_type : "");
if (!arg_full && arg_no_pager)
printf("%.*s\n", desc_len, u->description);
else
if (n_shown) {
printf("\nLOAD = Reflects whether the unit definition was properly loaded.\n"
"ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
- "SUB = The low-level unit activation state, values depend on unit type.\n"
- "JOB = Pending job for the unit.\n\n");
+ "SUB = The low-level unit activation state, values depend on unit type.\n");
+ if (job_count)
+ printf("JOB = Pending job for the unit.\n");
+ puts("");
on = ansi_highlight(true);
off = ansi_highlight(false);
} else {
}
static int list_units(DBusConnection *bus, char **args) {
- DBusMessage *reply = NULL;
- int r;
+ _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
+ _cleanup_free_ struct unit_info *unit_infos = NULL;
DBusMessageIter iter, sub, sub2;
unsigned c = 0, n_units = 0;
- struct unit_info *unit_infos = NULL;
+ int r;
pager_open_if_enabled();
- r = bus_method_call_with_reply (
+ r = bus_method_call_with_reply(
bus,
"org.freedesktop.systemd1",
"/org/freedesktop/systemd1",
&reply,
NULL,
DBUS_TYPE_INVALID);
- if (r)
- goto finish;
+ if (r < 0)
+ return r;
if (!dbus_message_iter_init(reply, &iter) ||
dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
log_error("Failed to parse reply.");
- r = -EIO;
- goto finish;
+ return -EIO;
}
dbus_message_iter_recurse(&iter, &sub);
while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
struct unit_info *u;
- if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
- log_error("Failed to parse reply.");
- r = -EIO;
- goto finish;
- }
+ assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT);
if (c >= n_units) {
struct unit_info *w;
n_units = MAX(2*c, 16);
w = realloc(unit_infos, sizeof(struct unit_info) * n_units);
-
- if (!w) {
- log_error("Failed to allocate unit array.");
- r = -ENOMEM;
- goto finish;
- }
+ if (!w)
+ return log_oom();
unit_infos = w;
}
- u = unit_infos+c;
+ u = unit_infos + c;
dbus_message_iter_recurse(&sub, &sub2);
bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->job_type, true) < 0 ||
bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &u->job_path, false) < 0) {
log_error("Failed to parse reply.");
- r = -EIO;
- goto finish;
+ return -EIO;
}
dbus_message_iter_next(&sub);
output_units_list(unit_infos, c);
}
-finish:
- if (reply)
- dbus_message_unref(reply);
-
- free(unit_infos);
-
- return r;
+ return 0;
}
static int compare_unit_file_list(const void *a, const void *b) {
}
static int list_unit_files(DBusConnection *bus, char **args) {
- DBusMessage *reply = NULL;
- int r;
+ _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
+ _cleanup_free_ UnitFileList *units = NULL;
DBusMessageIter iter, sub, sub2;
unsigned c = 0, n_units = 0;
- UnitFileList *units = NULL;
+ int r;
pager_open_if_enabled();
hashmap_free(h);
} else {
- r = bus_method_call_with_reply (
+ r = bus_method_call_with_reply(
bus,
"org.freedesktop.systemd1",
"/org/freedesktop/systemd1",
&reply,
NULL,
DBUS_TYPE_INVALID);
- if (r)
- goto finish;
+ if (r < 0)
+ return r;
if (!dbus_message_iter_init(reply, &iter) ||
dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
log_error("Failed to parse reply.");
- r = -EIO;
- goto finish;
+ return -EIO;
}
dbus_message_iter_recurse(&iter, &sub);
UnitFileList *u;
const char *state;
- if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
- log_error("Failed to parse reply.");
- r = -EIO;
- goto finish;
- }
+ assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT);
if (c >= n_units) {
UnitFileList *w;
n_units = MAX(2*c, 16);
w = realloc(units, sizeof(struct UnitFileList) * n_units);
-
- if (!w) {
- log_error("Failed to allocate unit array.");
- r = -ENOMEM;
- goto finish;
- }
+ if (!w)
+ return log_oom();
units = w;
}
- u = units+c;
+ u = units + c;
dbus_message_iter_recurse(&sub, &sub2);
if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->path, true) < 0 ||
bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &state, false) < 0) {
log_error("Failed to parse reply.");
- r = -EIO;
- goto finish;
+ return -EIO;
}
u->state = unit_file_state_from_string(state);
output_unit_file_list(units, c);
}
- r = 0;
+ return 0;
+}
+
+static int list_dependencies_print(const char *name, int level, unsigned int branches, bool last) {
+ int i;
+ _cleanup_free_ char *n = NULL;
+ size_t len = 0;
+ size_t max_len = MAX(columns(),20);
+
+ for (i = level - 1; i >= 0; i--) {
+ len += 2;
+ if(len > max_len - 3 && !arg_full) {
+ printf("%s...\n",max_len % 2 ? "" : " ");
+ return 0;
+ }
+ printf("%s", draw_special_char(branches & (1 << i) ? DRAW_TREE_VERT : DRAW_TREE_SPACE));
+ }
+ len += 2;
+ if(len > max_len - 3 && !arg_full) {
+ printf("%s...\n",max_len % 2 ? "" : " ");
+ return 0;
+ }
+ printf("%s", draw_special_char(last ? DRAW_TREE_RIGHT : DRAW_TREE_BRANCH));
+
+ if(arg_full){
+ printf("%s\n", name);
+ return 0;
+ }
+
+ n = ellipsize(name, max_len-len, 100);
+ if(!n)
+ return log_oom();
+
+ printf("%s\n", n);
+ return 0;
+}
+
+static int list_dependencies_get_dependencies(DBusConnection *bus, const char *name, char ***deps) {
+ static const char dependencies[] =
+ "Requires\0"
+ "RequiresOverridable\0"
+ "Requisite\0"
+ "RequisiteOverridable\0"
+ "Wants\0";
+
+ _cleanup_free_ char *path;
+ const char *interface = "org.freedesktop.systemd1.Unit";
+
+ _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
+ DBusMessageIter iter, sub, sub2, sub3;
+
+ int r = 0;
+ char **ret = NULL;
+
+ assert(bus);
+ assert(name);
+ assert(deps);
+
+ path = unit_dbus_path_from_name(name);
+ if (path == NULL) {
+ r = -EINVAL;
+ goto finish;
+ }
+
+ r = bus_method_call_with_reply(
+ bus,
+ "org.freedesktop.systemd1",
+ path,
+ "org.freedesktop.DBus.Properties",
+ "GetAll",
+ &reply,
+ NULL,
+ DBUS_TYPE_STRING, &interface,
+ DBUS_TYPE_INVALID);
+ if (r < 0)
+ goto finish;
+
+ if (!dbus_message_iter_init(reply, &iter) ||
+ dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
+ dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
+ log_error("Failed to parse reply.");
+ r = -EIO;
+ goto finish;
+ }
+
+ dbus_message_iter_recurse(&iter, &sub);
+
+ while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
+ const char *prop;
+
+ assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_DICT_ENTRY);
+ dbus_message_iter_recurse(&sub, &sub2);
+
+ if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &prop, true) < 0) {
+ log_error("Failed to parse reply.");
+ r = -EIO;
+ goto finish;
+ }
+
+ if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
+ log_error("Failed to parse reply.");
+ r = -EIO;
+ goto finish;
+ }
+
+ dbus_message_iter_recurse(&sub2, &sub3);
+ dbus_message_iter_next(&sub);
+
+ if (!nulstr_contains(dependencies, prop))
+ continue;
+
+ if (dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_ARRAY) {
+ if (dbus_message_iter_get_element_type(&sub3) == DBUS_TYPE_STRING) {
+ DBusMessageIter sub4;
+ dbus_message_iter_recurse(&sub3, &sub4);
+ while (dbus_message_iter_get_arg_type(&sub4) != DBUS_TYPE_INVALID) {
+ const char *s;
+
+ assert(dbus_message_iter_get_arg_type(&sub4) == DBUS_TYPE_STRING);
+ dbus_message_iter_get_basic(&sub4, &s);
+
+ r = strv_extend(&ret, s);
+ if (r < 0) {
+ log_oom();
+ goto finish;
+ }
+
+ dbus_message_iter_next(&sub4);
+ }
+ }
+ }
+ }
finish:
- if (reply)
- dbus_message_unref(reply);
+ if (r < 0)
+ strv_free(ret);
+ else
+ *deps = ret;
+ return r;
+}
+
+static int list_dependencies_compare(const void *_a, const void *_b) {
+ const char **a = (const char**) _a, **b = (const char**) _b;
+ if (unit_name_to_type(*a) == UNIT_TARGET && unit_name_to_type(*b) != UNIT_TARGET)
+ return 1;
+ if (unit_name_to_type(*a) != UNIT_TARGET && unit_name_to_type(*b) == UNIT_TARGET)
+ return -1;
+ return strcasecmp(*a, *b);
+}
+
+static int list_dependencies_one(DBusConnection *bus, const char *name, int level, char **units, unsigned int branches) {
+ char **deps = NULL;
+ char **c;
+ char **u = NULL;
+ int r = 0;
+
+ u = strv_append(units, name);
+ if(!u)
+ return log_oom();
+
+ r = list_dependencies_get_dependencies(bus, name, &deps);
+ if (r < 0)
+ goto finish;
+
+ qsort(deps, strv_length(deps), sizeof (char*), list_dependencies_compare);
+
+ STRV_FOREACH(c, deps) {
+ if (strv_contains(u, *c)) {
+ r = list_dependencies_print("...", level + 1, (branches << 1) | (c[1] == NULL ? 0 : 1), 1);
+ if(r < 0)
+ goto finish;
+ continue;
+ }
+
+ r = list_dependencies_print(*c, level, branches, c[1] == NULL);
+ if(r < 0)
+ goto finish;
- free(units);
+ if (arg_all || unit_name_to_type(*c) == UNIT_TARGET) {
+ r = list_dependencies_one(bus, *c, level + 1, u, (branches << 1) | (c[1] == NULL ? 0 : 1));
+ if(r < 0)
+ goto finish;
+ }
+ }
+ r = 0;
+finish:
+ strv_free(deps);
+ strv_free(u);
return r;
}
+static int list_dependencies(DBusConnection *bus, char **args) {
+ _cleanup_free_ char *unit = NULL;
+ const char *u;
+
+ assert(bus);
+
+ if (args[1]) {
+ unit = unit_name_mangle(args[1]);
+ if (!unit)
+ return log_oom();
+ u = unit;
+ } else
+ u = SPECIAL_DEFAULT_TARGET;
+
+ pager_open_if_enabled();
+
+ puts(u);
+
+ return list_dependencies_one(bus, u, 0, NULL, 0);
+}
+
static int dot_one_property(const char *name, const char *prop, DBusMessageIter *iter) {
+
static const char * const colors[] = {
"Requires", "[color=\"black\"]",
"RequiresOverridable", "[color=\"black\"]",
}
static int dot_one(DBusConnection *bus, const char *name, const char *path) {
- DBusMessage *reply = NULL;
+ _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
const char *interface = "org.freedesktop.systemd1.Unit";
int r;
DBusMessageIter iter, sub, sub2, sub3;
+ assert(bus);
assert(path);
- r = bus_method_call_with_reply (
+ r = bus_method_call_with_reply(
bus,
"org.freedesktop.systemd1",
path,
NULL,
DBUS_TYPE_STRING, &interface,
DBUS_TYPE_INVALID);
- if (r)
- goto finish;
+ if (r < 0)
+ return r;
if (!dbus_message_iter_init(reply, &iter) ||
dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
log_error("Failed to parse reply.");
- r = -EIO;
- goto finish;
+ return -EIO;
}
dbus_message_iter_recurse(&iter, &sub);
while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
const char *prop;
- if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_DICT_ENTRY) {
- log_error("Failed to parse reply.");
- r = -EIO;
- goto finish;
- }
-
+ assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_DICT_ENTRY);
dbus_message_iter_recurse(&sub, &sub2);
- if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &prop, true) < 0) {
- log_error("Failed to parse reply.");
- r = -EIO;
- goto finish;
- }
-
- if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
+ if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &prop, true) < 0 ||
+ dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
log_error("Failed to parse reply.");
- r = -EIO;
- goto finish;
+ return -EIO;
}
dbus_message_iter_recurse(&sub2, &sub3);
-
- if (dot_one_property(name, prop, &sub3)) {
- log_error("Failed to parse reply.");
- r = -EIO;
- goto finish;
- }
+ r = dot_one_property(name, prop, &sub3);
+ if (r < 0)
+ return r;
dbus_message_iter_next(&sub);
}
-finish:
- if (reply)
- dbus_message_unref(reply);
-
- return r;
+ return 0;
}
static int dot(DBusConnection *bus, char **args) {
- DBusMessage *reply = NULL;
- int r;
+ _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
DBusMessageIter iter, sub, sub2;
+ int r;
- r = bus_method_call_with_reply (
+ r = bus_method_call_with_reply(
bus,
"org.freedesktop.systemd1",
"/org/freedesktop/systemd1",
&reply,
NULL,
DBUS_TYPE_INVALID);
- if (r)
- goto finish;
+ if (r < 0)
+ return r;
if (!dbus_message_iter_init(reply, &iter) ||
dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
log_error("Failed to parse reply.");
- r = -EIO;
- goto finish;
+ return -EIO;
}
printf("digraph systemd {\n");
if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
log_error("Failed to parse reply.");
- r = -EIO;
- goto finish;
+ return -EIO;
}
dbus_message_iter_recurse(&sub, &sub2);
bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &following, true) < 0 ||
bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &unit_path, true) < 0) {
log_error("Failed to parse reply.");
- r = -EIO;
- goto finish;
+ return -EIO;
}
- if ((r = dot_one(bus, id, unit_path)) < 0)
- goto finish;
+ r = dot_one(bus, id, unit_path);
+ if (r < 0)
+ return r;
/* printf("\t\"%s\";\n", id); */
dbus_message_iter_next(&sub);
log_notice("-- You probably want to process this output with graphviz' dot tool.\n"
"-- Try a shell pipeline like 'systemctl dot | dot -Tsvg > systemd.svg'!\n");
- r = 0;
-
-finish:
- if (reply)
- dbus_message_unref(reply);
-
- return r;
+ return 0;
}
static int list_jobs(DBusConnection *bus, char **args) {
- DBusMessage *reply = NULL;
- int r;
+ _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
DBusMessageIter iter, sub, sub2;
unsigned k = 0;
+ int r;
pager_open_if_enabled();
- r = bus_method_call_with_reply (
+ r = bus_method_call_with_reply(
bus,
"org.freedesktop.systemd1",
"/org/freedesktop/systemd1",
&reply,
NULL,
DBUS_TYPE_INVALID);
- if (r)
- goto finish;
+ if (r < 0)
+ return r;
if (!dbus_message_iter_init(reply, &iter) ||
dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
log_error("Failed to parse reply.");
- r = -EIO;
- goto finish;
+ return -EIO;
}
dbus_message_iter_recurse(&iter, &sub);
if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
log_error("Failed to parse reply.");
- r = -EIO;
- goto finish;
+ return -EIO;
}
dbus_message_iter_recurse(&sub, &sub2);
bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &job_path, true) < 0 ||
bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &unit_path, false) < 0) {
log_error("Failed to parse reply.");
- r = -EIO;
- goto finish;
+ return -EIO;
}
e = arg_full ? NULL : ellipsize(name, 25, 33);
if (on_tty())
printf("\n%u jobs listed.\n", k);
- r = 0;
-
-finish:
- if (reply)
- dbus_message_unref(reply);
-
- return r;
+ return 0;
}
static int load_unit(DBusConnection *bus, char **args) {
- int r = 0;
- char **name, *n;
+ char **name;
assert(args);
STRV_FOREACH(name, args+1) {
+ _cleanup_free_ char *n = NULL;
+ int r;
+
n = unit_name_mangle(*name);
- r = bus_method_call_with_reply (
+ if (!n)
+ return log_oom();
+
+ r = bus_method_call_with_reply(
bus,
"org.freedesktop.systemd1",
"/org/freedesktop/systemd1",
"LoadUnit",
NULL,
NULL,
- DBUS_TYPE_STRING, n ? &n : name,
+ DBUS_TYPE_STRING, &n,
DBUS_TYPE_INVALID);
- free(n);
- if (r)
- goto finish;
+ if (r < 0)
+ return r;
}
-finish:
- return r;
+ return 0;
}
static int cancel_job(DBusConnection *bus, char **args) {
- DBusMessage *reply = NULL;
- int r = 0;
char **name;
assert(args);
return daemon_reload(bus, args);
STRV_FOREACH(name, args+1) {
- unsigned id;
- const char *path;
+ uint32_t id;
+ int r;
- r = safe_atou(*name, &id);
+ r = safe_atou32(*name, &id);
if (r < 0) {
log_error("Failed to parse job id: %s", strerror(-r));
- goto finish;
+ return r;
}
- assert_cc(sizeof(uint32_t) == sizeof(id));
- r = bus_method_call_with_reply (
+ r = bus_method_call_with_reply(
bus,
"org.freedesktop.systemd1",
"/org/freedesktop/systemd1",
"org.freedesktop.systemd1.Manager",
- "GetJob",
- &reply,
- NULL,
- DBUS_TYPE_UINT32, &id,
- DBUS_TYPE_INVALID);
- if (r)
- goto finish;
-
- if (!dbus_message_get_args(reply, NULL,
- DBUS_TYPE_OBJECT_PATH, &path,
- DBUS_TYPE_INVALID)) {
- log_error("Failed to parse reply");
- dbus_message_unref(reply);
- r = -EIO;
- goto finish;
- }
- dbus_message_unref(reply);
-
- r = bus_method_call_with_reply (
- bus,
- "org.freedesktop.systemd1",
- path,
- "org.freedesktop.systemd1.Job",
- "Cancel",
+ "CancelJob",
NULL,
NULL,
+ DBUS_TYPE_UINT32, &id,
DBUS_TYPE_INVALID);
- if (r)
- goto finish;
+ if (r < 0)
+ return r;
}
-finish:
- return r;
+ return 0;
}
static bool need_daemon_reload(DBusConnection *bus, const char *unit) {
- DBusMessage *reply = NULL;
+ _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
dbus_bool_t b = FALSE;
DBusMessageIter iter, sub;
const char
*interface = "org.freedesktop.systemd1.Unit",
*property = "NeedDaemonReload",
*path;
- char *n;
+ _cleanup_free_ char *n = NULL;
int r;
/* We ignore all errors here, since this is used to show a warning only */
n = unit_name_mangle(unit);
+ if (!n)
+ return log_oom();
+
r = bus_method_call_with_reply (
bus,
"org.freedesktop.systemd1",
"GetUnit",
&reply,
NULL,
- DBUS_TYPE_STRING, n ? (const char**) &n : &unit,
+ DBUS_TYPE_STRING, &n,
DBUS_TYPE_INVALID);
- free(n);
- if (r)
- goto finish;
+ if (r < 0)
+ return r;
if (!dbus_message_get_args(reply, NULL,
DBUS_TYPE_OBJECT_PATH, &path,
DBUS_TYPE_INVALID))
- goto finish;
+ return -EIO;
dbus_message_unref(reply);
- r = bus_method_call_with_reply (
+ reply = NULL;
+
+ r = bus_method_call_with_reply(
bus,
"org.freedesktop.systemd1",
path,
DBUS_TYPE_STRING, &interface,
DBUS_TYPE_STRING, &property,
DBUS_TYPE_INVALID);
- if (r)
- goto finish;
+ if (r < 0)
+ return r;
if (!dbus_message_iter_init(reply, &iter) ||
dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
- goto finish;
+ return -EIO;
dbus_message_iter_recurse(&iter, &sub);
-
if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_BOOLEAN)
- goto finish;
+ return -EIO;
dbus_message_iter_get_basic(&sub, &b);
-
-finish:
- if (reply)
- dbus_message_unref(reply);
-
return b;
}
} else if (dbus_message_is_signal(message, "org.freedesktop.systemd1.Manager", "JobRemoved")) {
uint32_t id;
const char *path, *result, *unit;
- dbus_bool_t success = true;
if (dbus_message_get_args(message, &error,
DBUS_TYPE_UINT32, &id,
DBUS_TYPE_STRING, &unit,
DBUS_TYPE_STRING, &result,
DBUS_TYPE_INVALID)) {
- char *p;
- p = set_remove(d->set, (char*) path);
- free(p);
+ free(set_remove(d->set, (char*) path));
if (!isempty(result))
d->result = strdup(result);
DBUS_TYPE_OBJECT_PATH, &path,
DBUS_TYPE_STRING, &result,
DBUS_TYPE_INVALID)) {
- char *p;
-
/* Compatibility with older systemd versions <
* 183 during upgrades. This should be dropped
* one day. */
- p = set_remove(d->set, (char*) path);
- free(p);
+ free(set_remove(d->set, (char*) path));
if (*result)
d->result = strdup(result);
goto finish;
}
-
- dbus_error_free(&error);
- if (dbus_message_get_args(message, &error,
- DBUS_TYPE_UINT32, &id,
- DBUS_TYPE_OBJECT_PATH, &path,
- DBUS_TYPE_BOOLEAN, &success,
- DBUS_TYPE_INVALID)) {
- char *p;
-
- /* Compatibility with older systemd versions <
- * 19 during upgrades. This should be dropped
- * one day */
-
- p = set_remove(d->set, (char*) path);
- free(p);
-
- if (!success)
- d->result = strdup("failed");
-
- goto finish;
- }
#endif
log_error("Failed to parse message: %s", bus_error_message(&error));
else if (streq(d.result, "canceled"))
log_error("Job for %s canceled.", strna(d.name));
else if (streq(d.result, "dependency"))
- log_error("A dependency job for %s failed. See 'journalctl -n' for details.", strna(d.name));
+ log_error("A dependency job for %s failed. See 'journalctl -xn' for details.", strna(d.name));
else if (!streq(d.result, "done") && !streq(d.result, "skipped"))
- log_error("Job for %s failed. See 'systemctl status %s' and 'journalctl -n' for details.", strna(d.name), strna(d.name));
+ log_error("Job for %s failed. See 'systemctl status %s' and 'journalctl -xn' for details.", strna(d.name), strna(d.name));
}
if (streq_ptr(d.result, "timeout"))
return r;
}
-static int check_one_unit(DBusConnection *bus, char *name, bool quiet) {
- DBusMessage *reply = NULL;
+static int check_one_unit(DBusConnection *bus, const char *name, char **check_states, bool quiet) {
+ _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
+ _cleanup_free_ char *n = NULL;
DBusMessageIter iter, sub;
const char
*interface = "org.freedesktop.systemd1.Unit",
*property = "ActiveState";
- const char *path = NULL;
- const char *state;
+ const char *state, *path;
+ DBusError error;
int r;
- char *n;
assert(name);
+ dbus_error_init(&error);
+
n = unit_name_mangle(name);
+ if (!n)
+ return log_oom();
+
r = bus_method_call_with_reply (
bus,
"org.freedesktop.systemd1",
"org.freedesktop.systemd1.Manager",
"GetUnit",
&reply,
- NULL,
- DBUS_TYPE_STRING, n ? &n : &name,
+ &error,
+ DBUS_TYPE_STRING, &n,
DBUS_TYPE_INVALID);
- free(n);
- if (r) {
- if ((r != -ENOMEM) && (!quiet))
+ if (r < 0) {
+ dbus_error_free(&error);
+
+ if (!quiet)
puts("unknown");
- goto finish;
+ return 0;
}
if (!dbus_message_get_args(reply, NULL,
DBUS_TYPE_OBJECT_PATH, &path,
DBUS_TYPE_INVALID)) {
log_error("Failed to parse reply.");
- r = -EIO;
- goto finish;
+ return -EIO;
}
dbus_message_unref(reply);
- r = bus_method_call_with_reply (
+ reply = NULL;
+
+ r = bus_method_call_with_reply(
bus,
"org.freedesktop.systemd1",
path,
DBUS_TYPE_STRING, &interface,
DBUS_TYPE_STRING, &property,
DBUS_TYPE_INVALID);
- if (r)
- goto finish;
+ if (r < 0) {
+ if (!quiet)
+ puts("unknown");
+ return 0;
+ }
if (!dbus_message_iter_init(reply, &iter) ||
dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
log_error("Failed to parse reply.");
- r = -EIO;
- goto finish;
+ return r;
}
dbus_message_iter_recurse(&iter, &sub);
if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
log_error("Failed to parse reply.");
- r = -EIO;
- goto finish;
+ return r;
}
dbus_message_iter_get_basic(&sub, &state);
if (!quiet)
puts(state);
- if (streq(state, "active") || streq(state, "reloading"))
- r = 0;
- else
- r = 3; /* According to LSB: "program is not running" */
-
-finish:
- if (reply)
- dbus_message_unref(reply);
-
- return r;
+ return strv_find(check_states, state) ? 1 : 0;
}
static void check_triggering_units(
_cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
DBusMessageIter iter, sub;
- char *service_trigger = NULL;
const char *interface = "org.freedesktop.systemd1.Unit",
*triggered_by_property = "TriggeredBy";
-
char _cleanup_free_ *unit_path = NULL, *n = NULL;
bool print_warning_label = true;
int r;
return;
}
- r = bus_method_call_with_reply (
+ r = bus_method_call_with_reply(
bus,
"org.freedesktop.systemd1",
unit_path,
DBUS_TYPE_STRING, &interface,
DBUS_TYPE_STRING, &triggered_by_property,
DBUS_TYPE_INVALID);
- if (r)
+ if (r < 0)
return;
if (!dbus_message_iter_init(reply, &iter) ||
sub = iter;
while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
+ const char * const check_states[] = {
+ "active",
+ "reloading",
+ NULL
+ };
+ const char *service_trigger;
if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
log_error("Failed to parse reply.");
dbus_message_iter_get_basic(&sub, &service_trigger);
- r = check_one_unit(bus, service_trigger, true);
+ r = check_one_unit(bus, service_trigger, (char**) check_states, true);
if (r < 0)
return;
- if (r == 0) {
+ if (r > 0) {
if (print_warning_label) {
log_warning("Warning: Stopping %s, but it can still be activated by:", unit_name);
print_warning_label = false;
}
+
log_warning(" %s", service_trigger);
}
Set *s) {
_cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
+ _cleanup_free_ char *n;
const char *path;
int r;
- _cleanup_free_ char *n, *p = NULL;
assert(method);
assert(name);
n, arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
if (s) {
+ char *p;
+
p = strdup(path);
if (!p)
return log_oom();
r = set_put(s, p);
if (r < 0) {
+ free(p);
log_error("Failed to add path to set.");
return r;
}
-
- p = NULL;
}
return 0;
const char *method;
dbus_bool_t interactive = true;
+ if (!bus)
+ return -EIO;
+
polkit_agent_open_if_enabled();
switch (a) {
return -EINVAL;
}
- return bus_method_call_with_reply (
+ return bus_method_call_with_reply(
bus,
"org.freedesktop.login1",
"/org/freedesktop/login1",
#endif
}
+static int check_inhibitors(DBusConnection *bus, enum action a) {
+#ifdef HAVE_LOGIND
+ _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
+ DBusMessageIter iter, sub, sub2;
+ int r;
+ unsigned c = 0;
+ _cleanup_strv_free_ char **sessions = NULL;
+ char **s;
+
+ if (!bus)
+ return 0;
+
+ if (arg_ignore_inhibitors || arg_force > 0)
+ return 0;
+
+ if (arg_when > 0)
+ return 0;
+
+ if (geteuid() == 0)
+ return 0;
+
+ if (!on_tty())
+ return 0;
+
+ r = bus_method_call_with_reply(
+ bus,
+ "org.freedesktop.login1",
+ "/org/freedesktop/login1",
+ "org.freedesktop.login1.Manager",
+ "ListInhibitors",
+ &reply,
+ NULL,
+ DBUS_TYPE_INVALID);
+ if (r < 0)
+ /* If logind is not around, then there are no inhibitors... */
+ return 0;
+
+ if (!dbus_message_iter_init(reply, &iter) ||
+ dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
+ dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
+ log_error("Failed to parse reply.");
+ return -EIO;
+ }
+
+ dbus_message_iter_recurse(&iter, &sub);
+ while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
+ const char *what, *who, *why, *mode;
+ uint32_t uid, pid;
+ _cleanup_strv_free_ char **sv = NULL;
+ _cleanup_free_ char *comm = NULL, *user = NULL;
+
+ if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
+ log_error("Failed to parse reply.");
+ return -EIO;
+ }
+
+ dbus_message_iter_recurse(&sub, &sub2);
+
+ if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &what, true) < 0 ||
+ bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &who, true) < 0 ||
+ bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &why, true) < 0 ||
+ bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &mode, true) < 0 ||
+ bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &uid, true) < 0 ||
+ bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, false) < 0) {
+ log_error("Failed to parse reply.");
+ return -EIO;
+ }
+
+ if (!streq(mode, "block"))
+ goto next;
+
+ sv = strv_split(what, ":");
+ if (!sv)
+ return log_oom();
+
+ if (!strv_contains(sv,
+ a == ACTION_HALT ||
+ a == ACTION_POWEROFF ||
+ a == ACTION_REBOOT ||
+ a == ACTION_KEXEC ? "shutdown" : "sleep"))
+ goto next;
+
+ get_process_comm(pid, &comm);
+ user = uid_to_name(uid);
+ log_warning("Operation inhibited by \"%s\" (PID %lu \"%s\", user %s), reason is \"%s\".",
+ who, (unsigned long) pid, strna(comm), strna(user), why);
+ c++;
+
+ next:
+ dbus_message_iter_next(&sub);
+ }
+
+ dbus_message_iter_recurse(&iter, &sub);
+
+ /* Check for current sessions */
+ sd_get_sessions(&sessions);
+ STRV_FOREACH(s, sessions) {
+ uid_t uid;
+ _cleanup_free_ char *type = NULL, *tty = NULL, *seat = NULL, *user = NULL, *service = NULL, *class = NULL;
+
+ if (sd_session_get_uid(*s, &uid) < 0 || uid == getuid())
+ continue;
+
+ if (sd_session_get_class(*s, &class) < 0 || !streq(class, "user"))
+ continue;
+
+ if (sd_session_get_type(*s, &type) < 0 || (!streq(type, "x11") && !streq(type, "tty")))
+ continue;
+
+ sd_session_get_tty(*s, &tty);
+ sd_session_get_seat(*s, &seat);
+ sd_session_get_service(*s, &service);
+ user = uid_to_name(uid);
+
+ log_warning("User %s is logged in on %s.", strna(user), isempty(tty) ? (isempty(seat) ? strna(service) : seat) : tty);
+ c++;
+ }
+
+ if (c <= 0)
+ 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");
+
+ return -EPERM;
+#else
+ return 0;
+#endif
+}
+
static int start_special(DBusConnection *bus, char **args) {
enum action a;
int r;
a = verb_to_action(args[0]);
+ r = check_inhibitors(bus, a);
+ if (r < 0)
+ return r;
+
if (arg_force >= 2 && geteuid() != 0) {
log_error("Must be root.");
return -EPERM;
return r;
}
-static int check_unit(DBusConnection *bus, char **args) {
+static int check_unit_active(DBusConnection *bus, char **args) {
+ const char * const check_states[] = {
+ "active",
+ "reloading",
+ NULL
+ };
+
char **name;
int r = 3; /* According to LSB: "program is not running" */
assert(bus);
assert(args);
- STRV_FOREACH(name, args+1) {
- int state = check_one_unit(bus, *name, arg_quiet);
- if (state < 0)
- return state;
- if (state == 0)
- r = 0;
- }
+ STRV_FOREACH(name, args+1) {
+ int state;
+
+ state = check_one_unit(bus, *name, (char**) check_states, arg_quiet);
+ if (state < 0)
+ return state;
+ if (state > 0)
+ r = 0;
+ }
+
+ return r;
+}
+
+static int check_unit_failed(DBusConnection *bus, char **args) {
+ const char * const check_states[] = {
+ "failed",
+ NULL
+ };
+
+ char **name;
+ int r = 1;
+
+ assert(bus);
+ assert(args);
+
+ STRV_FOREACH(name, args+1) {
+ int state;
+
+ state = check_one_unit(bus, *name, (char**) check_states, arg_quiet);
+ if (state < 0)
+ return state;
+ if (state > 0)
+ r = 0;
+ }
+
+ return r;
+}
+
+static int kill_unit(DBusConnection *bus, char **args) {
+ char **name;
+ int r = 0;
+
+ assert(bus);
+ assert(args);
+
+ if (!arg_kill_who)
+ arg_kill_who = "all";
+
+ STRV_FOREACH(name, args+1) {
+ _cleanup_free_ char *n = NULL;
+
+ n = unit_name_mangle(*name);
+ if (!n)
+ return log_oom();
+
+ r = bus_method_call_with_reply(
+ bus,
+ "org.freedesktop.systemd1",
+ "/org/freedesktop/systemd1",
+ "org.freedesktop.systemd1.Manager",
+ "KillUnit",
+ NULL,
+ NULL,
+ DBUS_TYPE_STRING, &n,
+ DBUS_TYPE_STRING, &arg_kill_who,
+ DBUS_TYPE_INT32, &arg_signal,
+ DBUS_TYPE_INVALID);
+ if (r < 0)
+ return r;
+ }
+ return 0;
+}
+
+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;
+
+ assert(bus);
+ assert(args);
+
+ dbus_error_init(&error);
+
+ method =
+ streq(args[0], "set-cgroup") ? "SetUnitControlGroups" :
+ streq(args[0], "unset-group") ? "UnsetUnitControlGroups"
+ : "UnsetUnitControlGroupAttributes";
+
+ 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();
+
+ 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;
+ }
+
+ 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;
+ _cleanup_free_ char *n = NULL;
+ const char *runtime;
+
+ assert(bus);
+ assert(args);
+
+ dbus_error_init(&error);
+
+ if (strv_length(args) % 2 != 0) {
+ log_error("Expecting an uneven number of arguments!");
+ return -EINVAL;
+ }
+
+ 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",
+ "SetUnitControlGroupAttributes");
+ 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))
+ 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();
+ }
+
+ runtime = arg_runtime ? "runtime" : "persistent";
+ if (!dbus_message_iter_close_container(&iter, &sub) ||
+ !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;
+ }
+
+ return 0;
+}
+
+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;
+
+ assert(bus);
+ assert(args);
+
+ dbus_error_init(&error);
- return r;
-}
+ n = unit_name_mangle(args[1]);
+ if (!n)
+ return log_oom();
-static int kill_unit(DBusConnection *bus, char **args) {
- int r = 0;
- char **name, *n;
+ m = dbus_message_new_method_call(
+ "org.freedesktop.systemd1",
+ "/org/freedesktop/systemd1",
+ "org.freedesktop.systemd1.Manager",
+ "GetUnitControlGroupAttributes");
+ if (!m)
+ return log_oom();
- assert(args);
+ dbus_message_iter_init_append(m, &iter);
+ if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &n))
+ return log_oom();
- if (!arg_kill_who)
- arg_kill_who = "all";
+ r = bus_append_strv_iter(&iter, args + 2);
+ if (r < 0)
+ return log_oom();
- STRV_FOREACH(name, args+1) {
- n = unit_name_mangle(*name);
- r = bus_method_call_with_reply (
- bus,
- "org.freedesktop.systemd1",
- "/org/freedesktop/systemd1",
- "org.freedesktop.systemd1.Manager",
- "KillUnit",
- NULL,
- NULL,
- DBUS_TYPE_STRING, n ? &n : name,
- DBUS_TYPE_STRING, &arg_kill_who,
- DBUS_TYPE_INT32, &arg_signal,
- DBUS_TYPE_INVALID);
- free(n);
- if (r)
- 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;
+ }
+
+ 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;
+ }
+
+ STRV_FOREACH(a, list) {
+ if (endswith(*a, "\n"))
+ fputs(*a, stdout);
+ else
+ puts(*a);
}
+
return 0;
}
if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0)
return -EIO;
- if (!(i->path = strdup(path)))
+ i->path = strdup(path);
+ if (!i->path)
return -ENOMEM;
if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_ARRAY ||
n++;
}
-
- if (!(i->argv = new0(char*, n+1)))
+ i->argv = new0(char*, n+1);
+ if (!i->argv)
return -ENOMEM;
n = 0;
dbus_message_iter_get_basic(&sub3, &s);
dbus_message_iter_next(&sub3);
- if (!(i->argv[n++] = strdup(s)))
+ i->argv[n] = strdup(s);
+ if (!i->argv[n])
return -ENOMEM;
+
+ n++;
}
if (!dbus_message_iter_next(&sub2) ||
ExecStatusInfo *p;
const char *on, *off, *ss;
usec_t timestamp;
- char since1[FORMAT_TIMESTAMP_PRETTY_MAX], *s1;
+ char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
char since2[FORMAT_TIMESTAMP_MAX], *s2;
const char *path;
+ int flags =
+ arg_all * OUTPUT_SHOW_ALL |
+ (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
+ on_tty() * OUTPUT_COLOR |
+ !arg_quiet * OUTPUT_WARN_CUTOFF |
+ arg_full * OUTPUT_FULL_WIDTH;
assert(i);
streq_ptr(i->active_state, "activating") ? i->inactive_exit_timestamp :
i->active_exit_timestamp;
- s1 = format_timestamp_pretty(since1, sizeof(since1), timestamp);
+ s1 = format_timestamp_relative(since1, sizeof(since1), timestamp);
s2 = format_timestamp(since2, sizeof(since2), timestamp);
if (s1)
printf("\n");
if (!i->condition_result && i->condition_timestamp > 0) {
- s1 = format_timestamp_pretty(since1, sizeof(since1), i->condition_timestamp);
+ s1 = format_timestamp_relative(since1, sizeof(since1), i->condition_timestamp);
s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
if (s1)
printf("\tAccepted: %u; Connected: %u\n", i->n_accepted, i->n_connections);
LIST_FOREACH(exec, p, i->exec) {
- char *t;
+ _cleanup_free_ char *t = NULL;
bool good;
/* Only show exited processes here */
t = strv_join(p->argv, " ");
printf("\t Process: %u %s=%s ", p->pid, p->name, strna(t));
- free(t);
good = is_clean_exit_lsb(p->code, p->status, NULL);
if (!good) {
printf("Main PID: %u", (unsigned) i->main_pid);
if (i->running) {
- char *t = NULL;
+ _cleanup_free_ char *t = NULL;
get_process_comm(i->main_pid, &t);
- if (t) {
+ if (t)
printf(" (%s)", t);
- free(t);
- }
} else if (i->exit_code > 0) {
printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
printf(";");
if (i->control_pid > 0) {
- char *t = NULL;
+ _cleanup_free_ char *t = NULL;
printf(" Control: %u", (unsigned) i->control_pid);
get_process_comm(i->control_pid, &t);
- if (t) {
+ if (t)
printf(" (%s)", t);
- free(t);
- }
}
printf("\n");
if (i->status_text)
printf("\t Status: \"%s\"\n", i->status_text);
- if (i->default_control_group) {
+ 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("\t CGroup: %s\n", i->default_control_group);
if (i->control_pid > 0)
extra[k++] = i->control_pid;
- show_cgroup_and_extra_by_spec(i->default_control_group, "\t\t ", c, false, arg_all, extra, k);
+ show_cgroup_and_extra_by_spec(i->default_control_group, "\t\t ", c, false, extra, k, flags);
}
}
if (i->id && arg_transport != TRANSPORT_SSH) {
- int flags =
- arg_all * OUTPUT_SHOW_ALL |
- (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
- on_tty() * OUTPUT_COLOR |
- !arg_quiet * OUTPUT_WARN_CUTOFF;
-
printf("\n");
- show_journal_by_unit(stdout,
- i->id,
- arg_output,
- 0,
- i->inactive_exit_timestamp_monotonic,
- arg_lines,
- flags);
+ if(arg_scope == UNIT_FILE_SYSTEM)
+ show_journal_by_unit(stdout,
+ i->id,
+ arg_output,
+ 0,
+ i->inactive_exit_timestamp_monotonic,
+ arg_lines,
+ flags);
+ else
+ show_journal_by_user_unit(stdout,
+ i->id,
+ arg_output,
+ 0,
+ i->inactive_exit_timestamp_monotonic,
+ arg_lines,
+ getuid(),
+ flags);
}
if (i->need_daemon_reload)
bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &attr, true) >= 0 &&
bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &value, false) >= 0) {
- printf("ControlGroupAttribute={ controller=%s ; attribute=%s ; value=\"%s\" }\n",
+ printf("ControlGroupAttributes={ controller=%s ; attribute=%s ; value=\"%s\" }\n",
controller,
attr,
value);
}
static int show_one(const char *verb, DBusConnection *bus, const char *path, bool show_properties, bool *new_line) {
- DBusMessage *reply = NULL;
+ _cleanup_free_ DBusMessage *reply = NULL;
const char *interface = "";
int r;
DBusMessageIter iter, sub, sub2, sub3;
zero(info);
- r = bus_method_call_with_reply (
+ r = bus_method_call_with_reply(
bus,
"org.freedesktop.systemd1",
path,
NULL,
DBUS_TYPE_STRING, &interface,
DBUS_TYPE_INVALID);
- if (r)
- goto finish;
+ if (r < 0)
+ return r;
if (!dbus_message_iter_init(reply, &iter) ||
dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
log_error("Failed to parse reply.");
- r = -EIO;
- goto finish;
+ return -EIO;
}
dbus_message_iter_recurse(&iter, &sub);
while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
const char *name;
- if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_DICT_ENTRY) {
- log_error("Failed to parse reply.");
- r = -EIO;
- goto finish;
- }
-
+ assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_DICT_ENTRY);
dbus_message_iter_recurse(&sub, &sub2);
- if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0) {
- log_error("Failed to parse reply.");
- r = -EIO;
- goto finish;
- }
-
- if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
+ if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0 ||
+ dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
log_error("Failed to parse reply.");
- r = -EIO;
- goto finish;
+ return -EIO;
}
dbus_message_iter_recurse(&sub2, &sub3);
r = print_property(name, &sub3);
else
r = status_property(name, &sub3, &info);
-
if (r < 0) {
log_error("Failed to parse reply.");
- r = -EIO;
- goto finish;
+ return -EIO;
}
dbus_message_iter_next(&sub);
exec_status_info_free(p);
}
-finish:
- if (reply)
- dbus_message_unref(reply);
-
return r;
}
static int show_one_by_pid(const char *verb, DBusConnection *bus, uint32_t pid, bool *new_line) {
- DBusMessage *reply = NULL;
+ _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
const char *path = NULL;
DBusError error;
int r;
dbus_error_init(&error);
- r = bus_method_call_with_reply (
+ r = bus_method_call_with_reply(
bus,
"org.freedesktop.systemd1",
"/org/freedesktop/systemd1",
NULL,
DBUS_TYPE_UINT32, &pid,
DBUS_TYPE_INVALID);
- if (r)
+ if (r < 0)
goto finish;
if (!dbus_message_get_args(reply, &error,
r = show_one(verb, bus, path, false, new_line);
finish:
- if (reply)
- dbus_message_unref(reply);
-
dbus_error_free(&error);
return r;
if (show_properties)
pager_open_if_enabled();
- if (show_properties && strv_length(args) <= 1) {
- /* If not argument is specified inspect the manager
- * itself */
+ /* If no argument is specified inspect the manager itself */
+ if (show_properties && strv_length(args) <= 1)
return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line);
- }
STRV_FOREACH(name, args+1) {
uint32_t id;
if (safe_atou32(*name, &id) < 0) {
- char *p, *n;
+ _cleanup_free_ char *p = NULL, *n = NULL;
/* Interpret as unit name */
n = unit_name_mangle(*name);
- p = unit_dbus_path_from_name(n ? n : *name);
- free(n);
+ if (!n)
+ return log_oom();
+
+ p = unit_dbus_path_from_name(n);
if (!p)
return log_oom();
r = show_one(args[0], bus, p, show_properties, &new_line);
- free(p);
-
if (r != 0)
ret = r;
} else if (show_properties) {
+ _cleanup_free_ char *p = NULL;
/* Interpret as job id */
-
- char *p;
if (asprintf(&p, "/org/freedesktop/systemd1/job/%u", id) < 0)
return log_oom();
r = show_one(args[0], bus, p, show_properties, &new_line);
- free(p);
-
if (r != 0)
ret = r;
} else {
-
/* Interpret as PID */
-
r = show_one_by_pid(args[0], bus, id, &new_line);
if (r != 0)
ret = r;
}
static int dump(DBusConnection *bus, char **args) {
- DBusMessage *reply = NULL;
+ _cleanup_free_ DBusMessage *reply = NULL;
DBusError error;
int r;
const char *text;
pager_open_if_enabled();
- r = bus_method_call_with_reply (
+ r = bus_method_call_with_reply(
bus,
"org.freedesktop.systemd1",
"/org/freedesktop/systemd1",
&reply,
NULL,
DBUS_TYPE_INVALID);
- if (r)
- goto finish;
+ if (r < 0)
+ return r;
if (!dbus_message_get_args(reply, &error,
DBUS_TYPE_STRING, &text,
DBUS_TYPE_INVALID)) {
log_error("Failed to parse reply: %s", bus_error_message(&error));
- r = -EIO;
- goto finish;
+ dbus_error_free(&error);
+ return -EIO;
}
fputs(text, stdout);
-
-finish:
- if (reply)
- dbus_message_unref(reply);
-
- dbus_error_free(&error);
-
- return r;
+ return 0;
}
static int snapshot(DBusConnection *bus, char **args) {
- DBusMessage *reply = NULL;
+ _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
DBusError error;
int r;
dbus_bool_t cleanup = FALSE;
DBusMessageIter iter, sub;
const char
- *name = "", *path, *id,
+ *path, *id,
*interface = "org.freedesktop.systemd1.Unit",
*property = "Id";
- char *n;
+ _cleanup_free_ char *n = NULL;
dbus_error_init(&error);
if (strv_length(args) > 1)
- name = args[1];
+ n = snapshot_name_mangle(args[1]);
+ else
+ n = strdup("");
+ if (!n)
+ return log_oom();
- n = unit_name_mangle(name);
r = bus_method_call_with_reply (
bus,
"org.freedesktop.systemd1",
"CreateSnapshot",
&reply,
NULL,
- DBUS_TYPE_STRING, n ? (const char**) &n : &name,
+ DBUS_TYPE_STRING, &n,
DBUS_TYPE_BOOLEAN, &cleanup,
DBUS_TYPE_INVALID);
- free(n);
- if (r)
- goto finish;
+ if (r < 0)
+ return r;
if (!dbus_message_get_args(reply, &error,
DBUS_TYPE_OBJECT_PATH, &path,
DBUS_TYPE_INVALID)) {
log_error("Failed to parse reply: %s", bus_error_message(&error));
- r = -EIO;
- goto finish;
+ dbus_error_free(&error);
+ return -EIO;
}
dbus_message_unref(reply);
+ reply = NULL;
+
r = bus_method_call_with_reply (
bus,
"org.freedesktop.systemd1",
DBUS_TYPE_STRING, &interface,
DBUS_TYPE_STRING, &property,
DBUS_TYPE_INVALID);
- if (r)
- goto finish;
+ if (r < 0)
+ return r;
if (!dbus_message_iter_init(reply, &iter) ||
dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
log_error("Failed to parse reply.");
- r = -EIO;
- goto finish;
+ return -EIO;
}
dbus_message_iter_recurse(&iter, &sub);
if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
log_error("Failed to parse reply.");
- r = -EIO;
- goto finish;
+ return -EIO;
}
dbus_message_iter_get_basic(&sub, &id);
if (!arg_quiet)
puts(id);
-finish:
- if (reply)
- dbus_message_unref(reply);
-
- dbus_error_free(&error);
-
- return r;
+ return 0;
}
static int delete_snapshot(DBusConnection *bus, char **args) {
- DBusMessage *reply = NULL;
- int r = 0;
- DBusError error;
char **name;
assert(args);
- dbus_error_init(&error);
-
STRV_FOREACH(name, args+1) {
- const char *path = NULL;
- char *n;
+ _cleanup_free_ char *n = NULL;
+ int r;
- n = unit_name_mangle(*name);
- r = bus_method_call_with_reply (
+ n = snapshot_name_mangle(*name);
+ if (!n)
+ return log_oom();
+
+ r = bus_method_call_with_reply(
bus,
"org.freedesktop.systemd1",
"/org/freedesktop/systemd1",
"org.freedesktop.systemd1.Manager",
- "GetUnit",
- &reply,
- NULL,
- DBUS_TYPE_STRING, n ? &n : name,
- DBUS_TYPE_INVALID);
- free(n);
- if (r)
- goto finish;
-
- if (!dbus_message_get_args(reply, &error,
- DBUS_TYPE_OBJECT_PATH, &path,
- DBUS_TYPE_INVALID)) {
- log_error("Failed to parse reply: %s", bus_error_message(&error));
- r = -EIO;
- dbus_message_unref(reply);
- dbus_error_free(&error);
- goto finish;
- }
- dbus_message_unref(reply);
-
- r = bus_method_call_with_reply (
- bus,
- "org.freedesktop.systemd1",
- path,
- "org.freedesktop.systemd1.Snapshot",
- "Remove",
+ "RemoveSnapshot",
NULL,
NULL,
+ DBUS_TYPE_STRING, &n,
DBUS_TYPE_INVALID);
- if (r)
- goto finish;
+ if (r < 0)
+ return r;
}
-finish:
- return r;
+ return 0;
}
static int daemon_reload(DBusConnection *bus, char **args) {
/* "daemon-reload" */ "Reload";
}
- r = bus_method_call_with_reply (
+ r = bus_method_call_with_reply(
bus,
"org.freedesktop.systemd1",
"/org/freedesktop/systemd1",
/* On reexecution, we expect a disconnect, not
* a reply */
r = 0;
- else if (r)
+ else if (r < 0)
log_error("Failed to issue method call: %s", bus_error_message(&error));
- dbus_error_free(&error);
+ dbus_error_free(&error);
return r;
}
static int reset_failed(DBusConnection *bus, char **args) {
int r = 0;
- char **name, *n;
+ char **name;
if (strv_length(args) <= 1)
return daemon_reload(bus, args);
STRV_FOREACH(name, args+1) {
+ _cleanup_free_ char *n;
+
n = unit_name_mangle(*name);
- r = bus_method_call_with_reply (
+ if (!n)
+ return log_oom();
+
+ r = bus_method_call_with_reply(
bus,
"org.freedesktop.systemd1",
"/org/freedesktop/systemd1",
"ResetFailedUnit",
NULL,
NULL,
- DBUS_TYPE_STRING, n ? &n : name,
+ DBUS_TYPE_STRING, &n,
DBUS_TYPE_INVALID);
- free(n);
- if (r)
- goto finish;
+ if (r < 0)
+ return r;
}
-finish:
- return r;
+ return 0;
}
static int show_enviroment(DBusConnection *bus, char **args) {
- DBusMessage *reply = NULL;
+ _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
DBusMessageIter iter, sub, sub2;
int r;
const char
pager_open_if_enabled();
- r = bus_method_call_with_reply (
+ r = bus_method_call_with_reply(
bus,
"org.freedesktop.systemd1",
"/org/freedesktop/systemd1",
DBUS_TYPE_STRING, &interface,
DBUS_TYPE_STRING, &property,
DBUS_TYPE_INVALID);
- if (r)
- goto finish;
+ if (r < 0)
+ return r;
if (!dbus_message_iter_init(reply, &iter) ||
dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
log_error("Failed to parse reply.");
- r = -EIO;
- goto finish;
+ return -EIO;
}
dbus_message_iter_recurse(&iter, &sub);
if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_ARRAY ||
dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_STRING) {
log_error("Failed to parse reply.");
- r = -EIO;
- goto finish;
+ return -EIO;
}
dbus_message_iter_recurse(&sub, &sub2);
if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_STRING) {
log_error("Failed to parse reply.");
- r = -EIO;
- goto finish;
+ return -EIO;
}
dbus_message_iter_get_basic(&sub2, &text);
- printf("%s\n", text);
+ puts(text);
dbus_message_iter_next(&sub2);
}
- r = 0;
-
-finish:
- if (reply)
- dbus_message_unref(reply);
-
- return r;
+ return 0;
}
static int switch_root(DBusConnection *bus, char **args) {
unsigned l;
- const char *root, *init;
+ const char *root;
+ _cleanup_free_ char *init = NULL;
l = strv_length(args);
if (l < 2 || l > 3) {
}
root = args[1];
- init = l >= 3 ? args[2] : "";
- return bus_method_call_with_reply (
+ if (l >= 3)
+ init = strdup(args[2]);
+ else {
+ parse_env_file("/proc/cmdline", WHITESPACE,
+ "init", &init,
+ NULL);
+
+ if (!init)
+ init = strdup("");
+ }
+ if (!init)
+ return log_oom();
+
+ log_debug("switching root - root: %s; init: %s", root, init);
+
+ return bus_method_call_with_reply(
bus,
"org.freedesktop.systemd1",
"/org/freedesktop/systemd1",
int r;
assert(bus);
+ assert(args);
dbus_error_init(&error);
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));
- r = -EIO;
- goto finish;
+ dbus_error_free(&error);
+ return -EIO;
}
- r = 0;
-
-finish:
- dbus_error_free(&error);
- return r;
+ return 0;
}
static int enable_sysv_units(char **args) {
int r = 0;
-#if defined (HAVE_SYSV_COMPAT) && (defined(TARGET_FEDORA) || defined(TARGET_MANDRIVA) || defined(TARGET_SUSE) || defined(TARGET_ALTLINUX) || defined(TARGET_MAGEIA))
+#if defined(HAVE_SYSV_COMPAT) && defined(HAVE_CHKCONFIG)
const char *verb = args[0];
unsigned f = 1, t = 1;
LookupPaths paths;
}
if (carries_install_info == 0)
- log_warning("The unit files have no [Install] section. They are not meant to be enabled using systemctl.");
+ 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:
if (m)
" pending\n"
" --ignore-dependencies\n"
" When queueing a new job, ignore all its dependencies\n"
+ " -i --ignore-inhibitors\n"
+ " When shutting down or sleeping, ignore inhibitors\n"
" --kill-who=WHO Who to send signal to\n"
" -s --signal=SIGNAL Which signal to send\n"
" -H --host=[USER@]HOST\n"
" reload [NAME...] Reload one or more units\n"
" restart [NAME...] Start or restart one or more units\n"
" try-restart [NAME...] Restart one or more units if active\n"
- " reload-or-restart [NAME...] Reload one or more units is possible,\n"
+ " reload-or-restart [NAME...] Reload one or more units if possible,\n"
" otherwise start or restart\n"
- " reload-or-try-restart [NAME...] Reload one or more units is possible,\n"
+ " reload-or-try-restart [NAME...] Reload one or more units if possible,\n"
" otherwise restart if active\n"
" isolate [NAME] Start one unit and stop all others\n"
" kill [NAME...] Send signal to processes of a unit\n"
" is-active [NAME...] Check whether units are active\n"
+ " is-failed [NAME...] Check whether units are failed\n"
" 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"
- " help [NAME...|PID...] Show manual for one or more units\n"
+ " help [NAME...|PID...] Show manual for one or more units\n"
" reset-failed [NAME...] Reset failed state for all, one, or more\n"
" units\n"
- " load [NAME...] Load one or more units\n\n"
+ " get-cgroup-attr [NAME] [ATTR] ...\n"
+ " Get control group attrubute\n"
+ " set-cgroup-attr [NAME] [ATTR] [VALUE] ...\n"
+ " Set control group attribute\n"
+ " unset-cgroup-attr [NAME] [ATTR...]\n"
+ " Unset control group attribute\n"
+ " set-cgroup [NAME] [CGROUP...] Add unit to a control group\n"
+ " unset-cgroup [NAME] [CGROUP...] Remove unit from a control group\n"
+ " load [NAME...] Load one or more units\n"
+ " list-dependencies [NAME] Recursively show units which are required\n"
+ " or wanted by this unit\n\n"
"Unit File Commands:\n"
" list-unit-files List installed unit files\n"
" enable [NAME...] Enable one or more unit files\n"
return 0;
}
+static int help_types(void) {
+ int i;
+
+ puts("Available unit types:");
+ for(i = UNIT_SERVICE; i < _UNIT_TYPE_MAX; i++)
+ if (unit_type_table[i])
+ puts(unit_type_table[i]);
+
+ puts("\nAvailable unit load states: ");
+ for(i = UNIT_STUB; i < _UNIT_LOAD_STATE_MAX; i++)
+ if (unit_type_table[i])
+ puts(unit_load_state_table[i]);
+
+ return 0;
+}
+
static int systemctl_parse_argv(int argc, char *argv[]) {
enum {
{ "full", no_argument, NULL, ARG_FULL },
{ "fail", no_argument, NULL, ARG_FAIL },
{ "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES },
+ { "ignore-inhibitors", no_argument, NULL, 'i' },
{ "user", no_argument, NULL, ARG_USER },
{ "system", no_argument, NULL, ARG_SYSTEM },
{ "global", no_argument, NULL, ARG_GLOBAL },
assert(argc >= 0);
assert(argv);
- while ((c = getopt_long(argc, argv, "ht:p:aqfs:H:Pn:o:", options, NULL)) >= 0) {
+ while ((c = getopt_long(argc, argv, "ht:p:aqfs:H:Pn:o:i", options, NULL)) >= 0) {
switch (c) {
case ARG_VERSION:
puts(PACKAGE_STRING);
- puts(DISTRIBUTION);
puts(SYSTEMD_FEATURES);
return 0;
case 't':
+ if (streq(optarg, "help")) {
+ help_types();
+ return 0;
+ }
+
if (unit_type_from_string(optarg) >= 0) {
arg_type = optarg;
break;
}
log_error("Unkown unit type or load state '%s'.",
optarg);
+ log_info("Use -t help to see a list of allowed values.");
return -EINVAL;
case 'p': {
char **l;
}
break;
+ case 'i':
+ arg_ignore_inhibitors = true;
+ break;
+
case '?':
return -EINVAL;
{ "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 },
{ "kill", MORE, 2, kill_unit },
- { "is-active", MORE, 2, check_unit },
- { "check", MORE, 2, check_unit },
+ { "is-active", MORE, 2, check_unit_active },
+ { "check", MORE, 2, check_unit_active },
+ { "is-failed", MORE, 2, check_unit_failed },
{ "show", MORE, 1, show },
{ "status", MORE, 2, show },
{ "help", MORE, 2, show },
{ "unmask", MORE, 2, enable_unit },
{ "link", MORE, 2, enable_unit },
{ "switch-root", MORE, 2, switch_root },
+ { "list-dependencies", LESS, 2, list_dependencies },
};
int left;
static int halt_main(DBusConnection *bus) {
int r;
+ r = check_inhibitors(bus, arg_action);
+ if (r < 0)
+ return r;
+
if (geteuid() != 0) {
/* Try logind if we are a normal user and no special
* mode applies. Maybe PolicyKit allows us to shutdown
if (arg_when <= 0 &&
!arg_dry &&
- !arg_force &&
+ arg_force <= 0 &&
(arg_action == ACTION_POWEROFF ||
arg_action == ACTION_REBOOT)) {
r = reboot_with_logind(bus, arg_action);
dbus_error_init(&error);
+ setlocale(LC_ALL, "");
log_parse_environment();
log_open();