51#ifdef HAVE_SYS_TYPES_H
52# include <sys/types.h>
77# include <unixlib/local.h>
78int __riscosify_control = __RISCOSIFY_STRICT_UNIX_SPECS;
90#if defined(PHP_WIN32) && defined(HAVE_OPENSSL_EXT)
91# include "openssl/applink.c"
95# include "valgrind/callgrind.h"
96# ifdef HAVE_VALGRIND_CACHEGRIND_H
97# include "valgrind/cachegrind.h"
103static struct sigaction act, old_term, old_quit, old_int;
106static void (*php_php_import_environment_variables)(
zval *array_ptr);
112static int children = 0;
118static int parent = 1;
122static volatile sig_atomic_t exit_signal = 0;
125static int parent_waiting = 0;
133#define PHP_MODE_STANDARD 1
134#define PHP_MODE_HIGHLIGHT 2
135#define PHP_MODE_LINT 4
136#define PHP_MODE_STRIP 5
138static char *php_optarg =
NULL;
139static int php_optind = 1;
143 {
'a', 0,
"interactive"},
144 {
'b', 1,
"bindpath"},
145 {
'C', 0,
"no-chdir"},
148 {
'e', 0,
"profile-info"},
152 {
'l', 0,
"syntax-check"},
154 {
'n', 0,
"no-php-ini"},
155 {
'q', 0,
"no-header"},
156 {
's', 0,
"syntax-highlight"},
157 {
's', 0,
"syntax-highlighting"},
161 {
'z', 1,
"zend-extension"},
195static void user_config_cache_entry_dtor(
zval *el)
205static int php_cgi_globals_id;
206#define CGIG(v) ZEND_TSRMG(php_cgi_globals_id, php_cgi_globals_struct *, v)
207#if defined(PHP_WIN32)
212#define CGIG(v) (php_cgi_globals.v)
216#define TRANSLATE_SLASHES(path) \
220 if (*tmp == '\\') *tmp = '/'; \
225#define TRANSLATE_SLASHES(path)
229#define WIN32_MAX_SPAWN_CHILDREN 64
230HANDLE kid_cgi_ps[WIN32_MAX_SPAWN_CHILDREN];
231int kids, cleaning_up = 0;
233JOBOBJECT_EXTENDED_LIMIT_INFORMATION job_info = { 0 };
234CRITICAL_SECTION cleanup_lock;
237#ifndef HAVE_ATTRIBUTE_WEAK
238static void fcgi_log(
int type,
const char *format, ...) {
241 va_start(ap, format);
253static void print_modules(
void)
260 zend_hash_sort(&sorted_registry, module_name_cmp, 0);
276 return strcmp(fe->name, se->name);
279static void print_extensions(
void)
291#define STDOUT_FILENO 1
294static inline size_t sapi_cgi_single_write(
const char *str,
size_t str_length)
296#ifdef PHP_WRITE_STDOUT
300 if (
ret <= 0)
return 0;
310static size_t sapi_cgi_ub_write(
const char *str,
size_t str_length)
312 const char *
ptr = str;
313 size_t remaining = str_length;
316 while (remaining > 0) {
317 ret = sapi_cgi_single_write(
ptr, remaining);
320 return str_length - remaining;
329static size_t sapi_fcgi_ub_write(
const char *str,
size_t str_length)
331 const char *
ptr = str;
332 size_t remaining = str_length;
335 while (remaining > 0) {
341 return str_length - remaining;
350static void sapi_cgi_flush(
void *server_context)
352 if (
fflush(stdout) == EOF) {
357static void sapi_fcgi_flush(
void *server_context)
361 if (!parent && request) {
369#define SAPI_CGI_MAX_HEADER_LENGTH 1024
375 bool ignore_status = 0;
376 int response_status =
SG(sapi_headers).http_response_code;
378 if (
SG(request_info).no_headers == 1) {
388 if (
CGIG(rfc2616_headers) &&
SG(sapi_headers).http_status_line) {
391 if ((
s =
strchr(
SG(sapi_headers).http_status_line,
' '))) {
392 response_status = atoi((
s + 1));
402 if (
SG(sapi_headers).http_status_line &&
403 (
s =
strchr(
SG(sapi_headers).http_status_line,
' ')) != 0 &&
404 (
s -
SG(sapi_headers).http_status_line) >= 5 &&
405 strncasecmp(
SG(sapi_headers).http_status_line,
"HTTP/", 5) == 0
408 response_status = atoi((
s + 1));
423 while (
err->code != 0) {
452 if (!ignore_status) {
457 }
else if (response_status == 304 && h->
header_len >
sizeof(
"Content-Type:")-1 &&
475# define STDIN_FILENO 0
478static size_t sapi_cgi_read_post(
char *
buffer,
size_t count_bytes)
480 size_t read_bytes = 0;
482 size_t remaining_bytes;
484 assert(
SG(request_info).content_length >=
SG(read_post_bytes));
486 remaining_bytes = (size_t)(
SG(request_info).content_length -
SG(read_post_bytes));
488 count_bytes =
MIN(count_bytes, remaining_bytes);
489 while (read_bytes < count_bytes) {
491 size_t diff = count_bytes - read_bytes;
492 unsigned int to_read = (diff >
INT_MAX) ?
INT_MAX : (
unsigned int)diff;
498 if (tmp_read_bytes <= 0) {
501 read_bytes += tmp_read_bytes;
506static size_t sapi_fcgi_read_post(
char *
buffer,
size_t count_bytes)
508 size_t read_bytes = 0;
511 size_t remaining =
SG(request_info).content_length -
SG(read_post_bytes);
513 if (remaining < count_bytes) {
514 count_bytes = remaining;
516 while (read_bytes < count_bytes) {
517 size_t diff = count_bytes - read_bytes;
521 if (tmp_read_bytes <= 0) {
524 read_bytes += tmp_read_bytes;
531static char *cgi_getenv_win32(
const char *
name,
size_t name_len)
534 wchar_t *keyw, *valw;
543 rc = _wgetenv_s(&
size,
NULL, 0, keyw);
544 if (rc || 0 ==
size) {
551 rc = _wgetenv_s(&
size, valw,
size, keyw);
563static char *sapi_cgi_getenv(
const char *
name,
size_t name_len)
568 return cgi_getenv_win32(
name, name_len);
572static char *sapi_fcgi_getenv(
const char *
name,
size_t name_len)
595 return cgi_getenv_win32(
name, name_len);
599static char *_sapi_cgi_putenv(
char *
name,
size_t name_len,
char *
value)
601#if !defined(HAVE_SETENV) || !defined(HAVE_UNSETENV)
617#if !defined(HAVE_SETENV) || !defined(HAVE_UNSETENV)
624 buf = (
char *) malloc(
len);
629#if !defined(HAVE_SETENV)
635#if !defined(HAVE_UNSETENV)
644static char *sapi_cgi_read_cookies(
void)
646 return getenv(
"HTTP_COOKIE");
649static char *sapi_fcgi_read_cookies(
void)
656static void cgi_php_load_env_var(
const char *var,
unsigned int var_len,
char *
val,
unsigned int val_len,
void *
arg)
667static void cgi_php_import_environment_variables(
zval *array_ptr)
669 if (
PG(variables_order) && (
strchr(
PG(variables_order),
'E') ||
strchr(
PG(variables_order),
'e'))) {
683 php_php_import_environment_variables(array_ptr);
691static void sapi_cgi_register_variables(
zval *track_vars_array)
701 if (
CGIG(fix_pathinfo)) {
702 char *script_name =
SG(request_info).request_uri;
712 path_info =
getenv(
"PATH_INFO");
716 size_t path_info_len =
strlen(path_info);
719 size_t script_name_len =
strlen(script_name);
721 php_self_len = script_name_len + path_info_len;
722 php_self =
do_alloca(php_self_len + 1, use_heap);
723 memcpy(php_self, script_name, script_name_len + 1);
724 memcpy(php_self + script_name_len, path_info, path_info_len + 1);
727 php_self = path_info;
728 php_self_len = path_info_len;
731 }
else if (script_name) {
732 php_self = script_name;
733 php_self_len =
strlen(script_name);
749 php_self =
SG(request_info).request_uri ?
SG(request_info).request_uri :
"";
750 php_self_len =
strlen(php_self);
757static void sapi_cgi_log_message(
const char *message,
int syslog_type_int)
765 char *
buf = malloc(
len+2);
775 fprintf(stderr,
"%s\n", message);
779 fprintf(stderr,
"%s\n", message);
784static void php_cgi_ini_activate_user_config(
char *path,
size_t path_len,
const char *doc_root,
size_t doc_root_len)
790 if ((entry = zend_hash_str_find_ptr(&
CGIG(user_config_cache), path, path_len)) ==
NULL) {
795 entry = zend_hash_str_update_ptr(&
CGIG(user_config_cache), path, path_len, new_entry);
799 if (request_time > entry->
expires) {
800 char *real_path =
NULL;
808 size_t real_path_len;
810 if (real_path ==
NULL) {
813 real_path_len =
strlen(real_path);
815 path_len = real_path_len;
818 if (path_len > doc_root_len) {
819 s1 = (
char *) doc_root;
821 s_len = doc_root_len;
824 s2 = (
char *) doc_root;
833 if (strnicmp(s1, s2, s_len) == 0) {
835 if (
strncmp(s1, s2, s_len) == 0) {
837 char *
ptr = s2 + doc_root_len;
855 entry->
expires = request_time +
PG(user_ini_cache_ttl);
863static int sapi_cgi_activate(
void)
866 if (!
SG(request_info).path_translated) {
879 server_name =
getenv(
"SERVER_NAME");
883 size_t server_name_len =
strlen(server_name);
884 server_name =
estrndup(server_name, server_name_len);
892 (
PG(user_ini_filename) && *
PG(user_ini_filename))
898 path_len =
strlen(
SG(request_info).path_translated);
901 if (!
IS_SLASH(
SG(request_info).path_translated[path_len])) {
903 memcpy(path,
SG(request_info).path_translated, path_len + 1);
907 path =
estrndup(
SG(request_info).path_translated, path_len);
916 if (
PG(user_ini_filename) && *
PG(user_ini_filename)) {
924 doc_root =
getenv(
"DOCUMENT_ROOT");
928 size_t doc_root_len =
strlen(doc_root);
929 if (doc_root_len > 0 &&
IS_SLASH(doc_root[doc_root_len - 1])) {
934 doc_root =
estrndup(doc_root, doc_root_len);
937 php_cgi_ini_activate_user_config(path, path_len, doc_root, doc_root_len);
951static int sapi_cgi_deactivate(
void)
957 if (
SG(sapi_started)) {
965 sapi_cgi_flush(
SG(server_context));
995 sapi_cgi_send_headers,
999 sapi_cgi_read_cookies,
1001 sapi_cgi_register_variables,
1002 sapi_cgi_log_message,
1016static void php_cgi_usage(
char *argv0)
1027 php_printf(
"Usage: %s [-q] [-h] [-s] [-v] [-i] [-f <file>]\n"
1028 " %s <file> [args...]\n"
1029 " -a Run interactively\n"
1030 " -b <address:port>|<port> Bind Path for external FASTCGI Server mode\n"
1031 " -C Do not chdir to the script's directory\n"
1032 " -c <path>|<file> Look for php.ini file in this directory\n"
1033 " -n No php.ini file will be used\n"
1034 " -d foo[=bar] Define INI entry foo with value 'bar'\n"
1035 " -e Generate extended information for debugger/profiler\n"
1036 " -f <file> Parse <file>. Implies `-q'\n"
1038 " -i PHP information\n"
1039 " -l Syntax check only (lint)\n"
1040 " -m Show compiled in modules\n"
1041 " -q Quiet-mode. Suppress HTTP Header output.\n"
1042 " -s Display colour syntax highlighted source.\n"
1043 " -v Version number\n"
1044 " -w Display source with stripped comments and whitespace.\n"
1045 " -z <file> Load Zend extension <file>.\n"
1046 " -T <count> Measure execution time of script repeated <count> times.\n",
1056static int is_valid_path(
const char *path)
1058 const char *
p = path;
1085#define CGI_GETENV(name) \
1087 FCGI_GETENV(request, name) : \
1090#define CGI_PUTENV(name, value) \
1092 FCGI_PUTENV(request, name, value) : \
1093 _sapi_cgi_putenv(name, sizeof(name)-1, value))
1164 char *env_script_filename =
CGI_GETENV(
"SCRIPT_FILENAME");
1165 char *env_path_translated =
CGI_GETENV(
"PATH_TRANSLATED");
1166 char *script_path_translated = env_script_filename;
1171 if (!script_path_translated && env_path_translated) {
1172 script_path_translated = env_path_translated;
1176 SG(request_info).path_translated =
NULL;
1177 SG(request_info).request_method =
NULL;
1178 SG(request_info).proto_num = 1000;
1179 SG(request_info).query_string =
NULL;
1180 SG(request_info).request_uri =
NULL;
1181 SG(request_info).content_type =
NULL;
1182 SG(request_info).content_length = 0;
1183 SG(sapi_headers).http_response_code = 200;
1189 if (script_path_translated) {
1191 char *content_length =
CGI_GETENV(
"CONTENT_LENGTH");
1192 char *content_type =
CGI_GETENV(
"CONTENT_TYPE");
1193 char *env_path_info =
CGI_GETENV(
"PATH_INFO");
1194 char *env_script_name =
CGI_GETENV(
"SCRIPT_NAME");
1198 char *env_server_software =
CGI_GETENV(
"SERVER_SOFTWARE");
1200 if (env_server_software &&
1203 strncmp(env_server_software,
"Microsoft-IIS",
sizeof(
"Microsoft-IIS")-1) == 0 &&
1204 strncmp(env_path_info, env_script_name,
strlen(env_script_name)) == 0
1206 env_path_info =
CGI_PUTENV(
"ORIG_PATH_INFO", env_path_info);
1207 env_path_info +=
strlen(env_script_name);
1208 if (*env_path_info == 0) {
1209 env_path_info =
NULL;
1211 env_path_info =
CGI_PUTENV(
"PATH_INFO", env_path_info);
1215 if (
CGIG(fix_pathinfo)) {
1217 char *real_path =
NULL;
1218 char *env_redirect_url =
CGI_GETENV(
"REDIRECT_URL");
1219 char *env_document_root =
CGI_GETENV(
"DOCUMENT_ROOT");
1220 char *orig_path_translated = env_path_translated;
1221 char *orig_path_info = env_path_info;
1222 char *orig_script_name = env_script_name;
1223 char *orig_script_filename = env_script_filename;
1224 size_t script_path_translated_len;
1226 if (!env_document_root &&
PG(doc_root)) {
1227 env_document_root =
CGI_PUTENV(
"DOCUMENT_ROOT",
PG(doc_root));
1232 if (env_path_translated !=
NULL && env_redirect_url !=
NULL &&
1233 env_path_translated != script_path_translated &&
1234 strcmp(env_path_translated, script_path_translated) != 0) {
1240 script_path_translated = env_path_translated;
1242 env_script_name = env_redirect_url;
1247 __riscosify_control |= __RISCOSIFY_DONT_CHECK_DIR;
1248 script_path_translated = __unixify(script_path_translated, 0,
NULL, 1, 0);
1256 if (script_path_translated &&
1257 (script_path_translated_len =
strlen(script_path_translated)) > 0 &&
1258 (script_path_translated[script_path_translated_len-1] ==
'/' ||
1260 script_path_translated[script_path_translated_len-1] ==
'\\' ||
1264 char *pt =
estrndup(script_path_translated, script_path_translated_len);
1265 size_t len = script_path_translated_len;
1287 size_t pilen = env_path_info ?
strlen(env_path_info) : 0;
1288 char *path_info = env_path_info ? env_path_info + pilen - slen :
NULL;
1290 if (orig_path_info != path_info) {
1291 if (orig_path_info) {
1294 CGI_PUTENV(
"ORIG_PATH_INFO", orig_path_info);
1297 if (!orig_script_name ||
1298 strcmp(orig_script_name, env_path_info) != 0) {
1299 if (orig_script_name) {
1300 CGI_PUTENV(
"ORIG_SCRIPT_NAME", orig_script_name);
1302 SG(request_info).request_uri =
CGI_PUTENV(
"SCRIPT_NAME", env_path_info);
1304 SG(request_info).request_uri = orig_script_name;
1308 env_path_info =
CGI_PUTENV(
"PATH_INFO", path_info);
1310 if (!orig_script_filename ||
1311 strcmp(orig_script_filename, pt) != 0) {
1312 if (orig_script_filename) {
1313 CGI_PUTENV(
"ORIG_SCRIPT_FILENAME", orig_script_filename);
1315 script_path_translated =
CGI_PUTENV(
"SCRIPT_FILENAME", pt);
1322 if (env_document_root) {
1323 size_t l =
strlen(env_document_root);
1324 size_t path_translated_len = 0;
1325 char *path_translated =
NULL;
1327 if (l && env_document_root[l - 1] ==
'/') {
1337 path_translated_len = l + (env_path_info ?
strlen(env_path_info) : 0);
1338 path_translated = (
char *)
emalloc(path_translated_len + 1);
1339 memcpy(path_translated, env_document_root, l);
1340 if (env_path_info) {
1341 memcpy(path_translated + l, env_path_info, (path_translated_len - l));
1343 path_translated[path_translated_len] =
'\0';
1344 if (orig_path_translated) {
1345 CGI_PUTENV(
"ORIG_PATH_TRANSLATED", orig_path_translated);
1347 env_path_translated =
CGI_PUTENV(
"PATH_TRANSLATED", path_translated);
1348 efree(path_translated);
1349 }
else if ( env_script_name &&
1350 strstr(pt, env_script_name)
1354 size_t path_translated_len = ptlen + (env_path_info ?
strlen(env_path_info) : 0);
1356 char *path_translated = (
char *)
emalloc(path_translated_len + 1);
1357 memcpy(path_translated, pt, ptlen);
1358 if (env_path_info) {
1359 memcpy(path_translated + ptlen, env_path_info, path_translated_len - ptlen);
1361 path_translated[path_translated_len] =
'\0';
1362 if (orig_path_translated) {
1363 CGI_PUTENV(
"ORIG_PATH_TRANSLATED", orig_path_translated);
1365 env_path_translated =
CGI_PUTENV(
"PATH_TRANSLATED", path_translated);
1366 efree(path_translated);
1377 if (orig_script_filename) {
1378 CGI_PUTENV(
"ORIG_SCRIPT_FILENAME", orig_script_filename);
1381 SG(sapi_headers).http_response_code = 404;
1383 if (!
SG(request_info).request_uri) {
1384 if (!orig_script_name ||
1385 strcmp(orig_script_name, env_script_name) != 0) {
1386 if (orig_script_name) {
1387 CGI_PUTENV(
"ORIG_SCRIPT_NAME", orig_script_name);
1389 SG(request_info).request_uri =
CGI_PUTENV(
"SCRIPT_NAME", env_script_name);
1391 SG(request_info).request_uri = orig_script_name;
1399 if (!orig_script_filename ||
1400 (script_path_translated != orig_script_filename &&
1401 strcmp(script_path_translated, orig_script_filename) != 0)) {
1402 if (orig_script_filename) {
1403 CGI_PUTENV(
"ORIG_SCRIPT_FILENAME", orig_script_filename);
1405 script_path_translated =
CGI_PUTENV(
"SCRIPT_FILENAME", script_path_translated);
1407 if (env_redirect_url) {
1408 if (orig_path_info) {
1409 CGI_PUTENV(
"ORIG_PATH_INFO", orig_path_info);
1412 if (orig_path_translated) {
1413 CGI_PUTENV(
"ORIG_PATH_TRANSLATED", orig_path_translated);
1417 if (env_script_name != orig_script_name) {
1418 if (orig_script_name) {
1419 CGI_PUTENV(
"ORIG_SCRIPT_NAME", orig_script_name);
1421 SG(request_info).request_uri =
CGI_PUTENV(
"SCRIPT_NAME", env_script_name);
1423 SG(request_info).request_uri = env_script_name;
1429 if (env_path_info) {
1430 SG(request_info).request_uri = env_path_info;
1432 SG(request_info).request_uri = env_script_name;
1434 if (!
CGIG(discard_path) && env_path_translated) {
1435 script_path_translated = env_path_translated;
1439 if (is_valid_path(script_path_translated)) {
1440 SG(request_info).path_translated =
estrdup(script_path_translated);
1443 SG(request_info).request_method =
CGI_GETENV(
"REQUEST_METHOD");
1445 SG(request_info).query_string =
CGI_GETENV(
"QUERY_STRING");
1446 SG(request_info).content_type = (content_type ? content_type :
"" );
1447 SG(request_info).content_length = (content_length ? atol(content_length) : 0);
1460static void fastcgi_cleanup(
int signal)
1463 fprintf(stderr,
"FastCGI shutdown, pid %d\n", getpid());
1466 sigaction(
SIGTERM, &old_term, 0);
1471 if (parent && parent_waiting) {
1482 EnterCriticalSection(&cleanup_lock);
1484 LeaveCriticalSection(&cleanup_lock);
1487 if (
NULL == kid_cgi_ps[i]) {
1491 TerminateProcess(kid_cgi_ps[i], 0);
1492 CloseHandle(kid_cgi_ps[i]);
1493 kid_cgi_ps[i] =
NULL;
1523#if defined(ZTS) && defined(PHP_WIN32)
1526 php_cgi_globals->rfc2616_headers = 0;
1527 php_cgi_globals->nph = 0;
1528 php_cgi_globals->check_shebang_line = 1;
1529 php_cgi_globals->force_redirect = 1;
1530 php_cgi_globals->redirect_status_env =
NULL;
1531 php_cgi_globals->fix_pathinfo = 1;
1532 php_cgi_globals->discard_path = 0;
1533 php_cgi_globals->fcgi_logging = 1;
1535 php_cgi_globals->impersonate = 0;
1537 zend_hash_init(&php_cgi_globals->user_config_cache, 8,
NULL, user_config_cache_entry_dtor, 1);
1590 char **env, *
p, *q, *var, *
val, *t =
buf;
1591 size_t alloc_size =
sizeof(
buf);
1599 var_len =
val - *env;
1600 if (var_len >= alloc_size) {
1601 alloc_size = var_len + 64;
1614 if (var_len >= alloc_size) {
1615 alloc_size = var_len + 64;
1627 }
else if (*
p ==
'_') {
1631 if (*
p && *
p!=
'=') {
1634 }
else if (*
p >=
'A' && *
p <=
'Z') {
1636 *q++ = (*
p++ -
'A' +
'a');
1642 }
else if (var_len ==
sizeof(
"CONTENT_TYPE")-1 &&
1643 memcmp(var,
"CONTENT_TYPE",
sizeof(
"CONTENT_TYPE")-1) == 0) {
1644 var =
"Content-Type";
1645 }
else if (var_len ==
sizeof(
"CONTENT_LENGTH")-1 &&
1646 memcmp(var,
"CONTENT_LENGTH",
sizeof(
"CONTENT_LENGTH")-1) == 0) {
1647 var =
"Content-Length";
1682 }
while (*
p ==
' ' || *
p ==
'\t');
1718 int free_query_string = 0;
1728 int orig_optind = php_optind;
1729 char *orig_optarg = php_optarg;
1730 char *script_file =
NULL;
1734 int max_requests = 500;
1737 char *bindpath =
NULL;
1740 int warmup_repeats = 0;
1743#ifdef HAVE_GETTIMEOFDAY
1752 int skip_getopt = 0;
1754#if defined(SIGPIPE) && defined(SIG_IGN)
1775 php_cgi_globals_ctor(&php_cgi_globals);
1780 cgi_sapi_module.php_ini_path_override =
NULL;
1784 _setmode(_fileno(stdin),
O_BINARY);
1785 _setmode(_fileno(stdout),
O_BINARY);
1786 _setmode(_fileno(stderr),
O_BINARY);
1792 if (
getenv(
"SERVER_SOFTWARE") ||
1794 getenv(
"GATEWAY_INTERFACE") ||
1811 skip_getopt = cgi || fastcgi;
1814 char *decoded_query_string = strdup(query_string);
1816 for (
p = (
unsigned char *)decoded_query_string; *
p && *
p <=
' ';
p++) {
1823 free(decoded_query_string);
1827 php_ini_builder_init(&ini_builder);
1829 while (!skip_getopt && (c =
php_getopt(argc, argv, OPTIONS, &php_optarg, &php_optind, 0, 2)) != -1) {
1832 if (cgi_sapi_module.php_ini_path_override) {
1833 free(cgi_sapi_module.php_ini_path_override);
1835 cgi_sapi_module.php_ini_path_override = strdup(php_optarg);
1838 cgi_sapi_module.php_ini_ignore = 1;
1849 bindpath = strdup(php_optarg);
1857 php_optind = orig_optind;
1858 php_optarg = orig_optarg;
1860 cgi_sapi_module.ini_entries = php_ini_builder_finish(&ini_builder);
1862 if (fastcgi || bindpath) {
1864 cgi_sapi_module.ub_write = sapi_fcgi_ub_write;
1865 cgi_sapi_module.flush = sapi_fcgi_flush;
1866 cgi_sapi_module.read_post = sapi_fcgi_read_post;
1867 cgi_sapi_module.getenv = sapi_fcgi_getenv;
1868 cgi_sapi_module.read_cookies = sapi_fcgi_read_cookies;
1872 SG(request_info).path_translated =
NULL;
1875 cgi_sapi_module.executable_location = argv[0];
1876 if (!cgi && !fastcgi && !bindpath) {
1877 cgi_sapi_module.additional_functions = additional_functions;
1881 if (cgi_sapi_module.startup(&cgi_sapi_module) ==
FAILURE) {
1890 if (cgi &&
CGIG(force_redirect)) {
1895 const char *redirect_status_env =
CGIG(redirect_status_env);
1896 if (!redirect_status_env) {
1898 redirect_status_env =
"REDIRECT_STATUS";
1901 if (!
getenv(redirect_status_env)) {
1903 SG(sapi_headers).http_response_code = 400;
1904 PUTS(
"<b>Security Alert!</b> The PHP CGI cannot be accessed directly.\n\n\
1905<p>This PHP CGI binary was compiled with force-cgi-redirect enabled. This\n\
1906means that a page will only be served up if the REDIRECT_STATUS CGI variable is\n\
1907set, e.g. via an Apache Action directive.</p>\n\
1908<p>For more information as to <i>why</i> this behaviour exists, see the <a href=\"https://www.php.net/security.cgi-bin\">\
1909manual page for CGI security</a>.</p>\n\
1910<p>For more information about changing this behaviour or re-enabling this webserver,\n\
1911consult the installation file that came with this distribution, or visit \n\
1912<a href=\"https://www.php.net/install.windows\">the manual page</a>.</p>\n");
1915#if defined(ZTS) && !PHP_DEBUG
1929#ifndef HAVE_ATTRIBUTE_WEAK
1935 if (
getenv(
"PHP_FCGI_BACKLOG")) {
1936 backlog = atoi(
getenv(
"PHP_FCGI_BACKLOG"));
1938 if (backlog < -1 || backlog >
SOMAXCONN) {
1939 fprintf(stderr,
"Invalid backlog %d, needs to be between -1 and %d\n", backlog,
SOMAXCONN);
1947 fprintf(stderr,
"Couldn't create FastCGI listen socket on port %s\n", bindpath);
1962 if (
getenv(
"PHP_FCGI_MAX_REQUESTS")) {
1963 max_requests = atoi(
getenv(
"PHP_FCGI_MAX_REQUESTS"));
1964 if (max_requests < 0) {
1965 fprintf(stderr,
"PHP_FCGI_MAX_REQUESTS is not valid\n");
1974 if (
getenv(
"PHP_FCGI_CHILDREN")) {
1975 char * children_str =
getenv(
"PHP_FCGI_CHILDREN");
1976 children = atoi(children_str);
1978 fprintf(stderr,
"PHP_FCGI_CHILDREN is not valid\n");
1989 char * children_str =
getenv(
"PHP_FCGI_CHILDREN_FOR_KID");
1991 char putenv_buf[
sizeof(
"PHP_FCGI_CHILDREN")+5];
1993 snprintf(putenv_buf,
sizeof(putenv_buf),
"%s=%s",
"PHP_FCGI_CHILDREN", children_str);
1995 putenv(
"PHP_FCGI_CHILDREN_FOR_KID=");
1997 SetEnvironmentVariable(
"PHP_FCGI_CHILDREN", children_str);
1998 SetEnvironmentVariable(
"PHP_FCGI_CHILDREN_FOR_KID",
NULL);
2001 fcgi_set_mgmt_var(
"FCGI_MAX_CONNS",
sizeof(
"FCGI_MAX_CONNS")-1,
"1",
sizeof(
"1")-1);
2002 fcgi_set_mgmt_var(
"FCGI_MAX_REQS",
sizeof(
"FCGI_MAX_REQS")-1,
"1",
sizeof(
"1")-1);
2014 fprintf(stderr,
"Process group %d\n", pgroup);
2019 act.sa_handler = fastcgi_cleanup;
2020 if (sigaction(
SIGTERM, &act, &old_term) ||
2021 sigaction(
SIGINT, &act, &old_int) ||
2022 sigaction(
SIGQUIT, &act, &old_quit)
2024 perror(
"Can't set signals");
2047 sigaction(
SIGTERM, &old_term, 0);
2048 sigaction(
SIGQUIT, &old_quit, 0);
2049 sigaction(
SIGINT, &old_int, 0);
2053 perror(
"php (pre-forking)");
2061 }
while (parent && (
running < children));
2065 fprintf(stderr,
"Wait for kids, pid %d\n", getpid());
2069 if (wait(&
status) >= 0) {
2072 }
else if (exit_signal) {
2079 while (wait(&
status) < 0) {
2096 size_t cmd_line_len;
2100 ZeroMemory(&kid_cgi_ps,
sizeof(kid_cgi_ps));
2101 kids = children < WIN32_MAX_SPAWN_CHILDREN ? children : WIN32_MAX_SPAWN_CHILDREN;
2103 InitializeCriticalSection(&cleanup_lock);
2104 SetConsoleCtrlHandler(fastcgi_cleanup,
TRUE);
2107 SetEnvironmentVariable(
"PHP_FCGI_CHILDREN",
NULL);
2110 snprintf(kid_buf, 16,
"%d", children);
2111 SetEnvironmentVariable(
"PHP_FCGI_CHILDREN_FOR_KID", kid_buf);
2116 cmd_line_tmp = GetCommandLineW();
2117 if (!cmd_line_tmp) {
2121 fprintf(stderr,
"unable to get current command line: [0x%08lx]: %s\n",
err, err_text);
2127 cmd_line_len = wcslen(cmd_line_tmp);
2128 if (cmd_line_len >
sizeof(cmd_line) - 1) {
2129 fprintf(stderr,
"command line is too long\n");
2132 memmove(cmd_line, cmd_line_tmp, (cmd_line_len + 1)*
sizeof(
wchar_t));
2139 fprintf(stderr,
"unable to create job object: [0x%08lx]: %s\n",
err, err_text);
2146 job_info.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
2147 if (!SetInformationJobObject(job, JobObjectExtendedLimitInformation, &job_info,
sizeof(job_info))) {
2151 fprintf(stderr,
"unable to configure job object: [0x%08lx]: %s\n",
err, err_text);
2156 EnterCriticalSection(&cleanup_lock);
2158 goto parent_loop_end;
2160 LeaveCriticalSection(&cleanup_lock);
2166 if (
NULL != kid_cgi_ps[i]) {
2167 if(!GetExitCodeProcess(kid_cgi_ps[i], &
status) ||
status != STILL_ACTIVE) {
2168 CloseHandle(kid_cgi_ps[i]);
2169 kid_cgi_ps[i] =
NULL;
2176 PROCESS_INFORMATION
pi;
2179 if (
NULL != kid_cgi_ps[i]) {
2183 ZeroMemory(&si,
sizeof(si));
2185 ZeroMemory(&
pi,
sizeof(
pi));
2187 si.dwFlags = STARTF_USESTDHANDLES;
2188 si.hStdOutput = INVALID_HANDLE_VALUE;
2189 si.hStdInput = (HANDLE)_get_osfhandle(fcgi_fd);
2190 si.hStdError = INVALID_HANDLE_VALUE;
2193 kid_cgi_ps[i] =
pi.hProcess;
2194 if (!AssignProcessToJobObject(job,
pi.hProcess)) {
2198 fprintf(stderr,
"unable to assign child process to job object: [0x%08lx]: %s\n",
err, err_text);
2201 CloseHandle(
pi.hThread);
2206 kid_cgi_ps[i] =
NULL;
2208 fprintf(stderr,
"unable to spawn: [0x%08lx]: %s\n",
err, err_text);
2213 WaitForMultipleObjects(kids, kid_cgi_ps,
FALSE, INFINITE);
2218 SetEnvironmentVariable(
"PHP_FCGI_CHILDREN", kid_buf);
2220 DeleteCriticalSection(&cleanup_lock);
2230 while (!skip_getopt && (c =
php_getopt(argc, argv, OPTIONS, &php_optarg, &php_optind, 1, 2)) != -1) {
2235 char *comma =
strchr(php_optarg,
',');
2237 warmup_repeats = atoi(php_optarg);
2238 repeats = atoi(comma + 1);
2240 if (warmup_repeats > 0) {
2241 CALLGRIND_STOP_INSTRUMENTATION;
2243 CALLGRIND_ZERO_STATS;
2244# ifdef HAVE_VALGRIND_CACHEGRIND_H
2245 CACHEGRIND_STOP_INSTRUMENTATION;
2251 repeats = atoi(php_optarg);
2254#ifdef HAVE_GETTIMEOFDAY
2269 php_cgi_usage(argv[0]);
2278 php_optind = orig_optind;
2279 php_optarg = orig_optarg;
2286 if (fastcgi &&
CGIG(impersonate)) {
2291 SG(server_context) = fastcgi ? (
void *)request : (
void *) 1;
2292 init_request_info(request);
2294 if (!cgi && !fastcgi) {
2295 while ((c =
php_getopt(argc, argv, OPTIONS, &php_optarg, &php_optind, 0, 2)) != -1) {
2299 printf(
"Interactive mode enabled\n\n");
2315 script_file =
estrdup(php_optarg);
2324 SG(server_context) =
NULL;
2331 SG(request_info).no_headers = 1;
2369 SG(server_context) =
NULL;
2375 SG(request_info).no_headers = 1;
2398 if (
SG(request_info).path_translated)
efree(
SG(request_info).path_translated);
2399 SG(request_info).path_translated = script_file;
2402 SG(request_info).argc = argc - (php_optind - 1);
2403 SG(request_info).argv = &argv[php_optind - 1];
2404 SG(request_info).argv[0] = script_file;
2405 }
else if (argc > php_optind) {
2407 if (
SG(request_info).path_translated)
efree(
SG(request_info).path_translated);
2408 SG(request_info).path_translated =
estrdup(argv[php_optind]);
2410 SG(request_info).argc = argc - php_optind;
2411 SG(request_info).argv = &argv[php_optind];
2416 SG(request_info).no_headers = 1;
2428 if (!
SG(request_info).query_string && argc > php_optind) {
2429 size_t slen =
strlen(
PG(arg_separator).input);
2431 for (i = php_optind; i < argc; i++) {
2432 if (i < (argc - 1)) {
2442 for (i = php_optind; i < argc; i++) {
2444 if (i < (argc - 1)) {
2448 SG(request_info).query_string =
s;
2449 free_query_string = 1;
2454 if (warmup_repeats == 0) {
2455 CALLGRIND_START_INSTRUMENTATION;
2456# ifdef HAVE_VALGRIND_CACHEGRIND_H
2457 CACHEGRIND_START_INSTRUMENTATION;
2468 SG(server_context) =
NULL;
2474 SG(request_info).no_headers = 1;
2482 if (cgi || fastcgi ||
SG(request_info).path_translated) {
2485 if (
errno == EACCES) {
2486 SG(sapi_headers).http_response_code = 403;
2487 PUTS(
"Access denied.\n");
2489 SG(sapi_headers).http_response_code = 404;
2490 PUTS(
"No input file specified.\n");
2498 goto fastcgi_request_done;
2501 if (
SG(request_info).path_translated) {
2502 efree(
SG(request_info).path_translated);
2503 SG(request_info).path_translated =
NULL;
2506 if (free_query_string &&
SG(request_info).query_string) {
2507 free(
SG(request_info).query_string);
2508 SG(request_info).query_string =
NULL;
2512 SG(server_context) =
NULL;
2527 if (
CGIG(check_shebang_line)) {
2528 CG(skip_shebang) = 1;
2536 PG(during_request_startup) = 0;
2561fastcgi_request_done:
2564 if (
SG(request_info).path_translated) {
2565 efree(
SG(request_info).path_translated);
2566 SG(request_info).path_translated =
NULL;
2571 if (exit_status == 0) {
2572 exit_status =
EG(exit_status);
2575 if (free_query_string &&
SG(request_info).query_string) {
2576 free(
SG(request_info).query_string);
2577 SG(request_info).query_string =
NULL;
2582 CALLGRIND_STOP_INSTRUMENTATION;
2583# ifdef HAVE_VALGRIND_CACHEGRIND_H
2584 CACHEGRIND_STOP_INSTRUMENTATION;
2590 if (warmup_repeats) {
2592 if (!warmup_repeats) {
2593#ifdef HAVE_GETTIMEOFDAY
2604 php_optind = orig_optind;
2605 php_optarg = orig_optarg;
2620 if (max_requests && (requests == max_requests)) {
2623 if (max_requests != 1) {
2637 if (cgi_sapi_module.php_ini_path_override) {
2638 free(cgi_sapi_module.php_ini_path_override);
2640 php_ini_builder_deinit(&ini_builder);
2648#ifdef HAVE_GETTIMEOFDAY
2652 sec = (int)(
end.tv_sec -
start.tv_sec);
2653 if (
end.tv_usec >=
start.tv_usec) {
2654 usec = (int)(
end.tv_usec -
start.tv_usec);
2657 usec = (int)(
end.tv_usec + 1000000 -
start.tv_usec);
2659 fprintf(stderr,
"\nElapsed time: %d.%06d sec\n", sec, usec);
2663 fprintf(stderr,
"\nElapsed time: %d sec\n", sec);
2669 SG(server_context) =
NULL;
2677#if defined(PHP_WIN32) && ZEND_DEBUG && 0
2678 _CrtDumpMemoryLeaks();
SAPI_API double sapi_get_request_time(void)
SAPI_API sapi_module_struct sapi_module
SAPI_API int sapi_send_headers(void)
SAPI_API void sapi_add_request_header(const char *var, unsigned int var_len, char *val, unsigned int val_len, void *arg)
SAPI_API void sapi_startup(sapi_module_struct *sf)
SAPI_API void sapi_shutdown(void)
#define SAPI_OPTION_NO_CHDIR
#define SAPI_HEADER_SENT_SUCCESSFULLY
#define STANDARD_SAPI_MODULE_PROPERTIES
struct _sapi_module_struct sapi_module_struct
file_private const char ext[]
ZEND_API void php_get_highlight_struct(zend_syntax_highlighter_ini *syntax_highlighter_ini)
sizeof(Countable|array $value, int $mode=COUNT_NORMAL)
fprintf($stream, string $format, mixed ... $values)
getenv(?string $name=null, bool $local_only=false)
http_response_code(int $response_code=0)
putenv(string $assignment)
printf(string $format, mixed ... $values)
vfprintf($stream, string $format, array $values)
strrchr(string $haystack, string $needle, bool $before_needle=false)
fwrite($stream, string $data, ?int $length=null)
gettimeofday(bool $as_float=false)
strpbrk(string $string, string $characters)
strstr(string $haystack, string $needle, bool $before_needle=false)
assert(mixed $assertion, Throwable|string|null $description=null)
strchr(string $haystack, string $needle, bool $before_needle=false)
headers_sent(&$filename=null, &$line=null)
#define PHP_MODE_HIGHLIGHT
#define TRANSLATE_SLASHES(path)
struct _php_cgi_globals_struct php_cgi_globals_struct
struct _user_config_cache_entry user_config_cache_entry
#define CGI_PUTENV(name, value)
#define PHP_MODE_STANDARD
#define SAPI_CGI_MAX_HEADER_LENGTH
#define PHP_WIN32_CP_IGNORE_LEN_P
#define php_win32_cp_w_to_any(in)
dl(string $extension_filename)
int fcgi_is_fastcgi(void)
void fcgi_set_mgmt_var(const char *name, size_t name_len, const char *value, size_t value_len)
int fcgi_listen(const char *path, int backlog)
int fcgi_accept_request(fcgi_request *req)
void fcgi_destroy_request(fcgi_request *req)
int fcgi_has_env(fcgi_request *req)
int fcgi_read(fcgi_request *req, char *str, int len)
int fcgi_flush(fcgi_request *req, int end)
fcgi_request * fcgi_init_request(int listen_socket, void(*on_accept)(void), void(*on_read)(void), void(*on_close)(void))
void fcgi_loadenv(fcgi_request *req, fcgi_apply_func func, zval *array)
void fcgi_terminate(void)
int fcgi_in_shutdown(void)
int fcgi_write(fcgi_request *req, fcgi_request_type type, const char *str, int len)
char * fcgi_getenv(fcgi_request *req, const char *var, int var_len)
int fcgi_finish_request(fcgi_request *req, int force_close)
void void fcgi_set_logger(fcgi_logger lg)
#define FCGI_GETENV(request, name)
struct _fcgi_request fcgi_request
zend_ffi_ctype_name_buf buf
PHPAPI int php_fopen_primary_script(zend_file_handle *file_handle)
void unsetenv(const char *name)
int setenv(char *name, char *value, int overwrite)
PHPAPI int php_getopt(int argc, char *const *argv, const opt_struct opts[], char **optarg, int *optind, int show_err, int arg_start)
struct _http_response_status_code_pair http_response_status_code_pair
PHPAPI ZEND_COLD void php_print_info(int flag)
#define PHP_WIN32_IOUTIL_MAXPATHLEN
PHPAPI size_t php_url_decode(char *str, size_t len)
PHPAPI zend_result php_lint_script(zend_file_handle *file)
PHPAPI size_t php_printf(const char *format,...)
void php_request_shutdown(void *dummy)
zend_result php_module_startup(sapi_module_struct *sf, zend_module_entry *additional_module)
PHPAPI void php_handle_aborted_connection(void)
PHPAPI bool php_execute_script(zend_file_handle *primary_file)
void php_module_shutdown(void)
PHPAPI void php_print_version(sapi_module_struct *sapi_module)
zend_result php_request_startup(void)
PHPAPI int php_handle_auth_data(const char *auth)
int php_module_shutdown_wrapper(sapi_module_struct *sapi_globals)
PHPAPI void php_output_end_all(void)
#define PHP_MSHUTDOWN_FUNCTION
#define PHP_MINIT_FUNCTION
#define PHP_MINFO_FUNCTION
unsigned const char * end
unsigned const char * pos
apache_response_headers()
#define PHP_GETOPT_INVALID_ARG
struct _opt_struct opt_struct
PHPAPI void config_zval_dtor(zval *zvalue)
PHPAPI int php_parse_user_ini_file(const char *dirname, const char *ini_filename, HashTable *target_hash)
PHPAPI int php_ini_has_per_host_config(void)
PHPAPI void php_ini_activate_config(HashTable *source_hash, int modify_type, int stage)
PHPAPI int php_ini_has_per_dir_config(void)
PHPAPI void php_ini_activate_per_host_config(const char *host, size_t host_len)
PHPAPI void php_ini_activate_per_dir_config(char *path, size_t path_len)
#define STD_PHP_INI_ENTRY
#define STD_PHP_INI_BOOLEAN
#define PHP_INI_STAGE_HTACCESS
PHPAPI void php_ini_builder_define(struct php_ini_builder *b, const char *arg)
PHP_JSON_API size_t int options
php_output_handler * running
#define PHPWRITE_H(str, str_len)
PHPAPI void(* php_import_environment_variables)(zval *array_ptr)
PHPAPI void php_register_variable_safe(const char *var, const char *strval, size_t str_len, zval *track_vars_array)
HashTable user_config_cache
char * redirect_status_env
PHP_WINUTIL_API char * php_win32_error_to_msg(HRESULT error)
PHP_WINUTIL_API void php_win32_error_msg_free(char *msg)
ZEND_API size_t(* zend_printf)(const char *format,...)
#define ZEND_TSRMLS_CACHE_UPDATE()
#define ZEND_TSRMLS_CACHE_DEFINE()
ZEND_API HashTable module_registry
ZEND_API void add_assoc_string_ex(zval *arg, const char *key, size_t key_len, const char *str)
ZEND_API void add_assoc_stringl_ex(zval *arg, const char *key, size_t key_len, const char *str, size_t length)
struct _zend_function_entry zend_function_entry
#define zend_parse_parameters_none()
#define ZEND_FE(name, arg_info)
#define estrndup(s, length)
#define pemalloc(size, persistent)
#define erealloc(ptr, size)
strncmp(string $string1, string $string2, int $length)
exit(string|int $status=0)
strcmp(string $string1, string $string2)
ZEND_API size_t zend_dirname(char *path, size_t len)
ZEND_API bool zend_is_auto_global(zend_string *name)
#define ZEND_COMPILE_EXTENDED_INFO
ZEND_API void zend_destroy_file_handle(zend_file_handle *file_handle)
ZEND_API zend_result open_file_for_scanning(zend_file_handle *file_handle)
#define strncasecmp(s1, s2, n)
#define strcasecmp(s1, s2)
ZEND_API void(ZEND_FASTCALL *zend_touch_vm_stack_data)(void *vm_stack_data)
zend_result zend_load_extension(const char *path)
ZEND_API zend_llist zend_extensions
struct _zend_extension zend_extension
ZEND_API void ZEND_FASTCALL zend_hash_destroy(HashTable *ht)
ZEND_API void ZEND_FASTCALL zend_hash_clean(HashTable *ht)
ZEND_API void ZEND_FASTCALL zend_hash_copy(HashTable *target, HashTable *source, copy_ctor_func_t pCopyConstructor)
ZEND_API void ZEND_FASTCALL zend_array_destroy(HashTable *ht)
ZEND_API HashTable *ZEND_FASTCALL zend_array_dup(HashTable *source)
#define zend_hash_init(ht, nSize, pHashFunction, pDestructor, persistent)
#define ZEND_HASH_MAP_FOREACH_PTR(ht, _ptr)
#define ZEND_HASH_FOREACH_END()
ZEND_API void zend_highlight(zend_syntax_highlighter_ini *syntax_highlighter_ini)
ZEND_API void zend_strip(void)
zend_syntax_highlighter_ini syntax_highlighter_ini
struct _zend_syntax_highlighter_ini zend_syntax_highlighter_ini
#define UNREGISTER_INI_ENTRIES()
#define REGISTER_INI_ENTRIES()
#define DISPLAY_INI_ENTRIES()
struct _zend_file_handle zend_file_handle
ZEND_API void zend_llist_destroy(zend_llist *l)
ZEND_API void zend_llist_copy(zend_llist *dst, zend_llist *src)
ZEND_API void * zend_llist_get_next_ex(zend_llist *l, zend_llist_position *pos)
ZEND_API void zend_llist_sort(zend_llist *l, llist_compare_func_t comp_func)
ZEND_API void zend_llist_apply(zend_llist *l, llist_apply_func_t func)
ZEND_API void zend_llist_apply_with_argument(zend_llist *l, llist_apply_with_arg_func_t func, void *arg)
ZEND_API void * zend_llist_get_first_ex(zend_llist *l, zend_llist_position *pos)
struct _zend_llist_element zend_llist_element
zend_llist_element * zend_llist_position
void(* llist_apply_with_arg_func_t)(void *data, void *arg)
void(* llist_apply_func_t)(void *)
struct _zend_llist zend_llist
#define STANDARD_MODULE_HEADER
struct _zend_module_entry zend_module_entry
#define STANDARD_MODULE_PROPERTIES
ZEND_API void ZEND_FASTCALL zend_str_tolower(char *str, size_t length)
#define ALLOCA_FLAG(name)
#define do_alloca(p, use_heap)
#define free_alloca(p, use_heap)
#define UNEXPECTED(condition)
#define zend_signal_startup()
#define zend_signal_init()
ZEND_API void zend_stream_init_fp(zend_file_handle *handle, FILE *fp, const char *filename)
struct _zend_array HashTable
void(* dtor_func_t)(zval *pDest)
CWD_API char * tsrm_realpath(const char *path, char *real_path)
#define IS_ABSOLUTE_PATH(path, len)