/************************************************************
* MultiUser - MultiUser Task/File Support System				*
* ---------------------------------------------------------	*
* Set the owner of a file - Kickstart 2.04 (V37+) version	*
* ---------------------------------------------------------	*
* © Copyright 1993 by 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 "SetOwner37_rev.h"


char __VersTag__[] = VERSTAG;


BOOL MySetOwner(char *name, LONG owner, struct DosLibrary *DOSBase);


int __saveds Start(char *arg)
{
	struct ExecBase *SysBase;
	struct DosLibrary *DOSBase;
	struct muBase *muBase = NULL;
	struct RDArgs *args;
	LONG argarray[] = {
		NULL, NULL, NULL, NULL, NULL
	};
	ULONG User = NULL;
	struct muUserInfo *info;
	struct AnchorPath *anchor;
	int rc = RETURN_OK;
	LONG error = NULL;
	BPTR dir;

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

	args = ReadArgs("FILE/A,USER,NOBODY/S,ALL/S,QUIET/S", argarray, NULL);
	if (!args)
		error = IoErr();
	else if (argarray[1] && argarray[2]) {
		PutStr("Invalid options\n");
		rc = RETURN_ERROR;
	} else {
		if (argarray[1]) {
			if (info = muAllocUserInfo()) {
				strncpy(info->UserID, (char *)argarray[1], muUSERIDSIZE);
				if (muGetUserInfo(info, muKeyType_UserID)) {
					User = (info->uid<<16)|info->gid;
				}
				muFreeUserInfo(info);
			}
			if (!User) {
				VPrintf("Unknown User '%s'\n", &argarray[1]);
				rc = RETURN_ERROR;
			}
		} else if (!argarray[2])
			User = muGetTaskOwner(NULL);
		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[0], anchor))) {
					do
						if (anchor->ap_Flags & APF_DIDDIR)
							anchor->ap_Flags &= ~APF_DIDDIR;
						else {
							if (argarray[3] && (anchor->ap_Info.fib_DirEntryType > 0))
								anchor->ap_Flags |= APF_DODIR;
							dir = CurrentDir(DupLock(anchor->ap_Last->an_Lock));
							if (!MySetOwner(anchor->ap_Info.fib_FileName, User, DOSBase)) {
								PutStr(anchor->ap_Buf);
								PrintFault(IoErr(), " ");
							} else if (!argarray[4]) {
								PutStr(anchor->ap_Buf);
								if (anchor->ap_Info.fib_DirEntryType > 0)
									PutStr(" (dir)");
								PutStr("...Done\n");
							}
							UnLock(CurrentDir(dir));
						}
					while (!(error = MatchNext(anchor)));
				}
				if (error = ERROR_NO_MORE_ENTRIES)
					error = NULL;
				MatchEnd(anchor);
				FreeVec(anchor);
			} else
				error = IoErr();
		}
	}
	FreeArgs(args);
	if (error) {
		PrintFault(error, NULL);
		rc = RETURN_ERROR;
	}

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

	return(rc);
}


BOOL MySetOwner(char *name, LONG owner, struct DosLibrary *DOSBase)
{
	BOOL rc = FALSE;

	struct DevProc *dp;
	BPTR fl;

	if (dp = GetDeviceProc(name, NULL)) {
		if (fl = Lock(name, ACCESS_READ)) {
			rc = DoPkt(dp->dvp_Port, ACTION_SET_OWNER, NULL, fl, NULL, owner, NULL);
			UnLock(fl);
		}
		FreeDeviceProc(dp);
	}
	return(rc);
}
