andi Tue Mar 20 10:13:21 2001 EDT Added files: (Branch: PHP_4_0_5) /php4/sapi/fastcgi CREDITS Makefile.in README.FastCGI config.m4 fastcgi.c php.sym php_fastcgi.h Log: - MFH
Index: php4/sapi/fastcgi/Makefile.in +++ php4/sapi/fastcgi/Makefile.in LTLIBRARY_NAME = libsapi.la LTLIBRARY_SOURCES = fastcgi.c include $(top_srcdir)/build/ltlib.mk Index: php4/sapi/fastcgi/README.FastCGI +++ php4/sapi/fastcgi/README.FastCGI FastCGI module -------------- This module requires the FastCGI development kit, available from http://www.fastcgi.com/ Before building PHP, please enter the dev kit, and run: /configure make make export This will compile the library code required for the FastCGI module. All that is then required is to configure PHP with the '--with-fastcgi' option. After making the code, you will end up with a binary file called 'php'. Installation of this file will depend on the web server being used, please see their documentation for details. Index: php4/sapi/fastcgi/config.m4 +++ php4/sapi/fastcgi/config.m4 AC_MSG_CHECKING(for FastCGI support) AC_ARG_WITH(fastcgi, [ --with-fastcgi=SRCDIR Build PHP as FastCGI application],[ if test "$withval" = "yes"; then FASTCGIPATH=/usr/local else FASTCGIPATH=$withval fi test -f "$FASTCGIPATH/lib/libfcgi.a" || AC_MSG_ERROR(Unable to find libfcgi.a in $FASTCGIPATH/lib) test -f "$FASTCGIPATH/include/fastcgi.h" || AC_MSG_ERROR(Unable to find fastcgi.h in $FASTCGIPATH/include) PHP_SAPI=fastcgi PHP_LIBS=$FASTCGIPATH/lib/libfcgi.a AC_ADD_INCLUDE($FASTCGIPATH/include) EXT_PROGRAM_LDADD="$EXT_PROGRAM_LDADD $FASTCGIPATH/lib/libfcgi.a" INSTALL_IT="\$(INSTALL) -m 0755 $SAPI_PROGRAM \$(bindir)/$SAPI_FASTCGI" RESULT="yes" PHP_SUBST(FASTCGI_LIBADD) PHP_SUBST(EXT_PROGRAM_LDADD) ],[ RESULT="no" ]) AC_MSG_RESULT($RESULT) Index: php4/sapi/fastcgi/fastcgi.c +++ php4/sapi/fastcgi/fastcgi.c /* +----------------------------------------------------------------------+ | PHP version 4.0 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2001 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 2.02 of the PHP license, | | 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. | | 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 | | [EMAIL PROTECTED] so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Author: Ben Mansell <[EMAIL PROTECTED]> | +----------------------------------------------------------------------+ */ /* Debugging */ /* #define DEBUG_FASTCGI 1 */ /* Two configurables for the FastCGI runner. * * PHP_FCGI_CHILDREN - if set, the FastCGI will pre-fork this many processes * which will accept requests. * * PHP_FCGI_MAX_REQUESTS - if set, the runner will kill itself after handling * the given number of requests. This is to curb any * memory leaks in PHP. */ /* The following code is based mainly on the thttpd sapi and the original * CGI code, no doubt with many new and interesting bugs created... :) */ #include "php.h" #include "SAPI.h" #include "php_main.h" #include "php_fastcgi.h" #include "php_variables.h" #include "fcgi_config.h" #include "fcgiapp.h" #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/wait.h> #include <sys/stat.h> #define TLS_D #define TLS_DC #define TLS_C #define TLS_CC #define TLS_FETCH() FCGX_Stream *in, *out, *err; FCGX_ParamArray envp; char *path_info = NULL; /* 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; static int sapi_fastcgi_ub_write(const char *str, uint str_length) { uint sent = FCGX_PutStr( str, str_length, out ); return sent; } static void sapi_fastcgi_flush( void *server_context ) { if( FCGX_FFlush( out ) == -1 ) { php_handle_aborted_connection(); } } static int sapi_fastcgi_send_headers(sapi_headers_struct *sapi_headers SLS_DC) { char buf[1024]; int n = 0; zend_llist_position pos; sapi_header_struct *h; switch( sapi_headers->http_response_code ) { case 200: /* Default, assumed by FastCGI */ break; case 302: FCGX_PutS( "Status: 302 Moved Temporarily\r\n", out ); break; case 401: FCGX_PutS( "Status: 401 Authorization Required\r\n", out ); break; default: FCGX_FPrintF( out, "Status: %d Undescribed\r\\n", sapi_headers->http_response_code ); } h = zend_llist_get_first_ex(&sapi_headers->headers, &pos); while (h) { /* TODO: Buffer headers together into one big Put? */ #ifdef DEBUG_FASTCGI fprintf( stderr, "Printing header %s\n", h->header ); #endif FCGX_PutStr( h->header, h->header_len, out ); FCGX_PutStr( "\r\n", 2, out ); h = zend_llist_get_next_ex(&sapi_headers->headers, &pos); } FCGX_PutStr( "\r\n", 2, out ); return SAPI_HEADER_SENT_SUCCESSFULLY; } static int sapi_fastcgi_read_post(char *buffer, uint count_bytes SLS_DC) { size_t read_bytes = 0, tmp; int c; char *pos = buffer; TLS_FETCH(); while( count_bytes ) { c = FCGX_GetStr( pos, count_bytes, in ); read_bytes += c; count_bytes -= c; pos += c; if( !c ) break; } return read_bytes; } static char *sapi_fastcgi_read_cookies(SLS_D) { return getenv( "HTTP_COOKIE" ); } static void sapi_fastcgi_register_variables(zval *track_vars_array ELS_DC SLS_DC PLS_DC) { char *self = getenv("REQUEST_URI"); char *ptr = strchr( self, '?' ); /* In CGI mode, we consider the environment to be a part of the server * variables */ php_import_environment_variables(track_vars_array ELS_CC PLS_CC); /* strip query string off this */ if ( ptr ) *ptr = 0; php_register_variable( "PHP_SELF", getenv("REQUEST_URI"), track_vars_array ELS_CC PLS_CC); if ( ptr ) *ptr = '?'; } static sapi_module_struct fastcgi_sapi_module = { "fastcgi", "FastCGI", php_module_startup, php_module_shutdown_wrapper, NULL, /* activate */ NULL, /* deactivate */ sapi_fastcgi_ub_write, sapi_fastcgi_flush, NULL, /* get uid */ NULL, /* getenv */ php_error, NULL, sapi_fastcgi_send_headers, NULL, sapi_fastcgi_read_post, sapi_fastcgi_read_cookies, sapi_fastcgi_register_variables, NULL, /* Log message */ NULL, /* Block interruptions */ NULL, /* Unblock interruptions */ STANDARD_SAPI_MODULE_PROPERTIES }; static void fastcgi_module_main(TLS_D SLS_DC) { zend_file_handle file_handle; CLS_FETCH(); ELS_FETCH(); PLS_FETCH(); file_handle.type = ZEND_HANDLE_FILENAME; file_handle.filename = SG(request_info).path_translated; file_handle.free_filename = 0; file_handle.opened_path = NULL; if (php_request_startup(CLS_C ELS_CC PLS_CC SLS_CC) == SUCCESS) { php_execute_script(&file_handle CLS_CC ELS_CC PLS_CC); } php_request_shutdown(NULL); } static void init_request_info( SLS_D ) { char *content_length = getenv("CONTENT_LENGTH"); const char *auth; struct stat st; char *pi = getenv( "PATH_INFO" ); char *pt = getenv( "PATH_TRANSLATED" ); path_info = strdup( pi ); SG(request_info).request_method = getenv("REQUEST_METHOD"); SG(request_info).query_string = getenv("QUERY_STRING"); SG(request_info).request_uri = path_info; SG(request_info).content_type = getenv("CONTENT_TYPE"); SG(request_info).content_length = (content_length?atoi(content_length):0); SG(sapi_headers).http_response_code = 200; SG(request_info).path_translated = pt; /* * if the file doesn't exist, try to extract PATH_INFO out * of it by stat'ing back through the '/' */ if ( stat( pt, &st ) == -1 ) { int len = strlen(pt); char *ptr; while( 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 */ int slen = len - strlen(pt); if ( pi ) { int pilen = strlen( pi ); strcpy( pi, pi + pilen - slen ); } break; } } /* * 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... is there a nice way to error? */ } else { /* the first stat succeeded... */ if ( pi ) *pi = 0; } /* The CGI RFC allows servers to pass on unvalidated Authorization data */ auth = getenv("HTTP_AUTHORIZATION"); #ifdef DEBUG_FASTCGI fprintf( stderr, "Authorization: %s\n", auth ); #endif php_handle_auth_data(auth SLS_CC); } void fastcgi_php_init(void) { sapi_startup(&fastcgi_sapi_module); fastcgi_sapi_module.startup(&fastcgi_sapi_module); SG(server_context) = (void *) 1; } void fastcgi_php_shutdown(void) { if (SG(server_context) != NULL) { fastcgi_sapi_module.shutdown(&fastcgi_sapi_module); sapi_shutdown(); } } int main(int argc, char *argv[]) { int exit_status = SUCCESS; int c, i, len; zend_file_handle file_handle; char *s; char *argv0=NULL; char *script_file=NULL; zend_llist global_vars; int children = 8; int max_requests = 500; int requests = 0; int status; int env_size; #ifdef FASTCGI_DEBUG fprintf( stderr, "Initialising now!\n" ); #endif /* 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 *)); #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! [EMAIL PROTECTED] 20000419 */ #endif #endif sapi_startup(&fastcgi_sapi_module); if (php_module_startup(&fastcgi_sapi_module)==FAILURE) { return FAILURE; } /* 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 ); } } /* 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 parent = 1; int running = 0; while( parent ) { do { #ifdef FASTCGI_DEBUG fprintf( stderr, "Forking, %d running\n", running ); #endif switch( fork() ) { case 0: /* One of the children. * Make sure we don't go round the * fork loop any more */ parent = 0; break; case -1: perror( "php (pre-forking)" ); exit( 1 ); break; default: /* Fine */ running++; break; } } while( parent && ( running < children )); if( parent ) { wait( &status ); running--; } } } /* Main FastCGI loop */ #ifdef FASTCGI_DEBUG fprintf( stderr, "Going into accept loop\n" ); #endif while( FCGX_Accept( &in, &out, &err, &cgi_env ) >= 0 ) { #ifdef FASTCGI_DEBUG fprintf( stderr, "Got accept\n" ); #endif /* Allocate for our environment */ merge_env = malloc( env_size * sizeof( char *)); if( !merge_env ) { perror( "Can't malloc environment" ); exit( 1 ); } memcpy( merge_env, orig_env, env_size * sizeof( char *)); /* Use the new environment */ environ = merge_env; /* Populate our environment with the CGI's */ for( i = 0; cgi_env[ i ]; i++ ) { putenv( cgi_env[ i ] ); } init_request_info( TLS_C SLS_CC ); SG(server_context) = (void *) 1; /* avoid server_context==NULL checks */ CG(extended_info) = 0; SG(request_info).argv0 = argv0; zend_llist_init(&global_vars, sizeof(char *), NULL, 0); fastcgi_module_main( TLS_C SLS_CC ); if( path_info ) { free( path_info ); path_info = NULL; } /* 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; } } #ifdef FASTCGI_DEBUG fprintf( stderr, "Exiting...\n" ); #endif return 0; } Index: php4/sapi/fastcgi/php.sym +++ php4/sapi/fastcgi/php.sym Index: php4/sapi/fastcgi/php_fastcgi.h +++ php4/sapi/fastcgi/php_fastcgi.h /* +----------------------------------------------------------------------+ | PHP version 4.0 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2001 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 2.02 of the PHP license, | | 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. | | 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 | | [EMAIL PROTECTED] so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Author: Sascha Schumann <[EMAIL PROTECTED]> | +----------------------------------------------------------------------+ */ #ifndef PHP_FASTCGI_H #define PHP_FASTCGI_H #include <sys/types.h> #include <sys/stat.h> void fastcgi_php_shutdown(void); void fastcgi_php_init(void); #endif
-- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] To contact the list administrators, e-mail: [EMAIL PROTECTED]