aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/libbb.h2
-rw-r--r--libbb/vfork_daemon_rexec.c15
-rw-r--r--networking/httpd.c140
3 files changed, 103 insertions, 54 deletions
diff --git a/include/libbb.h b/include/libbb.h
index 651c48ba1..2519aeb98 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -587,10 +587,12 @@ enum {
587}; 587};
588#if BB_MMU 588#if BB_MMU
589 void forkexit_or_rexec(void); 589 void forkexit_or_rexec(void);
590 enum { re_execed = 0 };
590# define forkexit_or_rexec(argv) forkexit_or_rexec() 591# define forkexit_or_rexec(argv) forkexit_or_rexec()
591# define bb_daemonize_or_rexec(flags, argv) bb_daemonize_or_rexec(flags) 592# define bb_daemonize_or_rexec(flags, argv) bb_daemonize_or_rexec(flags)
592# define bb_daemonize(flags) bb_daemonize_or_rexec(flags, bogus) 593# define bb_daemonize(flags) bb_daemonize_or_rexec(flags, bogus)
593#else 594#else
595 void re_exec(char **argv) ATTRIBUTE_NORETURN;
594 void forkexit_or_rexec(char **argv); 596 void forkexit_or_rexec(char **argv);
595 extern bool re_execed; 597 extern bool re_execed;
596# define fork() BUG_fork_is_unavailable_on_nommu() 598# define fork() BUG_fork_is_unavailable_on_nommu()
diff --git a/libbb/vfork_daemon_rexec.c b/libbb/vfork_daemon_rexec.c
index f7c620996..558510bc6 100644
--- a/libbb/vfork_daemon_rexec.c
+++ b/libbb/vfork_daemon_rexec.c
@@ -203,6 +203,15 @@ int spawn_and_wait(char **argv)
203} 203}
204 204
205#if !BB_MMU 205#if !BB_MMU
206void re_exec(char **argv)
207{
208 /* high-order bit of first char in argv[0] is a hidden
209 * "we have (already) re-execed, don't do it again" flag */
210 argv[0][0] |= 0x80;
211 execv(bb_busybox_exec_path, argv);
212 bb_perror_msg_and_die("exec %s", bb_busybox_exec_path);
213}
214
206void forkexit_or_rexec(char **argv) 215void forkexit_or_rexec(char **argv)
207{ 216{
208 pid_t pid; 217 pid_t pid;
@@ -216,11 +225,7 @@ void forkexit_or_rexec(char **argv)
216 if (pid) /* parent */ 225 if (pid) /* parent */
217 exit(0); 226 exit(0);
218 /* child - re-exec ourself */ 227 /* child - re-exec ourself */
219 /* high-order bit of first char in argv[0] is a hidden 228 re_exec(argv);
220 * "we have (alrealy) re-execed, don't do it again" flag */
221 argv[0][0] |= 0x80;
222 execv(bb_busybox_exec_path, argv);
223 bb_perror_msg_and_die("exec %s", bb_busybox_exec_path);
224} 229}
225#else 230#else
226/* Dance around (void)...*/ 231/* Dance around (void)...*/
diff --git a/networking/httpd.c b/networking/httpd.c
index d68dc06e9..cd46f49ef 100644
--- a/networking/httpd.c
+++ b/networking/httpd.c
@@ -764,7 +764,6 @@ static void decodeBase64(char *Data)
764/* 764/*
765 * Create a listen server socket on the designated port. 765 * Create a listen server socket on the designated port.
766 */ 766 */
767#if BB_MMU
768static int openServer(void) 767static int openServer(void)
769{ 768{
770 int n = bb_strtou(bind_addr_or_port, NULL, 10); 769 int n = bb_strtou(bind_addr_or_port, NULL, 10);
@@ -775,7 +774,6 @@ static int openServer(void)
775 xlisten(n, 9); 774 xlisten(n, 9);
776 return n; 775 return n;
777} 776}
778#endif
779 777
780/* 778/*
781 * Log the connection closure and exit. 779 * Log the connection closure and exit.
@@ -1474,8 +1472,8 @@ static void exit_on_signal(int sig)
1474/* 1472/*
1475 * Handle an incoming http request and exit. 1473 * Handle an incoming http request and exit.
1476 */ 1474 */
1477static void handle_incoming_and_exit(void) ATTRIBUTE_NORETURN; 1475static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr) ATTRIBUTE_NORETURN;
1478static void handle_incoming_and_exit(void) 1476static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr)
1479{ 1477{
1480 static const char request_GET[] ALIGN1 = "GET"; 1478 static const char request_GET[] ALIGN1 = "GET";
1481 1479
@@ -1497,6 +1495,22 @@ static void handle_incoming_and_exit(void)
1497 int credentials = -1; /* if not required this is Ok */ 1495 int credentials = -1; /* if not required this is Ok */
1498#endif 1496#endif
1499 1497
1498 rmt_port = get_nport(&fromAddr->sa);
1499 rmt_port = ntohs(rmt_port);
1500 rmt_ip = 0;
1501 if (fromAddr->sa.sa_family == AF_INET) {
1502 rmt_ip = ntohl(fromAddr->sin.sin_addr.s_addr);
1503 }
1504 if (ENABLE_FEATURE_HTTPD_CGI || DEBUG || verbose) {
1505 rmt_ip_str = xmalloc_sockaddr2dotted(&fromAddr->sa);
1506 }
1507 if (verbose) {
1508 /* this trick makes -v logging much simpler */
1509 applet_name = rmt_ip_str;
1510 if (verbose > 2)
1511 bb_error_msg("connected");
1512 }
1513
1500 /* Install timeout handler */ 1514 /* Install timeout handler */
1501 memset(&sa, 0, sizeof(sa)); 1515 memset(&sa, 0, sizeof(sa));
1502 sa.sa_handler = exit_on_signal; 1516 sa.sa_handler = exit_on_signal;
@@ -1772,13 +1786,13 @@ static void handle_incoming_and_exit(void)
1772#endif 1786#endif
1773} 1787}
1774 1788
1775#if BB_MMU
1776/* 1789/*
1777 * The main http server function. 1790 * The main http server function.
1778 * Given an open socket, listen for new connections and farm out 1791 * Given a socket, listen for new connections and farm out
1779 * the processing as a forked process. 1792 * the processing as a [v]forked process.
1780 * Never returns. 1793 * Never returns.
1781 */ 1794 */
1795#if BB_MMU
1782static void mini_httpd(int server_socket) ATTRIBUTE_NORETURN; 1796static void mini_httpd(int server_socket) ATTRIBUTE_NORETURN;
1783static void mini_httpd(int server_socket) 1797static void mini_httpd(int server_socket)
1784{ 1798{
@@ -1810,22 +1824,53 @@ static void mini_httpd(int server_socket)
1810 xmove_fd(n, 0); 1824 xmove_fd(n, 0);
1811 xdup2(0, 1); 1825 xdup2(0, 1);
1812 1826
1813 n = get_nport(&fromAddr.sa); 1827 handle_incoming_and_exit(&fromAddr);
1814 rmt_port = ntohs(n); 1828 }
1815 rmt_ip = 0; 1829 /* parent, or fork failed */
1816 if (fromAddr.sa.sa_family == AF_INET) { 1830 close(n);
1817 rmt_ip = ntohl(fromAddr.sin.sin_addr.s_addr); 1831 } /* while (1) */
1818 } 1832 /* never reached */
1819 if (ENABLE_FEATURE_HTTPD_CGI || DEBUG || verbose) { 1833}
1820 rmt_ip_str = xmalloc_sockaddr2dotted(&fromAddr.sa); 1834#else
1821 } 1835static void mini_httpd_nommu(int server_socket, int argc, char **argv) ATTRIBUTE_NORETURN;
1822 if (verbose) { 1836static void mini_httpd_nommu(int server_socket, int argc, char **argv)
1823 /* this trick makes -v logging much simpler */ 1837{
1824 applet_name = rmt_ip_str; 1838 char *argv_copy[argc + 2];
1825 if (verbose > 2) 1839
1826 bb_error_msg("connected"); 1840 argv_copy[0] = argv[0];
1827 } 1841 argv_copy[1] = (char*)"-i";
1828 handle_incoming_and_exit(); 1842 memcpy(&argv_copy[2], &argv[1], argc * sizeof(argv[0]));
1843
1844 /* NB: it's best to not use xfuncs in this loop before vfork().
1845 * Otherwise server may die on transient errors (temporary
1846 * out-of-memory condition, etc), which is Bad(tm).
1847 * Try to do any dangerous calls after fork.
1848 */
1849 while (1) {
1850 int n;
1851 len_and_sockaddr fromAddr;
1852
1853 /* Wait for connections... */
1854 fromAddr.len = LSA_SIZEOF_SA;
1855 n = accept(server_socket, &fromAddr.sa, &fromAddr.len);
1856
1857 if (n < 0)
1858 continue;
1859 /* set the KEEPALIVE option to cull dead connections */
1860 setsockopt(n, SOL_SOCKET, SO_KEEPALIVE, &const_int_1, sizeof(const_int_1));
1861
1862 if (vfork() == 0) {
1863 /* child */
1864#if ENABLE_FEATURE_HTTPD_RELOAD_CONFIG_SIGHUP
1865 /* Do not reload config on HUP */
1866 signal(SIGHUP, SIG_IGN);
1867#endif
1868 close(server_socket);
1869 xmove_fd(n, 0);
1870 xdup2(0, 1);
1871
1872 /* Run a copy of ourself in inetd mode */
1873 re_exec(argv_copy);
1829 } 1874 }
1830 /* parent, or fork failed */ 1875 /* parent, or fork failed */
1831 close(n); 1876 close(n);
@@ -1834,25 +1879,18 @@ static void mini_httpd(int server_socket)
1834} 1879}
1835#endif 1880#endif
1836 1881
1837/* from inetd */ 1882/*
1883 * Process a HTTP connection on stdin/out.
1884 * Never returns.
1885 */
1838static void mini_httpd_inetd(void) ATTRIBUTE_NORETURN; 1886static void mini_httpd_inetd(void) ATTRIBUTE_NORETURN;
1839static void mini_httpd_inetd(void) 1887static void mini_httpd_inetd(void)
1840{ 1888{
1841 int n;
1842 len_and_sockaddr fromAddr; 1889 len_and_sockaddr fromAddr;
1843 1890
1844 fromAddr.len = LSA_SIZEOF_SA; 1891 fromAddr.len = LSA_SIZEOF_SA;
1845 getpeername(0, &fromAddr.sa, &fromAddr.len); 1892 getpeername(0, &fromAddr.sa, &fromAddr.len);
1846 n = get_nport(&fromAddr.sa); 1893 handle_incoming_and_exit(&fromAddr);
1847 rmt_port = ntohs(n);
1848 rmt_ip = 0;
1849 if (fromAddr.sa.sa_family == AF_INET) {
1850 rmt_ip = ntohl(fromAddr.sin.sin_addr.s_addr);
1851 }
1852 if (ENABLE_FEATURE_HTTPD_CGI || DEBUG || verbose) {
1853 rmt_ip_str = xmalloc_sockaddr2dotted(&fromAddr.sa);
1854 }
1855 handle_incoming_and_exit();
1856} 1894}
1857 1895
1858#if ENABLE_FEATURE_HTTPD_RELOAD_CONFIG_SIGHUP 1896#if ENABLE_FEATURE_HTTPD_RELOAD_CONFIG_SIGHUP
@@ -1915,7 +1953,8 @@ int httpd_main(int argc, char **argv)
1915#endif 1953#endif
1916 1954
1917 home_httpd = xrealloc_getcwd_or_warn(NULL); 1955 home_httpd = xrealloc_getcwd_or_warn(NULL);
1918 opt_complementary = "vv"; /* counter */ 1956 /* -v counts, -i implies -f */
1957 opt_complementary = "vv:if";
1919 /* We do not "absolutize" path given by -h (home) opt. 1958 /* We do not "absolutize" path given by -h (home) opt.
1920 * If user gives relative path in -h, $SCRIPT_FILENAME can end up 1959 * If user gives relative path in -h, $SCRIPT_FILENAME can end up
1921 * relative too. */ 1960 * relative too. */
@@ -1934,12 +1973,12 @@ int httpd_main(int argc, char **argv)
1934 , &verbose 1973 , &verbose
1935 ); 1974 );
1936 if (opt & OPT_DECODE_URL) { 1975 if (opt & OPT_DECODE_URL) {
1937 printf("%s", decodeString(url_for_decode, 1)); 1976 fputs(decodeString(url_for_decode, 1), stdout);
1938 return 0; 1977 return 0;
1939 } 1978 }
1940#if ENABLE_FEATURE_HTTPD_ENCODE_URL_STR 1979#if ENABLE_FEATURE_HTTPD_ENCODE_URL_STR
1941 if (opt & OPT_ENCODE_URL) { 1980 if (opt & OPT_ENCODE_URL) {
1942 printf("%s", encodeString(url_for_encode)); 1981 fputs(encodeString(url_for_encode), stdout);
1943 return 0; 1982 return 0;
1944 } 1983 }
1945#endif 1984#endif
@@ -1957,9 +1996,14 @@ int httpd_main(int argc, char **argv)
1957 } 1996 }
1958#endif 1997#endif
1959 1998
1999#if !BB_MMU
2000 if (!(opt & OPT_FOREGROUND)) {
2001 bb_daemonize_or_rexec(0, argv); /* don't change current directory */
2002 }
2003#endif
2004
1960 xchdir(home_httpd); 2005 xchdir(home_httpd);
1961 if (!(opt & OPT_INETD)) { 2006 if (!(opt & OPT_INETD)) {
1962#if BB_MMU
1963 signal(SIGCHLD, SIG_IGN); 2007 signal(SIGCHLD, SIG_IGN);
1964 server_socket = openServer(); 2008 server_socket = openServer();
1965#if ENABLE_FEATURE_HTTPD_SETUID 2009#if ENABLE_FEATURE_HTTPD_SETUID
@@ -1973,9 +2017,6 @@ int httpd_main(int argc, char **argv)
1973 xsetuid(ugid.uid); 2017 xsetuid(ugid.uid);
1974 } 2018 }
1975#endif 2019#endif
1976#else /* BB_MMU */
1977 bb_error_msg_and_die("-i is required");
1978#endif
1979 } 2020 }
1980 2021
1981#if ENABLE_FEATURE_HTTPD_CGI 2022#if ENABLE_FEATURE_HTTPD_CGI
@@ -1990,21 +2031,22 @@ int httpd_main(int argc, char **argv)
1990 } 2031 }
1991#endif 2032#endif
1992 2033
1993#if BB_MMU
1994#if ENABLE_FEATURE_HTTPD_RELOAD_CONFIG_SIGHUP 2034#if ENABLE_FEATURE_HTTPD_RELOAD_CONFIG_SIGHUP
1995 sighup_handler(0); 2035 if (!(opt & OPT_INETD))
1996#else 2036 sighup_handler(0);
1997 parse_conf(default_path_httpd_conf, FIRST_PARSE); 2037 else /* do not install HUP handler in inetd mode */
1998#endif 2038#endif
2039 parse_conf(default_path_httpd_conf, FIRST_PARSE);
2040
1999 xfunc_error_retval = 0; 2041 xfunc_error_retval = 0;
2000 if (opt & OPT_INETD) 2042 if (opt & OPT_INETD)
2001 mini_httpd_inetd(); 2043 mini_httpd_inetd();
2044#if BB_MMU
2002 if (!(opt & OPT_FOREGROUND)) 2045 if (!(opt & OPT_FOREGROUND))
2003 bb_daemonize(0); /* don't change current directory */ 2046 bb_daemonize(0); /* don't change current directory */
2004 mini_httpd(server_socket); /* never returns */ 2047 mini_httpd(server_socket); /* never returns */
2005#else 2048#else
2006 xfunc_error_retval = 0; 2049 mini_httpd_nommu(server_socket, argc, argv); /* never returns */
2007 mini_httpd_inetd(); /* never returns */
2008 /* return 0; */
2009#endif 2050#endif
2051 /* return 0; */
2010} 2052}