blob: 9735d48f61b352f3def064c3cf6a901993d12590 [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 Vlasenkob6237c02020-12-17 12:34:25 +010072void FAST_FUNC send_r_n(const char *s)
73{
74 if (G.verbose)
75 bb_error_msg("send:'%s'", s);
76 printf("%s\r\n", s);
77}
78
Denys Vlasenko5707b522010-12-20 05:12:39 +010079char* FAST_FUNC send_mail_command(const char *fmt, const char *param)
Denis Vlasenko239d06b2008-11-06 23:42:42 +000080{
Denys Vlasenko5707b522010-12-20 05:12:39 +010081 char *msg;
Denys Vlasenko25b26802020-12-17 12:24:50 +010082 if (G.timeout)
83 alarm(G.timeout);
Denys Vlasenko5707b522010-12-20 05:12:39 +010084 msg = (char*)fmt;
85 if (fmt) {
Denis Vlasenko239d06b2008-11-06 23:42:42 +000086 msg = xasprintf(fmt, param);
Denys Vlasenkob6237c02020-12-17 12:34:25 +010087 send_r_n(msg);
Denis Vlasenko239d06b2008-11-06 23:42:42 +000088 }
Denys Vlasenko8131eea2009-11-02 14:19:51 +010089 fflush_all();
Denis Vlasenko239d06b2008-11-06 23:42:42 +000090 return msg;
91}
92
93// NB: parse_url can modify url[] (despite const), but only if '@' is there
94/*
Denys Vlasenko5707b522010-12-20 05:12:39 +010095static char* FAST_FUNC parse_url(char *url, char **user, char **pass)
Denis Vlasenko239d06b2008-11-06 23:42:42 +000096{
97 // parse [user[:pass]@]host
98 // return host
99 char *s = strchr(url, '@');
100 *user = *pass = NULL;
101 if (s) {
102 *s++ = '\0';
103 *user = url;
104 url = s;
105 s = strchr(*user, ':');
106 if (s) {
107 *s++ = '\0';
108 *pass = s;
109 }
110 }
111 return url;
112}
113*/
114
Denys Vlasenko8d634a02018-07-31 17:30:08 +0200115static void encode_n_base64(const char *fname, const char *text, size_t len)
Raffaello D. Di Napolif28b8852018-06-26 19:17:45 -0400116{
Denis Vlasenko239d06b2008-11-06 23:42:42 +0000117 enum {
Denys Vlasenko41fea012011-11-18 22:25:35 +0100118 SRC_BUF_SIZE = 57, /* This *MUST* be a multiple of 3 */
Denis Vlasenko239d06b2008-11-06 23:42:42 +0000119 DST_BUF_SIZE = 4 * ((SRC_BUF_SIZE + 2) / 3),
120 };
Denis Vlasenko239d06b2008-11-06 23:42:42 +0000121#define src_buf text
Denys Vlasenkoc8f9a8d2010-09-16 18:10:04 +0200122 char src[SRC_BUF_SIZE];
Denis Vlasenko239d06b2008-11-06 23:42:42 +0000123 FILE *fp = fp;
Denis Vlasenko239d06b2008-11-06 23:42:42 +0000124 char dst_buf[DST_BUF_SIZE + 1];
125
126 if (fname) {
Denys Vlasenko8d634a02018-07-31 17:30:08 +0200127 fp = (NOT_LONE_DASH(fname)) ? xfopen_for_read(fname) : stdin;
Denys Vlasenkoc8f9a8d2010-09-16 18:10:04 +0200128 src_buf = src;
Denys Vlasenko8d634a02018-07-31 17:30:08 +0200129 }
Denis Vlasenko239d06b2008-11-06 23:42:42 +0000130
131 while (1) {
132 size_t size;
133 if (fname) {
134 size = fread((char *)src_buf, 1, SRC_BUF_SIZE, fp);
135 if ((ssize_t)size < 0)
James Byrne69374872019-07-02 11:35:03 +0200136 bb_simple_perror_msg_and_die(bb_msg_read_error);
Denis Vlasenko239d06b2008-11-06 23:42:42 +0000137 } else {
138 size = len;
139 if (len > SRC_BUF_SIZE)
140 size = SRC_BUF_SIZE;
141 }
142 if (!size)
143 break;
144 // encode the buffer we just read in
145 bb_uuencode(dst_buf, src_buf, size, bb_uuenc_tbl_base64);
146 if (fname) {
Denys Vlasenko8d634a02018-07-31 17:30:08 +0200147 puts("");
Denis Vlasenko239d06b2008-11-06 23:42:42 +0000148 } else {
149 src_buf += size;
150 len -= size;
151 }
152 fwrite(dst_buf, 1, 4 * ((size + 2) / 3), stdout);
153 }
154 if (fname && NOT_LONE_DASH(fname))
155 fclose(fp);
156#undef src_buf
157}
158
Denys Vlasenko8d634a02018-07-31 17:30:08 +0200159void FAST_FUNC printstr_base64(const char *text)
160{
161 encode_n_base64(NULL, text, strlen(text));
162}
163
164void FAST_FUNC printbuf_base64(const char *text, unsigned len)
165{
166 encode_n_base64(NULL, text, len);
167}
168
169void FAST_FUNC printfile_base64(const char *fname)
170{
171 encode_n_base64(fname, NULL, 0);
172}
173
Denis Vlasenko239d06b2008-11-06 23:42:42 +0000174/*
175 * get username and password from a file descriptor
176 */
177void FAST_FUNC get_cred_or_die(int fd)
178{
Denis Vlasenko239d06b2008-11-06 23:42:42 +0000179 if (isatty(fd)) {
Denys Vlasenko17058a02018-04-07 15:50:30 +0200180 G.user = bb_ask_noecho(fd, /* timeout: */ 0, "User: ");
181 G.pass = bb_ask_noecho(fd, /* timeout: */ 0, "Password: ");
Denis Vlasenko239d06b2008-11-06 23:42:42 +0000182 } else {
Denys Vlasenko80c5b682011-05-08 21:21:10 +0200183 G.user = xmalloc_reads(fd, /* maxsize: */ NULL);
184 G.pass = xmalloc_reads(fd, /* maxsize: */ NULL);
Denis Vlasenko239d06b2008-11-06 23:42:42 +0000185 }
Denis Vlasenko021de3f2009-03-04 17:56:00 +0000186 if (!G.user || !*G.user || !G.pass)
James Byrne69374872019-07-02 11:35:03 +0200187 bb_simple_error_msg_and_die("no username or password");
Denis Vlasenko239d06b2008-11-06 23:42:42 +0000188}