1295016Sjkim/* crypto/ui/ui_openssl.c */
2280304Sjkim/*
3280304Sjkim * Written by Richard Levitte (richard@levitte.org) and others for the
4280304Sjkim * 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
14280304Sjkim *    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
60280304Sjkim/*-
61280304Sjkim * 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.
68280304Sjkim *
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).
75280304Sjkim *
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.
82280304Sjkim *
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 :-).
97280304Sjkim * 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)"
100280304Sjkim *
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.
112280304Sjkim *
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
121280304Sjkim/*
122280304Sjkim * need for #define _POSIX_C_SOURCE arises whenever you pass -ansi to gcc
123160814Ssimon * [maybe others?], because it masks interfaces not discussed in standard,
124280304Sjkim * sigaction and fileno included. -pedantic would be more appropriate for the
125280304Sjkim * intended purposes, but we can't prevent users from adding -ansi.
126160814Ssimon */
127246772Sjkim#if defined(OPENSSL_SYSNAME_VXWORKS)
128280304Sjkim# include <sys/types.h>
129246772Sjkim#endif
130246772Sjkim
131238405Sjkim#if !defined(_POSIX_C_SOURCE) && defined(OPENSSL_SYS_VMS)
132280304Sjkim# ifndef _POSIX_C_SOURCE
133280304Sjkim#  define _POSIX_C_SOURCE 2
134280304Sjkim# endif
135238405Sjkim#endif
136160814Ssimon#include <signal.h>
137160814Ssimon#include <stdio.h>
138160814Ssimon#include <string.h>
139160814Ssimon#include <errno.h>
140160814Ssimon
141109998Smarkm#if !defined(OPENSSL_SYS_MSDOS) && !defined(OPENSSL_SYS_VMS)
142109998Smarkm# ifdef OPENSSL_UNISTD
143109998Smarkm#  include OPENSSL_UNISTD
144109998Smarkm# else
145109998Smarkm#  include <unistd.h>
146109998Smarkm# endif
147280304Sjkim/*
148280304Sjkim * If unistd.h defines _POSIX_VERSION, we conclude that we are on a POSIX
149280304Sjkim * system and have sigaction and termios.
150280304Sjkim */
151109998Smarkm# if defined(_POSIX_VERSION)
152109998Smarkm
153109998Smarkm#  define SIGACTION
154109998Smarkm#  if !defined(TERMIOS) && !defined(TERMIO) && !defined(SGTTY)
155109998Smarkm#   define TERMIOS
156109998Smarkm#  endif
157109998Smarkm
158109998Smarkm# endif
159109998Smarkm#endif
160109998Smarkm
161109998Smarkm#ifdef WIN16TTY
162109998Smarkm# undef OPENSSL_SYS_WIN16
163109998Smarkm# undef WIN16
164109998Smarkm# undef _WINDOWS
165109998Smarkm# include <graph.h>
166109998Smarkm#endif
167109998Smarkm
168109998Smarkm/* 06-Apr-92 Luke Brennan    Support for VMS */
169109998Smarkm#include "ui_locl.h"
170109998Smarkm#include "cryptlib.h"
171109998Smarkm
172280304Sjkim#ifdef OPENSSL_SYS_VMS          /* prototypes for sys$whatever */
173109998Smarkm# include <starlet.h>
174109998Smarkm# ifdef __DECC
175109998Smarkm#  pragma message disable DOLLARID
176109998Smarkm# endif
177109998Smarkm#endif
178109998Smarkm
179109998Smarkm#ifdef WIN_CONSOLE_BUG
180109998Smarkm# include <windows.h>
181280304Sjkim# ifndef OPENSSL_SYS_WINCE
182280304Sjkim#  include <wincon.h>
183280304Sjkim# endif
184109998Smarkm#endif
185109998Smarkm
186280304Sjkim/*
187280304Sjkim * There are 5 types of terminal interface supported, TERMIO, TERMIOS, VMS,
188280304Sjkim * MSDOS and SGTTY.
189280304Sjkim *
190280304Sjkim * If someone defines one of the macros TERMIO, TERMIOS or SGTTY, it will
191280304Sjkim * remain respected.  Otherwise, we default to TERMIOS except for a few
192280304Sjkim * systems that require something different.
193280304Sjkim *
194280304Sjkim * Note: we do not use SGTTY unless it's defined by the configuration.  We
195280304Sjkim * may eventually opt to remove it's use entirely.
196109998Smarkm */
197109998Smarkm
198280304Sjkim#if !defined(TERMIOS) && !defined(TERMIO) && !defined(SGTTY)
199109998Smarkm
200280304Sjkim# if defined(_LIBC)
201280304Sjkim#  undef  TERMIOS
202280304Sjkim#  define TERMIO
203280304Sjkim#  undef  SGTTY
204280304Sjkim/*
205280304Sjkim * We know that VMS, MSDOS, VXWORKS, NETWARE use entirely other mechanisms.
206280304Sjkim * MAC_OS_GUSI_SOURCE should probably go away, but that needs to be confirmed.
207280304Sjkim */
208280304Sjkim# elif !defined(OPENSSL_SYS_VMS) \
209280304Sjkim	&& !defined(OPENSSL_SYS_MSDOS) \
210280304Sjkim	&& !defined(OPENSSL_SYS_MACINTOSH_CLASSIC) \
211280304Sjkim	&& !defined(MAC_OS_GUSI_SOURCE) \
212280304Sjkim	&& !defined(OPENSSL_SYS_VXWORKS) \
213280304Sjkim	&& !defined(OPENSSL_SYS_NETWARE)
214280304Sjkim#  define TERMIOS
215280304Sjkim#  undef  TERMIO
216280304Sjkim#  undef  SGTTY
217280304Sjkim# endif
218109998Smarkm
219109998Smarkm#endif
220109998Smarkm
221109998Smarkm#ifdef TERMIOS
222109998Smarkm# include <termios.h>
223280304Sjkim# define TTY_STRUCT             struct termios
224280304Sjkim# define TTY_FLAGS              c_lflag
225280304Sjkim# define TTY_get(tty,data)      tcgetattr(tty,data)
226280304Sjkim# define TTY_set(tty,data)      tcsetattr(tty,TCSANOW,data)
227109998Smarkm#endif
228109998Smarkm
229109998Smarkm#ifdef TERMIO
230109998Smarkm# include <termio.h>
231280304Sjkim# define TTY_STRUCT             struct termio
232280304Sjkim# define TTY_FLAGS              c_lflag
233280304Sjkim# define TTY_get(tty,data)      ioctl(tty,TCGETA,data)
234280304Sjkim# define TTY_set(tty,data)      ioctl(tty,TCSETA,data)
235109998Smarkm#endif
236109998Smarkm
237109998Smarkm#ifdef SGTTY
238109998Smarkm# include <sgtty.h>
239280304Sjkim# define TTY_STRUCT             struct sgttyb
240280304Sjkim# define TTY_FLAGS              sg_flags
241280304Sjkim# define TTY_get(tty,data)      ioctl(tty,TIOCGETP,data)
242280304Sjkim# define TTY_set(tty,data)      ioctl(tty,TIOCSETP,data)
243109998Smarkm#endif
244109998Smarkm
245109998Smarkm#if !defined(_LIBC) && !defined(OPENSSL_SYS_MSDOS) && !defined(OPENSSL_SYS_VMS) && !defined(OPENSSL_SYS_MACINTOSH_CLASSIC) && !defined(OPENSSL_SYS_SUNOS)
246109998Smarkm# include <sys/ioctl.h>
247109998Smarkm#endif
248109998Smarkm
249109998Smarkm#ifdef OPENSSL_SYS_MSDOS
250109998Smarkm# include <conio.h>
251109998Smarkm#endif
252109998Smarkm
253109998Smarkm#ifdef OPENSSL_SYS_VMS
254109998Smarkm# include <ssdef.h>
255109998Smarkm# include <iodef.h>
256109998Smarkm# include <ttdef.h>
257109998Smarkm# include <descrip.h>
258109998Smarkmstruct IOSB {
259280304Sjkim    short iosb$w_value;
260280304Sjkim    short iosb$w_count;
261280304Sjkim    long iosb$l_info;
262280304Sjkim};
263109998Smarkm#endif
264109998Smarkm
265109998Smarkm#ifdef OPENSSL_SYS_SUNOS
266280304Sjkimtypedef int sig_atomic_t;
267109998Smarkm#endif
268109998Smarkm
269160814Ssimon#if defined(OPENSSL_SYS_MACINTOSH_CLASSIC) || defined(MAC_OS_GUSI_SOURCE) || defined(OPENSSL_SYS_NETWARE)
270109998Smarkm/*
271109998Smarkm * This one needs work. As a matter of fact the code is unoperational
272109998Smarkm * and this is only a trick to get it compiled.
273280304Sjkim *                                      <appro@fy.chalmers.se>
274109998Smarkm */
275109998Smarkm# define TTY_STRUCT int
276109998Smarkm#endif
277109998Smarkm
278109998Smarkm#ifndef NX509_SIG
279109998Smarkm# define NX509_SIG 32
280109998Smarkm#endif
281109998Smarkm
282109998Smarkm/* Define globals.  They are protected by a lock */
283109998Smarkm#ifdef SIGACTION
284109998Smarkmstatic struct sigaction savsig[NX509_SIG];
285109998Smarkm#else
286280304Sjkimstatic void (*savsig[NX509_SIG]) (int);
287109998Smarkm#endif
288109998Smarkm
289109998Smarkm#ifdef OPENSSL_SYS_VMS
290109998Smarkmstatic struct IOSB iosb;
291280304Sjkimstatic $DESCRIPTOR(terminal, "TT");
292280304Sjkimstatic long tty_orig[3], tty_new[3]; /* XXX Is there any guarantee that this
293280304Sjkim                                      * will always suffice for the actual
294280304Sjkim                                      * structures? */
295109998Smarkmstatic long status;
296109998Smarkmstatic unsigned short channel = 0;
297109998Smarkm#else
298280304Sjkim# if !defined(OPENSSL_SYS_MSDOS) || defined(__DJGPP__)
299280304Sjkimstatic TTY_STRUCT tty_orig, tty_new;
300280304Sjkim# endif
301109998Smarkm#endif
302109998Smarkmstatic FILE *tty_in, *tty_out;
303109998Smarkmstatic int is_a_tty;
304109998Smarkm
305109998Smarkm/* Declare static functions */
306109998Smarkm#if !defined(OPENSSL_SYS_WIN16) && !defined(OPENSSL_SYS_WINCE)
307205128Ssimonstatic int read_till_nl(FILE *);
308109998Smarkmstatic void recsig(int);
309109998Smarkmstatic void pushsig(void);
310109998Smarkmstatic void popsig(void);
311109998Smarkm#endif
312109998Smarkm#if defined(OPENSSL_SYS_MSDOS) && !defined(OPENSSL_SYS_WIN16)
313109998Smarkmstatic int noecho_fgets(char *buf, int size, FILE *tty);
314109998Smarkm#endif
315109998Smarkmstatic int read_string_inner(UI *ui, UI_STRING *uis, int echo, int strip_nl);
316109998Smarkm
317109998Smarkmstatic int read_string(UI *ui, UI_STRING *uis);
318109998Smarkmstatic int write_string(UI *ui, UI_STRING *uis);
319109998Smarkm
320109998Smarkmstatic int open_console(UI *ui);
321109998Smarkmstatic int echo_console(UI *ui);
322109998Smarkmstatic int noecho_console(UI *ui);
323109998Smarkmstatic int close_console(UI *ui);
324109998Smarkm
325280304Sjkimstatic UI_METHOD ui_openssl = {
326280304Sjkim    "OpenSSL default user interface",
327280304Sjkim    open_console,
328280304Sjkim    write_string,
329280304Sjkim    NULL,                       /* No flusher is needed for command lines */
330280304Sjkim    read_string,
331280304Sjkim    close_console,
332280304Sjkim    NULL
333280304Sjkim};
334109998Smarkm
335109998Smarkm/* The method with all the built-in thingies */
336109998SmarkmUI_METHOD *UI_OpenSSL(void)
337280304Sjkim{
338280304Sjkim    return &ui_openssl;
339280304Sjkim}
340109998Smarkm
341280304Sjkim/*
342280304Sjkim * The following function makes sure that info and error strings are printed
343280304Sjkim * before any prompt.
344280304Sjkim */
345109998Smarkmstatic int write_string(UI *ui, UI_STRING *uis)
346280304Sjkim{
347280304Sjkim    switch (UI_get_string_type(uis)) {
348280304Sjkim    case UIT_ERROR:
349280304Sjkim    case UIT_INFO:
350280304Sjkim        fputs(UI_get0_output_string(uis), tty_out);
351280304Sjkim        fflush(tty_out);
352280304Sjkim        break;
353280304Sjkim    default:
354280304Sjkim        break;
355280304Sjkim    }
356280304Sjkim    return 1;
357280304Sjkim}
358109998Smarkm
359109998Smarkmstatic int read_string(UI *ui, UI_STRING *uis)
360280304Sjkim{
361280304Sjkim    int ok = 0;
362109998Smarkm
363280304Sjkim    switch (UI_get_string_type(uis)) {
364280304Sjkim    case UIT_BOOLEAN:
365280304Sjkim        fputs(UI_get0_output_string(uis), tty_out);
366280304Sjkim        fputs(UI_get0_action_string(uis), tty_out);
367280304Sjkim        fflush(tty_out);
368280304Sjkim        return read_string_inner(ui, uis,
369280304Sjkim                                 UI_get_input_flags(uis) & UI_INPUT_FLAG_ECHO,
370280304Sjkim                                 0);
371280304Sjkim    case UIT_PROMPT:
372280304Sjkim        fputs(UI_get0_output_string(uis), tty_out);
373280304Sjkim        fflush(tty_out);
374280304Sjkim        return read_string_inner(ui, uis,
375280304Sjkim                                 UI_get_input_flags(uis) & UI_INPUT_FLAG_ECHO,
376280304Sjkim                                 1);
377280304Sjkim    case UIT_VERIFY:
378280304Sjkim        fprintf(tty_out, "Verifying - %s", UI_get0_output_string(uis));
379280304Sjkim        fflush(tty_out);
380280304Sjkim        if ((ok = read_string_inner(ui, uis,
381280304Sjkim                                    UI_get_input_flags(uis) &
382280304Sjkim                                    UI_INPUT_FLAG_ECHO, 1)) <= 0)
383280304Sjkim            return ok;
384280304Sjkim        if (strcmp(UI_get0_result_string(uis), UI_get0_test_string(uis)) != 0) {
385280304Sjkim            fprintf(tty_out, "Verify failure\n");
386280304Sjkim            fflush(tty_out);
387280304Sjkim            return 0;
388280304Sjkim        }
389280304Sjkim        break;
390280304Sjkim    default:
391280304Sjkim        break;
392280304Sjkim    }
393280304Sjkim    return 1;
394280304Sjkim}
395109998Smarkm
396109998Smarkm#if !defined(OPENSSL_SYS_WIN16) && !defined(OPENSSL_SYS_WINCE)
397109998Smarkm/* Internal functions to read a string without echoing */
398205128Ssimonstatic int read_till_nl(FILE *in)
399280304Sjkim{
400280304Sjkim# define SIZE 4
401280304Sjkim    char buf[SIZE + 1];
402109998Smarkm
403280304Sjkim    do {
404280304Sjkim        if (!fgets(buf, SIZE, in))
405280304Sjkim            return 0;
406280304Sjkim    } while (strchr(buf, '\n') == NULL);
407280304Sjkim    return 1;
408280304Sjkim}
409109998Smarkm
410109998Smarkmstatic volatile sig_atomic_t intr_signal;
411109998Smarkm#endif
412109998Smarkm
413109998Smarkmstatic int read_string_inner(UI *ui, UI_STRING *uis, int echo, int strip_nl)
414280304Sjkim{
415280304Sjkim    static int ps;
416280304Sjkim    int ok;
417280304Sjkim    char result[BUFSIZ];
418280304Sjkim    int maxsize = BUFSIZ - 1;
419109998Smarkm#if !defined(OPENSSL_SYS_WIN16) && !defined(OPENSSL_SYS_WINCE)
420280304Sjkim    char *p;
421109998Smarkm
422280304Sjkim    intr_signal = 0;
423280304Sjkim    ok = 0;
424280304Sjkim    ps = 0;
425109998Smarkm
426280304Sjkim    pushsig();
427280304Sjkim    ps = 1;
428109998Smarkm
429280304Sjkim    if (!echo && !noecho_console(ui))
430280304Sjkim        goto error;
431280304Sjkim    ps = 2;
432109998Smarkm
433280304Sjkim    result[0] = '\0';
434280304Sjkim# ifdef OPENSSL_SYS_MSDOS
435280304Sjkim    if (!echo) {
436280304Sjkim        noecho_fgets(result, maxsize, tty_in);
437280304Sjkim        p = result;             /* FIXME: noecho_fgets doesn't return errors */
438280304Sjkim    } else
439280304Sjkim        p = fgets(result, maxsize, tty_in);
440280304Sjkim# else
441280304Sjkim    p = fgets(result, maxsize, tty_in);
442280304Sjkim# endif
443280304Sjkim    if (!p)
444280304Sjkim        goto error;
445280304Sjkim    if (feof(tty_in))
446280304Sjkim        goto error;
447280304Sjkim    if (ferror(tty_in))
448280304Sjkim        goto error;
449280304Sjkim    if ((p = (char *)strchr(result, '\n')) != NULL) {
450280304Sjkim        if (strip_nl)
451280304Sjkim            *p = '\0';
452280304Sjkim    } else if (!read_till_nl(tty_in))
453280304Sjkim        goto error;
454280304Sjkim    if (UI_set_result(ui, uis, result) >= 0)
455280304Sjkim        ok = 1;
456109998Smarkm
457280304Sjkim error:
458280304Sjkim    if (intr_signal == SIGINT)
459280304Sjkim        ok = -1;
460280304Sjkim    if (!echo)
461280304Sjkim        fprintf(tty_out, "\n");
462280304Sjkim    if (ps >= 2 && !echo && !echo_console(ui))
463280304Sjkim        ok = 0;
464109998Smarkm
465280304Sjkim    if (ps >= 1)
466280304Sjkim        popsig();
467109998Smarkm#else
468280304Sjkim    ok = 1;
469109998Smarkm#endif
470109998Smarkm
471280304Sjkim    OPENSSL_cleanse(result, BUFSIZ);
472280304Sjkim    return ok;
473280304Sjkim}
474109998Smarkm
475109998Smarkm/* Internal functions to open, handle and close a channel to the console.  */
476109998Smarkmstatic int open_console(UI *ui)
477280304Sjkim{
478280304Sjkim    CRYPTO_w_lock(CRYPTO_LOCK_UI);
479280304Sjkim    is_a_tty = 1;
480109998Smarkm
481238405Sjkim#if defined(OPENSSL_SYS_MACINTOSH_CLASSIC) || defined(OPENSSL_SYS_VXWORKS) || defined(OPENSSL_SYS_NETWARE) || defined(OPENSSL_SYS_BEOS)
482280304Sjkim    tty_in = stdin;
483280304Sjkim    tty_out = stderr;
484109998Smarkm#else
485280304Sjkim# ifdef OPENSSL_SYS_MSDOS
486280304Sjkim#  define DEV_TTY "con"
487280304Sjkim# else
488280304Sjkim#  define DEV_TTY "/dev/tty"
489280304Sjkim# endif
490280304Sjkim    if ((tty_in = fopen(DEV_TTY, "r")) == NULL)
491280304Sjkim        tty_in = stdin;
492280304Sjkim    if ((tty_out = fopen(DEV_TTY, "w")) == NULL)
493280304Sjkim        tty_out = stderr;
494109998Smarkm#endif
495109998Smarkm
496109998Smarkm#if defined(TTY_get) && !defined(OPENSSL_SYS_VMS)
497280304Sjkim    if (TTY_get(fileno(tty_in), &tty_orig) == -1) {
498280304Sjkim# ifdef ENOTTY
499280304Sjkim        if (errno == ENOTTY)
500280304Sjkim            is_a_tty = 0;
501280304Sjkim        else
502280304Sjkim# endif
503280304Sjkim# ifdef EINVAL
504280304Sjkim            /*
505280304Sjkim             * Ariel Glenn ariel@columbia.edu reports that solaris can return
506280304Sjkim             * EINVAL instead.  This should be ok
507280304Sjkim             */
508280304Sjkim        if (errno == EINVAL)
509280304Sjkim            is_a_tty = 0;
510280304Sjkim        else
511280304Sjkim# endif
512280304Sjkim            return 0;
513280304Sjkim    }
514109998Smarkm#endif
515109998Smarkm#ifdef OPENSSL_SYS_VMS
516280304Sjkim    status = sys$assign(&terminal, &channel, 0, 0);
517280304Sjkim    if (status != SS$_NORMAL)
518280304Sjkim        return 0;
519280304Sjkim    status =
520280304Sjkim        sys$qiow(0, channel, IO$_SENSEMODE, &iosb, 0, 0, tty_orig, 12, 0, 0,
521280304Sjkim                 0, 0);
522280304Sjkim    if ((status != SS$_NORMAL) || (iosb.iosb$w_value != SS$_NORMAL))
523280304Sjkim        return 0;
524109998Smarkm#endif
525280304Sjkim    return 1;
526280304Sjkim}
527109998Smarkm
528109998Smarkmstatic int noecho_console(UI *ui)
529280304Sjkim{
530109998Smarkm#ifdef TTY_FLAGS
531280304Sjkim    memcpy(&(tty_new), &(tty_orig), sizeof(tty_orig));
532280304Sjkim    tty_new.TTY_FLAGS &= ~ECHO;
533109998Smarkm#endif
534109998Smarkm
535109998Smarkm#if defined(TTY_set) && !defined(OPENSSL_SYS_VMS)
536280304Sjkim    if (is_a_tty && (TTY_set(fileno(tty_in), &tty_new) == -1))
537280304Sjkim        return 0;
538109998Smarkm#endif
539109998Smarkm#ifdef OPENSSL_SYS_VMS
540280304Sjkim    tty_new[0] = tty_orig[0];
541280304Sjkim    tty_new[1] = tty_orig[1] | TT$M_NOECHO;
542280304Sjkim    tty_new[2] = tty_orig[2];
543280304Sjkim    status =
544280304Sjkim        sys$qiow(0, channel, IO$_SETMODE, &iosb, 0, 0, tty_new, 12, 0, 0, 0,
545280304Sjkim                 0);
546280304Sjkim    if ((status != SS$_NORMAL) || (iosb.iosb$w_value != SS$_NORMAL))
547280304Sjkim        return 0;
548109998Smarkm#endif
549280304Sjkim    return 1;
550280304Sjkim}
551109998Smarkm
552109998Smarkmstatic int echo_console(UI *ui)
553280304Sjkim{
554109998Smarkm#if defined(TTY_set) && !defined(OPENSSL_SYS_VMS)
555280304Sjkim    memcpy(&(tty_new), &(tty_orig), sizeof(tty_orig));
556280304Sjkim    tty_new.TTY_FLAGS |= ECHO;
557109998Smarkm#endif
558109998Smarkm
559109998Smarkm#if defined(TTY_set) && !defined(OPENSSL_SYS_VMS)
560280304Sjkim    if (is_a_tty && (TTY_set(fileno(tty_in), &tty_new) == -1))
561280304Sjkim        return 0;
562109998Smarkm#endif
563109998Smarkm#ifdef OPENSSL_SYS_VMS
564280304Sjkim    tty_new[0] = tty_orig[0];
565280304Sjkim    tty_new[1] = tty_orig[1] & ~TT$M_NOECHO;
566280304Sjkim    tty_new[2] = tty_orig[2];
567280304Sjkim    status =
568280304Sjkim        sys$qiow(0, channel, IO$_SETMODE, &iosb, 0, 0, tty_new, 12, 0, 0, 0,
569280304Sjkim                 0);
570280304Sjkim    if ((status != SS$_NORMAL) || (iosb.iosb$w_value != SS$_NORMAL))
571280304Sjkim        return 0;
572109998Smarkm#endif
573280304Sjkim    return 1;
574280304Sjkim}
575109998Smarkm
576109998Smarkmstatic int close_console(UI *ui)
577280304Sjkim{
578280304Sjkim    if (tty_in != stdin)
579280304Sjkim        fclose(tty_in);
580280304Sjkim    if (tty_out != stderr)
581280304Sjkim        fclose(tty_out);
582109998Smarkm#ifdef OPENSSL_SYS_VMS
583280304Sjkim    status = sys$dassgn(channel);
584109998Smarkm#endif
585280304Sjkim    CRYPTO_w_unlock(CRYPTO_LOCK_UI);
586109998Smarkm
587280304Sjkim    return 1;
588280304Sjkim}
589109998Smarkm
590109998Smarkm#if !defined(OPENSSL_SYS_WIN16) && !defined(OPENSSL_SYS_WINCE)
591109998Smarkm/* Internal functions to handle signals and act on them */
592109998Smarkmstatic void pushsig(void)
593280304Sjkim{
594280304Sjkim# ifndef OPENSSL_SYS_WIN32
595280304Sjkim    int i;
596280304Sjkim# endif
597280304Sjkim# ifdef SIGACTION
598280304Sjkim    struct sigaction sa;
599109998Smarkm
600280304Sjkim    memset(&sa, 0, sizeof sa);
601280304Sjkim    sa.sa_handler = recsig;
602280304Sjkim# endif
603109998Smarkm
604280304Sjkim# ifdef OPENSSL_SYS_WIN32
605280304Sjkim    savsig[SIGABRT] = signal(SIGABRT, recsig);
606280304Sjkim    savsig[SIGFPE] = signal(SIGFPE, recsig);
607280304Sjkim    savsig[SIGILL] = signal(SIGILL, recsig);
608280304Sjkim    savsig[SIGINT] = signal(SIGINT, recsig);
609280304Sjkim    savsig[SIGSEGV] = signal(SIGSEGV, recsig);
610280304Sjkim    savsig[SIGTERM] = signal(SIGTERM, recsig);
611280304Sjkim# else
612280304Sjkim    for (i = 1; i < NX509_SIG; i++) {
613280304Sjkim#  ifdef SIGUSR1
614280304Sjkim        if (i == SIGUSR1)
615280304Sjkim            continue;
616280304Sjkim#  endif
617280304Sjkim#  ifdef SIGUSR2
618280304Sjkim        if (i == SIGUSR2)
619280304Sjkim            continue;
620280304Sjkim#  endif
621280304Sjkim#  ifdef SIGKILL
622280304Sjkim        if (i == SIGKILL)       /* We can't make any action on that. */
623280304Sjkim            continue;
624280304Sjkim#  endif
625280304Sjkim#  ifdef SIGACTION
626280304Sjkim        sigaction(i, &sa, &savsig[i]);
627280304Sjkim#  else
628280304Sjkim        savsig[i] = signal(i, recsig);
629280304Sjkim#  endif
630280304Sjkim    }
631280304Sjkim# endif
632109998Smarkm
633280304Sjkim# ifdef SIGWINCH
634280304Sjkim    signal(SIGWINCH, SIG_DFL);
635280304Sjkim# endif
636280304Sjkim}
637109998Smarkm
638109998Smarkmstatic void popsig(void)
639280304Sjkim{
640280304Sjkim# ifdef OPENSSL_SYS_WIN32
641280304Sjkim    signal(SIGABRT, savsig[SIGABRT]);
642280304Sjkim    signal(SIGFPE, savsig[SIGFPE]);
643280304Sjkim    signal(SIGILL, savsig[SIGILL]);
644280304Sjkim    signal(SIGINT, savsig[SIGINT]);
645280304Sjkim    signal(SIGSEGV, savsig[SIGSEGV]);
646280304Sjkim    signal(SIGTERM, savsig[SIGTERM]);
647280304Sjkim# else
648280304Sjkim    int i;
649280304Sjkim    for (i = 1; i < NX509_SIG; i++) {
650280304Sjkim#  ifdef SIGUSR1
651280304Sjkim        if (i == SIGUSR1)
652280304Sjkim            continue;
653280304Sjkim#  endif
654280304Sjkim#  ifdef SIGUSR2
655280304Sjkim        if (i == SIGUSR2)
656280304Sjkim            continue;
657280304Sjkim#  endif
658280304Sjkim#  ifdef SIGACTION
659280304Sjkim        sigaction(i, &savsig[i], NULL);
660280304Sjkim#  else
661280304Sjkim        signal(i, savsig[i]);
662280304Sjkim#  endif
663280304Sjkim    }
664280304Sjkim# endif
665280304Sjkim}
666109998Smarkm
667109998Smarkmstatic void recsig(int i)
668280304Sjkim{
669280304Sjkim    intr_signal = i;
670280304Sjkim}
671109998Smarkm#endif
672109998Smarkm
673109998Smarkm/* Internal functions specific for Windows */
674109998Smarkm#if defined(OPENSSL_SYS_MSDOS) && !defined(OPENSSL_SYS_WIN16) && !defined(OPENSSL_SYS_WINCE)
675109998Smarkmstatic int noecho_fgets(char *buf, int size, FILE *tty)
676280304Sjkim{
677280304Sjkim    int i;
678280304Sjkim    char *p;
679109998Smarkm
680280304Sjkim    p = buf;
681280304Sjkim    for (;;) {
682280304Sjkim        if (size == 0) {
683280304Sjkim            *p = '\0';
684280304Sjkim            break;
685280304Sjkim        }
686280304Sjkim        size--;
687280304Sjkim# ifdef WIN16TTY
688280304Sjkim        i = _inchar();
689280304Sjkim# elif defined(_WIN32)
690280304Sjkim        i = _getch();
691280304Sjkim# else
692280304Sjkim        i = getch();
693280304Sjkim# endif
694280304Sjkim        if (i == '\r')
695280304Sjkim            i = '\n';
696280304Sjkim        *(p++) = i;
697280304Sjkim        if (i == '\n') {
698280304Sjkim            *p = '\0';
699280304Sjkim            break;
700280304Sjkim        }
701280304Sjkim    }
702280304Sjkim# ifdef WIN_CONSOLE_BUG
703280304Sjkim    /*
704280304Sjkim     * Win95 has several evil console bugs: one of these is that the last
705280304Sjkim     * character read using getch() is passed to the next read: this is
706280304Sjkim     * usually a CR so this can be trouble. No STDIO fix seems to work but
707280304Sjkim     * flushing the console appears to do the trick.
708280304Sjkim     */
709280304Sjkim    {
710280304Sjkim        HANDLE inh;
711280304Sjkim        inh = GetStdHandle(STD_INPUT_HANDLE);
712280304Sjkim        FlushConsoleInputBuffer(inh);
713280304Sjkim    }
714280304Sjkim# endif
715280304Sjkim    return (strlen(buf));
716280304Sjkim}
717109998Smarkm#endif
718