# HG changeset patch # User Chris Webb # Date 1286102442 -39600 # Node ID dfc9ab125fd47ae12896f95d591e63cfe03bdf37 # Parent fd77dd58bde1bfeeb3b3b6e526a4a9067bdcd124 Fix spelling of 'receive' and 'voodoo'; make mlmmj-recieve a symlink diff -r fd77dd58bde1 -r dfc9ab125fd4 .hgignore --- a/.hgignore Mon Sep 27 10:59:35 2010 +1000 +++ b/.hgignore Sun Oct 03 21:40:42 2010 +1100 @@ -26,7 +26,7 @@ ^src/mlmmj-list$ ^src/mlmmj-maintd$ ^src/mlmmj-process$ -^src/mlmmj-recieve$ +^src/mlmmj-receive$ ^src/mlmmj-send$ ^src/mlmmj-sub$ ^src/mlmmj-unsub$ diff -r fd77dd58bde1 -r dfc9ab125fd4 ChangeLog --- a/ChangeLog Mon Sep 27 10:59:35 2010 +1000 +++ b/ChangeLog Sun Oct 03 21:40:42 2010 +1100 @@ -1,3 +1,5 @@ + o Correct spelling of 'receive' and 'voodoo' throughout the code and + documentation, making mlmmj-recieve a symlink to mlmmj-receive (Chris Webb) o Richer MIME list texts with inline messages (English only so far) o Add $random0$ through $random5$ substitutions o Add a $subject$ substitution for list texts diff -r fd77dd58bde1 -r dfc9ab125fd4 Makefile.am --- a/Makefile.am Mon Sep 27 10:59:35 2010 +1000 +++ b/Makefile.am Sun Oct 03 21:40:42 2010 +1100 @@ -10,7 +10,7 @@ dist-hook: rm -rf `find $(distdir)/ -name CVS` -man1_MANS = man/mlmmj-bounce.1 man/mlmmj-make-ml.sh.1 man/mlmmj-recieve.1 \ +man1_MANS = man/mlmmj-bounce.1 man/mlmmj-make-ml.sh.1 man/mlmmj-receive.1 \ man/mlmmj-sub.1 man/mlmmj-maintd.1 man/mlmmj-process.1 \ man/mlmmj-send.1 man/mlmmj-unsub.1 man/mlmmj-list.1 diff -r fd77dd58bde1 -r dfc9ab125fd4 README --- a/README Mon Sep 27 10:59:35 2010 +1000 +++ b/README Sun Oct 03 21:40:42 2010 +1100 @@ -30,8 +30,8 @@ $ ./configure && make && make install If you want to filter multipart/mime messages, pass the option - --enable-recieve-strip to configure, and take a look at - contrib/recievestrip/README. + --enable-receive-strip to configure, and take a look at + contrib/receivestrip/README. 1) Configure a recipient delimiter. The default is to use '+', and in Postfix it's done by adding @@ -83,7 +83,7 @@ 3) Make the changes to your mailserver aliases that came as output from mlmmj-make-ml.sh. Following the example above they will look like this: - mlmmj-test: "|/usr/bin/mlmmj-recieve -L /var/spool/mlmmj/mlmmj-test" + mlmmj-test: "|/usr/bin/mlmmj-receive -L /var/spool/mlmmj/mlmmj-test" NOTE: Don't forget newaliases. diff -r fd77dd58bde1 -r dfc9ab125fd4 README.exim4 --- a/README.exim4 Mon Sep 27 10:59:35 2010 +1000 +++ b/README.exim4 Sun Oct 03 21:40:42 2010 +1100 @@ -76,7 +76,7 @@ domains = !+mlmmj_domains : !+local_domains [...] -5. Somewhere in the transports section. (Change the path of mlmmj-recieve if you +5. Somewhere in the transports section. (Change the path of mlmmj-receive if you don't use the default location!): mlmmj_transport: @@ -86,7 +86,7 @@ group = mlmmj home_directory = MLMMJ_HOME current_directory = MLMMJ_HOME - command = /usr/local/bin/mlmmj-recieve -F -L MLMMJ_HOME/${lc:$local_part} + command = /usr/local/bin/mlmmj-receive -F -L MLMMJ_HOME/${lc:$local_part} If you want VERP to be done by your MTA, also add this: diff -r fd77dd58bde1 -r dfc9ab125fd4 README.postfix --- a/README.postfix Mon Sep 27 10:59:35 2010 +1000 +++ b/README.postfix Sun Oct 03 21:40:42 2010 +1100 @@ -99,22 +99,22 @@ Now we setup the 'mlmmj' transport. The 'mlmmj' in mlmmj:$1 above indicates a transport listed in the postfix master.cf file. We are just going to create a transport called 'mlmmj' but it is nothing - more than a pipe(8) to the mlmmj-recieve program that is invoked as + more than a pipe(8) to the mlmmj-receive program that is invoked as the 'mlmmj' user. master.cf: # mlmmj mailing lists mlmmj unix - n n - - pipe - flags=DORhu user=mlmmj argv=/usr/local/bin/mlmmj-recieve -F -L /var/spool/mlmmj/$nexthop/ + flags=DORhu user=mlmmj argv=/usr/local/bin/mlmmj-receive -F -L /var/spool/mlmmj/$nexthop/ This takes the pipe(8) postfix delivery agent and tells it to invoke - '/usr/local/bin/mlmmj-recieve' as the 'mlmmj' user and pipe the + '/usr/local/bin/mlmmj-receive' as the 'mlmmj' user and pipe the email to it on stdin. This mode of transportation is given the name 'mlmmj'. The 'flags' parameter to pipe(8) is pretty critical here. In - particular if the 'R' option is not used mlmmj-recieve fails to - recieve the mail correctly. The options mean: + particular if the 'R' option is not used mlmmj-receive fails to + receive the mail correctly. The options mean: D - Prepend a 'Delivered-To: recipient' header O - Prepend an 'X-Original-To: recipient' header diff -r fd77dd58bde1 -r dfc9ab125fd4 README.qmail --- a/README.qmail Mon Sep 27 10:59:35 2010 +1000 +++ b/README.qmail Sun Oct 03 21:40:42 2010 +1100 @@ -26,7 +26,7 @@ # cd ${LISTDIR}/control/; echo '-' > delimiter - chown and chmod the file according to the mlmmj configuration - create dot-qmail files for the list to handle direct requests and extensions: - # echo -e "|${BINDIR}/mlmmj-recieve -L ${LISTDIR}" > ${DQFILE} + # echo -e "|${BINDIR}/mlmmj-receive -L ${LISTDIR}" > ${DQFILE} - chown and chmod the files according to the qmail (and vpopmail) configuration WARNING: REMEMBER that the delimiter is -, so do not use + when composing mail @@ -53,7 +53,7 @@ # echo '-' > delimiter # chown vpopmail:vchkpw delimiter # cd /home/vpopmail/domains/programmazione.it/ -# echo -e "|/usr/local/bin/mlmmj-recieve -L /var/spool/mlmmj/ml/" > .qmail-ml +# echo -e "|/usr/local/bin/mlmmj-receive -L /var/spool/mlmmj/ml/" > .qmail-ml # cp -a .qmail-ml .qmail-ml-default # cat *-default # chown vpopmail:vchkpw .qmail-ml .qmail-ml-default diff -r fd77dd58bde1 -r dfc9ab125fd4 configure.ac --- a/configure.ac Mon Sep 27 10:59:35 2010 +1000 +++ b/configure.ac Sun Oct 03 21:40:42 2010 +1100 @@ -5,7 +5,7 @@ AC_SUBST(VERSION) AM_INIT_AUTOMAKE(mlmmj, $VERSION) -AC_CONFIG_SRCDIR([src/mlmmj-recieve.c]) +AC_CONFIG_SRCDIR([src/mlmmj-receive.c]) AM_CONFIG_HEADER([config.h]) # Checks for programs. @@ -33,10 +33,10 @@ AC_SUBST(textlibdir) -AC_ARG_ENABLE([recieve-strip], - AS_HELP_STRING([--enable-recieve-strip], - [build mlmmj-recieve-strip (default is no)])) -AM_CONDITIONAL(WANT_RECIEVESTRIP, test x"$enable_recieve_strip" = xyes) +AC_ARG_ENABLE([receive-strip], + AS_HELP_STRING([--enable-receive-strip], + [build mlmmj-receive-strip (default is no)])) +AM_CONDITIONAL(WANT_RECEIVESTRIP, test x"$enable_receive_strip" = xyes) # Checks for library functions. AC_FUNC_MALLOC @@ -48,5 +48,5 @@ AC_CONFIG_FILES([src/mlmmj-make-ml.sh]) AC_CONFIG_FILES([listtexts/Makefile]) AC_CONFIG_FILES([contrib/Makefile]) -AC_CONFIG_FILES([contrib/recievestrip/Makefile]) +AC_CONFIG_FILES([contrib/receivestrip/Makefile]) AC_OUTPUT diff -r fd77dd58bde1 -r dfc9ab125fd4 contrib/Makefile.am --- a/contrib/Makefile.am Mon Sep 27 10:59:35 2010 +1000 +++ b/contrib/Makefile.am Sun Oct 03 21:40:42 2010 +1100 @@ -1,4 +1,4 @@ ## Process this file with automake to produce Makefile.in EXTRA_DIST = web amime-receive -SUBDIRS = recievestrip +SUBDIRS = receivestrip diff -r fd77dd58bde1 -r dfc9ab125fd4 contrib/amime-receive/mlmmj-amime-receive --- a/contrib/amime-receive/mlmmj-amime-receive Mon Sep 27 10:59:35 2010 +1000 +++ b/contrib/amime-receive/mlmmj-amime-receive Sun Oct 03 21:40:42 2010 +1100 @@ -2,12 +2,12 @@ # # mlmmj-amime-receive # -# Take mail from stdin, pipe it through altermime and then to mlmmj-recieve +# Take mail from stdin, pipe it through altermime and then to mlmmj-receive # needed to add footers in a MIME-aware way # # requires altermime, see http://www.pldaniels.com/altermime/ # -# just replace mlmmj-recieve (sic) with mlmmj-amime-receive, e.g. in /etc/aliases: +# just replace mlmmj-receive with mlmmj-amime-receive, e.g. in /etc/aliases: # myml: "|/usr/bin/mlmmj-amime-receive -L /var/spool/mlmmj/myml/" # # put the footer-text for the different MIME-types into @@ -20,12 +20,12 @@ # Licensed under MIT License, see LICENSE file coming with mlmmj # -MLMMJRECIEVE=/usr/bin/mlmmj-recieve +MLMMJRECEIVE=/usr/bin/mlmmj-receive ALTERMIME=/usr/bin/altermime # check executables -if ! [ -x $MLMMJRECIEVE ]; then - echo "can't find $MLMMJRECIEVE executable, aborting" +if ! [ -x $MLMMJRECEIVE ]; then + echo "can't find $MLMMJRECEIVE executable, aborting" exit 1 fi @@ -86,4 +86,4 @@ cd $MLPATH # pipe the calls -$ALTERMIME --input=- ${PARAM} | $MLMMJRECIEVE "$@" +$ALTERMIME --input=- ${PARAM} | $MLMMJRECEIVE "$@" diff -r fd77dd58bde1 -r dfc9ab125fd4 contrib/receivestrip/Makefile.am --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/contrib/receivestrip/Makefile.am Sun Oct 03 21:40:42 2010 +1100 @@ -0,0 +1,14 @@ +# + +AUTOMAKE_OPTIONS = foreign + +AM_CFLAGS = -g -Wall -pedantic -Wsign-compare -DDEFAULTTEXTDIR='"@textlibdir@"' +INCLUDES = -I$(srcdir)/../../include + +if WANT_RECEIVESTRIP + bin_PROGRAMS = mlmmj-receive-strip +endif + +mlmmj_receive_strip_SOURCES = mlmmj-receive-strip.c ../../src/mygetline.c ../../src/memory.c ../../src/readn.c \ + ../../src/strgen.c ../../src/random-int.c ../../src/log_error.c ../../src/print-version.c \ + ../../src/writen.c ../../src/dumpfd2fd.c ../../src/ctrlvalues.c ../../src/chomp.c diff -r fd77dd58bde1 -r dfc9ab125fd4 contrib/receivestrip/README --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/contrib/receivestrip/README Sun Oct 03 21:40:42 2010 +1100 @@ -0,0 +1,37 @@ +mlmmj-receive-strip is a replacement for mlmmj-receive + +It opens the files control/mimedeny and control/mimestrip to get a list of mimetypes +for parts of multipart/mime messages that should be denied or stripped + +The parts then get stripped directly when the mail is received. + +mlmmj-receive-strip also appends an extra header + +X-ThisMailContainsUnwantedMimeParts: Y when the mail contains unwanted mime parts + + +Usage: +Compile the program in this directory with make and use "make install" to install it. +Afterwards replace mlmmj-receive with mlmmj-receive-strip in /etc/aliases for the mailinglist +you want to enable stripping and run newaliases + + +Then create the files mimedeny mimestrip in the control directory of your mailinglist. + +If control/mimestrip for example contains: + +text/html +application/octet-stream + +html texts and binarys will be stripped from the mail. + +When you also want to deny mails with certain mimeparts add the mimetypes to the mimedeny file +and add the following lines to the control/access file: + +deny ^X-ThisMailContainsUnwantedMimeParts: Y +allow + +You will most likely want to remove the X-ThisMailContainsUnwantedMimeParts +header by adding the following line to the control/delheaders file: + +X-ThisMailContainsUnwantedMimeParts: diff -r fd77dd58bde1 -r dfc9ab125fd4 contrib/receivestrip/mlmmj-receive-strip.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/contrib/receivestrip/mlmmj-receive-strip.c Sun Oct 03 21:40:42 2010 +1100 @@ -0,0 +1,523 @@ +/* Copyright (C) 2007 Sascha Sommer + * + * 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. + */ + +/* a version of mlmmj-receive that parses the mail on the fly and strips unwanted + mime parts + opens the files control/mimedeny and control/mimestrip for a list of mime + types for body parts that should be denied or stripped. + It adds an extra header X-ThisMailContainsUnwantedMimeParts: Y for mails that + contain disallowed mimeparts and X-ThisMailContainsUnwantedMimeParts: N otherwise +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + + +#include "mlmmj.h" +#include "mygetline.h" +#include "gethdrline.h" +#include "strgen.h" +#include "chomp.h" +#include "ctrlvalue.h" +#include "ctrlvalues.h" + +#include "log_error.h" +#include "wrappers.h" +#include "memory.h" + +#define UNWANTED_MIME_HDR "X-ThisMailContainsUnwantedMimeParts: N\n" + +/* append a copy of a string to a string list */ +static void append_strtolist(struct strlist *list, char* str) { + list->count++; + list->strs = myrealloc(list->strs, + sizeof(char *) * (list->count + 1)); + list->strs[list->count-1] = mystrdup(str); + list->strs[list->count] = NULL; +} + +/* free all strings in a strlist */ +static void free_strlist(struct strlist *list) { + if(!list) + return; + if(list->strs) { + int i; + for(i=0;i < list->count;i++) + myfree(list->strs[i]); + myfree(list->strs); + } + list->strs = NULL; + list->count = 0; +} + +static int findit(char *line, char **headers) +{ + int i = 0; + size_t len; + + if (!headers) + return 0; + + while(headers[i]) { + len = strlen(headers[i]); + if(strncasecmp(line, headers[i], len) == 0) + return 1; + i++; + } + + return 0; +} + +/* extract mime_type and boundary from the Content-Type header + * allocates a string for the mime_type if one is found + * always allocates a boundarie (using "--" when none is found) + * the caller needs to free the allocated strings +*/ +static void extract_boundary(struct strlist *allhdrs, char** mime_type, char** boundary) +{ + int x; + *boundary = NULL; + *mime_type = NULL; + for( x = 0 ; x < allhdrs->count ; x++ ){ + char* hdr = allhdrs->strs[x]; + if(hdr && !strncasecmp(hdr,"Content-Type:",13)){ + char* pos = hdr + 13; + size_t len = 0; + + /* find the start of the mimetype */ + while(*pos && (*pos == ' ' || *pos == '\t')) + ++pos; + + if(*pos == '"'){ /* handle quoted mime types */ + ++pos; + while(pos[len] && pos[len] != '"') + ++len; + }else{ + while(pos[len] && pos[len] != ' ' && pos[len] != '\t' && pos[len] != ';') + ++len; + } + + /* extract mime type if any */ + if(len){ + *mime_type = mymalloc(len+1); + strncpy(*mime_type,pos,len); + (*mime_type)[len] = '\0'; + } + + pos += len; + len = 0; + /* find start of the boundary info */ + while(*pos && strncasecmp(pos,"boundary=",9)) + ++pos; + if(*pos == '\0') /* no boundary */ + break; + + pos += 9; + if(*pos == '"'){ /* quoted boundary */ + ++pos; + while(pos[len] && pos[len] != '"') + ++len; + }else{ /* unquoted boundary */ + while(pos[len] && pos[len] != ' ' && pos[len] != '\t' && pos[len] != ';') + ++len; + } + + /* extract boundary */ + *boundary = mymalloc(len + 3); + strcpy(*boundary,"--"); + strncat(*boundary,pos,len); + break; + } + } +} + +/* read all mail headers and save them in a strlist + * check what to do with parts that contain the given mime_type + *return values + * 0: ok + * 1: strip + * sets deny to 1 if the entire mail should be denied + */ +#define MIME_OK 0 +#define MIME_STRIP 1 +static int read_hdrs(int fd, struct strlist *allhdrs,struct strlist* delmime,struct strlist* denymime,int* deny,char** boundary) { + int result = MIME_OK; + char* mime_type = NULL; + allhdrs->strs = NULL; + allhdrs->count = 0; + /* read headers */ + while(1) { + char* line = mygetline(fd); + if(!line) /* end of file and also end of headers */ + break; + + /* end of headers */ + if(line[0] == '\n'){ + myfree(line); + break; + } + if(!allhdrs->count || ((line[0] != '\t') && (line[0] != ' '))) /* first header line or no more unfolding */ + append_strtolist(allhdrs,line); + else{ + char* tmp = concatstr(2, allhdrs->strs[allhdrs->count-1], line); + myfree(allhdrs->strs[allhdrs->count-1]); + allhdrs->strs[allhdrs->count-1] = tmp; + } + myfree(line); + } + extract_boundary(allhdrs,&mime_type,boundary); + if(mime_type) { + /* check if this part should be stripped */ + if(delmime && findit(mime_type, delmime->strs)) + result = MIME_STRIP; + /* check if the mail should be denied */ + if(denymime && findit(mime_type, denymime->strs)) + *deny = 1; + myfree(mime_type); + } + return result; +} + +/* writes the mail headers if unwantedmime_hdrpos is not NULL an UNWANTED_MIME_HDR + * is inserted and its position saved in unwantedmime_hdrpos + * returns 0 on success + */ +static int write_hdrs(int outfd,struct strlist* hdrs,off_t* unwantedmime_hdrpos) { + int i; + for(i = 0; i < hdrs->count ; i++) { + if(writen(outfd, hdrs->strs[i], strlen(hdrs->strs[i])) < 0){ + log_error(LOG_ARGS, "Error when dumping headers"); + return -1; + } + } + + /* if this is not the header of an embedded part add the header that will + indicate if the mail contains unwanted mime parts */ + if(unwantedmime_hdrpos) { + if(writen(outfd, UNWANTED_MIME_HDR,strlen(UNWANTED_MIME_HDR)) < 0){ + log_error(LOG_ARGS, "Error writting unwanted mime header"); + return -1; + } + /* get the current position so that we can update the header later */ + *unwantedmime_hdrpos = lseek(outfd,0,SEEK_CUR); + if(*unwantedmime_hdrpos < 2){ + log_error(LOG_ARGS, "Error getting file position"); + return -1; + } + *unwantedmime_hdrpos -= 2; + } + + /* write a single line feed to terminate the header part */ + if(writen(outfd, "\n", 1) < 0) { + log_error(LOG_ARGS,"Error writting end of hdrs."); + return -1; + } + return 0; +} + +/* set the unwanted mime_hdr to Y */ +static int update_unwantedmime_hdr(int outfd,off_t unwantedmime_hdrpos) { + /* seek to the header position */ + if(lseek(outfd,unwantedmime_hdrpos,SEEK_SET) < 0) { + log_error(LOG_ARGS,"Error seeking to the unwantedmime_hdr"); + return -1; + } + + /* update the header */ + if(writen(outfd, "Y\n",2) < 0){ + log_error(LOG_ARGS, "Error writting extra header"); + return -1; + } + + /* seek back to the end of the mail */ + if(lseek(outfd,0,SEEK_END) < 0) { + log_error(LOG_ARGS,"Error seeking to the mail end"); + return -1; + } + return 0; +} + +static int parse_body(int infd,int outfd, struct strlist* delmime, struct strlist* denymime, + int* deny,char* boundary){ + int strip = 0; + char* line; + while((line = mygetline(infd))) { + if(boundary && !strncmp(line,boundary,strlen(boundary))){ + strip = 0; + /* check if the boundary is the beginning of a new part */ + if(strncmp(line + strlen(boundary),"--",2)){ + struct strlist hdrs; + char* new_boundary = NULL; + /* check if this part should be stripped */ + if(read_hdrs(infd, &hdrs,delmime,denymime,deny,&new_boundary) == MIME_STRIP) + strip = 1; + else { + /* write boundary */ + if(writen(outfd, line, strlen(line)) < 0){ + log_error(LOG_ARGS, "Error writting boundary"); + return -1; + } + /* write hdr */ + if(write_hdrs(outfd, &hdrs, NULL) < 0){ + log_error(LOG_ARGS, "Error writting hdrs"); + return -1; + } + /* parse embedded part if a new boundary was found */ + if(new_boundary && parse_body(infd,outfd,delmime,denymime,deny,new_boundary) != 0) { + log_error(LOG_ARGS, "Could not parse embedded part"); + return -1; + } + } + free_strlist(&hdrs); + if(new_boundary) + myfree(new_boundary); + }else{ + /* write end of part */ + if(writen(outfd, line, strlen(line)) < 0){ + log_error(LOG_ARGS, "Error writting hdrs"); + return -1; + } + /* and leave */ + myfree(line); + break; + } + }else { + if(!strip) { /* write the current line */ + if(writen(outfd, line, strlen(line)) < 0){ + log_error(LOG_ARGS, "Error when dumping line"); + return -1; + } + } + } + myfree(line); + } + return 0; +} + + + + + +/* read a mail stripping unwanted parts */ +static int dump_mail(int infd, int outfd,char* listdir) { + struct strlist hdrs; + struct strlist* delmime; + struct strlist* denymime; + char* boundary=NULL; + int deny = 0; + int result; + off_t unwantedmime_hdr_pos = 0; + + /* get list control values */ + delmime = ctrlvalues(listdir, "mimestrip"); + denymime = ctrlvalues(listdir, "mimedeny"); + + /* read mail header */ + result = read_hdrs(infd, &hdrs,delmime,denymime,&deny,&boundary); + /* write mail header */ + if(write_hdrs(outfd,&hdrs,&unwantedmime_hdr_pos) < 0) { + log_error(LOG_ARGS, "Could not write mail headers"); + return -1; + } + + /* free mail header */ + free_strlist(&hdrs); + + if(result == MIME_OK && !deny) { + /* try to parse the mail */ + if(parse_body(infd,outfd,delmime,denymime,&deny,boundary) != 0) { + log_error(LOG_ARGS, "Could not parse mail"); + return -1; + } + myfree(boundary); + }else + deny = 1; + + /* dump rest of mail */ + if(dumpfd2fd(infd, outfd) != 0) { + log_error(LOG_ARGS, "Could not receive mail"); + return -1; + } + + /* update header */ + if(deny) { + if(update_unwantedmime_hdr(outfd,unwantedmime_hdr_pos) != 0) { + log_error(LOG_ARGS, "Could not update header"); + return -1; + } + } + + /* free mime types */ + if(delmime) { + free_strlist(delmime); + myfree(delmime); + } + if(denymime) { + free_strlist(denymime); + myfree(denymime); + } + return 0; +} + +static void print_help(const char *prg) +{ + printf("Usage: %s -L /path/to/listdir [-h] [-V] [-P] [-F]\n" + " -h: This help\n" + " -F: Don't fork in the background\n" + " -L: Full path to list directory\n" + " -P: Don't execute mlmmj-process\n" + " -V: Print version\n", prg); + exit(EXIT_SUCCESS); +} + +int main(int argc, char **argv) +{ + char *infilename = NULL, *listdir = NULL; + char *randomstr = random_str(); + char *mlmmjprocess, *bindir; + int fd, opt, noprocess = 0, nofork = 0; + struct stat st; + uid_t uid; + pid_t childpid; + + CHECKFULLPATH(argv[0]); + + log_set_name(argv[0]); + + bindir = mydirname(argv[0]); + mlmmjprocess = concatstr(2, bindir, "/mlmmj-process"); + myfree(bindir); + + while ((opt = getopt(argc, argv, "hPVL:F")) != -1) { + switch(opt) { + case 'h': + print_help(argv[0]); + break; + case 'L': + listdir = optarg; + break; + case 'P': + noprocess = 1; + break; + case 'F': + nofork = 1; + break; + case 'V': + print_version(argv[0]); + exit(0); + } + } + + if(listdir == NULL) { + fprintf(stderr, "You have to specify -L\n"); + fprintf(stderr, "%s -h for help\n", argv[0]); + exit(EXIT_FAILURE); + } + + /* Lets make sure no random user tries to send mail to the list */ + if(listdir) { + if(stat(listdir, &st) == 0) { + uid = getuid(); + if(uid && uid != st.st_uid) { + log_error(LOG_ARGS, + "Have to invoke either as root " + "or as the user owning listdir " + "Invoked with uid = [%d]", (int)uid); + writen(STDERR_FILENO, + "Have to invoke either as root " + "or as the user owning listdir\n", 60); + exit(EXIT_FAILURE); + } + } else { + log_error(LOG_ARGS, "Could not stat %s", listdir); + exit(EXIT_FAILURE); + } + } + + infilename = concatstr(3, listdir, "/incoming/", randomstr); + myfree(randomstr); + fd = open(infilename, O_RDWR|O_CREAT|O_EXCL, S_IRUSR|S_IWUSR); + while(fd < 0 && errno == EEXIST) { + myfree(infilename); + randomstr = random_str(); + infilename = concatstr(3, listdir, "/incoming/", randomstr); + myfree(randomstr); + fd = open(infilename, O_RDWR|O_CREAT|O_EXCL, S_IRUSR|S_IWUSR); + } + + if(fd < 0) { + log_error(LOG_ARGS, "could not create mail file in " + "%s/incoming directory", listdir); + myfree(infilename); + exit(EXIT_FAILURE); + } + + if(dump_mail(fileno(stdin), fd, listdir) != 0) { + log_error(LOG_ARGS, "Could not receive mail"); + exit(EXIT_FAILURE); + } + +#if 0 + log_oper(listdir, OPLOGFNAME, "mlmmj-receive got %s", infilename); +#endif + fsync(fd); + close(fd); + + if(noprocess) { + myfree(infilename); + exit(EXIT_SUCCESS); + } + + /* + * Now we fork so we can exit with success since it could potentially + * take a long time for mlmmj-send to finish delivering the mails and + * returning, making it susceptible to getting a SIGKILL from the + * mailserver invoking mlmmj-receive. + */ + if (!nofork) { + childpid = fork(); + if(childpid < 0) + log_error(LOG_ARGS, "fork() failed! Proceeding anyway"); + + if(childpid) + exit(EXIT_SUCCESS); /* Parent says: "bye bye kids!"*/ + + close(0); + close(1); + close(2); + } + + execlp(mlmmjprocess, mlmmjprocess, + "-L", listdir, + "-m", infilename, NULL); + log_error(LOG_ARGS, "execlp() of '%s' failed", mlmmjprocess); + + exit(EXIT_FAILURE); +} + diff -r fd77dd58bde1 -r dfc9ab125fd4 contrib/recievestrip/Makefile.am --- a/contrib/recievestrip/Makefile.am Mon Sep 27 10:59:35 2010 +1000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,14 +0,0 @@ -# - -AUTOMAKE_OPTIONS = foreign - -AM_CFLAGS = -g -Wall -pedantic -Wsign-compare -DDEFAULTTEXTDIR='"@textlibdir@"' -INCLUDES = -I$(srcdir)/../../include - -if WANT_RECIEVESTRIP - bin_PROGRAMS = mlmmj-recieve-strip -endif - -mlmmj_recieve_strip_SOURCES = mlmmj-recieve-strip.c ../../src/mygetline.c ../../src/memory.c ../../src/readn.c \ - ../../src/strgen.c ../../src/random-int.c ../../src/log_error.c ../../src/print-version.c \ - ../../src/writen.c ../../src/dumpfd2fd.c ../../src/ctrlvalues.c ../../src/chomp.c diff -r fd77dd58bde1 -r dfc9ab125fd4 contrib/recievestrip/README --- a/contrib/recievestrip/README Mon Sep 27 10:59:35 2010 +1000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,37 +0,0 @@ -mlmmj-recieve-strip is a replacement for mlmmj-recieve - -It opens the files control/mimedeny and control/mimestrip to get a list of mimetypes -for parts of multipart/mime messages that should be denied or stripped - -The parts then get stripped directly when the mail is recieved. - -mlmmj-recieve-strip also appends an extra header - -X-ThisMailContainsUnwantedMimeParts: Y when the mail contains unwanted mime parts - - -Usage: -Compile the program in this directory with make and use "make install" to install it. -Afterwards replace mlmmj-receive with mlmmj-receive-strip in /etc/aliases for the mailinglist -you want to enable stripping and run newaliases - - -Then create the files mimedeny mimestrip in the control directory of your mailinglist. - -If control/mimestrip for example contains: - -text/html -application/octet-stream - -html texts and binarys will be stripped from the mail. - -When you also want to deny mails with certain mimeparts add the mimetypes to the mimedeny file -and add the following lines to the control/access file: - -deny ^X-ThisMailContainsUnwantedMimeParts: Y -allow - -You will most likely want to remove the X-ThisMailContainsUnwantedMimeParts -header by adding the following line to the control/delheaders file: - -X-ThisMailContainsUnwantedMimeParts: diff -r fd77dd58bde1 -r dfc9ab125fd4 contrib/recievestrip/mlmmj-recieve-strip.c --- a/contrib/recievestrip/mlmmj-recieve-strip.c Mon Sep 27 10:59:35 2010 +1000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,523 +0,0 @@ -/* Copyright (C) 2007 Sascha Sommer - * - * 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. - */ - -/* a version of mlmmj-recieve that parses the mail on the fly and strips unwanted - mime parts - opens the files control/mimedeny and control/mimestrip for a list of mime - types for body parts that should be denied or stripped. - It adds an extra header X-ThisMailContainsUnwantedMimeParts: Y for mails that - contain disallowed mimeparts and X-ThisMailContainsUnwantedMimeParts: N otherwise -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - - - -#include "mlmmj.h" -#include "mygetline.h" -#include "gethdrline.h" -#include "strgen.h" -#include "chomp.h" -#include "ctrlvalue.h" -#include "ctrlvalues.h" - -#include "log_error.h" -#include "wrappers.h" -#include "memory.h" - -#define UNWANTED_MIME_HDR "X-ThisMailContainsUnwantedMimeParts: N\n" - -/* append a copy of a string to a string list */ -static void append_strtolist(struct strlist *list, char* str) { - list->count++; - list->strs = myrealloc(list->strs, - sizeof(char *) * (list->count + 1)); - list->strs[list->count-1] = mystrdup(str); - list->strs[list->count] = NULL; -} - -/* free all strings in a strlist */ -static void free_strlist(struct strlist *list) { - if(!list) - return; - if(list->strs) { - int i; - for(i=0;i < list->count;i++) - myfree(list->strs[i]); - myfree(list->strs); - } - list->strs = NULL; - list->count = 0; -} - -static int findit(char *line, char **headers) -{ - int i = 0; - size_t len; - - if (!headers) - return 0; - - while(headers[i]) { - len = strlen(headers[i]); - if(strncasecmp(line, headers[i], len) == 0) - return 1; - i++; - } - - return 0; -} - -/* extract mime_type and boundary from the Content-Type header - * allocates a string for the mime_type if one is found - * always allocates a boundarie (using "--" when none is found) - * the caller needs to free the allocated strings -*/ -static void extract_boundary(struct strlist *allhdrs, char** mime_type, char** boundary) -{ - int x; - *boundary = NULL; - *mime_type = NULL; - for( x = 0 ; x < allhdrs->count ; x++ ){ - char* hdr = allhdrs->strs[x]; - if(hdr && !strncasecmp(hdr,"Content-Type:",13)){ - char* pos = hdr + 13; - size_t len = 0; - - /* find the start of the mimetype */ - while(*pos && (*pos == ' ' || *pos == '\t')) - ++pos; - - if(*pos == '"'){ /* handle quoted mime types */ - ++pos; - while(pos[len] && pos[len] != '"') - ++len; - }else{ - while(pos[len] && pos[len] != ' ' && pos[len] != '\t' && pos[len] != ';') - ++len; - } - - /* extract mime type if any */ - if(len){ - *mime_type = mymalloc(len+1); - strncpy(*mime_type,pos,len); - (*mime_type)[len] = '\0'; - } - - pos += len; - len = 0; - /* find start of the boundary info */ - while(*pos && strncasecmp(pos,"boundary=",9)) - ++pos; - if(*pos == '\0') /* no boundary */ - break; - - pos += 9; - if(*pos == '"'){ /* quoted boundary */ - ++pos; - while(pos[len] && pos[len] != '"') - ++len; - }else{ /* unquoted boundary */ - while(pos[len] && pos[len] != ' ' && pos[len] != '\t' && pos[len] != ';') - ++len; - } - - /* extract boundary */ - *boundary = mymalloc(len + 3); - strcpy(*boundary,"--"); - strncat(*boundary,pos,len); - break; - } - } -} - -/* read all mail headers and save them in a strlist - * check what to do with parts that contain the given mime_type - *return values - * 0: ok - * 1: strip - * sets deny to 1 if the entire mail should be denied - */ -#define MIME_OK 0 -#define MIME_STRIP 1 -static int read_hdrs(int fd, struct strlist *allhdrs,struct strlist* delmime,struct strlist* denymime,int* deny,char** boundary) { - int result = MIME_OK; - char* mime_type = NULL; - allhdrs->strs = NULL; - allhdrs->count = 0; - /* read headers */ - while(1) { - char* line = mygetline(fd); - if(!line) /* end of file and also end of headers */ - break; - - /* end of headers */ - if(line[0] == '\n'){ - myfree(line); - break; - } - if(!allhdrs->count || ((line[0] != '\t') && (line[0] != ' '))) /* first header line or no more unfolding */ - append_strtolist(allhdrs,line); - else{ - char* tmp = concatstr(2, allhdrs->strs[allhdrs->count-1], line); - myfree(allhdrs->strs[allhdrs->count-1]); - allhdrs->strs[allhdrs->count-1] = tmp; - } - myfree(line); - } - extract_boundary(allhdrs,&mime_type,boundary); - if(mime_type) { - /* check if this part should be stripped */ - if(delmime && findit(mime_type, delmime->strs)) - result = MIME_STRIP; - /* check if the mail should be denied */ - if(denymime && findit(mime_type, denymime->strs)) - *deny = 1; - myfree(mime_type); - } - return result; -} - -/* writes the mail headers if unwantedmime_hdrpos is not NULL an UNWANTED_MIME_HDR - * is inserted and its position saved in unwantedmime_hdrpos - * returns 0 on success - */ -static int write_hdrs(int outfd,struct strlist* hdrs,off_t* unwantedmime_hdrpos) { - int i; - for(i = 0; i < hdrs->count ; i++) { - if(writen(outfd, hdrs->strs[i], strlen(hdrs->strs[i])) < 0){ - log_error(LOG_ARGS, "Error when dumping headers"); - return -1; - } - } - - /* if this is not the header of an embedded part add the header that will - indicate if the mail contains unwanted mime parts */ - if(unwantedmime_hdrpos) { - if(writen(outfd, UNWANTED_MIME_HDR,strlen(UNWANTED_MIME_HDR)) < 0){ - log_error(LOG_ARGS, "Error writting unwanted mime header"); - return -1; - } - /* get the current position so that we can update the header later */ - *unwantedmime_hdrpos = lseek(outfd,0,SEEK_CUR); - if(*unwantedmime_hdrpos < 2){ - log_error(LOG_ARGS, "Error getting file position"); - return -1; - } - *unwantedmime_hdrpos -= 2; - } - - /* write a single line feed to terminate the header part */ - if(writen(outfd, "\n", 1) < 0) { - log_error(LOG_ARGS,"Error writting end of hdrs."); - return -1; - } - return 0; -} - -/* set the unwanted mime_hdr to Y */ -static int update_unwantedmime_hdr(int outfd,off_t unwantedmime_hdrpos) { - /* seek to the header position */ - if(lseek(outfd,unwantedmime_hdrpos,SEEK_SET) < 0) { - log_error(LOG_ARGS,"Error seeking to the unwantedmime_hdr"); - return -1; - } - - /* update the header */ - if(writen(outfd, "Y\n",2) < 0){ - log_error(LOG_ARGS, "Error writting extra header"); - return -1; - } - - /* seek back to the end of the mail */ - if(lseek(outfd,0,SEEK_END) < 0) { - log_error(LOG_ARGS,"Error seeking to the mail end"); - return -1; - } - return 0; -} - -static int parse_body(int infd,int outfd, struct strlist* delmime, struct strlist* denymime, - int* deny,char* boundary){ - int strip = 0; - char* line; - while((line = mygetline(infd))) { - if(boundary && !strncmp(line,boundary,strlen(boundary))){ - strip = 0; - /* check if the boundary is the beginning of a new part */ - if(strncmp(line + strlen(boundary),"--",2)){ - struct strlist hdrs; - char* new_boundary = NULL; - /* check if this part should be stripped */ - if(read_hdrs(infd, &hdrs,delmime,denymime,deny,&new_boundary) == MIME_STRIP) - strip = 1; - else { - /* write boundary */ - if(writen(outfd, line, strlen(line)) < 0){ - log_error(LOG_ARGS, "Error writting boundary"); - return -1; - } - /* write hdr */ - if(write_hdrs(outfd, &hdrs, NULL) < 0){ - log_error(LOG_ARGS, "Error writting hdrs"); - return -1; - } - /* parse embedded part if a new boundary was found */ - if(new_boundary && parse_body(infd,outfd,delmime,denymime,deny,new_boundary) != 0) { - log_error(LOG_ARGS, "Could not parse embedded part"); - return -1; - } - } - free_strlist(&hdrs); - if(new_boundary) - myfree(new_boundary); - }else{ - /* write end of part */ - if(writen(outfd, line, strlen(line)) < 0){ - log_error(LOG_ARGS, "Error writting hdrs"); - return -1; - } - /* and leave */ - myfree(line); - break; - } - }else { - if(!strip) { /* write the current line */ - if(writen(outfd, line, strlen(line)) < 0){ - log_error(LOG_ARGS, "Error when dumping line"); - return -1; - } - } - } - myfree(line); - } - return 0; -} - - - - - -/* read a mail stripping unwanted parts */ -static int dump_mail(int infd, int outfd,char* listdir) { - struct strlist hdrs; - struct strlist* delmime; - struct strlist* denymime; - char* boundary=NULL; - int deny = 0; - int result; - off_t unwantedmime_hdr_pos = 0; - - /* get list control values */ - delmime = ctrlvalues(listdir, "mimestrip"); - denymime = ctrlvalues(listdir, "mimedeny"); - - /* read mail header */ - result = read_hdrs(infd, &hdrs,delmime,denymime,&deny,&boundary); - /* write mail header */ - if(write_hdrs(outfd,&hdrs,&unwantedmime_hdr_pos) < 0) { - log_error(LOG_ARGS, "Could not write mail headers"); - return -1; - } - - /* free mail header */ - free_strlist(&hdrs); - - if(result == MIME_OK && !deny) { - /* try to parse the mail */ - if(parse_body(infd,outfd,delmime,denymime,&deny,boundary) != 0) { - log_error(LOG_ARGS, "Could not parse mail"); - return -1; - } - myfree(boundary); - }else - deny = 1; - - /* dump rest of mail */ - if(dumpfd2fd(infd, outfd) != 0) { - log_error(LOG_ARGS, "Could not recieve mail"); - return -1; - } - - /* update header */ - if(deny) { - if(update_unwantedmime_hdr(outfd,unwantedmime_hdr_pos) != 0) { - log_error(LOG_ARGS, "Could not update header"); - return -1; - } - } - - /* free mime types */ - if(delmime) { - free_strlist(delmime); - myfree(delmime); - } - if(denymime) { - free_strlist(denymime); - myfree(denymime); - } - return 0; -} - -static void print_help(const char *prg) -{ - printf("Usage: %s -L /path/to/listdir [-h] [-V] [-P] [-F]\n" - " -h: This help\n" - " -F: Don't fork in the background\n" - " -L: Full path to list directory\n" - " -P: Don't execute mlmmj-process\n" - " -V: Print version\n", prg); - exit(EXIT_SUCCESS); -} - -int main(int argc, char **argv) -{ - char *infilename = NULL, *listdir = NULL; - char *randomstr = random_str(); - char *mlmmjprocess, *bindir; - int fd, opt, noprocess = 0, nofork = 0; - struct stat st; - uid_t uid; - pid_t childpid; - - CHECKFULLPATH(argv[0]); - - log_set_name(argv[0]); - - bindir = mydirname(argv[0]); - mlmmjprocess = concatstr(2, bindir, "/mlmmj-process"); - myfree(bindir); - - while ((opt = getopt(argc, argv, "hPVL:F")) != -1) { - switch(opt) { - case 'h': - print_help(argv[0]); - break; - case 'L': - listdir = optarg; - break; - case 'P': - noprocess = 1; - break; - case 'F': - nofork = 1; - break; - case 'V': - print_version(argv[0]); - exit(0); - } - } - - if(listdir == NULL) { - fprintf(stderr, "You have to specify -L\n"); - fprintf(stderr, "%s -h for help\n", argv[0]); - exit(EXIT_FAILURE); - } - - /* Lets make sure no random user tries to send mail to the list */ - if(listdir) { - if(stat(listdir, &st) == 0) { - uid = getuid(); - if(uid && uid != st.st_uid) { - log_error(LOG_ARGS, - "Have to invoke either as root " - "or as the user owning listdir " - "Invoked with uid = [%d]", (int)uid); - writen(STDERR_FILENO, - "Have to invoke either as root " - "or as the user owning listdir\n", 60); - exit(EXIT_FAILURE); - } - } else { - log_error(LOG_ARGS, "Could not stat %s", listdir); - exit(EXIT_FAILURE); - } - } - - infilename = concatstr(3, listdir, "/incoming/", randomstr); - myfree(randomstr); - fd = open(infilename, O_RDWR|O_CREAT|O_EXCL, S_IRUSR|S_IWUSR); - while(fd < 0 && errno == EEXIST) { - myfree(infilename); - randomstr = random_str(); - infilename = concatstr(3, listdir, "/incoming/", randomstr); - myfree(randomstr); - fd = open(infilename, O_RDWR|O_CREAT|O_EXCL, S_IRUSR|S_IWUSR); - } - - if(fd < 0) { - log_error(LOG_ARGS, "could not create mail file in " - "%s/incoming directory", listdir); - myfree(infilename); - exit(EXIT_FAILURE); - } - - if(dump_mail(fileno(stdin), fd, listdir) != 0) { - log_error(LOG_ARGS, "Could not recieve mail"); - exit(EXIT_FAILURE); - } - -#if 0 - log_oper(listdir, OPLOGFNAME, "mlmmj-recieve got %s", infilename); -#endif - fsync(fd); - close(fd); - - if(noprocess) { - myfree(infilename); - exit(EXIT_SUCCESS); - } - - /* - * Now we fork so we can exit with success since it could potentially - * take a long time for mlmmj-send to finish delivering the mails and - * returning, making it susceptible to getting a SIGKILL from the - * mailserver invoking mlmmj-recieve. - */ - if (!nofork) { - childpid = fork(); - if(childpid < 0) - log_error(LOG_ARGS, "fork() failed! Proceeding anyway"); - - if(childpid) - exit(EXIT_SUCCESS); /* Parent says: "bye bye kids!"*/ - - close(0); - close(1); - close(2); - } - - execlp(mlmmjprocess, mlmmjprocess, - "-L", listdir, - "-m", infilename, NULL); - log_error(LOG_ARGS, "execlp() of '%s' failed", mlmmjprocess); - - exit(EXIT_FAILURE); -} - diff -r fd77dd58bde1 -r dfc9ab125fd4 include/do_all_the_voodo_here.h --- a/include/do_all_the_voodo_here.h Mon Sep 27 10:59:35 2010 +1000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,35 +0,0 @@ -/* Copyright (C) 2004 Mads Martin Joergensen - * - * $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 DO_ALL_THE_VOODO_HERE_H -#define DO_ALL_THE_VOODO_HERE_H - -#include "mlmmj.h" /* For struct mailhdr and struct strlist */ - -int findit(const char *line, const char **headers); -void getinfo(const char *line, struct mailhdr *readhdrs); -int do_all_the_voodo_here(int infd, int outfd, int hdrfd, int footfd, - const char **delhdrs, struct mailhdr *readhdrs, - struct strlist *allhdrs, const char *subjectprefix); - -#endif /* DO_ALL_THE_VOODO_HERE_H */ diff -r fd77dd58bde1 -r dfc9ab125fd4 include/do_all_the_voodoo_here.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/do_all_the_voodoo_here.h Sun Oct 03 21:40:42 2010 +1100 @@ -0,0 +1,35 @@ +/* Copyright (C) 2004 Mads Martin Joergensen + * + * $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 DO_ALL_THE_VOODOO_HERE_H +#define DO_ALL_THE_VOODOO_HERE_H + +#include "mlmmj.h" /* For struct mailhdr and struct strlist */ + +int findit(const char *line, const char **headers); +void getinfo(const char *line, struct mailhdr *readhdrs); +int do_all_the_voodoo_here(int infd, int outfd, int hdrfd, int footfd, + const char **delhdrs, struct mailhdr *readhdrs, + struct strlist *allhdrs, const char *subjectprefix); + +#endif /* DO_ALL_THE_VOODOO_HERE_H */ diff -r fd77dd58bde1 -r dfc9ab125fd4 include/mlmmj-receive.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/mlmmj-receive.h Sun Oct 03 21:40:42 2010 +1100 @@ -0,0 +1,30 @@ +/* Copyright (C) 2002, 2003 Mads Martin Joergensen + * + * $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 MMJML_RECEIVE_H +#define MMJML_RECEIVE_H + +void free_str_array(char **to_free); + + +#endif /* MMJML_RECEIVE_H */ diff -r fd77dd58bde1 -r dfc9ab125fd4 include/mlmmj-recieve.h --- a/include/mlmmj-recieve.h Mon Sep 27 10:59:35 2010 +1000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,30 +0,0 @@ -/* Copyright (C) 2002, 2003 Mads Martin Joergensen - * - * $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 MMJML_RECIEVE_H -#define MMJML_RECIEVE_H - -void free_str_array(char **to_free); - - -#endif /* MMJML_RECIEVE_H */ diff -r fd77dd58bde1 -r dfc9ab125fd4 man/mlmmj-bounce.1 --- a/man/mlmmj-bounce.1 Mon Sep 27 10:59:35 2010 +1000 +++ b/man/mlmmj-bounce.1 Sun Oct 03 21:40:42 2010 +1100 @@ -29,7 +29,7 @@ The above shows that message number 109 bounced 1094409801 seconds after epoch which is in human date stamps is Sunday September 5th 20:43:21 2004. -The last bounce mail recieved to the address is saved in /bounce/.lastmsg. +The last bounce mail received to the address is saved in /bounce/.lastmsg. When the \fB\-p\fR option is used it sends out a probe email including info that it's a bounce probe and a list of the bounced message numbers. The diff -r fd77dd58bde1 -r dfc9ab125fd4 man/mlmmj-list.1 --- a/man/mlmmj-list.1 Mon Sep 27 10:59:35 2010 +1000 +++ b/man/mlmmj-list.1 Sun Oct 03 21:40:42 2010 +1100 @@ -1,4 +1,4 @@ -.TH mlmmj-list "1" "November 2004" mlmmj-recieve +.TH mlmmj-list "1" "November 2004" mlmmj-receive .SH NAME mlmmj-list \- list people / subscribers associated with a list .SH SYNOPSIS diff -r fd77dd58bde1 -r dfc9ab125fd4 man/mlmmj-process.1 --- a/man/mlmmj-process.1 Mon Sep 27 10:59:35 2010 +1000 +++ b/man/mlmmj-process.1 Sun Oct 03 21:40:42 2010 +1100 @@ -41,7 +41,7 @@ List control In case there's a mail with a recipient delimiter it's not a regular list mail. -Processing of these happens in mlmmj-recieve as well. Examples of such are +Processing of these happens in mlmmj-receive as well. Examples of such are subscription requests, mails to owner etc. It will base it's recipient delimiter detection on the Delivered-To: header if present. If not, the To: header is used. diff -r fd77dd58bde1 -r dfc9ab125fd4 man/mlmmj-receive.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/man/mlmmj-receive.1 Sun Oct 03 21:40:42 2010 +1100 @@ -0,0 +1,41 @@ +.TH mlmmj-receive "1" "September 2004" mlmmj-receive +.SH NAME +mlmmj-receive \- receive mails for an mlmmj managed mailinglist +.SH SYNOPSIS +.B mlmmj-receive +\fI-L /path/to/listdir \fR[\fI-h\fR] [\fI-V\fR] [\fI-P\fR] [\fI-F\fR] +.HP +\fB\-h\fR: This help +.HP +\fB\-F\fR: Don't fork in the background (debugging only) +.HP +\fB\-L\fR: Full path to list directory +.HP +\fB\-P\fR: Don't execute mlmmj-process (debugging only) +.HP +\fB\-V\fR: Print version +.SH DESCRIPTION +The mlmmj-receive binary is the one specified in the mailserver configuration +file (aliases file), which writes the mail to the /incoming directory +and invokes mlmmj-process unless the \fB\-P\fR option is specified. On systems +using mailservers supporting the \fB/etc/aliases\fR file, a line to activate +an mlmmj managed mailinglist would look like this: +.LP +list: "|/usr/bin/mlmmj-receive -L /var/spool/mlmmj/list/" + +It's very important to specify the full path to the binary, or the mailinglist +will not function. + +When the \fB\-F\fR option is used, it will not fork in the background. The +reason it forks is that if delivery of a mail takes longer time than the mail +server will allow a command to be idle before presumed dead, the mail server +would kill it. + +.SH "SEE ALSO" +mlmmj-process(1) +.SH AUTHORS +This manual page was written by the following persons: +.HP +Søren Boll Overgaard (based on html2man output) +.HP +Mads Martin Jørgensen diff -r fd77dd58bde1 -r dfc9ab125fd4 man/mlmmj-recieve.1 --- a/man/mlmmj-recieve.1 Mon Sep 27 10:59:35 2010 +1000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,41 +0,0 @@ -.TH mlmmj-recieve "1" "September 2004" mlmmj-recieve -.SH NAME -mlmmj-recieve \- recieve mails for an mlmmj managed mailinglist -.SH SYNOPSIS -.B mlmmj-recieve -\fI-L /path/to/listdir \fR[\fI-h\fR] [\fI-V\fR] [\fI-P\fR] [\fI-F\fR] -.HP -\fB\-h\fR: This help -.HP -\fB\-F\fR: Don't fork in the background (debugging only) -.HP -\fB\-L\fR: Full path to list directory -.HP -\fB\-P\fR: Don't execute mlmmj-process (debugging only) -.HP -\fB\-V\fR: Print version -.SH DESCRIPTION -The mlmmj-recieve binary is the one specified in the mailserver configuration -file (aliases file), which writes the mail to the /incoming directory -and invokes mlmmj-process unless the \fB\-P\fR option is specified. On systems -using mailservers supporting the \fB/etc/aliases\fR file, a line to activate -an mlmmj managed mailinglist would look like this: -.LP -list: "|/usr/bin/mlmmj-recieve -L /var/spool/mlmmj/list/" - -It's very important to specify the full path to the binary, or the mailinglist -will not function. - -When the \fB\-F\fR option is used, it will not fork in the background. The -reason it forks is that if delivery of a mail takes longer time than the mail -server will allow a command to be idle before presumed dead, the mail server -would kill it. - -.SH "SEE ALSO" -mlmmj-process(1) -.SH AUTHORS -This manual page was written by the following persons: -.HP -Søren Boll Overgaard (based on html2man output) -.HP -Mads Martin Jørgensen diff -r fd77dd58bde1 -r dfc9ab125fd4 man/mlmmj-sub.1 --- a/man/mlmmj-sub.1 Mon Sep 27 10:59:35 2010 +1000 +++ b/man/mlmmj-sub.1 Sun Oct 03 21:40:42 2010 +1100 @@ -39,7 +39,7 @@ having correct permissions. The nomail version of the list is a list version where people are subscribed -like usual, but they won't recieve any postings to the list. This is useful for +like usual, but they won't receive any postings to the list. This is useful for people who read the mailinglist through a news gateway, but want to be able to post to the list. diff -r fd77dd58bde1 -r dfc9ab125fd4 src/Makefile.am --- a/src/Makefile.am Mon Sep 27 10:59:35 2010 +1000 +++ b/src/Makefile.am Sun Oct 03 21:40:42 2010 +1100 @@ -5,7 +5,7 @@ AM_CFLAGS = -g -Wall -pedantic -Wsign-compare -DDEFAULTTEXTDIR='"@textlibdir@"' INCLUDES = -I$(srcdir)/../include -bin_PROGRAMS = mlmmj-send mlmmj-recieve mlmmj-process mlmmj-sub \ +bin_PROGRAMS = mlmmj-send mlmmj-receive mlmmj-process mlmmj-sub \ mlmmj-unsub mlmmj-bounce mlmmj-maintd mlmmj-list bin_SCRIPTS = mlmmj-make-ml.sh @@ -19,7 +19,7 @@ statctrl.c ctrlvalue.c getaddrsfromfd.c readn.c \ getlistdelim.c -mlmmj_recieve_SOURCES = mlmmj-recieve.c writen.c random-int.c strgen.c \ +mlmmj_receive_SOURCES = mlmmj-receive.c writen.c random-int.c strgen.c \ print-version.c log_error.c dumpfd2fd.c memory.c \ log_oper.c mylocking.c readn.c @@ -27,7 +27,7 @@ incindexfile.c itoa.c getlistaddr.c chomp.c \ mylocking.c listcontrol.c random-int.c strgen.c \ print-version.c send_help.c prepstdreply.c \ - do_all_the_voodo_here.c mygetline.c gethdrline.c \ + do_all_the_voodoo_here.c mygetline.c gethdrline.c \ log_error.c statctrl.c ctrlvalue.c dumpfd2fd.c \ subscriberfuncs.c ctrlvalues.c memory.c log_oper.c \ send_list.c readn.c getlistdelim.c unistr.c @@ -59,3 +59,6 @@ mlmmj_list_SOURCES = mlmmj-list.c strgen.c writen.c print-version.c memory.c \ log_error.c random-int.c readn.c + +install-exec-hook: + ln -f -s mlmmj-receive $(DESTDIR)$(bindir)/mlmmj-recieve diff -r fd77dd58bde1 -r dfc9ab125fd4 src/do_all_the_voodo_here.c --- a/src/do_all_the_voodo_here.c Mon Sep 27 10:59:35 2010 +1000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,190 +0,0 @@ -/* Copyright (C) 2004 Mads Martin Joergensen - * - * $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 -#include -#include - -#include "mlmmj.h" -#include "mygetline.h" -#include "gethdrline.h" -#include "strgen.h" -#include "chomp.h" -#include "ctrlvalue.h" -#include "do_all_the_voodo_here.h" -#include "log_error.h" -#include "wrappers.h" -#include "memory.h" - -int findit(const char *line, const char **headers) -{ - int i = 0; - size_t len; - - while(headers[i]) { - len = strlen(headers[i]); - if(strncasecmp(line, headers[i], len) == 0) - return 1; - i++; - } - - return 0; -} - -void getinfo(const char *line, struct mailhdr *readhdrs) -{ - int i = 0; - size_t tokenlen, linelen, valuelen; - - while(readhdrs[i].token) { - tokenlen = strlen(readhdrs[i].token); - linelen = strlen(line); - if(strncasecmp(line, readhdrs[i].token, tokenlen) == 0) { - readhdrs[i].valuecount++; - valuelen = linelen - tokenlen + 1; - readhdrs[i].values = - (char **)myrealloc(readhdrs[i].values, - readhdrs[i].valuecount * sizeof(char *)); - readhdrs[i].values[readhdrs[i].valuecount - 1] = - (char *)mymalloc(valuelen + 1); - strncpy(readhdrs[i].values[readhdrs[i].valuecount - 1], - line+tokenlen, valuelen); - chomp(readhdrs[i].values[readhdrs[i].valuecount - 1]); - } - i++; - } -} - -int do_all_the_voodo_here(int infd, int outfd, int hdrfd, int footfd, - const char **delhdrs, struct mailhdr *readhdrs, - struct strlist *allhdrs, const char *prefix) -{ - char *hdrline, *subject, *unqp; - int hdrsadded = 0; - int subject_present = 0; - - allhdrs->count = 0; - allhdrs->strs = NULL; - - while((hdrline = gethdrline(infd))) { - /* Done with headers? Then add extra if wanted*/ - if((strncasecmp(hdrline, "mime", 4) == 0) || - ((strlen(hdrline) == 1) && (hdrline[0] == '\n'))){ - - /* add extra headers */ - if(!hdrsadded && hdrfd >= 0) { - if(dumpfd2fd(hdrfd, outfd) < 0) { - log_error(LOG_ARGS, "Could not " - "add extra headers"); - myfree(hdrline); - return -1; - } else - hdrsadded = 1; - } - - fsync(outfd); - - /* end of headers, write single LF */ - if(hdrline[0] == '\n') { - /* but first add Subject if none is present - * and a prefix is defined */ - if (prefix && !subject_present) - { - subject = concatstr(3, "Subject: ", - prefix, "\n"); - writen(outfd, subject, strlen(subject)); - myfree(subject); - subject_present = 1; - } - - if(writen(outfd, hdrline, strlen(hdrline)) - < 0) { - myfree(hdrline); - log_error(LOG_ARGS, - "Error writing hdrs."); - return -1; - } - myfree(hdrline); - break; - } - } - /* Do we want info from hdrs? Get it before it's gone */ - if(readhdrs) - getinfo(hdrline, readhdrs); - - /* Snatch a copy of the header */ - allhdrs->count++; - allhdrs->strs = myrealloc(allhdrs->strs, - sizeof(char *) * (allhdrs->count + 1)); - allhdrs->strs[allhdrs->count-1] = mystrdup(hdrline); - allhdrs->strs[allhdrs->count] = NULL; /* XXX why, why, why? */ - - /* Add Subject: prefix if wanted */ - if(prefix) { - if(strncasecmp(hdrline, "Subject:", 8) == 0) { - subject_present = 1; - unqp = cleanquotedp(hdrline + 8); - if(strstr(hdrline + 8, prefix) == NULL && - strstr(unqp, prefix) == NULL) { - subject = concatstr(3, - "Subject: ", prefix, - hdrline + 8); - writen(outfd, subject, - strlen(subject)); - myfree(subject); - myfree(hdrline); - myfree(unqp); - continue; - } - myfree(unqp); - } - } - - /* Should it be stripped? */ - if(delhdrs) { - if(!findit(hdrline, delhdrs)) - writen(outfd, hdrline, strlen(hdrline)); - } else - writen(outfd, hdrline, strlen(hdrline)); - - - myfree(hdrline); - } - - /* Just print the rest of the mail */ - if(dumpfd2fd(infd, outfd) < 0) { - log_error(LOG_ARGS, "Error when dumping rest of mail"); - return -1; - } - - /* No more, lets add the footer if one */ - if(footfd >= 0) - if(dumpfd2fd(footfd, outfd) < 0) { - log_error(LOG_ARGS, "Error when adding footer"); - return -1; - } - - fsync(outfd); - - return 0; -} diff -r fd77dd58bde1 -r dfc9ab125fd4 src/do_all_the_voodoo_here.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/do_all_the_voodoo_here.c Sun Oct 03 21:40:42 2010 +1100 @@ -0,0 +1,190 @@ +/* Copyright (C) 2004 Mads Martin Joergensen + * + * $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 +#include +#include + +#include "mlmmj.h" +#include "mygetline.h" +#include "gethdrline.h" +#include "strgen.h" +#include "chomp.h" +#include "ctrlvalue.h" +#include "do_all_the_voodoo_here.h" +#include "log_error.h" +#include "wrappers.h" +#include "memory.h" + +int findit(const char *line, const char **headers) +{ + int i = 0; + size_t len; + + while(headers[i]) { + len = strlen(headers[i]); + if(strncasecmp(line, headers[i], len) == 0) + return 1; + i++; + } + + return 0; +} + +void getinfo(const char *line, struct mailhdr *readhdrs) +{ + int i = 0; + size_t tokenlen, linelen, valuelen; + + while(readhdrs[i].token) { + tokenlen = strlen(readhdrs[i].token); + linelen = strlen(line); + if(strncasecmp(line, readhdrs[i].token, tokenlen) == 0) { + readhdrs[i].valuecount++; + valuelen = linelen - tokenlen + 1; + readhdrs[i].values = + (char **)myrealloc(readhdrs[i].values, + readhdrs[i].valuecount * sizeof(char *)); + readhdrs[i].values[readhdrs[i].valuecount - 1] = + (char *)mymalloc(valuelen + 1); + strncpy(readhdrs[i].values[readhdrs[i].valuecount - 1], + line+tokenlen, valuelen); + chomp(readhdrs[i].values[readhdrs[i].valuecount - 1]); + } + i++; + } +} + +int do_all_the_voodoo_here(int infd, int outfd, int hdrfd, int footfd, + const char **delhdrs, struct mailhdr *readhdrs, + struct strlist *allhdrs, const char *prefix) +{ + char *hdrline, *subject, *unqp; + int hdrsadded = 0; + int subject_present = 0; + + allhdrs->count = 0; + allhdrs->strs = NULL; + + while((hdrline = gethdrline(infd))) { + /* Done with headers? Then add extra if wanted*/ + if((strncasecmp(hdrline, "mime", 4) == 0) || + ((strlen(hdrline) == 1) && (hdrline[0] == '\n'))){ + + /* add extra headers */ + if(!hdrsadded && hdrfd >= 0) { + if(dumpfd2fd(hdrfd, outfd) < 0) { + log_error(LOG_ARGS, "Could not " + "add extra headers"); + myfree(hdrline); + return -1; + } else + hdrsadded = 1; + } + + fsync(outfd); + + /* end of headers, write single LF */ + if(hdrline[0] == '\n') { + /* but first add Subject if none is present + * and a prefix is defined */ + if (prefix && !subject_present) + { + subject = concatstr(3, "Subject: ", + prefix, "\n"); + writen(outfd, subject, strlen(subject)); + myfree(subject); + subject_present = 1; + } + + if(writen(outfd, hdrline, strlen(hdrline)) + < 0) { + myfree(hdrline); + log_error(LOG_ARGS, + "Error writing hdrs."); + return -1; + } + myfree(hdrline); + break; + } + } + /* Do we want info from hdrs? Get it before it's gone */ + if(readhdrs) + getinfo(hdrline, readhdrs); + + /* Snatch a copy of the header */ + allhdrs->count++; + allhdrs->strs = myrealloc(allhdrs->strs, + sizeof(char *) * (allhdrs->count + 1)); + allhdrs->strs[allhdrs->count-1] = mystrdup(hdrline); + allhdrs->strs[allhdrs->count] = NULL; /* XXX why, why, why? */ + + /* Add Subject: prefix if wanted */ + if(prefix) { + if(strncasecmp(hdrline, "Subject:", 8) == 0) { + subject_present = 1; + unqp = cleanquotedp(hdrline + 8); + if(strstr(hdrline + 8, prefix) == NULL && + strstr(unqp, prefix) == NULL) { + subject = concatstr(3, + "Subject: ", prefix, + hdrline + 8); + writen(outfd, subject, + strlen(subject)); + myfree(subject); + myfree(hdrline); + myfree(unqp); + continue; + } + myfree(unqp); + } + } + + /* Should it be stripped? */ + if(delhdrs) { + if(!findit(hdrline, delhdrs)) + writen(outfd, hdrline, strlen(hdrline)); + } else + writen(outfd, hdrline, strlen(hdrline)); + + + myfree(hdrline); + } + + /* Just print the rest of the mail */ + if(dumpfd2fd(infd, outfd) < 0) { + log_error(LOG_ARGS, "Error when dumping rest of mail"); + return -1; + } + + /* No more, lets add the footer if one */ + if(footfd >= 0) + if(dumpfd2fd(footfd, outfd) < 0) { + log_error(LOG_ARGS, "Error when adding footer"); + return -1; + } + + fsync(outfd); + + return 0; +} diff -r fd77dd58bde1 -r dfc9ab125fd4 src/mlmmj-make-ml.sh.in --- a/src/mlmmj-make-ml.sh.in Mon Sep 27 10:59:35 2010 +1000 +++ b/src/mlmmj-make-ml.sh.in Sun Oct 03 21:40:42 2010 +1100 @@ -120,9 +120,9 @@ LISTADDRESS="$LISTNAME@$FQDN" echo "$LISTADDRESS" > "$LISTDIR"/control/"listaddress" -MLMMJRECIEVE=`which mlmmj-recieve 2>/dev/null` -if [ -z "$MLMMJRECIEVE" ]; then - MLMMJRECIEVE="/path/to/mlmmj-recieve" +MLMMJRECEIVE=`which mlmmj-receive 2>/dev/null` +if [ -z "$MLMMJRECEIVE" ]; then + MLMMJRECEIVE="/path/to/mlmmj-receive" fi MLMMJMAINTD=`which mlmmj-maintd 2>/dev/null` @@ -130,7 +130,7 @@ MLMMJMAINTD="/path/to/mlmmj-maintd" fi -ALIAS="$LISTNAME: \"|$MLMMJRECIEVE -L $SPOOLDIR/$LISTNAME/\"" +ALIAS="$LISTNAME: \"|$MLMMJRECEIVE -L $SPOOLDIR/$LISTNAME/\"" CRONENTRY="0 */2 * * * \"$MLMMJMAINTD -F -L $SPOOLDIR/$LISTNAME/\"" if [ -n "$A_CREATE" ]; then diff -r fd77dd58bde1 -r dfc9ab125fd4 src/mlmmj-process.c --- a/src/mlmmj-process.c Mon Sep 27 10:59:35 2010 +1000 +++ b/src/mlmmj-process.c Sun Oct 03 21:40:42 2010 +1100 @@ -40,7 +40,7 @@ #include "getlistdelim.h" #include "listcontrol.h" #include "strgen.h" -#include "do_all_the_voodo_here.h" +#include "do_all_the_voodoo_here.h" #include "log_error.h" #include "mygetline.h" #include "statctrl.h" @@ -501,13 +501,13 @@ exit(EXIT_FAILURE); } - /* hdrfd is checked in do_all_the_voodo_here(), because the + /* hdrfd is checked in do_all_the_voodoo_here(), because the * customheaders file might not exist */ headerfilename = concatstr(2, listdir, "/control/customheaders"); hdrfd = open(headerfilename, O_RDONLY); myfree(headerfilename); - /* footfd is checked in do_all_the_voodo_here(), see above */ + /* footfd is checked in do_all_the_voodoo_here(), see above */ footerfilename = concatstr(2, listdir, "/control/footer"); footfd = open(footerfilename, O_RDONLY); myfree(footerfilename); @@ -527,10 +527,10 @@ subjectprefix = ctrlvalue(listdir, "prefix"); - if(do_all_the_voodo_here(rawmailfd, donemailfd, hdrfd, footfd, + if(do_all_the_voodoo_here(rawmailfd, donemailfd, hdrfd, footfd, (const char**)delheaders->strs, readhdrs, &allheaders, subjectprefix) < 0) { - log_error(LOG_ARGS, "Error in do_all_the_voodo_here"); + log_error(LOG_ARGS, "Error in do_all_the_voodoo_here"); exit(EXIT_FAILURE); } @@ -646,10 +646,10 @@ "output mail file"); exit(EXIT_FAILURE); } - if(do_all_the_voodo_here(rawmailfd, donemailfd, -1, + if(do_all_the_voodoo_here(rawmailfd, donemailfd, -1, -1, (const char**)delheaders->strs, NULL, &allheaders, NULL) < 0) { - log_error(LOG_ARGS, "do_all_the_voodo_here"); + log_error(LOG_ARGS, "do_all_the_voodoo_here"); exit(EXIT_FAILURE); } close(rawmailfd); diff -r fd77dd58bde1 -r dfc9ab125fd4 src/mlmmj-receive.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mlmmj-receive.c Sun Oct 03 21:40:42 2010 +1100 @@ -0,0 +1,185 @@ +/* Copyright (C) 2002, 2003 Mads Martin Joergensen + * + * $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 +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mlmmj.h" +#include "wrappers.h" +#include "mygetline.h" +#include "strgen.h" +#include "log_error.h" +#include "memory.h" + +extern char *optarg; + +static void print_help(const char *prg) +{ + printf("Usage: %s -L /path/to/listdir [-s sender@example.org] [-e extension] [-h] [-V] [-P] [-F]\n" + " -h: This help\n" + " -F: Don't fork in the background\n" + " -L: Full path to list directory\n" + " -s: Specify sender address\n" + " -e: The foo part of user+foo@example.org\n" + " -P: Don't execute mlmmj-process\n" + " -V: Print version\n", prg); + exit(EXIT_SUCCESS); +} + +int main(int argc, char **argv) +{ + char *infilename = NULL, *listdir = NULL; + char *randomstr = random_str(); + char *mlmmjprocess, *bindir; + int fd, opt, noprocess = 0, nofork = 0; + struct stat st; + uid_t uid; + pid_t childpid; + + CHECKFULLPATH(argv[0]); + + log_set_name(argv[0]); + + bindir = mydirname(argv[0]); + mlmmjprocess = concatstr(2, bindir, "/mlmmj-process"); + myfree(bindir); + + while ((opt = getopt(argc, argv, "hPVL:s:e:F")) != -1) { + switch(opt) { + case 'h': + print_help(argv[0]); + break; + case 'L': + listdir = optarg; + break; + case 's': + setenv("SENDER", optarg, 1); + break; + case 'e': + setenv("EXTENSION", optarg, 1); + break; + case 'P': + noprocess = 1; + break; + case 'F': + nofork = 1; + break; + case 'V': + print_version(argv[0]); + exit(0); + } + } + + if(listdir == NULL) { + fprintf(stderr, "You have to specify -L\n"); + fprintf(stderr, "%s -h for help\n", argv[0]); + exit(EXIT_FAILURE); + } + + /* Lets make sure no random user tries to send mail to the list */ + if(listdir) { + if(stat(listdir, &st) == 0) { + uid = getuid(); + if(uid && uid != st.st_uid) { + log_error(LOG_ARGS, + "Have to invoke either as root " + "or as the user owning listdir " + "Invoked with uid = [%d]", (int)uid); + writen(STDERR_FILENO, + "Have to invoke either as root " + "or as the user owning listdir\n", 60); + exit(EXIT_FAILURE); + } + } else { + log_error(LOG_ARGS, "Could not stat %s", listdir); + exit(EXIT_FAILURE); + } + } + + infilename = concatstr(3, listdir, "/incoming/", randomstr); + myfree(randomstr); + fd = open(infilename, O_RDWR|O_CREAT|O_EXCL, S_IRUSR|S_IWUSR); + while(fd < 0 && errno == EEXIST) { + myfree(infilename); + randomstr = random_str(); + infilename = concatstr(3, listdir, "/incoming/", randomstr); + myfree(randomstr); + fd = open(infilename, O_RDWR|O_CREAT|O_EXCL, S_IRUSR|S_IWUSR); + } + + if(fd < 0) { + log_error(LOG_ARGS, "could not create mail file in " + "%s/incoming directory", listdir); + myfree(infilename); + exit(EXIT_FAILURE); + } + + if(dumpfd2fd(fileno(stdin), fd) != 0) { + log_error(LOG_ARGS, "Could not receive mail"); + exit(EXIT_FAILURE); + } + +#if 0 + log_oper(listdir, OPLOGFNAME, "mlmmj-receive got %s", infilename); +#endif + fsync(fd); + close(fd); + + if(noprocess) { + myfree(infilename); + exit(EXIT_SUCCESS); + } + + /* + * Now we fork so we can exit with success since it could potentially + * take a long time for mlmmj-send to finish delivering the mails and + * returning, making it susceptible to getting a SIGKILL from the + * mailserver invoking mlmmj-receive. + */ + if (!nofork) { + childpid = fork(); + if(childpid < 0) + log_error(LOG_ARGS, "fork() failed! Proceeding anyway"); + + if(childpid) + exit(EXIT_SUCCESS); /* Parent says: "bye bye kids!"*/ + + close(0); + close(1); + close(2); + } + + execlp(mlmmjprocess, mlmmjprocess, + "-L", listdir, + "-m", infilename, (char *)NULL); + log_error(LOG_ARGS, "execlp() of '%s' failed", mlmmjprocess); + + exit(EXIT_FAILURE); +} diff -r fd77dd58bde1 -r dfc9ab125fd4 src/mlmmj-recieve.c --- a/src/mlmmj-recieve.c Mon Sep 27 10:59:35 2010 +1000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,185 +0,0 @@ -/* Copyright (C) 2002, 2003 Mads Martin Joergensen - * - * $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 -#include -#include -#include -#include -#include -#include -#include -#include - -#include "mlmmj.h" -#include "wrappers.h" -#include "mygetline.h" -#include "strgen.h" -#include "log_error.h" -#include "memory.h" - -extern char *optarg; - -static void print_help(const char *prg) -{ - printf("Usage: %s -L /path/to/listdir [-s sender@example.org] [-e extension] [-h] [-V] [-P] [-F]\n" - " -h: This help\n" - " -F: Don't fork in the background\n" - " -L: Full path to list directory\n" - " -s: Specify sender address\n" - " -e: The foo part of user+foo@example.org\n" - " -P: Don't execute mlmmj-process\n" - " -V: Print version\n", prg); - exit(EXIT_SUCCESS); -} - -int main(int argc, char **argv) -{ - char *infilename = NULL, *listdir = NULL; - char *randomstr = random_str(); - char *mlmmjprocess, *bindir; - int fd, opt, noprocess = 0, nofork = 0; - struct stat st; - uid_t uid; - pid_t childpid; - - CHECKFULLPATH(argv[0]); - - log_set_name(argv[0]); - - bindir = mydirname(argv[0]); - mlmmjprocess = concatstr(2, bindir, "/mlmmj-process"); - myfree(bindir); - - while ((opt = getopt(argc, argv, "hPVL:s:e:F")) != -1) { - switch(opt) { - case 'h': - print_help(argv[0]); - break; - case 'L': - listdir = optarg; - break; - case 's': - setenv("SENDER", optarg, 1); - break; - case 'e': - setenv("EXTENSION", optarg, 1); - break; - case 'P': - noprocess = 1; - break; - case 'F': - nofork = 1; - break; - case 'V': - print_version(argv[0]); - exit(0); - } - } - - if(listdir == NULL) { - fprintf(stderr, "You have to specify -L\n"); - fprintf(stderr, "%s -h for help\n", argv[0]); - exit(EXIT_FAILURE); - } - - /* Lets make sure no random user tries to send mail to the list */ - if(listdir) { - if(stat(listdir, &st) == 0) { - uid = getuid(); - if(uid && uid != st.st_uid) { - log_error(LOG_ARGS, - "Have to invoke either as root " - "or as the user owning listdir " - "Invoked with uid = [%d]", (int)uid); - writen(STDERR_FILENO, - "Have to invoke either as root " - "or as the user owning listdir\n", 60); - exit(EXIT_FAILURE); - } - } else { - log_error(LOG_ARGS, "Could not stat %s", listdir); - exit(EXIT_FAILURE); - } - } - - infilename = concatstr(3, listdir, "/incoming/", randomstr); - myfree(randomstr); - fd = open(infilename, O_RDWR|O_CREAT|O_EXCL, S_IRUSR|S_IWUSR); - while(fd < 0 && errno == EEXIST) { - myfree(infilename); - randomstr = random_str(); - infilename = concatstr(3, listdir, "/incoming/", randomstr); - myfree(randomstr); - fd = open(infilename, O_RDWR|O_CREAT|O_EXCL, S_IRUSR|S_IWUSR); - } - - if(fd < 0) { - log_error(LOG_ARGS, "could not create mail file in " - "%s/incoming directory", listdir); - myfree(infilename); - exit(EXIT_FAILURE); - } - - if(dumpfd2fd(fileno(stdin), fd) != 0) { - log_error(LOG_ARGS, "Could not recieve mail"); - exit(EXIT_FAILURE); - } - -#if 0 - log_oper(listdir, OPLOGFNAME, "mlmmj-recieve got %s", infilename); -#endif - fsync(fd); - close(fd); - - if(noprocess) { - myfree(infilename); - exit(EXIT_SUCCESS); - } - - /* - * Now we fork so we can exit with success since it could potentially - * take a long time for mlmmj-send to finish delivering the mails and - * returning, making it susceptible to getting a SIGKILL from the - * mailserver invoking mlmmj-recieve. - */ - if (!nofork) { - childpid = fork(); - if(childpid < 0) - log_error(LOG_ARGS, "fork() failed! Proceeding anyway"); - - if(childpid) - exit(EXIT_SUCCESS); /* Parent says: "bye bye kids!"*/ - - close(0); - close(1); - close(2); - } - - execlp(mlmmjprocess, mlmmjprocess, - "-L", listdir, - "-m", infilename, (char *)NULL); - log_error(LOG_ARGS, "execlp() of '%s' failed", mlmmjprocess); - - exit(EXIT_FAILURE); -} diff -r fd77dd58bde1 -r dfc9ab125fd4 src/mlmmj-send.c --- a/src/mlmmj-send.c Mon Sep 27 10:59:35 2010 +1000 +++ b/src/mlmmj-send.c Sun Oct 03 21:40:42 2010 +1100 @@ -446,7 +446,7 @@ } for(i = 0; i < addrs->count; i++) { if(gotsigterm) { - log_error(LOG_ARGS, "TERM signal recieved, " + log_error(LOG_ARGS, "TERM signal received, " "shutting down."); return -1; } @@ -640,7 +640,7 @@ } if(gotsigterm && listaddr && archivefilename) { /* we got SIGTERM, so save the addresses and bail */ - log_error(LOG_ARGS, "TERM signal recieved, " + log_error(LOG_ARGS, "TERM signal received, " "shutting down."); index = get_index_from_filename(archivefilename); status = requeuemail(listdir, index, addrs, i);