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