[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, &regex_mode, RUNPARTS_LSBSYSINIT},
       {"regex", 1, &regex_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.

Reply via email to