/**
 * Scout - The Amiga System Monitor
 *
 *------------------------------------------------------------------
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 * You must not use this source code to gain profit of any kind!
 *
 *------------------------------------------------------------------
 *
 * @author Andreas Gelhausen
 * @author Richard Körber <rkoerber@gmx.de>
 */

#include "system_headers.h"

/********************************************************************/
/*                        ARexx-Funktionen                          */
/********************************************************************/
static __asm __saveds long printlist_rxfunc (register __a1 ULONG *arg) {

   if (arg[2])
      PrintHandleMode = MODE_OLDFILE;
   else
      PrintHandleMode = MODE_NEWFILE;

   if (stricmp ("L", (char *) arg[0]) == 0)
      PrintLibraries ((char *) arg[1]);
   else if (stricmp ("D", (char *) arg[0]) == 0)
      PrintDevices ((char *) arg[1]);
   else if (stricmp ("U", (char *) arg[0]) == 0)
      PrintResources ((char *) arg[1]);
   else if (stricmp ("T", (char *) arg[0]) == 0)
      PrintTasks ((char *) arg[1]);
   else if (stricmp ("P", (char *) arg[0]) == 0)
      PrintPorts ((char *) arg[1]);
   else if (stricmp ("C", (char *) arg[0]) == 0)
      PrintCommands ((char *) arg[1]);
   else if (stricmp ("X", (char *) arg[0]) == 0)
      PrintExpansions ((char *) arg[1]);
   else if (stricmp ("M", (char *) arg[0]) == 0)
      PrintMemory ((char *) arg[1]);
   else if (stricmp ("R", (char *) arg[0]) == 0)
      PrintResidents ((char *) arg[1]);
   else if (stricmp ("G", (char *) arg[0]) == 0)
      PrintAssigns ((char *) arg[1]);
   else if (stricmp ("O", (char *) arg[0]) == 0)
      PrintLocks ((char *) arg[1]);
   else if (stricmp ("N", (char *) arg[0]) == 0)
      PrintMounts ((char *) arg[1]);
   else if (stricmp ("H", (char *) arg[0]) == 0)
      PrintInputHandlers ((char *) arg[1]);
   else if (stricmp ("I", (char *) arg[0]) == 0)
      PrintInterrupts ((char *) arg[1]);
   else if (stricmp ("V", (char *) arg[0]) == 0)
      PrintVectors ((char *) arg[1]);
   else if (stricmp ("F", (char *) arg[0]) == 0)
      PrintFonts ((char *) arg[1]);
   else if (stricmp ("S", (char *) arg[0]) == 0)
      PrintSemaphores ((char *) arg[1]);
   else if (stricmp ("W", (char *) arg[0]) == 0)
      PrintWindows ((char *) arg[1]);
   else if (stricmp ("J", (char *) arg[0]) == 0)
      PrintLowMemory ((char *) arg[1]);
   else if (stricmp ("K", (char *) arg[0]) == 0)
      PrintCx ((char *) arg[1]);
   else if (stricmp ("Z", (char *) arg[0]) == 0)
      PrintSMode ((char *) arg[1]);
   else if (stricmp ("Y", (char *) arg[0]) == 0)
      PrintSystem ((char *) arg[1]);
   else if (stricmp ("A", (char *) arg[0]) == 0)
      PrintAllocations ((char *) arg[1]);
   else if (stricmp ("B", (char *) arg[0]) == 0)
      PrintClass ((char *) arg[1]);
   return (RETURN_OK);
}

MakeHook(printlist_rxhook, printlist_rxfunc);

static __asm __saveds long findtask_rxfunc (register __a1 ULONG *arg)
{
   struct   Task     *task;
   long result = RETURN_ERROR;

   Forbid();
   if (task = MyFindTask ((char *) arg[0])) {
      if (SendResultString ("0x%08lx", task)) result = RETURN_OK;
   }
   Permit();
   return result;
}

MakeHook(findtask_rxhook, findtask_rxfunc);

static __asm __saveds long removetask_rxfunc (register __a1 ULONG *arg) {

   if (MyRemoveTask ((char *) arg[0], (BOOL) arg[1]))
      return (RETURN_OK);
   else
      return (RETURN_ERROR);
}

MakeHook(removetask_rxhook, removetask_rxfunc);

static __asm __saveds long freezetask_rxfunc (register __a1 ULONG *arg) {

   if (MyFreezeTask ((char *) arg[0]))
      return (RETURN_OK);
   else
      return (RETURN_ERROR);
}

MakeHook(freezetask_rxhook, freezetask_rxfunc);

static __asm __saveds long activatetask_rxfunc (register __a1 ULONG *arg) {

   if (MyActivateTask ((char *) arg[0]))
      return (RETURN_OK);
   else
      return (RETURN_ERROR);
}

MakeHook(activatetask_rxhook, activatetask_rxfunc);

static __asm __saveds long signaltask_rxfunc (register __a1 ULONG *arg) {

   if (MySignalTask ((char *) arg[0], (char *) arg[1]))
      return (RETURN_OK);
   else
      return (RETURN_ERROR);
}

MakeHook(signaltask_rxhook, signaltask_rxfunc);

