#include <sys/time.h>
#include <sys/resource.h>
#include <unistd.h>
#include <stdio.h>
#include <limits.h>
#include <stdlib.h>

#define SECONDS 1
#define JIFFIES 10

void showrlimit();
void usage();
void gather_args();
void checkbase10();
char *shiftarg();

char *self;

int main(argc, argv)
	int argc;
	char **argv;
{
	struct rlimit rlim;
	extern char **environ;

	rlim.rlim_cur = 0;
	rlim.rlim_max = 0;
	gather_args(&argc, &argv, &rlim);

	if (rlim.rlim_cur != LONG_MAX && rlim.rlim_max != 0) {
		if (setrlimit(RLIMIT_TCPU, &rlim) == -1) {
			perror ("setrlimit");
			_exit (1);
		}
	}

	execvp(*argv, argv);
	perror(*argv);
	_exit(1);
}

void showrlimit(rlim)
	struct rlimit *rlim;
{
	rlim->rlim_cur = 0;
	rlim->rlim_max = 0;

	if (getrlimit(RLIMIT_TCPU, rlim) == -1) {
		perror ("getrlimit");
		_exit(1);
	}
	printf ("wait %lu jiffies per %lu frac-cpu seconds\n", LONG_MAX-rlim->rlim_cur, rlim->rlim_max);

}

void usage() {
	fprintf (stderr, "usage: \n"
			 "   %s [-L m n] <-g|-e <command> [line]>\n"
			 "\n"
			 "-L s j     set limits: for every s frac-cpu seconds,"
				" wait j jiffies\n"
			 "-g         get current limit info\n"
			 "-e ...     command line to execute follows"
				" (last processed option)\n", self);

	_exit(1);
}

char *shiftarg(argc, argv)
	int *argc;
	char ***argv;
{
	char *ret = **argv;
	if (!(*argc)--) usage();
	(*argv)++;

	return(ret);
}

void checkbase10 (p)
	char *p;
{
	int val;

	for (;;) {
		if (!(val = *p)) return;
		if (((val-='0') < 0) || (val > 9)) usage();
		p++;
	}
}

void gather_args(argc, argv, rlim)
	int *argc;
	char ***argv;
	struct rlimit *rlim;
{
	char *option;
	self = shiftarg(argc, argv);

	for (;;) {
		option = shiftarg(argc, argv);

		if (*option == '-') {
			if (*(option+2) != 0) usage();
			switch(*(option+1)) {
				case 'L':
					checkbase10(option = shiftarg(argc, argv));
					rlim->rlim_max = atol(option);
					checkbase10(option = shiftarg(argc, argv));
					rlim->rlim_cur = LONG_MAX-atol(option);
					break;
				case 'g':
					showrlimit(rlim);
					_exit(0);
				case 'e':
					if (!*argc) usage();
					return;
				default:
					usage();
			}
		}
	}
}

