#include <exec/types.h>
#include <exec/memory.h>
#include <exec/execbase.h>
#include <dos/dos.h>

#include <FidoNet.h>
#include <jbio.h>
#include <CharTabs.h>

#include <stdlib.h>
#include <string.h>

#include <clib/alib_protos.h>
#include <clib/exec_protos.h>
#include <clib/dos_protos.h>

#define VERSION "1.5"

UBYTE *ver="\0$VER: ConvPkt "VERSION" ("__COMMODORE_DATE__")";

struct jbList
{
   struct jbNode *First;
   struct jbNode *Last;
};

struct jbNode
{
   struct jbNode *Next;
};

struct ChrsNode
{
   struct jbNode Node;
   UBYTE parsedpattern[200];
   UBYTE *chrs;
   UBYTE *defaultchrs;
};

struct jbList ChrsList;

jbNewList(struct jbList *list);
jbAddNode(struct jbList *list, struct jbNode *node);
jbFreeList(struct jbList *list,struct jbNode *firstnode,ULONG sizenode);
jbFreeNum(struct jbList *list,ULONG num,ULONG size);
jbFreeNode(struct jbList *list,struct jbNode *node,ULONG size);

#define PKT_MINREADLEN  200
#define PKT_CHUNKLEN  10000

struct TextChunk
{
   struct TextChunk *Next;
   ULONG Length;
   UBYTE Data[PKT_CHUNKLEN];
};

extern struct ExecBase *SysBase;

struct FileNode
{
   struct Node Node;
   UBYTE File[200];
};

struct List FileList;

#define ARG_FILE           0
#define ARG_TO             1
#define ARG_CHRSLIST       2
#define ARG_DEFAULTCHRS    3
#define ARG_IGNORECHRS     4
#define ARG_NOCHRS         5
#define ARG_CHRSONLY       6
#define ARG_CP865          7

UBYTE *argstring="FILE/A,TOCHRS=TO,CHRSLIST/K,DEFAULTCHRS=DEFCHRS/K,IGNORECHRS/S,NOCHRS/S,CHRSONLY/S,CP865/S";
ULONG argarray[8];

struct PktHeader PktHeader;
struct PktMsgHeader PktMsgHeader;

UBYTE Msg_To[36];
UBYTE Msg_From[36];
UBYTE Msg_Subject[72];
UBYTE Msg_DateTime[20];
UBYTE Msg_CHRS[50];
UBYTE Msg_Area[100];

struct jbList Msg_TextChunks;

BOOL longread,shortread,nomem,diskfull,messageend;
BOOL brk;

#define CHARSET_SKIP    -1

BOOL cmd_ignorechrs;
BOOL cmd_nochrs;
BOOL cmd_chrsonly;
UBYTE *cmd_chrs;
UBYTE *cmd_defaultchrs;

struct RDArgs *rdargs;

Xlat(UBYTE *buf,UBYTE *chrs,ULONG len)
{
   ULONG c;

   if(argarray[ARG_CP865])
   {
      if(chrs == IbmToAmiga) chrs=IbnToAmiga;
      if(chrs == AmigaToIbm) chrs=AmigaToIbn;
      if(chrs == DefToAmiga) chrs=DfnToAmiga;
   }

   if(!chrs)
      return;

   for(c=0;c<len;c++)
   {
      if(buf[c]!=0 && chrs[buf[c]]==0)
         buf[c]='?';

      else
         buf[c]=chrs[buf[c]];
   }
}

UBYTE *GetCharset(UBYTE *string,UBYTE *defchrs)
{
   if(strncmp(string,"IBMPC",5)==0)
      return(IbmToAmiga);

   else if(strncmp(string,"SWEDISH",7)==0)
      return(SF7ToAmiga);

   else if(strncmp(string,"MAC",3)==0)
      return(MacToAmiga);

   else if(strncmp(string,"LATIN",5)==0)
      return(NULL);

   return(defchrs);
}


