/* Scheme48/scsh Unix system interface.
** User and group db access routines
** Copyright (c) 1993, 1994 by Olin Shivers.
*/

/*
** The code in this file is separated out from the code in syscalls1.c
** because we must compile them with different compiler flags (non-posix)
** to get around a NeXTSTEP bug. Once they get their act together, we can
** stick it back into syscalls1.c.
*/

#include <sys/types.h>
#include <grp.h>
#include <pwd.h>

/* Make sure our exports match up w/the implementation: */
#include "userinfo1.h"

#include <unistd.h>

/* Compute the length of a null-terminated char* vector. */
static int strvec_len(char **vec)    
{
    int i = 0;
    char **ptr = vec;
    if ( !ptr ) return 0;

    while( *ptr++ ) i++;

    return i;
    }


/* User db access routines
*******************************************************************************
*/
    
/* Return a user name for ourself. 
** Uses our *real* uid, not our effective one.
*/

char *my_username(void)
{
    char *s = getlogin();
    if( s ) return s;
    else {
	struct passwd *pwd = getpwuid(getuid());
	return pwd ? pwd->pw_name : (char*) 0;
	}
    }

int user_info_uid(uid_t uid, 
		  char **name, gid_t *gid, char **dir, char **shell)
{
    struct passwd *pwd = getpwuid(uid);
    if( !pwd ) {
        *name = 0;
	*gid  = 0;
	*dir  = 0;
	*shell = 0;
	return 0;
        }
    *name = pwd->pw_name;
    *gid  = pwd->pw_gid;
    *dir  = pwd->pw_dir;
    *shell = pwd->pw_shell;
    return 1;
    }

int user_info_name(const char *name,
		   uid_t *uid, gid_t *gid, char **dir, char **shell)
{
    struct passwd *pwd = getpwnam(name);
    if( !pwd ) {
        *uid   = 0;
	*gid   = 0;
	*dir   = 0;
	*shell = 0;
	return 0;
        }
    *uid  = pwd->pw_uid;
    *gid  = pwd->pw_gid;
    *dir  = pwd->pw_dir;
    *shell = pwd->pw_shell;
    return 1;
    }


int group_info_gid (int gid,  char **name, char ***members, int *nmembers)
{
    struct group *grp = getgrgid(gid);
    if( !grp ) {
        name = 0;
	members = 0;
	nmembers = 0;
        return 0;
        }
    *name = grp->gr_name;
    *members = grp->gr_mem;
    *nmembers = strvec_len(grp->gr_mem);
    return 1;
    }

int group_info_name (const char *name,
		     int *gid, char ***members, int *nmembers)
{
    struct group *grp = getgrnam(name);
    if( !grp ) {
        gid = 0;
	members = 0;
	nmembers = 0;
        return 0;
        }
    *gid = grp->gr_gid;
    *members = grp->gr_mem;
    *nmembers = strvec_len(grp->gr_mem);
    return 1;
    }