svn commit: trunk/busybox: include libbb networking

vda at busybox.net vda at busybox.net
Sat Aug 18 14:20:22 UTC 2007


Author: vda
Date: 2007-08-18 07:20:21 -0700 (Sat, 18 Aug 2007)
New Revision: 19555

Log:
make standalone httpd work on NOMMU machines



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


Changeset:
Modified: trunk/busybox/include/libbb.h
===================================================================
--- trunk/busybox/include/libbb.h	2007-08-18 14:18:43 UTC (rev 19554)
+++ trunk/busybox/include/libbb.h	2007-08-18 14:20:21 UTC (rev 19555)
@@ -587,10 +587,12 @@
 };
 #if BB_MMU
   void forkexit_or_rexec(void);
+  enum { re_execed = 0 };
 # define forkexit_or_rexec(argv)            forkexit_or_rexec()
 # define bb_daemonize_or_rexec(flags, argv) bb_daemonize_or_rexec(flags)
 # define bb_daemonize(flags)                bb_daemonize_or_rexec(flags, bogus)
 #else
+  void re_exec(char **argv) ATTRIBUTE_NORETURN;
   void forkexit_or_rexec(char **argv);
   extern bool re_execed;
 # define fork()          BUG_fork_is_unavailable_on_nommu()

Modified: trunk/busybox/libbb/vfork_daemon_rexec.c
===================================================================
--- trunk/busybox/libbb/vfork_daemon_rexec.c	2007-08-18 14:18:43 UTC (rev 19554)
+++ trunk/busybox/libbb/vfork_daemon_rexec.c	2007-08-18 14:20:21 UTC (rev 19555)
@@ -203,6 +203,15 @@
 }
 
 #if !BB_MMU
+void re_exec(char **argv)
+{
+	/* high-order bit of first char in argv[0] is a hidden
+	 * "we have (already) re-execed, don't do it again" flag */
+	argv[0][0] |= 0x80;
+	execv(bb_busybox_exec_path, argv);
+	bb_perror_msg_and_die("exec %s", bb_busybox_exec_path);
+}
+
 void forkexit_or_rexec(char **argv)
 {
 	pid_t pid;
@@ -216,11 +225,7 @@
 	if (pid) /* parent */
 		exit(0);
 	/* child - re-exec ourself */
-	/* high-order bit of first char in argv[0] is a hidden
-	 * "we have (alrealy) re-execed, don't do it again" flag */
-	argv[0][0] |= 0x80;
-	execv(bb_busybox_exec_path, argv);
-	bb_perror_msg_and_die("exec %s", bb_busybox_exec_path);
+	re_exec(argv);
 }
 #else
 /* Dance around (void)...*/

Modified: trunk/busybox/networking/httpd.c
===================================================================
--- trunk/busybox/networking/httpd.c	2007-08-18 14:18:43 UTC (rev 19554)
+++ trunk/busybox/networking/httpd.c	2007-08-18 14:20:21 UTC (rev 19555)
@@ -764,7 +764,6 @@
 /*
  * Create a listen server socket on the designated port.
  */
-#if BB_MMU
 static int openServer(void)
 {
 	int n = bb_strtou(bind_addr_or_port, NULL, 10);
@@ -775,7 +774,6 @@
 	xlisten(n, 9);
 	return n;
 }
-#endif
 
 /*
  * Log the connection closure and exit.
@@ -1474,8 +1472,8 @@
 /*
  * Handle an incoming http request and exit.
  */
