main.c revision 173340
1/*
2 *  Copyright (c) 1999-2003, 2006, 2007 Sendmail, Inc. and its suppliers.
3 *	All rights reserved.
4 *
5 * By using this file, you agree to the terms and conditions set
6 * forth in the LICENSE file which can be found at the top level of
7 * the sendmail distribution.
8 *
9 */
10
11#include <sm/gen.h>
12SM_RCSID("@(#)$Id: main.c,v 8.83 2007/04/23 22:22:50 ca Exp $")
13
14#define _DEFINE	1
15#include "libmilter.h"
16#include <fcntl.h>
17#include <sys/stat.h>
18
19
20static smfiDesc_ptr smfi = NULL;
21
22/*
23**  SMFI_REGISTER -- register a filter description
24**
25**	Parameters:
26**		smfilter -- description of filter to register
27**
28**	Returns:
29**		MI_SUCCESS/MI_FAILURE
30*/
31
32int
33smfi_register(smfilter)
34	smfiDesc_str smfilter;
35{
36	size_t len;
37
38	if (smfi == NULL)
39	{
40		smfi = (smfiDesc_ptr) malloc(sizeof *smfi);
41		if (smfi == NULL)
42			return MI_FAILURE;
43	}
44	(void) memcpy(smfi, &smfilter, sizeof *smfi);
45	if (smfilter.xxfi_name == NULL)
46		smfilter.xxfi_name = "Unknown";
47
48	len = strlen(smfilter.xxfi_name) + 1;
49	smfi->xxfi_name = (char *) malloc(len);
50	if (smfi->xxfi_name == NULL)
51		return MI_FAILURE;
52	(void) sm_strlcpy(smfi->xxfi_name, smfilter.xxfi_name, len);
53
54	/* compare milter version with hard coded version */
55	if (smfi->xxfi_version != SMFI_VERSION &&
56	    smfi->xxfi_version != 2 &&
57	    smfi->xxfi_version != 3 &&
58	    smfi->xxfi_version != 4)
59	{
60		/* hard failure for now! */
61		smi_log(SMI_LOG_ERR,
62			"%s: smfi_register: version mismatch application: %d != milter: %d",
63			smfi->xxfi_name, smfi->xxfi_version,
64			(int) SMFI_VERSION);
65
66		/* XXX how about smfi? */
67		free(smfi->xxfi_name);
68		return MI_FAILURE;
69	}
70
71	return MI_SUCCESS;
72}
73
74/*
75**  SMFI_STOP -- stop milter
76**
77**	Parameters:
78**		none.
79**
80**	Returns:
81**		success.
82*/
83
84int
85smfi_stop()
86{
87	mi_stop_milters(MILTER_STOP);
88	return MI_SUCCESS;
89}
90
91/*
92**  Default values for some variables.
93**	Most of these can be changed with the functions below.
94*/
95
96static int dbg = 0;
97static char *conn = NULL;
98static int timeout = MI_TIMEOUT;
99static int backlog = MI_SOMAXCONN;
100
101/*
102**  SMFI_OPENSOCKET -- try the socket setup to make sure we'll be
103**		       able to start up
104**
105**	Parameters:
106**		rmsocket -- if true, instructs libmilter to attempt
107**			to remove the socket before creating it;
108**			only applies for "local:" or "unix:" sockets
109**
110**	Return:
111**		MI_SUCCESS/MI_FAILURE
112*/
113
114int
115smfi_opensocket(rmsocket)
116	bool rmsocket;
117{
118	if (smfi == NULL || conn == NULL)
119		return MI_FAILURE;
120
121	return mi_opensocket(conn, backlog, dbg, rmsocket, smfi);
122}
123
124/*
125**  SMFI_SETDBG -- set debug level.
126**
127**	Parameters:
128**		odbg -- new debug level.
129**
130**	Returns:
131**		MI_SUCCESS
132*/
133
134int
135smfi_setdbg(odbg)
136	int odbg;
137{
138	dbg = odbg;
139	return MI_SUCCESS;
140}
141
142/*
143**  SMFI_SETTIMEOUT -- set timeout (for read/write).
144**
145**	Parameters:
146**		otimeout -- new timeout.
147**
148**	Returns:
149**		MI_SUCCESS
150*/
151
152int
153smfi_settimeout(otimeout)
154	int otimeout;
155{
156	timeout = otimeout;
157	return MI_SUCCESS;
158}
159
160/*
161**  SMFI_SETCONN -- set connection information (socket description)
162**
163**	Parameters:
164**		oconn -- new connection information.
165**
166**	Returns:
167**		MI_SUCCESS/MI_FAILURE
168*/
169
170int
171smfi_setconn(oconn)
172	char *oconn;
173{
174	size_t l;
175
176	if (oconn == NULL || *oconn == '\0')
177		return MI_FAILURE;
178	l = strlen(oconn) + 1;
179	if ((conn = (char *) malloc(l)) == NULL)
180		return MI_FAILURE;
181	if (sm_strlcpy(conn, oconn, l) >= l)
182		return MI_FAILURE;
183	return MI_SUCCESS;
184}
185
186/*
187**  SMFI_SETBACKLOG -- set backlog
188**
189**	Parameters:
190**		obacklog -- new backlog.
191**
192**	Returns:
193**		MI_SUCCESS/MI_FAILURE
194*/
195
196int
197smfi_setbacklog(obacklog)
198	int obacklog;
199{
200	if (obacklog <= 0)
201		return MI_FAILURE;
202	backlog = obacklog;
203	return MI_SUCCESS;
204}
205
206
207/*
208**  SMFI_MAIN -- setup milter connnection and start listener.
209**
210**	Parameters:
211**		none.
212**
213**	Returns:
214**		MI_SUCCESS/MI_FAILURE
215*/
216
217int
218smfi_main()
219{
220	int r;
221
222	(void) signal(SIGPIPE, SIG_IGN);
223	if (conn == NULL)
224	{
225		smi_log(SMI_LOG_FATAL, "%s: missing connection information",
226			smfi->xxfi_name);
227		return MI_FAILURE;
228	}
229
230	(void) atexit(mi_clean_signals);
231	if (mi_control_startup(smfi->xxfi_name) != MI_SUCCESS)
232	{
233		smi_log(SMI_LOG_FATAL,
234			"%s: Couldn't start signal thread",
235			smfi->xxfi_name);
236		return MI_FAILURE;
237	}
238	r = MI_MONITOR_INIT();
239
240	/* Startup the listener */
241	if (mi_listener(conn, dbg, smfi, timeout, backlog) != MI_SUCCESS)
242		r = MI_FAILURE;
243
244	return r;
245}
246
247