My problem is that qmail is not delivering to the list(s) I have setup under mailman: - log snip @400000004394271706f44024 new msg 3368883 @400000004394271706f45794 info msg 3368883: bytes 954 from <meaje@xxxxxxxxxxx> qp 16690 uid 89 @4000000043942717074a62ec starting delivery 8: msg 3368883 to local mailman-cvsupdates@xxxxxxxxxxxxxxxxx @4000000043942717074a822c status: local 1/10 remote 0/20 @40000000439427170797988c delivery 8: failure: Sorry,_no_mailbox_here_by_that_name._(#5.1.1)/ @40000000439427170797b3e4 status: local 0/10 remote 0/20 @40000000439427170806dcec bounce msg 3368883 qp 16693 @40000000439427170806f45c end msg 3368883 @4000000043942717080aad7c new msg 3368891 @4000000043942717080bf1b4 info msg 3368891: bytes 1501 from <> qp 16693 uid 508 @4000000043942717085994b4 starting delivery 9: msg 3368891 to local meanspc.com-meaje@xxxxxxxxxxx @4000000043942717085a7f14 status: local 1/10 remote 0/20 @400000004394271721022454 delivery 9: success: did_0+0+1/ @400000004394271721023fac status: local 0/10 remote 0/20 @40000000439427172102477c end msg 3368891 @400000004394275c3b50de2c new msg 3368883 @400000004394275c3b50f984 info msg 3368883: bytes 954 from <meaje@xxxxxxxxxxx> qp 16792 uid 89 @400000004394275d000e32c4 starting delivery 10: msg 3368883 to local mailman-cvsupdates@xxxxxxxxxxxxxxxxx @400000004394275d000e4e1c status: local 1/10 remote 0/20 @400000004394275d005fe0ec delivery 10: failure: Sorry,_no_mailbox_here_by_that_name._(#5.1.1)/ @400000004394275d005ffc44 status: local 0/10 remote 0/20 @400000004394275d00d737b4 bounce msg 3368883 qp 16795 @400000004394275d00d7530c end msg 3368883 @400000004394275d00db2784 new msg 3368891 @400000004394275d00dc6fa4 info msg 3368891: bytes 1501 from <> qp 16795 uid 508 @400000004394275d014dd6e4 starting delivery 11: msg 3368891 to local meanspc.com-meaje@xxxxxxxxxxx @400000004394275d014f22ec status: local 1/10 remote 0/20 @400000004394275d19e518d4 delivery 11: success: did_0+0+1/ @400000004394275d19e53044 status: local 0/10 remote 0/20 @400000004394275d19e693bc end msg 3368891 I have applied the following patches to my qmail distribution: (attached if necessary) qmail-103.patch qmail-date-localtime.patch.txt qmail-limit-bounce-size.patch.txt qmail-maildir++.patch qmailqueue-patch qmail-smtpd-esmtp-size_qregex-compat.diff.txt qregex.patch-20020129.txt I have also made the following changes to my virtualdomains and rcpthosts files: - virtualdomains lists.meanspc.com:mailman meanspc.com:meanspc.com picotech.net:picotech.net - rcpthosts localhost bast.meanspc.com lists.meanspc.com meanspc.com I am assuming that qmail is trying to deliver to the local mailman account mailman which is listed as such in my passwd file with the permissions on it's home directory as such: - cat /etc/passwd |grep mailman mailman:x:41:41:GNU Mailing List Manager:/usr/lib/mailman:/sbin/nologin - ls -la /usr/lib/mailman total 52 drwxrwsr-x 13 root mailman 432 Dec 5 04:39 . drwxr-xr-x 80 root root 35344 Dec 6 04:10 .. drwxrwsr-x 2 root mailman 1264 Dec 5 02:47 bin drwxrwsr-x 2 root mailman 320 Dec 5 04:09 cgi-bin drwxrwsr-x 2 root mailman 344 Dec 4 05:44 cron drwxrwsr-x 2 root mailman 232 Dec 4 05:44 icons drwxrwsr-x 2 root mailman 72 Dec 5 04:09 mail drwxrwsr-x 11 root mailman 2168 Dec 5 03:27 Mailman -rw-r--r-- 1 mailman mailman 54 Dec 5 04:33 .mailman-default drwxrwsr-x 29 root mailman 696 Dec 4 05:44 messages drwxrwsr-x 6 root mailman 176 Dec 4 05:44 pythonlib -rw-r--r-- 1 mailman mailman 54 Dec 5 04:33 .qmail-default -rw-rw-rw- 1 mailman mailman 4050 Dec 5 04:39 qmail-to-mailman.py drwxrwsr-x 2 root mailman 408 Dec 4 05:44 scripts drwxrwsr-x 31 root mailman 744 Dec 4 05:44 templates drwxrwsr-x 4 root mailman 1104 Dec 4 05:44 tests So by this point I am horribly confused as to why qmail is refusing to deliver to a local address, unless I have somehow setup mailman wrong... Any help would be greatly appreciated :) -- Jeffrey D. Means meaje@xxxxxxxxxxx Owner / CIO for MeansPC http://www.meanspc.com/ Custom Web Development For Your Needs. (970)308-1298 - Everything in moderation including moderation. - Unknown My Public PGP Key ID is: 0x81F00126 and available via: http://pgp.mit.edu:11371/pks/lookup?op=get&search=0x81F00126
--- qmail-1.03/dns.c.103 Mon Aug 17 16:06:58 1998
+++ qmail-1.03/dns.c Wed Aug 26 16:28:56 1998
@@ -21,10 +21,12 @@
static unsigned short getshort(c) unsigned char *c;
{ unsigned short u; u = c[0]; return (u << 8) + c[1]; }
-static union { HEADER hdr; unsigned char buf[PACKETSZ]; } response;
+static struct { unsigned char *buf; } response;
+static int responsebuflen = 0;
static int responselen;
static unsigned char *responseend;
static unsigned char *responsepos;
+static u_long saveresoptions;
static int numanswers;
static char name[MAXDNAME];
@@ -45,18 +47,33 @@
errno = 0;
if (!stralloc_copy(&glue,domain)) return DNS_MEM;
if (!stralloc_0(&glue)) return DNS_MEM;
- responselen = lookup(glue.s,C_IN,type,response.buf,sizeof(response));
+ if (!responsebuflen)
+ if (response.buf = (unsigned char *)alloc(PACKETSZ+1))
+ responsebuflen = PACKETSZ+1;
+ else return DNS_MEM;
+
+ responselen = lookup(glue.s,C_IN,type,response.buf,responsebuflen);
+ if ((responselen >= responsebuflen) ||
+ (responselen > 0 && (((HEADER *)response.buf)->tc)))
+ {
+ if (responsebuflen < 65536)
+ if (alloc_re(&response.buf, responsebuflen, 65536))
+ responsebuflen = 65536;
+ else return DNS_MEM;
+ saveresoptions = _res.options;
+ _res.options |= RES_USEVC;
+ responselen = lookup(glue.s,C_IN,type,response.buf,responsebuflen);
+ _res.options = saveresoptions;
+ }
if (responselen <= 0)
{
if (errno == ECONNREFUSED) return DNS_SOFT;
if (h_errno == TRY_AGAIN) return DNS_SOFT;
return DNS_HARD;
}
- if (responselen >= sizeof(response))
- responselen = sizeof(response);
responseend = response.buf + responselen;
responsepos = response.buf + sizeof(HEADER);
- n = ntohs(response.hdr.qdcount);
+ n = ntohs(((HEADER *)response.buf)->qdcount);
while (n-- > 0)
{
i = dn_expand(response.buf,responseend,responsepos,name,MAXDNAME);
@@ -66,7 +83,7 @@
if (i < QFIXEDSZ) return DNS_SOFT;
responsepos += QFIXEDSZ;
}
- numanswers = ntohs(response.hdr.ancount);
+ numanswers = ntohs(((HEADER *)response.buf)->ancount);
return 0;
}
This patch causes the various qmail programs to generate date stamps in
the local timezone. I find GMT too annoying to convert from/to. I make
no warranties that it will work in your timezone, however it works for me.
Works with qmail 1.01 to 1.03.
To apply this patch, cd into the qmail source directory and type...
patch -s -p1 < patch-to-patch-file
--- qmail-1.03.orig/date822fmt.c Tue Apr 15 15:05:23 1997
+++ qmail-1.03/date822fmt.c Fri Apr 18 00:39:41 1997
@@ -1,3 +1,4 @@
+#include <time.h>
#include "datetime.h"
#include "fmt.h"
#include "date822fmt.h"
@@ -12,18 +13,51 @@
{
unsigned int i;
unsigned int len;
+ time_t now;
+ datetime_sec utc;
+ datetime_sec local;
+ struct tm *tm;
+ struct datetime new_dt;
+ int minutes;
+
+ utc = datetime_untai(dt);
+ now = (time_t)utc;
+ tm = localtime(&now);
+ new_dt.year = tm->tm_year;
+ new_dt.mon = tm->tm_mon;
+ new_dt.mday = tm->tm_mday;
+ new_dt.hour = tm->tm_hour;
+ new_dt.min = tm->tm_min;
+ new_dt.sec = tm->tm_sec;
+ local = datetime_untai(&new_dt);
+
len = 0;
- i = fmt_uint(s,dt->mday); len += i; if (s) s += i;
+ i = fmt_uint(s,new_dt.mday); len += i; if (s) s += i;
i = fmt_str(s," "); len += i; if (s) s += i;
- i = fmt_str(s,montab[dt->mon]); len += i; if (s) s += i;
+ i = fmt_str(s,montab[new_dt.mon]); len += i; if (s) s += i;
i = fmt_str(s," "); len += i; if (s) s += i;
- i = fmt_uint(s,dt->year + 1900); len += i; if (s) s += i;
+ i = fmt_uint(s,new_dt.year + 1900); len += i; if (s) s += i;
i = fmt_str(s," "); len += i; if (s) s += i;
- i = fmt_uint0(s,dt->hour,2); len += i; if (s) s += i;
+ i = fmt_uint0(s,new_dt.hour,2); len += i; if (s) s += i;
i = fmt_str(s,":"); len += i; if (s) s += i;
- i = fmt_uint0(s,dt->min,2); len += i; if (s) s += i;
+ i = fmt_uint0(s,new_dt.min,2); len += i; if (s) s += i;
i = fmt_str(s,":"); len += i; if (s) s += i;
- i = fmt_uint0(s,dt->sec,2); len += i; if (s) s += i;
- i = fmt_str(s," -0000\n"); len += i; if (s) s += i;
+ i = fmt_uint0(s,new_dt.sec,2); len += i; if (s) s += i;
+
+ if (local < utc) {
+ minutes = (utc - local + 30) / 60;
+ i = fmt_str(s," -"); len += i; if (s) s += i;
+ i = fmt_uint0(s,minutes / 60,2); len += i; if (s) s += i;
+ i = fmt_uint0(s,minutes % 60,2); len += i; if (s) s += i;
+ }
+ else {
+ minutes = (local - utc + 30) / 60;
+ i = fmt_str(s," +"); len += i; if (s) s += i;
+ i = fmt_uint0(s,minutes / 60,2); len += i; if (s) s += i;
+ i = fmt_uint0(s,minutes % 60,2); len += i; if (s) s += i;
+ }
+
+ i = fmt_str(s,"\n"); len += i; if (s) s += i;
+
return len;
}
Here is a little patch by Frank DENIS aka Jedi/Sector One <j@xxxxxx> to
limit the size of bounces.
The default limit for bounces is 50000 bytes, but you can create a file in
/var/qmail/crontrol/bouncemaxbytes (or wherever your control directory is)
in order to change that number.
diff -u ../qmail-1.03/qmail-send.c ./qmail-send.c
--- ../qmail-1.03/qmail-send.c Mon Jun 15 12:53:16 1998
+++ ./qmail-send.c Wed Jun 24 20:06:29 1998
@@ -44,6 +44,8 @@
int lifetime = 604800;
+int bouncemaxbytes = 50000;
+
stralloc percenthack = {0};
struct constmap mappercenthack;
stralloc locals = {0};
@@ -740,9 +742,17 @@
qmail_fail(&qqt);
else
{
+ int bytestogo = bouncemaxbytes;
+ int bytestoget = (bytestogo < sizeof buf) ? bytestogo : sizeof buf;
substdio_fdbuf(&ssread,read,fd,inbuf,sizeof(inbuf));
- while ((r = substdio_get(&ssread,buf,sizeof(buf))) > 0)
+ while (bytestoget > 0 && (r = substdio_get(&ssread,buf,bytestoget)) > 0) {
qmail_put(&qqt,buf,r);
+ bytestogo -= bytestoget;
+ bytestoget = (bytestogo < sizeof buf) ? bytestogo : sizeof buf;
+ }
+ if (r > 0) {
+ qmail_puts(&qqt,"\n\n--- End of message stripped.\n");
+ }
close(fd);
if (r == -1)
qmail_fail(&qqt);
@@ -1442,6 +1452,7 @@
/* this file is too long ---------------------------------------------- MAIN */
int getcontrols() { if (control_init() == -1) return 0;
+ if (control_readint(&bouncemaxbytes,"control/bouncemaxbytes") == -1) return 0;
if (control_readint(&lifetime,"control/queuelifetime") == -1) return 0;
if (control_readint(&concurrency[0],"control/concurrencylocal") == -1) return 0;
if (control_readint(&concurrency[1],"control/concurrencyremote") == -1) return 0;
20050120 6/9/2002
This patch adds maildirquota (Maildir++) support to qmail-pop3d and
qmail-local. It was created because when vpopmail switched to maildirquotas,
a user's quota usage was not decreased after deleting mail via qmail-pop3d.
Also, because .qmail files would allow qmail-local to write directly to a
Maildir whithout piping through vdelivermail first, quotas were not effective
for aliases. Actually, this was the case with vpopmail's old quota system as
well.
This patch is not specific to vpopmail. If you use qmail with other agents that
support Maildir++, this should work for you.
The functions used in this patch are taken from maildrop 1.3.9 and courier's
pop daemon, by Sam Varshavchik (www.courier-mta.org). The Maildir++
specification, also by Sam, can be viewed here:
http://www.courier-mta.org/imap/?README.maildirquota.html
However, Sam had NOTHING to do with this patch, so please don't bug him about
it. Either bug me directly, or the vpopmail list (vchkpw@xxxxxxxxxx), who
actually requested it.
Cheers,
Bill Shupp
hostmaster@xxxxxxxxx
www.shupp.org
diff -crN ../qmail-1.03/Makefile ./Makefile
*** ../qmail-1.03/Makefile Mon Jun 15 05:53:16 1998
--- ./Makefile Mon Jun 10 13:25:46 2002
***************
*** 890,895 ****
--- 890,927 ----
readwrite.h open.h headerbody.h maildir.h strerr.h
./compile maildirwatch.c
+ maildirgetquota.o: \
+ compile maildirgetquota.c maildirgetquota.h maildirmisc.h
+ ./compile maildirgetquota.c
+
+ maildirflags.o: \
+ compile maildirflags.c
+ ./compile maildirflags.c
+
+ maildiropen.o: \
+ compile maildiropen.c maildirmisc.h
+ ./compile maildiropen.c
+
+ maildirparsequota.o: \
+ compile maildirparsequota.c
+ ./compile maildirparsequota.c
+
+ maildirquota.o: \
+ compile maildirquota.c maildirquota.h maildirmisc.h numlib.h
+ ./compile maildirquota.c
+
+ overmaildirquota.o: \
+ compile overmaildirquota.c
+ ./compile overmaildirquota.c
+
+ strtimet.o: \
+ compile strtimet.c
+ ./compile strtimet.c
+
+ strpidt.o: \
+ compile strpidt.c
+ ./compile strpidt.c
+
mailsubj: \
warn-auto.sh mailsubj.sh conf-qmail conf-break conf-split
cat warn-auto.sh mailsubj.sh \
***************
*** 1174,1185 ****
load qmail-local.o qmail.o quote.o now.o gfrom.o myctime.o \
slurpclose.o case.a getln.a getopt.a sig.a open.a seek.a lock.a fd.a \
wait.a env.a stralloc.a alloc.a strerr.a substdio.a error.a str.a \
! fs.a datetime.a auto_qmail.o auto_patrn.o socket.lib
./load qmail-local qmail.o quote.o now.o gfrom.o myctime.o \
slurpclose.o case.a getln.a getopt.a sig.a open.a seek.a \
lock.a fd.a wait.a env.a stralloc.a alloc.a strerr.a \
substdio.a error.a str.a fs.a datetime.a auto_qmail.o \
! auto_patrn.o `cat socket.lib`
qmail-local.0: \
qmail-local.8
--- 1206,1220 ----
load qmail-local.o qmail.o quote.o now.o gfrom.o myctime.o \
slurpclose.o case.a getln.a getopt.a sig.a open.a seek.a lock.a fd.a \
wait.a env.a stralloc.a alloc.a strerr.a substdio.a error.a str.a \
! fs.a datetime.a auto_qmail.o auto_patrn.o socket.lib maildirquota.o \
! maildirgetquota.o maildiropen.o maildirparsequota.o overmaildirquota.o \
! strtimet.o strpidt.o
./load qmail-local qmail.o quote.o now.o gfrom.o myctime.o \
slurpclose.o case.a getln.a getopt.a sig.a open.a seek.a \
lock.a fd.a wait.a env.a stralloc.a alloc.a strerr.a \
substdio.a error.a str.a fs.a datetime.a auto_qmail.o \
! auto_patrn.o `cat socket.lib` maildirquota.o maildirgetquota.o \
! maildiropen.o maildirparsequota.o overmaildirquota.o strtimet.o strpidt.o
qmail-local.0: \
qmail-local.8
***************
*** 1269,1279 ****
qmail-pop3d: \
load qmail-pop3d.o commands.o case.a timeoutread.o timeoutwrite.o \
maildir.o prioq.o now.o env.a strerr.a sig.a open.a getln.a \
! stralloc.a alloc.a substdio.a error.a str.a fs.a socket.lib
./load qmail-pop3d commands.o case.a timeoutread.o \
timeoutwrite.o maildir.o prioq.o now.o env.a strerr.a sig.a \
open.a getln.a stralloc.a alloc.a substdio.a error.a str.a \
! fs.a `cat socket.lib`
qmail-pop3d.0: \
qmail-pop3d.8
--- 1304,1316 ----
qmail-pop3d: \
load qmail-pop3d.o commands.o case.a timeoutread.o timeoutwrite.o \
maildir.o prioq.o now.o env.a strerr.a sig.a open.a getln.a \
! stralloc.a alloc.a substdio.a error.a str.a fs.a socket.lib maildirquota.o \
! maildirparsequota.o maildirflags.o maildiropen.o strtimet.o strpidt.o
./load qmail-pop3d commands.o case.a timeoutread.o \
timeoutwrite.o maildir.o prioq.o now.o env.a strerr.a sig.a \
open.a getln.a stralloc.a alloc.a substdio.a error.a str.a \
! fs.a `cat socket.lib` maildirquota.o maildirgetquota.o \
! maildirparsequota.o maildirflags.o maildiropen.o strtimet.o strpidt.o
qmail-pop3d.0: \
qmail-pop3d.8
diff -crN ../qmail-1.03/TARGETS ./TARGETS
*** ../qmail-1.03/TARGETS Mon Jun 15 05:53:16 1998
--- ./TARGETS Mon Jun 10 13:25:46 2002
***************
*** 15,20 ****
--- 15,28 ----
slurpclose.o
make-makelib
makelib
+ maildirflags.o
+ maildirparsequota.o
+ maildiropen.o
+ maildirgetquota.o
+ maildirquota.o
+ overmaildirquota.o
+ strtimet.o
+ strpidt.o
case_diffb.o
case_diffs.o
case_lowerb.o
diff -crN ../qmail-1.03/maildirflags.c ./maildirflags.c
*** ../qmail-1.03/maildirflags.c Wed Dec 31 18:00:00 1969
--- ./maildirflags.c Mon Jun 10 13:25:46 2002
***************
*** 0 ****
--- 1,23 ----
+ /*
+ ** Copyright 2000 Double Precision, Inc.
+ ** See COPYING for distribution information.
+ */
+
+ #include <sys/types.h>
+ #include <string.h>
+
+ static const char rcsid[]="$Id: qmail-maildir++.patch,v 1.1.1.1.2.1 2005/01/19 23:35:23 tomcollins Exp $";
+
+ int maildir_hasflag(const char *filename, char flag)
+ {
+ const char *p=strrchr(filename, '/');
+
+ if (p)
+ filename=p+1;
+
+ p=strrchr(p, ':');
+ if (p && strncmp(p, ":2,", 3) == 0 &&
+ strchr(p+3, flag))
+ return (1);
+ return (0);
+ }
diff -crN ../qmail-1.03/maildirgetquota.c ./maildirgetquota.c
*** ../qmail-1.03/maildirgetquota.c Wed Dec 31 18:00:00 1969
--- ./maildirgetquota.c Mon Jun 10 13:25:46 2002
***************
*** 0 ****
--- 1,50 ----
+ /*
+ ** Copyright 1998 - 2000 Double Precision, Inc.
+ ** See COPYING for distribution information.
+ */
+
+ #include "maildirgetquota.h"
+ #include "maildirmisc.h"
+ #if HAVE_UNISTD_H
+ #include <unistd.h>
+ #endif
+ #include <stdlib.h>
+ #include <string.h>
+ #include <fcntl.h>
+ #include <sys/types.h>
+ #include <sys/stat.h>
+
+ int maildir_getquota(const char *dir, char buf[QUOTABUFSIZE])
+ {
+ char *p;
+ struct stat stat_buf;
+ int n;
+ int l;
+
+ p=(char *)malloc(strlen(dir)+sizeof("/maildirfolder"));
+ if (!p) return (-1);
+
+ strcat(strcpy(p, dir), "/maildirfolder");
+ if (stat(p, &stat_buf) == 0)
+ {
+ strcat(strcpy(p, dir), "/..");
+ n=maildir_getquota(p, buf);
+ free(p);
+ return (n);
+ }
+
+ strcat(strcpy(p, dir), "/maildirsize");
+ n=maildir_safeopen(p, O_RDONLY, 0);
+ free(p);
+ if (n < 0) return (n);
+ if ((l=read(n, buf, QUOTABUFSIZE-1)) < 0)
+ {
+ close(n);
+ return (-1);
+ }
+ close(n);
+ for (n=0; n<l; n++)
+ if (buf[n] == '\n') break;
+ buf[n]=0;
+ return (0);
+ }
diff -crN ../qmail-1.03/maildirgetquota.h ./maildirgetquota.h
*** ../qmail-1.03/maildirgetquota.h Wed Dec 31 18:00:00 1969
--- ./maildirgetquota.h Mon Jun 10 13:25:46 2002
***************
*** 0 ****
--- 1,30 ----
+ #ifndef maildirgetquota_h
+ #define maildirgetquota_h
+
+ /*
+ ** Copyright 1998 - 1999 Double Precision, Inc.
+ ** See COPYING for distribution information.
+ */
+
+ #if HAVE_CONFIG_H
+ #include "config.h"
+ #endif
+
+ #include <sys/types.h>
+ #include <stdio.h>
+
+ #ifdef __cplusplus
+ extern "C" {
+ #endif
+
+ static const char maildirgetquota_h_rcsid[]="$Id: qmail-maildir++.patch,v 1.1.1.1.2.1 2005/01/19 23:35:23 tomcollins Exp $";
+
+ #define QUOTABUFSIZE 256
+
+ int maildir_getquota(const char *, char [QUOTABUFSIZE]);
+
+ #ifdef __cplusplus
+ }
+ #endif
+
+ #endif
diff -crN ../qmail-1.03/maildirmisc.h ./maildirmisc.h
*** ../qmail-1.03/maildirmisc.h Wed Dec 31 18:00:00 1969
--- ./maildirmisc.h Mon Jun 10 13:25:46 2002
***************
*** 0 ****
--- 1,145 ----
+ #ifndef maildirmisc_h
+ #define maildirmisc_h
+
+ /*
+ ** Copyright 2000 Double Precision, Inc.
+ ** See COPYING for distribution information.
+ */
+
+ #if HAVE_CONFIG_H
+ #include "config.h"
+ #endif
+
+ #ifdef __cplusplus
+ extern "C" {
+ #endif
+
+ static const char maildirmisc_h_rcsid[]="$Id: qmail-maildir++.patch,v 1.1.1.1.2.1 2005/01/19 23:35:23 tomcollins Exp $";
+
+ /*
+ **
+ ** Miscellaneous maildir-related code
+ **
+ */
+
+ /* Some special folders */
+
+ #define INBOX "INBOX"
+ #define DRAFTS "Drafts"
+ #define SENT "Sent"
+ #define TRASH "Trash"
+
+ #define SHAREDSUBDIR "shared-folders"
+
+ char *maildir_folderdir(const char *, /* maildir */
+ const char *); /* folder name */
+ /* Returns the directory corresponding to foldername (foldername is
+ ** checked to make sure that it's a valid name, else we set errno
+ ** to EINVAL, and return (0).
+ */
+
+ char *maildir_filename(const char *, /* maildir */
+ const char *, /* folder */
+ const char *); /* filename */
+ /*
+ ** Builds the filename to this message, suitable for opening.
+ ** If the file doesn't appear to be there, search the maildir to
+ ** see if someone changed the flags, and return the current filename.
+ */
+
+ int maildir_safeopen(const char *, /* filename */
+ int, /* mode */
+ int); /* perm */
+
+ /*
+ ** Same arguments as open(). When we're accessing a shared maildir,
+ ** prevent someone from playing cute and dumping a bunch of symlinks
+ ** in there. This function will open the indicate file only if the
+ ** last component is not a symlink.
+ ** This is implemented by opening the file with O_NONBLOCK (to prevent
+ ** a DOS attack of someone pointing the symlink to a pipe, causing
+ ** the open to hang), clearing O_NONBLOCK, then stat-int the file
+ ** descriptor, lstating the filename, and making sure that dev/ino
+ ** match.
+ */
+
+ int maildir_semisafeopen(const char *, /* filename */
+ int, /* mode */
+ int); /* perm */
+
+ /*
+ ** Same thing, except that we allow ONE level of soft link indirection,
+ ** because we're reading from our own maildir, which points to the
+ ** message in the sharable maildir.
+ */
+
+ int maildir_mkdir(const char *); /* directory */
+ /*
+ ** Create maildir including all subdirectories in the path (like mkdir -p)
+ */
+
+ void maildir_purgetmp(const char *); /* maildir */
+ /* purges old stuff out of tmp */
+
+ void maildir_purge(const char *, /* directory */
+ unsigned); /* time_t to purge */
+
+ void maildir_getnew(const char *, /* maildir */
+ const char *); /* folder */
+ /* move messages from new to cur */
+
+ int maildir_deletefolder(const char *, /* maildir */
+ const char *); /* folder */
+ /* deletes a folder */
+
+ int maildir_mddelete(const char *); /* delete a maildir folder by path */
+
+ void maildir_list_sharable(const char *, /* maildir */
+ void (*)(const char *, void *), /* callback function */
+ void *); /* 2nd arg to callback func */
+ /* list sharable folders */
+
+ int maildir_shared_subscribe(const char *, /* maildir */
+ const char *); /* folder */
+ /* subscribe to a shared folder */
+
+ void maildir_list_shared(const char *, /* maildir */
+ void (*)(const char *, void *), /* callback function */
+ void *); /* 2nd arg to the callback func */
+ /* list subscribed folders */
+
+ int maildir_shared_unsubscribe(const char *, /* maildir */
+ const char *); /* folder */
+ /* unsubscribe from a shared folder */
+
+ char *maildir_shareddir(const char *, /* maildir */
+ const char *); /* folder */
+ /*
+ ** Validate and return a path to a shared folder. folderdir must be
+ ** a name of a valid shared folder.
+ */
+
+ void maildir_shared_sync(const char *); /* maildir */
+ /* "sync" the shared folder */
+
+ int maildir_sharedisro(const char *); /* maildir */
+ /* maildir is a shared read-only folder */
+
+ int maildir_unlinksharedmsg(const char *); /* filename */
+ /* Remove a message from a shared folder */
+
+ /* Internal function that reads a symlink */
+
+ char *maildir_getlink(const char *);
+
+ /* Determine whether the maildir filename has a certain flag */
+
+ int maildir_hasflag(const char *filename, char);
+
+ #define MAILDIR_DELETED(f) maildir_hasflag((f), 'T')
+
+ #ifdef __cplusplus
+ }
+ #endif
+
+ #endif
diff -crN ../qmail-1.03/maildiropen.c ./maildiropen.c
*** ../qmail-1.03/maildiropen.c Wed Dec 31 18:00:00 1969
--- ./maildiropen.c Mon Jun 10 13:25:46 2002
***************
*** 0 ****
--- 1,133 ----
+ /*
+ ** Copyright 2000 Double Precision, Inc.
+ ** See COPYING for distribution information.
+ */
+
+ #if HAVE_CONFIG_H
+ #include "config.h"
+ #endif
+
+ #include <sys/types.h>
+ #include <sys/stat.h>
+ #include <string.h>
+ #include <stdlib.h>
+ #include <time.h>
+ #if HAVE_UNISTD_H
+ #include <unistd.h>
+ #endif
+ #include <stdio.h>
+ #include <ctype.h>
+ #include <errno.h>
+ #include <fcntl.h>
+
+ #include "maildirmisc.h"
+
+ static const char rcsid[]="$Id: qmail-maildir++.patch,v 1.1.1.1.2.1 2005/01/19 23:35:23 tomcollins Exp $";
+
+ char *maildir_getlink(const char *filename)
+ {
+ #if HAVE_READLINK
+ size_t bufsiz;
+ char *buf;
+
+ bufsiz=0;
+ buf=0;
+
+ for (;;)
+ {
+ int n;
+
+ if (buf) free(buf);
+ bufsiz += 256;
+ if ((buf=malloc(bufsiz)) == 0)
+ {
+ perror("malloc");
+ return (0);
+ }
+ if ((n=readlink(filename, buf, bufsiz)) < 0)
+ {
+ free(buf);
+ return (0);
+ }
+ if (n < bufsiz)
+ {
+ buf[n]=0;
+ break;
+ }
+ }
+ return (buf);
+ #else
+ return (0);
+ #endif
+ }
+
+ int maildir_semisafeopen(const char *path, int mode, int perm)
+ {
+
+ #if HAVE_READLINK
+
+ char *l=maildir_getlink(path);
+
+ if (l)
+ {
+ int f;
+
+ if (*l != '/')
+ {
+ char *q=malloc(strlen(path)+strlen(l)+2);
+ char *s;
+
+ if (!q)
+ {
+ free(l);
+ return (-1);
+ }
+
+ strcpy(q, path);
+ if ((s=strchr(q, '/')) != 0)
+ s[1]=0;
+ else *q=0;
+ strcat(q, l);
+ free(l);
+ l=q;
+ }
+
+ f=maildir_safeopen(l, mode, perm);
+
+ free(l);
+ return (f);
+ }
+ #endif
+
+ return (maildir_safeopen(path, mode, perm));
+ }
+
+ int maildir_safeopen(const char *path, int mode, int perm)
+ {
+ struct stat stat1, stat2;
+
+ int fd=open(path, mode
+ #ifdef O_NONBLOCK
+ | O_NONBLOCK
+ #else
+ | O_NDELAY
+ #endif
+ , perm);
+
+ if (fd < 0) return (fd);
+ if (fcntl(fd, F_SETFL, (mode & O_APPEND)) || fstat(fd, &stat1)
+ || lstat(path, &stat2))
+ {
+ close(fd);
+ return (-1);
+ }
+
+ if (stat1.st_dev != stat2.st_dev || stat1.st_ino != stat2.st_ino)
+ {
+ close(fd);
+ errno=ENOENT;
+ return (-1);
+ }
+
+ return (fd);
+ }
diff -crN ../qmail-1.03/maildirparsequota.c ./maildirparsequota.c
*** ../qmail-1.03/maildirparsequota.c Wed Dec 31 18:00:00 1969
--- ./maildirparsequota.c Mon Jun 10 13:25:46 2002
***************
*** 0 ****
--- 1,44 ----
+ /*
+ ** Copyright 1998 - 1999 Double Precision, Inc.
+ ** See COPYING for distribution information.
+ */
+
+ #if HAVE_CONFIG_H
+ #include "config.h"
+ #endif
+ #include "maildirquota.h"
+ #include <stdlib.h>
+ #include <string.h>
+
+ static const char rcsid[]="$Id: qmail-maildir++.patch,v 1.1.1.1.2.1 2005/01/19 23:35:23 tomcollins Exp $";
+
+ int maildir_parsequota(const char *n, unsigned long *s)
+ {
+ const char *o;
+ int yes;
+
+ if ((o=strrchr(n, '/')) == 0) o=n;
+
+ for (; *o; o++)
+ if (*o == ':') break;
+ yes=0;
+ for ( ; o >= n; --o)
+ {
+ if (*o == '/') break;
+
+ if (*o == ',' && o[1] == 'S' && o[2] == '=')
+ {
+ yes=1;
+ o += 3;
+ break;
+ }
+ }
+ if (yes)
+ {
+ *s=0;
+ while (*o >= '0' && *o <= '9')
+ *s= *s*10 + (*o++ - '0');
+ return (0);
+ }
+ return (-1);
+ }
diff -crN ../qmail-1.03/maildirquota.c ./maildirquota.c
*** ../qmail-1.03/maildirquota.c Wed Dec 31 18:00:00 1969
--- ./maildirquota.c Mon Jun 10 13:25:46 2002
***************
*** 0 ****
--- 1,685 ----
+ /*
+ ** Copyright 1998 - 2002 Double Precision, Inc.
+ ** See COPYING for distribution information.
+ */
+
+ #if HAVE_CONFIG_H
+ #include "config.h"
+ #endif
+
+ #include <sys/types.h>
+ /* #if HAVE_DIRENT_H */
+ #include <dirent.h>
+ #define NAMLEN(dirent) strlen((dirent)->d_name)
+ /* #else
+ #define dirent direct
+ #define NAMLEN(dirent) (dirent)->d_namlen
+ #if HAVE_SYS_NDIR_H
+ #include <sys/ndir.h>
+ #endif
+ #if HAVE_SYS_DIR_H
+ #include <sys/dir.h>
+ #endif
+ #if HAVE_NDIR_H
+ #include <ndir.h>
+ #endif
+ #endif */
+ #include <sys/types.h>
+ /* #if HAVE_SYS_STAT_H */
+ #include <sys/stat.h>
+ /* #endif */
+ #include <sys/uio.h>
+
+ #include "maildirquota.h"
+ #include "maildirmisc.h"
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <string.h>
+ #include <errno.h>
+ /* #if HAVE_FCNTL_H */
+ #include <fcntl.h>
+ /* #endif */
+ #if HAVE_UNISTD_H
+ #include <unistd.h>
+ #endif
+ #include <time.h>
+ #include "numlib.h"
+
+ static const char rcsid[]="$Id: qmail-maildir++.patch,v 1.1.1.1.2.1 2005/01/19 23:35:23 tomcollins Exp $";
+
+ /* Read the maildirsize file */
+
+ int maildirsize_read(const char *filename, /* The filename */
+ int *fdptr, /* Keep the file descriptor open */
+ off_t *sizeptr, /* Grand total of maildir size */
+ unsigned *cntptr, /* Grand total of message count */
+ unsigned *nlines, /* # of lines in maildirsize */
+ struct stat *statptr) /* The stats on maildirsize */
+ {
+ char buf[5120];
+ int f;
+ char *p;
+ unsigned l;
+ int n;
+ int first;
+
+ if ((f=maildir_safeopen(filename, O_RDWR|O_APPEND, 0)) < 0)
+ return (-1);
+ p=buf;
+ l=sizeof(buf);
+
+ while (l)
+ {
+ n=read(f, p, l);
+ if (n < 0)
+ {
+ close(f);
+ return (-1);
+ }
+ if (n == 0) break;
+ p += n;
+ l -= n;
+ }
+ if (l == 0 || fstat(f, statptr)) /* maildir too big */
+ {
+ close(f);
+ return (-1);
+ }
+
+ *sizeptr=0;
+ *cntptr=0;
+ *nlines=0;
+ *p=0;
+ p=buf;
+ first=1;
+ while (*p)
+ {
+ long n=0;
+ int c=0;
+ char *q=p;
+
+ while (*p)
+ if (*p++ == '\n')
+ {
+ p[-1]=0;
+ break;
+ }
+
+ if (first)
+ {
+ first=0;
+ continue;
+ }
+ sscanf(q, "%ld %d", &n, &c);
+ *sizeptr += n;
+ *cntptr += c;
+ ++ *nlines;
+ }
+ *fdptr=f;
+ return (0);
+ }
+
+ static char *makenewmaildirsizename(const char *, int *);
+ static int countcurnew(const char *, time_t *, off_t *, unsigned *);
+ static int countsubdir(const char *, const char *,
+ time_t *, off_t *, unsigned *);
+ static int statcurnew(const char *, time_t *);
+ static int statsubdir(const char *, const char *, time_t *);
+
+ #define MDQUOTA_SIZE 'S' /* Total size of all messages in maildir */
+ #define MDQUOTA_BLOCKS 'B' /* Total # of blocks for all messages in
+ maildir -- NOT IMPLEMENTED */
+ #define MDQUOTA_COUNT 'C' /* Total number of messages in maildir */
+
+ static int qcalc(off_t s, unsigned n, const char *quota, int *percentage)
+ {
+ off_t i;
+ int spercentage=0;
+ int npercentage=0;
+
+ errno=ENOSPC;
+ while (quota && *quota)
+ {
+ int x=1;
+
+ if (*quota < '0' || *quota > '9')
+ {
+ ++quota;
+ continue;
+ }
+ i=0;
+ while (*quota >= '0' && *quota <= '9')
+ i=i*10 + (*quota++ - '0');
+ switch (*quota) {
+ default:
+ if (i < s)
+ {
+ *percentage=100;
+ return (-1);
+ }
+
+ /*
+ ** For huge quotas, over 20mb,
+ ** divide numerator & denominator by 1024 to prevent
+ ** an overflow when multiplying by 100
+ */
+
+ x=1;
+ if (i > 20000000) x=1024;
+
+ spercentage = i ? (s/x) * 100 / (i/x):100;
+ break;
+ case 'C':
+
+ if (i < n)
+ {
+ *percentage=100;
+ return (-1);
+ }
+
+ /* Ditto */
+
+ x=1;
+ if (i > 20000000) x=1024;
+
+ npercentage = i ? ((off_t)n/x) * 100 / (i/x):100;
+ break;
+ }
+ }
+ *percentage = spercentage > npercentage ? spercentage:npercentage;
+ return (0);
+ }
+
+ static int doaddquota(const char *, int, const char *, long, int, int);
+
+ static int docheckquota(const char *dir,
+ int *maildirsize_fdptr,
+ const char *quota_type,
+ long xtra_size,
+ int xtra_cnt, int *percentage);
+
+
+ int maildir_checkquota(const char *dir,
+ int *maildirsize_fdptr,
+ const char *quota_type,
+ long xtra_size,
+ int xtra_cnt)
+ {
+ int dummy;
+
+ return (docheckquota(dir, maildirsize_fdptr, quota_type,
+ xtra_size, xtra_cnt, &dummy));
+ }
+
+ int maildir_readquota(const char *dir, const char *quota_type)
+ {
+ int percentage=0;
+ int fd=-1;
+
+ (void)docheckquota(dir, &fd, quota_type, 0, 0, &percentage);
+ if (fd >= 0)
+ close(fd);
+ return (percentage);
+ }
+
+ static int docheckquota(const char *dir,
+ int *maildirsize_fdptr,
+ const char *quota_type,
+ long xtra_size,
+ int xtra_cnt,
+ int *percentage)
+ {
+ char *checkfolder=(char *)malloc(strlen(dir)+sizeof("/maildirfolder"));
+ char *newmaildirsizename;
+ struct stat stat_buf;
+ int maildirsize_fd;
+ off_t maildirsize_size;
+ unsigned maildirsize_cnt;
+ unsigned maildirsize_nlines;
+ int n;
+ time_t tm;
+ time_t maxtime;
+ DIR *dirp;
+ struct dirent *de;
+
+ if (checkfolder == 0) return (-1);
+ *maildirsize_fdptr= -1;
+ strcat(strcpy(checkfolder, dir), "/maildirfolder");
+ if (stat(checkfolder, &stat_buf) == 0) /* Go to parent */
+ {
+ strcat(strcpy(checkfolder, dir), "/..");
+ n=docheckquota(checkfolder, maildirsize_fdptr,
+ quota_type, xtra_size, xtra_cnt, percentage);
+ free(checkfolder);
+ return (n);
+ }
+ if (!quota_type || !*quota_type) return (0);
+
+ strcat(strcpy(checkfolder, dir), "/maildirsize");
+ time(&tm);
+ if (maildirsize_read(checkfolder, &maildirsize_fd,
+ &maildirsize_size, &maildirsize_cnt,
+ &maildirsize_nlines, &stat_buf) == 0)
+ {
+ n=qcalc(maildirsize_size+xtra_size, maildirsize_cnt+xtra_cnt,
+ quota_type, percentage);
+
+ if (n == 0)
+ {
+ free(checkfolder);
+ *maildirsize_fdptr=maildirsize_fd;
+ return (0);
+ }
+ close(maildirsize_fd);
+
+ if (maildirsize_nlines == 1 && tm < stat_buf.st_mtime + 15*60)
+ return (n);
+ }
+
+ maxtime=0;
+ maildirsize_size=0;
+ maildirsize_cnt=0;
+
+ if (countcurnew(dir, &maxtime, &maildirsize_size, &maildirsize_cnt))
+ {
+ free(checkfolder);
+ return (-1);
+ }
+
+ dirp=opendir(dir);
+ while (dirp && (de=readdir(dirp)) != 0)
+ {
+ if (countsubdir(dir, de->d_name, &maxtime, &maildirsize_size,
+ &maildirsize_cnt))
+ {
+ free(checkfolder);
+ closedir(dirp);
+ return (-1);
+ }
+ }
+ if (dirp)
+ {
+ #if CLOSEDIR_VOID
+ closedir(dirp);
+ #else
+ if (closedir(dirp))
+ {
+ free(checkfolder);
+ return (-1);
+ }
+ #endif
+ }
+
+ newmaildirsizename=makenewmaildirsizename(dir, &maildirsize_fd);
+ if (!newmaildirsizename)
+ {
+ free(checkfolder);
+ return (-1);
+ }
+
+ *maildirsize_fdptr=maildirsize_fd;
+
+ if (doaddquota(dir, maildirsize_fd, quota_type, maildirsize_size,
+ maildirsize_cnt, 1))
+ {
+ unlink(newmaildirsizename);
+ free(newmaildirsizename);
+ close(maildirsize_fd);
+ *maildirsize_fdptr= -1;
+ free(checkfolder);
+ return (-1);
+ }
+
+ strcat(strcpy(checkfolder, dir), "/maildirsize");
+
+ if (rename(newmaildirsizename, checkfolder))
+ {
+ /* free(checkfolder); */
+ unlink(newmaildirsizename);
+ close(maildirsize_fd);
+ *maildirsize_fdptr= -1;
+ }
+ free(checkfolder);
+ free(newmaildirsizename);
+
+ tm=0;
+
+ if (statcurnew(dir, &tm))
+ {
+ close(maildirsize_fd);
+ *maildirsize_fdptr= -1;
+ return (-1);
+ }
+
+ dirp=opendir(dir);
+ while (dirp && (de=readdir(dirp)) != 0)
+ {
+ if (statsubdir(dir, de->d_name, &tm))
+ {
+ close(maildirsize_fd);
+ *maildirsize_fdptr= -1;
+ closedir(dirp);
+ return (-1);
+ }
+ }
+ if (dirp)
+ {
+ #if CLOSEDIR_VOID
+ closedir(dirp);
+ #else
+ if (closedir(dirp))
+ {
+ close(maildirsize_fd);
+ *maildirsize_fdptr= -1;
+ return (-1);
+ }
+ #endif
+ }
+
+ if (tm != maxtime) /* Race condition, someone changed something */
+ {
+ errno=EAGAIN;
+ return (-1);
+ }
+
+ return (qcalc(maildirsize_size+xtra_size, maildirsize_cnt+xtra_cnt,
+ quota_type, percentage));
+ }
+
+ int maildir_addquota(const char *dir, int maildirsize_fd,
+ const char *quota_type, long maildirsize_size, int maildirsize_cnt)
+ {
+ if (!quota_type || !*quota_type) return (0);
+ return (doaddquota(dir, maildirsize_fd, quota_type, maildirsize_size,
+ maildirsize_cnt, 0));
+ }
+
+ static int doaddquota(const char *dir, int maildirsize_fd,
+ const char *quota_type, long maildirsize_size, int maildirsize_cnt,
+ int isnew)
+ {
+ union {
+ char buf[100];
+ struct stat stat_buf;
+ } u; /* Scrooge */
+ char *newname2=0;
+ char *newmaildirsizename=0;
+ struct iovec iov[3];
+ int niov;
+ struct iovec *p;
+ int n;
+
+ niov=0;
+ if ( maildirsize_fd < 0)
+ {
+ newname2=(char *)malloc(strlen(dir)+sizeof("/maildirfolder"));
+ if (!newname2) return (-1);
+ strcat(strcpy(newname2, dir), "/maildirfolder");
+ if (stat(newname2, &u.stat_buf) == 0)
+ {
+ strcat(strcpy(newname2, dir), "/..");
+ n=doaddquota(newname2, maildirsize_fd, quota_type,
+ maildirsize_size, maildirsize_cnt,
+ isnew);
+ free(newname2);
+ return (n);
+ }
+
+ strcat(strcpy(newname2, dir), "/maildirsize");
+
+ if ((maildirsize_fd=maildir_safeopen(newname2,
+ O_RDWR|O_APPEND, 0644)) < 0)
+ {
+ newmaildirsizename=makenewmaildirsizename(dir, &maildirsize_fd);
+ if (!newmaildirsizename)
+ {
+ free(newname2);
+ return (-1);
+ }
+
+ maildirsize_fd=maildir_safeopen(newmaildirsizename,
+ O_CREAT|O_RDWR|O_APPEND, 0644);
+
+ if (maildirsize_fd < 0)
+ {
+ free(newname2);
+ return (-1);
+ }
+ isnew=1;
+ }
+ }
+
+ if (isnew)
+ {
+ iov[0].iov_base=(caddr_t)quota_type;
+ iov[0].iov_len=strlen(quota_type);
+ iov[1].iov_base=(caddr_t)"\n";
+ iov[1].iov_len=1;
+ niov=2;
+ }
+
+
+ sprintf(u.buf, "%ld %d\n", maildirsize_size, maildirsize_cnt);
+ iov[niov].iov_base=(caddr_t)u.buf;
+ iov[niov].iov_len=strlen(u.buf);
+
+ p=iov;
+ ++niov;
+ n=0;
+ while (niov)
+ {
+ if (n)
+ {
+ if (n < p->iov_len)
+ {
+ p->iov_base=
+ (caddr_t)((char *)p->iov_base + n);
+ p->iov_len -= n;
+ }
+ else
+ {
+ n -= p->iov_len;
+ ++p;
+ --niov;
+ continue;
+ }
+ }
+
+ n=writev( maildirsize_fd, p, niov);
+
+ if (n <= 0)
+ {
+ if (newname2)
+ {
+ close(maildirsize_fd);
+ free(newname2);
+ }
+ return (-1);
+ }
+ }
+ if (newname2)
+ {
+ close(maildirsize_fd);
+
+ if (newmaildirsizename)
+ {
+ rename(newmaildirsizename, newname2);
+ free(newmaildirsizename);
+ }
+ free(newname2);
+ }
+ return (0);
+ }
+
+ /* New maildirsize is built in the tmp subdirectory */
+
+ static char *makenewmaildirsizename(const char *dir, int *fd)
+ {
+ char hostname[256];
+ struct stat stat_buf;
+ time_t t;
+ char *p;
+
+ hostname[0]=0;
+ hostname[sizeof(hostname)-1]=0;
+ gethostname(hostname, sizeof(hostname)-1);
+ p=(char *)malloc(strlen(dir)+strlen(hostname)+130);
+ if (!p) return (0);
+
+ for (;;)
+ {
+ char tbuf[NUMBUFSIZE];
+ char pbuf[NUMBUFSIZE];
+
+ time(&t);
+ strcat(strcpy(p, dir), "/tmp/");
+ sprintf(p+strlen(p), "%s.%s_NeWmAiLdIrSiZe.%s",
+ str_time_t(t, tbuf),
+ str_pid_t(getpid(), pbuf), hostname);
+
+ if (stat( (const char *)p, &stat_buf) < 0 &&
+ (*fd=maildir_safeopen(p,
+ O_CREAT|O_RDWR|O_APPEND, 0644)) >= 0)
+ break;
+ sleep(3);
+ }
+ return (p);
+ }
+
+ static int statcurnew(const char *dir, time_t *maxtimestamp)
+ {
+ char *p=(char *)malloc(strlen(dir)+5);
+ struct stat stat_buf;
+
+ if (!p) return (-1);
+ strcat(strcpy(p, dir), "/cur");
+ if ( stat(p, &stat_buf) == 0 && stat_buf.st_mtime > *maxtimestamp)
+ *maxtimestamp=stat_buf.st_mtime;
+ strcat(strcpy(p, dir), "/new");
+ if ( stat(p, &stat_buf) == 0 && stat_buf.st_mtime > *maxtimestamp)
+ *maxtimestamp=stat_buf.st_mtime;
+ free(p);
+ return (0);
+ }
+
+ static int statsubdir(const char *dir, const char *subdir, time_t *maxtime)
+ {
+ char *p;
+ int n;
+
+ if ( *subdir != '.' || strcmp(subdir, ".") == 0 ||
+ strcmp(subdir, "..") == 0 || strcmp(subdir, "." TRASH) == 0)
+ return (0);
+
+ p=(char *)malloc(strlen(dir)+strlen(subdir)+2);
+ if (!p) return (-1);
+ strcat(strcat(strcpy(p, dir), "/"), subdir);
+ n=statcurnew(p, maxtime);
+ free(p);
+ return (n);
+ }
+
+ static int docount(const char *, time_t *, off_t *, unsigned *);
+
+ static int countcurnew(const char *dir, time_t *maxtime,
+ off_t *sizep, unsigned *cntp)
+ {
+ char *p=(char *)malloc(strlen(dir)+5);
+ int n;
+
+ if (!p) return (-1);
+ strcat(strcpy(p, dir), "/new");
+ n=docount(p, maxtime, sizep, cntp);
+ if (n == 0)
+ {
+ strcat(strcpy(p, dir), "/cur");
+ n=docount(p, maxtime, sizep, cntp);
+ }
+ free(p);
+ return (n);
+ }
+
+ static int countsubdir(const char *dir, const char *subdir, time_t *maxtime,
+ off_t *sizep, unsigned *cntp)
+ {
+ char *p;
+ int n;
+
+ if ( *subdir != '.' || strcmp(subdir, ".") == 0 ||
+ strcmp(subdir, "..") == 0 || strcmp(subdir, "." TRASH) == 0)
+ return (0);
+
+ p=(char *)malloc(strlen(dir)+strlen(subdir)+2);
+ if (!p) return (2);
+ strcat(strcat(strcpy(p, dir), "/"), subdir);
+ n=countcurnew(p, maxtime, sizep, cntp);
+ free(p);
+ return (n);
+ }
+
+ static int docount(const char *dir, time_t *dirstamp,
+ off_t *sizep, unsigned *cntp)
+ {
+ struct stat stat_buf;
+ char *p;
+ DIR *dirp;
+ struct dirent *de;
+ unsigned long s;
+
+ if (stat(dir, &stat_buf)) return (0); /* Ignore */
+ if (stat_buf.st_mtime > *dirstamp) *dirstamp=stat_buf.st_mtime;
+ if ((dirp=opendir(dir)) == 0) return (0);
+ while ((de=readdir(dirp)) != 0)
+ {
+ const char *n=de->d_name;
+
+ if (*n == '.') continue;
+
+ /* PATCH - do not count msgs marked as deleted */
+
+ for ( ; *n; n++)
+ {
+ if (n[0] != ':' || n[1] != '2' ||
+ n[2] != ',') continue;
+ n += 3;
+ while (*n >= 'A' && *n <= 'Z')
+ {
+ if (*n == 'T') break;
+ ++n;
+ }
+ break;
+ }
+ if (*n == 'T') continue;
+ n=de->d_name;
+
+
+ if (maildir_parsequota(n, &s) == 0)
+ stat_buf.st_size=s;
+ else
+ {
+ p=(char *)malloc(strlen(dir)+strlen(n)+2);
+ if (!p)
+ {
+ closedir(dirp);
+ return (-1);
+ }
+ strcat(strcat(strcpy(p, dir), "/"), n);
+ if (stat(p, &stat_buf))
+ {
+ free(p);
+ continue;
+ }
+ free(p);
+ }
+ *sizep += stat_buf.st_size;
+ ++*cntp;
+ }
+
+ #if CLOSEDIR_VOID
+ closedir(dirp);
+ #else
+ if (closedir(dirp))
+ return (-1);
+ #endif
+ return (0);
+ }
diff -crN ../qmail-1.03/maildirquota.h ./maildirquota.h
*** ../qmail-1.03/maildirquota.h Wed Dec 31 18:00:00 1969
--- ./maildirquota.h Mon Jun 10 13:25:46 2002
***************
*** 0 ****
--- 1,45 ----
+ #ifndef maildirquota_h
+ #define maildirquota_h
+
+ /*
+ ** Copyright 1998 - 1999 Double Precision, Inc.
+ ** See COPYING for distribution information.
+ */
+
+ #if HAVE_CONFIG_H
+ #include "config.h"
+ #endif
+
+ #include <sys/types.h>
+ #include <stdio.h>
+
+ #ifdef __cplusplus
+ extern "C" {
+ #endif
+
+ static const char maildirquota_h_rcsid[]="$Id: qmail-maildir++.patch,v 1.1.1.1.2.1 2005/01/19 23:35:23 tomcollins Exp $";
+
+ int maildir_checkquota(const char *, /* Pointer to directory */
+ int *, /* Initialized to -1, or opened descriptor for maildirsize */
+ const char *, /* The quota */
+ long, /* Extra bytes planning to add/remove from maildir */
+ int); /* Extra messages planning to add/remove from maildir */
+
+ int maildir_addquota(const char *, /* Pointer to the maildir */
+ int, /* Must be the int pointed to by 2nd arg to checkquota */
+ const char *, /* The quota */
+ long, /* +/- bytes */
+ int); /* +/- files */
+
+ int maildir_readquota(const char *, /* Directory */
+ const char *); /* Quota, from getquota */
+
+ int maildir_parsequota(const char *, unsigned long *);
+ /* Attempt to parse file size encoded in filename. Returns 0 if
+ ** parsed, non-zero if we didn't parse. */
+
+ #ifdef __cplusplus
+ }
+ #endif
+
+ #endif
diff -crN ../qmail-1.03/numlib.h ./numlib.h
*** ../qmail-1.03/numlib.h Wed Dec 31 18:00:00 1969
--- ./numlib.h Mon Jun 10 13:25:46 2002
***************
*** 0 ****
--- 1,45 ----
+ #ifndef numlib_h
+ #define numlib_h
+
+ /*
+ ** Copyright 1998 - 1999 Double Precision, Inc.
+ ** See COPYING for distribution information.
+ */
+
+ #ifdef __cplusplus
+ extern "C" {
+ #endif
+
+ static const char numlib_h_rcsid[]="$Id: qmail-maildir++.patch,v 1.1.1.1.2.1 2005/01/19 23:35:23 tomcollins Exp $";
+
+ #if HAVE_CONFIG_H
+ #include "config.h"
+ #endif
+
+ #include <sys/types.h>
+ #include <time.h>
+
+ #define NUMBUFSIZE 60
+
+ /* Convert various system types to decimal */
+
+ char *str_time_t(time_t, char *);
+ char *str_off_t(off_t, char *);
+ char *str_pid_t(pid_t, char *);
+ char *str_ino_t(ino_t, char *);
+ char *str_uid_t(uid_t, char *);
+ char *str_gid_t(gid_t, char *);
+ char *str_size_t(size_t, char *);
+
+ char *str_sizekb(unsigned long, char *); /* X Kb or X Mb */
+
+ /* Convert selected system types to hex */
+
+ char *strh_time_t(time_t, char *);
+ char *strh_pid_t(pid_t, char *);
+ char *strh_ino_t(ino_t, char *);
+
+ #ifdef __cplusplus
+ }
+ #endif
+ #endif
diff -crN ../qmail-1.03/overmaildirquota.c ./overmaildirquota.c
*** ../qmail-1.03/overmaildirquota.c Wed Dec 31 18:00:00 1969
--- ./overmaildirquota.c Mon Jun 10 13:25:46 2002
***************
*** 0 ****
--- 1,43 ----
+ /*
+ ** Copyright 1998 - 1999 Double Precision, Inc.
+ ** See COPYING for distribution information.
+ */
+
+ #if HAVE_CONFIG_H
+ #include "config.h"
+ #endif
+ #include "maildirquota.h"
+ #include <stdlib.h>
+ #include <string.h>
+ #include <errno.h>
+ #include <sys/stat.h>
+
+ static const char rcsid[]="$Id: qmail-maildir++.patch,v 1.1.1.1.2.1 2005/01/19 23:35:23 tomcollins Exp $";
+
+
+
+ int user_over_maildirquota( const char *dir, const char *q)
+ {
+ struct stat stat_buf;
+ int quotafd;
+ int ret_value;
+
+ if (fstat(0, &stat_buf) == 0 && S_ISREG(stat_buf.st_mode) &&
+ stat_buf.st_size > 0 && *q)
+ {
+ if (maildir_checkquota(dir, "afd, q, stat_buf.st_size, 1)
+ && errno != EAGAIN)
+ {
+ if (quotafd >= 0) close(quotafd);
+ ret_value = 1;
+ } else {
+ maildir_addquota(dir, quotafd, q, stat_buf.st_size, 1);
+ if (quotafd >= 0) close(quotafd);
+ ret_value = 0;
+ }
+ } else {
+ ret_value = 0;
+ }
+
+ return(ret_value);
+ }
diff -crN ../qmail-1.03/qmail-local.c ./qmail-local.c
*** ../qmail-1.03/qmail-local.c Mon Jun 15 05:53:16 1998
--- ./qmail-local.c Mon Jun 10 13:54:19 2002
***************
*** 66,71 ****
--- 66,72 ----
char buf[1024];
char outbuf[1024];
+ #define QUOTABUFSIZE 256
/* child process */
***************
*** 86,94 ****
--- 87,101 ----
int fd;
substdio ss;
substdio ssout;
+ char quotabuf[QUOTABUFSIZE];
sig_alarmcatch(sigalrm);
if (chdir(dir) == -1) { if (error_temp(errno)) _exit(1); _exit(2); }
+ if (maildir_getquota(dir, quotabuf) == 0) {
+ if (user_over_maildirquota(dir,quotabuf)==1) {
+ _exit(1);
+ }
+ }
pid = getpid();
host[0] = 0;
gethostname(host,sizeof(host));
***************
*** 99,105 ****
s += fmt_str(s,"tmp/");
s += fmt_ulong(s,time); *s++ = '.';
s += fmt_ulong(s,pid); *s++ = '.';
! s += fmt_strn(s,host,sizeof(host)); *s++ = 0;
if (stat(fntmptph,&st) == -1) if (errno == error_noent) break;
/* really should never get to this point */
if (loop == 2) _exit(1);
--- 106,115 ----
s += fmt_str(s,"tmp/");
s += fmt_ulong(s,time); *s++ = '.';
s += fmt_ulong(s,pid); *s++ = '.';
! s += fmt_strn(s,host,sizeof(host));
! s += fmt_strn(s,",S=",sizeof(",S="));
! if (fstat(0,&st) == -1) if (errno == error_noent) break;
! s += fmt_ulong(s,st.st_size); *s++ = 0;
if (stat(fntmptph,&st) == -1) if (errno == error_noent) break;
/* really should never get to this point */
if (loop == 2) _exit(1);
***************
*** 159,164 ****
--- 169,175 ----
switch(wait_exitcode(wstat))
{
case 0: break;
+ case 1: strerr_die1x(1, "User over quota. (#5.1.1)");
case 2: strerr_die1x(111,"Unable to chdir to maildir. (#4.2.1)");
case 3: strerr_die1x(111,"Timeout on maildir delivery. (#4.3.0)");
case 4: strerr_die1x(111,"Unable to read message. (#4.3.0)");
diff -crN ../qmail-1.03/qmail-pop3d.c ./qmail-pop3d.c
*** ../qmail-1.03/qmail-pop3d.c Mon Jun 15 05:53:16 1998
--- ./qmail-pop3d.c Mon Jun 10 13:25:46 2002
***************
*** 16,21 ****
--- 16,26 ----
#include "readwrite.h"
#include "timeoutread.h"
#include "timeoutwrite.h"
+ #include <errno.h>
+ #include "maildirquota.h"
+ #include "maildirmisc.h"
+
+ #define QUOTABUFSIZE 256
void die() { _exit(0); }
***************
*** 45,63 ****
{
substdio_put(&ssout,buf,len);
}
- void puts(s) char *s;
- {
- substdio_puts(&ssout,s);
- }
void flush()
{
substdio_flush(&ssout);
}
void err(s) char *s;
{
! puts("-ERR ");
! puts(s);
! puts("\r\n");
flush();
}
--- 50,64 ----
{
substdio_put(&ssout,buf,len);
}
void flush()
{
substdio_flush(&ssout);
}
void err(s) char *s;
{
! substdio_puts(&ssout,"-ERR ");
! substdio_puts(&ssout,s);
! substdio_puts(&ssout,"\r\n");
flush();
}
***************
*** 73,79 ****
void err_nosuch() { err("unable to open that message"); }
void err_nounlink() { err("unable to unlink all deleted messages"); }
! void okay() { puts("+OK \r\n"); flush(); }
void printfn(fn) char *fn;
{
--- 74,80 ----
void err_nosuch() { err("unable to open that message"); }
void err_nounlink() { err("unable to unlink all deleted messages"); }
! void okay() { substdio_puts(&ssout,"+OK \r\n"); flush(); }
void printfn(fn) char *fn;
{
***************
*** 153,163 ****
total = 0;
for (i = 0;i < numm;++i) if (!m[i].flagdeleted) total += m[i].size;
! puts("+OK ");
put(strnum,fmt_uint(strnum,numm));
! puts(" ");
put(strnum,fmt_ulong(strnum,total));
! puts("\r\n");
flush();
}
--- 154,164 ----
total = 0;
for (i = 0;i < numm;++i) if (!m[i].flagdeleted) total += m[i].size;
! substdio_puts(&ssout,"+OK ");
put(strnum,fmt_uint(strnum,numm));
! substdio_puts(&ssout," ");
put(strnum,fmt_ulong(strnum,total));
! substdio_puts(&ssout,"\r\n");
flush();
}
***************
*** 171,188 ****
void pop3_last()
{
! puts("+OK ");
put(strnum,fmt_uint(strnum,last));
! puts("\r\n");
flush();
}
void pop3_quit()
{
int i;
for (i = 0;i < numm;++i)
if (m[i].flagdeleted) {
! if (unlink(m[i].fn) == -1) err_nounlink();
}
else
if (str_start(m[i].fn,"new/")) {
--- 172,212 ----
void pop3_last()
{
! substdio_puts(&ssout,"+OK ");
put(strnum,fmt_uint(strnum,last));
! substdio_puts(&ssout,"\r\n");
flush();
}
void pop3_quit()
{
int i;
+ char quotabuf[QUOTABUFSIZE];
+ int has_quota=maildir_getquota(".", quotabuf);
+
+ long deleted_bytes=0;
+ long deleted_messages=0;
+
for (i = 0;i < numm;++i)
if (m[i].flagdeleted) {
! unsigned long un=0;
! const char *filename=m[i].fn;
! if (has_quota == 0 && !MAILDIR_DELETED(filename)) {
! if (maildir_parsequota(filename, &un)) {
! struct stat stat_buf;
!
! if (stat(filename, &stat_buf) == 0)
! un=stat_buf.st_size;
! }
! }
! if (unlink(m[i].fn) == -1) {
! err_nounlink();
! un=0;
! }
! if (un) {
! deleted_bytes -= un;
! deleted_messages -= 1;
! }
}
else
if (str_start(m[i].fn,"new/")) {
***************
*** 192,197 ****
--- 216,236 ----
if (!stralloc_0(&line)) die_nomem();
rename(m[i].fn,line.s); /* if it fails, bummer */
}
+
+ if (deleted_messages < 0) {
+ int quotafd;
+
+ if (maildir_checkquota(".", "afd, quotabuf, deleted_bytes,
+ deleted_messages) && errno != EAGAIN &&
+ deleted_bytes >= 0)
+ {
+ if (quotafd >= 0) close (quotafd);
+ } else {
+ maildir_addquota(".", quotafd, quotabuf,
+ deleted_bytes, deleted_messages);
+ if (quotafd >= 0) close(quotafd);
+ }
+ }
okay();
die();
}
***************
*** 222,231 ****
int flaguidl;
{
put(strnum,fmt_uint(strnum,i + 1));
! puts(" ");
if (flaguidl) printfn(m[i].fn);
else put(strnum,fmt_ulong(strnum,m[i].size));
! puts("\r\n");
}
void dolisting(arg,flaguidl) char *arg; int flaguidl;
--- 261,270 ----
int flaguidl;
{
put(strnum,fmt_uint(strnum,i + 1));
! substdio_puts(&ssout," ");
if (flaguidl) printfn(m[i].fn);
else put(strnum,fmt_ulong(strnum,m[i].size));
! substdio_puts(&ssout,"\r\n");
}
void dolisting(arg,flaguidl) char *arg; int flaguidl;
***************
*** 234,240 ****
if (*arg) {
i = msgno(arg);
if (i == -1) return;
! puts("+OK ");
list(i,flaguidl);
}
else {
--- 273,279 ----
if (*arg) {
i = msgno(arg);
if (i == -1) return;
! substdio_puts(&ssout,"+OK ");
list(i,flaguidl);
}
else {
***************
*** 242,248 ****
for (i = 0;i < numm;++i)
if (!m[i].flagdeleted)
list(i,flaguidl);
! puts(".\r\n");
}
flush();
}
--- 281,287 ----
for (i = 0;i < numm;++i)
if (!m[i].flagdeleted)
list(i,flaguidl);
! substdio_puts(&ssout,".\r\n");
}
flush();
}
diff -crN ../qmail-1.03/strpidt.c ./strpidt.c
*** ../qmail-1.03/strpidt.c Wed Dec 31 18:00:00 1969
--- ./strpidt.c Mon Jun 10 13:25:46 2002
***************
*** 0 ****
--- 1,26 ----
+ /*
+ ** Copyright 1998 - 2000 Double Precision, Inc.
+ ** See COPYING for distribution information.
+ */
+
+ #if HAVE_CONFIG_H
+ #include "config.h"
+ #endif
+ #include "numlib.h"
+ #include <string.h>
+
+ static const char rcsid[]="$Id: qmail-maildir++.patch,v 1.1.1.1.2.1 2005/01/19 23:35:23 tomcollins Exp $";
+
+ char *str_pid_t(pid_t t, char *arg)
+ {
+ char buf[NUMBUFSIZE];
+ char *p=buf+sizeof(buf)-1;
+
+ *p=0;
+ do
+ {
+ *--p= '0' + (t % 10);
+ t=t / 10;
+ } while(t);
+ return (strcpy(arg, p));
+ }
diff -crN ../qmail-1.03/strtimet.c ./strtimet.c
*** ../qmail-1.03/strtimet.c Wed Dec 31 18:00:00 1969
--- ./strtimet.c Mon Jun 10 13:25:46 2002
***************
*** 0 ****
--- 1,26 ----
+ /*
+ ** Copyright 1998 - 2000 Double Precision, Inc.
+ ** See COPYING for distribution information.
+ */
+
+ #if HAVE_CONFIG_H
+ #include "config.h"
+ #endif
+ #include "numlib.h"
+ #include <string.h>
+
+ static const char rcsid[]="$Id: qmail-maildir++.patch,v 1.1.1.1.2.1 2005/01/19 23:35:23 tomcollins Exp $";
+
+ char *str_time_t(time_t t, char *arg)
+ {
+ char buf[NUMBUFSIZE];
+ char *p=buf+sizeof(buf)-1;
+
+ *p=0;
+ do
+ {
+ *--p= '0' + (t % 10);
+ t=t / 10;
+ } while(t);
+ return (strcpy(arg, p));
+ }
--- Begin Message ---
- To: qmail@xxxxxxxxxxxxx
- Subject: QMAILQUEUE patch for qmail-1.03
- From: Bruce Guenter <bguenter-djb-qmail@xxxxxxxxx>
- Date: Mon, 25 Jan 1999 15:37:21 -0600
Greetings. Appended is a patch to qmail-1.03 that causes any program that would run qmail-queue to look for an environment variable QMAILQUEUE. If it is present, it is used in place of the string "bin/qmail-queue" when running qmail-queue. This could be used, for example, to add a program into the qmail-smtpd->qmail-queue pipeline that could do filtering, rewrite broken headers, etc. (this is my planned usage for it). This has undergone virtually no testing, but it looks so simple that it almost has to be correct. No warranties, etc. Note that the chdir to /var/qmail is always done before exec'ing the program. Does this look like a reasonable thing to do? -- Bruce Guenter, QCC Communications Corp. EMail: bruce.guenter@xxxxxxxxx Phone: (306)249-0220 WWW: http://www.qcc.sk.ca/~bguenter/ diff -u qmail-1.03-orig/Makefile qmail-1.03/Makefile --- qmail-1.03-orig/Makefile Mon Jun 15 04:53:16 1998 +++ qmail-1.03/Makefile Tue Jan 19 10:52:24 1999 @@ -1483,12 +1483,12 @@ trigger.o fmtqfn.o quote.o now.o readsubdir.o qmail.o date822fmt.o \ datetime.a case.a ndelay.a getln.a wait.a seek.a fd.a sig.a open.a \ lock.a stralloc.a alloc.a substdio.a error.a str.a fs.a auto_qmail.o \ -auto_split.o +auto_split.o env.a ./load qmail-send qsutil.o control.o constmap.o newfield.o \ prioq.o trigger.o fmtqfn.o quote.o now.o readsubdir.o \ qmail.o date822fmt.o datetime.a case.a ndelay.a getln.a \ wait.a seek.a fd.a sig.a open.a lock.a stralloc.a alloc.a \ - substdio.a error.a str.a fs.a auto_qmail.o auto_split.o + substdio.a error.a str.a fs.a auto_qmail.o auto_split.o env.a qmail-send.0: \ qmail-send.8 diff -u qmail-1.03-orig/qmail.c qmail-1.03/qmail.c --- qmail-1.03-orig/qmail.c Mon Jun 15 04:53:16 1998 +++ qmail-1.03/qmail.c Tue Jan 19 09:57:36 1999 @@ -6,14 +6,25 @@ #include "fd.h" #include "qmail.h" #include "auto_qmail.h" +#include "env.h" -static char *binqqargs[2] = { "bin/qmail-queue", 0 } ; +static char *binqqargs[2] = { 0, 0 } ; + +static void setup_qqargs() +{ + if(!binqqargs[0]) + binqqargs[0] = env_get("QMAILQUEUE"); + if(!binqqargs[0]) + binqqargs[0] = "bin/qmail-queue"; +} int qmail_open(qq) struct qmail *qq; { int pim[2]; int pie[2]; + + setup_qqargs(); if (pipe(pim) == -1) return -1; if (pipe(pie) == -1) { close(pim[0]); close(pim[1]); return -1; }
--- End Message ---
--- qregex.c-dist Fri Dec 28 02:08:05 2001
+++ qregex.c Tue Jan 29 18:57:44 2002
@@ -0,0 +1,57 @@
+/*
+ * qregex (v2)
+ * $Id: qregex.c,v 2.1 2001/12/28 07:05:21 evan Exp $
+ *
+ * Author : Evan Borgstrom (evan at unixpimps dot org)
+ * Created : 2001/12/14 23:08:16
+ * Modified: $Date: 2001/12/28 07:05:21 $
+ * Revision: $Revision: 2.1 $
+ *
+ * Do POSIX regex matching on addresses for anti-relay / spam control.
+ * It logs to the maillog
+ * See the qregex-readme file included with this tarball.
+ * If you didn't get this file in a tarball please see the following URL:
+ * http://www.unixpimps.org/software/qregex
+ *
+ * qregex.c is released under a BSD style copyright.
+ * See http://www.unixpimps.org/software/qregex/copyright.html
+ *
+ * Note: this revision follows the coding guidelines set forth by the rest of
+ * the qmail code and that described at the following URL.
+ * http://cr.yp.to/qmail/guarantee.html
+ *
+ */
+
+#include <sys/types.h>
+#include <regex.h>
+#include "qregex.h"
+
+#define REGCOMP(X,Y) regcomp(&X, Y, REG_EXTENDED)
+#define REGEXEC(X,Y) regexec(&X, Y, (size_t)0, (regmatch_t *)0, (int)0)
+
+int matchregex(char *text, char *regex) {
+ regex_t qreg;
+ int retval = 0;
+
+
+ /* build the regex */
+ if ((retval = REGCOMP(qreg, regex)) != 0) {
+ regfree(&qreg);
+ return(-retval);
+ }
+
+ /* execute the regex */
+ if ((retval = REGEXEC(qreg, text)) != 0) {
+ /* did we just not match anything? */
+ if (retval == REG_NOMATCH) {
+ regfree(&qreg);
+ return(0);
+ }
+ regfree(&qreg);
+ return(-retval);
+ }
+
+ /* signal the match */
+ regfree(&qreg);
+ return(1);
+}
--- qregex.h-dist Fri Dec 28 02:08:09 2001
+++ qregex.h Thu Dec 27 13:04:19 2001
@@ -0,0 +1,5 @@
+/* simple header file for the matchregex prototype */
+#ifndef _QREGEX_H_
+#define _QREGEX_H_
+int matchregex(char *text, char *regex);
+#endif
--- qmail-smtpd.c-dist Fri Dec 28 01:53:50 2001
+++ qmail-smtpd.c Tue Jan 29 18:43:09 2002
@@ -23,6 +23,10 @@
#include "timeoutread.h"
#include "timeoutwrite.h"
#include "commands.h"
+#include "qregex.h"
+
+#define BMCHECK_BMF 0
+#define BMCHECK_BMT 1
#define MAXHOPS 100
unsigned int databytes = 0;
@@ -49,7 +53,8 @@
void die_ipme() { out("421 unable to figure out my IP addresses (#4.3.0)\r\n"); flush(); _exit(1); }
void straynewline() { out("451 See http://pobox.com/~djb/docs/smtplf.html.\r\n"); flush(); _exit(1); }
-void err_bmf() { out("553 sorry, your envelope sender is in my badmailfrom list (#5.7.1)\r\n"); }
+void err_bmf() { out("553 sorry, your envelope sender has been denied (#5.7.1)\r\n"); }
+void err_bmt() { out("533 sorry, your envelope recipient has been denied (#5.7.1)\r\n"); }
void err_nogateway() { out("553 sorry, that domain isn't in my list of allowed rcpthosts (#5.7.1)\r\n"); }
void err_unimpl() { out("502 unimplemented (#5.5.1)\r\n"); }
void err_syntax() { out("555 syntax error (#5.5.4)\r\n"); }
@@ -93,10 +98,15 @@
int liphostok = 0;
stralloc liphost = {0};
+
int bmfok = 0;
stralloc bmf = {0};
struct constmap mapbmf;
+int bmtok = 0;
+stralloc bmt = {0};
+struct constmap mapbmt;
+
void setup()
{
char *x;
@@ -114,8 +124,11 @@
bmfok = control_readfile(&bmf,"control/badmailfrom",0);
if (bmfok == -1) die_control();
- if (bmfok)
- if (!constmap_init(&mapbmf,bmf.s,bmf.len,0)) die_nomem();
+ if (!constmap_init(&mapbmf,bmf.s,bmf.len,0)) die_nomem();
+
+ bmtok = control_readfile(&bmt,"control/badmailto",0);
+ if (bmtok == -1) die_control();
+ if (!constmap_init(&mapbmt,bmt.s,bmt.len,0)) die_nomem();
if (control_readint(&databytes,"control/databytes") == -1) die_control();
x = env_get("DATABYTES");
@@ -197,14 +210,38 @@
return 1;
}
-int bmfcheck()
+int bmcheck(which) int which;
{
- int j;
- if (!bmfok) return 0;
- if (constmap(&mapbmf,addr.s,addr.len - 1)) return 1;
- j = byte_rchr(addr.s,addr.len,'@');
- if (j < addr.len)
- if (constmap(&mapbmf,addr.s + j,addr.len - j - 1)) return 1;
+ int i = 0;
+ int j = 0;
+ int x = 0;
+ int negate = 0;
+ stralloc bmb = {0};
+ stralloc curregex = {0};
+
+ if (which == BMCHECK_BMF) {
+ if (!stralloc_copy(&bmb,&bmf)) die_nomem();
+ } else if (which == BMCHECK_BMT) {
+ if (!stralloc_copy(&bmb,&bmt)) die_nomem();
+ } else {
+ die_control();
+ }
+
+ while (j < bmb.len) {
+ i = j;
+ while ((bmb.s[i] != '\0') && (i < bmb.len)) i++;
+ if (bmb.s[j] == '!') {
+ negate = 1;
+ j++;
+ }
+ stralloc_copyb(&curregex,bmb.s + j,(i - j));
+ stralloc_0(&curregex);
+ x = matchregex(addr.s, curregex.s);
+ if ((negate) && (x == 0)) return 1;
+ if (!(negate) && (x > 0)) return 1;
+ j = i + 1;
+ negate = 0;
+ }
return 0;
}
@@ -218,7 +255,8 @@
int seenmail = 0;
-int flagbarf; /* defined if seenmail */
+int flagbarfbmf; /* defined if seenmail */
+int flagbarfbmt;
stralloc mailfrom = {0};
stralloc rcptto = {0};
@@ -240,7 +278,7 @@
void smtp_mail(arg) char *arg;
{
if (!addrparse(arg)) { err_syntax(); return; }
- flagbarf = bmfcheck();
+ if (bmfok) flagbarfbmf = bmcheck(BMCHECK_BMF);
seenmail = 1;
if (!stralloc_copys(&rcptto,"")) die_nomem();
if (!stralloc_copys(&mailfrom,addr.s)) die_nomem();
@@ -250,7 +288,9 @@
void smtp_rcpt(arg) char *arg; {
if (!seenmail) { err_wantmail(); return; }
if (!addrparse(arg)) { err_syntax(); return; }
- if (flagbarf) { err_bmf(); return; }
+ if ((!flagbarfbmf) && (bmtok)) { flagbarfbmt = bmcheck(BMCHECK_BMT); }
+ if (flagbarfbmf) { err_bmf(); return; }
+ if (flagbarfbmt) { err_bmt(); return; }
if (relayclient) {
--addr.len;
if (!stralloc_cats(&addr,relayclient)) die_nomem();
--- Makefile-dist Mon Jun 15 06:53:16 1998
+++ Makefile Thu Dec 27 14:16:02 2001
@@ -1532,12 +1532,12 @@
./compile qmail-showctl.c
qmail-smtpd: \
-load qmail-smtpd.o rcpthosts.o commands.o timeoutread.o \
+load qmail-smtpd.o rcpthosts.o qregex.o commands.o timeoutread.o \
timeoutwrite.o ip.o ipme.o ipalloc.o control.o constmap.o received.o \
date822fmt.o now.o qmail.o cdb.a fd.a wait.a datetime.a getln.a \
open.a sig.a case.a env.a stralloc.a alloc.a substdio.a error.a str.a \
fs.a auto_qmail.o socket.lib
- ./load qmail-smtpd rcpthosts.o commands.o timeoutread.o \
+ ./load qmail-smtpd qregex.o rcpthosts.o commands.o timeoutread.o \
timeoutwrite.o ip.o ipme.o ipalloc.o control.o constmap.o \
received.o date822fmt.o now.o qmail.o cdb.a fd.a wait.a \
datetime.a getln.a open.a sig.a case.a env.a stralloc.a \
@@ -1680,6 +1680,10 @@
compile rcpthosts.c cdb.h uint32.h byte.h open.h error.h control.h \
constmap.h stralloc.h gen_alloc.h rcpthosts.h
./compile rcpthosts.c
+
+qregex.o: \
+compile qregex.c qregex.h
+ ./compile qregex.c
readsubdir.o: \
compile readsubdir.c readsubdir.h direntry.h fmt.h scan.h str.h \
--- TARGETS-dist Mon Jun 15 06:53:16 1998
+++ TARGETS Thu Dec 27 14:16:19 2001
@@ -252,6 +252,7 @@
qmail-qmtpd
qmail-smtpd.o
qmail-smtpd
+qregex.o
sendmail.o
sendmail
tcp-env.o
--- README.qregex-dist Fri Dec 28 01:53:13 2001
+++ README.qregex Fri Dec 28 01:48:28 2001
@@ -0,0 +1,110 @@
+QREGEX (v2) - README [12/28/01]
+A Regular Expression matching patch for qmail 1.03
+
+
+OVERVIEW:
+
+qregex adds the ability to match address evelopes via Regular Expressions (REs)
+in the qmail-smtpd process. It has the abiltiy to match both `mail from` and
+`rcpt to` commands with no load at all the parent process. It follows all the
+base rules that are set out with qmail (ie using control files) so it makes for
+easy integretion into an existing setup (see the install instructions for more info).
+The v2 noting is because qregex was re-written to better conform to the security
+gaurantee set forth by the author. The original version used stdio.h and stdlib.h
+for reading the control files where as v2 now uses all stralloc functions which
+are much more regulated against buffer overruns and the likes.
+See: http://cr.yp.to/qmail/guarantee.html
+
+
+
+PLATFORMS:
+
+qregex has been built and tested on the following platforms. I'm sure it won't have
+any problems on any platform that qmail will run on (providing they provide a regex
+interface) but if you run into problems let me know.
+
+ - Solaris 2.7 (7, SunOS 5.7)
+ - Solaris 2.8 (8, SunOS 5.8)
+ - OpenBSD 2.8
+ - OpenBSD 2.9
+ - FreeBSD 4.3-RELEASE
+ - FreeBSD 5.0-CURRENT
+ - Linux
+
+
+
+INSTALLATION INSTRUCTIONS:
+
+Installation is very simple, there is only one requirement. You need to use the GNU
+version of the patch utility (http://www.gnu.org/software/patch/patch.html).
+(For Solaris 8 users like me it is installed as 'gpatch')
+
+- If this is a new setup.
+Uncompress and untar the qmail archive, copy the 'qregex.patch' file into the new
+qmail-1.03 directory and run "patch < qregex.patch"
+Follow the instructions as per the included qmail INSTALL file.
+Once you are done come back to this file and read the section on the control files.
+
+- If this is an existing setup.
+FIRST: create your control files (see below).
+Copy the 'qregex.patch' file into your existing qmail source directory.
+Run "patch < qregex.patch" then "make qmail-smtpd". Now run ./qmail-smtpd and test
+your new rules to make sure they work as expected.
+
+Install the new binary by cd'ing to /var/qmail/bin and as root (in one command)
+copy the existing binary to 'qmail-smtpd.old' and copy the new binary from the
+source directory to 'qmail-smtpd'.
+(ex. cp qmail-smtpd qmail-smtpd.old && cp ~/qmail-1.03/qmail-smtpd qmail-smtpd)
+
+
+
+CONTROL FILES:
+
+qregex provides you with two new control files.
+The first (which really isn't new) is "control/badmailfrom". This file used to be
+used to statically match addresses and now will contain your REs for matching from
+the 'mail from' command.
+The second is "control/badmailto", it is the exact same as the first except it matches
+against the 'rcpt to' command.
+
+If you prefer you can symlink the two files (ln -s badmailfrom badmailto) and only
+need to maintain one set of rules. Beware this might cause problems in certian
+setups.
+
+ Here's an example "badmailfrom" file.
+ -----------------------------------
+ # drop everything containing the word spam
+ .*spam.*
+ # force users to fully qualify themselves (ie deny "user", accept "user@domain")
+ !@
+ -----------------------------------
+
+ And "badmailto" (a litte more interesting)
+ -----------------------------------
+ # must not contain invalid characters, brakets or multiple @'s
+ [\W\D!%#:\*\^]
+ [\(\)]
+ [\{\}]
+ @.*@
+ -----------------------------------
+
+Also you can use the non-RE character '!' to start a RE to signal to qregex to negate the
+action. As used above in the badmailfrom file, by negating the @ symbol qregex will signal
+qmail-smtpd to deny the 'mail from' command whenever the address doesn't contain an @ symbol.
+
+
+INTERNALS:
+
+qregex (or regexmatch as the function is called) will be called during both the
+`rcpt to` and `mail from` handling routenes in "qmail-smtpd.c". When called it will
+read the proper control file then one by one compile and execute the regex on the
+envelope passed into qmail-smtpd. If the regex matches it returns TRUE (1) and the
+qmail-smtpd process will deny the user the ability to continue.
+If you change anything and think it betters this patch please send me a new diff file
+so I can take a peek.
+
+
+CONTACT:
+All comments/questions/critisim welcomed...
+ www : http://www.unixpimps.org/software/qregex
+ email: evan at unixpimps dot org
--- qmail-smtpd.c.orig Mon Jan 26 16:53:54 2004
+++ qmail-smtpd.c Mon Jan 26 16:57:35 2004
@@ -57,6 +57,7 @@
void err_bmt() { out("533 sorry, your envelope recipient has been denied (#5.7.1)\r\n"); }
void err_nogateway() { out("553 sorry, that domain isn't in my list of allowed rcpthosts (#5.7.1)\r\n"); }
void err_unimpl() { out("502 unimplemented (#5.5.1)\r\n"); }
+void err_size() { out("552 sorry, that message size exceeds my databytes limit (#5.3.4)\r\n"); }
void err_syntax() { out("555 syntax error (#5.5.4)\r\n"); }
void err_wantmail() { out("503 MAIL first (#5.5.1)\r\n"); }
void err_wantrcpt() { out("503 RCPT first (#5.5.1)\r\n"); }
@@ -210,6 +211,40 @@
return 1;
}
+int sizelimit(arg)
+char *arg;
+{
+ int i;
+ long r;
+ unsigned long sizebytes = 0;
+
+ i = str_chr(arg,'<');
+ if (arg[i])
+ arg += i + 1;
+ else {
+ arg += str_chr(arg,':');
+ if (*arg == ':') ++arg;
+ while (*arg == ' ') ++arg;
+ }
+
+ arg += str_chr(arg,' ');
+ if (*arg == ' ') while (*arg == ' ') ++arg;
+ else return 1;
+
+ i = str_chr(arg,'=');
+ arg[i] = 0;
+ if (case_equals(arg,"SIZE")) {
+ arg += i;
+ while (*++arg && *arg > 47 && *arg < 58) {
+ sizebytes *= 10;
+ sizebytes += *arg - 48;
+ }
+ r = databytes - sizebytes;
+ if (r < 0) return 0;
+ }
+ return 1;
+}
+
int bmcheck(which) int which;
{
int i = 0;
@@ -265,9 +300,16 @@
smtp_greet("250 "); out("\r\n");
seenmail = 0; dohelo(arg);
}
+char size_buf[FMT_ULONG];
+void smtp_size()
+{
+ size_buf[fmt_ulong(size_buf,(unsigned long) databytes)] = 0;
+ out("250 SIZE "); out(size_buf); out("\r\n");
+}
void smtp_ehlo(arg) char *arg;
{
- smtp_greet("250-"); out("\r\n250-PIPELINING\r\n250 8BITMIME\r\n");
+ smtp_greet("250-"); out("\r\n250-PIPELINING\r\n250-8BITMIME\r\n");
+ smtp_size();
seenmail = 0; dohelo(arg);
}
void smtp_rset()
@@ -279,6 +321,7 @@
{
if (!addrparse(arg)) { err_syntax(); return; }
if (bmfok) flagbarfbmf = bmcheck(BMCHECK_BMF);
+ if (databytes && !sizelimit(arg)) { err_size(); return; }
seenmail = 1;
if (!stralloc_copys(&rcptto,"")) die_nomem();
if (!stralloc_copys(&mailfrom,addr.s)) die_nomem();
Attachment:
signature.asc
Description: This is a digitally signed message part