aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2007-08-17 19:21:12 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2007-08-17 19:21:12 +0000
commitb98c26ad684e3aed8f1480458737f1ab90477c9e (patch)
tree4e69e135c31c613093c2d34e7d754854c31b781b
parentfeac3ce8c00cde26cf081ec7a8566498364d834b (diff)
downloadbusybox-w32-b98c26ad684e3aed8f1480458737f1ab90477c9e.tar.gz
busybox-w32-b98c26ad684e3aed8f1480458737f1ab90477c9e.tar.bz2
busybox-w32-b98c26ad684e3aed8f1480458737f1ab90477c9e.zip
httpd shrink and logging update, part 7 of 7
text data bss dec hex filename 9836 0 0 9836 266c busybox.t1/networking/httpd.o.orig 9724 0 0 9724 25fc busybox.t2/networking/httpd.o 9657 0 0 9657 25b9 busybox.t3/networking/httpd.o 9342 0 0 9342 247e busybox.t4/networking/httpd.o 9342 0 0 9342 247e busybox.t5/networking/httpd.o 9262 0 0 9262 242e busybox.t6/networking/httpd.o 9283 0 0 9283 2443 busybox.t7/networking/httpd.o 9334 0 0 9334 2476 busybox.t8/networking/httpd.o
-rw-r--r--networking/httpd.c211
1 files changed, 104 insertions, 107 deletions
diff --git a/networking/httpd.c b/networking/httpd.c
index 32ecde0b8..a57504bac 100644
--- a/networking/httpd.c
+++ b/networking/httpd.c
@@ -934,43 +934,108 @@ static void send_cgi_and_exit(
934{ 934{
935 struct { int rd; int wr; } fromCgi; /* CGI -> httpd pipe */ 935 struct { int rd; int wr; } fromCgi; /* CGI -> httpd pipe */
936 struct { int rd; int wr; } toCgi; /* httpd -> CGI pipe */ 936 struct { int rd; int wr; } toCgi; /* httpd -> CGI pipe */
937 char *argp[] = { NULL, NULL }; 937 char *fullpath;
938 int pid = 0; 938 char *script;
939 char *purl;
940 size_t post_read_size, post_read_idx;
939 int buf_count; 941 int buf_count;
940 int status; 942 int status;
941 size_t post_read_size, post_read_idx; 943 int pid = 0;
944 int sv_accepted_socket = accepted_socket;
945
946 /*
947 * We are mucking with environment _first_ and then vfork/exec,
948 * this allows us to use vfork safely. Parent don't care about
949 * these environment changes anyway.
950 */
951
952 /*
953 * Find PATH_INFO.
954 */
955 purl = xstrdup(url);
956 script = purl;
957 while ((script = strchr(script + 1, '/')) != NULL) {
958 /* have script.cgi/PATH_INFO or dirs/script.cgi[/PATH_INFO] */
959 struct stat sb;
960
961 *script = '\0';
962 if (!is_directory(purl + 1, 1, &sb)) {
963 /* not directory, found script.cgi/PATH_INFO */
964 *script = '/';
965 break;
966 }
967 *script = '/'; /* is directory, find next '/' */
968 }
969 setenv1("PATH_INFO", script); /* set /PATH_INFO or "" */
970 setenv1("REQUEST_METHOD", request);
971 if (g_query) {
972 putenv(xasprintf("%s=%s?%s", "REQUEST_URI", purl, g_query));
973 } else {
974 setenv1("REQUEST_URI", purl);
975 }
976 if (script != NULL)
977 *script = '\0'; /* cut off /PATH_INFO */
978
979 /* SCRIPT_FILENAME required by PHP in CGI mode */
980 fullpath = concat_path_file(home_httpd, purl);
981 setenv1("SCRIPT_FILENAME", fullpath);
982 /* set SCRIPT_NAME as full path: /cgi-bin/dirs/script.cgi */
983 setenv1("SCRIPT_NAME", purl);
984 /* http://hoohoo.ncsa.uiuc.edu/cgi/env.html:
985 * QUERY_STRING: The information which follows the ? in the URL
986 * which referenced this script. This is the query information.
987 * It should not be decoded in any fashion. This variable
988 * should always be set when there is query information,
989 * regardless of command line decoding. */
990 /* (Older versions of bbox seem to do some decoding) */
991 setenv1("QUERY_STRING", g_query);
992 putenv((char*)"SERVER_SOFTWARE=busybox httpd/"BB_VER);
993 putenv((char*)"SERVER_PROTOCOL=HTTP/1.0");
994 putenv((char*)"GATEWAY_INTERFACE=CGI/1.1");
995 /* Having _separate_ variables for IP and port defeats
996 * the purpose of having socket abstraction. Which "port"
997 * are you using on Unix domain socket?
998 * IOW - REMOTE_PEER="1.2.3.4:56" makes much more sense.
999 * Oh well... */
1000 {
1001 char *p = rmt_ip_str ? rmt_ip_str : (char*)"";
1002 char *cp = strrchr(p, ':');
1003 if (ENABLE_FEATURE_IPV6 && cp && strchr(cp, ']'))
1004 cp = NULL;
1005 if (cp) *cp = '\0'; /* delete :PORT */
1006 setenv1("REMOTE_ADDR", p);
1007 if (cp) *cp = ':';
1008 }
1009 setenv1("HTTP_USER_AGENT", user_agent);
1010#if ENABLE_FEATURE_HTTPD_SET_REMOTE_PORT_TO_ENV
1011 setenv_long("REMOTE_PORT", tcp_port);
1012#endif
1013 if (bodyLen)
1014 setenv_long("CONTENT_LENGTH", bodyLen);
1015 if (cookie)
1016 setenv1("HTTP_COOKIE", cookie);
1017 if (content_type)
1018 setenv1("CONTENT_TYPE", content_type);
1019#if ENABLE_FEATURE_HTTPD_BASIC_AUTH
1020 if (remoteuser) {
1021 setenv1("REMOTE_USER", remoteuser);
1022 putenv((char*)"AUTH_TYPE=Basic");
1023 }
1024#endif
1025 if (referer)
1026 setenv1("HTTP_REFERER", referer);
942 1027
943 xpipe(&fromCgi.rd); 1028 xpipe(&fromCgi.rd);
944 xpipe(&toCgi.rd); 1029 xpipe(&toCgi.rd);
945 1030
946/*
947 * Note: We can use vfork() here in the no-mmu case, although
948 * the child modifies the parent's variables, due to:
949 * 1) The parent does not use the child-modified variables.
950 * 2) The allocated memory (in the child) is freed when the process
951 * exits. This happens instantly after the child finishes,
952 * since httpd is run from inetd (and it can't run standalone
953 * in uClinux).
954 * TODO: we can muck with environment _first_ and then fork/exec,
955 * that will be more understandable, and safer wrt vfork!
956 */
957
958#if !BB_MMU
959 pid = vfork(); 1031 pid = vfork();
960#else
961 pid = fork();
962#endif
963 if (pid < 0) { 1032 if (pid < 0) {
964 /* TODO: log perror? */ 1033 /* TODO: log perror? */
965 log_and_exit(); 1034 log_and_exit();
966 } 1035 }
967 1036
968 if (!pid) { 1037 if (!pid) {
969 /* child process */ 1038 /* Child process */
970 char *fullpath;
971 char *script;
972 char *purl;
973
974 xfunc_error_retval = 242; 1039 xfunc_error_retval = 242;
975 1040
976 if (accepted_socket > 1) 1041 if (accepted_socket > 1)
@@ -982,95 +1047,18 @@ static void send_cgi_and_exit(
982 xmove_fd(fromCgi.wr, 1); /* replace stdout with the pipe */ 1047 xmove_fd(fromCgi.wr, 1); /* replace stdout with the pipe */
983 close(fromCgi.rd); 1048 close(fromCgi.rd);
984 close(toCgi.wr); 1049 close(toCgi.wr);
985 /* Huh? User seeing stderr can be a security problem. 1050 /* User seeing stderr output can be a security problem.
986 * If CGI really wants that, it can always do dup itself. */ 1051 * If CGI really wants that, it can always do dup itself. */
987 /* dup2(1, 2); */ 1052 /* dup2(1, 2); */
988 1053
989 /* 1054 /* script must have absolute path */
990 * Find PATH_INFO.
991 */
992 purl = xstrdup(url);
993 script = purl;
994 while ((script = strchr(script + 1, '/')) != NULL) {
995 /* have script.cgi/PATH_INFO or dirs/script.cgi[/PATH_INFO] */
996 struct stat sb;
997
998 *script = '\0';
999 if (!is_directory(purl + 1, 1, &sb)) {
1000 /* not directory, found script.cgi/PATH_INFO */
1001 *script = '/';
1002 break;
1003 }
1004 *script = '/'; /* is directory, find next '/' */
1005 }
1006 setenv1("PATH_INFO", script); /* set /PATH_INFO or "" */
1007 setenv1("REQUEST_METHOD", request);
1008 if (g_query) {
1009 putenv(xasprintf("%s=%s?%s", "REQUEST_URI", purl, g_query));
1010 } else {
1011 setenv1("REQUEST_URI", purl);
1012 }
1013 if (script != NULL)
1014 *script = '\0'; /* cut off /PATH_INFO */
1015
1016 /* SCRIPT_FILENAME required by PHP in CGI mode */
1017 fullpath = concat_path_file(home_httpd, purl);
1018 setenv1("SCRIPT_FILENAME", fullpath);
1019 /* set SCRIPT_NAME as full path: /cgi-bin/dirs/script.cgi */
1020 setenv1("SCRIPT_NAME", purl);
1021 /* http://hoohoo.ncsa.uiuc.edu/cgi/env.html:
1022 * QUERY_STRING: The information which follows the ? in the URL
1023 * which referenced this script. This is the query information.
1024 * It should not be decoded in any fashion. This variable
1025 * should always be set when there is query information,
1026 * regardless of command line decoding. */
1027 /* (Older versions of bbox seem to do some decoding) */
1028 setenv1("QUERY_STRING", g_query);
1029 putenv((char*)"SERVER_SOFTWARE=busybox httpd/"BB_VER);
1030 putenv((char*)"SERVER_PROTOCOL=HTTP/1.0");
1031 putenv((char*)"GATEWAY_INTERFACE=CGI/1.1");
1032 /* Having _separate_ variables for IP and port defeats
1033 * the purpose of having socket abstraction. Which "port"
1034 * are you using on Unix domain socket?
1035 * IOW - REMOTE_PEER="1.2.3.4:56" makes much more sense.
1036 * Oh well... */
1037 {
1038 char *p = rmt_ip_str ? rmt_ip_str : (char*)"";
1039 char *cp = strrchr(p, ':');
1040 if (ENABLE_FEATURE_IPV6 && cp && strchr(cp, ']'))
1041 cp = NULL;
1042 if (cp) *cp = '\0'; /* delete :PORT */
1043 setenv1("REMOTE_ADDR", p);
1044 if (cp) *cp = ':';
1045 }
1046 setenv1("HTTP_USER_AGENT", user_agent);
1047#if ENABLE_FEATURE_HTTPD_SET_REMOTE_PORT_TO_ENV
1048 setenv_long("REMOTE_PORT", tcp_port);
1049#endif
1050 if (bodyLen)
1051 setenv_long("CONTENT_LENGTH", bodyLen);
1052 if (cookie)
1053 setenv1("HTTP_COOKIE", cookie);
1054 if (content_type)
1055 setenv1("CONTENT_TYPE", content_type);
1056#if ENABLE_FEATURE_HTTPD_BASIC_AUTH
1057 if (remoteuser) {
1058 setenv1("REMOTE_USER", remoteuser);
1059 putenv((char*)"AUTH_TYPE=Basic");
1060 }
1061#endif
1062 if (referer)
1063 setenv1("HTTP_REFERER", referer);
1064
1065 /* set execve argp[0] without path */
1066 argp[0] = (char*)bb_basename(purl);
1067 /* but script argp[0] must have absolute path */
1068 script = strrchr(fullpath, '/'); 1055 script = strrchr(fullpath, '/');
1069 if (!script) 1056 if (!script)
1070 goto error_execing_cgi; 1057 goto error_execing_cgi;
1071 *script = '\0'; 1058 *script = '\0';
1072 /* chdiring to script's dir */ 1059 /* chdiring to script's dir */
1073 if (chdir(fullpath) == 0) { 1060 if (chdir(fullpath) == 0) {
1061 char *argv[2];
1074#if ENABLE_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR 1062#if ENABLE_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR
1075 char *interpr = NULL; 1063 char *interpr = NULL;
1076 char *suffix = strrchr(purl, '.'); 1064 char *suffix = strrchr(purl, '.');
@@ -1086,12 +1074,15 @@ static void send_cgi_and_exit(
1086 } 1074 }
1087#endif 1075#endif
1088 *script = '/'; 1076 *script = '/';
1077 /* set argv[0] to name without path */
1078 argv[0] = (char*)bb_basename(purl);
1079 argv[1] = NULL;
1089#if ENABLE_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR 1080#if ENABLE_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR
1090 if (interpr) 1081 if (interpr)
1091 execv(interpr, argp); 1082 execv(interpr, argv);
1092 else 1083 else
1093#endif 1084#endif
1094 execv(fullpath, argp); 1085 execv(fullpath, argv);
1095 } 1086 }
1096 error_execing_cgi: 1087 error_execing_cgi:
1097 /* send to stdout 1088 /* send to stdout
@@ -1100,7 +1091,13 @@ static void send_cgi_and_exit(
1100 send_headers_and_exit(HTTP_NOT_FOUND); 1091 send_headers_and_exit(HTTP_NOT_FOUND);
1101 } /* end child */ 1092 } /* end child */
1102 1093
1103 /* parent process */ 1094 /* Parent process */
1095
1096 /* First, restore variables possibly changed by child */
1097 xfunc_error_retval = 0;
1098 accepted_socket = sv_accepted_socket;
1099
1100 /* Prepare for pumping data */
1104 buf_count = 0; 1101 buf_count = 0;
1105 post_read_size = 0; 1102 post_read_size = 0;
1106 post_read_idx = 0; /* for gcc */ 1103 post_read_idx = 0; /* for gcc */