svn commit: [25914] trunk/busybox: include mailutils scripts/kconfig

vda at busybox.net vda at busybox.net
Tue Mar 31 23:41:53 UTC 2009


Author: vda
Date: 2009-03-31 23:41:53 +0000 (Tue, 31 Mar 2009)
New Revision: 25914

Log:
sendmail: update by Vladimir
build system: tweak for rare case where include/autoconf.h
  does not get updated

function                                             old     new   delta
packed_usage                                       26238   26242      +4
sendmail_main                                       1353     897    -456
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 1/1 up/down: 4/-456)           Total: -452 bytes



Modified:
   trunk/busybox/include/usage.h
   trunk/busybox/mailutils/Config.in
   trunk/busybox/mailutils/sendmail.c
   trunk/busybox/scripts/kconfig/util.c


Changeset:
Modified: trunk/busybox/include/usage.h
===================================================================
--- trunk/busybox/include/usage.h	2009-03-31 22:14:32 UTC (rev 25913)
+++ trunk/busybox/include/usage.h	2009-03-31 23:41:53 UTC (rev 25914)
@@ -3686,32 +3686,27 @@
        "[OPTIONS] [rcpt]..."
 #define sendmail_full_usage "\n\n" \
        "Send an email\n" \
-     "\nOptions:" \
-     "\n	-w timeout	Network timeout" \
-     "\n	-N type		Request delivery notification. Type is ignored" \
-     "\n	-f sender	Sender" \
-     "\n	-F fullname	Sender full name. Overrides $NAME" \
-	USE_FEATURE_SENDMAIL_MAILX( \
-     "\n	-s subject	Subject" \
-     "\n	-j charset	Assume charset for body and subject (" CONFIG_FEATURE_MIME_CHARSET ")" \
-     "\n	-a file		File to attach. May be repeated" \
+     "\nStandard options:" \
+     "\n	-t		Read recipients from message body, add them to those on cmdline" \
+     "\n	-f sender	Sender. REQUIRED!" \
+     "\n	-o options	various options. -oi IMPLIED! others are IGNORED!" \
+     "\n" \
+     "\nBusybox specific options:" \
+     "\n	-w seconds	Network timeout" \
      "\n	-H 'prog args'	Run connection helper" \
      "\n			Examples:" \
      "\n			-H 'exec openssl s_client -quiet -tls1 -starttls smtp" \
      "\n				-connect smtp.gmail.com:25' <email.txt" \
-     "\n				[4<username_and_passwd.txt]" \
+     "\n				[4<username_and_passwd.txt | -au<username> -ap<password>]" \
      "\n			-H 'exec openssl s_client -quiet -tls1" \
      "\n				-connect smtp.gmail.com:465' <email.txt" \
-     "\n				[4<username_and_passwd.txt]" \
+     "\n				[4<username_and_passwd.txt | -au<username> -ap<password>]" \
      "\n	-S server[:port] Server" \
-	) \
-	USE_FEATURE_SENDMAIL_MAILXX( \
-     "\n	-c rcpt		Cc: recipient. May be repeated" \
-     "\n	-e rcpt		Errors-To: recipient" \
-	) \
-     "\n	-t		Read recipients and subject from body" \
+     "\n	-au<username>	Username for AUTH LOGIN" \
+     "\n	-ap<password>	Password for AUTH LOGIN" \
+     "\n	-am<method>	Authentication method. Ignored. login is implied." \
      "\n" \
-     "\nOther options are silently ignored; -oi is implied" \
+     "\nOther options are silently ignored; -oi -t is implied" \
 
 #define seq_trivial_usage \
        "[-w] [-s SEP] [FIRST [INC]] LAST"

Modified: trunk/busybox/mailutils/Config.in
===================================================================
--- trunk/busybox/mailutils/Config.in	2009-03-31 22:14:32 UTC (rev 25913)
+++ trunk/busybox/mailutils/Config.in	2009-03-31 23:41:53 UTC (rev 25914)
@@ -50,20 +50,4 @@
 	help
 	  Barebones sendmail.
 
