home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c019 / 3.ddi / UNZIP11 / UNZIP.C < prev    next >
Encoding:
C/C++ Source or Header  |  1989-03-06  |  20.2 KB  |  954 lines

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