#include "install.h"
#include "logs-show.h"
#include "path-util.h"
+#include "socket-util.h"
static const char *arg_type = NULL;
static const char *arg_load_state = NULL;
typedef struct WaitData {
Set *set;
+
+ char *name;
char *result;
} WaitData;
p = set_remove(d->set, (char*) path);
free(p);
- if (*result)
+ if (!isempty(result))
d->result = strdup(result);
+ if (!isempty(unit))
+ d->name = strdup(unit);
+
goto finish;
}
#ifndef LEGACY
}
static int wait_for_jobs(DBusConnection *bus, Set *s) {
- int r;
+ int r = 0;
WaitData d;
assert(bus);
zero(d);
d.set = s;
- if (!dbus_connection_add_filter(bus, wait_filter, &d, NULL)) {
- log_error("Failed to add filter.");
- r = -ENOMEM;
- goto finish;
- }
+ if (!dbus_connection_add_filter(bus, wait_filter, &d, NULL))
+ return log_oom();
- while (!set_isempty(s) &&
- dbus_connection_read_write_dispatch(bus, -1))
- ;
+ while (!set_isempty(s)) {
- if (!arg_quiet && d.result) {
- if (streq(d.result, "timeout"))
- log_error("Job timed out.");
- else if (streq(d.result, "canceled"))
- log_error("Job canceled.");
- else if (streq(d.result, "dependency"))
- log_error("A dependency job failed. See system journal for details.");
- else if (!streq(d.result, "done") && !streq(d.result, "skipped"))
- log_error("Job failed. See system journal and 'systemctl status' for details.");
- }
+ if (!dbus_connection_read_write_dispatch(bus, -1)) {
+ log_error("Disconnected from bus.");
+ return -ECONNREFUSED;
+ }
- if (streq_ptr(d.result, "timeout"))
- r = -ETIME;
- else if (streq_ptr(d.result, "canceled"))
- r = -ECANCELED;
- else if (!streq_ptr(d.result, "done") && !streq_ptr(d.result, "skipped"))
- r = -EIO;
- else
- r = 0;
+ if (!d.result)
+ goto free_name;
- free(d.result);
+ if (!arg_quiet) {
+ if (streq(d.result, "timeout"))
+ log_error("Job for %s timed out.", strna(d.name));
+ 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' 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' for details.", strna(d.name), strna(d.name));
+ }
-finish:
- /* This is slightly dirty, since we don't undo the filter registration. */
+ if (streq_ptr(d.result, "timeout"))
+ r = -ETIME;
+ else if (streq_ptr(d.result, "canceled"))
+ r = -ECANCELED;
+ else if (!streq_ptr(d.result, "done") && !streq_ptr(d.result, "skipped"))
+ r = -EIO;
+ free(d.result);
+ d.result = NULL;
+
+ free_name:
+ free(d.name);
+ d.name = NULL;
+ }
+
+ dbus_connection_remove_filter(bus, wait_filter, &d);
return r;
}
DBusConnection *bus,
const char *unit_name) {
- DBusMessage *reply = NULL;
+ DBusMessage _cleanup_dbus_msg_unref_ *reply = NULL;
DBusMessageIter iter, sub;
char *service_trigger = NULL;
const char *interface = "org.freedesktop.systemd1.Unit",
*triggered_by_property = "TriggeredBy";
- char *unit_path = NULL, *n = NULL;
+ char _cleanup_free_ *unit_path = NULL, *n = NULL;
bool print_warning_label = true;
int r;
n = unit_name_mangle(unit_name);
- unit_path = unit_dbus_path_from_name(n ? n : unit_name);
- free(n);
+ if (!n) {
+ log_oom();
+ return;
+ }
+
+ unit_path = unit_dbus_path_from_name(n);
if (!unit_path) {
- log_error("Could not allocate dbus path.");
- goto finish;
+ log_oom();
+ return;
}
r = bus_method_call_with_reply (
DBUS_TYPE_STRING, &triggered_by_property,
DBUS_TYPE_INVALID);
if (r)
- goto finish;
+ return;
if (!dbus_message_iter_init(reply, &iter) ||
dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
log_error("Failed to parse reply.");
- goto finish;
-
+ return;
}
dbus_message_iter_recurse(&iter, &sub);
if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
log_error("Failed to parse reply.");
- goto finish;
+ return;
}
dbus_message_iter_get_basic(&sub, &service_trigger);
r = check_one_unit(bus, service_trigger, true);
if (r < 0)
- goto finish;
+ return;
if (r == 0) {
if (print_warning_label) {
log_warning("Warning: Stopping %s, but it can still be activated by:", unit_name);
dbus_message_iter_next(&sub);
}
-finish:
- if (reply)
- dbus_message_unref(reply);
-
- free(unit_path);
}
static int start_unit_one(
DBusError *error,
Set *s) {
- DBusMessage *reply = NULL;
+ DBusMessage _cleanup_dbus_msg_unref_ *reply = NULL;
const char *path;
int r;
- char *n;
+ _cleanup_free_ char *n, *p = NULL;
assert(method);
assert(name);
assert(mode);
assert(error);
- assert(arg_no_block || s);
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",
method,
&reply,
error,
- DBUS_TYPE_STRING, n ? (const char **) &n : &name,
+ DBUS_TYPE_STRING, &n,
DBUS_TYPE_STRING, &mode,
DBUS_TYPE_INVALID);
- free(n);
if (r) {
- if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL )
+ if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
/* There's always a fallback possible for
* legacy actions. */
r = -EADDRNOTAVAIL;
else
log_error("Failed to issue method call: %s", bus_error_message(error));
- goto finish;
+
+ 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;
+ return -EIO;
}
- if (need_daemon_reload(bus, name))
- log_warning("Warning: Unit file of created job changed on disk, 'systemctl %s daemon-reload' recommended.",
- arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
-
- if (!arg_no_block) {
- char *p;
+ 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");
- if (!(p = strdup(path))) {
- log_error("Failed to duplicate path.");
- r = -ENOMEM;
- goto finish;
- }
+ if (s) {
+ p = strdup(path);
+ if (!p)
+ return log_oom();
- if ((r = set_put(s, p)) < 0) {
- free(p);
+ r = set_put(s, p);
+ if (r < 0) {
log_error("Failed to add path to set.");
- goto finish;
+ return r;
}
+
+ p = NULL;
}
/* When stopping a unit warn if it can still be triggered by
if (!arg_quiet && streq(method, "StopUnit"))
check_triggering_units(bus, name);
- r = 0;
-
-finish:
- if (reply)
- dbus_message_unref(reply);
-
- return r;
+ return 0;
}
static enum action verb_to_action(const char *verb) {
}
if (!arg_no_block) {
- if ((ret = enable_wait_for_jobs(bus)) < 0) {
+ ret = enable_wait_for_jobs(bus);
+ if (ret < 0) {
log_error("Could not watch jobs: %s", strerror(-ret));
goto finish;
}
- if (!(s = set_new(string_hash_func, string_compare_func))) {
- log_error("Failed to allocate set.");
- ret = -ENOMEM;
+ s = set_new(string_hash_func, string_compare_func);
+ if (!s) {
+ ret = log_oom();
goto finish;
}
}
if (one_name) {
- if ((ret = start_unit_one(bus, method, one_name, mode, &error, s)) <= 0)
- goto finish;
+ ret = start_unit_one(bus, method, one_name, mode, &error, s);
+ if (ret < 0)
+ ret = translate_bus_error_to_exit_status(ret, &error);
} else {
- STRV_FOREACH(name, args+1)
- if ((r = start_unit_one(bus, method, *name, mode, &error, s)) != 0) {
+ STRV_FOREACH(name, args+1) {
+ r = start_unit_one(bus, method, *name, mode, &error, s);
+ if (r < 0) {
ret = translate_bus_error_to_exit_status(r, &error);
dbus_error_free(&error);
}
+ }
}
- if (!arg_no_block)
- if ((r = wait_for_jobs(bus, s)) < 0) {
+ if (!arg_no_block) {
+ r = wait_for_jobs(bus, s);
+ if (r < 0) {
ret = r;
goto finish;
}
+ }
finish:
- if (s)
- set_free_free(s);
-
+ set_free_free(s);
dbus_error_free(&error);
return ret;
* afterwards only the native units remain */
zero(paths);
- r = lookup_paths_init(&paths, MANAGER_SYSTEM, false, NULL, NULL, NULL);
+ r = lookup_paths_init(&paths, SYSTEMD_SYSTEM, false, NULL, NULL, NULL);
if (r < 0)
return r;
return r;
}
+static int mangle_names(char **original_names, char ***mangled_names) {
+ char **i, **l, **name;
+
+ l = new(char*, strv_length(original_names) + 1);
+ if (!l)
+ return log_oom();
+
+ i = l;
+ STRV_FOREACH(name, original_names) {
+ *i = unit_name_mangle(*name);
+ if (!*i) {
+ strv_free(l);
+ return log_oom();
+ }
+
+ i++;
+ }
+
+ *i = NULL;
+ *mangled_names = l;
+
+ return 0;
+}
+
static int enable_unit(DBusConnection *bus, char **args) {
const char *verb = args[0];
UnitFileChange *changes = NULL;
DBusMessage *m = NULL, *reply = NULL;
int r;
DBusError error;
+ char **mangled_names = NULL;
r = enable_sysv_units(args);
if (r < 0)
dbus_message_iter_init_append(m, &iter);
- r = bus_append_strv_iter(&iter, args+1);
+ 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.");
goto finish;
unit_file_changes_free(changes, n_changes);
dbus_error_free(&error);
+
+ strv_free(mangled_names);
+
return r;
}