/*
* 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