#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>

#include <grp.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>

int find_id(char* file, char* id, int n) {
    int id_len = strlen(id);
    FILE* f = fopen(file, "r"); 
    if(!f) {
	perror(file);
	exit(errno); }
    while(!feof(f)) {
	char buffer[256];
	fgets(buffer, 256, f);
	if(!strncmp(id, buffer, id_len)) {
	    char* tok = strtok(buffer, ":");
	    for(; tok &&  n; n--, tok = strtok(0, ":"));
	    if(tok) {
		fclose(f);
		return atoi(tok); }
	    fprintf(stderr, "%s not found in %s\n", id, file);
	    exit(1); }}}


void usage() {
    puts("usage: execas <user> [-g <group>] program [arg...]");
    exit(1); }


int main(int c, char**v) {
    char **user = 0;
    char **group = 0;
    uid_t uid = 0;
    gid_t gid = 0;
    char **exec_args = 0;

    if(c < 3) usage();
    user = v + 1;
    if(c > 4 && !strcmp(v[2], "-g")) {
	group = v + 3;
	exec_args = v + 4; }
      else exec_args = v + 2;

    uid = find_id("/etc/passwd", *user, 2);
    if(group) gid = find_id("/etc/group", *group, 2);
      else gid = find_id("/etc/passwd", *user, 3);

    if(setresuid(uid, uid, uid) < 0) {
	perror("setresuid");
	return errno; }

    if(setresgid(gid, gid, gid) < 0) {
	perror("setresgid");
	return errno; }

    execvp(exec_args[0], exec_args);
    perror(exec_args[0]);
    return errno; }
