/*
 * 5799-WZQ (C) COPYRIGHT IBM CORPORATION 1987,1988
 * LICENSED MATERIALS - PROPERTY OF IBM
 * REFER TO COPYRIGHT INSTRUCTIONS FORM NUMBER G120-2083
 */
/* $Header:setid.c 12.0$ */
/* $ACIS:setid.c 12.0$ */
/* $Source: /ibm/acis/usr/src/etc/RCS/setid.c,v $ */

#ifndef lint
static char *rcsid = "$Header:setid.c 12.0$";
#endif

#include <stdio.h>
#include <ctype.h>
#include <pwd.h>
#include <grp.h>
#include <strings.h>
#include <sys/param.h>

/*
 * command to execute another command with the specified 
 * user/group id set.
 */

char *fixpath();

#ifdef __STDC__
void err(char *fmt, ...)
#else
err(fmt,d1,d2,d3)
char *fmt;
#endif __STDC__
{
	fprintf(stderr, fmt,((int *) &fmt)[1],((int *) &fmt)[2],((int *) &fmt)[3]);
	fprintf(stderr, "\n");
	exit(1);
}

int uid, gid;

main(argc,argv) char **argv;
{
	register char *argp;
	char *cmd;
	char buff[MAXPATHLEN+1];

	if (argc < 2)
		err("usage: %s [user.group cmd|-f file] args ...",argv[0]);
	cmd = argv[2];
	argp = argv[1];
	if (argp[0] == '-' && argp[1] == 'f')
		{
		FILE *f = fopen(argv[2], "r");
		if (f == NULL)
			err("can't open %s", argv[0]);
		getline(argv[2], buff, sizeof buff, f);
		getids(buff);
		getline(argv[2], buff, sizeof buff, f);
		cmd = buff;
		if (!strcmp(cmd,"-"))
		{
			strcpy(cmd,argv[2]);
			(void) fixpath(cmd);
		}
		fclose(f);
		}
	else
		getids(argp);
	if (gid != -1 && setegid(gid) == -1)
		err("setegid(%d) failed",gid);
	if (uid != -1 && seteuid(uid) == -1)
		err("setuid failed");
	if (uid == -1 && setuid(getuid()) == -1)
		err("setuid failed");
	argv[argc] = 0;
/*	printf("execing %s\n", cmd);	/* DEBUG */
	execv(cmd,argv+2);
	err("couldn't execv %s",cmd);
}

getids(argp)
char *argp;
{
	register struct passwd *pw;
	register struct group *gr;
	char *p = index(argp,'.');

	if (p) 
		*p++ = 0;
	gid = -1;
	if (*argp == 0)
		uid = -1;
	else
	{
		if ((pw = getpwnam(argp)) == NULL)
		{
			if (isdigit(*argp))
			{
				uid=atoi(argp);
			}
			else
			{
				err("no user %s",argp);
			}
		}
		else
		{
			uid = pw->pw_uid;
		}
		endpwent();	/* close /etc/passwd */
	}

	if ((argp = p) && *argp)
	{
		{
			if ((gr = getgrnam(argp)) == NULL)
			{
				if (isdigit(*argp))
				{
					gid=atoi(argp);
				}
				else
				{
					err("no group %s",argp);
				}
			}
			else
			{
				gid = gr->gr_gid;
			}
			endgrent();	/* close /etc/passwd */
		}

	}
/*	printf("uid=%d gid=%d\n",uid,gid);	/* */
}

/*
 * read a line from file, ignoring commented lines beginning with #
 */
getline(file,buff,len,f)
char *buff;
FILE *f;
{
	while (fgets(buff, len, f) != 0)
		{
		int l = strlen(buff);
		if (l > 0 && buff[l-1] == '\n')
			buff[l-1] = 0;
		if (buff[0] != '#')
			return;
		}
	err("%s: unexpeced EOF", file);
}

char *fixpath(path)
char *path;
{
  char *pos;
  
  pos=&path[strlen(path)];
  while ((pos>=path) && (*pos != '/'))
  {
    pos[1]=*(pos);
    pos--;
  }

  pos[1]='.';
  return(path);
}
