home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS 1992 June / SIMTEL_0692.cdr / msdos / filutl / xf.arc / XF.C next >
Encoding:
C/C++ Source or Header  |  1989-10-08  |  6.2 KB  |  273 lines

  1. /* XF.C  by Mark Adler  8 Oct 89
  2. Find a hexadecimal pattern in a set of files, recursing down the
  3. directories if need be.  Type just 'xf' for instructions.
  4. */
  5.  
  6. #pragma inline
  7.  
  8. #include <stdio.h>
  9. #include <io.h>
  10. #include <fcntl.h>
  11. #include <string.h>
  12. #include <dir.h>
  13. #include <dos.h>
  14.  
  15. #define FIND (FA_RDONLY | FA_HIDDEN | FA_SYSTEM)
  16. #define BUFSZ 512
  17. #define NAMLN 512
  18.  
  19. long fls, fnd;                  /* Files searched, pattern hits */
  20. unsigned char pat[BUFSZ];       /* Pattern of bytes to search for */
  21. int pln;                        /* Number of bytes */
  22.  
  23.  
  24. void scan(unsigned char *b, int m, char *f, long n)
  25. /* Search for the pattern pat of length pln which can start anywhere in
  26. b..b+m-1.  If found, report file (f) and location (n + offset in b).
  27. Also, update fnd for each pattern match. */
  28. {
  29.   if (pln == 1)
  30.   {
  31.     /* Scan for a single byte */
  32.     asm mov di,b
  33.     asm mov si,m
  34.     while (_SI)
  35.     {
  36.       asm mov cx,si
  37.       asm mov ax,ds
  38.       asm mov es,ax
  39.       asm mov al,pat
  40.       asm cld
  41.       asm repne scasb
  42.       asm mov si,cx
  43.       asm jne nf1
  44.         printf("%s: found pattern at offset %lx\n", f,
  45.                n + ((unsigned char *)_DI - b) - 1);
  46.         fnd++;
  47.      nf1: ;
  48.     }
  49.   }
  50.   else
  51.   {
  52.     /* Scan at even boundaries */
  53.     asm mov di,b
  54.     asm mov si,m
  55.     asm inc si
  56.     asm shr si,1
  57.     while (_SI)
  58.     {
  59.       asm mov cx,si
  60.       asm mov ax,ds
  61.       asm mov es,ax
  62.       asm mov ax,word ptr pat
  63.       asm cld
  64.       asm repne scasw
  65.       asm mov si,cx
  66.       asm jne nf2
  67.         if (pln == 2 || memcmp((void *) _DI, pat + 2, pln - 2) == 0)
  68.         {
  69.           printf("%s: found pattern at offset %lx\n", f,
  70.                  n + ((unsigned char *)_DI - b) - 2);
  71.           fnd++;
  72.         }
  73.      nf2: ;
  74.     }
  75.  
  76.     /* Scan at odd boundaries */
  77.     asm mov di,b
  78.     asm inc di
  79.     asm mov si,m
  80.     asm shr si,1
  81.     while (_SI)
  82.     {
  83.       asm mov cx,si
  84.       asm mov ax,ds
  85.       asm mov es,ax
  86.       asm mov ax,word ptr pat
  87.       asm cld
  88.       asm repne scasw
  89.       asm mov si,cx
  90.       asm jne nf3
  91.         if (pln == 2 || memcmp((void *) _DI, pat + 2, pln - 2) == 0)
  92.         {
  93.           printf("%s: found pattern at offset %lx\n", f,
  94.                  n + ((unsigned char *)_DI - b) - 2);
  95.           fnd++;
  96.         }
  97.      nf3: ;
  98.     }
  99.   }
  100. }
  101.  
  102.  
  103. void search(char *f)
  104. /* Search the file f for the pattern pat of length pln.  Abort the
  105. search on an open or read error.  Update fls for a successfully
  106. searched file. */
  107. {
  108.   int h, j, m;
  109.   long n;
  110.   unsigned char b[2*BUFSZ];
  111.  
  112.   strlwr(f);
  113.   if ((h = _open(f, O_RDONLY)) == -1)
  114.   {
  115.     printf("!couldn't open %s for reading\n", f);
  116.     return;
  117.   }
  118.   n = 0;
  119.   m = _read(h, b, 2 * BUFSZ);
  120.   if (m == -1)
  121.   {
  122.     _close(h);
  123.     printf("!error reading %s\n", f);
  124.     return;
  125.   }
  126.   while (m >= pln)
  127.   {
  128.     j = m - pln + 1;
  129.     if (j > BUFSZ)
  130.       j = BUFSZ;
  131.     scan(b, j, f, n);           /* Search for pattern pat starting */
  132.     m -= j;                     /*  at b..b+j-1 with file offset n */
  133.     memcpy(b, b + j, m);
  134.     n += j;
  135.     if ((j = _read(h, b + m, BUFSZ)) == -1)
  136.     {
  137.       _close(h);
  138.       printf("!error reading %s\n", f);
  139.       return;
  140.     }
  141.     m += j;
  142.   }
  143.   _close(h);
  144.   fls++;
  145. }
  146.  
  147.  
  148. int recurse(char *a)
  149. /* Find all files that match 'a' and all files anywhere in the tree
  150. under the path in 'a' that match the name in 'a'. */
  151. {
  152.   int r;
  153.   char *p, *q;
  154.   struct ffblk f;
  155.   char b[13];
  156.  
  157.   /* Point p to start of name, copy name into b */
  158.   p = strrchr(a, '\\');
  159.   q = strrchr(a, '/');
  160.   if (q > p && q != NULL)
  161.     p = q;
  162.   q = strrchr(a, ':');
  163.   if (q > p && q != NULL)
  164.     p = q;
  165.   if (p == NULL)
  166.     p = a;
  167.   else
  168.     p++;
  169.   if (strlen(p) > 12)
  170.     return 1;
  171.   strcpy(b, p);
  172.  
  173.   /* Find files */
  174.   r = findfirst(a, &f, FIND);
  175.   while (r == 0)
  176.   {
  177.     if ((p - a) + strlen(f.ff_name) >= NAMLN)
  178.     {
  179.       printf("??name got too long---abandoning this recursion\n");
  180.       return 0;
  181.     }
  182.     strcpy(p, f.ff_name);
  183.     search(a);                  /* Search for pattern in file a */
  184.     r = findnext(&f);
  185.   }
  186.  
  187.   /* Find directories */
  188.   strcpy(p, "*.*");
  189.   r = findfirst(a, &f, FIND | FA_DIREC);
  190.   while (r == 0)
  191.   {
  192.     if (f.ff_attrib & FA_DIREC &&
  193.         strcmp(f.ff_name, ".") && strcmp(f.ff_name, ".."))
  194.     {
  195.       if ((p - a) + strlen(f.ff_name) + 1 + strlen(b) >= NAMLN)
  196.       {
  197.         printf("??name got too long---abandoning this recursion\n");
  198.         return 0;
  199.       }
  200.       strcpy(p, f.ff_name);
  201.       strcat(a, "\\");
  202.       strcat(a, b);
  203.       recurse(a);
  204.     }
  205.     r = findnext(&f);
  206.   }
  207.   return 0;
  208. }
  209.  
  210.  
  211. void main(int argc, char *argv[])
  212. {
  213.   int j, k;
  214.   char *p;
  215.   char a[NAMLN];
  216.  
  217.   /* Help if one or no arguments */
  218.   if (argc < 3)
  219.   {
  220.     printf("XF version 1.0  Mark Adler  8 Oct 1989\n\
  221. \n\
  222. XF hex file1 file2 ...  will search for the hexadecimal pattern 'hex'\n\
  223. in all files matching the (possibly ambiguous) file name in 'filen',\n\
  224. that are in the path in 'filen', and any matching files in any\n\
  225. subdirectories, subsubdirectories, etc. in that path.  (If there is\n\
  226. no path, the current path is assumed.)  For example:\n\
  227. \n\
  228.      xf 12ff \\*.com\n\
  229. \n\
  230. will search all the *.com files on the current device, wherever they\n\
  231. are, for the hex bytes 0x12, 0xff.\n");
  232.     return;
  233.   }
  234.  
  235.   /* Get hex search pattern */
  236.   pln = 0;
  237.   for (j = 0, p = argv[1]; *p; p++, j = !j)
  238.   {
  239.     if ((k = *p) >= '0' && k <= '9')
  240.       k -= '0';
  241.     else if ((k &= 0x5f) >= 'A' && k <= 'F')
  242.       k -= 'A' - 10;
  243.     else
  244.     {
  245.       printf("?invalid hexadecimal search value---bad character\n");
  246.       return;
  247.     }
  248.     if (j)
  249.       pat[pln++] += k;
  250.     else
  251.       pat[pln] = k << 4;
  252.   }
  253.   if (j)
  254.   {
  255.     printf("?invalid hexadecimal search value---odd # of digits\n");
  256.     return;
  257.   }
  258.  
  259.   /* Search arguments */
  260.   fls = 0;
  261.   fnd = 0;
  262.   for (j = 2; j < argc; j++)
  263.     if (recurse(strcpy(a, argv[j])))
  264.       printf("?arg <%s> invalid---name too long\n", argv[j]);
  265.  
  266.   /* Show overall results */
  267.   printf("searched %ld file%s, ", fls, fls == 1 ? "" : "s");
  268.   if (fnd)
  269.     printf("found pattern %ld time%s\n", fnd, fnd == 1 ? "" : "s");
  270.   else
  271.     printf("pattern not found\n");
  272. }
  273.