home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 9 Archive / 09-Archive.zip / OS2LHX.LZH / LHX.C < prev    next >
C/C++ Source or Header  |  1989-08-27  |  6KB  |  321 lines

  1. /* LHX.C -- An LHARC archive tester/scanner
  2.  *
  3.  * version 1.0 by Mark Armbrust, 15 April 1985   (IRS? Just say NO!)
  4.  *
  5.  * The code in this module is public domain -- do whatever you want with it */
  6.  
  7. static char version[] = "@(#)lhx.c version 1.0 by Mark Armbrust";
  8.  
  9. #include <process.h>
  10. #include <stdio.h>
  11. #include <string.h>
  12. #include <dos.h>
  13. #include <os2.h>
  14. #include <stdlib.h>
  15. #include <malloc.h>
  16.  
  17. #define MAIN
  18. #include "lhx.h"
  19.  
  20. /* private routines */
  21.  
  22. PRIVATE void    Usage        (void);
  23. PRIVATE int     Match        (char *, char *);
  24. PRIVATE int     WC_Match    (char *, char *);
  25.  
  26.  
  27.  
  28. PUBLIC void        main    (argc, argv)
  29.  
  30. int                  argc;
  31. char            *    argv[];
  32. {
  33. char            *    arcname,
  34.                 *    arcpath;
  35. FILE            *    arcfile;
  36. struct fname    *    filename,
  37.                 *    filenames;
  38. char            *    p,
  39.                 *    q;
  40. FILEFINDBUF        findbuf;
  41. int                    i;
  42. int                    exitcode;
  43. HDIR     dirHandle;
  44. unsigned count;
  45.  
  46. if (argc < 2)
  47.     Usage();
  48.  
  49. --argc;
  50. ++argv;
  51.  
  52. mode = LIST;                    /* set default mode */
  53.  
  54. if (**argv == '-') {            /* get mode switch if present */
  55.     switch (*++*argv) {
  56.  
  57.         case 'e':
  58.         case 'E':
  59.             mode = EXTRACT;
  60.             break;
  61.  
  62.         case 'l':
  63.         case 'L':
  64.             mode = LIST;
  65.             break;
  66.  
  67.         case 's':
  68.         case 'S':
  69.             mode = SCAN;
  70.             break;
  71.  
  72.         case 't':
  73.         case 'T':
  74.             mode = TEST;
  75.             break;
  76.  
  77.         default:
  78.             Usage();
  79.  
  80.         }
  81.     --argc;
  82.     ++argv;
  83.     }
  84.  
  85. header_start = -1;                /* disable starting offset options */
  86. file_start = -1;
  87. file_size = -1;
  88. file_type = -1;
  89. file_name[0] = 0;
  90.  
  91. if (argc && **argv == '@') {    /* get starting offsets */
  92.     if (mode & SCAN)
  93.         fprintf (stderr, "lhx:  WARNING -- offsets ignored.\n");
  94.     else {
  95.         mode |= AT;
  96.         i = sscanf (++*argv, "%ld,%ld,%ld,%d,%s", &header_start, &file_start, 
  97.                     &file_size, &file_type, file_name);
  98.         if (!i)
  99.             Usage();
  100.         }
  101.     --argc;
  102.     ++argv;
  103.     }
  104.  
  105. if (argc) {                        /* get archive name */
  106.     arcname = *argv;
  107.     --argc;
  108.     ++argv;
  109.     }
  110. else
  111.     Usage();
  112.  
  113. if (argc == 0) {                /* get file names if present */
  114.     filenames = malloc (sizeof (struct fname));
  115.     filenames->name = "*.*";
  116.     filenames->next = 0;        /* none specified, assume *.* */
  117.     }
  118. else {
  119.     if (mode & SCAN)
  120.         fprintf (stderr, "lhx:  WARNING -- filenames ignored.\n");
  121.     else {
  122.         filenames = 0;                /* use the rest of the names to build a */
  123.         while (argc--) {            /* linked list of filenames to match.    */
  124.             filename = malloc (sizeof (struct fname));
  125.             filename->name = *argv++;
  126.             filename->next = filenames;
  127.             filenames = filename;
  128.             }
  129.         }
  130.     }
  131.  
  132. if (strpbrk (arcname, "\\/:")) {
  133.     arcpath = strdup(arcname);        /* strip path from arcname */
  134.     p = arcpath - 1;
  135.     while (q = strpbrk (++p, "\\/:"))
  136.         p = q;
  137.     *p = '\0';
  138.     }
  139. else
  140.     arcpath = "";
  141.  
  142. strcpy (name, arcname);
  143.  
  144. p = name;
  145. if (q = strrchr (p, '\\')) 
  146.     p = q + 1;
  147. if (q = strrchr (p, '/')) 
  148.     p = q + 1;
  149. if ( ! strchr (p, '.'))
  150.     strcat (name, ".lzh");
  151. dirHandle = 0xFFFF;  count = 1;
  152. if (DosFindFirst (name, &dirHandle, 0, &findbuf,sizeof findbuf,&count,0L)) {
  153.     fprintf (stderr, "lhx:  ERROR -- could not find any archive files "
  154.             "matching '%s'.\n", arcname);
  155.     exit (-1);
  156.     }
  157.  
  158. exitcode = 0;
  159.  
  160. do {
  161.     count = 1;
  162.     strcpy (name, arcpath);
  163.     strcat (name, findbuf.achName);
  164.     arcfile = fopen (name, "rb");
  165.     if ( ! arcfile) {
  166.         fprintf (stderr, "lzx:  ERROR -- could not open archive file '%s'.\n",
  167.                 name);
  168.         exit (-1);
  169.         }
  170.  
  171.     switch (mode & MODES) {
  172.  
  173.         case EXTRACT:
  174.         case LIST:
  175.         case TEST:
  176.             exitcode += Process (arcfile, filenames);
  177.             break;
  178.  
  179.         case SCAN:
  180.             Scan (arcfile);
  181.             break;
  182.         }
  183.  
  184.     fclose (arcfile);
  185.     } while ( !(mode & AT) && ! DosFindNext(dirHandle,&findbuf,
  186.                         sizeof findbuf,&count) );
  187.  
  188. exit (exitcode);
  189. }
  190.  
  191.  
  192.  
  193. PRIVATE void    Usage    ()
  194.  
  195. {
  196. printf ("\n");
  197. printf ("usage: lhx [-elst] [@hdr,data,size,type,name] arcname [filename ...]\n\n");
  198. printf ("           E => extract files\n");
  199. printf (" (default) L => list archive contents\n");
  200. printf ("           S => scan damaged archive\n");
  201. printf ("           T => test archive\n\n");
  202. printf ("           @hdr,data,size,type,name => where to start in a damaged archive.\n");
  203. exit (1);
  204. }
  205.  
  206.  
  207.  
  208. PUBLIC int        MatchAny (name, filenames)
  209.  
  210. char            *    name;
  211. struct fname    *    filenames;
  212. {
  213.  
  214. do {
  215.     if (Match (name, filenames->name))
  216.         return 1;
  217.     filenames = filenames->next;
  218.     }
  219. while (filenames);
  220.  
  221. return 0;
  222. }
  223.  
  224.  
  225.  
  226. PRIVATE int     Match (file, pattern)
  227.  
  228.     char            *file;
  229.     char            *pattern;
  230.     {
  231.     int                i;
  232.     register char    *filename;
  233.     register char    *s;
  234.  
  235.  
  236. /* strip off the leading path and trailing modifiers (zoo ver. number, etc.) */
  237.  
  238.     filename = file;
  239.     if (s = strrchr (filename, '/')) filename = s+1;
  240.     if (s = strrchr (filename, '\\')) filename = s+1;
  241.     filename = strdup (filename);
  242. /*    if (!filename) Abort ("filename strdup failed in Match"); */
  243.     if (s = strpbrk (filename, ";*, ")) *s = '\0';
  244.  
  245.     i = WC_Match (filename, pattern);
  246.     free (filename);
  247.  
  248.     return i;
  249.     }
  250.  
  251.  
  252.  
  253. /*    Returns TRUE if s1 and s2 match under modified MSDOS wildcard rules.
  254.  *
  255.  *    Two strings match if all their substrings between : . / and \ match
  256.  *    using * and ? as wildcards in the substrings.
  257.  *
  258.  *    Note that MSDOS is a bit schitzo about matching strings that end in : and .
  259.  *    This code will only match them 1-to-1.  For example 'DIR X' matches X.* or
  260.  *    X\*.* depending on what X is.  We do, however, match 'X' to 'X.' and 'X.*'
  261.  *
  262.  */
  263.  
  264. PRIVATE int     WC_Match (s1, s2)
  265.  
  266.     register    char    *s1;
  267.     register    char    *s2;
  268.     {
  269.  
  270. #define IS_SLANT(c)        ((c) == '/' || (c) == '\\')
  271. #define IS_FILE_SEP(c)    ( (c) == ':' || (c) == '.' || IS_SLANT(c) )
  272.  
  273.     while (1) {
  274.  
  275.         if (*s1 == '*' || *s2 == '*') {
  276.             while (*s1 && ! IS_FILE_SEP (*s1))
  277.                 ++s1;
  278.             while (*s2 && ! IS_FILE_SEP (*s2))
  279.                 ++s2;
  280.             continue;
  281.             }
  282.  
  283.         if (*s1 == '?') {
  284.             if (!*s2 || IS_FILE_SEP (*s2))
  285.                 return 0;
  286.             ++s1;
  287.             ++s2;
  288.             continue;
  289.             }
  290.  
  291.         if (*s2 == '?') {
  292.             if (!*s1 || IS_FILE_SEP (*s1))
  293.                 return 0;
  294.             ++s1;
  295.             ++s2;
  296.             continue;
  297.             }
  298.  
  299.         if (*s1 == 0 && *s2 == '.') {
  300.             ++s2;
  301.             continue;
  302.             }
  303.  
  304.         if (*s2 == 0 && *s1 == '.') {
  305.             ++s1;
  306.             continue;
  307.             }
  308.  
  309.         if (toupper(*s1) != toupper(*s2))
  310.             return 0;
  311.  
  312.         if (*s1 == 0)        /* then (*s2 == 0) as well! */
  313.             break;
  314.  
  315.         ++s1;
  316.         ++s2;
  317.         }
  318.  
  319.     return 1;
  320.     }
  321.