Enhance the user interface with better support for dialog box
authorRichard Levitte <levitte@openssl.org>
Tue, 19 Jun 2001 15:52:00 +0000 (15:52 +0000)
committerRichard Levitte <levitte@openssl.org>
Tue, 19 Jun 2001 15:52:00 +0000 (15:52 +0000)
prompting, application-defined prompts, the possibility to use
defaults (for example default passwords from somewhere else) and
interrupts/cancelations.

CHANGES
crypto/ui/ui.h
crypto/ui/ui_lib.c
crypto/ui/ui_locl.h
crypto/ui/ui_openssl.c

diff --git a/CHANGES b/CHANGES
index cf79a8e..ef113ed 100644 (file)
--- a/CHANGES
+++ b/CHANGES
          *) applies to 0.9.6a (/0.9.6b) and 0.9.7
          +) applies to 0.9.7 only
 
+  +) Enhance the general user interface with mechanisms to better support
+     dialog box interfaces, application-defined prompts, the possibility
+     to use defaults (for example default passwords from somewhere else)
+     and interrupts/cancelations.
+     [Richard Levitte]
+
   *) Don't change *pointer in CRYPTO_add_lock() is add_lock_callback is
      used: it isn't thread safe and the add_lock_callback should handle
      that itself.
index 452d9dc..5dda8ab 100644 (file)
@@ -80,9 +80,10 @@ typedef struct ui_st UI;
 typedef struct ui_method_st UI_METHOD;
 
 
-/* All the following functions return -1 or NULL on error.  When everything is
-   fine, they return 0, a positive value or a non-NULL pointer, all depending
-   on their purpose. */
+/* All the following functions return -1 or NULL on error and in some cases
+   (UI_process()) -2 if interrupted or in some other way cancelled.
+   When everything is fine, they return 0, a positive value or a non-NULL
+   pointer, all depending on their purpose. */
 
 /* Creators and destructor.   */
 UI *UI_new(void);
@@ -108,7 +109,7 @@ void UI_free(UI *ui);
    moment.
 
    All of the functions in this group take a UI and a string.  The input and
-   verify addition functions also take an echo flag, a buffer for the result
+   verify addition functions also take a flag argument, a buffer for the result
    to end up with, a minimum input size and a maximum input size (the result
    buffer MUST be large enough to be able to contain the maximum number of
    characters).  Additionally, the verify addition functions takes another
@@ -116,19 +117,62 @@ void UI_free(UI *ui);
 
    On success, the all return an index of the added information.  That index
    is usefull when retrieving results with UI_get0_result(). */
