Coverage Report

Created: 2026-07-16 06:59

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/openssl/crypto/ui/ui_openssl.c
Line
Count
Source
1
/*
2
 * Copyright 2001-2022 The OpenSSL Project Authors. All Rights Reserved.
3
 *
4
 * Licensed under the Apache License 2.0 (the "License").  You may not use
5
 * this file except in compliance with the License.  You can obtain a copy
6
 * in the file LICENSE in the source distribution or at
7
 * https://www.openssl.org/source/license.html
8
 */
9
10
#include "internal/e_os.h"
11
#include <openssl/e_os2.h>
12
#include <openssl/err.h>
13
#include <openssl/ui.h>
14
15
#ifndef OPENSSL_NO_UI_CONSOLE
16
/*
17
 * need for #define _POSIX_C_SOURCE arises whenever you pass -ansi to gcc
18
 * [maybe others?], because it masks interfaces not discussed in standard,
19
 * sigaction and fileno included. -pedantic would be more appropriate for the
20
 * intended purposes, but we can't prevent users from adding -ansi.
21
 */
22
#if defined(OPENSSL_SYS_VXWORKS)
23
#include <sys/types.h>
24
#endif
25
26
#if !defined(_POSIX_C_SOURCE) && defined(OPENSSL_SYS_VMS)
27
#ifndef _POSIX_C_SOURCE
28
#define _POSIX_C_SOURCE 2
29
#endif
30
#endif
31
#include <signal.h>
32
#include <stdio.h>
33
#include <string.h>
34
#include <errno.h>
35
36
#if !defined(OPENSSL_SYS_MSDOS) && !defined(OPENSSL_SYS_VMS)
37
#include <unistd.h>
38
/*
39
 * If unistd.h defines _POSIX_VERSION, we conclude that we are on a POSIX
40
 * system and have sigaction and termios.
41
 */
42
#if defined(_POSIX_VERSION) && _POSIX_VERSION >= 199309L
43
44
#define SIGACTION
45
#if !defined(TERMIOS) && !defined(TERMIO) && !defined(SGTTY)
46
#define TERMIOS
47
#endif
48
49
#endif
50
#endif
51
52
#include "ui_local.h"
53
#include "internal/cryptlib.h"
54
55
#ifdef OPENSSL_SYS_VMS /* prototypes for sys$whatever */
56
#include <starlet.h>
57
#ifdef __DECC
58
#pragma message disable DOLLARID
59
#endif
60
#endif
61
62
#ifdef WIN_CONSOLE_BUG
63
#include <wincon.h>
64
#endif
65
66
/*
67
 * There are 6 types of terminal interface supported, TERMIO, TERMIOS, VMS,
68
 * MSDOS, WIN32 Console and SGTTY.
69
 *
70
 * If someone defines one of the macros TERMIO, TERMIOS or SGTTY, it will
71
 * remain respected.  Otherwise, we default to TERMIOS except for a few
72
 * systems that require something different.
73
 *
74
 * Note: we do not use SGTTY unless it's defined by the configuration.  We
75
 * may eventually opt to remove its use entirely.
76
 */
77
78
#if !defined(TERMIOS) && !defined(TERMIO) && !defined(SGTTY)
79
80
#if defined(_LIBC)
81
#undef TERMIOS
82
#define TERMIO
83
#undef SGTTY
84
/*
85
 * We know that VMS, MSDOS, VXWORKS, use entirely other mechanisms.
86
 */
87
#elif !defined(OPENSSL_SYS_VMS)    \
88
    && !defined(OPENSSL_SYS_MSDOS) \
89
    && !defined(OPENSSL_SYS_VXWORKS)
