static const char *arg_device = NULL;
static int send_passwords(const char *socket_name, char **passwords) {
- _cleanup_(erase_and_freep) char *packet = NULL;
- _cleanup_close_ int socket_fd = -EBADF;
- union sockaddr_union sa;
- socklen_t sa_len;
- size_t packet_length = 1;
- char *d;
- ssize_t n;
int r;
assert(socket_name);
+ union sockaddr_union sa;
r = sockaddr_un_set_path(&sa.un, socket_name);
if (r < 0)
return r;
- sa_len = r;
+ socklen_t sa_len = r;
+ size_t packet_length = 1;
STRV_FOREACH(p, passwords)
packet_length += strlen(*p) + 1;
- packet = new(char, packet_length);
+ _cleanup_(erase_and_freep) char *packet = new(char, packet_length);
if (!packet)
return -ENOMEM;
packet[0] = '+';
- d = packet + 1;
+ char *d = packet + 1;
STRV_FOREACH(p, passwords)
d = stpcpy(d, *p) + 1;
- socket_fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
+ _cleanup_close_ int socket_fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
if (socket_fd < 0)
return log_debug_errno(errno, "socket(): %m");
- n = sendto(socket_fd, packet, packet_length, MSG_NOSIGNAL, &sa.sa, sa_len);
+ ssize_t n = sendto(socket_fd, packet, packet_length, MSG_NOSIGNAL, &sa.sa, sa_len);
if (n < 0)
return log_debug_errno(errno, "sendto(): %m");
}
static bool wall_tty_match(const char *path, bool is_local, void *userdata) {
- _cleanup_free_ char *p = NULL;
- _cleanup_close_ int fd = -EBADF;
- struct stat st;
-
assert(path_is_absolute(path));
+ struct stat st;
if (lstat(path, &st) < 0) {
log_debug_errno(errno, "Failed to stat %s: %m", path);
return true;
* advantage that the block will automatically go away if the
* process dies. */
+ _cleanup_free_ char *p = NULL;
if (asprintf(&p, "/run/systemd/ask-password-block/%u:%u", major(st.st_rdev), minor(st.st_rdev)) < 0) {
- log_oom();
+ log_oom_debug();
return true;
}
- fd = open(p, O_WRONLY|O_CLOEXEC|O_NONBLOCK|O_NOCTTY);
+ _cleanup_close_ int fd = open(p, O_WRONLY|O_CLOEXEC|O_NONBLOCK|O_NOCTTY);
if (fd < 0) {
log_debug_errno(errno, "Failed to open the wall pipe: %m");
return 1;
r = ask_password_tty(tty_fd, &req, until, flags, flag_file, ret);
if (arg_console) {
+ assert(tty_fd >= 0);
tty_fd = safe_close(tty_fd);
release_terminal();
return r;
}
-static int process_one_password_file(const char *filename) {
+static int process_one_password_file(const char *filename, FILE *f) {
_cleanup_free_ char *socket_name = NULL, *message = NULL;
bool accept_cached = false, echo = false, silent = false;
uint64_t not_after = 0;
int r;
assert(filename);
-
- r = config_parse(NULL, filename, NULL,
- NULL,
- config_item_table_lookup, items,
+ assert(f);
+
+ r = config_parse(/* unit= */ NULL,
+ filename,
+ f,
+ /* sections= */ "Ask\0",
+ config_item_table_lookup,
+ items,
CONFIG_PARSE_RELAXED|CONFIG_PARSE_WARN,
- NULL,
- NULL);
+ /* userdata= */ NULL,
+ /* ret_stat= */ NULL);
if (r < 0)
return r;
static int process_password_files(void) {
_cleanup_closedir_ DIR *d = NULL;
- int r = 0;
+ int ret = 0, r;
d = opendir("/run/systemd/ask-password");
if (!d) {
FOREACH_DIRENT(de, d, return log_error_errno(errno, "Failed to read directory: %m")) {
_cleanup_free_ char *p = NULL;
- int q;
-
- /* We only support /run on tmpfs, hence we can rely on
- * d_type to be reliable */
- if (de->d_type != DT_REG)
+ if (!IN_SET(de->d_type, DT_REG, DT_UNKNOWN))
continue;
if (!startswith(de->d_name, "ask."))
if (!p)
return log_oom();
- q = process_one_password_file(p);
- if (q < 0 && r == 0)
- r = q;
+ _cleanup_fclose_ FILE *f = NULL;
+ r = xfopenat(dirfd(d), de->d_name, "re", O_NOFOLLOW, &f);
+ if (r < 0) {
+ log_warning_errno(r, "Failed to open '%s', ignoring: %m", p);
+ continue;
+ }
+
+ RET_GATHER(ret, process_one_password_file(p, f));
}
- return r;
+ return ret;
}
static int process_and_watch_password_files(bool watch) {
usec_t timeout = USEC_INFINITY;
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 (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 if (r < 0)
+ /* FIXME: we should do something here since otherwise the service
+ * requesting the password won't notice the error and will wait
+ * indefinitely. */
+ log_warning_errno(r, "Failed to process password, ignoring: %m");
if (!watch)
break;