626 lines
18 KiB
C
626 lines
18 KiB
C
|
/*---------------------------------------------------------------------------
|
||
|
|
||
|
ttyio.c
|
||
|
|
||
|
This file contains routines for doing console input/output, including code
|
||
|
for non-echoing input. It is used by the encryption/decryption code but
|
||
|
does not contain any restricted code itself. This file is shared between
|
||
|
Info-ZIP's Zip and UnZip.
|
||
|
|
||
|
Contains: echo() (VMS only)
|
||
|
Echon() (Unix only)
|
||
|
Echoff() (Unix only)
|
||
|
screenlines() (Unix only)
|
||
|
zgetch() (Unix and non-Unix versions)
|
||
|
getp() ("PC," Unix/Atari/Be, VMS/VMCMS/MVS)
|
||
|
|
||
|
---------------------------------------------------------------------------*/
|
||
|
|
||
|
#define __TTYIO_C /* identifies this source module */
|
||
|
|
||
|
#include "zip.h"
|
||
|
#include "crypt.h"
|
||
|
|
||
|
#if (CRYPT || (defined(UNZIP) && !defined(FUNZIP)))
|
||
|
/* Non-echo console/keyboard input is needed for (en/de)cryption's password
|
||
|
* entry, and for UnZip(SFX)'s MORE and Pause features.
|
||
|
* (The corresponding #endif is found at the end of this module.)
|
||
|
*/
|
||
|
|
||
|
#include "ttyio.h"
|
||
|
|
||
|
#ifndef PUTC
|
||
|
# define PUTC putc
|
||
|
#endif
|
||
|
|
||
|
#ifdef ZIP
|
||
|
# ifdef GLOBAL /* used in Amiga system headers, maybe others too */
|
||
|
# undef GLOBAL
|
||
|
# endif
|
||
|
# define GLOBAL(g) g
|
||
|
#else
|
||
|
# define GLOBAL(g) G.g
|
||
|
#endif
|
||
|
|
||
|
#ifdef __BEOS__ /* why yes, we do */
|
||
|
# define HAVE_TERMIOS_H
|
||
|
#endif
|
||
|
|
||
|
#ifdef _POSIX_VERSION
|
||
|
# ifndef USE_POSIX_TERMIOS
|
||
|
# define USE_POSIX_TERMIOS /* use POSIX style termio (termios) */
|
||
|
# endif
|
||
|
# ifndef HAVE_TERMIOS_H
|
||
|
# define HAVE_TERMIOS_H /* POSIX termios.h */
|
||
|
# endif
|
||
|
#endif /* _POSIX_VERSION */
|
||
|
|
||
|
#ifdef UNZIP /* Zip handles this with the unix/configure script */
|
||
|
# ifndef _POSIX_VERSION
|
||
|
# if (defined(SYSV) || defined(CRAY)) && !defined(__MINT__)
|
||
|
# ifndef USE_SYSV_TERMIO
|
||
|
# define USE_SYSV_TERMIO
|
||
|
# endif
|
||
|
# ifdef COHERENT
|
||
|
# ifndef HAVE_TERMIO_H
|
||
|
# define HAVE_TERMIO_H
|
||
|
# endif
|
||
|
# ifdef HAVE_SYS_TERMIO_H
|
||
|
# undef HAVE_SYS_TERMIO_H
|
||
|
# endif
|
||
|
# else /* !COHERENT */
|
||
|
# ifdef HAVE_TERMIO_H
|
||
|
# undef HAVE_TERMIO_H
|
||
|
# endif
|
||
|
# ifndef HAVE_SYS_TERMIO_H
|
||
|
# define HAVE_SYS_TERMIO_H
|
||
|
# endif
|
||
|
# endif /* ?COHERENT */
|
||
|
# endif /* (SYSV || CRAY) && !__MINT__ */
|
||
|
# endif /* !_POSIX_VERSION */
|
||
|
# if !(defined(BSD4_4) || defined(SYSV) || defined(__convexc__))
|
||
|
# ifndef NO_FCNTL_H
|
||
|
# define NO_FCNTL_H
|
||
|
# endif
|
||
|
# endif /* !(BSD4_4 || SYSV || __convexc__) */
|
||
|
#endif /* UNZIP */
|
||
|
|
||
|
#ifdef HAVE_TERMIOS_H
|
||
|
# ifndef USE_POSIX_TERMIOS
|
||
|
# define USE_POSIX_TERMIOS
|
||
|
# endif
|
||
|
#endif
|
||
|
|
||
|
#if (defined(HAVE_TERMIO_H) || defined(HAVE_SYS_TERMIO_H))
|
||
|
# ifndef USE_SYSV_TERMIO
|
||
|
# define USE_SYSV_TERMIO
|
||
|
# endif
|
||
|
#endif
|
||
|
|
||
|
#if (defined(UNZIP) && !defined(FUNZIP) && defined(UNIX) && defined(MORE))
|
||
|
# include <sys/ioctl.h>
|
||
|
# define GOT_IOCTL_H
|
||
|
/* int ioctl OF((int, int, zvoid *)); GRR: may need for some systems */
|
||
|
#endif
|
||
|
|
||
|
#ifndef HAVE_WORKING_GETCH
|
||
|
/* include system support for switching of console echo */
|
||
|
# ifdef VMS
|
||
|
# include <descrip.h>
|
||
|
# include <iodef.h>
|
||
|
# include <ttdef.h>
|
||
|
# include <starlet.h>
|
||
|
# include <ssdef.h>
|
||
|
# else /* !VMS */
|
||
|
# ifdef HAVE_TERMIOS_H
|
||
|
# include <termios.h>
|
||
|
# define sgttyb termios
|
||
|
# define sg_flags c_lflag
|
||
|
# define GTTY(f, s) tcgetattr(f, (zvoid *) s)
|
||
|
# define STTY(f, s) tcsetattr(f, TCSAFLUSH, (zvoid *) s)
|
||
|
# else /* !HAVE_TERMIOS_H */
|
||
|
# ifdef USE_SYSV_TERMIO /* Amdahl, Cray, all SysV? */
|
||
|
# ifdef HAVE_TERMIO_H
|
||
|
# include <termio.h>
|
||
|
# endif
|
||
|
# ifdef HAVE_SYS_TERMIO_H
|
||
|
# include <sys/termio.h>
|
||
|
# endif
|
||
|
# ifdef NEED_PTEM
|
||
|
# include <sys/stream.h>
|
||
|
# include <sys/ptem.h>
|
||
|
# endif
|
||
|
# define sgttyb termio
|
||
|
# define sg_flags c_lflag
|
||
|
# define GTTY(f,s) ioctl(f,TCGETA,(zvoid *)s)
|
||
|
# define STTY(f,s) ioctl(f,TCSETAW,(zvoid *)s)
|
||
|
# else /* !USE_SYSV_TERMIO */
|
||
|
# ifndef CMS_MVS
|
||
|
# if (!defined(MINIX) && !defined(GOT_IOCTL_H))
|
||
|
# include <sys/ioctl.h>
|
||
|
# endif
|
||
|
# include <sgtty.h>
|
||
|
# define GTTY gtty
|
||
|
# define STTY stty
|
||
|
# ifdef UNZIP
|
||
|
/*
|
||
|
* XXX : Are these declarations needed at all ????
|
||
|
*/
|
||
|
/*
|
||
|
* GRR: let's find out... Hmmm, appears not...
|
||
|
int gtty OF((int, struct sgttyb *));
|
||
|
int stty OF((int, struct sgttyb *));
|
||
|
*/
|
||
|
# endif
|
||
|
# endif /* !CMS_MVS */
|
||
|
# endif /* ?USE_SYSV_TERMIO */
|
||
|
# endif /* ?HAVE_TERMIOS_H */
|
||
|
# ifndef NO_FCNTL_H
|
||
|
# ifndef UNZIP
|
||
|
# include <fcntl.h>
|
||
|
# endif
|
||
|
# else
|
||
|
char *ttyname OF((int));
|
||
|
# endif
|
||
|
# endif /* ?VMS */
|
||
|
#endif /* !HAVE_WORKING_GETCH */
|
||
|
|
||
|
|
||
|
|
||
|
#ifndef HAVE_WORKING_GETCH
|
||
|
#ifdef VMS
|
||
|
|
||
|
/*
|
||
|
* Turn keyboard echoing on or off (VMS). Loosely based on VMSmunch.c
|
||
|
* and hence on Joe Meadows' file.c code.
|
||
|
*/
|
||
|
int echo(opt)
|
||
|
int opt;
|
||
|
{
|
||
|
/*
|
||
|
* For VMS v5.x:
|
||
|
* IO$_SENSEMODE/SETMODE info: Programming, Vol. 7A, System Programming,
|
||
|
* I/O User's: Part I, sec. 8.4.1.1, 8.4.3, 8.4.5, 8.6
|
||
|
* sys$assign(), sys$qio() info: Programming, Vol. 4B, System Services,
|
||
|
* System Services Reference Manual, pp. sys-23, sys-379
|
||
|
* fixed-length descriptor info: Programming, Vol. 3, System Services,
|
||
|
* Intro to System Routines, sec. 2.9.2
|
||
|
* Greg Roelofs, 15 Aug 91
|
||
|
*/
|
||
|
|
||
|
/* SKM: make global? */
|
||
|
static struct dsc$descriptor_s DevDesc =
|
||
|
{11, DSC$K_DTYPE_T, DSC$K_CLASS_S, "SYS$COMMAND"};
|
||
|
/* {dsc$w_length, dsc$b_dtype, dsc$b_class, dsc$a_pointer}; */
|
||
|
static short DevChan, iosb[4];
|
||
|
static long status;
|
||
|
static unsigned long oldmode[2], newmode[2]; /* each = 8 bytes */
|
||
|
|
||
|
|
||
|
/* assign a channel to standard input */
|
||
|
status = sys$assign(&DevDesc, &DevChan, 0, 0);
|
||
|
if (!(status & 1))
|
||
|
return status;
|
||
|
|
||
|
/* use sys$qio and the IO$_SENSEMODE function to determine the current
|
||
|
* tty status (for password reading, could use IO$_READVBLK function
|
||
|
* instead, but echo on/off will be more general)
|
||
|
*/
|
||
|
status = sys$qiow(0, DevChan, IO$_SENSEMODE, &iosb, 0, 0,
|
||
|
oldmode, 8, 0, 0, 0, 0);
|
||
|
if (!(status & 1))
|
||
|
return status;
|
||
|
status = iosb[0];
|
||
|
if (!(status & 1))
|
||
|
return status;
|
||
|
|
||
|
/* copy old mode into new-mode buffer, then modify to be either NOECHO or
|
||
|
* ECHO (depending on function argument opt)
|
||
|
*/
|
||
|
newmode[0] = oldmode[0];
|
||
|
newmode[1] = oldmode[1];
|
||
|
if (opt == 0) /* off */
|
||
|
newmode[1] |= TT$M_NOECHO; /* set NOECHO bit */
|
||
|
else
|
||
|
newmode[1] &= ~((unsigned long) TT$M_NOECHO); /* clear NOECHO bit */
|
||
|
|
||
|
/* use the IO$_SETMODE function to change the tty status */
|
||
|
status = sys$qiow(0, DevChan, IO$_SETMODE, &iosb, 0, 0,
|
||
|
newmode, 8, 0, 0, 0, 0);
|
||
|
if (!(status & 1))
|
||
|
return status;
|
||
|
status = iosb[0];
|
||
|
if (!(status & 1))
|
||
|
return status;
|
||
|
|
||
|
/* deassign the sys$input channel by way of clean-up */
|
||
|
status = sys$dassgn(DevChan);
|
||
|
if (!(status & 1))
|
||
|
return status;
|
||
|
|
||
|
return SS$_NORMAL; /* we be happy */
|
||
|
|
||
|
} /* end function echo() */
|
||
|
|
||
|
|
||
|
#else /* !VMS: basically Unix */
|
||
|
|
||
|
|
||
|
/* For VM/CMS and MVS, non-echo terminal input is not (yet?) supported. */
|
||
|
#ifndef CMS_MVS
|
||
|
|
||
|
#ifdef ZIP /* moved to globals.h for UnZip */
|
||
|
static int echofd=(-1); /* file descriptor whose echo is off */
|
||
|
#endif
|
||
|
|
||
|
/*
|
||
|
* Turn echo off for file descriptor f. Assumes that f is a tty device.
|
||
|
*/
|
||
|
void Echoff(__G__ f)
|
||
|
__GDEF
|
||
|
int f; /* file descriptor for which to turn echo off */
|
||
|
{
|
||
|
struct sgttyb sg; /* tty device structure */
|
||
|
|
||
|
GLOBAL(echofd) = f;
|
||
|
GTTY(f, &sg); /* get settings */
|
||
|
sg.sg_flags &= ~ECHO; /* turn echo off */
|
||
|
STTY(f, &sg);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Turn echo back on for file descriptor echofd.
|
||
|
*/
|
||
|
void Echon(__G)
|
||
|
__GDEF
|
||
|
{
|
||
|
struct sgttyb sg; /* tty device structure */
|
||
|
|
||
|
if (GLOBAL(echofd) != -1) {
|
||
|
GTTY(GLOBAL(echofd), &sg); /* get settings */
|
||
|
sg.sg_flags |= ECHO; /* turn echo on */
|
||
|
STTY(GLOBAL(echofd), &sg);
|
||
|
GLOBAL(echofd) = -1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#endif /* !CMS_MVS */
|
||
|
#endif /* ?VMS */
|
||
|
|
||
|
|
||
|
#if (defined(UNZIP) && !defined(FUNZIP))
|
||
|
|
||
|
#if (defined(UNIX) || defined(__BEOS__))
|
||
|
#ifdef MORE
|
||
|
|
||
|
/*
|
||
|
* Get the number of lines on the output terminal. SCO Unix apparently
|
||
|
* defines TIOCGWINSZ but doesn't support it (!M_UNIX).
|
||
|
*
|
||
|
* GRR: will need to know width of terminal someday, too, to account for
|
||
|
* line-wrapping.
|
||
|
*/
|
||
|
|
||
|
#if (defined(TIOCGWINSZ) && !defined(M_UNIX))
|
||
|
|
||
|
int screenlines()
|
||
|
{
|
||
|
struct winsize wsz;
|
||
|
#ifdef DEBUG_WINSZ
|
||
|
static int firsttime = TRUE;
|
||
|
#endif
|
||
|
|
||
|
/* see termio(4) under, e.g., SunOS */
|
||
|
if (ioctl(1, TIOCGWINSZ, &wsz) == 0) {
|
||
|
#ifdef DEBUG_WINSZ
|
||
|
if (firsttime) {
|
||
|
firsttime = FALSE;
|
||
|
fprintf(stderr, "ttyio.c screenlines(): ws_row = %d\n",
|
||
|
wsz.ws_row);
|
||
|
}
|
||
|
#endif
|
||
|
/* number of columns = ws_col */
|
||
|
return (wsz.ws_row > 0)? wsz.ws_row : 24; /* number of rows */
|
||
|
|
||
|
} else { /* this happens when piping to more(1), for example */
|
||
|
#ifdef DEBUG_WINSZ
|
||
|
if (firsttime) {
|
||
|
firsttime = FALSE;
|
||
|
fprintf(stderr,
|
||
|
"ttyio.c screenlines(): ioctl(TIOCGWINSZ) failed\n"));
|
||
|
}
|
||
|
#endif
|
||
|
return 24; /* VT-100 assumed to be minimal hardware */
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#else /* !TIOCGWINSZ: service not available, fall back to semi-bogus method */
|
||
|
|
||
|
int screenlines()
|
||
|
{
|
||
|
char *envptr, *getenv();
|
||
|
int n;
|
||
|
|
||
|
/* GRR: this is overly simplistic, but don't have access to stty/gtty
|
||
|
* system anymore
|
||
|
*/
|
||
|
envptr = getenv("LINES");
|
||
|
if (envptr == (char *)NULL || (n = atoi(envptr)) < 5)
|
||
|
return 24; /* VT-100 assumed to be minimal hardware */
|
||
|
else
|
||
|
return n;
|
||
|
}
|
||
|
|
||
|
#endif /* ?(TIOCGWINSZ && !M_UNIX) */
|
||
|
#endif /* MORE */
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Get a character from the given file descriptor without echo or newline.
|
||
|
*/
|
||
|
int zgetch(__G__ f)
|
||
|
__GDEF
|
||
|
int f; /* file descriptor from which to read */
|
||
|
{
|
||
|
#if (defined(USE_SYSV_TERMIO) || defined(USE_POSIX_TERMIOS))
|
||
|
char oldmin, oldtim;
|
||
|
#endif
|
||
|
char c;
|
||
|
struct sgttyb sg; /* tty device structure */
|
||
|
|
||
|
GTTY(f, &sg); /* get settings */
|
||
|
#if (defined(USE_SYSV_TERMIO) || defined(USE_POSIX_TERMIOS))
|
||
|
oldmin = sg.c_cc[VMIN]; /* save old values */
|
||
|
oldtim = sg.c_cc[VTIME];
|
||
|
sg.c_cc[VMIN] = 1; /* need only one char to return read() */
|
||
|
sg.c_cc[VTIME] = 0; /* no timeout */
|
||
|
sg.sg_flags &= ~ICANON; /* canonical mode off */
|
||
|
#else
|
||
|
sg.sg_flags |= CBREAK; /* cbreak mode on */
|
||
|
#endif
|
||
|
sg.sg_flags &= ~ECHO; /* turn echo off, too */
|
||
|
STTY(f, &sg); /* set cbreak mode */
|
||
|
GLOBAL(echofd) = f; /* in case ^C hit (not perfect: still CBREAK) */
|
||
|
|
||
|
read(f, &c, 1); /* read our character */
|
||
|
|
||
|
#if (defined(USE_SYSV_TERMIO) || defined(USE_POSIX_TERMIOS))
|
||
|
sg.c_cc[VMIN] = oldmin; /* restore old values */
|
||
|
sg.c_cc[VTIME] = oldtim;
|
||
|
sg.sg_flags |= ICANON; /* canonical mode on */
|
||
|
#else
|
||
|
sg.sg_flags &= ~CBREAK; /* cbreak mode off */
|
||
|
#endif
|
||
|
sg.sg_flags |= ECHO; /* turn echo on */
|
||
|
STTY(f, &sg); /* restore canonical mode */
|
||
|
GLOBAL(echofd) = -1;
|
||
|
|
||
|
return (int)c;
|
||
|
}
|
||
|
|
||
|
|
||
|
#else /* !UNIX && !__BEOS__ */
|
||
|
|
||
|
|
||
|
int zgetch(__G__ f)
|
||
|
__GDEF
|
||
|
int f; /* file descriptor from which to read (must be open already) */
|
||
|
{
|
||
|
char c, c2;
|
||
|
|
||
|
/*---------------------------------------------------------------------------
|
||
|
Get a character from the given file descriptor without echo; can't fake
|
||
|
CBREAK mode (i.e., newline required), but can get rid of all chars up to
|
||
|
and including newline.
|
||
|
---------------------------------------------------------------------------*/
|
||
|
|
||
|
echoff(f);
|
||
|
read(f, &c, 1);
|
||
|
if (c != '\n')
|
||
|
do {
|
||
|
read(f, &c2, 1); /* throw away all other chars up thru newline */
|
||
|
} while (c2 != '\n');
|
||
|
echon();
|
||
|
return (int)c;
|
||
|
}
|
||
|
|
||
|
#endif /* ?(UNIX || __BEOS__) */
|
||
|
|
||
|
#endif /* UNZIP && !FUNZIP */
|
||
|
#endif /* !HAVE_WORKING_GETCH */
|
||
|
|
||
|
|
||
|
#if CRYPT /* getp() is only used with full encryption */
|
||
|
|
||
|
/*
|
||
|
* Simple compile-time check for source compatibility between
|
||
|
* zcrypt and ttyio:
|
||
|
*/
|
||
|
#if (!defined(CR_MAJORVER) || (CR_MAJORVER < 2) || (CR_MINORVER < 7))
|
||
|
error: This Info-ZIP tool requires zcrypt 2.7 or later.
|
||
|
#endif
|
||
|
|
||
|
/*
|
||
|
* Get a password of length n-1 or less into *p using the prompt *m.
|
||
|
* The entered password is not echoed.
|
||
|
*/
|
||
|
|
||
|
#ifdef HAVE_WORKING_GETCH
|
||
|
/*
|
||
|
* For the AMIGA, getch() is defined as Agetch(), which is in
|
||
|
* amiga/filedate.c; SAS/C 6.x provides a getch(), but since Agetch()
|
||
|
* uses the infrastructure that is already in place in filedate.c, it is
|
||
|
* smaller. With this function, echoff() and echon() are not needed.
|
||
|
*
|
||
|
* For the MAC, a non-echo macgetch() function is defined in the MacOS
|
||
|
* specific sources which uses the event handling mechanism of the
|
||
|
* desktop window manager to get a character from the keyboard.
|
||
|
*
|
||
|
* For the other systems in this section, a non-echo getch() function
|
||
|
* is either contained the C runtime library (conio package), or getch()
|
||
|
* is defined as an alias for a similar system specific RTL function.
|
||
|
*/
|
||
|
|
||
|
#ifndef WINDLL /* WINDLL does not support a console interface */
|
||
|
#ifndef QDOS /* QDOS supplies a variant of this function */
|
||
|
|
||
|
/* This is the getp() function for all systems (with TTY type user interface)
|
||
|
* that supply a working `non-echo' getch() function for "raw" console input.
|
||
|
*/
|
||
|
char *getp(__G__ m, p, n)
|
||
|
__GDEF
|
||
|
ZCONST char *m; /* prompt for password */
|
||
|
char *p; /* return value: line input */
|
||
|
int n; /* bytes available in p[] */
|
||
|
{
|
||
|
char c; /* one-byte buffer for read() to use */
|
||
|
int i; /* number of characters input */
|
||
|
char *w; /* warning on retry */
|
||
|
|
||
|
/* get password */
|
||
|
w = "";
|
||
|
do {
|
||
|
fputs(w, stderr); /* warning if back again */
|
||
|
fputs(m, stderr); /* display prompt and flush */
|
||
|
fflush(stderr);
|
||
|
i = 0;
|
||
|
do { /* read line, keeping first n characters */
|
||
|
if ((c = (char)getch()) == '\r')
|
||
|
c = '\n'; /* until user hits CR */
|
||
|
if (c == 8 || c == 127) {
|
||
|
if (i > 0) i--; /* the `backspace' and `del' keys works */
|
||
|
}
|
||
|
else if (i < n)
|
||
|
p[i++] = c; /* truncate past n */
|
||
|
} while (c != '\n');
|
||
|
PUTC('\n', stderr); fflush(stderr);
|
||
|
w = "(line too long--try again)\n";
|
||
|
} while (p[i-1] != '\n');
|
||
|
p[i-1] = 0; /* terminate at newline */
|
||
|
|
||
|
return p; /* return pointer to password */
|
||
|
|
||
|
} /* end function getp() */
|
||
|
|
||
|
#endif /* !QDOS */
|
||
|
#endif /* !WINDLL */
|
||
|
|
||
|
|
||
|
#else /* !HAVE_WORKING_GETCH */
|
||
|
|
||
|
|
||
|
#if (defined(UNIX) || defined(__MINT__) || defined(__BEOS__))
|
||
|
|
||
|
#ifndef _PATH_TTY
|
||
|
# ifdef __MINT__
|
||
|
# define _PATH_TTY ttyname(2)
|
||
|
# else
|
||
|
# define _PATH_TTY "/dev/tty"
|
||
|
# endif
|
||
|
#endif
|
||
|
|
||
|
char *getp(__G__ m, p, n)
|
||
|
__GDEF
|
||
|
ZCONST char *m; /* prompt for password */
|
||
|
char *p; /* return value: line input */
|
||
|
int n; /* bytes available in p[] */
|
||
|
{
|
||
|
char c; /* one-byte buffer for read() to use */
|
||
|
int i; /* number of characters input */
|
||
|
char *w; /* warning on retry */
|
||
|
int f; /* file descriptor for tty device */
|
||
|
|
||
|
#ifdef PASSWD_FROM_STDIN
|
||
|
/* Read from stdin. This is unsafe if the password is stored on disk. */
|
||
|
f = 0;
|
||
|
#else
|
||
|
/* turn off echo on tty */
|
||
|
|
||
|
if ((f = open(_PATH_TTY, 0)) == -1)
|
||
|
return NULL;
|
||
|
#endif
|
||
|
/* get password */
|
||
|
w = "";
|
||
|
do {
|
||
|
fputs(w, stderr); /* warning if back again */
|
||
|
fputs(m, stderr); /* prompt */
|
||
|
fflush(stderr);
|
||
|
i = 0;
|
||
|
echoff(f);
|
||
|
do { /* read line, keeping n */
|
||
|
read(f, &c, 1);
|
||
|
if (i < n)
|
||
|
p[i++] = c;
|
||
|
} while (c != '\n');
|
||
|
echon();
|
||
|
PUTC('\n', stderr); fflush(stderr);
|
||
|
w = "(line too long--try again)\n";
|
||
|
} while (p[i-1] != '\n');
|
||
|
p[i-1] = 0; /* terminate at newline */
|
||
|
|
||
|
#ifndef PASSWD_FROM_STDIN
|
||
|
close(f);
|
||
|
#endif
|
||
|
|
||
|
return p; /* return pointer to password */
|
||
|
|
||
|
} /* end function getp() */
|
||
|
|
||
|
#endif /* UNIX || __MINT__ || __BEOS__ */
|
||
|
|
||
|
|
||
|
|
||
|
#if (defined(VMS) || defined(CMS_MVS))
|
||
|
|
||
|
char *getp(__G__ m, p, n)
|
||
|
__GDEF
|
||
|
ZCONST char *m; /* prompt for password */
|
||
|
char *p; /* return value: line input */
|
||
|
int n; /* bytes available in p[] */
|
||
|
{
|
||
|
char c; /* one-byte buffer for read() to use */
|
||
|
int i; /* number of characters input */
|
||
|
char *w; /* warning on retry */
|
||
|
FILE *f; /* file structure for SYS$COMMAND device */
|
||
|
|
||
|
#ifdef PASSWD_FROM_STDIN
|
||
|
f = stdin;
|
||
|
#else
|
||
|
if ((f = fopen(ctermid(NULL), "r")) == NULL)
|
||
|
return NULL;
|
||
|
#endif
|
||
|
|
||
|
/* get password */
|
||
|
fflush(stdout);
|
||
|
w = "";
|
||
|
do {
|
||
|
if (*w) /* bug: VMS apparently adds \n to NULL fputs */
|
||
|
fputs(w, stderr); /* warning if back again */
|
||
|
fputs(m, stderr); /* prompt */
|
||
|
fflush(stderr);
|
||
|
i = 0;
|
||
|
echoff(f);
|
||
|
do { /* read line, keeping n */
|
||
|
if ((c = (char)getc(f)) == '\r')
|
||
|
c = '\n';
|
||
|
if (i < n)
|
||
|
p[i++] = c;
|
||
|
} while (c != '\n');
|
||
|
echon();
|
||
|
PUTC('\n', stderr); fflush(stderr);
|
||
|
w = "(line too long--try again)\n";
|
||
|
} while (p[i-1] != '\n');
|
||
|
p[i-1] = 0; /* terminate at newline */
|
||
|
#ifndef PASSWD_FROM_STDIN
|
||
|
fclose(f);
|
||
|
#endif
|
||
|
|
||
|
return p; /* return pointer to password */
|
||
|
|
||
|
} /* end function getp() */
|
||
|
|
||
|
#endif /* VMS || CMS_MVS */
|
||
|
#endif /* ?HAVE_WORKING_GETCH */
|
||
|
#endif /* CRYPT */
|
||
|
#endif /* CRYPT || (UNZIP && !FUNZIP) */
|