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