# New Ticket Created by  Jeff Horwitz 
# Please include the string:  [perl #35365]
# in the subject line of all future correspondence about this issue. 
# <URL: https://rt.perl.org/rt3/Ticket/Display.html?id=35365 >


the attached patch adds a new signature for spawnw so it can take a PMC
array of arguments rather than a single string.  with this, parrot can
support perl's system($cmd) as well as system(@args).  tests are
included, though i only have unix platforms to test on right now.

-jeff
Index: ops/ops.num

===================================================================

--- ops/ops.num (revision 8028)

+++ ops/ops.num (working copy)

@@ -1341,3 +1341,4 @@

 not_i                          1311

 not_p                          1312

 n_not_p_p                      1313

+spawnw_i_p                     1314

Index: ops/sys.ops

===================================================================

--- ops/sys.ops (revision 8028)

+++ ops/sys.ops (working copy)

@@ -20,9 +20,16 @@

 

 =item B<spawnw>(out INT, in STR)

 

-Spawn a subprocess and wait for it to finish. The return status, which is

-very system-dependent, goes in $1.

+Spawn a subprocess whose program name and arguments are contained in the string

+$2 and wait for it to finish. The return status, which is very

+system-dependent, goes in $1.

 

+=item B<spawnw>(out INT, in PMC)

+

+Spawn a subprocess whose program name and arguments are contained in the array

+$2 and wait for it to finish. The return status, which is very

+system-dependent, goes in $1.

+

 =cut

 

 inline op spawnw(out INT, in STR) {

@@ -30,6 +37,11 @@

   goto NEXT();

 }

 

+inline op spawnw(out INT, in PMC) {

+  $1 = Parrot_Run_OS_Command_Argv(interpreter, $2);

+  goto NEXT();

+}

+

 ###############################################################################

 

 =item B<err>(out INT)

Index: t/op/spawnw.t

===================================================================

--- t/op/spawnw.t       (revision 8028)

+++ t/op/spawnw.t       (working copy)

@@ -13,12 +13,12 @@

 

 Tests spawning external commands.

 

-spanwn does not capture STDOUT and STDERR from the spawnde command.

+spawnw does not capture STDOUT and STDERR from the spawned command.

 So only the exit code can be tested.

 

 The returned value is actually returned from the 'waitpid' system call.

-In order to get the exit code from the spawned process, it needs to be right 
shifted

-by 8 bit. 

+In order to get the exit code from the spawned process, it needs to be right

+shifted by 8 bit. 

 

 =head1 TODO

 

@@ -34,11 +34,13 @@

 

 =cut

 

-use Parrot::Test tests => 3;

+use Parrot::Test tests => 6;

 

 # perl command coded this way to avoid platform 

 # quoting issue.

 

+# test string version of spawnw

+

 pasm_output_is(<<'CODE', <<'OUTPUT', "exit code: 0");

         set     S1, 'perl -e "exit(0)"'

         set     I1, 99

@@ -65,7 +67,6 @@

 return code: 123

 OUTPUT

 

-

 output_is(<<'CODE', <<'OUTPUT', "exit code: 3");

         set     S1, 'perl -e "exit(3)"'

         set     I1, 99

@@ -78,3 +79,56 @@

 CODE

 return code: 3

 OUTPUT

+

+# test array version of spawnw

+

+output_is(<<'CODE', <<'OUTPUT', "exit code: 0");

+        new     P0, .Array

+        set     P0, 3

+        set     P0[0], "perl"

+        set     P0[1], "-e"

+        set     P0[2], "exit(0)"

+        set     I1, 99

+        spawnw  I1, P0

+       shr     I2, I1, 8

+        print   "return code: "

+        print   I2

+        print   "\n"

+        end

+CODE

+return code: 0

+OUTPUT

+

+output_is(<<'CODE', <<'OUTPUT', "exit code: 123");

+        new     P0, .Array

+        set     P0, 3

+        set     P0[0], "perl"

+        set     P0[1], "-e"

+        set     P0[2], "exit(123)"

+        set     I1, 99

+        spawnw  I1, P0

+       shr     I2, I1, 8

+        print   "return code: "

+        print   I2

+        print   "\n"

+        end

+CODE

+return code: 123

+OUTPUT

+

+output_is(<<'CODE', <<'OUTPUT', "exit code: 3");

+        new     P0, .Array

+        set     P0, 3

+        set     P0[0], "perl"

+        set     P0[1], "-e"

+        set     P0[2], "exit(3)"

+        set     I1, 99

+        spawnw  I1, P0

+       shr     I2, I1, 8

+        print   "return code: "

+        print   I2

+        print   "\n"

+        end

+CODE

+return code: 3

+OUTPUT

Index: config/gen/platform/platform_interface.h

===================================================================

--- config/gen/platform/platform_interface.h    (revision 8028)

+++ config/gen/platform/platform_interface.h    (working copy)

@@ -123,6 +123,8 @@

 struct parrot_string_t;

 INTVAL Parrot_Run_OS_Command(Interp*, struct parrot_string_t *);

 void Parrot_Exec_OS_Command(Interp*, struct parrot_string_t *);

+INTVAL Parrot_Run_OS_Command_Argv(Interp*, struct PMC *);

+void Parrot_Exec_OS_Command_Argv(Interp*, struct PMC *);

 

 /*

  * Local variables:

Index: config/gen/platform/generic/exec.c

===================================================================

--- config/gen/platform/generic/exec.c  (revision 8028)

+++ config/gen/platform/generic/exec.c  (working copy)

@@ -40,6 +40,51 @@

     return 1;  /* make gcc happy */

 }

 

+INTVAL

+Parrot_Run_OS_Command_Argv(Parrot_Interp interpreter, PMC *cmdargs)

+{

+    pid_t child;

+    int len = VTABLE_elements(interpreter, cmdargs);

+    if (len == 0) {

+        internal_exception(NOSPAWN, "Empty argument array for execvp");

+    }

+    child = fork();

+    /* Did we fail? */

+    if (-1 == child) {

+        internal_exception(NOSPAWN, "Can't spawn child process");

+    }

+    /* Are we the parent or child? */

+    if (child) {

+        /* parent */

+        int status;

+        pid_t returnstat;

+        returnstat = waitpid(child, &status, 0);

+        return status;

+    } else {

+        /* child. Be horribly profligate with memory, since we're

+           about to be something else */

+        int status, i;

+        char **argv;

+        STRING *s;

+        char *cmd;

+

+        argv = (char **)mem_sys_allocate((len+1)*sizeof(char *));

+        for (i = 0; i < len; ++i) {

+            s = VTABLE_get_string_keyed_int(interpreter, cmdargs, i);

+            argv[i] = string_to_cstring(interpreter, s);

+        }

+        cmd = argv[0];

+        argv[i] = NULL;

+

+        status = execvp(cmd, argv);

+        /* if we get here, something's horribly wrong... */

+        if (status) {

+            exit(status);

+        }

+    }

+    return 1;  /* make gcc happy */

+}

+

 void

 Parrot_Exec_OS_Command(Parrot_Interp interpreter, STRING *command) {

   /* Be horribly profligate with memory, since we're

Reply via email to