/* $Header: context.c,v 2.2 90/02/23 16:35:52 chip Exp $
 *
 * User context manager.
 * This module exists for efficiency reasons; I could just call getpwnam()
 * every time I need context info.
 *
 * $Log:	context.c,v $
 * Revision 2.2  90/02/23  16:35:52  chip
 * \Fix problems determining legality of user references.
 * 
 * Revision 2.1  89/06/09  12:25:13  network
 * Update RCS revisions.
 * 
 * Revision 1.5  89/06/09  12:23:39  network
 * Baseline for 2.0 release.
 * 
 */

#include "deliver.h"
#include <pwd.h>
#include <grp.h>

extern  struct passwd   *getpwnam();
extern  struct passwd   *getpwuid();
extern  struct group    *getgrnam();
extern  struct group    *getgrgid();

/*
 * Local functions.
 */

static  CONTEXT *new_context();

/*
 * Local data.
 */

static  CONTEXT *ctlist;	/* Chain of CONTEXT structures.		*/

/*----------------------------------------------------------------------
 * Look up a context by user name.
 */

CONTEXT *
name_context(name)
char    *name;
{
	struct passwd *pw;
	CONTEXT *ct;

	for (ct = ctlist; ct; ct = ct->ct_next)
	{
		if (strcmp(ct->ct_name, name) == 0)
			return ct;
	}

	if ((pw = getpwnam(name)) == NULL)
		return NULL;

	return new_context(pw);
}

/*----------------------------------------------------------------------
 * Look up a context by user ID.
 */

CONTEXT *
uid_context(uid)
int     uid;
{
	struct passwd *pw;
	CONTEXT *ct;

	for (ct = ctlist; ct; ct = ct->ct_next)
	{
		if (ct->ct_uid == uid)
			return ct;
	}

	if ((pw = getpwuid(uid)) == NULL)
		return NULL;

	return new_context(pw);
}

/*----------------------------------------------------------------------
 * Local function -- create a new context structure and return
 * its address.
 */

static CONTEXT *
new_context(pw)
struct passwd *pw;
{
	CONTEXT *ct;

	ct = (CONTEXT *) zalloc(sizeof(CONTEXT));
	ct->ct_uid = pw->pw_uid;
	ct->ct_gid = pw->pw_gid;
	ct->ct_name = copystr(pw->pw_name);
	ct->ct_home = copystr(pw->pw_dir);

	ct->ct_next = ctlist;
	ctlist = ct;

	return ct;
}

/*----------------------------------------------------------------------
 * Report whether is is possible or not to go from the given
 * effective uid/real uid/real gid to the given context.
 */

int
ok_context(euid, ruid, rgid, ct)
int	euid, ruid, rgid;
CONTEXT *ct;
{
	if (!ct)
		return FALSE;

	if (euid == 0
	 || ((ruid == ct->ct_uid) && (rgid == ct->ct_gid)))
		return TRUE;
	else
		return FALSE;
}

/*----------------------------------------------------------------------
 * Look up a group ID by name.
 */

#ifdef MBX_GROUP

int
group_id(name)
char    *name;
{
	struct group *grp;

	if ((grp = getgrnam(name)) == NULL)
		return -1;

	return grp->gr_gid;
}

#endif /* MBX_GROUP */
