#include <stdio.h>
#include <signal.h>
#include <errno.h>

int talarm, kalarm, pid;
int talrm(), kalrm();
int verbose;
char *argv0;

talrm()
{
	if (verbose)
		fprintf(stderr, "%s: SIGTERM sent\n", argv0);
	kill(pid, SIGTERM);
	if (kalarm > talarm) {
		if (verbose > 1)
			fprintf(stderr, "%s: SIGKILL alarm in %d seconds\n", argv0, kalarm-talarm);
		signal(SIGALRM, kalrm);
		alarm(kalarm-talarm);
	}
}

kalrm()
{
	if (verbose)
		fprintf(stderr, "%s: SIGKILL sent\n", argv0);
	kill(pid, SIGKILL);
	if (talarm > kalarm) {
		if (verbose > 1)
			fprintf(stderr, "%s: SIGTERM alarm in %d seconds\n", argv0, talarm-kalarm);
		signal(SIGTERM, talrm);
		alarm(talarm-kalarm);
	}
}

#define TIMTERM	60

main(argc, argv)
char **argv;
{
	extern int optind, errno;
	extern char *optarg;
	int optch, errcnt, exstat;

	talarm = TIMTERM;
	kalarm = -1;
	argv0=argv[0];
	while ((optch=getopt(argc, argv, "t:k:v")) != -1)
		switch (optch) {
		case 't':
			talarm=atoi(optarg);
			break;
		case 'k':
			kalarm=atoi(optarg);
			break;
		case 'v':
			verbose++;
			break;
		default:
usage:
			fprintf(stderr, "Usage: %s [-t<SECONDS>][-k<SECONDS>][-v] <CMD> ...\n", argv0);
			fprintf(stderr, "\t-t\tNumber of seconds to timeout SIGTERM (default=%d)\n", TIMTERM);
			fprintf(stderr, "\t-k\tNumber of seconds to timeout SIGKILL (default=2*SIGTERM time)\n", TIMTERM);
			fprintf(stderr, "\t-v\tverbose\n");
			fprintf(stderr, "\t-vv\tvery verbose\n");
			exit(255);
		}
	if (kalarm == -1) {
		if (talarm == 0)
			kalarm=TIMTERM;
		else
			kalarm=talarm*2;
	}
	if (kalarm == talarm)
		kalarm++;

	if (optind == argc)
		goto usage;

	errcnt=100;
	while ((pid=fork()) == -1)
		if (--errcnt == 0) {
			perror("fork");
			exit(255);
		}
	if (pid == 0) {
		/* child */
		switch (verbose) {
		case 1:
			fprintf(stderr, "%s: running \"%s", argv0, argv[optind]);
			for (verbose=optind+1; verbose < argc; verbose++)
				fprintf(stderr, " %s", argv[verbose]);
			fprintf(stderr, "\"\n");
			break;
		case 2:
			fprintf(stderr, "%s: execlp(\"%s\", ", argv0, argv[optind]);
			for (verbose=optind; verbose < argc; verbose++)
				fprintf(stderr, "\"%s\", ", argv[verbose]);
			fprintf(stderr, "NULL)\n");
			break;
		}
		execvp(argv[optind], &argv[optind]);
		perror("execvp");
		exit(255);
	}
	/* parent */
	if (talarm && (kalarm == 0 || talarm < kalarm)) {
		if (verbose > 1)
			fprintf(stderr, "%s: SIGTERM alarm in %d seconds\n", argv0, talarm);
		signal(SIGALRM, talrm);
		alarm(talarm);
	}
	if (kalarm && (talarm == 0 || kalarm < talarm)) {
		if (verbose > 1)
			fprintf(stderr, "%s: SIGKILL alarm in %d seconds\n", argv0, kalarm);
		signal(SIGALRM, kalrm);
		alarm(kalarm);
	}
	while (wait(&exstat) == -1)
		if (errno != EINTR) {
			perror("wait");
			exit(255);
		}
	if (exstat & 0377) {
		exstat |= 0200;
	} else {
		exstat >>= 8;
		exstat &= 0177;
	}
	if (verbose > 1)
		fprintf(stderr, "%s: exit status %d\n", argv0, exstat);
	exit(exstat);
}
