X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fshared%2Futil.c;h=4fda31c83832de5cd34efd99800e0da0f35dbeaf;hb=6589d0dba2b1ccf2406db527c2c1b51c7143e117;hp=d223ecf7114ddd809d65d954e1367f04551fe725;hpb=6294aa76d818e831de4592b41a37e225fd0871f9;p=elogind.git diff --git a/src/shared/util.c b/src/shared/util.c index d223ecf71..4fda31c83 100644 --- a/src/shared/util.c +++ b/src/shared/util.c @@ -1624,7 +1624,7 @@ int read_one_char(FILE *f, char *ret, usec_t t, bool *need_nl) { return 0; } -int ask(char *ret, const char *replies, const char *text, ...) { +int ask_char(char *ret, const char *replies, const char *text, ...) { int r; assert(ret); @@ -1672,6 +1672,49 @@ int ask(char *ret, const char *replies, const char *text, ...) { } } +int ask_string(char **ret, const char *text, ...) { + assert(ret); + assert(text); + + for (;;) { + char line[LINE_MAX]; + va_list ap; + + if (on_tty()) + fputs(ANSI_HIGHLIGHT_ON, stdout); + + va_start(ap, text); + vprintf(text, ap); + va_end(ap); + + if (on_tty()) + fputs(ANSI_HIGHLIGHT_OFF, stdout); + + fflush(stdout); + + errno = 0; + if (!fgets(line, sizeof(line), stdin)) + return errno ? -errno : -EIO; + + if (!endswith(line, "\n")) + putchar('\n'); + else { + char *s; + + if (isempty(line)) + continue; + + truncate_nl(line); + s = strdup(line); + if (!s) + return -ENOMEM; + + *ret = s; + return 0; + } + } +} + int reset_terminal_fd(int fd, bool switch_to_text) { struct termios termios; int r = 0; @@ -3561,6 +3604,17 @@ int null_or_empty_path(const char *fn) { return null_or_empty(&st); } +int null_or_empty_fd(int fd) { + struct stat st; + + assert(fd >= 0); + + if (fstat(fd, &st) < 0) + return -errno; + + return null_or_empty(&st); +} + DIR *xopendirat(int fd, const char *name, int flags) { int nfd; DIR *d; @@ -3807,7 +3861,8 @@ void execute_directory(const char *directory, DIR *d, usec_t timeout, char *argv if (!dirent_is_file(de)) continue; - if (asprintf(&path, "%s/%s", directory, de->d_name) < 0) { + path = strjoin(directory, "/", de->d_name, NULL); + if (!path) { log_oom(); _exit(EXIT_FAILURE); } @@ -5375,7 +5430,7 @@ bool string_has_cc(const char *p, const char *ok) { for (t = p; *t; t++) { if (ok && strchr(ok, *t)) - return false; + continue; if (*t > 0 && *t < ' ') return true; @@ -6771,3 +6826,43 @@ bool is_localhost(const char *hostname) { endswith(hostname, ".localdomain") || endswith(hostname, ".localdomain."); } + +int take_password_lock(const char *root) { + + struct flock flock = { + .l_type = F_WRLCK, + .l_whence = SEEK_SET, + .l_start = 0, + .l_len = 0, + }; + + const char *path; + int fd, r; + + /* This is roughly the same as lckpwdf(), but not as awful. We + * don't want to use alarm() and signals, hence we implement + * our own trivial version of this. + * + * Note that shadow-utils also takes per-database locks in + * addition to lckpwdf(). However, we don't given that they + * are redundant as they they invoke lckpwdf() first and keep + * it during everything they do. The per-database locks are + * awfully racy, and thus we just won't do them. */ + + if (root) + path = strappenda(root, "/etc/.pwd.lock"); + else + path = "/etc/.pwd.lock"; + + fd = open(path, O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW, 0600); + if (fd < 0) + return -errno; + + r = fcntl(fd, F_SETLKW, &flock); + if (r < 0) { + safe_close(fd); + return -errno; + } + + return fd; +}