#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <ctype.h>
#include <error.h>

#include <libraries/mui.h>
#include <libraries/asl.h>
#include <libraries/gadtools.h>
#include <libraries/multiuser.h>
#include <libraries/asl.h>
#include <libraries/iffparse.h>

#include <proto/dos.h>
#include <proto/exec.h>
#include <proto/intuition.h>
#include <proto/muimaster.h>
#include <proto/asl.h>
#include <proto/icon.h>

#define StringSucc(win,fromg,tog)\
	DoMethod(fromg,MUIM_Notify,MUIA_String_Acknowledge,MUIV_EveryTime,\
	win,3,MUIM_Set,MUIA_Window_ActiveObject,tog)
#define SetButtonID(app,butobj,id)\
	DoMethod(butobj,MUIM_Notify,MUIA_Pressed,FALSE,\
		app,2,MUIM_Application_ReturnID,id)
#define GetString(strobj,tostr,tempptr)\
	{ get(strobj,MUIA_String_Contents,&tempptr);\
	  strcpy(tostr,tempptr); }

char VersionTag[]="\0$VER: JoranEditUsers 1.0 (14.12.93)";

struct Library *MUIMasterBase;
extern struct WBStartup *WBenchMsg;
struct DiskObject *DiskObj;

char *PassFileName="RAM:passwd",*GroupFileName="RAM:multiuser.group";
char *SucPassFileName=NULL;
char *SucGroupFileName=NULL;

#define mySHELLSIZE 255

enum {
	UserID_ID=1,
	ChangedPasswd_ID,
	ChangeBut_ID,
	PasswdClose_ID,
	AddGroup_ID,
	DelGroup_ID,
	GidClose_ID,
	GidDblClk_ID,
	GroupID_ID,
	MainSave_ID,
	MainCancel_ID,
	CancelAddUser_ID,
	AddUser_ID,
	DelUser_ID,
	AddUserOk_ID,
	GroupID2_ID,
	AddGid_ID,
	AddGidCancel_ID,
	AddGidOk_ID,
	Admin_ID,
	DelGid_ID
};

//====== MainWin ==============
APTR App,MainWin;
APTR UserIDList,UserIDListview;
APTR GroupIDList,GroupIDListview;
APTR uidTxt,NameStr,HomeStr,PortStr;
APTR ChangePasswdBut,AddGroupBut,DelGroupBut,EditGroupBut;
APTR PasswdChk;
APTR MainSave,MainCancel;
APTR AddUserBut,DelUserBut;
//========= GetGidWin ========
APTR GetGidWin;
APTR GidListview,GidList;
//========= AddUserWin =======
APTR AddUserWin;
APTR UserIDStr,uidStr;
APTR AddUserOkBut,AddUserCancelBut;
//===== GroupWin =============
APTR GroupWin,GidList2,GidListview2;
APTR GidTxt,AdminTxt,AdminBut,GroupNameStr;
APTR AddGidBut,DoneGidBut,DelGidBut;
//======== AddGroupWin ========
APTR AddGroupWin;
APTR GroupIDStr,gidStr;
APTR AddGroupOkBut,AddGroupCancelBut;

struct UserInfo {
	struct Node UserNode;
	char UserID[muUSERIDSIZE];
	char Password[muPASSWORDSIZE];
	UWORD uid,gid;
	char UserName[muUSERNAMESIZE];
	char HomeDir[muHOMEDIRSIZE];
	char Shell[mySHELLSIZE];
};

struct GroupInfo {
	struct Node GroupNode;
	char GroupID[muGROUPIDSIZE];
	UWORD gid,MgsUid;
	char GroupName[muGROUPNAMESIZE];
};

struct ExtGroupInfo {
	struct MinNode ExtGroupNode;
	UWORD uid,gid;
};

struct MinList UserList;
struct MinList GroupList;
struct MinList ExtGroupList;

struct UserInfo *CurUserInfo;
struct GroupInfo *CurGroupInfo;
struct GroupInfo *CurGidInfo;

struct FileRequester *HomeFileRequest;

ULONG __asm __saveds GidMultiHookFunc(register __a1 struct GroupInfo *,register __a2 char **);
struct Hook GidMultiHook={0,0,GidMultiHookFunc,0,0};
ULONG __asm __saveds PopupHomeHookFunc(register __a2 APTR);
struct Hook PopupHomeHook={0,0,PopupHomeHookFunc,0,0};

ULONG __asm __saveds GidMultiHookFunc(register __a1 struct GroupInfo *gi,register __a2 char **cols)
{
	cols[0]=gi->GroupID;
	cols[1]=gi->GroupName;

	return 0;
}

ULONG __asm __saveds PopupHomeHookFunc(register __a2 APTR StrObj)
{
	struct Window *WinPtr;
	APTR Path;

	if(!CurUserInfo) return 0;

	get(StrObj,MUIA_Window,&WinPtr);
	get(StrObj,MUIA_String_Contents,&Path);
	set(App,MUIA_Application_Sleep,TRUE);
	if (MUI_AslRequestTags(HomeFileRequest,
		ASLFR_Window,WinPtr,
		ASLFR_InitialDrawer,Path,
		TAG_DONE
	))
	{
		set(App,MUIA_Application_Sleep,FALSE);
		set(StrObj,MUIA_String_Contents,HomeFileRequest->rf_Dir);
	} else set(App,MUIA_Application_Sleep,FALSE);
	
	return 0;
}

void GetArg(char *Line,char *Result)
{
	char *l=Line;
	
	while(*l!='|' && *l!='\n' && *l!='\0') *(Result++)=*(l++);
	*Result='\0';
	if(*l=='|') l++;
	while(*l!='\n' && *l!='\0') *(Line++)=*(l++);
	*Line='\0';
}

int chrcnt(char *str,char c)
{
	int r=0;
	while(*str) if(*(str++)==c) r++;
	return r;
}

struct UserInfo *GetUserInfo(UWORD uid)
{
	struct UserInfo *ui;
	
	for(ui=(struct UserInfo *)UserList.mlh_Head;ui!=(struct UserInfo *)&UserList.mlh_Tail;ui=(struct UserInfo *)ui->UserNode.ln_Succ)
		if(ui->uid==uid) return ui;
	return NULL;
}

struct GroupInfo *GetGroupInfo(UWORD gid)
{
	struct GroupInfo *gi;
	
