/*
/*   Copyright (c) 2003, David S. Madole
/*   All rights reserved.
/*
/*   For latest sources and information on this software, please
/*   go to http://www.madole.net/chroot
/*
/*   Questions, comments or suggestions should be directed to
/*   David S. Madole <david@madole.net>.
/*
/*   Redistribution and use in source and binary forms, with or without
/*   modification, are permitted provided that the following conditions
/*   are met:
/*
/*   1. Redistributions of source code must retain the above copyright
/*      notice unmodified, this list of conditions, and the following
/*      disclaimer.
/*
/*   2. Redistributions in binary form must reproduce the above copyright
/*      notice, this list of conditions and the following disclaimer in the
/*      documentation and/or other materials provided with the distribution.
/*
/*   THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
/*   ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
/*   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
/*   ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
/*   FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
/*   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
/*   OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
/*   HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
/*   LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
/*   OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
/*   SUCH DAMAGE.
*/


#include <syslog.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <pwd.h>
#include <grp.h>

int main(int argc, char *argv[])
{
    struct passwd *pass;
    char *self, *user, **cmnd, *p;

    for (p = self = argv[0]; *p; ) if (*p++ == '/') self = p;

    if (strcmp("chrootsu", self) == 0) {

	if (argc < 2) {

	    printf("usage: %s newuser [command] [arguments]\n", self);
	    return 1;
	}

	user = argv[1];
	cmnd = argv + 2;

    } else {

	user = self;
	cmnd = argv + 1;
    }


    if ((pass = getpwnam(user)) == 0) {

	printf("%s: unknown login: %s\n", self, user);
	return 1;
    }

    if (chdir(pass->pw_dir)) {

	printf("%s: %s: %s\n", self, pass->pw_dir, strerror(errno));
	return 1;
    }

    if (chroot(pass->pw_dir)) {

	printf("%s: %s: %s\n", self, pass->pw_dir, strerror(errno));
	return 1;
    }

    if (initgroups(user, pass->pw_gid)) {

	printf("%s: %s: permission denied\n", self, user);
	return 1;
    }

    if (setgid(pass->pw_gid)) {

	printf("%s: %s: permission denied\n", self, user);
	return 1;
    }

    if (setuid(pass->pw_uid)) {

	printf("%s: %s: permission denied\n", self, user);
	return 1;
    }

    endpwent();

    if (*cmnd == 0 || **cmnd == '-') {

	*--cmnd = pass->pw_shell;
	execv(*cmnd, cmnd);

    } else execvp(*cmnd, cmnd);

    printf("%s: %s: %s\n", self, *cmnd, strerror(errno));
    return 1;
}
