[systemd-commits] 6 commits - Makefile.am man/systemctl.xml src/ask-password.c src/service.c src/systemctl.c src/tty-ask-password-agent.c src/util.c TODO units/.gitignore units/systemd-ask-password-plymouth.path units/systemd-ask-password-plymouth.service.in

Lennart Poettering lennart at kemper.freedesktop.org
Tue Oct 26 06:18:39 PDT 2010


 Makefile.am                                    |   13 -
 TODO                                           |    8 
 man/systemctl.xml                              |   23 ++
 src/ask-password.c                             |   33 +--
 src/service.c                                  |    2 
 src/systemctl.c                                |   58 +++++
 src/tty-ask-password-agent.c                   |  258 ++++++++++++++++++++++---
 src/util.c                                     |    2 
 units/.gitignore                               |    1 
 units/systemd-ask-password-plymouth.path       |   13 +
 units/systemd-ask-password-plymouth.service.in |   12 +
 11 files changed, 371 insertions(+), 52 deletions(-)

New commits:
commit 0320828cac4fb7b704c5dbd365979cb3ac5ba4d2
Author: Mike Kazantsev <mk.fraggod at gmail.com>
Date:   Tue Oct 26 15:18:13 2010 +0200

    service: fix sysv-less build

diff --git a/src/service.c b/src/service.c
index dac4ada..46d7bbb 100644
--- a/src/service.c
+++ b/src/service.c
@@ -1585,6 +1585,7 @@ static int service_spawn(
                         goto fail;
                 }
 
+#ifdef HAVE_SYSV_COMPAT
         /* Make sure we set TERM=linux for SysV scripts, since some
          * require it to be set from the kernel */
         if (s->sysv_path && !strv_env_get(s->meta.manager->environment, "TERM"))
@@ -1592,6 +1593,7 @@ static int service_spawn(
                         r = -ENOMEM;
                         goto fail;
                 }
