Annotation of embedaddon/php/sapi/caudium/caudium.c, revision 1.1
1.1 ! misho 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: caudium.c 321634 2012-01-01 13:15:04Z felipe $ */
! 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 321634 2012-01-01 13:15:04Z felipe $");
! 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>