home *** CD-ROM | disk | FTP | other *** search
/ ARM Club 3 / TheARMClub_PDCD3.iso / hensa / unix / unixlib_1 / !UnixLib37_src_sys_c_vfork < prev    next >
Encoding:
C/C++ Source or Header  |  1996-11-09  |  5.6 KB  |  231 lines

  1. /****************************************************************************
  2.  *
  3.  * $Source: /unixb/home/unixlib/source/unixlib37/src/sys/c/RCS/vfork,v $
  4.  * $Date: 1996/10/30 21:59:00 $
  5.  * $Revision: 1.4 $
  6.  * $State: Rel $
  7.  * $Author: unixlib $
  8.  *
  9.  * $Log: vfork,v $
  10.  * Revision 1.4  1996/10/30 21:59:00  unixlib
  11.  * Massive changes made by Nick Burret and Peter Burwood.
  12.  *
  13.  * Revision 1.3  1996/07/21 22:12:31  unixlib
  14.  * CL_0001 Nick Burret
  15.  * Improve memory handling. Remove C++ library incompatibilities.
  16.  * Improve file stat routines.
  17.  *
  18.  * Revision 1.2  1996/05/06 09:03:14  unixlib
  19.  * Updates to sources made by Nick Burrett, Peter Burwood and Simon Callan.
  20.  * Saved for 3.7a release.
  21.  *
  22.  * Revision 1.1  1996/04/19 21:34:24  simon
  23.  * Initial revision
  24.  *
  25.  ***************************************************************************/
  26.  
  27. static const char rcs_id[] = "$Id: vfork,v 1.4 1996/10/30 21:59:00 unixlib Rel $";
  28.  
  29. #include <errno.h>
  30. #include <string.h>
  31. #include <stdlib.h>
  32. #include <setjmp.h>
  33. #include <limits.h>
  34.  
  35. #include <termio.h>
  36. #include <unistd.h>
  37.  
  38. #include <sys/unix.h>
  39. #include <sys/syslib.h>
  40. #include <sys/param.h>
  41. #include <sys/debug.h>
  42. #include <sys/wait.h>
  43. #include <sys/swis.h>
  44.  
  45. #ifdef DEBUG
  46. #include <stdio.h>
  47. #endif
  48.  
  49. /* vfork is similar to fork.
  50.  
  51.    fork makes a complete copy of the calling proces's address space
  52.    and allows both the parent and child to execute independently.
  53.    vfork does not make this copy.
  54.  
  55.    A child process created with vfork shares its parent's address
  56.    space until it calls exit or one of the exec functions. In the
  57.    meantime, the parent process suspends execution.  */
  58.  
  59. int *
  60. __vfork (void)
  61. {
  62.   register struct proc *u = 0;
  63.   register int argc;
  64.   register char **argv = 0;
  65.   register char *argb = 0;
  66.   register int i;
  67.   int regs[10];
  68.  
  69. #ifdef DEBUG
  70.   __debug ("vfork() entered <- parent");
  71. #endif
  72.  
  73.   if (!(u = malloc (sizeof (struct proc))))
  74.       goto nomem;
  75.   if (!(argv = malloc (sizeof (int) * (4 * MAXCOMMANDLEN >> 2))))
  76.       goto nomem;
  77.   if (!(argb = malloc (4 * MAXCOMMANDLEN)))
  78.     goto nomem;
  79.  
  80.   memcpy (u, __u, sizeof (struct proc));
  81.  
  82.   /* Copy the parent structure proc for the child process.
  83.      Create a unique ID number for the child. Reading the
  84.      monotonic clock should be okay.  */
  85.   os_swi (OS_ReadMonotonicTime, regs);
  86.   u->ppid = u->pid;
  87.   u->pid = regs[0];
  88.   u->pproc = __u;
  89.   /* For the time being, the child process will have the same
  90.      priority as the parent process.  */
  91.   u->ppri = __u->ppri;
  92.   u->gpri = __u->gpri;
  93.   u->upri = __u->upri;
  94.   /* Reset the resource usage statistics.  */
  95.   memset (&u->usage, 0, sizeof (struct rusage));
  96.   memset (&u->status, 0, sizeof (struct __process));
  97.   memset (&u->sigstate, 0, sizeof (struct unixlib_sigstate));
  98.  
  99.   /* A child process always inherits the signals blocked by the
  100.      parent process.  */
  101.   u->sigstate.blocked = __u->sigstate.blocked;
  102.   u->status.tty_type = TTY_CON;
  103.  
  104.   /* Copy over the command line arguments.  */
  105.   {
  106.     register char *s1, *s2;
  107.  
  108.     argc = u->argc;
  109.     s2 = argb;
  110.  
  111.     for (i = 0; i < argc; i++)
  112.       {
  113.     argv[i] = s2;
  114.     s1 = u->argv[i];
  115.     while (*s2++ = *s1++);
  116.       }
  117.     argv[i] = 0;
  118.   }
  119.   u->argv = argv;
  120.   u->argb = argb;
  121.   /* Copy over the file descriptors.  */
  122.   {
  123.     register int v = (char *) u - (char *) __u;
  124.  
  125.     for (i = 0; i < MAXFD; i++)
  126.       if (u->file[i].dup)
  127.     u->file[i].dup = (void *) ((char *) u->file[i].dup + v);
  128.   }
  129.  
  130.   /* Say that we are a child process to some lucky parent.  */
  131.   u->status.has_parent = 1;
  132.   __u = u;
  133.  
  134. #ifdef DEBUG
  135.   __debug ("vfork() -> child");
  136. #endif
  137.  
  138.   /* This will now return back to vfork(), with register a1 pointing
  139.      to a jmpbuf which will then be setup by setjmp().  */
  140.   return (u->vreg);
  141.  
  142. nomem:
  143.  
  144.   if (argb)
  145.     free (argb);
  146.   if (argv)
  147.     free (argv);
  148.   if (u)
  149.     free (u);
  150.  
  151.   errno = ENOMEM;
  152.  
  153.   return (0);
  154. }
  155.  
  156. int *
  157. __vexit (int e)
  158. {
  159.   register struct proc *u = __u;
  160.   register char **argv = u->argv;
  161.   register char *argb = u->argb;
  162.   register int i, j;
  163.  
  164. #ifdef DEBUG
  165.   __debug ("__vexit() entered <- child");
  166. #endif
  167.  
  168.   /* Stop any interval timers, just in case.  */
  169.   __stop_itimers ();
  170.  
  171.   /* Store the return code, then analyze it, setting various
  172.      bits in the process's status.  */
  173.   u->status.return_code = (__WIFEXITED(e)) ? __WEXITSTATUS(e) : 0;
  174.   if (__WIFSIGNALED(e))
  175.     {
  176.       u->status.signal_exit = 1;
  177.       u->status.signal = __WTERMSIG(e);
  178.     }
  179.   u->status.core_dump = __WCOREDUMP(e);
  180.  
  181.   /* Close the file descriptors we used.  */
  182.   for (i = 0; i < MAXFD; i++)
  183.     if (u->file[i].dup)
  184.       close (i);
  185.  
  186. #ifdef DEBUG
  187.   __debug ("__vexit() <- child (close())");
  188.   os_print ("__vexit() e = ");
  189.   os_prhex (e);
  190.   os_print ("\r\n");
  191.   os_print ("return code = "); os_prhex (u->status.return_code); os_print ("\r\n");
  192.   os_print ("signal exit = "); os_prhex (u->status.signal_exit); os_print ("\r\n");
  193.   os_print ("signal = "); os_prhex (u->status.signal); os_print ("\r\n");
  194.   os_print ("core dumped = "); os_prhex (u->status.core_dump); os_print ("\r\n");
  195. #endif
  196.  
  197.   __u = u->pproc;
  198. #if 0
  199.   i = __find_free_child ();
  200.   if (i != -1)
  201.     {
  202.       /* Copy over child structure data we will need to remember
  203.          for the wait functions.  */
  204. #endif
  205.       __u->child[0].pid = u->pid;
  206.       __u->child[0].uid = u->uid;
  207.       __u->child[0].gid = u->gid;
  208.       __u->child[0].ppri = u->ppri;
  209.       __u->child[0].upri = u->upri;
  210.       __u->child[0].gpri = u->gpri;
  211.       __u->child[0].usage = u->usage;
  212.       __u->child[0].status = u->status;
  213.  
  214.       for (j = 0; j < __JMP_BUF_SIZE; j++)
  215.         __u->child[0].vreg[j] = u->vreg[j];
  216.       __u->child[0].vreg[13] = u->pid;
  217.  
  218. #if 0
  219.     }
  220. #endif
  221.  
  222.   free (argb);
  223.   free (argv);
  224.   free (u);
  225.  
  226. #ifdef DEBUG
  227.   __debug ("__vexit() -> parent");
  228. #endif
  229.   return (__u->child[0].vreg);
  230. }
  231.