blob: 3a1fd69496386836087270d7c559fa2950d72a19 [file] [log] [blame]
Denis Vlasenko239d06b2008-11-06 23:42:42 +00001/* vi: set sw=4 ts=4: */
2/*
3 * helper routines
4 *
5 * Copyright (C) 2008 by Vladimir Dronnikov <dronnikov@gmail.com>
6 *
Denys Vlasenko0ef64bd2010-08-16 20:14:46 +02007 * Licensed under GPLv2, see file LICENSE in this source tree.
Denis Vlasenko239d06b2008-11-06 23:42:42 +00008 */
Denys Vlasenkoe440b392017-08-16 17:45:32 +02009#include <sys/prctl.h>
Denis Vlasenko239d06b2008-11-06 23:42:42 +000010#include "libbb.h"
11#include "mail.h"
12
Denis Vlasenko239d06b2008-11-06 23:42:42 +000013// generic signal handler
14static void signal_handler(int signo)
15{
16#define err signo
17 if (SIGALRM == signo) {
James Byrne69374872019-07-02 11:35:03 +020018 bb_simple_error_msg_and_die("timed out");
Denis Vlasenko239d06b2008-11-06 23:42:42 +000019 }
20
21 // SIGCHLD. reap zombies
Denis Vlasenko021de3f2009-03-04 17:56:00 +000022 if (safe_waitpid(G.helper_pid, &err, WNOHANG) > 0) {
23 if (WIFSIGNALED(err))
24 bb_error_msg_and_die("helper killed by signal %u", WTERMSIG(err));
Denis Vlasenko239d06b2008-11-06 23:42:42 +000025 if (WIFEXITED(err)) {
26 G.helper_pid = 0;
27 if (WEXITSTATUS(err))
Denis Vlasenko021de3f2009-03-04 17:56:00 +000028 bb_error_msg_and_die("helper exited (%u)", WEXITSTATUS(err));
Denis Vlasenko239d06b2008-11-06 23:42:42 +000029 }
Denis Vlasenko021de3f2009-03-04 17:56:00 +000030 }
Denis Vlasenko239d06b2008-11-06 23:42:42 +000031#undef err
32}
33
34void FAST_FUNC launch_helper(const char **argv)
35{
36 // setup vanilla unidirectional pipes interchange
Denis Vlasenko021de3f2009-03-04 17:56:00 +000037 int i;
Denis Vlasenko239d06b2008-11-06 23:42:42 +000038 int pipes[4];
39
40 xpipe(pipes);
Denis Vlasenko021de3f2009-03-04 17:56:00 +000041 xpipe(pipes + 2);
42
Denis Vlasenko47741792009-03-10 16:01:57 +000043 // NB: handler must be installed before vfork
44 bb_signals(0
45 + (1 << SIGCHLD)
46 + (1 << SIGALRM)
47 , signal_handler);
48
Pascal Bellard926031b2010-07-04 15:32:38 +020049 G.helper_pid = xvfork();
Denis Vlasenko021de3f2009-03-04 17:56:00 +000050
51 i = (!G.helper_pid) * 2; // for parent:0, for child:2
Denys Vlasenko34c469a2011-09-18 03:01:49 +020052 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]
Denis Vlasenko021de3f2009-03-04 17:56:00 +000059
Denis Vlasenko239d06b2008-11-06 23:42:42 +000060 if (!G.helper_pid) {
Denys Vlasenkoe440b392017-08-16 17:45:32 +020061 // child
62 // if parent dies, get SIGTERM
63 prctl(PR_SET_PDEATHSIG, SIGTERM, 0, 0, 0);
64 // try to execute connection helper
Denis Vlasenko47741792009-03-10 16:01:57 +000065 // NB: SIGCHLD & SIGALRM revert to SIG_DFL on exec
Pascal Bellard21e8e8d2010-07-04 00:57:03 +020066 BB_EXECVP_or_die((char**)argv);
Denis Vlasenko239d06b2008-11-06 23:42:42 +000067 }
Denis Vlasenko021de3f2009-03-04 17:56:00 +000068
Denys Vlasenkoe440b392017-08-16 17:45:32 +020069 // parent goes on
Denis Vlasenko239d06b2008-11-06 23:42:42 +000070}
71
Denys Vlasenko5707b522010-12-20 05:12:39 +010072char* FAST_FUNC send_mail_command(const char *fmt, const char *param)
Denis Vlasenko239d06b2008-11-06 23:42:42 +000073{
Denys Vlasenko5707b522010-12-20 05:12:39 +010074 char *msg;
Denis Vlasenko239d06b2008-11-06 23:42:42 +000075 if (timeout)
76 alarm(timeout);
Denys Vlasenko5707b522010-12-20 05:12:39 +010077 msg = (char*)fmt;
78 if (fmt) {
Denis Vlasenko239d06b2008-11-06 23:42:42 +000079 msg = xasprintf(fmt, param);
Denys Vlasenko5707b522010-12-20 05:12:39 +010080 if (verbose)
81 bb_error_msg("send:'%s'", msg);
Denis Vlasenko239d06b2008-11-06 23:42:42 +000082 printf("%s\r\n", msg);
83 }
Denys Vlasenko8131eea2009-11-02 14:19:51 +010084 fflush_all();
Denis Vlasenko239d06b2008-11-06 23:42:42 +000085 return msg;
86}
87
88// NB: parse_url can modify url[] (despite const), but only if '@' is there
89/*
Denys Vlasenko5707b522010-12-20 05:12:39 +010090static char* FAST_FUNC parse_url(char *url, char **user, char **pass)
Denis Vlasenko239d06b2008-11-06 23:42:42 +000091{
92 // parse [user[:pass]@]host
93 // return host
94 char *s = strchr(url, '@');
95 *user = *pass = NULL;
96 if (s) {
97 *s++ = '\0';
98 *user = url;
99 url = s;
100 s = strchr(*user, ':');
101 if (s) {
102 *s++ = '\0';
103 *pass = s;
104 }
105 }
106 return url;
107}
108*/
109
Denys Vlasenko8d634a02018-07-31 17:30:08 +0200110static void encode_n_base64(const char *fname, const char *text, size_t len)
Raffaello D. Di Napolif28b8852018-06-26 19:17:45 -0400111{
Denis Vlasenko239d06b2008-11-06 23:42:42 +0000112 enum {
Denys Vlasenko41fea012011-11-18 22:25:35 +0100113 SRC_BUF_SIZE = 57, /* This *MUST* be a multiple of 3 */
Denis Vlasenko239d06b2008-11-06 23:42:42 +0000114 DST_BUF_SIZE = 4 * ((SRC_BUF_SIZE + 2) / 3),
115 };
Denis Vlasenko239d06b2008-11-06 23:42:42 +0000116#define src_buf text
Denys Vlasenkoc8f9a8d2010-09-16 18:10:04 +0200117 char src[SRC_BUF_SIZE];
Denis Vlasenko239d06b2008-11-06 23:42:42 +0000118 FILE *fp = fp;
Denis Vlasenko239d06b2008-11-06 23:42:42 +0000119 char dst_buf[DST_BUF_SIZE + 1];
120
121 if (fname) {
Denys Vlasenko8d634a02018-07-31 17:30:08 +0200122 fp = (NOT_LONE_DASH(fname)) ? xfopen_for_read(fname) : stdin;
Denys Vlasenkoc8f9a8d2010-09-16 18:10:04 +0200123 src_buf = src;
Denys Vlasenko8d634a02018-07-31 17:30:08 +0200124 }
Denis Vlasenko239d06b2008-11-06 23:42:42 +0000125
126 while (1) {
127 size_t size;
128 if (fname) {
129 size = fread((char *)src_buf, 1, SRC_BUF_SIZE, fp);
130 if ((ssize_t)size < 0)
James Byrne69374872019-07-02 11:35:03 +0200131 bb_simple_perror_msg_and_die(bb_msg_read_error);
Denis Vlasenko239d06b2008-11-06 23:42:42 +0000132 } else {
133 size = len;
134 if (len > SRC_BUF_SIZE)
135 size = SRC_BUF_SIZE;
136 }
137 if (!size)
138 break;
139 // encode the buffer we just read in
140 bb_uuencode(dst_buf, src_buf, size, bb_uuenc_tbl_base64);
141 if (fname) {
Denys Vlasenko8d634a02018-07-31 17:30:08 +0200142 puts("");
Denis Vlasenko239d06b2008-11-06 23:42:42 +0000143 } else {
144 src_buf += size;
145 len -= size;
146 }
147 fwrite(dst_buf, 1, 4 * ((size + 2) / 3), stdout);
148 }
149 if (fname && NOT_LONE_DASH(fname))
150 fclose(fp);
151#undef src_buf
152}
153
Denys Vlasenko8d634a02018-07-31 17:30:08 +0200154void FAST_FUNC printstr_base64(const char *text)
155{
156 encode_n_base64(NULL, text, strlen(text));
157}
158
159void FAST_FUNC printbuf_base64(const char *text, unsigned len)
160{
161 encode_n_base64(NULL, text, len);
162}
163
164void FAST_FUNC printfile_base64(const char *fname)
165{
166 encode_n_base64(fname, NULL, 0);
167}
168
Denis Vlasenko239d06b2008-11-06 23:42:42 +0000169/*
170 * get username and password from a file descriptor
171 */
172void FAST_FUNC get_cred_or_die(int fd)
173{
Denis Vlasenko239d06b2008-11-06 23:42:42 +0000174 if (isatty(fd)) {
Denys Vlasenko17058a02018-04-07 15:50:30 +0200175 G.user = bb_ask_noecho(fd, /* timeout: */ 0, "User: ");
176 G.pass = bb_ask_noecho(fd, /* timeout: */ 0, "Password: ");
Denis Vlasenko239d06b2008-11-06 23:42:42 +0000177 } else {
Denys Vlasenko80c5b682011-05-08 21:21:10 +0200178 G.user = xmalloc_reads(fd, /* maxsize: */ NULL);
179 G.pass = xmalloc_reads(fd, /* maxsize: */ NULL);
Denis Vlasenko239d06b2008-11-06 23:42:42 +0000180 }
Denis Vlasenko021de3f2009-03-04 17:56:00 +0000181 if (!G.user || !*G.user || !G.pass)
James Byrne69374872019-07-02 11:35:03 +0200182 bb_simple_error_msg_and_die("no username or password");
Denis Vlasenko239d06b2008-11-06 23:42:42 +0000183}