diff options
Diffstat (limited to 'sapi/cgi')
-rw-r--r-- | sapi/cgi/CREDITS | 2 | ||||
-rw-r--r-- | sapi/cgi/Makefile.frag | 2 | ||||
-rw-r--r-- | sapi/cgi/README.FastCGI | 151 | ||||
-rw-r--r-- | sapi/cgi/cgi_main.c | 1749 | ||||
-rw-r--r-- | sapi/cgi/config.w32 | 26 | ||||
-rw-r--r-- | sapi/cgi/config9.m4 | 167 | ||||
-rw-r--r-- | sapi/cgi/fastcgi.c | 926 | ||||
-rw-r--r-- | sapi/cgi/fastcgi.h | 136 | ||||
-rw-r--r-- | sapi/cgi/getopt.c | 154 | ||||
-rw-r--r-- | sapi/cgi/php.sym | 0 | ||||
-rw-r--r-- | sapi/cgi/php_getopt.h | 30 |
11 files changed, 0 insertions, 3343 deletions
diff --git a/sapi/cgi/CREDITS b/sapi/cgi/CREDITS deleted file mode 100644 index a1c6a0be59..0000000000 --- a/sapi/cgi/CREDITS +++ /dev/null @@ -1,2 +0,0 @@ -CGI / FastCGI -Rasmus Lerdorf, Stig Bakken, Shane Caraveo diff --git a/sapi/cgi/Makefile.frag b/sapi/cgi/Makefile.frag deleted file mode 100644 index 57a3b2937c..0000000000 --- a/sapi/cgi/Makefile.frag +++ /dev/null @@ -1,2 +0,0 @@ -$(SAPI_CGI_PATH): $(PHP_GLOBAL_OBJS) $(PHP_SAPI_OBJS) - $(BUILD_CGI) diff --git a/sapi/cgi/README.FastCGI b/sapi/cgi/README.FastCGI deleted file mode 100644 index 3dda295d84..0000000000 --- a/sapi/cgi/README.FastCGI +++ /dev/null @@ -1,151 +0,0 @@ -Credits: -Ben Mansell, Stephen Landamore, Daniel Silverstone, Shane Caraveo - -Building PHP ------------- - -You must add '--enable-fastcgi' to the configure command on Linux or -OSX based systems to get fastcgi support in the php-cgi binary. You -also must not use '--enable-discard-path'. - -Running the FastCGI PHP module ------------------------------- - -There are two ways to run the resulting 'php' binary after the fastcgi -version has been built: - -1) Configure your web server to run the PHP binary itself. - -This is the simplest method, obviously you will have to configure your -web server appropriately. Some web servers may also not support this method, -or may not be as efficient. - -2) Run PHP separately from the web server. - -In this setup, PHP is started as a separate process entirely from the web -server. It will listen on a socket for new FastCGI requests, and deliver -PHP pages as appropriate. This is the recommended way of running PHP-FastCGI. -To run this way, you must start the PHP binary running by giving it an IP -and a port number to listen to on the command line, e.g.: - - ./php -b 127.0.0.1:8002 - -The above line is the recommended way of running FastCGI. You usually -want the FastCGI server to provide services to the localhost, not -everyone on the Internet. - -If your web server sits on a remote host, you can make FastCGI listen -on all interfaces: - - ./php -b :8002 - ./php -b "*:8002" - -Note that hostnames are not supported. - -You must also configure your web server to connect to the appropriate port -in order to talk to the PHP FastCGI process. - -The advantage of running PHP in this way is that it entirely separates the -web server and PHP process, so that one cannot disrupt the other. It also -allows PHP to be on an entirely separate machine from the web server if need -be, you could even have several web servers utilising the same running PHP -process if required! - - -Using FastCGI PHP with Apache -============================= - -First of all, you may well ask 'Why?'. After all, Apache already has mod_php. -However, there are advantages to running PHP with FastCGI. Separating the -PHP code from the web server removes 'bloat' from the main server, and should -improve the performance of non-PHP requests. Secondly, having one permanent -PHP process as opposed to one per apache process means that shared resources -like persistent database connections are used more efficiently. - -First of all, make sure that the FastCGI module is enabled. You should have -a line in your config like: - - LoadModule fastcgi_module /usr/lib/apache/2.0/mod_fastcgi.so - -Don't load mod_php, by the way. Make sure it is commented out! - - #LoadModule php5_module /usr/lib/apache/2.0/libphp5.so - -Now, we'll create a fcgi-bin directory, just like you would do with normal -CGI scripts. You'll need to create a directory somewhere to store your -FastCGI binaries. We'll use /space/fcgi-bin/ for this example. Remember to -copy the FastCGI-PHP binary in there. (named 'php-cgi') This sets up -php to run under mod_fastcgi as a dynamic server. - - ScriptAlias /fcgi-bin/ /space/fcgi-bin/ - <Location /fcgi-bin/> - Options ExecCGI - SetHandler fastcgi-script - </Location> - -To setup a specific static configuration for php, you have to use -the FastCgiServer configuration for mod_fastcgi. For this, do not -use the above configuration, but rather the following. -(see mod_fastcgi docs for more configuration information): - - Alias /fcgi-bin/ /space/fcgi-bin/ - FastCgiServer /path/to/php-cgi -processes 5 - -For either of the above configurations, we need to tell Apache to -use the FastCGI binary /fcgi-bin/php to deliver PHP pages. -All that is needed is: - - AddType application/x-httpd-fastphp .php - Action application/x-httpd-fastphp /fcgi-bin/php-cgi - -Now, if you restart Apache, php pages should now be delivered! - -Using FastCGI PHP with IIS or iPlanet -===================================== - -FastCGI server plugins are available at www.caraveo.com/fastcgi/ -Documentation on these are sparse. iPlanet is not very tested, -and no makefile exists yet for unix based iPlanet servers. - - -Security --------- - -Be sure to run the php binary as an appropriate userid. Also, firewall out -the port that PHP is listening on. In addition, you can set the environment -variable FCGI_WEB_SERVER_ADDRS to control who can connect to the FastCGI. -Set it to a comma separated list of IP addresses, e.g.: - -export FCGI_WEB_SERVER_ADDRS=199.170.183.28,199.170.183.71 - - -Tuning ------- - -There are a few tuning parameters that can be tweaked to control the -performance of FastCGI PHP. The following are environment variables that can -be set before running the PHP binary: - -PHP_FCGI_CHILDREN (default value: 0) - -This controls how many child processes the PHP process spawns. When the -fastcgi starts, it creates a number of child processes which handle one -page request at a time. Value 0 means that PHP willnot start additional -processes and main process will handle FastCGI requests by itself. Note that -this process may die (because of PHP_FCGI_MAX_REQUESTS) and it willnot -respawned automatic. Values 1 and above force PHP start additioanl processes -those will handle requests. The main process will restart children in case of -their death. So by default, you will be able to handle 1 concurrent PHP page -requests. Further requests will be queued. Increasing this number will allow -for better concurrency, especially if you have pages that take a significant -time to create, or supply a lot of data (e.g. downloading huge files via PHP). -On the other hand, having more processes running will use more RAM, and letting -too many PHP pages be generated concurrently will mean that each request will -be slow. - -PHP_FCGI_MAX_REQUESTS (default value: 500) - -This controls how many requests each child process will handle before -exitting. When one process exits, another will be created. This tuning is -necessary because several PHP functions are known to have memory leaks. If the -PHP processes were left around forever, they would be become very inefficient. diff --git a/sapi/cgi/cgi_main.c b/sapi/cgi/cgi_main.c deleted file mode 100644 index 45b6262fe9..0000000000 --- a/sapi/cgi/cgi_main.c +++ /dev/null @@ -1,1749 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP Version 5 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2006 The PHP Group | - +----------------------------------------------------------------------+ - | This source file is subject to version 3.01 of the PHP license, | - | that is bundled with this package in the file LICENSE, and is | - | available through the world-wide-web at the following url: | - | http://www.php.net/license/3_01.txt | - | If you did not receive a copy of the PHP license and are unable to | - | obtain it through the world-wide-web, please send a note to | - | license@php.net so we can mail you a copy immediately. | - +----------------------------------------------------------------------+ - | Authors: Rasmus Lerdorf <rasmus@lerdorf.on.ca> | - | Stig Bakken <ssb@php.net> | - | Zeev Suraski <zeev@zend.com> | - | FastCGI: Ben Mansell <php@slimyhorror.com> | - | Shane Caraveo <shane@caraveo.com> | - | Dmitry Stogov <dmitry@zend.com> | - +----------------------------------------------------------------------+ -*/ - -/* $Id$ */ - -#include "php.h" -#include "php_globals.h" -#include "php_variables.h" -#include "zend_modules.h" - -#include "SAPI.h" - -#include <stdio.h> -#include "php.h" -#ifdef PHP_WIN32 -#include "win32/time.h" -#include "win32/signal.h" -#include <process.h> -#endif -#if HAVE_SYS_TIME_H -#include <sys/time.h> -#endif -#if HAVE_UNISTD_H -#include <unistd.h> -#endif -#if HAVE_SIGNAL_H -#include <signal.h> -#endif -#if HAVE_SETLOCALE -#include <locale.h> -#endif -#if HAVE_SYS_TYPES_H -#include <sys/types.h> -#endif -#if HAVE_SYS_WAIT_H -#include <sys/wait.h> -#endif -#include "zend.h" -#include "zend_extensions.h" -#include "php_ini.h" -#include "php_globals.h" -#include "php_main.h" -#include "fopen_wrappers.h" -#include "ext/standard/php_standard.h" -#ifdef PHP_WIN32 -#include <io.h> -#include <fcntl.h> -#include "win32/php_registry.h" -#endif - -#ifdef __riscos__ -#include <unixlib/local.h> -int __riscosify_control = __RISCOSIFY_STRICT_UNIX_SPECS; -#endif - -#include "zend_compile.h" -#include "zend_execute.h" -#include "zend_highlight.h" -#include "zend_indent.h" - -#include "php_getopt.h" - -#if PHP_FASTCGI -#include "fastcgi.h" - -#ifndef PHP_WIN32 -/* XXX this will need to change later when threaded fastcgi is - implemented. shane */ -struct sigaction act, old_term, old_quit, old_int; -#endif - -static void (*php_php_import_environment_variables)(zval *array_ptr TSRMLS_DC); - -#ifndef PHP_WIN32 -/* these globals used for forking children on unix systems */ -/** - * Number of child processes that will get created to service requests - */ -static int children = 0; - -/** - * Set to non-zero if we are the parent process - */ -static int parent = 1; - -/** - * Process group - */ -static pid_t pgroup; -#endif - -#endif - -#define PHP_MODE_STANDARD 1 -#define PHP_MODE_HIGHLIGHT 2 -#define PHP_MODE_INDENT 3 -#define PHP_MODE_LINT 4 -#define PHP_MODE_STRIP 5 - -static char *php_optarg = NULL; -static int php_optind = 1; - -static const opt_struct OPTIONS[] = { - {'a', 0, "interactive"}, -#ifndef PHP_WIN32 - {'b', 1, "bindpath"}, -#endif - {'C', 0, "no-chdir"}, - {'c', 1, "php-ini"}, - {'d', 1, "define"}, - {'e', 0, "profile-info"}, - {'f', 1, "file"}, - {'h', 0, "help"}, - {'i', 0, "info"}, - {'l', 0, "syntax-check"}, - {'m', 0, "modules"}, - {'n', 0, "no-php-ini"}, - {'q', 0, "no-header"}, - {'s', 0, "syntax-highlight"}, - {'s', 0, "syntax-highlighting"}, - {'w', 0, "strip"}, - {'?', 0, "usage"},/* help alias (both '?' and 'usage') */ - {'v', 0, "version"}, - {'z', 1, "zend-extension"}, - {'-', 0, NULL} /* end of args */ -}; - -#if ENABLE_PATHINFO_CHECK -/* true global. this is retreived once only, even for fastcgi */ -long fix_pathinfo = 1; -#endif - -#if PHP_FASTCGI -long fcgi_logging = 1; -#endif - -static long rfc2616_headers = 0; -static long cgi_nph = 0; - -#ifdef PHP_WIN32 -#define TRANSLATE_SLASHES(path) \ - { \ - char *tmp = path; \ - while (*tmp) { \ - if (*tmp == '\\') *tmp = '/'; \ - tmp++; \ - } \ - } -#else -#define TRANSLATE_SLASHES(path) -#endif - -static int print_module_info(zend_module_entry *module, void *arg TSRMLS_DC) -{ - php_printf("%s\n", module->name); - return 0; -} - -static int module_name_cmp(const void *a, const void *b TSRMLS_DC) -{ - Bucket *f = *((Bucket **) a); - Bucket *s = *((Bucket **) b); - - return strcasecmp(((zend_module_entry *)f->pData)->name, - ((zend_module_entry *)s->pData)->name); -} - -static void print_modules(TSRMLS_D) -{ - HashTable sorted_registry; - zend_module_entry tmp; - - zend_hash_init(&sorted_registry, 50, NULL, NULL, 1); - zend_hash_copy(&sorted_registry, &module_registry, NULL, &tmp, sizeof(zend_module_entry)); - zend_hash_sort(&sorted_registry, zend_qsort, module_name_cmp, 0 TSRMLS_CC); - zend_hash_apply_with_argument(&sorted_registry, (apply_func_arg_t) print_module_info, NULL TSRMLS_CC); - zend_hash_destroy(&sorted_registry); -} - -static int print_extension_info(zend_extension *ext, void *arg TSRMLS_DC) -{ - php_printf("%s\n", ext->name); - return 0; -} - -static int extension_name_cmp(const zend_llist_element **f, - const zend_llist_element **s TSRMLS_DC) -{ - return strcmp(((zend_extension *)(*f)->data)->name, - ((zend_extension *)(*s)->data)->name); -} - -static void print_extensions(TSRMLS_D) -{ - zend_llist sorted_exts; - - zend_llist_copy(&sorted_exts, &zend_extensions); - zend_llist_sort(&sorted_exts, extension_name_cmp TSRMLS_CC); - zend_llist_apply_with_argument(&sorted_exts, (llist_apply_with_arg_func_t) print_extension_info, NULL TSRMLS_CC); - zend_llist_destroy(&sorted_exts); -} - -#ifndef STDOUT_FILENO -#define STDOUT_FILENO 1 -#endif - -static inline size_t sapi_cgibin_single_write(const char *str, uint str_length TSRMLS_DC) -{ -#ifdef PHP_WRITE_STDOUT - long ret; -#else - size_t ret; -#endif - -#if PHP_FASTCGI - if (fcgi_is_fastcgi()) { - fcgi_request *request = (fcgi_request*) SG(server_context); - long ret = fcgi_write(request, FCGI_STDOUT, str, str_length); - if (ret <= 0) { - return 0; - } - return ret; - } -#endif -#ifdef PHP_WRITE_STDOUT - ret = write(STDOUT_FILENO, str, str_length); - if (ret <= 0) return 0; - return ret; -#else - ret = fwrite(str, 1, MIN(str_length, 16384), stdout); - return ret; -#endif -} - -static int sapi_cgibin_ub_write(const char *str, uint str_length TSRMLS_DC) -{ - const char *ptr = str; - uint remaining = str_length; - size_t ret; - - while (remaining > 0) { - ret = sapi_cgibin_single_write(ptr, remaining TSRMLS_CC); - if (!ret) { - php_handle_aborted_connection(); - return str_length - remaining; - } - ptr += ret; - remaining -= ret; - } - - return str_length; -} - - -static void sapi_cgibin_flush(void *server_context) -{ -#if PHP_FASTCGI - if (fcgi_is_fastcgi()) { - fcgi_request *request = (fcgi_request*) server_context; - if ( -#ifndef PHP_WIN32 - !parent && -#endif - request && !fcgi_flush(request, 0)) { - php_handle_aborted_connection(); - } - return; - } -#endif - if (fflush(stdout) == EOF) { - php_handle_aborted_connection(); - } -} - -#define SAPI_CGI_MAX_HEADER_LENGTH 1024 - -static int sapi_cgi_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC) -{ - char buf[SAPI_CGI_MAX_HEADER_LENGTH]; - sapi_header_struct *h; - zend_llist_position pos; - - if (SG(request_info).no_headers == 1) { - return SAPI_HEADER_SENT_SUCCESSFULLY; - } - - if (cgi_nph || SG(sapi_headers).http_response_code != 200) - { - int len; - - if (rfc2616_headers && SG(sapi_headers).http_status_line) { - len = snprintf(buf, SAPI_CGI_MAX_HEADER_LENGTH, - "%s\r\n", SG(sapi_headers).http_status_line); - - if (len > SAPI_CGI_MAX_HEADER_LENGTH) { - len = SAPI_CGI_MAX_HEADER_LENGTH; - } - - } else { - len = sprintf(buf, "Status: %d\r\n", SG(sapi_headers).http_response_code); - } - - PHPWRITE_H(buf, len); - } - - h = (sapi_header_struct*)zend_llist_get_first_ex(&sapi_headers->headers, &pos); - while (h) { - /* prevent CRLFCRLF */ - if (h->header_len) { - PHPWRITE_H(h->header, h->header_len); - PHPWRITE_H("\r\n", 2); - } - h = (sapi_header_struct*)zend_llist_get_next_ex(&sapi_headers->headers, &pos); - } - PHPWRITE_H("\r\n", 2); - - return SAPI_HEADER_SENT_SUCCESSFULLY; -} - - -static int sapi_cgi_read_post(char *buffer, uint count_bytes TSRMLS_DC) -{ - uint read_bytes=0, tmp_read_bytes; -#if PHP_FASTCGI - char *pos = buffer; -#endif - - count_bytes = MIN(count_bytes, (uint) SG(request_info).content_length - SG(read_post_bytes)); - while (read_bytes < count_bytes) { -#if PHP_FASTCGI - if (fcgi_is_fastcgi()) { - fcgi_request *request = (fcgi_request*) SG(server_context); - tmp_read_bytes = fcgi_read(request, pos, count_bytes - read_bytes); - pos += tmp_read_bytes; - } else { - tmp_read_bytes = read(0, buffer + read_bytes, count_bytes - read_bytes); - } -#else - tmp_read_bytes = read(0, buffer + read_bytes, count_bytes - read_bytes); -#endif - - if (tmp_read_bytes <= 0) { - break; - } - read_bytes += tmp_read_bytes; - } - return read_bytes; -} - -static char *sapi_cgibin_getenv(char *name, size_t name_len TSRMLS_DC) -{ -#if PHP_FASTCGI - /* when php is started by mod_fastcgi, no regular environment - is provided to PHP. It is always sent to PHP at the start - of a request. So we have to do our own lookup to get env - vars. This could probably be faster somehow. */ - if (fcgi_is_fastcgi()) { - fcgi_request *request = (fcgi_request*) SG(server_context); - return fcgi_getenv(request, name, name_len); - } -#endif - /* if cgi, or fastcgi and not found in fcgi env - check the regular environment */ - return getenv(name); -} - -static char *_sapi_cgibin_putenv(char *name, char *value TSRMLS_DC) -{ - int name_len; -#if !HAVE_SETENV || !HAVE_UNSETENV - int len; - char *buf; -#endif - - if (!name) { - return NULL; - } - name_len = strlen(name); - -#if PHP_FASTCGI - /* when php is started by mod_fastcgi, no regular environment - is provided to PHP. It is always sent to PHP at the start - of a request. So we have to do our own lookup to get env - vars. This could probably be faster somehow. */ - if (fcgi_is_fastcgi()) { - fcgi_request *request = (fcgi_request*) SG(server_context); - return fcgi_putenv(request, name, name_len, value); - } -#endif -#if HAVE_SETENV - if (value) { - setenv(name, value, 1); - } -#endif -#if HAVE_UNSETENV - if (!value) { - unsetenv(name); - } -#endif - -#if !HAVE_SETENV || !HAVE_UNSETENV - /* if cgi, or fastcgi and not found in fcgi env - check the regular environment - this leaks, but it's only cgi anyway, we'll fix - it for 5.0 - */ - len = name_len + (value ? strlen(value) : 0) + sizeof("=") + 2; - buf = (char *) malloc(len); - if (buf == NULL) { - return getenv(name); - } -#endif -#if !HAVE_SETENV - if (value) { - len = snprintf(buf, len - 1, "%s=%s", name, value); - putenv(buf); - } -#endif -#if !HAVE_UNSETENV - if (!value) { - len = snprintf(buf, len - 1, "%s=", name); - putenv(buf); - } -#endif - return getenv(name); -} - -static char *sapi_cgi_read_cookies(TSRMLS_D) -{ - return sapi_cgibin_getenv((char *) "HTTP_COOKIE", sizeof("HTTP_COOKIE")-1 TSRMLS_CC); -} - -#if PHP_FASTCGI -void cgi_php_import_environment_variables(zval *array_ptr TSRMLS_DC) -{ - if (PG(http_globals)[TRACK_VARS_ENV] && - array_ptr != PG(http_globals)[TRACK_VARS_ENV] && - Z_TYPE_P(PG(http_globals)[TRACK_VARS_ENV]) == IS_ARRAY && - zend_hash_num_elements(Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_ENV])) > 0) { - zval_dtor(array_ptr); - *array_ptr = *PG(http_globals)[TRACK_VARS_ENV]; - INIT_PZVAL(array_ptr); - zval_copy_ctor(array_ptr); - return; - } else if (PG(http_globals)[TRACK_VARS_SERVER] && - array_ptr != PG(http_globals)[TRACK_VARS_SERVER] && - Z_TYPE_P(PG(http_globals)[TRACK_VARS_SERVER]) == IS_ARRAY && - zend_hash_num_elements(Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_SERVER])) > 0) { - zval_dtor(array_ptr); - *array_ptr = *PG(http_globals)[TRACK_VARS_SERVER]; - INIT_PZVAL(array_ptr); - zval_copy_ctor(array_ptr); - return; - } - - /* call php's original import as a catch-all */ - php_php_import_environment_variables(array_ptr TSRMLS_CC); - - if (fcgi_is_fastcgi()) { - fcgi_request *request = (fcgi_request*) SG(server_context); - HashPosition pos; - int magic_quotes_gpc = PG(magic_quotes_gpc); - char *var, **val; - uint var_len; - ulong idx; - - /* turn off magic_quotes while importing environment variables */ - PG(magic_quotes_gpc) = 0; - for (zend_hash_internal_pointer_reset_ex(&request->env, &pos); - zend_hash_get_current_key_ex(&request->env, &var, &var_len, &idx, 0, &pos) == HASH_KEY_IS_STRING && - zend_hash_get_current_data_ex(&request->env, (void **) &val, &pos) == SUCCESS; - zend_hash_move_forward_ex(&request->env, &pos)) { - php_register_variable(var, *val, array_ptr TSRMLS_CC); - } - PG(magic_quotes_gpc) = magic_quotes_gpc; - } -} -#endif - -static void sapi_cgi_register_variables(zval *track_vars_array TSRMLS_DC) -{ - /* In CGI mode, we consider the environment to be a part of the server - * variables - */ - php_import_environment_variables(track_vars_array TSRMLS_CC); - /* Build the special-case PHP_SELF variable for the CGI version */ - php_register_variable("PHP_SELF", (SG(request_info).request_uri ? SG(request_info).request_uri : ""), track_vars_array TSRMLS_CC); -} - -static void sapi_cgi_log_message(char *message) -{ -#if PHP_FASTCGI - if (fcgi_is_fastcgi() && fcgi_logging) { - fcgi_request *request; - TSRMLS_FETCH(); - - request = (fcgi_request*) SG(server_context); - if (request) { - int len = strlen(message); - char *buf = malloc(len+2); - - memcpy(buf, message, len); - memcpy(buf + len, "\n", sizeof("\n")); - fcgi_write(request, FCGI_STDERR, buf, len+1); - free(buf); - } else { - fprintf(stderr, "%s\n", message); - } - /* ignore return code */ - } else -#endif /* PHP_FASTCGI */ - fprintf(stderr, "%s\n", message); -} - -static int sapi_cgi_deactivate(TSRMLS_D) -{ - /* flush only when SAPI was started. The reasons are: - 1. SAPI Deactivate is called from two places: module init and request shutdown - 2. When the first call occurs and the request is not set up, flush fails on - FastCGI. - */ - if (SG(sapi_started)) { - sapi_cgibin_flush(SG(server_context)); - } - return SUCCESS; -} - -static int php_cgi_startup(sapi_module_struct *sapi_module) -{ - if (php_module_startup(sapi_module, NULL, 0) == FAILURE) { - return FAILURE; - } - return SUCCESS; -} - - -/* {{{ sapi_module_struct cgi_sapi_module - */ -static sapi_module_struct cgi_sapi_module = { -#if PHP_FASTCGI - "cgi-fcgi", /* name */ - "CGI/FastCGI", /* pretty name */ -#else - "cgi", /* name */ - "CGI", /* pretty name */ -#endif - - php_cgi_startup, /* startup */ - php_module_shutdown_wrapper, /* shutdown */ - - NULL, /* activate */ - sapi_cgi_deactivate, /* deactivate */ - - sapi_cgibin_ub_write, /* unbuffered write */ - sapi_cgibin_flush, /* flush */ - NULL, /* get uid */ - sapi_cgibin_getenv, /* getenv */ - - php_error, /* error handler */ - - NULL, /* header handler */ - sapi_cgi_send_headers, /* send headers handler */ - NULL, /* send header handler */ - - sapi_cgi_read_post, /* read POST data */ - sapi_cgi_read_cookies, /* read Cookies */ - - sapi_cgi_register_variables, /* register server variables */ - sapi_cgi_log_message, /* Log message */ - NULL, /* Get request time */ - - STANDARD_SAPI_MODULE_PROPERTIES -}; -/* }}} */ - -/* {{{ php_cgi_usage - */ -static void php_cgi_usage(char *argv0) -{ - char *prog; - - prog = strrchr(argv0, '/'); - if (prog) { - prog++; - } else { - prog = "php"; - } - - php_printf("Usage: %s [-q] [-h] [-s] [-v] [-i] [-f <file>]\n" - " %s <file> [args...]\n" - " -a Run interactively\n" -#if PHP_FASTCGI && !defined(PHP_WIN32) - " -b <address:port>|<port> Bind Path for external FASTCGI Server mode\n" -#endif - " -C Do not chdir to the script's directory\n" - " -c <path>|<file> Look for php.ini file in this directory\n" - " -n No php.ini file will be used\n" - " -d foo[=bar] Define INI entry foo with value 'bar'\n" - " -e Generate extended information for debugger/profiler\n" - " -f <file> Parse <file>. Implies `-q'\n" - " -h This help\n" - " -i PHP information\n" - " -l Syntax check only (lint)\n" - " -m Show compiled in modules\n" - " -q Quiet-mode. Suppress HTTP Header output.\n" - " -s Display colour syntax highlighted source.\n" - " -v Version number\n" - " -w Display source with stripped comments and whitespace.\n" - " -z <file> Load Zend extension <file>.\n", - prog, prog); -} -/* }}} */ - -/* {{{ init_request_info - - initializes request_info structure - - specificly in this section we handle proper translations - for: - - PATH_INFO - derived from the portion of the URI path following - the script name but preceding any query data - may be empty - - PATH_TRANSLATED - derived by taking any path-info component of the - request URI and performing any virtual-to-physical - translation appropriate to map it onto the server's - document repository structure - - empty if PATH_INFO is empty - - The env var PATH_TRANSLATED **IS DIFFERENT** than the - request_info.path_translated variable, the latter should - match SCRIPT_FILENAME instead. - - SCRIPT_NAME - set to a URL path that could identify the CGI script - rather than the interpreter. PHP_SELF is set to this. - - REQUEST_URI - uri section following the domain:port part of a URI - - SCRIPT_FILENAME - The virtual-to-physical translation of SCRIPT_NAME (as per - PATH_TRANSLATED) - - These settings are documented at - http://cgi-spec.golux.com/ - - - Based on the following URL request: - - http://localhost/info.php/test?a=b - - should produce, which btw is the same as if - we were running under mod_cgi on apache (ie. not - using ScriptAlias directives): - - PATH_INFO=/test - PATH_TRANSLATED=/docroot/test - SCRIPT_NAME=/info.php - REQUEST_URI=/info.php/test?a=b - SCRIPT_FILENAME=/docroot/info.php - QUERY_STRING=a=b - - but what we get is (cgi/mod_fastcgi under apache): - - PATH_INFO=/info.php/test - PATH_TRANSLATED=/docroot/info.php/test - SCRIPT_NAME=/php/php-cgi (from the Action setting I suppose) - REQUEST_URI=/info.php/test?a=b - SCRIPT_FILENAME=/path/to/php/bin/php-cgi (Action setting translated) - QUERY_STRING=a=b - - Comments in the code below refer to using the above URL in a request - - */ -static void init_request_info(TSRMLS_D) -{ - char *env_script_filename = sapi_cgibin_getenv("SCRIPT_FILENAME", sizeof("SCRIPT_FILENAME")-1 TSRMLS_CC); - char *env_path_translated = sapi_cgibin_getenv("PATH_TRANSLATED", sizeof("PATH_TRANSLATED")-1 TSRMLS_CC); - char *script_path_translated = env_script_filename; - -#if !DISCARD_PATH - /* some broken servers do not have script_filename or argv0 - an example, IIS configured in some ways. then they do more - broken stuff and set path_translated to the cgi script location */ - if (!script_path_translated && env_path_translated) { - script_path_translated = env_path_translated; - } -#endif - - /* initialize the defaults */ - SG(request_info).path_translated = NULL; - SG(request_info).request_method = NULL; - SG(request_info).proto_num = 1000; - SG(request_info).query_string = NULL; - SG(request_info).request_uri = NULL; - SG(request_info).content_type = NULL; - SG(request_info).content_length = 0; - SG(sapi_headers).http_response_code = 200; - - /* script_path_translated being set is a good indication that - we are running in a cgi environment, since it is always - null otherwise. otherwise, the filename - of the script will be retreived later via argc/argv */ - if (script_path_translated) { - const char *auth; - char *content_length = sapi_cgibin_getenv("CONTENT_LENGTH", sizeof("CONTENT_LENGTH")-1 TSRMLS_CC); - char *content_type = sapi_cgibin_getenv("CONTENT_TYPE", sizeof("CONTENT_TYPE")-1 TSRMLS_CC); - char *env_path_info = sapi_cgibin_getenv("PATH_INFO", sizeof("PATH_INFO")-1 TSRMLS_CC); - char *env_script_name = sapi_cgibin_getenv("SCRIPT_NAME", sizeof("SCRIPT_NAME")-1 TSRMLS_CC); -#if ENABLE_PATHINFO_CHECK - struct stat st; - char *env_redirect_url = sapi_cgibin_getenv("REDIRECT_URL", sizeof("REDIRECT_URL")-1 TSRMLS_CC); - char *env_document_root = sapi_cgibin_getenv("DOCUMENT_ROOT", sizeof("DOCUMENT_ROOT")-1 TSRMLS_CC); - - if (fix_pathinfo) { - - /* save the originals first for anything we change later */ - if (env_path_translated) { - _sapi_cgibin_putenv("ORIG_PATH_TRANSLATED", env_path_translated TSRMLS_CC); - } - if (env_path_info) { - _sapi_cgibin_putenv("ORIG_PATH_INFO", env_path_info TSRMLS_CC); - } - if (env_script_name) { - _sapi_cgibin_putenv("ORIG_SCRIPT_NAME", env_script_name TSRMLS_CC); - } - if (env_script_filename) { - _sapi_cgibin_putenv("ORIG_SCRIPT_FILENAME", env_script_filename TSRMLS_CC); - } - if (!env_document_root) { - /* ini version of document root */ - if (!env_document_root) { - env_document_root = PG(doc_root); - } - /* set the document root, this makes a more - consistent env for php scripts */ - if (env_document_root) { - env_document_root = _sapi_cgibin_putenv("DOCUMENT_ROOT", env_document_root TSRMLS_CC); - /* fix docroot */ - TRANSLATE_SLASHES(env_document_root); - } - } - - if (env_path_translated != NULL && env_redirect_url != NULL) { - /* - pretty much apache specific. If we have a redirect_url - then our script_filename and script_name point to the - php executable - */ - script_path_translated = env_path_translated; - /* we correct SCRIPT_NAME now in case we don't have PATH_INFO */ - env_script_name = _sapi_cgibin_putenv("SCRIPT_NAME", env_redirect_url TSRMLS_CC); - } - -#ifdef __riscos__ - /* Convert path to unix format*/ - __riscosify_control |= __RISCOSIFY_DONT_CHECK_DIR; - script_path_translated = __unixify(script_path_translated, 0, NULL, 1, 0); -#endif - - /* - * if the file doesn't exist, try to extract PATH_INFO out - * of it by stat'ing back through the '/' - * this fixes url's like /info.php/test - */ - if (script_path_translated && stat(script_path_translated, &st) == -1 ) { - char *pt = estrdup(script_path_translated); - int len = strlen(pt); - char *ptr; - - while ((ptr = strrchr(pt, '/')) || (ptr = strrchr(pt, '\\'))) { - *ptr = 0; - if (stat(pt, &st) == 0 && S_ISREG(st.st_mode)) { - /* - * okay, we found the base script! - * work out how many chars we had to strip off; - * then we can modify PATH_INFO - * accordingly - * - * we now have the makings of - * PATH_INFO=/test - * SCRIPT_FILENAME=/docroot/info.php - * - * we now need to figure out what docroot is. - * if DOCUMENT_ROOT is set, this is easy, otherwise, - * we have to play the game of hide and seek to figure - * out what SCRIPT_NAME should be - */ - int slen = len - strlen(pt); - int pilen = strlen(env_path_info); - char *path_info = env_path_info + pilen - slen; - - env_path_info = _sapi_cgibin_putenv("PATH_INFO", path_info TSRMLS_CC); - script_path_translated = _sapi_cgibin_putenv("SCRIPT_FILENAME", pt TSRMLS_CC); - TRANSLATE_SLASHES(pt); - - /* figure out docroot - SCRIPT_FILENAME minus SCRIPT_NAME - */ - - if (env_document_root) - { - int l = strlen(env_document_root); - int path_translated_len = 0; - char *path_translated = NULL; - - if (env_document_root[l - 1] == '/') { - --l; - } - - /* we have docroot, so we should have: - * DOCUMENT_ROOT=/docroot - * SCRIPT_FILENAME=/docroot/info.php - * - * SCRIPT_NAME is the portion of the path beyond docroot - */ - env_script_name = _sapi_cgibin_putenv("SCRIPT_NAME", pt + l TSRMLS_CC); - - /* PATH_TRANSATED = DOCUMENT_ROOT + PATH_INFO */ - path_translated_len = l + strlen(env_path_info) + 2; - path_translated = (char *) emalloc(path_translated_len); - *path_translated = 0; - strncat(path_translated, env_document_root, l); - strcat(path_translated, env_path_info); - env_path_translated = _sapi_cgibin_putenv("PATH_TRANSLATED", path_translated TSRMLS_CC); - efree(path_translated); - } else if (env_script_name && - strstr(pt, env_script_name) - ) { - /* PATH_TRANSATED = PATH_TRANSATED - SCRIPT_NAME + PATH_INFO */ - int ptlen = strlen(pt) - strlen(env_script_name); - int path_translated_len = ptlen + strlen(env_path_info) + 2; - char *path_translated = NULL; - - path_translated = (char *) emalloc(path_translated_len); - *path_translated = 0; - strncat(path_translated, pt, ptlen); - strcat(path_translated, env_path_info); - env_path_translated = _sapi_cgibin_putenv("PATH_TRANSLATED", path_translated TSRMLS_CC); - efree(path_translated); - } - break; - } - } - if (!ptr) { - /* - * if we stripped out all the '/' and still didn't find - * a valid path... we will fail, badly. of course we would - * have failed anyway... we output 'no input file' now. - */ - script_path_translated = _sapi_cgibin_putenv("SCRIPT_FILENAME", NULL TSRMLS_CC); - SG(sapi_headers).http_response_code = 404; - } - if (pt) { - efree(pt); - } - } else { - /* make sure path_info/translated are empty */ - script_path_translated = _sapi_cgibin_putenv("SCRIPT_FILENAME", script_path_translated TSRMLS_CC); - _sapi_cgibin_putenv("PATH_INFO", NULL TSRMLS_CC); - _sapi_cgibin_putenv("PATH_TRANSLATED", NULL TSRMLS_CC); - } - SG(request_info).request_uri = sapi_cgibin_getenv("SCRIPT_NAME", sizeof("SCRIPT_NAME")-1 TSRMLS_CC); - } else { -#endif - /* pre 4.3 behaviour, shouldn't be used but provides BC */ - if (env_path_info) { - SG(request_info).request_uri = env_path_info; - } else { - SG(request_info).request_uri = env_script_name; - } -#if !DISCARD_PATH - if (env_path_translated) - script_path_translated = env_path_translated; -#endif -#if ENABLE_PATHINFO_CHECK - } -#endif - SG(request_info).request_method = sapi_cgibin_getenv("REQUEST_METHOD", sizeof("REQUEST_METHOD")-1 TSRMLS_CC); - /* FIXME - Work out proto_num here */ - SG(request_info).query_string = sapi_cgibin_getenv("QUERY_STRING", sizeof("QUERY_STRING")-1 TSRMLS_CC); - /* some server configurations allow '..' to slip through in the - translated path. We'll just refuse to handle such a path. */ - if (script_path_translated && !strstr(script_path_translated, "..")) { - SG(request_info).path_translated = estrdup(script_path_translated); - } - SG(request_info).content_type = (content_type ? content_type : "" ); - SG(request_info).content_length = (content_length ? atoi(content_length) : 0); - - /* The CGI RFC allows servers to pass on unvalidated Authorization data */ - auth = sapi_cgibin_getenv("HTTP_AUTHORIZATION", sizeof("HTTP_AUTHORIZATION")-1 TSRMLS_CC); - php_handle_auth_data(auth TSRMLS_CC); - } -} -/* }}} */ - -#if PHP_FASTCGI -/** - * Clean up child processes upon exit - */ -void fastcgi_cleanup(int signal) -{ -#ifdef DEBUG_FASTCGI - fprintf(stderr, "FastCGI shutdown, pid %d\n", getpid()); -#endif - -#ifndef PHP_WIN32 - sigaction(SIGTERM, &old_term, 0); - - /* Kill all the processes in our process group */ - kill(-pgroup, SIGTERM); -#endif - - /* We should exit at this point, but MacOSX doesn't seem to */ - exit(0); -} -#endif - -#if PHP_FASTCGI -#ifndef PHP_WIN32 -static int is_port_number(const char *bindpath) -{ - while (*bindpath) { - if (*bindpath < '0' || *bindpath > '9') { - return 0; - } - bindpath++; - } - return 1; -} -#endif -#endif - -/* {{{ main - */ -int main(int argc, char *argv[]) -{ - int free_query_string = 0; - int exit_status = SUCCESS; - int cgi = 0, c, i, len; - zend_file_handle file_handle; - int retval = FAILURE; - char *s; -/* temporary locals */ - int behavior = PHP_MODE_STANDARD; - int no_headers = 0; - int orig_optind = php_optind; - char *orig_optarg = php_optarg; - char *script_file = NULL; - int ini_entries_len = 0; -#if FORCE_CGI_REDIRECT - long force_redirect = 1; - char *redirect_status_env = NULL; -#endif - -/* end of temporary locals */ -#ifdef ZTS - zend_compiler_globals *compiler_globals; - zend_executor_globals *executor_globals; - php_core_globals *core_globals; - sapi_globals_struct *sapi_globals; - void ***tsrm_ls; -#endif - -#if PHP_FASTCGI - int max_requests = 500; - int requests = 0; - int fastcgi = fcgi_is_fastcgi(); -#ifndef PHP_WIN32 - char *bindpath = NULL; -#endif - int fcgi_fd = 0; - fcgi_request request; -#ifdef PHP_WIN32 - long impersonate = 0; -#else - int status = 0; -#endif -#endif /* PHP_FASTCGI */ - -#if 0 && defined(PHP_DEBUG) - /* IIS is always making things more difficult. This allows - us to stop PHP and attach a debugger before much gets started */ - { - char szMessage [256]; - wsprintf (szMessage, "Please attach a debugger to the process 0x%X [%d] (%s) and click OK", - GetCurrentProcessId(), GetCurrentProcessId(), argv[0]); - MessageBox(NULL, szMessage, "CGI Debug Time!", MB_OK|MB_SERVICE_NOTIFICATION); - } -#endif - -#ifdef HAVE_SIGNAL_H -#if defined(SIGPIPE) && defined(SIG_IGN) - signal(SIGPIPE, SIG_IGN); /* ignore SIGPIPE in standalone mode so - that sockets created via fsockopen() - don't kill PHP if the remote site - closes it. in apache|apxs mode apache - does that for us! thies@thieso.net - 20000419 */ -#endif -#endif - -#ifdef ZTS - tsrm_startup(1, 1, 0, NULL); -#endif - - sapi_startup(&cgi_sapi_module); - -#ifdef PHP_WIN32 - _fmode = _O_BINARY; /* sets default for file streams to binary */ - setmode(_fileno(stdin), O_BINARY); /* make the stdio mode be binary */ - setmode(_fileno(stdout), O_BINARY); /* make the stdio mode be binary */ - setmode(_fileno(stderr), O_BINARY); /* make the stdio mode be binary */ -#endif - -#if PHP_FASTCGI - if (!fastcgi) { -#endif - /* Make sure we detect we are a cgi - a bit redundancy here, - but the default case is that we have to check only the first one. */ - if (getenv("SERVER_SOFTWARE") || - getenv("SERVER_NAME") || - getenv("GATEWAY_INTERFACE") || - getenv("REQUEST_METHOD") - ) { - cgi = 1; - } -#if PHP_FASTCGI - } -#endif - - while ((c = php_getopt(argc, argv, OPTIONS, &php_optarg, &php_optind, 0)) != -1) { - switch (c) { - case 'c': - cgi_sapi_module.php_ini_path_override = strdup(php_optarg); - break; - case 'n': - cgi_sapi_module.php_ini_ignore = 1; - break; - case 'd': { - /* define ini entries on command line */ - int len = strlen(php_optarg); - char *val; - - if ((val = strchr(php_optarg, '='))) { - val++; - if (!isalnum(*val) && *val != '"' && *val != '\'' && *val != '\0') { - cgi_sapi_module.ini_entries = realloc(cgi_sapi_module.ini_entries, ini_entries_len + len + sizeof("\"\"\n\0")); - memcpy(cgi_sapi_module.ini_entries + ini_entries_len, php_optarg, (val - php_optarg)); - ini_entries_len += (val - php_optarg); - memcpy(cgi_sapi_module.ini_entries + ini_entries_len, "\"", 1); - ini_entries_len++; - memcpy(cgi_sapi_module.ini_entries + ini_entries_len, val, len - (val - php_optarg)); - ini_entries_len += len - (val - php_optarg); - memcpy(cgi_sapi_module.ini_entries + ini_entries_len, "\"\n\0", sizeof("\"\n\0")); - ini_entries_len += sizeof("\n\0\"") - 2; - } else { - cgi_sapi_module.ini_entries = realloc(cgi_sapi_module.ini_entries, ini_entries_len + len + sizeof("\n\0")); - memcpy(cgi_sapi_module.ini_entries + ini_entries_len, php_optarg, len); - memcpy(cgi_sapi_module.ini_entries + ini_entries_len + len, "\n\0", sizeof("\n\0")); - ini_entries_len += len + sizeof("\n\0") - 2; - } - } else { - cgi_sapi_module.ini_entries = realloc(cgi_sapi_module.ini_entries, ini_entries_len + len + sizeof("=1\n\0")); - memcpy(cgi_sapi_module.ini_entries + ini_entries_len, php_optarg, len); - memcpy(cgi_sapi_module.ini_entries + ini_entries_len + len, "=1\n\0", sizeof("=1\n\0")); - ini_entries_len += len + sizeof("=1\n\0") - 2; - } - break; - } -#if PHP_FASTCGI -#ifndef PHP_WIN32 - /* if we're started on command line, check to see if - we are being started as an 'external' fastcgi - server by accepting a bindpath parameter. */ - case 'b': - if (!fastcgi) { - bindpath = strdup(php_optarg); - } - break; -#endif -#endif - } - - } - php_optind = orig_optind; - php_optarg = orig_optarg; - -#ifdef ZTS - compiler_globals = ts_resource(compiler_globals_id); - executor_globals = ts_resource(executor_globals_id); - core_globals = ts_resource(core_globals_id); - sapi_globals = ts_resource(sapi_globals_id); - tsrm_ls = ts_resource(0); - SG(request_info).path_translated = NULL; -#endif - - cgi_sapi_module.executable_location = argv[0]; - - /* startup after we get the above ini override se we get things right */ - if (php_module_startup(&cgi_sapi_module, NULL, 0) == FAILURE) { -#ifdef ZTS - tsrm_shutdown(); -#endif - return FAILURE; - } - -#if FORCE_CGI_REDIRECT - /* check force_cgi after startup, so we have proper output */ - if (cfg_get_long("cgi.force_redirect", &force_redirect) == FAILURE) { - force_redirect = 1; - } - if (cgi && force_redirect) { - if (cfg_get_string("cgi.redirect_status_env", &redirect_status_env) == FAILURE) { - redirect_status_env = NULL; - } - /* Apache will generate REDIRECT_STATUS, - * Netscape and redirect.so will generate HTTP_REDIRECT_STATUS. - * redirect.so and installation instructions available from - * http://www.koehntopp.de/php. - * -- kk@netuse.de - */ - if (!getenv("REDIRECT_STATUS") - && !getenv ("HTTP_REDIRECT_STATUS") - /* this is to allow a different env var to be configured - in case some server does something different than above */ - && (!redirect_status_env || !getenv(redirect_status_env)) - ) { - SG(sapi_headers).http_response_code = 400; - PUTS("<b>Security Alert!</b> The PHP CGI cannot be accessed directly.\n\n\ -<p>This PHP CGI binary was compiled with force-cgi-redirect enabled. This\n\ -means that a page will only be served up if the REDIRECT_STATUS CGI variable is\n\ -set, e.g. via an Apache Action directive.</p>\n\ -<p>For more information as to <i>why</i> this behaviour exists, see the <a href=\"http://php.net/security.cgi-bin\">\ -manual page for CGI security</a>.</p>\n\ -<p>For more information about changing this behaviour or re-enabling this webserver,\n\ -consult the installation file that came with this distribution, or visit \n\ -<a href=\"http://php.net/install.windows\">the manual page</a>.</p>\n"); - -#if defined(ZTS) && !defined(PHP_DEBUG) - /* XXX we're crashing here in msvc6 debug builds at - php_message_handler_for_zend:839 because - SG(request_info).path_translated is an invalid pointer. - It still happens even though I set it to null, so something - weird is going on. - */ - tsrm_shutdown(); -#endif - return FAILURE; - } - } -#endif /* FORCE_CGI_REDIRECT */ - -#if ENABLE_PATHINFO_CHECK - if (cfg_get_long("cgi.fix_pathinfo", &fix_pathinfo) == FAILURE) { - fix_pathinfo = 1; - } -#endif - -#if PHP_FASTCGI - if (cfg_get_long("fastcgi.logging", &fcgi_logging) == FAILURE) { - fcgi_logging = 1; - } -#endif - - /* Check wheater to send RFC2616 style headers compatible with - * PHP versions 4.2.3 and earlier compatible with web servers - * such as IIS. Default is informal CGI RFC header compatible - * with Apache. - */ - if (cfg_get_long("cgi.rfc2616_headers", &rfc2616_headers) == FAILURE) { - rfc2616_headers = 0; - } - - if (cfg_get_long("cgi.nph", &cgi_nph) == FAILURE) { - cgi_nph = 0; - } - -#if PHP_FASTCGI -#ifndef PHP_WIN32 - /* for windows, socket listening is broken in the fastcgi library itself - so dissabling this feature on windows till time is available to fix it */ - if (bindpath) { - /* Pass on the arg to the FastCGI library, with one exception. - * If just a port is specified, then we prepend a ':' onto the - * path (it's what the fastcgi library expects) - */ - if (strchr(bindpath, ':') == NULL && is_port_number(bindpath)) { - char *tmp; - - tmp = malloc(strlen(bindpath) + 2); - tmp[0] = ':'; - memcpy(tmp + 1, bindpath, strlen(bindpath) + 1); - - fcgi_fd = fcgi_listen(tmp, 128); - free(tmp); - } else { - fcgi_fd = fcgi_listen(bindpath, 128); - } - if (fcgi_fd < 0) { - fprintf(stderr, "Couldn't create FastCGI listen socket on port %s\n", bindpath); -#ifdef ZTS - tsrm_shutdown(); -#endif - return FAILURE; - } - fastcgi = fcgi_is_fastcgi(); - } -#endif - if (fastcgi) { - /* How many times to run PHP scripts before dying */ - if (getenv("PHP_FCGI_MAX_REQUESTS")) { - max_requests = atoi(getenv("PHP_FCGI_MAX_REQUESTS")); - if (max_requests < 0) { - fprintf(stderr, "PHP_FCGI_MAX_REQUESTS is not valid\n"); - return FAILURE; - } - } - - /* make php call us to get _ENV vars */ - php_php_import_environment_variables = php_import_environment_variables; - php_import_environment_variables = cgi_php_import_environment_variables; - - /* library is already initialized, now init our request */ - fcgi_init_request(&request, fcgi_fd); - -#ifndef PHP_WIN32 - /* Pre-fork, if required */ - if (getenv("PHP_FCGI_CHILDREN")) { - children = atoi(getenv("PHP_FCGI_CHILDREN")); - if (children < 0) { - fprintf(stderr, "PHP_FCGI_CHILDREN is not valid\n"); - return FAILURE; - } - } - - if (children) { - int running = 0; - pid_t pid; - - /* Create a process group for ourself & children */ - setsid(); - pgroup = getpgrp(); -#ifdef DEBUG_FASTCGI - fprintf(stderr, "Process group %d\n", pgroup); -#endif - - /* Set up handler to kill children upon exit */ - act.sa_flags = 0; - act.sa_handler = fastcgi_cleanup; - if (sigaction(SIGTERM, &act, &old_term) || - sigaction(SIGINT, &act, &old_int) || - sigaction(SIGQUIT, &act, &old_quit)) { - perror("Can't set signals"); - exit(1); - } - - while (parent) { - do { -#ifdef DEBUG_FASTCGI - fprintf(stderr, "Forking, %d running\n", running); -#endif - pid = fork(); - switch (pid) { - case 0: - /* One of the children. - * Make sure we don't go round the - * fork loop any more - */ - parent = 0; - - /* don't catch our signals */ - sigaction(SIGTERM, &old_term, 0); - sigaction(SIGQUIT, &old_quit, 0); - sigaction(SIGINT, &old_int, 0); - break; - case -1: - perror("php (pre-forking)"); - exit(1); - break; - default: - /* Fine */ - running++; - break; - } - } while (parent && (running < children)); - - if (parent) { -#ifdef DEBUG_FASTCGI - fprintf(stderr, "Wait for kids, pid %d\n", getpid()); -#endif - while (wait(&status) < 0) { - } - running--; - } - } - } else { - parent = 0; - } - -#endif /* WIN32 */ - } -#endif /* FASTCGI */ - - zend_first_try { - while ((c = php_getopt(argc, argv, OPTIONS, &php_optarg, &php_optind, 1)) != -1) { - switch (c) { - case 'h': - case '?': - no_headers = 1; - php_output_startup(); - php_output_activate(TSRMLS_C); - SG(headers_sent) = 1; - php_cgi_usage(argv[0]); - php_end_ob_buffers(1 TSRMLS_CC); - exit(1); - break; - } - } - php_optind = orig_optind; - php_optarg = orig_optarg; - -#if PHP_FASTCGI - /* start of FAST CGI loop */ - /* Initialise FastCGI request structure */ -#ifdef PHP_WIN32 - /* attempt to set security impersonation for fastcgi - will only happen on NT based OS, others will ignore it. */ - if (fastcgi) { - if (cfg_get_long("fastcgi.impersonate", &impersonate) == FAILURE) { - impersonate = 0; - } - if (impersonate) fcgi_impersonate(); - } -#endif - while (!fastcgi || fcgi_accept_request(&request) >= 0) { -#endif - -#if PHP_FASTCGI - SG(server_context) = (void *) &request; -#else - SG(server_context) = (void *) 1; /* avoid server_context==NULL checks */ -#endif - init_request_info(TSRMLS_C); - CG(interactive) = 0; - - if (!cgi -#if PHP_FASTCGI - && !fastcgi -#endif - ) { - if (cgi_sapi_module.php_ini_path_override && cgi_sapi_module.php_ini_ignore) { - no_headers = 1; - php_output_startup(); - php_output_activate(TSRMLS_C); - SG(headers_sent) = 1; - php_printf("You cannot use both -n and -c switch. Use -h for help.\n"); - php_end_ob_buffers(1 TSRMLS_CC); - exit(1); - } - - while ((c = php_getopt(argc, argv, OPTIONS, &php_optarg, &php_optind, 0)) != -1) { - switch (c) { - - case 'a': /* interactive mode */ - printf("Interactive mode enabled\n\n"); - CG(interactive) = 1; - break; - - case 'C': /* don't chdir to the script directory */ - SG(options) |= SAPI_OPTION_NO_CHDIR; - break; - - case 'e': /* enable extended info output */ - CG(extended_info) = 1; - break; - - case 'f': /* parse file */ - script_file = estrdup(php_optarg); - no_headers = 1; - /* arguments after the file are considered script args */ - SG(request_info).argc = argc - (php_optind - 1); - SG(request_info).argv = &argv[php_optind - 1]; - break; - - case 'i': /* php info & quit */ - if (php_request_startup(TSRMLS_C) == FAILURE) { - php_module_shutdown(TSRMLS_C); - return FAILURE; - } - if (no_headers) { - SG(headers_sent) = 1; - SG(request_info).no_headers = 1; - } - php_print_info(0xFFFFFFFF TSRMLS_CC); - php_end_ob_buffers(1 TSRMLS_CC); - exit(0); - break; - - case 'l': /* syntax check mode */ - no_headers = 1; - behavior = PHP_MODE_LINT; - break; - - case 'm': /* list compiled in modules */ - php_output_startup(); - php_output_activate(TSRMLS_C); - SG(headers_sent) = 1; - php_printf("[PHP Modules]\n"); - print_modules(TSRMLS_C); - php_printf("\n[Zend Modules]\n"); - print_extensions(TSRMLS_C); - php_printf("\n"); - php_end_ob_buffers(1 TSRMLS_CC); - exit(0); - break; - -#if 0 /* not yet operational, see also below ... */ - case '': /* generate indented source mode*/ - behavior=PHP_MODE_INDENT; - break; -#endif - - case 'q': /* do not generate HTTP headers */ - no_headers = 1; - break; - - case 's': /* generate highlighted HTML from source */ - behavior = PHP_MODE_HIGHLIGHT; - break; - - case 'v': /* show php version & quit */ - no_headers = 1; - if (php_request_startup(TSRMLS_C) == FAILURE) { - php_module_shutdown(TSRMLS_C); - return FAILURE; - } - if (no_headers) { - SG(headers_sent) = 1; - SG(request_info).no_headers = 1; - } -#if ZEND_DEBUG - php_printf("PHP %s (%s) (built: %s %s) (DEBUG)\nCopyright (c) 1997-2006 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version()); -#else - php_printf("PHP %s (%s) (built: %s %s)\nCopyright (c) 1997-2006 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version()); -#endif - php_end_ob_buffers(1 TSRMLS_CC); - exit(0); - break; - - case 'w': - behavior = PHP_MODE_STRIP; - break; - - case 'z': /* load extension file */ - zend_load_extension(php_optarg); - break; - - default: - break; - } - } - - if (script_file) { - /* override path_translated if -f on command line */ - STR_FREE(SG(request_info).path_translated); - SG(request_info).path_translated = script_file; - } - - if (no_headers) { - SG(headers_sent) = 1; - SG(request_info).no_headers = 1; - } - - if (!SG(request_info).path_translated && argc > php_optind) { - /* arguments after the file are considered script args */ - SG(request_info).argc = argc - php_optind; - SG(request_info).argv = &argv[php_optind]; - /* file is on command line, but not in -f opt */ - SG(request_info).path_translated = estrdup(argv[php_optind++]); - } - - /* all remaining arguments are part of the query string - this section of code concatenates all remaining arguments - into a single string, seperating args with a & - this allows command lines like: - - test.php v1=test v2=hello+world! - test.php "v1=test&v2=hello world!" - test.php v1=test "v2=hello world!" - */ - if (!SG(request_info).query_string && argc > php_optind) { - len = 0; - for (i = php_optind; i < argc; i++) { - len += strlen(argv[i]) + 1; - } - - s = malloc(len + 1); - *s = '\0'; /* we are pretending it came from the environment */ - for (i = php_optind, len = 0; i < argc; i++) { - strcat(s, argv[i]); - if (i < (argc - 1)) { - strcat(s, PG(arg_separator).input); - } - } - SG(request_info).query_string = s; - free_query_string = 1; - } - } /* end !cgi && !fastcgi */ - - /* - we never take stdin if we're (f)cgi, always - rely on the web server giving us the info - we need in the environment. - */ - if (SG(request_info).path_translated || cgi -#if PHP_FASTCGI - || fastcgi -#endif - ) - { - file_handle.type = ZEND_HANDLE_FILENAME; - file_handle.filename = SG(request_info).path_translated; - file_handle.handle.fp = NULL; - } else { - file_handle.filename = "-"; - file_handle.type = ZEND_HANDLE_FP; - file_handle.handle.fp = stdin; - } - - file_handle.opened_path = NULL; - file_handle.free_filename = 0; - - /* request startup only after we've done all we can to - get path_translated */ - if (php_request_startup(TSRMLS_C) == FAILURE) { -#if PHP_FASTCGI - if (fastcgi) { - fcgi_finish_request(&request); - } -#endif - php_module_shutdown(TSRMLS_C); - return FAILURE; - } - if (no_headers) { - SG(headers_sent) = 1; - SG(request_info).no_headers = 1; - } - - /* - at this point path_translated will be set if: - 1. we are running from shell and got filename was there - 2. we are running as cgi or fastcgi - */ - if (cgi || SG(request_info).path_translated) { - retval = php_fopen_primary_script(&file_handle TSRMLS_CC); - } - /* - if we are unable to open path_translated and we are not - running from shell (so fp == NULL), then fail. - */ - if (retval == FAILURE && file_handle.handle.fp == NULL) { - SG(sapi_headers).http_response_code = 404; - PUTS("No input file specified.\n"); -#if PHP_FASTCGI - /* we want to serve more requests if this is fastcgi - so cleanup and continue, request shutdown is - handled later */ - if (fastcgi) { - goto fastcgi_request_done; - } -#endif - php_request_shutdown((void *) 0); - php_module_shutdown(TSRMLS_C); - return FAILURE; - } - - if (file_handle.handle.fp && (file_handle.handle.fp != stdin)) { - /* #!php support */ - c = fgetc(file_handle.handle.fp); - if (c == '#') { - while (c != '\n' && c != '\r') { - c = fgetc(file_handle.handle.fp); /* skip to end of line */ - } - /* handle situations where line is terminated by \r\n */ - if (c == '\r') { - if (fgetc(file_handle.handle.fp) != '\n') { - long pos = ftell(file_handle.handle.fp); - fseek(file_handle.handle.fp, pos - 1, SEEK_SET); - } - } - CG(start_lineno) = 2; - } else { - rewind(file_handle.handle.fp); - } - } - - switch (behavior) { - case PHP_MODE_STANDARD: - php_execute_script(&file_handle TSRMLS_CC); - break; - case PHP_MODE_LINT: - PG(during_request_startup) = 0; - exit_status = php_lint_script(&file_handle TSRMLS_CC); - if (exit_status == SUCCESS) { - zend_printf("No syntax errors detected in %s\n", file_handle.filename); - } else { - zend_printf("Errors parsing %s\n", file_handle.filename); - } - break; - case PHP_MODE_STRIP: - if (open_file_for_scanning(&file_handle TSRMLS_CC) == SUCCESS) { - zend_strip(TSRMLS_C); - fclose(file_handle.handle.fp); - php_end_ob_buffers(1 TSRMLS_CC); - } - return SUCCESS; - break; - case PHP_MODE_HIGHLIGHT: - { - zend_syntax_highlighter_ini syntax_highlighter_ini; - - if (open_file_for_scanning(&file_handle TSRMLS_CC) == SUCCESS) { - php_get_highlight_struct(&syntax_highlighter_ini); - zend_highlight(&syntax_highlighter_ini TSRMLS_CC); - fclose(file_handle.handle.fp); - php_end_ob_buffers(1 TSRMLS_CC); - } - return SUCCESS; - } - break; -#if 0 - /* Zeev might want to do something with this one day */ - case PHP_MODE_INDENT: - open_file_for_scanning(&file_handle TSRMLS_CC); - zend_indent(); - fclose(file_handle.handle.fp); - return SUCCESS; - break; -#endif - } - -#if PHP_FASTCGI -fastcgi_request_done: -#endif - { - char *path_translated; - - /* Go through this trouble so that the memory manager doesn't warn - * about SG(request_info).path_translated leaking - */ - if (SG(request_info).path_translated) { - path_translated = strdup(SG(request_info).path_translated); - STR_FREE(SG(request_info).path_translated); - SG(request_info).path_translated = path_translated; - } - - php_request_shutdown((void *) 0); - if (exit_status == 0) { - exit_status = EG(exit_status); - } - - if (SG(request_info).path_translated) { - free(SG(request_info).path_translated); - SG(request_info).path_translated = NULL; - } - if (free_query_string && SG(request_info).query_string) { - free(SG(request_info).query_string); - SG(request_info).query_string = NULL; - } - - } - -#if PHP_FASTCGI - if (!fastcgi) break; - /* only fastcgi will get here */ - requests++; - if (max_requests && (requests == max_requests)) { - fcgi_finish_request(&request); -#ifndef PHP_WIN32 - if (bindpath) { - free(bindpath); - } -#endif - break; - } - /* end of fastcgi loop */ - } -#endif - - if (cgi_sapi_module.php_ini_path_override) { - free(cgi_sapi_module.php_ini_path_override); - } - if (cgi_sapi_module.ini_entries) { - free(cgi_sapi_module.ini_entries); - } - } zend_catch { - exit_status = 255; - } zend_end_try(); - - SG(server_context) = NULL; - php_module_shutdown(TSRMLS_C); - sapi_shutdown(); - -#ifdef ZTS - /*tsrm_shutdown();*/ -#endif - -#if defined(PHP_WIN32) && ZEND_DEBUG && 0 - _CrtDumpMemoryLeaks(); -#endif - - return exit_status; -} -/* }}} */ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/sapi/cgi/config.w32 b/sapi/cgi/config.w32 deleted file mode 100644 index 663e182888..0000000000 --- a/sapi/cgi/config.w32 +++ /dev/null @@ -1,26 +0,0 @@ -// vim:ft=javascript -// $Id$ - -ARG_ENABLE('cgi', 'Build CGI version of PHP', 'yes'); -ARG_ENABLE('fastcgi', 'Build FastCGI support into CGI binary', 'yes'); -ARG_ENABLE('path-info-check', - 'If this is disabled, paths such as /info.php/test?a=b will fail to work', 'yes'); - -ARG_ENABLE("force-cgi-redirect", "Enable the security check for internal \ -server redirects. You should use this if you are running the CGI \ -version with Apache.", "yes"); - -AC_DEFINE("FORCE_CGI_REDIRECT", PHP_FORCE_CGI_REDIRECT == "yes" ? 1 : 0, "CGI redirect mode"); -AC_DEFINE("ENABLE_PATHINFO_CHECK", PHP_PATH_INFO_CHECK == "yes" ? 1 : 0, "Pathinfo check"); - -if (PHP_CGI == "yes") { - AC_DEFINE('PHP_FASTCGI', PHP_FASTCGI == "yes" ? 1 : 0); - ADD_FLAG("LDFLAGS_CGI", "/stack:8388608"); - - if (PHP_FASTCGI == "yes") { - SAPI('cgi', 'cgi_main.c getopt.c fastcgi.c', 'php-cgi.exe'); - ADD_FLAG('LIBS_CGI', 'ws2_32.lib kernel32.lib advapi32.lib'); - } else { - SAPI('cgi', 'cgi_main.c getopt.c', 'php-cgi.exe'); - } -} diff --git a/sapi/cgi/config9.m4 b/sapi/cgi/config9.m4 deleted file mode 100644 index b31adabacc..0000000000 --- a/sapi/cgi/config9.m4 +++ /dev/null @@ -1,167 +0,0 @@ -dnl -dnl $Id$ -dnl - -AC_ARG_ENABLE(cgi, -[ --disable-cgi Disable building CGI version of PHP], -[ - PHP_SAPI_CGI=$enableval -],[ - PHP_SAPI_CGI=yes -]) - -AC_ARG_ENABLE(force-cgi-redirect, -[ --enable-force-cgi-redirect - CGI: Enable the security check for internal server - redirects. You should use this if you are - running the CGI version with Apache], -[ - PHP_FORCE_CGI_REDIRECT=$enableval -],[ - PHP_FORCE_CGI_REDIRECT=no -]) - -AC_ARG_ENABLE(discard-path, -[ --enable-discard-path CGI: If this is enabled, the PHP CGI binary - can safely be placed outside of the - web tree and people will not be able - to circumvent .htaccess security], -[ - PHP_DISCARD_PATH=$enableval -],[ - PHP_DISCARD_PATH=no -]) - -AC_ARG_ENABLE(fastcgi, -[ --enable-fastcgi CGI: If this is enabled, the cgi module will - be built with support for fastcgi also], -[ - PHP_ENABLE_FASTCGI=$enableval -],[ - PHP_ENABLE_FASTCGI=no -]) - -AC_ARG_ENABLE(path-info-check, -[ --disable-path-info-check CGI: If this is disabled, paths such as - /info.php/test?a=b will fail to work], -[ - PHP_ENABLE_PATHINFO_CHECK=$enableval -],[ - PHP_ENABLE_PATHINFO_CHECK=yes -]) - -AC_DEFUN([PHP_TEST_WRITE_STDOUT],[ - AC_CACHE_CHECK(whether writing to stdout works,ac_cv_write_stdout,[ - AC_TRY_RUN([ -#ifdef HAVE_UNISTD_H -#include <unistd.h> -#endif - -#define TEXT "This is the test message -- " - -main() -{ - int n; - - n = write(1, TEXT, sizeof(TEXT)-1); - return (!(n == sizeof(TEXT)-1)); -} - ],[ - ac_cv_write_stdout=yes - ],[ - ac_cv_write_stdout=no - ],[ - ac_cv_write_stdout=no - ]) - ]) - if test "$ac_cv_write_stdout" = "yes"; then - AC_DEFINE(PHP_WRITE_STDOUT, 1, [whether write(2) works]) - fi -]) - - -if test "$PHP_SAPI" = "default"; then - AC_MSG_CHECKING(for CGI build) - if test "$PHP_SAPI_CGI" != "no"; then - AC_MSG_RESULT(yes) - - PHP_ADD_MAKEFILE_FRAGMENT($abs_srcdir/sapi/cgi/Makefile.frag) - case $host_alias in - *cygwin* ) - SAPI_CGI_PATH=sapi/cgi/php.exe - ;; - * ) - SAPI_CGI_PATH=sapi/cgi/php - ;; - esac - PHP_SUBST(SAPI_CGI_PATH) - - PHP_TEST_WRITE_STDOUT - - AC_MSG_CHECKING(whether to force Apache CGI redirect) - if test "$PHP_FORCE_CGI_REDIRECT" = "yes"; then - REDIRECT=1 - else - REDIRECT=0 - fi - AC_DEFINE_UNQUOTED(FORCE_CGI_REDIRECT,$REDIRECT,[ ]) - AC_MSG_RESULT($PHP_FORCE_CGI_REDIRECT) - - - AC_MSG_CHECKING(whether to discard path_info + path_translated) - if test "$PHP_DISCARD_PATH" = "yes"; then - DISCARD_PATH=1 - else - DISCARD_PATH=0 - fi - AC_DEFINE_UNQUOTED(DISCARD_PATH, $DISCARD_PATH, [ ]) - AC_MSG_RESULT($PHP_DISCARD_PATH) - - AC_MSG_CHECKING(whether to enable path info checking) - if test "$PHP_ENABLE_PATHINFO_CHECK" = "yes"; then - ENABLE_PATHINFO_CHECK=1 - else - ENABLE_PATHINFO_CHECK=0 - fi - AC_DEFINE_UNQUOTED(ENABLE_PATHINFO_CHECK, $ENABLE_PATHINFO_CHECK, [ ]) - AC_MSG_RESULT($PHP_ENABLE_PATHINFO_CHECK) - - AC_MSG_CHECKING(whether to enable fastcgi support) - if test "$PHP_ENABLE_FASTCGI" = "yes"; then - PHP_FASTCGI=1 - PHP_FCGI_FILES="fastcgi.c" - PHP_FCGI_STATIC=1 - else - PHP_FASTCGI=0 - PHP_FCGI_FILES="" - PHP_FCGI_STATIC=0 - fi - AC_DEFINE_UNQUOTED(PHP_FASTCGI, $PHP_FASTCGI, [ ]) - AC_DEFINE_UNQUOTED(PHP_FCGI_STATIC, $PHP_FCGI_STATIC, [ ]) - AC_MSG_RESULT($PHP_ENABLE_FASTCGI) - - INSTALL_IT="@echo \"Installing PHP CGI into: \$(INSTALL_ROOT)\$(bindir)/\"; \$(INSTALL) -m 0755 \$(SAPI_CGI_PATH) \$(INSTALL_ROOT)\$(bindir)/\$(program_prefix)php\$(program_suffix)\$(EXEEXT)" - PHP_SELECT_SAPI(cgi, program, $PHP_FCGI_FILES cgi_main.c getopt.c, , '$(SAPI_CGI_PATH)') - - case $host_alias in - *aix*) - BUILD_CGI="echo '\#! .' > php.sym && echo >>php.sym && nm -BCpg \`echo \$(PHP_GLOBAL_OBJS) \$(PHP_SAPI_OBJS) | sed 's/\([A-Za-z0-9_]*\)\.lo/\1.o/g'\` | \$(AWK) '{ if (((\$\$2 == \"T\") || (\$\$2 == \"D\") || (\$\$2 == \"B\")) && (substr(\$\$3,1,1) != \".\")) { print \$\$3 } }' | sort -u >> php.sym && \$(LIBTOOL) --mode=link \$(CC) -export-dynamic \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) -Wl,-brtl -Wl,-bE:php.sym \$(PHP_RPATHS) \$(PHP_GLOBAL_OBJS) \$(PHP_SAPI_OBJS) \$(EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_CGI_PATH)" - ;; - *darwin*) - BUILD_CGI="\$(CC) \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) \$(NATIVE_RPATHS) \$(PHP_GLOBAL_OBJS:.lo=.o) \$(PHP_SAPI_OBJS:.lo=.o) \$(PHP_FRAMEWORKS) \$(EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_CGI_PATH)" - ;; - *) - BUILD_CGI="\$(LIBTOOL) --mode=link \$(CC) -export-dynamic \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) \$(PHP_RPATHS) \$(PHP_GLOBAL_OBJS) \$(PHP_SAPI_OBJS) \$(EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_CGI_PATH)" - ;; - esac - - PHP_SUBST(BUILD_CGI) - - elif test "$PHP_SAPI_CLI" != "no"; then - AC_MSG_RESULT(no) - OVERALL_TARGET= - PHP_SAPI=cli - else - AC_MSG_ERROR([No SAPIs selected.]) - fi -fi diff --git a/sapi/cgi/fastcgi.c b/sapi/cgi/fastcgi.c deleted file mode 100644 index cd38e584d7..0000000000 --- a/sapi/cgi/fastcgi.c +++ /dev/null @@ -1,926 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP Version 5 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2006 The PHP Group | - +----------------------------------------------------------------------+ - | This source file is subject to version 3.01 of the PHP license, | - | that is bundled with this package in the file LICENSE, and is | - | available through the world-wide-web at the following url: | - | http://www.php.net/license/3_01.txt | - | If you did not receive a copy of the PHP license and are unable to | - | obtain it through the world-wide-web, please send a note to | - | license@php.net so we can mail you a copy immediately. | - +----------------------------------------------------------------------+ - | Authors: Dmitry Stogov <dmitry@zend.com> | - +----------------------------------------------------------------------+ -*/ - -/* $Id$ */ - -#include "php.h" -#include "fastcgi.h" - -#include <string.h> -#include <stdlib.h> -#include <stdio.h> -#include <stdarg.h> -#include <errno.h> - -#ifdef _WIN32 - -#include <windows.h> - - typedef unsigned int size_t; - - struct sockaddr_un { - short sun_family; - char sun_path[MAXPATHLEN]; - }; - - static HANDLE fcgi_accept_mutex = INVALID_HANDLE_VALUE; - static int is_impersonate = 0; - -#define FCGI_LOCK(fd) \ - if (fcgi_accept_mutex != INVALID_HANDLE_VALUE) { \ - DWORD ret; \ - while ((ret = WaitForSingleObject(fcgi_accept_mutex, 1000)) == WAIT_TIMEOUT) { \ - if (in_shutdown) return -1; \ - } \ - if (ret == WAIT_FAILED) { \ - fprintf(stderr, "WaitForSingleObject() failed\n"); \ - return -1; \ - } \ - } - -#define FCGI_UNLOCK(fd) \ - if (fcgi_accept_mutex != INVALID_HANDLE_VALUE) { \ - ReleaseMutex(fcgi_accept_mutex); \ - } - -#else - -# include <sys/types.h> -# include <sys/stat.h> -# include <unistd.h> -# include <fcntl.h> -# include <sys/socket.h> -# include <sys/un.h> -# include <netinet/in.h> -# include <arpa/inet.h> -# include <netdb.h> -# include <signal.h> - -#ifndef INADDR_NONE -#define INADDR_NONE ((unsigned long) -1) -#endif - -# ifndef HAVE_SOCKLEN_T - typedef unsigned int socklen_t; -# endif - -# ifdef USE_LOCKING -# define FCGI_LOCK(fd) \ - do { \ - struct flock lock; \ - lock.l_type = F_WRLCK; \ - lock.l_start = 0; \ - lock.l_whence = SEEK_SET; \ - lock.l_len = 0; \ - if (fcntl(fd, F_SETLKW, &lock) != -1) { \ - break; \ - } else if (errno != EINTR || in_shutdown) { \ - return -1; \ - } \ - } while (1) - -# define FCGI_UNLOCK(fd) \ - do { \ - int orig_errno = errno; \ - while (1) { \ - struct flock lock; \ - lock.l_type = F_UNLCK; \ - lock.l_start = 0; \ - lock.l_whence = SEEK_SET; \ - lock.l_len = 0; \ - if (fcntl(fd, F_SETLK, &lock) != -1) { \ - break; \ - } else if (errno != EINTR) { \ - return -1; \ - } \ - } \ - errno = orig_errno; \ - } while (0) -# else -# define FCGI_LOCK(fd) -# define FCGI_UNLOCK(fd) -# endif - -#endif - -typedef union _sa_t { - struct sockaddr sa; - struct sockaddr_un sa_unix; - struct sockaddr_in sa_inet; -} sa_t; - -typedef struct _fcgi_mgmt_rec { - char* name; - size_t name_len; - char val; -} fcgi_mgmt_rec; - -static const fcgi_mgmt_rec fcgi_mgmt_vars[] = { - {"FCGI_MAX_CONNS", sizeof("FCGI_MAX_CONNS")-1, 1}, - {"FCGI_MAX_REQS", sizeof("FCGI_MAX_REQS")-1, 1}, - {"FCGI_MPXS_CONNS", sizeof("FCGI_MPXS_CONNS")-1, 0} -}; - - -static int is_initialized = 0; -static int is_fastcgi = 0; -static int in_shutdown = 0; - -#ifdef _WIN32 - -static DWORD WINAPI fcgi_shutdown_thread(LPVOID arg) -{ - HANDLE shutdown_event = (HANDLE) arg; - WaitForSingleObject(shutdown_event, INFINITE); - in_shutdown = 1; - return 0; -} - -#else - -static void fcgi_signal_handler(int signo) -{ - if (signo == SIGUSR1 || signo == SIGTERM) { - in_shutdown = 1; - } -} - -#endif - -int fcgi_init(void) -{ - if (!is_initialized) { -#ifdef _WIN32 -# if 0 - /* TODO: Support for TCP sockets */ - WSADATA wsaData; - - if (WSAStartup(MAKEWORD(2,0), &wsaData)) { - fprintf(stderr, "Error starting Windows Sockets. Error: %d", WSAGetLastError()); - return 0; - } -# endif - is_initialized = 1; - - if ((GetStdHandle(STD_OUTPUT_HANDLE) == INVALID_HANDLE_VALUE) && - (GetStdHandle(STD_ERROR_HANDLE) == INVALID_HANDLE_VALUE) && - (GetStdHandle(STD_INPUT_HANDLE) != INVALID_HANDLE_VALUE)) { - char *str; - DWORD pipe_mode = PIPE_READMODE_BYTE | PIPE_WAIT; - HANDLE pipe = GetStdHandle(STD_INPUT_HANDLE); - - SetNamedPipeHandleState(pipe, &pipe_mode, NULL, NULL); - - str = getenv("_FCGI_SHUTDOWN_EVENT_"); - if (str != NULL) { - HANDLE shutdown_event = (HANDLE) atoi(str); - if (!CreateThread(NULL, 0, fcgi_shutdown_thread, - shutdown_event, 0, NULL)) { - return -1; - } - } - str = getenv("_FCGI_MUTEX_"); - if (str != NULL) { - fcgi_accept_mutex = (HANDLE) atoi(str); - } - return is_fastcgi = 1; - } else { - return is_fastcgi = 0; - } -#else - sa_t sa; - socklen_t len = sizeof(sa); - - is_initialized = 1; - errno = 0; - if (getpeername(0, (struct sockaddr *)&sa, &len) != 0 && errno == ENOTCONN) { - struct sigaction new_sa, old_sa; - - sigemptyset(&new_sa.sa_mask); - new_sa.sa_flags = 0; - new_sa.sa_handler = fcgi_signal_handler; - sigaction(SIGUSR1, &new_sa, NULL); - sigaction(SIGTERM, &new_sa, NULL); - sigaction(SIGPIPE, NULL, &old_sa); - if (old_sa.sa_handler == SIG_DFL) { - sigaction(SIGPIPE, &new_sa, NULL); - } - - return is_fastcgi = 1; - } else { - return is_fastcgi = 0; - } -#endif - } - return is_fastcgi; -} - - -int fcgi_is_fastcgi(void) -{ - if (!is_initialized) { - return fcgi_init(); - } else { - return is_fastcgi; - } -} - -int fcgi_listen(const char *path, int backlog) -{ -#ifdef _WIN32 - /* TODO: Support for manual binding on TCP sockets (php -b <port>) */ - return -1; -#else - char *s; - int tcp = 0; - char host[MAXPATHLEN]; - short port = 0; - int listen_socket; - sa_t sa; - socklen_t sock_len; - - if ((s = strchr(path, ':'))) { - port = atoi(s+1); - if (port != 0 && (s-path) < MAXPATHLEN) { - strncpy(host, path, s-path); - host[s-path] = '\0'; - tcp = 1; - } - } - - /* Prepare socket address */ - if (tcp) { - memset(&sa.sa_inet, 0, sizeof(sa.sa_inet)); - sa.sa_inet.sin_family = AF_INET; - sa.sa_inet.sin_port = htons(port); - sock_len = sizeof(sa.sa_inet); - - if (!*host || !strncmp(host, "*", sizeof("*")-1)) { - sa.sa_inet.sin_addr.s_addr = htonl(INADDR_ANY); - } else { - sa.sa_inet.sin_addr.s_addr = inet_addr(host); - if (sa.sa_inet.sin_addr.s_addr == INADDR_NONE) { - struct hostent *hep; - - hep = gethostbyname(host); - if (!hep || hep->h_addrtype != AF_INET || !hep->h_addr_list[0]) { - fprintf(stderr, "Cannot resolve host name '%s'!\n", host); - return -1; - } else if (hep->h_addr_list[1]) { - fprintf(stderr, "Host '%s' has multiple addresses. You must choose one explicitly!\n", host); - return -1; - } - sa.sa_inet.sin_addr.s_addr = ((struct in_addr*)hep->h_addr_list[0])->s_addr; - } - } - } else { - int path_len = strlen(path); - - if (path_len >= sizeof(sa.sa_unix.sun_path)) { - fprintf(stderr, "Listening socket's path name is too long.\n"); - return -1; - } - - memset(&sa.sa_unix, 0, sizeof(sa.sa_unix)); - sa.sa_unix.sun_family = AF_UNIX; - memcpy(sa.sa_unix.sun_path, path, path_len + 1); - sock_len = (size_t)(((struct sockaddr_un *)0)->sun_path) + path_len; -#ifdef HAVE_SOCKADDR_UN_SUN_LEN - sa.sa_unix.sun_len = sock_len; -#endif - unlink(path); - } - - /* Create, bind socket and start listen on it */ - if ((listen_socket = socket(sa.sa.sa_family, SOCK_STREAM, 0)) < 0 || - bind(listen_socket, (struct sockaddr *) &sa, sock_len) < 0 || - listen(listen_socket, backlog) < 0) { - - fprintf(stderr, "Cannot bind/listen socket - [%d] %s.\n",errno, strerror(errno)); - return -1; - } - - if (!tcp) { - chmod(path, 0777); - } - - if (!is_initialized) { - fcgi_init(); - } - is_fastcgi = 1; - return listen_socket; -#endif -} - -void fcgi_init_request(fcgi_request *req, int listen_socket) -{ - memset(req, 0, sizeof(fcgi_request)); - req->listen_socket = listen_socket; - req->fd = -1; - req->id = -1; - - req->in_len = 0; - req->in_pad = 0; - - req->out_hdr = NULL; - req->out_pos = req->out_buf; -} - -static inline ssize_t safe_write(fcgi_request *req, const void *buf, size_t count) -{ - int ret; - size_t n = 0; - - do { - ret = write(req->fd, ((char*)buf)+n, count-n); - if (ret > 0) { - n += ret; - } else if (ret <= 0 && errno != 0 && errno != EINTR) { - return ret; - } - } while (n != count); - return n; -} - -static inline ssize_t safe_read(fcgi_request *req, const void *buf, size_t count) -{ - int ret; - size_t n = 0; - - do { - ret = read(req->fd, ((char*)buf)+n, count-n); - if (ret > 0) { - n += ret; - } else if (ret == 0 && errno == 0) { - return n; - } else if (ret <= 0 && errno != 0 && errno != EINTR) { - return ret; - } - } while (n != count); - return n; -} - -static inline int fcgi_make_header(fcgi_header *hdr, fcgi_request_type type, int req_id, int len) -{ - int pad = ((len + 7) & ~7) - len; - - hdr->contentLengthB0 = (unsigned char)(len & 0xff); - hdr->contentLengthB1 = (unsigned char)((len >> 8) & 0xff); - hdr->paddingLength = (unsigned char)pad; - hdr->requestIdB0 = (unsigned char)(req_id & 0xff); - hdr->requestIdB1 = (unsigned char)((req_id >> 8) & 0xff); - hdr->reserved = 0; - hdr->type = type; - hdr->version = FCGI_VERSION_1; - return pad; -} - -static void fcgi_get_params(fcgi_request *req, unsigned char *p, unsigned char *end) -{ - char buf[128]; - char *tmp = buf; - int buf_size = sizeof(buf); - int name_len, val_len; - char *s; - - while (p < end) { - name_len = *p++; - if (name_len >= 128) { - name_len = ((name_len & 0x7f) << 24); - name_len |= (*p++ << 16); - name_len |= (*p++ << 8); - name_len |= *p++; - } - val_len = *p++; - if (val_len >= 128) { - val_len = ((val_len & 0x7f) << 24); - val_len |= (*p++ << 16); - val_len |= (*p++ << 8); - val_len |= *p++; - } - if (name_len+1 >= buf_size) { - buf_size = name_len + 64; - tmp = (tmp == buf ? emalloc(buf_size): erealloc(tmp, buf_size)); - } - memcpy(tmp, p, name_len); - tmp[name_len] = 0; - s = zend_strndup((char*)p + name_len, val_len); - zend_hash_update(&req->env, tmp, name_len+1, &s, sizeof(char*), NULL); - p += name_len + val_len; - } - if (tmp != buf && tmp != NULL) { - efree(tmp); - } -} - -static void fcgi_free_var(char **s) -{ - free(*s); -} - -static int fcgi_read_request(fcgi_request *req) -{ - fcgi_header hdr; - int len, padding; - unsigned char buf[FCGI_MAX_LENGTH+8]; - - req->keep = 0; - req->in_len = 0; - req->out_hdr = NULL; - req->out_pos = req->out_buf; - zend_hash_init(&req->env, 0, NULL, (void (*)(void *)) fcgi_free_var, 1); - - if (safe_read(req, &hdr, sizeof(fcgi_header)) != sizeof(fcgi_header) || - hdr.version < FCGI_VERSION_1) { - return 0; - } - - len = (hdr.contentLengthB1 << 8) | hdr.contentLengthB0; - padding = hdr.paddingLength; - - while (hdr.type == FCGI_STDIN && len == 0) { - if (safe_read(req, &hdr, sizeof(fcgi_header)) != sizeof(fcgi_header) || - hdr.version < FCGI_VERSION_1) { - return 0; - } - - len = (hdr.contentLengthB1 << 8) | hdr.contentLengthB0; - padding = hdr.paddingLength; - } - - req->id = (hdr.requestIdB1 << 8) + hdr.requestIdB0; - - if (hdr.type == FCGI_BEGIN_REQUEST && len == sizeof(fcgi_begin_request)) { - char *val; - - if (safe_read(req, buf, len+padding) != len+padding) { - return 0; - } - - req->keep = (((fcgi_begin_request*)buf)->flags & FCGI_KEEP_CONN); - switch ((((fcgi_begin_request*)buf)->roleB1 << 8) + ((fcgi_begin_request*)buf)->roleB0) { - case FCGI_RESPONDER: - val = strdup("RESPONDER"); - zend_hash_update(&req->env, "FCGI_ROLE", sizeof("FCGI_ROLE"), &val, sizeof(char*), NULL); - break; - case FCGI_AUTHORIZER: - val = strdup("AUTHORIZER"); - zend_hash_update(&req->env, "FCGI_ROLE", sizeof("FCGI_ROLE"), &val, sizeof(char*), NULL); - break; - case FCGI_FILTER: - val = strdup("FILTER"); - zend_hash_update(&req->env, "FCGI_ROLE", sizeof("FCGI_ROLE"), &val, sizeof(char*), NULL); - break; - default: - return 0; - } - - if (safe_read(req, &hdr, sizeof(fcgi_header)) != sizeof(fcgi_header) || - hdr.version < FCGI_VERSION_1) { - return 0; - } - - len = (hdr.contentLengthB1 << 8) | hdr.contentLengthB0; - padding = hdr.paddingLength; - - while (hdr.type == FCGI_PARAMS && len > 0) { - if (safe_read(req, buf, len+padding) != len+padding) { - req->keep = 0; - return 0; - } - fcgi_get_params(req, buf, buf+len); - - if (safe_read(req, &hdr, sizeof(fcgi_header)) != sizeof(fcgi_header) || - hdr.version < FCGI_VERSION_1) { - req->keep = 0; - return 0; - } - len = (hdr.contentLengthB1 << 8) | hdr.contentLengthB0; - padding = hdr.paddingLength; - } - } else if (hdr.type == FCGI_GET_VALUES) { - int j; - unsigned char *p = buf + sizeof(fcgi_header); - - if (safe_read(req, buf, len+padding) != len+padding) { - return 0; - } - fcgi_get_params(req, buf, buf+len); - - for (j = 0; j < sizeof(fcgi_mgmt_vars)/sizeof(fcgi_mgmt_vars[0]); j++) { - if (zend_hash_exists(&req->env, fcgi_mgmt_vars[j].name, fcgi_mgmt_vars[j].name_len+1) == 0) { - sprintf((char*)p, "%c%c%s%c", fcgi_mgmt_vars[j].name_len, 1, fcgi_mgmt_vars[j].name, fcgi_mgmt_vars[j].val); - p += fcgi_mgmt_vars[j].name_len + 3; - } - } - len = p - buf - sizeof(fcgi_header); - len += fcgi_make_header((fcgi_header*)buf, FCGI_GET_VALUES_RESULT, 0, len); - if (safe_write(req, buf, sizeof(fcgi_header)+len) != (int)sizeof(fcgi_header)+len) { - return 0; - } - return 0; - } else { - return 0; - } - - return 1; -} - -int fcgi_read(fcgi_request *req, char *str, int len) -{ - int ret, n, rest; - fcgi_header hdr; - unsigned char buf[8]; - - n = 0; - rest = len; - while (rest > 0) { - if (req->in_len == 0) { - if (safe_read(req, &hdr, sizeof(fcgi_header)) != sizeof(fcgi_header) || - hdr.version < FCGI_VERSION_1 || - hdr.type != FCGI_STDIN) { - req->keep = 0; - return 0; - } - req->in_len = (hdr.contentLengthB1 << 8) | hdr.contentLengthB0; - req->in_pad = hdr.paddingLength; - if (req->in_len == 0) { - return n; - } - } - - if (req->in_len >= rest) { - ret = safe_read(req, str, rest); - } else { - ret = safe_read(req, str, req->in_len); - } - if (ret < 0) { - req->keep = 0; - return ret; - } else if (ret > 0) { - req->in_len -= ret; - rest -= ret; - n += ret; - str += ret; - if (req->in_len == 0) { - if (req->in_pad) { - if (safe_read(req, buf, req->in_pad) != req->in_pad) { - req->keep = 0; - return ret; - } - } - } else { - return n; - } - } else { - return n; - } - } - return n; -} - -static inline void fcgi_close(fcgi_request *req, int force, int destroy) -{ - if (destroy) { - zend_hash_destroy(&req->env); - } - if ((force || !req->keep) && req->fd >= 0) { -#ifdef _WIN32 - HANDLE pipe = (HANDLE)_get_osfhandle(req->fd); - - if (!force) { - FlushFileBuffers(pipe); - } - DisconnectNamedPipe(pipe); - if (is_impersonate) { - RevertToSelf(); - } -#else - if (!force) { - char buf[8]; - - shutdown(req->fd, 1); - while (recv(req->fd, buf, sizeof(buf), 0) > 0) {} - } - close(req->fd); -#endif - req->fd = -1; - } -} - -int fcgi_accept_request(fcgi_request *req) -{ -#ifdef _WIN32 - HANDLE pipe; - OVERLAPPED ov; -#endif - fcgi_finish_request(req); - - while (1) { - if (req->fd < 0) { - while (1) { - if (in_shutdown) { - return -1; - } -#ifdef _WIN32 - pipe = (HANDLE)_get_osfhandle(req->listen_socket); - - FCGI_LOCK(req->listen_socket); - ov.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); - if (!ConnectNamedPipe(pipe, &ov)) { - errno = GetLastError(); - if (errno == ERROR_IO_PENDING) { - while (WaitForSingleObject(ov.hEvent, 1000) == WAIT_TIMEOUT) { - if (in_shutdown) { - CloseHandle(ov.hEvent); - FCGI_UNLOCK(req->listen_socket); - return -1; - } - } - } else if (errno != ERROR_PIPE_CONNECTED) { - } - } - CloseHandle(ov.hEvent); - if (is_impersonate && !ImpersonateNamedPipeClient(pipe)) { - DisconnectNamedPipe(pipe); - req->fd = -1; - } else { - req->fd = req->listen_socket; - } - FCGI_UNLOCK(req->listen_socket); -#else - { - sa_t sa; - socklen_t len = sizeof(sa); - - FCGI_LOCK(req->listen_socket); - req->fd = accept(req->listen_socket, (struct sockaddr *)&sa, &len); - FCGI_UNLOCK(req->listen_socket); - } -#endif - - if (req->fd < 0 && (in_shutdown || errno != EINTR)) { - return -1; - } - -#ifdef _WIN32 - break; -#else - if (req->fd >= 0) { - struct timeval tv = {5,0}; - fd_set set; - - FD_ZERO(&set); - FD_SET(req->fd, &set); -try_again: - errno = 0; - if (select(req->fd + 1, &set, NULL, NULL, &tv) >= 0 && FD_ISSET(req->fd, &set)) { - break; - } - if (errno == EINTR) goto try_again; - fcgi_close(req, 1, 0); - } -#endif - } - } else if (in_shutdown) { - return -1; - } - if (fcgi_read_request(req)) { - return req->fd; - } else { - fcgi_close(req, 1, 1); - } - } -} - -static inline fcgi_header* open_packet(fcgi_request *req, fcgi_request_type type) -{ - req->out_hdr = (fcgi_header*) req->out_pos; - req->out_hdr->type = type; - req->out_pos += sizeof(fcgi_header); - return req->out_hdr; -} - -static inline void close_packet(fcgi_request *req) -{ - if (req->out_hdr) { - int len = req->out_pos - ((unsigned char*)req->out_hdr + sizeof(fcgi_header)); - - req->out_pos += fcgi_make_header(req->out_hdr, (fcgi_request_type)req->out_hdr->type, req->id, len); - req->out_hdr = NULL; - } -} - -int fcgi_flush(fcgi_request *req, int close) -{ - int len; - - close_packet(req); - - len = req->out_pos - req->out_buf; - - if (close) { - fcgi_end_request_rec *rec = (fcgi_end_request_rec*)(req->out_pos); - - fcgi_make_header(&rec->hdr, FCGI_END_REQUEST, req->id, sizeof(fcgi_end_request)); - rec->body.appStatusB3 = 0; - rec->body.appStatusB2 = 0; - rec->body.appStatusB1 = 0; - rec->body.appStatusB0 = 0; - rec->body.protocolStatus = FCGI_REQUEST_COMPLETE; - len += sizeof(fcgi_end_request_rec); - } - - if (safe_write(req, req->out_buf, len) != len) { - req->keep = 0; - return 0; - } - - req->out_pos = req->out_buf; - return 1; -} - -int fcgi_write(fcgi_request *req, fcgi_request_type type, const char *str, int len) -{ - int limit, rest; - - if (len <= 0) { - return 0; - } - - if (req->out_hdr && req->out_hdr->type != type) { - close_packet(req); - } -#if 0 - /* Unoptimized, but clear version */ - rest = len; - while (rest > 0) { - limit = sizeof(req->out_buf) - (req->out_pos - req->out_buf); - - if (!req->out_hdr) { - if (limit < sizeof(fcgi_header)) { - if (!fcgi_flush(req, 0)) { - return -1; - } - } - open_packet(req, type); - } - limit = sizeof(req->out_buf) - (req->out_pos - req->out_buf); - if (rest < limit) { - memcpy(req->out_pos, str, rest); - req->out_pos += rest; - return len; - } else { - memcpy(req->out_pos, str, limit); - req->out_pos += limit; - rest -= limit; - str += limit; - if (!fcgi_flush(req, 0)) { - return -1; - } - } - } -#else - /* Optimized version */ - limit = sizeof(req->out_buf) - (req->out_pos - req->out_buf); - if (!req->out_hdr) { - limit -= sizeof(fcgi_header); - if (limit < 0) limit = 0; - } - - if (len < limit) { - if (!req->out_hdr) { - open_packet(req, type); - } - memcpy(req->out_pos, str, len); - req->out_pos += len; - } else if (len - limit < sizeof(req->out_buf) - sizeof(fcgi_header)) { - if (!req->out_hdr) { - open_packet(req, type); - } - if (limit > 0) { - memcpy(req->out_pos, str, limit); - req->out_pos += limit; - } - if (!fcgi_flush(req, 0)) { - return -1; - } - if (len > limit) { - open_packet(req, type); - memcpy(req->out_pos, str + limit, len - limit); - req->out_pos += len - limit; - } - } else { - int pos = 0; - int pad; - - close_packet(req); - while ((len - pos) > 0xffff) { - open_packet(req, type); - fcgi_make_header(req->out_hdr, type, req->id, 0xfff8); - req->out_hdr = NULL; - if (!fcgi_flush(req, 0)) { - return -1; - } - if (safe_write(req, str + pos, 0xfff8) != 0xfff8) { - req->keep = 0; - return -1; - } - pos += 0xfff8; - } - - pad = (((len - pos) + 7) & ~7) - (len - pos); - rest = pad ? 8 - pad : 0; - - open_packet(req, type); - fcgi_make_header(req->out_hdr, type, req->id, (len - pos) - rest); - req->out_hdr = NULL; - if (!fcgi_flush(req, 0)) { - return -1; - } - if (safe_write(req, str + pos, (len - pos) - rest) != (len - pos) - rest) { - req->keep = 0; - return -1; - } - if (pad) { - open_packet(req, type); - memcpy(req->out_pos, str + len - rest, rest); - req->out_pos += rest; - } - } -#endif - return len; -} - -int fcgi_finish_request(fcgi_request *req) -{ - if (req->fd >= 0) { - fcgi_flush(req, 1); - fcgi_close(req, 0, 1); - } - return 1; -} - -char* fcgi_getenv(fcgi_request *req, const char* var, int var_len) -{ - char **val; - - if (!req) return NULL; - - if (zend_hash_find(&req->env, (char*)var, var_len+1, (void**)&val) == SUCCESS) { - return *val; - } - return NULL; -} - -char* fcgi_putenv(fcgi_request *req, char* var, int var_len, char* val) -{ - if (var && req) { - char **ret; - - if (val == NULL) { - val = ""; - } - val = strdup(val); - if (zend_hash_update(&req->env, var, var_len+1, &val, sizeof(char*), (void**)&ret) == SUCCESS) { - return *ret; - } - } - return NULL; -} - -#ifdef _WIN32 -void fcgi_impersonate(void) -{ - char *os_name; - - os_name = getenv("OS"); - if (os_name && stricmp(os_name, "Windows_NT") == 0) { - is_impersonate = 1; - } -} -#endif - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/sapi/cgi/fastcgi.h b/sapi/cgi/fastcgi.h deleted file mode 100644 index ba648f3ea5..0000000000 --- a/sapi/cgi/fastcgi.h +++ /dev/null @@ -1,136 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP Version 5 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2006 The PHP Group | - +----------------------------------------------------------------------+ - | This source file is subject to version 3.01 of the PHP license, | - | that is bundled with this package in the file LICENSE, and is | - | available through the world-wide-web at the following url: | - | http://www.php.net/license/3_01.txt | - | If you did not receive a copy of the PHP license and are unable to | - | obtain it through the world-wide-web, please send a note to | - | license@php.net so we can mail you a copy immediately. | - +----------------------------------------------------------------------+ - | Authors: Dmitry Stogov <dmitry@zend.com> | - +----------------------------------------------------------------------+ -*/ - -/* $Id$ */ - -/* FastCGI protocol */ - -#define FCGI_VERSION_1 1 - -#define FCGI_MAX_LENGTH 0xffff - -#define FCGI_KEEP_CONN 1 - -typedef enum _fcgi_role { - FCGI_RESPONDER = 1, - FCGI_AUTHORIZER = 2, - FCGI_FILTER = 3 -} fcgi_role; - -typedef enum _fcgi_request_type { - FCGI_BEGIN_REQUEST = 1, /* [in] */ - FCGI_ABORT_REQUEST = 2, /* [in] (not supported) */ - FCGI_END_REQUEST = 3, /* [out] */ - FCGI_PARAMS = 4, /* [in] environment variables */ - FCGI_STDIN = 5, /* [in] post data */ - FCGI_STDOUT = 6, /* [out] response */ - FCGI_STDERR = 7, /* [out] errors */ - FCGI_DATA = 8, /* [in] filter data (not supported) */ - FCGI_GET_VALUES = 9, /* [in] */ - FCGI_GET_VALUES_RESULT = 10 /* [out] */ -} fcgi_request_type; - -typedef enum _fcgi_protocol_status { - FCGI_REQUEST_COMPLETE = 0, - FCGI_CANT_MPX_CONN = 1, - FCGI_OVERLOADED = 2, - FCGI_UNKNOWN_ROLE = 3 -} dcgi_protocol_status; - -typedef struct _fcgi_header { - unsigned char version; - unsigned char type; - unsigned char requestIdB1; - unsigned char requestIdB0; - unsigned char contentLengthB1; - unsigned char contentLengthB0; - unsigned char paddingLength; - unsigned char reserved; -} fcgi_header; - -typedef struct _fcgi_begin_request { - unsigned char roleB1; - unsigned char roleB0; - unsigned char flags; - unsigned char reserved[5]; -} fcgi_begin_request; - -typedef struct _fcgi_begin_request_rec { - fcgi_header hdr; - fcgi_begin_request body; -} fcgi_begin_request_rec; - -typedef struct _fcgi_end_request { - unsigned char appStatusB3; - unsigned char appStatusB2; - unsigned char appStatusB1; - unsigned char appStatusB0; - unsigned char protocolStatus; - unsigned char reserved[3]; -} fcgi_end_request; - -typedef struct _fcgi_end_request_rec { - fcgi_header hdr; - fcgi_end_request body; -} fcgi_end_request_rec; - -/* FastCGI client API */ - -typedef struct _fcgi_request { - int listen_socket; - int fd; - int id; - int keep; - - int in_len; - int in_pad; - - fcgi_header *out_hdr; - unsigned char *out_pos; - unsigned char out_buf[1024*8]; - unsigned char reserved[sizeof(fcgi_end_request_rec)]; - - HashTable env; -} fcgi_request; - -int fcgi_init(void); -int fcgi_is_fastcgi(void); -int fcgi_listen(const char *path, int backlog); -void fcgi_init_request(fcgi_request *req, int listen_socket); -int fcgi_accept_request(fcgi_request *req); -int fcgi_finish_request(fcgi_request *req); - -char* fcgi_getenv(fcgi_request *req, const char* var, int var_len); -char* fcgi_putenv(fcgi_request *req, char* var, int var_len, char* val); - -int fcgi_read(fcgi_request *req, char *str, int len); - -int fcgi_write(fcgi_request *req, fcgi_request_type type, const char *str, int len); -int fcgi_flush(fcgi_request *req, int close); - -#ifdef PHP_WIN32 -void fcgi_impersonate(void); -#endif -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/sapi/cgi/getopt.c b/sapi/cgi/getopt.c deleted file mode 100644 index 1c86f1e4eb..0000000000 --- a/sapi/cgi/getopt.c +++ /dev/null @@ -1,154 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP Version 5 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2006 The PHP Group | - +----------------------------------------------------------------------+ - | This source file is subject to version 3.01 of the PHP license, | - | that is bundled with this package in the file LICENSE, and is | - | available through the world-wide-web at the following url: | - | http://www.php.net/license/3_01.txt | - | If you did not receive a copy of the PHP license and are unable to | - | obtain it through the world-wide-web, please send a note to | - | license@php.net so we can mail you a copy immediately. | - +----------------------------------------------------------------------+ - | Author: Marcus Boerger <helly@php.net> | - +----------------------------------------------------------------------+ -*/ - -#include <stdio.h> -#include <string.h> -#include <assert.h> -#include <stdlib.h> -#include "php_getopt.h" -#define OPTERRCOLON (1) -#define OPTERRNF (2) -#define OPTERRARG (3) - - -static int php_opt_error(int argc, char * const *argv, int oint, int optchr, int err, int show_err) -{ - if (show_err) - { - fprintf(stderr, "Error in argument %d, char %d: ", oint, optchr+1); - switch(err) - { - case OPTERRCOLON: - fprintf(stderr, ": in flags\n"); - break; - case OPTERRNF: - fprintf(stderr, "option not found %c\n", argv[oint][optchr]); - break; - case OPTERRARG: - fprintf(stderr, "no argument for option %c\n", argv[oint][optchr]); - break; - default: - fprintf(stderr, "unknown\n"); - break; - } - } - return('?'); -} - -int php_getopt(int argc, char* const *argv, const opt_struct opts[], char **optarg, int *optind, int show_err) -{ - static int optchr = 0; - static int dash = 0; /* have already seen the - */ - int arg_start = 2; - - int opts_idx = -1; - - if (*optind >= argc) { - return(EOF); - } - if (!dash) { - if ((argv[*optind][0] != '-')) { - return(EOF); - } else { - if (!argv[*optind][1]) - { - /* - * use to specify stdin. Need to let pgm process this and - * the following args - */ - return(EOF); - } - } - } - if ((argv[*optind][0] == '-') && (argv[*optind][1] == '-')) { - /* '--' indicates end of args if not followed by a known long option name */ - while (1) { - opts_idx++; - if (opts[opts_idx].opt_char == '-') { - (*optind)++; - return(EOF); - } else if (opts[opts_idx].opt_name && !strcmp(&argv[*optind][2], opts[opts_idx].opt_name)) { - break; - } - } - optchr = 0; - dash = 1; - arg_start = 2 + strlen(opts[opts_idx].opt_name); - } - if (!dash) { - dash = 1; - optchr = 1; - } - - /* Check if the guy tries to do a -: kind of flag */ - if (argv[*optind][optchr] == ':') { - dash = 0; - (*optind)++; - return (php_opt_error(argc, argv, *optind-1, optchr, OPTERRCOLON, show_err)); - } - if (opts_idx < 0) { - while (1) { - opts_idx++; - if (opts[opts_idx].opt_char == '-') { - int errind = *optind; - int errchr = optchr; - - if (!argv[*optind][optchr+1]) { - dash = 0; - (*optind)++; - } else { - optchr++; - } - return(php_opt_error(argc, argv, errind, errchr, OPTERRNF, show_err)); - } else if (argv[*optind][optchr] == opts[opts_idx].opt_char) { - break; - } - } - } - if (opts[opts_idx].need_param) { - /* Check for cases where the value of the argument - is in the form -<arg> <val> or in the form -<arg><val> */ - dash = 0; - if(!argv[*optind][arg_start]) { - (*optind)++; - if (*optind == argc) { - return(php_opt_error(argc, argv, *optind-1, optchr, OPTERRARG, show_err)); - } - *optarg = argv[(*optind)++]; - } else { - *optarg = &argv[*optind][arg_start]; - (*optind)++; - } - return opts[opts_idx].opt_char; - } else { - if (arg_start == 2) { - if (!argv[*optind][optchr+1]) - { - dash = 0; - (*optind)++; - } else { - optchr++; - } - } else { - (*optind)++; - } - return opts[opts_idx].opt_char; - } - assert(0); - return(0); /* never reached */ -} diff --git a/sapi/cgi/php.sym b/sapi/cgi/php.sym deleted file mode 100644 index e69de29bb2..0000000000 --- a/sapi/cgi/php.sym +++ /dev/null diff --git a/sapi/cgi/php_getopt.h b/sapi/cgi/php_getopt.h deleted file mode 100644 index ad10f423bb..0000000000 --- a/sapi/cgi/php_getopt.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP Version 5 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2006 The PHP Group | - +----------------------------------------------------------------------+ - | This source file is subject to version 3.01 of the PHP license, | - | that is bundled with this package in the file LICENSE, and is | - | available through the world-wide-web at the following url: | - | http://www.php.net/license/3_01.txt | - | If you did not receive a copy of the PHP license and are unable to | - | obtain it through the world-wide-web, please send a note to | - | license@php.net so we can mail you a copy immediately. | - +----------------------------------------------------------------------+ - | Author: Marcus Boerger <helly@php.net> | - +----------------------------------------------------------------------+ -*/ - -#include "php.h" - -/* Define structure for one recognized option (both single char and long name). - * If short_open is '-' this is the last option. - */ -typedef struct _opt_struct { - const char opt_char; - const int need_param; - const char * opt_name; -} opt_struct; - -int php_getopt(int argc, char* const *argv, const opt_struct opts[], char **optarg, int *optind, int show_err); |