+ if ($^O eq 'MSWin32') {
+ #
+ # On Windows, the return value of system is the lower 8
+ # bits of the exit status of the process, shifted left
+ # 8 bits.
+ #
+ # If the process crashed, rather than exiting, the
+ # exit status will be one of the EXCEPTION_ values
+ # listed in the documentation for the GetExceptionCode()
+ # macro.
+ #
+ # Those are defined as STATUS_ values, which should have
+ # 0xC in the topmost 4 bits (being fatal error
+ # statuses); some of them have a value that fits in
+ # the lower 8 bits. We could, I guess, assume that
+ # any value that 1) isn't returned by tcpdump and 2)
+ # corresponds to the lower 8 bits of a STATUS_ value
+ # used as an EXCEPTION_ value indicates that tcpdump
+ # exited with that exception.
+ #
+ # However, as we're running tcpdump with system, which
+ # runs the command through cmd.exe, and as cmd.exe
+ # doesn't map the command's exit code to its own exit
+ # code in any straightforward manner, we can't get
+ # that information in any case, so there's no point
+ # in trying to interpret it in that fashion.
+ #
+ $status = $r >> 8;
+ } else {
+ #
+ # On UN*Xes, the return status is a POSIX as filled in
+ # by wait() or waitpid().
+ #
+ # POSIX offers some calls for analyzing it, such as
+ # WIFSIGNALED() to test whether it indicates that the
+ # process was terminated by a signal, WTERMSIG() to
+ # get the signal number from it, WIFEXITED() to test
+ # whether it indicates that the process exited normally,
+ # and WEXITSTATUS() to get the exit status from it.
+ #
+ # POSIX doesn't standardize core dumps, so the POSIX
+ # calls can't test whether a core dump occurred.
+ # However, all the UN*Xes we are likely to encounter
+ # follow Research UNIX in this regard, with the exit
+ # status containing either 0 or a signal number in
+ # the lower 7 bits, with 0 meaning "exited rather
+ # than being terminated by a signal", the "core dumped"
+ # flag in the 0x80 bit, and, if the signal number is
+ # 0, the exit status in the next 8 bits up.
+ #
+ # This should be cleaned up to use the POSIX calls
+ # from the Perl library - and to define an additional
+ # WCOREDUMP() call to test the "core dumped" bit and
+ # use that.
+ #
+ # But note also that, as we're running tcpdump with
+ # system, which runs the command through a shell, if
+ # tcpdump crashes, we'll only know that if the shell
+ # maps the signal indication and uses that as its
+ # exit status.
+ #
+ # The good news is that the Bourne shell, and compatible
+ # shells, have traditionally done that. If the process
+ # for which the shell reports the exit status terminates
+ # with a signal, it adds 128 to the signal number and
+ # returns that as its exit status. (This is why the
+ # "this is now working right" behavior described in a
+ # comment below is occurring.)
+ #
+ # As tcpdump itself never returns with an exit status
+ # >= 128, we can try checking for an exit status with
+ # the 0x80 bit set and, if we have one, get the signal
+ # number from the lower 7 bits of the exit status. We
+ # can't get the "core dumped" indication from the
+ # shell's exit status; all we can do is check whether
+ # there's a core file.
+ #
+ if( $r & 128 ) {
+ $coredump = $r & 127;
+ }
+ if( WIFEXITED($r)) {
+ $status = WEXITSTATUS($r);
+ }
+ }
+
+ if($coredump || $status) {
+ printf OUTPUT "EXIT CODE %08x: dump:%d code: %d\n", $r, $coredump, $status;
+ } else {
+ printf OUTPUT "EXIT CODE %08x\n", $r;
+ }
+ $r = 0;