[systemd-commits] 3 commits - src/tmpfiles.c src/tty-ask-password-agent.c src/util.c src/util.h src/utmp-wtmp.c

Lennart Poettering lennart at kemper.freedesktop.org
Thu Feb 17 07:31:14 PST 2011


 src/tmpfiles.c               |    2 
 src/tty-ask-password-agent.c |   31 +++++++--
 src/util.c                   |  135 ++++++++++++++++++++++++++++++++++++++++---
 src/util.h                   |    7 +-
 src/utmp-wtmp.c              |    2 
 5 files changed, 159 insertions(+), 18 deletions(-)

New commits:
commit f73f76acff4fd1d90bfbef486eedb25c4462809b
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Feb 17 16:29:47 2011 +0100

    util: retry opening a TTY on EIO
    
    https://bugs.freedesktop.org/show_bug.cgi?id=33996
    https://bugs.launchpad.net/ubuntu/+source/linux/+bug/554172/comments/245

diff --git a/src/util.c b/src/util.c
index 92268b6..b8e73ef 100644
--- a/src/util.c
+++ b/src/util.c
@@ -2134,8 +2134,32 @@ finish:
 
 int open_terminal(const char *name, int mode) {
         int fd, r;
+        unsigned c = 0;
 
-        if ((fd = open(name, mode)) < 0)
+        /*
+         * If a TTY is in the process of being closed opening it might
+         * cause EIO. This is horribly awful, but unlikely to be
+         * changed in the kernel. Hence we work around this problem by
+         * retrying a couple of times.
+         *
+         * https://bugs.launchpad.net/ubuntu/+source/linux/+bug/554172/comments/245
+         */
+
+        for (;;) {
+                if ((fd = open(name, mode)) >= 0)
+                        break;
+
+                if (errno != EIO)
+                        return -errno;
+
+                if (c >= 20)
+                        return -errno;
+
+                usleep(50 * USEC_PER_MSEC);
+                c++;
+        }
+
+        if (fd < 0)
                 return -errno;
 
         if ((r = isatty(fd)) < 0) {

commit fc116c6a19877275eabb085cf03f0df23b17c0e9
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Feb 17 16:29:04 2011 +0100

    util: beef up logic to find ctty name

diff --git a/src/tty-ask-password-agent.c b/src/tty-ask-password-agent.c
index 00496e7..655bfb9 100644
--- a/src/tty-ask-password-agent.c
+++ b/src/tty-ask-password-agent.c
@@ -353,13 +353,13 @@ finish:
 
 static int wall_tty_block(void) {
         char *p;
-        const char *t;
-        int fd;
+        int fd, r;
+        dev_t devnr;
 
-        if (!(t = ttyname(STDIN_FILENO)))
-                return -errno;
+        if ((r = get_ctty_devnr(&devnr)) < 0)
+                return -r;
 
-        if (asprintf(&p, "/dev/.systemd/ask-password-block/%s", file_name_from_path(t)) < 0)
+        if (asprintf(&p, "/dev/.systemd/ask-password-block/%u:%u", major(devnr), minor(devnr)) < 0)
                 return -ENOMEM;
 
         mkdir_parents(p, 0700);
@@ -375,8 +375,25 @@ static int wall_tty_block(void) {
 }
 
 static bool wall_tty_match(const char *path) {
-        int fd;
+        int fd, k;
         char *p;
+        struct stat st;
+
+        if (path_is_absolute(path))
+                k = lstat(path, &st);
+        else {
+                if (asprintf(&p, "/dev/%s", path) < 0)
+                        return true;
+
+                k = lstat(p, &st);
+                free(p);
+        }
+
+        if (k < 0)
+                return true;
+
+        if (!S_ISCHR(st.st_mode))
+                return true;
 
         /* We use named pipes to ensure that wall messages suggesting
          * password entry are not printed over password prompts
@@ -386,7 +403,7 @@ static bool wall_tty_match(const char *path) {
          * advantage that the block will automatically go away if the
          * process dies. */
 
-        if (asprintf(&p, "/dev/.systemd/ask-password-block/%s", file_name_from_path(path)) < 0)
+        if (asprintf(&p, "/dev/.systemd/ask-password-block/%u:%u", major(st.st_rdev), minor(st.st_rdev)) < 0)
                 return true;
 
         fd = open(p, O_WRONLY|O_CLOEXEC|O_NONBLOCK|O_NOCTTY);
diff --git a/src/util.c b/src/util.c
index 16e4ab2..92268b6 100644
--- a/src/util.c
+++ b/src/util.c
@@ -2749,28 +2749,121 @@ char* getlogname_malloc(void) {
         return name;
 }
 
-int getttyname_malloc(char **r) {
-        char path[PATH_MAX], *p, *c;
+int getttyname_malloc(int fd, char **r) {
+        char path[PATH_MAX], *c;
         int k;
 
         assert(r);
 
-        if ((k = ttyname_r(STDIN_FILENO, path, sizeof(path))) != 0)
+        if ((k = ttyname_r(fd, path, sizeof(path))) != 0)
                 return -k;
 
         char_array_0(path);
 
-        p = path;
-        if (startswith(path, "/dev/"))
-                p += 5;
-
-        if (!(c = strdup(p)))
+        if (!(c = strdup(startswith(path, "/dev/") ? path + 5 : path)))
                 return -ENOMEM;
 
         *r = c;
         return 0;
 }
 
+int getttyname_harder(int fd, char **r) {
+        int k;
+        char *s;
+
+        if ((k = getttyname_malloc(fd, &s)) < 0)
+                return k;
+
+        if (streq(s, "tty")) {
+                free(s);
+                return get_ctty(r);
+        }
+
+        *r = s;
+        return 0;
+}
+
+int get_ctty_devnr(dev_t *d) {
+        int k;
+        char line[256], *p;
+        unsigned long ttynr;
+        FILE *f;
+
+        if (!(f = fopen("/proc/self/stat", "r")))
+                return -errno;
+
+        if (!(fgets(line, sizeof(line), f))) {
+                k = -errno;
+                fclose(f);
+                return k;
+        }
+
+        fclose(f);
+
+        if (!(p = strrchr(line, ')')))
+                return -EIO;
+
+        p++;
+
+        if (sscanf(p, " "
+                   "%*c "  /* state */
+                   "%*d "  /* ppid */
+                   "%*d "  /* pgrp */
+                   "%*d "  /* session */
+                   "%lu ", /* ttynr */
+                   &ttynr) != 1)
+                return -EIO;
+
+        *d = (dev_t) ttynr;
+        return 0;
+}
+
+int get_ctty(char **r) {
+        int k;
+        char fn[128], *s, *b, *p;
+        dev_t devnr;
+
+        assert(r);
+
+        if ((k = get_ctty_devnr(&devnr)) < 0)
+                return k;
+
+        snprintf(fn, sizeof(fn), "/dev/char/%u:%u", major(devnr), minor(devnr));
+        char_array_0(fn);
+
+        if ((k = readlink_malloc(fn, &s)) < 0) {
+
+                if (k != -ENOENT)
+                        return k;
+
+                /* Probably something like the ptys which have no
+                 * symlink in /dev/char. Let's return something
+                 * vaguely useful. */
+
+                if (!(b = strdup(fn + 5)))
+                        return -ENOMEM;
+
+                *r = b;
+                return 0;
+        }
+
+        if (startswith(s, "/dev/"))
+                p = s + 5;
+        else if (startswith(s, "../"))
+                p = s + 3;
+        else
+                p = s;
+
+        b = strdup(p);
+        free(s);
+
+        if (!b)
+                return -ENOMEM;
+
+        *r = b;
+        return 0;
+}
+
 static int rm_rf_children(int fd, bool only_dirs) {
         DIR *d;
         int ret = 0;
diff --git a/src/util.h b/src/util.h
index 3898b89..80f1a38 100644
--- a/src/util.h
+++ b/src/util.h
@@ -331,7 +331,12 @@ void sigset_add_many(sigset_t *ss, ...);
 
 char* gethostname_malloc(void);
 char* getlogname_malloc(void);
-int getttyname_malloc(char **r);
+
+int getttyname_malloc(int fd, char **r);
+int getttyname_harder(int fd, char **r);
+
+int get_ctty_devnr(dev_t *d);
+int get_ctty(char **r);
 
 int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid);
 
diff --git a/src/utmp-wtmp.c b/src/utmp-wtmp.c
index 83da640..b03a3e7 100644
--- a/src/utmp-wtmp.c
+++ b/src/utmp-wtmp.c
@@ -370,7 +370,7 @@ int utmp_wall(const char *message, bool (*match_tty)(const char *tty)) {
                 goto finish;
         }
 
-        getttyname_malloc(&tty);
+        getttyname_harder(STDIN_FILENO, &tty);
 
         if (asprintf(&text,
                      "\a\r\n"

commit 4ff21d85822b521ed6741ef88cb4aaa384539dec
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Feb 17 13:13:34 2011 +0100

    tmpfiles: kill double slashes in unix socket names, just in case

diff --git a/src/tmpfiles.c b/src/tmpfiles.c
index 01668da..c5397ef 100644
--- a/src/tmpfiles.c
+++ b/src/tmpfiles.c
@@ -147,6 +147,8 @@ static void load_unix_sockets(void) {
                 if (!(s = strdup(p)))
                         goto fail;
 
+                path_kill_slashes(s);
+
                 if ((k = set_put(unix_sockets, s)) < 0) {
                         free(s);
 



More information about the systemd-commits mailing list