/*
 * 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.
 *
 *	$Id: t-pmilter.h,v 1.19 2007/02/13 03:58:18 ca Exp $
 */

#ifndef T_PMILTER_H
#define T_PMILTER_H 1

#include "sm/generic.h"
#include "sm/types.h"
#include "sm/limits.h"
#include "sm/str.h"
#include "sm/queue.h"
#include "sm/pmfdef.h"
#include "sm/pmfapi.h"
#include "sm/pmilter.h"

#define SM_STAGE_NSEID	0
#define SM_STAGE_HELO	1
#define SM_STAGE_MAIL	2
#define SM_STAGE_RCPT	3
#define SM_STAGE_DATA	4
#define SM_STAGE_MSG	5
#define SM_STAGE_DOT	6
#define SM_STAGE_RPLC_MSG	7
#define SM_STAGE_RSAD	8
#define SM_STAGES	9

typedef struct pmt_ctx_S	pmt_ctx_T, *pmt_ctx_P;
typedef struct pmt_rcpt_S	pmt_rcpt_T, *pmt_rcpt_P;
typedef struct pmt_rcpts_S	pmt_rcpts_T, *pmt_rcpts_P;
TAILQ_HEAD(pmt_rcpts_S, pmt_rcpt_S);

/*
**  pmilter test context
**  Note: this is a "global" context, hence fd/fname are "global",
**  i.e., there can be only one file (transaction) at a time.
*/

struct pmt_ctx_S
{
	int		 pmt_rcode[SM_STAGES];
	uint		 pmt_delay[SM_STAGES];

	uint32_t	 pmt_flags;
	int		 pmt_fd;
	char		 pmt_fname[PATH_MAX];

	char		 pmt_rfname[PATH_MAX];
	int		 pmt_rfd;
	char		*pmt_buf;

	uint		 pmt_se_cnt;
	uint		 pmt_ta_cnt;

	uint		 pmt_ta_rcpts_ok;

	uint32_t	 pmt_cap;
	uint32_t	 pmt_fct;
	uint32_t	 pmt_feat;
	uint32_t	 pmt_misc;

	char		*pmt_reply[SM_STAGES];

	pmt_rcpts_T	 pmt_rcpts;	/* rcpts */
};

struct pmt_rcpt_S
{
	char		*pmtr_pa;
	TAILQ_ENTRY(pmt_rcpt_S)	pmtr_link;	/* links */
};

/* operations on rcpt lists */
#define PMT_RCPTS_INIT(rcpts)	TAILQ_INIT(rcpts)
#define PMT_RCPTS_EMPTY(rcpts)	TAILQ_EMPTY(rcpts)
#define PMT_RCPTS_FIRST(rcpts)	TAILQ_FIRST(rcpts)
#define PMT_RCPTS_END(rcpts)	TAILQ_END(rcpts)
#define PMT_RCPTS_NEXT(rcpt)	TAILQ_NEXT(rcpt, pmtr_link)
#define PMT_RCPTS_INSERT_TAIL(rcpts, rcpt) TAILQ_INSERT_TAIL(rcpts, rcpt, pmtr_link)
#define PMT_RCPTS_INSERT_HEAD(rcpts, rcpt) TAILQ_INSERT_HEAD(rcpts, rcpt, pmtr_link)
#define PMT_RCPTS_REMOVE(rcpts, rcpt)	TAILQ_REMOVE(rcpts, rcpt, pmtr_link)
#define PMT_RCPTS_REMOVE_FREE(ta, rcpts, rcpt) do {	\
		TAILQ_REMOVE((rcpts), (rcpt), pmtr_link);	\
		pmt_rcpt_free((ta), (rcpt));		\
	} while (0)


#define PMT_EXIT_CODE	999
#define PMT_EXIT(rcode)	((rcode) == PMT_EXIT_CODE)

#define PMT_FL_NONE	0x0000
#define PMT_FL_W2F	0x0001	/* write to file */
#define PMT_FL_FD_OPEN	0x0002	/* fd is ok to use */
#define PMT_FL_FD_FAIL	0x0004	/* don't try to open file */
#define PMT_FL_WR_FAIL	0x0008	/* write failed before */

#define PMT_FL_M_HOSTN	0x0010	/* request hostname macro */
#define PMT_FL_M_MSGID	0x0020	/* request message-id macro */
#define PMT_FL_M_SEID	0x0040	/* request session id macro */
#define PMT_FL_M_TAID	0x0080	/* request transaction id macro */

#define PMT_FL_M_2ND	0x0100	/* check whether macro is set in 2nd TA */

#define PMT_FL_R_ST	0x0200	/* check recipient status */

#define PMT_FL_RPLC_MSG	0x0400	/* replace message */
#define PMT_FL_RFD_OPEN	0x0800	/* fd is ok to use */
#define PMT_FL_RFD_FAIL	0x1000	/* don't try to open file */
#define PMT_FL_RD_FAIL	0x2000	/* read failed before */

#define PMT_FL_RD_RSAD	0x8000	/* RSAD is in used */

#define PMT_SET_FLAG(pmt_ctx, fl)	(pmt_ctx)->pmt_flags |= (fl)
#define PMT_CLR_FLAG(pmt_ctx, fl)	(pmt_ctx)->pmt_flags &= ~(fl)
#define PMT_IS_FLAG(pmt_ctx, fl)	(((pmt_ctx)->pmt_flags & (fl)) != 0)

int sm_getstage(char _arg);
sm_ret_T pmt_rcpt_new(pmt_ctx_P _pmt_ctx, const char *_rcpt_pa, pmt_rcpt_P *_prcpt);
sm_ret_T pmt_rcpts_free(pmt_ctx_P _pmt_ctx);

#endif /* ! T_PMILTER_H */


syntax highlighted by Code2HTML, v. 0.9.1