/*
* Copyright (c) 2002-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: smar_start.c,v 1.51 2007/06/18 04:42:31 ca Exp $")
#include "sm/error.h"
#include "sm/assert.h"
#include "sm/map.h"
#include "smar.h"
#include "sm/unixsock.h"
#include "sm/signal.h"
#include "sm/misc.h"
#include "log.h"
/*
** SMAR_STLI -- start SMAR listeners
**
** Parameters:
** smar_ctx -- SMAR context
**
** Returns:
** usual sm_error code
**
** Question: should we store "task" in smar_ctx?
*/
static sm_ret_T
smar_stli(smar_ctx_P smar_ctx)
{
int lfd, r;
sm_ret_T ret;
sm_evthr_task_P task;
SM_IS_SMAR_CTX(smar_ctx);
/* start listen connections */
/* these should be in smar_ctx after the configuration has been read */
/* QMGR */
(void) unlink(smar_ctx->smar_cnf.smar_cnf_sock_abs);
lfd = unix_server_listen(smar_ctx->smar_cnf.smar_cnf_sock_abs, 10);
if (!is_valid_fd(lfd)) {
ret = sm_error_perm(SM_EM_AR, errno);
sm_log_write(smar_ctx->smar_lctx,
AR_LCAT_INIT, AR_LMOD_COMM,
SM_LOG_ERROR, 1,
"sev=ERROR, func=smar_start, socket=%.256s, server_listen=%m",
smar_ctx->smar_cnf.smar_cnf_sock_abs, ret);
goto error;
}
r = chmod(smar_ctx->smar_cnf.smar_cnf_sock_abs, 0660);
if (r < 0 && errno != ENOENT) {
ret = sm_error_perm(SM_EM_AR, errno);
sm_log_write(smar_ctx->smar_lctx,
AR_LCAT_INIT, AR_LMOD_COMM,
SM_LOG_ERROR, 1,
"sev=ERROR, func=smar_stli, socket=%.256s, chmod=%m",
smar_ctx->smar_cnf.smar_cnf_sock_abs, ret);
goto error;
}
#if 0
smar_ctx->smar_sslfd = lfd;
#endif /* 0 */
ret = evthr_task_new(smar_ctx->smar_ev_ctx, &task, EVTHR_EV_LI,
lfd, NULL, smar_li, (void *) smar_ctx);
if (sm_is_err(ret))
goto error;
return SM_SUCCESS;
error:
if (is_valid_fd(lfd))
close(lfd);
return ret;
}
#if SMAR_USE_DNS
/*
** SMAR_DNS_START -- start DNS system for SMAR
**
** Parameters:
** smar_ctx -- SMAR context
**
** Returns:
** usual sm_error code
*/
static sm_ret_T
smar_dns_start(smar_ctx_P smar_ctx)
{
sm_ret_T ret;
uint u;
dns_tsk_P dns_tsk;
for (u = 0; u < smar_ctx->smar_dns_ntsks; u++) {
dns_tsk = NULL;
ret = dns_tsk_new(smar_ctx->smar_dns_mgr_ctx,
smar_ctx->smar_cnf.smar_cnf_dns_flags,
smar_ctx->smar_nameserveripv4s[u], &dns_tsk);
if (sm_is_err(ret))
goto error;
dns_tsk->dnstsk_maxtimeouts = smar_ctx->smar_cnf.smar_cnf_dns_max_tmos;
}
ret = dns_tsk_start(smar_ctx->smar_dns_mgr_ctx, smar_ctx->smar_ev_ctx);
if (sm_is_err(ret))
goto error;
return SM_SUCCESS;
error:
/* XXX How to clean up? */
if (smar_ctx->smar_dns_mgr_ctx != NULL) {
dns_mgr_ctx_del(smar_ctx->smar_dns_mgr_ctx);
smar_ctx->smar_dns_mgr_ctx = NULL;
}
return ret;
}
#endif /* SMAR_USE_DNS */
/*
** SMAR_USR1 -- task handler for SIGUSR1
** reopen maps
**
** Parameters:
** tsk -- evthr task
**
** Returns:
** usual sm_error code
*/
static sm_ret_T
smar_usr1(sm_evthr_task_P tsk)
{
sm_ret_T ret;
smar_ctx_P smar_ctx;
char stats[256];
SM_IS_EVTHR_TSK(tsk);
smar_ctx = (smar_ctx_P) tsk->evthr_t_actx;
SM_IS_SMAR_CTX(smar_ctx);
if (smar_ctx->smar_ev_ctx != NULL) {
time_T now;
now = evthr_time(smar_ctx->smar_ev_ctx);
sm_io_fprintf(smioerr, "[");
(void) sm_timestamp(now, smioerr);
sm_io_fprintf(smioerr, "] sev=INFO, where=smar_usr1\n");
}
#if SM_HEAP_CHECK
if (HEAP_CHECK)
sm_heap_report(smioerr, 3);
#endif /* SM_HEAP_CHECK */
stats[0] = '\0';
bht_stats(smar_ctx->smar_dns_mgr_ctx->dnsmgr_req_ht, stats, sizeof(stats));
sm_io_fprintf(smioerr,
"dns_ht_size=%u\n"
"dns_ht_used=%u\n"
"dns_ht_limit=%u\n"
"%s"
, smar_ctx->smar_dns_mgr_ctx->dnsmgr_req_ht->bht_size
, smar_ctx->smar_dns_mgr_ctx->dnsmgr_req_ht->bht_used
, smar_ctx->smar_dns_mgr_ctx->dnsmgr_req_ht->bht_limit
, stats
);
smar_prt_cnf(&smar_ctx->smar_cnf, smioerr, true);
if (smar_ctx->smar_aliases != NULL) {
ret = sm_map_reopen(smar_ctx->smar_aliases, 0, SMPO_END);
if (sm_is_err(ret)) {
sm_io_fprintf(smioerr,
"sev=ERROR, func=smar_usr1, map=aliases, reopen=%m\n"
, ret);
/* XXX close map first? */
smar_ctx->smar_aliases = NULL;
}
}
if (smar_ctx->smar_access != NULL) {
ret = sm_map_reopen(smar_ctx->smar_access, 0, SMPO_END);
if (sm_is_err(ret)) {
sm_io_fprintf(smioerr,
"sev=ERROR, func=smar_usr1, map=access, reopen=%m\n"
, ret);
/* XXX close map first? */
smar_ctx->smar_access = NULL;
}
}
if (smar_ctx->smar_mt_map != NULL) {
ret = sm_map_reopen(smar_ctx->smar_mt_map, 0, SMPO_END);
if (sm_is_err(ret)) {
sm_io_fprintf(smioerr,
"sev=ERROR, func=smar_usr1, map=mt, reopen=%m\n"
, ret);
}
}
return EVTHR_WAITQ;
}
/*
** SMAR_USR2 -- task handler for SIGUSR2
**
** Parameters:
** tsk -- evthr task
**
** Returns:
** usual sm_error code
*/
static sm_ret_T
smar_usr2(sm_evthr_task_P tsk)
{
smar_ctx_P smar_ctx;
SM_IS_EVTHR_TSK(tsk);
smar_ctx = (smar_ctx_P) tsk->evthr_t_actx;
SM_IS_SMAR_CTX(smar_ctx);
(void) sm_log_reopen(smar_ctx->smar_lctx);
return EVTHR_WAITQ;
}
/*
** SMAR_START -- start SMAR
**
** Parameters:
** smar_ctx -- SMAR context
**
** Returns:
** usual sm_error code
*/
sm_ret_T
smar_start(smar_ctx_P smar_ctx)
{
sm_ret_T ret;
sm_evthr_task_P task;
SM_IS_SMAR_CTX(smar_ctx);
#if SMAR_USE_DNS
ret = smar_dns_start(smar_ctx);
if (sm_is_err(ret)) {
sm_log_write(smar_ctx->smar_lctx,
AR_LCAT_INIT, AR_LMOD_COMM,
SM_LOG_ERROR, 1,
"sev=ERROR, func=smar_start, smar_dns_start=%m",
ret);
goto error;
}
#endif /* SMAR_USE_DNS */
ret = evthr_task_new(smar_ctx->smar_ev_ctx, &task, EVTHR_EV_SG,
SIGUSR1, NULL, smar_usr1, (void *) smar_ctx);
if (sm_is_err(ret)) {
sm_log_write(smar_ctx->smar_lctx,
AR_LCAT_INIT, AR_LMOD_COMM,
SM_LOG_ERROR, 1,
"sev=ERROR, func=smar_start, smar_usr1=%m",
ret);
goto error;
}
ret = evthr_task_new(smar_ctx->smar_ev_ctx, &task, EVTHR_EV_SG,
SIGUSR2, NULL, smar_usr2, (void *) smar_ctx);
if (sm_is_err(ret)) {
sm_log_write(smar_ctx->smar_lctx,
AR_LCAT_INIT, AR_LMOD_COMM,
SM_LOG_ERROR, 1,
"sev=ERROR, func=smar_start, smar_usr2=%m",
ret);
goto error;
}
ret = smar_stli(smar_ctx);
if (sm_is_err(ret)) {
sm_log_write(smar_ctx->smar_lctx,
AR_LCAT_INIT, AR_LMOD_COMM,
SM_LOG_ERROR, 1,
"sev=ERROR, func=smar_start, smar_stli=%m",
ret);
goto error;
}
smar_ctx->smar_status = SMAR_ST_START;
return SM_SUCCESS;
error:
return ret;
}
syntax highlighted by Code2HTML, v. 0.9.1