home *** CD-ROM | disk | FTP | other *** search
/ Otherware / Otherware_1_SB_Development.iso / amiga / programm / programi / ixemupd_.lzh / ixemupd-920129 / stdlib / ssystem.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-01-26  |  7.8 KB  |  306 lines

  1. /*
  2.  *  This file is part of ixemul.library for the Amiga.
  3.  *  Copyright (C) 1991, 1992  Markus M. Wild
  4.  *
  5.  *  This library is free software; you can redistribute it and/or
  6.  *  modify it under the terms of the GNU Library General Public
  7.  *  License as published by the Free Software Foundation; either
  8.  *  version 2 of the License, or (at your option) any later version.
  9.  *
  10.  *  This library is distributed in the hope that it will be useful,
  11.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13.  *  Library General Public License for more details.
  14.  *
  15.  *  You should have received a copy of the GNU Library General Public
  16.  *  License along with this library; if not, write to the Free
  17.  *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  *
  19.  *  22-jan-92    -mw-    restore sigmask before calling system()
  20.  */
  21.  
  22. #define KERNEL
  23. #include "ixemul.h"
  24. #include <ctype.h>
  25. #include <sys/wait.h>
  26.  
  27. #ifdef DEBUG
  28. #define DP(a) kprintf a
  29. #else
  30. #define DP(a)
  31. #endif
  32.  
  33. #define NO_PROTOTYPES
  34. #include <libraries/arpbase.h>  /* HAS! to be V39 or higher! */
  35. #undef NO_PROTOTYPES
  36.  
  37. #define BASE_EXT_DECL
  38. #define BASE_PAR_DECL    
  39. #define BASE_PAR_DECL0    
  40. #define BASE_NAME    ix.ix_arp_base
  41. #include <inline/arp.h>
  42.  
  43. /* 2.0 support */
  44. #include "gcc:include20/utility/tagitem.h"
  45. #include "gcc:include20/dos/dostags.h"
  46. #define BASE_EXT_DECL
  47. #define BASE_PAR_DECL    
  48. #define BASE_PAR_DECL0    
  49. #define BASE_NAME    ix.ix_dos_base
  50. __inline static LONG RunCommand(BASE_PAR_DECL BPTR seg, long int stack, UBYTE* paramptr, long int paramlen)
  51. {
  52.     BASE_EXT_DECL
  53.     register LONG res __asm("d0");
  54.     register void *a6 __asm ("a6");
  55.     register BPTR d1 __asm("d1");
  56.     register long int d2 __asm("d2");
  57.     register UBYTE* d3 __asm("d3");
  58.     register long int d4 __asm("d4");
  59.  
  60.     a6 = BASE_NAME;
  61.     d1 = seg;
  62.     d2 = stack;
  63.     d3 = paramptr;
  64.     d4 = paramlen;
  65.     __asm volatile ("
  66.     jsr a6@(-0x1f8)"
  67.     : "=r" (res)
  68.     : "r" (a6), "r" (d1), "r" (d2), "r" (d3), "r" (d4)
  69.     : "d0", "d1", "a0", "a1", "d2", "d3", "d4");
  70.     return res;
  71. }
  72. #ifndef CMD_SYSTEM
  73. #define CMD_SYSTEM    -1
  74. #define CMD_INTERNAL    -2
  75.  
  76. struct Segment {
  77.     BPTR seg_Next;
  78.     LONG seg_UC;
  79.     BPTR seg_Seg;
  80.     UBYTE seg_Name[4];    /* actually the first 4 chars of BSTR name */
  81. };
  82. #endif
  83. __inline static struct Segment* FindSegment(BASE_PAR_DECL UBYTE* name, struct Segment* seg, long int system)
  84. {
  85.     BASE_EXT_DECL
  86.     register struct Segment* res __asm("d0");
  87.     register void *a6 __asm ("a6");
  88.     register UBYTE* d1 __asm("d1");
  89.     register struct Segment* d2 __asm("d2");
  90.     register long int d3 __asm("d3");
  91.  
  92.     a6 = BASE_NAME;
  93.     d1 = name;
  94.     d2 = seg;
  95.     d3 = system;
  96.     __asm volatile ("
  97.     jsr a6@(-0x30c)"
  98.     : "=r" (res)
  99.     : "r" (a6), "r" (d1), "r" (d2), "r" (d3)
  100.     : "d0", "d1", "a0", "a1", "d2", "d3");
  101.     return res;
  102. }
  103.  
  104. extern int _dos20; /* set in crt0.c */
  105.  
  106. #if __GNUC__ != 2
  107. #define alloca __builtin_alloca
  108. #endif
  109.  
  110. extern BPTR __load_seg (char *name, char **args, BPTR *interp_lock);
  111.  
  112. int
  113. ssystem(char *argline)
  114. {
  115.   int rc, err = 0;
  116.   UBYTE *arg, *index();
  117.   UBYTE *tmp;
  118.   int stack_size;
  119.   struct CommandLineInterface *CLI;
  120.   struct Process *me;
  121.   int omask;
  122.  
  123.   omask = syscall (SYS_sigsetmask, ~0);
  124.   me = (struct Process *)FindTask(0);
  125.   CLI = BTOCPTR (me->pr_CLI);
  126.   stack_size = CLI ? CLI->cli_DefaultStack * 4 : me->pr_StackSize;
  127.   if (stack_size <= 4096) stack_size = 250000;
  128.  
  129.   /* the +1 is to get a cheap way to transform this into a BSTR */
  130.   tmp = alloca (strlen (argline) + 6);
  131.   tmp = LONG_ALIGN (tmp);
  132.   tmp++;
  133.  
  134.   strcpy (tmp, argline);
  135.  
  136.   while (*tmp == ' ' || *tmp == '\t') ++tmp;
  137.   /* not needed with custom load-seg function */
  138.   if (! _dos20)
  139.     while (tmp[0] == '.' && tmp[1] == '/') tmp += 2;
  140.  
  141.   if (arg = index(tmp, ' '))  *arg++ = 0;
  142.  
  143.   if (! _dos20)
  144.     {
  145.       if (arg)
  146.         {
  147.           /* the following for BCPL pecularities.. */
  148.           if (arg[strlen (arg) - 1] != '\n') strcat (arg, "\n");
  149.         }
  150.  
  151.       /* no interpreter expansion here, but Arp runs much stabler than 2.0... */
  152.       rc = SyncRun((char *)tmp, (char *)arg, 0, 0);
  153.       err = __ioerr_to_errno (IoErr ());
  154.     }
  155.   else
  156.     {
  157.       BPTR segs;
  158.       char *args;
  159.       struct Segment *res_seg = 0;
  160.  
  161.       segs = __load_seg (tmp, &args, 0);
  162.  
  163.       /* check for special cookie */
  164.       if (segs == (BPTR) -2)
  165.     {
  166.       syscall (SYS_sigsetmask, omask);
  167.  
  168.       /* let the shell do the dirty work ;-)) */
  169.       return system (argline);
  170.     }
  171.  
  172.       /* also check the resident list, for those that actually don't use rez... */
  173.       if (! segs)
  174.         {
  175.           Forbid ();
  176.           res_seg = FindSegment (tmp, 0, 0);
  177.           if (res_seg)
  178.             {
  179.               /* strange they didn't provide a function for this... */
  180.               if (res_seg->seg_UC >= 0) 
  181.             res_seg->seg_UC++;
  182.               segs = res_seg->seg_Seg;
  183.               args = 0;
  184.         }
  185.           Permit ();
  186.         }
  187.  
  188.       if (segs)
  189.     {
  190.       char **name;
  191.       char *orig;
  192.       char *all_args;
  193.       
  194.       /* if __load_seg() set args to something, we have to rebuild our
  195.        * command line, but really just in that case ;-))
  196.        */
  197.       if (args)
  198.         {
  199.           int force_quotes = 0;
  200.  
  201.           /* now this IS a horrible kludge.. but again, I *NEED* sksh
  202.            * working, and it only works, if the argument to the -c 
  203.            * switch is passed quoted... So if the __load_seg code
  204.            * decided, that this was such a special sksh-script, it 
  205.            * negates the *arg parameter... shudder... 
  206.            *
  207.            * NOTE: This only works for command lines that contain no
  208.            *       quotes themselves... I don't escape the argument
  209.            *       line, I just put a pair of quotes around it!
  210.            *       The starting quote is already included in the args
  211.            *       string from __load_seg()...
  212.            */
  213.           if (((int)args) < 0)
  214.             {
  215.               force_quotes = 1;
  216.               args = (char *) ((-(int)args));
  217.             }
  218.  
  219.           /* make handling easier */
  220.           if (! arg) arg = "";
  221.           
  222.           /* the command we build looks like:
  223.            * <seg'd command> args arg
  224.            */
  225.           
  226.           all_args = alloca (strlen (args) + 1 + strlen (arg) + 4);
  227.           strcpy (all_args, args);
  228.           if (*arg)
  229.             {
  230.               strcat (all_args, " ");
  231.               strcat (all_args, arg);
  232.             }
  233.  
  234.           if (force_quotes)
  235.         strcat (all_args, "\"");  /* no comment... */
  236.           strcat (all_args, "\n");      /* neither, this insn't my kludge though.. */
  237.  
  238.           /* and finally reassign the commandline to arg */
  239.           arg = all_args;
  240.           /* if args was not "", we have to free it, it's from strdup() */
  241.           if (*args) syscall (SYS_free, args);
  242.         }
  243.       else
  244.         {    
  245.           /* even if we didn't get any arguments from the expander, we still
  246.            * need to protect the original arguments ala BCPL ..
  247.            * Remember that `arg' is a (large enough) alloca() string ;-) */
  248.           if (arg)
  249.         strcat (arg, "\n");
  250.           else
  251.         arg = "\n";
  252.         }
  253.  
  254.       /*
  255.        * Hack to always get the name of the currently executing program
  256.        * in Xoper
  257.        */
  258.       if (CLI)
  259.         {
  260.           name = (char **) & CLI->cli_CommandName;
  261.           orig = *name;
  262.           /* that's why we incremented tmp before ;-)) */
  263.           ((unsigned char *)tmp)[-1] = strlen (tmp);
  264.           /* this is always odd (stack=even + 1), so will chop fine to BPTR */
  265.           *name = (char *) ((long)tmp >> 2);
  266.         }
  267.       else
  268.         {
  269.           name = (char **) & me->pr_Task.tc_Node.ln_Name;
  270.           orig = *name;
  271.           *name = tmp;
  272.         }
  273.  
  274. DP(("RunCommand (.. arg = >%s<, len = %ld)\n", arg, strlen (arg)));
  275.     
  276.       rc = RunCommand (segs, stack_size, arg, strlen (arg));
  277.  
  278.       *name = orig;
  279.       if (res_seg)
  280.         {
  281.           Forbid ();
  282.           if (res_seg->seg_UC > 0)
  283.         res_seg->seg_UC--;
  284.           Permit ();
  285.         }
  286.       else
  287.         UnLoadSeg (segs);
  288.     }
  289.       else
  290.     {
  291.       rc = 20;
  292.  
  293.           err = __ioerr_to_errno (IoErr ());
  294.         }
  295.     }
  296.  
  297.   syscall (SYS_sigsetmask, omask);
  298.  
  299.   if (rc > 128)
  300.     errno = EINTR;
  301.   else
  302.     errno = err;
  303.  
  304.   return (rc >= 128) ? W_EXITCODE (0, rc & 0x7f) : W_EXITCODE (rc, 0);
  305. }
  306.