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