#include <exec/types.h>
#include <proto/dos.h>          /* C= */
#include <proto/exec.h>
#include <utility/tagitem.h>
#include <exec/memory.h>
#include <dos/dosasl.h>
#include <stdio.h>              /* SAS printf */
#include <stdlib.h>             /*     qsort + atoi herfra */
#include <string.h>             /*     strengbehandling */
#include <ctype.h>              /*     isdigit */

const char versionsting[]="$VER: MaxFileAdd version 1.1 by Claus Dyring Jensen\n\0";

ULONG filescount[101];

struct maxfile
{
  ULONG DateDays;
  ULONG DateMins;
  ULONG Siz;
  ULONG Dl;
  UBYTE Flags;
  UBYTE Section;
  UBYTE Name[41];
  UBYTE Desc[60];
  UBYTE From[41];
  UBYTE Alias[41];
  UBYTE maxfilepad;
};

struct maxfile2
{
  UBYTE Name[41];
  UBYTE Section;
  UBYTE Flags;
  UBYTE maxfilepad2;
};

struct maxfile thefile;
struct maxfile2 thefile2;

char tempstr[100];
char tempstr2[100];

ULONG main(int argc,char *argv[])
{
struct AnchorPath *anchorpathptr;
BPTR filehandle,filehandle2,lock;
struct FileInfoBlock *fib;
BOOL more;
int areanumber;
int nul=0;
struct maxfile2 *indexptr=NULL;
int filesinindex;

  if(argc!=6)
  {
    printf("Usage: %s filepattern uploader alias areanumber path\n\n",argv[0]);
    printf("Filepattern: Files to include. Use full path and amiga wildcards.\n\n");
    printf("Uploader: Name of uploader, if any. Quote the name if it contains spaces\nUse \"\" if no name desired.\n\n");
    printf("Alias: Uploader's alias. Same as above.\n\n");
    printf("Areanumber: Maxs section number, from 0 to 99.\n\n");
    printf("Path: Path to your file.data and file.index. These two must be together.\n\n");
    printf("Descriptions will be taken from filecomments or promted for if the filecomment\nis empty.\n");
    printf("Datestamps are taken from files so use the C:SetDate command first if you want\ntoday's date on the files.\n");
    return(10);
  }
  areanumber=atoi(argv[4]);
  if(areanumber<0 || areanumber>99)
  {
    printf("Areanumbers should be between 0 and 99\n");
    return(10);
  }
  if(fib=AllocDosObject(DOS_FIB,0))
  {
    if(anchorpathptr=AllocVec(sizeof(struct AnchorPath),MEMF_ANY))
    {
      strcpy(tempstr,argv[5]);
      AddPart(tempstr,"file.data",80);
      if(lock=Lock(tempstr,ACCESS_READ))
      {
        UnLock(lock);
      }
      else
      {
        Fault(ERROR_OBJECT_NOT_FOUND,tempstr,tempstr2,100);
        printf("%s\n",tempstr2);
        FreeVec(anchorpathptr);
        FreeDosObject(DOS_FIB,fib);
        return(10);
      }
      if(filehandle=Open(tempstr,MODE_READWRITE))
      {
        Read(filehandle,tempstr,62);
        if(!strncmp(tempstr,"M A X's BBS",11))
        {
          strcpy(tempstr,argv[5]);
          AddPart(tempstr,"file.index",80);
          if(lock=Lock(tempstr,ACCESS_READ))
          {
            UnLock(lock);
          }
          else
          {
            Fault(ERROR_OBJECT_NOT_FOUND,tempstr,tempstr2,100);
            printf("%s\n",tempstr2);
            Close(filehandle);
            FreeVec(anchorpathptr);
            FreeDosObject(DOS_FIB,fib);
            return(10);
          }
          if(filehandle2=Open(tempstr,MODE_READWRITE))
          {
            Read(filehandle2,tempstr,62);
            if(!strncmp(tempstr,"M A X's BBS",11))
            {
              if(ExamineFH(filehandle2,fib))
              {
                if(Seek(filehandle2,62,OFFSET_BEGINNING)==-1)
                {
                  printf("Fatal error on file.index, file size or file is bad\n");
                  Close(filehandle2);
                  Close(filehandle);
                  FreeVec(anchorpathptr);
                  FreeDosObject(DOS_FIB,fib);
                  return(10);
                }
                filesinindex=(fib->fib_Size-62)/44;
                if(indexptr=AllocVec(filesinindex*44,MEMF_ANY))
                {
                  if(Read(filehandle2,indexptr,filesinindex*44)!=filesinindex*44)
                  {
                    printf("Coulden't read file.index\n");
                    FreeVec(indexptr);
                    Close(filehandle2);
                    Close(filehandle);
                    FreeVec(anchorpathptr);
                    FreeDosObject(DOS_FIB,fib);
                    return(10);
                  }
                  else
                  {
                    qsort(indexptr,filesinindex,44,&strcmp);
                  }
                }
                else
                {
                  printf("No free memory to hold file.index\n");
                  Close(filehandle2);
                  Close(filehandle);
                  FreeVec(anchorpathptr);
                  FreeDosObject(DOS_FIB,fib);
                  return(10);
                }
              }
              else
              {
                printf("Fatal error on file.index, file size or file is bad\n");
                Close(filehandle2);
                Close(filehandle);
                FreeVec(anchorpathptr);
                FreeDosObject(DOS_FIB,fib);
                return(10);
              }
              if(ExamineFH(filehandle,fib))
              {
                if(Seek(filehandle,62,OFFSET_BEGINNING)==-1)
                {
                  printf("Fatal error on file.data, file size or file is bad\n");
                  FreeVec(indexptr);
                  Close(filehandle2);
                  Close(filehandle);
                  FreeVec(anchorpathptr);
                  FreeDosObject(DOS_FIB,fib);
                  return(10);
                }
                Read(filehandle,filescount,404);
                if(Seek(filehandle,466+((fib->fib_Size-466)/202)*202,OFFSET_BEGINNING)==-1)
                {
                  printf("Fatal error on file.data, file size or file is bad\n");
                  FreeVec(indexptr);
                  Close(filehandle2);
                  Close(filehandle);
                  FreeVec(anchorpathptr);
                  FreeDosObject(DOS_FIB,fib);
                  return(10);
                }
                if(Seek(filehandle2,0,OFFSET_END)==-1)
                {
                  printf("Fatal error on file.index, file size or file is bad\n");
                  FreeVec(indexptr);
                  Close(filehandle2);
                  Close(filehandle);
                  FreeVec(anchorpathptr);
                  FreeDosObject(DOS_FIB,fib);
                  return(10);
                }
                anchorpathptr->ap_BreakBits=NULL;
                anchorpathptr->ap_Flags=0;
                anchorpathptr->ap_Strlen=0;
                if(MatchFirst(argv[1],anchorpathptr)==0)
                {
                  do
                  {
                    if(anchorpathptr->ap_Info.fib_DirEntryType<0)
                    {
                      if(bsearch(anchorpathptr->ap_Info.fib_FileName,indexptr,filesinindex,44,&strcmp))
                      {
                        printf("Dupe ignored:%s\n",anchorpathptr->ap_Info.fib_FileName);
                      }
                      else
                      {
                        printf("%s\n",anchorpathptr->ap_Info.fib_FileName);
                        filescount[0]++;
                        filescount[areanumber+1]++;
                        InitStruct(&nul,&thefile,sizeof(struct maxfile));
                        strncpy(thefile.Name,anchorpathptr->ap_Info.fib_FileName,40); /* Altid nul termineret */
                        strncpy(thefile.Desc,anchorpathptr->ap_Info.fib_Comment,59);
                        if(!strlen(thefile.Desc))
                        {
                          printf("Filedescription?\n-----------------------------------------------------------\n");
                          gets(thefile.Desc);
                          thefile.Desc[59]=0;
                          printf("\n");
                        }
                        strncpy(thefile.From,argv[2],40);
                        strncpy(thefile.Alias,argv[3],40);
                        thefile.Section=areanumber;
                        thefile.Siz=anchorpathptr->ap_Info.fib_Size;
                        thefile.DateDays=anchorpathptr->ap_Info.fib_Date.ds_Days;         /* Burde være NU, ikke fil oprettelses tid */
                        thefile.DateMins=anchorpathptr->ap_Info.fib_Date.ds_Minute;
                        if(Write(filehandle,&thefile,sizeof(struct maxfile))!=sizeof(struct maxfile)) printf("Write operation failed\n");
                        InitStruct(&nul,&thefile2,sizeof(struct maxfile2));
                        strcpy(thefile2.Name,thefile.Name);
                        thefile2.Section=areanumber;
                        if(Write(filehandle2,&thefile2,sizeof(struct maxfile2))!=sizeof(struct maxfile2)) printf("Write operation failed\n");
                      }
                    }
                    more=!MatchNext(anchorpathptr);
                    if(SetSignal(0L,SIGBREAKF_CTRL_C)&SIGBREAKF_CTRL_C)
                    {
                      more=FALSE;
                      printf("Aborting.. processed files have been saved.");
                    }
                  } while(more);
                  MatchEnd(anchorpathptr);
                  printf("\nAll done!\n");
                }
                else
                {
                  Fault(ERROR_OBJECT_NOT_FOUND,argv[1],tempstr,100);
                  printf("%s\n",tempstr);
                }
                Seek(filehandle,62,OFFSET_BEGINNING);
                if(Write(filehandle,filescount,404)!=404) printf("Write operation failed\n");
              }
              else
              {
                printf("File.data coulden't be accessed\n");
              }
            }
            else
            {
              printf("File.index not for MAXS BBS or mangled file\n");
            }
            Close(filehandle2);
          }
          else
          {
            printf("Coulden't open file.index\n");
          }
        }
        else
        {
          printf("File.data not for MAXS BBS or mangled file\n");
        }
        Close(filehandle);
      }
      else
      {
        printf("Couldn't open file.data\n");
      }
      FreeVec(anchorpathptr);
    }
    FreeDosObject(DOS_FIB,fib);
  }
  if(indexptr) FreeVec(indexptr);
  return(0);
}
