]> asedeno.scripts.mit.edu Git - PuTTY.git/blobdiff - unix/uxcons.c
New program 'osxlaunch', to use as an OS X bundle launcher.
[PuTTY.git] / unix / uxcons.c
index eabb7769dddc0a3284018c0efe2a8fa4ed3edd73..abad00db0ef7a065460fd04a1496e9562874b422 100644 (file)
@@ -7,6 +7,7 @@
 #include <stdlib.h>
 #include <stdarg.h>
 #include <assert.h>
+#include <errno.h>
 
 #include <termios.h>
 #include <unistd.h>
@@ -74,6 +75,38 @@ void timer_change_notify(unsigned long next)
 {
 }
 
+/*
+ * Wrapper around Unix read(2), suitable for use on a file descriptor
+ * that's been set into nonblocking mode. Handles EAGAIN/EWOULDBLOCK
+ * by means of doing a one-fd select and then trying again; all other
+ * errors (including errors from select) are returned to the caller.
+ */
+static int block_and_read(int fd, void *buf, size_t len)
+{
+    int ret;
+
+    while ((ret = read(fd, buf, len)) < 0 && (
+#ifdef EAGAIN
+               (errno == EAGAIN) ||
+#endif
+#ifdef EWOULDBLOCK
+               (errno == EWOULDBLOCK) ||
+#endif
+               0)) {
+
+        fd_set rfds;
+        FD_ZERO(&rfds);
+        FD_SET(fd, &rfds);
+        ret = select(fd+1, &rfds, NULL, NULL, NULL);
+        assert(ret != 0);
+        if (ret < 0)
+            return ret;
+        assert(FD_ISSET(fd, &rfds));
+    }
+
+    return ret;
+}
+
 int verify_ssh_host_key(void *frontend, char *host, int port,
                         const char *keytype, char *keystr, char *fingerprint,
                         void (*callback)(void *ctx, int result), void *ctx)
@@ -163,7 +196,7 @@ int verify_ssh_host_key(void *frontend, char *host, int port,
        newmode.c_lflag |= ECHO | ISIG | ICANON;
        tcsetattr(0, TCSANOW, &newmode);
        line[0] = '\0';
-       if (read(0, line, sizeof(line) - 1) <= 0)
+       if (block_and_read(0, line, sizeof(line) - 1) <= 0)
            /* handled below */;
        tcsetattr(0, TCSANOW, &oldmode);
     }
@@ -216,7 +249,7 @@ int askalg(void *frontend, const char *algtype, const char *algname,
        newmode.c_lflag |= ECHO | ISIG | ICANON;
        tcsetattr(0, TCSANOW, &newmode);
        line[0] = '\0';
-       if (read(0, line, sizeof(line) - 1) <= 0)
+       if (block_and_read(0, line, sizeof(line) - 1) <= 0)
            /* handled below */;
        tcsetattr(0, TCSANOW, &oldmode);
     }
@@ -270,7 +303,7 @@ int askappend(void *frontend, Filename *filename,
        newmode.c_lflag |= ECHO | ISIG | ICANON;
        tcsetattr(0, TCSANOW, &newmode);
        line[0] = '\0';
-       if (read(0, line, sizeof(line) - 1) <= 0)
+       if (block_and_read(0, line, sizeof(line) - 1) <= 0)
            /* handled below */;
        tcsetattr(0, TCSANOW, &oldmode);
     }