summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2019-10-08 09:20:40 +0200
committerGitHub <noreply@github.com>2019-10-08 09:20:40 +0200
commite0a0c64cb904c336948821647cc4c873cf668e35 (patch)
tree5b21066642b9caca13dc456cd61f2561c3483316
parenttrivial: rename chromeos to chromiumos (diff)
parenttty-ask-pwd-agent: move ask_password_plymouth() in ask-password-api.c (diff)
downloadsystemd-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.c15
-rw-r--r--src/basic/fs-util.h1
-rw-r--r--src/core/manager.c8
-rw-r--r--src/core/path.c39
-rw-r--r--src/shared/ask-password-api.c189
-rw-r--r--src/shared/ask-password-api.h1
-rw-r--r--src/time-wait-sync/time-wait-sync.c4
-rw-r--r--src/tty-ask-password-agent/tty-ask-password-agent.c373
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);