blob: 61e5053bc7515726e7f2734457818a67e5eb5182 [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 Vlasenkocd48f072020-12-17 12:55:22 +010049 fflush_all();
50 pid = xvfork();
Denys Vlasenkob0e7cb42020-12-17 12:51:58 +010051 if (pid == 0) {
Denys Vlasenkoe440b392017-08-16 17:45:32 +020052 // child
Denys Vlasenkob0e7cb42020-12-17 12:51:58 +010053 close(child_in.wr);
54 close(child_out.rd);
55 xmove_fd(child_in.rd, STDIN_FILENO);
56 xmove_fd(child_out.wr, STDOUT_FILENO);
Denys Vlasenkoe440b392017-08-16 17:45:32 +020057 // if parent dies, get SIGTERM
58 prctl(PR_SET_PDEATHSIG, SIGTERM, 0, 0, 0);
59 // try to execute connection helper
Denis Vlasenko47741792009-03-10 16:01:57 +000060 // NB: SIGCHLD & SIGALRM revert to SIG_DFL on exec
Pascal Bellard21e8e8d2010-07-04 00:57:03 +020061 BB_EXECVP_or_die((char**)argv);
Denis Vlasenko239d06b2008-11-06 23:42:42 +000062 }
Denys Vlasenkocd48f072020-12-17 12:55:22 +010063 G.helper_pid = pid;
Denys Vlasenkob0e7cb42020-12-17 12:51:58 +010064 close(child_out.wr);
65 close(child_in.rd);
66 xmove_fd(child_out.rd, STDIN_FILENO);
67 xmove_fd(child_in.wr, STDOUT_FILENO);
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}