pipeln

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

commit 25aef9010259cf14d0b9a138cbadc13740feaff5
parent 9e4b252a5bbe1f8bf829af85c76cfb1e89c55c7e
Author: Louis Burda <quent.burda@gmail.com>
Date:   Sun, 18 Feb 2024 17:26:52 +0100

Add manpage, README and flag to disable binary resolving

Diffstat:
AREADME | 35+++++++++++++++++++++++++++++++++++
Apipeln.1 | 46++++++++++++++++++++++++++++++++++++++++++++++
Mpipeln.c | 36++++++++++++++++++++++++++++++++----
3 files changed, 113 insertions(+), 4 deletions(-)

diff --git a/README b/README @@ -0,0 +1,35 @@ +pipeln +====== + +A command pipeline creation tool + +SYNOPSIS +-------- + +pipeln [-x] -- [CMD |..] CMD + +DESCRIPTION +----------- + +pipeln builds data processing pipelines without the need to invoke a shell. +No argument expansion takes place, which ensures all arguments are properly quoted. + +The pipeline is described in familiar shell-syntax: +A | character is placed behind commands whose output should be redirected +as the following command's input. + +By default, command names are resolved automatically using the PATH +environment variable. The -x flag disables this behavior. + +EXAMPLES +-------- + +Build a data processing pipeline from C with clear argument boundaries: + +> const char *argv[] = {"tmpl", "--", "ls", "|", "grep", "test", NULL} +> execv("/bin/tmpl", argv); + +AUTHORS +------- + +Written by Louis Burda <quent.burda@gmail.com>. diff --git a/pipeln.1 b/pipeln.1 @@ -0,0 +1,46 @@ + +.Dd Feb 18, 2024 +.Dt PIPELN 1 +.Os linux + +.Sh NAME +.Nm pipeln +.Nd A command pipeline creation tool + +.Sh SYNOPSIS + +.Nm +.Op Fl x +.Ar -- +.Op Ar CMD |.. +.Ar CMD + +.Sh DESCRIPTION + +.Nm +builds data processing pipelines without the need to invoke a shell. +No argument expansion takes place, which ensures all arguments are properly quoted. + +The pipeline is described in familiar shell-syntax: +.br +A | character is placed behind commands whose output should be redirected +as the following command's input. + +By default, command names are resolved automatically using the +.Em PATH +environment variable. The +.Fl x +flag disables this behavior. + +.Sh EXAMPLES + +Build a data processing pipeline from C with clear argument boundaries: + +.Bd -literal -offset 1c +const char *argv[] = {"tmpl", "ls", "|", "grep", "test", NULL} +execv("/bin/tmpl", argv); +.Ed + +.Sh AUTHORS +Written by +.An Louis Burda Aq Mt quent.burda@gmail.com . diff --git a/pipeln.c b/pipeln.c @@ -1,15 +1,19 @@ #include <asm-generic/errno-base.h> #include <linux/limits.h> #include <sys/wait.h> -#include <errno.h> #include <unistd.h> #include <dirent.h> #include <wait.h> -#include <stdio.h> + +#include <errno.h> #include <limits.h> +#include <stdio.h> #include <stdarg.h> #include <string.h> #include <stdlib.h> +#include <stdbool.h> + +static bool resolve_bin = true; static void __attribute__((noreturn)) @@ -54,7 +58,11 @@ run(int *in, int *out, const char **argv) close(out[0]); close(out[1]); } - execvp(argv[0], (char *const *) argv); + if (resolve_bin) { + execvp(argv[0], (char *const *) argv); + } else { + execv(argv[0], (char *const *) argv); + } die("execv %s:", argv[0]); } @@ -91,6 +99,7 @@ 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; @@ -99,7 +108,24 @@ main(int argc, const char **argv) in = NULL; out = pipe2; - cmdargs = argv + 1; + if (argc < 1) return 1; + + invalid = NULL; + cmdargs = NULL; + for (arg = argv + 1; *arg; arg++) { + if (!strcmp(*arg, "--")) { + cmdargs = arg; + break; + } else if (!strcmp(*arg, "-x")) { + resolve_bin = false; + } else { + invalid = *arg; + } + } + if (!cmdargs) die("missing -- separator"); + if (invalid) die("invalid argument '%s'", invalid); + + cmdargs += 1; for (arg = argv + 1; ; arg++) { if (!*arg || !strcmp(*arg, "|")) { /* last cmd goes to stdout */ @@ -115,6 +141,8 @@ main(int argc, const char **argv) /* out => in */ in = out; out = out == pipe1 ? pipe2 : pipe1; + } else if (!strcmp(*arg, "\\|")) { + *arg = "|"; } } }