The joy of $0. Undoing the #16399 makes Andreas'
Jarkko Hietaniemi [Sun, 29 Jun 2003 15:41:05 +0000 (15:41 +0000)]
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

mg.c
perl.c
pod/perlvar.pod

diff --git a/mg.c b/mg.c
index 98ccb34..8182376 100644 (file)
--- 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 (file)
--- 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. */
index ad791dd..7667f1d 100644 (file)
@@ -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