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


#include <proto/exec.h>

#include "Memory.h"
#include "UserInfo.h"
#include "Server.h"


	/*
	 *		Allocate a UserInfo Structure
	 *
	 *		Public Library Function
	 */

struct muPrivUserInfo __asm __saveds *muAllocUserInfo(void)
{
	return(MAlloc(sizeof(struct muPrivUserInfo)));
}


	/*
	 *		Free a UserInfo Structure
	 *
	 *		Public Library Function
	 */

void __asm __saveds muFreeUserInfo(register __a0 struct muPrivUserInfo *info)
{
   if (info) {
		if (info->Pub.NumSecGroups)
	   	Free(info->Pub.SecGroups, info->Pub.NumSecGroups*sizeof(UWORD));
      FreeV(info->Pattern);
 		Free(info, sizeof(struct muPrivUserInfo));
	}
}


	/*
	 *		Get Information about a User
	 *
	 *		Public Library Function
	 */

struct muPrivUserInfo __asm __saveds *muGetUserInfo(register __a0 struct muPrivUserInfo *info,
																	 register __d0 ULONG keytype)
{
	return((struct muPrivUserInfo *)SendServerPacket(muSAction_GetUserInfo, (LONG)info, keytype, NULL,
																	 NULL));
}


	/*
	 *		Get the Relationship from a User to an Object
	 *
	 *		Public Library Function
	 */

ULONG __asm muGetRelationshipA(register __d0 struct muExtOwner *user, register __d1 ULONG owner,
										 register __a0 struct TagItem *taglist)
{
	ULONG flags;
	UWORD useruid, usergid;
	UWORD owneruid;

	if (user) {
		useruid = user->uid;
		usergid = user->gid;
	} else
		useruid = usergid = NULL;

	owneruid = (owner & muMASK_UID)>>16;
	if (owneruid == muNOBODY_UID) {
		if (useruid == muROOT_UID)
			flags = muRelF_ROOT_UID | muRelF_ROOT_GID | muRelF_UID_MATCH | muRelF_GID_MATCH |
					  muRelF_PRIM_GID | muRelF_NO_OWNER;
		else if (useruid == muNOBODY_UID)
			flags = muRelF_NOBODY | muRelF_UID_MATCH | muRelF_GID_MATCH | muRelF_PRIM_GID | muRelF_NO_OWNER;
		else if (usergid == muROOT_GID)
			flags = muRelF_ROOT_GID | muRelF_UID_MATCH | muRelF_GID_MATCH | muRelF_PRIM_GID |
					  muRelF_NO_OWNER;
		else
			flags = muRelF_UID_MATCH | muRelF_GID_MATCH | muRelF_PRIM_GID | muRelF_NO_OWNER;
	} else {
		if (useruid == muROOT_UID)
			flags = muRelF_ROOT_UID | muRelF_ROOT_GID | muRelF_UID_MATCH | muRelF_GID_MATCH |
					  muRelF_PRIM_GID;
		else if (useruid == muNOBODY_UID)
			flags = muRelF_NOBODY;
		else {
			if (owneruid == useruid)
				flags = muRelF_UID_MATCH;
			else
				flags = NULL;
			if (usergid == muROOT_GID)
				flags |= muRelF_ROOT_GID | muRelF_GID_MATCH | muRelF_PRIM_GID;
			else {
				UWORD ownergid = owner & muMASK_GID;
				if (ownergid == usergid)
					flags |= muRelF_GID_MATCH | muRelF_PRIM_GID;
				else if (user) {
					UWORD *sgids = muSecGroups(user);
					int i;
					for (i = 0; i < user->NumSecGroups; i++)
						if (ownergid == sgids[i]) {
							flags |= muRelF_GID_MATCH;
							break;
						}
				}
			}
		}
	}
	return(flags);
}


	/*
	 *		Convert a Public User Information Structure to an Extended Owner
	 *		Information Structure
	 *
	 *		Public Library Function
	 */

struct muExtOwner __asm __saveds *muUserInfo2ExtOwner(register __a0 struct muUserInfo *info)
{
	struct muExtOwner *owner = NULL;
	ULONG size;

	if (info) {
		size = info->NumSecGroups*sizeof(UWORD);
		if (owner = (struct muExtOwner *)MAlloc(size+sizeof(struct muExtOwner))) {
			owner->uid = info->uid;
			owner->gid = info->gid;
			owner->NumSecGroups = info->NumSecGroups;
			CopyMem(info->SecGroups, muSecGroups(owner), size);
		}
	}
	return(owner);
}
