/*
 * 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_start.c,v 1.12 2006/10/05 04:27:38 ca Exp $")
#include "sm/error.h"
#include "sm/assert.h"
#include "sm/sysexits.h"
#include "sm/signal.h"
#include "sm/io.h"
#include "sm/socket.h"
#include "sm/sockcnf.h"
#include "pmilter.h"
#include "sm/pmfapi.h"

#if MTA_USE_PMILTER
/*
**  SM_PMILT_LISTEN -- start one listener
**
**	Parameters:
**		sockspec -- socket specification
**		pfd -- (pointer to) fd (output)
**
**	Returns:
**		usual sm_error code
*/

static sm_ret_T
sm_pmilt_listen(sockspec_P sockspec, int *pfd)
{
	sm_ret_T ret;

	SM_REQUIRE(sockspec != NULL);
	SM_REQUIRE(pfd != NULL);
	if (sockspec->sckspc_type == SOCK_TYPE_UNIX)
		sockspec->sock_unix.unixsckspc_umask = 0007;
	ret = sock_listen(sockspec, 10, pfd);
	return ret;
}

/*
**  SM_PMILT_STLI -- start PMILTER listeners
**
**	Parameters:
**		pmg_ctx -- pmilter (library) context
**
**	Returns:
**		usual sm_error code
**
**	Question: should we store "task" in pmilt_ctx?
*/

static sm_ret_T
sm_pmilt_stli(pmg_ctx_P pmg_ctx)
{
	int fd;
	sm_ret_T ret;
	sm_evthr_task_P task;

	SM_IS_PMG_CTX(pmg_ctx);

	if (pmg_ctx->pmg_sockname == NULL ||
	    *pmg_ctx->pmg_sockname == '\0')
		return sm_error_perm(SM_EM_PMILTER, EINVAL);
	ret = parsesockstr(pmg_ctx->pmg_sockname, &pmg_ctx->pmg_sockspec);
	if (sm_is_err(ret))
		goto error;

	/* start listen connections */
	/* these should be in pmg_ctx after the configuration has been read */

	/* SMTPS */
	ret = sm_pmilt_listen(&pmg_ctx->pmg_sockspec, &fd);
	if (sm_is_err(ret))
		goto error;

	pmg_ctx->pmg_sslfd = fd;
	ret = evthr_task_new(pmg_ctx->pmg_ev_ctx, &task, EVTHR_EV_LI,
			fd, NULL, sm_pmilt_smtpsli, (void *) pmg_ctx);
	if (sm_is_err(ret))
		goto error;

#if 0
	pmg_ctx->pmg_st_time = evthr_time(pmg_ctx->pmg_ev_ctx);
#endif
	return SM_SUCCESS;

  error:
	CLOSE_FD(pmg_ctx->pmg_sslfd);
	return ret;
}

/*
**  SM_PMILT_USR1 -- handler for USR1 signal
**
**	Parameters:
**		ctx -- pmilter (library) context
**
**	Returns:
**		EVTHR_WAITQ
*/

static sm_ret_T
sm_pmilt_usr1(sm_evthr_task_P tsk)
{
	pmg_ctx_P pmg_ctx;
	pmilter_P pmilter;

	SM_IS_EVTHR_TSK(tsk);
	pmg_ctx = (pmg_ctx_P) tsk->evthr_t_actx;
	SM_IS_PMG_CTX(pmg_ctx);
	pmilter = pmg_ctx->pmg_pmilter;
	if (pmilter != NULL && pmilter->pmfi_signal != NULL)
	{
		(void) (*pmilter->pmfi_signal)(pmg_ctx, SIGUSR1);
	}
	return EVTHR_WAITQ;
}

/*
**  SM_PMILT_USR2 -- handler for USR2 signal
**
**	Parameters:
**		ctx -- pmilter (library) context
**
**	Returns:
**		EVTHR_WAITQ
*/

static sm_ret_T
sm_pmilt_usr2(sm_evthr_task_P tsk)
{
	pmg_ctx_P pmg_ctx;
	pmilter_P pmilter;

	SM_IS_EVTHR_TSK(tsk);
	pmg_ctx = (pmg_ctx_P) tsk->evthr_t_actx;
	SM_IS_PMG_CTX(pmg_ctx);
	pmilter = pmg_ctx->pmg_pmilter;
	if (pmilter != NULL && pmilter->pmfi_signal != NULL)
	{
		(void) (*pmilter->pmfi_signal)(pmg_ctx, SIGUSR2);
	}
	return EVTHR_WAITQ;
}

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

sm_ret_T
sm_pmilt_start(pmg_ctx_P pmg_ctx)
{
	sm_ret_T ret;
	sm_evthr_task_P task;
	pmilter_P pmilter;

	SM_IS_PMG_CTX(pmg_ctx);

	ret = sm_pmilt_stli(pmg_ctx);
	if (sm_is_err(ret))
	{
		sm_io_fprintf(smioerr, "sev=ERROR, sm_pmilt_stli=%x\n", ret);
		goto error;
	}

	pmilter = pmg_ctx->pmg_pmilter;
	if (pmilter != NULL && pmilter->pmfi_signal != NULL)
	{
		ret = evthr_task_new(pmg_ctx->pmg_ev_ctx, &task, EVTHR_EV_SG,
			SIGUSR1, NULL, sm_pmilt_usr1, (void *) pmg_ctx);
		if (sm_is_err(ret))
		{
			sm_io_fprintf(smioerr,
				"sev=ERROR, start_sm_pmilt_usr1=%x\n",
				ret);
			goto error;
		}

		ret = evthr_task_new(pmg_ctx->pmg_ev_ctx, &task, EVTHR_EV_SG,
			SIGUSR2, NULL, sm_pmilt_usr2, (void *) pmg_ctx);
		if (sm_is_err(ret))
		{
			sm_io_fprintf(smioerr,
				"sev=ERROR, start_sm_pmilt_usr2=%x\n",
				ret);
			goto error;
		}
	}

	return SM_SUCCESS;

  error:
	/*
	**  cleanup? tasks may have been started, but PMILTER will terminate
	**  due to the errors.
	*/

	return ret;
}
#endif /* MTA_USE_PMILTER */


syntax highlighted by Code2HTML, v. 0.9.1