RCS_ID_C="$Id: id.c,v 2.1 1994/02/15 15:25:46 ppessi Exp $";
/*
 * id.c -- print out the identity of user
 *
 * Author: ppessi <Pekka.Pessi@hut.fi>
 *
 * Copyright © 1994 AmiTCP/IP Group, <AmiTCP-group@hut.fi>
 *                  Helsinki University of Technology, Finland.
 *
 * Created      : Tue Jan 11 22:33:06 1994 ppessi
 * Last modified: Tue Feb 15 14:25:22 1994 ppessi
 */

#include "id_rev.h"

static const char version[] = VERSTAG " "
"Copyright © 1994 AmiTCP/IP Group, <amitcp-group@hut.fi>\n"
  "Helsinki University of Technology, Finland.\n";

#include <pwd.h>
#include <grp.h>
#include <unistd.h>

#include <proto/usergroup.h>
#include <proto/dos.h>

#include <clib/exec_protos.h>
extern struct ExecBase* SysBase;
#include <pragmas/exec_sysbase_pragmas.h>

#include <dos/dos.h>

#include <string.h>
#include <stdlib.h>

#define USERGROUPVERSION 2	/* minimum version to use */

#ifndef MAXLINELENGTH 
#define MAXLINELENGTH 1024
#endif

LONG id(void)
{
  LONG retval = 128;
  struct DosLibrary *DOSBase;
  struct ExecBase *SysBase;
  struct Library *UserGroupBase;

  SysBase = *(struct ExecBase**)4;
  DOSBase = (struct DosLibrary *)OpenLibrary("dos.library", 37L);
  UserGroupBase = OpenLibrary(USERGROUPNAME, USERGROUPVERSION);
  
  if (DOSBase && UserGroupBase) {
    uid_t ruid = getuid(), euid = geteuid();
    gid_t rgid = getgid(), egid = getegid(), groups[NGROUPS];
    
    const char *template = "-u,-g,-n,-r,USER";
    struct {
      LONG   a_uid;
      LONG   a_gid;
      LONG   a_name;
      LONG   a_real;
      STRPTR a_user;
    } args[1] = { 0 };
    struct RDArgs *rdargs = NULL;

    retval = RETURN_OK;

    rdargs = ReadArgs((UBYTE *)template, (LONG *)args, NULL);

    if (rdargs == NULL) {
      PrintFault(IoErr(), "id");
      retval = RETURN_ERROR;
    } else if (args->a_uid) {
      struct passwd *pw;
      /* Print user id */
      uid_t uid = euid;

      /* Use real id? */
      if (args->a_real)
      uid = euid;

      if (args->a_name && (pw = getpwuid(uid))) {
	Printf("%s\n", pw->pw_name);
      } else {
	Printf("%ld\n", uid);
      }
    } else if (args->a_gid) {
      struct group *gr;
      /* Print primary group id */
      gid_t gid = egid;

      /* Use real id? */
      if (args->a_real)
	gid = egid;

      if (args->a_name && (gr = getgrgid(gid))) {
	Printf("%s\n", gr->gr_name);
      } else {
	Printf("%ld\n", gid);
      }
    } else {
      /* Print all identification information */
      char *sep = " groups=";
      short i, ngroups;

      if (euid == ruid) {
	struct passwd *pw;

	Printf("uid=%ld", euid);
	if (pw = getpwuid(ruid))
	  Printf("(%s)", pw->pw_name);
      } else {
	struct passwd *pw;

	Printf("ruid=%ld", ruid);
	if (pw = getpwuid(ruid))
	  Printf("(%s)", pw->pw_name);
	Printf(" euid=%ld", euid);
	if (pw = getpwuid(euid))
	  Printf("(%s)", pw->pw_name);
      }

      if (egid == rgid) {
	struct group *gr = getgrgid(egid);

	Printf(" gid=%ld", egid);
	if (gr)
	  Printf("(%s)", gr->gr_name);
      } else {
	struct group *gr;

	Printf(" rgid=%ld", rgid);
	if (gr = getgrgid(rgid))
	  Printf("(%s)", gr->gr_name);
	Printf(" egid=%ld", egid);
	if (gr = getgrgid(egid))
	  Printf("(%s)", gr->gr_name);
      }

      ngroups = getgroups(NGROUPS, groups);
      if (ngroups != -1) {
	for (i = 0; i < ngroups; i++) {
	  if ((rgid = groups[i]) != egid) {
	    struct group *gr;

	    Printf("%s%ld", sep, rgid);
	    if (gr = getgrgid(rgid))
	      Printf("(%s)", gr->gr_name);
	    sep = ",";
	  }
	}
	PutStr("\n");
      } else {
	Printf("%s: %s\n", "getgroups", ug_StrError(ug_GetErr()));
      }
    }
    if (rdargs) {
      FreeArgs(rdargs);
    }
  }

  if (UserGroupBase) {
    CloseLibrary(UserGroupBase);
  } else {
    Printf("id: cannot open %s\n", USERGROUPNAME);
  }

  if (DOSBase)
    CloseLibrary((struct Library *)DOSBase);

  return retval;
}
