about summary refs log tree commit diff
path: root/lib/libsystem.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libsystem.c')
-rw-r--r--lib/libsystem.c204
1 files changed, 179 insertions, 25 deletions
diff --git a/lib/libsystem.c b/lib/libsystem.c
index ba48ed85..332cc5e2 100644
--- a/lib/libsystem.c
+++ b/lib/libsystem.c
@@ -40,8 +40,8 @@
 
 
 static void
-closeUninheritableFds(int const stdinFd,
-                      int const stdoutFd) {
+closeUninheritableFds(int const keepFdA,
+                      int const keepFdB) {
 /*----------------------------------------------------------------------------
   Close all the file descriptors that we declare uninheritable -- files Parent
   has open that Child has no business accessing.
@@ -49,14 +49,21 @@ closeUninheritableFds(int const stdinFd,
   Closing an extra file descriptor is essential to allow the file to close
   when Parent closes it.
 
+  It is also essential to prevent the system from messing with the position of
+  the file as the child process exits.  If the file descriptor is backing a
+  stream (FILE *), some process-exit code seeks the file to the current stream
+  position (from the readahead position), but having the file descriptor
+  closed defeats that.
+
   We define uninheritable as less than 64 and not Standard Input, Output,
-  or Error, or 'stdinFd' or 'stdoutFd'.
+  or Error, or 'keepFdA' or 'keepFdB'.
 -----------------------------------------------------------------------------*/
     int fd;
 
     for (fd = 0; fd < 64; ++fd) {
-        if (fd == stdinFd) {
-        } else if (fd == stdoutFd) {
+        if (false) {
+        } else if (fd == keepFdA) {
+        } else if (fd == keepFdB) {
         } else if (fd == STDIN_FILENO) {
         } else if (fd == STDOUT_FILENO) {
         } else if (fd == STDERR_FILENO) {
@@ -148,6 +155,9 @@ createPipeFeeder(void          pipeFeederRtn(int, void *),
     } else if (rc == 0) {
         /* This is the child -- the stdin feeder process */
         close(pipeToFeed[0]);
+
+        closeUninheritableFds(pipeToFeed[1], pipeToFeed[1]);
+
         (*pipeFeederRtn)(pipeToFeed[1], feederParm);
         exit(0);
     } else {
@@ -513,10 +523,7 @@ pm_system2_lp(const char *    const progName,
 
     va_start(args, termStatusP);
 
-    endOfArgs = FALSE;
-    argArray = NULL;
-
-    for (endOfArgs = FALSE, argArray = NULL, n = 0;
+    for (endOfArgs = false, argArray = NULL, n = 0;
          !endOfArgs;
         ) {
         const char * const arg = va_arg(args, const char *);
@@ -526,7 +533,7 @@ pm_system2_lp(const char *    const progName,
         argArray[n++] = arg;
 
         if (!arg)
-            endOfArgs = TRUE;
+            endOfArgs = true;
     }
 
     va_end(args);
@@ -618,9 +625,6 @@ pm_system_lp(const char *    const progName,
 
     va_start(args, accepterParm);
 
-    endOfArgs = FALSE;
-    argArray = NULL;
-
     for (endOfArgs = FALSE, argArray = NULL, n = 0;
          !endOfArgs;
         ) {
@@ -631,7 +635,7 @@ pm_system_lp(const char *    const progName,
         argArray[n++] = arg;
 
         if (!arg)
-            endOfArgs = TRUE;
+            endOfArgs = true;
     }
 
     va_end(args);
@@ -680,7 +684,7 @@ pm_feed_null(int    const pipeToFeedFd,
 
 
 void
-pm_accept_null(int    const pipetosuckFd,
+pm_accept_null(int    const pipeToSuckFd,
                void * const accepterParm ) {
 
     size_t const bufferSize = 4096;
@@ -695,7 +699,7 @@ pm_accept_null(int    const pipetosuckFd,
         for (eof = false; !eof; ) {
             ssize_t rc;
 
-            rc = read(pipetosuckFd, buffer, bufferSize);
+            rc = read(pipeToSuckFd, buffer, bufferSize);
 
             if (rc < 0) {
                 /* No way to report the problem; just say we're done */
@@ -706,7 +710,7 @@ pm_accept_null(int    const pipetosuckFd,
         }
         free(buffer);
     }
-    close(pipetosuckFd);
+    close(pipeToSuckFd);
 }
 
 
@@ -719,16 +723,16 @@ pm_feed_from_memory(int    const pipeToFeedFd,
 
     FILE * const outFileP = fdopen(pipeToFeedFd, "w");
 
-    size_t bytesTransferred;
+    size_t byteCtTransferred;
 
     /* The following signals (and normally kills) the process with
        SIGPIPE if the pipe does not take all 'size' bytes.
     */
-    bytesTransferred =
+    byteCtTransferred =
         fwrite(inputBufferP->buffer, 1, inputBufferP->size, outFileP);
 
     if (inputBufferP->bytesTransferredP)
-        *(inputBufferP->bytesTransferredP) = bytesTransferred;
+        *(inputBufferP->bytesTransferredP) = byteCtTransferred;
 
     fclose(outFileP);
 }
@@ -736,23 +740,173 @@ pm_feed_from_memory(int    const pipeToFeedFd,
 
 
 void
-pm_accept_to_memory(int             const pipetosuckFd,
+pm_accept_to_memory(int             const pipeToSuckFd,
                     void *          const accepterParm ) {
 
     pm_bufferDesc * const outputBufferP = accepterParm;
 
-    FILE * const inFileP = fdopen(pipetosuckFd, "r");
+    FILE * const inFileP = fdopen(pipeToSuckFd, "r");
 
-    size_t bytesTransferred;
+    size_t byteCtTransferred;
 
-    bytesTransferred =
+    byteCtTransferred =
         fread(outputBufferP->buffer, 1, outputBufferP->size, inFileP);
 
     fclose(inFileP);
 
     if (outputBufferP->bytesTransferredP)
-        *(outputBufferP->bytesTransferredP) = bytesTransferred;
+        *(outputBufferP->bytesTransferredP) = byteCtTransferred;
 }
 
 
 
+void
+pm_feed_from_file(int    const pipeToFeedFd,
+                  void * const feederParm) {
+
+    const char * const inFileNm = feederParm;
+
+    size_t const bufferSz = 64*1024;
+
+    FILE * const outFileP = fdopen(pipeToFeedFd, "w");
+
+    FILE * inFileP;
+    unsigned char * buffer;
+    bool eof;
+
+    inFileP = pm_openr(inFileNm);
+
+    MALLOCARRAY(buffer, bufferSz);
+
+    if (!buffer)
+        pm_error("Failed to allocate %u bytes for I/O buffer",
+                 (unsigned) bufferSz);
+
+    for (eof = false; !eof; ) {
+        size_t byteCtRead;
+
+        byteCtRead = fread(buffer, 1, bufferSz, inFileP);
+
+        if (ferror(inFileP))
+            pm_error("Error reading file.  errno=%d (%s)",
+                     errno, strerror(errno));
+
+        if (byteCtRead > 0) {
+            /* The following signals (and normally kills) the process with
+               SIGPIPE if the pipe does not take all 'size' bytes.
+            */
+            fwrite(buffer, 1, byteCtRead, outFileP);
+        } else
+            eof = true;
+    }
+
+    pm_close(inFileP);
+    fclose(outFileP);
+
+    free(buffer);
+}
+
+
+
+void
+pm_accept_to_file(int             const pipeToSuckFd,
+                  void *          const accepterParm ) {
+
+    const char * const outFileNm = accepterParm;
+
+    size_t const bufferSz = 64*1024;
+
+    FILE * const inFileP = fdopen(pipeToSuckFd, "r");
+
+    FILE * outFileP;
+    unsigned char * buffer;
+    bool eof;
+
+    outFileP = pm_openw(outFileNm);
+
+    MALLOCARRAY(buffer, bufferSz);
+
+    if (!buffer)
+        pm_error("Failed to allocate %u bytes for I/O buffer",
+                 (unsigned) bufferSz);
+
+    for (eof = false; !eof; ) {
+        size_t byteCtRead;
+
+        byteCtRead = fread(buffer, 1, bufferSz, inFileP);
+
+        if (ferror(inFileP))
+            pm_error("Error reading Standard Output accepter pipe.  "
+                     "errno=%d (%s)",
+                     errno, strerror(errno));
+
+        if (byteCtRead > 0) {
+            fwrite(buffer, 1, byteCtRead, outFileP);
+
+            if (ferror(outFileP))
+                pm_error("Error writing to file.  errno=%d (%s)",
+                         errno, strerror(errno));
+        } else
+            eof = true;
+    }
+
+    pm_close(outFileP);
+    fclose(inFileP);
+
+    free(buffer);
+}
+
+
+
+/* Note that pm_feed_from_filestream is not possible because Standard Input is
+   feed by a child process and we can't properly pass a FILE * to a child
+   process.
+*/
+
+
+
+void
+pm_accept_to_filestream(int             const pipeToSuckFd,
+                        void *          const accepterParm ) {
+
+    FILE * const outFileP = accepterParm;
+
+    size_t const bufferSz = 64*1024;
+
+    FILE * const inFileP = fdopen(pipeToSuckFd, "r");
+
+    unsigned char * buffer;
+    bool eof;
+
+    MALLOCARRAY(buffer, bufferSz);
+
+    if (!buffer)
+        pm_error("Failed to allocate %u bytes for I/O buffer",
+                 (unsigned) bufferSz);
+
+    for (eof = false; !eof; ) {
+        size_t byteCtRead;
+
+        byteCtRead = fread(buffer, 1, bufferSz, inFileP);
+
+        if (ferror(inFileP))
+            pm_error("Error reading Standard Output accepter pipe.  "
+                     "errno=%d (%s)",
+                     errno, strerror(errno));
+
+        if (byteCtRead > 0) {
+            fwrite(buffer, 1, byteCtRead, outFileP);
+
+            if (ferror(outFileP))
+                pm_error("Error writing to file.  errno=%d (%s)",
+                         errno, strerror(errno));
+        } else
+            eof = true;
+    }
+
+    fclose(inFileP);
+
+    free(buffer);
+}
+
+