90
#define TERMIOS
91
#undef TERMIO
92
#undef SGTTY
93
#endif
94
95
#endif
96
97
#if defined(OPENSSL_SYS_VXWORKS)
98
#undef TERMIOS
99
#undef TERMIO
100
#undef SGTTY
101
#endif
102
103
#ifdef TERMIOS
104
#include <termios.h>
105
#define TTY_STRUCT struct termios
106
0
#define TTY_FLAGS c_lflag
107
0
#define TTY_get(tty, data) tcgetattr(tty, data)
108
0
#define TTY_set(tty, data) tcsetattr(tty, TCSANOW, data)
109
#endif
110
111
#ifdef TERMIO
112
#include <termio.h>
113
#define TTY_STRUCT struct termio
114
#define TTY_FLAGS c_lflag
115
#define TTY_get(tty, data) ioctl(tty, TCGETA, data)
116
#define TTY_set(tty, data) ioctl(tty, TCSETA, data)
117
#endif
118
119
#ifdef SGTTY
120
#include <sgtty.h>
121
#define TTY_STRUCT struct sgttyb
122
#define TTY_FLAGS sg_flags
123
#define TTY_get(tty, data) ioctl(tty, TIOCGETP, data)
124
#define TTY_set(tty, data) ioctl(tty, TIOCSETP, data)
125
#endif
126
127
#if !defined(_LIBC) && !defined(OPENSSL_SYS_MSDOS) && !defined(OPENSSL_SYS_VMS) && !(defined(OPENSSL_SYS_TANDEM) && defined(_SPT_MODEL_))
128
#include <sys/ioctl.h>
129
#endif
130
131
#ifdef OPENSSL_SYS_MSDOS
132
#include <conio.h>
133
#endif
134
135
#ifdef OPENSSL_SYS_VMS
136
#include <ssdef.h>
137
#include <iodef.h>
138
#include <ttdef.h>
139
#include <descrip.h>
140
struct IOSB {
141
    short iosb$w_value;
142
    short iosb$w_count;
143
    long iosb$l_info;
144
};
145
#endif
146
147
#ifndef NX509_SIG
148
0
#define NX509_SIG 32
149
#endif
150
151
/* Define globals.  They are protected by a lock */
152
#ifdef SIGACTION
153
static struct sigaction savsig[NX509_SIG];
154
#else
155
static void (*savsig[NX509_SIG])(int);
156
#endif
157
158
#ifdef OPENSSL_SYS_VMS
159
static struct IOSB iosb;
160
static $DESCRIPTOR(terminal, "TT");
161
static long tty_orig[3], tty_new[3]; /* XXX Is there any guarantee that this
162
                                      * will always suffice for the actual
163
                                      * structures? */
164
static long status;
165
static unsigned short channel = 0;
166
#elif defined(_WIN32)
167
static DWORD tty_orig, tty_new;
168
#else
169
#if !defined(OPENSSL_SYS_MSDOS) || defined(__DJGPP__)
170
static TTY_STRUCT tty_orig, tty_new;
171
#endif
172
#endif
173
static FILE *tty_in, *tty_out;
174
static int is_a_tty;
175
176
/* Declare static functions */
177
static int read_till_nl(FILE *);
178
static void recsig(int);
179
static void pushsig(void);
180
static void popsig(void);
181
#if defined(OPENSSL_SYS_MSDOS) && !defined(_WIN32)
182
static int noecho_fgets(char *buf, int size, FILE *tty);
183
#endif
184
static int read_string_inner(UI *ui, UI_STRING *uis, int echo, int strip_nl);
185
186
static int read_string(UI *ui, UI_STRING *uis);
187
static int write_string(UI *ui, UI_STRING *uis);
188
189
static int open_console(UI *ui);
190
static int echo_console(UI *ui);
191
static int noecho_console(UI *ui);
192
static int close_console(UI *ui);
193
194
/*
195
 * The following function makes sure that info and error strings are printed
196
 * before any prompt.
197
 */
