While I'm crusading against arbitrary limits, here's a redesign of
[u/mdw/putty] / windows / wincons.c
index e0f0215..9824a5a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * console.c: various interactive-prompt routines shared between
+ * wincons.c - various interactive-prompt routines shared between
  * the Windows console PuTTY tools
  */
 
@@ -201,7 +201,7 @@ int askalg(void *frontend, const char *algtype, const char *algname,
  * Ask whether to wipe a session log file before writing to it.
  * Returns 2 for wipe, 1 for append, 0 for cancel (don't log).
  */
-int askappend(void *frontend, Filename filename,
+int askappend(void *frontend, Filename *filename,
              void (*callback)(void *ctx, int result), void *ctx)
 {
     HANDLE hin;
@@ -223,11 +223,11 @@ int askappend(void *frontend, Filename filename,
     char line[32];
 
     if (console_batch_mode) {
-       fprintf(stderr, msgtemplate_batch, FILENAME_MAX, filename.path);
+       fprintf(stderr, msgtemplate_batch, FILENAME_MAX, filename->path);
        fflush(stderr);
        return 0;
     }
-    fprintf(stderr, msgtemplate, FILENAME_MAX, filename.path);
+    fprintf(stderr, msgtemplate, FILENAME_MAX, filename->path);
     fflush(stderr);
 
     hin = GetStdHandle(STD_INPUT_HANDLE);
@@ -294,8 +294,7 @@ void console_provide_logctx(void *logctx)
 
 void logevent(void *frontend, const char *string)
 {
-    if (console_logctx)
-       log_eventlog(console_logctx, string);
+    log_eventlog(console_logctx, string);
 }
 
 static void console_data_untrusted(HANDLE hout, const char *data, int len)
@@ -315,18 +314,35 @@ int console_get_userpass_input(prompts_t *p, unsigned char *in, int inlen)
      */
     {
        int i;
-       for (i = 0; i < p->n_prompts; i++)
-           memset(p->prompts[i]->result, 0, p->prompts[i]->result_len);
+       for (i = 0; i < (int)p->n_prompts; i++)
+            prompt_set_result(p->prompts[i], "");
     }
 
-    if (console_batch_mode)
-       return 0;
+    /*
+     * The prompts_t might contain a message to be displayed but no
+     * actual prompt. More usually, though, it will contain
+     * questions that the user needs to answer, in which case we
+     * need to ensure that we're able to get the answers.
+     */
+    if (p->n_prompts) {
+       if (console_batch_mode)
+           return 0;
+       hin = GetStdHandle(STD_INPUT_HANDLE);
+       if (hin == INVALID_HANDLE_VALUE) {
+           fprintf(stderr, "Cannot get standard input handle\n");
+           cleanup_exit(1);
+       }
+    }
 
-    hin = GetStdHandle(STD_INPUT_HANDLE);
-    hout = GetStdHandle(STD_OUTPUT_HANDLE);
-    if (hin == INVALID_HANDLE_VALUE || hout == INVALID_HANDLE_VALUE) {
-       fprintf(stderr, "Cannot get standard input/output handles\n");
-       cleanup_exit(1);
+    /*
+     * And if we have anything to print, we need standard output.
+     */
+    if ((p->name_reqd && p->name) || p->instruction || p->n_prompts) {
+       hout = GetStdHandle(STD_OUTPUT_HANDLE);
+       if (hout == INVALID_HANDLE_VALUE) {
+           fprintf(stderr, "Cannot get standard output handle\n");
+           cleanup_exit(1);
+       }
     }
 
     /*
@@ -349,9 +365,9 @@ int console_get_userpass_input(prompts_t *p, unsigned char *in, int inlen)
 
     for (curr_prompt = 0; curr_prompt < p->n_prompts; curr_prompt++) {
 
-       DWORD savemode, newmode, i = 0;
+       DWORD savemode, newmode;
+        int len;
        prompt_t *pr = p->prompts[curr_prompt];
-       BOOL r;
 
        GetConsoleMode(hin, &savemode);
        newmode = savemode | ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT;
@@ -363,25 +379,44 @@ int console_get_userpass_input(prompts_t *p, unsigned char *in, int inlen)
 
        console_data_untrusted(hout, pr->prompt, strlen(pr->prompt));
 
-       r = ReadFile(hin, pr->result, pr->result_len - 1, &i, NULL);
+        len = 0;
+        while (1) {
+            DWORD ret = 0;
+            BOOL r;
+
+            prompt_ensure_result_size(pr, len * 5 / 4 + 512);
+
+            r = ReadFile(hin, pr->result + len, pr->resultsize - len - 1,
+                         &ret, NULL);
+
+            if (!r || ret == 0) {
+                len = -1;
+                break;
+            }
+            len += ret;
+            if (pr->result[len - 1] == '\n') {
+                len--;
+                if (pr->result[len - 1] == '\r')
+                    len--;
+                break;
+            }
+        }
 
        SetConsoleMode(hin, savemode);
 
-       if ((int) i > pr->result_len)
-           i = pr->result_len - 1;
-       else
-           i = i - 2;
-       pr->result[i] = '\0';
-
        if (!pr->echo) {
            DWORD dummy;
            WriteFile(hout, "\r\n", 2, &dummy, NULL);
        }
 
+        if (len < 0) {
+            return 0;                  /* failure due to read error */
+        }
+
+       pr->result[len] = '\0';
     }
 
     return 1; /* success */
-
 }
 
 void frontend_keypress(void *handle)