Implement boolean (yes/no or OK/Cancel, ...) input.
[openssl.git] / crypto / ui / ui_lib.c
1 /* crypto/ui/ui_lib.c -*- mode:C; c-file-style: "eay" -*- */
2 /* Written by Richard Levitte (levitte@stacken.kth.se) for the OpenSSL
3  * project 2000.
4  */
5 /* ====================================================================
6  * Copyright (c) 1998-2000 The OpenSSL Project.  All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer. 
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in
17  *    the documentation and/or other materials provided with the
18  *    distribution.
19  *
20  * 3. All advertising materials mentioning features or use of this
21  *    software must display the following acknowledgment:
22  *    "This product includes software developed by the OpenSSL Project
23  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
24  *
25  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26  *    endorse or promote products derived from this software without
27  *    prior written permission. For written permission, please contact
28  *    openssl-core@openssl.org.
29  *
30  * 5. Products derived from this software may not be called "OpenSSL"
31  *    nor may "OpenSSL" appear in their names without prior written
32  *    permission of the OpenSSL Project.
33  *
34  * 6. Redistributions of any form whatsoever must retain the following
35  *    acknowledgment:
36  *    "This product includes software developed by the OpenSSL Project
37  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
38  *
39  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
43  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50  * OF THE POSSIBILITY OF SUCH DAMAGE.
51  * ====================================================================
52  *
53  * This product includes cryptographic software written by Eric Young
54  * (eay@cryptsoft.com).  This product includes software written by Tim
55  * Hudson (tjh@cryptsoft.com).
56  *
57  */
58
59 #include <string.h>
60 #include <openssl/e_os2.h>
61 #include <openssl/buffer.h>
62 #include <openssl/ui.h>
63 #include <openssl/err.h>
64 #include "ui_locl.h"
65
66 IMPLEMENT_STACK_OF(UI_STRING_ST)
67
68 static const UI_METHOD *default_UI_meth=NULL;
69 static int ui_meth_num=0;
70 static STACK_OF(CRYPTO_EX_DATA_FUNCS) *ui_meth=NULL;
71
72 UI *UI_new(void)
73         {
74         return(UI_new_method(NULL));
75         }
76
77 UI *UI_new_method(const UI_METHOD *method)
78         {
79         UI *ret;
80
81         ret=(UI *)OPENSSL_malloc(sizeof(UI));
82         if (ret == NULL)
83                 {
84                 UIerr(UI_F_UI_NEW_METHOD,ERR_R_MALLOC_FAILURE);
85                 return NULL;
86                 }
87         if (method == NULL)
88                 ret->meth=UI_get_default_method();
89         else
90                 ret->meth=method;
91
92         ret->strings=NULL;
93         ret->user_data=NULL;
94         CRYPTO_new_ex_data(ui_meth,ret,&ret->ex_data);
95         return ret;
96         }
97
98 static void free_string(UI_STRING *uis)
99         {
100         if (uis->flags & OUT_STRING_FREEABLE)
101                 {
102                 OPENSSL_free((char *)uis->out_string);
103                 switch(uis->type)
104                         {
105                 case UIT_BOOLEAN:
106                         OPENSSL_free((char *)uis->_.boolean_data.action_desc);
107                         OPENSSL_free((char *)uis->_.boolean_data.ok_chars);
108                         OPENSSL_free((char *)uis->_.boolean_data.cancel_chars);
109                         break;
110                 default:
111                         break;
112                         }
113                 }
114         OPENSSL_free(uis);
115         }
116
117 void UI_free(UI *ui)
118         {
119         if (ui == NULL)
120                 return;
121         sk_UI_STRING_pop_free(ui->strings,free_string);
122         OPENSSL_free(ui);
123         }
124
125 static int allocate_string_stack(UI *ui)
126         {
127         if (ui->strings == NULL)
128                 {
129                 ui->strings=sk_UI_STRING_new_null();
130                 if (ui->strings == NULL)
131                         {
132                         return -1;
133                         }
134                 }
135         return 0;
136         }
137
138 static UI_STRING *general_allocate_prompt(UI *ui, const char *prompt,
139         int prompt_freeable, enum UI_string_types type, int input_flags,
140         char *result_buf)
141         {
142         UI_STRING *ret = NULL;
143
144         if (prompt == NULL)
145                 {
146                 UIerr(UI_F_GENERAL_ALLOCATE_PROMPT,ERR_R_PASSED_NULL_PARAMETER);
147                 }
148         else if (result_buf == NULL)
149                 {
150                 UIerr(UI_F_GENERAL_ALLOCATE_PROMPT,UI_R_NO_RESULT_BUFFER);
151                 }
152         else if ((ret = (UI_STRING *)OPENSSL_malloc(sizeof(UI_STRING))))
153                 {
154                 ret->out_string=prompt;
155                 ret->flags=prompt_freeable ? OUT_STRING_FREEABLE : 0;
156                 ret->input_flags=input_flags;
157                 ret->type=type;
158                 ret->result_buf=result_buf;
159                 }
160         return ret;
161         }
162
163 static int general_allocate_string(UI *ui, const char *prompt,
164         int prompt_freeable, enum UI_string_types type, int input_flags,
165         char *result_buf, int minsize, int maxsize, const char *test_buf)
166         {
167         int ret = -1;
168         UI_STRING *s = general_allocate_prompt(ui, prompt, prompt_freeable,
169                 type, input_flags, result_buf);
170
171         if (s)
172                 {
173                 if (allocate_string_stack(ui) >= 0)
174                         {
175                         s->_.string_data.result_minsize=minsize;
176                         s->_.string_data.result_maxsize=maxsize;
177                         s->_.string_data.test_buf=test_buf;
178                         ret=sk_UI_STRING_push(ui->strings, s);
179                         }
180                 else
181                         free_string(s);
182                 }
183         return ret;
184         }
185
186 static int general_allocate_boolean(UI *ui,
187         const char *prompt, const char *action_desc,
188         const char *ok_chars, const char *cancel_chars,
189         int prompt_freeable, enum UI_string_types type, int input_flags,
190         char *result_buf)
191         {
192         int ret = -1;
193         UI_STRING *s;
194         const char *p;
195
196         if (ok_chars == NULL)
197                 {
198                 UIerr(UI_F_GENERAL_ALLOCATE_BOOLEAN,ERR_R_PASSED_NULL_PARAMETER);
199                 }
200         else if (cancel_chars == NULL)
201                 {
202                 UIerr(UI_F_GENERAL_ALLOCATE_BOOLEAN,ERR_R_PASSED_NULL_PARAMETER);
203                 }
204         else
205                 {
206                 for(p = ok_chars; *p; p++)
207                         {
208                         if (strchr(cancel_chars, *p))
209                                 {
210                                 UIerr(UI_F_GENERAL_ALLOCATE_BOOLEAN,
211                                         UI_R_COMMON_OK_AND_CANCEL_CHARACTERS);
212                                 }
213                         }
214
215                 s = general_allocate_prompt(ui, prompt, prompt_freeable,
216                         type, input_flags, result_buf);
217
218                 if (s)
219                         {
220                         if (allocate_string_stack(ui) >= 0)
221                                 {
222                                 s->_.boolean_data.action_desc = action_desc;
223                                 s->_.boolean_data.ok_chars = ok_chars;
224                                 s->_.boolean_data.cancel_chars = cancel_chars;
225                                 ret=sk_UI_STRING_push(ui->strings, s);
226                                 }
227                         else
228                                 free_string(s);
229                         }
230                 }
231         return ret;
232         }
233
234 /* Returns the index to the place in the stack or 0 for error.  Uses a
235    direct reference to the prompt.  */
236 int UI_add_input_string(UI *ui, const char *prompt, int flags,
237         char *result_buf, int minsize, int maxsize)
238         {
239         return general_allocate_string(ui, prompt, 0,
240                 UIT_PROMPT, flags, result_buf, minsize, maxsize, NULL);
241         }
242
243 /* Same as UI_add_input_string(), excepts it takes a copy of the prompt */
244 int UI_dup_input_string(UI *ui, const char *prompt, int flags,
245         char *result_buf, int minsize, int maxsize)
246         {
247         char *prompt_copy=NULL;
248
249         if (prompt)
250                 {
251                 prompt_copy=BUF_strdup(prompt);
252                 if (prompt_copy == NULL)
253                         {
254                         UIerr(UI_F_UI_DUP_INPUT_STRING,ERR_R_MALLOC_FAILURE);
255                         return 0;
256                         }
257                 }
258         
259         return general_allocate_string(ui, prompt_copy, 1,
260                 UIT_PROMPT, flags, result_buf, minsize, maxsize, NULL);
261         }
262
263 int UI_add_verify_string(UI *ui, const char *prompt, int flags,
264         char *result_buf, int minsize, int maxsize, const char *test_buf)
265         {
266         return general_allocate_string(ui, prompt, 0,
267                 UIT_VERIFY, flags, result_buf, minsize, maxsize, test_buf);
268         }
269
270 int UI_dup_verify_string(UI *ui, const char *prompt, int flags,
271         char *result_buf, int minsize, int maxsize, const char *test_buf)
272         {
273         char *prompt_copy=NULL;
274
275         if (prompt)
276                 {
277                 prompt_copy=BUF_strdup(prompt);
278                 if (prompt_copy == NULL)
279                         {
280                         UIerr(UI_F_UI_DUP_VERIFY_STRING,ERR_R_MALLOC_FAILURE);
281                         return -1;
282                         }
283                 }
284         
285         return general_allocate_string(ui, prompt_copy, 1,
286                 UIT_VERIFY, flags, result_buf, minsize, maxsize, test_buf);
287         }
288
289 int UI_add_input_boolean(UI *ui, const char *prompt, const char *action_desc,
290         const char *ok_chars, const char *cancel_chars,
291         int flags, char *result_buf)
292         {
293         return general_allocate_boolean(ui, prompt, action_desc,
294                 ok_chars, cancel_chars, 0, UIT_BOOLEAN, flags, result_buf);
295         }
296
297 int UI_dup_input_boolean(UI *ui, const char *prompt, const char *action_desc,
298         const char *ok_chars, const char *cancel_chars,
299         int flags, char *result_buf)
300         {
301         char *prompt_copy = NULL;
302         char *action_desc_copy = NULL;
303         char *ok_chars_copy = NULL;
304         char *cancel_chars_copy = NULL;
305
306         if (prompt)
307                 {
308                 prompt_copy=BUF_strdup(prompt);
309                 if (prompt_copy == NULL)
310                         {
311                         UIerr(UI_F_UI_DUP_INPUT_BOOLEAN,ERR_R_MALLOC_FAILURE);
312                         goto err;
313                         }
314                 }
315         
316         if (action_desc)
317                 {
318                 action_desc_copy=BUF_strdup(action_desc);
319                 if (action_desc_copy == NULL)
320                         {
321                         UIerr(UI_F_UI_DUP_INPUT_BOOLEAN,ERR_R_MALLOC_FAILURE);
322                         goto err;
323                         }
324                 }
325         
326         if (ok_chars)
327                 {
328                 ok_chars_copy=BUF_strdup(ok_chars);
329                 if (ok_chars_copy == NULL)
330                         {
331                         UIerr(UI_F_UI_DUP_INPUT_BOOLEAN,ERR_R_MALLOC_FAILURE);
332                         goto err;
333                         }
334                 }
335         
336         if (cancel_chars)
337                 {
338                 cancel_chars_copy=BUF_strdup(cancel_chars);
339                 if (cancel_chars_copy == NULL)
340                         {
341                         UIerr(UI_F_UI_DUP_INPUT_BOOLEAN,ERR_R_MALLOC_FAILURE);
342                         goto err;
343                         }
344                 }
345         
346         return general_allocate_boolean(ui, prompt_copy, action_desc_copy,
347                 ok_chars_copy, cancel_chars_copy, 1, UIT_BOOLEAN, flags,
348                 result_buf);
349  err:
350         if (prompt_copy) OPENSSL_free(prompt_copy);
351         if (action_desc_copy) OPENSSL_free(action_desc_copy);
352         if (ok_chars_copy) OPENSSL_free(ok_chars_copy);
353         if (cancel_chars_copy) OPENSSL_free(cancel_chars_copy);
354         return -1;
355         }
356
357 int UI_add_info_string(UI *ui, const char *text)
358         {
359         return general_allocate_string(ui, text, 0, UIT_INFO, 0, NULL, 0, 0,
360                 NULL);
361         }
362
363 int UI_dup_info_string(UI *ui, const char *text)
364         {
365         char *text_copy=NULL;
366
367         if (text)
368                 {
369                 text_copy=BUF_strdup(text);
370                 if (text_copy == NULL)
371                         {
372                         UIerr(UI_F_UI_DUP_INFO_STRING,ERR_R_MALLOC_FAILURE);
373                         return -1;
374                         }
375                 }
376
377         return general_allocate_string(ui, text_copy, 1, UIT_INFO, 0, NULL,
378                 0, 0, NULL);
379         }
380
381 int UI_add_error_string(UI *ui, const char *text)
382         {
383         return general_allocate_string(ui, text, 0, UIT_ERROR, 0, NULL, 0, 0,
384                 NULL);
385         }
386
387 int UI_dup_error_string(UI *ui, const char *text)
388         {
389         char *text_copy=NULL;
390
391         if (text)
392                 {
393                 text_copy=BUF_strdup(text);
394                 if (text_copy == NULL)
395                         {
396                         UIerr(UI_F_UI_DUP_ERROR_STRING,ERR_R_MALLOC_FAILURE);
397                         return -1;
398                         }
399                 }
400         return general_allocate_string(ui, text_copy, 1, UIT_ERROR, 0, NULL,
401                 0, 0, NULL);
402         }
403
404 char *UI_construct_prompt(UI *ui, const char *object_desc,
405         const char *object_name)
406         {
407         char *prompt = NULL;
408
409         if (ui->meth->ui_construct_prompt)
410                 prompt = ui->meth->ui_construct_prompt(ui,
411                         object_desc, object_name);
412         else
413                 {
414                 char prompt1[] = "Enter ";
415                 char prompt2[] = " for ";
416                 char prompt3[] = ":";
417                 int len = 0;
418
419                 if (object_desc == NULL)
420                         return NULL;
421                 len = sizeof(prompt1) - 1 + strlen(object_desc);
422                 if (object_name)
423                         len += sizeof(prompt2) - 1 + strlen(object_name);
424                 len += sizeof(prompt3) - 1;
425
426                 prompt = (char *)OPENSSL_malloc(len + 1);
427                 strcpy(prompt, prompt1);
428                 strcat(prompt, object_desc);
429                 if (object_name)
430                         {
431                         strcat(prompt, prompt2);
432                         strcat(prompt, object_name);
433                         }
434                 strcat(prompt, prompt3);
435                 }
436         return prompt;
437         }
438
439 void *UI_add_user_data(UI *ui, void *user_data)
440         {
441         void *old_data = ui->user_data;
442         ui->user_data = user_data;
443         return old_data;
444         }
445
446 void *UI_get0_user_data(UI *ui)
447         {
448         return ui->user_data;
449         }
450
451 const char *UI_get0_result(UI *ui, int i)
452         {
453         if (i < 0)
454                 {
455                 UIerr(UI_F_UI_GET0_RESULT,UI_R_INDEX_TOO_SMALL);
456                 return NULL;
457                 }
458         if (i >= sk_UI_STRING_num(ui->strings))
459                 {
460                 UIerr(UI_F_UI_GET0_RESULT,UI_R_INDEX_TOO_LARGE);
461                 return NULL;
462                 }
463         return UI_get0_result_string(sk_UI_STRING_value(ui->strings, i));
464         }
465
466 static int print_error(const char *str, size_t len, UI *ui)
467         {
468         UI_STRING uis;
469
470         memset(&uis, 0, sizeof(uis));
471         uis.type = UIT_ERROR;
472         uis.out_string = str;
473
474         if (ui->meth->ui_write_string
475                 && !ui->meth->ui_write_string(ui, &uis))
476                 return -1;
477         return 0;
478         }
479
480 int UI_process(UI *ui)
481         {
482         int i, ok=0;
483
484         if (ui->meth->ui_open_session && !ui->meth->ui_open_session(ui))
485                 return -1;
486
487         if (ui->flags & UI_FLAG_PRINT_ERRORS)
488                 ERR_print_errors_cb(
489                         (int (*)(const char *, size_t, void *))print_error,
490                         (void *)ui);
491
492         for(i=0; i<sk_UI_STRING_num(ui->strings); i++)
493                 {
494                 if (ui->meth->ui_write_string
495                         && !ui->meth->ui_write_string(ui,
496                                 sk_UI_STRING_value(ui->strings, i)))
497                         {
498                         ok=-1;
499                         goto err;
500                         }
501                 }
502
503         if (ui->meth->ui_flush)
504                 switch(ui->meth->ui_flush(ui))
505                         {
506                 case -1: /* Interrupt/Cancel/something... */
507                         ok = -2;
508                         goto err;
509                 case 0: /* Errors */
510                         ok = -1;
511                         goto err;
512                 default: /* Success */
513                         ok = 0;
514                         break;
515                         }
516
517         for(i=0; i<sk_UI_STRING_num(ui->strings); i++)
518                 {
519                 if (ui->meth->ui_read_string)
520                         {
521                         switch(ui->meth->ui_read_string(ui,
522                                 sk_UI_STRING_value(ui->strings, i)))
523                                 {
524                         case -1: /* Interrupt/Cancel/something... */
525                                 ok = -2;
526                                 goto err;
527                         case 0: /* Errors */
528                                 ok = -1;
529                                 goto err;
530                         default: /* Success */
531                                 ok = 0;
532                                 break;
533                                 }
534                         }
535                 }
536  err:
537         if (ui->meth->ui_close_session && !ui->meth->ui_close_session(ui))
538                 return -1;
539         return ok;
540         }
541
542 int UI_ctrl(UI *ui, int cmd, long i, void *p, void (*f)())
543         {
544         if (ui == NULL)
545                 {
546                 UIerr(UI_F_UI_CTRL,ERR_R_PASSED_NULL_PARAMETER);
547                 return -1;
548                 }
549         switch(cmd)
550                 {
551         case UI_CTRL_PRINT_ERRORS:
552                 {
553                 int save_flag = !!(ui->flags & UI_FLAG_PRINT_ERRORS);
554                 if (i)
555                         ui->flags |= UI_FLAG_PRINT_ERRORS;
556                 else
557                         ui->flags &= ~UI_FLAG_PRINT_ERRORS;
558                 return save_flag;
559                 }
560         case UI_CTRL_IS_REDOABLE:
561                 return !!(ui->flags & UI_FLAG_REDOABLE);
562         default:
563                 break;
564                 }
565         UIerr(UI_F_UI_CTRL,UI_R_UNKNOWN_CONTROL_COMMAND);
566         return -1;
567         }
568
569 int UI_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
570              CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func)
571         {
572         ui_meth_num++;
573         return(CRYPTO_get_ex_new_index(ui_meth_num-1,
574                 &ui_meth,argl,argp,new_func,dup_func,free_func));
575         }
576
577 int UI_set_ex_data(UI *r, int idx, void *arg)
578         {
579         return(CRYPTO_set_ex_data(&r->ex_data,idx,arg));
580         }
581
582 void *UI_get_ex_data(UI *r, int idx)
583         {
584         return(CRYPTO_get_ex_data(&r->ex_data,idx));
585         }
586
587 void UI_set_default_method(const UI_METHOD *meth)
588         {
589         default_UI_meth=meth;
590         }
591
592 const UI_METHOD *UI_get_default_method(void)
593         {
594         if (default_UI_meth == NULL)
595                 {
596                 default_UI_meth=UI_OpenSSL();
597                 }
598         return default_UI_meth;
599         }
600
601 const UI_METHOD *UI_get_method(UI *ui)
602         {
603         return ui->meth;
604         }
605
606 const UI_METHOD *UI_set_method(UI *ui, const UI_METHOD *meth)
607         {
608         ui->meth=meth;
609         return ui->meth;
610         }
611
612
613 UI_METHOD *UI_create_method(char *name)
614         {
615         UI_METHOD *ui_method = (UI_METHOD *)OPENSSL_malloc(sizeof(UI_METHOD));
616
617         if (ui_method)
618                 memset(ui_method, 0, sizeof(*ui_method));
619         ui_method->name = BUF_strdup(name);
620         return ui_method;
621         }
622
623 /* BIG FSCKING WARNING!!!!  If you use this on a statically allocated method
624    (that is, it hasn't been allocated using UI_create_method(), you deserve
625    anything Murphy can throw at you and more!  You have been warned. */
626 void UI_destroy_method(UI_METHOD *ui_method)
627         {
628         OPENSSL_free(ui_method->name);
629         ui_method->name = NULL;
630         OPENSSL_free(ui_method);
631         }
632
633 int UI_method_set_opener(UI_METHOD *method, int (*opener)(UI *ui))
634         {
635         if (method)
636                 {
637                 method->ui_open_session = opener;
638                 return 0;
639                 }
640         else
641                 return -1;
642         }
643
644 int UI_method_set_writer(UI_METHOD *method, int (*writer)(UI *ui, UI_STRING *uis))
645         {
646         if (method)
647                 {
648                 method->ui_write_string = writer;
649                 return 0;
650                 }
651         else
652                 return -1;
653         }
654
655 int UI_method_set_flusher(UI_METHOD *method, int (*flusher)(UI *ui))
656         {
657         if (method)
658                 {
659                 method->ui_flush = flusher;
660                 return 0;
661                 }
662         else
663                 return -1;
664         }
665
666 int UI_method_set_reader(UI_METHOD *method, int (*reader)(UI *ui, UI_STRING *uis))
667         {
668         if (method)
669                 {
670                 method->ui_read_string = reader;
671                 return 0;
672                 }
673         else
674                 return -1;
675         }
676
677 int UI_method_set_closer(UI_METHOD *method, int (*closer)(UI *ui))
678         {
679         if (method)
680                 {
681                 method->ui_close_session = closer;
682                 return 0;
683                 }
684         else
685                 return -1;
686         }
687
688 int (*UI_method_get_opener(UI_METHOD *method))(UI*)
689         {
690         if (method)
691                 return method->ui_open_session;
692         else
693                 return NULL;
694         }
695
696 int (*UI_method_get_writer(UI_METHOD *method))(UI*,UI_STRING*)
697         {
698         if (method)
699                 return method->ui_write_string;
700         else
701                 return NULL;
702         }
703
704 int (*UI_method_get_reader(UI_METHOD *method))(UI*,UI_STRING*)
705         {
706         if (method)
707                 return method->ui_read_string;
708         else
709                 return NULL;
710         }
711
712 int (*UI_method_get_closer(UI_METHOD *method))(UI*)
713         {
714         if (method)
715                 return method->ui_close_session;
716         else
717                 return NULL;
718         }
719
720 enum UI_string_types UI_get_string_type(UI_STRING *uis)
721         {
722         if (!uis)
723                 return UIT_NONE;
724         return uis->type;
725         }
726
727 int UI_get_input_flags(UI_STRING *uis)
728         {
729         if (!uis)
730                 return 0;
731         return uis->input_flags;
732         }
733
734 const char *UI_get0_output_string(UI_STRING *uis)
735         {
736         if (!uis)
737                 return NULL;
738         return uis->out_string;
739         }
740
741 const char *UI_get0_action_string(UI_STRING *uis)
742         {
743         if (!uis)
744                 return NULL;
745         switch(uis->type)
746                 {
747         case UIT_PROMPT:
748         case UIT_BOOLEAN:
749                 return uis->_.boolean_data.action_desc;
750         default:
751                 return NULL;
752                 }
753         }
754
755 const char *UI_get0_result_string(UI_STRING *uis)
756         {
757         if (!uis)
758                 return NULL;
759         switch(uis->type)
760                 {
761         case UIT_PROMPT:
762         case UIT_VERIFY:
763                 return uis->result_buf;
764         default:
765                 return NULL;
766                 }
767         }
768
769 const char *UI_get0_test_string(UI_STRING *uis)
770         {
771         if (!uis)
772                 return NULL;
773         switch(uis->type)
774                 {
775         case UIT_VERIFY:
776                 return uis->_.string_data.test_buf;
777         default:
778                 return NULL;
779                 }
780         }
781
782 int UI_get_result_minsize(UI_STRING *uis)
783         {
784         if (!uis)
785                 return -1;
786         switch(uis->type)
787                 {
788         case UIT_PROMPT:
789         case UIT_VERIFY:
790                 return uis->_.string_data.result_minsize;
791         default:
792                 return -1;
793                 }
794         }
795
796 int UI_get_result_maxsize(UI_STRING *uis)
797         {
798         if (!uis)
799                 return -1;
800         switch(uis->type)
801                 {
802         case UIT_PROMPT:
803         case UIT_VERIFY:
804                 return uis->_.string_data.result_maxsize;
805         default:
806                 return -1;
807                 }
808         }
809
810 int UI_set_result(UI *ui, UI_STRING *uis, const char *result)
811         {
812         int l = strlen(result);
813
814         ui->flags &= ~UI_FLAG_REDOABLE;
815
816         if (!uis)
817                 return -1;
818         switch (uis->type)
819                 {
820         case UIT_PROMPT:
821         case UIT_VERIFY:
822                 {
823                 char number1[20];
824                 char number2[20];
825
826                 BIO_snprintf(number1, sizeof(number1), "%d",
827                         uis->_.string_data.result_minsize);
828                 BIO_snprintf(number2, sizeof(number2), "%d",
829                         uis->_.string_data.result_maxsize);
830
831                 if (l < uis->_.string_data.result_minsize)
832                         {
833                         ui->flags |= UI_FLAG_REDOABLE;
834                         UIerr(UI_F_UI_SET_RESULT,UI_R_RESULT_TOO_SMALL);
835                         ERR_add_error_data(5,"You must type in ",
836                                 number1," to ",number2," characters");
837                         return -1;
838                         }
839                 if (l > uis->_.string_data.result_maxsize)
840                         {
841                         ui->flags |= UI_FLAG_REDOABLE;
842                         UIerr(UI_F_UI_SET_RESULT,UI_R_RESULT_TOO_LARGE);
843                         ERR_add_error_data(5,"You must type in ",
844                                 number1," to ",number2," characters");
845                         return -1;
846                         }
847                 }
848
849                 if (!uis->result_buf)
850                         {
851                         UIerr(UI_F_UI_SET_RESULT,UI_R_NO_RESULT_BUFFER);
852                         return -1;
853                         }
854
855                 strcpy(uis->result_buf, result);
856                 break;
857         case UIT_BOOLEAN:
858                 {
859                 const char *p;
860
861                 if (!uis->result_buf)
862                         {
863                         UIerr(UI_F_UI_SET_RESULT,UI_R_NO_RESULT_BUFFER);
864                         return -1;
865                         }
866
867                 uis->result_buf[0] = '\0';
868                 for(p = result; *p; p++)
869                         {
870                         if (strchr(uis->_.boolean_data.ok_chars, *p))
871                                 {
872                                 uis->result_buf[0] =
873                                         uis->_.boolean_data.ok_chars[0];
874                                 break;
875                                 }
876                         if (strchr(uis->_.boolean_data.cancel_chars, *p))
877                                 {
878                                 uis->result_buf[0] =
879                                         uis->_.boolean_data.cancel_chars[0];
880                                 break;
881                                 }
882                         }
883         default:
884                 break;
885                 }
886                 }
887         return 0;
888         }