which included commits to RCS files with non-trunk default branches. git-svn-id: svn://10.65.10.50/trunk@5403 c028cbd2-c16b-5b4b-a496-9718f37d4682
		
			
				
	
	
		
			624 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			624 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
/*---------------------------------------------------------------------------
 | 
						|
 | 
						|
  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)
 | 
						|
 | 
						|
  ---------------------------------------------------------------------------*/
 | 
						|
 | 
						|
#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 mac/mac.c,
 | 
						|
 * which uses the event handling mechanisme 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) */
 |