198
static int write_string(UI *ui, UI_STRING *uis)
199
0
{
200
0
    switch (UI_get_string_type(uis)) {
201
0
    case UIT_ERROR:
202
0
    case UIT_INFO:
203
0
        fputs(UI_get0_output_string(uis), tty_out);
204
0
        fflush(tty_out);
205
0
        break;
206
0
    case UIT_NONE:
207
0
    case UIT_PROMPT:
208
0
    case UIT_VERIFY:
209
0
    case UIT_BOOLEAN:
210
0
        break;
211
0
    }
212
0
    return 1;
213
0
}
214
215
static int read_string(UI *ui, UI_STRING *uis)
216
0
{
217
0
    int ok = 0;
218
219
0
    switch (UI_get_string_type(uis)) {
220
0
    case UIT_BOOLEAN:
221
0
        fputs(UI_get0_output_string(uis), tty_out);
222
0
        fputs(UI_get0_action_string(uis), tty_out);
223
0
        fflush(tty_out);
224
0
        return read_string_inner(ui, uis,
225
0
            UI_get_input_flags(uis) & UI_INPUT_FLAG_ECHO,
226
0
            0);
227
0
    case UIT_PROMPT:
228
0
        fputs(UI_get0_output_string(uis), tty_out);
229
0
        fflush(tty_out);
230
0
        return read_string_inner(ui, uis,
231
0
            UI_get_input_flags(uis) & UI_INPUT_FLAG_ECHO,
232
0
            1);
233
0
    case UIT_VERIFY:
234
0
        fprintf(tty_out, "Verifying - %s", UI_get0_output_string(uis));
235
0
        fflush(tty_out);
236
0
        if ((ok = read_string_inner(ui, uis,
237
0
                 UI_get_input_flags(uis) & UI_INPUT_FLAG_ECHO, 1))
238
0
            <= 0)
239
0
            return ok;
240
0
        if (strcmp(UI_get0_result_string(uis), UI_get0_test_string(uis)) != 0) {
241
0
            fprintf(tty_out, "Verify failure\n");
242
0
            fflush(tty_out);
243
0
            return 0;
244
0
        }
245
0
        break;
246
0
    case UIT_NONE:
247
0
    case UIT_INFO:
248
0
    case UIT_ERROR:
249
0
        break;
250
0
    }
251
0
    return 1;
252
0
}
253
254
/* Internal functions to read a string without echoing */
255
static int read_till_nl(FILE *in)
256
0
{
257
0
#define SIZE 4
258
0
    char buf[SIZE + 1];
259
260
0
    do {
261
0
        if (!fgets(buf, SIZE, in))
262
0
            return 0;
263
0
    } while (strchr(buf, '\n') == NULL);
264
0
    return 1;
265
0
}
266
267
static volatile sig_atomic_t intr_signal;
268
269
static int read_string_inner(UI *ui, UI_STRING *uis, int echo, int strip_nl)
270
0
{
271
0
    static int ps;
272
0
    int ok;
273
0
    char result[BUFSIZ];
274
0
    int maxsize = BUFSIZ - 1;
275
0
    char *p = NULL;
276
0
    int echo_eol = !echo;
277
278
0
    intr_signal = 0;
279
0
    ok = 0;
280
0
    ps = 0;
281
282
0
    pushsig();
283
0
    ps = 1;
284
285
0
    if (!echo && !noecho_console(ui))
286
0
        goto error;
287
0
    ps = 2;
288
289
0
    result[0] = '\0';
290
#if defined(_WIN32)
291
    if (is_a_tty) {
292
        DWORD numread;
293
#if defined(CP_UTF8)
294
        if (GetEnvironmentVariableW(L"OPENSSL_WIN32_UTF8", NULL, 0) != 0) {
295
            WCHAR wresult[BUFSIZ];
296
297
            if (ReadConsoleW(GetStdHandle(STD_INPUT_HANDLE),
298
                    wresult, maxsize, &numread, NULL)) {
299
                if (numread >= 2 && wresult[numread - 2] == L'\r' && wresult[numread - 1] == L'\n') {
300
                    wresult[numread - 2] = L'\n';
301
                    numread--;
302
                }
303
                wresult[numread] = '\0';
304
                if (WideCharToMultiByte(CP_UTF8, 0, wresult, -1,
305
                        result, sizeof(result), NULL, 0)
306
                    > 0)
307
                    p = result;
308
309
                OPENSSL_cleanse(wresult, sizeof(wresult));
310
            }
311
        } else
312
#endif
313
            if (ReadConsoleA(GetStdHandle(STD_INPUT_HANDLE),
314
                    result, maxsize, &numread, NULL)) {
315
            if (numread >= 2 && result[numread - 2] == '\r' && result[numread - 1] == '\n') {
316
                result[numread - 2] = '\n';
317
                numread--;
318
            }
319
            result[numread] = '\0';
320
            p = result;
321
        }
322
    } else
323
#elif defined(OPENSSL_SYS_MSDOS)
324
    if (!echo) {
325
        noecho_fgets(result, maxsize, tty_in);
326
        p = result; /* FIXME: noecho_fgets doesn't return errors */
327
    } else
328
#endif
329
0
        p = fgets(result, maxsize, tty_in);
330
0
    if (p == NULL)
331
0
        goto error;
332
0
    if (feof(tty_in))
333
0
        goto error;
334
0
    if (ferror(tty_in))
335
0
        goto error;
336
0
    if ((p = (char *)strchr(result, '\n')) != NULL) {
337
0
        if (strip_nl)
338
0
            *p = '\0';
339
0
    } else if (!read_till_nl(tty_in))
340
0
        goto error;
341
0
    if (UI_set_result(ui, uis, result) >= 0)
342
0
        ok = 1;
343
344
0
error:
345
0
    if (intr_signal == SIGINT)
346
0
        ok = -1;
347
0
    if (echo_eol)
348
0
        fprintf(tty_out, "\n");
349
0
    if (ps >= 2 && !echo && !echo_console(ui))
350
0
        ok = 0;
351
352
0
    if (ps >= 1)
353
0
        popsig();
354
355
0
    OPENSSL_cleanse(result, BUFSIZ);
356
0
    return ok;
357
0
}
358
359
/* Internal functions to open, handle and close a channel to the console.  */
360
static int open_console(UI *ui)
361
0
{
362
0
    if (!CRYPTO_THREAD_write_lock(ui->lock))
363
0
        return 0;
364
0
    is_a_tty = 1;
365
366
#if defined(OPENSSL_SYS_VXWORKS)
367
    tty_in = stdin;
368
    tty_out = stderr;
369
#elif defined(_WIN32)
370
    if ((tty_out = fopen("conout$", "w")) == NULL)
371
        tty_out = stderr;
372
373
    if (GetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), &tty_orig)) {
374
        tty_in = stdin;
375
    } else {
376
        is_a_tty = 0;
377
        if ((tty_in = fopen("conin$", "r")) == NULL)
378
            tty_in = stdin;
379
    }
