File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / php / sapi / roxen / roxen.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue May 29 12:34:35 2012 UTC (12 years, 1 month ago) by misho
Branches: php, MAIN
CVS tags: v5_4_3elwix, v5_4_17p0, HEAD
php 5.4.3+patches

    1: /* 
    2:    +----------------------------------------------------------------------+
    3:    | PHP Version 5                                                        |
    4:    +----------------------------------------------------------------------+
    5:    | Copyright (c) 1997-2012 The PHP Group                                |
    6:    +----------------------------------------------------------------------+
    7:    | This source file is subject to version 3.01 of the PHP license,      |
    8:    | that is bundled with this package in the file LICENSE, and is        |
    9:    | available through the world-wide-web at the following url:           |
   10:    | http://www.php.net/license/3_01.txt                                  |
   11:    | If you did not receive a copy of the PHP license and are unable to   |
   12:    | obtain it through the world-wide-web, please send a note to          |
   13:    | license@php.net so we can mail you a copy immediately.               |
   14:    +----------------------------------------------------------------------+
   15:    | Author: David Hedbor <neotron@php.net>                               |
   16:    | Based on aolserver SAPI by Sascha Schumann <sascha@schumann.cx>      |
   17:    +----------------------------------------------------------------------+
   18:  */
   19: 
   20: /* $Id: roxen.c,v 1.1.1.2 2012/05/29 12:34:35 misho Exp $ */
   21: 
   22: #include "php.h"
   23: #ifdef HAVE_ROXEN
   24: 
   25: #include "php_ini.h"
   26: #include "php_globals.h"
   27: #include "SAPI.h"
   28: #include "php_main.h" 
   29: #include "ext/standard/info.h"
   30: 
   31: #include "php_version.h"
   32: 
   33: #ifndef ZTS
   34: /* Only valid if thread safety is enabled. */
   35: #undef ROXEN_USE_ZTS
   36: #endif
   37: 
   38: 
   39: /* Pike Include Files 
   40:  *
   41:  * conflicts with pike avoided by only using long names. Requires a new
   42:  * Pike 0.7 since it was implemented for this interface only.
   43:  *
   44:  */
   45: #define NO_PIKE_SHORTHAND
   46: 
   47: #include <fdlib.h>
   48: #include <program.h>
   49: #include <pike_types.h>
   50: #include <interpret.h>
   51: #include <module_support.h>
   52: #include <error.h>
   53: #include <array.h>
   54: #include <backend.h>
   55: #include <stralloc.h>
   56: #include <mapping.h>
   57: #include <object.h>
   58: #include <threads.h>
   59: #include <builtin_functions.h>
   60: #include <operators.h>
   61: 
   62: #undef HIDE_GLOBAL_VARIABLES
   63: #undef REVEAL_GLOBAL_VARIABLES
   64: #define HIDE_GLOBAL_VARIABLES()
   65: #define REVEAL_GLOBAL_VARIABLES()
   66: 
   67: /* php_roxen_request is per-request object storage */
   68: 
   69: typedef struct
   70: {
   71:   struct mapping *request_data;
   72:   struct object *my_fd_obj;
   73:   int my_fd;
   74:   char *filename;
   75: } php_roxen_request;
   76: 
   77: 
   78: /* Defines to get to the data supplied when the script is started. */
   79: 
   80: #ifdef ROXEN_USE_ZTS
   81: 
   82: /* ZTS does work now, but it seems like it's faster using the "serialization"
   83:  * method I previously used. Thus it's not used unless ROXEN_USE_ZTS is defined.
   84:  */
   85: 
   86: /* Per thread storage area id... */
   87: static int roxen_globals_id;
   88: 
   89: # define GET_THIS() php_roxen_request *_request = ts_resource(roxen_globals_id)
   90: # define THIS _request
   91: #else
   92: static php_roxen_request *current_request = NULL;
   93: 
   94: # define GET_THIS() current_request = ((php_roxen_request *)Pike_fp->current_storage)
   95: # define THIS current_request
   96: #endif
   97: 
   98: /* File descriptor integer. Used to write directly to the FD without 
   99:  * passing Pike
  100:  */
  101: #define MY_FD    (THIS->my_fd)
  102: 
  103: /* FD object. Really a PHPScript object from Pike which implements a couple
  104:  * of functions to handle headers, writing and buffering.
  105:  */
  106: #define MY_FD_OBJ        ((struct object *)(THIS->my_fd_obj))
  107: 
  108: /* Mapping with data supplied from the calling Roxen module. Contains
  109:  * a mapping with headers, an FD object etc.
  110:  */
  111: #define REQUEST_DATA ((struct mapping *)(THIS->request_data))
  112: 
  113: 
  114: #if defined(_REENTRANT) && !defined(ROXEN_USE_ZTS)
  115: /* Lock used to serialize the PHP execution. If ROXEN_USE_ZTS is defined, we
  116:  * are using the PHP thread safe mechanism instead.
  117:  */
  118: static PIKE_MUTEX_T roxen_php_execution_lock;
  119: # define PHP_INIT_LOCK()	mt_init(&roxen_php_execution_lock)
  120: # define PHP_LOCK(X)    THREADS_ALLOW();mt_lock(&roxen_php_execution_lock);THREADS_DISALLOW()
  121: # define PHP_UNLOCK(X)	mt_unlock(&roxen_php_execution_lock);
  122: # define PHP_DESTROY()	mt_destroy(&roxen_php_execution_lock)
  123: #else /* !_REENTRANT */
  124: # define PHP_INIT_LOCK()	
  125: # define PHP_LOCK(X)
  126: # define PHP_UNLOCK(X)
  127: # define PHP_DESTROY()	
  128: #endif /* _REENTRANT */
  129: 
  130: extern int fd_from_object(struct object *o);
  131: static unsigned char roxen_php_initialized;
  132: 
  133: /* This allows calling of pike functions from the PHP callbacks,
  134:  * which requires the Pike interpreter to be locked.
  135:  */
  136: #define THREAD_SAFE_RUN(COMMAND, what)  do {\
  137:   struct thread_state *state;\
  138:  if((state = thread_state_for_id(th_self()))!=NULL) {\
  139:     if(!state->swapped) {\
  140:       COMMAND;\
  141:     } else {\
  142:       mt_lock(&interpreter_lock);\
  143:       SWAP_IN_THREAD(state);\
  144:       COMMAND;\
  145:       SWAP_OUT_THREAD(state);\
  146:       mt_unlock(&interpreter_lock);\
  147:     }\
  148:   }\
  149: } while(0)
  150: 
  151: struct program *php_program;
  152: 
  153: 
  154: /* To avoid executing a PHP script from a PHP callback, which would
  155:  * create a deadlock, a global thread id is used. If the thread calling the
  156:  * php-script is the same as the current thread, it fails. 
  157:  */
  158: static int current_thread = -1;
  159: 
  160: 
  161: /* Low level header lookup. Basically looks for the named header in the mapping
  162:  * headers in the supplied options mapping.
  163:  */
  164:  
  165: static INLINE struct svalue *lookup_header(char *headername)
  166: {
  167:   struct svalue *headers, *value;
  168:   struct pike_string *sind;
  169: #ifdef ROXEN_USE_ZTS
  170:   GET_THIS();
  171: #endif
  172:   sind = make_shared_string("env");
  173:   headers = low_mapping_string_lookup(REQUEST_DATA, sind);
  174:   free_string(sind);
  175:   if(!headers || headers->type != PIKE_T_MAPPING) return NULL;
  176:   sind = make_shared_string(headername);
  177:   value = low_mapping_string_lookup(headers->u.mapping, sind);
  178:   free_string(sind);
  179:   if(!value) return NULL;
  180:   return value;
  181: }
  182: 
  183: /* Lookup a header in the mapping and return the value as a string, or
  184:  * return the default if it's missing
  185:  */
  186: INLINE static char *lookup_string_header(char *headername, char *default_value)
  187: {
  188:   struct svalue *head = NULL;
  189:   THREAD_SAFE_RUN(head = lookup_header(headername), "header lookup");
  190:   if(!head || head->type != PIKE_T_STRING)
  191:     return default_value;
  192:   return head->u.string->str;
  193: }
  194: 
  195: /* Lookup a header in the mapping and return the value as if it's an integer
  196:  * and otherwise return the default.
  197:  */
  198: INLINE static int lookup_integer_header(char *headername, int default_value)
  199: {
  200:   struct svalue *head = NULL;
  201:   THREAD_SAFE_RUN(head = lookup_header(headername), "header lookup");
  202:   if(!head || head->type != PIKE_T_INT)
  203:     return default_value;
  204:   return head->u.integer;
  205: }
  206: 
  207: /*
  208:  * php_roxen_low_ub_write() writes data to the client connection. Might be
  209:  * rewritten to do more direct IO to save CPU and the need to lock the *
  210:  * interpreter for better threading.
  211:  */
  212: 
  213: static int
  214: php_roxen_low_ub_write(const char *str, uint str_length TSRMLS_DC) {
  215:   int sent_bytes = 0;
  216:   struct pike_string *to_write = NULL;
  217: #ifdef ROXEN_USE_ZTS
  218:   GET_THIS();
  219: #endif
  220: 
  221:   if(!MY_FD_OBJ->prog) {
  222:     PG(connection_status) = PHP_CONNECTION_ABORTED;
  223:     zend_bailout();
  224:     return -1;
  225:   }
  226:   to_write = make_shared_binary_string(str, str_length);
  227:   push_string(to_write);
  228:   safe_apply(MY_FD_OBJ, "write", 1);
  229:   if(Pike_sp[-1].type == PIKE_T_INT)
  230:     sent_bytes = Pike_sp[-1].u.integer;
  231:   pop_stack();
  232:   if(sent_bytes != str_length) {
  233:     /* This means the connection is closed. Dead. Gone. *sniff*  */
  234:     php_handle_aborted_connection();
  235:   }
  236:   return sent_bytes;
  237: }
  238: 
  239: /*
  240:  * php_roxen_sapi_ub_write() calls php_roxen_low_ub_write in a Pike thread
  241:  * safe manner.
  242:  */
  243: 
  244: static int
  245: php_roxen_sapi_ub_write(const char *str, uint str_length TSRMLS_DC)
  246: {
  247: #ifdef ROXEN_USE_ZTS
  248:   GET_THIS();
  249: #endif
  250: 
  251:   int sent_bytes = 0, fd = MY_FD;
  252:   if(fd)
  253:   {
  254:     for(sent_bytes=0;sent_bytes < str_length;)
  255:     {
  256:       int written;
  257:       written = fd_write(fd, str + sent_bytes, str_length - sent_bytes);
  258:       if(written < 0)
  259:       {
  260: 	switch(errno)
  261: 	{
  262: 	 default:
  263: 	  /* This means the connection is closed. Dead. Gone. *sniff*  */
  264: 	  PG(connection_status) = PHP_CONNECTION_ABORTED;
  265: 	  zend_bailout();
  266: 	  return sent_bytes;
  267: 	 case EINTR: 
  268: 	 case EWOULDBLOCK:
  269: 	  continue;
  270: 	}
  271: 
  272:       } else {
  273: 	sent_bytes += written;
  274:       }
  275:     }
  276:   } else {
  277:     THREAD_SAFE_RUN(sent_bytes = php_roxen_low_ub_write(str, str_length TSRMLS_CC),
  278: 		    "write");
  279:   }
  280:   return sent_bytes;
  281: }
  282: 
  283: /* php_roxen_set_header() sets a header in the header mapping. Called in a
  284:  * thread safe manner from php_roxen_sapi_header_handler.
  285:  */
  286: static void php_roxen_set_header(char *header_name, char *value, char *p)
  287: {
  288:   struct svalue hsval;
  289:   struct pike_string *hval, *ind, *hind;
  290:   struct mapping *headermap;
  291:   struct svalue *s_headermap;
  292: #ifdef ROXEN_USE_ZTS
  293:   GET_THIS();
  294: #endif
  295:   hval = make_shared_string(value);
  296:   ind = make_shared_string(" _headers");
  297:   hind = make_shared_binary_string(header_name,
  298: 				   (int)(p - header_name));
  299: 
  300:   s_headermap = low_mapping_string_lookup(REQUEST_DATA, ind);
  301:   if(!s_headermap)
  302:   {
  303:     struct svalue mappie;                                           
  304:     mappie.type = PIKE_T_MAPPING;
  305:     headermap = allocate_mapping(1);
  306:     mappie.u.mapping = headermap;
  307:     mapping_string_insert(REQUEST_DATA, ind, &mappie);
  308:     free_mapping(headermap);
  309:   } else
  310:     headermap = s_headermap->u.mapping;
  311: 
  312:   hsval.type = PIKE_T_STRING;
  313:   hsval.u.string = hval;
  314:   mapping_string_insert(headermap, hind, &hsval);
  315: 
  316:   free_string(hval);
  317:   free_string(ind);
  318:   free_string(hind);
  319: }
  320: 
  321: /*
  322:  * php_roxen_sapi_header_handler() sets a HTTP reply header to be 
  323:  * sent to the client.
  324:  */
  325: static int
  326: php_roxen_sapi_header_handler(sapi_header_struct *sapi_header,
  327: 			      sapi_headers_struct *sapi_headers TSRMLS_DC)
  328: {
  329:   char *header_name, *header_content, *p;
  330:   header_name = sapi_header->header;
  331:   header_content = p = strchr(header_name, ':');
  332:   
  333:   if(p) {
  334:   do {
  335:     header_content++;
  336:   } while(*header_content == ' ');
  337:     THREAD_SAFE_RUN(php_roxen_set_header(header_name, header_content, p), "header handler");
  338:   }
  339:   sapi_free_header(sapi_header);
  340:   return 0;
  341: }
  342: 
  343: /*
  344:  * php_roxen_sapi_send_headers() flushes the headers to the client.
  345:  * Called before real content is sent by PHP.
  346:  */
  347: 
  348: static int
  349: php_roxen_low_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC)
  350: {
  351:   struct pike_string *ind;
  352:   struct svalue *s_headermap;
  353: #ifdef ROXEN_USE_ZTS
  354:   GET_THIS();
  355: #endif
  356: 
  357:   if(!MY_FD_OBJ->prog) {
  358:     PG(connection_status) = PHP_CONNECTION_ABORTED;
  359:     zend_bailout();
  360:     return SAPI_HEADER_SEND_FAILED;
  361:   }
  362:   ind = make_shared_string(" _headers");  
  363:   s_headermap = low_mapping_string_lookup(REQUEST_DATA, ind);
  364:   free_string(ind);
  365:   
  366:   push_int(SG(sapi_headers).http_response_code);
  367:   if(s_headermap && s_headermap->type == PIKE_T_MAPPING)
  368:     ref_push_mapping(s_headermap->u.mapping);
  369:   else
  370:     push_int(0);
  371:   safe_apply(MY_FD_OBJ, "send_headers", 2);
  372:   pop_stack();
  373:   
  374:   return SAPI_HEADER_SENT_SUCCESSFULLY;
  375: }
  376: 
  377: static int
  378: php_roxen_sapi_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC)
  379: {
  380:   int res = 0;
  381:   THREAD_SAFE_RUN(res = php_roxen_low_send_headers(sapi_headers TSRMLS_CC), "send headers");
  382:   return res;
  383: }
  384: 
  385: /*
  386:  * php_roxen_sapi_read_post() reads a specified number of bytes from
  387:  * the client. Used for POST/PUT requests.
  388:  */
  389: 
  390: INLINE static int php_roxen_low_read_post(char *buf, uint count_bytes)
  391: {
  392:   uint total_read = 0;
  393: #ifdef ROXEN_USE_ZTS
  394:   GET_THIS();
  395: #endif
  396:   TSRMLS_FETCH();
  397:   
  398:   if(!MY_FD_OBJ->prog)
  399:   {
  400:     PG(connection_status) = PHP_CONNECTION_ABORTED;
  401:     zend_bailout();
  402:     return -1;
  403:   }
  404:   push_int(count_bytes);
  405:   safe_apply(MY_FD_OBJ, "read_post", 1);
  406:   if(Pike_sp[-1].type == PIKE_T_STRING) {
  407:     MEMCPY(buf, Pike_sp[-1].u.string->str,
  408:            (total_read = Pike_sp[-1].u.string->len));
  409:     buf[total_read] = '\0';
  410:   } else
  411:     total_read = 0;
  412:   pop_stack();
  413:   return total_read;
  414: }
  415: 
  416: static int
  417: php_roxen_sapi_read_post(char *buf, uint count_bytes TSRMLS_DC)
  418: {
  419:   uint total_read = 0;
  420:   THREAD_SAFE_RUN(total_read = php_roxen_low_read_post(buf, count_bytes), "read post");
  421:   return total_read;
  422: }
  423: 
  424: /* 
  425:  * php_roxen_sapi_read_cookies() returns the Cookie header from
  426:  * the HTTP request header
  427:  */
  428: 	
  429: static char *
  430: php_roxen_sapi_read_cookies(TSRMLS_D)
  431: {
  432:   char *cookies;
  433:   cookies = lookup_string_header("HTTP_COOKIE", NULL);
  434:   return cookies;
  435: }
  436: 
  437: static void php_info_roxen(ZEND_MODULE_INFO_FUNC_ARGS)
  438: {
  439:   /*  char buf[512]; */
  440:   php_info_print_table_start();
  441:   php_info_print_table_row(2, "SAPI module version", "$Id: roxen.c,v 1.1.1.2 2012/05/29 12:34:35 misho Exp $");
  442:   /*  php_info_print_table_row(2, "Build date", Ns_InfoBuildDate());
  443:       php_info_print_table_row(2, "Config file path", Ns_InfoConfigFile());
  444:       php_info_print_table_row(2, "Error Log path", Ns_InfoErrorLog());
  445:       php_info_print_table_row(2, "Installation path", Ns_InfoHomePath());
  446:       php_info_print_table_row(2, "Hostname of server", Ns_InfoHostname());
  447:       php_info_print_table_row(2, "Source code label", Ns_InfoLabel());
  448:       php_info_print_table_row(2, "Server platform", Ns_InfoPlatform());
  449:       snprintf(buf, 511, "%s/%s", Ns_InfoServerName(), Ns_InfoServerVersion());
  450:       php_info_print_table_row(2, "Server version", buf);
  451:       snprintf(buf, 511, "%d day(s), %02d:%02d:%02d", 
  452:       uptime / 86400,
  453:       (uptime / 3600) % 24,
  454:       (uptime / 60) % 60,
  455:       uptime % 60);
  456:       php_info_print_table_row(2, "Server uptime", buf);
  457:   */
  458:   php_info_print_table_end();
  459: }
  460: 
  461: static zend_module_entry php_roxen_module = {
  462:   STANDARD_MODULE_HEADER,
  463:   "Roxen",
  464:   NULL,
  465:   NULL,
  466:   NULL,
  467:   NULL,
  468:   NULL,
  469:   php_info_roxen,
  470:   NULL,
  471:   STANDARD_MODULE_PROPERTIES
  472: };
  473: 
  474: static int php_roxen_startup(sapi_module_struct *sapi_module)
  475: {
  476:   if(php_module_startup(sapi_module, &php_roxen_module, 1) == FAILURE) {
  477:     return FAILURE;
  478:   } else {
  479:     return SUCCESS;
  480:   }
  481: }
  482: 
  483: /* this structure is static (as in "it does not change") */
  484: 
  485: static sapi_module_struct roxen_sapi_module = {
  486:   "roxen",
  487:   "Roxen",
  488:   php_roxen_startup,			/* startup */
  489:   php_module_shutdown_wrapper,		/* shutdown */
  490:   NULL,					/* activate */
  491:   NULL,					/* deactivate */
  492:   php_roxen_sapi_ub_write,		/* unbuffered write */
  493:   NULL,					/* flush */
  494:   NULL,					/* get uid */
  495:   NULL,					/* getenv */
  496:   php_error,				/* error handler */
  497:   php_roxen_sapi_header_handler,	/* header handler */
  498:   php_roxen_sapi_send_headers,		/* send headers handler */
  499:   NULL,					/* send header handler */
  500:   php_roxen_sapi_read_post,		/* read POST data */
  501:   php_roxen_sapi_read_cookies,		/* read Cookies */
  502:   NULL,					/* register server variables */
  503:   NULL,					/* Log message */
  504:   NULL,					/* Get request time */
  505:   NULL,					/* Child terminate */
  506: 
  507:   STANDARD_SAPI_MODULE_PROPERTIES
  508: };
  509: 
  510: /*
  511:  * php_roxen_hash_environment() populates the php script environment
  512:  * with a number of variables. HTTP_* variables are created for
  513:  * the HTTP header data, so that a script can access these.
  514:  */
  515: #define ADD_STRING(name)										\
  516: 	MAKE_STD_ZVAL(zvalue);										\
  517: 	zvalue->type = IS_STRING;										\
  518: 	zvalue->value.str.len = strlen(buf);							\
  519: 	zvalue->value.str.val = estrndup(buf, zvalue->value.str.len);	\
  520: 	zend_hash_update(&EG(symbol_table), name, sizeof(name), 	\
  521: 			&zvalue, sizeof(zval *), NULL)
  522: 
  523: static void
  524: php_roxen_hash_environment(TSRMLS_D)
  525: {
  526:   int i;
  527:   char buf[512];
  528:   zval *zvalue;
  529:   struct svalue *headers;
  530:   struct pike_string *sind;
  531:   struct array *indices;
  532:   struct svalue *ind, *val;
  533: #ifdef ROXEN_USE_ZTS
  534:   GET_THIS();
  535: #endif
  536:   sind = make_shared_string("env");
  537:   headers = low_mapping_string_lookup(REQUEST_DATA, sind);
  538:   free_string(sind);
  539:   if(headers && headers->type == PIKE_T_MAPPING) {
  540:     indices = mapping_indices(headers->u.mapping);
  541:     for(i = 0; i < indices->size; i++) {
  542:       ind = &indices->item[i];
  543:       val = low_mapping_lookup(headers->u.mapping, ind);
  544:       if(ind && ind->type == PIKE_T_STRING &&
  545: 	 val && val->type == PIKE_T_STRING) {
  546: 	int buf_len;
  547: 	buf_len = MIN(511, ind->u.string->len);
  548: 	strncpy(buf, ind->u.string->str, buf_len);
  549: 	buf[buf_len] = '\0'; /* Terminate correctly */
  550: 	MAKE_STD_ZVAL(zvalue);
  551: 	zvalue->type = IS_STRING;
  552: 	zvalue->value.str.len = val->u.string->len;
  553: 	zvalue->value.str.val = estrndup(val->u.string->str, zvalue->value.str.len);
  554: 	
  555: 	zend_hash_update(&EG(symbol_table), buf, buf_len + 1, &zvalue, sizeof(zval *), NULL);
  556:       }
  557:     }
  558:     free_array(indices);
  559:   }
  560:   
  561:   /*
  562:     MAKE_STD_ZVAL(zvalue);
  563:     zvalue->type = IS_LONG;
  564:     zvalue->value.lval = Ns_InfoBootTime();
  565:     zend_hash_update(&EG(symbol_table), "SERVER_BOOTTIME", sizeof("SERVER_BOOTTIME"), &zvalue, sizeof(zval *), NULL);
  566:   */
  567: }
  568: 
  569: /*
  570:  * php_roxen_module_main() is called by the per-request handler and
  571:  * "executes" the script
  572:  */
  573: 
  574: static int php_roxen_module_main(TSRMLS_D)
  575: {
  576:   int res, len;
  577:   char *dir;
  578:   zend_file_handle file_handle;
  579: #ifdef ROXEN_USE_ZTS
  580:   GET_THIS();
  581: #endif
  582: 
  583:   file_handle.type = ZEND_HANDLE_FILENAME;
  584:   file_handle.filename = THIS->filename;
  585:   file_handle.free_filename = 0;
  586:   file_handle.opened_path = NULL;
  587: 
  588:   THREADS_ALLOW();
  589:   res = php_request_startup(TSRMLS_C);
  590:   THREADS_DISALLOW();
  591:   if(res == FAILURE) {
  592:     return 0;
  593:   }
  594:   php_roxen_hash_environment(TSRMLS_C);
  595:   THREADS_ALLOW();
  596:   php_execute_script(&file_handle TSRMLS_CC);
  597:   php_request_shutdown(NULL);
  598:   THREADS_DISALLOW();
  599:   return 1;
  600: }
  601: 
  602: /*
  603:  * The php_roxen_request_handler() is called per request and handles
  604:  * everything for one request.
  605:  */
  606: 
  607: void f_php_roxen_request_handler(INT32 args)
  608: {
  609:   struct object *my_fd_obj;
  610:   struct mapping *request_data;
  611:   struct svalue *done_callback, *raw_fd;
  612:   struct pike_string *script, *ind;
  613:   int status = 1;
  614: #ifdef ROXEN_USE_ZTS
  615:   GET_THIS();
  616: #endif
  617:   TSRMLS_FETCH();
  618: 
  619:   if(current_thread == th_self())
  620:     php_error(E_WARNING, "PHP5.Interpreter->run: Tried to run a PHP-script from a PHP "
  621: 	  "callback!");
  622:   get_all_args("PHP5.Interpreter->run", args, "%S%m%O%*", &script,
  623: 	       &request_data, &my_fd_obj, &done_callback);
  624:   if(done_callback->type != PIKE_T_FUNCTION) 
  625:     php_error(E_WARNING, "PHP5.Interpreter->run: Bad argument 4, expected function.\n");
  626:   PHP_LOCK(THIS); /* Need to lock here or reusing the same object might cause
  627: 		       * problems in changing stuff in that object */
  628: #ifndef ROXEN_USE_ZTS
  629:   GET_THIS();
  630: #endif
  631:   THIS->request_data = request_data;
  632:   THIS->my_fd_obj = my_fd_obj;
  633:   THIS->filename = script->str;
  634:   current_thread = th_self();
  635:   SG(request_info).query_string = lookup_string_header("QUERY_STRING", 0);
  636:   SG(server_context) = (void *)1; /* avoid server_context == NULL */
  637: 
  638:   /* path_translated is apparently the absolute path to the file, not
  639:      the translated PATH_INFO
  640:   */
  641:   SG(request_info).path_translated =
  642:     lookup_string_header("SCRIPT_FILENAME", NULL);
  643:   SG(request_info).request_uri = lookup_string_header("DOCUMENT_URI", NULL);
  644:   if(!SG(request_info).request_uri)
  645:     SG(request_info).request_uri = lookup_string_header("SCRIPT_NAME", NULL);
  646:   SG(request_info).request_method = lookup_string_header("REQUEST_METHOD", "GET");
  647:   SG(request_info).content_length = lookup_integer_header("HTTP_CONTENT_LENGTH", 0);
  648:   SG(request_info).content_type = lookup_string_header("HTTP_CONTENT_TYPE", NULL);
  649:   SG(sapi_headers).http_response_code = 200;
  650: 
  651:   /* FIXME: Check for auth stuff needs to be fixed... */ 
  652:   SG(request_info).auth_user = NULL; 
  653:   SG(request_info).auth_password = NULL;
  654:   
  655:   ind = make_shared_binary_string("my_fd", 5);
  656:   raw_fd = low_mapping_string_lookup(THIS->request_data, ind);
  657:   if(raw_fd && raw_fd->type == PIKE_T_OBJECT)
  658:   {
  659:     int fd = fd_from_object(raw_fd->u.object);
  660:     if(fd == -1)
  661:       php_error(E_WARNING, "PHP5.Interpreter->run: my_fd object not open or not an FD.\n");
  662:     THIS->my_fd = fd;
  663:   } else
  664:     THIS->my_fd = 0;
  665:   
  666:   status = php_roxen_module_main(TSRMLS_C);
  667:   current_thread = -1;
  668:   
  669:   apply_svalue(done_callback, 0);
  670:   pop_stack();
  671:   pop_n_elems(args);
  672:   push_int(status);
  673:   PHP_UNLOCK(THIS);
  674: }
  675: 
  676: 
  677: /* Clear the object global struct */
  678: static void clear_struct(struct object *o)
  679: {
  680:   MEMSET(Pike_fp->current_storage, 0, sizeof(php_roxen_request));
  681: }
  682: 
  683: 
  684: /*
  685:  * pike_module_init() is called by Pike once at startup
  686:  *
  687:  * This functions allocates basic structures
  688:  */
  689: 
  690: void pike_module_init( void )
  691: {
  692:   if (!roxen_php_initialized) {
  693: #ifdef ZTS
  694:     tsrm_startup(1, 1, 0, NULL);
  695: #ifdef ROXEN_USE_ZTS
  696:     ts_allocate_id(&roxen_globals_id, sizeof(php_roxen_request), NULL, NULL);
  697: #endif	 
  698: #endif
  699:     sapi_startup(&roxen_sapi_module);
  700:     /*php_roxen_startup(&roxen_sapi_module); removed - should be called from SAPI activation*/
  701:     roxen_php_initialized = 1;
  702:     PHP_INIT_LOCK();
  703:   }
  704:   start_new_program(); /* Text */
  705:   ADD_STORAGE(php_roxen_request);
  706:   set_init_callback(clear_struct);
  707:   pike_add_function("run", f_php_roxen_request_handler,
  708: 		    "function(string, mapping, object, function:int)", 0);
  709:   add_program_constant("Interpreter", (php_program = end_program()), 0);
  710: }
  711: 
  712: /*
  713:  * pike_module_exit() performs the last steps before the
  714:  * server exists. Shutdowns basic services and frees memory
  715:  */
  716: 
  717: void pike_module_exit(void)
  718: {
  719:   roxen_php_initialized = 0;
  720:   roxen_sapi_module.shutdown(&roxen_sapi_module);
  721:   if(php_program)  free_program(php_program);
  722: #ifdef ZTS
  723:   tsrm_shutdown();
  724: #endif
  725:   PHP_DESTROY();
  726: }
  727: #endif

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>