blob: 7e9efdbfa84510baea70d974b90dc7ff15560528 [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
Denys Vlasenkob0e7cb42020-12-17 12:51:58 +010013// common signal handler
Denis Vlasenko239d06b2008-11-06 23:42:42 +000014static void signal_handler(int signo)
15{
Denis Vlasenko239d06b2008-11-06 23:42:42 +000016 if (SIGALRM == signo) {
James Byrne69374872019-07-02 11:35:03 +020017 bb_simple_error_msg_and_die("timed out");
Denis Vlasenko239d06b2008-11-06 23:42:42 +000018 }
19
Denys Vlasenkob0e7cb42020-12-17 12:51:58 +010020 // SIGCHLD. reap the zombie if we expect one
21 if (G.helper_pid == 0)
22 return;
23#define status signo
24 if (safe_waitpid(G.helper_pid, &status, WNOHANG) > 0) {
25 G.helper_pid = 0;
26 if (WIFSIGNALED(status))
27 bb_error_msg_and_die("helper killed by signal %u", WTERMSIG(status));
28 if (WIFEXITED(status) && WEXITSTATUS(status) != 0)
29 bb_error_msg_and_die("helper exited (%u)", WEXITSTATUS(status));
Denis Vlasenko021de3f2009-03-04 17:56:00 +000030 }
Denys Vlasenkob0e7cb42020-12-17 12:51:58 +010031#undef status
Denis Vlasenko239d06b2008-11-06 23:42:42 +000032}
33
34void FAST_FUNC launch_helper(const char **argv)
35{
Denys Vlasenkob0e7cb42020-12-17 12:51:58 +010036 pid_t pid;
37 struct fd_pair child_out;
38 struct fd_pair child_in;
Denis Vlasenko239d06b2008-11-06 23:42:42 +000039
Denys Vlasenkob0e7cb42020-12-17 12:51:58 +010040 xpiped_pair(child_out);
41 xpiped_pair(child_in);
Denis Vlasenko021de3f2009-03-04 17:56:00 +000042
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
Denys Vlasenkob0e7cb42020-12-17 12:51:58 +010049 G.helper_pid = pid = xvfork();
50 if (pid == 0) {
Denys Vlasenkoe440b392017-08-16 17:45:32 +020051 // child
Denys Vlasenkob0e7cb42020-12-17 12:51:58 +010052 close(child_in.wr);
53 close(child_out.rd);
54 xmove_fd(child_in.rd, STDIN_FILENO);
55 xmove_fd(child_out.wr, STDOUT_FILENO);
Denys Vlasenkoe440b392017-08-16 17:45:32 +020056 // if parent dies, get SIGTERM
57 prctl(PR_SET_PDEATHSIG, SIGTERM, 0, 0, 0);
58 // try to execute connection helper
Denis Vlasenko47741792009-03-10 16:01:57 +000059 // NB: SIGCHLD & SIGALRM revert to SIG_DFL on exec
Pascal Bellard21e8e8d2010-07-04 00:57:03 +020060 BB_EXECVP_or_die((char**)argv);
Denis Vlasenko239d06b2008-11-06 23:42:42 +000061 }
Denys Vlasenkob0e7cb42020-12-17 12:51:58 +010062 close(child_out.wr);
63 close(child_in.rd);
64 xmove_fd(child_out.rd, STDIN_FILENO);
65 xmove_fd(child_in.wr, STDOUT_FILENO);
Denis Vlasenko021de3f2009-03-04 17:56:00 +000066
Denys Vlasenkoe440b392017-08-16 17:45:32 +020067 // parent goes on
Denis Vlasenko239d06b2008-11-06 23:42:42 +000068}
69
Denys Vlasenkob6237c02020-12-17 12:34:25 +010070void FAST_FUNC send_r_n(const char *s)
71{
72 if (G.verbose)
73 bb_error_msg("send:'%s'", s);
74 printf("%s\r\n", s);
75}
76
Denys Vlasenko5707b522010-12-20 05:12:39 +010077char* FAST_FUNC send_mail_command(const char *fmt, const char *param)
Denis Vlasenko239d06b2008-11-06 23:42:42 +000078{
Denys Vlasenko5707b522010-12-20 05:12:39 +010079 char *msg;
Denys Vlasenko25b26802020-12-17 12:24:50 +010080 if (G.timeout)
81 alarm(G.timeout);
Denys Vlasenko5707b522010-12-20 05:12:39 +010082 msg = (char*)fmt;
83 if (fmt) {
Denis Vlasenko239d06b2008-11-06 23:42:42 +000084 msg = xasprintf(fmt, param);
Denys Vlasenkob6237c02020-12-17 12:34:25 +010085 send_r_n(msg);
Denis Vlasenko239d06b2008-11-06 23:42:42 +000086 }
Denys Vlasenko8131eea2009-11-02 14:19:51 +010087 fflush_all();
Denis Vlasenko239d06b2008-11-06 23:42:42 +000088 return msg;
89}
90
91// NB: parse_url can modify url[] (despite const), but only if '@' is there
92/*
Denys Vlasenko5707b522010-12-20 05:12:39 +010093static char* FAST_FUNC parse_url(char *url, char **user, char **pass)
Denis Vlasenko239d06b2008-11-06 23:42:42 +000094{
95 // parse [user[:pass]@]host
96 // return host
97 char *s = strchr(url, '@');
98 *user = *pass = NULL;
99 if (s) {
100 *s++ = '\0';
101 *user = url;
102 url = s;
103 s = strchr(*user, ':');
104 if (s) {
105 *s++ = '\0';
106 *pass = s;
107 }
108 }
109 return url;
110}
111*/
112
Denys Vlasenko8d634a02018-07-31 17:30:08 +0200113static void encode_n_base64(const char *fname, const char *text, size_t len)
Raffaello D. Di Napolif28b8852018-06-26 19:17:45 -0400114{
Denis Vlasenko239d06b2008-11-06 23:42:42 +0000115 enum {
Denys Vlasenko41fea012011-11-18 22:25:35 +0100116 SRC_BUF_SIZE = 57, /* This *MUST* be a multiple of 3 */
Denis Vlasenko239d06b2008-11-06 23:42:42 +0000117 DST_BUF_SIZE = 4 * ((SRC_BUF_SIZE + 2) / 3),
118 };
Denis Vlasenko239d06b2008-11-06 23:42:42 +0000119#define src_buf text
Denys Vlasenkoc8f9a8d2010-09-16 18:10:04 +0200120 char src[SRC_BUF_SIZE];
Denis Vlasenko239d06b2008-11-06 23:42:42 +0000121 FILE *fp = fp;
Denis Vlasenko239d06b2008-11-06 23:42:42 +0000122 char dst_buf[DST_BUF_SIZE + 1];
123
124 if (fname) {
Denys Vlasenko8d634a02018-07-31 17:30:08 +0200125 fp = (NOT_LONE_DASH(fname)) ? xfopen_for_read(fname) : stdin;
Denys Vlasenkoc8f9a8d2010-09-16 18:10:04 +0200126 src_buf = src;
Denys Vlasenko8d634a02018-07-31 17:30:08 +0200127 }
Denis Vlasenko239d06b2008-11-06 23:42:42 +0000128
129 while (1) {
130 size_t size;
131 if (fname) {
132 size = fread((char *)src_buf, 1, SRC_BUF_SIZE, fp);
133 if ((ssize_t)size < 0)
James Byrne69374872019-07-02 11:35:03 +0200134 bb_simple_perror_msg_and_die(bb_msg_read_error);
Denis Vlasenko239d06b2008-11-06 23:42:42 +0000135 } else {
136 size = len;
137 if (len > SRC_BUF_SIZE)
138 size = SRC_BUF_SIZE;
139 }
140 if (!size)
141 break;
142 // encode the buffer we just read in
143 bb_uuencode(dst_buf, src_buf, size, bb_uuenc_tbl_base64);
144 if (fname) {
Denys Vlasenko8d634a02018-07-31 17:30:08 +0200145 puts("");
Denis Vlasenko239d06b2008-11-06 23:42:42 +0000146 } else {
147 src_buf += size;
148 len -= size;
149 }
150 fwrite(dst_buf, 1, 4 * ((size + 2) / 3), stdout);
151 }
152 if (fname && NOT_LONE_DASH(fname))
153 fclose(fp);
154#undef src_buf
155}
156
Denys Vlasenko8d634a02018-07-31 17:30:08 +0200157void FAST_FUNC printstr_base64(const char *text)
158{
159 encode_n_base64(NULL, text, strlen(text));
160}
161
162void FAST_FUNC printbuf_base64(const char *text, unsigned len)
163{
164 encode_n_base64(NULL, text, len);
165}
166
167void FAST_FUNC printfile_base64(const char *fname)
168{
169 encode_n_base64(fname, NULL, 0);
170}
171
Denis Vlasenko239d06b2008-11-06 23:42:42 +0000172/*
173 * get username and password from a file descriptor
174 */
175void FAST_FUNC get_cred_or_die(int fd)
176{
Denis Vlasenko239d06b2008-11-06 23:42:42 +0000177 if (isatty(fd)) {
Denys Vlasenko17058a02018-04-07 15:50:30 +0200178 G.user = bb_ask_noecho(fd, /* timeout: */ 0, "User: ");
179 G.pass = bb_ask_noecho(fd, /* timeout: */ 0, "Password: ");
Denis Vlasenko239d06b2008-11-06 23:42:42 +0000180 } else {
Denys Vlasenko80c5b682011-05-08 21:21:10 +0200181 G.user = xmalloc_reads(fd, /* maxsize: */ NULL);
182 G.pass = xmalloc_reads(fd, /* maxsize: */ NULL);
Denis Vlasenko239d06b2008-11-06 23:42:42 +0000183 }
Denis Vlasenko021de3f2009-03-04 17:56:00 +0000184 if (!G.user || !*G.user || !G.pass)
James Byrne69374872019-07-02 11:35:03 +0200185 bb_simple_error_msg_and_die("no username or password");
Denis Vlasenko239d06b2008-11-06 23:42:42 +0000186}