All pastes #944148 Raw Edit

Miscellany

public text v1 · immutable
·published 2008-03-15 22:02 UTC
rendered paste body
#include <sys/priv.h>
#include <sys/sysproto.h>
#include <sys/lock.h>
#include <sys/sx.h>
#include <sys/proc.h>
#include <sys/mutex.h>
#include <sys/kernel.h>
#include <sys/unistd.h>
#include <sys/systm.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/condvar.h>

#define MAXGLOBALMAILBOXES 	50

#define MPERM_OWNER_READ	0x100
#define MPERM_OWNER_WRITE	0x080
#define MPERM_OWNER_ADMIN	0x040
#define MPERM_GROUP_READ	0x020
#define MPERM_GROUP_WRITE	0x010
#define MPERM_GROUP_ADMIN	0x008
#define MPERM_OTHER_READ	0x004
#define MPERM_OTHER_WRITE	0x002
#define MPERM_OTHER_ADMIN	0x001

#define MPERM_READ_ALLOWED	0x4
#define MPERM_WRITE_ALLOWED	0x2
#define MPERM_ADMIN_ALLOWED	0x1

MALLOC_DECLARE(M_MBOX);
MALLOC_DEFINE(M_MBOX, "mailbox_system", "Buffers to hold mboxgr and mbox structs and their associated data");

// Function Prototypes
//==========================
static void mboxinit(void *dummy);
struct mboxgr* find_gmboxgr(const char *name, const int flag);
struct mboxgr* find_umboxgr(const uid_t uid, const int flag);
int check_mperms(struct proc *p, int perms, uid_t owner, int numGroups, gid_t *groups);


// Global Data
//==========================
struct sx 		all_gmboxgr_lock;
struct sx 		all_umboxgr_lock;
LIST_HEAD(mboxgrlist, mboxgr);
struct mboxgrlist 	all_gmboxgr;
struct mboxgrlist 	all_umboxgr;
int 			numGlobalGroups;


// Data Structures
//============================
struct mboxgr
{
	int 		type;			// 0 for user, 1 for global
	char 		name[9];		// name of GLOBAL mboxgr
	int 		perms;			// permissions
	uid_t 		owner;			// uid of owner
	gid_t		groups[NGROUPS+1];	// groups the owner belonged to when this mboxgr was created
	int		numGroups;
	LIST_ENTRY(mboxgr) mlist;
	struct mbox 	*boxes[8];
	int 		numBoxes;
	struct mtx 	m_mtx;			// lock for this struct
};

struct mbox
{
	char 		name[256];		// name of mbox
	int 		perms;			// permissions
	uid_t 		owner;			// uid of owner
	gid_t		groups[NGROUPS+1];	// groups the owner belonged to when this mboxgr was created
	int		numGroups;
	char 		message[256];		// message in mbox
	int		hasMessage;		// 0 if mbox is empty, 1 if there is a message
	struct mtx	m_mtx;
	struct cv	*readable;		// lock for this struct
	struct cv	*writeable;
};



// SUPPORT FUNCTIONS:
//======================
static void
mboxinit(dummy)
	void *dummy;
{
	printf("mailbox: Initializing CSE422 Project0 mailbox subsystem.\n");
	sx_init(&all_gmboxgr_lock, "allgmboxgr");
	sx_init(&all_umboxgr_lock, "allumboxgr");

	numGlobalGroups = 0;
	LIST_INIT(&all_gmboxgr);
	LIST_INIT(&all_umboxgr);
}
SYSINIT(mbox, SI_SUB_MBOX, SI_ORDER_ANY, mboxinit, NULL)



struct mboxgr*
find_gmboxgr(name, flag)
	const char *name;
	const int flag;
{
	struct mboxgr *g;

	sx_assert(&all_gmboxgr_lock, SA_LOCKED);
	LIST_FOREACH(g, &all_gmboxgr, mlist)
	{
		if(strcmp(name, g->name) == 0)
		{
			if(flag)
				mtx_lock(&g->m_mtx);
			return g;
		}
	}
	return NULL;
}


struct mboxgr*
find_umboxgr(uid, flag)
	const uid_t uid;
	const int flag;
{
	struct mboxgr *g;

	sx_assert(&all_umboxgr_lock, SA_LOCKED);
	LIST_FOREACH(g, &all_umboxgr, mlist)
	{
	
		if(uid == g->owner)
		{
			if(flag)
				mtx_lock(&g->m_mtx);
			return g;
		}
	}
	return NULL;
}




