GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: lib/libcrypto/crypto/../../libssl/src/crypto/ui/ui_lib.c Lines: 26 337 7.7 %
Date: 2016-12-06 Branches: 5 198 2.5 %

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