aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/applets.h2
-rw-r--r--include/usage.h15
-rw-r--r--networking/sendmail.c130
3 files changed, 89 insertions, 58 deletions
diff --git a/include/applets.h b/include/applets.h
index e7fc3c03c..591d715c8 100644
--- a/include/applets.h
+++ b/include/applets.h
@@ -306,7 +306,7 @@ USE_RX(APPLET(rx, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
306USE_SCRIPT(APPLET(script, _BB_DIR_USR_BIN, _BB_SUID_NEVER)) 306USE_SCRIPT(APPLET(script, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
307USE_SED(APPLET(sed, _BB_DIR_BIN, _BB_SUID_NEVER)) 307USE_SED(APPLET(sed, _BB_DIR_BIN, _BB_SUID_NEVER))
308USE_SELINUXENABLED(APPLET(selinuxenabled, _BB_DIR_USR_SBIN, _BB_SUID_NEVER)) 308USE_SELINUXENABLED(APPLET(selinuxenabled, _BB_DIR_USR_SBIN, _BB_SUID_NEVER))
309USE_SENDMAIL(APPLET_ODDNAME(sendmail, sendgetmail, _BB_DIR_USR_BIN, _BB_SUID_NEVER, sendmail)) 309USE_SENDMAIL(APPLET_ODDNAME(sendmail, sendgetmail, _BB_DIR_USR_SBIN, _BB_SUID_NEVER, sendmail))
310USE_SEQ(APPLET_NOFORK(seq, seq, _BB_DIR_USR_BIN, _BB_SUID_NEVER, seq)) 310USE_SEQ(APPLET_NOFORK(seq, seq, _BB_DIR_USR_BIN, _BB_SUID_NEVER, seq))
311USE_SESTATUS(APPLET(sestatus, _BB_DIR_USR_SBIN, _BB_SUID_NEVER)) 311USE_SESTATUS(APPLET(sestatus, _BB_DIR_USR_SBIN, _BB_SUID_NEVER))
312USE_SETARCH(APPLET(setarch, _BB_DIR_BIN, _BB_SUID_NEVER)) 312USE_SETARCH(APPLET(setarch, _BB_DIR_BIN, _BB_SUID_NEVER))
diff --git a/include/usage.h b/include/usage.h
index df8958060..dd66728be 100644
--- a/include/usage.h
+++ b/include/usage.h
@@ -1088,11 +1088,12 @@
1088 "\n -S SECTORS" \ 1088 "\n -S SECTORS" \
1089 1089
1090#define fetchmail_trivial_usage \ 1090#define fetchmail_trivial_usage \
1091 "[-w timeout] [-U user] -P password [-X] [-t] [-z] server[:port] maildir [prog]" 1091 "[-w timeout] [-H server[:port]] [-U user] -P password [-X] [-t] [-z] maildir [prog]"
1092#define fetchmail_full_usage "\n\n" \ 1092#define fetchmail_full_usage "\n\n" \
1093 "Fetch content of remote mailbox to local Maildir.\n" \ 1093 "Fetch content of remote mailbox to local Maildir.\n" \
1094 "\nOptions:" \ 1094 "\nOptions:" \
1095 "\n -w timeout Set timeout on network operations" \ 1095 "\n -w timeout Set timeout on network operations" \
1096 "\n -H server[:port] Set server" \
1096 "\n -U username Authenticate with specified username/password" \ 1097 "\n -U username Authenticate with specified username/password" \
1097 "\n -P password" \ 1098 "\n -P password" \
1098 "\n -X Use openssl connection helper for secured servers" \ 1099 "\n -X Use openssl connection helper for secured servers" \
@@ -3425,19 +3426,23 @@
3425#define selinuxenabled_full_usage "" 3426#define selinuxenabled_full_usage ""
3426 3427
3427#define sendmail_trivial_usage \ 3428#define sendmail_trivial_usage \
3428 "[-w timeout] [-U user] [-P password] [-X]\n" \ 3429 "[-w timeout] [-H server[:port]] [-U user] [-P password] [-X]\n" \
3429 "-t to [-t to]... [-n] [-s subject] [-c charset] server[:port] from [body] [attachment ...]" 3430 "[-c charset] [-n] [-i] [-s subject] [-a attach]... [-t] [-f sender] [rcpt]..."
3430#define sendmail_full_usage "\n\n" \ 3431#define sendmail_full_usage "\n\n" \
3431 "Send an email.\n" \ 3432 "Send an email.\n" \
3432 "\nOptions:" \ 3433 "\nOptions:" \
3433 "\n -w timeout Set timeout on network operations" \ 3434 "\n -w timeout Set timeout on network operations" \
3435 "\n -H server[:port] Set server" \
3434 "\n -U username Authenticate with specified username/password" \ 3436 "\n -U username Authenticate with specified username/password" \
3435 "\n -P password" \ 3437 "\n -P password" \
3436 "\n -t address Recipient(s). May be repeated" \
3437 "\n -X Use openssl connection helper for secured servers" \ 3438 "\n -X Use openssl connection helper for secured servers" \
3439 "\n -c charset Assumed charset for body and subject [utf-8]" \
3438 "\n -n Request delivery notification to sender" \ 3440 "\n -n Request delivery notification to sender" \
3441 "\n -i Ignore single dots in mail body. Implied" \
3439 "\n -s subject Subject" \ 3442 "\n -s subject Subject" \
3440 "\n -c charset Assumed charset for body and subject [utf-8]" \ 3443 "\n -a file File to attach. May be multiple" \
3444 "\n -t Read recipients and subject from body" \
3445 "\n -f Set sender address" \
3441 3446
3442#define seq_trivial_usage \ 3447#define seq_trivial_usage \
3443 "[first [increment]] last" 3448 "[first [increment]] last"
diff --git a/networking/sendmail.c b/networking/sendmail.c
index 027656dd8..071d9d62d 100644
--- a/networking/sendmail.c
+++ b/networking/sendmail.c
@@ -61,6 +61,8 @@ static void uuencode(char *fname, const char *text)
61 } 61 }
62 if (fname) 62 if (fname)
63 close(fd); 63 close(fd);
64#undef src_buf
65#undef len
64} 66}
65 67
66struct globals { 68struct globals {
@@ -82,7 +84,7 @@ struct globals {
82 xargs[1] = "s_client"; \ 84 xargs[1] = "s_client"; \
83 xargs[2] = "-quiet"; \ 85 xargs[2] = "-quiet"; \
84 xargs[3] = "-connect"; \ 86 xargs[3] = "-connect"; \
85 /*xargs[4] = "server[:port]";*/ \ 87 /*xargs[4] = "localhost";*/ \
86 xargs[5] = "-tls1"; \ 88 xargs[5] = "-tls1"; \
87 xargs[6] = "-starttls"; \ 89 xargs[6] = "-starttls"; \
88 xargs[7] = "smtp"; \ 90 xargs[7] = "smtp"; \
@@ -115,6 +117,16 @@ static void signal_handler(int signo)
115 if (wait_any_nohang(&err) > 0) 117 if (wait_any_nohang(&err) > 0)
116 if (WIFEXITED(err) && WEXITSTATUS(err)) 118 if (WIFEXITED(err) && WEXITSTATUS(err))
117 bb_error_msg_and_die("child exited (%d)", WEXITSTATUS(err)); 119 bb_error_msg_and_die("child exited (%d)", WEXITSTATUS(err));
120#undef err
121}
122
123/* libbb candidate */
124static pid_t vfork_or_die(void)
125{
126 pid_t pid = vfork();
127 if (pid < 0)
128 bb_perror_msg_and_die("vfork");
129 return pid;
118} 130}
119 131
120static void launch_helper(const char **argv) 132static void launch_helper(const char **argv)
@@ -122,12 +134,11 @@ static void launch_helper(const char **argv)
122 // setup vanilla unidirectional pipes interchange 134 // setup vanilla unidirectional pipes interchange
123 int idx; 135 int idx;
124 int pipes[4]; 136 int pipes[4];
137
125 xpipe(pipes); 138 xpipe(pipes);
126 xpipe(pipes+2); 139 xpipe(pipes+2);
127 helper_pid = vfork(); 140 helper_pid = vfork_or_die();
128 if (helper_pid < 0) 141 idx = (!helper_pid) * 2;
129 bb_perror_msg_and_die("vfork");
130 idx = (!helper_pid)*2;
131 xdup2(pipes[idx], STDIN_FILENO); 142 xdup2(pipes[idx], STDIN_FILENO);
132 xdup2(pipes[3-idx], STDOUT_FILENO); 143 xdup2(pipes[3-idx], STDOUT_FILENO);
133 if (ENABLE_FEATURE_CLEAN_UP) 144 if (ENABLE_FEATURE_CLEAN_UP)
@@ -255,29 +266,31 @@ int sendgetmail_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
255int sendgetmail_main(int argc ATTRIBUTE_UNUSED, char **argv) 266int sendgetmail_main(int argc ATTRIBUTE_UNUSED, char **argv)
256{ 267{
257 llist_t *opt_recipients = NULL; 268 llist_t *opt_recipients = NULL;
258 269 llist_t *opt_attachments = NULL;
270 char *opt_from;
259 const char *opt_user; 271 const char *opt_user;
260 const char *opt_pass; 272 const char *opt_pass;
261
262 enum { 273 enum {
263 OPT_w = 1 << 0, // network timeout 274 OPT_w = 1 << 0, // network timeout
264 OPT_U = 1 << 1, // user 275 OPT_H = 1 << 1, // server[:port]
265 OPT_P = 1 << 2, // password 276 OPT_U = 1 << 2, // user
266 OPT_X = 1 << 3, // connect using openssl s_client helper 277 OPT_P = 1 << 3, // password
278 OPT_X = 1 << 4, // connect using openssl s_client helper
267 279
268 OPTS_n = 1 << 4, // sendmail: request notification 280 OPTS_t = 1 << 5, // sendmail: read addresses from body
269 OPTF_t = 1 << 4, // fetchmail: use "TOP" not "RETR" 281 OPTF_t = 1 << 5, // fetchmail: use "TOP" not "RETR"
270 282
271 OPTS_s = 1 << 5, // sendmail: subject 283 OPTS_s = 1 << 6, // sendmail: subject
272 OPTF_z = 1 << 5, // fetchmail: delete from server 284 OPTF_z = 1 << 6, // fetchmail: delete from server
273 285
274 OPTS_c = 1 << 6, // sendmail: assumed charset 286 OPTS_c = 1 << 7, // sendmail: assumed charset
275 OPTS_t = 1 << 7, // sendmail: recipient(s) 287 OPTS_a = 1 << 8, // sendmail: attachment(s)
276 OPTS_i = 1 << 8, // sendmail: ignore lone dots in message body (implied) 288 OPTS_i = 1 << 9, // sendmail: ignore lone dots in message body (implied)
277 };
278 289
290 OPTS_n = 1 << 10, // sendmail: request notification
291 };
279 const char *options; 292 const char *options;
280 unsigned opts; 293 int opts;
281 294
282 // init global variables 295 // init global variables
283 INIT_G(); 296 INIT_G();
@@ -289,25 +302,30 @@ int sendgetmail_main(int argc ATTRIBUTE_UNUSED, char **argv)
289 // SENDMAIL 302 // SENDMAIL
290 // save initial stdin (body or attachements can be piped!) 303 // save initial stdin (body or attachements can be piped!)
291 xdup2(STDIN_FILENO, INITIAL_STDIN_FILENO); 304 xdup2(STDIN_FILENO, INITIAL_STDIN_FILENO);
292 opt_complementary = "-2:w+:t::"; 305 opt_complementary = "w+:a::";
293 options = "w:U:P:X" "ns:c:t:i"; 306 options = "w:H:U:P:Xt" "s:c:a:inf:";
307 // body is pseudo attachment read from stdin
308 llist_add_to_end(&opt_attachments, (char *)"-");
294 } else { 309 } else {
295 // FETCHMAIL 310 // FETCHMAIL
296 opt_after_connect = NULL; 311 opt_after_connect = NULL;
297 opt_complementary = "-2:w+:P"; 312 opt_complementary = "-1:w+:P";
298 options = "w:U:P:X" "tz"; 313 options = "w:H:U:P:Xt" "z";
299 } 314 }
300 opts = getopt32(argv, options, 315 opts = getopt32(argv, options,
301 &timeout, &opt_user, &opt_pass, 316 &timeout, &opt_connect, &opt_user, &opt_pass,
302 &opt_subject, &opt_charset, &opt_recipients 317 &opt_subject, &opt_charset, &opt_attachments, &opt_from
303 ); 318 );
304 //argc -= optind; 319 //argc -= optind;
305 argv += optind; 320 argv += optind;
306 321
307 // first argument is remote server[:port]
308 opt_connect = *argv++;
309
310 // connect to server 322 // connect to server
323 // host[:port] not specified ? -> use $HOST. no $HOST ? -> use localhost
324 if (!(opts & OPT_H)) {
325 opt_connect = getenv("HOST");
326 if (!opt_connect)
327 opt_connect = "127.0.0.1";
328 }
311 // SSL ordered? -> 329 // SSL ordered? ->
312 if (opts & OPT_X) { 330 if (opts & OPT_X) {
313 // ... use openssl helper 331 // ... use openssl helper
@@ -323,20 +341,27 @@ int sendgetmail_main(int argc ATTRIBUTE_UNUSED, char **argv)
323 } 341 }
324 342
325#if ENABLE_FETCHMAIL 343#if ENABLE_FETCHMAIL
326 // we are sendmail? 344 // are we sendmail?
327 if (opt_after_connect) 345 if (opt_after_connect)
328#endif 346#endif
329 {
330/*************************************************** 347/***************************************************
331 * SENDMAIL 348 * SENDMAIL
332 ***************************************************/ 349 ***************************************************/
333 350 {
334 char *opt_from;
335 int code; 351 int code;
336 char *boundary; 352 char *boundary;
337 const char *fmt; 353 const char *fmt;
338 const char *p; 354 const char *p;
339 char *q; 355 char *q;
356 llist_t *l;
357
358 // recipients specified as arguments
359 while (*argv) {
360 // loose test on email address validity
361 if (strchr(sane(*argv), '@'))
362 llist_add_to_end(&opt_recipients, *argv);
363 argv++;
364 }
340 365
341 // we didn't use SSL helper? -> 366 // we didn't use SSL helper? ->
342 if (!(opts & OPT_X)) { 367 if (!(opts & OPT_X)) {
@@ -344,13 +369,13 @@ int sendgetmail_main(int argc ATTRIBUTE_UNUSED, char **argv)
344 smtp_check(NULL, 220); 369 smtp_check(NULL, 220);
345 } 370 }
346 371
347 // get the sender 372 // if -t specified or no recipients specified -> enter all-included mode
348 opt_from = sane(*argv++);
349
350 // if no recipients _and_ no body files specified -> enter all-included mode
351 // i.e. scan stdin for To: and Subject: lines ... 373 // i.e. scan stdin for To: and Subject: lines ...
352 // ... and then use the rest of stdin as message body 374 // ... and then use the rest of stdin as message body
353 if (!opt_recipients && !*argv) { 375 // N.B. subject read from body has priority
376 // over that specified on command line.
377 // recipients are merged
378 if (opts & OPTS_t || !opt_recipients) {
354 // fetch recipients and (optionally) subject 379 // fetch recipients and (optionally) subject
355 char *s; 380 char *s;
356 while ((s = xmalloc_reads(INITIAL_STDIN_FILENO, NULL, NULL)) != NULL) { 381 while ((s = xmalloc_reads(INITIAL_STDIN_FILENO, NULL, NULL)) != NULL) {
@@ -366,13 +391,11 @@ int sendgetmail_main(int argc ATTRIBUTE_UNUSED, char **argv)
366 break; // empty line 391 break; // empty line
367 } 392 }
368 } 393 }
369 // order to read body from stdin
370 *--argv = (char *)"-";
371 } 394 }
372 395
373 // introduce to server 396 // introduce to server
374 // we should start with modern EHLO 397 // we should start with modern EHLO
375 if (250 != smtp_checkp("EHLO %s", opt_from, -1)) { 398 if (250 != smtp_checkp("EHLO %s", sane(opt_from), -1)) {
376 smtp_checkp("HELO %s", opt_from, 250); 399 smtp_checkp("HELO %s", opt_from, 250);
377 } 400 }
378 401
@@ -404,8 +427,8 @@ int sendgetmail_main(int argc ATTRIBUTE_UNUSED, char **argv)
404 } 427 }
405 428
406 // set recipients 429 // set recipients
407 for (llist_t *to = opt_recipients; to; to = to->link) { 430 for (l = opt_recipients; l; l = l->link) {
408 smtp_checkp("RCPT TO:<%s>", sane(to->data), 250); 431 smtp_checkp("RCPT TO:<%s>", sane(l->data), 250);
409 } 432 }
410 433
411 // enter "put message" mode 434 // enter "put message" mode
@@ -413,8 +436,8 @@ int sendgetmail_main(int argc ATTRIBUTE_UNUSED, char **argv)
413 436
414 // put address headers 437 // put address headers
415 printf("From: %s\r\n", opt_from); 438 printf("From: %s\r\n", opt_from);
416 for (llist_t *to = opt_recipients; to; to = to->link) { 439 for (l = opt_recipients; l; l = l->link) {
417 printf("To: %s\r\n", to->data); 440 printf("To: %s\r\n", l->data);
418 } 441 }
419 442
420 // put encoded subject 443 // put encoded subject
@@ -455,7 +478,8 @@ int sendgetmail_main(int argc ATTRIBUTE_UNUSED, char **argv)
455 ; 478 ;
456 p = opt_charset; 479 p = opt_charset;
457 q = (char *)""; 480 q = (char *)"";
458 while (*argv) { 481 l = opt_attachments;
482 while (l) {
459 printf( 483 printf(
460 fmt 484 fmt
461 , boundary 485 , boundary
@@ -472,9 +496,10 @@ int sendgetmail_main(int argc ATTRIBUTE_UNUSED, char **argv)
472 "%s; filename=\"%s\"\r\n" 496 "%s; filename=\"%s\"\r\n"
473 "%s" 497 "%s"
474 ; 498 ;
475 uuencode(*argv, NULL); 499 uuencode(l->data, NULL);
476 if (*(++argv)) 500 l = l->link;
477 q = bb_get_last_path_component_strip(*argv); 501 if (l)
502 q = bb_get_last_path_component_strip(l->data);
478 } 503 }
479 504
480 // put message terminator 505 // put message terminator
@@ -484,12 +509,12 @@ int sendgetmail_main(int argc ATTRIBUTE_UNUSED, char **argv)
484 smtp_check(".", 250); 509 smtp_check(".", 250);
485 // ... and say goodbye 510 // ... and say goodbye
486 smtp_check("QUIT", 221); 511 smtp_check("QUIT", 221);
487 512 }
488#if ENABLE_FETCHMAIL 513#if ENABLE_FETCHMAIL
489 } else {
490/*************************************************** 514/***************************************************
491 * FETCHMAIL 515 * FETCHMAIL
492 ***************************************************/ 516 ***************************************************/
517 else {
493 518
494 char *buf; 519 char *buf;
495 unsigned nmsg; 520 unsigned nmsg;
@@ -570,7 +595,8 @@ int sendgetmail_main(int argc ATTRIBUTE_UNUSED, char **argv)
570 for (; nmsg; nmsg--) { 595 for (; nmsg; nmsg--) {
571 596
572 // generate unique filename 597 // generate unique filename
573 char *filename = xasprintf("tmp/%llu.%u.%s", monotonic_us(), pid, hostname); 598 char *filename = xasprintf("tmp/%llu.%u.%s",
599 monotonic_us(), (unsigned)pid, hostname);
574 char *target; 600 char *target;
575 int rc; 601 int rc;
576 602
@@ -604,8 +630,8 @@ int sendgetmail_main(int argc ATTRIBUTE_UNUSED, char **argv)
604 630
605 // Bye 631 // Bye
606 pop3_check("QUIT", NULL); 632 pop3_check("QUIT", NULL);
607#endif // ENABLE_FETCHMAIL
608 } 633 }
634#endif // ENABLE_FETCHMAIL
609 635
610 return 0; 636 return 0;
611} 637}