فهرست منبع

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>
Denys Vlasenko 3 سال پیش
والد
کامیت
b0e7cb4c3f
1فایلهای تغییر یافته به همراه27 افزوده شده و 29 حذف شده
  1. 27 29
      mailutils/mail.c

+ 27 - 29
mailutils/mail.c

@@ -10,35 +10,35 @@
 #include "libbb.h"
 #include "mail.h"
 
-// generic signal handler
+// common signal handler
 static void signal_handler(int signo)
 {
-#define err signo
 	if (SIGALRM == signo) {
 		bb_simple_error_msg_and_die("timed out");
 	}
 
-	// SIGCHLD. reap zombies
-	if (safe_waitpid(G.helper_pid, &err, WNOHANG) > 0) {
-		if (WIFSIGNALED(err))
-			bb_error_msg_and_die("helper killed by signal %u", WTERMSIG(err));
-		if (WIFEXITED(err)) {
-			G.helper_pid = 0;
-			if (WEXITSTATUS(err))
-				bb_error_msg_and_die("helper exited (%u)", WEXITSTATUS(err));
-		}
+	// SIGCHLD. reap the zombie if we expect one
+	if (G.helper_pid == 0)
+		return;
+#define status signo
+	if (safe_waitpid(G.helper_pid, &status, WNOHANG) > 0) {
+		G.helper_pid = 0;
+		if (WIFSIGNALED(status))
+			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)
 {
-	// setup vanilla unidirectional pipes interchange
-	int i;
-	int pipes[4];
+	pid_t pid;
+	struct fd_pair child_out;
+	struct fd_pair child_in;
 
-	xpipe(pipes);
-	xpipe(pipes + 2);
+	xpiped_pair(child_out);
+	xpiped_pair(child_in);
 
 	// NB: handler must be installed before vfork
 	bb_signals(0
@@ -46,25 +46,23 @@ void FAST_FUNC launch_helper(const char **argv)
 		+ (1 << SIGALRM)
 		, signal_handler);
 
-	G.helper_pid = xvfork();
-
-	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) {
+	G.helper_pid = pid = xvfork();
+	if (pid == 0) {
 		// 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
 		prctl(PR_SET_PDEATHSIG, SIGTERM, 0, 0, 0);
 		// try to execute connection helper
 		// NB: SIGCHLD & SIGALRM revert to SIG_DFL on exec
 		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
 }