//#define _XOPEN_SOURCE 600
#define _GNU_SOURCE
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <sys/time.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>

#define PIPESIZE 512*1024

volatile int running = 1;

void sighandler(int sig, siginfo_t *info, void *ctxt)
{
  // Don't use printf() in signal handler.
  printf("Caught: %d, %d\n", sig, (int)(info->si_int));
  running = 0;
  if (sig == SIGINT) exit(0);
}

int main(int argc, char *argv[])
{
  struct itimerval it;
  struct sigaction act;
  int i, seconds;
  pid_t pid;

  if (argc > 1)
    seconds = atoi(argv[1]);
  else seconds = 5;
  
  act.sa_flags = SA_SIGINFO;
  act.sa_sigaction = &sighandler;
  sigaction(SIGALRM, &act, NULL);

  int pipefd[2];
  char buf[PIPESIZE];

  if (pipe(pipefd) < 0) {
    fprintf(stderr,"Error opening pipe\n");
    exit(1);
  }
  if (fcntl(pipefd[0], F_SETPIPE_SZ, PIPESIZE) < 0) {
    perror("fcntl");
  }
  printf("Pipe size set to %d\n", fcntl(pipefd[0], F_GETPIPE_SZ, 0));
  pid = fork();
  if (pid < 0) {
    perror("fork");
    return 0;
  }
  if (pid > 0) {
    // This is the parent
    close(pipefd[1]);
    int r, count=0;
    alarm(seconds);
    while (running && (r=read(pipefd[0], buf, sizeof(buf))) > 0) {
      count++;
    }
    kill(pid, 9);
    printf("%.3f bytes / second\n", (float)(sizeof(buf)*count) / (float)seconds);
  } else {
    // This is the child
    close(pipefd[0]);
    int i;
    for(;;) {
      memset(buf, 'a', sizeof(buf));
      write(pipefd[1], buf, sizeof(buf));
    }
  }
  return 0;
}
