/*
***************************************************************************
*
* 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 , struct 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"

	/*
	 * MakeLibList() erzeugt eine Liste aus allen im System
	 * angemeldeten Libraries.
	 */
void
MakeLibList(void)
{
	struct Node *node;
	struct 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 = (struct 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
MakeResList(void)
{
	struct Node *node;
	struct 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 = (struct 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)
{
	struct Node *node;
	int	i;

	DPOS;

	countentries = 16;

	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)
		{
			savestrcpy(Entries[i].se_obj_id.fullname, node, MAXFULLNAME - 1, NT_INTERRUPT);

			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)((struct Interrupt *) node)->is_Data,
					  (long)(((struct Interrupt *) node)->is_Code));
		}
		else sprintf(Entries[i].se_Entry, EntryAttr[INTERRUPTS].ea_dataformat,
					  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)
{
	struct Node *node;
	struct Task *task;
	struct 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 = (struct MsgPort *)node;
		task = (struct 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, struct Node *node)
{
   struct CommandLineInterface *CLI;
   struct 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 = (struct Process *) node;
      CLI = (struct 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) && ((struct Process *) node)->pr_CLI)
		sprintf(cli, "%3ld", ((struct 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) ((struct Task *) node)->tc_SPUpper -
				(ULONG) ((struct Task *) node)->tc_SPLower),
			  status[((struct Task *) node)->tc_State],
			  cli);

	return;
}

	/*
	 * MakeTaskList() erzeugt eine Liste der im System angemeldeten Tasks und
	 * Prozesse
	 */
void
MakeTaskList(void)
{
	struct Node *node, **membernode;
	register int i = 0;

	DPOS;

	countentries = CountNodes(&SysBase->TaskWait);
	countentries += CountNodes(&SysBase->TaskReady) + 1;

	if (NoEntries()) return;

	Entries = AllocScrollEntries(countentries);

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

	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();

	MyFreeVec(membernode);

	CreateEntryList(SORT, 9);

	return;
}

	/*
	 * SysSemaphoreList() listet alle angemeldeten Semaphoren
	 * auf, die in der ExecBase eingetragen sind
	 */
void
SysSemaphoreList(void)
{
	struct Node *node;
	int	i = 0;
	struct 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 = (struct 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)
{
	struct 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(struct 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)
{
	struct Node *node;
	struct 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 = &((struct 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)
{
	struct Node *node;
   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 = (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;
}

