mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-01-31 11:37:35 +00:00
cf93ecbbb2
The whole repository is now buildable with GNU Make Landlock sandboxing. This proves that no Makefile targets exist which touch files other than their declared prerequisites. In order to do this, we had to: 1. Stop code morphing GCC output in package.com and instead run a newly introduced FIXUPOBJ.COM command after GCC invocations. 2. Disable all the crumby Python unit tests that do things like create files in the current directory, or rename() files between folders. This ended up being a lot of tests, but most of them are still ok. 3. Introduce an .UNSANDBOXED variable to GNU Make to disable Landlock. We currently only do this for things like `make tags`. 4. This change deletes some GNU Make code that was preventing the execve() optimization from working. This means it should no longer be necessary in most cases for command invocations to be indirected through the cocmd interpreter. 5. Missing dependencies had to be declared in certain places, in cases where they couldn't be automatically determined by MKDEPS.COM 6. The libcxx header situation has finally been tamed. One of the things that makes this difficult is MKDEPS.COM only wants to consider the first 64kb of a file, in order to go fast. But libcxx likes to have #include lines buried after huge documentation. 7. An .UNVEIL variable has been introduced to GNU Make just in case we ever wish to explicitly specify additional things that need to be whitelisted which aren't strictly prerequisites. This works in a manner similar to the recently introduced .EXTRA_PREREQS feature. There's now a new build/bootstrap/make.com prebuilt binary available. It should no longer be possible to write invalid Makefile code.
695 lines
20 KiB
C
695 lines
20 KiB
C
// clang-format off
|
|
/*
|
|
Copyright (c) 1990-2008 Info-ZIP. All rights reserved.
|
|
|
|
See the accompanying file LICENSE, version 2000-Apr-09 or later
|
|
(the contents of which are also included in zip.h) for terms of use.
|
|
If, for some reason, all these files are missing, the Info-ZIP license
|
|
also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html
|
|
*/
|
|
/*---------------------------------------------------------------------------
|
|
|
|
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)
|
|
screensize() (Unix only)
|
|
zgetch() (Unix, VMS, and non-Unix/VMS versions)
|
|
getp() ("PC," Unix/Atari/Be, VMS/VMCMS/MVS)
|
|
|
|
---------------------------------------------------------------------------*/
|
|
|
|
#define __TTYIO_C /* identifies this source module */
|
|
|
|
#include "third_party/unzip/zip.h"
|
|
#include "libc/calls/calls.h"
|
|
#include "libc/calls/struct/termios.h"
|
|
#include "libc/calls/termios.h"
|
|
#include "third_party/unzip/crypt.h"
|
|
#include "third_party/unzip/globals.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 "third_party/unzip/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
|
|
|
|
#if (defined(__ATHEOS__) || defined(__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))
|
|
# 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
|
|
/* Workaround for broken header files of older DECC distributions
|
|
* that are incompatible with the /NAMES=AS_IS qualifier. */
|
|
# define sys$assign SYS$ASSIGN
|
|
# define sys$dassgn SYS$DASSGN
|
|
# define sys$qiow SYS$QIOW
|
|
# else /* !VMS */
|
|
# ifdef HAVE_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
|
|
# endif
|
|
# ifdef HAVE_SYS_TERMIO_H
|
|
# endif
|
|
# ifdef NEED_PTEM
|
|
# 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))
|
|
# endif
|
|
# 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
|
|
# endif
|
|
# else
|
|
# endif
|
|
# endif /* ?VMS */
|
|
#endif /* !HAVE_WORKING_GETCH */
|
|
|
|
|
|
|
|
#ifndef HAVE_WORKING_GETCH
|
|
#ifdef VMS
|
|
|
|
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}; */
|
|
|
|
/*
|
|
* 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
|
|
*/
|
|
|
|
short DevChan, iosb[4];
|
|
long status;
|
|
unsigned long ttmode[2]; /* space for 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,
|
|
ttmode, 8, 0, 0, 0, 0);
|
|
if (!(status & 1))
|
|
return status;
|
|
status = iosb[0];
|
|
if (!(status & 1))
|
|
return status;
|
|
|
|
/* modify mode buffer to be either NOECHO or ECHO
|
|
* (depending on function argument opt)
|
|
*/
|
|
if (opt == 0) /* off */
|
|
ttmode[1] |= TT$M_NOECHO; /* set NOECHO bit */
|
|
else
|
|
ttmode[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,
|
|
ttmode, 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() */
|
|
|
|
|
|
/*
|
|
* Read a single character from keyboard in non-echoing mode (VMS).
|
|
* (returns EOF in case of errors)
|
|
*/
|
|
int tt_getch()
|
|
{
|
|
short DevChan, iosb[4];
|
|
long status;
|
|
char kbbuf[16]; /* input buffer with - some - excess length */
|
|
|
|
/* assign a channel to standard input */
|
|
status = sys$assign(&DevDesc, &DevChan, 0, 0);
|
|
if (!(status & 1))
|
|
return EOF;
|
|
|
|
/* read a single character from SYS$COMMAND (no-echo) and
|
|
* wait for completion
|
|
*/
|
|
status = sys$qiow(0,DevChan,
|
|
IO$_READVBLK|IO$M_NOECHO|IO$M_NOFILTR,
|
|
&iosb, 0, 0,
|
|
&kbbuf, 1, 0, 0, 0, 0);
|
|
if ((status&1) == 1)
|
|
status = iosb[0];
|
|
|
|
/* deassign the sys$input channel by way of clean-up
|
|
* (for this step, we do not need to check the completion status)
|
|
*/
|
|
sys$dassgn(DevChan);
|
|
|
|
/* return the first char read, or EOF in case the read request failed */
|
|
return (int)(((status&1) == 1) ? (uch)kbbuf[0] : EOF);
|
|
|
|
} /* end function tt_getch() */
|
|
|
|
|
|
#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))
|
|
|
|
#ifdef ATH_BEO_UNX
|
|
#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 screensize(tt_rows, tt_cols)
|
|
int *tt_rows;
|
|
int *tt_cols;
|
|
{
|
|
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 screensize(): ws_row = %d\n",
|
|
wsz.ws_row);
|
|
fprintf(stderr, "ttyio.c screensize(): ws_col = %d\n",
|
|
wsz.ws_col);
|
|
}
|
|
#endif
|
|
/* number of rows */
|
|
if (tt_rows != NULL)
|
|
*tt_rows = (int)((wsz.ws_row > 0) ? wsz.ws_row : 24);
|
|
/* number of columns */
|
|
if (tt_cols != NULL)
|
|
*tt_cols = (int)((wsz.ws_col > 0) ? wsz.ws_col : 80);
|
|
return 0; /* signal success */
|
|
} else { /* this happens when piping to more(1), for example */
|
|
#ifdef DEBUG_WINSZ
|
|
if (firsttime) {
|
|
firsttime = FALSE;
|
|
fprintf(stderr,
|
|
"ttyio.c screensize(): ioctl(TIOCGWINSZ) failed\n"));
|
|
}
|
|
#endif
|
|
/* VT-100 assumed to be minimal hardware */
|
|
if (tt_rows != NULL)
|
|
*tt_rows = 24;
|
|
if (tt_cols != NULL)
|
|
*tt_cols = 80;
|
|
return 1; /* signal failure */
|
|
}
|
|
}
|
|
|
|
#else /* !TIOCGWINSZ: service not available, fall back to semi-bogus method */
|
|
|
|
int screensize(tt_rows, tt_cols)
|
|
int *tt_rows;
|
|
int *tt_cols;
|
|
{
|
|
char *envptr, *getenv();
|
|
int n;
|
|
int errstat = 0;
|
|
|
|
/* GRR: this is overly simplistic, but don't have access to stty/gtty
|
|
* system anymore
|
|
*/
|
|
if (tt_rows != NULL) {
|
|
envptr = getenv("LINES");
|
|
if (envptr == (char *)NULL || (n = atoi(envptr)) < 5) {
|
|
/* VT-100 assumed to be minimal hardware */
|
|
*tt_rows = 24;
|
|
errstat = 1; /* signal failure */
|
|
} else {
|
|
*tt_rows = n;
|
|
}
|
|
}
|
|
if (tt_cols != NULL) {
|
|
envptr = getenv("COLUMNS");
|
|
if (envptr == (char *)NULL || (n = atoi(envptr)) < 5) {
|
|
*tt_cols = 80;
|
|
errstat = 1; /* signal failure */
|
|
} else {
|
|
*tt_cols = n;
|
|
}
|
|
}
|
|
return errstat;
|
|
}
|
|
|
|
#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)(uch)c;
|
|
}
|
|
|
|
|
|
#else /* !ATH_BEO_UNX */
|
|
#ifndef VMS /* VMS supplies its own variant of getch() */
|
|
|
|
|
|
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 /* !VMS */
|
|
#endif /* ?ATH_BEO_UNX */
|
|
|
|
#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(ATH_BEO_UNX) || defined(__MINT__))
|
|
|
|
#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 /* ATH_BEO_UNX || __MINT__ */
|
|
|
|
|
|
|
|
#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) */
|