ProcessKludge(UBYTE *kludge, ULONG klen)
{
   if(strncmp(kludge,"\x01CHRS:",6)==0)
   {
      strncpy(Msg_CHRS,&kludge[7],49);
      if(klen-11<49) Msg_CHRS[klen-8]=0;
      else           Msg_CHRS[49]=0;
      klen=0;
   }

   if(strncmp(kludge,"\x01CHARSET:",9)==0)
   {
      strncpy(Msg_CHRS,&kludge[10],49);
      if(klen-11<49) Msg_CHRS[klen-11]=0;
      else           Msg_CHRS[49]=0;
      klen=0;
   }

   return(klen);
}

ULONG ReadNull(UBYTE *buf, ULONG maxlen, struct jbFile *jb)
{
   /* Reads from jb until buffer full or NULL */

   WORD ch,c=0;

   if(shortread) return(0);

   ch=jbGetChar(jb);

   while(ch!=-1 && ch!=0 && c!=maxlen-1)
   {
      buf[c++]=ch;
      ch=jbGetChar(jb);
   }
   buf[c]=0;

   if(ch==-1)
      shortread=TRUE;

   if(ch!=0 && c==maxlen-1)
      longread=TRUE;

   return(c);
}

ULONG ReadCR(UBYTE *buf, ULONG maxlen, struct jbFile *jb)
{
   /* Reads from jb until buffer full or CR */

   WORD ch,c=0;

   ch=jbGetChar(jb);

   while(ch!=-1 && ch!=0 && ch!=10 && ch !=13 && c!=maxlen-1)
   {
      buf[c++]=ch;
      ch=jbGetChar(jb);
   }

   if(ch==13 || ch==10)
      buf[c++]=ch;

   if(ch==0)  messageend=TRUE;
   if(ch==-1) shortread=TRUE;

   return(c);
}

void CleanMemMessage(void)
{
   if(Msg_TextChunks.First->Next)
      jbFreeList(&Msg_TextChunks,Msg_TextChunks.First->Next,sizeof(struct TextChunk));
}

BOOL WriteNull(struct jbFile *jb,UBYTE *str)
{
   jbWrite(jb,str,strlen(str)+1);
}

