[patch@25809]restore documented exit behavior
John E. Malmberg [Thu, 20 Oct 2005 18:21:20 +0000 (14:21 -0400)]
From: "John E. Malmberg" <wb8tyw@qsl.net>
Message-id: <43581860.3020108@qsl.net>

p4raw-id: //depot/perl@25810

mg.c
perl.c
perl.h
t/op/exec.t
vms/perlvms.pod
vms/vms.c

diff --git a/mg.c b/mg.c
index 17f9a24..5754732 100644 (file)
--- a/mg.c
+++ b/mg.c
@@ -2397,10 +2397,10 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg)
 #endif
 #ifdef VMSISH_STATUS
        if (VMSISH_STATUS)
-           STATUS_NATIVE_SET((U32)(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv)));
+           STATUS_NATIVE_CHILD_SET((U32)SvIV(sv));
        else
 #endif
-           STATUS_UNIX_SET(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv));
+           STATUS_UNIX_EXIT_SET(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv));
        break;
     case '!':
         {
diff --git a/perl.c b/perl.c
index 102a8bd..1a4b889 100644 (file)
--- a/perl.c
+++ b/perl.c
@@ -5165,16 +5165,18 @@ void
 Perl_my_failure_exit(pTHX)
 {
 #ifdef VMS
-    if (vaxc$errno & 1) {
-       if (STATUS_NATIVE & 1)          /* fortuitiously includes "-1" */
-           STATUS_NATIVE_SET(44);
-    }
-    else {
-       if (!vaxc$errno)                /* unlikely */
-           STATUS_NATIVE_SET(44);
-       else
-           STATUS_NATIVE_SET(vaxc$errno);
-    }
+     /* We have been called to fall on our sword.  The desired exit code
+      * should be already set in STATUS_UNIX, but could be shifted over
+      * by 8 bits.  STATUS_UNIX_EXIT_SET will fix all cases where
+      * an error code has been set.
+      *
+      * If an error code has not been set, then force the issue.
+      */
+    if (STATUS_UNIX == 0)   /* No errors or status recorded? */
+       STATUS_ALL_FAILURE; /* Ok, force the issue with a generic code */
+    else
+      STATUS_UNIX_EXIT_SET(STATUS_UNIX);
+
 #else
     int exitstatus;
     if (errno & 255)
diff --git a/perl.h b/perl.h
index 9d48457..11cfc75 100644 (file)
--- a/perl.h
+++ b/perl.h
@@ -390,7 +390,7 @@ register struct op *Perl_op asm(stringify(OP_IN_REGISTER));
 #define DOSISH 1
 #endif
 
-#if defined(__STDC__) || defined(vax11c) || defined(_AIX) || defined(__stdc__) || defined(__cplusplus) || defined(EPOC) || defined(NETWARE) || defined(__SYMBIAN32__)
+#if defined(__STDC__) || defined(_AIX) || defined(__stdc__) || defined(__cplusplus) || defined(EPOC) || defined(NETWARE) || defined(__SYMBIAN32__)
 # define STANDARD_C 1
 #endif
 
@@ -2574,24 +2574,29 @@ typedef pthread_key_t   perl_key;
        (((I32)PL_statusvalue_vms == -1 ? SS$_ABORT : PL_statusvalue_vms) | \
           (VMSISH_HUSHED ? STS$M_INHIB_MSG : 0))
 
-/* STATUS_NATIVE_SET - takes a NATIVE status code and converts it to a
- * UNIX/POSIX status value and updates both the native and PL_statusvalue
- * as needed.  This currently seems only exist for VMS and is used in the exit
- * handling.
- */
-
-#   define STATUS_NATIVE_SET(n) STATUS_NATIVE_SET_PORC(n, 0)
 
-/* STATUS_NATIVE_CHILD_SET - same as STATUS_NATIVE_SET, but shifts the UNIX
- * value over the correct number of bits to be a child status.  Usually
- * the number of bits is 8, but that could be platform dependent.  The NATIVE
- * status code is presumed to have either from a child process.
+/* STATUS_NATIVE_CHILD_SET - Calculate UNIX status that matches the child
+ * exit code and shifts the UNIX value over the correct number of bits to
+ * be a child status.  Usually the number of bits is 8, but that could be
+ * platform dependent.  The NATIVE status code is presumed to have either
+ * from a child process.
  */
 
-#   define STATUS_NATIVE_CHILD_SET(n) STATUS_NATIVE_SET_PORC(n, 1)
+/* This is complicated.  The child processes return a true native VMS
+   status which must be saved.  But there is an assumption in Perl that
+   the UNIX child status has some relationship to errno values, so
+   Perl tries to translate it to text in some of the tests.  
+   In order to get the string translation correct, for the error, errno
+   must be EVMSERR, but that generates a different text message
+   than what the test programs are expecting.  So an errno value must
+   be derived from the native status value when an error occurs.
+   That will hide the true native status message.  With this version of
+   perl, the true native child status can always be retrieved so that
+   is not a problem.  But in this case, Pl_statusvalue and errno may
+   have different values in them.
+ */
 
-  /* internal convert VMS status codes to UNIX error or status codes */
-#   define STATUS_NATIVE_SET_PORC(n, _x)                               \
+#   define STATUS_NATIVE_CHILD_SET(n) \
        STMT_START {                                                    \
            I32 evalue = (I32)n;                                        \
            if (evalue == EVMSERR) {                                    \
@@ -2599,14 +2604,16 @@ typedef pthread_key_t   perl_key;
              PL_statusvalue = evalue;                                  \
            } else {                                                    \
              PL_statusvalue_vms = evalue;                              \
-             if ((I32)PL_statusvalue_vms == -1) {                      \
+             if (evalue == -1) {                                       \
                PL_statusvalue = -1;                                    \
                PL_statusvalue_vms = SS$_ABORT; /* Should not happen */ \
              } else                                                    \
-               PL_statusvalue = Perl_vms_status_to_unix(evalue, _x);   \
+               PL_statusvalue = Perl_vms_status_to_unix(evalue, 1);    \
              set_vaxc_errno(evalue);                                   \
-             set_errno(PL_statusvalue);                                \
-             if (_x) PL_statusvalue = PL_statusvalue << child_offset_bits; \
+             if ((PL_statusvalue_vms & C_FAC_POSIX) == C_FAC_POSIX)    \
+                 set_errno(EVMSERR);                                   \
+             else set_errno(Perl_vms_status_to_unix(evalue, 0));       \
+             PL_statusvalue = PL_statusvalue << child_offset_bits;     \
            }                                                           \
        } STMT_END
 
@@ -2641,42 +2648,56 @@ typedef pthread_key_t   perl_key;
 
   /* STATUS_UNIX_EXIT_SET - Takes a UNIX/POSIX exit code and sets
    * the NATIVE error status based on it.  It does not assume that
-   * the UNIX/POSIX exit codes have any relationship to errno
-   * values and are only being encoded into the NATIVE form so
-   * that they can be properly passed through to the calling
-   * program or shell.
+   * the UNIX/POSIX exit codes have any relationship to errno, except
+   * that 0 indicates a success.  When in the default mode to comply
+   * with the Perl VMS documentation, anything other than 0 indicates
+   * a native status should be set to the failure code SS$_ABORT;
+   *
+   * In the new POSIX EXIT mode, native status will be set so that the
+   * actual exit code will can be retrieved by the calling program or
+   * shell.
+   *
+   * If the exit code is not clearly a UNIX parent or child exit status,
+   * it will be passed through as a VMS status.
    */
 
-#   define STATUS_UNIX_EXIT_SET(n)                             \
+#   define STATUS_UNIX_EXIT_SET(n)                     \
        STMT_START {                                    \
            I32 evalue = (I32)n;                        \
            PL_statusvalue = evalue;                    \
-           if (PL_statusvalue != -1) {                 \
-               if (PL_statusvalue != EVMSERR) {        \
-                 if (PL_statusvalue < 256) {           \
-                     if (PL_statusvalue == 0)          \
-                       PL_statusvalue_vms == SS$_NORMAL; \
-                     else \
-                       PL_statusvalue_vms = MY_POSIX_EXIT ? \
-                         (C_FAC_POSIX | (evalue << 3 ) | (evalue == 1)? \
-                           (STS$K_ERROR | STS$M_INHIB_MSG) : 0) : evalue; \
-                 } else { /* forgive them Perl, for they have sinned */ \
-                     PL_statusvalue_vms = evalue;              \
-                 }  /* And obviously used a VMS status value instead of UNIX */ \
-                 PL_statusvalue = EVMSERR;             \
-               }                                               \
-               else {                                          \
-                 PL_statusvalue_vms = vaxc$errno;              \
-               }                                               \
+           if (evalue != -1) {                         \
+             if (evalue <= 0xFF00) {                   \
+               if (evalue > 0xFF)                      \
+                 evalue = (evalue >> child_offset_bits) & 0xFF; \
+               if (evalue == 0)                        \
+                 PL_statusvalue_vms == SS$_NORMAL;     \
+               else                                    \
+                 if (MY_POSIX_EXIT)                    \
+                   PL_statusvalue_vms =        \
+                      (C_FAC_POSIX | (evalue << 3 ) | (evalue == 1)? \
+                       (STS$K_ERROR | STS$M_INHIB_MSG) : 0); \
+                 else PL_statusvalue_vms = SS$_ABORT; \
+             } else { /* forgive them Perl, for they have sinned */ \
+               if (evalue != EVMSERR) PL_statusvalue_vms = evalue; \
+               else PL_statusvalue_vms = vaxc$errno;           \
+               /* And obviously used a VMS status value instead of UNIX */ \
+               PL_statusvalue = EVMSERR;                               \
+             }                                                 \
            }                                                   \
            else PL_statusvalue_vms = SS$_ABORT;                \
            set_vaxc_errno(PL_statusvalue_vms);                 \
        } STMT_END
+
+
+ /* This macro forces a success status */
 #   define STATUS_ALL_SUCCESS  \
        (PL_statusvalue = 0, PL_statusvalue_vms = SS$_NORMAL)
+
+ /* This macro forces a failure status */
 #   define STATUS_ALL_FAILURE  (PL_statusvalue = 1, \
      vaxc$errno = PL_statusvalue_vms = MY_POSIX_EXIT ? \
        (C_FAC_POSIX | (1 << 3) | STS$K_ERROR | STS$M_INHIB_MSG) : SS$_ABORT)
+
 #else
 #   define STATUS_NATIVE       PL_statusvalue_posix
 #   if defined(WCOREDUMP)
index 8e0e16f..a6eeeb5 100755 (executable)
@@ -90,14 +90,13 @@ is( system(qq{$Perl "-I../lib" -e "use vmsish qw(hushed); exit 1"}), $exit_one,
     'Explicit exit of 1' );
 
 $rc = system { "lskdfj" } "lskdfj";
-$rc = 256 if ($rc == 5632) && $Is_VMS;
 unless( ok($rc == 255 << 8 or $rc == -1 or $rc == 256 or $rc == 512) ) {
     print "# \$rc == $rc\n";
 }
 
 unless ( ok( $! == 2  or  $! =~ /\bno\b.*\bfile/i or  
              $! == 13 or  $! =~ /permission denied/i or
-             $! == 22 or  $! =~ /invalid argument/           ) ) {
+             $! == 22 or  $! =~ /invalid argument/  ) ) {
     printf "# \$! eq %d, '%s'\n", $!, $!;
 }
 
index a277da3..685e39c 100644 (file)
@@ -195,14 +195,14 @@ interconversion between VMS and Unix syntax; its
 documentation provides more details.
 
 Perl is now in the process of evolving to follow the setting of
-the DECC$* feature logicals in the interpretation of UNIX pathnames.
+the DECC$* feature logical names in the interpretation of UNIX pathnames.
 This is still a work in progress.
 
 For handling extended characters, and case sensitivity, as long as
 DECC$POSIX_COMPLIANT_PATHNAMES, DECC$FILENAME_UNIX_REPORT, and
 DECC$FILENAME_UNIX_ONLY are not set, then the older Perl behavior
 for conversions of file specifications from UNIX to VMS is followed,
-except that VMS paths with concealed rooted logicals are now
+except that VMS paths with concealed rooted logical names are now
 translated correctly to UNIX paths.
 
 With those features set, then new routines may handle the translation,
@@ -271,7 +271,7 @@ Programs should use the File::Spec:case_tolerant setting to determine
 the state, and not the $^O setting.
 
 For consistency, when the above feature is clear and when not
-otherwise overridden by DECC feature logicals, most Perl routines
+otherwise overridden by DECC feature logical names, most Perl routines
 return file specifications using lower case letters only,
 regardless of the case used in the arguments passed to them.
 (This is true only when running under VMS; Perl respects the
@@ -562,7 +562,7 @@ st_mode field.  Finally, C<-d> returns true if passed a device
 specification without an explicit directory (e.g. C<DUA1:>), as
 well as if passed a directory.
 
-There are DECC feature logicals AND ODS-5 volume attributes that
+There are DECC feature logical names AND ODS-5 volume attributes that
 also control what values are returned for the date fields.
 
 Note: Some sites have reported problems when using the file-access
@@ -812,6 +812,9 @@ change the file protection to delete the file, and you interrupt it
 in midstream, the file may be left intact, but with a changed ACL
 allowing you delete access.
 
+This behavior of C<unlink> is to be compatible with POSIX behavior
+and not traditional VMS behavior.
+
 =item utime LIST
 
 Since ODS-2, the VMS file structure for disk files, does not keep
@@ -968,7 +971,7 @@ a fatal error.  This is equivalent to doing the following from DCL:
     DELETE/LOGICAL *
 
 You can imagine how bad things would be if, for example, the SYS$MANAGER
-or SYS$SYSTEM logicals were deleted.
+or SYS$SYSTEM logical names were deleted.
 
 At present, the first time you iterate over %ENV using
 C<keys>, or C<values>,  you will incur a time penalty as all
@@ -977,12 +980,13 @@ Subsequent iterations will not reread logical names, so they
 won't be as slow, but they also won't reflect any changes
 to logical name tables caused by other programs.
 
-You do need to be careful with the logicals representing process-permanent
-files, such as C<SYS$INPUT> and C<SYS$OUTPUT>.  The translations for these
-logicals are prepended with a two-byte binary value (0x1B 0x00) that needs to be
-stripped off if you want to use it. (In previous versions of Perl it wasn't
-possible to get the values of these logicals, as the null byte acted as an
-end-of-string marker)
+You do need to be careful with the logical names representing
+process-permanent files, such as C<SYS$INPUT> and C<SYS$OUTPUT>.
+The translations for these logical names are prepended with a
+two-byte binary value (0x1B 0x00) that needs to be stripped off
+if you wantto use it. (In previous versions of Perl it wasn't
+possible to get the values of these logical names, as the null
+byte acted as an end-of-string marker)
 
 =item $!
 
@@ -1026,8 +1030,9 @@ contain the actual value of 0 to 255 returned by that program
 on a normal exit.
 
 With the _POSIX_EXIT macro set, the exit code of zero is represented
-as 1, and the values from 1 to 255 are encoded by the equation
-VMS_status = 0x35a000 + (exit_code * 8).
+as 1, and the values from 2 to 255 are encoded by the equation
+VMS_status = 0x35a000 + (exit_code * 8) + 1.  And in the special
+case of value 1, VMS_status = 0x35a000 + 8 + 2 + 0x10000000.
 
 For other termination statuses, the severity portion of the
 subprocess' exit status: if the severity was success or
@@ -1053,6 +1058,11 @@ call traditional VMS programs will be expecting the previous behavior.
 
 And success is always the code 0.
 
+When the actual VMS termination status of the child is an error,
+internally the C<$!> value will be set to the closest UNIX code to
+that error so that Perl scripts that test for error messages will
+see the expected UNIX style error message instead of a VMS message.
+
 Conversely, when setting C<$?> in an END block, an attempt is made
 to convert the POSIX value into a native status intelligible to
 the operating system upon exiting Perl.  What this boils down to
index ffb3c10..d4b81c3 100644 (file)
--- a/vms/vms.c
+++ b/vms/vms.c
@@ -1865,7 +1865,9 @@ int unix_status;
     case SS$_NOSUCHOBJECT:
        unix_status = ENOENT;
        break;
-    case SS$_ABORT:
+    case SS$_ABORT:                                /* Fatal case */
+    case ((SS$_ABORT & STS$M_COND_ID) | STS$K_ERROR): /* Error case */
+    case ((SS$_ABORT & STS$M_COND_ID) | STS$K_WARNING): /* Warning case */
        unix_status = EINTR;
        break;
     case SS$_BUFFEROVF: