static char **arg_load_states = NULL;
static char **arg_properties = NULL;
static bool arg_all = false;
+static enum dependency {
+ DEPENDENCY_FORWARD,
+ DEPENDENCY_REVERSE,
+ DEPENDENCY_AFTER,
+ DEPENDENCY_BEFORE,
+} arg_dependency = DEPENDENCY_FORWARD;
static const char *arg_job_mode = "replace";
static UnitFileScope arg_scope = UNIT_FILE_SYSTEM;
static bool arg_no_block = false;
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;
static bool private_bus = false;
id_len = max_id_len;
for (u = unit_infos; u < unit_infos + c; u++) {
- char _cleanup_free_ *e = NULL;
+ _cleanup_free_ char *e = NULL;
const char *on_loaded, *off_loaded, *on = "";
const char *on_active, *off_active, *off = "";
{
const char *interface = "org.freedesktop.systemd1.Unit",
*triggers_property = "Triggers";
- DBusMessage _cleanup_dbus_message_unref_ *reply = NULL;
+ _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
DBusMessageIter iter, sub;
int r;
{
const char *interface = "org.freedesktop.systemd1.Socket",
*listen_property = "Listen";
- DBusMessage _cleanup_dbus_message_unref_ *reply = NULL;
+ _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
DBusMessageIter iter, sub;
int r;
}
if (cs) {
- printf("%-*s %-*.*s%-*s %s\n",
- pathlen, "LISTEN",
- typelen + arg_show_types, typelen + arg_show_types, "TYPE ",
- socklen, "UNIT",
- "ACTIVATES");
+ if (!arg_no_legend)
+ printf("%-*s %-*.*s%-*s %s\n",
+ pathlen, "LISTEN",
+ typelen + arg_show_types, typelen + arg_show_types, "TYPE ",
+ socklen, "UNIT",
+ "ACTIVATES");
for (s = socket_infos; s < socket_infos + cs; s++) {
char **a;
on = ansi_highlight(true);
off = ansi_highlight(false);
- printf("\n");
+ if (!arg_no_legend)
+ printf("\n");
} else {
on = ansi_highlight_red(true);
off = ansi_highlight_red(false);
}
- printf("%s%u sockets listed.%s\n", on, cs, off);
- if (!arg_all)
- printf("Pass --all to see loaded but inactive sockets, too.\n");
+ if (!arg_no_legend) {
+ printf("%s%u sockets listed.%s\n", on, cs, off);
+ if (!arg_all)
+ printf("Pass --all to see loaded but inactive sockets, too.\n");
+ }
return 0;
}
for (u = unit_infos; u < unit_infos + cu; u++) {
const char *dot;
- char _cleanup_strv_free_ **listen = NULL, **triggered = NULL;
+ _cleanup_strv_free_ char **listen = NULL, **triggered = NULL;
unsigned c = 0, i;
if (!output_show_unit(u))
printf("%-*s %-*s\n", id_cols, "UNIT FILE", state_cols, "STATE");
for (u = units; u < units + c; u++) {
- char _cleanup_free_ *e = NULL;
+ _cleanup_free_ char *e = NULL;
const char *on, *off;
const char *id;
size_t len = 0;
size_t max_len = MAX(columns(),20u);
- for (i = level - 1; i >= 0; i--) {
+ if (!arg_plain) {
+ 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(branches & (1 << i) ? DRAW_TREE_VERT : DRAW_TREE_SPACE));
+ printf("%s", draw_special_char(last ? DRAW_TREE_RIGHT : DRAW_TREE_BRANCH));
}
- 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);
}
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";
+ static const char *dependencies[] = {
+ [DEPENDENCY_FORWARD] = "Requires\0"
+ "RequiresOverridable\0"
+ "Requisite\0"
+ "RequisiteOverridable\0"
+ "Wants\0",
+ [DEPENDENCY_REVERSE] = "RequiredBy\0"
+ "RequiredByOverridable\0"
+ "WantedBy\0"
+ "PartOf\0",
+ [DEPENDENCY_AFTER] = "After\0",
+ [DEPENDENCY_BEFORE] = "Before\0",
+ };
_cleanup_free_ char *path;
const char *interface = "org.freedesktop.systemd1.Unit";
dbus_message_iter_recurse(&sub2, &sub3);
dbus_message_iter_next(&sub);
- if (!nulstr_contains(dependencies, prop))
+ assert(arg_dependency < ELEMENTSOF(dependencies));
+ if (!nulstr_contains(dependencies[arg_dependency], prop))
continue;
if (dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_ARRAY) {
return strcasecmp(*a, *b);
}
-static int list_dependencies_one(DBusConnection *bus, const char *name, int level, char **units, unsigned int branches) {
- char _cleanup_strv_free_ **deps = NULL, **u;
+static int list_dependencies_one(DBusConnection *bus, const char *name, int level, char ***units, unsigned int branches) {
+ _cleanup_strv_free_ char **deps = NULL, **u;
char **c;
int r = 0;
- u = strv_append(units, name);
+ u = strv_append(*units, name);
if (!u)
return log_oom();
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)
- return r;
+ if (!arg_plain) {
+ r = list_dependencies_print("...", level + 1, (branches << 1) | (c[1] == NULL ? 0 : 1), 1);
+ if (r < 0)
+ return r;
+ }
continue;
}
return r;
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));
+ r = list_dependencies_one(bus, *c, level + 1, &u, (branches << 1) | (c[1] == NULL ? 0 : 1));
if(r < 0)
return r;
}
}
-
+ if (arg_plain) {
+ strv_free(*units);
+ *units = u;
+ u = NULL;
+ }
return 0;
}
static int list_dependencies(DBusConnection *bus, char **args) {
_cleanup_free_ char *unit = NULL;
+ _cleanup_strv_free_ char **units = NULL;
const char *u;
assert(bus);
puts(u);
- return list_dependencies_one(bus, u, 0, NULL, 0);
+ 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 {
l3, "STATE");
for (i = 0, j = jobs; i < n; i++, j++) {
- char _cleanup_free_ *e = NULL;
+ _cleanup_free_ char *e = NULL;
if (streq(j->state, "running")) {
on = ansi_highlight(true);
goto finish;
}
- if (!greedy_realloc((void**) &jobs, &size,
- sizeof(struct job_info) * (used + 1))) {
+ if (!GREEDY_REALLOC(jobs, size, used + 1)) {
r = log_oom();
goto finish;
}
} WaitData;
static DBusHandlerResult wait_filter(DBusConnection *connection, DBusMessage *message, void *data) {
- DBusError _cleanup_dbus_error_free_ error;
+ _cleanup_dbus_error_free_ DBusError error;
WaitData *d = data;
dbus_error_init(&error);
*load_state_property = "LoadState",
*triggered_by_property = "TriggeredBy",
*state;
- char _cleanup_free_ *unit_path = NULL, *n = NULL;
+ _cleanup_free_ char *unit_path = NULL, *n = NULL;
bool print_warning_label = true;
int r;
}
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;
if (!p)
return log_oom();
- r = set_put(s, p);
+ r = set_consume(s, p);
if (r < 0) {
- free(p);
log_error("Failed to add path to set.");
return r;
}
int r, ret = 0;
const char *method, *mode, *one_name;
- Set _cleanup_set_free_free_ *s = NULL;
- DBusError _cleanup_dbus_error_free_ error;
+ _cleanup_set_free_free_ Set *s = NULL;
+ _cleanup_dbus_error_free_ DBusError error;
char **name;
dbus_error_init(&error);
return 0;
}
-static int set_cgroup(DBusConnection *bus, char **args) {
- _cleanup_free_ char *n = NULL;
- const char *method, *runtime;
- char **argument;
- int r;
-
- assert(bus);
- assert(args);
-
- method =
- 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();
-
- STRV_FOREACH(argument, args + 2) {
-
- 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;
- _cleanup_free_ char *n = NULL;
- const char *runtime;
- int r;
-
- assert(bus);
- assert(args);
-
- dbus_error_init(&error);
-
- 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",
- "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_append_basic(&iter, DBUS_TYPE_STRING, &args[2]))
- return log_oom();
-
- r = bus_append_strv_iter(&iter, args + 3);
- if (r < 0)
- return log_oom();
-
- 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 get_cgroup_attr(DBusConnection *bus, char **args) {
- _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
- _cleanup_free_ char *n = NULL;
- char **argument;
- int r;
-
- assert(bus);
- assert(args);
-
- n = unit_name_mangle(args[1]);
- if (!n)
- return log_oom();
-
- STRV_FOREACH(argument, args + 2) {
- _cleanup_strv_free_ char **list = NULL;
- DBusMessageIter iter;
- char **a;
-
- 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;
-
- if (!dbus_message_iter_init(reply, &iter)) {
- log_error("Failed to initialize iterator.");
- return -EIO;
- }
-
- 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;
-}
-
typedef struct ExecStatusInfo {
char *name;
const char *fragment_path;
const char *source_path;
- const char *default_control_group;
+ const char *control_group;
char **dropin_paths;
pid_t main_pid;
pid_t control_pid;
const char *status_text;
+ const char *pid_file;
bool running:1;
usec_t start_timestamp;
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 */
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);
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;
STRV_FOREACH(dropin, i->dropin_paths) {
if (! dir || last) {
- printf(" %*s ", maxlen, dir ? "" : "Drop-In:");
+ printf(dir ? " " : " Drop-In: ");
free(dir);
return;
}
- printf("%s\n %*s %s", dir, maxlen, "",
+ printf("%s\n %s", dir,
draw_special_char(DRAW_TREE_RIGHT));
}
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);
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;
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) {
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;
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)
}
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)) {
+ if (i->control_group &&
+ (i->main_pid > 0 || i->control_pid > 0 || cg_is_empty_by_spec(i->control_group, false) == 0)) {
unsigned c;
- printf(" %*s: %s\n", maxlen, "CGroup", i->default_control_group);
+ printf(" CGroup: %s\n", i->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)
if (i->control_pid > 0)
extra[k++] = i->control_pid;
- show_cgroup_and_extra_by_spec(i->default_control_group, prefix,
+ show_cgroup_and_extra_by_spec(i->control_group, prefix,
c, false, extra, k, flags);
}
}
}
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) {
if (startswith(*p, "man:")) {
size_t k;
char *e = NULL;
- char _cleanup_free_ *page = NULL, *section = NULL;
+ _cleanup_free_ char *page = NULL, *section = NULL;
const char *args[4] = { "man", NULL, NULL, NULL };
pid_t pid;
i->fragment_path = s;
else if (streq(name, "SourcePath"))
i->source_path = s;
+#ifndef LEGACY
else if (streq(name, "DefaultControlGroup"))
- i->default_control_group = s;
+ i->control_group = s;
+#endif
+ else if (streq(name, "ControlGroup"))
+ i->control_group = s;
else if (streq(name, "StatusText"))
i->status_text = s;
+ else if (streq(name, "PIDFile"))
+ i->pid_file = s;
else if (streq(name, "SysFSPath"))
i->sysfs_path = s;
else if (streq(name, "Where"))
if (exec_status_info_deserialize(&sub, &info) >= 0) {
char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
- char _cleanup_free_ *t;
+ _cleanup_free_ char *t;
t = strv_join(info.argv, " ");
}
return 0;
+
+ } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "DeviceAllow")) {
+ DBusMessageIter sub, sub2;
+
+ dbus_message_iter_recurse(iter, &sub);
+ while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
+ const char *path, *rwm;
+
+ dbus_message_iter_recurse(&sub, &sub2);
+
+ if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
+ bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &rwm, false) >= 0)
+ printf("%s=%s %s\n", name, strna(path), strna(rwm));
+
+ dbus_message_iter_next(&sub);
+ }
+ return 0;
+
+ } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && (streq(name, "BlockIOReadBandwidth") || streq(name, "BlockIOWriteBandwidth"))) {
+ DBusMessageIter sub, sub2;
+
+ dbus_message_iter_recurse(iter, &sub);
+ while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
+ const char *path;
+ uint64_t bandwidth;
+
+ dbus_message_iter_recurse(&sub, &sub2);
+
+ if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
+ bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &bandwidth, false) >= 0)
+ printf("%s=%s %" PRIu64 "\n", name, strna(path), bandwidth);
+
+ dbus_message_iter_next(&sub);
+ }
+ return 0;
}
+
break;
}
}
static int show_one(const char *verb, DBusConnection *bus, const char *path, bool show_properties, bool *new_line) {
- DBusMessage _cleanup_free_ *reply = NULL;
+ _cleanup_free_ DBusMessage *reply = NULL;
const char *interface = "";
int r;
DBusMessageIter iter, sub, sub2, sub3;
if (!streq_ptr(info.active_state, "active") &&
!streq_ptr(info.active_state, "reloading") &&
- streq(verb, "status"))
+ streq(verb, "status")) {
/* According to LSB: "program not running" */
- r = 3;
+ /* 0: program is running or service is OK
+ * 1: program is dead and /var/run pid file exists
+ * 2: program is dead and /var/lock lock file exists
+ * 3: program is not running
+ * 4: program or service status is unknown
+ */
+ if (info.pid_file && access(info.pid_file, F_OK) == 0)
+ r = 1;
+ else
+ r = 3;
+ }
while ((p = info.exec)) {
LIST_REMOVE(ExecStatusInfo, exec, info.exec, p);
static int show_one_by_pid(const char *verb, DBusConnection *bus, uint32_t pid, bool *new_line) {
_cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
const char *path = NULL;
- DBusError _cleanup_dbus_error_free_ error;
+ _cleanup_dbus_error_free_ DBusError error;
int r;
dbus_error_init(&error);
qsort(unit_infos, c, sizeof(struct unit_info), compare_unit_info);
for (u = unit_infos; u < unit_infos + c; u++) {
- char _cleanup_free_ *p = NULL;
+ _cleanup_free_ char *p = NULL;
if (!output_show_unit(u))
continue;
return ret;
}
+static int append_assignment(DBusMessageIter *iter, const char *assignment) {
+ const char *eq;
+ char *field;
+ DBusMessageIter sub;
+ int r;
+
+ assert(iter);
+ assert(assignment);
+
+ eq = strchr(assignment, '=');
+ if (!eq) {
+ log_error("Not an assignment: %s", assignment);
+ return -EINVAL;
+ }
+
+ field = strndupa(assignment, eq - assignment);
+ eq ++;
+
+ if (!dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &field))
+ return log_oom();
+
+ if (streq(field, "CPUAccounting") ||
+ streq(field, "MemoryAccounting") ||
+ streq(field, "BlockIOAccounting")) {
+ dbus_bool_t b;
+
+ r = parse_boolean(eq);
+ if (r < 0) {
+ log_error("Failed to parse boolean assignment %s.", assignment);
+ return -EINVAL;
+ }
+
+ b = r;
+ if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "b", &sub) ||
+ !dbus_message_iter_append_basic(&sub, DBUS_TYPE_BOOLEAN, &b))
+ return log_oom();
+
+ } else if (streq(field, "MemoryLimit") || streq(field, "MemorySoftLimit")) {
+ off_t bytes;
+ uint64_t u;
+
+ r = parse_bytes(eq, &bytes);
+ if (r < 0) {
+ log_error("Failed to parse bytes specification %s", assignment);
+ return -EINVAL;
+ }
+
+ u = bytes;
+ if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "t", &sub) ||
+ !dbus_message_iter_append_basic(&sub, DBUS_TYPE_UINT64, &u))
+ return log_oom();
+
+ } else if (streq(field, "CPUShares") || streq(field, "BlockIOWeight")) {
+ uint64_t u;
+
+ r = safe_atou64(eq, &u);
+ if (r < 0) {
+ log_error("Failed to parse %s value %s.", field, eq);
+ return -EINVAL;
+ }
+
+ if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "t", &sub) ||
+ !dbus_message_iter_append_basic(&sub, DBUS_TYPE_UINT64, &u))
+ return log_oom();
+
+ } else {
+ log_error("Unknown assignment %s.", assignment);
+ return -EINVAL;
+ }
+
+ if (!dbus_message_iter_close_container(iter, &sub))
+ return log_oom();
+
+ return 0;
+}
+
+static int set_property(DBusConnection *bus, char **args) {
+
+ _cleanup_free_ DBusMessage *m = NULL, *reply = NULL;
+ DBusMessageIter iter, sub;
+ dbus_bool_t runtime;
+ DBusError error;
+ char **i;
+ int r;
+
+ dbus_error_init(&error);
+
+ m = dbus_message_new_method_call(
+ "org.freedesktop.systemd1",
+ "/org/freedesktop/systemd1",
+ "org.freedesktop.systemd1.Manager",
+ "SetUnitProperties");
+ if (!m)
+ return log_oom();
+
+ dbus_message_iter_init_append(m, &iter);
+
+ runtime = arg_runtime;
+
+ if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &args[1]) ||
+ !dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &runtime) ||
+ !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(sv)", &sub))
+ return log_oom();
+
+ STRV_FOREACH(i, args + 2) {
+ DBusMessageIter sub2;
+
+ if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2))
+ return log_oom();
+
+ r = append_assignment(&sub2, *i);
+ if (r < 0)
+ return r;
+
+ if (!dbus_message_iter_close_container(&sub, &sub2))
+ 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));
+ dbus_error_free(&error);
+ return -EIO;
+ }
+
+ return 0;
+}
+
static int dump(DBusConnection *bus, char **args) {
_cleanup_free_ DBusMessage *reply = NULL;
DBusError error;
dbus_error_init(&error);
if (strv_length(args) > 1)
- n = snapshot_name_mangle(args[1]);
+ n = unit_name_mangle_with_suffix(args[1], ".snapshot");
else
n = strdup("");
if (!n)
_cleanup_free_ char *n = NULL;
int r;
- n = snapshot_name_mangle(*name);
+ n = unit_name_mangle_with_suffix(*name, ".snapshot");
if (!n)
return log_oom();
r = 0;
for (f = 1; args[f]; f++) {
const char *name;
- char _cleanup_free_ *p = NULL, *q = NULL;
+ _cleanup_free_ char *p = NULL, *q = NULL;
bool found_native = false, found_sysv;
unsigned c = 1;
const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
UnitFileChange *changes = NULL;
unsigned n_changes = 0, i;
int carries_install_info = -1;
- DBusMessage _cleanup_dbus_message_unref_ *m = NULL, *reply = NULL;
+ _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
int r;
- DBusError _cleanup_dbus_error_free_ error;
- char _cleanup_strv_free_ **mangled_names = NULL;
+ _cleanup_dbus_error_free_ DBusError error;
+ _cleanup_strv_free_ char **mangled_names = NULL;
dbus_error_init(&error);
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");
else if (streq(verb, "unmask")) {
method = "UnmaskUnitFiles";
send_force = false;
+ } else if (streq(verb, "set-default")) {
+ method = "SetDefaultTarget";
} else
assert_not_reached("Unknown verb");
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.");
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) {
- DBusError _cleanup_dbus_error_free_ error;
+ _cleanup_dbus_error_free_ DBusError error;
int r;
- DBusMessage _cleanup_dbus_message_unref_ *reply = NULL;
+ _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
bool enabled;
char **name;
char *n;
" --version Show package version\n"
" -t --type=TYPE List only units of a particular type\n"
" -p --property=NAME Show only properties by this name\n"
- " -a --all Show all internally loaded units/properties,\n"
- " including dead/empty ones. To list all units installed\n"
- " on disk, use the command 'list-unit-files' instead.\n"
+ " -a --all Show all loaded units/properties, including dead/empty\n"
+ " ones. To list all units installed on the system, use\n"
+ " the 'list-unit-files' command instead.\n"
+ " --reverse Show reverse dependencies with 'list-dependencies'\n"
" --failed Show only failed units\n"
- " --full Don't ellipsize unit names on output\n"
+ " -l --full Don't ellipsize unit names on output\n"
" --fail When queueing a new job, fail if conflicting jobs are\n"
" pending\n"
" --irreversible Create jobs which cannot be implicitly cancelled\n"
" 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"
" 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"
+ " set-property [NAME] [ASSIGNMENT...]\n"
+ " Sets one or more properties of a unit\n"
" help [NAME...|PID...] Show manual for one or more units\n"
" reset-failed [NAME...] Reset failed state for all, one, or more\n"
" units\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"
+ " or wanted by this unit or by which this\n"
+ " unit is required or wanted\n\n"
"Unit File Commands:\n"
" list-unit-files List installed unit files\n"
" enable [NAME...] Enable one or more unit files\n"
" 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"
"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"
enum {
ARG_FAIL = 0x100,
+ ARG_REVERSE,
+ ARG_AFTER,
+ ARG_BEFORE,
ARG_SHOW_TYPES,
ARG_IRREVERSIBLE,
ARG_IGNORE_DEPENDENCIES,
ARG_NO_PAGER,
ARG_NO_WALL,
ARG_ROOT,
- ARG_FULL,
ARG_NO_RELOAD,
ARG_KILL_WHO,
ARG_NO_ASK_PASSWORD,
ARG_FAILED,
ARG_RUNTIME,
- ARG_FORCE
+ ARG_FORCE,
+ ARG_PLAIN
};
static const struct option options[] = {
{ "type", required_argument, NULL, 't' },
{ "property", required_argument, NULL, 'p' },
{ "all", no_argument, NULL, 'a' },
+ { "reverse", no_argument, NULL, ARG_REVERSE },
+ { "after", no_argument, NULL, ARG_AFTER },
+ { "before", no_argument, NULL, ARG_BEFORE },
{ "show-types", no_argument, NULL, ARG_SHOW_TYPES },
{ "failed", no_argument, NULL, ARG_FAILED },
- { "full", no_argument, NULL, ARG_FULL },
+ { "full", no_argument, NULL, 'l' },
{ "fail", no_argument, NULL, ARG_FAIL },
{ "irreversible", no_argument, NULL, ARG_IRREVERSIBLE },
{ "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES },
{ "runtime", no_argument, NULL, ARG_RUNTIME },
{ "lines", required_argument, NULL, 'n' },
{ "output", required_argument, NULL, 'o' },
+ { "plain", no_argument, NULL, ARG_PLAIN },
{ NULL, 0, NULL, 0 }
};
assert(argc >= 0);
assert(argv);
- while ((c = getopt_long(argc, argv, "ht:p:aqfs:H:Pn:o:i", options, NULL)) >= 0) {
+ while ((c = getopt_long(argc, argv, "ht:p:alqfs:H:Pn:o:i", options, NULL)) >= 0) {
switch (c) {
size_t size;
FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
- char _cleanup_free_ *type;
+ _cleanup_free_ char *type;
type = strndup(word, size);
if (!type)
arg_all = true;
break;
+ case ARG_REVERSE:
+ arg_dependency = DEPENDENCY_REVERSE;
+ break;
+
+ case ARG_AFTER:
+ arg_dependency = DEPENDENCY_AFTER;
+ break;
+
+ case ARG_BEFORE:
+ arg_dependency = DEPENDENCY_BEFORE;
+ break;
+
case ARG_SHOW_TYPES:
arg_show_types = true;
break;
arg_root = optarg;
break;
- case ARG_FULL:
+ case 'l':
arg_full = true;
break;
case 'H':
arg_transport = TRANSPORT_SSH;
- arg_host = optarg;
+ parse_user_at_host(optarg, &arg_user, &arg_host);
break;
case ARG_RUNTIME:
arg_ignore_inhibitors = true;
break;
+ case ARG_PLAIN:
+ arg_plain = true;
+ break;
+
case '?':
return -EINVAL;
return systemctl_parse_argv(argc, argv);
}
-static int action_to_runlevel(void) {
+_pure_ static int action_to_runlevel(void) {
static const char table[_ACTION_MAX] = {
[ACTION_HALT] = '0',
}
static int talk_upstart(void) {
- DBusMessage _cleanup_dbus_message_unref_ *m = NULL, *reply = NULL;
- DBusError _cleanup_dbus_error_free_ error;
+ _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
+ _cleanup_dbus_error_free_ DBusError error;
int previous, rl, r;
char
env1_buf[] = "RUNLEVEL=X",
static int talk_initctl(void) {
struct init_request request = {};
int r;
- int _cleanup_close_ fd = -1;
+ _cleanup_close_ int fd = -1;
char rl;
rl = action_to_runlevel();
{ "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, 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 },
{ "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 },
+ { "set-property", MORE, 3, set_property },
};
int left;
!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.");
}
static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
- int _cleanup_close_ fd;
+ _cleanup_close_ int fd;
struct sd_shutdown_command c = {
.usec = t,
.mode = mode,
}
if (arg_when > 0) {
- char _cleanup_free_ *m;
+ _cleanup_free_ char *m;
m = strv_join(arg_wall, " ");
r = send_shutdownd(arg_when,
int main(int argc, char*argv[]) {
int r, retval = EXIT_FAILURE;
DBusConnection *bus = NULL;
- DBusError _cleanup_dbus_error_free_ error;
+ _cleanup_dbus_error_free_ DBusError error;
dbus_error_init(&error);
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...");