Mercurial > sm-archive
comparison src/sm-archive.cpp @ 13:75e1a9bcbc2e
gpl3, add removal option for original recipients
author | carl |
---|---|
date | Sat, 25 Aug 2007 11:14:49 -0700 |
parents | f9e8bbf33a2a |
children | 8ebecad6530f |
comparison
equal
deleted
inserted
replaced
12:bb3d2cd6007e | 13:75e1a9bcbc2e |
---|---|
1 /* | 1 /* |
2 | 2 |
3 Copyright (c) 2004, 2005 Carl Byington - 510 Software Group, released | 3 Copyright (c) 2007 Carl Byington - 510 Software Group, released under |
4 under the GPL version 2 or any later version at your choice available at | 4 the GPL version 3 or any later version at your choice available at |
5 http://www.fsf.org/licenses/gpl.txt | 5 http://www.gnu.org/licenses/gpl-3.0.txt |
6 | 6 |
7 Based on a sample milter Copyright (c) 2000-2003 Sendmail, Inc. and its | 7 Based on a sample milter Copyright (c) 2000-2003 Sendmail, Inc. and its |
8 suppliers. Inspired by the DCC by Rhyolite Software | 8 suppliers. |
9 | 9 |
10 -p port The port through which the MTA will connect to this milter. | 10 -p port The port through which the MTA will connect to this milter. |
11 -t sec The timeout value. | 11 -t sec The timeout value. |
12 -c Check the config, and print a copy to stdout. Don't start the | 12 -c Check the config, and print a copy to stdout. Don't start the |
13 milter or do anything with the socket. | 13 milter or do anything with the socket. |
87 reset(true); | 87 reset(true); |
88 } | 88 } |
89 | 89 |
90 void mlfiPriv::reset(bool final) { | 90 void mlfiPriv::reset(bool final) { |
91 targets.clear(); | 91 targets.clear(); |
92 for (string_set::iterator i=removal.begin(); i!=removal.end(); i++) { | |
93 char *remove = (*i); | |
94 free(remove); | |
95 } | |
96 removal.clear(); | |
92 if (mailaddr) free(mailaddr); | 97 if (mailaddr) free(mailaddr); |
93 if (queueid) free(queueid); | 98 if (queueid) free(queueid); |
94 if (!final) { | 99 if (!final) { |
95 mailaddr = NULL; | 100 mailaddr = NULL; |
96 queueid = NULL; | 101 queueid = NULL; |
172 string_set::iterator i = priv.targets.find(target); | 177 string_set::iterator i = priv.targets.find(target); |
173 if (i == priv.targets.end()) priv.targets.insert(target); | 178 if (i == priv.targets.end()) priv.targets.insert(target); |
174 } | 179 } |
175 } | 180 } |
176 | 181 |
182 void add_remove(mlfiPriv &priv, char *remove); | |
183 void add_remove(mlfiPriv &priv, char *remove) | |
184 { | |
185 if (remove) { | |
186 string_set::iterator i = priv.removal.find(remove); | |
187 if (i == priv.removal.end()) priv.removal.insert(remove); | |
188 } | |
189 } | |
190 | |
177 sfsistat mlfi_envrcpt(SMFICTX *ctx, char **rcpt) | 191 sfsistat mlfi_envrcpt(SMFICTX *ctx, char **rcpt) |
178 { | 192 { |
179 mlfiPriv &priv = *MLFIPRIV; | 193 mlfiPriv &priv = *MLFIPRIV; |
180 CONFIG &dc = *priv.pc; | 194 CONFIG &dc = *priv.pc; |
181 if (!priv.queueid) priv.queueid = strdup(smfi_getsymval(ctx, "i")); | 195 if (!priv.queueid) priv.queueid = strdup(smfi_getsymval(ctx, "i")); |
184 char msg[maxlen]; | 198 char msg[maxlen]; |
185 snprintf(msg, sizeof(msg), "from <%s> to <%s>", priv.mailaddr, rcptaddr); | 199 snprintf(msg, sizeof(msg), "from <%s> to <%s>", priv.mailaddr, rcptaddr); |
186 my_syslog(&priv, msg); | 200 my_syslog(&priv, msg); |
187 } | 201 } |
188 char *target = dc.find_to(rcptaddr); | 202 char *target = dc.find_to(rcptaddr); |
203 add_target(priv, target); | |
204 bool remove = dc.find_remove(rcptaddr); | |
205 if (remove) add_remove(priv, strdup(rcptaddr)); | |
189 free(rcptaddr); | 206 free(rcptaddr); |
190 add_target(priv, target); | |
191 return SMFIS_CONTINUE; | 207 return SMFIS_CONTINUE; |
192 } | 208 } |
193 | 209 |
194 sfsistat mlfi_eom(SMFICTX *ctx) | 210 sfsistat mlfi_eom(SMFICTX *ctx) |
195 { | 211 { |
204 char msg[maxlen]; | 220 char msg[maxlen]; |
205 snprintf(msg, sizeof(msg), "adding recipient <%s>", target); | 221 snprintf(msg, sizeof(msg), "adding recipient <%s>", target); |
206 my_syslog(&priv, msg); | 222 my_syslog(&priv, msg); |
207 } | 223 } |
208 } | 224 } |
225 for (string_set::iterator i=priv.removal.begin(); i!=priv.removal.end(); i++) { | |
226 char *remove = (*i); | |
227 smfi_delrcpt(ctx, remove); | |
228 if (debug_syslog > 1) { | |
229 char msg[maxlen]; | |
230 snprintf(msg, sizeof(msg), "removing recipient <%s>", remove); | |
231 my_syslog(&priv, msg); | |
232 } | |
233 } | |
209 // reset for a new message on the same connection | 234 // reset for a new message on the same connection |
210 mlfi_abort(ctx); | 235 mlfi_abort(ctx); |
211 return SMFIS_CONTINUE; | 236 return SMFIS_CONTINUE; |
212 } | 237 } |
213 | 238 |
229 | 254 |
230 struct smfiDesc smfilter = | 255 struct smfiDesc smfilter = |
231 { | 256 { |
232 "SM-ARCHIVE", // filter name | 257 "SM-ARCHIVE", // filter name |
233 SMFI_VERSION, // version code -- do not change | 258 SMFI_VERSION, // version code -- do not change |
234 SMFIF_ADDRCPT, // flags | 259 SMFIF_ADDRCPT | \ |
260 SMFIF_DELRCPT, // flags | |
235 mlfi_connect, // connection info filter | 261 mlfi_connect, // connection info filter |
236 NULL, // SMTP HELO command filter | 262 NULL, // SMTP HELO command filter |
237 mlfi_envfrom, // envelope sender filter | 263 mlfi_envfrom, // envelope sender filter |
238 mlfi_envrcpt, // envelope recipient filter | 264 mlfi_envrcpt, // envelope recipient filter |
239 NULL, // header filter | 265 NULL, // header filter |
273 // and reload when needed. we also cleanup old | 299 // and reload when needed. we also cleanup old |
274 // configs whose reference count has gone to zero. | 300 // configs whose reference count has gone to zero. |
275 // | 301 // |
276 extern "C" {void* config_loader(void *arg);} | 302 extern "C" {void* config_loader(void *arg);} |
277 void* config_loader(void *arg) { | 303 void* config_loader(void *arg) { |
278 typedef set<CONFIG *> configp_set; | |
279 configp_set old_configs; | |
280 while (loader_run) { | 304 while (loader_run) { |
281 sleep(180); // look for modifications every 3 minutes | 305 sleep(180); // look for modifications every 3 minutes |
282 if (!loader_run) break; | 306 if (!loader_run) break; |
283 CONFIG &dc = *config; | 307 CONFIG &dc = *config; |
284 time_t then = dc.load_time; | 308 time_t then = dc.load_time; |
294 CONFIG *newc = new_conf(); | 318 CONFIG *newc = new_conf(); |
295 if (newc) { | 319 if (newc) { |
296 // replace the global config pointer | 320 // replace the global config pointer |
297 pthread_mutex_lock(&config_mutex); | 321 pthread_mutex_lock(&config_mutex); |
298 CONFIG *old = config; | 322 CONFIG *old = config; |
323 bool last = old && (!old->reference_count); | |
299 config = newc; | 324 config = newc; |
300 pthread_mutex_unlock(&config_mutex); | 325 pthread_mutex_unlock(&config_mutex); |
301 if (old) old_configs.insert(old); | 326 if (last) delete old; // there were no references to this config |
302 } | 327 } |
303 else { | 328 else { |
304 // failed to load new config | 329 // failed to load new config |
305 my_syslog("failed to load new configuration"); | 330 my_syslog("failed to load new configuration"); |
306 system("echo 'failed to load new sm-archive configuration from /etc/sm-archive' | mail -s 'error in /etc/sm-archive configuration' root"); | 331 system("echo 'failed to load new sm-archive configuration from /etc/sm-archive' | mail -s 'error in /etc/sm-archive configuration' root"); |
307 // update the load time on the current config to prevent complaining every 3 minutes | 332 // update the load time on the current config to prevent complaining every 3 minutes |
308 dc.load_time = time(NULL); | 333 dc.load_time = time(NULL); |
309 } | 334 } |
310 } | |
311 // now look for old configs with zero ref counts | |
312 for (configp_set::iterator i=old_configs.begin(); i!=old_configs.end(); ) { | |
313 CONFIG *old = *i; | |
314 if (!old->reference_count) { | |
315 if (debug_syslog) { | |
316 char buf[maxlen]; | |
317 snprintf(buf, sizeof(buf), "freeing memory for old configuration generation %d", old->generation); | |
318 my_syslog(buf); | |
319 } | |
320 delete old; // destructor does all the work | |
321 old_configs.erase(i++); | |
322 } | |
323 else i++; | |
324 } | 335 } |
325 } | 336 } |
326 return NULL; | 337 return NULL; |
327 } | 338 } |
328 | 339 |
426 debug_syslog = 10; | 437 debug_syslog = 10; |
427 CONFIG *conf = new_conf(); | 438 CONFIG *conf = new_conf(); |
428 if (conf) { | 439 if (conf) { |
429 conf->dump(); | 440 conf->dump(); |
430 delete conf; | 441 delete conf; |
442 clear_strings(); // for valgrind checking | |
431 return 0; | 443 return 0; |
432 } | 444 } |
433 else { | 445 else { |
434 return 1; // config failed to load | 446 return 1; // config failed to load |
435 } | 447 } |