From 0475b7a649209487269e35cbe49662a33524e6ae Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Thu, 14 Sep 2023 08:09:14 +0100 Subject: 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. --- include/mingw.h | 2 ++ loginutils/suw32.c | 2 ++ miscutils/drop.c | 2 +- shell/ash.c | 15 ++------------- win32/process.c | 37 +++++++++++++++++++++++++++++++++++-- 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); BOOL WINAPI kill_child_ctrl_handler(DWORD dwCtrlType); int kill_signal_by_handle(HANDLE process, int sig); int FAST_FUNC is_valid_signal(int number); +int exit_code_to_wait_status(DWORD win_exit_code); +int exit_code_to_posix(DWORD win_exit_code); #define find_mount_point(n, s) find_mount_point(n) 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) WaitForSingleObject(info.hProcess, INFINITE); if (!GetExitCodeProcess(info.hProcess, &r)) r = 1; + else + r = exit_code_to_posix(r); CloseHandle(info.hProcess); return r; } 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) SetConsoleCtrlHandler(kill_child_ctrl_handler, TRUE); WaitForSingleObject(pi.hProcess, INFINITE); if (GetExitCodeProcess(pi.hProcess, &code)) { - return (int)code; + return exit_code_to_posix(code); } } } 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) HANDLE *proclist; pid_t pid = -1; DWORD win_status, idx; - int i, sig; + int i; for (jb = curjob; jb; jb = jb->prev_job) { if (jb->state != JOBDONE) @@ -4992,18 +4992,7 @@ waitpid_child(int *status, int wait_flags) wait_flags&WNOHANG ? 1 : INFINITE); if (idx < pid_nr) { GetExitCodeProcess(proclist[idx], &win_status); - if (win_status == 0xc0000005) - win_status = SIGSEGV << 24; - else if (win_status == 0xc000013a) - win_status = SIGINT << 24; - - // When a process is terminated as if by a signal the exit - // code is zero apart from the signal in its topmost byte. - sig = win_status >> 24; - if (sig != 0 && win_status == sig << 24 && is_valid_signal(sig)) - *status = sig; - else - *status = (int)win_status << 8; + *status = exit_code_to_wait_status(win_status); pid = pidlist[idx]; } 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) } #endif CloseHandle(proc); - *status = code << 8; + *status = exit_code_to_wait_status(code); return pid; } } @@ -407,7 +407,7 @@ static NORETURN void wait_for_child(HANDLE child) SetConsoleCtrlHandler(kill_child_ctrl_handler, TRUE); WaitForSingleObject(child, INFINITE); GetExitCodeProcess(child, &code); - exit((int)code); + exit(exit_code_to_posix(code)); } int @@ -807,6 +807,39 @@ int FAST_FUNC is_valid_signal(int number) return isalpha(*get_signame(number)); } +int exit_code_to_wait_status(DWORD exit_code) +{ + int sig, status; + + if (exit_code == 0xc0000005) + return SIGSEGV; + else if (exit_code == 0xc000013a) + return SIGINT; + + // When a process is terminated as if by a signal the Windows + // exit code is zero apart from the signal in its topmost byte. + // This is a busybox-w32 convention. + sig = exit_code >> 24; + if (sig != 0 && exit_code == sig << 24 && is_valid_signal(sig)) + return sig; + + // Use least significant byte as exit code, but not if it's zero + // and the Windows exit code as a whole is non-zero. + status = exit_code & 0xff; + if (exit_code != 0 && status == 0) + status = 255; + return status << 8; +} + +int exit_code_to_posix(DWORD exit_code) +{ + int status = exit_code_to_wait_status(exit_code); + + if (WIFSIGNALED(status)) + return 128 + WTERMSIG(status); + return WEXITSTATUS(status); +} + int kill(pid_t pid, int sig) { 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) intptr_t proc; HANDLE h; DWORD ret = 0; - int sig; if (cmd == NULL) return 1; @@ -19,9 +18,5 @@ int mingw_system(const char *cmd) GetExitCodeProcess(h, &ret); CloseHandle(h); - // Was process terminated as if by a signal? - sig = ret >> 24; - if (sig != 0 && ret == sig << 24 && is_valid_signal(sig)) - return sig; - return ret << 8; + return exit_code_to_wait_status(ret); } -- cgit v1.2.3-55-g6feb