--- /dev/null
+prefix = /usr/local
+bindir = $(prefix)/bin
+INSTALL = install
+
+tl-append:
+
+%: %.c
+ $(CC) -Wall -Wextra -pedantic -o $@ $^
+
+.PHONY: check
+check: tl-append tl-append-test
+ ./tl-append-test
+
+.PHONY: install
+install: tl-append
+ $(INSTALL) -d $(DESTDIR)$(bindir)
+ $(INSTALL) -m 755 $^ $(DESTDIR)$(bindir)
--- /dev/null
+#define _POSIX_C_SOURCE 2
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+static void die(const char *message) {
+ fputs(message, stderr);
+ fputc('\n', stderr);
+ exit(1);
+}
+
+static void die_err(const char *message) {
+ perror(message);
+ exit(1);
+}
+
+static void write_and_read_line() {
+ char buf[10];
+
+ FILE *p = popen("./tl-append", "w");
+ if (p == NULL)
+ die_err("Couldn't run tl-append");
+ if (fputs("foo\n", p) == EOF)
+ die("Couldn't write to pipe");
+ int status = pclose(p);
+ if (status < 0)
+ die_err("Error closing pipe");
+ if (status != 0)
+ die("tl-append exited abnormally");
+
+ FILE *f = fopen("tl.log", "r");
+ if (f == NULL)
+ die_err("Error opening log file");
+ if (fgets(buf, sizeof(buf), f) == NULL)
+ die("Error reading log file");
+ if (strncmp("foo\n", buf, sizeof(buf)) != 0)
+ die("Wrong contents in log file");
+ if (fclose(f) != 0)
+ die_err("Error closing log file");
+}
+
+int main() { write_and_read_line(); }
--- /dev/null
+#include <stdio.h>
+#include <stdlib.h>
+
+const char *FILENAME = "tl.log";
+const size_t BUF_SIZE = 1024;
+
+static void die(const char *message) {
+ fputs(message, stderr);
+ fputc('\n', stderr);
+ exit(1);
+}
+
+static void die_err(const char *message) {
+ perror(message);
+ exit(1);
+}
+
+static void read_line(char *buf) {
+ if (fgets(buf, BUF_SIZE, stdin) == NULL) {
+ if (ferror(stdin))
+ die("I/O error reading line");
+ if (feof(stdin)) {
+ buf[0] = '\0'; /* Unclear if fgets does this already */
+ return;
+ }
+ die("Unexpected error reading line");
+ }
+}
+
+static void write_line(const char *line) {
+ FILE *f = fopen(FILENAME, "a");
+ if (f == NULL)
+ die_err("Error opening output file");
+ if (fputs(line, f) == EOF)
+ die("Error writing to output file");
+ if (fclose(f) != 0)
+ die_err("Error closing output file");
+}
+
+int main() {
+ char buf[BUF_SIZE];
+ for (read_line(buf); buf[0]; read_line(buf)) {
+ write_line(buf);
+ }
+ return 0;
+}