/*****************************************************************************/
/** Program: Stow        Version: 0.95ß                                     **/
/** Date: September 1994                                                    **/
/** Author: Leonard D Atkinson II                                           **/
/**                                                                         **/
/** Purpose:  Stow examines a given pathname for files and then copies      **/
/**           those files to a device, volume by volume, with the lease     **/
/**           ammount of waste of space.  It optionally outputs a list of   **/
/**           what volumes hold what files.                                 **/
/**                                                                         **/
/** Requires: LIST, COPY, FORMAT commands somewhere in the path.            **/
/**                                                                         **/
/** History (since 0.8ß):                                                   **/
/**  0.85ß                                                                  **/
/**       Changed command line options to use ReadArgs()                    **/
/**       (As suggested by Richard Ludwig)                                  **/
/**                                                                         **/
/**  0.90ß                                                                  **/
/**       Changed file-choosing method, now we do it recursively            **/
/**                                                                         **/
/**  0.95ß                                                                  **/
/**       Ironed out some bugs                                              **/
/**       Finally got perfect method for figuring disk space used per file  **/
/**       Added options for setting blocksize and choosing if overflow      **/
/**            files are copied or not                                      **/
/**                                                                         **/
/** This source copyright 1994 by Leonard D Atkinson II                     **/
/*****************************************************************************/


/****************************/
/* INCLUDES                 */
/****************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <time.h>             /*so we can make unique filename*/
#include <libraries/dos.h>    /*for the checking disk space*/
#include <exec/memory.h>      /*for AllocMem()*/
#include <exec/types.h>       /*for ULONG definition*/
#include <clib/dos_protos.h>
#include <clib/exec_protos.h>
#include "ansi.h"             /*My own ansi macros*/


/****************************/
/* Data Types               */
/****************************/
struct my_file_node {         /*For putting files into linked list*/
     char filename[40];
     long filesize;
     struct my_file_node *next;
     };

struct disk_slot {            /*for making a disk full of files*/
     struct my_file_node *file;
     struct disk_slot *next;
     };

/****************************/
/* function prototypes      */
/****************************/
long check_free_space(char *); /*Returns the free space on the given volume*/
void bad_format(void); /*sends user format and exits*/
void set_num(char *, int); /*changes the integer into ABC form*/
void my_system(char *, char *);/*execute system call with error checking*/
void verify_file(char *, int);/*checks given filesize to copied filesize*/
void cat_files();/*tack arg2 onto arg3*/
int  find_disk(struct my_file_node *, struct disk_slot *);
void do_format(void); /*formats a disk, or puts info into script*/

/****************************/
/* global variables         */
/****************************/
char fixed_size = 0;               /*FLAG: assume fixed size?*/  
int assumed_size = 899072 - 512;   /*default disk size, blank noicons FFS*/
                                   /*seems like we need to spare a block*/
int volume_num = 0;                /*counter of number of volumes used*/
int max_waste = 10*1024;           /*default maximum waste*/
char output_device[40] = "";       /*where the files are copied*/
char output_script[40] = "";       /*name of script file*/
char format_options[40] = "";      /*options passed to FORMAT*/
char current_diskname[4] = "   ";  /*four-char disk numbering*/
char dos_input[80];                /*Working strings*/
char archive_name[40] = "STOW_";   /*prefix for disk names*/
long block_size = 512;             /*block size for output device*/
FILE *fp;                          /*Generic file point for reading temp file*/
                                   /*and writing to the output file          */

