[T106][ZXW-22]7520V3SCV2.01.01.02P42U09_VEC_V0.8_AP_VEC origin source commit

Change-Id: Ic6e05d89ecd62fc34f82b23dcf306c93764aec4b
diff --git a/ap/app/busybox/src/mailutils/Config.src b/ap/app/busybox/src/mailutils/Config.src
new file mode 100644
index 0000000..2a9c5c0
--- /dev/null
+++ b/ap/app/busybox/src/mailutils/Config.src
@@ -0,0 +1,55 @@
+menu "Mail Utilities"
+
+INSERT
+
+config MAKEMIME
+	bool "makemime"
+	default y
+	help
+	  Create MIME-formatted messages.
+
+config FEATURE_MIME_CHARSET
+	string "Default charset"
+	default "us-ascii"
+	depends on MAKEMIME || REFORMIME || SENDMAIL
+	help
+	  Default charset of the message.
+
+config POPMAILDIR
+	bool "popmaildir"
+	default y
+	help
+	  Simple yet powerful POP3 mail popper. Delivers content
+	  of remote mailboxes to local Maildir.
+
+config FEATURE_POPMAILDIR_DELIVERY
+	bool "Allow message filters and custom delivery program"
+	default y
+	depends on POPMAILDIR
+	help
+	  Allow to use a custom program to filter the content
+	  of the message before actual delivery (-F "prog [args...]").
+	  Allow to use a custom program for message actual delivery
+	  (-M "prog [args...]").
+
+config REFORMIME
+	bool "reformime"
+	default y
+	help
+	  Parse MIME-formatted messages.
+
+config FEATURE_REFORMIME_COMPAT
+	bool "Accept and ignore options other than -x and -X"
+	default y
+	depends on REFORMIME
+	help
+	  Accept (for compatibility only) and ignore options
+	  other than -x and -X.
+
+config SENDMAIL
+	bool "sendmail"
+	default y
+	help
+	  Barebones sendmail.
+
+endmenu
diff --git a/ap/app/busybox/src/mailutils/Kbuild.src b/ap/app/busybox/src/mailutils/Kbuild.src
new file mode 100644
index 0000000..6b4fb74
--- /dev/null
+++ b/ap/app/busybox/src/mailutils/Kbuild.src
@@ -0,0 +1,9 @@
+# Makefile for busybox
+#
+# Copyright (C) 1999-2005 by Erik Andersen <andersen@codepoet.org>
+#
+# Licensed under GPLv2, see file LICENSE in this source tree.
+
+lib-y:=
+
+INSERT
diff --git a/ap/app/busybox/src/mailutils/mail.c b/ap/app/busybox/src/mailutils/mail.c
new file mode 100644
index 0000000..199f644
--- /dev/null
+++ b/ap/app/busybox/src/mailutils/mail.c
@@ -0,0 +1,183 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * helper routines
+ *
+ * Copyright (C) 2008 by Vladimir Dronnikov <dronnikov@gmail.com>
+ *
+ * Licensed under GPLv2, see file LICENSE in this source tree.
+ */
+#include "libbb.h"
+#include "mail.h"
+
+static void kill_helper(void)
+{
+	if (G.helper_pid > 0) {
+		kill(G.helper_pid, SIGTERM);
+		G.helper_pid = 0;
+	}
+}
+
+// generic signal handler
+static void signal_handler(int signo)
+{
+#define err signo
+	if (SIGALRM == signo) {
+		kill_helper();
+		bb_error_msg_and_die("timed out");
+	}
+
+	// SIGCHLD. reap zombies
+	if (safe_waitpid(G.helper_pid, &err, WNOHANG) > 0) {
+		if (WIFSIGNALED(err))
+			bb_error_msg_and_die("helper killed by signal %u", WTERMSIG(err));
+		if (WIFEXITED(err)) {
+			G.helper_pid = 0;
+			if (WEXITSTATUS(err))
+				bb_error_msg_and_die("helper exited (%u)", WEXITSTATUS(err));
+		}
+	}
+#undef err
+}
+
+void FAST_FUNC launch_helper(const char **argv)
+{
+	// setup vanilla unidirectional pipes interchange
+	int i;
+	int pipes[4];
+
+	xpipe(pipes);
+	xpipe(pipes + 2);
+
+	// NB: handler must be installed before vfork
+	bb_signals(0
+		+ (1 << SIGCHLD)
+		+ (1 << SIGALRM)
+		, signal_handler);
+
+	G.helper_pid = xvfork();
+
+	i = (!G.helper_pid) * 2; // for parent:0, for child:2
+	close(pipes[i + 1]);     // 1 or 3 - closing one write end
+	close(pipes[2 - i]);     // 2 or 0 - closing one read end
+	xmove_fd(pipes[i], STDIN_FILENO);      // 0 or 2 - using other read end
+	xmove_fd(pipes[3 - i], STDOUT_FILENO); // 3 or 1 - using other write end
+	// End result:
+	// parent stdout [3] -> child stdin [2]
+	// child stdout [1] -> parent stdin [0]
+
+	if (!G.helper_pid) {
+		// child: try to execute connection helper
+		// NB: SIGCHLD & SIGALRM revert to SIG_DFL on exec
+		BB_EXECVP_or_die((char**)argv);
+	}
+
+	// parent
+	// check whether child is alive
+	//redundant:signal_handler(SIGCHLD);
+	// child seems OK -> parent goes on
+	atexit(kill_helper);
+}
+
+char* FAST_FUNC send_mail_command(const char *fmt, const char *param)
+{
+	char *msg;
+	if (timeout)
+		alarm(timeout);
+	msg = (char*)fmt;
+	if (fmt) {
+		msg = xasprintf(fmt, param);
+		if (verbose)
+			bb_error_msg("send:'%s'", msg);
+		printf("%s\r\n", msg);
+	}
+	fflush_all();
+	return msg;
+}
+
+// NB: parse_url can modify url[] (despite const), but only if '@' is there
+/*
+static char* FAST_FUNC parse_url(char *url, char **user, char **pass)
+{
+	// parse [user[:pass]@]host
+	// return host
+	char *s = strchr(url, '@');
+	*user = *pass = NULL;
+	if (s) {
+		*s++ = '\0';
+		*user = url;
+		url = s;
+		s = strchr(*user, ':');
+		if (s) {
+			*s++ = '\0';
+			*pass = s;
+		}
+	}
+	return url;
+}
+*/
+
+void FAST_FUNC encode_base64(char *fname, const char *text, const char *eol)
+{
+	enum {
+		SRC_BUF_SIZE = 57,  /* This *MUST* be a multiple of 3 */
+		DST_BUF_SIZE = 4 * ((SRC_BUF_SIZE + 2) / 3),
+	};
+#define src_buf text
+	char src[SRC_BUF_SIZE];
+	FILE *fp = fp;
+	ssize_t len = len;
+	char dst_buf[DST_BUF_SIZE + 1];
+
+	if (fname) {
+		fp = (NOT_LONE_DASH(fname)) ? xfopen_for_read(fname) : (FILE *)text;
+		src_buf = src;
+	} else if (text) {
+		// though we do not call uuencode(NULL, NULL) explicitly
+		// still we do not want to break things suddenly
+		len = strlen(text);
+	} else
+		return;
+
+	while (1) {
+		size_t size;
+		if (fname) {
+			size = fread((char *)src_buf, 1, SRC_BUF_SIZE, fp);
+			if ((ssize_t)size < 0)
+				bb_perror_msg_and_die(bb_msg_read_error);
+		} else {
+			size = len;
+			if (len > SRC_BUF_SIZE)
+				size = SRC_BUF_SIZE;
+		}
+		if (!size)
+			break;
+		// encode the buffer we just read in
+		bb_uuencode(dst_buf, src_buf, size, bb_uuenc_tbl_base64);
+		if (fname) {
+			printf("%s\n", eol);
+		} else {
+			src_buf += size;
+			len -= size;
+		}
+		fwrite(dst_buf, 1, 4 * ((size + 2) / 3), stdout);
+	}
+	if (fname && NOT_LONE_DASH(fname))
+		fclose(fp);
+#undef src_buf
+}
+
+/*
+ * get username and password from a file descriptor
+ */
+void FAST_FUNC get_cred_or_die(int fd)
+{
+	if (isatty(fd)) {
+		G.user = xstrdup(bb_ask(fd, /* timeout: */ 0, "User: "));
+		G.pass = xstrdup(bb_ask(fd, /* timeout: */ 0, "Password: "));
+	} else {
+		G.user = xmalloc_reads(fd, /* maxsize: */ NULL);
+		G.pass = xmalloc_reads(fd, /* maxsize: */ NULL);
+	}
+	if (!G.user || !*G.user || !G.pass)
+		bb_error_msg_and_die("no username or password");
+}
diff --git a/ap/app/busybox/src/mailutils/mail.h b/ap/app/busybox/src/mailutils/mail.h
new file mode 100644
index 0000000..fa0c5b3
--- /dev/null
+++ b/ap/app/busybox/src/mailutils/mail.h
@@ -0,0 +1,37 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * helper routines
+ *
+ * Copyright (C) 2008 by Vladimir Dronnikov <dronnikov@gmail.com>
+ *
+ * Licensed under GPLv2, see file LICENSE in this source tree.
+ */
+
+struct globals {
+	pid_t helper_pid;
+	unsigned timeout;
+	unsigned verbose;
+	unsigned opts;
+	char *user;
+	char *pass;
+	FILE *fp0; // initial stdin
+	char *opt_charset;
+};
+
+#define G (*ptr_to_globals)
+#define timeout         (G.timeout  )
+#define verbose         (G.verbose  )
+#define opts            (G.opts     )
+#define INIT_G() do { \
+	SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \
+	G.opt_charset = (char *)CONFIG_FEATURE_MIME_CHARSET; \
+} while (0)
+
+//char FAST_FUNC *parse_url(char *url, char **user, char **pass);
+
+void launch_helper(const char **argv) FAST_FUNC;
+void get_cred_or_die(int fd) FAST_FUNC;
+
+char *send_mail_command(const char *fmt, const char *param) FAST_FUNC;
+
+void encode_base64(char *fname, const char *text, const char *eol) FAST_FUNC;
diff --git a/ap/app/busybox/src/mailutils/makemime.c b/ap/app/busybox/src/mailutils/makemime.c
new file mode 100644
index 0000000..1dadd71
--- /dev/null
+++ b/ap/app/busybox/src/mailutils/makemime.c
@@ -0,0 +1,239 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * makemime: create MIME-encoded message
+ *
+ * Copyright (C) 2008 by Vladimir Dronnikov <dronnikov@gmail.com>
+ *
+ * Licensed under GPLv2, see file LICENSE in this source tree.
+ */
+
+//kbuild:lib-$(CONFIG_MAKEMIME) += makemime.o mail.o
+
+#include "libbb.h"
+#include "mail.h"
+
+#if 0
+# define dbg_error_msg(...) bb_error_msg(__VA_ARGS__)
+#else
+# define dbg_error_msg(...) ((void)0)
+#endif
+
+/*
+  makemime -c type [-o file] [-e encoding] [-C charset] [-N name] \
+                   [-a "Header: Contents"] file
+           -m [ type ] [-o file] [-e encoding] [-a "Header: Contents"] file
+           -j [-o file] file1 file2
+           @file
+
+   file:  filename    - read or write from filename
+          -           - read or write from stdin or stdout
+          &n          - read or write from file descriptor n
+          \( opts \)  - read from child process, that generates [ opts ]
+
+Options:
+  -c type         - create a new MIME section from "file" with this
+                    Content-Type: (default is application/octet-stream).
+  -C charset      - MIME charset of a new text/plain section.
+  -N name         - MIME content name of the new mime section.
+  -m [ type ]     - create a multipart mime section from "file" of this
+                    Content-Type: (default is multipart/mixed).
+  -e encoding     - use the given encoding (7bit, 8bit, quoted-printable,
+                    or base64), instead of guessing.  Omit "-e" and use
+                    -c auto to set Content-Type: to text/plain or
+                    application/octet-stream based on picked encoding.
+  -j file1 file2  - join mime section file2 to multipart section file1.
+  -o file         - write the result to file, instead of stdout (not
+                    allowed in child processes).
+  -a header       - prepend an additional header to the output.
+
+  @file - read all of the above options from file, one option or
+          value on each line.
+  {which version of makemime is this? What do we support?}
+*/
+/* man makemime:
+
+ * -c TYPE: create a (non-multipart) MIME section with Content-Type: TYPE
+ * makemime -c TYPE [-e ENCODING] [-o OUTFILE] [-C CHARSET] [-N NAME] [-a HEADER...] FILE
+ * The -C option sets the MIME charset attribute for text/plain content.
+ * The -N option sets the name attribute for Content-Type:
+ * Encoding must be one of the following: 7bit, 8bit, quoted-printable, or base64.
+
+ * -m multipart/TYPE: create a multipart MIME collection with Content-Type: multipart/TYPE
+ * makemime -m multipart/TYPE [-e ENCODING] [-o OUTFILE] [-a HEADER...] FILE
+ * Type must be either "multipart/mixed", "multipart/alternative", or some other MIME multipart content type.
+ * Additionally, encoding can only be "7bit" or "8bit", and will default to "8bit" if not specified.
+ * Finally, filename must be a MIME-formatted section, NOT a regular file.
+ * The -m option creates an initial multipart MIME collection, that contains only one MIME section, taken from filename.
+ * The collection is written to standard output, or the pipe or to outputfile.
+
+ * -j FILE1: add a section to a multipart MIME collection
+ * makemime -j FILE1 [-o OUTFILE] FILE2
+ * FILE1 must be a MIME collection that was previously created by the -m option.
+ * FILE2 must be a MIME section that was previously created by the -c option.
+ * The -j options adds the MIME section in FILE2 to the MIME collection in FILE1.
+ */
+
+
+/* In busybox 1.15.0.svn, makemime generates output like this
+ * (empty lines are shown exactly!):
+{headers added with -a HDR}
+Mime-Version: 1.0
+Content-Type: multipart/mixed; boundary="24269534-2145583448-1655890676"
+
+--24269534-2145583448-1655890676
+Content-Type: {set by -c, e.g. text/plain}; charset={set by -C, e.g. us-ascii}
+Content-Disposition: inline; filename="A"
+Content-Transfer-Encoding: base64
+
+...file A contents...
+--24269534-2145583448-1655890676
+Content-Type: {set by -c, e.g. text/plain}; charset={set by -C, e.g. us-ascii}
+Content-Disposition: inline; filename="B"
+Content-Transfer-Encoding: base64
+
+...file B contents...
+--24269534-2145583448-1655890676--
+
+ *
+ * For reference: here is an example email to LKML which has
+ * 1st unnamed part (so it serves as an email body)
+ * and one attached file:
+...other headers...
+Content-Type: multipart/mixed; boundary="=-tOfTf3byOS0vZgxEWcX+"
+...other headers...
+Mime-Version: 1.0
+...other headers...
+
+
+--=-tOfTf3byOS0vZgxEWcX+
+Content-Type: text/plain
+Content-Transfer-Encoding: 7bit
+
+...email text...
+...email text...
+
+
+--=-tOfTf3byOS0vZgxEWcX+
+Content-Disposition: attachment; filename="xyz"
+Content-Type: text/plain; name="xyz"; charset="UTF-8"
+Content-Transfer-Encoding: 7bit
+
+...file contents...
+...file contents...
+
+--=-tOfTf3byOS0vZgxEWcX+--
+
+...random junk added by mailing list robots and such...
+*/
+
+//usage:#define makemime_trivial_usage
+//usage:       "[OPTIONS] [FILE]..."
+//usage:#define makemime_full_usage "\n\n"
+//usage:       "Create multipart MIME-encoded message from FILEs\n"
+/* //usage:    "Transfer encoding is base64, disposition is inline (not attachment)\n" */
+//usage:     "\n	-o FILE	Output. Default: stdout"
+//usage:     "\n	-a HDR	Add header(s). Examples:"
+//usage:     "\n		\"From: user@host.org\", \"Date: `date -R`\""
+//usage:     "\n	-c CT	Content type. Default: application/octet-stream"
+//usage:     "\n	-C CS	Charset. Default: " CONFIG_FEATURE_MIME_CHARSET
+/* //usage:  "\n	-e ENC	Transfer encoding. Ignored. base64 is assumed" */
+//usage:     "\n"
+//usage:     "\nOther options are silently ignored"
+
+/*
+ * -c [Content-Type] should create just one MIME section
+ * with "Content-Type:", "Content-Transfer-Encoding:", and HDRs from "-a HDR".
+ * NB: without "Content-Disposition:" auto-added, unlike we do now
+ * NB2: -c has *optional* param which nevertheless _can_ be specified after a space :(
+ *
+ * -m [multipart/mixed] should create multipart MIME section
+ * with "Content-Type:", "Content-Transfer-Encoding:", and HDRs from "-a HDR",
+ * and add FILE to it _verbatim_:
+ *  HEADERS
+ *
+ *  --=_1_1321709112_1605
+ *  FILE_CONTENTS
+ *  --=_1_1321709112_1605
+ * without any encoding of FILE_CONTENTS. (Basically, it expects that FILE
+ * is the result of "makemime -c").
+ *
+ * -j MULTIPART_FILE1 SINGLE_FILE2 should output MULTIPART_FILE1 + SINGLE_FILE2
+ *
+ * Our current behavior is a mutant "-m + -c + -j" one: we create multipart MIME
+ * and we put "-c" encoded FILEs into many multipart sections.
+ */
+
+int makemime_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
+int makemime_main(int argc UNUSED_PARAM, char **argv)
+{
+	llist_t *opt_headers = NULL, *l;
+	const char *opt_output;
+	const char *content_type = "application/octet-stream";
+#define boundary opt_output
+	enum {
+		OPT_c = 1 << 0,         // create (non-multipart) section
+		OPT_e = 1 << 1,         // Content-Transfer-Encoding. Ignored. Assumed base64
+		OPT_o = 1 << 2,         // output to
+		OPT_C = 1 << 3,         // charset
+		OPT_N = 1 << 4,         // COMPAT
+		OPT_a = 1 << 5,         // additional headers
+		//OPT_m = 1 << 6,         // create mutipart section
+		//OPT_j = 1 << 7,         // join section to multipart section
+	};
+
+	INIT_G();
+
+	// parse options
+	opt_complementary = "a::";
+	opts = getopt32(argv,
+		"c:e:o:C:N:a:", // "m:j:",
+		&content_type, NULL, &opt_output, &G.opt_charset, NULL, &opt_headers //, NULL, NULL
+	);
+	//argc -= optind;
+	argv += optind;
+
+	// respect -o output
+	if (opts & OPT_o)
+		freopen(opt_output, "w", stdout);
+
+	// no files given on command line? -> use stdin
+	if (!*argv)
+		*--argv = (char *)"-";
+
+	// put additional headers
+	for (l = opt_headers; l; l = l->link)
+		puts(l->data);
+
+	// make a random string -- it will delimit message parts
+	srand(monotonic_us());
+	boundary = xasprintf("%u-%u-%u",
+			(unsigned)rand(), (unsigned)rand(), (unsigned)rand());
+
+	// put multipart header
+	printf(
+		"Mime-Version: 1.0\n"
+		"Content-Type: multipart/mixed; boundary=\"%s\"\n"
+		, boundary
+	);
+
+	// put attachments
+	while (*argv) {
+		printf(
+			"\n--%s\n"
+			"Content-Type: %s; charset=%s\n"
+			"Content-Disposition: inline; filename=\"%s\"\n"
+			"Content-Transfer-Encoding: base64\n"
+			, boundary
+			, content_type
+			, G.opt_charset
+			, bb_get_last_path_component_strip(*argv)
+		);
+		encode_base64(*argv++, (const char *)stdin, "");
+	}
+
+	// put multipart footer
+	printf("\n--%s--\n" "\n", boundary);
+
+	return EXIT_SUCCESS;
+#undef boundary
+}
diff --git a/ap/app/busybox/src/mailutils/popmaildir.c b/ap/app/busybox/src/mailutils/popmaildir.c
new file mode 100644
index 0000000..6203033
--- /dev/null
+++ b/ap/app/busybox/src/mailutils/popmaildir.c
@@ -0,0 +1,271 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * popmaildir: a simple yet powerful POP3 client
+ * Delivers contents of remote mailboxes to local Maildir
+ *
+ * Inspired by original utility by Nikola Vladov
+ *
+ * Copyright (C) 2008 by Vladimir Dronnikov <dronnikov@gmail.com>
+ *
+ * Licensed under GPLv2, see file LICENSE in this source tree.
+ */
+
+//kbuild:lib-$(CONFIG_POPMAILDIR) += popmaildir.o mail.o
+
+//usage:#define popmaildir_trivial_usage
+//usage:       "[OPTIONS] MAILDIR [CONN_HELPER ARGS]"
+//usage:#define popmaildir_full_usage "\n\n"
+//usage:       "Fetch content of remote mailbox to local maildir\n"
+/* //usage:  "\n	-b		Binary mode. Ignored" */
+/* //usage:  "\n	-d		Debug. Ignored" */
+/* //usage:  "\n	-m		Show used memory. Ignored" */
+/* //usage:  "\n	-V		Show version. Ignored" */
+/* //usage:  "\n	-c		Use tcpclient. Ignored" */
+/* //usage:  "\n	-a		Use APOP protocol. Implied. If server supports APOP -> use it" */
+//usage:     "\n	-s		Skip authorization"
+//usage:     "\n	-T		Get messages with TOP instead of RETR"
+//usage:     "\n	-k		Keep retrieved messages on the server"
+//usage:     "\n	-t SEC		Network timeout"
+//usage:	IF_FEATURE_POPMAILDIR_DELIVERY(
+//usage:     "\n	-F \"PROG ARGS\"	Filter program (may be repeated)"
+//usage:     "\n	-M \"PROG ARGS\"	Delivery program"
+//usage:	)
+//usage:     "\n"
+//usage:     "\nFetch from plain POP3 server:"
+//usage:     "\npopmaildir -k DIR nc pop3.server.com 110 <user_and_pass.txt"
+//usage:     "\nFetch from SSLed POP3 server and delete fetched emails:"
+//usage:     "\npopmaildir DIR -- openssl s_client -quiet -connect pop3.server.com:995 <user_and_pass.txt"
+/* //usage:  "\n	-R BYTES	Remove old messages on the server >= BYTES. Ignored" */
+/* //usage:  "\n	-Z N1-N2	Remove messages from N1 to N2 (dangerous). Ignored" */
+/* //usage:  "\n	-L BYTES	Don't retrieve new messages >= BYTES. Ignored" */
+/* //usage:  "\n	-H LINES	Type first LINES of a message. Ignored" */
+//usage:
+//usage:#define popmaildir_example_usage
+//usage:       "$ popmaildir -k ~/Maildir -- nc pop.drvv.ru 110 [<password_file]\n"
+//usage:       "$ popmaildir ~/Maildir -- openssl s_client -quiet -connect pop.gmail.com:995 [<password_file]\n"
+
+#include "libbb.h"
+#include "mail.h"
+
+static void pop3_checkr(const char *fmt, const char *param, char **ret)
+{
+	char *msg = send_mail_command(fmt, param);
+	char *answer = xmalloc_fgetline(stdin);
+	if (answer && '+' == answer[0]) {
+		free(msg);
+		if (timeout)
+			alarm(0);
+		if (ret) {
+			// skip "+OK "
+			memmove(answer, answer + 4, strlen(answer) - 4);
+			*ret = answer;
+		} else
+			free(answer);
+		return;
+	}
+	bb_error_msg_and_die("%s failed, reply was: %s", msg, answer);
+}
+
+static void pop3_check(const char *fmt, const char *param)
+{
+	pop3_checkr(fmt, param, NULL);
+}
+
+int popmaildir_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
+int popmaildir_main(int argc UNUSED_PARAM, char **argv)
+{
+	char *buf;
+	unsigned nmsg;
+	char *hostname;
+	pid_t pid;
+	const char *retr;
+#if ENABLE_FEATURE_POPMAILDIR_DELIVERY
+	const char *delivery;
+#endif
+	unsigned opt_nlines = 0;
+
+	enum {
+		OPT_b = 1 << 0,		// -b binary mode. Ignored
+		OPT_d = 1 << 1,		// -d,-dd,-ddd debug. Ignored
+		OPT_m = 1 << 2,		// -m show used memory. Ignored
+		OPT_V = 1 << 3,		// -V version. Ignored
+		OPT_c = 1 << 4,		// -c use tcpclient. Ignored
+		OPT_a = 1 << 5,		// -a use APOP protocol
+		OPT_s = 1 << 6,		// -s skip authorization
+		OPT_T = 1 << 7,		// -T get messages with TOP instead with RETR
+		OPT_k = 1 << 8,		// -k keep retrieved messages on the server
+		OPT_t = 1 << 9,		// -t90 set timeout to 90 sec
+		OPT_R = 1 << 10,	// -R20000 remove old messages on the server >= 20000 bytes (requires -k). Ignored
+		OPT_Z = 1 << 11,	// -Z11-23 remove messages from 11 to 23 (dangerous). Ignored
+		OPT_L = 1 << 12,	// -L50000 not retrieve new messages >= 50000 bytes. Ignored
+		OPT_H = 1 << 13,	// -H30 type first 30 lines of a message; (-L12000 -H30). Ignored
+		OPT_M = 1 << 14,	// -M\"program arg1 arg2 ...\"; deliver by program. Treated like -F
+		OPT_F = 1 << 15,	// -F\"program arg1 arg2 ...\"; filter by program. Treated like -M
+	};
+
+	// init global variables
+	INIT_G();
+
+	// parse options
+	opt_complementary = "-1:dd:t+:R+:L+:H+";
+	opts = getopt32(argv,
+		"bdmVcasTkt:" "R:Z:L:H:" IF_FEATURE_POPMAILDIR_DELIVERY("M:F:"),
+		&timeout, NULL, NULL, NULL, &opt_nlines
+		IF_FEATURE_POPMAILDIR_DELIVERY(, &delivery, &delivery) // we treat -M and -F the same
+	);
+	//argc -= optind;
+	argv += optind;
+
+	// get auth info
+	if (!(opts & OPT_s))
+		get_cred_or_die(STDIN_FILENO);
+
+	// goto maildir
+	xchdir(*argv++);
+
+	// launch connect helper, if any
+	if (*argv)
+		launch_helper((const char **)argv);
+
+	// get server greeting
+	pop3_checkr(NULL, NULL, &buf);
+
+	// authenticate (if no -s given)
+	if (!(opts & OPT_s)) {
+		// server supports APOP and we want it?
+		if ('<' == buf[0] && (opts & OPT_a)) {
+			union { // save a bit of stack
+				md5_ctx_t ctx;
+				char hex[16 * 2 + 1];
+			} md5;
+			uint32_t res[16 / 4];
+
+			char *s = strchr(buf, '>');
+			if (s)
+				s[1] = '\0';
+			// get md5 sum of "<stamp>password" string
+			md5_begin(&md5.ctx);
+			md5_hash(&md5.ctx, buf, strlen(buf));
+			md5_hash(&md5.ctx, G.pass, strlen(G.pass));
+			md5_end(&md5.ctx, res);
+			*bin2hex(md5.hex, (char*)res, 16) = '\0';
+			// APOP
+			s = xasprintf("%s %s", G.user, md5.hex);
+			pop3_check("APOP %s", s);
+			free(s);
+			free(buf);
+		// server ignores APOP -> use simple text authentication
+		} else {
+			// USER
+			pop3_check("USER %s", G.user);
+			// PASS
+			pop3_check("PASS %s", G.pass);
+		}
+	}
+
+	// get mailbox statistics
+	pop3_checkr("STAT", NULL, &buf);
+
+	// prepare message filename suffix
+	hostname = safe_gethostname();
+	pid = getpid();
+
+	// get messages counter
+	// NOTE: we don't use xatou(buf) since buf is "nmsg nbytes"
+	// we only need nmsg and atoi is just exactly what we need
+	// if atoi fails to convert buf into number it returns 0
+	// in this case the following loop simply will not be executed
+	nmsg = atoi(buf);
+	free(buf);
+
+	// loop through messages
+	retr = (opts & OPT_T) ? xasprintf("TOP %%u %u", opt_nlines) : "RETR %u";
+	for (; nmsg; nmsg--) {
+
+		char *filename;
+		char *target;
+		char *answer;
+		FILE *fp;
+#if ENABLE_FEATURE_POPMAILDIR_DELIVERY
+		int rc;
+#endif
+		// generate unique filename
+		filename  = xasprintf("tmp/%llu.%u.%s",
+			monotonic_us(), (unsigned)pid, hostname);
+
+		// retrieve message in ./tmp/ unless filter is specified
+		pop3_check(retr, (const char *)(ptrdiff_t)nmsg);
+
+#if ENABLE_FEATURE_POPMAILDIR_DELIVERY
+		// delivery helper ordered? -> setup pipe
+		if (opts & (OPT_F|OPT_M)) {
+			// helper will have $FILENAME set to filename
+			xsetenv("FILENAME", filename);
+			fp = popen(delivery, "w");
+			unsetenv("FILENAME");
+			if (!fp) {
+				bb_perror_msg("delivery helper");
+				break;
+			}
+		} else
+#endif
+		// create and open file filename
+		fp = xfopen_for_write(filename);
+
+		// copy stdin to fp (either filename or delivery helper)
+		while ((answer = xmalloc_fgets_str(stdin, "\r\n")) != NULL) {
+			char *s = answer;
+			if ('.' == answer[0]) {
+				if ('.' == answer[1])
+					s++;
+				else if ('\r' == answer[1] && '\n' == answer[2] && '\0' == answer[3])
+					break;
+			}
+			//*strchrnul(s, '\r') = '\n';
+			fputs(s, fp);
+			free(answer);
+		}
+
+#if ENABLE_FEATURE_POPMAILDIR_DELIVERY
+		// analyse delivery status
+		if (opts & (OPT_F|OPT_M)) {
+			rc = pclose(fp);
+			if (99 == rc) // 99 means bail out
+				break;
+//			if (rc) // !0 means skip to the next message
+				goto skip;
+//			// 0 means continue
+		} else {
+			// close filename
+			fclose(fp);
+		}
+#endif
+
+		// delete message from server
+		if (!(opts & OPT_k))
+			pop3_check("DELE %u", (const char*)(ptrdiff_t)nmsg);
+
+		// atomically move message to ./new/
+		target = xstrdup(filename);
+		strncpy(target, "new", 3);
+		// ... or just stop receiving on failure
+		if (rename_or_warn(filename, target))
+			break;
+		free(target);
+
+#if ENABLE_FEATURE_POPMAILDIR_DELIVERY
+ skip:
+#endif
+		free(filename);
+	}
+
+	// Bye
+	pop3_check("QUIT", NULL);
+
+	if (ENABLE_FEATURE_CLEAN_UP) {
+		free(G.user);
+		free(G.pass);
+	}
+
+	return EXIT_SUCCESS;
+}
diff --git a/ap/app/busybox/src/mailutils/reformime.c b/ap/app/busybox/src/mailutils/reformime.c
new file mode 100644
index 0000000..8e7d455
--- /dev/null
+++ b/ap/app/busybox/src/mailutils/reformime.c
@@ -0,0 +1,278 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * reformime: parse MIME-encoded message
+ *
+ * Copyright (C) 2008 by Vladimir Dronnikov <dronnikov@gmail.com>
+ *
+ * Licensed under GPLv2, see file LICENSE in this source tree.
+ */
+
+//kbuild:lib-$(CONFIG_REFORMIME) += reformime.o mail.o
+
+#include "libbb.h"
+#include "mail.h"
+
+#if 0
+# define dbg_error_msg(...) bb_error_msg(__VA_ARGS__)
+#else
+# define dbg_error_msg(...) ((void)0)
+#endif
+
+static const char *find_token(const char *const string_array[], const char *key, const char *defvalue)
+{
+	const char *r = NULL;
+	int i;
+	for (i = 0; string_array[i] != NULL; i++) {
+		if (strcasecmp(string_array[i], key) == 0) {
+			r = (char *)string_array[i+1];
+			break;
+		}
+	}
+	return (r) ? r : defvalue;
+}
+
+static const char *xfind_token(const char *const string_array[], const char *key)
+{
+	const char *r = find_token(string_array, key, NULL);
+	if (r)
+		return r;
+	bb_error_msg_and_die("not found: '%s'", key);
+}
+
+enum {
+	OPT_x = 1 << 0,
+	OPT_X = 1 << 1,
+#if ENABLE_FEATURE_REFORMIME_COMPAT
+	OPT_d = 1 << 2,
+	OPT_e = 1 << 3,
+	OPT_i = 1 << 4,
+	OPT_s = 1 << 5,
+	OPT_r = 1 << 6,
+	OPT_c = 1 << 7,
+	OPT_m = 1 << 8,
+	OPT_h = 1 << 9,
+	OPT_o = 1 << 10,
+	OPT_O = 1 << 11,
+#endif
+};
+
+static int parse(const char *boundary, char **argv)
+{
+	int boundary_len = strlen(boundary);
+	char uniq[sizeof("%%llu.%u") + sizeof(int)*3];
+
+	dbg_error_msg("BOUNDARY[%s]", boundary);
+
+	// prepare unique string pattern
+	sprintf(uniq, "%%llu.%u", (unsigned)getpid());
+	dbg_error_msg("UNIQ[%s]", uniq);
+
+	while (1) {
+		char *header;
+		const char *tokens[32]; /* 32 is enough */
+		const char *type;
+
+		/* Read the header (everything up to two \n) */
+		{
+			unsigned header_idx = 0;
+			int last_ch = 0;
+			header = NULL;
+			while (1) {
+				int ch = fgetc(stdin);
+				if (ch == '\r') /* Support both line endings */
+					continue;
+				if (ch == EOF)
+					break;
+				if (ch == '\n' && last_ch == ch)
+					break;
+				if (!(header_idx & 0xff))
+					header = xrealloc(header, header_idx + 0x101);
+				header[header_idx++] = last_ch = ch;
+			}
+			if (!header) {
+				dbg_error_msg("EOF");
+				break;
+			}
+			header[header_idx] = '\0';
+			dbg_error_msg("H:'%s'", p);
+		}
+
+		/* Split to tokens */
+		{
+			char *s, *p;
+			unsigned ntokens;
+			const char *delims = ";=\" \t\n";
+
+			/* Skip to last Content-Type: */
+			s = p = header;
+			while ((p = strchr(p, '\n')) != NULL) {
+				p++;
+				if (strncasecmp(p, "Content-Type:", sizeof("Content-Type:")-1) == 0)
+					s = p;
+			}
+			dbg_error_msg("L:'%s'", p);
+			ntokens = 0;
+			s = strtok(s, delims);
+			while (s) {
+				tokens[ntokens] = s;
+				if (ntokens < ARRAY_SIZE(tokens) - 1)
+					ntokens++;
+				dbg_error_msg("L[%d]='%s'", ntokens, s);
+				s = strtok(NULL, delims);
+			}
+			tokens[ntokens] = NULL;
+			dbg_error_msg("EMPTYLINE, ntokens:%d", ntokens);
+			if (ntokens == 0)
+				break;
+		}
+
+		/* Is it multipart? */
+		type = find_token(tokens, "Content-Type:", "text/plain");
+		dbg_error_msg("TYPE:'%s'", type);
+		if (0 == strncasecmp(type, "multipart/", 10)) {
+			/* Yes, recurse */
+			if (strcasecmp(type + 10, "mixed") != 0)
+				bb_error_msg_and_die("no support of content type '%s'", type);
+			parse(xfind_token(tokens, "boundary"), argv);
+
+		} else {
+			/* No, process one non-multipart section */
+			char *end;
+			pid_t pid = pid;
+			FILE *fp;
+
+			const char *charset = find_token(tokens, "charset", CONFIG_FEATURE_MIME_CHARSET);
+			const char *encoding = find_token(tokens, "Content-Transfer-Encoding:", "7bit");
+
+			/* Compose target filename */
+			char *filename = (char *)find_token(tokens, "filename", NULL);
+			if (!filename)
+				filename = xasprintf(uniq, monotonic_us());
+			else
+				filename = bb_get_last_path_component_strip(xstrdup(filename));
+
+			if (opts & OPT_X) {
+				int fd[2];
+
+				/* start external helper */
+				xpipe(fd);
+				pid = vfork();
+				if (0 == pid) {
+					/* child reads from fd[0] */
+					close(fd[1]);
+					xmove_fd(fd[0], STDIN_FILENO);
+					xsetenv("CONTENT_TYPE", type);
+					xsetenv("CHARSET", charset);
+					xsetenv("ENCODING", encoding);
+					xsetenv("FILENAME", filename);
+					BB_EXECVP_or_die(argv);
+				}
+				/* parent will write to fd[1] */
+				close(fd[0]);
+				fp = xfdopen_for_write(fd[1]);
+				signal(SIGPIPE, SIG_IGN);
+			} else {
+				/* write to file */
+				char *fname = xasprintf("%s%s", *argv, filename);
+				fp = xfopen_for_write(fname);
+				free(fname);
+			}
+			free(filename);
+
+			/* write to fp */
+			end = NULL;
+			if (0 == strcasecmp(encoding, "base64")) {
+				read_base64(stdin, fp, '-');
+			} else
+			if (0 != strcasecmp(encoding, "7bit")
+			 && 0 != strcasecmp(encoding, "8bit")
+			) {
+				/* quoted-printable, binary, user-defined are unsupported so far */
+				bb_error_msg_and_die("encoding '%s' not supported", encoding);
+			} else {
+				/* plain 7bit or 8bit */
+				while ((end = xmalloc_fgets(stdin)) != NULL) {
+					if ('-' == end[0]
+					 && '-' == end[1]
+					 && strncmp(end + 2, boundary, boundary_len) == 0
+					) {
+						break;
+					}
+					fputs(end, fp);
+				}
+			}
+			fclose(fp);
+
+			/* Wait for child */
+			if (opts & OPT_X) {
+				int rc;
+				signal(SIGPIPE, SIG_DFL);
+				rc = (wait4pid(pid) & 0xff);
+				if (rc != 0)
+					return rc + 20;
+			}
+
+			/* Multipart ended? */
+			if (end && '-' == end[2 + boundary_len] && '-' == end[2 + boundary_len + 1]) {
+				dbg_error_msg("FINISHED MPART:'%s'", end);
+				break;
+			}
+			dbg_error_msg("FINISHED:'%s'", end);
+			free(end);
+		} /* end of "handle one non-multipart block" */
+
+		free(header);
+	} /* while (1) */
+
+	dbg_error_msg("ENDPARSE[%s]", boundary);
+
+	return EXIT_SUCCESS;
+}
+
+//usage:#define reformime_trivial_usage
+//usage:       "[OPTIONS]"
+//usage:#define reformime_full_usage "\n\n"
+//usage:       "Parse MIME-encoded message on stdin\n"
+//usage:     "\n	-x PREFIX	Extract content of MIME sections to files"
+//usage:     "\n	-X PROG ARGS	Filter content of MIME sections through PROG"
+//usage:     "\n			Must be the last option"
+//usage:     "\n"
+//usage:     "\nOther options are silently ignored"
+
+/*
+Usage: reformime [options]
+    -d - parse a delivery status notification.
+    -e - extract contents of MIME section.
+    -x - extract MIME section to a file.
+    -X - pipe MIME section to a program.
+    -i - show MIME info.
+    -s n.n.n.n - specify MIME section.
+    -r - rewrite message, filling in missing MIME headers.
+    -r7 - also convert 8bit/raw encoding to quoted-printable, if possible.
+    -r8 - also convert quoted-printable encoding to 8bit, if possible.
+    -c charset - default charset for rewriting, -o, and -O.
+    -m [file] [file]... - create a MIME message digest.
+    -h "header" - decode RFC 2047-encoded header.
+    -o "header" - encode unstructured header using RFC 2047.
+    -O "header" - encode address list header using RFC 2047.
+*/
+
+int reformime_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
+int reformime_main(int argc UNUSED_PARAM, char **argv)
+{
+	const char *opt_prefix = "";
+
+	INIT_G();
+
+	// parse options
+	// N.B. only -x and -X are supported so far
+	opt_complementary = "x--X:X--x" IF_FEATURE_REFORMIME_COMPAT(":m::");
+	opts = getopt32(argv,
+		"x:X" IF_FEATURE_REFORMIME_COMPAT("deis:r:c:m:h:o:O:"),
+		&opt_prefix
+		IF_FEATURE_REFORMIME_COMPAT(, NULL, NULL, &G.opt_charset, NULL, NULL, NULL, NULL)
+	);
+	argv += optind;
+
+	return parse("", (opts & OPT_X) ? argv : (char **)&opt_prefix);
+}
diff --git a/ap/app/busybox/src/mailutils/sendmail.c b/ap/app/busybox/src/mailutils/sendmail.c
new file mode 100644
index 0000000..c426e9d
--- /dev/null
+++ b/ap/app/busybox/src/mailutils/sendmail.c
@@ -0,0 +1,357 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * bare bones sendmail
+ *
+ * Copyright (C) 2008 by Vladimir Dronnikov <dronnikov@gmail.com>
+ *
+ * Licensed under GPLv2, see file LICENSE in this source tree.
+ */
+
+//kbuild:lib-$(CONFIG_SENDMAIL) += sendmail.o mail.o
+
+//usage:#define sendmail_trivial_usage
+//usage:       "[OPTIONS] [RECIPIENT_EMAIL]..."
+//usage:#define sendmail_full_usage "\n\n"
+//usage:       "Read email from stdin and send it\n"
+//usage:     "\nStandard options:"
+//usage:     "\n	-t		Read additional recipients from message body"
+//usage:     "\n	-f SENDER	Sender (required)"
+//usage:     "\n	-o OPTIONS	Various options. -oi implied, others are ignored"
+//usage:     "\n	-i		-oi synonym. implied and ignored"
+//usage:     "\n"
+//usage:     "\nBusybox specific options:"
+//usage:     "\n	-v		Verbose"
+//usage:     "\n	-w SECS		Network timeout"
+//usage:     "\n	-H 'PROG ARGS'	Run connection helper"
+//usage:     "\n			Examples:"
+//usage:     "\n			-H 'exec openssl s_client -quiet -tls1 -starttls smtp"
+//usage:     "\n				-connect smtp.gmail.com:25' <email.txt"
+//usage:     "\n				[4<username_and_passwd.txt | -auUSER -apPASS]"
+//usage:     "\n			-H 'exec openssl s_client -quiet -tls1"
+//usage:     "\n				-connect smtp.gmail.com:465' <email.txt"
+//usage:     "\n				[4<username_and_passwd.txt | -auUSER -apPASS]"
+//usage:     "\n	-S HOST[:PORT]	Server"
+//usage:     "\n	-auUSER		Username for AUTH LOGIN"
+//usage:     "\n	-apPASS 	Password for AUTH LOGIN"
+////usage:     "\n	-amMETHOD	Authentication method. Ignored. LOGIN is implied"
+//usage:     "\n"
+//usage:     "\nOther options are silently ignored; -oi -t is implied"
+//usage:	IF_MAKEMIME(
+//usage:     "\nUse makemime to create emails with attachments"
+//usage:	)
+
+#include "libbb.h"
+#include "mail.h"
+
+// limit maximum allowed number of headers to prevent overflows.
+// set to 0 to not limit
+#define MAX_HEADERS 256
+
+static void send_r_n(const char *s)
+{
+	if (verbose)
+		bb_error_msg("send:'%s'", s);
+	printf("%s\r\n", s);
+}
+
+static int smtp_checkp(const char *fmt, const char *param, int code)
+{
+	char *answer;
+	char *msg = send_mail_command(fmt, param);
+	// read stdin
+	// if the string has a form NNN- -- read next string. E.g. EHLO response
+	// parse first bytes to a number
+	// if code = -1 then just return this number
+	// if code != -1 then checks whether the number equals the code
+	// if not equal -> die saying msg
+	while ((answer = xmalloc_fgetline(stdin)) != NULL) {
+		if (verbose)
+			bb_error_msg("recv:'%.*s'", (int)(strchrnul(answer, '\r') - answer), answer);
+		if (strlen(answer) <= 3 || '-' != answer[3])
+			break;
+		free(answer);
+	}
+	if (answer) {
+		int n = atoi(answer);
+		if (timeout)
+			alarm(0);
+		free(answer);
+		if (-1 == code || n == code) {
+			free(msg);
+			return n;
+		}
+	}
+	bb_error_msg_and_die("%s failed", msg);
+}
+
+static int smtp_check(const char *fmt, int code)
+{
+	return smtp_checkp(fmt, NULL, code);
+}
+
+// strip argument of bad chars
+static char *sane_address(char *str)
+{
+	char *s = str;
+	char *p = s;
+	while (*s) {
+		if (isalnum(*s) || '_' == *s || '-' == *s || '.' == *s || '@' == *s) {
+			*p++ = *s;
+		}
+		s++;
+	}
+	*p = '\0';
+	return str;
+}
+
+static void rcptto(const char *s)
+{
+	// N.B. we don't die if recipient is rejected, for the other recipients may be accepted
+	if (250 != smtp_checkp("RCPT TO:<%s>", s, -1))
+		bb_error_msg("Bad recipient: <%s>", s);
+}
+
+int sendmail_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
+int sendmail_main(int argc UNUSED_PARAM, char **argv)
+{
+	char *opt_connect = opt_connect;
+	char *opt_from;
+	char *s;
+	llist_t *list = NULL;
+	char *host = sane_address(safe_gethostname());
+	unsigned nheaders = 0;
+	int code;
+
+	enum {
+	//--- standard options
+		OPT_t = 1 << 0,         // read message for recipients, append them to those on cmdline
+		OPT_f = 1 << 1,         // sender address
+		OPT_o = 1 << 2,         // various options. -oi IMPLIED! others are IGNORED!
+		OPT_i = 1 << 3,         // IMPLIED!
+	//--- BB specific options
+		OPT_w = 1 << 4,         // network timeout
+		OPT_H = 1 << 5,         // use external connection helper
+		OPT_S = 1 << 6,         // specify connection string
+		OPT_a = 1 << 7,         // authentication tokens
+		OPT_v = 1 << 8,         // verbosity
+	};
+
+	// init global variables
+	INIT_G();
+
+	// save initial stdin since body is piped!
+	xdup2(STDIN_FILENO, 3);
+	G.fp0 = xfdopen_for_read(3);
+
+	// parse options
+	// -v is a counter, -f is required. -H and -S are mutually exclusive, -a is a list
+	opt_complementary = "vv:f:w+:H--S:S--H:a::";
+	// N.B. since -H and -S are mutually exclusive they do not interfere in opt_connect
+	// -a is for ssmtp (http://downloads.openwrt.org/people/nico/man/man8/ssmtp.8.html) compatibility,
+	// it is still under development.
+	opts = getopt32(argv, "tf:o:iw:H:S:a::v", &opt_from, NULL,
+			&timeout, &opt_connect, &opt_connect, &list, &verbose);
+	//argc -= optind;
+	argv += optind;
+
+	// process -a[upm]<token> options
+	if ((opts & OPT_a) && !list)
+		bb_show_usage();
+	while (list) {
+		char *a = (char *) llist_pop(&list);
+		if ('u' == a[0])
+			G.user = xstrdup(a+1);
+		if ('p' == a[0])
+			G.pass = xstrdup(a+1);
+		// N.B. we support only AUTH LOGIN so far
+		//if ('m' == a[0])
+		//	G.method = xstrdup(a+1);
+	}
+	// N.B. list == NULL here
+	//bb_info_msg("OPT[%x] AU[%s], AP[%s], AM[%s], ARGV[%s]", opts, au, ap, am, *argv);
+
+	// connect to server
+
+	// connection helper ordered? ->
+	if (opts & OPT_H) {
+		const char *args[] = { "sh", "-c", opt_connect, NULL };
+		// plug it in
+		launch_helper(args);
+		// Now:
+		// our stdout will go to helper's stdin,
+		// helper's stdout will be available on our stdin.
+
+		// Wait for initial server message.
+		// If helper (such as openssl) invokes STARTTLS, the initial 220
+		// is swallowed by helper (and not repeated after TLS is initiated).
+		// We will send NOOP cmd to server and check the response.
+		// We should get 220+250 on plain connection, 250 on STARTTLSed session.
+		//
+		// The problem here is some servers delay initial 220 message,
+		// and consider client to be a spammer if it starts sending cmds
+		// before 220 reached it. The code below is unsafe in this regard:
+		// in non-STARTTLSed case, we potentially send NOOP before 220
+		// is sent by server.
+		// Ideas? (--delay SECS opt? --assume-starttls-helper opt?)
+		code = smtp_check("NOOP", -1);
+		if (code == 220)
+			// we got 220 - this is not STARTTLSed connection,
+			// eat 250 response to our NOOP
+			smtp_check(NULL, 250);
+		else
+		if (code != 250)
+			bb_error_msg_and_die("SMTP init failed");
+	} else {
+		// vanilla connection
+		int fd;
+		// host[:port] not explicitly specified? -> use $SMTPHOST
+		// no $SMTPHOST? -> use localhost
+		if (!(opts & OPT_S)) {
+			opt_connect = getenv("SMTPHOST");
+			if (!opt_connect)
+				opt_connect = (char *)"127.0.0.1";
+		}
+		// do connect
+		fd = create_and_connect_stream_or_die(opt_connect, 25);
+		// and make ourselves a simple IO filter
+		xmove_fd(fd, STDIN_FILENO);
+		xdup2(STDIN_FILENO, STDOUT_FILENO);
+
+		// Wait for initial server 220 message
+		smtp_check(NULL, 220);
+	}
+
+	// we should start with modern EHLO
+	if (250 != smtp_checkp("EHLO %s", host, -1))
+		smtp_checkp("HELO %s", host, 250);
+	free(host);
+
+	// perform authentication
+	if (opts & OPT_a) {
+		smtp_check("AUTH LOGIN", 334);
+		// we must read credentials unless they are given via -a[up] options
+		if (!G.user || !G.pass)
+			get_cred_or_die(4);
+		encode_base64(NULL, G.user, NULL);
+		smtp_check("", 334);
+		encode_base64(NULL, G.pass, NULL);
+		smtp_check("", 235);
+	}
+
+	// set sender
+	// N.B. we have here a very loosely defined algorythm
+	// since sendmail historically offers no means to specify secrets on cmdline.
+	// 1) server can require no authentication ->
+	//	we must just provide a (possibly fake) reply address.
+	// 2) server can require AUTH ->
+	//	we must provide valid username and password along with a (possibly fake) reply address.
+	//	For the sake of security username and password are to be read either from console or from a secured file.
+	//	Since reading from console may defeat usability, the solution is either to read from a predefined
+	//	file descriptor (e.g. 4), or again from a secured file.
+
+	// got no sender address? -> use system username as a resort
+	// N.B. we marked -f as required option!
+	//if (!G.user) {
+	//	// N.B. IMHO getenv("USER") can be way easily spoofed!
+	//	G.user = xuid2uname(getuid());
+	//	opt_from = xasprintf("%s@%s", G.user, domain);
+	//}
+	smtp_checkp("MAIL FROM:<%s>", opt_from, 250);
+
+	// process message
+
+	// read recipients from message and add them to those given on cmdline.
+	// this means we scan stdin for To:, Cc:, Bcc: lines until an empty line
+	// and then use the rest of stdin as message body
+	code = 0; // set "analyze headers" mode
+	while ((s = xmalloc_fgetline(G.fp0)) != NULL) {
+ dump:
+		// put message lines doubling leading dots
+		if (code) {
+			// escape leading dots
+			// N.B. this feature is implied even if no -i (-oi) switch given
+			// N.B. we need to escape the leading dot regardless of
+			// whether it is single or not character on the line
+			if ('.' == s[0] /*&& '\0' == s[1] */)
+				printf(".");
+			// dump read line
+			send_r_n(s);
+			free(s);
+			continue;
+		}
+
+		// analyze headers
+		// To: or Cc: headers add recipients
+		if (opts & OPT_t) {
+			if (0 == strncasecmp("To:", s, 3) || 0 == strncasecmp("Bcc:" + 1, s, 3)) {
+				rcptto(sane_address(s+3));
+				goto addheader;
+			}
+			// Bcc: header adds blind copy (hidden) recipient
+			if (0 == strncasecmp("Bcc:", s, 4)) {
+				rcptto(sane_address(s+4));
+				free(s);
+				continue; // N.B. Bcc: vanishes from headers!
+			}
+		}
+		if (strchr(s, ':') || (list && isspace(s[0]))) {
+			// other headers go verbatim
+			// N.B. RFC2822 2.2.3 "Long Header Fields" allows for headers to occupy several lines.
+			// Continuation is denoted by prefixing additional lines with whitespace(s).
+			// Thanks (stefan.seyfried at googlemail.com) for pointing this out.
+ addheader:
+			// N.B. we allow MAX_HEADERS generic headers at most to prevent attacks
+			if (MAX_HEADERS && ++nheaders >= MAX_HEADERS)
+				goto bail;
+			llist_add_to_end(&list, s);
+		} else {
+			// a line without ":" (an empty line too, by definition) doesn't look like a valid header
+			// so stop "analyze headers" mode
+ reenter:
+			// put recipients specified on cmdline
+			while (*argv) {
+				char *t = sane_address(*argv);
+				rcptto(t);
+				//if (MAX_HEADERS && ++nheaders >= MAX_HEADERS)
+				//	goto bail;
+				llist_add_to_end(&list, xasprintf("To: %s", t));
+				argv++;
+			}
+			// enter "put message" mode
+			// N.B. DATA fails iff no recipients were accepted (or even provided)
+			// in this case just bail out gracefully
+			if (354 != smtp_check("DATA", -1))
+				goto bail;
+			// dump the headers
+			while (list) {
+				send_r_n((char *) llist_pop(&list));
+			}
+			// stop analyzing headers
+			code++;
+			// N.B. !s means: we read nothing, and nothing to be read in the future.
+			// just dump empty line and break the loop
+			if (!s) {
+				send_r_n("");
+				break;
+			}
+			// go dump message body
+			// N.B. "s" already contains the first non-header line, so pretend we read it from input
+			goto dump;
+		}
+	}
+	// odd case: we didn't stop "analyze headers" mode -> message body is empty. Reenter the loop
+	// N.B. after reenter code will be > 0
+	if (!code)
+		goto reenter;
+
+	// finalize the message
+	smtp_check(".", 250);
+ bail:
+	// ... and say goodbye
+	smtp_check("QUIT", 221);
+	// cleanup
+	if (ENABLE_FEATURE_CLEAN_UP)
+		fclose(G.fp0);
+
+	return EXIT_SUCCESS;
+}