Enhance the user interface with better support for dialog box
prompting, application-defined prompts, the possibility to use
defaults (for example default passwords from somewhere else) and
interrupts/cancelations.
diff --git a/CHANGES b/CHANGES
index cf79a8e..ef113ed 100644
--- a/CHANGES
+++ b/CHANGES
@@ -11,6 +11,12 @@
          *) 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.
diff --git a/crypto/ui/ui.h b/crypto/ui/ui.h
index 452d9dc..5dda8ab 100644
--- a/crypto/ui/ui.h
+++ b/crypto/ui/ui.h
@@ -80,9 +80,10 @@
 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 @@
    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 @@
 
    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 @@
 	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 @@
 	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 @@
    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 @@
 /* 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 */
diff --git a/crypto/ui/ui_lib.c b/crypto/ui/ui_lib.c
index 5b6cacf..ffbcb75 100644
--- a/crypto/ui/ui_lib.c
+++ b/crypto/ui/ui_lib.c
@@ -131,7 +131,7 @@
 	}
 
 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 @@
 		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 @@
 
 /* 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 @@
 		}
 	
 	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 @@
 		}
 	
 	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 @@
 			}
 		}
 
-	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 @@
 			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 @@
 			}
 		}
 
+	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 @@
 	}
 
 
-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 @@
 		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 @@
 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 @@
 		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 @@
 	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);
 
diff --git a/crypto/ui/ui_locl.h b/crypto/ui/ui_locl.h
index 4adf0d8..8f48f8e 100644
--- a/crypto/ui/ui_locl.h
+++ b/crypto/ui/ui_locl.h
@@ -65,22 +65,40 @@
 	{
 	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 @@
 	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
diff --git a/crypto/ui/ui_openssl.c b/crypto/ui/ui_openssl.c
index bb66291..7c988aa 100644
--- a/crypto/ui/ui_openssl.c
+++ b/crypto/ui/ui_openssl.c
@@ -283,6 +283,7 @@
 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 @@
 	{
 	"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,46 +307,15 @@
 	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));
-		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;
-			}
+	case UIT_VERIFY:
+	case UIT_PROMPT:
 		break;
-	case UI_VERIFY_ECHO:
-		fprintf(tty_out,"Verifying - %s",
-			UI_get0_output_string(uis));
-		fflush(tty_out);
-		if (read_string_inner(ui, uis, 1) == 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_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);
@@ -352,6 +324,38 @@
 	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 ((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)
+			{
+			fprintf(tty_out,"Verify failure\n");
+			fflush(tty_out);
+			return 0;
+			}
+		break;
+	default:
+		break;
+		}
+	return 1;
+	}
+
 
 /* Internal functions to read a string without echoing */
 static void read_till_nl(FILE *in)
@@ -372,9 +376,9 @@
 	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 recsig(int i)
 	{
+	switch(i)
+		{
+	case SIGINT:
+		longjmp(save,-1);
+		break;
+	default:
+		break;
+		}
 	longjmp(save,1);
-#ifdef LINT
-	i=i;
-#endif
 	}