#include "php.h"
#include "php_globals.h"
#include "php_variables.h"
#include "zend_modules.h"
#ifndef ZTS
#error SRM sapi module is only useable in thread-safe mode
#endif
#include "SAPI.h"
#include <stdio.h>
#include "php.h"
#if HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#if HAVE_SIGNAL_H
#include <signal.h>
#endif
#if HAVE_SETLOCALE
#include <locale.h>
#endif
#include "zend.h"
#include "zend_extensions.h"
#include "php_ini.h"
#include "php_globals.h"
#include "php_main.h"
#include "fopen_wrappers.h"
#include "ext/standard/php_standard.h"
#ifdef __riscos__
#include <unixlib/local.h>
#endif
#include "zend_compile.h"
#include "zend_execute.h"
#include "zend_highlight.h"
#include "zend_indent.h"
#include "libmilter/mfapi.h"
#include "php_getopt.h"
#define OPTSTRING "ac:d:Def:hnp:vVz:?"
#define MG(v) TSRMG(milter_globals_id, zend_milter_globals *, v)
#define IS_NONE "%s(): This function must not be called outside of a milter callback function's scope"
#define NOT_EOM "%s(): This function can only be used inside the milter_eom callback's scope"
#define NOT_INIT "%s(): This function can only be used inside the milter_init callback's scope"
#define MLFI_NONE 0
#define MLFI_CONNECT 1
#define MLFI_HELO 2
#define MLFI_ENVFROM 3
#define MLFI_ENVRCPT 4
#define MLFI_HEADER 5
#define MLFI_EOH 6
#define MLFI_BODY 7
#define MLFI_EOM 8
#define MLFI_ABORT 9
#define MLFI_CLOSE 10
#define MLFI_INIT 11
extern char *ap_php_optarg;
extern int ap_php_optind;
static int flag_debug=0;
static char *filename = NULL;
ZEND_BEGIN_MODULE_GLOBALS(milter)
SMFICTX *ctx;
int state;
int initialized;
ZEND_END_MODULE_GLOBALS(milter)
ZEND_DECLARE_MODULE_GLOBALS(milter)
static int mlfi_init()
{
int ret = 0;
zend_file_handle file_handle;
zval function_name, retval;
int status;
TSRMLS_FETCH();
if (php_request_startup(TSRMLS_C)==FAILURE) {
SG(headers_sent) = 1;
SG(request_info).no_headers = 1;
php_request_shutdown((void *) 0);
return -1;
}
SG(headers_sent) = 1;
SG(request_info).no_headers = 1;
if (filename == NULL) {
php_printf("No input file specified");
return SMFIS_TEMPFAIL;
}
if (!(file_handle.handle.fp = VCWD_FOPEN(filename, "rb"))) {
php_printf("Could not open input file: %s\n", filename);
return SMFIS_TEMPFAIL;
}
file_handle.type = ZEND_HANDLE_FP;
file_handle.filename = filename;
file_handle.free_filename = 0;
file_handle.opened_path = NULL;
php_execute_script(&file_handle TSRMLS_CC);
INIT_ZVAL(function_name);
ZVAL_STRING(&function_name, "milter_init", 0);
MG(state) = MLFI_INIT;
status = call_user_function(CG(function_table), NULL, &function_name, &retval, 0, NULL TSRMLS_CC);
MG(state) = MLFI_NONE;
MG(initialized) = 1;
if (status == SUCCESS && Z_TYPE(retval) == IS_LONG) {
ret = Z_LVAL(retval);
}
php_request_shutdown((void *) 0);
return ret;
}
static sfsistat mlfi_connect(SMFICTX *ctx, char *hostname, _SOCK_ADDR *hostaddr)
{
zend_file_handle file_handle;
zval function_name, retval, *param[1];
int status;
TSRMLS_FETCH();
if (php_request_startup(TSRMLS_C)==FAILURE) {
SG(headers_sent) = 1;
SG(request_info).no_headers = 1;
php_request_shutdown((void *) 0);
return SMFIS_TEMPFAIL;
}
SG(headers_sent) = 1;
SG(request_info).no_headers = 1;
if (filename == NULL) {
php_printf("No input file specified");
return SMFIS_TEMPFAIL;
}
if (!(file_handle.handle.fp = VCWD_FOPEN(filename, "rb"))) {
php_printf("Could not open input file: %s\n", filename);
return SMFIS_TEMPFAIL;
}
file_handle.type = ZEND_HANDLE_FP;
file_handle.filename = filename;
file_handle.free_filename = 0;
file_handle.opened_path = NULL;
php_execute_script(&file_handle TSRMLS_CC);
INIT_ZVAL(function_name);
ALLOC_ZVAL(param[0]);
INIT_PZVAL(param[0]);
ZVAL_STRING(&function_name, "milter_connect", 0);
ZVAL_STRING(param[0], hostname, 1);
MG(ctx) = ctx;
MG(state) = MLFI_CONNECT;
status = call_user_function(CG(function_table), NULL, &function_name, &retval, 1, param TSRMLS_CC);
MG(state) = MLFI_NONE;
zval_ptr_dtor(param);
if (status == SUCCESS && Z_TYPE(retval) == IS_LONG) {
return Z_LVAL(retval);
}
return SMFIS_CONTINUE;
}
static sfsistat mlfi_helo(SMFICTX *ctx, char *helohost)
{
zval function_name, retval, *param[1];
int status;
TSRMLS_FETCH();
INIT_ZVAL(function_name);
ALLOC_ZVAL(param[0]);
INIT_PZVAL(param[0]);
ZVAL_STRING(&function_name, "milter_helo", 0);
ZVAL_STRING(param[0], helohost, 1);
MG(ctx) = ctx;
MG(state) = MLFI_HELO;
status = call_user_function(CG(function_table), NULL, &function_name, &retval, 1, param TSRMLS_CC);
MG(state) = MLFI_NONE;
zval_ptr_dtor(param);
if (status == SUCCESS && Z_TYPE(retval) == IS_LONG) {
return Z_LVAL(retval);
}
return SMFIS_CONTINUE;
}
static sfsistat mlfi_envfrom(SMFICTX *ctx, char **argv)
{
zval function_name, retval, *param[1];
int status;
TSRMLS_FETCH();
INIT_ZVAL(function_name);
ALLOC_ZVAL(param[0]);
INIT_PZVAL(param[0]);
ZVAL_STRING(&function_name, "milter_envfrom", 0);
array_init(param[0]);
while (*argv) {
add_next_index_string(param[0], *argv, 1);
argv++;
}
MG(ctx) = ctx;
MG(state) = MLFI_ENVFROM;
status = call_user_function(CG(function_table), NULL, &function_name, &retval, 1, param TSRMLS_CC);
MG(state) = MLFI_NONE;
zval_ptr_dtor(param);
if (status == SUCCESS && Z_TYPE(retval) == IS_LONG) {
return Z_LVAL(retval);
}
return SMFIS_CONTINUE;
}
static sfsistat mlfi_envrcpt(SMFICTX *ctx, char **argv)
{
zval function_name, retval, *param[1];
int status;
TSRMLS_FETCH();
INIT_ZVAL(function_name);
ALLOC_ZVAL(param[0]);
INIT_PZVAL(param[0]);
ZVAL_STRING(&function_name, "milter_envrcpt", 0);
array_init(param[0]);
while (*argv) {
add_next_index_string(param[0], *argv, 1);
argv++;
}
MG(ctx) = ctx;
MG(state) = MLFI_ENVRCPT;
status = call_user_function(CG(function_table), NULL, &function_name, &retval, 1, param TSRMLS_CC);
MG(state) = MLFI_NONE;
zval_ptr_dtor(param);
if (status == SUCCESS && Z_TYPE(retval) == IS_LONG) {
return Z_LVAL(retval);
}
return SMFIS_CONTINUE;
}
static sfsistat mlfi_header(SMFICTX *ctx, char *headerf, char *headerv)
{
zval function_name, retval, *param[2];
int status;
TSRMLS_FETCH();
INIT_ZVAL(function_name);
ALLOC_ZVAL(param[0]);
ALLOC_ZVAL(param[1]);
INIT_PZVAL(param[0]);
INIT_PZVAL(param[1]);
ZVAL_STRING(&function_name, "milter_header", 0);
ZVAL_STRING(param[0], headerf, 1);
ZVAL_STRING(param[1], headerv, 1);
MG(ctx) = ctx;
MG(state) = MLFI_HEADER;
status = call_user_function(CG(function_table), NULL, &function_name, &retval, 2, param TSRMLS_CC);
MG(state) = MLFI_NONE;
zval_ptr_dtor(¶m[0]);
zval_ptr_dtor(¶m[1]);
if (status == SUCCESS && Z_TYPE(retval) == IS_LONG) {
return Z_LVAL(retval);
}
return SMFIS_CONTINUE;
}
static sfsistat mlfi_eoh(SMFICTX *ctx)
{
zval function_name, retval;
int status;
TSRMLS_FETCH();
INIT_ZVAL(function_name);
ZVAL_STRING(&function_name, "milter_eoh", 0);
MG(ctx) = ctx;
MG(state) = MLFI_EOH;
status = call_user_function(CG(function_table), NULL, &function_name, &retval, 0, NULL TSRMLS_CC);
MG(state) = MLFI_NONE;
if (status == SUCCESS && Z_TYPE(retval) == IS_LONG) {
return Z_LVAL(retval);
}
return SMFIS_CONTINUE;
}
static sfsistat mlfi_body(SMFICTX *ctx, u_char *bodyp, size_t len)
{
zval function_name, retval, *param[1];
int status;
TSRMLS_FETCH();
INIT_ZVAL(function_name);
ALLOC_ZVAL(param[0]);
INIT_PZVAL(param[0]);
ZVAL_STRING(&function_name, "milter_body", 0);
ZVAL_STRINGL(param[0], (char*)bodyp, len, 1);
MG(ctx) = ctx;
MG(state) = MLFI_BODY;
status = call_user_function(CG(function_table), NULL, &function_name, &retval, 1, param TSRMLS_CC);
MG(state) = MLFI_NONE;
zval_ptr_dtor(param);
if (status == SUCCESS && Z_TYPE(retval) == IS_LONG) {
return Z_LVAL(retval);
}
return SMFIS_CONTINUE;
}
static sfsistat mlfi_eom(SMFICTX *ctx)
{
zval function_name, retval;
int status;
TSRMLS_FETCH();
INIT_ZVAL(function_name);
ZVAL_STRING(&function_name, "milter_eom", 0);
MG(ctx) = ctx;
MG(state) = MLFI_EOM;
status = call_user_function(CG(function_table), NULL, &function_name, &retval, 0, NULL TSRMLS_CC);
MG(state) = MLFI_NONE;
if (status == SUCCESS && Z_TYPE(retval) == IS_LONG) {
return Z_LVAL(retval);
}
return SMFIS_CONTINUE;
}
static sfsistat mlfi_abort(SMFICTX *ctx)
{
zval function_name, retval;
int status;
TSRMLS_FETCH();
INIT_ZVAL(function_name);
ZVAL_STRING(&function_name, "milter_abort", 0);
MG(ctx) = ctx;
MG(state) = MLFI_ABORT;
status = call_user_function(CG(function_table), NULL, &function_name, &retval, 0, NULL TSRMLS_CC);
MG(state) = MLFI_NONE;
if (status == SUCCESS && Z_TYPE(retval) == IS_LONG) {
return Z_LVAL(retval);
}
return SMFIS_CONTINUE;
}
static sfsistat mlfi_close(SMFICTX *ctx)
{
int ret = SMFIS_CONTINUE;
zval function_name, retval;
int status;
TSRMLS_FETCH();
if (!SG(sapi_started) && SUCCESS != php_request_startup(TSRMLS_C)) {
return ret;
}
INIT_ZVAL(function_name);
ZVAL_STRING(&function_name, "milter_close", 0);
MG(ctx) = ctx;
MG(state) = MLFI_CLOSE;
status = call_user_function(CG(function_table), NULL, &function_name, &retval, 0, NULL TSRMLS_CC);
MG(state) = MLFI_NONE;
if (status == SUCCESS && Z_TYPE(retval) == IS_LONG) {
ret = Z_LVAL(retval);
}
php_request_shutdown((void *) 0);
return ret;
}
static struct smfiDesc smfilter = {
"php-milter",
SMFI_VERSION,
0,
mlfi_connect,
mlfi_helo,
mlfi_envfrom,
mlfi_envrcpt,
mlfi_header,
mlfi_eoh,
mlfi_body,
mlfi_eom,
mlfi_abort,
mlfi_close,
};
PHP_FUNCTION(smfi_setflags)
{
long flags;
if (MG(state) != MLFI_INIT) {
php_error(E_WARNING, NOT_INIT, get_active_function_name(TSRMLS_C));
} else if (zend_parse_parameters(1 TSRMLS_CC, "l", &flags) == SUCCESS) {
flags = flags & (SMFIF_ADDHDRS|SMFIF_CHGHDRS|SMFIF_CHGBODY|SMFIF_ADDRCPT|SMFIF_DELRCPT);
smfilter.xxfi_flags = flags;
}
}
PHP_FUNCTION(smfi_settimeout)
{
long timeout;
if (MG(state) != MLFI_INIT) {
php_error(E_WARNING, NOT_INIT, get_active_function_name(TSRMLS_C));
} else if (zend_parse_parameters(1 TSRMLS_CC, "l", &timeout) == SUCCESS) {
smfi_settimeout(timeout);
}
}
PHP_FUNCTION(smfi_getsymval)
{
char *symname, *ret;
int len;
if (MG(state) == MLFI_NONE) {
php_error(E_WARNING, IS_NONE, get_active_function_name(TSRMLS_C));
} else if (zend_parse_parameters(1 TSRMLS_CC, "s", &symname, &len) == SUCCESS) {
if ((ret = smfi_getsymval(MG(ctx), symname)) != NULL) {
RETURN_STRING(ret, 1);
}
}
RETURN_NULL();
}
PHP_FUNCTION(smfi_setreply)
{
char *rcode, *xcode, *message;
int len;
if (MG(state) == MLFI_NONE) {
php_error(E_WARNING, IS_NONE, get_active_function_name(TSRMLS_C));
} else if (zend_parse_parameters(3 TSRMLS_CC, "sss", &rcode, &len, &xcode, &len, &message, &len) == SUCCESS) {
if (smfi_setreply(MG(ctx), rcode, xcode, message) == MI_SUCCESS) {
RETURN_TRUE;
}
}
RETURN_FALSE;
}
PHP_FUNCTION(smfi_addheader)
{
char *f, *v;
int len;
if (MG(state) != MLFI_EOM) {
php_error(E_WARNING, NOT_EOM, get_active_function_name(TSRMLS_C));
} else if (zend_parse_parameters(2 TSRMLS_CC, "ss", &f, &len, &v, &len) == SUCCESS) {
if (smfi_addheader(MG(ctx), f, v) == MI_SUCCESS) {
RETURN_TRUE;
}
}
RETURN_FALSE;
}
PHP_FUNCTION(smfi_chgheader)
{
char *f, *v;
long idx;
int len;
if (MG(state) != MLFI_EOM) {
php_error(E_WARNING, NOT_EOM, get_active_function_name(TSRMLS_C));
} else if (zend_parse_parameters(3 TSRMLS_CC, "sls", &f, &len, &idx, &v, &len) == SUCCESS) {
if (smfi_chgheader(MG(ctx), f, idx, v) == MI_SUCCESS) {
RETURN_TRUE;
}
}
RETURN_FALSE;
}
PHP_FUNCTION(smfi_addrcpt)
{
char *rcpt;
int len;
if (MG(state) != MLFI_EOM) {
php_error(E_WARNING, NOT_EOM, get_active_function_name(TSRMLS_C));
} else if (zend_parse_parameters(1 TSRMLS_CC, "s", &rcpt, &len) == SUCCESS) {
if (smfi_addrcpt(MG(ctx), rcpt) == MI_SUCCESS) {
RETURN_TRUE;
}
}
RETURN_FALSE;
}
PHP_FUNCTION(smfi_delrcpt)
{
char *rcpt;
int len;
if (MG(state) != MLFI_EOM) {
php_error(E_WARNING, NOT_EOM, get_active_function_name(TSRMLS_C));
} else if (zend_parse_parameters(1 TSRMLS_CC, "s", &rcpt, &len) == SUCCESS) {
if (smfi_delrcpt(MG(ctx), rcpt) == MI_SUCCESS) {
RETURN_TRUE;
}
}
RETURN_FALSE;
}
PHP_FUNCTION(smfi_replacebody)
{
char *body;
int len;
if (MG(state) != MLFI_EOM) {
php_error(E_WARNING, NOT_EOM, get_active_function_name(TSRMLS_C));
} else if (zend_parse_parameters(1 TSRMLS_CC, "s", &body, &len) == SUCCESS) {
if (smfi_replacebody(MG(ctx), (u_char*)body, len) == MI_SUCCESS) {
RETURN_TRUE;
}
}
RETURN_FALSE;
}
PHP_MINIT_FUNCTION(milter)
{
REGISTER_LONG_CONSTANT("SMFIS_CONTINUE", SMFIS_CONTINUE, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("SMFIS_REJECT", SMFIS_REJECT, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("SMFIS_DISCARD", SMFIS_DISCARD, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("SMFIS_ACCEPT", SMFIS_ACCEPT, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("SMFIS_TEMPFAIL", SMFIS_TEMPFAIL, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("SMFIF_ADDHDRS", SMFIF_ADDHDRS, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("SMFIF_CHGHDRS", SMFIF_CHGHDRS, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("SMFIF_CHGBODY", SMFIF_CHGBODY, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("SMFIF_ADDRCPT", SMFIF_ADDRCPT, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("SMFIF_DELRCPT", SMFIF_DELRCPT, CONST_CS | CONST_PERSISTENT);
ZEND_INIT_MODULE_GLOBALS(milter, NULL, NULL);
MG(state) = MLFI_NONE;
MG(initialized) = 0;
return SUCCESS;
}
PHP_MINFO_FUNCTION(milter)
{
php_info_print_table_start();
php_info_print_table_header(2, "Milter support", "enabled");
php_info_print_table_end();
}
ZEND_BEGIN_ARG_INFO_EX(arginfo_smfi_setflags, 0, 0, 1)
ZEND_ARG_INFO(0, flags)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_smfi_settimeout, 0, 0, 1)
ZEND_ARG_INFO(0, timeout)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_smfi_getsymval, 0, 0, 1)
ZEND_ARG_INFO(0, macro)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_smfi_setreply, 0, 0, 3)
ZEND_ARG_INFO(0, rcode)
ZEND_ARG_INFO(0, xcode)
ZEND_ARG_INFO(0, message)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_smfi_addheader, 0, 0, 2)
ZEND_ARG_INFO(0, headerf)
ZEND_ARG_INFO(0, headerv)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_smfi_chgheader, 0, 0, 2)
ZEND_ARG_INFO(0, headerf)
ZEND_ARG_INFO(0, headerv)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_smfi_addrcpt, 0, 0, 1)
ZEND_ARG_INFO(0, rcpt)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_smfi_delrcpt, 0, 0, 1)
ZEND_ARG_INFO(0, rcpt)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_smfi_replacebody, 0, 0, 1)
ZEND_ARG_INFO(0, body)
ZEND_END_ARG_INFO()
const static zend_function_entry milter_functions[] = {
PHP_FE(smfi_setflags, arginfo_smfi_setflags)
PHP_FE(smfi_settimeout, arginfo_smfi_settimeout)
PHP_FE(smfi_getsymval, arginfo_smfi_getsymval)
PHP_FE(smfi_setreply, arginfo_smfi_setreply)
PHP_FE(smfi_addheader, arginfo_smfi_addheader)
PHP_FE(smfi_chgheader, arginfo_smfi_chgheader)
PHP_FE(smfi_addrcpt, arginfo_smfi_addrcpt)
PHP_FE(smfi_delrcpt, arginfo_smfi_delrcpt)
PHP_FE(smfi_replacebody, arginfo_smfi_replacebody)
PHP_FE_END
};
static zend_module_entry php_milter_module = {
STANDARD_MODULE_HEADER,
"Milter",
milter_functions,
PHP_MINIT(milter),
NULL,
NULL,
NULL,
PHP_MINFO(milter),
"0.1.0",
STANDARD_MODULE_PROPERTIES
};
static int sapi_milter_ub_write(const char *str, uint str_length TSRMLS_DC)
{
return str_length;
}
static void sapi_milter_flush(void *server_context)
{
}
static void sapi_milter_register_variables(zval *track_vars_array TSRMLS_DC)
{
php_register_variable ("SERVER_SOFTWARE", "Sendmail Milter", track_vars_array TSRMLS_CC);
}
static int sapi_milter_post_read(char *buf, uint count_bytes TSRMLS_DC)
{
return 0;
}
static char* sapi_milter_read_cookies(TSRMLS_D)
{
return NULL;
}
static int sapi_milter_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC)
{
return SAPI_HEADER_SENT_SUCCESSFULLY;
}
static int php_milter_startup(sapi_module_struct *sapi_module)
{
if (php_module_startup(sapi_module, &php_milter_module, 1) == FAILURE) {
return FAILURE;
}
return SUCCESS;
}
static sapi_module_struct milter_sapi_module = {
"milter",
"Sendmail Milter SAPI",
php_milter_startup,
php_module_shutdown_wrapper,
NULL,
NULL,
sapi_milter_ub_write,
sapi_milter_flush,
NULL,
NULL,
php_error,
NULL,
sapi_milter_send_headers,
NULL,
sapi_milter_post_read,
sapi_milter_read_cookies,
sapi_milter_register_variables,
NULL,
NULL,
NULL,
NULL,
NULL,
STANDARD_SAPI_MODULE_PROPERTIES
};
static void php_milter_usage(char *argv0)
{
char *prog;
prog = strrchr(argv0, '/');
if (prog) {
prog++;
} else {
prog = "php-milter";
}
printf( "Usage: %s [options] [-f] <file> [args...]\n"
" %s [options] [-- args...]\n"
" -a Run interactively\n"
" -c <path>|<file> Look for php.ini file in this directory\n"
" -n No php.ini file will be used\n"
" -d foo[=bar] Define INI entry foo with value 'bar'\n"
" -D run as daemon\n"
" -e Generate extended information for debugger/profiler\n"
" -f <file> Parse <file>.\n"
" -h This help\n"
" -p <socket> path to create socket\n"
" -v Version number\n"
" -V <n> set debug level to n (1 or 2).\n"
" -z <file> Load Zend extension <file>.\n"
" args... Arguments passed to script. Use -- args when first argument \n"
" starts with - or script is read from stdin\n"
, prog, prog);
}
static void define_command_line_ini_entry(char *arg)
{
char *name, *value;
name = arg;
value = strchr(arg, '=');
if (value) {
*value = 0;
value++;
} else {
value = "1";
}
zend_alter_ini_entry(name, strlen(name)+1, value, strlen(value), PHP_INI_SYSTEM, PHP_INI_STAGE_ACTIVATE);
}
int main(int argc, char *argv[])
{
char *sock = NULL;
int dofork = 0;
int exit_status = SUCCESS;
int c;
int orig_optind=ap_php_optind;
char *orig_optarg=ap_php_optarg;
int interactive=0;
char *param_error=NULL;
void ***tsrm_ls;
#ifdef HAVE_SIGNAL_H
#if defined(SIGPIPE) && defined(SIG_IGN)
signal(SIGPIPE, SIG_IGN);
#endif
#endif
tsrm_startup(1, 1, 0, NULL);
tsrm_ls = ts_resource(0);
sapi_startup(&milter_sapi_module);
while ((c=ap_php_getopt(argc, argv, OPTSTRING))!=-1) {
switch (c) {
case 'c':
milter_sapi_module.php_ini_path_override = strdup(ap_php_optarg);
break;
case 'n':
milter_sapi_module.php_ini_ignore = 1;
break;
}
}
ap_php_optind = orig_optind;
ap_php_optarg = orig_optarg;
milter_sapi_module.executable_location = argv[0];
sapi_module.startup(&milter_sapi_module);
zend_first_try {
while ((c=ap_php_getopt(argc, argv, OPTSTRING))!=-1) {
switch (c) {
case '?':
php_output_tearup();
SG(headers_sent) = 1;
php_milter_usage(argv[0]);
php_output_teardown();
exit(1);
break;
}
}
ap_php_optind = orig_optind;
ap_php_optarg = orig_optarg;
SG(options) |= SAPI_OPTION_NO_CHDIR;
zend_alter_ini_entry("html_errors", 12, "0", 1, PHP_INI_SYSTEM, PHP_INI_STAGE_ACTIVATE);
zend_alter_ini_entry("max_execution_time", 19, "0", 1, PHP_INI_SYSTEM, PHP_INI_STAGE_ACTIVATE);
zend_uv.html_errors = 0;
while ((c = ap_php_getopt(argc, argv, OPTSTRING)) != -1) {
switch (c) {
case 'a':
printf("Interactive mode enabled\n\n");
interactive=1;
break;
case 'C':
break;
case 'd':
define_command_line_ini_entry(ap_php_optarg);
break;
case 'D':
dofork = 1;
break;
case 'e':
CG(compiler_options) |= ZEND_COMPILE_EXTENDED_INFO;
break;
case 'f':
filename = ap_php_optarg;
break;
case 'h':
case '?':
php_output_tearup();
SG(headers_sent) = 1;
php_milter_usage(argv[0]);
php_output_teardown();
exit(1);
break;
case 'p':
sock = strdup(ap_php_optarg);
break;
case 'v':
if (php_request_startup(TSRMLS_C)==FAILURE) {
zend_ini_deactivate(TSRMLS_C);
php_module_shutdown(TSRMLS_C);
sapi_shutdown();
tsrm_shutdown();
exit(1);
}
SG(headers_sent) = 1;
SG(request_info).no_headers = 1;
php_printf("PHP %s (%s) (built: %s %s)\nCopyright (c) 1997-2016 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
php_output_teardown();
exit(1);
break;
case 'V':
flag_debug = atoi(ap_php_optarg);
break;
case 'z':
zend_load_extension(ap_php_optarg);
break;
default:
break;
}
}
if (param_error) {
SG(headers_sent) = 1;
SG(request_info).no_headers = 1;
PUTS(param_error);
exit(1);
}
CG(interactive) = interactive;
if (argc > ap_php_optind && !filename) {
filename=argv[ap_php_optind];
ap_php_optind++;
}
if (dofork) {
switch(fork()) {
case -1:
fprintf(stderr, "Uh-oh, couldn't fork!\n");
exit(errno);
break;
case 0:
break;
default:
exit(0);
}
}
if (sock) {
struct stat junk;
if (stat(sock,&junk) == 0) unlink(sock);
}
openlog("php-milter", LOG_PID, LOG_MAIL);
if ((exit_status = mlfi_init())) {
syslog(1, "mlfi_init failed.");
closelog();
goto err;
}
smfi_setconn(sock);
if (smfi_register(smfilter) == MI_FAILURE) {
syslog(1, "smfi_register failed.");
fprintf(stderr, "smfi_register failed\n");
closelog();
goto err;
} else {
exit_status = smfi_main();
}
closelog();
if (milter_sapi_module.php_ini_path_override) {
free(milter_sapi_module.php_ini_path_override);
}
} zend_catch {
exit_status = EG(exit_status);
} zend_end_try();
err:
php_module_shutdown(TSRMLS_C);
sapi_shutdown();
tsrm_shutdown();
exit(exit_status);
}