This source file includes following definitions.
- user_config_cache_entry_dtor
- print_module_info
- module_name_cmp
- print_modules
- print_extension_info
- extension_name_cmp
- print_extensions
- sapi_cgi_single_write
- sapi_cgi_ub_write
- sapi_fcgi_ub_write
- sapi_cgi_flush
- sapi_fcgi_flush
- sapi_cgi_send_headers
- sapi_cgi_read_post
- sapi_fcgi_read_post
- sapi_cgi_getenv
- sapi_fcgi_getenv
- _sapi_cgi_putenv
- sapi_cgi_read_cookies
- sapi_fcgi_read_cookies
- cgi_php_load_env_var
- cgi_php_import_environment_variables
- sapi_cgi_register_variables
- sapi_cgi_log_message
- php_cgi_ini_activate_user_config
- sapi_cgi_activate
- sapi_cgi_deactivate
- php_cgi_startup
- php_cgi_usage
- is_valid_path
- init_request_info
- fastcgi_cleanup
- PHP_INI_BEGIN
- PHP_MINIT_FUNCTION
- PHP_MSHUTDOWN_FUNCTION
- PHP_MINFO_FUNCTION
- PHP_FUNCTION
- add_request_header
- PHP_FUNCTION
- add_response_header
- PHP_FUNCTION
- main
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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 #include "ext/standard/url.h"
74
75 #ifdef PHP_WIN32
76 # include <io.h>
77 # include <fcntl.h>
78 # include "win32/php_registry.h"
79 #endif
80
81 #ifdef __riscos__
82 # include <unixlib/local.h>
83 int __riscosify_control = __RISCOSIFY_STRICT_UNIX_SPECS;
84 #endif
85
86 #include "zend_compile.h"
87 #include "zend_execute.h"
88 #include "zend_highlight.h"
89 #include "zend_indent.h"
90
91 #include "php_getopt.h"
92
93 #include "fastcgi.h"
94
95 #ifndef PHP_WIN32
96
97 struct sigaction act, old_term, old_quit, old_int;
98 #endif
99
100 static void (*php_php_import_environment_variables)(zval *array_ptr TSRMLS_DC);
101
102 #ifndef PHP_WIN32
103
104
105
106
107 static int children = 0;
108
109
110
111
112
113 static int parent = 1;
114
115
116 static int exit_signal = 0;
117
118
119 static int parent_waiting = 0;
120
121
122
123
124 static pid_t pgroup;
125 #endif
126
127 #define PHP_MODE_STANDARD 1
128 #define PHP_MODE_HIGHLIGHT 2
129 #define PHP_MODE_INDENT 3
130 #define PHP_MODE_LINT 4
131 #define PHP_MODE_STRIP 5
132
133 static char *php_optarg = NULL;
134 static int php_optind = 1;
135 static zend_module_entry cgi_module_entry;
136
137 static const opt_struct OPTIONS[] = {
138 {'a', 0, "interactive"},
139 {'b', 1, "bindpath"},
140 {'C', 0, "no-chdir"},
141 {'c', 1, "php-ini"},
142 {'d', 1, "define"},
143 {'e', 0, "profile-info"},
144 {'f', 1, "file"},
145 {'h', 0, "help"},
146 {'i', 0, "info"},
147 {'l', 0, "syntax-check"},
148 {'m', 0, "modules"},
149 {'n', 0, "no-php-ini"},
150 {'q', 0, "no-header"},
151 {'s', 0, "syntax-highlight"},
152 {'s', 0, "syntax-highlighting"},
153 {'w', 0, "strip"},
154 {'?', 0, "usage"},
155 {'v', 0, "version"},
156 {'z', 1, "zend-extension"},
157 {'T', 1, "timing"},
158 {'-', 0, NULL}
159 };
160
161 typedef struct _php_cgi_globals_struct {
162 zend_bool rfc2616_headers;
163 zend_bool nph;
164 zend_bool check_shebang_line;
165 zend_bool fix_pathinfo;
166 zend_bool force_redirect;
167 zend_bool discard_path;
168 zend_bool fcgi_logging;
169 char *redirect_status_env;
170 #ifdef PHP_WIN32
171 zend_bool impersonate;
172 #endif
173 HashTable user_config_cache;
174 } php_cgi_globals_struct;
175
176
177
178
179
180
181
182
183
184
185 typedef struct _user_config_cache_entry {
186 time_t expires;
187 HashTable *user_config;
188 } user_config_cache_entry;
189
190 static void user_config_cache_entry_dtor(user_config_cache_entry *entry)
191 {
192 zend_hash_destroy(entry->user_config);
193 free(entry->user_config);
194 }
195
196
197 #ifdef ZTS
198 static int php_cgi_globals_id;
199 #define CGIG(v) TSRMG(php_cgi_globals_id, php_cgi_globals_struct *, v)
200 #else
201 static php_cgi_globals_struct php_cgi_globals;
202 #define CGIG(v) (php_cgi_globals.v)
203 #endif
204
205 #ifdef PHP_WIN32
206 #define TRANSLATE_SLASHES(path) \
207 { \
208 char *tmp = path; \
209 while (*tmp) { \
210 if (*tmp == '\\') *tmp = '/'; \
211 tmp++; \
212 } \
213 }
214 #else
215 #define TRANSLATE_SLASHES(path)
216 #endif
217
218 static int print_module_info(zend_module_entry *module, void *arg TSRMLS_DC)
219 {
220 php_printf("%s\n", module->name);
221 return 0;
222 }
223
224 static int module_name_cmp(const void *a, const void *b TSRMLS_DC)
225 {
226 Bucket *f = *((Bucket **) a);
227 Bucket *s = *((Bucket **) b);
228
229 return strcasecmp( ((zend_module_entry *)f->pData)->name,
230 ((zend_module_entry *)s->pData)->name);
231 }
232
233 static void print_modules(TSRMLS_D)
234 {
235 HashTable sorted_registry;
236 zend_module_entry tmp;
237
238 zend_hash_init(&sorted_registry, 50, NULL, NULL, 1);
239 zend_hash_copy(&sorted_registry, &module_registry, NULL, &tmp, sizeof(zend_module_entry));
240 zend_hash_sort(&sorted_registry, zend_qsort, module_name_cmp, 0 TSRMLS_CC);
241 zend_hash_apply_with_argument(&sorted_registry, (apply_func_arg_t) print_module_info, NULL TSRMLS_CC);
242 zend_hash_destroy(&sorted_registry);
243 }
244
245 static int print_extension_info(zend_extension *ext, void *arg TSRMLS_DC)
246 {
247 php_printf("%s\n", ext->name);
248 return 0;
249 }
250
251 static int extension_name_cmp(const zend_llist_element **f, const zend_llist_element **s TSRMLS_DC)
252 {
253 return strcmp( ((zend_extension *)(*f)->data)->name,
254 ((zend_extension *)(*s)->data)->name);
255 }
256
257 static void print_extensions(TSRMLS_D)
258 {
259 zend_llist sorted_exts;
260
261 zend_llist_copy(&sorted_exts, &zend_extensions);
262 sorted_exts.dtor = NULL;
263 zend_llist_sort(&sorted_exts, extension_name_cmp TSRMLS_CC);
264 zend_llist_apply_with_argument(&sorted_exts, (llist_apply_with_arg_func_t) print_extension_info, NULL TSRMLS_CC);
265 zend_llist_destroy(&sorted_exts);
266 }
267
268 #ifndef STDOUT_FILENO
269 #define STDOUT_FILENO 1
270 #endif
271
272 static inline size_t sapi_cgi_single_write(const char *str, uint str_length TSRMLS_DC)
273 {
274 #ifdef PHP_WRITE_STDOUT
275 long ret;
276
277 ret = write(STDOUT_FILENO, str, str_length);
278 if (ret <= 0) return 0;
279 return ret;
280 #else
281 size_t ret;
282
283 ret = fwrite(str, 1, MIN(str_length, 16384), stdout);
284 return ret;
285 #endif
286 }
287
288 static int sapi_cgi_ub_write(const char *str, uint str_length TSRMLS_DC)
289 {
290 const char *ptr = str;
291 uint remaining = str_length;
292 size_t ret;
293
294 while (remaining > 0) {
295 ret = sapi_cgi_single_write(ptr, remaining TSRMLS_CC);
296 if (!ret) {
297 php_handle_aborted_connection();
298 return str_length - remaining;
299 }
300 ptr += ret;
301 remaining -= ret;
302 }
303
304 return str_length;
305 }
306
307 static int sapi_fcgi_ub_write(const char *str, uint str_length TSRMLS_DC)
308 {
309 const char *ptr = str;
310 uint remaining = str_length;
311 fcgi_request *request = (fcgi_request*) SG(server_context);
312
313 while (remaining > 0) {
314 long ret = fcgi_write(request, FCGI_STDOUT, ptr, remaining);
315
316 if (ret <= 0) {
317 php_handle_aborted_connection();
318 return str_length - remaining;
319 }
320 ptr += ret;
321 remaining -= ret;
322 }
323
324 return str_length;
325 }
326
327 static void sapi_cgi_flush(void *server_context)
328 {
329 if (fflush(stdout) == EOF) {
330 php_handle_aborted_connection();
331 }
332 }
333
334 static void sapi_fcgi_flush(void *server_context)
335 {
336 fcgi_request *request = (fcgi_request*) server_context;
337
338 if (
339 #ifndef PHP_WIN32
340 !parent &&
341 #endif
342 request && !fcgi_flush(request, 0)) {
343
344 php_handle_aborted_connection();
345 }
346 }
347
348 #define SAPI_CGI_MAX_HEADER_LENGTH 1024
349
350 typedef struct _http_error {
351 int code;
352 const char* msg;
353 } http_error;
354
355 static const http_error http_error_codes[] = {
356 {100, "Continue"},
357 {101, "Switching Protocols"},
358 {200, "OK"},
359 {201, "Created"},
360 {202, "Accepted"},
361 {203, "Non-Authoritative Information"},
362 {204, "No Content"},
363 {205, "Reset Content"},
364 {206, "Partial Content"},
365 {300, "Multiple Choices"},
366 {301, "Moved Permanently"},
367 {302, "Moved Temporarily"},
368 {303, "See Other"},
369 {304, "Not Modified"},
370 {305, "Use Proxy"},
371 {400, "Bad Request"},
372 {401, "Unauthorized"},
373 {402, "Payment Required"},
374 {403, "Forbidden"},
375 {404, "Not Found"},
376 {405, "Method Not Allowed"},
377 {406, "Not Acceptable"},
378 {407, "Proxy Authentication Required"},
379 {408, "Request Time-out"},
380 {409, "Conflict"},
381 {410, "Gone"},
382 {411, "Length Required"},
383 {412, "Precondition Failed"},
384 {413, "Request Entity Too Large"},
385 {414, "Request-URI Too Large"},
386 {415, "Unsupported Media Type"},
387 {428, "Precondition Required"},
388 {429, "Too Many Requests"},
389 {431, "Request Header Fields Too Large"},
390 {451, "Unavailable For Legal Reasons"},
391 {500, "Internal Server Error"},
392 {501, "Not Implemented"},
393 {502, "Bad Gateway"},
394 {503, "Service Unavailable"},
395 {504, "Gateway Time-out"},
396 {505, "HTTP Version not supported"},
397 {511, "Network Authentication Required"},
398 {0, NULL}
399 };
400
401 static int sapi_cgi_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC)
402 {
403 char buf[SAPI_CGI_MAX_HEADER_LENGTH];
404 sapi_header_struct *h;
405 zend_llist_position pos;
406 zend_bool ignore_status = 0;
407 int response_status = SG(sapi_headers).http_response_code;
408
409 if (SG(request_info).no_headers == 1) {
410 return SAPI_HEADER_SENT_SUCCESSFULLY;
411 }
412
413 if (CGIG(nph) || SG(sapi_headers).http_response_code != 200)
414 {
415 int len;
416 zend_bool has_status = 0;
417
418 if (CGIG(rfc2616_headers) && SG(sapi_headers).http_status_line) {
419 char *s;
420 len = slprintf(buf, SAPI_CGI_MAX_HEADER_LENGTH, "%s\r\n", SG(sapi_headers).http_status_line);
421 if ((s = strchr(SG(sapi_headers).http_status_line, ' '))) {
422 response_status = atoi((s + 1));
423 }
424
425 if (len > SAPI_CGI_MAX_HEADER_LENGTH) {
426 len = SAPI_CGI_MAX_HEADER_LENGTH;
427 }
428
429 } else {
430 char *s;
431
432 if (SG(sapi_headers).http_status_line &&
433 (s = strchr(SG(sapi_headers).http_status_line, ' ')) != 0 &&
434 (s - SG(sapi_headers).http_status_line) >= 5 &&
435 strncasecmp(SG(sapi_headers).http_status_line, "HTTP/", 5) == 0
436 ) {
437 len = slprintf(buf, sizeof(buf), "Status:%s\r\n", s);
438 response_status = atoi((s + 1));
439 } else {
440 h = (sapi_header_struct*)zend_llist_get_first_ex(&sapi_headers->headers, &pos);
441 while (h) {
442 if (h->header_len > sizeof("Status:")-1 &&
443 strncasecmp(h->header, "Status:", sizeof("Status:")-1) == 0
444 ) {
445 has_status = 1;
446 break;
447 }
448 h = (sapi_header_struct*)zend_llist_get_next_ex(&sapi_headers->headers, &pos);
449 }
450 if (!has_status) {
451 http_error *err = (http_error*)http_error_codes;
452
453 while (err->code != 0) {
454 if (err->code == SG(sapi_headers).http_response_code) {
455 break;
456 }
457 err++;
458 }
459 if (err->msg) {
460 len = slprintf(buf, sizeof(buf), "Status: %d %s\r\n", SG(sapi_headers).http_response_code, err->msg);
461 } else {
462 len = slprintf(buf, sizeof(buf), "Status: %d\r\n", SG(sapi_headers).http_response_code);
463 }
464 }
465 }
466 }
467
468 if (!has_status) {
469 PHPWRITE_H(buf, len);
470 ignore_status = 1;
471 }
472 }
473
474 h = (sapi_header_struct*)zend_llist_get_first_ex(&sapi_headers->headers, &pos);
475 while (h) {
476
477 if (h->header_len) {
478 if (h->header_len > sizeof("Status:")-1 &&
479 strncasecmp(h->header, "Status:", sizeof("Status:")-1) == 0
480 ) {
481 if (!ignore_status) {
482 ignore_status = 1;
483 PHPWRITE_H(h->header, h->header_len);
484 PHPWRITE_H("\r\n", 2);
485 }
486 } else if (response_status == 304 && h->header_len > sizeof("Content-Type:")-1 &&
487 strncasecmp(h->header, "Content-Type:", sizeof("Content-Type:")-1) == 0
488 ) {
489 h = (sapi_header_struct*)zend_llist_get_next_ex(&sapi_headers->headers, &pos);
490 continue;
491 } else {
492 PHPWRITE_H(h->header, h->header_len);
493 PHPWRITE_H("\r\n", 2);
494 }
495 }
496 h = (sapi_header_struct*)zend_llist_get_next_ex(&sapi_headers->headers, &pos);
497 }
498 PHPWRITE_H("\r\n", 2);
499
500 return SAPI_HEADER_SENT_SUCCESSFULLY;
501 }
502
503 #ifndef STDIN_FILENO
504 # define STDIN_FILENO 0
505 #endif
506
507 static int sapi_cgi_read_post(char *buffer, uint count_bytes TSRMLS_DC)
508 {
509 uint read_bytes = 0;
510 int tmp_read_bytes;
511
512 count_bytes = MIN(count_bytes, SG(request_info).content_length - SG(read_post_bytes));
513 while (read_bytes < count_bytes) {
514 tmp_read_bytes = read(STDIN_FILENO, buffer + read_bytes, count_bytes - read_bytes);
515 if (tmp_read_bytes <= 0) {
516 break;
517 }
518 read_bytes += tmp_read_bytes;
519 }
520 return read_bytes;
521 }
522
523 static int sapi_fcgi_read_post(char *buffer, uint count_bytes TSRMLS_DC)
524 {
525 uint read_bytes = 0;
526 int tmp_read_bytes;
527 fcgi_request *request = (fcgi_request*) SG(server_context);
528 size_t remaining = SG(request_info).content_length - SG(read_post_bytes);
529
530 if (remaining < count_bytes) {
531 count_bytes = remaining;
532 }
533 while (read_bytes < count_bytes) {
534 tmp_read_bytes = fcgi_read(request, buffer + read_bytes, count_bytes - read_bytes);
535 if (tmp_read_bytes <= 0) {
536 break;
537 }
538 read_bytes += tmp_read_bytes;
539 }
540 return read_bytes;
541 }
542
543 static char *sapi_cgi_getenv(char *name, size_t name_len TSRMLS_DC)
544 {
545 return getenv(name);
546 }
547
548 static char *sapi_fcgi_getenv(char *name, size_t name_len TSRMLS_DC)
549 {
550
551
552
553
554 fcgi_request *request = (fcgi_request*) SG(server_context);
555 char *ret = fcgi_getenv(request, name, name_len);
556
557 if (ret) return ret;
558
559
560 return getenv(name);
561 }
562
563 static char *_sapi_cgi_putenv(char *name, int name_len, char *value)
564 {
565 #if !HAVE_SETENV || !HAVE_UNSETENV
566 int len;
567 char *buf;
568 #endif
569
570 #if HAVE_SETENV
571 if (value) {
572 setenv(name, value, 1);
573 }
574 #endif
575 #if HAVE_UNSETENV
576 if (!value) {
577 unsetenv(name);
578 }
579 #endif
580
581 #if !HAVE_SETENV || !HAVE_UNSETENV
582
583
584
585
586
587 len = name_len + (value ? strlen(value) : 0) + sizeof("=") + 2;
588 buf = (char *) malloc(len);
589 if (buf == NULL) {
590 return getenv(name);
591 }
592 #endif
593 #if !HAVE_SETENV
594 if (value) {
595 len = slprintf(buf, len - 1, "%s=%s", name, value);
596 putenv(buf);
597 }
598 #endif
599 #if !HAVE_UNSETENV
600 if (!value) {
601 len = slprintf(buf, len - 1, "%s=", name);
602 putenv(buf);
603 }
604 #endif
605 return getenv(name);
606 }
607
608 static char *sapi_cgi_read_cookies(TSRMLS_D)
609 {
610 return getenv("HTTP_COOKIE");
611 }
612
613 static char *sapi_fcgi_read_cookies(TSRMLS_D)
614 {
615 fcgi_request *request = (fcgi_request*) SG(server_context);
616
617 return FCGI_GETENV(request, "HTTP_COOKIE");
618 }
619
620 static void cgi_php_load_env_var(char *var, unsigned int var_len, char *val, unsigned int val_len, void *arg TSRMLS_DC)
621 {
622 zval *array_ptr = (zval*)arg;
623 int filter_arg = (array_ptr == PG(http_globals)[TRACK_VARS_ENV])?PARSE_ENV:PARSE_SERVER;
624 unsigned int new_val_len;
625
626 if (sapi_module.input_filter(filter_arg, var, &val, strlen(val), &new_val_len TSRMLS_CC)) {
627 php_register_variable_safe(var, val, new_val_len, array_ptr TSRMLS_CC);
628 }
629 }
630
631 static void cgi_php_import_environment_variables(zval *array_ptr TSRMLS_DC)
632 {
633 if (PG(http_globals)[TRACK_VARS_ENV] &&
634 array_ptr != PG(http_globals)[TRACK_VARS_ENV] &&
635 Z_TYPE_P(PG(http_globals)[TRACK_VARS_ENV]) == IS_ARRAY &&
636 zend_hash_num_elements(Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_ENV])) > 0
637 ) {
638 zval_dtor(array_ptr);
639 *array_ptr = *PG(http_globals)[TRACK_VARS_ENV];
640 INIT_PZVAL(array_ptr);
641 zval_copy_ctor(array_ptr);
642 return;
643 } else if (PG(http_globals)[TRACK_VARS_SERVER] &&
644 array_ptr != PG(http_globals)[TRACK_VARS_SERVER] &&
645 Z_TYPE_P(PG(http_globals)[TRACK_VARS_SERVER]) == IS_ARRAY &&
646 zend_hash_num_elements(Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_SERVER])) > 0
647 ) {
648 zval_dtor(array_ptr);
649 *array_ptr = *PG(http_globals)[TRACK_VARS_SERVER];
650 INIT_PZVAL(array_ptr);
651 zval_copy_ctor(array_ptr);
652 return;
653 }
654
655
656 php_php_import_environment_variables(array_ptr TSRMLS_CC);
657
658 if (fcgi_is_fastcgi()) {
659 fcgi_request *request = (fcgi_request*) SG(server_context);
660 fcgi_loadenv(request, cgi_php_load_env_var, array_ptr TSRMLS_CC);
661 }
662 }
663
664 static void sapi_cgi_register_variables(zval *track_vars_array TSRMLS_DC)
665 {
666 unsigned int php_self_len;
667 char *php_self;
668
669
670
671
672 php_import_environment_variables(track_vars_array TSRMLS_CC);
673
674 if (CGIG(fix_pathinfo)) {
675 char *script_name = SG(request_info).request_uri;
676 char *path_info;
677 int free_php_self;
678 ALLOCA_FLAG(use_heap)
679
680 if (fcgi_is_fastcgi()) {
681 fcgi_request *request = (fcgi_request*) SG(server_context);
682
683 path_info = FCGI_GETENV(request, "PATH_INFO");
684 } else {
685 path_info = getenv("PATH_INFO");
686 }
687
688 if (path_info) {
689 unsigned int path_info_len = strlen(path_info);
690
691 if (script_name) {
692 unsigned int script_name_len = strlen(script_name);
693
694 php_self_len = script_name_len + path_info_len;
695 php_self = do_alloca(php_self_len + 1, use_heap);
696 memcpy(php_self, script_name, script_name_len + 1);
697 memcpy(php_self + script_name_len, path_info, path_info_len + 1);
698 free_php_self = 1;
699 } else {
700 php_self = path_info;
701 php_self_len = path_info_len;
702 free_php_self = 0;
703 }
704 } else if (script_name) {
705 php_self = script_name;
706 php_self_len = strlen(script_name);
707 free_php_self = 0;
708 } else {
709 php_self = "";
710 php_self_len = 0;
711 free_php_self = 0;
712 }
713
714
715 if (sapi_module.input_filter(PARSE_SERVER, "PHP_SELF", &php_self, php_self_len, &php_self_len TSRMLS_CC)) {
716 php_register_variable_safe("PHP_SELF", php_self, php_self_len, track_vars_array TSRMLS_CC);
717 }
718 if (free_php_self) {
719 free_alloca(php_self, use_heap);
720 }
721 } else {
722 php_self = SG(request_info).request_uri ? SG(request_info).request_uri : "";
723 php_self_len = strlen(php_self);
724 if (sapi_module.input_filter(PARSE_SERVER, "PHP_SELF", &php_self, php_self_len, &php_self_len TSRMLS_CC)) {
725 php_register_variable_safe("PHP_SELF", php_self, php_self_len, track_vars_array TSRMLS_CC);
726 }
727 }
728 }
729
730 static void sapi_cgi_log_message(char *message TSRMLS_DC)
731 {
732 if (fcgi_is_fastcgi() && CGIG(fcgi_logging)) {
733 fcgi_request *request;
734
735 request = (fcgi_request*) SG(server_context);
736 if (request) {
737 int ret, len = strlen(message);
738 char *buf = malloc(len+2);
739
740 memcpy(buf, message, len);
741 memcpy(buf + len, "\n", sizeof("\n"));
742 ret = fcgi_write(request, FCGI_STDERR, buf, len + 1);
743 free(buf);
744 if (ret < 0) {
745 php_handle_aborted_connection();
746 }
747 } else {
748 fprintf(stderr, "%s\n", message);
749 }
750
751 } else {
752 fprintf(stderr, "%s\n", message);
753 }
754 }
755
756
757
758 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)
759 {
760 char *ptr;
761 user_config_cache_entry *new_entry, *entry;
762 time_t request_time = sapi_get_request_time(TSRMLS_C);
763
764
765 if (zend_hash_find(&CGIG(user_config_cache), path, path_len + 1, (void **) &entry) == FAILURE) {
766 new_entry = pemalloc(sizeof(user_config_cache_entry), 1);
767 new_entry->expires = 0;
768 new_entry->user_config = (HashTable *) pemalloc(sizeof(HashTable), 1);
769 zend_hash_init(new_entry->user_config, 0, NULL, (dtor_func_t) config_zval_dtor, 1);
770 zend_hash_update(&CGIG(user_config_cache), path, path_len + 1, new_entry, sizeof(user_config_cache_entry), (void **) &entry);
771 free(new_entry);
772 }
773
774
775 if (request_time > entry->expires) {
776 char *real_path = NULL;
777 int real_path_len;
778 char *s1, *s2;
779 int s_len;
780
781
782 zend_hash_clean(entry->user_config);
783
784 if (!IS_ABSOLUTE_PATH(path, path_len)) {
785 real_path = tsrm_realpath(path, NULL TSRMLS_CC);
786 if (real_path == NULL) {
787 return;
788 }
789 real_path_len = strlen(real_path);
790 path = real_path;
791 path_len = real_path_len;
792 }
793
794 if (path_len > doc_root_len) {
795 s1 = (char *) doc_root;
796 s2 = path;
797 s_len = doc_root_len;
798 } else {
799 s1 = path;
800 s2 = (char *) doc_root;
801 s_len = path_len;
802 }
803
804
805
806
807
808 #ifdef PHP_WIN32
809 if (strnicmp(s1, s2, s_len) == 0) {
810 #else
811 if (strncmp(s1, s2, s_len) == 0) {
812 #endif
813 ptr = s2 + start;
814 while ((ptr = strchr(ptr, DEFAULT_SLASH)) != NULL) {
815 *ptr = 0;
816 php_parse_user_ini_file(path, PG(user_ini_filename), entry->user_config TSRMLS_CC);
817 *ptr = '/';
818 ptr++;
819 }
820 } else {
821 php_parse_user_ini_file(path, PG(user_ini_filename), entry->user_config TSRMLS_CC);
822 }
823
824 if (real_path) {
825 efree(real_path);
826 }
827 entry->expires = request_time + PG(user_ini_cache_ttl);
828 }
829
830
831 php_ini_activate_config(entry->user_config, PHP_INI_PERDIR, PHP_INI_STAGE_HTACCESS TSRMLS_CC);
832 }
833
834
835 static int sapi_cgi_activate(TSRMLS_D)
836 {
837 char *path, *doc_root, *server_name;
838 uint path_len, doc_root_len, server_name_len;
839
840
841 if (!SG(request_info).path_translated) {
842 return FAILURE;
843 }
844
845 if (php_ini_has_per_host_config()) {
846
847 if (fcgi_is_fastcgi()) {
848 fcgi_request *request = (fcgi_request*) SG(server_context);
849
850 server_name = FCGI_GETENV(request, "SERVER_NAME");
851 } else {
852 server_name = getenv("SERVER_NAME");
853 }
854
855 if (server_name) {
856 server_name_len = strlen(server_name);
857 server_name = estrndup(server_name, server_name_len);
858 zend_str_tolower(server_name, server_name_len);
859 php_ini_activate_per_host_config(server_name, server_name_len + 1 TSRMLS_CC);
860 efree(server_name);
861 }
862 }
863
864 if (php_ini_has_per_dir_config() ||
865 (PG(user_ini_filename) && *PG(user_ini_filename))
866 ) {
867
868 path_len = strlen(SG(request_info).path_translated);
869
870
871 if (!IS_SLASH(SG(request_info).path_translated[path_len])) {
872 path = emalloc(path_len + 2);
873 memcpy(path, SG(request_info).path_translated, path_len + 1);
874 path_len = zend_dirname(path, path_len);
875 path[path_len++] = DEFAULT_SLASH;
876 } else {
877 path = estrndup(SG(request_info).path_translated, path_len);
878 path_len = zend_dirname(path, path_len);
879 }
880 path[path_len] = 0;
881
882
883 php_ini_activate_per_dir_config(path, path_len TSRMLS_CC);
884
885
886 if (PG(user_ini_filename) && *PG(user_ini_filename)) {
887 if (fcgi_is_fastcgi()) {
888 fcgi_request *request = (fcgi_request*) SG(server_context);
889
890 doc_root = FCGI_GETENV(request, "DOCUMENT_ROOT");
891 } else {
892 doc_root = getenv("DOCUMENT_ROOT");
893 }
894
895 if (doc_root) {
896 doc_root_len = strlen(doc_root);
897 if (doc_root_len > 0 && IS_SLASH(doc_root[doc_root_len - 1])) {
898 --doc_root_len;
899 }
900 #ifdef PHP_WIN32
901
902 doc_root = estrndup(doc_root, doc_root_len);
903 zend_str_tolower(doc_root, doc_root_len);
904 #endif
905 php_cgi_ini_activate_user_config(path, path_len, doc_root, doc_root_len, doc_root_len - 1 TSRMLS_CC);
906
907 #ifdef PHP_WIN32
908 efree(doc_root);
909 #endif
910 }
911 }
912
913 efree(path);
914 }
915
916 return SUCCESS;
917 }
918
919 static int sapi_cgi_deactivate(TSRMLS_D)
920 {
921
922
923
924
925 if (SG(sapi_started)) {
926 if (fcgi_is_fastcgi()) {
927 if (
928 #ifndef PHP_WIN32
929 !parent &&
930 #endif
931 !fcgi_finish_request((fcgi_request*)SG(server_context), 0)) {
932 php_handle_aborted_connection();
933 }
934 } else {
935 sapi_cgi_flush(SG(server_context));
936 }
937 }
938 return SUCCESS;
939 }
940
941 static int php_cgi_startup(sapi_module_struct *sapi_module)
942 {
943 if (php_module_startup(sapi_module, &cgi_module_entry, 1) == FAILURE) {
944 return FAILURE;
945 }
946 return SUCCESS;
947 }
948
949
950
951 static sapi_module_struct cgi_sapi_module = {
952 "cgi-fcgi",
953 "CGI/FastCGI",
954
955 php_cgi_startup,
956 php_module_shutdown_wrapper,
957
958 sapi_cgi_activate,
959 sapi_cgi_deactivate,
960
961 sapi_cgi_ub_write,
962 sapi_cgi_flush,
963 NULL,
964 sapi_cgi_getenv,
965
966 php_error,
967
968 NULL,
969 sapi_cgi_send_headers,
970 NULL,
971
972 sapi_cgi_read_post,
973 sapi_cgi_read_cookies,
974
975 sapi_cgi_register_variables,
976 sapi_cgi_log_message,
977 NULL,
978 NULL,
979
980 STANDARD_SAPI_MODULE_PROPERTIES
981 };
982
983
984
985 ZEND_BEGIN_ARG_INFO(arginfo_dl, 0)
986 ZEND_ARG_INFO(0, extension_filename)
987 ZEND_END_ARG_INFO()
988
989
990 static const zend_function_entry additional_functions[] = {
991 ZEND_FE(dl, arginfo_dl)
992 {NULL, NULL, NULL}
993 };
994
995
996
997 static void php_cgi_usage(char *argv0)
998 {
999 char *prog;
1000
1001 prog = strrchr(argv0, '/');
1002 if (prog) {
1003 prog++;
1004 } else {
1005 prog = "php";
1006 }
1007
1008 php_printf( "Usage: %s [-q] [-h] [-s] [-v] [-i] [-f <file>]\n"
1009 " %s <file> [args...]\n"
1010 " -a Run interactively\n"
1011 " -b <address:port>|<port> Bind Path for external FASTCGI Server mode\n"
1012 " -C Do not chdir to the script's directory\n"
1013 " -c <path>|<file> Look for php.ini file in this directory\n"
1014 " -n No php.ini file will be used\n"
1015 " -d foo[=bar] Define INI entry foo with value 'bar'\n"
1016 " -e Generate extended information for debugger/profiler\n"
1017 " -f <file> Parse <file>. Implies `-q'\n"
1018 " -h This help\n"
1019 " -i PHP information\n"
1020 " -l Syntax check only (lint)\n"
1021 " -m Show compiled in modules\n"
1022 " -q Quiet-mode. Suppress HTTP Header output.\n"
1023 " -s Display colour syntax highlighted source.\n"
1024 " -v Version number\n"
1025 " -w Display source with stripped comments and whitespace.\n"
1026 " -z <file> Load Zend extension <file>.\n"
1027 " -T <count> Measure execution time of script repeated <count> times.\n",
1028 prog, prog);
1029 }
1030
1031
1032
1033
1034
1035
1036
1037 static int is_valid_path(const char *path)
1038 {
1039 const char *p = path;
1040
1041 if (UNEXPECTED(!p)) {
1042 return 0;
1043 }
1044 if (UNEXPECTED(*p == '.') && *(p+1) == '.' && (!*(p+2) || IS_SLASH(*(p+2)))) {
1045 return 0;
1046 }
1047 while (*p) {
1048 if (IS_SLASH(*p)) {
1049 p++;
1050 if (UNEXPECTED(*p == '.')) {
1051 p++;
1052 if (UNEXPECTED(*p == '.')) {
1053 p++;
1054 if (UNEXPECTED(!*p) || UNEXPECTED(IS_SLASH(*p))) {
1055 return 0;
1056 }
1057 }
1058 }
1059 }
1060 p++;
1061 }
1062 return 1;
1063 }
1064
1065
1066 #define CGI_GETENV(name) \
1067 ((request) ? \
1068 FCGI_GETENV(request, name) : \
1069 getenv(name))
1070
1071 #define CGI_PUTENV(name, value) \
1072 ((request) ? \
1073 FCGI_PUTENV(request, name, value) : \
1074 _sapi_cgi_putenv(name, sizeof(name)-1, value))
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142 static void init_request_info(fcgi_request *request TSRMLS_DC)
1143 {
1144 char *env_script_filename = CGI_GETENV("SCRIPT_FILENAME");
1145 char *env_path_translated = CGI_GETENV("PATH_TRANSLATED");
1146 char *script_path_translated = env_script_filename;
1147
1148
1149
1150
1151 if (!script_path_translated && env_path_translated) {
1152 script_path_translated = env_path_translated;
1153 }
1154
1155
1156 SG(request_info).path_translated = NULL;
1157 SG(request_info).request_method = NULL;
1158 SG(request_info).proto_num = 1000;
1159 SG(request_info).query_string = NULL;
1160 SG(request_info).request_uri = NULL;
1161 SG(request_info).content_type = NULL;
1162 SG(request_info).content_length = 0;
1163 SG(sapi_headers).http_response_code = 200;
1164
1165
1166
1167
1168
1169 if (script_path_translated) {
1170 const char *auth;
1171 char *content_length = CGI_GETENV("CONTENT_LENGTH");
1172 char *content_type = CGI_GETENV("CONTENT_TYPE");
1173 char *env_path_info = CGI_GETENV("PATH_INFO");
1174 char *env_script_name = CGI_GETENV("SCRIPT_NAME");
1175
1176 #ifdef PHP_WIN32
1177
1178 char *env_server_software = CGI_GETENV("SERVER_SOFTWARE");
1179
1180 if (env_server_software &&
1181 env_script_name &&
1182 env_path_info &&
1183 strncmp(env_server_software, "Microsoft-IIS", sizeof("Microsoft-IIS")-1) == 0 &&
1184 strncmp(env_path_info, env_script_name, strlen(env_script_name)) == 0
1185 ) {
1186 env_path_info = CGI_PUTENV("ORIG_PATH_INFO", env_path_info);
1187 env_path_info += strlen(env_script_name);
1188 if (*env_path_info == 0) {
1189 env_path_info = NULL;
1190 }
1191 env_path_info = CGI_PUTENV("PATH_INFO", env_path_info);
1192 }
1193 #endif
1194
1195 if (CGIG(fix_pathinfo)) {
1196 struct stat st;
1197 char *real_path = NULL;
1198 char *env_redirect_url = CGI_GETENV("REDIRECT_URL");
1199 char *env_document_root = CGI_GETENV("DOCUMENT_ROOT");
1200 char *orig_path_translated = env_path_translated;
1201 char *orig_path_info = env_path_info;
1202 char *orig_script_name = env_script_name;
1203 char *orig_script_filename = env_script_filename;
1204 int script_path_translated_len;
1205
1206 if (!env_document_root && PG(doc_root)) {
1207 env_document_root = CGI_PUTENV("DOCUMENT_ROOT", PG(doc_root));
1208
1209 TRANSLATE_SLASHES(env_document_root);
1210 }
1211
1212 if (env_path_translated != NULL && env_redirect_url != NULL &&
1213 env_path_translated != script_path_translated &&
1214 strcmp(env_path_translated, script_path_translated) != 0) {
1215
1216
1217
1218
1219
1220 script_path_translated = env_path_translated;
1221
1222 env_script_name = env_redirect_url;
1223 }
1224
1225 #ifdef __riscos__
1226
1227 __riscosify_control |= __RISCOSIFY_DONT_CHECK_DIR;
1228 script_path_translated = __unixify(script_path_translated, 0, NULL, 1, 0);
1229 #endif
1230
1231
1232
1233
1234
1235
1236 if (script_path_translated &&
1237 (script_path_translated_len = strlen(script_path_translated)) > 0 &&
1238 (script_path_translated[script_path_translated_len-1] == '/' ||
1239 #ifdef PHP_WIN32
1240 script_path_translated[script_path_translated_len-1] == '\\' ||
1241 #endif
1242 (real_path = tsrm_realpath(script_path_translated, NULL TSRMLS_CC)) == NULL)
1243 ) {
1244 char *pt = estrndup(script_path_translated, script_path_translated_len);
1245 int len = script_path_translated_len;
1246 char *ptr;
1247
1248 while ((ptr = strrchr(pt, '/')) || (ptr = strrchr(pt, '\\'))) {
1249 *ptr = 0;
1250 if (stat(pt, &st) == 0 && S_ISREG(st.st_mode)) {
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266 int slen = len - strlen(pt);
1267 int pilen = env_path_info ? strlen(env_path_info) : 0;
1268 char *path_info = env_path_info ? env_path_info + pilen - slen : NULL;
1269
1270 if (orig_path_info != path_info) {
1271 if (orig_path_info) {
1272 char old;
1273
1274 CGI_PUTENV("ORIG_PATH_INFO", orig_path_info);
1275 old = path_info[0];
1276 path_info[0] = 0;
1277 if (!orig_script_name ||
1278 strcmp(orig_script_name, env_path_info) != 0) {
1279 if (orig_script_name) {
1280 CGI_PUTENV("ORIG_SCRIPT_NAME", orig_script_name);
1281 }
1282 SG(request_info).request_uri = CGI_PUTENV("SCRIPT_NAME", env_path_info);
1283 } else {
1284 SG(request_info).request_uri = orig_script_name;
1285 }
1286 path_info[0] = old;
1287 }
1288 env_path_info = CGI_PUTENV("PATH_INFO", path_info);
1289 }
1290 if (!orig_script_filename ||
1291 strcmp(orig_script_filename, pt) != 0) {
1292 if (orig_script_filename) {
1293 CGI_PUTENV("ORIG_SCRIPT_FILENAME", orig_script_filename);
1294 }
1295 script_path_translated = CGI_PUTENV("SCRIPT_FILENAME", pt);
1296 }
1297 TRANSLATE_SLASHES(pt);
1298
1299
1300
1301
1302 if (env_document_root) {
1303 int l = strlen(env_document_root);
1304 int path_translated_len = 0;
1305 char *path_translated = NULL;
1306
1307 if (l && env_document_root[l - 1] == '/') {
1308 --l;
1309 }
1310
1311
1312
1313
1314
1315
1316
1317 path_translated_len = l + (env_path_info ? strlen(env_path_info) : 0);
1318 path_translated = (char *) emalloc(path_translated_len + 1);
1319 memcpy(path_translated, env_document_root, l);
1320 if (env_path_info) {
1321 memcpy(path_translated + l, env_path_info, (path_translated_len - l));
1322 }
1323 path_translated[path_translated_len] = '\0';
1324 if (orig_path_translated) {
1325 CGI_PUTENV("ORIG_PATH_TRANSLATED", orig_path_translated);
1326 }
1327 env_path_translated = CGI_PUTENV("PATH_TRANSLATED", path_translated);
1328 efree(path_translated);
1329 } else if ( env_script_name &&
1330 strstr(pt, env_script_name)
1331 ) {
1332
1333 int ptlen = strlen(pt) - strlen(env_script_name);
1334 int path_translated_len = ptlen + (env_path_info ? strlen(env_path_info) : 0);
1335 char *path_translated = NULL;
1336
1337 path_translated = (char *) emalloc(path_translated_len + 1);
1338 memcpy(path_translated, pt, ptlen);
1339 if (env_path_info) {
1340 memcpy(path_translated + ptlen, env_path_info, path_translated_len - ptlen);
1341 }
1342 path_translated[path_translated_len] = '\0';
1343 if (orig_path_translated) {
1344 CGI_PUTENV("ORIG_PATH_TRANSLATED", orig_path_translated);
1345 }
1346 env_path_translated = CGI_PUTENV("PATH_TRANSLATED", path_translated);
1347 efree(path_translated);
1348 }
1349 break;
1350 }
1351 }
1352 if (!ptr) {
1353
1354
1355
1356
1357
1358 if (orig_script_filename) {
1359 CGI_PUTENV("ORIG_SCRIPT_FILENAME", orig_script_filename);
1360 }
1361 script_path_translated = CGI_PUTENV("SCRIPT_FILENAME", NULL);
1362 SG(sapi_headers).http_response_code = 404;
1363 }
1364 if (!SG(request_info).request_uri) {
1365 if (!orig_script_name ||
1366 strcmp(orig_script_name, env_script_name) != 0) {
1367 if (orig_script_name) {
1368 CGI_PUTENV("ORIG_SCRIPT_NAME", orig_script_name);
1369 }
1370 SG(request_info).request_uri = CGI_PUTENV("SCRIPT_NAME", env_script_name);
1371 } else {
1372 SG(request_info).request_uri = orig_script_name;
1373 }
1374 }
1375 if (pt) {
1376 efree(pt);
1377 }
1378 } else {
1379
1380 if (!orig_script_filename ||
1381 (script_path_translated != orig_script_filename &&
1382 strcmp(script_path_translated, orig_script_filename) != 0)) {
1383 if (orig_script_filename) {
1384 CGI_PUTENV("ORIG_SCRIPT_FILENAME", orig_script_filename);
1385 }
1386 script_path_translated = CGI_PUTENV("SCRIPT_FILENAME", script_path_translated);
1387 }
1388 if (env_redirect_url) {
1389 if (orig_path_info) {
1390 CGI_PUTENV("ORIG_PATH_INFO", orig_path_info);
1391 CGI_PUTENV("PATH_INFO", NULL);
1392 }
1393 if (orig_path_translated) {
1394 CGI_PUTENV("ORIG_PATH_TRANSLATED", orig_path_translated);
1395 CGI_PUTENV("PATH_TRANSLATED", NULL);
1396 }
1397 }
1398 if (env_script_name != orig_script_name) {
1399 if (orig_script_name) {
1400 CGI_PUTENV("ORIG_SCRIPT_NAME", orig_script_name);
1401 }
1402 SG(request_info).request_uri = CGI_PUTENV("SCRIPT_NAME", env_script_name);
1403 } else {
1404 SG(request_info).request_uri = env_script_name;
1405 }
1406 efree(real_path);
1407 }
1408 } else {
1409
1410 if (env_path_info) {
1411 SG(request_info).request_uri = env_path_info;
1412 } else {
1413 SG(request_info).request_uri = env_script_name;
1414 }
1415 if (!CGIG(discard_path) && env_path_translated) {
1416 script_path_translated = env_path_translated;
1417 }
1418 }
1419
1420 if (is_valid_path(script_path_translated)) {
1421 SG(request_info).path_translated = estrdup(script_path_translated);
1422 }
1423
1424 SG(request_info).request_method = CGI_GETENV("REQUEST_METHOD");
1425
1426 SG(request_info).query_string = CGI_GETENV("QUERY_STRING");
1427 SG(request_info).content_type = (content_type ? content_type : "" );
1428 SG(request_info).content_length = (content_length ? atol(content_length) : 0);
1429
1430
1431 auth = CGI_GETENV("HTTP_AUTHORIZATION");
1432 php_handle_auth_data(auth TSRMLS_CC);
1433 }
1434 }
1435
1436
1437 #ifndef PHP_WIN32
1438
1439
1440
1441 void fastcgi_cleanup(int signal)
1442 {
1443 #ifdef DEBUG_FASTCGI
1444 fprintf(stderr, "FastCGI shutdown, pid %d\n", getpid());
1445 #endif
1446
1447 sigaction(SIGTERM, &old_term, 0);
1448
1449
1450 kill(-pgroup, SIGTERM);
1451
1452 if (parent && parent_waiting) {
1453 exit_signal = 1;
1454 } else {
1455 exit(0);
1456 }
1457 }
1458 #endif
1459
1460 PHP_INI_BEGIN()
1461 STD_PHP_INI_ENTRY("cgi.rfc2616_headers", "0", PHP_INI_ALL, OnUpdateBool, rfc2616_headers, php_cgi_globals_struct, php_cgi_globals)
1462 STD_PHP_INI_ENTRY("cgi.nph", "0", PHP_INI_ALL, OnUpdateBool, nph, php_cgi_globals_struct, php_cgi_globals)
1463 STD_PHP_INI_ENTRY("cgi.check_shebang_line", "1", PHP_INI_SYSTEM, OnUpdateBool, check_shebang_line, php_cgi_globals_struct, php_cgi_globals)
1464 STD_PHP_INI_ENTRY("cgi.force_redirect", "1", PHP_INI_SYSTEM, OnUpdateBool, force_redirect, php_cgi_globals_struct, php_cgi_globals)
1465 STD_PHP_INI_ENTRY("cgi.redirect_status_env", NULL, PHP_INI_SYSTEM, OnUpdateString, redirect_status_env, php_cgi_globals_struct, php_cgi_globals)
1466 STD_PHP_INI_ENTRY("cgi.fix_pathinfo", "1", PHP_INI_SYSTEM, OnUpdateBool, fix_pathinfo, php_cgi_globals_struct, php_cgi_globals)
1467 STD_PHP_INI_ENTRY("cgi.discard_path", "0", PHP_INI_SYSTEM, OnUpdateBool, discard_path, php_cgi_globals_struct, php_cgi_globals)
1468 STD_PHP_INI_ENTRY("fastcgi.logging", "1", PHP_INI_SYSTEM, OnUpdateBool, fcgi_logging, php_cgi_globals_struct, php_cgi_globals)
1469 #ifdef PHP_WIN32
1470 STD_PHP_INI_ENTRY("fastcgi.impersonate", "0", PHP_INI_SYSTEM, OnUpdateBool, impersonate, php_cgi_globals_struct, php_cgi_globals)
1471 #endif
1472 PHP_INI_END()
1473
1474
1475
1476 static void php_cgi_globals_ctor(php_cgi_globals_struct *php_cgi_globals TSRMLS_DC)
1477 {
1478 php_cgi_globals->rfc2616_headers = 0;
1479 php_cgi_globals->nph = 0;
1480 php_cgi_globals->check_shebang_line = 1;
1481 php_cgi_globals->force_redirect = 1;
1482 php_cgi_globals->redirect_status_env = NULL;
1483 php_cgi_globals->fix_pathinfo = 1;
1484 php_cgi_globals->discard_path = 0;
1485 php_cgi_globals->fcgi_logging = 1;
1486 #ifdef PHP_WIN32
1487 php_cgi_globals->impersonate = 0;
1488 #endif
1489 zend_hash_init(&php_cgi_globals->user_config_cache, 0, NULL, (dtor_func_t) user_config_cache_entry_dtor, 1);
1490 }
1491
1492
1493
1494
1495 static PHP_MINIT_FUNCTION(cgi)
1496 {
1497 REGISTER_INI_ENTRIES();
1498 return SUCCESS;
1499 }
1500
1501
1502
1503
1504 static PHP_MSHUTDOWN_FUNCTION(cgi)
1505 {
1506 zend_hash_destroy(&CGIG(user_config_cache));
1507
1508 UNREGISTER_INI_ENTRIES();
1509 return SUCCESS;
1510 }
1511
1512
1513
1514
1515 static PHP_MINFO_FUNCTION(cgi)
1516 {
1517 DISPLAY_INI_ENTRIES();
1518 }
1519
1520
1521 PHP_FUNCTION(apache_child_terminate)
1522 {
1523 if (ZEND_NUM_ARGS() > 0) {
1524 WRONG_PARAM_COUNT;
1525 }
1526 if (fcgi_is_fastcgi()) {
1527 fcgi_terminate();
1528 }
1529 }
1530
1531
1532 static void add_request_header(char *var, unsigned int var_len, char *val, unsigned int val_len, void *arg TSRMLS_DC)
1533 {
1534 zval *return_value = (zval*)arg;
1535 char *str = NULL;
1536 char *p;
1537 ALLOCA_FLAG(use_heap)
1538
1539 if (var_len > 5 &&
1540 var[0] == 'H' &&
1541 var[1] == 'T' &&
1542 var[2] == 'T' &&
1543 var[3] == 'P' &&
1544 var[4] == '_') {
1545
1546 var_len -= 5;
1547 p = var + 5;
1548 var = str = do_alloca(var_len + 1, use_heap);
1549 *str++ = *p++;
1550 while (*p) {
1551 if (*p == '_') {
1552 *str++ = '-';
1553 p++;
1554 if (*p) {
1555 *str++ = *p++;
1556 }
1557 } else if (*p >= 'A' && *p <= 'Z') {
1558 *str++ = (*p++ - 'A' + 'a');
1559 } else {
1560 *str++ = *p++;
1561 }
1562 }
1563 *str = 0;
1564 } else if (var_len == sizeof("CONTENT_TYPE")-1 &&
1565 memcmp(var, "CONTENT_TYPE", sizeof("CONTENT_TYPE")-1) == 0) {
1566 var = "Content-Type";
1567 } else if (var_len == sizeof("CONTENT_LENGTH")-1 &&
1568 memcmp(var, "CONTENT_LENGTH", sizeof("CONTENT_LENGTH")-1) == 0) {
1569 var = "Content-Length";
1570 } else {
1571 return;
1572 }
1573 add_assoc_stringl_ex(return_value, var, var_len+1, val, val_len, 1);
1574 if (str) {
1575 free_alloca(var, use_heap);
1576 }
1577 }
1578
1579
1580 PHP_FUNCTION(apache_request_headers)
1581 {
1582 if (ZEND_NUM_ARGS() > 0) {
1583 WRONG_PARAM_COUNT;
1584 }
1585 array_init(return_value);
1586 if (fcgi_is_fastcgi()) {
1587 fcgi_request *request = (fcgi_request*) SG(server_context);
1588
1589 fcgi_loadenv(request, add_request_header, return_value TSRMLS_CC);
1590 } else {
1591 char buf[128];
1592 char **env, *p, *q, *var, *val, *t = buf;
1593 size_t alloc_size = sizeof(buf);
1594 unsigned long var_len;
1595
1596 for (env = environ; env != NULL && *env != NULL; env++) {
1597 val = strchr(*env, '=');
1598 if (!val) {
1599 continue;
1600 }
1601 var_len = val - *env;
1602 if (var_len >= alloc_size) {
1603 alloc_size = var_len + 64;
1604 t = (t == buf ? emalloc(alloc_size): erealloc(t, alloc_size));
1605 }
1606 var = *env;
1607 if (var_len > 5 &&
1608 var[0] == 'H' &&
1609 var[1] == 'T' &&
1610 var[2] == 'T' &&
1611 var[3] == 'P' &&
1612 var[4] == '_') {
1613
1614 var_len -= 5;
1615
1616 if (var_len >= alloc_size) {
1617 alloc_size = var_len + 64;
1618 t = (t == buf ? emalloc(alloc_size): erealloc(t, alloc_size));
1619 }
1620 p = var + 5;
1621
1622 var = q = t;
1623
1624 *q++ = *p++;
1625 while (*p) {
1626 if (*p == '=') {
1627
1628 break;
1629 } else if (*p == '_') {
1630 *q++ = '-';
1631 p++;
1632
1633 if (*p && *p!='=') {
1634 *q++ = *p++;
1635 }
1636 } else if (*p >= 'A' && *p <= 'Z') {
1637
1638 *q++ = (*p++ - 'A' + 'a');
1639 } else {
1640 *q++ = *p++;
1641 }
1642 }
1643 *q = 0;
1644 } else if (var_len == sizeof("CONTENT_TYPE")-1 &&
1645 memcmp(var, "CONTENT_TYPE", sizeof("CONTENT_TYPE")-1) == 0) {
1646 var = "Content-Type";
1647 } else if (var_len == sizeof("CONTENT_LENGTH")-1 &&
1648 memcmp(var, "CONTENT_LENGTH", sizeof("CONTENT_LENGTH")-1) == 0) {
1649 var = "Content-Length";
1650 } else {
1651 continue;
1652 }
1653 val++;
1654 add_assoc_string_ex(return_value, var, var_len+1, val, 1);
1655 }
1656 if (t != buf && t != NULL) {
1657 efree(t);
1658 }
1659 }
1660 }
1661
1662
1663 static void add_response_header(sapi_header_struct *h, zval *return_value TSRMLS_DC)
1664 {
1665 char *s, *p;
1666 int len = 0;
1667 ALLOCA_FLAG(use_heap)
1668
1669 if (h->header_len > 0) {
1670 p = strchr(h->header, ':');
1671 if (NULL != p) {
1672 len = p - h->header;
1673 }
1674 if (len > 0) {
1675 while (len > 0 && (h->header[len-1] == ' ' || h->header[len-1] == '\t')) {
1676 len--;
1677 }
1678 if (len) {
1679 s = do_alloca(len + 1, use_heap);
1680 memcpy(s, h->header, len);
1681 s[len] = 0;
1682 do {
1683 p++;
1684 } while (*p == ' ' || *p == '\t');
1685 add_assoc_stringl_ex(return_value, s, len+1, p, h->header_len - (p - h->header), 1);
1686 free_alloca(s, use_heap);
1687 }
1688 }
1689 }
1690 }
1691
1692
1693 PHP_FUNCTION(apache_response_headers)
1694 {
1695 if (zend_parse_parameters_none() == FAILURE) {
1696 return;
1697 }
1698
1699 if (!&SG(sapi_headers).headers) {
1700 RETURN_FALSE;
1701 }
1702 array_init(return_value);
1703 zend_llist_apply_with_argument(&SG(sapi_headers).headers, (llist_apply_with_arg_func_t)add_response_header, return_value TSRMLS_CC);
1704 }
1705
1706
1707 ZEND_BEGIN_ARG_INFO(arginfo_no_args, 0)
1708 ZEND_END_ARG_INFO()
1709
1710 const zend_function_entry cgi_functions[] = {
1711 PHP_FE(apache_child_terminate, arginfo_no_args)
1712 PHP_FE(apache_request_headers, arginfo_no_args)
1713 PHP_FE(apache_response_headers, arginfo_no_args)
1714 PHP_FALIAS(getallheaders, apache_request_headers, arginfo_no_args)
1715 {NULL, NULL, NULL}
1716 };
1717
1718 static zend_module_entry cgi_module_entry = {
1719 STANDARD_MODULE_HEADER,
1720 "cgi-fcgi",
1721 cgi_functions,
1722 PHP_MINIT(cgi),
1723 PHP_MSHUTDOWN(cgi),
1724 NULL,
1725 NULL,
1726 PHP_MINFO(cgi),
1727 NO_VERSION_YET,
1728 STANDARD_MODULE_PROPERTIES
1729 };
1730
1731
1732
1733 int main(int argc, char *argv[])
1734 {
1735 int free_query_string = 0;
1736 int exit_status = SUCCESS;
1737 int cgi = 0, c, i, len;
1738 zend_file_handle file_handle;
1739 char *s;
1740
1741
1742 int behavior = PHP_MODE_STANDARD;
1743 int no_headers = 0;
1744 int orig_optind = php_optind;
1745 char *orig_optarg = php_optarg;
1746 char *script_file = NULL;
1747 int ini_entries_len = 0;
1748
1749
1750 #ifdef ZTS
1751 void ***tsrm_ls;
1752 #endif
1753
1754 int max_requests = 500;
1755 int requests = 0;
1756 int fastcgi;
1757 char *bindpath = NULL;
1758 int fcgi_fd = 0;
1759 fcgi_request *request = NULL;
1760 int repeats = 1;
1761 int benchmark = 0;
1762 #if HAVE_GETTIMEOFDAY
1763 struct timeval start, end;
1764 #else
1765 time_t start, end;
1766 #endif
1767 #ifndef PHP_WIN32
1768 int status = 0;
1769 #endif
1770 char *query_string;
1771 char *decoded_query_string;
1772 int skip_getopt = 0;
1773
1774 #if 0 && defined(PHP_DEBUG)
1775
1776
1777 {
1778 char szMessage [256];
1779 wsprintf (szMessage, "Please attach a debugger to the process 0x%X [%d] (%s) and click OK", GetCurrentProcessId(), GetCurrentProcessId(), argv[0]);
1780 MessageBox(NULL, szMessage, "CGI Debug Time!", MB_OK|MB_SERVICE_NOTIFICATION);
1781 }
1782 #endif
1783
1784 #ifdef HAVE_SIGNAL_H
1785 #if defined(SIGPIPE) && defined(SIG_IGN)
1786 signal(SIGPIPE, SIG_IGN);
1787
1788
1789
1790
1791
1792 #endif
1793 #endif
1794
1795 #ifdef ZTS
1796 tsrm_startup(1, 1, 0, NULL);
1797 tsrm_ls = ts_resource(0);
1798 #endif
1799
1800 #ifdef ZTS
1801 ts_allocate_id(&php_cgi_globals_id, sizeof(php_cgi_globals_struct), (ts_allocate_ctor) php_cgi_globals_ctor, NULL);
1802 #else
1803 php_cgi_globals_ctor(&php_cgi_globals TSRMLS_CC);
1804 #endif
1805
1806 sapi_startup(&cgi_sapi_module);
1807 fastcgi = fcgi_is_fastcgi();
1808 cgi_sapi_module.php_ini_path_override = NULL;
1809
1810 #ifdef PHP_WIN32
1811 _fmode = _O_BINARY;
1812 setmode(_fileno(stdin), O_BINARY);
1813 setmode(_fileno(stdout), O_BINARY);
1814 setmode(_fileno(stderr), O_BINARY);
1815 #endif
1816
1817 if (!fastcgi) {
1818
1819
1820 if (getenv("SERVER_SOFTWARE") ||
1821 getenv("SERVER_NAME") ||
1822 getenv("GATEWAY_INTERFACE") ||
1823 getenv("REQUEST_METHOD")
1824 ) {
1825 cgi = 1;
1826 }
1827 }
1828
1829 if((query_string = getenv("QUERY_STRING")) != NULL && strchr(query_string, '=') == NULL) {
1830
1831 unsigned char *p;
1832 decoded_query_string = strdup(query_string);
1833 php_url_decode(decoded_query_string, strlen(decoded_query_string));
1834 for (p = (unsigned char *)decoded_query_string; *p && *p <= ' '; p++) {
1835
1836 }
1837 if(*p == '-') {
1838 skip_getopt = 1;
1839 }
1840 free(decoded_query_string);
1841 }
1842
1843 while (!skip_getopt && (c = php_getopt(argc, argv, OPTIONS, &php_optarg, &php_optind, 0, 2)) != -1) {
1844 switch (c) {
1845 case 'c':
1846 if (cgi_sapi_module.php_ini_path_override) {
1847 free(cgi_sapi_module.php_ini_path_override);
1848 }
1849 cgi_sapi_module.php_ini_path_override = strdup(php_optarg);
1850 break;
1851 case 'n':
1852 cgi_sapi_module.php_ini_ignore = 1;
1853 break;
1854 case 'd': {
1855
1856 int len = strlen(php_optarg);
1857 char *val;
1858
1859 if ((val = strchr(php_optarg, '='))) {
1860 val++;
1861 if (!isalnum(*val) && *val != '"' && *val != '\'' && *val != '\0') {
1862 cgi_sapi_module.ini_entries = realloc(cgi_sapi_module.ini_entries, ini_entries_len + len + sizeof("\"\"\n\0"));
1863 memcpy(cgi_sapi_module.ini_entries + ini_entries_len, php_optarg, (val - php_optarg));
1864 ini_entries_len += (val - php_optarg);
1865 memcpy(cgi_sapi_module.ini_entries + ini_entries_len, "\"", 1);
1866 ini_entries_len++;
1867 memcpy(cgi_sapi_module.ini_entries + ini_entries_len, val, len - (val - php_optarg));
1868 ini_entries_len += len - (val - php_optarg);
1869 memcpy(cgi_sapi_module.ini_entries + ini_entries_len, "\"\n\0", sizeof("\"\n\0"));
1870 ini_entries_len += sizeof("\n\0\"") - 2;
1871 } else {
1872 cgi_sapi_module.ini_entries = realloc(cgi_sapi_module.ini_entries, ini_entries_len + len + sizeof("\n\0"));
1873 memcpy(cgi_sapi_module.ini_entries + ini_entries_len, php_optarg, len);
1874 memcpy(cgi_sapi_module.ini_entries + ini_entries_len + len, "\n\0", sizeof("\n\0"));
1875 ini_entries_len += len + sizeof("\n\0") - 2;
1876 }
1877 } else {
1878 cgi_sapi_module.ini_entries = realloc(cgi_sapi_module.ini_entries, ini_entries_len + len + sizeof("=1\n\0"));
1879 memcpy(cgi_sapi_module.ini_entries + ini_entries_len, php_optarg, len);
1880 memcpy(cgi_sapi_module.ini_entries + ini_entries_len + len, "=1\n\0", sizeof("=1\n\0"));
1881 ini_entries_len += len + sizeof("=1\n\0") - 2;
1882 }
1883 break;
1884 }
1885
1886
1887
1888 case 'b':
1889 if (!fastcgi) {
1890 bindpath = strdup(php_optarg);
1891 }
1892 break;
1893 case 's':
1894 behavior = PHP_MODE_HIGHLIGHT;
1895 break;
1896 }
1897 }
1898 php_optind = orig_optind;
1899 php_optarg = orig_optarg;
1900
1901 if (fastcgi || bindpath) {
1902
1903 cgi_sapi_module.ub_write = sapi_fcgi_ub_write;
1904 cgi_sapi_module.flush = sapi_fcgi_flush;
1905 cgi_sapi_module.read_post = sapi_fcgi_read_post;
1906 cgi_sapi_module.getenv = sapi_fcgi_getenv;
1907 cgi_sapi_module.read_cookies = sapi_fcgi_read_cookies;
1908 }
1909
1910 #ifdef ZTS
1911 SG(request_info).path_translated = NULL;
1912 #endif
1913
1914 cgi_sapi_module.executable_location = argv[0];
1915 if (!cgi && !fastcgi && !bindpath) {
1916 cgi_sapi_module.additional_functions = additional_functions;
1917 }
1918
1919
1920 if (cgi_sapi_module.startup(&cgi_sapi_module) == FAILURE) {
1921 #ifdef ZTS
1922 tsrm_shutdown();
1923 #endif
1924 return FAILURE;
1925 }
1926
1927
1928 if (cgi && CGIG(force_redirect)) {
1929
1930
1931
1932
1933
1934
1935 if (!getenv("REDIRECT_STATUS") &&
1936 !getenv ("HTTP_REDIRECT_STATUS") &&
1937
1938
1939 (!CGIG(redirect_status_env) || !getenv(CGIG(redirect_status_env)))
1940 ) {
1941 zend_try {
1942 SG(sapi_headers).http_response_code = 400;
1943 PUTS("<b>Security Alert!</b> The PHP CGI cannot be accessed directly.\n\n\
1944 <p>This PHP CGI binary was compiled with force-cgi-redirect enabled. This\n\
1945 means that a page will only be served up if the REDIRECT_STATUS CGI variable is\n\
1946 set, e.g. via an Apache Action directive.</p>\n\
1947 <p>For more information as to <i>why</i> this behaviour exists, see the <a href=\"http://php.net/security.cgi-bin\">\
1948 manual page for CGI security</a>.</p>\n\
1949 <p>For more information about changing this behaviour or re-enabling this webserver,\n\
1950 consult the installation file that came with this distribution, or visit \n\
1951 <a href=\"http://php.net/install.windows\">the manual page</a>.</p>\n");
1952 } zend_catch {
1953 } zend_end_try();
1954 #if defined(ZTS) && !defined(PHP_DEBUG)
1955
1956
1957
1958
1959
1960
1961 tsrm_shutdown();
1962 #endif
1963 return FAILURE;
1964 }
1965 }
1966
1967 if (bindpath) {
1968 int backlog = 128;
1969 if (getenv("PHP_FCGI_BACKLOG")) {
1970 backlog = atoi(getenv("PHP_FCGI_BACKLOG"));
1971 }
1972 fcgi_fd = fcgi_listen(bindpath, backlog);
1973 if (fcgi_fd < 0) {
1974 fprintf(stderr, "Couldn't create FastCGI listen socket on port %s\n", bindpath);
1975 #ifdef ZTS
1976 tsrm_shutdown();
1977 #endif
1978 return FAILURE;
1979 }
1980 fastcgi = fcgi_is_fastcgi();
1981 }
1982 if (fastcgi) {
1983
1984 if (getenv("PHP_FCGI_MAX_REQUESTS")) {
1985 max_requests = atoi(getenv("PHP_FCGI_MAX_REQUESTS"));
1986 if (max_requests < 0) {
1987 fprintf(stderr, "PHP_FCGI_MAX_REQUESTS is not valid\n");
1988 return FAILURE;
1989 }
1990 }
1991
1992
1993 php_php_import_environment_variables = php_import_environment_variables;
1994 php_import_environment_variables = cgi_php_import_environment_variables;
1995
1996
1997 request = fcgi_init_request(fcgi_fd);
1998
1999 #ifndef PHP_WIN32
2000
2001 if (getenv("PHP_FCGI_CHILDREN")) {
2002 char * children_str = getenv("PHP_FCGI_CHILDREN");
2003 children = atoi(children_str);
2004 if (children < 0) {
2005 fprintf(stderr, "PHP_FCGI_CHILDREN is not valid\n");
2006 return FAILURE;
2007 }
2008 fcgi_set_mgmt_var("FCGI_MAX_CONNS", sizeof("FCGI_MAX_CONNS")-1, children_str, strlen(children_str));
2009
2010 fcgi_set_mgmt_var("FCGI_MAX_REQS", sizeof("FCGI_MAX_REQS")-1, children_str, strlen(children_str));
2011 } else {
2012 fcgi_set_mgmt_var("FCGI_MAX_CONNS", sizeof("FCGI_MAX_CONNS")-1, "1", sizeof("1")-1);
2013 fcgi_set_mgmt_var("FCGI_MAX_REQS", sizeof("FCGI_MAX_REQS")-1, "1", sizeof("1")-1);
2014 }
2015
2016 if (children) {
2017 int running = 0;
2018 pid_t pid;
2019
2020
2021 setsid();
2022 pgroup = getpgrp();
2023 #ifdef DEBUG_FASTCGI
2024 fprintf(stderr, "Process group %d\n", pgroup);
2025 #endif
2026
2027
2028 act.sa_flags = 0;
2029 act.sa_handler = fastcgi_cleanup;
2030 if (sigaction(SIGTERM, &act, &old_term) ||
2031 sigaction(SIGINT, &act, &old_int) ||
2032 sigaction(SIGQUIT, &act, &old_quit)
2033 ) {
2034 perror("Can't set signals");
2035 exit(1);
2036 }
2037
2038 if (fcgi_in_shutdown()) {
2039 goto parent_out;
2040 }
2041
2042 while (parent) {
2043 do {
2044 #ifdef DEBUG_FASTCGI
2045 fprintf(stderr, "Forking, %d running\n", running);
2046 #endif
2047 pid = fork();
2048 switch (pid) {
2049 case 0:
2050
2051
2052
2053
2054 parent = 0;
2055
2056
2057 sigaction(SIGTERM, &old_term, 0);
2058 sigaction(SIGQUIT, &old_quit, 0);
2059 sigaction(SIGINT, &old_int, 0);
2060 break;
2061 case -1:
2062 perror("php (pre-forking)");
2063 exit(1);
2064 break;
2065 default:
2066
2067 running++;
2068 break;
2069 }
2070 } while (parent && (running < children));
2071
2072 if (parent) {
2073 #ifdef DEBUG_FASTCGI
2074 fprintf(stderr, "Wait for kids, pid %d\n", getpid());
2075 #endif
2076 parent_waiting = 1;
2077 while (1) {
2078 if (wait(&status) >= 0) {
2079 running--;
2080 break;
2081 } else if (exit_signal) {
2082 break;
2083 }
2084 }
2085 if (exit_signal) {
2086 #if 0
2087 while (running > 0) {
2088 while (wait(&status) < 0) {
2089 }
2090 running--;
2091 }
2092 #endif
2093 goto parent_out;
2094 }
2095 }
2096 }
2097 } else {
2098 parent = 0;
2099 }
2100
2101 #endif
2102 }
2103
2104 zend_first_try {
2105 while (!skip_getopt && (c = php_getopt(argc, argv, OPTIONS, &php_optarg, &php_optind, 1, 2)) != -1) {
2106 switch (c) {
2107 case 'T':
2108 benchmark = 1;
2109 repeats = atoi(php_optarg);
2110 #ifdef HAVE_GETTIMEOFDAY
2111 gettimeofday(&start, NULL);
2112 #else
2113 time(&start);
2114 #endif
2115 break;
2116 case 'h':
2117 case '?':
2118 if (request) {
2119 fcgi_destroy_request(request);
2120 }
2121 fcgi_shutdown();
2122 no_headers = 1;
2123 SG(headers_sent) = 1;
2124 php_cgi_usage(argv[0]);
2125 php_output_end_all(TSRMLS_C);
2126 exit_status = 0;
2127 goto out;
2128 }
2129 }
2130 php_optind = orig_optind;
2131 php_optarg = orig_optarg;
2132
2133
2134
2135 #ifdef PHP_WIN32
2136
2137
2138 if (fastcgi && CGIG(impersonate)) {
2139 fcgi_impersonate();
2140 }
2141 #endif
2142 while (!fastcgi || fcgi_accept_request(request) >= 0) {
2143 SG(server_context) = fastcgi ? (void *) request : (void *) 1;
2144 init_request_info(request TSRMLS_CC);
2145 CG(interactive) = 0;
2146
2147 if (!cgi && !fastcgi) {
2148 while ((c = php_getopt(argc, argv, OPTIONS, &php_optarg, &php_optind, 0, 2)) != -1) {
2149 switch (c) {
2150
2151 case 'a':
2152 printf("Interactive mode enabled\n\n");
2153 CG(interactive) = 1;
2154 break;
2155
2156 case 'C':
2157 SG(options) |= SAPI_OPTION_NO_CHDIR;
2158 break;
2159
2160 case 'e':
2161 CG(compiler_options) |= ZEND_COMPILE_EXTENDED_INFO;
2162 break;
2163
2164 case 'f':
2165 if (script_file) {
2166 efree(script_file);
2167 }
2168 script_file = estrdup(php_optarg);
2169 no_headers = 1;
2170 break;
2171
2172 case 'i':
2173 if (script_file) {
2174 efree(script_file);
2175 }
2176 if (php_request_startup(TSRMLS_C) == FAILURE) {
2177 SG(server_context) = NULL;
2178 php_module_shutdown(TSRMLS_C);
2179 return FAILURE;
2180 }
2181 if (no_headers) {
2182 SG(headers_sent) = 1;
2183 SG(request_info).no_headers = 1;
2184 }
2185 php_print_info(0xFFFFFFFF TSRMLS_CC);
2186 php_request_shutdown((void *) 0);
2187 fcgi_shutdown();
2188 exit_status = 0;
2189 goto out;
2190
2191 case 'l':
2192 no_headers = 1;
2193 behavior = PHP_MODE_LINT;
2194 break;
2195
2196 case 'm':
2197 if (script_file) {
2198 efree(script_file);
2199 }
2200 SG(headers_sent) = 1;
2201 php_printf("[PHP Modules]\n");
2202 print_modules(TSRMLS_C);
2203 php_printf("\n[Zend Modules]\n");
2204 print_extensions(TSRMLS_C);
2205 php_printf("\n");
2206 php_output_end_all(TSRMLS_C);
2207 fcgi_shutdown();
2208 exit_status = 0;
2209 goto out;
2210
2211 #if 0
2212 case '':
2213 behavior=PHP_MODE_INDENT;
2214 break;
2215 #endif
2216
2217 case 'q':
2218 no_headers = 1;
2219 break;
2220
2221 case 'v':
2222 if (script_file) {
2223 efree(script_file);
2224 }
2225 no_headers = 1;
2226 if (php_request_startup(TSRMLS_C) == FAILURE) {
2227 SG(server_context) = NULL;
2228 php_module_shutdown(TSRMLS_C);
2229 return FAILURE;
2230 }
2231 if (no_headers) {
2232 SG(headers_sent) = 1;
2233 SG(request_info).no_headers = 1;
2234 }
2235 #if ZEND_DEBUG
2236 php_printf("PHP %s (%s) (built: %s %s) (DEBUG)\nCopyright (c) 1997-2016 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
2237 #else
2238 php_printf("PHP %s (%s) (built: %s %s)\nCopyright (c) 1997-2016 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
2239 #endif
2240 php_request_shutdown((void *) 0);
2241 fcgi_shutdown();
2242 exit_status = 0;
2243 goto out;
2244
2245 case 'w':
2246 behavior = PHP_MODE_STRIP;
2247 break;
2248
2249 case 'z':
2250 zend_load_extension(php_optarg);
2251 break;
2252
2253 default:
2254 break;
2255 }
2256 }
2257
2258 if (script_file) {
2259
2260 STR_FREE(SG(request_info).path_translated);
2261 SG(request_info).path_translated = script_file;
2262
2263
2264 SG(request_info).argc = argc - (php_optind - 1);
2265 SG(request_info).argv = &argv[php_optind - 1];
2266 SG(request_info).argv[0] = script_file;
2267 } else if (argc > php_optind) {
2268
2269 STR_FREE(SG(request_info).path_translated);
2270 SG(request_info).path_translated = estrdup(argv[php_optind]);
2271
2272 SG(request_info).argc = argc - php_optind;
2273 SG(request_info).argv = &argv[php_optind];
2274 }
2275
2276 if (no_headers) {
2277 SG(headers_sent) = 1;
2278 SG(request_info).no_headers = 1;
2279 }
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290 if (!SG(request_info).query_string && argc > php_optind) {
2291 int slen = strlen(PG(arg_separator).input);
2292 len = 0;
2293 for (i = php_optind; i < argc; i++) {
2294 if (i < (argc - 1)) {
2295 len += strlen(argv[i]) + slen;
2296 } else {
2297 len += strlen(argv[i]);
2298 }
2299 }
2300
2301 len += 2;
2302 s = malloc(len);
2303 *s = '\0';
2304 for (i = php_optind; i < argc; i++) {
2305 strlcat(s, argv[i], len);
2306 if (i < (argc - 1)) {
2307 strlcat(s, PG(arg_separator).input, len);
2308 }
2309 }
2310 SG(request_info).query_string = s;
2311 free_query_string = 1;
2312 }
2313 }
2314
2315
2316
2317
2318
2319
2320 if (SG(request_info).path_translated || cgi || fastcgi) {
2321 file_handle.type = ZEND_HANDLE_FILENAME;
2322 file_handle.filename = SG(request_info).path_translated;
2323 file_handle.handle.fp = NULL;
2324 } else {
2325 file_handle.filename = "-";
2326 file_handle.type = ZEND_HANDLE_FP;
2327 file_handle.handle.fp = stdin;
2328 }
2329
2330 file_handle.opened_path = NULL;
2331 file_handle.free_filename = 0;
2332
2333
2334
2335 if (php_request_startup(TSRMLS_C) == FAILURE) {
2336 if (fastcgi) {
2337 fcgi_finish_request(request, 1);
2338 }
2339 SG(server_context) = NULL;
2340 php_module_shutdown(TSRMLS_C);
2341 return FAILURE;
2342 }
2343 if (no_headers) {
2344 SG(headers_sent) = 1;
2345 SG(request_info).no_headers = 1;
2346 }
2347
2348
2349
2350
2351
2352
2353 if (cgi || fastcgi || SG(request_info).path_translated) {
2354 if (php_fopen_primary_script(&file_handle TSRMLS_CC) == FAILURE) {
2355 zend_try {
2356 if (errno == EACCES) {
2357 SG(sapi_headers).http_response_code = 403;
2358 PUTS("Access denied.\n");
2359 } else {
2360 SG(sapi_headers).http_response_code = 404;
2361 PUTS("No input file specified.\n");
2362 }
2363 } zend_catch {
2364 } zend_end_try();
2365
2366
2367
2368 if (fastcgi) {
2369 goto fastcgi_request_done;
2370 }
2371
2372 STR_FREE(SG(request_info).path_translated);
2373
2374 if (free_query_string && SG(request_info).query_string) {
2375 free(SG(request_info).query_string);
2376 SG(request_info).query_string = NULL;
2377 }
2378
2379 php_request_shutdown((void *) 0);
2380 SG(server_context) = NULL;
2381 php_module_shutdown(TSRMLS_C);
2382 sapi_shutdown();
2383 #ifdef ZTS
2384 tsrm_shutdown();
2385 #endif
2386 return FAILURE;
2387 }
2388 }
2389
2390 if (CGIG(check_shebang_line)) {
2391
2392 switch (file_handle.type) {
2393 case ZEND_HANDLE_FD:
2394 if (file_handle.handle.fd < 0) {
2395 break;
2396 }
2397 file_handle.type = ZEND_HANDLE_FP;
2398 file_handle.handle.fp = fdopen(file_handle.handle.fd, "rb");
2399
2400 case ZEND_HANDLE_FP:
2401 if (!file_handle.handle.fp ||
2402 (file_handle.handle.fp == stdin)) {
2403 break;
2404 }
2405 c = fgetc(file_handle.handle.fp);
2406 if (c == '#') {
2407 while (c != '\n' && c != '\r' && c != EOF) {
2408 c = fgetc(file_handle.handle.fp);
2409 }
2410
2411 if (c == '\r') {
2412 if (fgetc(file_handle.handle.fp) != '\n') {
2413 long pos = ftell(file_handle.handle.fp);
2414 fseek(file_handle.handle.fp, pos - 1, SEEK_SET);
2415 }
2416 }
2417 CG(start_lineno) = 2;
2418 } else {
2419 rewind(file_handle.handle.fp);
2420 }
2421 break;
2422 case ZEND_HANDLE_STREAM:
2423 c = php_stream_getc((php_stream*)file_handle.handle.stream.handle);
2424 if (c == '#') {
2425 while (c != '\n' && c != '\r' && c != EOF) {
2426 c = php_stream_getc((php_stream*)file_handle.handle.stream.handle);
2427 }
2428
2429 if (c == '\r') {
2430 if (php_stream_getc((php_stream*)file_handle.handle.stream.handle) != '\n') {
2431 long pos = php_stream_tell((php_stream*)file_handle.handle.stream.handle);
2432 php_stream_seek((php_stream*)file_handle.handle.stream.handle, pos - 1, SEEK_SET);
2433 }
2434 }
2435 CG(start_lineno) = 2;
2436 } else {
2437 php_stream_rewind((php_stream*)file_handle.handle.stream.handle);
2438 }
2439 break;
2440 case ZEND_HANDLE_MAPPED:
2441 if (file_handle.handle.stream.mmap.buf[0] == '#') {
2442 int i = 1;
2443
2444 c = file_handle.handle.stream.mmap.buf[i++];
2445 while (c != '\n' && c != '\r' && i < file_handle.handle.stream.mmap.len) {
2446 c = file_handle.handle.stream.mmap.buf[i++];
2447 }
2448 if (c == '\r') {
2449 if (i < file_handle.handle.stream.mmap.len && file_handle.handle.stream.mmap.buf[i] == '\n') {
2450 i++;
2451 }
2452 }
2453 if(i > file_handle.handle.stream.mmap.len) {
2454 i = file_handle.handle.stream.mmap.len;
2455 }
2456 file_handle.handle.stream.mmap.buf += i;
2457 file_handle.handle.stream.mmap.len -= i;
2458 }
2459 break;
2460 default:
2461 break;
2462 }
2463 }
2464
2465 switch (behavior) {
2466 case PHP_MODE_STANDARD:
2467 php_execute_script(&file_handle TSRMLS_CC);
2468 break;
2469 case PHP_MODE_LINT:
2470 PG(during_request_startup) = 0;
2471 exit_status = php_lint_script(&file_handle TSRMLS_CC);
2472 if (exit_status == SUCCESS) {
2473 zend_printf("No syntax errors detected in %s\n", file_handle.filename);
2474 } else {
2475 zend_printf("Errors parsing %s\n", file_handle.filename);
2476 }
2477 break;
2478 case PHP_MODE_STRIP:
2479 if (open_file_for_scanning(&file_handle TSRMLS_CC) == SUCCESS) {
2480 zend_strip(TSRMLS_C);
2481 zend_file_handle_dtor(&file_handle TSRMLS_CC);
2482 php_output_teardown();
2483 }
2484 return SUCCESS;
2485 break;
2486 case PHP_MODE_HIGHLIGHT:
2487 {
2488 zend_syntax_highlighter_ini syntax_highlighter_ini;
2489
2490 if (open_file_for_scanning(&file_handle TSRMLS_CC) == SUCCESS) {
2491 php_get_highlight_struct(&syntax_highlighter_ini);
2492 zend_highlight(&syntax_highlighter_ini TSRMLS_CC);
2493 if (fastcgi) {
2494 goto fastcgi_request_done;
2495 }
2496 zend_file_handle_dtor(&file_handle TSRMLS_CC);
2497 php_output_teardown();
2498 }
2499 return SUCCESS;
2500 }
2501 break;
2502 #if 0
2503
2504 case PHP_MODE_INDENT:
2505 open_file_for_scanning(&file_handle TSRMLS_CC);
2506 zend_indent();
2507 zend_file_handle_dtor(&file_handle TSRMLS_CC);
2508 php_output_teardown();
2509 return SUCCESS;
2510 break;
2511 #endif
2512 }
2513
2514 fastcgi_request_done:
2515 {
2516 STR_FREE(SG(request_info).path_translated);
2517
2518 php_request_shutdown((void *) 0);
2519
2520 if (exit_status == 0) {
2521 exit_status = EG(exit_status);
2522 }
2523
2524 if (free_query_string && SG(request_info).query_string) {
2525 free(SG(request_info).query_string);
2526 SG(request_info).query_string = NULL;
2527 }
2528 }
2529
2530 if (!fastcgi) {
2531 if (benchmark) {
2532 repeats--;
2533 if (repeats > 0) {
2534 script_file = NULL;
2535 php_optind = orig_optind;
2536 php_optarg = orig_optarg;
2537 continue;
2538 }
2539 }
2540 break;
2541 }
2542
2543
2544 requests++;
2545 if (max_requests && (requests == max_requests)) {
2546 fcgi_finish_request(request, 1);
2547 if (bindpath) {
2548 free(bindpath);
2549 }
2550 if (max_requests != 1) {
2551
2552 exit_status = 0;
2553 }
2554 break;
2555 }
2556
2557 }
2558 if (request) {
2559 fcgi_destroy_request(request);
2560 }
2561 fcgi_shutdown();
2562
2563 if (cgi_sapi_module.php_ini_path_override) {
2564 free(cgi_sapi_module.php_ini_path_override);
2565 }
2566 if (cgi_sapi_module.ini_entries) {
2567 free(cgi_sapi_module.ini_entries);
2568 }
2569 } zend_catch {
2570 exit_status = 255;
2571 } zend_end_try();
2572
2573 out:
2574 if (benchmark) {
2575 int sec;
2576 #ifdef HAVE_GETTIMEOFDAY
2577 int usec;
2578
2579 gettimeofday(&end, NULL);
2580 sec = (int)(end.tv_sec - start.tv_sec);
2581 if (end.tv_usec >= start.tv_usec) {
2582 usec = (int)(end.tv_usec - start.tv_usec);
2583 } else {
2584 sec -= 1;
2585 usec = (int)(end.tv_usec + 1000000 - start.tv_usec);
2586 }
2587 fprintf(stderr, "\nElapsed time: %d.%06d sec\n", sec, usec);
2588 #else
2589 time(&end);
2590 sec = (int)(end - start);
2591 fprintf(stderr, "\nElapsed time: %d sec\n", sec);
2592 #endif
2593 }
2594
2595 #ifndef PHP_WIN32
2596 parent_out:
2597 #endif
2598
2599 SG(server_context) = NULL;
2600 php_module_shutdown(TSRMLS_C);
2601 sapi_shutdown();
2602
2603 #ifdef ZTS
2604 tsrm_shutdown();
2605 #endif
2606
2607 #if defined(PHP_WIN32) && ZEND_DEBUG && 0
2608 _CrtDumpMemoryLeaks();
2609 #endif
2610
2611 return exit_status;
2612 }
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622