Perl script behavior while exiting with 256 - perl

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).

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).

What is the command and syntax for breaking/stopping a program in QBASIC?

I am currently writing a QBASIC program that runs an indefinite loop (while loop). However, if a certain condition is met, I want to exit the program. What command do I use, and also what is the syntax.
Thanks
ENDexits program, and clears all variables, which frees up memory.
STOPexits program, but retains the value of all variables, which makes it possible (in certain versions of QB) to continue execution at another point, by choosing Set next statement from the Debugmenu, and then Startfrom the Runmenu. END has the same effect as STOP + choosing Restart from the Runmenu once the program has terminated.
If you have a loop, and want to exit the program from inside it, you may use either
DO
IF condition THEN EXIT DO
LOOP
END
or
DO
IF condition THEN END
LOOP
You're looking for the END or SYSTEM statement. For example:
PRINT "Hello World!"
END
PRINT "This won't be printed."
If you're using regular old QBASIC/QuickBASIC, then you can ignore all of the QB64 details on the linked pages and just use either SYSTEM or END. Both will do the same thing for the most part.1
If you're using FreeBASIC, it's recommended to use END instead of SYSTEM since some things won't get cleaned up properly when you use SYSTEM. See SYSTEM for more information pertaining to FreeBASIC if that's what you're using.
1 The END statement when running the program using QB.EXE /RUN PROGRAM.BAS will print "Press any key to continue" before exiting to the QB/QBASIC environment. The SYSTEM statement when run the same way will simply return you to the DOS shell without any need for a key press. Also, typing SYSTEM in the "Immediate Window" of the QB/QBASIC environment will exit the environment and return to the DOS shell. Otherwise the two statements behave exactly the same in QB/QBASIC, whether for standalone (compiled) programs or .BAS modules.
You can keep any condition according to the need of your program. For eg:
CLS
LET a = 5
WHILE a > 0
PRINT a;
a = a - 1
WEND
END
Here, in the program while wends executes itself until a = 0. This will not run an infinite loop.
The answer is
exit();
to exit the program.

valgrind returns the c-program return value

I'm running valgrind in a script to find memory issues only by the return value of valgrind (I don't want to print anything to the screen).
Using this line:
valgrind --tool=memcheck --leak-check=full --error-exitcode=3 {c program} < {input file} > /dev/null 2> {errors redirection file}
The return value ($?) that I get is the return value of the c-program and not the one of valgrind.
How can I do it right?
Thanks :)
Documentation on the valgrind site says:
"--error-exitcode= [default: 0]
Specifies an alternative exit code to return if Valgrind reported any errors in the run. When set to the default value (zero), the return value from Valgrind will always be the return value of the process being simulated. When set to a nonzero value, that value is returned instead, if Valgrind detects any errors. This is useful for using Valgrind as part of an automated test suite, since it makes it easy to detect test cases for which Valgrind has reported errors, just by inspecting return codes."
The implication is that if valgrind doesn't detect errors, it will still return the value of the process being simulated. Therefore, you should pick some value to use that the C program doesn't ever return when using this option.
http://valgrind.org/docs/manual/manual-core.html

Program exited with error code 04

I'm trying to run a program with perl to print "A" 512 times through gdb. It returned with code 04. I started slowly going down to 511 then 510 and so on. But it still returned with code 04. Is this how it's supposed to be? If not, what am I doing wrong? Thanks for your answers.
Code:
#include <stdio.h>
int main(int argc, char * argv[])
{
char buf[256];
if(argc == 1)
{
printf("Usage: %s input\n", argv[0]);
exit(0);
}
strcpy(buf,argv[1]);
printf("%s", buf);
}
And I'm running from gdb:
run perl -e 'print "A" x 512'
There's no reason to involve either perl or gdb for this.
As of the 1989/1990 C standard, reaching the } at the end of main returns an undefined status to the environment. (The actual status of 4 in your case is probably the value returned by printf, which is the number of characters it printed. The way you invoked the program, argv[0] points to the string "perl", which is 4 characters long. But you absolutely should not count on that behavior.)
The 1999 standard introduced a new rule (inspired by C++): reaching the end of main does the equivalent of return 0;. But gcc by default uses the C90 standard plus GNU extensions (equivalent to -std=gnu90).
Add a return 0; to the end of your main function and/or compile your C program with an option that specifies a later standard, such as -std=c99 (or -std=gnu99 if you want to use GNU-specific extensions).
Finally, it looks like you were trying to print 512 'A' characters, but you were invoking your program with the arguments:
perl -e 'print "A" x 512'
That's three arguments, and your program ignores all but the first, the 4-character string "perl". The remaining arguments were meant to be passed to the Perl interpreter, but you didn't invoke the Perl interpreter.
One correct way to do this would be:
./foo $(perl -e 'print "A" x 512')
where foo is the name of your program. But that would cause undefined behavior (possibly a program crash, or it might appear to "work" if you're unlucky), because you copy the string pointed to by argv[1] into an array of only 256 characters. For this simple program, that's easily avoided by not copying the string.
And your program's output doesn't end with a newline, which can cause problems. On a UNIX-like system, the program's output will likely be printed on the same line as your next shell prompt -- or the output might not be visible at all.
To see the program's exit status, type:
echo $?
(This assumes you're using bash or a similar shell.)

backticks do not return any value in perl

I wrote a perl script in Cygwin environment. Inside, I use backticks to execute another program, and returned value is assigned to a variable. It worked fine before I upgraded some packages in cygwin two weeks ago. Now the backticks do not return any value. Any thoughts?
Try checking the value of $?. It contains the return code of the last external command executed, but it's overloaded to contain extra information, such as the signal that killed the command and whether there was a core dump, etc.
The actual return code can be obtained through
my $return_code = $? >> 8;
If it's zero, the command executed successfully, if not, that's the error status the commadn exited with (what int main() returns with in C, for example).