/*****************************************************************************/
/* Main                                                                      */
/*****************************************************************************/
main(int argc, char *argv[]) {

     /****************************/
     /* Variables                */
     /****************************/
     char filename[40],   /*global filename, for reading into*/
          temp_file_name[80];
     long filesize = 0;   /*global filesize, for reading into*/
     long total = 0;      /*total bytes tally*/

     struct my_file_node *head, /*Pointers to linked list*/
                         *temp, 
                         *temp2;
     
     struct disk_slot *work_disk,
                      *current_slot,
                      *temp_slot;

     int count,i; /*generic count variable*/
     char list_output[40] = "";/*name of list of files copied.*/
     char input_dir[40] = "";/*input directory to be copied from*/

     char verify_copies = 0;
     char quiet_output = 0;
     char list_sort = 1;

	char	Template[]="STOW V0.95 ©1994 Leonard D Atkinson II\nFROM/A,TO/A,LIST/K,ASSUME/K/N,WASTE/K/N,BLOCKSIZE/K/N,SCRIPT/K,FORMAT/K,NAME/K,VERIFY/S,QUIET/S,NOSORT/S,NOCOPYALL/S";
	struct	RDArgs * rdargs=NULL;
	long	     MyArgs[13];
	ULONG 	error_value=0;

     char copy_all = 1;

     /***********************************************************/
     /* Parse command line arguments using AmigaDos's ReadArgs  */
     /***********************************************************/
     for(count = 0;count<13;count++) MyArgs[count] = 0;
     if( rdargs = (struct RDArgs *) ReadArgs(Template,MyArgs,NULL)) {
          if(MyArgs[0]) strcpy(input_dir,(char *)MyArgs[0]);          /*source dir*/

          if(MyArgs[1]) strcpy(output_device,(char *)MyArgs[1]);      /*dest dir*/

          if(MyArgs[2]) strcpy(list_output,(char *)MyArgs[2]);        /*output file*/

          if(MyArgs[4]){                                              /*Max waste*/
               max_waste = *(long *)MyArgs[4];
               max_waste *= 1024;
               printf("max waste is %d\n", max_waste);
               }

          if(MyArgs[5]) {
               block_size = *(long *)MyArgs[5];
               printf("Setting block size to %d.\n", block_size);
               if(block_size == 0) {
                    ChangeColors(YELLOW,BLACK);
                    printf("Block sizes of 0 are bad luck!\n");
                    ChangeColors(RED,BLACK);
                    exit(1);
                    }
               }

          if(MyArgs[6]) {                                             /*to script*/
               strcpy(output_script,(char *)MyArgs[6]);
               }

          if(MyArgs[7]) {                                             /*format*/
               /*if options are provided, do it, else just*/
               /*put a space in there for signaling purposes*/
               if(strlen((char *)MyArgs[7])) {
                    strcpy(format_options,(char *)MyArgs[7]);
                    }
               else {
                    strcpy(format_options," ");
                    }
               }

          if(MyArgs[8]){                                              /*name*/
               strncpy(archive_name,(char *)MyArgs[8],16);
               strcat(archive_name,"_");
               /*turn all non-printables into underscores*/
               for(i = 0; i<strlen(archive_name); i++)
                    if(isspace(archive_name[i])) archive_name[i] = '_';
               }

          if(MyArgs[9]) verify_copies = 1;                            /*verify*/
               
          if(MyArgs[10]) quiet_output = 1;                             /*quiet*/

          if(MyArgs[11]) list_sort = 0;                               /*sort*/

          if(MyArgs[12]) 
               copy_all = 0;                    /*don't copy all files*/

          if(MyArgs[3]){                                              /*assumed size*/
               assumed_size=*(long *)MyArgs[3];
               assumed_size *= 1024;
               assumed_size -= block_size; /*spare one block*/
               fixed_size = 1;
               }

          FreeArgs((struct RDArgs *) rdargs); /*done parsing, so free memory*/
          }
     else {
          error_value=IoErr();
          PrintFault(error_value,"Stow");
          }

     if((strlen(output_device) == 0) || (strlen(input_dir) == 0)) bad_format();

     if((strlen(output_script) > 0) && (fixed_size != 1)) {
          printf("Output scripts require an assumed size.\n");
          printf("Auto-enabling an assumed size of %d.\n",assumed_size+block_size);
          fixed_size = 1;
          }

     if(quiet_output != 1) printf("Assembling the list of files to be stowed.\n");

     /***********************************************************/
     /*Call the LIST command to make a list of all the files    */
     /*name the file with current time afterwards to avoid      */
     /*two versions of the program from clobbering each other's */
     /*temp files.                                              */
     /***********************************************************/
     sprintf(temp_file_name, "t:stow%d", (unsigned int)time(NULL));
     sprintf(dos_input, "list %s %s >%s", input_dir, "lformat \"%S %L\"", temp_file_name );
     my_system(dos_input,"Can't create file list in temp!");     

     fp = fopen(temp_file_name,"r");  /*open the file just created*/
     if(fp == NULL) {
          ChangeColors(YELLOW,BLACK);
          printf("For some reason the temp file can't be opened!\n");
          ChangeColors(RED,BLACK);
          exit(1);
          }

     /*Make a head node*/
     head = (struct my_file_node *) AllocMem( sizeof(struct my_file_node),
          MEMF_PUBLIC | MEMF_CLEAR );
     if(head == NULL) {
          ChangeColors(YELLOW,BLACK);
          printf("Couldn't allocate memory!\n");
          ChangeColors(RED,BLACK);
          exit(1);
          }          
     head->next = NULL;
     head->filesize = 0;
     strcpy(head->filename, "HEAD NODE");

     /****************************/
     /* Build Linked List        */
     /****************************/
     while(fscanf(fp, "%s %d",filename,&filesize) != EOF) {/*while more*/
          if((filesize > 0) && (strlen(filename)>0)) {
                            /*only bother making nodes for non-empty files*/
                            /*with valid names                            */

               total += filesize;

               /*make a new node*/
               temp = (struct my_file_node *) 
                    AllocMem( sizeof(struct my_file_node),
                              MEMF_PUBLIC | MEMF_CLEAR );
               if(temp == NULL) {
                    ChangeColors(YELLOW,BLACK);
                    printf("Couldn't allocate memory!\n");
                    ChangeColors(RED,BLACK);
                    exit(1);
                    } 
               strcpy(temp->filename, filename);/*fill with information*/
               temp->filesize = filesize;

               temp2 = head;/*Find the right place to insert new node*/

               if(list_sort == 1) {/*find insertion point*/
                    while((temp2->next != NULL) && 
                         (((temp2->next)->filesize) > (temp->filesize))) 
                              temp2 = temp2->next;
                    }
               else {
                    /*just add to end of list now*/
                    while(temp2->next != NULL) temp2 = temp2->next;
                    }

               /*Insert Node*/
               if(temp2->next == NULL) {
                    temp2->next = temp;
                    temp->next = NULL;
                    }
               else {
                    temp->next = temp2->next;
                    temp2->next = temp;
                    }
               }
          }
     fclose(fp); /*close temp file*/
     if(DeleteFile(temp_file_name) == TRUE) { /*delete temp file*/
          ChangeColors(YELLOW,BLACK);
          printf("For some reason the temp file can't be deleted!\n");
          ChangeColors(RED,BLACK);
          exit(1);
          }

      if(strlen(list_output) > 0) { /*if requested, open output file*/
          fp = fopen(list_output,"w");
          if(fp == NULL) {
               ChangeColors(YELLOW,BLACK);
               printf("Error--Cannot open file %s for output.\n",list_output);
               ChangeColors(RED,BLACK);
               exit(1);
               }
          fprintf(fp,"!!! Files Stowed !!!\n");
          fclose(fp);
          }    
     if(strlen(output_script) > 0) { /*if requested, open output script*/
          fp = fopen(output_script,"w");
          if(fp == NULL) {
               ChangeColors(YELLOW,BLACK);
               printf("Error--Cannot open file %s for output.\n",output_script);
               ChangeColors(RED,BLACK);
               exit(1);
               }
          fprintf(fp,"echo Stowing %s from script\n",input_dir);
          fclose(fp);
          }

     /***************************************************************/
     /*if the input directory doesn't end in / or : then assume it's*/
     /*a directory and put the / in for later catenation.           */
     /***************************************************************/
     if((input_dir[strlen(input_dir) - 1] != '/') && 
        (input_dir[strlen(input_dir) - 1] != ':')) 
          strcat(input_dir, "/");
          
     if(quiet_output != 1) {
          printf("%d total bytes to be packed.\n",total);
          printf("This will take about %d FFS floppies.\n",(total/890000)+1);
          }

     /* make work_disk head node */
     work_disk = (struct disk_slot *) AllocMem( sizeof(struct disk_slot),
          MEMF_PUBLIC | MEMF_CLEAR );
     if(work_disk == NULL) {
          ChangeColors(YELLOW,BLACK);
          printf("Couldn't allocate memory!\n");
          ChangeColors(RED,BLACK);
          exit(1);
          }          
     work_disk->next = NULL;
     work_disk->file = head;

     if(strlen(output_script) != 0) { /*Add disk prompt to script*/
          fp = fopen(output_script,"a");
          if(fp == NULL) {
               ChangeColors(YELLOW,BLACK);
               printf("Error--Cannot open file %s for output.\n",temp_file_name);
               ChangeColors(RED,BLACK);
               exit(1);
               }
          fprintf(fp, "ask \"next disk\"\n");
          fclose(fp);
          }
     else {
          printf("Please put a disk in %s and press RETURN.\n",output_device);
          getchar();
          }

     /*If we need to format a disk, do it*/
     if(strlen(format_options) != 0) {
          do_format();
          }

     if(fixed_size == 0) { /*we don't have fixed sizes*/
          assumed_size = check_free_space(output_device);
          assumed_size -= block_size;
          }

     /****************************/
     /* Main Loop                */
     /****************************/
     while(find_disk(head->next, work_disk)) {
          /*made a disk, so copy the files*/

          current_slot = work_disk->next;
          while(current_slot != NULL) {
               temp = head;
               while(temp->next != current_slot->file) {
                    temp = temp->next;
                    }
               temp->next = temp->next->next;
               /*Inform user what's going on*/
               if(quiet_output != 1) {
                    printf("Copying %s to disk %d\n",
                              current_slot->file->filename,
                              volume_num);
                    }

               /*assemble dos call to COPY*/
               sprintf(dos_input, "copy %s%s %s",input_dir,current_slot->file->filename,output_device);

               if(strlen(output_script) > 0) { /*if requested, open output file*/
                    fp = fopen(output_script,"a");
                    if(fp == NULL) {
                         ChangeColors(YELLOW,BLACK);
                         printf("Error--Cannot open file %s for output.\n",list_output);
                         ChangeColors(RED,BLACK);
                         exit(1);
                         }
                    fprintf(fp,"%s\n",dos_input);
                    fclose(fp);
                    }
               else {
                    my_system(dos_input,"Copy Failed!\n");
                    }

               if(verify_copies == 1) {
                    sprintf(filename,"%s%s",input_dir,current_slot->file->filename);
                    verify_file(filename,current_slot->file->filesize);
                    }

               /*Add filename to output file*/
               if(strlen(list_output) > 0) { /*if requested, open output file*/
                    fp = fopen(list_output,"a");
                    if(fp == NULL) {
                         ChangeColors(YELLOW,BLACK);
                         printf("Error--Cannot open file %s for output.\n",list_output);
                         ChangeColors(RED,BLACK);
                         exit(1);
                         }
                    fprintf(fp,"%-32.32s %6d %s%s\n",current_slot->file->filename,
                         current_slot->file->filesize,archive_name,current_diskname);
                    fclose(fp);
                    }

               /*Free up the memory from the nodes*/
               FreeMem(current_slot->file, sizeof(struct disk_slot));
               temp_slot = current_slot;
               current_slot = current_slot->next;
               FreeMem(temp_slot, sizeof(struct disk_slot));
               }

          work_disk->next = NULL;

          /*Quick check: do we have enough to make a disk?*/
          temp = head->next;
          count = 0;
          while(temp != NULL) {
               count += temp->filesize;
               temp = temp->next;
               }
          if(count < (assumed_size - max_waste)) {
               break;
               }

          if(strlen(output_script) > 0) {
               fp = fopen(output_script,"a");
               if(fp == NULL) {
                    ChangeColors(YELLOW,BLACK);
                    printf("Error--Cannot open file %s for output.\n",list_output);
                    ChangeColors(RED,BLACK);
                    exit(1);
                    }
               fprintf(fp, "ask \"next disk\"\n");
               fclose(fp);
               }
          else {
               printf("Remove the volume in %s and put in another.\n",output_device);
               printf("Press RETURN");
               getchar();
               }

          volume_num++; /*advance to next volume number*/

          /*If we need to format a disk, do it*/
          if(strlen(format_options) != 0) {
               do_format();
               }

          if(fixed_size == 0) { /*we don't have fixed sizes*/
               assumed_size = check_free_space(output_device);
               }
          }

     if(copy_all == 1) {
          printf("Copying remaining files to last disk.\n");

          if(strlen(output_script) > 0) {
               fp = fopen(output_script,"a");
               if(fp == NULL) {
                    ChangeColors(YELLOW,BLACK);
                    printf("Error--Cannot open file %s for output.\n",list_output);
                    ChangeColors(RED,BLACK);
                    exit(1);
                    }
               fprintf(fp, "ask \"next disk\"\n");
               fclose(fp);
               }
          else {
               printf("Remove the volume in %s and put in another.\n",output_device);
               printf("Press RETURN");
               getchar();
               }

          volume_num++; /*advance to next volume number*/

          /*If we need to format a disk, do it*/
          if(strlen(format_options) != 0) {
               do_format();
               }

          temp = head->next;
          while(temp != NULL) {
               /*Inform user what's going on*/
               if(quiet_output != 1) {
                    printf("Copying %s to disk %d\n",
                              temp->filename,
                              volume_num);
                    }

               /*assemble dos call to COPY*/
               sprintf(dos_input, "copy %s%s %s",input_dir,temp->filename,output_device);

               if(strlen(output_script) > 0) { /*if requested, open output file*/
                    fp = fopen(output_script,"a");
                    if(fp == NULL) {
                         ChangeColors(YELLOW,BLACK);
                         printf("Error--Cannot open file %s for output.\n",list_output);
                         ChangeColors(RED,BLACK);
                         exit(1);
                         }
                    fprintf(fp,"%s\n",dos_input);
                    fclose(fp);
                    }
               else {
                    my_system(dos_input,"Copy Failed!\n");
                    }

               if(verify_copies == 1) {
                    sprintf(filename,"%s%s",input_dir,temp->filename);
                    verify_file(filename,temp->filesize);
                    }

               /*Add filename to output file*/
               if(strlen(list_output) > 0) { /*if requested, open output file*/
                    fp = fopen(list_output,"a");
                    if(fp == NULL) {
                         ChangeColors(YELLOW,BLACK);
                         printf("Error--Cannot open file %s for output.\n",list_output);
                         ChangeColors(RED,BLACK);
                         exit(1);
                         }
                    fprintf(fp,"%-32.32s %6d %s%s\n",temp->filename,
                         temp->filesize,archive_name,current_diskname);
                    fclose(fp);
                    }
               head->next = temp->next;
               FreeMem(temp, sizeof(struct my_file_node));
               temp = head->next;
               }
          }
     else {
          printf("\nno more disks can be made\n");
          }

     }/*end of main*/

