/*
 * UserTool - A Tool for managing users in a MuFS environment.
 *
 * $VER: funcs.c 37.1 (20.1.94)
 */

#include <exec/memory.h>
#include <clib/exec_protos.h>

#include <libraries/reqtools.h>
#include <clib/reqtools_protos.h>

#include <libraries/gadtools.h>
#include <clib/gadtools_protos.h>

#include <stdlib.h>
#include <ctype.h>

#include "UserTool.h"
#include "parse.h"

extern LONG Tags[];
extern struct List *Users, *Groups;
extern UserStruct *CurUser;
extern GroupStruct *CurGroup;

LONG NodePos( struct List *List, struct Node *Node )
{
	struct Node *T;
	LONG i = 0;

	for( T = List->lh_Head; T != Node; T = T->ln_Succ, i++ );

	return i;
}

ULONG GetNextNumber( UBYTE *Str, LONG *Pos )
{
	UBYTE Number[256];
	LONG NumPos = 0, InPos = *Pos;

	if( Str[InPos] == '\n' )
		return -1;

	while(!( isdigit( Str[InPos] )))
		if( Str[++InPos] == '\n' )
			return -1;
	
	while( isdigit( Str[InPos] ))
		Number[NumPos++] = Str[InPos++];
	Number[NumPos] = '\0';
	
	*Pos = InPos;

	if( NumPos )
		return (ULONG) atoi( Number );
	
	return -2;
}

UserStruct *UserWithID( LONG UID )
{
	UserStruct *Tmp;

	for( Tmp = ( UserStruct * )Users->lh_Head; Tmp->us_Node.ln_Succ;
		Tmp = ( UserStruct * )Tmp->us_Node.ln_Succ )
		if( Tmp->us_UserID == UID )
			return Tmp;

	Tags[7] = ( LONG )"Group Information";
	rtEZRequest( "Illegal user UID:%ld.", "_Ok", 0L, ( struct TagItem * )Tags,
				UID );
	return 0L;
}

LONG UniqueID( UserStruct *User )
{
	UserStruct *TmpUser;

	for( TmpUser = ( UserStruct * )Users->lh_Head; TmpUser->us_Node.ln_Succ;
		TmpUser = ( UserStruct * )TmpUser->us_Node.ln_Succ ) {
		if(( TmpUser->us_UserID == User->us_UserID )&&( User != TmpUser ))
			return 0L;
	}

	return 1L;
}

LONG GetNextUID( VOID )
{
	UserStruct *User;
	LONG MaxID = 0;
	
	for( User = ( UserStruct * )Users->lh_Head; User->us_Node.ln_Succ;
		User = ( UserStruct * )User->us_Node.ln_Succ )
		if( User->us_UserID > MaxID && User->us_UserID < 65535 )
		   MaxID = User->us_UserID;
		   
	return MaxID + 1;
}

LONG GetNextGID( VOID )
{
	GroupStruct *Group;
	LONG MaxID = 0;
	
	for( Group = ( GroupStruct * )Groups->lh_Head; Group->gs_Node.ln_Succ;
		Group = ( GroupStruct * )Group->gs_Node.ln_Succ )
		if( Group->gs_GID > MaxID )
		   MaxID = Group->gs_GID;
		   
	return MaxID + 1;
}

void UpdateMember( void )
{
	struct Node *Tmp;
	LONG UserIsMember = 0;
	
	if( CurGroup ) {
		for( Tmp = CurUser->us_Groups.lh_Head; Tmp->ln_Succ;
			Tmp = Tmp->ln_Succ )
			if( Tmp->ln_Pri == CurGroup->gs_GID ) {
				UserIsMember = 1;
				break;
			}
		
		if( CurUser->us_UserID == CurGroup->gs_MgrID )
			UserIsMember = 2;
	}

	GT_SetGadgetAttrs( UserToolGadgets[GD_MEMBER], UserToolWnd, 0l,
					  GTMX_Active, UserIsMember, TAG_DONE );
}

void UpdateGadgets( LONG ListPos )
{
	LONG i;

	for( CurUser = ( UserStruct * )Users->lh_Head, i = 0;
		i < ListPos;
		i++, CurUser = ( UserStruct * )CurUser->us_Node.ln_Succ );
	
	GT_SetGadgetAttrs( UserToolGadgets[GD_USERID], UserToolWnd, 0L,
					  GTIN_Number, CurUser->us_UserID, TAG_END );
	GT_SetGadgetAttrs( UserToolGadgets[GD_REALNAME], UserToolWnd, 0L,
					  GTST_String, CurUser->us_RealName, TAG_END );
	GT_SetGadgetAttrs( UserToolGadgets[GD_HOMEDIR], UserToolWnd, 0L, 
					  GTST_String, CurUser->us_HomeDir, TAG_END );
	GT_SetGadgetAttrs( UserToolGadgets[GD_PORT], UserToolWnd, 0L,
					  GTST_String, CurUser->us_Port, TAG_END );
	UpdateMember();
}

void UpdateGroups( LONG ListPos )
{
	LONG i;

	for( CurGroup = ( GroupStruct * )Groups->lh_Head, i = 0;
		i < ListPos;
		i++, CurGroup = ( GroupStruct * )CurGroup->gs_Node.ln_Succ );
	
	UpdateMember();
}

VOID FreeUserList( struct List *FreeList )
{
	struct Node *FreeMe, *MeToo;

	while( FreeMe = RemHead( FreeList )) {
		while( MeToo = RemHead( &(( UserStruct * )FreeMe )->us_Groups ))
			FreeVec( MeToo );
		FreeVec( FreeMe );
	}
}

VOID FreeGroupList( struct List *FreeList )
{
	struct Node *FreeMe;
	
	while( FreeMe = RemHead( FreeList ))
		FreeVec( FreeMe );
}

LONG AddGroupToUser( LONG UID, LONG GID )
{
	UserStruct *User;
	struct Node *Group;
	
	if( User = UserWithID( UID )) {
		if( Group = AllocVec( sizeof( struct Node ), MEMF_CLEAR )) {
			Group->ln_Pri = GID;
			Enqueue( &User->us_Groups, Group );
			return 0L;
		}
	}

	return 1L;
}

LONG RemoveGroupFromUser( LONG UID, LONG GID )
{
	UserStruct *User;
	struct Node *Group;
	
	if( User = UserWithID( UID )) {
		for( Group = User->us_Groups.lh_Head; Group->ln_Succ;
			Group = Group->ln_Succ ) {
			if( Group->ln_Pri == GID ) {
				Remove( Group );
				FreeVec( Group );
				return 0L;
			}
		}
		return 2L;
	} else
		return 1L;
}
