/*
   ***************************************************************************
   *
   * Datei:
   *      RSysExecLists.c
   *
   * Inhalt:
   *
   *      --- Globale Routinen ---
   *
   *    void MakeIntrList ( void );
   *    void MakeLibList ( void );
   *    void MakePortList ( void );
   *    void MakeResList ( void );
   *    void MakeTaskList ( void );
   *    void RSysMemoryAreaList ( void );
   *    void SysSemaphoreList ( void );
   *    void SysSoftDeviceList ( void );
   *    void SysVectorList ( void );
   *
   *      --- Lokale  Routinen ---
   *
   *    static void CopyTaskNode ( int entrynum , NODE *node );
   *
   * Bemerkungen:
   *      Erzeugung von EXEC-Listen (Tasks, Ports, Libraries etc.).
   *
   * Erstellungsdatum:
   *      07-Jul-93     Rolf Böhme
   *
   * Änderungen:
   *      07-Jul-93     Rolf Böhme        Erstellung
   *
   ***************************************************************************
 */

#include "RSys.h"
#include "protos.h"

 /*
  * MakeLibList() erzeugt eine Liste aus allen im System
  * angemeldeten Libraries.
  */
void
MakeLibList (void)
{
  NODE *node;
  LIBRARY *lib;
  int i = 0;

  DPOS;

  countentries = CountNodes (&SysBase->LibList);

  if (NoEntries ())
    return;

  Entries = AllocScrollEntries (countentries);

  Forbid ();

  for (node = SysBase->LibList.lh_Head; node->ln_Succ && (i < countentries); node = node->ln_Succ)
    {
      lib = (LIBRARY *) node;

      Entries[i].se_obj_id.address = lib;
      savestrcpy (Entries[i].se_obj_id.fullname, node, MAXFULLNAME - 1, NT_LIBRARY);

      sprintf (Entries[i].se_Entry, EntryAttr[LIBRARIES].ea_dataformat,
	       Entries[i].se_obj_id.address,
	       Entries[i].se_obj_id.fullname,
	       lib->lib_Version,
	       lib->lib_Revision,
	       lib->lib_OpenCnt,
	       (lib->lib_OpenCnt ? '*' : ' '));

      i++;
    }

  countentries = i;

  Permit ();

  CreateEntryList (SORT, 9);

  return;
}

 /*
  * MakeResList() erzeugt eine Liste der Ressourcen, die
  * in der ExecBase eingetragen sind
  */
void
MakeResourceList (void)
{
  NODE *node;
  LIBRARY *lib;
  int i;

  DPOS;

  countentries = CountNodes (&SysBase->ResourceList);

  if (NoEntries ())
    return;

  Entries = AllocScrollEntries (countentries);

  Forbid ();

  i = 0;

  for (node = SysBase->ResourceList.lh_Head;
       node->ln_Succ && (i < countentries); node = node->ln_Succ)
    {
      lib = (LIBRARY *) node;

      Entries[i].se_obj_id.address = lib;
      savestrcpy (Entries[i].se_obj_id.fullname, node,
		  MAXFULLNAME - 1, NT_RESOURCE);

      sprintf (Entries[i].se_Entry, EntryAttr[RESOURCES].ea_dataformat,
	       Entries[i].se_obj_id.address,
	       Entries[i].se_obj_id.fullname,
	       lib->lib_Version,
	       lib->lib_Revision,
	       lib->lib_OpenCnt);

      i++;
    }

  countentries = i;

  Permit ();

  CreateEntryList (SORT, 9);

  return;
}

 /*
  * MakeIntrList() listet alle 16 Interrupts auf, die vom System
  * verwaltet werden können
  */
