static char **arg_states = NULL;
static char **arg_properties = NULL;
static bool arg_all = false;
+static bool original_stdout_is_tty;
static enum dependency {
DEPENDENCY_FORWARD,
DEPENDENCY_REVERSE,
}
}
- if (!arg_full) {
+ if (!arg_full && original_stdout_is_tty) {
unsigned basic_len;
id_len = MIN(max_id_len, 25u);
basic_len = 5 + id_len + 5 + active_len + sub_len;
on_active, active_len, u->active_state,
sub_len, u->sub_state, off_active,
job_count ? job_len + 1 : 0, u->job_id ? u->job_type : "");
- if (!arg_full && arg_no_pager)
+ if (desc_len > 0)
printf("%.*s\n", desc_len, u->description);
else
printf("%s\n", u->description);
if (r < 0)
return r;
- qsort(unit_infos, c, sizeof(struct unit_info), compare_unit_info);
+ qsort_safe(unit_infos, c, sizeof(struct unit_info), compare_unit_info);
output_units_list(unit_infos, c);
listen = triggered = NULL; /* avoid cleanup */
}
- qsort(socket_infos, cs, sizeof(struct socket_info),
- (__compar_fn_t) socket_info_compare);
+ qsort_safe(socket_infos, cs, sizeof(struct socket_info),
+ (__compar_fn_t) socket_info_compare);
output_sockets_list(socket_infos, cs);
}
free(socket_infos);
- return 0;
+ return r;
}
static int compare_unit_file_list(const void *a, const void *b) {
if (r < 0)
return r;
- qsort(deps, strv_length(deps), sizeof (char*), list_dependencies_compare);
+ qsort_safe(deps, strv_length(deps), sizeof (char*), list_dependencies_compare);
STRV_FOREACH(c, deps) {
if (strv_contains(u, *c)) {
return r;
}
- LIST_PREPEND(ExecStatusInfo, exec, i->exec, info);
+ LIST_PREPEND(exec, i->exec, info);
dbus_message_iter_next(&sub);
}
}
while ((p = info.exec)) {
- LIST_REMOVE(ExecStatusInfo, exec, info.exec, p);
+ LIST_REMOVE(exec, info.exec, p);
exec_status_info_free(p);
}
if (r < 0)
return r;
- qsort(unit_infos, c, sizeof(struct unit_info), compare_unit_info);
+ qsort_safe(unit_infos, c, sizeof(struct unit_info), compare_unit_info);
for (u = unit_infos; u < unit_infos + c; u++) {
_cleanup_free_ char *p = NULL;
!dbus_message_iter_append_basic(&sub, DBUS_TYPE_BOOLEAN, &b))
return log_oom();
- } else if (streq(field, "MemoryLimit") || streq(field, "MemorySoftLimit")) {
+ } else if (streq(field, "MemoryLimit")) {
off_t bytes;
uint64_t u;
static int set_property(DBusConnection *bus, char **args) {
- _cleanup_free_ DBusMessage *m = NULL, *reply = NULL;
+ _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
+ _cleanup_free_ char *n = NULL;
DBusMessageIter iter, sub;
dbus_bool_t runtime;
DBusError error;
runtime = arg_runtime;
- if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &args[1]) ||
+ n = unit_name_mangle(args[1]);
+ if (!n)
+ return log_oom();
+
+ if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &n) ||
!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &runtime) ||
!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(sv)", &sub))
return log_oom();
return 0;
}
-static int enable_sysv_units(char **args) {
+static int enable_sysv_units(const char *verb, char **args) {
int r = 0;
#if defined(HAVE_SYSV_COMPAT) && defined(HAVE_CHKCONFIG)
- const char *verb = args[0];
unsigned f = 1, t = 1;
- LookupPaths paths = {};
+ _cleanup_lookup_paths_free_ LookupPaths paths = {};
if (arg_scope != UNIT_FILE_SYSTEM)
return 0;
return r;
r = 0;
- for (f = 1; args[f]; f++) {
+ for (f = 0; args[f]; f++) {
const char *name;
_cleanup_free_ char *p = NULL, *q = NULL;
bool found_native = false, found_sysv;
}
finish:
- lookup_paths_free(&paths);
-
/* Drop all SysV units */
- for (f = 1, t = 1; args[f]; f++) {
+ for (f = 0, t = 0; args[f]; f++) {
if (isempty(args[f]))
continue;
dbus_error_init(&error);
- r = enable_sysv_units(args);
- if (r < 0)
- return r;
-
if (!args[1])
return 0;
r = mangle_names(args+1, &mangled_names);
if (r < 0)
- goto finish;
+ return r;
+
+ r = enable_sysv_units(verb, mangled_names);
+ if (r < 0)
+ return r;
if (!bus || avoid_bus()) {
if (streq(verb, "enable")) {
_cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
bool enabled;
char **name;
- char *n;
+ _cleanup_strv_free_ char **mangled_names = NULL;
dbus_error_init(&error);
- r = enable_sysv_units(args);
+ r = mangle_names(args+1, &mangled_names);
+ if (r < 0)
+ return r;
+
+ r = enable_sysv_units(args[0], mangled_names);
if (r < 0)
return r;
if (!bus || avoid_bus()) {
- STRV_FOREACH(name, args+1) {
+ STRV_FOREACH(name, mangled_names) {
UnitFileState state;
- n = unit_name_mangle(*name);
- if (!n)
- return log_oom();
-
- state = unit_file_get_state(arg_scope, arg_root, n);
-
- free(n);
+ state = unit_file_get_state(arg_scope, arg_root, *name);
if (state < 0)
return state;
}
} else {
- STRV_FOREACH(name, args+1) {
+ STRV_FOREACH(name, mangled_names) {
const char *s;
- n = unit_name_mangle(*name);
- if (!n)
- return log_oom();
-
r = bus_method_call_with_reply (
bus,
"org.freedesktop.systemd1",
"GetUnitFileState",
&reply,
NULL,
- DBUS_TYPE_STRING, &n,
+ DBUS_TYPE_STRING, name,
DBUS_TYPE_INVALID);
- free(n);
-
if (r)
return r;
return table[arg_action];
}
-static int talk_upstart(void) {
- _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
- _cleanup_dbus_error_free_ DBusError error;
- int previous, rl, r;
- char
- env1_buf[] = "RUNLEVEL=X",
- env2_buf[] = "PREVLEVEL=X";
- char *env1 = env1_buf, *env2 = env2_buf;
- const char *emit = "runlevel";
- dbus_bool_t b_false = FALSE;
- DBusMessageIter iter, sub;
- DBusConnection *bus;
-
- dbus_error_init(&error);
-
- if (!(rl = action_to_runlevel()))
- return 0;
-
- if (utmp_get_runlevel(&previous, NULL) < 0)
- previous = 'N';
-
- if (!(bus = dbus_connection_open_private("unix:abstract=/com/ubuntu/upstart", &error))) {
- if (dbus_error_has_name(&error, DBUS_ERROR_NO_SERVER)) {
- r = 0;
- goto finish;
- }
-
- log_error("Failed to connect to Upstart bus: %s", bus_error_message(&error));
- r = -EIO;
- goto finish;
- }
-
- if ((r = bus_check_peercred(bus)) < 0) {
- log_error("Failed to verify owner of bus.");
- goto finish;
- }
-
- if (!(m = dbus_message_new_method_call(
- "com.ubuntu.Upstart",
- "/com/ubuntu/Upstart",
- "com.ubuntu.Upstart0_6",
- "EmitEvent"))) {
-
- log_error("Could not allocate message.");
- r = -ENOMEM;
- goto finish;
- }
-
- dbus_message_iter_init_append(m, &iter);
-
- env1_buf[sizeof(env1_buf)-2] = rl;
- env2_buf[sizeof(env2_buf)-2] = previous;
-
- if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &emit) ||
- !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub) ||
- !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env1) ||
- !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env2) ||
- !dbus_message_iter_close_container(&iter, &sub) ||
- !dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b_false)) {
- log_error("Could not append arguments to message.");
- r = -ENOMEM;
- goto finish;
- }
-
- if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
-
- if (bus_error_is_no_service(&error)) {
- r = -EADDRNOTAVAIL;
- goto finish;
- }
-
- log_error("Failed to issue method call: %s", bus_error_message(&error));
- r = -EIO;
- goto finish;
- }
-
- r = 1;
-
-finish:
- if (bus) {
- dbus_connection_flush(bus);
- dbus_connection_close(bus);
- dbus_connection_unref(bus);
- }
-
- return r;
-}
-
static int talk_initctl(void) {
struct init_request request = {};
int r;
goto done;
}
- /* Hmm, talking to systemd via D-Bus didn't work. Then
- * let's try to talk to Upstart via D-Bus. */
- if (talk_upstart() > 0)
- goto done;
-
/* Nothing else worked, so let's try
* /dev/initctl */
if (talk_initctl() > 0)
log_parse_environment();
log_open();
+ /* Explicitly not on_tty() to avoid setting cached value.
+ * This becomes relevant for piping output which might be
+ * ellipsized. */
+ original_stdout_is_tty = isatty(STDOUT_FILENO);
+
r = parse_argv(argc, argv);
if (r < 0)
goto finish;