diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2020-12-17 12:51:58 +0100 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2020-12-17 12:51:58 +0100 |
commit | b0e7cb4c3f1bd9872444711ebc44258430156cad (patch) | |
tree | c129fc2f71354fcfc9ac2f77f018ddf1a73b36e1 | |
parent | b6237c0657074e8a61b2123601df36389659b603 (diff) | |
download | busybox-w32-b0e7cb4c3f1bd9872444711ebc44258430156cad.tar.gz busybox-w32-b0e7cb4c3f1bd9872444711ebc44258430156cad.tar.bz2 busybox-w32-b0e7cb4c3f1bd9872444711ebc44258430156cad.zip |
mail: deobfuscate launch_helper()
13 bytes are not worth the risk of doing something iffy after vfork().
Let's have much clearer code there.
function old new delta
launch_helper 175 188 +13
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | mailutils/mail.c | 56 |
1 files changed, 27 insertions, 29 deletions
diff --git a/mailutils/mail.c b/mailutils/mail.c index 9735d48f6..7e9efdbfa 100644 --- a/mailutils/mail.c +++ b/mailutils/mail.c | |||
@@ -10,35 +10,35 @@ | |||
10 | #include "libbb.h" | 10 | #include "libbb.h" |
11 | #include "mail.h" | 11 | #include "mail.h" |
12 | 12 | ||
13 | // generic signal handler | 13 | // common signal handler |
14 | static void signal_handler(int signo) | 14 | static void signal_handler(int signo) |
15 | { | 15 | { |
16 | #define err signo | ||
17 | if (SIGALRM == signo) { | 16 | if (SIGALRM == signo) { |
18 | bb_simple_error_msg_and_die("timed out"); | 17 | bb_simple_error_msg_and_die("timed out"); |
19 | } | 18 | } |
20 | 19 | ||
21 | // SIGCHLD. reap zombies | 20 | // SIGCHLD. reap the zombie if we expect one |
22 | if (safe_waitpid(G.helper_pid, &err, WNOHANG) > 0) { | 21 | if (G.helper_pid == 0) |
23 | if (WIFSIGNALED(err)) | 22 | return; |
24 | bb_error_msg_and_die("helper killed by signal %u", WTERMSIG(err)); | 23 | #define status signo |
25 | if (WIFEXITED(err)) { | 24 | if (safe_waitpid(G.helper_pid, &status, WNOHANG) > 0) { |
26 | G.helper_pid = 0; | 25 | G.helper_pid = 0; |
27 | if (WEXITSTATUS(err)) | 26 | if (WIFSIGNALED(status)) |
28 | bb_error_msg_and_die("helper exited (%u)", WEXITSTATUS(err)); | 27 | bb_error_msg_and_die("helper killed by signal %u", WTERMSIG(status)); |
29 | } | 28 | if (WIFEXITED(status) && WEXITSTATUS(status) != 0) |
29 | bb_error_msg_and_die("helper exited (%u)", WEXITSTATUS(status)); | ||
30 | } | 30 | } |
31 | #undef err | 31 | #undef status |
32 | } | 32 | } |
33 | 33 | ||
34 | void FAST_FUNC launch_helper(const char **argv) | 34 | void FAST_FUNC launch_helper(const char **argv) |
35 | { | 35 | { |
36 | // setup vanilla unidirectional pipes interchange | 36 | pid_t pid; |
37 | int i; | 37 | struct fd_pair child_out; |
38 | int pipes[4]; | 38 | struct fd_pair child_in; |
39 | 39 | ||
40 | xpipe(pipes); | 40 | xpiped_pair(child_out); |
41 | xpipe(pipes + 2); | 41 | xpiped_pair(child_in); |
42 | 42 | ||
43 | // NB: handler must be installed before vfork | 43 | // NB: handler must be installed before vfork |
44 | bb_signals(0 | 44 | bb_signals(0 |
@@ -46,25 +46,23 @@ void FAST_FUNC launch_helper(const char **argv) | |||
46 | + (1 << SIGALRM) | 46 | + (1 << SIGALRM) |
47 | , signal_handler); | 47 | , signal_handler); |
48 | 48 | ||
49 | G.helper_pid = xvfork(); | 49 | G.helper_pid = pid = xvfork(); |
50 | 50 | if (pid == 0) { | |
51 | i = (!G.helper_pid) * 2; // for parent:0, for child:2 | ||
52 | close(pipes[i + 1]); // 1 or 3 - closing one write end | ||
53 | close(pipes[2 - i]); // 2 or 0 - closing one read end | ||
54 | xmove_fd(pipes[i], STDIN_FILENO); // 0 or 2 - using other read end | ||
55 | xmove_fd(pipes[3 - i], STDOUT_FILENO); // 3 or 1 - using other write end | ||
56 | // End result: | ||
57 | // parent stdout [3] -> child stdin [2] | ||
58 | // child stdout [1] -> parent stdin [0] | ||
59 | |||
60 | if (!G.helper_pid) { | ||
61 | // child | 51 | // child |
52 | close(child_in.wr); | ||
53 | close(child_out.rd); | ||
54 | xmove_fd(child_in.rd, STDIN_FILENO); | ||
55 | xmove_fd(child_out.wr, STDOUT_FILENO); | ||
62 | // if parent dies, get SIGTERM | 56 | // if parent dies, get SIGTERM |
63 | prctl(PR_SET_PDEATHSIG, SIGTERM, 0, 0, 0); | 57 | prctl(PR_SET_PDEATHSIG, SIGTERM, 0, 0, 0); |
64 | // try to execute connection helper | 58 | // try to execute connection helper |
65 | // NB: SIGCHLD & SIGALRM revert to SIG_DFL on exec | 59 | // NB: SIGCHLD & SIGALRM revert to SIG_DFL on exec |
66 | BB_EXECVP_or_die((char**)argv); | 60 | BB_EXECVP_or_die((char**)argv); |
67 | } | 61 | } |
62 | close(child_out.wr); | ||
63 | close(child_in.rd); | ||
64 | xmove_fd(child_out.rd, STDIN_FILENO); | ||
65 | xmove_fd(child_in.wr, STDOUT_FILENO); | ||
68 | 66 | ||
69 | // parent goes on | 67 | // parent goes on |
70 | } | 68 | } |