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