1 : /*
2 : +----------------------------------------------------------------------+
3 : | PHP Version 5 |
4 : +----------------------------------------------------------------------+
5 : | Copyright (c) 1997-2007 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,v 1.267.2.15.2.32 2007/03/29 18:47:04 pollita Exp $ */
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 : #ifdef PHP_WIN32
36 : #include "win32/time.h"
37 : #include "win32/signal.h"
38 : #include <process.h>
39 : #endif
40 : #if HAVE_SYS_TIME_H
41 : #include <sys/time.h>
42 : #endif
43 : #if HAVE_UNISTD_H
44 : #include <unistd.h>
45 : #endif
46 : #if HAVE_SIGNAL_H
47 : #include <signal.h>
48 : #endif
49 : #if HAVE_SETLOCALE
50 : #include <locale.h>
51 : #endif
52 : #if HAVE_SYS_TYPES_H
53 : #include <sys/types.h>
54 : #endif
55 : #if HAVE_SYS_WAIT_H
56 : #include <sys/wait.h>
57 : #endif
58 : #include "zend.h"
59 : #include "zend_extensions.h"
60 : #include "php_ini.h"
61 : #include "php_globals.h"
62 : #include "php_main.h"
63 : #include "fopen_wrappers.h"
64 : #include "ext/standard/php_standard.h"
65 : #ifdef PHP_WIN32
66 : #include <io.h>
67 : #include <fcntl.h>
68 : #include "win32/php_registry.h"
69 : #endif
70 :
71 : #ifdef __riscos__
72 : #include <unixlib/local.h>
73 : int __riscosify_control = __RISCOSIFY_STRICT_UNIX_SPECS;
74 : #endif
75 :
76 : #include "zend_compile.h"
77 : #include "zend_execute.h"
78 : #include "zend_highlight.h"
79 : #include "zend_indent.h"
80 :
81 : #include "php_getopt.h"
82 :
83 : #if PHP_FASTCGI
84 : #include "fastcgi.h"
85 :
86 : #ifndef PHP_WIN32
87 : /* XXX this will need to change later when threaded fastcgi is
88 : implemented. shane */
89 : struct sigaction act, old_term, old_quit, old_int;
90 : #endif
91 :
92 : static void (*php_php_import_environment_variables)(zval *array_ptr TSRMLS_DC);
93 :
94 : #ifndef PHP_WIN32
95 : /* these globals used for forking children on unix systems */
96 : /**
97 : * Number of child processes that will get created to service requests
98 : */
99 : static int children = 0;
100 :
101 : /**
102 : * Set to non-zero if we are the parent process
103 : */
104 : static int parent = 1;
105 :
106 : /**
107 : * Process group
108 : */
109 : static pid_t pgroup;
110 : #endif
111 :
112 : #endif
113 :
114 : #define PHP_MODE_STANDARD 1
115 : #define PHP_MODE_HIGHLIGHT 2
116 : #define PHP_MODE_INDENT 3
117 : #define PHP_MODE_LINT 4
118 : #define PHP_MODE_STRIP 5
119 :
120 : static char *php_optarg = NULL;
121 : static int php_optind = 1;
122 : static zend_module_entry cgi_module_entry;
123 :
124 : static const opt_struct OPTIONS[] = {
125 : {'a', 0, "interactive"},
126 : {'b', 1, "bindpath"},
127 : {'C', 0, "no-chdir"},
128 : {'c', 1, "php-ini"},
129 : {'d', 1, "define"},
130 : {'e', 0, "profile-info"},
131 : {'f', 1, "file"},
132 : {'h', 0, "help"},
133 : {'i', 0, "info"},
134 : {'l', 0, "syntax-check"},
135 : {'m', 0, "modules"},
136 : {'n', 0, "no-php-ini"},
137 : {'q', 0, "no-header"},
138 : {'s', 0, "syntax-highlight"},
139 : {'s', 0, "syntax-highlighting"},
140 : {'w', 0, "strip"},
141 : {'?', 0, "usage"},/* help alias (both '?' and 'usage') */
142 : {'v', 0, "version"},
143 : {'z', 1, "zend-extension"},
144 : {'-', 0, NULL} /* end of args */
145 : };
146 :
147 : typedef struct _php_cgi_globals_struct {
148 : zend_bool rfc2616_headers;
149 : zend_bool nph;
150 : zend_bool check_shebang_line;
151 : #if ENABLE_PATHINFO_CHECK
152 : zend_bool fix_pathinfo;
153 : #endif
154 : #if FORCE_CGI_REDIRECT
155 : zend_bool force_redirect;
156 : char *redirect_status_env;
157 : #endif
158 : #if PHP_FASTCGI
159 : zend_bool fcgi_logging;
160 : # ifdef PHP_WIN32
161 : zend_bool impersonate;
162 : # endif
163 : #endif
164 : } php_cgi_globals_struct;
165 :
166 : #ifdef ZTS
167 : static int php_cgi_globals_id;
168 : #define CGIG(v) TSRMG(php_cgi_globals_id, php_cgi_globals_struct *, v)
169 : #else
170 : static php_cgi_globals_struct php_cgi_globals;
171 : #define CGIG(v) (php_cgi_globals.v)
172 : #endif
173 :
174 : #ifdef PHP_WIN32
175 : #define TRANSLATE_SLASHES(path) \
176 : { \
177 : char *tmp = path; \
178 : while (*tmp) { \
179 : if (*tmp == '\\') *tmp = '/'; \
180 : tmp++; \
181 : } \
182 : }
183 : #else
184 : #define TRANSLATE_SLASHES(path)
185 : #endif
186 :
187 : static int print_module_info(zend_module_entry *module, void *arg TSRMLS_DC)
188 0 : {
189 0 : php_printf("%s\n", module->name);
190 0 : return 0;
191 : }
192 :
193 : static int module_name_cmp(const void *a, const void *b TSRMLS_DC)
194 0 : {
195 0 : Bucket *f = *((Bucket **) a);
196 0 : Bucket *s = *((Bucket **) b);
197 :
198 0 : return strcasecmp(((zend_module_entry *)f->pData)->name,
199 : ((zend_module_entry *)s->pData)->name);
200 : }
201 :
202 : static void print_modules(TSRMLS_D)
203 0 : {
204 : HashTable sorted_registry;
205 : zend_module_entry tmp;
206 :
207 0 : zend_hash_init(&sorted_registry, 50, NULL, NULL, 1);
208 0 : zend_hash_copy(&sorted_registry, &module_registry, NULL, &tmp, sizeof(zend_module_entry));
209 0 : zend_hash_sort(&sorted_registry, zend_qsort, module_name_cmp, 0 TSRMLS_CC);
210 0 : zend_hash_apply_with_argument(&sorted_registry, (apply_func_arg_t) print_module_info, NULL TSRMLS_CC);
211 0 : zend_hash_destroy(&sorted_registry);
212 0 : }
213 :
214 : static int print_extension_info(zend_extension *ext, void *arg TSRMLS_DC)
215 0 : {
216 0 : php_printf("%s\n", ext->name);
217 0 : return 0;
218 : }
219 :
220 : static int extension_name_cmp(const zend_llist_element **f,
221 : const zend_llist_element **s TSRMLS_DC)
222 0 : {
223 0 : return strcmp(((zend_extension *)(*f)->data)->name,
224 : ((zend_extension *)(*s)->data)->name);
225 : }
226 :
227 : static void print_extensions(TSRMLS_D)
228 0 : {
229 : zend_llist sorted_exts;
230 :
231 0 : zend_llist_copy(&sorted_exts, &zend_extensions);
232 0 : zend_llist_sort(&sorted_exts, extension_name_cmp TSRMLS_CC);
233 0 : zend_llist_apply_with_argument(&sorted_exts, (llist_apply_with_arg_func_t) print_extension_info, NULL TSRMLS_CC);
234 0 : zend_llist_destroy(&sorted_exts);
235 0 : }
236 :
237 : #ifndef STDOUT_FILENO
238 : #define STDOUT_FILENO 1
239 : #endif
240 :
241 : static inline size_t sapi_cgibin_single_write(const char *str, uint str_length TSRMLS_DC)
242 4457 : {
243 : #ifdef PHP_WRITE_STDOUT
244 : long ret;
245 : #else
246 : size_t ret;
247 : #endif
248 :
249 : #if PHP_FASTCGI
250 : if (fcgi_is_fastcgi()) {
251 : fcgi_request *request = (fcgi_request*) SG(server_context);
252 : long ret = fcgi_write(request, FCGI_STDOUT, str, str_length);
253 : if (ret <= 0) {
254 : return 0;
255 : }
256 : return ret;
257 : }
258 : #endif
259 : #ifdef PHP_WRITE_STDOUT
260 4457 : ret = write(STDOUT_FILENO, str, str_length);
261 4457 : if (ret <= 0) return 0;
262 4457 : return ret;
263 : #else
264 : ret = fwrite(str, 1, MIN(str_length, 16384), stdout);
265 : return ret;
266 : #endif
267 : }
268 :
269 : static int sapi_cgibin_ub_write(const char *str, uint str_length TSRMLS_DC)
270 4477 : {
271 4477 : const char *ptr = str;
272 4477 : uint remaining = str_length;
273 : size_t ret;
274 :
275 13411 : while (remaining > 0) {
276 4457 : ret = sapi_cgibin_single_write(ptr, remaining TSRMLS_CC);
277 4457 : if (!ret) {
278 0 : php_handle_aborted_connection();
279 0 : return str_length - remaining;
280 : }
281 4457 : ptr += ret;
282 4457 : remaining -= ret;
283 : }
284 :
285 4477 : return str_length;
286 : }
287 :
288 :
289 : static void sapi_cgibin_flush(void *server_context)
290 280 : {
291 : #if PHP_FASTCGI
292 : if (fcgi_is_fastcgi()) {
293 : fcgi_request *request = (fcgi_request*) server_context;
294 : if (
295 : #ifndef PHP_WIN32
296 : !parent &&
297 : #endif
298 : request && !fcgi_flush(request, 0)) {
299 : php_handle_aborted_connection();
300 : }
301 : return;
302 : }
303 : #endif
304 280 : if (fflush(stdout) == EOF) {
305 0 : php_handle_aborted_connection();
306 : }
307 280 : }
308 :
309 : #define SAPI_CGI_MAX_HEADER_LENGTH 1024
310 :
311 : static int sapi_cgi_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC)
312 110 : {
313 : char buf[SAPI_CGI_MAX_HEADER_LENGTH];
314 : sapi_header_struct *h;
315 : zend_llist_position pos;
316 :
317 110 : if (SG(request_info).no_headers == 1) {
318 0 : return SAPI_HEADER_SENT_SUCCESSFULLY;
319 : }
320 :
321 110 : if (CGIG(nph) || SG(sapi_headers).http_response_code != 200)
322 : {
323 : int len;
324 :
325 22 : if (CGIG(rfc2616_headers) && SG(sapi_headers).http_status_line) {
326 0 : len = slprintf(buf, SAPI_CGI_MAX_HEADER_LENGTH,
327 : "%s\r\n", SG(sapi_headers).http_status_line);
328 :
329 0 : if (len > SAPI_CGI_MAX_HEADER_LENGTH) {
330 0 : len = SAPI_CGI_MAX_HEADER_LENGTH;
331 : }
332 :
333 : } else {
334 22 : len = slprintf(buf, sizeof(buf), "Status: %d\r\n", SG(sapi_headers).http_response_code);
335 : }
336 :
337 22 : PHPWRITE_H(buf, len);
338 : }
339 :
340 110 : h = (sapi_header_struct*)zend_llist_get_first_ex(&sapi_headers->headers, &pos);
341 546 : while (h) {
342 : /* prevent CRLFCRLF */
343 326 : if (h->header_len) {
344 326 : PHPWRITE_H(h->header, h->header_len);
345 326 : PHPWRITE_H("\r\n", 2);
346 : }
347 326 : h = (sapi_header_struct*)zend_llist_get_next_ex(&sapi_headers->headers, &pos);
348 : }
349 110 : PHPWRITE_H("\r\n", 2);
350 :
351 110 : return SAPI_HEADER_SENT_SUCCESSFULLY;
352 : }
353 :
354 :
355 : static int sapi_cgi_read_post(char *buffer, uint count_bytes TSRMLS_DC)
356 218 : {
357 218 : int read_bytes=0, tmp_read_bytes;
358 :
359 218 : count_bytes = MIN(count_bytes, (uint) SG(request_info).content_length - SG(read_post_bytes));
360 436 : while (read_bytes < count_bytes) {
361 : #if PHP_FASTCGI
362 : if (fcgi_is_fastcgi()) {
363 : fcgi_request *request = (fcgi_request*) SG(server_context);
364 : tmp_read_bytes = fcgi_read(request, buffer + read_bytes, count_bytes - read_bytes);
365 : } else {
366 : tmp_read_bytes = read(0, buffer + read_bytes, count_bytes - read_bytes);
367 : }
368 : #else
369 0 : tmp_read_bytes = read(0, buffer + read_bytes, count_bytes - read_bytes);
370 : #endif
371 :
372 0 : if (tmp_read_bytes <= 0) {
373 0 : break;
374 : }
375 0 : read_bytes += tmp_read_bytes;
376 : }
377 218 : return read_bytes;
378 : }
379 :
380 : static char *sapi_cgibin_getenv(char *name, size_t name_len TSRMLS_DC)
381 1773 : {
382 : #if PHP_FASTCGI
383 : /* when php is started by mod_fastcgi, no regular environment
384 : is provided to PHP. It is always sent to PHP at the start
385 : of a request. So we have to do our own lookup to get env
386 : vars. This could probably be faster somehow. */
387 : if (fcgi_is_fastcgi()) {
388 : fcgi_request *request = (fcgi_request*) SG(server_context);
389 : return fcgi_getenv(request, name, name_len);
390 : }
391 : #endif
392 : /* if cgi, or fastcgi and not found in fcgi env
393 : check the regular environment */
394 1773 : return getenv(name);
395 : }
396 :
397 : static char *_sapi_cgibin_putenv(char *name, char *value TSRMLS_DC)
398 216 : {
399 : int name_len;
400 : #if !HAVE_SETENV || !HAVE_UNSETENV
401 : int len;
402 : char *buf;
403 : #endif
404 :
405 216 : if (!name) {
406 0 : return NULL;
407 : }
408 216 : name_len = strlen(name);
409 :
410 : #if PHP_FASTCGI
411 : /* when php is started by mod_fastcgi, no regular environment
412 : is provided to PHP. It is always sent to PHP at the start
413 : of a request. So we have to do our own lookup to get env
414 : vars. This could probably be faster somehow. */
415 : if (fcgi_is_fastcgi()) {
416 : fcgi_request *request = (fcgi_request*) SG(server_context);
417 : return fcgi_putenv(request, name, name_len, value);
418 : }
419 : #endif
420 : #if HAVE_SETENV
421 216 : if (value) {
422 108 : setenv(name, value, 1);
423 : }
424 : #endif
425 : #if HAVE_UNSETENV
426 216 : if (!value) {
427 108 : unsetenv(name);
428 : }
429 : #endif
430 :
431 : #if !HAVE_SETENV || !HAVE_UNSETENV
432 : /* if cgi, or fastcgi and not found in fcgi env
433 : check the regular environment
434 : this leaks, but it's only cgi anyway, we'll fix
435 : it for 5.0
436 : */
437 : len = name_len + (value ? strlen(value) : 0) + sizeof("=") + 2;
438 : buf = (char *) malloc(len);
439 : if (buf == NULL) {
440 : return getenv(name);
441 : }
442 : #endif
443 : #if !HAVE_SETENV
444 : if (value) {
445 : len = slprintf(buf, len - 1, "%s=%s", name, value);
446 : putenv(buf);
447 : }
448 : #endif
449 : #if !HAVE_UNSETENV
450 : if (!value) {
451 : len = slprintf(buf, len - 1, "%s=", name);
452 : putenv(buf);
453 : }
454 : #endif
455 216 : return getenv(name);
456 : }
457 :
458 : static char *sapi_cgi_read_cookies(TSRMLS_D)
459 218 : {
460 218 : return sapi_cgibin_getenv((char *) "HTTP_COOKIE", sizeof("HTTP_COOKIE")-1 TSRMLS_CC);
461 : }
462 :
463 : #if PHP_FASTCGI
464 : void cgi_php_import_environment_variables(zval *array_ptr TSRMLS_DC)
465 : {
466 : if (PG(http_globals)[TRACK_VARS_ENV] &&
467 : array_ptr != PG(http_globals)[TRACK_VARS_ENV] &&
468 : Z_TYPE_P(PG(http_globals)[TRACK_VARS_ENV]) == IS_ARRAY &&
469 : zend_hash_num_elements(Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_ENV])) > 0) {
470 : zval_dtor(array_ptr);
471 : *array_ptr = *PG(http_globals)[TRACK_VARS_ENV];
472 : INIT_PZVAL(array_ptr);
473 : zval_copy_ctor(array_ptr);
474 : return;
475 : } else if (PG(http_globals)[TRACK_VARS_SERVER] &&
476 : array_ptr != PG(http_globals)[TRACK_VARS_SERVER] &&
477 : Z_TYPE_P(PG(http_globals)[TRACK_VARS_SERVER]) == IS_ARRAY &&
478 : zend_hash_num_elements(Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_SERVER])) > 0) {
479 : zval_dtor(array_ptr);
480 : *array_ptr = *PG(http_globals)[TRACK_VARS_SERVER];
481 : INIT_PZVAL(array_ptr);
482 : zval_copy_ctor(array_ptr);
483 : return;
484 : }
485 :
486 : /* call php's original import as a catch-all */
487 : php_php_import_environment_variables(array_ptr TSRMLS_CC);
488 :
489 : if (fcgi_is_fastcgi()) {
490 : fcgi_request *request = (fcgi_request*) SG(server_context);
491 : HashPosition pos;
492 : int magic_quotes_gpc = PG(magic_quotes_gpc);
493 : char *var, **val;
494 : uint var_len;
495 : ulong idx;
496 : int filter_arg = (array_ptr == PG(http_globals)[TRACK_VARS_ENV])?PARSE_ENV:PARSE_SERVER;
497 :
498 : /* turn off magic_quotes while importing environment variables */
499 : PG(magic_quotes_gpc) = 0;
500 : for (zend_hash_internal_pointer_reset_ex(&request->env, &pos);
501 : zend_hash_get_current_key_ex(&request->env, &var, &var_len, &idx, 0, &pos) == HASH_KEY_IS_STRING &&
502 : zend_hash_get_current_data_ex(&request->env, (void **) &val, &pos) == SUCCESS;
503 : zend_hash_move_forward_ex(&request->env, &pos)) {
504 : unsigned int new_val_len;
505 : if (sapi_module.input_filter(filter_arg, var, val, strlen(*val), &new_val_len TSRMLS_CC)) {
506 : php_register_variable_safe(var, *val, new_val_len, array_ptr TSRMLS_CC);
507 : }
508 : }
509 : PG(magic_quotes_gpc) = magic_quotes_gpc;
510 : }
511 : }
512 : #endif
513 :
514 : static void sapi_cgi_register_variables(zval *track_vars_array TSRMLS_DC)
515 218 : {
516 : unsigned int new_val_len;
517 218 : char *val = SG(request_info).request_uri ? SG(request_info).request_uri : "";
518 : /* In CGI mode, we consider the environment to be a part of the server
519 : * variables
520 : */
521 218 : php_import_environment_variables(track_vars_array TSRMLS_CC);
522 : /* Build the special-case PHP_SELF variable for the CGI version */
523 218 : if (sapi_module.input_filter(PARSE_SERVER, "PHP_SELF", &val, strlen(val), &new_val_len TSRMLS_CC)) {
524 218 : php_register_variable_safe("PHP_SELF", val, new_val_len, track_vars_array TSRMLS_CC);
525 : }
526 218 : }
527 :
528 : static void sapi_cgi_log_message(char *message)
529 0 : {
530 : #if PHP_FASTCGI
531 : TSRMLS_FETCH();
532 :
533 : if (fcgi_is_fastcgi() && CGIG(fcgi_logging)) {
534 : fcgi_request *request;
535 :
536 : request = (fcgi_request*) SG(server_context);
537 : if (request) {
538 : int len = strlen(message);
539 : char *buf = malloc(len+2);
540 :
541 : memcpy(buf, message, len);
542 : memcpy(buf + len, "\n", sizeof("\n"));
543 : fcgi_write(request, FCGI_STDERR, buf, len+1);
544 : free(buf);
545 : } else {
546 : fprintf(stderr, "%s\n", message);
547 : }
548 : /* ignore return code */
549 : } else
550 : #endif /* PHP_FASTCGI */
551 0 : fprintf(stderr, "%s\n", message);
552 0 : }
553 :
554 : static int sapi_cgi_deactivate(TSRMLS_D)
555 437 : {
556 : /* flush only when SAPI was started. The reasons are:
557 : 1. SAPI Deactivate is called from two places: module init and request shutdown
558 : 2. When the first call occurs and the request is not set up, flush fails on
559 : FastCGI.
560 : */
561 437 : if (SG(sapi_started)) {
562 0 : sapi_cgibin_flush(SG(server_context));
563 : }
564 437 : return SUCCESS;
565 : }
566 :
567 : static int php_cgi_startup(sapi_module_struct *sapi_module)
568 219 : {
569 219 : if (php_module_startup(sapi_module, &cgi_module_entry, 1) == FAILURE) {
570 0 : return FAILURE;
571 : }
572 219 : return SUCCESS;
573 : }
574 :
575 :
576 : /* {{{ sapi_module_struct cgi_sapi_module
577 : */
578 : static sapi_module_struct cgi_sapi_module = {
579 : #if PHP_FASTCGI
580 : "cgi-fcgi", /* name */
581 : "CGI/FastCGI", /* pretty name */
582 : #else
583 : "cgi", /* name */
584 : "CGI", /* pretty name */
585 : #endif
586 :
587 : php_cgi_startup, /* startup */
588 : php_module_shutdown_wrapper, /* shutdown */
589 :
590 : NULL, /* activate */
591 : sapi_cgi_deactivate, /* deactivate */
592 :
593 : sapi_cgibin_ub_write, /* unbuffered write */
594 : sapi_cgibin_flush, /* flush */
595 : NULL, /* get uid */
596 : sapi_cgibin_getenv, /* getenv */
597 :
598 : php_error, /* error handler */
599 :
600 : NULL, /* header handler */
601 : sapi_cgi_send_headers, /* send headers handler */
602 : NULL, /* send header handler */
603 :
604 : sapi_cgi_read_post, /* read POST data */
605 : sapi_cgi_read_cookies, /* read Cookies */
606 :
607 : sapi_cgi_register_variables, /* register server variables */
608 : sapi_cgi_log_message, /* Log message */
609 : NULL, /* Get request time */
610 :
611 : STANDARD_SAPI_MODULE_PROPERTIES
612 : };
613 : /* }}} */
614 :
615 : /* {{{ php_cgi_usage
616 : */
617 : static void php_cgi_usage(char *argv0)
618 1 : {
619 : char *prog;
620 :
621 1 : prog = strrchr(argv0, '/');
622 1 : if (prog) {
623 1 : prog++;
624 : } else {
625 0 : prog = "php";
626 : }
627 :
628 1 : php_printf("Usage: %s [-q] [-h] [-s] [-v] [-i] [-f <file>]\n"
629 : " %s <file> [args...]\n"
630 : " -a Run interactively\n"
631 : #if PHP_FASTCGI
632 : " -b <address:port>|<port> Bind Path for external FASTCGI Server mode\n"
633 : #endif
634 : " -C Do not chdir to the script's directory\n"
635 : " -c <path>|<file> Look for php.ini file in this directory\n"
636 : " -n No php.ini file will be used\n"
637 : " -d foo[=bar] Define INI entry foo with value 'bar'\n"
638 : " -e Generate extended information for debugger/profiler\n"
639 : " -f <file> Parse <file>. Implies `-q'\n"
640 : " -h This help\n"
641 : " -i PHP information\n"
642 : " -l Syntax check only (lint)\n"
643 : " -m Show compiled in modules\n"
644 : " -q Quiet-mode. Suppress HTTP Header output.\n"
645 : " -s Display colour syntax highlighted source.\n"
646 : " -v Version number\n"
647 : " -w Display source with stripped comments and whitespace.\n"
648 : " -z <file> Load Zend extension <file>.\n",
649 : prog, prog);
650 1 : }
651 : /* }}} */
652 :
653 : /* {{{ init_request_info
654 :
655 : initializes request_info structure
656 :
657 : specificly in this section we handle proper translations
658 : for:
659 :
660 : PATH_INFO
661 : derived from the portion of the URI path following
662 : the script name but preceding any query data
663 : may be empty
664 :
665 : PATH_TRANSLATED
666 : derived by taking any path-info component of the
667 : request URI and performing any virtual-to-physical
668 : translation appropriate to map it onto the server's
669 : document repository structure
670 :
671 : empty if PATH_INFO is empty
672 :
673 : The env var PATH_TRANSLATED **IS DIFFERENT** than the
674 : request_info.path_translated variable, the latter should
675 : match SCRIPT_FILENAME instead.
676 :
677 : SCRIPT_NAME
678 : set to a URL path that could identify the CGI script
679 : rather than the interpreter. PHP_SELF is set to this.
680 :
681 : REQUEST_URI
682 : uri section following the domain:port part of a URI
683 :
684 : SCRIPT_FILENAME
685 : The virtual-to-physical translation of SCRIPT_NAME (as per
686 : PATH_TRANSLATED)
687 :
688 : These settings are documented at
689 : http://cgi-spec.golux.com/
690 :
691 :
692 : Based on the following URL request:
693 :
694 : http://localhost/info.php/test?a=b
695 :
696 : should produce, which btw is the same as if
697 : we were running under mod_cgi on apache (ie. not
698 : using ScriptAlias directives):
699 :
700 : PATH_INFO=/test
701 : PATH_TRANSLATED=/docroot/test
702 : SCRIPT_NAME=/info.php
703 : REQUEST_URI=/info.php/test?a=b
704 : SCRIPT_FILENAME=/docroot/info.php
705 : QUERY_STRING=a=b
706 :
707 : but what we get is (cgi/mod_fastcgi under apache):
708 :
709 : PATH_INFO=/info.php/test
710 : PATH_TRANSLATED=/docroot/info.php/test
711 : SCRIPT_NAME=/php/php-cgi (from the Action setting I suppose)
712 : REQUEST_URI=/info.php/test?a=b
713 : SCRIPT_FILENAME=/path/to/php/bin/php-cgi (Action setting translated)
714 : QUERY_STRING=a=b
715 :
716 : Comments in the code below refer to using the above URL in a request
717 :
718 : */
719 : static void init_request_info(TSRMLS_D)
720 218 : {
721 218 : char *env_script_filename = sapi_cgibin_getenv("SCRIPT_FILENAME", sizeof("SCRIPT_FILENAME")-1 TSRMLS_CC);
722 218 : char *env_path_translated = sapi_cgibin_getenv("PATH_TRANSLATED", sizeof("PATH_TRANSLATED")-1 TSRMLS_CC);
723 218 : char *script_path_translated = env_script_filename;
724 :
725 : #if !DISCARD_PATH
726 : /* some broken servers do not have script_filename or argv0
727 : an example, IIS configured in some ways. then they do more
728 : broken stuff and set path_translated to the cgi script location */
729 218 : if (!script_path_translated && env_path_translated) {
730 0 : script_path_translated = env_path_translated;
731 : }
732 : #endif
733 :
734 : /* initialize the defaults */
735 218 : SG(request_info).path_translated = NULL;
736 218 : SG(request_info).request_method = NULL;
737 218 : SG(request_info).proto_num = 1000;
738 218 : SG(request_info).query_string = NULL;
739 218 : SG(request_info).request_uri = NULL;
740 218 : SG(request_info).content_type = NULL;
741 218 : SG(request_info).content_length = 0;
742 218 : SG(sapi_headers).http_response_code = 200;
743 :
744 : /* script_path_translated being set is a good indication that
745 : we are running in a cgi environment, since it is always
746 : null otherwise. otherwise, the filename
747 : of the script will be retreived later via argc/argv */
748 218 : if (script_path_translated) {
749 : const char *auth;
750 108 : char *content_length = sapi_cgibin_getenv("CONTENT_LENGTH", sizeof("CONTENT_LENGTH")-1 TSRMLS_CC);
751 108 : char *content_type = sapi_cgibin_getenv("CONTENT_TYPE", sizeof("CONTENT_TYPE")-1 TSRMLS_CC);
752 108 : char *env_path_info = sapi_cgibin_getenv("PATH_INFO", sizeof("PATH_INFO")-1 TSRMLS_CC);
753 108 : char *env_script_name = sapi_cgibin_getenv("SCRIPT_NAME", sizeof("SCRIPT_NAME")-1 TSRMLS_CC);
754 : #if ENABLE_PATHINFO_CHECK
755 : struct stat st;
756 108 : char *env_redirect_url = sapi_cgibin_getenv("REDIRECT_URL", sizeof("REDIRECT_URL")-1 TSRMLS_CC);
757 108 : char *env_document_root = sapi_cgibin_getenv("DOCUMENT_ROOT", sizeof("DOCUMENT_ROOT")-1 TSRMLS_CC);
758 :
759 108 : if (CGIG(fix_pathinfo)) {
760 : char *real_path;
761 108 : char *orig_path_translated = env_path_translated;
762 108 : char *orig_path_info = env_path_info;
763 108 : char *orig_script_name = env_script_name;
764 108 : char *orig_script_filename = env_script_filename;
765 :
766 108 : if (!env_document_root && PG(doc_root)) {
767 0 : env_document_root = _sapi_cgibin_putenv("DOCUMENT_ROOT", PG(doc_root) TSRMLS_CC);
768 : /* fix docroot */
769 : TRANSLATE_SLASHES(env_document_root);
770 : }
771 :
772 108 : if (env_path_translated != NULL && env_redirect_url != NULL) {
773 : /*
774 : pretty much apache specific. If we have a redirect_url
775 : then our script_filename and script_name point to the
776 : php executable
777 : */
778 0 : script_path_translated = env_path_translated;
779 : /* we correct SCRIPT_NAME now in case we don't have PATH_INFO */
780 0 : env_script_name = env_redirect_url;
781 : }
782 :
783 : #ifdef __riscos__
784 : /* Convert path to unix format*/
785 : __riscosify_control |= __RISCOSIFY_DONT_CHECK_DIR;
786 : script_path_translated = __unixify(script_path_translated, 0, NULL, 1, 0);
787 : #endif
788 :
789 : /*
790 : * if the file doesn't exist, try to extract PATH_INFO out
791 : * of it by stat'ing back through the '/'
792 : * this fixes url's like /info.php/test
793 : */
794 108 : if (script_path_translated &&
795 : (real_path = tsrm_realpath(script_path_translated, NULL TSRMLS_CC)) == NULL) {
796 0 : char *pt = estrdup(script_path_translated);
797 0 : int len = strlen(pt);
798 : char *ptr;
799 :
800 0 : while ((ptr = strrchr(pt, '/')) || (ptr = strrchr(pt, '\\'))) {
801 0 : *ptr = 0;
802 0 : if (stat(pt, &st) == 0 && S_ISREG(st.st_mode)) {
803 : /*
804 : * okay, we found the base script!
805 : * work out how many chars we had to strip off;
806 : * then we can modify PATH_INFO
807 : * accordingly
808 : *
809 : * we now have the makings of
810 : * PATH_INFO=/test
811 : * SCRIPT_FILENAME=/docroot/info.php
812 : *
813 : * we now need to figure out what docroot is.
814 : * if DOCUMENT_ROOT is set, this is easy, otherwise,
815 : * we have to play the game of hide and seek to figure
816 : * out what SCRIPT_NAME should be
817 : */
818 0 : int slen = len - strlen(pt);
819 0 : int pilen = strlen(env_path_info);
820 0 : char *path_info = env_path_info + pilen - slen;
821 :
822 0 : if (orig_path_info != path_info) {
823 0 : if (orig_path_info) {
824 0 : _sapi_cgibin_putenv("ORIG_PATH_INFO", orig_path_info TSRMLS_CC);
825 : }
826 0 : env_path_info = _sapi_cgibin_putenv("PATH_INFO", path_info TSRMLS_CC);
827 : }
828 0 : if (!orig_script_filename ||
829 : strcmp(orig_script_filename, pt) != 0) {
830 0 : if (orig_script_filename) {
831 0 : _sapi_cgibin_putenv("ORIG_SCRIPT_FILENAME", orig_script_filename TSRMLS_CC);
832 : }
833 0 : script_path_translated = _sapi_cgibin_putenv("SCRIPT_FILENAME", pt TSRMLS_CC);
834 : }
835 : TRANSLATE_SLASHES(pt);
836 :
837 : /* figure out docroot
838 : SCRIPT_FILENAME minus SCRIPT_NAME
839 : */
840 :
841 0 : if (env_document_root)
842 : {
843 0 : int l = strlen(env_document_root);
844 0 : int path_translated_len = 0;
845 0 : char *path_translated = NULL;
846 :
847 0 : if (l && env_document_root[l - 1] == '/') {
848 0 : --l;
849 : }
850 :
851 : /* we have docroot, so we should have:
852 : * DOCUMENT_ROOT=/docroot
853 : * SCRIPT_FILENAME=/docroot/info.php
854 : *
855 : * SCRIPT_NAME is the portion of the path beyond docroot
856 : */
857 0 : env_script_name = pt + l;
858 :
859 : /* PATH_TRANSATED = DOCUMENT_ROOT + PATH_INFO */
860 0 : path_translated_len = l + strlen(env_path_info);
861 0 : path_translated = (char *) emalloc(path_translated_len + 1);
862 0 : memcpy(path_translated, env_document_root, l);
863 0 : memcpy(path_translated + l, env_path_info, (path_translated_len - l));
864 0 : path_translated[path_translated_len] = '\0';
865 0 : if (orig_path_translated) {
866 0 : _sapi_cgibin_putenv("ORIG_PATH_TRANSLATED", orig_path_translated TSRMLS_CC);
867 : }
868 0 : env_path_translated = _sapi_cgibin_putenv("PATH_TRANSLATED", path_translated TSRMLS_CC);
869 0 : efree(path_translated);
870 0 : } else if (env_script_name &&
871 : strstr(pt, env_script_name)
872 : ) {
873 : /* PATH_TRANSATED = PATH_TRANSATED - SCRIPT_NAME + PATH_INFO */
874 0 : int ptlen = strlen(pt) - strlen(env_script_name);
875 0 : int path_translated_len = ptlen + strlen(env_path_info);
876 0 : char *path_translated = NULL;
877 :
878 0 : path_translated = (char *) emalloc(path_translated_len + 1);
879 0 : memcpy(path_translated, pt, ptlen);
880 0 : memcpy(path_translated + ptlen, env_path_info, path_translated_len - ptlen);
881 0 : path_translated[path_translated_len] = '\0';
882 0 : if (orig_path_translated) {
883 0 : _sapi_cgibin_putenv("ORIG_PATH_TRANSLATED", orig_path_translated TSRMLS_CC);
884 : }
885 0 : env_path_translated = _sapi_cgibin_putenv("PATH_TRANSLATED", path_translated TSRMLS_CC);
886 0 : efree(path_translated);
887 : }
888 0 : break;
889 : }
890 : }
891 0 : if (!ptr) {
892 : /*
893 : * if we stripped out all the '/' and still didn't find
894 : * a valid path... we will fail, badly. of course we would
895 : * have failed anyway... we output 'no input file' now.
896 : */
897 0 : if (orig_script_filename) {
898 0 : _sapi_cgibin_putenv("ORIG_SCRIPT_FILENAME", orig_script_filename TSRMLS_CC);
899 : }
900 0 : script_path_translated = _sapi_cgibin_putenv("SCRIPT_FILENAME", NULL TSRMLS_CC);
901 0 : SG(sapi_headers).http_response_code = 404;
902 : }
903 0 : if (!orig_script_name ||
904 : strcmp(orig_script_name, env_script_name) != 0) {
905 0 : if (orig_script_name) {
906 0 : _sapi_cgibin_putenv("ORIG_SCRIPT_NAME", orig_script_name TSRMLS_CC);
907 : }
908 0 : SG(request_info).request_uri = _sapi_cgibin_putenv("SCRIPT_NAME", env_script_name TSRMLS_CC);
909 : } else {
910 0 : SG(request_info).request_uri = orig_script_name;
911 : }
912 0 : if (pt) {
913 0 : efree(pt);
914 : }
915 : } else {
916 : /* make sure path_info/translated are empty */
917 108 : if (!orig_script_filename ||
918 : (script_path_translated != orig_script_filename) ||
919 : strcmp(script_path_translated, orig_script_filename) != 0) {
920 0 : if (orig_script_filename) {
921 0 : _sapi_cgibin_putenv("ORIG_SCRIPT_FILENAME", orig_script_filename TSRMLS_CC);
922 : }
923 0 : script_path_translated = _sapi_cgibin_putenv("SCRIPT_FILENAME", script_path_translated TSRMLS_CC);
924 : }
925 108 : if (orig_path_info) {
926 0 : _sapi_cgibin_putenv("ORIG_PATH_INFO", orig_path_info TSRMLS_CC);
927 0 : _sapi_cgibin_putenv("PATH_INFO", NULL TSRMLS_CC);
928 : }
929 108 : if (orig_path_translated) {
930 108 : _sapi_cgibin_putenv("ORIG_PATH_TRANSLATED", orig_path_translated TSRMLS_CC);
931 108 : _sapi_cgibin_putenv("PATH_TRANSLATED", NULL TSRMLS_CC);
932 : }
933 108 : if (env_script_name != orig_script_name) {
934 0 : if (orig_script_name) {
935 0 : _sapi_cgibin_putenv("ORIG_SCRIPT_NAME", orig_script_name TSRMLS_CC);
936 : }
937 0 : SG(request_info).request_uri = _sapi_cgibin_putenv("SCRIPT_NAME", env_script_name TSRMLS_CC);
938 : } else {
939 108 : SG(request_info).request_uri = env_script_name;
940 : }
941 : }
942 108 : free(real_path);
943 : } else {
944 : #endif
945 : /* pre 4.3 behaviour, shouldn't be used but provides BC */
946 0 : if (env_path_info) {
947 0 : SG(request_info).request_uri = env_path_info;
948 : } else {
949 0 : SG(request_info).request_uri = env_script_name;
950 : }
951 : #if !DISCARD_PATH
952 0 : if (env_path_translated)
953 0 : script_path_translated = env_path_translated;
954 : #endif
955 : #if ENABLE_PATHINFO_CHECK
956 : }
957 : #endif
958 108 : SG(request_info).request_method = sapi_cgibin_getenv("REQUEST_METHOD", sizeof("REQUEST_METHOD")-1 TSRMLS_CC);
959 : /* FIXME - Work out proto_num here */
960 108 : SG(request_info).query_string = sapi_cgibin_getenv("QUERY_STRING", sizeof("QUERY_STRING")-1 TSRMLS_CC);
961 : /* some server configurations allow '..' to slip through in the
962 : translated path. We'll just refuse to handle such a path. */
963 108 : if (script_path_translated && !strstr(script_path_translated, "..")) {
964 108 : SG(request_info).path_translated = estrdup(script_path_translated);
965 : }
966 108 : SG(request_info).content_type = (content_type ? content_type : "" );
967 108 : SG(request_info).content_length = (content_length ? atoi(content_length) : 0);
968 :
969 : /* The CGI RFC allows servers to pass on unvalidated Authorization data */
970 108 : auth = sapi_cgibin_getenv("HTTP_AUTHORIZATION", sizeof("HTTP_AUTHORIZATION")-1 TSRMLS_CC);
971 108 : php_handle_auth_data(auth TSRMLS_CC);
972 : }
973 218 : }
974 : /* }}} */
975 :
976 : #if PHP_FASTCGI
977 : /**
978 : * Clean up child processes upon exit
979 : */
980 : void fastcgi_cleanup(int signal)
981 : {
982 : #ifdef DEBUG_FASTCGI
983 : fprintf(stderr, "FastCGI shutdown, pid %d\n", getpid());
984 : #endif
985 :
986 : #ifndef PHP_WIN32
987 : sigaction(SIGTERM, &old_term, 0);
988 :
989 : /* Kill all the processes in our process group */
990 : kill(-pgroup, SIGTERM);
991 : #endif
992 :
993 : /* We should exit at this point, but MacOSX doesn't seem to */
994 : exit(0);
995 : }
996 : #endif
997 :
998 : PHP_INI_BEGIN()
999 : STD_PHP_INI_ENTRY("cgi.rfc2616_headers", "0", PHP_INI_ALL, OnUpdateBool, rfc2616_headers, php_cgi_globals_struct, php_cgi_globals)
1000 : STD_PHP_INI_ENTRY("cgi.nph", "0", PHP_INI_ALL, OnUpdateBool, nph, php_cgi_globals_struct, php_cgi_globals)
1001 : STD_PHP_INI_ENTRY("cgi.check_shebang_line", "1", PHP_INI_SYSTEM, OnUpdateBool, check_shebang_line, php_cgi_globals_struct, php_cgi_globals)
1002 : #if FORCE_CGI_REDIRECT
1003 : STD_PHP_INI_ENTRY("cgi.force_redirect", "1", PHP_INI_SYSTEM, OnUpdateBool, force_redirect, php_cgi_globals_struct, php_cgi_globals)
1004 : STD_PHP_INI_ENTRY("cgi.redirect_status_env", NULL, PHP_INI_SYSTEM, OnUpdateString, redirect_status_env, php_cgi_globals_struct, php_cgi_globals)
1005 : #endif
1006 : #if ENABLE_PATHINFO_CHECK
1007 : STD_PHP_INI_ENTRY("cgi.fix_pathinfo", "1", PHP_INI_SYSTEM, OnUpdateBool, fix_pathinfo, php_cgi_globals_struct, php_cgi_globals)
1008 : #endif
1009 : #if PHP_FASTCGI
1010 : STD_PHP_INI_ENTRY("fastcgi.logging", "1", PHP_INI_SYSTEM, OnUpdateBool, fcgi_logging, php_cgi_globals_struct, php_cgi_globals)
1011 : # ifdef PHP_WIN32
1012 : STD_PHP_INI_ENTRY("fastcgi.impersonate", "0", PHP_INI_SYSTEM, OnUpdateBool, impersonate, php_cgi_globals_struct, php_cgi_globals)
1013 : # endif
1014 : #endif
1015 : PHP_INI_END()
1016 :
1017 : /* {{{ php_cgi_globals_ctor
1018 : */
1019 : static void php_cgi_globals_ctor(php_cgi_globals_struct *php_cgi_globals TSRMLS_DC)
1020 219 : {
1021 219 : php_cgi_globals->rfc2616_headers = 0;
1022 219 : php_cgi_globals->nph = 0;
1023 219 : php_cgi_globals->check_shebang_line = 1;
1024 : #if FORCE_CGI_REDIRECT
1025 : php_cgi_globals->force_redirect = 1;
1026 : php_cgi_globals->redirect_status_env = NULL;
1027 : #endif
1028 : #if ENABLE_PATHINFO_CHECK
1029 219 : php_cgi_globals->fix_pathinfo = 1;
1030 : #endif
1031 : #if PHP_FASTCGI
1032 : php_cgi_globals->fcgi_logging = 1;
1033 : # ifdef PHP_WIN32
1034 : php_cgi_globals->impersonate = 0;
1035 : # endif
1036 : #endif
1037 219 : }
1038 : /* }}} */
1039 :
1040 : /* {{{ PHP_MINIT_FUNCTION
1041 : */
1042 : static PHP_MINIT_FUNCTION(cgi)
1043 219 : {
1044 : #ifdef ZTS
1045 : ts_allocate_id(&php_cgi_globals_id, sizeof(php_cgi_globals_struct), (ts_allocate_ctor) php_cgi_globals_ctor, NULL);
1046 : #else
1047 219 : php_cgi_globals_ctor(&php_cgi_globals TSRMLS_CC);
1048 : #endif
1049 219 : REGISTER_INI_ENTRIES();
1050 219 : return SUCCESS;
1051 : }
1052 : /* }}} */
1053 :
1054 : /* {{{ PHP_MSHUTDOWN_FUNCTION
1055 : */
1056 : static PHP_MSHUTDOWN_FUNCTION(cgi)
1057 218 : {
1058 218 : UNREGISTER_INI_ENTRIES();
1059 218 : return SUCCESS;
1060 : }
1061 : /* }}} */
1062 :
1063 : /* {{{ PHP_MINFO_FUNCTION
1064 : */
1065 : static PHP_MINFO_FUNCTION(cgi)
1066 0 : {
1067 0 : DISPLAY_INI_ENTRIES();
1068 0 : }
1069 : /* }}} */
1070 :
1071 : static zend_module_entry cgi_module_entry = {
1072 : STANDARD_MODULE_HEADER,
1073 : #if PHP_FASTCGI
1074 : "cgi-fcgi",
1075 : #else
1076 : "cgi",
1077 : #endif
1078 : NULL,
1079 : PHP_MINIT(cgi),
1080 : PHP_MSHUTDOWN(cgi),
1081 : NULL,
1082 : NULL,
1083 : PHP_MINFO(cgi),
1084 : NO_VERSION_YET,
1085 : STANDARD_MODULE_PROPERTIES
1086 : };
1087 :
1088 : /* {{{ main
1089 : */
1090 : int main(int argc, char *argv[])
1091 219 : {
1092 219 : int free_query_string = 0;
1093 219 : int exit_status = SUCCESS;
1094 219 : int cgi = 0, c, i, len;
1095 : zend_file_handle file_handle;
1096 219 : int retval = FAILURE;
1097 : char *s;
1098 : /* temporary locals */
1099 219 : int behavior = PHP_MODE_STANDARD;
1100 219 : int no_headers = 0;
1101 219 : int orig_optind = php_optind;
1102 219 : char *orig_optarg = php_optarg;
1103 219 : char *script_file = NULL;
1104 219 : int ini_entries_len = 0;
1105 :
1106 : /* end of temporary locals */
1107 : #ifdef ZTS
1108 : zend_compiler_globals *compiler_globals;
1109 : zend_executor_globals *executor_globals;
1110 : php_core_globals *core_globals;
1111 : sapi_globals_struct *sapi_globals;
1112 : void ***tsrm_ls;
1113 : #endif
1114 :
1115 : #if PHP_FASTCGI
1116 : int max_requests = 500;
1117 : int requests = 0;
1118 : int fastcgi = fcgi_is_fastcgi();
1119 : char *bindpath = NULL;
1120 : int fcgi_fd = 0;
1121 : fcgi_request request;
1122 : #ifndef PHP_WIN32
1123 : int status = 0;
1124 : #endif
1125 : #endif /* PHP_FASTCGI */
1126 :
1127 : #if 0 && defined(PHP_DEBUG)
1128 : /* IIS is always making things more difficult. This allows
1129 : us to stop PHP and attach a debugger before much gets started */
1130 : {
1131 : char szMessage [256];
1132 : wsprintf (szMessage, "Please attach a debugger to the process 0x%X [%d] (%s) and click OK",
1133 : GetCurrentProcessId(), GetCurrentProcessId(), argv[0]);
1134 : MessageBox(NULL, szMessage, "CGI Debug Time!", MB_OK|MB_SERVICE_NOTIFICATION);
1135 : }
1136 : #endif
1137 :
1138 : #ifdef HAVE_SIGNAL_H
1139 : #if defined(SIGPIPE) && defined(SIG_IGN)
1140 219 : signal(SIGPIPE, SIG_IGN); /* ignore SIGPIPE in standalone mode so
1141 : that sockets created via fsockopen()
1142 : don't kill PHP if the remote site
1143 : closes it. in apache|apxs mode apache
1144 : does that for us! thies@thieso.net
1145 : 20000419 */
1146 : #endif
1147 : #endif
1148 :
1149 : #ifdef ZTS
1150 : tsrm_startup(1, 1, 0, NULL);
1151 : #endif
1152 :
1153 219 : sapi_startup(&cgi_sapi_module);
1154 :
1155 : #ifdef PHP_WIN32
1156 : _fmode = _O_BINARY; /* sets default for file streams to binary */
1157 : setmode(_fileno(stdin), O_BINARY); /* make the stdio mode be binary */
1158 : setmode(_fileno(stdout), O_BINARY); /* make the stdio mode be binary */
1159 : setmode(_fileno(stderr), O_BINARY); /* make the stdio mode be binary */
1160 : #endif
1161 :
1162 : #if PHP_FASTCGI
1163 : if (!fastcgi) {
1164 : #endif
1165 : /* Make sure we detect we are a cgi - a bit redundancy here,
1166 : but the default case is that we have to check only the first one. */
1167 219 : if (getenv("SERVER_SOFTWARE") ||
1168 : getenv("SERVER_NAME") ||
1169 : getenv("GATEWAY_INTERFACE") ||
1170 : getenv("REQUEST_METHOD")
1171 : ) {
1172 108 : cgi = 1;
1173 : }
1174 : #if PHP_FASTCGI
1175 : }
1176 : #endif
1177 :
1178 5017 : while ((c = php_getopt(argc, argv, OPTIONS, &php_optarg, &php_optind, 0)) != -1) {
1179 4579 : switch (c) {
1180 : case 'c':
1181 0 : cgi_sapi_module.php_ini_path_override = strdup(php_optarg);
1182 0 : break;
1183 : case 'n':
1184 0 : cgi_sapi_module.php_ini_ignore = 1;
1185 0 : break;
1186 : case 'd': {
1187 : /* define ini entries on command line */
1188 4362 : int len = strlen(php_optarg);
1189 : char *val;
1190 :
1191 4362 : if ((val = strchr(php_optarg, '='))) {
1192 4362 : val++;
1193 4582 : if (!isalnum(*val) && *val != '"' && *val != '\'' && *val != '\0') {
1194 220 : cgi_sapi_module.ini_entries = realloc(cgi_sapi_module.ini_entries, ini_entries_len + len + sizeof("\"\"\n\0"));
1195 220 : memcpy(cgi_sapi_module.ini_entries + ini_entries_len, php_optarg, (val - php_optarg));
1196 220 : ini_entries_len += (val - php_optarg);
1197 220 : memcpy(cgi_sapi_module.ini_entries + ini_entries_len, "\"", 1);
1198 220 : ini_entries_len++;
1199 220 : memcpy(cgi_sapi_module.ini_entries + ini_entries_len, val, len - (val - php_optarg));
1200 220 : ini_entries_len += len - (val - php_optarg);
1201 220 : memcpy(cgi_sapi_module.ini_entries + ini_entries_len, "\"\n\0", sizeof("\"\n\0"));
1202 220 : ini_entries_len += sizeof("\n\0\"") - 2;
1203 : } else {
1204 4142 : cgi_sapi_module.ini_entries = realloc(cgi_sapi_module.ini_entries, ini_entries_len + len + sizeof("\n\0"));
1205 4142 : memcpy(cgi_sapi_module.ini_entries + ini_entries_len, php_optarg, len);
1206 4142 : memcpy(cgi_sapi_module.ini_entries + ini_entries_len + len, "\n\0", sizeof("\n\0"));
1207 4142 : ini_entries_len += len + sizeof("\n\0") - 2;
1208 : }
1209 : } else {
1210 0 : cgi_sapi_module.ini_entries = realloc(cgi_sapi_module.ini_entries, ini_entries_len + len + sizeof("=1\n\0"));
1211 0 : memcpy(cgi_sapi_module.ini_entries + ini_entries_len, php_optarg, len);
1212 0 : memcpy(cgi_sapi_module.ini_entries + ini_entries_len + len, "=1\n\0", sizeof("=1\n\0"));
1213 0 : ini_entries_len += len + sizeof("=1\n\0") - 2;
1214 : }
1215 : break;
1216 : }
1217 : #if PHP_FASTCGI
1218 : /* if we're started on command line, check to see if
1219 : we are being started as an 'external' fastcgi
1220 : server by accepting a bindpath parameter. */
1221 : case 'b':
1222 : if (!fastcgi) {
1223 : bindpath = strdup(php_optarg);
1224 : }
1225 : break;
1226 : #endif
1227 : }
1228 :
1229 : }
1230 219 : php_optind = orig_optind;
1231 219 : php_optarg = orig_optarg;
1232 :
1233 : #ifdef ZTS
1234 : compiler_globals = ts_resource(compiler_globals_id);
1235 : executor_globals = ts_resource(executor_globals_id);
1236 : core_globals = ts_resource(core_globals_id);
1237 : sapi_globals = ts_resource(sapi_globals_id);
1238 : tsrm_ls = ts_resource(0);
1239 : SG(request_info).path_translated = NULL;
1240 : #endif
1241 :
1242 219 : cgi_sapi_module.executable_location = argv[0];
1243 :
1244 : /* startup after we get the above ini override se we get things right */
1245 219 : if (cgi_sapi_module.startup(&cgi_sapi_module) == FAILURE) {
1246 : #ifdef ZTS
1247 : tsrm_shutdown();
1248 : #endif
1249 0 : return FAILURE;
1250 : }
1251 :
1252 : #if FORCE_CGI_REDIRECT
1253 : /* check force_cgi after startup, so we have proper output */
1254 : if (cgi && CGIG(force_redirect)) {
1255 : /* Apache will generate REDIRECT_STATUS,
1256 : * Netscape and redirect.so will generate HTTP_REDIRECT_STATUS.
1257 : * redirect.so and installation instructions available from
1258 : * http://www.koehntopp.de/php.
1259 : * -- kk@netuse.de
1260 : */
1261 : if (!getenv("REDIRECT_STATUS")
1262 : && !getenv ("HTTP_REDIRECT_STATUS")
1263 : /* this is to allow a different env var to be configured
1264 : in case some server does something different than above */
1265 : && (!CGIG(redirect_status_env) || !getenv(CGIG(redirect_status_env)))
1266 : ) {
1267 : SG(sapi_headers).http_response_code = 400;
1268 : PUTS("<b>Security Alert!</b> The PHP CGI cannot be accessed directly.\n\n\
1269 : <p>This PHP CGI binary was compiled with force-cgi-redirect enabled. This\n\
1270 : means that a page will only be served up if the REDIRECT_STATUS CGI variable is\n\
1271 : set, e.g. via an Apache Action directive.</p>\n\
1272 : <p>For more information as to <i>why</i> this behaviour exists, see the <a href=\"http://php.net/security.cgi-bin\">\
1273 : manual page for CGI security</a>.</p>\n\
1274 : <p>For more information about changing this behaviour or re-enabling this webserver,\n\
1275 : consult the installation file that came with this distribution, or visit \n\
1276 : <a href=\"http://php.net/install.windows\">the manual page</a>.</p>\n");
1277 :
1278 : #if defined(ZTS) && !defined(PHP_DEBUG)
1279 : /* XXX we're crashing here in msvc6 debug builds at
1280 : php_message_handler_for_zend:839 because
1281 : SG(request_info).path_translated is an invalid pointer.
1282 : It still happens even though I set it to null, so something
1283 : weird is going on.
1284 : */
1285 : tsrm_shutdown();
1286 : #endif
1287 : return FAILURE;
1288 : }
1289 : }
1290 : #endif /* FORCE_CGI_REDIRECT */
1291 :
1292 : #if PHP_FASTCGI
1293 : /* for windows, socket listening is broken in the fastcgi library itself
1294 : so dissabling this feature on windows till time is available to fix it */
1295 : if (bindpath) {
1296 : fcgi_fd = fcgi_listen(bindpath, 128);
1297 : if (fcgi_fd < 0) {
1298 : fprintf(stderr, "Couldn't create FastCGI listen socket on port %s\n", bindpath);
1299 : #ifdef ZTS
1300 : tsrm_shutdown();
1301 : #endif
1302 : return FAILURE;
1303 : }
1304 : fastcgi = fcgi_is_fastcgi();
1305 : }
1306 :
1307 : if (fastcgi) {
1308 : /* How many times to run PHP scripts before dying */
1309 : if (getenv("PHP_FCGI_MAX_REQUESTS")) {
1310 : max_requests = atoi(getenv("PHP_FCGI_MAX_REQUESTS"));
1311 : if (max_requests < 0) {
1312 : fprintf(stderr, "PHP_FCGI_MAX_REQUESTS is not valid\n");
1313 : return FAILURE;
1314 : }
1315 : }
1316 :
1317 : /* make php call us to get _ENV vars */
1318 : php_php_import_environment_variables = php_import_environment_variables;
1319 : php_import_environment_variables = cgi_php_import_environment_variables;
1320 :
1321 : /* library is already initialized, now init our request */
1322 : fcgi_init_request(&request, fcgi_fd);
1323 :
1324 : #ifndef PHP_WIN32
1325 : /* Pre-fork, if required */
1326 : if (getenv("PHP_FCGI_CHILDREN")) {
1327 : children = atoi(getenv("PHP_FCGI_CHILDREN"));
1328 : if (children < 0) {
1329 : fprintf(stderr, "PHP_FCGI_CHILDREN is not valid\n");
1330 : return FAILURE;
1331 : }
1332 : }
1333 :
1334 : if (children) {
1335 : int running = 0;
1336 : pid_t pid;
1337 :
1338 : /* Create a process group for ourself & children */
1339 : setsid();
1340 : pgroup = getpgrp();
1341 : #ifdef DEBUG_FASTCGI
1342 : fprintf(stderr, "Process group %d\n", pgroup);
1343 : #endif
1344 :
1345 : /* Set up handler to kill children upon exit */
1346 : act.sa_flags = 0;
1347 : act.sa_handler = fastcgi_cleanup;
1348 : if (sigaction(SIGTERM, &act, &old_term) ||
1349 : sigaction(SIGINT, &act, &old_int) ||
1350 : sigaction(SIGQUIT, &act, &old_quit)) {
1351 : perror("Can't set signals");
1352 : exit(1);
1353 : }
1354 :
1355 : if (fcgi_in_shutdown()) {
1356 : exit(0);
1357 : }
1358 :
1359 : while (parent) {
1360 : do {
1361 : #ifdef DEBUG_FASTCGI
1362 : fprintf(stderr, "Forking, %d running\n", running);
1363 : #endif
1364 : pid = fork();
1365 : switch (pid) {
1366 : case 0:
1367 : /* One of the children.
1368 : * Make sure we don't go round the
1369 : * fork loop any more
1370 : */
1371 : parent = 0;
1372 :
1373 : /* don't catch our signals */
1374 : sigaction(SIGTERM, &old_term, 0);
1375 : sigaction(SIGQUIT, &old_quit, 0);
1376 : sigaction(SIGINT, &old_int, 0);
1377 : break;
1378 : case -1:
1379 : perror("php (pre-forking)");
1380 : exit(1);
1381 : break;
1382 : default:
1383 : /* Fine */
1384 : running++;
1385 : break;
1386 : }
1387 : } while (parent && (running < children));
1388 :
1389 : if (parent) {
1390 : #ifdef DEBUG_FASTCGI
1391 : fprintf(stderr, "Wait for kids, pid %d\n", getpid());
1392 : #endif
1393 : while (wait(&status) < 0) {
1394 : }
1395 : running--;
1396 : }
1397 : }
1398 : } else {
1399 : parent = 0;
1400 : }
1401 :
1402 : #endif /* WIN32 */
1403 : }
1404 : #endif /* FASTCGI */
1405 :
1406 219 : zend_first_try {
1407 5016 : while ((c = php_getopt(argc, argv, OPTIONS, &php_optarg, &php_optind, 1)) != -1) {
1408 4579 : switch (c) {
1409 : case 'h':
1410 : case '?':
1411 1 : no_headers = 1;
1412 1 : php_output_startup();
1413 1 : php_output_activate(TSRMLS_C);
1414 1 : SG(headers_sent) = 1;
1415 1 : php_cgi_usage(argv[0]);
1416 1 : php_end_ob_buffers(1 TSRMLS_CC);
1417 1 : exit(1);
1418 : break;
1419 : }
1420 : }
1421 218 : php_optind = orig_optind;
1422 218 : php_optarg = orig_optarg;
1423 :
1424 : #if PHP_FASTCGI
1425 : /* start of FAST CGI loop */
1426 : /* Initialise FastCGI request structure */
1427 : #ifdef PHP_WIN32
1428 : /* attempt to set security impersonation for fastcgi
1429 : will only happen on NT based OS, others will ignore it. */
1430 : if (fastcgi && CGIG(impersonate)) {
1431 : fcgi_impersonate();
1432 : }
1433 : #endif
1434 : while (!fastcgi || fcgi_accept_request(&request) >= 0) {
1435 : #endif
1436 :
1437 : #if PHP_FASTCGI
1438 : SG(server_context) = (void *) &request;
1439 : #else
1440 218 : SG(server_context) = (void *) 1; /* avoid server_context==NULL checks */
1441 : #endif
1442 218 : init_request_info(TSRMLS_C);
1443 218 : CG(interactive) = 0;
1444 :
1445 218 : if (!cgi
1446 : #if PHP_FASTCGI
1447 : && !fastcgi
1448 : #endif
1449 : ) {
1450 110 : if (cgi_sapi_module.php_ini_path_override && cgi_sapi_module.php_ini_ignore) {
1451 0 : no_headers = 1;
1452 0 : php_output_startup();
1453 0 : php_output_activate(TSRMLS_C);
1454 0 : SG(headers_sent) = 1;
1455 0 : php_printf("You cannot use both -n and -c switch. Use -h for help.\n");
1456 0 : php_end_ob_buffers(1 TSRMLS_CC);
1457 0 : exit(1);
1458 : }
1459 :
1460 2528 : while ((c = php_getopt(argc, argv, OPTIONS, &php_optarg, &php_optind, 0)) != -1) {
1461 2308 : switch (c) {
1462 :
1463 : case 'a': /* interactive mode */
1464 0 : printf("Interactive mode enabled\n\n");
1465 0 : CG(interactive) = 1;
1466 0 : break;
1467 :
1468 : case 'C': /* don't chdir to the script directory */
1469 0 : SG(options) |= SAPI_OPTION_NO_CHDIR;
1470 0 : break;
1471 :
1472 : case 'e': /* enable extended info output */
1473 0 : CG(extended_info) = 1;
1474 0 : break;
1475 :
1476 : case 'f': /* parse file */
1477 0 : script_file = estrdup(php_optarg);
1478 0 : no_headers = 1;
1479 : /* arguments after the file are considered script args */
1480 0 : SG(request_info).argc = argc - (php_optind - 1);
1481 0 : SG(request_info).argv = &argv[php_optind - 1];
1482 0 : break;
1483 :
1484 : case 'i': /* php info & quit */
1485 0 : if (php_request_startup(TSRMLS_C) == FAILURE) {
1486 0 : SG(server_context) = NULL;
1487 0 : php_module_shutdown(TSRMLS_C);
1488 0 : return FAILURE;
1489 : }
1490 0 : if (no_headers) {
1491 0 : SG(headers_sent) = 1;
1492 0 : SG(request_info).no_headers = 1;
1493 : }
1494 0 : php_print_info(0xFFFFFFFF TSRMLS_CC);
1495 0 : php_end_ob_buffers(1 TSRMLS_CC);
1496 0 : exit(0);
1497 : break;
1498 :
1499 : case 'l': /* syntax check mode */
1500 0 : no_headers = 1;
1501 0 : behavior = PHP_MODE_LINT;
1502 0 : break;
1503 :
1504 : case 'm': /* list compiled in modules */
1505 0 : php_output_startup();
1506 0 : php_output_activate(TSRMLS_C);
1507 0 : SG(headers_sent) = 1;
1508 0 : php_printf("[PHP Modules]\n");
1509 0 : print_modules(TSRMLS_C);
1510 0 : php_printf("\n[Zend Modules]\n");
1511 0 : print_extensions(TSRMLS_C);
1512 0 : php_printf("\n");
1513 0 : php_end_ob_buffers(1 TSRMLS_CC);
1514 0 : exit(0);
1515 : break;
1516 :
1517 : #if 0 /* not yet operational, see also below ... */
1518 : case '': /* generate indented source mode*/
1519 : behavior=PHP_MODE_INDENT;
1520 : break;
1521 : #endif
1522 :
1523 : case 'q': /* do not generate HTTP headers */
1524 108 : no_headers = 1;
1525 108 : break;
1526 :
1527 : case 's': /* generate highlighted HTML from source */
1528 0 : behavior = PHP_MODE_HIGHLIGHT;
1529 0 : break;
1530 :
1531 : case 'v': /* show php version & quit */
1532 0 : no_headers = 1;
1533 0 : if (php_request_startup(TSRMLS_C) == FAILURE) {
1534 0 : SG(server_context) = NULL;
1535 0 : php_module_shutdown(TSRMLS_C);
1536 0 : return FAILURE;
1537 : }
1538 0 : if (no_headers) {
1539 0 : SG(headers_sent) = 1;
1540 0 : SG(request_info).no_headers = 1;
1541 : }
1542 : #if ZEND_DEBUG
1543 : php_printf("PHP %s (%s) (built: %s %s) (DEBUG)\nCopyright (c) 1997-2007 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
1544 : #else
1545 0 : php_printf("PHP %s (%s) (built: %s %s)\nCopyright (c) 1997-2007 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
1546 : #endif
1547 0 : php_end_ob_buffers(1 TSRMLS_CC);
1548 0 : exit(0);
1549 : break;
1550 :
1551 : case 'w':
1552 0 : behavior = PHP_MODE_STRIP;
1553 0 : break;
1554 :
1555 : case 'z': /* load extension file */
1556 0 : zend_load_extension(php_optarg);
1557 : break;
1558 :
1559 : default:
1560 : break;
1561 : }
1562 : }
1563 :
1564 110 : if (script_file) {
1565 : /* override path_translated if -f on command line */
1566 0 : STR_FREE(SG(request_info).path_translated);
1567 0 : SG(request_info).path_translated = script_file;
1568 : }
1569 :
1570 110 : if (no_headers) {
1571 108 : SG(headers_sent) = 1;
1572 108 : SG(request_info).no_headers = 1;
1573 : }
1574 :
1575 110 : if (!SG(request_info).path_translated && argc > php_optind) {
1576 : /* arguments after the file are considered script args */
1577 110 : SG(request_info).argc = argc - php_optind;
1578 110 : SG(request_info).argv = &argv[php_optind];
1579 : /* file is on command line, but not in -f opt */
1580 110 : SG(request_info).path_translated = estrdup(argv[php_optind++]);
1581 : }
1582 :
1583 : /* all remaining arguments are part of the query string
1584 : this section of code concatenates all remaining arguments
1585 : into a single string, seperating args with a &
1586 : this allows command lines like:
1587 :
1588 : test.php v1=test v2=hello+world!
1589 : test.php "v1=test&v2=hello world!"
1590 : test.php v1=test "v2=hello world!"
1591 : */
1592 110 : if (!SG(request_info).query_string && argc > php_optind) {
1593 0 : int slen = strlen(PG(arg_separator).input);
1594 0 : len = 0;
1595 0 : for (i = php_optind; i < argc; i++) {
1596 0 : if (i < (argc - 1)) {
1597 0 : len += strlen(argv[i]) + slen;
1598 : } else {
1599 0 : len += strlen(argv[i]);
1600 : }
1601 : }
1602 :
1603 0 : len += 2;
1604 0 : s = malloc(len);
1605 0 : *s = '\0'; /* we are pretending it came from the environment */
1606 0 : for (i = php_optind; i < argc; i++) {
1607 0 : strlcat(s, argv[i], len);
1608 0 : if (i < (argc - 1)) {
1609 0 : strlcat(s, PG(arg_separator).input, len);
1610 : }
1611 : }
1612 0 : SG(request_info).query_string = s;
1613 0 : free_query_string = 1;
1614 : }
1615 : } /* end !cgi && !fastcgi */
1616 :
1617 : /*
1618 : we never take stdin if we're (f)cgi, always
1619 : rely on the web server giving us the info
1620 : we need in the environment.
1621 : */
1622 436 : if (SG(request_info).path_translated || cgi
1623 : #if PHP_FASTCGI
1624 : || fastcgi
1625 : #endif
1626 : )
1627 : {
1628 218 : file_handle.type = ZEND_HANDLE_FILENAME;
1629 218 : file_handle.filename = SG(request_info).path_translated;
1630 218 : file_handle.handle.fp = NULL;
1631 : } else {
1632 0 : file_handle.filename = "-";
1633 0 : file_handle.type = ZEND_HANDLE_FP;
1634 0 : file_handle.handle.fp = stdin;
1635 : }
1636 :
1637 218 : file_handle.opened_path = NULL;
1638 218 : file_handle.free_filename = 0;
1639 :
1640 : /* request startup only after we've done all we can to
1641 : get path_translated */
1642 218 : if (php_request_startup(TSRMLS_C) == FAILURE) {
1643 : #if PHP_FASTCGI
1644 : if (fastcgi) {
1645 : fcgi_finish_request(&request);
1646 : }
1647 : #endif
1648 0 : SG(server_context) = NULL;
1649 0 : php_module_shutdown(TSRMLS_C);
1650 0 : return FAILURE;
1651 : }
1652 218 : if (no_headers) {
1653 108 : SG(headers_sent) = 1;
1654 108 : SG(request_info).no_headers = 1;
1655 : }
1656 :
1657 : /*
1658 : at this point path_translated will be set if:
1659 : 1. we are running from shell and got filename was there
1660 : 2. we are running as cgi or fastcgi
1661 : */
1662 218 : retval = FAILURE;
1663 218 : if (cgi || SG(request_info).path_translated) {
1664 218 : retval = php_fopen_primary_script(&file_handle TSRMLS_CC);
1665 : }
1666 : /*
1667 : if we are unable to open path_translated and we are not
1668 : running from shell (so fp == NULL), then fail.
1669 : */
1670 218 : if (retval == FAILURE && file_handle.handle.fp == NULL) {
1671 0 : if (errno == EACCES) {
1672 0 : SG(sapi_headers).http_response_code = 403;
1673 0 : PUTS("Access denied.\n");
1674 : } else {
1675 0 : SG(sapi_headers).http_response_code = 404;
1676 0 : PUTS("No input file specified.\n");
1677 : }
1678 : #if PHP_FASTCGI
1679 : /* we want to serve more requests if this is fastcgi
1680 : so cleanup and continue, request shutdown is
1681 : handled later */
1682 : if (fastcgi) {
1683 : goto fastcgi_request_done;
1684 : }
1685 : #endif
1686 0 : php_request_shutdown((void *) 0);
1687 0 : SG(server_context) = NULL;
1688 0 : php_module_shutdown(TSRMLS_C);
1689 0 : return FAILURE;
1690 : }
1691 :
1692 218 : if (CGIG(check_shebang_line) && file_handle.handle.fp && (file_handle.handle.fp != stdin)) {
1693 : /* #!php support */
1694 218 : c = fgetc(file_handle.handle.fp);
1695 218 : if (c == '#') {
1696 0 : while (c != '\n' && c != '\r') {
1697 0 : c = fgetc(file_handle.handle.fp); /* skip to end of line */
1698 : }
1699 : /* handle situations where line is terminated by \r\n */
1700 0 : if (c == '\r') {
1701 0 : if (fgetc(file_handle.handle.fp) != '\n') {
1702 0 : long pos = ftell(file_handle.handle.fp);
1703 0 : fseek(file_handle.handle.fp, pos - 1, SEEK_SET);
1704 : }
1705 : }
1706 0 : CG(start_lineno) = 2;
1707 : } else {
1708 218 : rewind(file_handle.handle.fp);
1709 : }
1710 : }
1711 :
1712 218 : switch (behavior) {
1713 : case PHP_MODE_STANDARD:
1714 218 : php_execute_script(&file_handle TSRMLS_CC);
1715 218 : break;
1716 : case PHP_MODE_LINT:
1717 0 : PG(during_request_startup) = 0;
1718 0 : exit_status = php_lint_script(&file_handle TSRMLS_CC);
1719 0 : if (exit_status == SUCCESS) {
1720 0 : zend_printf("No syntax errors detected in %s\n", file_handle.filename);
1721 : } else {
1722 0 : zend_printf("Errors parsing %s\n", file_handle.filename);
1723 : }
1724 0 : break;
1725 : case PHP_MODE_STRIP:
1726 0 : if (open_file_for_scanning(&file_handle TSRMLS_CC) == SUCCESS) {
1727 0 : zend_strip(TSRMLS_C);
1728 0 : fclose(file_handle.handle.fp);
1729 0 : php_end_ob_buffers(1 TSRMLS_CC);
1730 : }
1731 0 : return SUCCESS;
1732 : break;
1733 : case PHP_MODE_HIGHLIGHT:
1734 : {
1735 : zend_syntax_highlighter_ini syntax_highlighter_ini;
1736 :
1737 0 : if (open_file_for_scanning(&file_handle TSRMLS_CC) == SUCCESS) {
1738 0 : php_get_highlight_struct(&syntax_highlighter_ini);
1739 0 : zend_highlight(&syntax_highlighter_ini TSRMLS_CC);
1740 0 : fclose(file_handle.handle.fp);
1741 0 : php_end_ob_buffers(1 TSRMLS_CC);
1742 : }
1743 0 : return SUCCESS;
1744 : }
1745 : break;
1746 : #if 0
1747 : /* Zeev might want to do something with this one day */
1748 : case PHP_MODE_INDENT:
1749 : open_file_for_scanning(&file_handle TSRMLS_CC);
1750 : zend_indent();
1751 : fclose(file_handle.handle.fp);
1752 : return SUCCESS;
1753 : break;
1754 : #endif
1755 : }
1756 :
1757 : #if PHP_FASTCGI
1758 : fastcgi_request_done:
1759 : #endif
1760 : {
1761 : char *path_translated;
1762 :
1763 : /* Go through this trouble so that the memory manager doesn't warn
1764 : * about SG(request_info).path_translated leaking
1765 : */
1766 218 : if (SG(request_info).path_translated) {
1767 218 : path_translated = strdup(SG(request_info).path_translated);
1768 218 : STR_FREE(SG(request_info).path_translated);
1769 218 : SG(request_info).path_translated = path_translated;
1770 : }
1771 :
1772 218 : php_request_shutdown((void *) 0);
1773 218 : if (exit_status == 0) {
1774 218 : exit_status = EG(exit_status);
1775 : }
1776 :
1777 218 : if (SG(request_info).path_translated) {
1778 218 : free(SG(request_info).path_translated);
1779 218 : SG(request_info).path_translated = NULL;
1780 : }
1781 218 : if (free_query_string && SG(request_info).query_string) {
1782 0 : free(SG(request_info).query_string);
1783 0 : SG(request_info).query_string = NULL;
1784 : }
1785 :
1786 : }
1787 :
1788 : #if PHP_FASTCGI
1789 : if (!fastcgi) break;
1790 : /* only fastcgi will get here */
1791 : requests++;
1792 : if (max_requests && (requests == max_requests)) {
1793 : fcgi_finish_request(&request);
1794 : if (bindpath) {
1795 : free(bindpath);
1796 : }
1797 : break;
1798 : }
1799 : /* end of fastcgi loop */
1800 : }
1801 : #endif
1802 :
1803 218 : if (cgi_sapi_module.php_ini_path_override) {
1804 0 : free(cgi_sapi_module.php_ini_path_override);
1805 : }
1806 218 : if (cgi_sapi_module.ini_entries) {
1807 218 : free(cgi_sapi_module.ini_entries);
1808 : }
1809 0 : } zend_catch {
1810 0 : exit_status = 255;
1811 218 : } zend_end_try();
1812 :
1813 218 : SG(server_context) = NULL;
1814 218 : php_module_shutdown(TSRMLS_C);
1815 218 : sapi_shutdown();
1816 :
1817 : #ifdef ZTS
1818 : /*tsrm_shutdown();*/
1819 : #endif
1820 :
1821 : #if defined(PHP_WIN32) && ZEND_DEBUG && 0
1822 : _CrtDumpMemoryLeaks();
1823 : #endif
1824 :
1825 218 : return exit_status;
1826 : }
1827 : /* }}} */
1828 :
1829 : /*
1830 : * Local variables:
1831 : * tab-width: 4
1832 : * c-basic-offset: 4
1833 : * End:
1834 : * vim600: sw=4 ts=4 fdm=marker
1835 : * vim<600: sw=4 ts=4
1836 : */
|