From 40e5a5811c6ffce9b0974e93cdd927cbcf60c157 Mon Sep 17 00:00:00 2001 From: Joe Hunkeler Date: Tue, 11 Aug 2015 16:51:37 -0400 Subject: Repatch (from linux) of OSX IRAF --- unix/os/prwait.c | 175 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 175 insertions(+) create mode 100644 unix/os/prwait.c (limited to 'unix/os/prwait.c') diff --git a/unix/os/prwait.c b/unix/os/prwait.c new file mode 100644 index 00000000..381d87b1 --- /dev/null +++ b/unix/os/prwait.c @@ -0,0 +1,175 @@ +/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + */ + +#include +#include + +#define import_kernel +#define import_knames +#define import_spp +#include + +/* Process table code. The high level code assumes that it can open and close + * processes in any order. The UNIX "wait" primitive, called when a process is + * closed, returns the process status and pid of the first process to exit. + * Hence several calls to wait may be necessary to wait for a given process to + * exit. We hide all this behind the pr_wait call, which waits for a PARTICULAR + * process to exit and returns its exit status. + * + * NOT INTERFACE PROCEDURES. This code is only called internally by other + * kernel procedures. All primitives which execute subprocesses, i.e., ZOPCPR, + * ZOPDPR, ZOSCMD, etc. must call these routines. + */ + +struct proctable { + int pr_pid; /* process id */ + int pr_active; /* if YES, process is still active */ + int pr_inchan; /* input IPC channel */ + int pr_outchan; /* output IPC channel */ + int pr_exit_status; /* process exit_status */ +} prtable[MAXPROCS]; + +extern int errno; + +#ifdef MACOSX +#define POSIX +#endif + + +/* PR_ENTER -- Make a new entry in the process table. Something is very wrong + * if the table overflows. + */ +void +pr_enter (int pid, int inchan, int outchan) +{ + register struct proctable *pr; + struct proctable *pr_findpid(); + + extern int kernel_panic (char *msg); + + + if ((pr = pr_findpid (NULL)) == NULL) + kernel_panic ("iraf process table overflow"); + else { + pr->pr_pid = pid; + pr->pr_active = YES; + pr->pr_inchan = inchan; + pr->pr_outchan = outchan; + } +} + + +/* PR_WAIT -- Wait for the process associated with the given pid to terminate + * and return it's exit status. If there is no such process in the table + * return ERR. The table entry is cleared by this call. + */ +int +pr_wait (int pid) +{ + register struct proctable *pr; + int error_code; + pid_t waitpid; + struct proctable *pr_findpid(); +#ifdef POSIX + int exit_status; +#else + union wait exit_status; +#endif + + + /* Lookup process in table. Return ERR if there is no entry. + */ + if ((pr = pr_findpid (pid)) == NULL) + return (ERR); + + if (pr->pr_active == NO) { + /* Process has already terminated. Clear table entry and return + * exit status (set in a previous call). + */ + pr->pr_pid = (int) 0; + return (pr->pr_exit_status); + + } else { + /* Process is in table but has not yet terminated. Call wait until + * the process exits. If other processes exit in the meantime + * save their exit status in the table and mark them inactive. + * If an unknown process terminates ignore it; this will happen + * when a killed bkg process terminates after its process slot + * has been released. + */ + while ((waitpid = wait (&exit_status)) != ERR) { + if ((pr = pr_findpid (waitpid)) != NULL) { + pr->pr_active = NO; + + /* The integer argument to exit() is returned in the + * wait struct defined in . + */ +#ifdef POSIX + error_code = WEXITSTATUS(exit_status); +#else + error_code = exit_status.w_T.w_Retcode; +#endif + pr->pr_exit_status = error_code ? error_code : XOK; + + if (waitpid == pid) { + pr->pr_pid = (int) 0; + return (pr->pr_exit_status); + } + } + } + return (ERR); + } +} + + +/* PR_GETIPC -- Get the codes for the IPC channels assigned to a process. + */ +int +pr_getipc (int pid, int *inchan, int *outchan) +{ + register struct proctable *pr; + struct proctable *pr_findpid(); + + + /* Lookup process in table. Return ERR if there is no entry. + */ + if ((pr = pr_findpid (pid)) == NULL) + return (ERR); + else { + *inchan = pr->pr_inchan; + *outchan = pr->pr_outchan; + return (pid); + } +} + + +/* PR_FINDPID -- Search the process table for a process. NULL is returned if + * the process cannot be found, otherwise a pointer to the table entry is + * returned. + */ +struct proctable * +pr_findpid (int pid) +{ + register int pr; + + + for (pr=0; pr < MAXPROCS; pr++) { + if (prtable[pr].pr_pid == pid) + return (&prtable[pr]); + } + + return (NULL); +} + + +/* PR_RELEASE -- Release the table entry for the process. Used when a process + * is killed and we do not wish to wait for process termination. + */ +void +pr_release (int pid) +{ + register struct proctable *pr; + + if ((pr = pr_findpid (pid)) != NULL) + pr->pr_pid = (int) 0; +} -- cgit