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