380
#else
381
#ifdef OPENSSL_SYS_MSDOS
382
#define DEV_TTY "con"
383
#else
384
0
#define DEV_TTY "/dev/tty"
385
0
#endif
386
0
    if ((tty_in = fopen(DEV_TTY, "r")) == NULL)
387
0
        tty_in = stdin;
388
0
    if ((tty_out = fopen(DEV_TTY, "w")) == NULL)
389
0
        tty_out = stderr;
390
0
#endif
391
392
0
#if defined(TTY_get) && !defined(OPENSSL_SYS_VMS)
393
0
    if (TTY_get(fileno(tty_in), &tty_orig) == -1) {
394
0
#ifdef ENOTTY
395
0
        if (errno == ENOTTY)
396
0
            is_a_tty = 0;
397
0
        else
398
0
#endif
399
0
#ifdef EINVAL
400
            /*
401
             * Ariel Glenn reports that solaris can return EINVAL instead.
402
             * This should be ok
403
             */
404
0
            if (errno == EINVAL)
405
0
                is_a_tty = 0;
406
0
            else
407
0
#endif
408
0
#ifdef ENXIO
409
                /*
410
                 * Solaris can return ENXIO.
411
                 * This should be ok
412
                 */
413
0
                if (errno == ENXIO)
414
0
                    is_a_tty = 0;
415
0
                else
416
0
#endif
417
0
#ifdef EIO
418
                    /*
419
                     * Linux can return EIO.
420
                     * This should be ok
421
                     */
422
0
                    if (errno == EIO)
423
0
                        is_a_tty = 0;
424
0
                    else
425
0
#endif
426
0
#ifdef EPERM
427
                        /*
428
                         * Linux can return EPERM (Operation not permitted),
429
                         * e.g. if a daemon executes openssl via fork()+execve()
430
                         * This should be ok
431
                         */
432
0
                        if (errno == EPERM)
433
0
                            is_a_tty = 0;
434
0
                        else
435
0
#endif
436
0
#ifdef ENODEV
437
                            /*
438
                             * MacOS X returns ENODEV (Operation not supported by device),
439
                             * which seems appropriate.
440
                             */
441
0
                            if (errno == ENODEV)
442
0
                                is_a_tty = 0;
443
0
                            else
444
0
#endif
445
0
                            {
446
0
                                ERR_raise_data(ERR_LIB_UI, UI_R_UNKNOWN_TTYGET_ERRNO_VALUE,
447
0
                                    "errno=%d", errno);
448
0
                                return 0;
449
0
                            }
450
0
    }
451
0
#endif
452
#ifdef OPENSSL_SYS_VMS
453
    status = sys$assign(&terminal, &channel, 0, 0);
454
455
    /* if there isn't a TT device, something is very wrong */
456
    if (status != SS$_NORMAL) {
457
        ERR_raise_data(ERR_LIB_UI, UI_R_SYSASSIGN_ERROR,
458
            "status=%%X%08X", status);
459
        return 0;
460
    }
461
462
    status = sys$qiow(0, channel, IO$_SENSEMODE, &iosb, 0, 0, tty_orig, 12,
463
        0, 0, 0, 0);
464
465
    /* If IO$_SENSEMODE doesn't work, this is not a terminal device */
