/*
 *	Copyright (C) 1988, 1989  TGV, Incorporated
 *
 *	A very simple interface to the VMS lock manager
 *	(derived from the software tools mail system)
 */

#include <lckdef.h>

static int Create_Lock();

/*
 *	Lock the given user's mailbox
 */
int Lock_User_Mailbox(Username,Lock_ID)
char *Username;
int *Lock_ID;
{
	return(Do_Lock_User_Mailbox(Username, Lock_ID, 1));
}

int Lock_User_Mailbox_NoWait(Username, Lock_ID)
char *Username;
int *Lock_ID;
{
	return(Do_Lock_User_Mailbox(Username, Lock_ID, 0));
}

int Do_Lock_User_Mailbox(Username, Lock_ID, Wait)
char *Username;
int *Lock_ID;
int Wait;
{
	char Lock_Name[256];
	register char *cp,*cp1;

	/*
	 *	The lock name is "ST_username"
	 */
	cp1 = Lock_Name;
	*cp1++ = 'S'; *cp1++ = 'T'; *cp1++ = '_';
	cp = Username;
	while(*cp) {
		if ((*cp >= 'A') && (*cp <= 'Z'))
			*cp1++ = *cp++ + ('a' - 'A');
		else
			*cp1++ = *cp++;
	}
	*cp1 = 0;
	/*
	 *	Take the lock
	 */
	if (!(Create_Lock(Lock_Name, Lock_ID, Wait) & 1)) return(-1);
	return(0);
}

/*
 *	Create an exclusive access system lock
 */
static int Create_Lock(Name, Lock_ID, Wait)
char *Name;
int *Lock_ID;
int Wait;
{
	register int Status;
	long LKSB[4];
	struct {int Size; char *Ptr;} Resource_Name;

	/*
	 *	Create the resource name descriptor (limited to 31 chars)
	 */
	Resource_Name.Ptr = Name;
	Resource_Name.Size = strlen(Name);
	if (Resource_Name.Size > 31) Resource_Name.Size = 31;
	/*
	 *	Take the lock (and wait for it)
	 */
	Status = SYS$ENQW(0,LCK$K_EXMODE,LKSB,
			  Wait ? LCK$M_SYSTEM : LCK$M_SYSTEM|LCK$M_NOQUEUE,
			  &Resource_Name,0,0,0,0,0,0);
	/*
	 *	Check the return status
	 */
	if (!(Status & 1)) return(Status);
	if (!(LKSB[0] & 1)) return(LKSB[0]);
	/*
	 *	OK: Return the Lock ID and success
	 */
	*Lock_ID = LKSB[1];
	return(Status);
}

/*
 *	Remove a lock
 */
Remove_Lock(Lock_ID)
int Lock_ID;
{
	(void) SYS$DEQ(Lock_ID,0,0,0);
}
