/************************************************************
* MultiUser - MultiUser Task/File Support System				*
* ---------------------------------------------------------	*
* Monitoring																*
* ---------------------------------------------------------	*
* © Copyright 1993-1994 Geert Uytterhoeven						*
* All Rights Reserved.													*
************************************************************/


#include <exec/semaphores.h>
#include <exec/execbase.h>
#include <proto/exec.h>
#include <string.h>

#include "Memory.h"
#include "Monitor.h"
#include "Config.h"
#include "Locale.h"
#include "LibHeader.h"
#include "Task.h"
#include "UserInfo.h"


	/*
	 *		Init Monitor List
	 */

void InitMonList(void)
{
	ObtainSemaphore(&muBase->MonitorSem);
	NewList((struct List *)&muBase->MonitorList);
	ReleaseSemaphore(&muBase->MonitorSem);
}

	/*
	 *		Add a Monitor
	 *
	 *		Public Library Function
	 *
	 *		This routine may be called only by root
	 */

BOOL __asm __saveds muAddMonitor(register __a0 struct muMonitor *monitor)
{
	struct muExtOwner *xowner;
	BOOL res = FALSE;

	if (monitor) {
		xowner = GetTaskExtOwner(SysBase->ThisTask);
		if (muGetRelationshipA(xowner, NULL, NULL) & muRelF_ROOT_UID) {
			ObtainSemaphore(&muBase->MonitorSem);
			AddTail((struct List *)&muBase->MonitorList, (struct Node *)&monitor->Node);
			ReleaseSemaphore(&muBase->MonitorSem);
			res = TRUE;
		}
		muFreeExtOwner(xowner);
	}
	return(res);
}


	/*
	 *		Remove a Monitor
	 *
	 *		Public Library Function
	 */

void __asm __saveds muRemMonitor(register __a0 struct muMonitor *monitor)
{
	struct muMonMsg *msg;

	if (monitor) {
		ObtainSemaphore(&muBase->MonitorSem);
		Remove((struct Node *)&monitor->Node);
		if (monitor->Mode == muMon_SEND_MESSAGE)
			while (msg = (struct muMonMsg *)GetMsg(monitor->Message.Port))
				ReplyMsg(msg);
		ReleaseSemaphore(&muBase->MonitorSem);
	}
}


	/*
	 *		Call the Monitors
	 */

void CallMonitors(ULONG triggerbit, UWORD from, UWORD to, char *userid)
{
	struct muMonitor *mon;
	struct muMonMsg *msg;

	ObtainSemaphoreShared(&muBase->MonitorSem);
	for (mon = (struct muMonitor *)muBase->MonitorList.mlh_Head; mon->Node.mln_Succ;
		  mon = (struct muMonitor *)mon->Node.mln_Succ)
		if (mon->Triggers & 1<<triggerbit)
			switch (mon->Mode) {
				case muMon_SEND_SIGNAL:
					Signal(mon->Signal.Task, 1<<mon->Signal.SignalNum);
					break;
				
				case muMon_SEND_MESSAGE:
					if (msg = MAlloc(sizeof(struct muMonMsg))) {
						msg->ExecMsg.mn_ReplyPort = muBase->MonitorPort;
						msg->ExecMsg.mn_Length = sizeof(struct muMonMsg);
						msg->Monitor = mon;
						msg->Trigger = 1<<triggerbit;
						msg->From = from;
						msg->To = to;
						if (userid) {
							strncpy(msg->UserID, userid, muUSERIDSIZE-1);
							msg->UserID[muUSERIDSIZE-1] = '\0';
						}
						PutMsg(mon->Message.Port, msg);
					}
					break;
			}
	ReleaseSemaphore(&muBase->MonitorSem);
}


	/*
	 *		Free the replied Monitor Messages
	 */

void FreeRepliedMonMsg(void)
{
	struct muMonMsg *msg;

	while (msg = (struct muMonMsg *)GetMsg(muBase->MonitorPort))
		Free(msg, sizeof(struct muMonMsg));
}