int
check_mperms(p,perms, owner, numGroups, groups)
	struct proc *p;
	int perms;
	uid_t owner;
	int numGroups;
	gid_t *groups;
{
	int auth = 0;
	int haveCommonGroup = 0;

	PROC_LOCK_ASSERT(p, MA_OWNED);
	
	auth = perms & (MPERM_OTHER_READ | MPERM_OTHER_WRITE | MPERM_OTHER_ADMIN);

	if(owner == p->p_ucred->cr_ruid)
		auth = auth & ((perms & (MPERM_OWNER_READ | MPERM_OWNER_WRITE | MPERM_OWNER_ADMIN)) >> 6);

	
	for(int i = 0; i < p->p_ucred->cr_ngroups;i++)
	{
		for(int j = 0; j < numGroups; j++)
		{
			if(p->p_ucred->cr_groups[i] == groups[j])
			{
				haveCommonGroup = 1;
				i = p->p_ucred->cr_ngroups;  // set this to break out of outer loop.
				break;
			}
		}
	}

	if(haveCommonGroup)
		auth = auth & ((perms & (MPERM_GROUP_READ | MPERM_GROUP_WRITE | MPERM_GROUP_ADMIN)) >> 3);
	
	return auth;
}



// SYSTEM CALLS:
//=============================


//(int type, char *name, uid_t uid, int perms)
int
create_mboxgr(td, uap)
	struct thread *td;
	register struct create_mboxgr_args *uap;
{
	struct mboxgr *g;
	uid_t targetUID;

	if(uap->type < 0 || uap->type > 1)
		return (EINVAL);

	if((uap->type == 0 && uap->name != NULL) || (uap->type == 1 && uap->name == NULL))
		return (EINVAL);

	if((uap->type==1) && (uap->name[0]==0))
		return (EINVAL);

	targetUID = uap->uid;
	if(uap->uid != 0)
	{
		if(priv_check_cred(td->td_ucred, PRIV_ROOT,0)!=0)
			return (EACCES);
	}
	else
	{
		targetUID = td->td_ucred->cr_ruid;
	}

	if(uap->type == 0)
	{
		sx_xlock(&all_umboxgr_lock);

		if((g = find_umboxgr(uap->uid, 0)) != NULL)
		{
			sx_xunlock(&all_umboxgr_lock);
			return (EINVAL);
		}
		
		MALLOC(g, struct mboxgr *, sizeof(struct mboxgr), M_MBOX, M_WAITOK);
		g->type = 0;
		g->name[0] = 0;
		g->perms = uap->perms;
		g->owner = targetUID;
		g->numBoxes = 0;
		mtx_init(&g->m_mtx,"struct mboxgr mutex",NULL, MTX_DEF);
		g->numGroups = td->td_ucred->cr_ngroups + 1;
		g->groups[0] = td->td_ucred->cr_rgid;
		for(int j =1; j<g->numGroups; j++)
		{
			g->groups[j] = td->td_ucred->cr_groups[j-1];
		}

		LIST_INSERT_HEAD(&all_umboxgr, g, mlist);
		sx_xunlock(&all_umboxgr_lock);
	}
	else // (uap->type == 1)
	{
		sx_xlock(&all_gmboxgr_lock);
		if(numGlobalGroups == MAXGLOBALMAILBOXES)
		{
			sx_xunlock(&all_gmboxgr_lock);
			return (EPERM);
		}
		
		if((g = find_gmboxgr(uap->name, 0)) != NULL)
		{
			sx_xunlock(&all_gmboxgr_lock);
			return (EINVAL);
		}
		
		MALLOC(g, struct mboxgr *, sizeof(struct mboxgr), M_MBOX, M_WAITOK);
		g->type = 1;
		strncpy(uap->name, g->name, 8);
		g->name[8]=0;
		g->perms = uap->perms; //FIXME
		g->owner = targetUID;
		g->numBoxes = 0;
		mtx_init(&g->m_mtx,"struct mboxgr mutex",NULL, MTX_DEF);
		g->numGroups = td->td_ucred->cr_ngroups + 1;
		g->groups[0] = td->td_ucred->cr_rgid;
		for(int j =1; j<g->numGroups; j++)
		{
			g->groups[j] = td->td_ucred->cr_groups[j-1];
		}

		LIST_INSERT_HEAD(&all_gmboxgr, g, mlist);
		numGlobalGroups++;
		sx_xunlock(&all_gmboxgr_lock);
	}

	return 0;
}



