home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 9 Archive / 09-Archive.zip / unzip52.zip / ttyio.c < prev    next >
C/C++ Source or Header  |  1996-04-16  |  19KB  |  636 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," Win, Unix/Atari and VMS/VMCMS/MVS versions)
  16.  
  17.   ---------------------------------------------------------------------------*/
  18.  
  19. #include "zip.h"
  20. #include "crypt.h"
  21.  
  22. #if (defined(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. #ifdef MSWIN
  29. #  include "wingui\wizunzip.h"
  30. #  include "wingui\password.h"
  31. #endif
  32. #include "ttyio.h"
  33.  
  34.  
  35. #ifndef PUTC
  36. #  define PUTC putc
  37. #endif
  38.  
  39. #ifdef ZIP
  40. #  ifdef GLOBAL          /* used in Amiga system headers, maybe others too */
  41. #    undef GLOBAL
  42. #  endif
  43. #  define GLOBAL(g) g
  44. #else /* !ZIP */
  45. #  define GLOBAL(g) G.g
  46. #endif /* ?ZIP */
  47.  
  48. #ifdef _POSIX_VERSION
  49. #  ifndef USE_POSIX_TERMIOS
  50. #    define USE_POSIX_TERMIOS  /* use POSIX style termio (termios) */
  51. #  endif
  52. #  ifndef HAVE_TERMIOS_H
  53. #    define HAVE_TERMIOS_H     /* POSIX termios.h */
  54. #  endif
  55. #endif /* _POSIX_VERSION */
  56.  
  57. #ifdef UNZIP            /* Zip handles this with the unix/configure script */
  58. #  ifndef _POSIX_VERSION
  59. #    if (defined(SYSV) || defined(CRAY)) &&  !defined(__MINT__)
  60. #      ifndef USE_SYSV_TERMIO
  61. #        define USE_SYSV_TERMIO
  62. #      endif
  63. #      ifdef COHERENT
  64. #        ifndef HAVE_TERMIO_H
  65. #          define HAVE_TERMIO_H
  66. #        endif
  67. #        ifdef HAVE_SYS_TERMIO_H
  68. #          undef HAVE_SYS_TERMIO_H
  69. #        endif
  70. #      else /* !COHERENT */
  71. #        ifdef HAVE_TERMIO_H
  72. #          undef HAVE_TERMIO_H
  73. #        endif
  74. #        ifndef HAVE_SYS_TERMIO_H
  75. #           define HAVE_SYS_TERMIO_H
  76. #        endif
  77. #      endif /* ?COHERENT */
  78. #    endif /* (SYSV || CRAY) && !__MINT__ */
  79. #  endif /* !_POSIX_VERSION */
  80. #  if !(defined(BSD4_4) || defined(SYSV) || defined(__convexc__))
  81. #    ifndef NO_FCNTL_H
  82. #      define NO_FCNTL_H
  83. #    endif
  84. #  endif /* !(BSD4_4 || SYSV || __convexc__) */
  85. #endif /* UNZIP */
  86.  
  87. #ifdef HAVE_TERMIOS_H
  88. #  ifndef USE_POSIX_TERMIOS
  89. #    define USE_POSIX_TERMIOS
  90. #  endif
  91. #endif
  92.  
  93. #if (defined(HAVE_TERMIO_H) || defined(HAVE_SYS_TERMIO_H))
  94. #  ifndef USE_SYSV_TERMIO
  95. #    define USE_SYSV_TERMIO
  96. #  endif
  97. #endif
  98.  
  99. #ifndef HAVE_WORKING_GETCH
  100.    /* include system support for switching of console echo */
  101. #  ifdef VMS
  102. #    include <descrip.h>
  103. #    include <iodef.h>
  104. #    include <ttdef.h>
  105. #    include <starlet.h>
  106. #    include <ssdef.h>
  107. #  else /* !VMS */
  108. #    ifdef HAVE_TERMIOS_H
  109. #      include <termios.h>
  110. #      define sgttyb termios
  111. #      define sg_flags c_lflag
  112. #      define GTTY(f, s) tcgetattr(f, (zvoid *) s)
  113. #      define STTY(f, s) tcsetattr(f, TCSAFLUSH, (zvoid *) s)
  114. #    else /* !HAVE_TERMIOS */
  115. #       ifdef USE_SYSV_TERMIO           /* Amdahl, Cray, all SysV? */
  116. #         ifdef HAVE_TERMIO_H
  117. #           include <termio.h>
  118. #         endif
  119. #         ifdef HAVE_SYS_TERMIO_H
  120. #           include <sys/termio.h>
  121. #         endif
  122. #         define sgttyb termio
  123. #         define sg_flags c_lflag
  124. #         ifdef UNZIP
  125.            /*
  126.             * XXX : We should check if this declaration can get removed
  127.             *       (already in unistd.h)
  128. #          ifndef SYSV
  129.             int ioctl OF((int, int, zvoid *));
  130. #          endif
  131.             */
  132. #         endif
  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. #           ifndef MINIX
  138. #             include <sys/ioctl.h>
  139. #           endif /* !MINIX */
  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...
  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. /* For VM/CMS and MVS, non-echo terminal input is not (yet?) supported. */
  246. #ifndef CMS_MVS
  247.  
  248. #ifndef UNZIP                   /* moved to globals.h for UnZip */
  249.    static int echofd=(-1);      /* file descriptor whose echo is off */
  250. #endif
  251.  
  252. /***********************************************************************
  253.  * Turn echo off for file descriptor f.  Assumes that f is a tty device.
  254.  */
  255. void Echoff(__G__ f)
  256.     __GDEF
  257.     int f;                    /* file descriptor for which to turn echo off */
  258. {
  259.     struct sgttyb sg;         /* tty device structure */
  260.  
  261.     GLOBAL(echofd) = f;
  262.     GTTY(f, &sg);             /* get settings */
  263.     sg.sg_flags &= ~ECHO;     /* turn echo off */
  264.     STTY(f, &sg);
  265. }
  266.  
  267. /***********************************************************************
  268.  * Turn echo back on for file descriptor echofd.
  269.  */
  270. void Echon(__G)
  271.     __GDEF
  272. {
  273.     struct sgttyb sg;         /* tty device structure */
  274.  
  275.     if (GLOBAL(echofd) != -1) {
  276.         GTTY(GLOBAL(echofd), &sg);    /* get settings */
  277.         sg.sg_flags |= ECHO;  /* turn echo on */
  278.         STTY(GLOBAL(echofd), &sg);
  279.         GLOBAL(echofd) = -1;
  280.     }
  281. }
  282.  
  283. #endif /* !CMS_MVS */
  284. #endif /* ?VMS */
  285.  
  286.  
  287. #if (defined(UNZIP) && !defined(FUNZIP))
  288.  
  289. #ifdef UNIX
  290. #ifdef MORE
  291.  
  292. /***********************************************************************
  293.  * Get the number of lines on the output terminal.
  294.  * GRR:  will need to know width of terminal someday, too:  line wrap
  295.  */
  296.  
  297. #ifdef TIOCGWINSZ
  298.  
  299. int screenlines()
  300. {
  301.     struct winsize wsz;
  302. #ifdef DEBUG_WINSZ
  303.     static int firsttime = TRUE;
  304. #endif
  305.  
  306.     /* see termio(4) under, e.g., SunOS */
  307.     if (ioctl(1, TIOCGWINSZ, &wsz) == 0) {
  308. #ifdef DEBUG_WINSZ
  309.         if (firsttime) {
  310.             firsttime = FALSE;
  311.             fprintf(stderr, "ttyio.c screenlines():  ws_row = %d\n",
  312.               wsz.ws_row);
  313.         }
  314. #endif
  315.         /* number of columns = ws_col */
  316.         return (wsz.ws_row > 0)? wsz.ws_row : 24;   /* number of rows */
  317.  
  318.     } else {         /* this happens when piping to more(1), for example */
  319. #ifdef DEBUG_WINSZ
  320.         if (firsttime) {
  321.             firsttime = FALSE;
  322.             fprintf(stderr,
  323.               "ttyio.c screenlines():  ioctl(TIOCGWINSZ) failed\n"));
  324.         }
  325. #endif
  326.         return 24;   /* VT-100 assumed to be minimal hardware */
  327.     }
  328. }
  329.  
  330. #else /* !TIOCGWINSZ: service not available, fall back to semi-bogus method */
  331.  
  332. int screenlines()
  333. {
  334.     char *envptr, *getenv();
  335.     int n;
  336.  
  337.     /* GRR:  this is overly simplistic, but don't have access to stty/gtty
  338.      * system anymore
  339.      */
  340.     envptr = getenv("LINES");
  341.     if (envptr == (char *)NULL || (n = atoi(envptr)) < 5)
  342.         return 24;   /* VT-100 assumed to be minimal hardware */
  343.     else
  344.         return n;
  345. }
  346.  
  347. #endif /* ?TIOCGWINSZ */
  348. #endif /* MORE */
  349.  
  350.  
  351. /***********************************************************************
  352.  * Get a character from the given file descriptor without echo or newline.
  353.  */
  354. int zgetch(__G__ f)
  355.     __GDEF
  356.     int f;                      /* file descriptor from which to read */
  357. {
  358. #if (defined(USE_SYSV_TERMIO) || defined(USE_POSIX_TERMIOS))
  359.     char oldmin, oldtim;
  360. #endif
  361.     char c;
  362.     struct sgttyb sg;           /* tty device structure */
  363.  
  364.     GTTY(f, &sg);               /* get settings */
  365. #if (defined(USE_SYSV_TERMIO) || defined(USE_POSIX_TERMIOS))
  366.     oldmin = sg.c_cc[VMIN];     /* save old values */
  367.     oldtim = sg.c_cc[VTIME];
  368.     sg.c_cc[VMIN] = 1;          /* need only one char to return read() */
  369.     sg.c_cc[VTIME] = 0;         /* no timeout */
  370.     sg.sg_flags &= ~ICANON;     /* canonical mode off */
  371. #else
  372.     sg.sg_flags |= CBREAK;      /* cbreak mode on */
  373. #endif
  374.     sg.sg_flags &= ~ECHO;       /* turn echo off, too */
  375.     STTY(f, &sg);               /* set cbreak mode */
  376.     GLOBAL(echofd) = f;         /* in case ^C hit (not perfect: still CBREAK) */
  377.  
  378.     read(f, &c, 1);             /* read our character */
  379.  
  380. #if (defined(USE_SYSV_TERMIO) || defined(USE_POSIX_TERMIOS))
  381.     sg.c_cc[VMIN] = oldmin;     /* restore old values */
  382.     sg.c_cc[VTIME] = oldtim;
  383.     sg.sg_flags |= ICANON;      /* canonical mode on */
  384. #else
  385.     sg.sg_flags &= ~CBREAK;     /* cbreak mode off */
  386. #endif
  387.     sg.sg_flags |= ECHO;        /* turn echo on */
  388.     STTY(f, &sg);               /* restore canonical mode */
  389.     GLOBAL(echofd) = -1;
  390.  
  391.     return (int)c;
  392. }
  393.  
  394. #else /* !UNIX */
  395.  
  396. int zgetch(__G__ f)
  397.     __GDEF
  398.     int f;    /* file descriptor from which to read (must be open already) */
  399. {
  400.     char c, c2;
  401.  
  402. /*---------------------------------------------------------------------------
  403.     Get a character from the given file descriptor without echo; can't fake
  404.     CBREAK mode (i.e., newline required), but can get rid of all chars up to
  405.     and including newline.
  406.   ---------------------------------------------------------------------------*/
  407.  
  408.     echoff(f);
  409.     read(f, &c, 1);
  410.     if (c != '\n')
  411.         do {
  412.             read(f, &c2, 1);   /* throw away all other chars up thru newline */
  413.         } while (c2 != '\n');
  414.     echon();
  415.     return (int)c;
  416. }
  417.  
  418. #endif /* ?UNIX */
  419.  
  420. #endif /* UNZIP && !FUNZIP */
  421. #endif /* !HAVE_WORKING_GETCH */
  422.  
  423.  
  424. #ifdef CRYPT                    /* getp() is only used with full encryption */
  425.  
  426. /***********************************************************************
  427.  * Get a password of length n-1 or less into *p using the prompt *m.
  428.  * The entered password is not echoed.
  429.  */
  430.  
  431. #ifdef HAVE_WORKING_GETCH
  432. /*
  433.  * For the AMIGA, getch() is defined as Agetch(), which is in
  434.  * amiga/filedate.c; SAS/C 6.x provides a getch(), but since Agetch()
  435.  * uses the infrastructure that is already in place in filedate.c, it is
  436.  * smaller.  With this function, echoff() and echon() are not needed.
  437.  *
  438.  * For the MAC, a non-echo macgetch() function is defined in mac/mac.c,
  439.  * which uses the event handling mechanisme of the desktop window manager
  440.  * to get a character from the keyboard.
  441.  *
  442.  * For the other systems in this section, a non-echo getch() function
  443.  * is either contained the C runtime library (conio package), or getch()
  444.  * is defined as an alias for a similar system specific RTL function.
  445.  */
  446.  
  447. #ifndef MSWIN
  448. /* This is the getp() function for all systems (with TTY type user interface)
  449.  * that supply a working `non-echo' getch() function for "raw" console input.
  450.  */
  451. char *getp(__G__ m, p, n)
  452.     __GDEF
  453.     char *m;                    /* prompt for password */
  454.     char *p;                    /* return value: line input */
  455.     int n;                      /* bytes available in p[] */
  456. {
  457.     char c;                     /* one-byte buffer for read() to use */
  458.     int i;                      /* number of characters input */
  459.     char *w;                    /* warning on retry */
  460.  
  461.     /* get password */
  462.     w = "";
  463.     do {
  464.         fputs(w, stderr);       /* warning if back again */
  465.         fputs(m, stderr);       /* display prompt and flush */
  466.         fflush(stderr);
  467.         i = 0;
  468.         do {                    /* read line, keeping first n characters */
  469.             if ((c = (char)getch()) == '\r')
  470.                 c = '\n';       /* until user hits CR */
  471.             if (c == 8 || c == 127) {
  472.                 if (i > 0) i--; /* the `backspace' and `del' keys works */
  473.             }
  474.             else if (i < n)
  475.                 p[i++] = c;     /* truncate past n */
  476.         } while (c != '\n');
  477.         PUTC('\n', stderr);  fflush(stderr);
  478.         w = "(line too long--try again)\n";
  479.     } while (p[i-1] != '\n');
  480.     p[i-1] = 0;                 /* terminate at newline */
  481.  
  482.     return p;  /* return pointer to password */
  483.  
  484. } /* end function getp() */
  485.  
  486. #else /* MSWIN */
  487.  
  488. char *getp(__G__ m, p, n)
  489.     __GDEF
  490.     char *m;                    /* prompt for password */
  491.     char *p;                    /* return value: line input */
  492.     int n;                      /* bytes available in p[] */
  493. {
  494.     FARPROC lpProcPassword;
  495.     lpumb->lpPassword = lpumb->szPassword;
  496.  
  497.     lpProcPassword = MakeProcInstance(PasswordProc, hInst);
  498.     if (m[0] == ' ')
  499.         lstrcpy(lpumb->szBuffer, "      ");
  500.     else
  501.         wsprintf(lpumb->szBuffer, "%s", "mike");
  502.  
  503.     DialogBoxParam(hInst, "Password", hWndMain, lpProcPassword,
  504.       (DWORD)(LPSTR)G.filename);
  505. #ifndef WIN32
  506.     FreeProcInstance(lpProcPassword);
  507. #endif
  508.     G.key = lpumb->lpPassword;
  509.     p = lpumb->szPassword;
  510.     return p;
  511.  
  512. } /* end function getp() */
  513.  
  514. #endif /* ?MSWIN */
  515.  
  516.  
  517. #else /* !HAVE_WORKING_GETCH */
  518.  
  519.  
  520. #if (defined(UNIX) || defined(__MINT__))
  521.  
  522. #ifndef _PATH_TTY
  523. #  ifdef __MINT__
  524. #    define _PATH_TTY ttyname(2)
  525. #  else
  526. #    define _PATH_TTY "/dev/tty"
  527. #  endif
  528. #endif
  529.  
  530. char *getp(__G__ m, p, n)
  531.     __GDEF
  532.     char *m;                  /* prompt for password */
  533.     char *p;                  /* return value: line input */
  534.     int n;                    /* bytes available in p[] */
  535. {
  536.     char c;                   /* one-byte buffer for read() to use */
  537.     int i;                    /* number of characters input */
  538.     char *w;                  /* warning on retry */
  539.     int f;                    /* file descriptor for tty device */
  540.  
  541. #ifdef PASSWD_FROM_STDIN
  542.     /* Read from stdin. This is unsafe if the password is stored on disk. */
  543.     f = 0;
  544. #else
  545.     /* turn off echo on tty */
  546.  
  547.     if ((f = open(_PATH_TTY, 0)) == -1)
  548.         return NULL;
  549. #endif
  550.     /* get password */
  551.     w = "";
  552.     do {
  553.         fputs(w, stderr);     /* warning if back again */
  554.         fputs(m, stderr);     /* prompt */
  555.         fflush(stderr);
  556.         i = 0;
  557.         echoff(f);
  558.         do {                  /* read line, keeping n */
  559.             read(f, &c, 1);
  560.             if (i < n)
  561.                 p[i++] = c;
  562.         } while (c != '\n');
  563.         echon();
  564.         PUTC('\n', stderr);  fflush(stderr);
  565.         w = "(line too long--try again)\n";
  566.     } while (p[i-1] != '\n');
  567.     p[i-1] = 0;               /* terminate at newline */
  568.  
  569. #ifndef PASSWD_FROM_STDIN
  570.     close(f);
  571. #endif
  572.  
  573.     return p;  /* return pointer to password */
  574.  
  575. } /* end function getp() */
  576.  
  577. #endif /* UNIX || __MINT__ */
  578.  
  579.  
  580.  
  581. #if (defined(VMS) || defined(CMS_MVS))
  582.  
  583. char *getp(__G__ m, p, n)
  584.     __GDEF
  585.     char *m;                  /* prompt for password */
  586.     char *p;                  /* return value: line input */
  587.     int n;                    /* bytes available in p[] */
  588. {
  589.     char c;                   /* one-byte buffer for read() to use */
  590.     int i;                    /* number of characters input */
  591.     char *w;                  /* warning on retry */
  592.     FILE *f;                  /* file structure for SYS$COMMAND device */
  593.  
  594. #ifdef PASSWD_FROM_STDIN
  595.     f = stdin;
  596. #else
  597.     if ((f = fopen(ctermid(NULL), "r")) == NULL)
  598.         return NULL;
  599. #endif
  600.  
  601.     /* get password */
  602.     fflush(stdout);
  603.     w = "";
  604.     do {
  605.         if (*w)               /* bug: VMS adds \n to NULL fputs (apparently) */
  606.             fputs(w, stderr); /* warning if back again */
  607.         fputs(m, stderr);     /* prompt */
  608.         fflush(stderr);
  609.         i = 0;
  610.         echoff(f);
  611.         do {                  /* read line, keeping n */
  612.             if ((c = (char)getc(f)) == '\r')
  613.                 c = '\n';
  614.             if (i < n)
  615.                 p[i++] = c;
  616.         } while (c != '\n');
  617.         echon();
  618.         PUTC('\n', stderr);  fflush(stderr);
  619.         w = "(line too long--try again)\n";
  620.     } while (p[i-1] != '\n');
  621.     p[i-1] = 0;               /* terminate at newline */
  622. #ifndef PASSWD_FROM_STDIN
  623.     fclose(f);
  624. #endif
  625.  
  626.     return p;  /* return pointer to password */
  627.  
  628. } /* end function getp() */
  629.  
  630. #endif /* VMS || CMS_MVS */
  631.  
  632. #endif /* ?HAVE_WORKING_GETCH */
  633. #endif /* CRYPT */
  634.  
  635. #endif /* CRYPT || (UNZIP && !FUNZIP) */
  636.