blob: 7af7edd6c9e58cffdcf1f5344c3ce928fc5e7c6f [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) {
Denis Vlasenko239d06b2008-11-06 23:42:42 +000018 bb_error_msg_and_die("timed out");
19 }
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
110void FAST_FUNC encode_base64(char *fname, const char *text, const char *eol)
111{
112 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;
119 ssize_t len = len;
120 char dst_buf[DST_BUF_SIZE + 1];
121
122 if (fname) {
123 fp = (NOT_LONE_DASH(fname)) ? xfopen_for_read(fname) : (FILE *)text;
Denys Vlasenkoc8f9a8d2010-09-16 18:10:04 +0200124 src_buf = src;
Denis Vlasenko239d06b2008-11-06 23:42:42 +0000125 } else if (text) {
126 // though we do not call uuencode(NULL, NULL) explicitly
127 // still we do not want to break things suddenly
128 len = strlen(text);
129 } else
130 return;
131
132 while (1) {
133 size_t size;
134 if (fname) {
135 size = fread((char *)src_buf, 1, SRC_BUF_SIZE, fp);
136 if ((ssize_t)size < 0)
137 bb_perror_msg_and_die(bb_msg_read_error);
138 } else {
139 size = len;
140 if (len > SRC_BUF_SIZE)
141 size = SRC_BUF_SIZE;
142 }
143 if (!size)
144 break;
145 // encode the buffer we just read in
146 bb_uuencode(dst_buf, src_buf, size, bb_uuenc_tbl_base64);
147 if (fname) {
Denys Vlasenkod60752f2015-10-07 22:42:45 +0200148 puts(eol);
Denis Vlasenko239d06b2008-11-06 23:42:42 +0000149 } else {
150 src_buf += size;
151 len -= size;
152 }
153 fwrite(dst_buf, 1, 4 * ((size + 2) / 3), stdout);
154 }
155 if (fname && NOT_LONE_DASH(fname))
156 fclose(fp);
157#undef src_buf
158}
159
Denis Vlasenko239d06b2008-11-06 23:42:42 +0000160/*
161 * get username and password from a file descriptor
162 */
163void FAST_FUNC get_cred_or_die(int fd)
164{
Denis Vlasenko239d06b2008-11-06 23:42:42 +0000165 if (isatty(fd)) {
Denys Vlasenko17058a02018-04-07 15:50:30 +0200166 G.user = bb_ask_noecho(fd, /* timeout: */ 0, "User: ");
167 G.pass = bb_ask_noecho(fd, /* timeout: */ 0, "Password: ");
Denis Vlasenko239d06b2008-11-06 23:42:42 +0000168 } else {
Denys Vlasenko80c5b682011-05-08 21:21:10 +0200169 G.user = xmalloc_reads(fd, /* maxsize: */ NULL);
170 G.pass = xmalloc_reads(fd, /* maxsize: */ NULL);
Denis Vlasenko239d06b2008-11-06 23:42:42 +0000171 }
Denis Vlasenko021de3f2009-03-04 17:56:00 +0000172 if (!G.user || !*G.user || !G.pass)
Denis Vlasenko239d06b2008-11-06 23:42:42 +0000173 bb_error_msg_and_die("no username or password");
174}