Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2.   Copyright (c) 1990-2008 Info-ZIP.  All rights reserved.
  3.  
  4.   See the accompanying file LICENSE, version 2000-Apr-09 or later
  5.   (the contents of which are also included in zip.h) for terms of use.
  6.   If, for some reason, all these files are missing, the Info-ZIP license
  7.   also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
  8. */
  9. /*---------------------------------------------------------------------------
  10.  
  11.   ttyio.c
  12.  
  13.   This file contains routines for doing console input/output, including code
  14.   for non-echoing input.  It is used by the encryption/decryption code but
  15.   does not contain any restricted code itself.  This file is shared between
  16.   Info-ZIP's Zip and UnZip.
  17.  
  18.   Contains:  echo()         (VMS only)
  19.              Echon()        (Unix only)
  20.              Echoff()       (Unix only)
  21.              screensize()   (Unix only)
  22.              zgetch()       (Unix, VMS, and non-Unix/VMS versions)
  23.              getp()         ("PC," Unix/Atari/Be, VMS/VMCMS/MVS)
  24.  
  25.   ---------------------------------------------------------------------------*/
  26.  
  27. #define __TTYIO_C       /* identifies this source module */
  28.  
  29. #include "zip.h"
  30. #include "crypt.h"
  31.  
  32. #if (CRYPT || (defined(UNZIP) && !defined(FUNZIP)))
  33. /* Non-echo console/keyboard input is needed for (en/de)cryption's password
  34.  * entry, and for UnZip(SFX)'s MORE and Pause features.
  35.  * (The corresponding #endif is found at the end of this module.)
  36.  */
  37.  
  38. #include "ttyio.h"
  39.  
  40. #ifndef PUTC
  41. #  define PUTC putc
  42. #endif
  43.  
  44. #ifdef ZIP
  45. #  ifdef GLOBAL          /* used in Amiga system headers, maybe others too */
  46. #    undef GLOBAL
  47. #  endif
  48. #  define GLOBAL(g) g
  49. #else
  50. #  define GLOBAL(g) G.g
  51. #endif
  52.  
  53. #if (defined(__ATHEOS__) || defined(__BEOS__))  /* why yes, we do */
  54. #  define HAVE_TERMIOS_H
  55. #endif
  56.  
  57. #ifdef _POSIX_VERSION
  58. #  ifndef USE_POSIX_TERMIOS
  59. #    define USE_POSIX_TERMIOS  /* use POSIX style termio (termios) */
  60. #  endif
  61. #  ifndef HAVE_TERMIOS_H
  62. #    define HAVE_TERMIOS_H     /* POSIX termios.h */
  63. #  endif
  64. #endif /* _POSIX_VERSION */
  65.  
  66. #ifdef UNZIP            /* Zip handles this with the unix/configure script */
  67. #  ifndef _POSIX_VERSION
  68. #    if (defined(SYSV) || defined(CRAY)) &&  !defined(__MINT__)
  69. #      ifndef USE_SYSV_TERMIO
  70. #        define USE_SYSV_TERMIO
  71. #      endif
  72. #      ifdef COHERENT
  73. #        ifndef HAVE_TERMIO_H
  74. #          define HAVE_TERMIO_H
  75. #        endif
  76. #        ifdef HAVE_SYS_TERMIO_H
  77. #          undef HAVE_SYS_TERMIO_H
  78. #        endif
  79. #      else /* !COHERENT */
  80. #        ifdef HAVE_TERMIO_H
  81. #          undef HAVE_TERMIO_H
  82. #        endif
  83. #        ifndef HAVE_SYS_TERMIO_H
  84. #           define HAVE_SYS_TERMIO_H
  85. #        endif
  86. #      endif /* ?COHERENT */
  87. #    endif /* (SYSV || CRAY) && !__MINT__ */
  88. #  endif /* !_POSIX_VERSION */
  89. #  if !(defined(BSD4_4) || defined(SYSV) || defined(__convexc__))
  90. #    ifndef NO_FCNTL_H
  91. #      define NO_FCNTL_H
  92. #    endif
  93. #  endif /* !(BSD4_4 || SYSV || __convexc__) */
  94. #endif /* UNZIP */
  95.  
  96. #ifdef HAVE_TERMIOS_H
  97. #  ifndef USE_POSIX_TERMIOS
  98. #    define USE_POSIX_TERMIOS
  99. #  endif
  100. #endif
  101.  
  102. #if (defined(HAVE_TERMIO_H) || defined(HAVE_SYS_TERMIO_H))
  103. #  ifndef USE_SYSV_TERMIO
  104. #    define USE_SYSV_TERMIO
  105. #  endif
  106. #endif
  107.  
  108. #if (defined(UNZIP) && !defined(FUNZIP) && defined(UNIX) && defined(MORE))
  109. #  include <sys/ioctl.h>
  110. #  define GOT_IOCTL_H
  111.    /* int ioctl OF((int, int, zvoid *));   GRR: may need for some systems */
  112. #endif
  113.  
  114. #ifndef HAVE_WORKING_GETCH
  115.    /* include system support for switching of console echo */
  116. #  ifdef VMS
  117. #    include <descrip.h>
  118. #    include <iodef.h>
  119. #    include <ttdef.h>
  120.      /* Workaround for broken header files of older DECC distributions
  121.       * that are incompatible with the /NAMES=AS_IS qualifier. */
  122. #    define sys$assign SYS$ASSIGN
  123. #    define sys$dassgn SYS$DASSGN
  124. #    define sys$qiow SYS$QIOW
  125. #    include <starlet.h>
  126. #    include <ssdef.h>
  127. #  else /* !VMS */
  128. #    ifdef HAVE_TERMIOS_H
  129. #      include <termios.h>
  130. #      define sgttyb termios
  131. #      define sg_flags c_lflag
  132. #      define GTTY(f, s) tcgetattr(f, (zvoid *) s)
  133. #      define STTY(f, s) tcsetattr(f, TCSAFLUSH, (zvoid *) s)
  134. #    else /* !HAVE_TERMIOS_H */
  135. #      ifdef USE_SYSV_TERMIO           /* Amdahl, Cray, all SysV? */
  136. #        ifdef HAVE_TERMIO_H
  137. #          include <termio.h>
  138. #        endif
  139. #        ifdef HAVE_SYS_TERMIO_H
  140. #          include <sys/termio.h>
  141. #        endif
  142. #        ifdef NEED_PTEM
  143. #          include <sys/stream.h>
  144. #          include <sys/ptem.h>
  145. #        endif
  146. #        define sgttyb termio
  147. #        define sg_flags c_lflag
  148. #        define GTTY(f,s) ioctl(f,TCGETA,(zvoid *)s)
  149. #        define STTY(f,s) ioctl(f,TCSETAW,(zvoid *)s)
  150. #      else /* !USE_SYSV_TERMIO */
  151. #        ifndef CMS_MVS
  152. #          if (!defined(MINIX) && !defined(GOT_IOCTL_H))
  153. #            include <sys/ioctl.h>
  154. #          endif
  155. #          include <sgtty.h>
  156. #          define GTTY gtty
  157. #          define STTY stty
  158. #          ifdef UNZIP
  159.              /*
  160.               * XXX : Are these declarations needed at all ????
  161.               */
  162.              /*
  163.               * GRR: let's find out...   Hmmm, appears not...
  164.              int gtty OF((int, struct sgttyb *));
  165.              int stty OF((int, struct sgttyb *));
  166.               */
  167. #          endif
  168. #        endif /* !CMS_MVS */
  169. #      endif /* ?USE_SYSV_TERMIO */
  170. #    endif /* ?HAVE_TERMIOS_H */
  171. #    ifndef NO_FCNTL_H
  172. #      ifndef UNZIP
  173. #        include <fcntl.h>
  174. #      endif
  175. #    else
  176.        char *ttyname OF((int));
  177. #    endif
  178. #  endif /* ?VMS */
  179. #endif /* !HAVE_WORKING_GETCH */
  180.  
  181.  
  182.  
  183. #ifndef HAVE_WORKING_GETCH
  184. #ifdef VMS
  185.  
  186. static struct dsc$descriptor_s DevDesc =
  187.         {11, DSC$K_DTYPE_T, DSC$K_CLASS_S, "SYS$COMMAND"};
  188.      /* {dsc$w_length, dsc$b_dtype, dsc$b_class, dsc$a_pointer}; */
  189.  
  190. /*
  191.  * Turn keyboard echoing on or off (VMS).  Loosely based on VMSmunch.c
  192.  * and hence on Joe Meadows' file.c code.
  193.  */
  194. int echo(opt)
  195.     int opt;
  196. {
  197.     /*
  198.      * For VMS v5.x:
  199.      *   IO$_SENSEMODE/SETMODE info:  Programming, Vol. 7A, System Programming,
  200.      *     I/O User's: Part I, sec. 8.4.1.1, 8.4.3, 8.4.5, 8.6
  201.      *   sys$assign(), sys$qio() info:  Programming, Vol. 4B, System Services,
  202.      *     System Services Reference Manual, pp. sys-23, sys-379
  203.      *   fixed-length descriptor info:  Programming, Vol. 3, System Services,
  204.      *     Intro to System Routines, sec. 2.9.2
  205.      * Greg Roelofs, 15 Aug 91
  206.      */
  207.  
  208.     short           DevChan, iosb[4];
  209.     long            status;
  210.     unsigned long   ttmode[2];  /* space for 8 bytes */
  211.  
  212.  
  213.     /* assign a channel to standard input */
  214.     status = sys$assign(&DevDesc, &DevChan, 0, 0);
  215.     if (!(status & 1))
  216.         return status;
  217.  
  218.     /* use sys$qio and the IO$_SENSEMODE function to determine the current
  219.      * tty status (for password reading, could use IO$_READVBLK function
  220.      * instead, but echo on/off will be more general)
  221.      */
  222.     status = sys$qiow(0, DevChan, IO$_SENSEMODE, &iosb, 0, 0,
  223.                      ttmode, 8, 0, 0, 0, 0);
  224.     if (!(status & 1))
  225.         return status;
  226.     status = iosb[0];
  227.     if (!(status & 1))
  228.         return status;
  229.  
  230.     /* modify mode buffer to be either NOECHO or ECHO
  231.      * (depending on function argument opt)
  232.      */
  233.     if (opt == 0)   /* off */
  234.         ttmode[1] |= TT$M_NOECHO;                       /* set NOECHO bit */
  235.     else
  236.         ttmode[1] &= ~((unsigned long) TT$M_NOECHO);    /* clear NOECHO bit */
  237.  
  238.     /* use the IO$_SETMODE function to change the tty status */
  239.     status = sys$qiow(0, DevChan, IO$_SETMODE, &iosb, 0, 0,
  240.                      ttmode, 8, 0, 0, 0, 0);
  241.     if (!(status & 1))
  242.         return status;
  243.     status = iosb[0];
  244.     if (!(status & 1))
  245.         return status;
  246.  
  247.     /* deassign the sys$input channel by way of clean-up */
  248.     status = sys$dassgn(DevChan);
  249.     if (!(status & 1))
  250.         return status;
  251.  
  252.     return SS$_NORMAL;   /* we be happy */
  253.  
  254. } /* end function echo() */
  255.  
  256.  
  257. /*
  258.  * Read a single character from keyboard in non-echoing mode (VMS).
  259.  * (returns EOF in case of errors)
  260.  */
  261. int tt_getch()
  262. {
  263.     short           DevChan, iosb[4];
  264.     long            status;
  265.     char            kbbuf[16];  /* input buffer with - some - excess length */
  266.  
  267.     /* assign a channel to standard input */
  268.     status = sys$assign(&DevDesc, &DevChan, 0, 0);
  269.     if (!(status & 1))
  270.         return EOF;
  271.  
  272.     /* read a single character from SYS$COMMAND (no-echo) and
  273.      * wait for completion
  274.      */
  275.     status = sys$qiow(0,DevChan,
  276.                       IO$_READVBLK|IO$M_NOECHO|IO$M_NOFILTR,
  277.                       &iosb, 0, 0,
  278.                       &kbbuf, 1, 0, 0, 0, 0);
  279.     if ((status&1) == 1)
  280.         status = iosb[0];
  281.  
  282.     /* deassign the sys$input channel by way of clean-up
  283.      * (for this step, we do not need to check the completion status)
  284.      */
  285.     sys$dassgn(DevChan);
  286.  
  287.     /* return the first char read, or EOF in case the read request failed */
  288.     return (int)(((status&1) == 1) ? (uch)kbbuf[0] : EOF);
  289.  
  290. } /* end function tt_getch() */
  291.  
  292.  
  293. #else /* !VMS:  basically Unix */
  294.  
  295.  
  296. /* For VM/CMS and MVS, non-echo terminal input is not (yet?) supported. */
  297. #ifndef CMS_MVS
  298.  
  299. #ifdef ZIP                      /* moved to globals.h for UnZip */
  300.    static int echofd=(-1);      /* file descriptor whose echo is off */
  301. #endif
  302.  
  303. /*
  304.  * Turn echo off for file descriptor f.  Assumes that f is a tty device.
  305.  */
  306. void Echoff(__G__ f)
  307.     __GDEF
  308.     int f;                    /* file descriptor for which to turn echo off */
  309. {
  310.     struct sgttyb sg;         /* tty device structure */
  311.  
  312.     GLOBAL(echofd) = f;
  313.     GTTY(f, &sg);             /* get settings */
  314.     sg.sg_flags &= ~ECHO;     /* turn echo off */
  315.     STTY(f, &sg);
  316. }
  317.  
  318. /*
  319.  * Turn echo back on for file descriptor echofd.
  320.  */
  321. void Echon(__G)
  322.     __GDEF
  323. {
  324.     struct sgttyb sg;         /* tty device structure */
  325.  
  326.     if (GLOBAL(echofd) != -1) {
  327.         GTTY(GLOBAL(echofd), &sg);    /* get settings */
  328.         sg.sg_flags |= ECHO;  /* turn echo on */
  329.         STTY(GLOBAL(echofd), &sg);
  330.         GLOBAL(echofd) = -1;
  331.     }
  332. }
  333.  
  334. #endif /* !CMS_MVS */
  335. #endif /* ?VMS */
  336.  
  337.  
  338. #if (defined(UNZIP) && !defined(FUNZIP))
  339.  
  340. #ifdef ATH_BEO_UNX
  341. #ifdef MORE
  342.  
  343. /*
  344.  * Get the number of lines on the output terminal.  SCO Unix apparently
  345.  * defines TIOCGWINSZ but doesn't support it (!M_UNIX).
  346.  *
  347.  * GRR:  will need to know width of terminal someday, too, to account for
  348.  *       line-wrapping.
  349.  */
  350.  
  351. #if (defined(TIOCGWINSZ) && !defined(M_UNIX))
  352.  
  353. int screensize(tt_rows, tt_cols)
  354.     int *tt_rows;
  355.     int *tt_cols;
  356. {
  357.     struct winsize wsz;
  358. #ifdef DEBUG_WINSZ
  359.     static int firsttime = TRUE;
  360. #endif
  361.  
  362.     /* see termio(4) under, e.g., SunOS */
  363.     if (ioctl(1, TIOCGWINSZ, &wsz) == 0) {
  364. #ifdef DEBUG_WINSZ
  365.         if (firsttime) {
  366.             firsttime = FALSE;
  367.             fprintf(stderr, "ttyio.c screensize():  ws_row = %d\n",
  368.               wsz.ws_row);
  369.             fprintf(stderr, "ttyio.c screensize():  ws_col = %d\n",
  370.               wsz.ws_col);
  371.         }
  372. #endif
  373.         /* number of rows */
  374.         if (tt_rows != NULL)
  375.             *tt_rows = (int)((wsz.ws_row > 0) ? wsz.ws_row : 24);
  376.         /* number of columns */
  377.         if (tt_cols != NULL)
  378.             *tt_cols = (int)((wsz.ws_col > 0) ? wsz.ws_col : 80);
  379.         return 0;    /* signal success */
  380.     } else {         /* this happens when piping to more(1), for example */
  381. #ifdef DEBUG_WINSZ
  382.         if (firsttime) {
  383.             firsttime = FALSE;
  384.             fprintf(stderr,
  385.               "ttyio.c screensize():  ioctl(TIOCGWINSZ) failed\n"));
  386.         }
  387. #endif
  388.         /* VT-100 assumed to be minimal hardware */
  389.         if (tt_rows != NULL)
  390.             *tt_rows = 24;
  391.         if (tt_cols != NULL)
  392.             *tt_cols = 80;
  393.         return 1;       /* signal failure */
  394.     }
  395. }
  396.  
  397. #else /* !TIOCGWINSZ: service not available, fall back to semi-bogus method */
  398.  
  399. int screensize(tt_rows, tt_cols)
  400.     int *tt_rows;
  401.     int *tt_cols;
  402. {
  403.     char *envptr, *getenv();
  404.     int n;
  405.     int errstat = 0;
  406.  
  407.     /* GRR:  this is overly simplistic, but don't have access to stty/gtty
  408.      * system anymore
  409.      */
  410.     if (tt_rows != NULL) {
  411.         envptr = getenv("LINES");
  412.         if (envptr == (char *)NULL || (n = atoi(envptr)) < 5) {
  413.             /* VT-100 assumed to be minimal hardware */
  414.             *tt_rows = 24;
  415.             errstat = 1;    /* signal failure */
  416.         } else {
  417.             *tt_rows = n;
  418.         }
  419.     }
  420.     if (tt_cols != NULL) {
  421.         envptr = getenv("COLUMNS");
  422.         if (envptr == (char *)NULL || (n = atoi(envptr)) < 5) {
  423.             *tt_cols = 80;
  424.             errstat = 1;    /* signal failure */
  425.         } else {
  426.             *tt_cols = n;
  427.         }
  428.     }
  429.     return errstat;
  430. }
  431.  
  432. #endif /* ?(TIOCGWINSZ && !M_UNIX) */
  433. #endif /* MORE */
  434.  
  435.  
  436. /*
  437.  * Get a character from the given file descriptor without echo or newline.
  438.  */
  439. int zgetch(__G__ f)
  440.     __GDEF
  441.     int f;                      /* file descriptor from which to read */
  442. {
  443. #if (defined(USE_SYSV_TERMIO) || defined(USE_POSIX_TERMIOS))
  444.     char oldmin, oldtim;
  445. #endif
  446.     char c;
  447.     struct sgttyb sg;           /* tty device structure */
  448.  
  449.     GTTY(f, &sg);               /* get settings */
  450. #if (defined(USE_SYSV_TERMIO) || defined(USE_POSIX_TERMIOS))
  451.     oldmin = sg.c_cc[VMIN];     /* save old values */
  452.     oldtim = sg.c_cc[VTIME];
  453.     sg.c_cc[VMIN] = 1;          /* need only one char to return read() */
  454.     sg.c_cc[VTIME] = 0;         /* no timeout */
  455.     sg.sg_flags &= ~ICANON;     /* canonical mode off */
  456. #else
  457.     sg.sg_flags |= CBREAK;      /* cbreak mode on */
  458. #endif
  459.     sg.sg_flags &= ~ECHO;       /* turn echo off, too */
  460.     STTY(f, &sg);               /* set cbreak mode */
  461.     GLOBAL(echofd) = f;         /* in case ^C hit (not perfect: still CBREAK) */
  462.  
  463.     read(f, &c, 1);             /* read our character */
  464.  
  465. #if (defined(USE_SYSV_TERMIO) || defined(USE_POSIX_TERMIOS))
  466.     sg.c_cc[VMIN] = oldmin;     /* restore old values */
  467.     sg.c_cc[VTIME] = oldtim;
  468.     sg.sg_flags |= ICANON;      /* canonical mode on */
  469. #else
  470.     sg.sg_flags &= ~CBREAK;     /* cbreak mode off */
  471. #endif
  472.     sg.sg_flags |= ECHO;        /* turn echo on */
  473.     STTY(f, &sg);               /* restore canonical mode */
  474.     GLOBAL(echofd) = -1;
  475.  
  476.     return (int)(uch)c;
  477. }
  478.  
  479.  
  480. #else /* !ATH_BEO_UNX */
  481. #ifndef VMS     /* VMS supplies its own variant of getch() */
  482.  
  483.  
  484. int zgetch(__G__ f)
  485.     __GDEF
  486.     int f;    /* file descriptor from which to read (must be open already) */
  487. {
  488.     char c, c2;
  489.  
  490. /*---------------------------------------------------------------------------
  491.     Get a character from the given file descriptor without echo; can't fake
  492.     CBREAK mode (i.e., newline required), but can get rid of all chars up to
  493.     and including newline.
  494.   ---------------------------------------------------------------------------*/
  495.  
  496.     echoff(f);
  497.     read(f, &c, 1);
  498.     if (c != '\n')
  499.         do {
  500.             read(f, &c2, 1);   /* throw away all other chars up thru newline */
  501.         } while (c2 != '\n');
  502.     echon();
  503.     return (int)c;
  504. }
  505.  
  506. #endif /* !VMS */
  507. #endif /* ?ATH_BEO_UNX */
  508.  
  509. #endif /* UNZIP && !FUNZIP */
  510. #endif /* !HAVE_WORKING_GETCH */
  511.  
  512.  
  513. #if CRYPT                       /* getp() is only used with full encryption */
  514.  
  515. /*
  516.  * Simple compile-time check for source compatibility between
  517.  * zcrypt and ttyio:
  518.  */
  519. #if (!defined(CR_MAJORVER) || (CR_MAJORVER < 2) || (CR_MINORVER < 7))
  520.    error:  This Info-ZIP tool requires zcrypt 2.7 or later.
  521. #endif
  522.  
  523. /*
  524.  * Get a password of length n-1 or less into *p using the prompt *m.
  525.  * The entered password is not echoed.
  526.  */
  527.  
  528. #ifdef HAVE_WORKING_GETCH
  529. /*
  530.  * For the AMIGA, getch() is defined as Agetch(), which is in
  531.  * amiga/filedate.c; SAS/C 6.x provides a getch(), but since Agetch()
  532.  * uses the infrastructure that is already in place in filedate.c, it is
  533.  * smaller.  With this function, echoff() and echon() are not needed.
  534.  *
  535.  * For the MAC, a non-echo macgetch() function is defined in the MacOS
  536.  * specific sources which uses the event handling mechanism of the
  537.  * desktop window manager to get a character from the keyboard.
  538.  *
  539.  * For the other systems in this section, a non-echo getch() function
  540.  * is either contained the C runtime library (conio package), or getch()
  541.  * is defined as an alias for a similar system specific RTL function.
  542.  */
  543.  
  544. #ifndef WINDLL   /* WINDLL does not support a console interface */
  545. #ifndef QDOS     /* QDOS supplies a variant of this function */
  546.  
  547. /* This is the getp() function for all systems (with TTY type user interface)
  548.  * that supply a working `non-echo' getch() function for "raw" console input.
  549.  */
  550. char *getp(__G__ m, p, n)
  551.     __GDEF
  552.     ZCONST char *m;             /* prompt for password */
  553.     char *p;                    /* return value: line input */
  554.     int n;                      /* bytes available in p[] */
  555. {
  556.     char c;                     /* one-byte buffer for read() to use */
  557.     int i;                      /* number of characters input */
  558.     char *w;                    /* warning on retry */
  559.  
  560.     /* get password */
  561.     w = "";
  562.     do {
  563.         fputs(w, stderr);       /* warning if back again */
  564.         fputs(m, stderr);       /* display prompt and flush */
  565.         fflush(stderr);
  566.         i = 0;
  567.         do {                    /* read line, keeping first n characters */
  568.             if ((c = (char)getch()) == '\r')
  569.                 c = '\n';       /* until user hits CR */
  570.             if (c == 8 || c == 127) {
  571.                 if (i > 0) i--; /* the `backspace' and `del' keys works */
  572.             }
  573.             else if (i < n)
  574.                 p[i++] = c;     /* truncate past n */
  575.         } while (c != '\n');
  576.         PUTC('\n', stderr);  fflush(stderr);
  577.         w = "(line too long--try again)\n";
  578.     } while (p[i-1] != '\n');
  579.     p[i-1] = 0;                 /* terminate at newline */
  580.  
  581.     return p;                   /* return pointer to password */
  582.  
  583. } /* end function getp() */
  584.  
  585. #endif /* !QDOS */
  586. #endif /* !WINDLL */
  587.  
  588.  
  589. #else /* !HAVE_WORKING_GETCH */
  590.  
  591.  
  592. #if (defined(ATH_BEO_UNX) || defined(__MINT__))
  593.  
  594. #ifndef _PATH_TTY
  595. #  ifdef __MINT__
  596. #    define _PATH_TTY ttyname(2)
  597. #  else
  598. #    define _PATH_TTY "/dev/tty"
  599. #  endif
  600. #endif
  601.  
  602. char *getp(__G__ m, p, n)
  603.     __GDEF
  604.     ZCONST char *m;             /* prompt for password */
  605.     char *p;                    /* return value: line input */
  606.     int n;                      /* bytes available in p[] */
  607. {
  608.     char c;                     /* one-byte buffer for read() to use */
  609.     int i;                      /* number of characters input */
  610.     char *w;                    /* warning on retry */
  611.     int f;                      /* file descriptor for tty device */
  612.  
  613. #ifdef PASSWD_FROM_STDIN
  614.     /* Read from stdin. This is unsafe if the password is stored on disk. */
  615.     f = 0;
  616. #else
  617.     /* turn off echo on tty */
  618.  
  619.     if ((f = open(_PATH_TTY, 0)) == -1)
  620.         return NULL;
  621. #endif
  622.     /* get password */
  623.     w = "";
  624.     do {
  625.         fputs(w, stderr);       /* warning if back again */
  626.         fputs(m, stderr);       /* prompt */
  627.         fflush(stderr);
  628.         i = 0;
  629.         echoff(f);
  630.         do {                    /* read line, keeping n */
  631.             read(f, &c, 1);
  632.             if (i < n)
  633.                 p[i++] = c;
  634.         } while (c != '\n');
  635.         echon();
  636.         PUTC('\n', stderr);  fflush(stderr);
  637.         w = "(line too long--try again)\n";
  638.     } while (p[i-1] != '\n');
  639.     p[i-1] = 0;                 /* terminate at newline */
  640.  
  641. #ifndef PASSWD_FROM_STDIN
  642.     close(f);
  643. #endif
  644.  
  645.     return p;                   /* return pointer to password */
  646.  
  647. } /* end function getp() */
  648.  
  649. #endif /* ATH_BEO_UNX || __MINT__ */
  650.  
  651.  
  652.  
  653. #if (defined(VMS) || defined(CMS_MVS))
  654.  
  655. char *getp(__G__ m, p, n)
  656.     __GDEF
  657.     ZCONST char *m;             /* prompt for password */
  658.     char *p;                    /* return value: line input */
  659.     int n;                      /* bytes available in p[] */
  660. {
  661.     char c;                     /* one-byte buffer for read() to use */
  662.     int i;                      /* number of characters input */
  663.     char *w;                    /* warning on retry */
  664.     FILE *f;                    /* file structure for SYS$COMMAND device */
  665.  
  666. #ifdef PASSWD_FROM_STDIN
  667.     f = stdin;
  668. #else
  669.     if ((f = fopen(ctermid(NULL), "r")) == NULL)
  670.         return NULL;
  671. #endif
  672.  
  673.     /* get password */
  674.     fflush(stdout);
  675.     w = "";
  676.     do {
  677.         if (*w)                 /* bug: VMS apparently adds \n to NULL fputs */
  678.             fputs(w, stderr);   /* warning if back again */
  679.         fputs(m, stderr);       /* prompt */
  680.         fflush(stderr);
  681.         i = 0;
  682.         echoff(f);
  683.         do {                    /* read line, keeping n */
  684.             if ((c = (char)getc(f)) == '\r')
  685.                 c = '\n';
  686.             if (i < n)
  687.                 p[i++] = c;
  688.         } while (c != '\n');
  689.         echon();
  690.         PUTC('\n', stderr);  fflush(stderr);
  691.         w = "(line too long--try again)\n";
  692.     } while (p[i-1] != '\n');
  693.     p[i-1] = 0;                 /* terminate at newline */
  694. #ifndef PASSWD_FROM_STDIN
  695.     fclose(f);
  696. #endif
  697.  
  698.     return p;                   /* return pointer to password */
  699.  
  700. } /* end function getp() */
  701.  
  702. #endif /* VMS || CMS_MVS */
  703. #endif /* ?HAVE_WORKING_GETCH */
  704. #endif /* CRYPT */
  705. #endif /* CRYPT || (UNZIP && !FUNZIP) */
  706.