home *** CD-ROM | disk | FTP | other *** search
/ The CDPD Public Domain Collection for CDTV 3 / CDPDIII.bin / pd / programming / gnuc / stdlib / rcs / execve.c,v < prev    next >
Encoding:
Text File  |  1992-09-14  |  26.3 KB  |  1,043 lines

  1. head    1.6;
  2. access;
  3. symbols
  4.     version39-41:1.2;
  5. locks;
  6. comment    @ * @;
  7.  
  8.  
  9. 1.6
  10. date    92.09.14.01.50.16;    author mwild;    state Exp;
  11. branches;
  12. next    1.5;
  13.  
  14. 1.5
  15. date    92.08.09.21.06.31;    author amiga;    state Exp;
  16. branches;
  17. next    1.4;
  18.  
  19. 1.4
  20. date    92.07.28.03.12.04;    author mwild;    state Exp;
  21. branches;
  22. next    1.3;
  23.  
  24. 1.3
  25. date    92.07.28.02.59.44;    author mwild;    state Exp;
  26. branches;
  27. next    1.2;
  28.  
  29. 1.2
  30. date    92.07.04.18.59.29;    author mwild;    state Exp;
  31. branches;
  32. next    1.1;
  33.  
  34. 1.1
  35. date    92.06.08.17.01.06;    author mwild;    state Exp;
  36. branches;
  37. next    ;
  38.  
  39.  
  40. desc
  41. @initial checkin
  42. @
  43.  
  44.  
  45. 1.6
  46. log
  47. @change NO_VFORK_RESUME into USE_VFORK_RESUME, which is what the macro really
  48. is about (don't use it though at the moment!).
  49. Test for p_vfork_msg instead of u_save_sp, since only the first one is
  50. reset when the process is detached.
  51. @
  52. text
  53. @/*
  54.  *  This file is part of ixemul.library for the Amiga.
  55.  *  Copyright (C) 1991, 1992  Markus M. Wild
  56.  *
  57.  *  This library is free software; you can redistribute it and/or
  58.  *  modify it under the terms of the GNU Library General Public
  59.  *  License as published by the Free Software Foundation; either
  60.  *  version 2 of the License, or (at your option) any later version.
  61.  *
  62.  *  This library is distributed in the hope that it will be useful,
  63.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  64.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  65.  *  Library General Public License for more details.
  66.  *
  67.  *  You should have received a copy of the GNU Library General Public
  68.  *  License along with this library; if not, write to the Free
  69.  *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  70.  *
  71.  */
  72.  
  73. #define KERNEL
  74. #include "ixemul.h"
  75. #include <hardware/intbits.h>
  76. #include <ctype.h>
  77. #include <sys/wait.h>
  78.  
  79. #include <sys/exec.h>
  80.  
  81. #include "atexit.h"
  82. #define __atexit (u.u_atexit)
  83.  
  84. #define alloca __builtin_alloca
  85.  
  86. #undef DEBUG
  87. #ifdef DEBUG
  88. #define DP(a) kprintf a
  89. #else
  90. #define DP(a)
  91. #endif
  92.  
  93. extern int _dos20;
  94.  
  95. extern void bcopy (void *, void *, int);
  96. extern BPTR *__load_seg (const char *name, char **args);
  97. extern void __free_seg (BPTR *segs);
  98. extern void *kmalloc (size_t);
  99. extern void *krealloc (void *, size_t);
  100. extern char *index (const char *, int);
  101. extern char *strpbrk (const char *, const char *);
  102. extern void kfree (void *);
  103. extern char *strcpy (char *, const char *);
  104. extern void kprintf (const char *, ...);
  105. extern void all_free (void);
  106.  
  107. static int compatible_startup (void *code, int argc, char **argv);
  108. static char *quote (char *orig);
  109. static void volatile on_real_stack (BPTR *segs, char **argv, char **environ);
  110.  
  111. int
  112. execve (char *path, char **argv, char **environ)
  113. {
  114.   BPTR *segs;
  115.   u_int omask, err;
  116.   char *extra_args = 0;
  117.  
  118.   omask = syscall (SYS_sigsetmask, ~0);
  119.   u.u_oldmask = omask;
  120.   
  121.   segs = __load_seg (path, &extra_args);
  122.  
  123.   if (segs && segs != (BPTR *)-2)
  124.     {
  125.       /* Now it gets somewhat nasty... since I have to revert to the `real'
  126.          stack (since the parent will want its sp back ;-)), I have to save
  127.          the values of this stack frame into registers, or I'll never be
  128.          able to access them afterwards again.. */
  129.       register BPTR *_segs asm ("d2");
  130.       register char **_argv asm ("d3");
  131.       register char **_environ asm ("d4");
  132.  
  133.       /* if we got extra arguments, split them into a 2 el argument vector, and join
  134.        * `argv' */
  135.       if (extra_args && *extra_args)
  136.     {
  137.       char **ap, **nargv;
  138.           int size;
  139.  
  140.           for (size = 0, ap = argv; *ap; size++, ap++) ;
  141.           nargv = (char **) syscall (SYS_malloc, (size + 4) * 4);
  142.           ap = nargv;
  143.           *ap++ = *argv++;    /* keep the program name */
  144.           *ap++ = extra_args;
  145.           *ap = index (extra_args, ' ');
  146.           if (*ap)
  147.             {
  148.               **ap = 0;
  149.               ++*ap;
  150.               ++ap;
  151.          }
  152.           while (*ap++ = *argv++) ;
  153.           argv = nargv;
  154.     }
  155.  
  156.       _segs = segs;
  157.       _argv = argv;
  158.       _environ = environ;
  159.  
  160. #ifndef USE_VFORK_RESUME
  161.       DP(("execve: about to call on_real_stack ()\n"));
  162.       if (u.p_vfork_msg)
  163.         {
  164.           set_sp ((u_int) u.u_save_sp);
  165.           /* fool the optimizer... */
  166.           asm volatile ("" : "=g" (_segs), "=g" (_argv), "=g" (_environ) : "0" (_segs), "1" (_argv), "2" (_environ));
  167.           DP(("execve () restored native sp\n"));
  168.     }
  169. #else
  170.       /* this option is currently not recommended. execve needs to allocate memory
  171.      later on, and this should not happen inside Forbid! */
  172.       Forbid ();
  173.       vfork_resume ();
  174. #endif
  175.       on_real_stack (_segs, _argv, _environ);
  176.       /* never reached */
  177.     }
  178.  
  179.   err = ENOENT;
  180.  
  181.   syscall (SYS_sigsetmask, omask);
  182.  
  183.   errno = err;
  184.   return -1;
  185. }
  186.  
  187.  
  188. char **
  189. dupvec (char **vec)
  190. {
  191.   int n;
  192.   char **vp, **res;
  193.   static char *empty[] = { "" };
  194.   
  195.   if (! vec)
  196.     return empty;
  197.  
  198.   for (n = 0, vp = vec; *vp; n++, vp++) ;
  199.  
  200.   /* contrary to `real' vfork(), malloc() works in the child on its own
  201.      data, that is it won't clobber anything in the parent  */
  202.   
  203.   res = (char **) syscall (SYS_malloc, (n + 1) * 4);
  204.   if (res)
  205.     {
  206.       for (vp = res; n-- > 0; vp++, vec++)
  207.         *vp = (char *) syscall (SYS_strdup, *vec);
  208.  
  209.       *vp = 0;
  210.     }
  211.  
  212.   return res;
  213. }
  214.  
  215.  
  216. static void volatile 
  217. on_real_stack (BPTR *segs, char **argv, char **environ)
  218. {
  219.   int private_startup;
  220.   u_int *code;
  221.   int (*entry) (struct ixemul_base *, int, char **, char **);
  222.   struct exec *hdr;
  223.   int f;
  224.   jmp_buf old_exit;
  225.  
  226.   /* first make sure that we're later passing on `safe' data to our child, ie.
  227.      copy it from wherever the data is currently stored into child malloc space */
  228.   argv = dupvec (argv);
  229.   environ = dupvec (environ);
  230.     
  231.   code = BTOCPTR (*segs);
  232.   code ++;    /* code starts at offset 4 */
  233.   
  234.   /* check whether this program has our magic header */
  235.   private_startup = ((code[0] & 0xffff0000) == 0x4efa0000  /* jmp pc@@(amiga-dos-entry) */
  236.                && (code [1] & 0xffff) == OMAGIC);
  237.  
  238. #if 0
  239.   {
  240.     char **cp;
  241.     kprintf ("execve [");
  242.     for (cp = argv; *cp; cp++) kprintf ("%s%s", *cp, cp[1] ? ", " : "], [");
  243.     for (cp = environ; *cp; cp++) kprintf ("%s%s", *cp, cp[1] ? ", " : "]\n");
  244.   }
  245. #endif
  246.  
  247.   if (private_startup)
  248.     {
  249.       hdr = (struct exec *) &code[1];
  250.       entry = (void *) hdr->a_entry;
  251.       
  252.       if (! entry) private_startup = 0;
  253.     }
  254.       
  255.   /* okay, get ready to turn us into a new process, as much as
  256.      we can actually.. */
  257.  
  258.   /* close all files with the close-on-exec flag set */
  259.   for (f = 0; f < NOFILE; f++)
  260.     {
  261.       if (u.u_ofile[f] && (u.u_pofile[f] & UF_EXCLOSE))
  262.       syscall (SYS_close, f);
  263.     }
  264.  
  265.   /* BIG question what to do with registered atexit() handlers before
  266.      an exec.. Unix for sure does nothing, since the process space is
  267.      physically written over. In the AmigaDOS I could (!) imagine
  268.      cases where calling some atexit() handlers (mostly in the case
  269.      of destructors for C++ objects) would result in erronous
  270.      behaving of the program. However, since atexit() handlers also
  271.      serve to get rid of acquired Amiga resources, I morally feel
  272.      obliged to call the handlers.. lets see if this results in
  273.      incompatibilities with programs that expect Unix behavior. (Note
  274.      that I don't call exit() after exeve() returns, I call _exit(),
  275.      and _exit() does not walk the atexit() list).
  276.  
  277.      There is one special case that I catch here, this is stdio. No
  278.      Unix program would ever expect stdio buffers to be flushed by
  279.      an execve() call. So since stdio is in the library I know the
  280.      address of the handler to skip ;-)) */
  281.      
  282.   while (__atexit)
  283.     {
  284.       while (__atexit->ind --)
  285.     {
  286.       /* this is the stdio function to flush all buffers */
  287.       extern void _cleanup();
  288.     
  289.       if (__atexit->fns[__atexit->ind] != _cleanup)
  290.         {
  291.           if (u.u_a4)
  292.             asm volatile ("movel %0, a4" : : "g" (u.u_a4));
  293.           __atexit->fns[__atexit->ind] ();
  294.         }
  295.     }
  296.       __atexit = __atexit->next;
  297.     }
  298.  
  299.   /* `ignored signals remain ignored across an execve, but
  300.       signals that are caught are reset to their default values.
  301.       Blocked signals remain blocked regardless of changes to
  302.       the signal action. The signal stack is reset to be
  303.       undefined'. */
  304.  
  305.   u.u_sigonstack = 0;    /* default = on normal stack */
  306.   u.u_sigintr    = 0;    /* default = don't interrupt syscalls */
  307.   u.p_sigcatch   = 0;    /* no signals caught by user -> SIG_DFL */
  308.  
  309.   /* what happens when we execute execve() from a signal handler
  310.      that executes on the signal stack? Better don't do this... */
  311.  
  312.   /* deinstall our sigwinch input-handler */
  313.   ix_remove_sigwinch ();
  314.           
  315.   /* save the original exit-jmpbuf, as ix_exec_entry() will destroy
  316.    * it later */
  317.   bcopy (u.u_jmp_buf, old_exit, sizeof (old_exit));
  318.           
  319.   /* count the arguments */
  320.   for (f = 0; argv[f]; f++) ;
  321.  
  322. #ifndef USE_VFORK_RESUME
  323. DP(("execve() having parent resume\n"));
  324.   if (u.p_vfork_msg)
  325.     {
  326.       /* make the parent runable again */
  327.       ReplyMsg ((struct Message *) u.p_vfork_msg);
  328.       u.p_vfork_msg = 0;
  329.     }
  330. #else
  331.   Permit ();
  332. #endif
  333.  
  334. DP(("execve() calling entry(%ld, $%lx, $%lx)\n", f, argv, environ));
  335.   {
  336.     char *orig, **name;
  337.     struct Process *me = (struct Process *) FindTask (0);
  338.     struct CommandLineInterface *CLI = BTOCPTR (me->pr_CLI);
  339.     char *bcpl_argv0;
  340.     
  341.     bcpl_argv0 = alloca (strlen (argv[0]) + 4);
  342.     bcpl_argv0 = LONG_ALIGN (bcpl_argv0);
  343.     
  344.     if (CLI)
  345.       {
  346.     name = (char **) & CLI->cli_CommandName;
  347.     orig = *name;
  348.     bcpl_argv0[0] = strlen (argv[0]);
  349.     bcopy (argv[0], &bcpl_argv0[1], bcpl_argv0[0] + 1);
  350.     *name = (char *) CTOBPTR (bcpl_argv0);
  351.       }
  352.     else
  353.       {
  354.     name = (char **) & me->pr_Task.tc_Node.ln_Name;
  355.     orig = *name;
  356.     *name = argv[0];
  357.       }
  358.  
  359.     if (private_startup)
  360.       f = entry (ixemulbase, f, argv, environ);
  361.     else
  362.       f = compatible_startup (code, f, argv);
  363.  
  364.     *name = orig;
  365.   }
  366.  
  367.   __free_seg (segs);
  368.  
  369. DP(("old program doing _exit(%ld)\n", f));
  370.   /* and fake an _exit */
  371.   longjmp (old_exit, f + 1);
  372. }  
  373.  
  374.  
  375. /* some rather rude support to start programs that don't have a struct exec
  376.  * information at the beginning.
  377.  * 1.3 NOTE: This will only start plain C programs, nothing that smells like
  378.  *           BCPL. Limited support for ReadArgs() style parsing is here, but not
  379.  *         everything is set up that would have to be set up for BCPL programs
  380.  *         to feel at home. Also don't use Exit() in those programs, it wouldn't
  381.  *         find what it expects on the stack....
  382.  */
  383. static int
  384. compatible_startup (void *code, int argc, char **argv)
  385. {
  386.   char *al;
  387.   int max, res;
  388.   u_int oldsigalloc;
  389.   struct Process *me = (struct Process *) FindTask (0);
  390.   
  391.   /* ignore the command name ;-) */
  392.   argv++;
  393.  
  394.   max = 1024;
  395.   al = (char *) kmalloc (max);
  396.   res = -1;
  397.   if (al)
  398.     {
  399.       char *cp;
  400.       register int d0 asm ("d0");
  401.       register char *a0 asm ("a0");
  402.       register void *a1 asm ("a1");
  403.       BPTR old_cis, old_cos, old_ces;
  404.       BPTR dup_cis, dup_cos, dup_ces;
  405.       void *old_trapdata, *old_trapcode;
  406.       int old_flags;
  407.       void *old_launch, *old_switch;
  408.       struct file *f;
  409.  
  410.       for (cp = al; *argv; )
  411.         {
  412.       char *newel = quote (*argv);
  413.           int elsize = strlen (newel ? newel : *argv) + 2;
  414.           
  415.           if (cp + elsize >= al + max)
  416.             {
  417.           char *nal;
  418.               max <<= 1;
  419.               nal = (char *) krealloc (al, max);
  420.               if (! nal) break;
  421.               cp = nal + (cp-al);
  422.               al = nal;
  423.         }
  424.  
  425.       strcpy (cp, newel ? newel : *argv);
  426.       cp += elsize - 2;
  427.       *cp++ = ' ';
  428.       *cp = 0;
  429.       if (newel) kfree (newel);
  430.       ++argv;
  431.         }
  432.       
  433.       /* BCPL weirdness ... */
  434.       *cp++ = '\n';
  435.       *cp = 0;
  436.  
  437. DP(("compatible_startup (%s)\n", al));
  438.  
  439.       /* problem with RunCommand: the allocated signal mask is not reset
  440.      for the new process, thus if several RunCommands are nested, a
  441.      late started process might run out of signals. This behavior makes
  442.      no sense, since the starting process is *suspended* while the `child'
  443.      is running, thus it doesn't need its signals in the meantime ! */
  444.  
  445.       oldsigalloc = me->pr_Task.tc_SigAlloc & 0xffff0000;    /* hacky...*/
  446.       me->pr_Task.tc_SigAlloc &= 0xffff;
  447.  
  448.       /* cleanup as much of ixemul.library as possible, so that the started
  449.          process can take over */
  450.       old_flags             = me->pr_Task.tc_Flags;
  451.       me->pr_Task.tc_Flags  = u_save.u_otask_flags;
  452.       old_launch            = me->pr_Task.tc_Launch;
  453.       me->pr_Task.tc_Launch = u_save.u_olaunch; /* restoring this disables our signals */
  454.       old_switch            = me->pr_Task.tc_Switch;
  455.       me->pr_Task.tc_Switch = u_save.u_oswitch;
  456.       RemIntServer (INTB_VERTB, & u_save.u_itimerint);
  457.  
  458. #if 0
  459.       /* looks like we shouldn't do this, bus errors are the consequence.. */
  460.  
  461.       /* free the task private malloc'd data */
  462.       all_free ();
  463. #endif
  464.  
  465.       /* limited support (part 2 ;-)) for I/O redirection on old programs
  466.          If we're redirecting to a plain file, don't go thru a IXPIPE, 
  467.          temporarily use our DOS files in that case. Any other file type
  468.          is routed thru an IXPIPE though. */
  469.       
  470.       if (! _dos20)
  471.     {
  472.       old_cis = me->pr_CIS;
  473.       old_cos = me->pr_COS;
  474.       if ((f = u_save.u_ofile[0]) && f->f_type == DTYPE_FILE)
  475.         {
  476.           dup_cis = 0;
  477.           me->pr_CIS = CTOBPTR (f->f_fh);
  478.         }
  479.           else
  480.         {
  481.           if (!f)
  482.             {
  483.               int fd = open ("/dev/null", 0);
  484.               dup_cis = dup2_BPTR (fd);
  485.               close (fd);
  486.             }
  487.           else
  488.             dup_cis = dup2_BPTR (0);
  489.           me->pr_CIS = dup_cis ? : old_cis;
  490.         }
  491.       if ((f = u_save.u_ofile[1]) && f->f_type == DTYPE_FILE)
  492.         {
  493.           dup_cos = 0;
  494.           me->pr_COS = CTOBPTR (f->f_fh);
  495.         }
  496.           else
  497.         {
  498.           if (!f)
  499.             {
  500.               int fd = open ("/dev/null", 1);
  501.               dup_cos = dup2_BPTR (fd);
  502.               close (fd);
  503.             }
  504.           else
  505.             dup_cos = dup2_BPTR (1);
  506.           me->pr_COS = dup_cos ? : old_cos;
  507.         }
  508.       dup_ces = 0;
  509.     }
  510.       else
  511.     {
  512.       if ((f = u_save.u_ofile[0]) && f->f_type == DTYPE_FILE)
  513.         {
  514.           dup_cis = 0;
  515.           old_cis = SelectInput (CTOBPTR (f->f_fh));
  516.           readargs_kludge (CTOBPTR (f->f_fh));
  517.         }
  518.       else
  519.         {
  520.           if (!f)
  521.             {
  522.               int fd = open ("/dev/null", 0);
  523.               dup_cis = dup2_BPTR (fd);
  524.               close (fd);
  525.             }
  526.           else
  527.             dup_cis = dup2_BPTR (0);
  528.           old_cis = 0;
  529.           if (dup_cis)
  530.             {
  531.               old_cis = SelectInput (dup_cis);
  532.               readargs_kludge (dup_cis);
  533.             }
  534.         }
  535.       if ((f = u_save.u_ofile[1]) && f->f_type == DTYPE_FILE)
  536.         {
  537.           dup_cos = 0;
  538.           old_cos = SelectOutput (CTOBPTR (f->f_fh));
  539.         }
  540.       else
  541.         {
  542.           if (!f)
  543.             {
  544.               int fd = open ("/dev/null", 1);
  545.               dup_cos = dup2_BPTR (fd);
  546.               close (fd);
  547.             }
  548.           else
  549.             dup_cos = dup2_BPTR (1);
  550.           old_cos = 0;
  551.           if (dup_cos)
  552.             old_cos = SelectOutput (dup_cos);
  553.         }
  554.       old_ces = me->pr_CES;
  555.       if ((f = u_save.u_ofile[2]) && f->f_type == DTYPE_FILE)
  556.         {
  557.           dup_ces = 0;
  558.           me->pr_CES = CTOBPTR (f->f_fh);
  559.         }
  560.           else
  561.         {
  562.           if (!f)
  563.             {
  564.               int fd = open ("/dev/null", 2);
  565.               dup_ces = dup2_BPTR (fd);
  566.               close (fd);
  567.             }
  568.           else
  569.             dup_ces = dup2_BPTR (2);
  570.           me->pr_CES = dup_ces ? : old_ces;
  571.         }
  572.     }
  573.  
  574.       /* BEWARE that after this reset no library functions can be
  575.          called any longer until the moment where trapdata is 
  576.          reinstalled !! */
  577.       old_trapdata = me->pr_Task.tc_TrapData;
  578.       me->pr_Task.tc_TrapData = u_save.u_otrap_data;
  579.       old_trapcode = me->pr_Task.tc_TrapCode;
  580.       me->pr_Task.tc_TrapCode = u_save.u_otrap_code;
  581.  
  582.       if (! _dos20)
  583.         /* this is a hack, since some programs expect pr_ReturnAddr to
  584.          * be valid... */
  585.         {
  586.           void *old_return_addr = me->pr_ReturnAddr;
  587.       u_int *sp = (u_int *) get_sp ();
  588.       struct FileHandle *fh = BTOCPTR (Input ());
  589.       u_int obuf=fh->fh_Buf, oend=fh->fh_End, opos=fh->fh_Pos;
  590.  
  591.       *--sp = 0;
  592.       *--sp = 0;
  593.       me->pr_ReturnAddr = sp;
  594.       asm volatile ("movel %0,sp" : : "a" (sp));
  595.       me->pr_Result2 = 0;
  596.       fh->fh_Buf = CTOBPTR (al);
  597.       fh->fh_Pos = 0;
  598.       fh->fh_End = cp-al;
  599.     
  600.           /* start the baby */
  601.           d0 = cp - al;
  602.           a0 = al;
  603.           a1 = code;
  604.           asm volatile ("jsr a1@@" : "=d" (d0) : "0" (d0), "a" (a0), "a" (a1));
  605.           /* save the result before it's destroyed.. */
  606.           res = d0;
  607.  
  608.           me->pr_ReturnAddr = old_return_addr;
  609.       fh->fh_Buf = obuf;
  610.       fh->fh_Pos = opos;
  611.       fh->fh_End = oend;
  612.       sp += 2;
  613.       asm volatile ("movel %0,sp" : : "a" (sp));
  614.         }
  615.       else
  616.     {
  617.       struct CommandLineInterface *CLI = BTOCPTR (me->pr_CLI);
  618.       u_int stack_size = CLI ? CLI->cli_DefaultStack * 4 : me->pr_StackSize;
  619.  
  620.       /* perhaps someone really uses so small stacks......... */
  621.       /* if (stack_size <= 4096) stack_size = 250000; */
  622.  
  623.       /* the above approach has too many incompatibilities, sigh.
  624.  
  625.          Note: The use of RunCommand() here means, that we *waste* the
  626.                entire stack space allocated for this process! If someone
  627.                comes up with a clever trick (probably involving StackSwap ())
  628.                where the stack of this process can be freed before calling
  629.                RunCommand (), lots of users with memory problems would be
  630.                thankful! */
  631.  
  632.       res = RunCommand (CTOBPTR (code) - 1, stack_size, al, cp - al);
  633.     }
  634.  
  635.       /* reinstall enough of ixemul to be able to finish cleanly 
  636.          (the recent addition of an ix_sleep() at the end of a vfork'd
  637.           process makes it necessary to reinstall the signalling facilities!) */
  638.  
  639.       me->pr_Task.tc_TrapData = old_trapdata;
  640.       me->pr_Task.tc_TrapCode = old_trapcode;
  641.       /* have to do this, or ix_close() is not able to RemoveIntServer .. */
  642.       AddIntServer (INTB_VERTB, & u_save.u_itimerint);
  643.       me->pr_Task.tc_Flags  = old_flags;
  644.       me->pr_Task.tc_Launch = old_launch;
  645.       me->pr_Task.tc_Switch = old_switch;
  646.  
  647.       kfree (al);
  648.  
  649.       if (! _dos20)
  650.     {
  651.       me->pr_CIS = old_cis;
  652.       me->pr_COS = old_cos;
  653.     }
  654.       else
  655.     {
  656.       if (old_cis)
  657.         SelectInput (old_cis);
  658.       if (old_cos)
  659.         Flush (SelectOutput (old_cos));
  660.       me->pr_CES = old_ces;
  661.     }
  662.  
  663.       if (dup_cis)
  664.         Close (dup_cis);
  665.       if (dup_cos)
  666.         Close (dup_cos);
  667.       if (dup_ces)
  668.         Close (dup_ces);
  669.  
  670.       me->pr_Task.tc_SigAlloc |= oldsigalloc;
  671.     }
  672.  
  673.   return res;
  674. }
  675.  
  676. static char *
  677. quote (char *orig)
  678. {
  679.   int i;
  680.   char *new, *cp;
  681.   
  682.   i = strlen (orig);
  683.   
  684.   if (strpbrk (orig, "\"\'\\ \t\n"))
  685.     {
  686.       /* worst case, each character needs quoting plus starting and ending " */
  687.       new = (char *) kmalloc (i * 2 + 3);
  688.       if (! new) return 0;
  689.  
  690.       cp = new;
  691.       *cp++ = '"';
  692.       while (*orig)
  693.         {
  694.           if (index ("\"\\", *orig))
  695.             *cp++ = '\\';
  696.       *cp++ = *orig++;
  697.     }
  698.       *cp++ = '"';
  699.       *cp = 0;
  700.       
  701.       return new;
  702.     }
  703.   else
  704.     return 0;    /* means `just use the original string' */
  705. }   
  706.  
  707. /* try to obtain a DOS filehandle on the specified descriptor. This only
  708.    works, if the user has mounted IXPIPE: */
  709. BPTR
  710. dup2_BPTR (int fd)
  711. {
  712.   long id;
  713.   char name[20];
  714.   
  715.   id = fcntl (fd, F_EXTERNALIZE, 0);
  716.   if (id >= 0)
  717.     {
  718.       sprintf (name, "IXPIPE:%x", id);
  719.       /* 0x4242 is a magic packet understood by IXPIPE: to F_INTERNALIZE id */
  720.       return Open (name, 0x4242);
  721.     }
  722.  
  723.   return 0;
  724. }
  725.  
  726.  
  727. /* the misteries of DOS seem to never want to take an end... */
  728. void
  729. readargs_kludge (BPTR bp)
  730. {
  731.   int ch;
  732.   static const int EOS_CHAR = -1;
  733.  
  734. #if 0
  735.   /* the autodocs say this bug is fixed after v37, well, perhaps that was a
  736.      very deep wish, nevertheless unheard by dos...
  737.      Without this kludge, you have to actually press return if stdin is not
  738.      redirected...
  739.      Thanks mbs: whithout your shell code I would never have guessed that 
  740.                  something that weird could be possible....
  741.    */
  742.   if (ix.ix_dos_base->lib_Version <= 37)
  743. #endif
  744.     {
  745.       ch = UnGetC (bp, EOS_CHAR) ? 0 : '\n';
  746.       while ((ch != '\n') && (ch != EOS_CHAR))
  747.         ch = FGetC (bp);
  748.       Flush (bp);
  749.     }
  750. }
  751. @
  752.  
  753.  
  754. 1.5
  755. log
  756. @change to 2.x header files
  757. @
  758. text
  759. @d108 1
  760. a108 1
  761. #ifndef NO_VFORK_RESUME
  762. d110 1
  763. a110 1
  764.       if (u.u_save_sp)
  765. d118 2
  766. d270 1
  767. a270 1
  768. #ifndef NO_VFORK_RESUME
  769. @
  770.  
  771.  
  772. 1.4
  773. log
  774. @don't believe autodocs.. the flush-bug is still there, get rid of the `if'..
  775. @
  776. text
  777. @a31 32
  778. struct Process_20 {
  779.     struct  Task    pr_Task;
  780.     struct  MsgPort pr_MsgPort; /* This is BPTR address from DOS functions  */
  781.     WORD    pr_Pad;        /* Remaining variables on 4 byte boundaries */
  782.     BPTR    pr_SegList;        /* Array of seg lists used by this process  */
  783.     LONG    pr_StackSize;    /* Size of process stack in bytes        */
  784.     APTR    pr_GlobVec;        /* Global vector for this process (BCPL)    */
  785.     LONG    pr_TaskNum;        /* CLI task number of zero if not a CLI        */
  786.     BPTR    pr_StackBase;    /* Ptr to high memory end of process stack  */
  787.     LONG    pr_Result2;        /* Value of secondary result from last call */
  788.     BPTR    pr_CurrentDir;    /* Lock associated with current directory   */
  789.     BPTR    pr_CIS;        /* Current CLI Input Stream            */
  790.     BPTR    pr_COS;        /* Current CLI Output Stream            */
  791.     APTR    pr_ConsoleTask;    /* Console handler process for current window*/
  792.     APTR    pr_FileSystemTask;    /* File handler process for current drive   */
  793.     BPTR    pr_CLI;        /* pointer to CommandLineInterface        */
  794.     APTR    pr_ReturnAddr;    /* pointer to previous stack frame        */
  795.     APTR    pr_PktWait;        /* Function to be called when awaiting msg  */
  796.     APTR    pr_WindowPtr;    /* Window for error printing            */
  797.  
  798.     /* following definitions are new with 2.0 */
  799.     BPTR    pr_HomeDir;        /* Home directory of executing program        */
  800.     LONG    pr_Flags;        /* flags telling dos about process        */
  801.     void    (*pr_ExitCode)();    /* code to call on exit of program or NULL  */
  802.     LONG    pr_ExitData;    /* Passed as an argument to pr_ExitCode.    */
  803.     UBYTE   *pr_Arguments;    /* Arguments passed to the process at start */
  804.     struct MinList pr_LocalVars; /* Local environment variables            */
  805.     ULONG   pr_ShellPrivate;    /* for the use of the current shell        */
  806.     BPTR    pr_CES;        /* Error stream - if NULL, use pr_COS        */
  807. };  /* Process */
  808.  
  809.  
  810. a42 100
  811. /* 2.0 support */
  812. #define BASE_EXT_DECL
  813. #define BASE_PAR_DECL    
  814. #define BASE_PAR_DECL0    
  815. #define BASE_NAME    ix.ix_dos_base
  816. __inline static LONG RunCommand(BASE_PAR_DECL BPTR seg, long int stack, UBYTE* paramptr, long int paramlen)
  817. {
  818.     BASE_EXT_DECL
  819.     register LONG res __asm("d0");
  820.     register void *a6 __asm ("a6");
  821.     register BPTR d1 __asm("d1");
  822.     register long int d2 __asm("d2");
  823.     register UBYTE* d3 __asm("d3");
  824.     register long int d4 __asm("d4");
  825.  
  826.     a6 = BASE_NAME;
  827.     d1 = seg;
  828.     d2 = stack;
  829.     d3 = paramptr;
  830.     d4 = paramlen;
  831.     __asm volatile ("
  832.     jsr a6@@(-0x1f8)"
  833.     : "=r" (res)
  834.     : "r" (a6), "r" (d1), "r" (d2), "r" (d3), "r" (d4)
  835.     : "d0", "d1", "a0", "a1", "d2", "d3", "d4");
  836.     return res;
  837. }
  838. __inline static BPTR SelectInput(BASE_PAR_DECL BPTR fh)
  839. {
  840.     BASE_EXT_DECL
  841.     register BPTR res __asm("d0");
  842.     register void *a6 __asm ("a6");
  843.     register BPTR d1 __asm("d1");
  844.  
  845.     a6 = BASE_NAME;
  846.     d1 = fh;
  847.     __asm volatile ("
  848.     jsr a6@@(-0x126)"
  849.     : "=r" (res)
  850.     : "r" (a6), "r" (d1)
  851.     : "d0", "d1", "a0", "a1");
  852.     return res;
  853. }
  854. __inline static BPTR SelectOutput(BASE_PAR_DECL BPTR fh)
  855. {
  856.     BASE_EXT_DECL
  857.     register BPTR res __asm("d0");
  858.     register void *a6 __asm ("a6");
  859.     register BPTR d1 __asm("d1");
  860.  
  861.     a6 = BASE_NAME;
  862.     d1 = fh;
  863.     __asm volatile ("
  864.     jsr a6@@(-0x12c)"
  865.     : "=r" (res)
  866.     : "r" (a6), "r" (d1)
  867.     : "d0", "d1", "a0", "a1");
  868.     return res;
  869. }
  870. static __inline LONG 
  871. UnGetC (BASE_PAR_DECL BPTR fh,long character)
  872. {
  873.   BASE_EXT_DECL
  874.   register LONG  _res  __asm("d0");
  875.   register struct DosLibrary *a6 __asm("a6") = BASE_NAME;
  876.   register BPTR d1 __asm("d1") = fh;
  877.   register long d2 __asm("d2") = character;
  878.   __asm __volatile ("jsr a6@@(-0x13e)"
  879.   : "=r" (_res)
  880.   : "r" (a6), "r" (d1), "r" (d2)
  881.   : "a0","a1","d0","d1","d2");
  882.   return _res;
  883. }
  884. static __inline LONG 
  885. FGetC (BASE_PAR_DECL BPTR fh)
  886. {
  887.   BASE_EXT_DECL
  888.   register LONG  _res  __asm("d0");
  889.   register struct DosLibrary *a6 __asm("a6") = BASE_NAME;
  890.   register BPTR d1 __asm("d1") = fh;
  891.   __asm __volatile ("jsr a6@@(-0x132)"
  892.   : "=r" (_res)
  893.   : "r" (a6), "r" (d1)
  894.   : "a0","a1","d0","d1");
  895.   return _res;
  896. }
  897. static __inline LONG 
  898. Flush (BASE_PAR_DECL BPTR fh)
  899. {
  900.   BASE_EXT_DECL
  901.   register LONG  _res  __asm("d0");
  902.   register struct DosLibrary *a6 __asm("a6") = BASE_NAME;
  903.   register BPTR d1 __asm("d1") = fh;
  904.   __asm __volatile ("jsr a6@@(-0x168)"
  905.   : "=r" (_res)
  906.   : "r" (a6), "r" (d1)
  907.   : "a0","a1","d0","d1");
  908.   return _res;
  909. }
  910.  
  911. d335 1
  912. a335 1
  913.   struct Process_20 *me = (struct Process_20 *) FindTask (0);
  914. d397 1
  915. a397 1
  916.       me->pr_Task.tc_Flags  = u.u_otask_flags;
  917. d399 1
  918. a399 1
  919.       me->pr_Task.tc_Launch = u.u_olaunch; /* restoring this disables our signals */
  920. d401 2
  921. a402 2
  922.       me->pr_Task.tc_Switch = u.u_oswitch;
  923.       RemIntServer (INTB_VERTB, & u.u_itimerint);
  924. d420 1
  925. a420 1
  926.       if ((f = u.u_ofile[0]) && f->f_type == DTYPE_FILE)
  927. d437 1
  928. a437 1
  929.       if ((f = u.u_ofile[1]) && f->f_type == DTYPE_FILE)
  930. d458 1
  931. a458 1
  932.       if ((f = u.u_ofile[0]) && f->f_type == DTYPE_FILE)
  933. d481 1
  934. a481 1
  935.       if ((f = u.u_ofile[1]) && f->f_type == DTYPE_FILE)
  936. d501 1
  937. a501 1
  938.       if ((f = u.u_ofile[2]) && f->f_type == DTYPE_FILE)
  939. d524 1
  940. a524 1
  941.       me->pr_Task.tc_TrapData = u.u_otrap_data;
  942. d526 1
  943. a526 1
  944.       me->pr_Task.tc_TrapCode = u.u_otrap_code;
  945. d588 1
  946. a588 1
  947.       AddIntServer (INTB_VERTB, & u.u_itimerint);
  948. @
  949.  
  950.  
  951. 1.3
  952. log
  953. @integrate changes made to ssystem() here as well.
  954. @
  955. text
  956. @d812 8
  957. d821 1
  958. @
  959.  
  960.  
  961. 1.2
  962. log
  963. @make dupvec() public, it's used somewhere else in the library.
  964. make use of new F_EXTERNALIZE feature and use IXPIPE instead of the default
  965. NIL: filehandles if starting a program in compatibility mode and its
  966. descriptors don't refer to DTYPE_FILE files.
  967. @
  968. text
  969. @d134 40
  970. d240 1
  971. d249 4
  972. d400 1
  973. d408 3
  974. d559 8
  975. a566 1
  976.           dup_cis = dup2_BPTR (0);
  977. d576 8
  978. a583 1
  979.           dup_cos = dup2_BPTR (1);
  980. d594 1
  981. d598 8
  982. a605 1
  983.           dup_cis = dup2_BPTR (0);
  984. d608 4
  985. a611 1
  986.             old_cis = SelectInput (dup_cis);
  987. d620 8
  988. a627 1
  989.           dup_cos = dup2_BPTR (1);
  990. d640 8
  991. a647 1
  992.           dup_ces = dup2_BPTR (2);
  993. a726 7
  994.       if (dup_cis)
  995.         Close (dup_cis);
  996.       if (dup_cos)
  997.         Close (dup_cos);
  998.       if (dup_ces)
  999.         Close (dup_ces);
  1000.  
  1001. d737 1
  1002. a737 1
  1003.         SelectOutput (old_cos);
  1004. d741 7
  1005. d787 1
  1006. a787 1
  1007. static BPTR
  1008. d802 17
  1009. @
  1010.  
  1011.  
  1012. 1.1
  1013. log
  1014. @Initial revision
  1015. @
  1016. text
  1017. @d221 1
  1018. a221 1
  1019. static char **
  1020. d344 3
  1021. d433 1
  1022. d494 5
  1023. a498 1
  1024.       /* limited support (part 2 ;-)) for I/O redirection on old programs */
  1025. d504 9
  1026. a512 1
  1027.         me->pr_CIS = CTOBPTR (f->f_fh);
  1028. d514 10
  1029. a523 1
  1030.         me->pr_COS = CTOBPTR (f->f_fh);
  1031. d527 24
  1032. a550 4
  1033.       old_cis = ((f = u.u_ofile[0]) && f->f_type == DTYPE_FILE) ?
  1034.             SelectInput (CTOBPTR (f->f_fh)) : 0;
  1035.       old_cos = ((f = u.u_ofile[1]) && f->f_type == DTYPE_FILE) ?
  1036.             SelectOutput (CTOBPTR (f->f_fh)) : 0;
  1037. d553 9
  1038. a561 1
  1039.         me->pr_CES = CTOBPTR (f->f_fh);
  1040. d639 7
  1041. d696 19
  1042. @
  1043.