static __asm __saveds long breaktask_rxfunc (register __a1 ULONG *arg) {

   if (MySignalTask ((char *) arg[0], "0x1000"))
      return (RETURN_OK);
   else
      return (RETURN_ERROR);
}

MakeHook(breaktask_rxhook, breaktask_rxfunc);

static __asm __saveds long settaskpri_rxfunc (register __a1 ULONG *arg)
{
   struct   Task     *task;
   long     pri, result = RETURN_ERROR;

   Forbid();
   if ((task = MyFindTask ((char *) arg[0])) && (IsDec ((char *) arg[1], &pri))) {
      SetTaskPri (task, (int) pri);
      result = RETURN_OK;
   }
   Permit();

   return result;
}

MakeHook(settaskpri_rxhook, settaskpri_rxfunc);

static __asm __saveds long removeport_rxfunc (register __a1 ULONG *arg) {
   struct   MsgPort  *port;

   if (port = (struct MsgPort *) MyFindName ("PORT", (char *) arg[0])) {
      RemPort (port);
      return (RETURN_OK);
   }
   return (RETURN_ERROR);
}

MakeHook(removeport_rxhook, removeport_rxfunc);

static __asm __saveds long getlocknumber_rxfunc (register __a1 ULONG *arg)
{
   if (SendResultString("%ld", CountLocks((UBYTE *)*arg))) return RETURN_OK;

   return RETURN_ERROR;
}

MakeHook(getlocknumber_rxhook, getlocknumber_rxfunc);

static __asm __saveds long removelocks_rxfunc (register __a1 ULONG *arg)
{
   RemoveLock((UBYTE *)*arg);

   return RETURN_OK;
}

MakeHook(removelocks_rxhook, removelocks_rxfunc);

static __asm __saveds long removelock_rxfunc (register __a1 ULONG *arg) {
   long  nobptr;

   if (IsHex ((char *) arg[0], &nobptr)) {
      UnLock ((BPTR) nobptr>>2);
      return (RETURN_OK);
   }
   return (RETURN_ERROR);
}

MakeHook(removelock_rxhook, removelock_rxfunc);

static __asm __saveds long getpriority_rxfunc (register __a1 ULONG *arg) {
   long  address;

   if (IsHex ((char *) arg[0], &address)) {
      if (SendResultString ("%d", ((struct Node *) address)->ln_Pri))
         return (RETURN_OK);
   }
   return (RETURN_ERROR);
}

MakeHook(getpriority_rxhook, getpriority_rxfunc);

static __asm __saveds long setpriority_rxfunc (register __a1 ULONG *arg) {
   struct   Node  *node;
   struct   List  *list;
   int      value;

   if ((list = MyGetList ((char *) arg[0])) \
     && (node = MyFindName ((char *) arg[0], (char *) arg[1]))) {

      value = (int) *(ULONG *) arg[2];
      if ((value < 128) && (value > -129)) {

         Remove (node);
         node->ln_Pri = value;
         Enqueue (list, node);

         return (RETURN_OK);
      }
   }
   return (RETURN_ERROR);
}

MakeHook(setpriority_rxhook, setpriority_rxfunc);

static __asm __saveds long findnode_rxfunc (register __a1 ULONG *arg) {
   struct   Node  *node;

   if (node = MyFindName ((char *) arg[0], (char *) arg[1])) {
      if (SendResultString ("0x%08lx", node))
         return (RETURN_OK);
   }
   return (RETURN_ERROR);
}

MakeHook(findnode_rxhook, findnode_rxfunc);

static __asm __saveds long closelib_rxfunc (register __a1 ULONG *arg) {
   struct   Node  *node;

   if (node = MyFindName ("LIBRARY", (char *) arg[0])) {
      CloseLibrary ((struct Library *) node);
      return (RETURN_OK);
   }
   return (RETURN_ERROR);
}

MakeHook(closelib_rxhook, closelib_rxfunc);

static __asm __saveds long removelib_rxfunc (register __a1 ULONG *arg) {
   struct   Node  *node;

   if (node = MyFindName ("LIBRARY", (char *) arg[0])) {
      RemLibrary ((struct Library *) node);
      return (RETURN_OK);
   }
   return (RETURN_ERROR);
}

MakeHook(removelib_rxhook, removelib_rxfunc);

static __asm __saveds long removedev_rxfunc (register __a1 ULONG *arg) {
   struct   Node  *node;

   if (node = MyFindName ("DEVICE", (char *) arg[0])) {
      RemDevice ((struct Device *) node);
      return (RETURN_OK);
   }
   return (RETURN_ERROR);
}

MakeHook(removedev_rxhook, removedev_rxfunc);

static __asm __saveds long removeres_rxfunc (register __a1 ULONG *arg) {
   struct   Node  *node;

   if (node = MyFindName ("RESOURCE", (char *) arg[0])) {
      RemResource ((struct Library *) node);
      return (RETURN_OK);
   }
   return (RETURN_ERROR);
}

MakeHook(removeres_rxhook, removeres_rxfunc);

static __asm __saveds long obtainsem_rxfunc (register __a1 ULONG *arg) {
   struct   Node  *node;

   if (node = MyFindName ("SEMAPHORE", (char *) arg[0])) {
      ObtainSemaphore ((struct SignalSemaphore *) node);
      return (RETURN_OK);
   }
   return (RETURN_ERROR);
}

