/**
 * Copyright 2010 Quest Software, Inc.
 * All Rights reserved.
 *
 * Program for running a subprocess with a SIGALRM scheduled.
 *
 * To compile:
 *   gcc -Wall -o timedkill killalarm.c
 * To run:
 *   ./timedkill <command>
 * Example usage (with shell prompt shown):
 *   $ gcc -Wall -o timedkill killalarm.c
 *   $ ./timedkill vastool kinit
 *   Password for user@EXAMPLE.COM:
 * At this point you can wait 60 seconds, after which "Alarm clock" will
 * be printed and the program will exit.
 *
 * If the program installs its own SIGALRM handler then this will not
 * necessarily cause the program to exit. This program exists as an
 * example only and is designed to kill a `vastool kinit` prompt
 * which we STRONGLY RECOMMEND YOU SHOULD NOT DO due to the security
 * implementations of turning on terminal echo while a user may be typing
 * their password.
 *
 * THIS PROGRAM IS FOR DEMONSTRATION ONLY AND SHOULD NOT BE USED.
 * IT COMES WITH NO WARRANTY AND WE EXPLICITLY DISCOURAGE ITS USE.
 */
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>

/* Set this to however long you want to wait before killing the user's
 * process. It will be sent a SIGALRM after that period, so if it
 * has implemented its own SIGALRM handler (instead of the default:
 * terminate) then it can choose to survive.
 *
 * It is left as an exercise to the reader should you choose to kill the
 * process mercilessly with a SIGKILL. In that case you are responsible
 * for doing any cleanup, such as restoring terminal echo. */
static const int CMD_TIMEOUT = 60;

static void shift_args(int *argc, char **argv) {
    int targ;

    for (targ = 0; targ < *argc - 1; ++targ)
        argv[targ] = argv[targ + 1];

    argv[*argc - 1] = NULL;
    (*argc)--;
}

int main(int argc, char *argv[]) {
    if (argc == 1) {
        fprintf(stderr, "Usage: %s <program> [args]\n", argv[0]);
        return 2;
    }

    /* Ensure argv is NULL-terminated. Reuse existing argv allocation. */
    shift_args(&argc, argv);
    alarm(CMD_TIMEOUT);
    execvp(argv[0], argv);
    fprintf(stderr, "Failed to exec %s: %s\n", argv[0], strerror(errno));
    return 1;
}

