[net.micro.amiga] Binary Search and replace utility

dillon@CORY.BERKELEY.EDU (Matt Dillon) (04/28/86)

	This is the program I wrote that allowed me to fix the priority that
the run command executed processes.  The format for the command is:

sr file xx xx xx xx  ...			where xx are bytes in HEX
				or
sr file xx xx xx -r xx xx xx 

	The first form simply reports all occurances of the sequence in the
file (usually an executable).  The second form actually replaces a given
sequence with another sequence (of the same length).  Thus, to set the
priority that run run's processes, do:

sr run 72 fb 60 00 -r 72 00 60 00

	The 72 fb being a MOVEQ #-5,d1 . (Don't do this on your only
copy of RUN .. do it to your 'working' version).  

NOTE: There is no provision for just changing the Nth occursion of the
string... SR changes ALL matches.  There is obviously room for improvement
in this program.  For instance, you cannot change the 72 00 back to a 
72 fb because there are two occurances of the sequence.  You'll have to
go into Wack yourself and find a sequence which only appears once; I 
leave it to you.


					-Matt

----------------------------------------------------------------

#include <lattice/stdio.h>
#include <lattice/fcntl.h>

#define BUFSIZE 512

static int replace, ssize, rsize, fd;
static unsigned char Search[128], Replace[128];

extern char *rtemplate();
extern long whereami();
extern long lseek();


main(argc, argv)
char *argv[];
{
   int i, result, open_flags;

   if (argc < 3) {
      puts ("sr file <search bytes in hex> [-r replace bytes in hex]");
      exit (1);
   }
   for (i = 2; i < argc; ++i) {
      if (*argv[i] == '-') {
         switch (*++argv[i]) {
         case 'r':
            replace = 1;
            break;
         default:
            puts ("-r :replace with");
            break;
         }
      } else {
         if (replace) {
            stch_i(argv[i],&result);
            Replace[rsize++] = result;
         } else {
            stch_i(argv[i],&result);
            Search[ssize++] = result;
         }
      }
   }
   if (replace && rsize != ssize) {
      puts ("replace not same size as search");
      exit (1);
   }
   open_flags = (replace) ? O_RDWR : O_RDONLY;
   fd = open (argv[1], open_flags);
   if (fd < 0) {
      puts ("could not open file");
      exit (1);
   }
   do_stuff();
   lseek (fd, 0L, 2);
   close(fd);
}


do_stuff()
{
   register unsigned char *ptr;
   register int i;

   printf ("ssize is: %d\n", ssize);
   while (ptr = rtemplate(ssize)) {
      for (i = 0; i < ssize; ++i) {
         if (Search[i] != ptr[i])
            break;
      }
      if (i == ssize) {
         printf ("OFFSET: %8lx\n", whereami());
         if (replace) {
            for (i = 0; i < ssize; ++i)
               ptr[i] = Replace[i];
            wtemplate(ssize);
         }
      }
      skip();
   }
}

static unsigned char Buf[BUFSIZE];
static long base;                   /* base seek position */
static int offset, size;            /* offset from base   */

char *
rtemplate(bytes)
{
   int r;

   if (offset + bytes > size) {
      if (offset < size)
         movmem (Buf + offset, Buf, size - offset);
      r = read(fd, Buf + size - offset, BUFSIZE - (size - offset));
      if (r < 0) {
         puts ("read failed");
         close (fd);
         exit (1);
      }
      base += offset;
      size = r + size - offset;
      offset = 0;
   }
   if (offset + bytes > size)
      return (NULL);
   return((char *)&Buf[offset]);
}

wtemplate(bytes)
{
   if (lseek(fd, base + offset, 0) != base + offset) {
      puts ("seek failed");
      close(fd);
      exit (1);
   }
   if (write(fd, &Buf[offset], bytes) != bytes) {
      puts ("write failed");
      close(fd);
      exit (1);
   }
   if (lseek(fd, base + offset, 0) != base + offset) {
      puts ("seek2 failed");
      close(fd);
      exit (1);
   }
}

skip()
{
   if (++offset == size) {
      base += offset;
      offset = 0;
      size = read(fd, Buf, BUFSIZE);
   }
}

