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

    1: /*
    2:    +----------------------------------------------------------------------+
    3:    | PHP Version 5                                                        |
    4:    +----------------------------------------------------------------------+
    5:    | Copyright (c) 1997-2014 The PHP Group                                |
    6:    +----------------------------------------------------------------------+
    7:    | This source file is subject to version 3.01 of the PHP license,      |
    8:    | that is bundled with this package in the file LICENSE, and is        |
    9:    | available through the world-wide-web at the following url:           |
   10:    | http://www.php.net/license/3_01.txt                                  |
   11:    | If you did not receive a copy of the PHP license and are unable to   |
   12:    | obtain it through the world-wide-web, please send a note to          |
   13:    | license@php.net so we can mail you a copy immediately.               |
   14:    +----------------------------------------------------------------------+
   15:    | Author: Sascha Schumann <sascha@schumann.cx>                         |
   16:    +----------------------------------------------------------------------+
   17:  */
   18: 
   19: /*
   20:  * TODO:
   21:  * - write documentation
   22:  * - CGI/1.1 conformance
   23:  */
   24: 
   25: /* $Id: aolserver.c,v 1.1.1.4 2014/06/15 20:04:02 misho Exp $ */
   26: 
   27: /* conflict between PHP and AOLserver headers */
   28: #define Debug php_Debug
   29: #include "php.h"
   30: #undef Debug
   31: 
   32: #ifdef HAVE_AOLSERVER
   33: 
   34: #ifndef ZTS
   35: #error AOLserver module is only useable in thread-safe mode
   36: #endif
   37: 
   38: #include "ext/standard/info.h"
   39: #define SECTION(name)  PUTS("<h2>" name "</h2>\n")
   40: 
   41: #define NS_BUF_SIZE 511
   42: 
   43: #include "php_ini.h"
   44: #include "php_globals.h"
   45: #include "SAPI.h"
   46: #include "php_main.h"
   47: #include "php_variables.h"
   48: 
   49: #include "ns.h"
   50: 
   51: #include "php_version.h"
   52: 
   53: /* This symbol is used by AOLserver to tell the API version we expect */
   54: 
   55: int Ns_ModuleVersion = 1;
   56: 
   57: #define NSG(v) TSRMG(ns_globals_id, ns_globals_struct *, v)
   58: 
   59: /* php_ns_context is per-server (thus only once at all) */
   60: 
   61: typedef struct {
   62: 	sapi_module_struct *sapi_module;
   63: 	char *ns_server;
   64: 	char *ns_module;
   65: } php_ns_context;
   66: 
   67: /* ns_globals_struct is per-thread */
   68: 
   69: typedef struct {
   70: 	Ns_Conn *conn;
   71: 	size_t data_avail;
   72: } ns_globals_struct;
   73: 
   74: /* TSRM id */
   75: 
   76: static int ns_globals_id;
   77: 
   78: /* global context */
   79: 
   80: static php_ns_context *global_context;
   81: 
   82: static void php_ns_config(php_ns_context *ctx, char global);
   83: 
   84: /*
   85:  * php_ns_sapi_ub_write() writes data to the client connection.
   86:  */
   87: 
   88: static int
   89: php_ns_sapi_ub_write(const char *str, uint str_length TSRMLS_DC)
   90: {
   91: 	int n;
   92: 	uint sent = 0;
   93: 
   94: 	while (str_length > 0) {
   95: 		n = Ns_ConnWrite(NSG(conn), (void *) str, str_length);
   96: 
   97: 		if (n == -1)
   98: 			php_handle_aborted_connection();
   99: 
  100: 		str += n;
  101: 		sent += n;
  102: 		str_length -= n;
  103: 	}
  104: 	
  105: 	return sent;
  106: }
  107: 
  108: /*
  109:  * php_ns_sapi_header_handler() sets a HTTP reply header to be 
  110:  * sent to the client.
  111:  */
  112: 
  113: static int
  114: php_ns_sapi_header_handler(sapi_header_struct *sapi_header, sapi_headers_struct *sapi_headers TSRMLS_DC)
  115: {
  116: 	char *header_name, *header_content;
  117: 	char *p;
  118: 
  119: 	header_name = sapi_header->header;
  120: 	header_content = p = strchr(header_name, ':');
  121: 
  122: 	if (p) {
  123: 		*p = '\0';
  124: 		do {
  125: 			header_content++;
  126: 		} while (*header_content == ' ');
  127: 
  128: 		if (!strcasecmp(header_name, "Content-type")) {
  129: 			Ns_ConnSetTypeHeader(NSG(conn), header_content);
  130: 		} else {
  131: 			Ns_ConnSetHeaders(NSG(conn), header_name, header_content);
  132: 		}
  133: 
  134: 		*p = ':';
  135: 	}
  136: 
  137: 	sapi_free_header(sapi_header);
  138: 	
  139: 	return 0;
  140: }
  141: 
  142: /*
  143:  * php_ns_sapi_send_headers() flushes the headers to the client.
  144:  * Called before real content is sent by PHP.
  145:  */
  146: 
  147: static int
  148: php_ns_sapi_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC)
  149: {
  150: 	if(SG(sapi_headers).send_default_content_type) {
  151: 		Ns_ConnSetRequiredHeaders(NSG(conn), "text/html", 0);
  152: 	}
  153: 	
  154: 	Ns_ConnFlushHeaders(NSG(conn), SG(sapi_headers).http_response_code);
  155: 	
  156: 	return SAPI_HEADER_SENT_SUCCESSFULLY;
  157: }
  158: 
  159: /*
  160:  * php_ns_sapi_read_post() reads a specified number of bytes from
  161:  * the client. Used for POST/PUT requests.
  162:  */
  163: 
  164: static int
  165: php_ns_sapi_read_post(char *buf, uint count_bytes TSRMLS_DC)
  166: {
  167: 	uint max_read;
  168: 	uint total_read = 0;
  169: 
  170: 	max_read = MIN(NSG(data_avail), count_bytes);
  171: 	
  172: 	total_read = Ns_ConnRead(NSG(conn), buf, max_read);
  173: 	
  174: 	if(total_read == NS_ERROR) {
  175: 		total_read = -1;
  176: 	} else {
  177: 		NSG(data_avail) -= total_read;
  178: 	}
  179: 
  180: 	return total_read;
  181: }
  182: 
  183: /* 
  184:  * php_ns_sapi_read_cookies() returns the Cookie header from
  185:  * the HTTP request header
  186:  */
  187: 	
  188: static char *php_ns_sapi_read_cookies(TSRMLS_D)
  189: {
  190: 	int i;
  191: 	char *http_cookie = NULL;
  192: 	
  193: 	i = Ns_SetIFind(NSG(conn->headers), "cookie");
  194: 	if(i != -1) {
  195: 		http_cookie = Ns_SetValue(NSG(conn->headers), i);
  196: 	}
  197: 
  198: 	return http_cookie;
  199: }
  200: 
  201: static void php_info_aolserver(ZEND_MODULE_INFO_FUNC_ARGS)
  202: {
  203: 	char buf[512];
  204: 	int uptime = Ns_InfoUptime();
  205: 	int i;
  206: 	
  207: 	php_info_print_table_start();
  208: 	php_info_print_table_row(2, "SAPI module version", "$Id: aolserver.c,v 1.1.1.4 2014/06/15 20:04:02 misho Exp $");
  209: 	php_info_print_table_row(2, "Build date", Ns_InfoBuildDate());
  210: 	php_info_print_table_row(2, "Config file path", Ns_InfoConfigFile());
  211: 	php_info_print_table_row(2, "Error Log path", Ns_InfoErrorLog());
  212: 	php_info_print_table_row(2, "Installation path", Ns_InfoHomePath());
  213: 	php_info_print_table_row(2, "Hostname of server", Ns_InfoHostname());
  214: 	php_info_print_table_row(2, "Source code label", Ns_InfoLabel());
  215: 	php_info_print_table_row(2, "Server platform", Ns_InfoPlatform());
  216: 	snprintf(buf, 511, "%s/%s", Ns_InfoServerName(), Ns_InfoServerVersion());
  217: 	php_info_print_table_row(2, "Server version", buf);
  218: 	snprintf(buf, 511, "%d day(s), %02d:%02d:%02d", 
  219: 			uptime / 86400,
  220: 			(uptime / 3600) % 24,
  221: 			(uptime / 60) % 60,
  222: 			uptime % 60);
  223: 	php_info_print_table_row(2, "Server uptime", buf);
  224: 	php_info_print_table_end();
  225: 
  226: 	SECTION("HTTP Headers Information");
  227: 	php_info_print_table_start();
  228: 	php_info_print_table_colspan_header(2, "HTTP Request Headers");
  229: 	php_info_print_table_row(2, "HTTP Request", NSG(conn)->request->line);
  230: 	for (i = 0; i < Ns_SetSize(NSG(conn)->headers); i++) {
  231: 		php_info_print_table_row(2, Ns_SetKey(NSG(conn)->headers, i), Ns_SetValue(NSG(conn)->headers, i));
  232: 	}
  233: 
  234: 	php_info_print_table_colspan_header(2, "HTTP Response Headers");
  235: 	for (i = 0; i < Ns_SetSize(NSG(conn)->outputheaders); i++) {
  236: 		php_info_print_table_row(2, Ns_SetKey(NSG(conn)->outputheaders, i), Ns_SetValue(NSG(conn)->outputheaders, i));
  237: 	}
  238: 	php_info_print_table_end();
  239: }
  240: 
  241: PHP_FUNCTION(getallheaders);
  242: 
  243: /* {{{ arginfo */
  244: ZEND_BEGIN_ARG_INFO(arginfo_aolserver_getallheaders, 0)
  245: ZEND_END_ARG_INFO()
  246: /* }}} */
  247: 
  248: static const zend_function_entry aolserver_functions[] = {
  249: 	PHP_FE(getallheaders, arginfo_aolserver_getallheaders)
  250: 	{NULL, NULL, NULL}
  251: };
  252: 
  253: static zend_module_entry php_aolserver_module = {
  254: 	STANDARD_MODULE_HEADER,
  255: 	"AOLserver",
  256: 	aolserver_functions,
  257: 	NULL,
  258: 	NULL,
  259: 	NULL,
  260: 	NULL,
  261: 	php_info_aolserver,
  262: 	NULL,
  263: 	STANDARD_MODULE_PROPERTIES
  264: };
  265: 
  266: PHP_FUNCTION(getallheaders)
  267: {
  268: 	int i;
  269: 
  270: 	array_init(return_value);
  271: 	
  272: 	for (i = 0; i < Ns_SetSize(NSG(conn->headers)); i++) {
  273: 		char *key = Ns_SetKey(NSG(conn->headers), i);
  274: 		char *value = Ns_SetValue(NSG(conn->headers), i);
  275: 		
  276: 		add_assoc_string(return_value, key, value, 1);
  277: 	}
  278: }
  279: 
  280: static int
  281: php_ns_startup(sapi_module_struct *sapi_module)
  282: {
  283: 	if (php_module_startup(sapi_module, &php_aolserver_module, 1) == FAILURE) {
  284: 		return FAILURE;
  285: 	} else {
  286: 		return SUCCESS;
  287: 	}
  288: }
  289: 
  290: 
  291: /*
  292:  * php_ns_sapi_register_variables() populates the php script environment
  293:  * with a number of variables. HTTP_* variables are created for
  294:  * the HTTP header data, so that a script can access these.
  295:  */
  296: 
  297: #define ADD_STRINGX(name, buf)										\
  298: 	php_register_variable(name, buf, track_vars_array TSRMLS_CC)
  299: 
  300: #define ADD_STRING(name)										\
  301: 	ADD_STRINGX(name, buf)
  302: 
  303: static void
  304: php_ns_sapi_register_variables(zval *track_vars_array TSRMLS_DC)
  305: {
  306: 	int i;
  307: 	char buf[NS_BUF_SIZE + 1];
  308: 	char *tmp;
  309: 
  310: 	for(i = 0; i < Ns_SetSize(NSG(conn->headers)); i++) {
  311: 		char *key = Ns_SetKey(NSG(conn->headers), i);
  312: 		char *value = Ns_SetValue(NSG(conn->headers), i);
  313: 		char *p;
  314: 		char c;
  315: 
  316: 		snprintf(buf, NS_BUF_SIZE, "HTTP_%s", key);
  317: 		
  318: 		for(p = buf + 5; (c = *p); p++) {
  319: 			c = toupper(c);
  320: 			if(c < 'A' || c > 'Z') {
  321: 				c = '_';
  322: 			}
  323: 			*p = c;
  324: 		}
  325: 
  326: 		ADD_STRINGX(buf, value);
  327: 	}
  328: 	
  329: 	snprintf(buf, NS_BUF_SIZE, "%s/%s", Ns_InfoServerName(), Ns_InfoServerVersion());
  330: 	ADD_STRING("SERVER_SOFTWARE");
  331: 	snprintf(buf, NS_BUF_SIZE, "HTTP/%1.1f", NSG(conn)->request->version);
  332: 	ADD_STRING("SERVER_PROTOCOL");
  333: 
  334: 	ADD_STRINGX("REQUEST_METHOD", NSG(conn)->request->method);
  335: 
  336: 	if(NSG(conn)->request->query)
  337: 		ADD_STRINGX("QUERY_STRING", NSG(conn)->request->query);
  338: 	
  339: 	ADD_STRINGX("SERVER_BUILDDATE", Ns_InfoBuildDate());
  340: 
  341: 	ADD_STRINGX("REMOTE_ADDR", Ns_ConnPeer(NSG(conn)));
  342: 
  343: 	snprintf(buf, NS_BUF_SIZE, "%d", Ns_ConnPeerPort(NSG(conn)));
  344: 	ADD_STRING("REMOTE_PORT");
  345: 
  346: 	snprintf(buf, NS_BUF_SIZE, "%d", Ns_ConnPort(NSG(conn)));
  347: 	ADD_STRING("SERVER_PORT");
  348: 
  349: 	tmp = Ns_ConnHost(NSG(conn));
  350: 	if (tmp)
  351: 		ADD_STRINGX("SERVER_NAME", tmp);
  352: 
  353: 	ADD_STRINGX("PATH_TRANSLATED", SG(request_info).path_translated);
  354: 	ADD_STRINGX("REQUEST_URI", SG(request_info).request_uri);
  355: 	ADD_STRINGX("PHP_SELF", SG(request_info).request_uri);
  356: 
  357: 	ADD_STRINGX("GATEWAY_INTERFACE", "CGI/1.1");
  358: 
  359: 	snprintf(buf, NS_BUF_SIZE, "%d", Ns_InfoBootTime());
  360: 	ADD_STRING("SERVER_BOOTTIME");
  361: }
  362: 
  363: 
  364: 
  365: /* this structure is static (as in "it does not change") */
  366: 
  367: static sapi_module_struct aolserver_sapi_module = {
  368: 	"aolserver",
  369: 	"AOLserver",
  370: 
  371: 	php_ns_startup,							/* startup */
  372: 	php_module_shutdown_wrapper,			/* shutdown */
  373: 
  374: 	NULL,									/* activate */
  375: 	NULL,									/* deactivate */
  376: 
  377: 	php_ns_sapi_ub_write,					/* unbuffered write */
  378: 	NULL,									/* flush */
  379: 	NULL,									/* get uid */
  380: 	NULL,									/* getenv */
  381: 
  382: 	php_error,								/* error handler */
  383: 
  384: 	php_ns_sapi_header_handler,				/* header handler */
  385: 	php_ns_sapi_send_headers,				/* send headers handler */
  386: 	NULL,									/* send header handler */
  387: 
  388: 	php_ns_sapi_read_post,					/* read POST data */
  389: 	php_ns_sapi_read_cookies,				/* read Cookies */
  390: 
  391: 	php_ns_sapi_register_variables,
  392: 	NULL,									/* Log message */
  393: 	NULL,									/* Get request time */
  394: 	NULL,							/* child terminate */
  395: 
  396: 	STANDARD_SAPI_MODULE_PROPERTIES
  397: };
  398: 
  399: /*
  400:  * php_ns_module_main() is called by the per-request handler and
  401:  * "executes" the script
  402:  */
  403: 
  404: static int
  405: php_ns_module_main(TSRMLS_D)
  406: {
  407: 	zend_file_handle file_handle;
  408: 
  409: 	file_handle.type = ZEND_HANDLE_FILENAME;
  410: 	file_handle.filename = SG(request_info).path_translated;
  411: 	file_handle.free_filename = 0;
  412: 	file_handle.opened_path = NULL;
  413: 	
  414: 	php_ns_config(global_context, 0);
  415: 	if (php_request_startup(TSRMLS_C) == FAILURE) {
  416: 		return NS_ERROR;
  417: 	}
  418: 	
  419: 	php_execute_script(&file_handle TSRMLS_CC);
  420: 	php_request_shutdown(NULL);
  421: 
  422: 	return NS_OK;
  423: }
  424: 
  425: /*
  426:  * php_ns_request_ctor() initializes the per-request data structure
  427:  * and fills it with data provided by the web server
  428:  */
  429: 
  430: static void 
  431: php_ns_request_ctor(TSRMLS_D)
  432: {
  433: 	char *server;
  434: 	Ns_DString ds;
  435: 	char *root;
  436: 	int index;
  437: 	char *tmp;
  438: 	
  439: 	server = Ns_ConnServer(NSG(conn));
  440: 	
  441: #define safe_strdup(x) ((x)?strdup((x)):NULL)
  442: 	SG(request_info).query_string = safe_strdup(NSG(conn->request->query));
  443: 
  444: 	Ns_DStringInit(&ds);
  445: 	Ns_UrlToFile(&ds, server, NSG(conn->request->url));
  446: 	
  447: 	/* path_translated is the absolute path to the file */
  448: 	SG(request_info).path_translated = safe_strdup(Ns_DStringValue(&ds));
  449: 	Ns_DStringFree(&ds);
  450: 	root = Ns_PageRoot(server);
  451: 	SG(request_info).request_uri = strdup(SG(request_info).path_translated + strlen(root));
  452: 	SG(request_info).request_method = NSG(conn)->request->method;
  453: 	if(NSG(conn)->request->version > 1.0) SG(request_info).proto_num = 1001;
  454: 	else SG(request_info).proto_num = 1000;
  455: 	SG(request_info).content_length = Ns_ConnContentLength(NSG(conn));
  456: 	index = Ns_SetIFind(NSG(conn)->headers, "content-type");
  457: 	SG(request_info).content_type = index == -1 ? NULL : 
  458: 		Ns_SetValue(NSG(conn)->headers, index);
  459: 	SG(sapi_headers).http_response_code = 200;
  460: 
  461: 	tmp = Ns_ConnAuthUser(NSG(conn));
  462: 	if (tmp)
  463: 		tmp = estrdup(tmp);
  464: 	SG(request_info).auth_user = tmp;
  465: 
  466: 	tmp = Ns_ConnAuthPasswd(NSG(conn));
  467: 	if (tmp)
  468: 		tmp = estrdup(tmp);
  469: 	SG(request_info).auth_password = tmp;
  470: 
  471: 	NSG(data_avail) = SG(request_info).content_length;
  472: }
  473: 
  474: /*
  475:  * php_ns_request_dtor() destroys all data associated with
  476:  * the per-request structure 
  477:  */
  478: 
  479: static void
  480: php_ns_request_dtor(TSRMLS_D)
  481: {
  482: 	free(SG(request_info).path_translated);
  483: 	if (SG(request_info).query_string)
  484: 		free(SG(request_info).query_string);
  485: 	free(SG(request_info).request_uri);
  486: }
  487: 
  488: /*
  489:  * The php_ns_request_handler() is called per request and handles
  490:  * everything for one request.
  491:  */
  492: 
  493: static int
  494: php_ns_request_handler(void *context, Ns_Conn *conn)
  495: {
  496: 	int status = NS_OK;
  497: 	TSRMLS_FETCH();
  498: 	
  499: 	NSG(conn) = conn;
  500: 	
  501: 	SG(server_context) = global_context;
  502: 
  503: 	php_ns_request_ctor(TSRMLS_C);
  504: 	
  505: 	status = php_ns_module_main(TSRMLS_C);
  506: 	
  507: 	php_ns_request_dtor(TSRMLS_C);
  508: 
  509: 	return status;
  510: }
  511: 
  512: /*
  513:  * php_ns_config() fetches the configuration data.
  514:  *
  515:  * It understands the "map" and "php_value" command.
  516:  */
  517: 
  518: static void 
  519: php_ns_config(php_ns_context *ctx, char global)
  520: {
  521: 	int i;
  522: 	char *path;
  523: 	Ns_Set *set;
  524: 
  525: 	path = Ns_ConfigGetPath(ctx->ns_server, ctx->ns_module, NULL);
  526: 	set = Ns_ConfigGetSection(path);
  527: 
  528: 	for (i = 0; set && i < Ns_SetSize(set); i++) {
  529: 		char *key = Ns_SetKey(set, i);
  530: 		char *value = Ns_SetValue(set, i);
  531: 
  532: 		if (global && !strcasecmp(key, "map")) {
  533: 			Ns_Log(Notice, "Registering PHP for \"%s\"", value);
  534: 			Ns_RegisterRequest(ctx->ns_server, "GET", value, php_ns_request_handler, NULL, ctx, 0);
  535: 			Ns_RegisterRequest(ctx->ns_server, "POST", value, php_ns_request_handler, NULL, ctx, 0);
  536: 			Ns_RegisterRequest(ctx->ns_server, "HEAD", value, php_ns_request_handler, NULL, ctx, 0);
  537: 
  538: 	/* 
  539: 	 * Deactivated for now. The ini system will cause random crashes when 
  540: 	 * accessed from here (since there are no locks to protect the global 
  541: 	 * known_directives) 
  542: 	 */
  543: 
  544: 		} else if (!global && !strcasecmp(key, "php_value")) {
  545: 			Ns_Log(Notice, "php_value has been deactivated temporarily. Please use a php.ini file to pass directives to PHP. Thanks.");
  546: #if 0
  547: 			char *val;
  548: 
  549: 			val = strchr(value, ' ');
  550: 			if (val) {
  551: 				char *new_key;
  552: 				
  553: 				new_key = estrndup(value, val - value);
  554: 				
  555: 				do { 
  556: 					val++; 
  557: 				} while(*val == ' ');
  558: 
  559: 				Ns_Log(Debug, "PHP configuration option '%s=%s'", new_key, val);
  560: 				zend_alter_ini_entry(new_key, strlen(new_key) + 1, val, 
  561: 						strlen(val) + 1, PHP_INI_SYSTEM, PHP_INI_STAGE_ACTIVATE);
  562: 				
  563: 				efree(new_key);
  564: 			}
  565: #endif
  566: 		}
  567: 		
  568: 	}
  569: }
  570: 	
  571: /*
  572:  * php_ns_server_shutdown() performs the last steps before the
  573:  * server exits. Shutdowns basic services and frees memory
  574:  */
  575: 
  576: static void
  577: php_ns_server_shutdown(void *context)
  578: {
  579: 	php_ns_context *ctx = (php_ns_context *) context;
  580: 	
  581: 	ctx->sapi_module->shutdown(ctx->sapi_module);
  582: 	sapi_shutdown();
  583: 	tsrm_shutdown();
  584: 
  585: 	free(ctx->ns_module);
  586: 	free(ctx->ns_server);
  587: 	free(ctx);
  588: }
  589: 
  590: /*
  591:  * Ns_ModuleInit() is called by AOLserver once at startup
  592:  *
  593:  * This functions allocates basic structures and initializes
  594:  * basic services.
  595:  */
  596: 
  597: int Ns_ModuleInit(char *server, char *module)
  598: {
  599: 	php_ns_context *ctx;
  600: 	
  601: 	tsrm_startup(1, 1, 0, NULL);
  602: 	sapi_startup(&aolserver_sapi_module);
  603: 	sapi_module.startup(&aolserver_sapi_module);
  604: 	
  605: 	/* TSRM is used to allocate a per-thread structure */
  606: 	ts_allocate_id(&ns_globals_id, sizeof(ns_globals_struct), NULL, NULL);
  607: 	
  608: 	/* the context contains data valid for all threads */
  609: 	ctx = malloc(sizeof *ctx);
  610: 	ctx->sapi_module = &aolserver_sapi_module;
  611: 	ctx->ns_server = strdup(server);
  612: 	ctx->ns_module = strdup(module);
  613: 	
  614: 	/* read the configuration */
  615: 	php_ns_config(ctx, 1);
  616: 
  617: 	global_context = ctx;
  618: 
  619: 	/* register shutdown handler */
  620: 	Ns_RegisterServerShutdown(server, php_ns_server_shutdown, ctx);
  621: 
  622: 	return NS_OK;
  623: }
  624: 
  625: #endif

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