aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libbb/appletlib.c4
-rw-r--r--win32/process.c93
2 files changed, 68 insertions, 29 deletions
diff --git a/libbb/appletlib.c b/libbb/appletlib.c
index 51824f1b3..c90285ae9 100644
--- a/libbb/appletlib.c
+++ b/libbb/appletlib.c
@@ -1349,6 +1349,10 @@ int main(int argc UNUSED_PARAM, char **argv)
1349 break; 1349 break;
1350 } 1350 }
1351 } 1351 }
1352
1353 /* Have this process handle critical errors itself: the default
1354 * system-generated error dialogs may be inconvenient. */
1355 SetErrorMode(SEM_FAILCRITICALERRORS);
1352#endif 1356#endif
1353 1357
1354#if defined(__MINGW64_VERSION_MAJOR) 1358#if defined(__MINGW64_VERSION_MAJOR)
diff --git a/win32/process.c b/win32/process.c
index caea87492..94a1e23a9 100644
--- a/win32/process.c
+++ b/win32/process.c
@@ -443,7 +443,65 @@ BOOL WINAPI kill_child_ctrl_handler(DWORD dwCtrlType)
443 return FALSE; 443 return FALSE;
444} 444}
445 445
446static NORETURN void wait_for_child(HANDLE child) 446static int exit_code_to_wait_status_cmd(DWORD exit_code, const char *cmd)
447{
448 int sig, status;
449 DECLARE_PROC_ADDR(ULONG, RtlNtStatusToDosError, NTSTATUS);
450 DWORD flags, code;
451 char *msg = NULL;
452
453 if (exit_code == 0xc0000005)
454 return SIGSEGV;
455 else if (exit_code == 0xc000013a)
456 return SIGINT;
457
458 // When a process is terminated as if by a signal the Windows
459 // exit code is zero apart from the signal in its topmost byte.
460 // This is a busybox-w32 convention.
461 sig = exit_code >> 24;
462 if (sig != 0 && exit_code == sig << 24 && is_valid_signal(sig))
463 return sig;
464
465 // The exit code may be an NTSTATUS code. Try to obtain a
466 // descriptive message for it.
467 if (exit_code > 0xff) {
468 flags = FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM;
469 if (INIT_PROC_ADDR(ntdll.dll, RtlNtStatusToDosError)) {
470 code = RtlNtStatusToDosError(exit_code);
471 if (FormatMessage(flags, NULL, code, 0, (char *)&msg, 0, NULL)) {
472 char *cr = strrchr(msg, '\r');
473 if (cr) { // Replace CRLF with a space
474 cr[0] = ' ';
475 cr[1] = '\0';
476 }
477 }
478 }
479
480 if (cmd)
481 bb_error_msg("%s: %sError 0x%lx", cmd, msg ?: "", exit_code);
482 else
483 bb_error_msg("%s: %sError 0x%lx" + 4, msg ?: "", exit_code);
484 LocalFree(msg);
485 }
486
487 // Use least significant byte as exit code, but not if it's zero
488 // and the Windows exit code as a whole is non-zero.
489 status = exit_code & 0xff;
490 if (exit_code != 0 && status == 0)
491 status = 255;
492 return status << 8;
493}
494
495static int exit_code_to_posix_cmd(DWORD exit_code, const char *cmd)
496{
497 int status = exit_code_to_wait_status_cmd(exit_code, cmd);
498
499 if (WIFSIGNALED(status))
500 return 128 + WTERMSIG(status);
501 return WEXITSTATUS(status);
502}
503
504static NORETURN void wait_for_child(HANDLE child, const char *cmd)
447{ 505{
448 DWORD code; 506 DWORD code;
449 507
@@ -451,7 +509,7 @@ static NORETURN void wait_for_child(HANDLE child)
451 SetConsoleCtrlHandler(kill_child_ctrl_handler, TRUE); 509 SetConsoleCtrlHandler(kill_child_ctrl_handler, TRUE);
452 WaitForSingleObject(child, INFINITE); 510 WaitForSingleObject(child, INFINITE);
453 GetExitCodeProcess(child, &code); 511 GetExitCodeProcess(child, &code);
454 exit(exit_code_to_posix(code)); 512 exit(exit_code_to_posix_cmd(code, cmd));
455} 513}
456 514
457int 515int
@@ -459,7 +517,7 @@ mingw_execvp(const char *cmd, char *const *argv)
459{ 517{
460 intptr_t ret = mingw_spawnvp(P_NOWAIT, cmd, argv); 518 intptr_t ret = mingw_spawnvp(P_NOWAIT, cmd, argv);
461 if (ret != -1) 519 if (ret != -1)
462 wait_for_child((HANDLE)ret); 520 wait_for_child((HANDLE)ret, cmd);
463 return ret; 521 return ret;
464} 522}
465 523
@@ -468,7 +526,7 @@ mingw_execve(const char *cmd, char *const *argv, char *const *envp)
468{ 526{
469 intptr_t ret = mingw_spawn_interpreter(P_NOWAIT, cmd, argv, envp, 0); 527 intptr_t ret = mingw_spawn_interpreter(P_NOWAIT, cmd, argv, envp, 0);
470 if (ret != -1) 528 if (ret != -1)
471 wait_for_child((HANDLE)ret); 529 wait_for_child((HANDLE)ret, cmd);
472 return ret; 530 return ret;
473} 531}
474 532
@@ -896,33 +954,10 @@ int FAST_FUNC is_valid_signal(int number)
896 954
897int exit_code_to_wait_status(DWORD exit_code) 955int exit_code_to_wait_status(DWORD exit_code)
898{ 956{
899 int sig, status; 957 return exit_code_to_wait_status_cmd(exit_code, NULL);
900
901 if (exit_code == 0xc0000005)
902 return SIGSEGV;
903 else if (exit_code == 0xc000013a)
904 return SIGINT;
905
906 // When a process is terminated as if by a signal the Windows
907 // exit code is zero apart from the signal in its topmost byte.
908 // This is a busybox-w32 convention.
909 sig = exit_code >> 24;
910 if (sig != 0 && exit_code == sig << 24 && is_valid_signal(sig))
911 return sig;
912
913 // Use least significant byte as exit code, but not if it's zero
914 // and the Windows exit code as a whole is non-zero.
915 status = exit_code & 0xff;
916 if (exit_code != 0 && status == 0)
917 status = 255;
918 return status << 8;
919} 958}
920 959
921int exit_code_to_posix(DWORD exit_code) 960int exit_code_to_posix(DWORD exit_code)
922{ 961{
923 int status = exit_code_to_wait_status(exit_code); 962 return exit_code_to_posix_cmd(exit_code, NULL);
924
925 if (WIFSIGNALED(status))
926 return 128 + WTERMSIG(status);
927 return WEXITSTATUS(status);
928} 963}