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 }