login1: Add "inhibited" state to Can* methods
Desktops cannot currently tell the difference between a power action being set to challenge permanently (i.e. because the sysadmin wanted to restrict the given user) and a power action being set to challenge because it's temporarily inhibited. Thus, a desktop might take an action that is valid in the first case but not the second case. For instance: GNOME hides all of its automatic suspend settings from the UI whenever a sleep inhibitor is active. This now returns a new state: "inhibited". It communicates to the desktop that the action is available normally, but at the moment the desktop isn't allowed to perform the action due to an inhibitor. Related: https://github.com/systemd/systemd/issues/37311
This commit is contained in:
+39
-42
@@ -2927,7 +2927,6 @@ static int method_can_shutdown_or_sleep(
|
||||
_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;
|
||||
|
||||
@@ -2984,12 +2983,27 @@ static int method_can_shutdown_or_sleep(
|
||||
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,
|
||||
@@ -3001,12 +3015,13 @@ static int method_can_shutdown_or_sleep(
|
||||
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) {
|
||||
@@ -3020,39 +3035,21 @@ static int method_can_shutdown_or_sleep(
|
||||
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 (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 */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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";
|
||||
}
|
||||
|
||||
finish:
|
||||
return sd_bus_reply_method_return(message, "s", result);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user