	for(gi=(struct GroupInfo *)GroupList.mlh_Head;gi!=(struct GroupInfo *)&GroupList.mlh_Tail;gi=(struct GroupInfo *)gi->GroupNode.ln_Succ)
		if(gi->gid==gid) return gi;
	return NULL;
}

char *InitLists(void)
{
	FILE *UserFile=NULL,*GroupFile=NULL;
	struct UserInfo *ui;
	struct GroupInfo *gi;
	struct ExtGroupInfo *egi;
	char Line[512];
	char Arg[512];
	int error;
	
	NewList((struct List *)&UserList);
	NewList((struct List *)&GroupList);
	NewList((struct List *)&ExtGroupList);
	
	error=0;
	if(!(UserFile=fopen(PassFileName,"r"))) error=errno;
	if(!error &&!(GroupFile=fopen(GroupFileName,"r"))) error=errno;
	
	while(!error && fgets(Line,sizeof(Line),UserFile))
	{
		if(strlen(Line)<10) continue;
		if(chrcnt(Line,'|')!=6) error=-2;
		else if(ui=malloc(sizeof(struct UserInfo)))
		{
			GetArg(Line,ui->UserID);
			if(!*ui->UserID) error=-2;
			else 
			{
				GetArg(Line,ui->Password);
				GetArg(Line,Arg);ui->uid=atoi(Arg);
				if(GetUserInfo(ui->uid)) error=-2;
				else
				{
					GetArg(Line,Arg);ui->gid=atoi(Arg);
					GetArg(Line,ui->UserName);
					GetArg(Line,ui->HomeDir);
					GetArg(Line,ui->Shell);
					ui->UserNode.ln_Name=ui->UserID;
					AddTail((struct List *)&UserList,(struct Node *)ui);
				}
			}
		} else error=-1;
	}
	
	if(!error && errno) error=errno;
	
	while(!error && fgets(Line,sizeof(Line),GroupFile))
	{
		if(strlen(Line)<2) continue;
		if(!strchr(Line,'|'))
		{
			char *p,*q;
			UWORD uid,gid;
			
			if(p=strchr(Line,':'))
			{
				*(p++)='\0';
				uid=atoi(Line);
				while(!error && *p)
				{
					if(q=strchr(p,',')) *(q++)='\0';
					else while(*q) q++;
					gid=atoi(p);
					p=q;
					if(egi=malloc(sizeof(struct ExtGroupInfo)))
					{
						egi->uid=uid;
						egi->gid=gid;
						AddTail((struct List *)&ExtGroupList,(struct Node *)egi);
					} else error=-1;
				}
			} else error=-3;
		}
		else if(gi=malloc(sizeof(struct GroupInfo)))
		{
			if(chrcnt(Line,'|')!=3) error=-4;
			else
			{
				GetArg(Line,gi->GroupID);
				if(!*gi->GroupID) error=-4;
				else
				{
					GetArg(Line,Arg);gi->gid=atoi(Arg);
					if(GetGroupInfo(gi->gid)) error=-4;
					else
					{
						GetArg(Line,Arg);gi->MgsUid=atoi(Arg);
						GetArg(Line,gi->GroupName);
						gi->GroupNode.ln_Name=gi->GroupID;
						AddTail((struct List *)&GroupList,(struct Node *)gi);
					}
				}
			}
		} else error=-1;
	}
	
	if(!error && errno) error=errno;
		
	if(UserFile) fclose(UserFile);
	if(GroupFile) fclose(GroupFile);
	
	if(!error) return NULL;
	switch(error) {
		case -1:	return "Out of memory.";
		case -2:	return "Error in Password file.";
		case -3:	return "Error in first part of groupfile";
		case -4:	return "Error in second part of groupfile";
		default:	return strerror(error);
	}
}

char *SaveLists(char *PassName,char *GroupName)
{
	FILE *uf=NULL,*gf=NULL;
	struct UserInfo *ui;
	struct GroupInfo *gi;
	struct ExtGroupInfo *egi;
	static char npass[256],ngroup[256];
	static char opass[256],ogroup[256];
	int error;
	
	error=0;
	
	strcpy(npass,PassName);strcat(npass,".new");
	strcpy(opass,PassName);strcat(opass,".old");
	strcpy(ngroup,GroupName);strcat(ngroup,".new");
	strcpy(ogroup,GroupName);strcat(ogroup,".old");
	
	unlink(opass);
	unlink(ogroup);
	if(!(uf=fopen(npass,"w"))) error=errno;
	else if(!(gf=fopen(ngroup,"w"))) error=errno;
	
	if(!error) for(ui=(struct UserInfo *)UserList.mlh_Head;!error && ui!=(struct UserInfo *)&UserList.mlh_Tail;ui=(struct UserInfo *)ui->UserNode.ln_Succ)
		if(fprintf(uf,"%s|%s|%d|%d|%s|%s|%s\n",
			ui->UserID,ui->Password,ui->uid,ui->gid,
			ui->UserName,ui->HomeDir,ui->Shell
		)<0) error=errno;
	if(!error) for(gi=(struct GroupInfo *)GroupList.mlh_Head;!error && gi!=(struct GroupInfo *)&GroupList.mlh_Tail;gi=(struct GroupInfo *)gi->GroupNode.ln_Succ)
		if(fprintf(gf,"%s|%d|%d|%s\n",
			gi->GroupID,gi->gid,gi->MgsUid,gi->GroupName
		)<0) error=errno;
	if(!error) if(fprintf(gf,"\n")<0) error=errno;
	if(!error) for(ui=(struct UserInfo *)UserList.mlh_Head;!error && ui!=(struct UserInfo *)&UserList.mlh_Tail;ui=(struct UserInfo *)ui->UserNode.ln_Succ)
	{
		int cnt;
		
		cnt=0;
		for(egi=(struct ExtGroupInfo *)ExtGroupList.mlh_Head;!error && egi!=(struct ExtGroupInfo *)&ExtGroupList.mlh_Tail;egi=(struct ExtGroupInfo *)egi->ExtGroupNode.mln_Succ)
		{
			if(egi->uid==ui->uid)
			{
				if(cnt++) { if(fprintf(gf,",")<0) error=errno; }
				else { if(fprintf(gf,"%d:",ui->uid)<0) error=errno; }
				if(!error) if(fprintf(gf,"%d",egi->gid)<0) error=errno;
			}
		}
		if(!error && cnt) if(fprintf(gf,"\n")<0) error=errno;
	}

	if(uf) fclose(uf);
	if(gf) fclose(gf);
	
	if(!error) if(rename(PassName,opass)) error=errno;
	else if(rename(npass,PassName)) error=errno;
	else if(rename(GroupName,ogroup)) error=errno;
	else if(rename(ngroup,GroupName)) error=errno;
	
	if(!error) return NULL;
	return strerror(error);
}

