xref: /freebsd/crypto/openssl/crypto/ui/ui_openssl.c (revision b077aed3)
16f9291ceSJung-uk Kim /*
25ac766abSJung-uk Kim  * Copyright 2001-2022 The OpenSSL Project Authors. All Rights Reserved.
35c87c606SMark Murray  *
4b077aed3SPierre Pronchery  * Licensed under the Apache License 2.0 (the "License").  You may not use
5e71b7053SJung-uk Kim  * this file except in compliance with the License.  You can obtain a copy
6e71b7053SJung-uk Kim  * in the file LICENSE in the source distribution or at
7e71b7053SJung-uk Kim  * https://www.openssl.org/source/license.html
85c87c606SMark Murray  */
95c87c606SMark Murray 
10e71b7053SJung-uk Kim #include "e_os.h"
115c87c606SMark Murray #include <openssl/e_os2.h>
12e71b7053SJung-uk Kim #include <openssl/err.h>
13e71b7053SJung-uk Kim #include <openssl/ui.h>
145c87c606SMark Murray 
15e71b7053SJung-uk Kim #ifndef OPENSSL_NO_UI_CONSOLE
166f9291ceSJung-uk Kim /*
176f9291ceSJung-uk Kim  * need for #define _POSIX_C_SOURCE arises whenever you pass -ansi to gcc
183b4e3dcbSSimon L. B. Nielsen  * [maybe others?], because it masks interfaces not discussed in standard,
196f9291ceSJung-uk Kim  * sigaction and fileno included. -pedantic would be more appropriate for the
206f9291ceSJung-uk Kim  * intended purposes, but we can't prevent users from adding -ansi.
213b4e3dcbSSimon L. B. Nielsen  */
22e71b7053SJung-uk Kim # if defined(OPENSSL_SYS_VXWORKS)
2309286989SJung-uk Kim #  include <sys/types.h>
2409286989SJung-uk Kim # endif
2509286989SJung-uk Kim 
261f13597dSJung-uk Kim # if !defined(_POSIX_C_SOURCE) && defined(OPENSSL_SYS_VMS)
2709286989SJung-uk Kim #  ifndef _POSIX_C_SOURCE
281f13597dSJung-uk Kim #   define _POSIX_C_SOURCE 2
291f13597dSJung-uk Kim #  endif
3009286989SJung-uk Kim # endif
313b4e3dcbSSimon L. B. Nielsen # include <signal.h>
323b4e3dcbSSimon L. B. Nielsen # include <stdio.h>
333b4e3dcbSSimon L. B. Nielsen # include <string.h>
343b4e3dcbSSimon L. B. Nielsen # include <errno.h>
353b4e3dcbSSimon L. B. Nielsen 
365c87c606SMark Murray # if !defined(OPENSSL_SYS_MSDOS) && !defined(OPENSSL_SYS_VMS)
375c87c606SMark Murray #  include <unistd.h>
386f9291ceSJung-uk Kim /*
396f9291ceSJung-uk Kim  * If unistd.h defines _POSIX_VERSION, we conclude that we are on a POSIX
406f9291ceSJung-uk Kim  * system and have sigaction and termios.
416f9291ceSJung-uk Kim  */
42e71b7053SJung-uk Kim #  if defined(_POSIX_VERSION) && _POSIX_VERSION>=199309L
435c87c606SMark Murray 
445c87c606SMark Murray #   define SIGACTION
455c87c606SMark Murray #   if !defined(TERMIOS) && !defined(TERMIO) && !defined(SGTTY)
465c87c606SMark Murray #    define TERMIOS
475c87c606SMark Murray #   endif
485c87c606SMark Murray 
495c87c606SMark Murray #  endif
505c87c606SMark Murray # endif
515c87c606SMark Murray 
5217f01e99SJung-uk Kim # include "ui_local.h"
53e71b7053SJung-uk Kim # include "internal/cryptlib.h"
545c87c606SMark Murray 
555c87c606SMark Murray # ifdef OPENSSL_SYS_VMS          /* prototypes for sys$whatever */
565c87c606SMark Murray #  include <starlet.h>
575c87c606SMark Murray #  ifdef __DECC
585c87c606SMark Murray #   pragma message disable DOLLARID
595c87c606SMark Murray #  endif
605c87c606SMark Murray # endif
615c87c606SMark Murray 
625c87c606SMark Murray # ifdef WIN_CONSOLE_BUG
635c87c606SMark Murray #  include <windows.h>
645c87c606SMark Murray #  ifndef OPENSSL_SYS_WINCE
655c87c606SMark Murray #   include <wincon.h>
665c87c606SMark Murray #  endif
675c87c606SMark Murray # endif
685c87c606SMark Murray 
696f9291ceSJung-uk Kim /*
70e71b7053SJung-uk Kim  * There are 6 types of terminal interface supported, TERMIO, TERMIOS, VMS,
71e71b7053SJung-uk Kim  * MSDOS, WIN32 Console and SGTTY.
726f9291ceSJung-uk Kim  *
736f9291ceSJung-uk Kim  * If someone defines one of the macros TERMIO, TERMIOS or SGTTY, it will
746f9291ceSJung-uk Kim  * remain respected.  Otherwise, we default to TERMIOS except for a few
756f9291ceSJung-uk Kim  * systems that require something different.
766f9291ceSJung-uk Kim  *
776f9291ceSJung-uk Kim  * Note: we do not use SGTTY unless it's defined by the configuration.  We
78da327cd2SJung-uk Kim  * may eventually opt to remove its use entirely.
795c87c606SMark Murray  */
805c87c606SMark Murray 
816f9291ceSJung-uk Kim # if !defined(TERMIOS) && !defined(TERMIO) && !defined(SGTTY)
826f9291ceSJung-uk Kim 
836f9291ceSJung-uk Kim #  if defined(_LIBC)
846f9291ceSJung-uk Kim #   undef  TERMIOS
856f9291ceSJung-uk Kim #   define TERMIO
866f9291ceSJung-uk Kim #   undef  SGTTY
876f9291ceSJung-uk Kim /*
88e71b7053SJung-uk Kim  * We know that VMS, MSDOS, VXWORKS, use entirely other mechanisms.
896f9291ceSJung-uk Kim  */
906f9291ceSJung-uk Kim #  elif !defined(OPENSSL_SYS_VMS) \
916f9291ceSJung-uk Kim         && !defined(OPENSSL_SYS_MSDOS) \
92e71b7053SJung-uk Kim         && !defined(OPENSSL_SYS_VXWORKS)
935c87c606SMark Murray #   define TERMIOS
945c87c606SMark Murray #   undef  TERMIO
955c87c606SMark Murray #   undef  SGTTY
965c87c606SMark Murray #  endif
975c87c606SMark Murray 
983b4e3dcbSSimon L. B. Nielsen # endif
993b4e3dcbSSimon L. B. Nielsen 
1006935a639SJung-uk Kim # if defined(OPENSSL_SYS_VXWORKS)
1016935a639SJung-uk Kim #  undef TERMIOS
1026935a639SJung-uk Kim #  undef TERMIO
1036935a639SJung-uk Kim #  undef SGTTY
1046935a639SJung-uk Kim # endif
1056935a639SJung-uk Kim 
1065c87c606SMark Murray # ifdef TERMIOS
1075c87c606SMark Murray #  include <termios.h>
1085c87c606SMark Murray #  define TTY_STRUCT             struct termios
1095c87c606SMark Murray #  define TTY_FLAGS              c_lflag
1105c87c606SMark Murray #  define TTY_get(tty,data)      tcgetattr(tty,data)
1115c87c606SMark Murray #  define TTY_set(tty,data)      tcsetattr(tty,TCSANOW,data)
1125c87c606SMark Murray # endif
1135c87c606SMark Murray 
1145c87c606SMark Murray # ifdef TERMIO
1155c87c606SMark Murray #  include <termio.h>
1165c87c606SMark Murray #  define TTY_STRUCT             struct termio
1175c87c606SMark Murray #  define TTY_FLAGS              c_lflag
1185c87c606SMark Murray #  define TTY_get(tty,data)      ioctl(tty,TCGETA,data)
1195c87c606SMark Murray #  define TTY_set(tty,data)      ioctl(tty,TCSETA,data)
1205c87c606SMark Murray # endif
1215c87c606SMark Murray 
1225c87c606SMark Murray # ifdef SGTTY
1235c87c606SMark Murray #  include <sgtty.h>
1245c87c606SMark Murray #  define TTY_STRUCT             struct sgttyb
1255c87c606SMark Murray #  define TTY_FLAGS              sg_flags
1265c87c606SMark Murray #  define TTY_get(tty,data)      ioctl(tty,TIOCGETP,data)
1275c87c606SMark Murray #  define TTY_set(tty,data)      ioctl(tty,TIOCSETP,data)
1285c87c606SMark Murray # endif
1295c87c606SMark Murray 
130b077aed3SPierre Pronchery # if !defined(_LIBC) && !defined(OPENSSL_SYS_MSDOS) && !defined(OPENSSL_SYS_VMS) && ! (defined(OPENSSL_SYS_TANDEM) && defined(_SPT_MODEL_))
1315c87c606SMark Murray #  include <sys/ioctl.h>
1325c87c606SMark Murray # endif
1335c87c606SMark Murray 
1345c87c606SMark Murray # ifdef OPENSSL_SYS_MSDOS
1355c87c606SMark Murray #  include <conio.h>
1365c87c606SMark Murray # endif
1375c87c606SMark Murray 
1385c87c606SMark Murray # ifdef OPENSSL_SYS_VMS
1395c87c606SMark Murray #  include <ssdef.h>
1405c87c606SMark Murray #  include <iodef.h>
1415c87c606SMark Murray #  include <ttdef.h>
1425c87c606SMark Murray #  include <descrip.h>
1435c87c606SMark Murray struct IOSB {
1445c87c606SMark Murray     short iosb$w_value;
1455c87c606SMark Murray     short iosb$w_count;
1465c87c606SMark Murray     long iosb$l_info;
1475c87c606SMark Murray };
1485c87c606SMark Murray # endif
1495c87c606SMark Murray 
1505c87c606SMark Murray # ifndef NX509_SIG
1515c87c606SMark Murray #  define NX509_SIG 32
1525c87c606SMark Murray # endif
1535c87c606SMark Murray 
1545c87c606SMark Murray /* Define globals.  They are protected by a lock */
1555c87c606SMark Murray # ifdef SIGACTION
1565c87c606SMark Murray static struct sigaction savsig[NX509_SIG];
1575c87c606SMark Murray # else
1585c87c606SMark Murray static void (*savsig[NX509_SIG]) (int);
1595c87c606SMark Murray # endif
1605c87c606SMark Murray 
1615c87c606SMark Murray # ifdef OPENSSL_SYS_VMS
1625c87c606SMark Murray static struct IOSB iosb;
1635c87c606SMark Murray static $DESCRIPTOR(terminal, "TT");
1646f9291ceSJung-uk Kim static long tty_orig[3], tty_new[3]; /* XXX Is there any guarantee that this
1656f9291ceSJung-uk Kim                                       * will always suffice for the actual
1666f9291ceSJung-uk Kim                                       * structures? */
1675c87c606SMark Murray static long status;
1685c87c606SMark Murray static unsigned short channel = 0;
169e71b7053SJung-uk Kim # elif defined(_WIN32) && !defined(_WIN32_WCE)
170e71b7053SJung-uk Kim static DWORD tty_orig, tty_new;
1715c87c606SMark Murray # else
1725c87c606SMark Murray #  if !defined(OPENSSL_SYS_MSDOS) || defined(__DJGPP__)
1735c87c606SMark Murray static TTY_STRUCT tty_orig, tty_new;
1745c87c606SMark Murray #  endif
1755c87c606SMark Murray # endif
1765c87c606SMark Murray static FILE *tty_in, *tty_out;
1775c87c606SMark Murray static int is_a_tty;
1785c87c606SMark Murray 
1795c87c606SMark Murray /* Declare static functions */
180e71b7053SJung-uk Kim # if !defined(OPENSSL_SYS_WINCE)
1816a599222SSimon L. B. Nielsen static int read_till_nl(FILE *);
1825c87c606SMark Murray static void recsig(int);
1835c87c606SMark Murray static void pushsig(void);
1845c87c606SMark Murray static void popsig(void);
1855c87c606SMark Murray # endif
186e71b7053SJung-uk Kim # if defined(OPENSSL_SYS_MSDOS) && !defined(_WIN32)
1875c87c606SMark Murray static int noecho_fgets(char *buf, int size, FILE *tty);
1885c87c606SMark Murray # endif
1895c87c606SMark Murray static int read_string_inner(UI *ui, UI_STRING *uis, int echo, int strip_nl);
1905c87c606SMark Murray 
1915c87c606SMark Murray static int read_string(UI *ui, UI_STRING *uis);
1925c87c606SMark Murray static int write_string(UI *ui, UI_STRING *uis);
1935c87c606SMark Murray 
1945c87c606SMark Murray static int open_console(UI *ui);
1955c87c606SMark Murray static int echo_console(UI *ui);
1965c87c606SMark Murray static int noecho_console(UI *ui);
1975c87c606SMark Murray static int close_console(UI *ui);
1985c87c606SMark Murray 
1996f9291ceSJung-uk Kim /*
2006f9291ceSJung-uk Kim  * The following function makes sure that info and error strings are printed
2016f9291ceSJung-uk Kim  * before any prompt.
2026f9291ceSJung-uk Kim  */
write_string(UI * ui,UI_STRING * uis)2035c87c606SMark Murray static int write_string(UI *ui, UI_STRING *uis)
2045c87c606SMark Murray {
2056f9291ceSJung-uk Kim     switch (UI_get_string_type(uis)) {
2065c87c606SMark Murray     case UIT_ERROR:
2075c87c606SMark Murray     case UIT_INFO:
2085c87c606SMark Murray         fputs(UI_get0_output_string(uis), tty_out);
2095c87c606SMark Murray         fflush(tty_out);
2105c87c606SMark Murray         break;
211e71b7053SJung-uk Kim     case UIT_NONE:
212e71b7053SJung-uk Kim     case UIT_PROMPT:
213e71b7053SJung-uk Kim     case UIT_VERIFY:
214e71b7053SJung-uk Kim     case UIT_BOOLEAN:
2155c87c606SMark Murray         break;
2165c87c606SMark Murray     }
2175c87c606SMark Murray     return 1;
2185c87c606SMark Murray }
2195c87c606SMark Murray 
read_string(UI * ui,UI_STRING * uis)2205c87c606SMark Murray static int read_string(UI *ui, UI_STRING *uis)
2215c87c606SMark Murray {
2225c87c606SMark Murray     int ok = 0;
2235c87c606SMark Murray 
2246f9291ceSJung-uk Kim     switch (UI_get_string_type(uis)) {
2255c87c606SMark Murray     case UIT_BOOLEAN:
2265c87c606SMark Murray         fputs(UI_get0_output_string(uis), tty_out);
2275c87c606SMark Murray         fputs(UI_get0_action_string(uis), tty_out);
2285c87c606SMark Murray         fflush(tty_out);
2295c87c606SMark Murray         return read_string_inner(ui, uis,
2306f9291ceSJung-uk Kim                                  UI_get_input_flags(uis) & UI_INPUT_FLAG_ECHO,
2316f9291ceSJung-uk Kim                                  0);
2325c87c606SMark Murray     case UIT_PROMPT:
2335c87c606SMark Murray         fputs(UI_get0_output_string(uis), tty_out);
2345c87c606SMark Murray         fflush(tty_out);
2355c87c606SMark Murray         return read_string_inner(ui, uis,
2366f9291ceSJung-uk Kim                                  UI_get_input_flags(uis) & UI_INPUT_FLAG_ECHO,
2376f9291ceSJung-uk Kim                                  1);
2385c87c606SMark Murray     case UIT_VERIFY:
2396f9291ceSJung-uk Kim         fprintf(tty_out, "Verifying - %s", UI_get0_output_string(uis));
2405c87c606SMark Murray         fflush(tty_out);
2415c87c606SMark Murray         if ((ok = read_string_inner(ui, uis,
2426f9291ceSJung-uk Kim                                     UI_get_input_flags(uis) &
2436f9291ceSJung-uk Kim                                     UI_INPUT_FLAG_ECHO, 1)) <= 0)
2445c87c606SMark Murray             return ok;
2456f9291ceSJung-uk Kim         if (strcmp(UI_get0_result_string(uis), UI_get0_test_string(uis)) != 0) {
2465c87c606SMark Murray             fprintf(tty_out, "Verify failure\n");
2475c87c606SMark Murray             fflush(tty_out);
2485c87c606SMark Murray             return 0;
2495c87c606SMark Murray         }
2505c87c606SMark Murray         break;
251e71b7053SJung-uk Kim     case UIT_NONE:
252e71b7053SJung-uk Kim     case UIT_INFO:
253e71b7053SJung-uk Kim     case UIT_ERROR:
2545c87c606SMark Murray         break;
2555c87c606SMark Murray     }
2565c87c606SMark Murray     return 1;
2575c87c606SMark Murray }
2585c87c606SMark Murray 
259e71b7053SJung-uk Kim # if !defined(OPENSSL_SYS_WINCE)
2605c87c606SMark Murray /* Internal functions to read a string without echoing */
read_till_nl(FILE * in)2616a599222SSimon L. B. Nielsen static int read_till_nl(FILE *in)
2625c87c606SMark Murray {
2635c87c606SMark Murray #  define SIZE 4
2645c87c606SMark Murray     char buf[SIZE + 1];
2655c87c606SMark Murray 
2665c87c606SMark Murray     do {
2676a599222SSimon L. B. Nielsen         if (!fgets(buf, SIZE, in))
2686a599222SSimon L. B. Nielsen             return 0;
2695c87c606SMark Murray     } while (strchr(buf, '\n') == NULL);
2706a599222SSimon L. B. Nielsen     return 1;
2715c87c606SMark Murray }
2725c87c606SMark Murray 
2735c87c606SMark Murray static volatile sig_atomic_t intr_signal;
2745c87c606SMark Murray # endif
2755c87c606SMark Murray 
read_string_inner(UI * ui,UI_STRING * uis,int echo,int strip_nl)2765c87c606SMark Murray static int read_string_inner(UI *ui, UI_STRING *uis, int echo, int strip_nl)
2775c87c606SMark Murray {
2785c87c606SMark Murray     static int ps;
2795c87c606SMark Murray     int ok;
2805c87c606SMark Murray     char result[BUFSIZ];
2815c87c606SMark Murray     int maxsize = BUFSIZ - 1;
282e71b7053SJung-uk Kim # if !defined(OPENSSL_SYS_WINCE)
283e71b7053SJung-uk Kim     char *p = NULL;
284e71b7053SJung-uk Kim     int echo_eol = !echo;
2855c87c606SMark Murray 
2865c87c606SMark Murray     intr_signal = 0;
2875c87c606SMark Murray     ok = 0;
2885c87c606SMark Murray     ps = 0;
2895c87c606SMark Murray 
2905c87c606SMark Murray     pushsig();
2915c87c606SMark Murray     ps = 1;
2925c87c606SMark Murray 
2935c87c606SMark Murray     if (!echo && !noecho_console(ui))
2945c87c606SMark Murray         goto error;
2955c87c606SMark Murray     ps = 2;
2965c87c606SMark Murray 
2975c87c606SMark Murray     result[0] = '\0';
298e71b7053SJung-uk Kim #  if defined(_WIN32)
299e71b7053SJung-uk Kim     if (is_a_tty) {
300e71b7053SJung-uk Kim         DWORD numread;
301e71b7053SJung-uk Kim #   if defined(CP_UTF8)
302e71b7053SJung-uk Kim         if (GetEnvironmentVariableW(L"OPENSSL_WIN32_UTF8", NULL, 0) != 0) {
303e71b7053SJung-uk Kim             WCHAR wresult[BUFSIZ];
304e71b7053SJung-uk Kim 
305e71b7053SJung-uk Kim             if (ReadConsoleW(GetStdHandle(STD_INPUT_HANDLE),
306e71b7053SJung-uk Kim                          wresult, maxsize, &numread, NULL)) {
307e71b7053SJung-uk Kim                 if (numread >= 2 &&
308e71b7053SJung-uk Kim                     wresult[numread-2] == L'\r' &&
309e71b7053SJung-uk Kim                     wresult[numread-1] == L'\n') {
310e71b7053SJung-uk Kim                     wresult[numread-2] = L'\n';
311e71b7053SJung-uk Kim                     numread--;
312e71b7053SJung-uk Kim                 }
313e71b7053SJung-uk Kim                 wresult[numread] = '\0';
314e71b7053SJung-uk Kim                 if (WideCharToMultiByte(CP_UTF8, 0, wresult, -1,
315e71b7053SJung-uk Kim                                         result, sizeof(result), NULL, 0) > 0)
316e71b7053SJung-uk Kim                     p = result;
317e71b7053SJung-uk Kim 
318e71b7053SJung-uk Kim                 OPENSSL_cleanse(wresult, sizeof(wresult));
319e71b7053SJung-uk Kim             }
320e71b7053SJung-uk Kim         } else
321e71b7053SJung-uk Kim #   endif
322e71b7053SJung-uk Kim         if (ReadConsoleA(GetStdHandle(STD_INPUT_HANDLE),
323e71b7053SJung-uk Kim                          result, maxsize, &numread, NULL)) {
324e71b7053SJung-uk Kim             if (numread >= 2 &&
325e71b7053SJung-uk Kim                 result[numread-2] == '\r' && result[numread-1] == '\n') {
326e71b7053SJung-uk Kim                 result[numread-2] = '\n';
327e71b7053SJung-uk Kim                 numread--;
328e71b7053SJung-uk Kim             }
329e71b7053SJung-uk Kim             result[numread] = '\0';
330e71b7053SJung-uk Kim             p = result;
331e71b7053SJung-uk Kim         }
332e71b7053SJung-uk Kim     } else
333e71b7053SJung-uk Kim #  elif defined(OPENSSL_SYS_MSDOS)
3346f9291ceSJung-uk Kim     if (!echo) {
3355c87c606SMark Murray         noecho_fgets(result, maxsize, tty_in);
3365c87c606SMark Murray         p = result;             /* FIXME: noecho_fgets doesn't return errors */
3376f9291ceSJung-uk Kim     } else
3385c87c606SMark Murray #  endif
339e71b7053SJung-uk Kim     p = fgets(result, maxsize, tty_in);
3406cf8931aSJung-uk Kim     if (p == NULL)
3415c87c606SMark Murray         goto error;
3426f9291ceSJung-uk Kim     if (feof(tty_in))
3436f9291ceSJung-uk Kim         goto error;
3446f9291ceSJung-uk Kim     if (ferror(tty_in))
3456f9291ceSJung-uk Kim         goto error;
3466f9291ceSJung-uk Kim     if ((p = (char *)strchr(result, '\n')) != NULL) {
3475c87c606SMark Murray         if (strip_nl)
3485c87c606SMark Murray             *p = '\0';
3496f9291ceSJung-uk Kim     } else if (!read_till_nl(tty_in))
3506a599222SSimon L. B. Nielsen         goto error;
3515c87c606SMark Murray     if (UI_set_result(ui, uis, result) >= 0)
3525c87c606SMark Murray         ok = 1;
3535c87c606SMark Murray 
3545c87c606SMark Murray  error:
3555c87c606SMark Murray     if (intr_signal == SIGINT)
3565c87c606SMark Murray         ok = -1;
357e71b7053SJung-uk Kim     if (echo_eol)
3586f9291ceSJung-uk Kim         fprintf(tty_out, "\n");
3595c87c606SMark Murray     if (ps >= 2 && !echo && !echo_console(ui))
3605c87c606SMark Murray         ok = 0;
3615c87c606SMark Murray 
3625c87c606SMark Murray     if (ps >= 1)
3635c87c606SMark Murray         popsig();
3645c87c606SMark Murray # else
3655c87c606SMark Murray     ok = 1;
3665c87c606SMark Murray # endif
3675c87c606SMark Murray 
3685c87c606SMark Murray     OPENSSL_cleanse(result, BUFSIZ);
3695c87c606SMark Murray     return ok;
3705c87c606SMark Murray }
3715c87c606SMark Murray 
3725c87c606SMark Murray /* Internal functions to open, handle and close a channel to the console.  */
open_console(UI * ui)3735c87c606SMark Murray static int open_console(UI *ui)
3745c87c606SMark Murray {
375b077aed3SPierre Pronchery     if (!CRYPTO_THREAD_write_lock(ui->lock))
376b077aed3SPierre Pronchery         return 0;
3775c87c606SMark Murray     is_a_tty = 1;
3785c87c606SMark Murray 
379e71b7053SJung-uk Kim # if defined(OPENSSL_SYS_VXWORKS)
3805c87c606SMark Murray     tty_in = stdin;
3815c87c606SMark Murray     tty_out = stderr;
382e71b7053SJung-uk Kim # elif defined(_WIN32) && !defined(_WIN32_WCE)
383e71b7053SJung-uk Kim     if ((tty_out = fopen("conout$", "w")) == NULL)
384e71b7053SJung-uk Kim         tty_out = stderr;
385e71b7053SJung-uk Kim 
386e71b7053SJung-uk Kim     if (GetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), &tty_orig)) {
387e71b7053SJung-uk Kim         tty_in = stdin;
388e71b7053SJung-uk Kim     } else {
389e71b7053SJung-uk Kim         is_a_tty = 0;
390e71b7053SJung-uk Kim         if ((tty_in = fopen("conin$", "r")) == NULL)
391e71b7053SJung-uk Kim             tty_in = stdin;
392e71b7053SJung-uk Kim     }
3935c87c606SMark Murray # else
3945c87c606SMark Murray #  ifdef OPENSSL_SYS_MSDOS
3955c87c606SMark Murray #   define DEV_TTY "con"
3965c87c606SMark Murray #  else
3975c87c606SMark Murray #   define DEV_TTY "/dev/tty"
3985c87c606SMark Murray #  endif
3995c87c606SMark Murray     if ((tty_in = fopen(DEV_TTY, "r")) == NULL)
4005c87c606SMark Murray         tty_in = stdin;
4015c87c606SMark Murray     if ((tty_out = fopen(DEV_TTY, "w")) == NULL)
4025c87c606SMark Murray         tty_out = stderr;
4035c87c606SMark Murray # endif
4045c87c606SMark Murray 
4055c87c606SMark Murray # if defined(TTY_get) && !defined(OPENSSL_SYS_VMS)
4066f9291ceSJung-uk Kim     if (TTY_get(fileno(tty_in), &tty_orig) == -1) {
4075c87c606SMark Murray #  ifdef ENOTTY
4085c87c606SMark Murray         if (errno == ENOTTY)
4095c87c606SMark Murray             is_a_tty = 0;
4105c87c606SMark Murray         else
4115c87c606SMark Murray #  endif
4125c87c606SMark Murray #  ifdef EINVAL
4136f9291ceSJung-uk Kim             /*
414e71b7053SJung-uk Kim              * Ariel Glenn reports that solaris can return EINVAL instead.
415e71b7053SJung-uk Kim              * This should be ok
4166f9291ceSJung-uk Kim              */
4175c87c606SMark Murray         if (errno == EINVAL)
4185c87c606SMark Murray             is_a_tty = 0;
4195c87c606SMark Murray         else
4205c87c606SMark Murray #  endif
421c9cf7b5cSJung-uk Kim #  ifdef ENXIO
422c9cf7b5cSJung-uk Kim             /*
423c9cf7b5cSJung-uk Kim              * Solaris can return ENXIO.
424c9cf7b5cSJung-uk Kim              * This should be ok
425c9cf7b5cSJung-uk Kim              */
426c9cf7b5cSJung-uk Kim         if (errno == ENXIO)
427c9cf7b5cSJung-uk Kim             is_a_tty = 0;
428c9cf7b5cSJung-uk Kim         else
429c9cf7b5cSJung-uk Kim #  endif
430c9cf7b5cSJung-uk Kim #  ifdef EIO
431c9cf7b5cSJung-uk Kim             /*
432c9cf7b5cSJung-uk Kim              * Linux can return EIO.
433c9cf7b5cSJung-uk Kim              * This should be ok
434c9cf7b5cSJung-uk Kim              */
435c9cf7b5cSJung-uk Kim         if (errno == EIO)
436c9cf7b5cSJung-uk Kim             is_a_tty = 0;
437c9cf7b5cSJung-uk Kim         else
438c9cf7b5cSJung-uk Kim #  endif
43958f35182SJung-uk Kim #  ifdef EPERM
44058f35182SJung-uk Kim             /*
44158f35182SJung-uk Kim              * Linux can return EPERM (Operation not permitted),
44258f35182SJung-uk Kim              * e.g. if a daemon executes openssl via fork()+execve()
44358f35182SJung-uk Kim              * This should be ok
44458f35182SJung-uk Kim              */
44558f35182SJung-uk Kim         if (errno == EPERM)
44658f35182SJung-uk Kim             is_a_tty = 0;
44758f35182SJung-uk Kim         else
44858f35182SJung-uk Kim #  endif
4496cf8931aSJung-uk Kim #  ifdef ENODEV
4506cf8931aSJung-uk Kim             /*
4516cf8931aSJung-uk Kim              * MacOS X returns ENODEV (Operation not supported by device),
4526cf8931aSJung-uk Kim              * which seems appropriate.
4536cf8931aSJung-uk Kim              */
4546cf8931aSJung-uk Kim         if (errno == ENODEV)
4556cf8931aSJung-uk Kim                 is_a_tty = 0;
4566cf8931aSJung-uk Kim         else
4576cf8931aSJung-uk Kim #  endif
458e71b7053SJung-uk Kim             {
459b077aed3SPierre Pronchery                 ERR_raise_data(ERR_LIB_UI, UI_R_UNKNOWN_TTYGET_ERRNO_VALUE,
460b077aed3SPierre Pronchery                                "errno=%d", errno);
4615c87c606SMark Murray                 return 0;
4625c87c606SMark Murray             }
463e71b7053SJung-uk Kim     }
4645c87c606SMark Murray # endif
4655c87c606SMark Murray # ifdef OPENSSL_SYS_VMS
4665c87c606SMark Murray     status = sys$assign(&terminal, &channel, 0, 0);
4676cf8931aSJung-uk Kim 
4686cf8931aSJung-uk Kim     /* if there isn't a TT device, something is very wrong */
469e71b7053SJung-uk Kim     if (status != SS$_NORMAL) {
470b077aed3SPierre Pronchery         ERR_raise_data(ERR_LIB_UI, UI_R_SYSASSIGN_ERROR,
471b077aed3SPierre Pronchery                        "status=%%X%08X", status);
4725c87c606SMark Murray         return 0;
473e71b7053SJung-uk Kim     }
4746cf8931aSJung-uk Kim 
4756cf8931aSJung-uk Kim     status = sys$qiow(0, channel, IO$_SENSEMODE, &iosb, 0, 0, tty_orig, 12,
4766cf8931aSJung-uk Kim                       0, 0, 0, 0);
4776cf8931aSJung-uk Kim 
4786cf8931aSJung-uk Kim     /* If IO$_SENSEMODE doesn't work, this is not a terminal device */
4795c87c606SMark Murray     if ((status != SS$_NORMAL) || (iosb.iosb$w_value != SS$_NORMAL))
4806cf8931aSJung-uk Kim         is_a_tty = 0;
4815c87c606SMark Murray # endif
4825c87c606SMark Murray     return 1;
4835c87c606SMark Murray }
4845c87c606SMark Murray 
noecho_console(UI * ui)4855c87c606SMark Murray static int noecho_console(UI *ui)
4865c87c606SMark Murray {
4875c87c606SMark Murray # ifdef TTY_FLAGS
4885c87c606SMark Murray     memcpy(&(tty_new), &(tty_orig), sizeof(tty_orig));
4895c87c606SMark Murray     tty_new.TTY_FLAGS &= ~ECHO;
4905c87c606SMark Murray # endif
4915c87c606SMark Murray 
4925c87c606SMark Murray # if defined(TTY_set) && !defined(OPENSSL_SYS_VMS)
4935c87c606SMark Murray     if (is_a_tty && (TTY_set(fileno(tty_in), &tty_new) == -1))
4945c87c606SMark Murray         return 0;
4955c87c606SMark Murray # endif
4965c87c606SMark Murray # ifdef OPENSSL_SYS_VMS
4976cf8931aSJung-uk Kim     if (is_a_tty) {
4985c87c606SMark Murray         tty_new[0] = tty_orig[0];
4995c87c606SMark Murray         tty_new[1] = tty_orig[1] | TT$M_NOECHO;
5005c87c606SMark Murray         tty_new[2] = tty_orig[2];
5016cf8931aSJung-uk Kim         status = sys$qiow(0, channel, IO$_SETMODE, &iosb, 0, 0, tty_new, 12,
5026cf8931aSJung-uk Kim                           0, 0, 0, 0);
503e71b7053SJung-uk Kim         if ((status != SS$_NORMAL) || (iosb.iosb$w_value != SS$_NORMAL)) {
504b077aed3SPierre Pronchery             ERR_raise_data(ERR_LIB_UI, UI_R_SYSQIOW_ERROR,
505b077aed3SPierre Pronchery                            "status=%%X%08X, iosb.iosb$w_value=%%X%08X",
506b077aed3SPierre Pronchery                            status, iosb.iosb$w_value);
5075c87c606SMark Murray             return 0;
5086cf8931aSJung-uk Kim         }
509e71b7053SJung-uk Kim     }
510e71b7053SJung-uk Kim # endif
511e71b7053SJung-uk Kim # if defined(_WIN32) && !defined(_WIN32_WCE)
512e71b7053SJung-uk Kim     if (is_a_tty) {
513e71b7053SJung-uk Kim         tty_new = tty_orig;
514e71b7053SJung-uk Kim         tty_new &= ~ENABLE_ECHO_INPUT;
515e71b7053SJung-uk Kim         SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), tty_new);
516e71b7053SJung-uk Kim     }
5175c87c606SMark Murray # endif
5185c87c606SMark Murray     return 1;
5195c87c606SMark Murray }
5205c87c606SMark Murray 
echo_console(UI * ui)5215c87c606SMark Murray static int echo_console(UI *ui)
5225c87c606SMark Murray {
5235c87c606SMark Murray # if defined(TTY_set) && !defined(OPENSSL_SYS_VMS)
5245c87c606SMark Murray     memcpy(&(tty_new), &(tty_orig), sizeof(tty_orig));
5255c87c606SMark Murray     if (is_a_tty && (TTY_set(fileno(tty_in), &tty_new) == -1))
5265c87c606SMark Murray         return 0;
5275c87c606SMark Murray # endif
5285c87c606SMark Murray # ifdef OPENSSL_SYS_VMS
5296cf8931aSJung-uk Kim     if (is_a_tty) {
5305c87c606SMark Murray         tty_new[0] = tty_orig[0];
531dea77ea6SJung-uk Kim         tty_new[1] = tty_orig[1];
5325c87c606SMark Murray         tty_new[2] = tty_orig[2];
5336cf8931aSJung-uk Kim         status = sys$qiow(0, channel, IO$_SETMODE, &iosb, 0, 0, tty_new, 12,
5346cf8931aSJung-uk Kim                           0, 0, 0, 0);
535e71b7053SJung-uk Kim         if ((status != SS$_NORMAL) || (iosb.iosb$w_value != SS$_NORMAL)) {
536b077aed3SPierre Pronchery             ERR_raise_data(ERR_LIB_UI, UI_R_SYSQIOW_ERROR,
537b077aed3SPierre Pronchery                            "status=%%X%08X, iosb.iosb$w_value=%%X%08X",
538b077aed3SPierre Pronchery                            status, iosb.iosb$w_value);
5395c87c606SMark Murray             return 0;
5406cf8931aSJung-uk Kim         }
541e71b7053SJung-uk Kim     }
542e71b7053SJung-uk Kim # endif
543e71b7053SJung-uk Kim # if defined(_WIN32) && !defined(_WIN32_WCE)
544e71b7053SJung-uk Kim     if (is_a_tty) {
545e71b7053SJung-uk Kim         tty_new = tty_orig;
546e71b7053SJung-uk Kim         SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), tty_new);
547e71b7053SJung-uk Kim     }
5485c87c606SMark Murray # endif
5495c87c606SMark Murray     return 1;
5505c87c606SMark Murray }
5515c87c606SMark Murray 
close_console(UI * ui)5525c87c606SMark Murray static int close_console(UI *ui)
5535c87c606SMark Murray {
5545ac766abSJung-uk Kim     int ret = 1;
5555ac766abSJung-uk Kim 
5566f9291ceSJung-uk Kim     if (tty_in != stdin)
5576f9291ceSJung-uk Kim         fclose(tty_in);
5586f9291ceSJung-uk Kim     if (tty_out != stderr)
5596f9291ceSJung-uk Kim         fclose(tty_out);
5605c87c606SMark Murray # ifdef OPENSSL_SYS_VMS
5615c87c606SMark Murray     status = sys$dassgn(channel);
562e71b7053SJung-uk Kim     if (status != SS$_NORMAL) {
563b077aed3SPierre Pronchery         ERR_raise_data(ERR_LIB_UI, UI_R_SYSDASSGN_ERROR,
564b077aed3SPierre Pronchery                        "status=%%X%08X", status);
5655ac766abSJung-uk Kim         ret = 0;
566e71b7053SJung-uk Kim     }
5675c87c606SMark Murray # endif
568e71b7053SJung-uk Kim     CRYPTO_THREAD_unlock(ui->lock);
5695c87c606SMark Murray 
5705ac766abSJung-uk Kim     return ret;
5715c87c606SMark Murray }
5725c87c606SMark Murray 
573e71b7053SJung-uk Kim # if !defined(OPENSSL_SYS_WINCE)
5745c87c606SMark Murray /* Internal functions to handle signals and act on them */
pushsig(void)5755c87c606SMark Murray static void pushsig(void)
5765c87c606SMark Murray {
5773b4e3dcbSSimon L. B. Nielsen #  ifndef OPENSSL_SYS_WIN32
5785c87c606SMark Murray     int i;
5793b4e3dcbSSimon L. B. Nielsen #  endif
5805c87c606SMark Murray #  ifdef SIGACTION
5815c87c606SMark Murray     struct sigaction sa;
5825c87c606SMark Murray 
583dee36b4fSJung-uk Kim     memset(&sa, 0, sizeof(sa));
5845c87c606SMark Murray     sa.sa_handler = recsig;
5855c87c606SMark Murray #  endif
5865c87c606SMark Murray 
5873b4e3dcbSSimon L. B. Nielsen #  ifdef OPENSSL_SYS_WIN32
5883b4e3dcbSSimon L. B. Nielsen     savsig[SIGABRT] = signal(SIGABRT, recsig);
5893b4e3dcbSSimon L. B. Nielsen     savsig[SIGFPE] = signal(SIGFPE, recsig);
5903b4e3dcbSSimon L. B. Nielsen     savsig[SIGILL] = signal(SIGILL, recsig);
5913b4e3dcbSSimon L. B. Nielsen     savsig[SIGINT] = signal(SIGINT, recsig);
5923b4e3dcbSSimon L. B. Nielsen     savsig[SIGSEGV] = signal(SIGSEGV, recsig);
5933b4e3dcbSSimon L. B. Nielsen     savsig[SIGTERM] = signal(SIGTERM, recsig);
5943b4e3dcbSSimon L. B. Nielsen #  else
5956f9291ceSJung-uk Kim     for (i = 1; i < NX509_SIG; i++) {
5965c87c606SMark Murray #   ifdef SIGUSR1
5975c87c606SMark Murray         if (i == SIGUSR1)
5985c87c606SMark Murray             continue;
5995c87c606SMark Murray #   endif
6005c87c606SMark Murray #   ifdef SIGUSR2
6015c87c606SMark Murray         if (i == SIGUSR2)
6025c87c606SMark Murray             continue;
6035c87c606SMark Murray #   endif
6045c87c606SMark Murray #   ifdef SIGKILL
6055c87c606SMark Murray         if (i == SIGKILL)       /* We can't make any action on that. */
6065c87c606SMark Murray             continue;
6075c87c606SMark Murray #   endif
6085c87c606SMark Murray #   ifdef SIGACTION
6095c87c606SMark Murray         sigaction(i, &sa, &savsig[i]);
6105c87c606SMark Murray #   else
6115c87c606SMark Murray         savsig[i] = signal(i, recsig);
6125c87c606SMark Murray #   endif
6135c87c606SMark Murray     }
6143b4e3dcbSSimon L. B. Nielsen #  endif
6155c87c606SMark Murray 
6165c87c606SMark Murray #  ifdef SIGWINCH
6175c87c606SMark Murray     signal(SIGWINCH, SIG_DFL);
6185c87c606SMark Murray #  endif
6195c87c606SMark Murray }
6205c87c606SMark Murray 
popsig(void)6215c87c606SMark Murray static void popsig(void)
6225c87c606SMark Murray {
6233b4e3dcbSSimon L. B. Nielsen #  ifdef OPENSSL_SYS_WIN32
6243b4e3dcbSSimon L. B. Nielsen     signal(SIGABRT, savsig[SIGABRT]);
6253b4e3dcbSSimon L. B. Nielsen     signal(SIGFPE, savsig[SIGFPE]);
6263b4e3dcbSSimon L. B. Nielsen     signal(SIGILL, savsig[SIGILL]);
6273b4e3dcbSSimon L. B. Nielsen     signal(SIGINT, savsig[SIGINT]);
6283b4e3dcbSSimon L. B. Nielsen     signal(SIGSEGV, savsig[SIGSEGV]);
6293b4e3dcbSSimon L. B. Nielsen     signal(SIGTERM, savsig[SIGTERM]);
6303b4e3dcbSSimon L. B. Nielsen #  else
6315c87c606SMark Murray     int i;
6326f9291ceSJung-uk Kim     for (i = 1; i < NX509_SIG; i++) {
6335c87c606SMark Murray #   ifdef SIGUSR1
6345c87c606SMark Murray         if (i == SIGUSR1)
6355c87c606SMark Murray             continue;
6365c87c606SMark Murray #   endif
6375c87c606SMark Murray #   ifdef SIGUSR2
6385c87c606SMark Murray         if (i == SIGUSR2)
6395c87c606SMark Murray             continue;
6405c87c606SMark Murray #   endif
6415c87c606SMark Murray #   ifdef SIGACTION
6425c87c606SMark Murray         sigaction(i, &savsig[i], NULL);
6435c87c606SMark Murray #   else
6445c87c606SMark Murray         signal(i, savsig[i]);
6455c87c606SMark Murray #   endif
6465c87c606SMark Murray     }
6473b4e3dcbSSimon L. B. Nielsen #  endif
6485c87c606SMark Murray }
6495c87c606SMark Murray 
recsig(int i)6505c87c606SMark Murray static void recsig(int i)
6515c87c606SMark Murray {
6525c87c606SMark Murray     intr_signal = i;
6535c87c606SMark Murray }
6545c87c606SMark Murray # endif
6555c87c606SMark Murray 
6565c87c606SMark Murray /* Internal functions specific for Windows */
657e71b7053SJung-uk Kim # if defined(OPENSSL_SYS_MSDOS) && !defined(_WIN32)
noecho_fgets(char * buf,int size,FILE * tty)6585c87c606SMark Murray static int noecho_fgets(char *buf, int size, FILE *tty)
6595c87c606SMark Murray {
6605c87c606SMark Murray     int i;
6615c87c606SMark Murray     char *p;
6625c87c606SMark Murray 
6635c87c606SMark Murray     p = buf;
6646f9291ceSJung-uk Kim     for (;;) {
6656f9291ceSJung-uk Kim         if (size == 0) {
6665c87c606SMark Murray             *p = '\0';
6675c87c606SMark Murray             break;
6685c87c606SMark Murray         }
6695c87c606SMark Murray         size--;
670e71b7053SJung-uk Kim #  if defined(_WIN32)
671db522d3aSSimon L. B. Nielsen         i = _getch();
6725c87c606SMark Murray #  else
6735c87c606SMark Murray         i = getch();
6745c87c606SMark Murray #  endif
6756f9291ceSJung-uk Kim         if (i == '\r')
6766f9291ceSJung-uk Kim             i = '\n';
6775c87c606SMark Murray         *(p++) = i;
6786f9291ceSJung-uk Kim         if (i == '\n') {
6795c87c606SMark Murray             *p = '\0';
6805c87c606SMark Murray             break;
6815c87c606SMark Murray         }
6825c87c606SMark Murray     }
6835c87c606SMark Murray #  ifdef WIN_CONSOLE_BUG
6846f9291ceSJung-uk Kim     /*
6856f9291ceSJung-uk Kim      * Win95 has several evil console bugs: one of these is that the last
6866f9291ceSJung-uk Kim      * character read using getch() is passed to the next read: this is
6875c87c606SMark Murray      * usually a CR so this can be trouble. No STDIO fix seems to work but
6885c87c606SMark Murray      * flushing the console appears to do the trick.
6895c87c606SMark Murray      */
6905c87c606SMark Murray     {
6915c87c606SMark Murray         HANDLE inh;
6925c87c606SMark Murray         inh = GetStdHandle(STD_INPUT_HANDLE);
6935c87c606SMark Murray         FlushConsoleInputBuffer(inh);
6945c87c606SMark Murray     }
6955c87c606SMark Murray #  endif
696e71b7053SJung-uk Kim     return strlen(buf);
6975c87c606SMark Murray }
6985c87c606SMark Murray # endif
699e71b7053SJung-uk Kim 
700e71b7053SJung-uk Kim static UI_METHOD ui_openssl = {
701e71b7053SJung-uk Kim     "OpenSSL default user interface",
702e71b7053SJung-uk Kim     open_console,
703e71b7053SJung-uk Kim     write_string,
704e71b7053SJung-uk Kim     NULL,                       /* No flusher is needed for command lines */
705e71b7053SJung-uk Kim     read_string,
706e71b7053SJung-uk Kim     close_console,
707e71b7053SJung-uk Kim     NULL
708e71b7053SJung-uk Kim };
709e71b7053SJung-uk Kim 
710e71b7053SJung-uk Kim /* The method with all the built-in console thingies */
UI_OpenSSL(void)711e71b7053SJung-uk Kim UI_METHOD *UI_OpenSSL(void)
712e71b7053SJung-uk Kim {
713e71b7053SJung-uk Kim     return &ui_openssl;
714e71b7053SJung-uk Kim }
715e71b7053SJung-uk Kim 
716e71b7053SJung-uk Kim static const UI_METHOD *default_UI_meth = &ui_openssl;
717e71b7053SJung-uk Kim 
718e71b7053SJung-uk Kim #else
719e71b7053SJung-uk Kim 
720e71b7053SJung-uk Kim static const UI_METHOD *default_UI_meth = NULL;
721e71b7053SJung-uk Kim 
722e71b7053SJung-uk Kim #endif
723e71b7053SJung-uk Kim 
UI_set_default_method(const UI_METHOD * meth)724e71b7053SJung-uk Kim void UI_set_default_method(const UI_METHOD *meth)
725e71b7053SJung-uk Kim {
726e71b7053SJung-uk Kim     default_UI_meth = meth;
727e71b7053SJung-uk Kim }
728e71b7053SJung-uk Kim 
UI_get_default_method(void)729e71b7053SJung-uk Kim const UI_METHOD *UI_get_default_method(void)
730e71b7053SJung-uk Kim {
731e71b7053SJung-uk Kim     return default_UI_meth;
732e71b7053SJung-uk Kim }
733