-int UI_add_input_string(UI *ui, const char *prompt, int echo_p,
+int UI_add_input_string(UI *ui, const char *prompt, int flags,
        char *result_buf, int minsize, int maxsize);
-int UI_dup_input_string(UI *ui, const char *prompt, int echo_p,
+int UI_dup_input_string(UI *ui, const char *prompt, int flags,
        char *result_buf, int minsize, int maxsize);
-int UI_add_verify_string(UI *ui, const char *prompt, int echo_p,
+int UI_add_verify_string(UI *ui, const char *prompt, int flags,
        char *result_buf, int minsize, int maxsize, const char *test_buf);
-int UI_dup_verify_string(UI *ui, const char *prompt, int echo_p,
+int UI_dup_verify_string(UI *ui, const char *prompt, int flags,
        char *result_buf, int minsize, int maxsize, const char *test_buf);
 int UI_add_info_string(UI *ui, const char *text);
 int UI_dup_info_string(UI *ui, const char *text);
 int UI_add_error_string(UI *ui, const char *text);
 int UI_dup_error_string(UI *ui, const char *text);
 
+/* These are the possible flags.  They can be or'ed together. */
+/* Use to have echoing of input */
+#define UI_INPUT_FLAG_ECHO     0x01
+/* Use a default answer.  Where that answer is found is completely up
+   to the application, it might for example be in the user data set
+   with UI_add_user_data().  It is not recommended to have more than
+   one input in each UI being marked with this flag, or the application
+   might get confused. */
+#define UI_INPUT_FLAG_DEFAULT  0x02
+
+/* The user of these routines may want to define flags of their own.  The core
+   UI won't look at those, but will pass them on to the method routines.  They
+   must use higher bits so they don't get confused with the UI bits above.
+   UI_INPUT_FLAG_USER_BASE tells which is the lowest bit to use.  A good
+   example of use is this:
+
+       #define MY_UI_FLAG1     (0x01 << UI_INPUT_FLAG_USER_BASE)
+
+*/
+#define UI_INPUT_FLAG_USER_BASE        16
+
+
+/* The following function helps construct a prompt.  object_desc is a
+   textual short description of the object, for example "pass phrase",
+   and object_name is the name of the object (might be a card name or
+   a file name.
+   The returned string shall always be allocated on the heap with
+   OPENSSL_malloc(), and need to be free'd with OPENSSL_free().
+
+   If the ui_method doesn't contain a pointer to a user-defined prompt
+   constructor, a default string is built, looking like this:
+
+       "Enter {object_desc} for {object_name}:"
+
+   So, if object_desc has the value "pass phrase" and object_name has
+   the value "foo.key", the resulting string is:
+
+       "Enter pass phrase for foo.key:"
+*/
+char *UI_construct_prompt(UI *ui_method,
+       const char *object_desc, const char *object_name);
+
+
 /* The following function is used to store a pointer to user-specific data.
    Any previous such pointer will be returned and replaced.
 
@@ -175,6 +219,9 @@ UI_METHOD *UI_OpenSSL(void);
        a writer        This function is called to write a given string,
                        maybe to the tty, maybe as a field label in a
                        window.
+       a flusher       This function is called to flush everything that
+                       has been output so far.  It can be used to actually
+                       display a dialog box after it has been built.
        a reader        This function is called to read a given prompt,
                        maybe from the tty, maybe from a field in a
                        window.  Note that it's called wth all string
@@ -183,13 +230,27 @@ UI_METHOD *UI_OpenSSL(void);
        a closer        This function closes the session, maybe by closing
                        the channel to the tty, or closing the window.
 
+   All these functions are expected to return:
+
+       0       on error.
+       1       on success.
+       -1      on out-of-band events, for example if some prompting has
+               been canceled (by pressing Ctrl-C, for example).  This is
+               only checked when returned by the flusher or the reader.
+
    The way this is used, the opener is first called, then the writer for all
-   strings, then the reader for all strings and finally the closer.  Note that
-   if you want to prompt from a terminal or other command line interface, the
-   best is to have the reader also write the prompts instead of having the
-   writer do it.
+   strings, then the flusher, then the reader for all strings and finally the
+   closer.  Note that if you want to prompt from a terminal or other command
+   line interface, the best is to have the reader also write the prompts
+   instead of having the writer do it.  If you want to prompt from a dialog
+   box, the writer can be used to build up the contents of the box, and the
+   flusher to actually display the box and run the event loop until all data
+   has been given, after which the reader only grabs the given data and puts
+   them back into the UI strings.
+
    All method functions take a UI as argument.  Additionally, the writer and
-   the reader take a UI_STRING. */
+   the reader take a UI_STRING.
+*/
 
 /* The UI_STRING type is the data structure that contains all the needed info
    about a string or a prompt, including test data for a verification prompt.
@@ -201,31 +262,33 @@ typedef struct ui_string_st UI_STRING;
    This is only needed by method authors. */
 enum UI_string_types
        {
-       UI_NONE=0,
-       UI_STRING_ECHO,         /* Prompt for a string */
-       UI_STRING_NOECHO,       /* Prompt for a hidden string */
-       UI_VERIFY_ECHO,         /* Prompt for a string and verify */
-       UI_VERIFY_NOECHO,       /* Prompt for a hidden string and verify */
-       UI_INFO,                /* Send info to the user */
-       UI_ERROR                /* Send an error message to the user */
+       UIT_NONE=0,
+       UIT_PROMPT,             /* Prompt for a string */
+       UIT_VERIFY,             /* Prompt for a string and verify */
+       UIT_INFO,               /* Send info to the user */
+       UIT_ERROR               /* Send an error message to the user */
        };
 
 /* Create and manipulate methods */
-UI_METHOD *UI_create_method(void);
+UI_METHOD *UI_create_method(char *name);
 int UI_method_set_opener(UI_METHOD *method, int (*opener)(UI *ui));
 int UI_method_set_writer(UI_METHOD *method, int (*writer)(UI *ui, UI_STRING *uis));
+int UI_method_set_flusher(UI_METHOD *method, int (*flusher)(UI *ui));
 int UI_method_set_reader(UI_METHOD *method, int (*reader)(UI *ui, UI_STRING *uis));
 int UI_method_set_closer(UI_METHOD *method, int (*closer)(UI *ui));
 int (*UI_method_get_opener(UI_METHOD *method))(UI*);
 int (*UI_method_get_writer(UI_METHOD *method))(UI*,UI_STRING*);
+int (*UI_method_get_flusher(UI_METHOD *method))(UI*);
 int (*UI_method_get_reader(UI_METHOD *method))(UI*,UI_STRING*);
 int (*UI_method_get_closer(UI_METHOD *method))(UI*);
 
 /* The following functions are helpers for method writers to access relevant
    data from a UI_STRING. */
 
-/* Return type type of the UI_STRING */
+/* Return type of the UI_STRING */
 enum UI_string_types UI_get_string_type(UI_STRING *uis);
+/* Return input flags of the UI_STRING */
+int UI_get_input_flags(UI_STRING *uis);
 /* Return the actual string to output (the prompt, info or error) */
 const char *UI_get0_output_string(UI_STRING *uis);
 /* Return the result of a prompt */
@@ -237,7 +300,7 @@ int UI_get_result_minsize(UI_STRING *uis);
 /* Return the required maximum size of the result */
 int UI_get_result_maxsize(UI_STRING *uis);
 /* Set the result of a UI_STRING. */
-int UI_set_result(UI_STRING *uis, char *result);
+int UI_set_result(UI_STRING *uis, const char *result);
 
 
 /* BEGIN ERROR CODES */
index 5b6cacf..ffbcb75 100644 (file)
@@ -131,7 +131,7 @@ static int allocate_string_stack(UI *ui)
        }
 
 static int general_allocate_string(UI *ui, const char *prompt,
-       int prompt_freeable, enum UI_string_types type,
+       int prompt_freeable, enum UI_string_types type, int input_flags,
        char *result_buf, int minsize, int maxsize, const char *test_buf)
        {
        int ret=-1;
@@ -145,6 +145,7 @@ static int general_allocate_string(UI *ui, const char *prompt,
                UI_STRING *s=(UI_STRING *)OPENSSL_malloc(sizeof(UI_STRING));
                s->out_string=prompt;
                s->flags=prompt_freeable ? OUT_STRING_FREEABLE : 0;
+               s->input_flags=input_flags;
                s->type=type;
                s->result_buf=result_buf;
                s->result_minsize=minsize;
@@ -157,16 +158,15 @@ static int general_allocate_string(UI *ui, const char *prompt,
 
 /* Returns the index to the place in the stack or 0 for error.  Uses a
    direct reference to the prompt.  */
-int UI_add_input_string(UI *ui, const char *prompt, int echo_p,
+int UI_add_input_string(UI *ui, const char *prompt, int flags,
        char *result_buf, int minsize, int maxsize)
        {
        return general_allocate_string(ui, prompt, 0,
-               echo_p?UI_STRING_ECHO:UI_STRING_NOECHO,
-               result_buf, minsize, maxsize, NULL);
+               UIT_PROMPT, flags, result_buf, minsize, maxsize, NULL);
        }
 
 /* Same as UI_add_input_string(), excepts it takes a copy of the prompt */
-int UI_dup_input_string(UI *ui, const char *prompt, int echo_p,
+int UI_dup_input_string(UI *ui, const char *prompt, int flags,
        char *result_buf, int minsize, int maxsize)
        {
        char *prompt_copy=NULL;
@@ -182,19 +182,17 @@ int UI_dup_input_string(UI *ui, const char *prompt, int echo_p,
                }
        
        return general_allocate_string(ui, prompt, 1,
-               echo_p?UI_STRING_ECHO:UI_STRING_NOECHO,
-               result_buf, minsize, maxsize, NULL);
+               UIT_PROMPT, flags, result_buf, minsize, maxsize, NULL);
        }
 
-int UI_add_verify_string(UI *ui, const char *prompt, int echo_p,
+int UI_add_verify_string(UI *ui, const char *prompt, int flags,
        char *result_buf, int minsize, int maxsize, const char *test_buf)
        {
        return general_allocate_string(ui, prompt, 0,
-               echo_p?UI_VERIFY_ECHO:UI_VERIFY_NOECHO,
-               result_buf, minsize, maxsize, test_buf);
+               UIT_VERIFY, flags, result_buf, minsize, maxsize, test_buf);
        }
 
-int UI_dup_verify_string(UI *ui, const char *prompt, int echo_p,
+int UI_dup_verify_string(UI *ui, const char *prompt, int flags,
        char *result_buf, int minsize, int maxsize, const char *test_buf)
        {
        char *prompt_copy=NULL;
@@ -210,13 +208,13 @@ int UI_dup_verify_string(UI *ui, const char *prompt, int echo_p,
                }
        
        return general_allocate_string(ui, prompt, 1,
-               echo_p?UI_VERIFY_ECHO:UI_VERIFY_NOECHO,
-               result_buf, minsize, maxsize, test_buf);
+               UIT_VERIFY, flags, result_buf, minsize, maxsize, test_buf);
        }
 
 int UI_add_info_string(UI *ui, const char *text)
        {
-       return general_allocate_string(ui, text, 0, UI_INFO, NULL, 0, 0, NULL);
+       return general_allocate_string(ui, text, 0, UIT_INFO, 0, NULL, 0, 0,
+               NULL);
        }
 
 int UI_dup_info_string(UI *ui, const char *text)
@@ -233,12 +231,13 @@ int UI_dup_info_string(UI *ui, const char *text)
                        }
                }
 
-       return general_allocate_string(ui, text, 1, UI_INFO, NULL, 0, 0, NULL);
+       return general_allocate_string(ui, text, 1, UIT_INFO, 0, NULL, 0, 0,
+               NULL);
        }
 
 int UI_add_error_string(UI *ui, const char *text)
        {
-       return general_allocate_string(ui, text, 0, UI_ERROR, NULL, 0, 0,
+       return general_allocate_string(ui, text, 0, UIT_ERROR, 0, NULL, 0, 0,
                NULL);
        }
 
@@ -255,8 +254,43 @@ int UI_dup_error_string(UI *ui, const char *text)
                        return -1;
                        }
                }
-       return general_allocate_string(ui, text_copy, 1, UI_ERROR, NULL, 0, 0,
-               NULL);
+       return general_allocate_string(ui, text_copy, 1, UIT_ERROR, 0, NULL,
+               0, 0, NULL);
+       }
+
+char *UI_construct_prompt(UI *ui, const char *object_desc,
+       const char *object_name)
+       {
+       char *prompt = NULL;
+
+       if (ui->meth->ui_construct_prompt)
+               prompt = ui->meth->ui_construct_prompt(ui,
+                       object_desc, object_name);
+       else
+               {
+               char prompt1[] = "Enter ";
+               char prompt2[] = " for ";
+               char prompt3[] = ":";
+               int len = 0;
+
+               if (object_desc == NULL)
+                       return NULL;
+               len = sizeof(prompt1) - 1 + strlen(object_desc);
+               if (object_name)
+                       len += sizeof(prompt2) - 1 + strlen(object_name);
+               len += sizeof(prompt3) - 1;
+
+               prompt = (char *)OPENSSL_malloc(len + 1);
+               strcpy(prompt, prompt1);
+               strcat(prompt, object_desc);
+               if (object_name)
+                       {
+                       strcat(prompt, prompt2);
+                       strcat(prompt, object_name);
+                       }
+               strcat(prompt, prompt3);
+               }
+       return prompt;
        }
 
 void *UI_add_user_data(UI *ui, void *user_data)
@@ -304,14 +338,37 @@ int UI_process(UI *ui)
                        }
                }
 
