Annotation of embedaddon/php/sapi/caudium/caudium.c, revision 1.1.1.3

1.1       misho       1: /* 
                      2:    +----------------------------------------------------------------------+
                      3:    | PHP Version 5                                                        |
                      4:    +----------------------------------------------------------------------+
1.1.1.3 ! misho       5:    | Copyright (c) 1997-2013 The PHP Group                                |
1.1       misho       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: 
1.1.1.2   misho      20: /* $Id$ */
1.1       misho      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();
1.1.1.2   misho     447:   php_info_print_table_row(2, "SAPI module version", "$Id$");
1.1       misho     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>