long
whereami()
{
   return (base + offset);
}

dillon@cory (04/28/86)

Subject: Binary Search and replace utility (very simple)


	This is the program I wrote that allowed me to fix the priority that
the run command executed processes.  The format for the command is:

sr file xx xx xx xx  ...			where xx are bytes in HEX
				or
sr file xx xx xx -r xx xx xx 

	The first form simply reports all occurances of the sequence in the
file (usually an executable).  The second form actually replaces a given
sequence with another sequence (of the same length).  Thus, to set the
priority that run run's processes, do:

sr run 72 fb 60 00 -r 72 00 60 00

	The 72 fb being a MOVEQ #-5,d1 . (Don't do this on your only
copy of RUN .. do it to your 'working' version).  

NOTE: There is no provision for just changing the Nth occursion of the
string... SR changes ALL matches.  There is obviously room for improvement
in this program.  For instance, you cannot change the 72 00 back to a 
72 fb because there are two occurances of the sequence.  You'll have to
go into Wack yourself and find a sequence which only appears once; I 
leave it to you.


					-Matt

----------------------------------------------------------------

#include <lattice/stdio.h>
#include <lattice/fcntl.h>

#define BUFSIZE 512

static int replace, ssize, rsize, fd;
static unsigned char Search[128], Replace[128];

extern char *rtemplate();
extern long whereami();
extern long lseek();


main(argc, argv)
char *argv[];
{
   int i, result, open_flags;

   if (argc < 3) {
      puts ("sr file <search bytes in hex> [-r replace bytes in hex]");
      exit (1);
   }
   for (i = 2; i < argc; ++i) {
      if (*argv[i] == '-') {
         switch (*++argv[i]) {
         case 'r':
            replace = 1;
            break;
         default:
            puts ("-r :replace with");
            break;
         }
      } else {
         if (replace) {
            stch_i(argv[i],&result);
            Replace[rsize++] = result;
         } else {
            stch_i(argv[i],&result);
            Search[ssize++] = result;
         }
      }
   }
   if (replace && rsize != ssize) {
      puts ("replace not same size as search");
      exit (1);
   }
   open_flags = (replace) ? O_RDWR : O_RDONLY;
   fd = open (argv[1], open_flags);
   if (fd < 0) {
      puts ("could not open file");
      exit (1);
   }
   do_stuff();
   lseek (fd, 0L, 2);
   close(fd);
}


do_stuff()
{
   register unsigned char *ptr;
   register int i;

   printf ("ssize is: %d\n", ssize);
   while (ptr = rtemplate(ssize)) {
      for (i = 0; i < ssize; ++i) {
         if (Search[i] != ptr[i])
            break;
      }
      if (i == ssize) {
         printf ("OFFSET: %8lx\n", whereami());
         if (replace) {
            for (i = 0; i < ssize; ++i)
               ptr[i] = Replace[i];
            wtemplate(ssize);
         }
      }
      skip();
   }
}

static unsigned char Buf[BUFSIZE];
static long base;                   /* base seek position */
static int offset, size;            /* offset from base   */

char *
rtemplate(bytes)
{
   int r;

   if (offset + bytes > size) {
      if (offset < size)
         movmem (Buf + offset, Buf, size - offset);
      r = read(fd, Buf + size - offset, BUFSIZE - (size - offset));
      if (r < 0) {
         puts ("read failed");
         close (fd);
         exit (1);
      }
      base += offset;
      size = r + size - offset;
      offset = 0;
   }
   if (offset + bytes > size)
      return (NULL);
   return((char *)&Buf[offset]);
}

wtemplate(bytes)
{
   if (lseek(fd, base + offset, 0) != base + offset) {
      puts ("seek failed");
      close(fd);
      exit (1);
   }
   if (write(fd, &Buf[offset], bytes) != bytes) {
      puts ("write failed");
      close(fd);
      exit (1);
   }
   if (lseek(fd, base + offset, 0) != base + offset) {
      puts ("seek2 failed");
      close(fd);
      exit (1);
   }
}

skip()
{
   if (++offset == size) {
      base += offset;
      offset = 0;
      size = read(fd, Buf, BUFSIZE);
   }
}

long
whereami()
{
   return (base + offset);
}