;/* Just execute to compile.

sc RamLibPatch
quit

*/

/*
**      $VER: RamLibPatch 1.4 (1.8.98)
**
**      Patches the "ramlib" process to use a bigger stack
**
**      written in 1998 by Andreas R. Kleinert, minor mods by Jim Cooper
**      All Rights Reserved.
*/

#define __USE_SYSBASE

#include <exec/types.h>
#include <exec/memory.h>
#include <exec/tasks.h>

#include <proto/exec.h>
#include <proto/dos.h>

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

#ifdef __SASC
static const char ver_text[] = "$VER: RamLibPatch 1.4 " __AMIGADATE__;
#else
static const char ver_text[] = "$VER: RamLibPatch 1.4 (1.8.98)";
#endif

#define STACKSIZE 8192

 /* NOTE: This is NOT a good example for stack swapping,
          since the OLD stack's buffer _NEVER_ will
          be delocated. However, there is no other
          way to achieve a larger stack for RamLib,
          and since RamLib never will end, this perhaps
          isn't a problem...

    DON'T TRY THIS PATCHING SCHEME WITH OTHER TASKS/PROCESSES !

 */

int RamLibPatch(void)
{
 struct Task *we;
 UBYTE *msg;
 struct ExecBase *SysBase = *(void **)4;
 struct DosLibrary *DOSBase;

 DOSBase = (struct DosLibrary *)OpenLibrary("dos.library", 33);

 Forbid();

 we = FindTask("ramlib");
 if(we)
  {
   if( (ULONG) we->tc_SPUpper - (ULONG) we->tc_SPLower < STACKSIZE)
    {
     struct Process *we2;
     UBYTE *lower, *upper, *pointer;
     ULONG inuse;

     lower   = (UBYTE *) AllocMem(STACKSIZE, MEMF_PUBLIC);
     upper   = (UBYTE *) (STACKSIZE + (UBYTE *) lower);

     inuse = (ULONG) we->tc_SPUpper - (ULONG) we->tc_SPReg;

     pointer = ((UBYTE *) upper) - inuse;

     CopyMem(we->tc_SPReg, pointer, inuse);

     we->tc_SPReg   = (APTR) pointer;
     we->tc_SPLower = (APTR) lower;
     we->tc_SPUpper = (APTR) upper;

     we2               = (struct Process *) we;
     we2->pr_StackSize = STACKSIZE;
     we2->pr_StackBase = (BPTR) (((ULONG)upper)>>2);

         msg = "Patch done!\n";
   }else msg = "Already patched.\n";
  }else  msg = "Wrong AmigaOS version.\n";

 Permit();

 if(IsInteractive(Output()))
  {
   Write(Output(), msg, strlen(msg));
  }

 CloseLibrary((struct Library *)DOSBase);

 return(0);
}
