IBM Z/os Rexx script returns 255 exit code - zos

I have simple Rexx script hello_world.rexx:
/* rexx */
SAY 'Hello World'
EXIT
Then I run it:
>./hello_world.rexx
Hello World
It executes well, but somehow I always get 255 exit code.
>echo $?
255
Does somebody know how to fix script to get 0 as exit code?

I assume you are running the REXX code from USS.
See here => https://www.ibm.com/support/knowledgecenter/en/SSLTBW_2.1.0/com.ibm.zos.v2r1.bpxb600/bpx1rx32.htm
You can explicitly set return code 0 by using EXIT 0, for example:
/* rexx */
SAY 'Hello World'
EXIT 0

According to the documentation an return code of 255 indicates that the program was terminated. Use exit 0 if you want a zero returned.

Or you can use the RETURN keyword with a code:
RETURN 0

Related

No-op shell command that preserves $?

Using only the features of the POSIX shell, is there a "simple command" that does nothing and does not change the value of $? People usually describe : as a no-op command for shell, but this always sets $? to zero, so it's not what I want.
This is needed by a program that generates shell scripts. In several places it needs to emit an if-then-else block
if CONDITION
then
TRUE-COMMANDS
else
FALSE-COMMANDS
fi
but, because of further complications that I'd rather not try to explain right now, it cannot reliably tell whether TRUE-COMMANDS and FALSE-COMMANDS are empty. An empty then- or else-clause will be a shell syntax error.
: can be put at the beginning of the then-clause to take care of TRUE-COMMANDS being empty, but that won't work for FALSE-COMMANDS because it clobbers $? and the FALSE-COMMANDS might want to look at the value $? was set to by the condition. For the same reason, : can't be put after FALSE-COMMANDS—the code after the if-then-else might want to see $? from the last operation within the if-then-else.
Bonus points if you can avoid:
Forking: (exit $?) does the job, but there are so many of these conditional blocks in a generated script that it produces a measurable slowdown.
Functions: given nop () { return $? } then nop does the job, but due to more complications that I'd rather not get into, it's not practical to have nop defined sufficiently early for all of the places that would need it.
The easiest would be to make use of a simple assignment. Instead of using :, do _rc=$?.
if condition; then
[ list-true ] # optional
_rc=$?
else
[ list-false ] # optional
_rc=$?
fi
( exit $_rc ) # optional
list-post-if
Using this variable _rc, you have stored the exit status of the last executed command, whether this is condition or the last command in list-true or list-false.
The arguments in favour of this method is the low overhead of an assignment.
The argument against is the need to at least rewrite list-post-if to make use of _rc instead of $?.
If the latter is not possible, or too tedious, you might concider to add a (exit $_rc) just after the conditional statement. This, however, requires a sub-shell, but it is only one.
Don't let anyone tell you there are only functions and sub-shells.
Can you create or distribute another tiny file? If so, you can create a file with just
return $?
and then source it as an "empty" command keeping the exit status:
$ echo 'return $?' > keepstatus
$ ls foobar
ls: fooobar: No such file or directory
$ . ./keepstatus
$ echo $?
2
$ sleep 100
^C
$ . ./keepstatus
$ echo $?
130
Doesn't fork, doesn't use functions, no extra variable, keeps the status and is as POSIXly as they come.
There's even a fourth way I can see, when I sacrifice the bonus points for forking and assuming, since you are in autoconf m4 territory, that finding and using a host compiler is a breeze.
cat > keepstatus.c <<EOF
#include <stdlib.h>
int main(int argc, char **argv) {
return argv[1] ? atoi(argv[1]) : 0;
}
EOF
$CC -o keepstatus keepstatus.c
Then use /path/to/keepstatus $?.
It’s certainly not possible in a POSIX-compliant shell to write a command that does not touch $?. By reading through IEEE Std 1003.1-2017 vol. 3 chapter 2 ‘Shell Command Language’, we learn that:
§2.8.2 says that ‘[e]ach command has an exit status’ (so no command has no exit status).
§2.5.2 ‘Special Parameters’ says that $? ‘[e]xpands to the decimal exit status of the most recent pipeline (see Section 2.9.2)’.
§2.9.2 ‘Pipelines’ says that a pipeline is a sequence of one or more commands, optionally preceded (as a whole) by !, with commands joined by |. About exit status, it says
If the pipeline does not begin with the ! reserved word, the exit status shall be the exit status of the last command specified in the pipeline. Otherwise, the exit status shall be the logical NOT of the exit status of the last command.
§2.9 ‘Shell Commands’ defines a ‘command’ and says that ‘[u]nless otherwise stated, the exit status of a command shall be that of the last simple command executed by the command’. A ‘command’ may be any of the following:
A simple command (§2.9.1), which is simply an external program, a shell built-in or a variable assignment (without a command name). The former will of course return the exit status of the command executed. About the latter, the specification says:
If there is no command name, but the command contained a command substitution, the command shall complete with the exit status of the last command substitution performed. Otherwise, the command shall complete with a zero exit status.
A pipeline, described by §2.9.2 mentioned above.
A compound-list (§2.9.3), which is a sequence of one or more {sequences of one or more {sequences of one or more pipelines (see above), joined by && or ||}, each terminated by ; or & (with a final ; optional)}, joined by newline characters. A compound-list returns the exit status of the last pipeline executed synchronously; asynchronously-executed pipelines (those terminated by &) set exit status to zero. None of the sequences may be empty, which guarantees at least one pipeline will be executed.
A compound command (§2.9.4), which is either:
A subshell or a braced compound-list (§2.9.4.1), which returns the exit status of the underlying compound-list (see above).
A conditional construct (case, §2.9.4.3 or if, §2.9.4.4) or a loop (for, §2.9.4.2; while, §2.9.4.5; until, §2.9.4.6). If the body of this construct is not executed, it returns an exit status of zero.
A function definition (§2.9.5), which returns an exit status of zero if the definition is accepted, and a non-zero status otherwise.
And finally, §2.9.4.4 ‘The if Conditional Construct’ defines the condition and the body of the if construct to be a compound-list, described by §2.9.3 mentioned above. This means that the body of an if construct will always contain at least one command that will clobber $?. The specification does not even leave any wiggle room for ‘implementation-defined behaviour’.
All of the above means that the only way to write a no-op command that preserves $? is by reading out the value in $? and returning it back. There are three constructs in POSIX shell that are capable of this, two of which are already mentioned in the question body: an exit from a subshell or a function invocation.
The third is .: the shell sourcing statement mentioned in #Jens’ answer. By sourcing a script containing just a return "$?" command, the value of $? can be preserved. However, this requires you to arrange that a suitable script is found at some known location, which I assume to be just as inconvenient as ensuring that a no-op function has been defined early enough in the file (if not in fact more).
If you bend the strict POSIX requirement a little, even this can be overcome, though:
. /dev/stdin <<EOF
return "$?"
EOF
/dev/stdin is not a POSIX feature, but is widely available; it is explicitly listed in IEEE Std 1003.1-2017 vol. 1 §2.1.1 as an extension. The above snippet has been tested to work in bash 5.0.8, dash 0.5.11 and busybox sh 1.30.1 on Linux (with appropriately set-up /dev and so on).