int
destroy_mboxgr(td, uap)
	register struct thread *td;
	struct destroy_mboxgr_args *uap;
//(int type, char *name, uid_t uid)
{
	struct mboxgr *g;
	int authorization;
	int rootPrivs;

	if(uap->type < 0 || uap->type > 1)
		return (EINVAL);

	if((uap->type == 0 && uap->name != NULL) || (uap->type == 1 && uap->name == NULL))
		return (EINVAL);

	if((uap->type==1) && (uap->name[0]==0))
		return (EINVAL);

	if(priv_check_cred(td->td_ucred, PRIV_ROOT,0)==0)
		rootPrivs = 1;
	else
		rootPrivs = 0;


	if(uap->type == 1)
	{
		sx_xlock(&all_gmboxgr_lock);
		
		if((g = find_gmboxgr(uap->name, 1)) != NULL)
		{
			if(!rootPrivs) // root can destroy any mailbox group???? 
			{
				PROC_LOCK(td->td_proc);
				authorization = check_mperms(td->td_proc,g->perms,g->owner,g->numGroups,g->groups);
				PROC_UNLOCK(td->td_proc);
				if((authorization & MPERM_ADMIN_ALLOWED) == 0)
				{
					mtx_unlock(&g->m_mtx);
					sx_xunlock(&all_gmboxgr_lock);
					return (EACCES);
				}
			}
		
			LIST_REMOVE(g, mlist);
			numGlobalGroups--;
		}
		else
		{
			sx_xunlock(&all_gmboxgr_lock);
			return 0; // No such group, so return success.
		}
	}
	else // uap->type == 0
	{
		sx_xlock(&all_umboxgr_lock);

		if((g = find_umboxgr(uap->uid,1)) != NULL)
		{
			if(!rootPrivs) // root can destroy any mailbox group???? 
			{
				PROC_LOCK(td->td_proc);
				authorization = check_mperms(td->td_proc,g->perms,g->owner,g->numGroups,g->groups);
				PROC_UNLOCK(td->td_proc);
				if((authorization & MPERM_ADMIN_ALLOWED) == 0)
				{
					mtx_unlock(&g->m_mtx);
					sx_xunlock(&all_gmboxgr_lock);
					return (EACCES);
				}
			}
			LIST_REMOVE(g, mlist);	
		}
		else
		{
			sx_xunlock(&all_umboxgr_lock);
			return 0; // No such group, so return success.
		}
	}
		
	// replace this with calls to mbox_destroy() if neccessary to check we have perm. to delete each mbox?...?
	for(int i = 0; i < g->numBoxes; i++)
	{
		mtx_lock(&g->boxes[i]->m_mtx);
		cv_broadcast(g->boxes[i]->readable);
		cv_broadcast(g->boxes[i]->writeable);
		cv_destroy(g->boxes[i]->readable);
		cv_destroy(g->boxes[i]->writeable);
		mtx_destroy(&g->boxes[i]->m_mtx);		
		FREE(g->boxes[i],M_MBOX);
	}
	mtx_destroy(&g->m_mtx);
	FREE(g,M_MBOX);	

	if(uap->type == 0)
		sx_xunlock(&all_umboxgr_lock);
	else
		sx_xunlock(&all_gmboxgr_lock);

	return 0;
}

int
join_mboxgr(td, uap)
	register struct thread *td;
	struct join_mboxgr_args *uap;
