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

#define BILLION  1000000000L
#define MILLION  1000000L
#define THOUSAND 1000L

void get_time_ts(struct timespec *t0) {
	if (clock_gettime(CLOCK_REALTIME, t0) == -1) {
		perror("clock_gettime");
		exit(1);
	}
}

long long duration_ns(struct timespec t0, struct timespec t1) {
	return ((t1.tv_sec - t0.tv_sec)*BILLION) + (t1.tv_nsec - t0.tv_nsec);
}

void print_time_ns(long long time) {
	printf("%llds %lldms %lldµs %lldns\n"
		, time/BILLION
		, (time/MILLION)%THOUSAND
		, (time/THOUSAND)%THOUSAND
		, time%THOUSAND
	);
}

#define BUFSIZE 1024
int main (int argc, char **argv) {
	struct timespec t0, t1;
	long long duration;
	long long max_duration = 0;

	int parent_to_child[2];
	int child_to_parent[2];

	if ( -1 == pipe(parent_to_child) ) return 1;
	if ( -1 == pipe(child_to_parent) ) return 1;

	char msg1[] = "ping";
	char bufchild[BUFSIZE] = {0} ;
	int nbytes;

	int pid = fork();
	switch ( pid ) {
		case -1: return 2;
		case 0: /*child*/
			close(child_to_parent[0]);
			close(parent_to_child[1]);
			while((nbytes = read(parent_to_child[0], bufchild, BUFSIZE)) > 0) {
				write(child_to_parent[1], bufchild, nbytes);
			}
			break;
		default: /*parent*/
			close(parent_to_child[0]);
			close(child_to_parent[1]);
			while (max_duration < BILLION) {
				get_time_ts(&t0);
				write(parent_to_child[1], msg1, strlen(msg1) + 1);
				nbytes = read(child_to_parent[0], bufchild, BUFSIZE);
				get_time_ts(&t1);
				duration = duration_ns(t0, t1);
				printf("read: %s\n", bufchild);
				print_time_ns(duration);
				max_duration += duration;
			}
			close(parent_to_child[0]);
			close(parent_to_child[1]);
			wait(NULL);
	}
	return 0;
}