Perl script behavior while exiting with 256

My perl script temp.pl looks like:
exit 256;
If i do following:
perl temp.pl
echo $?
Answer is 0.
If i change, perl script to
exit 255;
And do again then, answer is 255.
is there anything wrong ?
Yes, the exit return codes are limited to single byte - 0 to 255.
The full exit code consists of the exit code itself and flags which say how the program exited - whether regularly or because of some signal (being killed, interrupted, temporarily stopped etc.).
So the value to exit() function is always masked with 0xff in order to not conflict with signal delivery.
On Linux (and most unix systems), the status passed to exit is limited to 8 bits (0 to 255).
void exit(int status);
The exit() function causes normal process termination and the value of status & 0377 is returned to the parent (see wait(2)).
The reason it's limited to 8 bits is to support systems with 16-bit int. In an int, wait must convey the following information:
Whether the process existed normally (e.g. via exit).
If it exited normally,
The status passed to exit.
If it was terminated by a signal,
The number of the signal that killed the process.
Whether a core dump was produced.
On Windows, the status passed to exit is limited to 16-bits (0 to 65535).

perl program to handle return of batch file

i am trying to run a batch file from a perl script but i am not able to handle the return of a batch file. below is my code
perl script:
// call a batch file
my $output =system("D:\\WORKSPACE\\CC_Triggers\\batch_file.bat");
// based on output check the status of the batch file
if($output==0){
print "success in trigger**********";
}
else
{
print "FAilure**********";
}
batch file:
set "java_output="
setlocal enableDelayedExpansion
//this will call a java program and get return value.
for /f "delims=" %%J in ('java -cp "PMDfileRead.jar;jxl.jar" PMDfileRead') do (
set "java_output=!java_output! %%J"
)
endlocal & set java_output=%java_output%
// check the ouput of java and act accordingly
IF %java_output% == 1 (
echo failed
exit(1);
)else (
echo succeeded
)
basically i am trying to validate an xls file and return flag from java code which is being called by a batch file and from ther i need to return back to perl script which i am not able to get. in case of success and failure, i am getting as "0" as output due to which output is success.. request to please correct my code or suggest me the best way to handle this.
edit: Sorry i somehow read past the comment by mpapec stating the same thing.
The Perl part is fine. If you always get a 0, it has to be the batch script acting up. Or the Java.
If you want to inspect the return value in Perl for anything except whether it is zero or not, then you would have to shift it right 8 bits.
my $output = (system("D:\\WORKSPACE\\CC_Triggers\\batch_file.bat")) >> 8;
But as you only check for zero or not, that should not be an issue here.
edit:
When using Windows, it is important to never define an environment variable ERRORLEVEL as that will mix up with the actual exit codes returned by applications. This is explained in more detail here: How do I get the application exit code from a Windows command line?
Replace your system() call with backticks instead:
A system() wrapped call returns the exit status of the command, whereas using ``'s returns the actual STDOUT (i.e. your echo statements)
For more info:
What's the difference between Perl's backticks, system, and exec?
i.e.:
my $output = `D:\WORKSPACE\CC_Triggers\batch_file.bat`;