//(char *name, pid_t pid)
{
	struct mboxgr *g;
	struct proc* p;
	p = NULL;
	int authorization;
	int rootPrivs = 0;
	//int i;
	
	if(uap->name==NULL)
		return (EINVAL);

	if(uap->name[0]==0)
		return (EINVAL);

	if(priv_check_cred(td->td_ucred, PRIV_ROOT,0)==0)
		rootPrivs = 1;
	else
		rootPrivs = 0;

	if(uap->pid == 0)
	{
		p = td->td_proc;
		PROC_LOCK(p);
	}
	else //uap->pid != 0
	{
		if((p = pfind(uap->pid)) == NULL)
		{
			return (ESRCH);
		}
	}	
	
	sx_slock(&all_gmboxgr_lock);
		
	if((g = find_gmboxgr(uap->name,1)) != NULL)  // uap->name is a valid global mailbox group name
	{
		if(!rootPrivs) // root can destroy any mailbox group???? 
		{
			authorization = check_mperms(p,g->perms,g->owner,g->numGroups,g->groups);
			mtx_unlock(&g->m_mtx);
			if((authorization & (MPERM_READ_ALLOWED | MPERM_WRITE_ALLOWED)) == 0)
			{
				PROC_UNLOCK(p);				
				sx_sunlock(&all_gmboxgr_lock);
				return (EACCES);
			}
		}

		mtx_unlock(&g->m_mtx);
		strncpy(uap->name, p->p_gmboxgr, 8);
		p->p_gmboxgr[8] = 0;
		PROC_UNLOCK(p);
		sx_sunlock(&all_gmboxgr_lock);
	}
	else
	{
		if(uap->name == NULL && (rootPrivs || (p->p_ucred->cr_ruid == td->td_ucred->cr_ruid)))
		{
			p->p_gmboxgr[0] = 0;
			PROC_UNLOCK(p);
			sx_sunlock(&all_gmboxgr_lock);			
		}
		else
		{
			PROC_UNLOCK(p);				
			sx_sunlock(&all_gmboxgr_lock);
			return (EACCES);
		}
	}

	return 0;
}


int
create_mbox(td, uap)
	register struct thread *td;
	struct create_mbox_args *uap;
//(int type, char *name, uid_t uid, int perms)
{
	uid_t targetUID;
	struct mboxgr *g;
	struct mbox *b;
	struct proc* p;
	p = NULL;
	int authorization;
	int rootPrivs = 0;
	int i;

	if(uap->type < 0 || uap->type > 1)
		return (EINVAL);

	if(uap->name == NULL)
		return (EINVAL);

	if((uap->name[0])==0)
		return (EINVAL);

	if((uap->type == 1) && (td->td_proc->p_gmboxgr[0]==0))
		return (EINVAL);

	if(strlen(uap->name)>255)
		return (E2BIG);

	if(priv_check_cred(td->td_ucred, PRIV_ROOT,0)==0)
		rootPrivs = 1;
	else
		rootPrivs = 0;

	if(uap->type == 1)
	{
		sx_slock(&all_gmboxgr_lock);
		g = find_gmboxgr(td->td_proc->p_gmboxgr,1);
		sx_sunlock(&all_gmboxgr_lock);
	}
	else // uap->type == 0
	{
		targetUID = uap->uid;
		if(targetUID == 0)
		{
			targetUID = td->td_ucred->cr_ruid;
		}
		sx_slock(&all_umboxgr_lock);
		g = find_umboxgr(targetUID,1);
		sx_sunlock(&all_umboxgr_lock);
	}

	if(g == NULL)
	{
		return (EINVAL); // mailbox group not found
	}

	if(!rootPrivs)
	{
		PROC_LOCK(td->td_proc);
		authorization = check_mperms(td->td_proc,g->perms,g->owner,g->numGroups,g->groups);
		PROC_UNLOCK(td->td_proc);
		if((authorization & MPERM_ADMIN_ALLOWED) == 0)
		{
			mtx_unlock(&g->m_mtx);
			return (EACCES);  // not allowed to create new mbox
		}
	}

	if(g->numBoxes == 8)
	{
		mtx_unlock(&g->m_mtx);
		return (EPERM);  // not allowed to create any more mboxs
	}

	for(int i = 0; i < g->numBoxes; i++)
	{
		mtx_lock(&g->boxes[i]->m_mtx);
		if(strcmp(g->boxes[i]->name, uap->name) == 0)
		{
			mtx_unlock(&g->boxes[i]->m_mtx);
			mtx_unlock(&g->m_mtx);
			return (EINVAL);  // already a box with that name
		}
		mtx_unlock(&g->boxes[i]->m_mtx);
	}

	MALLOC(b, struct mbox *, sizeof(struct mbox), M_MBOX, M_WAITOK);

	// dont use strncpy because it'd copy 255 bytes every time.
	for(i = 0; i < 255 && uap->name[i] != 0; i++)
	{
		b->name[i] = uap->name[i];
	}
	b->name[i] = 0;
	b->perms = uap->perms;
	b->owner = td->td_ucred->cr_ruid;
	mtx_init(&b->m_mtx,"struct mbox mutex",NULL, MTX_DEF);
	cv_init(b->readable,"struct mbox readable condition variable");
	cv_init(b->writeable,"struct mbox writable condition variable");
	b->numGroups = td->td_ucred->cr_ngroups + 1;
	b->groups[0] = td->td_ucred->cr_rgid;
	for(int i =1; i<b->numGroups; i++)
	{
		b->groups[i] = td->td_ucred->cr_groups[i-1];
	}
	g->boxes[g->numBoxes++] = b;
	mtx_unlock(&g->m_mtx);
	return 0;
}

