+/* SPDX-License-Identifier: LGPL-2.1+ */
/***
This file is part of systemd.
user = arg_scope != UNIT_FILE_SYSTEM;
+ if (!user && sd_booted() <= 0) {
+ /* Print a friendly message when the local system is actually not running systemd as PID 1. */
+ log_error("System has not been booted with systemd as init system (PID 1). Can't operate.");
+ return -EHOSTDOWN;
+ }
+
if (focus == BUS_MANAGER)
r = bus_connect_transport_systemd(arg_transport, arg_host, user, &busses[focus]);
else
ask_password_agent_open();
}
-static void polkit_agent_open_if_enabled(void) {
-
+static void polkit_agent_open_maybe(void) {
/* Open the polkit agent as a child process if necessary */
- if (!arg_ask_password)
- return;
-
if (arg_scope != UNIT_FILE_SYSTEM)
return;
- if (arg_transport != BUS_TRANSPORT_LOCAL)
- return;
-
- polkit_agent_open();
+ polkit_agent_open_if_enabled(arg_transport, arg_ask_password);
}
static OutputFlags get_output_flags(void) {
return
arg_all * OUTPUT_SHOW_ALL |
- arg_full * OUTPUT_FULL_WIDTH |
- (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
+ (arg_full || !on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
colors_enabled() * OUTPUT_COLOR |
!arg_quiet * OUTPUT_WARN_CUTOFF;
}
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
sd_bus *bus;
- polkit_agent_open_if_enabled();
+ polkit_agent_open_maybe();
r = acquire_bus(BUS_MANAGER, &bus);
if (r < 0)
if (r < 0)
return r;
- polkit_agent_open_if_enabled();
+ polkit_agent_open_maybe();
STRV_FOREACH(name, strv_skip(argv, 1)) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
return r;
ask_password_agent_open_if_enabled();
- polkit_agent_open_if_enabled();
+ polkit_agent_open_maybe();
if (arg_action == ACTION_SYSTEMCTL) {
enum action action;
return r;
}
-#ifdef ENABLE_LOGIND
+#if ENABLE_LOGIND
static int logind_set_wall_message(void) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
sd_bus *bus;
/* Ask systemd-logind, which might grant access to unprivileged users
* through PolicyKit */
static int logind_reboot(enum action a) {
-#ifdef ENABLE_LOGIND
+#if ENABLE_LOGIND
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
const char *method, *description;
sd_bus *bus;
switch (a) {
+ case ACTION_POWEROFF:
+ method = "PowerOff";
+ description = "power off system";
+ break;
+
case ACTION_REBOOT:
method = "Reboot";
description = "reboot system";
break;
- case ACTION_POWEROFF:
- method = "PowerOff";
- description = "power off system";
+ case ACTION_HALT:
+ method = "Halt";
+ description = "halt system";
break;
case ACTION_SUSPEND:
return -EINVAL;
}
- polkit_agent_open_if_enabled();
+ polkit_agent_open_maybe();
(void) logind_set_wall_message();
r = sd_bus_call_method(
}
static int logind_check_inhibitors(enum action a) {
-#ifdef ENABLE_LOGIND
+#if ENABLE_LOGIND
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
_cleanup_strv_free_ char **sessions = NULL;
const char *what, *who, *why, *mode;
return log_oom();
if (!pid_is_valid((pid_t) pid)) {
- log_error("Invalid PID %" PRIu32 ".", pid);
+ log_error("Invalid PID "PID_FMT".", (pid_t) pid);
return -ERANGE;
}
if (sd_session_get_class(*s, &class) < 0 || !streq(class, "user"))
continue;
- if (sd_session_get_type(*s, &type) < 0 || !STR_IN_SET(type, "x11", "tty"))
+ if (sd_session_get_type(*s, &type) < 0 || !STR_IN_SET(type, "x11", "wayland", "tty", "mir"))
continue;
sd_session_get_tty(*s, &tty);
}
static int logind_prepare_firmware_setup(void) {
-#ifdef ENABLE_LOGIND
+#if ENABLE_LOGIND
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
sd_bus *bus;
int r;
if (IN_SET(a,
ACTION_POWEROFF,
ACTION_REBOOT,
+ ACTION_HALT,
ACTION_SUSPEND,
ACTION_HIBERNATE,
ACTION_HYBRID_SLEEP)) {
/* requested operation is not supported or already in progress */
return r;
- /* On all other errors, try low-level operation */
- }
+ /* On all other errors, try low-level operation. In order to minimize the difference between
+ * operation with and without logind, we explicitly enable non-blocking mode for this, as
+ * logind's shutdown operations are always non-blocking. */
+
+ arg_no_block = true;
+
+ } else if (IN_SET(a, ACTION_EXIT, ACTION_KEXEC))
+ /* Since exit/kexec are so close in behaviour to power-off/reboot, let's also make them
+ * asynchronous, in order to not confuse the user needlessly with unexpected behaviour. */
+ arg_no_block = true;
r = start_unit(argc, argv, userdata);
}
if (r < 0)
return r;
- polkit_agent_open_if_enabled();
+ polkit_agent_open_maybe();
if (!arg_kill_who)
arg_kill_who = "all";
uint64_t tasks_current;
uint64_t tasks_max;
+ uint64_t ip_ingress_bytes;
+ uint64_t ip_egress_bytes;
+
LIST_HEAD(ExecStatusInfo, exec);
} UnitStatusInfo;
if (i->status_errno > 0)
printf(" Error: %i (%s)\n", i->status_errno, strerror(i->status_errno));
+ if (i->ip_ingress_bytes != (uint64_t) -1 && i->ip_egress_bytes != (uint64_t) -1) {
+ char buf_in[FORMAT_BYTES_MAX], buf_out[FORMAT_BYTES_MAX];
+
+ printf(" IP: %s in, %s out\n",
+ format_bytes(buf_in, sizeof(buf_in), i->ip_ingress_bytes),
+ format_bytes(buf_out, sizeof(buf_out), i->ip_egress_bytes));
+ }
+
if (i->tasks_current != (uint64_t) -1) {
printf(" Tasks: %" PRIu64, i->tasks_current);
i->next_elapse_monotonic = u;
else if (streq(name, "NextElapseUSecRealtime"))
i->next_elapse_real = u;
+ else if (streq(name, "IPIngressBytes"))
+ i->ip_ingress_bytes = u;
+ else if (streq(name, "IPEgressBytes"))
+ i->ip_egress_bytes = u;
break;
}
.cpu_usage_nsec = (uint64_t) -1,
.tasks_current = (uint64_t) -1,
.tasks_max = (uint64_t) -1,
+ .ip_ingress_bytes = (uint64_t) -1,
+ .ip_egress_bytes = (uint64_t) -1,
};
int r;
if (streq_ptr(mi.state, "degraded")) {
on = ansi_highlight_red();
off = ansi_normal();
- } else if (!streq_ptr(mi.state, "running")) {
+ } else if (streq_ptr(mi.state, "running")) {
+ on = ansi_highlight_green();
+ off = ansi_normal();
+ } else {
on = ansi_highlight_yellow();
off = ansi_normal();
- } else
- on = off = "";
+ }
printf("%s%s%s %s\n", on, special_glyph(BLACK_CIRCLE), off, arg_host ? arg_host : hn);
if (r < 0)
return r;
- polkit_agent_open_if_enabled();
+ polkit_agent_open_maybe();
r = sd_bus_message_new_method_call(
bus,
if (r < 0)
return r;
- polkit_agent_open_if_enabled();
+ polkit_agent_open_maybe();
switch (arg_action) {
if (r < 0)
return r;
- polkit_agent_open_if_enabled();
+ polkit_agent_open_maybe();
method =
streq(argv[0], "clear-jobs") ||
if (r < 0)
return r;
- polkit_agent_open_if_enabled();
+ polkit_agent_open_maybe();
r = expand_names(bus, strv_skip(argv, 1), NULL, &names);
if (r < 0)
if (r < 0)
return r;
- polkit_agent_open_if_enabled();
+ polkit_agent_open_maybe();
method = streq(argv[0], "set-environment")
? "SetEnvironment"
if (r < 0)
return r;
- polkit_agent_open_if_enabled();
+ polkit_agent_open_maybe();
r = sd_bus_message_new_method_call(
bus,
static int enable_sysv_units(const char *verb, char **args) {
int r = 0;
-#if defined(HAVE_SYSV_COMPAT)
+#if HAVE_SYSV_COMPAT
_cleanup_lookup_paths_free_ LookupPaths paths = {};
unsigned f = 0;
if (r < 0)
return r;
- polkit_agent_open_if_enabled();
+ polkit_agent_open_maybe();
if (streq(verb, "enable")) {
method = "EnableUnitFiles";
if (r < 0)
return r;
- polkit_agent_open_if_enabled();
+ polkit_agent_open_maybe();
r = sd_bus_message_new_method_call(
bus,
if (r < 0)
return r;
- polkit_agent_open_if_enabled();
+ polkit_agent_open_maybe();
r = sd_bus_call_method(
bus,
" --no-pager Do not pipe output into a pager\n"
" --no-ask-password\n"
" Do not ask for system passwords\n"
- " --global Enable/disable unit files globally\n"
- " --runtime Enable unit files only temporarily until next reboot\n"
+ " --global Enable/disable/mask unit files globally\n"
+ " --runtime Enable/disable/mask unit files temporarily until next\n"
+ " reboot\n"
" -f --force When enabling unit files, override existing symlinks\n"
" When shutting down, execute action immediately\n"
" --preset-mode= Apply only enable, only disable, or all presets\n"
- " --root=PATH Enable unit files in the specified root directory\n"
+ " --root=PATH Enable/disable/mask unit files in the specified root\n"
+ " directory\n"
" -n --lines=INTEGER Number of journal entries to show\n"
" -o --output=STRING Change journal output mode (short, short-precise,\n"
" short-iso, short-iso-precise, short-full,\n"
assert(argv);
if (utmp_get_runlevel(&runlevel, NULL) >= 0)
- if (runlevel == '0' || runlevel == '6')
+ if (IN_SET(runlevel, '0', '6'))
arg_force = 2;
while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0)
return systemctl_parse_argv(argc, argv);
}
-#ifdef HAVE_SYSV_COMPAT
+#if HAVE_SYSV_COMPAT
_pure_ static int action_to_runlevel(void) {
static const char table[_ACTION_MAX] = {
#endif
static int talk_initctl(void) {
-#ifdef HAVE_SYSV_COMPAT
+#if HAVE_SYSV_COMPAT
struct init_request request = {
.magic = INIT_MAGIC,
.sleeptime = 0,
static int logind_schedule_shutdown(void) {
-#ifdef ENABLE_LOGIND
+#if ENABLE_LOGIND
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
char date[FORMAT_TIMESTAMP_MAX];
const char *action;
/* Try logind if we are a normal user and no special
* mode applies. Maybe PolicyKit allows us to shutdown
* the machine. */
- if (IN_SET(arg_action, ACTION_POWEROFF, ACTION_REBOOT)) {
+ if (IN_SET(arg_action, ACTION_POWEROFF, ACTION_REBOOT, ACTION_HALT)) {
r = logind_reboot(arg_action);
if (r >= 0)
return r;
}
static int logind_cancel_shutdown(void) {
-#ifdef ENABLE_LOGIND
+#if ENABLE_LOGIND
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
sd_bus *bus;
int r;