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