void ToUserInfo(struct UserInfo *ui)
{
	char *tmpptr;
	
	GetString(NameStr,ui->UserName,tmpptr);
	GetString(HomeStr,ui->HomeDir,tmpptr);
	GetString(PortStr,ui->Shell,tmpptr);
}

void ToGroupInfo(struct GroupInfo *gi)
{
	char *tmpptr;
	
	GetString(GroupNameStr,gi->GroupName,tmpptr);
}

void ShowUserIds(void)
{
	struct UserInfo *ui;
	char *p;
	
	DoMethod(UserIDList,MUIM_List_Clear);
	set(UserIDList,MUIA_List_Quiet,TRUE);
	for(ui=(struct UserInfo *)UserList.mlh_Head;ui!=(struct UserInfo *)&UserList.mlh_Tail;ui=(struct UserInfo *)ui->UserNode.ln_Succ)
	{
		p=ui->UserID;
		DoMethod(UserIDList,MUIM_List_Insert,&p,1,MUIV_List_Insert_Sorted);
	}
	set(UserIDList,MUIA_List_Quiet,FALSE);
}

char *GetGroupName(UWORD gid)
{
	struct GroupInfo *gi;
	
	if(gi=GetGroupInfo(gid)) return gi->GroupID;
	return NULL;
}

void AddGroupUser(UWORD uid,UWORD gid)
{
	struct ExtGroupInfo *egi;
	struct UserInfo *ui;
	
	if(!(ui=GetUserInfo(uid)))
	{
		MUI_Request(App,MainWin,0,"Add Group To User","Hmmm",
			"User does not exist."
		);
		return;
	}
	if(!GetGroupInfo(gid))
	{
		MUI_Request(App,MainWin,0,"Add Group To User","Hmmm",
			"Group does not exist."
		);
		return;
	}
	if(ui->gid==gid)
	{
		MUI_Request(App,MainWin,0,"Add Group To User","Hmmm",
			"Group already exists."
		);
		return;
	}
	for(egi=(struct ExtGroupInfo *)ExtGroupList.mlh_Head;egi!=(struct ExtGroupInfo *)&ExtGroupList.mlh_Tail;egi=(struct ExtGroupInfo *)egi->ExtGroupNode.mln_Succ)
	{
		if(egi->uid==uid && egi->gid==gid)
		{
			MUI_Request(App,MainWin,0,"Add Group To User","Hmmm",
				"Group already exists."
			);
			return;
		}
	}
	if(egi=malloc(sizeof(struct ExtGroupInfo)))
	{
		egi->uid=uid;
		egi->gid=gid;
		AddTail((struct List *)&ExtGroupList,(struct Node *)egi);
	}
	else 	MUI_Request(App,MainWin,0,"Add Group To User","Hmmm",
		"Not enough memory."
	);
}

void DelGroupUser(UWORD uid,UWORD gid)
{
	struct ExtGroupInfo *egi;
	struct UserInfo *ui;
	
	if(!(ui=GetUserInfo(uid)))
	{
		MUI_Request(App,MainWin,0,"Add Group To User","Hmmm",
			"User does not exist."
		);
		return;
	}
	if(!GetGroupInfo(gid))
	{
		MUI_Request(App,MainWin,0,"Add Group To User","Hmmm",
			"Group does not exist."
		);
		return;
	}
	for(egi=(struct ExtGroupInfo *)ExtGroupList.mlh_Head;egi!=(struct ExtGroupInfo *)&ExtGroupList.mlh_Tail;egi=(struct ExtGroupInfo *)egi->ExtGroupNode.mln_Succ)
	{
		if(egi->uid==uid && egi->gid==gid)
		{
			Remove((struct Node *)egi);
			free(egi);
			return;
		}
	}
	MUI_Request(App,MainWin,0,"Add Group To User","Hmmm",
		"Group does not exist."
	);
}

void ShowGroups(UWORD uid)
{
	struct UserInfo *ui;
	struct ExtGroupInfo *egi;
	char *p;
	
	if(ui=GetUserInfo(uid))
	{
		p=GetGroupName(ui->gid);
		set(GroupIDList,MUIA_List_Quiet,TRUE);
		DoMethod(GroupIDList,MUIM_List_Clear);
		DoMethod(GroupIDList,MUIM_List_Insert,&p,1,MUIV_List_Insert_Bottom);
		for(egi=(struct ExtGroupInfo *)ExtGroupList.mlh_Head;egi!=(struct ExtGroupInfo *)&ExtGroupList.mlh_Tail;egi=(struct ExtGroupInfo *)egi->ExtGroupNode.mln_Succ)
		{
			if(ui->uid==egi->uid)
			{
				p=GetGroupName(egi->gid);
				DoMethod(GroupIDList,MUIM_List_Insert,&p,1,MUIV_List_Insert_Bottom);
			}
		}
		set(GroupIDList,MUIA_List_Quiet,FALSE);
	}
}

void SetUserInfo(void)
{
	char *userid;
	struct UserInfo *ui;
	static LONG ls=-1;
	LONG ca;
	
	get(UserIDList,MUIA_List_Active,&ca);
	if(ca==ls) return; else ls=ca;
		
	if(CurUserInfo) ToUserInfo(CurUserInfo);
	
	DoMethod(UserIDList,MUIM_List_GetEntry,MUIV_List_GetEntry_Active,&userid);
	ui=(struct UserInfo *)FindName((struct List *)&UserList,userid);
	if(ui)
	{
		char buf[20];
		
		CurUserInfo=ui;
		sprintf(buf,"%d",ui->uid);
		set(uidTxt,MUIA_Text_Contents,buf);
		set(NameStr,MUIA_String_Contents,ui->UserName);
		set(HomeStr,MUIA_String_Contents,ui->HomeDir);
		set(PortStr,MUIA_String_Contents,ui->Shell);
		set(PasswdChk,MUIA_Selected,*ui->Password!='\0');
		ShowGroups(ui->uid);
	} else
	{
		set(uidTxt,MUIA_Text_Contents,"");
		set(NameStr,MUIA_String_Contents,"");
		set(HomeStr,MUIA_String_Contents,"");
		set(PortStr,MUIA_String_Contents,"");
		set(PasswdChk,MUIA_Selected,FALSE);
		DoMethod(GroupIDList,MUIM_List_Clear);
		CurUserInfo=NULL;
	}
}

