Subversion Repositories Kolibri OS

Rev

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) */