#include "bus-common-errors.h"
#include "bus-error.h"
#include "bus-message.h"
+#include "bus-unit-util.h"
#include "bus-util.h"
#include "cgroup-show.h"
#include "cgroup-util.h"
if (arg_all)
return true;
+ /* Note that '--all' is not purely a state filter, but also a
+ * filter that hides units that "follow" other units (which is
+ * used for device units that appear under different names). */
+ if (!isempty(u->following))
+ return false;
+
if (!strv_isempty(arg_states))
return true;
if (u->job_id > 0)
return true;
- if (streq(u->active_state, "inactive") || u->following[0])
+ if (streq(u->active_state, "inactive"))
return false;
return true;
return 0;
}
-static void dump_unit_file_changes(const UnitFileChange *changes, unsigned n_changes) {
- unsigned i;
-
- assert(changes || n_changes == 0);
-
- for (i = 0; i < n_changes; i++) {
- if (changes[i].type == UNIT_FILE_SYMLINK)
- log_info("Created symlink %s, pointing to %s.", changes[i].path, changes[i].source);
- else
- log_info("Removed %s.", changes[i].path);
- }
-}
-
static int set_default(int argc, char *argv[], void *userdata) {
_cleanup_free_ char *unit = NULL;
int r;
unsigned n_changes = 0;
r = unit_file_set_default(arg_scope, arg_root, unit, true, &changes, &n_changes);
- if (r < 0)
- return log_error_errno(r, "Failed to set default target: %m");
-
- if (!arg_quiet)
- dump_unit_file_changes(changes, n_changes);
-
+ unit_file_dump_changes(r, "set default", changes, n_changes, arg_quiet);
unit_file_changes_free(changes, n_changes);
- r = 0;
+ return r;
} else {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
NULL,
"y", code);
if (r < 0)
- return log_error_errno(r, "Failed to execute operation: %s", bus_error_message(&error, r));
+ return log_error_errno(r, "Failed to set exit code: %s", bus_error_message(&error, r));
return 0;
}
/* --fail was specified */
if (streq(arg_job_mode, "fail"))
- kill_who = strjoina(arg_kill_who, "-fail", NULL);
+ kill_who = strjoina(arg_kill_who, "-fail");
r = expand_names(bus, strv_skip(argv, 1), NULL, &names);
if (r < 0)
} UnitStatusInfo;
static void print_status_info(
+ sd_bus *bus,
UnitStatusInfo *i,
bool *ellipsized) {
char since2[FORMAT_TIMESTAMP_MAX], *s2;
const char *path;
char **t, **t2;
+ int r;
assert(i);
printf(" CPU: %s\n", format_timespan(buf, sizeof(buf), i->cpu_usage_nsec / NSEC_PER_USEC, USEC_PER_MSEC));
}
- if (i->control_group &&
- (i->main_pid > 0 || i->control_pid > 0 ||
- (!IN_SET(arg_transport, BUS_TRANSPORT_LOCAL, BUS_TRANSPORT_MACHINE) || cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, i->control_group) == 0))) {
+ if (i->control_group)
+ printf(" CGroup: %s\n", i->control_group);
+
+ {
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ static const char prefix[] = " ";
unsigned c;
- printf(" CGroup: %s\n", i->control_group);
+ c = columns();
+ if (c > sizeof(prefix) - 1)
+ c -= sizeof(prefix) - 1;
+ else
+ c = 0;
- if (IN_SET(arg_transport,
- BUS_TRANSPORT_LOCAL,
- BUS_TRANSPORT_MACHINE)) {
+ r = unit_show_processes(bus, i->id, i->control_group, prefix, c, get_output_flags(), &error);
+ if (r == -EBADR) {
unsigned k = 0;
pid_t extra[2];
- static const char prefix[] = " ";
- c = columns();
- if (c > sizeof(prefix) - 1)
- c -= sizeof(prefix) - 1;
- else
- c = 0;
+ /* Fallback for older systemd versions where the GetUnitProcesses() call is not yet available */
if (i->main_pid > 0)
extra[k++] = i->main_pid;
if (i->control_pid > 0)
extra[k++] = i->control_pid;
- show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER, i->control_group, prefix, c, false, extra, k, get_output_flags());
- }
+ show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER, i->control_group, prefix, c, extra, k, get_output_flags());
+ } else if (r < 0)
+ log_warning_errno(r, "Failed to dump process list, ignoring: %s", bus_error_message(&error, r));
}
if (i->id && arg_transport == BUS_TRANSPORT_LOCAL)
if (streq(verb, "help"))
show_unit_help(&info);
else
- print_status_info(&info, ellipsized);
+ print_status_info(bus, &info, ellipsized);
}
strv_free(info.documentation);
else
c = 0;
- show_cgroup(SYSTEMD_CGROUP_CONTROLLER, strempty(mi.control_group), prefix, c, false, get_output_flags());
+ show_cgroup(SYSTEMD_CGROUP_CONTROLLER, strempty(mi.control_group), prefix, c, get_output_flags());
}
return 0;
* reply */
r = 0;
else if (r < 0)
- return log_error_errno(r, "Failed to execute operation: %s", bus_error_message(&error, r));
+ return log_error_errno(r, "Failed to reload daemon: %s", bus_error_message(&error, r));
return r < 0 ? r : 0;
}
continue;
j = unit_file_exists(arg_scope, &paths, name);
- if (j < 0)
+ if (j < 0 && !IN_SET(j, -ELOOP, -ERFKILL, -EADDRNOTAVAIL))
return log_error_errno(j, "Failed to lookup unit file state: %m");
- found_native = j > 0;
+ found_native = j != 0;
/* If we have both a native unit and a SysV script, enable/disable them both (below); for is-enabled,
* prefer the native unit */
UnitFileChange *changes = NULL;
unsigned n_changes = 0;
int carries_install_info = -1;
+ bool ignore_carries_install_info = false;
int r;
if (!argv[1])
r = unit_file_link(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
else if (streq(verb, "preset")) {
r = unit_file_preset(arg_scope, arg_runtime, arg_root, names, arg_preset_mode, arg_force, &changes, &n_changes);
- carries_install_info = r;
} else if (streq(verb, "mask"))
r = unit_file_mask(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
else if (streq(verb, "unmask"))
else
assert_not_reached("Unknown verb");
- if (r == -ESHUTDOWN)
- return log_error_errno(r, "Unit file is masked.");
- if (r == -EADDRNOTAVAIL)
- return log_error_errno(r, "Unit file is transient or generated.");
- if (r == -ELOOP)
- return log_error_errno(r, "Refusing to operate on linked unit file.");
+ unit_file_dump_changes(r, verb, changes, n_changes, arg_quiet);
if (r < 0)
- return log_error_errno(r, "Operation failed: %m");
-
- if (!arg_quiet)
- dump_unit_file_changes(changes, n_changes);
-
+ return r;
r = 0;
} else {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL, *m = NULL;
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- int expect_carries_install_info = false;
+ bool expect_carries_install_info = false;
bool send_runtime = true, send_force = true, send_preset_mode = false;
const char *method;
sd_bus *bus;
method = "PresetUnitFiles";
expect_carries_install_info = true;
+ ignore_carries_install_info = true;
} else if (streq(verb, "mask"))
method = "MaskUnitFiles";
else if (streq(verb, "unmask")) {
r = sd_bus_call(bus, m, 0, &error, &reply);
if (r < 0)
- return log_error_errno(r, "Failed to execute operation: %s", bus_error_message(&error, r));
+ return log_error_errno(r, "Failed to %s unit: %s", verb, bus_error_message(&error, r));
if (expect_carries_install_info) {
r = sd_bus_message_read(reply, "b", &carries_install_info);
r = 0;
}
- if (carries_install_info == 0)
- log_warning("The unit files have no [Install] section. They are not meant to be enabled\n"
- "using systemctl.\n"
+ if (carries_install_info == 0 && !ignore_carries_install_info)
+ log_warning("The unit files have no installation config (WantedBy, RequiredBy, Also, Alias\n"
+ "settings in the [Install] section, and DefaultInstance for template units).\n"
+ "This means they are not meant to be enabled 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");
+ " D-Bus, udev, scripted systemctl call, ...).\n"
+ "4) In case of template units, the unit is meant to be enabled with some\n"
+ " instance name specified.");
if (arg_now && n_changes > 0 && STR_IN_SET(argv[0], "enable", "disable", "mask")) {
char *new_args[n_changes + 2];
unsigned n_changes = 0;
r = unit_file_add_dependency(arg_scope, arg_runtime, arg_root, names, target, dep, arg_force, &changes, &n_changes);
- if (r == -ESHUTDOWN)
- return log_error_errno(r, "Unit file is masked.");
- if (r == -EADDRNOTAVAIL)
- return log_error_errno(r, "Unit file is transient or generated.");
- if (r < 0)
- return log_error_errno(r, "Can't add dependency: %m");
-
- if (!arg_quiet)
- dump_unit_file_changes(changes, n_changes);
-
+ unit_file_dump_changes(r, "add dependency on", changes, n_changes, arg_quiet);
unit_file_changes_free(changes, n_changes);
-
+ return r;
} else {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL, *m = NULL;
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
r = sd_bus_call(bus, m, 0, &error, &reply);
if (r < 0)
- return log_error_errno(r, "Failed to execute operation: %s", bus_error_message(&error, r));
+ return log_error_errno(r, "Failed to add dependency: %s", bus_error_message(&error, r));
r = bus_deserialize_and_dump_unit_file_changes(reply, arg_quiet, NULL, NULL);
if (r < 0)
return r;
- if (!arg_no_reload)
- r = daemon_reload(argc, argv, userdata);
- else
- r = 0;
+ if (arg_no_reload)
+ return 0;
+ return daemon_reload(argc, argv, userdata);
}
-
- return r;
}
static int preset_all(int argc, char *argv[], void *userdata) {
- UnitFileChange *changes = NULL;
- unsigned n_changes = 0;
int r;
if (install_client_side()) {
+ UnitFileChange *changes = NULL;
+ unsigned n_changes = 0;
r = unit_file_preset_all(arg_scope, arg_runtime, arg_root, arg_preset_mode, arg_force, &changes, &n_changes);
- if (r < 0) {
- log_error_errno(r, "Operation failed: %m");
- goto finish;
- }
-
- if (!arg_quiet)
- dump_unit_file_changes(changes, n_changes);
-
- r = 0;
-
+ unit_file_dump_changes(r, "preset", changes, n_changes, arg_quiet);
+ unit_file_changes_free(changes, n_changes);
+ return r;
} else {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
arg_runtime,
arg_force);
if (r < 0)
- return log_error_errno(r, "Failed to execute operation: %s", bus_error_message(&error, r));
+ return log_error_errno(r, "Failed to preset all units: %s", bus_error_message(&error, r));
r = bus_deserialize_and_dump_unit_file_changes(reply, arg_quiet, NULL, NULL);
if (r < 0)
return r;
- if (!arg_no_reload)
- r = daemon_reload(argc, argv, userdata);
- else
- r = 0;
+ if (arg_no_reload)
+ return 0;
+ return daemon_reload(argc, argv, userdata);
}
-
-finish:
- unit_file_changes_free(changes, n_changes);
-
- return r;
}
static int unit_is_enabled(int argc, char *argv[], void *userdata) {
return r;
STRV_FOREACH(name, names) {
- _cleanup_free_ char *path = NULL;
- char *new_path, *tmp_path;
+ _cleanup_free_ char *path = NULL, *new_path = NULL, *tmp_path = NULL;
r = unit_find_paths(bus, *name, &lp, &path, NULL);
if (r < 0)
r = strv_push_pair(paths, new_path, tmp_path);
if (r < 0)
return log_oom();
+ new_path = tmp_path = NULL;
}
return 0;
break;
case ARG_ROOT:
- r = parse_path_argument_and_warn(optarg, true, &arg_root);
+ r = parse_path_argument_and_warn(optarg, false, &arg_root);
if (r < 0)
return r;
break;