LONG GetGid(void)
{
	BOOL running=TRUE;
	struct GroupInfo *gi;
	APTR p;
	LONG pos,ret=-1;
	
	set(App,MUIA_Application_Sleep,TRUE);
	
	DoMethod(GidList,MUIM_List_Clear);
	set(GidList,MUIA_List_Quiet,TRUE);
	for(gi=(struct GroupInfo *)GroupList.mlh_Head;gi!=(struct GroupInfo *)&GroupList.mlh_Tail;gi=(struct GroupInfo *)gi->GroupNode.ln_Succ)
	{
		p=gi;
		DoMethod(GidList,MUIM_List_Insert,&p,1,MUIV_List_Insert_Bottom);
	}
	set(GidList,MUIA_List_Quiet,FALSE);
	
	set(GetGidWin,MUIA_Window_Open,TRUE);
	
	while(running)
	{
		ULONG sigs;
		
		switch(DoMethod(App,MUIM_Application_Input,&sigs))
		{
			case MUIV_Application_ReturnID_Quit:
				running=FALSE;
				DoMethod(App,MUIM_Application_ReturnID,MUIV_Application_ReturnID_Quit);
				break;
			case GidClose_ID:
				running=FALSE;
				break;
			case GidDblClk_ID:
				get(GidList,MUIA_List_Active,&pos);
				if(pos!=MUIV_List_Active_Off)
				{
					gi=(struct GroupInfo *)GroupList.mlh_Head;
					while(pos--) gi=(struct GroupInfo *)gi->GroupNode.ln_Succ;
					ret=gi->gid;
				}
				running=FALSE;
				break;
		}
		if (running && sigs) Wait(sigs);
	}
	
	set(GetGidWin,MUIA_Window_Open,FALSE);
	set(App,MUIA_Application_Sleep,FALSE);
	
	return ret;
}

void SelectUid(int uid)
{
}

void DoAddUser(void)
{
	BOOL running=TRUE;
	int uid,tuid;
	struct UserInfo *ui;
	char UserID[muUSERIDSIZE];
	char *tmpptr;
	
	set(App,MUIA_Application_Sleep,TRUE);
	set(AddUserWin,MUIA_Window_Open,TRUE);
	set(UserIDStr,MUIA_String_Contents,"");
	uid=1;tuid=-1;
	while(uid!=tuid)
	{
		tuid=uid;
		for(ui=(struct UserInfo *)UserList.mlh_Head;ui!=(struct UserInfo *)&UserList.mlh_Tail;ui=(struct UserInfo *)ui->UserNode.ln_Succ)
			if(ui->uid==uid) uid++;
	}
	set(uidStr,MUIA_String_Integer,uid);
	set(AddUserWin,MUIA_Window_ActiveObject,UserIDStr);
	
	while(running)
	{
		ULONG sigs;
		
		switch(DoMethod(App,MUIM_Application_Input,&sigs))
		{
			case MUIV_Application_ReturnID_Quit:
				running=FALSE;
				DoMethod(App,MUIM_Application_ReturnID,MUIV_Application_ReturnID_Quit);
				break;
			case CancelAddUser_ID:
				running=FALSE;
				break;
			case AddUserOk_ID:
				running=FALSE;
				GetString(UserIDStr,UserID,tmpptr);
				get(uidStr,MUIA_String_Integer,&uid);
				if(uid<1 || uid>65535) running=TRUE;
				if(!(*UserID)) running=TRUE;
				if(!running) for(ui=(struct UserInfo *)UserList.mlh_Head;ui!=(struct UserInfo *)&UserList.mlh_Tail;ui=(struct UserInfo *)ui->UserNode.ln_Succ)
				{
					if(ui->uid==uid || !strcmp(ui->UserID,UserID))
					{
						running=TRUE;
						break;
					}
				}
				if(running)
				{
					MUI_Request(App,AddUserWin,0,"Add Group To User","Ok",
						"Unallowed UserID or uid."
					);
				}
				else
				{
					if(ui=malloc(sizeof(struct UserInfo)))
					{
						strcpy(ui->UserID,UserID);
						ui->uid=uid;
						ui->gid=65535;
						*ui->UserName='\0';
						*ui->Password='\0';
						strcpy(ui->HomeDir,"SYS:Homes");
						strcpy(ui->Shell,"cli");
						ui->UserNode.ln_Name=ui->UserID;
						AddTail((struct List *)&UserList,(struct Node *)ui);
					}		
					ShowUserIds();
					SelectUid(uid);
				}
				break;
		}
		if (running && sigs) Wait(sigs);
	}
	
	set(AddUserWin,MUIA_Window_Open,FALSE);
	set(App,MUIA_Application_Sleep,FALSE);
}

void DoAddGroup(void)
{
	LONG gid;
	
	if(!CurUserInfo) return;
	if((gid=GetGid())==-1) return;
	AddGroupUser(CurUserInfo->uid,gid);
	ShowGroups(CurUserInfo->uid);
}

void DoDelGroup(void)
{
	LONG pos;
	LONG gid;
	
	get(GroupIDList,MUIA_List_Active,&pos);
	if(pos!=MUIV_List_Active_Off)
	{
		if(pos==0)
		{
			if((gid=GetGid())!=-1)
			{
					CurUserInfo->gid=gid;
			}
		}
		else DelGroupUser(CurUserInfo->uid,CurGroupInfo->gid);
		ShowGroups(CurUserInfo->uid);
	}
}

void SetCurGid(void)
{
	LONG pos;
	struct ExtGroupInfo *egi;
	
	get(GroupIDList,MUIA_List_Active,&pos);
	if(pos==0) CurGroupInfo=GetGroupInfo(CurUserInfo->gid);
	else if(pos!=MUIV_List_Active_Off)
	{
		egi=(struct ExtGroupInfo *)ExtGroupList.mlh_Head;
		while(egi->uid!=CurUserInfo->uid)
			egi=(struct ExtGroupInfo *)egi->ExtGroupNode.mln_Succ;
		pos--;
		while(pos) 
		{
			if(egi->uid==CurUserInfo->uid) pos--;
			egi=(struct ExtGroupInfo *)egi->ExtGroupNode.mln_Succ;
		}
		CurGroupInfo=GetGroupInfo(egi->gid);
	} else CurGroupInfo=NULL;
}

