aboutsummaryrefslogtreecommitdiff
path: root/mailutils/mail.c
diff options
context:
space:
mode:
Diffstat (limited to 'mailutils/mail.c')
-rw-r--r--mailutils/mail.c88
1 files changed, 53 insertions, 35 deletions
diff --git a/mailutils/mail.c b/mailutils/mail.c
index 3a1fd6949..f48b41bab 100644
--- a/mailutils/mail.c
+++ b/mailutils/mail.c
@@ -6,39 +6,45 @@
6 * 6 *
7 * Licensed under GPLv2, see file LICENSE in this source tree. 7 * Licensed under GPLv2, see file LICENSE in this source tree.
8 */ 8 */
9#include <sys/prctl.h> 9#if defined(__linux__)
10# include <sys/prctl.h>
11# define PRCTL
12#elif defined(__FreeBSD__)
13# include <sys/procctl.h>
14# define PROCCTL
15#endif
10#include "libbb.h" 16#include "libbb.h"
11#include "mail.h" 17#include "mail.h"
12 18
13// generic signal handler 19// common signal handler
14static void signal_handler(int signo) 20static void signal_handler(int signo)
15{ 21{
16#define err signo
17 if (SIGALRM == signo) { 22 if (SIGALRM == signo) {
18 bb_simple_error_msg_and_die("timed out"); 23 bb_simple_error_msg_and_die("timed out");
19 } 24 }
20 25
21 // SIGCHLD. reap zombies 26 // SIGCHLD. reap the zombie if we expect one
22 if (safe_waitpid(G.helper_pid, &err, WNOHANG) > 0) { 27 if (G.helper_pid == 0)
23 if (WIFSIGNALED(err)) 28 return;
24 bb_error_msg_and_die("helper killed by signal %u", WTERMSIG(err)); 29#define status signo
25 if (WIFEXITED(err)) { 30 if (safe_waitpid(G.helper_pid, &status, WNOHANG) > 0) {
26 G.helper_pid = 0; 31 G.helper_pid = 0;
27 if (WEXITSTATUS(err)) 32 if (WIFSIGNALED(status))
28 bb_error_msg_and_die("helper exited (%u)", WEXITSTATUS(err)); 33 bb_error_msg_and_die("helper killed by signal %u", WTERMSIG(status));
29 } 34 if (WIFEXITED(status) && WEXITSTATUS(status) != 0)
35 bb_error_msg_and_die("helper exited (%u)", WEXITSTATUS(status));
30 } 36 }
31#undef err 37#undef status
32} 38}
33 39
34void FAST_FUNC launch_helper(const char **argv) 40void FAST_FUNC launch_helper(const char **argv)
35{ 41{
36 // setup vanilla unidirectional pipes interchange 42 pid_t pid;
37 int i; 43 struct fd_pair child_out;
38 int pipes[4]; 44 struct fd_pair child_in;
39 45
40 xpipe(pipes); 46 xpiped_pair(child_out);
41 xpipe(pipes + 2); 47 xpiped_pair(child_in);
42 48
43 // NB: handler must be installed before vfork 49 // NB: handler must be installed before vfork
44 bb_signals(0 50 bb_signals(0
@@ -46,40 +52,52 @@ void FAST_FUNC launch_helper(const char **argv)
46 + (1 << SIGALRM) 52 + (1 << SIGALRM)
47 , signal_handler); 53 , signal_handler);
48 54
49 G.helper_pid = xvfork(); 55 fflush_all();
50 56 pid = xvfork();
51 i = (!G.helper_pid) * 2; // for parent:0, for child:2 57 if (pid == 0) {
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 58 // child
59 close(child_in.wr);
60 close(child_out.rd);
61 xmove_fd(child_in.rd, STDIN_FILENO);
62 xmove_fd(child_out.wr, STDOUT_FILENO);
62 // if parent dies, get SIGTERM 63 // if parent dies, get SIGTERM
64#if defined(PRCTL)
63 prctl(PR_SET_PDEATHSIG, SIGTERM, 0, 0, 0); 65 prctl(PR_SET_PDEATHSIG, SIGTERM, 0, 0, 0);
66#elif defined(PROCCTL)
67 {
68 int signum = SIGTERM;
69 procctl(P_PID, 0, PROC_PDEATHSIG_CTL, &signum);
70 }
71#endif
64 // try to execute connection helper 72 // try to execute connection helper
65 // NB: SIGCHLD & SIGALRM revert to SIG_DFL on exec 73 // NB: SIGCHLD & SIGALRM revert to SIG_DFL on exec
66 BB_EXECVP_or_die((char**)argv); 74 BB_EXECVP_or_die((char**)argv);
67 } 75 }
76 G.helper_pid = pid;
77 close(child_out.wr);
78 close(child_in.rd);
79 xmove_fd(child_out.rd, STDIN_FILENO);
80 xmove_fd(child_in.wr, STDOUT_FILENO);
68 81
69 // parent goes on 82 // parent goes on
70} 83}
71 84
85void FAST_FUNC send_r_n(const char *s)
86{
87 if (G.verbose)
88 bb_error_msg("send:'%s'", s);
89 printf("%s\r\n", s);
90}
91
72char* FAST_FUNC send_mail_command(const char *fmt, const char *param) 92char* FAST_FUNC send_mail_command(const char *fmt, const char *param)
73{ 93{
74 char *msg; 94 char *msg;
75 if (timeout) 95 if (G.timeout)
76 alarm(timeout); 96 alarm(G.timeout);
77 msg = (char*)fmt; 97 msg = (char*)fmt;
78 if (fmt) { 98 if (fmt) {
79 msg = xasprintf(fmt, param); 99 msg = xasprintf(fmt, param);
80 if (verbose) 100 send_r_n(msg);
81 bb_error_msg("send:'%s'", msg);
82 printf("%s\r\n", msg);
83 } 101 }
84 fflush_all(); 102 fflush_all();
85 return msg; 103 return msg;