sendmail: another update from the maintainer

function                                             old     new   delta
sendgetmail_main                                    1894    1937     +43
crond_main                                          1416    1423      +7
packed_usage                                       24540   24470     -70
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 2/1 up/down: 50/-70)            Total: -20 bytes

diff --git a/networking/sendmail.c b/networking/sendmail.c
index 071d9d6..b81c852 100644
--- a/networking/sendmail.c
+++ b/networking/sendmail.c
@@ -262,32 +262,49 @@
 }
 #endif
 
+static char *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;
+}
+
 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;
+	char *opt_user;
+	char *opt_pass;
 	enum {
 		OPT_w = 1 << 0,         // network timeout
-		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
+		OPT_H = 1 << 1,         // [user:password@]server[:port]
+		OPT_S = 1 << 2,         // connect using openssl s_client helper
 
-		OPTS_t = 1 << 5,        // sendmail: read addresses from body
-		OPTF_t = 1 << 5,        // fetchmail: use "TOP" not "RETR"
+		OPTS_t = 1 << 3,        // sendmail: read addresses from body
+		OPTF_t = 1 << 3,        // fetchmail: use "TOP" not "RETR"
 
-		OPTS_s = 1 << 6,        // sendmail: subject
-		OPTF_z = 1 << 6,        // fetchmail: delete from server
+		OPTS_s = 1 << 4,        // sendmail: subject
+		OPTF_z = 1 << 4,        // fetchmail: delete from server
 
-		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_c = 1 << 5,        // sendmail: assumed charset
+		OPTS_a = 1 << 6,        // sendmail: attachment(s)
+		OPTS_i = 1 << 7,        // sendmail: ignore lone dots in message body (implied)
 
-		OPTS_n = 1 << 10,       // sendmail: request notification
+		OPTS_N = 1 << 8,        // sendmail: request notification
 	};
 	const char *options;
 	int opts;
@@ -303,18 +320,18 @@
 		// save initial stdin (body or attachements can be piped!)
 		xdup2(STDIN_FILENO, INITIAL_STDIN_FILENO);
 		opt_complementary = "w+:a::";
-		options = "w:H:U:P:Xt" "s:c:a:inf:";
+		options = "w:H:St" "s:c:a:iN:f:";
 		// body is pseudo attachment read from stdin
 		llist_add_to_end(&opt_attachments, (char *)"-");
 	} else {
 		// FETCHMAIL
 		opt_after_connect = NULL;
-		opt_complementary = "-1:w+:P";
-		options = "w:H:U:P:Xt" "z";
+		opt_complementary = "-1:w+";
+		options = "w:H:St" "z";
 	}
 	opts = getopt32(argv, options,
-		&timeout, &opt_connect, &opt_user, &opt_pass,
-		&opt_subject, &opt_charset, &opt_attachments, &opt_from
+		&timeout /* -w */, &opt_connect /* -H */,
+		&opt_subject, &opt_charset, &opt_attachments, NULL, &opt_from
 	);
 	//argc -= optind;
 	argv += optind;
@@ -326,8 +343,14 @@
 		if (!opt_connect)
 			opt_connect = "127.0.0.1";
 	}
+	// fetch username and password, if any
+	// NB: parse_url modifies opt_connect[] ONLY if '@' is there.
+	// Thus "127.0.0.1" won't be modified, an is ok that it is RO.
+	opt_connect = parse_url((char*)opt_connect, &opt_user, &opt_pass);
+//	bb_error_msg("H[%s] U[%s] P[%s]", opt_connect, opt_user, opt_pass);
+
 	// SSL ordered? ->
-	if (opts & OPT_X) {
+	if (opts & OPT_S) {
 		// ... use openssl helper
 		launch_helper(xargs);
 	// no SSL ordered? ->
@@ -340,10 +363,8 @@
 		xdup2(STDIN_FILENO, STDOUT_FILENO);
 	}
 
-#if ENABLE_FETCHMAIL
 	// are we sendmail?
-	if (opt_after_connect)
-#endif
+	if (!ENABLE_FETCHMAIL || opt_after_connect)
 /***************************************************
  * SENDMAIL
  ***************************************************/
@@ -364,7 +385,7 @@
 		}
 
 		// we didn't use SSL helper? ->
-		if (!(opts & OPT_X)) {
+		if (!(opts & OPT_S)) {
 			// ... wait for initial server OK
 			smtp_check(NULL, 220);
 		}
@@ -402,14 +423,13 @@
 		// set sender
 		// NOTE: if password has not been specified
 		// then no authentication is possible
-		code = (opts & OPT_P) ? -1 : 250;
+		code = (opt_pass) ? -1 : 250;
 		// first try softly without authentication
 		while (250 != smtp_checkp("MAIL FROM:<%s>", opt_from, code)) {
 			// MAIL FROM failed -> authentication needed
 			// have we got username?
-			if (!(opts & OPT_U)) {
+			if (!opt_user) {
 				// no! fetch it from "from" option
-				//opts |= OPT_U;
 				opt_user = xstrdup(opt_from);
 				*strchrnul(opt_user, '@') = '\0';
 			}
@@ -450,7 +470,7 @@
 		}
 
 		// put notification
-		if (opts & OPTS_n)
+		if (opts & OPTS_N)
 			printf("Disposition-Notification-To: %s\r\n", opt_from);
 
 		// make a random string -- it will delimit message parts
@@ -515,7 +535,6 @@
  * FETCHMAIL
  ***************************************************/
 	else {
-
 		char *buf;
 		unsigned nmsg;
 		char *hostname;
@@ -533,11 +552,14 @@
 		*fargs = *argv;
 
 		// authenticate
-		if (!(opts & OPT_U)) {
-			//opts |= OPT_U;
+		if (!opt_user) {
 			// N.B. IMHO getenv("USER") can be way easily spoofed!
 			opt_user = bb_getpwuid(NULL, -1, getuid());
 		}
+		// password is mandatory
+		if (!opt_pass) {
+			bb_error_msg_and_die("no password");
+		}
 
 		// get server greeting
 		pop3_checkr(NULL, NULL, &buf);