/*
**	$RCSfile: BcMTest.c,v $
**	$Filename: BcMTest.c $
**	$Revision: 1.1 $
**	$Date: 2000/05/01 15:25:03 $
**
**	sysmon.library Broadcast Message Test Client (version 1.1)
**	
**	(C) Copyright 1996-2000 by Etienne Vogt
*/

#include <exec/alerts.h>
#include <exec/memory.h>
#include <exec/ports.h>
#include <dos/dos.h>
#include <workbench/startup.h>
#define __USE_SYSBASE
#include <proto/exec.h>
#include <proto/dos.h>
#include <string.h>
#include <stdlib.h>
#include "sysmon.h"
#include "sysmon_protos.h"
#include "sysmon_pragmas.h"

struct ExecBase *SysBase;
struct DosLibrary *DOSBase;
struct SysmonBase *SysmonBase;
static struct WBStartup *wbmsg;
static struct MsgPort *bcport;
static struct RDArgs *myrda;

ULONG __saveds main(void);
static void cleanexit(ULONG rc);
static BOOL SysLog(ULONG priority, APTR format, ...);
static STRPTR bclevel(UBYTE level);

static UBYTE version[] = "$VER: BcMTest 1.1 (1.5.2000)";
static UBYTE template[] = "PRI=PRIORITY/K/N,DEBUG/S";

#define	OPT_PRIORITY	0
#define	OPT_DEBUG	1
#define	OPTMAX		2

ULONG __saveds main(void)	/* No startup code */
{
  struct Process *myproc;
  ULONG signals;
  BOOL abort = FALSE;
  LONG opts[OPTMAX];

  SysBase = *(struct ExecBase **)4;
  DOSBase = NULL;
  SysmonBase = NULL;
  wbmsg = NULL;
  bcport = NULL;
  myrda = NULL;

  myproc = (struct Process *)FindTask(NULL);
  if ((DOSBase = (struct DosLibrary *)OpenLibrary("dos.library",36)) == NULL)
  { Alert(AT_Recovery|AG_OpenLib|AO_DOSLib);
    return 100;
  }

  if (!(myproc->pr_CLI))		/* If started from WB, exit cleanly */
  { WaitPort(&(myproc->pr_MsgPort));
    wbmsg = (struct WBStartup *)GetMsg(&(myproc->pr_MsgPort));
    cleanexit(20);
  }
  else
  {
    if ((SysmonBase = (struct SysmonBase *)OpenLibrary("sysmon.library",1)) == NULL)
    { PutStr("BcMTest: Couldn't open sysmon.library V1\n");
      cleanexit(20);
    }

    memset((char *)opts, 0, sizeof(opts));
    if ((myrda = ReadArgs(template, opts, NULL)) == NULL)
    { PrintFault(IoErr(),NULL);
      cleanexit(20);
    }

    if ((bcport = CreateMsgPort()) == NULL)
    { PutStr("BcMTest: No memory for struct BroadCastPort\n");
      cleanexit(20);
    }
    bcport->mp_Node.ln_Name = &version[6];
    if (opts[OPT_PRIORITY]) bcport->mp_Node.ln_Pri = *(LONG *)opts[OPT_PRIORITY];
    smAddBroadcastPort(bcport);

    while (!abort)
    { signals = Wait(1L << bcport->mp_SigBit | SIGBREAKF_CTRL_C);

      if (signals & 1L << bcport->mp_SigBit)
      { struct BroadcastMsg *bcmsg;

	while (bcmsg = (struct BroadcastMsg *)GetMsg(bcport))
	{ struct BroadcastMsg bcmcopy;
	  char msgtxt[256];

	/* Copy and reply message so we can't block the sender */
	  CopyMem(bcmsg, &bcmcopy, sizeof(struct BroadcastMsg));
	  strncpy(msgtxt, bcmsg->bcm_EventTxt, sizeof(msgtxt)-1);
	  msgtxt[sizeof(msgtxt)-1] = '\0';
	  bcmcopy.bcm_EventTxt = (STRPTR)msgtxt;
	  ReplyMsg((struct Message *)bcmsg);

	  Printf("%s message received from task %08lx\n%s\n",bclevel(bcmcopy.bcm_Level),bcmcopy.bcm_SenderTask,bcmcopy.bcm_EventTxt);
	  if (opts[OPT_DEBUG])
	  { Printf("bcm_Level        = %ld\n",(LONG)bcmcopy.bcm_Level);
	    Printf("bcm_Flags        = %02lx\n",(ULONG)bcmcopy.bcm_Flags);
	    Printf("bcm_CountDown    = %ld\n",(ULONG)bcmcopy.bcm_CountDown);
	    Printf("bcm_TimeOut      = %ld\n",(ULONG)bcmcopy.bcm_TimeOut);
	    Printf("bcm_ReplyCount   = %ld\n",(ULONG)bcmcopy.bcm_ReplyCount);
	    Printf("bcm_TimeOutCount = %ld\n",(ULONG)bcmcopy.bcm_TimeOutCount);
	  }
	}
      }
      if (signals & SIGBREAKF_CTRL_C) abort = TRUE;
    }
    PutStr("BcMTest exiting\n");
    smRemBroadcastPort(bcport);
  }
  cleanexit(0);
}

static void cleanexit(ULONG rc)
{
  if (bcport) DeleteMsgPort(bcport);
  if (myrda) FreeArgs(myrda);
  if (DOSBase) CloseLibrary((struct Library *)DOSBase);
  if (SysmonBase) CloseLibrary((struct Library *)SysmonBase);
  if (wbmsg)
  { Forbid();
    ReplyMsg((struct Message *)wbmsg);
  }
  Exit(rc);
}

static BOOL SysLog(ULONG priority, APTR format, ...)
{ return smVSysLog(priority, format, &format + 1);
}

static STRPTR bclevel(UBYTE level)
{
  switch (level)
  { case BCM_HALT:
    case BCM_UNMOUNT:
    case BCM_SHUTDOWN:
      return "\a\a\aSHUTDOWN";
    case BCM_URGENT:
      return "\a\aURGENT";
    case BCM_NORMAL:
    case BCM_DEBUG:
      return "\aBROADCAST";
    default:
      return "UNKNOWN";
  }
}
