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 #ifndef _POSIX_C_SOURCE
    126 #define _POSIX_C_SOURCE 2
    127 #endif
    128 #include <signal.h>
    129 #include <stdio.h>
    130 #include <string.h>
    131 #include <errno.h>
    132 
    133 #if !defined(OPENSSL_SYS_MSDOS) && !defined(OPENSSL_SYS_VMS)
    134 # ifdef OPENSSL_UNISTD
    135 #  include OPENSSL_UNISTD
    136 # else
    137 #  include <unistd.h>
    138 # endif
    139 /* If unistd.h defines _POSIX_VERSION, we conclude that we
    140  * are on a POSIX system and have sigaction and termios. */
    141 # if defined(_POSIX_VERSION)
    142 
    143 #  define SIGACTION
    144 #  if !defined(TERMIOS) && !defined(TERMIO) && !defined(SGTTY)
    145 #   define TERMIOS
    146 #  endif
    147 
    148 # endif
    149 #endif
    150 
    151 #ifdef WIN16TTY
    152 # undef OPENSSL_SYS_WIN16
    153 # undef WIN16
    154 # undef _WINDOWS
    155 # include <graph.h>
    156 #endif
    157 
    158 /* 06-Apr-92 Luke Brennan    Support for VMS */
    159 #include "ui_locl.h"
    160 #include "cryptlib.h"
    161 
    162 #ifdef OPENSSL_SYS_VMS		/* prototypes for sys$whatever */
    163 # include <starlet.h>
    164 # ifdef __DECC
    165 #  pragma message disable DOLLARID
    166 # endif
    167 #endif
    168 
    169 #ifdef WIN_CONSOLE_BUG
    170 # include <windows.h>
    171 #ifndef OPENSSL_SYS_WINCE
    172 # include <wincon.h>
    173 #endif
    174 #endif
    175 
    176 
    177 /* There are 5 types of terminal interface supported,
    178  * TERMIO, TERMIOS, VMS, MSDOS and SGTTY
    179  */
    180 
    181 #if defined(__sgi) && !defined(TERMIOS)
    182 # define TERMIOS
    183 # undef  TERMIO
    184 # undef  SGTTY
    185 #endif
    186 
    187 #if defined(linux) && !defined(TERMIO) && !defined(__ANDROID__)
    188 # undef  TERMIOS
    189 # define TERMIO
    190 # undef  SGTTY
    191 #endif
    192 
    193 #ifdef _LIBC
    194 # undef  TERMIOS
    195 # define TERMIO
    196 # undef  SGTTY
    197 #endif
    198 
    199 #if !defined(TERMIO) && !defined(TERMIOS) && !defined(OPENSSL_SYS_VMS) && !defined(OPENSSL_SYS_MSDOS) && !defined(OPENSSL_SYS_MACINTOSH_CLASSIC) && !defined(MAC_OS_GUSI_SOURCE)
    200 # undef  TERMIOS
    201 # undef  TERMIO
    202 # define SGTTY
    203 #endif
    204 
    205 #if defined(OPENSSL_SYS_VXWORKS)
    206 #undef TERMIOS
    207 #undef TERMIO
    208 #undef SGTTY
    209 #endif
    210 
    211 #if defined(OPENSSL_SYS_NETWARE)
    212 #undef TERMIOS
    213 #undef TERMIO
    214 #undef SGTTY
    215 #endif
    216 
    217 #ifdef TERMIOS
    218 # include <termios.h>
    219 # define TTY_STRUCT		struct termios
    220 # define TTY_FLAGS		c_lflag
    221 # define TTY_get(tty,data)	tcgetattr(tty,data)
    222 # define TTY_set(tty,data)	tcsetattr(tty,TCSANOW,data)
    223 #endif
    224 
    225 #ifdef TERMIO
    226 # include <termio.h>
    227 # define TTY_STRUCT		struct termio
    228 # define TTY_FLAGS		c_lflag
    229 # define TTY_get(tty,data)	ioctl(tty,TCGETA,data)
    230 # define TTY_set(tty,data)	ioctl(tty,TCSETA,data)
    231 #endif
    232 
    233 #ifdef SGTTY
    234 # include <sgtty.h>
    235 # define TTY_STRUCT		struct sgttyb
    236 # define TTY_FLAGS		sg_flags
    237 # define TTY_get(tty,data)	ioctl(tty,TIOCGETP,data)
    238 # define TTY_set(tty,data)	ioctl(tty,TIOCSETP,data)
    239 #endif
    240 
    241 #if !defined(_LIBC) && !defined(OPENSSL_SYS_MSDOS) && !defined(OPENSSL_SYS_VMS) && !defined(OPENSSL_SYS_MACINTOSH_CLASSIC) && !defined(OPENSSL_SYS_SUNOS)
    242 # include <sys/ioctl.h>
    243 #endif
    244 
    245 #ifdef OPENSSL_SYS_MSDOS
    246 # include <conio.h>
    247 #endif
    248 
    249 #ifdef OPENSSL_SYS_VMS
    250 # include <ssdef.h>
    251 # include <iodef.h>
    252 # include <ttdef.h>
    253 # include <descrip.h>
    254 struct IOSB {
    255 	short iosb$w_value;
    256 	short iosb$w_count;
    257 	long  iosb$l_info;
    258 	};
    259 #endif
    260 
    261 #ifdef OPENSSL_SYS_SUNOS
    262 	typedef int sig_atomic_t;
    263 #endif
    264 
    265 #if defined(OPENSSL_SYS_MACINTOSH_CLASSIC) || defined(MAC_OS_GUSI_SOURCE) || defined(OPENSSL_SYS_NETWARE)
    266 /*
    267  * This one needs work. As a matter of fact the code is unoperational
    268  * and this is only a trick to get it compiled.
    269  *					<appro (at) fy.chalmers.se>
    270  */
    271 # define TTY_STRUCT int
    272 #endif
    273 
    274 #ifndef NX509_SIG
    275 # define NX509_SIG 32
    276 #endif
    277 
    278 
    279 /* Define globals.  They are protected by a lock */
    280 #ifdef SIGACTION
    281 static struct sigaction savsig[NX509_SIG];
    282 #else
    283 static void (*savsig[NX509_SIG])(int );
    284 #endif
    285 
    286 #ifdef OPENSSL_SYS_VMS
    287 static struct IOSB iosb;
    288 static $DESCRIPTOR(terminal,"TT");
    289 static long tty_orig[3], tty_new[3]; /* XXX   Is there any guarantee that this will always suffice for the actual structures? */
    290 static long status;
    291 static unsigned short channel = 0;
    292 #else
    293 #if !defined(OPENSSL_SYS_MSDOS) || defined(__DJGPP__)
    294 static TTY_STRUCT tty_orig,tty_new;
    295 #endif
    296 #endif
    297 static FILE *tty_in, *tty_out;
    298 static int is_a_tty;
    299 
    300 /* Declare static functions */
    301 #if !defined(OPENSSL_SYS_WIN16) && !defined(OPENSSL_SYS_WINCE)
    302 static int read_till_nl(FILE *);
    303 static void recsig(int);
    304 static void pushsig(void);
    305 static void popsig(void);
    306 #endif
    307 #if defined(OPENSSL_SYS_MSDOS) && !defined(OPENSSL_SYS_WIN16)
    308 static int noecho_fgets(char *buf, int size, FILE *tty);
    309 #endif
    310 static int read_string_inner(UI *ui, UI_STRING *uis, int echo, int strip_nl);
    311 
    312 static int read_string(UI *ui, UI_STRING *uis);
    313 static int write_string(UI *ui, UI_STRING *uis);
    314 
    315 static int open_console(UI *ui);
    316 static int echo_console(UI *ui);
    317 static int noecho_console(UI *ui);
    318 static int close_console(UI *ui);
    319 
    320 static UI_METHOD ui_openssl =
    321 	{
    322 	"OpenSSL default user interface",
    323 	open_console,
    324 	write_string,
    325 	NULL,			/* No flusher is needed for command lines */
    326 	read_string,
    327 	close_console,
    328 	NULL
    329 	};
    330 
    331 /* The method with all the built-in thingies */
    332 UI_METHOD *UI_OpenSSL(void)
    333 	{
    334 	return &ui_openssl;
    335 	}
    336 
    337 /* The following function makes sure that info and error strings are printed
    338    before any prompt. */
    339 static int write_string(UI *ui, UI_STRING *uis)
    340 	{
    341 	switch (UI_get_string_type(uis))
    342 		{
    343 	case UIT_ERROR:
    344 	case UIT_INFO:
    345 		fputs(UI_get0_output_string(uis), tty_out);
    346 		fflush(tty_out);
    347 		break;
    348 	default:
    349 		break;
    350 		}
    351 	return 1;
    352 	}
    353 
    354 static int read_string(UI *ui, UI_STRING *uis)
    355 	{
    356 	int ok = 0;
    357 
    358 	switch (UI_get_string_type(uis))
    359 		{
    360 	case UIT_BOOLEAN:
    361 		fputs(UI_get0_output_string(uis), tty_out);
    362 		fputs(UI_get0_action_string(uis), tty_out);
    363 		fflush(tty_out);
    364 		return read_string_inner(ui, uis,
    365 			UI_get_input_flags(uis) & UI_INPUT_FLAG_ECHO, 0);
    366 	case UIT_PROMPT:
    367 		fputs(UI_get0_output_string(uis), tty_out);
    368 		fflush(tty_out);
    369 		return read_string_inner(ui, uis,
    370 			UI_get_input_flags(uis) & UI_INPUT_FLAG_ECHO, 1);
    371 	case UIT_VERIFY:
    372 		fprintf(tty_out,"Verifying - %s",
    373 			UI_get0_output_string(uis));
    374 		fflush(tty_out);
    375 		if ((ok = read_string_inner(ui, uis,
    376 			UI_get_input_flags(uis) & UI_INPUT_FLAG_ECHO, 1)) <= 0)
    377 			return ok;
    378 		if (strcmp(UI_get0_result_string(uis),
    379 			UI_get0_test_string(uis)) != 0)
    380 			{
    381 			fprintf(tty_out,"Verify failure\n");
    382 			fflush(tty_out);
    383 			return 0;
    384 			}
    385 		break;
    386 	default:
    387 		break;
    388 		}
    389 	return 1;
    390 	}
    391 
    392 
    393 #if !defined(OPENSSL_SYS_WIN16) && !defined(OPENSSL_SYS_WINCE)
    394 /* Internal functions to read a string without echoing */
    395 static int read_till_nl(FILE *in)
    396 	{
    397 #define SIZE 4
    398 	char buf[SIZE+1];
    399 
    400 	do	{
    401 		if (!fgets(buf,SIZE,in))
    402 			return 0;
    403 		} while (strchr(buf,'\n') == NULL);
    404 	return 1;
    405 	}
    406 
    407 static volatile sig_atomic_t intr_signal;
    408 #endif
    409 
    410 static int read_string_inner(UI *ui, UI_STRING *uis, int echo, int strip_nl)
    411 	{
    412 	static int ps;
    413 	int ok;
    414 	char result[BUFSIZ];
    415 	int maxsize = BUFSIZ-1;
    416 #if !defined(OPENSSL_SYS_WIN16) && !defined(OPENSSL_SYS_WINCE)
    417 	char *p;
    418 
    419 	intr_signal=0;
    420 	ok=0;
    421 	ps=0;
    422 
    423 	pushsig();
    424 	ps=1;
    425 
    426 	if (!echo && !noecho_console(ui))
    427 		goto error;
    428 	ps=2;
    429 
    430 	result[0]='\0';
    431 #ifdef OPENSSL_SYS_MSDOS
    432 	if (!echo)
    433 		{
    434 		noecho_fgets(result,maxsize,tty_in);
    435 		p=result; /* FIXME: noecho_fgets doesn't return errors */
    436 		}
    437 	else
    438 		p=fgets(result,maxsize,tty_in);
    439 #else
    440 	p=fgets(result,maxsize,tty_in);
    441 #endif
    442 	if(!p)
    443 		goto error;
    444 	if (feof(tty_in)) goto error;
    445 	if (ferror(tty_in)) goto error;
    446 	if ((p=(char *)strchr(result,'\n')) != NULL)
    447 		{
    448 		if (strip_nl)
    449 			*p='\0';
    450 		}
    451 	else
    452 		if (!read_till_nl(tty_in))
    453 			goto error;
    454 	if (UI_set_result(ui, uis, result) >= 0)
    455 		ok=1;
    456 
    457 error:
    458 	if (intr_signal == SIGINT)
    459 		ok=-1;
    460 	if (!echo) fprintf(tty_out,"\n");
    461 	if (ps >= 2 && !echo && !echo_console(ui))
    462 		ok=0;
    463 
    464 	if (ps >= 1)
    465 		popsig();
    466 #else
    467 	ok=1;
    468 #endif
    469 
    470 	OPENSSL_cleanse(result,BUFSIZ);
    471 	return ok;
    472 	}
    473 
    474 
    475 /* Internal functions to open, handle and close a channel to the console.  */
    476 static int open_console(UI *ui)
    477 	{
    478 	CRYPTO_w_lock(CRYPTO_LOCK_UI);
    479 	is_a_tty = 1;
    480 
    481 #if defined(OPENSSL_SYS_MACINTOSH_CLASSIC) || defined(OPENSSL_SYS_VXWORKS) || defined(OPENSSL_SYS_NETWARE) || defined(OPENSSL_SYS_BEOS)
    482 	tty_in=stdin;
    483 	tty_out=stderr;
    484 #else
    485 #  ifdef OPENSSL_SYS_MSDOS
    486 #    define DEV_TTY "con"
    487 #  else
    488 #    define DEV_TTY "/dev/tty"
    489 #  endif
    490 	if ((tty_in=fopen(DEV_TTY,"r")) == NULL)
    491 		tty_in=stdin;
    492 	if ((tty_out=fopen(DEV_TTY,"w")) == NULL)
    493 		tty_out=stderr;
    494 #endif
    495 
    496 #if defined(TTY_get) && !defined(OPENSSL_SYS_VMS)
    497  	if (TTY_get(fileno(tty_in),&tty_orig) == -1)
    498 		{
    499 #ifdef ENOTTY
    500 		if (errno == ENOTTY)
    501 			is_a_tty=0;
    502 		else
    503 #endif
    504 #ifdef EINVAL
    505 		/* Ariel Glenn ariel (at) columbia.edu reports that solaris
    506 		 * can return EINVAL instead.  This should be ok */
    507 		if (errno == EINVAL)
    508 			is_a_tty=0;
    509 		else
    510 #endif
    511 			return 0;
    512 		}
    513 #endif
    514 #ifdef OPENSSL_SYS_VMS
    515 	status = sys$assign(&terminal,&channel,0,0);
    516 	if (status != SS$_NORMAL)
    517 		return 0;
    518 	status=sys$qiow(0,channel,IO$_SENSEMODE,&iosb,0,0,tty_orig,12,0,0,0,0);
    519 	if ((status != SS$_NORMAL) || (iosb.iosb$w_value != SS$_NORMAL))
    520 		return 0;
    521 #endif
    522 	return 1;
    523 	}
    524 
    525 static int noecho_console(UI *ui)
    526 	{
    527 #ifdef TTY_FLAGS
    528 	memcpy(&(tty_new),&(tty_orig),sizeof(tty_orig));
    529 	tty_new.TTY_FLAGS &= ~ECHO;
    530 #endif
    531 
    532 #if defined(TTY_set) && !defined(OPENSSL_SYS_VMS)
    533 	if (is_a_tty && (TTY_set(fileno(tty_in),&tty_new) == -1))
    534 		return 0;
    535 #endif
    536 #ifdef OPENSSL_SYS_VMS
    537 	tty_new[0] = tty_orig[0];
    538 	tty_new[1] = tty_orig[1] | TT$M_NOECHO;
    539 	tty_new[2] = tty_orig[2];
    540 	status = sys$qiow(0,channel,IO$_SETMODE,&iosb,0,0,tty_new,12,0,0,0,0);
    541 	if ((status != SS$_NORMAL) || (iosb.iosb$w_value != SS$_NORMAL))
    542 		return 0;
    543 #endif
    544 	return 1;
    545 	}
    546 
    547 static int echo_console(UI *ui)
    548 	{
    549 #if defined(TTY_set) && !defined(OPENSSL_SYS_VMS)
    550 	memcpy(&(tty_new),&(tty_orig),sizeof(tty_orig));
    551 	tty_new.TTY_FLAGS |= ECHO;
    552 #endif
    553 
    554 #if defined(TTY_set) && !defined(OPENSSL_SYS_VMS)
    555 	if (is_a_tty && (TTY_set(fileno(tty_in),&tty_new) == -1))
    556 		return 0;
    557 #endif
    558 #ifdef OPENSSL_SYS_VMS
    559 	tty_new[0] = tty_orig[0];
    560 	tty_new[1] = tty_orig[1] & ~TT$M_NOECHO;
    561 	tty_new[2] = tty_orig[2];
    562 	status = sys$qiow(0,channel,IO$_SETMODE,&iosb,0,0,tty_new,12,0,0,0,0);
    563 	if ((status != SS$_NORMAL) || (iosb.iosb$w_value != SS$_NORMAL))
    564 		return 0;
    565 #endif
    566 	return 1;
    567 	}
    568 
    569 static int close_console(UI *ui)
    570 	{
    571 	if (tty_in != stdin) fclose(tty_in);
    572 	if (tty_out != stderr) fclose(tty_out);
    573 #ifdef OPENSSL_SYS_VMS
    574 	status = sys$dassgn(channel);
    575 #endif
    576 	CRYPTO_w_unlock(CRYPTO_LOCK_UI);
    577 
    578 	return 1;
    579 	}
    580 
    581 
    582 #if !defined(OPENSSL_SYS_WIN16) && !defined(OPENSSL_SYS_WINCE)
    583 /* Internal functions to handle signals and act on them */
    584 static void pushsig(void)
    585 	{
    586 #ifndef OPENSSL_SYS_WIN32
    587 	int i;
    588 #endif
    589 #ifdef SIGACTION
    590 	struct sigaction sa;
    591 
    592 	memset(&sa,0,sizeof sa);
    593 	sa.sa_handler=recsig;
    594 #endif
    595 
    596 #ifdef OPENSSL_SYS_WIN32
    597 	savsig[SIGABRT]=signal(SIGABRT,recsig);
    598 	savsig[SIGFPE]=signal(SIGFPE,recsig);
    599 	savsig[SIGILL]=signal(SIGILL,recsig);
    600 	savsig[SIGINT]=signal(SIGINT,recsig);
    601 	savsig[SIGSEGV]=signal(SIGSEGV,recsig);
    602 	savsig[SIGTERM]=signal(SIGTERM,recsig);
    603 #else
    604 	for (i=1; i<NX509_SIG; i++)
    605 		{
    606 #ifdef SIGUSR1
    607 		if (i == SIGUSR1)
    608 			continue;
    609 #endif
    610 #ifdef SIGUSR2
    611 		if (i == SIGUSR2)
    612 			continue;
    613 #endif
    614 #ifdef SIGKILL
    615 		if (i == SIGKILL) /* We can't make any action on that. */
    616 			continue;
    617 #endif
    618 #ifdef SIGACTION
    619 		sigaction(i,&sa,&savsig[i]);
    620 #else
    621 		savsig[i]=signal(i,recsig);
    622 #endif
    623 		}
    624 #endif
    625 
    626 #ifdef SIGWINCH
    627 	signal(SIGWINCH,SIG_DFL);
    628 #endif
    629 	}
    630 
    631 static void popsig(void)
    632 	{
    633 #ifdef OPENSSL_SYS_WIN32
    634 	signal(SIGABRT,savsig[SIGABRT]);
    635 	signal(SIGFPE,savsig[SIGFPE]);
    636 	signal(SIGILL,savsig[SIGILL]);
    637 	signal(SIGINT,savsig[SIGINT]);
    638 	signal(SIGSEGV,savsig[SIGSEGV]);
    639 	signal(SIGTERM,savsig[SIGTERM]);
    640 #else
    641 	int i;
    642 	for (i=1; i<NX509_SIG; i++)
    643 		{
    644 #ifdef SIGUSR1
    645 		if (i == SIGUSR1)
    646 			continue;
    647 #endif
    648 #ifdef SIGUSR2
    649 		if (i == SIGUSR2)
    650 			continue;
    651 #endif
    652 #ifdef SIGACTION
    653 		sigaction(i,&savsig[i],NULL);
    654 #else
    655 		signal(i,savsig[i]);
    656 #endif
    657 		}
    658 #endif
    659 	}
    660 
    661 static void recsig(int i)
    662 	{
    663 	intr_signal=i;
    664 	}
    665 #endif
    666 
    667 /* Internal functions specific for Windows */
    668 #if defined(OPENSSL_SYS_MSDOS) && !defined(OPENSSL_SYS_WIN16) && !defined(OPENSSL_SYS_WINCE)
    669 static int noecho_fgets(char *buf, int size, FILE *tty)
    670 	{
    671 	int i;
    672 	char *p;
    673 
    674 	p=buf;
    675 	for (;;)
    676 		{
    677 		if (size == 0)
    678 			{
    679 			*p='\0';
    680 			break;
    681 			}
    682 		size--;
    683 #ifdef WIN16TTY
    684 		i=_inchar();
    685 #elif defined(_WIN32)
    686 		i=_getch();
    687 #else
    688 		i=getch();
    689 #endif
    690 		if (i == '\r') i='\n';
    691 		*(p++)=i;
    692 		if (i == '\n')
    693 			{
    694 			*p='\0';
    695 			break;
    696 			}
    697 		}
    698 #ifdef WIN_CONSOLE_BUG
    699 /* Win95 has several evil console bugs: one of these is that the
    700  * last character read using getch() is passed to the next read: this is
    701  * usually a CR so this can be trouble. No STDIO fix seems to work but
    702  * flushing the console appears to do the trick.
    703  */
    704 		{
    705 			HANDLE inh;
    706 			inh = GetStdHandle(STD_INPUT_HANDLE);
    707 			FlushConsoleInputBuffer(inh);
    708 		}
    709 #endif
    710 	return(strlen(buf));
    711 	}
    712 #endif
    713