You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1676 lines
45 KiB

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