[patch@34779] Get posix exit mode working/tested on VMS
John E. Malmberg [Sun, 9 Nov 2008 00:46:03 +0000 (18:46 -0600)]
From: "John E. Malmberg" <wb8tyw@qsl.net>
Message-id: <4916872B.5040500@qsl.net>

p4raw-id: //depot/perl@34790

perl.h
t/run/exit.t
vms/vms.c

diff --git a/perl.h b/perl.h
index 526155b..d08a4a6 100644 (file)
--- a/perl.h
+++ b/perl.h
@@ -2941,9 +2941,9 @@ typedef pthread_key_t     perl_key;
                  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) : 1); \
+                   PL_statusvalue_vms =                \
+                      (C_FAC_POSIX | (evalue << 3 ) |  \
+                      ((evalue == 1) ? (STS$K_ERROR | STS$M_INHIB_MSG) : 1)); \
                  else                                  \
                    PL_statusvalue_vms = SS$_ABORT; \
              } else { /* forgive them Perl, for they have sinned */ \
@@ -2969,6 +2969,9 @@ typedef pthread_key_t     perl_key;
    * actual exit code will can be retrieved by the calling program or
    * shell.
    *
+   * A POSIX exit code is from 0 to 255.  If the exit code is higher
+   * than this, it needs to be assumed that it is a VMS exit code and
+   * passed through.
    */
 
 #   define STATUS_EXIT_SET(n)                          \
@@ -2976,9 +2979,10 @@ typedef pthread_key_t    perl_key;
            I32 evalue = (I32)n;                        \
            PL_statusvalue = evalue;                    \
            if (MY_POSIX_EXIT)                          \
-               PL_statusvalue_vms =                    \
-                 (C_FAC_POSIX | (evalue << 3 ) | (evalue == 1)? \
-                  (STS$K_ERROR | STS$M_INHIB_MSG) : 1); \
+               if (evalue > 255) PL_statusvalue_vms = evalue; else {   \
+                 PL_statusvalue_vms = \
+                   (C_FAC_POSIX | (evalue << 3 ) |     \
+                    ((evalue == 1) ? (STS$K_ERROR | STS$M_INHIB_MSG) : 1));} \
            else                                        \
                PL_statusvalue_vms = evalue ? evalue : SS$_NORMAL; \
            set_vaxc_errno(PL_statusvalue_vms);         \
index 2b2b99d..f59584c 100644 (file)
@@ -20,6 +20,24 @@ BEGIN {
     $numtests = ($^O eq 'VMS') ? 16 : ($^O eq 'MacOS') ? 0 : 17;
 }
 
+
+my $vms_exit_mode = 0;
+
+if ($^O eq 'VMS') {
+    if (eval 'require VMS::Feature') {
+        $vms_exit_mode = !(VMS::Feature::current("posix_exit"));
+    } else {
+        my $unix_rpt = $ENV{'DECC$FILENAME_UNIX_REPORT'} =~ /^[ET1]/i; 
+        my $posix_ex = $ENV{'PERL_VMS_POSIX_EXIT'} =~ /^[ET1]/i;
+        if (($unix_rpt || $posix_ex) ) {
+            $vms_exit_mode = 0;
+        } else {
+            $vms_exit_mode = 1;
+        }
+    }
+    $numtests = 29 unless $vms_exit_mode;
+}
+
 require "test.pl";
 plan(tests => $numtests);
 
@@ -34,7 +52,7 @@ is( $exit >> 8, 0,              'Normal exit' );
 is( $exit, $?,                  'Normal exit $?' );
 is( ${^CHILD_ERROR_NATIVE}, $native_success,  'Normal exit ${^CHILD_ERROR_NATIVE}' );
 
-if ($^O ne 'VMS') {
+if (!$vms_exit_mode) {
   my $posix_ok = eval { require POSIX; };
   my $wait_macros_ok = defined &POSIX::WIFEXITED;
   eval { POSIX::WIFEXITED() };
@@ -52,7 +70,11 @@ if ($^O ne 'VMS') {
   }
 
   SKIP: {
-    skip("Skip signals and core dump tests on Win32", 7) if $^O eq 'MSWin32';
+    skip("Skip signals and core dump tests on Win32 and VMS", 7) 
+        if ($^O eq 'MSWin32' || $^O eq 'VMS');
+
+    #TODO VMS will backtrace on this test and exits with code of 0
+    #instead of 15.
 
     $exit = run('kill 15, $$; sleep(1);');
 
@@ -69,7 +91,9 @@ if ($^O ne 'VMS') {
     }
   }
 
-} else {
+}
+
+if ($^O eq 'VMS') {
 
 # On VMS, successful returns from system() are reported 0,  VMS errors that
 # can not be translated to UNIX are reported as EVMSERR, which has a value
@@ -139,7 +163,7 @@ $exit = run("END { \$? = $exit_arg }");
 # status codes to SS$_ABORT on exit, but passes through unmodified UNIX
 # status codes that exit() is called with by scripts.
 
-$exit_arg = (44 & 7) if $^O eq 'VMS';  
+$exit_arg = (44 & 7) if $vms_exit_mode;
 
 is( $exit >> 8, $exit_arg,             'Changing $? in END block' );
 }
index e11ed59..e674a8a 100644 (file)
--- a/vms/vms.c
+++ b/vms/vms.c
@@ -353,6 +353,7 @@ static int vms_process_case_tolerant = 1;
 int vms_vtf7_filenames = 0;
 int gnv_unix_shell = 0;
 static int vms_unlink_all_versions = 0;
+static int vms_posix_exit = 0;
 
 /* bug workarounds if needed */
 int decc_bug_readdir_efs1 = 0;
@@ -13080,9 +13081,7 @@ Perl_sys_intern_init(pTHX)
 
     VMSISH_HUSHED = 0;
 
-    /* fix me later to track running under GNV */
-    /* this allows some limited testing */
-    MY_POSIX_EXIT = decc_filename_unix_report;
+    MY_POSIX_EXIT = vms_posix_exit;
 
     x = (float)ix;
     MY_INV_RAND_MAX = 1./x;
@@ -13556,7 +13555,6 @@ static int set_features
     gnv_unix_shell = 0;
     status = sys_trnlnm("GNV$UNIX_SHELL", val_str, sizeof(val_str));
     if ($VMS_STATUS_SUCCESS(status)) {
-       if ((val_str[0] == 'E') || (val_str[0] == '1') || (val_str[0] == 'T')) {
         gnv_unix_shell = 1;
         set_feature_default("DECC$EFS_CASE_PRESERVE", 1);
         set_feature_default("DECC$EFS_CHARSET", 1);
@@ -13565,9 +13563,7 @@ static int set_features
         set_feature_default("DECC$READDIR_DROPDOTNOTYPE", 1);
         set_feature_default("DECC$DISABLE_POSIX_ROOT", 0);
         vms_unlink_all_versions = 1;
-       }
-       else
-        gnv_unix_shell = 0;
+        vms_posix_exit = 1;
     }
 #endif
 
@@ -13638,8 +13634,10 @@ static int set_features
     s = decc$feature_get_index("DECC$FILENAME_UNIX_REPORT");
     if (s >= 0) {
        decc_filename_unix_report = decc$feature_get_value(s, 1);
-       if (decc_filename_unix_report > 0)
+       if (decc_filename_unix_report > 0) {
            decc_filename_unix_report = 1;
+           vms_posix_exit = 1;
+       }
        else
            decc_filename_unix_report = 0;
     }
@@ -13767,6 +13765,17 @@ static int set_features
 
 #endif
 
+    /* USE POSIX/DCL Exit codes - Recommended, but needs to default to  */
+    /* for strict backward compatibilty */
+    status = sys_trnlnm
+       ("PERL_VMS_POSIX_EXIT", val_str, sizeof(val_str));
+    if ($VMS_STATUS_SUCCESS(status)) {
+       if ((val_str[0] == 'E') || (val_str[0] == '1') || (val_str[0] == 'T'))
+        vms_posix_exit = 1;
+       else
+        vms_posix_exit = 0;
+    }
+
 
     /* CRTL can be initialized past this point, but not before. */
 /*    DECC$CRTL_INIT(); */