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