142421Syokota/*
242421Syokota * Copyright 2001-2022 The OpenSSL Project Authors. All Rights Reserved.
342421Syokota *
442421Syokota * Licensed under the OpenSSL license (the "License").  You may not use
542421Syokota * this file except in compliance with the License.  You can obtain a copy
642421Syokota * in the file LICENSE in the source distribution or at
742421Syokota * https://www.openssl.org/source/license.html
842421Syokota */
942421Syokota
1042421Syokota#include "e_os.h"
1142421Syokota#include <openssl/e_os2.h>
1242421Syokota#include <openssl/err.h>
1342421Syokota#include <openssl/ui.h>
1442421Syokota
1542421Syokota#ifndef OPENSSL_NO_UI_CONSOLE
1642421Syokota/*
1742421Syokota * need for #define _POSIX_C_SOURCE arises whenever you pass -ansi to gcc
1842421Syokota * [maybe others?], because it masks interfaces not discussed in standard,
1942421Syokota * sigaction and fileno included. -pedantic would be more appropriate for the
2042421Syokota * intended purposes, but we can't prevent users from adding -ansi.
2142421Syokota */
2242421Syokota# if defined(OPENSSL_SYS_VXWORKS)
2342421Syokota#  include <sys/types.h>
2442421Syokota# endif
2542421Syokota
2642421Syokota# if !defined(_POSIX_C_SOURCE) && defined(OPENSSL_SYS_VMS)
2742421Syokota#  ifndef _POSIX_C_SOURCE
2842421Syokota#   define _POSIX_C_SOURCE 2
2942421Syokota#  endif
3042421Syokota# endif
3142421Syokota# include <signal.h>
3242421Syokota# include <stdio.h>
33119418Sobrien# include <string.h>
34119418Sobrien# include <errno.h>
35119418Sobrien
3642421Syokota# if !defined(OPENSSL_SYS_MSDOS) && !defined(OPENSSL_SYS_VMS)
3742421Syokota#  ifdef OPENSSL_UNISTD
3842421Syokota#   include OPENSSL_UNISTD
3942421Syokota#  else
4058271Syokota#   include <unistd.h>
4142421Syokota#  endif
4242421Syokota/*
4358271Syokota * If unistd.h defines _POSIX_VERSION, we conclude that we are on a POSIX
4458271Syokota * system and have sigaction and termios.
4558271Syokota */
4642421Syokota#  if defined(_POSIX_VERSION) && _POSIX_VERSION>=199309L
47147271Smarius
4842421Syokota#   define SIGACTION
49147271Smarius#   if !defined(TERMIOS) && !defined(TERMIO) && !defined(SGTTY)
50147271Smarius#    define TERMIOS
51147271Smarius#   endif
52147271Smarius
53147271Smarius#  endif
5442421Syokota# endif
55147271Smarius
5642421Syokota# include "ui_local.h"
5742421Syokota# include "internal/cryptlib.h"
5842421Syokota
59102149Speter# ifdef OPENSSL_SYS_VMS          /* prototypes for sys$whatever */
6042421Syokota#  include <starlet.h>
6142421Syokota#  ifdef __DECC
6242421Syokota#   pragma message disable DOLLARID
6342421Syokota#  endif
6442421Syokota# endif
6542421Syokota
6642421Syokota# ifdef WIN_CONSOLE_BUG
6742421Syokota#  include <windows.h>
6842421Syokota#  ifndef OPENSSL_SYS_WINCE
6942421Syokota#   include <wincon.h>
7042421Syokota#  endif
7142421Syokota# endif
7242421Syokota
7342421Syokota/*
7442421Syokota * There are 6 types of terminal interface supported, TERMIO, TERMIOS, VMS,
7542421Syokota * MSDOS, WIN32 Console and SGTTY.
7658271Syokota *
7758271Syokota * If someone defines one of the macros TERMIO, TERMIOS or SGTTY, it will
7858271Syokota * remain respected.  Otherwise, we default to TERMIOS except for a few
7958271Syokota * systems that require something different.
8058271Syokota *
8158271Syokota * Note: we do not use SGTTY unless it's defined by the configuration.  We
8258271Syokota * may eventually opt to remove its use entirely.
8342421Syokota */
8442421Syokota
8542421Syokota# if !defined(TERMIOS) && !defined(TERMIO) && !defined(SGTTY)
8642421Syokota
8742421Syokota#  if defined(_LIBC)
8842421Syokota#   undef  TERMIOS
8942421Syokota#   define TERMIO
9042421Syokota#   undef  SGTTY
9142421Syokota/*
9242421Syokota * We know that VMS, MSDOS, VXWORKS, use entirely other mechanisms.
9342421Syokota */
9442421Syokota#  elif !defined(OPENSSL_SYS_VMS) \
9542421Syokota	&& !defined(OPENSSL_SYS_MSDOS) \
96147271Smarius	&& !defined(OPENSSL_SYS_VXWORKS)
97147271Smarius#   define TERMIOS
98147271Smarius#   undef  TERMIO
99147271Smarius#   undef  SGTTY
10042421Syokota#  endif
10142421Syokota
10258271Syokota# endif
10358271Syokota
10442421Syokota# if defined(OPENSSL_SYS_VXWORKS)
10542421Syokota#  undef TERMIOS
10642421Syokota#  undef TERMIO
10742421Syokota#  undef SGTTY
10842421Syokota# endif
10942421Syokota
11042421Syokota# ifdef TERMIOS
11142421Syokota#  include <termios.h>
11242421Syokota#  define TTY_STRUCT             struct termios
11342421Syokota#  define TTY_FLAGS              c_lflag
11442421Syokota#  define TTY_get(tty,data)      tcgetattr(tty,data)
11542421Syokota#  define TTY_set(tty,data)      tcsetattr(tty,TCSANOW,data)
11642421Syokota# endif
11742421Syokota
11842421Syokota# ifdef TERMIO
11942421Syokota#  include <termio.h>
12042421Syokota#  define TTY_STRUCT             struct termio
12142421Syokota#  define TTY_FLAGS              c_lflag
12242421Syokota#  define TTY_get(tty,data)      ioctl(tty,TCGETA,data)
12369781Sdwmalone#  define TTY_set(tty,data)      ioctl(tty,TCSETA,data)
12442421Syokota# endif
12542421Syokota
12642421Syokota# ifdef SGTTY
12742421Syokota#  include <sgtty.h>
12842421Syokota#  define TTY_STRUCT             struct sgttyb
12942421Syokota#  define TTY_FLAGS              sg_flags
13042421Syokota#  define TTY_get(tty,data)      ioctl(tty,TIOCGETP,data)
13158271Syokota#  define TTY_set(tty,data)      ioctl(tty,TIOCSETP,data)
13242421Syokota# endif
13358271Syokota
13447296Syokota# if !defined(_LIBC) && !defined(OPENSSL_SYS_MSDOS) && !defined(OPENSSL_SYS_VMS)
13558271Syokota#  include <sys/ioctl.h>
13658271Syokota# endif
13747296Syokota
13847296Syokota# ifdef OPENSSL_SYS_MSDOS
13947296Syokota#  include <conio.h>
14047296Syokota# endif
14158271Syokota
14258271Syokota# ifdef OPENSSL_SYS_VMS
14347296Syokota#  include <ssdef.h>
14458271Syokota#  include <iodef.h>
14558271Syokota#  include <ttdef.h>
14658271Syokota#  include <descrip.h>
14742421Syokotastruct IOSB {
14842421Syokota    short iosb$w_value;
14942421Syokota    short iosb$w_count;
15042421Syokota    long iosb$l_info;
15142421Syokota};
15242421Syokota# endif
15358271Syokota
15458271Syokota# ifndef NX509_SIG
15558271Syokota#  define NX509_SIG 32
156158041Ssobomax# endif
157158041Ssobomax
158158041Ssobomax/* Define globals.  They are protected by a lock */
159158041Ssobomax# ifdef SIGACTION
160147271Smariusstatic struct sigaction savsig[NX509_SIG];
161147271Smarius# else
162147271Smariusstatic void (*savsig[NX509_SIG]) (int);
163147271Smarius# endif
164147271Smarius
165147271Smarius# ifdef OPENSSL_SYS_VMS
166147271Smariusstatic struct IOSB iosb;
167147271Smariusstatic $DESCRIPTOR(terminal, "TT");
16858271Syokotastatic long tty_orig[3], tty_new[3]; /* XXX Is there any guarantee that this
16958271Syokota                                      * will always suffice for the actual
17058271Syokota                                      * structures? */
17158271Syokotastatic long status;
17258271Syokotastatic unsigned short channel = 0;
173114930Speter# elif defined(_WIN32) && !defined(_WIN32_WCE)
17458271Syokotastatic DWORD tty_orig, tty_new;
175114930Speter# else
176114930Speter#  if !defined(OPENSSL_SYS_MSDOS) || defined(__DJGPP__)
17758271Syokotastatic TTY_STRUCT tty_orig, tty_new;
17865176Sdfr#  endif
17992661Speter# endif
18092661Speterstatic FILE *tty_in, *tty_out;
181147271Smariusstatic int is_a_tty;
182147271Smarius
18392661Speter/* Declare static functions */
18492661Speter# if !defined(OPENSSL_SYS_WINCE)
18558271Syokotastatic int read_till_nl(FILE *);
18658271Syokotastatic void recsig(int);
187147271Smariusstatic void pushsig(void);
188147271Smariusstatic void popsig(void);
189147271Smarius# endif
190147271Smarius# if defined(OPENSSL_SYS_MSDOS) && !defined(_WIN32)
191147271Smariusstatic int noecho_fgets(char *buf, int size, FILE *tty);
192147271Smarius# endif
193147271Smariusstatic int read_string_inner(UI *ui, UI_STRING *uis, int echo, int strip_nl);
194147271Smarius
195147271Smariusstatic int read_string(UI *ui, UI_STRING *uis);
196147271Smariusstatic int write_string(UI *ui, UI_STRING *uis);
197147271Smarius
198147271Smariusstatic int open_console(UI *ui);
199147271Smariusstatic int echo_console(UI *ui);
200147271Smariusstatic int noecho_console(UI *ui);
201147271Smariusstatic int close_console(UI *ui);
202147271Smarius
203147271Smarius/*
204147271Smarius * The following function makes sure that info and error strings are printed
205147271Smarius * before any prompt.
206147271Smarius */
207147271Smariusstatic int write_string(UI *ui, UI_STRING *uis)
208147271Smarius{
209147271Smarius    switch (UI_get_string_type(uis)) {
210147271Smarius    case UIT_ERROR:
211147271Smarius    case UIT_INFO:
212147271Smarius        fputs(UI_get0_output_string(uis), tty_out);
213147271Smarius        fflush(tty_out);
214147271Smarius        break;
215147271Smarius    case UIT_NONE:
216147271Smarius    case UIT_PROMPT:
217147271Smarius    case UIT_VERIFY:
218153072Sru    case UIT_BOOLEAN:
21958271Syokota        break;
22058271Syokota    }
22158271Syokota    return 1;
22258271Syokota}
22358271Syokota
22458271Syokotastatic int read_string(UI *ui, UI_STRING *uis)
225147271Smarius{
226158041Ssobomax    int ok = 0;
227158041Ssobomax
228158041Ssobomax    switch (UI_get_string_type(uis)) {
229158041Ssobomax    case UIT_BOOLEAN:
230158041Ssobomax        fputs(UI_get0_output_string(uis), tty_out);
231158041Ssobomax        fputs(UI_get0_action_string(uis), tty_out);
232158041Ssobomax        fflush(tty_out);
233158041Ssobomax        return read_string_inner(ui, uis,
234158041Ssobomax                                 UI_get_input_flags(uis) & UI_INPUT_FLAG_ECHO,
235158041Ssobomax                                 0);
236158041Ssobomax    case UIT_PROMPT:
237158041Ssobomax        fputs(UI_get0_output_string(uis), tty_out);
238158041Ssobomax        fflush(tty_out);
239158041Ssobomax        return read_string_inner(ui, uis,
240158041Ssobomax                                 UI_get_input_flags(uis) & UI_INPUT_FLAG_ECHO,
241158041Ssobomax                                 1);
242158041Ssobomax    case UIT_VERIFY:
243158041Ssobomax        fprintf(tty_out, "Verifying - %s", UI_get0_output_string(uis));
244158041Ssobomax        fflush(tty_out);
245158041Ssobomax        if ((ok = read_string_inner(ui, uis,
24658271Syokota                                    UI_get_input_flags(uis) &
24742421Syokota                                    UI_INPUT_FLAG_ECHO, 1)) <= 0)
24842421Syokota            return ok;
24942421Syokota        if (strcmp(UI_get0_result_string(uis), UI_get0_test_string(uis)) != 0) {
25058271Syokota            fprintf(tty_out, "Verify failure\n");
25158271Syokota            fflush(tty_out);
25242421Syokota            return 0;
25358271Syokota        }
25442421Syokota        break;
25542421Syokota    case UIT_NONE:
25642421Syokota    case UIT_INFO:
25742421Syokota    case UIT_ERROR:
25842421Syokota        break;
25942421Syokota    }
26042421Syokota    return 1;
26142421Syokota}
26242421Syokota
26342421Syokota# if !defined(OPENSSL_SYS_WINCE)
26442421Syokota/* Internal functions to read a string without echoing */
26542421Syokotastatic int read_till_nl(FILE *in)
26658271Syokota{
26758271Syokota#  define SIZE 4
26858271Syokota    char buf[SIZE + 1];
26942421Syokota
27042421Syokota    do {
27142421Syokota        if (!fgets(buf, SIZE, in))
27258271Syokota            return 0;
27342421Syokota    } while (strchr(buf, '\n') == NULL);
27458271Syokota    return 1;
27542421Syokota}
27658271Syokota
27758271Syokotastatic volatile sig_atomic_t intr_signal;
27858271Syokota# endif
27958271Syokota
28058271Syokotastatic int read_string_inner(UI *ui, UI_STRING *uis, int echo, int strip_nl)
28158271Syokota{
28258271Syokota    static int ps;
28342421Syokota    int ok;
28442421Syokota    char result[BUFSIZ];
28542421Syokota    int maxsize = BUFSIZ - 1;
28642421Syokota# if !defined(OPENSSL_SYS_WINCE)
28742421Syokota    char *p = NULL;
28842421Syokota    int echo_eol = !echo;
28942421Syokota
29042421Syokota    intr_signal = 0;
29142421Syokota    ok = 0;
29242421Syokota    ps = 0;
29393279Smurray
29442421Syokota    pushsig();
29542421Syokota    ps = 1;
29693279Smurray
29742421Syokota    if (!echo && !noecho_console(ui))
29842421Syokota        goto error;
29942421Syokota    ps = 2;
30042421Syokota
30142421Syokota    result[0] = '\0';
30242421Syokota#  if defined(_WIN32)
30342421Syokota    if (is_a_tty) {
30442421Syokota        DWORD numread;
30542421Syokota#   if defined(CP_UTF8)
30642421Syokota        if (GetEnvironmentVariableW(L"OPENSSL_WIN32_UTF8", NULL, 0) != 0) {
30742421Syokota            WCHAR wresult[BUFSIZ];
30842421Syokota
30942421Syokota            if (ReadConsoleW(GetStdHandle(STD_INPUT_HANDLE),
31042421Syokota                         wresult, maxsize, &numread, NULL)) {
31142421Syokota                if (numread >= 2 &&
31242421Syokota                    wresult[numread-2] == L'\r' &&
31342421Syokota                    wresult[numread-1] == L'\n') {
31442421Syokota                    wresult[numread-2] = L'\n';
31593279Smurray                    numread--;
31693279Smurray                }
31742421Syokota                wresult[numread] = '\0';
31893279Smurray                if (WideCharToMultiByte(CP_UTF8, 0, wresult, -1,
31993279Smurray                                        result, sizeof(result), NULL, 0) > 0)
32093279Smurray                    p = result;
32142421Syokota
32242421Syokota                OPENSSL_cleanse(wresult, sizeof(wresult));
32342421Syokota            }
32442421Syokota        } else
32542421Syokota#   endif
32642421Syokota        if (ReadConsoleA(GetStdHandle(STD_INPUT_HANDLE),
32742421Syokota                         result, maxsize, &numread, NULL)) {
32842421Syokota            if (numread >= 2 &&
32942421Syokota                result[numread-2] == '\r' && result[numread-1] == '\n') {
33042421Syokota                result[numread-2] = '\n';
33142421Syokota                numread--;
33242421Syokota            }
33342421Syokota            result[numread] = '\0';
33442421Syokota            p = result;
33542421Syokota        }
33642421Syokota    } else
33742421Syokota#  elif defined(OPENSSL_SYS_MSDOS)
33842421Syokota    if (!echo) {
33942421Syokota        noecho_fgets(result, maxsize, tty_in);
34042421Syokota        p = result;             /* FIXME: noecho_fgets doesn't return errors */
34158271Syokota    } else
34242421Syokota#  endif
34342421Syokota    p = fgets(result, maxsize, tty_in);
34442421Syokota    if (p == NULL)
34542421Syokota        goto error;
34642421Syokota    if (feof(tty_in))
34742421Syokota        goto error;
34842421Syokota    if (ferror(tty_in))
34942421Syokota        goto error;
35042421Syokota    if ((p = (char *)strchr(result, '\n')) != NULL) {
35142421Syokota        if (strip_nl)
35242421Syokota            *p = '\0';
35342421Syokota    } else if (!read_till_nl(tty_in))
35442421Syokota        goto error;
35542421Syokota    if (UI_set_result(ui, uis, result) >= 0)
35642421Syokota        ok = 1;
35742421Syokota
35842421Syokota error:
35942421Syokota    if (intr_signal == SIGINT)
36042421Syokota        ok = -1;
36142421Syokota    if (echo_eol)
36242421Syokota        fprintf(tty_out, "\n");
36342421Syokota    if (ps >= 2 && !echo && !echo_console(ui))
36442421Syokota        ok = 0;
36542421Syokota
36642421Syokota    if (ps >= 1)
36742421Syokota        popsig();
36842421Syokota# else
36942421Syokota    ok = 1;
37042421Syokota# endif
37142421Syokota
37242421Syokota    OPENSSL_cleanse(result, BUFSIZ);
37342421Syokota    return ok;
37442421Syokota}
37542421Syokota
37642421Syokota/* Internal functions to open, handle and close a channel to the console.  */
37742421Syokotastatic int open_console(UI *ui)
37842421Syokota{
37942421Syokota    CRYPTO_THREAD_write_lock(ui->lock);
38042421Syokota    is_a_tty = 1;
38142421Syokota
38242421Syokota# if defined(OPENSSL_SYS_VXWORKS)
38342421Syokota    tty_in = stdin;
38442421Syokota    tty_out = stderr;
38542421Syokota# elif defined(_WIN32) && !defined(_WIN32_WCE)
38642421Syokota    if ((tty_out = fopen("conout$", "w")) == NULL)
38742421Syokota        tty_out = stderr;
38842421Syokota
38958271Syokota    if (GetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), &tty_orig)) {
39042421Syokota        tty_in = stdin;
39142421Syokota    } else {
39258271Syokota        is_a_tty = 0;
39342421Syokota        if ((tty_in = fopen("conin$", "r")) == NULL)
39442421Syokota            tty_in = stdin;
39558271Syokota    }
39642421Syokota# else
39742421Syokota#  ifdef OPENSSL_SYS_MSDOS
39842421Syokota#   define DEV_TTY "con"
39942421Syokota#  else
40042421Syokota#   define DEV_TTY "/dev/tty"
40142421Syokota#  endif
40242421Syokota    if ((tty_in = fopen(DEV_TTY, "r")) == NULL)
40342421Syokota        tty_in = stdin;
40442421Syokota    if ((tty_out = fopen(DEV_TTY, "w")) == NULL)
40542421Syokota        tty_out = stderr;
40642421Syokota# endif
40742421Syokota
40842421Syokota# if defined(TTY_get) && !defined(OPENSSL_SYS_VMS)
40942421Syokota    if (TTY_get(fileno(tty_in), &tty_orig) == -1) {
41042421Syokota#  ifdef ENOTTY
41142421Syokota        if (errno == ENOTTY)
41242421Syokota            is_a_tty = 0;
41342421Syokota        else
41442421Syokota#  endif
41558271Syokota#  ifdef EINVAL
41642421Syokota            /*
41742421Syokota             * Ariel Glenn reports that solaris can return EINVAL instead.
41842421Syokota             * This should be ok
41942421Syokota             */
42042421Syokota        if (errno == EINVAL)
42142421Syokota            is_a_tty = 0;
42242421Syokota        else
42342421Syokota#  endif
42442421Syokota#  ifdef ENXIO
42542421Syokota            /*
42642421Syokota             * Solaris can return ENXIO.
42742421Syokota             * This should be ok
42842421Syokota             */
42942421Syokota        if (errno == ENXIO)
43042421Syokota            is_a_tty = 0;
43142421Syokota        else
43258271Syokota#  endif
43342421Syokota#  ifdef EIO
43442421Syokota            /*
43542421Syokota             * Linux can return EIO.
43658271Syokota             * This should be ok
43742421Syokota             */
43842421Syokota        if (errno == EIO)
43942421Syokota            is_a_tty = 0;
44042421Syokota        else
44142421Syokota#  endif
44242421Syokota#  ifdef EPERM
44342421Syokota            /*
44442421Syokota             * Linux can return EPERM (Operation not permitted),
44542421Syokota             * e.g. if a daemon executes openssl via fork()+execve()
44642421Syokota             * This should be ok
44742421Syokota             */
44842421Syokota        if (errno == EPERM)
44942421Syokota            is_a_tty = 0;
45042421Syokota        else
45142421Syokota#  endif
45242421Syokota#  ifdef ENODEV
45342421Syokota            /*
45442421Syokota             * MacOS X returns ENODEV (Operation not supported by device),
45542421Syokota             * which seems appropriate.
45642421Syokota             */
45742421Syokota        if (errno == ENODEV)
45842421Syokota            is_a_tty = 0;
45958271Syokota        else
46042421Syokota#  endif
46158271Syokota            {
46242421Syokota                char tmp_num[10];
46342421Syokota                BIO_snprintf(tmp_num, sizeof(tmp_num) - 1, "%d", errno);
46442421Syokota                UIerr(UI_F_OPEN_CONSOLE, UI_R_UNKNOWN_TTYGET_ERRNO_VALUE);
46542421Syokota                ERR_add_error_data(2, "errno=", tmp_num);
46642421Syokota
46742421Syokota                return 0;
46842421Syokota            }
46942421Syokota    }
47042421Syokota# endif
47142421Syokota# ifdef OPENSSL_SYS_VMS
47242421Syokota    status = sys$assign(&terminal, &channel, 0, 0);
47342421Syokota
47442421Syokota    /* if there isn't a TT device, something is very wrong */
47542421Syokota    if (status != SS$_NORMAL) {
47642421Syokota        char tmp_num[12];
47742421Syokota
47842421Syokota        BIO_snprintf(tmp_num, sizeof(tmp_num) - 1, "%%X%08X", status);
47942421Syokota        UIerr(UI_F_OPEN_CONSOLE, UI_R_SYSASSIGN_ERROR);
48042421Syokota        ERR_add_error_data(2, "status=", tmp_num);
48142421Syokota        return 0;
48242421Syokota    }
48342421Syokota
48458271Syokota    status = sys$qiow(0, channel, IO$_SENSEMODE, &iosb, 0, 0, tty_orig, 12,
48542421Syokota                      0, 0, 0, 0);
48642421Syokota
48742421Syokota    /* If IO$_SENSEMODE doesn't work, this is not a terminal device */
48858271Syokota    if ((status != SS$_NORMAL) || (iosb.iosb$w_value != SS$_NORMAL))
48942421Syokota        is_a_tty = 0;
49042421Syokota# endif
49142421Syokota    return 1;
49242421Syokota}
49342421Syokota
49442421Syokotastatic int noecho_console(UI *ui)
49542421Syokota{
49642421Syokota# ifdef TTY_FLAGS
49742421Syokota    memcpy(&(tty_new), &(tty_orig), sizeof(tty_orig));
49842421Syokota    tty_new.TTY_FLAGS &= ~ECHO;
49942421Syokota# endif
50042421Syokota
50142421Syokota# if defined(TTY_set) && !defined(OPENSSL_SYS_VMS)
50242421Syokota    if (is_a_tty && (TTY_set(fileno(tty_in), &tty_new) == -1))
50342421Syokota        return 0;
50442421Syokota# endif
50542421Syokota# ifdef OPENSSL_SYS_VMS
50642421Syokota    if (is_a_tty) {
50742421Syokota        tty_new[0] = tty_orig[0];
50842421Syokota        tty_new[1] = tty_orig[1] | TT$M_NOECHO;
50942421Syokota        tty_new[2] = tty_orig[2];
51042421Syokota        status = sys$qiow(0, channel, IO$_SETMODE, &iosb, 0, 0, tty_new, 12,
51158271Syokota                          0, 0, 0, 0);
51242421Syokota        if ((status != SS$_NORMAL) || (iosb.iosb$w_value != SS$_NORMAL)) {
51358271Syokota            char tmp_num[2][12];
51442421Syokota
51542421Syokota            BIO_snprintf(tmp_num[0], sizeof(tmp_num[0]) - 1, "%%X%08X",
51642421Syokota                         status);
51742421Syokota            BIO_snprintf(tmp_num[1], sizeof(tmp_num[1]) - 1, "%%X%08X",
51842421Syokota                         iosb.iosb$w_value);
51942421Syokota            UIerr(UI_F_NOECHO_CONSOLE, UI_R_SYSQIOW_ERROR);
52042421Syokota            ERR_add_error_data(5, "status=", tmp_num[0],
52142421Syokota                               ",", "iosb.iosb$w_value=", tmp_num[1]);
52242421Syokota            return 0;
52342421Syokota        }
52442421Syokota    }
52542421Syokota# endif
52642421Syokota# if defined(_WIN32) && !defined(_WIN32_WCE)
52742421Syokota    if (is_a_tty) {
52842421Syokota        tty_new = tty_orig;
52942421Syokota        tty_new &= ~ENABLE_ECHO_INPUT;
53042421Syokota        SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), tty_new);
53142421Syokota    }
53242421Syokota# endif
53342421Syokota    return 1;
53458271Syokota}
53542421Syokota
53642421Syokotastatic int echo_console(UI *ui)
53742421Syokota{
53842421Syokota# if defined(TTY_set) && !defined(OPENSSL_SYS_VMS)
53942421Syokota    memcpy(&(tty_new), &(tty_orig), sizeof(tty_orig));
54042421Syokota    if (is_a_tty && (TTY_set(fileno(tty_in), &tty_new) == -1))
54142421Syokota        return 0;
54242421Syokota# endif
54342421Syokota# ifdef OPENSSL_SYS_VMS
54458271Syokota    if (is_a_tty) {
54542421Syokota        tty_new[0] = tty_orig[0];
54642421Syokota        tty_new[1] = tty_orig[1];
54742421Syokota        tty_new[2] = tty_orig[2];
54842421Syokota        status = sys$qiow(0, channel, IO$_SETMODE, &iosb, 0, 0, tty_new, 12,
54942421Syokota                          0, 0, 0, 0);
55042421Syokota        if ((status != SS$_NORMAL) || (iosb.iosb$w_value != SS$_NORMAL)) {
55142421Syokota            char tmp_num[2][12];
55242421Syokota
55342421Syokota            BIO_snprintf(tmp_num[0], sizeof(tmp_num[0]) - 1, "%%X%08X",
55458271Syokota                         status);
55542421Syokota            BIO_snprintf(tmp_num[1], sizeof(tmp_num[1]) - 1, "%%X%08X",
55642421Syokota                         iosb.iosb$w_value);
55742421Syokota            UIerr(UI_F_ECHO_CONSOLE, UI_R_SYSQIOW_ERROR);
55842421Syokota            ERR_add_error_data(5, "status=", tmp_num[0],
55942421Syokota                               ",", "iosb.iosb$w_value=", tmp_num[1]);
56042421Syokota            return 0;
56142421Syokota        }
56242421Syokota    }
56342421Syokota# endif
56442421Syokota# if defined(_WIN32) && !defined(_WIN32_WCE)
56542421Syokota    if (is_a_tty) {
56642421Syokota        tty_new = tty_orig;
56742421Syokota        SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), tty_new);
56842421Syokota    }
56942421Syokota# endif
57042421Syokota    return 1;
57142421Syokota}
57242421Syokota
57342421Syokotastatic int close_console(UI *ui)
57442421Syokota{
57542421Syokota    int ret = 1;
57642421Syokota
57742421Syokota    if (tty_in != stdin)
57842421Syokota        fclose(tty_in);
57942421Syokota    if (tty_out != stderr)
58042421Syokota        fclose(tty_out);
58142421Syokota# ifdef OPENSSL_SYS_VMS
58242421Syokota    status = sys$dassgn(channel);
58342421Syokota    if (status != SS$_NORMAL) {
58442421Syokota        char tmp_num[12];
58542421Syokota
58642421Syokota        BIO_snprintf(tmp_num, sizeof(tmp_num) - 1, "%%X%08X", status);
58742421Syokota        UIerr(UI_F_CLOSE_CONSOLE, UI_R_SYSDASSGN_ERROR);
58842421Syokota        ERR_add_error_data(2, "status=", tmp_num);
58942421Syokota        ret = 0;
59042421Syokota    }
59142421Syokota# endif
59242421Syokota    CRYPTO_THREAD_unlock(ui->lock);
59342421Syokota
59442421Syokota    return ret;
59542421Syokota}
59642421Syokota
59742421Syokota# if !defined(OPENSSL_SYS_WINCE)
59842421Syokota/* Internal functions to handle signals and act on them */
59942421Syokotastatic void pushsig(void)
60042421Syokota{
60142421Syokota#  ifndef OPENSSL_SYS_WIN32
60242421Syokota    int i;
60342421Syokota#  endif
60442421Syokota#  ifdef SIGACTION
60542421Syokota    struct sigaction sa;
60642421Syokota
60742421Syokota    memset(&sa, 0, sizeof(sa));
60842421Syokota    sa.sa_handler = recsig;
60942421Syokota#  endif
61042421Syokota
61142421Syokota#  ifdef OPENSSL_SYS_WIN32
61242421Syokota    savsig[SIGABRT] = signal(SIGABRT, recsig);
61342421Syokota    savsig[SIGFPE] = signal(SIGFPE, recsig);
61442421Syokota    savsig[SIGILL] = signal(SIGILL, recsig);
61542421Syokota    savsig[SIGINT] = signal(SIGINT, recsig);
61642421Syokota    savsig[SIGSEGV] = signal(SIGSEGV, recsig);
61742421Syokota    savsig[SIGTERM] = signal(SIGTERM, recsig);
61842421Syokota#  else
61942421Syokota    for (i = 1; i < NX509_SIG; i++) {
62042421Syokota#   ifdef SIGUSR1
62142421Syokota        if (i == SIGUSR1)
62242421Syokota            continue;
62342421Syokota#   endif
62442421Syokota#   ifdef SIGUSR2
62542421Syokota        if (i == SIGUSR2)
62642421Syokota            continue;
62742421Syokota#   endif
62842421Syokota#   ifdef SIGKILL
62942421Syokota        if (i == SIGKILL)       /* We can't make any action on that. */
63042421Syokota            continue;
63142421Syokota#   endif
63242421Syokota#   ifdef SIGACTION
63342421Syokota        sigaction(i, &sa, &savsig[i]);
63442421Syokota#   else
63542421Syokota        savsig[i] = signal(i, recsig);
63642421Syokota#   endif
63742421Syokota    }
63842421Syokota#  endif
63942421Syokota
64042421Syokota#  ifdef SIGWINCH
64142421Syokota    signal(SIGWINCH, SIG_DFL);
64242421Syokota#  endif
64342421Syokota}
64442421Syokota
64542421Syokotastatic void popsig(void)
64642421Syokota{
64742421Syokota#  ifdef OPENSSL_SYS_WIN32
64842421Syokota    signal(SIGABRT, savsig[SIGABRT]);
64942421Syokota    signal(SIGFPE, savsig[SIGFPE]);
65042421Syokota    signal(SIGILL, savsig[SIGILL]);
65142421Syokota    signal(SIGINT, savsig[SIGINT]);
65242421Syokota    signal(SIGSEGV, savsig[SIGSEGV]);
65342421Syokota    signal(SIGTERM, savsig[SIGTERM]);
65442421Syokota#  else
65542421Syokota    int i;
65642421Syokota    for (i = 1; i < NX509_SIG; i++) {
65742421Syokota#   ifdef SIGUSR1
65842421Syokota        if (i == SIGUSR1)
65942421Syokota            continue;
66042421Syokota#   endif
66142421Syokota#   ifdef SIGUSR2
66242421Syokota        if (i == SIGUSR2)
66342421Syokota            continue;
66442421Syokota#   endif
66542421Syokota#   ifdef SIGACTION
66642421Syokota        sigaction(i, &savsig[i], NULL);
66742421Syokota#   else
66842421Syokota        signal(i, savsig[i]);
66942421Syokota#   endif
67042421Syokota    }
67142421Syokota#  endif
67242421Syokota}
67342421Syokota
67442421Syokotastatic void recsig(int i)
67542421Syokota{
67642421Syokota    intr_signal = i;
67742421Syokota}
67842421Syokota# endif
67942421Syokota
68042421Syokota/* Internal functions specific for Windows */
68142421Syokota# if defined(OPENSSL_SYS_MSDOS) && !defined(_WIN32)
68242421Syokotastatic int noecho_fgets(char *buf, int size, FILE *tty)
68358271Syokota{
68442421Syokota    int i;
68542421Syokota    char *p;
68642421Syokota
68742421Syokota    p = buf;
68842421Syokota    for (;;) {
68942421Syokota        if (size == 0) {
69042421Syokota            *p = '\0';
69142421Syokota            break;
69242421Syokota        }
69342421Syokota        size--;
69442421Syokota#  if defined(_WIN32)
69542421Syokota        i = _getch();
69642421Syokota#  else
69742421Syokota        i = getch();
69842421Syokota#  endif
69942421Syokota        if (i == '\r')
70042421Syokota            i = '\n';
70142421Syokota        *(p++) = i;
70242421Syokota        if (i == '\n') {
70342421Syokota            *p = '\0';
70442421Syokota            break;
70542421Syokota        }
70642421Syokota    }
70742421Syokota#  ifdef WIN_CONSOLE_BUG
70858271Syokota    /*
70942421Syokota     * Win95 has several evil console bugs: one of these is that the last
71042421Syokota     * character read using getch() is passed to the next read: this is
71142421Syokota     * usually a CR so this can be trouble. No STDIO fix seems to work but
71242421Syokota     * flushing the console appears to do the trick.
71342421Syokota     */
71442421Syokota    {
71542421Syokota        HANDLE inh;
71642421Syokota        inh = GetStdHandle(STD_INPUT_HANDLE);
71742421Syokota        FlushConsoleInputBuffer(inh);
71842421Syokota    }
71942421Syokota#  endif
72042421Syokota    return strlen(buf);
72142421Syokota}
72242421Syokota# endif
72342421Syokota
72442421Syokotastatic UI_METHOD ui_openssl = {
72542421Syokota    "OpenSSL default user interface",
72642421Syokota    open_console,
72742421Syokota    write_string,
72842421Syokota    NULL,                       /* No flusher is needed for command lines */
72942421Syokota    read_string,
73042421Syokota    close_console,
73158271Syokota    NULL
73242421Syokota};
73342421Syokota
73458271Syokota/* The method with all the built-in console thingies */
73558271SyokotaUI_METHOD *UI_OpenSSL(void)
73642421Syokota{
73742421Syokota    return &ui_openssl;
73842421Syokota}
73958271Syokota
74042421Syokotastatic const UI_METHOD *default_UI_meth = &ui_openssl;
74142421Syokota
74242421Syokota#else
74342421Syokota
74442421Syokotastatic const UI_METHOD *default_UI_meth = NULL;
74542421Syokota
74642421Syokota#endif
74742421Syokota
74842421Syokotavoid UI_set_default_method(const UI_METHOD *meth)
74942421Syokota{
75042421Syokota    default_UI_meth = meth;
75142421Syokota}
75258271Syokota
75342421Syokotaconst UI_METHOD *UI_get_default_method(void)
75442421Syokota{
75542421Syokota    return default_UI_meth;
75642421Syokota}
75742421Syokota