ConvertPkt(UBYTE *file)
{
   struct TextChunk *ThisChunk;
   ULONG rlen,msgnum;
   struct jbFile *jbin,*jbout;
   UBYTE out[200];
   UBYTE *chrs;
   struct TextChunk *chunk;
   BOOL noconv;
   UBYTE firstline[200];
   UBYTE area[200];
   UBYTE *destchrs,*defchrs;
   ULONG c;
   struct ChrsNode *chrsnode;
   BPTR l;
   struct FileInfoBlock *fib;

   Printf("Converting %s...\n",file);

   if(!(l=Lock(file,SHARED_LOCK)))
   {
      Printf("Unable to lock file\n");
      return;
   }

   if(!(fib=(struct FileInfoBlock *)AllocMem(sizeof(struct FileInfoBlock),MEMF_ANY)))
   {
      Printf("Out of memory\n");
      UnLock(l);
      return;
   }

   Examine(l,fib);

   if(!(jbin=jbOpen(file,MODE_OLDFILE,10000)))
   {
      PrintFault(IoErr(),NULL);
      UnLock(l);
      FreeMem(fib,sizeof(struct FileInfoBlock));
      return;
   }

   strcpy(out,file);
   strncat(out,".tmp",190);

   if(jbRead(jbin,&PktHeader,sizeof(struct PktHeader))!=sizeof(struct PktHeader))
   {
      Printf("Packet header is too short\n");
      jbClose(jbin);
      UnLock(l);
      FreeMem(fib,sizeof(struct FileInfoBlock));
      return;
   }

   if(PktHeader.PktType!=0x0200)
   {
      Printf("Not a Type-2 packet\n");
      jbClose(jbin);
      UnLock(l);
      FreeMem(fib,sizeof(struct FileInfoBlock));
      return;
   }

   if(!(jbout=jbOpen(out,MODE_NEWFILE,10000)))
   {
      jbClose(jbin);
      PrintFault(IoErr(),NULL);
      UnLock(l);
      FreeMem(fib,sizeof(struct FileInfoBlock));
      return;
   }

   jbWrite(jbout,&PktHeader,sizeof(struct PktHeader));

   if(diskfull)
   {
      PrintFault(IoErr(),"I/O error");
      jbClose(jbin);
      jbClose(jbout);
      DeleteFile(out);
      UnLock(l);
      FreeMem(fib,sizeof(struct FileInfoBlock));
      return;
   }

   shortread=FALSE;
   longread=FALSE;

   if(jbRead(jbin,&PktMsgHeader,sizeof(struct PktMsgHeader)) < 2)
   {
      Printf("Message header for msg #1 is too short\n");
      jbClose(jbin);
      jbClose(jbout);
      DeleteFile(out);
      UnLock(l);
      FreeMem(fib,sizeof(struct FileInfoBlock));
      return;
   }

   msgnum=0;

   while(PktMsgHeader.PktType==0x0200)
   {
      msgnum++;

      ((struct TextChunk *)Msg_TextChunks.First)->Length=NULL;
      ThisChunk=Msg_TextChunks.First;

      /* Get header strings */

      Msg_CHRS[0]=0;
      Msg_Area[0]=0;

      ReadNull(Msg_DateTime,20,jbin);
      ReadNull(Msg_To,36,jbin);
      ReadNull(Msg_From,36,jbin);
      ReadNull(Msg_Subject,72,jbin);

      /* Corrupt packet? */

      if(shortread)
      {
         Printf("Message header for msg #%lu is short\n",msgnum);
         jbClose(jbin);
         jbClose(jbout);
         DeleteFile(out);
         UnLock(l);
         FreeMem(fib,sizeof(struct FileInfoBlock));
         return;
      }

      if(longread)
      {
         Printf("Header strings too long in msg #%lu\n",msgnum);
         jbClose(jbin);
         jbClose(jbout);
         DeleteFile(out);
         UnLock(l);
         FreeMem(fib,sizeof(struct FileInfoBlock));
         return;
      }

      messageend=FALSE;

      rlen=ReadCR(firstline,190,jbin);
      firstline[rlen]=0;

      destchrs=cmd_chrs;
      defchrs=cmd_defaultchrs;

      ThisChunk->Data[0]=0;

      if(strncmp(firstline,"AREA:",5)==0)
      {
         strcpy(area,&firstline[5]);
         for(c=strlen(area);c;c--) if(area[c]<32) area[c]=0;
         strcpy(Msg_Area,area);
      }
      else
      {
         strcpy(area,"NETMAIL");
      }

      for(chrsnode=ChrsList.First;chrsnode;chrsnode=chrsnode->Node.Next)
         if(MatchPatternNoCase(chrsnode->parsedpattern,area)) break;

      if(chrsnode)
      {
         destchrs=chrsnode->chrs;
         defchrs=chrsnode->defaultchrs;
      }

      ThisChunk->Length=strlen(ThisChunk->Data);

      if(strncmp(firstline,"AREA:",5)!=0)
      {
         strcat(ThisChunk->Data,firstline);

        if(ThisChunk->Data[ThisChunk->Length]==1 && destchrs!=(UBYTE *)CHARSET_SKIP)
            rlen=ProcessKludge(&ThisChunk->Data[ThisChunk->Length],rlen);

         ThisChunk->Length+=rlen;
      }

      while(messageend==FALSE)
      {
         if(PKT_CHUNKLEN-ThisChunk->Length<PKT_MINREADLEN)
         {
            Printf("Allocated more memory\n");

            if(!(ThisChunk=(struct TextChunk *)AllocMem(sizeof(struct TextChunk),MEMF_ANY)))
            {
               Printf("Out of memory\n");
               jbClose(jbin);
               jbClose(jbout);
               DeleteFile(out);
               CleanMemMessage();
               UnLock(l);
               FreeMem(fib,sizeof(struct FileInfoBlock));
               return;
            }

            jbAddNode(&Msg_TextChunks,(struct jbNode *)ThisChunk);
            ThisChunk->Length=0;
         }

         rlen=ReadCR(&ThisChunk->Data[ThisChunk->Length],PKT_CHUNKLEN-ThisChunk->Length,jbin);

         if(shortread)
         {
            Printf("Got unexpected EOF when reading msg #%lu\n",msgnum);
            jbClose(jbin);
            jbClose(jbout);
            DeleteFile(out);
            CleanMemMessage();
            UnLock(l);
            FreeMem(fib,sizeof(struct FileInfoBlock));
            return;
         }

         if(ThisChunk->Data[ThisChunk->Length]==1 && destchrs!=(UBYTE *)CHARSET_SKIP)
            rlen=ProcessKludge(&ThisChunk->Data[ThisChunk->Length],rlen);

         ThisChunk->Length+=rlen;
      }

      if(SetSignal(0L,0L) & SIGBREAKF_CTRL_C)
      {
         brk=TRUE;
         jbClose(jbin);
         jbClose(jbout);
         DeleteFile(out);
         CleanMemMessage();
         UnLock(l);
         FreeMem(fib,sizeof(struct FileInfoBlock));
         return;
      }

      if(cmd_ignorechrs)
         chrs=defchrs;
      else
         chrs=GetCharset(Msg_CHRS,defchrs);

      noconv=FALSE;

      if(chrs == NULL && destchrs == NULL)             noconv=TRUE;
      if(chrs == SF7ToAmiga && destchrs == AmigaToSF7) noconv=TRUE;
      if(chrs == MacToAmiga && destchrs == AmigaToMac) noconv=TRUE;
      if(chrs == IbmToAmiga && destchrs == AmigaToIbm) noconv=TRUE;

      if(destchrs == (UBYTE *)CHARSET_SKIP) noconv=TRUE;
      if(Msg_CHRS[0]==0 && cmd_chrsonly) noconv=TRUE;

      if(!noconv)
      {
         Xlat(Msg_To,chrs,strlen(Msg_To));
         Xlat(Msg_From,chrs,strlen(Msg_From));
         Xlat(Msg_Subject,chrs,strlen(Msg_Subject));

         for(chunk=Msg_TextChunks.First;chunk;chunk=chunk->Next)
            Xlat(chunk->Data,chrs,chunk->Length);

         Xlat(Msg_To,destchrs,strlen(Msg_To));
         Xlat(Msg_From,destchrs,strlen(Msg_From));
         Xlat(Msg_Subject,destchrs,strlen(Msg_Subject));

         for(chunk=Msg_TextChunks.First;chunk;chunk=chunk->Next)
            Xlat(chunk->Data,destchrs,chunk->Length);
      }

      jbWrite(jbout,&PktMsgHeader,sizeof(struct PktMsgHeader));

      WriteNull(jbout,Msg_DateTime);
      WriteNull(jbout,Msg_To);
      WriteNull(jbout,Msg_From);
      WriteNull(jbout,Msg_Subject);

      if(Msg_Area[0])
      {
         jbWrite(jbout,"AREA:",5);
         jbWrite(jbout,Msg_Area,strlen(Msg_Area));
         jbPutChar(jbout,13);
      }

      if(!cmd_nochrs && !(Msg_CHRS[0]==0 && cmd_chrsonly) && destchrs!=(UBYTE *)CHARSET_SKIP)
      {
         UBYTE *chrsbuf;

         chrsbuf="\x01CHRS: LATIN-1 2\x0d";

         if(destchrs==AmigaToMac)
            chrsbuf="\x01CHRS: MAC 2\x0d";

         if(destchrs==AmigaToIbm)
            chrsbuf="\x01CHRS: IBMPC 2\x0d";

         if(destchrs==AmigaToSF7)
            chrsbuf="\x01CHRS: SWEDISH 1\x0d";

         jbWrite(jbout,chrsbuf,strlen(chrsbuf));
      }

      for(chunk=Msg_TextChunks.First;chunk && !diskfull;chunk=chunk->Next)
         jbWrite(jbout,chunk->Data,chunk->Length);

      jbPutChar(jbout,0);

      CleanMemMessage();

     if(diskfull)
         PrintFault(IoErr(),"I/O error");

      if(nomem || diskfull)
      {
         jbClose(jbin);
         jbClose(jbout);
         DeleteFile(out);
         UnLock(l);
         FreeMem(fib,sizeof(struct FileInfoBlock));
         return;
      }

      if(jbRead(jbin,&PktMsgHeader,sizeof(struct PktMsgHeader)) < 2)
      {
         Printf("Message header for msg #%lu is too short\n",msgnum);
         jbClose(jbin);
         jbClose(jbout);
         DeleteFile(out);
         UnLock(l);
         FreeMem(fib,sizeof(struct FileInfoBlock));
         return;
      }
   }

   jbPutChar(jbout,0);
   jbPutChar(jbout,0);

   jbClose(jbin);
   jbClose(jbout);
   UnLock(l);

   DeleteFile(file);
   Rename(out,file);

   SetComment(file,fib->fib_Comment);
   SetProtection(file,fib->fib_Protection);
   SetFileDate(file,&fib->fib_Date);

   FreeMem(fib,sizeof(struct FileInfoBlock));
}

