summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZefram <zefram@fysh.org>2017-12-06 21:27:15 +0000
committerZefram <zefram@fysh.org>2017-12-14 22:48:30 +0000
commit282fc0b3cc2439f69587d980b62bef7f5d5bdfef (patch)
tree6dc6abf858b4903d0adb99d6309a74f84ebf7782
parente135ff695231a81e2a70a739e8d813525432fd4d (diff)
downloadperl-282fc0b3cc2439f69587d980b62bef7f5d5bdfef.tar.gz
make exec keep its argument list more reliably
Bits of exec code were putting the constructed commands into globals PL_Argv and PL_Cmd, which could then be clobbered by reentrancy. These are only global in order to manage their freeing, but that's better managed by using the scope stack. So replace them with automatic variables, with ENTER/SAVEFREEPV/LEAVE to free the memory. Also copy the strings acquired from SVs, to avoid magic clobbering the buffers of SVs already read. Fixes [perl #129888].
-rw-r--r--amigaos4/amigaio.c66
-rw-r--r--cygwin/cygwin.c28
-rw-r--r--djgpp/djgpp.c36
-rw-r--r--doio.c77
-rw-r--r--embed.fnc1
-rw-r--r--embed.h1
-rw-r--r--embedvar.h2
-rw-r--r--intrpvar.h2
-rw-r--r--os2/os2.c109
-rw-r--r--pp_sys.c2
-rw-r--r--proto.h1
-rw-r--r--sv.c2
-rw-r--r--util.c2
-rw-r--r--vms/vms.c23
14 files changed, 186 insertions, 166 deletions
diff --git a/amigaos4/amigaio.c b/amigaos4/amigaio.c
index b471220260..edc237a033 100644
--- a/amigaos4/amigaio.c
+++ b/amigaos4/amigaio.c
@@ -646,7 +646,7 @@ static void S_exec_failed(pTHX_ const char *cmd, int fd, int do_report)
static I32 S_do_amigaos_exec3(pTHX_ const char *incmd, int fd, int do_report)
{
dVAR;
- const char **a;
+ const char **argv, **a;
char *s;
char *buf;
char *cmd;
@@ -656,7 +656,9 @@ static I32 S_do_amigaos_exec3(pTHX_ const char *incmd, int fd, int do_report)
PERL_ARGS_ASSERT_DO_EXEC3;
+ ENTER;
Newx(buf, cmdlen, char);
+ SAVEFREEPV(buf);
cmd = buf;
memcpy(cmd, incmd, cmdlen);
@@ -709,15 +711,16 @@ doshell:
PERL_FPU_POST_EXEC
S_exec_failed(aTHX_ PL_sh_path, fd, do_report);
amigaos_post_exec(fd, do_report);
- Safefree(buf);
- return result;
+ goto leave;
}
}
- Newx(PL_Argv, (s - cmd) / 2 + 2, const char *);
- PL_Cmd = savepvn(cmd, s - cmd);
- a = PL_Argv;
- for (s = PL_Cmd; *s;)
+ Newx(argv, (s - cmd) / 2 + 2, const char *);
+ SAVEFREEPV(argv);
+ cmd = savepvn(cmd, s - cmd);
+ SAVEFREEPV(cmd);
+ a = argv;
+ for (s = cmd; *s;)
{
while (isSPACE(*s))
s++;
@@ -729,22 +732,18 @@ doshell:
*s++ = '\0';
}
*a = NULL;
- if (PL_Argv[0])
+ if (argv[0])
{
PERL_FPU_PRE_EXEC
- result = myexecvp(FALSE, PL_Argv[0], EXEC_ARGV_CAST(PL_Argv));
+ result = myexecvp(FALSE, argv[0], EXEC_ARGV_CAST(argv));
PERL_FPU_POST_EXEC
- if (errno == ENOEXEC)
- {
- /* for system V NIH syndrome */
- do_execfree();
+ if (errno == ENOEXEC) /* for system V NIH syndrome */
goto doshell;
- }
- S_exec_failed(aTHX_ PL_Argv[0], fd, do_report);
+ S_exec_failed(aTHX_ argv[0], fd, do_report);
amigaos_post_exec(fd, do_report);
}
- do_execfree();
- Safefree(buf);
+leave:
+ LEAVE;
return result;
}
@@ -754,42 +753,47 @@ I32 S_do_amigaos_aexec5(
dVAR;
I32 result = -1;
PERL_ARGS_ASSERT_DO_AEXEC5;
+ ENTER;
if (sp > mark)
{
- const char **a;
+ const char **argv, **a;
const char *tmps = NULL;
- Newx(PL_Argv, sp - mark + 1, const char *);
- a = PL_Argv;
+ Newx(argv, sp - mark + 1, const char *);
+ SAVEFREEPV(argv);
+ a = argv;
while (++mark <= sp)
{
- if (*mark)
- *a++ = SvPV_nolen_const(*mark);
- else
+ if (*mark) {
+ char *arg = savepv(SvPV_nolen_const(*mark));
+ SAVEFREEPV(arg);
+ *a++ = arg;
+ } else
*a++ = "";
}
*a = NULL;
- if (really)
- tmps = SvPV_nolen_const(really);
- if ((!really && *PL_Argv[0] != '/') ||
+ if (really) {
+ tmps = savepv(SvPV_nolen_const(really));
+ SAVEFREEPV(tmps);
+ }
+ if ((!really && *argv[0] != '/') ||
(really && *tmps != '/')) /* will execvp use PATH? */
TAINT_ENV(); /* testing IFS here is overkill, probably
*/
PERL_FPU_PRE_EXEC
if (really && *tmps)
{
- result = myexecvp(FALSE, tmps, EXEC_ARGV_CAST(PL_Argv));
+ result = myexecvp(FALSE, tmps, EXEC_ARGV_CAST(argv));
}
else
{
- result = myexecvp(FALSE, PL_Argv[0],
- EXEC_ARGV_CAST(PL_Argv));
+ result = myexecvp(FALSE, argv[0], EXEC_ARGV_CAST(argv));
}
PERL_FPU_POST_EXEC
- S_exec_failed(aTHX_(really ? tmps : PL_Argv[0]), fd, do_report);
+ S_exec_failed(aTHX_(really ? tmps : argv[0]), fd, do_report);
}
amigaos_post_exec(fd, do_report);
- do_execfree();
+ LEAVE;
return result;
}
diff --git a/cygwin/cygwin.c b/cygwin/cygwin.c
index a234825eba..fae90af000 100644
--- a/cygwin/cygwin.c
+++ b/cygwin/cygwin.c
@@ -90,11 +90,13 @@ int
do_spawn (char *cmd)
{
dTHX;
- char const **a;
+ char const **argv, **a;
char *s;
char const *metachars = "$&*(){}[]'\";\\?>|<~`\n";
const char *command[4];
+ int result;
+ ENTER;
while (*cmd && isSPACE(*cmd))
cmd++;
@@ -127,13 +129,16 @@ do_spawn (char *cmd)
command[2] = cmd;
command[3] = NULL;
- return do_spawnvp("sh",command);
+ result = do_spawnvp("sh",command);
+ goto leave;
}
- Newx (PL_Argv, (s-cmd)/2+2, const char*);
- PL_Cmd=savepvn (cmd,s-cmd);
- a=PL_Argv;
- for (s=PL_Cmd; *s;) {
+ Newx (argv, (s-cmd)/2+2, const char*);
+ SAVEFREEPV(argv);
+ cmd=savepvn (cmd,s-cmd);
+ SAVEFREEPV(cmd);
+ a=argv;
+ for (s=cmd; *s;) {
while (*s && isSPACE (*s)) s++;
if (*s)
*(a++)=s;
@@ -142,10 +147,13 @@ do_spawn (char *cmd)
*s++='\0';
}
*a = (char*)NULL;
- if (!PL_Argv[0])
- return -1;
-
- return do_spawnvp(PL_Argv[0],(const char * const *)PL_Argv);
+ if (!argv[0])
+ result = -1;
+ else
+ result = do_spawnvp(argv[0],(const char * const *)argv);
+leave:
+ LEAVE;
+ return result;
}
#if (CYGWIN_VERSION_API_MINOR >= 181)
diff --git a/djgpp/djgpp.c b/djgpp/djgpp.c
index d1c09aad67..24d12f254b 100644
--- a/djgpp/djgpp.c
+++ b/djgpp/djgpp.c
@@ -150,9 +150,10 @@ do_aspawn (pTHX_ SV *really,SV **mark,SV **sp)
int
do_spawn2 (pTHX_ char *cmd,int execf)
{
- char **a,*s,*shell,*metachars;
- int rc,unixysh;
+ char **argv,**a,*s,*shell,*metachars;
+ int rc,unixysh,result;
+ ENTER;
if ((shell=getenv("SHELL"))==NULL && (shell=getenv("COMSPEC"))==NULL)
shell="c:\\command.com" EXTRA;
@@ -189,14 +190,18 @@ do_spawn2 (pTHX_ char *cmd,int execf)
}
doshell:
if (execf==EXECF_EXEC)
- return convretcode (execl (shell,shell,unixysh ? "-c" : "/c",cmd,NULL),cmd,execf);
- return convretcode (system (cmd),cmd,execf);
+ result = convretcode (execl (shell,shell,unixysh ? "-c" : "/c",cmd,NULL),cmd,execf);
+ else
+ result = convretcode (system (cmd),cmd,execf);
+ goto leave;
}
- Newx (PL_Argv,(s-cmd)/2+2,char*);
- PL_Cmd=savepvn (cmd,s-cmd);
- a=PL_Argv;
- for (s=PL_Cmd; *s;) {
+ Newx (argv,(s-cmd)/2+2,char*);
+ SAVEFREEPV(argv);
+ cmd=savepvn (cmd,s-cmd);
+ SAVEFREEPV(cmd);
+ a=argv;
+ for (s=cmd; *s;) {
while (*s && isSPACE (*s)) s++;
if (*s)
*(a++)=s;
@@ -205,14 +210,19 @@ doshell:
*s++='\0';
}
*a=NULL;
- if (!PL_Argv[0])
- return -1;
+ if (!argv[0]) {
+ result = -1;
+ goto leave;
+ }
if (execf==EXECF_EXEC)
- rc=execvp (PL_Argv[0],PL_Argv);
+ rc=execvp (argv[0],argv);
else
- rc=spawnvp (P_WAIT,PL_Argv[0],PL_Argv);
- return convretcode (rc,PL_Argv[0],execf);
+ rc=spawnvp (P_WAIT,argv[0],argv);
+ result = convretcode (rc,argv[0],execf);
+leave:
+ LEAVE;
+ return result;
}
int
diff --git a/doio.c b/doio.c
index 9b713e1507..c98a5f5e44 100644
--- a/doio.c
+++ b/doio.c
@@ -1992,56 +1992,53 @@ Perl_do_aexec5(pTHX_ SV *really, SV **mark, SV **sp,
Perl_croak(aTHX_ "exec? I'm not *that* kind of operating system");
#else
assert(sp >= mark);
+ ENTER;
{
- const char **a;
+ const char **argv, **a;
const char *tmps = NULL;
- Newx(PL_Argv, sp - mark + 1, const char*);
- a = PL_Argv;
+ Newx(argv, sp - mark + 1, const char*);
+ SAVEFREEPV(argv);
+ a = argv;
while (++mark <= sp) {
- if (*mark)
- *a++ = SvPV_nolen_const(*mark);
- else
+ if (*mark) {
+ char *arg = savepv(SvPV_nolen_const(*mark));
+ SAVEFREEPV(arg);
+ *a++ = arg;
+ } else
*a++ = "";
}
*a = NULL;
- if (really)
- tmps = SvPV_nolen_const(really);
- if ((!really && PL_Argv[0] && *PL_Argv[0] != '/') ||
+ if (really) {
+ tmps = savepv(SvPV_nolen_const(really));
+ SAVEFREEPV(tmps);
+ }
+ if ((!really && argv[0] && *argv[0] != '/') ||
(really && *tmps != '/')) /* will execvp use PATH? */
TAINT_ENV(); /* testing IFS here is overkill, probably */
PERL_FPU_PRE_EXEC
if (really && *tmps) {
- PerlProc_execvp(tmps,EXEC_ARGV_CAST(PL_Argv));
- } else if (PL_Argv[0]) {
- PerlProc_execvp(PL_Argv[0],EXEC_ARGV_CAST(PL_Argv));
+ PerlProc_execvp(tmps,EXEC_ARGV_CAST(argv));
+ } else if (argv[0]) {
+ PerlProc_execvp(argv[0],EXEC_ARGV_CAST(argv));
} else {
SETERRNO(ENOENT,RMS_FNF);
}
PERL_FPU_POST_EXEC
- S_exec_failed(aTHX_ (really ? tmps : PL_Argv[0] ? PL_Argv[0] : ""), fd, do_report);
+ S_exec_failed(aTHX_ (really ? tmps : argv[0] ? argv[0] : ""), fd, do_report);
}
- do_execfree();
+ LEAVE;
#endif
return FALSE;
}
-void
-Perl_do_execfree(pTHX)
-{
- Safefree(PL_Argv);
- PL_Argv = NULL;
- Safefree(PL_Cmd);
- PL_Cmd = NULL;
-}
-
#ifdef PERL_DEFAULT_DO_EXEC3_IMPLEMENTATION
bool
Perl_do_exec3(pTHX_ const char *incmd, int fd, int do_report)
{
dVAR;
- const char **a;
+ const char **argv, **a;
char *s;
char *buf;
char *cmd;
@@ -2050,7 +2047,9 @@ Perl_do_exec3(pTHX_ const char *incmd, int fd, int do_report)
PERL_ARGS_ASSERT_DO_EXEC3;
+ ENTER;
Newx(buf, cmdlen, char);
+ SAVEFREEPV(buf);
cmd = buf;
memcpy(cmd, incmd, cmdlen);
@@ -2086,8 +2085,7 @@ Perl_do_exec3(pTHX_ const char *incmd, int fd, int do_report)
PERL_FPU_POST_EXEC
*s = '\'';
S_exec_failed(aTHX_ PL_cshname, fd, do_report);
- Safefree(buf);
- return FALSE;
+ goto leave;
}
}
}
@@ -2134,15 +2132,16 @@ Perl_do_exec3(pTHX_ const char *incmd, int fd, int do_report)
PerlProc_execl(PL_sh_path, "sh", "-c", cmd, (char *)NULL);
PERL_FPU_POST_EXEC
S_exec_failed(aTHX_ PL_sh_path, fd, do_report);
- Safefree(buf);
- return FALSE;
+ goto leave;
}
}
- Newx(PL_Argv, (s - cmd) / 2 + 2, const char*);
- PL_Cmd = savepvn(cmd, s-cmd);
- a = PL_Argv;
- for (s = PL_Cmd; *s;) {
+ Newx(argv, (s - cmd) / 2 + 2, const char*);
+ SAVEFREEPV(argv);
+ cmd = savepvn(cmd, s-cmd);
+ SAVEFREEPV(cmd);
+ a = argv;
+ for (s = cmd; *s;) {
while (isSPACE(*s))
s++;
if (*s)
@@ -2153,18 +2152,16 @@ Perl_do_exec3(pTHX_ const char *incmd, int fd, int do_report)
*s++ = '\0';
}
*a = NULL;
- if (PL_Argv[0]) {
+ if (argv[0]) {
PERL_FPU_PRE_EXEC
- PerlProc_execvp(PL_Argv[0],EXEC_ARGV_CAST(PL_Argv));
+ PerlProc_execvp(argv[0],EXEC_ARGV_CAST(argv));
PERL_FPU_POST_EXEC
- if (errno == ENOEXEC) { /* for system V NIH syndrome */
- do_execfree();
+ if (errno == ENOEXEC) /* for system V NIH syndrome */
goto doshell;
- }
- S_exec_failed(aTHX_ PL_Argv[0], fd, do_report);
+ S_exec_failed(aTHX_ argv[0], fd, do_report);
}
- do_execfree();
- Safefree(buf);
+leave:
+ LEAVE;
return FALSE;
}
diff --git a/embed.fnc b/embed.fnc
index ad4df86324..3387026948 100644
--- a/embed.fnc
+++ b/embed.fnc
@@ -437,7 +437,6 @@ Ap |int |do_spawn_nowait|NN char* cmd
#if !defined(WIN32)
p |bool|do_exec3 |NN const char *incmd|int fd|int do_report
#endif
-p |void |do_execfree
#if defined(PERL_IN_DOIO_C)
s |void |exec_failed |NN const char *cmd|int fd|int do_report
#endif
diff --git a/embed.h b/embed.h
index fb4832d43e..a410a355e5 100644
--- a/embed.h
+++ b/embed.h
@@ -1228,7 +1228,6 @@
#define do_aexec5(a,b,c,d,e) Perl_do_aexec5(aTHX_ a,b,c,d,e)
#define do_dump_pad(a,b,c,d) Perl_do_dump_pad(aTHX_ a,b,c,d)
#define do_eof(a) Perl_do_eof(aTHX_ a)
-#define do_execfree() Perl_do_execfree(aTHX)
#define do_ncmp(a,b) Perl_do_ncmp(aTHX_ a,b)
#define do_open6(a,b,c,d,e,f) Perl_do_open6(aTHX_ a,b,c,d,e,f)
#define do_open_raw(a,b,c,d,e,f) Perl_do_open_raw(aTHX_ a,b,c,d,e,f)
diff --git a/embedvar.h b/embedvar.h
index 1a146c4d54..635a01a796 100644
--- a/embedvar.h
+++ b/embedvar.h
@@ -41,9 +41,7 @@
# endif
#define PL_AboveLatin1 (vTHX->IAboveLatin1)
-#define PL_Argv (vTHX->IArgv)
#define PL_Assigned_invlist (vTHX->IAssigned_invlist)
-#define PL_Cmd (vTHX->ICmd)
#define PL_DBcontrol (vTHX->IDBcontrol)
#define PL_DBcv (vTHX->IDBcv)
#define PL_DBgv (vTHX->IDBgv)
diff --git a/intrpvar.h b/intrpvar.h
index d88628a094..006880a37c 100644
--- a/intrpvar.h
+++ b/intrpvar.h
@@ -456,8 +456,6 @@ PERLVARI(I, curcopdb, COP *, NULL)
PERLVAR(I, filemode, int) /* so nextargv() can preserve mode */
PERLVAR(I, lastfd, int) /* what to preserve mode on */
PERLVAR(I, oldname, char *) /* what to preserve mode on */
-PERLVAR(I, Argv, const char **) /* stuff to free from do_aexec, vfork safe */
-PERLVAR(I, Cmd, char *) /* stuff to free from do_aexec, vfork safe */
/* Elements in this array have ';' appended and are injected as a single line
into the tokeniser. You can't put any (literal) newlines into any program
you stuff in into this array, as the point where it's injected is expecting
diff --git a/os2/os2.c b/os2/os2.c
index 66f387bd3c..54c7ef18d9 100644
--- a/os2/os2.c
+++ b/os2/os2.c
@@ -970,7 +970,6 @@ file_type(char *path)
}
/* Spawn/exec a program, revert to shell if needed. */
-/* global PL_Argv[] contains arguments. */
extern ULONG _emx_exception ( EXCEPTIONREPORTRECORD *,
EXCEPTIONREGISTRATIONRECORD *,
@@ -978,7 +977,7 @@ extern ULONG _emx_exception ( EXCEPTIONREPORTRECORD *,
void *);
int
-do_spawn_ve(pTHX_ SV *really, U32 flag, U32 execf, char *inicmd, U32 addflag)
+do_spawn_ve(pTHX_ SV *really, const char **argv, U32 flag, U32 execf, char *inicmd, U32 addflag)
{
int trueflag = flag;
int rc, pass = 1;
@@ -997,16 +996,21 @@ do_spawn_ve(pTHX_ SV *really, U32 flag, U32 execf, char *inicmd, U32 addflag)
if (flag == P_WAIT)
flag = P_NOWAIT;
- if (really && !*(real_name = SvPV(really, n_a)))
- really = NULL;
+ if (really) {
+ real_name = SvPV(really, n_a);
+ real_name = savepv(real_name);
+ SAVEFREEPV(real_name);
+ if (!*real_name)
+ really = NULL;
+ }
retry:
- if (strEQ(PL_Argv[0],"/bin/sh"))
- PL_Argv[0] = PL_sh_path;
+ if (strEQ(argv[0],"/bin/sh"))
+ argv[0] = PL_sh_path;
/* We should check PERL_SH* and PERLLIB_* as well? */
if (!really || pass >= 2)
- real_name = PL_Argv[0];
+ real_name = argv[0];
if (real_name[0] != '/' && real_name[0] != '\\'
&& !(real_name[0] && real_name[1] == ':'
&& (real_name[2] == '/' || real_name[2] != '\\'))
@@ -1098,30 +1102,30 @@ do_spawn_ve(pTHX_ SV *really, U32 flag, U32 execf, char *inicmd, U32 addflag)
}
#if 0
- rc = result(aTHX_ trueflag, spawnvp(flag,real_name,PL_Argv));
+ rc = result(aTHX_ trueflag, spawnvp(flag,real_name,argv));
#else
if (execf == EXECF_TRUEEXEC)
- rc = execvp(real_name,PL_Argv);
+ rc = execvp(real_name,argv);
else if (execf == EXECF_EXEC)
- rc = spawnvp(trueflag | P_OVERLAY,real_name,PL_Argv);
+ rc = spawnvp(trueflag | P_OVERLAY,real_name,argv);
else if (execf == EXECF_SPAWN_NOWAIT)
- rc = spawnvp(flag,real_name,PL_Argv);
+ rc = spawnvp(flag,real_name,argv);
else if (execf == EXECF_SYNC)
- rc = spawnvp(trueflag,real_name,PL_Argv);
+ rc = spawnvp(trueflag,real_name,argv);
else /* EXECF_SPAWN, EXECF_SPAWN_BYFLAG */
rc = result(aTHX_ trueflag,
- spawnvp(flag,real_name,PL_Argv));
+ spawnvp(flag,real_name,argv));
#endif
if (rc < 0 && pass == 1) {
do_script:
- if (real_name == PL_Argv[0]) {
+ if (real_name == argv[0]) {
int err = errno;
if (err == ENOENT || err == ENOEXEC) {
/* No such file, or is a script. */
/* Try adding script extensions to the file name, and
search on PATH. */
- char *scr = find_script(PL_Argv[0], TRUE, NULL, 0);
+ char *scr = find_script(argv[0], TRUE, NULL, 0);
if (scr) {
char *s = 0, *s1;
@@ -1132,7 +1136,7 @@ do_spawn_ve(pTHX_ SV *really, U32 flag, U32 execf, char *inicmd, U32 addflag)
scr = SvPV(scrsv, n_a); /* free()ed later */
file = PerlIO_open(scr, "r");
- PL_Argv[0] = scr;
+ argv[0] = scr;
if (!file)
goto panic_file;
@@ -1148,7 +1152,7 @@ do_spawn_ve(pTHX_ SV *really, U32 flag, U32 execf, char *inicmd, U32 addflag)
does not append ".exe", so we could have
reached this place). */
sv_catpv(scrsv, ".exe");
- PL_Argv[0] = scr = SvPV(scrsv, n_a); /* Reload */
+ argv[0] = scr = SvPV(scrsv, n_a); /* Reload */
if (PerlLIO_stat(scr,&statbuf) >= 0
&& !S_ISDIR(statbuf.st_mode)) { /* Found */
real_name = scr;
@@ -1214,7 +1218,7 @@ do_spawn_ve(pTHX_ SV *really, U32 flag, U32 execf, char *inicmd, U32 addflag)
/* Can jump from far, buf/file invalid if force_shell: */
doshell_args:
{
- char **a = PL_Argv;
+ char **a = argv;
const char *exec_args[2];
if (force_shell
@@ -1240,7 +1244,7 @@ do_spawn_ve(pTHX_ SV *really, U32 flag, U32 execf, char *inicmd, U32 addflag)
}
}
if (!inicmd) {
- s = PL_Argv[0];
+ s = argv[0];
while (*s) {
/* Dosish shells will choke on slashes
in paths, fortunately, this is
@@ -1265,29 +1269,29 @@ do_spawn_ve(pTHX_ SV *really, U32 flag, U32 execf, char *inicmd, U32 addflag)
/* Use the original cmd line */
/* XXXX This is good only until we refuse
quoted arguments... */
- PL_Argv[0] = inicmd;
- PL_Argv[1] = NULL;
+ argv[0] = inicmd;
+ argv[1] = NULL;
}
} else if (!buf[0] && inicmd) { /* No file */
/* Start with the original cmdline. */
/* XXXX This is good only until we refuse
quoted arguments... */
- PL_Argv[0] = inicmd;
- PL_Argv[1] = NULL;
+ argv[0] = inicmd;
+ argv[1] = NULL;
nargs = 2; /* shell -c */
}
while (a[1]) /* Get to the end */
a++;
a++; /* Copy finil NULL too */
- while (a >= PL_Argv) {
- *(a + nargs) = *a; /* PL_Argv was preallocated to be
+ while (a >= argv) {
+ *(a + nargs) = *a; /* argv was preallocated to be
long enough. */
a--;
}
while (--nargs >= 0) /* XXXX Discard const... */
- PL_Argv[nargs] = (char*)argsp[nargs];
+ argv[nargs] = (char*)argsp[nargs];
/* Enable pathless exec if #! (as pdksh). */
pass = (buf[0] == '#' ? 2 : 3);
goto retry;
@@ -1301,23 +1305,23 @@ do_spawn_ve(pTHX_ SV *really, U32 flag, U32 execf, char *inicmd, U32 addflag)
Perl_warner(aTHX_ packWARN(WARN_EXEC), "Can't %s script `%s' with ARGV[0] being `%s'",
((execf != EXECF_EXEC && execf != EXECF_TRUEEXEC)
? "spawn" : "exec"),
- real_name, PL_Argv[0]);
+ real_name, argv[0]);
goto warned;
} else if (errno == ENOENT) { /* Cannot transfer `real_name' via shell. */
if (rc < 0 && ckWARN(WARN_EXEC))
Perl_warner(aTHX_ packWARN(WARN_EXEC), "Can't %s `%s' with ARGV[0] being `%s' (looking for executables only, not found)",
((execf != EXECF_EXEC && execf != EXECF_TRUEEXEC)
? "spawn" : "exec"),
- real_name, PL_Argv[0]);
+ real_name, argv[0]);
goto warned;
}
} else if (rc < 0 && pass == 2 && errno == ENOENT) { /* File not found */
- char *no_dir = strrchr(PL_Argv[0], '/');
+ char *no_dir = strrchr(argv[0], '/');
/* Do as pdksh port does: if not found with /, try without
path. */
if (no_dir) {
- PL_Argv[0] = no_dir + 1;
+ argv[0] = no_dir + 1;
pass++;
goto retry;
}
@@ -1346,11 +1350,12 @@ do_spawn_ve(pTHX_ SV *really, U32 flag, U32 execf, char *inicmd, U32 addflag)
int
do_spawn3(pTHX_ char *cmd, int execf, int flag)
{
- char **a;
+ char **argv, **a;
char *s;
char *shell, *copt, *news = NULL;
int rc, seenspace = 0, mergestderr = 0;
+ ENTER;
#ifdef TRYSHELL
if ((shell = getenv("EMXSHELL")) != NULL)
copt = "-c";
@@ -1441,17 +1446,19 @@ do_spawn3(pTHX_ char *cmd, int execf, int flag)
}
if (news)
Safefree(news);
- return rc;
+ goto leave;
} else if (*s == ' ' || *s == '\t') {
seenspace = 1;
}
}
/* cmd="a" may lead to "sh", "-c", "\"$@\"", "a", "a.cmd", NULL */
- Newx(PL_Argv, (s - cmd + 11) / 2, char*);
- PL_Cmd = savepvn(cmd, s-cmd);
- a = PL_Argv;
- for (s = PL_Cmd; *s;) {
+ Newx(argv, (s - cmd + 11) / 2, char*);
+ SAVEFREEPV(argv);
+ cmd = savepvn(cmd, s-cmd);
+ SAVEFREEPV(cmd);
+ a = argv;
+ for (s = cmd; *s;) {
while (*s && isSPACE(*s)) s++;
if (*s)
*(a++) = s;
@@ -1460,13 +1467,14 @@ do_spawn3(pTHX_ char *cmd, int execf, int flag)
*s++ = '\0';
}
*a = NULL;
- if (PL_Argv[0])
- rc = do_spawn_ve(aTHX_ NULL, flag, execf, cmd, mergestderr);
+ if (argv[0])
+ rc = do_spawn_ve(aTHX_ NULL, argv, flag, execf, cmd, mergestderr);
else
rc = -1;
if (news)
Safefree(news);
- do_execfree();
+leave:
+ LEAVE;
return rc;
}
@@ -1480,14 +1488,16 @@ os2_aspawn_4(pTHX_ SV *really, SV **args, I32 cnt, int execing)
{
SV **argp = (SV **)args;
SV **last = argp + cnt;
- char **a;
+ char **argv, **a;
int rc;
int flag = P_WAIT, flag_set = 0;
STRLEN n_a;
+ ENTER;
if (cnt) {
- Newx(PL_Argv, cnt + 3, char*); /* 3 extra to expand #! */
- a = PL_Argv;
+ Newx(argv, cnt + 3, char*); /* 3 extra to expand #! */
+ SAVEFREEPV(argv);
+ a = argv;
if (cnt > 1 && SvNIOKp(*argp) && !SvPOKp(*argp)) {
flag = SvIVx(*argp);
@@ -1496,24 +1506,27 @@ os2_aspawn_4(pTHX_ SV *really, SV **args, I32 cnt, int execing)
--argp;
while (++argp < last) {
- if (*argp)
- *a++ = SvPVx(*argp, n_a);
- else
+ if (*argp) {
+ char *arg = SvPVx(*argp, n_a);
+ arg = savepv(arg);
+ SAVEFREEPV(arg);
+ *a++ = arg;
+ } else
*a++ = "";
}
*a = NULL;
- if ( flag_set && (a == PL_Argv + 1)
+ if ( flag_set && (a == argv + 1)
&& !really && execing == ASPAWN_WAIT ) { /* One arg? */
rc = do_spawn3(aTHX_ a[-1], EXECF_SPAWN_BYFLAG, flag);
} else {
const int execf[3] = {EXECF_SPAWN, EXECF_EXEC, EXECF_SPAWN_NOWAIT};
- rc = do_spawn_ve(aTHX_ really, flag, execf[execing], NULL, 0);
+ rc = do_spawn_ve(aTHX_ really, argv, flag, execf[execing], NULL, 0);
}
} else
rc = -1;
- do_execfree();
+ LEAVE;
return rc;
}
diff --git a/pp_sys.c b/pp_sys.c
index b078586974..337769b959 100644
--- a/pp_sys.c
+++ b/pp_sys.c
@@ -4480,7 +4480,6 @@ PP(pp_system)
(void)rsignal_restore(SIGQUIT, &qhand);
#endif
STATUS_NATIVE_CHILD_SET(result == -1 ? -1 : status);
- do_execfree(); /* free any memory child malloced on fork */
SP = ORIGMARK;
if (did_pipes) {
int errkid;
@@ -4559,7 +4558,6 @@ PP(pp_system)
if (PL_statusvalue == -1) /* hint that value must be returned as is */
result = 1;
STATUS_NATIVE_CHILD_SET(value);
- do_execfree();
SP = ORIGMARK;
XPUSHi(result ? value : STATUS_CURRENT);
#endif /* !FORK or VMS or OS/2 */
diff --git a/proto.h b/proto.h
index 2a2f25a3e6..80981d43ba 100644
--- a/proto.h
+++ b/proto.h
@@ -744,7 +744,6 @@ PERL_CALLCONV void Perl_do_dump_pad(pTHX_ I32 level, PerlIO *file, PADLIST *padl
PERL_CALLCONV bool Perl_do_eof(pTHX_ GV* gv);
#define PERL_ARGS_ASSERT_DO_EOF \
assert(gv)
-PERL_CALLCONV void Perl_do_execfree(pTHX);
PERL_CALLCONV void Perl_do_gv_dump(pTHX_ I32 level, PerlIO *file, const char *name, GV *sv);
#define PERL_ARGS_ASSERT_DO_GV_DUMP \
assert(file); assert(name)
diff --git a/sv.c b/sv.c
index 924a7e3058..4f45992423 100644
--- a/sv.c
+++ b/sv.c
@@ -15174,8 +15174,6 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
PL_filemode = proto_perl->Ifilemode;
PL_lastfd = proto_perl->Ilastfd;
PL_oldname = proto_perl->Ioldname; /* XXX not quite right */
- PL_Argv = NULL;
- PL_Cmd = NULL;
PL_gensym = proto_perl->Igensym;
PL_laststatval = proto_perl->Ilaststatval;
diff --git a/util.c b/util.c
index 9c989a6e8d..f89922cfa3 100644
--- a/util.c
+++ b/util.c
@@ -2300,7 +2300,6 @@ Perl_my_popen_list(pTHX_ const char *mode, int n, SV **args)
#undef THAT
}
/* Parent */
- do_execfree(); /* free any memory malloced by child on fork */
if (did_pipes)
PerlLIO_close(pp[1]);
/* Keep the lower of the two fd numbers */
@@ -2459,7 +2458,6 @@ Perl_my_popen(pTHX_ const char *cmd, const char *mode)
#undef THIS
#undef THAT
}
- do_execfree(); /* free any memory malloced by child on vfork */
if (did_pipes)
PerlLIO_close(pp[1]);
if (p[that] < p[This]) {
diff --git a/vms/vms.c b/vms/vms.c
index 83e38f1956..7698fac6ed 100644
--- a/vms/vms.c
+++ b/vms/vms.c
@@ -10485,7 +10485,7 @@ vms_execfree(struct dsc$descriptor_s *vmscmd)
static char *
setup_argstr(pTHX_ SV *really, SV **mark, SV **sp)
{
- char *junk, *tmps = NULL;
+ char *junk, *tmps = NULL, *cmd;
size_t cmdlen = 0;
size_t rlen;
SV **idx;
@@ -10506,22 +10506,23 @@ setup_argstr(pTHX_ SV *really, SV **mark, SV **sp)
cmdlen += rlen ? rlen + 1 : 0;
}
}
- Newx(PL_Cmd, cmdlen+1, char);
+ Newx(cmd, cmdlen+1, char);
+ SAVEFREEPV(cmd);
if (tmps && *tmps) {
- my_strlcpy(PL_Cmd, tmps, cmdlen + 1);
+ my_strlcpy(cmd, tmps, cmdlen + 1);
mark++;
}
- else *PL_Cmd = '\0';
+ else *cmd = '\0';
while (++mark <= sp) {
if (*mark) {
char *s = SvPVx(*mark,n_a);
if (!*s) continue;
- if (*PL_Cmd) my_strlcat(PL_Cmd, " ", cmdlen+1);
- my_strlcat(PL_Cmd, s, cmdlen+1);
+ if (*cmd) my_strlcat(cmd, " ", cmdlen+1);
+ my_strlcat(cmd, s, cmdlen+1);
}
}
- return PL_Cmd;
+ return cmd;
} /* end of setup_argstr() */
@@ -10948,9 +10949,10 @@ Perl_vms_do_aexec(pTHX_ SV *really,SV **mark,SV **sp)
}
/* no vfork - act VMSish */
if (sp > mark) {
+ ENTER;
cmd = setup_argstr(aTHX_ really,mark,sp);
exec_sts = vms_do_exec(cmd);
- Safefree(cmd); /* Clean up from setup_argstr() */
+ LEAVE;
return exec_sts;
}
@@ -11039,8 +11041,10 @@ Perl_do_aspawn(pTHX_ SV* really, SV** mark, SV** sp)
else
flags = 0;
+ ENTER;
cmd = setup_argstr(aTHX_ really, mark, sp);
sts = do_spawn2(aTHX_ cmd, flags);
+ LEAVE;
/* pp_sys will clean up cmd */
return sts;
}
@@ -11075,9 +11079,6 @@ do_spawn2(pTHX_ const char *cmd, int flags)
{
unsigned long int sts, substs;
- /* The caller of this routine expects to Safefree(PL_Cmd) */
- Newx(PL_Cmd,10,char);
-
TAINT_ENV();
TAINT_PROPER("spawn");
if (!cmd || !*cmd) {