svn commit: trunk/busybox: include libbb networking

vda at busybox.net vda at busybox.net
Tue Aug 14 16:55:01 UTC 2007


Author: vda
Date: 2007-08-14 09:55:01 -0700 (Tue, 14 Aug 2007)
New Revision: 19509

Log:
httpd: add -v[v]: prints client addresses, HTTP codes returned [and URLs]

get_line                                               -      70     +70
packed_usage                                       22811   22863     +52
handle_incoming_and_exit                            2246    2277     +31
httpd_main                                          1141    1155     +14
sendHeaders                                          489     482      -7
getLine                                               77       -     -77
------------------------------------------------------------------------------
(add/remove: 1/1 grow/shrink: 3/1 up/down: 167/-84)            Total: 83 bytes
   text    data     bss     dec     hex filename
 774335    1058   11092  786485   c0035 busybox_old
 774447    1058   11092  786597   c00a5 busybox_unstripped



Modified:
   trunk/busybox/include/usage.h
   trunk/busybox/libbb/xfuncs.c
   trunk/busybox/networking/httpd.c


Changeset:
Modified: trunk/busybox/include/usage.h
===================================================================
--- trunk/busybox/include/usage.h	2007-08-14 16:50:01 UTC (rev 19508)
+++ trunk/busybox/include/usage.h	2007-08-14 16:55:01 UTC (rev 19509)
@@ -1344,8 +1344,8 @@
 
 #define httpd_trivial_usage \
        "[-c conffile]" \
-       " [-p port]" \
-       " [-i] [-f]" \
+       " [-p [ip:]port]" \
+       " [-i] [-f] [-v[v]]" \
 	USE_FEATURE_HTTPD_SETUID(" [-u user[:grp]]") \
 	USE_FEATURE_HTTPD_BASIC_AUTH(" [-r realm]") \
 	USE_FEATURE_HTTPD_AUTH_MD5(" [-m pass]") \
@@ -1355,9 +1355,10 @@
        "Listen for incoming HTTP requests" \
        "\n\nOptions:" \
        "\n	-c FILE		Configuration file (default httpd.conf)" \
-       "\n	-p PORT		Server port (default 80)" \
+       "\n	-p [IP:]PORT	Bind to ip:port (default *:80)" \
        "\n	-i		Inetd mode" \
        "\n	-f		Do not daemonize" \
+       "\n	-v[v]		Verbose" \
 	USE_FEATURE_HTTPD_SETUID( \
        "\n	-u USER[:GRP]	Set uid/gid after binding to port") \
 	USE_FEATURE_HTTPD_BASIC_AUTH( \
@@ -1366,7 +1367,7 @@
        "\n	-m PASS		Crypt PASS with md5 algorithm") \
        "\n	-h HOME		Home directory (default .)" \
        "\n	-e STRING	HTML encode STRING" \
-       "\n	-d STRING	URL decode STRING"
+       "\n	-d STRING	URL decode STRING" \
 
 #define hwclock_trivial_usage \
        "[-r|--show] [-s|--hctosys] [-w|--systohc]" \

Modified: trunk/busybox/libbb/xfuncs.c
===================================================================
--- trunk/busybox/libbb/xfuncs.c	2007-08-14 16:50:01 UTC (rev 19508)
+++ trunk/busybox/libbb/xfuncs.c	2007-08-14 16:55:01 UTC (rev 19509)
@@ -484,12 +484,14 @@
 #else
 	// Bloat for systems that haven't got the GNU extension.
 	va_start(p, format);
-	r = vsnprintf(NULL, 0, format, p);
+	r = vsnprintf(NULL, 0, format, p) + 1;
 	va_end(p);
