/******************************************************************
* MultiUser - MultiUser Task/File Support System		  *
* --------------------------------------------------------------- *
* Get User ID data - AmigaShell script support utility		  *
*-----------------------------------------------------------------*
*								  *
* Usage:  UserID USERID/S,UID/S,GID/S,NAME/S,UACCESS/K/N,         *
*                GACCESS/K/N                                      *
*         USERID : Default. Returns userID of looged in user.     *
*         UID    : Returns User ID Number                         *
*         GID    : Returns Group ID Number (this will change :)   *
*         NAME   : Returns full user name                         *
*         UACCESS: Used for User security filter with scripts     *
*         GACCESS: Used for Group security filter with scripts    *
* Action: Returns data of the currently logged in user	          *
*	  (similar to UserInfo). However, this ONLY returns the   *
*         required data, so it can be used with SetEnv            *
*         (ie. SetEnv login `UserID` will make the environment    *
*         variable $login contain your userid           	  *
*	  NB: use *backward* single quotes - "`" not "'" )	  *
*	  or other AmigaDOS commands.				  *
*	  eg. Echo "hello `UserID`" > SPEAK:			  *
*	 							  *
*	  If no-one is logged in UserID returns "Nobody" and	  *
*	  sets an ERROR condition.				  *
*	  Eg: Failat 21						  *
*	 	  UserID <>NIL:					  *
*	      If ERROR						  *
*	 	  Echo "no-one home!"				  *
*	      Else                                                *
*                 UserInfo					  *
*	      EndIf						  *
* 								  *
*	  If the current user is in root's group ($FFFF), a WARN  *
*	  condition is set.					  *
*	  Eg: UserID <>NIL:					  *
*	      If WARN						  *
*	 	  Prompt "*e[32m%N.%S> *e[31m"			  *
*	      Else						  *
*		  Prompt "%N.%S> "				  *
*	      EndIf						  *
*								  *
*         The two special keywords UACCESS and GACCESS are used   *
*         to determine access priority in shell scripts.          *
*         UserID UACCESS k will set a WARN condition if the UID   *
*         of the current user is less than k.                     *
*         Note that WARN and usage with regard to root's group is *
*         disabled then.                                          *
*         Eg: Echo "Attempted access by " NOLINE                  *
*             UserID NAME UACCESS 5                               *
*             If WARN                                             *
*                 Echo "Access denied."                           *
*             EndIf                                               *
*                                                                 *
*         UserID GACCESS k will behave similarly, checking group  *
*         access instead of user access.                          *
*                                                                 * 
*-----------------------------------------------------------------*
*								  *
* © 1993 Fabian Nuñez  -  contact me at: fnunez@cs.uct.ac.za	  *
*								  *
******************************************************************/

#include <dos/dos.h>
#include <exec/types.h>
#include <proto/exec.h>
#include <proto/dos.h>
#include <proto/multiuser.h>
#include <libraries/multiuser.h>
#include "UserID_rev.h"

/* Prototypes */
void itoa(LONG,STRPTR);


char __VersTag__[] = VERSTAG;

void __main(char *arg)
{
        struct DosLibrary *DOSBase = NULL;
	struct muBase *muBase = NULL;
	struct muUserInfo *info = NULL;
	struct RDArgs *args;
        ULONG code;
	UBYTE *returned = NULL;
        LONG argarray[] = { NULL, NULL, NULL, NULL, NULL, NULL };
	UBYTE bitarray[] = {1,2,4,8};
        UBYTE bits;
        LONG i;
        	
	/* Open libraries */
        
        DOSBase = (struct DosLibrary *)OpenLibrary("dos.library",0L);
                        
	muBase = (struct muBase *)OpenLibrary("multiuser.library",39L);
	if (!muBase) Exit(122); /* invalid resident library */
	
        args = ReadArgs("USERID/S,UID/S,GID/S,NAME/S,UACCESS/K/N,GACCESS/K/N",argarray,NULL);
        if (!args)
        {
                PrintFault(IoErr(),NULL);
                code = 0; /* force error */
                goto EXIT;
        }

        for (i=0,bits=0;i<4;i++)
                if (argarray[i]) bits += bitarray[i];
                
	/* Get a muUserInfo struct */
	info = muAllocUserInfo();

	/* store info in 'returned' */
	if (code = muGetTaskOwner(NULL)) /* get uid of owner of this task */
	{
		info->uid = (UWORD) (code >> 16); 
		info = muGetUserInfo(info,muKeyType_uid);  
                switch(bits)
                {
                        case 0: /* Default case is case 1 */
                        case 1: returned = info->UserID;
                                break;
                        case 2: returned = "     ";
                                itoa(info->uid,returned);
                                break;
                        case 4: returned = "     ";
                                itoa(info->gid,returned);
                                break;                                
                        case 8: returned = info->UserName;
                                break;
                        default: returned = "One switch only!";
                                 code = 0; /* force error */
                }                       
	}
	else returned = "Nobody"; /* task owned by nobody */

        if (argarray[4] && argarray[5])
        {
                returned = "One keyword only!";
                code = 0; /* force error */
        }
        else if (code != 0) /* If error or no-one logged in skip this part */
        {
                if (argarray[4])
                        if (((ULONG)info->uid) < *(ULONG *)argarray[4])
                                code = 0xFFFFFFFF; /* Force a WARN condition */
                        else code = 1; /* remove normal WARN if root is logged on */

                if (argarray[5])
                        if (((ULONG)info->gid) < *(ULONG *)argarray[5])
                                code = 0xFFFFFFFF; /* Force a WARN condition */
                        else code = 1; /* remove normal WARN as above */
        }
        
        PutStr(returned);
        PutStr("\n");
                       
EXIT:	muFreeUserInfo(info); /* Return memory to Exec */
	CloseLibrary((struct Library *)muBase);
        CloseLibrary((struct Library *)DOSBase);
	
	if (code == 0)
		Exit(RETURN_ERROR); /* ERROR or no-one home today */
	else if ((code & muMASK_GID) == 0xFFFF)
		Exit(RETURN_WARN);  /* WARN - a root is logged in or security violation */
	else Exit(RETURN_OK);	    /* OK - nothing to remark */ 
}

void itoa(LONG number,STRPTR string)
{
        LONG i;
        
        for (i=4;i;i--)
        {
                string[i] = '0' + number % 10;
                number /= 10;
        }
        string[i] = '0' + number % 10; /* Last digit */
}