void DoDeletePasswd(void)
{
	if(CurUserInfo)
	{
		if(MUI_Request(App,MainWin,0,"Delete Password","Yes|Nope",
			"Are you sure you want to delete the password?"
		))
		{
			CurUserInfo->Password[0]='\0';
			set(PasswdChk,MUIA_Selected,FALSE);
		}
	}
}

void DoSaveQuit(void)
{
	char *errmsg;
	
	if(CurUserInfo) ToUserInfo(CurUserInfo);
	if(CurGidInfo) ToGroupInfo(CurGidInfo);
	if(errmsg=SaveLists(PassFileName,GroupFileName))
	{
		MUI_Request(App,MainWin,0,"Save Files","Oops",
				"Error writing primary files.\n%s",errmsg
		);
		return;
	}
	
	if(SucPassFileName && SucGroupFileName)	
	{
		if(errmsg=SaveLists(SucPassFileName,SucGroupFileName))
		{
			MUI_Request(App,MainWin,0,"Save Files","Oops",
					"Error writing secondary files.\n%s",errmsg
			);
			return;
		}
	}
	
	DoMethod(App,MUIM_Application_ReturnID,MUIV_Application_ReturnID_Quit);
}

void DoDelUser(void)
{
	struct ExtGroupInfo *egi,*degi;
	struct GroupInfo *gi;
	
	if(CurUserInfo)
	{
		if(CurUserInfo->uid==65535)
		{
			MUI_Request(App,MainWin,0,"Delete User","Oops",
				"You are not allowed to delete the root user."
			);
			return;
		}
		for(gi=(struct GroupInfo *)GroupList.mlh_Head;gi!=(struct GroupInfo *)&GroupList.mlh_Tail;gi=(struct GroupInfo *)gi->GroupNode.ln_Succ)
		{
			if(CurUserInfo->uid==gi->MgsUid)
			{
				MUI_Request(App,MainWin,0,"Delete User","Oops",
					"This user is a group manager."
				);
				return;
			}
		}
		if(!MUI_Request(App,MainWin,0,"Delete User","Yes|No",
				"Are you sure you want to delete the user \"%s\"?",
				CurUserInfo->UserID
		)) return;
	
		// Delete the ExtGroupInfo
		degi=NULL;
		for(egi=(struct ExtGroupInfo *)ExtGroupList.mlh_Head;egi!=(struct ExtGroupInfo *)&ExtGroupList.mlh_Tail;egi=(struct ExtGroupInfo *)egi->ExtGroupNode.mln_Succ)
		{
			if(degi)
			{
				Remove((struct Node *)degi);
				free(degi);
				degi=NULL;
			}
			if(egi->uid==CurUserInfo->uid) degi=egi;
		}
		if(degi)
		{
			Remove((struct Node *)degi);
			free(degi);
			degi=NULL;
		}
		// Delete user info
		Remove((struct Node *)CurUserInfo);
		free(CurUserInfo);
		CurUserInfo=NULL;
		ShowUserIds();
	}
}

void ShowGroupIds(void)
{
	struct GroupInfo *gi;
	char *p;
	
	DoMethod(GidList2,MUIM_List_Clear);
	set(GidList2,MUIA_List_Quiet,TRUE);
	for(gi=(struct GroupInfo *)GroupList.mlh_Head;gi!=(struct GroupInfo *)&GroupList.mlh_Tail;gi=(struct GroupInfo *)gi->GroupNode.ln_Succ)
	{
		p=gi->GroupID;
		DoMethod(GidList2,MUIM_List_Insert,&p,1,MUIV_List_Insert_Sorted);
	}
	set(GidList2,MUIA_List_Quiet,FALSE);
}

void SetGroupInfo(void)
{
	char *groupid;
	struct GroupInfo *gi;
	static LONG ls=-1;
	LONG ca;
	
	get(GidList2,MUIA_List_Active,&ca);
	if(ca==ls) return; else ls=ca;
		
	if(CurGidInfo) ToGroupInfo(CurGidInfo);
	
	DoMethod(GidList2,MUIM_List_GetEntry,MUIV_List_GetEntry_Active,&groupid);
	gi=(struct GroupInfo *)FindName((struct List *)&GroupList,groupid);
	if(gi)
	{
		char buf[20];
		struct UserInfo *ui;
		
		sprintf(buf,"%d",gi->gid);set(GidTxt,MUIA_Text_Contents,buf);
		if(ui=GetUserInfo(gi->MgsUid)) set(AdminTxt,MUIA_Text_Contents,ui->UserID);
		else set(AdminTxt,MUIA_Text_Contents,"\33bError");
		set(GroupNameStr,MUIA_String_Contents,gi->GroupName);
		CurGidInfo=gi;
	} else
	{
		set(GidTxt,MUIA_Text_Contents,"");
		set(AdminTxt,MUIA_Text_Contents,"");
		set(GroupNameStr,MUIA_String_Contents,"");
		CurGidInfo=NULL;
	}
}

void DoAddGid(void)
{
	BOOL running=TRUE;
	int gid,tgid;
	struct GroupInfo *gi;
	char GroupID[muGROUPIDSIZE];
	char *tmpptr;
	
	set(App,MUIA_Application_Sleep,TRUE);
	set(AddGroupWin,MUIA_Window_Open,TRUE);
	set(GroupIDStr,MUIA_String_Contents,"");
	gid=0;tgid=-1;
	while(gid!=tgid)
	{
		tgid=gid;
		for(gi=(struct GroupInfo *)GroupList.mlh_Head;gi!=(struct GroupInfo *)&GroupList.mlh_Tail;gi=(struct GroupInfo *)gi->GroupNode.ln_Succ)
			if(gi->gid==gid) gid++;
	}
	set(gidStr,MUIA_String_Integer,gid);
	set(AddGroupWin,MUIA_Window_ActiveObject,GroupIDStr);
	
	while(running)
	{
		ULONG sigs;
		
		switch(DoMethod(App,MUIM_Application_Input,&sigs))
		{
			case MUIV_Application_ReturnID_Quit:
				running=FALSE;
				DoMethod(App,MUIM_Application_ReturnID,MUIV_Application_ReturnID_Quit);
				break;
			case AddGidCancel_ID:
				running=FALSE;
				break;
			case AddGidOk_ID:
				running=FALSE;
				GetString(GroupIDStr,GroupID,tmpptr);
				get(gidStr,MUIA_String_Integer,&gid);
				if(gid<0 || gid>65535) running=TRUE;
				if(!(*GroupID)) running=TRUE;
				if(!running) for(gi=(struct GroupInfo *)GroupList.mlh_Head;gi!=(struct GroupInfo *)&GroupList.mlh_Tail;gi=(struct GroupInfo *)gi->GroupNode.ln_Succ)
				{
					if(gi->gid==gid || !strcmp(gi->GroupID,GroupID))
					{
						running=TRUE;
						break;
					}
				}
				if(running)
				{
					MUI_Request(App,AddGroupWin,0,"Add Group","Ok",
						"Unallowed GroupID or gid."
					);
				}
				else
				{
					if(gi=malloc(sizeof(struct GroupInfo)))
					{
						strcpy(gi->GroupID,GroupID);
						gi->gid=gid;
						gi->MgsUid=65535;
						*gi->GroupName='\0';
						gi->GroupNode.ln_Name=gi->GroupID;
						AddTail((struct List *)&GroupList,(struct Node *)gi);
					}		
					ShowGroupIds();
				}
				break;
		}
		if (running && sigs) Wait(sigs);
	}
	
	set(AddGroupWin,MUIA_Window_Open,FALSE);
	set(App,MUIA_Application_Sleep,FALSE);
}

