/*
* Copyright (c) 2007 Claus Assmann
*
* By using this file, you agree to the terms and conditions set
* forth in the license/LICENSE.3C file which can be found at the
* top level of this source code distribution.
*/
#include "sm/generic.h"
SM_RCSID("@(#)$Id: pmilter_setreplies.c,v 1.4 2007/02/13 03:58:18 ca Exp $")
#include "sm/error.h"
#include "sm/assert.h"
#include "sm/ctype.h"
#include "pmilter.h"
#include "sm/pmfdef.h"
#include "sm/pmfapi.h"
#if MTA_USE_PMILTER && MTA_USE_RSAD
/*
** SM_PM_CLRREPLIES -- Clear replies in session context
**
** Parameters:
** pmse_ctx -- pmilter/SMTP server session context
**
** Returns:
** usual sm_error code
*/
sm_ret_T
pm_clrreplies(pmse_ctx_P pmse_ctx)
{
sm_ret_T ret;
SM_IS_PMSE_CTX(pmse_ctx);
ret = SM_SUCCESS;
if (pmse_ctx->pmse_nreplies > 0 && pmse_ctx->pmse_rcodes != NULL)
SM_FREE(pmse_ctx->pmse_rcodes);
if (pmse_ctx->pmse_nreplies > 0 && pmse_ctx->pmse_replies != NULL) {
uint u;
sm_str_P reply;
for (u = 0; u < pmse_ctx->pmse_nreplies; u++) {
reply = pmse_ctx->pmse_replies[u];
SM_STR_FREE(reply);
}
SM_FREE(pmse_ctx->pmse_replies);
}
pmse_ctx->pmse_nreplies = 0;
return ret;
}
/*
** SM_PMFI_SETREPLIES -- Set replies for several commands
**
** Parameters:
** pmse_ctx -- pmilter/SMTP server session context
** nreplies -- number of entries in replies array
** rcodes -- array of reply codes
** rtexts -- array of reply texts including error codes (can be NULL)
**
** Returns:
** usual sm_error code
*/
sm_ret_T
sm_pmfi_setreplies(pmse_ctx_P pmse_ctx, uint nreplies, int *rcodes, const char **rtexts)
{
sm_ret_T ret;
uint u;
int i;
const char *rtext;
SM_IS_PMSE_CTX(pmse_ctx);
ret = SM_SUCCESS;
if (NULL == rcodes || 0 == nreplies)
return sm_err_perm(EINVAL);
(void) pm_clrreplies(pmse_ctx);
/* check codes */
for (u = 0; u < nreplies; u++) {
i = rcodes[u] / 100;
if (i < 2 || i > 5)
return sm_err_perm(EINVAL);
}
pmse_ctx->pmse_nreplies = nreplies;
u = nreplies * sizeof(*pmse_ctx->pmse_rcodes);
if (u <= nreplies || u < sizeof(*pmse_ctx->pmse_rcodes))
return sm_err_perm(SM_E_OVFLW_SC);
pmse_ctx->pmse_rcodes = (int *) sm_zalloc(u);
if (NULL == pmse_ctx->pmse_rcodes)
return sm_err_temp(ENOMEM);
/* copy codes */
for (u = 0; u < nreplies; u++)
pmse_ctx->pmse_rcodes[u] = rcodes[u];
if (NULL == rtexts)
return SM_SUCCESS;
/* check rtexts */
ret = sm_err_perm(EINVAL);
for (u = 0; u < nreplies; u++) {
size_t len;
char c;
rtext = rtexts[u];
if (NULL == rtext)
goto error;
len = strlen(rtext);
if (len < 5)
goto error;
c = rtext[0];
if (c != '2' && c != '3' && c != '4' && c != '5')
goto error;
if (!ISDIGIT(rtext[1]) || !ISDIGIT(rtext[2]))
goto error;
if (rtext[len - 2] != '\r' || rtext[len - 1] != '\n')
goto error;
}
pmse_ctx->pmse_nreplies = nreplies;
u = nreplies * sizeof(*pmse_ctx->pmse_replies);
if (u <= nreplies || u < sizeof(*pmse_ctx->pmse_replies)) {
ret = sm_err_perm(SM_E_OVFLW_SC);
goto error;
}
pmse_ctx->pmse_replies = (sm_str_P *) sm_zalloc(u);
if (NULL == pmse_ctx->pmse_replies)
goto enomem;
/* next: copy */
for (u = 0; u < nreplies; u++) {
rtext = rtexts[u];
pmse_ctx->pmse_replies[u] = sm_str_scpy(NULL, rtext, strlen(rtext));
if (NULL == pmse_ctx->pmse_replies[u])
goto enomem;
}
return SM_SUCCESS;
enomem:
ret = sm_err_temp(ENOMEM);
error:
(void) pm_clrreplies(pmse_ctx);
return ret;
}
#endif /* MTA_USE_PMILTER && MTA_USE_RSAD */
syntax highlighted by Code2HTML, v. 0.9.1