blob: f48b41bab55c575c0d14e0dc303e611e5befb695 [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 */
Alex Samorukov4455cff2021-01-04 01:18:44 +01009#if defined(__linux__)
10# include <sys/prctl.h>
11# define PRCTL
12#elif defined(__FreeBSD__)
13# include <sys/procctl.h>
14# define PROCCTL
15#endif
Denis Vlasenko239d06b2008-11-06 23:42:42 +000016#include "libbb.h"
17#include "mail.h"
18
Denys Vlasenkob0e7cb42020-12-17 12:51:58 +010019// common signal handler
Denis Vlasenko239d06b2008-11-06 23:42:42 +000020static void signal_handler(int signo)
21{
Denis Vlasenko239d06b2008-11-06 23:42:42 +000022 if (SIGALRM == signo) {
James Byrne69374872019-07-02 11:35:03 +020023 bb_simple_error_msg_and_die("timed out");
Denis Vlasenko239d06b2008-11-06 23:42:42 +000024 }
25
Denys Vlasenkob0e7cb42020-12-17 12:51:58 +010026 // SIGCHLD. reap the zombie if we expect one
27 if (G.helper_pid == 0)
28 return;
29#define status signo
30 if (safe_waitpid(G.helper_pid, &status, WNOHANG) > 0) {
31 G.helper_pid = 0;
32 if (WIFSIGNALED(status))
33 bb_error_msg_and_die("helper killed by signal %u", WTERMSIG(status));
34 if (WIFEXITED(status) && WEXITSTATUS(status) != 0)
35 bb_error_msg_and_die("helper exited (%u)", WEXITSTATUS(status));
Denis Vlasenko021de3f2009-03-04 17:56:00 +000036 }
Denys Vlasenkob0e7cb42020-12-17 12:51:58 +010037#undef status
Denis Vlasenko239d06b2008-11-06 23:42:42 +000038}
39
40void FAST_FUNC launch_helper(const char **argv)
41{
Denys Vlasenkob0e7cb42020-12-17 12:51:58 +010042 pid_t pid;
43 struct fd_pair child_out;
44 struct fd_pair child_in;
Denis Vlasenko239d06b2008-11-06 23:42:42 +000045
Denys Vlasenkob0e7cb42020-12-17 12:51:58 +010046 xpiped_pair(child_out);
47 xpiped_pair(child_in);
Denis Vlasenko021de3f2009-03-04 17:56:00 +000048
Denis Vlasenko47741792009-03-10 16:01:57 +000049 // NB: handler must be installed before vfork
50 bb_signals(0
51 + (1 << SIGCHLD)
52 + (1 << SIGALRM)
53 , signal_handler);
54
Denys Vlasenkocd48f072020-12-17 12:55:22 +010055 fflush_all();
56 pid = xvfork();
Denys Vlasenkob0e7cb42020-12-17 12:51:58 +010057 if (pid == 0) {
Denys Vlasenkoe440b392017-08-16 17:45:32 +020058 // child
Denys Vlasenkob0e7cb42020-12-17 12:51:58 +010059 close(child_in.wr);
60 close(child_out.rd);
61 xmove_fd(child_in.rd, STDIN_FILENO);
62 xmove_fd(child_out.wr, STDOUT_FILENO);
Denys Vlasenkoe440b392017-08-16 17:45:32 +020063 // if parent dies, get SIGTERM
Alex Samorukov4455cff2021-01-04 01:18:44 +010064#if defined(PRCTL)
Denys Vlasenkoe440b392017-08-16 17:45:32 +020065 prctl(PR_SET_PDEATHSIG, SIGTERM, 0, 0, 0);
Alex Samorukov4455cff2021-01-04 01:18:44 +010066#elif defined(PROCCTL)
67 {
68 int signum = SIGTERM;
69 procctl(P_PID, 0, PROC_PDEATHSIG_CTL, &signum);
70 }
71#endif
Denys Vlasenkoe440b392017-08-16 17:45:32 +020072 // try to execute connection helper
Denis Vlasenko47741792009-03-10 16:01:57 +000073 // NB: SIGCHLD & SIGALRM revert to SIG_DFL on exec
Pascal Bellard21e8e8d2010-07-04 00:57:03 +020074 BB_EXECVP_or_die((char**)argv);
Denis Vlasenko239d06b2008-11-06 23:42:42 +000075 }
Denys Vlasenkocd48f072020-12-17 12:55:22 +010076 G.helper_pid = pid;
Denys Vlasenkob0e7cb42020-12-17 12:51:58 +010077 close(child_out.wr);
78 close(child_in.rd);
79 xmove_fd(child_out.rd, STDIN_FILENO);
80 xmove_fd(child_in.wr, STDOUT_FILENO);
Denis Vlasenko021de3f2009-03-04 17:56:00 +000081
Denys Vlasenkoe440b392017-08-16 17:45:32 +020082 // parent goes on
Denis Vlasenko239d06b2008-11-06 23:42:42 +000083}
84
Denys Vlasenkob6237c02020-12-17 12:34:25 +010085void FAST_FUNC send_r_n(const char *s)
86{
87 if (G.verbose)
88 bb_error_msg("send:'%s'", s);
89 printf("%s\r\n", s);
90}
91
Denys Vlasenko5707b522010-12-20 05:12:39 +010092char* FAST_FUNC send_mail_command(const char *fmt, const char *param)
Denis Vlasenko239d06b2008-11-06 23:42:42 +000093{
Denys Vlasenko5707b522010-12-20 05:12:39 +010094 char *msg;
Denys Vlasenko25b26802020-12-17 12:24:50 +010095 if (G.timeout)
96 alarm(G.timeout);
Denys Vlasenko5707b522010-12-20 05:12:39 +010097 msg = (char*)fmt;
98 if (fmt) {
Denis Vlasenko239d06b2008-11-06 23:42:42 +000099 msg = xasprintf(fmt, param);
Denys Vlasenkob6237c02020-12-17 12:34:25 +0100100 send_r_n(msg);
Denis Vlasenko239d06b2008-11-06 23:42:42 +0000101 }
Denys Vlasenko8131eea2009-11-02 14:19:51 +0100102 fflush_all();
Denis Vlasenko239d06b2008-11-06 23:42:42 +0000103 return msg;
104}
105
106// NB: parse_url can modify url[] (despite const), but only if '@' is there
107/*
Denys Vlasenko5707b522010-12-20 05:12:39 +0100108static char* FAST_FUNC parse_url(char *url, char **user, char **pass)
Denis Vlasenko239d06b2008-11-06 23:42:42 +0000109{
110 // parse [user[:pass]@]host
111 // return host
112 char *s = strchr(url, '@');
113 *user = *pass = NULL;
114 if (s) {
115 *s++ = '\0';
116 *user = url;
117 url = s;
118 s = strchr(*user, ':');
119 if (s) {
120 *s++ = '\0';
121 *pass = s;
122 }
123 }
124 return url;
125}
126*/
127
Denys Vlasenko8d634a02018-07-31 17:30:08 +0200128static void encode_n_base64(const char *fname, const char *text, size_t len)
Raffaello D. Di Napolif28b8852018-06-26 19:17:45 -0400129{
Denis Vlasenko239d06b2008-11-06 23:42:42 +0000130 enum {
Denys Vlasenko41fea012011-11-18 22:25:35 +0100131 SRC_BUF_SIZE = 57, /* This *MUST* be a multiple of 3 */
Denis Vlasenko239d06b2008-11-06 23:42:42 +0000132 DST_BUF_SIZE = 4 * ((SRC_BUF_SIZE + 2) / 3),
133 };
Denis Vlasenko239d06b2008-11-06 23:42:42 +0000134#define src_buf text
Denys Vlasenkoc8f9a8d2010-09-16 18:10:04 +0200135 char src[SRC_BUF_SIZE];
Denis Vlasenko239d06b2008-11-06 23:42:42 +0000136 FILE *fp = fp;
Denis Vlasenko239d06b2008-11-06 23:42:42 +0000137 char dst_buf[DST_BUF_SIZE + 1];
138
139 if (fname) {
Denys Vlasenko8d634a02018-07-31 17:30:08 +0200140 fp = (NOT_LONE_DASH(fname)) ? xfopen_for_read(fname) : stdin;
Denys Vlasenkoc8f9a8d2010-09-16 18:10:04 +0200141 src_buf = src;
Denys Vlasenko8d634a02018-07-31 17:30:08 +0200142 }
Denis Vlasenko239d06b2008-11-06 23:42:42 +0000143
144 while (1) {
145 size_t size;
146 if (fname) {
147 size = fread((char *)src_buf, 1, SRC_BUF_SIZE, fp);
148 if ((ssize_t)size < 0)
James Byrne69374872019-07-02 11:35:03 +0200149 bb_simple_perror_msg_and_die(bb_msg_read_error);
Denis Vlasenko239d06b2008-11-06 23:42:42 +0000150 } else {
151 size = len;
152 if (len > SRC_BUF_SIZE)
153 size = SRC_BUF_SIZE;
154 }
155 if (!size)
156 break;
157 // encode the buffer we just read in
158 bb_uuencode(dst_buf, src_buf, size, bb_uuenc_tbl_base64);
159 if (fname) {
Denys Vlasenko8d634a02018-07-31 17:30:08 +0200160 puts("");
Denis Vlasenko239d06b2008-11-06 23:42:42 +0000161 } else {
162 src_buf += size;
163 len -= size;
164 }
165 fwrite(dst_buf, 1, 4 * ((size + 2) / 3), stdout);
166 }
167 if (fname && NOT_LONE_DASH(fname))
168 fclose(fp);
169#undef src_buf
170}
171
Denys Vlasenko8d634a02018-07-31 17:30:08 +0200172void FAST_FUNC printstr_base64(const char *text)
173{
174 encode_n_base64(NULL, text, strlen(text));
175}
176
177void FAST_FUNC printbuf_base64(const char *text, unsigned len)
178{
179 encode_n_base64(NULL, text, len);
180}
181
182void FAST_FUNC printfile_base64(const char *fname)
183{
184 encode_n_base64(fname, NULL, 0);
185}
186
Denis Vlasenko239d06b2008-11-06 23:42:42 +0000187/*
188 * get username and password from a file descriptor
189 */
190void FAST_FUNC get_cred_or_die(int fd)
191{
Denis Vlasenko239d06b2008-11-06 23:42:42 +0000192 if (isatty(fd)) {
Denys Vlasenko17058a02018-04-07 15:50:30 +0200193 G.user = bb_ask_noecho(fd, /* timeout: */ 0, "User: ");
194 G.pass = bb_ask_noecho(fd, /* timeout: */ 0, "Password: ");
Denis Vlasenko239d06b2008-11-06 23:42:42 +0000195 } else {
Denys Vlasenko80c5b682011-05-08 21:21:10 +0200196 G.user = xmalloc_reads(fd, /* maxsize: */ NULL);
197 G.pass = xmalloc_reads(fd, /* maxsize: */ NULL);
Denis Vlasenko239d06b2008-11-06 23:42:42 +0000198 }
Denis Vlasenko021de3f2009-03-04 17:56:00 +0000199 if (!G.user || !*G.user || !G.pass)
James Byrne69374872019-07-02 11:35:03 +0200200 bb_simple_error_msg_and_die("no username or password");
Denis Vlasenko239d06b2008-11-06 23:42:42 +0000201}