MakeHook(obtainsem_rxhook, obtainsem_rxfunc);

static __asm __saveds long releasesem_rxfunc (register __a1 ULONG *arg) {
   struct   Node  *node;

   if ((node = MyFindName ("SEMAPHORE", (char *) arg[0])) \
      && (((struct SignalSemaphore *) node)->ss_NestCount)) {
      ReleaseSemaphore ((struct SignalSemaphore *) node);
      return (RETURN_OK);
   }
   return (RETURN_ERROR);
}

MakeHook(releasesem_rxhook, releasesem_rxfunc);

static __asm __saveds long removesem_rxfunc (register __a1 ULONG *arg) {
   struct   Node  *node;

   if (node = MyFindName ("SEMAPHORE", (char *) arg[0])) {
      RemSemaphore ((struct SignalSemaphore *) node);
      return (RETURN_OK);
   }
   return (RETURN_ERROR);
}

MakeHook(removesem_rxhook, removesem_rxfunc);

static __asm __saveds long removeinput_rxfunc (register __a1 ULONG *arg) {
   struct   Node  *node;

   if (node = MyFindName ("INPUTHANDLER", (char *) arg[0])) {
      InputIORequest->io_Command = IND_REMHANDLER;
      InputIORequest->io_Data = (void *) node;
      SendIO ((struct IORequest *) InputIORequest);
      return (RETURN_OK);
   }
   return (RETURN_ERROR);
}

MakeHook(removeinput_rxhook, removeinput_rxfunc);

static __asm __saveds long removelowmemory_rxfunc (register __a1 ULONG *arg) {
   struct Interrupt *intr;

   if (intr = (struct Interrupt *)MyFindName ("LOWMEMORY", (char *) arg[0])) {
      if (SysBase->LibNode.lib_Version >= 39)
         RemMemHandler(intr);
      return (RETURN_OK);
   }
   return (RETURN_ERROR);
}

MakeHook(removelowmemory_rxhook, removelowmemory_rxfunc);

/*
static __asm __saveds long causelowmem_rxfunc (register __a1 ULONG *arg) {
   struct Interrupt *intr;
   struct MemHandlerData mhd = {1000,MEMF_ANY,0};

   if (intr = (struct Interrupt *)MyFindName ("LOWMEMORY", (char *) arg[0])) {
      MyCause(intr,&mhd);
      return (RETURN_OK);
   }
   return (RETURN_ERROR);
}

MakeHook(causelowmem_rxhook, causelowmem_rxfunc);
*/

static __asm __saveds long findresident_rxfunc (register __a1 ULONG *arg) {
   struct   Resident *resi;

   if (resi = FindResident ((char *) arg[0])) {
      if (SendResultString ("0x%08lx", resi))
         return (RETURN_OK);
   }
   return (RETURN_ERROR);
}

MakeHook(findresident_rxhook, findresident_rxfunc);

static __asm __saveds long findinterrupt_rxfunc (register __a1 ULONG *arg)
{
    struct Interrupt *intr;

    if (intr = FindInterrupt((UBYTE *)arg[0])) {
        if (SendResultString("0x%08lx", intr)) {
            return RETURN_OK;
        }
    }

    return RETURN_ERROR;
}

MakeHook(findinterrupt_rxhook, findinterrupt_rxfunc);

static __asm __saveds long removeinterrupt_rxfunc (register __a1 ULONG *arg)
{
    struct Interrupt *intr;
   
    if (intr = RemoveInterrupt((UBYTE *)arg[0])) {
        return RETURN_OK;
    }

    return RETURN_ERROR;
}

MakeHook(removeinterrupt_rxhook, removeinterrupt_rxfunc);

static __asm __saveds long removeclass_rxfunc (register __a1 ULONG *arg) {
   struct IClass *node;
   BOOL ret;

   if (node = (struct IClass *)MyFindName ("CLASSES", (char *) arg[0])) {
      if((!node->cl_ObjectCount) && (!node->cl_SubclassCount))
      {
        ret = FreeClass((struct IClass *)node);
        return (ret ? RETURN_OK : RETURN_ERROR);
      }
   }
   return (RETURN_ERROR);
}

MakeHook(removeclass_rxhook, removeclass_rxfunc);


static __asm __saveds long flushdevs_rxfunc (register __a1 ULONG *arg) {
   FlushDevices();
   return (RETURN_OK);
}

MakeHook(flushdevs_rxhook, flushdevs_rxfunc);

static __asm __saveds long flushfonts_rxfunc (register __a1 ULONG *arg) {
   FlushFonts();
   return (RETURN_OK);
}

MakeHook(flushfonts_rxhook, flushfonts_rxfunc);

static __asm __saveds long flushlibs_rxfunc (register __a1 ULONG *arg) {
   FlushLibraries();
   return (RETURN_OK);
}

MakeHook(flushlibs_rxhook, flushlibs_rxfunc);

static __asm __saveds long flushall_rxfunc (register __a1 ULONG *arg) {
   FlushDevices();
   FlushFonts();
   FlushLibraries();
   return (RETURN_OK);
}