-static void handle_incoming_and_exit(void) ATTRIBUTE_NORETURN;
-static void handle_incoming_and_exit(void)
+static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr) ATTRIBUTE_NORETURN;
+static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr)
 {
 	static const char request_GET[] ALIGN1 = "GET";
 
@@ -1497,6 +1495,22 @@
 	int credentials = -1;  /* if not required this is Ok */
 #endif
 
+	rmt_port = get_nport(&fromAddr->sa);
+	rmt_port = ntohs(rmt_port);
+	rmt_ip = 0;
+	if (fromAddr->sa.sa_family == AF_INET) {
+		rmt_ip = ntohl(fromAddr->sin.sin_addr.s_addr);
+	}
+	if (ENABLE_FEATURE_HTTPD_CGI || DEBUG || verbose) {
+		rmt_ip_str = xmalloc_sockaddr2dotted(&fromAddr->sa);
+	}
+	if (verbose) {
+		/* this trick makes -v logging much simpler */
+		applet_name = rmt_ip_str;
+		if (verbose > 2)
+			bb_error_msg("connected");
+	}
+
 	/* Install timeout handler */
 	memset(&sa, 0, sizeof(sa));
 	sa.sa_handler = exit_on_signal;
@@ -1772,13 +1786,13 @@
 #endif
 }
 
-#if BB_MMU
 /*
  * The main http server function.
- * Given an open socket, listen for new connections and farm out
- * the processing as a forked process.
+ * Given a socket, listen for new connections and farm out
+ * the processing as a [v]forked process.
  * Never returns.
  */
+#if BB_MMU
 static void mini_httpd(int server_socket) ATTRIBUTE_NORETURN;
 static void mini_httpd(int server_socket)
 {
@@ -1810,49 +1824,73 @@
 			xmove_fd(n, 0);
 			xdup2(0, 1);
 
-			n = get_nport(&fromAddr.sa);
-			rmt_port = ntohs(n);
-			rmt_ip = 0;
-			if (fromAddr.sa.sa_family == AF_INET) {
-				rmt_ip = ntohl(fromAddr.sin.sin_addr.s_addr);
-			}
-			if (ENABLE_FEATURE_HTTPD_CGI || DEBUG || verbose) {
-				rmt_ip_str = xmalloc_sockaddr2dotted(&fromAddr.sa);
-			}
-			if (verbose) {
-				/* this trick makes -v logging much simpler */
-				applet_name = rmt_ip_str;
-				if (verbose > 2)
-					bb_error_msg("connected");
-			}
-			handle_incoming_and_exit();
+			handle_incoming_and_exit(&fromAddr);
 		}
 		/* parent, or fork failed */
 		close(n);
 	} /* while (1) */
 	/* never reached */
 }
+#else
+static void mini_httpd_nommu(int server_socket, int argc, char **argv) ATTRIBUTE_NORETURN;
+static void mini_httpd_nommu(int server_socket, int argc, char **argv)
+{
+	char *argv_copy[argc + 2];
+
+	argv_copy[0] = argv[0];
+	argv_copy[1] = (char*)"-i";
+	memcpy(&argv_copy[2], &argv[1], argc * sizeof(argv[0]));
+
+	/* NB: it's best to not use xfuncs in this loop before vfork().
+	 * Otherwise server may die on transient errors (temporary
+	 * out-of-memory condition, etc), which is Bad(tm).
+	 * Try to do any dangerous calls after fork.
+	 */
+	while (1) {
+		int n;
+		len_and_sockaddr fromAddr;
+		
+		/* Wait for connections... */
+		fromAddr.len = LSA_SIZEOF_SA;
+		n = accept(server_socket, &fromAddr.sa, &fromAddr.len);
+
+		if (n < 0)
+			continue;
+		/* set the KEEPALIVE option to cull dead connections */
+		setsockopt(n, SOL_SOCKET, SO_KEEPALIVE, &const_int_1, sizeof(const_int_1));
+
+		if (vfork() == 0) {
+			/* child */
+#if ENABLE_FEATURE_HTTPD_RELOAD_CONFIG_SIGHUP
+			/* Do not reload config on HUP */
+			signal(SIGHUP, SIG_IGN);
 #endif
+			close(server_socket);
+			xmove_fd(n, 0);
+			xdup2(0, 1);
 
-/* from inetd */
+			/* Run a copy of ourself in inetd mode */
+			re_exec(argv_copy);
+		}
+		/* parent, or fork failed */
+		close(n);
+	} /* while (1) */
+	/* never reached */
+}
+#endif
+
+/*
+ * Process a HTTP connection on stdin/out.
+ * Never returns.
+ */
 static void mini_httpd_inetd(void) ATTRIBUTE_NORETURN;
 static void mini_httpd_inetd(void)
 {
-	int n;
 	len_and_sockaddr fromAddr;
 
 	fromAddr.len = LSA_SIZEOF_SA;
 	getpeername(0, &fromAddr.sa, &fromAddr.len);
-	n = get_nport(&fromAddr.sa);
-	rmt_port = ntohs(n);
-	rmt_ip = 0;
-	if (fromAddr.sa.sa_family == AF_INET) {
-		rmt_ip = ntohl(fromAddr.sin.sin_addr.s_addr);
-	}
-	if (ENABLE_FEATURE_HTTPD_CGI || DEBUG || verbose) {
-		rmt_ip_str = xmalloc_sockaddr2dotted(&fromAddr.sa);
-	}
-	handle_incoming_and_exit();
+	handle_incoming_and_exit(&fromAddr);
 }
 
 #if ENABLE_FEATURE_HTTPD_RELOAD_CONFIG_SIGHUP
