155714Skris/* crypto/des/read_pwd.c */
255714Skris/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
355714Skris * All rights reserved.
455714Skris *
555714Skris * This package is an SSL implementation written
655714Skris * by Eric Young (eay@cryptsoft.com).
755714Skris * The implementation was written so as to conform with Netscapes SSL.
8280304Sjkim *
955714Skris * This library is free for commercial and non-commercial use as long as
1055714Skris * the following conditions are aheared to.  The following conditions
1155714Skris * apply to all code found in this distribution, be it the RC4, RSA,
1255714Skris * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
1355714Skris * included with this distribution is covered by the same copyright terms
1455714Skris * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15280304Sjkim *
1655714Skris * Copyright remains Eric Young's, and as such any Copyright notices in
1755714Skris * the code are not to be removed.
1855714Skris * If this package is used in a product, Eric Young should be given attribution
1955714Skris * as the author of the parts of the library used.
2055714Skris * This can be in the form of a textual message at program startup or
2155714Skris * in documentation (online or textual) provided with the package.
22280304Sjkim *
2355714Skris * Redistribution and use in source and binary forms, with or without
2455714Skris * modification, are permitted provided that the following conditions
2555714Skris * are met:
2655714Skris * 1. Redistributions of source code must retain the copyright
2755714Skris *    notice, this list of conditions and the following disclaimer.
2855714Skris * 2. Redistributions in binary form must reproduce the above copyright
2955714Skris *    notice, this list of conditions and the following disclaimer in the
3055714Skris *    documentation and/or other materials provided with the distribution.
3155714Skris * 3. All advertising materials mentioning features or use of this software
3255714Skris *    must display the following acknowledgement:
3355714Skris *    "This product includes cryptographic software written by
3455714Skris *     Eric Young (eay@cryptsoft.com)"
3555714Skris *    The word 'cryptographic' can be left out if the rouines from the library
3655714Skris *    being used are not cryptographic related :-).
37280304Sjkim * 4. If you include any Windows specific code (or a derivative thereof) from
3855714Skris *    the apps directory (application code) you must include an acknowledgement:
3955714Skris *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40280304Sjkim *
4155714Skris * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
4255714Skris * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4355714Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4455714Skris * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
4555714Skris * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
4655714Skris * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
4755714Skris * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4855714Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
4955714Skris * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
5055714Skris * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
5155714Skris * SUCH DAMAGE.
52280304Sjkim *
5355714Skris * The licence and distribution terms for any publically available version or
5455714Skris * derivative of this code cannot be changed.  i.e. this code cannot simply be
5555714Skris * copied and put under another distribution licence
5655714Skris * [including the GNU Public Licence.]
5755714Skris */
5855714Skris
59109998Smarkm#include <openssl/e_os2.h>
60109998Smarkm#if !defined(OPENSSL_SYS_MSDOS) && !defined(OPENSSL_SYS_VMS) && !defined(OPENSSL_SYS_WIN32)
61280304Sjkim# ifdef OPENSSL_UNISTD
62280304Sjkim#  include OPENSSL_UNISTD
63280304Sjkim# else
64280304Sjkim#  include <unistd.h>
65280304Sjkim# endif
66280304Sjkim/*
67280304Sjkim * If unistd.h defines _POSIX_VERSION, we conclude that we are on a POSIX
68280304Sjkim * system and have sigaction and termios.
69280304Sjkim */
70280304Sjkim# if defined(_POSIX_VERSION)
7155714Skris
72280304Sjkim#  define SIGACTION
73280304Sjkim#  if !defined(TERMIOS) && !defined(TERMIO) && !defined(SGTTY)
74280304Sjkim#   define TERMIOS
75280304Sjkim#  endif
76280304Sjkim
7755714Skris# endif
7855714Skris#endif
7955714Skris
80280304Sjkim/* Define this if you have sigaction() */
81280304Sjkim/* #define SIGACTION */
8255714Skris
8355714Skris#ifdef WIN16TTY
84280304Sjkim# undef OPENSSL_SYS_WIN16
85280304Sjkim# undef _WINDOWS
86280304Sjkim# include <graph.h>
8755714Skris#endif
8855714Skris
8955714Skris/* 06-Apr-92 Luke Brennan    Support for VMS */
9055714Skris#include "des_locl.h"
9155714Skris#include "cryptlib.h"
9255714Skris#include <signal.h>
9355714Skris#include <stdio.h>
9455714Skris#include <string.h>
9555714Skris#include <setjmp.h>
9655714Skris#include <errno.h>
9755714Skris
98280304Sjkim#ifdef OPENSSL_SYS_VMS          /* prototypes for sys$whatever */
99280304Sjkim# include <starlet.h>
100280304Sjkim# ifdef __DECC
101280304Sjkim#  pragma message disable DOLLARID
102280304Sjkim# endif
10355714Skris#endif
10455714Skris
10555714Skris#ifdef WIN_CONSOLE_BUG
106280304Sjkim# include <windows.h>
107280304Sjkim# ifndef OPENSSL_SYS_WINCE
108280304Sjkim#  include <wincon.h>
109280304Sjkim# endif
11055714Skris#endif
11155714Skris
112280304Sjkim/*
113280304Sjkim * There are 5 types of terminal interface supported, TERMIO, TERMIOS, VMS,
114280304Sjkim * MSDOS and SGTTY
11555714Skris */
11655714Skris
11755714Skris#if defined(__sgi) && !defined(TERMIOS)
118280304Sjkim# define TERMIOS
119280304Sjkim# undef  TERMIO
120280304Sjkim# undef  SGTTY
12155714Skris#endif
12255714Skris
12355714Skris#if defined(linux) && !defined(TERMIO)
124280304Sjkim# undef  TERMIOS
125280304Sjkim# define TERMIO
126280304Sjkim# undef  SGTTY
12755714Skris#endif
12855714Skris
12955714Skris#ifdef _LIBC
130280304Sjkim# undef  TERMIOS
131280304Sjkim# define TERMIO
132280304Sjkim# undef  SGTTY
13355714Skris#endif
13455714Skris
135109998Smarkm#if !defined(TERMIO) && !defined(TERMIOS) && !defined(OPENSSL_SYS_VMS) && !defined(OPENSSL_SYS_MSDOS) && !defined(MAC_OS_pre_X) && !defined(MAC_OS_GUSI_SOURCE)
136280304Sjkim# undef  TERMIOS
137280304Sjkim# undef  TERMIO
138280304Sjkim# define SGTTY
13955714Skris#endif
14055714Skris
141109998Smarkm#if defined(OPENSSL_SYS_VXWORKS)
142280304Sjkim# undef TERMIOS
143280304Sjkim# undef TERMIO
144280304Sjkim# undef SGTTY
145100928Snectar#endif
146100928Snectar
14755714Skris#ifdef TERMIOS
148280304Sjkim# include <termios.h>
149280304Sjkim# define TTY_STRUCT              struct termios
150280304Sjkim# define TTY_FLAGS               c_lflag
151280304Sjkim# define TTY_get(tty,data)       tcgetattr(tty,data)
152280304Sjkim# define TTY_set(tty,data)       tcsetattr(tty,TCSANOW,data)
15355714Skris#endif
15455714Skris
15555714Skris#ifdef TERMIO
156280304Sjkim# include <termio.h>
157280304Sjkim# define TTY_STRUCT              struct termio
158280304Sjkim# define TTY_FLAGS               c_lflag
159280304Sjkim# define TTY_get(tty,data)       ioctl(tty,TCGETA,data)
160280304Sjkim# define TTY_set(tty,data)       ioctl(tty,TCSETA,data)
16155714Skris#endif
16255714Skris
16355714Skris#ifdef SGTTY
164280304Sjkim# include <sgtty.h>
165280304Sjkim# define TTY_STRUCT              struct sgttyb
166280304Sjkim# define TTY_FLAGS               sg_flags
167280304Sjkim# define TTY_get(tty,data)       ioctl(tty,TIOCGETP,data)
168280304Sjkim# define TTY_set(tty,data)       ioctl(tty,TIOCSETP,data)
16955714Skris#endif
17055714Skris
171109998Smarkm#if !defined(_LIBC) && !defined(OPENSSL_SYS_MSDOS) && !defined(OPENSSL_SYS_VMS) && !defined(MAC_OS_pre_X)
172280304Sjkim# include <sys/ioctl.h>
17355714Skris#endif
17455714Skris
175109998Smarkm#if defined(OPENSSL_SYS_MSDOS) && !defined(__CYGWIN32__) && !defined(OPENSSL_SYS_WINCE)
176280304Sjkim# include <conio.h>
177280304Sjkim# define fgets(a,b,c) noecho_fgets(a,b,c)
17855714Skris#endif
17955714Skris
180109998Smarkm#ifdef OPENSSL_SYS_VMS
181280304Sjkim# include <ssdef.h>
182280304Sjkim# include <iodef.h>
183280304Sjkim# include <ttdef.h>
184280304Sjkim# include <descrip.h>
18555714Skrisstruct IOSB {
186280304Sjkim    short iosb$w_value;
187280304Sjkim    short iosb$w_count;
188280304Sjkim    long iosb$l_info;
189280304Sjkim};
19055714Skris#endif
19155714Skris
19259191Skris#if defined(MAC_OS_pre_X) || defined(MAC_OS_GUSI_SOURCE)
19359191Skris/*
19459191Skris * This one needs work. As a matter of fact the code is unoperational
19559191Skris * and this is only a trick to get it compiled.
196280304Sjkim *                                      <appro@fy.chalmers.se>
19759191Skris */
198280304Sjkim# define TTY_STRUCT int
19959191Skris#endif
20059191Skris
20155714Skris#ifndef NX509_SIG
202280304Sjkim# define NX509_SIG 32
20355714Skris#endif
20455714Skris
20555714Skrisstatic void read_till_nl(FILE *);
20655714Skrisstatic void recsig(int);
20755714Skrisstatic void pushsig(void);
20855714Skrisstatic void popsig(void);
209109998Smarkm#if defined(OPENSSL_SYS_MSDOS) && !defined(OPENSSL_SYS_WIN16)
21055714Skrisstatic int noecho_fgets(char *buf, int size, FILE *tty);
21155714Skris#endif
21255714Skris#ifdef SIGACTION
213280304Sjkimstatic struct sigaction savsig[NX509_SIG];
21455714Skris#else
215280304Sjkimstatic void (*savsig[NX509_SIG]) (int);
21655714Skris#endif
21755714Skrisstatic jmp_buf save;
21855714Skris
219280304Sjkimint des_read_pw_string(char *buf, int length, const char *prompt, int verify)
220280304Sjkim{
221280304Sjkim    char buff[BUFSIZ];
222280304Sjkim    int ret;
22355714Skris
224280304Sjkim    ret =
225280304Sjkim        des_read_pw(buf, buff, (length > BUFSIZ) ? BUFSIZ : length, prompt,
226280304Sjkim                    verify);
227280304Sjkim    OPENSSL_cleanse(buff, BUFSIZ);
228280304Sjkim    return (ret);
229280304Sjkim}
23055714Skris
231109998Smarkm#ifdef OPENSSL_SYS_WINCE
23255714Skris
233280304Sjkimint des_read_pw(char *buf, char *buff, int size, const char *prompt,
234280304Sjkim                int verify)
235280304Sjkim{
236280304Sjkim    memset(buf, 0, size);
237280304Sjkim    memset(buff, 0, size);
238280304Sjkim    return (0);
239280304Sjkim}
240109998Smarkm
241109998Smarkm#elif defined(OPENSSL_SYS_WIN16)
242109998Smarkm
243109998Smarkmint des_read_pw(char *buf, char *buff, int size, char *prompt, int verify)
244280304Sjkim{
245280304Sjkim    memset(buf, 0, size);
246280304Sjkim    memset(buff, 0, size);
247280304Sjkim    return (0);
248280304Sjkim}
249109998Smarkm
250280304Sjkim#else                           /* !OPENSSL_SYS_WINCE && !OPENSSL_SYS_WIN16 */
251109998Smarkm
25255714Skrisstatic void read_till_nl(FILE *in)
253280304Sjkim{
254280304Sjkim# define SIZE 4
255280304Sjkim    char buf[SIZE + 1];
25655714Skris
257280304Sjkim    do {
258280304Sjkim        fgets(buf, SIZE, in);
259280304Sjkim    } while (strchr(buf, '\n') == NULL);
260280304Sjkim}
26155714Skris
26255714Skris/* return 0 if ok, 1 (or -1) otherwise */
26355714Skrisint des_read_pw(char *buf, char *buff, int size, const char *prompt,
264280304Sjkim                int verify)
265280304Sjkim{
266280304Sjkim# ifdef OPENSSL_SYS_VMS
267280304Sjkim    struct IOSB iosb;
268280304Sjkim    $DESCRIPTOR(terminal, "TT");
269280304Sjkim    long tty_orig[3], tty_new[3];
270280304Sjkim    long status;
271280304Sjkim    unsigned short channel = 0;
272280304Sjkim# else
273280304Sjkim#  if !defined(OPENSSL_SYS_MSDOS) || defined(__DJGPP__)
274280304Sjkim    TTY_STRUCT tty_orig, tty_new;
275280304Sjkim#  endif
276280304Sjkim# endif
277280304Sjkim    int number;
278280304Sjkim    int ok;
279280304Sjkim    /*
280280304Sjkim     * statics are simply to avoid warnings about longjmp clobbering things
281280304Sjkim     */
282280304Sjkim    static int ps;
283280304Sjkim    int is_a_tty;
284280304Sjkim    static FILE *tty;
285280304Sjkim    char *p;
28655714Skris
287280304Sjkim    if (setjmp(save)) {
288280304Sjkim        ok = 0;
289280304Sjkim        goto error;
290280304Sjkim    }
29155714Skris
292280304Sjkim    number = 5;
293280304Sjkim    ok = 0;
294280304Sjkim    ps = 0;
295280304Sjkim    is_a_tty = 1;
296280304Sjkim    tty = NULL;
29755714Skris
298280304Sjkim# ifdef OPENSSL_SYS_MSDOS
299280304Sjkim    if ((tty = fopen("con", "r")) == NULL)
300280304Sjkim        tty = stdin;
301280304Sjkim# elif defined(MAC_OS_pre_X) || defined(OPENSSL_SYS_VXWORKS)
302280304Sjkim    tty = stdin;
303280304Sjkim# else
304280304Sjkim#  ifndef OPENSSL_SYS_MPE
305280304Sjkim    if ((tty = fopen("/dev/tty", "r")) == NULL)
306280304Sjkim#  endif
307280304Sjkim        tty = stdin;
308280304Sjkim# endif
30955714Skris
310280304Sjkim# if defined(TTY_get) && !defined(OPENSSL_SYS_VMS)
311280304Sjkim    if (TTY_get(fileno(tty), &tty_orig) == -1) {
312280304Sjkim#  ifdef ENOTTY
313280304Sjkim        if (errno == ENOTTY)
314280304Sjkim            is_a_tty = 0;
315280304Sjkim        else
316280304Sjkim#  endif
317280304Sjkim#  ifdef EINVAL
318280304Sjkim            /*
319280304Sjkim             * Ariel Glenn ariel@columbia.edu reports that solaris can return
320280304Sjkim             * EINVAL instead.  This should be ok
321280304Sjkim             */
322280304Sjkim        if (errno == EINVAL)
323280304Sjkim            is_a_tty = 0;
324280304Sjkim        else
325280304Sjkim#  endif
326280304Sjkim            return (-1);
327280304Sjkim    }
328280304Sjkim    memcpy(&(tty_new), &(tty_orig), sizeof(tty_orig));
329280304Sjkim# endif
330280304Sjkim# ifdef OPENSSL_SYS_VMS
331280304Sjkim    status = sys$assign(&terminal, &channel, 0, 0);
332280304Sjkim    if (status != SS$_NORMAL)
333280304Sjkim        return (-1);
334280304Sjkim    status =
335280304Sjkim        sys$qiow(0, channel, IO$_SENSEMODE, &iosb, 0, 0, tty_orig, 12, 0, 0,
336280304Sjkim                 0, 0);
337280304Sjkim    if ((status != SS$_NORMAL) || (iosb.iosb$w_value != SS$_NORMAL))
338280304Sjkim        return (-1);
339280304Sjkim# endif
34055714Skris
341280304Sjkim    pushsig();
342280304Sjkim    ps = 1;
34355714Skris
344280304Sjkim# ifdef TTY_FLAGS
345280304Sjkim    tty_new.TTY_FLAGS &= ~ECHO;
346280304Sjkim# endif
34755714Skris
348280304Sjkim# if defined(TTY_set) && !defined(OPENSSL_SYS_VMS)
349280304Sjkim    if (is_a_tty && (TTY_set(fileno(tty), &tty_new) == -1))
350280304Sjkim#  ifdef OPENSSL_SYS_MPE
351280304Sjkim        ;                       /* MPE lies -- echo really has been disabled */
352280304Sjkim#  else
353280304Sjkim        return (-1);
354280304Sjkim#  endif
355280304Sjkim# endif
356280304Sjkim# ifdef OPENSSL_SYS_VMS
357280304Sjkim    tty_new[0] = tty_orig[0];
358280304Sjkim    tty_new[1] = tty_orig[1] | TT$M_NOECHO;
359280304Sjkim    tty_new[2] = tty_orig[2];
360280304Sjkim    status =
361280304Sjkim        sys$qiow(0, channel, IO$_SETMODE, &iosb, 0, 0, tty_new, 12, 0, 0, 0,
362280304Sjkim                 0);
363280304Sjkim    if ((status != SS$_NORMAL) || (iosb.iosb$w_value != SS$_NORMAL))
364280304Sjkim        return (-1);
365280304Sjkim# endif
366280304Sjkim    ps = 2;
36755714Skris
368280304Sjkim    while ((!ok) && (number--)) {
369280304Sjkim        fputs(prompt, stderr);
370280304Sjkim        fflush(stderr);
37155714Skris
372280304Sjkim        buf[0] = '\0';
373280304Sjkim        fgets(buf, size, tty);
374280304Sjkim        if (feof(tty))
375280304Sjkim            goto error;
376280304Sjkim        if (ferror(tty))
377280304Sjkim            goto error;
378280304Sjkim        if ((p = (char *)strchr(buf, '\n')) != NULL)
379280304Sjkim            *p = '\0';
380280304Sjkim        else
381280304Sjkim            read_till_nl(tty);
382280304Sjkim        if (verify) {
383280304Sjkim            fprintf(stderr, "\nVerifying password - %s", prompt);
384280304Sjkim            fflush(stderr);
385280304Sjkim            buff[0] = '\0';
386280304Sjkim            fgets(buff, size, tty);
387280304Sjkim            if (feof(tty))
388280304Sjkim                goto error;
389280304Sjkim            if ((p = (char *)strchr(buff, '\n')) != NULL)
390280304Sjkim                *p = '\0';
391280304Sjkim            else
392280304Sjkim                read_till_nl(tty);
39355714Skris
394280304Sjkim            if (strcmp(buf, buff) != 0) {
395280304Sjkim                fprintf(stderr, "\nVerify failure");
396280304Sjkim                fflush(stderr);
397280304Sjkim                break;
398280304Sjkim                /* continue; */
399280304Sjkim            }
400280304Sjkim        }
401280304Sjkim        ok = 1;
402280304Sjkim    }
40355714Skris
404280304Sjkim error:
405280304Sjkim    fprintf(stderr, "\n");
406280304Sjkim# if 0
407280304Sjkim    perror("fgets(tty)");
408280304Sjkim# endif
409280304Sjkim    /* What can we do if there is an error? */
410280304Sjkim# if defined(TTY_set) && !defined(OPENSSL_SYS_VMS)
411280304Sjkim    if (ps >= 2)
412280304Sjkim        TTY_set(fileno(tty), &tty_orig);
413280304Sjkim# endif
414280304Sjkim# ifdef OPENSSL_SYS_VMS
415280304Sjkim    if (ps >= 2)
416280304Sjkim        status =
417280304Sjkim            sys$qiow(0, channel, IO$_SETMODE, &iosb, 0, 0, tty_orig, 12, 0, 0,
418280304Sjkim                     0, 0);
419280304Sjkim# endif
420280304Sjkim
421280304Sjkim    if (ps >= 1)
422280304Sjkim        popsig();
423280304Sjkim    if (stdin != tty)
424280304Sjkim        fclose(tty);
425280304Sjkim# ifdef OPENSSL_SYS_VMS
426280304Sjkim    status = sys$dassgn(channel);
427280304Sjkim# endif
428280304Sjkim    return (!ok);
429280304Sjkim}
430280304Sjkim
43155714Skrisstatic void pushsig(void)
432280304Sjkim{
433280304Sjkim    int i;
434280304Sjkim# ifdef SIGACTION
435280304Sjkim    struct sigaction sa;
43655714Skris
437280304Sjkim    memset(&sa, 0, sizeof sa);
438280304Sjkim    sa.sa_handler = recsig;
439280304Sjkim# endif
44055714Skris
441280304Sjkim    for (i = 1; i < NX509_SIG; i++) {
442280304Sjkim# ifdef SIGUSR1
443280304Sjkim        if (i == SIGUSR1)
444280304Sjkim            continue;
445280304Sjkim# endif
446280304Sjkim# ifdef SIGUSR2
447280304Sjkim        if (i == SIGUSR2)
448280304Sjkim            continue;
449280304Sjkim# endif
450280304Sjkim# ifdef SIGACTION
451280304Sjkim        sigaction(i, &sa, &savsig[i]);
452280304Sjkim# else
453280304Sjkim        savsig[i] = signal(i, recsig);
454280304Sjkim# endif
455280304Sjkim    }
45655714Skris
457280304Sjkim# ifdef SIGWINCH
458280304Sjkim    signal(SIGWINCH, SIG_DFL);
459280304Sjkim# endif
460280304Sjkim}
46155714Skris
46255714Skrisstatic void popsig(void)
463280304Sjkim{
464280304Sjkim    int i;
46555714Skris
466280304Sjkim    for (i = 1; i < NX509_SIG; i++) {
467280304Sjkim# ifdef SIGUSR1
468280304Sjkim        if (i == SIGUSR1)
469280304Sjkim            continue;
470280304Sjkim# endif
471280304Sjkim# ifdef SIGUSR2
472280304Sjkim        if (i == SIGUSR2)
473280304Sjkim            continue;
474280304Sjkim# endif
475280304Sjkim# ifdef SIGACTION
476280304Sjkim        sigaction(i, &savsig[i], NULL);
477280304Sjkim# else
478280304Sjkim        signal(i, savsig[i]);
479280304Sjkim# endif
480280304Sjkim    }
481280304Sjkim}
48255714Skris
48355714Skrisstatic void recsig(int i)
484280304Sjkim{
485280304Sjkim    longjmp(save, 1);
486280304Sjkim# ifdef LINT
487280304Sjkim    i = i;
488280304Sjkim# endif
489280304Sjkim}
49055714Skris
491280304Sjkim# ifdef OPENSSL_SYS_MSDOS
49255714Skrisstatic int noecho_fgets(char *buf, int size, FILE *tty)
493280304Sjkim{
494280304Sjkim    int i;
495280304Sjkim    char *p;
49655714Skris
497280304Sjkim    p = buf;
498280304Sjkim    for (;;) {
499280304Sjkim        if (size == 0) {
500280304Sjkim            *p = '\0';
501280304Sjkim            break;
502280304Sjkim        }
503280304Sjkim        size--;
504280304Sjkim#  ifdef WIN16TTY
505280304Sjkim        i = _inchar();
506280304Sjkim#  else
507280304Sjkim        i = getch();
508280304Sjkim#  endif
509280304Sjkim        if (i == '\r')
510280304Sjkim            i = '\n';
511280304Sjkim        *(p++) = i;
512280304Sjkim        if (i == '\n') {
513280304Sjkim            *p = '\0';
514280304Sjkim            break;
515280304Sjkim        }
516280304Sjkim    }
517280304Sjkim#  ifdef WIN_CONSOLE_BUG
518280304Sjkim    /*
519280304Sjkim     * Win95 has several evil console bugs: one of these is that the last
520280304Sjkim     * character read using getch() is passed to the next read: this is
521280304Sjkim     * usually a CR so this can be trouble. No STDIO fix seems to work but
522280304Sjkim     * flushing the console appears to do the trick.
523280304Sjkim     */
524280304Sjkim    {
525280304Sjkim        HANDLE inh;
526280304Sjkim        inh = GetStdHandle(STD_INPUT_HANDLE);
527280304Sjkim        FlushConsoleInputBuffer(inh);
528280304Sjkim    }
529280304Sjkim#  endif
530280304Sjkim    return (strlen(buf));
531280304Sjkim}
532280304Sjkim# endif
533280304Sjkim#endif                          /* !OPENSSL_SYS_WINCE && !WIN16 */
534