-	string_ptr = xmalloc(r+1);
-	va_start(p, format);
-	r = vsnprintf(string_ptr, r+1, format, p);
-	va_end(p);
+	string_ptr = malloc(r);
+	if (string_ptr) {
+		va_start(p, format);
+		r = vsnprintf(string_ptr, r, format, p);
+		va_end(p);
+	}
 #endif
 
 	if (r >= 0) {

Modified: trunk/busybox/networking/httpd.c
===================================================================
--- trunk/busybox/networking/httpd.c	2007-08-14 16:50:01 UTC (rev 19508)
+++ trunk/busybox/networking/httpd.c	2007-08-14 16:55:01 UTC (rev 19509)
@@ -132,17 +132,22 @@
 struct globals {
 	int server_socket;
 	int accepted_socket;
+	int verbose;
 	volatile smallint alarm_signaled;
 	smallint flg_deny_all;
+
+	unsigned rmt_ip;
+	unsigned tcp_port;       /* for set env REMOTE_PORT */
+	const char *bind_addr_or_port;
+
 	const char *g_query;
 	const char *configFile;
 	const char *home_httpd;
-	unsigned rmt_ip;
 
 	const char *found_mime_type;
 	const char *found_moved_temporarily;
-	off_t ContentLength;          /* -1 - unknown */
 	time_t last_mod;
+	off_t ContentLength;          /* -1 - unknown */
 	Htaccess_IP *ip_a_d;          /* config allow/deny lines */
 
 	USE_FEATURE_HTTPD_BASIC_AUTH(const char *g_realm;)
@@ -150,11 +155,7 @@
 	USE_FEATURE_HTTPD_CGI(char *referer;)
 	USE_FEATURE_HTTPD_CGI(char *user_agent;)
 
-#if ENABLE_FEATURE_HTTPD_CGI || DEBUG
 	char *rmt_ip_str;        /* for set env REMOTE_ADDR */
-#endif
-	const char *bind_addr_or_port;
-	unsigned tcp_port;       /* for set env REMOTE_PORT */
 
 #if ENABLE_FEATURE_HTTPD_BASIC_AUTH
 	Htaccess *g_auth;        /* config user:password lines */
@@ -168,38 +169,31 @@
 	char iobuf[MAX_MEMORY_BUF];
 };
 #define G (*ptr_to_globals)
-#define server_socket   (G.server_socket  )
-#define accepted_socket (G.accepted_socket)
-#define alarm_signaled  (G.alarm_signaled )
-#define flg_deny_all    (G.flg_deny_all   )
-#define g_query         (G.g_query        )
-#define configFile      (G.configFile     )
-#define home_httpd      (G.home_httpd     )
-#define rmt_ip          (G.rmt_ip         )
-#define found_mime_type (G.found_mime_type)
-#define found_moved_temporarily (G.found_moved_temporarily)
-#define ContentLength   (G.ContentLength  )
-#define last_mod        (G.last_mod       )
-#define ip_a_d          (G.ip_a_d         )
-#define g_realm         (G.g_realm        )
-#define remoteuser      (G.remoteuser     )
-#define referer         (G.referer        )
-#define user_agent      (G.user_agent     )
-#if ENABLE_FEATURE_HTTPD_CGI || DEBUG
-#define rmt_ip_str      (G.rmt_ip_str     )
-#endif
+#define server_socket     (G.server_socket    )
+#define accepted_socket   (G.accepted_socket  )
+#define verbose           (G.verbose          )
+#define alarm_signaled    (G.alarm_signaled   )
+#define flg_deny_all      (G.flg_deny_all     )
+#define rmt_ip            (G.rmt_ip           )
+#define tcp_port          (G.tcp_port         )
 #define bind_addr_or_port (G.bind_addr_or_port)
-#define tcp_port        (G.tcp_port       )
-#if ENABLE_FEATURE_HTTPD_BASIC_AUTH
-#define g_auth          (G.g_auth         )
-#endif
-#if ENABLE_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES
-#define mime_a          (G.mime_a         )
-#endif
-#if ENABLE_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR
-#define script_i        (G.script_i       )
-#endif
-#define iobuf           (G.iobuf          )
+#define g_query           (G.g_query          )
+#define configFile        (G.configFile       )
+#define home_httpd        (G.home_httpd       )
+#define found_mime_type   (G.found_mime_type  )
+#define found_moved_temporarily (G.found_moved_temporarily)
+#define ContentLength     (G.ContentLength    )
+#define last_mod          (G.last_mod         )
+#define ip_a_d            (G.ip_a_d           )
+#define g_realm           (G.g_realm          )
+#define remoteuser        (G.remoteuser       )
+#define referer           (G.referer          )
+#define user_agent        (G.user_agent       )
+#define rmt_ip_str        (G.rmt_ip_str       )
+#define g_auth            (G.g_auth           )
+#define mime_a            (G.mime_a           )
+#define script_i          (G.script_i         )
+#define iobuf             (G.iobuf            )
 #define INIT_G() do { \
 	PTR_TO_GLOBALS = xzalloc(sizeof(G)); \
 	USE_FEATURE_HTTPD_BASIC_AUTH(g_realm = "Web Server Authentication";) \
@@ -210,7 +204,7 @@
 static const char request_GET[] ALIGN1 = "GET";    /* size algorithmic optimize */
 
 static const char *const suffixTable[] = {
-/* Warning: shorted equivalent suffix in one line must be first */
+/* Warning: shorter equivalent suffix in one line must be first */
 	".htm.html", "text/html",
 	".jpg.jpeg", "image/jpeg",
 	".gif", "image/gif",
@@ -780,24 +774,14 @@
 #endif
 
 #if ENABLE_FEATURE_HTTPD_BASIC_AUTH
-/****************************************************************************
- *
- > $Function: decodeBase64()
- *
- > $Description: Decode a base 64 data stream as per rfc1521.
- *    Note that the rfc states that none base64 chars are to be ignored.
- *    Since the decode always results in a shorter size than the input, it is
- *    OK to pass the input arg as an output arg.
- *
- * $Parameter:
- *      (char *) Data . . . . A pointer to a base64 encoded string.
- *                            Where to place the decoded data.
- *
- * $Return: void
- *
- * $Errors: None
- *
- ****************************************************************************/
+/*
+ * Decode a base 64 data stream as per rfc1521.
+ * Note that the rfc states that non base64 chars are to be ignored.
+ * Since the decode always results in a shorter size than the input, it is
+ * OK to pass the input arg as an output arg.
+ * Parameter: a pointer to a base64 encoded string.
+ * Decoded data is stored in-place.
+ */
 static void decodeBase64(char *Data)
 {
 	const unsigned char *in = (const unsigned char *)Data;
@@ -871,13 +855,12 @@
  */
 static int sendHeaders(HttpResponseNum responseNum)
 {
-	char *const buf = iobuf; // dont really need it?
 	const char *responseString = "";
-	const char *infoString = 0;
+	const char *infoString = NULL;
 	const char *mime_type;
 	unsigned i;
 	time_t timer = time(0);
-	char timeStr[80];
+	char tmp_str[80];
 	int len;
 
 	for (i = 0; i < ARRAY_SIZE(httpResponseNames); i++) {
@@ -891,54 +874,60 @@
 	mime_type = responseNum == HTTP_OK ?
 				found_mime_type : "text/html";
 
+	if (verbose)
+		write(2, iobuf, sprintf(iobuf, "%s response:%u\n", rmt_ip_str, responseNum));
+
 	/* emit the current date */
-	strftime(timeStr, sizeof(timeStr), RFC1123FMT, gmtime(&timer));
-	len = sprintf(buf,
+	strftime(tmp_str, sizeof(tmp_str), RFC1123FMT, gmtime(&timer));
+	len = sprintf(iobuf,
 			"HTTP/1.0 %d %s\r\nContent-type: %s\r\n"
 			"Date: %s\r\nConnection: close\r\n",
-			responseNum, responseString, mime_type, timeStr);
+			responseNum, responseString, mime_type, tmp_str);
 
 #if ENABLE_FEATURE_HTTPD_BASIC_AUTH
 	if (responseNum == HTTP_UNAUTHORIZED) {
-		len += sprintf(buf+len,
+		len += sprintf(iobuf + len,
 				"WWW-Authenticate: Basic realm=\"%s\"\r\n",
 				g_realm);
 	}
 #endif
 	if (responseNum == HTTP_MOVED_TEMPORARILY) {
-		len += sprintf(buf+len, "Location: %s/%s%s\r\n",
+		len += sprintf(iobuf + len, "Location: %s/%s%s\r\n",
 				found_moved_temporarily,
 				(g_query ? "?" : ""),
 				(g_query ? g_query : ""));
 	}
 
 	if (ContentLength != -1) {    /* file */
-		strftime(timeStr, sizeof(timeStr), RFC1123FMT, gmtime(&last_mod));
-		len += sprintf(buf+len, "Last-Modified: %s\r\n%s %"OFF_FMT"d\r\n",
-			timeStr, "Content-length:", ContentLength);
+		strftime(tmp_str, sizeof(tmp_str), RFC1123FMT, gmtime(&last_mod));
+		len += sprintf(iobuf + len, "Last-Modified: %s\r\n%s %"OFF_FMT"d\r\n",
+			tmp_str, "Content-length:", ContentLength);
 	}
-	strcat(buf, "\r\n");
+	strcat(iobuf, "\r\n");
 	len += 2;
 	if (infoString) {
-		len += sprintf(buf+len,
+		len += sprintf(iobuf + len,
 				"<HTML><HEAD><TITLE>%d %s</TITLE></HEAD>\n"
 				"<BODY><H1>%d %s</H1>\n%s\n</BODY></HTML>\n",
 				responseNum, responseString,
 				responseNum, responseString, infoString);
 	}
 	if (DEBUG)
-		fprintf(stderr, "headers: '%s'\n", buf);
+		fprintf(stderr, "headers: '%s'\n", iobuf);
 	i = accepted_socket;
-	if (i == 0) i++; /* write to fd #1 in inetd mode */
-	return full_write(i, buf, len);
+	if (i == 0)
+		i++; /* write to fd #1 in inetd mode */
+	return full_write(i, iobuf, len);
 }
 
 /*
  * Read from the socket until '\n' or EOF. '\r' chars are removed.
- * Return number of characters read or -1 if nothing is read.
+ * '\n' is replaced with NUL.
+ * Return number of characters read or 0 if nothing is read
+ * ('\r' and '\n' are not counted).
  * Data is returned in iobuf.
  */
-static int getLine(void)
+static int get_line(void)
 {
 	int count = 0;
 
@@ -953,9 +942,7 @@
 		if (count < (MAX_MEMORY_BUF - 1))      /* check overflow */
 			count++;
 	}
-	if (count)
-		return count;
-	return -1;
+	return count;
 }
 
 #if ENABLE_FEATURE_HTTPD_CGI
@@ -1414,11 +1401,10 @@
 
 	/* This could stand some work */
 	for (cur = ip_a_d; cur; cur = cur->next) {
-#if ENABLE_FEATURE_HTTPD_CGI && DEBUG
-		fprintf(stderr, "checkPermIP: '%s' ? ", rmt_ip_str);
-#endif
 #if DEBUG
-		fprintf(stderr, "'%u.%u.%u.%u/%u.%u.%u.%u'\n",
+		fprintf(stderr,
+			"checkPermIP: '%s' ? '%u.%u.%u.%u/%u.%u.%u.%u'\n",
+			rmt_ip_str,
 			(unsigned char)(cur->ip >> 24),
 			(unsigned char)(cur->ip >> 16),
 			(unsigned char)(cur->ip >> 8),
@@ -1539,7 +1525,6 @@
 static void handle_incoming_and_exit(void) ATTRIBUTE_NORETURN;
 static void handle_incoming_and_exit(void)
 {
-	char *buf = iobuf;
 	char *url;
 	char *purl;
 	int blank = -1;
@@ -1569,10 +1554,10 @@
 		int count;
 
 		alarm(TIMEOUT);
-		if (getLine() <= 0)
-			break;  /* closed */
+		if (!get_line())
+			break;  /* EOF or error or empty line */
 
-		purl = strpbrk(buf, " \t");
+		purl = strpbrk(iobuf, " \t");
 		if (purl == NULL) {
  BAD_REQUEST:
 			sendHeaders(HTTP_BAD_REQUEST);
@@ -1580,32 +1565,32 @@
 		}
 		*purl = '\0';
 #if ENABLE_FEATURE_HTTPD_CGI
-		if (strcasecmp(buf, prequest) != 0) {
+		if (strcasecmp(iobuf, prequest) != 0) {
 			prequest = "POST";
-			if (strcasecmp(buf, prequest) != 0) {
+			if (strcasecmp(iobuf, prequest) != 0) {
 				sendHeaders(HTTP_NOT_IMPLEMENTED);
 				break;
 			}
 		}
 #else
-		if (strcasecmp(buf, request_GET) != 0) {
+		if (strcasecmp(iobuf, request_GET) != 0) {
 			sendHeaders(HTTP_NOT_IMPLEMENTED);
 			break;
 		}
 #endif
 		*purl = ' ';
-		count = sscanf(purl, " %[^ ] HTTP/%d.%*d", buf, &blank);
+		count = sscanf(purl, " %[^ ] HTTP/%d.%*d", iobuf, &blank);
 
-		if (count < 1 || buf[0] != '/') {
+		if (count < 1 || iobuf[0] != '/') {
 			/* Garbled request/URL */
 			goto BAD_REQUEST;
 		}
-		url = alloca(strlen(buf) + sizeof("/index.html"));
+		url = alloca(strlen(iobuf) + sizeof("/index.html"));
 		if (url == NULL) {
 			sendHeaders(HTTP_INTERNAL_SERVER_ERROR);
 			break;
 		}
-		strcpy(url, buf);
+		strcpy(url, iobuf);
 		/* extract url args if present */
 		test = strchr(url, '?');
 		g_query = NULL;
@@ -1641,7 +1626,7 @@
 					if (test[1] == '.' && (test[2] == '/' || !test[2])) {
 						++test;
 						if (purl == url) {
-							/* protect out root */
+							/* protect root */
 							goto BAD_REQUEST;
 						}
 						while (*--purl != '/') /* omit previous dir */;
@@ -1660,8 +1645,11 @@
 				found_moved_temporarily = url;
 			}
 		}
-		if (DEBUG)
-			fprintf(stderr, "url='%s', args=%s\n", url, g_query);
+		if (verbose > 1) {
+			/* Hopefully does it with single write[v] */
+			/* (uclibc does, glibc: ?) */
+			fdprintf(2, "%s url:%s\n", rmt_ip_str, url);
+		}
 
 		test = url;
 		ip_allowed = checkPermIP();
@@ -1679,18 +1667,18 @@
 			/* read until blank line for HTTP version specified, else parse immediate */
 			while (1) {
 				alarm(TIMEOUT);
-				if (getLine() <= 0)
-					break;
+				if (!get_line())
+					break; /* EOF or error or empty line */
 
 				if (DEBUG)
-					fprintf(stderr, "header: '%s'\n", buf);
+					fprintf(stderr, "header: '%s'\n", iobuf);
 
 #if ENABLE_FEATURE_HTTPD_CGI
 				/* try and do our best to parse more lines */
-				if ((STRNCASECMP(buf, "Content-length:") == 0)) {
+				if ((STRNCASECMP(iobuf, "Content-length:") == 0)) {
 					/* extra read only for POST */
 					if (prequest != request_GET) {
-						test = buf + sizeof("Content-length:") - 1;
+						test = iobuf + sizeof("Content-length:") - 1;
 						if (!test[0])
 							goto bail_out;
 						errno = 0;
@@ -1702,24 +1690,24 @@
 						if (test[0] || errno || length > INT_MAX)
 							goto bail_out;
 					}
-				} else if (STRNCASECMP(buf, "Cookie:") == 0) {
-					cookie = strdup(skip_whitespace(buf + sizeof("Cookie:")-1));
-				} else if (STRNCASECMP(buf, "Content-Type:") == 0) {
-					content_type = strdup(skip_whitespace(buf + sizeof("Content-Type:")-1));
-				} else if (STRNCASECMP(buf, "Referer:") == 0) {
-					referer = strdup(skip_whitespace(buf + sizeof("Referer:")-1));
-				} else if (STRNCASECMP(buf, "User-Agent:") == 0) {
-					user_agent = strdup(skip_whitespace(buf + sizeof("User-Agent:")-1));
+				} else if (STRNCASECMP(iobuf, "Cookie:") == 0) {
+					cookie = strdup(skip_whitespace(iobuf + sizeof("Cookie:")-1));
+				} else if (STRNCASECMP(iobuf, "Content-Type:") == 0) {
+					content_type = strdup(skip_whitespace(iobuf + sizeof("Content-Type:")-1));
+				} else if (STRNCASECMP(iobuf, "Referer:") == 0) {
+					referer = strdup(skip_whitespace(iobuf + sizeof("Referer:")-1));
+				} else if (STRNCASECMP(iobuf, "User-Agent:") == 0) {
+					user_agent = strdup(skip_whitespace(iobuf + sizeof("User-Agent:")-1));
 				}
 #endif
 
 #if ENABLE_FEATURE_HTTPD_BASIC_AUTH
-				if (STRNCASECMP(buf, "Authorization:") == 0) {
+				if (STRNCASECMP(iobuf, "Authorization:") == 0) {
 					/* We only allow Basic credentials.
 					 * It shows up as "Authorization: Basic <userid:password>" where
 					 * the userid:password is base64 encoded.
 					 */
-					test = skip_whitespace(buf + sizeof("Authorization:")-1);
+					test = skip_whitespace(iobuf + sizeof("Authorization:")-1);
 					if (STRNCASECMP(test, "Basic") != 0)
 						continue;
 					test += sizeof("Basic")-1;
@@ -1762,7 +1750,7 @@
 
 #if ENABLE_FEATURE_HTTPD_CGI
 		if (strncmp(test, "cgi-bin", 7) == 0) {
-			if (test[7] == '/' && test[8] == 0)
+			if (test[7] == '/' && test[8] == '\0')
 				goto FORBIDDEN;     /* protect listing cgi-bin/ */
 			sendCgi(url, prequest, length, cookie, content_type);
 			break;
@@ -1839,7 +1827,7 @@
 		tv.tv_sec = 2;
 		tv.tv_usec = 0;
 		retval = select(accepted_socket + 1, &s_fd, NULL, NULL, &tv);
-	} while (retval > 0 && read(accepted_socket, buf, sizeof(iobuf) > 0));
+	} while (retval > 0 && read(accepted_socket, iobuf, sizeof(iobuf) > 0));
 	shutdown(accepted_socket, SHUT_RD);
 	close(accepted_socket);
 	exit(0);
@@ -1883,13 +1871,12 @@
 		accepted_socket = s;
 		rmt_ip = 0;
 		tcp_port = 0;
-#if ENABLE_FEATURE_HTTPD_CGI || DEBUG
-		free(rmt_ip_str);
-		rmt_ip_str = xmalloc_sockaddr2dotted(&fromAddr.sa, fromAddrLen);
-#if DEBUG
-		bb_error_msg("connection from '%s'", rmt_ip_str);
-#endif
-#endif /* FEATURE_HTTPD_CGI */
+		if (verbose || ENABLE_FEATURE_HTTPD_CGI || DEBUG) {
+			free(rmt_ip_str);
+			rmt_ip_str = xmalloc_sockaddr2dotted(&fromAddr.sa, fromAddrLen);
+			if (DEBUG)
+				bb_error_msg("connection from '%s'", rmt_ip_str);
+		}
 		if (fromAddr.sa.sa_family == AF_INET) {
 			rmt_ip = ntohl(fromAddr.sin.sin_addr.s_addr);
 			tcp_port = ntohs(fromAddr.sin.sin_port);
@@ -1932,10 +1919,10 @@
 	getpeername(0, &fromAddr.sa, &fromAddrLen);
 	rmt_ip = 0;
 	tcp_port = 0;
-#if ENABLE_FEATURE_HTTPD_CGI || DEBUG
-	free(rmt_ip_str);
-	rmt_ip_str = xmalloc_sockaddr2dotted(&fromAddr.sa, fromAddrLen);
-#endif
+	if (verbose || ENABLE_FEATURE_HTTPD_CGI || DEBUG) {
+		free(rmt_ip_str);
+		rmt_ip_str = xmalloc_sockaddr2dotted(&fromAddr.sa, fromAddrLen);
+	}
 	if (fromAddr.sa.sa_family == AF_INET) {
 		rmt_ip = ntohl(fromAddr.sin.sin_addr.s_addr);
 		tcp_port = ntohs(fromAddr.sin.sin_port);
@@ -1974,6 +1961,7 @@
 	p_opt_port      ,
 	p_opt_inetd     ,
 	p_opt_foreground,
+	p_opt_verbose   ,
 	OPT_CONFIG_FILE = 1 << c_opt_config_file,
 	OPT_DECODE_URL  = 1 << d_opt_decode_url,
 	OPT_HOME_HTTPD  = 1 << h_opt_home_httpd,
@@ -1984,6 +1972,7 @@
 	OPT_PORT        = 1 << p_opt_port,
 	OPT_INETD       = 1 << p_opt_inetd,
 	OPT_FOREGROUND  = 1 << p_opt_foreground,
+	OPT_VERBOSE     = 1 << p_opt_verbose,
 };
 
 
@@ -2004,6 +1993,7 @@
 
 	INIT_G();
 	home_httpd = xrealloc_getcwd_or_warn(NULL);
+	opt_complementary = "vv"; /* counter */
 	/* We do not "absolutize" path given by -h (home) opt.
 	 * If user gives relative path in -h, $SCRIPT_FILENAME can end up
 	 * relative too. */
@@ -2012,13 +2002,14 @@
 			USE_FEATURE_HTTPD_BASIC_AUTH("r:")
 			USE_FEATURE_HTTPD_AUTH_MD5("m:")
 			USE_FEATURE_HTTPD_SETUID("u:")
-			"p:if",
-			&(configFile), &url_for_decode, &home_httpd
+			"p:ifv",
+			&configFile, &url_for_decode, &home_httpd
 			USE_FEATURE_HTTPD_ENCODE_URL_STR(, &url_for_encode)
 			USE_FEATURE_HTTPD_BASIC_AUTH(, &g_realm)
 			USE_FEATURE_HTTPD_AUTH_MD5(, &pass)
 			USE_FEATURE_HTTPD_SETUID(, &s_ugid)
 			, &bind_addr_or_port
+			, &verbose
 		);
 	if (opt & OPT_DECODE_URL) {
 		printf("%s", decodeString(url_for_decode, 1));
@@ -2036,7 +2027,6 @@
 		return 0;
 	}
 #endif
-
 #if ENABLE_FEATURE_HTTPD_SETUID
 	if (opt & OPT_SETUID) {
 		if (!get_uidgid(&ugid, s_ugid, 1))




More information about the busybox-cvs mailing list