[2019-08-16 17:35] Clint Adams <cl...@debian.org> > On Thu, Aug 15, 2019 at 09:24:46PM +0000, 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 <kact...@debian.org> Date: Sat, 17 Aug 2019 05:38:10 +0000 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 <stdio.h> #include <stdarg.h> @@ -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" " --lsbsysinit validate 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, &set, 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, ®ex_mode, RUNPARTS_LSBSYSINIT}, {"regex", 1, ®ex_mode, RUNPARTS_ERE}, + {"stdin", 0, &stdin_mode, 1}, {"exit-on-error", 0, &exit_on_error_mode, 1}, {"new-session", 0, &new_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.