+#endif
 
         if (!(final_env = strv_env_merge(2,
                                          s->meta.manager->environment,

commit b9ba604e8720c30deb7095b049b577eec1cbb74a
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Oct 26 15:15:00 2010 +0200

    ask-password-tty: properly handle SIGINT/SIGTERM

diff --git a/TODO b/TODO
index f1e6312..45ef095 100644
--- a/TODO
+++ b/TODO
@@ -49,8 +49,6 @@
 
 * suspend, resume
 
-* passphrase agent https://bugs.freedesktop.org/show_bug.cgi?id=30038
-
 * systemctl auto-pager a la git
 
 * merge CK
@@ -58,7 +56,7 @@
 * start getty 2-6 only when actual vt switch happens
   (same model as socket on-demand activation)
 
-* spawn ask-password tty agent temporarily in systemctl
+* ask-password: find way to disable wall agent where tty agent is running
 
 * readahead: btrfs/LVM SSD detection
 
diff --git a/src/ask-password.c b/src/ask-password.c
index 493bbfe..1d89eaf 100644
--- a/src/ask-password.c
+++ b/src/ask-password.c
@@ -167,14 +167,21 @@ static int parse_argv(int argc, char *argv[]) {
 }
 
 static int ask_agent(void) {
+        enum {
+                FD_SOCKET,
+                FD_SIGNAL,
+                _FD_MAX
+        };
+
         char temp[] = "/dev/.systemd/ask-password/tmp.XXXXXX";
         char final[sizeof(temp)] = "";
         int fd = -1, r;
         FILE *f = NULL;
         char *socket_name = NULL;
-        int socket_fd = -1, signal_fd;
+        int socket_fd = -1, signal_fd = -1;
         sigset_t mask;
         usec_t not_after;
+        struct pollfd pollfd[_FD_MAX];
 
         mkdir_p("/dev/.systemd/ask-password", 0755);
 
@@ -246,13 +253,13 @@ static int ask_agent(void) {
                 goto finish;
         }
 
-        for (;;) {
-                enum {
-                        FD_SOCKET,
-                        FD_SIGNAL,
-                        _FD_MAX
-                };
+        zero(pollfd);
+        pollfd[FD_SOCKET].fd = socket_fd;
+        pollfd[FD_SOCKET].events = POLLIN;
+        pollfd[FD_SIGNAL].fd = signal_fd;
+        pollfd[FD_SIGNAL].events = POLLIN;
 
+        for (;;) {
                 char passphrase[LINE_MAX+1];
                 struct msghdr msghdr;
                 struct iovec iovec;
@@ -262,16 +269,9 @@ static int ask_agent(void) {
                         uint8_t buf[CMSG_SPACE(sizeof(struct ucred))];
                 } control;
                 ssize_t n;
-                struct pollfd pollfd[_FD_MAX];
                 int k;
 
-                zero(pollfd);
-                pollfd[FD_SOCKET].fd = socket_fd;
-                pollfd[FD_SOCKET].events = POLLIN;
-                pollfd[FD_SIGNAL].fd = signal_fd;
-                pollfd[FD_SIGNAL].events = POLLIN;
-
-                if ((k = poll(pollfd, 2, arg_timeout/USEC_PER_MSEC)) < 0) {
+                if ((k = poll(pollfd, _FD_MAX, arg_timeout/USEC_PER_MSEC)) < 0) {
 
                         if (errno == EINTR)
                                 continue;
@@ -366,6 +366,9 @@ finish:
         if (socket_fd >= 0)
                 close_nointr_nofail(socket_fd);
 
+        if (signal_fd >= 0)
+                close_nointr_nofail(signal_fd);
+
         if (f)
                 fclose(f);
 
diff --git a/src/tty-ask-password-agent.c b/src/tty-ask-password-agent.c
index 5b42939..d610cbd 100644
--- a/src/tty-ask-password-agent.c
+++ b/src/tty-ask-password-agent.c
@@ -29,6 +29,7 @@
 #include <sys/inotify.h>
 #include <unistd.h>
 #include <getopt.h>
+#include <sys/signalfd.h>
 
 #include "util.h"
 #include "conf-parser.h"
@@ -385,8 +386,15 @@ finish:
 }
 
 static int watch_passwords(void) {
-        int notify;
-        struct pollfd pollfd;
+        enum {
+                FD_INOTIFY,
+                FD_SIGNAL,
+                _FD_MAX
+        };
+
+        int notify = -1, signal_fd = -1;
+        struct pollfd pollfd[_FD_MAX];
+        sigset_t mask;
         int r;
 
         mkdir_p("/dev/.systemd/ask-password", 0755);
@@ -401,15 +409,27 @@ static int watch_passwords(void) {
                 goto finish;
         }
 
+        assert_se(sigemptyset(&mask) == 0);
+        sigset_add_many(&mask, SIGINT, SIGTERM, -1);
+        assert_se(sigprocmask(SIG_SETMASK, &mask, NULL) == 0);
+
+        if ((signal_fd = signalfd(-1, &mask, SFD_NONBLOCK|SFD_CLOEXEC)) < 0) {
+                log_error("signalfd(): %m");
+                r = -errno;
+                goto finish;
+        }
+
         zero(pollfd);
-        pollfd.fd = notify;
-        pollfd.events = POLLIN;
+        pollfd[FD_INOTIFY].fd = notify;
+        pollfd[FD_INOTIFY].events = POLLIN;
+        pollfd[FD_SIGNAL].fd = signal_fd;
+        pollfd[FD_SIGNAL].events = POLLIN;
 
         for (;;) {
                 if ((r = show_passwords()) < 0)
                         break;
 
-                if (poll(&pollfd, 1, -1) < 0) {
+                if (poll(pollfd, _FD_MAX, -1) < 0) {
 
                         if (errno == EINTR)
                                 continue;
@@ -418,8 +438,11 @@ static int watch_passwords(void) {
                         goto finish;
                 }
 
-                if (pollfd.revents != 0)
+                if (pollfd[FD_INOTIFY].revents != 0)
                         flush_fd(notify);
+
+                if (pollfd[FD_SIGNAL].revents != 0)
+                        break;
         }
 
         r = 0;
@@ -428,6 +451,9 @@ finish:
         if (notify >= 0)
                 close_nointr_nofail(notify);
 
+        if (signal_fd >= 0)
+                close_nointr_nofail(signal_fd);
+
         return r;
 }
 

commit 501fc174c22aebd3181af08a4cfa65cc92bbe233
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Oct 26 05:29:39 2010 +0200

    systemctl: automatically spawn temporary password agent when we might need one

diff --git a/Makefile.am b/Makefile.am
index 7f8df05..b005f3a 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -53,9 +53,10 @@ AM_CPPFLAGS = \
 	-DSYSTEMD_BINARY_PATH=\"$(rootbindir)/systemd\" \
 	-DSYSTEMD_SHUTDOWN_BINARY_PATH=\"$(rootlibexecdir)/systemd-shutdown\" \
 	-DSYSTEMCTL_BINARY_PATH=\"$(rootbindir)/systemctl\" \
+	-DSYSTEMD_TTY_ASK_PASSWORD_AGENT_BINARY_PATH=\"$(rootbindir)/systemd-tty-ask-password-agent\" \
 	-DRUNTIME_DIR=\"$(localstatedir)/run\" \
 	-DRANDOM_SEED=\"$(localstatedir)/lib/random-seed\" \
-	-DKEXEC_BINARY_PATH=\"$(rootsbindir)/kexec\" \
+	-DKEXEC_BINARY_PATH=\"/sbin/kexec\" \
 	-I $(top_srcdir)/src
 
 if TARGET_GENTOO
diff --git a/man/systemctl.xml b/man/systemctl.xml
index cdf4f5c..10e0f82 100644
--- a/man/systemctl.xml
+++ b/man/systemctl.xml
@@ -242,6 +242,29 @@
                         </varlistentry>
 
                         <varlistentry>
+                                <term><option>--no-ask-password</option></term>
+
+                                <listitem><para>When used with
+                                <command>start</command> and related
+                                commands, disables asking for
+                                passwords. Background services may
+                                require input of a password or
+                                passphrase string, for example to
+                                unlock system hard disks or
+                                cryptographic certificates. Unless
+                                this option is specified and the
+                                command is invoked from a terminal
+                                <command>systemctl</command> will
+                                query the user on the terminal for the
+                                necessary secrets. Use this option to
+                                switch this behaviour off. In this
+                                case the password must be supplied by
+                                some other means (for example
+                                graphical password agents) or the
+                                service might fail.</para></listitem>
+                        </varlistentry>
+
+                        <varlistentry>
                                 <term><option>--kill-mode=</option></term>
 
                                 <listitem><para>When used with
diff --git a/src/systemctl.c b/src/systemctl.c
index ffbe4db..a4b83af 100644
--- a/src/systemctl.c
+++ b/src/systemctl.c
@@ -32,6 +32,7 @@
 #include <sys/socket.h>
 #include <sys/stat.h>
 #include <stddef.h>
+#include <sys/prctl.h>
 
 #include <dbus/dbus.h>
 
@@ -73,6 +74,7 @@ static bool arg_quiet = false;
 static bool arg_full = false;
 static bool arg_force = false;
 static bool arg_defaults = false;
+static bool arg_ask_password = false;
 static char **arg_wall = NULL;
 static const char *arg_kill_who = NULL;
 static const char *arg_kill_mode = NULL;
@@ -118,6 +120,47 @@ static bool on_tty(void) {
         return t;
 }
 
+static void spawn_ask_password_agent(void) {
+        pid_t parent, child;
+
+        /* We check STDIN here, not STDOUT, since this is about input,
+         * not output */
+        if (!isatty(STDIN_FILENO))
+                return;
+
+        if (!arg_ask_password)
+                return;
+
+        parent = getpid();
+
+        /* Spawns a temporary TTY agent, making sure it goes away when
+         * we go away */
+
+        if ((child = fork()) < 0)
+                return;
+
+        if (child == 0) {
+                /* In the child */
+
+                const char * const args[] = {
+                        SYSTEMD_TTY_ASK_PASSWORD_AGENT_BINARY_PATH,
+                        "--watch",
+                        NULL
+                };
+
+                if (prctl(PR_SET_PDEATHSIG, SIGTERM) < 0)
+                        _exit(EXIT_FAILURE);
+
+                /* Check whether our parent died before we were able
+                 * to set the death signal */
+                if (getppid() != parent)
+                        _exit(EXIT_SUCCESS);
+
+                execv(args[0], (char **) args);
+                _exit(EXIT_FAILURE);
+        }
+}
+
 static const char *ansi_highlight(bool b) {
 
         if (!on_tty())
@@ -1269,6 +1312,8 @@ static int start_unit(DBusConnection *bus, char **args, unsigned n) {
 
         assert(bus);
 
+        spawn_ask_password_agent();
+
         if (arg_action == ACTION_SYSTEMCTL) {
                 method =
                         streq(args[0], "stop")                  ? "StopUnit" :
@@ -4010,6 +4055,8 @@ static int systemctl_help(void) {
                "     --global         Enable/disable unit files globally\n"
                "     --no-reload      When enabling/disabling unit files, don't reload daemon\n"
                "                      configuration\n"
+               "     --no-ask-password\n"
+               "                      Do not ask for system passwords\n"
                "     --kill-mode=MODE How to send signal\n"
                "     --kill-who=WHO   Who to send signal to\n"
                "  -s --signal=SIGNAL  Which signal to send\n"
@@ -4146,7 +4193,8 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
                 ARG_NO_RELOAD,
                 ARG_DEFAULTS,
                 ARG_KILL_MODE,
-                ARG_KILL_WHO
+                ARG_KILL_WHO,
+                ARG_NO_ASK_PASSWORD
         };
 
         static const struct option options[] = {
@@ -4171,6 +4219,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
                 { "kill-mode", required_argument, NULL, ARG_KILL_MODE },
                 { "kill-who",  required_argument, NULL, ARG_KILL_WHO  },
                 { "signal",    required_argument, NULL, 's'           },
+                { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
                 { NULL,        0,                 NULL, 0             }
         };
 
@@ -4179,6 +4228,9 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
         assert(argc >= 0);
         assert(argv);
 
+        /* Only when running as systemctl we ask for passwords */
+        arg_ask_password = true;
+
         while ((c = getopt_long(argc, argv, "ht:p:aqfs:", options, NULL)) >= 0) {
 
                 switch (c) {
@@ -4285,6 +4337,10 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
                         }
                         break;
 
+                case ARG_NO_ASK_PASSWORD:
+                        arg_ask_password = false;
+                        break;
+
                 case '?':
                         return -EINVAL;
 

commit 0ddf1d3aa5e96b752ad62be48f99d7850a3d8542
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Oct 26 04:45:27 2010 +0200

    ask-password: properly handle multiple pending passwords when writing wall msg

diff --git a/src/tty-ask-password-agent.c b/src/tty-ask-password-agent.c
index 8a9330d..5b42939 100644
--- a/src/tty-ask-password-agent.c
+++ b/src/tty-ask-password-agent.c
@@ -200,7 +200,7 @@ finish:
         return r;
 }
 
-static int parse_password(const char *filename) {
+static int parse_password(const char *filename, char **wall) {
         char *socket_name = NULL, *message = NULL, *packet = NULL;
         uint64_t not_after = 0;
         unsigned pid = 0;
@@ -248,11 +248,13 @@ static int parse_password(const char *filename) {
         if (arg_action == ACTION_LIST)
                 printf("'%s' (PID %u)\n", message, pid);
         else if (arg_action == ACTION_WALL) {
-                char *wall;
+                char *_wall;
 
-                if (asprintf(&wall,
-                             "Password entry required for \'%s\' (PID %u).\r\n"
+                if (asprintf(&_wall,
+                             "%s%sPassword entry required for \'%s\' (PID %u).\r\n"
                              "Please enter password with the systemd-tty-password-agent tool!",
+                             *wall ? *wall : "",
+                             *wall ? "\r\n\r\n" : "",
                              message,
                              pid) < 0) {
                         log_error("Out of memory");
@@ -260,8 +262,8 @@ static int parse_password(const char *filename) {
                         goto finish;
                 }
 
-                r = utmp_wall(wall);
-                free(wall);
+                free(*wall);
+                *wall = _wall;
         } else {
                 union {
                         struct sockaddr sa;
@@ -346,6 +348,7 @@ static int show_passwords(void) {
         while ((de = readdir(d))) {
                 char *p;
                 int q;
+                char *wall;
 
                 if (de->d_type != DT_REG)
                         continue;
@@ -362,10 +365,16 @@ static int show_passwords(void) {
                         goto finish;
                 }
 
-                if ((q = parse_password(p)) < 0)
+                wall = NULL;
+                if ((q = parse_password(p, &wall)) < 0)
                         r = q;
 
                 free(p);
+
+                if (wall) {
+                        utmp_wall(wall);
+                        free(wall);
+                }
         }
 
 finish:

commit e0e1580aae5913870933518f3cb7055730ce3a49
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Oct 26 04:40:32 2010 +0200

    ask-password: enable plymouth agent by default

diff --git a/Makefile.am b/Makefile.am
index a55b244..7f8df05 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -210,7 +210,8 @@ dist_systemunit_DATA = \
 	units/systemd-readahead-done.timer \
 	units/systemd-tmpfiles-clean.timer \
 	units/quotaon.service \
-	units/systemd-ask-password-wall.path
+	units/systemd-ask-password-wall.path \
+	units/systemd-ask-password-plymouth.path
 
 nodist_systemunit_DATA = \
 	units/sysinit.target \
@@ -237,6 +238,7 @@ nodist_systemunit_DATA = \
 	units/systemd-tmpfiles-clean.service \
 	units/systemd-user-sessions.service \
 	units/systemd-ask-password-wall.service \
+	units/systemd-ask-password-plymouth.service \
 	units/syslog.target \
 	units/halt.service \
 	units/poweroff.service \
@@ -279,6 +281,7 @@ EXTRA_DIST = \
 	units/systemd-tmpfiles-clean.service.in \
 	units/systemd-user-sessions.service.in \
 	units/systemd-ask-password-wall.service.in \
+	units/systemd-ask-password-plymouth.service.in \
 	units/syslog.target.in \
 	units/halt.service.in \
 	units/poweroff.service.in \
@@ -1186,8 +1189,9 @@ if TARGET_FEDORA
 		rm -f single.service && \
 		$(LN_S) $(systemunitdir)/single.service single.service )
 	( cd $(DESTDIR)$(systemunitdir)/multi-user.target.wants && \
-		rm -f plymouth-quit.service && \
-		$(LN_S) ../plymouth-quit.service plymouth-quit.service )
+		rm -f plymouth-quit.service systemd-ask-password-plymouth.path && \
+		$(LN_S) ../plymouth-quit.service plymouth-quit.service && \
+		$(LN_S) ../systemd-ask-password-plymouth.path systemd-ask-password-plymouth.path )
 	( cd $(DESTDIR)$(systemunitdir)/reboot.target.wants && \
 		rm -f plymouth-reboot.service && \
 		$(LN_S) ../plymouth-reboot.service plymouth-reboot.service )
diff --git a/units/.gitignore b/units/.gitignore
index 42058c5..add0c6b 100644
--- a/units/.gitignore
+++ b/units/.gitignore
@@ -1,3 +1,4 @@
+systemd-ask-password-plymouth.service
 systemd-ask-password-wall.service
 quotacheck.service
 fsck at .service
diff --git a/units/systemd-ask-password-plymouth.path b/units/systemd-ask-password-plymouth.path
new file mode 100644
index 0000000..9fd51f2
--- /dev/null
+++ b/units/systemd-ask-password-plymouth.path
@@ -0,0 +1,13 @@
+#  This file is part of systemd.
+#
+#  systemd is free software; you can redistribute it and/or modify it
+#  under the terms of the GNU General Public License as published by
+#  the Free Software Foundation; either version 2 of the License, or
+#  (at your option) any later version.
+
+[Unit]
+Description=Forward Password Requests to Plymouth Directory Watch
+After=local-fs.target
+
+[Path]
+DirectoryNotEmpty=/dev/.systemd/ask-password
diff --git a/units/systemd-ask-password-plymouth.service.in b/units/systemd-ask-password-plymouth.service.in
new file mode 100644
index 0000000..3cd9b7f
--- /dev/null
+++ b/units/systemd-ask-password-plymouth.service.in
@@ -0,0 +1,12 @@
+#  This file is part of systemd.
+#
+#  systemd is free software; you can redistribute it and/or modify it
+#  under the terms of the GNU General Public License as published by
+#  the Free Software Foundation; either version 2 of the License, or
+#  (at your option) any later version.
+
+[Unit]
+Description=Forward Password Requests to Plymouth
+
+[Service]
+ExecStart=@rootbindir@/systemd-tty-ask-password-agent --watch --plymouth

commit e5ebf783cb8e353bf1e07b34ac344bd4883a4ec2
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Oct 26 04:35:25 2010 +0200

    ask-password: add minimal plymouth password agent

diff --git a/TODO b/TODO
index 938ee49..f1e6312 100644
--- a/TODO
+++ b/TODO
@@ -58,8 +58,6 @@
 * start getty 2-6 only when actual vt switch happens
   (same model as socket on-demand activation)
 
-* ask-password plymouth agent
-
 * spawn ask-password tty agent temporarily in systemctl
 
 * readahead: btrfs/LVM SSD detection
@@ -84,6 +82,8 @@
 
 * make description of .swap files nicer: resolve /dev/by-uuid/ symlink
 
+* systemctl status getty at tty1.service
+
 External:
 
 * patch kernel to add /proc/swaps change notifications
diff --git a/src/tty-ask-password-agent.c b/src/tty-ask-password-agent.c
index 9c4d076..8a9330d 100644
--- a/src/tty-ask-password-agent.c
+++ b/src/tty-ask-password-agent.c
@@ -33,6 +33,7 @@
 #include "util.h"
 #include "conf-parser.h"
 #include "utmp-wtmp.h"
+#include "socket-util.h"
 
 static enum {
         ACTION_LIST,
@@ -41,6 +42,164 @@ static enum {
         ACTION_WALL
 } arg_action = ACTION_QUERY;
 
+static bool arg_plymouth = false;
+
+static int ask_password_plymouth(const char *message, usec_t until, const char *flag_file, char **_passphrase) {
+        int fd = -1, notify = -1;
+        union sockaddr_union sa;
+        char *packet = NULL;
+        ssize_t k;
+        int r, n;
+        struct pollfd pollfd[2];
+        char buffer[LINE_MAX];
+        size_t p = 0;
+        enum {
+                POLL_SOCKET,
+                POLL_INOTIFY
+        };
+
+        if (flag_file) {
+                if ((notify = inotify_init1(IN_CLOEXEC|IN_NONBLOCK)) < 0) {
+                        r = -errno;
+                        goto finish;
+                }
+
+                if (inotify_add_watch(notify, flag_file, IN_ATTRIB /* for the link count */) < 0) {
+                        r = -errno;
+                        goto finish;
+                }
+        }
+
+        if ((fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0)) < 0) {
+                r = -errno;
+                goto finish;
+        }
+
+        zero(sa);
+        sa.sa.sa_family = AF_UNIX;
+        strncpy(sa.un.sun_path+1, "/ply-boot-protocol", sizeof(sa.un.sun_path)-1);
+
+        if (connect(fd, &sa.sa, sizeof(sa.un)) < 0) {
+                r = -errno;
+                goto finish;
+        }
+
+        if (asprintf(&packet, "*\002%c%s%n", (int) (strlen(message) + 1), message, &n) < 0) {
+                r = -ENOMEM;
+                goto finish;
+        }
+
+        if ((k = loop_write(fd, packet, n+1, true)) != n+1) {
+                r = k < 0 ? (int) k : -EIO;
+                goto finish;
+        }
+
+        zero(pollfd);
+        pollfd[POLL_SOCKET].fd = fd;
+        pollfd[POLL_SOCKET].events = POLLIN;
+        pollfd[POLL_INOTIFY].fd = notify;
+        pollfd[POLL_INOTIFY].events = POLLIN;
+
+        for (;;) {
+                int sleep_for = -1, j;
+
+                if (until > 0) {
+                        usec_t y;
+
+                        y = now(CLOCK_MONOTONIC);
+
+                        if (y > until) {
+                                r = -ETIMEDOUT;
+                                goto finish;
+                        }
+
+                        sleep_for = (int) ((until - y) / USEC_PER_MSEC);
+                }
+
+                if (flag_file)
+                        if (access(flag_file, F_OK) < 0) {
+                                r = -errno;
+                                goto finish;
+                        }
+
+                if ((j = poll(pollfd, notify > 0 ? 2 : 1, sleep_for)) < 0) {
+
+                        if (errno == EINTR)
+                                continue;
+
+                        r = -errno;
+                        goto finish;
+                } else if (j == 0) {
+                        r = -ETIMEDOUT;
+                        goto finish;
+                }
+
+                if (notify > 0 && pollfd[POLL_INOTIFY].revents != 0)
+                        flush_fd(notify);
+
+                if (pollfd[POLL_SOCKET].revents == 0)
+                        continue;
+
+                if ((k = read(fd, buffer + p, sizeof(buffer) - p)) <= 0) {
+                        r = k < 0 ? -errno : -EIO;
+                        goto finish;
+                }
+
+                p += k;
+
+                if (p < 1)
+                        continue;
+
+                if (buffer[0] == 5) {
+                        /* No password, because UI not shown */
+                        r = -ENOENT;
+                        goto finish;
+
+                } else if (buffer[0] == 2) {
+                        uint32_t size;
+                        char *s;
+
+                        /* One answer */
+                        if (p < 5)
+                                continue;
+
+                        memcpy(&size, buffer+1, sizeof(size));
+                        if (size+5 > sizeof(buffer)) {
+                                r = -EIO;
+                                goto finish;
+                        }
+
+                        if (p-5 < size)
+                                continue;
+
+                        if (!(s = strndup(buffer + 5, size))) {
+                                r = -ENOMEM;
+                                goto finish;
+                        }
+
+                        *_passphrase = s;
+                        break;
+                } else {
+                        /* Unknown packet */
+                        r = -EIO;
+                        goto finish;
+                }
+        }
+
+        r = 0;
+
+finish:
+        if (notify >= 0)
+                close_nointr_nofail(notify);
+
+        if (fd >= 0)
+                close_nointr_nofail(fd);
+
+        free(packet);
+
+        return r;
+}
+
 static int parse_password(const char *filename) {
         char *socket_name = NULL, *message = NULL, *packet = NULL;
         uint64_t not_after = 0;
@@ -122,8 +281,13 @@ static int parse_password(const char *filename) {
                         goto finish;
                 }
 
-                if ((r = ask_password_tty(message, not_after, filename, &password)) < 0) {
-                        log_error("Failed to query passwords: %s", strerror(-r));
+                if (arg_plymouth)
+                        r = ask_password_plymouth(message, not_after, filename, &password);
+                else
+                        r = ask_password_tty(message, not_after, filename, &password);
+
+                if (r < 0) {
+                        log_error("Failed to query password: %s", strerror(-r));
                         goto finish;
                 }
 
@@ -262,11 +426,12 @@ static int help(void) {
 
         printf("%s [OPTIONS...]\n\n"
                "Process system password requests.\n\n"
-               "  -h --help   Show this help\n"
-               "     --list   Show pending password requests\n"
-               "     --query  Process pending password requests\n"
-               "     --watch  Continously process password requests\n"
-               "     --wall   Continously forward password requests to wall\n",
+               "  -h --help     Show this help\n"
+               "     --list     Show pending password requests\n"
+               "     --query    Process pending password requests\n"
+               "     --watch    Continously process password requests\n"
+               "     --wall     Continously forward password requests to wall\n"
+               "     --plymouth Ask question with Plymouth instead of on TTY\n",
                program_invocation_short_name);
 
         return 0;
@@ -279,15 +444,17 @@ static int parse_argv(int argc, char *argv[]) {
                 ARG_QUERY,
                 ARG_WATCH,
                 ARG_WALL,
+                ARG_PLYMOUTH
         };
 
         static const struct option options[] = {
-                { "help",  no_argument, NULL, 'h'       },
-                { "list",  no_argument, NULL, ARG_LIST  },
-                { "query", no_argument, NULL, ARG_QUERY },
-                { "watch", no_argument, NULL, ARG_WATCH },
-                { "wall",  no_argument, NULL, ARG_WALL  },
-                { NULL,    0,           NULL, 0         }
+                { "help",     no_argument, NULL, 'h'          },
+                { "list",     no_argument, NULL, ARG_LIST     },
+                { "query",    no_argument, NULL, ARG_QUERY    },
+                { "watch",    no_argument, NULL, ARG_WATCH    },
+                { "wall",     no_argument, NULL, ARG_WALL     },
+                { "plymouth", no_argument, NULL, ARG_PLYMOUTH },
+                { NULL,    0,           NULL, 0               }
         };
 
         int c;
@@ -319,6 +486,10 @@ static int parse_argv(int argc, char *argv[]) {
                         arg_action = ACTION_WALL;
                         break;
 
+                case ARG_PLYMOUTH:
+                        arg_plymouth = true;
+                        break;
+
                 case '?':
                         return -EINVAL;
 
diff --git a/src/util.c b/src/util.c
index 973cee1..f5ee298 100644
--- a/src/util.c
+++ b/src/util.c
@@ -3380,7 +3380,7 @@ int ask_password_tty(const char *message, usec_t until, const char *flag_file, c
         assert(_passphrase);
 
         if (flag_file) {
-                if ((notify = inotify_init1(IN_CLOEXEC)) < 0) {
+                if ((notify = inotify_init1(IN_CLOEXEC|IN_NONBLOCK)) < 0) {
                         r = -errno;
                         goto finish;
                 }



More information about the systemd-commits mailing list