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:
M | Makefile | | | 8 | +++++++- |
M | pipeln.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 = "|";
}