-config FEATURE_SENDMAIL_MAILX
-	bool "Allow to specify subject, attachments, their charset etc"
-	default y
-	depends on SENDMAIL
-	help
-	  Allow to specify subject, attachments and their charset.
-	  Allow to use custom connection helper.
-
-config FEATURE_SENDMAIL_MAILXX
-	bool "Allow to specify Cc: addresses and some additional headers"
-	default n
-	depends on FEATURE_SENDMAIL_MAILX
-	help
-	  Allow to specify Cc: addresses and some additional headers:
-	  Errors-To:
-
 endmenu

Modified: trunk/busybox/mailutils/sendmail.c
===================================================================
--- trunk/busybox/mailutils/sendmail.c	2009-03-31 22:14:32 UTC (rev 25913)
+++ trunk/busybox/mailutils/sendmail.c	2009-03-31 23:41:53 UTC (rev 25914)
@@ -61,35 +61,23 @@
 int sendmail_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
 int sendmail_main(int argc UNUSED_PARAM, char **argv)
 {
-#if ENABLE_FEATURE_SENDMAIL_MAILX
-	llist_t *opt_attachments = NULL;
-	const char *opt_subject;
-#if ENABLE_FEATURE_SENDMAIL_MAILXX
-	llist_t *opt_carboncopies = NULL;
-	char *opt_errors_to;
-#endif
-#endif
 	char *opt_connect = opt_connect;
-	char *opt_from, *opt_fullname;
-	char *boundary;
-	llist_t *l;
-	llist_t *headers = NULL;
+	char *opt_from;
+	char *s;
+	llist_t *list = NULL;
 	char *domain = sane_address(safe_getdomainname());
 	int code;
 
 	enum {
-		OPT_w = 1 << 0,         // network timeout
-		OPT_t = 1 << 1,         // read message for recipients
-		OPT_N = 1 << 2,         // request notification
-		OPT_f = 1 << 3,         // sender address
-		OPT_F = 1 << 4,         // sender name, overrides $NAME
-		OPT_s = 1 << 5,         // subject
-		OPT_j = 1 << 6,         // assumed charset
-		OPT_a = 1 << 7,         // attachment(s)
-		OPT_H = 1 << 8,         // use external connection helper
-		OPT_S = 1 << 9,         // specify connection string
-		OPT_c = 1 << 10,        // carbon copy
-		OPT_e = 1 << 11,        // errors-to address
+	//--- 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!
+	//--- BB specific options
+		OPT_w = 1 << 3,         // network timeout
+		OPT_H = 1 << 4,         // use external connection helper
+		OPT_S = 1 << 5,         // specify connection string
+		OPT_a = 1 << 6,         // authentication tokens
 	};
 
 	// init global variables
@@ -100,35 +88,42 @@
 	G.fp0 = fdopen(3, "r");
 
 	// parse options
-	opt_complementary = "w+" USE_FEATURE_SENDMAIL_MAILX(":a::H--S:S--H") USE_FEATURE_SENDMAIL_MAILXX(":c::");
-	opts = getopt32(argv,
-		"w:t" "N:f:F:" USE_FEATURE_SENDMAIL_MAILX("s:j:a:H:S:") USE_FEATURE_SENDMAIL_MAILXX("c:e:")
-		"X:V:vq:R:O:o:nmL:Iih:GC:B:b:A:" // postfix compat only, ignored
-		// r:Q:p:M:Dd are candidates from another man page. TODO?
-		"46E", // ssmtp introduces another quirks. TODO?: -a[upm] (user, pass, method) to be supported
-		&timeout /* -w */, NULL, &opt_from, &opt_fullname,
-		USE_FEATURE_SENDMAIL_MAILX(&opt_subject, &G.opt_charset, &opt_attachments, &opt_connect, &opt_connect,)
-		USE_FEATURE_SENDMAIL_MAILXX(&opt_carboncopies, &opt_errors_to,)
-		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
-	);
+	// -f is required. -H and -S are mutually exclusive
+	opt_complementary = "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:w:H:S:a::", &opt_from, NULL, &timeout, &opt_connect, &opt_connect, &list);
 	//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
 
