From fed8339de92f60c271fb37e9ed7f5ca5737ea0a9 Mon Sep 17 00:00:00 2001
From: Philippe Pittoli <karchnu@karchnu.fr>
Date: Sat, 8 Feb 2025 18:35:56 +0100
Subject: [PATCH] Chapter 1, exercise 1, ping pong.

---
 exercises/chapter1-exo1-ping.c | 76 ++++++++++++++++++++++++++++++++++
 1 file changed, 76 insertions(+)
 create mode 100644 exercises/chapter1-exo1-ping.c

diff --git a/exercises/chapter1-exo1-ping.c b/exercises/chapter1-exo1-ping.c
new file mode 100644
index 0000000..9201ee8
--- /dev/null
+++ b/exercises/chapter1-exo1-ping.c
@@ -0,0 +1,76 @@
+#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;
+}