/******************************************************************************/
/**do_format()                                                               **/
/**Formats a disk                                                            **/
/******************************************************************************/
void do_format() {

     set_num(current_diskname,volume_num);/*make new disk name*/

     sprintf(dos_input,"FORMAT DRIVE %s NAME %s%s %s",
          output_device,archive_name,current_diskname, format_options);
     if(strlen(output_script) != 0) { /*if requested, open output file*/
          fp = fopen(output_script,"a");
          if(fp == NULL) {
               ChangeColors(YELLOW,BLACK);
               printf("Error--Cannot open file %s for output.\n",output_script);
               ChangeColors(RED,BLACK);
               exit(1);
               }
          fprintf(fp, "%s\n",dos_input);
          fclose(fp);
          }
     else {
          my_system(dos_input,"Can't format disk!\n");
          }

     }/*end of do_format*/


/******************************************************************************/
/**find_disk()                                                               **/
/**Recursively builds the perfect disk                                       **/
/******************************************************************************/
int find_disk(struct my_file_node *input_files,
               struct disk_slot *output_disk) {

     struct my_file_node *current_file;
     struct disk_slot *current_slot;
     long current_size;

     /*count up the disk size*/
     current_size = 0;
     current_slot = output_disk->next;
     while(current_slot != NULL) {
          current_size += current_slot->file->filesize;
          current_slot = current_slot->next;
          }

     current_file = input_files;
     while(current_file != NULL) {
          if(((((((current_file->filesize/block_size)+1)/72)+1)*block_size) + current_size) > assumed_size) {
               current_file = current_file->next;
               }
          else { /*current_file will fit on disk*/
               /*add file*/
               current_slot = output_disk;
               while(current_slot->next != NULL) current_slot = current_slot->next;

               current_slot->next = (struct disk_slot *) AllocMem( sizeof(struct disk_slot),
                    MEMF_PUBLIC | MEMF_CLEAR );
               if(current_slot == NULL) {
                    ChangeColors(YELLOW,BLACK);
                    printf("Couldn't allocate memory!\n");
                    ChangeColors(RED,BLACK);
                    exit(1);
                    }
               current_slot->next->next = NULL;
               current_slot->next->file = current_file;

               if(((((((current_file->filesize/block_size)+1)/72)+1)*block_size) + current_size) > (assumed_size - max_waste)) {
                    /*we've made a good disk*/
                    return(TRUE);
                    }
               else { /*we need more files*/
                    if(find_disk(current_file->next, output_disk)) {
                         /*we find a disk after this*/
                         return(TRUE);
                         }
                    else {/*dead end, no disks found*/
                         /*remove file, try next one*/
                         FreeMem(current_slot->next, sizeof(struct disk_slot));
                         current_slot->next = NULL;
                         current_file = current_file->next;
                         
                         }
                    }
               }
          }/*end of while loop*/
          return(FALSE);/*no disks beyond this point*/
     }




