[2019-08-16 17:35] Clint Adams
> On Thu, Aug 15, 2019 at 09:24:46PM +, Dmitry Bogatov wrote:
> > I want this feature too. Dear maintainer, are you interested? Will you
> > accept patch?
>
> Sure. Would you read all of stdin into memory or would you
> do something else?
I use temporary file. Do you foresee problems with it? Here is patch.
Note, it uses Linux-only (I believe) O_TMPFILE. I can make it
posix-compliant if you want.
From 0d5c423d5305092be9b28cc3dcd55604af24827d Mon Sep 17 00:00:00 2001
From: Dmitry Bogatov
Date: Sat, 17 Aug 2019 05:38:10 +
Subject: [PATCH] run-parts: add option to multiplex stdin for children
Closes: #719692
---
run-parts.c | 71 +
1 file changed, 71 insertions(+)
diff --git a/run-parts.c b/run-parts.c
index 9a80229..64022f8 100644
--- a/run-parts.c
+++ b/run-parts.c
@@ -11,6 +11,7 @@
* Based on run-parts.pl version 0.2, Copyright (C) 1994 Ian Jackson.
*
*/
+#define _GNU_SOURCE
#include
#include
@@ -44,6 +45,9 @@ int exitstatus = 0;
int regex_mode = 0;
int exit_on_error_mode = 0;
int new_session_mode = 0;
+int stdin_mode = 0;
+int stdin_fd = -1; // initialized in run_parts() if {stdin_mode} != 0
+
int argcount = 0, argsize = 0;
char **args = 0;
@@ -95,6 +99,7 @@ void usage()
" --reverse reverse execution order of scripts.\n"
" --exit-on-error exit as soon as a script returns with a
non-zero exit\n"
" code.\n"
+ " --stdin multiplex stdin to scripts being run, using
temporary file\n"
" --lsbsysinitvalidate filenames based on LSB sysinit
specs.\n"
" --new-session run each script in a separate process
session\n"
" --regex=PATTERN validate filenames based on POSIX ERE pattern
PATTERN.\n"
@@ -184,6 +189,17 @@ void run_part(char *progname)
restore_signals();
if (new_session_mode)
setsid();
+
+if (stdin_mode) {
+ if (dup2(stdin_fd, STDIN_FILENO) == -1) {
+error("dup2: %s", strerror(errno));
+exit(1);
+ }
+ if (lseek(STDIN_FILENO, 0, SEEK_SET) == (off_t) -1) {
+error("run-parts: failed to rewind temporary file: %s\n",
strerror(errno));
+exit(1);
+ }
+}
if (report_mode) {
if (dup2(pout[1], STDOUT_FILENO) == -1 ||
dup2(perr[1], STDERR_FILENO) == -1) {
@@ -370,6 +386,52 @@ static void restore_signals()
sigprocmask(SIG_UNBLOCK, , NULL);
}
+/*
+ * Copy stdin into temporary read-write file, and return file descriptor to it.
+ */
+static int copy_stdin(void)
+{
+ int fd;
+ const char *tmpdir;
+ char buffer[4096];
+ ssize_t bytes;
+
+ tmpdir = getenv("TMPDIR");
+ if (!tmpdir) {
+tmpdir = "/tmp";
+ };
+
+ fd = open(tmpdir, O_TMPFILE|O_RDWR|O_EXCL, S_IRUSR | S_IWUSR);
+ if (fd < 0) {
+return -1;
+ };
+
+ do {
+ssize_t rest;
+
+bytes = rest = read(STDIN_FILENO, buffer, sizeof(buffer));
+if (bytes < 0) {
+ error("run-parts: failed to read from stdin\n");
+ close(fd);
+ return -1;
+}
+
+while (rest > 0) {
+ ssize_t written;
+
+ written = write(fd, buffer, rest);
+ if (written < 0) {
+error("run-parts: failed to write to temporary file\n");
+close(fd);
+return -1;
+ }
+ rest -= written;
+}
+ } while (bytes > 0);
+
+ return fd;
+}
+
/* Find the parts to run & call run_part() */
void run_parts(char *dirname)
{
@@ -397,6 +459,14 @@ void run_parts(char *dirname)
exit(1);
}
+ if (stdin_mode) {
+stdin_fd = copy_stdin();
+if (stdin_fd < 0) {
+ error("run-parts: failed to copy content of stdin\n");
+ exit(1);
+}
+ }
+
i = reverse_mode ? 0 : entries;
for (i = reverse_mode ? (entries - 1) : 0;
reverse_mode ? (i >= 0) : (i < entries); reverse_mode ? i-- : i++) {
@@ -497,6 +567,7 @@ int main(int argc, char *argv[])
{"version", 0, 0, 'V'},
{"lsbsysinit", 0, _mode, RUNPARTS_LSBSYSINIT},
{"regex", 1, _mode, RUNPARTS_ERE},
+ {"stdin", 0, _mode, 1},
{"exit-on-error", 0, _on_error_mode, 1},
{"new-session", 0, _session_mode, 1},
{0, 0, 0, 0}
--
Note, that I send and fetch email in batch, once in a few days.
Please, mention in body of your reply when you add or remove recepients.