myputs(UBYTE *str)
{
   Write(Output(),str,strlen(str));
}

ULONG jbcpos;

jbstrcpy(UBYTE *dest,UBYTE *src,ULONG maxlen)
{
   ULONG d=0;
   UBYTE stopchar1,stopchar2;

   while(src[jbcpos]==32 || src[jbcpos]==9) jbcpos++;

   if(src[jbcpos]=='"')
   {
      jbcpos++;
      stopchar1='"';
      stopchar2=0;
   }
   else
   {
   	stopchar1=' ';
   	stopchar2=9;
   }

   while(src[jbcpos]!=stopchar1 && src[jbcpos]!=stopchar2 && src[jbcpos]!=10 && src[jbcpos]!=0 && d<maxlen-1)
   {
      if(src[jbcpos]=='\\' && src[jbcpos+1]!=0 && src[jbcpos+1]!=10)
      {
         jbcpos++;
         dest[d++]=src[jbcpos++];
      }

      else
         dest[d++]=src[jbcpos++];
   }
   dest[d]=0;
   if(src[jbcpos]==9 || src[jbcpos]==' ' || src[jbcpos]=='"') jbcpos++;

   if(d!=0 || stopchar1=='"') return(TRUE);

   return(FALSE);
}

BOOL ReadChrsFile(UBYTE *file)
{
   struct ChrsNode *chrsnode;
   BPTR fh;
   UBYTE buf[500];
   UBYTE parsedpattern[210];
   UBYTE buf1[110],buf2[30],buf3[30];
   ULONG line;
   UBYTE *defchrs,*chrs;

   if(!(fh=Open(file,MODE_OLDFILE)))
   {
      PrintFault(IoErr(),file);
      return(FALSE);
   }

   line=0;

   while(FGets(fh,buf,495))
   {
      line++;

      if(buf[0]!=0 && buf[strlen(buf)-1]=='\n')
         buf[strlen(buf)-1]=0;

      if(buf[0]!=0 && buf[0]!=';')
      {
         jbcpos=0;

         jbstrcpy(buf1,buf,100);

         if(ParsePatternNoCase(buf1,parsedpattern,200)==-1)
         {
            Printf("Error in %s on line %lu: Invalid or too long pattern\n",file,line);
            Close(fh);
            return(FALSE);
         }

         if(!jbstrcpy(buf2,buf,25))
         {
            Printf("Error in %s on line %lu: No charset specified\n",file,line);
            Close(fh);
            return(FALSE);
         }

         chrs=NULL;

        if(stricmp(buf2,"IBMPC")==0)
            chrs=AmigaToIbm;

         else if(stricmp(buf2,"MAC")==0)
            chrs=AmigaToMac;

         else if(stricmp(buf2,"SWEDISH")==0)
            chrs=AmigaToSF7;

         else if(stricmp(buf2,"SKIP")==0)
            chrs=(UBYTE *)CHARSET_SKIP;

         else if(stricmp(buf2,"LATIN-1")!=0)
         {
            Printf("Error in %s on line %lu: Unknown charset \"%s\"\n",file,line,buf2);
            Close(fh);
            return(FALSE);
         }

         defchrs=cmd_defaultchrs;

         if(jbstrcpy(buf3,buf,25))
         {
           if(stricmp(buf3,"IBMPC")==0)
               defchrs=IbmToAmiga;

            else if(stricmp(buf3,"MAC")==0)
               defchrs=MacToAmiga;

            else if(stricmp(buf3,"SWEDISH")==0)
               defchrs=SF7ToAmiga;

            else if(stricmp(buf3,"DEFAULT")==0)
               defchrs=DefToAmiga;

            else if(stricmp(buf3,"LATIN-1")!=0)
            {
               Printf("Error in %s on line %lu: Unknown charset \"%s\"\n",file,line,buf3);
               Close(fh);
               return(FALSE);
            }
         }

         if(!(chrsnode=(struct ChrsNode *)AllocMem(sizeof(struct ChrsNode),MEMF_CLEAR)))
         {
            Printf("Out of memory\n");
            Close(fh);
            return(FALSE);
         }

         ParsePatternNoCase(buf1,chrsnode->parsedpattern,200);
         chrsnode->defaultchrs=defchrs;
         chrsnode->chrs=chrs;
         jbAddNode(&ChrsList,(struct jbNode *)chrsnode);
      }
   }

   Close(fh);
   return(TRUE);
}