/******************************************************************************/
/**check_free_space()                                                        **/
/**Takes the name of a device and returns the bytes free                     **/
/******************************************************************************/
long check_free_space(char *checked_device) {

     /*************************/
     /* Variables             */
     /*************************/
     struct FileLock *lock;
     struct InfoData *info_ptr;
     long return_value;

     /***********************************/
     /*Get a new InfoData structure     */
     /*AllocMem assures a 4 byte boundry*/
     /***********************************/
     info_ptr = (struct InfoData *) AllocMem( sizeof( struct InfoData ),
          MEMF_PUBLIC | MEMF_CLEAR );
     if( info_ptr == NULL ) {
          ChangeColors(YELLOW,BLACK);
          printf("Couldn't allocate memory!\n");
          ChangeColors(RED,BLACK);
          exit(1);
          }

     /*get a file lock*/
     lock = (struct FileLock *) Lock( checked_device, SHARED_LOCK );
     if( lock == NULL ) {
          ChangeColors(YELLOW,BLACK);
          printf("Could not lock your desination device!\n");
          ChangeColors(RED,BLACK);
          FreeMem( info_ptr, sizeof( struct InfoData ) );
          exit(1);
          }
     if( Info((BPTR) lock, info_ptr ) == NULL ) {
          ChangeColors(YELLOW,BLACK);
          printf("Could not examine your destination device!\n");
          ChangeColors(RED,BLACK);
          FreeMem( info_ptr, sizeof( struct InfoData ) );
          UnLock((BPTR)lock );  
          exit(1);
          }

     /*Set return value*/
     return_value = (info_ptr->id_NumBlocks - info_ptr->id_NumBlocksUsed) 
            * info_ptr->id_BytesPerBlock;

     /*Free up the file and memory*/
     UnLock((BPTR) lock );  
     FreeMem( info_ptr, sizeof( struct InfoData ) );
     
     return(return_value);
     }/*end of check_free_space() */

