1109998Smarkm/* crypto/ui/ui_openssl.c -*- mode:C; c-file-style: "eay" -*- */ 2296465Sdelphij/* 3296465Sdelphij * Written by Richard Levitte (richard@levitte.org) and others for the 4296465Sdelphij * OpenSSL project 2001. 5109998Smarkm */ 6109998Smarkm/* ==================================================================== 7109998Smarkm * Copyright (c) 2001 The OpenSSL Project. All rights reserved. 8109998Smarkm * 9109998Smarkm * Redistribution and use in source and binary forms, with or without 10109998Smarkm * modification, are permitted provided that the following conditions 11109998Smarkm * are met: 12109998Smarkm * 13109998Smarkm * 1. Redistributions of source code must retain the above copyright 14296465Sdelphij * notice, this list of conditions and the following disclaimer. 15109998Smarkm * 16109998Smarkm * 2. Redistributions in binary form must reproduce the above copyright 17109998Smarkm * notice, this list of conditions and the following disclaimer in 18109998Smarkm * the documentation and/or other materials provided with the 19109998Smarkm * distribution. 20109998Smarkm * 21109998Smarkm * 3. All advertising materials mentioning features or use of this 22109998Smarkm * software must display the following acknowledgment: 23109998Smarkm * "This product includes software developed by the OpenSSL Project 24109998Smarkm * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" 25109998Smarkm * 26109998Smarkm * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 27109998Smarkm * endorse or promote products derived from this software without 28109998Smarkm * prior written permission. For written permission, please contact 29109998Smarkm * openssl-core@openssl.org. 30109998Smarkm * 31109998Smarkm * 5. Products derived from this software may not be called "OpenSSL" 32109998Smarkm * nor may "OpenSSL" appear in their names without prior written 33109998Smarkm * permission of the OpenSSL Project. 34109998Smarkm * 35109998Smarkm * 6. Redistributions of any form whatsoever must retain the following 36109998Smarkm * acknowledgment: 37109998Smarkm * "This product includes software developed by the OpenSSL Project 38109998Smarkm * for use in the OpenSSL Toolkit (http://www.openssl.org/)" 39109998Smarkm * 40109998Smarkm * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 41109998Smarkm * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 42109998Smarkm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 43109998Smarkm * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 44109998Smarkm * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 45109998Smarkm * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 46109998Smarkm * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 47109998Smarkm * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48109998Smarkm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 49109998Smarkm * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 50109998Smarkm * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 51109998Smarkm * OF THE POSSIBILITY OF SUCH DAMAGE. 52109998Smarkm * ==================================================================== 53109998Smarkm * 54109998Smarkm * This product includes cryptographic software written by Eric Young 55109998Smarkm * (eay@cryptsoft.com). This product includes software written by Tim 56109998Smarkm * Hudson (tjh@cryptsoft.com). 57109998Smarkm * 58109998Smarkm */ 59109998Smarkm 60296465Sdelphij/*- 61296465Sdelphij * The lowest level part of this file was previously in crypto/des/read_pwd.c, 62109998Smarkm * Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 63109998Smarkm * All rights reserved. 64109998Smarkm * 65109998Smarkm * This package is an SSL implementation written 66109998Smarkm * by Eric Young (eay@cryptsoft.com). 67109998Smarkm * The implementation was written so as to conform with Netscapes SSL. 68296465Sdelphij * 69109998Smarkm * This library is free for commercial and non-commercial use as long as 70109998Smarkm * the following conditions are aheared to. The following conditions 71109998Smarkm * apply to all code found in this distribution, be it the RC4, RSA, 72109998Smarkm * lhash, DES, etc., code; not just the SSL code. The SSL documentation 73109998Smarkm * included with this distribution is covered by the same copyright terms 74109998Smarkm * except that the holder is Tim Hudson (tjh@cryptsoft.com). 75296465Sdelphij * 76109998Smarkm * Copyright remains Eric Young's, and as such any Copyright notices in 77109998Smarkm * the code are not to be removed. 78109998Smarkm * If this package is used in a product, Eric Young should be given attribution 79109998Smarkm * as the author of the parts of the library used. 80109998Smarkm * This can be in the form of a textual message at program startup or 81109998Smarkm * in documentation (online or textual) provided with the package. 82296465Sdelphij * 83109998Smarkm * Redistribution and use in source and binary forms, with or without 84109998Smarkm * modification, are permitted provided that the following conditions 85109998Smarkm * are met: 86109998Smarkm * 1. Redistributions of source code must retain the copyright 87109998Smarkm * notice, this list of conditions and the following disclaimer. 88109998Smarkm * 2. Redistributions in binary form must reproduce the above copyright 89109998Smarkm * notice, this list of conditions and the following disclaimer in the 90109998Smarkm * documentation and/or other materials provided with the distribution. 91109998Smarkm * 3. All advertising materials mentioning features or use of this software 92109998Smarkm * must display the following acknowledgement: 93109998Smarkm * "This product includes cryptographic software written by 94109998Smarkm * Eric Young (eay@cryptsoft.com)" 95109998Smarkm * The word 'cryptographic' can be left out if the rouines from the library 96109998Smarkm * being used are not cryptographic related :-). 97296465Sdelphij * 4. If you include any Windows specific code (or a derivative thereof) from 98109998Smarkm * the apps directory (application code) you must include an acknowledgement: 99109998Smarkm * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 100296465Sdelphij * 101109998Smarkm * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 102109998Smarkm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 103109998Smarkm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 104109998Smarkm * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 105109998Smarkm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 106109998Smarkm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 107109998Smarkm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 108109998Smarkm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 109109998Smarkm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 110109998Smarkm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 111109998Smarkm * SUCH DAMAGE. 112296465Sdelphij * 113109998Smarkm * The licence and distribution terms for any publically available version or 114109998Smarkm * derivative of this code cannot be changed. i.e. this code cannot simply be 115109998Smarkm * copied and put under another distribution licence 116109998Smarkm * [including the GNU Public Licence.] 117109998Smarkm */ 118109998Smarkm 119109998Smarkm#include <openssl/e_os2.h> 120109998Smarkm 121296465Sdelphij/* 122296465Sdelphij * need for #define _POSIX_C_SOURCE arises whenever you pass -ansi to gcc 123160814Ssimon * [maybe others?], because it masks interfaces not discussed in standard, 124296465Sdelphij * sigaction and fileno included. -pedantic would be more appropriate for the 125296465Sdelphij * intended purposes, but we can't prevent users from adding -ansi. 126160814Ssimon */ 127160814Ssimon#define _POSIX_C_SOURCE 1 128160814Ssimon#include <signal.h> 129160814Ssimon#include <stdio.h> 130160814Ssimon#include <string.h> 131160814Ssimon#include <errno.h> 132160814Ssimon 133109998Smarkm#if !defined(OPENSSL_SYS_MSDOS) && !defined(OPENSSL_SYS_VMS) 134109998Smarkm# ifdef OPENSSL_UNISTD 135109998Smarkm# include OPENSSL_UNISTD 136109998Smarkm# else 137109998Smarkm# include <unistd.h> 138109998Smarkm# endif 139296465Sdelphij/* 140296465Sdelphij * If unistd.h defines _POSIX_VERSION, we conclude that we are on a POSIX 141296465Sdelphij * system and have sigaction and termios. 142296465Sdelphij */ 143109998Smarkm# if defined(_POSIX_VERSION) 144109998Smarkm 145109998Smarkm# define SIGACTION 146109998Smarkm# if !defined(TERMIOS) && !defined(TERMIO) && !defined(SGTTY) 147109998Smarkm# define TERMIOS 148109998Smarkm# endif 149109998Smarkm 150109998Smarkm# endif 151109998Smarkm#endif 152109998Smarkm 153109998Smarkm#ifdef WIN16TTY 154109998Smarkm# undef OPENSSL_SYS_WIN16 155109998Smarkm# undef WIN16 156109998Smarkm# undef _WINDOWS 157109998Smarkm# include <graph.h> 158109998Smarkm#endif 159109998Smarkm 160109998Smarkm/* 06-Apr-92 Luke Brennan Support for VMS */ 161109998Smarkm#include "ui_locl.h" 162109998Smarkm#include "cryptlib.h" 163109998Smarkm 164296465Sdelphij#ifdef OPENSSL_SYS_VMS /* prototypes for sys$whatever */ 165109998Smarkm# include <starlet.h> 166109998Smarkm# ifdef __DECC 167109998Smarkm# pragma message disable DOLLARID 168109998Smarkm# endif 169109998Smarkm#endif 170109998Smarkm 171109998Smarkm#ifdef WIN_CONSOLE_BUG 172109998Smarkm# include <windows.h> 173296465Sdelphij# ifndef OPENSSL_SYS_WINCE 174296465Sdelphij# include <wincon.h> 175296465Sdelphij# endif 176109998Smarkm#endif 177109998Smarkm 178296465Sdelphij/* 179296465Sdelphij * There are 5 types of terminal interface supported, TERMIO, TERMIOS, VMS, 180296465Sdelphij * MSDOS and SGTTY 181109998Smarkm */ 182109998Smarkm 183109998Smarkm#if defined(__sgi) && !defined(TERMIOS) 184109998Smarkm# define TERMIOS 185109998Smarkm# undef TERMIO 186109998Smarkm# undef SGTTY 187109998Smarkm#endif 188109998Smarkm 189109998Smarkm#if defined(linux) && !defined(TERMIO) 190109998Smarkm# undef TERMIOS 191109998Smarkm# define TERMIO 192109998Smarkm# undef SGTTY 193109998Smarkm#endif 194109998Smarkm 195109998Smarkm#ifdef _LIBC 196109998Smarkm# undef TERMIOS 197109998Smarkm# define TERMIO 198109998Smarkm# undef SGTTY 199109998Smarkm#endif 200109998Smarkm 201109998Smarkm#if !defined(TERMIO) && !defined(TERMIOS) && !defined(OPENSSL_SYS_VMS) && !defined(OPENSSL_SYS_MSDOS) && !defined(OPENSSL_SYS_MACINTOSH_CLASSIC) && !defined(MAC_OS_GUSI_SOURCE) 202109998Smarkm# undef TERMIOS 203109998Smarkm# undef TERMIO 204109998Smarkm# define SGTTY 205109998Smarkm#endif 206109998Smarkm 207109998Smarkm#if defined(OPENSSL_SYS_VXWORKS) 208296465Sdelphij# undef TERMIOS 209296465Sdelphij# undef TERMIO 210296465Sdelphij# undef SGTTY 211109998Smarkm#endif 212109998Smarkm 213160814Ssimon#if defined(OPENSSL_SYS_NETWARE) 214296465Sdelphij# undef TERMIOS 215296465Sdelphij# undef TERMIO 216296465Sdelphij# undef SGTTY 217160814Ssimon#endif 218160814Ssimon 219109998Smarkm#ifdef TERMIOS 220109998Smarkm# include <termios.h> 221296465Sdelphij# define TTY_STRUCT struct termios 222296465Sdelphij# define TTY_FLAGS c_lflag 223296465Sdelphij# define TTY_get(tty,data) tcgetattr(tty,data) 224296465Sdelphij# define TTY_set(tty,data) tcsetattr(tty,TCSANOW,data) 225109998Smarkm#endif 226109998Smarkm 227109998Smarkm#ifdef TERMIO 228109998Smarkm# include <termio.h> 229296465Sdelphij# define TTY_STRUCT struct termio 230296465Sdelphij# define TTY_FLAGS c_lflag 231296465Sdelphij# define TTY_get(tty,data) ioctl(tty,TCGETA,data) 232296465Sdelphij# define TTY_set(tty,data) ioctl(tty,TCSETA,data) 233109998Smarkm#endif 234109998Smarkm 235109998Smarkm#ifdef SGTTY 236109998Smarkm# include <sgtty.h> 237296465Sdelphij# define TTY_STRUCT struct sgttyb 238296465Sdelphij# define TTY_FLAGS sg_flags 239296465Sdelphij# define TTY_get(tty,data) ioctl(tty,TIOCGETP,data) 240296465Sdelphij# define TTY_set(tty,data) ioctl(tty,TIOCSETP,data) 241109998Smarkm#endif 242109998Smarkm 243109998Smarkm#if !defined(_LIBC) && !defined(OPENSSL_SYS_MSDOS) && !defined(OPENSSL_SYS_VMS) && !defined(OPENSSL_SYS_MACINTOSH_CLASSIC) && !defined(OPENSSL_SYS_SUNOS) 244109998Smarkm# include <sys/ioctl.h> 245109998Smarkm#endif 246109998Smarkm 247109998Smarkm#ifdef OPENSSL_SYS_MSDOS 248109998Smarkm# include <conio.h> 249109998Smarkm#endif 250109998Smarkm 251109998Smarkm#ifdef OPENSSL_SYS_VMS 252109998Smarkm# include <ssdef.h> 253109998Smarkm# include <iodef.h> 254109998Smarkm# include <ttdef.h> 255109998Smarkm# include <descrip.h> 256109998Smarkmstruct IOSB { 257296465Sdelphij short iosb$w_value; 258296465Sdelphij short iosb$w_count; 259296465Sdelphij long iosb$l_info; 260296465Sdelphij}; 261109998Smarkm#endif 262109998Smarkm 263109998Smarkm#ifdef OPENSSL_SYS_SUNOS 264296465Sdelphijtypedef int sig_atomic_t; 265109998Smarkm#endif 266109998Smarkm 267160814Ssimon#if defined(OPENSSL_SYS_MACINTOSH_CLASSIC) || defined(MAC_OS_GUSI_SOURCE) || defined(OPENSSL_SYS_NETWARE) 268109998Smarkm/* 269109998Smarkm * This one needs work. As a matter of fact the code is unoperational 270109998Smarkm * and this is only a trick to get it compiled. 271296465Sdelphij * <appro@fy.chalmers.se> 272109998Smarkm */ 273109998Smarkm# define TTY_STRUCT int 274109998Smarkm#endif 275109998Smarkm 276109998Smarkm#ifndef NX509_SIG 277109998Smarkm# define NX509_SIG 32 278109998Smarkm#endif 279109998Smarkm 280109998Smarkm/* Define globals. They are protected by a lock */ 281109998Smarkm#ifdef SIGACTION 282109998Smarkmstatic struct sigaction savsig[NX509_SIG]; 283109998Smarkm#else 284296465Sdelphijstatic void (*savsig[NX509_SIG]) (int); 285109998Smarkm#endif 286109998Smarkm 287109998Smarkm#ifdef OPENSSL_SYS_VMS 288109998Smarkmstatic struct IOSB iosb; 289296465Sdelphijstatic $DESCRIPTOR(terminal, "TT"); 290296465Sdelphijstatic long tty_orig[3], tty_new[3]; /* XXX Is there any guarantee that this 291296465Sdelphij * will always suffice for the actual 292296465Sdelphij * structures? */ 293109998Smarkmstatic long status; 294109998Smarkmstatic unsigned short channel = 0; 295109998Smarkm#else 296296465Sdelphij# if !defined(OPENSSL_SYS_MSDOS) || defined(__DJGPP__) 297296465Sdelphijstatic TTY_STRUCT tty_orig, tty_new; 298296465Sdelphij# endif 299109998Smarkm#endif 300109998Smarkmstatic FILE *tty_in, *tty_out; 301109998Smarkmstatic int is_a_tty; 302109998Smarkm 303109998Smarkm/* Declare static functions */ 304109998Smarkm#if !defined(OPENSSL_SYS_WIN16) && !defined(OPENSSL_SYS_WINCE) 305205128Ssimonstatic int read_till_nl(FILE *); 306109998Smarkmstatic void recsig(int); 307109998Smarkmstatic void pushsig(void); 308109998Smarkmstatic void popsig(void); 309109998Smarkm#endif 310109998Smarkm#if defined(OPENSSL_SYS_MSDOS) && !defined(OPENSSL_SYS_WIN16) 311109998Smarkmstatic int noecho_fgets(char *buf, int size, FILE *tty); 312109998Smarkm#endif 313109998Smarkmstatic int read_string_inner(UI *ui, UI_STRING *uis, int echo, int strip_nl); 314109998Smarkm 315109998Smarkmstatic int read_string(UI *ui, UI_STRING *uis); 316109998Smarkmstatic int write_string(UI *ui, UI_STRING *uis); 317109998Smarkm 318109998Smarkmstatic int open_console(UI *ui); 319109998Smarkmstatic int echo_console(UI *ui); 320109998Smarkmstatic int noecho_console(UI *ui); 321109998Smarkmstatic int close_console(UI *ui); 322109998Smarkm 323296465Sdelphijstatic UI_METHOD ui_openssl = { 324296465Sdelphij "OpenSSL default user interface", 325296465Sdelphij open_console, 326296465Sdelphij write_string, 327296465Sdelphij NULL, /* No flusher is needed for command lines */ 328296465Sdelphij read_string, 329296465Sdelphij close_console, 330296465Sdelphij NULL 331296465Sdelphij}; 332109998Smarkm 333109998Smarkm/* The method with all the built-in thingies */ 334109998SmarkmUI_METHOD *UI_OpenSSL(void) 335296465Sdelphij{ 336296465Sdelphij return &ui_openssl; 337296465Sdelphij} 338109998Smarkm 339296465Sdelphij/* 340296465Sdelphij * The following function makes sure that info and error strings are printed 341296465Sdelphij * before any prompt. 342296465Sdelphij */ 343109998Smarkmstatic int write_string(UI *ui, UI_STRING *uis) 344296465Sdelphij{ 345296465Sdelphij switch (UI_get_string_type(uis)) { 346296465Sdelphij case UIT_ERROR: 347296465Sdelphij case UIT_INFO: 348296465Sdelphij fputs(UI_get0_output_string(uis), tty_out); 349296465Sdelphij fflush(tty_out); 350296465Sdelphij break; 351296465Sdelphij default: 352296465Sdelphij break; 353296465Sdelphij } 354296465Sdelphij return 1; 355296465Sdelphij} 356109998Smarkm 357109998Smarkmstatic int read_string(UI *ui, UI_STRING *uis) 358296465Sdelphij{ 359296465Sdelphij int ok = 0; 360109998Smarkm 361296465Sdelphij switch (UI_get_string_type(uis)) { 362296465Sdelphij case UIT_BOOLEAN: 363296465Sdelphij fputs(UI_get0_output_string(uis), tty_out); 364296465Sdelphij fputs(UI_get0_action_string(uis), tty_out); 365296465Sdelphij fflush(tty_out); 366296465Sdelphij return read_string_inner(ui, uis, 367296465Sdelphij UI_get_input_flags(uis) & UI_INPUT_FLAG_ECHO, 368296465Sdelphij 0); 369296465Sdelphij case UIT_PROMPT: 370296465Sdelphij fputs(UI_get0_output_string(uis), tty_out); 371296465Sdelphij fflush(tty_out); 372296465Sdelphij return read_string_inner(ui, uis, 373296465Sdelphij UI_get_input_flags(uis) & UI_INPUT_FLAG_ECHO, 374296465Sdelphij 1); 375296465Sdelphij case UIT_VERIFY: 376296465Sdelphij fprintf(tty_out, "Verifying - %s", UI_get0_output_string(uis)); 377296465Sdelphij fflush(tty_out); 378296465Sdelphij if ((ok = read_string_inner(ui, uis, 379296465Sdelphij UI_get_input_flags(uis) & 380296465Sdelphij UI_INPUT_FLAG_ECHO, 1)) <= 0) 381296465Sdelphij return ok; 382296465Sdelphij if (strcmp(UI_get0_result_string(uis), UI_get0_test_string(uis)) != 0) { 383296465Sdelphij fprintf(tty_out, "Verify failure\n"); 384296465Sdelphij fflush(tty_out); 385296465Sdelphij return 0; 386296465Sdelphij } 387296465Sdelphij break; 388296465Sdelphij default: 389296465Sdelphij break; 390296465Sdelphij } 391296465Sdelphij return 1; 392296465Sdelphij} 393109998Smarkm 394109998Smarkm#if !defined(OPENSSL_SYS_WIN16) && !defined(OPENSSL_SYS_WINCE) 395109998Smarkm/* Internal functions to read a string without echoing */ 396205128Ssimonstatic int read_till_nl(FILE *in) 397296465Sdelphij{ 398296465Sdelphij# define SIZE 4 399296465Sdelphij char buf[SIZE + 1]; 400109998Smarkm 401296465Sdelphij do { 402296465Sdelphij if (!fgets(buf, SIZE, in)) 403296465Sdelphij return 0; 404296465Sdelphij } while (strchr(buf, '\n') == NULL); 405296465Sdelphij return 1; 406296465Sdelphij} 407109998Smarkm 408109998Smarkmstatic volatile sig_atomic_t intr_signal; 409109998Smarkm#endif 410109998Smarkm 411109998Smarkmstatic int read_string_inner(UI *ui, UI_STRING *uis, int echo, int strip_nl) 412296465Sdelphij{ 413296465Sdelphij static int ps; 414296465Sdelphij int ok; 415296465Sdelphij char result[BUFSIZ]; 416296465Sdelphij int maxsize = BUFSIZ - 1; 417109998Smarkm#if !defined(OPENSSL_SYS_WIN16) && !defined(OPENSSL_SYS_WINCE) 418296465Sdelphij char *p; 419109998Smarkm 420296465Sdelphij intr_signal = 0; 421296465Sdelphij ok = 0; 422296465Sdelphij ps = 0; 423109998Smarkm 424296465Sdelphij pushsig(); 425296465Sdelphij ps = 1; 426109998Smarkm 427296465Sdelphij if (!echo && !noecho_console(ui)) 428296465Sdelphij goto error; 429296465Sdelphij ps = 2; 430109998Smarkm 431296465Sdelphij result[0] = '\0'; 432296465Sdelphij# ifdef OPENSSL_SYS_MSDOS 433296465Sdelphij if (!echo) { 434296465Sdelphij noecho_fgets(result, maxsize, tty_in); 435296465Sdelphij p = result; /* FIXME: noecho_fgets doesn't return errors */ 436296465Sdelphij } else 437296465Sdelphij p = fgets(result, maxsize, tty_in); 438296465Sdelphij# else 439296465Sdelphij p = fgets(result, maxsize, tty_in); 440296465Sdelphij# endif 441296465Sdelphij if (!p) 442296465Sdelphij goto error; 443296465Sdelphij if (feof(tty_in)) 444296465Sdelphij goto error; 445296465Sdelphij if (ferror(tty_in)) 446296465Sdelphij goto error; 447296465Sdelphij if ((p = (char *)strchr(result, '\n')) != NULL) { 448296465Sdelphij if (strip_nl) 449296465Sdelphij *p = '\0'; 450296465Sdelphij } else if (!read_till_nl(tty_in)) 451296465Sdelphij goto error; 452296465Sdelphij if (UI_set_result(ui, uis, result) >= 0) 453296465Sdelphij ok = 1; 454109998Smarkm 455296465Sdelphij error: 456296465Sdelphij if (intr_signal == SIGINT) 457296465Sdelphij ok = -1; 458296465Sdelphij if (!echo) 459296465Sdelphij fprintf(tty_out, "\n"); 460296465Sdelphij if (ps >= 2 && !echo && !echo_console(ui)) 461296465Sdelphij ok = 0; 462109998Smarkm 463296465Sdelphij if (ps >= 1) 464296465Sdelphij popsig(); 465109998Smarkm#else 466296465Sdelphij ok = 1; 467109998Smarkm#endif 468109998Smarkm 469296465Sdelphij OPENSSL_cleanse(result, BUFSIZ); 470296465Sdelphij return ok; 471296465Sdelphij} 472109998Smarkm 473109998Smarkm/* Internal functions to open, handle and close a channel to the console. */ 474109998Smarkmstatic int open_console(UI *ui) 475296465Sdelphij{ 476296465Sdelphij CRYPTO_w_lock(CRYPTO_LOCK_UI); 477296465Sdelphij is_a_tty = 1; 478109998Smarkm 479160814Ssimon#if defined(OPENSSL_SYS_MACINTOSH_CLASSIC) || defined(OPENSSL_SYS_VXWORKS) || defined(OPENSSL_SYS_NETWARE) 480296465Sdelphij tty_in = stdin; 481296465Sdelphij tty_out = stderr; 482109998Smarkm#else 483296465Sdelphij# ifdef OPENSSL_SYS_MSDOS 484296465Sdelphij# define DEV_TTY "con" 485296465Sdelphij# else 486296465Sdelphij# define DEV_TTY "/dev/tty" 487296465Sdelphij# endif 488296465Sdelphij if ((tty_in = fopen(DEV_TTY, "r")) == NULL) 489296465Sdelphij tty_in = stdin; 490296465Sdelphij if ((tty_out = fopen(DEV_TTY, "w")) == NULL) 491296465Sdelphij tty_out = stderr; 492109998Smarkm#endif 493109998Smarkm 494109998Smarkm#if defined(TTY_get) && !defined(OPENSSL_SYS_VMS) 495296465Sdelphij if (TTY_get(fileno(tty_in), &tty_orig) == -1) { 496296465Sdelphij# ifdef ENOTTY 497296465Sdelphij if (errno == ENOTTY) 498296465Sdelphij is_a_tty = 0; 499296465Sdelphij else 500296465Sdelphij# endif 501296465Sdelphij# ifdef EINVAL 502296465Sdelphij /* 503296465Sdelphij * Ariel Glenn ariel@columbia.edu reports that solaris can return 504296465Sdelphij * EINVAL instead. This should be ok 505296465Sdelphij */ 506296465Sdelphij if (errno == EINVAL) 507296465Sdelphij is_a_tty = 0; 508296465Sdelphij else 509296465Sdelphij# endif 510296465Sdelphij return 0; 511296465Sdelphij } 512109998Smarkm#endif 513109998Smarkm#ifdef OPENSSL_SYS_VMS 514296465Sdelphij status = sys$assign(&terminal, &channel, 0, 0); 515296465Sdelphij if (status != SS$_NORMAL) 516296465Sdelphij return 0; 517296465Sdelphij status = 518296465Sdelphij sys$qiow(0, channel, IO$_SENSEMODE, &iosb, 0, 0, tty_orig, 12, 0, 0, 519296465Sdelphij 0, 0); 520296465Sdelphij if ((status != SS$_NORMAL) || (iosb.iosb$w_value != SS$_NORMAL)) 521296465Sdelphij return 0; 522109998Smarkm#endif 523296465Sdelphij return 1; 524296465Sdelphij} 525109998Smarkm 526109998Smarkmstatic int noecho_console(UI *ui) 527296465Sdelphij{ 528109998Smarkm#ifdef TTY_FLAGS 529296465Sdelphij memcpy(&(tty_new), &(tty_orig), sizeof(tty_orig)); 530296465Sdelphij tty_new.TTY_FLAGS &= ~ECHO; 531109998Smarkm#endif 532109998Smarkm 533109998Smarkm#if defined(TTY_set) && !defined(OPENSSL_SYS_VMS) 534296465Sdelphij if (is_a_tty && (TTY_set(fileno(tty_in), &tty_new) == -1)) 535296465Sdelphij return 0; 536109998Smarkm#endif 537109998Smarkm#ifdef OPENSSL_SYS_VMS 538296465Sdelphij tty_new[0] = tty_orig[0]; 539296465Sdelphij tty_new[1] = tty_orig[1] | TT$M_NOECHO; 540296465Sdelphij tty_new[2] = tty_orig[2]; 541296465Sdelphij status = 542296465Sdelphij sys$qiow(0, channel, IO$_SETMODE, &iosb, 0, 0, tty_new, 12, 0, 0, 0, 543296465Sdelphij 0); 544296465Sdelphij if ((status != SS$_NORMAL) || (iosb.iosb$w_value != SS$_NORMAL)) 545296465Sdelphij return 0; 546109998Smarkm#endif 547296465Sdelphij return 1; 548296465Sdelphij} 549109998Smarkm 550109998Smarkmstatic int echo_console(UI *ui) 551296465Sdelphij{ 552109998Smarkm#if defined(TTY_set) && !defined(OPENSSL_SYS_VMS) 553296465Sdelphij memcpy(&(tty_new), &(tty_orig), sizeof(tty_orig)); 554296465Sdelphij tty_new.TTY_FLAGS |= ECHO; 555109998Smarkm#endif 556109998Smarkm 557109998Smarkm#if defined(TTY_set) && !defined(OPENSSL_SYS_VMS) 558296465Sdelphij if (is_a_tty && (TTY_set(fileno(tty_in), &tty_new) == -1)) 559296465Sdelphij return 0; 560109998Smarkm#endif 561109998Smarkm#ifdef OPENSSL_SYS_VMS 562296465Sdelphij tty_new[0] = tty_orig[0]; 563296465Sdelphij tty_new[1] = tty_orig[1] & ~TT$M_NOECHO; 564296465Sdelphij tty_new[2] = tty_orig[2]; 565296465Sdelphij status = 566296465Sdelphij sys$qiow(0, channel, IO$_SETMODE, &iosb, 0, 0, tty_new, 12, 0, 0, 0, 567296465Sdelphij 0); 568296465Sdelphij if ((status != SS$_NORMAL) || (iosb.iosb$w_value != SS$_NORMAL)) 569296465Sdelphij return 0; 570109998Smarkm#endif 571296465Sdelphij return 1; 572296465Sdelphij} 573109998Smarkm 574109998Smarkmstatic int close_console(UI *ui) 575296465Sdelphij{ 576296465Sdelphij if (tty_in != stdin) 577296465Sdelphij fclose(tty_in); 578296465Sdelphij if (tty_out != stderr) 579296465Sdelphij fclose(tty_out); 580109998Smarkm#ifdef OPENSSL_SYS_VMS 581296465Sdelphij status = sys$dassgn(channel); 582109998Smarkm#endif 583296465Sdelphij CRYPTO_w_unlock(CRYPTO_LOCK_UI); 584109998Smarkm 585296465Sdelphij return 1; 586296465Sdelphij} 587109998Smarkm 588109998Smarkm#if !defined(OPENSSL_SYS_WIN16) && !defined(OPENSSL_SYS_WINCE) 589109998Smarkm/* Internal functions to handle signals and act on them */ 590109998Smarkmstatic void pushsig(void) 591296465Sdelphij{ 592296465Sdelphij# ifndef OPENSSL_SYS_WIN32 593296465Sdelphij int i; 594296465Sdelphij# endif 595296465Sdelphij# ifdef SIGACTION 596296465Sdelphij struct sigaction sa; 597109998Smarkm 598296465Sdelphij memset(&sa, 0, sizeof sa); 599296465Sdelphij sa.sa_handler = recsig; 600296465Sdelphij# endif 601109998Smarkm 602296465Sdelphij# ifdef OPENSSL_SYS_WIN32 603296465Sdelphij savsig[SIGABRT] = signal(SIGABRT, recsig); 604296465Sdelphij savsig[SIGFPE] = signal(SIGFPE, recsig); 605296465Sdelphij savsig[SIGILL] = signal(SIGILL, recsig); 606296465Sdelphij savsig[SIGINT] = signal(SIGINT, recsig); 607296465Sdelphij savsig[SIGSEGV] = signal(SIGSEGV, recsig); 608296465Sdelphij savsig[SIGTERM] = signal(SIGTERM, recsig); 609296465Sdelphij# else 610296465Sdelphij for (i = 1; i < NX509_SIG; i++) { 611296465Sdelphij# ifdef SIGUSR1 612296465Sdelphij if (i == SIGUSR1) 613296465Sdelphij continue; 614296465Sdelphij# endif 615296465Sdelphij# ifdef SIGUSR2 616296465Sdelphij if (i == SIGUSR2) 617296465Sdelphij continue; 618296465Sdelphij# endif 619296465Sdelphij# ifdef SIGKILL 620296465Sdelphij if (i == SIGKILL) /* We can't make any action on that. */ 621296465Sdelphij continue; 622296465Sdelphij# endif 623296465Sdelphij# ifdef SIGACTION 624296465Sdelphij sigaction(i, &sa, &savsig[i]); 625296465Sdelphij# else 626296465Sdelphij savsig[i] = signal(i, recsig); 627296465Sdelphij# endif 628296465Sdelphij } 629296465Sdelphij# endif 630109998Smarkm 631296465Sdelphij# ifdef SIGWINCH 632296465Sdelphij signal(SIGWINCH, SIG_DFL); 633296465Sdelphij# endif 634296465Sdelphij} 635109998Smarkm 636109998Smarkmstatic void popsig(void) 637296465Sdelphij{ 638296465Sdelphij# ifdef OPENSSL_SYS_WIN32 639296465Sdelphij signal(SIGABRT, savsig[SIGABRT]); 640296465Sdelphij signal(SIGFPE, savsig[SIGFPE]); 641296465Sdelphij signal(SIGILL, savsig[SIGILL]); 642296465Sdelphij signal(SIGINT, savsig[SIGINT]); 643296465Sdelphij signal(SIGSEGV, savsig[SIGSEGV]); 644296465Sdelphij signal(SIGTERM, savsig[SIGTERM]); 645296465Sdelphij# else 646296465Sdelphij int i; 647296465Sdelphij for (i = 1; i < NX509_SIG; i++) { 648296465Sdelphij# ifdef SIGUSR1 649296465Sdelphij if (i == SIGUSR1) 650296465Sdelphij continue; 651296465Sdelphij# endif 652296465Sdelphij# ifdef SIGUSR2 653296465Sdelphij if (i == SIGUSR2) 654296465Sdelphij continue; 655296465Sdelphij# endif 656296465Sdelphij# ifdef SIGACTION 657296465Sdelphij sigaction(i, &savsig[i], NULL); 658296465Sdelphij# else 659296465Sdelphij signal(i, savsig[i]); 660296465Sdelphij# endif 661296465Sdelphij } 662296465Sdelphij# endif 663296465Sdelphij} 664109998Smarkm 665109998Smarkmstatic void recsig(int i) 666296465Sdelphij{ 667296465Sdelphij intr_signal = i; 668296465Sdelphij} 669109998Smarkm#endif 670109998Smarkm 671109998Smarkm/* Internal functions specific for Windows */ 672109998Smarkm#if defined(OPENSSL_SYS_MSDOS) && !defined(OPENSSL_SYS_WIN16) && !defined(OPENSSL_SYS_WINCE) 673109998Smarkmstatic int noecho_fgets(char *buf, int size, FILE *tty) 674296465Sdelphij{ 675296465Sdelphij int i; 676296465Sdelphij char *p; 677109998Smarkm 678296465Sdelphij p = buf; 679296465Sdelphij for (;;) { 680296465Sdelphij if (size == 0) { 681296465Sdelphij *p = '\0'; 682296465Sdelphij break; 683296465Sdelphij } 684296465Sdelphij size--; 685296465Sdelphij# ifdef WIN16TTY 686296465Sdelphij i = _inchar(); 687296465Sdelphij# elif defined(_WIN32) 688296465Sdelphij i = _getch(); 689296465Sdelphij# else 690296465Sdelphij i = getch(); 691296465Sdelphij# endif 692296465Sdelphij if (i == '\r') 693296465Sdelphij i = '\n'; 694296465Sdelphij *(p++) = i; 695296465Sdelphij if (i == '\n') { 696296465Sdelphij *p = '\0'; 697296465Sdelphij break; 698296465Sdelphij } 699296465Sdelphij } 700296465Sdelphij# ifdef WIN_CONSOLE_BUG 701296465Sdelphij /* 702296465Sdelphij * Win95 has several evil console bugs: one of these is that the last 703296465Sdelphij * character read using getch() is passed to the next read: this is 704296465Sdelphij * usually a CR so this can be trouble. No STDIO fix seems to work but 705296465Sdelphij * flushing the console appears to do the trick. 706296465Sdelphij */ 707296465Sdelphij { 708296465Sdelphij HANDLE inh; 709296465Sdelphij inh = GetStdHandle(STD_INPUT_HANDLE); 710296465Sdelphij FlushConsoleInputBuffer(inh); 711296465Sdelphij } 712296465Sdelphij# endif 713296465Sdelphij return (strlen(buf)); 714296465Sdelphij} 715109998Smarkm#endif 716