]> asedeno.scripts.mit.edu Git - PuTTY.git/blobdiff - unix/uxcons.c
Compile fix for GTK 3.18: avoid gtk_adjustment_changed().
[PuTTY.git] / unix / uxcons.c
index ce1a49238b4547f131337e658d5238672f866627..b9fd67fe927423c7587be969ff545247218ff1fd 100644 (file)
@@ -7,6 +7,7 @@
 #include <stdlib.h>
 #include <stdarg.h>
 #include <assert.h>
+#include <errno.h>
 
 #include <termios.h>
 #include <unistd.h>
@@ -70,12 +71,44 @@ void notify_remote_exit(void *frontend)
 {
 }
 
-void timer_change_notify(long next)
+void timer_change_notify(unsigned long next)
 {
 }
 
-int verify_ssh_host_key(void *frontend, char *host, int port, char *keytype,
-                        char *keystr, char *fingerprint,
+/*
+ * 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)
 {
     int ret;
@@ -163,7 +196,7 @@ int verify_ssh_host_key(void *frontend, char *host, int port, char *keytype,
        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,60 @@ 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);
+    }
+
+    if (line[0] == 'y' || line[0] == 'Y') {
+       postmsg(&cf);
+       return 1;
+    } else {
+       fprintf(stderr, abandoned);
+       postmsg(&cf);
+       return 0;
+    }
+}
+
+int askhk(void *frontend, const char *algname, const char *betteralgs,
+          void (*callback)(void *ctx, int result), void *ctx)
+{
+    static const char msg[] =
+       "The first host key type we have stored for this server\n"
+       "is %s, which is below the configured warning threshold.\n"
+       "The server also provides the following types of host key\n"
+        "above the threshold, which we do not have stored:\n"
+        "%s\n"
+       "Continue with connection? (y/n) ";
+    static const char msg_batch[] =
+       "The first host key type we have stored for this server\n"
+       "is %s, which is below the configured warning threshold.\n"
+       "The server also provides the following types of host key\n"
+        "above the threshold, which we do not have stored:\n"
+        "%s\n"
+       "Connection abandoned.\n";
+    static const char abandoned[] = "Connection abandoned.\n";
+
+    char line[32];
+    struct termios cf;
+
+    premsg(&cf);
+    if (console_batch_mode) {
+       fprintf(stderr, msg_batch, algname, betteralgs);
+       return 0;
+    }
+
+    fprintf(stderr, msg, algname, betteralgs);
+    fflush(stderr);
+
+    {
+       struct termios oldmode, newmode;
+       tcgetattr(0, &oldmode);
+       newmode = oldmode;
+       newmode.c_lflag |= ECHO | ISIG | ICANON;
+       tcsetattr(0, TCSANOW, &newmode);
+       line[0] = '\0';
+       if (block_and_read(0, line, sizeof(line) - 1) <= 0)
            /* handled below */;
        tcsetattr(0, TCSANOW, &oldmode);
     }
@@ -270,7 +356,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);
     }
@@ -321,10 +407,12 @@ void console_provide_logctx(void *logctx)
 void logevent(void *frontend, const char *string)
 {
     struct termios cf;
-    premsg(&cf);
+    if ((flags & FLAG_STDERR) && (flags & FLAG_VERBOSE))
+        premsg(&cf);
     if (console_logctx)
        log_eventlog(console_logctx, string);
-    postmsg(&cf);
+    if ((flags & FLAG_STDERR) && (flags & FLAG_VERBOSE))
+        postmsg(&cf);
 }
 
 /*
@@ -362,7 +450,8 @@ static void console_prompt_text(FILE *outfp, const char *data, int len)
     fflush(outfp);
 }
 
-int console_get_userpass_input(prompts_t *p, unsigned char *in, int inlen)
+int console_get_userpass_input(prompts_t *p, const unsigned char *in,
+                               int inlen)
 {
     size_t curr_prompt;
     FILE *outfp = NULL;