diff options
-rw-r--r-- | GNUmakefile | 5 | ||||
-rw-r--r-- | lib/libpm.c | 99 | ||||
-rw-r--r-- | lib/pm.h | 15 |
3 files changed, 113 insertions, 6 deletions
diff --git a/GNUmakefile b/GNUmakefile index 4b01cec2..780ec870 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -150,6 +150,11 @@ ifeq ($(HAVE_INT64),Y) else echo "#define HAVE_INT64 0" >>$@ endif +ifeq ($(DONT_HAVE_PROCESS_MGMT),Y) + echo "#define HAVE_FORK 0" >>$@ +else + echo "#define HAVE_FORK 1" >>$@ +endif echo '/* pm_config.h.in FOLLOWS ... */' >>$@ cat $(SRCDIR)/pm_config.in.h >>$@ $(ENDIANGEN) >>$@ diff --git a/lib/libpm.c b/lib/libpm.c index 1089da3c..099d4bf7 100644 --- a/lib/libpm.c +++ b/lib/libpm.c @@ -10,6 +10,9 @@ #define _XOPEN_SOURCE 500 /* Make sure ftello, fseeko are defined */ +#include "netpbm/pm_config.h" + +#include <assert.h> #include <unistd.h> #include <stdio.h> #include <stdarg.h> @@ -18,15 +21,19 @@ #include <setjmp.h> #include <time.h> #include <limits.h> +#if HAVE_FORK +#include <sys/wait.h> +#endif +#include <sys/types.h> -#include "pm_c_util.h" -#include "mallocvar.h" -#include "version.h" +#include "netpbm/pm_c_util.h" +#include "netpbm/mallocvar.h" +#include "netpbm/version.h" +#include "netpbm/nstring.h" +#include "netpbm/shhopt.h" #include "compile.h" -#include "nstring.h" -#include "shhopt.h" -#include "pm.h" +#include "netpbm/pm.h" /* The following are set by pm_init(), then used by subsequent calls to other pm_xxx() functions. @@ -95,6 +102,86 @@ pm_longjmp(void) { void +pm_fork(int * const iAmParentP, + pid_t * const childPidP, + const char ** const errorP) { +/*---------------------------------------------------------------------------- + Same as POSIX fork, except with a nicer interface and works + (fails cleanly) on systems that don't have POSIX fork(). +-----------------------------------------------------------------------------*/ +#if HAVE_FORK + int rc; + + rc = fork(); + + if (rc < 0) { + asprintfN(errorP, "Failed to fork a process. errno=%d (%s)", + errno, strerror(errno)); + } else { + *errorP = NULL; + + if (rc == 0) { + *iAmParentP = FALSE; + } else { + *iAmParentP = TRUE; + *childPidP = rc; + } + } +#else + asprintfN(errorP, "Cannot fork a process, because this system does " + "not have POSIX fork()"); +#endif +} + + + +void +pm_waitpid(pid_t const pid, + int * const statusP, + int const options, + pid_t * const exitedPidP, + const char ** const errorP) { + +#if HAVE_FORK + pid_t rc; + rc = waitpid(pid, statusP, options); + if (rc == (pid_t)-1) { + asprintfN(errorP, "Failed to wait for process exit. " + "waitpid() errno = %d (%s)", + errno, strerror(errno)); + } else { + *exitedPidP = rc; + *errorP = NULL; + } +#else + pm_error("INTERNAL ERROR: Attempt to wait for a process we created on " + "a system on which we can't create processes"); +#endif +} + + + +void +pm_waitpidSimple(pid_t const pid) { + + int status; + pid_t exitedPid; + const char * error; + + pm_waitpid(pid, &status, 0, &exitedPid, &error); + + if (error) { + pm_errormsg("%s", error); + strfree(error); + pm_longjmp(); + } else { + assert(exitedPid != 0); + } +} + + + +void pm_setusererrormsgfn(pm_usererrormsgfn * fn) { userErrorMsgFn = fn; diff --git a/lib/pm.h b/lib/pm.h index 4ba20aa5..55ea4f29 100644 --- a/lib/pm.h +++ b/lib/pm.h @@ -164,6 +164,21 @@ pm_setjmpbufsave(jmp_buf * const jmpbufP, void pm_longjmp(void); +void +pm_fork(int * const iAmParentP, + pid_t * const childPidP, + const char ** const errorP); + +void +pm_waitpid(pid_t const pid, + int * const statusP, + int const options, + pid_t * const exitedPidP, + const char ** const errorP); + + +void +pm_waitpidSimple(pid_t const pid); typedef void pm_usermessagefn(const char * msg); |