<function>CanRebootParameter()</function>, <function>CanRebootToFirmwareSetup()</function>,
<function>CanRebootToBootLoaderMenu()</function>, and <function>CanRebootToBootLoaderEntry()</function>
test whether the system supports the respective operation and whether the calling user is allowed to
- execute it. Returns one of <literal>na</literal>, <literal>yes</literal>, <literal>no</literal>, and
- <literal>challenge</literal>. If <literal>na</literal> is returned, the operation is not available because
- hardware, kernel, or drivers do not support it. If <literal>yes</literal> is returned, the operation is
- supported and the user may execute the operation without further authentication. If <literal>no</literal>
- is returned, the operation is available but the user is not allowed to execute the operation. If
- <literal>challenge</literal> is returned, the operation is available but only after authorization.</para>
+ execute it. Returns one of <literal>na</literal>, <literal>yes</literal>, <literal>no</literal>,
+ <literal>challenge</literal>, and <literal>inhibited</literal>. If <literal>na</literal> is returned,
+ the operation is not available because hardware, kernel, or drivers do not support it. If <literal>yes</literal>
+ is returned, the operation is supported and the user may execute the operation without further authentication.
+ If <literal>no</literal> is returned, the operation is available but the user is not allowed to execute
+ the operation. If <literal>challenge</literal> is returned, the operation is available but only after
+ authorization. If <literal>inhibited</literal> is returned, the operation is normally available without
+ authorization but is currently inhibited. The operation is available only if inhibitors are ignored and
+ after authorization. If <literal>inhibitor-blocked</literal> is returned, the operation is normally
+ available without authorization but is currently inhibited. While the inhibitor remains active, the user
+ is not allowed to execute the operation. <literal>challenge-inhibitor-blocked</literal> is similar:
+ the operation is normally available after authorization but a held inhibitor disallows the user from
+ executing the operation.</para>
<para><function>ScheduleShutdown()</function> schedules a shutdown operation <varname>type</varname> at
time <varname>usec</varname> in microseconds since the UNIX epoch. Alternatively, if
_cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
bool multiple_sessions, challenge, blocked, check_unit_state = true;
const HandleActionData *a;
- const char *result = NULL;
uid_t uid;
int r;
if (r < 0)
return r;
- if (!streq(load_state, "loaded")) {
- result = "no";
- goto finish;
- }
+ if (!streq(load_state, "loaded"))
+ return sd_bus_reply_method_return(message, "s", "no");
}
+ const char *result;
+ r = bus_test_polkit(
+ message,
+ a->polkit_action,
+ /* details= */ NULL,
+ /* good_user= */ UID_INVALID,
+ &challenge,
+ error);
+ if (r < 0)
+ return r;
+ if (r > 0)
+ result = "yes";
+ else if (challenge)
+ result = "challenge";
+ else
+ result = "no";
+
if (multiple_sessions) {
r = bus_test_polkit(
message,
if (r < 0)
return r;
- if (r > 0)
- result = "yes";
- else if (challenge)
- result = "challenge";
- else
- result = "no";
+ if (r == 0) {
+ if (challenge) {
+ if (streq(result, "yes")) /* Avoid upgrading no -> challenge */
+ result = "challenge";
+ } else
+ result = "no";
+ }
}
if (blocked) {
if (r < 0)
return r;
- if (r > 0) {
- if (!result)
- result = "yes";
- } else if (challenge) {
- if (!result || streq(result, "yes"))
- result = "challenge";
- } else
- result = "no";
- }
-
- if (!multiple_sessions && !blocked) {
- /* If neither inhibit nor multiple sessions
- * apply then just check the normal policy */
-
- r = bus_test_polkit(
- message,
- a->polkit_action,
- /* details= */ NULL,
- /* good_user= */ UID_INVALID,
- &challenge,
- error);
- if (r < 0)
- return r;
-
- if (r > 0)
- result = "yes";
- else if (challenge)
- result = "challenge";
- else
- result = "no";
+ if (r == 0) {
+ if (challenge) {
+ if (streq(result, "yes"))
+ result = "inhibited";
+ /* If result is already "challenge" or "no", the held inhibitor has no effect */
+ } else {
+ if (streq(result, "yes"))
+ result = "inhibitor-blocked";
+ else if (streq(result, "challenge"))
+ result = "challenge-inhibitor-blocked";
+ /* If the result is already "no", the held inhibitor has no effect */
+ }
+ }
}
- finish:
return sd_bus_reply_method_return(message, "s", result);
}