Annotation of embedaddon/php/sapi/cgi/cgi_main.c, revision 1.1
1.1 ! misho 1: /*
! 2: +----------------------------------------------------------------------+
! 3: | PHP Version 5 |
! 4: +----------------------------------------------------------------------+
! 5: | Copyright (c) 1997-2012 The PHP Group |
! 6: +----------------------------------------------------------------------+
! 7: | This source file is subject to version 3.01 of the PHP license, |
! 8: | that is bundled with this package in the file LICENSE, and is |
! 9: | available through the world-wide-web at the following url: |
! 10: | http://www.php.net/license/3_01.txt |
! 11: | If you did not receive a copy of the PHP license and are unable to |
! 12: | obtain it through the world-wide-web, please send a note to |
! 13: | license@php.net so we can mail you a copy immediately. |
! 14: +----------------------------------------------------------------------+
! 15: | Authors: Rasmus Lerdorf <rasmus@lerdorf.on.ca> |
! 16: | Stig Bakken <ssb@php.net> |
! 17: | Zeev Suraski <zeev@zend.com> |
! 18: | FastCGI: Ben Mansell <php@slimyhorror.com> |
! 19: | Shane Caraveo <shane@caraveo.com> |
! 20: | Dmitry Stogov <dmitry@zend.com> |
! 21: +----------------------------------------------------------------------+
! 22: */
! 23:
! 24: /* $Id: cgi_main.c 321634 2012-01-01 13:15:04Z felipe $ */
! 25:
! 26: #include "php.h"
! 27: #include "php_globals.h"
! 28: #include "php_variables.h"
! 29: #include "zend_modules.h"
! 30:
! 31: #include "SAPI.h"
! 32:
! 33: #include <stdio.h>
! 34: #include "php.h"
! 35:
! 36: #ifdef PHP_WIN32
! 37: # include "win32/time.h"
! 38: # include "win32/signal.h"
! 39: # include <process.h>
! 40: #endif
! 41:
! 42: #if HAVE_SYS_TIME_H
! 43: # include <sys/time.h>
! 44: #endif
! 45:
! 46: #if HAVE_UNISTD_H
! 47: # include <unistd.h>
! 48: #endif
! 49:
! 50: #if HAVE_SIGNAL_H
! 51: # include <signal.h>
! 52: #endif
! 53:
! 54: #if HAVE_SETLOCALE
! 55: # include <locale.h>
! 56: #endif
! 57:
! 58: #if HAVE_SYS_TYPES_H
! 59: # include <sys/types.h>
! 60: #endif
! 61:
! 62: #if HAVE_SYS_WAIT_H
! 63: # include <sys/wait.h>
! 64: #endif
! 65:
! 66: #include "zend.h"
! 67: #include "zend_extensions.h"
! 68: #include "php_ini.h"
! 69: #include "php_globals.h"
! 70: #include "php_main.h"
! 71: #include "fopen_wrappers.h"
! 72: #include "ext/standard/php_standard.h"
! 73:
! 74: #ifdef PHP_WIN32
! 75: # include <io.h>
! 76: # include <fcntl.h>
! 77: # include "win32/php_registry.h"
! 78: #endif
! 79:
! 80: #ifdef __riscos__
! 81: # include <unixlib/local.h>
! 82: int __riscosify_control = __RISCOSIFY_STRICT_UNIX_SPECS;
! 83: #endif
! 84:
! 85: #include "zend_compile.h"
! 86: #include "zend_execute.h"
! 87: #include "zend_highlight.h"
! 88: #include "zend_indent.h"
! 89:
! 90: #include "php_getopt.h"
! 91:
! 92: #include "fastcgi.h"
! 93:
! 94: #ifndef PHP_WIN32
! 95: /* XXX this will need to change later when threaded fastcgi is implemented. shane */
! 96: struct sigaction act, old_term, old_quit, old_int;
! 97: #endif
! 98:
! 99: static void (*php_php_import_environment_variables)(zval *array_ptr TSRMLS_DC);
! 100:
! 101: #ifndef PHP_WIN32
! 102: /* these globals used for forking children on unix systems */
! 103: /**
! 104: * Number of child processes that will get created to service requests
! 105: */
! 106: static int children = 0;
! 107:
! 108: /**
! 109: * Set to non-zero if we are the parent process
! 110: */
! 111: static int parent = 1;
! 112:
! 113: /* Did parent received exit signals SIG_TERM/SIG_INT/SIG_QUIT */
! 114: static int exit_signal = 0;
! 115:
! 116: /* Is Parent waiting for children to exit */
! 117: static int parent_waiting = 0;
! 118:
! 119: /**
! 120: * Process group
! 121: */
! 122: static pid_t pgroup;
! 123: #endif
! 124:
! 125: #define PHP_MODE_STANDARD 1
! 126: #define PHP_MODE_HIGHLIGHT 2
! 127: #define PHP_MODE_INDENT 3
! 128: #define PHP_MODE_LINT 4
! 129: #define PHP_MODE_STRIP 5
! 130:
! 131: static char *php_optarg = NULL;
! 132: static int php_optind = 1;
! 133: static zend_module_entry cgi_module_entry;
! 134:
! 135: static const opt_struct OPTIONS[] = {
! 136: {'a', 0, "interactive"},
! 137: {'b', 1, "bindpath"},
! 138: {'C', 0, "no-chdir"},
! 139: {'c', 1, "php-ini"},
! 140: {'d', 1, "define"},
! 141: {'e', 0, "profile-info"},
! 142: {'f', 1, "file"},
! 143: {'h', 0, "help"},
! 144: {'i', 0, "info"},
! 145: {'l', 0, "syntax-check"},
! 146: {'m', 0, "modules"},
! 147: {'n', 0, "no-php-ini"},
! 148: {'q', 0, "no-header"},
! 149: {'s', 0, "syntax-highlight"},
! 150: {'s', 0, "syntax-highlighting"},
! 151: {'w', 0, "strip"},
! 152: {'?', 0, "usage"},/* help alias (both '?' and 'usage') */
! 153: {'v', 0, "version"},
! 154: {'z', 1, "zend-extension"},
! 155: {'T', 1, "timing"},
! 156: {'-', 0, NULL} /* end of args */
! 157: };
! 158:
! 159: typedef struct _php_cgi_globals_struct {
! 160: zend_bool rfc2616_headers;
! 161: zend_bool nph;
! 162: zend_bool check_shebang_line;
! 163: zend_bool fix_pathinfo;
! 164: zend_bool force_redirect;
! 165: zend_bool discard_path;
! 166: zend_bool fcgi_logging;
! 167: char *redirect_status_env;
! 168: #ifdef PHP_WIN32
! 169: zend_bool impersonate;
! 170: #endif
! 171: HashTable user_config_cache;
! 172: } php_cgi_globals_struct;
! 173:
! 174: /* {{{ user_config_cache
! 175: *
! 176: * Key for each cache entry is dirname(PATH_TRANSLATED).
! 177: *
! 178: * NOTE: Each cache entry config_hash contains the combination from all user ini files found in
! 179: * the path starting from doc_root throught to dirname(PATH_TRANSLATED). There is no point
! 180: * storing per-file entries as it would not be possible to detect added / deleted entries
! 181: * between separate files.
! 182: */
! 183: typedef struct _user_config_cache_entry {
! 184: time_t expires;
! 185: HashTable *user_config;
! 186: } user_config_cache_entry;
! 187:
! 188: static void user_config_cache_entry_dtor(user_config_cache_entry *entry)
! 189: {
! 190: zend_hash_destroy(entry->user_config);
! 191: free(entry->user_config);
! 192: }
! 193: /* }}} */
! 194:
! 195: #ifdef ZTS
! 196: static int php_cgi_globals_id;
! 197: #define CGIG(v) TSRMG(php_cgi_globals_id, php_cgi_globals_struct *, v)
! 198: #else
! 199: static php_cgi_globals_struct php_cgi_globals;
! 200: #define CGIG(v) (php_cgi_globals.v)
! 201: #endif
! 202:
! 203: #ifdef PHP_WIN32
! 204: #define TRANSLATE_SLASHES(path) \
! 205: { \
! 206: char *tmp = path; \
! 207: while (*tmp) { \
! 208: if (*tmp == '\\') *tmp = '/'; \
! 209: tmp++; \
! 210: } \
! 211: }
! 212: #else
! 213: #define TRANSLATE_SLASHES(path)
! 214: #endif
! 215:
! 216: static int print_module_info(zend_module_entry *module, void *arg TSRMLS_DC)
! 217: {
! 218: php_printf("%s\n", module->name);
! 219: return 0;
! 220: }
! 221:
! 222: static int module_name_cmp(const void *a, const void *b TSRMLS_DC)
! 223: {
! 224: Bucket *f = *((Bucket **) a);
! 225: Bucket *s = *((Bucket **) b);
! 226:
! 227: return strcasecmp( ((zend_module_entry *)f->pData)->name,
! 228: ((zend_module_entry *)s->pData)->name);
! 229: }
! 230:
! 231: static void print_modules(TSRMLS_D)
! 232: {
! 233: HashTable sorted_registry;
! 234: zend_module_entry tmp;
! 235:
! 236: zend_hash_init(&sorted_registry, 50, NULL, NULL, 1);
! 237: zend_hash_copy(&sorted_registry, &module_registry, NULL, &tmp, sizeof(zend_module_entry));
! 238: zend_hash_sort(&sorted_registry, zend_qsort, module_name_cmp, 0 TSRMLS_CC);
! 239: zend_hash_apply_with_argument(&sorted_registry, (apply_func_arg_t) print_module_info, NULL TSRMLS_CC);
! 240: zend_hash_destroy(&sorted_registry);
! 241: }
! 242:
! 243: static int print_extension_info(zend_extension *ext, void *arg TSRMLS_DC)
! 244: {
! 245: php_printf("%s\n", ext->name);
! 246: return 0;
! 247: }
! 248:
! 249: static int extension_name_cmp(const zend_llist_element **f, const zend_llist_element **s TSRMLS_DC)
! 250: {
! 251: return strcmp( ((zend_extension *)(*f)->data)->name,
! 252: ((zend_extension *)(*s)->data)->name);
! 253: }
! 254:
! 255: static void print_extensions(TSRMLS_D)
! 256: {
! 257: zend_llist sorted_exts;
! 258:
! 259: zend_llist_copy(&sorted_exts, &zend_extensions);
! 260: sorted_exts.dtor = NULL;
! 261: zend_llist_sort(&sorted_exts, extension_name_cmp TSRMLS_CC);
! 262: zend_llist_apply_with_argument(&sorted_exts, (llist_apply_with_arg_func_t) print_extension_info, NULL TSRMLS_CC);
! 263: zend_llist_destroy(&sorted_exts);
! 264: }
! 265:
! 266: #ifndef STDOUT_FILENO
! 267: #define STDOUT_FILENO 1
! 268: #endif
! 269:
! 270: static inline size_t sapi_cgibin_single_write(const char *str, uint str_length TSRMLS_DC)
! 271: {
! 272: #ifdef PHP_WRITE_STDOUT
! 273: long ret;
! 274: #else
! 275: size_t ret;
! 276: #endif
! 277:
! 278: if (fcgi_is_fastcgi()) {
! 279: fcgi_request *request = (fcgi_request*) SG(server_context);
! 280: long ret = fcgi_write(request, FCGI_STDOUT, str, str_length);
! 281: if (ret <= 0) {
! 282: return 0;
! 283: }
! 284: return ret;
! 285: }
! 286:
! 287: #ifdef PHP_WRITE_STDOUT
! 288: ret = write(STDOUT_FILENO, str, str_length);
! 289: if (ret <= 0) return 0;
! 290: return ret;
! 291: #else
! 292: ret = fwrite(str, 1, MIN(str_length, 16384), stdout);
! 293: return ret;
! 294: #endif
! 295: }
! 296:
! 297: static int sapi_cgibin_ub_write(const char *str, uint str_length TSRMLS_DC)
! 298: {
! 299: const char *ptr = str;
! 300: uint remaining = str_length;
! 301: size_t ret;
! 302:
! 303: while (remaining > 0) {
! 304: ret = sapi_cgibin_single_write(ptr, remaining TSRMLS_CC);
! 305: if (!ret) {
! 306: php_handle_aborted_connection();
! 307: return str_length - remaining;
! 308: }
! 309: ptr += ret;
! 310: remaining -= ret;
! 311: }
! 312:
! 313: return str_length;
! 314: }
! 315:
! 316:
! 317: static void sapi_cgibin_flush(void *server_context)
! 318: {
! 319: if (fcgi_is_fastcgi()) {
! 320: fcgi_request *request = (fcgi_request*) server_context;
! 321: if (
! 322: #ifndef PHP_WIN32
! 323: !parent &&
! 324: #endif
! 325: request && !fcgi_flush(request, 0)) {
! 326: php_handle_aborted_connection();
! 327: }
! 328: return;
! 329: }
! 330: if (fflush(stdout) == EOF) {
! 331: php_handle_aborted_connection();
! 332: }
! 333: }
! 334:
! 335: #define SAPI_CGI_MAX_HEADER_LENGTH 1024
! 336:
! 337: typedef struct _http_error {
! 338: int code;
! 339: const char* msg;
! 340: } http_error;
! 341:
! 342: static const http_error http_error_codes[] = {
! 343: {100, "Continue"},
! 344: {101, "Switching Protocols"},
! 345: {200, "OK"},
! 346: {201, "Created"},
! 347: {202, "Accepted"},
! 348: {203, "Non-Authoritative Information"},
! 349: {204, "No Content"},
! 350: {205, "Reset Content"},
! 351: {206, "Partial Content"},
! 352: {300, "Multiple Choices"},
! 353: {301, "Moved Permanently"},
! 354: {302, "Moved Temporarily"},
! 355: {303, "See Other"},
! 356: {304, "Not Modified"},
! 357: {305, "Use Proxy"},
! 358: {400, "Bad Request"},
! 359: {401, "Unauthorized"},
! 360: {402, "Payment Required"},
! 361: {403, "Forbidden"},
! 362: {404, "Not Found"},
! 363: {405, "Method Not Allowed"},
! 364: {406, "Not Acceptable"},
! 365: {407, "Proxy Authentication Required"},
! 366: {408, "Request Time-out"},
! 367: {409, "Conflict"},
! 368: {410, "Gone"},
! 369: {411, "Length Required"},
! 370: {412, "Precondition Failed"},
! 371: {413, "Request Entity Too Large"},
! 372: {414, "Request-URI Too Large"},
! 373: {415, "Unsupported Media Type"},
! 374: {500, "Internal Server Error"},
! 375: {501, "Not Implemented"},
! 376: {502, "Bad Gateway"},
! 377: {503, "Service Unavailable"},
! 378: {504, "Gateway Time-out"},
! 379: {505, "HTTP Version not supported"},
! 380: {0, NULL}
! 381: };
! 382:
! 383: static int sapi_cgi_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC)
! 384: {
! 385: char buf[SAPI_CGI_MAX_HEADER_LENGTH];
! 386: sapi_header_struct *h;
! 387: zend_llist_position pos;
! 388: zend_bool ignore_status = 0;
! 389: int response_status = SG(sapi_headers).http_response_code;
! 390:
! 391: if (SG(request_info).no_headers == 1) {
! 392: return SAPI_HEADER_SENT_SUCCESSFULLY;
! 393: }
! 394:
! 395: if (CGIG(nph) || SG(sapi_headers).http_response_code != 200)
! 396: {
! 397: int len;
! 398: zend_bool has_status = 0;
! 399:
! 400: if (CGIG(rfc2616_headers) && SG(sapi_headers).http_status_line) {
! 401: char *s;
! 402: len = slprintf(buf, SAPI_CGI_MAX_HEADER_LENGTH, "%s\r\n", SG(sapi_headers).http_status_line);
! 403: if ((s = strchr(SG(sapi_headers).http_status_line, ' '))) {
! 404: response_status = atoi((s + 1));
! 405: }
! 406:
! 407: if (len > SAPI_CGI_MAX_HEADER_LENGTH) {
! 408: len = SAPI_CGI_MAX_HEADER_LENGTH;
! 409: }
! 410:
! 411: } else {
! 412: char *s;
! 413:
! 414: if (SG(sapi_headers).http_status_line &&
! 415: (s = strchr(SG(sapi_headers).http_status_line, ' ')) != 0 &&
! 416: (s - SG(sapi_headers).http_status_line) >= 5 &&
! 417: strncasecmp(SG(sapi_headers).http_status_line, "HTTP/", 5) == 0
! 418: ) {
! 419: len = slprintf(buf, sizeof(buf), "Status:%s\r\n", s);
! 420: response_status = atoi((s + 1));
! 421: } else {
! 422: h = (sapi_header_struct*)zend_llist_get_first_ex(&sapi_headers->headers, &pos);
! 423: while (h) {
! 424: if (h->header_len > sizeof("Status:")-1 &&
! 425: strncasecmp(h->header, "Status:", sizeof("Status:")-1) == 0
! 426: ) {
! 427: has_status = 1;
! 428: break;
! 429: }
! 430: h = (sapi_header_struct*)zend_llist_get_next_ex(&sapi_headers->headers, &pos);
! 431: }
! 432: if (!has_status) {
! 433: http_error *err = (http_error*)http_error_codes;
! 434:
! 435: while (err->code != 0) {
! 436: if (err->code == SG(sapi_headers).http_response_code) {
! 437: break;
! 438: }
! 439: err++;
! 440: }
! 441: if (err->msg) {
! 442: len = slprintf(buf, sizeof(buf), "Status: %d %s\r\n", SG(sapi_headers).http_response_code, err->msg);
! 443: } else {
! 444: len = slprintf(buf, sizeof(buf), "Status: %d\r\n", SG(sapi_headers).http_response_code);
! 445: }
! 446: }
! 447: }
! 448: }
! 449:
! 450: if (!has_status) {
! 451: PHPWRITE_H(buf, len);
! 452: ignore_status = 1;
! 453: }
! 454: }
! 455:
! 456: h = (sapi_header_struct*)zend_llist_get_first_ex(&sapi_headers->headers, &pos);
! 457: while (h) {
! 458: /* prevent CRLFCRLF */
! 459: if (h->header_len) {
! 460: if (h->header_len > sizeof("Status:")-1 &&
! 461: strncasecmp(h->header, "Status:", sizeof("Status:")-1) == 0
! 462: ) {
! 463: if (!ignore_status) {
! 464: ignore_status = 1;
! 465: PHPWRITE_H(h->header, h->header_len);
! 466: PHPWRITE_H("\r\n", 2);
! 467: }
! 468: } else if (response_status == 304 && h->header_len > sizeof("Content-Type:")-1 &&
! 469: strncasecmp(h->header, "Content-Type:", sizeof("Content-Type:")-1) == 0
! 470: ) {
! 471: h = (sapi_header_struct*)zend_llist_get_next_ex(&sapi_headers->headers, &pos);
! 472: continue;
! 473: } else {
! 474: PHPWRITE_H(h->header, h->header_len);
! 475: PHPWRITE_H("\r\n", 2);
! 476: }
! 477: }
! 478: h = (sapi_header_struct*)zend_llist_get_next_ex(&sapi_headers->headers, &pos);
! 479: }
! 480: PHPWRITE_H("\r\n", 2);
! 481:
! 482: return SAPI_HEADER_SENT_SUCCESSFULLY;
! 483: }
! 484:
! 485: #ifndef STDIN_FILENO
! 486: # define STDIN_FILENO 0
! 487: #endif
! 488:
! 489: static int sapi_cgi_read_post(char *buffer, uint count_bytes TSRMLS_DC)
! 490: {
! 491: uint read_bytes = 0;
! 492: int tmp_read_bytes;
! 493:
! 494: count_bytes = MIN(count_bytes, (uint) SG(request_info).content_length - SG(read_post_bytes));
! 495: while (read_bytes < count_bytes) {
! 496: if (fcgi_is_fastcgi()) {
! 497: fcgi_request *request = (fcgi_request*) SG(server_context);
! 498: tmp_read_bytes = fcgi_read(request, buffer + read_bytes, count_bytes - read_bytes);
! 499: } else {
! 500: tmp_read_bytes = read(STDIN_FILENO, buffer + read_bytes, count_bytes - read_bytes);
! 501: }
! 502: if (tmp_read_bytes <= 0) {
! 503: break;
! 504: }
! 505: read_bytes += tmp_read_bytes;
! 506: }
! 507: return read_bytes;
! 508: }
! 509:
! 510: static char *sapi_cgibin_getenv(char *name, size_t name_len TSRMLS_DC)
! 511: {
! 512: /* when php is started by mod_fastcgi, no regular environment
! 513: * is provided to PHP. It is always sent to PHP at the start
! 514: * of a request. So we have to do our own lookup to get env
! 515: * vars. This could probably be faster somehow. */
! 516: if (fcgi_is_fastcgi()) {
! 517: fcgi_request *request = (fcgi_request*) SG(server_context);
! 518: return fcgi_getenv(request, name, name_len);
! 519: }
! 520: /* if cgi, or fastcgi and not found in fcgi env
! 521: check the regular environment */
! 522: return getenv(name);
! 523: }
! 524:
! 525: static char *_sapi_cgibin_putenv(char *name, char *value TSRMLS_DC)
! 526: {
! 527: int name_len;
! 528: #if !HAVE_SETENV || !HAVE_UNSETENV
! 529: int len;
! 530: char *buf;
! 531: #endif
! 532:
! 533: if (!name) {
! 534: return NULL;
! 535: }
! 536: name_len = strlen(name);
! 537:
! 538: /* when php is started by mod_fastcgi, no regular environment
! 539: * is provided to PHP. It is always sent to PHP at the start
! 540: * of a request. So we have to do our own lookup to get env
! 541: * vars. This could probably be faster somehow. */
! 542: if (fcgi_is_fastcgi()) {
! 543: fcgi_request *request = (fcgi_request*) SG(server_context);
! 544: return fcgi_putenv(request, name, name_len, value);
! 545: }
! 546:
! 547: #if HAVE_SETENV
! 548: if (value) {
! 549: setenv(name, value, 1);
! 550: }
! 551: #endif
! 552: #if HAVE_UNSETENV
! 553: if (!value) {
! 554: unsetenv(name);
! 555: }
! 556: #endif
! 557:
! 558: #if !HAVE_SETENV || !HAVE_UNSETENV
! 559: /* if cgi, or fastcgi and not found in fcgi env
! 560: check the regular environment
! 561: this leaks, but it's only cgi anyway, we'll fix
! 562: it for 5.0
! 563: */
! 564: len = name_len + (value ? strlen(value) : 0) + sizeof("=") + 2;
! 565: buf = (char *) malloc(len);
! 566: if (buf == NULL) {
! 567: return getenv(name);
! 568: }
! 569: #endif
! 570: #if !HAVE_SETENV
! 571: if (value) {
! 572: len = slprintf(buf, len - 1, "%s=%s", name, value);
! 573: putenv(buf);
! 574: }
! 575: #endif
! 576: #if !HAVE_UNSETENV
! 577: if (!value) {
! 578: len = slprintf(buf, len - 1, "%s=", name);
! 579: putenv(buf);
! 580: }
! 581: #endif
! 582: return getenv(name);
! 583: }
! 584:
! 585: static char *sapi_cgi_read_cookies(TSRMLS_D)
! 586: {
! 587: return sapi_cgibin_getenv((char *) "HTTP_COOKIE", sizeof("HTTP_COOKIE")-1 TSRMLS_CC);
! 588: }
! 589:
! 590: void cgi_php_import_environment_variables(zval *array_ptr TSRMLS_DC)
! 591: {
! 592: if (PG(http_globals)[TRACK_VARS_ENV] &&
! 593: array_ptr != PG(http_globals)[TRACK_VARS_ENV] &&
! 594: Z_TYPE_P(PG(http_globals)[TRACK_VARS_ENV]) == IS_ARRAY &&
! 595: zend_hash_num_elements(Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_ENV])) > 0
! 596: ) {
! 597: zval_dtor(array_ptr);
! 598: *array_ptr = *PG(http_globals)[TRACK_VARS_ENV];
! 599: INIT_PZVAL(array_ptr);
! 600: zval_copy_ctor(array_ptr);
! 601: return;
! 602: } else if (PG(http_globals)[TRACK_VARS_SERVER] &&
! 603: array_ptr != PG(http_globals)[TRACK_VARS_SERVER] &&
! 604: Z_TYPE_P(PG(http_globals)[TRACK_VARS_SERVER]) == IS_ARRAY &&
! 605: zend_hash_num_elements(Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_SERVER])) > 0
! 606: ) {
! 607: zval_dtor(array_ptr);
! 608: *array_ptr = *PG(http_globals)[TRACK_VARS_SERVER];
! 609: INIT_PZVAL(array_ptr);
! 610: zval_copy_ctor(array_ptr);
! 611: return;
! 612: }
! 613:
! 614: /* call php's original import as a catch-all */
! 615: php_php_import_environment_variables(array_ptr TSRMLS_CC);
! 616:
! 617: if (fcgi_is_fastcgi()) {
! 618: fcgi_request *request = (fcgi_request*) SG(server_context);
! 619: HashPosition pos;
! 620: int magic_quotes_gpc = PG(magic_quotes_gpc);
! 621: char *var, **val;
! 622: uint var_len;
! 623: ulong idx;
! 624: int filter_arg = (array_ptr == PG(http_globals)[TRACK_VARS_ENV])?PARSE_ENV:PARSE_SERVER;
! 625:
! 626: /* turn off magic_quotes while importing environment variables */
! 627: PG(magic_quotes_gpc) = 0;
! 628: for (zend_hash_internal_pointer_reset_ex(request->env, &pos);
! 629: zend_hash_get_current_key_ex(request->env, &var, &var_len, &idx, 0, &pos) == HASH_KEY_IS_STRING &&
! 630: zend_hash_get_current_data_ex(request->env, (void **) &val, &pos) == SUCCESS;
! 631: zend_hash_move_forward_ex(request->env, &pos)
! 632: ) {
! 633: unsigned int new_val_len;
! 634:
! 635: if (sapi_module.input_filter(filter_arg, var, val, strlen(*val), &new_val_len TSRMLS_CC)) {
! 636: php_register_variable_safe(var, *val, new_val_len, array_ptr TSRMLS_CC);
! 637: }
! 638: }
! 639: PG(magic_quotes_gpc) = magic_quotes_gpc;
! 640: }
! 641: }
! 642:
! 643: static void sapi_cgi_register_variables(zval *track_vars_array TSRMLS_DC)
! 644: {
! 645: unsigned int php_self_len;
! 646: char *php_self;
! 647:
! 648: /* In CGI mode, we consider the environment to be a part of the server
! 649: * variables
! 650: */
! 651: php_import_environment_variables(track_vars_array TSRMLS_CC);
! 652:
! 653: if (CGIG(fix_pathinfo)) {
! 654: char *script_name = SG(request_info).request_uri;
! 655: unsigned int script_name_len = script_name ? strlen(script_name) : 0;
! 656: char *path_info = sapi_cgibin_getenv("PATH_INFO", sizeof("PATH_INFO")-1 TSRMLS_CC);
! 657: unsigned int path_info_len = path_info ? strlen(path_info) : 0;
! 658:
! 659: php_self_len = script_name_len + path_info_len;
! 660: php_self = emalloc(php_self_len + 1);
! 661:
! 662: if (script_name) {
! 663: memcpy(php_self, script_name, script_name_len + 1);
! 664: }
! 665: if (path_info) {
! 666: memcpy(php_self + script_name_len, path_info, path_info_len + 1);
! 667: }
! 668:
! 669: /* Build the special-case PHP_SELF variable for the CGI version */
! 670: if (sapi_module.input_filter(PARSE_SERVER, "PHP_SELF", &php_self, php_self_len, &php_self_len TSRMLS_CC)) {
! 671: php_register_variable_safe("PHP_SELF", php_self, php_self_len, track_vars_array TSRMLS_CC);
! 672: }
! 673: efree(php_self);
! 674: } else {
! 675: php_self = SG(request_info).request_uri ? SG(request_info).request_uri : "";
! 676: php_self_len = strlen(php_self);
! 677: if (sapi_module.input_filter(PARSE_SERVER, "PHP_SELF", &php_self, php_self_len, &php_self_len TSRMLS_CC)) {
! 678: php_register_variable_safe("PHP_SELF", php_self, php_self_len, track_vars_array TSRMLS_CC);
! 679: }
! 680: }
! 681: }
! 682:
! 683: static void sapi_cgi_log_message(char *message)
! 684: {
! 685: TSRMLS_FETCH();
! 686:
! 687: if (fcgi_is_fastcgi() && CGIG(fcgi_logging)) {
! 688: fcgi_request *request;
! 689:
! 690: request = (fcgi_request*) SG(server_context);
! 691: if (request) {
! 692: int len = strlen(message);
! 693: char *buf = malloc(len+2);
! 694:
! 695: memcpy(buf, message, len);
! 696: memcpy(buf + len, "\n", sizeof("\n"));
! 697: fcgi_write(request, FCGI_STDERR, buf, len+1);
! 698: free(buf);
! 699: } else {
! 700: fprintf(stderr, "%s\n", message);
! 701: }
! 702: /* ignore return code */
! 703: } else {
! 704: fprintf(stderr, "%s\n", message);
! 705: }
! 706: }
! 707:
! 708: /* {{{ php_cgi_ini_activate_user_config
! 709: */
! 710: static void php_cgi_ini_activate_user_config(char *path, int path_len, const char *doc_root, int doc_root_len, int start TSRMLS_DC)
! 711: {
! 712: char *ptr;
! 713: user_config_cache_entry *new_entry, *entry;
! 714: time_t request_time = sapi_get_request_time(TSRMLS_C);
! 715:
! 716: /* Find cached config entry: If not found, create one */
! 717: if (zend_hash_find(&CGIG(user_config_cache), path, path_len + 1, (void **) &entry) == FAILURE) {
! 718: new_entry = pemalloc(sizeof(user_config_cache_entry), 1);
! 719: new_entry->expires = 0;
! 720: new_entry->user_config = (HashTable *) pemalloc(sizeof(HashTable), 1);
! 721: zend_hash_init(new_entry->user_config, 0, NULL, (dtor_func_t) config_zval_dtor, 1);
! 722: zend_hash_update(&CGIG(user_config_cache), path, path_len + 1, new_entry, sizeof(user_config_cache_entry), (void **) &entry);
! 723: free(new_entry);
! 724: }
! 725:
! 726: /* Check whether cache entry has expired and rescan if it is */
! 727: if (request_time > entry->expires) {
! 728: char *real_path = NULL;
! 729: int real_path_len;
! 730: char *s1, *s2;
! 731: int s_len;
! 732:
! 733: /* Clear the expired config */
! 734: zend_hash_clean(entry->user_config);
! 735:
! 736: if (!IS_ABSOLUTE_PATH(path, path_len)) {
! 737: real_path = tsrm_realpath(path, NULL TSRMLS_CC);
! 738: /* see #51688, looks like we may get invalid path as doc root using cgi with apache */
! 739: if (real_path == NULL) {
! 740: return;
! 741: }
! 742: real_path_len = strlen(real_path);
! 743: path = real_path;
! 744: path_len = real_path_len;
! 745: }
! 746:
! 747: if (path_len > doc_root_len) {
! 748: s1 = (char *) doc_root;
! 749: s2 = path;
! 750: s_len = doc_root_len;
! 751: } else {
! 752: s1 = path;
! 753: s2 = (char *) doc_root;
! 754: s_len = path_len;
! 755: }
! 756:
! 757: /* we have to test if path is part of DOCUMENT_ROOT.
! 758: if it is inside the docroot, we scan the tree up to the docroot
! 759: to find more user.ini, if not we only scan the current path.
! 760: */
! 761: #ifdef PHP_WIN32
! 762: if (strnicmp(s1, s2, s_len) == 0) {
! 763: #else
! 764: if (strncmp(s1, s2, s_len) == 0) {
! 765: #endif
! 766: ptr = s2 + start; /* start is the point where doc_root ends! */
! 767: while ((ptr = strchr(ptr, DEFAULT_SLASH)) != NULL) {
! 768: *ptr = 0;
! 769: php_parse_user_ini_file(path, PG(user_ini_filename), entry->user_config TSRMLS_CC);
! 770: *ptr = '/';
! 771: ptr++;
! 772: }
! 773: } else {
! 774: php_parse_user_ini_file(path, PG(user_ini_filename), entry->user_config TSRMLS_CC);
! 775: }
! 776:
! 777: if (real_path) {
! 778: free(real_path);
! 779: }
! 780: entry->expires = request_time + PG(user_ini_cache_ttl);
! 781: }
! 782:
! 783: /* Activate ini entries with values from the user config hash */
! 784: php_ini_activate_config(entry->user_config, PHP_INI_PERDIR, PHP_INI_STAGE_HTACCESS TSRMLS_CC);
! 785: }
! 786: /* }}} */
! 787:
! 788: static int sapi_cgi_activate(TSRMLS_D)
! 789: {
! 790: char *path, *doc_root, *server_name;
! 791: uint path_len, doc_root_len, server_name_len;
! 792:
! 793: /* PATH_TRANSLATED should be defined at this stage but better safe than sorry :) */
! 794: if (!SG(request_info).path_translated) {
! 795: return FAILURE;
! 796: }
! 797:
! 798: if (php_ini_has_per_host_config()) {
! 799: /* Activate per-host-system-configuration defined in php.ini and stored into configuration_hash during startup */
! 800: server_name = sapi_cgibin_getenv("SERVER_NAME", sizeof("SERVER_NAME") - 1 TSRMLS_CC);
! 801: /* SERVER_NAME should also be defined at this stage..but better check it anyway */
! 802: if (server_name) {
! 803: server_name_len = strlen(server_name);
! 804: server_name = estrndup(server_name, server_name_len);
! 805: zend_str_tolower(server_name, server_name_len);
! 806: php_ini_activate_per_host_config(server_name, server_name_len + 1 TSRMLS_CC);
! 807: efree(server_name);
! 808: }
! 809: }
! 810:
! 811: if (php_ini_has_per_dir_config() ||
! 812: (PG(user_ini_filename) && *PG(user_ini_filename))
! 813: ) {
! 814: /* Prepare search path */
! 815: path_len = strlen(SG(request_info).path_translated);
! 816:
! 817: /* Make sure we have trailing slash! */
! 818: if (!IS_SLASH(SG(request_info).path_translated[path_len])) {
! 819: path = emalloc(path_len + 2);
! 820: memcpy(path, SG(request_info).path_translated, path_len + 1);
! 821: path_len = zend_dirname(path, path_len);
! 822: path[path_len++] = DEFAULT_SLASH;
! 823: } else {
! 824: path = estrndup(SG(request_info).path_translated, path_len);
! 825: path_len = zend_dirname(path, path_len);
! 826: }
! 827: path[path_len] = 0;
! 828:
! 829: /* Activate per-dir-system-configuration defined in php.ini and stored into configuration_hash during startup */
! 830: php_ini_activate_per_dir_config(path, path_len TSRMLS_CC); /* Note: for global settings sake we check from root to path */
! 831:
! 832: /* Load and activate user ini files in path starting from DOCUMENT_ROOT */
! 833: if (PG(user_ini_filename) && *PG(user_ini_filename)) {
! 834: doc_root = sapi_cgibin_getenv("DOCUMENT_ROOT", sizeof("DOCUMENT_ROOT") - 1 TSRMLS_CC);
! 835: /* DOCUMENT_ROOT should also be defined at this stage..but better check it anyway */
! 836: if (doc_root) {
! 837: doc_root_len = strlen(doc_root);
! 838: if (doc_root_len > 0 && IS_SLASH(doc_root[doc_root_len - 1])) {
! 839: --doc_root_len;
! 840: }
! 841: #ifdef PHP_WIN32
! 842: /* paths on windows should be case-insensitive */
! 843: doc_root = estrndup(doc_root, doc_root_len);
! 844: zend_str_tolower(doc_root, doc_root_len);
! 845: #endif
! 846: php_cgi_ini_activate_user_config(path, path_len, doc_root, doc_root_len, doc_root_len - 1 TSRMLS_CC);
! 847: }
! 848: }
! 849:
! 850: #ifdef PHP_WIN32
! 851: efree(doc_root);
! 852: #endif
! 853: efree(path);
! 854: }
! 855:
! 856: return SUCCESS;
! 857: }
! 858:
! 859: static int sapi_cgi_deactivate(TSRMLS_D)
! 860: {
! 861: /* flush only when SAPI was started. The reasons are:
! 862: 1. SAPI Deactivate is called from two places: module init and request shutdown
! 863: 2. When the first call occurs and the request is not set up, flush fails on FastCGI.
! 864: */
! 865: if (SG(sapi_started)) {
! 866: if (fcgi_is_fastcgi()) {
! 867: if (
! 868: #ifndef PHP_WIN32
! 869: !parent &&
! 870: #endif
! 871: !fcgi_finish_request((fcgi_request*)SG(server_context), 0)) {
! 872: php_handle_aborted_connection();
! 873: }
! 874: } else {
! 875: sapi_cgibin_flush(SG(server_context));
! 876: }
! 877: }
! 878: return SUCCESS;
! 879: }
! 880:
! 881: static int php_cgi_startup(sapi_module_struct *sapi_module)
! 882: {
! 883: if (php_module_startup(sapi_module, &cgi_module_entry, 1) == FAILURE) {
! 884: return FAILURE;
! 885: }
! 886: return SUCCESS;
! 887: }
! 888:
! 889: /* {{{ sapi_module_struct cgi_sapi_module
! 890: */
! 891: static sapi_module_struct cgi_sapi_module = {
! 892: "cgi-fcgi", /* name */
! 893: "CGI/FastCGI", /* pretty name */
! 894:
! 895: php_cgi_startup, /* startup */
! 896: php_module_shutdown_wrapper, /* shutdown */
! 897:
! 898: sapi_cgi_activate, /* activate */
! 899: sapi_cgi_deactivate, /* deactivate */
! 900:
! 901: sapi_cgibin_ub_write, /* unbuffered write */
! 902: sapi_cgibin_flush, /* flush */
! 903: NULL, /* get uid */
! 904: sapi_cgibin_getenv, /* getenv */
! 905:
! 906: php_error, /* error handler */
! 907:
! 908: NULL, /* header handler */
! 909: sapi_cgi_send_headers, /* send headers handler */
! 910: NULL, /* send header handler */
! 911:
! 912: sapi_cgi_read_post, /* read POST data */
! 913: sapi_cgi_read_cookies, /* read Cookies */
! 914:
! 915: sapi_cgi_register_variables, /* register server variables */
! 916: sapi_cgi_log_message, /* Log message */
! 917: NULL, /* Get request time */
! 918: NULL, /* Child terminate */
! 919:
! 920: STANDARD_SAPI_MODULE_PROPERTIES
! 921: };
! 922: /* }}} */
! 923:
! 924: /* {{{ arginfo ext/standard/dl.c */
! 925: ZEND_BEGIN_ARG_INFO(arginfo_dl, 0)
! 926: ZEND_ARG_INFO(0, extension_filename)
! 927: ZEND_END_ARG_INFO()
! 928: /* }}} */
! 929:
! 930: static const zend_function_entry additional_functions[] = {
! 931: ZEND_FE(dl, arginfo_dl)
! 932: {NULL, NULL, NULL}
! 933: };
! 934:
! 935: /* {{{ php_cgi_usage
! 936: */
! 937: static void php_cgi_usage(char *argv0)
! 938: {
! 939: char *prog;
! 940:
! 941: prog = strrchr(argv0, '/');
! 942: if (prog) {
! 943: prog++;
! 944: } else {
! 945: prog = "php";
! 946: }
! 947:
! 948: php_printf( "Usage: %s [-q] [-h] [-s] [-v] [-i] [-f <file>]\n"
! 949: " %s <file> [args...]\n"
! 950: " -a Run interactively\n"
! 951: " -b <address:port>|<port> Bind Path for external FASTCGI Server mode\n"
! 952: " -C Do not chdir to the script's directory\n"
! 953: " -c <path>|<file> Look for php.ini file in this directory\n"
! 954: " -n No php.ini file will be used\n"
! 955: " -d foo[=bar] Define INI entry foo with value 'bar'\n"
! 956: " -e Generate extended information for debugger/profiler\n"
! 957: " -f <file> Parse <file>. Implies `-q'\n"
! 958: " -h This help\n"
! 959: " -i PHP information\n"
! 960: " -l Syntax check only (lint)\n"
! 961: " -m Show compiled in modules\n"
! 962: " -q Quiet-mode. Suppress HTTP Header output.\n"
! 963: " -s Display colour syntax highlighted source.\n"
! 964: " -v Version number\n"
! 965: " -w Display source with stripped comments and whitespace.\n"
! 966: " -z <file> Load Zend extension <file>.\n"
! 967: " -T <count> Measure execution time of script repeated <count> times.\n",
! 968: prog, prog);
! 969: }
! 970: /* }}} */
! 971:
! 972: /* {{{ is_valid_path
! 973: *
! 974: * some server configurations allow '..' to slip through in the
! 975: * translated path. We'll just refuse to handle such a path.
! 976: */
! 977: static int is_valid_path(const char *path)
! 978: {
! 979: const char *p;
! 980:
! 981: if (!path) {
! 982: return 0;
! 983: }
! 984: p = strstr(path, "..");
! 985: if (p) {
! 986: if ((p == path || IS_SLASH(*(p-1))) &&
! 987: (*(p+2) == 0 || IS_SLASH(*(p+2)))
! 988: ) {
! 989: return 0;
! 990: }
! 991: while (1) {
! 992: p = strstr(p+1, "..");
! 993: if (!p) {
! 994: break;
! 995: }
! 996: if (IS_SLASH(*(p-1)) &&
! 997: (*(p+2) == 0 || IS_SLASH(*(p+2)))
! 998: ) {
! 999: return 0;
! 1000: }
! 1001: }
! 1002: }
! 1003: return 1;
! 1004: }
! 1005: /* }}} */
! 1006:
! 1007: /* {{{ init_request_info
! 1008:
! 1009: initializes request_info structure
! 1010:
! 1011: specificly in this section we handle proper translations
! 1012: for:
! 1013:
! 1014: PATH_INFO
! 1015: derived from the portion of the URI path following
! 1016: the script name but preceding any query data
! 1017: may be empty
! 1018:
! 1019: PATH_TRANSLATED
! 1020: derived by taking any path-info component of the
! 1021: request URI and performing any virtual-to-physical
! 1022: translation appropriate to map it onto the server's
! 1023: document repository structure
! 1024:
! 1025: empty if PATH_INFO is empty
! 1026:
! 1027: The env var PATH_TRANSLATED **IS DIFFERENT** than the
! 1028: request_info.path_translated variable, the latter should
! 1029: match SCRIPT_FILENAME instead.
! 1030:
! 1031: SCRIPT_NAME
! 1032: set to a URL path that could identify the CGI script
! 1033: rather than the interpreter. PHP_SELF is set to this
! 1034:
! 1035: REQUEST_URI
! 1036: uri section following the domain:port part of a URI
! 1037:
! 1038: SCRIPT_FILENAME
! 1039: The virtual-to-physical translation of SCRIPT_NAME (as per
! 1040: PATH_TRANSLATED)
! 1041:
! 1042: These settings are documented at
! 1043: http://cgi-spec.golux.com/
! 1044:
! 1045:
! 1046: Based on the following URL request:
! 1047:
! 1048: http://localhost/info.php/test?a=b
! 1049:
! 1050: should produce, which btw is the same as if
! 1051: we were running under mod_cgi on apache (ie. not
! 1052: using ScriptAlias directives):
! 1053:
! 1054: PATH_INFO=/test
! 1055: PATH_TRANSLATED=/docroot/test
! 1056: SCRIPT_NAME=/info.php
! 1057: REQUEST_URI=/info.php/test?a=b
! 1058: SCRIPT_FILENAME=/docroot/info.php
! 1059: QUERY_STRING=a=b
! 1060:
! 1061: but what we get is (cgi/mod_fastcgi under apache):
! 1062:
! 1063: PATH_INFO=/info.php/test
! 1064: PATH_TRANSLATED=/docroot/info.php/test
! 1065: SCRIPT_NAME=/php/php-cgi (from the Action setting I suppose)
! 1066: REQUEST_URI=/info.php/test?a=b
! 1067: SCRIPT_FILENAME=/path/to/php/bin/php-cgi (Action setting translated)
! 1068: QUERY_STRING=a=b
! 1069:
! 1070: Comments in the code below refer to using the above URL in a request
! 1071:
! 1072: */
! 1073: static void init_request_info(TSRMLS_D)
! 1074: {
! 1075: char *env_script_filename = sapi_cgibin_getenv("SCRIPT_FILENAME", sizeof("SCRIPT_FILENAME")-1 TSRMLS_CC);
! 1076: char *env_path_translated = sapi_cgibin_getenv("PATH_TRANSLATED", sizeof("PATH_TRANSLATED")-1 TSRMLS_CC);
! 1077: char *script_path_translated = env_script_filename;
! 1078:
! 1079: /* some broken servers do not have script_filename or argv0
! 1080: * an example, IIS configured in some ways. then they do more
! 1081: * broken stuff and set path_translated to the cgi script location */
! 1082: if (!script_path_translated && env_path_translated) {
! 1083: script_path_translated = env_path_translated;
! 1084: }
! 1085:
! 1086: /* initialize the defaults */
! 1087: SG(request_info).path_translated = NULL;
! 1088: SG(request_info).request_method = NULL;
! 1089: SG(request_info).proto_num = 1000;
! 1090: SG(request_info).query_string = NULL;
! 1091: SG(request_info).request_uri = NULL;
! 1092: SG(request_info).content_type = NULL;
! 1093: SG(request_info).content_length = 0;
! 1094: SG(sapi_headers).http_response_code = 200;
! 1095:
! 1096: /* script_path_translated being set is a good indication that
! 1097: * we are running in a cgi environment, since it is always
! 1098: * null otherwise. otherwise, the filename
! 1099: * of the script will be retreived later via argc/argv */
! 1100: if (script_path_translated) {
! 1101: const char *auth;
! 1102: char *content_length = sapi_cgibin_getenv("CONTENT_LENGTH", sizeof("CONTENT_LENGTH")-1 TSRMLS_CC);
! 1103: char *content_type = sapi_cgibin_getenv("CONTENT_TYPE", sizeof("CONTENT_TYPE")-1 TSRMLS_CC);
! 1104: char *env_path_info = sapi_cgibin_getenv("PATH_INFO", sizeof("PATH_INFO")-1 TSRMLS_CC);
! 1105: char *env_script_name = sapi_cgibin_getenv("SCRIPT_NAME", sizeof("SCRIPT_NAME")-1 TSRMLS_CC);
! 1106:
! 1107: /* Hack for buggy IIS that sets incorrect PATH_INFO */
! 1108: char *env_server_software = sapi_cgibin_getenv("SERVER_SOFTWARE", sizeof("SERVER_SOFTWARE")-1 TSRMLS_CC);
! 1109: if (env_server_software &&
! 1110: env_script_name &&
! 1111: env_path_info &&
! 1112: strncmp(env_server_software, "Microsoft-IIS", sizeof("Microsoft-IIS")-1) == 0 &&
! 1113: strncmp(env_path_info, env_script_name, strlen(env_script_name)) == 0
! 1114: ) {
! 1115: env_path_info = _sapi_cgibin_putenv("ORIG_PATH_INFO", env_path_info TSRMLS_CC);
! 1116: env_path_info += strlen(env_script_name);
! 1117: if (*env_path_info == 0) {
! 1118: env_path_info = NULL;
! 1119: }
! 1120: env_path_info = _sapi_cgibin_putenv("PATH_INFO", env_path_info TSRMLS_CC);
! 1121: }
! 1122:
! 1123: if (CGIG(fix_pathinfo)) {
! 1124: struct stat st;
! 1125: char *real_path = NULL;
! 1126: char *env_redirect_url = sapi_cgibin_getenv("REDIRECT_URL", sizeof("REDIRECT_URL")-1 TSRMLS_CC);
! 1127: char *env_document_root = sapi_cgibin_getenv("DOCUMENT_ROOT", sizeof("DOCUMENT_ROOT")-1 TSRMLS_CC);
! 1128: char *orig_path_translated = env_path_translated;
! 1129: char *orig_path_info = env_path_info;
! 1130: char *orig_script_name = env_script_name;
! 1131: char *orig_script_filename = env_script_filename;
! 1132: int script_path_translated_len;
! 1133:
! 1134: if (!env_document_root && PG(doc_root)) {
! 1135: env_document_root = _sapi_cgibin_putenv("DOCUMENT_ROOT", PG(doc_root) TSRMLS_CC);
! 1136: /* fix docroot */
! 1137: TRANSLATE_SLASHES(env_document_root);
! 1138: }
! 1139:
! 1140: if (env_path_translated != NULL && env_redirect_url != NULL &&
! 1141: env_path_translated != script_path_translated &&
! 1142: strcmp(env_path_translated, script_path_translated) != 0) {
! 1143: /*
! 1144: * pretty much apache specific. If we have a redirect_url
! 1145: * then our script_filename and script_name point to the
! 1146: * php executable
! 1147: */
! 1148: script_path_translated = env_path_translated;
! 1149: /* we correct SCRIPT_NAME now in case we don't have PATH_INFO */
! 1150: env_script_name = env_redirect_url;
! 1151: }
! 1152:
! 1153: #ifdef __riscos__
! 1154: /* Convert path to unix format*/
! 1155: __riscosify_control |= __RISCOSIFY_DONT_CHECK_DIR;
! 1156: script_path_translated = __unixify(script_path_translated, 0, NULL, 1, 0);
! 1157: #endif
! 1158:
! 1159: /*
! 1160: * if the file doesn't exist, try to extract PATH_INFO out
! 1161: * of it by stat'ing back through the '/'
! 1162: * this fixes url's like /info.php/test
! 1163: */
! 1164: if (script_path_translated &&
! 1165: (script_path_translated_len = strlen(script_path_translated)) > 0 &&
! 1166: (script_path_translated[script_path_translated_len-1] == '/' ||
! 1167: #ifdef PHP_WIN32
! 1168: script_path_translated[script_path_translated_len-1] == '\\' ||
! 1169: #endif
! 1170: (real_path = tsrm_realpath(script_path_translated, NULL TSRMLS_CC)) == NULL)
! 1171: ) {
! 1172: char *pt = estrndup(script_path_translated, script_path_translated_len);
! 1173: int len = script_path_translated_len;
! 1174: char *ptr;
! 1175:
! 1176: while ((ptr = strrchr(pt, '/')) || (ptr = strrchr(pt, '\\'))) {
! 1177: *ptr = 0;
! 1178: if (stat(pt, &st) == 0 && S_ISREG(st.st_mode)) {
! 1179: /*
! 1180: * okay, we found the base script!
! 1181: * work out how many chars we had to strip off;
! 1182: * then we can modify PATH_INFO
! 1183: * accordingly
! 1184: *
! 1185: * we now have the makings of
! 1186: * PATH_INFO=/test
! 1187: * SCRIPT_FILENAME=/docroot/info.php
! 1188: *
! 1189: * we now need to figure out what docroot is.
! 1190: * if DOCUMENT_ROOT is set, this is easy, otherwise,
! 1191: * we have to play the game of hide and seek to figure
! 1192: * out what SCRIPT_NAME should be
! 1193: */
! 1194: int slen = len - strlen(pt);
! 1195: int pilen = env_path_info ? strlen(env_path_info) : 0;
! 1196: char *path_info = env_path_info ? env_path_info + pilen - slen : NULL;
! 1197:
! 1198: if (orig_path_info != path_info) {
! 1199: if (orig_path_info) {
! 1200: char old;
! 1201:
! 1202: _sapi_cgibin_putenv("ORIG_PATH_INFO", orig_path_info TSRMLS_CC);
! 1203: old = path_info[0];
! 1204: path_info[0] = 0;
! 1205: if (!orig_script_name ||
! 1206: strcmp(orig_script_name, env_path_info) != 0) {
! 1207: if (orig_script_name) {
! 1208: _sapi_cgibin_putenv("ORIG_SCRIPT_NAME", orig_script_name TSRMLS_CC);
! 1209: }
! 1210: SG(request_info).request_uri = _sapi_cgibin_putenv("SCRIPT_NAME", env_path_info TSRMLS_CC);
! 1211: } else {
! 1212: SG(request_info).request_uri = orig_script_name;
! 1213: }
! 1214: path_info[0] = old;
! 1215: }
! 1216: env_path_info = _sapi_cgibin_putenv("PATH_INFO", path_info TSRMLS_CC);
! 1217: }
! 1218: if (!orig_script_filename ||
! 1219: strcmp(orig_script_filename, pt) != 0) {
! 1220: if (orig_script_filename) {
! 1221: _sapi_cgibin_putenv("ORIG_SCRIPT_FILENAME", orig_script_filename TSRMLS_CC);
! 1222: }
! 1223: script_path_translated = _sapi_cgibin_putenv("SCRIPT_FILENAME", pt TSRMLS_CC);
! 1224: }
! 1225: TRANSLATE_SLASHES(pt);
! 1226:
! 1227: /* figure out docroot
! 1228: * SCRIPT_FILENAME minus SCRIPT_NAME
! 1229: */
! 1230: if (env_document_root) {
! 1231: int l = strlen(env_document_root);
! 1232: int path_translated_len = 0;
! 1233: char *path_translated = NULL;
! 1234:
! 1235: if (l && env_document_root[l - 1] == '/') {
! 1236: --l;
! 1237: }
! 1238:
! 1239: /* we have docroot, so we should have:
! 1240: * DOCUMENT_ROOT=/docroot
! 1241: * SCRIPT_FILENAME=/docroot/info.php
! 1242: */
! 1243:
! 1244: /* PATH_TRANSLATED = DOCUMENT_ROOT + PATH_INFO */
! 1245: path_translated_len = l + (env_path_info ? strlen(env_path_info) : 0);
! 1246: path_translated = (char *) emalloc(path_translated_len + 1);
! 1247: memcpy(path_translated, env_document_root, l);
! 1248: if (env_path_info) {
! 1249: memcpy(path_translated + l, env_path_info, (path_translated_len - l));
! 1250: }
! 1251: path_translated[path_translated_len] = '\0';
! 1252: if (orig_path_translated) {
! 1253: _sapi_cgibin_putenv("ORIG_PATH_TRANSLATED", orig_path_translated TSRMLS_CC);
! 1254: }
! 1255: env_path_translated = _sapi_cgibin_putenv("PATH_TRANSLATED", path_translated TSRMLS_CC);
! 1256: efree(path_translated);
! 1257: } else if ( env_script_name &&
! 1258: strstr(pt, env_script_name)
! 1259: ) {
! 1260: /* PATH_TRANSLATED = PATH_TRANSLATED - SCRIPT_NAME + PATH_INFO */
! 1261: int ptlen = strlen(pt) - strlen(env_script_name);
! 1262: int path_translated_len = ptlen + (env_path_info ? strlen(env_path_info) : 0);
! 1263: char *path_translated = NULL;
! 1264:
! 1265: path_translated = (char *) emalloc(path_translated_len + 1);
! 1266: memcpy(path_translated, pt, ptlen);
! 1267: if (env_path_info) {
! 1268: memcpy(path_translated + ptlen, env_path_info, path_translated_len - ptlen);
! 1269: }
! 1270: path_translated[path_translated_len] = '\0';
! 1271: if (orig_path_translated) {
! 1272: _sapi_cgibin_putenv("ORIG_PATH_TRANSLATED", orig_path_translated TSRMLS_CC);
! 1273: }
! 1274: env_path_translated = _sapi_cgibin_putenv("PATH_TRANSLATED", path_translated TSRMLS_CC);
! 1275: efree(path_translated);
! 1276: }
! 1277: break;
! 1278: }
! 1279: }
! 1280: if (!ptr) {
! 1281: /*
! 1282: * if we stripped out all the '/' and still didn't find
! 1283: * a valid path... we will fail, badly. of course we would
! 1284: * have failed anyway... we output 'no input file' now.
! 1285: */
! 1286: if (orig_script_filename) {
! 1287: _sapi_cgibin_putenv("ORIG_SCRIPT_FILENAME", orig_script_filename TSRMLS_CC);
! 1288: }
! 1289: script_path_translated = _sapi_cgibin_putenv("SCRIPT_FILENAME", NULL TSRMLS_CC);
! 1290: SG(sapi_headers).http_response_code = 404;
! 1291: }
! 1292: if (!SG(request_info).request_uri) {
! 1293: if (!orig_script_name ||
! 1294: strcmp(orig_script_name, env_script_name) != 0) {
! 1295: if (orig_script_name) {
! 1296: _sapi_cgibin_putenv("ORIG_SCRIPT_NAME", orig_script_name TSRMLS_CC);
! 1297: }
! 1298: SG(request_info).request_uri = _sapi_cgibin_putenv("SCRIPT_NAME", env_script_name TSRMLS_CC);
! 1299: } else {
! 1300: SG(request_info).request_uri = orig_script_name;
! 1301: }
! 1302: }
! 1303: if (pt) {
! 1304: efree(pt);
! 1305: }
! 1306: } else {
! 1307: /* make sure path_info/translated are empty */
! 1308: if (!orig_script_filename ||
! 1309: (script_path_translated != orig_script_filename &&
! 1310: strcmp(script_path_translated, orig_script_filename) != 0)) {
! 1311: if (orig_script_filename) {
! 1312: _sapi_cgibin_putenv("ORIG_SCRIPT_FILENAME", orig_script_filename TSRMLS_CC);
! 1313: }
! 1314: script_path_translated = _sapi_cgibin_putenv("SCRIPT_FILENAME", script_path_translated TSRMLS_CC);
! 1315: }
! 1316: if (env_redirect_url) {
! 1317: if (orig_path_info) {
! 1318: _sapi_cgibin_putenv("ORIG_PATH_INFO", orig_path_info TSRMLS_CC);
! 1319: _sapi_cgibin_putenv("PATH_INFO", NULL TSRMLS_CC);
! 1320: }
! 1321: if (orig_path_translated) {
! 1322: _sapi_cgibin_putenv("ORIG_PATH_TRANSLATED", orig_path_translated TSRMLS_CC);
! 1323: _sapi_cgibin_putenv("PATH_TRANSLATED", NULL TSRMLS_CC);
! 1324: }
! 1325: }
! 1326: if (env_script_name != orig_script_name) {
! 1327: if (orig_script_name) {
! 1328: _sapi_cgibin_putenv("ORIG_SCRIPT_NAME", orig_script_name TSRMLS_CC);
! 1329: }
! 1330: SG(request_info).request_uri = _sapi_cgibin_putenv("SCRIPT_NAME", env_script_name TSRMLS_CC);
! 1331: } else {
! 1332: SG(request_info).request_uri = env_script_name;
! 1333: }
! 1334: free(real_path);
! 1335: }
! 1336: } else {
! 1337: /* pre 4.3 behaviour, shouldn't be used but provides BC */
! 1338: if (env_path_info) {
! 1339: SG(request_info).request_uri = env_path_info;
! 1340: } else {
! 1341: SG(request_info).request_uri = env_script_name;
! 1342: }
! 1343: if (!CGIG(discard_path) && env_path_translated) {
! 1344: script_path_translated = env_path_translated;
! 1345: }
! 1346: }
! 1347:
! 1348: if (is_valid_path(script_path_translated)) {
! 1349: SG(request_info).path_translated = estrdup(script_path_translated);
! 1350: }
! 1351:
! 1352: SG(request_info).request_method = sapi_cgibin_getenv("REQUEST_METHOD", sizeof("REQUEST_METHOD")-1 TSRMLS_CC);
! 1353: /* FIXME - Work out proto_num here */
! 1354: SG(request_info).query_string = sapi_cgibin_getenv("QUERY_STRING", sizeof("QUERY_STRING")-1 TSRMLS_CC);
! 1355: SG(request_info).content_type = (content_type ? content_type : "" );
! 1356: SG(request_info).content_length = (content_length ? atol(content_length) : 0);
! 1357:
! 1358: /* The CGI RFC allows servers to pass on unvalidated Authorization data */
! 1359: auth = sapi_cgibin_getenv("HTTP_AUTHORIZATION", sizeof("HTTP_AUTHORIZATION")-1 TSRMLS_CC);
! 1360: php_handle_auth_data(auth TSRMLS_CC);
! 1361: }
! 1362: }
! 1363: /* }}} */
! 1364:
! 1365: #ifndef PHP_WIN32
! 1366: /**
! 1367: * Clean up child processes upon exit
! 1368: */
! 1369: void fastcgi_cleanup(int signal)
! 1370: {
! 1371: #ifdef DEBUG_FASTCGI
! 1372: fprintf(stderr, "FastCGI shutdown, pid %d\n", getpid());
! 1373: #endif
! 1374:
! 1375: sigaction(SIGTERM, &old_term, 0);
! 1376:
! 1377: /* Kill all the processes in our process group */
! 1378: kill(-pgroup, SIGTERM);
! 1379:
! 1380: if (parent && parent_waiting) {
! 1381: exit_signal = 1;
! 1382: } else {
! 1383: exit(0);
! 1384: }
! 1385: }
! 1386: #endif
! 1387:
! 1388: PHP_INI_BEGIN()
! 1389: STD_PHP_INI_ENTRY("cgi.rfc2616_headers", "0", PHP_INI_ALL, OnUpdateBool, rfc2616_headers, php_cgi_globals_struct, php_cgi_globals)
! 1390: STD_PHP_INI_ENTRY("cgi.nph", "0", PHP_INI_ALL, OnUpdateBool, nph, php_cgi_globals_struct, php_cgi_globals)
! 1391: STD_PHP_INI_ENTRY("cgi.check_shebang_line", "1", PHP_INI_SYSTEM, OnUpdateBool, check_shebang_line, php_cgi_globals_struct, php_cgi_globals)
! 1392: STD_PHP_INI_ENTRY("cgi.force_redirect", "1", PHP_INI_SYSTEM, OnUpdateBool, force_redirect, php_cgi_globals_struct, php_cgi_globals)
! 1393: STD_PHP_INI_ENTRY("cgi.redirect_status_env", NULL, PHP_INI_SYSTEM, OnUpdateString, redirect_status_env, php_cgi_globals_struct, php_cgi_globals)
! 1394: STD_PHP_INI_ENTRY("cgi.fix_pathinfo", "1", PHP_INI_SYSTEM, OnUpdateBool, fix_pathinfo, php_cgi_globals_struct, php_cgi_globals)
! 1395: STD_PHP_INI_ENTRY("cgi.discard_path", "0", PHP_INI_SYSTEM, OnUpdateBool, discard_path, php_cgi_globals_struct, php_cgi_globals)
! 1396: STD_PHP_INI_ENTRY("fastcgi.logging", "1", PHP_INI_SYSTEM, OnUpdateBool, fcgi_logging, php_cgi_globals_struct, php_cgi_globals)
! 1397: #ifdef PHP_WIN32
! 1398: STD_PHP_INI_ENTRY("fastcgi.impersonate", "0", PHP_INI_SYSTEM, OnUpdateBool, impersonate, php_cgi_globals_struct, php_cgi_globals)
! 1399: #endif
! 1400: PHP_INI_END()
! 1401:
! 1402: /* {{{ php_cgi_globals_ctor
! 1403: */
! 1404: static void php_cgi_globals_ctor(php_cgi_globals_struct *php_cgi_globals TSRMLS_DC)
! 1405: {
! 1406: php_cgi_globals->rfc2616_headers = 0;
! 1407: php_cgi_globals->nph = 0;
! 1408: php_cgi_globals->check_shebang_line = 1;
! 1409: php_cgi_globals->force_redirect = 1;
! 1410: php_cgi_globals->redirect_status_env = NULL;
! 1411: php_cgi_globals->fix_pathinfo = 1;
! 1412: php_cgi_globals->discard_path = 0;
! 1413: php_cgi_globals->fcgi_logging = 1;
! 1414: #ifdef PHP_WIN32
! 1415: php_cgi_globals->impersonate = 0;
! 1416: #endif
! 1417: zend_hash_init(&php_cgi_globals->user_config_cache, 0, NULL, (dtor_func_t) user_config_cache_entry_dtor, 1);
! 1418: }
! 1419: /* }}} */
! 1420:
! 1421: /* {{{ PHP_MINIT_FUNCTION
! 1422: */
! 1423: static PHP_MINIT_FUNCTION(cgi)
! 1424: {
! 1425: #ifdef ZTS
! 1426: ts_allocate_id(&php_cgi_globals_id, sizeof(php_cgi_globals_struct), (ts_allocate_ctor) php_cgi_globals_ctor, NULL);
! 1427: #else
! 1428: php_cgi_globals_ctor(&php_cgi_globals TSRMLS_CC);
! 1429: #endif
! 1430: REGISTER_INI_ENTRIES();
! 1431: return SUCCESS;
! 1432: }
! 1433: /* }}} */
! 1434:
! 1435: /* {{{ PHP_MSHUTDOWN_FUNCTION
! 1436: */
! 1437: static PHP_MSHUTDOWN_FUNCTION(cgi)
! 1438: {
! 1439: zend_hash_destroy(&CGIG(user_config_cache));
! 1440:
! 1441: UNREGISTER_INI_ENTRIES();
! 1442: return SUCCESS;
! 1443: }
! 1444: /* }}} */
! 1445:
! 1446: /* {{{ PHP_MINFO_FUNCTION
! 1447: */
! 1448: static PHP_MINFO_FUNCTION(cgi)
! 1449: {
! 1450: DISPLAY_INI_ENTRIES();
! 1451: }
! 1452: /* }}} */
! 1453:
! 1454: static zend_module_entry cgi_module_entry = {
! 1455: STANDARD_MODULE_HEADER,
! 1456: "cgi-fcgi",
! 1457: NULL,
! 1458: PHP_MINIT(cgi),
! 1459: PHP_MSHUTDOWN(cgi),
! 1460: NULL,
! 1461: NULL,
! 1462: PHP_MINFO(cgi),
! 1463: NO_VERSION_YET,
! 1464: STANDARD_MODULE_PROPERTIES
! 1465: };
! 1466:
! 1467: /* {{{ main
! 1468: */
! 1469: int main(int argc, char *argv[])
! 1470: {
! 1471: int free_query_string = 0;
! 1472: int exit_status = SUCCESS;
! 1473: int cgi = 0, c, i, len;
! 1474: zend_file_handle file_handle;
! 1475: char *s;
! 1476:
! 1477: /* temporary locals */
! 1478: int behavior = PHP_MODE_STANDARD;
! 1479: int no_headers = 0;
! 1480: int orig_optind = php_optind;
! 1481: char *orig_optarg = php_optarg;
! 1482: char *script_file = NULL;
! 1483: int ini_entries_len = 0;
! 1484: /* end of temporary locals */
! 1485:
! 1486: #ifdef ZTS
! 1487: void ***tsrm_ls;
! 1488: #endif
! 1489:
! 1490: int max_requests = 500;
! 1491: int requests = 0;
! 1492: int fastcgi = fcgi_is_fastcgi();
! 1493: char *bindpath = NULL;
! 1494: int fcgi_fd = 0;
! 1495: fcgi_request request;
! 1496: int repeats = 1;
! 1497: int benchmark = 0;
! 1498: #if HAVE_GETTIMEOFDAY
! 1499: struct timeval start, end;
! 1500: #else
! 1501: time_t start, end;
! 1502: #endif
! 1503: #ifndef PHP_WIN32
! 1504: int status = 0;
! 1505: #endif
! 1506:
! 1507: #if 0 && defined(PHP_DEBUG)
! 1508: /* IIS is always making things more difficult. This allows
! 1509: * us to stop PHP and attach a debugger before much gets started */
! 1510: {
! 1511: char szMessage [256];
! 1512: wsprintf (szMessage, "Please attach a debugger to the process 0x%X [%d] (%s) and click OK", GetCurrentProcessId(), GetCurrentProcessId(), argv[0]);
! 1513: MessageBox(NULL, szMessage, "CGI Debug Time!", MB_OK|MB_SERVICE_NOTIFICATION);
! 1514: }
! 1515: #endif
! 1516:
! 1517: #ifdef HAVE_SIGNAL_H
! 1518: #if defined(SIGPIPE) && defined(SIG_IGN)
! 1519: signal(SIGPIPE, SIG_IGN); /* ignore SIGPIPE in standalone mode so
! 1520: that sockets created via fsockopen()
! 1521: don't kill PHP if the remote site
! 1522: closes it. in apache|apxs mode apache
! 1523: does that for us! thies@thieso.net
! 1524: 20000419 */
! 1525: #endif
! 1526: #endif
! 1527:
! 1528: #ifdef ZTS
! 1529: tsrm_startup(1, 1, 0, NULL);
! 1530: tsrm_ls = ts_resource(0);
! 1531: #endif
! 1532:
! 1533: sapi_startup(&cgi_sapi_module);
! 1534: cgi_sapi_module.php_ini_path_override = NULL;
! 1535:
! 1536: #ifdef PHP_WIN32
! 1537: _fmode = _O_BINARY; /* sets default for file streams to binary */
! 1538: setmode(_fileno(stdin), O_BINARY); /* make the stdio mode be binary */
! 1539: setmode(_fileno(stdout), O_BINARY); /* make the stdio mode be binary */
! 1540: setmode(_fileno(stderr), O_BINARY); /* make the stdio mode be binary */
! 1541: #endif
! 1542:
! 1543: if (!fastcgi) {
! 1544: /* Make sure we detect we are a cgi - a bit redundancy here,
! 1545: * but the default case is that we have to check only the first one. */
! 1546: if (getenv("SERVER_SOFTWARE") ||
! 1547: getenv("SERVER_NAME") ||
! 1548: getenv("GATEWAY_INTERFACE") ||
! 1549: getenv("REQUEST_METHOD")
! 1550: ) {
! 1551: cgi = 1;
! 1552: }
! 1553: }
! 1554:
! 1555: while ((c = php_getopt(argc, argv, OPTIONS, &php_optarg, &php_optind, 0, 2)) != -1) {
! 1556: switch (c) {
! 1557: case 'c':
! 1558: if (cgi_sapi_module.php_ini_path_override) {
! 1559: free(cgi_sapi_module.php_ini_path_override);
! 1560: }
! 1561: cgi_sapi_module.php_ini_path_override = strdup(php_optarg);
! 1562: break;
! 1563: case 'n':
! 1564: cgi_sapi_module.php_ini_ignore = 1;
! 1565: break;
! 1566: case 'd': {
! 1567: /* define ini entries on command line */
! 1568: int len = strlen(php_optarg);
! 1569: char *val;
! 1570:
! 1571: if ((val = strchr(php_optarg, '='))) {
! 1572: val++;
! 1573: if (!isalnum(*val) && *val != '"' && *val != '\'' && *val != '\0') {
! 1574: cgi_sapi_module.ini_entries = realloc(cgi_sapi_module.ini_entries, ini_entries_len + len + sizeof("\"\"\n\0"));
! 1575: memcpy(cgi_sapi_module.ini_entries + ini_entries_len, php_optarg, (val - php_optarg));
! 1576: ini_entries_len += (val - php_optarg);
! 1577: memcpy(cgi_sapi_module.ini_entries + ini_entries_len, "\"", 1);
! 1578: ini_entries_len++;
! 1579: memcpy(cgi_sapi_module.ini_entries + ini_entries_len, val, len - (val - php_optarg));
! 1580: ini_entries_len += len - (val - php_optarg);
! 1581: memcpy(cgi_sapi_module.ini_entries + ini_entries_len, "\"\n\0", sizeof("\"\n\0"));
! 1582: ini_entries_len += sizeof("\n\0\"") - 2;
! 1583: } else {
! 1584: cgi_sapi_module.ini_entries = realloc(cgi_sapi_module.ini_entries, ini_entries_len + len + sizeof("\n\0"));
! 1585: memcpy(cgi_sapi_module.ini_entries + ini_entries_len, php_optarg, len);
! 1586: memcpy(cgi_sapi_module.ini_entries + ini_entries_len + len, "\n\0", sizeof("\n\0"));
! 1587: ini_entries_len += len + sizeof("\n\0") - 2;
! 1588: }
! 1589: } else {
! 1590: cgi_sapi_module.ini_entries = realloc(cgi_sapi_module.ini_entries, ini_entries_len + len + sizeof("=1\n\0"));
! 1591: memcpy(cgi_sapi_module.ini_entries + ini_entries_len, php_optarg, len);
! 1592: memcpy(cgi_sapi_module.ini_entries + ini_entries_len + len, "=1\n\0", sizeof("=1\n\0"));
! 1593: ini_entries_len += len + sizeof("=1\n\0") - 2;
! 1594: }
! 1595: break;
! 1596: }
! 1597: /* if we're started on command line, check to see if
! 1598: * we are being started as an 'external' fastcgi
! 1599: * server by accepting a bindpath parameter. */
! 1600: case 'b':
! 1601: if (!fastcgi) {
! 1602: bindpath = strdup(php_optarg);
! 1603: }
! 1604: break;
! 1605: case 's': /* generate highlighted HTML from source */
! 1606: behavior = PHP_MODE_HIGHLIGHT;
! 1607: break;
! 1608: }
! 1609: }
! 1610: php_optind = orig_optind;
! 1611: php_optarg = orig_optarg;
! 1612:
! 1613: #ifdef ZTS
! 1614: SG(request_info).path_translated = NULL;
! 1615: #endif
! 1616:
! 1617: cgi_sapi_module.executable_location = argv[0];
! 1618: if (!cgi && !fastcgi && !bindpath) {
! 1619: cgi_sapi_module.additional_functions = additional_functions;
! 1620: }
! 1621:
! 1622: /* startup after we get the above ini override se we get things right */
! 1623: if (cgi_sapi_module.startup(&cgi_sapi_module) == FAILURE) {
! 1624: #ifdef ZTS
! 1625: tsrm_shutdown();
! 1626: #endif
! 1627: return FAILURE;
! 1628: }
! 1629:
! 1630: /* check force_cgi after startup, so we have proper output */
! 1631: if (cgi && CGIG(force_redirect)) {
! 1632: /* Apache will generate REDIRECT_STATUS,
! 1633: * Netscape and redirect.so will generate HTTP_REDIRECT_STATUS.
! 1634: * redirect.so and installation instructions available from
! 1635: * http://www.koehntopp.de/php.
! 1636: * -- kk@netuse.de
! 1637: */
! 1638: if (!getenv("REDIRECT_STATUS") &&
! 1639: !getenv ("HTTP_REDIRECT_STATUS") &&
! 1640: /* this is to allow a different env var to be configured
! 1641: * in case some server does something different than above */
! 1642: (!CGIG(redirect_status_env) || !getenv(CGIG(redirect_status_env)))
! 1643: ) {
! 1644: zend_try {
! 1645: SG(sapi_headers).http_response_code = 400;
! 1646: PUTS("<b>Security Alert!</b> The PHP CGI cannot be accessed directly.\n\n\
! 1647: <p>This PHP CGI binary was compiled with force-cgi-redirect enabled. This\n\
! 1648: means that a page will only be served up if the REDIRECT_STATUS CGI variable is\n\
! 1649: set, e.g. via an Apache Action directive.</p>\n\
! 1650: <p>For more information as to <i>why</i> this behaviour exists, see the <a href=\"http://php.net/security.cgi-bin\">\
! 1651: manual page for CGI security</a>.</p>\n\
! 1652: <p>For more information about changing this behaviour or re-enabling this webserver,\n\
! 1653: consult the installation file that came with this distribution, or visit \n\
! 1654: <a href=\"http://php.net/install.windows\">the manual page</a>.</p>\n");
! 1655: } zend_catch {
! 1656: } zend_end_try();
! 1657: #if defined(ZTS) && !defined(PHP_DEBUG)
! 1658: /* XXX we're crashing here in msvc6 debug builds at
! 1659: * php_message_handler_for_zend:839 because
! 1660: * SG(request_info).path_translated is an invalid pointer.
! 1661: * It still happens even though I set it to null, so something
! 1662: * weird is going on.
! 1663: */
! 1664: tsrm_shutdown();
! 1665: #endif
! 1666: return FAILURE;
! 1667: }
! 1668: }
! 1669:
! 1670: if (bindpath) {
! 1671: fcgi_fd = fcgi_listen(bindpath, 128);
! 1672: if (fcgi_fd < 0) {
! 1673: fprintf(stderr, "Couldn't create FastCGI listen socket on port %s\n", bindpath);
! 1674: #ifdef ZTS
! 1675: tsrm_shutdown();
! 1676: #endif
! 1677: return FAILURE;
! 1678: }
! 1679: fastcgi = fcgi_is_fastcgi();
! 1680: }
! 1681: if (fastcgi) {
! 1682: /* How many times to run PHP scripts before dying */
! 1683: if (getenv("PHP_FCGI_MAX_REQUESTS")) {
! 1684: max_requests = atoi(getenv("PHP_FCGI_MAX_REQUESTS"));
! 1685: if (max_requests < 0) {
! 1686: fprintf(stderr, "PHP_FCGI_MAX_REQUESTS is not valid\n");
! 1687: return FAILURE;
! 1688: }
! 1689: }
! 1690:
! 1691: /* make php call us to get _ENV vars */
! 1692: php_php_import_environment_variables = php_import_environment_variables;
! 1693: php_import_environment_variables = cgi_php_import_environment_variables;
! 1694:
! 1695: /* library is already initialized, now init our request */
! 1696: fcgi_init_request(&request, fcgi_fd);
! 1697:
! 1698: #ifndef PHP_WIN32
! 1699: /* Pre-fork, if required */
! 1700: if (getenv("PHP_FCGI_CHILDREN")) {
! 1701: char * children_str = getenv("PHP_FCGI_CHILDREN");
! 1702: children = atoi(children_str);
! 1703: if (children < 0) {
! 1704: fprintf(stderr, "PHP_FCGI_CHILDREN is not valid\n");
! 1705: return FAILURE;
! 1706: }
! 1707: fcgi_set_mgmt_var("FCGI_MAX_CONNS", sizeof("FCGI_MAX_CONNS")-1, children_str, strlen(children_str));
! 1708: /* This is the number of concurrent requests, equals FCGI_MAX_CONNS */
! 1709: fcgi_set_mgmt_var("FCGI_MAX_REQS", sizeof("FCGI_MAX_REQS")-1, children_str, strlen(children_str));
! 1710: } else {
! 1711: fcgi_set_mgmt_var("FCGI_MAX_CONNS", sizeof("FCGI_MAX_CONNS")-1, "1", sizeof("1")-1);
! 1712: fcgi_set_mgmt_var("FCGI_MAX_REQS", sizeof("FCGI_MAX_REQS")-1, "1", sizeof("1")-1);
! 1713: }
! 1714:
! 1715: if (children) {
! 1716: int running = 0;
! 1717: pid_t pid;
! 1718:
! 1719: /* Create a process group for ourself & children */
! 1720: setsid();
! 1721: pgroup = getpgrp();
! 1722: #ifdef DEBUG_FASTCGI
! 1723: fprintf(stderr, "Process group %d\n", pgroup);
! 1724: #endif
! 1725:
! 1726: /* Set up handler to kill children upon exit */
! 1727: act.sa_flags = 0;
! 1728: act.sa_handler = fastcgi_cleanup;
! 1729: if (sigaction(SIGTERM, &act, &old_term) ||
! 1730: sigaction(SIGINT, &act, &old_int) ||
! 1731: sigaction(SIGQUIT, &act, &old_quit)
! 1732: ) {
! 1733: perror("Can't set signals");
! 1734: exit(1);
! 1735: }
! 1736:
! 1737: if (fcgi_in_shutdown()) {
! 1738: goto parent_out;
! 1739: }
! 1740:
! 1741: while (parent) {
! 1742: do {
! 1743: #ifdef DEBUG_FASTCGI
! 1744: fprintf(stderr, "Forking, %d running\n", running);
! 1745: #endif
! 1746: pid = fork();
! 1747: switch (pid) {
! 1748: case 0:
! 1749: /* One of the children.
! 1750: * Make sure we don't go round the
! 1751: * fork loop any more
! 1752: */
! 1753: parent = 0;
! 1754:
! 1755: /* don't catch our signals */
! 1756: sigaction(SIGTERM, &old_term, 0);
! 1757: sigaction(SIGQUIT, &old_quit, 0);
! 1758: sigaction(SIGINT, &old_int, 0);
! 1759: break;
! 1760: case -1:
! 1761: perror("php (pre-forking)");
! 1762: exit(1);
! 1763: break;
! 1764: default:
! 1765: /* Fine */
! 1766: running++;
! 1767: break;
! 1768: }
! 1769: } while (parent && (running < children));
! 1770:
! 1771: if (parent) {
! 1772: #ifdef DEBUG_FASTCGI
! 1773: fprintf(stderr, "Wait for kids, pid %d\n", getpid());
! 1774: #endif
! 1775: parent_waiting = 1;
! 1776: while (1) {
! 1777: if (wait(&status) >= 0) {
! 1778: running--;
! 1779: break;
! 1780: } else if (exit_signal) {
! 1781: break;
! 1782: }
! 1783: }
! 1784: if (exit_signal) {
! 1785: #if 0
! 1786: while (running > 0) {
! 1787: while (wait(&status) < 0) {
! 1788: }
! 1789: running--;
! 1790: }
! 1791: #endif
! 1792: goto parent_out;
! 1793: }
! 1794: }
! 1795: }
! 1796: } else {
! 1797: parent = 0;
! 1798: }
! 1799:
! 1800: #endif /* WIN32 */
! 1801: }
! 1802:
! 1803: zend_first_try {
! 1804: while ((c = php_getopt(argc, argv, OPTIONS, &php_optarg, &php_optind, 1, 2)) != -1) {
! 1805: switch (c) {
! 1806: case 'T':
! 1807: benchmark = 1;
! 1808: repeats = atoi(php_optarg);
! 1809: #ifdef HAVE_GETTIMEOFDAY
! 1810: gettimeofday(&start, NULL);
! 1811: #else
! 1812: time(&start);
! 1813: #endif
! 1814: break;
! 1815: case 'h':
! 1816: case '?':
! 1817: fcgi_shutdown();
! 1818: no_headers = 1;
! 1819: php_output_startup();
! 1820: php_output_activate(TSRMLS_C);
! 1821: SG(headers_sent) = 1;
! 1822: php_cgi_usage(argv[0]);
! 1823: php_end_ob_buffers(1 TSRMLS_CC);
! 1824: exit_status = 0;
! 1825: goto out;
! 1826: }
! 1827: }
! 1828: php_optind = orig_optind;
! 1829: php_optarg = orig_optarg;
! 1830:
! 1831: /* start of FAST CGI loop */
! 1832: /* Initialise FastCGI request structure */
! 1833: #ifdef PHP_WIN32
! 1834: /* attempt to set security impersonation for fastcgi
! 1835: * will only happen on NT based OS, others will ignore it. */
! 1836: if (fastcgi && CGIG(impersonate)) {
! 1837: fcgi_impersonate();
! 1838: }
! 1839: #endif
! 1840: while (!fastcgi || fcgi_accept_request(&request) >= 0) {
! 1841: SG(server_context) = (void *) &request;
! 1842: init_request_info(TSRMLS_C);
! 1843: CG(interactive) = 0;
! 1844:
! 1845: if (!cgi && !fastcgi) {
! 1846: while ((c = php_getopt(argc, argv, OPTIONS, &php_optarg, &php_optind, 0, 2)) != -1) {
! 1847: switch (c) {
! 1848:
! 1849: case 'a': /* interactive mode */
! 1850: printf("Interactive mode enabled\n\n");
! 1851: CG(interactive) = 1;
! 1852: break;
! 1853:
! 1854: case 'C': /* don't chdir to the script directory */
! 1855: SG(options) |= SAPI_OPTION_NO_CHDIR;
! 1856: break;
! 1857:
! 1858: case 'e': /* enable extended info output */
! 1859: CG(compiler_options) |= ZEND_COMPILE_EXTENDED_INFO;
! 1860: break;
! 1861:
! 1862: case 'f': /* parse file */
! 1863: if (script_file) {
! 1864: efree(script_file);
! 1865: }
! 1866: script_file = estrdup(php_optarg);
! 1867: no_headers = 1;
! 1868: break;
! 1869:
! 1870: case 'i': /* php info & quit */
! 1871: if (script_file) {
! 1872: efree(script_file);
! 1873: }
! 1874: if (php_request_startup(TSRMLS_C) == FAILURE) {
! 1875: SG(server_context) = NULL;
! 1876: php_module_shutdown(TSRMLS_C);
! 1877: return FAILURE;
! 1878: }
! 1879: if (no_headers) {
! 1880: SG(headers_sent) = 1;
! 1881: SG(request_info).no_headers = 1;
! 1882: }
! 1883: php_print_info(0xFFFFFFFF TSRMLS_CC);
! 1884: php_request_shutdown((void *) 0);
! 1885: fcgi_shutdown();
! 1886: exit_status = 0;
! 1887: goto out;
! 1888:
! 1889: case 'l': /* syntax check mode */
! 1890: no_headers = 1;
! 1891: behavior = PHP_MODE_LINT;
! 1892: break;
! 1893:
! 1894: case 'm': /* list compiled in modules */
! 1895: if (script_file) {
! 1896: efree(script_file);
! 1897: }
! 1898: php_output_startup();
! 1899: php_output_activate(TSRMLS_C);
! 1900: SG(headers_sent) = 1;
! 1901: php_printf("[PHP Modules]\n");
! 1902: print_modules(TSRMLS_C);
! 1903: php_printf("\n[Zend Modules]\n");
! 1904: print_extensions(TSRMLS_C);
! 1905: php_printf("\n");
! 1906: php_end_ob_buffers(1 TSRMLS_CC);
! 1907: fcgi_shutdown();
! 1908: exit_status = 0;
! 1909: goto out;
! 1910:
! 1911: #if 0 /* not yet operational, see also below ... */
! 1912: case '': /* generate indented source mode*/
! 1913: behavior=PHP_MODE_INDENT;
! 1914: break;
! 1915: #endif
! 1916:
! 1917: case 'q': /* do not generate HTTP headers */
! 1918: no_headers = 1;
! 1919: break;
! 1920:
! 1921: case 'v': /* show php version & quit */
! 1922: if (script_file) {
! 1923: efree(script_file);
! 1924: }
! 1925: no_headers = 1;
! 1926: if (php_request_startup(TSRMLS_C) == FAILURE) {
! 1927: SG(server_context) = NULL;
! 1928: php_module_shutdown(TSRMLS_C);
! 1929: return FAILURE;
! 1930: }
! 1931: if (no_headers) {
! 1932: SG(headers_sent) = 1;
! 1933: SG(request_info).no_headers = 1;
! 1934: }
! 1935: #if SUHOSIN_PATCH
! 1936: #if ZEND_DEBUG
! 1937: php_printf("PHP %s with Suhosin-Patch (%s) (built: %s %s) (DEBUG)\nCopyright (c) 1997-2012 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
! 1938: #else
! 1939: php_printf("PHP %s with Suhosin-Patch (%s) (built: %s %s)\nCopyright (c) 1997-2012 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
! 1940: #endif
! 1941: #else
! 1942: #if ZEND_DEBUG
! 1943: php_printf("PHP %s (%s) (built: %s %s) (DEBUG)\nCopyright (c) 1997-2012 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
! 1944: #else
! 1945: php_printf("PHP %s (%s) (built: %s %s)\nCopyright (c) 1997-2012 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
! 1946: #endif
! 1947: #endif
! 1948: php_request_shutdown((void *) 0);
! 1949: fcgi_shutdown();
! 1950: exit_status = 0;
! 1951: goto out;
! 1952:
! 1953: case 'w':
! 1954: behavior = PHP_MODE_STRIP;
! 1955: break;
! 1956:
! 1957: case 'z': /* load extension file */
! 1958: zend_load_extension(php_optarg);
! 1959: break;
! 1960:
! 1961: default:
! 1962: break;
! 1963: }
! 1964: }
! 1965:
! 1966: if (script_file) {
! 1967: /* override path_translated if -f on command line */
! 1968: STR_FREE(SG(request_info).path_translated);
! 1969: SG(request_info).path_translated = script_file;
! 1970: /* before registering argv to module exchange the *new* argv[0] */
! 1971: /* we can achieve this without allocating more memory */
! 1972: SG(request_info).argc = argc - (php_optind - 1);
! 1973: SG(request_info).argv = &argv[php_optind - 1];
! 1974: SG(request_info).argv[0] = script_file;
! 1975: } else if (argc > php_optind) {
! 1976: /* file is on command line, but not in -f opt */
! 1977: STR_FREE(SG(request_info).path_translated);
! 1978: SG(request_info).path_translated = estrdup(argv[php_optind]);
! 1979: /* arguments after the file are considered script args */
! 1980: SG(request_info).argc = argc - php_optind;
! 1981: SG(request_info).argv = &argv[php_optind];
! 1982: }
! 1983:
! 1984: if (no_headers) {
! 1985: SG(headers_sent) = 1;
! 1986: SG(request_info).no_headers = 1;
! 1987: }
! 1988:
! 1989: /* all remaining arguments are part of the query string
! 1990: * this section of code concatenates all remaining arguments
! 1991: * into a single string, seperating args with a &
! 1992: * this allows command lines like:
! 1993: *
! 1994: * test.php v1=test v2=hello+world!
! 1995: * test.php "v1=test&v2=hello world!"
! 1996: * test.php v1=test "v2=hello world!"
! 1997: */
! 1998: if (!SG(request_info).query_string && argc > php_optind) {
! 1999: int slen = strlen(PG(arg_separator).input);
! 2000: len = 0;
! 2001: for (i = php_optind; i < argc; i++) {
! 2002: if (i < (argc - 1)) {
! 2003: len += strlen(argv[i]) + slen;
! 2004: } else {
! 2005: len += strlen(argv[i]);
! 2006: }
! 2007: }
! 2008:
! 2009: len += 2;
! 2010: s = malloc(len);
! 2011: *s = '\0'; /* we are pretending it came from the environment */
! 2012: for (i = php_optind; i < argc; i++) {
! 2013: strlcat(s, argv[i], len);
! 2014: if (i < (argc - 1)) {
! 2015: strlcat(s, PG(arg_separator).input, len);
! 2016: }
! 2017: }
! 2018: SG(request_info).query_string = s;
! 2019: free_query_string = 1;
! 2020: }
! 2021: } /* end !cgi && !fastcgi */
! 2022:
! 2023: /*
! 2024: we never take stdin if we're (f)cgi, always
! 2025: rely on the web server giving us the info
! 2026: we need in the environment.
! 2027: */
! 2028: if (SG(request_info).path_translated || cgi || fastcgi) {
! 2029: file_handle.type = ZEND_HANDLE_FILENAME;
! 2030: file_handle.filename = SG(request_info).path_translated;
! 2031: file_handle.handle.fp = NULL;
! 2032: } else {
! 2033: file_handle.filename = "-";
! 2034: file_handle.type = ZEND_HANDLE_FP;
! 2035: file_handle.handle.fp = stdin;
! 2036: }
! 2037:
! 2038: file_handle.opened_path = NULL;
! 2039: file_handle.free_filename = 0;
! 2040:
! 2041: /* request startup only after we've done all we can to
! 2042: * get path_translated */
! 2043: if (php_request_startup(TSRMLS_C) == FAILURE) {
! 2044: if (fastcgi) {
! 2045: fcgi_finish_request(&request, 1);
! 2046: }
! 2047: SG(server_context) = NULL;
! 2048: php_module_shutdown(TSRMLS_C);
! 2049: return FAILURE;
! 2050: }
! 2051: if (no_headers) {
! 2052: SG(headers_sent) = 1;
! 2053: SG(request_info).no_headers = 1;
! 2054: }
! 2055:
! 2056: /*
! 2057: at this point path_translated will be set if:
! 2058: 1. we are running from shell and got filename was there
! 2059: 2. we are running as cgi or fastcgi
! 2060: */
! 2061: if (cgi || fastcgi || SG(request_info).path_translated) {
! 2062: if (php_fopen_primary_script(&file_handle TSRMLS_CC) == FAILURE) {
! 2063: zend_try {
! 2064: if (errno == EACCES) {
! 2065: SG(sapi_headers).http_response_code = 403;
! 2066: PUTS("Access denied.\n");
! 2067: } else {
! 2068: SG(sapi_headers).http_response_code = 404;
! 2069: PUTS("No input file specified.\n");
! 2070: }
! 2071: } zend_catch {
! 2072: } zend_end_try();
! 2073: /* we want to serve more requests if this is fastcgi
! 2074: * so cleanup and continue, request shutdown is
! 2075: * handled later */
! 2076: if (fastcgi) {
! 2077: goto fastcgi_request_done;
! 2078: }
! 2079:
! 2080: STR_FREE(SG(request_info).path_translated);
! 2081:
! 2082: if (free_query_string && SG(request_info).query_string) {
! 2083: free(SG(request_info).query_string);
! 2084: SG(request_info).query_string = NULL;
! 2085: }
! 2086:
! 2087: php_request_shutdown((void *) 0);
! 2088: SG(server_context) = NULL;
! 2089: php_module_shutdown(TSRMLS_C);
! 2090: sapi_shutdown();
! 2091: #ifdef ZTS
! 2092: tsrm_shutdown();
! 2093: #endif
! 2094: return FAILURE;
! 2095: }
! 2096: }
! 2097:
! 2098: if (CGIG(check_shebang_line) && file_handle.handle.fp && (file_handle.handle.fp != stdin)) {
! 2099: /* #!php support */
! 2100: c = fgetc(file_handle.handle.fp);
! 2101: if (c == '#') {
! 2102: while (c != '\n' && c != '\r' && c != EOF) {
! 2103: c = fgetc(file_handle.handle.fp); /* skip to end of line */
! 2104: }
! 2105: /* handle situations where line is terminated by \r\n */
! 2106: if (c == '\r') {
! 2107: if (fgetc(file_handle.handle.fp) != '\n') {
! 2108: long pos = ftell(file_handle.handle.fp);
! 2109: fseek(file_handle.handle.fp, pos - 1, SEEK_SET);
! 2110: }
! 2111: }
! 2112: CG(start_lineno) = 2;
! 2113: } else {
! 2114: rewind(file_handle.handle.fp);
! 2115: }
! 2116: }
! 2117:
! 2118: switch (behavior) {
! 2119: case PHP_MODE_STANDARD:
! 2120: php_execute_script(&file_handle TSRMLS_CC);
! 2121: break;
! 2122: case PHP_MODE_LINT:
! 2123: PG(during_request_startup) = 0;
! 2124: exit_status = php_lint_script(&file_handle TSRMLS_CC);
! 2125: if (exit_status == SUCCESS) {
! 2126: zend_printf("No syntax errors detected in %s\n", file_handle.filename);
! 2127: } else {
! 2128: zend_printf("Errors parsing %s\n", file_handle.filename);
! 2129: }
! 2130: break;
! 2131: case PHP_MODE_STRIP:
! 2132: if (open_file_for_scanning(&file_handle TSRMLS_CC) == SUCCESS) {
! 2133: zend_strip(TSRMLS_C);
! 2134: zend_file_handle_dtor(&file_handle TSRMLS_CC);
! 2135: php_end_ob_buffers(1 TSRMLS_CC);
! 2136: }
! 2137: return SUCCESS;
! 2138: break;
! 2139: case PHP_MODE_HIGHLIGHT:
! 2140: {
! 2141: zend_syntax_highlighter_ini syntax_highlighter_ini;
! 2142:
! 2143: if (open_file_for_scanning(&file_handle TSRMLS_CC) == SUCCESS) {
! 2144: php_get_highlight_struct(&syntax_highlighter_ini);
! 2145: zend_highlight(&syntax_highlighter_ini TSRMLS_CC);
! 2146: if (fastcgi) {
! 2147: goto fastcgi_request_done;
! 2148: }
! 2149: zend_file_handle_dtor(&file_handle TSRMLS_CC);
! 2150: php_end_ob_buffers(1 TSRMLS_CC);
! 2151: }
! 2152: return SUCCESS;
! 2153: }
! 2154: break;
! 2155: #if 0
! 2156: /* Zeev might want to do something with this one day */
! 2157: case PHP_MODE_INDENT:
! 2158: open_file_for_scanning(&file_handle TSRMLS_CC);
! 2159: zend_indent();
! 2160: zend_file_handle_dtor(&file_handle TSRMLS_CC);
! 2161: return SUCCESS;
! 2162: break;
! 2163: #endif
! 2164: }
! 2165:
! 2166: fastcgi_request_done:
! 2167: {
! 2168: STR_FREE(SG(request_info).path_translated);
! 2169:
! 2170: php_request_shutdown((void *) 0);
! 2171:
! 2172: if (exit_status == 0) {
! 2173: exit_status = EG(exit_status);
! 2174: }
! 2175:
! 2176: if (free_query_string && SG(request_info).query_string) {
! 2177: free(SG(request_info).query_string);
! 2178: SG(request_info).query_string = NULL;
! 2179: }
! 2180: }
! 2181:
! 2182: if (!fastcgi) {
! 2183: if (benchmark) {
! 2184: repeats--;
! 2185: if (repeats > 0) {
! 2186: script_file = NULL;
! 2187: php_optind = orig_optind;
! 2188: php_optarg = orig_optarg;
! 2189: continue;
! 2190: }
! 2191: }
! 2192: break;
! 2193: }
! 2194:
! 2195: /* only fastcgi will get here */
! 2196: requests++;
! 2197: if (max_requests && (requests == max_requests)) {
! 2198: fcgi_finish_request(&request, 1);
! 2199: if (bindpath) {
! 2200: free(bindpath);
! 2201: }
! 2202: if (max_requests != 1) {
! 2203: /* no need to return exit_status of the last request */
! 2204: exit_status = 0;
! 2205: }
! 2206: break;
! 2207: }
! 2208: /* end of fastcgi loop */
! 2209: }
! 2210: fcgi_shutdown();
! 2211:
! 2212: if (cgi_sapi_module.php_ini_path_override) {
! 2213: free(cgi_sapi_module.php_ini_path_override);
! 2214: }
! 2215: if (cgi_sapi_module.ini_entries) {
! 2216: free(cgi_sapi_module.ini_entries);
! 2217: }
! 2218: } zend_catch {
! 2219: exit_status = 255;
! 2220: } zend_end_try();
! 2221:
! 2222: out:
! 2223: if (benchmark) {
! 2224: int sec;
! 2225: #ifdef HAVE_GETTIMEOFDAY
! 2226: int usec;
! 2227:
! 2228: gettimeofday(&end, NULL);
! 2229: sec = (int)(end.tv_sec - start.tv_sec);
! 2230: if (end.tv_usec >= start.tv_usec) {
! 2231: usec = (int)(end.tv_usec - start.tv_usec);
! 2232: } else {
! 2233: sec -= 1;
! 2234: usec = (int)(end.tv_usec + 1000000 - start.tv_usec);
! 2235: }
! 2236: fprintf(stderr, "\nElapsed time: %d.%06d sec\n", sec, usec);
! 2237: #else
! 2238: time(&end);
! 2239: sec = (int)(end - start);
! 2240: fprintf(stderr, "\nElapsed time: %d sec\n", sec);
! 2241: #endif
! 2242: }
! 2243:
! 2244: #ifndef PHP_WIN32
! 2245: parent_out:
! 2246: #endif
! 2247:
! 2248: SG(server_context) = NULL;
! 2249: php_module_shutdown(TSRMLS_C);
! 2250: sapi_shutdown();
! 2251:
! 2252: #ifdef ZTS
! 2253: tsrm_shutdown();
! 2254: #endif
! 2255:
! 2256: #if defined(PHP_WIN32) && ZEND_DEBUG && 0
! 2257: _CrtDumpMemoryLeaks();
! 2258: #endif
! 2259:
! 2260: return exit_status;
! 2261: }
! 2262: /* }}} */
! 2263:
! 2264: /*
! 2265: * Local variables:
! 2266: * tab-width: 4
! 2267: * c-basic-offset: 4
! 2268: * End:
! 2269: * vim600: sw=4 ts=4 fdm=marker
! 2270: * vim<600: sw=4 ts=4
! 2271: */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>