File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / php / sapi / milter / php_milter.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue May 29 12:34:35 2012 UTC (12 years, 2 months ago) by misho
Branches: php, MAIN
CVS tags: v5_4_3elwix, v5_4_17p0, HEAD
php 5.4.3+patches

    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: Harald Radi <phanto@php.net>                                 |
   16:    |         Parts based on CGI SAPI Module by                            |
   17:    |         Rasmus Lerdorf, Stig Bakken and Zeev Suraski                 |
   18:    +----------------------------------------------------------------------+
   19: */
   20: 
   21: /* $Id: php_milter.c,v 1.1.1.2 2012/05/29 12:34:35 misho Exp $ */
   22: 
   23: #include "php.h"
   24: #include "php_globals.h"
   25: #include "php_variables.h"
   26: #include "zend_modules.h"
   27: 
   28: #ifndef ZTS
   29: #error SRM sapi module is only useable in thread-safe mode
   30: #endif
   31: 
   32: #include "SAPI.h"
   33: 
   34: #include <stdio.h>
   35: #include "php.h"
   36: #if HAVE_SYS_TIME_H
   37: #include <sys/time.h>
   38: #endif
   39: #if HAVE_UNISTD_H
   40: #include <unistd.h>
   41: #endif
   42: #if HAVE_SIGNAL_H
   43: #include <signal.h>
   44: #endif
   45: #if HAVE_SETLOCALE
   46: #include <locale.h>
   47: #endif
   48: #include "zend.h"
   49: #include "zend_extensions.h"
   50: #include "php_ini.h"
   51: #include "php_globals.h"
   52: #include "php_main.h"
   53: #include "fopen_wrappers.h"
   54: #include "ext/standard/php_standard.h"
   55: 
   56: #ifdef __riscos__
   57: #include <unixlib/local.h>
   58: #endif
   59: 
   60: #include "zend_compile.h"
   61: #include "zend_execute.h"
   62: #include "zend_highlight.h"
   63: #include "zend_indent.h"
   64: 
   65: #include "libmilter/mfapi.h"
   66: 
   67: #include "php_getopt.h"
   68: 
   69: #define OPTSTRING "ac:d:Def:hnp:vVz:?"
   70: #define MG(v)  TSRMG(milter_globals_id, zend_milter_globals *, v)
   71: 
   72: #define IS_NONE "%s(): This function must not be called outside of a milter callback function's scope"
   73: #define NOT_EOM "%s(): This function can only be used inside the milter_eom callback's scope"
   74: #define NOT_INIT "%s(): This function can only be used inside the milter_init callback's scope"
   75: 
   76: #define MLFI_NONE		0
   77: #define MLFI_CONNECT	1
   78: #define MLFI_HELO		2
   79: #define MLFI_ENVFROM	3
   80: #define MLFI_ENVRCPT	4
   81: #define MLFI_HEADER		5
   82: #define MLFI_EOH		6
   83: #define MLFI_BODY		7
   84: #define MLFI_EOM		8
   85: #define MLFI_ABORT		9
   86: #define MLFI_CLOSE		10
   87: #define MLFI_INIT		11
   88: 
   89: /* {{{ globals
   90:  */
   91: extern char *ap_php_optarg;
   92: extern int ap_php_optind;
   93: 
   94: static int flag_debug=0;
   95: static char *filename = NULL;
   96: 
   97: /* per thread */
   98: ZEND_BEGIN_MODULE_GLOBALS(milter)
   99: 	SMFICTX *ctx;
  100: 	int state;
  101: 	int initialized;
  102: ZEND_END_MODULE_GLOBALS(milter)
  103: 
  104: ZEND_DECLARE_MODULE_GLOBALS(milter)
  105: /* }}} */
  106: 
  107: /* this method is called only once when the milter starts */
  108: /* {{{ Init Milter
  109: */
  110: static int mlfi_init()
  111: {
  112: 	int ret = 0;
  113: 	zend_file_handle file_handle;
  114: 	zval function_name, retval;
  115: 	int status;
  116: 	TSRMLS_FETCH();
  117: 
  118: 	/* request startup */
  119: 	if (php_request_startup(TSRMLS_C)==FAILURE) {
  120: 		SG(headers_sent) = 1;
  121: 		SG(request_info).no_headers = 1;
  122: 		php_request_shutdown((void *) 0);
  123: 
  124: 		return -1;
  125: 	}
  126: 	
  127: 	/* disable headers */
  128: 	SG(headers_sent) = 1;
  129: 	SG(request_info).no_headers = 1;
  130: 	 
  131: 	if (filename == NULL) {
  132: 		php_printf("No input file specified");
  133: 		return SMFIS_TEMPFAIL;
  134: 	}
  135: 
  136: 	if (!(file_handle.handle.fp = VCWD_FOPEN(filename, "rb"))) {
  137: 		php_printf("Could not open input file: %s\n", filename);
  138: 		return SMFIS_TEMPFAIL;
  139: 	}
  140: 
  141: 	file_handle.type = ZEND_HANDLE_FP;
  142: 	file_handle.filename = filename;
  143: 	file_handle.free_filename = 0;
  144: 	file_handle.opened_path = NULL;
  145: 
  146: 	php_execute_script(&file_handle TSRMLS_CC);
  147: 	
  148: 	/* call userland */
  149: 	INIT_ZVAL(function_name);
  150: 
  151: 	ZVAL_STRING(&function_name, "milter_init", 0);
  152: 
  153: 	/* set the milter context for possible use in API functions */
  154: 	MG(state) = MLFI_INIT;
  155: 
  156: 	status = call_user_function(CG(function_table), NULL, &function_name, &retval, 0, NULL TSRMLS_CC);
  157: 
  158: 	MG(state) = MLFI_NONE;
  159: 	MG(initialized) = 1;
  160: 
  161: 	if (status == SUCCESS && Z_TYPE(retval) == IS_LONG) {
  162: 		ret = Z_LVAL(retval);
  163: 	}
  164: 	
  165: 	php_request_shutdown((void *) 0);
  166: 	
  167: 	return ret;
  168: }
  169: /* }}} */
  170: 
  171: /* {{{ Milter callback functions
  172:  */
  173: 
  174: /* connection info filter, is called whenever sendmail connects to the milter */
  175: /* {{{ mlfi_connect()
  176: */
  177: static sfsistat	mlfi_connect(SMFICTX *ctx, char *hostname, _SOCK_ADDR *hostaddr)
  178: {
  179: 	zend_file_handle file_handle;
  180: 	zval function_name, retval, *param[1];
  181: 	int status;
  182: 	TSRMLS_FETCH();
  183: 
  184: 	/* request startup */
  185: 	if (php_request_startup(TSRMLS_C)==FAILURE) {
  186: 		SG(headers_sent) = 1;
  187: 		SG(request_info).no_headers = 1;
  188: 		php_request_shutdown((void *) 0);
  189: 
  190: 		return SMFIS_TEMPFAIL;
  191: 	}
  192: 	
  193: 	/* disable headers */
  194: 	SG(headers_sent) = 1;
  195: 	SG(request_info).no_headers = 1;
  196: 	
  197: 	if (filename == NULL) {
  198: 		php_printf("No input file specified");
  199: 		return SMFIS_TEMPFAIL;
  200: 	}
  201: 	
  202: 	if (!(file_handle.handle.fp = VCWD_FOPEN(filename, "rb"))) {
  203: 		php_printf("Could not open input file: %s\n", filename);
  204: 		return SMFIS_TEMPFAIL;
  205: 	}
  206: 
  207: 	file_handle.type = ZEND_HANDLE_FP;
  208: 	file_handle.filename = filename;
  209: 	file_handle.free_filename = 0;
  210: 	file_handle.opened_path = NULL;
  211: 
  212: 	php_execute_script(&file_handle TSRMLS_CC);
  213: 	
  214: 	/* call userland */
  215: 	INIT_ZVAL(function_name);
  216: 
  217: 	ALLOC_ZVAL(param[0]);
  218: 	INIT_PZVAL(param[0]);
  219: 
  220: 	ZVAL_STRING(&function_name, "milter_connect", 0);
  221: 	ZVAL_STRING(param[0], hostname, 1);
  222: 
  223: 	/* set the milter context for possible use in API functions */
  224: 	MG(ctx) = ctx;
  225: 	MG(state) = MLFI_CONNECT;
  226: 
  227: 	status = call_user_function(CG(function_table), NULL, &function_name, &retval, 1, param TSRMLS_CC);
  228: 
  229: 	MG(state) = MLFI_NONE;
  230: 	zval_ptr_dtor(param);
  231: 	if (status == SUCCESS && Z_TYPE(retval) == IS_LONG) {
  232: 		return Z_LVAL(retval);
  233: 	}
  234: 	
  235: 	return SMFIS_CONTINUE;
  236: }
  237: /* }}} */
  238: 
  239: /* SMTP HELO command filter */
  240: /* {{{ mlfi_helo()
  241: */
  242: static sfsistat mlfi_helo(SMFICTX *ctx, char *helohost)
  243: {
  244: 	zval function_name, retval, *param[1];
  245: 	int status;
  246: 	TSRMLS_FETCH();
  247: 
  248: 	/* call userland */
  249: 	INIT_ZVAL(function_name);
  250: 	
  251: 	ALLOC_ZVAL(param[0]);
  252: 	INIT_PZVAL(param[0]);
  253: 
  254: 	ZVAL_STRING(&function_name, "milter_helo", 0);
  255: 	ZVAL_STRING(param[0], helohost, 1);
  256: 
  257: 	/* set the milter context for possible use in API functions */
  258: 	MG(ctx) = ctx;
  259: 	MG(state) = MLFI_HELO;
  260: 	
  261: 	status = call_user_function(CG(function_table), NULL, &function_name, &retval, 1, param TSRMLS_CC);
  262: 
  263: 	MG(state) = MLFI_NONE;
  264: 	zval_ptr_dtor(param);
  265: 	
  266: 	if (status == SUCCESS && Z_TYPE(retval) == IS_LONG) {
  267: 		return Z_LVAL(retval);
  268: 	}
  269: 	
  270: 	return SMFIS_CONTINUE;
  271: }
  272: /* }}} */
  273: 
  274: /* envelope sender filter */
  275: /* {{{ mlfi_envform()
  276: */
  277: static sfsistat mlfi_envfrom(SMFICTX *ctx, char **argv)
  278: {
  279: 	zval function_name, retval, *param[1];
  280: 	int status;
  281: 	TSRMLS_FETCH();
  282: 
  283: 	/* call userland */
  284: 	INIT_ZVAL(function_name);
  285: 	
  286: 	ALLOC_ZVAL(param[0]);
  287: 	INIT_PZVAL(param[0]);
  288: 
  289: 	ZVAL_STRING(&function_name, "milter_envfrom", 0);
  290: 	array_init(param[0]);
  291: 
  292: 	while (*argv) {
  293: 		add_next_index_string(param[0], *argv, 1);
  294: 		argv++;
  295: 	}
  296: 
  297: 	/* set the milter context for possible use in API functions */
  298: 	MG(ctx) = ctx;
  299: 	MG(state) = MLFI_ENVFROM;
  300: 	
  301: 	status = call_user_function(CG(function_table), NULL, &function_name, &retval, 1, param TSRMLS_CC);
  302: 
  303: 	MG(state) = MLFI_NONE;
  304: 	zval_ptr_dtor(param);
  305: 	
  306: 	if (status == SUCCESS && Z_TYPE(retval) == IS_LONG) {
  307: 		return Z_LVAL(retval);
  308: 	}
  309: 
  310: 	return SMFIS_CONTINUE;
  311: }
  312: /* }}} */
  313: 
  314: /* envelope recipient filter */
  315: /* {{{ mlfi_envrcpt()
  316: */
  317: static sfsistat mlfi_envrcpt(SMFICTX *ctx, char **argv)
  318: {
  319: 	zval function_name, retval, *param[1];
  320: 	int status;
  321: 	TSRMLS_FETCH();
  322: 
  323: 	/* call userland */
  324: 	INIT_ZVAL(function_name);
  325: 	
  326: 	ALLOC_ZVAL(param[0]);
  327: 	INIT_PZVAL(param[0]);
  328: 
  329: 	ZVAL_STRING(&function_name, "milter_envrcpt", 0);
  330: 	array_init(param[0]);
  331: 
  332: 	while (*argv) {
  333: 		add_next_index_string(param[0], *argv, 1);
  334: 		argv++;
  335: 	}
  336: 
  337: 	/* set the milter context for possible use in API functions */
  338: 	MG(ctx) = ctx;
  339: 	MG(state) = MLFI_ENVRCPT;
  340: 	
  341: 	status = call_user_function(CG(function_table), NULL, &function_name, &retval, 1, param TSRMLS_CC);
  342: 
  343: 	MG(state) = MLFI_NONE;
  344: 	
  345: 	zval_ptr_dtor(param);
  346: 	
  347: 	if (status == SUCCESS && Z_TYPE(retval) == IS_LONG) {
  348: 		return Z_LVAL(retval);
  349: 	}
  350: 
  351: 	return SMFIS_CONTINUE;
  352: }
  353: /* }}} */
  354: 
  355: /* header filter */
  356: /* {{{ mlfi_header()
  357: */
  358: static sfsistat mlfi_header(SMFICTX *ctx, char *headerf, char *headerv)
  359: {
  360: 	zval function_name, retval, *param[2];
  361: 	int status;
  362: 	TSRMLS_FETCH();
  363: 
  364: 	/* call userland */
  365: 	INIT_ZVAL(function_name);
  366: 	
  367: 	ALLOC_ZVAL(param[0]);
  368: 	ALLOC_ZVAL(param[1]);
  369: 	INIT_PZVAL(param[0]);
  370: 	INIT_PZVAL(param[1]);
  371: 	
  372: 	ZVAL_STRING(&function_name, "milter_header", 0);
  373: 	ZVAL_STRING(param[0], headerf, 1);
  374: 	ZVAL_STRING(param[1], headerv, 1);
  375: 
  376: 	/* set the milter context for possible use in API functions */
  377: 	MG(ctx) = ctx;
  378: 	MG(state) = MLFI_HEADER;
  379: 	
  380: 	status = call_user_function(CG(function_table), NULL, &function_name, &retval, 2, param TSRMLS_CC);
  381: 
  382: 	MG(state) = MLFI_NONE;
  383: 	
  384: 	zval_ptr_dtor(&param[0]);
  385: 	zval_ptr_dtor(&param[1]);	
  386: 	
  387: 	if (status == SUCCESS && Z_TYPE(retval) == IS_LONG) {
  388: 		return Z_LVAL(retval);
  389: 	}
  390: 	
  391: 	return SMFIS_CONTINUE;
  392: }
  393: /* }}} */
  394: 
  395: /* end of header */
  396: /* {{{ mlfi_eoh()
  397: */
  398: static sfsistat mlfi_eoh(SMFICTX *ctx)
  399: {
  400: 	zval function_name, retval;
  401: 	int status;
  402: 	TSRMLS_FETCH();
  403: 
  404: 	/* call userland */
  405: 	INIT_ZVAL(function_name);
  406: 	ZVAL_STRING(&function_name, "milter_eoh", 0);
  407: 
  408: 	/* set the milter context for possible use in API functions */
  409: 	MG(ctx) = ctx;
  410: 	MG(state) = MLFI_EOH;
  411: 	
  412: 	status = call_user_function(CG(function_table), NULL, &function_name, &retval, 0, NULL TSRMLS_CC);
  413: 
  414: 	MG(state) = MLFI_NONE;
  415: 	
  416: 	if (status == SUCCESS && Z_TYPE(retval) == IS_LONG) {
  417: 		return Z_LVAL(retval);
  418: 	}
  419: 
  420: 	return SMFIS_CONTINUE;
  421: }
  422: /* }}} */
  423: 
  424: /* body block */
  425: /* {{{ mlfi_body()
  426: */
  427: static sfsistat mlfi_body(SMFICTX *ctx, u_char *bodyp, size_t len)
  428: {
  429: 	zval function_name, retval, *param[1];
  430: 	int status;
  431: 	TSRMLS_FETCH();
  432: 
  433: 	/* call userland */
  434: 	INIT_ZVAL(function_name);
  435: 	
  436: 	ALLOC_ZVAL(param[0]);
  437: 	INIT_PZVAL(param[0]);
  438: 
  439: 	ZVAL_STRING(&function_name, "milter_body", 0);
  440: 	ZVAL_STRINGL(param[0], (char*)bodyp, len, 1); /*alex*/
  441: 	
  442: 	/* set the milter context for possible use in API functions */
  443: 	MG(ctx) = ctx;
  444: 	MG(state) = MLFI_BODY;
  445: 	
  446: 	status = call_user_function(CG(function_table), NULL, &function_name, &retval, 1, param TSRMLS_CC);
  447: 
  448: 	MG(state) = MLFI_NONE;
  449: 	
  450: 	zval_ptr_dtor(param);	
  451: 
  452: 	if (status == SUCCESS && Z_TYPE(retval) == IS_LONG) {
  453: 		return Z_LVAL(retval);
  454: 	}
  455: 
  456: 	return SMFIS_CONTINUE;
  457: }
  458: /* }}} */
  459: 
  460: /* end of message */
  461: /* {{{ mlfi_eom()
  462: */
  463: static sfsistat mlfi_eom(SMFICTX *ctx)
  464: {
  465: 	zval function_name, retval;
  466: 	int status;
  467: 	TSRMLS_FETCH();
  468: 
  469: 	/* call userland */
  470: 	INIT_ZVAL(function_name);
  471: 	ZVAL_STRING(&function_name, "milter_eom", 0);
  472: 	
  473: 	/* set the milter context for possible use in API functions */
  474: 	MG(ctx) = ctx;
  475: 	MG(state) = MLFI_EOM;
  476: 
  477: 	status = call_user_function(CG(function_table), NULL, &function_name, &retval, 0, NULL TSRMLS_CC);
  478: 
  479: 	MG(state) = MLFI_NONE;
  480: 	
  481: 	if (status == SUCCESS && Z_TYPE(retval) == IS_LONG) {
  482: 		return Z_LVAL(retval);
  483: 	}
  484: 
  485: 	return SMFIS_CONTINUE;
  486: }
  487: /* }}} */
  488: 
  489: /* message aborted */
  490: /* {{{ mlfi_abort()
  491: */
  492: static sfsistat mlfi_abort(SMFICTX *ctx)
  493: {
  494: 	zval function_name, retval;
  495: 	int status;
  496: 	TSRMLS_FETCH();
  497: 
  498: 	/* call userland */
  499: 	INIT_ZVAL(function_name);
  500: 	ZVAL_STRING(&function_name, "milter_abort", 0);
  501: 	
  502: 	/* set the milter context for possible use in API functions */
  503: 	MG(ctx) = ctx;
  504: 	MG(state) = MLFI_ABORT;
  505: 	
  506: 	status = call_user_function(CG(function_table), NULL, &function_name, &retval, 0, NULL TSRMLS_CC);
  507: 
  508: 	MG(state) = MLFI_NONE;
  509: 	
  510: 	if (status == SUCCESS && Z_TYPE(retval) == IS_LONG) {
  511: 		return Z_LVAL(retval);
  512: 	}
  513: 
  514: 	return SMFIS_CONTINUE;
  515: }
  516: /* }}} */
  517: 
  518: /* connection cleanup */
  519: /* {{{ mlfi_close()
  520: */
  521: static sfsistat mlfi_close(SMFICTX *ctx)
  522: {
  523: 	int ret = SMFIS_CONTINUE;
  524: 	zval function_name, retval;
  525: 	int status;
  526: 	TSRMLS_FETCH();
  527: 
  528: 	/* call userland */
  529: 	INIT_ZVAL(function_name);
  530: 	ZVAL_STRING(&function_name, "milter_close", 0);
  531: 	
  532: 	/* set the milter context for possible use in API functions */
  533: 	MG(ctx) = ctx;
  534: 	MG(state) = MLFI_CLOSE;
  535: 	
  536: 	status = call_user_function(CG(function_table), NULL, &function_name, &retval, 0, NULL TSRMLS_CC);
  537: 
  538: 	MG(state) = MLFI_NONE;
  539: 	
  540: 	if (status == SUCCESS && Z_TYPE(retval) == IS_LONG) {
  541: 		ret = Z_LVAL(retval);
  542: 	}
  543: 	
  544: 	php_request_shutdown((void *) 0);
  545: 
  546: 	return ret;
  547: }
  548: /* }}} */
  549: /* }}} */
  550: 
  551: /* {{{ Milter entry struct
  552:  */
  553: struct smfiDesc smfilter = {
  554:     "php-milter",	/* filter name */
  555:     SMFI_VERSION,   /* version code -- leave untouched */
  556:     0,				/* flags */
  557:     mlfi_connect,	/* info filter callback */
  558:     mlfi_helo,		/* HELO filter callback */
  559:     mlfi_envfrom,	/* envelope filter callback */
  560:     mlfi_envrcpt,	/* envelope recipient filter callback */
  561:     mlfi_header,	/* header filter callback */
  562:     mlfi_eoh,		/* end of header callback */
  563:     mlfi_body,		/* body filter callback */
  564:     mlfi_eom,		/* end of message callback */
  565:     mlfi_abort,		/* message aborted callback */
  566:     mlfi_close,		/* connection cleanup callback */
  567: };
  568: /* }}} */
  569: 
  570: /* {{{ PHP Milter API
  571:  */
  572: 
  573: /* {{{ proto void smfi_setflags(long flags)
  574:    Sets the flags describing the actions the filter may take. */	
  575: PHP_FUNCTION(smfi_setflags)
  576: {
  577: 	long flags;
  578: 	
  579: 	/* valid only in the init callback */
  580: 	if (MG(state) != MLFI_INIT) {
  581: 		php_error(E_WARNING, NOT_INIT, get_active_function_name(TSRMLS_C));
  582: 	} else if (zend_parse_parameters(1 TSRMLS_CC, "l", &flags) == SUCCESS) {
  583: 		flags = flags & (SMFIF_ADDHDRS|SMFIF_CHGHDRS|SMFIF_CHGBODY|SMFIF_ADDRCPT|SMFIF_DELRCPT);
  584: 		smfilter.xxfi_flags = flags;
  585: 	}	
  586: }
  587: /* }}} */
  588: 
  589: /* {{{ proto void smfi_settimeout(long timeout)
  590:    Sets the number of seconds libmilter will wait for an MTA connection before timing out a socket. */	
  591: PHP_FUNCTION(smfi_settimeout)
  592: {
  593: 	long timeout;
  594: 	
  595: 	/* valid only in the init callback */
  596: 	if (MG(state) != MLFI_INIT) {
  597: 		php_error(E_WARNING, NOT_INIT, get_active_function_name(TSRMLS_C));
  598: 	} else if (zend_parse_parameters(1 TSRMLS_CC, "l", &timeout) == SUCCESS) {
  599: 		smfi_settimeout(timeout);
  600: 	}	
  601: }
  602: /* }}} */
  603: 
  604: /* {{{ proto string smfi_getsymval(string macro)
  605:    Returns the value of the given macro or NULL if the macro is not defined. */	
  606: PHP_FUNCTION(smfi_getsymval)
  607: {
  608: 	char *symname, *ret;
  609: 	int len;
  610: 
  611: 	/* valid in any callback */
  612: 	if (MG(state) == MLFI_NONE) {
  613: 		php_error(E_WARNING, IS_NONE, get_active_function_name(TSRMLS_C));
  614: 	} else if (zend_parse_parameters(1 TSRMLS_CC, "s", &symname, &len) == SUCCESS) {
  615: 		if ((ret = smfi_getsymval(MG(ctx), symname)) != NULL) {
  616: 			RETURN_STRING(ret, 1);
  617: 		}
  618: 	}
  619: 
  620: 	RETURN_NULL();
  621: }
  622: /* }}} */
  623: 
  624: /* {{{ proto bool smfi_setreply(string rcode, string xcode, string message)
  625:    Directly set the SMTP error reply code for this connection.
  626:    This code will be used on subsequent error replies resulting from actions taken by this filter. */	
  627: PHP_FUNCTION(smfi_setreply)
  628: {
  629: 	char *rcode, *xcode, *message;
  630: 	int len;
  631: 	
  632: 	/* valid in any callback */
  633: 	if (MG(state) == MLFI_NONE) {
  634: 		php_error(E_WARNING, IS_NONE, get_active_function_name(TSRMLS_C));
  635: 	} else if (zend_parse_parameters(3 TSRMLS_CC, "sss", &rcode, &len, &xcode, &len, &message, &len) == SUCCESS) {
  636: 		if (smfi_setreply(MG(ctx), rcode, xcode, message) == MI_SUCCESS) {
  637: 			RETURN_TRUE;
  638: 		}
  639: 	}
  640: 	
  641: 	RETURN_FALSE;
  642: }
  643: /* }}} */
  644: 
  645: /* {{{ proto bool smfi_addheader(string headerf, string headerv)
  646:    Adds a header to the current message. */	
  647: PHP_FUNCTION(smfi_addheader)
  648: {
  649: 	char *f, *v;
  650: 	int len;
  651: 	
  652: 	/* valid only in milter_eom */
  653: 	if (MG(state) != MLFI_EOM) {
  654: 		php_error(E_WARNING, NOT_EOM, get_active_function_name(TSRMLS_C));
  655: 	} else if (zend_parse_parameters(2 TSRMLS_CC, "ss", &f, &len, &v, &len) == SUCCESS) {
  656: 		if (smfi_addheader(MG(ctx), f, v) == MI_SUCCESS) {
  657: 			RETURN_TRUE;
  658: 		}
  659: 	}
  660: 	
  661: 	RETURN_FALSE;
  662: }
  663: /* }}} */
  664: 
  665: /* {{{ proto bool smfi_chgheader(string headerf, string headerv)
  666:    Changes a header's value for the current message. */	
  667: PHP_FUNCTION(smfi_chgheader)
  668: {
  669: 	char *f, *v;
  670: 	long idx;
  671: 	int len;
  672: 	
  673: 	/* valid only in milter_eom */
  674: 	if (MG(state) != MLFI_EOM) {
  675: 		php_error(E_WARNING, NOT_EOM, get_active_function_name(TSRMLS_C));
  676: 	} else if (zend_parse_parameters(3 TSRMLS_CC, "sls", &f, &len, &idx, &v, &len) == SUCCESS) {
  677: 		if (smfi_chgheader(MG(ctx), f, idx, v) == MI_SUCCESS) {
  678: 			RETURN_TRUE;
  679: 		}
  680: 	}
  681: 	
  682: 	RETURN_FALSE;
  683: }
  684: /* }}} */
  685: 
  686: /* {{{ proto bool smfi_addrcpt(string rcpt)
  687:    Add a recipient to the message envelope. */	
  688: PHP_FUNCTION(smfi_addrcpt)
  689: {
  690: 	char *rcpt;
  691: 	int len;
  692: 	
  693: 	/* valid only in milter_eom */
  694: 	if (MG(state) != MLFI_EOM) {
  695: 		php_error(E_WARNING, NOT_EOM, get_active_function_name(TSRMLS_C));
  696: 	} else if (zend_parse_parameters(1 TSRMLS_CC, "s", &rcpt, &len) == SUCCESS) {
  697: 		if (smfi_addrcpt(MG(ctx), rcpt) == MI_SUCCESS) {
  698: 			RETURN_TRUE;
  699: 		}
  700: 	}
  701: 	
  702: 	RETURN_FALSE;
  703: }
  704: /* }}} */
  705: 
  706: /* {{{ proto bool smfi_delrcpt(string rcpt)
  707:    Removes the named recipient from the current message's envelope. */	
  708: PHP_FUNCTION(smfi_delrcpt)
  709: {
  710: 	char *rcpt;
  711: 	int len;
  712: 	
  713: 	/* valid only in milter_eom */
  714: 	if (MG(state) != MLFI_EOM) {
  715: 		php_error(E_WARNING, NOT_EOM, get_active_function_name(TSRMLS_C));
  716: 	} else if (zend_parse_parameters(1 TSRMLS_CC, "s", &rcpt, &len) == SUCCESS) {
  717: 		if (smfi_delrcpt(MG(ctx), rcpt) == MI_SUCCESS) {
  718: 			RETURN_TRUE;
  719: 		}
  720: 	}
  721: 	
  722: 	RETURN_FALSE;
  723: }
  724: /* }}} */
  725: 
  726: /* {{{ proto bool smfi_replacebody(string body)
  727:    Replaces the body of the current message. If called more than once,
  728:    subsequent calls result in data being appended to the new body. */	
  729: PHP_FUNCTION(smfi_replacebody)
  730: {
  731: 	char *body;
  732: 	int len;
  733: 	
  734: 	/* valid only in milter_eom */
  735: 	if (MG(state) != MLFI_EOM) {
  736: 		php_error(E_WARNING, NOT_EOM, get_active_function_name(TSRMLS_C));
  737: 	} else if (zend_parse_parameters(1 TSRMLS_CC, "s", &body, &len) == SUCCESS) {
  738: 		if (smfi_replacebody(MG(ctx), (u_char*)body, len) == MI_SUCCESS) {
  739: 			RETURN_TRUE;
  740: 		}
  741: 	}
  742: 	
  743: 	RETURN_FALSE;
  744: }
  745: /* }}} */
  746: 
  747: /* {{{ PHP_MINIT_FUNCTION
  748:  */
  749: PHP_MINIT_FUNCTION(milter)
  750: {
  751: 	REGISTER_LONG_CONSTANT("SMFIS_CONTINUE",	SMFIS_CONTINUE,	CONST_CS | CONST_PERSISTENT);
  752: 	REGISTER_LONG_CONSTANT("SMFIS_REJECT",		SMFIS_REJECT,	CONST_CS | CONST_PERSISTENT);
  753: 	REGISTER_LONG_CONSTANT("SMFIS_DISCARD",		SMFIS_DISCARD,	CONST_CS | CONST_PERSISTENT);
  754: 	REGISTER_LONG_CONSTANT("SMFIS_ACCEPT",		SMFIS_ACCEPT,	CONST_CS | CONST_PERSISTENT);
  755: 	REGISTER_LONG_CONSTANT("SMFIS_TEMPFAIL",	SMFIS_TEMPFAIL,	CONST_CS | CONST_PERSISTENT);
  756: 
  757: 	REGISTER_LONG_CONSTANT("SMFIF_ADDHDRS",		SMFIF_ADDHDRS,	CONST_CS | CONST_PERSISTENT);
  758: 	REGISTER_LONG_CONSTANT("SMFIF_CHGHDRS",		SMFIF_CHGHDRS,	CONST_CS | CONST_PERSISTENT);
  759: 	REGISTER_LONG_CONSTANT("SMFIF_CHGBODY",		SMFIF_CHGBODY,	CONST_CS | CONST_PERSISTENT);
  760: 	REGISTER_LONG_CONSTANT("SMFIF_ADDRCPT",		SMFIF_ADDRCPT,	CONST_CS | CONST_PERSISTENT);
  761: 	REGISTER_LONG_CONSTANT("SMFIF_DELRCPT",		SMFIF_DELRCPT,	CONST_CS | CONST_PERSISTENT);
  762: 
  763: 	ZEND_INIT_MODULE_GLOBALS(milter, NULL, NULL);
  764: 
  765: 	MG(state) = MLFI_NONE;
  766: 	MG(initialized) = 0;
  767: 	return SUCCESS;
  768: }
  769: /* }}} */
  770: 
  771: /* {{{ PHP_MINFO_FUNCTION
  772:  */
  773: PHP_MINFO_FUNCTION(milter)
  774: {
  775: 	php_info_print_table_start();
  776: 	php_info_print_table_header(2, "Milter support", "enabled");
  777: 	php_info_print_table_end();
  778: }
  779: /* }}} */
  780: /* }}} */
  781: 
  782: /* {{{ arginfo */
  783: ZEND_BEGIN_ARG_INFO_EX(arginfo_smfi_setflags, 0, 0, 1)
  784: 	ZEND_ARG_INFO(0, flags)
  785: ZEND_END_ARG_INFO()
  786: 
  787: ZEND_BEGIN_ARG_INFO_EX(arginfo_smfi_settimeout, 0, 0, 1)
  788: 	ZEND_ARG_INFO(0, timeout)
  789: ZEND_END_ARG_INFO()
  790: 
  791: ZEND_BEGIN_ARG_INFO_EX(arginfo_smfi_getsymval, 0, 0, 1)
  792: 	ZEND_ARG_INFO(0, macro)
  793: ZEND_END_ARG_INFO()
  794: 
  795: ZEND_BEGIN_ARG_INFO_EX(arginfo_smfi_setreply, 0, 0, 3)
  796: 	ZEND_ARG_INFO(0, rcode)
  797: 	ZEND_ARG_INFO(0, xcode)
  798: 	ZEND_ARG_INFO(0, message)
  799: ZEND_END_ARG_INFO()
  800: 
  801: ZEND_BEGIN_ARG_INFO_EX(arginfo_smfi_addheader, 0, 0, 2)
  802: 	ZEND_ARG_INFO(0, headerf)
  803: 	ZEND_ARG_INFO(0, headerv)
  804: ZEND_END_ARG_INFO()
  805: 
  806: ZEND_BEGIN_ARG_INFO_EX(arginfo_smfi_chgheader, 0, 0, 2)
  807: 	ZEND_ARG_INFO(0, headerf)
  808: 	ZEND_ARG_INFO(0, headerv)
  809: ZEND_END_ARG_INFO()
  810: 
  811: ZEND_BEGIN_ARG_INFO_EX(arginfo_smfi_addrcpt, 0, 0, 1)
  812: 	ZEND_ARG_INFO(0, rcpt)
  813: ZEND_END_ARG_INFO()
  814: 
  815: ZEND_BEGIN_ARG_INFO_EX(arginfo_smfi_delrcpt, 0, 0, 1)
  816: 	ZEND_ARG_INFO(0, rcpt)
  817: ZEND_END_ARG_INFO()
  818: 
  819: ZEND_BEGIN_ARG_INFO_EX(arginfo_smfi_replacebody, 0, 0, 1)
  820: 	ZEND_ARG_INFO(0, body)
  821: ZEND_END_ARG_INFO()
  822: /* }}} */
  823: 
  824: /* {{{ milter_functions[]
  825: */
  826: const static zend_function_entry milter_functions[] = {
  827: 	PHP_FE(smfi_setflags, 		arginfo_smfi_setflags)
  828: 	PHP_FE(smfi_settimeout, 	arginfo_smfi_settimeout)
  829: 	PHP_FE(smfi_getsymval, 		arginfo_smfi_getsymval)
  830: 	PHP_FE(smfi_setreply, 		arginfo_smfi_setreply)
  831: 	PHP_FE(smfi_addheader, 		arginfo_smfi_addheader)
  832: 	PHP_FE(smfi_chgheader, 		arginfo_smfi_chgheader)
  833: 	PHP_FE(smfi_addrcpt, 		arginfo_smfi_addrcpt)
  834: 	PHP_FE(smfi_delrcpt, 		arginfo_smfi_delrcpt)
  835: 	PHP_FE(smfi_replacebody, 	arginfo_smfi_replacebody)
  836: 	PHP_FE_END
  837: };
  838: /* }}} */
  839: 
  840: /* {{{ Zend module entry
  841: */
  842: static zend_module_entry php_milter_module = {
  843: 	STANDARD_MODULE_HEADER,
  844: 	"Milter",
  845: 	milter_functions,
  846: 	PHP_MINIT(milter),
  847: 	NULL,
  848: 	NULL,
  849: 	NULL,
  850: 	PHP_MINFO(milter),
  851: 	"0.1.0",
  852: 	STANDARD_MODULE_PROPERTIES
  853: };
  854: /* }}} */
  855: 
  856: /* {{{ Milter SAPI
  857: */
  858: static int sapi_milter_ub_write(const char *str, uint str_length TSRMLS_DC)
  859: {
  860: 	return str_length;
  861: }
  862: 
  863: static void sapi_milter_flush(void *server_context)
  864: {
  865: }
  866: 
  867: static void sapi_milter_register_variables(zval *track_vars_array TSRMLS_DC)
  868: {
  869: 	php_register_variable ("SERVER_SOFTWARE", "Sendmail Milter", track_vars_array TSRMLS_CC);
  870: }
  871: 
  872: static int sapi_milter_post_read(char *buf, uint count_bytes TSRMLS_DC)
  873: {
  874: 	return 0;
  875: }
  876: 
  877: static char* sapi_milter_read_cookies(TSRMLS_D)
  878: {
  879: 	return NULL;
  880: }
  881: 
  882: static int sapi_milter_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC)
  883: {
  884: 	return SAPI_HEADER_SENT_SUCCESSFULLY;
  885: }
  886: 
  887: static int php_milter_startup(sapi_module_struct *sapi_module)
  888: {
  889: 	if (php_module_startup(sapi_module, &php_milter_module, 1) == FAILURE) {
  890: 		return FAILURE;
  891: 	}
  892: 	return SUCCESS;
  893: }
  894: /* }}} */
  895: 
  896: /* {{{ sapi_module_struct milter_sapi_module
  897: */
  898: static sapi_module_struct milter_sapi_module = {
  899: 	"milter",						/* name */
  900: 	"Sendmail Milter SAPI",			/* pretty name */
  901: 
  902: 	php_milter_startup,				/* startup */
  903: 	php_module_shutdown_wrapper,	/* shutdown */
  904: 
  905: 	NULL,							/* activate */
  906: 	NULL,							/* deactivate */
  907: 
  908: 	sapi_milter_ub_write,			/* unbuffered write */
  909: 	sapi_milter_flush,				/* flush */
  910: 	NULL,							/* get uid */
  911: 	NULL,							/* getenv */
  912: 
  913: 	php_error,						/* error handler */
  914: 
  915: 	NULL,							/* header handler */
  916: 	sapi_milter_send_headers,		/* send headers handler */
  917: 	NULL,							/* send header handler */
  918: 
  919: 	sapi_milter_post_read,			/* read POST data */
  920: 	sapi_milter_read_cookies,		/* read Cookies */
  921: 
  922: 	sapi_milter_register_variables,	/* register server variables */
  923: 	NULL,							/* Log message */
  924: 	NULL,							/* Get request time */
  925: 	NULL,							/* Child terminate */
  926: 
  927: 	NULL,							/* Block interruptions */
  928: 	NULL,							/* Unblock interruptions */
  929: 
  930: 	STANDARD_SAPI_MODULE_PROPERTIES
  931: };
  932: /* }}} */
  933: 
  934: /****
  935: * ripped from cli, has to be cleaned up !
  936: */
  937: 
  938: /* {{{ php_milter_usage
  939: */
  940: static void php_milter_usage(char *argv0)
  941: {
  942: 	char *prog;
  943: 
  944: 	prog = strrchr(argv0, '/');
  945: 	if (prog) {
  946: 		prog++;
  947: 	} else {
  948: 		prog = "php-milter";
  949: 	}
  950: 
  951: 	printf(     "Usage: %s [options] [-f] <file> [args...]\n"
  952: 	            "       %s [options] [-- args...]\n"
  953: 				"  -a               Run interactively\n"
  954: 				"  -c <path>|<file> Look for php.ini file in this directory\n"
  955: 				"  -n               No php.ini file will be used\n"
  956: 				"  -d foo[=bar]     Define INI entry foo with value 'bar'\n"
  957: 				"  -D               run as daemon\n"
  958: 				"  -e               Generate extended information for debugger/profiler\n"
  959: 				"  -f <file>        Parse <file>.\n"
  960: 				"  -h               This help\n"
  961: 				"  -p <socket>      path to create socket\n"
  962: 				"  -v               Version number\n"
  963: 				"  -V <n>           set debug level to n (1 or 2).\n"
  964: 				"  -z <file>        Load Zend extension <file>.\n"
  965: 				"  args...          Arguments passed to script. Use -- args when first argument \n"
  966: 				"                   starts with - or script is read from stdin\n"
  967: 				, prog, prog);
  968: }
  969: /* }}} */
  970: 
  971: static void define_command_line_ini_entry(char *arg) /* {{{ */
  972: {
  973: 	char *name, *value;
  974: 
  975: 	name = arg;
  976: 	value = strchr(arg, '=');
  977: 	if (value) {
  978: 		*value = 0;
  979: 		value++;
  980: 	} else {
  981: 		value = "1";
  982: 	}
  983: 	zend_alter_ini_entry(name, strlen(name)+1, value, strlen(value), PHP_INI_SYSTEM, PHP_INI_STAGE_ACTIVATE);
  984: }
  985: /* }}} */
  986: 
  987: /* {{{ main
  988: */
  989: int main(int argc, char *argv[])
  990: {
  991:     char *sock = NULL;
  992: 	int dofork = 0;
  993: 
  994: 	int exit_status = SUCCESS;
  995: 	int c;
  996: /* temporary locals */
  997: 	int orig_optind=ap_php_optind;
  998: 	char *orig_optarg=ap_php_optarg;
  999: 	int interactive=0;
 1000: 	char *param_error=NULL;
 1001: /* end of temporary locals */
 1002: 
 1003: 	void ***tsrm_ls;
 1004: 
 1005: #ifdef HAVE_SIGNAL_H
 1006: #if defined(SIGPIPE) && defined(SIG_IGN)
 1007: 	signal(SIGPIPE, SIG_IGN); /* ignore SIGPIPE in standalone mode so
 1008: 								that sockets created via fsockopen()
 1009: 								don't kill PHP if the remote site
 1010: 								closes it.  in apache|apxs mode apache
 1011: 								does that for us!  thies@thieso.net
 1012: 								20000419 */
 1013: #endif
 1014: #endif
 1015: 
 1016: 
 1017: 	tsrm_startup(1, 1, 0, NULL);
 1018: 	sapi_startup(&milter_sapi_module);
 1019: 	
 1020: 	while ((c=ap_php_getopt(argc, argv, OPTSTRING))!=-1) {
 1021: 		switch (c) {
 1022: 		case 'c':
 1023: 			milter_sapi_module.php_ini_path_override = strdup(ap_php_optarg);
 1024: 			break;
 1025: 		case 'n':
 1026: 			milter_sapi_module.php_ini_ignore = 1;
 1027: 			break;
 1028: 		}
 1029: 	}
 1030: 	ap_php_optind = orig_optind;
 1031: 	ap_php_optarg = orig_optarg;
 1032: 
 1033: 	milter_sapi_module.executable_location = argv[0];
 1034: 
 1035: 	tsrm_ls = ts_resource(0);
 1036: 
 1037: 	sapi_module.startup(&milter_sapi_module);
 1038: 
 1039: 	zend_first_try {
 1040: 		while ((c=ap_php_getopt(argc, argv, OPTSTRING))!=-1) {
 1041: 			switch (c) {
 1042: 			case '?':
 1043: 				php_output_tearup();
 1044: 				SG(headers_sent) = 1;
 1045: 				php_milter_usage(argv[0]);
 1046: 				php_output_teardown();
 1047: 				exit(1);
 1048: 				break;
 1049: 			}
 1050: 		}
 1051: 		ap_php_optind = orig_optind;
 1052: 		ap_php_optarg = orig_optarg;
 1053: 
 1054:         /* Set some CLI defaults */
 1055: 		SG(options) |= SAPI_OPTION_NO_CHDIR;
 1056: 		zend_alter_ini_entry("html_errors", 12, "0", 1, PHP_INI_SYSTEM, PHP_INI_STAGE_ACTIVATE);
 1057: 		zend_alter_ini_entry("max_execution_time", 19, "0", 1, PHP_INI_SYSTEM, PHP_INI_STAGE_ACTIVATE);
 1058: 
 1059: 		zend_uv.html_errors = 0; /* tell the engine we're in non-html mode */
 1060: 
 1061: 		while ((c = ap_php_getopt(argc, argv, OPTSTRING)) != -1) {
 1062: 			switch (c) {
 1063: 
 1064: 			case 'a':	/* interactive mode */
 1065: 				printf("Interactive mode enabled\n\n");
 1066: 				interactive=1;
 1067: 				break;
 1068: 
 1069: 			case 'C': /* don't chdir to the script directory */
 1070: 				/* This is default so NOP */
 1071: 				break;
 1072: 			case 'd': /* define ini entries on command line */
 1073: 				define_command_line_ini_entry(ap_php_optarg);
 1074: 				break;
 1075: 
 1076: 			case 'D': /* daemon */
 1077: 				dofork = 1;
 1078: 				break;
 1079: 
 1080: 			case 'e': /* enable extended info output */
 1081: 				CG(compiler_options) |= ZEND_COMPILE_EXTENDED_INFO;
 1082: 				break;
 1083: 
 1084: 			case 'f': /* parse file */
 1085: 				filename = ap_php_optarg;
 1086: 				break;
 1087: 
 1088: 			case 'h': /* help & quit */
 1089: 			case '?':
 1090: 				php_output_tearup();
 1091: 				SG(headers_sent) = 1;
 1092: 				php_milter_usage(argv[0]);
 1093: 				php_output_teardown();
 1094: 				exit(1);
 1095: 				break;
 1096: 
 1097: 			case 'p': /* socket */
 1098: 				sock = strdup(ap_php_optarg);
 1099: 				break;
 1100: 
 1101: 			case 'v': /* show php version & quit */
 1102: 				if (php_request_startup(TSRMLS_C)==FAILURE) {
 1103: 					zend_ini_deactivate(TSRMLS_C);
 1104: 					php_module_shutdown(TSRMLS_C);
 1105: 					sapi_shutdown();
 1106: 					tsrm_shutdown();
 1107: 
 1108: 					exit(1);
 1109: 				}
 1110: 				SG(headers_sent) = 1;
 1111: 				SG(request_info).no_headers = 1;
 1112: 				php_printf("PHP %s (%s) (built: %s %s)\nCopyright (c) 1997-2012 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
 1113: 				php_output_teardown();
 1114: 				exit(1);
 1115: 				break;
 1116: 
 1117: 			case 'V': /* verbose */
 1118: 				flag_debug = atoi(ap_php_optarg);
 1119: 				break;
 1120: 
 1121: 			case 'z': /* load extension file */
 1122: 				zend_load_extension(ap_php_optarg);
 1123: 				break;
 1124: 
 1125: 			default:
 1126: 				break;
 1127: 			}
 1128: 		}
 1129: 
 1130: 		if (param_error) {
 1131: 			SG(headers_sent) = 1;
 1132: 			SG(request_info).no_headers = 1;
 1133: 			PUTS(param_error);
 1134: 			exit(1);
 1135: 		}
 1136: 
 1137: 		CG(interactive) = interactive;
 1138: 
 1139: 		/* only set script_file if not set already and not in direct mode and not at end of parameter list */
 1140: 		if (argc > ap_php_optind && !filename) {
 1141: 			filename=argv[ap_php_optind];
 1142: 			ap_php_optind++;
 1143: 		}
 1144: 
 1145: 		/* check if file exists, exit else */
 1146: 		
 1147: 		if (dofork) {
 1148: 			switch(fork()) {
 1149: 				case -1: /* Uh-oh, we have a problem forking. */
 1150: 					fprintf(stderr, "Uh-oh, couldn't fork!\n");
 1151: 					exit(errno);
 1152: 					break;
 1153: 				case 0: /* Child */
 1154: 					break;
 1155: 				default: /* Parent */
 1156: 					exit(0);
 1157: 			}
 1158: 		}
 1159: 			
 1160: 		if (sock) {
 1161: 			struct stat junk;
 1162: 			if (stat(sock,&junk) == 0) unlink(sock);
 1163: 		}
 1164: 
 1165: 		openlog("php-milter", LOG_PID, LOG_MAIL);
 1166: 		
 1167: 		if ((exit_status = mlfi_init())) {
 1168: 			syslog(1, "mlfi_init failed.");
 1169: 			closelog();
 1170: 			goto err;
 1171: 		}
 1172: 
 1173: 		smfi_setconn(sock);
 1174: 		if (smfi_register(smfilter) == MI_FAILURE) {
 1175: 			syslog(1, "smfi_register failed.");
 1176: 			fprintf(stderr, "smfi_register failed\n");
 1177: 			closelog();
 1178: 			goto err;
 1179: 		} else {
 1180: 			exit_status = smfi_main();
 1181: 		}			
 1182: 
 1183: 		closelog();
 1184: 
 1185: 		if (milter_sapi_module.php_ini_path_override) {
 1186: 			free(milter_sapi_module.php_ini_path_override);
 1187: 		}
 1188: 
 1189: 	} zend_catch {
 1190: 		exit_status = EG(exit_status);
 1191: 	} zend_end_try();
 1192: 
 1193: err:
 1194: 	php_module_shutdown(TSRMLS_C);
 1195: 	sapi_shutdown();
 1196: 	tsrm_shutdown();
 1197: 
 1198: 	exit(exit_status);
 1199: }
 1200: /* }}} */
 1201: 
 1202: /*
 1203:  * Local variables:
 1204:  * tab-width: 4
 1205:  * c-basic-offset: 4
 1206:  * End:
 1207:  * vim600: sw=4 ts=4 fdm=marker
 1208:  * vim<600: sw=4 ts=4
 1209:  */

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