#include <err.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>

int
main(int argc, char **argv)
{
	uid_t origuid, origeuid, nuid;
	long num;
	const char *uidstr;
	char *invchr;

	if (argc != 2)
		errx(2, "need exactly 1 argument");
	if (argv[1][0] == '\0')
		errx(2, "need a non-empty argument");
	uidstr = argv[1];
	num = strtol(uidstr, &invchr, 10);
	if (*invchr != '\0')
		errx(2, "can't convert %s to a number", uidstr);
	if (num < 0)
		errx(2, "UIDs can't be negative");
	if (num > (long)(uid_t)-1)
		errx(2, "UID %s is too large", uidstr);
	nuid = (uid_t)num;

	origuid = getuid();
	origeuid = geteuid();
	printf("Starting with uid %d, euid %d\n", origuid, origeuid);

	if (nuid == origuid)
		errx(2, "current uid same as given");
	printf("setuid(%d)\n", nuid);
	if (setuid(nuid))
		err(1, "setuid");

	printf("Now running with uid %d, euid %d\n", getuid(), geteuid());

	if (setuid(origuid) == 0)
		err(3, "Was able to setuid(origuid)!");
	if (setuid(origeuid) == 0)
		err(3, "Was able to setuid(origeuid)!");
	if (seteuid(origuid) == 0)
		err(3, "Was able to seteuid(origuid)!");
	if (seteuid(origeuid) == 0)
		err(3, "Was able to seteuid(origeuid)!");
	printf("Could not switch back, all is well\n");
	exit(0);
}