@@ -1915,7 +1953,8 @@
 #endif
 
 	home_httpd = xrealloc_getcwd_or_warn(NULL);
-	opt_complementary = "vv"; /* counter */
+	/* -v counts, -i implies -f */
+	opt_complementary = "vv:if";
 	/* We do not "absolutize" path given by -h (home) opt.
 	 * If user gives relative path in -h, $SCRIPT_FILENAME can end up
 	 * relative too. */
@@ -1934,12 +1973,12 @@
 			, &verbose
 		);
 	if (opt & OPT_DECODE_URL) {
-		printf("%s", decodeString(url_for_decode, 1));
+		fputs(decodeString(url_for_decode, 1), stdout);
 		return 0;
 	}
 #if ENABLE_FEATURE_HTTPD_ENCODE_URL_STR
 	if (opt & OPT_ENCODE_URL) {
-		printf("%s", encodeString(url_for_encode));
+		fputs(encodeString(url_for_encode), stdout);
 		return 0;
 	}
 #endif
@@ -1957,9 +1996,14 @@
 	}
 #endif
 
+#if !BB_MMU
+	if (!(opt & OPT_FOREGROUND)) {
+		bb_daemonize_or_rexec(0, argv); /* don't change current directory */
+	}
+#endif
+
 	xchdir(home_httpd);
 	if (!(opt & OPT_INETD)) {
-#if BB_MMU
 		signal(SIGCHLD, SIG_IGN);
 		server_socket = openServer();
 #if ENABLE_FEATURE_HTTPD_SETUID
@@ -1973,9 +2017,6 @@
 			xsetuid(ugid.uid);
 		}
 #endif
-#else	/* BB_MMU */
-		bb_error_msg_and_die("-i is required");
-#endif
 	}
 
 #if ENABLE_FEATURE_HTTPD_CGI
@@ -1990,21 +2031,22 @@
 	}
 #endif
 
-#if BB_MMU
 #if ENABLE_FEATURE_HTTPD_RELOAD_CONFIG_SIGHUP
-	sighup_handler(0);
-#else
-	parse_conf(default_path_httpd_conf, FIRST_PARSE);
+	if (!(opt & OPT_INETD))
+		sighup_handler(0);
+	else /* do not install HUP handler in inetd mode */
 #endif
+		parse_conf(default_path_httpd_conf, FIRST_PARSE);
+
 	xfunc_error_retval = 0;
 	if (opt & OPT_INETD)
 		mini_httpd_inetd();
+#if BB_MMU
 	if (!(opt & OPT_FOREGROUND))
 		bb_daemonize(0); /* don't change current directory */
 	mini_httpd(server_socket); /* never returns */
 #else
-	xfunc_error_retval = 0;
-	mini_httpd_inetd(); /* never returns */
+	mini_httpd_nommu(server_socket, argc, argv); /* never returns */
+#endif
 	/* return 0; */
-#endif
 }




More information about the busybox-cvs mailing list