MakeHook(flushall_rxhook, flushall_rxfunc);

static __asm __saveds long clearreset_rxfunc (register __a1 ULONG *arg) {
   ClearResetVectors();
   return (RETURN_OK);
}

MakeHook(clearreset_rxhook, clearreset_rxfunc);

static __asm __saveds long poptofront_rxfunc (register __a1 ULONG *arg) {
   struct   Window   *window;
   struct   Screen   *screen;
   
   if (screen = MyFindScreen ((char *) arg[0])) {
      ScreenToFront (screen);
      return (RETURN_OK);
   } else if (window = MyFindWindow ((char *) arg[0])) {
      WindowToFront (window);
      return (RETURN_OK);
   }
   return (RETURN_ERROR);
}

MakeHook(poptofront_rxhook, poptofront_rxfunc);

static __asm __saveds long closewindow_rxfunc (register __a1 ULONG *arg) {
   struct   Window   *window;

   if (window = MyFindWindow ((char *) arg[0])) {
      CloseWindow (window);
      return (RETURN_OK);
   }
   return (RETURN_ERROR);
}

MakeHook(closewindow_rxhook, closewindow_rxfunc);

static __asm __saveds long closescreen_rxfunc (register __a1 ULONG *arg) {
   struct   Screen   *screen;

   if (screen = MyFindScreen ((char *) arg[0])) {
      CloseScreenAll (screen);
      return (RETURN_OK);
   }
   return (RETURN_ERROR);
}

MakeHook(closescreen_rxhook, closescreen_rxfunc);

static __asm __saveds long closefont_rxfunc (register __a1 ULONG *arg) {
   struct TextFont *font;

   if (IsHex ((char *) arg[0], (long *) &font)) {
      CloseFont (font);
      return (RETURN_OK);
   }
   return (RETURN_ERROR);
}

MakeHook(closefont_rxhook, closefont_rxfunc);

static __asm __saveds long removefont_rxfunc (register __a1 ULONG *arg) {
   struct TextFont *font;

   if (IsHex ((char *) arg[0], (long *) &font)) {
      RemFont (font);
      Remove ((struct Node *) font);
      return (RETURN_OK);
   }
   return (RETURN_ERROR);
}

MakeHook(removefont_rxhook, removefont_rxfunc);

static __asm __saveds long removecommand_rxfunc (register __a1 ULONG *arg) {
   struct   Segment *seg;

   if ((IsHex ((char *) arg[0], (long *) &seg)) && (RemSegment (seg))) {
      return (RETURN_OK);
   }
   return (RETURN_ERROR);
}

MakeHook(removecommand_rxhook, removecommand_rxfunc);

static __asm __saveds long removeassign_rxfunc (register __a1 ULONG *arg) {

   if (AssignLock((char *) arg[0], (BPTR)NULL)) {
      return (RETURN_OK);
   }
   return (RETURN_ERROR);
}

MakeHook(removeassign_rxhook, removeassign_rxfunc);

static __asm __saveds long removeassignlist_rxfunc (register __a1 ULONG *arg) {
   BPTR  address;

   if (IsHex ((char *) arg[1], (long *) &address)) {
      if (RemAssignList ((char *) arg[0], address)) {
         return (RETURN_OK);
      }
   }
   return (RETURN_ERROR);
}

MakeHook(removeassignlist_rxhook, removeassignlist_rxfunc);

static struct WindowCmd {
    UBYTE *wc_Name;
    ULONG wc_Method;
} wincmds[] = {
    { "Allocations",   MUIM_MainWin_ShowAllocations   },
    { "Assigns",       MUIM_MainWin_ShowAssigns       },
    { "Classes",       MUIM_MainWin_ShowClasses       },
    { "Commodities",   MUIM_MainWin_ShowCommodities   },
    { "Devices",       MUIM_MainWin_ShowDevices       },
    { "Expansions",    MUIM_MainWin_ShowExpansions    },
    { "Fonts",         MUIM_MainWin_ShowFonts         },
    { "InputHandlers", MUIM_MainWin_ShowInputHandlers },
    { "Interrupts",    MUIM_MainWin_ShowInterrupts    },
    { "Libraries",     MUIM_MainWin_ShowLibraries     },
    { "Locks",         MUIM_MainWin_ShowLocks         },
    { "LowMemory",     MUIM_MainWin_ShowLowMemory     },
    { "Memory",        MUIM_MainWin_ShowMemory        },
    { "Mount",         MUIM_MainWin_ShowMounts        },
    { "Ports",         MUIM_MainWin_ShowPorts         },
    { "Residents",     MUIM_MainWin_ShowResidents     },
    { "Commands",      MUIM_MainWin_ShowCommands      },
    { "Resources",     MUIM_MainWin_ShowResources     },
    { "ScreenMode",    MUIM_MainWin_ShowScreenModes   },
    { "Semaphores",    MUIM_MainWin_ShowSemaphores    },
    { "System",        MUIM_MainWin_ShowSystem        },
    { "Tasks",         MUIM_MainWin_ShowTasks         },
    { "Timer",         MUIM_MainWin_ShowTimers        },
    { "Vectors",       MUIM_MainWin_ShowVectors       },
    { "Windows",       MUIM_MainWin_ShowWindows       },
    { "Patches",       MUIM_MainWin_ShowPatches       },
    { "Catalogs",      MUIM_MainWin_ShowCatalogs      },
    { NULL,            0                              }
};

