Skip to content

Commit

Permalink
Added option --check-inhibitors for non-tty usage
Browse files Browse the repository at this point in the history
As described in #2680, systemctl did ignore inhibitors if it is not
attached to a tty to allow scripts to ignore inhibitors automatically.
This pull request preserves this behavior but allows scripts to
explicit check inhibitors if required.

The new parameter '--check-inhibitors=yes' enables this feature.
The old parameter '-i'/'--ignore-inhibitors' was deprecated in favor
of '--check-inhibitors=no', the default behaviour can be specified
with '--check-inhibitors=auto'.
The new parameter is also described in the documentations and shell
completions found here.

(cherry picked from commit b8ebe378b49a31549b8531d4b3177095ef385d55)

Related: #1269726
  • Loading branch information
Zocker1999NET authored and systemd-rhel-bot committed Jul 23, 2021
1 parent 998041f commit f875436
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 26 deletions.
38 changes: 25 additions & 13 deletions man/systemctl.xml
Original file line number Diff line number Diff line change
Expand Up @@ -323,23 +323,35 @@
</listitem>
</varlistentry>

<varlistentry>
<term><option>--check-inhibitors=</option></term>

<listitem>
<para>When system shutdown or sleep state is request, this option controls how to deal with
inhibitor locks. It takes one of <literal>auto</literal>, <literal>yes</literal> or
<literal>no</literal>. Defaults to <literal>auto</literal>, which will behave like
<literal>yes</literal> for interactive invocations (i.e. from a TTY) and <literal>no</literal>
for non-interactive invocations.
<literal>yes</literal> will let the request respect inhibitor locks.
<literal>no</literal> will let the request ignore inhibitor locks.
</para>
<para>Applications can establish inhibitor locks to avoid that certain important operations
(such as CD burning or suchlike) are interrupted by system shutdown or a sleep state. Any user may
take these locks and privileged users may override these locks.
If any locks are taken, shutdown and sleep state requests will normally fail (unless privileged)
and a list of active locks is printed.
However, if <literal>no</literal> is specified or <literal>auto</literal> is specified on a
non-interactive requests, the established locks are ignored and not shown, and the operation
attempted anyway, possibly requiring additional privileges.
May be overriden by <option>--force</option>.</para>
</listitem>
</varlistentry>

<varlistentry>
<term><option>-i</option></term>
<term><option>--ignore-inhibitors</option></term>

<listitem>
<para>When system shutdown or a sleep state is requested,
ignore inhibitor locks. Applications can establish inhibitor
locks to avoid that certain important operations (such as CD
burning or suchlike) are interrupted by system shutdown or a
sleep state. Any user may take these locks and privileged
users may override these locks. If any locks are taken,
shutdown and sleep state requests will normally fail
(regardless of whether privileged or not) and a list of active locks
is printed. However, if <option>--ignore-inhibitors</option>
is specified, the locks are ignored and not printed, and the
operation attempted anyway, possibly requiring additional
privileges.</para>
<para>Shortcut for <option>--check-inhibitors=no</option>.</para>
</listitem>
</varlistentry>

Expand Down
7 changes: 5 additions & 2 deletions shell-completion/bash/systemctl.in
Original file line number Diff line number Diff line change
Expand Up @@ -111,9 +111,9 @@ _systemctl () {
[STANDALONE]='--all -a --reverse --after --before --defaults --force -f --full -l --global
--help -h --no-ask-password --no-block --no-legend --no-pager --no-reload --no-wall --now
--quiet -q --system --user --version --runtime --recursive -r --firmware-setup
--show-types -i --ignore-inhibitors --plain --failed --value --fail --dry-run --wait'
--show-types --plain --failed --value --fail --dry-run --wait'
[ARG]='--host -H --kill-who --property -p --signal -s --type -t --state --job-mode --root
--preset-mode -n --lines -o --output -M --machine --message'
--preset-mode -n --lines -o --output -M --machine --message --check-inhibitors'
)

if __contains_word "--user" ${COMP_WORDS[*]}; then
Expand Down Expand Up @@ -163,6 +163,9 @@ _systemctl () {
--machine|-M)
comps=$( __get_machines )
;;
--check-inhibitors)
comps='auto yes no'
;;
esac
COMPREPLY=( $(compgen -W '$comps' -- "$cur") )
return 0
Expand Down
9 changes: 8 additions & 1 deletion shell-completion/zsh/_systemctl.in
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,13 @@ _job_modes() {
_values -s , "${_modes[@]}"
}