void
MakeIntrList (void)
{
  NODE *node;
  int i;

  DPOS;

  countentries = 16;		/* IntVects size */

  Entries = AllocScrollEntries (countentries);

  Disable ();

  for (i = 0; i < countentries; i++)
    {
      node = SysBase->IntVects[i].iv_Node;

      Entries[i].se_obj_id.address = node;
      if (node && (node->ln_Name))	/*GMD */
	{

	  savestrcpy (Entries[i].se_obj_id.fullname, node,
		      MAXFULLNAME - 1, node->ln_Type);	/*hack */

	  sprintf (Entries[i].se_Entry, EntryAttr[INTERRUPTS].ea_dataformat,
		   Entries[i].se_obj_id.address,
		   Entries[i].se_obj_id.fullname,
		   node->ln_Pri,
		   (long) ((INTERRUPT *) node)->is_Data,
		   (long) (((INTERRUPT *) node)->is_Code));
	}
      else
	{
	  sprintf (Entries[i].se_Entry, EntryAttr[INTERRUPTS].ea_dataformat,
		   0L, field[NO_NODE], 0, 0L, 0L);
	}
    }

  Enable ();

  CreateEntryList (NO_SORT, 9);

  return;
}

 /*
  * MakePortList() erzeugt eine Liste der im System angemeldeten
  * öffentlichen Ports
  */
void
MakePortList (void)
{
  NODE *node;
  TASK *task;
  MSGPORT *port;
  char sigtask[16];
  int i = 0;

  DPOS;

  countentries = CountNodes (&SysBase->PortList);

  if (NoEntries ())
    return;

  Entries = AllocScrollEntries (countentries);

  Forbid ();

  for (node = SysBase->PortList.lh_Head; node->ln_Succ && (i < countentries); node = node->ln_Succ)
    {
      Entries[i].se_obj_id.address = node;
      savestrcpy (Entries[i].se_obj_id.fullname, node,
		  MAXFULLNAME - 1, NT_MSGPORT);

      port = (MSGPORT *) node;
      task = (TASK *) port->mp_SigTask;
      if (task)
	savestrcpy (sigtask, &(task->tc_Node), 15, NT_TASK);
      else
	strcpy (sigtask, field[NO_TASK]);

      sprintf (Entries[i].se_Entry, EntryAttr[PORTS].ea_dataformat,
	       Entries[i].se_obj_id.address,
	       Entries[i].se_obj_id.fullname,
	       sigtask, node->ln_Pri);

      i++;
    }

  countentries = i;

  Permit ();

  CreateEntryList (SORT, 9);

  return;
}


 /*
  * CopyTaskNode() kopiert die Daten eines Tasks in eine interne
  * Listenstruktur
  */
static void
CopyTaskNode (int entrynum, NODE * node)
{
  COMMANDLINEINTERFACE *CLI;
  PROCESS *proc;
  char *status[] =
  {
    "Inv", "Add", "Run", "Rdy", "Wait", "Excp", "Rem"
  }, cli[5], buf[BUFSIZE], backtask[BUFSIZE], *backtaskstr = NULL;

  Entries[entrynum].se_obj_id.address = node;

  savestrcpy (Entries[entrynum].se_obj_id.fullname, node, MAXFULLNAME - 1, NT_TASK);

  if (!strcmp (Entries[entrynum].se_obj_id.fullname, "Background CLI") ||
      !strcmp (Entries[entrynum].se_obj_id.fullname, "Shell Process"))
    {
      proc = (PROCESS *) node;
      CLI = (COMMANDLINEINTERFACE *) BADDR (proc->pr_CLI);

      backtaskstr = B2CStr (buf, CLI->cli_CommandName);
      buf[15] = STRINGEND;

      if (strlen (backtaskstr) != 0)
	sprintf (backtask, "[%s]", buf);
      else
	strcpy (backtask, "[no command]");
    }

  if ((node->ln_Type == NT_PROCESS) && ((PROCESS *) node)->pr_CLI)
    sprintf (cli, "%3ld", ((PROCESS *) node)->pr_TaskNum);
  else
    strcpy (cli, field[NO_FIELD]);

  sprintf (Entries[entrynum].se_Entry, EntryAttr[TASKS].ea_dataformat,
	   Entries[entrynum].se_obj_id.address,
	   backtaskstr ? backtask : Entries[entrynum].se_obj_id.fullname,
	   (node->ln_Type == NT_PROCESS) ? (char *) "Proc" : (char *) "Task",
	   node->ln_Pri,
	   ((ULONG) ((TASK *) node)->tc_SPUpper -
	    (ULONG) ((TASK *) node)->tc_SPLower),
	   status[((TASK *) node)->tc_State],
	   cli);
  return;
}

 /*
  * MakeTaskList() erzeugt eine Liste der im System angemeldeten Tasks und
  * Prozesse
  */