static __asm __saveds long openwindow_rxfunc( register __a1 ULONG *arg )
{

    if (AP_Scout) {
        ULONG i = 0;

        while (wincmds[i].wc_Name) {
            if (stricmp((UBYTE *)arg[0], wincmds[i].wc_Name) == 0) {
                DoMethod(WI_Main, wincmds[i].wc_Method);
                return RETURN_OK;
            }
            i++;
        }
    }

    return RETURN_ERROR;
}

MakeHook(openwindow_rxhook, openwindow_rxfunc);



static __asm __saveds long cxappear_rxfunc (register __a1 ULONG *arg) {
   return(BrokerCommand((char *) arg[0], CXCMD_APPEAR ) ? RETURN_ERROR : RETURN_OK);
}
MakeHook(cxappear_rxhook, cxappear_rxfunc);

static __asm __saveds long cxdisappear_rxfunc (register __a1 ULONG *arg) {
   return(BrokerCommand((char *) arg[0], CXCMD_DISAPPEAR ) ? RETURN_ERROR : RETURN_OK);
}
MakeHook(cxdisappear_rxhook, cxdisappear_rxfunc);

static __asm __saveds long cxenable_rxfunc (register __a1 ULONG *arg) {
   return(BrokerCommand((char *) arg[0], CXCMD_ENABLE ) ? RETURN_ERROR : RETURN_OK);
}
MakeHook(cxenable_rxhook, cxenable_rxfunc);

static __asm __saveds long cxdisable_rxfunc (register __a1 ULONG *arg) {
   return(BrokerCommand((char *) arg[0], CXCMD_DISABLE ) ? RETURN_ERROR : RETURN_OK);
}
MakeHook(cxdisable_rxhook, cxdisable_rxfunc);

static __asm __saveds long cxkill_rxfunc (register __a1 ULONG *arg) {
   return(BrokerCommand((char *) arg[0], CXCMD_KILL ) ? RETURN_ERROR : RETURN_OK);
}
MakeHook(cxkill_rxhook, cxkill_rxfunc);

static __asm __saveds long cxlistchg_rxfunc (register __a1 ULONG *arg) {
   return(BrokerCommand((char *) arg[0], CXCMD_LIST_CHG ) ? RETURN_ERROR : RETURN_OK);
}
MakeHook(cxlistchg_rxhook, cxlistchg_rxfunc);

static __asm __saveds long cxunique_rxfunc (register __a1 ULONG *arg) {
   return(BrokerCommand((char *) arg[0], CXCMD_UNIQUE ) ? RETURN_ERROR : RETURN_OK);
}
MakeHook(cxunique_rxhook, cxunique_rxfunc);

static __asm __saveds long removecx_rxfunc (register __a1 ULONG *arg) {
   struct   Node  *node;

   if (node = MyFindName ("COMMODITIES", (char *) arg[0])) {
      RemoveCxObj((CxObj *)node);
      return (RETURN_OK);
   }
   return (RETURN_ERROR);
}
MakeHook(removecx_rxhook, removecx_rxfunc);

static __asm __saveds long setcxpri_rxfunc (register __a1 ULONG *arg) {
   struct   Node  *node;
   long     pri;

   if ((node = MyFindName ("COMMODITIES", (char *) arg[0])) && (IsDec ((char *) arg[1], &pri))) {
      if((pri>=-128) && (pri<=127)) {
        struct List *list = MyGetList("COMMODITIES");
        Forbid();
        Remove(node);
        node->ln_Pri = pri;
        Enqueue(list,node);
        Permit();
        return (RETURN_OK);
      }
   }
   return (RETURN_ERROR);
}
MakeHook(setcxpri_rxhook, setcxpri_rxfunc);


