source: MondoRescue/branches/3.3/mindi-busybox/mailutils/mail.c@ 3723

Last change on this file since 3723 was 3621, checked in by Bruno Cornec, 10 years ago

New 3?3 banch for incorporation of latest busybox 1.25. Changing minor version to handle potential incompatibilities.

  • Property svn:eol-style set to native
File size: 4.1 KB
Line 
1/* vi: set sw=4 ts=4: */
2/*
3 * helper routines
4 *
5 * Copyright (C) 2008 by Vladimir Dronnikov <dronnikov@gmail.com>
6 *
7 * Licensed under GPLv2, see file LICENSE in this source tree.
8 */
9#include "libbb.h"
10#include "mail.h"
11
12static void kill_helper(void)
13{
14 if (G.helper_pid > 0) {
15 kill(G.helper_pid, SIGTERM);
16 G.helper_pid = 0;
17 }
18}
19
20// generic signal handler
21static void signal_handler(int signo)
22{
23#define err signo
24 if (SIGALRM == signo) {
25 kill_helper();
26 bb_error_msg_and_die("timed out");
27 }
28
29 // SIGCHLD. reap zombies
30 if (safe_waitpid(G.helper_pid, &err, WNOHANG) > 0) {
31 if (WIFSIGNALED(err))
32 bb_error_msg_and_die("helper killed by signal %u", WTERMSIG(err));
33 if (WIFEXITED(err)) {
34 G.helper_pid = 0;
35 if (WEXITSTATUS(err))
36 bb_error_msg_and_die("helper exited (%u)", WEXITSTATUS(err));
37 }
38 }
39#undef err
40}
41
42void FAST_FUNC launch_helper(const char **argv)
43{
44 // setup vanilla unidirectional pipes interchange
45 int i;
46 int pipes[4];
47
48 xpipe(pipes);
49 xpipe(pipes + 2);
50
51 // NB: handler must be installed before vfork
52 bb_signals(0
53 + (1 << SIGCHLD)
54 + (1 << SIGALRM)
55 , signal_handler);
56
57 G.helper_pid = xvfork();
58
59 i = (!G.helper_pid) * 2; // for parent:0, for child:2
60 close(pipes[i + 1]); // 1 or 3 - closing one write end
61 close(pipes[2 - i]); // 2 or 0 - closing one read end
62 xmove_fd(pipes[i], STDIN_FILENO); // 0 or 2 - using other read end
63 xmove_fd(pipes[3 - i], STDOUT_FILENO); // 3 or 1 - using other write end
64 // End result:
65 // parent stdout [3] -> child stdin [2]
66 // child stdout [1] -> parent stdin [0]
67
68 if (!G.helper_pid) {
69 // child: try to execute connection helper
70 // NB: SIGCHLD & SIGALRM revert to SIG_DFL on exec
71 BB_EXECVP_or_die((char**)argv);
72 }
73
74 // parent
75 // check whether child is alive
76 //redundant:signal_handler(SIGCHLD);
77 // child seems OK -> parent goes on
78 atexit(kill_helper);
79}
80
81char* FAST_FUNC send_mail_command(const char *fmt, const char *param)
82{
83 char *msg;
84 if (timeout)
85 alarm(timeout);
86 msg = (char*)fmt;
87 if (fmt) {
88 msg = xasprintf(fmt, param);
89 if (verbose)
90 bb_error_msg("send:'%s'", msg);
91 printf("%s\r\n", msg);
92 }
93 fflush_all();
94 return msg;
95}
96
97// NB: parse_url can modify url[] (despite const), but only if '@' is there
98/*
99static char* FAST_FUNC parse_url(char *url, char **user, char **pass)
100{
101 // parse [user[:pass]@]host
102 // return host
103 char *s = strchr(url, '@');
104 *user = *pass = NULL;
105 if (s) {
106 *s++ = '\0';
107 *user = url;
108 url = s;
109 s = strchr(*user, ':');
110 if (s) {
111 *s++ = '\0';
112 *pass = s;
113 }
114 }
115 return url;
116}
117*/
118
119void FAST_FUNC encode_base64(char *fname, const char *text, const char *eol)
120{
121 enum {
122 SRC_BUF_SIZE = 57, /* This *MUST* be a multiple of 3 */
123 DST_BUF_SIZE = 4 * ((SRC_BUF_SIZE + 2) / 3),
124 };
125#define src_buf text
126 char src[SRC_BUF_SIZE];
127 FILE *fp = fp;
128 ssize_t len = len;
129 char dst_buf[DST_BUF_SIZE + 1];
130
131 if (fname) {
132 fp = (NOT_LONE_DASH(fname)) ? xfopen_for_read(fname) : (FILE *)text;
133 src_buf = src;
134 } else if (text) {
135 // though we do not call uuencode(NULL, NULL) explicitly
136 // still we do not want to break things suddenly
137 len = strlen(text);
138 } else
139 return;
140
141 while (1) {
142 size_t size;
143 if (fname) {
144 size = fread((char *)src_buf, 1, SRC_BUF_SIZE, fp);
145 if ((ssize_t)size < 0)
146 bb_perror_msg_and_die(bb_msg_read_error);
147 } else {
148 size = len;
149 if (len > SRC_BUF_SIZE)
150 size = SRC_BUF_SIZE;
151 }
152 if (!size)
153 break;
154 // encode the buffer we just read in
155 bb_uuencode(dst_buf, src_buf, size, bb_uuenc_tbl_base64);
156 if (fname) {
157 puts(eol);
158 } else {
159 src_buf += size;
160 len -= size;
161 }
162 fwrite(dst_buf, 1, 4 * ((size + 2) / 3), stdout);
163 }
164 if (fname && NOT_LONE_DASH(fname))
165 fclose(fp);
166#undef src_buf
167}
168
169/*
170 * get username and password from a file descriptor
171 */
172void FAST_FUNC get_cred_or_die(int fd)
173{
174 if (isatty(fd)) {
175 G.user = xstrdup(bb_ask(fd, /* timeout: */ 0, "User: "));
176 G.pass = xstrdup(bb_ask(fd, /* timeout: */ 0, "Password: "));
177 } else {
178 G.user = xmalloc_reads(fd, /* maxsize: */ NULL);
179 G.pass = xmalloc_reads(fd, /* maxsize: */ NULL);
180 }
181 if (!G.user || !*G.user || !G.pass)
182 bb_error_msg_and_die("no username or password");
183}
Note: See TracBrowser for help on using the repository browser.