(( $+functions[_systemctl_check_inhibitors] )) ||
_systemctl_check_inhibitors() {
local -a _modes
_modes=(auto yes no)
_values -s , "${_modes[@]}"
}

# Build arguments for "systemctl" to be used in completion.
local -a _modes; _modes=("--user" "--system")
# Use the last mode (they are exclusive and the last one is used).
Expand All @@ -380,7 +387,7 @@ _arguments -s \
'--before[Show units ordered before]' \
{-l,--full}"[Don't ellipsize unit names on output]" \
'--show-types[When showing sockets, show socket type]' \
{-i,--ignore-inhibitors}'[When executing a job, ignore jobs dependencies]' \
'--check-inhibitors[Specify if inhibitors should be checked]:mode:_systemctl_check_inhibitors' \
{-q,--quiet}'[Suppress output]' \
'--no-block[Do not wait until operation finished]' \
'--no-legend[Do not print a legend, i.e. the column headers and the footer with hints]' \
Expand Down
37 changes: 27 additions & 10 deletions src/systemctl/systemctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ static bool arg_no_wall = false;
static bool arg_no_reload = false;
static bool arg_value = false;
static bool arg_show_types = false;
static bool arg_ignore_inhibitors = false;
static int arg_check_inhibitors = -1;
static bool arg_dry_run = false;
static bool arg_quiet = false;
static bool arg_full = false;
Expand Down Expand Up @@ -3313,17 +3313,19 @@ static int logind_check_inhibitors(enum action a) {
char **s;
int r;

if (arg_ignore_inhibitors || arg_force > 0)
if (arg_check_inhibitors == 0 || arg_force > 0)
return 0;

if (arg_when > 0)
return 0;

if (geteuid() == 0)
return 0;
if (arg_check_inhibitors < 0) {
if (geteuid() == 0)
return 0;

if (!on_tty())
return 0;
if (!on_tty())
return 0;
}

if (arg_transport != BUS_TRANSPORT_LOCAL)
return 0;
Expand Down Expand Up @@ -7237,8 +7239,10 @@ static void systemctl_help(void) {
" When enqueuing a unit job, show full transaction\n"
" --show-types When showing sockets, explicitly show their type\n"
" --value When showing properties, only print the value\n"
" -i --ignore-inhibitors\n"
" When shutting down or sleeping, ignore inhibitors\n"
" --check-inhibitors=MODE\n"
" Specify if checking inhibitors before shutting down,\n"
" sleeping or hibernating\n"
" -i Shortcut for --check-inhibitors=no\n"
" --kill-who=WHO Who to send signal to\n"
" -s --signal=SIGNAL Which signal to send\n"
" --now Start or stop unit in addition to enabling or disabling it\n"
Expand Down Expand Up @@ -7475,6 +7479,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
ARG_REVERSE,
ARG_AFTER,
ARG_BEFORE,
ARG_CHECK_INHIBITORS,
ARG_DRY_RUN,
ARG_SHOW_TYPES,
ARG_IRREVERSIBLE,
Expand Down Expand Up @@ -7520,7 +7525,8 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
{ "fail", no_argument, NULL, ARG_FAIL }, /* compatibility only */
{ "irreversible", no_argument, NULL, ARG_IRREVERSIBLE }, /* compatibility only */
{ "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES }, /* compatibility only */
{ "ignore-inhibitors", no_argument, NULL, 'i' },
{ "ignore-inhibitors", no_argument, NULL, 'i' }, /* compatibility only */
{ "check-inhibitors", required_argument, NULL, ARG_CHECK_INHIBITORS },
{ "value", no_argument, NULL, ARG_VALUE },
{ "user", no_argument, NULL, ARG_USER },
{ "system", no_argument, NULL, ARG_SYSTEM },
Expand Down Expand Up @@ -7813,7 +7819,18 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
break;

case 'i':
arg_ignore_inhibitors = true;
arg_check_inhibitors = 0;
break;

case ARG_CHECK_INHIBITORS:
if (streq(optarg, "auto"))
arg_check_inhibitors = -1;
else {
r = parse_boolean(optarg);
if (r < 0)
return log_error_errno(r, "Failed to parse --check-inhibitors= argument: %s", optarg);
arg_check_inhibitors = r;
}
break;

case ARG_PLAIN:
Expand Down

0 comments on commit f875436

Please sign in to comment.