void DoGetAdmin(void)
{
	if(!CurGidInfo) return;
	if(!CurUserInfo)
	{
		MUI_Request(App,GroupWin,0,"Edit Groups","Ok",
						"Please select a user in the user window."
		);
		return;
	}
	CurGidInfo->MgsUid=CurUserInfo->uid;
	set(AdminTxt,MUIA_Text_Contents,CurUserInfo->UserID);
}

void DoDelGid(void)
{
	struct ExtGroupInfo *egi;
	struct UserInfo *ui;
	
	if(!CurGidInfo) return;
	
	if(CurUserInfo->uid==65535)
	{
		MUI_Request(App,GroupWin,0,"Delete Group","Oops",
			"You are not allowed to delete the root group."
		);
		return;
	}
	for(ui=(struct UserInfo *)UserList.mlh_Head;ui!=(struct UserInfo *)&UserList.mlh_Tail;ui=(struct UserInfo *)ui->UserNode.ln_Succ)
	{
		if(CurGidInfo->gid==ui->gid)
		{
			MUI_Request(App,GroupWin,0,"Delete Group","Oops",
				"This group is still used as primary group."
			);
			return;
		}
	}
	for(egi=(struct ExtGroupInfo *)ExtGroupList.mlh_Head;egi!=(struct ExtGroupInfo *)&ExtGroupList.mlh_Tail;egi=(struct ExtGroupInfo *)egi->ExtGroupNode.mln_Succ)
	{
		if(CurGidInfo->gid==egi->gid)
		{
			MUI_Request(App,GroupWin,0,"Delete Group","Oops",
				"This group is still used as secondary group."
			);
			return;
		}
	}
	if(!MUI_Request(App,GroupWin,0,"Delete Group","Yes|No",
			"Are you sure you want to delete the group \"%s\"?",
			CurGidInfo->GroupID
	)) return;

	// Delete group info
	Remove((struct Node *)CurGidInfo);
	free(CurGidInfo);
	CurGidInfo=NULL;
	ShowGroupIds();
}

int GetIconInfo(void)
{
	char *tt;
	
	if(!(DiskObj=GetDiskObject(WBenchMsg->sm_ArgList->wa_Name))) return FALSE;
	if(tt=FindToolType(DiskObj->do_ToolTypes,"PRIMPASSFILE")) PassFileName=tt;
	if(tt=FindToolType(DiskObj->do_ToolTypes,"PRIMGROUPFILE")) GroupFileName=tt;
	if(tt=FindToolType(DiskObj->do_ToolTypes,"SUCCPASSFILE")) SucPassFileName=tt;
	if(tt=FindToolType(DiskObj->do_ToolTypes,"SUCCGROUPFILE")) SucGroupFileName=tt;
	return TRUE;
}