int
destroy_mbox(td, uap)
	register struct thread *td;
	struct destroy_mbox_args *uap;
//(int type, char *name, uid_t uid)
{
	struct mboxgr *g;
	struct mbox *b;
	struct proc* p;
	uid_t targetUID;
	p = NULL;
	int authorization;
	int rootPrivs = 0;
	int i;
	int foundBox;

	if(uap->type < 0 || uap->type > 1)
		return (EINVAL);

	if(uap->name == NULL)
		return (EINVAL);

	if(uap->name[0]==0)
		return (EINVAL);

	if((uap->type == 1) && (td->td_proc->p_gmboxgr[0]==0))
		return (EINVAL);

	if(strlen(uap->name)>255)
		return (E2BIG);

	if(priv_check_cred(td->td_ucred, PRIV_ROOT,0)==0)
		rootPrivs = 1;
	else
		rootPrivs = 0;

	if(uap->type == 1)
	{
		sx_slock(&all_gmboxgr_lock);
		g = find_gmboxgr(td->td_proc->p_gmboxgr,1);
		sx_sunlock(&all_gmboxgr_lock);
	}
	else // uap->type == 0
	{
		targetUID = uap->uid;
		if(targetUID == 0)
		{
			targetUID = td->td_ucred->cr_ruid;
		}
		
		sx_slock(&all_umboxgr_lock);
		g = find_umboxgr(targetUID,1);
		sx_slock(&all_umboxgr_lock);
	}

	if(g == NULL)
	{
		return (EINVAL); // mailbox group not found
	}

	foundBox = 0;
	for(i = 0; i < g->numBoxes; i++)
	{
		mtx_lock(&g->boxes[i]->m_mtx);
		if(strcmp(g->boxes[i]->name, uap->name) == 0)
		{
			foundBox = 1;
			b = g->boxes[i];
			break;
		}
		mtx_unlock(&g->boxes[i]->m_mtx);
	}

	if(!foundBox)
	{
		mtx_unlock(&g->m_mtx);
		return (EINVAL);  // mailbox not found
	}

	if(!rootPrivs)
	{
		PROC_LOCK(td->td_proc);
		authorization = check_mperms(td->td_proc,b->perms,b->owner,b->numGroups,b->groups);
		PROC_UNLOCK(td->td_proc);
		if((authorization & MPERM_ADMIN_ALLOWED) == 0)
		{
			mtx_unlock(&b->m_mtx);
			mtx_unlock(&g->m_mtx);
			return (EACCES);  // not allowed to create new mbox
		}
	}

	if(i != ((g->numBoxes)-1))
	{
		g->boxes[i] = g->boxes[(g->numBoxes)-1];
	}
	g->boxes[(g->numBoxes)-1] = NULL;
	g->numBoxes--;
	cv_broadcast(b->readable);
	cv_broadcast(b->writeable);
	cv_destroy(b->readable);
	cv_destroy(b->writeable);
	mtx_destroy(&b->m_mtx);
	FREE(b,M_MBOX);
	mtx_unlock(&g->m_mtx);
	return 0;
}


int
write_mbox(td, uap)
	register struct thread *td;
	struct write_mbox_args *uap;
