user-record: Add preferredSession{Type,Launcher}

These will be used by display managers to pre-select the user's
preferred desktop environment and display server type. On homed, the
display manager will also be able to set these fields to cache the
user's last selection.
This commit is contained in:
Adrian Vovk 2024-02-04 19:21:29 -05:00 committed by Luca Boccassi
parent 9dbabd0a8b
commit 793ceda177
7 changed files with 69 additions and 4 deletions

View file

@ -568,6 +568,15 @@ it is bypassed.
auto-login. Systems are supposed to automatically log in a user marked this way
during boot, if there's exactly one user on it defined this way.
`preferredSessionType` → A string that indicates the user's preferred session type
(i.e. `x11`, `wayland`, or other values valid for `$XDG_SESSION_TYPE`). This should
be used by the display manager to pre-select the correct environment to log into.
`preferredSessionLauncher` → A string that indicates the user's preferred session launcher
desktop entry file (i.e. `gnome`, `gnome-classic`, `plasma`, `kodi`, or others that appear
in `/usr/share/xsessions/` or `/usr/share/wayland-sessions/`). This should be used by the
display manager to pre-select the correct environment to launch when the user logs in.
`stopDelayUSec` → An unsigned 64-bit integer, indicating the time in µs the
per-user service manager is kept around after the user fully logged out. This
value is honored by
@ -780,8 +789,8 @@ that may be used in this section are identical to the equally named ones in the
`luksPbkdfType`, `luksPbkdfForceIterations`, `luksPbkdfTimeCostUSec`, `luksPbkdfMemoryCost`,
`luksPbkdfParallelThreads`, `luksSectorSize`, `autoResizeMode`, `rebalanceWeight`,
`rateLimitIntervalUSec`, `rateLimitBurst`, `enforcePasswordPolicy`,
`autoLogin`, `stopDelayUSec`, `killProcesses`, `passwordChangeMinUSec`,
`passwordChangeMaxUSec`, `passwordChangeWarnUSec`,
`autoLogin`, `preferredSessionType`, `preferredSessionLauncher`, `stopDelayUSec`, `killProcesses`,
`passwordChangeMinUSec`, `passwordChangeMaxUSec`, `passwordChangeWarnUSec`,
`passwordChangeInactiveUSec`, `passwordChangeNow`, `pkcs11TokenUri`,
`fido2HmacCredential`.

View file

@ -963,6 +963,28 @@
<xi:include href="version-info.xml" xpointer="v245"/></listitem>
</varlistentry>
<varlistentry>
<term><option>--session-launcher=</option><replaceable>LAUNCHER</replaceable></term>
<listitem><para>Takes a string argument. Configures the user's preferred session launcher
.desktop entry file (i.e. <literal>gnome</literal>, <literal>plasma</literal>, or other names that
appear in <filename>/usr/share/xesssions/</filename> or <filename>/usr/share/wayland-sessions</filename>).
This is read by the display manager to pick the default session that is launched when the user logs in.</para>
<xi:include href="version-info.xml" xpointer="v256"/></listitem>
</varlistentry>
<varlistentry>
<term><option>--session-type=</option><replaceable>TYPE</replaceable></term>
<listitem><para>Takes a string argument. Configures the user's preferred session type
(i.e. <literal>x11</literal>, <literal>wayland</literal>, and other values accepted by
<varname>$XDG_SESSION_TYPE</varname>). This is read by the display manage to pick the
default session type the user is logged into.</para>
<xi:include href="version-info.xml" xpointer="v256"/></listitem>
</varlistentry>
</variablelist>
</refsect1>

View file

@ -110,7 +110,9 @@ _homectl() {
--auto-login
-b --blob
--avatar
--login-background'
--login-background
--session-launcher
--session-type'
)
if __contains_word "$prev" ${OPTS[ARG]}; then
@ -153,6 +155,12 @@ _homectl() {
--language)
comps=$(localectl list-locales 2>/dev/null)
;;
--session-launcher)
comps=$(find /usr/share/{x,wayland-}sessions/ -type f -name '*.desktop' -exec basename {} .desktop \; 2>/dev/null | sort -u)
;;
--session-type)
comps='wayland x11 tty'
;;
esac
COMPREPLY=( $(compgen -W '$comps' -- "$cur") )
return 0

View file

