On an interactive ksh(1) session, to help me identify whether a command
has failed and what was its exit code, I trap the ERR special signal to
print the exit code of a command that returns nonzero.
trap 'printf "EXIT: %s\n" "$?"' ERR
Here is how a terminal session looks like after running the above
command. As you can see, if a command fails, its exit code is printed
right after it exits. If a command succeeds, the "EXIT ..." string is
not printed.
> false
EXIT: 1
> true
> cat nonexistentfile.txt
cat: nonexistentfile.txt: No such file or directory
EXIT: 1
> cat /dev/null
>
However, OpenBSD ksh(1) behaves a little different from ksh93 and bash
when the command terminates from a signal (such as when typing CTRL+C
while the command is running): Rather than the trap handler be run
right after the command is terminated from a signal, it is run only
after the next non-builtin command terminates normally.
For example, here is a terminal session in bash(1) (the behavior is the
same on ksh93(1)). I run the previous trap command and then run cat(1)
without any arguments and immediately type ^C (CTRL+C) to send SIGINT to
cat. The shell prints "EXIT ..." right after the cat(1) is terminated
and before the next prompt.
> echo $0
bash
> cat
^C
EXIT: 130
>
Now, trying that on OpenBSD ksh(1), the "EXIT: ..." string is not
printed right after the command terminates from the signal. It is
printed, however, after the next non-builtin command successfully
terminates. In this example, I'm running ls(1) after terminating cat(1)
with ^C; note that the "EXIT ..." string, which was supposed to be
printed after cat(1) terminates, is only printed after ls(1) terminates.
> echo $0
ksh
> cat
^C
> ls
Documents/
Downloads/
[...]
EXIT: 0
>
(The output of ls(1) is longer, I ran it on my $HOME, but I am
suppressing the output here with a "[...]".) Note that ls(1)
terminated successfully (the "$?" on the trapped command expands
to "0").