//(int type, char *name, uid_t uid, char *message, int flag)
{
	struct mbox *b;
	struct proc* p;
	struct mboxgr *g;
	uid_t targetUID;
	p = NULL;
	int authorization;
	int rootPrivs = 0;
	int i;
	int foundBox;

	if(uap->type < 0 || uap->type > 1)
		return (EINVAL);

	if(uap->name == NULL)
		return (EINVAL);

	if(uap->name[0]==0)
		return (EINVAL);

	if((uap->type == 1) && (td->td_proc->p_gmboxgr[0]==0))
		return (EINVAL);

	if(strlen(uap->name)>255)
		return (E2BIG);

	if(strlen(uap->message)>255)
		return (E2BIG);

	if(priv_check_cred(td->td_ucred, PRIV_ROOT,0)==0)
		rootPrivs = 1;
	else
		rootPrivs = 0;

	do
	{
		if(uap->type == 1)
		{
			sx_slock(&all_gmboxgr_lock);
			g = find_gmboxgr(td->td_proc->p_gmboxgr,1);
			sx_sunlock(&all_gmboxgr_lock);
		}
		else // uap->type == 0
		{
			targetUID = uap->uid;
			if(targetUID == 0)
			{
				targetUID = td->td_ucred->cr_ruid;
			}
			
			sx_slock(&all_umboxgr_lock);
			g = find_umboxgr(targetUID,1);
			sx_sunlock(&all_umboxgr_lock);
		}
	
		if(g == NULL)
		{
			return (EINVAL); // mailbox group not found
		}
	
		foundBox = 0;
		b=NULL;
		for(i = 0; i < g->numBoxes; i++)
		{
			mtx_lock(&g->boxes[i]->m_mtx);
			if(strcmp(g->boxes[i]->name, uap->name) == 0)
			{
				foundBox = 1;
				b = g->boxes[i];
				break;
			}
			mtx_unlock(&g->boxes[i]->m_mtx);
		}
	
		mtx_unlock(&g->m_mtx);
	
		if(!foundBox)
		{
			return (EINVAL);  // mailbox not found
		}
	
		if(!rootPrivs)
		{
			PROC_LOCK(td->td_proc);
			authorization = check_mperms(td->td_proc,b->perms,b->owner,b->numGroups,b->groups);
			PROC_UNLOCK(td->td_proc);
			if((authorization & (MPERM_WRITE_ALLOWED)) == 0)
			{
				mtx_unlock(&b->m_mtx);
				return (EACCES);  // not allowed to create new mbox
			}
		}
	
		if(b->hasMessage == 0)
		{
			//write message
			b->hasMessage = 1;
			cv_broadcast(b->readable);
			mtx_unlock(&b->m_mtx);
			return 0;
		}
	
		if(uap->flag)
		{
			mtx_unlock(&b->m_mtx);
			return (EWOULDBLOCK);
		}
	
		cv_wait_unlock(b->writeable, &b->m_mtx);
	} while(1);


	return 0;//should never get here
}

int
read_mbox(td, uap)
	register struct thread *td;
	struct read_mbox_args *uap;