@ -2701,6 +2701,9 @@ static int help(int argc, char *argv[], void *userdata) {
" --kill-processes=BOOL Whether to kill user processes when sessions\n"
" terminate\n"
" --auto-login=BOOL Try to log this user in automatically\n"
" --session-launcher=LAUNCHER\n"
" Preferred session launcher file\n"
" --session-type=TYPE Preferred session type\n"
"\nSee the %6$s for details.\n",
program_invocation_short_name,
ansi_highlight(),
@ -2777,6 +2780,8 @@ static int parse_argv(int argc, char *argv[]) {
ARG_PASSWORD_CHANGE_INACTIVE,
ARG_EXPORT_FORMAT,
ARG_AUTO_LOGIN,
ARG_SESSION_LAUNCHER,
ARG_SESSION_TYPE,
ARG_PKCS11_TOKEN_URI,
ARG_FIDO2_DEVICE,
ARG_FIDO2_WITH_PIN,
@ -2870,6 +2875,8 @@ static int parse_argv(int argc, char *argv[]) {
{ "password-change-warn", required_argument, NULL, ARG_PASSWORD_CHANGE_WARN },
{ "password-change-inactive", required_argument, NULL, ARG_PASSWORD_CHANGE_INACTIVE },
{ "auto-login", required_argument, NULL, ARG_AUTO_LOGIN },
{ "session-launcher", required_argument, NULL, ARG_SESSION_LAUNCHER, },
{ "session-type", required_argument, NULL, ARG_SESSION_TYPE, },
{ "json", required_argument, NULL, ARG_JSON },
{ "export-format", required_argument, NULL, ARG_EXPORT_FORMAT },
{ "pkcs11-token-uri", required_argument, NULL, ARG_PKCS11_TOKEN_URI },
@ -3009,7 +3016,9 @@ static int parse_argv(int argc, char *argv[]) {
case ARG_CIFS_USER_NAME:
case ARG_CIFS_DOMAIN:
case ARG_CIFS_EXTRA_MOUNT_OPTIONS:
case ARG_LUKS_EXTRA_MOUNT_OPTIONS: {
case ARG_LUKS_EXTRA_MOUNT_OPTIONS:
case ARG_SESSION_LAUNCHER:
case ARG_SESSION_TYPE: {
const char *field =
c == ARG_EMAIL_ADDRESS ? "emailAddress" :
@ -3019,6 +3028,8 @@ static int parse_argv(int argc, char *argv[]) {
c == ARG_CIFS_DOMAIN ? "cifsDomain" :
c == ARG_CIFS_EXTRA_MOUNT_OPTIONS ? "cifsExtraMountOptions" :
c == ARG_LUKS_EXTRA_MOUNT_OPTIONS ? "luksExtraMountOptions" :
c == ARG_SESSION_LAUNCHER ? "preferredSessionLauncher" :
c == ARG_SESSION_TYPE ? "preferredSessionType" :
NULL;
assert(field);

View file

@ -575,6 +575,11 @@ void user_record_show(UserRecord *hr, bool show_full_group_info) {
if (hr->auto_login >= 0)
printf("Autom. Login: %s\n", yes_no(hr->auto_login));
if (hr->preferred_session_launcher)
printf("Sess. Launch: %s\n", hr->preferred_session_launcher);
if (hr->preferred_session_type)
printf("Session Type: %s\n", hr->preferred_session_type);
if (hr->kill_processes >= 0)
printf(" Kill Proc.: %s\n", yes_no(hr->kill_processes));

View file

@ -189,6 +189,9 @@ static UserRecord* user_record_free(UserRecord *h) {
free(h->state);
free(h->service);
free(h->preferred_session_type);
free(h->preferred_session_launcher);
strv_free(h->pkcs11_token_uri);
for (size_t i = 0; i < h->n_pkcs11_encrypted_key; i++)
pkcs11_encrypted_key_done(h->pkcs11_encrypted_key + i);
@ -1340,6 +1343,8 @@ static int dispatch_per_machine(const char *name, JsonVariant *variant, JsonDisp
{ "rateLimitBurst", _JSON_VARIANT_TYPE_INVALID, json_dispatch_uint64, offsetof(UserRecord, ratelimit_burst), 0 },
{ "enforcePasswordPolicy", JSON_VARIANT_BOOLEAN, json_dispatch_tristate, offsetof(UserRecord, enforce_password_policy), 0 },
{ "autoLogin", JSON_VARIANT_BOOLEAN, json_dispatch_tristate, offsetof(UserRecord, auto_login), 0 },
{ "preferredSessionType", JSON_VARIANT_STRING, json_dispatch_string, offsetof(UserRecord, preferred_session_type), JSON_SAFE },
{ "preferredSessionLauncher", JSON_VARIANT_STRING, json_dispatch_string, offsetof(UserRecord, preferred_session_launcher), JSON_SAFE },
{ "stopDelayUSec", _JSON_VARIANT_TYPE_INVALID, json_dispatch_uint64, offsetof(UserRecord, stop_delay_usec), 0 },
{ "killProcesses", JSON_VARIANT_BOOLEAN, json_dispatch_tristate, offsetof(UserRecord, kill_processes), 0 },
{ "passwordChangeMinUSec", _JSON_VARIANT_TYPE_INVALID, json_dispatch_uint64, offsetof(UserRecord, password_change_min_usec), 0 },
@ -1683,6 +1688,8 @@ int user_record_load(UserRecord *h, JsonVariant *v, UserRecordLoadFlags load_fla
{ "rateLimitBurst", _JSON_VARIANT_TYPE_INVALID, json_dispatch_uint64, offsetof(UserRecord, ratelimit_burst), 0 },
{ "enforcePasswordPolicy", JSON_VARIANT_BOOLEAN, json_dispatch_tristate, offsetof(UserRecord, enforce_password_policy), 0 },
{ "autoLogin", JSON_VARIANT_BOOLEAN, json_dispatch_tristate, offsetof(UserRecord, auto_login), 0 },
{ "preferredSessionType", JSON_VARIANT_STRING, json_dispatch_string, offsetof(UserRecord, preferred_session_type), JSON_SAFE },
{ "preferredSessionLauncher", JSON_VARIANT_STRING, json_dispatch_string, offsetof(UserRecord, preferred_session_launcher), JSON_SAFE },
{ "stopDelayUSec", _JSON_VARIANT_TYPE_INVALID, json_dispatch_uint64, offsetof(UserRecord, stop_delay_usec), 0 },
{ "killProcesses", JSON_VARIANT_BOOLEAN, json_dispatch_tristate, offsetof(UserRecord, kill_processes), 0 },
{ "passwordChangeMinUSec", _JSON_VARIANT_TYPE_INVALID, json_dispatch_uint64, offsetof(UserRecord, password_change_min_usec), 0 },

View file

@ -351,6 +351,9 @@ typedef struct UserRecord {
int auto_login;
int drop_caches;
char *preferred_session_type;
char *preferred_session_launcher;
uint64_t stop_delay_usec; /* How long to leave systemd --user around on log-out */
int kill_processes; /* Whether to kill user processes forcibly on log-out */