Path: utzoo!mnetor!uunet!seismo!sundc!pitstop!sun!quintus!ok From: ok@quintus.UUCP (Richard A. O'Keefe) Newsgroups: comp.unix.wizards Subject: Re: Confusing documentation about system(3) in 4.3BSD? Message-ID: <696@cresswell.quintus.UUCP> Date: 26 Feb 88 06:06:49 GMT References: <3161@phri.UUCP> Organization: Quintus Computer Systems, Mountain View, CA Lines: 66 Keywords: exit status In article <3161@phri.UUCP>, roy@phri.UUCP (Roy Smith) writes: > > I was recently surprised to discover that if you run the following > program fragment: > printf("%d\n", system("exit 0")); ... > printf("%d\n", system("exit 3")); > you get: > 0 ... > 768 > > Clearly what is going on is that system() is returning the exit > status as described in wait(2), i.e. with the argument to exit() shifted up > one byte, and the low byte containing the termination status. But, as I > read the man pages, the above fragment should have printed 0, 1, 2, and 3. The documentation has always been confusing. It's not just 4.3BSD. However, don't BSD systems come with a /usr/include/sys/wait.h which makes it rather clearer? The picture is (on a 32-bit machine) +----------------+--------+-+-------+ |xxxxxxxxxxxxxxxx|exit-val|c|termval| +----------------+--------+-+-------+ 31 (MSB) 15 8 7 6 0 (LSB) exit-val is the least significant byte of the value passed to exit(). For a stopped process, it is the number of the signal which caused the child to stop. c is 1 if the child dumped core. termval is the "termination status" of the child. It is 0 for successful exit, 0177 for a stopped process, otherwise the number of the signal which killed the child. You aren't told about stopped processes unless you ask or they are being traced; wait(2) is supposed to treat them as if they were still running. system(3) adds its own complication: the *exit status* (NOT return value!) 127 means "couldn't execute the shell". That is, if it couldn't fork a shell, you get ((system(...) >> 8) & 255) == 127. Note that this is ambiguous! Consider system("exit 127"), for example. Summary: x = system(command_string); #ifdef BSD if ((x & 0xFF) == 0x7F) { cause_of_death = NOT_DEAD_BUT_SLEEPING; childs_death_signal = (x >> 8) & 0xFF; } else #endif if ((x & 0xFF) != 0) { cause_of_death = KILLED_BY_SIGNAL; childs_death_signal = x & 0x7F; child_dumped_core = (x >> 7) & 1; } else if ((x & 0xFFFF) == 0x7F00) { cause_of_death = COULD_NOT_EXECUTE_SHELL; } else { cause_of_death = NATURAL_CAUSES; childs_exit_status = (x >> 8) & 0xFF; } This is what I have culled from manuals, and seems to be right. Let's have it from someone who *knows*.