+       if (ui->meth->ui_flush)
+               switch(ui->meth->ui_flush(ui))
+                       {
+               case -1: /* Interrupt/Cancel/something... */
+                       ok = -2;
+                       goto err;
+               case 0: /* Errors */
+                       ok = -1;
+                       goto err;
+               default: /* Success */
+                       ok = 0;
+                       break;
+                       }
+
        for(i=0; i<sk_UI_STRING_num(ui->strings); i++)
                {
-               if (ui->meth->ui_read_string
-                       && !ui->meth->ui_read_string(ui,
-                               sk_UI_STRING_value(ui->strings, i)))
+               if (ui->meth->ui_read_string)
                        {
-                       ok=-1;
-                       goto err;
+                       switch(ui->meth->ui_read_string(ui,
+                               sk_UI_STRING_value(ui->strings, i)))
+                               {
+                       case -1: /* Interrupt/Cancel/something... */
+                               ok = -2;
+                               goto err;
+                       case 0: /* Errors */
+                               ok = -1;
+                               goto err;
+                       default: /* Success */
+                               ok = 0;
+                               break;
+                               }
                        }
                }
  err:
@@ -364,9 +421,14 @@ const UI_METHOD *UI_set_method(UI *ui, const UI_METHOD *meth)
        }
 
 
