diff options
Diffstat (limited to 'converter/other/pnmtops.c')
-rw-r--r-- | converter/other/pnmtops.c | 73 |
1 files changed, 65 insertions, 8 deletions
diff --git a/converter/other/pnmtops.c b/converter/other/pnmtops.c index 1d0a44f7..e1f2d185 100644 --- a/converter/other/pnmtops.c +++ b/converter/other/pnmtops.c @@ -42,6 +42,8 @@ #include <unistd.h> #include <assert.h> #include <string.h> +#include <errno.h> +#include <signal.h> #ifndef NOFLATE #include <zlib.h> #endif @@ -52,6 +54,37 @@ #include "shhopt.h" #include "nstring.h" + + +static void +setSignals() { +/*---------------------------------------------------------------------------- + Set up the process-global signal-related state. + + Note that we can't rely on defaults, because much of this is inherited + from the process that forked and exec'ed this program. +-----------------------------------------------------------------------------*/ + /* See waitForChildren() for why we do this to SIGCHLD */ + + struct sigaction sigchldAction; + int rc; + sigset_t emptySet; + + sigemptyset(&emptySet); + + sigchldAction.sa_handler = SIG_DFL; + sigchldAction.sa_mask = emptySet; + sigchldAction.sa_flags = SA_NOCLDSTOP; + + rc = sigaction(SIGCHLD, &sigchldAction, NULL); + + if (rc != 0) + pm_error("sigaction() to set up signal environment failed, " + "errno = %d (%s)", errno, strerror(errno)); +} + + + struct cmdlineInfo { /* All the information the user supplied in the command line, in a form easy for the program to use. @@ -351,6 +384,17 @@ writeFile(const unsigned char * const buffer, +static void +writeFileChar(const char * const buffer, + size_t const writeCt, + const char * const name, + FILE * const ofP) { + + writeFile((const unsigned char *)buffer, writeCt, name, ofP); +} + + + #define MAX_FILTER_CT 10 /* The maximum number of filters this code is capable of applying */ @@ -558,8 +602,10 @@ rlePutBuffer (unsigned int const repeat, if (repeat) { fputc(257 - count, fP); fputc(repeatitem, fP); - } else + } else { + fputc(count - 1, fP); writeFile(itembuf, count, "rlePutBuffer", fP); + } } @@ -736,7 +782,8 @@ ascii85Filter(FILE * const ifP, ++count; if (value == 0 && count == 4) { - putchar('z'); /* Ascii85 encoding z exception */ + writeFileChar("z", 1, "ASCII 85 filter", ofP); + /* Ascii85 encoding z exception */ ++outcount; count = 0; } else if (count == 4) { @@ -746,15 +793,14 @@ ascii85Filter(FILE * const ifP, outbuff[1] = value % 85 + 33; outbuff[0] = value / 85 + 33; - writeFile((const unsigned char *)outbuff, count + 1, - "ASCII 85 filter", ofP); + writeFileChar(outbuff, count + 1, "ASCII 85 filter", ofP); count = value = 0; outcount += 5; } if (outcount > 75) { - putchar('\n'); + writeFileChar("\n", 1, "ASCII 85 filter", ofP); outcount = 0; } } @@ -770,8 +816,7 @@ ascii85Filter(FILE * const ifP, outbuff[0] = value / 85 + 33; outbuff[count + 1] = '\n'; - writeFile((const unsigned char *)outbuff, count + 2, - "ASCII 85 filter", ofP); + writeFileChar(outbuff, count + 2, "ASCII 85 filter", ofP); } fclose(ifP); @@ -966,6 +1011,15 @@ waitForChildren(const pid_t * const pidList) { Wait for all child processes with PIDs in pidList[] to exit. In pidList[], end-of-list is marked with a special zero value. -----------------------------------------------------------------------------*/ + /* There's an odd behavior in Unix such that if you have set the + action for SIGCHLD to ignore the signal (even though ignoring the + signal is the default), the process' children do not become + zombies. Consequently, waitpid() always fails with ECHILD - but + nonetheless waits for the child to exit. + + We expect the process not to have the action for SIGCHLD set that + way. + */ unsigned int i; for (i = 0; pidList[i]; ++i) { @@ -977,7 +1031,8 @@ waitForChildren(const pid_t * const pidList) { rc = waitpid(pidList[i], &status, 0); if (rc == -1) - pm_error ("waitpid() for child %u failed", i); + pm_error ("waitpid() for child %u failed, errno=%d (%s)", + i, errno, strerror(errno)); else if (status != EXIT_SUCCESS) pm_error ("Child process %u terminated abnormally", i); } @@ -2011,6 +2066,8 @@ main(int argc, const char * argv[]) { pm_proginit(&argc, argv); + setSignals(); + parseCommandLine(argc, argv, &cmdline); verbose = cmdline.verbose; |