home *** CD-ROM | disk | FTP | other *** search
- /****************************************************************************
- *
- * $Source: /unixb/home/unixlib/source/unixlib37/src/sys/c/RCS/vfork,v $
- * $Date: 1996/10/30 21:59:00 $
- * $Revision: 1.4 $
- * $State: Rel $
- * $Author: unixlib $
- *
- * $Log: vfork,v $
- * Revision 1.4 1996/10/30 21:59:00 unixlib
- * Massive changes made by Nick Burret and Peter Burwood.
- *
- * Revision 1.3 1996/07/21 22:12:31 unixlib
- * CL_0001 Nick Burret
- * Improve memory handling. Remove C++ library incompatibilities.
- * Improve file stat routines.
- *
- * Revision 1.2 1996/05/06 09:03:14 unixlib
- * Updates to sources made by Nick Burrett, Peter Burwood and Simon Callan.
- * Saved for 3.7a release.
- *
- * Revision 1.1 1996/04/19 21:34:24 simon
- * Initial revision
- *
- ***************************************************************************/
-
- static const char rcs_id[] = "$Id: vfork,v 1.4 1996/10/30 21:59:00 unixlib Rel $";
-
- #include <errno.h>
- #include <string.h>
- #include <stdlib.h>
- #include <setjmp.h>
- #include <limits.h>
-
- #include <termio.h>
- #include <unistd.h>
-
- #include <sys/unix.h>
- #include <sys/syslib.h>
- #include <sys/param.h>
- #include <sys/debug.h>
- #include <sys/wait.h>
- #include <sys/swis.h>
-
- #ifdef DEBUG
- #include <stdio.h>
- #endif
-
- /* vfork is similar to fork.
-
- fork makes a complete copy of the calling proces's address space
- and allows both the parent and child to execute independently.
- vfork does not make this copy.
-
- A child process created with vfork shares its parent's address
- space until it calls exit or one of the exec functions. In the
- meantime, the parent process suspends execution. */
-
- int *
- __vfork (void)
- {
- register struct proc *u = 0;
- register int argc;
- register char **argv = 0;
- register char *argb = 0;
- register int i;
- int regs[10];
-
- #ifdef DEBUG
- __debug ("vfork() entered <- parent");
- #endif
-
- if (!(u = malloc (sizeof (struct proc))))
- goto nomem;
- if (!(argv = malloc (sizeof (int) * (4 * MAXCOMMANDLEN >> 2))))
- goto nomem;
- if (!(argb = malloc (4 * MAXCOMMANDLEN)))
- goto nomem;
-
- memcpy (u, __u, sizeof (struct proc));
-
- /* Copy the parent structure proc for the child process.
- Create a unique ID number for the child. Reading the
- monotonic clock should be okay. */
- os_swi (OS_ReadMonotonicTime, regs);
- u->ppid = u->pid;
- u->pid = regs[0];
- u->pproc = __u;
- /* For the time being, the child process will have the same
- priority as the parent process. */
- u->ppri = __u->ppri;
- u->gpri = __u->gpri;
- u->upri = __u->upri;
- /* Reset the resource usage statistics. */
- memset (&u->usage, 0, sizeof (struct rusage));
- memset (&u->status, 0, sizeof (struct __process));
- memset (&u->sigstate, 0, sizeof (struct unixlib_sigstate));
-
- /* A child process always inherits the signals blocked by the
- parent process. */
- u->sigstate.blocked = __u->sigstate.blocked;
- u->status.tty_type = TTY_CON;
-
- /* Copy over the command line arguments. */
- {
- register char *s1, *s2;
-
- argc = u->argc;
- s2 = argb;
-
- for (i = 0; i < argc; i++)
- {
- argv[i] = s2;
- s1 = u->argv[i];
- while (*s2++ = *s1++);
- }
- argv[i] = 0;
- }
- u->argv = argv;
- u->argb = argb;
- /* Copy over the file descriptors. */
- {
- register int v = (char *) u - (char *) __u;
-
- for (i = 0; i < MAXFD; i++)
- if (u->file[i].dup)
- u->file[i].dup = (void *) ((char *) u->file[i].dup + v);
- }
-
- /* Say that we are a child process to some lucky parent. */
- u->status.has_parent = 1;
- __u = u;
-
- #ifdef DEBUG
- __debug ("vfork() -> child");
- #endif
-
- /* This will now return back to vfork(), with register a1 pointing
- to a jmpbuf which will then be setup by setjmp(). */
- return (u->vreg);
-
- nomem:
-
- if (argb)
- free (argb);
- if (argv)
- free (argv);
- if (u)
- free (u);
-
- errno = ENOMEM;
-
- return (0);
- }
-
- int *
- __vexit (int e)
- {
- register struct proc *u = __u;
- register char **argv = u->argv;
- register char *argb = u->argb;
- register int i, j;
-
- #ifdef DEBUG
- __debug ("__vexit() entered <- child");
- #endif
-
- /* Stop any interval timers, just in case. */
- __stop_itimers ();
-
- /* Store the return code, then analyze it, setting various
- bits in the process's status. */
- u->status.return_code = (__WIFEXITED(e)) ? __WEXITSTATUS(e) : 0;
- if (__WIFSIGNALED(e))
- {
- u->status.signal_exit = 1;
- u->status.signal = __WTERMSIG(e);
- }
- u->status.core_dump = __WCOREDUMP(e);
-
- /* Close the file descriptors we used. */
- for (i = 0; i < MAXFD; i++)
- if (u->file[i].dup)
- close (i);
-
- #ifdef DEBUG
- __debug ("__vexit() <- child (close())");
- os_print ("__vexit() e = ");
- os_prhex (e);
- os_print ("\r\n");
- os_print ("return code = "); os_prhex (u->status.return_code); os_print ("\r\n");
- os_print ("signal exit = "); os_prhex (u->status.signal_exit); os_print ("\r\n");
- os_print ("signal = "); os_prhex (u->status.signal); os_print ("\r\n");
- os_print ("core dumped = "); os_prhex (u->status.core_dump); os_print ("\r\n");
- #endif
-
- __u = u->pproc;
- #if 0
- i = __find_free_child ();
- if (i != -1)
- {
- /* Copy over child structure data we will need to remember
- for the wait functions. */
- #endif
- __u->child[0].pid = u->pid;
- __u->child[0].uid = u->uid;
- __u->child[0].gid = u->gid;
- __u->child[0].ppri = u->ppri;
- __u->child[0].upri = u->upri;
- __u->child[0].gpri = u->gpri;
- __u->child[0].usage = u->usage;
- __u->child[0].status = u->status;
-
- for (j = 0; j < __JMP_BUF_SIZE; j++)
- __u->child[0].vreg[j] = u->vreg[j];
- __u->child[0].vreg[13] = u->pid;
-
- #if 0
- }
- #endif
-
- free (argb);
- free (argv);
- free (u);
-
- #ifdef DEBUG
- __debug ("__vexit() -> parent");
- #endif
- return (__u->child[0].vreg);
- }
-