home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 9 Archive / 09-Archive.zip / unzip52.zip / fileio.c < prev    next >
C/C++ Source or Header  |  1996-04-25  |  49KB  |  1,585 lines

  1. /*---------------------------------------------------------------------------
  2.  
  3.   fileio.c
  4.  
  5.   This file contains routines for doing direct but relatively generic input/
  6.   output, file-related sorts of things, plus some miscellaneous stuff.  Most
  7.   of the stuff has to do with opening, closing, reading and/or writing files.
  8.  
  9.   Contains:  open_input_file()
  10.              open_outfile()           (non-VMS, non-AOS/VS, non-CMS_MVS)
  11.              undefer_input()
  12.              defer_leftover_input()
  13.              readbuf()
  14.              readbyte()
  15.              fillinbuf()
  16.              flush()                  (non-VMS)
  17.              disk_error()             (non-VMS)
  18.              UzpMessagePrnt()
  19.              UzpMessageNull()         (DLL only)
  20.              UzpInput()
  21.              UzpMorePause()
  22.              handler()
  23.              dos_to_unix_time()       (non-VMS, non-OS/2, non-VM/CMS, non-MVS)
  24.              check_for_newer()        (non-VMS, non-OS/2, non-VM/CMS, non-MVS)
  25.              do_string()
  26.              makeword()
  27.              makelong()
  28.              memset()                 (ZMEM only)
  29.              memcpy()                 (ZMEM only)
  30.              zstrnicmp()
  31.              zstat()                  (REGULUS only)
  32.              fLoadFarString()         (SMALL_MEM only)
  33.              fLoadFarStringSmall()    (SMALL_MEM only)
  34.              fLoadFarStringSmall2()   (SMALL_MEM only)
  35.              zfstrcpy()               (SMALL_MEM only)
  36.  
  37.   ---------------------------------------------------------------------------*/
  38.  
  39.  
  40. #define FILEIO_C
  41. #define UNZIP_INTERNAL
  42. #include "unzip.h"
  43. #include "crypt.h"
  44. #include "ttyio.h"
  45. #include "ebcdic.h"   /* definition/initialization of ebcdic[] */
  46.  
  47.  
  48. /*
  49.    Note: Under Windows, the maximum size of the buffer that can be used
  50.    with any of the *printf calls is 16,384, so win_fprintf was used to
  51.    feed the fprintf clone no more than 16K chunks at a time. This should
  52.    be valid for anything up to 64K (and probably beyond, assuming your
  53.    buffers are that big.)
  54. */
  55. #ifdef MSWIN
  56. #  define WriteError(buf,len,strm) \
  57.    ((extent)win_fprintf(strm, (extent)len, (char *)buf) != (extent)(len))
  58. #else
  59. #  ifdef USE_FWRITE
  60. #    define WriteError(buf,len,strm) \
  61.      ((extent)fwrite((char *)(buf),1,(extent)(len),strm) != (extent)(len))
  62. #  else
  63. #    define WriteError(buf,len,strm) \
  64.      ((extent)write(fileno(strm),(char *)(buf),(extent)(len)) != (extent)(len))
  65. #  endif
  66. #endif /* ?MSWIN */
  67.  
  68. static int disk_error OF((__GPRO));
  69.  
  70. #ifdef MSWIN
  71.    extern int win_fprintf(FILE *file, unsigned int, char *);
  72. #endif
  73.  
  74.  
  75.  
  76. /****************************/
  77. /* Strings used in fileio.c */
  78. /****************************/
  79.  
  80. #ifdef UNIX
  81.    static char Far CannotDeleteOldFile[] = "error:  cannot delete old %s\n";
  82. #endif
  83.  
  84. static char Far CantOpenZipfile[] = "error:  can't open zipfile [ %s ]\n";
  85. #if (!defined(VMS) && !defined(AOS_VS) && !defined(CMS_MVS))
  86.    static char Far CannotCreateFile[] = "error:  cannot create %s\n";
  87. #endif
  88. #ifdef NOVELL_BUG_FAILSAFE
  89.    static char Far NovellBug[] =
  90.      "error:  %s: stat() says does not exist, but fopen() found anyway\n";
  91. #endif
  92. static char Far ReadError[] = "error:  zipfile read error\n";
  93. static char Far DiskFullQuery[] =
  94.   "\n%s:  write error (disk full?).  Continue? (y/n/^C) ";
  95. static char Far ZipfileCorrupt[] = "error:  zipfile probably corrupt (%s)\n";
  96. static char Far FilenameTooLongTrunc[] =
  97.   "warning:  filename too long--truncating.\n";
  98. static char Far ExtraFieldTooLong[] =
  99.   "warning:  extra field too long (%d).  Ignoring...\n";
  100.  
  101. #ifndef MSWIN
  102. #  ifdef MORE
  103.      static char Far MorePrompt[] = "--More--(%lu)";
  104. #  endif
  105.    static char Far QuitPrompt[] =
  106.      "--- Press `Q' to quit, or any other key to continue ---";
  107.    static char Far HidePrompt[] = /* "\r                       \r"; */
  108.      "\r                                                         \r";
  109. #endif /* !MSWIN */
  110.  
  111.  
  112.  
  113.  
  114.  
  115. /******************************/
  116. /* Function open_input_file() */
  117. /******************************/
  118.  
  119. int open_input_file(__G)    /* return 1 if open failed */
  120.     __GDEF
  121. {
  122.     /*
  123.      *  open the zipfile for reading and in BINARY mode to prevent cr/lf
  124.      *  translation, which would corrupt the bitstreams
  125.      */
  126.  
  127. #if (defined(UNIX) || defined(TOPS20) || defined(AOS_VS))
  128.     G.zipfd = open(G.zipfn, O_RDONLY);
  129. #else /* !(UNIX || TOPS20 || AOS_VS) */
  130. #ifdef VMS
  131.     G.zipfd = open(G.zipfn, O_RDONLY, 0, "ctx=stm");
  132. #else /* !VMS */
  133. #ifdef MACOS
  134.     G.zipfd = open(G.zipfn, 0);
  135. #else /* !MACOS */
  136. #ifdef RISCOS
  137.     G.zipfd = fopen(G.zipfn, "rb");
  138. #else /* !RISCOS */
  139. #ifdef CMS_MVS
  140.     G.zipfd = vmmvs_open_infile(__G);
  141. #else /* !CMS_MVS */
  142.     G.zipfd = open(G.zipfn, O_RDONLY | O_BINARY);
  143. #endif /* ?CMS_MVS */
  144. #endif /* ?RISCOS */
  145. #endif /* ?MACOS */
  146. #endif /* ?VMS */
  147. #endif /* ?(UNIX || TOPS20 || AOS_VS) */
  148.  
  149. #ifdef USE_STRM_INPUT
  150.     if (G.zipfd == NULL)
  151. #else
  152.     if (G.zipfd < 0)
  153. #endif
  154.     {
  155.         Info(slide, 0x401, ((char *)slide, LoadFarString(CantOpenZipfile),
  156.           G.zipfn));
  157.         return 1;
  158.     }
  159.     return 0;
  160.  
  161. } /* end function open_input_file() */
  162.  
  163.  
  164.  
  165.  
  166. #if (!defined(VMS) && !defined(AOS_VS) && !defined(CMS_MVS))
  167.  
  168. /***************************/
  169. /* Function open_outfile() */
  170. /***************************/
  171.  
  172. int open_outfile(__G)         /* return 1 if fail */
  173.     __GDEF
  174. {
  175. #ifdef DLL
  176.     if (G.redirect_data)
  177.         return redirect_outfile(__G)==FALSE;
  178. #endif
  179. #ifdef DOS_OS2_W32
  180.     if (stat(G.filename, &G.statbuf) == 0) {
  181.         Trace((stderr, "open_outfile:  stat(%s) returns 0 (file exists)\n",
  182.           G.filename));
  183.         if (!(G.statbuf.st_mode & S_IWRITE)) {
  184.             Trace((stderr, "open_outfile:  existing file %s is read-only\n",
  185.               G.filename));
  186.             chmod(G.filename, S_IREAD | S_IWRITE);
  187.             Trace((stderr, "open_outfile:  %s now writable\n", G.filename));
  188.         }
  189.         if (unlink(G.filename) != 0)
  190.             return 1;
  191.         Trace((stderr, "open_outfile:  %s now deleted\n", G.filename));
  192.     }
  193. #endif /* DOS_OS2_W32 */
  194. #ifdef UNIX
  195.     if (stat(G.filename, &G.statbuf) == 0 && unlink(G.filename) < 0) {
  196.         Info(slide, 0x401, ((char *)slide, LoadFarString(CannotDeleteOldFile),
  197.           G.filename));
  198.         return 1;
  199.     }
  200. #endif /* UNIX */
  201. #ifdef RISCOS
  202.     if (SWI_OS_File_7(G.filename,0xDEADDEAD,0xDEADDEAD,G.lrec.ucsize)!=NULL) {
  203.         Info(slide, 1, ((char *)slide, LoadFarString(CannotCreateFile),
  204.           G.filename));
  205.         return 1;
  206.     }
  207. #endif /* RISCOS */
  208. #ifdef TOPS20
  209.     char *tfilnam;
  210.  
  211.     if ((tfilnam = (char *)malloc(2*strlen(G.filename)+1)) == (char *)NULL)
  212.         return 1;
  213.     strcpy(tfilnam, G.filename);
  214.     upper(tfilnam);
  215.     enquote(tfilnam);
  216.     if ((G.outfile = fopen(tfilnam, FOPW)) == (FILE *)NULL) {
  217.         Info(slide, 1, ((char *)slide, LoadFarString(CannotCreateFile),
  218.           tfilnam));
  219.         free(tfilnam);
  220.         return 1;
  221.     }
  222.     free(tfilnam);
  223. #else /* !TOPS20 */
  224. #ifdef MTS
  225.     if (G.aflag)
  226.         G.outfile = fopen(G.filename, FOPWT);
  227.     else
  228.         G.outfile = fopen(G.filename, FOPW);
  229.     if (G.outfile == (FILE *)NULL) {
  230.         Info(slide, 1, ((char *)slide, LoadFarString(CannotCreateFile),
  231.           G.filename));
  232.         return 1;
  233.     }
  234. #else /* !MTS */
  235. #ifdef DEBUG
  236.     Info(slide, 1, ((char *)slide,
  237.       "open_outfile:  doing fopen(%s) for reading\n", G.filename));
  238.     if ((G.outfile = fopen(G.filename, FOPR)) == (FILE *)NULL)
  239.         Info(slide, 1, ((char *)slide,
  240.           "open_outfile:  fopen(%s) for reading failed:  does not exist\n",
  241.           G.filename));
  242.     else {
  243.         Info(slide, 1, ((char *)slide,
  244.           "open_outfile:  fopen(%s) for reading succeeded:  file exists\n",
  245.           G.filename));
  246.         fclose(G.outfile);
  247.     }
  248. #endif /* DEBUG */
  249. #ifdef NOVELL_BUG_FAILSAFE
  250.     if (G.dne && ((G.outfile = fopen(G.filename, FOPR)) != (FILE *)NULL)) {
  251.         Info(slide, 0x401, ((char *)slide, LoadFarString(NovellBug),
  252.           G.filename));
  253.         fclose(G.outfile);
  254.         return 1;   /* with "./" fix in checkdir(), should never reach here */
  255.     }
  256. #endif /* NOVELL_BUG_FAILSAFE */
  257.     Trace((stderr, "open_outfile:  doing fopen(%s) for writing\n", G.filename));
  258.     if ((G.outfile = fopen(G.filename, FOPW)) == (FILE *)NULL) {
  259.         Info(slide, 0x401, ((char *)slide, LoadFarString(CannotCreateFile),
  260.           G.filename));
  261.         return 1;
  262.     }
  263.     Trace((stderr, "open_outfile:  fopen(%s) for writing succeeded\n",
  264.       G.filename));
  265. #endif /* !MTS */
  266. #endif /* !TOPS20 */
  267.  
  268. #if 0      /* this SUCKS!  on Ultrix, it must be writing a byte at a time... */
  269.     setbuf(G.outfile, (char *)NULL);   /* make output unbuffered */
  270. #endif
  271.  
  272. #ifdef USE_FWRITE
  273. #ifdef DOS_OS2_W32
  274.     /* 16-bit MSC: buffer size must be strictly LESS than 32K (WSIZE):  bogus */
  275.     setbuf(G.outfile, (char *)NULL);   /* make output unbuffered */
  276. #else /* !DOS_OS2_W32 */
  277. #ifndef RISCOS
  278. #ifdef _IOFBF  /* make output fully buffered (works just about like write()) */
  279.     setvbuf(G.outfile, (char *)slide, _IOFBF, WSIZE);
  280. #else
  281.     setbuf(G.outfile, (char *)slide);
  282. #endif
  283. #endif /* !RISCOS */
  284. #endif /* ?DOS_OS2_W32 */
  285. #endif /* USE_FWRITE */
  286.     return 0;
  287.  
  288. } /* end function open_outfile() */
  289.  
  290. #endif /* !VMS && !AOS_VS && !CMS_MVS */
  291.  
  292.  
  293.  
  294.  
  295.  
  296. /*
  297.  * These functions allow NEXTBYTE to function without needing two bounds
  298.  * checks.  Call defer_leftover_input() if you ever have filled G.inbuf
  299.  * by some means other than readbyte(), and you then want to start using
  300.  * NEXTBYTE.  When going back to processing bytes without NEXTBYTE, call
  301.  * undefer_input().  For example, extract_or_test_member brackets its
  302.  * central section that does the decompression with these two functions.
  303.  * If you need to check the number of bytes remaining in the current
  304.  * file while using NEXTBYTE, check (G.csize + G.incnt), not G.csize.
  305.  */
  306.  
  307. /****************************/
  308. /* function undefer_input() */
  309. /****************************/
  310.  
  311. void undefer_input(__G)
  312.     __GDEF
  313. {
  314.     if (G.incnt > 0)
  315.         G.csize += G.incnt;
  316.     if (G.incnt_leftover > 0) {
  317.         /* We know that "(G.csize < MAXINT)" so we can cast G.csize to int:
  318.          * This condition was checked when G.incnt_leftover was set > 0 in
  319.          * defer_leftover_input(), and it is NOT allowed to touch G.csize
  320.          * before calling undefer_input() when (G.incnt_leftover > 0)
  321.          * (single exception: see read_byte()'s  "G.csize <= 0" handling) !!
  322.          */
  323.         G.incnt = G.incnt_leftover + (int)G.csize;
  324.         G.inptr = G.inptr_leftover - (int)G.csize;
  325.         G.incnt_leftover = 0;
  326.     } else if (G.incnt < 0)
  327.         G.incnt = 0;
  328. } /* end function undefer_input() */
  329.  
  330.  
  331.  
  332.  
  333.  
  334. /***********************************/
  335. /* function defer_leftover_input() */
  336. /***********************************/
  337.  
  338. void defer_leftover_input(__G)
  339.     __GDEF
  340. {
  341.     if ((long)G.incnt > G.csize) {
  342.         /* (G.csize < MAXINT), we can safely cast it to int !! */
  343.         if (G.csize < 0L)
  344.             G.csize = 0L;
  345.         G.inptr_leftover = G.inptr + (int)G.csize;
  346.         G.incnt_leftover = G.incnt - (int)G.csize;
  347.         G.incnt = (int)G.csize;
  348.     } else
  349.         G.incnt_leftover = 0;
  350.     G.csize -= G.incnt;
  351. } /* end function defer_leftover_input() */
  352.  
  353.  
  354.  
  355.  
  356.  
  357. /**********************/
  358. /* Function readbuf() */
  359. /**********************/
  360.  
  361. unsigned readbuf(__G__ buf, size)   /* return number of bytes read into buf */
  362.     __GDEF
  363.     char *buf;
  364.     register unsigned size;
  365. {
  366.     register unsigned count;
  367.     unsigned n;
  368.  
  369.     n = size;
  370.     while (size) {
  371.         if (G.incnt <= 0) {
  372.             if ((G.incnt = read(G.zipfd, (char *)G.inbuf, INBUFSIZ)) == 0)
  373.                 return (n-size);
  374.             else if (G.incnt < 0) {
  375.                 /* another hack, but no real harm copying same thing twice */
  376.                 (*G.message)((zvoid *)&G,
  377.                   (uch *)LoadFarString(ReadError),  /* CANNOT use slide */
  378.                   (ulg)strlen(LoadFarString(ReadError)), 0x401);
  379.                 return 0;  /* discarding some data; better than lock-up */
  380.             }
  381.             /* buffer ALWAYS starts on a block boundary:  */
  382.             G.cur_zipfile_bufstart += INBUFSIZ;
  383.             G.inptr = G.inbuf;
  384.         }
  385.         count = MIN(size, (unsigned)G.incnt);
  386.         memcpy(buf, G.inptr, count);
  387.         buf += count;
  388.         G.inptr += count;
  389.         G.incnt -= count;
  390.         size -= count;
  391.     }
  392.     return n;
  393.  
  394. } /* end function readbuf() */
  395.  
  396.  
  397.  
  398.  
  399.  
  400. /***********************/
  401. /* Function readbyte() */
  402. /***********************/
  403.  
  404. int readbyte(__G)   /* refill inbuf and return a byte if available, else EOF */
  405.     __GDEF
  406. {
  407.     if (G.mem_mode)
  408.         return EOF;
  409.     if (G.csize <= 0) {
  410.         G.csize--;             /* for tests done after exploding */
  411.         G.incnt = 0;
  412.         return EOF;
  413.     }
  414.     if (G.incnt <= 0) {
  415.         if ((G.incnt = read(G.zipfd, (char *)G.inbuf, INBUFSIZ)) == 0) {
  416.             G.incnt = 0;       /* do not allow negative value to affect stuff */
  417.             return EOF;
  418.         } else if (G.incnt < 0) {  /* "fail" (abort, retry, ...) returns this */
  419.             /* another hack, but no real harm copying same thing twice */
  420.             (*G.message)((zvoid *)&G,
  421.               (uch *)LoadFarString(ReadError),
  422.               (ulg)strlen(LoadFarString(ReadError)), 0x401);
  423.             echon();
  424.             DESTROYGLOBALS()
  425.             exit(PK_BADERR);  /* totally bailing; better than lock-up */
  426.         }
  427.         G.cur_zipfile_bufstart += INBUFSIZ; /* always starts on block bndry */
  428.         G.inptr = G.inbuf;
  429.         defer_leftover_input(__G);           /* decrements G.csize */
  430.     }
  431.  
  432. #ifdef CRYPT
  433.     if (G.pInfo->encrypted) {
  434.         uch *p;
  435.         int n;
  436.  
  437.         /* This was previously set to decrypt one byte beyond G.csize, when
  438.          * incnt reached that far.  GRR said, "but it's required:  why?"  This
  439.          * was a bug in fillinbuf() -- was it also a bug here?
  440.          */
  441.         for (n = G.incnt, p = G.inptr;  n--;  p++)
  442.             zdecode(*p);
  443.     }
  444. #endif /* CRYPT */
  445.  
  446.     --G.incnt;
  447.     return *G.inptr++;
  448.  
  449. } /* end function readbyte() */
  450.  
  451.  
  452.  
  453.  
  454.  
  455. #ifdef USE_ZLIB
  456.  
  457. /************************/
  458. /* Function fillinbuf() */
  459. /************************/
  460.  
  461. int fillinbuf(__G) /* like readbyte() except returns number of bytes in inbuf */
  462.     __GDEF
  463. {
  464.     if (G.mem_mode ||
  465.                   (G.incnt = read(G.zipfd, (char *)G.inbuf, INBUFSIZ)) <= 0)
  466.         return 0;
  467.     G.cur_zipfile_bufstart += INBUFSIZ;   /* always starts on a block boundary */
  468.     G.inptr = G.inbuf;
  469.     defer_leftover_input(__G);           /* decrements G.csize */
  470.  
  471. #ifdef CRYPT
  472.     if (G.pInfo->encrypted) {
  473.         uch *p;
  474.         int n;
  475.  
  476.         for (n = G.incnt, p = G.inptr;  n--;  p++)
  477.             zdecode(*p);
  478.     }
  479. #endif /* CRYPT */
  480.  
  481.     return G.incnt;
  482.  
  483. } /* end function fillinbuf() */
  484.  
  485. #endif /* USE_ZLIB */
  486.  
  487.  
  488.  
  489.  
  490.  
  491. #ifndef VMS                 /* for VMS use code in vms.c */
  492.  
  493. /********************/
  494. /* Function flush() */
  495. /********************/
  496.  
  497. int flush(__G__ rawbuf, size, unshrink)   /* cflag => always 0; 50 if write error */
  498.     __GDEF
  499.     uch *rawbuf;
  500.     ulg size;
  501.     int unshrink;
  502. {
  503.     register uch *p, *q;
  504.     uch *transbuf;
  505. #if (defined(SMALL_MEM) || defined(MED_MEM))
  506.     ulg transbufsiz;
  507. #endif
  508.     /* static int didCRlast = FALSE;    moved to globals.h */
  509.  
  510.  
  511. /*---------------------------------------------------------------------------
  512.     Compute the CRC first; if testing or if disk is full, that's it.
  513.   ---------------------------------------------------------------------------*/
  514.  
  515.     G.crc32val = crc32(G.crc32val, rawbuf, (extent)size);
  516.  
  517.     if (G.tflag || size == 0L)   /* testing or nothing to write:  all done */
  518.         return 0;
  519.  
  520.     if (G.disk_full)
  521.         return 50;            /* disk already full:  ignore rest of file */
  522.  
  523. /*---------------------------------------------------------------------------
  524.     Write the bytes rawbuf[0..size-1] to the output device, first converting
  525.     end-of-lines and ASCII/EBCDIC as needed.  If SMALL_MEM or MED_MEM are NOT
  526.     defined, outbuf is assumed to be at least as large as rawbuf and is not
  527.     necessarily checked for overflow.
  528.   ---------------------------------------------------------------------------*/
  529.  
  530.     if (!G.pInfo->textmode) {   /* write raw binary data */
  531.         /* GRR:  note that for standard MS-DOS compilers, size argument to
  532.          * fwrite() can never be more than 65534, so WriteError macro will
  533.          * have to be rewritten if size can ever be that large.  For now,
  534.          * never more than 32K.  Also note that write() returns an int, which
  535.          * doesn't necessarily limit size to 32767 bytes if write() is used
  536.          * on 16-bit systems but does make it more of a pain; however, because
  537.          * at least MSC 5.1 has a lousy implementation of fwrite() (as does
  538.          * DEC Ultrix cc), write() is used anyway.
  539.          */
  540. #ifdef DLL
  541.         if (G.redirect_data)
  542.             writeToMemory(__G__ rawbuf, (unsigned)(q-transbuf));
  543.         else
  544. #endif
  545.         if (!G.cflag && WriteError(rawbuf, size, G.outfile))
  546.             return disk_error(__G);
  547.         else if (G.cflag && (*G.message)((zvoid *)&G, rawbuf, size, 0))
  548.             return 0;
  549.     } else {
  550.         if (unshrink) {
  551.             /* rawbuf = outbuf */
  552.             transbuf = G.outbuf2;
  553. #if (defined(SMALL_MEM) || defined(MED_MEM))
  554.             transbufsiz = TRANSBUFSIZ;
  555. #endif
  556.         } else {
  557.             /* rawbuf = slide */
  558.             transbuf = G.outbuf;
  559. #if (defined(SMALL_MEM) || defined(MED_MEM))
  560.             transbufsiz = OUTBUFSIZ;
  561.             Trace((stderr, "\ntransbufsiz = OUTBUFSIZ = %u\n", OUTBUFSIZ));
  562. #endif
  563.         }
  564.         if (G.newfile) {
  565.             G.didCRlast = FALSE;   /* no previous buffers written */
  566.             G.newfile = FALSE;
  567.         }
  568.         p = rawbuf;
  569.         if (*p == LF && G.didCRlast)
  570.             ++p;
  571.  
  572.     /*-----------------------------------------------------------------------
  573.         Algorithm:  CR/LF => native; lone CR => native; lone LF => native.
  574.         This routine is only for non-raw-VMS, non-raw-VM/CMS files (i.e.,
  575.         stream-oriented files, not record-oriented).
  576.       -----------------------------------------------------------------------*/
  577.  
  578.         G.didCRlast = FALSE;
  579.         for (q = transbuf;  p < rawbuf+(unsigned)size;  ++p) {
  580.             if (*p == CR) {              /* lone CR or CR/LF: EOL either way */
  581.                 PutNativeEOL
  582.                 if (p == rawbuf+(unsigned)size-1)  /* last char in buffer */
  583.                     G.didCRlast = TRUE;
  584.                 else if (p[1] == LF)     /* get rid of accompanying LF */
  585.                     ++p;
  586.             } else if (*p == LF)         /* lone LF */
  587.                 PutNativeEOL
  588.             else
  589. #ifndef DOS_OS2_W32
  590.             if (*p != CTRLZ)             /* lose all ^Z's */
  591. #endif
  592.                 *q++ = native(*p);
  593.  
  594. #if (defined(SMALL_MEM) || defined(MED_MEM))
  595. # if (lenEOL == 1)   /* don't check unshrink:  both buffers small but equal */
  596.             if (!unshrink)
  597. # endif
  598.                 /* check for danger of buffer overflow and flush */
  599.                 if (q > transbuf+(unsigned)transbufsiz-lenEOL) {
  600.                     Trace((stderr,
  601.                       "p - rawbuf = %u   q-transbuf = %u   size = %lu\n",
  602.                       (unsigned)(p-rawbuf), (unsigned)(q-transbuf), size));
  603.                     if (!G.cflag &&
  604.                         WriteError(transbuf, (unsigned)(q-transbuf),G.outfile))
  605.                         return disk_error(__G);
  606.                     else if (G.cflag && (*G.message)((zvoid *)&G, transbuf,
  607.                              (ulg)(q-transbuf), 0))
  608.                         return 0;
  609.                     q = transbuf;
  610.                     continue;
  611.                 }
  612. #endif /* SMALL_MEM || MED_MEM */
  613.         }
  614.  
  615.     /*-----------------------------------------------------------------------
  616.         Done translating:  write whatever we've got to file (or screen).
  617.       -----------------------------------------------------------------------*/
  618.  
  619.         Trace((stderr, "p - rawbuf = %u   q-transbuf = %u   size = %lu\n",
  620.           (unsigned)(p-rawbuf), (unsigned)(q-transbuf), size));
  621.         if (q > transbuf)
  622. #ifdef DLL
  623.             if (G.redirect_data)
  624.                 writeToMemory(__G__ transbuf, (unsigned)(q-transbuf));
  625.             else
  626. #endif
  627.             if (!G.cflag && WriteError(transbuf, (unsigned)(q-transbuf),
  628.                 G.outfile))
  629.                 return disk_error(__G);
  630.             else if (G.cflag && (*G.message)((zvoid *)&G, transbuf,
  631.                 (ulg)(q-transbuf), 0))
  632.                 return 0;
  633.     }
  634.  
  635.     return 0;
  636.  
  637. } /* end function flush() */
  638.  
  639.  
  640.  
  641.  
  642.  
  643. /*************************/
  644. /* Function disk_error() */
  645. /*************************/
  646.  
  647. static int disk_error(__G)
  648.     __GDEF
  649. {
  650.     /* OK to use slide[] here because this file is finished regardless */
  651.     Info(slide, 0x481, ((char *)slide, LoadFarString(DiskFullQuery), G.filename));
  652.  
  653. #ifndef MSWIN
  654.     fgets(G.answerbuf, 9, stdin);
  655.     if (*G.answerbuf == 'y')   /* stop writing to this file */
  656.         G.disk_full = 1;       /*  (outfile bad?), but new OK */
  657.     else
  658. #endif
  659.         G.disk_full = 2;       /* no:  exit program */
  660.  
  661.     return PK_DISK;
  662.  
  663. } /* end function disk_error() */
  664.  
  665. #endif /* !VMS */
  666.  
  667.  
  668.  
  669.  
  670.  
  671. /*****************************/
  672. /* Function UzpMessagePrnt() */
  673. /*****************************/
  674.  
  675. int UzpMessagePrnt(pG, buf, size, flag)
  676.     zvoid *pG;      /* globals struct:  always passed */
  677.     uch *buf;       /* preformatted string to be printed */
  678.     ulg size;       /* length of string (may include nulls) */
  679.     int flag;       /* flag bits */
  680. {
  681.     /* Important NOTE:
  682.      * The name of the first parameter of UzpMessagePrnt(), which passes
  683.      * the struct Globals address, >>> MUST <<< be identical to the string
  684.      * expansion of the __G__ macro in the REENTRANT case (see globals.h).
  685.      * This name identity is mandatory for the LoadFarString() macro
  686.      * (in the SMALL_MEM case) !!!
  687.      */
  688.     int error;
  689.     uch *q=buf, *endbuf=buf+(unsigned)size;
  690. #ifdef MORE
  691.     uch *p=buf-1;
  692. #endif
  693.     FILE *outfp;
  694.  
  695.  
  696. /*---------------------------------------------------------------------------
  697.     These tests are here to allow fine-tuning of UnZip's output messages,
  698.     but none of them will do anything without setting the appropriate bit
  699.     in the flag argument of every Info() statement which is to be turned
  700.     *off*.  That is, all messages are currently turned on for all ports.
  701.     To turn off *all* messages, use the UzpMessageNull() function instead
  702.     of this one.
  703.   ---------------------------------------------------------------------------*/
  704.  
  705. #if (defined(OS2) && defined(DLL))
  706.     if (MSG_NO_DLL2(flag))  /* if OS/2 DLL bit is set, do NOT print this msg */
  707.         return 0;
  708. #endif
  709. #ifdef WINDLL
  710.     if (MSG_NO_WDLL(flag))
  711.         return 0;
  712. #endif
  713. #ifdef MSWIN
  714.     if (MSG_NO_WGUI(flag))
  715.         return 0;
  716. #endif
  717. /*
  718. #ifdef ACORN_GUI
  719.     if (MSG_NO_AGUI(flag))
  720.         return 0;
  721. #endif
  722.  */
  723. #ifdef DLL                    /* don't display message if data is redirected */
  724.     if (((struct Globals *)pG)->redirect_data &&
  725.         !((struct Globals *)pG)->redirect_text)
  726.         return 0;
  727. #endif
  728.  
  729.     if (MSG_STDERR(flag) && !((struct Globals *)pG)->tflag)
  730.         outfp = (FILE *)stderr;
  731.     else
  732.         outfp = (FILE *)stdout;
  733.  
  734. #ifdef MPW
  735.     if (MSG_MNEWLN(flag)) {   /* assumes writable buffer (e.g., slide[]) */
  736.         *endbuf++ = '\n';     /*  with room for one more char at end of buf */
  737.         ++size;               /*  (safe assumption:  only used for four */
  738.     }                         /*  short queries in extract.c and fileio.c) */
  739. #endif
  740.  
  741.     if (MSG_TNEWLN(flag)) {   /* again assumes writable buffer:  fragile... */
  742.         if ((!size && !((struct Globals *)pG)->sol) ||
  743.             (size && (endbuf[-1] != '\n')))
  744.         {
  745.             *endbuf++ = '\n';
  746.             ++size;
  747.         }
  748.     }
  749.  
  750.     if (MSG_LNEWLN(flag) && !((struct Globals *)pG)->sol) {
  751.         /* not at start of line:  want newline */
  752. #ifdef DLL
  753.         if (!((struct Globals *)pG)->redirect_text) {
  754. #endif
  755.             putc('\n', outfp);          /* "more" will be off by one...oops */
  756.             fflush(outfp);
  757.             if (MSG_STDERR(flag) && ((struct Globals *)pG)->tflag &&
  758.                 !isatty(1) && isatty(2))
  759.             {
  760.                 /* error output from testing redirected:  also send to stderr */
  761.                 putc('\n', stderr);
  762.                 fflush(stderr);
  763.             }
  764. #ifdef DLL
  765.         } else
  766.            REDIRECTC('\n');
  767. #endif
  768.         ((struct Globals *)pG)->sol = TRUE;
  769.     }
  770.  
  771.     /* put zipfile name, filename and/or error/warning keywords here */
  772.  
  773. #ifdef MORE
  774.     /* room for --More-- and one line of overlap: */
  775.     ((struct Globals *)pG)->height = SCREENLINES - 2;
  776.  
  777.     if (((struct Globals *)pG)->M_flag
  778. #ifdef DLL
  779.          && !((struct Globals *)pG)->redirect_text
  780. #endif
  781.                                                  )
  782.     {
  783.         while (++p < endbuf) {
  784.             if (*p == '\n') {
  785.                 ++((struct Globals *)pG)->numlines;
  786.                 if (((struct Globals *)pG)->numlines %
  787.                     ((struct Globals *)pG)->height == 0L)    /* GRR: fix */
  788.                 {
  789.                     if ((error = WriteError(q, p-q+1, outfp)) != 0)
  790.                         return error;
  791.                     fflush(outfp);
  792.                     ((struct Globals *)pG)->sol = TRUE;
  793.                     q = p + 1;
  794.                     (*((struct Globals *)pG)->mpause)((zvoid *)pG,
  795.                       LoadFarString(MorePrompt), 1);
  796.                 }
  797.             }
  798.         } /* end while */
  799.         size = (ulg)(p - q);   /* remaining text */
  800.     }
  801. #endif /* MORE */
  802.  
  803.     if (size) {
  804. #ifdef DLL
  805.         if (!((struct Globals *)pG)->redirect_text) {
  806. #endif
  807.             if ((error = WriteError(q, size, outfp)) != 0)
  808.                 return error;
  809.             fflush(outfp);
  810.             if (MSG_STDERR(flag) && ((struct Globals *)pG)->tflag &&
  811.                 !isatty(1) && isatty(2))
  812.             {
  813.                 /* error output from testing redirected:  also send to stderr */
  814.                 if ((error = WriteError(q, size, stderr)) != 0)
  815.                     return error;
  816.                 fflush(stderr);
  817.             }
  818. #ifdef DLL
  819.         } else {
  820.             REDIRECTPRINT(q, size);   /* GRR:  this is ugly:  hide with macro */
  821.         }
  822. #endif
  823.         ((struct Globals *)pG)->sol = (endbuf[-1] == '\n');
  824.     }
  825.     return 0;
  826.  
  827. } /* end function UzpMessagePrnt() */
  828.  
  829.  
  830.  
  831.  
  832.  
  833. #ifdef DLL
  834.  
  835. /*****************************/
  836. /* Function UzpMessageNull() */  /* convenience routine for no output at all */
  837. /*****************************/
  838.  
  839. int UzpMessageNull(pG, buf, size, flag)
  840.     zvoid *pG;    /* globals struct:  always passed */
  841.     uch *buf;     /* preformatted string to be printed */
  842.     ulg size;     /* length of string (may include nulls) */
  843.     int flag;     /* flag bits */
  844. {
  845.     return 0;
  846.  
  847. } /* end function UzpMessageNull() */
  848.  
  849. #endif /* DLL */
  850.  
  851.  
  852.  
  853.  
  854.  
  855. /***********************/
  856. /* Function UzpInput() */   /* GRR:  this is a placeholder for now */
  857. /***********************/
  858.  
  859. int UzpInput(pG, buf, size, flag)
  860.     zvoid *pG;    /* globals struct:  always passed */
  861.     uch *buf;     /* preformatted string to be printed */
  862.     int *size;    /* (address of) size of buf and of returned string */
  863.     int flag;     /* flag bits (bit 0: no echo) */
  864. {
  865.     *size = 0;
  866.     return 0;
  867.  
  868. } /* end function UzpInput() */
  869.  
  870.  
  871.  
  872.  
  873.  
  874. #if (!defined(MSWIN) && !defined(MACOS))
  875.  
  876. /***************************/
  877. /* Function UzpMorePause() */
  878. /***************************/
  879.  
  880. void UzpMorePause(pG, prompt, flag)
  881.     zvoid *pG;            /* globals struct:  always passed */
  882.     const char *prompt;   /* "--More--" prompt */
  883.     int flag;             /* 0 = any char OK; 1 = accept only '\n', ' ', q */
  884. {
  885.     uch c;
  886.  
  887. /*---------------------------------------------------------------------------
  888.     Print a prompt and wait for the user to press a key, then erase prompt
  889.     if possible.
  890.   ---------------------------------------------------------------------------*/
  891.  
  892.     if (!((struct Globals *)pG)->sol)
  893.         fprintf(stderr, "\n");
  894.     /* numlines may or may not be used: */
  895.     fprintf(stderr, prompt, ((struct Globals *)pG)->numlines);
  896.     fflush(stderr);
  897.     if (flag & 1) {
  898.         do {
  899.             c = (uch)FGETCH(0);
  900.         } while (c != '\r' && c != '\n' && c != ' ' && c != 'q' && c != 'Q');
  901.     } else
  902.         c = (uch)FGETCH(0);
  903.  
  904.     /* newline was not echoed, so cover up prompt line */
  905.     fprintf(stderr, LoadFarString(HidePrompt));
  906.     fflush(stderr);
  907.  
  908.     if (ToLower(c) == 'q') {
  909.         DESTROYGLOBALS()
  910.         EXIT(PK_COOL);
  911.     }
  912.  
  913.     ((struct Globals *)pG)->sol = TRUE;
  914.  
  915. } /* end function UzpMorePause() */
  916.  
  917. #endif /* !MSWIN && !MACOS */
  918.  
  919.  
  920.  
  921.  
  922.  
  923. /**********************/
  924. /* Function handler() */
  925. /**********************/
  926.  
  927. void handler(signal)   /* upon interrupt, turn on echo and exit cleanly */
  928.     int signal;
  929. {
  930.     GETGLOBALS();
  931.  
  932. #if !(defined(SIGBUS) || defined(SIGSEGV))      /* add a newline if not at */
  933.     (*G.message)((zvoid *)&G, slide, 0L, 0x41); /*  start of line (to stderr; */
  934. #endif                                          /*  slide[] should be safe) */
  935.  
  936.     echon();
  937.  
  938. #ifdef SIGBUS
  939.     if (signal == SIGBUS) {
  940.         Info(slide, 0x421, ((char *)slide, LoadFarString(ZipfileCorrupt),
  941.           "bus error"));
  942.         DESTROYGLOBALS()
  943.         EXIT(PK_BADERR);
  944.     }
  945. #endif /* SIGBUS */
  946.  
  947. #ifdef SIGSEGV
  948.     if (signal == SIGSEGV) {
  949.         Info(slide, 0x421, ((char *)slide, LoadFarString(ZipfileCorrupt),
  950.           "segmentation violation"));
  951.         DESTROYGLOBALS()
  952.         EXIT(PK_BADERR);
  953.     }
  954. #endif /* SIGSEGV */
  955.  
  956.     /* probably ctrl-C */
  957.     DESTROYGLOBALS()
  958.     EXIT(PK_ERR);         /* was EXIT(0) */
  959. }
  960.  
  961.  
  962.  
  963.  
  964.  
  965. #if (!defined(VMS) && !defined(OS2) && !defined(CMS_MVS))
  966. #ifdef MSWIN
  967. #  ifndef timezone
  968. #    define timezone _timezone
  969. #  endif
  970. #endif
  971.  
  972. /*******************************/
  973. /* Function dos_to_unix_time() */   /* only used for freshening/updating */
  974. /*******************************/
  975.  
  976. time_t dos_to_unix_time(ddate, dtime)
  977.     unsigned ddate, dtime;
  978. {
  979.     time_t m_time;
  980.     int yr, mo, dy, hh, mm, ss;
  981. #ifdef TOPS20
  982. #   define YRBASE  1900
  983.     struct tmx *tmx;
  984.     char temp[20];
  985. #else /* !TOPS20 */
  986. #   define YRBASE  1970
  987.     static short yday[]={0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
  988.     int leap;
  989.     unsigned days;
  990. #if (!defined(MACOS) && !defined(RISCOS))
  991. #ifndef BSD4_4   /* GRR:  change to !defined(MODERN) ? */
  992. #if (defined(BSD) || defined(MTS) || defined(__GO32__))
  993.     struct timeb tbp;
  994. #else /* !(BSD || MTS || __GO32__) */
  995. #ifdef DECLARE_TIMEZONE
  996.     extern time_t timezone;
  997. #endif
  998. #endif /* ?(BSD || MTS || __GO32__) */
  999. #endif /* !BSD4_4 */
  1000. #endif /* !MACOS && !RISCOS */
  1001. #endif /* ?TOPS20 */
  1002.  
  1003.  
  1004.     /* dissect date */
  1005.     yr = ((ddate >> 9) & 0x7f) + (1980 - YRBASE);
  1006.     mo = ((ddate >> 5) & 0x0f) - 1;
  1007.     dy = (ddate & 0x1f) - 1;
  1008.  
  1009.     /* dissect time */
  1010.     hh = (dtime >> 11) & 0x1f;
  1011.     mm = (dtime >> 5) & 0x3f;
  1012.     ss = (dtime & 0x1f) * 2;
  1013.  
  1014. #ifdef TOPS20
  1015.     tmx = (struct tmx *)malloc(sizeof(struct tmx));
  1016.     sprintf (temp, "%02d/%02d/%02d %02d:%02d:%02d", mo+1, dy+1, yr, hh, mm, ss);
  1017.     time_parse(temp, tmx, (char *)0);
  1018.     m_time = time_make(tmx);
  1019.     free(tmx);
  1020.  
  1021. #else /* !TOPS20 */
  1022.     /* leap = # of leap yrs from YRBASE up to but not including current year */
  1023.     leap = ((yr + YRBASE - 1) / 4);   /* leap year base factor */
  1024.  
  1025.     /* calculate days from BASE to this year and add expired days this year */
  1026.     days = (yr * 365) + (leap - 492) + yday[mo];
  1027.  
  1028.     /* if year is a leap year and month is after February, add another day */
  1029.     if ((mo > 1) && ((yr+YRBASE)%4 == 0) && ((yr+YRBASE) != 2100))
  1030.         ++days;                 /* OK through 2199 */
  1031.  
  1032.     /* convert date & time to seconds relative to 00:00:00, 01/01/YRBASE */
  1033.     m_time = (time_t)((long)(days + dy) * 86400L + (long)hh * 3600L +
  1034.                       (long)(mm * 60 + ss));
  1035.       /* - 1;   MS-DOS times always rounded up to nearest even second */
  1036.     TTrace((stderr, "dos_to_unix_time:\n"));
  1037.     TTrace((stderr, "  m_time before timezone = %ld\n", (long)m_time));
  1038.  
  1039. #if (!defined(MACOS) && !defined(RISCOS))
  1040.     /* adjust for local standard timezone offset */
  1041. #if (defined(BSD) || defined(MTS) || defined(__GO32__))
  1042. #ifdef BSD4_4
  1043.     m_time -= localtime(&m_time)->tm_gmtoff;    /* sec. EAST of GMT: subtr. */
  1044. #else /* !BSD4_4 */
  1045.     ftime(&tbp);                                /* get `timezone' */
  1046.     m_time += tbp.timezone * 60L;               /* seconds WEST of GMT:  add */
  1047. #endif /* ?BSD4_4 */
  1048. #else /* !(BSD || MTS || __GO32__) */
  1049. #ifdef WIN32
  1050.     {
  1051.         TIME_ZONE_INFORMATION tzinfo;
  1052.         DWORD res;
  1053.  
  1054.         /* account for timezone differences */
  1055.         res = GetTimeZoneInformation(&tzinfo);
  1056.         if (res == TIME_ZONE_ID_STANDARD)
  1057.             m_time += 60*(tzinfo.Bias + tzinfo.StandardBias);
  1058.         else if (res == TIME_ZONE_ID_DAYLIGHT)
  1059.             m_time += 60*(tzinfo.Bias + tzinfo.DaylightBias);
  1060.         /* GRR:  are other return-values possible? */
  1061.     }
  1062. #else /* !WIN32 */
  1063.     tzset();                    /* set `timezone' variable */
  1064.     m_time += timezone;         /* seconds WEST of GMT:  add */
  1065. #endif /* ?WIN32 */
  1066. #endif /* ?(BSD || MTS || __GO32__) */
  1067.  
  1068.     TTrace((stderr, "  m_time after timezone =  %ld\n", (long)m_time));
  1069. #endif /* !MACOS && !RISCOS */
  1070.  
  1071. #ifndef WIN32
  1072. #ifndef BSD4_4  /* (DST already added to tm_gmtoff, so skip tm_isdst) */
  1073.     /* adjust for local daylight savings (summer) time */
  1074.     if (localtime((time_t *)&m_time)->tm_isdst)
  1075.         m_time -= 60L * 60L;    /* adjust for daylight savings time */
  1076.  
  1077.     TTrace((stderr, "  m_time after DST =       %ld\n", (long)m_time));
  1078. #endif /* !BSD4_4 */
  1079. #endif /* !WIN32 */
  1080.  
  1081. #endif /* ?TOPS20 */
  1082.  
  1083.     return m_time;
  1084.  
  1085. } /* end function dos_to_unix_time() */
  1086.  
  1087.  
  1088.  
  1089.  
  1090.  
  1091. /******************************/
  1092. /* Function check_for_newer() */  /* used for overwriting/freshening/updating */
  1093. /******************************/
  1094.  
  1095. int check_for_newer(__G__ filename)  /* return 1 if existing file is newer */
  1096.     __GDEF                           /*  or equal; 0 if older; -1 if doesn't */
  1097.     char *filename;                  /*  exist yet */
  1098. {
  1099.     time_t existing, archive;
  1100. #ifdef USE_EF_UX_TIME
  1101.     ztimbuf z_utime;
  1102. #endif
  1103. #ifdef AOS_VS
  1104.     long    dmm, ddd, dyy, dhh, dmin, dss;
  1105.  
  1106.  
  1107.     dmm = (lrec.last_mod_file_date >> 5) & 0x0f;
  1108.     ddd = lrec.last_mod_file_date & 0x1f;
  1109.     dyy = (lrec.last_mod_file_date >> 9) + 1980;
  1110.     dhh = (lrec.last_mod_file_time >> 11) & 0x1f;
  1111.     dmin = (lrec.last_mod_file_time >> 5) & 0x3f;
  1112.     dss = (lrec.last_mod_file_time & 0x1f) * 2;
  1113.  
  1114.     /* under AOS/VS, file times can only be set at creation time,
  1115.      * with the info in a special DG format.  Make sure we can create
  1116.      * it here - we delete it later & re-create it, whether or not
  1117.      * it exists now.
  1118.      */
  1119.     if (!zvs_create(filename, (((ulg)dgdate(dmm, ddd, dyy)) << 16) |
  1120.         (dhh*1800L + dmin*30L + dss/2L), -1L, -1L, (char *) -1, -1, -1, -1))
  1121.         return DOES_NOT_EXIST;
  1122. #endif /* AOS_VS */
  1123.  
  1124.     Trace((stderr, "check_for_newer:  doing stat(%s)\n", filename));
  1125.     if (stat(filename, &G.statbuf)) {
  1126.         Trace((stderr,
  1127.           "check_for_newer:  stat(%s) returns %d:  file does not exist\n",
  1128.           filename, stat(filename, &G.statbuf)));
  1129.         return DOES_NOT_EXIST;
  1130.     }
  1131.     Trace((stderr, "check_for_newer:  stat(%s) returns 0:  file exists\n",
  1132.       filename));
  1133.  
  1134. #ifdef USE_EF_UX_TIME
  1135.     /* The `Unix extra field mtime' should be used for comparison with the
  1136.      * time stamp of the existing file >>>ONLY<<< when the EF info is also
  1137.      * used to set the modification time of the extracted file.
  1138.      * Currently, this is only the case for systems that incorporate
  1139.      * the OS specific code from the "unix/" subdirectory.
  1140.      */
  1141.     if (G.extra_field &&
  1142.         ef_scan_for_izux(G.extra_field, G.lrec.extra_field_length,
  1143.                          &z_utime, NULL) > 0) {
  1144.         TTrace((stderr, "check_for_newer:  using Unix extra field mtime\n"));
  1145.         existing = G.statbuf.st_mtime;
  1146.         archive  = z_utime.modtime;
  1147.     } else {
  1148.         /* round up existing filetime to nearest 2 seconds for comparison */
  1149.         existing = G.statbuf.st_mtime & 1 ? G.statbuf.st_mtime + 1
  1150.                                           : G.statbuf.st_mtime;
  1151.         archive  = dos_to_unix_time(G.lrec.last_mod_file_date,
  1152.                                     G.lrec.last_mod_file_time);
  1153.     }
  1154. #else /* !USE_EF_UX_TIME */
  1155.     /* round up existing filetime to nearest 2 seconds for comparison */
  1156.     existing = G.statbuf.st_mtime & 1 ? G.statbuf.st_mtime + 1
  1157.                                       : G.statbuf.st_mtime;
  1158.     archive  = dos_to_unix_time(G.lrec.last_mod_file_date,
  1159.                                 G.lrec.last_mod_file_time);
  1160. #endif /* ?USE_EF_UX_TIME */
  1161.  
  1162.     TTrace((stderr, "check_for_newer:  existing %ld, archive %ld, e-a %ld\n",
  1163.       existing, archive, existing-archive));
  1164.  
  1165.     return (existing >= archive);
  1166.  
  1167. } /* end function check_for_newer() */
  1168.  
  1169. #endif /* !VMS && !OS2 && !CMS_MVS */
  1170.  
  1171.  
  1172.  
  1173.  
  1174.  
  1175. /************************/
  1176. /* Function do_string() */
  1177. /************************/
  1178.  
  1179. int do_string(__G__ len, option)      /* return PK-type error code */
  1180.     __GDEF
  1181.     unsigned int len;           /* without prototype, ush converted to this */
  1182.     int option;
  1183. {
  1184.     long comment_bytes_left, block_length;
  1185.     int error=PK_OK;
  1186.     ush extra_len;
  1187. #ifdef AMIGA
  1188.     char tmp_filenote[2 * AMIGA_FILENOTELEN]; /* extra room for squozen chars */
  1189. #endif
  1190.  
  1191.  
  1192. /*---------------------------------------------------------------------------
  1193.     This function processes arbitrary-length (well, usually) strings.  Four
  1194.     options are allowed:  SKIP, wherein the string is skipped (pretty logical,
  1195.     eh?); DISPLAY, wherein the string is printed to standard output after un-
  1196.     dergoing any necessary or unnecessary character conversions; DS_FN,
  1197.     wherein the string is put into the filename[] array after undergoing ap-
  1198.     propriate conversions (including case-conversion, if that is indicated:
  1199.     see the global variable pInfo->lcflag); and EXTRA_FIELD, wherein the
  1200.     `string' is assumed to be an extra field and is copied to the (freshly
  1201.     malloced) buffer G.extra_field.  The third option should be OK since
  1202.     filename is dimensioned at 1025, but we check anyway.
  1203.  
  1204.     The string, by the way, is assumed to start at the current file-pointer
  1205.     position; its length is given by len.  So start off by checking length
  1206.     of string:  if zero, we're already done.
  1207.   ---------------------------------------------------------------------------*/
  1208.  
  1209.     if (!len)
  1210.         return PK_COOL;
  1211.  
  1212.     switch (option) {
  1213.  
  1214.     /*
  1215.      * First case:  print string on standard output.  First set loop vari-
  1216.      * ables, then loop through the comment in chunks of OUTBUFSIZ bytes,
  1217.      * converting formats and printing as we go.  The second half of the
  1218.      * loop conditional was added because the file might be truncated, in
  1219.      * which case comment_bytes_left will remain at some non-zero value for
  1220.      * all time.  outbuf and slide are used as scratch buffers because they
  1221.      * are available (we should be either before or in between any file pro-
  1222.      * cessing).
  1223.      */
  1224.  
  1225.     case DISPLAY:
  1226.         comment_bytes_left = len;
  1227.         block_length = OUTBUFSIZ;    /* for the while statement, first time */
  1228.         while (comment_bytes_left > 0 && block_length > 0) {
  1229.             register uch *p = G.outbuf;
  1230.             register uch *q = G.outbuf;
  1231.  
  1232.             if ((block_length = readbuf(__G__ (char *)G.outbuf,
  1233.                    (unsigned) MIN((long)OUTBUFSIZ, comment_bytes_left))) == 0)
  1234.                 return PK_EOF;
  1235.             comment_bytes_left -= block_length;
  1236.  
  1237.             /* this is why we allocated an extra byte for outbuf:  terminate
  1238.              *  with zero (ASCIIZ) */
  1239.             G.outbuf[(unsigned)block_length] = '\0';
  1240.  
  1241.             /* remove all ASCII carriage returns from comment before printing
  1242.              * (since used before A_TO_N(), check for CR instead of '\r')
  1243.              */
  1244.             while (*p) {
  1245.                 while (*p == CR)
  1246.                     ++p;
  1247.                 *q++ = *p++;
  1248.             }
  1249.             /* could check whether (p - outbuf) == block_length here */
  1250.             *q = '\0';
  1251.  
  1252.             A_TO_N(G.outbuf);   /* translate string to native */
  1253.  
  1254. #ifdef MSWIN
  1255.             /* ran out of local mem -- had to cheat */
  1256.             win_fprintf(stdout, len, (char *)G.outbuf);
  1257.             win_fprintf(stdout, 2, (char *)"\n\n");
  1258. #else /* !MSWIN */
  1259. #ifdef NATIVE          /* GRR:  can ANSI be used with EBCDIC? */
  1260.             (*G.message)((zvoid *)&G, G.outbuf, (ulg)(q-G.outbuf), 0);
  1261. #else /* ASCII */
  1262.             p = G.outbuf - 1;
  1263.             q = slide;
  1264.             while (*++p) {
  1265.                 int pause = FALSE;
  1266.  
  1267.                 if (*p == 0x1B) {          /* ASCII escape char */
  1268.                     *q++ = '^';
  1269.                     *q++ = '[';
  1270.                 } else if (*p == 0x13) {   /* ASCII ^S (pause) */
  1271.                     pause = TRUE;
  1272.                     if (p[1] == 0x0a)      /* ASCII LF */
  1273.                         *q++ = *++p;
  1274.                     else if (p[1] == 0x0d && p[2] == 0x0a) {  /* ASCII CR LF */
  1275.                         *q++ = *++p;
  1276.                         *q++ = *++p;
  1277.                     }
  1278.                 } else
  1279.                     *q++ = *p;
  1280.                 if ((unsigned)(q-slide) > WSIZE-3 || pause) {   /* flush */
  1281.                     (*G.message)((zvoid *)&G, slide, (ulg)(q-slide), 0);
  1282.                     q = slide;
  1283.                     if (pause)
  1284.                         (*G.mpause)((zvoid *)&G, LoadFarString(QuitPrompt), 0);
  1285.                 }
  1286.             }
  1287.             (*G.message)((zvoid *)&G, slide, (ulg)(q-slide), 0);
  1288. #endif /* ?NATIVE */
  1289. #endif /* ?MSWIN */
  1290.         }
  1291.         /* add '\n' if not at start of line */
  1292.         (*G.message)((zvoid *)&G, slide, 0L, 0x40);
  1293.         break;
  1294.  
  1295.     /*
  1296.      * Second case:  read string into filename[] array.  The filename should
  1297.      * never ever be longer than FILNAMSIZ-1 (1024), but for now we'll check,
  1298.      * just to be sure.
  1299.      */
  1300.  
  1301.     case DS_FN:
  1302.         extra_len = 0;
  1303.         if (len >= FILNAMSIZ) {
  1304.             Info(slide, 0x401, ((char *)slide,
  1305.               LoadFarString(FilenameTooLongTrunc)));
  1306.             error = PK_WARN;
  1307.             extra_len = (ush)(len - FILNAMSIZ + 1);
  1308.             len = FILNAMSIZ - 1;
  1309.         }
  1310.         if (readbuf(__G__  G.filename, len) == 0)
  1311.             return PK_EOF;
  1312.         G.filename[len] = '\0';   /* terminate w/zero:  ASCIIZ */
  1313.  
  1314.         A_TO_N(G.filename);       /* translate string to native */
  1315.  
  1316.         if (G.pInfo->lcflag)      /* replace with lowercase filename */
  1317.             TOLOWER(G.filename, G.filename);
  1318.  
  1319.         if (G.pInfo->vollabel && len > 8 && G.filename[8] == '.') {
  1320.             char *p = G.filename+8;
  1321.             while (*p++)
  1322.                 p[-1] = *p;  /* disk label, and 8th char is dot:  remove dot */
  1323.         }
  1324.  
  1325.         if (!extra_len)         /* we're done here */
  1326.             break;
  1327.  
  1328.         /*
  1329.          * We truncated the filename, so print what's left and then fall
  1330.          * through to the SKIP routine.
  1331.          */
  1332.         Info(slide, 0x401, ((char *)slide, "[ %s ]\n", G.filename));
  1333.         len = extra_len;
  1334.         /*  FALL THROUGH...  */
  1335.  
  1336.     /*
  1337.      * Third case:  skip string, adjusting readbuf's internal variables
  1338.      * as necessary (and possibly skipping to and reading a new block of
  1339.      * data).
  1340.      */
  1341.  
  1342.     case SKIP:
  1343.         /* cur_zipfile_bufstart already takes account of extra_bytes, so don't
  1344.          * correct for it twice: */
  1345.         ZLSEEK(G.cur_zipfile_bufstart - G.extra_bytes +
  1346.                (G.inptr-G.inbuf) + len)
  1347.         break;
  1348.  
  1349.     /*
  1350.      * Fourth case:  assume we're at the start of an "extra field"; malloc
  1351.      * storage for it and read data into the allocated space.
  1352.      */
  1353.  
  1354.     case EXTRA_FIELD:
  1355.         if (G.extra_field != (uch *)NULL)
  1356.             free(G.extra_field);
  1357.         if ((G.extra_field = (uch *)malloc(len)) == (uch *)NULL) {
  1358.             Info(slide, 0x401, ((char *)slide, LoadFarString(ExtraFieldTooLong),
  1359.               len));
  1360.             /* cur_zipfile_bufstart already takes account of extra_bytes,
  1361.              * so don't correct for it twice: */
  1362.             ZLSEEK(G.cur_zipfile_bufstart - G.extra_bytes +
  1363.                    (G.inptr-G.inbuf) + len)
  1364.         } else
  1365.             if (readbuf(__G__  (char *)G.extra_field, len) == 0)
  1366.                 return PK_EOF;
  1367.         break;
  1368.  
  1369. #ifdef AMIGA
  1370.     /*
  1371.      * Fifth case, for the Amiga only:  take the comment that would ordinarily
  1372.      * be skipped over, and turn it into a 79 character string that will be
  1373.      * attached to the file as a "filenote" after it is extracted.
  1374.      */
  1375.  
  1376.     case FILENOTE:
  1377.         if ((extra_len = readbuf(__G__ tmp_filenote, (unsigned)
  1378.                                  MIN(len, 2 * AMIGA_FILENOTELEN - 1))) == 0)
  1379.             return PK_EOF;
  1380.         if ((len -= extra_len) > 0)     /* treat remainder as in case SKIP: */
  1381.             ZLSEEK(G.cur_zipfile_bufstart - G.extra_bytes
  1382.                    + (G.inptr - G.inbuf) + len)
  1383.         /* convert multi-line text into single line with no ctl-chars: */
  1384.         tmp_filenote[extra_len] = '\0';
  1385.         while ((int) --extra_len >= 0)
  1386.             if ((unsigned) tmp_filenote[extra_len] < ' ')
  1387.                 if (tmp_filenote[extra_len+1] == ' ')     /* no excess */
  1388.                     strcpy(tmp_filenote+extra_len, tmp_filenote+extra_len+1);
  1389.                 else
  1390.                     tmp_filenote[extra_len] = ' ';
  1391.         tmp_filenote[AMIGA_FILENOTELEN - 1] = '\0';
  1392.         if (G.filenotes[G.filenote_slot])
  1393.             free(G.filenotes[G.filenote_slot]);     /* should not happen */
  1394.         G.filenotes[G.filenote_slot] = NULL;
  1395.         if (tmp_filenote[0]) {
  1396.             if (!(G.filenotes[G.filenote_slot] = malloc(strlen(tmp_filenote)+1)))
  1397.                 return PK_MEM;
  1398.             strcpy(G.filenotes[G.filenote_slot], tmp_filenote);
  1399.         }
  1400.         break;
  1401. #endif /* AMIGA */
  1402.  
  1403.     } /* end switch (option) */
  1404.  
  1405.     return error;
  1406.  
  1407. } /* end function do_string() */
  1408.  
  1409.  
  1410.  
  1411.  
  1412.  
  1413. /***********************/
  1414. /* Function makeword() */
  1415. /***********************/
  1416.  
  1417. ush makeword(b)
  1418.     uch *b;
  1419. {
  1420.     /*
  1421.      * Convert Intel style 'short' integer to non-Intel non-16-bit
  1422.      * host format.  This routine also takes care of byte-ordering.
  1423.      */
  1424.     return (ush)((b[1] << 8) | b[0]);
  1425. }
  1426.  
  1427.  
  1428.  
  1429.  
  1430.  
  1431. /***********************/
  1432. /* Function makelong() */
  1433. /***********************/
  1434.  
  1435. ulg makelong(sig)
  1436.     uch *sig;
  1437. {
  1438.     /*
  1439.      * Convert intel style 'long' variable to non-Intel non-16-bit
  1440.      * host format.  This routine also takes care of byte-ordering.
  1441.      */
  1442.     return (((ulg)sig[3]) << 24)
  1443.         + (((ulg)sig[2]) << 16)
  1444.         + (((ulg)sig[1]) << 8)
  1445.         + ((ulg)sig[0]);
  1446. }
  1447.  
  1448.  
  1449.  
  1450.  
  1451.  
  1452. #ifdef ZMEM  /* memset/memcpy for systems without either them or bzero/bcopy */
  1453.              /* (no known systems as of 960211) */
  1454.  
  1455. /*********************/
  1456. /* Function memset() */
  1457. /*********************/
  1458.  
  1459. zvoid *memset(buf, init, len)
  1460.     register zvoid *buf;        /* buffer location */
  1461.     register int init;          /* initializer character */
  1462.     register unsigned int len;  /* length of the buffer */
  1463. {
  1464.     zvoid *start;
  1465.  
  1466.     start = buf;
  1467.     while (len--)
  1468.         *((char *)buf++) = (char)init;
  1469.     return start;
  1470. }
  1471.  
  1472.  
  1473.  
  1474.  
  1475.  
  1476. /*********************/
  1477. /* Function memcpy() */
  1478. /*********************/
  1479.  
  1480. zvoid *memcpy(dst, src, len)
  1481.     register zvoid *dst;
  1482.     register const zvoid *src;
  1483.     register unsigned int len;
  1484. {
  1485.     zvoid *start;
  1486.  
  1487.     start = dst;
  1488.     while (len-- > 0)
  1489.         *((char *)dst)++ = *((char *)src)++;
  1490.     return start;
  1491. }
  1492.  
  1493. #endif /* ZMEM */
  1494.  
  1495.  
  1496.  
  1497.  
  1498.  
  1499. /************************/
  1500. /* Function zstrnicmp() */
  1501. /************************/
  1502.  
  1503. int zstrnicmp(s1, s2, n)
  1504.     register const char *s1, *s2;
  1505.     register unsigned n;
  1506. {
  1507.     for (; n > 0;  --n, ++s1, ++s2) {
  1508.  
  1509.         if (ToLower(*s1) != ToLower(*s2))
  1510.             /* test includes early termination of one string */
  1511.             return (ToLower(*s1) < ToLower(*s2))? -1 : 1;
  1512.  
  1513.         if (*s1 == '\0')   /* both strings terminate early */
  1514.             return 0;
  1515.     }
  1516.     return 0;
  1517. }
  1518.  
  1519.  
  1520.  
  1521.  
  1522.  
  1523. #ifdef REGULUS  /* returns the inode number on success(!)...argh argh argh */
  1524. #  undef stat
  1525.  
  1526. /********************/
  1527. /* Function zstat() */
  1528. /********************/
  1529.  
  1530. int zstat(p, s)
  1531.     char *p;
  1532.     struct stat *s;
  1533. {
  1534.     return (stat(p,s) >= 0? 0 : (-1));
  1535. }
  1536.  
  1537. #endif /* REGULUS */
  1538.  
  1539.  
  1540.  
  1541.  
  1542.  
  1543. #ifdef SMALL_MEM
  1544.  
  1545. /*******************************/
  1546. /*  Function fLoadFarString()  */   /* (and friends...) */
  1547. /*******************************/
  1548.  
  1549. char *fLoadFarString(__GPRO__ const char Far *sz)
  1550. {
  1551.     (void)zfstrcpy(G.rgchBigBuffer, sz);
  1552.     return G.rgchBigBuffer;
  1553. }
  1554.  
  1555. char *fLoadFarStringSmall(__GPRO__ const char Far *sz)
  1556. {
  1557.     (void)zfstrcpy(G.rgchSmallBuffer, sz);
  1558.     return G.rgchSmallBuffer;
  1559. }
  1560.  
  1561. char *fLoadFarStringSmall2(__GPRO__ const char Far *sz)
  1562. {
  1563.     (void)zfstrcpy(G.rgchSmallBuffer2, sz);
  1564.     return G.rgchSmallBuffer2;
  1565. }
  1566.  
  1567.  
  1568.  
  1569.  
  1570. #if (!defined(_MSC_VER) || (_MSC_VER < 600))
  1571. /*************************/
  1572. /*  Function zfstrcpy()  */   /* portable clone of _fstrcpy() */
  1573. /*************************/
  1574.  
  1575. char Far * Far zfstrcpy(char Far *s1, const char Far *s2)
  1576. {
  1577.     char Far *p = s1;
  1578.  
  1579.     while ((*s1++ = *s2++) != '\0');
  1580.     return p;
  1581. }
  1582. #endif /* !_MSC_VER || (_MSC_VER < 600) */
  1583.  
  1584. #endif /* SMALL_MEM */
  1585.