Annotation of coherent/b/bin/unzip/file_io.c, revision 1.1

1.1     ! root        1: /*---------------------------------------------------------------------------
        !             2: 
        !             3:   file_io.c
        !             4: 
        !             5:   This file contains routines for doing direct input/output, file-related
        !             6:   sorts of things.  Most of the system-specific code for unzip is contained
        !             7:   here, including the non-echoing password code for decryption (bottom).
        !             8: 
        !             9:   ---------------------------------------------------------------------------*/
        !            10: 
        !            11: 
        !            12: #if (!defined(__GO32__) && !defined(NeXT))
        !            13: #  define const
        !            14: #endif
        !            15: 
        !            16: #define FILE_IO_C
        !            17: #include "unzip.h"
        !            18: 
        !            19: #ifdef  MSWIN
        !            20: #  include "wizunzip.h"
        !            21: #endif
        !            22: 
        !            23: 
        !            24: /************************************/
        !            25: /*  File_IO Local Prototypes, etc.  */
        !            26: /************************************/
        !            27: 
        !            28: #if (!defined(DOS_OS2) || defined(MSWIN))
        !            29:    static int dos2unix __((unsigned char *buf, int len));
        !            30:    int CR_flag = 0;      /* when last char of buffer == CR (for dos2unix()) */
        !            31: #endif
        !            32: 
        !            33: #ifdef OS2
        !            34:    extern int   longname;          /* set in mapname.c */
        !            35:    extern char  longfilename[];
        !            36: #endif
        !            37: 
        !            38: #ifdef CRYPT
        !            39: #  if (defined(DOS_OS2) || defined(VMS))
        !            40: #    define MSVMS
        !            41: #    ifdef DOS_OS2
        !            42: #      ifdef __EMX__
        !            43: #        define getch() _read_kbd(0, 1, 0)
        !            44: #      else
        !            45: #        ifdef __GO32__
        !            46: #          include <pc.h>
        !            47: #          define getch() getkey()
        !            48: #        else /* !__GO32__ */
        !            49: #          include <conio.h>
        !            50: #        endif /* ?__GO32__ */
        !            51: #      endif
        !            52: #    else /* !DOS_OS2 */
        !            53: #      define getch() getc(stderr)
        !            54: #      define OFF 0   /* for echo control */
        !            55: #      define ON 1
        !            56: #      define echoff(f) echo(OFF)
        !            57: #      define echon()   echo(ON)
        !            58: #      include <descrip.h>
        !            59: #      include <iodef.h>
        !            60: #      include <ttdef.h>
        !            61: #      if !defined(SS$_NORMAL)
        !            62: #        define SS$_NORMAL 1   /* only thing we need from <ssdef.h> */
        !            63: #      endif
        !            64: #    endif /* ?DOS_OS2 */
        !            65: #  else /* !(DOS_OS2 || VMS) */
        !            66: #    ifdef TERMIO       /* Amdahl, Cray, all SysV? */
        !            67: #      ifdef CONVEX
        !            68: #        include <sys/termios.h>
        !            69: #        include <sgtty.h>
        !            70: #      else /* !CONVEX */
        !            71: #        ifdef LINUX
        !            72: #          include <termios.h>
        !            73: #        else /* !LINUX */
        !            74: #          include <termio.h>
        !            75: #        endif /* ?LINUX */
        !            76: #        define sgttyb termio
        !            77: #        define sg_flags c_lflag
        !            78: #      endif /* ?CONVEX */
        !            79:        int ioctl OF((int, int, voidp *));
        !            80: #      define GTTY(f,s) ioctl(f,TCGETA,(voidp *)s)
        !            81: #      define STTY(f,s) ioctl(f,TCSETAW,(voidp *)s)
        !            82: #    else /* !TERMIO */
        !            83: #      if (!defined(MINIX) && !defined(__386BSD__))
        !            84: #        include <sys/ioctl.h>
        !            85: #      endif /* !MINIX && !__386BSD__ */
        !            86: #      include <sgtty.h>
        !            87: #      ifdef __386BSD__
        !            88: #        define GTTY(f, s) ioctl(f, TIOCGETP, (voidp *) s)
        !            89: #        define STTY(f, s) ioctl(f, TIOCSETP, (voidp *) s)
        !            90: #      else /* !__386BSD__ */
        !            91: #        define GTTY gtty
        !            92: #        define STTY stty
        !            93:          int gtty OF((int, struct sgttyb *));
        !            94:          int stty OF((int, struct sgttyb *));
        !            95: #      endif /* ?__386BSD__ */
        !            96: #    endif /* ?TERMIO */
        !            97:      int isatty OF((int));
        !            98:      char *ttyname OF((int));
        !            99: #    if (defined(PROTO) && !defined(__GNUC__) && !defined(_AIX))
        !           100:        int open (char *, int, ...);
        !           101: #    endif
        !           102:      int close OF((int));
        !           103:      int read OF((int, voidp *, int));
        !           104: #  endif /* ?(DOS_OS2 || VMS) */
        !           105: #endif /* CRYPT */
        !           106: 
        !           107: 
        !           108: 
        !           109: 
        !           110: 
        !           111: /******************************/
        !           112: /* Function open_input_file() */
        !           113: /******************************/
        !           114: 
        !           115: int open_input_file()    /* return non-zero if open failed */
        !           116: {
        !           117:     /*
        !           118:      *  open the zipfile for reading and in BINARY mode to prevent cr/lf
        !           119:      *  translation, which would corrupt the bitstreams
        !           120:      */
        !           121: 
        !           122: #ifdef VMS
        !           123:     zipfd = open(zipfn, O_RDONLY, 0, "ctx=stm");
        !           124: #else /* !VMS */
        !           125: #ifdef UNIX
        !           126:     zipfd = open(zipfn, O_RDONLY);
        !           127: #else /* !UNIX */
        !           128: #ifdef MACOS
        !           129:     zipfd = open(zipfn, 0);
        !           130: #else /* !MACOS */
        !           131:     zipfd = open(zipfn, O_RDONLY | O_BINARY);
        !           132: #endif /* ?MACOS */
        !           133: #endif /* ?UNIX */
        !           134: #endif /* ?VMS */
        !           135:     if (zipfd < 1) {
        !           136:         fprintf(stderr, "error:  can't open zipfile [ %s ]\n", zipfn);
        !           137:         return (1);
        !           138:     }
        !           139:     return 0;
        !           140: }
        !           141: 
        !           142: 
        !           143: 
        !           144: 
        !           145: 
        !           146: /**********************/
        !           147: /* Function readbuf() */
        !           148: /**********************/
        !           149: 
        !           150: int readbuf(buf, size)
        !           151:     char *buf;
        !           152:     register unsigned size;
        !           153: {                               /* return number of bytes read into buf */
        !           154:     register int count;
        !           155:     int n;
        !           156: 
        !           157:     n = size;
        !           158:     while (size) {
        !           159:         if (incnt == 0) {
        !           160:             if ((incnt = read(zipfd, (char *)inbuf, INBUFSIZ)) <= 0)
        !           161:                 return (n-size);
        !           162:             /* buffer ALWAYS starts on a block boundary:  */
        !           163:             cur_zipfile_bufstart += INBUFSIZ;
        !           164:             inptr = inbuf;
        !           165:         }
        !           166:         count = MIN(size, (unsigned)incnt);
        !           167:         memcpy(buf, inptr, count);
        !           168:         buf += count;
        !           169:         inptr += count;
        !           170:         incnt -= count;
        !           171:         size -= count;
        !           172:     }
        !           173:     return (n);
        !           174: }
        !           175: 
        !           176: 
        !           177: 
        !           178: 
        !           179: 
        !           180: #ifndef VMS   /* for VMS use code in vms.c (old VMS code below is retained
        !           181:                * in case of problems...will be removed in a later release) */
        !           182: 
        !           183: /*********************************/
        !           184: /* Function create_output_file() */
        !           185: /*********************************/
        !           186: 
        !           187: int create_output_file()         /* return non-0 if creat failed */
        !           188: {
        !           189: /*---------------------------------------------------------------------------
        !           190:     Create the output file with appropriate permissions.  If we've gotten to
        !           191:     this point and the file still exists, we have permission to blow it away.
        !           192:   ---------------------------------------------------------------------------*/
        !           193: 
        !           194: #if (!defined(DOS_OS2) || defined(MSWIN))
        !           195:     CR_flag = 0;   /* hack to get CR at end of buffer working */
        !           196: #endif
        !           197: 
        !           198: #if (defined(UNIX) && !defined(AMIGA))
        !           199:     {
        !           200:         int mask;
        !           201: 
        !           202: #ifndef VMS
        !           203:         if (!stat(filename, &statbuf) && (unlink(filename) < 0)) {
        !           204:             fprintf(stderr, "\n%s:  cannot delete old copy\n", filename);
        !           205:             return 1;
        !           206:         }
        !           207: #       define EXTRA_ARGS
        !           208: #else /* VMS */
        !           209: #       define EXTRA_ARGS   ,"rfm=stmlf","rat=cr"
        !           210: #endif /* ?VMS */
        !           211: 
        !           212:         mask = umask(0);   /* now know that we own it */
        !           213:         outfd = creat(filename, 0xffff & pInfo->unix_attr  EXTRA_ARGS);
        !           214:         umask(mask);                                            /* VMS, Unix */
        !           215:     }
        !           216: #else /* !UNIX || AMIGA */  /* file permissions set after file closed */
        !           217: #ifndef MACOS
        !           218:     outfd = creat(filename, S_IWRITE | S_IREAD);     /* DOS, OS2, Mac, Amiga */
        !           219: #else /* MACOS */
        !           220:     {
        !           221:         short fDataFork=TRUE;
        !           222:         MACINFO mi;
        !           223:         OSErr err;
        !           224: 
        !           225:         fMacZipped = FALSE;
        !           226:         CtoPstr(filename);
        !           227:         if (extra_field &&
        !           228:             (lrec.extra_field_length > sizeof(MACINFOMIN)) &&
        !           229:             (lrec.extra_field_length <= sizeof(MACINFO))) {
        !           230:             BlockMove(extra_field, &mi, lrec.extra_field_length);
        !           231:             if ((makeword((byte *)&mi.header) == 1992) &&
        !           232:                 (makeword((byte *)&mi.data) ==
        !           233:                   lrec.extra_field_length-sizeof(ZIP_EXTRA_HEADER)) &&
        !           234:                 (mi.signature == 'JLEE')) {
        !           235:                 gostCreator = mi.finfo.fdCreator;
        !           236:                 gostType = mi.finfo.fdType;
        !           237:                 fDataFork = (mi.flags & 1) ? TRUE : FALSE;
        !           238:                 fMacZipped = true;
        !           239:                 /* If it was Zipped w/Mac version, the filename has either */
        !           240:                 /* a 'd' or 'r' appended.  Remove the d/r when unzipping */
        !           241:                 filename[0]-=1;
        !           242:             }
        !           243:         }
        !           244:         if (!fMacZipped) {
        !           245:             if (!aflag)
        !           246:                 gostType = gostCreator = '\?\?\?\?';
        !           247:             else {
        !           248: #ifdef THINK_C
        !           249:                 gostCreator = 'KAHL';
        !           250: #else
        !           251: #ifdef MCH_MACINTOSH
        !           252:                 gostCreator = 'Manx';
        !           253: #else
        !           254:                 gostCreator = 'MPS ';
        !           255: #endif
        !           256: #endif
        !           257:                 gostType = 'TEXT';
        !           258:             }
        !           259:         }
        !           260:         PtoCstr(filename);
        !           261: 
        !           262:         outfd = creat(filename, 0);
        !           263:         if (fMacZipped) {
        !           264:             CtoPstr(filename);
        !           265:             if (hfsflag) {
        !           266:                 HParamBlockRec   hpbr;
        !           267:     
        !           268:                 hpbr.fileParam.ioNamePtr = (StringPtr)filename;
        !           269:                 hpbr.fileParam.ioVRefNum = gnVRefNum;
        !           270:                 hpbr.fileParam.ioDirID = glDirID;
        !           271:                 hpbr.fileParam.ioFlFndrInfo = mi.finfo;
        !           272:                 hpbr.fileParam.ioFlCrDat = mi.lCrDat;
        !           273:                 hpbr.fileParam.ioFlMdDat = mi.lMdDat;
        !           274:                 err = PBHSetFInfo(&hpbr, 0);
        !           275:             } else {
        !           276:                 err = SetFInfo((StringPtr)filename , 0, &mi.finfo);
        !           277:             }
        !           278:             PtoCstr(filename);
        !           279:         }
        !           280:         if (outfd != -1)
        !           281:             outfd = open(filename, (fDataFork)? 1 : 2);
        !           282:     }
        !           283: #endif /* ?MACOS */
        !           284: #endif /* ?(UNIX && !AMIGA) */
        !           285: 
        !           286:     if (outfd < 1) {
        !           287:         fprintf(stderr, "\n%s:  cannot create\n", filename);
        !           288:         return 1;
        !           289:     }
        !           290: 
        !           291: /*---------------------------------------------------------------------------
        !           292:     If newly created file is in text mode and should be binary (to disable
        !           293:     automatic CR/LF translations), either close it and reopen as binary or
        !           294:     else change the mode to binary (DOS, OS/2).
        !           295:   ---------------------------------------------------------------------------*/
        !           296: 
        !           297: #if (!defined(UNIX) && !defined(MACOS))
        !           298:     if (!aflag) {
        !           299: #ifdef DOS_OS2
        !           300:         if (setmode(outfd, O_BINARY) == -1) {
        !           301: #else /* !DOS_OS2 */
        !           302:         close(outfd);
        !           303:         if ((outfd = open(filename, O_RDWR | O_BINARY)) < 1) {
        !           304: #endif /* ?DOS_OS2 */
        !           305:             fprintf(stderr, "Can't make output file binary:  %s\n", filename);
        !           306:             return 1;
        !           307:         }
        !           308:     }
        !           309: #endif /* !UNIX && !MACOS */
        !           310: 
        !           311:     return 0;
        !           312: }
        !           313: 
        !           314: #endif /* !VMS */
        !           315: 
        !           316: 
        !           317: 
        !           318: 
        !           319: 
        !           320: /****************************/
        !           321: /* Function FillBitBuffer() */
        !           322: /****************************/
        !           323: 
        !           324: int FillBitBuffer()
        !           325: {
        !           326:     /*
        !           327:      * Fill bitbuf, which is 32 bits.  This function is only used by the
        !           328:      * READBIT and PEEKBIT macros (which are used by all of the uncompression
        !           329:      * routines).
        !           330:      */
        !           331:     UWORD temp;
        !           332: 
        !           333:     zipeof = 1;
        !           334:     while (bits_left < 25 && ReadByte(&temp) == 8)
        !           335:     {
        !           336:       bitbuf |= (ULONG)temp << bits_left;
        !           337:       bits_left += 8;
        !           338:       zipeof = 0;
        !           339:     }
        !           340:     return 0;
        !           341: }
        !           342: 
        !           343: 
        !           344: 
        !           345: 
        !           346: 
        !           347: /***********************/
        !           348: /* Function ReadByte() */
        !           349: /***********************/
        !           350: 
        !           351: int ReadByte(x)
        !           352:     UWORD *x;
        !           353: {
        !           354:     /*
        !           355:      * read a byte; return 8 if byte available, 0 if not
        !           356:      */
        !           357: 
        !           358:     if (mem_mode)
        !           359:         return ReadMemoryByte(x);
        !           360: 
        !           361:     if (csize-- <= 0)
        !           362:         return 0;
        !           363: 
        !           364:     if (incnt == 0) {
        !           365:         if ((incnt = read(zipfd, (char *)inbuf, INBUFSIZ)) <= 0)
        !           366:             return 0;
        !           367:         /* buffer ALWAYS starts on a block boundary:  */
        !           368:         cur_zipfile_bufstart += INBUFSIZ;
        !           369:         inptr = inbuf;
        !           370: #ifdef CRYPT
        !           371:         if (pInfo->encrypted) {
        !           372:             byte *p;
        !           373:             int n, t;
        !           374: 
        !           375:             for (n = (longint)incnt > csize + 1 ? (int)csize + 1 : incnt,
        !           376:                  p = inptr; n--; p++)
        !           377:                 *p = (byte) DECRYPT(*p);
        !           378:         }
        !           379: #endif /* CRYPT */
        !           380:     }
        !           381:     *x = *inptr++;
        !           382:     --incnt;
        !           383:     return 8;
        !           384: }
        !           385: 
        !           386: 
        !           387: 
        !           388: 
        !           389: 
        !           390: #ifndef VMS   /* for VMS use code in vms.c */
        !           391: 
        !           392: /**************************/
        !           393: /* Function FlushOutput() */
        !           394: /**************************/
        !           395: 
        !           396: int FlushOutput()
        !           397: {
        !           398:     /*
        !           399:      * flush contents of output buffer; return PK-type error code
        !           400:      */
        !           401: #if (!defined(DOS_OS2) || defined(MSWIN))
        !           402:     int saved_ctrlZ = FALSE;
        !           403: #endif
        !           404:     int len;
        !           405: 
        !           406: 
        !           407:     if (mem_mode) {
        !           408:         int rc = FlushMemory();
        !           409:         outpos += outcnt;
        !           410:         outcnt = 0;
        !           411:         outptr = outbuf;
        !           412:         return rc;
        !           413:     }
        !           414: 
        !           415:     if (disk_full) {
        !           416:         outpos += outcnt;   /* fake emptied buffer */
        !           417:         outcnt = 0;
        !           418:         outptr = outbuf;
        !           419:         return 50;          /* ignore rest of this file */
        !           420:     }
        !           421: 
        !           422:     if (outcnt) {
        !           423:         UpdateCRC(outbuf, outcnt);
        !           424: 
        !           425:         if (!tflag) {
        !           426: #if (!defined(DOS_OS2) || defined(MSWIN))
        !           427:             if (aflag) {
        !           428:                 if (outbuf[outcnt-1] == CTRLZ) {
        !           429:                     --outcnt;
        !           430:                     saved_ctrlZ = TRUE;
        !           431:                 }
        !           432:                 len = dos2unix(outbuf, outcnt);
        !           433:             } else
        !           434: #endif /* !DOS_OS2 || MSWIN */
        !           435:                 len = outcnt;
        !           436: #ifdef MACOS
        !           437:             if ((giCursor+1) >> 2 != (giCursor>>2))
        !           438:                 SetCursor( *rghCursor[((giCursor+1)>>2)&0x03] );
        !           439:             giCursor = (giCursor+1) & 15;
        !           440: #endif /* MACOS */
        !           441: #ifdef MSWIN
        !           442:             /* if writing to console vs. actual file, write to Msg Window */
        !           443:             if (cflag)
        !           444:                 WriteBufferToMsgWin(outout, len, FALSE);
        !           445:             else if (_lwrite(outfd, outout, len) != (UINT)len)
        !           446: #else /* !MSWIN */
        !           447:             if (write(outfd, (char *)outout, len) != len)
        !           448: #endif /* ?MSWIN */
        !           449: #ifdef DOS_OS2
        !           450:                 if (!cflag)           /* ^Z treated as EOF, removed with -c */
        !           451: #else /* !DOS_OS2 */
        !           452: #ifdef MINIX
        !           453:                 if (errno == EFBIG)
        !           454:                     if (write(fd, outout, len/2) != len/2  ||
        !           455:                         write(fd, outout+len/2, len/2) != len/2)
        !           456: #endif /* MINIX */
        !           457: #endif /* ?DOS_OS2 */
        !           458:                 {
        !           459:                     /* GRR: add test for force_flag when has its own switch */
        !           460:                     fprintf(stderr,
        !           461:                       "\n%s:  write error (disk full?).  Continue? (y/n/^C) ",
        !           462:                       filename);
        !           463:                     FFLUSH   /* for Amiga and Mac MPW */
        !           464: #ifdef MSWIN
        !           465:                     disk_full = 2;
        !           466: #else /* !MSWIN */
        !           467:                     fgets(answerbuf, 9, stdin);
        !           468:                     if (*answerbuf == 'y')   /* stop writing to this file */
        !           469:                         disk_full = 1;       /*  (outfd bad?), but new OK */
        !           470:                     else
        !           471:                         disk_full = 2;       /* no:  exit program */
        !           472: #endif /* ?MSWIN */
        !           473:                     return 50;    /* 50:  disk full */
        !           474:                 }
        !           475:         }
        !           476:         outpos += outcnt;
        !           477:         outcnt = 0;
        !           478:         outptr = outbuf;
        !           479: #if (!defined(DOS_OS2) || defined(MSWIN))
        !           480:         if (saved_ctrlZ) {
        !           481:             *outptr++ = CTRLZ;
        !           482:             ++outcnt;
        !           483:         }
        !           484: #endif /* !DOS_OS2 || MSWIN */
        !           485:     }
        !           486:     return 0;                   /* 0:  no error */
        !           487: }
        !           488: 
        !           489: #endif /* !VMS */
        !           490: 
        !           491: 
        !           492: 
        !           493: 
        !           494: 
        !           495: #if (!defined(DOS_OS2) || defined(MSWIN))
        !           496: 
        !           497: /***********************/
        !           498: /* Function dos2unix() */
        !           499: /***********************/
        !           500: 
        !           501: static int dos2unix(buf, len)   /* GRR:  rewrite for generic text conversions */
        !           502:     unsigned char *buf;
        !           503:     int len;
        !           504: {
        !           505:     int new_len;
        !           506:     int i;
        !           507: #ifdef MSWIN
        !           508:     unsigned char __far *walker;
        !           509: #else /* !MSWIN */
        !           510:     unsigned char *walker;
        !           511: #endif /* ?MSWIN */
        !           512: 
        !           513:     new_len = len;
        !           514:     walker = outout;
        !           515: #ifdef MACOS
        !           516:     /*
        !           517:      * Mac wants to strip LFs instead CRs from CRLF pairs
        !           518:      */
        !           519:     if (CR_flag && *buf == LF) {
        !           520:         buf++;
        !           521:         new_len--;
        !           522:         len--;
        !           523:         CR_flag = buf[len] == CR;
        !           524:     }
        !           525:     else
        !           526:         CR_flag = buf[len - 1] == CR;
        !           527:     for (i = 0; i < len; i += 1) {
        !           528:         *walker++ = ascii_to_native(*buf);
        !           529:         if (*buf == LF) walker[-1] = CR;
        !           530:         if (*buf++ == CR && *buf == LF) {
        !           531:             new_len--;
        !           532:             buf++;
        !           533:             i++;
        !           534:         }
        !           535:     }
        !           536: #else /* !MACOS */
        !           537:     if (CR_flag && *buf != LF)
        !           538:         *walker++ = ascii_to_native(CR);
        !           539:     CR_flag = buf[len - 1] == CR;
        !           540:     for (i = 0; i < len; i += 1) {
        !           541:         *walker++ = ascii_to_native(*buf);
        !           542:         if (*buf++ == CR && *buf == LF) {
        !           543:             new_len--;
        !           544:             walker[-1] = ascii_to_native(*buf++);
        !           545:             i++;
        !           546:         }
        !           547:     }
        !           548:     /*
        !           549:      * If the last character is a CR, then "ignore it" for now...
        !           550:      */
        !           551:     if (walker[-1] == ascii_to_native(CR))
        !           552:         new_len--;
        !           553: #endif /* ?MACOS */
        !           554:     return new_len;
        !           555: }
        !           556: 
        !           557: #endif /* !DOS_OS2 || MSWIN */
        !           558: 
        !           559: 
        !           560: 
        !           561: 
        !           562: 
        !           563: #ifdef __GO32__
        !           564: 
        !           565: void _dos_setftime(int fd, UWORD dosdate, UWORD dostime)
        !           566: {
        !           567:     asm("pushl %ebx");
        !           568:     asm("movl %0, %%ebx": : "g" (fd));
        !           569:     asm("movl %0, %%ecx": : "g" (dostime));
        !           570:     asm("movl %0, %%edx": : "g" (dosdate));
        !           571:     asm("movl $0x5701, %eax");
        !           572:     asm("int $0x21");
        !           573:     asm("popl %ebx");
        !           574: }
        !           575: 
        !           576: void _dos_setfileattr(char *name, int attr)
        !           577: {
        !           578:     asm("movl %0, %%edx": : "g" (name));
        !           579:     asm("movl %0, %%ecx": : "g" (attr));
        !           580:     asm("movl $0x4301, %eax");
        !           581:     asm("int $0x21");
        !           582: }
        !           583: 
        !           584: #endif /* __GO32__ */
        !           585: 
        !           586: 
        !           587: 
        !           588: 
        !           589: 
        !           590: #ifdef DOS_OS2
        !           591: 
        !           592: /**************************************/
        !           593: /* Function set_file_time_and_close() */
        !           594: /**************************************/
        !           595: 
        !           596: void set_file_time_and_close()
        !           597:  /*
        !           598:   * MS-DOS AND OS/2 VERSION (Mac, Unix/VMS versions are below)
        !           599:   *
        !           600:   * Set the output file date/time stamp according to information from the
        !           601:   * zipfile directory record for this member, then close the file and set
        !           602:   * its permissions (archive, hidden, read-only, system).  Aside from closing
        !           603:   * the file, this routine is optional (but most compilers support it).
        !           604:   */
        !           605: {
        !           606: /*---------------------------------------------------------------------------
        !           607:     Allocate local variables needed by OS/2 and Turbo C.
        !           608:   ---------------------------------------------------------------------------*/
        !           609: 
        !           610: #ifdef __TURBOC__
        !           611: 
        !           612:     union {
        !           613:         struct ftime ft;        /* system file time record */
        !           614:         struct {
        !           615:             UWORD ztime;        /* date and time words */
        !           616:             UWORD zdate;        /* .. same format as in .ZIP file */
        !           617:         } zt;
        !           618:     } td;
        !           619: 
        !           620: #endif                          /* __TURBOC__ */
        !           621: 
        !           622: /*---------------------------------------------------------------------------
        !           623:      Do not attempt to set the time stamp on standard output.
        !           624:   ---------------------------------------------------------------------------*/
        !           625: 
        !           626:     if (cflag) {
        !           627:         close(outfd);
        !           628:         return;
        !           629:     }
        !           630: 
        !           631: /*---------------------------------------------------------------------------
        !           632:     Copy and/or convert time and date variables, if necessary; then set the
        !           633:     file time/date.
        !           634:   ---------------------------------------------------------------------------*/
        !           635: 
        !           636: #ifndef OS2
        !           637: #ifdef __TURBOC__
        !           638:     td.zt.ztime = lrec.last_mod_file_time;
        !           639:     td.zt.zdate = lrec.last_mod_file_date;
        !           640:     setftime(outfd, &td.ft);
        !           641: #else /* !__TURBOC__ */
        !           642: #ifdef WIN32
        !           643:     {
        !           644:         FILETIME ft;     /* 64-bit value made up of two 32 bit [low & high] */
        !           645:         WORD wDOSDate;   /* for vconvertin from DOS date to Windows NT */
        !           646:         WORD wDOSTime;
        !           647:         HANDLE hFile;    /* file handle (defined in Windows NT) */
        !           648: 
        !           649:         wDOSTime = (WORD) lrec.last_mod_file_time;
        !           650:         wDOSDate = (WORD) lrec.last_mod_file_date;
        !           651: 
        !           652:         /* The DosDateTimeToFileTime() function converts a DOS date/time
        !           653:          * into a 64 bit Windows NT file time */
        !           654:         DosDateTimeToFileTime(wDOSDate, wDOSTime, &ft);
        !           655: 
        !           656:         /* Close the file and then re-open it using the Win32
        !           657:          * CreateFile call, so that the file can be created
        !           658:          * with GENERIC_WRITE access, otherwise the SetFileTime
        !           659:          * call will fail. */
        !           660:         close(outfd);
        !           661: 
        !           662:         hFile = CreateFile(filename, GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
        !           663:              FILE_ATTRIBUTE_NORMAL, NULL);
        !           664: 
        !           665:         if (!SetFileTime(hFile, NULL, NULL, &ft))
        !           666:             printf("\nSetFileTime failed: %d\n", GetLastError());
        !           667:         CloseHandle(hFile);
        !           668:         return;
        !           669:     }
        !           670: #else /* !WIN32 */
        !           671:     _dos_setftime(outfd, lrec.last_mod_file_date, lrec.last_mod_file_time);
        !           672: #endif /* ?WIN32 */
        !           673: #endif /* ?__TURBOC__ */
        !           674: #endif /* ?OS2 */
        !           675: 
        !           676: /*---------------------------------------------------------------------------
        !           677:     And finally we can close the file...at least everybody agrees on how to
        !           678:     do *this*.  I think...  Oh yeah, also change the mode according to the
        !           679:     stored file attributes, since we didn't do that when we opened the dude.
        !           680:   ---------------------------------------------------------------------------*/
        !           681: 
        !           682:     close(outfd);
        !           683: 
        !           684: #ifdef OS2
        !           685:     SetPathInfo(filename, lrec.last_mod_file_date,
        !           686:                           lrec.last_mod_file_time, pInfo->dos_attr);
        !           687:     if (extra_field)
        !           688:         SetEAs(filename, extra_field);
        !           689:     if (longname)
        !           690:         SetLongNameEA(filename, longfilename);
        !           691: #else /* !OS2 */
        !           692: #ifdef __TURBOC__
        !           693:     if (_chmod(filename, 1, pInfo->dos_attr) != pInfo->dos_attr)
        !           694:         fprintf(stderr, "\nwarning:  file attributes may not be correct\n");
        !           695: #else /* !__TURBOC__ */
        !           696: #ifdef WIN32
        !           697:     /* Attempt to set the file attributes.  SetFileAttributes returns
        !           698:      * FALSE (0) if unsucessful, in which case print an error message,
        !           699:      * with error value returned from GetLastError call. */
        !           700:     pInfo->dos_attr = pInfo->dos_attr & 0x7F;
        !           701: 
        !           702:     if (!(SetFileAttributes(filename, pInfo->dos_attr)))
        !           703:         fprintf(stderr, "\nwarning (%d): could not set file attributes\n",
        !           704:           GetLastError());
        !           705: #else /* !WIN32 */
        !           706:     _dos_setfileattr(filename, pInfo->dos_attr);
        !           707: #endif /* ?WIN32 */
        !           708: #endif /* ?__TURBOC__ */
        !           709: #endif /* ?OS2 */
        !           710: 
        !           711: } /* end function set_file_time_and_close() (DOS, OS/2) */
        !           712: 
        !           713: 
        !           714: 
        !           715: 
        !           716: 
        !           717: #else                           /* !DOS_OS2 */
        !           718: #ifdef MACOS                    /* Mac */
        !           719: 
        !           720: /**************************************/
        !           721: /* Function set_file_time_and_close() */
        !           722: /**************************************/
        !           723: 
        !           724: void set_file_time_and_close()
        !           725:  /*
        !           726:   * MAC VERSION
        !           727:   */
        !           728: {
        !           729:     long m_time;
        !           730:     DateTimeRec dtr;
        !           731:     ParamBlockRec pbr;
        !           732:     HParamBlockRec hpbr;
        !           733:     OSErr err;
        !           734: 
        !           735:     if (outfd != 1) {
        !           736:         close(outfd);
        !           737: 
        !           738:         /*
        !           739:          * Macintosh bases all file modification times on the number of seconds
        !           740:          * elapsed since Jan 1, 1904, 00:00:00.  Therefore, to maintain
        !           741:          * compatibility with MS-DOS archives, which date from Jan 1, 1980,
        !           742:          * with NO relation to GMT, the following conversions must be made:
        !           743:          *      the Year (yr) must be incremented by 1980;
        !           744:          *      and converted to seconds using the Mac routine Date2Secs(),
        !           745:          *      almost similar in complexity to the Unix version :-)
        !           746:          *                                     J. Lee
        !           747:          */
        !           748: 
        !           749:         dtr.year = (((lrec.last_mod_file_date >> 9) & 0x7f) + 1980);
        !           750:         dtr.month = ((lrec.last_mod_file_date >> 5) & 0x0f);
        !           751:         dtr.day = (lrec.last_mod_file_date & 0x1f);
        !           752: 
        !           753:         dtr.hour = ((lrec.last_mod_file_time >> 11) & 0x1f);
        !           754:         dtr.minute = ((lrec.last_mod_file_time >> 5) & 0x3f);
        !           755:         dtr.second = ((lrec.last_mod_file_time & 0x1f) * 2);
        !           756: 
        !           757:         Date2Secs(&dtr, (unsigned long *)&m_time);
        !           758:         CtoPstr(filename);
        !           759:         if (hfsflag) {
        !           760:             hpbr.fileParam.ioNamePtr = (StringPtr)filename;
        !           761:             hpbr.fileParam.ioVRefNum = gnVRefNum;
        !           762:             hpbr.fileParam.ioDirID = glDirID;
        !           763:             hpbr.fileParam.ioFDirIndex = 0;
        !           764:             err = PBHGetFInfo(&hpbr, 0L);
        !           765:             hpbr.fileParam.ioFlMdDat = m_time;
        !           766:             if ( !fMacZipped )
        !           767:                 hpbr.fileParam.ioFlCrDat = m_time;
        !           768:             hpbr.fileParam.ioDirID = glDirID;
        !           769:             if (err == noErr)
        !           770:                 err = PBHSetFInfo(&hpbr, 0L);
        !           771:             if (err != noErr)
        !           772:                 printf("error:  can't set the time for %s\n", filename);
        !           773:         } else {
        !           774:             pbr.fileParam.ioNamePtr = (StringPtr)filename;
        !           775:             pbr.fileParam.ioVRefNum = pbr.fileParam.ioFVersNum =
        !           776:               pbr.fileParam.ioFDirIndex = 0;
        !           777:             err = PBGetFInfo(&pbr, 0L);
        !           778:             pbr.fileParam.ioFlMdDat = pbr.fileParam.ioFlCrDat = m_time;
        !           779:             if (err == noErr)
        !           780:                 err = PBSetFInfo(&pbr, 0L);
        !           781:             if (err != noErr)
        !           782:                 printf("error:  can't set the time for %s\n", filename);
        !           783:         }
        !           784: 
        !           785:         /* set read-only perms if needed */
        !           786:         if ((err == noErr) && !(pInfo->unix_attr & S_IWRITE)) {
        !           787:             if (hfsflag) {
        !           788:                 hpbr.fileParam.ioNamePtr = (StringPtr)filename;
        !           789:                 hpbr.fileParam.ioVRefNum = gnVRefNum;
        !           790:                 hpbr.fileParam.ioDirID = glDirID;
        !           791:                 err = PBHSetFLock(&hpbr, 0);
        !           792:             } else
        !           793:                 err = SetFLock((ConstStr255Param)filename, 0);
        !           794:         }
        !           795:         PtoCstr(filename);
        !           796:     }
        !           797: }
        !           798: 
        !           799: 
        !           800: 
        !           801: 
        !           802: 
        !           803: #else /* !MACOS... */
        !           804: #if (!defined(MTS) && !defined(VMS))   /* && !MTS (can't do) && !VMS: only one
        !           805:                                   * left is UNIX (for VMS use code in vms.c) */
        !           806: 
        !           807: /**************************************/
        !           808: /* Function set_file_time_and_close() */
        !           809: /**************************************/
        !           810: 
        !           811: void set_file_time_and_close()
        !           812:  /*
        !           813:   * UNIX VERSION (MS-DOS & OS/2, Mac versions are above)
        !           814:   */
        !           815: {
        !           816:     static short yday[]={0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
        !           817:     long m_time;
        !           818:     int yr, mo, dy, hh, mm, ss, leap, days=0;
        !           819:     struct utimbuf {
        !           820:         time_t actime;          /* new access time */
        !           821:         time_t modtime;         /* new modification time */
        !           822:     } tp;
        !           823: #ifdef AMIGA
        !           824: #   define YRBASE  1978         /* in AmigaDos, counting begins 01-Jan-1978 */
        !           825:     struct DateStamp myadate;
        !           826: /*  extern char *_TZ;   no longer used? */
        !           827: #else /* !AMIGA */
        !           828: #   define YRBASE  1970
        !           829: #ifdef BSD
        !           830: #ifndef __386BSD__
        !           831:     static struct timeb tbp;
        !           832: #endif /* !__386BSD__ */
        !           833: #else /* !BSD */
        !           834:     extern long timezone;
        !           835: #endif /* ?BSD */
        !           836: #endif /* ?AMIGA */
        !           837: 
        !           838: 
        !           839:     /*
        !           840:      * Close the file *before* setting its time under Unix and AmigaDos.
        !           841:      */
        !           842: #ifdef AMIGA
        !           843:     if (cflag)                  /* can't set time on stdout */
        !           844:         return;
        !           845:     close(outfd);
        !           846: #else /* !AMIGA */
        !           847:     close(outfd);
        !           848:     if (cflag)                  /* can't set time on stdout */
        !           849:         return;
        !           850: #endif /* ?AMIGA */
        !           851: 
        !           852:     /*
        !           853:      * These date conversions look a little weird, so I'll explain.
        !           854:      * UNIX bases all file modification times on the number of seconds
        !           855:      * elapsed since Jan 1, 1970, 00:00:00 GMT.  Therefore, to maintain
        !           856:      * compatibility with MS-DOS archives, which date from Jan 1, 1980,
        !           857:      * with NO relation to GMT, the following conversions must be made:
        !           858:      *      the Year (yr) must be incremented by 10;
        !           859:      *      the Date (dy) must be decremented by 1;
        !           860:      *      and the whole mess must be adjusted by TWO factors:
        !           861:      *          relationship to GMT (ie.,Pacific Time adds 8 hrs.),
        !           862:      *          and whether or not it is Daylight Savings Time.
        !           863:      * Also, the usual conversions must take place to account for leap years,
        !           864:      * etc.
        !           865:      *                                     C. Seaman
        !           866:      */
        !           867: 
        !           868:     /* dissect date */
        !           869:     yr = ((lrec.last_mod_file_date >> 9) & 0x7f) + (1980 - YRBASE);
        !           870:     mo = ((lrec.last_mod_file_date >> 5) & 0x0f) - 1;
        !           871:     dy = (lrec.last_mod_file_date & 0x1f) - 1;
        !           872: 
        !           873:     /* dissect time */
        !           874:     hh = (lrec.last_mod_file_time >> 11) & 0x1f;
        !           875:     mm = (lrec.last_mod_file_time >> 5) & 0x3f;
        !           876:     ss = (lrec.last_mod_file_time & 0x1f) * 2;
        !           877: 
        !           878:     /* leap = # of leap years from BASE up to but not including current year */
        !           879:     leap = ((yr + YRBASE - 1) / 4);   /* leap year base factor */
        !           880: 
        !           881:     /* How many days from BASE to this year? (& add expired days this year) */
        !           882:     days = (yr * 365) + (leap - 492) + yday[mo];
        !           883: 
        !           884:     /* if year is a leap year and month is after February, add another day */
        !           885:     if ((mo > 1) && ((yr+YRBASE)%4 == 0) && ((yr+YRBASE) != 2100))
        !           886:         ++days;                 /* OK through 2199 */
        !           887: 
        !           888: #ifdef AMIGA
        !           889: /*  _TZ = getenv("TZ"); does Amiga not have TZ and tzset() after all? */
        !           890:     myadate.ds_Days   =   days+dy-2;   /* off by one? */
        !           891:     myadate.ds_Minute =   hh*60+mm;
        !           892:     myadate.ds_Tick   =   ss*TICKS_PER_SECOND;
        !           893: 
        !           894:     if (!(SetFileDate(filename, &myadate)))
        !           895:         fprintf(stderr, "error:  can't set the time for %s\n", filename);
        !           896: 
        !           897: #else /* !AMIGA */
        !           898:     /* convert date & time to seconds relative to 00:00:00, 01/01/YRBASE */
        !           899:     m_time = ((days + dy) * 86400) + (hh * 3600) + (mm * 60) + ss;
        !           900: 
        !           901: #ifdef BSD
        !           902: #ifndef __386BSD__
        !           903:     ftime(&tbp);
        !           904:     m_time += tbp.timezone * 60L;
        !           905: #endif
        !           906: /* #elif WIN32
        !           907:  * don't do anything right now (esp. since "elif" is not legal for old cc's */
        !           908: #else /* !BSD */
        !           909:     tzset();                    /* set `timezone' */
        !           910:     m_time += timezone;         /* account for timezone differences */
        !           911: #endif /* ?BSD */
        !           912: 
        !           913: #ifdef __386BSD__
        !           914:     m_time += localtime(&m_time)->tm_gmtoff;
        !           915: #else
        !           916:     if (localtime(&m_time)->tm_isdst)
        !           917:         m_time -= 60L * 60L;    /* adjust for daylight savings time */
        !           918: #endif
        !           919: 
        !           920:     tp.actime = m_time;         /* set access time */
        !           921:     tp.modtime = m_time;        /* set modification time */
        !           922: 
        !           923:     /* set the time stamp on the file */
        !           924:     if (utime(filename, &tp))
        !           925:         fprintf(stderr, "error:  can't set the time for %s\n", filename);
        !           926: #endif /* ?AMIGA */
        !           927: }
        !           928: 
        !           929: #endif /* !MTS && !VMS */
        !           930: #endif /* ?MACOS */
        !           931: #endif /* ?DOS_OS2 */
        !           932: 
        !           933: 
        !           934: 
        !           935: 
        !           936: 
        !           937: /************************/
        !           938: /*  Function handler()  */
        !           939: /************************/
        !           940: 
        !           941: void handler(signal)   /* upon interrupt, turn on echo and exit cleanly */
        !           942:     int signal;
        !           943: {
        !           944: #if (defined(SIGBUS) || defined(SIGSEGV))
        !           945:     static char *corrupt = "error:  zipfile probably corrupt\n";
        !           946: #endif
        !           947: 
        !           948: #ifndef DOS_OS2
        !           949: #ifdef CRYPT
        !           950:     echon();
        !           951: #endif /* CRYPT */
        !           952:     putc('\n', stderr);
        !           953: #endif /* !DOS_OS2 */
        !           954: #ifdef SIGBUS
        !           955:     if (signal == SIGBUS) {
        !           956:         fprintf(stderr, corrupt);
        !           957:         exit(3);
        !           958:     }
        !           959: #endif /* SIGBUS */
        !           960: #ifdef SIGSEGV
        !           961:     if (signal == SIGSEGV) {
        !           962:         fprintf(stderr, corrupt);
        !           963:         exit(3);
        !           964:     }
        !           965: #endif /* SIGSEGV */
        !           966:     exit(0);
        !           967: }
        !           968: 
        !           969: 
        !           970: 
        !           971: 
        !           972: 
        !           973: /*******************************/
        !           974: /*  Non-echoing password code  */
        !           975: /*******************************/
        !           976: 
        !           977: #ifdef CRYPT
        !           978: #ifndef DOS_OS2
        !           979: #ifdef VMS
        !           980: 
        !           981: int echo(opt)
        !           982:     int opt;
        !           983: {
        !           984: /*---------------------------------------------------------------------------
        !           985:     Based on VMSmunch.c, which in turn was based on Joe Meadows' file.c code.
        !           986:   ---------------------------------------------------------------------------
        !           987:      * For VMS v5.x:
        !           988:      *   IO$_SENSEMODE/SETMODE info:  Programming, Vol. 7A, System Programming,
        !           989:      *     I/O User's: Part I, sec. 8.4.1.1, 8.4.3, 8.4.5, 8.6
        !           990:      *   sys$assign(), sys$qio() info:  Programming, Vol. 4B, System Services,
        !           991:      *     System Services Reference Manual, pp. sys-23, sys-379
        !           992:      *   fixed-length descriptor info:  Programming, Vol. 3, System Services,
        !           993:      *     Intro to System Routines, sec. 2.9.2
        !           994:      * GRR, 15 Aug 91
        !           995:   ---------------------------------------------------------------------------*/
        !           996:     static struct dsc$descriptor_s DevDesc =
        !           997:         {9, DSC$K_DTYPE_T, DSC$K_CLASS_S, "SYS$INPUT"};
        !           998:      /* {dsc$w_length, dsc$b_dtype, dsc$b_class, dsc$a_pointer}; */
        !           999:     static short           DevChan, iosb[4];
        !          1000:     static long            i, status;
        !          1001:     static unsigned long   oldmode[2], newmode[2];   /* each = 8 bytes */
        !          1002:   
        !          1003: 
        !          1004: /*---------------------------------------------------------------------------
        !          1005:     Assign a channel to standard input.
        !          1006:   ---------------------------------------------------------------------------*/
        !          1007: 
        !          1008:     status = sys$assign(&DevDesc, &DevChan, 0, 0);
        !          1009:     if (!(status & 1))
        !          1010:         return status;
        !          1011: 
        !          1012: /*---------------------------------------------------------------------------
        !          1013:     Use sys$qio and the IO$_SENSEMODE function to determine the current tty
        !          1014:     status (for password reading, could use IO$_READVBLK function instead,
        !          1015:     but echo on/off will be more general).
        !          1016:   ---------------------------------------------------------------------------*/
        !          1017: 
        !          1018:     status = sys$qio(0, DevChan, IO$_SENSEMODE, &iosb, 0, 0,
        !          1019:                      oldmode, 8, 0, 0, 0, 0);
        !          1020:     if (!(status & 1))
        !          1021:         return status;
        !          1022:     status = iosb[0];
        !          1023:     if (!(status & 1))
        !          1024:         return status;
        !          1025: 
        !          1026: /*---------------------------------------------------------------------------
        !          1027:     Copy old mode into new-mode buffer, then modify to be either NOECHO or
        !          1028:     ECHO (depending on function argument opt).
        !          1029:   ---------------------------------------------------------------------------*/
        !          1030: 
        !          1031:     newmode[0] = oldmode[0];
        !          1032:     newmode[1] = oldmode[1];
        !          1033:     if (opt == OFF)
        !          1034:         newmode[1] |= TT$M_NOECHO;                      /* set NOECHO bit */
        !          1035:     else
        !          1036:         newmode[1] &= ~((unsigned long) TT$M_NOECHO);   /* clear NOECHO bit */
        !          1037: 
        !          1038: /*---------------------------------------------------------------------------
        !          1039:     Use the IO$_SETMODE function to change the tty status.
        !          1040:   ---------------------------------------------------------------------------*/
        !          1041: 
        !          1042:     status = sys$qio(0, DevChan, IO$_SETMODE, &iosb, 0, 0,
        !          1043:                      newmode, 8, 0, 0, 0, 0);
        !          1044:     if (!(status & 1))
        !          1045:         return status;
        !          1046:     status = iosb[0];
        !          1047:     if (!(status & 1))
        !          1048:         return status;
        !          1049: 
        !          1050: /*---------------------------------------------------------------------------
        !          1051:     Deassign the sys$input channel by way of clean-up, then exit happily.
        !          1052:   ---------------------------------------------------------------------------*/
        !          1053: 
        !          1054:     status = sys$dassgn(DevChan);
        !          1055:     if (!(status & 1))
        !          1056:         return status;
        !          1057: 
        !          1058:     return SS$_NORMAL;   /* we be happy */
        !          1059: 
        !          1060: } /* end function echo() */
        !          1061: 
        !          1062: 
        !          1063: 
        !          1064: 
        !          1065: 
        !          1066: #else /* !VMS */
        !          1067: 
        !          1068: static int echofd=(-1);       /* file descriptor whose echo is off */
        !          1069: 
        !          1070: void echoff(f)
        !          1071:     int f;                    /* file descriptor for which to turn echo off */
        !          1072: /* Turn echo off for file descriptor f.  Assumes that f is a tty device. */
        !          1073: {
        !          1074:     struct sgttyb sg;         /* tty device structure */
        !          1075: 
        !          1076:     echofd = f;
        !          1077:     GTTY(f, &sg);             /* get settings */
        !          1078:     sg.sg_flags &= ~ECHO;     /* turn echo off */
        !          1079:     STTY(f, &sg);
        !          1080: }
        !          1081: 
        !          1082: 
        !          1083: 
        !          1084: void echon()
        !          1085: /* Turn echo back on for file descriptor echofd. */
        !          1086: {
        !          1087:     struct sgttyb sg;         /* tty device structure */
        !          1088: 
        !          1089:     if (echofd != -1) {
        !          1090:         GTTY(echofd, &sg);    /* get settings */
        !          1091:         sg.sg_flags |= ECHO;  /* turn echo on */
        !          1092:         STTY(echofd, &sg);
        !          1093:         echofd = -1;
        !          1094:     }
        !          1095: }
        !          1096: 
        !          1097: #endif /* ?VMS */
        !          1098: #endif /* !DOS_OS2 */
        !          1099: 
        !          1100: 
        !          1101: 
        !          1102: 
        !          1103: 
        !          1104: char *getp(m, p, n)
        !          1105:     char *m;                  /* prompt for password */
        !          1106:     char *p;                  /* return value: line input */
        !          1107:     int n;                    /* bytes available in p[] */
        !          1108: /* Get a password of length n-1 or less into *p using the prompt *m.
        !          1109:    The entered password is not echoed.  Return p on success, NULL on
        !          1110:    failure (can't get controlling tty). */
        !          1111: {
        !          1112:     char c;                   /* one-byte buffer for read() to use */
        !          1113:     int i;                    /* number of characters input */
        !          1114:     char *w;                  /* warning on retry */
        !          1115: 
        !          1116: #ifndef DOS_OS2
        !          1117: #ifndef VMS
        !          1118:     int f;                    /* file decsriptor for tty device */
        !          1119: 
        !          1120:     /* turn off echo on tty */
        !          1121:     if (!isatty(2))
        !          1122:         return NULL;          /* error if not tty */
        !          1123:     if ((f = open(ttyname(2), 0, 0)) == -1)
        !          1124:         return NULL;
        !          1125: #endif /* !VMS */
        !          1126:     echoff(f);                /* turn echo off */
        !          1127: #endif /* !DOS_OS2 */
        !          1128: 
        !          1129:     /* get password */
        !          1130:     w = "";
        !          1131:     do {
        !          1132: #ifdef VMS   /* bug:  VMS adds '\n' to NULL fputs (apparently) */
        !          1133:         if (*w)
        !          1134: #endif /* VMS */
        !          1135:             fputs(w, stderr); /* warning if back again */
        !          1136:         fputs(m, stderr);     /* prompt */
        !          1137:         fflush(stderr);
        !          1138:         i = 0;
        !          1139:         do {                  /* read line, keeping n */
        !          1140: #ifdef MSVMS
        !          1141:             if ((c = (char)getch()) == '\r')
        !          1142:                 c = '\n';
        !          1143: #else /* !MSVMS */
        !          1144:             read(f, &c, 1);
        !          1145: #endif /* ?MSVMS */
        !          1146:             if (i < n)
        !          1147:                 p[i++] = c;
        !          1148:         } while (c != '\n');
        !          1149:         putc('\n', stderr);  fflush(stderr);
        !          1150:         w = "(line too long--try again)\n";
        !          1151:     } while (p[i-1] != '\n');
        !          1152:     p[i-1] = 0;               /* terminate at newline */
        !          1153: 
        !          1154: #ifndef DOS_OS2
        !          1155:     echon();                  /* turn echo back on */
        !          1156: #ifndef VMS
        !          1157:     close(f);
        !          1158: #endif /* !VMS */
        !          1159: #endif /* !DOS_OS2 */
        !          1160: 
        !          1161:     /* return pointer to password */
        !          1162:     return p;
        !          1163: }
        !          1164: 
        !          1165: #endif /* CRYPT */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.