Return to caudium.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / php / sapi / caudium |
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