home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 9 Archive / 09-Archive.zip / unzip531.zip / ttyio.c < prev    next >
C/C++ Source or Header  |  1997-04-13  |  18KB  |  624 lines

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