Mercurial > hg > mlmmj
changeset 338:60da8d3ef63e
added digest support
author | mortenp |
---|---|
date | Tue, 14 Sep 2004 09:01:32 +1000 |
parents | 30a300660a9a |
children | 6ec796e27f54 |
files | README TUNABLES include/mlmmj-maintd.h include/mlmmj-sub.h include/mlmmj-unsub.h include/mlmmj.h include/send_digest.h listtexts/notifysub-digest listtexts/notifyunsub-digest listtexts/sub-confirm-digest listtexts/sub-ok-digest listtexts/unsub-confirm-digest listtexts/unsub-ok-digest src/Makefile.am src/listcontrol.c src/log_error.c src/mlmmj-maintd.c src/mlmmj-make-ml.sh src/mlmmj-send.c src/mlmmj-sub.c src/mlmmj-unsub.c src/send_digest.c src/subscriberfuncs.c |
diffstat | 23 files changed, 853 insertions(+), 164 deletions(-) [+] |
line wrap: on
line diff
--- a/README Tue Sep 14 08:47:55 2004 +1000 +++ b/README Tue Sep 14 09:01:32 2004 +1000 @@ -16,6 +16,7 @@ · Regular expression access control · Functionality to retrieve old posts · Web-interface + · Digests To use mlmmj, do the following:
--- a/TUNABLES Tue Sep 14 08:47:55 2004 +1000 +++ b/TUNABLES Tue Sep 14 09:01:32 2004 +1000 @@ -78,6 +78,17 @@ If this file is present, the owner(s) will get a mail with the address of someone sub/unsubscribing to a mailinglist. + · digestinterval (normal) + + This file specifies how many seconds will pass before the next digest is + sent. Defaults to 604800 seconds, which is 7 days. + + · digestmaxmails (normal) + + This file specifies how many mails can accumulate before digest sending is + triggered. Defaults to 50 mails, meaning that if 50 mails arrive to the list + before digestinterval have passed, the digest is delivered. + · bouncelife (normal) Here is specified for how long time in seconds an address can bounce before
--- a/include/mlmmj-maintd.h Tue Sep 14 08:47:55 2004 +1000 +++ b/include/mlmmj-maintd.h Tue Sep 14 09:01:32 2004 +1000 @@ -34,6 +34,7 @@ int clean_nolongerbouncing(const char *listdir); int probe_bouncers(const char *listdir, const char *mlmmjbounce); int unsub_bouncers(const char *listdir, const char *mlmmjunsub); +int run_digests(const char *listdir, const char *mlmmjsend); /* I know the below is nasty, but it requires C99 to have multiple * argument macros, and this would then be the only thing needing
--- a/include/mlmmj-sub.h Tue Sep 14 08:47:55 2004 +1000 +++ b/include/mlmmj-sub.h Tue Sep 14 09:01:32 2004 +1000 @@ -25,8 +25,9 @@ #define MLMMJ_SUBSCRIBE_H void confirm_sub(const char *listdir, const char *listaddr, - const char *subaddr, const char *mlmmjsend); + const char *subaddr, const char *mlmmjsend, int digest); void generate_subconfirm(const char *listdir, const char *listadr, - const char *subaddr, const char *mlmmjsend); + const char *subaddr, const char *mlmmjsend, + int digest); #endif /* MLMMJ_SUBSCRIBE_H */
--- a/include/mlmmj-unsub.h Tue Sep 14 08:47:55 2004 +1000 +++ b/include/mlmmj-unsub.h Tue Sep 14 09:01:32 2004 +1000 @@ -27,9 +27,10 @@ #include <sys/types.h> void confirm_unsub(const char *listdir, const char *listaddr, - const char *subaddr, const char *mlmmj); + const char *subaddr, const char *mlmmj, int digest); ssize_t unsubscribe(int subreadfd, int subwritefd, const char *address); void generate_unsubconfirm(const char *listdir, const char *listaddr, - const char *subaddr, const char *mlmmjsend); + const char *subaddr, const char *mlmmjsend, + int digest); #endif /* MLMMJ_UNSUBSCRIBE_H */
--- a/include/mlmmj.h Tue Sep 14 08:47:55 2004 +1000 +++ b/include/mlmmj.h Tue Sep 14 09:01:32 2004 +1000 @@ -28,7 +28,7 @@ #define RELAYHOST "127.0.0.1" #define READ_BUFSIZE 2048 -#define RECIPDELIM '+' +#define RECIPDELIM '+' /* XXX Warning: not changable at the moment */ #define MODREQLIFE 604800 /* How long time will moderation requests be kept? * 604800s is 7 days */ #define DISCARDEDLIFE 604800 /* How long time will discarded mails be kept? @@ -47,6 +47,12 @@ #define MEMORYMAILSIZE 16384 /* How big can a mail be before we don't want to it in memory? control/memorymailsize */ +#define DIGESTINTERVAL 604800 /* How long do we collect mails for digests + * 604800s is 7 days */ +#define DIGESTMAXMAILS 50 /* How many mails can accumulate before we send the + * digest */ +#define DIGESTMIMETYPE "digest" /* Which sub-type of multipart to use when + * sending digest mails */ struct strlist { int count;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/send_digest.h Tue Sep 14 09:01:32 2004 +1000 @@ -0,0 +1,30 @@ +/* Copyright (C) 2004 Morten K. Poulsen <morten at afdelingp.dk> + * + * $Id$ + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifndef SEND_DIGEST_H +#define SEND_DIGEST_H + +int send_digest(const char *listdir, int lastindex, int index, + const char *addr, const char *mlmmjsend); + +#endif /* SEND_DIGEST_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/listtexts/notifysub-digest Tue Sep 14 09:01:32 2004 +1000 @@ -0,0 +1,10 @@ +Hi, this is the mlmmj program managing the mailinglist + +*LSTADDR* + + +The following address has just subscribed to the digest of the +mailinglist: + +*SUBADDR* +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/listtexts/notifyunsub-digest Tue Sep 14 09:01:32 2004 +1000 @@ -0,0 +1,10 @@ +Hi, this is the mlmmj program managing the mailinglist + +*LSTADDR* + + +The following address has just unsubscribed from the digest of +mailinglist: + +*SUBADDR* +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/listtexts/sub-confirm-digest Tue Sep 14 09:01:32 2004 +1000 @@ -0,0 +1,21 @@ +Hi, this is the mlmmj program managing the mailinglist + +*LSTADDR* + + +To confirm you want the address + +*SUBADDR* + + +added to the digest of this list, please send a reply to + +*CNFADDR* + + +Your mailer probably automatically replies to this address, when you hit +the reply button. + +This confirmation serves two purposes. It tests that mail can be sent to your +address. Second, it makes sure someone else did not try and subscribe your +emailaddress.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/listtexts/sub-ok-digest Tue Sep 14 09:01:32 2004 +1000 @@ -0,0 +1,6 @@ +WELCOME! You have been subscribed to the digest of the + +*LSTADDR* + + +mailinglist.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/listtexts/unsub-confirm-digest Tue Sep 14 09:01:32 2004 +1000 @@ -0,0 +1,21 @@ +Hi, this is the mlmmj program managing the mailinglist + +*LSTADDR* + + +To confirm you want the address + +*SUBADDR* + + +removed from the digest of this list, please send a reply to + +*CNFADDR* + + +Your mailer probably automatically replies to this address, when you hit +the reply button. + +If you're not subscribed with this list, you will recieve no reply. You can +see in the From header of a mail to the mailinglist which mail you're sub- +scribed with.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/listtexts/unsub-ok-digest Tue Sep 14 09:01:32 2004 +1000 @@ -0,0 +1,6 @@ +GOODBYE! You have been removed from the digest of the + +*LSTADDR* + + +mailinglist.
--- a/src/Makefile.am Tue Sep 14 08:47:55 2004 +1000 +++ b/src/Makefile.am Tue Sep 14 09:01:32 2004 +1000 @@ -47,4 +47,5 @@ mlmmj_maintd_SOURCES = mlmmj-maintd.c print-version.c log_error.c mygetline.c \ strgen.c random-int.c chomp.c writen.c memory.c \ - ctrlvalue.c + ctrlvalue.c send_digest.c getlistaddr.c dumpfd2fd.c \ + mylocking.c
--- a/src/listcontrol.c Tue Sep 14 08:47:55 2004 +1000 +++ b/src/listcontrol.c Tue Sep 14 09:01:32 2004 +1000 @@ -43,9 +43,13 @@ #include "memory.h" enum ctrl_e { + CTRL_SUBSCRIBE_DIGEST, CTRL_SUBSCRIBE, + CTRL_CONFSUB_DIGEST, CTRL_CONFSUB, + CTRL_UNSUBSCRIBE_DIGEST, CTRL_UNSUBSCRIBE, + CTRL_CONFUNSUB_DIGEST, CTRL_CONFUNSUB, CTRL_BOUNCES, CTRL_MODERATE, @@ -61,11 +65,17 @@ unsigned int accepts_parameter; }; -/* must match the enum */ +/* Must match the enum. CAREFUL when using commands that are substrings + * of other commands. In that case the longest one have to be listed + * first to match correctly. */ static struct ctrl_command ctrl_commands[] = { + { "subscribe-digest", 0 }, { "subscribe", 0 }, + { "confsub-digest", 1 }, { "confsub", 1 }, + { "unsubscribe-digest", 0 }, { "unsubscribe", 0 }, + { "confunsub-digest", 1 }, { "confunsub", 1 }, { "bounces", 1 }, { "moderate", 1 }, @@ -122,45 +132,94 @@ " discarding mail"); exit(EXIT_SUCCESS); } - myfree(controlstr); - break; } else if (!ctrl_commands[ctrl].accepts_parameter && (controlstr[cmdlen] == '\0')) { param = NULL; + } else { + /* malformed request, ignore and clean up */ + unlink(mailname); + exit(EXIT_SUCCESS); + } + myfree(controlstr); break; - } else { - log_error(LOG_ARGS, "Received a malformed" - " list control request"); - myfree(controlstr); - return -1; - } } } switch (ctrl) { + /* listname+subscribe-digest@domain.tld */ + case CTRL_SUBSCRIBE_DIGEST: + unlink(mailname); + if (closedlist) + exit(EXIT_SUCCESS); + if (!strchr(fromemails->emaillist[0], '@')) + /* Not a valid From: address, silently ignore */ + exit(EXIT_SUCCESS); + execlp(mlmmjsub, mlmmjsub, + "-L", listdir, + "-a", fromemails->emaillist[0], + "-d", + "-C", NULL); + log_error(LOG_ARGS, "execlp() of '%s' failed", + mlmmjsub); + exit(EXIT_FAILURE); + break; + + /* listname+subscribe@domain.tld */ case CTRL_SUBSCRIBE: unlink(mailname); - if (closedlist) exit(EXIT_SUCCESS); - if(strchr(fromemails->emaillist[0], '@')) { + if (closedlist) + exit(EXIT_SUCCESS); + if (!strchr(fromemails->emaillist[0], '@')) + /* Not a valid From: address, silently ignore */ + exit(EXIT_SUCCESS); execlp(mlmmjsub, mlmmjsub, "-L", listdir, "-a", fromemails->emaillist[0], "-C", NULL); - log_error(LOG_ARGS, "execlp() of '%s' failed", mlmmjsub); + log_error(LOG_ARGS, "execlp() of '%s' failed", + mlmmjsub); exit(EXIT_FAILURE); - } else /* Not a valid From: address, so we silently ignore */ - exit(EXIT_SUCCESS); break; + /* listname+subconf-digest-COOKIE@domain.tld */ + case CTRL_CONFSUB_DIGEST: + unlink(mailname); + if (closedlist) + exit(EXIT_SUCCESS); + conffilename = concatstr(3, listdir, "/subconf/", param); + myfree(param); + if((tmpfd = open(conffilename, O_RDONLY)) < 0) { + /* invalid COOKIE, silently ignore */ + exit(EXIT_SUCCESS); + } + tmpstr = mygetline(tmpfd); + chomp(tmpstr); + close(tmpfd); + unlink(conffilename); + execlp(mlmmjsub, mlmmjsub, + "-L", listdir, + "-a", tmpstr, + "-d", + "-c", NULL); + log_error(LOG_ARGS, "execlp() of '%s' failed", + mlmmjsub); + exit(EXIT_FAILURE); + break; + + /* listname+subconf-COOKIE@domain.tld */ case CTRL_CONFSUB: unlink(mailname); - if (closedlist) exit(EXIT_SUCCESS); + if (closedlist) + exit(EXIT_SUCCESS); conffilename = concatstr(3, listdir, "/subconf/", param); myfree(param); - if((tmpfd = open(conffilename, O_RDONLY)) >= 0) { + if((tmpfd = open(conffilename, O_RDONLY)) < 0) { + /* invalid COOKIE, silently ignore */ + exit(EXIT_SUCCESS); + } tmpstr = mygetline(tmpfd); chomp(tmpstr); close(tmpfd); @@ -172,14 +231,34 @@ log_error(LOG_ARGS, "execlp() of '%s' failed", mlmmjsub); exit(EXIT_FAILURE); - } else /* Not a confirm so silently ignore */ - exit(EXIT_SUCCESS); break; + /* listname+unsubscribe-digest@domain.tld */ + case CTRL_UNSUBSCRIBE_DIGEST: + unlink(mailname); + if (closedlist) + exit(EXIT_SUCCESS); + if (!strchr(fromemails->emaillist[0], '@')) + /* Not a valid From: address, silently ignore */ + exit(EXIT_SUCCESS); + execlp(mlmmjunsub, mlmmjunsub, + "-L", listdir, + "-a", fromemails->emaillist[0], + "-d", + "-C", NULL); + log_error(LOG_ARGS, "execlp() of '%s' failed", + mlmmjunsub); + exit(EXIT_FAILURE); + break; + + /* listname+unsubscribe@domain.tld */ case CTRL_UNSUBSCRIBE: unlink(mailname); - if (closedlist) exit(EXIT_SUCCESS); - if(strchr(fromemails->emaillist[0], '@')) { + if (closedlist) + exit(EXIT_SUCCESS); + if (!strchr(fromemails->emaillist[0], '@')) + /* Not a valid From: address, silently ignore */ + exit(EXIT_SUCCESS); execlp(mlmmjunsub, mlmmjunsub, "-L", listdir, "-a", fromemails->emaillist[0], @@ -187,16 +266,44 @@ log_error(LOG_ARGS, "execlp() of '%s' failed", mlmmjunsub); exit(EXIT_FAILURE); - } else /* Not a valid From: address, so we silently ignore */ - exit(EXIT_SUCCESS); break; + /* listname+unsubconf-digest-COOKIE@domain.tld */ + case CTRL_CONFUNSUB_DIGEST: + unlink(mailname); + if (closedlist) + exit(EXIT_SUCCESS); + conffilename = concatstr(3, listdir, "/unsubconf/", param); + myfree(param); + if((tmpfd = open(conffilename, O_RDONLY)) < 0) { + /* invalid COOKIE, silently ignore */ + exit(EXIT_SUCCESS); + } + tmpstr = mygetline(tmpfd); + close(tmpfd); + chomp(tmpstr); + unlink(conffilename); + execlp(mlmmjunsub, mlmmjunsub, + "-L", listdir, + "-a", tmpstr, + "-d", + "-c", NULL); + log_error(LOG_ARGS, "execlp() of '%s' failed", + mlmmjunsub); + exit(EXIT_FAILURE); + break; + + /* listname+unsubconf-COOKIE@domain.tld */ case CTRL_CONFUNSUB: unlink(mailname); - if (closedlist) exit(EXIT_SUCCESS); + if (closedlist) + exit(EXIT_SUCCESS); conffilename = concatstr(3, listdir, "/unsubconf/", param); myfree(param); - if((tmpfd = open(conffilename, O_RDONLY)) >= 0) { + if((tmpfd = open(conffilename, O_RDONLY)) < 0) { + /* invalid COOKIE, silently ignore */ + exit(EXIT_SUCCESS); + } tmpstr = mygetline(tmpfd); close(tmpfd); chomp(tmpstr); @@ -208,10 +315,9 @@ log_error(LOG_ARGS, "execlp() of '%s' failed", mlmmjunsub); exit(EXIT_FAILURE); - } else /* Not a confirm so silently ignore */ - exit(EXIT_SUCCESS); break; + /* listname+bounces-user=example.tld-INDEX@domain.tld */ case CTRL_BOUNCES: bouncenr = strrchr(param, '-'); if (!bouncenr) { /* malformed bounce, ignore and clean up */ @@ -228,6 +334,7 @@ exit(EXIT_FAILURE); break; + /* listname+moderate-COOKIE@domain.tld */ case CTRL_MODERATE: /* TODO Add accept/reject parameter to moderate */ unlink(mailname); @@ -236,15 +343,16 @@ if(stat(moderatefilename, &stbuf) < 0) { myfree(moderatefilename); exit(EXIT_SUCCESS); /* just exit, no mail to moderate */ - } else { + } execlp(mlmmjsend, mlmmjsend, "-L", listdir, "-m", moderatefilename, NULL); - log_error(LOG_ARGS, "execlp() of %s failed", mlmmjsend); + log_error(LOG_ARGS, "execlp() of '%s' failed", + mlmmjsend); exit(EXIT_FAILURE); - } break; + /* listname+help@domain.tld */ case CTRL_HELP: unlink(mailname); if(strchr(fromemails->emaillist[0], '@')) @@ -252,12 +360,10 @@ mlmmjsend); break; + /* listname+get-INDEX@domain.tld */ case CTRL_GET: - errno = 0; unlink(mailname); - if(!param) /* malformed get, ignore silently */ - exit(EXIT_SUCCESS); - else { /* sanity check--is it all digits? */ + /* sanity check--is it all digits? */ for(c = param; *c != '\0'; c++) { if(!isdigit((int)*c)) exit(EXIT_SUCCESS); @@ -266,7 +372,6 @@ param); if(stat(archivefilename, &stbuf) < 0) exit(EXIT_SUCCESS); - else { execlp(mlmmjsend, mlmmjsend, "-T", fromemails->emaillist[0], "-L", listdir, @@ -276,8 +381,6 @@ log_error(LOG_ARGS, "execlp() of '%s' failed", mlmmjsend); exit(EXIT_FAILURE); - } - } break; }
--- a/src/log_error.c Tue Sep 14 08:47:55 2004 +1000 +++ b/src/log_error.c Tue Sep 14 09:01:32 2004 +1000 @@ -25,6 +25,8 @@ #include <string.h> #include <stdlib.h> #include <stdarg.h> +#include <sys/types.h> +#include <unistd.h> #include "log_error.h" #include "../config.h"
--- a/src/mlmmj-maintd.c Tue Sep 14 08:47:55 2004 +1000 +++ b/src/mlmmj-maintd.c Tue Sep 14 09:01:32 2004 +1000 @@ -42,6 +42,8 @@ #include "wrappers.h" #include "memory.h" #include "ctrlvalue.h" +#include "send_digest.h" +#include "mylocking.h" static int maintdlogfd = -1; @@ -740,6 +742,134 @@ return 0; } +int run_digests(const char *listdir, const char *mlmmjsend) +{ + char *lasttimestr, *lastindexstr; + char *digestname, *indexname; + char *digestintervalstr, *digestmaxmailsstr; + char *s1, *s2, *s3; + time_t digestinterval, t, lasttime; + long digestmaxmails, lastindex, index; + int fd, indexfd, lock; + size_t lenbuf, lenstr; + + digestintervalstr = ctrlvalue(listdir, "digestinterval"); + if (digestintervalstr) { + digestinterval = (time_t)atol(digestintervalstr); + myfree(digestintervalstr); + } else { + digestinterval = (time_t)DIGESTINTERVAL; + } + + digestmaxmailsstr = ctrlvalue(listdir, "digestmaxmails"); + if (digestmaxmailsstr) { + digestmaxmails = atol(digestmaxmailsstr); + myfree(digestmaxmailsstr); + } else { + digestmaxmails = DIGESTMAXMAILS; + } + + digestname = concatstr(2, listdir, "/lastdigest"); + fd = open(digestname, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); + if (fd < 0) { + log_error(LOG_ARGS, "Could not open '%s'", digestname); + myfree(digestname); + return 1; + } + + lock = myexcllock(fd); + if(lock) { + log_error(LOG_ARGS, "Error locking lastdigest"); + myfree(digestname); + close(fd); + return 1; + } + + s1 = mygetline(fd); + + /* Syntax is lastindex:lasttime */ + if (s1 && (lasttimestr = strchr(s1, ':'))) { + *(lasttimestr++) = '\0'; + lasttime = atol(lasttimestr); + lastindexstr = s1; + lastindex = atol(lastindexstr); + } else { + if (s1 && (strlen(s1) > 0)) { + log_error(LOG_ARGS, "'%s' contains malformed data", + digestname); + myfree(digestname); + myfree(s1); + myunlock(fd); + close(fd); + return 1; + } + /* If lastdigest is empty, we start from scratch */ + lasttime = 0; + lastindex = 0; + } + + indexname = concatstr(2, listdir, "/index"); + indexfd = open(indexname, O_RDONLY); + if (indexfd < 0) { + log_error(LOG_ARGS, "Could not open '%s'", indexname); + myfree(digestname); + myfree(indexname); + myfree(s1); + myunlock(fd); + close(fd); + return 1; + } + s2 = mygetline(indexfd); + close(indexfd); + if (!s2) { + /* If we don't have an index, no mails have been sent to the + * list, and therefore we don't need to send a digest */ + myfree(digestname); + myfree(indexname); + myfree(s1); + myunlock(fd); + close(fd); + return 1; + } + + index = atol(s2); + t = time(NULL); + + if ((t - lasttime >= digestinterval) || + (index - lastindex >= digestmaxmails)) { + + if (index > lastindex+digestmaxmails) + index = lastindex+digestmaxmails; + + send_digest(listdir, lastindex+1, index, NULL, mlmmjsend); + + if (lseek(fd, 0, SEEK_SET) < 0) { + log_error(LOG_ARGS, "Could not seek '%s'", digestname); + } else { + /* index + ':' + time + '\n' + '\0' */ + lenbuf = 20 + 1 + 20 + 2; + s3 = mymalloc(lenbuf); + lenstr = snprintf(s3, lenbuf, "%ld:%ld\n", index, t); + if (lenstr >= lenbuf) + lenstr = lenbuf - 1; + if (writen(fd, s3, lenstr) == -1) { + log_error(LOG_ARGS, "Could not write new '%s'", + digestname); + } + myfree(s3); + } + } + + myfree(digestname); + myfree(indexname); + myfree(s1); + myfree(s2); + myunlock(fd); + close(fd); + + return 0; +} + void do_maintenance(const char *listdir, const char *mlmmjsend, const char *mlmmjbounce, const char *mlmmjunsub) { @@ -825,6 +955,10 @@ mlmmjbounce, ");\n"); probe_bouncers(listdir, mlmmjbounce); + WRITEMAINTLOG6(5, "run_digests(", listdir, ", ", mlmmjsend, + ");\n"); + run_digests(listdir, mlmmjsend); + close(maintdlogfd); logstr = concatstr(3, listdir, "/", MAINTD_LOGFILE);
--- a/src/mlmmj-make-ml.sh Tue Sep 14 08:47:55 2004 +1000 +++ b/src/mlmmj-make-ml.sh Tue Sep 14 09:01:32 2004 +1000 @@ -67,12 +67,12 @@ mkdir -p $LISTDIR for DIR in incoming queue queue/discarded archive text subconf unsubconf \ - bounce control moderation subscribers.d requeue + bounce control moderation subscribers.d digesters.d requeue do mkdir "$LISTDIR"/"$DIR" done -touch "$LISTDIR"/index +test -f "$LISTDIR"/index || touch "$LISTDIR"/index echo -n "The Domain for the List? [] : " read FQDN
--- a/src/mlmmj-send.c Tue Sep 14 08:47:55 2004 +1000 +++ b/src/mlmmj-send.c Tue Sep 14 09:01:32 2004 +1000 @@ -369,11 +369,11 @@ } else continue; - if(from) + if(from) { sendres = send_mail(sockfd, from, addr, replyto, mailmap, mailsize, listdir, NULL, hdrs, hdrslen, body, bodylen); - else { + } else { bounceaddr = bounce_from_adr(addr, listaddr, archivefilename); sendres = send_mail(sockfd, bounceaddr, addr, replyto, @@ -456,6 +456,7 @@ " '4' means 'send to file with recipients'\n" " '5' means 'bounceprobe'\n" " '6' means 'single listmail to single recipient'\n" + " '7' means 'digest'\n" " -L: Full path to list directory\n" " -m: Full path to mail file\n" " -r: Relayhost IP address (defaults to 127.0.0.1)\n" @@ -470,7 +471,7 @@ { size_t len = 0, hdrslen, bodylen; int sockfd = 0, mailfd = 0, opt, mindex, subfd, tmpfd; - int deletewhensent = 1, sendres, archive = 1; + int deletewhensent = 1, sendres, archive = 1, digest = 0; char *listaddr, *mailfilename = NULL, *subfilename = NULL; char *replyto = NULL, *bounceaddr = NULL, *to_addr = NULL; char *relayhost = NULL, *archivefilename = NULL, *tmpstr; @@ -574,6 +575,12 @@ exit(EXIT_FAILURE); } + if((listctrl[0] == '7' && listdir == NULL)) { + fprintf(stderr, "With -l 7 you need -L\n"); + exit(EXIT_FAILURE); + } + + switch(listctrl[0]) { case '1': case '2': @@ -581,6 +588,7 @@ case '4': case '5': case '6': + case '7': archive = 0; default: break; @@ -797,8 +805,16 @@ myfree(tmpstr); } break; + case '7': + digest = 1; + archivefilename = mystrdup("digest"); + /* fall through */ default: /* normal list mail */ + if (!digest) { subddirname = concatstr(2, listdir, "/subscribers.d/"); + } else { + subddirname = concatstr(2, listdir, "/digesters.d/"); + } if((subddir = opendir(subddirname)) == NULL) { log_error(LOG_ARGS, "Could not opendir(%s)", subddirname); @@ -807,15 +823,13 @@ myfree(body); exit(EXIT_FAILURE); } - myfree(subddirname); while((dp = readdir(subddir)) != NULL) { if(!strcmp(dp->d_name, ".")) continue; if(!strcmp(dp->d_name, "..")) continue; - subfilename = concatstr(3, listdir, "/subscribers.d/", - dp->d_name); + subfilename = concatstr(2, subddirname, dp->d_name); if((subfd = open(subfilename, O_RDONLY)) < 0) { log_error(LOG_ARGS, "Could not open '%s'", subfilename); @@ -841,6 +855,7 @@ close(subfd); } closedir(subddir); + myfree(subddirname); break; }
--- a/src/mlmmj-sub.c Tue Sep 14 08:47:55 2004 +1000 +++ b/src/mlmmj-sub.c Tue Sep 14 09:01:32 2004 +1000 @@ -47,13 +47,18 @@ #include "memory.h" void confirm_sub(const char *listdir, const char *listaddr, - const char *subaddr, const char *mlmmjsend) + const char *subaddr, const char *mlmmjsend, + int digest) { int subtextfd, queuefd; char *buf, *subtextfilename, *randomstr, *queuefilename = NULL; char *fromaddr, *listname, *listfqdn, *s1; + if (!digest) { subtextfilename = concatstr(2, listdir, "/text/sub-ok"); + } else { + subtextfilename = concatstr(2, listdir, "/text/sub-ok-digest"); + } if((subtextfd = open(subtextfilename, O_RDONLY)) < 0) { log_error(LOG_ARGS, "Could not open '%s'", subtextfilename); @@ -84,8 +89,16 @@ fromaddr = concatstr(3, listname, "+bounces-help@", listfqdn); - s1 = concatstr(9, "From: ", listname, "+help@", listfqdn, "\nTo: ", - subaddr, "\nSubject: Welcome to ", listaddr, "\n\n"); + if (!digest) { + s1 = concatstr(9, "From: ", listname, "+help@", listfqdn, + "\nTo: ", subaddr, "\nSubject: Welcome to ", + listaddr, "\n\n"); + } else { + s1 = concatstr(9, "From: ", listname, "+help@", listfqdn, + "\nTo: ", subaddr, "\nSubject: Welcome to " + "digest of ", listaddr, "\n\n"); + } + if(writen(queuefd, s1, strlen(s1)) < 0) { log_error(LOG_ARGS, "Could not write welcome mail"); exit(EXIT_FAILURE); @@ -124,7 +137,8 @@ } void notify_sub(const char *listdir, const char *listaddr, - const char *subaddr, const char *mlmmjsend) + const char *subaddr, const char *mlmmjsend, + int digest) { char *maildata[4] = { "*LSTADDR*", NULL, "*SUBADDR*", NULL }; char *listfqdn, *listname, *fromaddr, *fromstr, *subject; @@ -136,9 +150,18 @@ maildata[3] = mystrdup(subaddr); fromaddr = concatstr(3, listname, "+bounces-help@", listfqdn); fromstr = concatstr(3, listname, "+owner@", listfqdn); + if (!digest) { subject = concatstr(2, "New subscription to ", listaddr); queuefilename = prepstdreply(listdir, "notifysub", fromstr, - fromstr, NULL, subject, 2, maildata); + fromstr, NULL, subject, 2, + maildata); + } else { + subject = concatstr(2, "New subscription to digest of ", + listaddr); + queuefilename = prepstdreply(listdir, "notifysub-digest", + fromstr, fromstr, NULL, + subject, 2, maildata); + } MY_ASSERT(queuefilename) myfree(listname); myfree(listfqdn); @@ -158,7 +181,8 @@ } void generate_subconfirm(const char *listdir, const char *listaddr, - const char *subaddr, const char *mlmmjsend) + const char *subaddr, const char *mlmmjsend, + int digest) { int subconffd, subtextfd, queuefd; char *confirmaddr, *listname, *listfqdn, *confirmfilename = NULL; @@ -198,15 +222,20 @@ close(subconffd); - confirmaddr = concatstr(5, listname, "+confsub-", randomstr, "@", - listfqdn); - fromaddr = concatstr(5, listname, "+bounces-confsub-", randomstr, "@", listfqdn); - myfree(randomstr); + if (!digest) { + subtextfilename = concatstr(2, listdir, "/text/sub-confirm"); + confirmaddr = concatstr(5, listname, "+confsub-", + randomstr, "@", listfqdn); + } else { + subtextfilename = concatstr(2, listdir, "/text/sub-confirm-digest"); + confirmaddr = concatstr(5, listname, "+confsub-digest-", + randomstr, "@", listfqdn); + } - subtextfilename = concatstr(2, listdir, "/text/sub-confirm"); + myfree(randomstr); if((subtextfd = open(subtextfilename, O_RDONLY)) < 0) { log_error(LOG_ARGS, "Could not open '%s'", subtextfilename); @@ -233,9 +262,16 @@ exit(EXIT_FAILURE); } - s1 = concatstr(9, "From: ", listname, "+help@", listfqdn, "\nTo: ", - subaddr, "\nSubject: Confirm subscribe to ", listaddr, - "\n\n"); + if (!digest) { + s1 = concatstr(9, "From: ", listname, "+help@", listfqdn, + "\nTo: ", subaddr, "\nSubject: Confirm subscribe to ", + listaddr, "\n\n"); + } else { + s1 = concatstr(9, "From: ", listname, "+help@", listfqdn, + "\nTo: ", subaddr, "\nSubject: Confirm subscribe to " + "digest of ", listaddr, "\n\n"); + } + if(writen(queuefd, s1, strlen(s1)) < 0) { log_error(LOG_ARGS, "Could not write subconffile"); exit(EXIT_FAILURE); @@ -294,6 +330,7 @@ " -a: Email address to subscribe \n" " -c: Send welcome mail\n" " -C: Request mail confirmation\n" + " -d: Subscribe to digest of list\n" " -h: This help\n" " -L: Full path to list directory\n" " -U: Don't switch to the user id of the listdir owner\n" @@ -308,7 +345,7 @@ char *listaddr, *listdir = NULL, *address = NULL, *subfilename = NULL; char *mlmmjsend, *bindir, chstr[2]; int subconfirm = 0, confirmsub = 0, opt, subfilefd, lock, notifysub; - int changeuid = 1, status; + int changeuid = 1, status, digest = 0; size_t len; off_t suboff; struct stat st; @@ -322,7 +359,7 @@ mlmmjsend = concatstr(2, bindir, "/mlmmj-send"); myfree(bindir); - while ((opt = getopt(argc, argv, "hcCVL:a:")) != -1) { + while ((opt = getopt(argc, argv, "hcCdVL:a:")) != -1) { switch(opt) { case 'a': address = optarg; @@ -333,6 +370,9 @@ case 'C': subconfirm = 1; break; + case 'd': + digest = 1; + break; case 'h': print_help(argv[0]); break; @@ -380,7 +420,11 @@ chstr[0] = address[0]; chstr[1] = '\0'; + if (!digest) { subfilename = concatstr(3, listdir, "/subscribers.d/", chstr); + } else { + subfilename = concatstr(3, listdir, "/digesters.d/", chstr); + } subfilefd = open(subfilename, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR); if(subfilefd == -1) { @@ -398,7 +442,7 @@ if(suboff == -1) { if(subconfirm) generate_subconfirm(listdir, listaddr, address, - mlmmjsend); + mlmmjsend, digest); else { lseek(subfilefd, 0L, SEEK_END); len = strlen(address); @@ -419,7 +463,8 @@ if(childpid < 0) { log_error(LOG_ARGS, "Could not fork"); - confirm_sub(listdir, listaddr, address, mlmmjsend); + confirm_sub(listdir, listaddr, address, mlmmjsend, + digest); } if(childpid > 0) { @@ -430,14 +475,15 @@ /* child confirms subscription */ if(childpid == 0) - confirm_sub(listdir, listaddr, address, mlmmjsend); + confirm_sub(listdir, listaddr, address, mlmmjsend, + digest); } notifysub = statctrl(listdir, "notifysub"); /* Notify list owner about subscription */ if (notifysub) - notify_sub(listdir, listaddr, address, mlmmjsend); + notify_sub(listdir, listaddr, address, mlmmjsend, digest); myfree(listaddr);
--- a/src/mlmmj-unsub.c Tue Sep 14 08:47:55 2004 +1000 +++ b/src/mlmmj-unsub.c Tue Sep 14 09:01:32 2004 +1000 @@ -47,13 +47,18 @@ #include "prepstdreply.h" void confirm_unsub(const char *listdir, const char *listaddr, - const char *subaddr, const char *mlmmjsend) + const char *subaddr, const char *mlmmjsend, int digest) { int subtextfd, queuefd; char *buf, *subtextfilename, *randomstr, *queuefilename = NULL; char *fromaddr, *listname, *listfqdn, *s1; + if (!digest) { subtextfilename = concatstr(2, listdir, "/text/unsub-ok"); + } else { + subtextfilename = concatstr(2, listdir, + "/text/unsub-ok-digest"); + } if((subtextfd = open(subtextfilename, O_RDONLY)) < 0) { log_error(LOG_ARGS, "Could not open '%s'", subtextfilename); @@ -84,9 +89,15 @@ fromaddr = concatstr(3, listname, "+bounces-help@", listfqdn); - s1 = concatstr(9, "From: ", listname, "+help@", listfqdn, "\nTo: ", - subaddr, "\nSubject: Goodbye from ", listaddr, - "\n\n"); + if (!digest) { + s1 = concatstr(9, "From: ", listname, "+help@", listfqdn, + "\nTo: ", subaddr, "\nSubject: Goodbye from ", + listaddr, "\n\n"); + } else { + s1 = concatstr(9, "From: ", listname, "+help@", listfqdn, + "\nTo: ", subaddr, "\nSubject: Goodbye from " + "digest of ", listaddr, "\n\n"); + } if(writen(queuefd, s1, strlen(s1)) < 0) { log_error(LOG_ARGS, "Could not write subconffile"); @@ -126,7 +137,7 @@ } void notify_unsub(const char *listdir, const char *listaddr, - const char *subaddr, const char *mlmmjsend) + const char *subaddr, const char *mlmmjsend, int digest) { char *maildata[4] = { "*LSTADDR*", NULL, "*SUBADDR*", NULL }; char *listfqdn, *listname, *fromaddr, *fromstr, *subject; @@ -138,9 +149,17 @@ maildata[3] = mystrdup(subaddr); fromaddr = concatstr(3, listname, "+bounces-help@", listfqdn); fromstr = concatstr(3, listname, "+owner@", listfqdn); + if (!digest) { subject = concatstr(2, "Unsubscription from ", listaddr); queuefilename = prepstdreply(listdir, "notifyunsub", fromstr, fromstr, NULL, subject, 2, maildata); + } else { + subject = concatstr(2, "Unsubscription from digest of ", + listaddr); + queuefilename = prepstdreply(listdir, "notifyunsub-digest", + fromstr, fromstr, NULL, subject, 2, + maildata); + } MY_ASSERT(queuefilename) myfree(listname); myfree(listfqdn); @@ -161,7 +180,8 @@ void generate_unsubconfirm(const char *listdir, const char *listaddr, - const char *subaddr, const char *mlmmjsend) + const char *subaddr, const char *mlmmjsend, + int digest) { char *confirmaddr, *buf, *listname, *listfqdn; char *subtextfilename, *queuefilename = NULL, *fromaddr, *s1; @@ -201,13 +221,21 @@ close(subconffd); - confirmaddr = concatstr(5, listname, "+confunsub-", randomstr, "@", - listfqdn); fromaddr = concatstr(5, listname, "+bounces-confunsub-", randomstr, "@", listfqdn); - myfree(randomstr); + if (!digest) { subtextfilename = concatstr(2, listdir, "/text/unsub-confirm"); + confirmaddr = concatstr(5, listname, "+confunsub-", randomstr, + "@", listfqdn); + } else { + subtextfilename = concatstr(2, listdir, + "/text/unsub-confirm-digest"); + confirmaddr = concatstr(5, listname, "+confunsub-digest-", + randomstr, "@", listfqdn); + } + + myfree(randomstr); if((subtextfd = open(subtextfilename, O_RDONLY)) < 0) { log_error(LOG_ARGS, "Could not open '%s'", subtextfilename); @@ -233,9 +261,16 @@ exit(EXIT_FAILURE); } - s1 = concatstr(9, "From: ", listname, "+help@", listfqdn, "\nTo: ", - subaddr, "\nSubject: Confirm unsubscribe from ", - listaddr, "\n\n"); + if (!digest) { + s1 = concatstr(9, "From: ", listname, "+help@", listfqdn, + "\nTo: ", subaddr, "\nSubject: Confirm " + "unsubscribe from ", listaddr, "\n\n"); + } else { + s1 = concatstr(9, "From: ", listname, "+help@", listfqdn, + "\nTo: ", subaddr, "\nSubject: Confirm " + "unsubscribe from digest of ", listaddr, + "\n\n"); + } if(writen(queuefd, s1, strlen(s1)) < 0) { log_error(LOG_ARGS, "Could not write subconffile"); @@ -331,6 +366,7 @@ " -a: Email address to unsubscribe \n" " -c: Send goodbye mail\n" " -C: Request mail confirmation\n" + " -d: Subscribe to digest of list\n" " -h: This help\n" " -L: Full path to list directory\n" " -V: Print version\n" @@ -342,7 +378,7 @@ int main(int argc, char **argv) { int subread, subwrite, rlock, wlock, opt, unsubres, status; - int confirmunsub = 0, unsubconfirm = 0, notifysub = 0; + int confirmunsub = 0, unsubconfirm = 0, notifysub = 0, digest = 0; char *listaddr, *listdir = NULL, *address = NULL, *subreadname = NULL; char *subwritename, *mlmmjsend, *bindir; char *subddirname; @@ -359,7 +395,7 @@ mlmmjsend = concatstr(2, bindir, "/mlmmj-send"); myfree(bindir); - while ((opt = getopt(argc, argv, "hcCVL:a:")) != -1) { + while ((opt = getopt(argc, argv, "hcCdVL:a:")) != -1) { switch(opt) { case 'L': listdir = optarg; @@ -373,6 +409,9 @@ case 'C': unsubconfirm = 1; break; + case 'd': + digest = 1; + break; case 'h': print_help(argv[0]); break; @@ -397,9 +436,14 @@ listaddr = getlistaddr(listdir); if(unsubconfirm) - generate_unsubconfirm(listdir, listaddr, address, mlmmjsend); + generate_unsubconfirm(listdir, listaddr, address, mlmmjsend, + digest); + if (!digest) { subddirname = concatstr(2, listdir, "/subscribers.d/"); + } else { + subddirname = concatstr(2, listdir, "/digesters.d/"); + } if((subddir = opendir(subddirname)) == NULL) { log_error(LOG_ARGS, "Could not opendir(%s)", subddirname); @@ -412,8 +456,13 @@ continue; if(!strcmp(dp->d_name, "..")) continue; + if (!digest) { subreadname = concatstr(3, listdir, "/subscribers.d/", dp->d_name); + } else { + subreadname = concatstr(3, listdir, "/digesters.d/", + dp->d_name); + } subread = open(subreadname, O_RDWR); if(subread == -1) { @@ -509,7 +558,7 @@ if(childpid < 0) { log_error(LOG_ARGS, "Could not fork"); confirm_unsub(listdir, listaddr, address, - mlmmjsend); + mlmmjsend, digest); } if(childpid > 0) { @@ -521,7 +570,7 @@ /* child confirms subscription */ if(childpid == 0) confirm_unsub(listdir, listaddr, address, - mlmmjsend); + mlmmjsend, digest); } } @@ -530,7 +579,7 @@ /* Notify list owner about subscription */ if (notifysub) - notify_unsub(listdir, listaddr, address, mlmmjsend); + notify_unsub(listdir, listaddr, address, mlmmjsend, digest); myfree(listaddr);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/send_digest.c Tue Sep 14 09:01:32 2004 +1000 @@ -0,0 +1,199 @@ +/* Copyright (C) 2004 Morten K. Poulsen <morten at afdelingp.dk> + * + * $Id$ + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include <unistd.h> +#include <string.h> +#include <stdio.h> +#include <fcntl.h> +#include <stdlib.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/wait.h> + +#include "mlmmj.h" +#include "send_digest.h" +#include "log_error.h" +#include "strgen.h" +#include "memory.h" +#include "getlistaddr.h" +#include "wrappers.h" + + +int send_digest(const char *listdir, int firstindex, int lastindex, + const char *addr, const char *mlmmjsend) +{ + int i; + int fd, archivefd; + char buf[45]; + char *tmp, *queuename = NULL, *archivename; + char *boundary, *listaddr, *listname, *listfqdn; + pid_t childpid, pid; + int status; + + if (addr) { + errno = 0; + log_error(LOG_ARGS, "send_digest() does not support sending " + "digest mails to only one recipient yet"); + return -1; + } + + if (firstindex > lastindex) + return -1; + + do { + tmp = random_str(); + myfree(queuename); + queuename = concatstr(3, listdir, "/queue/", tmp); + myfree(tmp); + fd = open(queuename, O_RDWR|O_CREAT|O_EXCL, S_IRUSR|S_IWUSR); + } while ((fd < 0) && (errno == EEXIST)); + + if (fd < 0) { + log_error(LOG_ARGS, "Could not open digest queue file '%s'", + queuename); + myfree(queuename); + return -1; + } + + boundary = random_str(); + + listaddr = getlistaddr(listdir); + listname = genlistname(listaddr); + listfqdn = genlistfqdn(listaddr); + myfree(listaddr); + + if (lastindex == firstindex) { + snprintf(buf, sizeof(buf), " (%d)", firstindex); + } else { + snprintf(buf, sizeof(buf), " (%d-%d)", firstindex, lastindex); + } + tmp = concatstr(10, "From: ", listname, "+help@", listfqdn, + "\nMIME-Version: 1.0" + "\nContent-Type: multipart/" DIGESTMIMETYPE "; " + "boundary=", boundary, + "\nSubject: Digest of ", listname, buf, + "\n\n"); + myfree(listfqdn); + + if (writen(fd, tmp, strlen(tmp)) == -1) { + log_error(LOG_ARGS, "Could not write digest headers to '%s'", + queuename); + close(fd); + unlink(queuename); + myfree(boundary); + myfree(tmp); + myfree(queuename); + myfree(listname); + return -1; + } + myfree(tmp); + + for (i=firstindex; i<=lastindex; i++) { + snprintf(buf, sizeof(buf), "%d", i); + + archivename = concatstr(3, listdir, "/archive/", buf); + archivefd = open(archivename, O_RDONLY); + myfree(archivename); + + if (archivefd < 0) + continue; + + tmp = concatstr(7, "--", boundary, + "\nContent-Type: message/rfc822" + "\nContent-Disposition: inline; filename=\"", + listname, "_", buf, ".eml\"" + "\n\n"); + if (writen(fd, tmp, strlen(tmp)) == -1) { + log_error(LOG_ARGS, "Could not write digest part " + "headers for archive index %d to " + "'%s'", i, queuename); + close(fd); + close(archivefd); + unlink(queuename); + myfree(boundary); + myfree(tmp); + myfree(queuename); + myfree(listname); + return -1; + } + myfree(tmp); + + if (dumpfd2fd(archivefd, fd) < 0) { + log_error(LOG_ARGS, "Could not write digest part %d " + "to '%s'", i, + queuename); + close(fd); + close(archivefd); + unlink(queuename); + myfree(boundary); + myfree(queuename); + myfree(listname); + return -1; + } + + close(archivefd); + } + + tmp = concatstr(3, "--", boundary, "--\n"); + if (writen(fd, tmp, strlen(tmp)) == -1) { + log_error(LOG_ARGS, "Could not write digest end to '%s'", + queuename); + close(fd); + unlink(queuename); + myfree(boundary); + myfree(queuename); + myfree(listname); + return -1; + } + + close(fd); + myfree(boundary); + myfree(listname); + + childpid = fork(); + + if(childpid < 0) { + log_error(LOG_ARGS, "Could not fork"); + myfree(queuename); + return -1; + } + + if(childpid > 0) { + do /* Parent waits for the child */ + pid = waitpid(childpid, &status, 0); + while(pid == -1 && errno == EINTR); + } else { + execlp(mlmmjsend, mlmmjsend, + "-l", "7", + "-L", listdir, + "-m", queuename, + NULL); + log_error(LOG_ARGS, "execlp() of '%s' failed", mlmmjsend); + exit(EXIT_FAILURE); /* It is OK to exit, as this is a child */ + } + + unlink(queuename); + myfree(queuename); + + return 0; +}
--- a/src/subscriberfuncs.c Tue Sep 14 08:47:55 2004 +1000 +++ b/src/subscriberfuncs.c Tue Sep 14 09:01:32 2004 +1000 @@ -87,31 +87,26 @@ return (off_t)-1; } -int is_subbed(const char *listdir, const char *address) +static int is_subbed_in(const char *subddirname, const char *address) { int retval = 1, subread; - char *subddirname, *subreadname; + char *subreadname; off_t suboff; DIR *subddir; struct dirent *dp; - subddirname = concatstr(2, listdir, "/subscribers.d/"); if((subddir = opendir(subddirname)) == NULL) { log_error(LOG_ARGS, "Could not opendir(%s)", subddirname); - myfree(subddirname); exit(EXIT_FAILURE); } - myfree(subddirname); - while((dp = readdir(subddir)) != NULL) { if(!strcmp(dp->d_name, ".")) continue; if(!strcmp(dp->d_name, "..")) continue; - subreadname = concatstr(3, listdir, "/subscribers.d/", - dp->d_name); + subreadname = concatstr(2, subddirname, dp->d_name); subread = open(subreadname, O_RDONLY); if(subread < 0) { log_error(LOG_ARGS, "Could not open '%s'", @@ -135,3 +130,23 @@ return retval; } + +int is_subbed(const char *listdir, const char *address) +{ + int retval; + char *subddirname; + + subddirname = concatstr(2, listdir, "/subscribers.d/"); + retval = is_subbed_in(subddirname, address); + myfree(subddirname); + if (retval == 0) + return 0; + + subddirname = concatstr(2, listdir, "/digesters.d/"); + retval = is_subbed_in(subddirname, address); + myfree(subddirname); + if (retval == 0) + return 0; + + return 1; +}