File pam-use-plymouth.patch of Package pam
diff --git a/libpam_misc/meson.build b/libpam_misc/meson.build
index e0bb30f5..fcbcc552 100644
--- a/libpam_misc/meson.build
+++ b/libpam_misc/meson.build
@@ -14,16 +14,30 @@ libpam_misc_map_path = meson.current_source_dir() / libpam_misc_map
libpam_misc_link_deps = [libpam_misc_map]
libpam_misc_link_args = ['-Wl,--version-script=' + libpam_misc_map_path]
-libpam_misc = shared_library(
- 'pam_misc',
- sources: libpam_misc_src,
- include_directories: [libpam_misc_inc, libpamc_inc],
- dependencies: [libpam_internal_dep, libpam_dep],
- link_depends: libpam_misc_link_deps,
- link_args: libpam_misc_link_args,
- version: libpam_misc_version,
- install: true,
-)
+if libply_boot_client.found()
+ libpam_misc = shared_library(
+ 'pam_misc',
+ sources: libpam_misc_src,
+ include_directories: [libpam_ply_inc, libpam_misc_inc, libpamc_inc],
+ dependencies: [libpam_internal_dep, libpam_dep],
+ link_with: libpam_ply,
+ link_depends: libpam_misc_link_deps,
+ link_args: libpam_misc_link_args,
+ version: libpam_misc_version,
+ install: true,
+ )
+else
+ libpam_misc = shared_library(
+ 'pam_misc',
+ sources: libpam_misc_src,
+ include_directories: [libpam_misc_inc, libpamc_inc],
+ dependencies: [libpam_internal_dep, libpam_dep],
+ link_depends: libpam_misc_link_deps,
+ link_args: libpam_misc_link_args,
+ version: libpam_misc_version,
+ install: true,
+ )
+endif
libpam_misc_dep = declare_dependency(
include_directories: [libpam_misc_inc],
diff --git a/libpam_misc/misc_conv.c b/libpam_misc/misc_conv.c
index fa3848e3..a6ca2dc5 100644
--- a/libpam_misc/misc_conv.c
+++ b/libpam_misc/misc_conv.c
@@ -1,11 +1,39 @@
/*
- * A generic conversation function for text based applications
- *
- * Written by Andrew Morgan <morgan@linux.kernel.org>
- */
+ Generic conversation function
+ Copyright (C) XXXX-2026 Andrew Morgan <morgan@linux.kernel.org>
+ Copyright (C) 2022-2026 Mark A. Williams, Jr.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
#include "config.h"
+#ifdef USE_PLYMOUTH
+# include <fcntl.h>
+# include <limits.h>
+# include <linux/futex.h>
+# include <linux/sched.h>
+# include <linux/vt.h>
+# include <paths.h>
+# include <sys/ioctl.h>
+# include <sys/mman.h>
+# include <sys/stat.h>
+# include <sys/syscall.h>
+# include <sys/sysmacros.h>
+# include <sys/wait.h>
+#endif
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
@@ -17,6 +45,9 @@
#include <security/pam_appl.h>
#include <security/pam_misc.h>
+#ifdef USE_PLYMOUTH
+# include <security/pam_ply.h>
+#endif
#include "pam_inline.h"
#include "pam_i18n.h"
@@ -25,6 +56,12 @@
#define CONV_ECHO_ON 1 /* types of echo state */
#define CONV_ECHO_OFF 0
+#ifdef USE_PLYMOUTH
+# ifndef _PATH_PLYHOME
+# define _PATH_PLYHOME _PATH_VARRUN "plymouth"
+# endif
+#endif
+
/*
* external timeout definitions - these can be overridden by the
* application.
@@ -277,8 +314,13 @@ static int read_string(int echo, const char *prompt, char **retstr)
* confusing amount of pointer indirection).
*/
+#ifdef USE_PLYMOUTH
+static int tui_conv(int num_msg, const struct pam_message **msgm,
+ struct pam_response **response, void *appdata_ptr)
+#else
int misc_conv(int num_msg, const struct pam_message **msgm,
struct pam_response **response, void *appdata_ptr)
+#endif
{
int count=0;
struct pam_response *reply;
@@ -402,3 +444,158 @@ failed_conversation:
return PAM_CONV_ERR;
}
+
+#ifdef USE_PLYMOUTH
+/*
+ * This conversation function is supposed to be a graphical PAM one based on
+ * plymouth(8) via ply_conv(3). Like with tui_conv above, this too is _not_
+ * completely compatible with the Solaris PAM codebase.
+ */
+static int gui_conv(int num_msg, const struct pam_message **msgm,
+ struct pam_response **response, void *appdata_ptr)
+{
+ int tries = 3;
+
+ do {
+ char cld_arg2[TTY_NAME_MAX + 6] = "--tty=";
+
+ if (!ttyname_r(STDIN_FILENO, cld_arg2 + 6, sizeof cld_arg2 - 6)) {
+ struct stat st;
+
+ if (fstat(STDIN_FILENO, &st) ||
+ ioctl(STDIN_FILENO, VT_WAITACTIVE, minor(st.st_rdev)))
+ continue;
+ }
+
+ struct pam_message msg_txt = {
+ .msg_style = PAM_TEXT_INFO,
+ .msg = cld_arg2 + (sizeof _PATH_TTY + 2),
+ };
+ struct pam_message msg_cmd = {
+ .msg_style = PAM_BINARY_PROMPT,
+ .msg = PLY_BOOT_PROTOCOL_REQUEST_TYPE_HAS_ACTIVE_VT,
+ };
+
+ const struct pam_message *msgs[] = { &msg_cmd, &msg_txt };
+ struct pam_response *resp = NULL;
+
+ switch (ply_conv(1, msgs, &resp, NULL)) {
+ case PAM_SUCCESS:
+ {
+ char *const s = resp->resp;
+
+ free(s);
+ free(resp);
+ resp = NULL;
+
+ if (s) {
+ break;
+ }
+ }
+ msg_cmd.msg = PLY_BOOT_PROTOCOL_REQUEST_TYPE_QUIT "\2\2\1";
+ ply_conv(1, msgs, &resp, NULL);
+ [[fallthrough]];
+ default:
+ if (resp) {
+ free(resp->resp);
+ free(resp);
+ resp = NULL;
+ }
+
+ siginfo_t si = { .si_status = EXIT_FAILURE };
+
+ const struct clone_args cl_args = {
+ .flags = CLONE_FS | CLONE_IO | CLONE_PTRACE | CLONE_SYSVSEM
+ | CLONE_CLEAR_SIGHAND
+ | CLONE_PARENT_SETTID | CLONE_VFORK,
+ .parent_tid = (uintptr_t)&si.si_pid,
+ };
+
+ switch (syscall(SYS_clone3, &cl_args, sizeof cl_args)) {
+ default:
+ while (waitid(P_PID, si.si_pid, &si, WEXITED) &&
+ errno == EINTR) { }
+
+ if (si.si_code == CLD_EXITED && si.si_status == EXIT_SUCCESS) {
+ break;
+ }
+ case -1:
+ continue;
+
+ case 0:
+ char cld_arg0[] = "plymouthd";
+ char cld_arg1[] = "--no-boot-log";
+ char *const cld_argv[] = { cld_arg0, cld_arg1, cld_arg2, NULL };
+
+ dup2(open(_PATH_DEVNULL, O_RDWR | O_CLOEXEC | O_NONBLOCK),
+ STDERR_FILENO);
+
+ execv("/sbin/plymouthd", cld_argv);
+ syscall(SYS_exit, EXIT_FAILURE);
+ }
+ }
+
+ msg_cmd.msg = PLY_BOOT_PROTOCOL_REQUEST_TYPE_SHOW_SPLASH;
+ ply_conv(2, msgs, &resp, NULL);
+ if (resp) {
+ free(resp->resp);
+ free(resp);
+ }
+
+ return ply_conv(num_msg, msgm, response, appdata_ptr);
+ } while (--tries);
+
+ return tui_conv(num_msg, msgm, response, appdata_ptr);
+}
+
+int misc_conv(int num_msg, const struct pam_message **msgm,
+ struct pam_response **response, void *appdata_ptr)
+{
+ static uint32_t mtx;
+ static int (*conv)(int, const struct pam_message **,
+ struct pam_response **, void *) = tui_conv;
+
+ if (syscall(SYS_futex, &mtx, FUTEX_TRYLOCK_PI_PRIVATE)) {
+ syscall(SYS_futex, &mtx, FUTEX_WAIT_PRIVATE, 1, NULL);
+ } else {
+ if (getppid() == 1 && getenv("PWD")) {
+ struct pam_message msg_cmd = {
+ .msg_style = PAM_BINARY_PROMPT,
+ .msg = PLY_BOOT_PROTOCOL_REQUEST_TYPE_QUIT "\2\2\1",
+ };
+
+ const struct pam_message *msgs[] = { &msg_cmd };
+ struct pam_response *resp = NULL;
+
+ char cl_stack[sysconf(_SC_PAGESIZE)];
+ struct clone_args cl_args = {
+ .flags = CLONE_FS | CLONE_IO | CLONE_PTRACE | CLONE_SYSVSEM
+ | CLONE_PARENT | CLONE_SIGHAND | CLONE_VM,
+ .stack = (uintptr_t)(cl_stack + sizeof cl_stack),
+ .stack_size = sizeof cl_stack,
+ };
+
+ switch (syscall(SYS_clone3, &cl_args, sizeof cl_args)) {
+ case 0:
+ const int fd = open(_PATH_WTMP, O_RDONLY | O_CLOEXEC);
+
+ syscall(SYS_exit, fcntl(fd, F_SETSIG, SIGCONT) ||
+ fcntl(fd, F_SETLEASE, F_RDLCK) ||
+ raise(SIGSTOP) ||
+ ply_conv(1, msgs, &resp, NULL) != PAM_SUCCESS
+ ? EXIT_FAILURE : EXIT_SUCCESS);
+ [[fallthrough]];
+ default:
+ conv = gui_conv;
+ case -1:
+ break;
+ }
+ }
+
+ mtx = 1;
+ syscall(SYS_futex, &mtx, FUTEX_WAKE, UINT32_MAX);
+ }
+
+ return conv(num_msg, msgm, response, appdata_ptr);
+}
+#endif /* USE_PLYMOUTH */
diff --git a/libpam_ply/help_socket.c b/libpam_ply/help_socket.c
new file mode 100644
index 00000000..8a2bba60
--- /dev/null
+++ b/libpam_ply/help_socket.c
@@ -0,0 +1,50 @@
+/*
+ Plymouth-based, PAM conversation function
+ Copyright (C) 2024-26 Mark A. Williams, Jr.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#ifdef PAM_DEBUG
+# include <err.h>
+#endif
+
+#include <security/pam_ply.h>
+
+static const char *const SOCKET_PATHV[] = {
+ PLY_BOOT_PROTOCOL_OLD_ABSTRACT_SOCKET_PATH,
+ PLY_BOOT_PROTOCOL_TRIMMED_ABSTRACT_SOCKET_PATH,
+};
+static const int SOCKET_TYPEV[] = {
+ PLY_UNIX_SOCKET_TYPE_ABSTRACT,
+ PLY_UNIX_SOCKET_TYPE_TRIMMED_ABSTRACT,
+};
+
+inline int pam_ply_socket() {
+ int i = sizeof SOCKET_TYPEV / sizeof *SOCKET_TYPEV - 1;
+
+ do {
+ const int sockfd = ply_connect_to_unix_socket(SOCKET_PATHV[i],
+ SOCKET_TYPEV[i]);
+
+ if (sockfd != -1)
+ return sockfd;
+ } while (i--);
+
+#ifdef PAM_DEBUG
+ warn("pam_ply_socket()");
+#endif
+ return -1;
+}
diff --git a/libpam_ply/include/security/meson.build b/libpam_ply/include/security/meson.build
new file mode 100644
index 00000000..49be3046
--- /dev/null
+++ b/libpam_ply/include/security/meson.build
@@ -0,0 +1 @@
+install_headers('pam_ply.h', install_dir: includedir)
diff --git a/libpam_ply/include/security/pam_ply.h b/libpam_ply/include/security/pam_ply.h
new file mode 100644
index 00000000..ff096943
--- /dev/null
+++ b/libpam_ply/include/security/pam_ply.h
@@ -0,0 +1,53 @@
+/*
+ Plymouth-based, PAM conversation function
+ Copyright (C) 2024-2 Mark A. Williams, Jr.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#ifndef __PAMPLY_H
+#define __PAMPLY_H
+
+#include <plymouth-1/ply/ply-utils.h>
+#include <plymouth-1/ply-boot-client/ply-boot-protocol.h>
+
+#include <security/pam_appl.h>
+#include <security/pam_client.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/* include some useful macros */
+
+#include <security/_pam_macros.h>
+
+/* functions defined in pam_ply.* libraries */
+
+extern int ply_conv(int num_msg, const struct pam_message **msgm,
+ struct pam_response **response, void *appdata_ptr);
+
+/*
+ * Communication helper functions
+ */
+
+/* create an endpoint for communication (with plymouthd) */
+extern int pam_ply_socket();
+
+#ifdef __cplusplus
+}
+#endif /* def __cplusplus */
+
+#endif /* ndef __PAMPLY_H */
diff --git a/libpam_ply/libpam_ply.map b/libpam_ply/libpam_ply.map
new file mode 100644
index 00000000..262e16ef
--- /dev/null
+++ b/libpam_ply/libpam_ply.map
@@ -0,0 +1,8 @@
+LIBPAM_MISC_1.0 {
+ global:
+ ply_conv;
+ pam_ply_socket;
+
+ local:
+ *;
+};
diff --git a/libpam_ply/meson.build b/libpam_ply/meson.build
new file mode 100644
index 00000000..d7b8784c
--- /dev/null
+++ b/libpam_ply/meson.build
@@ -0,0 +1,40 @@
+subdir('include/security')
+
+libpam_ply_src = [
+ 'help_socket.c',
+ 'ply_conv.c',
+]
+
+libpam_ply_inc = include_directories('include')
+
+libpam_ply_version = '1.0.0'
+libpam_ply_map = 'libpam_ply.map'
+libpam_ply_map_path = meson.current_source_dir() / libpam_ply_map
+
+libpam_ply_link_deps = [libpam_ply_map]
+libpam_ply_link_args = ['-Wl,--version-script=' + libpam_ply_map_path]
+
+libpam_ply = shared_library(
+ 'pam_ply',
+ sources: libpam_ply_src,
+ include_directories: [libpam_ply_inc, libpamc_inc],
+ dependencies: [libply_boot_client, libpam_internal_dep, libpam_dep],
+ link_depends: libpam_ply_link_deps,
+ link_args: libpam_ply_link_args,
+ version: libpam_ply_version,
+ install: true,
+)
+
+libpam_ply_dep = declare_dependency(
+ include_directories: [libpam_ply_inc],
+ link_with: [libpam_ply],
+)
+
+pkgconfig.generate(
+ libpam_ply,
+ description: 'PAM conversation function that uses Plymouth as its UX',
+ name: 'pam_ply',
+ filebase: 'pam_ply',
+ version: meson.project_version(),
+ url: 'http://www.linux-pam.org/'
+)
diff --git a/libpam_ply/ply_conv.c b/libpam_ply/ply_conv.c
new file mode 100644
index 00000000..54dff8a0
--- /dev/null
+++ b/libpam_ply/ply_conv.c
@@ -0,0 +1,229 @@
+/*
+ Plymouth-based, PAM conversation function
+ Copyright (C) 2024-26 Mark A. Williams, Jr.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#ifdef PAM_DEBUG
+# include <err.h>
+#endif
+#include <errno.h>
+#include <malloc.h>
+#include <limits.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <sys/socket.h>
+
+#include <security/pam_appl.h>
+#include <security/pam_ply.h>
+
+
+static ssize_t conv_send(const int sockfd,
+ const struct pam_message *const msg) {
+ errno = EINVAL;
+
+ if (msg && msg->msg) do {
+ const char *s;
+
+ switch (msg->msg_style) {
+ case PAM_PROMPT_ECHO_OFF:
+ s = PLY_BOOT_PROTOCOL_REQUEST_TYPE_PASSWORD;
+ break;
+
+ case PAM_PROMPT_ECHO_ON:
+ s = PLY_BOOT_PROTOCOL_REQUEST_TYPE_QUESTION;
+ break;
+
+ case PAM_ERROR_MSG:
+ s = PLY_BOOT_PROTOCOL_REQUEST_TYPE_ERROR;
+ break;
+
+ case PAM_TEXT_INFO:
+ s = PLY_BOOT_PROTOCOL_REQUEST_TYPE_SHOW_MESSAGE;
+ break;
+
+ case PAM_BINARY_PROMPT:
+ if (msg->msg[0]) {
+ ssize_t ret, len;
+
+ switch (msg->msg[1]) {
+ case '\0':
+ ret = 0;
+ len = 1;
+ break;
+ case '\2':
+ if ((ret = 2[(const unsigned char *)msg->msg])) {
+ len = ret + 2;
+ break;
+ }
+ default:
+ continue;
+ }
+
+ if (send(sockfd, msg->msg, len, MSG_MORE) == len &&
+ send(sockfd, "", 1, 0) == 1) {
+ return ret;
+ }
+ }
+ default:
+ continue;
+ }
+
+ if (send(sockfd, s, 1, MSG_MORE) == 1) {
+ const size_t len = strnlen(msg->msg, UINT8_MAX - 1);
+ const unsigned char dat[] = { '\2', len + 1 };
+
+ if (send(sockfd, dat, sizeof dat, MSG_MORE) == sizeof dat &&
+ send(sockfd, msg->msg, len, MSG_MORE) == (ssize_t)len &&
+ send(sockfd, "", 1, 0) == 1) {
+ return dat[1];
+ }
+ }
+ } while(0);
+
+#ifdef PAM_DEBUG
+ warn("conv_send()");
+#endif
+ return -1;
+}
+
+static ssize_t conv_recv(const int sockfd, struct pam_response *const resp) {
+ union {
+ char ch;
+ void *p;
+ } res;
+
+ resp->resp_retcode = PAM_CONV_ERR;
+
+ if (recv(sockfd, &res.ch, 1, MSG_WAITALL) == 1) {
+ ssize_t ret = 0;
+
+ union {
+ int i;
+ uint32_t u32;
+ size_t n;
+ } len = { 0 };
+
+ while (PLY_BOOT_PROTOCOL_RESPONSE_TYPE_ANSWER
+ PLY_BOOT_PROTOCOL_RESPONSE_TYPE_MULTIPLE_ANSWERS
+ PLY_BOOT_PROTOCOL_RESPONSE_TYPE_ACK
+ PLY_BOOT_PROTOCOL_RESPONSE_TYPE_NAK
+ PLY_BOOT_PROTOCOL_RESPONSE_TYPE_NO_ANSWER[len.i] != res.ch) {
+ if (++len.i == 5) {
+ errno = EINVAL;
+ goto done;
+ }
+ }
+
+ switch (len.i) {
+ case 0:
+ case 1:
+ if (recv(sockfd, &len.u32, sizeof len.u32, MSG_WAITALL) == sizeof len.u32) {
+ if ((res.p = malloc((len.n = ret = len.u32) + 1))) {
+ mlock(res.p, len.n);
+ if (recv(sockfd, res.p, len.n, MSG_WAITALL) >= ret) {
+ break;
+ }
+ munlock(res.p, len.n);
+ free(res.p);
+ } else {
+ resp->resp_retcode = PAM_BUF_ERR;
+ }
+ }
+ goto done;
+
+ case 2:
+ if ((res.p = aligned_alloc(sizeof(void *), 0))) {
+ break;
+ }
+ resp->resp_retcode = PAM_BUF_ERR;
+ goto done;
+
+ default:
+ res.p = NULL;
+ break;
+ }
+
+ resp->resp = res.p;
+ resp->resp_retcode = PAM_SUCCESS;
+ return ret;
+ }
+
+done:
+#ifdef PAM_DEBUG
+ warn("conv_recv()");
+#endif
+ return -1;
+}
+
+int ply_conv(const int num_msg, const struct pam_message **const msgv,
+ struct pam_response **const prespv, void *) {
+ int ret = PAM_SUCCESS;
+
+ mallopt(M_PERTURB, '\xFF');
+ do {
+ struct pam_response *const respv =
+ aligned_alloc(sizeof *respv, num_msg * sizeof *respv);
+
+ if (respv) {
+ const int sockfd = pam_ply_socket();
+
+ if (sockfd == -1) {
+ ret = PAM_CONV_ERR;
+ } else {
+ for (unsigned i = 0;;) {
+ if ((unsigned)num_msg == i) {
+ *prespv = respv;
+ break;
+ }
+
+ struct pam_response *resp = respv + i;
+
+ if (conv_send(sockfd, msgv[i++]) != -1 &&
+ (conv_recv(sockfd, resp), resp->resp_retcode) != PAM_CONV_ERR) {
+ if (resp->resp_retcode == PAM_BUF_ERR) {
+ ret = PAM_BUF_ERR;
+ }
+ continue;
+ }
+ ret = PAM_CONV_ERR;
+
+ do {
+ free(resp->resp);
+ } while (resp-- != respv);
+ free(respv);
+
+ break;
+ }
+
+ if (!close(sockfd)) {
+ break;
+ }
+ }
+ } else {
+ ret = PAM_BUF_ERR;
+ }
+
+#ifdef PAM_DEBUG
+ warn("ply_conv()");
+#endif
+ } while (0);
+ mallopt(M_PERTURB, 0);
+
+ return ret;
+}
diff --git a/meson.build b/meson.build
index 123c88ed..e53da179 100644
--- a/meson.build
+++ b/meson.build
@@ -314,6 +314,11 @@ else
stringparam_profileconditions += ';no_openssl_hmac'
endif
+libply_boot_client = dependency('ply-boot-client', required: get_option('plymouth'))
+if libply_boot_client.found()
+ cdata.set('USE_PLYMOUTH', 1)
+endif
+
use_logind = get_option('logind')
use_elogind = get_option('elogind').require(not use_logind.enabled()).disable_auto_if(use_logind.enabled())
use_logind = use_logind.disable_auto_if(use_elogind.enabled())
@@ -637,6 +642,9 @@ subdir('po')
subdir('libpam_internal')
subdir('libpam')
subdir('libpamc')
+if libply_boot_client.found()
+ subdir('libpam_ply')
+endif
subdir('libpam_misc')
if enable_docs
subdir('doc')
diff --git a/meson_options.txt b/meson_options.txt
index 35d979b5..9e36d43d 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -20,6 +20,8 @@ option('selinux', type: 'feature', value: 'auto',
description: 'SELinux support')
option('nis', type: 'feature', value: 'auto',
description: 'NIS/YP support in pam_unix')
+option('plymouth', type: 'feature', value: 'auto',
+ description: 'plymouth as GUI support in pam_misc via pam_ply')
option('examples', type: 'boolean', value: true,
description: 'Build examples')