void main(int argc)
{
	BOOL running=TRUE;
	APTR dummy;
	char *errmsg;
	
	kputs("Test");
	
	if(!(MUIMasterBase=OpenLibrary(MUIMASTER_NAME,MUIMASTER_VMIN))) exit(0);
	if(argc!=0)
	{
		fprintf(stderr,"Aaaaah... u are u-sing the CLI.\n");
		exit(0);
	}
		
	App = ApplicationObject,
		MUIA_Application_Title,		"EditUsers",
		MUIA_Application_Version,	"$VER: EditUsers 1.0 (11.9.93)",
		MUIA_Application_Copyright,"©1993 by Joran Jessurun",
		MUIA_Application_Author,	"Joran Jessurun",
		MUIA_Application_Base,		"EDITUSERS",
		MUIA_Application_Description,"Edit the multiuser database",
		SubWindow, MainWin=WindowObject,
			MUIA_Window_Title,		"EditUsers V1.0",
			MUIA_Window_ID,			MAKE_ID('E','U','M','A'),
			WindowContents,
			VGroup, 
				Child, HGroup,
					Child, VGroup,
						GroupFrameT("userid's"),
						Child, UserIDListview=ListviewObject,
							MUIA_Listview_List,UserIDList=ListObject,
								ReadListFrame,
								MUIA_Listview_Input,TRUE,
							End,
						End,
						Child, HGroup,
							Child,AddUserBut=SimpleButton("Add"),
							Child,DelUserBut=SimpleButton("Delete"),
						End,
					End,
					Child, HSpace(2),
					Child, VGroup,
						Child, HGroup,
							GroupFrameT("userinfo"),
							Child, VGroup,
								Child, Label2("uid"),
								Child, Label2("name"),
								Child, Label2("home"),
								Child, Label2("port"),
							End,
							Child, VGroup,
								Child, uidTxt=TextObject,
									ReadListFrame,
								End,
								Child, NameStr=String("",muUSERNAMESIZE),
								Child, Popup(HomeStr,String("",muHOMEDIRSIZE),&PopupHomeHook,MUII_PopDrawer),
								Child, PortStr=String("",mySHELLSIZE),
							End,
						End,
						Child, VGroup,
							GroupFrameT("Password"),
							Child, HGroup,
								Child, ChangePasswdBut=TextObject, ButtonFrame, 
									MUIA_Text_Contents, "Delete",
									MUIA_Text_PreParse, "\33c",
									MUIA_InputMode    , MUIV_InputMode_RelVerify,
									MUIA_Background   , MUII_ButtonBack,
									MUIA_Disabled,TRUE,
								End,
								Child, HSpace(0),
								Child, Label("Password Set"),
								Child, PasswdChk=ImageObject,
									ReadListFrame,
									MUIA_Image_Spec,MUII_CheckMark,
									MUIA_Image_FreeVert,TRUE,
									MUIA_Selected,FALSE,
									MUIA_Background,MUII_ButtonBack,
									MUIA_ShowSelState,FALSE,
								End,
							End,
						End,
						Child, VGroup,
							GroupFrameT("Group"),
							Child, GroupIDListview=ListviewObject,
								MUIA_Listview_List,GroupIDList=ListObject,
									ReadListFrame,
								End,
							End,
							Child, HGroup,
								Child, AddGroupBut=SimpleButton("Add"),
								Child, DelGroupBut=SimpleButton("Delete"),
								Child, EditGroupBut=SimpleButton("Edit"),
							End,
						End,
					End,
				End,
				Child, HGroup,
					Child, MainSave=SimpleButton("Save"),
					Child, HSpace(200),
					Child, MainCancel=SimpleButton("Cancel"),
				End,
			End,
		End,
		SubWindow, GetGidWin=WindowObject,
			MUIA_Window_Title,		"Select Group",
			MUIA_Window_ID,			MAKE_ID('E','U','G','G'),
			WindowContents,
			HGroup,
				GroupFrameT("groups"),
				Child, GidListview=ListviewObject,
					MUIA_Listview_List, GidList=ListObject,
						ReadListFrame,
						MUIA_List_Format,",",
						MUIA_List_DisplayHook,&GidMultiHook,
					End,
				End,
			End,
		End,
		SubWindow, GroupWin=WindowObject,
			MUIA_Window_Title,		"Edit Groups",
			MUIA_Window_ID,			MAKE_ID('E','U','G','W'),
			WindowContents,
			HGroup,
				Child, HGroup,
					MUIA_Weight,100,
					GroupFrameT("groups"),
					Child, GidListview2=ListviewObject,
						MUIA_Listview_List, GidList2=ListObject,
							ReadListFrame,
						End,
					End,
				End,
				Child, VGroup,
					MUIA_Weight,200,
					Child, HGroup,
						GroupFrameT("group info"),
						Child, VGroup,
							Child, Label1("gid"),
							Child, Label1("Manager"),
							Child, Label2("GroupName"),
						End,
						Child, VGroup,
							Child, GidTxt=TextObject,
								ReadListFrame,
							End,
							Child, HGroup,
								Child, AdminTxt=TextObject,
									ReadListFrame,
									MUIA_Weight,300,
								End,
								Child, AdminBut=TextObject,
									ButtonFrame,
									MUIA_Text_Contents,"Get",
									MUIA_InputMode,MUIV_InputMode_RelVerify,
									MUIA_Background,MUII_ButtonBack,
									MUIA_Weight,0,
								End,
							End,
							Child, GroupNameStr=String("",20),
						End,
					End,
					Child, VSpace(0),
					Child, HGroup,
						Child, AddGidBut=SimpleButton("Add"),
						Child, DelGidBut=SimpleButton("Delete"),
						Child, DoneGidBut=SimpleButton("Done"),
					End,
				End,
			End,
		End,
		SubWindow, AddUserWin=WindowObject,
			MUIA_Window_Title,		"Add User ID",
			MUIA_Window_ID,			MAKE_ID('E','U','A','U'),
			WindowContents,
			VGroup,
				Child, HGroup,
					Child, VGroup,
						Child, Label2("UserID"),
						Child, Label2("uid"),
					End,
					Child, VGroup,
						Child, UserIDStr=StringObject,
							StringFrame,
							MUIA_String_MaxLen,muUSERIDSIZE,
							MUIA_String_Accept,"abcdefghijklmnopqrstuvwxyz"
													 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
													 "1234567890",
						End,
						Child, uidStr=StringObject,
							StringFrame,
							MUIA_String_MaxLen,6,
							MUIA_String_Integer,0,
						End,
					End,
				End,
				Child, HGroup,
					Child, AddUserOkBut=SimpleButton("Ok"),
					Child, HSpace(100),
					Child, AddUserCancelBut=SimpleButton("Cancel"),
				End,
			End,
		End,
		SubWindow, AddGroupWin=WindowObject,
			MUIA_Window_Title,		"Add Group ID",
			MUIA_Window_ID,			MAKE_ID('E','U','A','H'),
			WindowContents,
			VGroup,
				Child, HGroup,
					Child, VGroup,
						Child, Label2("GroupID"),
						Child, Label2("gid"),
					End,
					Child, VGroup,
						Child, GroupIDStr=StringObject,
							StringFrame,
							MUIA_String_MaxLen,muGROUPIDSIZE,
							MUIA_String_Accept,"abcdefghijklmnopqrstuvwxyz"
													 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
													 "1234567890",
						End,
						Child, gidStr=StringObject,
							StringFrame,
							MUIA_String_MaxLen,6,
							MUIA_String_Integer,0,
						End,
					End,
				End,
				Child, HGroup,
					Child, AddGroupOkBut=SimpleButton("Ok"),
					Child, HSpace(100),
					Child, AddGroupCancelBut=SimpleButton("Cancel"),
				End,
			End,
		End,
	End;

	if(!App)
	{
		MUI_Request(NULL,NULL,0,"AdresBase V3.0 MUI","Hmmm",
			"Error initialising program."
		);
		exit(0);
	}
	
	// Install notify's to main program
	DoMethod(MainWin,MUIM_Notify,MUIA_Window_CloseRequest,TRUE,
		App,2,MUIM_Application_ReturnID,MUIV_Application_ReturnID_Quit);
	DoMethod(UserIDList,MUIM_Notify,MUIA_List_Active,MUIV_EveryTime,
		App,2,MUIM_Application_ReturnID,UserID_ID);
	DoMethod(GroupIDList,MUIM_Notify,MUIA_List_Active,MUIV_EveryTime,
		App,2,MUIM_Application_ReturnID,GroupID_ID);
	DoMethod(ChangePasswdBut,MUIM_Notify,MUIA_Pressed,FALSE,
		App,2,MUIM_Application_ReturnID,ChangeBut_ID);
	DoMethod(AddGroupBut,MUIM_Notify,MUIA_Pressed,FALSE,
		App,2,MUIM_Application_ReturnID,AddGroup_ID);
	DoMethod(DelGroupBut,MUIM_Notify,MUIA_Pressed,FALSE,
		App,2,MUIM_Application_ReturnID,DelGroup_ID);
	DoMethod(GetGidWin,MUIM_Notify,MUIA_Window_CloseRequest,TRUE,
		App,2,MUIM_Application_ReturnID,GidClose_ID);
	DoMethod(GidListview,MUIM_Notify,MUIA_Listview_DoubleClick,TRUE,
		App,2,MUIM_Application_ReturnID,GidDblClk_ID);
	DoMethod(PasswdChk,MUIM_Notify,MUIA_Selected,TRUE,
		ChangePasswdBut,3,MUIM_Set,MUIA_Disabled,FALSE);
	DoMethod(PasswdChk,MUIM_Notify,MUIA_Selected,FALSE,
		ChangePasswdBut,3,MUIM_Set,MUIA_Disabled,TRUE);
	SetButtonID(App,MainSave,MainSave_ID);
	SetButtonID(App,MainCancel,MUIV_Application_ReturnID_Quit);
	SetButtonID(App,AddUserBut,AddUser_ID);
	DoMethod(AddUserWin,MUIM_Notify,MUIA_Window_CloseRequest,TRUE,
		App,2,MUIM_Application_ReturnID,CancelAddUser_ID);
	SetButtonID(App,AddUserOkBut,AddUserOk_ID);
	SetButtonID(App,AddUserCancelBut,CancelAddUser_ID);
	DoMethod(UserIDStr,MUIM_Notify,MUIA_String_Acknowledge,MUIV_EveryTime,
		App,2,MUIM_Application_ReturnID,AddUserOk_ID);
	SetButtonID(App,DelUserBut,DelUser_ID);
	DoMethod(EditGroupBut,MUIM_Notify,MUIA_Pressed,FALSE,
		GroupWin,3,MUIM_Set,MUIA_Window_Open,TRUE);
	DoMethod(GroupWin,MUIM_Notify,MUIA_Window_CloseRequest,TRUE,
		GroupWin,3,MUIM_Set,MUIA_Window_Open,FALSE);
	DoMethod(GidList2,MUIM_Notify,MUIA_List_Active,MUIV_EveryTime,
		App,2,MUIM_Application_ReturnID,GroupID2_ID);
	SetButtonID(App,AddGidBut,AddGid_ID);
	SetButtonID(App,AddGroupCancelBut,AddGidCancel_ID);
	SetButtonID(App,AddGroupOkBut,AddGidOk_ID);
	DoMethod(AddGroupWin,MUIM_Notify,MUIA_Window_CloseRequest,TRUE,
		App,2,MUIM_Application_ReturnID,AddGidCancel_ID);
	DoMethod(GroupIDStr,MUIM_Notify,MUIA_String_Acknowledge,MUIV_EveryTime,
		App,2,MUIM_Application_ReturnID,AddGidOk_ID);
	SetButtonID(App,AdminBut,Admin_ID);
	DoMethod(DoneGidBut,MUIM_Notify,MUIA_Pressed,FALSE,
		GroupWin,3,MUIM_Set,MUIA_Window_Open,FALSE);
	SetButtonID(App,DelGidBut,DelGid_ID);
	DoMethod(MainWin,MUIM_Window_SetCycleChain,
		UserIDListview,AddUserBut,DelUserBut,
		NameStr,HomeStr,PortStr,
		ChangePasswdBut,
		GroupIDListview,
		AddGroupBut,DelGroupBut,EditGroupBut,
		MainSave,MainCancel,
		NULL
	);
	DoMethod(AddUserWin,MUIM_Window_SetCycleChain,
		UserIDStr,uidStr,
		AddUserOkBut,AddUserCancelBut,
		NULL
	);
	DoMethod(GetGidWin,MUIM_Window_SetCycleChain,
		GidListview,
		NULL
	);
	DoMethod(GroupWin,MUIM_Window_SetCycleChain,
		GidListview2,
		AdminBut,GroupNameStr,
		AddGidBut,DelGidBut,DoneGidBut,
		NULL
	);
	DoMethod(AddGroupWin,MUIM_Window_SetCycleChain,
		GroupIDStr,gidStr,
		AddGroupOkBut,AddGroupCancelBut,
		NULL
	);

	// Openen main window
	set(MainWin,MUIA_Window_Open,TRUE);
	
	if(!GetIconInfo())
	{
		MUI_Request(App,MainWin,0,"Edit Users","Hmmm",
			"Error getting diskobject."
		);
		running=FALSE;
	}
	else if(errmsg=InitLists())
	{
		MUI_Request(App,MainWin,0,"Edit Users","Hmmm",
			errmsg
		);
		running=FALSE;
	}
	else if(!(HomeFileRequest=(struct FileRequester *)MUI_AllocAslRequestTags(
		ASL_FileRequest,
		ASLFR_SleepWindow,TRUE,
		ASLFR_TitleText,"Select home directory",
		ASLFR_DoSaveMode,TRUE,
		ASLFR_DrawersOnly,TRUE,
		ASLFR_RejectIcons,TRUE,
		TAG_DONE
	)))
	{
		MUI_Request(App,MainWin,0,"Edit Users","Wuk",
			"Error allocating FileRequester."
		);
		running=FALSE;
	}
	else
	{
		ShowUserIds();
		ShowGroupIds();
	}

	while (running)
	{
	   ULONG signals;

	   switch (DoMethod(App,MUIM_Application_Input,&signals))
	   {
			case MUIV_Application_ReturnID_Quit:
				running = FALSE;
				break;
			case UserID_ID:		SetUserInfo();			break;	
			case AddGroup_ID:		DoAddGroup();			break;
			case GroupID_ID:		SetCurGid();			break;
			case DelGroup_ID:		DoDelGroup();			break;
			case ChangeBut_ID:	DoDeletePasswd();		break;
			case MainSave_ID:		DoSaveQuit();			break;
			case AddUser_ID:		DoAddUser();			break;
			case DelUser_ID:		DoDelUser();			break;
			case GroupID2_ID:		SetGroupInfo();		break;
			case AddGid_ID:		DoAddGid();				break;
			case Admin_ID:			DoGetAdmin();			break;
			case DelGid_ID:		DoDelGid();				break;
	   }

	   if (running && signals) Wait(signals);
	}
	
	if(HomeFileRequest) MUI_FreeAslRequest(HomeFileRequest);
	if(App) DisposeObject(App);
	if(MUIMasterBase) CloseLibrary(MUIMasterBase);
}
