/* ----------------------------------------------------------------
 *
 *  Project: Filevirus Library
 *
 *  Program: fvkiller.c
 *
 *  Author : Bjorn Reese <breese@imada.ou.dk>
 *
 *  Short  : Example of a simple virus killer
 *           Compile with "sc LINK fvkiller.c"
 *
 * ---------------------------------------------------------------- */

#include <stdio.h>

#include <exec/types.h>
#include <exec/memory.h>
#include <dos/dos.h>
#include <dos/dostags.h>
#include <proto/exec.h>
#include <proto/dos.h>

#include <libraries/filevirus.h>
#include <proto/filevirus.h>

extern struct Library *SysBase;
struct FilevirusBase *FilevirusBase=NULL;

/* ---------------------------------------------------------------- */

long FileSize(BPTR file)
{
  long len = 0;
  struct FileInfoBlock *fib;

  if ( fib=AllocDosObjectTags(DOS_FIB, ADO_FH_Mode) ) {
    len = ExamineFH(file, fib) ? fib->fib_Size : 0L;
    FreeDosObject(DOS_FIB, fib);
  }
  return len;
}

/* ---------------------------------------------------------------- */

void RepairFile(struct FilevirusNode *p, char *fname)
{
  BPTR f = NULL;
  long len;
  void *buff;
  char answer[256];

  if ( f=Open(fname, MODE_OLDFILE) ) {

    len = FileSize(f);
    if (buff = AllocMem((ULONG)len, MEMF_ANY|MEMF_CLEAR) ) {

      Read(f, buff, len);
      p->fv_Buffer = buff;
      p->fv_BufferLen = (ULONG)len;

      printf("File: '%s' ", fname);

      if ( !fvCheckFile(p, 0) ) {

        if (p->fv_FileInfection != NULL) {

          printf("*** virus '%s' found\n", (p->fv_FileInfection)->fi_VirusName);
          printf("Repair (yes/no) : ");
          fgets(answer, 256, stdin);

          if (answer[0] == 'y') {

            switch (fvRepairFile(p, NULL, 0)) {

              case FVMSG_DELETE:
                Close(f);
                f = NULL;
                if ( DeleteFile(fname) )
                  printf("File deleted\n");
                else
                  printf("Error! Cannot delete\n");
                break;

              case FVMSG_RENAME:
                printf("Please rename\n");
                break;

              case FVMSG_SAVE:
                Close(f);
                if ( f=Open(fname, MODE_NEWFILE) ) {
                  Seek(f, 0, OFFSET_BEGINNING);
                  Write(f, buff, (int)p->fv_BufferLen);
                  printf("Hunk/code removed\n");
                } else
                  printf("Error! Unable to remove hunk/code\n");
                break;

              default:
                printf("No action taken\n");
                break;
            }
          }
        } else printf("clean\n");

      } else printf("error %d\n", p->fv_Status);

      FreeMem(buff, len);
    }
    if (f) Close(f);
  }
}

/* ---------------------------------------------------------------- */

int main(int argc, char *argv[])
{
  struct FilevirusNode *p;

  if ( FilevirusBase = (struct FilevirusBase *)OpenLibrary("filevirus.library", 2) ) {

    if ( p = fvAllocNode() ) {

      RepairFile(p, argv[1]);
      fvFreeNode(p);

    } else fprintf(stderr, "fvAllocNode() failed\n");

    CloseLibrary((struct Library *)FilevirusBase);

  } else fprintf(stderr, "Cannot open 'filevirus.library'\n");

}