struct MUI_Command arexx_list[] = {
   {"PrintList"         , "LIST/A,FILENAME/A,APPEND/S", 3, &printlist_rxhook },
   {"FindTask"          , "NAME=ADDRESS/A"           , 1, &findtask_rxhook },
   {"FreezeTask"        , "NAME=ADDRESS/A"           , 1, &freezetask_rxhook },
   {"ActivateTask"      , "NAME=ADDRESS/A"           , 1, &activatetask_rxhook },
   {"RemoveTask"        , "NAME=ADDRESS/A,WITHPORTS/S", 2, &removetask_rxhook },
   {"BreakTask"         , "NAME=ADDRESS/A"           , 1, &breaktask_rxhook },
   {"SignalTask"        , "NAME=ADDRESS/A,HEXSIGNAL/A", 2, &signaltask_rxhook },
   {"SetTaskPri"        , "NAME=ADDRESS/A,PRIORITY/A", 2, &settaskpri_rxhook },
   {"RemovePort"        , "NAME=ADDRESS/A"           , 1, &removeport_rxhook },
   {"GetLockNumber"     , "LOCKPATTERN/F"            , 1, &getlocknumber_rxhook },
   {"RemoveLocks"       , "LOCKPATTERN/F"            , 1, &removelocks_rxhook },
   {"RemoveLock"        , "ADDRESS/A"                , 1, &removelock_rxhook },
   {"GetPriority"       , "ADDRESS/A"                , 1, &getpriority_rxhook },
   {"SetPriority"       , "TYPE/A,NAME=ADDRESS/A,PRIORITY/N", 3, &setpriority_rxhook },
   {"FindNode"          , "TYPE/A,NAME=ADDRESS/A"    , 2, &findnode_rxhook },
   {"CloseLibrary"      , "NAME=ADDRESS/A"           , 1, &closelib_rxhook },
   {"RemoveLibrary"     , "NAME=ADDRESS/A"           , 1, &removelib_rxhook },
   {"RemoveDevice"      , "NAME=ADDRESS/A"           , 1, &removedev_rxhook },
   {"RemoveResource"    , "NAME=ADDRESS/A"           , 1, &removeres_rxhook },
   {"ObtainSemaphore"   , "NAME=ADDRESS/A"           , 1, &obtainsem_rxhook },
   {"ReleaseSemaphore"  , "NAME=ADDRESS/A"           , 1, &releasesem_rxhook },
   {"RemoveSemaphore"   , "NAME=ADDRESS/A"           , 1, &removesem_rxhook },
   {"RemoveInputhandler", "NAME=ADDRESS/A"           , 1, &removeinput_rxhook },
   {"RemoveLowMemory"   , "NAME=ADDRESS/A"           , 1, &removelowmemory_rxhook },
   {"FindResident"      , "NAME=ADDRESS/A"           , 1, &findresident_rxhook },
   {"FindInterrupt"     , "NAME/A"                   , 1, &findinterrupt_rxhook },
   {"RemoveInterrupt"   , "NAME/A"                   , 1, &removeinterrupt_rxhook },
   {"FlushDevs"         , NULL                       , 0, &flushdevs_rxhook },
   {"FlushFonts"        , NULL                       , 0, &flushfonts_rxhook },
   {"FlushLibs"         , NULL                       , 0, &flushlibs_rxhook },
   {"FlushAll"          , NULL                       , 0, &flushall_rxhook },
   {"ClearResetVectors" , NULL                       , 0, &clearreset_rxhook },
   {"PopToFront"        , "TITLE=ADDRESS/A"          , 1, &poptofront_rxhook },
   {"CloseWindow"       , "TITLE=ADDRESS/A"          , 1, &closewindow_rxhook },
   {"CloseScreen"       , "TITLE=ADDRESS/A"          , 1, &closescreen_rxhook },
   {"CloseFont"         , "ADDRESS/A"                , 1, &closefont_rxhook },
   {"RemoveFont"        , "ADDRESS/A"                , 1, &removefont_rxhook },
   {"RemoveCommand"     , "ADDRESS/A"                , 1, &removecommand_rxhook },
   {"RemoveAssign"      , "NAME/A"                   , 1, &removeassign_rxhook },
   {"RemoveAssignList"  , "NAME/A,ADDRESS/A"         , 2, &removeassignlist_rxhook },
   {"OpenWindow"        , "WINDOWID/F"               , 1, &openwindow_rxhook },
   {"CxAppear"          , "NAME/A"                   , 1, &cxappear_rxhook },
   {"CxDisappear"       , "NAME/A"                   , 1, &cxdisappear_rxhook },
   {"CxEnable"          , "NAME/A"                   , 1, &cxenable_rxhook },
   {"CxDisable"         , "NAME/A"                   , 1, &cxdisable_rxhook },
   {"CxKill"            , "NAME/A"                   , 1, &cxkill_rxhook },
   {"CxListChg"         , "NAME/A"                   , 1, &cxlistchg_rxhook },
   {"CxUnique"          , "NAME/A"                   , 1, &cxunique_rxhook },
   {"RemoveCx"          , "NAME=ADDRESS/A"           , 1, &removecx_rxhook },
   {"SetCxPri"          , "NAME=ADDRESS/A,PRIORITY/A", 2, &setcxpri_rxhook },
//*   {"CauseLowMemory"    , "NAME=ADDRESS/A"           , 1, &causelowmem_rxhook },
   {"RemoveClass"       , "NAME/A"                   , 1, &removeclass_rxhook },
   { NULL, NULL, 0, NULL }
};

char *FindMyARexxPort (char *name)
{
   char *result = NULL;
   UBYTE *tmp;
   struct   MsgPort  *port;
   struct   Task     *task;
   int      i;

   if (tmp = tbAllocVecPooled(globalPool, PATH_LENGTH)) {
       task = FindTask (NULL);
       for (i = 0; i < 10; i++) {
          _snprintf(tmp, PATH_LENGTH, "%s.%ld", name, i);

          Forbid();
          port = FindPort (tmp);
          Permit();

          if (port != NULL && port->mp_SigTask == task) {
             result = port->mp_Node.ln_Name;
             break;
          }
       }
       tbFreeVecPooled(globalPool, tmp);
   }

   return result;
}

ULONG SafePutToPort(struct Message *message, STRPTR portname) {
   struct MsgPort *port;

   Forbid();
   if (port = FindPort(portname))
      PutMsg (port,message);
   Permit();
   return ((ULONG) port); /* If zero, the port has gone away */
}

