/************************************************************
* MultiUser - MultiUser Task/File Support System				*
* ---------------------------------------------------------	*
* Get Information about one or more Users							*
* ---------------------------------------------------------	*
* © Copyright 1993-1994 Geert Uytterhoeven						*
* All Rights Reserved.													*
************************************************************/


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

#include "UserInfo_rev.h"

#include "Locale.h"

char __VersTag__[] = VERSTAG;


static void __regargs DumpUserInfo(struct muUserInfo *uinfo,
											  struct muGroupInfo *ginfo, BOOL quick,
											  BOOL groups, struct muBase *muBase,
											  struct DosLibrary *DOSBase,
											  struct ExecBase *SysBase,
                                   struct LocaleInfo *li);

int __saveds Start(char *arg)
{
	struct ExecBase *SysBase;
	struct DosLibrary *DOSBase;
	struct muBase *muBase = NULL;
	struct RDArgs *args;
	LONG argarray[] = {
#define argUSERID		0
#define argUID			1
#define argGID			2
#define argNAME		3
#define argGROUPID	4
#define argGROUPNAME	5
#define argALL			6
#define argQUICK		7
#define argGROUPS		8
		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
	};
	struct muUserInfo *uinfo;
	struct muGroupInfo *ginfo;
	UWORD gid;
	LONG error = NULL;
	int rc = RETURN_OK;
	struct LocaleInfo li;

	SysBase = *(struct ExecBase **)4;

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

	OpenLoc(&li);

	args = ReadArgs("USERID,UID/K/N,GID/K/N,NAME/K,GROUPID/K,GROUPNAME/K,"
						 "ALL/S,Q=QUICK/S,GROUPS/S", argarray, NULL);
	if (!args)
		error = IoErr();
	else
		if (uinfo = muAllocUserInfo()) {
			if (ginfo = muAllocGroupInfo()) {
				if (!argarray[argALL] && !argarray[argUSERID] && 
					 !argarray[argUID] && !argarray[argGID] && !argarray[argNAME] &&
					 !argarray[argGROUPID] && !argarray[argGROUPNAME]) {
					if (!argarray[argQUICK])
						PutStr(GetLocS(&li,MSG_UINFO_THIS));
					uinfo->uid = muGetTaskOwner(NULL)>>16;
					if (muGetUserInfo(uinfo, muKeyType_uid))
						DumpUserInfo(uinfo, ginfo, argarray[argQUICK],
										 argarray[argGROUPS], muBase, DOSBase, SysBase, &li);
					else
						PutStr(GetLocS(&li,MSG_NOINFO));
					goto Done;
				}

				if (argarray[argALL]) {
					if (!argarray[argQUICK])
						PutStr(GetLocS(&li,MSG_UINFO_ALL));
					if (muGetUserInfo(uinfo, muKeyType_First))
						do
							DumpUserInfo(uinfo, ginfo, argarray[argQUICK],
											 argarray[argGROUPS], muBase, DOSBase,
											 SysBase, &li);
						while (muGetUserInfo(uinfo, muKeyType_Next) &&
								 !CheckSignal(SIGBREAKF_CTRL_C));
					else
						PutStr(GetLocS(&li,MSG_NOINFO));
					goto Done;
				}

				if (argarray[argUSERID]) {
					if (!argarray[argQUICK])
						VPrintf(GetLocS(&li,MSG_UINFO_USERID),
								  &argarray[argUSERID]);
					strncpy(uinfo->UserID, (char *)argarray[argUSERID],
							  muUSERIDSIZE-1);
					uinfo->UserID[muUSERIDSIZE-1] = '\0';
					if (muGetUserInfo(uinfo, muKeyType_WUserID))
						do
							DumpUserInfo(uinfo, ginfo, argarray[argQUICK],
											 argarray[argGROUPS], muBase, DOSBase,
											 SysBase, &li);
						while (muGetUserInfo(uinfo, muKeyType_WUserIDNext) &&
								 !CheckSignal(SIGBREAKF_CTRL_C));
					else
						PutStr(GetLocS(&li,MSG_NOINFO));
					goto Done;
				}

				if (argarray[argUID]) {
					if (!argarray[argQUICK])
						VPrintf(GetLocS(&li,MSG_UINFO_UID),
								  (LONG *)argarray[argUID]);
					uinfo->uid = (UWORD)*(LONG *)argarray[argUID];
					if (muGetUserInfo(uinfo, muKeyType_uid))
						DumpUserInfo(uinfo, ginfo, argarray[argQUICK],
										 argarray[argGROUPS], muBase, DOSBase,
						             SysBase, &li);
					else
						PutStr(GetLocS(&li,MSG_NOINFO));
					goto Done;
				}

				if (argarray[argGID] || argarray[argGROUPID] ||
					 argarray[argGROUPNAME]) {
					if (argarray[argGID]) {
						if (!argarray[argQUICK])
							VPrintf(GetLocS(&li,MSG_GINFO_GID),
									  (LONG *)argarray[argGID]);
						gid = *(LONG *)argarray[argGID];
					} else if (argarray[argGROUPID]) {
						if (!argarray[argQUICK])
							VPrintf(GetLocS(&li,MSG_GINFO_GROUPID),
									  &argarray[argGROUPID]);
						strncpy(ginfo->GroupID, (char *)argarray[argGROUPID],
								  muGROUPIDSIZE-1);
						ginfo->GroupID[muGROUPIDSIZE-1] = '\0';
						if (muGetGroupInfo(ginfo, muKeyType_GroupID))
							gid = ginfo->gid;
						else {
							PutStr(GetLocS(&li,MSG_NOINFO));
							goto Done;
						}
					} else {
						if (!argarray[argQUICK])
							VPrintf(GetLocS(&li,MSG_GINFO_GROUPID),
									  &argarray[argGROUPNAME]);
						strncpy(ginfo->GroupName, (char *)argarray[argGROUPNAME],
								  muGROUPNAMESIZE-1);
						ginfo->GroupID[muGROUPNAMESIZE-1] = '\0';
						if (muGetGroupInfo(ginfo, muKeyType_GroupName))
							gid = ginfo->gid;
						else {
							PutStr(GetLocS(&li,MSG_NOINFO));
							goto Done;
						}
					}
					uinfo->gid = gid;
					if (muGetUserInfo(uinfo, muKeyType_gid))
						do
							DumpUserInfo(uinfo, ginfo, argarray[argQUICK],
											 argarray[argGROUPS], muBase, DOSBase,
											 SysBase, &li);
						while (muGetUserInfo(uinfo, muKeyType_gidNext) &&
								 !CheckSignal(SIGBREAKF_CTRL_C));
					else
						PutStr(GetLocS(&li,MSG_NOINFO));
					goto Done;
				}

				if (argarray[argNAME]) {
					if (!argarray[argQUICK])
						VPrintf(GetLocS(&li,MSG_UINFO_USERID),
								  &argarray[argNAME]);
					strncpy(uinfo->UserName, (char *)argarray[argNAME],
							  muUSERNAMESIZE-1);
					uinfo->UserName[muUSERNAMESIZE-1] = '\0';
					if (muGetUserInfo(uinfo, muKeyType_WUserName))
						do
							DumpUserInfo(uinfo, ginfo, argarray[argQUICK],
											 argarray[argGROUPS], muBase, DOSBase,
											 SysBase, &li);
						while (muGetUserInfo(uinfo, muKeyType_WUserNameNext) &&
								 !CheckSignal(SIGBREAKF_CTRL_C));
					else
						PutStr(GetLocS(&li,MSG_NOINFO));
					goto Done;
				}

Done:			muFreeGroupInfo(ginfo);
			} else
				error = IoErr();
			muFreeUserInfo(uinfo);
		} 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);
}


	/*
	 *		Dump User Information
	 */

