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