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