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

  1. head    1.3;
  2. access;
  3. symbols
  4.     version39-41:1.1;
  5. locks;
  6. comment    @ * @;
  7.  
  8.  
  9. 1.3
  10. date    92.08.09.21.07.02;    author amiga;    state Exp;
  11. branches;
  12. next    1.2;
  13.  
  14. 1.2
  15. date    92.07.28.02.53.06;    author mwild;    state Exp;
  16. branches;
  17. next    1.1;
  18.  
  19. 1.1
  20. date    92.06.08.17.01.06;    author mwild;    state Exp;
  21. branches;
  22. next    ;
  23.  
  24.  
  25. desc
  26. @initial checkin
  27. @
  28.  
  29.  
  30. 1.3
  31. log
  32. @change to 2.x header files
  33. @
  34. text
  35. @/*
  36.  *  This file is part of ixemul.library for the Amiga.
  37.  *  Copyright (C) 1991, 1992  Markus M. Wild
  38.  *
  39.  *  This library is free software; you can redistribute it and/or
  40.  *  modify it under the terms of the GNU Library General Public
  41.  *  License as published by the Free Software Foundation; either
  42.  *  version 2 of the License, or (at your option) any later version.
  43.  *
  44.  *  This library is distributed in the hope that it will be useful,
  45.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  46.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  47.  *  Library General Public License for more details.
  48.  *
  49.  *  You should have received a copy of the GNU Library General Public
  50.  *  License along with this library; if not, write to the Free
  51.  *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  52.  *
  53.  *  22-jan-92    -mw-    restore sigmask before calling system()
  54.  */
  55.  
  56. #define KERNEL
  57. #include "ixemul.h"
  58. #include <ctype.h>
  59. #include <sys/wait.h>
  60.  
  61. #ifdef DEBUG
  62. #define DP(a) kprintf a
  63. #else
  64. #define DP(a)
  65. #endif
  66.  
  67. /* 2.0 support */
  68. #include <utility/tagitem.h>
  69. #include <dos/dostags.h>
  70.  
  71. #define BASE_EXT_DECL
  72. #define BASE_PAR_DECL    
  73. #define BASE_PAR_DECL0    
  74. #define BASE_NAME    ix.ix_arp_base
  75. __inline static LONG SyncRun(BASE_PAR_DECL const char* name, const char* command, BPTR input, BPTR output)
  76. {
  77.     BASE_EXT_DECL
  78.     register LONG res __asm("d0");
  79.     register void *a6 __asm ("a6");
  80.     register const char* a0 __asm("a0");
  81.     register const char* a1 __asm("a1");
  82.     register BPTR d0 __asm("d0");
  83.     register BPTR d1 __asm("d1");
  84.  
  85.     a6 = BASE_NAME;
  86.     a0 = name;
  87.     a1 = command;
  88.     d0 = input;
  89.     d1 = output;
  90.     __asm volatile ("
  91.     jsr a6@@(-0x21c)"
  92.     : "=r" (res)
  93.     : "r" (a6), "r" (a0), "r" (a1), "r" (d0), "r" (d1)
  94.     : "d0", "d1", "a0", "a1");
  95.     return res;
  96. }
  97.  
  98. extern int _dos20; /* set in crt0.c */
  99.  
  100. #if __GNUC__ != 2
  101. #define alloca __builtin_alloca
  102. #endif
  103.  
  104. extern BPTR *__load_seg (char *name, char **args);
  105.  
  106. int
  107. ssystem(char *argline)
  108. {
  109.   int rc, err = 0;
  110.   UBYTE *arg, *index();
  111.   UBYTE *tmp;
  112.   int stack_size;
  113.   struct CommandLineInterface *CLI;
  114.   struct Process *me;
  115.   int omask;
  116.  
  117.   omask = syscall (SYS_sigsetmask, ~0);
  118.   me = (struct Process *)FindTask(0);
  119.   CLI = BTOCPTR (me->pr_CLI);
  120.   stack_size = CLI ? CLI->cli_DefaultStack * 4 : me->pr_StackSize;
  121.   if (stack_size <= 4096) stack_size = 250000;
  122.  
  123.   /* the +1 is to get a cheap way to transform this into a BSTR */
  124.   tmp = alloca (strlen (argline) + 6);
  125.   tmp = LONG_ALIGN (tmp);
  126.   tmp++;
  127.  
  128.   strcpy (tmp, argline);
  129.  
  130.   while (*tmp == ' ' || *tmp == '\t') ++tmp;
  131.   /* not needed with custom load-seg function */
  132.   if (! _dos20)
  133.     while (tmp[0] == '.' && tmp[1] == '/') tmp += 2;
  134.  
  135.   if (arg = index(tmp, ' '))  *arg++ = 0;
  136.  
  137.   if (! _dos20)
  138.     {
  139.       if (arg)
  140.         {
  141.           /* the following for BCPL pecularities.. */
  142.           if (arg[strlen (arg) - 1] != '\n') strcat (arg, "\n");
  143.         }
  144.  
  145.       /* no interpreter expansion here, but Arp runs much stabler than 2.0... */
  146.       rc = SyncRun((char *)tmp, (char *)arg, 0, 0);
  147.       err = __ioerr_to_errno (IoErr ());
  148.     }
  149.   else
  150.     {
  151.       BPTR *segs;
  152.       char *args;
  153.       BPTR old_cis, old_cos, old_ces;
  154.       BPTR dup_cis, dup_cos, dup_ces;
  155.       struct file *f;
  156.  
  157.       segs = __load_seg (tmp, &args);
  158.  
  159.       /* check for special cookie */
  160.       if (segs == (BPTR *) -2)
  161.     {
  162.       syscall (SYS_sigsetmask, omask);
  163.  
  164.       /* let the shell do the dirty work ;-)) */
  165.       return system (argline);
  166.     }
  167.  
  168.       if (segs)
  169.     {
  170.       char **name;
  171.       char *orig;
  172.       char *all_args;
  173.       u_int old_signals;
  174.       
  175.       /* if __load_seg() set args to something, we have to rebuild our
  176.        * command line, but only just in that case ;-))
  177.        */
  178.       if (args)
  179.         {
  180.           int force_quotes = 0;
  181.  
  182.           /* now this IS a horrible kludge.. but again, I *NEED* sksh
  183.            * working, and it only works, if the argument to the -c 
  184.            * switch is passed quoted... So if the __load_seg code
  185.            * decided, that this was such a special sksh-script, it 
  186.            * negates the *arg parameter... shudder... 
  187.            *
  188.            * NOTE: This only works for command lines that contain no
  189.            *       quotes themselves... I don't escape the argument
  190.            *       line, I just put a pair of quotes around it!
  191.            *       The starting quote is already included in the args
  192.            *       string from __load_seg()...
  193.            */
  194.           if (((int)args) < 0)
  195.             {
  196.               force_quotes = 1;
  197.               args = (char *) ((-(int)args));
  198.             }
  199.  
  200.           /* make handling easier */
  201.           if (! arg) arg = "";
  202.           
  203.           /* the command we build looks like:
  204.            * <seg'd command> args arg
  205.            */
  206.           
  207.           all_args = alloca (strlen (args) + 1 + strlen (arg) + 4);
  208.           strcpy (all_args, args);
  209.           if (*arg)
  210.             {
  211.               strcat (all_args, " ");
  212.               strcat (all_args, arg);
  213.             }
  214.  
  215.           if (force_quotes)
  216.         strcat (all_args, "\"");  /* no comment... */
  217.           strcat (all_args, "\n");      /* neither, this insn't my kludge though.. */
  218.  
  219.           /* and finally reassign the commandline to arg */
  220.           arg = all_args;
  221.           /* if args was not "", we have to free it, it's from strdup() */
  222.           if (*args) syscall (SYS_free, args);
  223.         }
  224.       else
  225.         {    
  226.           /* even if we didn't get any arguments from the expander, we still
  227.            * need to protect the original arguments ala BCPL ..
  228.            * Remember that `arg' is a (large enough) alloca() string ;-) */
  229.           if (arg)
  230.         strcat (arg, "\n");
  231.           else
  232.         arg = "\n";
  233.         }
  234.  
  235.       /*
  236.        * Hack to always get the name of the currently executing program
  237.        * to show up in Xoper
  238.        */
  239.       if (CLI)
  240.         {
  241.           name = (char **) & CLI->cli_CommandName;
  242.           orig = *name;
  243.           /* that's why we incremented tmp before ;-)) */
  244.           ((unsigned char *)tmp)[-1] = strlen (tmp);
  245.           /* this is always odd (stack=even + 1), so will chop fine to BPTR */
  246.           *name = (char *) ((long)tmp >> 2);
  247.         }
  248.       else
  249.         {
  250.           name = (char **) & me->pr_Task.tc_Node.ln_Name;
  251.           orig = *name;
  252.           *name = tmp;
  253.         }
  254.  
  255. DP(("RunCommand (.. arg = >%s<, len = %ld)\n", arg, strlen (arg)));
  256.       /* perform I/O redirection... (copied from execve.c) */
  257.  
  258.       if ((f = u.u_ofile[0]) && f->f_type == DTYPE_FILE)
  259.         {
  260.           dup_cis = 0;
  261.           old_cis = SelectInput (CTOBPTR (f->f_fh));
  262.           readargs_kludge (CTOBPTR (f->f_fh));
  263.           DP(("redir 0, old_cis = $%lx\n",old_cis));
  264.         }
  265.       else
  266.         {
  267.           if (!f)
  268.             {
  269.               int fd = open ("/dev/null", 0);
  270.               dup_cis = dup2_BPTR (fd);
  271.               close (fd);
  272.             }
  273.           else
  274.         dup_cis = dup2_BPTR (0);
  275.           old_cis = 0;
  276.           if (dup_cis)
  277.             {
  278.               old_cis = SelectInput (dup_cis);
  279.               readargs_kludge (dup_cis);
  280.           DP(("redir 0, old_cis = $%lx, dup_cis = $%lx\n", old_cis, dup_cis));
  281.             }
  282.           else
  283.         DP(("redir 0, dup2_BPTR failed\n"));
  284.         }
  285.  
  286.       if ((f = u.u_ofile[1]) && f->f_type == DTYPE_FILE)
  287.         {
  288.           dup_cos = 0;
  289.           old_cos = SelectOutput (CTOBPTR (f->f_fh));
  290.           DP(("redir 1, old_cos = $%lx\n", old_cos));
  291.         }
  292.       else
  293.         {
  294.           if (!f)
  295.             {
  296.               int fd = open ("/dev/null", 1);
  297.               dup_cos = dup2_BPTR (fd);
  298.               close (fd);
  299.             }
  300.           else
  301.             dup_cos = dup2_BPTR (1);
  302.           old_cos = 0;
  303.           if (dup_cos)
  304.             {
  305.               old_cos = SelectOutput (dup_cos);
  306.               DP(("redir 1, old_cos = $%lx, dup_cos = $%lx\n", old_cos, dup_cos));
  307.             }
  308.           else
  309.             DP(("redir 1, dup2_BPTR failed\n"));
  310.         }
  311.       old_ces = me->pr_CES;
  312.       if ((f = u.u_ofile[2]) && f->f_type == DTYPE_FILE)
  313.         {
  314.           dup_ces = 0;
  315.           me->pr_CES = CTOBPTR (f->f_fh);
  316.         }
  317.           else
  318.         {
  319.           if (!f)
  320.             {
  321.               int fd = open ("/dev/null", 2);
  322.               dup_ces = dup2_BPTR (fd);
  323.               close (fd);
  324.             }
  325.           else
  326.             dup_ces = dup2_BPTR (2);
  327.           me->pr_CES = dup_ces ? : old_ces;
  328.         }
  329.  
  330.       /* RunCommand should provide the started program with a fresh set of
  331.        * signals, it doesn't. So we do this by hand here... */
  332.       old_signals = me->pr_Task.tc_SigAlloc;
  333.       me->pr_Task.tc_SigAlloc &= 0xffff;
  334.       rc = RunCommand (*segs, stack_size, arg, strlen (arg));
  335.       me->pr_Task.tc_SigAlloc = old_signals;
  336.           err = __ioerr_to_errno (IoErr ());
  337.       *name = orig;
  338.  
  339.       if (old_cis)
  340.         SelectInput (old_cis);
  341.       if (old_cos)
  342.         Flush (SelectOutput (old_cos));
  343.       me->pr_CES = old_ces;
  344.  
  345.       /* reset I/O */
  346.       if (dup_cis)
  347.         Close (dup_cis);
  348.           if (dup_cos)
  349.             Close (dup_cos);
  350.           if (dup_ces)
  351.             Close (dup_ces);
  352.  
  353.       __free_seg (segs);
  354.     }
  355.       else
  356.     {
  357.       rc = 20;
  358.  
  359.           err = __ioerr_to_errno (IoErr ());
  360.         }
  361.     }
  362.  
  363.   syscall (SYS_sigsetmask, omask);
  364.  
  365.   if (rc > 128)
  366.     errno = EINTR;
  367.   else
  368.     errno = err;
  369.  
  370.   return (rc >= 128) ? W_EXITCODE (0, rc & 0x7f) : W_EXITCODE (rc, 0);
  371. }
  372. @
  373.  
  374.  
  375. 1.2
  376. log
  377. @provide better I/O-redirection, seems to finally cooperate with ReadArgs...
  378. @
  379. text
  380. @d33 3
  381. a35 3
  382. #define NO_PROTOTYPES
  383. #include <libraries/arpbase.h>  /* HAS! to be V39 or higher! */
  384. #undef NO_PROTOTYPES
  385. d41 1
  386. a41 10
  387. #include <inline/arp.h>
  388.  
  389. /* 2.0 support */
  390. #include "gcc:include20/utility/tagitem.h"
  391. #include "gcc:include20/dos/dostags.h"
  392. #define BASE_EXT_DECL
  393. #define BASE_PAR_DECL    
  394. #define BASE_PAR_DECL0    
  395. #define BASE_NAME    ix.ix_dos_base
  396. __inline static LONG RunCommand(BASE_PAR_DECL BPTR seg, long int stack, UBYTE* paramptr, long int paramlen)
  397. d46 3
  398. a49 3
  399.     register long int d2 __asm("d2");
  400.     register UBYTE* d3 __asm("d3");
  401.     register long int d4 __asm("d4");
  402. d52 4
  403. a55 4
  404.     d1 = seg;
  405.     d2 = stack;
  406.     d3 = paramptr;
  407.     d4 = paramlen;
  408. d57 1
  409. a57 1
  410.     jsr a6@@(-0x1f8)"
  411. d59 2
  412. a60 2
  413.     : "r" (a6), "r" (d1), "r" (d2), "r" (d3), "r" (d4)
  414.     : "d0", "d1", "a0", "a1", "d2", "d3", "d4");
  415. a62 69
  416. static __inline BPTR 
  417. SelectInput (BASE_PAR_DECL BPTR fh)
  418. {
  419.   BASE_EXT_DECL
  420.   register BPTR  _res  __asm("d0");
  421.   register struct DosLibrary *a6 __asm("a6") = BASE_NAME;
  422.   register BPTR d1 __asm("d1") = fh;
  423.   __asm __volatile ("jsr a6@@(-0x126)"
  424.   : "=r" (_res)
  425.   : "r" (a6), "r" (d1)
  426.   : "a0","a1","d0","d1", "memory");
  427.   return _res;
  428. }
  429. static __inline BPTR 
  430. SelectOutput (BASE_PAR_DECL BPTR fh)
  431. {
  432.   BASE_EXT_DECL
  433.   register BPTR  _res  __asm("d0");
  434.   register struct DosLibrary *a6 __asm("a6") = BASE_NAME;
  435.   register BPTR d1 __asm("d1") = fh;
  436.   __asm __volatile ("jsr a6@@(-0x12c)"
  437.   : "=r" (_res)
  438.   : "r" (a6), "r" (d1)
  439.   : "a0","a1","d0","d1", "memory");
  440.   return _res;
  441. }
  442. static __inline LONG 
  443. Flush (BASE_PAR_DECL BPTR fh)
  444. {
  445.   BASE_EXT_DECL
  446.   register LONG  _res  __asm("d0");
  447.   register struct DosLibrary *a6 __asm("a6") = BASE_NAME;
  448.   register BPTR d1 __asm("d1") = fh;
  449.   __asm __volatile ("jsr a6@@(-0x168)"
  450.   : "=r" (_res)
  451.   : "r" (a6), "r" (d1)
  452.   : "a0","a1","d0","d1", "memory");
  453.   return _res;
  454. }
  455. struct Process_20 {
  456.     struct  Task    pr_Task;
  457.     struct  MsgPort pr_MsgPort; /* This is BPTR address from DOS functions  */
  458.     WORD    pr_Pad;        /* Remaining variables on 4 byte boundaries */
  459.     BPTR    pr_SegList;        /* Array of seg lists used by this process  */
  460.     LONG    pr_StackSize;    /* Size of process stack in bytes        */
  461.     APTR    pr_GlobVec;        /* Global vector for this process (BCPL)    */
  462.     LONG    pr_TaskNum;        /* CLI task number of zero if not a CLI        */
  463.     BPTR    pr_StackBase;    /* Ptr to high memory end of process stack  */
  464.     LONG    pr_Result2;        /* Value of secondary result from last call */
  465.     BPTR    pr_CurrentDir;    /* Lock associated with current directory   */
  466.     BPTR    pr_CIS;        /* Current CLI Input Stream            */
  467.     BPTR    pr_COS;        /* Current CLI Output Stream            */
  468.     APTR    pr_ConsoleTask;    /* Console handler process for current window*/
  469.     APTR    pr_FileSystemTask;    /* File handler process for current drive   */
  470.     BPTR    pr_CLI;        /* pointer to CommandLineInterface        */
  471.     APTR    pr_ReturnAddr;    /* pointer to previous stack frame        */
  472.     APTR    pr_PktWait;        /* Function to be called when awaiting msg  */
  473.     APTR    pr_WindowPtr;    /* Window for error printing            */
  474.  
  475.     /* following definitions are new with 2.0 */
  476.     BPTR    pr_HomeDir;        /* Home directory of executing program        */
  477.     LONG    pr_Flags;        /* flags telling dos about process        */
  478.     void    (*pr_ExitCode)();    /* code to call on exit of program or NULL  */
  479.     LONG    pr_ExitData;    /* Passed as an argument to pr_ExitCode.    */
  480.     UBYTE   *pr_Arguments;    /* Arguments passed to the process at start */
  481.     struct MinList pr_LocalVars; /* Local environment variables            */
  482.     ULONG   pr_ShellPrivate;    /* for the use of the current shell        */
  483.     BPTR    pr_CES;        /* Error stream - if NULL, use pr_COS        */
  484. };  /* Process */
  485. d80 1
  486. a80 1
  487.   struct Process_20 *me;
  488. @
  489.  
  490.  
  491. 1.1
  492. log
  493. @Initial revision
  494. @
  495. text
  496. @d72 70
  497. d158 1
  498. a158 1
  499.   struct Process *me;
  500. d197 3
  501. d300 73
  502. d382 14
  503. @
  504.