//(int type, char *name, uid_t uid, char *message, int len, int flag)
{
	struct mbox *b;
	struct proc* p;
	struct mboxgr *g;
	uid_t targetUID;
	p = NULL;
	int authorization;
	int rootPrivs = 0;
	int i;
	int foundBox;

	if(uap->type < 0 || uap->type > 1)
		return (EINVAL);

	if(uap->name == NULL)
		return (EINVAL);

	if(uap->name[0]==0)
		return (EINVAL);

	if((uap->type == 1) && (td->td_proc->p_gmboxgr[0]==0))
		return (EINVAL);

	if(strlen(uap->name)>255)
		return (E2BIG);

	if(strlen(uap->message)>255)
		return (E2BIG);

	if(priv_check_cred(td->td_ucred, PRIV_ROOT,0)==0)
		rootPrivs = 1;
	else
		rootPrivs = 0;

	do
	{
		if(uap->type == 1)
		{
			sx_slock(&all_gmboxgr_lock);
			g = find_gmboxgr(td->td_proc->p_gmboxgr,1);
			sx_sunlock(&all_gmboxgr_lock);
		}
		else // uap->type == 0
		{
			targetUID = uap->uid;
			if(targetUID == 0)
			{
				targetUID = td->td_ucred->cr_ruid;
			}
			
			sx_slock(&all_umboxgr_lock);
			g = find_umboxgr(targetUID,1);
			sx_sunlock(&all_umboxgr_lock);
		}
	
		if(g == NULL)
		{
			return (EINVAL); // mailbox group not found
		}
	
		foundBox = 0;
		b=NULL;
		for(i = 0; i < g->numBoxes; i++)
		{
			mtx_lock(&g->boxes[i]->m_mtx);
			if(strcmp(g->boxes[i]->name, uap->name) == 0)
			{
				foundBox = 1;
				b = g->boxes[i];
				break;
			}
			mtx_unlock(&g->boxes[i]->m_mtx);
		}
	
		mtx_unlock(&g->m_mtx);
	
		if(!foundBox)
		{
			return (EINVAL);  // mailbox not found
		}
	
		if(!rootPrivs)
		{
			PROC_LOCK(td->td_proc);
			authorization = check_mperms(td->td_proc,b->perms,b->owner,b->numGroups,b->groups);
			PROC_UNLOCK(td->td_proc);
			if((authorization & (MPERM_READ_ALLOWED)) == 0)
			{
				mtx_unlock(&b->m_mtx);
				return (EACCES);  // not allowed to create new mbox
			}
		}
	
		if(b->hasMessage == 1)
		{
			//read message
			b->hasMessage = 0;
			cv_broadcast(b->writeable);
			mtx_unlock(&b->m_mtx);
			return 0;
		}
	
		if(uap->flag)
		{
			mtx_unlock(&b->m_mtx);
			return (EWOULDBLOCK);
		}
	
		mtx_unlock(&b->m_mtx);

		cv_wait_unlock(b->readable, &b->m_mtx);
	} while(1);
}

int
clear_mbox(td, uap)
	register struct thread *td;
	struct clear_mbox_args *uap;
//(int type, char *name, uid_t uid)
{
struct mboxgr *g;
	struct mbox *b;
	struct proc* p;
	uid_t targetUID;
	p = NULL;
	int authorization;
	int rootPrivs = 0;
	int i;
	int foundBox;

	if(uap->type < 0 || uap->type > 1)
		return (EINVAL);

	if(uap->name == NULL)
		return (EINVAL);

	if(uap->name[0]==0)
		return (EINVAL);

	if((uap->type == 1) && (td->td_proc->p_gmboxgr[0]==0))
		return (E2BIG);

	if(strlen(uap->name)>255)
		return (E2BIG);

	if(priv_check_cred(td->td_ucred, PRIV_ROOT,0)==0)
		rootPrivs = 1;
	else
		rootPrivs = 0;

	if(uap->type == 1)
	{
		sx_slock(&all_gmboxgr_lock);
		g = find_gmboxgr(td->td_proc->p_gmboxgr,1);
		sx_sunlock(&all_gmboxgr_lock);
	}
	else // uap->type == 0
	{
		targetUID = uap->uid;
		if(targetUID == 0)
		{
			targetUID = td->td_ucred->cr_ruid;
		}
		
		sx_slock(&all_umboxgr_lock);
		g = find_umboxgr(targetUID,1);
		sx_sunlock(&all_umboxgr_lock);
	}

	if(g == NULL)
	{
		return (EINVAL); // mailbox group not found
	}

	foundBox = 0;
	b=NULL;
	for(i = 0; i < g->numBoxes; i++)
	{
		mtx_lock(&g->boxes[i]->m_mtx);
		if(strcmp(g->boxes[i]->name, uap->name) == 0)
		{
			foundBox = 1;
			b = g->boxes[i];
			break;
		}
		mtx_unlock(&g->boxes[i]->m_mtx);
	}

	mtx_unlock(&g->m_mtx);

	if(!foundBox)
	{
		return (EINVAL);  // mailbox not found
	}

	if(!rootPrivs)
	{
		PROC_LOCK(td->td_proc);
		authorization = check_mperms(td->td_proc,b->perms,b->owner,b->numGroups,b->groups);
		PROC_UNLOCK(td->td_proc);
		if((authorization & (MPERM_ADMIN_ALLOWED|MPERM_READ_ALLOWED)) == 0)
		{
			mtx_unlock(&b->m_mtx);
			return (EACCES);  // not allowed to create new mbox
		}
	}

	b->hasMessage = 0;
	cv_broadcast(b->readable);
	cv_broadcast(b->writeable);
	mtx_unlock(&b->m_mtx);
	return 0;
}