(EDIT, stolen from the answer, referred to by the question comment, which ultimately pointed here).
In shell scripting, fake exit statuses over 128 are provided for certain conditions, so it's probably best to avoid these. (ssh uses 255 though, which is not used this way).
The two exit statuses below 128 are also used to represent certain shell errors, so you generally don't want to use those codes either.
BSD went on to try and standardize some exit codes, starting at 64. I don't see any problem using these if you fell in love with them (search sysexit.h, it's not a formal standard so you'll have to copy it). And if you're not using this, then "less than 64" is a nicer round number than 126 :-P. That said, neither the shell nor the kernel will care about these at all. They're used between co-operating programs - specifically this was intended for mailer components. If you want more than 63 "error" statuses, I wouldn't worry about these ones being "reserved" in Unix.
The system call interface itself aka kernel, doesn't really care. In the system calls, special exit statuses are encoded out of band of the 0-255 range. This is how the shell detects and prints the status "Killed", for a command terminated by SIGKILL. This out-of-band information cannot be faked by any simple
If status is not NULL, wait() and waitpid()
store status information in the int to which it points. This
integer can be inspected with the following macros (which take the
integer itself as an argument, not a pointer to it, as is done in
wait() and waitpid()!):
WIFEXITED(status) returns true if the
child terminated normally, that is, by calling exit(3) or _exit(2), or by returning from main().
WEXITSTATUS(status) returns the exit
status of the child. This consists of the least significant 8 bits of
the status argument that the child specified in a call to exit(3) or _exit(2) or as the argument for a
return statement in main(). This macro should only be employed if
WIFEXITED returned true.
WIFSIGNALED(status) returns true if the
child process was terminated by a signal.
WTERMSIG(status) returns the number of
the signal that caused the child process to terminate. This macro
should only be employed if WIFSIGNALED returned true.
WCOREDUMP(status) returns true if the
child produced a core dump. This macro should only be employed if
WIFSIGNALED returned true. This macro is not specified in
POSIX.1-2001 and is not available on some UNIX implementations (e.g.,
AIX, SunOS). Only use this enclosed in #ifdef WCOREDUMP ... #endif.
WIFSTOPPED(status) returns true if the
child process was stopped by delivery of a signal; this is only
possible if the call was done using WUNTRACED or when the child
is being traced (see ptrace(2)).
WSTOPSIG(status) returns the number of
the signal which caused the child to stop. This macro should only be
employed if WIFSTOPPED returned true.
WIFCONTINUED(status) (since Linux 2.6.10)
returns true if the child process was resumed by delivery of
ssh exits with the exit status of the remote command or with 255 if an error occurred.
bash: a: command not found...
$ echo $?
bash: /dev/null: Permission denied
$ echo $?