/*
   testfs.c --- test (filesystem) handlers.

   (c) Copyright 1998 SHW Wabnitz
   Written by Bernhard Fastenrath (fasten@shw.com)

   This file may be distributed under the terms
   of the GNU General Public License.
*/

#include <stdio.h>

#include "shutdown_cmd.h"

typedef struct {
  struct Message   sp_Msg;
  struct DosPacket sp_Pkt;
  struct Node     *sp_Dev;
} MyStandardPacket;

/// FreeList()
static void
FreeList (List *list)
{
  Node *node, *next;

  for (next = node = list -> lh_Head; next = node -> ln_Succ; node = next)
  {
    if (node -> ln_Name)
      FreeMem (node -> ln_Name, node -> ln_Pri);
    FreeMem (node, sizeof (Node));
  }
}
///

/// FreeStdPktList()
static void
FreeStdPktList (List *list)
{
  Node *node, *next;

  for (next = node = list -> lh_Head; next = node -> ln_Succ; node = next)
    FreeMem (node, sizeof (MyStandardPacket));
}
///

/// SendStandardPacket()
static int
SendStandardPacket (MsgPort *mp, MyStandardPacket *sp, char *handler, ULONG action, ULONG arg1)
{
  DevProc *dp = NULL;

  dp = GetDeviceProc (handler, dp);
  if (dp)
  {
    sp -> sp_Pkt.dp_Type = action;
    sp -> sp_Pkt.dp_Arg1 = arg1;
    SendPkt (&sp -> sp_Pkt, dp -> dvp_Port, mp);
    FreeDeviceProc (dp);
    return 1;
  }
  return 0;
}
///

/// AllocateStandardPackets ()
static int
AllocateStandardPackets (List *pktlist, int count)
{
  MyStandardPacket *sp;  
  int t;

  NewList (pktlist);

  for (t=0; t<count; t++)
  {
    if (!(sp = AllocMem (sizeof (MyStandardPacket), MEMF_PUBLIC | MEMF_CLEAR)))
      break;
    sp -> sp_Msg.mn_Length = sizeof (MyStandardPacket);
    sp -> sp_Msg.mn_Node.ln_Name = (char *) &sp -> sp_Pkt;
    sp -> sp_Pkt.dp_Link = &sp -> sp_Msg;
    AddTail (pktlist, &sp -> sp_Msg.mn_Node);
  }
  return t;
}
///

/// TestHandler()
static int
TestHandler (MsgPort *mp, char *filesystem, int flag)
{
  int len, count = 0, icount = 0, out_of_mem = 0;
  List devlist, pktlist;
  MyStandardPacket *sp;
  Node *node;
  DosList *dl;
  char *name;

  NewList (&devlist);
  NewList (&pktlist);

  dl = LockDosList ( LDF_DEVICES | LDF_READ );

  while (dl = NextDosEntry (dl, LDF_DEVICES))
  {
    if (node = (Node *) AllocMem (sizeof (Node), MEMF_CLEAR))
    {
      name = BADDR (dl -> dol_Name);
      len = (int) name[0];

      if (node -> ln_Name = AllocMem (len + 2, 0))
      {
        CopyMem (name+1, node -> ln_Name, len);
        node -> ln_Name[len] = ':';
        node -> ln_Name[len+1] = '\0';
        node -> ln_Pri = len + 2;
        AddTail (&devlist, node);
        count ++;
      }
      else
      {
        out_of_mem = 1;
        FreeMem (node, sizeof (Node));
        break;
      }
    }
  }

  UnLockDosList ( LDF_DEVICES | LDF_READ );

  if ((icount = AllocateStandardPackets (&pktlist, count)) == 0)
    out_of_mem = 1;
  count = icount;

  if (out_of_mem)
  {
    FreeStdPktList (&pktlist);
    FreeList (&devlist);
    return 0;
  }

  node = devlist.lh_Head;

  printf ("testfs found the following handlers:\n");

  while (node -> ln_Succ)
  {
    if (sp = (MyStandardPacket *) RemHead (&pktlist))
    {
      sp -> sp_Dev = node;
      SendStandardPacket (mp, sp, node -> ln_Name, ACTION_IS_FILESYSTEM, 0);
      icount --;
      printf ("%s ", node -> ln_Name);
      node = node -> ln_Succ;
    }
  }
  printf ("\n");
  for (;;)
  {
    WaitPort (mp);

    while (sp = (MyStandardPacket *) GetMsg (mp))
    {
      icount ++;
      node = (Node *) sp -> sp_Dev;

      if (sp -> sp_Pkt.dp_Type == ACTION_IS_FILESYSTEM &&
          sp -> sp_Pkt.dp_Res1 == DOSTRUE)
      {
        printf ("Filesystem Handler: %s", node -> ln_Name);
        AddTail (&pktlist, &sp -> sp_Msg.mn_Node);
      }
      else
      {
        printf ("    Non-fs Handler: %s", node -> ln_Name); 
        AddTail (&pktlist, &sp -> sp_Msg.mn_Node);
      }
      printf ("\t(%d replies out of %d)\n", icount, count);
    }
    if (icount == count)
      break;
  }
  FreeStdPktList (&pktlist);
  FreeList (&devlist);
  return 1;
}
///

/// main()
int
main (int argc, char *argv[])
{
  char *filesystem = NULL;
  MsgPort *mp;

  if (!(mp = CreatePort (NULL, 0)))
    return 0;

  if (argc == 2) {
    filesystem = argv[1];
  }
  TestHandler (mp, filesystem, 0);
  DeletePort (mp);
}
///
