summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLouis Burda <quent.burda@gmail.com>2024-02-18 17:26:52 +0100
committerLouis Burda <quent.burda@gmail.com>2024-02-18 17:26:52 +0100
commit25aef9010259cf14d0b9a138cbadc13740feaff5 (patch)
tree15a9bc6e29931cd9bfaa7282d33db2e4179384a1
parent9e4b252a5bbe1f8bf829af85c76cfb1e89c55c7e (diff)
downloadpipeln-25aef9010259cf14d0b9a138cbadc13740feaff5.tar.gz
pipeln-25aef9010259cf14d0b9a138cbadc13740feaff5.zip
Add manpage, README and flag to disable binary resolving
-rw-r--r--README35
-rw-r--r--pipeln.146
-rw-r--r--pipeln.c36
3 files changed, 113 insertions, 4 deletions
diff --git a/README b/README
new file mode 100644
index 0000000..b0d5519
--- /dev/null
+++ 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
new file mode 100644
index 0000000..939c24a
--- /dev/null
+++ 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
index b4ba876..71f3ff2 100644
--- 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 = "|";
}
}
}