From: Jarkko Hietaniemi Date: Sun, 29 Jun 2003 15:41:05 +0000 (+0000) Subject: The joy of $0. Undoing the #16399 makes Andreas' X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=54bfe034ba642318cf2c7d0b37579f30adef144a;p=p5sagit%2Fp5-mst-13.2.git The joy of $0. Undoing the #16399 makes Andreas' tests (see [perl #22811]) pass (yes, padding with space instead of nul makes no sense, but that seems to work, maybe Linux does some deep magic in ps(1)?); moving the PL_origalen computation earlier makes also the threaded-first case fully pass. But in general modifying the argv[] is very non-portable. (e.g. in Tru64 it seems to be limited to the size of the original argv[0] since the argv[] are not contiguous?) Everybody should just have setproctitle(). p4raw-id: //depot/perl@19884 --- diff --git a/mg.c b/mg.c index 98ccb34..8182376 100644 --- a/mg.c +++ b/mg.c @@ -2372,60 +2372,32 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg) pstat(PSTAT_SETCMD, un, len, 0, 0); } #endif - if (!PL_origalen) { - s = PL_origargv[0]; - s += strlen(s); - /* See if all the arguments are contiguous in memory */ - for (i = 1; i < PL_origargc; i++) { - if (PL_origargv[i] == s + 1 -#ifdef OS2 - || PL_origargv[i] == s + 2 -#endif - ) - { - ++s; - s += strlen(s); /* this one is ok too */ - } - else - break; - } - /* can grab env area too? */ - if (PL_origenviron -#ifdef USE_ITHREADS - && PL_curinterp == aTHX -#endif - && (PL_origenviron[0] == s + 1)) - { - my_setenv("NoNe SuCh", Nullch); - /* force copy of environment */ - for (i = 0; PL_origenviron[i]; i++) - if (PL_origenviron[i] == s + 1) { - ++s; - s += strlen(s); - } - else - break; - } - PL_origalen = s - PL_origargv[0]; - } + /* PL_origalen is set in perl_parse() to be the sum + * of the contiguous argv[] elements plus the size of + * the env in case that is contiguous with the argv[]. + * + * This means that in the worst case the area we are able + * to modify is limited to the size of the original argv[0]. + * --jhi */ s = SvPV_force(sv,len); - i = len; - if (i >= (I32)PL_origalen) { - i = PL_origalen; - /* don't allow system to limit $0 seen by script */ - /* SvCUR_set(sv, i); *SvEND(sv) = '\0'; */ - Copy(s, PL_origargv[0], i, char); - s = PL_origargv[0]+i; - *s = '\0'; + if (len >= (I32)PL_origalen) { + /* Longer than original, will be truncated. */ + Copy(s, PL_origargv[0], PL_origalen, char); + PL_origargv[0][PL_origalen - 1] = 0; } else { - Copy(s, PL_origargv[0], i, char); - s = PL_origargv[0]+i; - *s++ = '\0'; - while (++i < (I32)PL_origalen) - *s++ = '\0'; + /* Shorter than original, will be padded. */ + Copy(s, PL_origargv[0], len, char); + PL_origargv[0][len] = 0; + memset(PL_origargv[0] + len + 1, + /* Is the space counterintuitive? Yes. + * (You were expecting \0?) + * Does it work? Seems to. (In Linux at least.) + * --jhi */ + (int)' ', + PL_origalen - len - 1); for (i = 1; i < PL_origargc; i++) - PL_origargv[i] = Nullch; + PL_origargv[i] = 0; } UNLOCK_DOLLARZERO_MUTEX; break; diff --git a/perl.c b/perl.c index bb45684..2f07f4c 100644 --- a/perl.c +++ b/perl.c @@ -933,6 +933,43 @@ setuid perl scripts securely.\n"); PL_origargc = argc; PL_origargv = argv; + { + char *s = PL_origargv[0]; + int i; + + s += strlen(s); + /* See if all the arguments are contiguous in memory */ + for (i = 1; i < PL_origargc; i++) { + if (PL_origargv[i] == s + 1 +#ifdef OS2 + || PL_origargv[i] == s + 2 +#endif + ) + { + ++s; + s += strlen(s); /* this one is ok too */ + } + else + break; + } + /* Can we grab env area too to be used as the area for $0 + * (in case we later modify it)? */ + if (PL_origenviron + && (PL_origenviron[0] == s + 1)) + { + my_setenv("NoNe SuCh", Nullch); + /* force copy of environment */ + for (i = 0; PL_origenviron[i]; i++) + if (PL_origenviron[i] == s + 1) { + ++s; + s += strlen(s); + } + else + break; + } + PL_origalen = s - PL_origargv[0]; + } + if (PL_do_undump) { /* Come here if running an undumped a.out. */ diff --git a/pod/perlvar.pod b/pod/perlvar.pod index ad791dd..7667f1d 100644 --- a/pod/perlvar.pod +++ b/pod/perlvar.pod @@ -838,16 +838,17 @@ and C<$)> can be swapped only on machines supporting setregid(). =item $0 -Contains the name of the program being executed. On some operating -systems assigning to C<$0> modifies the argument area that the B -program sees. This is more useful as a way of indicating the current -program state than it is for hiding the program you're running. -(Mnemonic: same as B and B.) +Contains the name of the program being executed. On some (read: not +all) operating systems assigning to C<$0> modifies the argument area +that the B program sees. Also note that depending on the platform, +the maximum length of C<$0> may be limited to the space occupied by +the original C<$0>. This is more useful as a way of indicating the +current program state than it is for hiding the program you're +running. (Mnemonic: same as B and B.) Note for BSD users: setting C<$0> does not completely remove "perl" from the ps(1) output. For example, setting C<$0> to C<"foobar"> will -result in C<"perl: foobar (perl)">. This is an operating system -feature. +result in C<"perl: foobar (perl)">. This is an operating system feature. In multithreaded scripts Perl coordinates the threads so that any thread may modify its copy of the C<$0> and the change becomes visible