diff options
author | Joe Hunkeler <jhunkeler@gmail.com> | 2015-08-11 16:51:37 -0400 |
---|---|---|
committer | Joe Hunkeler <jhunkeler@gmail.com> | 2015-08-11 16:51:37 -0400 |
commit | 40e5a5811c6ffce9b0974e93cdd927cbcf60c157 (patch) | |
tree | 4464880c571602d54f6ae114729bf62a89518057 /unix/os/zopdpr.c | |
download | iraf-osx-40e5a5811c6ffce9b0974e93cdd927cbcf60c157.tar.gz |
Repatch (from linux) of OSX IRAF
Diffstat (limited to 'unix/os/zopdpr.c')
-rw-r--r-- | unix/os/zopdpr.c | 201 |
1 files changed, 201 insertions, 0 deletions
diff --git a/unix/os/zopdpr.c b/unix/os/zopdpr.c new file mode 100644 index 00000000..56e97f20 --- /dev/null +++ b/unix/os/zopdpr.c @@ -0,0 +1,201 @@ +/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + */ + +#include <ctype.h> +#include <stdio.h> +#include <signal.h> +#include <fcntl.h> +#include <unistd.h> +#include <sys/time.h> +#include <sys/resource.h> + +#define import_spp +#define import_xwhen +#define import_kernel +#define import_knames +#include <iraf.h> + +#define QUANTUM 6 +#ifdef SYSV +#define vfork fork +#endif + +extern void pr_enter (int pid, int inchan, int outchan); +extern int pr_wait (int pid); +extern void pr_release (int pid); + + +/* ZOPDPR -- Open a detached process. In this implementation detached + * processes begin execution immediately, runing concurrently with the parent. + * "Jobcode" can be anything we want, provided it is unique. Since detached + * processes run concurrently we return the pid of the child as the jobcode. + */ +int +ZOPDPR ( + PKCHAR *osfn, + PKCHAR *bkgfile, + PKCHAR *queue, + XINT *jobcode +) +{ + register char *ip; + register int sum; + int pid, maxforks = 3; + int curpri, priority, delta, neg; + + + /* Check that the process file exists and is executable. + * Check that the background file exists and is readable. + */ + if (access ((char *)osfn, 1) == ERR) { + *jobcode = XERR; + return (XERR); + } else if (access ((char *)bkgfile, 4) == ERR) { + *jobcode = XERR; + return (XERR); + } + + /* Determine priority at which child process is to run. A relative + * priority of -1 lowers the priority by QUANTUM UNIX units (e.g., nices + * the process to 4, 6 or whatever the QUANTUM is). If an absolute + * priority is specified it is used without scaling. + */ +#ifdef SYSV + curpri = nice (0); +#else + curpri = getpriority (PRIO_PROCESS, 0); +#endif + + for (ip=(char *)queue; isspace (*ip); ip++) + ; + if (*ip != EOS) { + if (*ip == '+' || *ip == '-') { + delta = 1; + neg = (*ip++ == '-'); + } else { + delta = 0; + neg = 0; + } + + for (sum=0; isdigit (*ip); ip++) + sum = sum * 10 + *ip - '0'; + if (neg) + sum = -sum; + + } else { + delta = 1; + sum = -1; + } + + if (delta) + priority = curpri - (QUANTUM * sum); + else + priority = sum; + + /* Create child process. Vfork is used to avoid necessity to copy + * the full address space of the parent, since we are going to overlay + * a new process immediately with Execl anyhow. The child inherits + * the open stdio files. The fork can fail if swap space is full or + * if we have too many processes. + */ + while ((pid = vfork()) == ERR) { + if (--maxforks == 0) { + *jobcode = XERR; + return (XERR); + } + sleep (2); + } + + if (pid == 0) { + /* New, child process. + * Arrange for the local file descriptors of the parent to be + * closed in the child if the exec succeeds. IRAF subprocesses + * do not expect to inherit any file descriptors other than + * stdin, stdout, and stderr. + */ + struct rlimit rlim; + int maxfd, fd; + + if (getrlimit (RLIMIT_NOFILE, &rlim)) + maxfd = MAXOFILES; + else + maxfd = rlim.rlim_cur; + + for (fd=3; fd < min(MAXOFILES,maxfd); fd++) + fcntl (fd, F_SETFD, 1); + +#ifdef SYSV + /* nice (0, priority * 2); */ + nice ( priority * 2); +#else + setpriority (PRIO_PROCESS, 0, priority); +#endif + + /* Since we used vfork we share memory with the parent until the + * call to execl(), hence we must not close any files or do + * anything else which would corrupt the parent's data structures. + * Instead, immediately exec the new process (will not return if + * successful). The "-d" flag tells the subprocess that it is a + * detached process. The background file name is passed to the + * child, which reads the file to learn what to do, and deletes + * the file upon exit. + */ + execl ((char *)osfn, (char *)osfn, "-d", (char *)bkgfile, + (char *) 0); + + /* If we get here the new process could not be executed for some + * reason. Shutdown, calling _exit to avoid flushing parent's + * io buffers. Delete bkgfile to tell parent that child has + * terminated. + */ + unlink ((char *)bkgfile); + _exit (1); + + } else { + /* Existing, parent process. + * Save pid in parent's process table. Entry cleared when + * pr_wait is called to wait for process to terminate. + */ + pr_enter (pid, 0, 0); + } + + *jobcode = pid; + + return (XOK); +} + + +/* ZCLDPR -- Close a detached process. If killflag is set interrupt the + * process before waiting for it to die. A detached process will shutdown + * when interrupted, unlike a connected subprocess which merely processes + * the interrupt and continues execution. The process itself deletes the + * bkgfile before exiting. + */ +int +ZCLDPR ( + XINT *jobcode, + XINT *killflag, + XINT *exit_status +) +{ + int pid = *jobcode; + + + /* If killing process do not wait for it to die. + */ + if (*killflag == XYES) { + if (kill (pid, SIGTERM) == ERR) { + *exit_status = XERR; + return (XERR); + } else { + pr_release (pid); + *exit_status = X_INT; + return (*exit_status); + } + } + + if ((*exit_status = pr_wait (pid)) == ERR) + *exit_status = XERR; + + return (*exit_status); +} |