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