diff options
author | Ron Yorston <rmy@pobox.com> | 2023-09-14 08:09:14 +0100 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2023-09-14 08:09:14 +0100 |
commit | 0475b7a649209487269e35cbe49662a33524e6ae (patch) | |
tree | 531237e1d8716e7c94fdcd0b2966e2e0cbfc0255 | |
parent | e3d50157ce21f990c33afdcf8dba8080308ce0f0 (diff) | |
download | busybox-w32-0475b7a649209487269e35cbe49662a33524e6ae.tar.gz busybox-w32-0475b7a649209487269e35cbe49662a33524e6ae.tar.bz2 busybox-w32-0475b7a649209487269e35cbe49662a33524e6ae.zip |
win32: convert exit codes
Add two utility functions to convert Windows process exit codes.
- exit_code_to_wait_status() converts to a POSIX wait status.
This is used in ash and the implementations of system(3) and
mingw_wait3().
- exit_code_to_posix() converts to a POSIX exit code. (Not that
POSIX has much to say about them.)
As a result it's possible for more applets to report when child
processes are killed as if by a signal. 'time', 'drop' and 'su -W',
for example.
Adds 64-80 bytes.
-rw-r--r-- | include/mingw.h | 2 | ||||
-rw-r--r-- | loginutils/suw32.c | 2 | ||||
-rw-r--r-- | miscutils/drop.c | 2 | ||||
-rw-r--r-- | shell/ash.c | 15 | ||||
-rw-r--r-- | win32/process.c | 37 | ||||
-rw-r--r-- | win32/system.c | 7 |
6 files changed, 43 insertions, 22 deletions
diff --git a/include/mingw.h b/include/mingw.h index 1dcc84bde..6ed9bed4a 100644 --- a/include/mingw.h +++ b/include/mingw.h | |||
@@ -562,6 +562,8 @@ int mingw_execve(const char *cmd, char *const *argv, char *const *envp); | |||
562 | BOOL WINAPI kill_child_ctrl_handler(DWORD dwCtrlType); | 562 | BOOL WINAPI kill_child_ctrl_handler(DWORD dwCtrlType); |
563 | int kill_signal_by_handle(HANDLE process, int sig); | 563 | int kill_signal_by_handle(HANDLE process, int sig); |
564 | int FAST_FUNC is_valid_signal(int number); | 564 | int FAST_FUNC is_valid_signal(int number); |
565 | int exit_code_to_wait_status(DWORD win_exit_code); | ||
566 | int exit_code_to_posix(DWORD win_exit_code); | ||
565 | 567 | ||
566 | #define find_mount_point(n, s) find_mount_point(n) | 568 | #define find_mount_point(n, s) find_mount_point(n) |
567 | 569 | ||
diff --git a/loginutils/suw32.c b/loginutils/suw32.c index 79e8415a8..240a692bc 100644 --- a/loginutils/suw32.c +++ b/loginutils/suw32.c | |||
@@ -112,6 +112,8 @@ int suw32_main(int argc UNUSED_PARAM, char **argv) | |||
112 | WaitForSingleObject(info.hProcess, INFINITE); | 112 | WaitForSingleObject(info.hProcess, INFINITE); |
113 | if (!GetExitCodeProcess(info.hProcess, &r)) | 113 | if (!GetExitCodeProcess(info.hProcess, &r)) |
114 | r = 1; | 114 | r = 1; |
115 | else | ||
116 | r = exit_code_to_posix(r); | ||
115 | CloseHandle(info.hProcess); | 117 | CloseHandle(info.hProcess); |
116 | return r; | 118 | return r; |
117 | } | 119 | } |
diff --git a/miscutils/drop.c b/miscutils/drop.c index 6903254c3..629460564 100644 --- a/miscutils/drop.c +++ b/miscutils/drop.c | |||
@@ -200,7 +200,7 @@ int drop_main(int argc, char **argv) | |||
200 | SetConsoleCtrlHandler(kill_child_ctrl_handler, TRUE); | 200 | SetConsoleCtrlHandler(kill_child_ctrl_handler, TRUE); |
201 | WaitForSingleObject(pi.hProcess, INFINITE); | 201 | WaitForSingleObject(pi.hProcess, INFINITE); |
202 | if (GetExitCodeProcess(pi.hProcess, &code)) { | 202 | if (GetExitCodeProcess(pi.hProcess, &code)) { |
203 | return (int)code; | 203 | return exit_code_to_posix(code); |
204 | } | 204 | } |
205 | } | 205 | } |
206 | } | 206 | } |
diff --git a/shell/ash.c b/shell/ash.c index dcc73031f..f0480f723 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
@@ -4960,7 +4960,7 @@ waitpid_child(int *status, int wait_flags) | |||
4960 | HANDLE *proclist; | 4960 | HANDLE *proclist; |
4961 | pid_t pid = -1; | 4961 | pid_t pid = -1; |
4962 | DWORD win_status, idx; | 4962 | DWORD win_status, idx; |
4963 | int i, sig; | 4963 | int i; |
4964 | 4964 | ||
4965 | for (jb = curjob; jb; jb = jb->prev_job) { | 4965 | for (jb = curjob; jb; jb = jb->prev_job) { |
4966 | if (jb->state != JOBDONE) | 4966 | if (jb->state != JOBDONE) |
@@ -4992,18 +4992,7 @@ waitpid_child(int *status, int wait_flags) | |||
4992 | wait_flags&WNOHANG ? 1 : INFINITE); | 4992 | wait_flags&WNOHANG ? 1 : INFINITE); |
4993 | if (idx < pid_nr) { | 4993 | if (idx < pid_nr) { |
4994 | GetExitCodeProcess(proclist[idx], &win_status); | 4994 | GetExitCodeProcess(proclist[idx], &win_status); |
4995 | if (win_status == 0xc0000005) | 4995 | *status = exit_code_to_wait_status(win_status); |
4996 | win_status = SIGSEGV << 24; | ||
4997 | else if (win_status == 0xc000013a) | ||
4998 | win_status = SIGINT << 24; | ||
4999 | |||
5000 | // When a process is terminated as if by a signal the exit | ||
5001 | // code is zero apart from the signal in its topmost byte. | ||
5002 | sig = win_status >> 24; | ||
5003 | if (sig != 0 && win_status == sig << 24 && is_valid_signal(sig)) | ||
5004 | *status = sig; | ||
5005 | else | ||
5006 | *status = (int)win_status << 8; | ||
5007 | pid = pidlist[idx]; | 4996 | pid = pidlist[idx]; |
5008 | } | 4997 | } |
5009 | done: | 4998 | done: |
diff --git a/win32/process.c b/win32/process.c index 2f8b6ce31..54d98e1d9 100644 --- a/win32/process.c +++ b/win32/process.c | |||
@@ -45,7 +45,7 @@ pid_t mingw_wait3(pid_t pid, int *status, int options, struct rusage *rusage) | |||
45 | } | 45 | } |
46 | #endif | 46 | #endif |
47 | CloseHandle(proc); | 47 | CloseHandle(proc); |
48 | *status = code << 8; | 48 | *status = exit_code_to_wait_status(code); |
49 | return pid; | 49 | return pid; |
50 | } | 50 | } |
51 | } | 51 | } |
@@ -407,7 +407,7 @@ static NORETURN void wait_for_child(HANDLE child) | |||
407 | SetConsoleCtrlHandler(kill_child_ctrl_handler, TRUE); | 407 | SetConsoleCtrlHandler(kill_child_ctrl_handler, TRUE); |
408 | WaitForSingleObject(child, INFINITE); | 408 | WaitForSingleObject(child, INFINITE); |
409 | GetExitCodeProcess(child, &code); | 409 | GetExitCodeProcess(child, &code); |
410 | exit((int)code); | 410 | exit(exit_code_to_posix(code)); |
411 | } | 411 | } |
412 | 412 | ||
413 | int | 413 | int |
@@ -807,6 +807,39 @@ int FAST_FUNC is_valid_signal(int number) | |||
807 | return isalpha(*get_signame(number)); | 807 | return isalpha(*get_signame(number)); |
808 | } | 808 | } |
809 | 809 | ||
810 | int exit_code_to_wait_status(DWORD exit_code) | ||
811 | { | ||
812 | int sig, status; | ||
813 | |||
814 | if (exit_code == 0xc0000005) | ||
815 | return SIGSEGV; | ||
816 | else if (exit_code == 0xc000013a) | ||
817 | return SIGINT; | ||
818 | |||
819 | // When a process is terminated as if by a signal the Windows | ||
820 | // exit code is zero apart from the signal in its topmost byte. | ||
821 | // This is a busybox-w32 convention. | ||
822 | sig = exit_code >> 24; | ||
823 | if (sig != 0 && exit_code == sig << 24 && is_valid_signal(sig)) | ||
824 | return sig; | ||
825 | |||
826 | // Use least significant byte as exit code, but not if it's zero | ||
827 | // and the Windows exit code as a whole is non-zero. | ||
828 | status = exit_code & 0xff; | ||
829 | if (exit_code != 0 && status == 0) | ||
830 | status = 255; | ||
831 | return status << 8; | ||
832 | } | ||
833 | |||
834 | int exit_code_to_posix(DWORD exit_code) | ||
835 | { | ||
836 | int status = exit_code_to_wait_status(exit_code); | ||
837 | |||
838 | if (WIFSIGNALED(status)) | ||
839 | return 128 + WTERMSIG(status); | ||
840 | return WEXITSTATUS(status); | ||
841 | } | ||
842 | |||
810 | int kill(pid_t pid, int sig) | 843 | int kill(pid_t pid, int sig) |
811 | { | 844 | { |
812 | if (sig == SIGKILL || sig == 0) | 845 | if (sig == SIGKILL || sig == 0) |
diff --git a/win32/system.c b/win32/system.c index 00b594242..c718d9948 100644 --- a/win32/system.c +++ b/win32/system.c | |||
@@ -6,7 +6,6 @@ int mingw_system(const char *cmd) | |||
6 | intptr_t proc; | 6 | intptr_t proc; |
7 | HANDLE h; | 7 | HANDLE h; |
8 | DWORD ret = 0; | 8 | DWORD ret = 0; |
9 | int sig; | ||
10 | 9 | ||
11 | if (cmd == NULL) | 10 | if (cmd == NULL) |
12 | return 1; | 11 | return 1; |
@@ -19,9 +18,5 @@ int mingw_system(const char *cmd) | |||
19 | GetExitCodeProcess(h, &ret); | 18 | GetExitCodeProcess(h, &ret); |
20 | CloseHandle(h); | 19 | CloseHandle(h); |
21 | 20 | ||
22 | // Was process terminated as if by a signal? | 21 | return exit_code_to_wait_status(ret); |
23 | sig = ret >> 24; | ||
24 | if (sig != 0 && ret == sig << 24 && is_valid_signal(sig)) | ||
25 | return sig; | ||
26 | return ret << 8; | ||
27 | } | 22 | } |