diff options
author | Zefram <zefram@fysh.org> | 2017-12-06 21:27:15 +0000 |
---|---|---|
committer | Zefram <zefram@fysh.org> | 2017-12-14 22:48:30 +0000 |
commit | 282fc0b3cc2439f69587d980b62bef7f5d5bdfef (patch) | |
tree | 6dc6abf858b4903d0adb99d6309a74f84ebf7782 | |
parent | e135ff695231a81e2a70a739e8d813525432fd4d (diff) | |
download | perl-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.c | 66 | ||||
-rw-r--r-- | cygwin/cygwin.c | 28 | ||||
-rw-r--r-- | djgpp/djgpp.c | 36 | ||||
-rw-r--r-- | doio.c | 77 | ||||
-rw-r--r-- | embed.fnc | 1 | ||||
-rw-r--r-- | embed.h | 1 | ||||
-rw-r--r-- | embedvar.h | 2 | ||||
-rw-r--r-- | intrpvar.h | 2 | ||||
-rw-r--r-- | os2/os2.c | 109 | ||||
-rw-r--r-- | pp_sys.c | 2 | ||||
-rw-r--r-- | proto.h | 1 | ||||
-rw-r--r-- | sv.c | 2 | ||||
-rw-r--r-- | util.c | 2 | ||||
-rw-r--r-- | vms/vms.c | 23 |
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 @@ -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; } @@ -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 @@ -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 @@ -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; } @@ -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 */ @@ -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) @@ -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; @@ -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]) { @@ -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) { |