static void __regargs DumpUserInfo(struct muUserInfo *uinfo,
											  struct muGroupInfo *ginfo, BOOL quick,
											  BOOL groups, struct muBase *muBase,
											  struct DosLibrary *DOSBase,
											  struct ExecBase *SysBase,
                                   struct LocaleInfo *li)
{
	LONG stream[6];
	BPTR dir, file;
	char buffer[256];
	BOOL neverloggedin = TRUE;
	int i;

	stream[0] = (LONG)uinfo->UserID;
	stream[1] = uinfo->uid;
	ginfo->gid = uinfo->gid;
	if (muGetGroupInfo(ginfo, muKeyType_gid))
		stream[2] = (LONG)ginfo->GroupID;
	else
		stream[2] = (LONG)"???";
	stream[3] = uinfo->gid;
	stream[4] = (LONG)uinfo->UserName;
	stream[5] = (LONG)uinfo->HomeDir;

	if (quick)
		VPrintf("%s\n", stream);
	else {
		VPrintf(GetLocS(li,MSG_UFORMAT_USER), stream);

		if (groups)
			if (uinfo->NumSecGroups) {
				ginfo->gid = uinfo->SecGroups[0];
				if (muGetGroupInfo(ginfo, muKeyType_gid))
					stream[0] = (LONG)ginfo->GroupID;
				else
					stream[0] = (LONG)"???";
				stream[1] = uinfo->SecGroups[0];
				VPrintf(GetLocS(li,MSG_UFORMAT_SECGROUPS), stream);
				for (i = 1; i < uinfo->NumSecGroups; i++) {
					ginfo->gid = uinfo->SecGroups[i];
					if (muGetGroupInfo(ginfo, muKeyType_gid))
						stream[0] = (LONG)ginfo->GroupID;
					else
						stream[0] = (LONG)"???";
					stream[1] = uinfo->SecGroups[i];
					VPrintf(GetLocS(li,MSG_UFORMAT_SECGROUPS2), stream);
				}
				PutStr("\n");
			} else
				PutStr(GetLocS(li,MSG_UFORMAT_NOSECGROUPS));

		if (dir = Lock(uinfo->HomeDir, SHARED_LOCK)) {
			dir = CurrentDir(dir);
			if (file = Open(muLastLogin_FileName, MODE_OLDFILE)) {
				if (FGets(file, buffer, 3*LEN_DATSTRING+2))
					neverloggedin = FALSE;
				Close(file);
			}
			if (neverloggedin)
				PutStr(GetLocS(li,MSG_NEVERLOGGED));
			else {
				stream[0] = (LONG)buffer;
				stream[1] = (LONG)"";
				stream[2] = (LONG)"";
				for (i = 0; buffer[i] && (buffer[i] != ' '); i++);
				if (buffer[i]) {
					buffer[i++] = '\0';
					while (buffer[i] == ' ')
						i++;
					stream[1] = (LONG)&buffer[i];
					while (buffer[i] && (buffer[i] != ' '))
						i++;
					if (buffer[i]) {
						buffer[i++] = '\0';
						while (buffer[i] == ' ')
							i++;
						stream[2] = (LONG)&buffer[i];
						while (buffer[i] && (buffer[i] != ' ') &&
								 (buffer[i] != '\n'))
							i++;
						buffer[i] = '\0';
					}
				}
				VPrintf(GetLocS(li,MSG_LASTLOGGED), stream);
			}
			if (file = Open(".plan", MODE_OLDFILE)) {
				PutStr(GetLocS(li,MSG_PLAN));
				while (!CheckSignal(SIGBREAKF_CTRL_C) &&
						 FGets(file, buffer, 255))			/* V39: use 256 */
					PutStr(buffer);
				Close(file);
			} else
				PutStr(GetLocS(li,MSG_NOPLAN));
			UnLock(CurrentDir(dir));
		} else
			PutStr(GetLocS(li,MSG_NOLOGACCESS));
	}
}
