xref: /openbsd-src/lib/libcrypto/ui/ui_lib.c (revision ce7e0fc6a9d74d25b78fb6ad846387717f5172b6)
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 	}
900