/******************************************************************************/
/**  bad_format                                                              **/
/**  instructs user that a bad format of options was given                   **/
/******************************************************************************/
void bad_format(){
     printf("Usage: stow <input directory> <output directory>\n");
     printf("Followed by these options:\n");
     printf("LIST <filename>       create a file with a list of all files\n");
     printf("ASSUME [n]            assume disk size nKbytes, or 842K default\n");
     printf("WASTE <n>             allow a maximum of nKbytes of unused space\n");
     printf("SCRIPT <filename>     put all commands into file instead\n");
     printf("FORMAT \"<options>\"    format each disk using options\n");
     printf("NAME <name>           name each disk with name_XXX\n");
     printf("VERIFY                verify each copy\n");
     printf("QUIET                 don't output to console\n");
     printf("NOSORT                don't sort files before building disks\n");
     printf("BLOCKSIZE <n>         set block size to n\n");
     printf("NOCOPYALL             don't copy the leftover files\n");  
     exit(1);
     }


/******************************************************************************/
/**  set_num                                                                 **/
/**  converts int to letter form for naming disks                            **/
/******************************************************************************/
void set_num(char *output, int num) {

     output[0] = 'A' + (num/(26*26));
     num -= ((num/(26*26)) * (26*26));
     output[1] = 'A' + (num/(26));
     num -= ((num/(26)) * 26);
     output[2] = 'A' + num;

     return;
     }

