X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Futil.c;h=2363ea27b2b87766a459aa31522f7a71a968874d;hp=4fdc8e57c5bbe93db072ee978e9ae36eb5055685;hb=eb22ac37f3e07b9c49a3f8fdc8cc02631faabcb4;hpb=7d7936059fac45b909faeb6a65dd7346e9d55378 diff --git a/src/util.c b/src/util.c index 4fdc8e57c..2363ea27b 100644 --- a/src/util.c +++ b/src/util.c @@ -44,6 +44,8 @@ #include #include #include +#include +#include #include "macro.h" #include "util.h" @@ -1962,7 +1964,7 @@ int close_pipe(int p[]) { return a < 0 ? a : b; } -ssize_t loop_read(int fd, void *buf, size_t nbytes) { +ssize_t loop_read(int fd, void *buf, size_t nbytes, bool do_poll) { uint8_t *p; ssize_t n = 0; @@ -1976,10 +1978,10 @@ ssize_t loop_read(int fd, void *buf, size_t nbytes) { if ((k = read(fd, p, nbytes)) <= 0) { - if (errno == EINTR) + if (k < 0 && errno == EINTR) continue; - if (errno == EAGAIN) { + if (k < 0 && errno == EAGAIN && do_poll) { struct pollfd pollfd; zero(pollfd); @@ -2010,6 +2012,54 @@ ssize_t loop_read(int fd, void *buf, size_t nbytes) { return n; } +ssize_t loop_write(int fd, const void *buf, size_t nbytes, bool do_poll) { + const uint8_t *p; + ssize_t n = 0; + + assert(fd >= 0); + assert(buf); + + p = buf; + + while (nbytes > 0) { + ssize_t k; + + if ((k = write(fd, p, nbytes)) <= 0) { + + if (k < 0 && errno == EINTR) + continue; + + if (k < 0 && errno == EAGAIN && do_poll) { + struct pollfd pollfd; + + zero(pollfd); + pollfd.fd = fd; + pollfd.events = POLLOUT; + + if (poll(&pollfd, 1, -1) < 0) { + if (errno == EINTR) + continue; + + return n > 0 ? n : -errno; + } + + if (pollfd.revents != POLLOUT) + return n > 0 ? n : -EIO; + + continue; + } + + return n > 0 ? n : (k < 0 ? -errno : 0); + } + + p += k; + nbytes -= k; + n += k; + } + + return n; +} + int path_is_mount_point(const char *t) { struct stat a, b; char *copy; @@ -2180,7 +2230,7 @@ unsigned long long random_ull(void) { if ((fd = open("/dev/urandom", O_RDONLY|O_CLOEXEC|O_NOCTTY)) < 0) goto fallback; - r = loop_read(fd, &ull, sizeof(ull)); + r = loop_read(fd, &ull, sizeof(ull), true); close_nointr_nofail(fd); if (r != sizeof(ull)) @@ -2217,6 +2267,68 @@ void sigset_add_many(sigset_t *ss, ...) { va_end(ap); } +char* gethostname_malloc(void) { + struct utsname u; + + assert_se(uname(&u) >= 0); + + if (u.nodename[0]) + return strdup(u.nodename); + + return strdup(u.sysname); +} + +char* getlogname_malloc(void) { + uid_t uid; + long bufsize; + char *buf, *name; + struct passwd pwbuf, *pw = NULL; + struct stat st; + + if (isatty(STDIN_FILENO) && fstat(STDIN_FILENO, &st) >= 0) + uid = st.st_uid; + else + uid = getuid(); + + /* Shortcut things to avoid NSS lookups */ + if (uid == 0) + return strdup("root"); + + if ((bufsize = sysconf(_SC_GETPW_R_SIZE_MAX)) <= 0) + bufsize = 4096; + + if (!(buf = malloc(bufsize))) + return NULL; + + if (getpwuid_r(uid, &pwbuf, buf, bufsize, &pw) == 0 && pw) { + name = strdup(pw->pw_name); + free(buf); + return name; + } + + free(buf); + + if (asprintf(&name, "%lu", (unsigned long) uid) < 0) + return NULL; + + return name; +} + +char *getttyname_malloc(void) { + char path[PATH_MAX], *p; + + if (ttyname_r(STDIN_FILENO, path, sizeof(path)) < 0) + return strdup("unknown"); + + char_array_0(path); + + p = path; + if (startswith(path, "/dev/")) + p += 5; + + return strdup(p); +} + static const char *const ioprio_class_table[] = { [IOPRIO_CLASS_NONE] = "none", [IOPRIO_CLASS_RT] = "realtime",