streamutils

Utilities for working dealing with stdio as streams of lines in the shell
git clone http://shtanton.xyz/git/repo/streamutils
Log | Files | Refs

commit eb3c0123f187e0ef6696c8f1d74994fe5c162e74
Author: Charlie Stanton <charlie@shtanton.xyz>
Date:   Wed, 17 Aug 2022 12:45:19 +0100

Initial commit

Implements version 0.1.0 of roundrobin

Diffstat:
A.gitignore | 1+
AMakefile | 9+++++++++
Asrc/roundrobin.c | 101+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 111 insertions(+), 0 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -0,0 +1 @@ +bin diff --git a/Makefile b/Makefile @@ -0,0 +1,9 @@ +PROGRAMS=roundrobin +BINARIES=$(patsubst %, bin/%, $(PROGRAMS)) + +all: $(BINARIES) + +bin/%: src/%.c + $(CC) $(CFLAGS) $^ -o $@ + +.PHONY: all diff --git a/src/roundrobin.c b/src/roundrobin.c @@ -0,0 +1,101 @@ +#include <stdio.h> +#include <stdlib.h> + +struct { + size_t length; + size_t capacity; + FILE **writers; +} outputs; + +void append_output(FILE *writer) { + if (outputs.length >= outputs.capacity) { + outputs.capacity *= 2; + outputs.writers = realloc(outputs.writers, outputs.capacity * sizeof(FILE **)); + if (outputs.writers == NULL) { + fprintf(stderr, "Out of memory\n"); + exit(1); + } + } + outputs.writers[outputs.length++] = writer; +} + +int main(int argc, char *argv[]) { + int c; + size_t output_index = 0; + char separator = '\n'; + FILE *writer; + + outputs.length = 0; + outputs.capacity = 4; + outputs.writers = malloc(4 * sizeof(FILE **)); + if (outputs.writers == NULL) { + fprintf(stderr, "Out of memory\n"); + return 1; + } + + if (argc <= 1) { + fprintf(stderr, "Missing output files\n"); + return 1; + } + + size_t i; + for (i = 1; i < argc; i++) { + if (argv[i][0] != '-') { + fprintf(stderr, "Expected flag, found: \"%s\"\n", argv[i]); + return 1; + } + + if (argv[i][1] != '\0' && argv[i][2] != '\0') { + fprintf(stderr, "Invalid flag: \"%s\"", argv[i]); + return 1; + } + + switch (argv[i][1]) { + case 'e': + if (++i >= argc) { + fprintf(stderr, "Missing file after -f\n"); + return 1; + } + writer = popen(argv[i], "w"); + if (writer == NULL) { + fprintf(stderr, "Error running command: %s\n", argv[i]); + return 1; + } + append_output(writer); + break; + case 'f': + if (++i >= argc) { + fprintf(stderr, "Missing file after -f\n"); + return 1; + } + writer = fopen(argv[i], "w"); + if (writer == NULL) { + fprintf(stderr, "Error opening file %s\n", argv[i]); + return 1; + } + append_output(writer); + break; + default: + fprintf(stderr, "Invalid flag: \"%s\"\n", argv[i]); + return 1; + } + } + + for (;;) { + c = getchar(); + if (c == EOF) { + break; + } + + if (fputc(c, outputs.writers[output_index]) == EOF) { + fprintf(stderr, "Error writing to output %lu\n", output_index); + return 1; + } + + if (c == separator) { + fflush(outputs.writers[output_index]); + output_index++; + output_index %= outputs.length; + } + } +}