short SendStartupMsg (char *PortName,char *RString,BOOL IsFileName) {
   register struct   RexxMsg  *rmsg;
   register short    flag = FALSE;

   char     *buffer = NULL;
   ULONG    buflen;

   if ((RString) && (rmsg = CreateRexxMsg(ScoutPort,NULL,PortName))) {

      rmsg->rm_Action = (RXCOMM|RXFF_STRING);

      if (IsFileName) {
         buflen = strlen (RString) + 4;

         if (buffer = tbAllocVecPooled(globalPool, buflen)) {
            /*
             * Fill in the hostname and the command
             */
            _snprintf(buffer, buflen, "'%s'", RString);

            rmsg->rm_Args[0] = CreateArgstring (buffer, buflen);
         }
      } else {          
         rmsg->rm_Args[0] = CreateArgstring (RString,(LONG) strlen (RString));
      }

      if (rmsg->rm_Args[0]) {
         if (SafePutToPort ((struct Message *) rmsg, RXSDIR)) {
            flag=TRUE;
         } else {
            DeleteArgstring (rmsg->rm_Args[0]);
            DeleteRexxMsg (rmsg);
         }
      } else {
            DeleteRexxMsg (rmsg);
      }

      if (buffer) tbFreeVecPooled(globalPool, buffer);
   }
   return (flag);
}


/********************************************************************/
/*         Neue Hilfsroutinen für die ARexx-Funktionen              */
/********************************************************************/

struct Task *MyFindTask (char *stask) {
   struct   Task  *lauf, *task, *result = NULL;

   if (IsHex (stask, (long *) &task)) {
      Forbid();

      lauf = FIRSTTASKREADY;
      while ((! result) && (lauf->tc_Node.ln_Succ != 0)) {
         if (task == lauf)
            result = lauf;
         lauf = (struct Task *) lauf->tc_Node.ln_Succ;
      }

      lauf = FIRSTTASKWAIT;
      while ((! result) && (lauf->tc_Node.ln_Succ != 0)) {
         if (task == lauf)
            result = lauf;
         lauf = (struct Task *) lauf->tc_Node.ln_Succ;
      }
      Permit();

      if ((! result) && (task == FindTask (NULL)))
         result = task;

   } else {
      Forbid();

      lauf = FIRSTTASKREADY;
      while ((! result) && (lauf->tc_Node.ln_Succ != 0)) {
         if (stricmp (stask, GetTaskName (lauf)) == 0) 
            result = lauf;
   
         lauf = (struct Task *) lauf->tc_Node.ln_Succ;
      }

      lauf = FIRSTTASKWAIT;
      while ((! result) && (lauf->tc_Node.ln_Succ != 0)) {
         if (stricmp (stask, GetTaskName (lauf)) == 0) 
            result = lauf;
   
         lauf = (struct Task *) lauf->tc_Node.ln_Succ;
      }
      Permit();

      if ((! result) && (stricmp (stask, GetTaskName (lauf = FindTask (NULL))) == 0)) 
         result = lauf;
   }
   return (result);
}

BOOL MyRemoveTask (char *stask, BOOL withports) {
   struct   Task     *task;
   struct   MsgPort  *port, *nextport;
   struct   Window   *window, *nextwindow;
   struct   Screen   *screen, *nextscreen;
   struct   SignalSemaphore   *sem, *nextsem;
   BOOL     allwins = FALSE;

   Forbid();
   if (task = MyFindTask (stask)) {

   // Wegen groben Unfugs gestrichen!

      if (MyFreezeTask (stask) && withports) {
         port = FIRSTPORT;
         while (port) {
            nextport = (struct MsgPort *) port->mp_Node.ln_Succ;
            if (port->mp_SigTask == task) {
               RemPort (port);
            }
            port = nextport;
         }


         sem = FIRSTSEMAPHORE;
         while (nextsem = (struct SignalSemaphore *) sem->ss_Link.ln_Succ) {

            if (sem->ss_Owner == task) {
               int tmpint = sem->ss_NestCount;
               while (tmpint-- > 0) {
                  ReleaseSemaphore (sem);
               }
            }
            sem = nextsem;
         }

         screen = FIRSTSCREEN;
         while (screen) {
            nextscreen = screen->NextScreen;

            if (window = screen->FirstWindow) {
               allwins = TRUE;

               while (window) {
                  nextwindow = window->NextWindow;

                  if (window->UserPort->mp_SigTask == task) {
                     CloseWindow (window);
                  } else {
                     allwins = FALSE;
                  }
                  window = nextwindow;
               }
            }

            if (allwins && !screen->FirstWindow)
               CloseScreen (screen);

            screen = nextscreen;
         }
      }

      RemTask (task);
      Permit();
      return (TRUE);
   }
   Permit();
   return (FALSE);
}

BOOL MyFreezeTask (char *stask)
{
   BOOL result = FALSE;
   struct   Task     *task;

   Forbid();
   if (task = MyFindTask (stask)) {
      Remove ((struct Node *) task);
      task->tc_State = (BYTE) TS_FROZEN;
      Enqueue ((struct List *) &SysBase->TaskWait, (struct Node *) task);
      result = TRUE;
   }
   Permit();

   return result;
}

