summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJarkko Hietaniemi <jhi@iki.fi>2003-06-29 15:41:05 +0000
committerJarkko Hietaniemi <jhi@iki.fi>2003-06-29 15:41:05 +0000
commit54bfe034ba642318cf2c7d0b37579f30adef144a (patch)
tree9d4a1a11a7d2ea0e6bab798b52a7d08ff374981a
parent52d59bef96c881381bce1bcb84a8c08ce48c2544 (diff)
downloadperl-54bfe034ba642318cf2c7d0b37579f30adef144a.tar.gz
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
-rw-r--r--mg.c72
-rw-r--r--perl.c37
-rw-r--r--pod/perlvar.pod15
3 files changed, 67 insertions, 57 deletions
diff --git a/mg.c b/mg.c
index 98ccb34e3d..8182376662 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 bb45684638..2f07f4cb80 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 ad791dd71b..7667f1d75d 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<ps>
-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<sh> and B<ksh>.)
+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<ps> 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<sh> and B<ksh>.)
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