void _main(void)
{
   UBYTE str[600];
   UBYTE path[300];
   UBYTE parsedpattern[600];
   BPTR l;
   struct FileInfoBlock *fib;
   struct FileNode *fn;

   if(SysBase->LibNode.lib_Version<37)
   {
      myputs("Sorry! This program requires Kickstart 2.04 or higher\n");
      _exit(0);
   }

   cmd_defaultchrs=DefToAmiga;
   cmd_chrs=NULL;

   jbNewList(&ChrsList);

   if(!(rdargs = (struct RDArgs *)ReadArgs(argstring,argarray,NULL)))
   {
      PrintFault(IoErr(),NULL);
      _exit(10);
   }

   if(!argarray[ARG_TO] && !argarray[ARG_CHRSLIST])
   {
      Printf("You must specify either TOCHRS or CHRSLIST\n");
      _exit(10);
   }

   if(argarray[ARG_TO])
   {
      if(stricmp((UBYTE *)argarray[ARG_TO],"IBMPC")==0)
         cmd_chrs=AmigaToIbm;

      else if(stricmp((UBYTE *)argarray[ARG_TO],"MAC")==0)
         cmd_chrs=AmigaToMac;

      else if(stricmp((UBYTE *)argarray[ARG_TO],"SWEDISH")==0)
         cmd_chrs=AmigaToSF7;

      else if(stricmp((UBYTE *)argarray[ARG_TO],"SKIP")==0)
         cmd_chrs=(UBYTE *)CHARSET_SKIP;

      else if(stricmp((UBYTE *)argarray[ARG_TO],"LATIN-1")!=0)
      {
         Printf("Unknown charset \"%s\"\n",argarray[ARG_TO]);
         FreeArgs(rdargs);
         _exit(0);
      }
   }

   if(argarray[ARG_DEFAULTCHRS])
   {
      if(stricmp((UBYTE *)argarray[ARG_DEFAULTCHRS],"IBMPC")==0)
         cmd_defaultchrs=IbmToAmiga;

      else if(stricmp((UBYTE *)argarray[ARG_DEFAULTCHRS],"MAC")==0)
         cmd_defaultchrs=MacToAmiga;

      else if(stricmp((UBYTE *)argarray[ARG_DEFAULTCHRS],"SWEDISH")==0)
         cmd_defaultchrs=SF7ToAmiga;

      else if(stricmp((UBYTE *)argarray[ARG_DEFAULTCHRS],"DEFAULT")==0)
         cmd_defaultchrs=DefToAmiga;

      else if(stricmp((UBYTE *)argarray[ARG_DEFAULTCHRS],"LATIN-1")!=0)
      {
         Printf("Unknown charset \"%s\"\n",argarray[ARG_DEFAULTCHRS]);
         FreeArgs(rdargs);
         _exit(0);
      }
   }

   if(argarray[ARG_IGNORECHRS])
      cmd_ignorechrs=TRUE;

   if(argarray[ARG_NOCHRS])
      cmd_nochrs=TRUE;

   if(argarray[ARG_CHRSONLY])
      cmd_chrsonly=TRUE;

   strcpy(str,(UBYTE *)argarray[ARG_FILE]);

   if(argarray[ARG_CHRSLIST])
   {
      if(!ReadChrsFile((UBYTE *)argarray[ARG_CHRSLIST]))
      {
         FreeArgs(rdargs);
         jbFreeList(&ChrsList,ChrsList.First,sizeof(struct ChrsNode));
         _exit(0);
      }
   }

   FreeArgs(rdargs);

   jbNewList(&Msg_TextChunks);

   Msg_TextChunks.First = (struct TextChunk *)AllocMem(sizeof(struct TextChunk),MEMF_ANY);
   Msg_TextChunks.First->Next=NULL;
   Msg_TextChunks.Last = Msg_TextChunks.First;

   if(!Msg_TextChunks.First)
   {
      Printf("Out of memory\n");
      jbFreeList(&ChrsList,ChrsList.First,sizeof(struct ChrsNode));
      _exit(10);
   }

   if(ParsePatternNoCase(FilePart(str),parsedpattern,590))
   {
      strcpy(path,str);
      *((UBYTE *)PathPart(path))=0;

      if(fib=(struct FileInfoBlock *)AllocMem(sizeof(struct FileInfoBlock),MEMF_ANY))
      {
         if(l=Lock(path,SHARED_LOCK))
         {
            Examine(l,fib);
            NewList(&FileList);

            while(ExNext(l,fib) && !nomem && !diskfull && !brk)
            {
               if(SetSignal(0L,0L) & SIGBREAKF_CTRL_C)
               {
                  brk=TRUE;
               }
               else if(MatchPatternNoCase(parsedpattern,fib->fib_FileName))
               {
                  if(fn=AllocMem(sizeof(struct FileNode),MEMF_CLEAR))
                  {
                     strcpy(fn->File,path);
                     AddPart(fn->File,fib->fib_FileName,200);
                     AddTail(&FileList,(struct Node *)fn);
                  }
                  else
                  {
                     Printf("Out of memory\n");
                     nomem=TRUE;
                  }
               }
            }
            UnLock(l);

            while(fn=RemHead(&FileList))
            {
               if(SetSignal(0L,0L) & SIGBREAKF_CTRL_C)
                  brk=TRUE;

               if(!brk) ConvertPkt(fn->File);

               FreeMem(fn,sizeof(struct FileNode));
            }
         }
         else
         {
            Printf("Unable to lock %s: ",str);
            PrintFault(IoErr(),NULL);
         }

         FreeMem(fib,sizeof(struct FileInfoBlock));
      }
      else
      {
         nomem=TRUE;
         Printf("Out of memory\n");
      }
   }
   else
   {
      ConvertPkt(str);
   }

   FreeMem(Msg_TextChunks.First,sizeof(struct TextChunk));
   jbFreeList(&ChrsList,ChrsList.First,sizeof(struct ChrsNode));

   if(brk)
      Printf("*** Break\n");

   if(nomem || diskfull)
      _exit(10);

   _exit(0);
}