BOOL MyActivateTask (char *stask)
{
   BOOL result = FALSE;
   struct   Task     *task;

   Forbid();
   if (task = MyFindTask (stask)) {
      Remove ((struct Node *) task);
      task->tc_State = (BYTE) TS_READY;
      Enqueue ((struct List *) &SysBase->TaskReady, (struct Node *) task);
      result = TRUE;
   }
   Permit();

   return result;
}

BOOL MySignalTask (char *stask, char *ssignal)
{
   BOOL result = FALSE;
   struct   Task     *task;
   long     signal;

   Forbid();
   if ((task = MyFindTask (stask)) && (IsHex (ssignal, &signal))) {
      Signal (task, signal);
      result = TRUE;
   }
   Permit();

   return result;
}

static char *nodetype[] = {
   "LIBRARY", "DEVICE", "RESOURCE", "MEMORY", "SEMAPHORE", 
   "PORT", "INPUTHANDLER", "LOWMEMORY", "COMMODITIES", "CLASSES", NULL
};

struct List *MyGetList (char *type) {
   int      i = 0;
   char     *tmp;
   struct   List  *list = NULL;

   while (nodetype[i]) {
      if (! stricmp (nodetype[i], type)) {
         switch (i) {
            case 0:
               list = &SysBase->LibList;
               break;
            case 1:
               list = &SysBase->DeviceList;
               break;
            case 2:
               list = &SysBase->ResourceList;
               break;
            case 3:
               list = &SysBase->MemList;
               break;
            case 4:
               list = &SysBase->SemaphoreList;
               break;
            case 5:
               list = &SysBase->PortList;
               break;
            case 6:
               if (list = (struct List *) FindName (&SysBase->DeviceList, "input.device")) {
                  tmp = (char *) list;
                  tmp += 148;    /* Mir unbekannter Offsetname! */
                  list = (struct List *) ((struct Node *) tmp)->ln_Succ;
               }
               break;
            case 7:
               if (SysBase->LibNode.lib_Version >= 39)
                 list = (struct List *)&SysBase->ex_MemHandlers;
               else
                 list = NULL;
               break;
            case 8:
               {
                  struct MsgPort *cxport;
                  struct NewBroker cxnewbroker =
                  {
                    NB_VERSION,
                    "« Scout Dummy »",
                    "« Scout Dummy »",
                    "Dummy Broker",
                    0,
                    0,
                    0,
                    NULL,
                    0
                  };
                  struct Node *cxbroker;
                  struct Node *broker;

                  if(cxport = CreateMsgPort()) {
                     cxnewbroker.nb_Port = cxport;
                     if(cxbroker = (struct Node *)CxBroker(&cxnewbroker,NULL)) {
                          Forbid();
                          for(broker=cxbroker; broker->ln_Pred; broker=broker->ln_Pred);   /* Search the list head */
                          list = (struct List *)broker;
                          Permit();
                        DeleteCxObjAll((CxObj *)cxbroker);
                     }
                     DeleteMsgPort(cxport);
                  }
               }
               break;
            case 9:
               {
                  struct IClass *myclass = MakeClass("« Scout Dummy Class »","rootclass",NULL,0,0);
                  struct Node *clist;
                  if(myclass) {
                     AddClass(myclass);
                     Forbid();
                        for(clist=(struct Node *)&myclass->cl_Dispatcher.h_MinNode; clist->ln_Pred; clist=clist->ln_Pred);   /* Search the list head */
                        list = (struct List *)clist;
                     Permit();
                     FreeClass(myclass);
                  }
               }
               break;
          }
      }
      i++;
   }
   return (list);
}

struct Node *MyFindName (char *type, char *sname) {
   struct   List  *list;
   struct   Node  *lauf, *node = NULL, *result = NULL;

   if (list = MyGetList (type)) {
      if (IsHex (sname, (long *) &node)) {
         Forbid();

         lauf = list->lh_Head;
         while (lauf->ln_Succ != 0) {
            if (node == lauf) {
               result = lauf;
               break;
            }
            lauf = lauf->ln_Succ;
         }

         Permit();
      } else {
         result = FindName (list, sname);
      }
   }
   return (result);
}

struct Screen *MyFindScreen (char *sname) {
   struct   Screen   *screen = NULL, *lauf;

   lauf = FIRSTSCREEN;
   IsHex (sname, (long *) &screen);
   
   while (lauf) {
      if (screen) {
         if (lauf == screen)
            return (lauf);
      } else {
         if (stricmp (sname, nonetest (lauf->Title)) == 0)
            return (lauf);
      }
      lauf = lauf->NextScreen;
   }
   return (NULL);
}

struct Window *MyFindWindow (char *sname) {
   struct   Window   *window, *lauf;
   struct   Screen   *screen;

   screen = FIRSTSCREEN;
   IsHex (sname, (long *) &window);
   
   while (screen) {
      lauf = screen->FirstWindow;

      while (lauf) {
         if (window) {
            if (lauf == window)
               return (lauf);
         } else {
            if (stricmp (sname, nonetest (lauf->Title)) == 0)
               return (lauf);
         }
         lauf = lauf->NextWindow;
      }
      screen = screen->NextScreen;
   }
   return (NULL);
}