-UI_METHOD *UI_create_method(void)
+UI_METHOD *UI_create_method(char *name)
        {
-       return (UI_METHOD *)OPENSSL_malloc(sizeof(UI_METHOD));
+       UI_METHOD *ui_method = (UI_METHOD *)OPENSSL_malloc(sizeof(UI_METHOD));
+
+       if (ui_method)
+               memset(ui_method, 0, sizeof(*ui_method));
+       ui_method->name = strdup(name);
+       return ui_method;
        }
 
 int UI_method_set_opener(UI_METHOD *method, int (*opener)(UI *ui))
@@ -391,6 +453,17 @@ int UI_method_set_writer(UI_METHOD *method, int (*writer)(UI *ui, UI_STRING *uis
                return -1;
        }
 
+int UI_method_set_flusher(UI_METHOD *method, int (*flusher)(UI *ui))
+       {
+       if (method)
+               {
+               method->ui_flush = flusher;
+               return 0;
+               }
+       else
+               return -1;
+       }
+
 int UI_method_set_reader(UI_METHOD *method, int (*reader)(UI *ui, UI_STRING *uis))
        {
        if (method)
@@ -448,10 +521,17 @@ int (*UI_method_get_closer(UI_METHOD *method))(UI*)
 enum UI_string_types UI_get_string_type(UI_STRING *uis)
        {
        if (!uis)
-               return UI_NONE;
+               return UIT_NONE;
        return uis->type;
        }
 
+int UI_get_input_flags(UI_STRING *uis)
+       {
+       if (!uis)
+               return 0;
+       return uis->input_flags;
+       }
+
 const char *UI_get0_output_string(UI_STRING *uis)
        {
        if (!uis)
@@ -465,10 +545,8 @@ const char *UI_get0_result_string(UI_STRING *uis)
                return NULL;
        switch(uis->type)
                {
-       case UI_STRING_ECHO:
-       case UI_STRING_NOECHO:
-       case UI_VERIFY_ECHO:
-       case UI_VERIFY_NOECHO:
+       case UIT_PROMPT:
+       case UIT_VERIFY:
                return uis->result_buf;
        default:
                return NULL;
@@ -496,7 +574,7 @@ int UI_get_result_maxsize(UI_STRING *uis)
        return uis->result_maxsize;
        }
 
-int UI_set_result(UI_STRING *uis, char *result)
+int UI_set_result(UI_STRING *uis, const char *result)
        {
        int l = strlen(result);
 
index 4adf0d8..8f48f8e 100644 (file)
@@ -65,22 +65,40 @@ struct ui_method_st
        {
        const char *name;
 
-       /* All the functions return 1 for success and 0 for failure */
-       int (*ui_open_session)(UI *ui); /* Open whatever channel for this,
-                                          be it the console, an X window
-                                          or whatever.
-                                          This function should use the
-                                          ex_data structure to save
-                                          intermediate data. */
-       int (*ui_read_string)(UI *ui, UI_STRING *uis);
+       /* All the functions return 1 or non-NULL for success and 0 or NULL
+          for failure */
+
+       /* Open whatever channel for this, be it the console, an X window
+          or whatever.
+          This function should use the ex_data structure to save
+          intermediate data. */
+       int (*ui_open_session)(UI *ui);
+
        int (*ui_write_string)(UI *ui, UI_STRING *uis);
+
+       /* Flush the output.  If a GUI dialog box is used, this function can
+          be used to actually display it. */
+       int (*ui_flush)(UI *ui);
+
+       int (*ui_read_string)(UI *ui, UI_STRING *uis);
+
        int (*ui_close_session)(UI *ui);
+
+       /* Construct a prompt in a user-defined manner.  object_desc is a
+          textual short description of the object, for example "pass phrase",
+          and object_name is the name of the object (might be a card name or
+          a file name.
+          The returned string shall always be allocated on the heap with
+          OPENSSL_malloc(), and need to be free'd with OPENSSL_free(). */
+       char *(*ui_construct_prompt)(UI *ui, const char *object_desc,
+               const char *object_name);
        };
 
 struct ui_string_st
        {
        const char *out_string; /* Input */
        enum UI_string_types type; /* Input */
+       int input_flags;        /* Flags from the user */
 
        /* The following parameters are completely irrelevant for UI_INFO,
           and can therefore be set to 0 ro NULL */
@@ -95,7 +113,7 @@ struct ui_string_st
        const char *test_buf;   /* Input: test string to verify against */
 
 #define OUT_STRING_FREEABLE 0x01
-       int flags;
+       int flags;              /* flags for internal use */
        };
 
 struct ui_st
index bb66291..7c988aa 100644 (file)
@@ -283,6 +283,7 @@ static int noecho_fgets(char *buf, int size, FILE *tty);
 static int read_string_inner(UI *ui, UI_STRING *uis, int echo);
 
 static int read_string(UI *ui, UI_STRING *uis);
+static int write_string(UI *ui, UI_STRING *uis);
 
 static int open_console(UI *ui);
 static int echo_console(UI *ui);
@@ -293,9 +294,11 @@ static UI_METHOD ui_openssl =
        {
        "OpenSSL default user interface",
        open_console,
+       write_string,
+       NULL,                   /* No flusher is needed for command lines */
        read_string,
-       NULL,                   /* The reader function writes as well */
        close_console,
+       NULL
        };
 
 /* The method with all the built-in thingies */
@@ -304,30 +307,41 @@ UI_METHOD *UI_OpenSSL(void)
        return &ui_openssl;
        }
 
-static int read_string(UI *ui, UI_STRING *uis)
+/* The following function makes sure that info and error strings are printed
+   before any prompt. */
+static int write_string(UI *ui, UI_STRING *uis)
        {
        switch (UI_get_string_type(uis))
                {
-       case UI_VERIFY_NOECHO:
-               fprintf(tty_out,"Verifying - %s",
-                       UI_get0_output_string(uis));
+       case UIT_VERIFY:
+       case UIT_PROMPT:
+               break;
+       default:
+               fputs(UI_get0_output_string(uis), tty_out);
                fflush(tty_out);
-               if (read_string_inner(ui, uis, 0) == 0)
-                       return 0;
-               if (strcmp(UI_get0_result_string(uis),
-                       UI_get0_test_string(uis)) != 0)
-                       {
-                       fprintf(tty_out,"Verify failure\n");
-                       fflush(tty_out);
-                       return 0;
-                       }
                break;
-       case UI_VERIFY_ECHO:
+               }
+       return 1;
+       }
+
+static int read_string(UI *ui, UI_STRING *uis)
+       {
+       int ok = 0;
+
+       switch (UI_get_string_type(uis))
+               {
+       case UIT_PROMPT:
+               fputs(UI_get0_output_string(uis), tty_out);
+               fflush(tty_out);
+               return read_string_inner(ui, uis,
+                       UI_get_input_flags(uis) & UI_INPUT_FLAG_ECHO);
+       case UIT_VERIFY:
                fprintf(tty_out,"Verifying - %s",
                        UI_get0_output_string(uis));
                fflush(tty_out);
-               if (read_string_inner(ui, uis, 1) == 0)
-                       return 0;
+               if ((ok = read_string_inner(ui, uis,
+                       UI_get_input_flags(uis) & UI_INPUT_FLAG_ECHO)) <= 0)
+                       return ok;
                if (strcmp(UI_get0_result_string(uis),
                        UI_get0_test_string(uis)) != 0)
                        {
@@ -336,17 +350,7 @@ static int read_string(UI *ui, UI_STRING *uis)
                        return 0;
                        }
                break;
-       case UI_STRING_NOECHO:
-               fputs(UI_get0_output_string(uis), tty_out);
-               fflush(tty_out);
-               return read_string_inner(ui, uis, 0);
-       case UI_STRING_ECHO:
-               fputs(UI_get0_output_string(uis), tty_out);
-               fflush(tty_out);
-               return read_string_inner(ui, uis, 1);
        default:
-               fputs(UI_get0_output_string(uis), tty_out);
-               fflush(tty_out);
                break;
                }
        return 1;
@@ -372,9 +376,9 @@ static int read_string_inner(UI *ui, UI_STRING *uis, int echo)
        int maxsize = BUFSIZ-1;
 
 #ifndef OPENSSL_SYS_WIN16
-       if (setjmp(save))
+       if ((ok = setjmp(save)))
                {
-               ok=0;
+               if (ok == 1) ok=0;
                goto error;
                }
        ok=0;
@@ -594,10 +598,15 @@ static void popsig(void)
 
 static void recsig(int i)
        {
+       switch(i)
+               {
+       case SIGINT:
+               longjmp(save,-1);
+               break;
+       default:
+               break;
+               }
        longjmp(save,1);
-#ifdef LINT
-       i=i;
-#endif
        }