/*********************************************************************/         
/*                                                                   */   
/*    FREE Copyright 1987 by Tom Smythe                              */
/*         RealTime Asc. Seattle, Wa.                                */
/*         (206)-547-7292                                            */
/*         (206)-774-4735                                            */
/*                                                                   */
/*    Returns free bytes of memory available from specified drives   */
/*                                                                   */                                                               
/*                                                                   */
/*********************************************************************/         

#include <libraries/dos.h>
#include <libraries/dosextens.h>
#include <exec/types.h>cc
#include <exec/memory.h>
#include <functions.h>

#define   OFFSET    0x2eL
#define   ARGS     "bad arguments\n"
#define   IN       "need full path\n"
#define   READ     "list too long ?\n"
#define   WRITE    "write error\n"
#define   CLEAR    "list cleared\n"
#define   DONE     "list updated\n"
#define   BUFF     "out of memory\n"
#define   STOP     "Real"
#define   FREE     "Time"
#define   USAGE    "FREE Copyright 1987 by Tom Smythe\n\
     [32mRealTime Asc.[0m Seattle, Wa.\n\
     (206)-547-7292\n\
     (206)-774-4735 bbs\n\n\
     FREE    returns available memory.\n\
     <full path>/FREE -x <device list> updates list.\n\
     <full path>/FREE -x clears list.\n"  
     
struct FileHandle *    output       =  NULL;
struct FileHandle *    comfile      =  NULL;

struct Lock *          lock         =  NULL;
struct Lock *          mylock       =  NULL;

char *                 buf          =  NULL;
char *                 msg          =  NULL;
char                   outline[256] =  NULL;           
char                   *drive[7]    = 
                                    {"DF0:","DF1:","VD0:",FREE,FREE,FREE,STOP};

/***************************/ 

main(argc,argv)

   int argc;
   char *argv[];

   {
   char * getfree();
   char * control();
   
   output = Output();
   
   if (*(argv[1]) == '?') Write(output,USAGE,250L); 
      else  if (argc == 1) getfree(outline);
         else strcpy(outline,control(argc,argv));
         Write(output,outline,(long)strlen(outline));
   }
   
   

/***************************/ 
      

char * itos(ord)
   
   long   ord;
   
   {
   static char  ostring[10];
   int          next = 9;
   
   if (!ord) ostring[next--] = '0';
      
   while ((ord+9)/10)
      {      
      ostring[next--] = ord % 10 + 0x30;
      ord /= 10;
      }
   while (next+1) ostring[next--] = 0x20;
   return(ostring);
   }

/* ************************* */ 

long avail(disk)

   struct Lock *         *disk;
   
   {
   struct InfoData *     info;

   long bytes = 0L;

   info = AllocMem((long)sizeof(struct InfoData),MEMF_PUBLIC);
   Info(disk,info);
   bytes = (info->id_NumBlocks - info->id_NumBlocksUsed) * info->id_BytesPerBlock;
   FreeMem(info,(long)sizeof(struct InfoData));
   return(bytes);
   }

/* ************************* */ 

char * getfree(outline)

      char * outline;

      {
             
      long dfree = 0L;
      long cfree = 0L;
      long ffree = 0L;
      int  i = -1;
      
      Forbid();
      cfree = AvailMem(MEMF_CHIP);
      ffree = AvailMem(MEMF_FAST);
      Permit();
      
      strcat(outline,"[33mChip[0m");
      strcat(outline,itos(cfree));
      if (ffree)
         {
         strcat(outline,"   [33mFast[0m");
         strcat(outline,itos(ffree));
         }
      strcat(outline,"\n");   
   
      while (*(drive[++i] +3) == ':')
         {
         if (lock = Lock(drive[i],ACCESS_READ)) 
            {
            dfree = avail(lock);
            UnLock(lock);
            if (!dfree)
               {
               if (!strcmp(drive[i],"RAM:")) dfree = ffree + cfree;  
               if (!strcmp(drive[i],"ram:")) dfree = ffree + cfree;
               }
            strcat(outline,"[33m");
            strcat(outline,drive[i]);
            strcat(outline,"[0m");
            strcat(outline,itos(dfree));
            strcat(outline,"\n");   
            }   
         }
      }
      
/* ************************* */ 

char * control(Argc,Argv)

   int Argc;
   char * Argv[];
   
   {
   char *                       cleanup();
   char *                       msg = NULL;
   int i;
   
   if (strcmp(Argv[1],"-x")) return(ARGS);
   if (Argc > 2)
      for (i=Argc;i>2;i--) 
         if (*(Argv[i-1]+3) != ':') return(ARGS);

   if (!(mylock = Lock(Argv[0],ACCESS_READ))) return(IN);
   if (!(comfile = Open(Argv[0],MODE_OLDFILE))) return(cleanup(IN));
      
   if (!(buf = (char *)AllocMem(4L,MEMF_CHIP|MEMF_CLEAR))) return(cleanup(BUFF));
     
   Seek(comfile,OFFSET,OFFSET_BEGINNING);
   
   if (Argc == 2)
      {
      while ((Read(comfile,buf,4L) == 4L) && (strcmp(buf,STOP)))  
         {
         Seek(comfile,-4L,OFFSET_CURRENT);
         Write(comfile,FREE,4L);
         Seek(comfile,1L,OFFSET_CURRENT);
         }
      return(cleanup(strcmp(buf,STOP) ? READ : CLEAR));
      }
   
   while (Argv[i])

      {
      if ((Read(comfile,buf,4L) != 4L) || (!(strcmp(buf,STOP))))
         return(cleanup(READ));
         
      if (!strcmp(buf,FREE))
         {
         Seek(comfile,-4L,OFFSET_CURRENT);
         if (Write(comfile,Argv[i],4L) != 4L)
            return(cleanup(WRITE));
         i++;
         }
      Seek(comfile,1L,OFFSET_CURRENT);
      }     
    
   return(cleanup(DONE));
   }

/***************************/ 
char * cleanup(err)

   char *err;
   
   {
   if (comfile) Close(comfile);
   if (mylock) UnLock(mylock);
   if (buf) FreeMem(buf,4L);
   return(err);
   }

/***************************/ 
