/*
 * Copyright (c) 2004, 2005 Sendmail, Inc. and its suppliers.
 *	All rights reserved.
 *
 * By using this file, you agree to the terms and conditions set
 * forth in the LICENSE file which can be found at the top level of
 * the sendmail distribution.
 */

#include "sm/generic.h"
SM_RCSID("@(#)$Id: pmilter_api.c,v 1.13 2006/10/05 04:27:37 ca Exp $")
#include "sm/error.h"
#include "sm/assert.h"
#include "sm/types.h"
#include "sm/fcntl.h"
#include "sm/io.h"
#include "sm/ctype.h"
#include "sm/reccom.h"
#include "sm/mta.h"
#define PMILTER_DEBUG_DEFINE 1
#include "pmilter.h"
#include "sm/pmilter.h"
#include "sm/pmfapi.h"
#include "util.h"

#if MTA_USE_PMILTER

/*
**  SM_PMFI_VERSION -- return version of libpmilter
**
**	Parameters:
**		pmg_ctx -- pmilter (library) context
**		major -- (pointer to) major version number of libpmilter
**		minor -- (pointer to) minor version number of libpmilter
**		patchlevel -- (pointer to) patchlevel of libpmilter
**
**	Returns:
**		usual sm_error code
*/

sm_ret_T
sm_pmfi_version(pmg_ctx_P pmg_ctx, uint32_t *major, uint32_t *minor, uint32_t *patchlevel)
{
	SM_REQUIRE(major != NULL);
	SM_REQUIRE(minor != NULL);
	SM_REQUIRE(patchlevel != NULL);
	*major = LPMILTER_VERSION_MAJOR;
	*minor = LPMILTER_VERSION_MINOR;
	*patchlevel = LPMILTER_VERSION_PL;
	return SM_SUCCESS;
}

/*
**  SM_PMFI_SETCONN -- set pathname of socket
**
**	Parameters:
**		pmg_ctx -- pmilter (library) context
**		path -- pathname of socket to use
**
**	Returns:
**		usual sm_error code
*/

sm_ret_T
sm_pmfi_setconn(pmg_ctx_P pmg_ctx, const char *path)
{
	SM_IS_PMG_CTX(pmg_ctx);
	SM_REQUIRE(path != NULL);

	/* memory leak if called multiple times. */
	pmg_ctx->pmg_sockname = strdup(path);
	if (pmg_ctx->pmg_sockname == NULL)
		return sm_err_temp(ENOMEM);
	return SM_PMI_SUCCESS;
}

/*
**  SM_PMFI_INIT -- initialize PMILTER library
**
**	Parameters:
**		ppmg_ctx -- (pointer to) pmilter (library) context (output)
**
**	Returns:
**		usual sm_error code
*/

sm_ret_T
sm_pmfi_init(pmg_ctx_P *ppmg_ctx)
{
	sm_ret_T ret;

	if (getuid() == 0 || geteuid() == 0)
	{
		sm_io_fprintf(smioerr,
			"ERROR: do not run this as super-user!\n");
		return sm_err_perm(EPERM);
	}

	/* basic initialization */
	ret = sm_pmilt_init0(ppmg_ctx);
#if SM_HEAP_CHECK
	SmHeapCheck = 1;
	if (HEAP_CHECK)
		sm_heap_report(smioerr, 3);
#endif
	return ret;
}

/*
**  SM_PMFI_START -- start PMILTER
**
**	Parameters:
**		pmg_ctx -- pmilter (library) context
**		pmilter -- pmilter application context
**
**	Returns:
**		exit code
*/

sm_ret_T
sm_pmfi_start(pmg_ctx_P pmg_ctx, pmilter_P pmilter)
{
	sm_ret_T ret;

	SM_IS_PMG_CTX(pmg_ctx);
	SM_REQUIRE(pmilter != NULL);
	if (getuid() == 0 || geteuid() == 0)
	{
		sm_io_fprintf(smioerr,
			"ERROR: do not run this as super-user!\n");
		return EPERM;
	}
	pmg_ctx->pmg_pmilter = pmilter;

	if (SM_PM_VRS_MAJOR(pmilter->pmfi_version) != LPMILTER_VERSION_MAJOR)
	{
		sm_io_fprintf(smioerr,
			"ERROR: major version numbers do not match [lib=%d, pmilter=%d]\n"
			, LPMILTER_VERSION_MAJOR
			, SM_PM_VRS_MAJOR(pmilter->pmfi_version));
		return EINVAL;
	}

	/* initialize system */
	ret = sm_pmilt_init1(pmg_ctx);
	if (sm_is_err(ret))
	{
		sm_io_fprintf(smioerr, "sev=ERROR, sm_pmilt_init=%x\n", ret);
		goto error;
	}

	/* startup pmilt */
	ret = sm_pmilt_start(pmg_ctx);
	if (sm_is_err(ret))
	{
		sm_io_fprintf(smioerr, "sev=ERROR, sm_pmilt_start=%x\n", ret);
		goto error;
	}
	pmg_ctx->pmg_state = PMILT_ST_RUN;

	/* wait for events, schedule tasks */
	ret = evthr_loop(pmg_ctx->pmg_ev_ctx);

	pmg_ctx->pmg_state = PMILT_ST_STOPPING;
	ret = sm_pmilt_stop(pmg_ctx);
	pmg_ctx->pmg_state = PMILT_ST_STOPPED;
#if SM_HEAP_CHECK
	if (HEAP_CHECK)
		sm_heap_report(smioerr, 3);
#endif
	return SM_PMI_SUCCESS;

  error:
	/* ignore shutdown errors... */
	(void) sm_pmilt_stop(pmg_ctx);

	/* select an appropriate error here... */
	return sm_error_value(ret);
}

/*
**  SM_PMFI_STOP -- stop PMILTER
**
**	Parameters:
**		pmg_ctx -- pmilter (library) context
**
**	Returns:
**		usual sm_error code
*/

sm_ret_T
sm_pmfi_stop(pmg_ctx_P pmg_ctx)
{
	SM_IS_PMG_CTX(pmg_ctx);
	return sm_pmilt_stop(pmg_ctx);
}

/*
**  SM_PMFI_SETDBG -- set debug level
**
**	Parameters:
**		pmg_ctx -- pmilter (library) context
**		debuglevel -- debug level
**
**	Returns:
**		usual sm_error code
*/

sm_ret_T
sm_pmfi_setdbg(pmg_ctx_P pmg_ctx, unsigned int debuglevel)
{
	SM_IS_PMG_CTX(pmg_ctx);

#if PMILTER_DEBUG
	pm_debug = debuglevel;
#endif
	return SM_SUCCESS;
}
#endif /* MTA_USE_PMILTER */


syntax highlighted by Code2HTML, v. 0.9.1