home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 9 Archive / 09-Archive.zip / UNZ_OS2.ZIP / UNZIP2.C next >
C/C++ Source or Header  |  1989-07-21  |  22KB  |  980 lines

  1. /*
  2.  * Copyright 1987, 1989 Samuel H. Smith;  All rights reserved
  3.  *
  4.  * This is a component of the ProDoor System.
  5.  * Do not distribute modified versions without my permission.
  6.  * Do not remove or alter this notice or any other copyright notice.
  7.  * If you use this in your own program you must distribute source code.
  8.  * Do not use any of this in a commercial product.
  9.  *
  10.  */
  11.  
  12. /*
  13.  * UnZip - A simple zipfile extract utility
  14.  *
  15.  *
  16.  * 24-July-89 Modified for OS/2 support Malcolm Greenhalgh
  17.  *            changes made to 'setftime' function.
  18.  */ 
  19.  
  20. #define version  "UnZip:  Zipfile Extract v1.1ß/² of 24-07-89;  (C) 1989 S.H.Smith"
  21.  
  22. typedef unsigned char byte;
  23. typedef long longint;
  24. typedef unsigned word;
  25. typedef char boolean;
  26. #define STRSIZ  256
  27.  
  28. #include <fcntl.h>
  29. #include <sys/types.h>      //...   MCG 24-07-89 for OS/2 version
  30. #include <sys/stat.h>
  31. #include <io.h>
  32. #include <stdio.h>
  33. #include <stdlib.h>
  34.  
  35. #define INCL_DOSFILEMGR     //...   MCG 24-07-89 for OS/2 version
  36. #define INCL_SUB            //...   MCG 24-07-89 for OS/2 version
  37. #include <os2.h>            //...   MCG 24-07-89 for OS/2 version
  38.  
  39.  
  40. /* ----------------------------------------------------------- */ 
  41. /*
  42.  * Zipfile layout declarations
  43.  *
  44.  */ 
  45.  
  46.    typedef longint       signature_type;
  47.  
  48.  
  49.    #define local_file_header_signature  0x04034b50L
  50.  
  51.  
  52.    typedef struct local_file_header { 
  53.       word         version_needed_to_extract; 
  54.       word         general_purpose_bit_flag; 
  55.       word         compression_method; 
  56.       word         last_mod_file_time; 
  57.       word         last_mod_file_date; 
  58.       longint      crc32; 
  59.       longint      compressed_size; 
  60.       longint      uncompressed_size; 
  61.       word         filename_length; 
  62.       word         extra_field_length; 
  63.    } local_file_header; 
  64.  
  65.  
  66.    #define cntrl_file_header_signature  0x02014b50L
  67.  
  68.  
  69.    typedef struct cntrl_dir_file_header {
  70.       word         version_made_by; 
  71.       word         version_needed_to_extract; 
  72.       word         general_purpose_bit_flag; 
  73.       word         compression_method; 
  74.       word         last_mod_file_time; 
  75.       word         last_mod_file_date; 
  76.       longint      crc32; 
  77.       longint      compressed_size; 
  78.       longint      uncompressed_size; 
  79.       word         filename_length; 
  80.       word         extra_field_length; 
  81.       word         file_comment_length; 
  82.       word         disk_number_start; 
  83.       word         internal_file_attributes; 
  84.       longint      external_file_attributes; 
  85.       longint      relative_offset_local_header; 
  86.    } cntrl_dir_file_header;
  87.  
  88.  
  89.    #define end_cntrl_dir_signature  0x06054b50L
  90.  
  91.  
  92.    typedef struct end_cntrl_dir_record {
  93.       word         number_this_disk; 
  94.       word         number_disk_with_strt_cntrl_dir;
  95.       word         total_entries_cntrl_dir_on_disk;
  96.       word         total_entries_cntrl_dir;
  97.       longint      size_cntrl_dir;
  98.       longint      offset_start_cntrl_dir;
  99.       word         zipfile_comment_length; 
  100.    } end_cntrl_dir_record;
  101.  
  102.  
  103.  
  104. /* ----------------------------------------------------------- */ 
  105. /*
  106.  * input file variables
  107.  *
  108.  */ 
  109.  
  110.  
  111.    #define           uinbufsize    512L   /* input buffer size */
  112.    byte              inbuf[uinbufsize];
  113.  
  114.    boolean           zipeof;
  115.    longint           csize;
  116.    longint           cusize;
  117.    int               cmethod;
  118.    int               inpos;
  119.    int               incnt;
  120.    int               pc;
  121.    int               pcbits;
  122.    int               pcbitv;
  123.    
  124.    int               zipfd;
  125.    char              zipfn[STRSIZ];
  126.    local_file_header lrec;
  127.    FILESTATUS        fistat;
  128.    USHORT            filevel;
  129.  
  130.  
  131.  
  132. /* ----------------------------------------------------------- */ 
  133. /*
  134.  * output stream variables
  135.  *
  136.  */ 
  137.  
  138.  
  139.    byte     outbuf[4096];   /* for rle look-back */
  140.    longint  outpos;         /* absolute position in outfile */
  141.    int      outcnt;
  142.  
  143.    int      outfd;
  144.    char     filename[STRSIZ];
  145.    char     extra[STRSIZ];
  146.  
  147.  
  148.  
  149. /* ----------------------------------------------------------- */ 
  150. /*
  151.  * shrink/reduce working storage
  152.  *
  153.  */ 
  154.  
  155.  
  156.    int      factor;
  157.    byte     followers[256][64];
  158.    byte     Slen[256];
  159.    int      ExState;
  160.    int      C;
  161.    int      V;
  162.    int      Len;
  163.  
  164.    #define max_bits      13
  165.    #define init_bits     9
  166.    #define hsize         8192
  167.    #define first_ent     257
  168.    #define clear         256
  169.  
  170.    typedef int  hsize_array_integer[hsize+1];
  171.    typedef byte hsize_array_byte[hsize+1];
  172.  
  173.    hsize_array_integer prefix_of;
  174.    hsize_array_byte    suffix_of;
  175.    hsize_array_byte    stack;
  176.  
  177.    int      cbits;
  178.    int      maxcode;
  179.    int      free_ent;
  180.    int      maxcodemax;
  181.    int      offset;
  182.    int      sizex;
  183.  
  184.  
  185. /* ------------------------------------------------------------- */ 
  186.  
  187. void         skip_csize(void)
  188.    lseek(zipfd,csize,SEEK_CUR);
  189.    zipeof = 1;
  190.    csize = 0L; 
  191.    incnt = 0; 
  192.  
  193.  
  194. /* ------------------------------------------------------------- */ 
  195.  
  196. void         ReadByte(int *       x)
  197.    if (incnt == 0) 
  198.    { 
  199.       if (csize == 0L) 
  200.       { 
  201.          zipeof = 1;
  202.          return;
  203.       } 
  204.  
  205.       inpos = sizeof(inbuf);
  206.       if (inpos > csize) 
  207.          inpos = (int)csize;
  208.       incnt = read(zipfd,inbuf,inpos);
  209.  
  210.       inpos = 1; 
  211.       csize -= incnt; 
  212.    } 
  213.  
  214.    *x = inbuf[inpos-1]; 
  215.    inpos++; 
  216.    incnt--; 
  217.  
  218.  
  219. /* ------------------------------------------------------------- */ 
  220.  
  221. void         ReadBits(int      bits,
  222.                       int *    x)
  223.      /* read the specified number of bits */ 
  224.    int      bit;
  225.    int      bitv;
  226.  
  227.    *x = 0;
  228.    bitv = 1;
  229.  
  230.    for (bit = 0; bit <= bits-1; bit++)
  231.    { 
  232.  
  233.       if (pcbits > 0) 
  234.       { 
  235.          pcbits--; 
  236.          pcbitv = pcbitv << 1; 
  237.       } 
  238.       else 
  239.  
  240.       { 
  241.          ReadByte(&pc); 
  242.          pcbits = 7; 
  243.          pcbitv = 1; 
  244.       } 
  245.  
  246.       if ((pc & pcbitv) != 0) 
  247.          *x = *x | bitv; 
  248.  
  249.       bitv = (int) (bitv << 1);
  250.    } 
  251.  
  252.  
  253.  
  254. /* ---------------------------------------------------------- */ 
  255.  
  256. void         get_string(int      len,
  257.                         char *   s)
  258.    read(zipfd,s,len);
  259.    s[len] = 0;
  260.  
  261.  
  262. /* ------------------------------------------------------------- */ 
  263.  
  264. void         OutByte(int      c)
  265.    /* output each character from archive to screen */ 
  266.    outbuf[outcnt /* outpos % sizeof(outbuf) */] = c;
  267.    outpos++; 
  268.    outcnt++;
  269.  
  270.    if (outcnt == sizeof(outbuf)) 
  271.    { 
  272.       write(outfd,outbuf,outcnt);
  273.       outcnt = 0; 
  274.       printf("."); 
  275.    } 
  276.  
  277.  
  278. /* ----------------------------------------------------------- */
  279.    
  280. int         reduce_L(int         x)
  281.    { 
  282.       switch (factor) {
  283.          case 1:   return x & 0x7f; 
  284.          case 2:   return x & 0x3f; 
  285.          case 3:   return x & 0x1f; 
  286.          case 4:   return x & 0x0f; 
  287.       } 
  288.     return 0; /* error */
  289.    } 
  290.  
  291.    
  292. int         reduce_F(int         x)
  293.    { 
  294.       switch (factor) {
  295.          case 1:   if (x == 127) return 2;  else return 3;
  296.          case 2:   if (x == 63) return 2;   else return 3;
  297.          case 3:   if (x == 31) return 2;   else return 3;
  298.          case 4:   if (x == 15) return 2;   else return 3;
  299.       } 
  300.     return 0; /* error */
  301.    } 
  302.  
  303.    
  304. int         reduce_D(int         x,
  305.                      int         y)
  306.    { 
  307.       switch (factor) {
  308.          case 1:   return ((x >> 7) & 0x01) * 256 + y + 1; 
  309.          case 2:   return ((x >> 6) & 0x03) * 256 + y + 1; 
  310.          case 3:   return ((x >> 5) & 0x07) * 256 + y + 1; 
  311.          case 4:   return ((x >> 4) & 0x0f) * 256 + y + 1; 
  312.       } 
  313.     return 0; /* error */
  314.    } 
  315.  
  316.  
  317. int         reduce_B(int         x)
  318.         /* number of bits needed to encode the specified number */ 
  319.    { 
  320.       switch (x - 1) {
  321.          
  322.          case 0:   
  323.          case 1:   return 1; 
  324.          
  325.          case 2:   
  326.          case 3:   return 2; 
  327.          
  328.          case 4:
  329.          case 5:   
  330.          case 6:   
  331.          case 7:   return 3; 
  332.          
  333.          case 8:   
  334.          case 9:   
  335.          case 10:   
  336.          case 11:   
  337.          case 12:   
  338.          case 13:   
  339.          case 14:   
  340.          case 15:   return 4; 
  341.         
  342.          case 16:
  343.          case 17:
  344.          case 18:
  345.          case 19:
  346.          case 20:
  347.          case 21:
  348.          case 22:
  349.          case 23:
  350.          case 24:
  351.          case 25:
  352.          case 26:
  353.          case 27:
  354.          case 28:
  355.          case 29:
  356.          case 30:
  357.          case 31:   return 5;
  358.         
  359.          case 32:
  360.          case 33:
  361.          case 34:
  362.          case 35:
  363.          case 36:
  364.          case 37:
  365.          case 38:
  366.          case 39:
  367.          case 40:
  368.          case 41:
  369.          case 42:
  370.          case 43:
  371.          case 44:
  372.          case 45:
  373.          case 46:
  374.          case 47:
  375.          case 48:
  376.          case 49:
  377.          case 50:
  378.          case 51:
  379.          case 52:
  380.          case 53:
  381.          case 54:
  382.          case 55:
  383.          case 56:
  384.          case 57:
  385.          case 58:
  386.          case 59:
  387.          case 60:
  388.          case 61:
  389.          case 62:
  390.          case 63:   return 6;
  391.  
  392.          case 64:
  393.          case 65:
  394.          case 66:
  395.          case 67:
  396.          case 68:
  397.          case 69:
  398.          case 70:
  399.          case 71:
  400.          case 72:
  401.          case 73:
  402.          case 74:
  403.          case 75:
  404.          case 76:
  405.          case 77:
  406.          case 78:
  407.          case 79:
  408.          case 80:
  409.          case 81:
  410.          case 82:
  411.          case 83:
  412.          case 84:
  413.          case 85:
  414.          case 86:
  415.          case 87:
  416.          case 88:
  417.          case 89:
  418.          case 90:
  419.          case 91:
  420.          case 92:
  421.          case 93:
  422.          case 94:
  423.          case 95:
  424.          case 96:
  425.          case 97:
  426.          case 98:
  427.          case 99:
  428.          case 100:
  429.          case 101:
  430.          case 102:
  431.          case 103:
  432.          case 104:
  433.          case 105:
  434.          case 106:
  435.          case 107:
  436.          case 108:
  437.          case 109:
  438.          case 110:
  439.          case 111:
  440.          case 112:
  441.          case 113:
  442.          case 114:
  443.          case 115:
  444.          case 116:
  445.          case 117:
  446.          case 118:
  447.          case 119:
  448.          case 120:
  449.          case 121:
  450.          case 122:
  451.          case 123:
  452.          case 124:
  453.          case 125:
  454.          case 126:
  455.          case 127:   return 7;
  456.       
  457.       default:       return 8;
  458.       } 
  459.    } 
  460.  
  461.  
  462.  
  463. /* ----------------------------------------------------------- */
  464.  
  465. void         Expand(int      c)
  466.    { 
  467.       #define DLE           144
  468.    
  469.       switch (ExState) {
  470.            
  471.            case 0:
  472.                if (c != DLE)
  473.                    OutByte(c);
  474.                else 
  475.                    ExState = 1; 
  476.            break; 
  477.            
  478.            case 1:
  479.                if (c != 0)
  480.                { 
  481.                    V = c; 
  482.                    Len = reduce_L(V);
  483.                    ExState = reduce_F(Len);
  484.                } 
  485.                else 
  486.                { 
  487.                    OutByte(DLE); 
  488.                    ExState = 0; 
  489.                } 
  490.            break; 
  491.            
  492.            case 2:   { 
  493.                   Len = Len + c; 
  494.                   ExState = 3; 
  495.                } 
  496.            break; 
  497.            
  498.            case 3:   { 
  499.                   int i;
  500.                   longint offset = reduce_D(V,c);
  501.                   longint op = outpos - offset;
  502.  
  503.                   for (i = 0; i <= Len + 2; i++) 
  504.                   { 
  505.                      if (op < 0L) 
  506.                         OutByte(0);
  507.                      else 
  508.                         OutByte(outbuf[(int)(op % sizeof(outbuf))]);
  509.                      op++; 
  510.                   } 
  511.  
  512.                   ExState = 0; 
  513.                } 
  514.          break;
  515.       } 
  516.    } 
  517.  
  518.  
  519. /* ----------------------------------------------------------- */
  520.    
  521. void         LoadFollowers(void)
  522.    { 
  523.       int      x;
  524.       int      i;
  525.       int      b;
  526.  
  527.       for (x = 255; x >= 0; x--) 
  528.       { 
  529.          ReadBits(6,&b); 
  530.          Slen[x] = b;
  531.  
  532.          for (i = 0; i < Slen[x]; i++)
  533.          { 
  534.             ReadBits(8,&b); 
  535.             followers[x][i] = b;
  536.          } 
  537.       } 
  538.    } 
  539.  
  540.  
  541.    
  542. /* ----------------------------------------------------------- */ 
  543.  
  544. /*
  545.  * The Reducing algorithm is actually a combination of two
  546.  * distinct algorithms.  The first algorithm compresses repeated
  547.  * byte sequences, and the second algorithm takes the compressed
  548.  * stream from the first algorithm and applies a probabilistic
  549.  * compression method.
  550.  *
  551.  */ 
  552.  
  553. void         unReduce(void)
  554.      /* expand probablisticly reduced data */ 
  555.  
  556.    { 
  557.  
  558.    int    lchar;
  559.    int    lout;
  560.    int    I;
  561.  
  562.    factor = cmethod - 1; 
  563.    if ((factor < 1) || (factor > 4)) 
  564.    { 
  565.       skip_csize(); 
  566.       return;
  567.    } 
  568.  
  569.    ExState = 0; 
  570.    LoadFollowers(); 
  571.    lchar =  0;
  572.  
  573.    while ((!zipeof) && (outpos < cusize))
  574.    { 
  575.  
  576.       if (Slen[lchar] == 0)
  577.          ReadBits(8,&lout);
  578.       else 
  579.  
  580.       { 
  581.          ReadBits(1,&lout); 
  582.          if (lout != 0) 
  583.             ReadBits(8,&lout);
  584.          else 
  585.          { 
  586.             ReadBits(reduce_B(Slen[lchar]),&I);
  587.             lout = followers[lchar][I];
  588.          } 
  589.       } 
  590.  
  591.       Expand(lout); 
  592.       lchar = lout; 
  593.    } 
  594.  
  595.  
  596. /* ------------------------------------------------------------- */
  597. /*
  598.  * Shrinking is a Dynamic Ziv-Lempel-Welch compression algorithm
  599.  * with partial clearing.
  600.  *
  601.  */ 
  602.  
  603. void         partial_clear(void)
  604.    int      pr;
  605.    int      cd;
  606.  
  607.  
  608.    /* mark all nodes as potentially unused */
  609.    for (cd = first_ent; cd < free_ent; cd++)
  610.       prefix_of[cd] |= 0x8000;
  611.  
  612.  
  613.    /* unmark those that are used by other nodes */
  614.    for (cd = first_ent; cd < free_ent; cd++)
  615.    { 
  616.       pr = prefix_of[cd] & 0x7fff;   /* reference to another node? */ 
  617.       if (pr >= first_ent)           /* flag node as referenced */
  618.          prefix_of[pr] &= 0x7fff;
  619.    } 
  620.  
  621.  
  622.    /* clear the ones that are still marked */ 
  623.    for (cd = first_ent; cd < free_ent; cd++)
  624.       if ((prefix_of[cd] & 0x8000) != 0) 
  625.          prefix_of[cd] = -1;
  626.  
  627.  
  628.    /* find first cleared node as next free_ent */ 
  629.    free_ent = first_ent; 
  630.    while ((free_ent < maxcodemax) && (prefix_of[free_ent] != -1)) 
  631.       free_ent++; 
  632.  
  633.  
  634. /* ------------------------------------------------------------- */
  635.  
  636. void         unShrink(void)
  637.  
  638.    int      stackp;
  639.    int      finchar;
  640.    int      code;
  641.    int      oldcode;
  642.    int      incode;
  643.  
  644.  
  645.    /* decompress the file */ 
  646.    maxcodemax = 1 << max_bits; 
  647.    cbits = init_bits; 
  648.    maxcode = (1 << cbits) - 1; 
  649.    free_ent = first_ent; 
  650.    offset = 0; 
  651.    sizex = 0; 
  652.  
  653.    for (code = maxcodemax; code > 255; code--)
  654.       prefix_of[code] = -1;
  655.  
  656.    for (code = 255; code >= 0; code--) 
  657.    { 
  658.       prefix_of[code] = 0;
  659.       suffix_of[code] = code;
  660.    } 
  661.  
  662.    ReadBits(cbits,&oldcode); 
  663.    if (zipeof) return;
  664.    finchar = oldcode; 
  665.  
  666.    OutByte(finchar); 
  667.  
  668.    stackp = 0; 
  669.  
  670.    while ((!zipeof)) 
  671.    { 
  672.       ReadBits(cbits,&code); 
  673.       if (zipeof) return;
  674.  
  675.       while (code == clear)
  676.       { 
  677.          ReadBits(cbits,&code); 
  678.  
  679.          switch (code) {
  680.             
  681.             case 1:   { 
  682.                   cbits++; 
  683.                   if (cbits == max_bits) 
  684.                      maxcode = maxcodemax;
  685.                   else 
  686.                      maxcode = (1 << cbits) - 1; 
  687.                } 
  688.             break;
  689.  
  690.             case 2:
  691.                   partial_clear();
  692.             break;
  693.          } 
  694.  
  695.          ReadBits(cbits,&code); 
  696.          if (zipeof) return;
  697.       } 
  698.  
  699.    
  700.       /* special case for KwKwK string */
  701.       incode = code;
  702.       if (prefix_of[code] == -1)
  703.       { 
  704.          stack[stackp] = finchar;
  705.          stackp++; 
  706.          code = oldcode; 
  707.       } 
  708.  
  709.  
  710.       /* generate output characters in reverse order */
  711.       while (code >= first_ent)
  712.       { 
  713.          stack[stackp] = suffix_of[code];
  714.          stackp++; 
  715.          code = prefix_of[code];
  716.       } 
  717.  
  718.       finchar = suffix_of[code];
  719.       stack[stackp] = finchar;
  720.       stackp++; 
  721.  
  722.  
  723.       /* and put them out in forward order */
  724.       while (stackp > 0)
  725.       { 
  726.          stackp--; 
  727.          OutByte(stack[stackp]);
  728.       } 
  729.  
  730.  
  731.       /* generate new entry */
  732.       code = free_ent;
  733.       if (code < maxcodemax) 
  734.       { 
  735.          prefix_of[code] = oldcode;
  736.          suffix_of[code] = finchar;
  737.          while ((free_ent < maxcodemax) && (prefix_of[free_ent] != -1))
  738.             free_ent++;
  739.       } 
  740.  
  741.  
  742.       /* remember previous code */
  743.       oldcode = incode; 
  744.    } 
  745.  
  746.  
  747. /* ---------------------------------------------------------- */
  748. //...   MCG 24-07-89 for OS/2 version
  749.  
  750. static int setftime(fn, fd, ft)
  751.    char *fn;
  752.    unsigned fd, ft;
  753. {
  754.    USHORT   eact;
  755.    HDIR     ehand;
  756.    unsigned eflag = 0x01, emode = 0x42;
  757.  
  758.    if (DosOpen(fn, &ehand, &eact, 0L, 0, eflag, emode, 0L))
  759.       return (1);
  760.  
  761.    /* set output file date and time ; modified MCG OS/2 */
  762.    filevel = 1;
  763.    DosQFileInfo (ehand,filevel,&fistat,sizeof(fistat));
  764.    fistat.fdateLastWrite.day   = (fd & 0x1F);
  765.    fistat.fdateLastWrite.month = ((fd >> 5) & 0xF);
  766.    fistat.fdateLastWrite.year  = (fd >> 9);
  767.    fistat.ftimeLastWrite.twosecs = (ft & 0x1F);
  768.    fistat.ftimeLastWrite.minutes = ((ft >> 5) & 0x2F);
  769.    fistat.ftimeLastWrite.hours   = (ft >> 11);
  770.    if (DosSetFileInfo (ehand,filevel,&fistat,sizeof(fistat)))
  771.       return(2);
  772.    return(0);
  773. }
  774.  
  775. /* ---------------------------------------------------------- */ 
  776.  
  777. void         extract_member(void)
  778.    int    b;
  779.  
  780.    union {
  781.         // struct ftime ft;
  782.         struct {
  783.             word ztime;
  784.             word zdate;
  785.         } zt;
  786.     } td;
  787.  
  788. for (b=0; b<sizeof(outbuf); b++) outbuf[b]=0;
  789.    pcbits = 0; 
  790.    incnt = 0; 
  791.    outpos = 0L; 
  792.    outcnt = 0; 
  793.    zipeof = 0;
  794.  
  795.    outfd = creat(filename,S_IWRITE|S_IREAD);
  796.    if (outfd < 1)
  797.    { 
  798.       printf("Can't create output: %s\n",filename); 
  799.       exit(0);
  800.    } 
  801.  
  802.    close(outfd);
  803.    outfd = open(filename,O_RDWR|O_BINARY);
  804.  
  805.  
  806.    switch (cmethod) {
  807.       
  808.       case 0:     /* stored */ 
  809.             { 
  810.                printf(" Extract: %s ...",filename); 
  811.                while ((!zipeof)) 
  812.                { 
  813.                   ReadByte(&b); 
  814.                   OutByte(b); 
  815.                } 
  816.             } 
  817.       break; 
  818.       
  819.       case 1:   { 
  820.                printf("UnShrink: %s ...",filename); 
  821.                unShrink(); 
  822.             } 
  823.       break; 
  824.       
  825.       case 2:   
  826.       case 3:   
  827.       case 4:   
  828.       case 5:   { 
  829.                printf("  Expand: %s ...",filename); 
  830.                unReduce(); 
  831.             } 
  832.       break; 
  833.       
  834.       default: printf("Unknown compression method."); 
  835.    } 
  836.  
  837.    if (outcnt > 0) 
  838.       write(outfd,outbuf,outcnt);
  839.    close(outfd);
  840.    setftime(filename,lrec.last_mod_file_date,lrec.last_mod_file_time);
  841.    printf("  done.\n"); 
  842.  
  843.  
  844. /* ---------------------------------------------------------- */ 
  845.  
  846. void         process_local_file_header(void)
  847.    read(zipfd,&lrec,sizeof(lrec));
  848.    get_string(lrec.filename_length,filename);
  849.    get_string(lrec.extra_field_length,extra);
  850.    csize = lrec.compressed_size;
  851.    cusize = lrec.uncompressed_size;
  852.    cmethod = lrec.compression_method;
  853.    extract_member(); 
  854.  
  855.  
  856. /* ---------------------------------------------------------- */ 
  857.  
  858. void         process_cntrl_file_header(void)
  859.    cntrl_dir_file_header rec;
  860.    char filename[STRSIZ];
  861.    char extra[STRSIZ];
  862.    char comment[STRSIZ];
  863.  
  864.    read(zipfd,&rec,sizeof(rec));
  865.    get_string(rec.filename_length,filename); 
  866.    get_string(rec.extra_field_length,extra); 
  867.    get_string(rec.file_comment_length,comment); 
  868.  
  869.  
  870. /* ---------------------------------------------------------- */ 
  871.  
  872. void         process_end_cntrl_dir(void)
  873.    end_cntrl_dir_record rec;
  874.    char comment[STRSIZ];
  875.  
  876.    read(zipfd,&rec,sizeof(rec));
  877.    get_string(rec.zipfile_comment_length,comment); 
  878.  
  879.  
  880. /* ---------------------------------------------------------- */ 
  881.  
  882. void         process_headers(void)
  883.    longint sig;
  884.  
  885.    while (1)
  886.    { 
  887.       if (read(zipfd,&sig,sizeof(sig)) != sizeof(sig))
  888.          return;
  889.       else 
  890.  
  891.       if (sig == local_file_header_signature) 
  892.          process_local_file_header();
  893.       else 
  894.  
  895.       if (sig == cntrl_file_header_signature)
  896.          process_cntrl_file_header();
  897.       else 
  898.  
  899.       if (sig == end_cntrl_dir_signature)
  900.       { 
  901.          process_end_cntrl_dir();
  902.          return;
  903.       } 
  904.  
  905.       else 
  906.       { 
  907.          printf("Invalid Zipfile Header\n"); 
  908.          return;
  909.       } 
  910.    } 
  911.  
  912.  
  913.  
  914. /* ---------------------------------------------------------- */ 
  915.  
  916. void         extract_zipfile(void)
  917.    zipfd = open(zipfn,O_RDONLY|O_BINARY);
  918.    if (zipfd < 1) {
  919.       printf("Can't open input file: %s\n",zipfn);
  920.       return;
  921.    }
  922.  
  923.    process_headers();
  924.  
  925.    close(zipfd);
  926.  
  927.  
  928. /* ---------------------------------------------------------- */
  929. /*
  930.  * main program
  931.  *
  932.  */ 
  933.  
  934. void main(int argc, char **argv)
  935. {
  936.    char *courtesy = "Courtesy of:  S.H.Smith  and  The Tool Shop BBS,  (602) 279-2673.\n\n";
  937.    VioWrtTTy(version, strlen(version), 0);
  938.    VioWrtTTy(courtesy, strlen(courtesy), 0);
  939.  
  940.    if (argc != 2)
  941.    { 
  942.       VioWrtTTy("Usage:  UnZip FILE[.zip]\n", 25, 0);
  943.       DosExit(0,1);
  944.    } 
  945.  
  946.    strcpy(zipfn,argv[1]);
  947.    if (strchr(zipfn,'.') == NULL)
  948.       strcat(zipfn,".ZIP");
  949.  
  950.    extract_zipfile(); 
  951.    DosExit(0,1);
  952. }
  953.