File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / php / sapi / caudium / caudium.c
Revision 1.1.1.4 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Sun Jun 15 20:04:02 2014 UTC (10 years, 6 months ago) by misho
Branches: php, MAIN
CVS tags: v5_4_29, HEAD
php 5.4.29

    1: /* 
    2:    +----------------------------------------------------------------------+
    3:    | PHP Version 5                                                        |
    4:    +----------------------------------------------------------------------+
    5:    | Copyright (c) 1997-2014 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: caudium.c,v 1.1.1.4 2014/06/15 20:04:02 misho Exp $ */
   21: 
   22: #include "php.h"
   23: #ifdef HAVE_CAUDIUM
   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: /* Pike Include Files 
   34:  *
   35:  * conflicts with pike avoided by only using long names. Requires a new
   36:  * Pike 0.7 since it was implemented for this interface only.
   37:  *
   38:  */
   39: #define NO_PIKE_SHORTHAND
   40: 
   41: /* Ok, we are now using Pike level threads to handle PHP5 since
   42:  * the nice th_farm threads aren't working on Linux with glibc 2.2
   43:  * (why this is I don't know).
   44:  */
   45: #define USE_PIKE_LEVEL_THREADS
   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 <array.h>
   53: #include <backend.h>
   54: #include <stralloc.h>
   55: #include <mapping.h>
   56: #include <object.h>
   57: #include <threads.h>
   58: #include <builtin_functions.h>
   59: #include <operators.h>
   60: #include <version.h>
   61: 
   62: #if (PIKE_MAJOR_VERSION == 7 && PIKE_MINOR_VERSION == 1 && PIKE_BUILD_VERSION >= 12) || PIKE_MAJOR_VERSION > 7 || (PIKE_MAJOR_VERSION == 7 && PIKE_MINOR_VERSION > 1)
   63: # include "pike_error.h"
   64: #else
   65: # include "error.h"
   66: # ifndef Pike_error
   67: #  define Pike_error error
   68: # endif
   69: #endif
   70: 
   71: /* Pike 7.x and newer */
   72: #define MY_MAPPING_LOOP(md, COUNT, KEY) \
   73:   for(COUNT=0;COUNT < md->data->hashsize; COUNT++ ) \
   74: 	for(KEY=md->data->hash[COUNT];KEY;KEY=KEY->next)
   75: 
   76: #ifndef ZTS
   77: /* Need thread safety */
   78: #error You need to compile PHP with threads.
   79: #endif
   80: 
   81: #ifndef PIKE_THREADS
   82: #error The PHP5 module requires that your Pike has thread support.
   83: #endif
   84: 
   85: #undef HIDE_GLOBAL_VARIABLES
   86: #undef REVEAL_GLOBAL_VARIABLES
   87: #define HIDE_GLOBAL_VARIABLES()
   88: #define REVEAL_GLOBAL_VARIABLES()
   89: 
   90: /* php_caudium_request is per-request object storage */
   91: 
   92: typedef struct
   93: {
   94:   struct mapping *request_data;
   95:   struct object *my_fd_obj;
   96:   struct svalue done_cb;
   97:   struct pike_string *filename;
   98:   int my_fd;
   99:   int written;
  100:   TSRMLS_D;
  101: } php_caudium_request;
  102: 
  103: 
  104: void pike_module_init(void);
  105: void pike_module_exit(void);
  106: static void free_struct(TSRMLS_D);
  107: void f_php_caudium_request_handler(INT32 args);
  108: 
  109: /* Defines to get to the data supplied when the script is started. */
  110: 
  111: /* Per thread storage area id... */
  112: static int caudium_globals_id;
  113: 
  114: #define GET_THIS() php_caudium_request *_request = ts_resource(caudium_globals_id)
  115: #define THIS _request
  116: #define PTHIS ((php_caudium_request *)(Pike_fp->current_storage))
  117: /* File descriptor integer. Used to write directly to the FD without 
  118:  * passing Pike
  119:  */
  120: #define MY_FD    (THIS->my_fd)
  121: 
  122: /* FD object. Really a PHPScript object from Pike which implements a couple
  123:  * of functions to handle headers, writing and buffering.
  124:  */
  125: #define MY_FD_OBJ        ((struct object *)(THIS->my_fd_obj))
  126: 
  127: /* Mapping with data supplied from the calling Caudium module. Contains
  128:  * a mapping with headers, an FD object etc.
  129:  */
  130: #define REQUEST_DATA ((struct mapping *)(THIS->request_data))
  131: 
  132: extern int fd_from_object(struct object *o);
  133: static unsigned char caudium_php_initialized;
  134: 
  135: #ifndef mt_lock_interpreter
  136: #define mt_lock_interpreter()     mt_lock(&interpreter_lock);
  137: #define mt_unlock_interpreter()   mt_unlock(&interpreter_lock);
  138: #endif
  139: 
  140: 
  141: /* This allows calling of pike functions from the PHP callbacks,
  142:  * which requires the Pike interpreter to be locked.
  143:  */
  144: #define THREAD_SAFE_RUN(COMMAND, what)  do {\
  145:   struct thread_state *state;\
  146:   if((state = thread_state_for_id(th_self()))!=NULL) {\
  147:     if(!state->swapped) {\
  148:       COMMAND;\
  149:     } else {\
  150:       mt_lock_interpreter();\
  151:       SWAP_IN_THREAD(state);\
  152:       COMMAND;\
  153:       SWAP_OUT_THREAD(state);\
  154:       mt_unlock_interpreter();\
  155:     }\
  156:   }\
  157: } while(0)
  158: 
  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: INLINE static struct svalue *lookup_header(char *headername)
  166: {
  167:   struct svalue *headers, *value;
  168:   struct pike_string *sind;
  169:   GET_THIS();
  170:   sind = make_shared_string("env");
  171:   headers = low_mapping_string_lookup(REQUEST_DATA, sind);
  172:   free_string(sind);
  173:   if(!headers || headers->type != PIKE_T_MAPPING) return NULL;
  174:   sind = make_shared_string(headername);
  175:   value = low_mapping_string_lookup(headers->u.mapping, sind);
  176:   free_string(sind);
  177:   if(!value) return NULL;
  178:   return value;
  179: }
  180: 
  181: /* Lookup a header in the mapping and return the value as a string, or
  182:  * return the default if it's missing
  183:  */
  184: INLINE static char *lookup_string_header(char *headername, char *default_value)
  185: {
  186:   struct svalue *head = NULL;
  187:   THREAD_SAFE_RUN(head = lookup_header(headername), "header lookup");
  188:   if(!head || head->type != PIKE_T_STRING)
  189:     return default_value;
  190:   return head->u.string->str;
  191: }
  192: 
  193: /* Lookup a header in the mapping and return the value as if it's an integer
  194:  * and otherwise return the default.
  195:  */
  196: INLINE static int lookup_integer_header(char *headername, int default_value)
  197: {
  198:   struct svalue *head = NULL;
  199:   THREAD_SAFE_RUN(head = lookup_header(headername), "header lookup");
  200:   if(!head || head->type != PIKE_T_INT)
  201:     return default_value;
  202:   return head->u.integer;
  203: }
  204: 
  205: /*
  206:  * php_caudium_low_ub_write() writes data to the client connection. Might be
  207:  * rewritten to do more direct IO to save CPU and the need to lock the 
  208:  * interpreter for better threading.
  209:  */
  210: 
  211: INLINE static int
  212: php_caudium_low_ub_write(const char *str, uint str_length TSRMLS_DC) {
  213:   int sent_bytes = 0;
  214:   struct pike_string *to_write = NULL;
  215:   GET_THIS();
  216:   if(!MY_FD_OBJ->prog) {
  217:     PG(connection_status) = PHP_CONNECTION_ABORTED;
  218:     zend_bailout();
  219:     return -1;
  220:   }
  221:   to_write = make_shared_binary_string(str, str_length);
  222:   push_string(to_write);
  223:   safe_apply(MY_FD_OBJ, "write", 1);
  224:   if(Pike_sp[-1].type == PIKE_T_INT)
  225:     sent_bytes = Pike_sp[-1].u.integer;
  226:   pop_stack();
  227:   if(sent_bytes != str_length) {
  228:     /* This means the connection is closed. Dead. Gone. *sniff*  */
  229:     PG(connection_status) = PHP_CONNECTION_ABORTED;
  230:     zend_bailout();
  231:   }
  232:   return sent_bytes;
  233: }
  234: 
  235: /*
  236:  * php_caudium_sapi_ub_write() calls php_caudium_low_ub_write in a Pike thread
  237:  * safe manner or writes directly to the output FD if RXML post-parsing is
  238:  * disabled. 
  239:  */
  240: 
  241: static int
  242: php_caudium_sapi_ub_write(const char *str, uint str_length TSRMLS_DC)
  243: {
  244:   GET_THIS();
  245:   int sent_bytes = 0, fd = MY_FD;
  246:   if(fd)
  247:   {
  248:     for(sent_bytes=0;sent_bytes < str_length;)
  249:     {
  250:       int written;
  251:       written = fd_write(fd, str + sent_bytes, str_length - sent_bytes);
  252:       if(written < 0)
  253:       {
  254: 	switch(errno)
  255: 	{
  256: 	 default:
  257: 	  /* This means the connection is closed. Dead. Gone. *sniff*  */
  258: 	  PG(connection_status) = PHP_CONNECTION_ABORTED;
  259: 	  zend_bailout();
  260: 	  THIS->written += sent_bytes;
  261: 	  return sent_bytes;
  262: 	 case EINTR: 
  263: 	 case EWOULDBLOCK:
  264: 	  continue;
  265: 	}
  266:       } else {
  267: 	sent_bytes += written;
  268:       }
  269:     }
  270:     THIS->written += sent_bytes;
  271:   } else {
  272:     THREAD_SAFE_RUN(sent_bytes = php_caudium_low_ub_write(str, str_length TSRMLS_CC),
  273: 		    "write");
  274:   }
  275:   return sent_bytes;
  276: }
  277: 
  278: /* php_caudium_set_header() sets a header in the header mapping. Called in a
  279:  * thread safe manner from php_caudium_sapi_header_handler.
  280:  */
  281: INLINE static void
  282: php_caudium_set_header(char *header_name, char *value, char *p)
  283: {
  284:   struct svalue hsval;
  285:   struct pike_string *hval, *ind, *hind;
  286:   struct mapping *headermap;
  287:   struct svalue *s_headermap, *soldval;
  288:   int vallen;
  289:   GET_THIS();
  290:   /*  hval = make_shared_string(value); */
  291:   ind = make_shared_string(" _headers");
  292:   hind = make_shared_binary_string(header_name,
  293: 				   (int)(p - header_name));
  294: 
  295:   s_headermap = low_mapping_string_lookup(REQUEST_DATA, ind);
  296:   if(!s_headermap || s_headermap->type != PIKE_T_MAPPING)
  297:   {
  298:     struct svalue mappie;                                           
  299:     mappie.type = PIKE_T_MAPPING;
  300:     headermap = allocate_mapping(1);
  301:     mappie.u.mapping = headermap;
  302:     mapping_string_insert(REQUEST_DATA, ind, &mappie);
  303:     free_mapping(headermap);
  304:     hval = make_shared_string(value);
  305:   } else {
  306:     headermap = s_headermap->u.mapping;
  307:     soldval = low_mapping_string_lookup(headermap, hind);
  308:     vallen = strlen(value);
  309:     if(soldval != NULL && 
  310:        soldval->type == PIKE_T_STRING &&
  311:        soldval->u.string->size_shift == 0) {
  312:       /* Existing, valid header. Prepend.*/
  313:       hval = begin_shared_string(soldval->u.string->len + 1 + vallen);
  314:       MEMCPY(hval->str, soldval->u.string->str, soldval->u.string->len);
  315:       STR0(hval)[soldval->u.string->len] = '\0';
  316:       MEMCPY(hval->str+soldval->u.string->len+1, value, vallen);
  317:       hval = end_shared_string(hval);
  318:     } else { 
  319:       hval = make_shared_string(value);
  320:     }
  321:   }
  322:   hsval.type = PIKE_T_STRING;
  323:   hsval.u.string = hval;
  324: 
  325:   mapping_string_insert(headermap, hind, &hsval);
  326: 
  327:   free_string(hval);
  328:   free_string(ind);
  329:   free_string(hind);
  330: }
  331: 
  332: /*
  333:  * php_caudium_sapi_header_handler() sets a HTTP reply header to be 
  334:  * sent to the client.
  335:  */
  336: static int
  337: php_caudium_sapi_header_handler(sapi_header_struct *sapi_header,
  338: 			      sapi_headers_struct *sapi_headers TSRMLS_DC)
  339: {
  340:   char *header_name, *header_content, *p;
  341:   header_name = sapi_header->header;
  342:   header_content = p = strchr(header_name, ':');
  343:   
  344:   if(p) {
  345:   do {
  346:     header_content++;
  347:   } while(*header_content == ' ');
  348:     THREAD_SAFE_RUN(php_caudium_set_header(header_name, header_content, p), "header handler");
  349:   }
  350:   sapi_free_header(sapi_header);
  351:   return 0;
  352: }
  353: 
  354: /*
  355:  * php_caudium_sapi_send_headers() flushes the headers to the client.
  356:  * Called before real content is sent by PHP.
  357:  */
  358: 
  359: INLINE static int
  360: php_caudium_low_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC)
  361: {
  362:   struct pike_string *ind;
  363:   struct svalue *s_headermap;
  364:   GET_THIS();
  365:   if(!MY_FD_OBJ->prog) {
  366:     PG(connection_status) = PHP_CONNECTION_ABORTED;
  367:     zend_bailout();
  368:     return SAPI_HEADER_SEND_FAILED;
  369:   }
  370:   ind = make_shared_string(" _headers");  
  371:   s_headermap = low_mapping_string_lookup(REQUEST_DATA, ind);
  372:   free_string(ind);
  373:   
  374:   push_int(SG(sapi_headers).http_response_code);
  375:   if(s_headermap && s_headermap->type == PIKE_T_MAPPING)
  376:     ref_push_mapping(s_headermap->u.mapping);
  377:   else
  378:     push_int(0);
  379:   safe_apply(MY_FD_OBJ, "send_headers", 2);
  380:   pop_stack();
  381:   
  382:   return SAPI_HEADER_SENT_SUCCESSFULLY;
  383: }
  384: 
  385: static int
  386: php_caudium_sapi_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC)
  387: {
  388:   int res = 0;
  389:   THREAD_SAFE_RUN(res = php_caudium_low_send_headers(sapi_headers TSRMLS_CC), "send headers");
  390:   return res;
  391: }
  392: 
  393: /*
  394:  * php_caudium_sapi_read_post() reads a specified number of bytes from
  395:  * the client. Used for POST/PUT requests.
  396:  */
  397: 
  398: INLINE static int php_caudium_low_read_post(char *buf, uint count_bytes)
  399: {
  400:   uint total_read = 0;
  401:   GET_THIS();
  402:   TSRMLS_FETCH();
  403:   
  404:   if(!MY_FD_OBJ->prog)
  405:   {
  406:     PG(connection_status) = PHP_CONNECTION_ABORTED;
  407:     zend_bailout();
  408:     return -1;
  409:   }
  410:   push_int(count_bytes);
  411:   safe_apply(MY_FD_OBJ, "read_post", 1);
  412:   if(Pike_sp[-1].type == PIKE_T_STRING) {
  413:     MEMCPY(buf, Pike_sp[-1].u.string->str,
  414:            (total_read = Pike_sp[-1].u.string->len));
  415:     buf[total_read] = '\0';
  416:   } else
  417:     total_read = 0;
  418:   pop_stack();
  419:   return total_read;
  420: }
  421: 
  422: static int
  423: php_caudium_sapi_read_post(char *buf, uint count_bytes TSRMLS_DC)
  424: {
  425:   uint total_read = 0;
  426:   THREAD_SAFE_RUN(total_read = php_caudium_low_read_post(buf, count_bytes), "read post");
  427:   return total_read;
  428: }
  429: 
  430: /* 
  431:  * php_caudium_sapi_read_cookies() returns the Cookie header from
  432:  * the HTTP request header
  433:  */
  434: 	
  435: static char *
  436: php_caudium_sapi_read_cookies(TSRMLS_D)
  437: {
  438:   char *cookies;
  439:   cookies = lookup_string_header("HTTP_COOKIE", NULL);
  440:   return cookies;
  441: }
  442: 
  443: static void php_info_caudium(ZEND_MODULE_INFO_FUNC_ARGS)
  444: {
  445:   /*  char buf[512]; */
  446:   php_info_print_table_start();
  447:   php_info_print_table_row(2, "SAPI module version", "$Id: caudium.c,v 1.1.1.4 2014/06/15 20:04:02 misho Exp $");
  448:   /*  php_info_print_table_row(2, "Build date", Ns_InfoBuildDate());
  449:       php_info_print_table_row(2, "Config file path", Ns_InfoConfigFile());
  450:       php_info_print_table_row(2, "Error Log path", Ns_InfoErrorLog());
  451:       php_info_print_table_row(2, "Installation path", Ns_InfoHomePath());
  452:       php_info_print_table_row(2, "Hostname of server", Ns_InfoHostname());
  453:       php_info_print_table_row(2, "Source code label", Ns_InfoLabel());
  454:       php_info_print_table_row(2, "Server platform", Ns_InfoPlatform());
  455:       snprintf(buf, 511, "%s/%s", Ns_InfoServerName(), Ns_InfoServerVersion());
  456:       php_info_print_table_row(2, "Server version", buf);
  457:       snprintf(buf, 511, "%d day(s), %02d:%02d:%02d", 
  458:       uptime / 86400,
  459:       (uptime / 3600) % 24,
  460:       (uptime / 60) % 60,
  461:       uptime % 60);
  462:       php_info_print_table_row(2, "Server uptime", buf);
  463:   */
  464:   php_info_print_table_end();
  465: }
  466: 
  467: static zend_module_entry php_caudium_module = {
  468:   STANDARD_MODULE_HEADER,
  469:   "Caudium",
  470:   NULL,
  471:   NULL,
  472:   NULL,
  473:   NULL,
  474:   NULL,
  475:   php_info_caudium,
  476:   NULL,
  477:   STANDARD_MODULE_PROPERTIES
  478: };
  479: 
  480: 
  481: INLINE static void low_sapi_caudium_register_variables(zval *track_vars_array TSRMLS_DC)   
  482: {
  483:   int i;
  484:   struct keypair *k;
  485:   struct svalue *headers;
  486:   struct pike_string *sind;
  487:   struct svalue *ind;
  488:   struct svalue *val;
  489:   GET_THIS();
  490:   php_register_variable("PHP_SELF", SG(request_info).request_uri,
  491: 			track_vars_array TSRMLS_CC);
  492:   php_register_variable("GATEWAY_INTERFACE", "CGI/1.1",
  493: 			track_vars_array TSRMLS_CC);
  494:   php_register_variable("REQUEST_METHOD",
  495: 			(char *) SG(request_info).request_method,
  496: 			track_vars_array TSRMLS_CC);
  497:   php_register_variable("REQUEST_URI", SG(request_info).request_uri,
  498: 			track_vars_array TSRMLS_CC);
  499:   php_register_variable("PATH_TRANSLATED", SG(request_info).path_translated,
  500: 			track_vars_array TSRMLS_CC);
  501: 
  502:   sind = make_shared_string("env");
  503:   headers = low_mapping_string_lookup(REQUEST_DATA, sind);
  504:   free_string(sind);
  505:   if(headers && headers->type == PIKE_T_MAPPING) {
  506:     MY_MAPPING_LOOP(headers->u.mapping, i, k) {
  507:       ind = &k->ind;
  508:       val = &k->val;
  509:       if(ind && ind->type == PIKE_T_STRING &&
  510: 	 val && val->type == PIKE_T_STRING) {
  511: 	php_register_variable(ind->u.string->str, val->u.string->str,
  512: 			      track_vars_array TSRMLS_CC );
  513:       }
  514:     }
  515:   }
  516: }
  517: 
  518: static void sapi_caudium_register_variables(zval *track_vars_array TSRMLS_DC)
  519: {
  520:   THREAD_SAFE_RUN(low_sapi_caudium_register_variables(track_vars_array TSRMLS_CC), "register_variables");
  521: }
  522: 
  523: 
  524: static int php_caudium_startup(sapi_module_struct *sapi_module)
  525: {
  526: 	if (php_module_startup(sapi_module, &php_caudium_module, 1)==FAILURE) {
  527: 		return FAILURE;
  528: 	}
  529: 	return SUCCESS;
  530: }
  531: 
  532: 
  533: /* this structure is static (as in "it does not change") */
  534: static sapi_module_struct caudium_sapi_module = {
  535:   "caudium",
  536:   "Caudium",
  537:   php_caudium_startup,			/* startup */
  538:   php_module_shutdown_wrapper,		/* shutdown */
  539:   NULL,					/* activate */
  540:   NULL,					/* deactivate */
  541:   php_caudium_sapi_ub_write,		/* unbuffered write */
  542:   NULL,					/* flush */
  543:   NULL,					/* get uid */
  544:   NULL,					/* getenv */
  545:   php_error,				/* error handler */
  546:   php_caudium_sapi_header_handler,	/* header handler */
  547:   php_caudium_sapi_send_headers,	/* send headers handler */
  548:   NULL,					/* send header handler */
  549:   php_caudium_sapi_read_post,		/* read POST data */
  550:   php_caudium_sapi_read_cookies,	/* read cookies */
  551:   sapi_caudium_register_variables,	/* register server variables */
  552:   NULL,					/* Log message */
  553:   NULL,					/* Get request time */
  554:   NULL,					/* Child terminate */
  555: 
  556:   STANDARD_SAPI_MODULE_PROPERTIES
  557: };
  558: 
  559: /*
  560:  * php_caudium_module_main() is called by the per-request handler and
  561:  * "executes" the script
  562:  */
  563: 
  564: static void php_caudium_module_main(php_caudium_request *ureq)
  565: {
  566:   int res;
  567:   zend_file_handle file_handle;
  568: #ifndef USE_PIKE_LEVEL_THREADS
  569:   struct thread_state *state;
  570:   extern struct program *thread_id_prog;
  571: #endif
  572:   TSRMLS_FETCH();
  573:   GET_THIS();
  574:   THIS->filename = ureq->filename;
  575:   THIS->done_cb = ureq->done_cb;
  576:   THIS->my_fd_obj = ureq->my_fd_obj;
  577:   THIS->my_fd = ureq->my_fd;
  578:   THIS->request_data = ureq->request_data;
  579:   free(ureq);
  580: 
  581: #ifndef USE_PIKE_LEVEL_THREADS
  582:   mt_lock_interpreter();
  583:   init_interpreter();
  584: #if PIKE_MAJOR_VERSION == 7 && PIKE_MINOR_VERSION < 1
  585:   thread_id = low_clone(thread_id_prog);
  586:   state = OBJ2THREAD(thread_id);
  587:   Pike_stack_top=((char *)&state)+ (thread_stack_size-16384) * STACK_DIRECTION;
  588:   recoveries = NULL;
  589:   call_c_initializers(thread_id);
  590:   OBJ2THREAD(thread_id)->id=th_self();
  591:   num_threads++;
  592:   thread_table_insert(thread_id);
  593:   state->status=THREAD_RUNNING;
  594: #else
  595:   Pike_interpreter.thread_id = low_clone(thread_id_prog);
  596:   state = OBJ2THREAD(Pike_interpreter.thread_id);
  597:   Pike_interpreter.stack_top=((char *)&state)+ (thread_stack_size-16384) * STACK_DIRECTION;
  598:   Pike_interpreter.recoveries = NULL;
  599:   call_c_initializers(Pike_interpreter.thread_id);
  600:   state->id=th_self();
  601:   /*  SWAP_OUT_THREAD(OBJ2THREAD(Pike_interpreter.thread_id)); */
  602:   num_threads++;
  603:   thread_table_insert(Pike_interpreter.thread_id);
  604:   state->status=THREAD_RUNNING;
  605: #endif
  606:   state->swapped = 0;
  607: #endif 
  608:   SG(request_info).query_string = lookup_string_header("QUERY_STRING", 0);
  609:   SG(server_context) = (void *)1; /* avoid server_context == NULL */
  610: 
  611:   /* path_translated is apparently the absolute path to the file, not
  612:      the translated PATH_INFO
  613:   */
  614:   SG(request_info).path_translated =
  615:     lookup_string_header("SCRIPT_FILENAME", NULL);
  616:   SG(request_info).request_uri = lookup_string_header("DOCUMENT_URI", NULL);
  617:   if(!SG(request_info).request_uri)
  618:     SG(request_info).request_uri = lookup_string_header("SCRIPT_NAME", NULL);
  619:   SG(request_info).request_method = lookup_string_header("REQUEST_METHOD", "GET");
  620:   SG(request_info).content_length = lookup_integer_header("HTTP_CONTENT_LENGTH", 0);
  621:   SG(request_info).content_type = lookup_string_header("HTTP_CONTENT_TYPE", NULL);
  622:   SG(sapi_headers).http_response_code = 200;
  623:   if (!strcmp(SG(request_info).request_method, "HEAD")) {
  624:     SG(request_info).headers_only = 1;
  625:   } else {
  626:     SG(request_info).headers_only = 0;
  627:   }
  628: 
  629:   /* Let PHP5 handle the deconding of the AUTH */
  630:   php_handle_auth_data(lookup_string_header("HTTP_AUTHORIZATION", NULL), TSRMLS_C);
  631:    /* Swap out this thread and release the interpreter lock to allow
  632:    * Pike threads to run. We wait since the above would otherwise require
  633:    * a lot of unlock/lock.
  634:    */
  635: #ifndef USE_PIKE_LEVEL_THREADS
  636:   SWAP_OUT_THREAD(state);
  637:   mt_unlock_interpreter();
  638: #else
  639:   THREADS_ALLOW();
  640: #endif
  641: 
  642:   file_handle.type = ZEND_HANDLE_FILENAME;
  643:   file_handle.filename = THIS->filename->str;
  644:   file_handle.opened_path = NULL;
  645:   file_handle.free_filename = 0;
  646: 
  647:   THIS->written = 0;
  648:   res = php_request_startup(TSRMLS_C);
  649: 
  650:   if(res == FAILURE) {
  651:     THREAD_SAFE_RUN({
  652:       apply_svalue(&THIS->done_cb, 0);
  653:       pop_stack();
  654:       free_struct(TSRMLS_C);
  655:     }, "Negative run response");
  656:   } else {
  657:     php_execute_script(&file_handle TSRMLS_CC);
  658:     php_request_shutdown(NULL);
  659:     THREAD_SAFE_RUN({
  660:       push_int(THIS->written);
  661:       apply_svalue(&THIS->done_cb, 1);
  662:       pop_stack();
  663:       free_struct(TSRMLS_C);
  664:     }, "positive run response");
  665:   }
  666: 
  667: #ifndef USE_PIKE_LEVEL_THREADS
  668:   mt_lock_interpreter();
  669:   SWAP_IN_THREAD(state);
  670: #if PIKE_MAJOR_VERSION == 7 && PIKE_MINOR_VERSION < 1
  671:   state->status=THREAD_EXITED;
  672:   co_signal(& state->status_change);
  673:   thread_table_delete(thread_id);
  674:   free_object(thread_id);
  675:   thread_id=NULL;
  676: #else
  677:   state->status=THREAD_EXITED;
  678:   co_signal(& state->status_change);
  679:   thread_table_delete(Pike_interpreter.thread_id);
  680:   free_object(Pike_interpreter.thread_id);
  681:   Pike_interpreter.thread_id=NULL;
  682: #endif
  683:   cleanup_interpret();
  684:   num_threads--;
  685:   mt_unlock_interpreter();
  686: #else
  687:   THREADS_DISALLOW();
  688: #endif
  689: }
  690: 
  691: /*
  692:  * The php_caudium_request_handler() is called per request and handles
  693:  * everything for one request.
  694:  */
  695: 
  696: void f_php_caudium_request_handler(INT32 args)
  697: {
  698:   struct object *my_fd_obj;
  699:   struct mapping *request_data;
  700:   struct svalue *done_callback;
  701:   struct pike_string *script;
  702:   struct svalue *raw_fd;
  703:   struct pike_string *ind;
  704:   php_caudium_request *_request;
  705:   THIS = malloc(sizeof(php_caudium_request));
  706:   if(THIS == NULL)
  707:     Pike_error("Out of memory.");
  708: 
  709:   get_all_args("PHP5.Interpreter->run", args, "%S%m%O%*", &script,
  710: 	       &request_data, &my_fd_obj, &done_callback);
  711:   if(done_callback->type != PIKE_T_FUNCTION) 
  712:     Pike_error("PHP5.Interpreter->run: Bad argument 4, expected function.\n");
  713:   add_ref(request_data);
  714:   add_ref(my_fd_obj);
  715:   add_ref(script);
  716: 
  717:   THIS->request_data = request_data;
  718:   THIS->my_fd_obj = my_fd_obj;
  719:   THIS->filename = script;
  720:   assign_svalue_no_free(&THIS->done_cb, done_callback);
  721: 
  722:   ind = make_shared_binary_string("my_fd", 5);
  723:   raw_fd = low_mapping_string_lookup(THIS->request_data, ind);
  724:   if(raw_fd && raw_fd->type == PIKE_T_OBJECT)
  725:   {
  726:     int fd = fd_from_object(raw_fd->u.object);
  727:     if(fd == -1)
  728:       THIS->my_fd = 0; /* Don't send directly to this FD... */
  729:     else
  730:       THIS->my_fd = fd;
  731:   } else
  732:     THIS->my_fd = 0;
  733: #ifdef USE_PIKE_LEVEL_THREADS
  734:   php_caudium_module_main(THIS);
  735: #else
  736:   th_farm((void (*)(void *))php_caudium_module_main, THIS);
  737: #endif
  738:   pop_n_elems(args);
  739: }
  740: 
  741: static void free_struct(TSRMLS_D)
  742: {
  743:   GET_THIS();
  744:   if(THIS->request_data) free_mapping(THIS->request_data);
  745:   if(THIS->my_fd_obj)    free_object(THIS->my_fd_obj);
  746:   free_svalue(&THIS->done_cb);
  747:   if(THIS->filename)     free_string(THIS->filename);
  748:   MEMSET(THIS, 0, sizeof(php_caudium_request));
  749: }
  750: 
  751: 
  752: /*
  753:  * pike_module_init() is called by Pike once at startup
  754:  *
  755:  * This functions allocates basic structures
  756:  */
  757: 
  758: void pike_module_init( void )
  759: {
  760:   if (!caudium_php_initialized) {
  761:     caudium_php_initialized = 1;
  762:     tsrm_startup(1, 1, 0, NULL);
  763:     ts_allocate_id(&caudium_globals_id, sizeof(php_caudium_request), NULL, NULL);
  764:     sapi_startup(&caudium_sapi_module);
  765:     sapi_module.startup(&caudium_sapi_module);
  766:   }
  767:   start_new_program(); /* Text */
  768:   pike_add_function("run", f_php_caudium_request_handler,
  769: 		    "function(string, mapping, object, function:void)", 0);
  770:   end_class("Interpreter", 0);
  771: }
  772: 
  773: /*
  774:  * pike_module_exit() performs the last steps before the
  775:  * server exists. Shutdowns basic services and frees memory
  776:  */
  777: 
  778: void pike_module_exit(void)
  779: {
  780:   caudium_php_initialized = 0;
  781:   sapi_module.shutdown(&caudium_sapi_module);
  782:   tsrm_shutdown();
  783: }
  784: #endif

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