GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: lib/libcrypto/ui/ui_lib.c Lines: 24 327 7.3 %
Date: 2017-11-13 Branches: 5 198 2.5 %

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