void
MakeTaskList (void)
{
  NODE *node, **membernode;
  int i = 0;
  int tasks, processes;		/*GMD */

  DPOS;

  tasks = CountNodesType (&SysBase->TaskWait, NT_TASK);
  tasks += CountNodesType (&SysBase->TaskReady, NT_TASK);
  countentries = tasks;

  processes = CountNodesType (&SysBase->TaskWait, NT_PROCESS);
  processes += CountNodesType (&SysBase->TaskReady, NT_PROCESS) + 1;

  countentries += processes;


  if (NoEntries ())
    return;

  Entries = AllocScrollEntries (countentries);

  membernode = (NODE **) MyAllocVec (countentries * sizeof (NODE *),
				     MEMF_ANY | MEMF_CLEAR, KILL);

#if 0
/* *INDENT-OFF* */

* /* GMD; this Forbid/Disable looks suspect!! */
*   Forbid ();
*   Disable ();
* 
*   for (node = SysBase->TaskWait.lh_Head; node->ln_Succ && (i < countentries); node = node->ln_Succ)
*     membernode[i++] = node;
* 
*   for (node = SysBase->TaskReady.lh_Head; node->ln_Succ && (i < countentries); node = node->ln_Succ)
*     membernode[i++] = node;
* 
*   if (i < countentries)
*     membernode[i++] = &SysBase->ThisTask->tc_Node;
* 
*   Enable ();
* 
*   countentries = i;
* 
*   for (i = 0; i < countentries; i++)
*     CopyTaskNode (i, membernode[i]);
* 
*   Permit ();
*   Forbid ();
/* *INDENT-ON* */











#endif


  Forbid ();

  i = 0;

  for (node = SysBase->TaskWait.lh_Head;
       node->ln_Succ && (i < countentries); node = node->ln_Succ)
    {
      membernode[i++] = node;
    }

  for (node = SysBase->TaskReady.lh_Head;
       node->ln_Succ && (i < countentries); node = node->ln_Succ)
    {
      membernode[i++] = node;
    }

  if (i < countentries)
    {
      membernode[i++] = &SysBase->ThisTask->tc_Node;
    }

  countentries = i;

  for (i = 0; i < countentries; i++)
    {
      CopyTaskNode (i, membernode[i]);
    }

  Permit ();

  /*
   * now build a message for PrintStatistics() GMD
   */
  sprintf (gbuf, "Tasks = %d , Processes = %d", tasks, processes);

  MyFreeVec (membernode);

  CreateEntryList (SORT, 9);

  return;
}

 /*
  * SysSemaphoreList() listet alle angemeldeten Semaphoren
  * auf, die in der ExecBase eingetragen sind
  */
void
SysSemaphoreList (void)
{
  NODE *node;
  int i = 0;
  SIGNALSEMAPHORE *SigSem;
  char name[23], sigtask[20];

  DPOS;

  HandleHelp (MN_SysSemaphoreList);

  PrintHeader (SEMAPHORES, NULL);

  EmptyListView ();

  countentries = CountNodes (&SysBase->SemaphoreList);

  if (NoEntries ())
    return;

  Entries = AllocScrollEntries (countentries);

  Forbid ();

  for (node = SysBase->SemaphoreList.lh_Head; node->ln_Succ && (i < countentries); node = node->ln_Succ)
    {
      SigSem = (SIGNALSEMAPHORE *) node;

      savestrcpy (name, node, 22, NT_SEMAPHORE);

      if (SigSem->ss_Owner)
	savestrcpy (sigtask, &(SigSem->ss_Owner->tc_Node), 19, NT_TASK);
      else
	strcpy (sigtask, field[NO_TASK]);

      Entries[i].se_obj_id.address = node;

      sprintf (Entries[i].se_Entry, EntryAttr[SEMAPHORES].ea_dataformat,
	       Entries[i].se_obj_id.address,
	       name, node->ln_Pri, sigtask);

      i++;
    }

  countentries = i;

  Permit ();

  CreateEntryList (SORT, 9);

  PrintStatistics ();

  return;
}

 /*
  * SysVectorList() erzeugt eine Liste aller "kritischen"
  * Systemvektoren. Ist eine von ihnen ungleich NULL,
  * sollte dem nachgegangen werden, da diese eine beliebte
  * Einsprungadresse für Viren darstellen
  */