-#if ENABLE_FEATURE_SENDMAIL_MAILX
-	// N.B. -H and -S are mutually exclusive so they do not spoil opt_connect
 	// connection helper ordered? ->
 	if (opts & OPT_H) {
 		const char *args[] = { "sh", "-c", opt_connect, NULL };
 		// plug it in
 		launch_helper(args);
 	// vanilla connection
-	} else
-#endif
-	{
+	} else {
 		int fd;
-		// host[:port] not explicitly specified ? -> use $SMTPHOST
+		// host[:port] not explicitly specified? -> use $SMTPHOST
 		// no $SMTPHOST ? -> use localhost
 		if (!(opts & OPT_S)) {
 			opt_connect = getenv("SMTPHOST");
@@ -145,7 +140,7 @@
 
 	// wait for initial server OK
 	// N.B. if we used openssl the initial 220 answer is already swallowed during openssl TLS init procedure
-	// so we need to push the server to see whether we are ok
+	// so we need to kick the server to see whether we are ok
 	code = smtp_check("NOOP", -1);
 	// 220 on plain connection, 250 on openssl-helped TLS session
 	if (220 == code)
@@ -157,7 +152,21 @@
 	if (250 != smtp_checkp("EHLO %s", domain, -1)) {
 		smtp_checkp("HELO %s", domain, 250);
 	}
+	if (ENABLE_FEATURE_CLEAN_UP)
+		free(domain);
 
+	// 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 algotythm
 	// since sendmail historically offers no means to specify secrets on cmdline.
@@ -170,201 +179,25 @@
 	//	file descriptor (e.g. 4), or again from a secured file.
 
 	// got no sender address? -> use system username as a resort
-	if (!(opts & OPT_f)) {
-		// N.B. IMHO getenv("USER") can be way easily spoofed!
-		G.user = xuid2uname(getuid());
-		opt_from = xasprintf("%s@%s", G.user, domain);
-	}
-	if (ENABLE_FEATURE_CLEAN_UP)
-		free(domain);
+	// 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);
+	//}
+	//if (ENABLE_FEATURE_CLEAN_UP)
+	//	free(domain);
+	smtp_checkp("MAIL FROM:<%s>", opt_from, 250);
 
-	code = -1; // first try softly without authentication
-	while (250 != smtp_checkp("MAIL FROM:<%s>", opt_from, code)) {
-		// MAIL FROM failed -> authentication needed
-		if (334 == smtp_check("AUTH LOGIN", -1)) {
-			// we must read credentials
-			get_cred_or_die(4);
-			encode_base64(NULL, G.user, NULL);
-			smtp_check("", 334);
-			encode_base64(NULL, G.pass, NULL);
-			smtp_check("", 235);
-		}
-		// authenticated OK? -> retry to set sender
-		// but this time die on failure!
-		code = 250;
-	}
+	// process message
 
-	// recipients specified as arguments
-	while (*argv) {
-		char *s = sane_address(*argv);
-		// loose test on email address validity
-//		if (strchr(s, '@')) {
-			rcptto(s);
-			llist_add_to_end(&headers, xasprintf("To: %s", s));
-//		}
-		argv++;
-	}
-
-#if ENABLE_FEATURE_SENDMAIL_MAILXX
-	// carbon copies recipients specified as -c options
-	for (l = opt_carboncopies; l; l = l->link) {
-		char *s = sane_address(l->data);
-		// loose test on email address validity
-//		if (strchr(s, '@')) {
-			rcptto(s);
-			// TODO: do we ever need to mangle the message?
-			//llist_add_to_end(&headers, xasprintf("Cc: %s", s));
-//		}
-	}
-#endif
-
-	// if -t specified or no recipients specified -> read recipients from message
-	// i.e. scan stdin for To:, Cc:, Bcc: lines ...
-	// ... and then use the rest of stdin as message body
-	// N.B. subject read from body can be further overrided with one specified on command line.
-	// recipients are merged. Bcc: lines are deleted
-	// N.B. other headers are collected and will be dumped verbatim
-	if (opts & OPT_t || !headers) {
-		// fetch recipients and (optionally) subject
-		char *s;
-		while ((s = xmalloc_fgetline(G.fp0)) != NULL) {
-			if (0 == strncasecmp("To: ", s, 4) || 0 == strncasecmp("Cc: ", s, 4)) {
-				rcptto(sane_address(s+4));
-				llist_add_to_end(&headers, s);
-			} else if (0 == strncasecmp("Bcc: ", s, 5)) {
-				rcptto(sane_address(s+5));
-				free(s);
-				// N.B. Bcc vanishes from headers!
-			} else if (0 == strncmp("Subject: ", s, 9)) {
-				// we read subject -> use it verbatim unless it is specified
-				// on command line
-				if (!(opts & OPT_s))
-					llist_add_to_end(&headers, s);
-				else
-					free(s);
-			} else if (s[0]) {
-				// misc header
-				llist_add_to_end(&headers, s);
-			} else {
-				free(s);
-				break; // stop on the first empty line
-			}
-		}
-	}
-
-	// enter "put message" mode
-	smtp_check("DATA", 354);
-
-	// put headers we could have preread with -t
-	for (l = headers; l; l = l->link) {
-		printf("%s\r\n", l->data);
-		if (ENABLE_FEATURE_CLEAN_UP)
-			free(l->data);
-	}
-
-	// put (possibly encoded) subject
-#if ENABLE_FEATURE_SENDMAIL_MAILX
-	if (opts & OPT_s) {
-		printf("Subject: ");
-		if (opts & OPT_j) {
-			printf("=?%s?B?", G.opt_charset);
-			encode_base64(NULL, opt_subject, NULL);
-			printf("?=");
-		} else {
-			printf("%s", opt_subject);
-		}
-		printf("\r\n");
-	}
-#endif
-
-	// put sender name, $NAME is the default
-	if (!(opts & OPT_F))
-		opt_fullname = getenv("NAME");
-	if (opt_fullname)
-		printf("From: \"%s\" <%s>\r\n", opt_fullname, opt_from);
-
-	// put notification
-	if (opts & OPT_N)
-		printf("Disposition-Notification-To: %s\r\n", opt_from);
-
-#if ENABLE_FEATURE_SENDMAIL_MAILXX
-	// put errors recipient
-	if (opts & OPT_e)
-		printf("Errors-To: %s\r\n", opt_errors_to);
-#endif
-
-	// make a random string -- it will delimit message parts
-	srand(monotonic_us());
-	boundary = xasprintf("%d=_%d-%d", rand(), rand(), rand());
-
-	// put common headers
-	// TODO: do we really need this?
-//	printf("Message-ID: <%s>\r\n", boundary);
-
-#if ENABLE_FEATURE_SENDMAIL_MAILX
-	// have attachments? -> compose multipart MIME
-	if (opt_attachments) {
-		const char *fmt;
-		const char *p;
-		char *q;
-
-		printf(
-			"Mime-Version: 1.0\r\n"
-			"%smultipart/mixed; boundary=\"%s\"\r\n"
-			, "Content-Type: "
-			, boundary
-		);
-
-		// body is pseudo attachment read from stdin in first turn
-		llist_add_to(&opt_attachments, (char *)"-");
-
-		// put body + attachment(s)
-		// N.B. all these weird things just to be tiny
-		// by reusing string patterns!
-		fmt =
-			"\r\n--%s\r\n"
-			"%stext/plain; charset=%s\r\n"
-			"%s%s\r\n"
-			"%s"
-		;
-		p = G.opt_charset;
-		q = (char *)"";
-		l = opt_attachments;
-		while (l) {
-			printf(
-				fmt
-				, boundary
-				, "Content-Type: "
-				, p
-				, "Content-Disposition: inline"
-				, q
-				, "Content-Transfer-Encoding: base64\r\n"
-			);
-			p = "";
-			fmt =
-				"\r\n--%s\r\n"
-				"%sapplication/octet-stream%s\r\n"
-				"%s; filename=\"%s\"\r\n"
-				"%s"
-			;
-			encode_base64(l->data, (const char *)G.fp0, "\r");
-			l = l->link;
-			if (l)
-				q = bb_get_last_path_component_strip(l->data);
-		}
-
-		// put message terminator
-		printf("\r\n--%s--\r\n" "\r\n", boundary);
-
-	// no attachments? -> just dump message
-	} else
-#endif
-	{
-		char *s;
-		// terminate headers
-		printf("\r\n");
-		// put plain text respecting leading dots
-		while ((s = xmalloc_fgetline(G.fp0)) != NULL) {
+	// 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) {
+		// 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
@@ -373,10 +206,48 @@
 				printf(".");
 			// dump read line
 			printf("%s\r\n", s);
+			free(s);
+			continue;
 		}
+
+		// analyze headers
+		// To: or Cc: headers add recipients
+		if (0 == strncasecmp("To: ", s, 4) || 0 == strncasecmp("Bcc: " + 1, s, 4)) {
+			rcptto(sane_address(s+4));
+//			goto addh;
+			llist_add_to_end(&list, s);
+		// Bcc: header adds blind copy (hidden) recipient
+		} else if (0 == strncasecmp("Bcc: ", s, 5)) {
+			rcptto(sane_address(s+5));
+			free(s);
+			// N.B. Bcc: vanishes from headers!
+		// other headers go verbatim
+		} else if (s[0]) {
+// addh:
+			llist_add_to_end(&list, s);
+		// the empty line stops analyzing headers
+		} else {
+			free(s);
+			// put recipients specified on cmdline
+			while (*argv) {
+				s = sane_address(*argv);
+				rcptto(s);
+				llist_add_to_end(&list, xasprintf("To: %s", s));
+				argv++;
+			}
+			// enter "put message" mode
+			smtp_check("DATA", 354);
+			// dump the headers
+			while (list) {
+				printf("%s\r\n", (char *) llist_pop(&list));
+			}
+			printf("%s\r\n" + 2); // quirk for format string to be reused
+			// stop analyzing headers
+			code++;
+		}
 	}
 
-	// leave "put message" mode
+	// finalize the message
 	smtp_check(".", 250);
 	// ... and say goodbye
 	smtp_check("QUIT", 221);

Modified: trunk/busybox/scripts/kconfig/util.c
===================================================================
--- trunk/busybox/scripts/kconfig/util.c	2009-03-31 22:14:32 UTC (rev 25913)
+++ trunk/busybox/scripts/kconfig/util.c	2009-03-31 23:41:53 UTC (rev 25914)
@@ -44,7 +44,13 @@
 		else
 			fprintf(out, "\t%s\n", file->name);
 	}
-	fprintf(out, "\n.config include/autoconf.h: $(deps_config)\n\n$(deps_config):\n");
+	fprintf(out,
+		"\n"
+		".config include/autoconf.h: $(deps_config)\n"
+		"\n"
+		"include/autoconf.h: .config\n" /* bbox */
+		"\n"
+		"$(deps_config):\n");
 	fclose(out);
 	rename("..config.tmp", name);
 	return 0;



More information about the busybox-cvs mailing list