/******************************************************************************/
/** my_system                                                                **/
/** Gets rid of a bunch of repetitive calls to system()                      **/
/******************************************************************************/
void my_system(char *sys_call, char *error_string) {

     if(system(sys_call) != 0) {
          ChangeColors(YELLOW,BLACK);
          printf("%s\n",error_string);
          ChangeColors(RED,BLACK);
          exit(1);
          }
     return;
     }

/******************************************************************************/
/** Verify_File()                                                            **/
/** Checks actual filesize verses the original                               **/
/******************************************************************************/
void verify_file(char *checked_file, int check_size) {
     /*************************/
     /* Variables             */
     /*************************/
     struct FileLock *lock;
     struct FileInfoBlock *fib_ptr;

     /***********************************/
     /*Get a new FileInfoBlock structure*/
     /*AllocMem assures a 4 byte boundry*/
     /***********************************/
     fib_ptr = (struct FileInfoBlock *)
          AllocMem( sizeof( struct FileInfoBlock ),
          MEMF_PUBLIC | MEMF_CLEAR );
     /* Check if we have allocated the memory successfully: */
     if( fib_ptr == NULL ) {
          ChangeColors(YELLOW,BLACK);
          printf("Couldn't allocate memory!\n");
          ChangeColors(RED,BLACK);
          exit(1);
          }

     /*get a file lock*/
     lock = (struct FileLock *) Lock( checked_file, SHARED_LOCK );
     if( lock == NULL ) {
          ChangeColors(YELLOW,BLACK);
          printf("Could not lock %s!\n",checked_file);
          ChangeColors(RED,BLACK);
          FreeMem( fib_ptr, sizeof( struct FileInfoBlock ) );
          exit(1);
          }

     if( Examine((BPTR) lock, fib_ptr ) == NULL ) {
          ChangeColors(YELLOW,BLACK);
          printf("Could not examine %s!\n",checked_file);
          ChangeColors(RED,BLACK);
          FreeMem( fib_ptr, sizeof( struct FileInfoBlock ) );
          UnLock((BPTR) lock );  
          exit(1);
          }

     /*Set return value*/
     if(fib_ptr->fib_Size != check_size) {
          ChangeColors(YELLOW,BLACK);
          printf("%s did not verify!\n",checked_file);
          ChangeColors(RED,BLACK);
          FreeMem( fib_ptr, sizeof( struct FileInfoBlock ) );
          UnLock((BPTR) lock );  
          exit(1);
          }

     /*Free up the file and memory*/
     UnLock((BPTR) lock );  
     FreeMem( fib_ptr, sizeof( struct FileInfoBlock ) );
     
     return;
     }/*end of verify_file() */