batch file call errorlevel twice

I am struggling at a batch file errorlevel return issue, and could not find the answer.
Could any one give me any hints?
I have an external binary file, external.exe which read the return code (0-success, other-fail) of a batch file to decide what to do.
Within the batch file, mybatch.cmd, I wanted to run a script (perl) and return the result to the batch file.
For example, mybatch.cmd:
#echo off
myperl.pl
exit %errorlevel%
While myperl.pl is:
#!perl.exe
exit 0;
So I wanted myperl.pl to return value 0 to the batch file, and then the batch file return 0 to the external.exe file.
But external.exe didn't work as expected.
1) If I run mybatch.cmd from CLI, and then "echo %errorlevel%" from CLI, I could see it is 0.
2) If I add a line to display the return code from myperl.pl, I could see the return code from myperl.pl is exactly 0.
For example:
#echo off
myperl.pl
echo %errorlevel%
REM exit %errorlevel%
It will display 0, so the perl script returns the value exactly.
3) If I add a line to manually set the return code to 0, the external.exe works fine.
#echo off
myperl.pl
result=0
exit %result%
That is really weird. Any ideas? I could not control the external.exe, so I could not do debug on it.
In this example, the %errorlevel% is called twice:
1) Return from myperl.pl to batch.
2) Return from mybatch.cmd to external.exe. Will that be an issue?
All you have said is right: myperl.pl return a certain errorlevel, the Batch file take it and then it returns the appropriate errorlevel value. The problem is this: the Batch file, to what process return its errorlevel?
This scheme always works as a parent-children relation: a parent process execute a children one and waits for it to terminate, then the parent may take the errorlevel value returned by the children. The way to solve your problem is if the external.exe program execute the Batch file (cmd.exe) as a children! However, if you "could not control the external.exe", then there is no way to solve your problem...
How do you know that the external.exe program "read the return code (0-success, other-fail) of a batch file to decide what to do"? I think you have a confusion at this point.
Found out the root cause finally.
myperl.pl should be with fullpath, otherwise the external.exe didn't know where the myperl.pl was.

In perl, what is the difference between $DB::single = 1 and 2?

What is the difference between putting $DB::single=1 and $DB::single=2 in your code? Both seem to have the identical effect of halting execution at the statement following the assignment when I do a 'c' on the perl debugger command line.
perldebug says that a value of 1 is equivalent to having just pressed 's' to get to the next statement, and 2 is the same as 'n', but what difference does it make how you got to the statement?
From perldebug:
If you set $DB::single to 2, it's equivalent to having just typed the n command (which executes over subroutine calls), whereas a value of 1 means the s command (which enters subroutine calls).
That much you know already.
From a user point of view, I'm pretty sure there is no difference. I base this on an examination of the actual DB.pm source code.
Let's follow this logically. You may want to refer to the source code. I've simplified some of the code to remove unnecessary detail but you should be able to get the idea from my descriptions.
When you are executing code in the debugger, there are (at least) two important variables, running and single. The combination of these is what decides whether code is run:
running single description
------- ------ -----------
0 ? not running
1 0 running flat-out
1 1 single stepping, execute into function
1 2 single stepping, execute over function
The DB() function is executed for every single line, and it contains the following snippet which will stop the running if single has been set (it always executes the current line regardless):
if ($DB::single) {
$DB::single = 0;
$running = 0;
}
That's why, if you set the variable in your Perl code, it will break (by break, I mean "stop running the code", not "damage somehow") the debugger at the next line.
When running is 0, the DB() function enters this little loop:
# Now sit in an event loop until something sets $running
do {
$c->idle; # call client event loop; must not block
} until $running;
In other words, it waits on a user command which sets running back to 1. This can be done by one of the following three functions:
sub next {
$DB::single = 2;
$running = 1;
}
sub step {
$DB::single = 1;
$running = 1;
}
sub cont {
$DB::single = 0;
$running = 1;
}
You can see that these three commands set up a different combination of single and running which will be used while executing the next Perl line (see the earlier table to see what these combinations mean).
The ability to use either 1 or 2 in your Perl code is a direct result of the fact that you're using a sneaky but clever trick to break execution from your Perl code itself, by setting a variable that would normally be set by a debugger command.
That's why it's not the value that matters so much as the fact you're forcing the debugger into a particular state.