/************************************************************
* MultiUser - MultiUser Task/File Support System				*
* ---------------------------------------------------------	*
* Set the owner of a file - AmigaOS 3.0 (V39+) version		*
* ---------------------------------------------------------	*
* © Copyright 1993-1994 Geert Uytterhoeven						*
* All Rights Reserved.													*
************************************************************/


#include <exec/types.h>
#include <exec/memory.h>
#include <dos/dos.h>
#include <dos/dosasl.h>
#include <proto/exec.h>
#include <proto/dos.h>
#include <string.h>
#include <libraries/multiuser.h>
#include <proto/multiuser.h>

#include "SetOwner_rev.h"

#include "Locale.h"

char __VersTag__[] = VERSTAG;


int __saveds Start(char *arg)
{
	struct ExecBase *SysBase;
	struct DosLibrary *DOSBase;
	struct muBase *muBase = NULL;
	struct RDArgs *args;
	LONG argarray[] = {
#define argFILE	0
#define argUSER	1
#define argGROUP	2
#define argNOBODY	3
#define argALL		4
#define argQUIET	5
		NULL, NULL, NULL, NULL, NULL, NULL
	};
	ULONG user = NULL;
	struct muUserInfo *uinfo;
	struct muGroupInfo *ginfo;
	struct AnchorPath *anchor;
	int rc = RETURN_OK;
	LONG error = NULL;
	BPTR dir;
	struct LocaleInfo li;

	SysBase = *(struct ExecBase **)4;
	
	if ((!(DOSBase = (struct DosLibrary *)OpenLibrary("dos.library", 39))) ||
		 (!(muBase = (struct muBase *)OpenLibrary("multiuser.library", 39)))) {
		rc = ERROR_INVALID_RESIDENT_LIBRARY;
		goto Exit;
	}

	OpenLoc(&li);

	args = ReadArgs("FILE/A,USER,GROUP,NOBODY/S,ALL/S,QUIET/S", argarray, NULL);
	if (!args)
		error = IoErr();
	else if (argarray[argUSER] && argarray[argNOBODY]) {
		PutStr(GetLocS(&li,MSG_INVALID_OPTIONS));
		rc = RETURN_ERROR;
	} else {
		if (argarray[argUSER]) {
			if (uinfo = muAllocUserInfo()) {
				strncpy(uinfo->UserID, (char *)argarray[argUSER], muUSERIDSIZE-1);
				uinfo->UserID[muUSERIDSIZE-1] = '\0';
				if (muGetUserInfo(uinfo, muKeyType_UserID))
					user = (uinfo->uid<<16)|uinfo->gid;
				muFreeUserInfo(uinfo);
			} else {
				PrintFault(IoErr(), NULL);
				goto Exit;
			}
			if (!user) {
				VPrintf(GetLocS(&li,MSG_UNKNOWN_USER), &argarray[argUSER]);
				rc = RETURN_ERROR;
			}
		} else if (!argarray[argNOBODY])
			user = muGetTaskOwner(NULL);
		if (argarray[argGROUP]) {
			if (ginfo = muAllocGroupInfo()) {
				strncpy(ginfo->GroupID, (char *)argarray[argGROUP],
						  muGROUPIDSIZE-1);
				ginfo->GroupID[muGROUPIDSIZE-1] = '\0';
				if (muGetGroupInfo(ginfo, muKeyType_GroupID))
					user = user & muMASK_UID | ginfo->gid;
				else {
					VPrintf(GetLocS(&li,MSG_UNKNOWN_GROUP), &argarray[argGROUP]);
					rc = RETURN_ERROR;
				}
				muFreeGroupInfo(ginfo);				
			} else {
				PrintFault(IoErr(), NULL);
				goto Exit;
			}
		}
		if (!rc)
			if (anchor = (struct AnchorPath *)AllocVec(sizeof(struct AnchorPath)+1024,
																	 MEMF_CLEAR)) {
				anchor->ap_BreakBits = SIGBREAKF_CTRL_C;
				anchor->ap_Flags = APF_DOWILD;
				anchor->ap_Strlen = 1024;
				if (!(error = MatchFirst((char *)argarray[argFILE], anchor))) {
					do
						if (anchor->ap_Flags & APF_DIDDIR)
							anchor->ap_Flags &= ~APF_DIDDIR;
						else {
							if (argarray[argALL] && (anchor->ap_Info.fib_DirEntryType > 0))
								anchor->ap_Flags |= APF_DODIR;
							dir = CurrentDir(DupLock(anchor->ap_Last->an_Lock));
							if (!SetOwner(anchor->ap_Info.fib_FileName, user)) {
								PutStr(anchor->ap_Buf);
								PrintFault(IoErr(), " ");
							} else if (!argarray[argQUIET]) {
								PutStr(anchor->ap_Buf);
								if (anchor->ap_Info.fib_DirEntryType > 0)
									PutStr("(Dir)");
								PutStr(GetLocS(&li,MSG_DONE));
							}
							UnLock(CurrentDir(dir));
						}
					while (!(error = MatchNext(anchor)));
					if (error == ERROR_NO_MORE_ENTRIES)
						error = NULL;
				} else if (error == ERROR_NO_MORE_ENTRIES)
					error = ERROR_OBJECT_NOT_FOUND;
				MatchEnd(anchor);
				FreeVec(anchor);
			} else
				error = IoErr();
	}
	FreeArgs(args);
	if (error) {
		PrintFault(error, NULL);
		rc = RETURN_ERROR;
	}

	CloseLoc(&li);

Exit:
	CloseLibrary((struct Library *)muBase);
	CloseLibrary((struct Library *)DOSBase);

	return(rc);
}
