Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
6725 | siemargl | 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 |
||
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 |
||
118 | # include |
||
119 | # include |
||
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 |
||
126 | # include |
||
127 | # else /* !VMS */ |
||
128 | # ifdef HAVE_TERMIOS_H |
||
129 | # include |
||
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 |
||
138 | # endif |
||
139 | # ifdef HAVE_SYS_TERMIO_H |
||
140 | # include |
||
141 | # endif |
||
142 | # ifdef NEED_PTEM |
||
143 | # include |
||
144 | # include |
||
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 |
||
154 | # endif |
||
155 | # include |
||
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 |
||
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) */>>>>>>> |