void
SysVectorList (void)
{
  EXECBASE CopySysBase;
  int i = 0;

  HandleHelp (MN_SysVectorList);

  DPOS;

  PrintHeader (SYSVECTORS, NULL);

  EmptyListView ();

  countentries = 14;

  Entries = AllocScrollEntries (countentries);

  Forbid ();
  CopyMem ((APTR) SysBase, (APTR) & CopySysBase, sizeof (EXECBASE));
  Permit ();

  strcpy (Entries[i].se_Entry, "----- Capture vectors");
  AddNodeToList (i++, NO_SORT, 0);

  MakeHexEntry (&i, "ColdCapture", CopySysBase.ColdCapture);
  MakeHexEntry (&i, "CoolCapture", CopySysBase.CoolCapture);
  MakeHexEntry (&i, "WarmCapture", CopySysBase.WarmCapture);


  MakeHeadEntry (&i, "----- Kick pointer");

  MakeHexEntry (&i, "KickMemPtr", CopySysBase.KickMemPtr);
  MakeHexEntry (&i, "KickTagPtr", CopySysBase.KickTagPtr);
  MakeHexEntry (&i, "KickCheckSum", CopySysBase.KickCheckSum);

  MakeHeadEntry (&i, "----- Exec special pointer");

  MakeHexEntry (&i, "Debug entry", CopySysBase.DebugEntry);
  MakeHexEntry (&i, "ResModules", CopySysBase.ResModules);
  MakeHexEntry (&i, "MMU-Lock", CopySysBase.ex_MMULock);

  PrintStatistics ();

  return;
}

 /*
  * SysSoftDeviceList() listet alle *.device auf, die in
  * der ExecBase angemeldet sind
  */
void
SysSoftDeviceList (void)
{
  NODE *node;
  LIBRARY *device_lib;
  int i = 0;

  HandleHelp (MN_SysSoftDeviceList);

  DPOS;

  PrintHeader (SYSSOFTDEV, NULL);

  EmptyListView ();

  countentries = CountNodes (&SysBase->DeviceList);

  if (NoEntries ())
    return;

  Entries = AllocScrollEntries (countentries);

  Forbid ();

  for (node = SysBase->DeviceList.lh_Head; node->ln_Succ && (i < countentries); node = node->ln_Succ)
    {
      device_lib = &((DEVICE *) node)->dd_Library;

      Entries[i].se_obj_id.address = device_lib;
      savestrcpy (Entries[i].se_obj_id.fullname, node, MAXFULLNAME - 1, NT_DEVICE);

      sprintf (Entries[i].se_Entry, EntryAttr[RESOURCES].ea_dataformat,
	       Entries[i].se_obj_id.address,
	       Entries[i].se_obj_id.fullname,
	       device_lib->lib_Version,
	       device_lib->lib_Revision,
	       device_lib->lib_OpenCnt);
      i++;
    }

  countentries = i;

  Permit ();

  CreateEntryList (SORT, 9);

  PrintStatistics ();

  return;
}

void
RSysMemoryAreaList (void)
{
  NODE *node;
  RSYS_ValidMemoryNode *vmnode;
  int i = 0;

  DPOS;

  PrintHeader (MEMORYAREAS, NULL);

  EmptyListView ();

  if (!Flags.dummy4)
    return;

  countentries = CountNodes (&ValidMemoryList);

  Entries = AllocScrollEntries (countentries);

  for (node = ValidMemoryList.lh_Head; node->ln_Succ && (i < countentries); node = node->ln_Succ)
    {
      vmnode = (RSYS_ValidMemoryNode *) node;

      Entries[i].se_obj_id.address = (APTR) (vmnode->vm_startaddress);

      sprintf (Entries[i].se_Entry, EntryAttr[MEMORYAREAS].ea_dataformat,
	       vmnode->vm_startaddress,
	       vmnode->vm_endaddress,
	       (char *) (IsValid (vmnode) ? "VAL" : "INV"),
	       (char *) (IsWriteProtect (vmnode) ? "R/O" : "WRI"),
	       (char *) (IsCacheable (vmnode) ? "CAC" : "NCA"),
	       vmnode->vm_comment);
      i++;
    }

  CreateEntryList (SORT, 0);

  PrintStatistics ();

  return;
}
