]>
git.saurik.com Git - wxWidgets.git/blob - utils/Install/sfxzip/ttyio.c
1 /*---------------------------------------------------------------------------
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.
10 Contains: echo() (VMS only)
13 screenlines() (Unix only)
14 zgetch() (Unix and non-Unix versions)
15 getp() ("PC," Unix/Atari/Be, VMS/VMCMS/MVS)
17 ---------------------------------------------------------------------------*/
19 #define __TTYIO_C /* identifies this source module */
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.)
37 # ifdef GLOBAL /* used in Amiga system headers, maybe others too */
42 # define GLOBAL(g) G.g
45 #ifdef __BEOS__ /* why yes, we do */
46 # define HAVE_TERMIOS_H
50 # ifndef USE_POSIX_TERMIOS
51 # define USE_POSIX_TERMIOS /* use POSIX style termio (termios) */
53 # ifndef HAVE_TERMIOS_H
54 # define HAVE_TERMIOS_H /* POSIX termios.h */
56 #endif /* _POSIX_VERSION */
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
65 # ifndef HAVE_TERMIO_H
66 # define HAVE_TERMIO_H
68 # ifdef HAVE_SYS_TERMIO_H
69 # undef HAVE_SYS_TERMIO_H
71 # else /* !COHERENT */
75 # ifndef HAVE_SYS_TERMIO_H
76 # define HAVE_SYS_TERMIO_H
78 # endif /* ?COHERENT */
79 # endif /* (SYSV || CRAY) && !__MINT__ */
80 # endif /* !_POSIX_VERSION */
81 # if !(defined(BSD4_4) || defined(SYSV) || defined(__convexc__))
85 # endif /* !(BSD4_4 || SYSV || __convexc__) */
89 # ifndef USE_POSIX_TERMIOS
90 # define USE_POSIX_TERMIOS
94 #if (defined(HAVE_TERMIO_H) || defined(HAVE_SYS_TERMIO_H))
95 # ifndef USE_SYSV_TERMIO
96 # define USE_SYSV_TERMIO
100 #if (defined(UNZIP) && !defined(FUNZIP) && defined(UNIX) && defined(MORE))
101 # include <sys/ioctl.h>
103 /* int ioctl OF((int, int, zvoid *)); GRR: may need for some systems */
106 #ifndef HAVE_WORKING_GETCH
107 /* include system support for switching of console echo */
109 # include <descrip.h>
112 # include <starlet.h>
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
126 # ifdef HAVE_SYS_TERMIO_H
127 # include <sys/termio.h>
130 # include <sys/stream.h>
131 # include <sys/ptem.h>
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 */
139 # if (!defined(MINIX) && !defined(GOT_IOCTL_H))
140 # include <sys/ioctl.h>
147 * XXX : Are these declarations needed at all ????
150 * GRR: let's find out... Hmmm, appears not...
151 int gtty OF((int, struct sgttyb *));
152 int stty OF((int, struct sgttyb *));
155 # endif /* !CMS_MVS */
156 # endif /* ?USE_SYSV_TERMIO */
157 # endif /* ?HAVE_TERMIOS_H */
163 char *ttyname
OF((int));
166 #endif /* !HAVE_WORKING_GETCH */
170 #ifndef HAVE_WORKING_GETCH
174 * Turn keyboard echoing on or off (VMS). Loosely based on VMSmunch.c
175 * and hence on Joe Meadows' file.c code.
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
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];
197 static unsigned long oldmode
[2], newmode
[2]; /* each = 8 bytes */
200 /* assign a channel to standard input */
201 status
= sys$
assign(&DevDesc
, &DevChan
, 0, 0);
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)
209 status
= sys$
qiow(0, DevChan
, IO$_SENSEMODE
, &iosb
, 0, 0,
210 oldmode
, 8, 0, 0, 0, 0);
217 /* copy old mode into new-mode buffer, then modify to be either NOECHO or
218 * ECHO (depending on function argument opt)
220 newmode
[0] = oldmode
[0];
221 newmode
[1] = oldmode
[1];
222 if (opt
== 0) /* off */
223 newmode
[1] |= TT$M_NOECHO
; /* set NOECHO bit */
225 newmode
[1] &= ~((unsigned long) TT$M_NOECHO
); /* clear NOECHO bit */
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);
236 /* deassign the sys$input channel by way of clean-up */
237 status
= sys$
dassgn(DevChan
);
241 return SS$_NORMAL
; /* we be happy */
243 } /* end function echo() */
246 #else /* !VMS: basically Unix */
249 /* For VM/CMS and MVS, non-echo terminal input is not (yet?) supported. */
252 #ifdef ZIP /* moved to globals.h for UnZip */
253 static int echofd
=(-1); /* file descriptor whose echo is off */
257 * Turn echo off for file descriptor f. Assumes that f is a tty device.
261 int f
; /* file descriptor for which to turn echo off */
263 struct sgttyb sg
; /* tty device structure */
266 GTTY(f
, &sg
); /* get settings */
267 sg
.sg_flags
&= ~ECHO
; /* turn echo off */
272 * Turn echo back on for file descriptor echofd.
277 struct sgttyb sg
; /* tty device structure */
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
);
287 #endif /* !CMS_MVS */
291 #if (defined(UNZIP) && !defined(FUNZIP))
293 #if (defined(UNIX) || defined(__BEOS__))
297 * Get the number of lines on the output terminal. SCO Unix apparently
298 * defines TIOCGWINSZ but doesn't support it (!M_UNIX).
300 * GRR: will need to know width of terminal someday, too, to account for
304 #if (defined(TIOCGWINSZ) && !defined(M_UNIX))
310 static int firsttime
= TRUE
;
313 /* see termio(4) under, e.g., SunOS */
314 if (ioctl(1, TIOCGWINSZ
, &wsz
) == 0) {
318 fprintf(stderr
, "ttyio.c screenlines(): ws_row = %d\n",
322 /* number of columns = ws_col */
323 return (wsz
.ws_row
> 0)? wsz
.ws_row
: 24; /* number of rows */
325 } else { /* this happens when piping to more(1), for example */
330 "ttyio.c screenlines(): ioctl(TIOCGWINSZ) failed\n"));
333 return 24; /* VT-100 assumed to be minimal hardware */
337 #else /* !TIOCGWINSZ: service not available, fall back to semi-bogus method */
341 char *envptr
, *getenv();
344 /* GRR: this is overly simplistic, but don't have access to stty/gtty
347 envptr
= getenv("LINES");
348 if (envptr
== (char *)NULL
|| (n
= atoi(envptr
)) < 5)
349 return 24; /* VT-100 assumed to be minimal hardware */
354 #endif /* ?(TIOCGWINSZ && !M_UNIX) */
359 * Get a character from the given file descriptor without echo or newline.
363 int f
; /* file descriptor from which to read */
365 #if (defined(USE_SYSV_TERMIO) || defined(USE_POSIX_TERMIOS))
369 struct sgttyb sg
; /* tty device structure */
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 */
379 sg
.sg_flags
|= CBREAK
; /* cbreak mode on */
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) */
385 read(f
, &c
, 1); /* read our character */
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 */
392 sg
.sg_flags
&= ~CBREAK
; /* cbreak mode off */
394 sg
.sg_flags
|= ECHO
; /* turn echo on */
395 STTY(f
, &sg
); /* restore canonical mode */
402 #else /* !UNIX && !__BEOS__ */
407 int f
; /* file descriptor from which to read (must be open already) */
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 ---------------------------------------------------------------------------*/
421 read(f
, &c2
, 1); /* throw away all other chars up thru newline */
422 } while (c2
!= '\n');
427 #endif /* ?(UNIX || __BEOS__) */
429 #endif /* UNZIP && !FUNZIP */
430 #endif /* !HAVE_WORKING_GETCH */
433 #if CRYPT /* getp() is only used with full encryption */
436 * Simple compile-time check for source compatibility between
439 #if (!defined(CR_MAJORVER) || (CR_MAJORVER < 2) || (CR_MINORVER < 7))
440 error
: This Info
-ZIP tool
requires zcrypt
2.7 or later
.
444 * Get a password of length n-1 or less into *p using the prompt *m.
445 * The entered password is not echoed.
448 #ifdef HAVE_WORKING_GETCH
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.
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.
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.
464 #ifndef WINDLL /* WINDLL does not support a console interface */
465 #ifndef QDOS /* QDOS supplies a variant of this function */
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.
470 char *getp(__G__ m
, p
, n
)
472 ZCONST
char *m
; /* prompt for password */
473 char *p
; /* return value: line input */
474 int n
; /* bytes available in p[] */
476 char c
; /* one-byte buffer for read() to use */
477 int i
; /* number of characters input */
478 char *w
; /* warning on retry */
483 fputs(w
, stderr
); /* warning if back again */
484 fputs(m
, stderr
); /* display prompt and flush */
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 */
494 p
[i
++] = c
; /* truncate past 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 */
501 return p
; /* return pointer to password */
503 } /* end function getp() */
509 #else /* !HAVE_WORKING_GETCH */
512 #if (defined(UNIX) || defined(__MINT__) || defined(__BEOS__))
516 # define _PATH_TTY ttyname(2)
518 # define _PATH_TTY "/dev/tty"
522 char *getp(__G__ m
, p
, n
)
524 ZCONST
char *m
; /* prompt for password */
525 char *p
; /* return value: line input */
526 int n
; /* bytes available in p[] */
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 */
533 #ifdef PASSWD_FROM_STDIN
534 /* Read from stdin. This is unsafe if the password is stored on disk. */
537 /* turn off echo on tty */
539 if ((f
= open(_PATH_TTY
, 0)) == -1)
545 fputs(w
, stderr
); /* warning if back again */
546 fputs(m
, stderr
); /* prompt */
550 do { /* read line, keeping n */
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 */
561 #ifndef PASSWD_FROM_STDIN
565 return p
; /* return pointer to password */
567 } /* end function getp() */
569 #endif /* UNIX || __MINT__ || __BEOS__ */
573 #if (defined(VMS) || defined(CMS_MVS))
575 char *getp(__G__ m
, p
, n
)
577 ZCONST
char *m
; /* prompt for password */
578 char *p
; /* return value: line input */
579 int n
; /* bytes available in p[] */
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 */
586 #ifdef PASSWD_FROM_STDIN
589 if ((f
= fopen(ctermid(NULL
), "r")) == NULL
)
597 if (*w
) /* bug: VMS apparently adds \n to NULL fputs */
598 fputs(w
, stderr
); /* warning if back again */
599 fputs(m
, stderr
); /* prompt */
603 do { /* read line, keeping n */
604 if ((c
= (char)getc(f
)) == '\r')
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
618 return p
; /* return pointer to password */
620 } /* end function getp() */
622 #endif /* VMS || CMS_MVS */
623 #endif /* ?HAVE_WORKING_GETCH */
625 #endif /* CRYPT || (UNZIP && !FUNZIP) */