php-src/sapi/cgi/cgi_main.c

1120 lines
28 KiB
C
Raw Normal View History

1999-07-16 13:13:16 +00:00
/*
+----------------------------------------------------------------------+
2001-12-11 15:32:16 +00:00
| PHP Version 4 |
1999-07-16 13:13:16 +00:00
+----------------------------------------------------------------------+
2001-12-11 15:32:16 +00:00
| Copyright (c) 1997-2002 The PHP Group |
1999-07-16 13:13:16 +00:00
+----------------------------------------------------------------------+
| This source file is subject to version 2.02 of the PHP license, |
1999-07-16 13:13:16 +00:00
| that is bundled with this package in the file LICENSE, and is |
| available at through the world-wide-web at |
| http://www.php.net/license/2_02.txt. |
1999-07-16 13:13:16 +00:00
| 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@fast.no> |
| Zeev Suraski <zeev@zend.com> |
2002-03-10 22:08:09 +00:00
| FastCGI: Ben Mansell <php@slimyhorror.com> |
| Shane Caraveo <shane@caraveo.com> |
1999-07-16 13:13:16 +00:00
+----------------------------------------------------------------------+
*/
1999-04-25 19:36:57 +00:00
#include "php.h"
#include "php_globals.h"
#include "php_variables.h"
#include "zend_modules.h"
1999-04-25 19:36:57 +00:00
#include "SAPI.h"
#include <stdio.h>
#include "php.h"
2000-02-11 15:59:30 +00:00
#ifdef PHP_WIN32
1999-04-25 19:36:57 +00:00
#include "win32/time.h"
#include "win32/signal.h"
#include <process.h>
#else
#include "build-defs.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
#include "zend.h"
2000-05-05 07:18:50 +00:00
#include "zend_extensions.h"
1999-04-25 19:36:57 +00:00
#include "php_ini.h"
#include "php_globals.h"
2000-06-05 23:24:42 +00:00
#include "php_main.h"
2001-02-23 22:07:16 +00:00
#include "fopen_wrappers.h"
#include "ext/standard/php_standard.h"
2000-04-20 13:23:19 +00:00
#ifdef PHP_WIN32
1999-04-25 19:36:57 +00:00
#include <io.h>
#include <fcntl.h>
#include "win32/php_registry.h"
#endif
#if HAVE_SIGNAL_H
#include <signal.h>
#endif
2001-11-04 12:46:30 +00:00
#ifdef __riscos__
#include <unixlib/local.h>
#endif
1999-04-25 19:36:57 +00:00
#include "zend_compile.h"
#include "zend_execute.h"
#include "zend_highlight.h"
#include "zend_indent.h"
#include "php_getopt.h"
1999-04-25 19:36:57 +00:00
#ifdef PHP_FASTCGI
#include "fcgi_config.h"
#include "fcgiapp.h"
/* don't want to include fcgios.h, causes conflicts */
extern int OS_SetImpersonate(void);
FCGX_Stream *in, *out, *err;
FCGX_ParamArray envp;
/* Our original environment from when the FastCGI first started */
char **orig_env;
/* The environment given by the FastCGI */
char **cgi_env;
/* The manufactured environment, from merging the base environ with
* the parameters set by the per-connection environment
*/
char **merge_env;
/**
* 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
2002-05-09 20:03:36 +00:00
#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
1999-04-25 19:36:57 +00:00
2000-02-10 16:44:59 +00:00
extern char *ap_php_optarg;
extern int ap_php_optind;
1999-04-25 19:36:57 +00:00
#define OPTSTRING "aCc:d:ef:g:hilmnqsw?vz:"
2001-07-31 04:53:54 +00:00
static int _print_module_info(zend_module_entry *module, void *arg TSRMLS_DC)
{
2002-05-09 20:03:36 +00:00
php_printf("%s\n", module->name);
return 0;
}
1999-04-25 19:36:57 +00:00
2002-01-18 20:27:09 +00:00
static int _print_extension_info(zend_extension *module, void *arg TSRMLS_DC)
{
2002-05-09 20:03:36 +00:00
php_printf("%s\n", module->name);
return 0;
2002-01-18 20:27:09 +00:00
}
#ifndef STDOUT_FILENO
#define STDOUT_FILENO 1
#endif
static inline size_t sapi_cgibin_single_write(const char *str, uint str_length)
{
#ifdef PHP_WRITE_STDOUT
2002-05-09 20:03:36 +00:00
long ret;
#else
2002-05-09 20:03:36 +00:00
size_t ret;
#endif
#ifdef PHP_FASTCGI
2002-05-09 20:03:36 +00:00
if (!FCGX_IsCGI()) {
return FCGX_PutStr( str, str_length, out );
}
#endif
#ifdef PHP_WRITE_STDOUT
2002-05-09 20:03:36 +00:00
ret = write(STDOUT_FILENO, str, str_length);
if (ret <= 0) return 0;
return ret;
#else
2002-05-09 20:03:36 +00:00
ret = fwrite(str, 1, MIN(str_length, 16384), stdout);
return ret;
#endif
}
2001-08-05 15:29:47 +00:00
static int sapi_cgibin_ub_write(const char *str, uint str_length TSRMLS_DC)
1999-04-25 19:36:57 +00:00
{
2002-05-09 20:03:36 +00:00
const char *ptr = str;
uint remaining = str_length;
size_t ret;
while (remaining > 0)
{
ret = sapi_cgibin_single_write(ptr, remaining);
if (!ret) {
php_handle_aborted_connection();
}
ptr += ret;
remaining -= ret;
}
return str_length;
1999-04-25 19:36:57 +00:00
}
static void sapi_cgibin_flush(void *server_context)
{
#ifdef PHP_FASTCGI
2002-05-09 20:03:36 +00:00
if (!FCGX_IsCGI()) {
if( FCGX_FFlush( out ) == -1 ) {
php_handle_aborted_connection();
}
} else
#endif
2002-05-09 20:03:36 +00:00
if (fflush(stdout)==EOF) {
php_handle_aborted_connection();
}
}
2001-07-31 04:53:54 +00:00
static void sapi_cgi_send_header(sapi_header_struct *sapi_header, void *server_context TSRMLS_DC)
{
2002-05-09 20:03:36 +00:00
if (sapi_header) {
PHPWRITE_H(sapi_header->header, sapi_header->header_len);
}
PHPWRITE_H("\r\n", 2);
}
static int sapi_cgi_read_post(char *buffer, uint count_bytes TSRMLS_DC)
{
2002-05-09 20:03:36 +00:00
uint read_bytes=0, tmp_read_bytes;
#ifdef PHP_FASTCGI
2002-05-09 20:03:36 +00:00
char *pos = buffer;
#endif
2002-05-09 20:03:36 +00:00
count_bytes = MIN(count_bytes, (uint)SG(request_info).content_length-SG(read_post_bytes));
while (read_bytes < count_bytes) {
#ifdef PHP_FASTCGI
2002-05-09 20:03:36 +00:00
if (!FCGX_IsCGI()) {
tmp_read_bytes = FCGX_GetStr( pos, count_bytes-read_bytes, in );
pos += tmp_read_bytes;
} else
#endif
2002-05-09 20:03:36 +00:00
tmp_read_bytes = read(0, buffer+read_bytes, count_bytes-read_bytes);
if (tmp_read_bytes<=0) {
break;
}
read_bytes += tmp_read_bytes;
}
return read_bytes;
}
static char *sapi_cgi_read_cookies(TSRMLS_D)
{
2002-05-09 20:03:36 +00:00
return getenv("HTTP_COOKIE");
}
static void sapi_cgi_register_variables(zval *track_vars_array TSRMLS_DC)
{
2002-05-09 20:03:36 +00:00
/* In CGI mode, we consider the environment to be a part of the server
* variables
*/
php_import_environment_variables(track_vars_array TSRMLS_CC);
2002-05-09 20:03:36 +00:00
/* 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);
}
2000-02-10 15:55:10 +00:00
static void sapi_cgi_log_message(char *message)
{
2002-05-09 20:03:36 +00:00
if (php_header()) {
fprintf(stderr, "%s", message);
fprintf(stderr, "\n");
}
2000-02-10 15:55:10 +00:00
}
static int sapi_cgi_deactivate(TSRMLS_D)
2000-02-10 16:44:59 +00:00
{
2002-05-09 20:03:36 +00:00
fflush(stdout);
if(SG(request_info).argv0) {
free(SG(request_info).argv0);
SG(request_info).argv0 = NULL;
}
return SUCCESS;
2000-02-10 16:44:59 +00:00
}
2000-02-10 15:55:10 +00:00
/* {{{ sapi_module_struct cgi_sapi_module
*/
static sapi_module_struct cgi_sapi_module = {
2002-05-09 20:03:36 +00:00
"cgi", /* name */
#ifdef PHP_FASTCGI
2002-05-09 20:03:36 +00:00
"CGI/FastCGI", /* pretty name */
#else
2002-05-09 20:03:36 +00:00
"CGI", /* pretty name */
#endif
2002-05-09 20:03:36 +00:00
php_module_startup, /* startup */
php_module_shutdown_wrapper, /* shutdown */
2002-05-09 20:03:36 +00:00
NULL, /* activate */
sapi_cgi_deactivate, /* deactivate */
2000-02-10 16:44:59 +00:00
2002-05-09 20:03:36 +00:00
sapi_cgibin_ub_write, /* unbuffered write */
sapi_cgibin_flush, /* flush */
NULL, /* get uid */
NULL, /* getenv */
2002-05-09 20:03:36 +00:00
php_error, /* error handler */
2002-05-09 20:03:36 +00:00
NULL, /* header handler */
NULL, /* send headers handler */
sapi_cgi_send_header, /* send header handler */
2002-05-09 20:03:36 +00:00
sapi_cgi_read_post, /* read POST data */
sapi_cgi_read_cookies, /* read Cookies */
2002-05-09 20:03:36 +00:00
sapi_cgi_register_variables, /* register server variables */
sapi_cgi_log_message, /* Log message */
2002-05-09 20:03:36 +00:00
NULL, /* Block interruptions */
NULL, /* Unblock interruptions */
2000-02-10 18:44:33 +00:00
2002-05-09 20:03:36 +00:00
STANDARD_SAPI_MODULE_PROPERTIES
1999-04-25 19:36:57 +00:00
};
/* }}} */
1999-04-25 19:36:57 +00:00
/* {{{ php_cgi_usage
*/
static void php_cgi_usage(char *argv0)
{
2002-05-09 20:03:36 +00:00
char *prog;
prog = strrchr(argv0, '/');
if (prog) {
prog++;
} else {
prog = "php";
}
php_printf("Usage: %s [-q] [-h] [-s [-v] [-i] [-f <file>] | {<file> [args...]}\n"
" -q Quiet-mode. Suppress HTTP Header output.\n"
" -s Display colour syntax highlighted source.\n"
" -w Display source with stripped comments and whitespace.\n"
" -f <file> Parse <file>. Implies `-q'\n"
" -v Version number\n"
" -C Do not chdir to the script's directory\n"
" -c <path>|<file> Look for php.ini file in this directory\n"
" -a Run interactively\n"
" -d foo[=bar] Define INI entry foo with value 'bar'\n"
" -e Generate extended information for debugger/profiler\n"
" -z <file> Load Zend extension <file>.\n"
" -l Syntax check only (lint)\n"
" -m Show compiled in modules\n"
" -i PHP information\n"
" -h This help\n", prog);
}
/* }}} */
/* {{{ init_request_info
2001-06-06 13:24:17 +00:00
*/
static void init_request_info(TSRMLS_D)
1999-05-02 19:54:02 +00:00
{
2002-05-09 20:03:36 +00:00
char *content_length = getenv("CONTENT_LENGTH");
char *content_type = getenv("CONTENT_TYPE");
const char *auth;
#if 0
/* SG(request_info).path_translated is always set to NULL at the end of this function
call so why the hell did this code exist in the first place? Am I missing something? */
2002-05-09 20:03:36 +00:00
char *script_filename;
2000-02-10 20:03:17 +00:00
2002-05-09 20:03:36 +00:00
script_filename = getenv("SCRIPT_FILENAME");
/* Hack for annoying servers that do not set SCRIPT_FILENAME for us */
if (!script_filename) {
script_filename = SG(request_info).argv0;
}
2000-02-11 15:59:30 +00:00
#ifdef PHP_WIN32
2002-05-09 20:03:36 +00:00
/* FIXME WHEN APACHE NT IS FIXED */
/* a hack for apache nt because it does not appear to set argv[1] and sets
script filename to php.exe thus makes us parse php.exe instead of file.php
requires we get the info from path translated. This can be removed at
such a time that apache nt is fixed */
if (!script_filename) {
script_filename = getenv("PATH_TRANSLATED");
}
2000-02-10 20:03:17 +00:00
#endif
2002-05-09 20:03:36 +00:00
/* doc_root configuration variable is currently ignored,
as it is with every other access method currently also. */
2000-02-10 20:03:17 +00:00
2002-05-09 20:03:36 +00:00
/* We always need to emalloc() filename, since it gets placed into
the include file hash table, and gets freed with that table.
Notice that this means that we don't need to efree() it in
php_destroy_request_info()! */
2000-02-10 20:03:17 +00:00
#if DISCARD_PATH
2002-05-09 20:03:36 +00:00
if (script_filename) {
SG(request_info).path_translated = estrdup(script_filename);
} else {
SG(request_info).path_translated = NULL;
}
2000-02-10 20:03:17 +00:00
#endif
#endif /* 0 */
2002-05-09 20:03:36 +00:00
SG(request_info).request_method = getenv("REQUEST_METHOD");
SG(request_info).query_string = getenv("QUERY_STRING");
SG(request_info).request_uri = getenv("PATH_INFO");
if (!SG(request_info).request_uri) {
SG(request_info).request_uri = getenv("SCRIPT_NAME");
}
SG(request_info).path_translated = NULL; /* we have to update it later, when we have that information */
SG(request_info).content_type = (content_type ? content_type : "" );
SG(request_info).content_length = (content_length?atoi(content_length):0);
SG(sapi_headers).http_response_code = 200;
/* The CGI RFC allows servers to pass on unvalidated Authorization data */
auth = getenv("HTTP_AUTHORIZATION");
php_handle_auth_data(auth TSRMLS_CC);
1999-05-02 19:54:02 +00:00
}
/* }}} */
1999-05-02 19:54:02 +00:00
1999-12-05 16:25:32 +00:00
static void define_command_line_ini_entry(char *arg)
1999-08-28 23:06:07 +00:00
{
2002-05-09 20:03:36 +00:00
char *name, *value;
name = arg;
value = strchr(arg, '=');
if (value) {
*value = 0;
value++;
} else {
value = "1";
}
zend_alter_ini_entry(name, strlen(name)+1, value, strlen(value), PHP_INI_SYSTEM, PHP_INI_STAGE_ACTIVATE);
1999-08-28 23:06:07 +00:00
}
2001-07-31 04:53:54 +00:00
static void php_register_command_line_global_vars(char **arg TSRMLS_DC)
2000-05-04 13:42:21 +00:00
{
2002-05-09 20:03:36 +00:00
char *var, *val;
var = *arg;
val = strchr(var, '=');
if (!val) {
printf("No value specified for variable '%s'\n", var);
} else {
*val++ = '\0';
php_register_variable(var, val, NULL TSRMLS_CC);
}
efree(*arg);
2000-05-04 13:42:21 +00:00
}
/* {{{ main
*/
1999-04-25 19:36:57 +00:00
int main(int argc, char *argv[])
{
2002-05-09 20:03:36 +00:00
int exit_status = SUCCESS;
int cgi = 0, c, i, len;
zend_file_handle file_handle;
int retval = FAILURE;
char *s;
1999-04-25 19:36:57 +00:00
/* temporary locals */
2002-05-09 20:03:36 +00:00
int behavior=PHP_MODE_STANDARD;
int no_headers=0;
int orig_optind=ap_php_optind;
char *orig_optarg=ap_php_optarg;
char *argv0=NULL;
char *script_file=NULL;
zend_llist global_vars;
int interactive=0;
2002-03-06 13:25:25 +00:00
#if FORCE_CGI_REDIRECT
2002-05-09 20:03:36 +00:00
int force_redirect = 1;
char *redirect_status_env = NULL;
2002-03-06 13:25:25 +00:00
#endif
1999-04-25 19:36:57 +00:00
/* end of temporary locals */
#ifdef ZTS
2002-05-09 20:03:36 +00:00
zend_compiler_globals *compiler_globals;
zend_executor_globals *executor_globals;
php_core_globals *core_globals;
sapi_globals_struct *sapi_globals;
void ***tsrm_ls;
1999-04-25 19:36:57 +00:00
#endif
#ifdef PHP_FASTCGI
2002-05-09 20:03:36 +00:00
int env_size, cgi_env_size;
int max_requests = 500;
int requests = 0;
int fastcgi = !FCGX_IsCGI();
#ifdef PHP_WIN32
2002-05-09 20:03:36 +00:00
int impersonate = 0;
#endif
2002-05-09 20:03:36 +00:00
if (fastcgi) {
/* Calculate environment size */
env_size = 0;
while( environ[ env_size ] ) { env_size++; }
/* Also include the final NULL pointer */
env_size++;
/* Allocate for our environment */
orig_env = malloc( env_size * sizeof( char *));
if( !orig_env ) {
perror( "Can't malloc environment" );
exit( 1 );
}
memcpy( orig_env, environ, env_size * sizeof( char *));
}
#endif
1999-04-25 19:36:57 +00:00
#ifdef HAVE_SIGNAL_H
2000-04-20 07:35:22 +00:00
#if defined(SIGPIPE) && defined(SIG_IGN)
2002-05-09 20:03:36 +00:00
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
2000-04-19 17:28:23 +00:00
#endif
1999-05-02 19:01:45 +00:00
#ifdef ZTS
2002-05-09 20:03:36 +00:00
tsrm_startup(1, 1, 0, NULL);
1999-05-02 19:01:45 +00:00
#endif
2002-05-09 20:03:36 +00:00
sapi_startup(&cgi_sapi_module);
2000-04-20 13:43:48 +00:00
#ifdef PHP_WIN32
2002-05-09 20:03:36 +00:00
_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 */
1999-04-25 19:36:57 +00:00
#endif
2002-05-09 20:03:36 +00:00
/* 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 (argc > 1) {
argv0 = strdup(argv[1]);
} else {
argv0 = NULL;
}
}
if (!cgi
#ifdef PHP_FASTCGI
2002-05-09 20:03:36 +00:00
/* allow ini override for fastcgi */
#endif
2002-05-09 20:03:36 +00:00
) {
while ((c=ap_php_getopt(argc, argv, OPTSTRING))!=-1) {
switch (c) {
case 'c':
cgi_sapi_module.php_ini_path_override = strdup(ap_php_optarg);
break;
}
2002-05-09 20:03:36 +00:00
}
ap_php_optind = orig_optind;
ap_php_optarg = orig_optarg;
}
#ifdef ZTS
2002-05-09 20:03:36 +00:00
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);
#endif
cgi_sapi_module.executable_location = argv[0];
2002-05-09 20:03:36 +00:00
/* startup after we get the above ini override se we get things right */
if (php_module_startup(&cgi_sapi_module)==FAILURE) {
#ifdef ZTS
2002-05-09 20:03:36 +00:00
tsrm_shutdown();
#endif
2002-05-09 20:03:36 +00:00
return FAILURE;
}
1999-04-25 19:36:57 +00:00
#if FORCE_CGI_REDIRECT
2002-05-09 20:03:36 +00:00
/* check force_cgi after startup, so we have proper output */
if (cfg_get_long("cgi.force_redirect", &force_redirect) == FAILURE) {
force_redirect = 1;
2002-05-09 20:03:36 +00:00
}
if (cgi && force_redirect) {
if (cfg_get_string("cgi.redirect_status_env", &redirect_status_env) == FAILURE) {
redirect_status_env = NULL;
}
2002-05-09 20:03:36 +00:00
/* 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))
) {
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\
1999-04-25 19:36:57 +00:00
means that a page will only be served up if the REDIRECT_STATUS CGI variable is\n\
2002-05-02 17:19:42 +00:00
set, e.g. via an Apache Action directive.</p>\n\
2002-05-02 15:18:26 +00:00
<p>For more information as to <i>why</i> this behaviour exists, see the <a href=\"http://php.net/security.cgi-bin\">\
2002-05-02 17:19:42 +00:00
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\
2002-05-02 17:19:42 +00:00
<a href=\"http://php.net/install.windows\">the manual page</a>.</p>\n");
1999-04-25 19:36:57 +00:00
#ifdef ZTS
2002-05-09 20:03:36 +00:00
tsrm_shutdown();
#endif
1999-04-25 19:36:57 +00:00
2002-05-09 20:03:36 +00:00
return FAILURE;
}
}
#endif /* FORCE_CGI_REDIRECT */
#ifdef PHP_FASTCGI
2002-05-09 20:03:36 +00:00
/* 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 ) {
fprintf( stderr,
"PHP_FCGI_MAX_REQUESTS is not valid\n" );
exit( 1 );
}
}
#ifndef PHP_WIN32
2002-05-09 20:03:36 +00:00
/* Pre-fork, if required */
if( getenv( "PHP_FCGI_CHILDREN" )) {
children = atoi( getenv( "PHP_FCGI_CHILDREN" ));
if( !children ) {
fprintf( stderr,
"PHP_FCGI_CHILDREN is not valid\n" );
exit( 1 );
}
}
if( children ) {
int running = 0;
int i;
pid_t pid;
/* Create a process group for ourself & children */
setsid();
pgroup = getpgrp();
#ifdef DEBUG_FASTCGI
2002-05-09 20:03:36 +00:00
fprintf( stderr, "Process group %d\n", pgroup );
#endif
2002-05-09 20:03:36 +00:00
/* 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
2002-05-09 20:03:36 +00:00
fprintf( stderr, "Forking, %d running\n",
running );
#endif
2002-05-09 20:03:36 +00:00
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
2002-05-09 20:03:36 +00:00
fprintf( stderr, "Wait for kids, pid %d\n",
getpid() );
#endif
2002-05-09 20:03:36 +00:00
wait( &status );
running--;
}
}
}
#endif /* WIN32 */
#endif
2002-05-09 20:03:36 +00:00
zend_first_try {
if (!cgi
#ifdef PHP_FASTCGI
2002-05-09 20:03:36 +00:00
&& !fastcgi
#endif
2002-05-09 20:03:36 +00:00
) {
while ((c=ap_php_getopt(argc, argv, OPTSTRING))!=-1) {
switch (c) {
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;
}
}
ap_php_optind = orig_optind;
ap_php_optarg = orig_optarg;
}
1999-04-25 19:36:57 +00:00
#ifdef PHP_FASTCGI
2002-05-09 20:03:36 +00:00
/* start of FAST CGI loop */
#ifdef PHP_WIN32
2002-05-09 20:03:36 +00:00
/* 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) OS_SetImpersonate();
}
#endif
2002-05-09 20:03:36 +00:00
while (!fastcgi
|| FCGX_Accept( &in, &out, &err, &cgi_env ) >= 0) {
if (fastcgi) {
/* set up environment */
cgi_env_size = 0;
while( cgi_env[ cgi_env_size ] ) { cgi_env_size++; }
merge_env = malloc( (env_size+cgi_env_size)*sizeof(char*) );
if( !merge_env ) {
perror( "Can't malloc environment" );
exit( 1 );
}
memcpy( merge_env, orig_env, (env_size-1)*sizeof(char *) );
memcpy( merge_env + env_size - 1,
cgi_env, (cgi_env_size+1)*sizeof(char *) );
environ = merge_env;
}
#endif
2002-05-09 20:03:36 +00:00
init_request_info(TSRMLS_C);
SG(server_context) = (void *) 1; /* avoid server_context==NULL checks */
1999-04-25 19:36:57 +00:00
2002-05-09 20:03:36 +00:00
SG(request_info).argv0 = argv0;
2000-02-10 20:03:17 +00:00
2002-05-09 20:03:36 +00:00
zend_llist_init(&global_vars, sizeof(char *), NULL, 0);
2000-05-04 13:42:21 +00:00
2002-05-09 20:03:36 +00:00
if (!cgi
#ifdef PHP_FASTCGI
2002-05-09 20:03:36 +00:00
&& !fastcgi
#endif
2002-05-09 20:03:36 +00:00
) { /* never execute the arguments if you are a CGI */
if (SG(request_info).argv0) {
free(SG(request_info).argv0);
SG(request_info).argv0 = NULL;
}
while ((c = ap_php_getopt(argc, argv, OPTSTRING)) != -1) {
switch (c) {
case 'a': /* interactive mode */
printf("Interactive mode enabled\n\n");
interactive=1;
break;
case 'C': /* don't chdir to the script directory */
SG(options) |= SAPI_OPTION_NO_CHDIR;
break;
case 'd': /* define ini entries on command line */
define_command_line_ini_entry(ap_php_optarg);
break;
case 'e': /* enable extended info output */
CG(extended_info) = 1;
break;
case 'f': /* parse file */
script_file = estrdup(ap_php_optarg);
no_headers = 1;
break;
case 'g': /* define global variables on command line */
{
char *arg = estrdup(ap_php_optarg);
zend_llist_add_element(&global_vars, &arg);
}
break;
case 'h': /* help & quit */
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;
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(1);
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");
zend_hash_apply_with_argument(&module_registry, (apply_func_arg_t) _print_module_info, NULL TSRMLS_CC);
php_printf("\n[Zend Modules]\n");
zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) _print_extension_info, NULL TSRMLS_CC);
php_printf("\n");
php_end_ob_buffers(1 TSRMLS_CC);
exit(1);
break;
#if 0 /* not yet operational, see also below ... */
2002-05-09 20:03:36 +00:00
case 'n': /* generate indented source mode*/
behavior=PHP_MODE_INDENT;
break;
1999-04-25 19:36:57 +00:00
#endif
2002-05-09 20:03:36 +00:00
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;
}
php_printf("PHP %s (%s)\n%s", PHP_VERSION, sapi_module.name, get_zend_version());
2002-05-09 20:03:36 +00:00
php_end_ob_buffers(1 TSRMLS_CC);
exit(1);
break;
case 'w':
behavior=PHP_MODE_STRIP;
break;
case 'z': /* load extension file */
zend_load_extension(ap_php_optarg);
break;
default:
break;
}
}
} /* not cgi */
CG(interactive) = interactive;
if (!cgi
#ifdef PHP_FASTCGI
2002-05-09 20:03:36 +00:00
&& !fastcgi
#endif
2002-05-09 20:03:36 +00:00
) {
if (!SG(request_info).query_string) {
len = 0;
if (script_file) {
len += strlen(script_file) + 1;
}
for (i = ap_php_optind; i < argc; i++) {
len += strlen(argv[i]) + 1;
}
s = malloc(len + 1); /* leak - but only for command line version, so ok */
*s = '\0'; /* we are pretending it came from the environment */
if (script_file) {
strcpy(s, script_file);
if (ap_php_optind<argc) {
strcat(s, "+");
}
}
for (i = ap_php_optind, len = 0; i < argc; i++) {
strcat(s, argv[i]);
if (i < (argc - 1)) {
strcat(s, "+");
}
}
SG(request_info).query_string = s;
}
}
if (script_file) {
SG(request_info).path_translated = script_file;
}
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;
}
#ifdef PHP_FASTCGI
2002-05-09 20:03:36 +00:00
if (fastcgi) {
file_handle.type = ZEND_HANDLE_FILENAME;
file_handle.filename = SG(request_info).path_translated;
} else {
#endif
2002-05-09 20:03:36 +00:00
file_handle.filename = "-";
file_handle.type = ZEND_HANDLE_FP;
file_handle.handle.fp = stdin;
#ifdef PHP_FASTCGI
2002-05-09 20:03:36 +00:00
}
#endif
2002-05-09 20:03:36 +00:00
file_handle.opened_path = NULL;
file_handle.free_filename = 0;
2002-05-09 20:03:36 +00:00
/* This actually destructs the elements of the list - ugly hack */
zend_llist_apply(&global_vars, (llist_apply_func_t) php_register_command_line_global_vars TSRMLS_CC);
zend_llist_destroy(&global_vars);
2002-05-09 20:03:36 +00:00
if (!cgi
#ifdef PHP_FASTCGI
2002-05-09 20:03:36 +00:00
&& !fastcgi
#endif
2002-05-09 20:03:36 +00:00
) {
if (!SG(request_info).path_translated && argc > ap_php_optind) {
SG(request_info).path_translated = estrdup(argv[ap_php_optind]);
}
} else {
/* If for some reason the CGI interface is not setting the
PATH_TRANSLATED correctly, SG(request_info).path_translated is NULL.
We still call php_fopen_primary_script, because if you set doc_root
or user_dir configuration directives, PATH_INFO is used to construct
the filename as a side effect of php_fopen_primary_script.
*/
char *env_path_translated=NULL;
#if DISCARD_PATH
2002-05-09 20:03:36 +00:00
env_path_translated = getenv("SCRIPT_FILENAME");
#else
2002-05-09 20:03:36 +00:00
env_path_translated = getenv("PATH_TRANSLATED");
#endif
2002-05-09 20:03:36 +00:00
if(env_path_translated) {
2001-11-04 12:46:30 +00:00
#ifdef __riscos__
2002-05-09 20:03:36 +00:00
/* Convert path to unix format*/
__riscosify_control|=__RISCOSIFY_DONT_CHECK_DIR;
env_path_translated=__unixify(env_path_translated,0,NULL,1,0);
2001-11-04 12:46:30 +00:00
#endif
2002-05-09 20:03:36 +00:00
SG(request_info).path_translated = estrdup(env_path_translated);
}
}
if (cgi || SG(request_info).path_translated) {
retval = php_fopen_primary_script(&file_handle TSRMLS_CC);
}
if (cgi && (retval == FAILURE)) {
if(!argv0 || !(file_handle.handle.fp = VCWD_FOPEN(argv0, "rb"))) {
PUTS("No input file specified.\n");
php_request_shutdown((void *) 0);
php_module_shutdown(TSRMLS_C);
return FAILURE;
}
file_handle.filename = argv0;
file_handle.opened_path = expand_filepath(argv0, NULL TSRMLS_CC);
}
if (file_handle.handle.fp && (file_handle.handle.fp != stdin)) {
/* #!php support */
c = fgetc(file_handle.handle.fp);
if (c == '#') {
while (c != 10 && c != 13) {
c = fgetc(file_handle.handle.fp); /* skip to end of line */
}
CG(zend_lineno)++;
} else {
rewind(file_handle.handle.fp);
}
}
switch (behavior) {
case PHP_MODE_STANDARD:
if (php_execute_script(&file_handle TSRMLS_CC)) {
exit_status = EG(exit_status);
} else {
exit_status = 255;
}
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);
}
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);
}
return SUCCESS;
}
break;
#if 0
2002-05-09 20:03:36 +00:00
/* 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
2002-05-09 20:03:36 +00:00
}
1999-04-25 19:36:57 +00:00
2002-05-09 20:03:36 +00:00
if (SG(request_info).path_translated) {
persist_alloc(SG(request_info).path_translated);
}
2002-05-09 20:03:36 +00:00
php_request_shutdown((void *) 0);
2001-08-14 23:17:02 +00:00
2002-05-09 20:03:36 +00:00
STR_FREE(SG(request_info).path_translated);
2001-08-14 23:17:02 +00:00
#ifdef PHP_FASTCGI
2002-05-09 20:03:36 +00:00
if (!fastcgi) break;
/* only fastcgi will get here */
/* TODO: We should free our environment here, but
* some platforms are unhappy if they've altered our
* existing environment and we then free() the new
* environ pointer
*/
requests++;
if( max_requests && ( requests == max_requests )) {
FCGX_Finish();
break;
}
/* end of fastcgi loop */
}
#endif
2002-05-09 20:03:36 +00:00
if (cgi_sapi_module.php_ini_path_override) {
free(cgi_sapi_module.php_ini_path_override);
}
} zend_catch {
exit_status = 255;
} zend_end_try();
2002-05-09 20:03:36 +00:00
php_module_shutdown(TSRMLS_C);
2001-07-27 07:37:16 +00:00
#ifdef ZTS
2002-05-09 20:03:36 +00:00
tsrm_shutdown();
2001-07-27 07:37:16 +00:00
#endif
2002-05-09 20:03:36 +00:00
return exit_status;
1999-04-25 19:36:57 +00:00
}
/* }}} */
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* End:
* vim600: sw=4 ts=4 fdm=marker
* vim<600: sw=4 ts=4
*/