From 3dee8e2bac464eb66b14ac42806c8611b6fb6a19 Mon Sep 17 00:00:00 2001 From: Denis Vlasenko Date: Fri, 27 Jun 2008 21:24:08 +0000 Subject: [PATCH] sendmail: update from maintainer --- include/applets.h | 2 +- include/usage.h | 17 ++++-- networking/sendmail.c | 130 +++++++++++++++++++++++++----------------- 3 files changed, 90 insertions(+), 59 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)) USE_SCRIPT(APPLET(script, _BB_DIR_USR_BIN, _BB_SUID_NEVER)) USE_SED(APPLET(sed, _BB_DIR_BIN, _BB_SUID_NEVER)) USE_SELINUXENABLED(APPLET(selinuxenabled, _BB_DIR_USR_SBIN, _BB_SUID_NEVER)) -USE_SENDMAIL(APPLET_ODDNAME(sendmail, sendgetmail, _BB_DIR_USR_BIN, _BB_SUID_NEVER, sendmail)) +USE_SENDMAIL(APPLET_ODDNAME(sendmail, sendgetmail, _BB_DIR_USR_SBIN, _BB_SUID_NEVER, sendmail)) USE_SEQ(APPLET_NOFORK(seq, seq, _BB_DIR_USR_BIN, _BB_SUID_NEVER, seq)) USE_SESTATUS(APPLET(sestatus, _BB_DIR_USR_SBIN, _BB_SUID_NEVER)) USE_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 @@ "\n -S SECTORS" \ #define fetchmail_trivial_usage \ - "[-w timeout] [-U user] -P password [-X] [-t] [-z] server[:port] maildir [prog]" + "[-w timeout] [-H server[:port]] [-U user] -P password [-X] [-t] [-z] maildir [prog]" #define fetchmail_full_usage "\n\n" \ "Fetch content of remote mailbox to local Maildir.\n" \ "\nOptions:" \ "\n -w timeout Set timeout on network operations" \ + "\n -H server[:port] Set server" \ "\n -U username Authenticate with specified username/password" \ "\n -P password" \ "\n -X Use openssl connection helper for secured servers" \ @@ -3425,19 +3426,23 @@ #define selinuxenabled_full_usage "" #define sendmail_trivial_usage \ - "[-w timeout] [-U user] [-P password] [-X]\n" \ - "-t to [-t to]... [-n] [-s subject] [-c charset] server[:port] from [body] [attachment ...]" + "[-w timeout] [-H server[:port]] [-U user] [-P password] [-X]\n" \ + "[-c charset] [-n] [-i] [-s subject] [-a attach]... [-t] [-f sender] [rcpt]..." #define sendmail_full_usage "\n\n" \ "Send an email.\n" \ "\nOptions:" \ "\n -w timeout Set timeout on network operations" \ + "\n -H server[:port] Set server" \ "\n -U username Authenticate with specified username/password" \ "\n -P password" \ - "\n -t address Recipient(s). May be repeated" \ "\n -X Use openssl connection helper for secured servers" \ - "\n -n Request delivery notification to sender" \ - "\n -s subject Subject" \ "\n -c charset Assumed charset for body and subject [utf-8]" \ + "\n -n Request delivery notification to sender" \ + "\n -i Ignore single dots in mail body. Implied" \ + "\n -s subject Subject" \ + "\n -a file File to attach. May be multiple" \ + "\n -t Read recipients and subject from body" \ + "\n -f Set sender address" \ #define seq_trivial_usage \ "[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) } if (fname) close(fd); +#undef src_buf +#undef len } struct globals { @@ -82,7 +84,7 @@ struct globals { xargs[1] = "s_client"; \ xargs[2] = "-quiet"; \ xargs[3] = "-connect"; \ - /*xargs[4] = "server[:port]";*/ \ + /*xargs[4] = "localhost";*/ \ xargs[5] = "-tls1"; \ xargs[6] = "-starttls"; \ xargs[7] = "smtp"; \ @@ -115,6 +117,16 @@ static void signal_handler(int signo) if (wait_any_nohang(&err) > 0) if (WIFEXITED(err) && WEXITSTATUS(err)) bb_error_msg_and_die("child exited (%d)", WEXITSTATUS(err)); +#undef err +} + +/* libbb candidate */ +static pid_t vfork_or_die(void) +{ + pid_t pid = vfork(); + if (pid < 0) + bb_perror_msg_and_die("vfork"); + return pid; } static void launch_helper(const char **argv) @@ -122,12 +134,11 @@ static void launch_helper(const char **argv) // setup vanilla unidirectional pipes interchange int idx; int pipes[4]; + xpipe(pipes); xpipe(pipes+2); - helper_pid = vfork(); - if (helper_pid < 0) - bb_perror_msg_and_die("vfork"); - idx = (!helper_pid)*2; + helper_pid = vfork_or_die(); + idx = (!helper_pid) * 2; xdup2(pipes[idx], STDIN_FILENO); xdup2(pipes[3-idx], STDOUT_FILENO); if (ENABLE_FEATURE_CLEAN_UP) @@ -255,29 +266,31 @@ int sendgetmail_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int sendgetmail_main(int argc ATTRIBUTE_UNUSED, char **argv) { llist_t *opt_recipients = NULL; - + llist_t *opt_attachments = NULL; + char *opt_from; const char *opt_user; const char *opt_pass; - enum { OPT_w = 1 << 0, // network timeout - OPT_U = 1 << 1, // user - OPT_P = 1 << 2, // password - OPT_X = 1 << 3, // connect using openssl s_client helper + OPT_H = 1 << 1, // server[:port] + OPT_U = 1 << 2, // user + OPT_P = 1 << 3, // password + OPT_X = 1 << 4, // connect using openssl s_client helper - OPTS_n = 1 << 4, // sendmail: request notification - OPTF_t = 1 << 4, // fetchmail: use "TOP" not "RETR" + OPTS_t = 1 << 5, // sendmail: read addresses from body + OPTF_t = 1 << 5, // fetchmail: use "TOP" not "RETR" - OPTS_s = 1 << 5, // sendmail: subject - OPTF_z = 1 << 5, // fetchmail: delete from server + OPTS_s = 1 << 6, // sendmail: subject + OPTF_z = 1 << 6, // fetchmail: delete from server - OPTS_c = 1 << 6, // sendmail: assumed charset - OPTS_t = 1 << 7, // sendmail: recipient(s) - OPTS_i = 1 << 8, // sendmail: ignore lone dots in message body (implied) + OPTS_c = 1 << 7, // sendmail: assumed charset + OPTS_a = 1 << 8, // sendmail: attachment(s) + OPTS_i = 1 << 9, // sendmail: ignore lone dots in message body (implied) + + OPTS_n = 1 << 10, // sendmail: request notification }; - const char *options; - unsigned opts; + int opts; // init global variables INIT_G(); @@ -289,25 +302,30 @@ int sendgetmail_main(int argc ATTRIBUTE_UNUSED, char **argv) // SENDMAIL // save initial stdin (body or attachements can be piped!) xdup2(STDIN_FILENO, INITIAL_STDIN_FILENO); - opt_complementary = "-2:w+:t::"; - options = "w:U:P:X" "ns:c:t:i"; + opt_complementary = "w+:a::"; + options = "w:H:U:P:Xt" "s:c:a:inf:"; + // body is pseudo attachment read from stdin + llist_add_to_end(&opt_attachments, (char *)"-"); } else { // FETCHMAIL opt_after_connect = NULL; - opt_complementary = "-2:w+:P"; - options = "w:U:P:X" "tz"; + opt_complementary = "-1:w+:P"; + options = "w:H:U:P:Xt" "z"; } opts = getopt32(argv, options, - &timeout, &opt_user, &opt_pass, - &opt_subject, &opt_charset, &opt_recipients + &timeout, &opt_connect, &opt_user, &opt_pass, + &opt_subject, &opt_charset, &opt_attachments, &opt_from ); //argc -= optind; argv += optind; - // first argument is remote server[:port] - opt_connect = *argv++; - // connect to server + // host[:port] not specified ? -> use $HOST. no $HOST ? -> use localhost + if (!(opts & OPT_H)) { + opt_connect = getenv("HOST"); + if (!opt_connect) + opt_connect = "127.0.0.1"; + } // SSL ordered? -> if (opts & OPT_X) { // ... use openssl helper @@ -323,20 +341,27 @@ int sendgetmail_main(int argc ATTRIBUTE_UNUSED, char **argv) } #if ENABLE_FETCHMAIL - // we are sendmail? + // are we sendmail? if (opt_after_connect) #endif - { /*************************************************** * SENDMAIL ***************************************************/ - - char *opt_from; + { int code; char *boundary; const char *fmt; const char *p; char *q; + llist_t *l; + + // recipients specified as arguments + while (*argv) { + // loose test on email address validity + if (strchr(sane(*argv), '@')) + llist_add_to_end(&opt_recipients, *argv); + argv++; + } // we didn't use SSL helper? -> if (!(opts & OPT_X)) { @@ -344,13 +369,13 @@ int sendgetmail_main(int argc ATTRIBUTE_UNUSED, char **argv) smtp_check(NULL, 220); } - // get the sender - opt_from = sane(*argv++); - - // if no recipients _and_ no body files specified -> enter all-included mode + // if -t specified or no recipients specified -> enter all-included mode // i.e. scan stdin for To: and Subject: lines ... // ... and then use the rest of stdin as message body - if (!opt_recipients && !*argv) { + // N.B. subject read from body has priority + // over that specified on command line. + // recipients are merged + if (opts & OPTS_t || !opt_recipients) { // fetch recipients and (optionally) subject char *s; while ((s = xmalloc_reads(INITIAL_STDIN_FILENO, NULL, NULL)) != NULL) { @@ -366,13 +391,11 @@ int sendgetmail_main(int argc ATTRIBUTE_UNUSED, char **argv) break; // empty line } } - // order to read body from stdin - *--argv = (char *)"-"; } // introduce to server // we should start with modern EHLO - if (250 != smtp_checkp("EHLO %s", opt_from, -1)) { + if (250 != smtp_checkp("EHLO %s", sane(opt_from), -1)) { smtp_checkp("HELO %s", opt_from, 250); } @@ -404,8 +427,8 @@ int sendgetmail_main(int argc ATTRIBUTE_UNUSED, char **argv) } // set recipients - for (llist_t *to = opt_recipients; to; to = to->link) { - smtp_checkp("RCPT TO:<%s>", sane(to->data), 250); + for (l = opt_recipients; l; l = l->link) { + smtp_checkp("RCPT TO:<%s>", sane(l->data), 250); } // enter "put message" mode @@ -413,8 +436,8 @@ int sendgetmail_main(int argc ATTRIBUTE_UNUSED, char **argv) // put address headers printf("From: %s\r\n", opt_from); - for (llist_t *to = opt_recipients; to; to = to->link) { - printf("To: %s\r\n", to->data); + for (l = opt_recipients; l; l = l->link) { + printf("To: %s\r\n", l->data); } // put encoded subject @@ -455,7 +478,8 @@ int sendgetmail_main(int argc ATTRIBUTE_UNUSED, char **argv) ; p = opt_charset; q = (char *)""; - while (*argv) { + l = opt_attachments; + while (l) { printf( fmt , boundary @@ -472,9 +496,10 @@ int sendgetmail_main(int argc ATTRIBUTE_UNUSED, char **argv) "%s; filename=\"%s\"\r\n" "%s" ; - uuencode(*argv, NULL); - if (*(++argv)) - q = bb_get_last_path_component_strip(*argv); + uuencode(l->data, NULL); + l = l->link; + if (l) + q = bb_get_last_path_component_strip(l->data); } // put message terminator @@ -484,12 +509,12 @@ int sendgetmail_main(int argc ATTRIBUTE_UNUSED, char **argv) smtp_check(".", 250); // ... and say goodbye smtp_check("QUIT", 221); - + } #if ENABLE_FETCHMAIL - } else { /*************************************************** * FETCHMAIL ***************************************************/ + else { char *buf; unsigned nmsg; @@ -570,7 +595,8 @@ int sendgetmail_main(int argc ATTRIBUTE_UNUSED, char **argv) for (; nmsg; nmsg--) { // generate unique filename - char *filename = xasprintf("tmp/%llu.%u.%s", monotonic_us(), pid, hostname); + char *filename = xasprintf("tmp/%llu.%u.%s", + monotonic_us(), (unsigned)pid, hostname); char *target; int rc; @@ -604,8 +630,8 @@ int sendgetmail_main(int argc ATTRIBUTE_UNUSED, char **argv) // Bye pop3_check("QUIT", NULL); -#endif // ENABLE_FETCHMAIL } +#endif // ENABLE_FETCHMAIL return 0; }