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