/*
***************************************************************************
*
* Datei:
*    RSysDosLists.c
*
* Inhalt:
*    void MakeAssignList(void);
*    void MakeVolumeList(void);
*    void RSysLockList(void);
*    void SysResidentList(void);
*    void SysCLIList(void);
*    void SysResidentProg(void);
*
* Bemerkungen:
*    Erzeugung von Listen der DOS-Library.
*
* Erstellungsdatum:
*    07-Jul-93    Rolf Böhme
*
* Änderungen:
*    07-Jul-93    Rolf Böhme    Erstellung
*
***************************************************************************
*/

#include "RSysDebug.h"
#include "RSysFunc.h"

   /*
    * MakeAssignList() erzeugt eine Liste aller Assigns im
    * System
    */
void
MakeAssignList(void)
{
   int   i = 0;
   char  helpdir[MAXFULLNAME],dir[20];
   struct DosList *dl;
   BPTR  lock;

   DPOS;

   countentries = CountDevices(LDF_ASSIGNS);

   if (NoEntries())
      return;

   Entries = AllocScrollEntries(countentries);

   dl = LockDosList(LDF_ASSIGNS | LDF_READ);

   while ((dl = NextDosEntry(dl, LDF_ASSIGNS | LDF_READ)) &&
          (i < countentries))
   {
      B2CStr(Entries[i].se_obj_id.fullname, dl->dol_Name);
      strcat(Entries[i].se_obj_id.fullname, ":");

      if (lock = Lock((UBYTE *) Entries[i].se_obj_id.fullname, ACCESS_READ))
      {
         NameFromLock(lock, (UBYTE *) helpdir, 107);
         strncpy(dir, helpdir, 28);

         UnLock(lock);
      }
      else
         strcpy(dir, field[NO_LOCK]);

      sprintf(Entries[i].se_Entry, EntryAttr[ASSIGNS].ea_dataformat,
              Entries[i].se_obj_id.fullname, dir);

      AddNodeToList(i, SORT);

      i++;
   }

   UnLockDosList(LDF_ASSIGNS | LDF_READ);

   PrintStatistics();

   return;
}

   /*
    * MakeVolumeList() erzeugt eine Liste aller Volumes im
    * System
    */
void
MakeVolumeList(void)
{
   int   i = 0;
   struct DosList *dl;
   long free, used, percentused;
   char state[6],type[6];

   DPOS;

   DisableSysRequest(TRUE);

   countentries = CountDevices(LDF_VOLUMES);

   if (NoEntries())
      return;

   Entries = AllocScrollEntries(countentries);

   dl = LockDosList(LDF_VOLUMES | LDF_READ);

   while ((dl = NextDosEntry(dl, LDF_VOLUMES | LDF_READ)) &&
          (i < countentries))
   {
      B2CStr(Entries[i].se_obj_id.fullname, dl->dol_Name);
      strcat(Entries[i].se_obj_id.fullname, ":");

      FreeBytes(Entries[i].se_obj_id.fullname,&free,&used,&percentused,
                state,type);

      sprintf(Entries[i].se_Entry, EntryAttr[VOLUMES].ea_dataformat,
              Entries[i].se_obj_id.fullname,
              free, used, percentused,
              (percentused > 90L) ? '*' : ' ',
              state, type);

      AddNodeToList(i, SORT);

      i++;
   }

   UnLockDosList(LDF_VOLUMES | LDF_READ);

   DisableSysRequest(FALSE);

   PrintStatistics();

   return;
}

#define BPTR_TO_C(strtag, var)  ((struct strtag *)(BADDR( (ULONG) var)))
#define C_TO_BPTR(var)          (((ULONG)var)>>2)

void
RSysLockList(void)
{
   struct List *DispList;
   struct Remember *DispKey = NULL;
   struct Node *LockNode, *node;
   BPTR  lo;
   struct DosList *dl;
   register struct FileLock *lptr,
                            *alptr = NULL;
   char buffer[80], *access[] = { "-----", "WRITE", "READ" };
   int i;

   PrintHeader(VOLLOCKS, NULL);

   EmptyListView();

   DispList = AllocRemember(&DispKey,sizeof(struct List),MEMF_CLEAR);
   if(DispList)
   {
      NewList(DispList);

      Forbid();

      dl = LockDosList(LDF_VOLUMES | LDF_READ);

      while (dl)
      {
         if ((dl->dol_Type == DLT_VOLUME) && B2CStr(buffer, dl->dol_Name))
         {
            strcat(buffer, ":");

            if (lo = Lock((UBYTE *)buffer, ACCESS_READ))
            {
               for (lptr = BPTR_TO_C(FileLock, lo);
                    lptr != NULL; lptr = BPTR_TO_C(FileLock, lptr->fl_Link))
               {
                  if (NameFromLock(C_TO_BPTR(lptr), (UBYTE *)buffer, sizeof(buffer)) &&
                      (LockNode = AllocRemember(&DispKey,sizeof(struct Node),
                                                MEMF_CLEAR)) &&
                      (LockNode->ln_Name = AllocRemember(&DispKey,BUFSIZE,
                                                MEMF_CLEAR)))
                  {
                     sprintf(LockNode->ln_Name,EntryAttr[31].ea_dataformat,
                             buffer, access[-lptr->fl_Access]);

                     AddNodeSorted(DispList,LockNode);
                  }

                  if (BPTR_TO_C(FileLock, lptr->fl_Link) == alptr)
                     break;

                  alptr = lptr;
               }

               UnLock(lo);
            }
         }

         dl = NextDosEntry(dl, LDF_VOLUMES | LDF_READ);
      }

      UnLockDosList(LDF_VOLUMES | LDF_READ);

      Permit();

      countentries = CountNodes(DispList);

      if(!NoEntries())
      {
         Entries = AllocScrollEntries(countentries);

         for(node = DispList->lh_Head, i = 0; node->ln_Succ && (i < countentries);
             node = node->ln_Succ, i++)
            strcpy(Entries[i].se_Entry, node->ln_Name);

         CreateEntryList(SORT);
      }

      FreeRemember(&DispKey,TRUE);

      PrintStatistics();
   }
   else
      ErrorHandle(MEMORY_ERR, ALLOC_FAIL, KILL);

   return;
}

   /*
    * SysResidentList() listet die residenten Handler
    * aller Devices auf
    */
