/*
#include <libraries/dos.h>
#include <libraries/dosextens.h>
#include <exec/memory.h>
*/
/*----------------------------------------------------------

		FIND (c) 1987 Bob Malzan
	FIND sucht eine (mit Joker) spezifizierte Datei
	in allen Unterinhaltsverzeichnissen und gibt, falls
	gefunden, den dazugehoerigen Pfadnamen aus.

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


APTR		DosBase,OpenLibrary(),AllocMem();
struct File	*Out,*Output();
struct FileLock	*Lock();
VOID		Unlock(),FreeMem();
char		toupper(),*strcat();
char		*LockName,*SearchName;
BOOL		EntryFound,Examine(),ExNext(),strcmp();
BOOL		Found=FALSE;
LONG		Code=0L;

char ClrEoln[] = { 0x1B, 0x9B, 'K' };
#define CLREOLN Write(Out,ClrEoln,3L)

/*---------------------- Hilfsroutinen --------------------------*/

/* PrintOut loescht die aktuelle Zeile und schreibt String nach Out  */

VOID PrintOut(String)
char *String;
{
  CLREOLN;
  Write(Out,String,(long)strlen(String));
}

/*    StrToUpper wandelt einen String in einen UpperCase-String   */

VOID StrToUpper(Str)
char *Str;
{
  while(*Str!=(char)0) {
    *Str=toupper(*Str);
    Str++;
  }
}

/*    StrEqual vergleicht zwei Strings, wobei Str1 '*' als Joker   */
/*    enthalten darf.						   */

BOOL StrEqual(Str1,Str2)
char *Str1,*Str2;
{
  UBYTE P1=0,P2=0;

  while ((strlen(Str1)>P1) && (strlen(Str2)>P2)) {
    if (*(Str1+P1) != toupper(*(Str2+P2))) {
      if (*(Str1+P1)=='*') {
        if (strlen(Str1)==P1+1) return(TRUE);
        P1++;
        while ( (strlen(Str2)>P2) && (toupper(*(Str2+P2)) != *(Str1+P1)) ) P2++;
        if ( strlen(Str2)==P2 ) return(FALSE);
      }
      else return(FALSE);
    }
    P1++; P2++;
  }
  if ( (*(Str1+P1)=='*') && (P1+1==strlen(Str1)) ) return(TRUE);
  if ( (P2<strlen(Str2)) || (P1<strlen(Str1)) ) return(FALSE);
  else return(TRUE);
}

/*	FFind ist die rekursive Prozedur, die alle Unterinhalts-  */
/*	verzeichnisse durchlaeuft.				  */

VOID FFind(LName,First)
char *LName;
BOOL First;
{
  struct FileLock *CurrLock;
  char Path[80]; /* ist ein lokaler String, in dem sich der Pfadname befindet */
  struct FileInfoBlock *FInfo;

  CurrLock=Lock(LName,SHARED_LOCK);
  if (CurrLock!=NULL) {
    FInfo=(struct FileInfoBlock *)AllocMem((LONG)sizeof(struct FileInfoBlock)
                                              ,MEMF_PUBLIC);
    if (FInfo==NULL) {
      PrintOut("Memory Problems!!\n");
      UnLock(CurrLock);
      return;
    }

    EntryFound=Examine(CurrLock,FInfo);
    EntryFound=ExNext(CurrLock,FInfo);
    while ((EntryFound) && !(Code&SIGBREAKF_CTRL_C)) {
      Code=SetSignal(0L,SIGBREAKF_CTRL_C);
      strcpy(&Path[0],LName);
      if (StrEqual(SearchName,&FInfo->fib_FileName)) {
        PrintOut("Found ");
        PrintOut(&Path[0]);
        if (!First) PrintOut("/");
        PrintOut(&FInfo->fib_FileName);
        if (FInfo->fib_DirEntryType>0) PrintOut(" <DIR>");
        PrintOut("\n");
        Found=TRUE;
      }
      if (FInfo->fib_DirEntryType>0) {
        if (!First) strcat(&Path[0],"/");
        strcat(&Path[0],&FInfo->fib_FileName[0]);
        PrintOut("Searching ");
        PrintOut(&Path[0]);
        PrintOut("                  \r");
        FFind(&Path[0],FALSE);
      }
      EntryFound=ExNext(CurrLock,FInfo);
    }
    FreeMem(FInfo,(LONG)sizeof(struct FileInfoBlock));
    UnLock(CurrLock);
  }
}

main(argc,argv)
int argc;
char *argv[];
{
  ULONG Length;
  BOOL First=FALSE;
  char Test;

  DosBase=OpenLibrary(DOSNAME,NULL);
  Out=Output();
  if (Out==NULL) exit(20L);
  argc--;
  if ((argc<1)||((argc==1)&&(**(argv+1)=='?'))) {
    PrintOut("Usage: ");
    PrintOut(*argv);
    PrintOut(" [ROOT],NAME/A\n");
    exit(0L);
  }

  if (argc==1) {
    LockName=":"; /* no ROOT specified -> current device root */
    SearchName=*(argv+1);
  }
  else {
    LockName=*(argv+1);
    SearchName=*(argv+2);
  }

  StrToUpper(SearchName);
  Test=*(LockName+strlen(LockName)-1);
  if ( (Test==':')||(Test=='/') ) First=TRUE;
  FFind(LockName,First);
  if (Code&SIGBREAKF_CTRL_C) {
    PrintOut(*argv);
    PrintOut(" aborted by ^C");
  }
  else if (!Found) {
    PrintOut("Couldn't find ");  PrintOut(SearchName);
  }
  PrintOut("               \n");
  CloseLibrary(DosBase);
}
