ui_lib.c revision 312826
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 != NULL) { 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 != '\0'; p++) { 201 if (strchr(cancel_chars, *p) != NULL) { 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 != NULL) { 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 != NULL) { 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 != NULL) { 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 != NULL) { 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 != NULL) { 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 != NULL) { 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 != NULL) { 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 != NULL) { 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 != NULL) { 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 != NULL) 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 != NULL) 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 != NULL) { 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 != NULL 463 && ui->meth->ui_write_string(ui, &uis) <= 0) 464 return -1; 465 return 0; 466} 467 468int UI_process(UI *ui) 469{ 470 int i, ok = 0; 471 472 if (ui->meth->ui_open_session != NULL 473 && ui->meth->ui_open_session(ui) <= 0) { 474 ok = -1; 475 goto err; 476 } 477 478 if (ui->flags & UI_FLAG_PRINT_ERRORS) 479 ERR_print_errors_cb((int (*)(const char *, size_t, void *)) 480 print_error, (void *)ui); 481 482 for (i = 0; i < sk_UI_STRING_num(ui->strings); i++) { 483 if (ui->meth->ui_write_string != NULL 484 && (ui->meth->ui_write_string(ui, 485 sk_UI_STRING_value(ui->strings, i)) 486 <= 0)) 487 { 488 ok = -1; 489 goto err; 490 } 491 } 492 493 if (ui->meth->ui_flush != NULL) 494 switch (ui->meth->ui_flush(ui)) { 495 case -1: /* Interrupt/Cancel/something... */ 496 ok = -2; 497 goto err; 498 case 0: /* Errors */ 499 ok = -1; 500 goto err; 501 default: /* Success */ 502 ok = 0; 503 break; 504 } 505 506 for (i = 0; i < sk_UI_STRING_num(ui->strings); i++) { 507 if (ui->meth->ui_read_string != NULL) { 508 switch (ui->meth->ui_read_string(ui, 509 sk_UI_STRING_value(ui->strings, 510 i))) { 511 case -1: /* Interrupt/Cancel/something... */ 512 ok = -2; 513 goto err; 514 case 0: /* Errors */ 515 ok = -1; 516 goto err; 517 default: /* Success */ 518 ok = 0; 519 break; 520 } 521 } 522 } 523 err: 524 if (ui->meth->ui_close_session != NULL 525 && ui->meth->ui_close_session(ui) <= 0) 526 return -1; 527 return ok; 528} 529 530int UI_ctrl(UI *ui, int cmd, long i, void *p, void (*f) (void)) 531{ 532 if (ui == NULL) { 533 UIerr(UI_F_UI_CTRL, ERR_R_PASSED_NULL_PARAMETER); 534 return -1; 535 } 536 switch (cmd) { 537 case UI_CTRL_PRINT_ERRORS: 538 { 539 int save_flag = ! !(ui->flags & UI_FLAG_PRINT_ERRORS); 540 if (i) 541 ui->flags |= UI_FLAG_PRINT_ERRORS; 542 else 543 ui->flags &= ~UI_FLAG_PRINT_ERRORS; 544 return save_flag; 545 } 546 case UI_CTRL_IS_REDOABLE: 547 return ! !(ui->flags & UI_FLAG_REDOABLE); 548 default: 549 break; 550 } 551 UIerr(UI_F_UI_CTRL, UI_R_UNKNOWN_CONTROL_COMMAND); 552 return -1; 553} 554 555int UI_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, 556 CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func) 557{ 558 return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_UI, argl, argp, 559 new_func, dup_func, free_func); 560} 561 562int UI_set_ex_data(UI *r, int idx, void *arg) 563{ 564 return (CRYPTO_set_ex_data(&r->ex_data, idx, arg)); 565} 566 567void *UI_get_ex_data(UI *r, int idx) 568{ 569 return (CRYPTO_get_ex_data(&r->ex_data, idx)); 570} 571 572void UI_set_default_method(const UI_METHOD *meth) 573{ 574 default_UI_meth = meth; 575} 576 577const UI_METHOD *UI_get_default_method(void) 578{ 579 if (default_UI_meth == NULL) { 580 default_UI_meth = UI_OpenSSL(); 581 } 582 return default_UI_meth; 583} 584 585const UI_METHOD *UI_get_method(UI *ui) 586{ 587 return ui->meth; 588} 589 590const UI_METHOD *UI_set_method(UI *ui, const UI_METHOD *meth) 591{ 592 ui->meth = meth; 593 return ui->meth; 594} 595 596UI_METHOD *UI_create_method(char *name) 597{ 598 UI_METHOD *ui_method = (UI_METHOD *)OPENSSL_malloc(sizeof(UI_METHOD)); 599 600 if (ui_method) { 601 memset(ui_method, 0, sizeof(*ui_method)); 602 ui_method->name = BUF_strdup(name); 603 } 604 return ui_method; 605} 606 607/* 608 * BIG FSCKING WARNING!!!! If you use this on a statically allocated method 609 * (that is, it hasn't been allocated using UI_create_method(), you deserve 610 * anything Murphy can throw at you and more! You have been warned. 611 */ 612void UI_destroy_method(UI_METHOD *ui_method) 613{ 614 OPENSSL_free(ui_method->name); 615 ui_method->name = NULL; 616 OPENSSL_free(ui_method); 617} 618 619int UI_method_set_opener(UI_METHOD *method, int (*opener) (UI *ui)) 620{ 621 if (method != NULL) { 622 method->ui_open_session = opener; 623 return 0; 624 } 625 return -1; 626} 627 628int UI_method_set_writer(UI_METHOD *method, 629 int (*writer) (UI *ui, UI_STRING *uis)) 630{ 631 if (method != NULL) { 632 method->ui_write_string = writer; 633 return 0; 634 } 635 return -1; 636} 637 638int UI_method_set_flusher(UI_METHOD *method, int (*flusher) (UI *ui)) 639{ 640 if (method != NULL) { 641 method->ui_flush = flusher; 642 return 0; 643 } 644 return -1; 645} 646 647int UI_method_set_reader(UI_METHOD *method, 648 int (*reader) (UI *ui, UI_STRING *uis)) 649{ 650 if (method != NULL) { 651 method->ui_read_string = reader; 652 return 0; 653 } 654 return -1; 655} 656 657int UI_method_set_closer(UI_METHOD *method, int (*closer) (UI *ui)) 658{ 659 if (method != NULL) { 660 method->ui_close_session = closer; 661 return 0; 662 } 663 return -1; 664} 665 666int UI_method_set_prompt_constructor(UI_METHOD *method, 667 char *(*prompt_constructor) (UI *ui, 668 const char 669 *object_desc, 670 const char 671 *object_name)) 672{ 673 if (method != NULL) { 674 method->ui_construct_prompt = prompt_constructor; 675 return 0; 676 } 677 return -1; 678} 679 680int (*UI_method_get_opener(UI_METHOD *method)) (UI *) 681{ 682 if (method != NULL) 683 return method->ui_open_session; 684 return NULL; 685} 686 687int (*UI_method_get_writer(UI_METHOD *method)) (UI *, UI_STRING *) 688{ 689 if (method != NULL) 690 return method->ui_write_string; 691 return NULL; 692} 693 694int (*UI_method_get_flusher(UI_METHOD *method)) (UI *) 695{ 696 if (method != NULL) 697 return method->ui_flush; 698 return NULL; 699} 700 701int (*UI_method_get_reader(UI_METHOD *method)) (UI *, UI_STRING *) 702{ 703 if (method != NULL) 704 return method->ui_read_string; 705 return NULL; 706} 707 708int (*UI_method_get_closer(UI_METHOD *method)) (UI *) 709{ 710 if (method != NULL) 711 return method->ui_close_session; 712 return NULL; 713} 714 715char *(*UI_method_get_prompt_constructor(UI_METHOD *method)) (UI *, 716 const char *, 717 const char *) 718{ 719 if (method != NULL) 720 return method->ui_construct_prompt; 721 return NULL; 722} 723 724enum UI_string_types UI_get_string_type(UI_STRING *uis) 725{ 726 if (!uis) 727 return UIT_NONE; 728 return uis->type; 729} 730 731int UI_get_input_flags(UI_STRING *uis) 732{ 733 if (!uis) 734 return 0; 735 return uis->input_flags; 736} 737 738const char *UI_get0_output_string(UI_STRING *uis) 739{ 740 if (!uis) 741 return NULL; 742 return uis->out_string; 743} 744 745const char *UI_get0_action_string(UI_STRING *uis) 746{ 747 if (!uis) 748 return NULL; 749 switch (uis->type) { 750 case UIT_PROMPT: 751 case UIT_BOOLEAN: 752 return uis->_.boolean_data.action_desc; 753 default: 754 return NULL; 755 } 756} 757 758const char *UI_get0_result_string(UI_STRING *uis) 759{ 760 if (!uis) 761 return NULL; 762 switch (uis->type) { 763 case UIT_PROMPT: 764 case UIT_VERIFY: 765 return uis->result_buf; 766 default: 767 return NULL; 768 } 769} 770 771const char *UI_get0_test_string(UI_STRING *uis) 772{ 773 if (!uis) 774 return NULL; 775 switch (uis->type) { 776 case UIT_VERIFY: 777 return uis->_.string_data.test_buf; 778 default: 779 return NULL; 780 } 781} 782 783int UI_get_result_minsize(UI_STRING *uis) 784{ 785 if (!uis) 786 return -1; 787 switch (uis->type) { 788 case UIT_PROMPT: 789 case UIT_VERIFY: 790 return uis->_.string_data.result_minsize; 791 default: 792 return -1; 793 } 794} 795 796int UI_get_result_maxsize(UI_STRING *uis) 797{ 798 if (!uis) 799 return -1; 800 switch (uis->type) { 801 case UIT_PROMPT: 802 case UIT_VERIFY: 803 return uis->_.string_data.result_maxsize; 804 default: 805 return -1; 806 } 807} 808 809int UI_set_result(UI *ui, UI_STRING *uis, const char *result) 810{ 811 int l = strlen(result); 812 813 ui->flags &= ~UI_FLAG_REDOABLE; 814 815 if (!uis) 816 return -1; 817 switch (uis->type) { 818 case UIT_PROMPT: 819 case UIT_VERIFY: 820 { 821 char number1[DECIMAL_SIZE(uis->_.string_data.result_minsize) + 1]; 822 char number2[DECIMAL_SIZE(uis->_.string_data.result_maxsize) + 1]; 823 824 BIO_snprintf(number1, sizeof(number1), "%d", 825 uis->_.string_data.result_minsize); 826 BIO_snprintf(number2, sizeof(number2), "%d", 827 uis->_.string_data.result_maxsize); 828 829 if (l < uis->_.string_data.result_minsize) { 830 ui->flags |= UI_FLAG_REDOABLE; 831 UIerr(UI_F_UI_SET_RESULT, UI_R_RESULT_TOO_SMALL); 832 ERR_add_error_data(5, "You must type in ", 833 number1, " to ", number2, " characters"); 834 return -1; 835 } 836 if (l > uis->_.string_data.result_maxsize) { 837 ui->flags |= UI_FLAG_REDOABLE; 838 UIerr(UI_F_UI_SET_RESULT, UI_R_RESULT_TOO_LARGE); 839 ERR_add_error_data(5, "You must type in ", 840 number1, " to ", number2, " characters"); 841 return -1; 842 } 843 } 844 845 if (!uis->result_buf) { 846 UIerr(UI_F_UI_SET_RESULT, UI_R_NO_RESULT_BUFFER); 847 return -1; 848 } 849 850 BUF_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 UIerr(UI_F_UI_SET_RESULT, UI_R_NO_RESULT_BUFFER); 859 return -1; 860 } 861 862 uis->result_buf[0] = '\0'; 863 for (p = result; *p; p++) { 864 if (strchr(uis->_.boolean_data.ok_chars, *p)) { 865 uis->result_buf[0] = uis->_.boolean_data.ok_chars[0]; 866 break; 867 } 868 if (strchr(uis->_.boolean_data.cancel_chars, *p)) { 869 uis->result_buf[0] = uis->_.boolean_data.cancel_chars[0]; 870 break; 871 } 872 } 873 } 874 default: 875 break; 876 } 877 return 0; 878} 879