/* NAME:
 *	runas - run a commanline as someone
 *
 * SYNOPSIS:
 *	runas "user" "cmd" "arg" ...
 *
 * DESCRIPTION:
 *	It is often desried to do something like:
 *.nf
 *
 *	su nobody -c "command"
 *.fi
 *
 *	Which often fails, because 'nobody' has an invalid shell.
 *	This command simply does the above.
 *	
 * AUTHOR:
 *	Simon J. Gerraty <sjg@crufty.net>
 */
/*
 *      @(#)Copyright (c) 1993, Simon J. Gerraty.
 *      
 *      This code is presented AS IS.  It comes with NO WARRANTY.
 *      Permission to use, modify and distribute this source code 
 *      is granted subject to the following conditions.
 *      1/ that the above copyright notice and this notice 
 *      are preserved in all copies and that due credit be given 
 *      to the author.  
 *      2/ that any changes to this code are clearly commented 
 *      as such so that the author does not get blamed for bugs 
 *      other than his own.
 *      
 *      Please send copies of changes and bug-fixes to:
 *      sjg@crufty.net
 */
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

#ifndef lint
static char RCSid[] = "$Id: runas.c,v 1.7 2004/02/19 08:35:47 sjg Exp $";
#endif
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <pwd.h>

int
main(argc, argv)
	int	argc;
	char	**argv;
{
	const char *myname;
	const char *user;
	struct passwd *pw = 0;
	int uid;
	
	if ((myname = strrchr(argv[0], '/')))
		++myname;
	else
		myname = argv[0];

	/*
	 * this should only be run by root.
	 */
	if (getuid()) {
		(void) fprintf(stderr, "%s: must be root.\n",
			       myname);
		exit(1);
	}
	if (argc < 3) {
		(void) fprintf(stderr, "usage:\n\t%s user command\n",
			       myname);
		exit(1);
	}

	if ((uid = atoi(argv[1])) == 0) {
		pw = getpwnam(argv[1]);
	} else {
		pw = getpwuid(uid);
	}
	if (!pw) {
		(void)fprintf(stderr,
			      "%s: can't get passwd entry for '%s'.\n",
			      myname,
			      argv[1]);
		exit(1);
	}
#if defined(__svr4__) || defined(HAVE_INITGROUPS)
	initgroups(pw->pw_name, pw->pw_gid);
#endif
	setgid(pw->pw_gid);
	setuid(pw->pw_uid);
	if (getuid() != pw->pw_uid) {
		(void)fprintf(stderr, "%s: setuid(%s==%d) failed.\n",
			      myname,
			      pw->pw_name,
			      pw->pw_uid);
		exit(1);
	}
	argv += 2;
	argc -= 2;
	execvp(argv[0], argv);
	perror(argv[0]);
	exit(1);
}
