aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2023-09-14 08:09:14 +0100
committerRon Yorston <rmy@pobox.com>2023-09-14 08:09:14 +0100
commit0475b7a649209487269e35cbe49662a33524e6ae (patch)
tree531237e1d8716e7c94fdcd0b2966e2e0cbfc0255
parente3d50157ce21f990c33afdcf8dba8080308ce0f0 (diff)
downloadbusybox-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.h2
-rw-r--r--loginutils/suw32.c2
-rw-r--r--miscutils/drop.c2
-rw-r--r--shell/ash.c15
-rw-r--r--win32/process.c37
-rw-r--r--win32/system.c7
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);
562BOOL WINAPI kill_child_ctrl_handler(DWORD dwCtrlType); 562BOOL WINAPI kill_child_ctrl_handler(DWORD dwCtrlType);
563int kill_signal_by_handle(HANDLE process, int sig); 563int kill_signal_by_handle(HANDLE process, int sig);
564int FAST_FUNC is_valid_signal(int number); 564int FAST_FUNC is_valid_signal(int number);
565int exit_code_to_wait_status(DWORD win_exit_code);
566int 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
413int 413int
@@ -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
810int 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
834int 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
810int kill(pid_t pid, int sig) 843int 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}