Home | History | Annotate | Download | only in ui
      1 /* crypto/ui/ui_openssl.c -*- mode:C; c-file-style: "eay" -*- */
      2 /* Written by Richard Levitte (richard (at) levitte.org) and others
      3  * for the OpenSSL project 2001.
      4  */
      5 /* ====================================================================
      6  * Copyright (c) 2001 The OpenSSL Project.  All rights reserved.
      7  *
      8  * Redistribution and use in source and binary forms, with or without
      9  * modification, are permitted provided that the following conditions
     10  * are met:
     11  *
     12  * 1. Redistributions of source code must retain the above copyright
     13  *    notice, this list of conditions and the following disclaimer.
     14  *
     15  * 2. Redistributions in binary form must reproduce the above copyright
     16  *    notice, this list of conditions and the following disclaimer in
     17  *    the documentation and/or other materials provided with the
     18  *    distribution.
     19  *
     20  * 3. All advertising materials mentioning features or use of this
     21  *    software must display the following acknowledgment:
     22  *    "This product includes software developed by the OpenSSL Project
     23  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
     24  *
     25  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
     26  *    endorse or promote products derived from this software without
     27  *    prior written permission. For written permission, please contact
     28  *    openssl-core (at) openssl.org.
     29  *
     30  * 5. Products derived from this software may not be called "OpenSSL"
     31  *    nor may "OpenSSL" appear in their names without prior written
     32  *    permission of the OpenSSL Project.
     33  *
     34  * 6. Redistributions of any form whatsoever must retain the following
     35  *    acknowledgment:
     36  *    "This product includes software developed by the OpenSSL Project
     37  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
     38  *
     39  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
     40  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     41  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     42  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
     43  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     44  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     45  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     46  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     47  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
     48  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     49  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
     50  * OF THE POSSIBILITY OF SUCH DAMAGE.
     51  * ====================================================================
     52  *
     53  * This product includes cryptographic software written by Eric Young
     54  * (eay (at) cryptsoft.com).  This product includes software written by Tim
     55  * Hudson (tjh (at) cryptsoft.com).
     56  *
     57  */
     58 
     59 /* The lowest level part of this file was previously in crypto/des/read_pwd.c,
     60  * Copyright (C) 1995-1998 Eric Young (eay (at) cryptsoft.com)
     61  * All rights reserved.
     62  *
     63  * This package is an SSL implementation written
     64  * by Eric Young (eay (at) cryptsoft.com).
     65  * The implementation was written so as to conform with Netscapes SSL.
     66  *
     67  * This library is free for commercial and non-commercial use as long as
     68  * the following conditions are aheared to.  The following conditions
     69  * apply to all code found in this distribution, be it the RC4, RSA,
     70  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
     71  * included with this distribution is covered by the same copyright terms
     72  * except that the holder is Tim Hudson (tjh (at) cryptsoft.com).
     73  *
     74  * Copyright remains Eric Young's, and as such any Copyright notices in
     75  * the code are not to be removed.
     76  * If this package is used in a product, Eric Young should be given attribution
     77  * as the author of the parts of the library used.
     78  * This can be in the form of a textual message at program startup or
     79  * in documentation (online or textual) provided with the package.
     80  *
     81  * Redistribution and use in source and binary forms, with or without
     82  * modification, are permitted provided that the following conditions
     83  * are met:
     84  * 1. Redistributions of source code must retain the copyright
     85  *    notice, this list of conditions and the following disclaimer.
     86  * 2. Redistributions in binary form must reproduce the above copyright
     87  *    notice, this list of conditions and the following disclaimer in the
     88  *    documentation and/or other materials provided with the distribution.
     89  * 3. All advertising materials mentioning features or use of this software
     90  *    must display the following acknowledgement:
     91  *    "This product includes cryptographic software written by
     92  *     Eric Young (eay (at) cryptsoft.com)"
     93  *    The word 'cryptographic' can be left out if the rouines from the library
     94  *    being used are not cryptographic related :-).
     95  * 4. If you include any Windows specific code (or a derivative thereof) from
     96  *    the apps directory (application code) you must include an acknowledgement:
     97  *    "This product includes software written by Tim Hudson (tjh (at) cryptsoft.com)"
     98  *
     99  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
    100  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    101  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    102  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
    103  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    104  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
    105  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
    106  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
    107  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
    108  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
    109  * SUCH DAMAGE.
    110  *
    111  * The licence and distribution terms for any publically available version or
    112  * derivative of this code cannot be changed.  i.e. this code cannot simply be
    113  * copied and put under another distribution licence
    114  * [including the GNU Public Licence.]
    115  */
    116 
    117 
    118 #include <openssl/e_os2.h>
    119 
    120 /* need for #define _POSIX_C_SOURCE arises whenever you pass -ansi to gcc
    121  * [maybe others?], because it masks interfaces not discussed in standard,
    122  * sigaction and fileno included. -pedantic would be more appropriate for
    123  * the intended purposes, but we can't prevent users from adding -ansi.
    124  */
    125 #if defined(OPENSSL_SYSNAME_VXWORKS)
    126 #include <sys/types.h>
    127 #endif
    128 
    129 #if !defined(_POSIX_C_SOURCE) && defined(OPENSSL_SYS_VMS)
    130 #ifndef _POSIX_C_SOURCE
    131 #define _POSIX_C_SOURCE 2
    132 #endif
    133 #endif
    134 #include <signal.h>
    135 #include <stdio.h>
    136 #include <string.h>
    137 #include <errno.h>
    138 
    139 #if !defined(OPENSSL_SYS_MSDOS) && !defined(OPENSSL_SYS_VMS)
    140 # ifdef OPENSSL_UNISTD
    141 #  include OPENSSL_UNISTD
    142 # else
    143 #  include <unistd.h>
    144 # endif
    145 /* If unistd.h defines _POSIX_VERSION, we conclude that we
    146  * are on a POSIX system and have sigaction and termios. */
    147 # if defined(_POSIX_VERSION)
    148 
    149 #  define SIGACTION
    150 #  if !defined(TERMIOS) && !defined(TERMIO) && !defined(SGTTY)
    151 #   define TERMIOS
    152 #  endif
    153 
    154 # endif
    155 #endif
    156 
    157 #ifdef WIN16TTY
    158 # undef OPENSSL_SYS_WIN16
    159 # undef WIN16
    160 # undef _WINDOWS
    161 # include <graph.h>
    162 #endif
    163 
    164 /* 06-Apr-92 Luke Brennan    Support for VMS */
    165 #include "ui_locl.h"
    166 #include "cryptlib.h"
    167 
    168 #ifdef OPENSSL_SYS_VMS		/* prototypes for sys$whatever */
    169 # include <starlet.h>
    170 # ifdef __DECC
    171 #  pragma message disable DOLLARID
    172 # endif
    173 #endif
    174 
    175 #ifdef WIN_CONSOLE_BUG
    176 # include <windows.h>
    177 #ifndef OPENSSL_SYS_WINCE
    178 # include <wincon.h>
    179 #endif
    180 #endif
    181 
    182 
    183 /* There are 5 types of terminal interface supported,
    184  * TERMIO, TERMIOS, VMS, MSDOS and SGTTY
    185  */
    186 
    187 #if defined(__sgi) && !defined(TERMIOS)
    188 # define TERMIOS
    189 # undef  TERMIO
    190 # undef  SGTTY
    191 #endif
    192 
    193 #if defined(linux) && !defined(TERMIO) && !defined(__ANDROID__)
    194 # undef  TERMIOS
    195 # define TERMIO
    196 # undef  SGTTY
    197 #endif
    198 
    199 #ifdef _LIBC
    200 # undef  TERMIOS
    201 # define TERMIO
    202 # undef  SGTTY
    203 #endif
    204 
    205 #if !defined(TERMIO) && !defined(TERMIOS) && !defined(OPENSSL_SYS_VMS) && !defined(OPENSSL_SYS_MSDOS) && !defined(OPENSSL_SYS_MACINTOSH_CLASSIC) && !defined(MAC_OS_GUSI_SOURCE)
    206 # undef  TERMIOS
    207 # undef  TERMIO
    208 # define SGTTY
    209 #endif
    210 
    211 #if defined(OPENSSL_SYS_VXWORKS)
    212 #undef TERMIOS
    213 #undef TERMIO
    214 #undef SGTTY
    215 #endif
    216 
    217 #if defined(OPENSSL_SYS_NETWARE)
    218 #undef TERMIOS
    219 #undef TERMIO
    220 #undef SGTTY
    221 #endif
    222 
    223 #ifdef TERMIOS
    224 # include <termios.h>
    225 # define TTY_STRUCT		struct termios
    226 # define TTY_FLAGS		c_lflag
    227 # define TTY_get(tty,data)	tcgetattr(tty,data)
    228 # define TTY_set(tty,data)	tcsetattr(tty,TCSANOW,data)
    229 #endif
    230 
    231 #ifdef TERMIO
    232 # include <termio.h>
    233 # define TTY_STRUCT		struct termio
    234 # define TTY_FLAGS		c_lflag
    235 # define TTY_get(tty,data)	ioctl(tty,TCGETA,data)
    236 # define TTY_set(tty,data)	ioctl(tty,TCSETA,data)
    237 #endif
    238 
    239 #ifdef SGTTY
    240 # include <sgtty.h>
    241 # define TTY_STRUCT		struct sgttyb
    242 # define TTY_FLAGS		sg_flags
    243 # define TTY_get(tty,data)	ioctl(tty,TIOCGETP,data)
    244 # define TTY_set(tty,data)	ioctl(tty,TIOCSETP,data)
    245 #endif
    246 
    247 #if !defined(_LIBC) && !defined(OPENSSL_SYS_MSDOS) && !defined(OPENSSL_SYS_VMS) && !defined(OPENSSL_SYS_MACINTOSH_CLASSIC) && !defined(OPENSSL_SYS_SUNOS)
    248 # include <sys/ioctl.h>
    249 #endif
    250 
    251 #ifdef OPENSSL_SYS_MSDOS
    252 # include <conio.h>
    253 #endif
    254 
    255 #ifdef OPENSSL_SYS_VMS
    256 # include <ssdef.h>
    257 # include <iodef.h>
    258 # include <ttdef.h>
    259 # include <descrip.h>
    260 struct IOSB {
    261 	short iosb$w_value;
    262 	short iosb$w_count;
    263 	long  iosb$l_info;
    264 	};
    265 #endif
    266 
    267 #ifdef OPENSSL_SYS_SUNOS
    268 	typedef int sig_atomic_t;
    269 #endif
    270 
    271 #if defined(OPENSSL_SYS_MACINTOSH_CLASSIC) || defined(MAC_OS_GUSI_SOURCE) || defined(OPENSSL_SYS_NETWARE)
    272 /*
    273  * This one needs work. As a matter of fact the code is unoperational
    274  * and this is only a trick to get it compiled.
    275  *					<appro (at) fy.chalmers.se>
    276  */
    277 # define TTY_STRUCT int
    278 #endif
    279 
    280 #ifndef NX509_SIG
    281 # define NX509_SIG 32
    282 #endif
    283 
    284 
    285 /* Define globals.  They are protected by a lock */
    286 #ifdef SIGACTION
    287 static struct sigaction savsig[NX509_SIG];
    288 #else
    289 static void (*savsig[NX509_SIG])(int );
    290 #endif
    291 
    292 #ifdef OPENSSL_SYS_VMS
    293 static struct IOSB iosb;
    294 static $DESCRIPTOR(terminal,"TT");
    295 static long tty_orig[3], tty_new[3]; /* XXX   Is there any guarantee that this will always suffice for the actual structures? */
    296 static long status;
    297 static unsigned short channel = 0;
    298 #else
    299 #if !defined(OPENSSL_SYS_MSDOS) || defined(__DJGPP__)
    300 static TTY_STRUCT tty_orig,tty_new;
    301 #endif
    302 #endif
    303 static FILE *tty_in, *tty_out;
    304 static int is_a_tty;
    305 
    306 /* Declare static functions */
    307 #if !defined(OPENSSL_SYS_WIN16) && !defined(OPENSSL_SYS_WINCE)
    308 static int read_till_nl(FILE *);
    309 static void recsig(int);
    310 static void pushsig(void);
    311 static void popsig(void);
    312 #endif
    313 #if defined(OPENSSL_SYS_MSDOS) && !defined(OPENSSL_SYS_WIN16)
    314 static int noecho_fgets(char *buf, int size, FILE *tty);
    315 #endif
    316 static int read_string_inner(UI *ui, UI_STRING *uis, int echo, int strip_nl);
    317 
    318 static int read_string(UI *ui, UI_STRING *uis);
    319 static int write_string(UI *ui, UI_STRING *uis);
    320 
    321 static int open_console(UI *ui);
    322 static int echo_console(UI *ui);
    323 static int noecho_console(UI *ui);
    324 static int close_console(UI *ui);
    325 
    326 static UI_METHOD ui_openssl =
    327 	{
    328 	"OpenSSL default user interface",
    329 	open_console,
    330 	write_string,
    331 	NULL,			/* No flusher is needed for command lines */
    332 	read_string,
    333 	close_console,
    334 	NULL
    335 	};
    336 
    337 /* The method with all the built-in thingies */
    338 UI_METHOD *UI_OpenSSL(void)
    339 	{
    340 	return &ui_openssl;
    341 	}
    342 
    343 /* The following function makes sure that info and error strings are printed
    344    before any prompt. */
    345 static int write_string(UI *ui, UI_STRING *uis)
    346 	{
    347 	switch (UI_get_string_type(uis))
    348 		{
    349 	case UIT_ERROR:
    350 	case UIT_INFO:
    351 		fputs(UI_get0_output_string(uis), tty_out);
    352 		fflush(tty_out);
    353 		break;
    354 	default:
    355 		break;
    356 		}
    357 	return 1;
    358 	}
    359 
    360 static int read_string(UI *ui, UI_STRING *uis)
    361 	{
    362 	int ok = 0;
    363 
    364 	switch (UI_get_string_type(uis))
    365 		{
    366 	case UIT_BOOLEAN:
    367 		fputs(UI_get0_output_string(uis), tty_out);
    368 		fputs(UI_get0_action_string(uis), tty_out);
    369 		fflush(tty_out);
    370 		return read_string_inner(ui, uis,
    371 			UI_get_input_flags(uis) & UI_INPUT_FLAG_ECHO, 0);
    372 	case UIT_PROMPT:
    373 		fputs(UI_get0_output_string(uis), tty_out);
    374 		fflush(tty_out);
    375 		return read_string_inner(ui, uis,
    376 			UI_get_input_flags(uis) & UI_INPUT_FLAG_ECHO, 1);
    377 	case UIT_VERIFY:
    378 		fprintf(tty_out,"Verifying - %s",
    379 			UI_get0_output_string(uis));
    380 		fflush(tty_out);
    381 		if ((ok = read_string_inner(ui, uis,
    382 			UI_get_input_flags(uis) & UI_INPUT_FLAG_ECHO, 1)) <= 0)
    383 			return ok;
    384 		if (strcmp(UI_get0_result_string(uis),
    385 			UI_get0_test_string(uis)) != 0)
    386 			{
    387 			fprintf(tty_out,"Verify failure\n");
    388 			fflush(tty_out);
    389 			return 0;
    390 			}
    391 		break;
    392 	default:
    393 		break;
    394 		}
    395 	return 1;
    396 	}
    397 
    398 
    399 #if !defined(OPENSSL_SYS_WIN16) && !defined(OPENSSL_SYS_WINCE)
    400 /* Internal functions to read a string without echoing */
    401 static int read_till_nl(FILE *in)
    402 	{
    403 #define SIZE 4
    404 	char buf[SIZE+1];
    405 
    406 	do	{
    407 		if (!fgets(buf,SIZE,in))
    408 			return 0;
    409 		} while (strchr(buf,'\n') == NULL);
    410 	return 1;
    411 	}
    412 
    413 static volatile sig_atomic_t intr_signal;
    414 #endif
    415 
    416 static int read_string_inner(UI *ui, UI_STRING *uis, int echo, int strip_nl)
    417 	{
    418 	static int ps;
    419 	int ok;
    420 	char result[BUFSIZ];
    421 	int maxsize = BUFSIZ-1;
    422 #if !defined(OPENSSL_SYS_WIN16) && !defined(OPENSSL_SYS_WINCE)
    423 	char *p;
    424 
    425 	intr_signal=0;
    426 	ok=0;
    427 	ps=0;
    428 
    429 	pushsig();
    430 	ps=1;
    431 
    432 	if (!echo && !noecho_console(ui))
    433 		goto error;
    434 	ps=2;
    435 
    436 	result[0]='\0';
    437 #ifdef OPENSSL_SYS_MSDOS
    438 	if (!echo)
    439 		{
    440 		noecho_fgets(result,maxsize,tty_in);
    441 		p=result; /* FIXME: noecho_fgets doesn't return errors */
    442 		}
    443 	else
    444 		p=fgets(result,maxsize,tty_in);
    445 #else
    446 	p=fgets(result,maxsize,tty_in);
    447 #endif
    448 	if(!p)
    449 		goto error;
    450 	if (feof(tty_in)) goto error;
    451 	if (ferror(tty_in)) goto error;
    452 	if ((p=(char *)strchr(result,'\n')) != NULL)
    453 		{
    454 		if (strip_nl)
    455 			*p='\0';
    456 		}
    457 	else
    458 		if (!read_till_nl(tty_in))
    459 			goto error;
    460 	if (UI_set_result(ui, uis, result) >= 0)
    461 		ok=1;
    462 
    463 error:
    464 	if (intr_signal == SIGINT)
    465 		ok=-1;
    466 	if (!echo) fprintf(tty_out,"\n");
    467 	if (ps >= 2 && !echo && !echo_console(ui))
    468 		ok=0;
    469 
    470 	if (ps >= 1)
    471 		popsig();
    472 #else
    473 	ok=1;
    474 #endif
    475 
    476 	OPENSSL_cleanse(result,BUFSIZ);
    477 	return ok;
    478 	}
    479 
    480 
    481 /* Internal functions to open, handle and close a channel to the console.  */
    482 static int open_console(UI *ui)
    483 	{
    484 	CRYPTO_w_lock(CRYPTO_LOCK_UI);
    485 	is_a_tty = 1;
    486 
    487 #if defined(OPENSSL_SYS_MACINTOSH_CLASSIC) || defined(OPENSSL_SYS_VXWORKS) || defined(OPENSSL_SYS_NETWARE) || defined(OPENSSL_SYS_BEOS)
    488 	tty_in=stdin;
    489 	tty_out=stderr;
    490 #else
    491 #  ifdef OPENSSL_SYS_MSDOS
    492 #    define DEV_TTY "con"
    493 #  else
    494 #    define DEV_TTY "/dev/tty"
    495 #  endif
    496 	if ((tty_in=fopen(DEV_TTY,"r")) == NULL)
    497 		tty_in=stdin;
    498 	if ((tty_out=fopen(DEV_TTY,"w")) == NULL)
    499 		tty_out=stderr;
    500 #endif
    501 
    502 #if defined(TTY_get) && !defined(OPENSSL_SYS_VMS)
    503  	if (TTY_get(fileno(tty_in),&tty_orig) == -1)
    504 		{
    505 #ifdef ENOTTY
    506 		if (errno == ENOTTY)
    507 			is_a_tty=0;
    508 		else
    509 #endif
    510 #ifdef EINVAL
    511 		/* Ariel Glenn ariel (at) columbia.edu reports that solaris
    512 		 * can return EINVAL instead.  This should be ok */
    513 		if (errno == EINVAL)
    514 			is_a_tty=0;
    515 		else
    516 #endif
    517 			return 0;
    518 		}
    519 #endif
    520 #ifdef OPENSSL_SYS_VMS
    521 	status = sys$assign(&terminal,&channel,0,0);
    522 	if (status != SS$_NORMAL)
    523 		return 0;
    524 	status=sys$qiow(0,channel,IO$_SENSEMODE,&iosb,0,0,tty_orig,12,0,0,0,0);
    525 	if ((status != SS$_NORMAL) || (iosb.iosb$w_value != SS$_NORMAL))
    526 		return 0;
    527 #endif
    528 	return 1;
    529 	}
    530 
    531 static int noecho_console(UI *ui)
    532 	{
    533 #ifdef TTY_FLAGS
    534 	memcpy(&(tty_new),&(tty_orig),sizeof(tty_orig));
    535 	tty_new.TTY_FLAGS &= ~ECHO;
    536 #endif
    537 
    538 #if defined(TTY_set) && !defined(OPENSSL_SYS_VMS)
    539 	if (is_a_tty && (TTY_set(fileno(tty_in),&tty_new) == -1))
    540 		return 0;
    541 #endif
    542 #ifdef OPENSSL_SYS_VMS
    543 	tty_new[0] = tty_orig[0];
    544 	tty_new[1] = tty_orig[1] | TT$M_NOECHO;
    545 	tty_new[2] = tty_orig[2];
    546 	status = sys$qiow(0,channel,IO$_SETMODE,&iosb,0,0,tty_new,12,0,0,0,0);
    547 	if ((status != SS$_NORMAL) || (iosb.iosb$w_value != SS$_NORMAL))
    548 		return 0;
    549 #endif
    550 	return 1;
    551 	}
    552 
    553 static int echo_console(UI *ui)
    554 	{
    555 #if defined(TTY_set) && !defined(OPENSSL_SYS_VMS)
    556 	memcpy(&(tty_new),&(tty_orig),sizeof(tty_orig));
    557 	tty_new.TTY_FLAGS |= ECHO;
    558 #endif
    559 
    560 #if defined(TTY_set) && !defined(OPENSSL_SYS_VMS)
    561 	if (is_a_tty && (TTY_set(fileno(tty_in),&tty_new) == -1))
    562 		return 0;
    563 #endif
    564 #ifdef OPENSSL_SYS_VMS
    565 	tty_new[0] = tty_orig[0];
    566 	tty_new[1] = tty_orig[1] & ~TT$M_NOECHO;
    567 	tty_new[2] = tty_orig[2];
    568 	status = sys$qiow(0,channel,IO$_SETMODE,&iosb,0,0,tty_new,12,0,0,0,0);
    569 	if ((status != SS$_NORMAL) || (iosb.iosb$w_value != SS$_NORMAL))
    570 		return 0;
    571 #endif
    572 	return 1;
    573 	}
    574 
    575 static int close_console(UI *ui)
    576 	{
    577 	if (tty_in != stdin) fclose(tty_in);
    578 	if (tty_out != stderr) fclose(tty_out);
    579 #ifdef OPENSSL_SYS_VMS
    580 	status = sys$dassgn(channel);
    581 #endif
    582 	CRYPTO_w_unlock(CRYPTO_LOCK_UI);
    583 
    584 	return 1;
    585 	}
    586 
    587 
    588 #if !defined(OPENSSL_SYS_WIN16) && !defined(OPENSSL_SYS_WINCE)
    589 /* Internal functions to handle signals and act on them */
    590 static void pushsig(void)
    591 	{
    592 #ifndef OPENSSL_SYS_WIN32
    593 	int i;
    594 #endif
    595 #ifdef SIGACTION
    596 	struct sigaction sa;
    597 
    598 	memset(&sa,0,sizeof sa);
    599 	sa.sa_handler=recsig;
    600 #endif
    601 
    602 #ifdef OPENSSL_SYS_WIN32
    603 	savsig[SIGABRT]=signal(SIGABRT,recsig);
    604 	savsig[SIGFPE]=signal(SIGFPE,recsig);
    605 	savsig[SIGILL]=signal(SIGILL,recsig);
    606 	savsig[SIGINT]=signal(SIGINT,recsig);
    607 	savsig[SIGSEGV]=signal(SIGSEGV,recsig);
    608 	savsig[SIGTERM]=signal(SIGTERM,recsig);
    609 #else
    610 	for (i=1; i<NX509_SIG; i++)
    611 		{
    612 #ifdef SIGUSR1
    613 		if (i == SIGUSR1)
    614 			continue;
    615 #endif
    616 #ifdef SIGUSR2
    617 		if (i == SIGUSR2)
    618 			continue;
    619 #endif
    620 #ifdef SIGKILL
    621 		if (i == SIGKILL) /* We can't make any action on that. */
    622 			continue;
    623 #endif
    624 #ifdef SIGACTION
    625 		sigaction(i,&sa,&savsig[i]);
    626 #else
    627 		savsig[i]=signal(i,recsig);
    628 #endif
    629 		}
    630 #endif
    631 
    632 #ifdef SIGWINCH
    633 	signal(SIGWINCH,SIG_DFL);
    634 #endif
    635 	}
    636 
    637 static void popsig(void)
    638 	{
    639 #ifdef OPENSSL_SYS_WIN32
    640 	signal(SIGABRT,savsig[SIGABRT]);
    641 	signal(SIGFPE,savsig[SIGFPE]);
    642 	signal(SIGILL,savsig[SIGILL]);
    643 	signal(SIGINT,savsig[SIGINT]);
    644 	signal(SIGSEGV,savsig[SIGSEGV]);
    645 	signal(SIGTERM,savsig[SIGTERM]);
    646 #else
    647 	int i;
    648 	for (i=1; i<NX509_SIG; i++)
    649 		{
    650 #ifdef SIGUSR1
    651 		if (i == SIGUSR1)
    652 			continue;
    653 #endif
    654 #ifdef SIGUSR2
    655 		if (i == SIGUSR2)
    656 			continue;
    657 #endif
    658 #ifdef SIGACTION
    659 		sigaction(i,&savsig[i],NULL);
    660 #else
    661 		signal(i,savsig[i]);
    662 #endif
    663 		}
    664 #endif
    665 	}
    666 
    667 static void recsig(int i)
    668 	{
    669 	intr_signal=i;
    670 	}
    671 #endif
    672 
    673 /* Internal functions specific for Windows */
    674 #if defined(OPENSSL_SYS_MSDOS) && !defined(OPENSSL_SYS_WIN16) && !defined(OPENSSL_SYS_WINCE)
    675 static int noecho_fgets(char *buf, int size, FILE *tty)
    676 	{
    677 	int i;
    678 	char *p;
    679 
    680 	p=buf;
    681 	for (;;)
    682 		{
    683 		if (size == 0)
    684 			{
    685 			*p='\0';
    686 			break;
    687 			}
    688 		size--;
    689 #ifdef WIN16TTY
    690 		i=_inchar();
    691 #elif defined(_WIN32)
    692 		i=_getch();
    693 #else
    694 		i=getch();
    695 #endif
    696 		if (i == '\r') i='\n';
    697 		*(p++)=i;
    698 		if (i == '\n')
    699 			{
    700 			*p='\0';
    701 			break;
    702 			}
    703 		}
    704 #ifdef WIN_CONSOLE_BUG
    705 /* Win95 has several evil console bugs: one of these is that the
    706  * last character read using getch() is passed to the next read: this is
    707  * usually a CR so this can be trouble. No STDIO fix seems to work but
    708  * flushing the console appears to do the trick.
    709  */
    710 		{
    711 			HANDLE inh;
    712 			inh = GetStdHandle(STD_INPUT_HANDLE);
    713 			FlushConsoleInputBuffer(inh);
    714 		}
    715 #endif
    716 	return(strlen(buf));
    717 	}
    718 #endif
    719