466
    if ((status != SS$_NORMAL) || (iosb.iosb$w_value != SS$_NORMAL))
467
        is_a_tty = 0;
468
#endif
469
0
    return 1;
470
0
}
471
472
static int noecho_console(UI *ui)
473
0
{
474
0
#ifdef TTY_FLAGS
475
0
    memcpy(&(tty_new), &(tty_orig), sizeof(tty_orig));
476
0
    tty_new.TTY_FLAGS &= ~ECHO;
477
0
#endif
478
479
0
#if defined(TTY_set) && !defined(OPENSSL_SYS_VMS)
480
0
    if (is_a_tty && (TTY_set(fileno(tty_in), &tty_new) == -1))
481
0
        return 0;
482
0
#endif
483
#ifdef OPENSSL_SYS_VMS
484
    if (is_a_tty) {
485
        tty_new[0] = tty_orig[0];
486
        tty_new[1] = tty_orig[1] | TT$M_NOECHO;
487
        tty_new[2] = tty_orig[2];
488
        status = sys$qiow(0, channel, IO$_SETMODE, &iosb, 0, 0, tty_new, 12,
489
            0, 0, 0, 0);
490
        if ((status != SS$_NORMAL) || (iosb.iosb$w_value != SS$_NORMAL)) {
491
            ERR_raise_data(ERR_LIB_UI, UI_R_SYSQIOW_ERROR,
492
                "status=%%X%08X, iosb.iosb$w_value=%%X%08X",
493
                status, iosb.iosb$w_value);
494
            return 0;
495
        }
496
    }
497
#endif
498
#if defined(_WIN32)
499
    if (is_a_tty) {
500
        tty_new = tty_orig;
501
        tty_new &= ~ENABLE_ECHO_INPUT;
502
        SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), tty_new);
503
    }
504
#endif
505
0
    return 1;
506
0
}
507
508
static int echo_console(UI *ui)
509
0
{
510
0
#if defined(TTY_set) && !defined(OPENSSL_SYS_VMS)
511
0
    memcpy(&(tty_new), &(tty_orig), sizeof(tty_orig));
512
0
    if (is_a_tty && (TTY_set(fileno(tty_in), &tty_new) == -1))
513
0
        return 0;
514
0
#endif
515
#ifdef OPENSSL_SYS_VMS
516
    if (is_a_tty) {
517
        tty_new[0] = tty_orig[0];
518
        tty_new[1] = tty_orig[1];
519
        tty_new[2] = tty_orig[2];
520
        status = sys$qiow(0, channel, IO$_SETMODE, &iosb, 0, 0, tty_new, 12,
521
            0, 0, 0, 0);
522
        if ((status != SS$_NORMAL) || (iosb.iosb$w_value != SS$_NORMAL)) {
523
            ERR_raise_data(ERR_LIB_UI, UI_R_SYSQIOW_ERROR,
524
                "status=%%X%08X, iosb.iosb$w_value=%%X%08X",
525
                status, iosb.iosb$w_value);
526
            return 0;
527
        }
528
    }
529
#endif
530
#if defined(_WIN32)
531
    if (is_a_tty) {
532
        tty_new = tty_orig;
533
        SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), tty_new);
534
    }
535
#endif
536
0
    return 1;
