#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <sys/wait.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <stdbool.h>
#include <string.h>

void run(char *argv[])
{
  execvp(argv[0], argv);
  perror("exec");
  exit(1);
}

double ftime(struct timeval t)
{
  double s = t.tv_sec + (double)t.tv_usec/1000000.0;
  return s;
}

void usage(void)
{
  printf("Usage: rusage <cmd...>\n");
  exit(0);
}

int main(int argc, char *argv[])
{
  if (argc < 2) {
    usage();
  }

  pid_t pid = fork();
  if (pid < 0) {
    perror("fork");
    return 1;
  }
  if (pid == 0) run(argv+1);

  int status = 0;
  waitpid(pid, &status, 0);
  printf("--\n     Exit status: %d\n", WEXITSTATUS(status));
  struct rusage u;
  if (getrusage(RUSAGE_CHILDREN, &u) < 0) {
    perror("rusage");
    return 1;
  }
  printf("        CPU time: user: %.3fs, sys: %.3fs\n", ftime(u.ru_utime), ftime(u.ru_stime));
  printf("         Max RSS: %ldK\n", u.ru_maxrss);
  printf("     Page faults: minor: %ld, major: %ld\n", u.ru_minflt, u.ru_majflt);
  printf("      I/O blocks: in: %ld, out: %ld\n", u.ru_inblock, u.ru_oublock);
  printf("Context switches: voluntary: %ld, involuntary: %ld\n", u.ru_nvcsw, u.ru_nivcsw);

  return 0;
}