void
SysResidentList(void)
{
   int   i = 0;
   struct FileSysStartupMsg *fssm;
   struct DosList *dl;
   char devhandler[30];

   DPOS;

   PrintHeader(DEVS, NULL);

   EmptyListView();

   countentries = CountDevices(CNTMASK);

   if (NoEntries())
      return;

   Entries = AllocScrollEntries(countentries);

   DisableSysRequest(TRUE);

   dl = LockDosList(MASK);

   while ((dl = NextDosEntry(dl, MASK)) && (i < countentries))
   {
      B2CStr(Entries[i].se_obj_id.fullname, dl->dol_Name);
      strcat(Entries[i].se_obj_id.fullname, ":");

      if (dl->dol_Task &&
          (fssm = B2C(dl->dol_misc.dol_handler.dol_Startup)))
         B2CStr(devhandler, fssm->fssm_Device);
      else if (dl->dol_misc.dol_handler.dol_Handler)
         B2CStr(devhandler, dl->dol_misc.dol_handler.dol_Handler);
      else
         strcpy(devhandler, field[NO_HANDLER]);

      sprintf(Entries[i].se_Entry, EntryAttr[16].ea_dataformat,
              Entries[i].se_obj_id.fullname,
              devhandler);

      i++;
   }

   countentries = i;

   UnLockDosList(MASK);

   DisableSysRequest(FALSE);

   CreateEntryList(SORT);

   PrintStatistics();

   return;
}

   /*
    * Diese Struktur ist undokumentiert, existiert aber :-)
    */
struct ResidentList
{
   BPTR  rl_Next;
   LONG  rl_UseCount;
   BPTR  rl_SegList;
   BSTR  rl_SegName;
};

   /*
    * SysCLIList() erzeugt eine Liste aller CLI's im System
    */
void
SysCLIList(void)
{
   int   clicnt,
         i = 0;
   struct Process *cliproc;

   DPOS;

   PrintHeader(CLI, NULL);

   EmptyListView();

   countentries = MaxCli();

   if (NoEntries())
      return;

   Entries = AllocScrollEntries(countentries);

   Forbid();

   for (clicnt = 1; clicnt < countentries; clicnt++)
   {
      cliproc = FindCliProc((ULONG) clicnt);
      if (cliproc)
      {
         savestrcpy(Entries[i].se_obj_id.fullname, &(cliproc->pr_Task.tc_Node),
                    MAXFULLNAME - 1, NT_PROCESS);

         sprintf(Entries[i].se_Entry, EntryAttr[19].ea_dataformat,
                 (char)cliproc->pr_TaskNum,
                 Entries[i].se_obj_id.fullname,
                 cliproc->pr_Task.tc_Node.ln_Pri,
                 ((ULONG) cliproc->pr_Task.tc_SPUpper -
                  (ULONG) cliproc->pr_Task.tc_SPLower));

         i++;
      }
   }

   countentries = i;

   Permit();

   CreateEntryList(SORT);

   PrintStatistics();

   return;
}

   /*
    * SysResidentProg() listet alle internen residenten
    * Shell-Programme auf, die mit dem Befehl RESIDENT des
    * AmigaDOS verwaltet werden können
    */
void
SysResidentProg(void)
{
   extern struct DosLibrary *DOSBase;
   char  name[100];
   struct RootNode *RN = (struct RootNode *) DOSBase->dl_Root;
   struct DosInfo *DI = (struct DosInfo *) BADDR(RN->rn_Info);
   struct ResidentList *RL = (struct ResidentList *) BADDR(DI->di_NetHand),
        *loop = RL;
   int   cnt = 0,
         i;

   DPOS;

   PrintHeader(RESIDENTS, NULL);

   EmptyListView();

   PrintInfo("Counting residents", NO_SPEAK, 0);

   Forbid();

   for (loop = (struct ResidentList *) RL; loop;
        loop = (struct ResidentList *) BADDR(loop->rl_Next))
      cnt++;

   Permit();

   countentries = cnt;

   if (NoEntries())
      return;

   Entries = AllocScrollEntries(countentries);

   Forbid();

   cnt = 0;

   for (loop = (struct ResidentList *) RL; loop && (cnt < countentries);
        loop = (struct ResidentList *) BADDR(loop->rl_Next))
   {
      for (i = 0; i < *(UBYTE *)&loop->rl_SegName; i++)
         name[i] = (char)*(UBYTE *) (((BPTR) & loop->rl_SegName) + i + 1L);

      name[i] = STRINGEND;

      sprintf(Entries[cnt].se_Entry, EntryAttr[20].ea_dataformat,
              name,
              loop->rl_UseCount,
              ((loop->rl_UseCount >= 0) ? "EXTERNAL" : "INTERNAL"));

      cnt++;
   }

   countentries = cnt;

   Permit();

   CreateEntryList(SORT);

   PrintStatistics();

   return;
}
