diff options
Diffstat (limited to 'lib/libsystem.c')
-rw-r--r-- | lib/libsystem.c | 204 |
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); +} + + |