home *** CD-ROM | disk | FTP | other *** search
/ Actor 12 / actor.v12.1994.iso / files / win / winnt / unzipnt.arj / FILE_IO.C < prev    next >
C/C++ Source or Header  |  1992-03-23  |  32KB  |  1,072 lines

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