summaryrefslogtreecommitdiff
path: root/sapi/cgi/cgi_main.c
diff options
context:
space:
mode:
Diffstat (limited to 'sapi/cgi/cgi_main.c')
-rw-r--r--sapi/cgi/cgi_main.c153
1 files changed, 114 insertions, 39 deletions
diff --git a/sapi/cgi/cgi_main.c b/sapi/cgi/cgi_main.c
index f47ae96c8..6e1139966 100644
--- a/sapi/cgi/cgi_main.c
+++ b/sapi/cgi/cgi_main.c
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
- | Copyright (c) 1997-2008 The PHP Group |
+ | Copyright (c) 1997-2009 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
@@ -21,7 +21,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: cgi_main.c,v 1.267.2.15.2.56 2008/04/09 09:16:40 dmitry Exp $ */
+/* $Id: cgi_main.c,v 1.267.2.15.2.69 2009/01/19 18:17:59 dsp Exp $ */
#include "php.h"
#include "php_globals.h"
@@ -103,6 +103,12 @@ static int children = 0;
*/
static int parent = 1;
+/* Did parent received exit signals SIG_TERM/SIG_INT/SIG_QUIT */
+static int exit_signal = 0;
+
+/* Is Parent waiting for children to exit */
+static int parent_waiting = 0;
+
/**
* Process group
*/
@@ -232,6 +238,7 @@ static void print_extensions(TSRMLS_D)
zend_llist sorted_exts;
zend_llist_copy(&sorted_exts, &zend_extensions);
+ sorted_exts.dtor = NULL;
zend_llist_sort(&sorted_exts, extension_name_cmp TSRMLS_CC);
zend_llist_apply_with_argument(&sorted_exts, (llist_apply_with_arg_func_t) print_extension_info, NULL TSRMLS_CC);
zend_llist_destroy(&sorted_exts);
@@ -362,6 +369,8 @@ static int sapi_cgi_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC)
char buf[SAPI_CGI_MAX_HEADER_LENGTH];
sapi_header_struct *h;
zend_llist_position pos;
+ zend_bool ignore_status = 0;
+ int response_status = SG(sapi_headers).http_response_code;
if (SG(request_info).no_headers == 1) {
return SAPI_HEADER_SENT_SUCCESSFULLY;
@@ -373,8 +382,11 @@ static int sapi_cgi_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC)
zend_bool has_status = 0;
if (CGIG(rfc2616_headers) && SG(sapi_headers).http_status_line) {
- len = slprintf(buf, SAPI_CGI_MAX_HEADER_LENGTH,
- "%s\r\n", SG(sapi_headers).http_status_line);
+ char *s;
+ len = slprintf(buf, SAPI_CGI_MAX_HEADER_LENGTH, "%s\r\n", SG(sapi_headers).http_status_line);
+ if ((s = strchr(SG(sapi_headers).http_status_line, ' '))) {
+ response_status = atoi((s + 1));
+ }
if (len > SAPI_CGI_MAX_HEADER_LENGTH) {
len = SAPI_CGI_MAX_HEADER_LENGTH;
@@ -388,6 +400,7 @@ static int sapi_cgi_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC)
(s - SG(sapi_headers).http_status_line) >= 5 &&
strncasecmp(SG(sapi_headers).http_status_line, "HTTP/", 5) == 0) {
len = slprintf(buf, sizeof(buf), "Status:%s\r\n", s);
+ response_status = atoi((s + 1));
} else {
h = (sapi_header_struct*)zend_llist_get_first_ex(&sapi_headers->headers, &pos);
while (h) {
@@ -417,6 +430,7 @@ static int sapi_cgi_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC)
}
if (!has_status) {
PHPWRITE_H(buf, len);
+ ignore_status = 1;
}
}
@@ -424,8 +438,21 @@ static int sapi_cgi_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC)
while (h) {
/* prevent CRLFCRLF */
if (h->header_len) {
- PHPWRITE_H(h->header, h->header_len);
- PHPWRITE_H("\r\n", 2);
+ if (h->header_len > sizeof("Status:")-1 &&
+ strncasecmp(h->header, "Status:", sizeof("Status:")-1) == 0) {
+ if (!ignore_status) {
+ ignore_status = 1;
+ PHPWRITE_H(h->header, h->header_len);
+ PHPWRITE_H("\r\n", 2);
+ }
+ } else if (response_status == 304 && h->header_len > sizeof("Content-Type:")-1 &&
+ strncasecmp(h->header, "Content-Type:", sizeof("Content-Type:")-1) == 0) {
+ h = (sapi_header_struct*)zend_llist_get_next_ex(&sapi_headers->headers, &pos);
+ continue;
+ } else {
+ PHPWRITE_H(h->header, h->header_len);
+ PHPWRITE_H("\r\n", 2);
+ }
}
h = (sapi_header_struct*)zend_llist_get_next_ex(&sapi_headers->headers, &pos);
}
@@ -765,6 +792,39 @@ static void php_cgi_usage(char *argv0)
}
/* }}} */
+/* {{{ is_valid_path
+ *
+ * some server configurations allow '..' to slip through in the
+ * translated path. We'll just refuse to handle such a path.
+ */
+static int is_valid_path(const char *path)
+{
+ const char *p;
+
+ if (!path) {
+ return 0;
+ }
+ p = strstr(path, "..");
+ if (p) {
+ if ((p == path || IS_SLASH(*(p-1))) &&
+ (*(p+2) == 0 || IS_SLASH(*(p+2)))) {
+ return 0;
+ }
+ while (1) {
+ p = strstr(p+1, "..");
+ if (!p) {
+ break;
+ }
+ if (IS_SLASH(*(p-1)) &&
+ (*(p+2) == 0 || IS_SLASH(*(p+2)))) {
+ return 0;
+ }
+ }
+ }
+ return 1;
+}
+/* }}} */
+
/* {{{ init_request_info
initializes request_info structure
@@ -900,7 +960,8 @@ static void init_request_info(TSRMLS_D)
TRANSLATE_SLASHES(env_document_root);
}
- if (env_path_translated != NULL && env_redirect_url != NULL) {
+ if (env_path_translated != NULL && env_redirect_url != NULL &&
+ orig_script_filename != NULL && script_path_translated != NULL) {
/*
pretty much apache specific. If we have a redirect_url
then our script_filename and script_name point to the
@@ -925,6 +986,9 @@ static void init_request_info(TSRMLS_D)
if (script_path_translated &&
(script_path_translated_len = strlen(script_path_translated)) > 0 &&
(script_path_translated[script_path_translated_len-1] == '/' ||
+#ifdef PHP_WIN32
+ script_path_translated[script_path_translated_len-1] == '\\' ||
+#endif
(real_path = tsrm_realpath(script_path_translated, NULL TSRMLS_CC)) == NULL)) {
char *pt = estrndup(script_path_translated, script_path_translated_len);
int len = script_path_translated_len;
@@ -1061,9 +1125,7 @@ static void init_request_info(TSRMLS_D)
if (pt) {
efree(pt);
}
- /* some server configurations allow '..' to slip through in the
- translated path. We'll just refuse to handle such a path. */
- if (script_path_translated && !strstr(script_path_translated, "..")) {
+ if (is_valid_path(script_path_translated)) {
SG(request_info).path_translated = estrdup(script_path_translated);
}
} else {
@@ -1094,9 +1156,7 @@ static void init_request_info(TSRMLS_D)
} else {
SG(request_info).request_uri = env_script_name;
}
- /* some server configurations allow '..' to slip through in the
- translated path. We'll just refuse to handle such a path. */
- if (script_path_translated && !strstr(script_path_translated, "..")) {
+ if (is_valid_path(script_path_translated)) {
SG(request_info).path_translated = estrdup(script_path_translated);
}
free(real_path);
@@ -1114,9 +1174,7 @@ static void init_request_info(TSRMLS_D)
script_path_translated = env_path_translated;
}
#endif
- /* some server configurations allow '..' to slip through in the
- translated path. We'll just refuse to handle such a path. */
- if (script_path_translated && !strstr(script_path_translated, "..")) {
+ if (is_valid_path(script_path_translated)) {
SG(request_info).path_translated = estrdup(script_path_translated);
}
#if ENABLE_PATHINFO_CHECK
@@ -1135,7 +1193,7 @@ static void init_request_info(TSRMLS_D)
}
/* }}} */
-#if PHP_FASTCGI
+#if PHP_FASTCGI && !defined(PHP_WIN32)
/**
* Clean up child processes upon exit
*/
@@ -1145,15 +1203,16 @@ void fastcgi_cleanup(int signal)
fprintf(stderr, "FastCGI shutdown, pid %d\n", getpid());
#endif
-#ifndef PHP_WIN32
sigaction(SIGTERM, &old_term, 0);
/* Kill all the processes in our process group */
kill(-pgroup, SIGTERM);
-#endif
- /* We should exit at this point, but MacOSX doesn't seem to */
- exit(0);
+ if (parent && parent_waiting) {
+ exit_signal = 1;
+ } else {
+ exit(0);
+ }
}
#endif
@@ -1491,11 +1550,18 @@ consult the installation file that came with this distribution, or visit \n\
#ifndef PHP_WIN32
/* Pre-fork, if required */
if (getenv("PHP_FCGI_CHILDREN")) {
- children = atoi(getenv("PHP_FCGI_CHILDREN"));
+ char * children_str = getenv("PHP_FCGI_CHILDREN");
+ children = atoi(children_str);
if (children < 0) {
fprintf(stderr, "PHP_FCGI_CHILDREN is not valid\n");
return FAILURE;
}
+ fcgi_set_mgmt_var("FCGI_MAX_CONNS", sizeof("FCGI_MAX_CONNS")-1, children_str, strlen(children_str));
+ /* This is the number of concurrent requests, equals FCGI_MAX_CONNS */
+ fcgi_set_mgmt_var("FCGI_MAX_REQS", sizeof("FCGI_MAX_REQS")-1, children_str, strlen(children_str));
+ } else {
+ fcgi_set_mgmt_var("FCGI_MAX_CONNS", sizeof("FCGI_MAX_CONNS")-1, "1", sizeof("1")-1);
+ fcgi_set_mgmt_var("FCGI_MAX_REQS", sizeof("FCGI_MAX_REQS")-1, "1", sizeof("1")-1);
}
if (children) {
@@ -1520,7 +1586,7 @@ consult the installation file that came with this distribution, or visit \n\
}
if (fcgi_in_shutdown()) {
- exit(0);
+ goto parent_out;
}
while (parent) {
@@ -1557,9 +1623,25 @@ consult the installation file that came with this distribution, or visit \n\
#ifdef DEBUG_FASTCGI
fprintf(stderr, "Wait for kids, pid %d\n", getpid());
#endif
- while (wait(&status) < 0) {
+ parent_waiting = 1;
+ while (1) {
+ if (wait(&status) >= 0) {
+ running--;
+ break;
+ } else if (exit_signal) {
+ break;
+ }
+ }
+ if (exit_signal) {
+#if 0
+ while (running > 0) {
+ while (wait(&status) < 0) {
+ }
+ running--;
+ }
+#endif
+ goto parent_out;
}
- running--;
}
}
} else {
@@ -1628,17 +1710,6 @@ consult the installation file that came with this distribution, or visit \n\
&& !fastcgi
#endif
) {
- if (cgi_sapi_module.php_ini_path_override && cgi_sapi_module.php_ini_ignore) {
- no_headers = 1;
- php_output_startup();
- php_output_activate(TSRMLS_C);
- SG(headers_sent) = 1;
- php_printf("You cannot use both -n and -c switch. Use -h for help.\n");
- php_end_ob_buffers(1 TSRMLS_CC);
- exit_status = 1;
- goto out;
- }
-
while ((c = php_getopt(argc, argv, OPTIONS, &php_optarg, &php_optind, 0)) != -1) {
switch (c) {
@@ -1727,9 +1798,9 @@ consult the installation file that came with this distribution, or visit \n\
SG(request_info).no_headers = 1;
}
#if ZEND_DEBUG
- php_printf("PHP %s (%s) (built: %s %s) (DEBUG)\nCopyright (c) 1997-2008 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
+ php_printf("PHP %s (%s) (built: %s %s) (DEBUG)\nCopyright (c) 1997-2009 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
#else
- php_printf("PHP %s (%s) (built: %s %s)\nCopyright (c) 1997-2008 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
+ php_printf("PHP %s (%s) (built: %s %s)\nCopyright (c) 1997-2009 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
#endif
php_request_shutdown((void *) 0);
exit_status = 0;
@@ -1898,7 +1969,7 @@ consult the installation file that came with this distribution, or visit \n\
/* #!php support */
c = fgetc(file_handle.handle.fp);
if (c == '#') {
- while (c != '\n' && c != '\r') {
+ while (c != '\n' && c != '\r' && c != EOF) {
c = fgetc(file_handle.handle.fp); /* skip to end of line */
}
/* handle situations where line is terminated by \r\n */
@@ -2061,6 +2132,10 @@ out:
}
#endif
+#ifndef PHP_WIN32
+parent_out:
+#endif
+
SG(server_context) = NULL;
php_module_shutdown(TSRMLS_C);
sapi_shutdown();