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

char *_escape_command_param(const char *str);
long _get_alive_time_usec(const struct timeval *start);


int main(int argc, char **argv) {
    int i;
    char *pstr;
    char *command;
    struct rusage usage;
    struct timeval start;
    long usec;
    double score;

    if (argc <= 1) {
        printf("usage: getusage COMMAND [args]\n");
        exit(1);
    }

    command = strdup(argv[1]);
    for (i = 2; i < argc; i++) {
        pstr = _escape_command_param(argv[i]);
        command = (char *)realloc(command, strlen(command) + strlen(pstr) + 10);
        strcat(command, " \"");
        strcat(command, pstr);
        strcat(command, "\"");
        free(pstr);
    }

    gettimeofday(&start, (struct timezone *)NULL);
    system(command);
    usec = _get_alive_time_usec(&start);

    if (getrusage(RUSAGE_CHILDREN, &usage) != 0) {
        printf("Command Failed.\n");
        exit(1);
    }
    printf("system time used = %ld.%ld\n", usec/1000000L, usec%1000000L);
    printf("memory page used = %ld\n", (long)usage.ru_minflt);
    score = 0.0;
    if (usec != 0 && usage.ru_minflt != 0) {
        score = 100.0 / (((double)usec/1000000.0) * (double)usage.ru_minflt);
    }
    printf("score = %f\n", score);

    free(command);

    return 0;
}


char *_escape_command_param(const char *str) {
    unsigned char *new_str;
    int i, j, len;
    unsigned char c;

    if (str == NULL) {
        return strdup("");
    }

    len = strlen(str);
    new_str = (unsigned char *)malloc(len * 2 + 1);

    j = 0;
    for (i = 0; i < len; i++) {
        c = (unsigned char)str[i];
        switch (c) {
            case '"':
            case '`':
                new_str[j++] = '\\';
                new_str[j++] = c;
                break;
            case '\\':
                new_str[j++] = '\\';
                new_str[j++] = '\\';
                break;
            case '$':
                new_str[j++] = '\\';
            default:
                new_str[j++] = c;
                break;
        }
    }
    new_str[j] = '\0';

    return (char *)new_str;
}


long _get_alive_time_usec(const struct timeval *start) {
    struct timeval tp;
    long usec;

    gettimeofday(&tp, (struct timezone *)NULL);
    usec = ((long)(tp.tv_sec - start->tv_sec) * 1000000L) +
            (long)(tp.tv_usec - start->tv_usec);

    return usec;
}
