Audio plugin host https://kx.studio/carla
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

706 lines
21KB

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