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>
This commit is contained in:
parent
b6237c0657
commit
b0e7cb4c3f
@ -10,35 +10,35 @@
|
|||||||
#include "libbb.h"
|
#include "libbb.h"
|
||||||
#include "mail.h"
|
#include "mail.h"
|
||||||
|
|
||||||
// generic signal handler
|
// common signal handler
|
||||||
static void signal_handler(int signo)
|
static void signal_handler(int signo)
|
||||||
{
|
{
|
||||||
#define err signo
|
|
||||||
if (SIGALRM == signo) {
|
if (SIGALRM == signo) {
|
||||||
bb_simple_error_msg_and_die("timed out");
|
bb_simple_error_msg_and_die("timed out");
|
||||||
}
|
}
|
||||||
|
|
||||||
// SIGCHLD. reap zombies
|
// SIGCHLD. reap the zombie if we expect one
|
||||||
if (safe_waitpid(G.helper_pid, &err, WNOHANG) > 0) {
|
if (G.helper_pid == 0)
|
||||||
if (WIFSIGNALED(err))
|
return;
|
||||||
bb_error_msg_and_die("helper killed by signal %u", WTERMSIG(err));
|
#define status signo
|
||||||
if (WIFEXITED(err)) {
|
if (safe_waitpid(G.helper_pid, &status, WNOHANG) > 0) {
|
||||||
G.helper_pid = 0;
|
G.helper_pid = 0;
|
||||||
if (WEXITSTATUS(err))
|
if (WIFSIGNALED(status))
|
||||||
bb_error_msg_and_die("helper exited (%u)", WEXITSTATUS(err));
|
bb_error_msg_and_die("helper killed by signal %u", WTERMSIG(status));
|
||||||
}
|
if (WIFEXITED(status) && WEXITSTATUS(status) != 0)
|
||||||
|
bb_error_msg_and_die("helper exited (%u)", WEXITSTATUS(status));
|
||||||
}
|
}
|
||||||
#undef err
|
#undef status
|
||||||
}
|
}
|
||||||
|
|
||||||
void FAST_FUNC launch_helper(const char **argv)
|
void FAST_FUNC launch_helper(const char **argv)
|
||||||
{
|
{
|
||||||
// setup vanilla unidirectional pipes interchange
|
pid_t pid;
|
||||||
int i;
|
struct fd_pair child_out;
|
||||||
int pipes[4];
|
struct fd_pair child_in;
|
||||||
|
|
||||||
xpipe(pipes);
|
xpiped_pair(child_out);
|
||||||
xpipe(pipes + 2);
|
xpiped_pair(child_in);
|
||||||
|
|
||||||
// NB: handler must be installed before vfork
|
// NB: handler must be installed before vfork
|
||||||
bb_signals(0
|
bb_signals(0
|
||||||
@ -46,25 +46,23 @@ void FAST_FUNC launch_helper(const char **argv)
|
|||||||
+ (1 << SIGALRM)
|
+ (1 << SIGALRM)
|
||||||
, signal_handler);
|
, signal_handler);
|
||||||
|
|
||||||
G.helper_pid = xvfork();
|
G.helper_pid = pid = xvfork();
|
||||||
|
if (pid == 0) {
|
||||||
i = (!G.helper_pid) * 2; // for parent:0, for child:2
|
|
||||||
close(pipes[i + 1]); // 1 or 3 - closing one write end
|
|
||||||
close(pipes[2 - i]); // 2 or 0 - closing one read end
|
|
||||||
xmove_fd(pipes[i], STDIN_FILENO); // 0 or 2 - using other read end
|
|
||||||
xmove_fd(pipes[3 - i], STDOUT_FILENO); // 3 or 1 - using other write end
|
|
||||||
// End result:
|
|
||||||
// parent stdout [3] -> child stdin [2]
|
|
||||||
// child stdout [1] -> parent stdin [0]
|
|
||||||
|
|
||||||
if (!G.helper_pid) {
|
|
||||||
// child
|
// child
|
||||||
|
close(child_in.wr);
|
||||||
|
close(child_out.rd);
|
||||||
|
xmove_fd(child_in.rd, STDIN_FILENO);
|
||||||
|
xmove_fd(child_out.wr, STDOUT_FILENO);
|
||||||
// if parent dies, get SIGTERM
|
// if parent dies, get SIGTERM
|
||||||
prctl(PR_SET_PDEATHSIG, SIGTERM, 0, 0, 0);
|
prctl(PR_SET_PDEATHSIG, SIGTERM, 0, 0, 0);
|
||||||
// try to execute connection helper
|
// try to execute connection helper
|
||||||
// NB: SIGCHLD & SIGALRM revert to SIG_DFL on exec
|
// NB: SIGCHLD & SIGALRM revert to SIG_DFL on exec
|
||||||
BB_EXECVP_or_die((char**)argv);
|
BB_EXECVP_or_die((char**)argv);
|
||||||
}
|
}
|
||||||
|
close(child_out.wr);
|
||||||
|
close(child_in.rd);
|
||||||
|
xmove_fd(child_out.rd, STDIN_FILENO);
|
||||||
|
xmove_fd(child_in.wr, STDOUT_FILENO);
|
||||||
|
|
||||||
// parent goes on
|
// parent goes on
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user