home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 9 Archive / 09-Archive.zip / unzip540.zip / fileio.c < prev    next >
C/C++ Source or Header  |  1998-11-26  |  71KB  |  2,152 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.              UzpPassword()            (non-WINDLL)
  23.              handler()
  24.              dos_to_unix_time()       (non-VMS, non-VM/CMS, non-MVS)
  25.              check_for_newer()        (non-VMS, non-OS/2, non-VM/CMS, non-MVS)
  26.              do_string()
  27.              makeword()
  28.              makelong()
  29.              str2iso()                (CRYPT && NEED_STR2ISO, only)
  30.              str2oem()                (CRYPT && NEED_STR2OEM, only)
  31.              memset()                 (ZMEM only)
  32.              memcpy()                 (ZMEM only)
  33.              zstrnicmp()
  34.              zstat()                  (REGULUS only)
  35.              fLoadFarString()         (SMALL_MEM only)
  36.              fLoadFarStringSmall()    (SMALL_MEM only)
  37.              fLoadFarStringSmall2()   (SMALL_MEM only)
  38.              zfstrcpy()               (SMALL_MEM only)
  39.  
  40.   ---------------------------------------------------------------------------*/
  41.  
  42.  
  43. #define FILEIO_C
  44. #define UNZIP_INTERNAL
  45. #include "unzip.h"
  46. #ifdef WINDLL
  47. #  include "windll/windll.h"
  48. #  include <setjmp.h>
  49. #endif
  50. #include "crypt.h"
  51. #include "ttyio.h"
  52.  
  53. /* setup of codepage conversion for decryption passwords */
  54. #if CRYPT
  55. #  if (defined(CRYP_USES_ISO2OEM) && !defined(IZ_ISO2OEM_ARRAY))
  56. #    define IZ_ISO2OEM_ARRAY            /* pull in iso2oem[] table */
  57. #  endif
  58. #  if (defined(CRYP_USES_OEM2ISO) && !defined(IZ_OEM2ISO_ARRAY))
  59. #    define IZ_OEM2ISO_ARRAY            /* pull in oem2iso[] table */
  60. #  endif
  61. #endif
  62. #include "ebcdic.h"   /* definition/initialization of ebcdic[] */
  63.  
  64.  
  65. /*
  66.    Note: Under Windows, the maximum size of the buffer that can be used
  67.    with any of the *printf calls is 16,384, so win_fprintf was used to
  68.    feed the fprintf clone no more than 16K chunks at a time. This should
  69.    be valid for anything up to 64K (and probably beyond, assuming your
  70.    buffers are that big).
  71. */
  72. #ifdef WINDLL
  73. #  define WriteError(buf,len,strm) \
  74.    (win_fprintf(pG, strm, (extent)len, (char far *)buf) != (int)(len))
  75. #else /* !WINDLL */
  76. #  ifdef USE_FWRITE
  77. #    define WriteError(buf,len,strm) \
  78.      ((extent)fwrite((char *)(buf),1,(extent)(len),strm) != (extent)(len))
  79. #  else
  80. #    define WriteError(buf,len,strm) \
  81.      ((extent)write(fileno(strm),(char *)(buf),(extent)(len)) != (extent)(len))
  82. #  endif
  83. #endif /* ?WINDLL */
  84.  
  85. static int disk_error OF((__GPRO));
  86.  
  87.  
  88. /****************************/
  89. /* Strings used in fileio.c */
  90. /****************************/
  91.  
  92. #if (defined(UNIX) || defined(DOS_FLX_OS2_W32) || defined(__BEOS__))
  93.    static ZCONST char Far CannotDeleteOldFile[] =
  94.      "error:  cannot delete old %s\n";
  95. #ifdef UNIXBACKUP
  96.    static ZCONST char Far CannotRenameOldFile[] =
  97.      "error:  cannot rename old %s\n";
  98.    static ZCONST char Far BackupSuffix[] = "~";
  99. #endif
  100. #endif /* UNIX || DOS_FLX_OS2_W32 || __BEOS__ */
  101.  
  102. static ZCONST char Far CannotOpenZipfile[] =
  103.   "error:  cannot open zipfile [ %s ]\n";
  104. #if (!defined(VMS) && !defined(AOS_VS) && !defined(CMS_MVS) && !defined(MACOS))
  105.    static ZCONST char Far CannotCreateFile[] = "error:  cannot create %s\n";
  106. #endif
  107. #ifdef NOVELL_BUG_FAILSAFE
  108.    static ZCONST char Far NovellBug[] =
  109.      "error:  %s: stat() says does not exist, but fopen() found anyway\n";
  110. #endif
  111. static ZCONST char Far ReadError[] = "error:  zipfile read error\n";
  112. static ZCONST char Far FilenameTooLongTrunc[] =
  113.   "warning:  filename too long--truncating.\n";
  114. static ZCONST char Far ExtraFieldTooLong[] =
  115.   "warning:  extra field too long (%d).  Ignoring...\n";
  116.  
  117. #ifdef WINDLL
  118.    static ZCONST char Far DiskFullQuery[] =
  119.      "%s:  write error (disk full?).\n";
  120. #else
  121.    static ZCONST char Far DiskFullQuery[] =
  122.      "%s:  write error (disk full?).  Continue? (y/n/^C) ";
  123.    static ZCONST char Far ZipfileCorrupt[] =
  124.      "error:  zipfile probably corrupt (%s)\n";
  125. #  ifdef SYMLINKS
  126.      static ZCONST char Far FileIsSymLink[] =
  127.        "%s exists and is a symbolic link%s.\n";
  128. #  endif
  129. #  ifdef MORE
  130.      static ZCONST char Far MorePrompt[] = "--More--(%lu)";
  131. #  endif
  132.    static ZCONST char Far QuitPrompt[] =
  133.      "--- Press `Q' to quit, or any other key to continue ---";
  134.    static ZCONST char Far HidePrompt[] = /* "\r                       \r"; */
  135.      "\r                                                         \r";
  136. #  if CRYPT
  137. #    ifdef MACOS
  138.        /* SPC: are names on MacOS REALLY so much longer than elsewhere ??? */
  139.        static ZCONST char Far PasswPrompt[] = "[%s]\n %s password: ";
  140. #    else
  141.        static ZCONST char Far PasswPrompt[] = "[%s] %s password: ";
  142. #    endif
  143.      static ZCONST char Far PasswPrompt2[] = "Enter password: ";
  144.      static ZCONST char Far PasswRetry[] = "password incorrect--reenter: ";
  145. #  endif /* CRYPT */
  146. #endif /* !WINDLL */
  147.  
  148.  
  149.  
  150.  
  151.  
  152. /******************************/
  153. /* Function open_input_file() */
  154. /******************************/
  155.  
  156. int open_input_file(__G)    /* return 1 if open failed */
  157.     __GDEF
  158. {
  159.     /*
  160.      *  open the zipfile for reading and in BINARY mode to prevent cr/lf
  161.      *  translation, which would corrupt the bitstreams
  162.      */
  163.  
  164. #if (defined(UNIX) || defined(TOPS20) || defined(AOS_VS) || defined(__BEOS__))
  165.     G.zipfd = open(G.zipfn, O_RDONLY);
  166. #else /* !(UNIX || TOPS20 || AOS_VS || __BEOS__) */
  167. #ifdef VMS
  168.     G.zipfd = open(G.zipfn, O_RDONLY, 0, "ctx=stm");
  169. #else /* !VMS */
  170. #ifdef MACOS
  171.     G.zipfd = open(G.zipfn, 0);
  172. #else /* !MACOS */
  173. #ifdef RISCOS
  174.     G.zipfd = fopen(G.zipfn, "rb");
  175. #else /* !RISCOS */
  176. #ifdef CMS_MVS
  177.     G.zipfd = vmmvs_open_infile(__G);
  178. #else /* !CMS_MVS */
  179.     G.zipfd = open(G.zipfn, O_RDONLY | O_BINARY);
  180. #endif /* ?CMS_MVS */
  181. #endif /* ?RISCOS */
  182. #endif /* ?MACOS */
  183. #endif /* ?VMS */
  184. #endif /* ?(UNIX || TOPS20 || AOS_VS || __BEOS__) */
  185.  
  186. #ifdef USE_STRM_INPUT
  187.     if (G.zipfd == NULL)
  188. #else
  189.     /* if (G.zipfd < 0) */  /* no good for Windows CE port */
  190.     if (G.zipfd == -1)
  191. #endif
  192.     {
  193.         Info(slide, 0x401, ((char *)slide, LoadFarString(CannotOpenZipfile),
  194.           G.zipfn));
  195.         return 1;
  196.     }
  197.     return 0;
  198.  
  199. } /* end function open_input_file() */
  200.  
  201.  
  202.  
  203.  
  204. #if (!defined(VMS) && !defined(AOS_VS) && !defined(CMS_MVS) && !defined(MACOS))
  205.  
  206. /***************************/
  207. /* Function open_outfile() */
  208. /***************************/
  209.  
  210. int open_outfile(__G)         /* return 1 if fail */
  211.     __GDEF
  212. {
  213. #ifdef DLL
  214.     if (G.redirect_data)
  215.         return (redirect_outfile(__G) == FALSE);
  216. #endif
  217. #ifdef QDOS
  218.     QFilename(__G__ G.filename);
  219. #endif
  220. #if (defined(DOS_FLX_OS2_W32) || defined(UNIX) || defined(__BEOS__))
  221. #ifdef BORLAND_STAT_BUG
  222.     /* Borland 5.0's stat() barfs if the filename has no extension and the
  223.      * file doesn't exist. */
  224.     if (access(G.filename, 0) == -1) {
  225.         FILE *tmp = fopen(G.filename, "wb+");
  226.  
  227.         /* file doesn't exist, so create a dummy file to keep stat() from
  228.          * failing (will be over-written anyway) */
  229.         fputc('0', tmp);  /* just to have something in the file */
  230.         fclose(tmp);
  231.     }
  232. #endif /* BORLAND_STAT_BUG */
  233. #ifdef SYMLINKS
  234.     if (SSTAT(G.filename, &G.statbuf) == 0 || lstat(G.filename,&G.statbuf) == 0)
  235. #else
  236.     if (SSTAT(G.filename, &G.statbuf) == 0)
  237. #endif /* ?SYMLINKS */
  238.     {
  239.         Trace((stderr, "open_outfile:  stat(%s) returns 0:  file exists\n",
  240.           FnFilter1(G.filename)));
  241. #ifdef UNIXBACKUP
  242.         if (uO.B_flag) {    /* do backup */
  243.             char *tname;
  244.             int blen, flen, tlen;
  245.  
  246.             blen = strlen(BackupSuffix);
  247.             flen = strlen(G.filename);
  248.             tlen = flen + blen + 1;
  249.             if (tlen >= FILNAMSIZ) {   /* in case name is too long, truncate */
  250.                 tname = (char *)malloc(FILNAMSIZ);
  251.                 if (tname == NULL)
  252.                     return 1;                 /* in case we run out of space */
  253.                 tlen = FILNAMSIZ - 1 - blen;
  254.                 strcpy(tname, G.filename);    /* make backup name */
  255.                 tname[tlen] = '\0';
  256.             } else {
  257.                 tname = (char *)malloc(tlen);
  258.                 if (tname == NULL)
  259.                     return 1;                 /* in case we run out of space */
  260.                 strcpy(tname, G.filename);    /* make backup name */
  261.             }
  262.             strcpy(tname+flen, BackupSuffix);
  263.  
  264.             /* GRR:  should check if backup file exists, apply -n/-o to that */
  265.             if (rename(G.filename, tname) < 0) {   /* move file */
  266.                 Info(slide, 0x401, ((char *)slide,
  267.                   LoadFarString(CannotRenameOldFile), FnFilter1(G.filename)));
  268.                 free(tname);
  269.                 return 1;
  270.             }
  271.             free(tname);
  272.         } else
  273. #endif /* UNIXBACKUP */
  274. #ifdef DOS_FLX_OS2_W32
  275.         if (!(G.statbuf.st_mode & S_IWRITE)) {
  276.             Trace((stderr, "open_outfile:  existing file %s is read-only\n",
  277.               FnFilter1(G.filename)));
  278.             chmod(G.filename, S_IREAD | S_IWRITE);
  279.             Trace((stderr, "open_outfile:  %s now writable\n",
  280.               FnFilter1(G.filename)));
  281.         }
  282. #endif /* DOS_FLX_OS2_W32 */
  283.         if (unlink(G.filename) != 0) {
  284.             Info(slide, 0x401, ((char *)slide,
  285.               LoadFarString(CannotDeleteOldFile), FnFilter1(G.filename)));
  286.             return 1;
  287.         }
  288.         Trace((stderr, "open_outfile:  %s now deleted\n",
  289.           FnFilter1(G.filename)));
  290.     }
  291. #endif /* DOS_FLX_OS2_W32 || UNIX || __BEOS__ */
  292. #ifdef RISCOS
  293.     if (SWI_OS_File_7(G.filename,0xDEADDEAD,0xDEADDEAD,G.lrec.ucsize)!=NULL) {
  294.         Info(slide, 1, ((char *)slide, LoadFarString(CannotCreateFile),
  295.           FnFilter1(G.filename)));
  296.         return 1;
  297.     }
  298. #endif /* RISCOS */
  299. #ifdef TOPS20
  300.     char *tfilnam;
  301.  
  302.     if ((tfilnam = (char *)malloc(2*strlen(G.filename)+1)) == (char *)NULL)
  303.         return 1;
  304.     strcpy(tfilnam, G.filename);
  305.     upper(tfilnam);
  306.     enquote(tfilnam);
  307.     if ((G.outfile = fopen(tfilnam, FOPW)) == (FILE *)NULL) {
  308.         Info(slide, 1, ((char *)slide, LoadFarString(CannotCreateFile),
  309.           tfilnam));
  310.         free(tfilnam);
  311.         return 1;
  312.     }
  313.     free(tfilnam);
  314. #else /* !TOPS20 */
  315. #ifdef MTS
  316.     if (uO.aflag)
  317.         G.outfile = fopen(G.filename, FOPWT);
  318.     else
  319.         G.outfile = fopen(G.filename, FOPW);
  320.     if (G.outfile == (FILE *)NULL) {
  321.         Info(slide, 1, ((char *)slide, LoadFarString(CannotCreateFile),
  322.           FnFilter1(G.filename)));
  323.         return 1;
  324.     }
  325. #else /* !MTS */
  326. #ifdef TANDEM
  327.     if (SSTAT(G.filename, &G.statbuf) == 0) {
  328.         Trace((stderr, "open_outfile:  stat(%s) returns 0 (file exists)\n",
  329.           FnFilter1(G.filename)));
  330.         if (unlink(G.filename) != 0) {
  331.             Trace((stderr, "open_outfile:  existing file %s is read-only\n",
  332.               FnFilter1(G.filename)));
  333.             chmod(G.filename, S_IRUSR | S_IWUSR);
  334.             Trace((stderr, "open_outfile:  %s now writable\n",
  335.               FnFilter1(G.filename)));
  336.             if (unlink(G.filename) != 0)
  337.                 return 1;
  338.         }
  339.         Trace((stderr, "open_outfile:  %s now deleted\n",
  340.           FnFilter1(G.filename)));
  341.     }
  342.     if (G.pInfo->textmode)
  343.         G.outfile = fopen(G.filename, FOPWT);
  344.     else
  345.         G.outfile = fopen(G.filename, FOPW);
  346.     if (G.outfile == (FILE *)NULL) {
  347.         Info(slide, 1, ((char *)slide, LoadFarString(CannotCreateFile),
  348.           FnFilter1(G.filename)));
  349.         return 1;
  350.     }
  351. #else /* !TANDEM */
  352. #ifdef DEBUG
  353.     Info(slide, 1, ((char *)slide,
  354.       "open_outfile:  doing fopen(%s) for reading\n", FnFilter1(G.filename)));
  355.     if ((G.outfile = fopen(G.filename, FOPR)) == (FILE *)NULL)
  356.         Info(slide, 1, ((char *)slide,
  357.           "open_outfile:  fopen(%s) for reading failed:  does not exist\n",
  358.           FnFilter1(G.filename)));
  359.     else {
  360.         Info(slide, 1, ((char *)slide,
  361.           "open_outfile:  fopen(%s) for reading succeeded:  file exists\n",
  362.           FnFilter1(G.filename)));
  363.         fclose(G.outfile);
  364.     }
  365. #endif /* DEBUG */
  366. #ifdef NOVELL_BUG_FAILSAFE
  367.     if (G.dne && ((G.outfile = fopen(G.filename, FOPR)) != (FILE *)NULL)) {
  368.         Info(slide, 0x401, ((char *)slide, LoadFarString(NovellBug),
  369.           FnFilter1(G.filename)));
  370.         fclose(G.outfile);
  371.         return 1;   /* with "./" fix in checkdir(), should never reach here */
  372.     }
  373. #endif /* NOVELL_BUG_FAILSAFE */
  374.     Trace((stderr, "open_outfile:  doing fopen(%s) for writing\n",
  375.       FnFilter1(G.filename)));
  376.     if ((G.outfile = fopen(G.filename, FOPW)) == (FILE *)NULL) {
  377.         Info(slide, 0x401, ((char *)slide, LoadFarString(CannotCreateFile),
  378.           FnFilter1(G.filename)));
  379.         return 1;
  380.     }
  381.     Trace((stderr, "open_outfile:  fopen(%s) for writing succeeded\n",
  382.       FnFilter1(G.filename)));
  383. #endif /* !TANDEM */
  384. #endif /* !MTS */
  385. #endif /* !TOPS20 */
  386.  
  387. #ifdef USE_FWRITE
  388. #ifdef DOS_OS2_W32
  389.     /* 16-bit MSC: buffer size must be strictly LESS than 32K (WSIZE):  bogus */
  390.     setbuf(G.outfile, (char *)NULL);   /* make output unbuffered */
  391. #else /* !DOS_OS2_W32 */
  392. #ifndef RISCOS
  393. #ifdef _IOFBF  /* make output fully buffered (works just about like write()) */
  394.     setvbuf(G.outfile, (char *)slide, _IOFBF, WSIZE);
  395. #else
  396.     setbuf(G.outfile, (char *)slide);
  397. #endif
  398. #endif /* !RISCOS */
  399. #endif /* ?DOS_OS2_W32 */
  400. #endif /* USE_FWRITE */
  401.     return 0;
  402.  
  403. } /* end function open_outfile() */
  404.  
  405. #endif /* !VMS && !AOS_VS && !CMS_MVS && !MACOS */
  406.  
  407.  
  408.  
  409.  
  410.  
  411. /*
  412.  * These functions allow NEXTBYTE to function without needing two bounds
  413.  * checks.  Call defer_leftover_input() if you ever have filled G.inbuf
  414.  * by some means other than readbyte(), and you then want to start using
  415.  * NEXTBYTE.  When going back to processing bytes without NEXTBYTE, call
  416.  * undefer_input().  For example, extract_or_test_member brackets its
  417.  * central section that does the decompression with these two functions.
  418.  * If you need to check the number of bytes remaining in the current
  419.  * file while using NEXTBYTE, check (G.csize + G.incnt), not G.csize.
  420.  */
  421.  
  422. /****************************/
  423. /* function undefer_input() */
  424. /****************************/
  425.  
  426. void undefer_input(__G)
  427.     __GDEF
  428. {
  429.     if (G.incnt > 0)
  430.         G.csize += G.incnt;
  431.     if (G.incnt_leftover > 0) {
  432.         /* We know that "(G.csize < MAXINT)" so we can cast G.csize to int:
  433.          * This condition was checked when G.incnt_leftover was set > 0 in
  434.          * defer_leftover_input(), and it is NOT allowed to touch G.csize
  435.          * before calling undefer_input() when (G.incnt_leftover > 0)
  436.          * (single exception: see read_byte()'s  "G.csize <= 0" handling) !!
  437.          */
  438.         G.incnt = G.incnt_leftover + (int)G.csize;
  439.         G.inptr = G.inptr_leftover - (int)G.csize;
  440.         G.incnt_leftover = 0;
  441.     } else if (G.incnt < 0)
  442.         G.incnt = 0;
  443. } /* end function undefer_input() */
  444.  
  445.  
  446.  
  447.  
  448.  
  449. /***********************************/
  450. /* function defer_leftover_input() */
  451. /***********************************/
  452.  
  453. void defer_leftover_input(__G)
  454.     __GDEF
  455. {
  456.     if ((long)G.incnt > G.csize) {
  457.         /* (G.csize < MAXINT), we can safely cast it to int !! */
  458.         if (G.csize < 0L)
  459.             G.csize = 0L;
  460.         G.inptr_leftover = G.inptr + (int)G.csize;
  461.         G.incnt_leftover = G.incnt - (int)G.csize;
  462.         G.incnt = (int)G.csize;
  463.     } else
  464.         G.incnt_leftover = 0;
  465.     G.csize -= G.incnt;
  466. } /* end function defer_leftover_input() */
  467.  
  468.  
  469.  
  470.  
  471.  
  472. /**********************/
  473. /* Function readbuf() */
  474. /**********************/
  475.  
  476. unsigned readbuf(__G__ buf, size)   /* return number of bytes read into buf */
  477.     __GDEF
  478.     char *buf;
  479.     register unsigned size;
  480. {
  481.     register unsigned count;
  482.     unsigned n;
  483.  
  484.     n = size;
  485.     while (size) {
  486.         if (G.incnt <= 0) {
  487.             if ((G.incnt = read(G.zipfd, (char *)G.inbuf, INBUFSIZ)) == 0)
  488.                 return (n-size);
  489.             else if (G.incnt < 0) {
  490.                 /* another hack, but no real harm copying same thing twice */
  491.                 (*G.message)((zvoid *)&G,
  492.                   (uch *)LoadFarString(ReadError),  /* CANNOT use slide */
  493.                   (ulg)strlen(LoadFarString(ReadError)), 0x401);
  494.                 return 0;  /* discarding some data; better than lock-up */
  495.             }
  496.             /* buffer ALWAYS starts on a block boundary:  */
  497.             G.cur_zipfile_bufstart += INBUFSIZ;
  498.             G.inptr = G.inbuf;
  499.         }
  500.         count = MIN(size, (unsigned)G.incnt);
  501.         memcpy(buf, G.inptr, count);
  502.         buf += count;
  503.         G.inptr += count;
  504.         G.incnt -= count;
  505.         size -= count;
  506.     }
  507.     return n;
  508.  
  509. } /* end function readbuf() */
  510.  
  511.  
  512.  
  513.  
  514.  
  515. /***********************/
  516. /* Function readbyte() */
  517. /***********************/
  518.  
  519. int readbyte(__G)   /* refill inbuf and return a byte if available, else EOF */
  520.     __GDEF
  521. {
  522.     if (G.mem_mode)
  523.         return EOF;
  524.     if (G.csize <= 0) {
  525.         G.csize--;             /* for tests done after exploding */
  526.         G.incnt = 0;
  527.         return EOF;
  528.     }
  529.     if (G.incnt <= 0) {
  530.         if ((G.incnt = read(G.zipfd, (char *)G.inbuf, INBUFSIZ)) == 0) {
  531.             G.incnt = 0;       /* do not allow negative value to affect stuff */
  532.             return EOF;
  533.         } else if (G.incnt < 0) {  /* "fail" (abort, retry, ...) returns this */
  534.             /* another hack, but no real harm copying same thing twice */
  535.             (*G.message)((zvoid *)&G,
  536.               (uch *)LoadFarString(ReadError),
  537.               (ulg)strlen(LoadFarString(ReadError)), 0x401);
  538.             echon();
  539. #ifdef WINDLL
  540.             longjmp(dll_error_return, 1);
  541. #else
  542.             DESTROYGLOBALS()
  543.             EXIT(PK_BADERR);    /* totally bailing; better than lock-up */
  544. #endif
  545.         }
  546.         G.cur_zipfile_bufstart += INBUFSIZ; /* always starts on block bndry */
  547.         G.inptr = G.inbuf;
  548.         defer_leftover_input(__G);           /* decrements G.csize */
  549.     }
  550.  
  551. #if CRYPT
  552.     if (G.pInfo->encrypted) {
  553.         uch *p;
  554.         int n;
  555.  
  556.         /* This was previously set to decrypt one byte beyond G.csize, when
  557.          * incnt reached that far.  GRR said, "but it's required:  why?"  This
  558.          * was a bug in fillinbuf() -- was it also a bug here?
  559.          */
  560.         for (n = G.incnt, p = G.inptr;  n--;  p++)
  561.             zdecode(*p);
  562.     }
  563. #endif /* CRYPT */
  564.  
  565.     --G.incnt;
  566.     return *G.inptr++;
  567.  
  568. } /* end function readbyte() */
  569.  
  570.  
  571.  
  572.  
  573.  
  574. #ifdef USE_ZLIB
  575.  
  576. /************************/
  577. /* Function fillinbuf() */
  578. /************************/
  579.  
  580. int fillinbuf(__G) /* like readbyte() except returns number of bytes in inbuf */
  581.     __GDEF
  582. {
  583.     if (G.mem_mode ||
  584.                   (G.incnt = read(G.zipfd, (char *)G.inbuf, INBUFSIZ)) <= 0)
  585.         return 0;
  586.     G.cur_zipfile_bufstart += INBUFSIZ;  /* always starts on a block boundary */
  587.     G.inptr = G.inbuf;
  588.     defer_leftover_input(__G);           /* decrements G.csize */
  589.  
  590. #if CRYPT
  591.     if (G.pInfo->encrypted) {
  592.         uch *p;
  593.         int n;
  594.  
  595.         for (n = G.incnt, p = G.inptr;  n--;  p++)
  596.             zdecode(*p);
  597.     }
  598. #endif /* CRYPT */
  599.  
  600.     return G.incnt;
  601.  
  602. } /* end function fillinbuf() */
  603.  
  604. #endif /* USE_ZLIB */
  605.  
  606.  
  607.  
  608.  
  609.  
  610. #ifndef VMS  /* for VMS use code in vms.c */
  611.  
  612. /********************/
  613. /* Function flush() */   /* returns PK error codes: */
  614. /********************/   /* if cflag => always 0; PK_DISK if write error */
  615.  
  616. int flush(__G__ rawbuf, size, unshrink)
  617.     __GDEF
  618.     uch *rawbuf;
  619.     ulg size;
  620.     int unshrink;
  621. {
  622.     register uch *p, *q;
  623.     uch *transbuf;
  624. #if (defined(SMALL_MEM) || defined(MED_MEM) || defined(VMS_TEXT_CONV))
  625.     ulg transbufsiz;
  626. #endif
  627.     /* static int didCRlast = FALSE;    moved to globals.h */
  628.  
  629.  
  630. /*---------------------------------------------------------------------------
  631.     Compute the CRC first; if testing or if disk is full, that's it.
  632.   ---------------------------------------------------------------------------*/
  633.  
  634.     G.crc32val = crc32(G.crc32val, rawbuf, (extent)size);
  635.  
  636. #ifdef DLL
  637.     if ((G.statreportcb != NULL) &&
  638.         (*G.statreportcb)(__G__ UZ_ST_IN_PROGRESS, G.zipfn, G.filename, NULL))
  639.         return IZ_CTRLC;        /* cancel operation by user request */
  640. #endif
  641.  
  642.     if (uO.tflag || size == 0L)  /* testing or nothing to write:  all done */
  643.         return PK_OK;
  644.  
  645.     if (G.disk_full)
  646.         return PK_DISK;         /* disk already full:  ignore rest of file */
  647.  
  648. /*---------------------------------------------------------------------------
  649.     Write the bytes rawbuf[0..size-1] to the output device, first converting
  650.     end-of-lines and ASCII/EBCDIC as needed.  If SMALL_MEM or MED_MEM are NOT
  651.     defined, outbuf is assumed to be at least as large as rawbuf and is not
  652.     necessarily checked for overflow.
  653.   ---------------------------------------------------------------------------*/
  654.  
  655.     if (!G.pInfo->textmode) {   /* write raw binary data */
  656.         /* GRR:  note that for standard MS-DOS compilers, size argument to
  657.          * fwrite() can never be more than 65534, so WriteError macro will
  658.          * have to be rewritten if size can ever be that large.  For now,
  659.          * never more than 32K.  Also note that write() returns an int, which
  660.          * doesn't necessarily limit size to 32767 bytes if write() is used
  661.          * on 16-bit systems but does make it more of a pain; however, because
  662.          * at least MSC 5.1 has a lousy implementation of fwrite() (as does
  663.          * DEC Ultrix cc), write() is used anyway.
  664.          */
  665. #ifdef DLL
  666.         if (G.redirect_data)
  667.             writeToMemory(__G__ rawbuf, size);
  668.         else
  669. #endif
  670.         if (!uO.cflag && WriteError(rawbuf, size, G.outfile))
  671.             return disk_error(__G);
  672.         else if (uO.cflag && (*G.message)((zvoid *)&G, rawbuf, size, 0))
  673.             return 0;
  674.     } else {   /* textmode:  aflag is true */
  675.         if (unshrink) {
  676.             /* rawbuf = outbuf */
  677.             transbuf = G.outbuf2;
  678. #if (defined(SMALL_MEM) || defined(MED_MEM) || defined(VMS_TEXT_CONV))
  679.             transbufsiz = TRANSBUFSIZ;
  680. #endif
  681.         } else {
  682.             /* rawbuf = slide */
  683.             transbuf = G.outbuf;
  684. #if (defined(SMALL_MEM) || defined(MED_MEM) || defined(VMS_TEXT_CONV))
  685.             transbufsiz = OUTBUFSIZ;
  686.             Trace((stderr, "\ntransbufsiz = OUTBUFSIZ = %u\n", OUTBUFSIZ));
  687. #endif
  688.         }
  689.         if (G.newfile) {
  690. #ifdef VMS_TEXT_CONV
  691.             /* GRR: really want to check if -aa (or -aaa?) was given... */
  692.             if (rawbuf[1]) {       /* first line is more than 255 chars long */
  693.                 Trace((stderr,
  694.       "\nfirst line of VMS `text' too long; switching to normal extraction\n"));
  695.                 G.VMS_line_state = -1;   /* -1: don't treat as VMS text */
  696.             } else
  697.                 G.VMS_line_state = 0;    /* 0: ready to read line length */
  698. #endif
  699.             G.didCRlast = FALSE;         /* no previous buffers written */
  700.             G.newfile = FALSE;
  701.         }
  702.  
  703. #ifdef VMS_TEXT_CONV
  704.         if (G.pInfo->hostnum == VMS_ && G.extra_field && G.VMS_line_state >= 0)
  705.         {
  706.             /* GRR: really want to check for actual VMS extra field, and
  707.              *      ideally for variable-length record format */
  708. /*
  709.             printf("\n>>>>>> GRR:  file is VMS text and has an extra field\n");
  710.  */
  711.  
  712.             p = rawbuf;
  713.             q = transbuf;
  714.             while(p < rawbuf+(unsigned)size) {
  715.                 switch (G.VMS_line_state) {
  716.  
  717.                     /* 0: ready to read line length */
  718.                     case 0:
  719.                         G.VMS_line_length = 0;
  720.                         G.VMS_line_pad = 0;
  721.                         if (p == rawbuf+(unsigned)size-1) {    /* last char */
  722.                             G.VMS_line_length = (int)((uch)(*p++));
  723.                             G.VMS_line_state = 1;
  724.                         } else {
  725.                             G.VMS_line_length = makeword(p);
  726.                             p += 2;
  727.                             G.VMS_line_state = 2;
  728.                         }
  729.                         if (G.VMS_line_length & 1)   /* odd */
  730.                             G.VMS_line_pad = 1;
  731.                         break;
  732.  
  733.                     /* 1: read one byte of length, need second */
  734.                     case 1:
  735.                         G.VMS_line_length += ((int)((uch)(*p++)) << 8);
  736.                         G.VMS_line_state = 2;
  737.                         break;
  738.  
  739.                     /* 2: ready to read VMS_line_length chars */
  740.                     case 2:
  741.                         if (G.VMS_line_length < rawbuf+(unsigned)size-p) {
  742.                             if (G.VMS_line_length >=
  743.                                 transbuf+(unsigned)transbufsiz-q)
  744.                             {
  745.                                 int outroom = transbuf+(unsigned)transbufsiz-q;
  746.  
  747. /* GRR:  need to change this to *q++ = native(*p++); loop or something */
  748.                                 memcpy(q, p, outroom);
  749. #ifdef DLL
  750.                                 if (G.redirect_data)
  751.                                     writeToMemory(__G__ transbuf,
  752.                                       (unsigned)outroom);
  753.                                 else
  754. #endif
  755.                                 if (!uO.cflag && WriteError(transbuf,
  756.                                     (unsigned)outroom, G.outfile))
  757.                                     return disk_error(__G);
  758.                                 else if (uO.cflag && (*G.message)((zvoid *)&G,
  759.                                          transbuf, (ulg)outroom, 0))
  760.                                     return 0;
  761.                                 q = transbuf;
  762.                                 p += outroom;
  763.                                 G.VMS_line_length -= outroom;
  764.                                 /* fall through to normal case */
  765.                             }
  766. /* GRR:  need to change this to *q++ = native(*p++); loop or something */
  767.                             memcpy(q, p, G.VMS_line_length);
  768.                             q += G.VMS_line_length;
  769.                             p += G.VMS_line_length;
  770.                             G.VMS_line_length = 0;   /* necessary?? */
  771.                             G.VMS_line_state = 3;
  772.  
  773.                         } else {  /* remaining input is less than full line */
  774.                             int remaining = rawbuf+(unsigned)size-p;
  775.  
  776.                             if (remaining <
  777.                                 transbuf+(unsigned)transbufsiz-q)
  778.                             {
  779.                                 int outroom = transbuf+(unsigned)transbufsiz-q;
  780.  
  781. /* GRR:  need to change this to *q++ = native(*p++); loop or something */
  782.                                 memcpy(q, p, outroom);
  783. #ifdef DLL
  784.                                 if (G.redirect_data)
  785.                                     writeToMemory(__G__ transbuf,
  786.                                       (unsigned)(outroom));
  787.                                 else
  788. #endif
  789.                                 if (!uO.cflag && WriteError(transbuf,
  790.                                     (unsigned)outroom, G.outfile))
  791.                                     return disk_error(__G);
  792.                                 else if (uO.cflag && (*G.message)((zvoid *)&G,
  793.                                          transbuf, (ulg)outroom, 0))
  794.                                     return 0;
  795.                                 q = transbuf;
  796.                                 p += outroom;
  797.                                 remaining -= outroom;
  798.                             }
  799. /* GRR:  need to change this to *q++ = native(*p++); loop or something */
  800.                             memcpy(q, p, remaining);
  801.                             q += remaining;
  802.                             p += remaining;
  803.                             G.VMS_line_length -= remaining;
  804.                             /* no change in G.VMS_line_state */
  805.                         }
  806.                         break;
  807.  
  808.                     /* 3: ready to PutNativeEOL */
  809.                     case 3:
  810.                         if (q > transbuf+(unsigned)transbufsiz-lenEOL) {
  811. #ifdef DLL
  812.                             if (G.redirect_data)
  813.                                 writeToMemory(__G__ transbuf,
  814.                                   (unsigned)(q-transbuf));
  815.                             else
  816. #endif
  817.                             if (!uO.cflag &&
  818.                                 WriteError(transbuf, (unsigned)(q-transbuf),
  819.                                   G.outfile))
  820.                                 return disk_error(__G);
  821.                             else if (uO.cflag && (*G.message)((zvoid *)&G,
  822.                                      transbuf, (ulg)(q-transbuf), 0))
  823.                                 return 0;
  824.                             q = transbuf;
  825.                         }
  826.                         PutNativeEOL
  827.                         if (G.VMS_line_pad)
  828.                             if (p < rawbuf+(unsigned)size) {
  829.                                 ++p;
  830.                                 G.VMS_line_state = 0;
  831.                             } else
  832.                                 G.VMS_line_state = 4;
  833.                         else
  834.                             G.VMS_line_state = 0;
  835.                         break;
  836.  
  837.                     /* 4: ready to read pad byte */
  838.                     case 4:
  839.                         ++p;
  840.                         G.VMS_line_state = 0;
  841.                         break;
  842.                 }
  843.             } /* end while */
  844.  
  845.         } else
  846. #endif /* VMS_TEXT_CONV */
  847.  
  848.     /*-----------------------------------------------------------------------
  849.         Algorithm:  CR/LF => native; lone CR => native; lone LF => native.
  850.         This routine is only for non-raw-VMS, non-raw-VM/CMS files (i.e.,
  851.         stream-oriented files, not record-oriented).
  852.       -----------------------------------------------------------------------*/
  853.  
  854.         /* else not VMS text */ {
  855.             p = rawbuf;
  856.             if (*p == LF && G.didCRlast)
  857.                 ++p;
  858.             G.didCRlast = FALSE;
  859.             for (q = transbuf;  p < rawbuf+(unsigned)size;  ++p) {
  860.                 if (*p == CR) {           /* lone CR or CR/LF: EOL either way */
  861.                     PutNativeEOL
  862.                     if (p == rawbuf+(unsigned)size-1)  /* last char in buffer */
  863.                         G.didCRlast = TRUE;
  864.                     else if (p[1] == LF)  /* get rid of accompanying LF */
  865.                         ++p;
  866.                 } else if (*p == LF)      /* lone LF */
  867.                     PutNativeEOL
  868.                 else
  869. #ifndef DOS_FLX_OS2_W32
  870.                 if (*p != CTRLZ)          /* lose all ^Z's */
  871. #endif
  872.                     *q++ = native(*p);
  873.  
  874. #if (defined(SMALL_MEM) || defined(MED_MEM))
  875. # if (lenEOL == 1)   /* don't check unshrink:  both buffers small but equal */
  876.                 if (!unshrink)
  877. # endif
  878.                     /* check for danger of buffer overflow and flush */
  879.                     if (q > transbuf+(unsigned)transbufsiz-lenEOL) {
  880.                         Trace((stderr,
  881.                           "p - rawbuf = %u   q-transbuf = %u   size = %lu\n",
  882.                           (unsigned)(p-rawbuf), (unsigned)(q-transbuf), size));
  883.                         if (!uO.cflag && WriteError(transbuf,
  884.                             (unsigned)(q-transbuf), G.outfile))
  885.                             return disk_error(__G);
  886.                         else if (uO.cflag && (*G.message)((zvoid *)&G,
  887.                                  transbuf, (ulg)(q-transbuf), 0))
  888.                             return 0;
  889.                         q = transbuf;
  890.                         continue;
  891.                     }
  892. #endif /* SMALL_MEM || MED_MEM */
  893.             }
  894.         }
  895.  
  896.     /*-----------------------------------------------------------------------
  897.         Done translating:  write whatever we've got to file (or screen).
  898.       -----------------------------------------------------------------------*/
  899.  
  900.         Trace((stderr, "p - rawbuf = %u   q-transbuf = %u   size = %lu\n",
  901.           (unsigned)(p-rawbuf), (unsigned)(q-transbuf), size));
  902.         if (q > transbuf) {
  903. #ifdef DLL
  904.             if (G.redirect_data)
  905.                 writeToMemory(__G__ transbuf, (unsigned)(q-transbuf));
  906.             else
  907. #endif
  908.             if (!uO.cflag && WriteError(transbuf, (unsigned)(q-transbuf),
  909.                 G.outfile))
  910.                 return disk_error(__G);
  911.             else if (uO.cflag && (*G.message)((zvoid *)&G, transbuf,
  912.                 (ulg)(q-transbuf), 0))
  913.                 return 0;
  914.         }
  915.     }
  916.  
  917.     return 0;
  918.  
  919. } /* end function flush() */
  920.  
  921.  
  922.  
  923.  
  924.  
  925. /*************************/
  926. /* Function disk_error() */
  927. /*************************/
  928.  
  929. static int disk_error(__G)
  930.     __GDEF
  931. {
  932.     /* OK to use slide[] here because this file is finished regardless */
  933.     Info(slide, 0x4a1, ((char *)slide, LoadFarString(DiskFullQuery),
  934.       FnFilter1(G.filename)));
  935.  
  936. #ifndef WINDLL
  937.     fgets(G.answerbuf, 9, stdin);
  938.     if (*G.answerbuf == 'y')   /* stop writing to this file */
  939.         G.disk_full = 1;       /*  (outfile bad?), but new OK */
  940.     else
  941. #endif
  942.         G.disk_full = 2;       /* no:  exit program */
  943.  
  944.     return PK_DISK;
  945.  
  946. } /* end function disk_error() */
  947.  
  948. #endif /* !VMS */
  949.  
  950.  
  951.  
  952.  
  953.  
  954. /*****************************/
  955. /* Function UzpMessagePrnt() */
  956. /*****************************/
  957.  
  958. int UZ_EXP UzpMessagePrnt(pG, buf, size, flag)
  959.     zvoid *pG;   /* globals struct:  always passed */
  960.     uch *buf;    /* preformatted string to be printed */
  961.     ulg size;    /* length of string (may include nulls) */
  962.     int flag;    /* flag bits */
  963. {
  964.     /* IMPORTANT NOTE:
  965.      *    The name of the first parameter of UzpMessagePrnt(), which passes
  966.      *    the "Uz_Globs" address, >>> MUST <<< be identical to the string
  967.      *    expansion of the __G__ macro in the REENTRANT case (see globals.h).
  968.      *    This name identity is mandatory for the LoadFarString() macro
  969.      *    (in the SMALL_MEM case) !!!
  970.      */
  971.     int error;
  972.     uch *q=buf, *endbuf=buf+(unsigned)size;
  973. #ifdef MORE
  974.     uch *p=buf-1;
  975. #endif
  976.     FILE *outfp;
  977.  
  978.  
  979. /*---------------------------------------------------------------------------
  980.     These tests are here to allow fine-tuning of UnZip's output messages,
  981.     but none of them will do anything without setting the appropriate bit
  982.     in the flag argument of every Info() statement which is to be turned
  983.     *off*.  That is, all messages are currently turned on for all ports.
  984.     To turn off *all* messages, use the UzpMessageNull() function instead
  985.     of this one.
  986.   ---------------------------------------------------------------------------*/
  987.  
  988. #if (defined(OS2) && defined(DLL))
  989.     if (MSG_NO_DLL2(flag))  /* if OS/2 DLL bit is set, do NOT print this msg */
  990.         return 0;
  991. #endif
  992. #ifdef WINDLL
  993.     if (MSG_NO_WDLL(flag))
  994.         return 0;
  995. #endif
  996. #ifdef WINDLL
  997.     if (MSG_NO_WGUI(flag))
  998.         return 0;
  999. #endif
  1000. /*
  1001. #ifdef ACORN_GUI
  1002.     if (MSG_NO_AGUI(flag))
  1003.         return 0;
  1004. #endif
  1005.  */
  1006. #ifdef DLL                 /* don't display message if data is redirected */
  1007.     if (((Uz_Globs *)pG)->redirect_data &&
  1008.         !((Uz_Globs *)pG)->redirect_text)
  1009.         return 0;
  1010. #endif
  1011.  
  1012.     if (MSG_STDERR(flag) && !((Uz_Globs *)pG)->UzO.tflag)
  1013.         outfp = (FILE *)stderr;
  1014.     else
  1015.         outfp = (FILE *)stdout;
  1016.  
  1017. #ifdef QUERY_TRNEWLN
  1018.     /* some systems require termination of query prompts with '\n' to force
  1019.      * immediate display */
  1020.     if (MSG_MNEWLN(flag)) {   /* assumes writable buffer (e.g., slide[]) */
  1021.         *endbuf++ = '\n';     /*  with room for one more char at end of buf */
  1022.         ++size;               /*  (safe assumption:  only used for four */
  1023.     }                         /*  short queries in extract.c and fileio.c) */
  1024. #endif
  1025.  
  1026.     if (MSG_TNEWLN(flag)) {   /* again assumes writable buffer:  fragile... */
  1027.         if ((!size && !((Uz_Globs *)pG)->sol) ||
  1028.             (size && (endbuf[-1] != '\n')))
  1029.         {
  1030.             *endbuf++ = '\n';
  1031.             ++size;
  1032.         }
  1033.     }
  1034.  
  1035. #ifdef MORE
  1036.     /* room for --More-- and one line of overlap: */
  1037.     ((Uz_Globs *)pG)->height = SCREENLINES - 2;
  1038. #endif
  1039.  
  1040.     if (MSG_LNEWLN(flag) && !((Uz_Globs *)pG)->sol) {
  1041.         /* not at start of line:  want newline */
  1042. #ifdef OS2DLL
  1043.         if (!((Uz_Globs *)pG)->redirect_text) {
  1044. #endif
  1045.             putc('\n', outfp);
  1046.             fflush(outfp);
  1047. #ifdef MORE
  1048.             if (((Uz_Globs *)pG)->M_flag)
  1049.             {
  1050.                 ++((Uz_Globs *)pG)->numlines;
  1051.                 if (((Uz_Globs *)pG)->numlines %
  1052.                     ((Uz_Globs *)pG)->height == 0L)    /* GRR: fix */
  1053.                     (*((Uz_Globs *)pG)->mpause)((zvoid *)pG,
  1054.                       LoadFarString(MorePrompt), 1);
  1055.             }
  1056. #endif /* MORE */
  1057.             if (MSG_STDERR(flag) && ((Uz_Globs *)pG)->UzO.tflag &&
  1058.                 !isatty(1) && isatty(2))
  1059.             {
  1060.                 /* error output from testing redirected:  also send to stderr */
  1061.                 putc('\n', stderr);
  1062.                 fflush(stderr);
  1063.             }
  1064. #ifdef OS2DLL
  1065.         } else
  1066.            REDIRECTC('\n');
  1067. #endif
  1068.         ((Uz_Globs *)pG)->sol = TRUE;
  1069.     }
  1070.  
  1071.     /* put zipfile name, filename and/or error/warning keywords here */
  1072.  
  1073. #ifdef MORE
  1074.     if (((Uz_Globs *)pG)->M_flag
  1075. #ifdef OS2DLL
  1076.          && !((Uz_Globs *)pG)->redirect_text
  1077. #endif
  1078.                                                  )
  1079.     {
  1080.         while (++p < endbuf) {
  1081.             if (*p == '\n') {
  1082.                 ++((Uz_Globs *)pG)->numlines;
  1083.                 if (((Uz_Globs *)pG)->numlines %
  1084.                     ((Uz_Globs *)pG)->height == 0L)    /* GRR: fix */
  1085.                 {
  1086.                     if ((error = WriteError(q, p-q+1, outfp)) != 0)
  1087.                         return error;
  1088.                     fflush(outfp);
  1089.                     ((Uz_Globs *)pG)->sol = TRUE;
  1090.                     q = p + 1;
  1091.                     (*((Uz_Globs *)pG)->mpause)((zvoid *)pG,
  1092.                       LoadFarString(MorePrompt), 1);
  1093.                 }
  1094.             }
  1095.         } /* end while */
  1096.         size = (ulg)(p - q);   /* remaining text */
  1097.     }
  1098. #endif /* MORE */
  1099.  
  1100.     if (size) {
  1101. #ifdef OS2DLL
  1102.         if (!((Uz_Globs *)pG)->redirect_text) {
  1103. #endif
  1104.             if ((error = WriteError(q, size, outfp)) != 0)
  1105.                 return error;
  1106.             fflush(outfp);
  1107.             if (MSG_STDERR(flag) && ((Uz_Globs *)pG)->UzO.tflag &&
  1108.                 !isatty(1) && isatty(2))
  1109.             {
  1110.                 /* error output from testing redirected:  also send to stderr */
  1111.                 if ((error = WriteError(q, size, stderr)) != 0)
  1112.                     return error;
  1113.                 fflush(stderr);
  1114.             }
  1115. #ifdef OS2DLL
  1116.         } else {                /* GRR:  this is ugly:  hide with macro */
  1117.             if ((error = REDIRECTPRINT(q, size)) != 0)
  1118.                 return error;
  1119.         }
  1120. #endif
  1121.         ((Uz_Globs *)pG)->sol = (endbuf[-1] == '\n');
  1122.     }
  1123.     return 0;
  1124.  
  1125. } /* end function UzpMessagePrnt() */
  1126.  
  1127.  
  1128.  
  1129.  
  1130.  
  1131. #ifdef DLL
  1132.  
  1133. /*****************************/
  1134. /* Function UzpMessageNull() */  /* convenience routine for no output at all */
  1135. /*****************************/
  1136.  
  1137. int UZ_EXP UzpMessageNull(pG, buf, size, flag)
  1138.     zvoid *pG;    /* globals struct:  always passed */
  1139.     uch *buf;     /* preformatted string to be printed */
  1140.     ulg size;     /* length of string (may include nulls) */
  1141.     int flag;     /* flag bits */
  1142. {
  1143.     return 0;
  1144.  
  1145. } /* end function UzpMessageNull() */
  1146.  
  1147. #endif /* DLL */
  1148.  
  1149.  
  1150.  
  1151.  
  1152.  
  1153. /***********************/
  1154. /* Function UzpInput() */   /* GRR:  this is a placeholder for now */
  1155. /***********************/
  1156.  
  1157. int UZ_EXP UzpInput(pG, buf, size, flag)
  1158.     zvoid *pG;    /* globals struct:  always passed */
  1159.     uch *buf;     /* preformatted string to be printed */
  1160.     int *size;    /* (address of) size of buf and of returned string */
  1161.     int flag;     /* flag bits (bit 0: no echo) */
  1162. {
  1163.     /* tell picky compilers to shut up about "unused variable" warnings */
  1164.     pG = pG; buf = buf; flag = flag;
  1165.  
  1166.     *size = 0;
  1167.     return 0;
  1168.  
  1169. } /* end function UzpInput() */
  1170.  
  1171.  
  1172.  
  1173.  
  1174.  
  1175. #if (!defined(WINDLL) && !defined(MACOS))
  1176.  
  1177. /***************************/
  1178. /* Function UzpMorePause() */
  1179. /***************************/
  1180.  
  1181. void UZ_EXP UzpMorePause(pG, prompt, flag)
  1182.     zvoid *pG;            /* globals struct:  always passed */
  1183.     ZCONST char *prompt;  /* "--More--" prompt */
  1184.     int flag;             /* 0 = any char OK; 1 = accept only '\n', ' ', q */
  1185. {
  1186.     uch c;
  1187.  
  1188. /*---------------------------------------------------------------------------
  1189.     Print a prompt and wait for the user to press a key, then erase prompt
  1190.     if possible.
  1191.   ---------------------------------------------------------------------------*/
  1192.  
  1193.     if (!((Uz_Globs *)pG)->sol)
  1194.         fprintf(stderr, "\n");
  1195.     /* numlines may or may not be used: */
  1196.     fprintf(stderr, prompt, ((Uz_Globs *)pG)->numlines);
  1197.     fflush(stderr);
  1198.     if (flag & 1) {
  1199.         do {
  1200.             c = (uch)FGETCH(0);
  1201.         } while (c != '\r' && c != '\n' && c != ' ' && c != 'q' && c != 'Q');
  1202.     } else
  1203.         c = (uch)FGETCH(0);
  1204.  
  1205.     /* newline was not echoed, so cover up prompt line */
  1206.     fprintf(stderr, LoadFarString(HidePrompt));
  1207.     fflush(stderr);
  1208.  
  1209.     if (ToLower(c) == 'q') {
  1210.         DESTROYGLOBALS()
  1211.         EXIT(PK_COOL);
  1212.     }
  1213.  
  1214.     ((Uz_Globs *)pG)->sol = TRUE;
  1215.  
  1216. } /* end function UzpMorePause() */
  1217.  
  1218. #endif /* !WINDLL && !MACOS */
  1219.  
  1220.  
  1221.  
  1222.  
  1223. #ifndef WINDLL
  1224.  
  1225. /**************************/
  1226. /* Function UzpPassword() */
  1227. /**************************/
  1228.  
  1229. int UZ_EXP UzpPassword (pG, rcnt, pwbuf, size, zfn, efn)
  1230.     zvoid *pG;         /* pointer to UnZip's internal global vars */
  1231.     int *rcnt;         /* retry counter */
  1232.     char *pwbuf;       /* buffer for password */
  1233.     int size;          /* size of password buffer */
  1234.     ZCONST char *zfn;  /* name of zip archive */
  1235.     ZCONST char *efn;  /* name of archive entry being processed */
  1236. {
  1237. #if CRYPT
  1238.     int r = IZ_PW_ENTERED;
  1239.     char *m;
  1240.     char *prompt;
  1241.  
  1242. #ifndef REENTRANT
  1243.     /* tell picky compilers to shut up about "unused variable" warnings */
  1244.     pG = pG;
  1245. #endif
  1246.  
  1247.     if (*rcnt == 0) {           /* First call for current entry */
  1248.         *rcnt = 2;
  1249.         if ((prompt = (char *)malloc(2*FILNAMSIZ + 15)) != (char *)NULL) {
  1250.             sprintf(prompt, LoadFarString(PasswPrompt),
  1251.                     FnFilter1(zfn), FnFilter2(efn));
  1252.             m = prompt;
  1253.         } else
  1254.             m = (char *)LoadFarString(PasswPrompt2);
  1255.     } else {                    /* Retry call, previous password was wrong */
  1256.         (*rcnt)--;
  1257.         prompt = NULL;
  1258.         m = (char *)LoadFarString(PasswRetry);
  1259.     }
  1260.  
  1261.     m = getp(__G__ m, pwbuf, size);
  1262.     if (prompt != (char *)NULL) {
  1263.         free(prompt);
  1264.     }
  1265.     if (m == (char *)NULL) {
  1266.         r = IZ_PW_ERROR;
  1267.     }
  1268.     else if (*pwbuf == '\0') {
  1269.         r = IZ_PW_CANCELALL;
  1270.     }
  1271.     return r;
  1272.  
  1273. #else /* !CRYPT */
  1274.     /* tell picky compilers to shut up about "unused variable" warnings */
  1275.     pG = pG; rcnt = rcnt; pwbuf = pwbuf; size = size; zfn = zfn; efn = efn;
  1276.  
  1277.     return IZ_PW_ERROR;  /* internal error; function should never get called */
  1278. #endif /* ?CRYPT */
  1279.  
  1280. } /* end function UzpPassword() */
  1281.  
  1282.  
  1283.  
  1284.  
  1285.  
  1286. /**********************/
  1287. /* Function handler() */
  1288. /**********************/
  1289.  
  1290. void handler(signal)   /* upon interrupt, turn on echo and exit cleanly */
  1291.     int signal;
  1292. {
  1293.     GETGLOBALS();
  1294.  
  1295. #if !(defined(SIGBUS) || defined(SIGSEGV))      /* add a newline if not at */
  1296.     (*G.message)((zvoid *)&G, slide, 0L, 0x41); /*  start of line (to stderr; */
  1297. #endif                                          /*  slide[] should be safe) */
  1298.  
  1299.     echon();
  1300.  
  1301. #ifdef SIGBUS
  1302.     if (signal == SIGBUS) {
  1303.         Info(slide, 0x421, ((char *)slide, LoadFarString(ZipfileCorrupt),
  1304.           "bus error"));
  1305.         DESTROYGLOBALS()
  1306.         EXIT(PK_BADERR);
  1307.     }
  1308. #endif /* SIGBUS */
  1309.  
  1310. #ifdef SIGSEGV
  1311.     if (signal == SIGSEGV) {
  1312.         Info(slide, 0x421, ((char *)slide, LoadFarString(ZipfileCorrupt),
  1313.           "segmentation violation"));
  1314.         DESTROYGLOBALS()
  1315.         EXIT(PK_BADERR);
  1316.     }
  1317. #endif /* SIGSEGV */
  1318.  
  1319.     /* probably ctrl-C */
  1320.     DESTROYGLOBALS()
  1321. #if defined(AMIGA) && defined(__SASC)
  1322.     _abort();
  1323. #endif
  1324.     EXIT(IZ_CTRLC);       /* was EXIT(0), then EXIT(PK_ERR) */
  1325. }
  1326.  
  1327. #endif /* !WINDLL */
  1328.  
  1329.  
  1330.  
  1331.  
  1332. #if (!defined(VMS) && !defined(CMS_MVS))
  1333. #if (!defined(OS2) || defined(TIMESTAMP))
  1334.  
  1335. #if (!defined(HAVE_MKTIME) || defined(AMIGA) || defined(WIN32))
  1336. /* also used in amiga/filedate.c and win32/win32.c */
  1337. ZCONST ush ydays[] =
  1338.     { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 };
  1339. #endif
  1340.  
  1341. /*******************************/
  1342. /* Function dos_to_unix_time() */ /* used for freshening/updating/timestamps */
  1343. /*******************************/
  1344.  
  1345. time_t dos_to_unix_time(dosdatetime)
  1346.     ulg dosdatetime;
  1347. {
  1348.     time_t m_time;
  1349.  
  1350. #ifdef HAVE_MKTIME
  1351.  
  1352.     ZCONST time_t now = time(NULL);
  1353.     struct tm *tm;
  1354. #   define YRBASE  1900
  1355.  
  1356.     tm = localtime(&now);
  1357.     tm->tm_isdst = -1;          /* let mktime determine if DST is in effect */
  1358.  
  1359.     /* dissect date */
  1360.     tm->tm_year = ((int)(dosdatetime >> 25) & 0x7f) + (1980 - YRBASE);
  1361.     tm->tm_mon  = ((int)(dosdatetime >> 21) & 0x0f) - 1;
  1362.     tm->tm_mday = ((int)(dosdatetime >> 16) & 0x1f);
  1363.  
  1364.     /* dissect time */
  1365.     tm->tm_hour = (int)((unsigned)dosdatetime >> 11) & 0x1f;
  1366.     tm->tm_min  = (int)((unsigned)dosdatetime >> 5) & 0x3f;
  1367.     tm->tm_sec  = (int)((unsigned)dosdatetime << 1) & 0x3e;
  1368.  
  1369.     m_time = mktime(tm);
  1370.     NATIVE_TO_TIMET(m_time)     /* NOP unless MSC 7.0 or Macintosh */
  1371.     TTrace((stderr, "  final m_time  =       %lu\n", (ulg)m_time));
  1372.  
  1373. #else /* !HAVE_MKTIME */
  1374.  
  1375.     int yr, mo, dy, hh, mm, ss;
  1376. #ifdef TOPS20
  1377. #   define YRBASE  1900
  1378.     struct tmx *tmx;
  1379.     char temp[20];
  1380. #else /* !TOPS20 */
  1381. #   define YRBASE  1970
  1382.     int leap;
  1383.     unsigned days;
  1384.     struct tm *tm;
  1385. #if (!defined(MACOS) && !defined(RISCOS) && !defined(QDOS) && !defined(TANDEM))
  1386. #ifdef WIN32
  1387.     TIME_ZONE_INFORMATION tzinfo;
  1388.     DWORD res;
  1389. #else /* ! WIN32 */
  1390. #ifndef BSD4_4   /* GRR:  change to !defined(MODERN) ? */
  1391. #if (defined(BSD) || defined(MTS) || defined(__GO32__))
  1392.     struct timeb tbp;
  1393. #else /* !(BSD || MTS || __GO32__) */
  1394. #ifdef DECLARE_TIMEZONE
  1395.     extern time_t timezone;
  1396. #endif
  1397. #endif /* ?(BSD || MTS || __GO32__) */
  1398. #endif /* !BSD4_4 */
  1399. #endif /* ?WIN32 */
  1400. #endif /* !MACOS && !RISCOS && !QDOS && !TANDEM */
  1401. #endif /* ?TOPS20 */
  1402.  
  1403.  
  1404.     /* dissect date */
  1405.     yr = ((int)(dosdatetime >> 25) & 0x7f) + (1980 - YRBASE);
  1406.     mo = ((int)(dosdatetime >> 21) & 0x0f) - 1;
  1407.     dy = ((int)(dosdatetime >> 16) & 0x1f) - 1;
  1408.  
  1409.     /* dissect time */
  1410.     hh = (int)((unsigned)dosdatetime >> 11) & 0x1f;
  1411.     mm = (int)((unsigned)dosdatetime >> 5) & 0x3f;
  1412.     ss = (int)((unsigned)dosdatetime & 0x1f) * 2;
  1413.  
  1414. #ifdef TOPS20
  1415.     tmx = (struct tmx *)malloc(sizeof(struct tmx));
  1416.     sprintf (temp, "%02d/%02d/%02d %02d:%02d:%02d", mo+1, dy+1, yr, hh, mm, ss);
  1417.     time_parse(temp, tmx, (char *)0);
  1418.     m_time = time_make(tmx);
  1419.     free(tmx);
  1420.  
  1421. #else /* !TOPS20 */
  1422.  
  1423. /*---------------------------------------------------------------------------
  1424.     Calculate the number of seconds since the epoch, usually 1 January 1970.
  1425.   ---------------------------------------------------------------------------*/
  1426.  
  1427.     /* leap = # of leap yrs from YRBASE up to but not including current year */
  1428.     leap = ((yr + YRBASE - 1) / 4);   /* leap year base factor */
  1429.  
  1430.     /* calculate days from BASE to this year and add expired days this year */
  1431.     days = (yr * 365) + (leap - 492) + ydays[mo];
  1432.  
  1433.     /* if year is a leap year and month is after February, add another day */
  1434.     if ((mo > 1) && ((yr+YRBASE)%4 == 0) && ((yr+YRBASE) != 2100))
  1435.         ++days;                 /* OK through 2199 */
  1436.  
  1437.     /* convert date & time to seconds relative to 00:00:00, 01/01/YRBASE */
  1438.     m_time = (time_t)((unsigned long)(days + dy) * 86400L +
  1439.                       (unsigned long)hh * 3600L +
  1440.                       (unsigned long)(mm * 60 + ss));
  1441.       /* - 1;   MS-DOS times always rounded up to nearest even second */
  1442.     TTrace((stderr, "dos_to_unix_time:\n"));
  1443.     TTrace((stderr, "  m_time before timezone = %lu\n", (ulg)m_time));
  1444.  
  1445. /*---------------------------------------------------------------------------
  1446.     Adjust for local standard timezone offset.
  1447.   ---------------------------------------------------------------------------*/
  1448.  
  1449. #if (!defined(MACOS) && !defined(RISCOS) && !defined(QDOS) && !defined(TANDEM))
  1450. #ifdef WIN32
  1451.     /* account for timezone differences */
  1452.     res = GetTimeZoneInformation(&tzinfo);
  1453.     if (res != TIME_ZONE_ID_UNKNOWN)
  1454.     {
  1455.     m_time += 60*(tzinfo.Bias);
  1456. #else /* !WIN32 */
  1457. #if (defined(BSD) || defined(MTS) || defined(__GO32__))
  1458. #ifdef BSD4_4
  1459.     if ( (dosdatetime >= DOSTIME_2038_01_18) &&
  1460.          (m_time < (time_t)0x70000000L) )
  1461.         m_time = U_TIME_T_MAX;  /* saturate in case of (unsigned) overflow */
  1462.     if (m_time < (time_t)0L)    /* a converted DOS time cannot be negative */
  1463.         m_time = S_TIME_T_MAX;  /*  -> saturate at max signed time_t value */
  1464.     if ((tm = localtime(&m_time)) != (struct tm *)NULL)
  1465.         m_time -= tm->tm_gmtoff;                /* sec. EAST of GMT: subtr. */
  1466. #else /* !(BSD4_4 */
  1467.     ftime(&tbp);                                /* get `timezone' */
  1468.     m_time += tbp.timezone * 60L;               /* seconds WEST of GMT:  add */
  1469. #endif /* ?(BSD4_4 || __EMX__) */
  1470. #else /* !(BSD || MTS || __GO32__) */
  1471.     /* tzset was already called at start of process_zipfiles() */
  1472.     /* tzset(); */              /* set `timezone' variable */
  1473. #ifndef __BEOS__                /* BeOS DR8 has no timezones... */
  1474.     m_time += timezone;         /* seconds WEST of GMT:  add */
  1475. #endif
  1476. #endif /* ?(BSD || MTS || __GO32__) */
  1477. #endif /* ?WIN32 */
  1478.     TTrace((stderr, "  m_time after timezone =  %lu\n", (ulg)m_time));
  1479.  
  1480. /*---------------------------------------------------------------------------
  1481.     Adjust for local daylight savings (summer) time.
  1482.   ---------------------------------------------------------------------------*/
  1483.  
  1484. #ifndef BSD4_4  /* (DST already added to tm_gmtoff, so skip tm_isdst) */
  1485.     if ( (dosdatetime >= DOSTIME_2038_01_18) &&
  1486.          (m_time < (time_t)0x70000000L) )
  1487.         m_time = U_TIME_T_MAX;  /* saturate in case of (unsigned) overflow */
  1488.     if (m_time < (time_t)0L)    /* a converted DOS time cannot be negative */
  1489.         m_time = S_TIME_T_MAX;  /*  -> saturate at max signed time_t value */
  1490.     TIMET_TO_NATIVE(m_time)     /* NOP unless MSC 7.0 or Macintosh */
  1491.     if (((tm = localtime((time_t *)&m_time)) != NULL) && tm->tm_isdst)
  1492. #ifdef WIN32
  1493.         m_time += 60L * tzinfo.DaylightBias;    /* adjust with DST bias */
  1494.     else
  1495.         m_time += 60L * tzinfo.StandardBias;    /* add StdBias (normally 0) */
  1496. #else
  1497.         m_time -= 60L * 60L;    /* adjust for daylight savings time */
  1498. #endif
  1499.     NATIVE_TO_TIMET(m_time)     /* NOP unless MSC 7.0 or Macintosh */
  1500.     TTrace((stderr, "  m_time after DST =       %lu\n", (ulg)m_time));
  1501. #endif /* !BSD4_4 */
  1502. #ifdef WIN32
  1503.     }
  1504. #endif
  1505. #endif /* !MACOS && !RISCOS && !QDOS && !TANDEM */
  1506. #endif /* ?TOPS20 */
  1507.  
  1508. #endif /* ?HAVE_MKTIME */
  1509.  
  1510.     if ( (dosdatetime >= DOSTIME_2038_01_18) &&
  1511.          (m_time < (time_t)0x70000000L) )
  1512.         m_time = U_TIME_T_MAX;  /* saturate in case of (unsigned) overflow */
  1513.     if (m_time < (time_t)0L)    /* a converted DOS time cannot be negative */
  1514.         m_time = S_TIME_T_MAX;  /*  -> saturate at max signed time_t value */
  1515.  
  1516.     return m_time;
  1517.  
  1518. } /* end function dos_to_unix_time() */
  1519.  
  1520. #endif /* !OS2 || TIMESTAMP */
  1521. #endif /* !VMS && !CMS_MVS */
  1522.  
  1523.  
  1524.  
  1525. #if (!defined(VMS) && !defined(OS2) && !defined(CMS_MVS))
  1526.  
  1527. /******************************/
  1528. /* Function check_for_newer() */  /* used for overwriting/freshening/updating */
  1529. /******************************/
  1530.  
  1531. int check_for_newer(__G__ filename)  /* return 1 if existing file is newer */
  1532.     __GDEF                           /*  or equal; 0 if older; -1 if doesn't */
  1533.     char *filename;                  /*  exist yet */
  1534. {
  1535.     time_t existing, archive;
  1536. #ifdef USE_EF_UT_TIME
  1537.     iztimes z_utime;
  1538. #endif
  1539. #ifdef AOS_VS
  1540.     long    dyy, dmm, ddd, dhh, dmin, dss;
  1541.  
  1542.  
  1543.     dyy = (lrec.last_mod_dos_datetime >> 25) + 1980;
  1544.     dmm = (lrec.last_mod_dos_datetime >> 21) & 0x0f;
  1545.     ddd = (lrec.last_mod_dos_datetime >> 16) & 0x1f;
  1546.     dhh = (lrec.last_mod_dos_datetime >> 11) & 0x1f;
  1547.     dmin = (lrec.last_mod_dos_datetime >> 5) & 0x3f;
  1548.     dss = (lrec.last_mod_dos_datetime & 0x1f) * 2;
  1549.  
  1550.     /* under AOS/VS, file times can only be set at creation time,
  1551.      * with the info in a special DG format.  Make sure we can create
  1552.      * it here - we delete it later & re-create it, whether or not
  1553.      * it exists now.
  1554.      */
  1555.     if (!zvs_create(filename, (((ulg)dgdate(dmm, ddd, dyy)) << 16) |
  1556.         (dhh*1800L + dmin*30L + dss/2L), -1L, -1L, (char *) -1, -1, -1, -1))
  1557.         return DOES_NOT_EXIST;
  1558. #endif /* AOS_VS */
  1559.  
  1560.     Trace((stderr, "check_for_newer:  doing stat(%s)\n", FnFilter1(filename)));
  1561.     if (SSTAT(filename, &G.statbuf)) {
  1562.         Trace((stderr,
  1563.           "check_for_newer:  stat(%s) returns %d:  file does not exist\n",
  1564.           FnFilter1(filename), SSTAT(filename, &G.statbuf)));
  1565. #ifdef SYMLINKS
  1566.         Trace((stderr, "check_for_newer:  doing lstat(%s)\n",
  1567.           FnFilter1(filename)));
  1568.         /* GRR OPTION:  could instead do this test ONLY if G.symlnk is true */
  1569.         if (lstat(filename, &G.statbuf) == 0) {
  1570.             Trace((stderr,
  1571.               "check_for_newer:  lstat(%s) returns 0:  symlink does exist\n",
  1572.               FnFilter1(filename)));
  1573.             if (QCOND2 && !uO.overwrite_all)
  1574.                 Info(slide, 0, ((char *)slide, LoadFarString(FileIsSymLink),
  1575.                   FnFilter1(filename), " with no real file"));
  1576.             return EXISTS_AND_OLDER;   /* symlink dates are meaningless */
  1577.         }
  1578. #endif /* SYMLINKS */
  1579.         return DOES_NOT_EXIST;
  1580.     }
  1581.     Trace((stderr, "check_for_newer:  stat(%s) returns 0:  file exists\n",
  1582.       FnFilter1(filename)));
  1583.  
  1584. #ifdef SYMLINKS
  1585.     /* GRR OPTION:  could instead do this test ONLY if G.symlnk is true */
  1586.     if (lstat(filename, &G.statbuf) == 0 && S_ISLNK(G.statbuf.st_mode)) {
  1587.         Trace((stderr, "check_for_newer:  %s is a symbolic link\n",
  1588.           FnFilter1(filename)));
  1589.         if (QCOND2 && !uO.overwrite_all)
  1590.             Info(slide, 0, ((char *)slide, LoadFarString(FileIsSymLink),
  1591.               FnFilter1(filename), ""));
  1592.         return EXISTS_AND_OLDER;   /* symlink dates are meaningless */
  1593.     }
  1594. #endif /* SYMLINKS */
  1595.  
  1596.     NATIVE_TO_TIMET(G.statbuf.st_mtime)   /* NOP unless MSC 7.0 or Macintosh */
  1597.  
  1598. #ifdef USE_EF_UT_TIME
  1599.     /* The `Unix extra field mtime' should be used for comparison with the
  1600.      * time stamp of the existing file >>>ONLY<<< when the EF info is also
  1601.      * used to set the modification time of the extracted file.
  1602.      */
  1603.     if (G.extra_field &&
  1604. #ifdef IZ_CHECK_TZ
  1605.         G.tz_is_valid &&
  1606. #endif
  1607.         (ef_scan_for_izux(G.extra_field, G.lrec.extra_field_length, 0,
  1608.                           G.lrec.last_mod_dos_datetime, &z_utime, NULL)
  1609.          & EB_UT_FL_MTIME))
  1610.     {
  1611.         TTrace((stderr, "check_for_newer:  using Unix extra field mtime\n"));
  1612.         existing = G.statbuf.st_mtime;
  1613.         archive  = z_utime.mtime;
  1614.     } else {
  1615.         /* round up existing filetime to nearest 2 seconds for comparison,
  1616.          * but saturate in case of arithmetic overflow
  1617.          */
  1618.         existing = ((G.statbuf.st_mtime & 1) &&
  1619.                     (G.statbuf.st_mtime + 1 > G.statbuf.st_mtime)) ?
  1620.                    G.statbuf.st_mtime + 1 : G.statbuf.st_mtime;
  1621.         archive  = dos_to_unix_time(G.lrec.last_mod_dos_datetime);
  1622.     }
  1623. #else /* !USE_EF_UT_TIME */
  1624.     /* round up existing filetime to nearest 2 seconds for comparison,
  1625.      * but saturate in case of arithmetic overflow
  1626.      */
  1627.     existing = ((G.statbuf.st_mtime & 1) &&
  1628.                 (G.statbuf.st_mtime + 1 > G.statbuf.st_mtime)) ?
  1629.                G.statbuf.st_mtime + 1 : G.statbuf.st_mtime;
  1630.     archive  = dos_to_unix_time(G.lrec.last_mod_dos_datetime);
  1631. #endif /* ?USE_EF_UT_TIME */
  1632.  
  1633.     TTrace((stderr, "check_for_newer:  existing %lu, archive %lu, e-a %ld\n",
  1634.       (ulg)existing, (ulg)archive, (long)(existing-archive)));
  1635.  
  1636.     return (existing >= archive);
  1637.  
  1638. } /* end function check_for_newer() */
  1639.  
  1640. #endif /* !VMS && !OS2 && !CMS_MVS */
  1641.  
  1642.  
  1643.  
  1644.  
  1645.  
  1646. /************************/
  1647. /* Function do_string() */
  1648. /************************/
  1649.  
  1650. int do_string(__G__ len, option)      /* return PK-type error code */
  1651.     __GDEF
  1652.     unsigned int len;           /* without prototype, ush converted to this */
  1653.     int option;
  1654. {
  1655.     long comment_bytes_left, block_length;
  1656.     int error=PK_OK;
  1657.     ush extra_len;
  1658. #ifdef AMIGA
  1659.     char tmp_fnote[2 * AMIGA_FILENOTELEN];   /* extra room for squozen chars */
  1660. #endif
  1661.  
  1662.  
  1663. /*---------------------------------------------------------------------------
  1664.     This function processes arbitrary-length (well, usually) strings.  Four
  1665.     options are allowed:  SKIP, wherein the string is skipped (pretty logical,
  1666.     eh?); DISPLAY, wherein the string is printed to standard output after un-
  1667.     dergoing any necessary or unnecessary character conversions; DS_FN,
  1668.     wherein the string is put into the filename[] array after undergoing ap-
  1669.     propriate conversions (including case-conversion, if that is indicated:
  1670.     see the global variable pInfo->lcflag); and EXTRA_FIELD, wherein the
  1671.     `string' is assumed to be an extra field and is copied to the (freshly
  1672.     malloced) buffer G.extra_field.  The third option should be OK since
  1673.     filename is dimensioned at 1025, but we check anyway.
  1674.  
  1675.     The string, by the way, is assumed to start at the current file-pointer
  1676.     position; its length is given by len.  So start off by checking length
  1677.     of string:  if zero, we're already done.
  1678.   ---------------------------------------------------------------------------*/
  1679.  
  1680.     if (!len)
  1681.         return PK_COOL;
  1682.  
  1683.     switch (option) {
  1684.  
  1685.     /*
  1686.      * First case:  print string on standard output.  First set loop vari-
  1687.      * ables, then loop through the comment in chunks of OUTBUFSIZ bytes,
  1688.      * converting formats and printing as we go.  The second half of the
  1689.      * loop conditional was added because the file might be truncated, in
  1690.      * which case comment_bytes_left will remain at some non-zero value for
  1691.      * all time.  outbuf and slide are used as scratch buffers because they
  1692.      * are available (we should be either before or in between any file pro-
  1693.      * cessing).
  1694.      */
  1695.  
  1696.     case DISPLAY:
  1697.     case DISPL_8:
  1698.         comment_bytes_left = len;
  1699.         block_length = OUTBUFSIZ;    /* for the while statement, first time */
  1700.         while (comment_bytes_left > 0 && block_length > 0) {
  1701.             register uch *p = G.outbuf;
  1702.             register uch *q = G.outbuf;
  1703.  
  1704.             if ((block_length = readbuf(__G__ (char *)G.outbuf,
  1705.                    (unsigned) MIN((long)OUTBUFSIZ, comment_bytes_left))) == 0)
  1706.                 return PK_EOF;
  1707.             comment_bytes_left -= block_length;
  1708.  
  1709.             /* this is why we allocated an extra byte for outbuf:  terminate
  1710.              *  with zero (ASCIIZ) */
  1711.             G.outbuf[(unsigned)block_length] = '\0';
  1712.  
  1713.             /* remove all ASCII carriage returns from comment before printing
  1714.              * (since used before A_TO_N(), check for CR instead of '\r')
  1715.              */
  1716.             while (*p) {
  1717.                 while (*p == CR)
  1718.                     ++p;
  1719.                 *q++ = *p++;
  1720.             }
  1721.             /* could check whether (p - outbuf) == block_length here */
  1722.             *q = '\0';
  1723.  
  1724.             if (option == DISPL_8) {
  1725.                 /* translate the text coded in the entry's host-dependent
  1726.                    "extended ASCII" charset into the compiler's (system's)
  1727.                    internal text code page */
  1728.                 Ext_ASCII_TO_Native((char *)G.outbuf, G.pInfo->hostnum,
  1729.                                     G.crec.version_made_by[0]);
  1730. #ifdef WINDLL
  1731.                 /* translate to ANSI (RTL internal codepage may be OEM) */
  1732.                 INTERN_TO_ISO((char *)G.outbuf, (char *)G.outbuf);
  1733. #else /* !WINDLL */
  1734. #ifdef WIN32
  1735.                 /* Win9x console always uses OEM character coding, and
  1736.                    WinNT console is set to OEM charset by default, too */
  1737.                 INTERN_TO_OEM((char *)G.outbuf, (char *)G.outbuf);
  1738. #endif /* WIN32 */
  1739. #endif /* ?WINDLL */
  1740.             } else {
  1741.                 A_TO_N(G.outbuf);   /* translate string to native */
  1742.             }
  1743.  
  1744. #ifdef WINDLL
  1745.             /* ran out of local mem -- had to cheat */
  1746.             win_fprintf((zvoid *)&G, stdout, len, (char *)G.outbuf);
  1747.             win_fprintf((zvoid *)&G, stdout, 2, (char *)"\n\n");
  1748. #else /* !WINDLL */
  1749. #ifdef NOANSIFILT       /* GRR:  can ANSI be used with EBCDIC? */
  1750.             (*G.message)((zvoid *)&G, G.outbuf, (ulg)(q-G.outbuf), 0);
  1751. #else /* ASCII, filter out ANSI escape sequences and handle ^S (pause) */
  1752.             p = G.outbuf - 1;
  1753.             q = slide;
  1754.             while (*++p) {
  1755.                 int pause = FALSE;
  1756.  
  1757.                 if (*p == 0x1B) {          /* ASCII escape char */
  1758.                     *q++ = '^';
  1759.                     *q++ = '[';
  1760.                 } else if (*p == 0x13) {   /* ASCII ^S (pause) */
  1761.                     pause = TRUE;
  1762.                     if (p[1] == LF)        /* ASCII LF */
  1763.                         *q++ = *++p;
  1764.                     else if (p[1] == CR && p[2] == LF) {  /* ASCII CR LF */
  1765.                         *q++ = *++p;
  1766.                         *q++ = *++p;
  1767.                     }
  1768.                 } else
  1769.                     *q++ = *p;
  1770.                 if ((unsigned)(q-slide) > WSIZE-3 || pause) {   /* flush */
  1771.                     (*G.message)((zvoid *)&G, slide, (ulg)(q-slide), 0);
  1772.                     q = slide;
  1773.                     if (pause && G.extract_flag) /* don't pause for list/test */
  1774.                         (*G.mpause)((zvoid *)&G, LoadFarString(QuitPrompt), 0);
  1775.                 }
  1776.             }
  1777.             (*G.message)((zvoid *)&G, slide, (ulg)(q-slide), 0);
  1778. #endif /* ?NOANSIFILT */
  1779. #endif /* ?WINDLL */
  1780.         }
  1781.         /* add '\n' if not at start of line */
  1782.         (*G.message)((zvoid *)&G, slide, 0L, 0x40);
  1783.         break;
  1784.  
  1785.     /*
  1786.      * Second case:  read string into filename[] array.  The filename should
  1787.      * never ever be longer than FILNAMSIZ-1 (1024), but for now we'll check,
  1788.      * just to be sure.
  1789.      */
  1790.  
  1791.     case DS_FN:
  1792.         extra_len = 0;
  1793.         if (len >= FILNAMSIZ) {
  1794.             Info(slide, 0x401, ((char *)slide,
  1795.               LoadFarString(FilenameTooLongTrunc)));
  1796.             error = PK_WARN;
  1797.             extra_len = (ush)(len - FILNAMSIZ + 1);
  1798.             len = FILNAMSIZ - 1;
  1799.         }
  1800.         if (readbuf(__G__  G.filename, len) == 0)
  1801.             return PK_EOF;
  1802.         G.filename[len] = '\0';   /* terminate w/zero:  ASCIIZ */
  1803.  
  1804.         /* translate the Zip entry filename coded in host-dependent "extended
  1805.            ASCII" into the compiler's (system's) internal text code page */
  1806.         Ext_ASCII_TO_Native(G.filename, G.pInfo->hostnum,
  1807.                             G.crec.version_made_by[0]);
  1808.  
  1809.         if (G.pInfo->lcflag)      /* replace with lowercase filename */
  1810.             TOLOWER(G.filename, G.filename);
  1811.  
  1812.         if (G.pInfo->vollabel && len > 8 && G.filename[8] == '.') {
  1813.             char *p = G.filename+8;
  1814.             while (*p++)
  1815.                 p[-1] = *p;  /* disk label, and 8th char is dot:  remove dot */
  1816.         }
  1817.  
  1818.         if (!extra_len)         /* we're done here */
  1819.             break;
  1820.  
  1821.         /*
  1822.          * We truncated the filename, so print what's left and then fall
  1823.          * through to the SKIP routine.
  1824.          */
  1825.         Info(slide, 0x401, ((char *)slide, "[ %s ]\n", FnFilter1(G.filename)));
  1826.         len = extra_len;
  1827.         /*  FALL THROUGH...  */
  1828.  
  1829.     /*
  1830.      * Third case:  skip string, adjusting readbuf's internal variables
  1831.      * as necessary (and possibly skipping to and reading a new block of
  1832.      * data).
  1833.      */
  1834.  
  1835.     case SKIP:
  1836.         /* cur_zipfile_bufstart already takes account of extra_bytes, so don't
  1837.          * correct for it twice: */
  1838.         ZLSEEK(G.cur_zipfile_bufstart - G.extra_bytes +
  1839.                (G.inptr-G.inbuf) + len)
  1840.         break;
  1841.  
  1842.     /*
  1843.      * Fourth case:  assume we're at the start of an "extra field"; malloc
  1844.      * storage for it and read data into the allocated space.
  1845.      */
  1846.  
  1847.     case EXTRA_FIELD:
  1848.         if (G.extra_field != (uch *)NULL)
  1849.             free(G.extra_field);
  1850.         if ((G.extra_field = (uch *)malloc(len)) == (uch *)NULL) {
  1851.             Info(slide, 0x401, ((char *)slide, LoadFarString(ExtraFieldTooLong),
  1852.               len));
  1853.             /* cur_zipfile_bufstart already takes account of extra_bytes,
  1854.              * so don't correct for it twice: */
  1855.             ZLSEEK(G.cur_zipfile_bufstart - G.extra_bytes +
  1856.                    (G.inptr-G.inbuf) + len)
  1857.         } else
  1858.             if (readbuf(__G__  (char *)G.extra_field, len) == 0)
  1859.                 return PK_EOF;
  1860.         break;
  1861.  
  1862. #ifdef AMIGA
  1863.     /*
  1864.      * Fifth case, for the Amiga only:  take the comment that would ordinarily
  1865.      * be skipped over, and turn it into a 79 character string that will be
  1866.      * attached to the file as a "filenote" after it is extracted.
  1867.      */
  1868.  
  1869.     case FILENOTE:
  1870.         if ((extra_len = readbuf(__G__ tmp_fnote, (unsigned)
  1871.                                  MIN(len, 2 * AMIGA_FILENOTELEN - 1))) == 0)
  1872.             return PK_EOF;
  1873.         if ((len -= extra_len) > 0)     /* treat remainder as in case SKIP: */
  1874.             ZLSEEK(G.cur_zipfile_bufstart - G.extra_bytes
  1875.                    + (G.inptr - G.inbuf) + len)
  1876.         /* convert multi-line text into single line with no ctl-chars: */
  1877.         tmp_fnote[extra_len] = '\0';
  1878.         while ((short int) --extra_len >= 0)
  1879.             if ((unsigned) tmp_fnote[extra_len] < ' ')
  1880.                 if (tmp_fnote[extra_len+1] == ' ')     /* no excess */
  1881.                     strcpy(tmp_fnote+extra_len, tmp_fnote+extra_len+1);
  1882.                 else
  1883.                     tmp_fnote[extra_len] = ' ';
  1884.         tmp_fnote[AMIGA_FILENOTELEN - 1] = '\0';
  1885.         if (G.filenotes[G.filenote_slot])
  1886.             free(G.filenotes[G.filenote_slot]);     /* should not happen */
  1887.         G.filenotes[G.filenote_slot] = NULL;
  1888.         if (tmp_fnote[0]) {
  1889.             if (!(G.filenotes[G.filenote_slot] = malloc(strlen(tmp_fnote)+1)))
  1890.                 return PK_MEM;
  1891.             strcpy(G.filenotes[G.filenote_slot], tmp_fnote);
  1892.         }
  1893.         break;
  1894. #endif /* AMIGA */
  1895.  
  1896.     } /* end switch (option) */
  1897.  
  1898.     return error;
  1899.  
  1900. } /* end function do_string() */
  1901.  
  1902.  
  1903.  
  1904.  
  1905.  
  1906. /***********************/
  1907. /* Function makeword() */
  1908. /***********************/
  1909.  
  1910. ush makeword(b)
  1911.     ZCONST uch *b;
  1912. {
  1913.     /*
  1914.      * Convert Intel style 'short' integer to non-Intel non-16-bit
  1915.      * host format.  This routine also takes care of byte-ordering.
  1916.      */
  1917.     return (ush)((b[1] << 8) | b[0]);
  1918. }
  1919.  
  1920.  
  1921.  
  1922.  
  1923.  
  1924. /***********************/
  1925. /* Function makelong() */
  1926. /***********************/
  1927.  
  1928. ulg makelong(sig)
  1929.     ZCONST uch *sig;
  1930. {
  1931.     /*
  1932.      * Convert intel style 'long' variable to non-Intel non-16-bit
  1933.      * host format.  This routine also takes care of byte-ordering.
  1934.      */
  1935.     return (((ulg)sig[3]) << 24)
  1936.         + (((ulg)sig[2]) << 16)
  1937.         + (((ulg)sig[1]) << 8)
  1938.         + ((ulg)sig[0]);
  1939. }
  1940.  
  1941.  
  1942.  
  1943. #if CRYPT
  1944.  
  1945. #ifdef NEED_STR2ISO
  1946. /**********************/
  1947. /* Function str2iso() */
  1948. /**********************/
  1949.  
  1950. char *str2iso(dst, src)
  1951.     char *dst;                          /* destination buffer */
  1952.     register ZCONST char *src;          /* source string */
  1953. {
  1954. #ifdef INTERN_TO_ISO
  1955.     INTERN_TO_ISO(src, dst);
  1956. #else
  1957.     register uch c;
  1958.     register char *dstp = dst;
  1959.  
  1960.     do {
  1961.         c = (uch)foreign(*src++);
  1962.         *dstp++ = (char)ASCII2ISO(c);
  1963.     } while (c != '\0');
  1964. #endif
  1965.  
  1966.     return dst;
  1967. }
  1968. #endif /* NEED_STR2ISO */
  1969.  
  1970.  
  1971. #ifdef NEED_STR2OEM
  1972. /**********************/
  1973. /* Function str2oem() */
  1974. /**********************/
  1975.  
  1976. char *str2oem(dst, src)
  1977.     char *dst;                          /* destination buffer */
  1978.     register ZCONST char *src;          /* source string */
  1979. {
  1980. #ifdef INTERN_TO_OEM
  1981.     INTERN_TO_OEM(src, dst);
  1982. #else
  1983.     register uch c;
  1984.     register char *dstp = dst;
  1985.  
  1986.     do {
  1987.         c = (uch)foreign(*src++);
  1988.         *dstp++ = (char)ASCII2OEM(c);
  1989.     } while (c != '\0');
  1990. #endif
  1991.  
  1992.     return dst;
  1993. }
  1994. #endif /* NEED_STR2OEM */
  1995.  
  1996. #endif /* CRYPT */
  1997.  
  1998.  
  1999. #ifdef ZMEM  /* memset/memcmp/memcpy for systems without either them or */
  2000.              /* bzero/bcmp/bcopy */
  2001.              /* (no known systems as of 960211) */
  2002.  
  2003. /*********************/
  2004. /* Function memset() */
  2005. /*********************/
  2006.  
  2007. zvoid *memset(buf, init, len)
  2008.     register zvoid *buf;        /* buffer location */
  2009.     register int init;          /* initializer character */
  2010.     register unsigned int len;  /* length of the buffer */
  2011. {
  2012.     zvoid *start;
  2013.  
  2014.     start = buf;
  2015.     while (len--)
  2016.         *((char *)buf++) = (char)init;
  2017.     return start;
  2018. }
  2019.  
  2020.  
  2021.  
  2022. /*********************/
  2023. /* Function memcmp() */
  2024. /*********************/
  2025.  
  2026. int memcmp(b1, b2, len)
  2027.     register ZCONST zvoid *b1;
  2028.     register ZCONST zvoid *b2;
  2029.     register unsigned int len;
  2030. {
  2031.     register int c;
  2032.  
  2033.     if (len > 0) do {
  2034.         if ((c = (int)(*((ZCONST unsigned char *)b1)++) -
  2035.                  (int)(*((ZCONST unsigned char *)b2)++)) != 0)
  2036.            return c;
  2037.     } while (--len > 0)
  2038.     return 0;
  2039. }
  2040.  
  2041.  
  2042.  
  2043. /*********************/
  2044. /* Function memcpy() */
  2045. /*********************/
  2046.  
  2047. zvoid *memcpy(dst, src, len)
  2048.     register zvoid *dst;
  2049.     register ZCONST zvoid *src;
  2050.     register unsigned int len;
  2051. {
  2052.     zvoid *start;
  2053.  
  2054.     start = dst;
  2055.     while (len-- > 0)
  2056.         *((char *)dst)++ = *((ZCONST char *)src)++;
  2057.     return start;
  2058. }
  2059.  
  2060. #endif /* ZMEM */
  2061.  
  2062.  
  2063.  
  2064.  
  2065.  
  2066. /************************/
  2067. /* Function zstrnicmp() */
  2068. /************************/
  2069.  
  2070. int zstrnicmp(s1, s2, n)
  2071.     register ZCONST char *s1, *s2;
  2072.     register unsigned n;
  2073. {
  2074.     for (; n > 0;  --n, ++s1, ++s2) {
  2075.  
  2076.         if (ToLower(*s1) != ToLower(*s2))
  2077.             /* test includes early termination of one string */
  2078.             return (ToLower(*s1) < ToLower(*s2))? -1 : 1;
  2079.  
  2080.         if (*s1 == '\0')   /* both strings terminate early */
  2081.             return 0;
  2082.     }
  2083.     return 0;
  2084. }
  2085.  
  2086.  
  2087.  
  2088.  
  2089.  
  2090. #ifdef REGULUS  /* returns the inode number on success(!)...argh argh argh */
  2091. #  undef stat
  2092.  
  2093. /********************/
  2094. /* Function zstat() */
  2095. /********************/
  2096.  
  2097. int zstat(p, s)
  2098.     char *p;
  2099.     struct stat *s;
  2100. {
  2101.     return (stat(p,s) >= 0? 0 : (-1));
  2102. }
  2103.  
  2104. #endif /* REGULUS */
  2105.  
  2106.  
  2107.  
  2108.  
  2109.  
  2110. #ifdef SMALL_MEM
  2111.  
  2112. /*******************************/
  2113. /*  Function fLoadFarString()  */   /* (and friends...) */
  2114. /*******************************/
  2115.  
  2116. char *fLoadFarString(__GPRO__ const char Far *sz)
  2117. {
  2118.     (void)zfstrcpy(G.rgchBigBuffer, sz);
  2119.     return G.rgchBigBuffer;
  2120. }
  2121.  
  2122. char *fLoadFarStringSmall(__GPRO__ const char Far *sz)
  2123. {
  2124.     (void)zfstrcpy(G.rgchSmallBuffer, sz);
  2125.     return G.rgchSmallBuffer;
  2126. }
  2127.  
  2128. char *fLoadFarStringSmall2(__GPRO__ const char Far *sz)
  2129. {
  2130.     (void)zfstrcpy(G.rgchSmallBuffer2, sz);
  2131.     return G.rgchSmallBuffer2;
  2132. }
  2133.  
  2134.  
  2135.  
  2136.  
  2137. #if (!defined(_MSC_VER) || (_MSC_VER < 600))
  2138. /*************************/
  2139. /*  Function zfstrcpy()  */   /* portable clone of _fstrcpy() */
  2140. /*************************/
  2141.  
  2142. char Far * Far zfstrcpy(char Far *s1, const char Far *s2)
  2143. {
  2144.     char Far *p = s1;
  2145.  
  2146.     while ((*s1++ = *s2++) != '\0');
  2147.     return p;
  2148. }
  2149. #endif /* !_MSC_VER || (_MSC_VER < 600) */
  2150.  
  2151. #endif /* SMALL_MEM */
  2152.