pipeln

Pipeline creation tool
git clone https://git.sinitax.com/sinitax/pipeln
Log | Files | Refs | README | LICENSE | sfeed.txt

commit 45f674aa80b6cec9c95e12ea086e06811ccbdeb2
parent 25aef9010259cf14d0b9a138cbadc13740feaff5
Author: Louis Burda <quent.burda@gmail.com>
Date:   Sun, 14 Jul 2024 07:21:14 +0200

Prevent re-closing input pipe file descriptor

Diffstat:
MMakefile | 8+++++++-
Mpipeln.c | 55+++++++++++++++++++++++++++----------------------------
2 files changed, 34 insertions(+), 29 deletions(-)

diff --git a/Makefile b/Makefile @@ -1,7 +1,13 @@ PREFIX ?= /usr/local BINDIR ?= /bin -CFLAGS = -std=c99 -Wunused-variable -Wunused-function -Wconversion -O2 +CFLAGS = -std=c99 -Wunused-variable -Wunused-function -Wconversion + +ifeq ($(DEBUG), 1) +CFLAGS += -Og -g +else +CFLAGS += -O2 +endif all: pipeln diff --git a/pipeln.c b/pipeln.c @@ -1,12 +1,8 @@ -#include <asm-generic/errno-base.h> -#include <linux/limits.h> #include <sys/wait.h> #include <unistd.h> #include <dirent.h> #include <wait.h> - #include <errno.h> -#include <limits.h> #include <stdio.h> #include <stdarg.h> #include <string.h> @@ -21,6 +17,7 @@ die(const char *fmt, ...) { va_list ap; + setvbuf(stderr, NULL, _IOLBF, 0); fputs("pipeln: ", stderr); va_start(ap, fmt); vfprintf(stderr, fmt, ap); @@ -35,6 +32,13 @@ die(const char *fmt, ...) exit(1); } +static void +usage(int rc, FILE *file) +{ + fprintf(file, "Usage: pipeln [-h] [-R] [--] [CMD |].. CMD\n"); + exit(rc); +} + static pid_t run(int *in, int *out, const char **argv) { @@ -48,15 +52,15 @@ run(int *in, int *out, const char **argv) if (!child) { if (in) { if (dup2(in[0], 0) < 0) - die("dup2:"); - close(in[0]); - close(in[1]); + die("dup2 %i:", errno); + if (close(in[0]) < 0) + die("close:"); } if (out) { if (dup2(out[1], 1) < 0) die("dup2:"); - close(out[0]); - close(out[1]); + if (close(out[0]) < 0 || close(out[1]) < 0) + die("close:"); } if (resolve_bin) { execvp(argv[0], (char *const *) argv); @@ -99,48 +103,43 @@ int main(int argc, const char **argv) { const char **arg, **cmdargs; - const char *invalid; int pipe1[2], pipe2[2]; int *in, *out; pid_t pid; - /* first cmd from stdin */ - in = NULL; - out = pipe2; - if (argc < 1) return 1; - invalid = NULL; - cmdargs = NULL; for (arg = argv + 1; *arg; arg++) { if (!strcmp(*arg, "--")) { - cmdargs = arg; + arg++; break; - } else if (!strcmp(*arg, "-x")) { + } else if (!strcmp(*arg, "-h")) { + usage(1, stderr); + } else if (!strcmp(*arg, "-R")) { resolve_bin = false; } else { - invalid = *arg; + break; } } - if (!cmdargs) die("missing -- separator"); - if (invalid) die("invalid argument '%s'", invalid); - cmdargs += 1; - for (arg = argv + 1; ; arg++) { + // First command from stdin. + in = NULL; + out = pipe1; + + cmdargs = arg; + for (; ; arg++) { if (!*arg || !strcmp(*arg, "|")) { - /* last cmd goes to stdout */ + // Last command to stdout. if (!*arg) out = NULL; - else if (pipe(out)) die("pipe:"); + else if (pipe(out) < 0) die("pipe:"); - /* run piped cmd */ *arg = NULL; pid = run(in, out, cmdargs); if (!out) waitall(pid); cmdargs = arg + 1; - /* out => in */ in = out; - out = out == pipe1 ? pipe2 : pipe1; + out = (out == pipe1) ? pipe2 : pipe1; } else if (!strcmp(*arg, "\\|")) { *arg = "|"; }