537
0
}
538
539
static int close_console(UI *ui)
540
0
{
541
0
    int ret = 1;
542
543
0
    if (tty_in != stdin)
544
0
        fclose(tty_in);
545
0
    if (tty_out != stderr)
546
0
        fclose(tty_out);
547
#ifdef OPENSSL_SYS_VMS
548
    status = sys$dassgn(channel);
549
    if (status != SS$_NORMAL) {
550
        ERR_raise_data(ERR_LIB_UI, UI_R_SYSDASSGN_ERROR,
551
            "status=%%X%08X", status);
552
        ret = 0;
553
    }
554
#endif
555
0
    CRYPTO_THREAD_unlock(ui->lock);
556
557
0
    return ret;
558
0
}
559
560
/* Internal functions to handle signals and act on them */
561
static void pushsig(void)
562
0
{
563
0
#ifndef OPENSSL_SYS_WIN32
564
0
    int i;
565
0
#endif
566
0
#ifdef SIGACTION
567
0
    struct sigaction sa;
568
569
0
    memset(&sa, 0, sizeof(sa));
570
0
    sa.sa_handler = recsig;
571
0
#endif
572
573
#ifdef OPENSSL_SYS_WIN32
574
    savsig[SIGABRT] = signal(SIGABRT, recsig);
575
    savsig[SIGFPE] = signal(SIGFPE, recsig);
576
    savsig[SIGILL] = signal(SIGILL, recsig);
577
    savsig[SIGINT] = signal(SIGINT, recsig);
578
    savsig[SIGSEGV] = signal(SIGSEGV, recsig);
579
    savsig[SIGTERM] = signal(SIGTERM, recsig);
580
#else
581
0
    for (i = 1; i < NX509_SIG; i++) {
582
0
#ifdef SIGUSR1
583
0
        if (i == SIGUSR1)
584
0
            continue;
585
0
#endif
586
0
#ifdef SIGUSR2
587
0
        if (i == SIGUSR2)
588
0
            continue;
589
0
#endif
590
0
#ifdef SIGKILL
591
0
        if (i == SIGKILL) /* We can't make any action on that. */
592
0
            continue;
593
0
#endif
594
0
#ifdef SIGACTION
595
0
        sigaction(i, &sa, &savsig[i]);
596
#else
597
        savsig[i] = signal(i, recsig);
598
#endif
599
0
    }
600
0
#endif
601
602
0
#ifdef SIGWINCH
603
0
    signal(SIGWINCH, SIG_DFL);
604
0
#endif
605
0
}
606
607
static void popsig(void)
608
0
{
609
#ifdef OPENSSL_SYS_WIN32
610
    signal(SIGABRT, savsig[SIGABRT]);
611
    signal(SIGFPE, savsig[SIGFPE]);
612
    signal(SIGILL, savsig[SIGILL]);
613
    signal(SIGINT, savsig[SIGINT]);
614
    signal(SIGSEGV, savsig[SIGSEGV]);
615
    signal(SIGTERM, savsig[SIGTERM]);
616
#else
617
0
    int i;
618
0
    for (i = 1; i < NX509_SIG; i++) {
619
0
#ifdef SIGUSR1
620
0
        if (i == SIGUSR1)
621
0
            continue;
622
0
#endif
623
0
#ifdef SIGUSR2
624
0
        if (i == SIGUSR2)
625
0
            continue;
626
0
#endif
627
0
#ifdef SIGACTION
628
0
        sigaction(i, &savsig[i], NULL);
629
#else
630
        signal(i, savsig[i]);
631
#endif
632
0
    }
633
0
#endif
634
0
}
635
636
static void recsig(int i)
637
0
{
638
0
    intr_signal = i;
639
0
}
640
641
/* Internal functions specific for Windows */
642
#if defined(OPENSSL_SYS_MSDOS) && !defined(_WIN32)
643
static int noecho_fgets(char *buf, int size, FILE *tty)
644
{
645
    int i;
646
    char *p;
647
648
    p = buf;
649
    for (;;) {
650
        if (size == 0) {
651
            *p = '\0';
652
            break;
653
        }
654
        size--;
655
        i = getch();
656
        if (i == '\r')
657
            i = '\n';
658
        *(p++) = i;
659
        if (i == '\n') {
660
            *p = '\0';
661
            break;
662
        }
663
    }
664
#ifdef WIN_CONSOLE_BUG
665
    /*
666
     * Win95 has several evil console bugs: one of these is that the last
667
     * character read using getch() is passed to the next read: this is
668
     * usually a CR so this can be trouble. No STDIO fix seems to work but
669
     * flushing the console appears to do the trick.
670
     */
671
    {
672
        HANDLE inh;
673
        inh = GetStdHandle(STD_INPUT_HANDLE);
674
        FlushConsoleInputBuffer(inh);
675
    }
676
#endif
677
    return strlen(buf);
678
}
679
#endif
680
681
static UI_METHOD ui_openssl = {
682
    "OpenSSL default user interface",
683
    open_console,
684
    write_string,
685
    NULL, /* No flusher is needed for command lines */
686
    read_string,
687
    close_console,
688
    NULL
689
};
690
691
/* The method with all the built-in console thingies */
692
UI_METHOD *UI_OpenSSL(void)
693
0
{
694
0
    return &ui_openssl;
695
0
}
696
697
static const UI_METHOD *default_UI_meth = &ui_openssl;
698
699
#else
700
701
static const UI_METHOD *default_UI_meth = NULL;
702
703
#endif
704
705
void UI_set_default_method(const UI_METHOD *meth)
706
0
{
707
0
    default_UI_meth = meth;
708
0
}
709
710
const UI_METHOD *UI_get_default_method(void)
711
0
{
712
0
    return default_UI_meth;
713
0
}