diff options
author | Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> | 2019-10-08 09:20:40 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-10-08 09:20:40 +0200 |
commit | e0a0c64cb904c336948821647cc4c873cf668e35 (patch) | |
tree | 5b21066642b9caca13dc456cd61f2561c3483316 | |
parent | trivial: rename chromeos to chromiumos (diff) | |
parent | tty-ask-pwd-agent: move ask_password_plymouth() in ask-password-api.c (diff) | |
download | systemd-e0a0c64cb904c336948821647cc4c873cf668e35.tar.xz systemd-e0a0c64cb904c336948821647cc4c873cf668e35.zip |
Merge pull request #13632 from fbuihuu/ask-password-some-reworks
Ask password some reworks
-rw-r--r-- | src/basic/fs-util.c | 15 | ||||
-rw-r--r-- | src/basic/fs-util.h | 1 | ||||
-rw-r--r-- | src/core/manager.c | 8 | ||||
-rw-r--r-- | src/core/path.c | 39 | ||||
-rw-r--r-- | src/shared/ask-password-api.c | 189 | ||||
-rw-r--r-- | src/shared/ask-password-api.h | 1 | ||||
-rw-r--r-- | src/time-wait-sync/time-wait-sync.c | 4 | ||||
-rw-r--r-- | src/tty-ask-password-agent/tty-ask-password-agent.c | 373 |
8 files changed, 347 insertions, 283 deletions
diff --git a/src/basic/fs-util.c b/src/basic/fs-util.c index b2ac648838..a92241ca02 100644 --- a/src/basic/fs-util.c +++ b/src/basic/fs-util.c @@ -660,6 +660,21 @@ int inotify_add_watch_fd(int fd, int what, uint32_t mask) { return r; } +int inotify_add_watch_and_warn(int fd, const char *pathname, uint32_t mask) { + if (inotify_add_watch(fd, pathname, mask) < 0) { + const char *reason; + + if (errno == ENOSPC) + reason = "inotify watch limit reached"; + else + reason = strerror_safe(errno); + + return log_error_errno(errno, "Failed to add a watch for %s: %s", pathname, reason); + } + + return 0; +} + static bool unsafe_transition(const struct stat *a, const struct stat *b) { /* Returns true if the transition from a to b is safe, i.e. that we never transition from unprivileged to * privileged files or directories. Why bother? So that unprivileged code can't symlink to privileged files diff --git a/src/basic/fs-util.h b/src/basic/fs-util.h index 1f0bdd95b3..fa0f0de9a3 100644 --- a/src/basic/fs-util.h +++ b/src/basic/fs-util.h @@ -72,6 +72,7 @@ union inotify_event_buffer { }; int inotify_add_watch_fd(int fd, int what, uint32_t mask); +int inotify_add_watch_and_warn(int fd, const char *pathname, uint32_t mask); enum { CHASE_PREFIX_ROOT = 1 << 0, /* The specified path will be prefixed by the specified root before beginning the iteration */ diff --git a/src/core/manager.c b/src/core/manager.c index 600718e4bf..5f3cb6ea62 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -295,10 +295,12 @@ static int manager_check_ask_password(Manager *m) { if (m->ask_password_inotify_fd < 0) return log_error_errno(errno, "Failed to create inotify object: %m"); - if (inotify_add_watch(m->ask_password_inotify_fd, "/run/systemd/ask-password", IN_CREATE|IN_DELETE|IN_MOVE) < 0) { - log_error_errno(errno, "Failed to watch \"/run/systemd/ask-password\": %m"); + r = inotify_add_watch_and_warn(m->ask_password_inotify_fd, + "/run/systemd/ask-password", + IN_CREATE|IN_DELETE|IN_MOVE); + if (r < 0) { manager_close_ask_password(m); - return -errno; + return r; } r = sd_event_add_io(m->event, &m->ask_password_event_source, diff --git a/src/core/path.c b/src/core/path.c index ac1289a658..aee94ce7f0 100644 --- a/src/core/path.c +++ b/src/core/path.c @@ -89,24 +89,29 @@ int path_spec_watch(PathSpec *s, sd_event_io_handler_t handler) { break; } - r = log_warning_errno(errno, "Failed to add watch on %s: %s", s->path, errno == ENOSPC ? "too many watches" : strerror_safe(r)); - if (cut) - *cut = tmp; - goto fail; - } else { - exists = true; - - /* Path exists, we don't need to watch parent too closely. */ - if (oldslash) { - char *cut2 = oldslash + (oldslash == s->path); - char tmp2 = *cut2; - *cut2 = '\0'; - - (void) inotify_add_watch(s->inotify_fd, s->path, IN_MOVE_SELF); - /* Error is ignored, the worst can happen is we get spurious events. */ - - *cut2 = tmp2; + /* This second call to inotify_add_watch() should fail like the previous + * one and is done for logging the error in a comprehensive way. */ + r = inotify_add_watch_and_warn(s->inotify_fd, s->path, flags); + if (r < 0) { + if (cut) + *cut = tmp; + goto fail; } + + /* Hmm, we succeeded in adding the watch this time... let's continue. */ + } + exists = true; + + /* Path exists, we don't need to watch parent too closely. */ + if (oldslash) { + char *cut2 = oldslash + (oldslash == s->path); + char tmp2 = *cut2; + *cut2 = '\0'; + + (void) inotify_add_watch(s->inotify_fd, s->path, IN_MOVE_SELF); + /* Error is ignored, the worst can happen is we get spurious events. */ + + *cut2 = tmp2; } if (cut) diff --git a/src/shared/ask-password-api.c b/src/shared/ask-password-api.c index c41fa2dea6..a08a53d1b7 100644 --- a/src/shared/ask-password-api.c +++ b/src/shared/ask-password-api.c @@ -34,6 +34,7 @@ #include "memory-util.h" #include "missing.h" #include "mkdir.h" +#include "plymouth-util.h" #include "process-util.h" #include "random-util.h" #include "signal-util.h" @@ -211,6 +212,186 @@ static int backspace_string(int ttyfd, const char *str) { return backspace_chars(ttyfd, m); } +int ask_password_plymouth( + const char *message, + usec_t until, + AskPasswordFlags flags, + const char *flag_file, + char ***ret) { + + static const union sockaddr_union sa = PLYMOUTH_SOCKET; + _cleanup_close_ int fd = -1, notify = -1; + _cleanup_free_ 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 + }; + + assert(ret); + + if (flag_file) { + notify = inotify_init1(IN_CLOEXEC|IN_NONBLOCK); + if (notify < 0) + return -errno; + + r = inotify_add_watch(notify, flag_file, IN_ATTRIB); /* for the link count */ + if (r < 0) + return -errno; + } + + fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); + if (fd < 0) + return -errno; + + r = connect(fd, &sa.sa, SOCKADDR_UN_LEN(sa.un)); + if (r < 0) + return -errno; + + if (flags & ASK_PASSWORD_ACCEPT_CACHED) { + packet = strdup("c"); + n = 1; + } else if (asprintf(&packet, "*\002%c%s%n", (int) (strlen(message) + 1), message, &n) < 0) + packet = NULL; + if (!packet) + return -ENOMEM; + + r = loop_write(fd, packet, n + 1, true); + if (r < 0) + return r; + + 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 = -ETIME; + goto finish; + } + + sleep_for = (int) ((until - y) / USEC_PER_MSEC); + } + + if (flag_file && access(flag_file, F_OK) < 0) { + r = -errno; + goto finish; + } + + j = poll(pollfd, notify >= 0 ? 2 : 1, sleep_for); + if (j < 0) { + if (errno == EINTR) + continue; + + r = -errno; + goto finish; + } else if (j == 0) { + r = -ETIME; + goto finish; + } + + if (notify >= 0 && pollfd[POLL_INOTIFY].revents != 0) + (void) flush_fd(notify); + + if (pollfd[POLL_SOCKET].revents == 0) + continue; + + k = read(fd, buffer + p, sizeof(buffer) - p); + if (k < 0) { + if (IN_SET(errno, EINTR, EAGAIN)) + continue; + + r = -errno; + goto finish; + } else if (k == 0) { + r = -EIO; + goto finish; + } + + p += k; + + if (p < 1) + continue; + + if (buffer[0] == 5) { + + if (flags & ASK_PASSWORD_ACCEPT_CACHED) { + /* Hmm, first try with cached + * passwords failed, so let's retry + * with a normal password request */ + packet = mfree(packet); + + if (asprintf(&packet, "*\002%c%s%n", (int) (strlen(message) + 1), message, &n) < 0) { + r = -ENOMEM; + goto finish; + } + + r = loop_write(fd, packet, n+1, true); + if (r < 0) + goto finish; + + flags &= ~ASK_PASSWORD_ACCEPT_CACHED; + p = 0; + continue; + } + + /* No password, because UI not shown */ + r = -ENOENT; + goto finish; + + } else if (IN_SET(buffer[0], 2, 9)) { + uint32_t size; + char **l; + + /* One or more answers */ + if (p < 5) + continue; + + memcpy(&size, buffer+1, sizeof(size)); + size = le32toh(size); + if (size + 5 > sizeof(buffer)) { + r = -EIO; + goto finish; + } + + if (p-5 < size) + continue; + + l = strv_parse_nulstr(buffer + 5, size); + if (!l) { + r = -ENOMEM; + goto finish; + } + + *ret = l; + break; + + } else { + /* Unknown packet */ + r = -EIO; + goto finish; + } + } + + r = 0; + +finish: + explicit_bzero_safe(buffer, sizeof(buffer)); + return r; +} + int ask_password_tty( int ttyfd, const char *message, @@ -371,6 +552,13 @@ int ask_password_tty( if (n == 0 || c == '\n' || c == 0) break; + if (c == 4) { /* C-d also known as EOT */ + if (ttyfd >= 0) + (void) loop_write(ttyfd, "(skipped)", 9, false); + + goto skipped; + } + if (c == 21) { /* C-u */ if (!(flags & ASK_PASSWORD_SILENT)) @@ -467,6 +655,7 @@ int ask_password_tty( if (r < 0) goto finish; +skipped: if (keyname) (void) add_to_keyring_and_log(keyname, flags, l); diff --git a/src/shared/ask-password-api.h b/src/shared/ask-password-api.h index 15762b9cde..528e3d0197 100644 --- a/src/shared/ask-password-api.h +++ b/src/shared/ask-password-api.h @@ -16,5 +16,6 @@ typedef enum AskPasswordFlags { } AskPasswordFlags; int ask_password_tty(int tty_fd, const char *message, const char *keyname, usec_t until, AskPasswordFlags flags, const char *flag_file, char ***ret); +int ask_password_plymouth(const char *message, usec_t until, AskPasswordFlags flags, const char *flag_file, char ***ret); int ask_password_agent(const char *message, const char *icon, const char *id, const char *keyname, usec_t until, AskPasswordFlags flag, char ***ret); int ask_password_auto(const char *message, const char *icon, const char *id, const char *keyname, usec_t until, AskPasswordFlags flag, char ***ret); diff --git a/src/time-wait-sync/time-wait-sync.c b/src/time-wait-sync/time-wait-sync.c index f4d20af2d4..5b27df1f9e 100644 --- a/src/time-wait-sync/time-wait-sync.c +++ b/src/time-wait-sync/time-wait-sync.c @@ -225,9 +225,9 @@ static int run(int argc, char * argv[]) { if (r < 0) return log_error_errno(r, "Failed to create notify event source: %m"); - r = inotify_add_watch(state.inotify_fd, "/run/systemd/", IN_CREATE); + r = inotify_add_watch_and_warn(state.inotify_fd, "/run/systemd/", IN_CREATE); if (r < 0) - return log_error_errno(errno, "Failed to watch /run/systemd/: %m"); + return r; state.run_systemd_wd = r; diff --git a/src/tty-ask-password-agent/tty-ask-password-agent.c b/src/tty-ask-password-agent/tty-ask-password-agent.c index 3032f15898..2e57a628b2 100644 --- a/src/tty-ask-password-agent/tty-ask-password-agent.c +++ b/src/tty-ask-password-agent/tty-ask-password-agent.c @@ -11,7 +11,6 @@ #include <stdbool.h> #include <stddef.h> #include <string.h> -#include <sys/inotify.h> #include <sys/prctl.h> #include <sys/signalfd.h> #include <sys/socket.h> @@ -29,6 +28,7 @@ #include "exit-status.h" #include "fd-util.h" #include "fileio.h" +#include "fs-util.h" #include "hashmap.h" #include "io-util.h" #include "macro.h" @@ -36,7 +36,6 @@ #include "memory-util.h" #include "mkdir.h" #include "path-util.h" -#include "plymouth-util.h" #include "pretty-print.h" #include "process-util.h" #include "set.h" @@ -58,186 +57,6 @@ static bool arg_plymouth = false; static bool arg_console = false; static const char *arg_device = NULL; -static int ask_password_plymouth( - const char *message, - usec_t until, - AskPasswordFlags flags, - const char *flag_file, - char ***ret) { - - static const union sockaddr_union sa = PLYMOUTH_SOCKET; - _cleanup_close_ int fd = -1, notify = -1; - _cleanup_free_ 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 - }; - - assert(ret); - - if (flag_file) { - notify = inotify_init1(IN_CLOEXEC|IN_NONBLOCK); - if (notify < 0) - return -errno; - - r = inotify_add_watch(notify, flag_file, IN_ATTRIB); /* for the link count */ - if (r < 0) - return -errno; - } - - fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); - if (fd < 0) - return -errno; - - r = connect(fd, &sa.sa, SOCKADDR_UN_LEN(sa.un)); - if (r < 0) - return -errno; - - if (flags & ASK_PASSWORD_ACCEPT_CACHED) { - packet = strdup("c"); - n = 1; - } else if (asprintf(&packet, "*\002%c%s%n", (int) (strlen(message) + 1), message, &n) < 0) - packet = NULL; - if (!packet) - return -ENOMEM; - - r = loop_write(fd, packet, n + 1, true); - if (r < 0) - return r; - - 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 = -ETIME; - goto finish; - } - - sleep_for = (int) ((until - y) / USEC_PER_MSEC); - } - - if (flag_file && access(flag_file, F_OK) < 0) { - r = -errno; - goto finish; - } - - j = poll(pollfd, notify >= 0 ? 2 : 1, sleep_for); - if (j < 0) { - if (errno == EINTR) - continue; - - r = -errno; - goto finish; - } else if (j == 0) { - r = -ETIME; - goto finish; - } - - if (notify >= 0 && pollfd[POLL_INOTIFY].revents != 0) - (void) flush_fd(notify); - - if (pollfd[POLL_SOCKET].revents == 0) - continue; - - k = read(fd, buffer + p, sizeof(buffer) - p); - if (k < 0) { - if (IN_SET(errno, EINTR, EAGAIN)) - continue; - - r = -errno; - goto finish; - } else if (k == 0) { - r = -EIO; - goto finish; - } - - p += k; - - if (p < 1) - continue; - - if (buffer[0] == 5) { - - if (flags & ASK_PASSWORD_ACCEPT_CACHED) { - /* Hmm, first try with cached - * passwords failed, so let's retry - * with a normal password request */ - packet = mfree(packet); - - if (asprintf(&packet, "*\002%c%s%n", (int) (strlen(message) + 1), message, &n) < 0) { - r = -ENOMEM; - goto finish; - } - - r = loop_write(fd, packet, n+1, true); - if (r < 0) - goto finish; - - flags &= ~ASK_PASSWORD_ACCEPT_CACHED; - p = 0; - continue; - } - - /* No password, because UI not shown */ - r = -ENOENT; - goto finish; - - } else if (IN_SET(buffer[0], 2, 9)) { - uint32_t size; - char **l; - - /* One or more answers */ - if (p < 5) - continue; - - memcpy(&size, buffer+1, sizeof(size)); - size = le32toh(size); - if (size + 5 > sizeof(buffer)) { - r = -EIO; - goto finish; - } - - if (p-5 < size) - continue; - - l = strv_parse_nulstr(buffer + 5, size); - if (!l) { - r = -ENOMEM; - goto finish; - } - - *ret = l; - break; - - } else { - /* Unknown packet */ - r = -EIO; - goto finish; - } - } - - r = 0; - -finish: - explicit_bzero_safe(buffer, sizeof(buffer)); - return r; -} - static int send_passwords(const char *socket_name, char **passwords) { _cleanup_(erase_and_freep) char *packet = NULL; _cleanup_close_ int socket_fd = -1; @@ -318,7 +137,40 @@ static bool wall_tty_match(const char *path, void *userdata) { return 0; } -static int parse_password(const char *filename) { +static int agent_ask_password_tty( + const char *message, + usec_t until, + AskPasswordFlags flags, + const char *flag_file, + char ***ret) { + + int tty_fd = -1; + int r; + + if (arg_console) { + const char *con = arg_device ?: "/dev/console"; + + tty_fd = acquire_terminal(con, ACQUIRE_TERMINAL_WAIT, USEC_INFINITY); + if (tty_fd < 0) + return log_error_errno(tty_fd, "Failed to acquire %s: %m", con); + + r = reset_terminal_fd(tty_fd, true); + if (r < 0) + log_warning_errno(r, "Failed to reset terminal, ignoring: %m"); + + } + + r = ask_password_tty(tty_fd, message, NULL, until, flags, flag_file, ret); + + if (arg_console) { + tty_fd = safe_close(tty_fd); + release_terminal(); + } + + return 0; +} + +static int process_one_password_file(const char *filename) { _cleanup_free_ char *socket_name = NULL, *message = NULL; bool accept_cached = false, echo = false; uint64_t not_after = 0; @@ -355,25 +207,28 @@ static int parse_password(const char *filename) { if (pid > 0 && !pid_is_alive(pid)) return 0; - if (arg_action == ACTION_LIST) + switch (arg_action) { + case ACTION_LIST: printf("'%s' (PID %u)\n", message, pid); + return 0; - else if (arg_action == ACTION_WALL) { - _cleanup_free_ char *wall = NULL; - - if (asprintf(&wall, - "Password entry required for \'%s\' (PID %u).\r\n" - "Please enter password with the systemd-tty-ask-password-agent tool.", - message, - pid) < 0) - return log_oom(); + case ACTION_WALL: { + _cleanup_free_ char *wall = NULL; - (void) utmp_wall(wall, NULL, NULL, wall_tty_match, NULL); + if (asprintf(&wall, + "Password entry required for \'%s\' (PID %u).\r\n" + "Please enter password with the systemd-tty-ask-password-agent tool.", + message, + pid) < 0) + return log_oom(); - } else { + (void) utmp_wall(wall, NULL, NULL, wall_tty_match, NULL); + return 0; + } + case ACTION_QUERY: + case ACTION_WATCH: { _cleanup_strv_free_erase_ char **passwords = NULL; - - assert(IN_SET(arg_action, ACTION_QUERY, ACTION_WATCH)); + AskPasswordFlags flags = 0; if (access(socket_name, W_OK) < 0) { if (arg_action == ACTION_QUERY) @@ -382,44 +237,31 @@ static int parse_password(const char *filename) { return 0; } - if (arg_plymouth) - r = ask_password_plymouth(message, not_after, accept_cached ? ASK_PASSWORD_ACCEPT_CACHED : 0, filename, &passwords); - else { - int tty_fd = -1; - - if (arg_console) { - const char *con = arg_device ?: "/dev/console"; + SET_FLAG(flags, ASK_PASSWORD_ACCEPT_CACHED, accept_cached); + SET_FLAG(flags, ASK_PASSWORD_CONSOLE_COLOR, arg_console); + SET_FLAG(flags, ASK_PASSWORD_ECHO, echo); - tty_fd = acquire_terminal(con, ACQUIRE_TERMINAL_WAIT, USEC_INFINITY); - if (tty_fd < 0) - return log_error_errno(tty_fd, "Failed to acquire %s: %m", con); - - r = reset_terminal_fd(tty_fd, true); - if (r < 0) - log_warning_errno(r, "Failed to reset terminal, ignoring: %m"); - } + if (arg_plymouth) + r = ask_password_plymouth(message, not_after, flags, filename, &passwords); + else + r = agent_ask_password_tty(message, not_after, flags, filename, &passwords); - r = ask_password_tty(tty_fd, message, NULL, not_after, - (echo ? ASK_PASSWORD_ECHO : 0) | - (arg_console ? ASK_PASSWORD_CONSOLE_COLOR : 0), - filename, &passwords); + if (r < 0) { + /* If the query went away, that's OK */ + if (IN_SET(r, -ETIME, -ENOENT)) + return 0; - if (arg_console) { - tty_fd = safe_close(tty_fd); - release_terminal(); - } + return log_error_errno(r, "Failed to query password: %m"); } - /* If the query went away, that's OK */ - if (IN_SET(r, -ETIME, -ENOENT)) - return 0; - - if (r < 0) - return log_error_errno(r, "Failed to query password: %m"); + if (strv_isempty(passwords)) + return -ECANCELED; r = send_passwords(socket_name, passwords); if (r < 0) return log_error_errno(r, "Failed to send: %m"); + break; + } } return 0; @@ -449,7 +291,7 @@ static int wall_tty_block(void) { return fd; } -static int show_passwords(void) { +static int process_password_files(void) { _cleanup_closedir_ DIR *d; struct dirent *de; int r = 0; @@ -462,7 +304,7 @@ static int show_passwords(void) { return log_error_errno(errno, "Failed to open /run/systemd/ask-password: %m"); } - FOREACH_DIRENT_ALL(de, d, return log_error_errno(errno, "Failed to read directory: %m")) { + FOREACH_DIRENT(de, d, return log_error_errno(errno, "Failed to read directory: %m")) { _cleanup_free_ char *p = NULL; int q; @@ -472,9 +314,6 @@ static int show_passwords(void) { if (de->d_type != DT_REG) continue; - if (hidden_or_backup_file(de->d_name)) - continue; - if (!startswith(de->d_name, "ask.")) continue; @@ -482,7 +321,7 @@ static int show_passwords(void) { if (!p) return log_oom(); - q = parse_password(p); + q = process_one_password_file(p); if (q < 0 && r == 0) r = q; } @@ -490,10 +329,10 @@ static int show_passwords(void) { return r; } -static int watch_passwords(void) { +static int process_and_watch_password_files(bool watch) { enum { - FD_INOTIFY, FD_SIGNAL, + FD_INOTIFY, _FD_MAX }; @@ -506,36 +345,51 @@ static int watch_passwords(void) { (void) mkdir_p_label("/run/systemd/ask-password", 0755); - notify = inotify_init1(IN_CLOEXEC); - if (notify < 0) - return log_error_errno(errno, "Failed to allocate directory watch: %m"); - - if (inotify_add_watch(notify, "/run/systemd/ask-password", IN_CLOSE_WRITE|IN_MOVED_TO) < 0) { - if (errno == ENOSPC) - return log_error_errno(errno, "Failed to add /run/systemd/ask-password to directory watch: inotify watch limit reached"); - else - return log_error_errno(errno, "Failed to add /run/systemd/ask-password to directory watch: %m"); - } - assert_se(sigemptyset(&mask) >= 0); - assert_se(sigset_add_many(&mask, SIGINT, SIGTERM, -1) >= 0); + assert_se(sigset_add_many(&mask, SIGTERM, -1) >= 0); assert_se(sigprocmask(SIG_SETMASK, &mask, NULL) >= 0); - signal_fd = signalfd(-1, &mask, SFD_NONBLOCK|SFD_CLOEXEC); - if (signal_fd < 0) - return log_error_errno(errno, "Failed to allocate signal file descriptor: %m"); + if (watch) { + signal_fd = signalfd(-1, &mask, SFD_NONBLOCK|SFD_CLOEXEC); + if (signal_fd < 0) + return log_error_errno(errno, "Failed to allocate signal file descriptor: %m"); - pollfd[FD_INOTIFY].fd = notify; - pollfd[FD_INOTIFY].events = POLLIN; - pollfd[FD_SIGNAL].fd = signal_fd; - pollfd[FD_SIGNAL].events = POLLIN; + pollfd[FD_SIGNAL].fd = signal_fd; + pollfd[FD_SIGNAL].events = POLLIN; - for (;;) { - r = show_passwords(); + notify = inotify_init1(IN_CLOEXEC); + if (notify < 0) + return log_error_errno(errno, "Failed to allocate directory watch: %m"); + + r = inotify_add_watch_and_warn(notify, "/run/systemd/ask-password", IN_CLOSE_WRITE|IN_MOVED_TO); if (r < 0) - log_error_errno(r, "Failed to show password: %m"); + return r; + + pollfd[FD_INOTIFY].fd = notify; + pollfd[FD_INOTIFY].events = POLLIN; + } + + for (;;) { + int timeout = -1; + + r = process_password_files(); + if (r < 0) { + if (r == -ECANCELED) + /* Disable poll() timeout since at least one password has + * been skipped and therefore one file remains and is + * unlikely to trigger any events. */ + timeout = 0; + else + /* FIXME: we should do something here since otherwise the service + * requesting the password won't notice the error and will wait + * indefinitely. */ + log_error_errno(r, "Failed to process password: %m"); + } + + if (!watch) + break; - if (poll(pollfd, _FD_MAX, -1) < 0) { + if (poll(pollfd, watch ? _FD_MAX : _FD_MAX-1, timeout) < 0) { if (errno == EINTR) continue; @@ -856,10 +710,7 @@ static int run(int argc, char *argv[]) { (void) release_terminal(); } - if (IN_SET(arg_action, ACTION_WATCH, ACTION_WALL)) - return watch_passwords(); - else - return show_passwords(); + return process_and_watch_password_files(arg_action != ACTION_QUERY); } DEFINE_MAIN_FUNCTION(run); |