#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 '!':
{
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)
#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
(((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) { \
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
/* 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)
'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", $!, $!;
}
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,
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
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
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
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
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 $!
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
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
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: