+/* SPDX-License-Identifier: LGPL-2.1+ */
/***
This file is part of systemd.
#include "dropin.h"
#include "efivars.h"
#include "env-util.h"
+#include "escape.h"
#include "exit-status.h"
#include "fd-util.h"
#include "fileio.h"
static usec_t arg_when = 0;
static char *argv_cmdline = NULL;
static enum action {
- _ACTION_INVALID,
ACTION_SYSTEMCTL,
ACTION_HALT,
ACTION_POWEROFF,
ACTION_REEXEC,
ACTION_RUNLEVEL,
ACTION_CANCEL_SHUTDOWN,
- _ACTION_MAX
+ _ACTION_MAX,
+ _ACTION_INVALID = -1
} arg_action = ACTION_SYSTEMCTL;
static BusTransport arg_transport = BUS_TRANSPORT_LOCAL;
static const char *arg_host = NULL;
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;
}
ansi_normal());
for (u = units; u < units + c; u++) {
+ const char *on_underline = NULL, *on_color = NULL, *off = NULL, *id;
_cleanup_free_ char *e = NULL;
- const char *on, *off, *on_underline = "", *off_underline = "";
- const char *id;
- bool underline = false;
+ bool underline;
+
+ underline = u + 1 < units + c &&
+ !streq(unit_type_suffix(u->path), unit_type_suffix((u + 1)->path));
- if (u + 1 < units + c &&
- !streq(unit_type_suffix(u->path), unit_type_suffix((u + 1)->path))) {
+ if (underline)
on_underline = ansi_underline();
- off_underline = ansi_normal();
- underline = true;
- }
if (IN_SET(u->state,
UNIT_FILE_MASKED,
UNIT_FILE_MASKED_RUNTIME,
UNIT_FILE_DISABLED,
UNIT_FILE_BAD))
- on = underline ? ansi_highlight_red_underline() : ansi_highlight_red();
+ on_color = underline ? ansi_highlight_red_underline() : ansi_highlight_red();
else if (u->state == UNIT_FILE_ENABLED)
- on = underline ? ansi_highlight_green_underline() : ansi_highlight_green();
- else
- on = on_underline;
- off = off_underline;
+ on_color = underline ? ansi_highlight_green_underline() : ansi_highlight_green();
+
+ if (on_underline || on_color)
+ off = ansi_normal();
id = basename(u->path);
e = arg_full ? NULL : ellipsize(id, id_cols, 33);
- printf("%s%-*s %s%-*s%s%s\n",
- on_underline,
+ printf("%s%-*s %s%-*s%s\n",
+ strempty(on_underline),
id_cols, e ? e : id,
- on, state_cols, unit_file_state_to_string(u->state), off,
- off_underline);
+ strempty(on_color), state_cols, unit_file_state_to_string(u->state), strempty(off));
}
if (!arg_no_legend)
for (m = machine_infos; m < machine_infos + n; m++) {
namelen = MAX(namelen, strlen(m->name) + (m->is_host ? sizeof(" (host)") - 1 : 0));
- statelen = MAX(statelen, m->state ? strlen(m->state) : 0);
+ statelen = MAX(statelen, strlen_ptr(m->state));
failedlen = MAX(failedlen, DECIMAL_STR_WIDTH(m->n_failed_units));
jobslen = MAX(jobslen, DECIMAL_STR_WIDTH(m->n_jobs));
_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;
assert(lp);
assert(unit_name);
- assert(unit_path);
STRV_FOREACH(p, lp->search_path) {
_cleanup_free_ char *path = NULL, *lpath = NULL;
if (r < 0)
return log_error_errno(r, "Failed to access path '%s': %m", path);
- *unit_path = lpath;
- lpath = NULL;
+ if (unit_path) {
+ *unit_path = lpath;
+ lpath = NULL;
+ }
return 1;
}
return 0;
}
+static int unit_find_template_path(
+ const char *unit_name,
+ LookupPaths *lp,
+ char **fragment_path,
+ char **template) {
+
+ _cleanup_free_ char *_template = NULL;
+ int r;
+
+ /* Returns 1 if a fragment was found, 0 if not found, negative on error. */
+
+ r = unit_file_find_path(lp, unit_name, fragment_path);
+ if (r != 0)
+ return r; /* error or found a real unit */
+
+ r = unit_name_template(unit_name, &_template);
+ if (r == -EINVAL)
+ return 0; /* not a template, does not exist */
+ if (r < 0)
+ return log_error_errno(r, "Failed to determine template name: %m");
+
+ r = unit_file_find_path(lp, _template, fragment_path);
+ if (r < 0)
+ return r;
+
+ if (template) {
+ *template = _template;
+ _template = NULL;
+ }
+ return r;
+}
+
static int unit_find_paths(
sd_bus *bus,
const char *unit_name,
return log_error_errno(r, "Failed to get DropInPaths: %s", bus_error_message(&error, r));
}
} else {
- _cleanup_set_free_ Set *names;
+ _cleanup_set_free_ Set *names = NULL;
_cleanup_free_ char *template = NULL;
names = set_new(NULL);
if (!names)
return log_oom();
- r = unit_file_find_path(lp, unit_name, &path);
+ r = unit_find_template_path(unit_name, lp, &path, &template);
if (r < 0)
return r;
- if (r == 0) {
- r = unit_name_template(unit_name, &template);
- if (r < 0 && r != -EINVAL)
- return log_error_errno(r, "Failed to determine template name: %m");
- if (r >= 0) {
- r = unit_file_find_path(lp, template, &path);
- if (r < 0)
- return r;
- }
- }
-
- if (path)
+ if (r > 0)
/* We found the unit file. If we followed symlinks, this name might be
* different then the unit_name with started with. Look for dropins matching
* that "final" name. */
static enum action verb_to_action(const char *verb) {
enum action i;
- for (i = _ACTION_INVALID; i < _ACTION_MAX; i++)
+ for (i = 0; i < _ACTION_MAX; i++)
if (streq_ptr(action_table[i].verb, verb))
return i;
char **name;
int r = 0;
- if (arg_wait && !strstr(argv[0], "start")) {
- log_error("--wait may only be used with a command that starts units.");
+ if (arg_wait && !STR_IN_SET(argv[0], "start", "restart")) {
+ log_error("--wait may only be used with the 'start' or 'restart' commands.");
return -EINVAL;
}
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;
- method = verb_to_method(argv[0]);
action = verb_to_action(argv[0]);
- if (streq(argv[0], "isolate")) {
- mode = "isolate";
- suffix = ".target";
- } else
- mode = action_table[action].mode ?: arg_job_mode;
+ if (action != _ACTION_INVALID) {
+ method = "StartUnit";
+ mode = action_table[action].mode;
+ one_name = action_table[action].target;
+ } else {
+ if (streq(argv[0], "isolate")) {
+ method = "StartUnit";
+ mode = "isolate";
- one_name = action_table[action].target;
+ suffix = ".target";
+ } else {
+ method = verb_to_method(argv[0]);
+ mode = arg_job_mode;
+ }
+ one_name = NULL;
+ }
} else {
- assert(arg_action < ELEMENTSOF(action_table));
+ assert(arg_action >= 0 && arg_action < _ACTION_MAX);
assert(action_table[arg_action].target);
+ assert(action_table[arg_action].mode);
method = "StartUnit";
-
mode = action_table[arg_action].mode;
one_name = action_table[arg_action].target;
}
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;
if (!sv)
return log_oom();
- if ((pid_t) pid < 0)
- return log_error_errno(ERANGE, "Bad PID %"PRIu32": %m", pid);
+ if (!pid_is_valid((pid_t) pid)) {
+ log_error("Invalid PID "PID_FMT".", (pid_t) pid);
+ return -ERANGE;
+ }
if (!strv_contains(sv,
IN_SET(a,
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";
bool failed_assert_negate;
const char *failed_assert;
const char *failed_assert_parameter;
+ usec_t next_elapse_real;
+ usec_t next_elapse_monotonic;
/* Socket */
unsigned n_accepted;
uint64_t tasks_current;
uint64_t tasks_max;
+ uint64_t ip_ingress_bytes;
+ uint64_t ip_egress_bytes;
+
LIST_HEAD(ExecStatusInfo, exec);
} UnitStatusInfo;
else
printf("\n");
+ if (endswith(i->id, ".timer")) {
+ char tstamp1[FORMAT_TIMESTAMP_RELATIVE_MAX],
+ tstamp2[FORMAT_TIMESTAMP_MAX];
+ char *next_rel_time, *next_time;
+ dual_timestamp nw, next = {i->next_elapse_real,
+ i->next_elapse_monotonic};
+ usec_t next_elapse;
+
+ printf(" Trigger: ");
+
+ dual_timestamp_get(&nw);
+ next_elapse = calc_next_elapse(&nw, &next);
+ next_rel_time = format_timestamp_relative(tstamp1,
+ sizeof(tstamp1),
+ next_elapse);
+ next_time = format_timestamp(tstamp2,
+ sizeof(tstamp2),
+ next_elapse);
+
+ if (next_time && next_rel_time)
+ printf("%s; %s\n", next_time, next_rel_time);
+ else
+ printf("n/a\n");
+ }
+
if (!i->condition_result && i->condition_timestamp > 0) {
UnitCondition *c;
int n = 0;
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->tasks_max = u;
else if (streq(name, "CPUUsageNSec"))
i->cpu_usage_nsec = u;
+ else if (streq(name, "NextElapseUSecMonotonic"))
+ 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)
return r;
}
+static int print_variable(const char *s) {
+ const char *sep;
+ _cleanup_free_ char *esc = NULL;
+
+ sep = strchr(s, '=');
+ if (!sep) {
+ log_error("Invalid environment block");
+ return -EUCLEAN;
+ }
+
+ esc = shell_maybe_quote(sep + 1, ESCAPE_POSIX);
+ if (!esc)
+ return log_oom();
+
+ printf("%.*s=%s\n", (int)(sep-s), s, esc);
+ return 0;
+}
+
static int show_environment(int argc, char *argv[], void *userdata) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
if (r < 0)
return bus_log_parse_error(r);
- while ((r = sd_bus_message_read_basic(reply, SD_BUS_TYPE_STRING, &text)) > 0)
- puts(text);
+ while ((r = sd_bus_message_read_basic(reply, SD_BUS_TYPE_STRING, &text)) > 0) {
+ r = print_variable(text);
+ if (r < 0)
+ return r;
+ }
if (r < 0)
return bus_log_parse_error(r);
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 (!l)
return log_oom();
- log_info("Executing: %s", l);
+ if (!arg_quiet)
+ log_info("Executing: %s", l);
pid = fork();
if (pid < 0)
return 0;
}
+static int normalize_filenames(char **names) {
+ char **u;
+ int r;
+
+ STRV_FOREACH(u, names)
+ if (!path_is_absolute(*u)) {
+ char* normalized_path;
+
+ if (!isempty(arg_root)) {
+ log_error("Non-absolute paths are not allowed when --root is used: %s", *u);
+ return -EINVAL;
+ }
+
+ if (!strchr(*u,'/')) {
+ log_error("Link argument does contain at least one directory separator: %s", *u);
+ return -EINVAL;
+ }
+
+ r = path_make_absolute_cwd(*u, &normalized_path);
+ if (r < 0)
+ return r;
+
+ free_and_replace(*u, normalized_path);
+ }
+
+ return 0;
+}
+
static int normalize_names(char **names, bool warn_if_path) {
char **u;
bool was_path = false;
return 0;
}
-static int unit_exists(const char *unit) {
+static int unit_exists(LookupPaths *lp, const char *unit) {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_free_ char *path = NULL;
sd_bus *bus;
int r;
+ if (unit_name_is_valid(unit, UNIT_NAME_TEMPLATE))
+ return unit_find_template_path(unit, lp, NULL, NULL);
+
path = unit_dbus_path_from_name(unit);
if (!path)
return log_oom();
return r;
}
+ if (streq(verb, "link")) {
+ r = normalize_filenames(names);
+ if (r < 0)
+ return r;
+ }
+
if (install_client_side()) {
UnitFileFlags flags;
sd_bus *bus;
if (STR_IN_SET(verb, "mask", "unmask")) {
- r = unit_exists(*names);
+ char **name;
+ _cleanup_lookup_paths_free_ LookupPaths lp = {};
+
+ r = lookup_paths_init(&lp, arg_scope, 0, arg_root);
if (r < 0)
return r;
- if (r == 0)
- log_notice("Unit %s does not exist, proceeding anyway.", *names);
+
+ STRV_FOREACH(name, names) {
+ r = unit_exists(&lp, *name);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ log_notice("Unit %s does not exist, proceeding anyway.", *names);
+ }
}
r = acquire_bus(BUS_MANAGER, &bus);
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"
for (i = 0; i < _AUTOMOUNT_STATE_MAX; i++)
puts(automount_state_to_string(i));
- if (!arg_no_legend)
- puts("\nAvailable busname unit substates:");
- for (i = 0; i < _BUSNAME_STATE_MAX; i++)
- puts(busname_state_to_string(i));
-
if (!arg_no_legend)
puts("\nAvailable device unit substates:");
for (i = 0; i < _DEVICE_STATE_MAX; i++)
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] = {
[ACTION_RESCUE] = '1'
};
- assert(arg_action < _ACTION_MAX);
+ assert(arg_action >= 0 && arg_action < _ACTION_MAX);
return table[arg_action];
}
#endif
static int talk_initctl(void) {
-#ifdef HAVE_SYSV_COMPAT
+#if HAVE_SYSV_COMPAT
struct init_request request = {
.magic = INIT_MAGIC,
.sleeptime = 0,
switch (a) {
case ACTION_HALT:
- log_info("Halting.");
+ if (!arg_quiet)
+ log_info("Halting.");
(void) reboot(RB_HALT_SYSTEM);
return -errno;
case ACTION_POWEROFF:
- log_info("Powering off.");
+ if (!arg_quiet)
+ log_info("Powering off.");
(void) reboot(RB_POWER_OFF);
return -errno;
log_warning_errno(r, "Failed to read reboot parameter file: %m");
if (!isempty(param)) {
- log_info("Rebooting with argument '%s'.", param);
+ if (!arg_quiet)
+ log_info("Rebooting with argument '%s'.", param);
(void) syscall(SYS_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, LINUX_REBOOT_CMD_RESTART2, param);
log_warning_errno(errno, "Failed to reboot with parameter, retrying without: %m");
}
- log_info("Rebooting.");
+ if (!arg_quiet)
+ log_info("Rebooting.");
(void) reboot(RB_AUTOBOOT);
return -errno;
}
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;
if (r < 0)
return log_warning_errno(r, "Failed to call ScheduleShutdown in logind, proceeding with immediate shutdown: %s", bus_error_message(&error, r));
- log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.", format_timestamp(date, sizeof(date), arg_when));
+ if (!arg_quiet)
+ log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.", format_timestamp(date, sizeof(date), arg_when));
return 0;
#else
log_error("Cannot schedule shutdown without logind support, proceeding with immediate shutdown.");
/* 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;
goto finish;
if (arg_action != ACTION_SYSTEMCTL && running_in_chroot() > 0) {
- log_info("Running in chroot, ignoring request.");
+
+ if (!arg_quiet)
+ log_info("Running in chroot, ignoring request.");
r = 0;
goto finish;
}
r = systemctl_main(argc, argv);
break;
+ /* Legacy command aliases set arg_action. They provide some fallbacks,
+ * e.g. to tell sysvinit to reboot after you have installed systemd
+ * binaries. */
+
case ACTION_HALT:
case ACTION_POWEROFF:
case ACTION_REBOOT:
case ACTION_RUNLEVEL4:
case ACTION_RUNLEVEL5:
case ACTION_RESCUE:
- case ACTION_EMERGENCY:
- case ACTION_DEFAULT:
r = start_with_fallback();
break;
r = runlevel_main();
break;
+ case ACTION_EXIT:
+ case ACTION_SUSPEND:
+ case ACTION_HIBERNATE:
+ case ACTION_HYBRID_SLEEP:
+ case ACTION_EMERGENCY:
+ case ACTION_DEFAULT:
+ /* systemctl verbs with no equivalent in the legacy commands.
+ * These cannot appear in arg_action. Fall through. */
+
case _ACTION_INVALID:
default:
assert_not_reached("Unknown action");