diff -ruN qmail-1.03-orig/alloc.c qmail-1.03-ldap-20060201-orig/alloc.c
--- qmail-1.03-orig/alloc.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/alloc.c	2006-02-25 11:00:55.000000000 +0100
@@ -1,32 +1,18 @@
+#include <stdlib.h>
 #include "alloc.h"
 #include "error.h"
-extern char *malloc();
-extern void free();
 
-#define ALIGNMENT 16 /* XXX: assuming that this alignment is enough */
-#define SPACE 4096 /* must be multiple of ALIGNMENT */
-
-typedef union { char irrelevant[ALIGNMENT]; double d; } aligned;
-static aligned realspace[SPACE / ALIGNMENT];
-#define space ((char *) realspace)
-static unsigned int avail = SPACE; /* multiple of ALIGNMENT; 0<=avail<=SPACE */
-
-/*@null@*//*@out@*/char *alloc(n)
+/*@null@*//*@out@*/void *alloc(n)
 unsigned int n;
 {
-  char *x;
-  n = ALIGNMENT + n - (n & (ALIGNMENT - 1)); /* XXX: could overflow */
-  if (n <= avail) { avail -= n; return space + avail; }
+  void *x;
   x = malloc(n);
   if (!x) errno = error_nomem;
   return x;
 }
 
 void alloc_free(x)
-char *x;
+void *x;
 {
-  if (x >= space)
-    if (x < space + SPACE)
-      return; /* XXX: assuming that pointers are flat */
   free(x);
 }
diff -ruN qmail-1.03-orig/alloc.h qmail-1.03-ldap-20060201-orig/alloc.h
--- qmail-1.03-orig/alloc.h	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/alloc.h	2006-02-25 11:00:55.000000000 +0100
@@ -1,8 +1,8 @@
 #ifndef ALLOC_H
 #define ALLOC_H
 
-extern /*@null@*//*@out@*/char *alloc();
-extern void alloc_free();
-extern int alloc_re();
+extern /*@null@*//*@out@*/void *alloc(unsigned int);
+extern void alloc_free(void *);
+extern int alloc_re(char **, unsigned int, unsigned int);
 
 #endif
diff -ruN qmail-1.03-orig/auth_imap.c qmail-1.03-ldap-20060201-orig/auth_imap.c
--- qmail-1.03-orig/auth_imap.c	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/auth_imap.c	2006-02-25 11:00:55.000000000 +0100
@@ -0,0 +1,354 @@
+/*
+ * Copyright (c) 2000-2004 Claudio Jeker,
+ *      Internet Business Solutions AG, CH-8005 Zürich, Switzerland
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Internet Business
+ *      Solutions AG and its contributors.
+ * 4. Neither the name of the author nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+/* auth_imap.c for courier-imap */
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <errno.h>
+#include <unistd.h>
+#include "alloc.h"
+#include "byte.h"
+#include "env.h"
+#include "error.h"
+#include "exit.h"
+#include "fmt.h"
+#include "pbsexec.h"
+#include "qldap-debug.h"
+#include "qldap-errno.h"
+#include "qmail-ldap.h"
+#include "readwrite.h"
+#include "scan.h"
+#include "sgetopt.h"
+#include "sig.h"
+#include "str.h"
+#include "stralloc.h"
+#include "substdio.h"
+#include "timeoutread.h"
+
+#include "auth_mod.h"
+
+#ifndef PORT_IMAP /* this is for testing purposes */
+#define PORT_IMAP	143
+#endif
+
+const unsigned int auth_port = PORT_IMAP;
+
+#define UP_LEN 1024
+static char auth_up[UP_LEN];
+static unsigned int auth_uplen;
+static int auth_argc;
+static char **auth_argv;
+
+void
+auth_init(int argc, char **argv, stralloc *login, stralloc *authdata)
+{
+	char		*a, *s, *t, *l, *p;
+	int		 waitstat, opt, n;
+	unsigned int	 u;
+
+	while ((opt = getopt(argc, argv, "d:")) != opteof) {
+		switch (opt) {
+		case 'd':
+			pbstool = optarg;
+			break;
+		default:
+			auth_error(AUTH_CONF);
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	if (argc < 1)
+		auth_error(AUTH_CONF);
+	auth_argc = argc;
+	auth_argv = argv;
+
+	a = env_get("AUTHENTICATED");
+	if (a && *a) {  /* Already a good guy */
+		logit(8, "auth_init: allready authenticated\n");
+		execvp(*argv, argv);
+		auth_error(AUTH_EXEC);
+	}
+	
+#if 1
+	/*
+	 * remove all zombies, why should I do that?
+	 * Because courier makes zombies for breakfast
+	 */
+	sig_childdefault();
+	while (wait(&waitstat) >= 0) ;
+#endif
+	for (auth_uplen = 0;;) {
+		do {
+			n = read(3, auth_up + auth_uplen,
+			    sizeof(auth_up) - auth_uplen);
+		} while ((n == -1) && (errno == EINTR));
+		if (n == -1)
+			auth_error(ERRNO);
+		if (n == 0) break;
+		auth_uplen += n;
+		if (auth_uplen >= sizeof(auth_up)) {
+			auth_error(PANIC);
+		}
+	}
+	close(3);
+	auth_up[auth_uplen] = '\0';
+	
+	/*
+	 * get the different fields: service<NL>AUTHTYPE<NL>AUTHDATA
+	 */
+	u = 0;
+	s = auth_up; /* ignore service field */
+	while (auth_up[u] && auth_up[u] != '\n' ) u++;
+	if (u >= auth_uplen)
+		auth_error(NEEDED);
+	auth_up[u++] = '\0';
+	t = auth_up + u; /* type has to be "login" else fail ... */
+	while (auth_up[u] && auth_up[u] != '\n' ) u++;
+	if (u >= auth_uplen)
+		auth_error(NEEDED);
+	auth_up[u++] = '\0';
+	if (str_diff("login", t)) {
+		/* 
+		 * this modul supports only "login"-type,
+		 * fail with AUTH_TYPE, so the 
+		 * next modul is called, perhaps with greater success
+		 */
+		auth_fail("unknown", AUTH_TYPE);
+	}
+	l = auth_up + u; /* next login */
+	while (auth_up[u] && auth_up[u] != '\n' ) u++;
+	if (u >= auth_uplen)
+		auth_error(NEEDED);
+	auth_up[u++] = '\0';
+	p = auth_up + u; /* and the password */
+	while (auth_up[u] && auth_up[u] != '\n' ) u++;
+	if (u >= auth_uplen)
+		auth_error(NEEDED);
+	auth_up[u++] = '\0';
+	if (u > auth_uplen) /* paranoia */
+		auth_error(NEEDED);
+
+	/* copy the login and password into the coresponding structures */
+	if (!stralloc_copys(login, l))
+		auth_error(ERRNO);
+	if (!stralloc_0(login))
+		auth_error(ERRNO);
+
+	if (!stralloc_copys(authdata, p))
+		auth_error(ERRNO);
+	if (!stralloc_0(authdata))
+		auth_error(ERRNO);
+}
+
+void
+auth_fail(const char *login, int reason)
+{
+	unsigned int	 i;
+	int		 pi[2], n;
+	char		*t = auth_up;
+	
+	logit(2, "warning: auth_fail: user %s failed\n", login);
+	if (reason == NOSUCH || reason == AUTH_TYPE) {
+		logit(4, "warning: auth_fail: %s\n", qldap_err_str(reason));
+		if (!env_unset("AUTHENTICATED"))
+			auth_error(ERRNO);
+		for (i=0; i < auth_uplen; i++)
+			if (!auth_up[i])
+				auth_up[i] = '\n';
+		close(3);
+		if (pipe(pi) == -1)
+			auth_error(ERRNO);
+		if (pi[0] != 3) /* be serious, we closed 3 so ... */
+			auth_error(PANIC);
+		switch (fork()) {
+		case -1:
+			auth_error(ERRNO);
+		case 0:
+			break;
+		default: /* parent process */
+			close(pi[1]);
+			sig_pipedefault();
+			/* start next auth module */
+			execvp(*auth_argv, auth_argv);
+			auth_error(AUTH_EXEC);
+		}
+		/* child process */
+		close(pi[0]);
+		while (auth_uplen) {
+			n = subwrite(pi[1],t,auth_uplen);
+			if (n == -1) {
+				if (errno == error_intr) continue;
+				/* note that some data may have been written */
+			}
+			t += n;
+			auth_uplen -= n;
+		}
+		byte_zero(auth_up, sizeof(auth_up));
+		close(pi[1]);
+		_exit(0);
+	}
+	auth_error(reason); /* complete failure */
+}
+
+void
+auth_success(const char *login)
+{
+	byte_zero(auth_up, sizeof(auth_up));
+	
+	/* pop befor smtp */
+	pbsexec();
+	
+	/* start imap process */
+	execvp(*auth_argv, auth_argv);
+
+	auth_error(AUTH_EXEC);
+	/* end */
+}
+
+void auth_error(int errnum)
+{
+	char envname[FMT_ULONG+8];
+	char *env, *n, *n2;
+	char **argvs;
+	unsigned long numarg, i;
+	
+	/* XXX under courier-imap it is not simple to give the correct failure
+	 * XXX back to the user, perhaps somebody has a good idea */
+
+	byte_zero(auth_up, sizeof(auth_up));
+	
+	logit(2, "warning: auth_error: authorization failed (%s)\n",
+		   qldap_err_str(errnum));
+	if (!(env = env_get("AUTHARGC")))
+		_exit(111);
+	scan_ulong(env, &numarg);
+	argvs = (char **) alloc((numarg+1) * sizeof(char *));
+	n = envname;
+	n += fmt_str(n, "AUTHARGV");
+	for (i = 0; i < numarg; i++) {
+		n2 = n;
+		n2 += fmt_ulong(n2, i);
+		*n2 = 0;
+		if (!(argvs[i] = env_get(envname)))
+			_exit(111);
+	}
+	argvs[i+1] = (char *)0;
+#if 0
+	/*
+	 * can no longer find AUTHUSER in authlib(7) of courier-imap 1.7.2
+	 * but it still exists. So what should I do? Drop my pants?
+	 */
+	if (!(env = env_get("AUTHUSER")))
+		_exit(100);
+#endif
+	execv(*argvs, argvs);
+	_exit(111);
+	
+}
+
+char *
+auth_aliasempty(void)
+{
+	if (auth_argc > 0)
+		return auth_argv[auth_argc-1];
+	return (char *)0;
+}
+
+#ifdef QLDAP_CLUSTER
+static void get_ok(int , const char *);
+
+static void
+get_ok(int fd, const char *tag)
+/* get the ok for the next command, wait for "[TAG] OK.*\r\n" */
+/* This should work (Idea from RFC 1730 and fetchmail) */
+{
+#define AUTH_TIMEOUT 10 /* 10 sec timeout */
+#define OK_LEN 8192+1
+	char ok[OK_LEN];
+	char *s;
+	unsigned char x;
+	int  len;
+	int  i;
+
+	if (!tag) return; /* bad pointer */
+	do {
+		len = timeoutread(AUTH_TIMEOUT, fd, ok, sizeof(ok) - 1);
+		if (len == -1)
+			auth_error(ERRNO);
+		ok[len] = '\0';
+		/* upper case all */
+		for (i = 0, s = ok; i < len; i++) {
+			x = *s - 'a';
+			if ( x <= 'z' - 'a' ) *s = x + 'A';
+			s++;
+		}
+	} while (str_diffn(ok, tag, str_len(tag)));
+	/* tag found, next check for OK */
+	s = ok + str_len(tag); /* skip tag */
+	while (*s == ' ' || *s == '\t') s++; /* skip all spaces */
+	
+	if (str_diffn(s, "OK", 2) == 0 ) return;
+	else if (str_diffn(s, "BAD", 3) == 0 || str_diffn(s, "NO", 2) == 0)
+		/* other server not happy */
+		auth_error(BADCLUSTER);
+	/* ARRG, this server talks not my dialect */
+	auth_error(BADCLUSTER);
+}
+
+void
+auth_forward(int fd, char *login, char *passwd)
+{
+	char *tag;
+	substdio ss;
+	char buf[512];
+	
+	tag = env_get("IMAPLOGINTAG");
+	if (!(tag && *tag))
+		/* UH OH, no imap tag, how could that be ? */
+		auth_error(PANIC);
+	
+	get_ok(fd, "*");
+	substdio_fdbuf(&ss,subwrite,fd,buf,sizeof(buf));
+	substdio_puts(&ss, tag);
+	substdio_puts(&ss, " login "); 
+	substdio_puts(&ss, login); 
+	substdio_puts(&ss, " ");
+	substdio_puts(&ss, passwd); 
+	substdio_puts(&ss, "\r\n");
+	substdio_flush(&ss);
+}
+
+#endif /* QLDAP_CLUSTER */
+
diff -ruN qmail-1.03-orig/auth_mod.c qmail-1.03-ldap-20060201-orig/auth_mod.c
--- qmail-1.03-orig/auth_mod.c	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/auth_mod.c	2006-02-25 11:00:55.000000000 +0100
@@ -0,0 +1,392 @@
+/*
+ * Copyright (c) 2003-2004 Claudio Jeker,
+ *      Internet Business Solutions AG, CH-8005 Zürich, Switzerland
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Internet Business
+ *      Solutions AG and its contributors.
+ * 4. Neither the name of the author nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#include <sys/types.h>
+#include <unistd.h>
+#include "alloc.h"
+#include "byte.h"
+#include "error.h"
+#include "localdelivery.h"
+#include "locallookup.h"
+#include "output.h"
+#include "pbsexec.h"
+#include "qldap.h"
+#include "qldap-debug.h"
+#include "qldap-errno.h"
+#include "read-ctrl.h"
+#include "readwrite.h"
+#include "stralloc.h"
+#ifdef QLDAP_CLUSTER
+#include <sys/socket.h>
+#include "dns.h"
+#include "ipalloc.h"
+#include "ipme.h"
+#include "ndelay.h"
+#include "qldap-cluster.h"
+#include "select.h"
+#include "timeoutconn.h"
+#endif
+#ifdef AUTOHOMEDIRMAKE
+#include "dirmaker.h"
+#endif
+#ifdef AUTOMAILDIRMAKE
+#include "mailmaker.h"
+#endif
+
+
+#include "checkpassword.h"
+#include "auth_mod.h"
+
+stralloc	loginstr = {0};
+stralloc	authdatastr = {0};
+
+ctrlfunc	ctrls[] = {
+		qldap_ctrl_login,
+		qldap_ctrl_generic,
+		localdelivery_init,
+#ifdef QLDAP_CLUSTER
+		cluster_init,
+#endif
+#ifdef AUTOHOMEDIRMAKE
+		dirmaker_init,
+#endif		
+		0 };
+
+checkfunc	cfuncs[] = {
+	check_ldap,
+	check_passwd,
+	0
+};
+
+void chdir_or_make(char *, char *);
+
+#ifdef QLDAP_CLUSTER
+void forward(char *, char *, struct credentials *);
+#endif
+
+int
+main(int argc, char **argv)
+{
+	struct	credentials c;
+	int r;
+
+	log_init(STDERR, ~256, 0);	/* XXX limited so that it is not
+					   possible to get passwords via 
+					   debug on production systems.
+					 */
+	if (read_controls(ctrls) == -1)
+		auth_error(AUTH_CONF);
+
+	auth_init(argc, argv, &loginstr, &authdatastr);
+	logit(256, "auth_init: login=%s, authdata=%s\n",
+	    loginstr.s, authdatastr.s);
+
+	if (authdatastr.len <= 1) {
+		logit(1, "alert: null password.\n");
+		auth_fail(loginstr.s, BADPASS);
+	}
+	
+	byte_zero(&c, sizeof(c));
+	r = check(cfuncs, &loginstr, &authdatastr, &c, 0);
+	switch (r) {
+	case OK:
+		/* authdata no longer needed */
+		byte_zero(authdatastr.s, authdatastr.len);
+		change_uid(c.uid, c.gid);
+		setup_env(loginstr.s, &c);
+		chdir_or_make(c.home.s, c.maildir.s);
+		auth_success(loginstr.s);
+	case FORWARD:
+#ifdef QLDAP_CLUSTER
+		change_uid(-1, -1);
+		setup_env(loginstr.s, &c);
+		forward(loginstr.s, authdatastr.s, &c);
+		/* does not return */
+#else
+		/* authdata no longer needed */
+		byte_zero(authdatastr.s, authdatastr.len);
+		/* system error, now way out ... module likes to forward
+		   but we don't have support for it. */
+		auth_error(r);
+#endif
+	case NOSUCH: /* FALLTHROUGH */
+	case BADPASS:
+		/* authdata no longer needed */
+		byte_zero(authdatastr.s, authdatastr.len);
+		auth_fail(loginstr.s, r);
+	default:
+		/* authdata no longer needed */
+		byte_zero(authdatastr.s, authdatastr.len);
+		/* system error, now way out ... */
+		auth_error(r);
+	}
+		
+	auth_error(PANIC);
+	return 1; /* should never get here */
+}
+
+void
+chdir_or_make(char *home, char *maildir)
+{
+	char	*md;
+
+	if (maildir == (char *)0 || *maildir == '\0')
+		md = auth_aliasempty();
+	else
+		md = maildir;
+
+	/* ... go to home dir and create it if needed */
+	if (chdir(home) == -1) {
+#ifdef AUTOHOMEDIRMAKE
+		logit(8, "makeing homedir for %s %s\n", home, md);
+
+		switch (dirmaker_make(home, md)) {
+		case OK:
+			break;
+		case MAILDIR_CRASHED:
+			logit(2, "warning: dirmaker failed: program crashed\n");
+			auth_error(MAILDIR_FAILED);
+		case MAILDIR_FAILED:
+			logit(2, "warning: dirmaker failed: bad exit status\n");
+			auth_error(MAILDIR_FAILED);
+		case MAILDIR_UNCONF:
+			logit(2, "warning: dirmaker failed: not configured\n");
+			auth_error(MAILDIR_NONEXIST);
+		case MAILDIR_HARD:
+			logit(2, "warning: dirmaker failed: hard error\n");
+		case ERRNO:
+		default:
+			logit(2, "warning: dirmaker failed (%s)\n",
+			    error_str(errno));
+			auth_error(MAILDIR_FAILED);
+		}
+		if (chdir(home) == -1) {
+			logit(2, "warning: 2nd chdir failed: %s\n",
+			    error_str(errno));
+			auth_error(MAILDIR_FAILED);
+		}
+		logit(32, "homedir successfully made\n");
+#else
+		logit(2, "warning: chdir failed: %s\n", error_str(errno));
+		auth_error(MAILDIR_NONEXIST);
+#endif
+	}
+#ifdef AUTOMAILDIRMAKE
+	switch (maildir_make(md)) {
+	case OK:
+		break;
+	case MAILDIR_CORRUPT:
+		logit(2, "warning: maildir_make failed (%s)\n",
+		    "maildir seems to be corrupt");
+		auth_error(MAILDIR_CORRUPT);
+	case ERRNO:
+	default:
+		logit(2, "warning: maildir_make failed (%s)\n",
+		    error_str(errno));
+		auth_error(MAILDIR_FAILED);
+	}
+#endif
+}
+
+#ifdef QLDAP_CLUSTER
+#define COPY_BUF_SIZE	8192
+static void copyloop(int, int, int, int);
+
+static void
+copyloop(int infdr, int infdw, int outfd, int timeout)
+{
+	fd_set	rfds, wfds;
+	struct	timeval tv;
+	int	maxfd;	/* Maximum numbered fd used */
+	int	r, inpos = 0, outpos = 0;
+	int	inok = 1, outok = 1;
+	char	*inbuf, *outbuf;
+
+	inbuf = alloc(COPY_BUF_SIZE);
+	outbuf = alloc(COPY_BUF_SIZE);
+
+	if (inbuf == (char *)0 || outbuf == (char *)0) {
+		logit(1, "copyloop: %s\n", error_str(errno));
+		close(infdr);
+		close(infdw);
+		close(outfd);
+		return;
+	}
+
+	maxfd = infdr > infdw ? infdr : infdw;
+	maxfd = (maxfd > outfd ? maxfd : outfd) + 1;
+
+	while (1) {
+		/* file descriptor bits */
+		FD_ZERO(&rfds);
+		FD_ZERO(&wfds);
+		if (inok && inpos < COPY_BUF_SIZE)
+			FD_SET(infdr, &rfds);
+		if (outpos != 0)
+			FD_SET(infdw, &wfds);
+		if (outok && outpos < COPY_BUF_SIZE)
+			FD_SET(outfd, &rfds);
+		if (inpos != 0)
+			FD_SET(outfd, &wfds);
+
+		/* Set up timeout */
+		tv.tv_sec = timeout;
+		tv.tv_usec = 0;
+
+		r = select(maxfd, &rfds, &wfds, (fd_set *)0, &tv);
+		if (r == -1) {
+			logit(1, "copyloop: select: %s\n",
+			    error_str(errno));
+			break;
+		} else if (r == 0) {
+			logit(32, "copyloop: select timeout\n");
+			break;
+		}
+
+		if (FD_ISSET(infdr, &rfds)) {
+			if ((r = subread(infdr, inbuf + inpos,
+			    COPY_BUF_SIZE - inpos)) == -1) {
+				if (errno == error_intr) continue;
+				logit(1, "copyloop: read: %s\n",
+				    error_str(errno));
+				break;
+			}
+			if (r == 0)
+				inok = 0;
+			inpos += r;
+		}
+		if (FD_ISSET(outfd, &rfds)) {
+			if ((r = subread(outfd, outbuf + outpos,
+			    COPY_BUF_SIZE - outpos)) == -1) {
+				if (errno == error_intr) continue;
+				logit(1, "copyloop: read: %s\n",
+				    error_str(errno));
+				break;
+			}
+			if (r == 0)
+				outok = 0;
+			outpos += r;
+		}
+		if (FD_ISSET(infdw, &wfds)) {
+			if ((r = subwrite(infdw, outbuf, outpos)) == -1) {
+				if (errno == error_intr) continue;
+				logit(1, "copyloop: write: %s\n",
+				    error_str(errno));
+				break;
+			}
+			if (r != outpos)
+				byte_copy(outbuf, outpos - r, outbuf + r);
+			outpos -= r;
+		}
+		if (FD_ISSET(outfd, &wfds)) {
+			if ((r = subwrite(outfd, inbuf, inpos)) == -1) {
+				if (errno == error_intr) continue;
+				logit(1, "copyloop: write: %s\n",
+				    error_str(errno));
+				break;
+			}
+			if (r != inpos)
+				byte_copy(inbuf, inpos - r, inbuf + r);
+			inpos -= r;
+		}
+
+		if (inok == 0 && inpos == 0)
+			/* half close forwarding channel */
+			shutdown(outfd, SHUT_WR);
+
+		if (outpos == 0 && outok == 0)
+			/*
+			 * Can not half close channel to client so finish the
+			 * communication. Server is no longer intrested anyway.
+			 */
+			break;
+	}
+
+	close(infdr);
+	close(infdw);
+	close(outfd);
+}
+
+void
+forward(char *name, char *passwd, struct credentials *c)
+{
+	struct	ip_address outip;
+	ipalloc	ip = {0};
+	int	ffd;
+	int	timeout = 31*60; /* ~30 min timeout RFC1730 */
+	int	ctimeout = 30;
+	
+	/* pop befor smtp */
+	pbsexec();
+
+	if (!ip_scan("0.0.0.0", &outip))
+		auth_error(ERRNO);
+
+	dns_init(0);
+	switch (dns_ip(&ip,&c->forwarder)) {
+		case DNS_MEM:
+			auth_error(ERRNO);
+		case DNS_SOFT:
+		case DNS_HARD:
+			auth_error(BADCLUSTER);
+		case 1:
+			if (ip.len <= 0)
+				auth_error(BADCLUSTER);
+	}
+	/* 
+	   20010523 Don't check if only one IP is returned, so it is
+	   possible to have a cluster node consisting of multiple machines. 
+	   XXX If your mailhost is bad (bad entries in ldap) you will get
+	   bad loops, the only limit is the tcpserver concurrency limit.
+	   20030627 Could we use the ipme stuff of qmail-remote, to make
+	   single hop loops impossible? Let's try it.
+	 */
+	if (ipme_is(&ip.ix[0].ip) == 1)
+		auth_error(BADCLUSTER);
+
+	ffd = socket(AF_INET, SOCK_STREAM, 0);
+	if (ffd == -1)
+		auth_error(ERRNO);
+	
+	if (timeoutconn(ffd, &ip.ix[0].ip, &outip, auth_port, ctimeout) != 0)
+		auth_error(ERRNO);
+	
+	/* We have a connection, first send user and pass */
+	auth_forward(ffd, name, passwd);
+	copyloop(0, 1, ffd, timeout);
+
+	_exit(0); /* all went ok, exit normaly */
+}
+
+#endif /* QLDAP_CLUSTER */
+
diff -ruN qmail-1.03-orig/auth_mod.h qmail-1.03-ldap-20060201-orig/auth_mod.h
--- qmail-1.03-orig/auth_mod.h	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/auth_mod.h	2006-02-25 11:00:55.000000000 +0100
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2000-2004 Claudio Jeker,
+ *      Internet Business Solutions AG, CH-8005 Zürich, Switzerland
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Internet Business
+ *      Solutions AG and its contributors.
+ * 4. Neither the name of the author nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#ifndef __AUTH_MOD_H__
+#define __AUTH_MOD_H__
+
+#include "stralloc.h"
+
+extern const unsigned int auth_port;
+
+/* 
+ * auth_init must return the 0-terminated strings login and authdata.
+ * possible arguments should be parsed and the argument for auth_success
+ * need to be stored if later needed.
+ */
+void auth_init(int, char **, stralloc *, stralloc *);
+
+/*
+ * Checks if it was a hard fail (bad password) or just a soft error 
+ * (user not found). May start an other auth_module. MAY NOT return.
+ */
+void auth_fail(const char *, int);
+
+/* starts the next auth_module, or what ever (argv ... ) */
+void auth_success(const char *);
+
+/*
+ * Error handler, for this module, MAY NOT return.
+ * auth_error MAY be called befor auth_init so it is not possible to
+ * use the argument passed to auth_init in this function.
+ */
+void auth_error(int);
+
+/*
+ * for connection forwarding, makes the login part and returns after 
+ * sending the latest command immidiatly
+ */
+void auth_forward(int fd, char *login, char *passwd);
+
+/*
+ * returns the default maildir if it is not defined, this is normally
+ * the last argument of the execution chain.
+ */
+char *auth_aliasempty(void);
+
+#endif
diff -ruN qmail-1.03-orig/auth_pop.c qmail-1.03-ldap-20060201-orig/auth_pop.c
--- qmail-1.03-orig/auth_pop.c	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/auth_pop.c	2006-02-25 11:00:55.000000000 +0100
@@ -0,0 +1,240 @@
+/*
+ * Copyright (c) 2000-2004 Claudio Jeker,
+ *      Internet Business Solutions AG, CH-8005 Zürich, Switzerland
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Internet Business
+ *      Solutions AG and its contributors.
+ * 4. Neither the name of the author nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#include <errno.h>
+#include <unistd.h>
+#include "byte.h"
+#include "env.h"
+#include "error.h"
+#include "exit.h"
+#include "pbsexec.h"
+#include "qldap-debug.h"
+#include "qldap-errno.h"
+#include "qmail-ldap.h"
+#include "readwrite.h"
+#include "sgetopt.h"
+#include "str.h"
+#include "stralloc.h"
+#include "substdio.h"
+#include "timeoutread.h"
+
+#include "auth_mod.h"
+
+#ifndef PORT_POP3 /* this is for testing purposes */
+#define PORT_POP3	110
+#endif
+
+const unsigned int auth_port = PORT_POP3;
+
+#define UP_LEN 513
+static char auth_up[UP_LEN];
+static int auth_argc;
+static char **auth_argv;
+
+void
+auth_init(int argc, char **argv, stralloc *login, stralloc *authdata)
+{
+	char		*l, *p;
+	unsigned int	uplen, u;
+	int		n, opt;
+
+	while ((opt = getopt(argc, argv, "d:")) != opteof) {
+		switch (opt) {
+		case 'd':
+			pbstool = optarg;
+			break;
+		default:
+			auth_error(AUTH_CONF);
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	if (argc < 1)
+		auth_error(AUTH_CONF);
+	auth_argc = argc;
+	auth_argv = argv;
+	
+	for (uplen = 0;;) {
+		do {
+			n = subread(3, auth_up + uplen,
+			    sizeof(auth_up) - uplen);
+		} while (n == -1 && errno == EINTR);
+		if (n == -1)
+			auth_error(ERRNO);
+		if (n == 0) break;
+		uplen += n;
+		if (uplen >= sizeof(auth_up))
+			auth_error(PANIC);
+	}
+	close(3);
+	auth_up[uplen++] = '\0';
+	
+	u = 0;
+	l = auth_up;
+	while (auth_up[u++]) ;
+	if (u == uplen)
+		auth_error(NEEDED);
+	p = auth_up + u;
+	while (auth_up[u++]) ;
+	if (u == uplen)
+		auth_error(NEEDED);
+
+	if (!stralloc_copys(login, l))
+		auth_error(ERRNO);
+	if (!stralloc_0(login)) 
+		auth_error(ERRNO);
+
+	if (!stralloc_copys(authdata, p))
+		auth_error(ERRNO);
+	if (!stralloc_0(authdata))
+		auth_error(ERRNO);
+
+	/* up no longer needed so delete it */
+	byte_zero(auth_up, sizeof(auth_up));
+}
+
+void
+auth_fail(const char *login, int reason)
+{
+	/* in the qmail-pop3 chain it is not possible to have multiples 
+	 * authentication modules. So lets exit with the correct number ... */
+	/* In this case we can use auth_error() */
+	logit(2, "warning: auth_fail: user %s failed\n", login);
+	auth_error(reason);
+}
+
+void
+auth_success(const char *login)
+{
+	/* pop befor smtp */
+	pbsexec();
+	
+	/* start qmail-pop3d */
+	execvp(*auth_argv,auth_argv);
+
+	auth_error(AUTH_EXEC);
+	/* end */
+}
+
+void auth_error(int errnum)
+{
+	/*
+	 * See qmail-popup.c for exit codes meanings.
+	 */
+	logit(2, "warning: auth_error: authorization failed (%s)\n",
+		   qldap_err_str(errnum));
+
+	if (errnum == AUTH_CONF) _exit(1);
+	if (errnum == TIMEOUT || errnum == LDAP_BIND_UNREACH) _exit(2);
+	if (errnum == BADPASS || errnum == NOSUCH) _exit(3);
+	if (errnum == NEEDED || errnum == ILLVAL || errnum == BADVAL) _exit(25);
+	if (errnum == ACC_DISABLED) _exit(4);
+	if (errnum == BADCLUSTER) _exit(5);
+	if (errnum == MAILDIR_CORRUPT) _exit(6);
+	if (errnum == MAILDIR_FAILED) _exit(61);
+	if (errnum == MAILDIR_NONEXIST) _exit(62);
+	if (errnum == AUTH_EXEC) _exit(7);
+	if (errnum == ERRNO && errno == error_nomem) _exit(8);
+	_exit(111);
+}
+
+char *
+auth_aliasempty(void)
+{
+	if (auth_argc > 0)
+		return auth_argv[auth_argc-1];
+	return (char *)0;
+}
+
+#ifdef QLDAP_CLUSTER
+static void get_ok(int);
+
+static void get_ok(int fd)
+/* get the ok for the next command, wait for "+OK.*\r\n" */
+/* This should be a mostly correct solution (adapted from fetchmail) */
+{
+#define AUTH_TIMEOUT 10 /* 10 sec timeout */
+#define OK_LEN 512      /* max length of response (RFC1939) */
+	char ok[OK_LEN];
+	char *c;
+	int  len;
+	int  i;
+
+	/* first get one single line from the other pop server */
+	len = timeoutread(AUTH_TIMEOUT, fd, ok, OK_LEN);
+	if (len == -1) 
+		auth_error(ERRNO);
+	if (len != 0) {
+		c = ok;
+		if (*c == '+' || *c == '-')
+			c++;
+		else
+			auth_error(BADCLUSTER);
+		for (i = 1; i < len /* paranoia */ && 
+				('A' < *c && *c < 'Z') ; ) { i++; c++; }
+
+		if (i < len) {
+			*c = '\0';
+			if (str_diff(ok, "+OK") == 0)
+				return;
+			else if (str_diffn(ok, "-ERR", 4))
+				/* other server is not happy */
+				auth_error(BADCLUSTER);
+		}
+	}
+	/* ARRG, very strange POP3 answer */
+	auth_error(BADCLUSTER);
+}
+
+void auth_forward(int fd, char *login, char *passwd)
+{
+	char buf[512];
+	substdio ss;
+
+	substdio_fdbuf(&ss,subwrite,fd,buf,sizeof(buf));
+	get_ok(fd);
+	substdio_puts(&ss, "user "); 
+	substdio_puts(&ss, login);
+	substdio_puts(&ss, "\r\n");
+	substdio_flush(&ss);
+	get_ok(fd);
+	substdio_puts(&ss, "pass "); 
+	substdio_puts(&ss, passwd); 
+	substdio_puts(&ss, "\r\n");
+	substdio_flush(&ss);
+
+}
+
+#endif /* QLDAP_CLUSTER */
+
diff -ruN qmail-1.03-orig/auth_smtp.c qmail-1.03-ldap-20060201-orig/auth_smtp.c
--- qmail-1.03-orig/auth_smtp.c	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/auth_smtp.c	2006-02-25 11:00:55.000000000 +0100
@@ -0,0 +1,213 @@
+/*
+ * Copyright (c) 2003-2004 Claudio Jeker,
+ *      Internet Business Solutions AG, CH-8005 Zürich, Switzerland
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Internet Business
+ *      Solutions AG and its contributors.
+ * 4. Neither the name of the author nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#include <errno.h>
+#include <unistd.h>
+#include "base64.h"
+#include "byte.h"
+#include "env.h"
+#include "error.h"
+#include "exit.h"
+#include "getln.h"
+#include "output.h"
+#include "qldap.h"
+#include "qldap-debug.h"
+#include "qldap-errno.h"
+#include "qmail-ldap.h"
+#include "read-ctrl.h"
+#include "str.h"
+#include "stralloc.h"
+#include "subfd.h"
+#include "substdio.h"
+#include "timeoutread.h"
+
+#include "checkpassword.h"
+
+#include "auth_mod.h"
+
+checkfunc	cfuncs[] = {
+	check_ldap,
+	0
+};
+
+stralloc line = {0};
+stralloc plain = {0};
+
+void
+auth_init(int argc, char **argv, stralloc *login, stralloc *authdata)
+{
+	char *s, *smax;
+	int match;
+	
+	if (argc != 1)
+		auth_error(AUTH_CONF);
+	
+	if (getln(subfdin, &line, &match, '\0') != 0)
+		auth_error(ERRNO);
+	if (!match) auth_error(NEEDED);
+	if (!str_diff(line.s, "login")) {
+		if (getln(subfdin, &line, &match, '\0') != 0)
+			auth_error(ERRNO);
+		if (!match) auth_error(NEEDED);
+		if (b64_ptons(line.s, login) == -1) auth_error(BADVAL);
+		if (getln(subfdin, &line, &match, '\0') != 0)
+			auth_error(ERRNO);
+		if (!match) auth_error(NEEDED);
+		if (b64_ptons(line.s, authdata) == -1) auth_error(BADVAL);
+		/* XXX we should check if there is some bad
+		 * data in both values */
+		if (!stralloc_0(login)) auth_error(ERRNO);
+		if (!stralloc_0(authdata)) auth_error(ERRNO);
+		return;
+	}
+	if (!str_diff(line.s, "plain")) {
+		/*
+		 * plain sends: [authorize-id]\0authenticate-id\0password
+		 */
+		if (!stralloc_copys(login, "")) auth_error(ERRNO);
+		if (!stralloc_copys(authdata, "")) auth_error(ERRNO);
+		if (getln(subfdin, &line, &match, '\0') != 0)
+			auth_error(ERRNO);
+		if (!match) auth_error(NEEDED);
+		if (b64_ptons(line.s, &plain) == -1) auth_error(BADVAL);
+		s = plain.s; smax = s + plain.len;
+		while (*s++ != '\0') if (s >= smax) auth_error(BADVAL);
+		do {
+			if (!stralloc_append(login, s)) auth_error(ERRNO);
+			if (s >= smax) auth_error(BADVAL);
+		} while (*s++ != '\0');
+		while (*s && s < smax) {
+			if (!stralloc_append(authdata, s)) auth_error(ERRNO);
+			s++;
+		}
+		if (!stralloc_0(authdata)) auth_error(ERRNO);
+		return;
+	}
+	auth_error(AUTH_TYPE);
+}
+
+void
+auth_fail(const char *login, int reason)
+{
+	logit(2, "warning: auth_fail: user %s failed\n", login);
+
+	if (substdio_putflush(subfdout, "D", 1) == -1) auth_error(ERRNO);
+	_exit(0);
+}
+
+void
+auth_success(const char *login)
+{
+	if (substdio_put(subfdout, "K", 1) == -1) auth_error(ERRNO);
+	if (substdio_puts(subfdout, login) == -1) auth_error(ERRNO);
+	if (substdio_putflush(subfdout, "", 1) == -1) auth_error(ERRNO);
+	_exit(0);
+}
+
+void auth_error(int errnum)
+{
+	logit(2, "warning: auth_error: authorization failed (%s)\n",
+		   qldap_err_str(errnum));
+	if (errnum == BADVAL || errnum == NEEDED || errnum == ILLVAL) {
+		if (substdio_putflush(subfdout, "Z", 1) == -1)
+			auth_error(ERRNO);
+		_exit(0);
+	}
+
+	_exit(111);
+}
+
+char *
+auth_aliasempty(void)
+{
+	return (char *)0;
+}
+
+stralloc	loginstr = {0};
+stralloc	authdatastr = {0};
+
+ctrlfunc	ctrls[] = {
+		qldap_ctrl_trylogin,
+		qldap_ctrl_generic,
+		0 };
+
+int
+main(int argc, char **argv)
+{
+	struct	credentials c;
+	int r;
+
+	log_init(STDERR, ~256, 0);	/* XXX limited so that it is not
+					   possible to get passwords via 
+					   debug on production systems.
+					 */
+	if (read_controls(ctrls) == -1)
+		auth_error(AUTH_CONF);
+
+	auth_init(argc, argv, &loginstr, &authdatastr);
+	logit(256, "auth_init: login=%s, authdata=%s\n",
+	    loginstr.s, authdatastr.s);
+
+	if (authdatastr.len <= 1) {
+		logit(1, "alert: null password.\n");
+		auth_fail(loginstr.s, BADPASS);
+	}
+	
+	byte_zero(&c, sizeof(c));
+	r = check(cfuncs, &loginstr, &authdatastr, &c, 1);
+	/* XXX I'm not very happy with this solution but currently this
+	 * is the easiest way. This file, auth_mod.c and checkpassword.c
+	 * need some refactoring (: */
+	switch (r) {
+	case OK:
+	case FORWARD:
+		/* authdata no longer needed */
+		byte_zero(authdatastr.s, authdatastr.len);
+		auth_success(loginstr.s);
+	case NOSUCH: /* FALLTHROUGH */
+	case BADPASS:
+		/* authdata no longer needed */
+		byte_zero(authdatastr.s, authdatastr.len);
+		auth_fail(loginstr.s, r);
+	default:
+		/* authdata no longer needed */
+		byte_zero(authdatastr.s, authdatastr.len);
+		/* system error, now way out ... */
+		auth_error(r);
+	}
+		
+	auth_error(PANIC);
+	return 1; /* should never get here */
+}
+
+
diff -ruN qmail-1.03-orig/auto-gid.c qmail-1.03-ldap-20060201-orig/auto-gid.c
--- qmail-1.03-orig/auto-gid.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/auto-gid.c	2006-02-25 11:00:55.000000000 +0100
@@ -8,7 +8,7 @@
 #include "fmt.h"
 
 char buf1[256];
-substdio ss1 = SUBSTDIO_FDBUF(write,1,buf1,sizeof(buf1));
+substdio ss1 = SUBSTDIO_FDBUF(subwrite,1,buf1,sizeof(buf1));
 
 void outs(s)
 char *s;
@@ -16,7 +16,7 @@
   if (substdio_puts(&ss1,s) == -1) _exit(111);
 }
 
-void main(argc,argv)
+int main(argc,argv)
 int argc;
 char **argv;
 {
@@ -47,5 +47,5 @@
   outs(strnum);
   outs(";\n");
   if (substdio_flush(&ss1) == -1) _exit(111);
-  _exit(0);
+  return 0;
 }
diff -ruN qmail-1.03-orig/auto-int8.c qmail-1.03-ldap-20060201-orig/auto-int8.c
--- qmail-1.03-orig/auto-int8.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/auto-int8.c	2006-02-25 11:00:55.000000000 +0100
@@ -5,15 +5,15 @@
 #include "fmt.h"
 
 char buf1[256];
-substdio ss1 = SUBSTDIO_FDBUF(write,1,buf1,sizeof(buf1));
+substdio ss1 = SUBSTDIO_FDBUF(subwrite,1,buf1,sizeof(buf1));
 
-void puts(s)
+void putstr(s)
 char *s;
 {
   if (substdio_puts(&ss1,s) == -1) _exit(111);
 }
 
-void main(argc,argv)
+int main(argc,argv)
 int argc;
 char **argv;
 {
@@ -30,11 +30,11 @@
   scan_8long(value,&num);
   strnum[fmt_ulong(strnum,num)] = 0;
 
-  puts("int ");
-  puts(name);
-  puts(" = ");
-  puts(strnum);
-  puts(";\n");
+  putstr("int ");
+  putstr(name);
+  putstr(" = ");
+  putstr(strnum);
+  putstr(";\n");
   if (substdio_flush(&ss1) == -1) _exit(111);
-  _exit(0);
+  return 0;
 }
diff -ruN qmail-1.03-orig/auto-int.c qmail-1.03-ldap-20060201-orig/auto-int.c
--- qmail-1.03-orig/auto-int.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/auto-int.c	2006-02-25 11:00:55.000000000 +0100
@@ -5,15 +5,15 @@
 #include "fmt.h"
 
 char buf1[256];
-substdio ss1 = SUBSTDIO_FDBUF(write,1,buf1,sizeof(buf1));
+substdio ss1 = SUBSTDIO_FDBUF(subwrite,1,buf1,sizeof(buf1));
 
-void puts(s)
+void putstr(s)
 char *s;
 {
   if (substdio_puts(&ss1,s) == -1) _exit(111);
 }
 
-void main(argc,argv)
+int main(argc,argv)
 int argc;
 char **argv;
 {
@@ -30,11 +30,11 @@
   scan_ulong(value,&num);
   strnum[fmt_ulong(strnum,num)] = 0;
 
-  puts("int ");
-  puts(name);
-  puts(" = ");
-  puts(strnum);
-  puts(";\n");
+  putstr("unsigned int ");
+  putstr(name);
+  putstr(" = ");
+  putstr(strnum);
+  putstr(";\n");
   if (substdio_flush(&ss1) == -1) _exit(111);
-  _exit(0);
+  return 0;
 }
diff -ruN qmail-1.03-orig/auto_patrn.h qmail-1.03-ldap-20060201-orig/auto_patrn.h
--- qmail-1.03-orig/auto_patrn.h	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/auto_patrn.h	2006-02-25 11:00:55.000000000 +0100
@@ -1,6 +1,6 @@
 #ifndef AUTO_PATRN_H
 #define AUTO_PATRN_H
 
-extern int auto_patrn;
+extern unsigned int auto_patrn;
 
 #endif
diff -ruN qmail-1.03-orig/auto_spawn.h qmail-1.03-ldap-20060201-orig/auto_spawn.h
--- qmail-1.03-orig/auto_spawn.h	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/auto_spawn.h	2006-02-25 11:00:55.000000000 +0100
@@ -1,6 +1,6 @@
 #ifndef AUTO_SPAWN_H
 #define AUTO_SPAWN_H
 
-extern int auto_spawn;
+extern unsigned int auto_spawn;
 
 #endif
diff -ruN qmail-1.03-orig/auto_split.h qmail-1.03-ldap-20060201-orig/auto_split.h
--- qmail-1.03-orig/auto_split.h	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/auto_split.h	2006-02-25 11:00:55.000000000 +0100
@@ -1,6 +1,6 @@
 #ifndef AUTO_SPLIT_H
 #define AUTO_SPLIT_H
 
-extern int auto_split;
+extern unsigned int auto_split;
 
 #endif
diff -ruN qmail-1.03-orig/auto-str.c qmail-1.03-ldap-20060201-orig/auto-str.c
--- qmail-1.03-orig/auto-str.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/auto-str.c	2006-02-25 11:00:55.000000000 +0100
@@ -1,17 +1,17 @@
-#include "substdio.h"
 #include "readwrite.h"
+#include "substdio.h"
 #include "exit.h"
 
 char buf1[256];
-substdio ss1 = SUBSTDIO_FDBUF(write,1,buf1,sizeof(buf1));
+substdio ss1 = SUBSTDIO_FDBUF(subwrite,1,buf1,sizeof(buf1));
 
-void puts(s)
+void putstr(s)
 char *s;
 {
   if (substdio_puts(&ss1,s) == -1) _exit(111);
 }
 
-void main(argc,argv)
+int main(argc,argv)
 int argc;
 char **argv;
 {
@@ -25,20 +25,20 @@
   value = argv[2];
   if (!value) _exit(100);
 
-  puts("char ");
-  puts(name);
-  puts("[] = \"\\\n");
+  putstr("char ");
+  putstr(name);
+  putstr("[] = \"\\\n");
 
-  while (ch = *value++) {
-    puts("\\");
+  while ((ch = *value++)) {
+    putstr("\\");
     octal[3] = 0;
     octal[2] = '0' + (ch & 7); ch >>= 3;
     octal[1] = '0' + (ch & 7); ch >>= 3;
     octal[0] = '0' + (ch & 7);
-    puts(octal);
+    putstr(octal);
   }
 
-  puts("\\\n\";\n");
+  putstr("\\\n\";\n");
   if (substdio_flush(&ss1) == -1) _exit(111);
-  _exit(0);
+  return 0;
 }
diff -ruN qmail-1.03-orig/auto-uid.c qmail-1.03-ldap-20060201-orig/auto-uid.c
--- qmail-1.03-orig/auto-uid.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/auto-uid.c	2006-02-25 11:00:55.000000000 +0100
@@ -8,7 +8,7 @@
 #include "fmt.h"
 
 char buf1[256];
-substdio ss1 = SUBSTDIO_FDBUF(write,1,buf1,sizeof(buf1));
+substdio ss1 = SUBSTDIO_FDBUF(subwrite,1,buf1,sizeof(buf1));
 
 void outs(s) /* was named puts, but Solaris pwd.h includes stdio.h. dorks. */
 char *s;
@@ -16,7 +16,7 @@
   if (substdio_puts(&ss1,s) == -1) _exit(111);
 }
 
-void main(argc,argv)
+int main(argc,argv)
 int argc;
 char **argv;
 {
@@ -41,11 +41,11 @@
 
   strnum[fmt_ulong(strnum,(unsigned long) pw->pw_uid)] = 0;
 
-  outs("int ");
+  outs("unsigned int ");
   outs(name);
   outs(" = ");
   outs(strnum);
   outs(";\n");
   if (substdio_flush(&ss1) == -1) _exit(111);
-  _exit(0);
+  return 0;
 }
diff -ruN qmail-1.03-orig/auto_uids.h qmail-1.03-ldap-20060201-orig/auto_uids.h
--- qmail-1.03-orig/auto_uids.h	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/auto_uids.h	2006-02-25 11:00:55.000000000 +0100
@@ -1,16 +1,16 @@
 #ifndef AUTO_UIDS_H
 #define AUTO_UIDS_H
 
-extern int auto_uida;
-extern int auto_uidd;
-extern int auto_uidl;
-extern int auto_uido;
-extern int auto_uidp;
-extern int auto_uidq;
-extern int auto_uidr;
-extern int auto_uids;
+extern unsigned int auto_uida;
+extern unsigned int auto_uidd;
+extern unsigned int auto_uidl;
+extern unsigned int auto_uido;
+extern unsigned int auto_uidp;
+extern unsigned int auto_uidq;
+extern unsigned int auto_uidr;
+extern unsigned int auto_uids;
 
-extern int auto_gidn;
-extern int auto_gidq;
+extern unsigned int auto_gidn;
+extern unsigned int auto_gidq;
 
 #endif
diff -ruN qmail-1.03-orig/auto_userl.h qmail-1.03-ldap-20060201-orig/auto_userl.h
--- qmail-1.03-orig/auto_userl.h	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/auto_userl.h	2006-02-25 11:00:55.000000000 +0100
@@ -0,0 +1,6 @@
+#ifndef AUTO_USERL_H
+#define AUTO_USERL_H
+
+extern char auto_userl[];
+
+#endif
diff -ruN qmail-1.03-orig/base64.c qmail-1.03-ldap-20060201-orig/base64.c
--- qmail-1.03-orig/base64.c	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/base64.c	2006-02-25 11:00:55.000000000 +0100
@@ -0,0 +1,530 @@
+/* base64.c for QLDAP modified to use only djb's qmail stuff */
+
+/*        */
+/* BASE64 */
+/*        */
+
+/*
+ * Copyright (c) 1996 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+/*
+ * Portions Copyright (c) 1995 by International Business Machines, Inc.
+ *
+ * International Business Machines, Inc. (hereinafter called IBM) grants
+ * permission under its copyrights to use, copy, modify, and distribute this
+ * Software with or without fee, provided that the above copyright notice and
+ * all paragraphs of this notice appear in all copies, and that the name of IBM
+ * not be used in connection with the marketing of any product incorporating
+ * the Software or modifications thereof, without specific, written prior
+ * permission.
+ *
+ * To the extent it has a right to do so, IBM grants an immunity from suit
+ * under its patents, if any, for the use, sale or manufacture of products to
+ * the extent that such products are used for performing Domain Name System
+ * dynamic updates in TCP/IP networks by means of the Software.  No immunity is
+ * granted for any product per se or for any other function of any product.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE.  IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
+ * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
+ * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <sys/types.h>
+#include "str.h"
+#include "stralloc.h"
+#include "strerr.h"
+
+#define Assert(Cond) if (!(Cond)) strerr_die1x(111, "Abort: assert condition false in base64.")
+
+static const char Base64[] =
+	"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+static const char Pad64 = '=';
+
+/* (From RFC1521 and draft-ietf-dnssec-secext-03.txt)
+   The following encoding technique is taken from RFC 1521 by Borenstein
+   and Freed.  It is reproduced here in a slightly edited form for
+   convenience.
+
+   A 65-character subset of US-ASCII is used, enabling 6 bits to be
+   represented per printable character. (The extra 65th character, "=",
+   is used to signify a special processing function.)
+
+   The encoding process represents 24-bit groups of input bits as output
+   strings of 4 encoded characters. Proceeding from left to right, a
+   24-bit input group is formed by concatenating 3 8-bit input groups.
+   These 24 bits are then treated as 4 concatenated 6-bit groups, each
+   of which is translated into a single digit in the base64 alphabet.
+
+   Each 6-bit group is used as an index into an array of 64 printable
+   characters. The character referenced by the index is placed in the
+   output string.
+
+                         Table 1: The Base64 Alphabet
+
+      Value Encoding  Value Encoding  Value Encoding  Value Encoding
+          0 A            17 R            34 i            51 z
+          1 B            18 S            35 j            52 0
+          2 C            19 T            36 k            53 1
+          3 D            20 U            37 l            54 2
+          4 E            21 V            38 m            55 3
+          5 F            22 W            39 n            56 4
+          6 G            23 X            40 o            57 5
+          7 H            24 Y            41 p            58 6
+          8 I            25 Z            42 q            59 7
+          9 J            26 a            43 r            60 8
+         10 K            27 b            44 s            61 9
+         11 L            28 c            45 t            62 +
+         12 M            29 d            46 u            63 /
+         13 N            30 e            47 v
+         14 O            31 f            48 w         (pad) =
+         15 P            32 g            49 x
+         16 Q            33 h            50 y
+
+   Special processing is performed if fewer than 24 bits are available
+   at the end of the data being encoded.  A full encoding quantum is
+   always completed at the end of a quantity.  When fewer than 24 input
+   bits are available in an input group, zero bits are added (on the
+   right) to form an integral number of 6-bit groups.  Padding at the
+   end of the data is performed using the '=' character.
+
+   Since all base64 input is an integral number of octets, only the
+         -------------------------------------------------                       
+   following cases can arise:
+   
+       (1) the final quantum of encoding input is an integral
+           multiple of 24 bits; here, the final unit of encoded
+	   output will be an integral multiple of 4 characters
+	   with no "=" padding,
+       (2) the final quantum of encoding input is exactly 8 bits;
+           here, the final unit of encoded output will be two
+	   characters followed by two "=" padding characters, or
+       (3) the final quantum of encoding input is exactly 16 bits;
+           here, the final unit of encoded output will be three
+	   characters followed by one "=" padding character.
+   */
+
+int
+b64_ntop(unsigned char const *src, size_t srclength, 
+    char *target, size_t targsize)
+{
+	size_t datalength = 0;
+	unsigned char input[3];
+	unsigned char output[4];
+	size_t i;
+
+	while (2 < srclength) {
+		input[0] = *src++;
+		input[1] = *src++;
+		input[2] = *src++;
+		srclength -= 3;
+
+		output[0] = input[0] >> 2;
+		output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
+		output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
+		output[3] = input[2] & 0x3f;
+		Assert(output[0] < 64);
+		Assert(output[1] < 64);
+		Assert(output[2] < 64);
+		Assert(output[3] < 64);
+
+		if (datalength + 4 > targsize)
+			return (-1);
+		target[datalength++] = Base64[output[0]];
+		target[datalength++] = Base64[output[1]];
+		target[datalength++] = Base64[output[2]];
+		target[datalength++] = Base64[output[3]];
+	}
+
+	/* Now we worry about padding. */
+	if (0 != srclength) {
+		/* Get what's left. */
+		input[0] = input[1] = input[2] = '\0';
+		for (i = 0; i < srclength; i++)
+			input[i] = *src++;
+
+		output[0] = input[0] >> 2;
+		output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
+		output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
+		Assert(output[0] < 64);
+		Assert(output[1] < 64);
+		Assert(output[2] < 64);
+
+		if (datalength + 4 > targsize)
+			return (-1);
+		target[datalength++] = Base64[output[0]];
+		target[datalength++] = Base64[output[1]];
+		if (srclength == 1)
+			target[datalength++] = Pad64;
+		else
+			target[datalength++] = Base64[output[2]];
+		target[datalength++] = Pad64;
+	}
+	if (datalength >= targsize)
+		return (-1);
+	target[datalength] = '\0';	/* Returned value doesn't count \0. */
+	return (datalength);
+}
+
+/* skips all whitespace anywhere.
+   converts characters, four at a time, starting at (or after)
+   src from base - 64 numbers into three 8 bit bytes in the target area.
+   it returns the number of data bytes stored at the target, or -1 on error.
+ */
+
+#define ISSPACE(x) ((x) == ' ' || (x) == '\t' || (x) == '\n' || (x) == '\r')
+/* XXX
+   this is not the complete subset of ctypes.h isspace but for qmail-ldap
+   only space, tab, newline and carriage-return are useful (formfeed and 
+   vertical tabs are normaly not used in network communications.
+                                            Claudio Jeker
+ */
+
+int
+b64_pton(char const *src, unsigned char *target, size_t targsize)
+{
+	size_t tarindex;
+	int state, ch;
+	unsigned int pos;
+
+	state = 0;
+	tarindex = 0;
+
+	while ((ch = *src++) != '\0') {
+		if (ISSPACE(ch))	/* Skip whitespace anywhere. */
+			continue;
+
+		if (ch == Pad64)
+			break;
+
+		pos = str_chr(Base64, ch);
+		if (pos > 63) 		/* A non-base64 character. */
+			return (-1);
+
+		switch (state) {
+		case 0:
+			if (target) {
+				if (tarindex >= targsize)
+					return (-1);
+				target[tarindex] = pos << 2;
+			}
+			state = 1;
+			break;
+		case 1:
+			if (target) {
+				if (tarindex + 1 >= targsize)
+					return (-1);
+				target[tarindex]   |=  pos >> 4;
+				target[tarindex+1]  = (pos & 0x0f) << 4 ;
+			}
+			tarindex++;
+			state = 2;
+			break;
+		case 2:
+			if (target) {
+				if (tarindex + 1 >= targsize)
+					return (-1);
+				target[tarindex]   |=  pos >> 2;
+				target[tarindex+1]  = (pos & 0x03) << 6;
+			}
+			tarindex++;
+			state = 3;
+			break;
+		case 3:
+			if (target) {
+				if (tarindex >= targsize)
+					return (-1);
+				target[tarindex] |= pos;
+			}
+			tarindex++;
+			state = 0;
+			break;
+		default:
+			strerr_die1x(111, "Abort: bad state in base64 decode.");
+		}
+	}
+
+	/*
+	 * We are done decoding Base-64 chars.  Let's see if we ended
+	 * on a byte boundary, and/or with erroneous trailing characters.
+	 */
+
+	if (ch == Pad64) {		/* We got a pad char. */
+		ch = *src++;		/* Skip it, get next. */
+		switch (state) {
+		case 0:		/* Invalid = in first position */
+		case 1:		/* Invalid = in second position */
+			return (-1);
+
+		case 2:		/* Valid, means one byte of info */
+			/* Skip any number of spaces. */
+			for (; ch != '\0'; ch = *src++)
+				if (!ISSPACE(ch))
+					break;
+			/* Make sure there is another trailing = sign. */
+			if (ch != Pad64)
+				return (-1);
+			ch = *src++;		/* Skip the = */
+			/* Fall through to "single trailing =" case. */
+			/* FALLTHROUGH */
+
+		case 3:		/* Valid, means two bytes of info */
+			/*
+			 * We know this char is an =.  Is there anything but
+			 * whitespace after it?
+			 */
+			for (; ch != '\0'; ch = *src++)
+				if (!ISSPACE(ch))
+					return (-1);
+
+			/*
+			 * Now make sure for cases 2 and 3 that the "extra"
+			 * bits that slopped past the last full byte were
+			 * zeros.  If we don't check them, they become a
+			 * subliminal channel.
+			 */
+			if (target && target[tarindex] != 0)
+				return (-1);
+		}
+	} else {
+		/*
+		 * We ended by seeing the end of the string.  Make sure we
+		 * have no partial bytes lying around.
+		 */
+		if (state != 0)
+			return (-1);
+	}
+
+	return (tarindex);
+}
+
+int
+b64_ntops(unsigned char const *src, size_t srclength, stralloc *dest)
+{
+	unsigned char input[3];
+	unsigned char output[4];
+	size_t i;
+
+	if (!stralloc_copys(dest, "")) return -1;
+	while (2 < srclength) {
+		input[0] = *src++;
+		input[1] = *src++;
+		input[2] = *src++;
+		srclength -= 3;
+
+		output[0] = input[0] >> 2;
+		output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
+		output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
+		output[3] = input[2] & 0x3f;
+		Assert(output[0] < 64);
+		Assert(output[1] < 64);
+		Assert(output[2] < 64);
+		Assert(output[3] < 64);
+		output[0] = Base64[output[0]];
+		output[1] = Base64[output[1]];
+		output[2] = Base64[output[2]];
+		output[3] = Base64[output[3]];
+		
+		if (!stralloc_catb(dest, output, 4)) return -1;
+	}
+
+	/* Now we worry about padding. */
+	if (0 != srclength) {
+		/* Get what's left. */
+		input[0] = input[1] = input[2] = '\0';
+		for (i = 0; i < srclength; i++)
+			input[i] = *src++;
+
+		output[0] = input[0] >> 2;
+		output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
+		output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
+		Assert(output[0] < 64);
+		Assert(output[1] < 64);
+		Assert(output[2] < 64);
+
+		if (!stralloc_append(dest, &Base64[output[0]])) return -1;
+		if (!stralloc_append(dest, &Base64[output[1]])) return -1;
+		if (srclength == 1) {
+			if (!stralloc_append(dest, &Pad64)) return -1;
+		} else {
+			if (!stralloc_append(dest, &Base64[output[2]]))
+				return -1;
+		}
+		if (!stralloc_catb(dest, &Pad64, 1)) return -1;
+	}
+	return 0;
+}
+
+int
+b64_ptons(char const *src, stralloc *dest)
+{
+	unsigned char out[3];
+	int state, ch;
+	unsigned int pos;
+
+	state = 0;
+
+	if (!stralloc_copys(dest, "")) return -1;
+	while ((ch = *src++) != '\0') {
+		if (ISSPACE(ch))	/* Skip whitespace anywhere. */
+			continue;
+
+		if (ch == Pad64)
+			break;
+
+		pos = str_chr(Base64, ch);
+		if (pos > 63) 		/* A non-base64 character. */
+			return (-1);
+
+		switch (state) {
+		case 0:
+			out[0] = pos << 2;
+			state = 1;
+			break;
+		case 1:
+			out[0] |=  pos >> 4;
+			out[1] = (pos & 0x0f) << 4;
+			state = 2;
+			break;
+		case 2:
+			out[1] |=  pos >> 2;
+			out[2] = (pos & 0x03) << 6;
+			state = 3;
+			break;
+		case 3:
+			out[2] |= pos;
+			if (!stralloc_catb(dest, out, 3)) return -1;
+			state = 0;
+			break;
+		default:
+			strerr_die1x(111, "Abort: bad state in base64 decode.");
+		}
+	}
+
+	/*
+	 * We are done decoding Base-64 chars.  Let's see if we ended
+	 * on a byte boundary, and/or with erroneous trailing characters.
+	 */
+
+	if (ch == Pad64) {		/* We got a pad char. */
+		ch = *src++;		/* Skip it, get next. */
+		switch (state) {
+		case 0:		/* Invalid = in first position */
+		case 1:		/* Invalid = in second position */
+			return (-1);
+
+		case 2:		/* Valid, means one byte of info */
+			/* Skip any number of spaces. */
+			for (; ch != '\0'; ch = *src++)
+				if (!ISSPACE(ch))
+					break;
+			/* Make sure there is another trailing = sign. */
+			if (ch != Pad64)
+				return (-1);
+			ch = *src++;		/* Skip the = */
+			/* Fall through to "single trailing =" case. */
+			/* FALLTHROUGH */
+
+		case 3:		/* Valid, means two bytes of info */
+			/*
+			 * We know this char is an =.  Is there anything but
+			 * whitespace after it?
+			 */
+			for (; ch != '\0'; ch = *src++)
+				if (!ISSPACE(ch))
+					return (-1);
+
+			/*
+			 * Now we need to write the one or two bytes of
+			 * info to the stralloc.
+			 */
+			if (state == 2) { /* one byte */
+				if (!stralloc_catb(dest, out, 1)) return -1;
+			} else { /* two bytes */
+				if (!stralloc_catb(dest, out, 2)) return -1;
+			}
+		}
+	} else {
+		/*
+		 * We ended by seeing the end of the string.  Make sure we
+		 * have no partial bytes lying around.
+		 */
+		if (state != 0)
+			return (-1);
+	}
+
+	return 0;
+}
+
+/* function for decoding and encoding hex strings */
+static const char Hex[] = "0123456789abcdef";
+/* static const char HexBig[] = "0123456789ABCDEF"; */
+
+int
+hex_ntops(unsigned char const *src, size_t srclength, stralloc *dest)
+{
+	size_t	i;
+	
+	if (!stralloc_copys(dest, "")) return -1;
+	for (i=0; i<srclength; i++) {
+		if (!stralloc_append(dest, &Hex[src[i] >> 4])) return -1;
+		if (!stralloc_append(dest, &Hex[src[i] & 0x0f])) return -1;
+	}
+	return 0;
+}
+
+int
+hex_ptons(char const *src, stralloc *dest)
+{
+	int		state;
+	unsigned char	ch, out;
+
+	state = 0;
+	if (!stralloc_copys(dest, "")) return -1;
+	while ((ch = *src++) != '\0') {
+		if (ISSPACE(ch))	/* Skip whitespace anywhere. */
+			continue;
+		
+		if (ch >= '0' && ch <= '9')
+			ch -= '0';
+		else if (ch >= 'a')
+			ch -= ('a' - 10);
+		else 
+			ch -= ('A' - 10);
+		if (ch > 15) 		/* A non-Hex character. */
+			return (-1);
+
+		switch (state) {
+		case 0:
+			out = ch << 4;
+			state = 1;
+			break;
+		case 1:
+			out |= ch;
+			if (!stralloc_append(dest, &out)) return -1;
+			state = 0;
+			break;
+		default:
+			strerr_die1x(111, "Abort: bad state in hex decode.");
+		}
+	}
+	if (state != 0)
+		return -1;
+	return 0;
+}
diff -ruN qmail-1.03-orig/base64.h qmail-1.03-ldap-20060201-orig/base64.h
--- qmail-1.03-orig/base64.h	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/base64.h	2006-02-25 11:00:55.000000000 +0100
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 1999-2004 Claudio Jeker,
+ *      Internet Business Solutions AG, CH-8005 Zürich, Switzerland
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Internet Business
+ *      Solutions AG and its contributors.
+ * 4. Neither the name of the author nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#ifndef __BASE64_H__
+#define __BASE64_H__
+/* base64.h for QLDAP modified to use only djb's qmail stuff */
+
+#include "stralloc.h"
+
+/*        *
+ * BASE64 *
+ *        */
+
+/* base63 encode */
+int b64_ntop(unsigned char const *, size_t, char *, size_t);
+
+/* base64 decode */
+int b64_pton(char const *, unsigned char *, size_t);
+
+/* the same as above but this time with a stralloc as destination */
+int b64_ntops(unsigned char const *, size_t , stralloc *);
+
+/* the same as above but this time with a stralloc as destination */
+int b64_ptons(char const *, stralloc *);
+
+int hex_ntops(unsigned char const *, size_t, stralloc *);
+int hex_ptons(char const *, stralloc *);
+
+#endif
diff -ruN qmail-1.03-orig/bouncesaying.c qmail-1.03-ldap-20060201-orig/bouncesaying.c
--- qmail-1.03-orig/bouncesaying.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/bouncesaying.c	2006-02-25 11:00:55.000000000 +0100
@@ -1,3 +1,4 @@
+#include <unistd.h>
 #include "fork.h"
 #include "strerr.h"
 #include "error.h"
@@ -7,7 +8,7 @@
 
 #define FATAL "bouncesaying: fatal: "
 
-void main(argc,argv)
+int main(argc,argv)
 int argc;
 char **argv;
 {
@@ -38,4 +39,6 @@
   }
 
   strerr_die1x(100,argv[1]);
+  /* NOTREACHED */
+  return 100;
 }
diff -ruN qmail-1.03-orig/byte_chr.c qmail-1.03-ldap-20060201-orig/byte_chr.c
--- qmail-1.03-orig/byte_chr.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/byte_chr.c	2006-02-25 11:00:55.000000000 +0100
@@ -1,12 +1,12 @@
 #include "byte.h"
 
 unsigned int byte_chr(s,n,c)
-char *s;
+const char *s;
 register unsigned int n;
 int c;
 {
   register char ch;
-  register char *t;
+  register const char *t;
 
   ch = c;
   t = s;
diff -ruN qmail-1.03-orig/byte_copy.c qmail-1.03-ldap-20060201-orig/byte_copy.c
--- qmail-1.03-orig/byte_copy.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/byte_copy.c	2006-02-25 11:00:55.000000000 +0100
@@ -1,14 +1,16 @@
 #include "byte.h"
 
 void byte_copy(to,n,from)
-register char *to;
+void *to;
 register unsigned int n;
-register char *from;
+const void *from;
 {
+  register char *t = (char *)to;
+  register const char *f = (const char *)from;
   for (;;) {
-    if (!n) return; *to++ = *from++; --n;
-    if (!n) return; *to++ = *from++; --n;
-    if (!n) return; *to++ = *from++; --n;
-    if (!n) return; *to++ = *from++; --n;
+    if (!n) return; *t++ = *f++; --n;
+    if (!n) return; *t++ = *f++; --n;
+    if (!n) return; *t++ = *f++; --n;
+    if (!n) return; *t++ = *f++; --n;
   }
 }
diff -ruN qmail-1.03-orig/byte_cr.c qmail-1.03-ldap-20060201-orig/byte_cr.c
--- qmail-1.03-orig/byte_cr.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/byte_cr.c	2006-02-25 11:00:55.000000000 +0100
@@ -1,16 +1,19 @@
 #include "byte.h"
 
 void byte_copyr(to,n,from)
-register char *to;
+void *to;
 register unsigned int n;
-register char *from;
+const void *from;
 {
-  to += n;
-  from += n;
+  register char *t = (char *)to;
+  register const char *f = (const char *)from;
+
+  t += n;
+  f += n;
   for (;;) {
-    if (!n) return; *--to = *--from; --n;
-    if (!n) return; *--to = *--from; --n;
-    if (!n) return; *--to = *--from; --n;
-    if (!n) return; *--to = *--from; --n;
+    if (!n) return; *--t = *--f; --n;
+    if (!n) return; *--t = *--f; --n;
+    if (!n) return; *--t = *--f; --n;
+    if (!n) return; *--t = *--f; --n;
   }
 }
diff -ruN qmail-1.03-orig/byte_diff.c qmail-1.03-ldap-20060201-orig/byte_diff.c
--- qmail-1.03-orig/byte_diff.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/byte_diff.c	2006-02-25 11:00:55.000000000 +0100
@@ -1,16 +1,19 @@
 #include "byte.h"
 
 int byte_diff(s,n,t)
-register char *s;
+const void *s;
 register unsigned int n;
-register char *t;
+const void *t;
 {
+  register const char *S = (const char *)s;
+  register const char *T = (const char *)t;
+
   for (;;) {
-    if (!n) return 0; if (*s != *t) break; ++s; ++t; --n;
-    if (!n) return 0; if (*s != *t) break; ++s; ++t; --n;
-    if (!n) return 0; if (*s != *t) break; ++s; ++t; --n;
-    if (!n) return 0; if (*s != *t) break; ++s; ++t; --n;
+    if (!n) return 0; if (*S != *T) break; ++S; ++T; --n;
+    if (!n) return 0; if (*S != *T) break; ++S; ++T; --n;
+    if (!n) return 0; if (*S != *T) break; ++S; ++T; --n;
+    if (!n) return 0; if (*S != *T) break; ++S; ++T; --n;
   }
-  return ((int)(unsigned int)(unsigned char) *s)
-       - ((int)(unsigned int)(unsigned char) *t);
+  return ((int)(unsigned int)(unsigned char) *S)
+       - ((int)(unsigned int)(unsigned char) *T);
 }
diff -ruN qmail-1.03-orig/byte.h qmail-1.03-ldap-20060201-orig/byte.h
--- qmail-1.03-orig/byte.h	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/byte.h	2006-02-25 11:00:55.000000000 +0100
@@ -1,12 +1,13 @@
 #ifndef BYTE_H
 #define BYTE_H
 
-extern unsigned int byte_chr();
-extern unsigned int byte_rchr();
-extern void byte_copy();
-extern void byte_copyr();
-extern int byte_diff();
-extern void byte_zero();
+extern unsigned int byte_chr(const char *, unsigned int, int);
+extern unsigned int byte_rchr(const char *, unsigned int, int);
+extern void byte_copy(void *, unsigned int, const void *);
+extern void byte_copyr(void *, unsigned int, const void *);
+extern int byte_diff(const void *, unsigned int, const void *);
+extern void byte_zero(void *, unsigned int);
+extern unsigned int byte_repl(char *, unsigned int, int, int);
 
 #define byte_equal(s,n,t) (!byte_diff((s),(n),(t)))
 
diff -ruN qmail-1.03-orig/byte_rchr.c qmail-1.03-ldap-20060201-orig/byte_rchr.c
--- qmail-1.03-orig/byte_rchr.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/byte_rchr.c	2006-02-25 11:00:55.000000000 +0100
@@ -1,13 +1,13 @@
 #include "byte.h"
 
 unsigned int byte_rchr(s,n,c)
-char *s;
+const char *s;
 register unsigned int n;
 int c;
 {
   register char ch;
-  register char *t;
-  register char *u;
+  register const char *t;
+  register const char *u;
 
   ch = c;
   t = s;
diff -ruN qmail-1.03-orig/byte_repl.c qmail-1.03-ldap-20060201-orig/byte_repl.c
--- qmail-1.03-orig/byte_repl.c	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/byte_repl.c	2006-02-25 11:00:55.000000000 +0100
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2002-2004 Claudio Jeker,
+ *      Internet Business Solutions AG, CH-8005 Zürich, Switzerland
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Internet Business
+ *      Solutions AG and its contributors.
+ * 4. Neither the name of the author nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#include "byte.h"
+
+/* char replacement */
+unsigned int byte_repl(char *s, unsigned int len, int f, int r)
+{
+   register char *t;
+   int count = 0;
+   char fc;
+   char rc;
+
+   t = s; fc = f; rc = r;
+   for(;;) {
+      if (!len) return count; if (*t == fc) { *t=rc; count++; } ++t; --len;
+      if (!len) return count; if (*t == fc) { *t=rc; count++; } ++t; --len;
+      if (!len) return count; if (*t == fc) { *t=rc; count++; } ++t; --len;
+      if (!len) return count; if (*t == fc) { *t=rc; count++; } ++t; --len;
+   }
+}
+
+
diff -ruN qmail-1.03-orig/byte_zero.c qmail-1.03-ldap-20060201-orig/byte_zero.c
--- qmail-1.03-orig/byte_zero.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/byte_zero.c	2006-02-25 11:00:55.000000000 +0100
@@ -1,13 +1,14 @@
 #include "byte.h"
 
 void byte_zero(s,n)
-char *s;
+void *s;
 register unsigned int n;
 {
+  char *S = (char *)s;
   for (;;) {
-    if (!n) break; *s++ = 0; --n;
-    if (!n) break; *s++ = 0; --n;
-    if (!n) break; *s++ = 0; --n;
-    if (!n) break; *s++ = 0; --n;
+    if (!n) break; *S++ = 0; --n;
+    if (!n) break; *S++ = 0; --n;
+    if (!n) break; *S++ = 0; --n;
+    if (!n) break; *S++ = 0; --n;
   }
 }
diff -ruN qmail-1.03-orig/case_diffb.c qmail-1.03-ldap-20060201-orig/case_diffb.c
--- qmail-1.03-orig/case_diffb.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/case_diffb.c	2006-02-25 11:00:55.000000000 +0100
@@ -1,9 +1,9 @@
 #include "case.h"
 
 int case_diffb(s,len,t)
-register char *s;
+register const char *s;
 unsigned int len;
-register char *t;
+register const char *t;
 {
   register unsigned char x;
   register unsigned char y;
diff -ruN qmail-1.03-orig/case_diffs.c qmail-1.03-ldap-20060201-orig/case_diffs.c
--- qmail-1.03-orig/case_diffs.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/case_diffs.c	2006-02-25 11:00:55.000000000 +0100
@@ -1,8 +1,8 @@
 #include "case.h"
 
 int case_diffs(s,t)
-register char *s;
-register char *t;
+register const char *s;
+register const char *t;
 {
   register unsigned char x;
   register unsigned char y;
diff -ruN qmail-1.03-orig/case.h qmail-1.03-ldap-20060201-orig/case.h
--- qmail-1.03-orig/case.h	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/case.h	2006-02-25 11:00:55.000000000 +0100
@@ -1,12 +1,12 @@
 #ifndef CASE_H
 #define CASE_H
 
-extern void case_lowers();
-extern void case_lowerb();
-extern int case_diffs();
-extern int case_diffb();
-extern int case_starts();
-extern int case_startb();
+extern void case_lowers(char *);
+extern void case_lowerb(char *, unsigned int);
+extern int case_diffs(const char *, const char *);
+extern int case_diffb(const char *, unsigned int, const char *);
+extern int case_starts(const char *, const char *);
+extern int case_startb(const char *, unsigned int, const char *);
 
 #define case_equals(s,t) (!case_diffs((s),(t)))
 
diff -ruN qmail-1.03-orig/case_lowers.c qmail-1.03-ldap-20060201-orig/case_lowers.c
--- qmail-1.03-orig/case_lowers.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/case_lowers.c	2006-02-25 11:00:55.000000000 +0100
@@ -4,7 +4,7 @@
 char *s;
 {
   unsigned char x;
-  while (x = *s) {
+  while ((x = *s)) {
     x -= 'A';
     if (x <= 'Z' - 'A') *s = x + 'a';
     ++s;
diff -ruN qmail-1.03-orig/case_startb.c qmail-1.03-ldap-20060201-orig/case_startb.c
--- qmail-1.03-orig/case_startb.c	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/case_startb.c	2006-02-25 11:00:55.000000000 +0100
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2003-2004 Claudio Jeker,
+ *      Internet Business Solutions AG, CH-8005 Zürich, Switzerland
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Internet Business
+ *      Solutions AG and its contributors.
+ * 4. Neither the name of the author nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+/* based on case_starts.c by D.J. Bernstein */
+#include "case.h"
+
+int case_startb(const char *s, unsigned int len, const char *t)
+{
+	unsigned char x;
+	unsigned char y;
+
+	for (;;) {
+		y = *t++ - 'A';
+		if (y <= 'Z' - 'A')
+			y += 'a';
+		else
+			y += 'A';
+		if (!y)
+			return (1);
+		if (!len)
+			return (0);
+		--len;
+		x = *s++ - 'A';
+		if (x <= 'Z' - 'A')
+			x += 'a';
+		else
+			x += 'A';
+		if (x != y)
+			return (0);
+	}
+}
+
diff -ruN qmail-1.03-orig/case_starts.c qmail-1.03-ldap-20060201-orig/case_starts.c
--- qmail-1.03-orig/case_starts.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/case_starts.c	2006-02-25 11:00:55.000000000 +0100
@@ -1,8 +1,8 @@
 #include "case.h"
 
 int case_starts(s,t)
-register char *s;
-register char *t;
+register const char *s;
+register const char *t;
 {
   register unsigned char x;
   register unsigned char y;
diff -ruN qmail-1.03-orig/cdb.c qmail-1.03-ldap-20060201-orig/cdb.c
--- qmail-1.03-orig/cdb.c	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/cdb.c	2006-02-25 11:00:55.000000000 +0100
@@ -0,0 +1,164 @@
+/* Public domain. */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <unistd.h>
+
+#include "byte.h"
+#include "error.h"
+#include "seek.h"
+#include "uint32.h"
+
+#include "cdb.h"
+
+static void uint32_unpack(const unsigned char *buf, uint32 *u)
+{
+  uint32 num;
+  num = buf[3]; num <<= 8;
+  num += buf[2]; num <<= 8;
+  num += buf[1]; num <<= 8;
+  num += buf[0];
+
+  *u = num;
+}
+
+
+
+void cdb_free(struct cdb *c)
+{
+  if (c->map) {
+    munmap(c->map,c->size);
+    c->map = 0;
+  }
+}
+
+void cdb_findstart(struct cdb *c)
+{
+  c->loop = 0;
+}
+
+void cdb_init(struct cdb *c,int fd)
+{
+  struct stat st;
+  char *x;
+
+  cdb_free(c);
+  cdb_findstart(c);
+  c->fd = fd;
+
+  if (fstat(fd,&st) == 0)
+    if (st.st_size <= 0xffffffff) {
+      x = mmap(0,st.st_size,PROT_READ,MAP_SHARED,fd,0);
+      if (x + 1) {
+	c->size = st.st_size;
+	c->map = x;
+      }
+    }
+}
+
+int cdb_read(struct cdb *c,char *buf,unsigned int len,uint32 pos)
+{
+  if (c->map) {
+    if ((pos > c->size) || (c->size - pos < len)) goto FORMAT;
+    byte_copy(buf,len,c->map + pos);
+  }
+  else {
+    if (seek_set(c->fd,pos) == -1) return -1;
+    while (len > 0) {
+      int r;
+      do
+        r = read(c->fd,buf,len);
+      while ((r == -1) && (errno == error_intr));
+      if (r == -1) return -1;
+      if (r == 0) goto FORMAT;
+      buf += r;
+      len -= r;
+    }
+  }
+  return 0;
+
+  FORMAT:
+  errno = error_proto;
+  return -1;
+}
+
+static int match(struct cdb *c,const char *key,unsigned int len,uint32 pos)
+{
+  char buf[32];
+  unsigned int n;
+
+  while (len > 0) {
+    n = sizeof buf;
+    if (n > len) n = len;
+    if (cdb_read(c,buf,n,pos) == -1) return -1;
+    if (byte_diff(buf,n,key)) return 0;
+    pos += n;
+    key += n;
+    len -= n;
+  }
+  return 1;
+}
+
+int cdb_findnext(struct cdb *c,const char *key,unsigned int len)
+{
+  char buf[8];
+  uint32 pos;
+  uint32 u;
+
+  if (!c->loop) {
+    u = cdb_hash(key,len);
+    if (cdb_read(c,buf,8,(u << 3) & 2047) == -1) return -1;
+    uint32_unpack(buf + 4,&c->hslots);
+    if (!c->hslots) return 0;
+    uint32_unpack(buf,&c->hpos);
+    c->khash = u;
+    u >>= 8;
+    u %= c->hslots;
+    u <<= 3;
+    c->kpos = c->hpos + u;
+  }
+
+  while (c->loop < c->hslots) {
+    if (cdb_read(c,buf,8,c->kpos) == -1) return -1;
+    uint32_unpack(buf + 4,&pos);
+    if (!pos) return 0;
+    c->loop += 1;
+    c->kpos += 8;
+    if (c->kpos == c->hpos + (c->hslots << 3)) c->kpos = c->hpos;
+    uint32_unpack(buf,&u);
+    if (u == c->khash) {
+      if (cdb_read(c,buf,8,pos) == -1) return -1;
+      uint32_unpack(buf,&u);
+      if (u == len)
+	switch(match(c,key,len,pos + 8)) {
+	  case -1:
+	    return -1;
+	  case 1:
+	    uint32_unpack(buf + 4,&c->dlen);
+	    c->dpos = pos + 8 + len;
+	    return 1;
+	}
+    }
+  }
+
+  return 0;
+}
+
+int cdb_find(struct cdb *c,const char *key,unsigned int len)
+{
+  cdb_findstart(c);
+  return cdb_findnext(c,key,len);
+}
+
+int cdb_seek(struct cdb *c,const char *key,unsigned int len,uint32 *dlen)
+{
+  int rv;
+
+  rv = cdb_find(c, key, len);
+  if (rv != 1)
+    return rv;
+  *dlen = cdb_datalen(c);
+  return rv;
+}
+
diff -ruN qmail-1.03-orig/cdb.h qmail-1.03-ldap-20060201-orig/cdb.h
--- qmail-1.03-orig/cdb.h	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/cdb.h	2006-02-25 11:00:55.000000000 +0100
@@ -1,12 +1,40 @@
+/* Public domain. */
+
 #ifndef CDB_H
 #define CDB_H
 
 #include "uint32.h"
 
-extern uint32 cdb_hash();
-extern uint32 cdb_unpack();
+#define CDB_HASHSTART 5381
+extern uint32 cdb_hashadd(uint32,unsigned char);
+extern uint32 cdb_hash(const char *,unsigned int);
+
+struct cdb {
+  char *map; /* 0 if no map is available */
+  int fd;
+  uint32 size; /* initialized if map is nonzero */
+  uint32 loop; /* number of hash slots searched under this key */
+  uint32 khash; /* initialized if loop is nonzero */
+  uint32 kpos; /* initialized if loop is nonzero */
+  uint32 hpos; /* initialized if loop is nonzero */
+  uint32 hslots; /* initialized if loop is nonzero */
+  uint32 dpos; /* initialized if cdb_findnext() returns 1 */
+  uint32 dlen; /* initialized if cdb_findnext() returns 1 */
+} ;
+
+extern void cdb_free(struct cdb *);
+extern void cdb_init(struct cdb *,int fd);
+
+extern int cdb_read(struct cdb *,char *,unsigned int,uint32);
+
+extern void cdb_findstart(struct cdb *);
+extern int cdb_findnext(struct cdb *,const char *,unsigned int);
+extern int cdb_find(struct cdb *,const char *,unsigned int);
+extern int cdb_seek(struct cdb *,const char *,unsigned int,uint32 *);
 
-extern int cdb_bread();
-extern int cdb_seek();
+#define cdb_datapos(c) ((c)->dpos)
+#define cdb_datalen(c) ((c)->dlen)
+#define cdb_bread(c, b, l)	\
+	cdb_read((c), (b), (l), cdb_datapos(c))
 
 #endif
diff -ruN qmail-1.03-orig/cdb_hash.c qmail-1.03-ldap-20060201-orig/cdb_hash.c
--- qmail-1.03-orig/cdb_hash.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/cdb_hash.c	2006-02-25 11:00:55.000000000 +0100
@@ -1,16 +1,21 @@
+/* Public domain. */
+
 #include "cdb.h"
 
-uint32 cdb_hash(buf,len)
-unsigned char *buf;
-unsigned int len;
+uint32 cdb_hashadd(uint32 h,unsigned char c)
+{
+  h += (h << 5);
+  return h ^ c;
+}
+
+uint32 cdb_hash(const char *buf,unsigned int len)
 {
   uint32 h;
 
-  h = 5381;
+  h = CDB_HASHSTART;
   while (len) {
+    h = cdb_hashadd(h,*buf++);
     --len;
-    h += (h << 5);
-    h ^= (uint32) *buf++;
   }
   return h;
 }
diff -ruN qmail-1.03-orig/cdbmake_add.c qmail-1.03-ldap-20060201-orig/cdbmake_add.c
--- qmail-1.03-orig/cdbmake_add.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/cdbmake_add.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,117 +0,0 @@
-#include "cdbmake.h"
-
-void cdbmake_init(cdbm)
-struct cdbmake *cdbm;
-{
-  cdbm->head = 0;
-  cdbm->split = 0;
-  cdbm->hash = 0;
-  cdbm->numentries = 0;
-}
-
-int cdbmake_add(cdbm,h,p,alloc)
-struct cdbmake *cdbm;
-uint32 h;
-uint32 p;
-char *(*alloc)();
-{
-  struct cdbmake_hplist *head;
-
-  head = cdbm->head;
-  if (!head || (head->num >= CDBMAKE_HPLIST)) {
-    head = (struct cdbmake_hplist *) alloc(sizeof(struct cdbmake_hplist));
-    if (!head) return 0;
-    head->num = 0;
-    head->next = cdbm->head;
-    cdbm->head = head;
-  }
-  head->hp[head->num].h = h;
-  head->hp[head->num].p = p;
-  ++head->num;
-  ++cdbm->numentries;
-  return 1;
-}
-
-int cdbmake_split(cdbm,alloc)
-struct cdbmake *cdbm;
-char *(*alloc)();
-{
-  int i;
-  uint32 u;
-  uint32 memsize;
-  struct cdbmake_hplist *x;
-
-  for (i = 0;i < 256;++i)
-    cdbm->count[i] = 0;
-
-  for (x = cdbm->head;x;x = x->next) {
-    i = x->num;
-    while (i--)
-      ++cdbm->count[255 & x->hp[i].h];
-  }
-
-  memsize = 1;
-  for (i = 0;i < 256;++i) {
-    u = cdbm->count[i] * 2;
-    if (u > memsize)
-      memsize = u;
-  }
-
-  memsize += cdbm->numentries; /* no overflow possible up to now */
-  u = (uint32) 0 - (uint32) 1;
-  u /= sizeof(struct cdbmake_hp);
-  if (memsize > u) return 0;
-
-  cdbm->split = (struct cdbmake_hp *) alloc(memsize * sizeof(struct cdbmake_hp));
-  if (!cdbm->split) return 0;
-
-  cdbm->hash = cdbm->split + cdbm->numentries;
-
-  u = 0;
-  for (i = 0;i < 256;++i) {
-    u += cdbm->count[i]; /* bounded by numentries, so no overflow */
-    cdbm->start[i] = u;
-  }
-
-  for (x = cdbm->head;x;x = x->next) {
-    i = x->num;
-    while (i--)
-      cdbm->split[--cdbm->start[255 & x->hp[i].h]] = x->hp[i];
-  }
-
-  return 1;
-}
-
-uint32 cdbmake_throw(cdbm,pos,b)
-struct cdbmake *cdbm;
-uint32 pos;
-int b;
-{
-  uint32 len;
-  uint32 j;
-  uint32 count;
-  struct cdbmake_hp *hp;
-  uint32 where;
-
-  count = cdbm->count[b];
-
-  len = count + count; /* no overflow possible */
-  cdbmake_pack(cdbm->final + 8 * b,pos);
-  cdbmake_pack(cdbm->final + 8 * b + 4,len);
-
-  if (len) {
-    for (j = 0;j < len;++j)
-      cdbm->hash[j].h = cdbm->hash[j].p = 0;
-
-    hp = cdbm->split + cdbm->start[b];
-    for (j = 0;j < count;++j) {
-      where = (hp->h >> 8) % len;
-      while (cdbm->hash[where].p)
-	if (++where == len)
-	  where = 0;
-      cdbm->hash[where] = *hp++;
-    }
-  }
-
-  return len;
-}
diff -ruN qmail-1.03-orig/cdb_make.c qmail-1.03-ldap-20060201-orig/cdb_make.c
--- qmail-1.03-orig/cdb_make.c	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/cdb_make.c	2006-02-25 11:00:55.000000000 +0100
@@ -0,0 +1,163 @@
+/* Public domain. */
+
+#include "readwrite.h"
+#include "seek.h"
+#include "error.h"
+#include "alloc.h"
+#include "cdb.h"
+#include "cdb_make.h"
+
+static void uint32_pack(char s[4],uint32 u)
+{
+  s[0] = u & 255;
+  u >>= 8;
+  s[1] = u & 255;
+  u >>= 8;
+  s[2] = u & 255;
+  s[3] = u >> 8;
+}
+
+int cdb_make_start(struct cdb_make *c,int fd)
+{
+  c->head = 0;
+  c->split = 0;
+  c->hash = 0;
+  c->numentries = 0;
+  c->fd = fd;
+  c->pos = sizeof c->final;
+  substdio_fdbuf(&c->ss,subwrite,fd,c->ssbuf,sizeof c->ssbuf);
+  return seek_set(fd,c->pos);
+}
+
+static int posplus(struct cdb_make *c,uint32 len)
+{
+  uint32 newpos = c->pos + len;
+  if (newpos < len) { errno = error_nomem; return -1; }
+  c->pos = newpos;
+  return 0;
+}
+
+int cdb_make_addend(struct cdb_make *c,unsigned int keylen,unsigned int datalen,uint32 h)
+{
+  struct cdb_hplist *head;
+
+  head = c->head;
+  if (!head || (head->num >= CDB_HPLIST)) {
+    head = (struct cdb_hplist *) alloc(sizeof(struct cdb_hplist));
+    if (!head) return -1;
+    head->num = 0;
+    head->next = c->head;
+    c->head = head;
+  }
+  head->hp[head->num].h = h;
+  head->hp[head->num].p = c->pos;
+  ++head->num;
+  ++c->numentries;
+  if (posplus(c,8) == -1) return -1;
+  if (posplus(c,keylen) == -1) return -1;
+  if (posplus(c,datalen) == -1) return -1;
+  return 0;
+}
+
+int cdb_make_addbegin(struct cdb_make *c,unsigned int keylen,unsigned int datalen)
+{
+  char buf[8];
+
+  if (keylen > 0xffffffff) { errno = error_nomem; return -1; }
+  if (datalen > 0xffffffff) { errno = error_nomem; return -1; }
+
+  uint32_pack(buf,keylen);
+  uint32_pack(buf + 4,datalen);
+  if (substdio_put(&c->ss,buf,8) == -1) return -1;
+  return 0;
+}
+
+int cdb_make_add(struct cdb_make *c,const char *key,unsigned int keylen,const char *data,unsigned int datalen)
+{
+  if (cdb_make_addbegin(c,keylen,datalen) == -1) return -1;
+  if (substdio_put(&c->ss,key,keylen) == -1) return -1;
+  if (substdio_put(&c->ss,data,datalen) == -1) return -1;
+  return cdb_make_addend(c,keylen,datalen,cdb_hash(key,keylen));
+}
+
+int cdb_make_finish(struct cdb_make *c)
+{
+  char buf[8];
+  int i;
+  uint32 len;
+  uint32 u;
+  uint32 memsize;
+  uint32 count;
+  uint32 where;
+  struct cdb_hplist *x;
+  struct cdb_hp *hp;
+
+  for (i = 0;i < 256;++i)
+    c->count[i] = 0;
+
+  for (x = c->head;x;x = x->next) {
+    i = x->num;
+    while (i--)
+      ++c->count[255 & x->hp[i].h];
+  }
+
+  memsize = 1;
+  for (i = 0;i < 256;++i) {
+    u = c->count[i] * 2;
+    if (u > memsize)
+      memsize = u;
+  }
+
+  memsize += c->numentries; /* no overflow possible up to now */
+  u = (uint32) 0 - (uint32) 1;
+  u /= sizeof(struct cdb_hp);
+  if (memsize > u) { errno = error_nomem; return -1; }
+
+  c->split = (struct cdb_hp *) alloc(memsize * sizeof(struct cdb_hp));
+  if (!c->split) return -1;
+
+  c->hash = c->split + c->numentries;
+
+  u = 0;
+  for (i = 0;i < 256;++i) {
+    u += c->count[i]; /* bounded by numentries, so no overflow */
+    c->start[i] = u;
+  }
+
+  for (x = c->head;x;x = x->next) {
+    i = x->num;
+    while (i--)
+      c->split[--c->start[255 & x->hp[i].h]] = x->hp[i];
+  }
+
+  for (i = 0;i < 256;++i) {
+    count = c->count[i];
+
+    len = count + count; /* no overflow possible */
+    uint32_pack(c->final + 8 * i,c->pos);
+    uint32_pack(c->final + 8 * i + 4,len);
+
+    for (u = 0;u < len;++u)
+      c->hash[u].h = c->hash[u].p = 0;
+
+    hp = c->split + c->start[i];
+    for (u = 0;u < count;++u) {
+      where = (hp->h >> 8) % len;
+      while (c->hash[where].p)
+	if (++where == len)
+	  where = 0;
+      c->hash[where] = *hp++;
+    }
+
+    for (u = 0;u < len;++u) {
+      uint32_pack(buf,c->hash[u].h);
+      uint32_pack(buf + 4,c->hash[u].p);
+      if (substdio_put(&c->ss,buf,8) == -1) return -1;
+      if (posplus(c,8) == -1) return -1;
+    }
+  }
+
+  if (substdio_flush(&c->ss) == -1) return -1;
+  if (seek_begin(c->fd) == -1) return -1;
+  return substdio_putflush(&c->ss,c->final,sizeof c->final);
+}
diff -ruN qmail-1.03-orig/cdb_make.h qmail-1.03-ldap-20060201-orig/cdb_make.h
--- qmail-1.03-orig/cdb_make.h	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/cdb_make.h	2006-02-25 11:00:55.000000000 +0100
@@ -0,0 +1,39 @@
+/* Public domain. */
+
+#ifndef CDB_MAKE_H
+#define CDB_MAKE_H
+
+#include "substdio.h"
+#include "uint32.h"
+
+#define CDB_HPLIST 1000
+
+struct cdb_hp { uint32 h; uint32 p; } ;
+
+struct cdb_hplist {
+  struct cdb_hp hp[CDB_HPLIST];
+  struct cdb_hplist *next;
+  int num;
+} ;
+
+struct cdb_make {
+  char ssbuf[8192];
+  char final[2048];
+  uint32 count[256];
+  uint32 start[256];
+  struct cdb_hplist *head;
+  struct cdb_hp *split; /* includes space for hash */
+  struct cdb_hp *hash;
+  uint32 numentries;
+  substdio ss;
+  uint32 pos;
+  int fd;
+} ;
+
+extern int cdb_make_start(struct cdb_make *,int);
+extern int cdb_make_addbegin(struct cdb_make *,unsigned int,unsigned int);
+extern int cdb_make_addend(struct cdb_make *,unsigned int,unsigned int,uint32);
+extern int cdb_make_add(struct cdb_make *,const char *,unsigned int,const char *,unsigned int);
+extern int cdb_make_finish(struct cdb_make *);
+
+#endif
diff -ruN qmail-1.03-orig/cdbmake.h qmail-1.03-ldap-20060201-orig/cdbmake.h
--- qmail-1.03-orig/cdbmake.h	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/cdbmake.h	1970-01-01 01:00:00.000000000 +0100
@@ -1,35 +0,0 @@
-#ifndef CDBMAKE_H
-#define CDBMAKE_H
-
-#include "uint32.h"
-
-#define CDBMAKE_HPLIST 1000
-
-struct cdbmake_hp { uint32 h; uint32 p; } ;
-
-struct cdbmake_hplist {
-  struct cdbmake_hp hp[CDBMAKE_HPLIST];
-  struct cdbmake_hplist *next;
-  int num;
-} ;
-
-struct cdbmake {
-  char final[2048];
-  uint32 count[256];
-  uint32 start[256];
-  struct cdbmake_hplist *head;
-  struct cdbmake_hp *split; /* includes space for hash */
-  struct cdbmake_hp *hash;
-  uint32 numentries;
-} ;
-
-extern void cdbmake_pack();
-#define CDBMAKE_HASHSTART ((uint32) 5381)
-extern uint32 cdbmake_hashadd();
-
-extern void cdbmake_init();
-extern int cdbmake_add();
-extern int cdbmake_split();
-extern uint32 cdbmake_throw();
-
-#endif
diff -ruN qmail-1.03-orig/cdbmake_hash.c qmail-1.03-ldap-20060201-orig/cdbmake_hash.c
--- qmail-1.03-orig/cdbmake_hash.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/cdbmake_hash.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,10 +0,0 @@
-#include "cdbmake.h"
-
-uint32 cdbmake_hashadd(h,c)
-uint32 h;
-unsigned int c;
-{
-  h += (h << 5);
-  h ^= (uint32) (unsigned char) c;
-  return h;
-}
diff -ruN qmail-1.03-orig/cdbmake_pack.c qmail-1.03-ldap-20060201-orig/cdbmake_pack.c
--- qmail-1.03-orig/cdbmake_pack.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/cdbmake_pack.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,11 +0,0 @@
-#include "cdbmake.h"
-
-void cdbmake_pack(buf,num)
-unsigned char *buf;
-uint32 num;
-{
-  *buf++ = num; num >>= 8;
-  *buf++ = num; num >>= 8;
-  *buf++ = num; num >>= 8;
-  *buf = num;
-}
diff -ruN qmail-1.03-orig/cdbmss.c qmail-1.03-ldap-20060201-orig/cdbmss.c
--- qmail-1.03-orig/cdbmss.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/cdbmss.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,65 +0,0 @@
-#include "readwrite.h"
-#include "seek.h"
-#include "alloc.h"
-#include "cdbmss.h"
-
-int cdbmss_start(c,fd)
-struct cdbmss *c;
-int fd;
-{
-  cdbmake_init(&c->cdbm);
-  c->fd = fd;
-  c->pos = sizeof(c->cdbm.final);
-  substdio_fdbuf(&c->ss,write,fd,c->ssbuf,sizeof(c->ssbuf));
-  return seek_set(fd,(seek_pos) c->pos);
-}
-
-int cdbmss_add(c,key,keylen,data,datalen)
-struct cdbmss *c;
-unsigned char *key;
-unsigned int keylen;
-unsigned char *data;
-unsigned int datalen;
-{
-  uint32 h;
-  int i;
-
-  cdbmake_pack(c->packbuf,(uint32) keylen);
-  cdbmake_pack(c->packbuf + 4,(uint32) datalen);
-  if (substdio_put(&c->ss,c->packbuf,8) == -1) return -1;
-  if (substdio_put(&c->ss,key,keylen) == -1) return -1;
-  if (substdio_put(&c->ss,data,datalen) == -1) return -1;
-
-  h = CDBMAKE_HASHSTART;
-  for (i = 0;i < keylen;++i)
-    h = cdbmake_hashadd(h,(unsigned int) key[i]);
-
-  if (!cdbmake_add(&c->cdbm,h,c->pos,alloc)) return -1;
-
-  c->pos += 8 + keylen + datalen; /* XXX: overflow? */
-  return 0;
-}
-
-int cdbmss_finish(c)
-struct cdbmss *c;
-{
-  int i;
-  uint32 len;
-  uint32 u;
-
-  if (!cdbmake_split(&c->cdbm,alloc)) return -1;
-
-  for (i = 0;i < 256;++i) {
-    len = cdbmake_throw(&c->cdbm,c->pos,i);
-    for (u = 0;u < len;++u) {
-      cdbmake_pack(c->packbuf,c->cdbm.hash[u].h);
-      cdbmake_pack(c->packbuf + 4,c->cdbm.hash[u].p);
-      if (substdio_put(&c->ss,c->packbuf,8) == -1) return -1;
-      c->pos += 8; /* XXX: overflow? */
-    }
-  }
-
-  if (substdio_flush(&c->ss) == -1) return -1;
-  if (seek_begin(c->fd) == -1) return -1;
-  return substdio_putflush(&c->ss,c->cdbm.final,sizeof(c->cdbm.final));
-}
diff -ruN qmail-1.03-orig/cdbmss.h qmail-1.03-ldap-20060201-orig/cdbmss.h
--- qmail-1.03-orig/cdbmss.h	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/cdbmss.h	1970-01-01 01:00:00.000000000 +0100
@@ -1,16 +0,0 @@
-#ifndef CDBMSS_H
-#define CDBMSS_H
-
-#include "cdbmake.h"
-#include "substdio.h"
-
-struct cdbmss {
-  char ssbuf[1024];
-  struct cdbmake cdbm;
-  substdio ss;
-  char packbuf[8];
-  uint32 pos;
-  int fd;
-} ;
-
-#endif
diff -ruN qmail-1.03-orig/cdb_seek.c qmail-1.03-ldap-20060201-orig/cdb_seek.c
--- qmail-1.03-orig/cdb_seek.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/cdb_seek.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,95 +0,0 @@
-#include <sys/types.h>
-#include <errno.h>
-extern int errno;
-#include "cdb.h"
-
-#ifndef SEEK_SET
-#define SEEK_SET 0
-#endif
-
-int cdb_bread(fd,buf,len)
-int fd;
-char *buf;
-int len;
-{
-  int r;
-  while (len > 0) {
-    do
-      r = read(fd,buf,len);
-    while ((r == -1) && (errno == EINTR));
-    if (r == -1) return -1;
-    if (r == 0) { errno = EIO; return -1; }
-    buf += r;
-    len -= r;
-  }
-  return 0;
-}
-
-static int match(fd,key,len)
-int fd;
-char *key;
-unsigned int len;
-{
-  char buf[32];
-  int n;
-  int i;
-
-  while (len > 0) {
-    n = sizeof(buf);
-    if (n > len) n = len;
-    if (cdb_bread(fd,buf,n) == -1) return -1;
-    for (i = 0;i < n;++i) if (buf[i] != key[i]) return 0;
-    key += n;
-    len -= n;
-  }
-  return 1;
-}
-
-int cdb_seek(fd,key,len,dlen)
-int fd;
-char *key;
-unsigned int len;
-uint32 *dlen;
-{
-  char packbuf[8];
-  uint32 pos;
-  uint32 h;
-  uint32 lenhash;
-  uint32 h2;
-  uint32 loop;
-  uint32 poskd;
-
-  h = cdb_hash(key,len);
-
-  pos = 8 * (h & 255);
-  if (lseek(fd,(off_t) pos,SEEK_SET) == -1) return -1;
-
-  if (cdb_bread(fd,packbuf,8) == -1) return -1;
-
-  pos = cdb_unpack(packbuf);
-  lenhash = cdb_unpack(packbuf + 4);
-
-  if (!lenhash) return 0;
-  h2 = (h >> 8) % lenhash;
-
-  for (loop = 0;loop < lenhash;++loop) {
-    if (lseek(fd,(off_t) (pos + 8 * h2),SEEK_SET) == -1) return -1;
-    if (cdb_bread(fd,packbuf,8) == -1) return -1;
-    poskd = cdb_unpack(packbuf + 4);
-    if (!poskd) return 0;
-    if (cdb_unpack(packbuf) == h) {
-      if (lseek(fd,(off_t) poskd,SEEK_SET) == -1) return -1;
-      if (cdb_bread(fd,packbuf,8) == -1) return -1;
-      if (cdb_unpack(packbuf) == len)
-	switch(match(fd,key,len)) {
-	  case -1:
-	    return -1;
-	  case 1:
-	    *dlen = cdb_unpack(packbuf + 4);
-	    return 1;
-	}
-    }
-    if (++h2 == lenhash) h2 = 0;
-  }
-  return 0;
-}
diff -ruN qmail-1.03-orig/cdb_unpack.c qmail-1.03-ldap-20060201-orig/cdb_unpack.c
--- qmail-1.03-orig/cdb_unpack.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/cdb_unpack.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,12 +0,0 @@
-#include "cdb.h"
-
-uint32 cdb_unpack(buf)
-unsigned char *buf;
-{
-  uint32 num;
-  num = buf[3]; num <<= 8;
-  num += buf[2]; num <<= 8;
-  num += buf[1]; num <<= 8;
-  num += buf[0];
-  return num;
-}
diff -ruN qmail-1.03-orig/check.c qmail-1.03-ldap-20060201-orig/check.c
--- qmail-1.03-orig/check.c	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/check.c	2006-02-25 11:00:55.000000000 +0100
@@ -0,0 +1,282 @@
+/*
+ * Copyright (c) 1998-2004 Claudio Jeker,
+ *      Internet Business Solutions AG, CH-8005 Zürich, Switzerland
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Internet Business
+ *      Solutions AG and its contributors.
+ * 4. Neither the name of the author nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#include "qmail-ldap.h"
+#include "check.h"
+#include "str.h"
+
+extern unsigned char testvektor[128];
+
+/* XXX this is not a security checker, it just looks that no special chars 
+ * XXX are in the string this is because the ldap server could send some 
+ * XXX faked datas */
+int sanitycheckb(char *s, unsigned int len, unsigned char mask)
+{
+	unsigned char *tv;
+	unsigned int x;
+
+	tv = testvektor;
+	
+	x = (unsigned int)*s++; if (!len--) return 1;
+	/* is this char allowed as first char (normaly '-' is not) */
+	if (x > 0x7F || !(tv[x] & mask) || tv[x] & NOT_FIRST) return 0;
+
+	for (;;) {
+		x = (unsigned int)*s++; if (!len--) return 1;
+		if (x > 0x7F || !(tv[x] & mask)) return 0;
+		x = (unsigned int)*s++; if (!len--) return 1;
+		if (x > 0x7F || !(tv[x] & mask)) return 0;
+		x = (unsigned int)*s++; if (!len--) return 1;
+		if (x > 0x7F || !(tv[x] & mask)) return 0;
+		x = (unsigned int)*s++; if (!len--) return 1;
+		if (x > 0x7F || !(tv[x] & mask)) return 0;
+	}
+	return 0; /* paranoia */
+}
+
+/* XXX this is not a security checker, it just looks that no special chars 
+ * XXX are in the string this is because the ldap server could send some 
+ * XXX faked datas */
+int sanitypathcheckb(char *s, unsigned int len, unsigned char mask)
+/* works like sanitycheckb but also looks that there is no '..' in the
+ * string. This should be used for maildirpaths */
+{
+	unsigned char *tv;
+	unsigned int x;
+	enum { NODOT, FIRST, SLASH, ONEDOT, TWODOT } state = FIRST;
+
+	tv = testvektor;
+	
+	while (len--) {
+		x = (unsigned int)*s++;
+		if (x > 0x7F || !(tv[x] & mask)) return 0;
+		if (state == FIRST && tv[x] & NOT_FIRST) return 0;
+		switch (x) {
+		case '.':
+			switch (state) {
+			case ONEDOT:
+				state = TWODOT;
+				break;
+			case NODOT:
+				break;
+			default:
+				state = ONEDOT;
+			}
+			break;
+		case '/':
+			if (state == TWODOT)
+				return 0;
+			state = SLASH;
+			break;
+		default:
+			state = NODOT;
+			break;
+		}
+	}
+	return 1;
+}
+
+int sanitychecks(register char *s, register unsigned char mask) 
+{
+	return sanitycheckb(s, str_len(s), mask);
+}
+
+int sanitypathchecks(register char *s, register unsigned char mask) 
+{
+	return sanitypathcheckb(s, str_len(s), mask);
+}
+
+/************************************************************
+You can allow or deny chars by adding:
+  DENY_ALL:   always deny this char
+  ALLOW_ALL:  always allow this char
+  ALLOW_USER: allow this char for username checks (chck_user)
+  DENY_USER:  deny this char for username checks (chck_user)
+  ALLOW_PATH: allow this char for path checks (chck_path)
+  DENY_PATH:  deny this char for path checks (chck_path)
+  ALLOW_PROG: allow this char for program checks (chck_prog)
+  DENY_PROG:  deny this char for program checks (chck_prog)
+  NOT_FIRST:  deny this char at the beginning of a string
+  SPACE:      alias to ALLOW_PROG
+  PARANOIA:   deny most shell special chars like '|' or '*' for program checks
+              can be turned on or of in qmail-ldap.h
+  Example:
+   * 7  \007 ^G * DENY_ALL,               * deny control chars *
+   * 45 '-'     * ALLOW_ALL|NOT_FIRST,    * allowed but not first *
+   * 47 '/'     * ALLOW_ALL&DENY_USER,    * allowed only for path and prog *
+   * 58 ':'     * ALLOW_PROG|ALLOW_PATH,  * like before *
+ 
+  As you can see ALLOWs have to be ORed together whereas DENYs have to be ANDed
+  NOT_FIRST has to be ORed and PARANOIA has to be ANDed.
+
+************************************************************/
+
+unsigned char testvektor[128] = { 
+#define SPACE			ALLOW_PROG
+#if RESTRICT_PROG == 1
+# define PARANOIA		DENY_PROG
+#else
+# define PARANOIA		0xFF
+#endif
+	/* nr	char		*/
+	/********************/
+	/* 0	\000	^@	*/	DENY_ALL,
+	/* 1	\001	^A	*/	DENY_ALL,
+	/* 2	\002	^B	*/	DENY_ALL,
+	/* 3	\003	^C	*/	DENY_ALL,
+	/* 4	\004	^D	*/	DENY_ALL,
+	/* 5	\005	^E	*/	DENY_ALL,
+	/* 6	\006	^F	*/	DENY_ALL,
+	/* 7	\007	^G	*/	DENY_ALL,
+	/* 8	\010	^F	*/	DENY_ALL,
+	/* 9	\011	\t	*/	SPACE,
+	/* 10	\012	\n	*/	SPACE,
+	/* 11	\013	^K	*/	DENY_ALL,
+	/* 12	\014	^L	*/	DENY_ALL,
+	/* 13	\015	^M	*/	DENY_ALL,
+	/* 14	\016	^N	*/	DENY_ALL,
+	/* 15	\017	^O	*/	DENY_ALL,
+	/* 16	\020	^P	*/	DENY_ALL,
+	/* 17	\021	^Q	*/	DENY_ALL,
+	/* 18	\022	^R	*/	DENY_ALL,
+	/* 19	\023	^S	*/	DENY_ALL,
+	/* 20	\024	^T	*/	DENY_ALL,
+	/* 21	\025	^U	*/	DENY_ALL,
+	/* 22	\026	^V	*/	DENY_ALL,
+	/* 23	\027	^W	*/	DENY_ALL,
+	/* 24	\030	^X	*/	DENY_ALL,
+	/* 25	\031	^Y	*/	DENY_ALL,
+	/* 26	\032	^Z	*/	DENY_ALL,
+	/* 27	\033	ESC	*/	DENY_ALL,
+	/* 28	\034	^\	*/	DENY_ALL,
+	/* 29	\035	^]	*/	DENY_ALL,
+	/* 30	\036	^^	*/	DENY_ALL,
+	/* 31	\037	^_	*/	DENY_ALL,
+	/* 32	' '			*/	SPACE,
+	/* 33	'!'			*/	ALLOW_PROG&PARANOIA,
+	/* 34	'"'			*/	ALLOW_PROG,
+	/* 35	'#'			*/	ALLOW_ALL,
+	/* 36	'$'			*/	ALLOW_PROG&PARANOIA,
+	/* 37	'%'			*/	ALLOW_PROG&PARANOIA,
+	/* 38	'&'			*/	ALLOW_PROG&PARANOIA,
+	/* 39	'''			*/	ALLOW_PROG,
+	/* 40	'('			*/	ALLOW_PROG&PARANOIA,
+	/* 41	')'			*/	ALLOW_PROG&PARANOIA,
+	/* 42	'*'			*/	ALLOW_PROG&PARANOIA,
+	/* 43	'+'			*/	ALLOW_PROG,
+	/* 44	','			*/	ALLOW_PROG,
+	/* 45	'-'			*/	ALLOW_ALL|NOT_FIRST, /*XXX*/
+	/* 46	'.'			*/	ALLOW_ALL,
+	/* 47	'/'			*/	ALLOW_ALL&DENY_USER,
+	/* 48	'0'			*/	ALLOW_ALL,
+	/* 49	'1'			*/	ALLOW_ALL,
+	/* 50	'2'			*/	ALLOW_ALL,
+	/* 51	'3'			*/	ALLOW_ALL,
+	/* 52	'4'			*/	ALLOW_ALL,
+	/* 53	'5'			*/	ALLOW_ALL,
+	/* 54	'6'			*/	ALLOW_ALL,
+	/* 55	'7'			*/	ALLOW_ALL,
+	/* 56	'8'			*/	ALLOW_ALL,
+	/* 57	'9'			*/	ALLOW_ALL,
+	/* 58	':'			*/	ALLOW_PROG|ALLOW_PATH,
+	/* 59	';'			*/	ALLOW_PROG&PARANOIA,
+	/* 60	'<'			*/	ALLOW_PROG&PARANOIA,
+	/* 61	'='			*/	ALLOW_PROG|ALLOW_PATH,
+	/* 62	'>'			*/	ALLOW_PROG&PARANOIA,
+	/* 63	'?'			*/	ALLOW_PROG&PARANOIA,
+	/* 64	'@'			*/	ALLOW_USER|ALLOW_PATH|ALLOW_PROG, /*XXX*/
+	/* 65	'A'			*/	ALLOW_ALL,
+	/* 66	'B'			*/	ALLOW_ALL,
+	/* 67	'C'			*/	ALLOW_ALL,
+	/* 68	'D'			*/	ALLOW_ALL,
+	/* 69	'E'			*/	ALLOW_ALL,
+	/* 70	'F'			*/	ALLOW_ALL,
+	/* 71	'G'			*/	ALLOW_ALL,
+	/* 72	'H'			*/	ALLOW_ALL,
+	/* 73	'I'			*/	ALLOW_ALL,
+	/* 74	'J'			*/	ALLOW_ALL,
+	/* 75	'K'			*/	ALLOW_ALL,
+	/* 76	'L'			*/	ALLOW_ALL,
+	/* 77	'M'			*/	ALLOW_ALL,
+	/* 78	'N'			*/	ALLOW_ALL,
+	/* 79	'O'			*/	ALLOW_ALL,
+	/* 80	'P'			*/	ALLOW_ALL,
+	/* 81	'Q'			*/	ALLOW_ALL,
+	/* 82	'R'			*/	ALLOW_ALL,
+	/* 83	'S'			*/	ALLOW_ALL,
+	/* 84	'T'			*/	ALLOW_ALL,
+	/* 85	'U'			*/	ALLOW_ALL,
+	/* 86	'V'			*/	ALLOW_ALL,
+	/* 87	'W'			*/	ALLOW_ALL,
+	/* 88	'X'			*/	ALLOW_ALL,
+	/* 89	'Y'			*/	ALLOW_ALL,
+	/* 90	'Z'			*/	ALLOW_ALL,
+	/* 91	'['			*/	ALLOW_PROG&PARANOIA,
+	/* 92	'\\'			*/	ALLOW_PROG,
+	/* 93	']'			*/	ALLOW_PROG&PARANOIA,
+	/* 94	'^'			*/	ALLOW_PROG&PARANOIA,
+	/* 95	'_'			*/	ALLOW_ALL,
+	/* 96	'`'			*/	ALLOW_PROG&PARANOIA,
+	/* 97	'a'			*/	ALLOW_ALL,
+	/* 98	'b'			*/	ALLOW_ALL,
+	/* 99	'c'			*/	ALLOW_ALL,
+	/* 100	'd'			*/	ALLOW_ALL,
+	/* 101	'e'			*/	ALLOW_ALL,
+	/* 102	'f'			*/	ALLOW_ALL,
+	/* 103	'g'			*/	ALLOW_ALL,
+	/* 104	'h'			*/	ALLOW_ALL,
+	/* 105	'i'			*/	ALLOW_ALL,
+	/* 106	'j'			*/	ALLOW_ALL,
+	/* 107	'k'			*/	ALLOW_ALL,
+	/* 108	'l'			*/	ALLOW_ALL,
+	/* 109	'm'			*/	ALLOW_ALL,
+	/* 110	'n'			*/	ALLOW_ALL,
+	/* 111	'o'			*/	ALLOW_ALL,
+	/* 112	'p'			*/	ALLOW_ALL,
+	/* 113	'q'			*/	ALLOW_ALL,
+	/* 114	'r'			*/	ALLOW_ALL,
+	/* 115	's'			*/	ALLOW_ALL,
+	/* 116	't'			*/	ALLOW_ALL,
+	/* 117	'u'			*/	ALLOW_ALL,
+	/* 118	'v'			*/	ALLOW_ALL,
+	/* 119	'w'			*/	ALLOW_ALL,
+	/* 120	'x'			*/	ALLOW_ALL,
+	/* 121	'y'			*/	ALLOW_ALL,
+	/* 122	'z'			*/	ALLOW_ALL,
+	/* 123	'{'			*/	ALLOW_PROG&PARANOIA,
+	/* 124	'|'			*/	ALLOW_PROG&PARANOIA,
+	/* 125	'}'			*/	ALLOW_PROG&PARANOIA,
+	/* 126	'~'			*/	ALLOW_PROG&PARANOIA,
+	/* 127	^?			*/	DENY_ALL
+};
+
diff -ruN qmail-1.03-orig/check.h qmail-1.03-ldap-20060201-orig/check.h
--- qmail-1.03-orig/check.h	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/check.h	2006-02-25 11:00:55.000000000 +0100
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 1998-2004 Claudio Jeker,
+ *      Internet Business Solutions AG, CH-8005 Zürich, Switzerland
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Internet Business
+ *      Solutions AG and its contributors.
+ * 4. Neither the name of the author nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#ifndef _CHECK_H_
+#define _CHECK_H_
+
+
+#define DENY_ALL	0x00
+#define ALLOW_USER	0x01
+#define ALLOW_PATH	0x02
+#define ALLOW_PROG	0x04
+#define ALLOW_ALL	(ALLOW_USER | ALLOW_PATH | ALLOW_PROG)
+#define DENY_USER	(unsigned char) ~ALLOW_USER
+#define DENY_PATH	(unsigned char) ~ALLOW_PATH
+#define DENY_PROG	(unsigned char) ~ALLOW_PROG
+#define NOT_FIRST	0x80
+
+
+extern int sanitycheckb(char *, unsigned int, unsigned char);
+extern int sanitychecks(char *, unsigned char);
+
+extern int sanitypathcheckb(char *, unsigned int , unsigned char);
+extern int sanitypathchecks(char *, unsigned char);
+
+#define check_userb(str, len)	sanitycheckb((str), (len), ALLOW_USER)
+#define check_users(str)	sanitychecks((str), ALLOW_USER)
+
+#define check_pathb(str, len)	sanitypathcheckb((str), (len), ALLOW_PATH)
+#define check_paths(str)	sanitypathchecks((str), ALLOW_PATH)
+
+#define check_progb(str, len)	sanitycheckb((str), (len), ALLOW_PROG)
+#define check_progs(str)	sanitychecks((str), ALLOW_PROG)
+
+#endif
diff -ruN qmail-1.03-orig/checkpassword.c qmail-1.03-ldap-20060201-orig/checkpassword.c
--- qmail-1.03-orig/checkpassword.c	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/checkpassword.c	2006-02-25 11:00:55.000000000 +0100
@@ -0,0 +1,291 @@
+/*
+ * Copyright (c) 1998-2004 Claudio Jeker,
+ *      Internet Business Solutions AG, CH-8005 Zürich, Switzerland
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Internet Business
+ *      Solutions AG and its contributors.
+ * 4. Neither the name of the author nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#include <sys/types.h>
+#include <unistd.h>
+#include "auth_mod.h"
+#include "auto_uids.h"
+#include "byte.h"
+#include "check.h"
+#include "env.h"
+#include "error.h"
+#include "fmt.h"
+#include "passwd.h"
+#include "pbsexec.h"
+#include "prot.h"
+#include "qldap.h"
+#include "qldap-debug.h"
+#include "qldap-errno.h"
+#include "qmail-ldap.h"
+#include "scan.h"
+#include "str.h"
+#include "stralloc.h"
+#ifdef QLDAP_CLUSTER
+#include "qldap-cluster.h"
+#endif
+
+#include "checkpassword.h"
+
+int
+check(checkfunc *f, stralloc *login, stralloc *authdata,
+    struct credentials *c, int fast)
+{
+	int	i, r;
+
+	for (i = 0; f[i] != 0; i++)
+		switch (r = f[i](login, authdata, c, fast)) {
+		case OK:
+		case FORWARD:
+			return r;
+		case NOSUCH:
+			/* lets try an other backend */
+			break;
+		case BADPASS:
+			/* NOTE: users defined in two dbs are not allowed */
+			return BADPASS;
+		default:
+			return r;
+		}
+	
+	return NOSUCH;
+}
+
+char num[FMT_ULONG];
+
+int
+check_ldap(stralloc *login, stralloc *authdata,
+    struct credentials *c, int fast)
+{
+	static	stralloc ld = {0};
+	qldap	*q;
+	char	*filter;
+	int	r, status, pwok, needforward;
+	unsigned long count, size, max;
+	const	char	*attrs[] = {
+				LDAP_UID, /* the first 10 attrs are default */
+				LDAP_QMAILUID,
+				LDAP_QMAILGID,
+				LDAP_ISACTIVE,
+				LDAP_MAILHOST,
+				LDAP_MAILSTORE,
+				LDAP_HOMEDIR,
+				LDAP_QUOTA_SIZE,
+				LDAP_QUOTA_COUNT,
+				LDAP_MAXMSIZE,
+				LDAP_PASSWD, 0}; /* passwd is extra */
+
+	/* TODO more debug output is needed */
+	needforward = 0;
+	q = qldap_new();
+	if (q == 0)
+		return ERRNO;
+	
+	r = qldap_open(q);
+	if (r != OK) goto fail;
+	r = qldap_bind(q, 0, 0);
+	if (r != OK) goto fail;
+	
+	if (fast) {
+		/* just comapre passwords and account status */
+		attrs[0] = LDAP_ISACTIVE;
+		if (qldap_need_rebind() == 0) {
+			attrs[1] = LDAP_PASSWD;
+			attrs[2] = 0;
+		} else
+			attrs[1] = 0;
+	} else {
+		if (qldap_need_rebind() != 0)
+			attrs[10] = 0;
+	}
+
+	filter = filter_uid(login->s);
+	if (filter == 0) { r = ERRNO; goto fail; }
+
+	r = qldap_lookup(q, filter, attrs);
+	if (r != OK) goto fail;
+
+	r = qldap_get_status(q, &status);
+	if (r != OK) goto fail;
+	if (status == STATUS_BOUNCE || status == STATUS_NOACCESS ||
+	    status == STATUS_DELETE) {
+		qldap_free(q);
+		return ACC_DISABLED;
+	}
+	
+	if (!fast) {
+#ifdef QLDAP_CLUSTER
+		r = qldap_get_attr(q, LDAP_MAILHOST, &c->forwarder,
+		    SINGLE_VALUE);
+		if (r != OK && r != NOSUCH) goto fail;
+		if (r == OK && cluster(c->forwarder.s) == 1) {
+			/* hostname is different, so I reconnect */
+			logit(8, "check_ldap: forwarding session to %s\n",
+			    c->forwarder.s);
+			needforward = 1;
+		}
+#endif
+
+		r = qldap_get_uid(q, &c->uid);
+		if (r != OK) goto fail;
+		r = qldap_get_gid(q, &c->gid);
+		if (r != OK) goto fail;
+		r = qldap_get_mailstore(q, &c->home, &c->maildir);
+		if (r != OK) goto fail;
+		if (!stralloc_0(&c->home) ||
+		    !stralloc_0(&c->maildir))
+			return ERRNO;
+		size = count = max = 0;
+		r = qldap_get_quota(q, &size, &count, &max);
+		if (r != OK) goto fail;
+		if (max != 0) {
+			num[fmt_ulong(num, max)] = 0;
+			if (!env_put2("DATASIZE", num))
+				auth_error(ERRNO);
+		}
+		if (size != 0 || count != 0) {
+			if (!stralloc_copys(&ld, "")) auth_error(ERRNO);
+			if (size != 0) {
+				if (!stralloc_catb(&ld, num,
+					    fmt_ulong(num, size)))
+					auth_error(ERRNO);
+				if (!stralloc_append(&ld, "S"))
+					auth_error(ERRNO);
+			}
+			if (count != 0) {
+				if (size != 0)
+					if (!stralloc_append(&ld, ","))
+						auth_error(ERRNO);
+				if (!stralloc_catb(&ld, num,
+					    fmt_ulong(num, count)))
+					auth_error(ERRNO);
+				if (!stralloc_append(&ld, "C"))
+					auth_error(ERRNO);
+			}
+			if (!stralloc_0(&ld)) auth_error(ERRNO);
+			if (!env_put2(ENV_QUOTA, ld.s )) auth_error(ERRNO);
+		}
+	}
+	
+	if (qldap_need_rebind() == 0) {
+		r = qldap_get_attr(q, LDAP_PASSWD, &ld, SINGLE_VALUE);
+		if (r != OK) goto fail;
+		pwok = cmp_passwd(authdata->s, ld.s);
+	} else {
+		r = qldap_get_dn(q, &ld);
+		if (r != OK) goto fail;
+		r = qldap_rebind(q, ld.s, authdata->s);
+		switch (r) {
+		case OK:
+			pwok = OK;
+			break;
+		case LDAP_BIND_AUTH:
+			pwok = BADPASS;
+			break;
+		default:
+			pwok = r;
+			break;
+		}
+	}
+	logit(32, "check_ldap: password compare was %s\n", 
+	    pwok == OK?"successful":"not successful");
+	qldap_free(q);
+	if (pwok == OK  && needforward == 1)
+		return FORWARD;
+	return pwok;
+fail:
+	qldap_free(q);
+	return r;
+	
+}
+
+void
+change_uid(unsigned int uid, unsigned int gid)
+{
+	unsigned int	id;
+	
+	id = geteuid();
+	if (id != 0 && (id == uid || uid == (unsigned int)-1)) {
+		/* not running as root so return */
+		logit(32, "change_uid: already running non root\n");
+		return;
+	}
+	if (uid == (unsigned int)-1 && gid == (unsigned int)-1) {
+		/* run as non-privileged user qmaild group nofiles */
+		uid = auto_uidd;
+		gid = auto_gidn;
+	}
+	/* first set the group id */
+	if (prot_gid(gid) == -1)
+		auth_error(ERRNO);
+	logit(32, "setgid succeeded (%i)\n", gid);
+	
+	/* ... then the user id */
+	if (prot_uid(uid) == -1)
+		auth_error(ERRNO);
+	logit(32, "setuid succeeded (%i)\n", uid);
+	
+	/* ... now check that we are realy not running as root */
+	if (!getuid())
+		auth_error(FAILED);
+}
+
+void
+setup_env(char *user, struct credentials *c)
+{
+	/* set up the environment for the execution of the subprogram */
+	if (!env_put2("USER", user))
+		auth_error(ERRNO);
+	
+	/* only courier-imap needs this but we set it anyway */
+	if (!env_put2("AUTHENTICATED", user))
+		auth_error(ERRNO);
+	
+	if (c->home.s != 0 && c->home.len > 0)
+		if (!env_put2("HOME", c->home.s))
+			auth_error(ERRNO);
+	
+	if (c->maildir.s != 0 && c->maildir.len > 0) {
+		if (!env_put2("MAILDIR", c->maildir.s))
+			auth_error(ERRNO);
+	} else {
+		if (!env_unset("MAILDIR"))
+			auth_error(ERRNO);
+	}
+	logit(32, "environment successfully set: "
+	    "USER %s, HOME %s, MAILDIR %s\n",
+	    user, c->home.s != 0 && c->home.len > 0?
+	    c->home.s:"unset, forwarding",
+	    c->maildir.s != 0 && c->maildir.len > 0?
+	    c->maildir.s:"unset, using aliasempty"); 
+}
+
diff -ruN qmail-1.03-orig/checkpassword.h qmail-1.03-ldap-20060201-orig/checkpassword.h
--- qmail-1.03-orig/checkpassword.h	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/checkpassword.h	2006-02-25 11:00:55.000000000 +0100
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2003-2004 Claudio Jeker,
+ *      Internet Business Solutions AG, CH-8005 Zürich, Switzerland
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Internet Business
+ *      Solutions AG and its contributors.
+ * 4. Neither the name of the author nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#ifndef __CHECKPASSWORD_H__
+#define __CHECKPASSWORD_H__
+
+#include "stralloc.h"
+
+struct credentials {
+	unsigned int	uid;
+	unsigned int	gid;
+	stralloc	home;
+	stralloc	maildir;
+	stralloc	forwarder;
+};
+
+typedef int (*checkfunc)(stralloc *, stralloc *, struct credentials *, int);
+
+int check(checkfunc *, stralloc *, stralloc *, struct credentials *, int);
+int check_ldap(stralloc *, stralloc *, struct credentials *, int);
+void check_credentials(struct credentials *);
+void change_uid(unsigned int, unsigned int);
+void setup_env(char *, struct credentials *);
+
+#endif
diff -ruN qmail-1.03-orig/chkshsgr.c qmail-1.03-ldap-20060201-orig/chkshsgr.c
--- qmail-1.03-orig/chkshsgr.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/chkshsgr.c	2006-02-25 11:00:55.000000000 +0100
@@ -1,9 +1,12 @@
+#include <sys/types.h>
+#include <unistd.h>
 #include "exit.h"
-void main()
+
+int main(int argc, char ** argv)
 {
  short x[4];
 
  x[0] = x[1] = 0;
  if (getgroups(1,x) == 0) if (setgroups(1,x) == -1) _exit(1);
- _exit(0);
+ return 0;
 }
diff -ruN qmail-1.03-orig/chkspawn.c qmail-1.03-ldap-20060201-orig/chkspawn.c
--- qmail-1.03-orig/chkspawn.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/chkspawn.c	2006-02-25 11:00:55.000000000 +0100
@@ -8,7 +8,7 @@
 char num[FMT_ULONG];
 fd_set fds;
 
-void main()
+int main(int argc, char **argv)
 {
   unsigned long hiddenlimit;
   unsigned long maxnumd;
@@ -22,8 +22,8 @@
     _exit(1);
   }
 
-  if (auto_spawn > 255) {
-    substdio_puts(subfderr,"Oops. You have set conf-spawn higher than 255.\n");
+  if (auto_spawn > 65000) {
+    substdio_puts(subfderr,"Oops. You have set conf-spawn higher than 65000.\n");
     substdio_flush(subfderr);
     _exit(1);
   }
@@ -44,5 +44,5 @@
     substdio_flush(subfderr);
     _exit(1);
   }
-  _exit(0);
+  return 0;
 }
diff -ruN qmail-1.03-orig/coe.h qmail-1.03-ldap-20060201-orig/coe.h
--- qmail-1.03-orig/coe.h	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/coe.h	2006-02-25 11:00:55.000000000 +0100
@@ -1,6 +1,6 @@
 #ifndef COE_H
 #define COE_H
 
-extern int coe();
+extern int coe(int);
 
 #endif
diff -ruN qmail-1.03-orig/commands.c qmail-1.03-ldap-20060201-orig/commands.c
--- qmail-1.03-orig/commands.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/commands.c	2006-02-25 11:00:55.000000000 +0100
@@ -11,6 +11,7 @@
 struct commands *c;
 {
   int i;
+  unsigned int n;
   char *arg;
 
   for (;;) {
@@ -28,13 +29,13 @@
 
     cmd.s[cmd.len] = 0;
 
-    i = str_chr(cmd.s,' ');
-    arg = cmd.s + i;
+    n = str_chr(cmd.s,' ');
+    arg = cmd.s + n;
     while (*arg == ' ') ++arg;
-    cmd.s[i] = 0;
+    cmd.s[n] = 0;
 
-    for (i = 0;c[i].text;++i) if (case_equals(c[i].text,cmd.s)) break;
-    c[i].fun(arg);
-    if (c[i].flush) c[i].flush();
+    for (n = 0;c[n].text;++n) if (case_equals(c[n].text,cmd.s)) break;
+    c[n].fun(arg);
+    if (c[n].flush) c[n].flush();
   }
 }
diff -ruN qmail-1.03-orig/commands.h qmail-1.03-ldap-20060201-orig/commands.h
--- qmail-1.03-orig/commands.h	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/commands.h	2006-02-25 11:00:55.000000000 +0100
@@ -1,12 +1,14 @@
 #ifndef COMMANDS_H
 #define COMMANDS_H
 
+#include "substdio.h"
+
 struct commands {
-  char *text;
+  const char *text;
   void (*fun)();
   void (*flush)();
 } ;
 
-extern int commands();
+extern int commands(substdio *, struct commands *);
 
 #endif
diff -ruN qmail-1.03-orig/condredirect.c qmail-1.03-ldap-20060201-orig/condredirect.c
--- qmail-1.03-orig/condredirect.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/condredirect.c	2006-02-25 11:00:55.000000000 +0100
@@ -1,3 +1,4 @@
+#include <unistd.h>
 #include "sig.h"
 #include "readwrite.h"
 #include "exit.h"
@@ -23,12 +24,12 @@
 
 char inbuf[SUBSTDIO_INSIZE];
 char outbuf[1];
-substdio ssin = SUBSTDIO_FDBUF(read,0,inbuf,sizeof inbuf);
+substdio ssin = SUBSTDIO_FDBUF(subread,0,inbuf,sizeof inbuf);
 substdio ssout = SUBSTDIO_FDBUF(mywrite,-1,outbuf,sizeof outbuf);
 
 char num[FMT_ULONG];
 
-void main(argc,argv)
+int main(argc,argv)
 int argc;
 char **argv;
 {
@@ -36,7 +37,7 @@
   char *dtline;
   int pid;
   int wstat;
-  char *qqx;
+  const char *qqx;
  
   if (!argv[1] || !argv[2])
     strerr_die1x(100,"condredirect: usage: condredirect newaddress program [ arg ... ]");
@@ -82,4 +83,6 @@
   qqx = qmail_close(&qqt);
   if (*qqx) strerr_die2x(*qqx == 'D' ? 100 : 111,FATAL,qqx + 1);
   strerr_die2x(99,"condredirect: qp ",num);
+  /* NOTREACHED */
+  return 1;
 }
diff -ruN qmail-1.03-orig/condwrite.c qmail-1.03-ldap-20060201-orig/condwrite.c
--- qmail-1.03-orig/condwrite.c	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/condwrite.c	2006-02-25 11:00:55.000000000 +0100
@@ -0,0 +1,509 @@
+/*
+ * Copyright (c) 2003-2004 Claudio Jeker,
+ *      Internet Business Solutions AG, CH-8005 Zürich, Switzerland
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Internet Business
+ *      Solutions AG and its contributors.
+ * 4. Neither the name of the author nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+/* based on qmail-local.c and condredirect.c by D. J. Bernstein */
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include "auto_qmail.h"
+#include "byte.h"
+#include "env.h"
+#include "error.h"
+#include "fmt.h"
+#include "getln.h"
+#include "gfrom.h"
+#include "lock.h"
+#include "maildir++.h"
+#include "now.h"
+#include "open.h"
+#include "qmail-ldap.h"
+#include "readwrite.h"
+#include "seek.h"
+#include "sig.h"
+#include "str.h"
+#include "stralloc.h"
+#include "strerr.h"
+#include "subfd.h"
+#include "substdio.h"
+#include "wait.h"
+#ifdef AUTOMAILDIRMAKE
+#include "mailmaker.h"
+#include "qldap-errno.h"
+#endif
+
+#define FATAL "condwrite: fatal: "
+
+void temp_nomem(void)
+{
+	strerr_die2x(111, FATAL, "Out of memory. (#4.3.0)");
+}
+
+void temp_rewind(void)
+{
+	strerr_die2x(111, FATAL, "Unable to rewind message. (#4.3.0)");
+}
+
+void temp_childcrashed(void)
+{
+	strerr_die2x(111, FATAL, "Aack, child crashed. (#4.3.0)");
+}
+
+void temp_fork(void)
+{
+	strerr_die4x(111, FATAL, "Unable to fork: ",
+	    error_str(errno), ". (#4.3.0)");
+}
+
+void
+temp_slowlock(void)
+{
+	strerr_die2x(111, FATAL,
+	    "File has been locked for 30 seconds straight. (#4.3.0)");
+}
+
+char		 fntmptph[80 + FMT_ULONG * 2];
+char		 fnnewtph[83 + FMT_ULONG * 3];
+
+void
+tryunlinktmp(void)
+{
+	unlink(fntmptph);
+}
+
+void
+sigalrm(void)
+{
+	tryunlinktmp();
+	_exit(3);
+}
+
+char		*quotastring;
+
+stralloc	 dtline = {0};
+stralloc	 rpline = {0};
+stralloc	 ufline = {0};
+stralloc	 messline = {0};
+
+char		 buf[1024];
+char		 outbuf[1024];
+int		 msfd = -1; /* global filedescriptor to the quota file */
+
+void
+maildir_child(char *dir)
+{
+	substdio	 ss, ssout;
+	struct stat	 st;
+	unsigned long	 pid, tnow;
+	char		 host[64];
+	char		*s;
+	int		 loop, fd;
+
+	sig_alarmcatch(sigalrm);
+	if (chdir(dir) == -1) {
+		if (error_temp(errno))
+			_exit(1);
+		else
+			_exit(2);
+	}
+
+	pid = getpid();
+	host[0] = 0;
+	gethostname(host, sizeof(host));
+	for (loop = 0;;++loop) {
+		tnow = now();
+		s = fntmptph;
+		s += fmt_str(s, "tmp/");
+		s += fmt_ulong(s, tnow); *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);
+		sleep(2);
+	}
+	str_copy(fnnewtph, fntmptph);
+	byte_copy(fnnewtph, 3, "new");
+
+	alarm(86400);
+	fd = open_excl(fntmptph);
+	if (fd == -1)
+		_exit(1);
+
+	substdio_fdbuf(&ss, subread, 0, buf, sizeof(buf));
+	substdio_fdbuf(&ssout, subwrite, fd, outbuf, sizeof(outbuf));
+	if (substdio_put(&ssout, rpline.s, rpline.len) == -1) goto fail;
+	if (substdio_put(&ssout, dtline.s, dtline.len) == -1) goto fail;
+
+	switch(substdio_copy(&ssout, &ss)) {
+	case -2:
+		tryunlinktmp();
+		_exit(4);
+	case -3:
+		goto fail;
+	}
+
+	if (substdio_flush(&ssout) == -1) goto fail;
+	if (fsync(fd) == -1) goto fail;
+	if (fstat(fd, &st) == -1) goto fail;
+	if (close(fd) == -1) goto fail; /* NFS dorks */
+
+	s = fnnewtph;
+	while(*s) s++;
+	s += fmt_str(s,",S=");
+	s += fmt_ulong(s,(unsigned long)st.st_size);
+	*s++ = 0;
+
+	if(quotastring && *quotastring) {
+		/* finally update the quota file "maildirsize" */
+		quota_add(msfd, (unsigned long)st.st_size, 1);
+		close(msfd);
+	}
+
+	if (link(fntmptph, fnnewtph) == -1) goto fail;
+	/* if it was error_exist, almost certainly successful; i hate NFS */
+	tryunlinktmp();
+	_exit(0);
+
+fail:
+	tryunlinktmp();
+	_exit(1);
+}
+
+/* end child process */
+
+/* quota handling warning and bounce */
+void
+quota_bounce(const char *type)
+{
+	strerr_die4x(100, FATAL, "The users ", type,
+	    " is over the allowed quota (size). (#5.2.2)");
+}
+
+stralloc	qwapp = {0};
+
+void
+quota_warning(char *fn)
+{
+	char	*(args[3]);
+	int	 child, wstat;
+
+	if (!stralloc_copys(&qwapp, auto_qmail)) temp_nomem();
+	if (!stralloc_cats(&qwapp, "/bin/qmail-quotawarn")) temp_nomem();
+	if (!stralloc_0(&qwapp)) temp_nomem();
+
+	if (seek_begin(0) == -1) temp_rewind();
+
+	switch(child = fork()) {
+	case -1:
+		temp_fork();
+	case 0:
+		args[0] = qwapp.s; args[1] = fn; args[2] = 0;
+		sig_pipedefault();
+		execv(*args,args);
+		_exit(2);
+	}
+
+	wait_pid(&wstat,child);
+	if (wait_crashed(wstat))
+		temp_childcrashed();
+	switch(wait_exitcode(wstat)) {
+	case 2:
+		strerr_die6x(111, FATAL, "Unable to run quotawarn program: ",
+		    qwapp.s, ": ",error_str(errno),". (#4.2.2)");
+	case 111:
+		_exit(111);
+	case 0:
+		break;
+	default:
+		_exit(100);
+	}
+
+}
+
+/* end -- quota handling warning and bounce */
+
+void
+maildir_write(char *fn)
+{
+	struct stat	mailst;
+	quota_t		q;
+	unsigned long	mailsize;
+	int		child, wstat, perc;
+
+#ifdef AUTOMAILDIRMAKE
+	switch (maildir_make(fn)) {
+	case OK:
+		break;
+	case MAILDIR_CORRUPT:
+		strerr_die4x(111, FATAL, "The maildir '", fn,
+		    "' seems to be corrupted. (#4.2.1)");
+	case ERRNO:
+	default:
+		strerr_die4x(111, FATAL, "Unable to create maildir '",
+		    fn, "' (#4.3.0)");
+	}
+#endif
+
+	if (quotastring && *quotastring) {
+		if (fstat(0, &mailst) != 0)
+			strerr_die4x(111, FATAL,
+			    "Can not stat mail for quota: ",
+			    error_str(errno), ". (#4.3.0)");
+		mailsize = mailst.st_size;
+		quota_get(&q, quotastring);
+		if (quota_calc(fn, &msfd, &q) == -1) {
+			/* second chance */
+			sleep(3);
+			if (quota_calc(fn, &msfd, &q) == -1) {
+				strerr_die2x(111, FATAL,
+				    "Temporary race condition while "
+				    "calculating quota. (#4.3.0)");
+			}
+		}
+		/* fd can be -1, quota_add/rm take care of that */
+
+		if (quota_check(&q, mailsize, 1, &perc) != 0) { /* 0 if OK */
+			if (quota_recalc(fn, &msfd, &q) == -1) {
+				/* second chance */
+				sleep(3);
+				if (quota_recalc(fn, &msfd, &q) == -1)
+					strerr_die2x(111, FATAL,
+					    "Temporary race condition while "
+					    "recalculating quota. (#4.3.0)");
+			}
+			if (quota_check(&q, mailsize, 1, &perc) != 0) {
+				/* bounce mail but drop a warning first */
+				quota_warning(fn);
+				quota_bounce("mailfolder");
+			}
+		}
+		/* fd can be -1, quota_add/rm take care of that */
+
+		if (perc >= QUOTA_WARNING_LEVEL) 
+			/* drop a warning when mailbox is around 80% full */
+			quota_warning(fn);
+	}
+
+	/* end -- quota handling maildir */
+
+	if (seek_begin(0) == -1) temp_rewind();
+
+	switch(child = fork()) {
+	case -1:
+		temp_fork();
+	case 0:
+		maildir_child(fn);
+		_exit(111);
+	}
+
+	if (msfd != -1)
+		close(msfd);
+	/* close the maildirsize fd in the parent */
+
+	wait_pid(&wstat,child);
+	if (wait_crashed(wstat))
+		temp_childcrashed();
+	switch(wait_exitcode(wstat))
+	{
+	case 0:
+		/* we exit with 99 so no more deliveries are done */
+		_exit(99);
+	case 2:
+		strerr_die2x(111, FATAL,
+		    "Unable to chdir to maildir. (#4.2.1)");
+	case 3:
+		strerr_die2x(111, FATAL,
+		    "Timeout on maildir delivery. (#4.3.0)");
+	case 4:
+		strerr_die2x(111, FATAL, "Unable to read message. (#4.3.0)");
+	default:
+		strerr_die2x(111, FATAL,
+		    "Temporary error on maildir delivery. (#4.3.0)");
+	}
+}
+
+void
+mailfile(char *fn)
+{
+	substdio	ss, ssout;
+	struct stat	filest, mailst;
+	quota_t		q;
+	seek_pos	pos;
+	unsigned long	totalsize;
+	int		fd, match, flaglocked;
+
+	if(quotastring && *quotastring) {
+		quota_get(&q, quotastring);
+		if (stat(fn, &filest) == -1) {
+		 	/* size of nonexisting mailfile */
+			filest.st_size = 0;
+			if ( errno != error_noent)
+				strerr_die6x(111, FATAL, "Unable to quota ", fn,
+				    ": ",error_str(errno), ". (#4.3.0)");
+		}
+		if (fstat(0, &mailst) != 0)
+			strerr_die4x(111, FATAL, "Unable to quota mail: ",
+			    error_str(errno), ". (#4.3.0)");
+
+		totalsize = (unsigned long)filest.st_size +
+		    (unsigned long)mailst.st_size;
+		if (totalsize * 100 / q.quota_size >= QUOTA_WARNING_LEVEL)
+			/* drop a warning when mailbox is around 80% full */
+			quota_warning(fn);
+		if (totalsize > q.quota_size)
+			quota_bounce("mailbox");
+	}
+
+	/* end -- quota handling mbox */
+
+	if (seek_begin(0) == -1) temp_rewind();
+
+	fd = open_append(fn);
+	if (fd == -1)
+		strerr_die6x(111, FATAL, "Unable to open ",fn,": ",
+		    error_str(errno),". (#4.2.1)");
+
+	sig_alarmcatch(temp_slowlock);
+	alarm(30);
+	flaglocked = (lock_ex(fd) != -1);
+	alarm(0);
+	sig_alarmdefault();
+
+	seek_end(fd);
+	pos = seek_cur(fd);
+
+	substdio_fdbuf(&ss, subread, 0, buf, sizeof(buf));
+	substdio_fdbuf(&ssout, subwrite, fd, outbuf, sizeof(outbuf));
+	if (substdio_put(&ssout, ufline.s, ufline.len)) goto writeerrs;
+	if (substdio_put(&ssout, rpline.s, rpline.len)) goto writeerrs;
+	if (substdio_put(&ssout, dtline.s, dtline.len)) goto writeerrs;
+
+	for (;;) {
+		if (getln(&ss, &messline, &match, '\n') != 0) {
+			strerr_warn4(FATAL, "Unable to read message: ",
+			    error_str(errno),". (#4.3.0)",0);
+			if (flaglocked)
+				seek_trunc(fd, pos);
+			close(fd);
+			_exit(111);
+		}
+		if (!match && !messline.len) break;
+		if (gfrom(messline.s, messline.len))
+			if (substdio_bput(&ssout, ">", 1)) goto writeerrs;
+		if (substdio_bput(&ssout, messline.s, messline.len))
+			goto writeerrs;
+		if (!match) {
+			if (substdio_bputs(&ssout, "\n")) goto writeerrs;
+			break;
+		}
+	}
+	if (substdio_bputs(&ssout, "\n")) goto writeerrs;
+	if (substdio_flush(&ssout)) goto writeerrs;
+	if (fsync(fd) == -1) goto writeerrs;
+	close(fd);
+	_exit(99);
+
+writeerrs:
+	strerr_warn6(FATAL, "Unable to write ", fn, ": ",
+	    error_str(errno), ". (#4.3.0)",0);
+	if (flaglocked) seek_trunc(fd, pos);
+	close(fd);
+	_exit(111);
+}
+
+int main(int argc, char **argv)
+{
+	char	*s;
+	int	 pid, wstat;
+
+	if (!env_init()) temp_nomem();
+	if (!argv[1] || !argv[2])
+		strerr_die1x(100,"condwrite: usage: "
+		    "condwrite {maildir/|mailfile} program [ arg ... ]");
+
+	if ((s = env_get("RPLINE"))) { 
+		if (!stralloc_copys(&rpline, s)) temp_nomem();
+	} else
+		strerr_die2x(100, FATAL, "RPLINE not present.");
+
+	if ((s = env_get("DTLINE"))) {
+		if (!stralloc_copys(&dtline, s)) temp_nomem();
+	} else
+		strerr_die2x(100, FATAL, "DTLINE not present.");
+
+	if ((s = env_get("UFLINE"))) {
+		if (!stralloc_copys(&ufline, s)) temp_nomem();
+	} else
+		strerr_die2x(100, FATAL, "UFLINE not present.");
+
+	pid = fork();
+	if (pid == -1)
+		temp_fork();
+	if (pid == 0) {
+		execvp(argv[2],argv + 2);
+		if (error_temp(errno)) _exit(111);
+		_exit(100);
+	}
+
+	if (wait_pid(&wstat,pid) == -1)
+		strerr_die2x(111,FATAL,"wait failed");
+	if (wait_crashed(wstat))
+		temp_childcrashed();
+
+	switch(wait_exitcode(wstat)) {
+	case 0:
+		break;
+	case 111:
+		strerr_die2x(111,FATAL,"temporary child error");
+	default:
+		  _exit(0);
+	}
+
+	if (seek_begin(0) == -1)
+		temp_rewind();
+	sig_pipeignore();
+
+	/* quota, dotmode and forwarding handling - part 1 */
+	/* setting the quota */
+	quotastring = env_get(ENV_QUOTA);
+ 
+	if(argv[1][str_len(argv[1]) - 1] == '/')
+		maildir_write(argv[1]);
+	else
+		mailfile(argv[1]);
+
+	return (100);
+}
diff -ruN qmail-1.03-orig/conf-spawn qmail-1.03-ldap-20060201-orig/conf-spawn
--- qmail-1.03-orig/conf-spawn	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/conf-spawn	2006-02-25 11:00:55.000000000 +0100
@@ -1,4 +1,4 @@
-120
+500
 
 This is a silent concurrency limit. You can't set it above 255. On some
 systems you can't set it above 125. qmail will refuse to compile if the
diff -ruN qmail-1.03-orig/constmap.c qmail-1.03-ldap-20060201-orig/constmap.c
--- qmail-1.03-orig/constmap.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/constmap.c	2006-02-25 11:00:55.000000000 +0100
@@ -3,8 +3,8 @@
 #include "case.h"
 
 static constmap_hash hash(s,len)
-char *s;
-int len;
+const char *s;
+unsigned int len;
 {
   unsigned char ch;
   constmap_hash h;
@@ -18,10 +18,10 @@
   return h;
 }
 
-char *constmap(cm,s,len)
+const char *constmap(cm,s,len)
 struct constmap *cm;
-char *s;
-int len;
+const char *s;
+unsigned int len;
 {
   constmap_hash h;
   int pos;
@@ -39,28 +39,29 @@
 
 int constmap_init(cm,s,len,flagcolon)
 struct constmap *cm;
-char *s;
-int len;
+const char *s;
+unsigned int len;
 int flagcolon;
 {
-  int i;
-  int j;
-  int k;
+  unsigned int i;
+  unsigned int j;
+  unsigned int k;
   int pos;
   constmap_hash h;
  
   cm->num = 0;
   for (j = 0;j < len;++j) if (!s[j]) ++cm->num;
+  if (cm->num < 0) return 0;
  
   h = 64;
-  while (h && (h < cm->num)) h += h;
+  while (h && (h < cm->num)) h += h; /* XXX why is num an int */
   cm->mask = h - 1;
  
   cm->first = (int *) alloc(sizeof(int) * h);
   if (cm->first) {
-    cm->input = (char **) alloc(sizeof(char *) * cm->num);
+    cm->input = (const char **) alloc(sizeof(char *) * cm->num);
     if (cm->input) {
-      cm->inputlen = (int *) alloc(sizeof(int) * cm->num);
+      cm->inputlen = (unsigned int *) alloc(sizeof(unsigned int) * cm->num);
       if (cm->inputlen) {
         cm->hash = (constmap_hash *) alloc(sizeof(constmap_hash) * cm->num);
         if (cm->hash) {
@@ -111,4 +112,5 @@
   alloc_free(cm->inputlen);
   alloc_free(cm->input);
   alloc_free(cm->first);
+  cm->num = 0;
 }
diff -ruN qmail-1.03-orig/constmap.h qmail-1.03-ldap-20060201-orig/constmap.h
--- qmail-1.03-orig/constmap.h	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/constmap.h	2006-02-25 11:00:55.000000000 +0100
@@ -9,12 +9,12 @@
   constmap_hash *hash;
   int *first;
   int *next;
-  char **input;
-  int *inputlen;
+  const char **input;
+  unsigned int *inputlen;
 } ;
 
-extern int constmap_init();
-extern void constmap_free();
-extern char *constmap();
+extern int constmap_init(struct constmap *, const char *, unsigned int, int);
+extern void constmap_free(struct constmap *);
+extern const char *constmap(struct constmap *, const char *, unsigned int);
 
 #endif
diff -ruN qmail-1.03-orig/control.c qmail-1.03-ldap-20060201-orig/control.c
--- qmail-1.03-orig/control.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/control.c	2006-02-25 11:00:55.000000000 +0100
@@ -1,3 +1,4 @@
+#include <unistd.h>
 #include "readwrite.h"
 #include "open.h"
 #include "getln.h"
@@ -7,6 +8,7 @@
 #include "control.h"
 #include "alloc.h"
 #include "scan.h"
+#include "limit.h"
 
 static char inbuf[64];
 static stralloc line = {0};
@@ -27,7 +29,7 @@
     }
 }
 
-int control_init()
+int control_init(void)
 {
  int r;
  r = control_readline(&me,"control/me");
@@ -37,9 +39,9 @@
 
 int control_rldef(sa,fn,flagme,def)
 stralloc *sa;
-char *fn;
+const char *fn;
 int flagme;
-char *def;
+const char *def;
 {
  int r;
  r = control_readline(sa,fn);
@@ -51,7 +53,7 @@
 
 int control_readline(sa,fn)
 stralloc *sa;
-char *fn;
+const char *fn;
 {
  substdio ss;
  int fd;
@@ -60,7 +62,7 @@
  fd = open_read(fn);
  if (fd == -1) { if (errno == error_noent) return 0; return -1; }
  
- substdio_fdbuf(&ss,read,fd,inbuf,sizeof(inbuf));
+ substdio_fdbuf(&ss,subread,fd,inbuf,sizeof(inbuf));
 
  if (getln(&ss,sa,&match,'\n') == -1) { close(fd); return -1; }
 
@@ -71,7 +73,7 @@
 
 int control_readint(i,fn)
 int *i;
-char *fn;
+const char *fn;
 {
  unsigned long u;
  switch(control_readline(&line,fn))
@@ -81,13 +83,33 @@
   }
  if (!stralloc_0(&line)) return -1;
  if (!scan_ulong(line.s,&u)) return 0;
+ if (u > INT_MAX) {
+   errno = error_range;
+   return -1;
+ }
  *i = u;
  return 1;
 }
 
+int control_readulong(ul,fn)
+unsigned long *ul;
+const char *fn;
+{
+ unsigned long u;
+ switch(control_readline(&line,fn))
+  {
+   case 0: return 0;
+   case -1: return -1;
+  }
+ if (!stralloc_0(&line)) return -1;
+ if (!scan_ulong(line.s,&u)) return 0;
+ *ul = u;
+ return 1;
+}
+
 int control_readfile(sa,fn,flagme)
 stralloc *sa;
-char *fn;
+const char *fn;
 int flagme;
 {
  substdio ss;
@@ -112,7 +134,7 @@
    return -1;
   }
 
- substdio_fdbuf(&ss,read,fd,inbuf,sizeof(inbuf));
+ substdio_fdbuf(&ss,subread,fd,inbuf,sizeof(inbuf));
 
  for (;;)
   {
@@ -128,3 +150,33 @@
  close(fd);
  return -1;
 }
+
+int control_readrawfile(sa,fn)
+stralloc *sa;
+const char *fn;
+{
+ substdio ss;
+ int fd;
+ int match;
+
+ if (!stralloc_copys(sa,"")) return -1;
+
+ fd = open_read(fn);
+ if (fd == -1) 
+  {
+   if (errno == error_noent) return 0;
+   return -1;
+  }
+
+ substdio_fdbuf(&ss,subread,fd,inbuf,sizeof(inbuf));
+
+ for (;;)
+  {
+   if (getln(&ss,&line,&match,'\n') == -1) break;
+   if (!match && !line.len) { close(fd); return 1; }
+   if (!stralloc_cat(sa,&line)) break;
+   if (!match) { close(fd); return 1; }
+  }
+ close(fd);
+ return -1;
+}
diff -ruN qmail-1.03-orig/control.h qmail-1.03-ldap-20060201-orig/control.h
--- qmail-1.03-orig/control.h	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/control.h	2006-02-25 11:00:55.000000000 +0100
@@ -1,10 +1,14 @@
 #ifndef CONTROL_H
 #define CONTROL_H
 
-extern int control_init();
-extern int control_readline();
-extern int control_rldef();
-extern int control_readint();
-extern int control_readfile();
+#include "stralloc.h"
+
+extern int control_init(void);
+extern int control_readline(stralloc *, const char *);
+extern int control_rldef(stralloc *, const char *, int, const char *);
+extern int control_readint(int *, const char *);
+extern int control_readulong(unsigned long *, const char *);
+extern int control_readfile(stralloc *, const char *, int);
+extern int control_readrawfile(stralloc *, const char *);
 
 #endif
diff -ruN qmail-1.03-orig/date822fmt.c qmail-1.03-ldap-20060201-orig/date822fmt.c
--- qmail-1.03-orig/date822fmt.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/date822fmt.c	2006-02-25 11:00:55.000000000 +0100
@@ -2,7 +2,7 @@
 #include "fmt.h"
 #include "date822fmt.h"
 
-static char *montab[12] = {
+static const char *montab[12] = {
 "Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"
 };
 
diff -ruN qmail-1.03-orig/date822fmt.h qmail-1.03-ldap-20060201-orig/date822fmt.h
--- qmail-1.03-orig/date822fmt.h	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/date822fmt.h	2006-02-25 11:00:55.000000000 +0100
@@ -1,7 +1,9 @@
 #ifndef DATE822FMT_H
 #define DATE822FMT_H
 
-extern unsigned int date822fmt();
+#include "datetime.h"
+
+extern unsigned int date822fmt(char *, struct datetime *);
 #define DATE822FMT 60
 
 #endif
diff -ruN qmail-1.03-orig/datetime.h qmail-1.03-ldap-20060201-orig/datetime.h
--- qmail-1.03-orig/datetime.h	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/datetime.h	2006-02-25 11:00:55.000000000 +0100
@@ -14,7 +14,7 @@
 
 typedef long datetime_sec;
 
-extern void datetime_tai();
-extern datetime_sec datetime_untai();
+extern void datetime_tai(struct datetime *, datetime_sec);
+extern datetime_sec datetime_untai(struct datetime *);
 
 #endif
diff -ruN qmail-1.03-orig/digest.c qmail-1.03-ldap-20060201-orig/digest.c
--- qmail-1.03-orig/digest.c	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/digest.c	2006-02-25 11:00:55.000000000 +0100
@@ -0,0 +1,231 @@
+/*
+ * Copyright (c) 1998-2004 Andre Oppermann, Claudio Jeker,
+ *      Internet Business Solutions AG, CH-8005 Zürich, Switzerland
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Internet Business
+ *      Solutions AG and its contributors.
+ * 4. Neither the name of the author nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#include <sys/types.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include "base64.h"
+#include "case.h"
+#include "error.h"
+#include "passwd.h"
+#include "qldap-errno.h"
+#include "readwrite.h"
+#include "sgetopt.h"
+#include "stralloc.h"
+
+
+#define RANDDEV "/dev/urandom"
+
+const char *mode[] = {
+	"{CRYPT}",
+       	"{MD4}",
+       	"{MD5}",
+       	"{NS-MTA-MD5}",
+       	"{SMD5}",
+       	"{SHA}",
+       	"{SSHA}",
+       	"{RMD160}",
+       	0
+};
+
+const char *mode2[] = {
+	"crypt",
+       	"md4",
+       	"md5",
+       	"ns-mta-md5",
+       	"smd5",
+       	"sha",
+       	"ssha",
+       	"rmd160",
+       	0
+};
+
+stralloc pw = {0};
+stralloc salt = {0};
+
+void
+usage(void)
+{
+	fprintf(stderr,
+	    "usage:\tdigest [ -c ] [ -b | -5 | -C | -f cryptformat ] [ -s base64Salt ]\n\t[ -S hexSalt ] [ -t type ] passwd\n"
+	    "\tdigest -v password hashedPassword\n");
+	exit(1);
+}
+
+void
+getsalt(stralloc *b, int blen)
+{
+	char buf[64];
+	int l, fd;
+	
+	fd = open(RANDDEV, O_RDONLY);
+	if (fd == -1) {
+		fprintf(stderr, "digest: open %s failed: %s.\n",
+		    RANDDEV, error_str(errno));
+		exit(1);
+	}
+	l = read(fd, buf, sizeof(buf));
+	if (l == -1) {
+		fprintf(stderr, "digest: read failed: %s.\n",
+		    error_str(errno));
+		exit(1);
+	}
+	if (l < blen) {
+		fprintf(stderr, "digest: not enough random data read.\n");
+		exit(1);
+	}
+	if (!stralloc_copyb(b, buf, blen)) {
+		fprintf(stderr, "digest: stralloc_copyb failed: %s.\n",
+		    error_str(errno));
+		exit(1);
+	}
+}
+
+int
+main(int argc, char *argv[])
+{
+	int	i, opt, m, type = -1;
+	char	*clear, *encrypted;
+	const char *cformat;
+	
+	clear = (char *)0;
+	encrypted = (char *)0;
+	m = 0;
+	cformat = "XX";
+	while ((opt = getopt(argc, argv, "5bcf:s:S:t:v")) != opteof)
+		switch (opt) {
+		case '5':
+			/* md5 format */
+			cformat = "$1$XXXXXXXX$";
+			break;
+		case 'b':
+			/* blowfish format */
+			cformat = "$2a$07$XXXXXXXXXXXXXXXXXXXXXXXX";
+			break;
+		case 'C':
+			/* good (acctually bad) old crypt */
+			cformat = "XX";
+			break;
+		case 'c':
+			m = 0;
+			break;
+		case 'f':
+			cformat = optarg;
+			break;
+		case 's':
+			if (b64_ptons(optarg, &salt) == -1) {
+				fprintf(stderr, "digest: bad base64 string.\n");
+				usage();
+			}
+			break;
+		case 'S':
+			if (hex_ptons(optarg, &salt) == -1) {
+				fprintf(stderr, "digest: bad hex string.\n");
+				usage();
+			}
+			break;
+		case 't':
+			for (i = 0; mode2[i] != 0; i++)
+				if (!case_diffs(mode2[i], optarg))
+					break;
+			if (mode2[i]) {
+				type = i;
+				break;
+			}
+			fprintf(stderr,
+			    "digest: bad digest type, use one of:\n");
+			for (i = 0; mode2[i] != 0; i++)
+				fprintf(stderr, "\t%s\n", mode2[i]);
+			exit(1);
+		case 'v':
+			m = 1;
+			break;
+		default:
+			
+			usage();
+		}
+
+	argc -= optind;
+	argv += optind;
+	if (m == 0) {
+		if (argc != 1) usage();
+		clear = argv[0];
+		if (salt.s == 0)
+			getsalt(&salt, 18); /* actually 128bit salt but add
+					     * a bit for base64 errors */
+		feed_salt(salt.s, salt.len);
+		feed_crypt(cformat);
+		if (type != -1) {
+			if (make_passwd(mode[type], clear, &pw) == OK) {
+				stralloc_0(&pw);
+				printf("%s%s\n", mode[type], pw.s);
+			} else
+				printf("%s failed.\n", mode2[type]);
+		} else 
+			for (i = 0; mode[i] != 0; i++) {
+				if (make_passwd(mode[i], clear, &pw) == OK) {
+					stralloc_0(&pw);
+					printf("%s%s\n", mode[i], pw.s);
+				} else
+					printf("%s failed.\n", mode2[i]);
+			}
+	} else {
+		if (argc != 2) usage();
+		clear = argv[0];
+		encrypted = argv[1];
+		switch(cmp_passwd(clear, encrypted)) {
+		case OK:
+			printf("passwords are equal.\n");
+			break;
+		case BADPASS:
+			printf("passwords are NOT equal.\n");
+			break;
+		case ERRNO:
+			printf("digest: cmp_passwd: %s.\n", error_str(errno));
+			exit(1);
+		case ILLVAL:
+			printf("digest: cmp_password: "
+			    "illegal hashed password.\n");
+			exit(1);
+		default:
+			printf("digest: cmp_password: failed.");
+			exit(1);
+		}
+	}
+	
+	exit(0);
+}
+
diff -ruN qmail-1.03-orig/digest_md4.c qmail-1.03-ldap-20060201-orig/digest_md4.c
--- qmail-1.03-orig/digest_md4.c	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/digest_md4.c	2006-02-25 11:00:55.000000000 +0100
@@ -0,0 +1,290 @@
+/* digest_md4.c for QLDAP modified to use djb stuff    */
+/* contains MD4 algorithm stolen directly from OpenBSD */
+
+/*        */
+/*  MD4   */
+/*        */
+
+/* Copyright (C) 1990-2, RSA Data Security, Inc. All rights reserved.
+
+   License to copy and use this software is granted provided that it
+   is identified as the "RSA Data Security, Inc. MD4 Message-Digest
+   Algorithm" in all material mentioning or referencing this software
+   or this function.
+
+   License is also granted to make and use derivative works provided
+   that such works are identified as "derived from the RSA Data
+   Security, Inc. MD4 Message-Digest Algorithm" in all material
+   mentioning or referencing the derived work.
+
+   RSA Data Security, Inc. makes no representations concerning either
+   the merchantability of this software or the suitability of this
+   software for any particular purpose. It is provided "as is"
+   without express or implied warranty of any kind.
+
+   These notices must be retained in any copies of any part of this
+   documentation and/or software.
+ */
+
+#include <sys/types.h>
+#include "uint32.h"
+#include "byte.h"
+#include "digest_md4.h"
+
+/* POINTER defines a generic pointer type */
+typedef unsigned char *POINTER;
+
+/* Constants for MD4Transform routine.
+ */
+#define S11 3
+#define S12 7
+#define S13 11
+#define S14 19
+#define S21 3
+#define S22 5
+#define S23 9
+#define S24 13
+#define S31 3
+#define S32 9
+#define S33 11
+#define S34 15
+
+static void MD4Transform(uint32 [4], const unsigned char [64]);
+
+#ifdef __LITTLE_ENDIAN__
+#define Encode byte_copy
+#define Decode byte_copy
+#else  /* __BIG_ENDIAN__ */
+static void Encode(void *, size_t, const void *);
+static void Decode(void *, size_t, const void *);
+#endif /* __LITTLE_ENDIAN__ */
+
+static unsigned char PADDING[64] = {
+  0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+/* F, G and H are basic MD4 functions.
+ */
+#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
+#define G(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
+#define H(x, y, z) ((x) ^ (y) ^ (z))
+
+/* ROTATE_LEFT rotates x left n bits.
+ */
+#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
+
+/* FF, GG and HH are transformations for rounds 1, 2 and 3 */
+/* Rotation is separate from addition to prevent recomputation */
+#define FF(a, b, c, d, x, s) { \
+    (a) += F ((b), (c), (d)) + (x); \
+    (a) = ROTATE_LEFT ((a), (s)); \
+  }
+#define GG(a, b, c, d, x, s) { \
+    (a) += G ((b), (c), (d)) + (x) + (uint32)0x5a827999; \
+    (a) = ROTATE_LEFT ((a), (s)); \
+  }
+#define HH(a, b, c, d, x, s) { \
+    (a) += H ((b), (c), (d)) + (x) + (uint32)0x6ed9eba1; \
+    (a) = ROTATE_LEFT ((a), (s)); \
+  }
+
+#ifdef __BIG_ENDIAN__
+/* Encodes input (uint32) into output (unsigned char). Assumes len is
+     a multiple of 4.
+ */
+static void
+Encode(void *out, size_t len, const void *in)
+{
+  const uint32 *input = in;
+  unsigned char *output = out;
+  size_t i, j;
+
+  for (i = 0, j = 0; j < len; i++, j += 4) {
+    output[j] = (unsigned char)(input[i] & 0xff);
+    output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
+    output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
+    output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
+  }
+}
+
+/* Decodes input (unsigned char) into output (uint32). Assumes len is
+     a multiple of 4.
+ */
+static void
+Decode(void *out, size_t len, const void *in)
+{
+  uint32 *output = out;
+  const unsigned char *input = in;
+  size_t i, j;
+
+  for (i = 0, j = 0; j < len; i++, j += 4)
+    output[i] = ((uint32)input[j]) | (((uint32)input[j+1]) << 8) |
+      (((uint32)input[j+2]) << 16) | (((uint32)input[j+3]) << 24);
+}
+#endif /* __BIG_ENDIAN__ */
+
+/* MD4 initialization. Begins an MD4 operation, writing a new context.
+ */
+void
+MD4Init(MD4_CTX *context)
+{
+  context->count[0] = 0;
+  context->count[1] = 0;
+
+  /* Load magic initialization constants.
+   */
+  context->state[0] = 0x67452301;
+  context->state[1] = 0xefcdab89;
+  context->state[2] = 0x98badcfe;
+  context->state[3] = 0x10325476;
+}
+
+/* MD4 block update operation. Continues an MD4 message-digest
+     operation, processing another message block, and updating the
+     context.
+ */
+void
+MD4Update(MD4_CTX *context, const unsigned char *input, size_t inputLen)
+{
+  unsigned int i, idx, partLen;
+
+  /* Compute number of bytes mod 64 */
+  idx = (unsigned int)((context->count[0] >> 3) & 0x3F);
+
+  /* Update number of bits */
+  if ( (context->count[0] += ((uint32)inputLen << 3)) /* lower part of count */
+       < ((uint32)inputLen << 3) )
+    context->count[1]++; /* low part of count overflowed */
+
+  context->count[1] += ((uint32)inputLen >> 29); /* update high part of count */
+
+  partLen = 64 - idx;
+  /* Transform as many times as possible.  */
+  if (inputLen >= partLen) {
+    byte_copy
+      ((POINTER)&context->buffer[idx], partLen, input);
+    MD4Transform(context->state, context->buffer);
+
+    for (i = partLen; i + 63 < inputLen; i += 64)
+      MD4Transform(context->state, &input[i]);
+
+    idx = 0;
+  }
+  else
+    i = 0;
+
+  /* Buffer remaining input */
+  byte_copy
+    ((POINTER)&context->buffer[idx], inputLen-i, &input[i]);
+}
+
+/* MD4 finalization. Ends an MD4 message-digest operation, writing the
+     the message digest and zeroizing the context.
+ */
+void
+MD4Final(unsigned char digest[MD4_LEN], MD4_CTX *context)
+{
+  unsigned char bits[8];
+  unsigned int idx, padLen;
+  uint32 hi, lo;
+
+  /* Save number of bits */
+  hi = context->count[1];
+  lo = context->count[0];
+  Encode (bits, 4, &lo);
+  Encode (bits + 4, 4, &hi);
+
+  /* Pad out to 56 mod 64.
+   */
+  idx = (unsigned int)((context->count[0] >> 3) & 0x3f);
+  padLen = (idx < 56) ? (56 - idx) : (120 - idx);
+  MD4Update (context, PADDING, padLen);
+
+  /* Append length (before padding) */
+  MD4Update (context, bits, 8);
+
+  if (digest != (unsigned char *)0) {
+    /* Store state in digest */
+    Encode (digest, 16, context->state);
+
+    /* Zeroize sensitive information.
+     */
+	byte_zero((POINTER) context, sizeof (*context));
+  }
+}
+
+/* MD4 basic transformation. Transforms state based on block.
+ */
+static void
+MD4Transform(uint32 state[4], const unsigned char block[64])
+{
+  uint32 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
+
+  Decode (x, 64, block);
+
+  /* Round 1 */
+  FF (a, b, c, d, x[ 0], S11); /* 1 */
+  FF (d, a, b, c, x[ 1], S12); /* 2 */
+  FF (c, d, a, b, x[ 2], S13); /* 3 */
+  FF (b, c, d, a, x[ 3], S14); /* 4 */
+  FF (a, b, c, d, x[ 4], S11); /* 5 */
+  FF (d, a, b, c, x[ 5], S12); /* 6 */
+  FF (c, d, a, b, x[ 6], S13); /* 7 */
+  FF (b, c, d, a, x[ 7], S14); /* 8 */
+  FF (a, b, c, d, x[ 8], S11); /* 9 */
+  FF (d, a, b, c, x[ 9], S12); /* 10 */
+  FF (c, d, a, b, x[10], S13); /* 11 */
+  FF (b, c, d, a, x[11], S14); /* 12 */
+  FF (a, b, c, d, x[12], S11); /* 13 */
+  FF (d, a, b, c, x[13], S12); /* 14 */
+  FF (c, d, a, b, x[14], S13); /* 15 */
+  FF (b, c, d, a, x[15], S14); /* 16 */
+
+  /* Round 2 */
+  GG (a, b, c, d, x[ 0], S21); /* 17 */
+  GG (d, a, b, c, x[ 4], S22); /* 18 */
+  GG (c, d, a, b, x[ 8], S23); /* 19 */
+  GG (b, c, d, a, x[12], S24); /* 20 */
+  GG (a, b, c, d, x[ 1], S21); /* 21 */
+  GG (d, a, b, c, x[ 5], S22); /* 22 */
+  GG (c, d, a, b, x[ 9], S23); /* 23 */
+  GG (b, c, d, a, x[13], S24); /* 24 */
+  GG (a, b, c, d, x[ 2], S21); /* 25 */
+  GG (d, a, b, c, x[ 6], S22); /* 26 */
+  GG (c, d, a, b, x[10], S23); /* 27 */
+  GG (b, c, d, a, x[14], S24); /* 28 */
+  GG (a, b, c, d, x[ 3], S21); /* 29 */
+  GG (d, a, b, c, x[ 7], S22); /* 30 */
+  GG (c, d, a, b, x[11], S23); /* 31 */
+  GG (b, c, d, a, x[15], S24); /* 32 */
+
+  /* Round 3 */
+  HH (a, b, c, d, x[ 0], S31); /* 33 */
+  HH (d, a, b, c, x[ 8], S32); /* 34 */
+  HH (c, d, a, b, x[ 4], S33); /* 35 */
+  HH (b, c, d, a, x[12], S34); /* 36 */
+  HH (a, b, c, d, x[ 2], S31); /* 37 */
+  HH (d, a, b, c, x[10], S32); /* 38 */
+  HH (c, d, a, b, x[ 6], S33); /* 39 */
+  HH (b, c, d, a, x[14], S34); /* 40 */
+  HH (a, b, c, d, x[ 1], S31); /* 41 */
+  HH (d, a, b, c, x[ 9], S32); /* 42 */
+  HH (c, d, a, b, x[ 5], S33); /* 43 */
+  HH (b, c, d, a, x[13], S34); /* 44 */
+  HH (a, b, c, d, x[ 3], S31); /* 45 */
+  HH (d, a, b, c, x[11], S32); /* 46 */
+  HH (c, d, a, b, x[ 7], S33); /* 47 */
+  HH (b, c, d, a, x[15], S34); /* 48 */
+
+  state[0] += a;
+  state[1] += b;
+  state[2] += c;
+  state[3] += d;
+
+  /* Zeroize sensitive information.
+   */
+  byte_zero((POINTER) x, sizeof (x));
+}
+
diff -ruN qmail-1.03-orig/digest_md4.h qmail-1.03-ldap-20060201-orig/digest_md4.h
--- qmail-1.03-orig/digest_md4.h	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/digest_md4.h	2006-02-25 11:00:55.000000000 +0100
@@ -0,0 +1,45 @@
+/* digest_md4.h for QLDAP modified to use djb's stuff */
+
+/*        */
+/*  MD4   */
+/*        */
+
+/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
+   rights reserved.
+
+   License to copy and use this software is granted provided that it
+   is identified as the "RSA Data Security, Inc. MD4 Message-Digest
+   Algorithm" in all material mentioning or referencing this software
+   or this function.
+   License is also granted to make and use derivative works provided
+   that such works are identified as "derived from the RSA Data
+   Security, Inc. MD4 Message-Digest Algorithm" in all material
+   mentioning or referencing the derived work.
+
+   RSA Data Security, Inc. makes no representations concerning either
+   the merchantability of this software or the suitability of this
+   software for any particular purpose. It is provided "as is"
+   without express or implied warranty of any kind.
+
+   These notices must be retained in any copies of any part of this
+   documentation and/or software.                                   */
+
+#ifndef _MD4_H_
+#define _MD4_H_
+
+#include "uint32.h"
+
+/* MD4 context. */
+typedef struct MD4Context {
+    uint32 state[4];            /* state (ABCD) */
+    uint32 count[2];            /* number of bits, modulo 2^64 */
+    unsigned char buffer[64];   /* input buffer */
+} MD4_CTX;
+
+#define MD4_LEN 16
+
+void   MD4Init(MD4_CTX *);
+void   MD4Update(MD4_CTX *, const unsigned char *, size_t);
+void   MD4Final(unsigned char [MD4_LEN], MD4_CTX *);
+
+#endif /* _MD4_H_ */
diff -ruN qmail-1.03-orig/digest_md5.c qmail-1.03-ldap-20060201-orig/digest_md5.c
--- qmail-1.03-orig/digest_md5.c	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/digest_md5.c	2006-02-25 11:00:55.000000000 +0100
@@ -0,0 +1,319 @@
+/* digest_md5.c for QLDAP modified to use djb's stuff  */
+/* contains MD5 algorithm stolen directly from OpenBSD */
+
+/*        */
+/*  MD5   */
+/*        */
+
+/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
+rights reserved.
+
+License to copy and use this software is granted provided that it
+is identified as the "RSA Data Security, Inc. MD5 Message-Digest
+Algorithm" in all material mentioning or referencing this software
+or this function.
+
+License is also granted to make and use derivative works provided
+that such works are identified as "derived from the RSA Data
+Security, Inc. MD5 Message-Digest Algorithm" in all material
+mentioning or referencing the derived work.
+
+RSA Data Security, Inc. makes no representations concerning either
+the merchantability of this software or the suitability of this
+software for any particular purpose. It is provided "as is"
+without express or implied warranty of any kind.
+
+These notices must be retained in any copies of any part of this
+documentation and/or software.
+ */
+
+#include <sys/types.h>
+#include "uint32.h"
+#include "byte.h"
+#include "digest_md5.h"
+
+/* POINTER defines a generic pointer type */
+typedef unsigned char *POINTER;
+
+/* Constants for MD5Transform routine.
+ */
+#define S11 7
+#define S12 12
+#define S13 17
+#define S14 22
+#define S21 5
+#define S22 9
+#define S23 14
+#define S24 20
+#define S31 4
+#define S32 11
+#define S33 16
+#define S34 23
+#define S41 6
+#define S42 10
+#define S43 15
+#define S44 21
+
+static void MD5Transform (uint32 [4], const unsigned char [64]);
+
+#ifdef __LITTLE_ENDIAN__
+#define Encode byte_copy
+#define Decode byte_copy
+#else  /* __BIG_ENDIAN__ */
+static void Encode(void *, size_t, const void *);
+static void Decode(void *, size_t, const void *);
+#endif /* __LITTLE_ENDIAN__ */
+
+static unsigned char PADDING[64] = {
+  0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+/* F, G, H and I are basic MD5 functions.
+ */
+#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
+#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
+#define H(x, y, z) ((x) ^ (y) ^ (z))
+#define I(x, y, z) ((y) ^ ((x) | (~z)))
+
+/* ROTATE_LEFT rotates x left n bits.
+ */
+#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
+
+/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
+Rotation is separate from addition to prevent recomputation.
+ */
+#define FF(a, b, c, d, x, s, ac) { \
+ (a) += F ((b), (c), (d)) + (x) + (uint32)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+  }
+#define GG(a, b, c, d, x, s, ac) { \
+ (a) += G ((b), (c), (d)) + (x) + (uint32)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+  }
+#define HH(a, b, c, d, x, s, ac) { \
+ (a) += H ((b), (c), (d)) + (x) + (uint32)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+  }
+#define II(a, b, c, d, x, s, ac) { \
+ (a) += I ((b), (c), (d)) + (x) + (uint32)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+  }
+
+#ifdef __BIG_ENDIAN__
+/* Encodes input (uint32) into output (unsigned char). Assumes len is
+  a multiple of 4.
+ */
+static void
+Encode(void *out, size_t len, const void *in)
+{
+  unsigned char *output = out;
+  size_t i, j;
+  const uint32 *input = in;
+
+  for (i = 0, j = 0; j < len; i++, j += 4) {
+    output[j] = (unsigned char)(input[i] & 0xff);
+    output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
+    output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
+    output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
+  }
+}
+
+/* Decodes input (unsigned char) into output (uint32). Assumes len is
+  a multiple of 4.
+ */
+static void
+Decode(void *out, size_t len, const void *in)
+{
+  uint32 *output = out;
+  const unsigned char *input = in;
+  size_t i, j;
+
+  for (i = 0, j = 0; j < len; i++, j += 4)
+    output[i] = ((uint32)input[j]) | (((uint32)input[j+1]) << 8) |
+    (((uint32)input[j+2]) << 16) | (((uint32)input[j+3]) << 24);
+}
+#endif /* __BIG_ENDIAN__ */
+
+/* MD5 initialization. Begins an MD5 operation, writing a new context.
+ */
+void
+MD5Init(MD5_CTX *context)
+{
+  context->count[0] = 0;
+  context->count[1] = 0;
+
+  /* Load magic initialization constants. */
+  context->state[0] = 0x67452301;
+  context->state[1] = 0xefcdab89;
+  context->state[2] = 0x98badcfe;
+  context->state[3] = 0x10325476;
+}
+
+/* MD5 block update operation. Continues an MD5 message-digest
+  operation, processing another message block, and updating the
+  context.
+ */
+void
+MD5Update(MD5_CTX *context, const unsigned char *input, size_t inputLen)
+{
+  unsigned int i, idx, partLen;
+
+  /* Compute number of bytes mod 64 */
+  idx = (unsigned int)((context->count[0] >> 3) & 0x3F);
+
+  /* Update number of bits */
+  if ( (context->count[0] += ((uint32)inputLen << 3)) /* lower part of count */
+       < ((uint32)inputLen << 3) )
+    context->count[1]++; /* low part of count overflowed */
+
+  context->count[1] += ((uint32)inputLen >> 29); /* update high part of count */
+
+  partLen = 64 - idx;
+
+  /* Transform as many times as possible. */
+  if (inputLen >= partLen) {
+    byte_copy ((POINTER)&context->buffer[idx], partLen, input);
+    MD5Transform (context->state, context->buffer);
+
+    for (i = partLen; i + 63 < inputLen; i += 64)
+      MD5Transform (context->state, &input[i]);
+
+    idx = 0;
+  }
+  else
+    i = 0;
+
+  /* Buffer remaining input */
+  byte_copy ((POINTER)&context->buffer[idx], inputLen-i, &input[i]);
+}
+
+/* MD5 finalization. Ends an MD5 message-digest operation, writing the
+  the message digest and zeroizing the context.
+ */
+void
+MD5Final(unsigned char digest[MD5_LEN], MD5_CTX *context)
+{
+  unsigned char bits[8];
+  unsigned int idx;
+  size_t padLen;
+  uint32 hi, lo;
+
+  /* Save number of bits */
+  hi = context->count[1];
+  lo = context->count[0];
+  Encode (bits, 4, &lo);
+  Encode (bits + 4, 4, &hi);
+
+  /* Pad out to 56 mod 64. */
+  idx = (unsigned int)((context->count[0] >> 3) & 0x3f);
+  padLen = (idx < 56) ? (56 - idx) : (120 - idx);
+  MD5Update (context, PADDING, padLen);
+
+  /* Append length (before padding) */
+  MD5Update (context, bits, 8);
+
+  if (digest != (unsigned char *)0) {
+    /* Store state in digest */
+    Encode (digest, 16, context->state);
+
+    /* Zeroize sensitive information.  */
+    byte_zero ((POINTER)context, sizeof (*context));
+  }
+}
+
+/* MD5 basic transformation. Transforms state based on block.
+ */
+static void
+MD5Transform(uint32 state[4], const unsigned char block[64])
+{
+  uint32 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
+
+  Decode (x, 64, block);
+
+  /* Round 1 */
+  FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
+  FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
+  FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
+  FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
+  FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
+  FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
+  FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
+  FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
+  FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
+  FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
+  FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
+  FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
+  FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
+  FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
+  FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
+  FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
+
+ /* Round 2 */
+  GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
+  GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
+  GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
+  GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
+  GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
+  GG (d, a, b, c, x[10], S22,  0x2441453); /* 22 */
+  GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
+  GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
+  GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
+  GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
+  GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
+  GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
+  GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
+  GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
+  GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
+  GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
+
+  /* Round 3 */
+  HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
+  HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
+  HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
+  HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
+  HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
+  HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
+  HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
+  HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
+  HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
+  HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
+  HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
+  HH (b, c, d, a, x[ 6], S34,  0x4881d05); /* 44 */
+  HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
+  HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
+  HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
+  HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
+
+  /* Round 4 */
+  II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
+  II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
+  II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
+  II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
+  II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
+  II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
+  II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
+  II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
+  II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
+  II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
+  II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
+  II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
+  II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
+  II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
+  II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
+  II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
+
+  state[0] += a;
+  state[1] += b;
+  state[2] += c;
+  state[3] += d;
+
+  /* Zeroize sensitive information. */
+  byte_zero ((POINTER)x, sizeof (x));
+}
+
diff -ruN qmail-1.03-orig/digest_md5.h qmail-1.03-ldap-20060201-orig/digest_md5.h
--- qmail-1.03-orig/digest_md5.h	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/digest_md5.h	2006-02-25 11:00:55.000000000 +0100
@@ -0,0 +1,47 @@
+/* digest_md5.h for QLDAP modified to use djb's stuff */
+
+/*        */
+/*  MD5   */
+/*        */
+
+/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
+rights reserved.
+
+License to copy and use this software is granted provided that it
+is identified as the "RSA Data Security, Inc. MD5 Message-Digest
+Algorithm" in all material mentioning or referencing this software
+or this function.
+
+License is also granted to make and use derivative works provided
+that such works are identified as "derived from the RSA Data
+Security, Inc. MD5 Message-Digest Algorithm" in all material
+mentioning or referencing the derived work.
+
+RSA Data Security, Inc. makes no representations concerning either
+the merchantability of this software or the suitability of this
+software for any particular purpose. It is provided "as is"
+without express or implied warranty of any kind.
+
+These notices must be retained in any copies of any part of this
+documentation and/or software.
+ */
+
+#ifndef _MD5_H_
+#define _MD5_H_
+
+#include "uint32.h"
+
+/* MD5 context. */
+typedef struct MD5Context {
+    uint32 state[4];            /* state (ABCD) */
+    uint32 count[2];            /* number of bits, modulo 2^64 */
+    unsigned char buffer[64];   /* input buffer */
+} MD5_CTX;
+
+#define MD5_LEN 16
+
+void   MD5Init(MD5_CTX *);
+void   MD5Update(MD5_CTX *, const unsigned char *, size_t);
+void   MD5Final(unsigned char [MD5_LEN], MD5_CTX *);
+
+#endif /* _MD5_H_ */
diff -ruN qmail-1.03-orig/digest_rmd160.c qmail-1.03-ldap-20060201-orig/digest_rmd160.c
--- qmail-1.03-orig/digest_rmd160.c	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/digest_rmd160.c	2006-02-25 11:00:55.000000000 +0100
@@ -0,0 +1,412 @@
+/* digest_rmd160.c for QLDAP checkpassword.c              */
+/* contains RMD160 algorithm stolen directly from OpenBSD */
+
+/*        */
+/* RMD160 */
+/*        */
+
+/********************************************************************\
+ *
+ *      FILE:     rmd160.c
+ *
+ *      CONTENTS: A sample C-implementation of the RIPEMD-160
+ *                hash-function.
+ *      TARGET:   any computer with an ANSI C compiler
+ *
+ *      AUTHOR:   Antoon Bosselaers, ESAT-COSIC
+ *                (Arranged for libc by Todd C. Miller)
+ *      DATE:     1 March 1996
+ *      VERSION:  1.0
+ *
+ *      Copyright (c) Katholieke Universiteit Leuven
+ *      1996, All Rights Reserved
+ *
+\********************************************************************/
+
+/*  header files */
+#include <sys/types.h>
+#include "uint32.h"
+#include "byte.h"
+#include "digest_rmd160.h"
+
+/* macro definitions */
+
+/* collect four bytes into one word: */
+#define BYTES_TO_DWORD(strptr)                  \
+    (((uint32) *((strptr)+3) << 24) |        \
+    ((uint32) *((strptr)+2) << 16) |         \
+    ((uint32) *((strptr)+1) <<  8) |         \
+    ((uint32) *(strptr)))
+
+/* ROL(x, n) cyclically rotates x over n bits to the left */
+/* x must be of an unsigned 32 bits type and 0 <= n < 32. */
+#define ROL(x, n)       (((x) << (n)) | ((x) >> (32-(n))))
+
+/* the three basic functions F(), G() and H() */
+#define F(x, y, z)      ((x) ^ (y) ^ (z))
+#define G(x, y, z)      (((x) & (y)) | (~(x) & (z)))
+#define H(x, y, z)      (((x) | ~(y)) ^ (z))
+#define I(x, y, z)      (((x) & (z)) | ((y) & ~(z)))
+#define J(x, y, z)      ((x) ^ ((y) | ~(z)))
+
+/* the eight basic operations FF() through III() */
+#define FF(a, b, c, d, e, x, s) {                       \
+      (a) += F((b), (c), (d)) + (x);                    \
+      (a) = ROL((a), (s)) + (e);                        \
+      (c) = ROL((c), 10);                               \
+}
+#define GG(a, b, c, d, e, x, s) {                       \
+      (a) += G((b), (c), (d)) + (x) + 0x5a827999U;      \
+      (a) = ROL((a), (s)) + (e);                        \
+      (c) = ROL((c), 10);                               \
+}
+#define HH(a, b, c, d, e, x, s) {                       \
+      (a) += H((b), (c), (d)) + (x) + 0x6ed9eba1U;      \
+      (a) = ROL((a), (s)) + (e);                        \
+      (c) = ROL((c), 10);                               \
+}
+#define II(a, b, c, d, e, x, s) {                       \
+      (a) += I((b), (c), (d)) + (x) + 0x8f1bbcdcU;      \
+      (a) = ROL((a), (s)) + (e);                        \
+      (c) = ROL((c), 10);                               \
+}
+#define JJ(a, b, c, d, e, x, s) {                       \
+      (a) += J((b), (c), (d)) + (x) + 0xa953fd4eU;      \
+      (a) = ROL((a), (s)) + (e);                        \
+      (c) = ROL((c), 10);                               \
+}
+#define FFF(a, b, c, d, e, x, s)        {               \
+      (a) += F((b), (c), (d)) + (x);                    \
+      (a) = ROL((a), (s)) + (e);                        \
+      (c) = ROL((c), 10);                               \
+}
+#define GGG(a, b, c, d, e, x, s)        {               \
+      (a) += G((b), (c), (d)) + (x) + 0x7a6d76e9U;      \
+      (a) = ROL((a), (s)) + (e);                        \
+      (c) = ROL((c), 10);                               \
+}
+#define HHH(a, b, c, d, e, x, s)        {               \
+      (a) += H((b), (c), (d)) + (x) + 0x6d703ef3U;      \
+      (a) = ROL((a), (s)) + (e);                        \
+      (c) = ROL((c), 10);                               \
+}
+#define III(a, b, c, d, e, x, s)        {               \
+      (a) += I((b), (c), (d)) + (x) + 0x5c4dd124U;      \
+      (a) = ROL((a), (s)) + (e);                        \
+      (c) = ROL((c), 10);                               \
+}
+#define JJJ(a, b, c, d, e, x, s)        {               \
+      (a) += J((b), (c), (d)) + (x) + 0x50a28be6U;      \
+      (a) = ROL((a), (s)) + (e);                        \
+      (c) = ROL((c), 10);                               \
+}
+
+void
+RMD160Init(RMD160_CTX *context)
+{
+
+        /* ripemd-160 initialization constants */
+        context->state[0] = 0x67452301U;
+        context->state[1] = 0xefcdab89U;
+        context->state[2] = 0x98badcfeU;
+        context->state[3] = 0x10325476U;
+        context->state[4] = 0xc3d2e1f0U;
+        context->length[0] = context->length[1] = 0;
+        context->buflen = 0;
+}
+
+static void
+RMD160Transform(uint32 state[5], const uint32 block[16])
+{
+        uint32 aa = state[0],  bb = state[1],  cc = state[2],
+            dd = state[3],  ee = state[4];
+        uint32 aaa = state[0], bbb = state[1], ccc = state[2],
+            ddd = state[3], eee = state[4];
+
+        /* round 1 */
+        FF(aa, bb, cc, dd, ee, block[ 0], 11);
+        FF(ee, aa, bb, cc, dd, block[ 1], 14);
+        FF(dd, ee, aa, bb, cc, block[ 2], 15);
+        FF(cc, dd, ee, aa, bb, block[ 3], 12);
+        FF(bb, cc, dd, ee, aa, block[ 4],  5);
+        FF(aa, bb, cc, dd, ee, block[ 5],  8);
+        FF(ee, aa, bb, cc, dd, block[ 6],  7);
+        FF(dd, ee, aa, bb, cc, block[ 7],  9);
+        FF(cc, dd, ee, aa, bb, block[ 8], 11);
+        FF(bb, cc, dd, ee, aa, block[ 9], 13);
+        FF(aa, bb, cc, dd, ee, block[10], 14);
+        FF(ee, aa, bb, cc, dd, block[11], 15);
+        FF(dd, ee, aa, bb, cc, block[12],  6);
+        FF(cc, dd, ee, aa, bb, block[13],  7);
+        FF(bb, cc, dd, ee, aa, block[14],  9);
+        FF(aa, bb, cc, dd, ee, block[15],  8);
+
+        /* round 2 */
+        GG(ee, aa, bb, cc, dd, block[ 7],  7);
+        GG(dd, ee, aa, bb, cc, block[ 4],  6);
+        GG(cc, dd, ee, aa, bb, block[13],  8);
+        GG(bb, cc, dd, ee, aa, block[ 1], 13);
+        GG(aa, bb, cc, dd, ee, block[10], 11);
+        GG(ee, aa, bb, cc, dd, block[ 6],  9);
+        GG(dd, ee, aa, bb, cc, block[15],  7);
+        GG(cc, dd, ee, aa, bb, block[ 3], 15);
+        GG(bb, cc, dd, ee, aa, block[12],  7);
+        GG(aa, bb, cc, dd, ee, block[ 0], 12);
+        GG(ee, aa, bb, cc, dd, block[ 9], 15);
+        GG(dd, ee, aa, bb, cc, block[ 5],  9);
+        GG(cc, dd, ee, aa, bb, block[ 2], 11);
+        GG(bb, cc, dd, ee, aa, block[14],  7);
+        GG(aa, bb, cc, dd, ee, block[11], 13);
+        GG(ee, aa, bb, cc, dd, block[ 8], 12);
+
+        /* round 3 */
+        HH(dd, ee, aa, bb, cc, block[ 3], 11);
+        HH(cc, dd, ee, aa, bb, block[10], 13);
+        HH(bb, cc, dd, ee, aa, block[14],  6);
+        HH(aa, bb, cc, dd, ee, block[ 4],  7);
+        HH(ee, aa, bb, cc, dd, block[ 9], 14);
+        HH(dd, ee, aa, bb, cc, block[15],  9);
+        HH(cc, dd, ee, aa, bb, block[ 8], 13);
+        HH(bb, cc, dd, ee, aa, block[ 1], 15);
+        HH(aa, bb, cc, dd, ee, block[ 2], 14);
+        HH(ee, aa, bb, cc, dd, block[ 7],  8);
+        HH(dd, ee, aa, bb, cc, block[ 0], 13);
+        HH(cc, dd, ee, aa, bb, block[ 6],  6);
+        HH(bb, cc, dd, ee, aa, block[13],  5);
+        HH(aa, bb, cc, dd, ee, block[11], 12);
+        HH(ee, aa, bb, cc, dd, block[ 5],  7);
+        HH(dd, ee, aa, bb, cc, block[12],  5);
+
+        /* round 4 */
+        II(cc, dd, ee, aa, bb, block[ 1], 11);
+        II(bb, cc, dd, ee, aa, block[ 9], 12);
+        II(aa, bb, cc, dd, ee, block[11], 14);
+        II(ee, aa, bb, cc, dd, block[10], 15);
+        II(dd, ee, aa, bb, cc, block[ 0], 14);
+        II(cc, dd, ee, aa, bb, block[ 8], 15);
+        II(bb, cc, dd, ee, aa, block[12],  9);
+        II(aa, bb, cc, dd, ee, block[ 4],  8);
+        II(ee, aa, bb, cc, dd, block[13],  9);
+        II(dd, ee, aa, bb, cc, block[ 3], 14);
+        II(cc, dd, ee, aa, bb, block[ 7],  5);
+        II(bb, cc, dd, ee, aa, block[15],  6);
+        II(aa, bb, cc, dd, ee, block[14],  8);
+        II(ee, aa, bb, cc, dd, block[ 5],  6);
+        II(dd, ee, aa, bb, cc, block[ 6],  5);
+        II(cc, dd, ee, aa, bb, block[ 2], 12);
+
+        /* round 5 */
+        JJ(bb, cc, dd, ee, aa, block[ 4],  9);
+        JJ(aa, bb, cc, dd, ee, block[ 0], 15);
+        JJ(ee, aa, bb, cc, dd, block[ 5],  5);
+        JJ(dd, ee, aa, bb, cc, block[ 9], 11);
+        JJ(cc, dd, ee, aa, bb, block[ 7],  6);
+        JJ(bb, cc, dd, ee, aa, block[12],  8);
+        JJ(aa, bb, cc, dd, ee, block[ 2], 13);
+        JJ(ee, aa, bb, cc, dd, block[10], 12);
+        JJ(dd, ee, aa, bb, cc, block[14],  5);
+        JJ(cc, dd, ee, aa, bb, block[ 1], 12);
+        JJ(bb, cc, dd, ee, aa, block[ 3], 13);
+        JJ(aa, bb, cc, dd, ee, block[ 8], 14);
+        JJ(ee, aa, bb, cc, dd, block[11], 11);
+        JJ(dd, ee, aa, bb, cc, block[ 6],  8);
+        JJ(cc, dd, ee, aa, bb, block[15],  5);
+        JJ(bb, cc, dd, ee, aa, block[13],  6);
+
+        /* parallel round 1 */
+        JJJ(aaa, bbb, ccc, ddd, eee, block[ 5],  8);
+        JJJ(eee, aaa, bbb, ccc, ddd, block[14],  9);
+        JJJ(ddd, eee, aaa, bbb, ccc, block[ 7],  9);
+        JJJ(ccc, ddd, eee, aaa, bbb, block[ 0], 11);
+        JJJ(bbb, ccc, ddd, eee, aaa, block[ 9], 13);
+        JJJ(aaa, bbb, ccc, ddd, eee, block[ 2], 15);
+        JJJ(eee, aaa, bbb, ccc, ddd, block[11], 15);
+        JJJ(ddd, eee, aaa, bbb, ccc, block[ 4],  5);
+        JJJ(ccc, ddd, eee, aaa, bbb, block[13],  7);
+        JJJ(bbb, ccc, ddd, eee, aaa, block[ 6],  7);
+        JJJ(aaa, bbb, ccc, ddd, eee, block[15],  8);
+        JJJ(eee, aaa, bbb, ccc, ddd, block[ 8], 11);
+        JJJ(ddd, eee, aaa, bbb, ccc, block[ 1], 14);
+        JJJ(ccc, ddd, eee, aaa, bbb, block[10], 14);
+        JJJ(bbb, ccc, ddd, eee, aaa, block[ 3], 12);
+        JJJ(aaa, bbb, ccc, ddd, eee, block[12],  6);
+
+        /* parallel round 2 */
+        III(eee, aaa, bbb, ccc, ddd, block[ 6],  9);
+        III(ddd, eee, aaa, bbb, ccc, block[11], 13);
+        III(ccc, ddd, eee, aaa, bbb, block[ 3], 15);
+        III(bbb, ccc, ddd, eee, aaa, block[ 7],  7);
+        III(aaa, bbb, ccc, ddd, eee, block[ 0], 12);
+        III(eee, aaa, bbb, ccc, ddd, block[13],  8);
+        III(ddd, eee, aaa, bbb, ccc, block[ 5],  9);
+        III(ccc, ddd, eee, aaa, bbb, block[10], 11);
+        III(bbb, ccc, ddd, eee, aaa, block[14],  7);
+        III(aaa, bbb, ccc, ddd, eee, block[15],  7);
+        III(eee, aaa, bbb, ccc, ddd, block[ 8], 12);
+        III(ddd, eee, aaa, bbb, ccc, block[12],  7);
+        III(ccc, ddd, eee, aaa, bbb, block[ 4],  6);
+        III(bbb, ccc, ddd, eee, aaa, block[ 9], 15);
+        III(aaa, bbb, ccc, ddd, eee, block[ 1], 13);
+        III(eee, aaa, bbb, ccc, ddd, block[ 2], 11);
+
+        /* parallel round 3 */
+        HHH(ddd, eee, aaa, bbb, ccc, block[15],  9);
+        HHH(ccc, ddd, eee, aaa, bbb, block[ 5],  7);
+        HHH(bbb, ccc, ddd, eee, aaa, block[ 1], 15);
+        HHH(aaa, bbb, ccc, ddd, eee, block[ 3], 11);
+        HHH(eee, aaa, bbb, ccc, ddd, block[ 7],  8);
+        HHH(ddd, eee, aaa, bbb, ccc, block[14],  6);
+        HHH(ccc, ddd, eee, aaa, bbb, block[ 6],  6);
+        HHH(bbb, ccc, ddd, eee, aaa, block[ 9], 14);
+        HHH(aaa, bbb, ccc, ddd, eee, block[11], 12);
+        HHH(eee, aaa, bbb, ccc, ddd, block[ 8], 13);
+        HHH(ddd, eee, aaa, bbb, ccc, block[12],  5);
+        HHH(ccc, ddd, eee, aaa, bbb, block[ 2], 14);
+        HHH(bbb, ccc, ddd, eee, aaa, block[10], 13);
+        HHH(aaa, bbb, ccc, ddd, eee, block[ 0], 13);
+        HHH(eee, aaa, bbb, ccc, ddd, block[ 4],  7);
+        HHH(ddd, eee, aaa, bbb, ccc, block[13],  5);
+
+        /* parallel round 4 */
+        GGG(ccc, ddd, eee, aaa, bbb, block[ 8], 15);
+        GGG(bbb, ccc, ddd, eee, aaa, block[ 6],  5);
+        GGG(aaa, bbb, ccc, ddd, eee, block[ 4],  8);
+        GGG(eee, aaa, bbb, ccc, ddd, block[ 1], 11);
+        GGG(ddd, eee, aaa, bbb, ccc, block[ 3], 14);
+        GGG(ccc, ddd, eee, aaa, bbb, block[11], 14);
+        GGG(bbb, ccc, ddd, eee, aaa, block[15],  6);
+        GGG(aaa, bbb, ccc, ddd, eee, block[ 0], 14);
+        GGG(eee, aaa, bbb, ccc, ddd, block[ 5],  6);
+        GGG(ddd, eee, aaa, bbb, ccc, block[12],  9);
+        GGG(ccc, ddd, eee, aaa, bbb, block[ 2], 12);
+        GGG(bbb, ccc, ddd, eee, aaa, block[13],  9);
+        GGG(aaa, bbb, ccc, ddd, eee, block[ 9], 12);
+        GGG(eee, aaa, bbb, ccc, ddd, block[ 7],  5);
+        GGG(ddd, eee, aaa, bbb, ccc, block[10], 15);
+        GGG(ccc, ddd, eee, aaa, bbb, block[14],  8);
+
+        /* parallel round 5 */
+        FFF(bbb, ccc, ddd, eee, aaa, block[12] ,  8);
+        FFF(aaa, bbb, ccc, ddd, eee, block[15] ,  5);
+        FFF(eee, aaa, bbb, ccc, ddd, block[10] , 12);
+        FFF(ddd, eee, aaa, bbb, ccc, block[ 4] ,  9);
+        FFF(ccc, ddd, eee, aaa, bbb, block[ 1] , 12);
+        FFF(bbb, ccc, ddd, eee, aaa, block[ 5] ,  5);
+        FFF(aaa, bbb, ccc, ddd, eee, block[ 8] , 14);
+        FFF(eee, aaa, bbb, ccc, ddd, block[ 7] ,  6);
+        FFF(ddd, eee, aaa, bbb, ccc, block[ 6] ,  8);
+        FFF(ccc, ddd, eee, aaa, bbb, block[ 2] , 13);
+        FFF(bbb, ccc, ddd, eee, aaa, block[13] ,  6);
+        FFF(aaa, bbb, ccc, ddd, eee, block[14] ,  5);
+        FFF(eee, aaa, bbb, ccc, ddd, block[ 0] , 15);
+        FFF(ddd, eee, aaa, bbb, ccc, block[ 3] , 13);
+        FFF(ccc, ddd, eee, aaa, bbb, block[ 9] , 11);
+        FFF(bbb, ccc, ddd, eee, aaa, block[11] , 11);
+
+        /* combine results */
+        ddd += cc + state[1];           /* final result for state[0] */
+        state[1] = state[2] + dd + eee;
+        state[2] = state[3] + ee + aaa;
+        state[3] = state[4] + aa + bbb;
+        state[4] = state[0] + bb + ccc;
+        state[0] = ddd;
+}
+
+void
+RMD160Update(RMD160_CTX *context, const unsigned char *data, size_t nbytes)
+{
+        uint32 X[16];
+        uint32 ofs = 0;
+        uint32 i;
+#ifdef __BIG_ENDIAN__
+        uint32 j;
+#endif /* __BIG_ENDIAN__ */
+
+        /* update length[] */
+        if (context->length[0] + nbytes < context->length[0])
+                context->length[1]++;           /* overflow to msb of length */
+        context->length[0] += nbytes;
+
+        byte_zero(X, sizeof(X));
+
+        if ( context->buflen + nbytes < 64 )
+        {
+                byte_copy(context->bbuffer + context->buflen, nbytes, data);
+                context->buflen += nbytes;
+        }
+        else
+        {
+                /* process first block */
+                ofs = 64 - context->buflen;
+                byte_copy(context->bbuffer + context->buflen, ofs, data);
+#ifdef __LITTLE_ENDIAN__
+                byte_copy(X, sizeof(X), context->bbuffer);
+#else  /* __BIG_ENDIAN__ */
+                for (j=0; j < 16; j++)
+                        X[j] = BYTES_TO_DWORD(context->bbuffer + (4 * j));
+#endif /* __LITTLE_ENDIAN__ */
+                RMD160Transform(context->state, X);
+                nbytes -= ofs;
+
+                /* process remaining complete blocks */
+                for (i = 0; i < (nbytes >> 6); i++) {
+#ifdef __LITTLE_ENDIAN__
+                        byte_copy(X, sizeof(X), data + (64 * i) + ofs);
+#else  /* __BIG_ENDIAN__ */
+                        for (j=0; j < 16; j++)
+                                X[j] = BYTES_TO_DWORD(data + (64 * i) + (4 * j) + ofs);
+#endif /* __LITTLE_ENDIAN__ */
+                        RMD160Transform(context->state, X);
+                }
+
+                /*
+                 * Put last bytes from data into context's buffer
+                 */
+                context->buflen = nbytes & 63;
+                byte_copy(context->bbuffer, context->buflen, data + (64 * i) + ofs);
+        }
+}
+
+void
+RMD160Final(unsigned char digest[RMD160_LEN], RMD160_CTX *context)
+{
+        uint32 i;
+        uint32 X[16];
+#ifdef __BIG_ENDIAN__
+        uint32 j;
+#endif /* __BIG_ENDIAN__ */
+
+        /* append the bit m_n == 1 */
+        context->bbuffer[context->buflen] = '\200';
+
+        byte_zero(context->bbuffer + context->buflen + 1,
+                63 - context->buflen);
+#ifdef __LITTLE_ENDIAN__
+        byte_copy(X, sizeof(X), context->bbuffer);
+#else  /* __BIG_ENDIAN__ */
+        for (j=0; j < 16; j++)
+                X[j] = BYTES_TO_DWORD(context->bbuffer + (4 * j));
+#endif /* __LITTLE_ENDIAN__ */
+        if ((context->buflen) > 55) {
+                /* length goes to next block */
+                RMD160Transform(context->state, X);
+                byte_zero(X, sizeof(X));
+        }
+
+        /* append length in bits */
+        X[14] = context->length[0] << 3;
+        X[15] = (context->length[0] >> 29) |
+            (context->length[1] << 3);
+        RMD160Transform(context->state, X);
+
+        if (digest != (unsigned char*)0) {
+                for (i = 0; i < 20; i += 4) {
+                        /* extracts the 8 least significant bits. */
+                        digest[i]     =  context->state[i>>2];
+                        digest[i + 1] = (context->state[i>>2] >>  8);
+                        digest[i + 2] = (context->state[i>>2] >> 16);
+                        digest[i + 3] = (context->state[i>>2] >> 24);
+                }
+        }
+}
+
diff -ruN qmail-1.03-orig/digest_rmd160.h qmail-1.03-ldap-20060201-orig/digest_rmd160.h
--- qmail-1.03-orig/digest_rmd160.h	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/digest_rmd160.h	2006-02-25 11:00:55.000000000 +0100
@@ -0,0 +1,49 @@
+/* digest_rmd160.h for QLDAP modified to use djb's stuff */
+
+/*        */
+/* RMD160 */
+/*        */
+
+/********************************************************************\
+ *
+ *      FILE:     rmd160.h
+ *
+ *      CONTENTS: Header file for a sample C-implementation of the
+ *                RIPEMD-160 hash-function. 
+ *      TARGET:   any computer with an ANSI C compiler
+ *
+ *      AUTHOR:   Antoon Bosselaers, ESAT-COSIC
+ *      DATE:     1 March 1996
+ *      VERSION:  1.0
+ *
+ *      Copyright (c) Katholieke Universiteit Leuven
+ *      1996, All Rights Reserved
+ *
+\********************************************************************/
+
+#ifndef  _RMD160_H      /* make sure this file is read only once */
+#define  _RMD160_H
+
+/********************************************************************/
+#include "uint32.h"
+
+/* structure definitions */
+
+typedef struct {
+        uint32 state[5];     /* state (ABCDE) */
+        uint32 length[2];    /* number of bits */
+        unsigned char  bbuffer[64];    /* overflow buffer */
+        uint32 buflen;       /* number of chars in bbuffer */
+} RMD160_CTX;
+
+/********************************************************************/
+
+#define RMD160_LEN 20
+
+/* function prototypes */
+
+void RMD160Init(RMD160_CTX *);
+void RMD160Update(RMD160_CTX *, const unsigned char *, size_t);
+void RMD160Final(unsigned char [RMD160_LEN], RMD160_CTX *);
+
+#endif  /* _RMD160_H */
diff -ruN qmail-1.03-orig/digest_sha1.c qmail-1.03-ldap-20060201-orig/digest_sha1.c
--- qmail-1.03-orig/digest_sha1.c	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/digest_sha1.c	2006-02-25 11:00:55.000000000 +0100
@@ -0,0 +1,247 @@
+/* digest_sha1.c for QLDAP modified to use djb stuff    */
+/* contains SHA1 algorithm stolen directly from OpenBSD */
+/*	$OpenBSD: sha1.c,v 1.11 2003/01/08 19:53:59 millert Exp $	*/
+
+/*        */
+/*  SHA1  */
+/*        */
+
+/*
+ * SHA-1 in C
+ * By Steve Reid <steve@edmweb.com>
+ * 100% Public Domain
+ *
+ * Test Vectors (from FIPS PUB 180-1)
+ * "abc"
+ *   A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
+ * "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
+ *   84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
+ * A million repetitions of "a"
+ *   34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
+ */
+
+#define SHA1HANDSOFF            /* Copies data before messing with it. */
+
+#include <sys/types.h>
+#include "uint32.h"
+#include "byte.h"
+#include "digest_sha1.h"
+
+#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
+
+/*
+ * blk0() and blk() perform the initial expand.
+ * I got the idea of expanding during the round function from SSLeay
+ */
+#ifdef __LITTLE_ENDIAN__
+# define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \
+    |(rol(block->l[i],8)&0x00FF00FF))
+#else  /* __BIG_ENDIAN__ */
+# define blk0(i) block->l[i]
+#endif /* __LITTLE_ENDIAN__ */
+
+#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \
+    ^block->l[(i+2)&15]^block->l[i&15],1))
+
+/*
+ * (R0+R1), R2, R3, R4 are the different operations (rounds) used in SHA1
+ */
+#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
+#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
+#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
+#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
+#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
+
+typedef union {
+    unsigned char c[64];
+    uint32 l[16];
+} CHAR64LONG16;
+
+#ifdef __sparc_v9__
+static void do_R01(uint32 *a, uint32 *b, uint32 *c, uint32 *d, uint32 *e, CHAR64LONG16 *);
+static void do_R2(uint32 *a, uint32 *b, uint32 *c, uint32 *d, uint32 *e, CHAR64LONG16 *);
+static void do_R3(uint32 *a, uint32 *b, uint32 *c, uint32 *d, uint32 *e, CHAR64LONG16 *);
+static void do_R4(uint32 *a, uint32 *b, uint32 *c, uint32 *d, uint32 *e, CHAR64LONG16 *);
+
+#define nR0(v,w,x,y,z,i) R0(*v,*w,*x,*y,*z,i)
+#define nR1(v,w,x,y,z,i) R1(*v,*w,*x,*y,*z,i)
+#define nR2(v,w,x,y,z,i) R2(*v,*w,*x,*y,*z,i)
+#define nR3(v,w,x,y,z,i) R3(*v,*w,*x,*y,*z,i)
+#define nR4(v,w,x,y,z,i) R4(*v,*w,*x,*y,*z,i)
+
+static void
+do_R01(uint32 *a, uint32 *b, uint32 *c, uint32 *d, uint32 *e, CHAR64LONG16 *block)
+{
+    nR0(a,b,c,d,e, 0); nR0(e,a,b,c,d, 1); nR0(d,e,a,b,c, 2); nR0(c,d,e,a,b, 3);
+    nR0(b,c,d,e,a, 4); nR0(a,b,c,d,e, 5); nR0(e,a,b,c,d, 6); nR0(d,e,a,b,c, 7);
+    nR0(c,d,e,a,b, 8); nR0(b,c,d,e,a, 9); nR0(a,b,c,d,e,10); nR0(e,a,b,c,d,11);
+    nR0(d,e,a,b,c,12); nR0(c,d,e,a,b,13); nR0(b,c,d,e,a,14); nR0(a,b,c,d,e,15);
+    nR1(e,a,b,c,d,16); nR1(d,e,a,b,c,17); nR1(c,d,e,a,b,18); nR1(b,c,d,e,a,19);
+}
+
+static void
+do_R2(uint32 *a, uint32 *b, uint32 *c, uint32 *d, uint32 *e, CHAR64LONG16 *block)
+{
+    nR2(a,b,c,d,e,20); nR2(e,a,b,c,d,21); nR2(d,e,a,b,c,22); nR2(c,d,e,a,b,23);
+    nR2(b,c,d,e,a,24); nR2(a,b,c,d,e,25); nR2(e,a,b,c,d,26); nR2(d,e,a,b,c,27);
+    nR2(c,d,e,a,b,28); nR2(b,c,d,e,a,29); nR2(a,b,c,d,e,30); nR2(e,a,b,c,d,31);
+    nR2(d,e,a,b,c,32); nR2(c,d,e,a,b,33); nR2(b,c,d,e,a,34); nR2(a,b,c,d,e,35);
+    nR2(e,a,b,c,d,36); nR2(d,e,a,b,c,37); nR2(c,d,e,a,b,38); nR2(b,c,d,e,a,39);
+}
+
+static void
+do_R3(uint32 *a, uint32 *b, uint32 *c, uint32 *d, uint32 *e, CHAR64LONG16 *block)
+{
+    nR3(a,b,c,d,e,40); nR3(e,a,b,c,d,41); nR3(d,e,a,b,c,42); nR3(c,d,e,a,b,43);
+    nR3(b,c,d,e,a,44); nR3(a,b,c,d,e,45); nR3(e,a,b,c,d,46); nR3(d,e,a,b,c,47);
+    nR3(c,d,e,a,b,48); nR3(b,c,d,e,a,49); nR3(a,b,c,d,e,50); nR3(e,a,b,c,d,51);
+    nR3(d,e,a,b,c,52); nR3(c,d,e,a,b,53); nR3(b,c,d,e,a,54); nR3(a,b,c,d,e,55);
+    nR3(e,a,b,c,d,56); nR3(d,e,a,b,c,57); nR3(c,d,e,a,b,58); nR3(b,c,d,e,a,59);
+}
+
+static void
+do_R4(uint32 *a, uint32 *b, uint32 *c, uint32 *d, uint32 *e, CHAR64LONG16 *block)
+{
+    nR4(a,b,c,d,e,60); nR4(e,a,b,c,d,61); nR4(d,e,a,b,c,62); nR4(c,d,e,a,b,63);
+    nR4(b,c,d,e,a,64); nR4(a,b,c,d,e,65); nR4(e,a,b,c,d,66); nR4(d,e,a,b,c,67);
+    nR4(c,d,e,a,b,68); nR4(b,c,d,e,a,69); nR4(a,b,c,d,e,70); nR4(e,a,b,c,d,71);
+    nR4(d,e,a,b,c,72); nR4(c,d,e,a,b,73); nR4(b,c,d,e,a,74); nR4(a,b,c,d,e,75);
+    nR4(e,a,b,c,d,76); nR4(d,e,a,b,c,77); nR4(c,d,e,a,b,78); nR4(b,c,d,e,a,79);
+}
+#endif
+
+/*
+ * Hash a single 512-bit block. This is the core of the algorithm.
+ */
+static void
+SHA1Transform(uint32 state[5], const unsigned char buffer[64])
+{
+    uint32 a, b, c, d, e;
+    CHAR64LONG16 *block;
+
+#ifdef SHA1HANDSOFF
+    static CHAR64LONG16 workspace;
+    block = &workspace;
+    byte_copy(block, 64, buffer);
+#else
+    block = (CHAR64LONG16 *)buffer;
+#endif
+
+    /* Copy context->state[] to working vars */
+    a = state[0];
+    b = state[1];
+    c = state[2];
+    d = state[3];
+    e = state[4];
+
+#ifdef __sparc_v9__
+    do_R01(&a, &b, &c, &d, &e, block);
+    do_R2(&a, &b, &c, &d, &e, block);
+    do_R3(&a, &b, &c, &d, &e, block);
+    do_R4(&a, &b, &c, &d, &e, block);
+#else
+    /* 4 rounds of 20 operations each. Loop unrolled. */
+    R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
+    R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
+    R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
+    R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
+    R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
+    R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
+    R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
+    R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
+    R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
+    R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
+    R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
+    R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
+    R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
+    R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
+    R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
+    R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
+    R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
+    R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
+    R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
+    R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
+#endif
+
+    /* Add the working vars back into context.state[] */
+    state[0] += a;
+    state[1] += b;
+    state[2] += c;
+    state[3] += d;
+    state[4] += e;
+
+    /* Wipe variables */
+    a = b = c = d = e = 0;
+}
+
+/*
+ * SHA1Init - Initialize new context
+ */
+void
+SHA1Init(SHA1_CTX *context)
+{
+
+    /* SHA1 initialization constants */
+    context->state[0] = 0x67452301;
+    context->state[1] = 0xEFCDAB89;
+    context->state[2] = 0x98BADCFE;
+    context->state[3] = 0x10325476;
+    context->state[4] = 0xC3D2E1F0;
+    context->count[0] = context->count[1] = 0;
+}
+
+
+/*
+ * Run your data through this.
+ */
+void
+SHA1Update(SHA1_CTX *context, const unsigned char *data, size_t len)
+{
+    unsigned int i, j;
+
+    j = context->count[0];
+    if ((context->count[0] += len << 3) < j)
+        context->count[1] += (len>>29)+1;
+    j = (j >> 3) & 63;
+    if ((j + len) > 63) {
+        byte_copy(&context->buffer[j], (i = 64-j), data);
+        SHA1Transform(context->state, context->buffer);
+        for ( ; i + 63 < len; i += 64)
+            SHA1Transform(context->state, &data[i]);
+        j = 0;
+    } else {
+        i = 0;
+    }
+    byte_copy(&context->buffer[j], len - i, &data[i]);
+}
+
+
+/*
+ * Add padding and return the message digest.
+ */
+void
+SHA1Final(unsigned char digest[SHA1_LEN], SHA1_CTX *context)
+{
+    unsigned int i;
+    unsigned char finalcount[8];
+
+    for (i = 0; i < 8; i++) {
+        finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)]
+         >> ((3-(i & 3)) * 8) ) & 255);  /* Endian independent */
+    }
+    SHA1Update(context, (const unsigned char *)"\200", 1);
+    while ((context->count[0] & 504) != 448)
+        SHA1Update(context, (const unsigned char *)"\0", 1);
+    SHA1Update(context, finalcount, 8);  /* Should cause a SHA1Transform() */
+
+    if (digest) {
+        for (i = 0; i < 20; i++)
+            digest[i] = (unsigned char)
+                ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
+        /* Zeroize sensitive information.
+         */
+        byte_zero(context, sizeof (*context));
+	}
+	
+}
+
diff -ruN qmail-1.03-orig/digest_sha1.h qmail-1.03-ldap-20060201-orig/digest_sha1.h
--- qmail-1.03-orig/digest_sha1.h	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/digest_sha1.h	2006-02-25 11:00:55.000000000 +0100
@@ -0,0 +1,30 @@
+/* digest_sha1.h for QLDAP modified to use djb stuff */
+
+/*        */
+/*  SHA1  */
+/*        */
+
+/*
+ * SHA-1 in C
+ * By Steve Reid <steve@edmweb.com>
+ * 100% Public Domain
+ */
+
+#ifndef _SHA1_H
+#define _SHA1_H
+
+#include "uint32.h"
+
+typedef struct {
+    uint32 state[5];
+    uint32 count[2];  
+    unsigned char buffer[64];
+} SHA1_CTX;
+ 
+#define SHA1_LEN 20
+
+void SHA1Init(SHA1_CTX *);
+void SHA1Update(SHA1_CTX *, const unsigned char *, size_t);
+void SHA1Final(unsigned char [SHA1_LEN], SHA1_CTX *);
+
+#endif /* _SHA1_H */
diff -ruN qmail-1.03-orig/dirmaker qmail-1.03-ldap-20060201-orig/dirmaker
--- qmail-1.03-orig/dirmaker	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/dirmaker	2006-02-25 11:00:55.000000000 +0100
@@ -0,0 +1,5 @@
+#!/bin/sh
+# public domain
+#
+/bin/mkdir -m 700 -p $1
+#EOF
diff -ruN qmail-1.03-orig/dirmaker.c qmail-1.03-ldap-20060201-orig/dirmaker.c
--- qmail-1.03-orig/dirmaker.c	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/dirmaker.c	2006-02-25 11:00:55.000000000 +0100
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2003-2004 Claudio Jeker,
+ *      Internet Business Solutions AG, CH-8005 Zürich, Switzerland
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Internet Business
+ *      Solutions AG and its contributors.
+ * 4. Neither the name of the author nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#ifdef AUTOHOMEDIRMAKE
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "error.h"
+#include "control.h"
+#include "open.h"
+#include "qldap-debug.h"
+#include "qldap-errno.h"
+#include "qlx.h"
+#include "stralloc.h"
+#include "wait.h"
+
+#include "dirmaker.h"
+
+
+static stralloc	dirmaker = {0};
+
+int
+dirmaker_init(void)
+/* ~control/dirmaker SHOULD to be only writeable for root */
+{
+	if (control_rldef(&dirmaker, "control/dirmaker", 0, "") == -1)
+		return -1;
+	if (!stralloc_0(&dirmaker))
+		return -1;
+	logit(64, "init: control/dirmaker: %s\n", dirmaker.s);
+	return 0;
+}
+
+int
+dirmaker_make(const char *home, const char *maildir)
+{
+	char *(dirargs[3]);
+	int child, wstat;
+
+	if (dirmaker.s == 0 || dirmaker.len < 2)
+		return MAILDIR_UNCONF;
+	
+	switch(child = fork()) {
+		case -1:
+			if (error_temp(errno)) return MAILDIR_FAILED;
+			return MAILDIR_HARD;
+		case 0:
+			dirargs[0] = dirmaker.s; dirargs[1] = (char *)home;
+			dirargs[2] = (char *)maildir; dirargs[3] = 0;
+			execvp(*dirargs,dirargs);
+			if (error_temp(errno)) _exit(QLX_EXECSOFT);
+			_exit(QLX_EXECHARD);
+	}
+
+	wait_pid(&wstat,child);
+	if (wait_crashed(wstat)) {
+		return MAILDIR_CRASHED;
+	}
+	switch(wait_exitcode(wstat)) {
+		case 0:
+			return OK;
+		case 100: case QLX_EXECHARD:
+			return MAILDIR_HARD;
+		default:
+			return MAILDIR_FAILED;
+	}
+}
+#endif
+
diff -ruN qmail-1.03-orig/dirmaker.h qmail-1.03-ldap-20060201-orig/dirmaker.h
--- qmail-1.03-orig/dirmaker.h	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/dirmaker.h	2006-02-25 11:00:55.000000000 +0100
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2003-2004 Claudio Jeker,
+ *      Internet Business Solutions AG, CH-8005 Zürich, Switzerland
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Internet Business
+ *      Solutions AG and its contributors.
+ * 4. Neither the name of the author nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#ifndef __DIRMAKER_H__
+#define __DIRMAKER_H__
+
+/* init handler */
+int dirmaker_init(void);
+
+/* executes the dirmaker returns OK on success */
+int dirmaker_make(const char *, const char *);
+
+#endif
diff -ruN qmail-1.03-orig/dns.c qmail-1.03-ldap-20060201-orig/dns.c
--- qmail-1.03-orig/dns.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/dns.c	2006-02-25 11:00:55.000000000 +0100
@@ -7,8 +7,8 @@
 #include <errno.h>
 extern int res_query();
 extern int res_search();
-extern int errno;
 extern int h_errno;
+#include "errno.h"
 #include "ip.h"
 #include "ipalloc.h"
 #include "fmt.h"
@@ -17,14 +17,20 @@
 #include "stralloc.h"
 #include "dns.h"
 #include "case.h"
+#ifdef IGNOREVERISIGN
+#include "byte.h"
+#define FUCKVERISIGN 
+#endif
 
 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 +51,35 @@
  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((char **)&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 +89,7 @@
    if (i < QFIXEDSZ) return DNS_SOFT;
    responsepos += QFIXEDSZ;
   }
- numanswers = ntohs(response.hdr.ancount);
+ numanswers = ntohs(((HEADER *)response.buf)->ancount);
  return 0;
 }
 
@@ -219,32 +242,32 @@
 
 #define FMT_IAA 40
 
-static int iaafmt(s,ip)
+static int iaafmt(s,tip)
 char *s;
-struct ip_address *ip;
+struct ip_address *tip;
 {
  unsigned int i;
  unsigned int len;
  len = 0;
- i = fmt_ulong(s,(unsigned long) ip->d[3]); len += i; if (s) s += i;
+ i = fmt_ulong(s,(unsigned long) tip->d[3]); len += i; if (s) s += i;
  i = fmt_str(s,"."); len += i; if (s) s += i;
- i = fmt_ulong(s,(unsigned long) ip->d[2]); len += i; if (s) s += i;
+ i = fmt_ulong(s,(unsigned long) tip->d[2]); len += i; if (s) s += i;
  i = fmt_str(s,"."); len += i; if (s) s += i;
- i = fmt_ulong(s,(unsigned long) ip->d[1]); len += i; if (s) s += i;
+ i = fmt_ulong(s,(unsigned long) tip->d[1]); len += i; if (s) s += i;
  i = fmt_str(s,"."); len += i; if (s) s += i;
- i = fmt_ulong(s,(unsigned long) ip->d[0]); len += i; if (s) s += i;
+ i = fmt_ulong(s,(unsigned long) tip->d[0]); len += i; if (s) s += i;
  i = fmt_str(s,".in-addr.arpa."); len += i; if (s) s += i;
  return len;
 }
 
-int dns_ptr(sa,ip)
+int dns_ptr(sa,tip)
 stralloc *sa;
-struct ip_address *ip;
+struct ip_address *tip;
 {
  int r;
 
- if (!stralloc_ready(sa,iaafmt((char *) 0,ip))) return DNS_MEM;
- sa->len = iaafmt(sa->s,ip);
+ if (!stralloc_ready(sa,iaafmt((char *) 0,tip))) return DNS_MEM;
+ sa->len = iaafmt(sa->s,tip);
  switch(resolve(sa,T_PTR))
   {
    case DNS_MEM: return DNS_MEM;
@@ -263,13 +286,22 @@
  return DNS_HARD;
 }
 
-static int dns_ipplus(ia,sa,pref)
+#ifdef FUCKVERISIGN
+static stralloc tld = {0};
+static ipalloc  tldia = {0};
+#endif
+
+static int dns_ipplus(ia,sa,spref)
 ipalloc *ia;
 stralloc *sa;
-int pref;
+int spref;
 {
  int r;
  struct ip_mx ix;
+#ifdef FUCKVERISIGN
+ unsigned int j;
+ struct ip_mx tldix;
+#endif
 
  if (!stralloc_copy(&glue,sa)) return DNS_MEM;
  if (!stralloc_0(&glue)) return DNS_MEM;
@@ -280,8 +312,35 @@
      if (!ipalloc_append(ia,&ix)) return DNS_MEM;
      return 0;
     }
+
  }
 
+#ifdef FUCKVERISIGN
+   j = byte_rchr(sa->s,sa->len,'.');
+   if (j+2 < sa->len) {
+     if(!stralloc_copys(&tld, "*")) return DNS_MEM;
+     if(!stralloc_catb(&tld, sa->s+j, sa->len-j)) return DNS_MEM;
+     switch(resolve(&tld,T_A))
+     {
+       case DNS_HARD: tldia.len = 0; break;
+       case DNS_MEM: return DNS_MEM;
+       case DNS_SOFT: return DNS_SOFT;
+       default:
+         if (!ipalloc_readyplus(&tldia,0)) return DNS_MEM;
+	 tldia.len = 0;
+	 tldix.pref = 0;
+         while ((r = findip(T_A)) != 2)
+         {
+           if (r == DNS_SOFT) return DNS_SOFT;
+           if (r == 1) {
+	     tldix.ip = ip;
+	     if (!ipalloc_append(&tldia,&tldix)) return DNS_MEM;
+	   }
+         }
+     }
+   }
+#endif
+
  switch(resolve(sa,T_A))
   {
    case DNS_MEM: return DNS_MEM;
@@ -291,10 +350,17 @@
  while ((r = findip(T_A)) != 2)
   {
    ix.ip = ip;
-   ix.pref = pref;
+   ix.pref = spref;
    if (r == DNS_SOFT) return DNS_SOFT;
-   if (r == 1)
+   if (r == 1) {
+#ifdef FUCKVERISIGN
+     for (j = 0; j < tldia.len; j++)
+       if (byte_diff(&tldia.ix[j].ip, sizeof(struct ip_address), &ip) == 0)
+	 break;
+     if (j < tldia.len) continue;
+#endif
      if (!ipalloc_append(ia,&ix)) return DNS_MEM;
+   }
   }
  return 0;
 }
diff -ruN qmail-1.03-orig/dnscname.c qmail-1.03-ldap-20060201-orig/dnscname.c
--- qmail-1.03-orig/dnscname.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/dnscname.c	2006-02-25 11:00:55.000000000 +0100
@@ -8,7 +8,7 @@
 
 stralloc sa = {0};
 
-void main(argc,argv)
+int main(argc,argv)
 int argc;
 char **argv;
 {
@@ -21,5 +21,5 @@
  dnsdoe(dns_cname(&sa));
  substdio_putflush(subfdout,sa.s,sa.len);
  substdio_putsflush(subfdout,"\n");
- _exit(0);
+ return 0;
 }
diff -ruN qmail-1.03-orig/dnsdoe.h qmail-1.03-ldap-20060201-orig/dnsdoe.h
--- qmail-1.03-orig/dnsdoe.h	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/dnsdoe.h	2006-02-25 11:00:55.000000000 +0100
@@ -1,6 +1,6 @@
 #ifndef DNSDOE_H
 #define DNSDOE_H
 
-extern void dnsdoe();
+extern void dnsdoe(int);
 
 #endif
diff -ruN qmail-1.03-orig/dnsfq.c qmail-1.03-ldap-20060201-orig/dnsfq.c
--- qmail-1.03-orig/dnsfq.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/dnsfq.c	2006-02-25 11:00:55.000000000 +0100
@@ -10,7 +10,7 @@
 stralloc sa = {0};
 ipalloc ia = {0};
 
-void main(argc,argv)
+int main(argc,argv)
 int argc;
 char **argv;
 {
@@ -28,5 +28,5 @@
  dnsdoe(dns_ptr(&sa,&ia.ix[0].ip));
  substdio_putflush(subfdout,sa.s,sa.len);
  substdio_putsflush(subfdout,"\n");
- _exit(0);
+ return 0;
 }
diff -ruN qmail-1.03-orig/dns.h qmail-1.03-ldap-20060201-orig/dns.h
--- qmail-1.03-orig/dns.h	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/dns.h	2006-02-25 11:00:55.000000000 +0100
@@ -1,14 +1,18 @@
 #ifndef DNS_H
 #define DNS_H
 
+#include "ip.h"
+#include "ipalloc.h"
+#include "stralloc.h"
+
 #define DNS_SOFT -1
 #define DNS_HARD -2
 #define DNS_MEM -3
 
-void dns_init();
-int dns_cname();
-int dns_mxip();
-int dns_ip();
-int dns_ptr();
+void dns_init(int);
+int dns_cname(stralloc *);
+int dns_mxip(ipalloc *, stralloc *, unsigned long);
+int dns_ip(ipalloc *, stralloc *);
+int dns_ptr(stralloc *, struct ip_address *);
 
 #endif
diff -ruN qmail-1.03-orig/dnsip.c qmail-1.03-ldap-20060201-orig/dnsip.c
--- qmail-1.03-orig/dnsip.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/dnsip.c	2006-02-25 11:00:55.000000000 +0100
@@ -12,11 +12,11 @@
 stralloc sa = {0};
 ipalloc ia = {0};
 
-void main(argc,argv)
+int main(argc,argv)
 int argc;
 char **argv;
 {
- int j;
+ unsigned int j;
 
  if (!argv[1]) _exit(100);
 
@@ -30,5 +30,5 @@
    substdio_put(subfdout,temp,ip_fmt(temp,&ia.ix[j].ip));
    substdio_putsflush(subfdout,"\n");
   }
- _exit(0);
+ return 0;
 }
diff -ruN qmail-1.03-orig/dnsmxip.c qmail-1.03-ldap-20060201-orig/dnsmxip.c
--- qmail-1.03-orig/dnsmxip.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/dnsmxip.c	2006-02-25 11:00:55.000000000 +0100
@@ -1,3 +1,5 @@
+#include <sys/types.h>
+#include <unistd.h>
 #include "substdio.h"
 #include "subfd.h"
 #include "stralloc.h"
@@ -14,11 +16,11 @@
 stralloc sa = {0};
 ipalloc ia = {0};
 
-void main(argc,argv)
+int main(argc,argv)
 int argc;
 char **argv;
 {
- int j;
+ unsigned int j;
  unsigned long r;
 
  if (!argv[1]) _exit(100);
@@ -33,8 +35,8 @@
   {
    substdio_put(subfdout,temp,ip_fmt(temp,&ia.ix[j].ip));
    substdio_puts(subfdout," ");
-   substdio_put(subfdout,temp,fmt_ulong(temp,(unsigned long) ia.ix[j].pref));
+   substdio_put(subfdout,temp,fmt_uint(temp,ia.ix[j].pref));
    substdio_putsflush(subfdout,"\n");
   }
- _exit(0);
+ return 0;
 }
diff -ruN qmail-1.03-orig/dnsptr.c qmail-1.03-ldap-20060201-orig/dnsptr.c
--- qmail-1.03-orig/dnsptr.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/dnsptr.c	2006-02-25 11:00:55.000000000 +0100
@@ -11,7 +11,7 @@
 stralloc sa = {0};
 struct ip_address ip;
 
-void main(argc,argv)
+int main(argc,argv)
 int argc;
 char **argv;
 {
@@ -23,5 +23,5 @@
  dnsdoe(dns_ptr(&sa,&ip));
  substdio_putflush(subfdout,sa.s,sa.len);
  substdio_putsflush(subfdout,"\n");
- _exit(0);
+ return 0;
 }
diff -ruN qmail-1.03-orig/endian.c qmail-1.03-ldap-20060201-orig/endian.c
--- qmail-1.03-orig/endian.c	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/endian.c	2006-02-25 11:00:55.000000000 +0100
@@ -0,0 +1,34 @@
+/* endian.c
+ * ----------------------------------------------------------------------------
+ * "THE BEER-WARE LICENSE" (Revision 42):
+ * <jeker@n-r-g.com> wrote this file.  As long as you retain this notice you
+ * can do whatever you want with this stuff. If we meet some day, and you think
+ * this stuff is worth it, you can buy me a beer in return.       Claudio Jeker
+ * ----------------------------------------------------------------------------
+ *
+ *  This is a lowest-common-denominator (endian) program which should compile
+ *  under the default cc on any system, no matter how primitite ...
+ *  (even the SunOS one ;-) )
+ */
+
+#include <stdio.h>
+
+
+union endian_t {
+   unsigned char   c[8];
+   long   l;
+} endian;
+
+int main()
+{
+
+	endian.c[0]=0x80; endian.c[1]=0; endian.c[2]=0; endian.c[3]=0;
+	endian.c[4]=0;    endian.c[5]=0; endian.c[6]=0; endian.c[7]=0;
+   
+	if( endian.l < 0 )
+		printf( "-D__BIG_ENDIAN__" );
+	else
+		printf( "-D__LITTLE_ENDIAN__" );
+
+	return(0);
+}
diff -ruN qmail-1.03-orig/env.c qmail-1.03-ldap-20060201-orig/env.c
--- qmail-1.03-orig/env.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/env.c	2006-02-25 11:00:55.000000000 +0100
@@ -11,8 +11,8 @@
 #include "env.h"
 
 int env_isinit = 0; /* if env_isinit: */
-static int ea; /* environ is a pointer to ea+1 char*'s. */
-static int en; /* the first en of those are ALLOCATED. environ[en] is 0. */
+static unsigned int ea; /* environ is a pointer to ea+1 char*'s. */
+static unsigned int en; /* the first en of those are ALLOCATED. environ[en] is 0. */
 
 static void env_goodbye(i) int i;
 {
@@ -23,22 +23,26 @@
 
 static char *null = 0;
 
-void env_clear()
+void env_clear(void)
 {
  if (env_isinit) while (en) env_goodbye(0);
  else environ = &null;
 }
 
-static void env_unsetlen(s,len) char *s; int len;
+static void env_unsetlen(s,len) const char *s; unsigned int len;
 {
- int i;
- for (i = en - 1;i >= 0;--i)
+ unsigned int i;
+ 
+ i = en;
+ do {
+   --i;
    if (!str_diffn(s,environ[i],len))
      if (environ[i][len] == '=')
        env_goodbye(i);
+ } while (i > 0);
 }
 
-int env_unset(s) char *s;
+int env_unset(s) const char *s;
 {
  if (!env_isinit) if (!env_init()) return 0;
  env_unsetlen(s,str_len(s));
@@ -47,13 +51,13 @@
 
 static int env_add(s) char *s;
 {
- char *t;
+ const char *t;
  t = env_findeq(s);
  if (t) env_unsetlen(s,t - s);
  if (en == ea)
   {
    ea += 30;
-   if (!alloc_re(&environ,(en + 1) * sizeof(char *),(ea + 1) * sizeof(char *)))
+   if (!alloc_re((char **)&environ,(en + 1) * sizeof(char *),(ea + 1) * sizeof(char *)))
     { ea = en; return 0; }
   }
  environ[en++] = s;
@@ -61,7 +65,7 @@
  return 1;
 }
 
-int env_put(s) char *s;
+int env_put(s) const char *s;
 {
  char *u;
  if (!env_isinit) if (!env_init()) return 0;
@@ -72,10 +76,10 @@
  return 1;
 }
 
-int env_put2(s,t) char *s; char *t;
+int env_put2(s,t) const char *s; const char *t;
 {
  char *u;
- int slen;
+ unsigned int slen;
  if (!env_isinit) if (!env_init()) return 0;
  slen = str_len(s);
  u = alloc(slen + str_len(t) + 2);
@@ -87,10 +91,10 @@
  return 1;
 }
 
-int env_init()
+int env_init(void)
 {
  char **newenviron;
- int i;
+ unsigned int i;
  for (en = 0;environ[en];++en) ;
  ea = en + 10;
  newenviron = (char **) alloc((ea + 1) * sizeof(char *));
diff -ruN qmail-1.03-orig/env.h qmail-1.03-ldap-20060201-orig/env.h
--- qmail-1.03-orig/env.h	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/env.h	2006-02-25 11:00:55.000000000 +0100
@@ -3,14 +3,14 @@
 
 extern int env_isinit;
 
-extern int env_init();
-extern int env_put();
-extern int env_put2();
-extern int env_unset();
-extern /*@null@*/char *env_get();
-extern char *env_pick();
-extern void env_clear();
-extern char *env_findeq();
+extern int env_init(void);
+extern int env_put(const char *);
+extern int env_put2(const char *, const char *);
+extern int env_unset(const char *);
+extern /*@null@*/char *env_get(const char *);
+extern char *env_pick(void);
+extern void env_clear(void);
+extern const char *env_findeq(const char *);
 
 extern char **environ;
 
diff -ruN qmail-1.03-orig/envread.c qmail-1.03-ldap-20060201-orig/envread.c
--- qmail-1.03-orig/envread.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/envread.c	2006-02-25 11:00:55.000000000 +0100
@@ -2,26 +2,26 @@
 #include "str.h"
 
 extern /*@null@*/char *env_get(s)
-char *s;
+const char *s;
 {
-  int i;
+  unsigned int i;
   unsigned int slen;
   char *envi;
  
   slen = str_len(s);
-  for (i = 0;envi = environ[i];++i)
+  for (i = 0;(envi = environ[i]);++i)
     if ((!str_diffn(s,envi,slen)) && (envi[slen] == '='))
       return envi + slen + 1;
   return 0;
 }
 
-extern char *env_pick()
+extern char *env_pick(void)
 {
   return environ[0];
 }
 
-extern char *env_findeq(s)
-char *s;
+extern const char *env_findeq(s)
+const char *s;
 {
   for (;*s;++s)
     if (*s == '=')
diff -ruN qmail-1.03-orig/error.3 qmail-1.03-ldap-20060201-orig/error.3
--- qmail-1.03-orig/error.3	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/error.3	2006-02-25 11:00:55.000000000 +0100
@@ -4,8 +4,6 @@
 .SH SYNTAX
 .B #include <error.h>
 
-extern int \fBerrno\fP;
-
 extern int \fBerror_intr\fP;
 .br
 extern int \fBerror_nomem\fP;
diff -ruN qmail-1.03-orig/error.c qmail-1.03-ldap-20060201-orig/error.c
--- qmail-1.03-orig/error.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/error.c	2006-02-25 11:00:55.000000000 +0100
@@ -1,4 +1,3 @@
-#include <errno.h>
 #include "error.h"
 
 /* warning: as coverage improves here, should update error_{str,temp} */
@@ -93,3 +92,18 @@
 #else
 -13;
 #endif
+
+int error_range =
+#ifdef ERANGE
+ERANGE;
+#else
+-14;
+#endif
+
+int error_proto =
+#ifdef EPROTO
+EPROTO;
+#else
+-15;
+#endif
+
diff -ruN qmail-1.03-orig/error.h qmail-1.03-ldap-20060201-orig/error.h
--- qmail-1.03-orig/error.h	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/error.h	2006-02-25 11:00:55.000000000 +0100
@@ -1,7 +1,7 @@
 #ifndef ERROR_H
 #define ERROR_H
 
-extern int errno;
+#include <errno.h>
 
 extern int error_intr;
 extern int error_nomem;
@@ -16,8 +16,10 @@
 extern int error_pipe;
 extern int error_perm;
 extern int error_acces;
+extern int error_range;
+extern int error_proto;
 
-extern char *error_str();
-extern int error_temp();
+extern const char *error_str(int);
+extern int error_temp(int);
 
 #endif
diff -ruN qmail-1.03-orig/error_str.c qmail-1.03-ldap-20060201-orig/error_str.c
--- qmail-1.03-orig/error_str.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/error_str.c	2006-02-25 11:00:55.000000000 +0100
@@ -3,7 +3,7 @@
 
 #define X(e,s) if (i == e) return s;
 
-char *error_str(i)
+const char *error_str(i)
 int i;
 {
   X(0,"no error")
@@ -20,6 +20,8 @@
   X(error_pipe,"broken pipe")
   X(error_perm,"permission denied")
   X(error_acces,"access denied")
+  X(error_range,"numerical result out of range")
+  X(error_proto,"protocol error")
 #ifdef ESRCH
   X(ESRCH,"no such process")
 #endif
@@ -92,9 +94,6 @@
 #ifdef EDOM
   X(EDOM,"input out of range")
 #endif
-#ifdef ERANGE
-  X(ERANGE,"output out of range")
-#endif
 #ifdef EALREADY
   X(EALREADY,"operation already in progress")
 #endif
@@ -263,9 +262,6 @@
 #ifdef ECOMM
   X(ECOMM,"communication error")
 #endif
-#ifdef EPROTO
-  X(EPROTO,"protocol error")
-#endif
 #ifdef EMULTIHOP
   X(EMULTIHOP,"multihop attempted")
 #endif
diff -ruN qmail-1.03-orig/except.c qmail-1.03-ldap-20060201-orig/except.c
--- qmail-1.03-orig/except.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/except.c	2006-02-25 11:00:55.000000000 +0100
@@ -1,3 +1,4 @@
+#include <unistd.h>
 #include "fork.h"
 #include "strerr.h"
 #include "wait.h"
@@ -6,7 +7,7 @@
 
 #define FATAL "except: fatal: "
 
-void main(argc,argv)
+int main(argc,argv)
 int argc;
 char **argv;
 {
@@ -32,6 +33,7 @@
   switch(wait_exitcode(wstat)) {
     case 0: _exit(100);
     case 111: strerr_die2x(111,FATAL,"temporary child error");
-    default: _exit(0);
+    default: break;
   }
+  return 0;
 }
diff -ruN qmail-1.03-orig/execcheck.c qmail-1.03-ldap-20060201-orig/execcheck.c
--- qmail-1.03-orig/execcheck.c	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/execcheck.c	2006-02-25 11:00:55.000000000 +0100
@@ -0,0 +1,310 @@
+/*
+ * Copyright (c) 2003-2004 Claudio Jeker,
+ *      Internet Business Solutions AG, CH-8005 Zürich, Switzerland
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Internet Business
+ *      Solutions AG and its contributors.
+ * 4. Neither the name of the author nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+/*
+ * Code and idea is based on a patch by Russel Nelson.
+ */
+
+#ifdef SMTPEXECCHECK
+#include "byte.h"
+#include "case.h"
+#include "control.h"
+#include "env.h"
+#include "qmail.h"
+#include "str.h"
+#include "stralloc.h"
+
+#include "execcheck.h"
+
+extern void die_nomem(); /* needed error function from qmail-smtpd,c */
+extern void die_control();
+
+static int checkexecutable = 0;
+static int flagexecutable;
+static stralloc signatures = {0};
+
+void
+execcheck_setup(void)
+{
+	if (env_get("REJECTEXEC")) checkexecutable = 1;
+	switch (control_readfile(&signatures,"control/signatures",0)) {
+	case 0:
+		checkexecutable = 0;
+		break;
+	case 1:
+		break;
+	default:
+		die_control();
+	}
+}
+
+int
+execcheck_on(void)
+{
+	return checkexecutable;
+}
+
+int
+execcheck_flag(void)
+{
+	return flagexecutable;
+}
+
+static int
+signatures_match(stralloc *line, char *sig)
+{
+	unsigned int	k;
+
+	for (k = 0; k < line->len && *sig; k++, sig++)
+		if (*sig != '*')
+			if (*sig != line->s[k]) return 0;
+	if (*sig) return 0;
+	return 1;
+}
+
+static int
+signatures_check(stralloc *line)
+{
+	unsigned int	i, j;
+
+	for (i = j = 0; i < signatures.len; i++)
+		if (!signatures.s[i]) {
+			if (signatures_match(line, signatures.s + j))
+				return 1;
+			j = i+1;
+		}
+	return 0;
+}
+
+static int linespastheader;	/* = 0 if in header (mime or mail)
+			 	 * = 1 line after blank line
+				 * = 2 somewhere in body
+				 */
+static unsigned int boundary_start;
+static unsigned int boundary_len;
+static int flagrfc822;
+static char linetype;
+
+static stralloc line = {0};
+static stralloc content = {0};
+static stralloc boundary = {0};
+static stralloc token = {0};
+
+static void
+parse_token(void)
+{
+	if (token.len == 0 || *token.s == '\0')
+		return;
+
+	if (case_startb(token.s, token.len, "boundary=")) {
+		/*
+		 * push the current boundary.
+		 * Append a null and remember start.
+		 */
+		boundary_start = boundary.len;
+		if (!stralloc_cats(&boundary, "--"))
+			die_nomem();
+		if (!stralloc_cats(&boundary, token.s + 9))
+			die_nomem();
+		boundary_len = boundary.len - boundary_start;
+		if (!stralloc_0(&boundary))
+			die_nomem();
+		return;
+	}
+	if (!case_diffb(token.s, token.len, "message/rfc822")) {
+		flagrfc822 = 1;
+		return;
+	}
+}
+
+static void
+parse_contenttype(void)
+{
+	char	*c;
+	int	flagquoted = 0;
+	int	flagcomment = 0;
+
+	if (content.len == 0) /* NO MIME header */
+		return;
+
+	if (!stralloc_0(&content)) die_nomem();
+
+	for (c = content.s; *c != '\0'; ) {
+		for (; *c != '\0'; c++)
+			if (*c != ' ' && *c != '\t' && *c != ';')
+				break;
+
+		if (!stralloc_copys(&token, "")) die_nomem();
+		for (; *c != '\0'; c++)
+			switch (*c) {
+			case ' ':
+			case '\t':
+			case ';':
+				if (flagquoted)
+					break;
+				goto token_done;
+			case '"':
+				if (flagquoted)
+					flagquoted = 0;
+				else
+					flagquoted = 1;
+				break;
+			case '(':
+				if (flagquoted) {
+					if (!stralloc_append(&token, c))
+					       	die_nomem();
+					break;
+				}
+				flagcomment = 1;
+				break;
+			case ')':
+				if (flagquoted) {
+					if (!stralloc_append(&token, c))
+						die_nomem();
+					break;
+				}
+				flagcomment = 0;
+				break;
+			default:
+				if (flagcomment)
+					break;
+				if (!stralloc_append(&token, c)) die_nomem();
+				break;
+			}
+token_done:
+		if (!stralloc_0(&token)) die_nomem();
+		parse_token();
+	}
+}
+
+void
+execcheck_start(void)
+{
+	boundary.len = 0;
+	content.len = 0;
+	linespastheader = 0;
+	boundary_start = 0;
+	boundary_len = 0;
+	flagexecutable = 0;
+	flagrfc822 = 0;
+	linetype = ' ';
+}
+
+void
+execcheck_put(struct qmail *qq, const char *ch)
+{
+	if (!checkexecutable)
+		return;
+
+	/* already bad so leave it */
+	if (flagexecutable)
+		return;
+
+	if (line.len < 1024)
+		if (!stralloc_catb(&line,ch,1)) die_nomem();
+
+	if (*ch != '\n')
+		/* wait until we have a entire line together */
+		return;
+
+	if (linespastheader == 0) {
+		/*
+		 * in mail or mime header, search for content-type
+		 * and possible boundary
+		 */
+		if (line.len == 1) {	/* end of header */
+			linespastheader = 1;
+			if (content.len) /* MIME header */
+				parse_contenttype();
+			if (flagrfc822) {
+				/* now the forwarded rfc822 header is comming */
+				linespastheader = 0;
+				flagrfc822 = 0;
+			}
+		} else {	/* header lines */
+			if (*line.s == ' ' || *line.s == '\t') {
+				switch(linetype) {
+				case 'C':
+					if (!stralloc_catb(&content,
+						    line.s, line.len-1))
+						die_nomem();
+					break;
+				default:
+					break;
+				}
+			} else {
+				if (case_startb(line.s, line.len,
+					    "content-type:")) {
+					if (!stralloc_copyb(&content,
+						    line.s+13, line.len-14))
+						die_nomem();
+					linetype = 'C';
+				} else {
+					linetype = ' ';
+				}
+			}
+		}
+	} else {	/* non-header lines */
+		if (boundary_len && *line.s == '-' &&
+		    stralloc_starts(&line,boundary.s + boundary_start)) {
+			/* mime boundary matched */
+			if (line.len > boundary_len + 2 &&
+			    !str_diffn(line.s + boundary_len, "--", 2)) {
+				/* end marker - pop last boundary */
+				linespastheader = 2;
+				if (boundary_start) {
+					boundary.len = boundary_start;
+					boundary_start = byte_rchr(boundary.s,
+					    boundary.len - 1, '\0');
+					if (boundary_start + 1 >= boundary.len)
+						boundary_start = 0;
+					boundary_len = boundary.len - 1 -
+					    boundary_start;
+				} else
+					boundary_len = 0;
+			} else
+				linespastheader = 0;
+		} else if (linespastheader == 1) {
+			if (signatures_check(&line)) {
+				flagexecutable = 1;
+				qmail_fail(qq);
+			}
+			linespastheader = 2;
+		}
+	}
+	line.len = 0;
+}
+
+#endif
+
diff -ruN qmail-1.03-orig/execcheck.h qmail-1.03-ldap-20060201-orig/execcheck.h
--- qmail-1.03-orig/execcheck.h	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/execcheck.h	2006-02-25 11:00:55.000000000 +0100
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2003-2004 Claudio Jeker,
+ *      Internet Business Solutions AG, CH-8005 Zürich, Switzerland
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Internet Business
+ *      Solutions AG and its contributors.
+ * 4. Neither the name of the author nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#ifndef __EXECCHECK_H__
+#define __EXECCHECK_H__
+
+struct qmail;
+
+void execcheck_setup(void);
+void execcheck_start(void);
+int execcheck_on(void);
+int execcheck_flag(void);
+void execcheck_put(struct qmail *, const char *);
+
+#endif
diff -ruN qmail-1.03-orig/exit.h qmail-1.03-ldap-20060201-orig/exit.h
--- qmail-1.03-orig/exit.h	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/exit.h	2006-02-25 11:00:55.000000000 +0100
@@ -1,6 +1,7 @@
 #ifndef EXIT_H
 #define EXIT_H
 
-extern void _exit();
+/* XXX unistd.h */
+extern void _exit(int);
 
 #endif
diff -ruN qmail-1.03-orig/EXTTODO qmail-1.03-ldap-20060201-orig/EXTTODO
--- qmail-1.03-orig/EXTTODO	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/EXTTODO	2006-02-25 11:00:55.000000000 +0100
@@ -0,0 +1,112 @@
+EXTTODO by Claudio Jeker <jeker@n-r-g.com> and 
+Andre Oppermann <opi@nrg4u.com>
+(c) 2002-2004 Internet Business Solutions Ltd.
+
+The EXTTODO patch is a part of the qmail-ldap patch.
+This patches for qmail come with NO WARRANTY.
+
+RELEASE: 5. Jan. 2003 ($Date: 2004/04/16 13:24:16 $)
+
+EXTTODO:
+======================
+
+TOC:
+ WHAT DOES IT DO
+ INSTALL
+ CONFIG FILES
+ SETUP
+ BIG PICTURE
+
+NEWS:
+ 
+ This is the first release of the EXTTODO patch.
+
+================================================================================
+
+WHAT DOES IT DO
+
+ The exttodo patch addresses a problem known as the silly qmail (queue)
+ problem. This problem is found only on system with high injection rates.
+
+ qmail with a big local and remote concurrency could deliver a tremendous 
+ amount of messages but normally this can not be achieved because qmail-send
+ becomes a bottleneck on those high volumes servers.
+ qmail-send preprocesses all new messages before distributing them for local
+ or remote delivering. In one run qmail-send does one todo run but has the 
+ ability to close multiple jobs. Because of this layout qmail-send can not 
+ feed all the new available (local/remote) delivery slots and therefor it is 
+ not possible to achieve the maximum throughput.
+ This would be a minor problem if one qmail-send run could be done in extreme
+ short time but because of many file system calls (fsync and (un)link) a todo
+ run is expensive and throttles the throughput.
+
+ The exttodo patch tries to solve the problem by moving the todo routine into 
+ an external program. This reduces the run time in qmail-send.
+
+ exttodo adds a new program to qmail called qmail-todo. qmail-todo prepares
+ incoming messages for local and remote delivering (by creating info/<messid>
+ local/<messid> and remote/<messid> and removing todo/<messid>). See also
+ INTERNALS. As next qmail-todo transmits the <messid> to qmail-send which will
+ add this message into the priority queue which schedules the message for 
+ delivery. 
+
+INSTALL
+
+ To enable the exttodo patch you need to define EXTERNAL_TODO while compiling
+ qmail(-ldap) this can be done with the -D flag of cc (e.g. cc -DEXTERNAL_TODO).
+
+ NOTE: the exttodo patch can also be used on qmail systems without the 
+ qmail-ldap patch.
+ 
+================================================================================
+
+CONFIG FILES
+
+ No additional control files are used or needed.
+
+================================================================================
+
+SETUP
+
+ qmail-todo will be started by qmail-start and therefor no additional setup
+ is needed.
+
+ To verify that exttodo is running just check if qmail-todo is running.
+
+================================================================================
+
+BIG PICTURE
+
+               +-------+   +-------+
+               | clean |   | clean |
+               +--0-1--+   +--0-1--+       +-----------+
+         trigger  ^ |         ^ |        +->0,1 lspawn |
+            |     | v         | v       /  +-----------+
+ +-------+  v  +--2-3--+   +--5-6--+   /
+ |       |  |  |       0<--7     1,2<-+
+ | queue |--+--| todo  |   | send  |
+ |       |  |  |       1-->8     3,4<-+
+ +-------+     +-------+   +---0---+   \
+                               |        \  +-----------+
+                               v         +->0,1 rspwan |
+                           +---0---+       +-----------+
+                           | logger|
+                           +-------+
+
+Communication between qmail-send and qmail-todo
+
+todo -> send:
+   D[LRB]<mesgid>\0
+          Start delivery for new message with id <messid>.
+          the character L, R or B defines the type
+          of delivery, local, remote or both respectively.
+   L<string>\0
+          Dump string to the logger without adding additional \n or similar.
+send -> todo:
+   H      Got a SIGHUP reread ~/control/locals and ~/control/virtualdomains
+   X      Quit ASAP.
+
+qmail-todo sends "\0" terminated messages whereas qmail-send just send one
+character to qmail-todo.
+
+
diff -ruN qmail-1.03-orig/fd_copy.c qmail-1.03-ldap-20060201-orig/fd_copy.c
--- qmail-1.03-orig/fd_copy.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/fd_copy.c	2006-02-25 11:00:55.000000000 +0100
@@ -1,4 +1,5 @@
 #include <fcntl.h>
+#include <unistd.h>
 #include "fd.h"
 
 int fd_copy(to,from)
diff -ruN qmail-1.03-orig/fd.h qmail-1.03-ldap-20060201-orig/fd.h
--- qmail-1.03-orig/fd.h	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/fd.h	2006-02-25 11:00:55.000000000 +0100
@@ -1,7 +1,7 @@
 #ifndef FD_H
 #define FD_H
 
-extern int fd_copy();
-extern int fd_move();
+extern int fd_copy(int, int);
+extern int fd_move(int, int);
 
 #endif
diff -ruN qmail-1.03-orig/fd_move.c qmail-1.03-ldap-20060201-orig/fd_move.c
--- qmail-1.03-orig/fd_move.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/fd_move.c	2006-02-25 11:00:55.000000000 +0100
@@ -1,3 +1,4 @@
+#include <unistd.h>
 #include "fd.h"
 
 int fd_move(to,from)
diff -ruN qmail-1.03-orig/fifo.c qmail-1.03-ldap-20060201-orig/fifo.c
--- qmail-1.03-orig/fifo.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/fifo.c	2006-02-25 11:00:55.000000000 +0100
@@ -4,7 +4,7 @@
 #include "fifo.h"
 
 #ifdef HASMKFIFO
-int fifo_make(fn,mode) char *fn; int mode; { return mkfifo(fn,mode); }
+int fifo_make(fn,mode) const char *fn; int mode; { return mkfifo(fn,mode); }
 #else
-int fifo_make(fn,mode) char *fn; int mode; { return mknod(fn,S_IFIFO | mode,0); }
+int fifo_make(fn,mode) const char *fn; int mode; { return mknod(fn,S_IFIFO | mode,0); }
 #endif
diff -ruN qmail-1.03-orig/fifo.h qmail-1.03-ldap-20060201-orig/fifo.h
--- qmail-1.03-orig/fifo.h	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/fifo.h	2006-02-25 11:00:55.000000000 +0100
@@ -1,6 +1,6 @@
 #ifndef FIFO_H
 #define FIFO_H
 
-extern int fifo_make();
+extern int fifo_make(const char *, int);
 
 #endif
diff -ruN qmail-1.03-orig/FILES qmail-1.03-ldap-20060201-orig/FILES
--- qmail-1.03-orig/FILES	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/FILES	2006-02-25 11:00:55.000000000 +0100
@@ -227,16 +227,11 @@
 case_lowers.c
 case_starts.c
 cdb.3
+cdb.c
 cdb.h
 cdb_hash.c
-cdb_seek.c
-cdb_unpack.c
-cdbmake.h
-cdbmake_add.c
-cdbmake_hash.c
-cdbmake_pack.c
-cdbmss.h
-cdbmss.c
+cdb_make.c
+cdb_make.h
 coe.3
 coe.h
 coe.c
@@ -431,3 +426,105 @@
 tcp-environ.5
 constmap.h
 constmap.c
+EXTTODO
+Makefile.cdb
+POPBEFORESMTP
+QLDAPGROUP
+QLDAPINSTALL
+QLDAPNEWS
+QLDAPPICTURE
+QLDAPTODO
+TLS.readme
+auth_imap.c
+auth_mod.c
+auth_mod.h
+auth_pop.c
+auth_smtp.c
+auto_userl.h
+base64.c
+base64.h
+byte_repl.c
+case_startb.c
+check.c
+check.h
+checkpassword.c
+checkpassword.h
+condwrite.c
+digest.c
+digest_md4.c
+digest_md4.h
+digest_md5.c
+digest_md5.h
+digest_rmd160.c
+digest_rmd160.h
+digest_sha1.c
+digest_sha1.h
+dirmaker
+dirmaker.c
+dirmaker.h
+endian.c
+execcheck.c
+execcheck.h
+localdelivery.c
+localdelivery.h
+locallookup.c
+locallookup.h
+maildir++.c
+maildir++.h
+mailmagic.c
+mailmagic.h
+mailmaker.c
+mailmaker.h
+output.c
+output.h
+passwd.c
+passwd.h
+pbsadd.c
+pbscheck.c
+pbsdbd.c
+pbsexec.c
+pbsexec.h
+popfetch.pl
+qldap-cluster.c
+qldap-cluster.h
+qldap-debug.c
+qldap-debug.h
+qldap-errno.c
+qldap-errno.h
+qldap-filter.c
+qldap-profile.c
+qldap-profile.h
+qldap.c
+qldap.h
+qmail-cdb.c
+qmail-forward.c
+qmail-group.c
+qmail-imapd-ssl.sh
+qmail-imapd.rules
+qmail-imapd.sh
+qmail-ldap.h
+qmail-ldaplookup.c
+qmail-pop3d-ssl.sh
+qmail-pop3d.rules
+qmail-pop3d.sh
+qmail-qmqpd.rules
+qmail-qmqpd.sh
+qmail-quotawarn.c
+qmail-reply.c
+qmail-secretary.c
+qmail-smtpd.rules
+qmail-smtpd.sh
+qmail-todo.c
+qmail-verify.c
+qmail.schema
+qmail.sh
+rbl.c
+rbl.h
+read-ctrl.c
+read-ctrl.h
+readwrite.c
+signatures
+smtpcall.c
+smtpcall.h
+xtext.c
+xtext.h
diff -ruN qmail-1.03-orig/fmt.h qmail-1.03-ldap-20060201-orig/fmt.h
--- qmail-1.03-orig/fmt.h	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/fmt.h	2006-02-25 11:00:55.000000000 +0100
@@ -4,22 +4,26 @@
 #define FMT_ULONG 40 /* enough space to hold 2^128 - 1 in decimal, plus \0 */
 #define FMT_LEN ((char *) 0) /* convenient abbreviation */
 
-extern unsigned int fmt_uint();
-extern unsigned int fmt_uint0();
+extern unsigned int fmt_uint(char *, unsigned int);
+extern unsigned int fmt_uint0(char *, unsigned int, unsigned int);
+/* XXX not available in qmail-1.03
 extern unsigned int fmt_xint();
 extern unsigned int fmt_nbbint();
 extern unsigned int fmt_ushort();
 extern unsigned int fmt_xshort();
 extern unsigned int fmt_nbbshort();
-extern unsigned int fmt_ulong();
+*/
+extern unsigned int fmt_ulong(char *, unsigned long);
+/* XXX not available in qmail-1.03
 extern unsigned int fmt_xlong();
 extern unsigned int fmt_nbblong();
 
 extern unsigned int fmt_plusminus();
 extern unsigned int fmt_minus();
 extern unsigned int fmt_0x();
+*/
 
-extern unsigned int fmt_str();
-extern unsigned int fmt_strn();
+extern unsigned int fmt_str(char *, const char *);
+extern unsigned int fmt_strn(char *, const char *, unsigned int);
 
 #endif
diff -ruN qmail-1.03-orig/fmtqfn.c qmail-1.03-ldap-20060201-orig/fmtqfn.c
--- qmail-1.03-orig/fmtqfn.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/fmtqfn.c	2006-02-25 11:00:55.000000000 +0100
@@ -4,7 +4,7 @@
 
 unsigned int fmtqfn(s,dirslash,id,flagsplit)
 char *s;
-char *dirslash;
+const char *dirslash;
 unsigned long id;
 int flagsplit;
 {
diff -ruN qmail-1.03-orig/fmtqfn.h qmail-1.03-ldap-20060201-orig/fmtqfn.h
--- qmail-1.03-orig/fmtqfn.h	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/fmtqfn.h	2006-02-25 11:00:55.000000000 +0100
@@ -1,7 +1,7 @@
 #ifndef FMTQFN_H
 #define FMTQFN_H
 
-extern unsigned int fmtqfn();
+extern unsigned int fmtqfn(char *, const char *, unsigned long, int);
 
 #define FMTQFN 40 /* maximum space needed, if len(dirslash) <= 10 */
 
diff -ruN qmail-1.03-orig/fmt_str.c qmail-1.03-ldap-20060201-orig/fmt_str.c
--- qmail-1.03-orig/fmt_str.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/fmt_str.c	2006-02-25 11:00:55.000000000 +0100
@@ -1,12 +1,12 @@
 #include "fmt.h"
 
 unsigned int fmt_str(s,t)
-register char *s; register char *t;
+register char *s; register const char *t;
 {
   register unsigned int len;
   char ch;
   len = 0;
-  if (s) { while (ch = t[len]) s[len++] = ch; }
+  if (s) { while ((ch = t[len])) s[len++] = ch; }
   else while (t[len]) len++;
   return len;
 }
diff -ruN qmail-1.03-orig/fmt_strn.c qmail-1.03-ldap-20060201-orig/fmt_strn.c
--- qmail-1.03-orig/fmt_strn.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/fmt_strn.c	2006-02-25 11:00:55.000000000 +0100
@@ -1,7 +1,7 @@
 #include "fmt.h"
 
 unsigned int fmt_strn(s,t,n)
-register char *s; register char *t; register unsigned int n;
+register char *s; register const char *t; register unsigned int n;
 {
   register unsigned int len;
   char ch;
diff -ruN qmail-1.03-orig/fork.h1 qmail-1.03-ldap-20060201-orig/fork.h1
--- qmail-1.03-orig/fork.h1	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/fork.h1	2006-02-25 11:00:55.000000000 +0100
@@ -1,7 +1,8 @@
 #ifndef FORK_H
 #define FORK_H
 
-extern int fork();
+#include <unistd.h>
+
 #define vfork fork
 
 #endif
diff -ruN qmail-1.03-orig/fork.h2 qmail-1.03-ldap-20060201-orig/fork.h2
--- qmail-1.03-orig/fork.h2	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/fork.h2	2006-02-25 11:00:55.000000000 +0100
@@ -1,7 +1,6 @@
 #ifndef FORK_H
 #define FORK_H
 
-extern int fork();
-extern int vfork();
+#include <unistd.h>
 
 #endif
diff -ruN qmail-1.03-orig/forward.c qmail-1.03-ldap-20060201-orig/forward.c
--- qmail-1.03-orig/forward.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/forward.c	2006-02-25 11:00:55.000000000 +0100
@@ -13,7 +13,7 @@
 
 struct qmail qqt;
 
-int mywrite(fd,buf,len) int fd; char *buf; int len;
+int mywrite(int fd, void *buf, int len)
 {
   qmail_put(&qqt,buf,len);
   return len;
@@ -21,18 +21,18 @@
 
 char inbuf[SUBSTDIO_INSIZE];
 char outbuf[1];
-substdio ssin = SUBSTDIO_FDBUF(read,0,inbuf,sizeof inbuf);
+substdio ssin = SUBSTDIO_FDBUF(subread,0,inbuf,sizeof inbuf);
 substdio ssout = SUBSTDIO_FDBUF(mywrite,-1,outbuf,sizeof outbuf);
 
 char num[FMT_ULONG];
 
-void main(argc,argv)
+int main(argc,argv)
 int argc;
 char **argv;
 {
   char *sender;
   char *dtline;
-  char *qqx;
+  const char *qqx;
  
   sig_pipeignore();
  
@@ -57,4 +57,5 @@
   qqx = qmail_close(&qqt);
   if (*qqx) strerr_die2x(*qqx == 'D' ? 100 : 111,FATAL,qqx + 1);
   strerr_die2x(0,"forward: qp ",num);
+  return 0;
 }
diff -ruN qmail-1.03-orig/gen_allocdefs.h qmail-1.03-ldap-20060201-orig/gen_allocdefs.h
--- qmail-1.03-orig/gen_allocdefs.h	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/gen_allocdefs.h	2006-02-25 11:00:55.000000000 +0100
@@ -8,7 +8,7 @@
     i = x->a; \
     if (n > i) { \
       x->a = base + n + (n >> 3); \
-      if (alloc_re(&x->field,i * sizeof(type),x->a * sizeof(type))) return 1; \
+      if (alloc_re((char **)&x->field,i * sizeof(type),x->a * sizeof(type))) return 1; \
       x->a = i; return 0; } \
     return 1; } \
   x->len = 0; \
@@ -21,7 +21,7 @@
     i = x->a; n += x->len; \
     if (n > i) { \
       x->a = base + n + (n >> 3); \
-      if (alloc_re(&x->field,i * sizeof(type),x->a * sizeof(type))) return 1; \
+      if (alloc_re((char **)&x->field,i * sizeof(type),x->a * sizeof(type))) return 1; \
       x->a = i; return 0; } \
     return 1; } \
   x->len = 0; \
diff -ruN qmail-1.03-orig/getln2.c qmail-1.03-ldap-20060201-orig/getln2.c
--- qmail-1.03-orig/getln2.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/getln2.c	2006-02-25 11:00:55.000000000 +0100
@@ -23,7 +23,11 @@
     if (n == 0) { *clen = 0; return 0; }
     x = substdio_PEEK(ss);
     i = byte_chr(x,n,sep);
-    if (i < n) { substdio_SEEK(ss,*clen = i + 1); *cont = x; return 0; }
+    if (i < (unsigned int)n) {
+      substdio_SEEK(ss,*clen = i + 1);
+      *cont = x;
+      return 0;
+    }
     if (!stralloc_readyplus(sa,n)) return -1;
     i = sa->len;
     sa->len = i + substdio_get(ss,sa->s + i,n);
diff -ruN qmail-1.03-orig/getln.h qmail-1.03-ldap-20060201-orig/getln.h
--- qmail-1.03-orig/getln.h	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/getln.h	2006-02-25 11:00:55.000000000 +0100
@@ -1,7 +1,10 @@
 #ifndef GETLN_H
 #define GETLN_H
 
-extern int getln();
-extern int getln2();
+#include "stralloc.h"
+#include "substdio.h"
+
+extern int getln(substdio *, stralloc *, int *, int);
+extern int getln2(substdio *, stralloc *, char **, unsigned int *, int);
 
 #endif
diff -ruN qmail-1.03-orig/gettimeofday.c qmail-1.03-ldap-20060201-orig/gettimeofday.c
--- qmail-1.03-orig/gettimeofday.c	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/gettimeofday.c	2006-02-25 11:00:55.000000000 +0100
@@ -0,0 +1,13 @@
+#include   <stdio.h>
+#include   <sys/time.h>
+
+struct timeval sincepoch = {0,0};
+struct timezone notimezone = {0,0};
+
+int main()
+{
+  gettimeofday(&sincepoch, &notimezone);
+  printf("%d\n", sincepoch.tv_sec);
+  return 0;
+}
+
diff -ruN qmail-1.03-orig/gfrom.h qmail-1.03-ldap-20060201-orig/gfrom.h
--- qmail-1.03-orig/gfrom.h	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/gfrom.h	2006-02-25 11:00:55.000000000 +0100
@@ -1,6 +1,6 @@
 #ifndef GFROM_H
 #define GFROM_H
 
-extern int gfrom();
+extern int gfrom(char *, int);
 
 #endif
diff -ruN qmail-1.03-orig/headerbody.h qmail-1.03-ldap-20060201-orig/headerbody.h
--- qmail-1.03-orig/headerbody.h	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/headerbody.h	2006-02-25 11:00:55.000000000 +0100
@@ -1,6 +1,10 @@
 #ifndef HEADERBODY_H
 #define HEADERBODY_H
 
-extern int headerbody();
+#include "stralloc.h"
+#include "substdio.h"
+
+extern int headerbody(substdio *,
+    void (*)(stralloc *), void (*)(void), void (*)(stralloc *));
 
 #endif
diff -ruN qmail-1.03-orig/hfield.c qmail-1.03-ldap-20060201-orig/hfield.c
--- qmail-1.03-orig/hfield.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/hfield.c	2006-02-25 11:00:55.000000000 +0100
@@ -1,6 +1,6 @@
 #include "hfield.h"
 
-static char *(hname[]) = {
+static const char *(hname[]) = {
   "unknown-header"
 , "sender"
 , "from"
@@ -35,13 +35,13 @@
 
 static int hmatch(s,len,t)
 char *s;
-int len;
-char *t;
+unsigned int len;
+const char *t;
 {
- int i;
+ unsigned int i;
  char ch;
 
- for (i = 0;ch = t[i];++i)
+ for (i = 0;(ch = t[i]);++i)
   {
    if (i >= len) return 0;
    if (ch != s[i])
@@ -62,12 +62,12 @@
 
 int hfield_known(s,len)
 char *s;
-int len;
+unsigned int len;
 {
- int i;
- char *t;
+ unsigned int i;
+ const char *t;
 
- for (i = 1;t = hname[i];++i)
+ for (i = 1;(t = hname[i]);++i)
    if (hmatch(s,len,t))
      return i;
  return 0;
@@ -75,10 +75,10 @@
 
 int hfield_valid(s,len)
 char *s;
-int len;
+unsigned int len;
 {
- int i;
- int j;
+ unsigned int i;
+ unsigned int j;
  char ch;
 
  for (j = 0;j < len;++j)
@@ -105,9 +105,9 @@
 
 unsigned int hfield_skipname(s,len)
 char *s;
-int len;
+unsigned int len;
 {
- int i;
+ unsigned int i;
  char ch;
 
  for (i = 0;i < len;++i)
diff -ruN qmail-1.03-orig/hfield.h qmail-1.03-ldap-20060201-orig/hfield.h
--- qmail-1.03-orig/hfield.h	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/hfield.h	2006-02-25 11:00:55.000000000 +0100
@@ -1,9 +1,9 @@
 #ifndef HFIELD_H
 #define HFIELD_H
 
-extern unsigned int hfield_skipname();
-extern int hfield_known();
-extern int hfield_valid();
+extern unsigned int hfield_skipname(char *, unsigned int);
+extern int hfield_known(char *, unsigned int);
+extern int hfield_valid(char *, unsigned int);
 
 #define H_SENDER 1
 #define H_FROM 2
diff -ruN qmail-1.03-orig/hier.c qmail-1.03-ldap-20060201-orig/hier.c
--- qmail-1.03-orig/hier.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/hier.c	2006-02-25 11:00:55.000000000 +0100
@@ -1,9 +1,21 @@
 #include "auto_qmail.h"
 #include "auto_split.h"
 #include "auto_uids.h"
+#include "auto_userl.h"
 #include "fmt.h"
 #include "fifo.h"
 
+extern void c(const char *, const char *, const char *, int, int, int);
+extern void C(const char *, const char *, const char *, const char *,
+ int, int, int);
+extern void d(const char *, const char *, int, int, int);
+extern void h(const char *, int, int, int);
+extern void l(const char *, const char *, const char *, const char *,
+ int, int, int);
+extern void p(const char *, const char *, int, int, int);
+extern void z(const char *, const char *, int, int, int, int);
+
+
 char buf[100 + FMT_ULONG];
 
 void dsplit(base,uid,mode)
@@ -34,8 +46,46 @@
   d(auto_qmail,"control",auto_uido,auto_gidq,0755);
   d(auto_qmail,"users",auto_uido,auto_gidq,0755);
   d(auto_qmail,"bin",auto_uido,auto_gidq,0755);
-  d(auto_qmail,"boot",auto_uido,auto_gidq,0755);
   d(auto_qmail,"doc",auto_uido,auto_gidq,0755);
+
+  /* boot restructured for daemontools */
+  d(auto_qmail,"boot",auto_uido,auto_gidq,0755);
+  d(auto_qmail,"boot/qmail",auto_uido,auto_gidq,0755);
+  d(auto_qmail,"boot/qmail/env",auto_uido,auto_gidq,0755);
+  d(auto_qmail,"boot/qmail/log",auto_uido,auto_gidq,0755);
+  d(auto_qmail,"boot/qmail-smtpd",auto_uido,auto_gidq,0755);
+  d(auto_qmail,"boot/qmail-smtpd/env",auto_uido,auto_gidq,0755);
+  d(auto_qmail,"boot/qmail-smtpd/log",auto_uido,auto_gidq,0755);
+  d(auto_qmail,"boot/qmail-qmqpd",auto_uido,auto_gidq,0755);
+  d(auto_qmail,"boot/qmail-qmqpd/env",auto_uido,auto_gidq,0755);
+  d(auto_qmail,"boot/qmail-qmqpd/log",auto_uido,auto_gidq,0755);
+  d(auto_qmail,"boot/qmail-pop3d",auto_uido,auto_gidq,0755);
+  d(auto_qmail,"boot/qmail-pop3d/env",auto_uido,auto_gidq,0755);
+  d(auto_qmail,"boot/qmail-pop3d/log",auto_uido,auto_gidq,0755);
+  d(auto_qmail,"boot/qmail-imapd",auto_uido,auto_gidq,0755);
+  d(auto_qmail,"boot/qmail-imapd/env",auto_uido,auto_gidq,0755);
+  d(auto_qmail,"boot/qmail-imapd/log",auto_uido,auto_gidq,0755);
+  d(auto_qmail,"boot/qmail-pop3d-ssl",auto_uido,auto_gidq,0755);
+  d(auto_qmail,"boot/qmail-pop3d-ssl/env",auto_uido,auto_gidq,0755);
+  d(auto_qmail,"boot/qmail-pop3d-ssl/log",auto_uido,auto_gidq,0755);
+  d(auto_qmail,"boot/qmail-imapd-ssl",auto_uido,auto_gidq,0755);
+  d(auto_qmail,"boot/qmail-imapd-ssl/env",auto_uido,auto_gidq,0755);
+  d(auto_qmail,"boot/qmail-imapd-ssl/log",auto_uido,auto_gidq,0755);
+  d(auto_qmail,"boot/qmail-pbsdbd",auto_uido,auto_gidq,0755);
+  d(auto_qmail,"boot/qmail-pbsdbd/env",auto_uido,auto_gidq,0755);
+  d(auto_qmail,"boot/qmail-pbsdbd/log",auto_uido,auto_gidq,0755);
+
+  /* logging restructured for daemontools */
+  d(auto_qmail,"log",auto_uidl,auto_gidq,0755);
+  d(auto_qmail,"log/qmail",auto_uidl,auto_gidq,0755);
+  d(auto_qmail,"log/qmail-smtpd",auto_uidl,auto_gidq,0755);
+  d(auto_qmail,"log/qmail-qmqpd",auto_uidl,auto_gidq,0755);
+  d(auto_qmail,"log/qmail-pop3d",auto_uidl,auto_gidq,0755);
+  d(auto_qmail,"log/qmail-imapd",auto_uidl,auto_gidq,0755);
+  d(auto_qmail,"log/qmail-pop3d-ssl",auto_uidl,auto_gidq,0755);
+  d(auto_qmail,"log/qmail-imapd-ssl",auto_uidl,auto_gidq,0755);
+  d(auto_qmail,"log/qmail-pbsdbd",auto_uidl,auto_gidq,0755);
+
   d(auto_qmail,"man",auto_uido,auto_gidq,0755);
   d(auto_qmail,"man/cat1",auto_uido,auto_gidq,0755);
   d(auto_qmail,"man/cat5",auto_uido,auto_gidq,0755);
@@ -50,30 +100,57 @@
 
   d(auto_qmail,"queue",auto_uidq,auto_gidq,0750);
   d(auto_qmail,"queue/pid",auto_uidq,auto_gidq,0700);
+#ifndef BIGTODO
   d(auto_qmail,"queue/intd",auto_uidq,auto_gidq,0700);
   d(auto_qmail,"queue/todo",auto_uidq,auto_gidq,0750);
+#endif
   d(auto_qmail,"queue/bounce",auto_uids,auto_gidq,0700);
 
   dsplit("queue/mess",auto_uidq,0750);
   dsplit("queue/info",auto_uids,0700);
   dsplit("queue/local",auto_uids,0700);
   dsplit("queue/remote",auto_uids,0700);
+#ifdef BIGTODO
+  dsplit("queue/intd",auto_uidq,0700);
+  dsplit("queue/todo",auto_uidq,0750);
+#endif
 
   d(auto_qmail,"queue/lock",auto_uidq,auto_gidq,0750);
   z(auto_qmail,"queue/lock/tcpto",1024,auto_uidr,auto_gidq,0644);
   z(auto_qmail,"queue/lock/sendmutex",0,auto_uids,auto_gidq,0600);
   p(auto_qmail,"queue/lock/trigger",auto_uids,auto_gidq,0622);
 
-  c(auto_qmail,"boot","home",auto_uido,auto_gidq,0755);
-  c(auto_qmail,"boot","home+df",auto_uido,auto_gidq,0755);
-  c(auto_qmail,"boot","proc",auto_uido,auto_gidq,0755);
-  c(auto_qmail,"boot","proc+df",auto_uido,auto_gidq,0755);
-  c(auto_qmail,"boot","binm1",auto_uido,auto_gidq,0755);
-  c(auto_qmail,"boot","binm1+df",auto_uido,auto_gidq,0755);
-  c(auto_qmail,"boot","binm2",auto_uido,auto_gidq,0755);
-  c(auto_qmail,"boot","binm2+df",auto_uido,auto_gidq,0755);
-  c(auto_qmail,"boot","binm3",auto_uido,auto_gidq,0755);
-  c(auto_qmail,"boot","binm3+df",auto_uido,auto_gidq,0755);
+  /* rules file for tcpserver */
+  C(auto_qmail,"control","qmail-smtpd.rules","qmail-smtpd.rules",auto_uido,auto_gidq,0644);
+  C(auto_qmail,"control","qmail-qmqpd.rules","qmail-qmqpd.rules",auto_uido,auto_gidq,0644);
+  C(auto_qmail,"control","qmail-pop3d.rules","qmail-pop3d.rules",auto_uido,auto_gidq,0644);
+  C(auto_qmail,"control","qmail-imapd.rules","qmail-imapd.rules",auto_uido,auto_gidq,0644);
+  
+  /* Makefile for cdb creation */
+  C(auto_qmail,"control","Makefile","Makefile.cdb-p",auto_uido,auto_gidq,0644);
+  
+  /* signature file for qmail-smtpd ecexcheck freature */
+  C(auto_qmail,"control","signatures","signatures",auto_uido,auto_gidq,0644);
+
+  /* run files for boot/supervise scripts */
+  C(auto_qmail,"boot/qmail", "run", "qmail.run",auto_uido,auto_gidq,0755);
+  C(auto_qmail,"boot/qmail-smtpd", "run", "qmail-smtpd.run",auto_uido,auto_gidq,0755);
+  C(auto_qmail,"boot/qmail-qmqpd", "run", "qmail-qmqpd.run",auto_uido,auto_gidq,0755);
+  C(auto_qmail,"boot/qmail-pop3d", "run", "qmail-pop3d.run",auto_uido,auto_gidq,0755);
+  C(auto_qmail,"boot/qmail-imapd", "run", "qmail-imapd.run",auto_uido,auto_gidq,0755);
+  C(auto_qmail,"boot/qmail-pop3d-ssl", "run", "qmail-pop3d-ssl.run",auto_uido,auto_gidq,0755);
+  C(auto_qmail,"boot/qmail-imapd-ssl", "run", "qmail-imapd-ssl.run",auto_uido,auto_gidq,0755);
+  C(auto_qmail,"boot/qmail-pbsdbd", "run", "qmail-pbsdbd.run",auto_uido,auto_gidq,0755);
+
+  /* run files for logging process */
+  l(auto_qmail,"boot/qmail/log","log/qmail",auto_userl,auto_uido,auto_gidq,0755);
+  l(auto_qmail,"boot/qmail-smtpd/log","log/qmail-smtpd",auto_userl,auto_uido,auto_gidq,0755);
+  l(auto_qmail,"boot/qmail-qmqpd/log","log/qmail-qmqpd",auto_userl,auto_uido,auto_gidq,0755);
+  l(auto_qmail,"boot/qmail-pop3d/log","log/qmail-pop3d",auto_userl,auto_uido,auto_gidq,0755);
+  l(auto_qmail,"boot/qmail-imapd/log","log/qmail-imapd",auto_userl,auto_uido,auto_gidq,0755);
+  l(auto_qmail,"boot/qmail-pop3d-ssl/log","log/qmail-pop3d-ssl",auto_userl,auto_uido,auto_gidq,0755);
+  l(auto_qmail,"boot/qmail-imapd-ssl/log","log/qmail-imapd-ssl",auto_userl,auto_uido,auto_gidq,0755);
+  l(auto_qmail,"boot/qmail-pbsdbd/log","log/qmail-pbsdbd",auto_userl,auto_uido,auto_gidq,0755);
 
   c(auto_qmail,"doc","FAQ",auto_uido,auto_gidq,0644);
   c(auto_qmail,"doc","UPGRADE",auto_uido,auto_gidq,0644);
@@ -98,6 +175,13 @@
   c(auto_qmail,"doc","PIC.relaybad",auto_uido,auto_gidq,0644);
   c(auto_qmail,"doc","PIC.relaygood",auto_uido,auto_gidq,0644);
   c(auto_qmail,"doc","PIC.rem2local",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"doc","QLDAPGROUP",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"doc","QLDAPINSTALL",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"doc","QLDAPNEWS",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"doc","QLDAPTODO",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"doc","QLDAPPICTURE",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"doc","EXTTODO",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"doc","POPBEFORESMTP",auto_uido,auto_gidq,0644);
 
   c(auto_qmail,"bin","qmail-queue",auto_uidq,auto_gidq,04711);
   c(auto_qmail,"bin","qmail-lspawn",auto_uido,auto_gidq,0700);
@@ -108,6 +192,9 @@
   c(auto_qmail,"bin","qmail-rspawn",auto_uido,auto_gidq,0711);
   c(auto_qmail,"bin","qmail-clean",auto_uido,auto_gidq,0711);
   c(auto_qmail,"bin","qmail-send",auto_uido,auto_gidq,0711);
+#ifdef EXTERNAL_TODO
+  c(auto_qmail,"bin","qmail-todo",auto_uido,auto_gidq,0711);
+#endif
   c(auto_qmail,"bin","splogger",auto_uido,auto_gidq,0711);
   c(auto_qmail,"bin","qmail-newu",auto_uido,auto_gidq,0700);
   c(auto_qmail,"bin","qmail-newmrh",auto_uido,auto_gidq,0700);
@@ -135,6 +222,7 @@
   c(auto_qmail,"bin","forward",auto_uido,auto_gidq,0755);
   c(auto_qmail,"bin","preline",auto_uido,auto_gidq,0755);
   c(auto_qmail,"bin","condredirect",auto_uido,auto_gidq,0755);
+  c(auto_qmail,"bin","condwrite",auto_uido,auto_gidq,0755);
   c(auto_qmail,"bin","bouncesaying",auto_uido,auto_gidq,0755);
   c(auto_qmail,"bin","except",auto_uido,auto_gidq,0755);
   c(auto_qmail,"bin","maildirmake",auto_uido,auto_gidq,0755);
@@ -143,6 +231,21 @@
   c(auto_qmail,"bin","qail",auto_uido,auto_gidq,0755);
   c(auto_qmail,"bin","elq",auto_uido,auto_gidq,0755);
   c(auto_qmail,"bin","pinq",auto_uido,auto_gidq,0755);
+  c(auto_qmail,"bin","qmail-reply",auto_uido,auto_gidq,0755);
+  c(auto_qmail,"bin","qmail-quotawarn",auto_uido,auto_gidq,0755);
+  c(auto_qmail,"bin","auth_pop",auto_uido,auto_gidq,0700);
+  c(auto_qmail,"bin","auth_imap",auto_uido,auto_gidq,0700);
+  c(auto_qmail,"bin","auth_smtp",auto_uido,auto_gidq,0755);
+  c(auto_qmail,"bin","qmail-verify",auto_uido,auto_gidq,0755);
+  c(auto_qmail,"bin","qmail-ldaplookup",auto_uido,0,0750);
+  c(auto_qmail,"bin","qmail-cdb",auto_uido,auto_gidq,0700);
+  c(auto_qmail,"bin","digest",auto_uido,auto_gidq,0755);
+  c(auto_qmail,"bin","pbsadd",auto_uido,auto_gidq,0755);
+  c(auto_qmail,"bin","pbscheck",auto_uido,auto_gidq,0755);
+  c(auto_qmail,"bin","pbsdbd",auto_uido,auto_gidq,0755);
+  c(auto_qmail,"bin","qmail-forward",auto_uido,auto_gidq,0755);
+  c(auto_qmail,"bin","qmail-secretary",auto_uido,auto_gidq,0755);
+  c(auto_qmail,"bin","qmail-group",auto_uido,auto_gidq,0755);
 
   c(auto_qmail,"man/man5","addresses.5",auto_uido,auto_gidq,0644);
   c(auto_qmail,"man/cat5","addresses.0",auto_uido,auto_gidq,0644);
diff -ruN qmail-1.03-orig/hostname.c qmail-1.03-ldap-20060201-orig/hostname.c
--- qmail-1.03-orig/hostname.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/hostname.c	2006-02-25 11:00:55.000000000 +0100
@@ -1,3 +1,4 @@
+#include <unistd.h>
 #include "substdio.h"
 #include "subfd.h"
 #include "readwrite.h"
@@ -5,7 +6,7 @@
 
 char host[256];
 
-void main()
+int main()
 {
  host[0] = 0; /* sigh */
  gethostname(host,sizeof(host));
@@ -13,5 +14,5 @@
  substdio_puts(subfdoutsmall,host);
  substdio_puts(subfdoutsmall,"\n");
  substdio_flush(subfdoutsmall);
- _exit(0);
+ return 0;
 }
diff -ruN qmail-1.03-orig/idedit.c qmail-1.03-ldap-20060201-orig/idedit.c
--- qmail-1.03-orig/idedit.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/idedit.c	2006-02-25 11:00:55.000000000 +0100
@@ -1,6 +1,7 @@
 #include <sys/types.h>
 #include <pwd.h>
 #include <grp.h>
+#include <unistd.h>
 #include "readwrite.h"
 #include "exit.h"
 #include "scan.h"
@@ -9,6 +10,7 @@
 #include "open.h"
 #include "seek.h"
 #include "fork.h"
+#include "wait.h"
 
 #define FATAL "idedit: fatal: "
 #define WARNING "idedit: warning: "
@@ -67,7 +69,7 @@
   pw = getpwnam(account);
 
   if (!pw && group) {
-    args[0] = "add-account";
+    args[0] = (char *)"add-account";
     args[1] = account;
     args[2] = group;
     args[3] = home;
@@ -101,7 +103,7 @@
   gr = getgrnam(group);
 
   if (!gr) {
-    args[0] = "add-group";
+    args[0] = (char *)"add-group";
     args[1] = group;
     args[2] = 0;
     run();
@@ -120,7 +122,7 @@
     strerr_die3x(111,FATAL,"excessively large gid for ",group);
 }
 
-void main(argc,argv)
+int main(argc,argv)
 int argc;
 char **argv;
 {
@@ -143,5 +145,5 @@
   u("qmailr","qmail","/var/qmail",argv[26],argv[27],argv[28],argv[29]);
   u("qmails","qmail","/var/qmail",argv[30],argv[31],argv[32],argv[33]);
 
-  _exit(0);
+  return 0;
 }
diff -ruN qmail-1.03-orig/install-big.c qmail-1.03-ldap-20060201-orig/install-big.c
--- qmail-1.03-orig/install-big.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/install-big.c	2006-02-25 11:00:55.000000000 +0100
@@ -1,11 +1,22 @@
 #include "auto_qmail.h"
 #include "auto_split.h"
 #include "auto_uids.h"
+#include "auto_userl.h"
 #include "fmt.h"
 #include "fifo.h"
 
 char buf[100 + FMT_ULONG];
 
+extern void c(const char *, const char *, const char *, int, int, int);
+extern void C(const char *, const char *, const char *, const char *,
+ int, int, int);
+extern void d(const char *, const char *, int, int, int);
+extern void h(const char *, int, int, int);
+extern void l(const char *, const char *, const char *, const char *,
+ int, int, int);
+extern void p(const char *, const char *, int, int, int);
+extern void z(const char *, const char *, int, int, int, int);
+
 void dsplit(base,uid,mode)
 char *base; /* must be under 100 bytes */
 int uid;
@@ -35,6 +46,45 @@
   d(auto_qmail,"users",auto_uido,auto_gidq,0755);
   d(auto_qmail,"bin",auto_uido,auto_gidq,0755);
   d(auto_qmail,"boot",auto_uido,auto_gidq,0755);
+
+  /* boot restructured for daemontools */
+  d(auto_qmail,"boot",auto_uido,auto_gidq,0755);
+  d(auto_qmail,"boot/qmail",auto_uido,auto_gidq,0755);
+  d(auto_qmail,"boot/qmail/env",auto_uido,auto_gidq,0755);
+  d(auto_qmail,"boot/qmail/log",auto_uido,auto_gidq,0755);
+  d(auto_qmail,"boot/qmail-smtpd",auto_uido,auto_gidq,0755);
+  d(auto_qmail,"boot/qmail-smtpd/env",auto_uido,auto_gidq,0755);
+  d(auto_qmail,"boot/qmail-smtpd/log",auto_uido,auto_gidq,0755);
+  d(auto_qmail,"boot/qmail-qmqpd",auto_uido,auto_gidq,0755);
+  d(auto_qmail,"boot/qmail-qmqpd/env",auto_uido,auto_gidq,0755);
+  d(auto_qmail,"boot/qmail-qmqpd/log",auto_uido,auto_gidq,0755);
+  d(auto_qmail,"boot/qmail-pop3d",auto_uido,auto_gidq,0755);
+  d(auto_qmail,"boot/qmail-pop3d/env",auto_uido,auto_gidq,0755);
+  d(auto_qmail,"boot/qmail-pop3d/log",auto_uido,auto_gidq,0755);
+  d(auto_qmail,"boot/qmail-imapd",auto_uido,auto_gidq,0755);
+  d(auto_qmail,"boot/qmail-imapd/env",auto_uido,auto_gidq,0755);
+  d(auto_qmail,"boot/qmail-imapd/log",auto_uido,auto_gidq,0755);
+  d(auto_qmail,"boot/qmail-pop3d-ssl",auto_uido,auto_gidq,0755);
+  d(auto_qmail,"boot/qmail-pop3d-ssl/env",auto_uido,auto_gidq,0755);
+  d(auto_qmail,"boot/qmail-pop3d-ssl/log",auto_uido,auto_gidq,0755);
+  d(auto_qmail,"boot/qmail-imapd-ssl",auto_uido,auto_gidq,0755);
+  d(auto_qmail,"boot/qmail-imapd-ssl/env",auto_uido,auto_gidq,0755);
+  d(auto_qmail,"boot/qmail-imapd-ssl/log",auto_uido,auto_gidq,0755);
+  d(auto_qmail,"boot/qmail-pbsdbd",auto_uido,auto_gidq,0755);
+  d(auto_qmail,"boot/qmail-pbsdbd/env",auto_uido,auto_gidq,0755);
+  d(auto_qmail,"boot/qmail-pbsdbd/log",auto_uido,auto_gidq,0755);
+
+  /* logging restructured for daemontools */
+  d(auto_qmail,"log",auto_uidl,auto_gidq,0755);
+  d(auto_qmail,"log/qmail",auto_uidl,auto_gidq,0755);
+  d(auto_qmail,"log/qmail-smtpd",auto_uidl,auto_gidq,0755);
+  d(auto_qmail,"log/qmail-qmqpd",auto_uidl,auto_gidq,0755);
+  d(auto_qmail,"log/qmail-pop3d",auto_uidl,auto_gidq,0755);
+  d(auto_qmail,"log/qmail-imapd",auto_uidl,auto_gidq,0755);
+  d(auto_qmail,"log/qmail-pop3d-ssl",auto_uidl,auto_gidq,0755);
+  d(auto_qmail,"log/qmail-imapd-ssl",auto_uidl,auto_gidq,0755);
+  d(auto_qmail,"log/qmail-pbsdbd",auto_uidl,auto_gidq,0755);
+
   d(auto_qmail,"doc",auto_uido,auto_gidq,0755);
   d(auto_qmail,"man",auto_uido,auto_gidq,0755);
   d(auto_qmail,"man/cat1",auto_uido,auto_gidq,0755);
@@ -50,30 +100,57 @@
 
   d(auto_qmail,"queue",auto_uidq,auto_gidq,0750);
   d(auto_qmail,"queue/pid",auto_uidq,auto_gidq,0700);
+#ifndef BIGTODO
   d(auto_qmail,"queue/intd",auto_uidq,auto_gidq,0700);
   d(auto_qmail,"queue/todo",auto_uidq,auto_gidq,0750);
+#endif
   d(auto_qmail,"queue/bounce",auto_uids,auto_gidq,0700);
 
   dsplit("queue/mess",auto_uidq,0750);
   dsplit("queue/info",auto_uids,0700);
   dsplit("queue/local",auto_uids,0700);
   dsplit("queue/remote",auto_uids,0700);
+#ifdef BIGTODO
+  dsplit("queue/intd",auto_uidq,0700);
+  dsplit("queue/todo",auto_uidq,0750);
+#endif
 
   d(auto_qmail,"queue/lock",auto_uidq,auto_gidq,0750);
   z(auto_qmail,"queue/lock/tcpto",1024,auto_uidr,auto_gidq,0644);
   z(auto_qmail,"queue/lock/sendmutex",0,auto_uids,auto_gidq,0600);
   p(auto_qmail,"queue/lock/trigger",auto_uids,auto_gidq,0622);
 
-  c(auto_qmail,"boot","home",auto_uido,auto_gidq,0755);
-  c(auto_qmail,"boot","home+df",auto_uido,auto_gidq,0755);
-  c(auto_qmail,"boot","proc",auto_uido,auto_gidq,0755);
-  c(auto_qmail,"boot","proc+df",auto_uido,auto_gidq,0755);
-  c(auto_qmail,"boot","binm1",auto_uido,auto_gidq,0755);
-  c(auto_qmail,"boot","binm1+df",auto_uido,auto_gidq,0755);
-  c(auto_qmail,"boot","binm2",auto_uido,auto_gidq,0755);
-  c(auto_qmail,"boot","binm2+df",auto_uido,auto_gidq,0755);
-  c(auto_qmail,"boot","binm3",auto_uido,auto_gidq,0755);
-  c(auto_qmail,"boot","binm3+df",auto_uido,auto_gidq,0755);
+  /* rules file for tcpserver */
+  C(auto_qmail,"control","qmail-smtpd.rules","qmail-smtpd.rules",auto_uido,auto_gidq,0644);
+  C(auto_qmail,"control","qmail-qmqpd.rules","qmail-qmqpd.rules",auto_uido,auto_gidq,0644);
+  C(auto_qmail,"control","qmail-pop3d.rules","qmail-pop3d.rules",auto_uido,auto_gidq,0644);
+  C(auto_qmail,"control","qmail-imapd.rules","qmail-imapd.rules",auto_uido,auto_gidq,0644);
+  
+  /* Makefile for cdb creation */
+  C(auto_qmail,"control","Makefile","Makefile.cdb-p",auto_uido,auto_gidq,0644);
+  
+  /* signature file for qmail-smtpd ecexcheck freature */
+  C(auto_qmail,"control","signatures","signatures",auto_uido,auto_gidq,0644);
+
+  /* run files for boot/supervise scripts */
+  C(auto_qmail,"boot/qmail", "run", "qmail.run",auto_uido,auto_gidq,0755);
+  C(auto_qmail,"boot/qmail-smtpd", "run", "qmail-smtpd.run",auto_uido,auto_gidq,0755);
+  C(auto_qmail,"boot/qmail-qmqpd", "run", "qmail-qmqpd.run",auto_uido,auto_gidq,0755);
+  C(auto_qmail,"boot/qmail-pop3d", "run", "qmail-pop3d.run",auto_uido,auto_gidq,0755);
+  C(auto_qmail,"boot/qmail-imapd", "run", "qmail-imapd.run",auto_uido,auto_gidq,0755);
+  C(auto_qmail,"boot/qmail-pop3d-ssl", "run", "qmail-pop3d-ssl.run",auto_uido,auto_gidq,0755);
+  C(auto_qmail,"boot/qmail-imapd-ssl", "run", "qmail-imapd-ssl.run",auto_uido,auto_gidq,0755);
+  C(auto_qmail,"boot/qmail-pbsdbd", "run", "qmail-pbsdbd.run",auto_uido,auto_gidq,0755);
+
+  /* run files for logging process */
+  l(auto_qmail,"boot/qmail/log","log/qmail",auto_userl,auto_uido,auto_gidq,0755);
+  l(auto_qmail,"boot/qmail-smtpd/log","log/qmail-smtpd",auto_userl,auto_uido,auto_gidq,0755);
+  l(auto_qmail,"boot/qmail-qmqpd/log","log/qmail-qmqpd",auto_userl,auto_uido,auto_gidq,0755);
+  l(auto_qmail,"boot/qmail-pop3d/log","log/qmail-pop3d",auto_userl,auto_uido,auto_gidq,0755);
+  l(auto_qmail,"boot/qmail-imapd-ssl/log","log/qmail-imapd-ssl",auto_userl,auto_uido,auto_gidq,0755);
+  l(auto_qmail,"boot/qmail-pop3d-ssl/log","log/qmail-pop3d-ssl",auto_userl,auto_uido,auto_gidq,0755);
+  l(auto_qmail,"boot/qmail-imapd/log","log/qmail-imapd",auto_userl,auto_uido,auto_gidq,0755);
+  l(auto_qmail,"boot/qmail-pbsdbd/log","log/qmail-pbsdbd",auto_userl,auto_uido,auto_gidq,0755);
 
   c(auto_qmail,"doc","FAQ",auto_uido,auto_gidq,0644);
   c(auto_qmail,"doc","UPGRADE",auto_uido,auto_gidq,0644);
@@ -98,6 +175,13 @@
   c(auto_qmail,"doc","PIC.relaybad",auto_uido,auto_gidq,0644);
   c(auto_qmail,"doc","PIC.relaygood",auto_uido,auto_gidq,0644);
   c(auto_qmail,"doc","PIC.rem2local",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"doc","QLDAPGROUP",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"doc","QLDAPINSTALL",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"doc","QLDAPNEWS",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"doc","QLDAPTODO",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"doc","QLDAPPICTURE",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"doc","EXTTODO",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"doc","POPBEFORESMTP",auto_uido,auto_gidq,0644);
 
   c(auto_qmail,"bin","qmail-queue",auto_uidq,auto_gidq,04711);
   c(auto_qmail,"bin","qmail-lspawn",auto_uido,auto_gidq,0700);
@@ -108,6 +192,9 @@
   c(auto_qmail,"bin","qmail-rspawn",auto_uido,auto_gidq,0711);
   c(auto_qmail,"bin","qmail-clean",auto_uido,auto_gidq,0711);
   c(auto_qmail,"bin","qmail-send",auto_uido,auto_gidq,0711);
+#ifdef EXTERNAL_TODO
+  c(auto_qmail,"bin","qmail-todo",auto_uido,auto_gidq,0711);
+#endif
   c(auto_qmail,"bin","splogger",auto_uido,auto_gidq,0711);
   c(auto_qmail,"bin","qmail-newu",auto_uido,auto_gidq,0700);
   c(auto_qmail,"bin","qmail-newmrh",auto_uido,auto_gidq,0700);
@@ -135,6 +222,7 @@
   c(auto_qmail,"bin","forward",auto_uido,auto_gidq,0755);
   c(auto_qmail,"bin","preline",auto_uido,auto_gidq,0755);
   c(auto_qmail,"bin","condredirect",auto_uido,auto_gidq,0755);
+  c(auto_qmail,"bin","condwrite",auto_uido,auto_gidq,0755);
   c(auto_qmail,"bin","bouncesaying",auto_uido,auto_gidq,0755);
   c(auto_qmail,"bin","except",auto_uido,auto_gidq,0755);
   c(auto_qmail,"bin","maildirmake",auto_uido,auto_gidq,0755);
@@ -143,7 +231,22 @@
   c(auto_qmail,"bin","qail",auto_uido,auto_gidq,0755);
   c(auto_qmail,"bin","elq",auto_uido,auto_gidq,0755);
   c(auto_qmail,"bin","pinq",auto_uido,auto_gidq,0755);
-
+  c(auto_qmail,"bin","qmail-reply",auto_uido,auto_gidq,0755);
+  c(auto_qmail,"bin","qmail-quotawarn",auto_uido,auto_gidq,0755);
+  c(auto_qmail,"bin","auth_pop",auto_uido,auto_gidq,0700);
+  c(auto_qmail,"bin","auth_imap",auto_uido,auto_gidq,0700);
+  c(auto_qmail,"bin","auth_smtp",auto_uido,auto_gidq,0755);
+  c(auto_qmail,"bin","qmail-verify",auto_uido,auto_gidq,0755);
+  c(auto_qmail,"bin","qmail-ldaplookup",auto_uido,0,0750);
+  c(auto_qmail,"bin","qmail-cdb",auto_uido,auto_gidq,0700);
+  c(auto_qmail,"bin","digest",auto_uido,auto_gidq,0755);
+  c(auto_qmail,"bin","pbsadd",auto_uido,auto_gidq,0755);
+  c(auto_qmail,"bin","pbscheck",auto_uido,auto_gidq,0755);
+  c(auto_qmail,"bin","pbsdbd",auto_uido,auto_gidq,0755);
+  c(auto_qmail,"bin","qmail-forward",auto_uido,auto_gidq,0755);
+  c(auto_qmail,"bin","qmail-secretary",auto_uido,auto_gidq,0755);
+  c(auto_qmail,"bin","qmail-group",auto_uido,auto_gidq,0755);
+  
   c(auto_qmail,"man/man5","addresses.5",auto_uido,auto_gidq,0644);
   c(auto_qmail,"man/cat5","addresses.0",auto_uido,auto_gidq,0644);
   c(auto_qmail,"man/man5","envelopes.5",auto_uido,auto_gidq,0644);
diff -ruN qmail-1.03-orig/install.c qmail-1.03-ldap-20060201-orig/install.c
--- qmail-1.03-orig/install.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/install.c	2006-02-25 11:00:55.000000000 +0100
@@ -1,9 +1,13 @@
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
 #include "substdio.h"
 #include "strerr.h"
 #include "error.h"
 #include "open.h"
 #include "readwrite.h"
 #include "exit.h"
+#include "fifo.h"
 
 extern void hier();
 
@@ -12,7 +16,7 @@
 int fdsourcedir = -1;
 
 void h(home,uid,gid,mode)
-char *home;
+const char *home;
 int uid;
 int gid;
 int mode;
@@ -27,8 +31,8 @@
 }
 
 void d(home,subdir,uid,gid,mode)
-char *home;
-char *subdir;
+const char *home;
+const char *subdir;
 int uid;
 int gid;
 int mode;
@@ -45,8 +49,8 @@
 }
 
 void p(home,fifo,uid,gid,mode)
-char *home;
-char *fifo;
+const char *home;
+const char *fifo;
 int uid;
 int gid;
 int mode;
@@ -68,9 +72,9 @@
 substdio ssout;
 
 void c(home,subdir,file,uid,gid,mode)
-char *home;
-char *subdir;
-char *file;
+const char *home;
+const char *subdir;
+const char *file;
 int uid;
 int gid;
 int mode;
@@ -84,7 +88,7 @@
   fdin = open_read(file);
   if (fdin == -1)
     strerr_die4sys(111,FATAL,"unable to read ",file,": ");
-  substdio_fdbuf(&ssin,read,fdin,inbuf,sizeof inbuf);
+  substdio_fdbuf(&ssin,subread,fdin,inbuf,sizeof inbuf);
 
   if (chdir(home) == -1)
     strerr_die4sys(111,FATAL,"unable to switch to ",home,": ");
@@ -94,7 +98,7 @@
   fdout = open_trunc(file);
   if (fdout == -1)
     strerr_die6sys(111,FATAL,"unable to write .../",subdir,"/",file,": ");
-  substdio_fdbuf(&ssout,write,fdout,outbuf,sizeof outbuf);
+  substdio_fdbuf(&ssout,subwrite,fdout,outbuf,sizeof outbuf);
 
   switch(substdio_copy(&ssout,&ssin)) {
     case -2:
@@ -117,9 +121,123 @@
     strerr_die6sys(111,FATAL,"unable to chmod .../",subdir,"/",file,": ");
 }
 
+void C(home,subdir,file,source,uid,gid,mode)
+const char *home;
+const char *subdir;
+const char *file;
+const char *source;
+int uid;
+int gid;
+int mode;
+{
+  struct stat st;
+  int fdin;
+  int fdout;
+
+  if (fchdir(fdsourcedir) == -1)
+    strerr_die2sys(111,FATAL,"unable to switch back to source directory: ");
+
+  fdin = open_read(source);
+  if (fdin == -1)
+    strerr_die4sys(111,FATAL,"unable to read ",source,": ");
+  substdio_fdbuf(&ssin,subread,fdin,inbuf,sizeof inbuf);
+
+  if (chdir(home) == -1)
+    strerr_die4sys(111,FATAL,"unable to switch to ",home,": ");
+  if (chdir(subdir) == -1)
+    strerr_die6sys(111,FATAL,"unable to switch to ",home,"/",subdir,": ");
+
+  /* if file seems to exist don't overwrite */
+  if (stat(file, &st) == 0) {
+    close(fdin);
+    return;
+  }
+  
+  fdout = open_trunc(file);
+  if (fdout == -1)
+    strerr_die6sys(111,FATAL,"unable to write .../",subdir,"/",file,": ");
+  substdio_fdbuf(&ssout,subwrite,fdout,outbuf,sizeof outbuf);
+
+  switch(substdio_copy(&ssout,&ssin)) {
+    case -2:
+      strerr_die4sys(111,FATAL,"unable to read ",source,": ");
+    case -3:
+      strerr_die6sys(111,FATAL,"unable to write .../",subdir,"/",file,": ");
+  }
+
+  close(fdin);
+  if (substdio_flush(&ssout) == -1)
+    strerr_die6sys(111,FATAL,"unable to write .../",subdir,"/",file,": ");
+  if (fsync(fdout) == -1)
+    strerr_die6sys(111,FATAL,"unable to write .../",subdir,"/",file,": ");
+  if (close(fdout) == -1) /* NFS silliness */
+    strerr_die6sys(111,FATAL,"unable to write .../",subdir,"/",file,": ");
+
+  if (chown(file,uid,gid) == -1)
+    strerr_die6sys(111,FATAL,"unable to chown .../",subdir,"/",file,": ");
+  if (chmod(file,mode) == -1)
+    strerr_die6sys(111,FATAL,"unable to chmod .../",subdir,"/",file,": ");
+}
+
+void l(home,subdir,logdir,loguser,uid,gid,mode)
+const char *home;
+const char *subdir;
+const char *logdir;
+const char *loguser;
+int uid;
+int gid;
+int mode;
+{
+  int fdout;
+  struct stat st;
+
+  if (chdir(home) == -1)
+    strerr_die4sys(111,FATAL,"unable to switch to ",home,": ");
+  if (chdir(subdir) == -1)
+    strerr_die6sys(111,FATAL,"unable to switch to ",home,"/",subdir,": ");
+
+  /* if file seems to exist don't overwrite */
+  if (stat("run", &st) == 0) return;
+  
+  fdout = open_trunc("run");
+  if (fdout == -1)
+    strerr_die4sys(111,FATAL,"unable to write .../",subdir,"/run: ");
+  substdio_fdbuf(&ssout,subwrite,fdout,outbuf,sizeof outbuf);
+
+  /* write log script */
+  if (substdio_puts(&ssout,
+        "#!/bin/sh\n\nexec setuidgid ") == -1)
+    strerr_die4sys(111,FATAL,"unable to write .../",subdir,"/run: ");
+  if (substdio_puts(&ssout, loguser) == -1)
+    strerr_die4sys(111,FATAL,"unable to write .../",subdir,"/run: ");
+  if (substdio_puts(&ssout, " multilog t ") == -1)
+    strerr_die4sys(111,FATAL,"unable to write .../",subdir,"/run: ");
+  if (substdio_puts(&ssout, home) == -1)
+    strerr_die4sys(111,FATAL,"unable to write .../",subdir,"/run: ");
+  if (substdio_puts(&ssout, "/") == -1)
+    strerr_die4sys(111,FATAL,"unable to write .../",subdir,"/run: ");
+  if (substdio_puts(&ssout, logdir) == -1)
+    strerr_die4sys(111,FATAL,"unable to write .../",subdir,"/run: ");
+  if (substdio_puts(&ssout, "\n\n") == -1)
+    strerr_die4sys(111,FATAL,"unable to write .../",subdir,"/run: ");
+
+  if (substdio_flush(&ssout) == -1)
+    strerr_die4sys(111,FATAL,"unable to write .../",subdir,"/run: ");
+  if (fsync(fdout) == -1)
+    strerr_die4sys(111,FATAL,"unable to write .../",subdir,"/run: ");
+  if (close(fdout) == -1) /* NFS silliness */
+    strerr_die4sys(111,FATAL,"unable to write .../",subdir,"/run: ");
+
+  if (chown("run",uid,gid) == -1)
+    strerr_die4sys(111,FATAL,"unable to chown .../",subdir,"/run: ");
+  if (chmod("run",mode) == -1)
+    strerr_die4sys(111,FATAL,"unable to chmod .../",subdir,"/run: ");
+}
+
+
 void z(home,file,len,uid,gid,mode)
-char *home;
-char *file;
+const char *home;
+const char *file;
 int len;
 int uid;
 int gid;
@@ -133,7 +251,7 @@
   fdout = open_trunc(file);
   if (fdout == -1)
     strerr_die6sys(111,FATAL,"unable to write ",home,"/",file,": ");
-  substdio_fdbuf(&ssout,write,fdout,outbuf,sizeof outbuf);
+  substdio_fdbuf(&ssout,subwrite,fdout,outbuf,sizeof outbuf);
 
   while (len-- > 0)
     if (substdio_put(&ssout,"",1) == -1)
@@ -152,7 +270,7 @@
     strerr_die6sys(111,FATAL,"unable to chmod ",home,"/",file,": ");
 }
 
-void main()
+int main()
 {
   fdsourcedir = open_read(".");
   if (fdsourcedir == -1)
@@ -160,5 +278,5 @@
 
   umask(077);
   hier();
-  _exit(0);
+  return 0;
 }
diff -ruN qmail-1.03-orig/instcheck.c qmail-1.03-ldap-20060201-orig/instcheck.c
--- qmail-1.03-orig/instcheck.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/instcheck.c	2006-02-25 11:00:55.000000000 +0100
@@ -1,5 +1,6 @@
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <unistd.h>
 #include "strerr.h"
 #include "error.h"
 #include "readwrite.h"
@@ -11,14 +12,14 @@
 #define WARNING "instcheck: warning: "
 
 void perm(prefix1,prefix2,prefix3,file,type,uid,gid,mode)
-char *prefix1;
-char *prefix2;
-char *prefix3;
-char *file;
-int type;
+const char *prefix1;
+const char *prefix2;
+const char *prefix3;
+const char *file;
+unsigned int type;
 int uid;
 int gid;
-int mode;
+unsigned int mode;
 {
   struct stat st;
 
@@ -30,9 +31,9 @@
     return;
   }
 
-  if ((uid != -1) && (st.st_uid != uid))
+  if ((uid != -1) && (st.st_uid != (unsigned int)uid))
     strerr_warn6(WARNING,prefix1,prefix2,prefix3,file," has wrong owner",0);
-  if ((gid != -1) && (st.st_gid != gid))
+  if ((gid != -1) && (st.st_gid != (unsigned int)gid))
     strerr_warn6(WARNING,prefix1,prefix2,prefix3,file," has wrong group",0);
   if ((st.st_mode & 07777) != mode)
     strerr_warn6(WARNING,prefix1,prefix2,prefix3,file," has wrong permissions",0);
@@ -41,7 +42,7 @@
 }
 
 void h(home,uid,gid,mode)
-char *home;
+const char *home;
 int uid;
 int gid;
 int mode;
@@ -50,8 +51,8 @@
 }
 
 void d(home,subdir,uid,gid,mode)
-char *home;
-char *subdir;
+const char *home;
+const char *subdir;
 int uid;
 int gid;
 int mode;
@@ -62,8 +63,8 @@
 }
 
 void p(home,fifo,uid,gid,mode)
-char *home;
-char *fifo;
+const char *home;
+const char *fifo;
 int uid;
 int gid;
 int mode;
@@ -74,9 +75,25 @@
 }
 
 void c(home,subdir,file,uid,gid,mode)
-char *home;
-char *subdir;
-char *file;
+const char *home;
+const char *subdir;
+const char *file;
+int uid;
+int gid;
+int mode;
+{
+  if (chdir(home) == -1)
+    strerr_die4sys(111,FATAL,"unable to switch to ",home,": ");
+  if (chdir(subdir) == -1)
+    strerr_die6sys(111,FATAL,"unable to switch to ",home,"/",subdir,": ");
+  perm(".../",subdir,"/",file,S_IFREG,uid,gid,mode);
+}
+
+void C(home,subdir,file,source,uid,gid,mode)
+const char *home;
+const char *subdir;
+const char *file;
+const char *source;
 int uid;
 int gid;
 int mode;
@@ -89,8 +106,8 @@
 }
 
 void z(home,file,len,uid,gid,mode)
-char *home;
-char *file;
+const char *home;
+const char *file;
 int len;
 int uid;
 int gid;
@@ -101,8 +118,24 @@
   perm("",home,"/",file,S_IFREG,uid,gid,mode);
 }
 
-void main()
+void l(home,subdir,logdir,loguser,uid,gid,mode)
+const char *home;
+const char *subdir;
+const char *logdir;
+const char *loguser;
+int uid;
+int gid;
+int mode;
+{
+  if (chdir(home) == -1)
+    strerr_die4sys(111,FATAL,"unable to switch to ",home,": ");
+  if (chdir(subdir) == -1)
+    strerr_die6sys(111,FATAL,"unable to switch to ",home,"/",subdir,": ");
+  perm(".../",subdir,"/","run",S_IFREG,uid,gid,mode);
+}
+
+int main()
 {
   hier();
-  _exit(0);
+  return 0;
 }
diff -ruN qmail-1.03-orig/ipalloc.h qmail-1.03-ldap-20060201-orig/ipalloc.h
--- qmail-1.03-orig/ipalloc.h	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/ipalloc.h	2006-02-25 11:00:55.000000000 +0100
@@ -8,7 +8,7 @@
 #include "gen_alloc.h"
 
 GEN_ALLOC_typedef(ipalloc,struct ip_mx,ix,len,a)
-extern int ipalloc_readyplus();
-extern int ipalloc_append();
+extern int ipalloc_readyplus(ipalloc *, unsigned int);
+extern int ipalloc_append(ipalloc *, struct ip_mx *);
 
 #endif
diff -ruN qmail-1.03-orig/ip.c qmail-1.03-ldap-20060201-orig/ip.c
--- qmail-1.03-orig/ip.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/ip.c	2006-02-25 11:00:55.000000000 +0100
@@ -21,26 +21,42 @@
 }
 
 unsigned int ip_scan(s,ip)
-char *s;
+const char *s;
 struct ip_address *ip;
 {
   unsigned int i;
   unsigned int len;
   unsigned long u;
- 
+
+  /*
+   * Don't play games. everything over 255 is invalid and we need a full
+   * IP address. No magic expands like 127.1 or similar bullshit.
+   */
   len = 0;
-  i = scan_ulong(s,&u); if (!i) return 0; ip->d[0] = u; s += i; len += i;
+  i = scan_ulong(s,&u);
+  if (!i || u > 255) return 0;
+  ip->d[0] = u; s += i; len += i;
+
   if (*s != '.') return 0; ++s; ++len;
-  i = scan_ulong(s,&u); if (!i) return 0; ip->d[1] = u; s += i; len += i;
+  i = scan_ulong(s,&u);
+  if (!i || u > 255) return 0;
+  ip->d[1] = u; s += i; len += i;
+
   if (*s != '.') return 0; ++s; ++len;
-  i = scan_ulong(s,&u); if (!i) return 0; ip->d[2] = u; s += i; len += i;
+  i = scan_ulong(s,&u);
+  if (!i || u > 255) return 0;
+  ip->d[2] = u; s += i; len += i;
+
   if (*s != '.') return 0; ++s; ++len;
-  i = scan_ulong(s,&u); if (!i) return 0; ip->d[3] = u; s += i; len += i;
+  i = scan_ulong(s,&u);
+  if (!i || u > 255) return 0;
+  ip->d[3] = u; s += i; len += i;
+
   return len;
 }
 
 unsigned int ip_scanbracket(s,ip)
-char *s;
+const char *s;
 struct ip_address *ip;
 {
   unsigned int len;
diff -ruN qmail-1.03-orig/ip.h qmail-1.03-ldap-20060201-orig/ip.h
--- qmail-1.03-orig/ip.h	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/ip.h	2006-02-25 11:00:55.000000000 +0100
@@ -3,9 +3,9 @@
 
 struct ip_address { unsigned char d[4]; } ;
 
-extern unsigned int ip_fmt();
+extern unsigned int ip_fmt(char *, struct ip_address *);
 #define IPFMT 19
-extern unsigned int ip_scan();
-extern unsigned int ip_scanbracket();
+extern unsigned int ip_scan(const char *, struct ip_address *);
+extern unsigned int ip_scanbracket(const char *, struct ip_address *);
 
 #endif
diff -ruN qmail-1.03-orig/ipme.c qmail-1.03-ldap-20060201-orig/ipme.c
--- qmail-1.03-orig/ipme.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/ipme.c	2006-02-25 11:00:55.000000000 +0100
@@ -8,6 +8,7 @@
 #ifndef SIOCGIFCONF /* whatever works */
 #include <sys/sockio.h>
 #endif
+#include <unistd.h>
 #include "hassalen.h"
 #include "byte.h"
 #include "ip.h"
@@ -21,7 +22,7 @@
 int ipme_is(ip)
 struct ip_address *ip;
 {
-  int i;
+  unsigned int i;
   if (ipme_init() != 1) return -1;
   for (i = 0;i < ipme.len;++i)
     if (byte_equal(&ipme.ix[i].ip,4,ip))
@@ -36,8 +37,8 @@
   struct ifconf ifc;
   char *x;
   struct ifreq *ifr;
-  struct sockaddr_in *sin;
-  int len;
+  struct sockaddr_in *s_in;
+  unsigned int len;
   int s;
   struct ip_mx ix;
  
@@ -45,6 +46,12 @@
   if (!ipalloc_readyplus(&ipme,0)) return 0;
   ipme.len = 0;
   ix.pref = 0;
+
+  /* 0.0.0.0 is a special address which always refers to 
+   * "this host, this network", according to RFC 1122, Sec. 3.2.1.3a.
+   */
+  byte_copy(&ix.ip,4,"\0\0\0\0");
+  if (!ipalloc_append(&ipme,&ix)) { return 0; }
  
   if ((s = socket(AF_INET,SOCK_STREAM,0)) == -1) return -1;
  
@@ -70,8 +77,8 @@
     if (len < sizeof(*ifr))
       len = sizeof(*ifr);
     if (ifr->ifr_addr.sa_family == AF_INET) {
-      sin = (struct sockaddr_in *) &ifr->ifr_addr;
-      byte_copy(&ix.ip,4,&sin->sin_addr);
+      s_in = (struct sockaddr_in *) &ifr->ifr_addr;
+      byte_copy(&ix.ip,4,&s_in->sin_addr);
       if (ioctl(s,SIOCGIFFLAGS,x) == 0)
         if (ifr->ifr_flags & IFF_UP)
           if (!ipalloc_append(&ipme,&ix)) { close(s); return 0; }
@@ -82,8 +89,8 @@
       if (ifr->ifr_flags & IFF_UP)
         if (ioctl(s,SIOCGIFADDR,x) == 0)
 	  if (ifr->ifr_addr.sa_family == AF_INET) {
-	    sin = (struct sockaddr_in *) &ifr->ifr_addr;
-	    byte_copy(&ix.ip,4,&sin->sin_addr);
+	    s_in = (struct sockaddr_in *) &ifr->ifr_addr;
+	    byte_copy(&ix.ip,4,&s_in->sin_addr);
 	    if (!ipalloc_append(&ipme,&ix)) { close(s); return 0; }
 	  }
 #endif
diff -ruN qmail-1.03-orig/ipme.h qmail-1.03-ldap-20060201-orig/ipme.h
--- qmail-1.03-orig/ipme.h	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/ipme.h	2006-02-25 11:00:55.000000000 +0100
@@ -6,7 +6,7 @@
 
 extern ipalloc ipme;
 
-extern int ipme_init();
-extern int ipme_is();
+extern int ipme_init(void);
+extern int ipme_is(struct ip_address *);
 
 #endif
diff -ruN qmail-1.03-orig/ipmeprint.c qmail-1.03-ldap-20060201-orig/ipmeprint.c
--- qmail-1.03-orig/ipmeprint.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/ipmeprint.c	2006-02-25 11:00:55.000000000 +0100
@@ -6,9 +6,9 @@
 
 char temp[IPFMT];
 
-void main()
+int main(int argc, char **argv)
 {
- int j;
+ unsigned int j;
  switch(ipme_init())
   {
    case 0: substdio_putsflush(subfderr,"out of memory\n"); _exit(111);
@@ -20,5 +20,5 @@
    substdio_puts(subfdout,"\n");
   }
  substdio_flush(subfdout);
- _exit(0);
+ return 0;
 }
diff -ruN qmail-1.03-orig/LICENSE qmail-1.03-ldap-20060201-orig/LICENSE
--- qmail-1.03-orig/LICENSE	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/LICENSE	2006-02-25 11:00:55.000000000 +0100
@@ -0,0 +1,40 @@
+
+This copyright notice applies to the qmail-ldap patch. It does not apply
+to the original qmail-1.03 by Dan Bernstein. It also partly applies to
+the resulting source and object code. In that Dan Bernsteins copyright
+remains intact and is enhanced with ours as derivative work.
+
+/*
+ * Copyright (c) 1998-2004 Andre Oppermann, Claudio Jeker,
+ *      Internet Business Solutions AG, CH-8005 Zürich, Switzerland
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Internet Business
+ *      Solutions AG and its contributors.
+ * 4. Neither the name of the author nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
diff -ruN qmail-1.03-orig/limit.h qmail-1.03-ldap-20060201-orig/limit.h
--- qmail-1.03-orig/limit.h	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/limit.h	2006-02-25 11:00:55.000000000 +0100
@@ -0,0 +1,22 @@
+#ifndef __LIMIT_H__
+#define __LIMIT_H__
+
+#include <limits.h>
+
+/* 
+ * we only need the max value for 32bit integers so make sure that we have
+ * those available.
+ * So we assume ILP32 or I32LP64 based systems which should be the default
+ * for unix systems. AFAIK only Cray is ILP64...
+ */
+#ifndef UINT_MAX
+#define UINT_MAX        0xffffffffU     /* max value for an unsigned int */
+#endif
+#ifndef INT_MAX
+#define INT_MAX         0x7fffffff      /* max value for an int */
+#endif
+#ifndef INT_MIN
+#define INT_MIN         (-0x7fffffff-1) /* min value for an int */
+#endif
+
+#endif
diff -ruN qmail-1.03-orig/localdelivery.c qmail-1.03-ldap-20060201-orig/localdelivery.c
--- qmail-1.03-orig/localdelivery.c	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/localdelivery.c	2006-02-25 11:00:55.000000000 +0100
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2003-2004 Claudio Jeker,
+ *      Internet Business Solutions AG, CH-8005 Zürich, Switzerland
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Internet Business
+ *      Solutions AG and its contributors.
+ * 4. Neither the name of the author nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#include "control.h"
+#include "qldap-debug.h"
+
+#include "localdelivery.h"
+
+static int	flaglocaldelivery;
+
+int
+localdelivery_init(void)
+{
+	flaglocaldelivery = 1;	/* localdelivery is on (DEFAULT) */
+
+	if (control_readint(&flaglocaldelivery,
+		    "control/ldaplocaldelivery") == -1)
+		return -1;
+	logit(64, "init: control/ldaplocaldelivery: %i\n", flaglocaldelivery);
+	return 0;
+}
+
+int
+localdelivery(void)
+{
+	return flaglocaldelivery;
+}
+
diff -ruN qmail-1.03-orig/localdelivery.h qmail-1.03-ldap-20060201-orig/localdelivery.h
--- qmail-1.03-orig/localdelivery.h	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/localdelivery.h	2006-02-25 11:00:55.000000000 +0100
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2003-2004 Claudio Jeker,
+ *      Internet Business Solutions AG, CH-8005 Zürich, Switzerland
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Internet Business
+ *      Solutions AG and its contributors.
+ * 4. Neither the name of the author nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#ifndef __LOCALDELIVERY_H__
+#define __LOCALDELIVERY_H__
+
+int localdelivery_init(void);
+
+/* returns true if localdelivery is on */
+int localdelivery(void);
+
+#endif
+
diff -ruN qmail-1.03-orig/locallookup.c qmail-1.03-ldap-20060201-orig/locallookup.c
--- qmail-1.03-orig/locallookup.c	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/locallookup.c	2006-02-25 11:00:55.000000000 +0100
@@ -0,0 +1,182 @@
+/*
+ * Copyright (c) 2003-2004 Claudio Jeker,
+ *      Internet Business Solutions AG, CH-8005 Zürich, Switzerland
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Internet Business
+ *      Solutions AG and its contributors.
+ * 4. Neither the name of the author nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+/*
+ * Based on D. J. Bernsteins checkpassword program.
+ */
+
+#include <sys/types.h>
+#include <unistd.h>
+#include "error.h"
+#include "getln.h"
+#include "localdelivery.h"
+#include "open.h"
+#include "passwd.h"
+#include "qldap-debug.h"
+#include "qldap-errno.h"
+#include "readwrite.h"
+#include "substdio.h"
+
+#include "checkpassword.h"
+#include "locallookup.h"
+
+/* Edit the first lines in the Makefile to enable local passwd lookups 
+ * and debug options.
+ * To use shadow passwords under Solaris, uncomment the 'SHADOWOPTS' line 
+ * in the Makefile.
+ * To use shadow passwords under Linux, uncomment the 'SHADOWOPTS' line and
+ * the 'SHADOWLIBS=-lshadow' line in the Makefile.
+ */
+#include <pwd.h>
+#ifdef PW_SHADOW
+#include <shadow.h>
+#endif
+#ifdef AIX
+#include <userpw.h>
+#endif
+
+int
+check_passwd(stralloc *login, stralloc *authdata,
+    struct credentials *c, int fast)
+{
+	int ret;
+	struct passwd *pw;
+#ifdef PW_SHADOW
+	struct spwd *spw;
+#endif
+#ifdef AIX
+	struct userpw *spw;
+#endif
+
+	if (localdelivery() == 0) return NOSUCH;
+
+	pw = getpwnam(login->s);
+	if (!pw) {
+		/* XXX: unfortunately getpwnam() hides temporary errors */
+		logit(32, "check_passwd: user %s not found in passwd db\n",
+		    login->s);
+		return NOSUCH;
+	}
+	logit(32, "check_passwd: user %s found in passwd db\n",
+	    login->s);
+	if (!fast) {
+		c->gid = pw->pw_gid;
+		c->uid = pw->pw_uid;
+		/*
+		 * Here we don't check the home and maildir path, if a user
+		 * has a faked passwd entry, then you have a bigger problem
+		 * on your system than just a guy how can read the mail of
+		 * other users/customers.
+		 */
+		if (!stralloc_copys(&c->home, pw->pw_dir))
+			return ERRNO;
+		if (!stralloc_0(&c->home))
+			return ERRNO;
+	
+		ret = get_local_maildir(&c->home, &c->maildir);
+		if (ret != 0)
+			return ret;
+		logit(32, "get_local_maildir: maildir=%s\n", c->maildir.s);
+	}
+
+#ifdef PW_SHADOW
+	spw = getspnam(login->s);
+	if (!spw)
+		/* XXX: again, temp hidden */
+		return FAILED;
+	ret = cmp_passwd((unsigned char*) authdata->s, spw->sp_pwdp);
+#else /* no PW_SHADOW */
+#ifdef AIX
+	spw = getuserpw(login->s);
+	if (!spw)
+		/* XXX: and again */
+		return FAILED;
+	ret = cmp_passwd((unsigned char*) authdata->s, spw->upw_passwd);
+#else /* no AIX */
+	ret = cmp_passwd((unsigned char*) authdata->s, pw->pw_passwd);
+#endif /* END AIX */
+#endif /* END PW_SHADOW */
+	logit(32, "check_pw: password compare was %s\n", 
+	    ret==OK?"successful":"not successful");
+	return ret;
+}
+
+
+int
+get_local_maildir(stralloc *home, stralloc *maildir)
+{
+	substdio	ss;
+	char		buf[512];
+	int		dirfd, fd, match, save;
+	
+	dirfd = open_read(".");
+	if (dirfd == -1)
+		return ERRNO;
+	if (chdir(home->s) == -1)
+		return ERRNO;
+
+	if ((fd = open_read(".qmail")) == -1) {
+		if (errno == error_noent) return 0;
+		return ERRNO;
+	}
+
+	substdio_fdbuf(&ss, subread, fd, buf, sizeof(buf));
+	while (1) {
+		if (getln(&ss, maildir, &match, '\n') != 0) goto tryclose;
+		if (!match && !maildir->len) {
+			if (!stralloc_copyb(maildir, "", 1)) goto tryclose;
+			break;
+		}
+		if ((maildir->s[0] == '.' || maildir->s[0] == '/') && 
+			  maildir->s[maildir->len-2] == '/') {
+			maildir->s[maildir->len-1] = '\0';
+			break;
+		}
+	}
+	if (fchdir(dirfd) == -1)
+		return ERRNO;
+	close(dirfd);
+	close(fd);
+	return 0;
+
+tryclose:
+	save = errno; /* preserve errno */
+	if (fchdir(dirfd) == -1)
+		return ERRNO;
+	close(dirfd);
+	close(fd);
+	errno = save;
+	return ERRNO;
+}
+
diff -ruN qmail-1.03-orig/locallookup.h qmail-1.03-ldap-20060201-orig/locallookup.h
--- qmail-1.03-orig/locallookup.h	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/locallookup.h	2006-02-25 11:00:55.000000000 +0100
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2003-2004 Claudio Jeker,
+ *      Internet Business Solutions AG, CH-8005 Zürich, Switzerland
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Internet Business
+ *      Solutions AG and its contributors.
+ * 4. Neither the name of the author nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#ifndef __LOCALLOOKUP_H__
+#define __LOCALLOOKUP_H__
+
+#include "stralloc.h"
+
+struct credentials;
+
+int check_passwd(stralloc *, stralloc *, struct credentials *, int);
+int get_local_maildir(stralloc *, stralloc *);
+
+#endif
+
diff -ruN qmail-1.03-orig/lock.h qmail-1.03-ldap-20060201-orig/lock.h
--- qmail-1.03-orig/lock.h	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/lock.h	2006-02-25 11:00:55.000000000 +0100
@@ -1,8 +1,8 @@
 #ifndef LOCK_H
 #define LOCK_H
 
-extern int lock_ex();
-extern int lock_un();
-extern int lock_exnb();
+extern int lock_ex(int);
+extern int lock_un(int);
+extern int lock_exnb(int);
 
 #endif
diff -ruN qmail-1.03-orig/maildir2mbox.c qmail-1.03-ldap-20060201-orig/maildir2mbox.c
--- qmail-1.03-orig/maildir2mbox.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/maildir2mbox.c	2006-02-25 11:00:55.000000000 +0100
@@ -1,3 +1,7 @@
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <unistd.h>
 #include "readwrite.h"
 #include "prioq.h"
 #include "env.h"
@@ -33,7 +37,7 @@
 
 void die_nomem() { strerr_die2x(111,FATAL,"out of memory"); }
 
-void main()
+int main()
 {
  substdio ssin;
  substdio ssout;
@@ -73,8 +77,8 @@
  if (fdnewmbox == -1)
    strerr_die4sys(111,FATAL,"unable to create ",mboxtmp,": ");
 
- substdio_fdbuf(&ssin,read,fdoldmbox,inbuf,sizeof(inbuf));
- substdio_fdbuf(&ssout,write,fdnewmbox,outbuf,sizeof(outbuf));
+ substdio_fdbuf(&ssin,subread,fdoldmbox,inbuf,sizeof(inbuf));
+ substdio_fdbuf(&ssout,subwrite,fdnewmbox,outbuf,sizeof(outbuf));
 
  switch(substdio_copy(&ssout,&ssin))
   {
@@ -90,7 +94,7 @@
    fd = open_read(filenames.s + pe.id);
    if (fd == -1)
      strerr_die4sys(111,FATAL,"unable to read $MAILDIR/",filenames.s + pe.id,": ");
-   substdio_fdbuf(&ssin,read,fd,inbuf,sizeof(inbuf));
+   substdio_fdbuf(&ssin,subread,fd,inbuf,sizeof(inbuf));
 
    if (getln(&ssin,&line,&match,'\n') != 0)
      strerr_die4sys(111,FATAL,"unable to read $MAILDIR/",filenames.s + pe.id,": ");
@@ -105,7 +109,7 @@
 	}
        else
 	{
-	 int i;
+	 unsigned int i;
          if (!stralloc_ready(&ufline,line.len)) die_nomem();
          if (!stralloc_copys(&ufline,"From ")) die_nomem();
 	 for (i = 14;i < line.len - 2;++i)
@@ -158,5 +162,5 @@
      strerr_warn4(WARNING,"$MAILDIR/",filenames.s + pe.id," will be delivered twice; unable to unlink: ",&strerr_sys);
   }
 
- _exit(0);
+ return 0;
 }
diff -ruN qmail-1.03-orig/maildir.c qmail-1.03-ldap-20060201-orig/maildir.c
--- qmail-1.03-orig/maildir.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/maildir.c	2006-02-25 11:00:55.000000000 +0100
@@ -1,5 +1,6 @@
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <unistd.h>
 #include "prioq.h"
 #include "env.h"
 #include "stralloc.h"
@@ -12,7 +13,7 @@
 struct strerr maildir_chdir_err;
 struct strerr maildir_scan_err;
 
-int maildir_chdir()
+int maildir_chdir(void)
 {
  char *maildir;
  maildir = env_get("MAILDIR");
@@ -28,32 +29,32 @@
 {
  DIR *dir;
  direntry *d;
- datetime_sec time;
+ datetime_sec tnow;
  struct stat st;
 
- time = now();
+ tnow = now();
 
  dir = opendir("tmp");
  if (!dir) return;
 
- while (d = readdir(dir))
+ while ((d = readdir(dir)))
   {
    if (d->d_name[0] == '.') continue;
    if (!stralloc_copys(tmpname,"tmp/")) break;
    if (!stralloc_cats(tmpname,d->d_name)) break;
    if (!stralloc_0(tmpname)) break;
    if (stat(tmpname->s,&st) == 0)
-     if (time > st.st_atime + 129600)
+     if (tnow > st.st_atime + 129600)
        unlink(tmpname->s);
   }
  closedir(dir);
 }
 
-static int append(pq,filenames,subdir,time)
+static int append(pq,filenames,subdir,tnow)
 prioq *pq;
 stralloc *filenames;
 char *subdir;
-datetime_sec time;
+datetime_sec tnow;
 {
  DIR *dir;
  direntry *d;
@@ -65,7 +66,7 @@
  if (!dir)
    STRERR_SYS3(-1,maildir_scan_err,"unable to scan $MAILDIR/",subdir,": ")
 
- while (d = readdir(dir))
+ while ((d = readdir(dir)))
   {
    if (d->d_name[0] == '.') continue;
    pos = filenames->len;
@@ -74,7 +75,7 @@
    if (!stralloc_cats(filenames,d->d_name)) break;
    if (!stralloc_0(filenames)) break;
    if (stat(filenames->s + pos,&st) == 0)
-     if (st.st_mtime < time) /* don't want to mix up the order */
+     if (st.st_mtime < tnow) /* don't want to mix up the order */
       {
        pe.dt = st.st_mtime;
        pe.id = pos;
@@ -94,15 +95,14 @@
 int flagcur;
 {
  struct prioq_elt pe;
- datetime_sec time;
- int r;
+ datetime_sec tnow;
 
  if (!stralloc_copys(filenames,"")) return 0;
  while (prioq_min(pq,&pe)) prioq_delmin(pq);
 
- time = now();
+ tnow = now();
 
- if (flagnew) if (append(pq,filenames,"new",time) == -1) return -1;
- if (flagcur) if (append(pq,filenames,"cur",time) == -1) return -1;
+ if (flagnew) if (append(pq,filenames,"new",tnow) == -1) return -1;
+ if (flagcur) if (append(pq,filenames,"cur",tnow) == -1) return -1;
  return 0;
 }
diff -ruN qmail-1.03-orig/maildir++.c qmail-1.03-ldap-20060201-orig/maildir++.c
--- qmail-1.03-orig/maildir++.c	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/maildir++.c	2006-02-25 11:00:55.000000000 +0100
@@ -0,0 +1,736 @@
+/*
+ * Copyright (c) 2000-2004 Claudio Jeker,
+ *      Internet Business Solutions AG, CH-8005 Zürich, Switzerland
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Internet Business
+ *      Solutions AG and its contributors.
+ * 4. Neither the name of the author nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "alloc.h"
+#include "byte.h"
+#include "direntry.h"
+#include "error.h"
+#include "fmt.h"
+#include "getln.h"
+#include "now.h"
+#include "open.h"
+#include "readwrite.h"
+#include "scan.h"
+#include "seek.h"
+#include "sig.h"
+#include "str.h"
+#include "stralloc.h"
+#include "strerr.h"
+#include "substdio.h"
+
+#include "maildir++.h"
+
+static void temp_nomem() { strerr_die1x(111,"Out of memory. (QUOTA #1.0.1)"); }
+
+static int mailfolder(void);
+int quota_parsesize(quota_t *, int *, char *, int);
+static int quota_calcsize(quota_t *, int *, char *, int);
+static int quota_writesize(quota_t *, int *, time_t);
+static int check_maxtime(time_t);
+static int get_file_size(char *, struct stat *);
+static void calc_curnew(quota_t *, time_t *);
+static int read5120(const char *, char *, int *);
+
+
+static stralloc	path = {0};
+static char writebuf[3*FMT_ULONG]; /* enough big to hold all needed data */
+static char buf5120[5120]; /* buffer for maildirsize */
+
+/* alarm handler */
+static void
+sigalrm()
+{
+	unlink(path.s); 
+	strerr_die1x(111,"Timeout while writing maildirsize. (QUOTA #1.0.2)");
+}
+
+void
+quota_add(int fd, unsigned long size, unsigned long count)
+/* add size and count to the quota (maildirsize) */
+{
+	char num[FMT_ULONG];
+	seek_pos pos;
+	substdio ss;
+
+	if (fd == -1) return;
+
+	seek_end(fd);
+	pos = seek_cur(fd); /* again savety */
+
+	substdio_fdbuf(&ss,subwrite,fd,writebuf,sizeof(writebuf));
+
+	/* create string of the form '1234 12\n' and add it to the quota */
+	if (substdio_bput(&ss, num, fmt_ulong(num, size) ) == -1)
+		goto addfail;
+	if (substdio_bput(&ss, " ", 1) == -1)
+		goto addfail;
+	if (substdio_bput(&ss, num, fmt_ulong(num, count) ) == -1)
+		goto addfail;
+	if (substdio_bput(&ss, "\n", 1) == -1)
+		goto addfail;
+	if (substdio_flush(&ss) == -1)
+		goto addfail; 
+	if (fsync(fd) == -1)
+		goto addfail; 
+
+	return;
+
+addfail:
+	strerr_warn3("Unable to add file to quota: ", error_str(errno), 
+			". (QUOTA #1.2.1)",0);
+	seek_trunc(fd,pos); /* recover form error */
+	return; /* ignore errors, perhaps the file was removed */
+}
+
+void
+quota_rm(int fd, unsigned long size, unsigned long count)
+/* remove size and count from the quota (maildirsize) *
+ * both size and count are POSITVE integers           */
+{
+	char num[FMT_ULONG];
+	seek_pos pos;
+	substdio ss;
+
+	if (fd == -1) return;
+
+	seek_end(fd);
+	pos = seek_cur(fd); /* again savety */
+
+	substdio_fdbuf(&ss,subwrite,fd,writebuf,sizeof(writebuf));
+
+	/* create string of the form '-1232 -12\n' and add it to the quota */
+	if (substdio_bput(&ss, "-", 1) == -1)
+		goto rmfail;
+	if (substdio_bput(&ss, num, fmt_ulong(num, size)) == -1)
+		goto rmfail;
+	if (substdio_bput(&ss, " -", 2) == -1)
+		goto rmfail;
+	if (substdio_bput(&ss, num, fmt_ulong(num, count)) == -1)
+		goto rmfail;
+	if (substdio_bput(&ss, "\n", 1) == -1)
+		goto rmfail;
+	if (substdio_flush(&ss) == -1)
+		goto rmfail; 
+	if (fsync(fd) == -1)
+		goto rmfail; 
+	return;
+
+rmfail:
+	strerr_warn3("Unable to remove file from quota: ", error_str(errno), 
+			". (QUOTA #1.3.1)",0);
+	seek_trunc(fd,pos); /* recover form error */
+	return; /* ignore errors, perhaps the file was removed */
+}
+
+int
+quota_calc(const char *dir, int *fd, quota_t *q)
+{
+	int i = 0;
+	int ret;
+	
+	if (! stralloc_copys(&path, dir)) temp_nomem();
+	if (path.s[path.len-1] != '/')
+		if (! stralloc_cats(&path, "/")) temp_nomem();
+
+	while (mailfolder()) {
+		if (! stralloc_cats(&path, "../")) temp_nomem();
+		if (i++ > 1 ) strerr_die1x(111, 
+				"Unable to calc quota: recursive "
+				"maildir++ (QUOTA #1.1.1)");
+	}
+	
+	if (! stralloc_cats(&path, "maildirsize")) temp_nomem();
+	if (! stralloc_0(&path)) temp_nomem();
+	
+	*fd = read5120(path.s, buf5120, &i);
+
+	if (*fd != -1) {
+		ret = quota_parsesize(q, fd, buf5120, i);
+	} else {
+		ret = quota_calcsize(q, fd, buf5120, i);
+	}
+	return ret;
+}
+
+int
+quota_recalc(const char *dir, int *fd, quota_t *q)
+{
+	int  i = 0;
+	int  j;
+	int  lines = 0;
+	time_t tm;
+	struct stat st;
+	
+	if (!stralloc_copys(&path, dir)) temp_nomem();
+	if (path.s[path.len-1] != '/')
+		if (!stralloc_cats(&path, "/")) temp_nomem();
+
+	while (mailfolder()) {
+		if (!stralloc_cats(&path, "../")) temp_nomem();
+		if (i++ > 1 ) strerr_die1x(111, 
+				"Unable to calc quota: recursive "
+				"maildir++ (QUOTA #1.1.1)");
+	}
+	
+	if (!stralloc_cats(&path, "maildirsize")) temp_nomem();
+	if (!stralloc_0(&path)) temp_nomem();
+	
+	*fd = read5120(path.s, buf5120, &i);
+	
+	if (*fd != -1) {
+		for (j = 0; j < i && lines <= 2 ; j++) {
+			if (buf5120[j] == '\n') lines++;
+		}
+		if (lines <= 2) {
+			if (fstat(*fd, &st) == -1) 
+				strerr_die3x(111,
+					"Unable to fstat maildirsize: ", 
+					error_str(errno), " (QUOTA #1.5.1)");
+			tm = now();
+			if (tm < st.st_mtime + 900) {
+				/*
+				   parsed quota of quota_calc() is still valid.
+				   It is important that the caller does not
+				   clear the quota struct.
+				 */
+				/*
+				   If this can not be granted quota_parsesize()
+				   needs to be called here.
+				 */
+				return 0;
+			}
+		}
+		/* need to recalculate the quota */
+		close(*fd);
+		*fd = -1;
+		unlink(path.s);
+	}
+	
+	return quota_calcsize(q, fd, buf5120, i);
+}
+
+int
+quota_check(quota_t *q, unsigned long size, unsigned long count, int *perc)
+{
+	int sp , cp;
+	
+	if (q->quota_size == 0 && q->quota_count == 0) {
+		/* no quota defined */
+		if (perc) *perc = 0;
+		return 0;
+	}
+		
+	if (perc != (int *)0) {
+		sp = q->quota_size != 0 ?
+			(int)((q->size + size)*100.0/q->quota_size) :
+			0;
+		cp = q->quota_count != 0 ?
+			(int)((q->count + count)*100.0/q->quota_count) :
+			0;
+		if (sp > cp)
+			*perc = sp;
+		else
+			*perc = cp;
+	}
+	
+	if (q->size + size > q->quota_size && q->quota_size != 0) {
+		return -1;
+	}
+
+	if (q->count + count > q->quota_count && q->quota_count != 0) {
+		return -1;
+	}
+	
+	return 0;
+}
+
+void
+quota_get(quota_t *q, const char *quota)
+{
+	unsigned long i;
+
+	q->quota_size = 0;
+	q->quota_count = 0;
+	q->size = 0;
+	q->count = 0;
+	
+	if (quota == (char *)0) return;
+
+	while (*quota) {
+		if (*quota < '0' || *quota > '9') {
+			quota++;
+			continue;
+		}
+
+		/* parse found number */
+		quota += scan_ulong(quota, &i);
+
+		switch (*quota) {
+			case 'S':
+				q->quota_size = i;
+				break;
+			case 'C':
+				q->quota_count = i;
+				break;
+			default:
+				/* ignore */
+				break;
+		}
+	}
+}
+
+static int
+mailfolder(void)
+{
+	unsigned int len;
+	struct stat st;
+	
+	/* 
+	 * check if we are in a maildir subfolder, normaly this is impossible
+	 */
+	
+	len = path.len;
+	if (!stralloc_cats(&path, "maildirfolder")) temp_nomem();
+	if (!stralloc_0(&path)) temp_nomem();
+	path.len = len; /* cut away what this function has added */
+
+	if (stat(path.s, &st) == -1) { /* are we in a subdir ? */
+		if (errno != error_noent) {
+			strerr_die3x(111, "Unable to stat maildirfolder: ", 
+					error_str(errno), " (QUOTA #1.4.1)");
+		}
+		return 0;
+	} else {
+		return 1;
+	}
+}
+
+int
+quota_parsesize(quota_t *q, int *fd, char *buf, int len)
+{
+	char *s;
+	quota_t dummy;
+	long fig, pn;
+	int i;
+	char c;
+	
+	for (i = 0; i < len; i++) {
+		if (buf[i] == '\n') buf[i] = '\0';
+	}
+	
+	quota_get(&dummy, buf);
+	if (q->quota_size == 0 && q->quota_count == 0) {
+		/* no quota defined */
+		q->quota_size = dummy.quota_size;
+		q->quota_count = dummy.quota_count;
+	}
+
+	if (q->quota_size != dummy.quota_size || 
+		 q->quota_count != dummy.quota_count) {
+		/* quota definition has changed, remove old maildirsize file
+		 * and recalculate the quota */
+		close(*fd); *fd = -1;
+		unlink(path.s);
+		return quota_calcsize(q, fd, buf, len);
+	}
+	
+	q->size = 0; q->count = 0; /* just to be sure */
+	s = buf;
+	
+	while (s - buf < len) {
+		while (*s++) ; /* hop over the last line */
+		
+		pn = 1;
+		while ((c = *s) < '0' || c > '9') {
+			if (c == '\0') break;
+			if (c == '-') pn = -1;
+			s++; /* hop over spaces */
+		}
+		if (c == '\0') continue;
+		
+		/* first comes the size ... */
+		if ((i = scan_ulong(s, &fig)) == 0) continue;
+		s += i;
+		q->size += (fig * pn);
+
+		pn = 1;
+		while ((c = *s) < '0' || c > '9') {
+			if (c == '-') pn = -1;
+			s++; /* hop over spaces */
+		}
+
+		/* ... then the file count */
+		if ((i = scan_ulong(s, &fig)) == 0) continue;
+		s += i;
+		q->count += (fig * pn);
+	}
+
+	return 0;
+}
+
+static int
+quota_calcsize(quota_t *q, int *fd, char *buf, int len)
+{
+	unsigned int plen;
+	time_t tm;
+	time_t maxtime;
+	direntry *dp;
+	DIR *dirp;
+	
+	if (q->quota_size == 0 && q->quota_count == 0) {
+		/* no quota defined */
+		return 0;
+	}
+
+	q->size = 0; q->count = 0; /* just to be sure */
+	
+	tm = now();
+	maxtime = 0;
+
+	/* first pop away 'maildirsize' in path */
+	path.len -= 12; /* including the '\0' char */
+	plen = path.len;
+	
+	if (!stralloc_0(&path)) temp_nomem();
+	
+	dirp = opendir(path.s);
+	while (dirp && (dp = readdir(dirp)) != 0) {
+		if (dp->d_name[0] == '.' &&
+		    dp->d_name[1] != '\0' &&
+		    dp->d_name[1] != '.'
+#ifndef QUOTATRASH
+		    && str_diff(".Trash", dp->d_name)
+#endif
+		   ) {
+			
+			path.len = plen;
+			if (!stralloc_cats(&path, dp->d_name)) temp_nomem();
+			calc_curnew(q, &maxtime);
+			path.len = plen;
+		}
+	}
+	if (dirp) closedir(dirp);
+	
+	path.len = plen;
+	calc_curnew(q, &maxtime);
+	path.len = plen;
+
+	/* quota is calculated, now create the new maildirsize file */
+	return quota_writesize(q, fd, maxtime);
+}
+
+static int
+quota_writesize(quota_t *q, int *fd, time_t maxtime)
+{
+	int pid;
+	int i;
+	char *buf;
+	char *s;
+	char num[FMT_ULONG];
+	time_t tm;
+	struct stat st;
+	substdio ss;
+
+	/* write maildirsize in standart Maildir manner */
+	sig_alarmcatch(sigalrm);
+
+	for (i = 0; ; ++i) {
+		tm = now();
+		pid = getpid();
+		buf = (char *)alloc(path.len + 17 + (2 * FMT_ULONG) + 2);
+		if (buf == (char *)0)
+			temp_nomem();
+		s = buf;
+		byte_copy(s, path.len, path.s); s += path.len;
+		byte_copy(s, 17, "/tmp/maildirsize."); s += 17;
+		s += fmt_ulong(s,maxtime); *s++ = '.';
+		s += fmt_ulong(s,pid); *s++ = 0;
+		if (stat(buf, &st) == -1) if (errno == error_noent) break;
+		/* really should never get to this point */
+		if (i == 2) _exit(1);
+		sleep(2);
+	}
+
+	alarm(86400);
+
+	if ((*fd = open(buf, O_RDWR|O_NDELAY|O_APPEND|O_CREAT, 0600)) == -1) {
+		if (errno == error_noent) return 0;
+		goto fail;
+	}
+
+	substdio_fdbuf(&ss,subwrite,*fd,writebuf,sizeof(writebuf));
+	
+	if (q->quota_size != 0) {
+		if (substdio_bput(&ss, num, fmt_ulong(num, q->quota_size))
+				== -1 )
+			goto fail;
+		if (substdio_bput(&ss,"S", 1) == -1)
+			goto fail;
+		if (q->quota_count != 0)
+			if (substdio_bput(&ss,",", 1) == -1)
+				goto fail;
+	}
+	if (q->quota_count != 0) {
+		if (substdio_bput(&ss, num, fmt_ulong(num, q->quota_count))
+				== -1)
+			goto fail;
+		if (substdio_bput(&ss,"C", 1) == -1 )
+			goto fail;
+	}
+	if (substdio_bput(&ss,"\n", 1) == -1)
+		goto fail;
+	if (substdio_bput(&ss, num, fmt_ulong(num, q->size)) == -1)
+		goto fail;
+	if (substdio_bput(&ss, " ", 1) == -1)
+		goto fail;
+	if (substdio_bput(&ss, num, fmt_ulong(num, q->count)) == -1)
+		goto fail;
+	if (substdio_bput(&ss, "\n", 1) == -1)
+		goto fail;
+	if (substdio_flush(&ss) == -1)
+		goto fail; 
+	if (fsync(*fd) == -1)
+		goto fail; 
+	
+	i = check_maxtime(maxtime);
+	if (!stralloc_cats(&path, "maildirsize")) temp_nomem();
+	if (!stralloc_0(&path)) temp_nomem();
+	if (unlink(path.s) == -1 && errno != error_noent) goto fail;
+	
+	if (i) {
+		/* race condition, don't write maildir size */
+		unlink(buf);
+		alloc_free(buf);
+		*fd = -1;
+		return -1;
+	}
+	if (link(buf,path.s) == -1) goto fail;
+	unlink(buf);
+
+	/* unset the alarm, else %*#! may happen */
+	alarm(0);
+	sig_alarmdefault();
+
+	return 0;
+
+fail: 
+	strerr_warn3("Problems while trying to get maildirsize: ", 
+			error_str(errno), ". (QUOTA #1.1.1)", 0);
+	unlink(buf);
+	*fd = -1;
+	return -1;
+}
+
+static int
+check_maxtime(time_t t)
+/* check if a directory has changed, to avoid race conditions */
+{
+	direntry *dp;
+	DIR *dirp;
+	struct stat filest;
+	unsigned int slen;
+	int i;
+
+	slen = path.len;
+	if (!stralloc_0(&path)) temp_nomem();
+	dirp = opendir(path.s);
+	path.len = slen;
+	
+	i = 0;
+	while (dirp && (dp = readdir(dirp)) != 0) {
+		if (dp->d_name[0] == '.' &&
+		    dp->d_name[1] != '\0' &&
+		    dp->d_name[1] != '.'
+#ifndef QUOTATRASH
+		    && str_diff(".Trash", dp->d_name)
+#endif
+		   ) {
+
+			path.len = slen;
+			if (!stralloc_cats(&path, dp->d_name)) temp_nomem();
+			if (!stralloc_cats(&path, "/cur")) temp_nomem();
+			if (!stralloc_0(&path)) temp_nomem();
+			if (stat(path.s, &filest) == 0
+			    && filest.st_mtime > t) {
+				i = 1;
+				break;
+			}
+			path.len = slen;
+			if (!stralloc_cats(&path, dp->d_name)) temp_nomem();
+			if (!stralloc_cats(&path, "/new")) temp_nomem();
+			if (!stralloc_0(&path)) temp_nomem();
+			if (stat(path.s, &filest) == 0
+			    && filest.st_mtime > t) {
+				i = 1;
+				break;
+			}
+		}
+		if (!str_diff("new", dp->d_name)) {
+			path.len = slen;
+			if (!stralloc_cats(&path, "/new")) temp_nomem();
+			if (stat(path.s, &filest) == 0
+			    && filest.st_mtime > t) {
+				i = 1;
+				break;
+			}
+		}
+		if (!str_diff("cur", dp->d_name)) {
+			path.len = slen;
+			if (!stralloc_cats(&path, "/cur")) temp_nomem();
+			if (stat(path.s, &filest) == 0
+			    && filest.st_mtime > t) {
+				i = 1;
+				break;
+			}
+		}
+	}
+	if (dirp) closedir(dirp);
+
+	path.len = slen;
+	return i;
+}
+
+static int
+get_file_size(char *name, struct stat *st)
+/* get the filesize of the file name in dir, via the name or a stat */
+{
+	char *s = name;
+	unsigned int slen;
+
+	while (*s) {
+		if (*s != ',' || s[1] != 'S' || s[2] != '=') {
+			s++;
+		} else {
+			s += 3;
+			st->st_size = 0;
+			while (*s >= '0' && *s <= '9')
+				st->st_size = st->st_size*10 + (*s++ - '0');
+			return 0;
+		}
+	}
+	/* stat the file */
+	slen = --path.len; /* path was zero terminated */
+	if (!stralloc_cats(&path, name)) temp_nomem();
+	if (!stralloc_0(&path)) temp_nomem();
+	path.len = slen;
+
+	if (stat(path.s, st) == 0) {
+		if (!stralloc_0(&path)) temp_nomem();
+		return 0;
+	} else {
+		if (!stralloc_0(&path)) temp_nomem();
+		return -1;
+	}
+}
+
+static void
+calc_curnew(quota_t *q, time_t *maxtime)
+/* calculate the size of the two dirs new and cur of a maildir 
+ * (uses get_file_size) */
+{
+	struct stat		filest;
+	direntry		*dp;
+	DIR			*dirp;
+	char			*f;
+	int			i;
+
+	if (!stralloc_cats(&path, "/new/")) temp_nomem();
+	if (!stralloc_0(&path)) temp_nomem();
+	
+	for (i = 0; i < 2; i++) {
+		/* update the latest modified time to avoid race conditions */
+		if (stat(path.s, &filest) == 0 && filest.st_mtime > *maxtime)
+			*maxtime = filest.st_mtime;
+
+		dirp = opendir(path.s);
+		/* start with new */
+		while (dirp && (dp = readdir(dirp)) != 0) {
+			f = dp->d_name;
+			if ( *f == '.' ) continue; /* ignore all dot-files */
+			while(*f) {
+				if (*f != ':' || f[1] != '2' || f[2] != ',') {
+					f++;
+				} else {
+					f += 3;
+					while (	*f >= 'A'
+						&& *f <= 'Z'
+						&& *f != 'T') f++;
+					break;
+				}
+			}
+			if (*f == 'T') continue;
+			/* get the file size */
+			if(get_file_size(dp->d_name, &filest) == 0) {
+				q->count++;
+				q->size += (long)filest.st_size;
+			} 
+		}
+		if (dirp) closedir(dirp);
+
+		/* the same thing with cur */
+		fmt_str(path.s + path.len - 5, "cur");
+	}
+}
+
+static int
+read5120(const char *fn, char* buf, int *len)
+{
+	int fd;
+	int r;
+
+	if ((fd = open(fn, O_RDWR|O_NDELAY|O_APPEND, 0600)) == -1) {
+		if (errno == error_noent) return -1;
+		strerr_die3x(111, "Unable to open maildirsize: ", 
+				error_str(errno), " (QUOTA #1.5.1)");
+	}
+	
+	*len = 0;
+	for (;;) {
+		r = read(fd, buf, 5120 - *len);
+		if (r == -1) if (errno == error_intr) continue;
+		if (*len >= 5120) { /* file to big */
+			close(fd);
+			unlink(path.s);
+			return -1;
+		}
+		if (r == 0) return fd; /* no more data */
+		*len += r;
+		buf += r;
+	}
+}
+
diff -ruN qmail-1.03-orig/maildir.h qmail-1.03-ldap-20060201-orig/maildir.h
--- qmail-1.03-orig/maildir.h	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/maildir.h	2006-02-25 11:00:55.000000000 +0100
@@ -1,12 +1,15 @@
 #ifndef MAILDIR_H
 #define MAILDIR_H
 
+#include "prioq.h"
+#include "stralloc.h"
 #include "strerr.h"
+
 extern struct strerr maildir_chdir_err;
 extern struct strerr maildir_scan_err;
 
-extern int maildir_chdir();
-extern void maildir_clean();
-extern int maildir_scan();
+extern int maildir_chdir(void);
+extern void maildir_clean(stralloc *);
+extern int maildir_scan(prioq *, stralloc *, int, int);
 
 #endif
diff -ruN qmail-1.03-orig/maildir++.h qmail-1.03-ldap-20060201-orig/maildir++.h
--- qmail-1.03-orig/maildir++.h	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/maildir++.h	2006-02-25 11:00:55.000000000 +0100
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2000-2004 Claudio Jeker,
+ *      Internet Business Solutions AG, CH-8005 Zürich, Switzerland
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Internet Business
+ *      Solutions AG and its contributors.
+ * 4. Neither the name of the author nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#ifndef __MAILDIRPP_H__
+#define __MAILDIRPP_H__
+
+typedef struct {
+	unsigned long quota_size;
+	unsigned long quota_count;
+	long size;
+	long count;
+} quota_t;
+
+void quota_add(int , unsigned long , unsigned long);
+void quota_rm(int , unsigned long , unsigned long);
+int quota_calc(const char *, int *fd, quota_t *);
+int quota_recalc(const char *, int *fd, quota_t *);
+int quota_check(quota_t *, unsigned long , unsigned long , int *);
+void quota_get(quota_t *, const char *);
+
+#endif
diff -ruN qmail-1.03-orig/maildirmake.c qmail-1.03-ldap-20060201-orig/maildirmake.c
--- qmail-1.03-orig/maildirmake.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/maildirmake.c	2006-02-25 11:00:55.000000000 +0100
@@ -1,9 +1,12 @@
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
 #include "strerr.h"
 #include "exit.h"
 
 #define FATAL "maildirmake: fatal: "
 
-void main(argc,argv)
+int main(argc,argv)
 int argc;
 char **argv;
 {
@@ -20,5 +23,5 @@
     strerr_die4sys(111,FATAL,"unable to mkdir ",argv[1],"/new: ");
   if (mkdir("cur",0700) == -1)
     strerr_die4sys(111,FATAL,"unable to mkdir ",argv[1],"/cur: ");
-  _exit(0);
+  return 0;
 }
diff -ruN qmail-1.03-orig/maildirwatch.c qmail-1.03-ldap-20060201-orig/maildirwatch.c
--- qmail-1.03-orig/maildirwatch.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/maildirwatch.c	2006-02-25 11:00:55.000000000 +0100
@@ -1,3 +1,4 @@
+#include <unistd.h>
 #include "getln.h"
 #include "substdio.h"
 #include "subfd.h"
@@ -28,7 +29,7 @@
 void dobody(h) stralloc *h; { addtext(h->s,h->len); }
 void doheader(h) stralloc *h;
 {
- int i;
+ unsigned int i;
  switch(hfield_known(h->s,h->len))
   {
    case H_SUBJECT:
@@ -58,11 +59,11 @@
 char inbuf[SUBSTDIO_INSIZE];
 substdio ssin;
 
-void main()
+int main()
 {
  struct prioq_elt pe;
  int fd;
- int i;
+ unsigned int i;
 
  if (maildir_chdir() == -1)
    strerr_die1(111,FATAL,&maildir_chdir_err);
@@ -81,7 +82,7 @@
 
      fd = open_read(filenames.s + pe.id);
      if (fd == -1) continue;
-     substdio_fdbuf(&ssin,read,fd,inbuf,sizeof(inbuf));
+     substdio_fdbuf(&ssin,subread,fd,inbuf,sizeof(inbuf));
 
      if (!stralloc_copys(&sender,"?")) die_nomem();
      if (!stralloc_copys(&recipient,"?")) die_nomem();
@@ -122,4 +123,6 @@
    substdio_flush(subfdout);
    sleep(30);
   }
+ /* NOTREACHED */
+ return 1;
 }
diff -ruN qmail-1.03-orig/mailmagic.c qmail-1.03-ldap-20060201-orig/mailmagic.c
--- qmail-1.03-orig/mailmagic.c	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/mailmagic.c	2006-02-25 11:00:55.000000000 +0100
@@ -0,0 +1,205 @@
+/*
+ * Copyright (c) 2003-2004 Claudio Jeker,
+ *      Internet Business Solutions AG, CH-8005 Zürich, Switzerland
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Internet Business
+ *      Solutions AG and its contributors.
+ * 4. Neither the name of the author nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#include "byte.h"
+#include "case.h"
+#include "error.h"
+#include "getln.h"
+#include "now.h"
+#include "stralloc.h"
+#include "substdio.h"
+
+#include "qmail-ldap.h"
+#include "mailmagic.h"
+
+static unsigned int mypos;
+static stralloc *mysa;
+
+static void
+sa_init(stralloc *header)
+{
+	mypos = 0;
+	mysa = header;
+}
+
+static int
+sa_read(int fd, void *buf, int len)
+{
+	int	t;
+
+	t = mysa->len - mypos;
+	if (t == 0) return 0;
+	if (t < 0) {
+		errno = error_io;
+		return -1;
+	}
+	if (t > len) t = len;
+	byte_copy(buf, t, mysa->s + mypos);
+	mypos += t;
+	return t;
+}
+
+static char buf[256];
+static stralloc line = {0};
+
+#ifndef REPLY_SUBJ
+#define REPLY_SUBJ "Your Mail"
+#endif
+
+static int
+magicsubject(stralloc *l, stralloc *h, stralloc *s)
+{
+	unsigned int i, j;
+	
+	j = l->len;
+	for (i = 0; i < j; i++) {
+		if (l->s[i] != '%') {
+			if (!stralloc_append(h, &l->s[i])) return -1;
+			continue;
+		}
+		if (case_startb(l->s + i, j - i, "%SUBJECT%") == 0) {
+			if (!stralloc_append(h, &l->s[i])) return -1;
+			continue;
+		}
+		i += 8; /* strlen("%SUBJECT%") - 1 */
+		if (s == 0 || s->s == 0 || s->len == 0) {
+			if (!stralloc_cats(h, REPLY_SUBJ)) return -1;
+		} else {
+			if (!stralloc_cat(h, s)) return -1;
+		}
+	}
+	
+	return 0;
+}
+
+int
+headermagic(stralloc *mess, stralloc *header, stralloc *subj,
+    struct mheader *h)
+{
+	substdio	ss;
+	unsigned int	pos, i;
+	int		match, w;
+	
+	if (!stralloc_copys(header, "")) return -1;
+	for (i = 0; h[i].f != 0; i++) h[i].seen = 0;
+	pos = 0; w = 0;
+
+	sa_init(mess);
+	substdio_fdbuf(&ss, sa_read, -1, buf, sizeof(buf));
+	if (getln(&ss, &line, &match, '\n') != 0) return -1;
+	if (match && case_diffb(line.s, line.len, "%HEADER%\n") == 0) {
+		pos += line.len;
+		for (;;) {
+			if (getln(&ss, &line, &match, '\n') != 0) return -1;
+			if (!match) break;
+			pos += line.len;
+			if (line.len <= 1) break;
+			if (*line.s == '\t' || *line.s == ' ')
+				if (w) {
+					if (!stralloc_cat(header, &line))
+						return -1;
+					continue;
+				}
+			w = 0;
+			for (i = 0; h[i].f != 0; i++) {
+				if (case_startb(line.s, line.len, h[i].f) == 0)
+					continue;
+				if (h[i].type == DENY) break;
+				if (h[i].type == FORCE) break;
+				w = 1;
+				h[i].seen = 1;
+				if (h[i].type == SUBJECT) {
+					if (magicsubject(&line,
+						    header, subj) == -1)
+						return -1;
+					break;
+				}
+				if (!stralloc_cat(header, &line)) return -1;
+			}
+		}
+	}
+
+	for (i = 0; h[i].f != 0; i++)
+		if (h[i].seen == 0 && h[i].v != 0)
+			if (h[i].type != DENY ) {
+				if (h[i].type == SUBJECT) {
+					if (!stralloc_copys(&line, h[i].f))
+						return -1;
+					if (!stralloc_append(&line, " "))
+						return -1;
+					if (!stralloc_cats(&line, h[i].v))
+						return -1;
+					if (line.s[line.len-1] != '\n')
+						if (!stralloc_append(&line,
+							    "\n")) return -1;
+					if (magicsubject(&line,
+						    header, subj) == -1)
+						return -1;
+					continue;
+				}
+				if (!stralloc_cats(header, h[i].f)) return -1;
+				if (!stralloc_append(header, " ")) return -1;
+				if (!stralloc_cats(header, h[i].v)) return -1;
+				if (header->s[header->len-1] != '\n')
+					if (!stralloc_append(header, "\n"))
+						return -1;
+			}
+	return pos;
+}
+
+static stralloc mimebound = {0};
+
+int
+mimemagichead(stralloc *h, stralloc *salt)
+{
+	if (!stralloc_copys(&mimebound, "--")) return -1;
+	if (!stralloc_cat(&mimebound, salt)) return -1;
+
+	if (!stralloc_cats(h, "Content-Type: multipart/mixed; boundary=\""))
+		return -1;
+	if (!stralloc_catb(h, mimebound.s + 2, mimebound.len - 2)) return -1;
+	if (!stralloc_cats(h, "\"\n\n"
+		    "This is a multi-part message in MIME format.\n"
+		    "If you can read this your mail user agent does"
+		    "not support MIME messages\n")) return -1;
+
+	if (!stralloc_0(&mimebound)) return -1;
+	return 0;
+}
+
+char *
+mimemagic(void)
+{
+	return mimebound.s;
+}
+
diff -ruN qmail-1.03-orig/mailmagic.h qmail-1.03-ldap-20060201-orig/mailmagic.h
--- qmail-1.03-orig/mailmagic.h	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/mailmagic.h	2006-02-25 11:00:55.000000000 +0100
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2003-2004 Claudio Jeker,
+ *      Internet Business Solutions AG, CH-8005 Zürich, Switzerland
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Internet Business
+ *      Solutions AG and its contributors.
+ * 4. Neither the name of the author nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#ifndef __HEADERMAGIC_H__
+#define __HEADERMAGIC_H__
+
+#include "stralloc.h"
+
+#define DENY 1
+#define ALLOW 2
+#define FORCE 3
+#define SUBJECT 4
+#define DEFAULT ""
+
+struct mheader {
+	const char	*f; /* field */
+	const char	*v; /* default value */
+	int		type; /* one of DENY, ALLOW, FORCE, SUBJECT */
+	int		seen; /* used internally */
+};
+
+int headermagic(stralloc *, stralloc *, stralloc *, struct mheader *);
+int mimemagichead(stralloc *, stralloc *);
+char *mimemagic(void);
+
+#endif
+
diff -ruN qmail-1.03-orig/mailmaker.c qmail-1.03-ldap-20060201-orig/mailmaker.c
--- qmail-1.03-orig/mailmaker.c	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/mailmaker.c	2006-02-25 11:00:55.000000000 +0100
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2003-2004 Claudio Jeker,
+ *      Internet Business Solutions AG, CH-8005 Zürich, Switzerland
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Internet Business
+ *      Solutions AG and its contributors.
+ * 4. Neither the name of the author nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#ifdef AUTOMAILDIRMAKE
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <unistd.h>
+
+#include "error.h"
+#include "open.h"
+#include "qldap-errno.h"
+
+#include "mailmaker.h"
+
+/*
+ * XXX the maildirmake stuff is directly in qmail-local.c and qmail-pop3d.c
+ * XXX this is simpler and better (Perhaps I'll find a better way sometimes) ;-)
+ * XXX BULLSHIT! Simpler and better, was I on drugs? This needs definitifly a 
+ * XXX rewrite and while doing that I can also fix the problem with courier.
+ */
+static int makedir(const char *);
+
+static int
+makedir(const char *dir)
+{
+	struct	stat st;
+	
+	if (stat(dir, &st) == -1) {
+		if (errno == error_noent) {
+			if (mkdir(dir,0700) == -1) return ERRNO;
+		} else 
+			return ERRNO;
+	} else if (!S_ISDIR(st.st_mode))
+		return MAILDIR_CORRUPT;
+
+	return OK;
+}
+
+int
+maildir_make(char *maildir)
+{
+	int	dirfd, oldmask, r, se;
+
+	oldmask = umask(077);
+	dirfd = open_read(".");
+	if (dirfd == -1)
+		return ERRNO;
+	if (chdir(maildir) == -1) {
+		if ((r = makedir(maildir)) != OK) goto fail;
+		if (chdir(maildir) == -1) {
+			if (errno == ENOTDIR) {
+				r = MAILDIR_CORRUPT;
+				goto fail;
+			} else {
+				r = ERRNO;
+				goto fail;
+			}
+		}
+	}
+	if ((r = makedir("tmp")) != OK) goto fail;
+	if ((r = makedir("cur")) != OK) goto fail;
+	if ((r = makedir("new")) != OK) goto fail;
+
+	umask(oldmask);
+	if (fchdir(dirfd) == -1) {
+		r = ERRNO;
+		goto fail;
+	}
+	close(dirfd);
+	return OK;
+
+fail:
+	se = errno;
+	umask(oldmask);
+	fchdir(dirfd);
+	close(dirfd);
+	errno = se;
+	return r;
+}
+#endif
+
diff -ruN qmail-1.03-orig/mailmaker.h qmail-1.03-ldap-20060201-orig/mailmaker.h
--- qmail-1.03-orig/mailmaker.h	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/mailmaker.h	2006-02-25 11:00:55.000000000 +0100
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2003-2004 Claudio Jeker,
+ *      Internet Business Solutions AG, CH-8005 Zürich, Switzerland
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Internet Business
+ *      Solutions AG and its contributors.
+ * 4. Neither the name of the author nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#ifndef __MAILMAKER_H__
+#define __MAILMAKER_H__
+
+/* checks and creates maildirs as needed */
+int maildir_make(char *);
+
+#endif
diff -ruN qmail-1.03-orig/Makefile qmail-1.03-ldap-20060201-orig/Makefile
--- qmail-1.03-orig/Makefile	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/Makefile	2006-02-25 11:00:55.000000000 +0100
@@ -1,8 +1,101 @@
+# Edit this few lines to configure your ldap stuff
+
+# to enable some additional for qmail-ldap stuff put it on the LDAPFLAGS line
+#
+# -DALTQUEUE to use a diffrent qmail-queue programm on runtime
+# -DBIGBROTHER to use the control/bigbrother file to forward all mails comming
+#     from a specified account to another (swiss bigbrother law)
+# -DBIGTODO to enable the big todo patch (this can be used together with 
+#     EXTERNAL_TODO). Useful for servers with very many non-preprocessed mails
+# -DBIND_8_COMPAT need if the compile fails building dns.c because of
+#     undeclared defines. This is necessary on MacOS X 10.3.
+# -DCLEARTEXTPASSWD to use cleartext passwords (bad idea on production systems)
+# -DDASH_EXT to enable the dash_ext patch for extended mail addresses
+# -DDATA_COMPRESS to use the smtp on the fly DATA compression 
+# -DEXTERNAL_TODO to use the external high-performance todo processing (this
+#     avoids the silly qmail syndrome with high injection rates)
+# -DIGNOREVERISIGN to disallow dns wildchar matches on gtlds, thanks verisign.
+# -DQLDAP_CLUSTER for enabling cluster support
+# -DQMQP_COMPRESS to use the QMQP on the fly compression (for clusters)
+# -DQUOTATRASH to include the Trash in the quota calculation (normaly it is not)
+# -DSMTPEXECCHECK to enable smtp DOS/Windows executable detection
+#LDAPFLAGS=-DQLDAP_CLUSTER -DEXTERNAL_TODO -DDASH_EXT -DDATA_COMPRESS -DQMQP_COMPRESS -DSMTPEXECCHECK
+
+# Perhaps you have different ldap libraries, change them here
+LDAPLIBS=-L/usr/local/lib -lldap -llber
+# and change the location of the include files here
+LDAPINCLUDES=-I/usr/local/include
+# on Slowaris you need -lresolv and probably a LD_RUN_PATH added like this:
+#LDAPLIBS=-L/opt/OpenLDAP/lib -lldap -llber -lresolv -R/opt/OpenLDAP/lib
+# for example on my Linux box I use:
+#LDAPLIBS=-L/opt/OpenLDAP/lib -lldap -llber
+# if you need a special include-directory for ldap headers enable this
+#LDAPINCLUDES=-I/opt/OpenLDAP/include
+
+# ZLIB needed for -DDATA_COMPRESS and -DQMQP_COMPRESS
+#ZLIB=-lz
+# or you installed zlib in a different path you can use something like this
+#ZLIB=-L/opt/zlib/lib -lz
+#ZINCLUDES=-I/opt/zlib/include
+
+# TLS (SMTP encryption) in qmail-smtpd and qmail-remote, see TLS.readme
+# You need OpenSSL for this
+# use -DTLS_REMOTE to enable tls support in qmail-remote
+# use -DTLS_SMTPD to enable tls support in qmail-smtpd
+# use -DTLSDEBUG to enable additional tls debug information in qmail-remote
+#TLS=-DTLS_REMOTE -DTLS_SMTPD
+# Path to OpenSSL includes
+#TLSINCLUDES=-I/usr/local/include
+# Path to OpenSSL libraries
+#TLSLIBS=-L/usr/local/lib -lssl -lcrypto
+# Path to OpenSSL binary
+#OPENSSLBIN=/usr/local/bin/openssl
+#OPENSSLBIN=openssl
+
+# to make the Netscape download progress bar work with qmail-pop3d
+# uncomment the next line (allready done)
+MNW=-DMAKE_NETSCAPE_WORK 
+
+# to enable the auto-maildir-make feature uncomment the next line
+#MDIRMAKE=-DAUTOMAILDIRMAKE
+
+# to enable the auto-homedir-make feature uncomment the next line
+#HDIRMAKE=-DAUTOHOMEDIRMAKE
+
+# on most systems we need this to make auth_pop and auth_imap
+#SHADOWLIBS=-lcrypt
+# OpenBSD and other Systems do not have libcrypt, so comment the line out
+# if you get linking problems.
+# To use shadow passwords under some Linux OS, uncomment the next two lines.
+#SHADOWLIBS=-lcrypt -lshadow
+#SHADOWOPTS=-DPW_SHADOW
+# To use shadow passwords under Solaris, uncomment the SHADOWOPTS line.
+
+# to enable the possibility to log and debug imap and pop uncoment the
+# next line
+#DEBUG=-DDEBUG
+# WARNING: you need a NONE DEBUG auth_* to run with inetd
+
+# for profiling ...
+#INCTAI=../libtai-0.60
+#LIBTAI=../libtai-0.60
+
+# Just for me, make from time to time a backup
+BACKUPPATH=/backup/qmail-backup/qmail-ldap.`date "+%Y%m%d-%H%M"`.tar
+# STOP editing HERE !!!
+
 # Don't edit Makefile! Use conf-* for configuration.
 
 SHELL=/bin/sh
 
-default: it
+default: it ldap
+
+ldap: qmail-quotawarn qmail-reply auth_pop auth_imap auth_smtp digest \
+qmail-ldaplookup pbsadd pbscheck pbsdbd qmail-todo qmail-forward \
+qmail-secretary qmail-group qmail-verify condwrite qmail-cdb \
+qmail-imapd.run qmail-pbsdbd.run qmail-pop3d.run qmail-qmqpd.run \
+qmail-smtpd.run qmail.run qmail-imapd-ssl.run qmail-pop3d-ssl.run \
+Makefile.cdb-p
 
 addresses.0: \
 addresses.5
@@ -20,6 +113,75 @@
 compile alloc_re.c alloc.h byte.h
 	./compile alloc_re.c
 
+auth_imap: \
+load auth_imap.o auth_mod.o checkpassword.o passwd.o digest_md4.o \
+digest_md5.o digest_rmd160.o digest_sha1.o base64.o read-ctrl.o getopt.a \
+control.o dirmaker.o mailmaker.o qldap.a localdelivery.o locallookup.o \
+pbsexec.o constmap.o getln.a strerr.a substdio.a stralloc.a env.a wait.a \
+dns.o ip.o ipalloc.o ipme.o alloc.a str.a case.a fs.a error.a timeoutconn.o \
+timeoutread.o ndelay.a open.a sig.a prot.o auto_uids.o auto_qmail.o \
+dns.lib socket.lib
+	./load auth_imap auth_mod.o checkpassword.o passwd.o digest_md4.o \
+	digest_md5.o digest_rmd160.o digest_sha1.o base64.o read-ctrl.o \
+	getopt.a control.o dirmaker.o mailmaker.o qldap.a localdelivery.o \
+	locallookup.o pbsexec.o constmap.o getln.a strerr.a substdio.a \
+	stralloc.a env.a wait.a dns.o ip.o ipalloc.o ipme.o alloc.a str.a \
+	case.a fs.a error.a timeoutconn.o timeoutread.o ndelay.a open.a \
+	sig.a prot.o auto_uids.o auto_qmail.o $(LDAPLIBS) $(SHADOWLIBS) \
+	`cat dns.lib` `cat socket.lib`
+
+auth_imap.o: \
+compile auth_imap.c alloc.h byte.h env.h error.h exit.h fmt.h pbsexec.h \
+qldap-debug.h qldap-errno.h qmail-ldap.h readwrite.h scan.h sgetopt.h \
+sig.h str.h stralloc.h substdio.h timeoutread.h auth_mod.h
+	./compile $(LDAPFLAGS) $(DEBUG) auth_imap.c
+
+auth_mod.o: \
+compile auth_mod.c auth_mod.h checkpassword.h byte.h localdelivery.h \
+locallookup.h output.h qldap.h qldap-debug.h qldap-errno.h stralloc.h \
+read-ctrl.h dirmaker.h qldap-cluster.h select.h alloc.h
+	./compile $(LDAPFLAGS) $(DEBUG) $(HDIRMAKE) $(MDIRMAKE) auth_mod.c
+
+auth_pop: \
+load auth_pop.o auth_mod.o checkpassword.o passwd.o digest_md4.o \
+digest_md5.o digest_rmd160.o digest_sha1.o base64.o read-ctrl.o getopt.a \
+control.o dirmaker.o mailmaker.o qldap.a localdelivery.o locallookup.o \
+pbsexec.o constmap.o getln.a strerr.a substdio.a stralloc.a env.a wait.a \
+dns.o ip.o ipalloc.o ipme.o alloc.a str.a case.a fs.a error.a timeoutconn.o \
+timeoutread.o ndelay.a open.a prot.o auto_uids.o auto_qmail.o \
+dns.lib socket.lib
+	./load auth_pop auth_mod.o checkpassword.o passwd.o digest_md4.o \
+	digest_md5.o digest_rmd160.o digest_sha1.o base64.o read-ctrl.o \
+	getopt.a control.o qldap.a dirmaker.o mailmaker.o localdelivery.o \
+	locallookup.o pbsexec.o constmap.o getln.a strerr.a substdio.a \
+	stralloc.a env.a wait.a dns.o ip.o ipalloc.o ipme.o alloc.a str.a \
+	case.a fs.a error.a timeoutconn.o timeoutread.o ndelay.a open.a \
+	prot.o auto_uids.o auto_qmail.o $(LDAPLIBS) $(SHADOWLIBS) \
+	`cat dns.lib` `cat socket.lib`
+
+auth_pop.o: \
+compile auth_pop.c byte.h env.h error.h exit.h pbsexec.h qldap-debug.h \
+qldap-errno.h qmail-ldap.h readwrite.h sgetopt.h str.h stralloc.h substdio.h \
+timeoutread.h auth_mod.h
+	./compile $(LDAPFLAGS) $(DEBUG) auth_pop.c
+
+auth_smtp: \
+load auth_smtp.o checkpassword.o passwd.o digest_md4.o digest_md5.o \
+digest_rmd160.o digest_sha1.o base64.o read-ctrl.o control.o qldap.a \
+constmap.o getln.a strerr.a substdio.a stralloc.a env.a alloc.a str.a \
+case.a fs.a error.a open.a prot.o auto_uids.o auto_qmail.o
+	./load auth_smtp checkpassword.o passwd.o digest_md4.o \
+	digest_md5.o digest_rmd160.o digest_sha1.o base64.o read-ctrl.o \
+	control.o qldap.a constmap.o getln.a strerr.a substdio.a stralloc.a \
+	env.a alloc.a str.a case.a fs.a error.a open.a prot.o auto_uids.o \
+	auto_qmail.o $(LDAPLIBS) $(SHADOWLIBS)
+	
+auth_smtp.o: \
+compile auth_smtp.c byte.h env.h error.h exit.h output.h qldap.h \
+qldap-debug.h qldap-errno.h qmail-ldap.h read-ctrl.h str.h stralloc.h \
+substdio.h checkpassword.h auth_mod.h
+	./compile $(LDAPFLAGS) $(DEBUG) auth_smtp.c
+
 auto-ccld.sh: \
 conf-cc conf-ld warn-auto.sh
 	( cat warn-auto.sh; \
@@ -136,6 +298,18 @@
 compile auto_usera.c
 	./compile auto_usera.c
 
+auto_userl.c: \
+auto-str conf-users
+	./auto-str auto_userl `head -3 conf-users | tail -1` > auto_userl.c
+
+auto_userl.o: \
+compile auto_userl.c
+	./compile auto_userl.c
+
+base64.o: \
+compile base64.c base64.h str.h
+	./compile $(LDAPFLAGS) base64.c
+
 binm1: \
 binm1.sh conf-qmail
 	cat binm1.sh \
@@ -211,15 +385,19 @@
 compile byte_rchr.c byte.h
 	./compile byte_rchr.c
 
+byte_repl.o: \
+compile byte_repl.c byte.h
+	./compile byte_repl.c
+
 byte_zero.o: \
 compile byte_zero.c byte.h
 	./compile byte_zero.c
 
 case.a: \
 makelib case_diffb.o case_diffs.o case_lowerb.o case_lowers.o \
-case_starts.o
+case_startb.o case_starts.o
 	./makelib case.a case_diffb.o case_diffs.o case_lowerb.o \
-	case_lowers.o case_starts.o
+	case_lowers.o case_startb.o case_starts.o
 
 case_diffb.o: \
 compile case_diffb.c case.h
@@ -237,52 +415,50 @@
 compile case_lowers.c case.h
 	./compile case_lowers.c
 
+case_startb.o: \
+compile case_startb.c case.h
+	./compile case_startb.c
+
 case_starts.o: \
 compile case_starts.c case.h
 	./compile case_starts.c
 
 cdb.a: \
-makelib cdb_hash.o cdb_unpack.o cdb_seek.o
-	./makelib cdb.a cdb_hash.o cdb_unpack.o cdb_seek.o
+makelib cdb_hash.o cdb.o
+	./makelib cdb.a cdb_hash.o cdb.o
+
+cdb.o: \
+compile cdb.c cdb.h byte.h  error.h seek.h uint32.h
+	./compile cdb.c
 
 cdb_hash.o: \
 compile cdb_hash.c cdb.h uint32.h
 	./compile cdb_hash.c
 
-cdb_seek.o: \
-compile cdb_seek.c cdb.h uint32.h
-	./compile cdb_seek.c
-
-cdb_unpack.o: \
-compile cdb_unpack.c cdb.h uint32.h
-	./compile cdb_unpack.c
+cdb_make.o: \
+compile cdb_make.c cdb.h readwrite.h seek.h error.h alloc.h uint32.h
+	./compile cdb_make.c
 
 cdbmake.a: \
-makelib cdbmake_pack.o cdbmake_hash.o cdbmake_add.o
-	./makelib cdbmake.a cdbmake_pack.o cdbmake_hash.o \
-	cdbmake_add.o
-
-cdbmake_add.o: \
-compile cdbmake_add.c cdbmake.h uint32.h
-	./compile cdbmake_add.c
-
-cdbmake_hash.o: \
-compile cdbmake_hash.c cdbmake.h uint32.h
-	./compile cdbmake_hash.c
-
-cdbmake_pack.o: \
-compile cdbmake_pack.c cdbmake.h uint32.h
-	./compile cdbmake_pack.c
-
-cdbmss.o: \
-compile cdbmss.c readwrite.h seek.h alloc.h cdbmss.h cdbmake.h \
-uint32.h substdio.h
-	./compile cdbmss.c
+makelib cdb_make.o cdb_hash.o
+	./makelib cdbmake.a cdb_make.o cdb_hash.o
 
 check: \
-it man
+it man ldap
 	./instcheck
 
+check.o: \
+compile check.c check.h str.h str_len.c
+	./compile $(LDAPFLAGS) check.c
+
+checkpassword.o: \
+compile checkpassword.c auth_mod.h auto_uids.h byte.h check.h env.h \
+error.h fmt.h localdelivery.h passwd.h pbsexec.h prot.h \
+qldap.h qldap-debug.h qldap-errno.h qmail-ldap.h scan.h str.h stralloc.h \
+dns.h ipalloc.h ipme.h ndelay.h qldap-cluster.h readwrite.h select.h \
+timeoutconn.h dirmaker.h mailmaker.h
+	./compile $(LDAPFLAGS) $(LDAPINCLUDES) $(DEBUG) checkpassword.c
+
 chkshsgr: \
 load chkshsgr.o
 	./load chkshsgr 
@@ -334,6 +510,20 @@
 wait.h seek.h qmail.h substdio.h strerr.h substdio.h fmt.h
 	./compile condredirect.c
 
+condwrite: \
+load condwrite.o maildir++.o getln.a stralloc.a alloc.a env.a wait.a \
+seek.a strerr.a substdio.a error.a gfrom.o str.a now.o fs.a mailmaker.o \
+open.a sig.a lock.a auto_qmail.o
+	./load condwrite maildir++.o getln.a stralloc.a alloc.a env.a \
+	wait.a seek.a strerr.a substdio.a error.a gfrom.o str.a now.o \
+	fs.a mailmaker.o open.a sig.a lock.a auto_qmail.o
+
+condwrite.o: \
+compile condwrite.c auto_qmail.h byte.h env.h error.h fmt.h getln.h gfrom.h \
+lock.h maildir++.h now.h open.h qmail-ldap.h seek.h sig.h str.h stralloc.h \
+strerr.h subfd.h substdio.h wait.h mailmaker.h qldap-errno.h
+	./compile $(MDIRMAKE) condwrite.c
+
 config: \
 warn-auto.sh config.sh conf-qmail conf-break conf-split
 	cat warn-auto.sh config.sh \
@@ -386,12 +576,47 @@
 compile datetime_un.c datetime.h
 	./compile datetime_un.c
 
+digest: \
+load digest.o passwd.o digest_md4.o digest_md5.o digest_rmd160.o \
+digest_sha1.o base64.o qldap-debug.o output.o getopt.a strerr.a \
+substdio.a case.a env.a stralloc.a str.a fs.a alloc.a error.a
+	./load digest passwd.o digest_md4.o digest_md5.o digest_rmd160.o \
+	digest_sha1.o base64.o qldap-debug.o output.o getopt.a strerr.a \
+	substdio.a case.a env.a stralloc.a str.a fs.a alloc.a error.a \
+	$(SHADOWLIBS)
+
+digest.o: \
+compile digest.c base64.h error.h passwd.h qldap-errno.h \
+sgetopt.h stralloc.h
+	./compile $(LDAPFLAGS) digest.c
+
+digest_md4.o: \
+compile endian digest_md4.c byte.h digest_md4.h uint32.h
+	./compile $(LDAPFLAGS) `./endian` digest_md4.c
+
+digest_md5.o: \
+compile endian digest_md5.c byte.h digest_md5.h uint32.h
+	./compile $(LDAPFLAGS) `./endian` digest_md5.c
+
+digest_rmd160.o: \
+compile endian digest_rmd160.c byte.h digest_rmd160.h uint32.h
+	./compile $(LDAPFLAGS) `./endian` digest_rmd160.c
+
+digest_sha1.o: \
+compile endian digest_sha1.c byte.h digest_sha1.h uint32.h
+	./compile $(LDAPFLAGS) `./endian` digest_sha1.c
+
 direntry.h: \
 compile trydrent.c direntry.h1 direntry.h2
 	( ./compile trydrent.c >/dev/null 2>&1 \
 	&& cat direntry.h2 || cat direntry.h1 ) > direntry.h
 	rm -f trydrent.o
 
+dirmaker.o: \
+compile dirmaker.c dirmaker.h control.h qldap-debug.h qldap-errno.h \
+stralloc.h wait.h
+	./compile $(HDIRMAKE) $(DEBUG) dirmaker.c
+
 dns.lib: \
 tryrsolv.c compile load socket.lib dns.o ipalloc.o ip.o stralloc.a \
 alloc.a error.a fs.a str.a
@@ -404,7 +629,7 @@
 dns.o: \
 compile dns.c ip.h ipalloc.h ip.h gen_alloc.h fmt.h alloc.h str.h \
 stralloc.h gen_alloc.h dns.h case.h
-	./compile dns.c
+	./compile $(LDAPFLAGS) dns.c
 
 dnscname: \
 load dnscname.o dns.o dnsdoe.o ip.o ipalloc.o stralloc.a alloc.a \
@@ -492,6 +717,14 @@
 	> elq
 	chmod 755 elq
 
+endian: \
+load endian.o
+	./load endian
+
+endian.o: \
+compile endian.c
+	./compile $(LDAPFLAGS) endian.c
+
 env.a: \
 makelib env.o envread.o
 	./makelib env.a env.o envread.o
@@ -536,6 +769,10 @@
 compile except.c fork.h strerr.h wait.h error.h exit.h
 	./compile except.c
 
+execcheck.o: \
+compile execcheck.c execcheck.h case.h env.h qmail.h str.h stralloc.h
+	./compile $(LDAPFLAGS) execcheck.c
+
 fd.a: \
 makelib fd_copy.o fd_move.o
 	./makelib fd.a fd_copy.o fd_move.o
@@ -703,7 +940,7 @@
 
 hier.o: \
 compile hier.c auto_qmail.h auto_split.h auto_uids.h fmt.h fifo.h
-	./compile hier.c
+	./compile $(LDAPFLAGS) $(DEBUG) hier.c
 
 home: \
 home.sh conf-qmail
@@ -741,21 +978,22 @@
 
 install: \
 load install.o fifo.o hier.o auto_qmail.o auto_split.o auto_uids.o \
-strerr.a substdio.a open.a error.a str.a fs.a
+auto_userl.o strerr.a substdio.a open.a error.a str.a fs.a
 	./load install fifo.o hier.o auto_qmail.o auto_split.o \
-	auto_uids.o strerr.a substdio.a open.a error.a str.a fs.a 
+	auto_uids.o auto_userl.o strerr.a substdio.a open.a error.a \
+	str.a fs.a 
 
 install-big: \
 load install-big.o fifo.o install.o auto_qmail.o auto_split.o \
-auto_uids.o strerr.a substdio.a open.a error.a str.a fs.a
+auto_uids.o auto_userl.o strerr.a substdio.a open.a error.a str.a fs.a
 	./load install-big fifo.o install.o auto_qmail.o \
-	auto_split.o auto_uids.o strerr.a substdio.a open.a error.a \
-	str.a fs.a 
+	auto_split.o auto_uids.o auto_userl.o strerr.a substdio.a \
+	open.a error.a str.a fs.a 
 
 install-big.o: \
 compile install-big.c auto_qmail.h auto_split.h auto_uids.h fmt.h \
 fifo.h
-	./compile install-big.c
+	./compile $(LDAPFLAGS) $(DEBUG) install-big.c
 
 install.o: \
 compile install.c substdio.h strerr.h error.h open.h readwrite.h \
@@ -764,9 +1002,9 @@
 
 instcheck: \
 load instcheck.o fifo.o hier.o auto_qmail.o auto_split.o auto_uids.o \
-strerr.a substdio.a error.a str.a fs.a
+auto_userl.o strerr.a substdio.a error.a str.a fs.a
 	./load instcheck fifo.o hier.o auto_qmail.o auto_split.o \
-	auto_uids.o strerr.a substdio.a error.a str.a fs.a 
+	auto_uids.o auto_userl.o strerr.a substdio.a error.a str.a fs.a 
 
 instcheck.o: \
 compile instcheck.c strerr.h error.h readwrite.h exit.h
@@ -783,7 +1021,7 @@
 
 ipme.o: \
 compile ipme.c hassalen.h byte.h ip.h ipalloc.h ip.h gen_alloc.h \
-stralloc.h gen_alloc.h ipme.h ip.h ipalloc.h
+stralloc.h gen_alloc.h ipme.h ip.h
 	./compile ipme.c
 
 ipmeprint: \
@@ -794,7 +1032,7 @@
 
 ipmeprint.o: \
 compile ipmeprint.c subfd.h substdio.h substdio.h ip.h ipme.h ip.h \
-ipalloc.h ip.h gen_alloc.h exit.h
+ip.h gen_alloc.h exit.h
 	./compile ipmeprint.c
 
 it: \
@@ -806,15 +1044,24 @@
 qmail-smtpd sendmail tcp-env qmail-newmrh config config-fast dnscname \
 dnsptr dnsip dnsmxip dnsfq hostname ipmeprint qreceipt qsmhook qbiff \
 forward preline condredirect bouncesaying except maildirmake \
-maildir2mbox maildirwatch qail elq pinq idedit install-big install \
-instcheck home home+df proc proc+df binm1 binm1+df binm2 binm2+df \
-binm3 binm3+df
+maildir2mbox maildirwatch qail elq pinq idedit install-big \
+install instcheck home home+df proc proc+df binm1 \
+binm1+df binm2 binm2+df binm3 binm3+df
 
 load: \
 make-load warn-auto.sh systype
 	( cat warn-auto.sh; ./make-load "`cat systype`" ) > load
 	chmod 755 load
 
+localdelivery.o: \
+compile localdelivery.c localdelivery.h control.h qldap-debug.h
+	./compile $(DEBUG) localdelivery.c
+
+locallookup.o: \
+compile locallookup.c locallookup.h checkpassword.h error.h getln.h \
+localdelivery.h open.h passwd.h substdio.h
+	./compile $(DEBUG) $(SHADOWOPTS) locallookup.c
+
 lock.a: \
 makelib lock_ex.o lock_exnb.o lock_un.o
 	./makelib lock.a lock_ex.o lock_exnb.o lock_un.o
@@ -841,6 +1088,12 @@
 strerr.h
 	./compile maildir.c
 
+maildir++.o: \
+compile maildir++.c maildir++.h readwrite.h stralloc.h error.h str.h \
+open.h substdio.h getln.h error.h strerr.h fmt.h scan.h now.h seek.h \
+sig.h direntry.h
+	./compile $(LDAPFLAGS) maildir++.c
+
 maildir2mbox: \
 load maildir2mbox.o maildir.o prioq.o now.o myctime.o gfrom.o lock.a \
 getln.a env.a open.a strerr.a stralloc.a alloc.a substdio.a error.a \
@@ -890,6 +1143,15 @@
 readwrite.h open.h headerbody.h maildir.h strerr.h
 	./compile maildirwatch.c
 
+mailmagic.o: \
+compile mailmagic.c mailmagic.h byte.h case.h error.h getln.h \
+stralloc.h substdio.h qmail-ldap.h
+	./compile $(LDAPFLAGS) mailmagic.c
+
+mailmaker.o: \
+compile mailmaker.c mailmaker.h error.h open.h qldap-errno.h
+	./compile $(MDIRMAKE) mailmaker.c
+
 mailsubj: \
 warn-auto.sh mailsubj.sh conf-qmail conf-break conf-split
 	cat warn-auto.sh mailsubj.sh \
@@ -918,6 +1180,13 @@
 	cat auto-ccld.sh make-makelib.sh > make-makelib
 	chmod 755 make-makelib
 
+Makefile.cdb-p: \
+Makefile.cdb conf-qmail
+	cat Makefile.cdb \
+	| sed s}%QMAIL%}"`head -1 conf-qmail`"}g \
+	> Makefile.cdb-p
+	chmod 644 Makefile.cdb-p
+
 makelib: \
 make-makelib warn-auto.sh systype
 	( cat warn-auto.sh; ./make-makelib "`cat systype`" ) > \
@@ -992,6 +1261,59 @@
 compile open_write.c open.h
 	./compile open_write.c
 
+output.o: \
+compile output.c output.h stralloc.h substdio.h fmt.h str.h scan.h \
+readwrite.h
+	./compile output.c
+
+passwd.o: \
+compile passwd.c base64.h byte.h case.h digest_md4.h digest_md5.h \
+digest_rmd160.h digest_sha1.h qldap-debug.h qldap-errno.h str.h \
+stralloc.h uint32.h passwd.h
+	./compile $(LDAPFLAGS) $(DEBUG) passwd.c
+
+pbsadd: \
+load pbsadd.o control.o now.o ip.o getln.a open.a env.a stralloc.a \
+alloc.a strerr.a substdio.a error.a str.a fs.a auto_qmail.o socket.lib
+	./load pbsadd control.o now.o ip.o getln.a open.a env.a \
+	stralloc.a alloc.a strerr.a substdio.a error.a str.a fs.a \
+	auto_qmail.o `cat socket.lib`
+
+pbsadd.o: \
+compile pbsadd.c alloc.h auto_qmail.h byte.h control.h env.h error.h \
+exit.h fmt.h ip.h now.h readwrite.h stralloc.h substdio.h
+	./compile pbsadd.c
+
+pbscheck: \
+load pbscheck.o control.o now.o timeoutread.o timeoutwrite.o \
+ip.o getln.a open.a env.a stralloc.a alloc.a strerr.a substdio.a \
+error.a str.a fs.a auto_qmail.o socket.lib
+	./load pbscheck control.o now.o timeoutread.o timeoutwrite.o \
+	ip.o getln.a open.a env.a stralloc.a alloc.a strerr.a substdio.a \
+	error.a str.a fs.a auto_qmail.o `cat socket.lib`
+
+pbscheck.o: \
+compile pbscheck.c alloc.h auto_qmail.h byte.h control.h env.h error.h \
+exit.h fmt.h ip.h now.h readwrite.h str.h stralloc.h substdio.h timeoutread.h \
+timeoutwrite.h
+	./compile pbscheck.c
+
+pbsdbd: \
+load pbsdbd.o control.o now.o ip.o ndelay.a getln.a open.a stralloc.a \
+alloc.a strerr.a substdio.a error.a str.a fs.a auto_qmail.o socket.lib
+	./load pbsdbd control.o now.o ip.o ndelay.a getln.a open.a \
+	stralloc.a alloc.a strerr.a substdio.a error.a str.a fs.a \
+	auto_qmail.o `cat socket.lib`
+
+pbsdbd.o: \
+compile pbsdbd.c alloc.h auto_qmail.h byte.h control.h ip.h ndelay.h \
+now.h stralloc.h strerr.h substdio.h uint32.h
+	./compile pbsdbd.c
+
+pbsexec.o: \
+compile pbsexec.c pbsexec.h open.h qldap-debug.h wait.h
+	./compile $(DEBUG) pbsexec.c
+
 pinq: \
 warn-auto.sh pinq.sh conf-qmail conf-break conf-split
 	cat warn-auto.sh pinq.sh \
@@ -1074,6 +1396,53 @@
 substdio.h open.h byte.h str.h headerbody.h hfield.h env.h exit.h
 	./compile qbiff.c
 
+qldap.a: \
+makelib check.o output.o qldap.o qldap-cluster.o qldap-filter.o \
+qldap-debug.o qldap-errno.o auto_break.o
+	./makelib qldap.a check.o output.o qldap.o qldap-cluster.o \
+	qldap-filter.o qldap-debug.o qldap-errno.o auto_break.o
+
+qldap.o: \
+compile qldap.c qldap.h alloc.h byte.h case.h check.h control.h error.h \
+fmt.h qldap-debug.h qldap-errno.h qmail-ldap.h scan.h str.h stralloc.h
+	./compile $(LDAPFLAGS) $(LDAPINCLUDES) $(DEBUG) qldap.c
+
+qldap-cluster.o: \
+compile qldap-cluster.c qldap-cluster.h constmap.h control.h qldap-debug.h \
+stralloc.h
+	./compile $(LDAPFLAGS) $(DEBUG) qldap-cluster.c
+
+qldap-debug.o: \
+compile qldap-debug.c output.h stralloc.h substdio.h fmt.h str.h readwrite.h \
+error.h qldap-errno.h env.h scan.h qldap-debug.h
+	./compile $(LDAPFLAGS) $(DEBUG) qldap-debug.c
+
+qldap-errno.o: \
+compile qldap-errno.c qldap-errno.h error.h
+	./compile $(LDAPFLAGS) qldap-errno.c
+
+qldap-filter.o: \
+compile qldap-filter.c auto_break.h qldap.h qmail-ldap.h str.h stralloc.h
+	./compile $(LDAPFLAGS) qldap-filter.c
+
+profile: qldap-profile.o
+
+qldap-profile.o: \
+compile qldap-profile.c qldap-profile.h qldap-debug.h
+	./compile $(INCTAI) $(DEBUG) qldap-profile.c 
+
+qmail-cdb: \
+load qmail-cdb.o getln.a open.a cdbmake.a seek.a case.a \
+stralloc.a alloc.a strerr.a substdio.a error.a str.a auto_qmail.o
+	./load qmail-cdb getln.a open.a cdbmake.a seek.a \
+	case.a stralloc.a alloc.a strerr.a substdio.a error.a str.a \
+	auto_qmail.o
+
+qmail-cdb.o: \
+compile qmail-cdb.c auto_qmail.h case.h cdb_make.h exit.h getln.h \
+open.h readwrite.h stralloc.h strerr.h substdio.h uint32.h
+	./compile qmail-cdb.c
+
 qmail-clean: \
 load qmail-clean.o fmtqfn.o now.o getln.a sig.a stralloc.a alloc.a \
 substdio.a error.a str.a fs.a auto_qmail.o auto_split.o
@@ -1089,7 +1458,7 @@
 compile qmail-clean.c readwrite.h sig.h now.h datetime.h str.h \
 direntry.h getln.h stralloc.h gen_alloc.h substdio.h subfd.h \
 substdio.h byte.h scan.h fmt.h error.h exit.h fmtqfn.h auto_qmail.h
-	./compile qmail-clean.c
+	./compile $(LDAPFLAGS) qmail-clean.c
 
 qmail-command.0: \
 qmail-command.8
@@ -1107,6 +1476,18 @@
 	| sed s}SPAWN}"`head -1 conf-spawn`"}g \
 	> qmail-control.5
 
+qmail-forward: \
+load qmail-forward.o qmail.o control.o now.o env.a fd.a wait.a open.a getln.a \
+seek.a stralloc.a alloc.a strerr.a substdio.a error.a str.a fs.a auto_qmail.o
+	./load qmail-forward qmail.o control.o now.o env.a fd.a wait.a \
+	open.a getln.a seek.a strerr.a stralloc.a alloc.a substdio.a \
+	error.a str.a fs.a auto_qmail.o
+	
+qmail-forward.o: \
+compile qmail-forward.c auto_qmail.h control.h error.h fmt.h getln.h now.h \
+qmail.h seek.h str.h stralloc.h strerr.h substdio.h
+	./compile $(LDAPFLAGS) qmail-forward.c
+	
 qmail-getpw: \
 load qmail-getpw.o case.a substdio.a error.a str.a fs.a auto_break.o \
 auto_usera.o
@@ -1131,10 +1512,40 @@
 qlx.h
 	./compile qmail-getpw.c
 
+qmail-group: \
+load qmail-group.o qmail.o now.o control.o case.a getln.a sig.a open.a \
+seek.a fd.a wait.a env.a qldap.a read-ctrl.o stralloc.a alloc.a strerr.a \
+substdio.a error.a fs.a str.a coe.o auto_qmail.o
+	./load qmail-group qmail.o now.o control.o case.a getln.a sig.a \
+	open.a seek.a fd.a wait.a env.a qldap.a read-ctrl.o stralloc.a \
+	alloc.a fs.a strerr.a substdio.a error.a str.a coe.o auto_qmail.o \
+	$(LDAPLIBS) 
+
+qmail-group.o: \
+compile qmail-group.c alloc.h auto_break.h byte.h case.h coe.h control.h \
+env.h error.h fd.h fmt.h getln.h ndelay.h now.h open.h qldap.h qldap-errno.h \
+qmail.h qmail-ldap.h read-ctrl.h seek.h sig.h str.h stralloc.h strerr.h \
+substdio.h wait.h
+	./compile $(LDAPFLAGS) qmail-group.c
+
 qmail-header.0: \
 qmail-header.5
 	nroff -man qmail-header.5 > qmail-header.0
 
+qmail-imapd-ssl.run: \
+qmail-imapd-ssl.sh conf-qmail
+	cat qmail-imapd-ssl.sh \
+	| sed s}%QMAIL%}"`head -1 conf-qmail`"}g \
+	> qmail-imapd-ssl.run
+	chmod 755 qmail-imapd-ssl.run
+
+qmail-imapd.run: \
+qmail-imapd.sh conf-qmail
+	cat qmail-imapd.sh \
+	| sed s}%QMAIL%}"`head -1 conf-qmail`"}g \
+	> qmail-imapd.run
+	chmod 755 qmail-imapd.run
+
 qmail-inject: \
 load qmail-inject.o headerbody.o hfield.o newfield.o quote.o now.o \
 control.o date822fmt.o constmap.o qmail.o case.a fd.a wait.a open.a \
@@ -1171,15 +1582,16 @@
 	> qmail-limits.7
 
 qmail-local: \
-load qmail-local.o qmail.o quote.o now.o gfrom.o myctime.o \
+load qmail-local.o qmail.o quote.o now.o gfrom.o myctime.o mailmaker.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`
+fs.a datetime.a auto_qmail.o auto_patrn.o control.o socket.lib \
+maildir++.o qldap-errno.o
+	./load qmail-local qmail.o quote.o maildir++.o now.o gfrom.o \
+	myctime.o mailmaker.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 qldap-errno.o error.a str.a fs.a datetime.a auto_qmail.o \
+	auto_patrn.o `cat socket.lib`
 
 qmail-local.0: \
 qmail-local.8
@@ -1188,23 +1600,47 @@
 qmail-local.o: \
 compile qmail-local.c readwrite.h sig.h env.h byte.h exit.h fork.h \
 open.h wait.h lock.h seek.h substdio.h getln.h strerr.h subfd.h \
-substdio.h sgetopt.h subgetopt.h alloc.h error.h stralloc.h \
-gen_alloc.h fmt.h str.h now.h datetime.h case.h quote.h qmail.h \
-substdio.h slurpclose.h myctime.h gfrom.h auto_patrn.h
-	./compile qmail-local.c
+sgetopt.h subgetopt.h alloc.h error.h stralloc.h gen_alloc.h fmt.h \
+str.h now.h case.h quote.h qmail.h slurpclose.h myctime.h gfrom.h \
+auto_patrn.h qmail-ldap.h qldap-errno.h auto_qmail.h scan.h maildir++.h \
+mailmaker.h
+	./compile $(LDAPFLAGS) $(MDIRMAKE) qmail-local.c
 
 qmail-log.0: \
 qmail-log.5
 	nroff -man qmail-log.5 > qmail-log.0
 
+qmail-ldaplookup: \
+load qmail-ldaplookup.o qldap.a passwd.o digest_md4.o digest_md5.o \
+digest_rmd160.o digest_sha1.o base64.o constmap.o localdelivery.o \
+dirmaker.o wait.a read-ctrl.o control.o env.a getopt.a getln.a stralloc.a \
+alloc.a strerr.a error.a substdio.a open.a fs.a str.a case.a auto_usera.o \
+auto_qmail.o
+	./load qmail-ldaplookup qldap.a passwd.o digest_md4.o digest_md5.o \
+	digest_rmd160.o digest_sha1.o base64.o constmap.o localdelivery.o \
+	dirmaker.o wait.a read-ctrl.o control.o env.a getopt.a getln.a \
+	stralloc.a alloc.a strerr.a error.a substdio.a open.a fs.a str.a \
+	case.a auto_usera.o auto_qmail.o $(LDAPLIBS) $(SHADOWLIBS)
+
+qmail-ldaplookup.o: \
+compile qmail-ldaplookup.c alloc.h auto_usera.h byte.h case.h env.h error.h \
+localdelivery.h output.h passwd.h qldap.h qldap-cluster.h qldap-debug.h \
+qldap-errno.h qmail-ldap.h read-ctrl.h scan.h sgetopt.h str.h stralloc.h \
+strerr.h subfd.h substdio.h dirmaker.h
+	./compile $(LDAPFLAGS) $(SHADOWOPTS) $(HDIRMAKE) $(DEBUG) \
+	qmail-ldaplookup.c
+
 qmail-lspawn: \
-load qmail-lspawn.o spawn.o prot.o slurpclose.o coe.o sig.a wait.a \
-case.a cdb.a fd.a open.a stralloc.a alloc.a substdio.a error.a str.a \
-fs.a auto_qmail.o auto_uids.o auto_spawn.o
-	./load qmail-lspawn spawn.o prot.o slurpclose.o coe.o \
-	sig.a wait.a case.a cdb.a fd.a open.a stralloc.a alloc.a \
-	substdio.a error.a str.a fs.a auto_qmail.o auto_uids.o \
-	auto_spawn.o 
+load qmail-lspawn.o spawn.o prot.o slurpclose.o coe.o control.o \
+sig.a strerr.a getln.a wait.a case.a cdb.a fd.a open.a stralloc.a \
+alloc.a substdio.a error.a str.a fs.a auto_qmail.o auto_uids.o \
+auto_spawn.o auto_usera.o env.a qldap.a dirmaker.o read-ctrl.o \
+localdelivery.o seek.a constmap.o
+	./load qmail-lspawn spawn.o prot.o slurpclose.o coe.o control.o \
+	qldap.a sig.a strerr.a constmap.o getln.a wait.a case.a cdb.a \
+	fd.a seek.a open.a dirmaker.o read-ctrl.o localdelivery.o env.a \
+	stralloc.a alloc.a substdio.a str.a error.a fs.a auto_qmail.o \
+	auto_uids.o auto_usera.o auto_spawn.o $(LDAPLIBS)
 
 qmail-lspawn.0: \
 qmail-lspawn.8
@@ -1213,15 +1649,19 @@
 qmail-lspawn.o: \
 compile qmail-lspawn.c fd.h wait.h prot.h substdio.h stralloc.h \
 gen_alloc.h scan.h exit.h fork.h error.h cdb.h uint32.h case.h \
-slurpclose.h auto_qmail.h auto_uids.h qlx.h
-	./compile qmail-lspawn.c
+slurpclose.h auto_qmail.h auto_uids.h qlx.h \
+auto_break.h auto_usera.h byte.h check.h env.h fmt.h localdelivery.h \
+open.h qldap.h qldap-debug.h qldap-errno.h qmail-ldap.h read-ctrl.h \
+sig.h str.h qldap-cluster.h getln.h seek.h dirmaker.h
+	./compile $(LDAPFLAGS) $(HDIRMAKE) $(LDAPINCLUDES) $(DEBUG) \
+	qmail-lspawn.c
 
 qmail-newmrh: \
-load qmail-newmrh.o cdbmss.o getln.a open.a cdbmake.a seek.a case.a \
+load qmail-newmrh.o getln.a open.a cdbmake.a seek.a case.a \
 stralloc.a alloc.a strerr.a substdio.a error.a str.a auto_qmail.o
-	./load qmail-newmrh cdbmss.o getln.a open.a cdbmake.a \
-	seek.a case.a stralloc.a alloc.a strerr.a substdio.a \
-	error.a str.a auto_qmail.o 
+	./load qmail-newmrh getln.a open.a cdbmake.a seek.a \
+	case.a stralloc.a alloc.a strerr.a substdio.a error.a \
+	str.a auto_qmail.o 
 
 qmail-newmrh.0: \
 qmail-newmrh.8
@@ -1237,14 +1677,14 @@
 
 qmail-newmrh.o: \
 compile qmail-newmrh.c strerr.h stralloc.h gen_alloc.h substdio.h \
-getln.h exit.h readwrite.h open.h auto_qmail.h cdbmss.h cdbmake.h \
-uint32.h substdio.h
+getln.h exit.h readwrite.h open.h auto_qmail.h cdb_make.h uint32.h \
+substdio.h
 	./compile qmail-newmrh.c
 
 qmail-newu: \
-load qmail-newu.o cdbmss.o getln.a open.a seek.a cdbmake.a case.a \
+load qmail-newu.o getln.a open.a seek.a cdbmake.a case.a \
 stralloc.a alloc.a substdio.a error.a str.a auto_qmail.o
-	./load qmail-newu cdbmss.o getln.a open.a seek.a cdbmake.a \
+	./load qmail-newu getln.a open.a cdbmake.a seek.a \
 	case.a stralloc.a alloc.a substdio.a error.a str.a \
 	auto_qmail.o 
 
@@ -1262,18 +1702,26 @@
 
 qmail-newu.o: \
 compile qmail-newu.c stralloc.h gen_alloc.h subfd.h substdio.h \
-getln.h substdio.h cdbmss.h cdbmake.h uint32.h substdio.h exit.h \
-readwrite.h open.h error.h case.h auto_qmail.h
+getln.h substdio.h cdb_make.h uint32.h substdio.h exit.h readwrite.h \
+open.h error.h case.h auto_qmail.h
 	./compile qmail-newu.c
 
+qmail-pbsdbd.run: \
+qmail-pbsdbd.sh conf-qmail
+	cat qmail-pbsdbd.sh \
+	| sed s}%QMAIL%}"`head -1 conf-qmail`"}g \
+	> qmail-pbsdbd.run
+	chmod 755 qmail-pbsdbd.run
+
 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 \
+maildir.o prioq.o now.o env.a strerr.a sig.a open.a getln.a str.a \
+stralloc.a alloc.a substdio.a error.a fs.a socket.lib maildir++.o \
+seek.a
+	./load qmail-pop3d commands.o maildir++.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`
+	fs.a  seek.a `cat socket.lib`
 
 qmail-pop3d.0: \
 qmail-pop3d.8
@@ -1283,8 +1731,22 @@
 compile qmail-pop3d.c commands.h sig.h getln.h stralloc.h gen_alloc.h \
 substdio.h alloc.h open.h prioq.h datetime.h gen_alloc.h scan.h fmt.h \
 str.h exit.h maildir.h strerr.h readwrite.h timeoutread.h \
-timeoutwrite.h
-	./compile qmail-pop3d.c
+timeoutwrite.h maildir++.h
+	./compile $(LDAPFLAGS) $(MNW) qmail-pop3d.c
+
+qmail-pop3d-ssl.run: \
+qmail-pop3d-ssl.sh conf-qmail
+	cat qmail-pop3d-ssl.sh \
+	| sed s}%QMAIL%}"`head -1 conf-qmail`"}g \
+	> qmail-pop3d-ssl.run
+	chmod 755 qmail-pop3d-ssl.run
+
+qmail-pop3d.run: \
+qmail-pop3d.sh conf-qmail
+	cat qmail-pop3d.sh \
+	| sed s}%QMAIL%}"`head -1 conf-qmail`"}g \
+	> qmail-pop3d.run
+	chmod 755 qmail-pop3d.run
 
 qmail-popup: \
 load qmail-popup.o commands.o timeoutread.o timeoutwrite.o now.o \
@@ -1302,7 +1764,7 @@
 compile qmail-popup.c commands.h fd.h sig.h stralloc.h gen_alloc.h \
 substdio.h alloc.h wait.h str.h byte.h now.h datetime.h fmt.h exit.h \
 readwrite.h timeoutread.h timeoutwrite.h
-	./compile qmail-popup.c
+	./compile $(DEBUG) qmail-popup.c
 
 qmail-pw2u: \
 load qmail-pw2u.o constmap.o control.o open.a getln.a case.a getopt.a \
@@ -1334,11 +1796,13 @@
 qmail-qmqpc: \
 load qmail-qmqpc.o slurpclose.o timeoutread.o timeoutwrite.o \
 timeoutconn.o ip.o control.o auto_qmail.o sig.a ndelay.a open.a \
-getln.a substdio.a stralloc.a alloc.a error.a str.a fs.a socket.lib
+getln.a substdio.a stralloc.a alloc.a error.a str.a fs.a socket.lib \
+dns.lib
 	./load qmail-qmqpc slurpclose.o timeoutread.o \
 	timeoutwrite.o timeoutconn.o ip.o control.o auto_qmail.o \
 	sig.a ndelay.a open.a getln.a substdio.a stralloc.a alloc.a \
-	error.a str.a fs.a  `cat socket.lib`
+	error.a fs.a dns.o str.a ipalloc.o `cat dns.lib` `cat socket.lib` \
+	$(ZLIB)
 
 qmail-qmqpc.0: \
 qmail-qmqpc.8
@@ -1347,15 +1811,15 @@
 qmail-qmqpc.o: \
 compile qmail-qmqpc.c substdio.h getln.h readwrite.h exit.h \
 stralloc.h gen_alloc.h slurpclose.h error.h sig.h ip.h timeoutconn.h \
-timeoutread.h timeoutwrite.h auto_qmail.h control.h fmt.h
-	./compile qmail-qmqpc.c
+timeoutread.h timeoutwrite.h auto_qmail.h control.h fmt.h ipalloc.h
+	./compile $(LDAPFLAGS) $(ZINCLUDES) qmail-qmqpc.c
 
 qmail-qmqpd: \
 load qmail-qmqpd.o received.o now.o date822fmt.o qmail.o auto_qmail.o \
 env.a substdio.a sig.a error.a wait.a fd.a str.a datetime.a fs.a
 	./load qmail-qmqpd received.o now.o date822fmt.o qmail.o \
 	auto_qmail.o env.a substdio.a sig.a error.a wait.a fd.a \
-	str.a datetime.a fs.a 
+	str.a datetime.a fs.a $(ZLIB)
 
 qmail-qmqpd.0: \
 qmail-qmqpd.8
@@ -1364,17 +1828,24 @@
 qmail-qmqpd.o: \
 compile qmail-qmqpd.c auto_qmail.h qmail.h substdio.h received.h \
 sig.h substdio.h readwrite.h exit.h now.h datetime.h fmt.h env.h
-	./compile qmail-qmqpd.c
+	./compile $(LDAPFLAGS) $(ZINCLUDES) qmail-qmqpd.c
+
+qmail-qmqpd.run: \
+qmail-qmqpd.sh conf-qmail
+	cat qmail-qmqpd.sh \
+	| sed s}%QMAIL%}"`head -1 conf-qmail`"}g \
+	> qmail-qmqpd.run
+	chmod 755 qmail-qmqpd.run
 
 qmail-qmtpd: \
 load qmail-qmtpd.o rcpthosts.o control.o constmap.o received.o \
-date822fmt.o now.o qmail.o cdb.a fd.a wait.a datetime.a open.a \
-getln.a sig.a case.a env.a stralloc.a alloc.a substdio.a error.a \
-str.a fs.a auto_qmail.o
+date822fmt.o now.o qmail.o cdb.a fd.a seek.a wait.a datetime.a \
+open.a getln.a sig.a case.a env.a stralloc.a alloc.a substdio.a \
+error.a str.a fs.a auto_qmail.o
 	./load qmail-qmtpd rcpthosts.o control.o constmap.o \
-	received.o date822fmt.o now.o qmail.o cdb.a fd.a wait.a \
-	datetime.a open.a getln.a sig.a case.a env.a stralloc.a \
-	alloc.a substdio.a error.a str.a fs.a auto_qmail.o 
+	received.o date822fmt.o now.o qmail.o cdb.a fd.a seek.a \
+	wait.a datetime.a open.a getln.a sig.a case.a env.a \
+	stralloc.a alloc.a substdio.a error.a str.a fs.a auto_qmail.o 
 
 qmail-qmtpd.0: \
 qmail-qmtpd.8
@@ -1421,11 +1892,12 @@
 qmail-queue: \
 load qmail-queue.o triggerpull.o fmtqfn.o now.o date822fmt.o \
 datetime.a seek.a ndelay.a open.a sig.a alloc.a substdio.a error.a \
-str.a fs.a auto_qmail.o auto_split.o auto_uids.o
-	./load qmail-queue triggerpull.o fmtqfn.o now.o \
-	date822fmt.o datetime.a seek.a ndelay.a open.a sig.a \
-	alloc.a substdio.a error.a str.a fs.a auto_qmail.o \
-	auto_split.o auto_uids.o 
+str.a fs.a auto_qmail.o auto_split.o auto_uids.o control.o constmap.o \
+stralloc.a case.a getln.a
+	./load qmail-queue triggerpull.o fmtqfn.o now.o control.o \
+	constmap.o date822fmt.o datetime.a seek.a ndelay.a open.a sig.a \
+	stralloc.a getln.a case.a alloc.a substdio.a error.a str.a fs.a \
+	auto_qmail.o auto_split.o auto_uids.o 
 
 qmail-queue.0: \
 qmail-queue.8
@@ -1435,18 +1907,37 @@
 compile qmail-queue.c readwrite.h sig.h exit.h open.h seek.h fmt.h \
 alloc.h substdio.h datetime.h now.h datetime.h triggerpull.h extra.h \
 auto_qmail.h auto_uids.h date822fmt.h fmtqfn.h
-	./compile qmail-queue.c
+	./compile $(LDAPFLAGS) qmail-queue.c
+
+qmail-quotawarn: \
+load qmail-quotawarn.o newfield.o now.o date822fmt.o mailmagic.o case.a \
+control.o fd.a wait.a open.a myctime.o case.a getln.a sig.a open.a seek.a \
+lock.a datetime.a env.a stralloc.a alloc.a strerr.a substdio.a error.a str.a \
+fs.a auto_qmail.o
+	./load qmail-quotawarn newfield.o now.o date822fmt.o mailmagic.o \
+	case.a control.o fd.a wait.a open.a myctime.o case.a getln.a sig.a \
+	open.a seek.a lock.a datetime.a env.a stralloc.a alloc.a strerr.a \
+	substdio.a error.a str.a fs.a auto_qmail.o
+
+qmail-quotawarn.o: \
+compile qmail-quotawarn.c auto_qmail.h byte.h case.h control.h date822fmt.h \
+datetime.h env.h error.h exit.h fmt.h getln.h mailmagic.h myctime.h \
+newfield.h now.h open.h qmail-ldap.h seek.h sig.h str.h strerr.h substdio.h \
+wait.h lock.h
+	./compile qmail-quotawarn.c
 
 qmail-remote: \
 load qmail-remote.o control.o constmap.o timeoutread.o timeoutwrite.o \
-timeoutconn.o tcpto.o now.o dns.o ip.o ipalloc.o ipme.o quote.o \
-ndelay.a case.a sig.a open.a lock.a seek.a getln.a stralloc.a alloc.a \
-substdio.a error.a str.a fs.a auto_qmail.o dns.lib socket.lib
+timeoutconn.o tcpto.o now.o dns.o ip.o ipalloc.o ipme.o quote.o xtext.o \
+base64.o ndelay.a case.a sig.a open.a lock.a seek.a getln.a stralloc.a \
+alloc.a strerr.a substdio.a error.a str.a fs.a auto_qmail.o \
+dns.lib socket.lib
 	./load qmail-remote control.o constmap.o timeoutread.o \
 	timeoutwrite.o timeoutconn.o tcpto.o now.o dns.o ip.o \
-	ipalloc.o ipme.o quote.o ndelay.a case.a sig.a open.a \
-	lock.a seek.a getln.a stralloc.a alloc.a substdio.a error.a \
-	str.a fs.a auto_qmail.o  `cat dns.lib` `cat socket.lib`
+	ipalloc.o ipme.o quote.o xtext.o base64.o ndelay.a case.a \
+	sig.a open.a lock.a seek.a getln.a stralloc.a alloc.a \
+	strerr.a substdio.a error.a str.a fs.a auto_qmail.o \
+	`cat dns.lib` `cat socket.lib` $(TLSLIBS) $(ZLIB)
 
 qmail-remote.0: \
 qmail-remote.8
@@ -1458,7 +1949,24 @@
 alloc.h quote.h ip.h ipalloc.h ip.h gen_alloc.h ipme.h ip.h ipalloc.h \
 gen_alloc.h gen_allocdefs.h str.h now.h datetime.h exit.h constmap.h \
 tcpto.h readwrite.h timeoutconn.h timeoutread.h timeoutwrite.h
-	./compile qmail-remote.c
+	./compile $(LDAPFLAGS) $(TLS) $(TLSINCLUDES) $(ZINCLUDES) \
+	qmail-remote.c
+
+qmail-reply: \
+load qmail-reply.o mailmagic.o case.a control.o constmap.o getln.a \
+sig.a newfield.o now.o date822fmt.o datetime.a open.a seek.a env.a \
+qmail.o getopt.a fd.a wait.a digest_md5.o base64.o stralloc.a alloc.a \
+strerr.a substdio.a error.a str.a fs.a auto_qmail.o
+	./load qmail-reply mailmagic.o case.a control.o constmap.o \
+	getln.a sig.a newfield.o now.o date822fmt.o datetime.a open.a \
+	seek.a env.a qmail.o getopt.a fd.a wait.a digest_md5.o base64.o \
+	stralloc.a alloc.a strerr.a substdio.a error.a str.a fs.a auto_qmail.o
+
+qmail-reply.o: \
+compile qmail-reply.c byte.h case.h control.h constmap.h direntry.h env.h \
+error.h exit.h getln.h newfield.h now.h open.h qmail.h qmail-ldap.h \
+readwrite.h seek.h sgetopt.h strerr.h stralloc.h substdio.h uint32.h
+	./compile $(LDAPFLAGS) qmail-reply.c
 
 qmail-rspawn: \
 load qmail-rspawn.o spawn.o tcpto_clean.o now.o coe.o sig.a open.a \
@@ -1478,17 +1986,34 @@
 tcpto.h
 	./compile qmail-rspawn.c
 
+qmail-secretary: \
+load qmail-secretary.o base64.o digest_sha1.o control.o newfield.o now.o \
+date822fmt.o datetime.a mailmaker.o mailmagic.o case.a getln.a qmail.o \
+quote.o getopt.a seek.a fd.a wait.a sig.a open.a stralloc.a env.a alloc.a \
+strerr.a substdio.a error.a str.a fs.a auto_qmail.o
+	./load qmail-secretary base64.o digest_sha1.o control.o newfield.o \
+	now.o date822fmt.o datetime.a mailmaker.o mailmagic.o case.a getln.a \
+	qmail.o quote.o getopt.a seek.a fd.a wait.a sig.a open.a stralloc.a \
+	env.a alloc.a strerr.a substdio.a error.a str.a fs.a auto_qmail.o
+	
+qmail-secretary.o: \
+compile qmail-secretary.c uint32.h base64.h byte.h case.h digest_sha1.h \
+direntry.h env.h error.h fd.h fmt.h getln.h mailmagic.h newfield.h now.h \
+open.h qmail.h quote.h readwrite.h seek.h sgetopt.h sig.h str.h stralloc.h \
+strerr.h substdio.h wait.h qldap-errno.h mailmaker.h
+	./compile $(LDAPFLAGS) $(MDIRMAKE) qmail-secretary.c
+
 qmail-send: \
 load qmail-send.o 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
+datetime.a case.a ndelay.a getln.a wait.a cdb.a seek.a fd.a sig.a \
+open.a lock.a stralloc.a env.a alloc.a substdio.a error.a str.a fs.a \
+auto_qmail.o auto_split.o
 	./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 
+	wait.a cdb.a seek.a fd.a sig.a open.a lock.a stralloc.a env.a \
+	alloc.a substdio.a error.a str.a fs.a auto_qmail.o auto_split.o 
 
 qmail-send.0: \
 qmail-send.8
@@ -1508,8 +2033,8 @@
 substdio.h alloc.h error.h stralloc.h gen_alloc.h str.h byte.h fmt.h \
 scan.h case.h auto_qmail.h trigger.h newfield.h stralloc.h quote.h \
 qmail.h substdio.h qsutil.h prioq.h datetime.h gen_alloc.h constmap.h \
-fmtqfn.h readsubdir.h direntry.h
-	./compile qmail-send.c
+fmtqfn.h readsubdir.h direntry.h cdb.h uint32.h
+	./compile $(LDAPFLAGS) qmail-send.c
 
 qmail-showctl: \
 load qmail-showctl.o auto_uids.o control.o open.a getln.a stralloc.a \
@@ -1532,17 +2057,19 @@
 	./compile qmail-showctl.c
 
 qmail-smtpd: \
-load qmail-smtpd.o rcpthosts.o commands.o timeoutread.o \
+load qmail-smtpd.o rcpthosts.o commands.o timeoutread.o rbl.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 \
+date822fmt.o now.o qmail.o execcheck.o cdb.a smtpcall.o coe.o fd.a \
+seek.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 auto_break.o \
+dns.lib socket.lib
+	./load qmail-smtpd rcpthosts.o commands.o timeoutread.o rbl.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  `cat \
-	socket.lib`
+	received.o date822fmt.o now.o qmail.o execcheck.o cdb.a \
+	smtpcall.o coe.o fd.a seek.a wait.a datetime.a getln.a \
+	open.a sig.a case.a env.a stralloc.a alloc.a substdio.a \
+	error.a fs.a auto_qmail.o dns.o str.a auto_break.o \
+	`cat dns.lib` `cat socket.lib` $(TLSLIBS) $(ZLIB)
 
 qmail-smtpd.0: \
 qmail-smtpd.8
@@ -1553,8 +2080,17 @@
 substdio.h alloc.h auto_qmail.h control.h received.h constmap.h \
 error.h ipme.h ip.h ipalloc.h ip.h gen_alloc.h ip.h qmail.h \
 substdio.h str.h fmt.h scan.h byte.h case.h env.h now.h datetime.h \
-exit.h rcpthosts.h timeoutread.h timeoutwrite.h commands.h
-	./compile qmail-smtpd.c
+exit.h rcpthosts.h timeoutread.h timeoutwrite.h commands.h rbl.h \
+qmail-ldap.h auto_break.h
+	./compile $(LDAPFLAGS) $(TLS) $(TLSINCLUDES) $(ZINCLUDES) \
+	qmail-smtpd.c
+
+qmail-smtpd.run: \
+qmail-smtpd.sh conf-qmail
+	cat qmail-smtpd.sh \
+	| sed s}%QMAIL%}"`head -1 conf-qmail`"}g \
+	> qmail-smtpd.run
+	chmod 755 qmail-smtpd.run
 
 qmail-start: \
 load qmail-start.o prot.o fd.a auto_uids.o
@@ -1574,7 +2110,7 @@
 
 qmail-start.o: \
 compile qmail-start.c fd.h prot.h exit.h fork.h auto_uids.h
-	./compile qmail-start.c
+	./compile $(LDAPFLAGS) qmail-start.c
 
 qmail-tcpok: \
 load qmail-tcpok.o open.a lock.a strerr.a substdio.a error.a str.a \
@@ -1606,6 +2142,20 @@
 fmt.h ip.h lock.h error.h exit.h datetime.h now.h datetime.h
 	./compile qmail-tcpto.c
 
+qmail-todo: \
+load qmail-todo.o control.o constmap.o trigger.o fmtqfn.o now.o \
+readsubdir.o case.a ndelay.a getln.a sig.a cdb.a open.a stralloc.a \
+alloc.a substdio.a error.a str.a seek.a fs.a auto_qmail.o auto_split.o
+	./load qmail-todo control.o constmap.o trigger.o fmtqfn.o now.o \
+	readsubdir.o case.a ndelay.a getln.a sig.a cdb.a open.a stralloc.a \
+	alloc.a substdio.a error.a str.a seek.a fs.a auto_qmail.o auto_split.o
+
+qmail-todo.o: \
+compile qmail-todo.c alloc.h auto_qmail.h byte.h cdb.h constmap.h control.h \
+direntry.h error.h exit.h fmt.h fmtqfn.h getln.h open.h ndelay.h now.h \
+readsubdir.h scan.h select.h sig.h str.h stralloc.h substdio.h trigger.h
+	./compile $(LDAPFLAGS) qmail-todo.c
+
 qmail-upq: \
 warn-auto.sh qmail-upq.sh conf-qmail conf-break conf-split
 	cat warn-auto.sh qmail-upq.sh \
@@ -1627,6 +2177,22 @@
 	| sed s}SPAWN}"`head -1 conf-spawn`"}g \
 	> qmail-users.5
 
+qmail-verify: \
+load qmail-verify.o qldap.a read-ctrl.o control.o getln.a substdio.a \
+stralloc.a env.a alloc.a error.a open.a fs.a case.a cdb.a str.a timeoutread.o \
+localdelivery.o auto_qmail.o
+	./load qmail-verify qldap.a read-ctrl.o control.o getln.a \
+	substdio.a stralloc.a env.a alloc.a error.a open.a fs.a case.a \
+	cdb.a str.a seek.a timeoutread.o localdelivery.o auto_qmail.o \
+	$(LDAPLIBS)
+
+qmail-verify.o: \
+compile qmail-verify.c auto_break.h byte.h case.h cdb.h error.h getln.h \
+localdelivery.h open.h output.h qldap.h qldap-debug.h qldap-errno.h \
+qmail-ldap.h read-ctrl.h str.h stralloc.h subfd.h substdio.h \
+timeoutread.h
+	./compile $(LDAPFLAGS) $(DEBUG) qmail-verify.c
+
 qmail.0: \
 qmail.7
 	nroff -man qmail.7 > qmail.0
@@ -1634,7 +2200,14 @@
 qmail.o: \
 compile qmail.c substdio.h readwrite.h wait.h exit.h fork.h fd.h \
 qmail.h substdio.h auto_qmail.h
-	./compile qmail.c
+	./compile $(LDAPFLAGS) qmail.c
+
+qmail.run: \
+qmail.sh conf-qmail
+	cat qmail.sh \
+	| sed s}%QMAIL%}"`head -1 conf-qmail`"}g \
+	> qmail.run
+	chmod 755 qmail.run
 
 qreceipt: \
 load qreceipt.o headerbody.o hfield.o quote.o token822.o qmail.o \
@@ -1676,6 +2249,10 @@
 compile quote.c stralloc.h gen_alloc.h str.h quote.h
 	./compile quote.c
 
+rbl.o: \
+compile rbl.c dns.h env.h ipalloc.h qmail.h rbl.h stralloc.h
+	./compile rbl.c
+
 rcpthosts.o: \
 compile rcpthosts.c cdb.h uint32.h byte.h open.h error.h control.h \
 constmap.h stralloc.h gen_alloc.h rcpthosts.h
@@ -1686,6 +2263,14 @@
 auto_split.h
 	./compile readsubdir.c
 
+readwrite.o: \
+compile readwrite.c readwrite.h
+	./compile readwrite.c
+
+read-ctrl.o: \
+compile read-ctrl.c auto_qmail.h error.h open.h read-ctrl.h
+	./compile read-ctrl.c
+
 received.o: \
 compile received.c fmt.h qmail.h substdio.h now.h datetime.h \
 datetime.h date822fmt.h received.h
@@ -1743,7 +2328,7 @@
 	./compile sendmail.c
 
 setup: \
-it man
+it man ldap
 	./install
 
 sgetopt.o: \
@@ -1795,9 +2380,8 @@
 auto-int8.c auto-gid.c auto-uid.c hier.c install.c instcheck.c \
 install-big.c alloc.3 alloc.h alloc.c alloc_re.c case.3 case.h \
 case_diffb.c case_diffs.c case_lowerb.c case_lowers.c case_starts.c \
-cdb.3 cdb.h cdb_hash.c cdb_seek.c cdb_unpack.c cdbmake.h \
-cdbmake_add.c cdbmake_hash.c cdbmake_pack.c cdbmss.h cdbmss.c coe.3 \
-coe.h coe.c fd.h fd_copy.3 fd_copy.c fd_move.3 fd_move.c fifo_make.3 \
+cdb.3 cdb.c cdb.h cdb_hash.c cdb_make.c cdb_make.h coe.3 coe.h \
+coe.c fd.h fd_copy.3 fd_copy.c fd_move.3 fd_move.c fifo_make.3 \
 fifo.h fifo.c trymkffo.c fork.h1 fork.h2 tryvfork.c now.3 now.h now.c \
 open.h open_append.c open_excl.c open_read.c open_trunc.c \
 open_write.c seek.h seek_cur.c seek_end.c seek_set.c seek_trunc.c \
@@ -1883,6 +2467,11 @@
 error.h
 	./compile slurpclose.c
 
+smtpcall.o: \
+compile smtpcall.c auto_qmail.h coe.h fd.h substdio.h str.h stralloc.h \
+timeoutread.h timeoutwrite.h wait.h smtpcall.h
+	./compile smtpcall.c
+
 socket.lib: \
 trylsock.c compile load
 	( ( ./compile trylsock.c && \
@@ -1895,7 +2484,7 @@
 stralloc.h gen_alloc.h select.h exit.h coe.h open.h error.h \
 auto_qmail.h auto_uids.h auto_spawn.h
 	./chkspawn
-	./compile spawn.c
+	./compile $(DEBUG) spawn.c
 
 splogger: \
 load splogger.o substdio.a error.a str.a fs.a syslog.lib socket.lib
@@ -1914,10 +2503,10 @@
 str.a: \
 makelib str_len.o str_diff.o str_diffn.o str_cpy.o str_chr.o \
 str_rchr.o str_start.o byte_chr.o byte_rchr.o byte_diff.o byte_copy.o \
-byte_cr.o byte_zero.o
+byte_cr.o byte_zero.o byte_repl.o
 	./makelib str.a str_len.o str_diff.o str_diffn.o str_cpy.o \
 	str_chr.o str_rchr.o str_start.o byte_chr.o byte_rchr.o \
-	byte_diff.o byte_copy.o byte_cr.o byte_zero.o
+	byte_diff.o byte_copy.o byte_cr.o byte_zero.o byte_repl.o
 
 str_chr.o: \
 compile str_chr.c str.h
@@ -2036,10 +2625,10 @@
 
 substdio.a: \
 makelib substdio.o substdi.o substdo.o subfderr.o subfdout.o \
-subfdouts.o subfdin.o subfdins.o substdio_copy.o
+subfdouts.o subfdin.o subfdins.o substdio_copy.o readwrite.o
 	./makelib substdio.a substdio.o substdi.o substdo.o \
 	subfderr.o subfdout.o subfdouts.o subfdin.o subfdins.o \
-	substdio_copy.o
+	substdio_copy.o readwrite.o
 
 substdio.o: \
 compile substdio.c substdio.h
@@ -2139,3 +2728,28 @@
 wait_pid.o: \
 compile wait_pid.c error.h haswaitp.h
 	./compile wait_pid.c
+
+xtext.o: \
+compile xtext.c xtext.h stralloc.h
+	./compile xtext.c
+
+cert:
+	$(OPENSSLBIN) req -new -x509 -nodes \
+	-out `head -1 conf-qmail`/control/cert.pem -days 366 \
+	-keyout `head -1 conf-qmail`/control/cert.pem
+	chmod 640 `head -1 conf-qmail`/control/cert.pem
+	chown qmaild:qmail `head -1 conf-qmail`/control/cert.pem
+
+cert-req:
+	$(OPENSSLBIN) req -new -nodes \
+	-out req.pem \
+	-keyout `head -1 conf-qmail`/control/cert.pem
+	chmod 640 `head -1 conf-qmail`/control/cert.pem
+	chown qmaild:qmail `head -1 conf-qmail`/control/cert.pem
+	@echo
+	@echo "Send req.pem to your CA to obtain signed_req.pem, and do:"
+	@echo "cat signed_req.pem >> `head -1 conf-qmail`/control/cert.pem"
+
+backup: \
+clean
+	tar cf $(BACKUPPATH) .
diff -ruN qmail-1.03-orig/Makefile.cdb qmail-1.03-ldap-20060201-orig/Makefile.cdb
--- qmail-1.03-orig/Makefile.cdb	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/Makefile.cdb	2006-02-25 11:00:55.000000000 +0100
@@ -0,0 +1,60 @@
+#
+# Copyright (c) 2003-2004 Andre Oppermann, Claudio Jeker,
+#      Internet Business Solutions AG, CH-8005 Zürich, Switzerland
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+#    must display the following acknowledgement:
+#      This product includes software developed by Internet Business
+#      Solutions AG and its contributors.
+# 4. Neither the name of the author nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+
+
+# Simple Makefile to keep cdb databases up to date
+# This Makefile assumes that tcprules and qmail-cdb are in your $PATH
+# if not edit the next two lines.
+TCPRULES=tcprules
+QMAILRULES="%QMAIL%/bin/qmail-cdb"
+
+FILES=	locals.cdb rcpthosts.cdb qmail-smtpd.cdb qmail-qmqpd.cdb \
+	qmail-pop3d.cdb qmail-imapd.cdb
+
+TMPFILE=rules.tmp
+
+.SUFFIXES: .cdb .rules
+
+all: $(FILES)
+	@rm -f $(TMPFILE)
+
+# locals and rcpthosts are special cases...
+locals.cdb: locals
+	$(QMAILRULES) locals.cdb $(TMPFILE) < locals
+
+rcpthosts.cdb: rcpthosts
+	$(QMAILRULES) rcpthosts.cdb $(TMPFILE) < rcpthosts
+
+.rules.cdb:
+	$(TCPRULES) $@ $(TMPFILE) < $<
+
diff -ruN qmail-1.03-orig/myctime.c qmail-1.03-ldap-20060201-orig/myctime.c
--- qmail-1.03-orig/myctime.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/myctime.c	2006-02-25 11:00:55.000000000 +0100
@@ -2,10 +2,10 @@
 #include "fmt.h"
 #include "myctime.h"
 
-static char *daytab[7] = {
+static const char *daytab[7] = {
 "Sun","Mon","Tue","Wed","Thu","Fri","Sat"
 };
-static char *montab[12] = {
+static const char *montab[12] = {
 "Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"
 };
 
diff -ruN qmail-1.03-orig/myctime.h qmail-1.03-ldap-20060201-orig/myctime.h
--- qmail-1.03-orig/myctime.h	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/myctime.h	2006-02-25 11:00:55.000000000 +0100
@@ -1,6 +1,8 @@
 #ifndef MYCTIME_H
 #define MYCTIME_H
 
-extern char *myctime();
+#include "datetime.h"
+
+extern char *myctime(datetime_sec);
 
 #endif
diff -ruN qmail-1.03-orig/ndelay.h qmail-1.03-ldap-20060201-orig/ndelay.h
--- qmail-1.03-orig/ndelay.h	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/ndelay.h	2006-02-25 11:00:55.000000000 +0100
@@ -1,7 +1,7 @@
 #ifndef NDELAY_H
 #define NDELAY_H
 
-extern int ndelay_on();
-extern int ndelay_off();
+extern int ndelay_on(int fd);
+extern int ndelay_off(int fd);
 
 #endif
diff -ruN qmail-1.03-orig/newfield.c qmail-1.03-ldap-20060201-orig/newfield.c
--- qmail-1.03-orig/newfield.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/newfield.c	2006-02-25 11:00:55.000000000 +0100
@@ -1,3 +1,5 @@
+#include <sys/types.h>
+#include <unistd.h>
 #include "fmt.h"
 #include "datetime.h"
 #include "stralloc.h"
@@ -25,7 +27,7 @@
 
 static unsigned int msgidfmt(s,idhost,idhostlen,when)
 char *s;
-char *idhost;
+const char *idhost;
 int idhostlen;
 datetime_sec when;
 {
@@ -58,7 +60,7 @@
 }
 
 int newfield_msgidmake(idhost,idhostlen,when)
-char *idhost;
+const char *idhost;
 int idhostlen;
 datetime_sec when;
 {
diff -ruN qmail-1.03-orig/newfield.h qmail-1.03-ldap-20060201-orig/newfield.h
--- qmail-1.03-orig/newfield.h	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/newfield.h	2006-02-25 11:00:55.000000000 +0100
@@ -1,12 +1,13 @@
 #ifndef NEWFIELD_H
 #define NEWFIELD_H
 
+#include "datetime.h"
 #include "stralloc.h"
 
 extern stralloc newfield_date;
-extern int newfield_datemake();
+extern int newfield_datemake(datetime_sec);
 
 extern stralloc newfield_msgid;
-extern int newfield_msgidmake();
+extern int newfield_msgidmake(const char *, int, datetime_sec);
 
 #endif
diff -ruN qmail-1.03-orig/now.c qmail-1.03-ldap-20060201-orig/now.c
--- qmail-1.03-orig/now.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/now.c	2006-02-25 11:00:55.000000000 +0100
@@ -2,7 +2,7 @@
 #include "datetime.h"
 #include "now.h"
 
-datetime_sec now()
+datetime_sec now(void)
 {
-  return time((long *) 0);
+  return time((void *)0);
 }
diff -ruN qmail-1.03-orig/now.h qmail-1.03-ldap-20060201-orig/now.h
--- qmail-1.03-orig/now.h	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/now.h	2006-02-25 11:00:55.000000000 +0100
@@ -3,6 +3,6 @@
 
 #include "datetime.h"
 
-extern datetime_sec now();
+extern datetime_sec now(void);
 
 #endif
diff -ruN qmail-1.03-orig/open_append.c qmail-1.03-ldap-20060201-orig/open_append.c
--- qmail-1.03-orig/open_append.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/open_append.c	2006-02-25 11:00:55.000000000 +0100
@@ -2,5 +2,5 @@
 #include <fcntl.h>
 #include "open.h"
 
-int open_append(fn) char *fn;
+int open_append(fn) const char *fn;
 { return open(fn,O_WRONLY | O_NDELAY | O_APPEND | O_CREAT,0600); }
diff -ruN qmail-1.03-orig/open_excl.c qmail-1.03-ldap-20060201-orig/open_excl.c
--- qmail-1.03-orig/open_excl.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/open_excl.c	2006-02-25 11:00:55.000000000 +0100
@@ -2,5 +2,5 @@
 #include <fcntl.h>
 #include "open.h"
 
-int open_excl(fn) char *fn;
+int open_excl(fn) const char *fn;
 { return open(fn,O_WRONLY | O_EXCL | O_CREAT,0644); }
diff -ruN qmail-1.03-orig/open.h qmail-1.03-ldap-20060201-orig/open.h
--- qmail-1.03-orig/open.h	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/open.h	2006-02-25 11:00:55.000000000 +0100
@@ -1,10 +1,10 @@
 #ifndef OPEN_H
 #define OPEN_H
 
-extern int open_read();
-extern int open_excl();
-extern int open_append();
-extern int open_trunc();
-extern int open_write();
+extern int open_read(const char *);
+extern int open_excl(const char *);
+extern int open_append(const char *);
+extern int open_trunc(const char *);
+extern int open_write(const char *);
 
 #endif
diff -ruN qmail-1.03-orig/open_read.c qmail-1.03-ldap-20060201-orig/open_read.c
--- qmail-1.03-orig/open_read.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/open_read.c	2006-02-25 11:00:55.000000000 +0100
@@ -2,5 +2,5 @@
 #include <fcntl.h>
 #include "open.h"
 
-int open_read(fn) char *fn;
+int open_read(fn) const char *fn;
 { return open(fn,O_RDONLY | O_NDELAY); }
diff -ruN qmail-1.03-orig/open_trunc.c qmail-1.03-ldap-20060201-orig/open_trunc.c
--- qmail-1.03-orig/open_trunc.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/open_trunc.c	2006-02-25 11:00:55.000000000 +0100
@@ -2,5 +2,5 @@
 #include <fcntl.h>
 #include "open.h"
 
-int open_trunc(fn) char *fn;
+int open_trunc(fn) const char *fn;
 { return open(fn,O_WRONLY | O_NDELAY | O_TRUNC | O_CREAT,0644); }
diff -ruN qmail-1.03-orig/open_write.c qmail-1.03-ldap-20060201-orig/open_write.c
--- qmail-1.03-orig/open_write.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/open_write.c	2006-02-25 11:00:55.000000000 +0100
@@ -2,5 +2,5 @@
 #include <fcntl.h>
 #include "open.h"
 
-int open_write(fn) char *fn;
+int open_write(fn) const char *fn;
 { return open(fn,O_WRONLY | O_NDELAY); }
diff -ruN qmail-1.03-orig/output.c qmail-1.03-ldap-20060201-orig/output.c
--- qmail-1.03-orig/output.c	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/output.c	2006-02-25 11:00:55.000000000 +0100
@@ -0,0 +1,181 @@
+/*
+ * Copyright (c) 2001-2004 Claudio Jeker,
+ *      Internet Business Solutions AG, CH-8005 Zürich, Switzerland
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Internet Business
+ *      Solutions AG and its contributors.
+ * 4. Neither the name of the author nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#include "stralloc.h"
+#include "substdio.h"
+#include "fmt.h"
+#include "str.h"
+#include "scan.h"
+#include "output.h"
+
+#include <stdarg.h>
+
+char num[FMT_ULONG];
+
+static const char nullString[] = "(null pointer)";
+static const char ioHexArray[] = "0123456789abcdef";
+
+static int fmt_hexulong(char *s, unsigned long x) 
+	/* s has to be allready allocated, use at least FMT_ULONG chars 
+	 * 40 chars should be enough for a 20 byte unsigned long (2^160) 
+	 * so djb's fmt_ulong would first fail ;-) */
+{
+	unsigned int i;
+
+	for (i = 0; i < sizeof(unsigned long) * 2; i++) {
+		*s++ = (ioHexArray[(x >> (sizeof(unsigned long)*8 - 4)) & 0xf]);
+		x = x << 4;
+	}
+	return sizeof(unsigned long) * 2;
+}
+
+void va_output(substdio *ss, char const *fmt, va_list args)
+/*
+ * works like vprintf has the format options %i, ...
+ * all flags (#, 0, -, ' ', +, ' ... ) are not supported if not special noted
+ * Also not supported are all options for foating-point numbers 
+ * (not needed in qmail)
+ * Supported conversion specifiers: diouxcsSp%
+ * diux are for integer (long) conversions
+ * c is a single unsigned char
+ * s is a zero terminated string
+ * S is a stralloc object (should not be zero terminated (else the zero 
+ *   will be printed))
+ * p is the hex address of a generic pointer (void *)
+ * % is the % sign
+ */
+{
+	unsigned long ul;
+	long l;
+	char *s;
+	char const *start;
+	char const *cur;
+	void *p;
+	unsigned char c;
+	stralloc *sa;
+
+	start = fmt;
+	cur = fmt;
+	if (!cur) return;
+	while (*cur) {
+		if (*cur == '%') {
+			if ( substdio_put(ss, start, cur-start) == -1 ) return;
+			/*
+			 * no need to care if the output is save qmail-send
+			 * looks if the output is save
+			 */
+			cur++;
+			switch (*cur) {
+			case 'd':
+			case 'i':
+				l = va_arg(args, long);
+				if (l < 0) {
+					/* negativ number, d and i are signed */
+					l *= -1;
+					if (substdio_put(ss, "-", 1) == -1)
+						return;
+				}
+				ul = (unsigned long)l;
+				if (substdio_put(ss, num, fmt_ulong(num, ul))) 
+					return;
+				break;
+			case 'u':
+				ul = va_arg(args, unsigned long);
+				if (substdio_put(ss, num, fmt_ulong(num, ul))) 
+					return;
+				break;
+			case 's':
+				s = va_arg(args, char *);
+				if (!s) {
+					if (substdio_put(ss, nullString, 
+						    str_len(nullString))) 
+						return;
+					break;
+				}
+				if (substdio_put(ss, s, str_len(s))) return;
+				break;
+			case 'S':
+				sa = va_arg(args, stralloc *);
+				if (!sa) {
+					if (substdio_put(ss, nullString, 
+						    str_len(nullString)))
+						return;
+					break;
+				}
+				if (substdio_put(ss, sa->s, sa->len))
+					return;
+				break;
+			case '%':
+				if (substdio_put(ss, "%", 1) == -1)
+					return;
+				break;
+			case 'p':
+				p = va_arg(args, void *);
+				ul = (unsigned long)p;
+				if (substdio_put(ss, "0x", 2)) return;
+				if (substdio_put(ss, num,
+					    fmt_hexulong(num, ul))) 
+					return;
+				break;
+			case 'x':
+				ul = va_arg(args, unsigned long);
+				if (substdio_put(ss, "0x", 2)) return;
+				if (substdio_put(ss, num,
+					    fmt_hexulong(num, ul))) 
+					return;
+				break;
+			case 'c':
+				c = (unsigned char)
+				    va_arg(args, unsigned int);
+				substdio_BPUTC(ss, c);
+				break;
+			}
+			start = ++cur; 
+		} else {
+			++cur;
+		}
+	}
+	if (substdio_put(ss, start, cur-start) == -1) return;
+}
+
+void output(substdio *ss, char const *fmt, ...)
+	/* see va_output */
+{
+	va_list args;
+
+	va_start(args,fmt);
+	va_output(ss, fmt, args);
+	va_end(args);
+	if (substdio_flush(ss) == -1) return; 
+}
+
diff -ruN qmail-1.03-orig/output.h qmail-1.03-ldap-20060201-orig/output.h
--- qmail-1.03-orig/output.h	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/output.h	2006-02-25 11:00:55.000000000 +0100
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2001-2004 Claudio Jeker,
+ *      Internet Business Solutions AG, CH-8005 Zürich, Switzerland
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Internet Business
+ *      Solutions AG and its contributors.
+ * 4. Neither the name of the author nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#ifndef __OUTPUT_H__
+#define __OUTPUT_H__
+
+#include <stdarg.h>
+#include "substdio.h"
+
+#define STDERR 2
+#define STDOUT 1
+#define STDIN  0
+
+void va_output(substdio *ss, char const *fmt, va_list args);
+/*
+ * works like printf has the format options %i, ...
+ * all flags (#, 0, -, ' ', +, ' ... ) are not supported
+ * Also not supported are all options for foating-point numbers 
+ * (not needed in qmail)
+ * Supported conversion specifiers: diuxcsSp%
+ * diux are for integer (long) conversions (di are signed all other unsigned)
+ * c is a single unsigned char
+ * s is a zero terminated string
+ * S is a stralloc object (should not be zero terminated (else the zero 
+ *   will be printed))
+ * p is the hex address of a generic pointer (void *)
+ * % is the % sign
+ */
+
+void output(substdio *ss, char const *fmt, ...);
+
+#endif
diff -ruN qmail-1.03-orig/passwd.c qmail-1.03-ldap-20060201-orig/passwd.c
--- qmail-1.03-orig/passwd.c	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/passwd.c	2006-02-25 11:00:55.000000000 +0100
@@ -0,0 +1,360 @@
+/*
+ * Copyright (c) 2003-2004 Claudio Jeker,
+ *      Internet Business Solutions AG, CH-8005 Zürich, Switzerland
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Internet Business
+ *      Solutions AG and its contributors.
+ * 4. Neither the name of the author nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#ifdef linux
+#define _XOPEN_SOURCE
+#endif
+#include <unistd.h>
+#include "base64.h"
+#include "byte.h"
+#include "case.h"
+#include "digest_md4.h"
+#include "digest_md5.h"
+#include "digest_rmd160.h"
+#include "digest_sha1.h"
+#include "qldap-debug.h"
+#include "qldap-errno.h"
+#include "str.h"
+#include "stralloc.h"
+
+#include "passwd.h"
+
+static stralloc hashed = {0};
+static stralloc salt = {0};
+static stralloc intermediate = {0};
+static stralloc cryptformat = {0};
+
+static int do_crypt(char *, char *);
+static int do_md4(char *, char *);
+static int do_md5(char *, char *);
+static int do_nsmta_md5(char *, char *);
+static int do_smd5(char *, char *);
+static int do_sha1(char *, char *);
+static int do_ssha1(char *, char *);
+static int do_rmd160(char *, char *);
+
+static struct func {
+	const char	*scheme;
+	unsigned int	slen;
+	int		(*func)(char *, char *);
+} algo[] = {
+	{ "{crypt}",	7, do_crypt },
+	{ "{md4}",	5, do_md4 },
+	{ "{md5}",	5, do_md5 },
+	{ "{ns-mta-md5}", 12, do_nsmta_md5 },
+	{ "{smd5}",	6, do_smd5 },
+	{ "{sha}",	5, do_sha1 },
+	{ "{ssha}",	6, do_ssha1 },
+	{ "{rmd160}",	8, do_rmd160 },
+	{ 0,		0, 0 }
+};
+
+/* return zero on success else the error number */
+int
+cmp_passwd(char *clear, char *encrypted)
+{
+	int	i, r;
+
+	for (i = 0; algo[i].scheme != 0; i++) {
+		if (case_diffb(encrypted, algo[i].slen, algo[i].scheme) == 0) {
+			encrypted += algo[i].slen;
+			r = algo[i].func(clear, encrypted);
+			if (r != OK) return r;
+			logit(256, "cpm_passwd: comparing hashed %s"
+			    "passwd (%S == %s)\n", 
+			    algo[i].scheme, hashed, encrypted);
+			if (str_diffn(hashed.s, encrypted, hashed.len) == 0 &&
+			    encrypted[hashed.len] == 0)
+				return OK;
+			/* hashed passwds are equal */
+			return BADPASS;
+		}
+	}
+	logit(256, "cpm_passwd: comparing crypt(3) passwd (%s == %s)\n", 
+	    crypt(clear,encrypted), encrypted);
+	if (str_diff(encrypted, crypt(clear,encrypted)) == 0)
+		return OK;
+#ifdef CLEARTEXTPASSWD
+#warning ___CLEARTEXT_PASSWORD_SUPPORT_IS_ON___
+	/* CLEARTEXTPASSWD ARE NOT GOOD */
+	/* so they are disabled by default */
+	if (str_diff(encrypted, clear) == 0)
+		return OK;
+#endif
+	return BADPASS;
+}
+
+int
+make_passwd(const char *want, char *clear, stralloc *result)
+{
+	int	i, r;
+
+	for (i = 0; algo[i].scheme != 0; i++) {
+		if (case_diffb(want, algo[i].slen, algo[i].scheme) == 0) {
+			r = algo[i].func(clear, (char *) 0);
+			if (r != OK) return r;
+			if (!stralloc_copy(result, &hashed)) return ERRNO;
+			return OK;
+		}
+	}
+	return NOSUCH;
+}
+
+int
+feed_salt(char *b, int l)
+{
+	if (!stralloc_copyb(&salt, b, l)) return ERRNO;
+	return OK;
+}
+
+void
+feed_crypt(const char *format)
+{
+	unsigned int len, slen;
+	
+	len = str_chr(format, 'X');
+	if (format[len] != 'X') goto fail;
+	if (!stralloc_copyb(&cryptformat, format, len)) goto fail;
+	for (slen = len; format[slen] == 'X'; slen++) ;
+	slen -= len;
+	if (slen * 3 > salt.len * 4) goto fail; /* slen is in base64 but salt
+						   is not. The conversion isn't
+						   100% correct but close
+						   enough. */
+	if (b64_ntops(salt.s, slen, &intermediate) == -1) goto fail;
+	if (!stralloc_catb(&cryptformat, intermediate.s, slen)) goto fail;
+	if (!stralloc_0(&cryptformat)) goto fail;
+	return;
+	
+fail:
+       	/* crypt will fail later */
+	if (!stralloc_copys(&cryptformat, "")) return;
+	if (!stralloc_copys(&intermediate, "")) return;
+}
+
+static int
+do_crypt(char *clear, char *encrypted)
+{
+	if (encrypted) {
+		if (!stralloc_copys(&hashed, crypt(clear, encrypted)))
+			return ERRNO;
+	} else {
+		/* salt and prefix */
+		if (cryptformat.s == 0 || cryptformat.len == 0)
+			return ILLVAL;
+		if (!stralloc_copys(&hashed, crypt(clear, cryptformat.s)))
+			return ERRNO;
+	}
+	return OK;
+}
+
+static int
+do_md4(char *clear, char *encrypted)
+{
+	MD4_CTX ctx;
+	unsigned char buffer[MD4_LEN];
+
+	/* not slated */
+	MD4Init(&ctx);
+	MD4Update(&ctx, clear, str_len(clear));
+	MD4Final(buffer,&ctx);
+	if (b64_ntops(buffer, sizeof(buffer), &hashed) == -1) return ERRNO;
+
+	return OK;
+}
+
+static int
+do_md5(char *clear, char *encrypted)
+{
+	MD5_CTX ctx;
+	unsigned char buffer[MD5_LEN];
+
+	MD5Init(&ctx);
+	MD5Update(&ctx, clear, str_len(clear));
+	MD5Final(buffer,&ctx);
+	if (b64_ntops(buffer, sizeof(buffer), &hashed) == -1) return ERRNO;
+
+	return OK;
+}
+
+static int
+do_nsmta_md5(char *clear, char *encrypted)
+{
+/*
+ * Netscape MTA MD5 as found in Netscape MailServer < 2.02 and 
+ * Software.com's Post.Office
+ */
+	MD5_CTX ctx;
+	unsigned char buffer[MD5_LEN];
+	unsigned char c;
+
+	/* NS-MTA-MD5 */
+	if (encrypted) {
+		if (str_len(encrypted) != 64)
+			return BADVAL;
+	
+		MD5Init(&ctx);
+		MD5Update(&ctx, &encrypted[32], 32);
+		c = 89;
+		MD5Update(&ctx, &c, 1);
+		MD5Update(&ctx, clear, str_len(clear));
+		c = 247;
+		MD5Update(&ctx, &c, 1);
+		MD5Update(&ctx, &encrypted[32], 32);
+		MD5Final(buffer, &ctx);
+
+		if (hex_ntops(buffer, sizeof(buffer), &hashed) == -1)
+			return ERRNO;
+		if (!stralloc_catb(&hashed, &encrypted[32], 32)) return ERRNO;
+		
+		return OK;
+	} else {
+		if (salt.s == 0 || salt.len < 16)
+			return FAILED;
+		if (hex_ntops(salt.s, 16, &intermediate) == -1) return ERRNO;
+		if (intermediate.len != 32) return FAILED;
+		
+		MD5Init(&ctx);
+		MD5Update(&ctx, intermediate.s, 32);
+		c = 89;
+		MD5Update(&ctx, &c, 1);
+		MD5Update(&ctx, clear, str_len(clear));
+		c = 247;
+		MD5Update(&ctx, &c, 1);
+		MD5Update(&ctx, intermediate.s, 32);
+		MD5Final(buffer, &ctx);
+
+		if (hex_ntops(buffer, sizeof(buffer), &hashed) == -1)
+			return ERRNO;
+		if (!stralloc_cat(&hashed, &intermediate)) return ERRNO;
+		
+		return OK;
+	}
+}
+
+static int
+do_smd5(char *clear, char *encrypted)
+{
+	MD5_CTX ctx;
+	
+	if (encrypted) {
+		if (b64_ptons(encrypted, &salt) == -1)
+			return BADVAL;
+
+		MD5Init(&ctx);
+		MD5Update(&ctx, clear, str_len(clear));
+		MD5Update(&ctx, salt.s + MD5_LEN, salt.len - MD5_LEN);
+		MD5Final(salt.s,&ctx);
+		if (b64_ntops(salt.s, salt.len, &hashed) == -1)
+			return ERRNO;
+		return OK;
+	} else {
+		if (salt.s == 0 || salt.len < 4)
+			return FAILED;
+		if (!stralloc_ready(&intermediate, MD5_LEN)) return ERRNO;
+		intermediate.len = MD5_LEN;
+		MD5Init(&ctx);
+		MD5Update(&ctx, clear, str_len(clear));
+		MD5Update(&ctx, salt.s, salt.len);
+		MD5Final(intermediate.s,&ctx);
+		
+		if (!stralloc_cat(&intermediate, &salt)) return ERRNO;
+		if (b64_ntops(intermediate.s, intermediate.len, &hashed) == -1)
+			return ERRNO;
+		
+		return OK;
+	}
+}
+
+static int
+do_sha1(char *clear, char *encrypted)
+{
+	SHA1_CTX ctx;
+	unsigned char buffer[SHA1_LEN];
+
+	SHA1Init(&ctx);
+	SHA1Update(&ctx, clear, str_len(clear));
+	SHA1Final(buffer,&ctx);
+	if (b64_ntops(buffer, sizeof(buffer), &hashed) == -1) return ERRNO;
+
+	return OK;
+}
+
+static int
+do_ssha1(char *clear, char *encrypted)
+{
+	SHA1_CTX ctx;
+	
+	if (encrypted) {
+		if (b64_ptons(encrypted, &salt) == -1)
+			return BADVAL;
+
+		SHA1Init(&ctx);
+		SHA1Update(&ctx, clear, str_len(clear));
+		SHA1Update(&ctx, salt.s + SHA1_LEN, salt.len - SHA1_LEN);
+		SHA1Final(salt.s,&ctx);
+		if (b64_ntops(salt.s, salt.len, &hashed) == -1)
+			return ERRNO;
+		return OK;
+	} else {
+		if (salt.s == 0 || salt.len < 4)
+			return FAILED;
+		if (!stralloc_ready(&intermediate, SHA1_LEN)) return ERRNO;
+		intermediate.len = SHA1_LEN;
+		SHA1Init(&ctx);
+		SHA1Update(&ctx, clear, str_len(clear));
+		SHA1Update(&ctx, salt.s, salt.len);
+		SHA1Final(intermediate.s,&ctx);
+		
+		if (!stralloc_cat(&intermediate, &salt)) return ERRNO;
+		if (b64_ntops(intermediate.s, intermediate.len, &hashed) == -1)
+			return ERRNO;
+		
+		return OK;
+	}
+}
+
+static int
+do_rmd160(char *clear, char *encrypted)
+{
+	RMD160_CTX ctx;
+	unsigned char buffer[RMD160_LEN];
+
+	RMD160Init(&ctx);
+	RMD160Update(&ctx, clear, str_len(clear));
+	RMD160Final(buffer,&ctx);
+	if (b64_ntops(buffer, sizeof(buffer), &hashed) == -1) return ERRNO;
+
+	return OK;
+}
+
diff -ruN qmail-1.03-orig/passwd.h qmail-1.03-ldap-20060201-orig/passwd.h
--- qmail-1.03-orig/passwd.h	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/passwd.h	2006-02-25 11:00:55.000000000 +0100
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2003-2004 Claudio Jeker,
+ *      Internet Business Solutions AG, CH-8005 Zürich, Switzerland
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Internet Business
+ *      Solutions AG and its contributors.
+ * 4. Neither the name of the author nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#ifndef __PASSWD_H__
+#define __PASSWD_H__
+
+#include "stralloc.h"
+
+/* returns 0 on success else a errro number is returned (see qldap-errno.h) */
+int cmp_passwd(char *, char *);
+
+/* make a password */
+int make_passwd(const char *, char *, stralloc *);
+
+/* feed salt pool for passwd generation */
+int feed_salt(char *, int);
+
+/* feed crypt(3) format to the passwd function */
+void feed_crypt(const char *);
+
+#endif
diff -ruN qmail-1.03-orig/pbsadd.c qmail-1.03-ldap-20060201-orig/pbsadd.c
--- qmail-1.03-orig/pbsadd.c	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/pbsadd.c	2006-02-25 11:00:55.000000000 +0100
@@ -0,0 +1,362 @@
+/*
+ * Copyright (c) 2002-2004 Claudio Jeker,
+ *      Internet Business Solutions AG, CH-8005 Zürich, Switzerland
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Internet Business
+ *      Solutions AG and its contributors.
+ * 4. Neither the name of the author nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <unistd.h>
+#include "alloc.h"
+#include "auto_qmail.h"
+#include "byte.h"
+#include "control.h"
+#include "env.h"
+#include "error.h"
+#include "exit.h"
+#include "fmt.h"
+#include "ip.h"
+#include "open.h"
+#include "readwrite.h"
+#include "str.h"
+#include "stralloc.h"
+#include "substdio.h"
+
+static void die(void);
+static void logit(const char* );
+static void logits(const char *);
+static void die_badenv(void);
+static void die_control(void);
+static void die_dir(void);
+static void die_exec(void);
+static void die_secret(void);
+static void log_socket(void);
+static void die_dirback(void);
+static void die_envs(void);
+static void log_nomem(void);
+static void log_envsize(void);
+static void log_envvar(char *);
+
+void setup(void);
+static void uint16_pack_big(char [], unsigned int);
+int sendrequest(int, char *, unsigned int, struct ip_address *);
+unsigned int addenv(char *, unsigned int);
+
+char sserrbuf[128];
+substdio sserr = SUBSTDIO_FDBUF(subwrite,2,sserrbuf,sizeof sserrbuf);
+
+char **childargs;
+
+#define MAX_PACKET_SIZE 1024
+char packet[MAX_PACKET_SIZE];
+
+stralloc addresses = {0};
+stralloc envs = {0};
+stralloc secret = {0};
+struct ip_address *servers;
+unsigned int numservers = 0;
+unsigned int numenvs = 0;
+unsigned int serverport = 2821;
+
+void
+setup(void)
+{
+	char* s;
+	unsigned int i, len;
+	int fdsourcedir;
+
+	fdsourcedir = open_read(".");
+	if (fdsourcedir == -1)
+		die_dir();
+
+	if (chdir(auto_qmail) == -1) die_control();
+
+	if (control_readfile(&addresses,"control/pbsservers",0) != 1)
+		die_control();
+
+	if (control_readint(&serverport,"control/pbsport") == -1)
+		die_control();
+	if (serverport > 65000)
+		die_control();
+	if (control_rldef(&secret,"control/pbssecret",0,"") != 1)
+		die_control();
+	if (secret.len > 255)
+		die_secret();
+	if (control_readfile(&envs,"control/pbsenv",0) == -1)
+		die_control();
+
+	if (fchdir(fdsourcedir) == -1)
+		die_dirback();
+	close(fdsourcedir);
+
+	for (i = 0; i < addresses.len; i++)
+		if(addresses.s[i] == '\0') numservers++;
+	if (numservers == 0) die_control();
+
+	for (i = 0; i < envs.len; i++)
+		if(envs.s[i] == '\0') numenvs++;
+	if (numenvs > 255) die_envs();
+
+	servers = (struct ip_address*)
+	    alloc(numservers * sizeof(struct ip_address));
+	if (!servers) log_nomem();
+
+	s = addresses.s;
+	for (i = 0; i < numservers; i++) {
+		len = ip_scan(s, &servers[i]);
+		if (len == 0 || len > 15) die_control();
+		while (*s++);
+	}
+
+}
+
+
+static void
+uint16_pack_big(char s[2], unsigned int u)
+{
+	s[1] = u & 255;
+	s[0] = (u >> 8) & 255;
+}
+
+int
+sendrequest(int fd, char *buf, unsigned int len, struct ip_address *ip)
+{
+	struct sockaddr_in s;
+
+	byte_zero(&s,sizeof(s));
+	byte_copy(&s.sin_addr,4,ip);
+	uint16_pack_big((char *)&s.sin_port, serverport);
+	s.sin_family = AF_INET;
+
+	return sendto(fd, buf, len, 0, (struct sockaddr*)&s, sizeof(s));
+}
+
+
+unsigned int
+addenv(char *buf, unsigned int len)
+{
+	unsigned int i;
+	unsigned int vlen;	/* length of the envvar  */
+	unsigned int elen;	/* length of the envname */
+	unsigned int telen;	/* length of the envline envname=rewritename */
+	unsigned int olen;	/* old length of the packet buffer */
+	char *e;
+	char *v;
+
+	olen = len;
+	buf += len;
+	*buf++ = numenvs; len++;
+
+	e = envs.s;
+	for (i=0; i < numenvs; i++) {
+		telen = str_len(e);
+		/* we are not interested in the rewrite name */
+		elen = str_chr(e, '=');
+		e[elen] = '\0';
+
+		/* get the requested envvar */
+		v = env_get(e);
+		vlen = v != (char *)0?str_len(v):0;
+
+		/* write the result */
+		if (elen + vlen + 1 > 255) {
+			/* Check that length indicator does not overflow */
+			log_envvar(e);
+			return olen;
+		}
+		if (len + elen + vlen + 2 > MAX_PACKET_SIZE) {
+			/*
+			 * Packet may not overflow.
+			 * The environment is written like this:
+			 *   [length]envname"="envvar
+			 */
+			log_envsize();
+			return olen;
+		}
+		*buf++ = elen + vlen + 1; len++; /* length */
+		byte_copy(buf, elen, e); buf+=elen, len+=elen; /* envname */
+		*buf++ = '='; len++; /* "=" */
+		if (vlen != 0) {
+			byte_copy(buf, vlen, v);
+			buf+=vlen;
+			len+=vlen;
+		}
+		if (len > MAX_PACKET_SIZE) {
+			/* call me paranoid ... */
+			log_envsize();
+			return olen;
+		}
+		e += telen + 1;
+	}
+	return len;
+}
+
+int
+main(int argc, char** argv)
+{
+	struct ip_address ip;
+	char *ipstr;
+	char *s;
+	int sfd;
+	unsigned int i, len;
+
+	childargs = argv + 1;
+
+	if (env_get("NOPBS")) goto done;
+
+	setup();
+
+	ipstr = env_get("TCPREMOTEIP");
+	if (!ipstr) die_badenv();
+	len = ip_scan(ipstr, &ip);
+	if (len == 0 || len > 15) die_badenv();
+
+	sfd = socket(AF_INET,SOCK_DGRAM,0);
+	if (sfd == -1) {
+		log_socket();
+		goto done;
+	}
+
+	/* create request */
+	s = packet; len = 0;
+	*s++ = 'A'; len++; /* ADD */
+	*s++ = 4; len++;   /* Size of address in bytes (4 IPv4|16 IPv6) */
+	byte_copy(s, 4, &ip); s+=4; len+=4;
+	*s++ = secret.len; len++;   /* secret length */
+	byte_copy(s, secret.len, secret.s); s+=secret.len; len+=secret.len;
+	len = addenv(packet, len);
+
+	/* send update notification to all servers */
+	for (i = 0; i < numservers; i++) {
+		sendrequest(sfd, packet, len, &servers[i]);
+	}
+	close(sfd); /* try to close socket */
+done:
+	if (!*childargs) _exit(0);
+	else execvp(*childargs,childargs);
+	/* should never reach this point */
+	die_exec();
+	/* NOTREACHED */
+	return 1;
+}
+
+static void
+die(void)
+{
+	_exit(1);
+}
+
+static void
+logit(const char* s)
+{
+	substdio_puts(&sserr,s);
+	substdio_puts(&sserr,"\n");
+	substdio_flush(&sserr);  
+}
+
+static void
+logits(const char *s)
+{
+	substdio_puts(&sserr,s);
+}
+
+static void
+die_badenv(void)
+{
+	logit("pbsadd unable to read $TCPREMOTEIP"); die();
+}
+
+static void
+die_control(void)
+{
+	logit("pbsadd unable to read controls"); die();
+}
+
+static void
+die_dir(void)
+{
+	logit("pbsadd unable to open current directory"); die();
+}
+
+static void
+die_exec(void)
+{
+	logit("pbsadd unable to start pop3 daemon"); die();
+}
+
+static void
+die_secret(void)
+{
+	logit("pbsadd control/pbssecret is to long"); die();
+}
+
+static void
+log_socket(void)
+{
+	logit("pbsadd socket syscall failed");
+}
+
+static void
+die_dirback(void)
+{
+	logit("pbsadd unable to switch back to source directory");
+	die();
+}
+
+static void
+die_envs(void)
+{
+	logit("pbsadd control/pbsenvs has to many entries");
+	die();
+}
+
+static void
+log_nomem(void)
+{
+	logit("pbsadd out of memory"); 
+	if (*childargs) _exit(111);
+	else execvp(*childargs,childargs);
+	/* should never reach this point */
+	die_exec();
+}
+
+static void
+log_envsize(void)
+{
+	logit("pbsadd to many environment entries (pkg to small)");
+}
+
+static void
+log_envvar(char *s)
+{
+	logits("pbsadd environment "); logits(s); logit(" is to big"); 
+}
+
diff -ruN qmail-1.03-orig/pbscheck.c qmail-1.03-ldap-20060201-orig/pbscheck.c
--- qmail-1.03-orig/pbscheck.c	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/pbscheck.c	2006-02-25 11:00:55.000000000 +0100
@@ -0,0 +1,421 @@
+/*
+ * Copyright (c) 2002-2004 Claudio Jeker,
+ *      Internet Business Solutions AG, CH-8005 Zürich, Switzerland
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Internet Business
+ *      Solutions AG and its contributors.
+ * 4. Neither the name of the author nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <unistd.h>
+#include "alloc.h"
+#include "auto_qmail.h"
+#include "byte.h"
+#include "control.h"
+#include "env.h"
+#include "error.h"
+#include "exit.h"
+#include "fmt.h"
+#include "ip.h"
+#include "now.h"
+#include "open.h"
+#include "str.h"
+#include "stralloc.h"
+#include "substdio.h"
+#include "timeoutread.h"
+#include "timeoutwrite.h"
+
+static void die(void);
+static int safewrite(int, void *, int);
+static void putstr(const char *);
+static void flush(void);
+static void errstr(const char *);
+static void logit(const char *);
+static void die_usage(void);
+static void die_exec(void);
+static void die_badenv(void);
+static void die_control(void);
+static void die_nomem(void);
+static void die_envs(void);
+static void die_dir(void);
+static void die_dirback(void);
+void setup(void);
+static void uint16_pack_big(char [], unsigned int);
+int sendrequest(int, char *, unsigned int, struct ip_address *);
+int env_snap(void);
+void env_rewrite(char**, char**);
+void setenv(char *, unsigned int);
+
+char ssoutbuf[128];
+substdio ssout = SUBSTDIO_FDBUF(safewrite,1,ssoutbuf,sizeof ssoutbuf);
+
+char sserrbuf[128];
+substdio sserr = SUBSTDIO_FDBUF(safewrite,2,sserrbuf,sizeof sserrbuf);
+
+#define MAX_PACKET_SIZE 1024
+char packet[MAX_PACKET_SIZE];
+
+stralloc addresses = {0};
+stralloc envs = {0};
+struct ip_address *servers;
+unsigned int numservers = 0;
+unsigned int numenvs = 0;
+unsigned int serverport = 2821;
+
+
+void
+setup(void)
+{
+	char* s;
+	unsigned int i, len;
+	int fdsourcedir;
+
+	fdsourcedir = open_read(".");
+	if (fdsourcedir == -1)
+		die_dir();
+
+	if (chdir(auto_qmail) == -1) die_control();
+
+	if (control_readfile(&addresses,"control/pbsservers",0) != 1)
+	       	die_control();
+
+	if (control_readint(&serverport,"control/pbsport") == -1)
+	       	die_control();
+	if (serverport > 65000)
+	       	die_control();
+	if (control_readfile(&envs,"control/pbsenv",0) == -1)
+	       	die_control();
+
+	if (fchdir(fdsourcedir) == -1)
+		die_dirback();
+	close(fdsourcedir);
+
+	for (i = 0; i < addresses.len; i++)
+		if( addresses.s[i] == '\0') numservers++;
+	if (numservers == 0) die_control();
+
+	for (i = 0; i < envs.len; i++)
+		if( envs.s[i] == '\0') numenvs++;
+	if (numenvs > 255) die_envs();
+
+	servers = (struct ip_address*)
+	    alloc(numservers * sizeof(struct ip_address));
+	if (!servers) die_nomem();
+
+	s = addresses.s;
+	for (i = 0; i < numservers; i++) {
+		len = ip_scan(s, &servers[i]);
+		if (len == 0 || len > 15) die_control();
+		while (*s++);
+	}
+}
+
+
+static void
+uint16_pack_big(char s[2], unsigned int u)
+{
+	s[1] = u & 255;
+	s[0] = (u >> 8) & 255;
+}
+
+int
+sendrequest(int fd, char *buf, unsigned int len, struct ip_address *ip)
+{
+	struct sockaddr_in s;
+
+	byte_zero(&s,sizeof(s));
+	byte_copy(&s.sin_addr,4,ip);
+	uint16_pack_big((char *)&s.sin_port, serverport);
+	s.sin_family = AF_INET;
+
+	return sendto(fd, buf, len, 0, (struct sockaddr*)&s, sizeof(s));
+}
+
+char **envsnap;
+
+int
+env_snap(void)
+{
+	unsigned int en, i;
+	
+	for (en = 0;environ[en];++en) ;
+	envsnap = (char **) alloc((en + 1) * sizeof(char *));
+	if (!envsnap) return 0;
+	for (en = 0;environ[en];++en) {
+		envsnap[en] = alloc(str_len(environ[en]) + 1);
+		if (!envsnap[en]) {
+			for (i = 0; i < en; ++i) alloc_free(envsnap[i]);
+			alloc_free(envsnap);
+			return 0;
+		}
+		str_copy(envsnap[en],environ[en]);
+	}
+	envsnap[en] = 0;
+	return 1;
+}
+
+stralloc vbuf = {0};
+
+void
+env_rewrite(char** name, char** value)
+{
+	char *e;
+	unsigned int i;
+	unsigned int llen;
+	unsigned int nlen;
+	unsigned int elen;
+
+	e = envs.s;
+	nlen = str_len(*name);
+
+	for (i=0; i < numenvs; i++) {
+		llen = str_len(e);
+		if (byte_equal(*name, nlen, e))
+			if (*(e + nlen) == '=') {
+				elen = str_chr(e + nlen + 1, '=');
+				if (*(e + nlen + elen + 1) == '=') {
+					*(e + nlen + elen + 1) = '\0';
+					if (!stralloc_copys(&vbuf,
+						    e + nlen + elen + 2))
+						die_nomem();
+					if (!stralloc_cats(&vbuf, *value))
+						die_nomem();
+					if (!stralloc_0(&vbuf)) die_nomem();
+					*value = vbuf.s;
+				}
+				*name = e + nlen + 1;
+				return;
+			}
+		e += llen + 1;
+	}
+}
+
+void setenv(char *env, unsigned int envlen)
+{
+	char *v;
+	char *e;
+	unsigned int numenv;
+	unsigned int elen;
+	unsigned int nlen;
+	unsigned int tlen;
+	unsigned int i;
+
+	if (!env_snap()) die_nomem();
+
+	numenv=(unsigned char)*env++; envlen--;
+
+	nlen=(unsigned char)*env++; envlen--;
+	for (i=0; i < numenv; i++) {
+		elen=nlen;
+		if (envlen <= 0) {
+			environ = envsnap;
+			return;
+		}
+		nlen=(unsigned char)*(env+elen);
+		*(env+elen)=0;
+		tlen = str_chr(env, '=');
+		env[tlen] = '\0';
+		e = env;
+		v = env + tlen + 1;
+		env_rewrite(&e, &v);
+		if (!env_put2(e, v)) die_nomem();
+		env+=elen+1; envlen-=(elen+1);
+	}
+}
+
+int main (int argc, char** argv)
+{
+	struct ip_address ip;
+	char **childargs;
+	char *ipstr;
+	char *s;
+	unsigned long t;
+	int sfd = -1;
+	unsigned int len;
+	int i;
+
+	childargs = argv + 1;
+	if (!*childargs) die_usage();
+
+	if (env_get("NOPBS")) goto start_daemon;
+
+	setup();
+
+	t = now() ^ getpid(); /* at least on OpenBSD this is mostly random */
+	t %= numservers;
+
+	ipstr = env_get("TCPREMOTEIP");
+	if (!ipstr) die_badenv();
+	len = ip_scan(ipstr, &ip);
+	if (len == 0 || len > 15) die_badenv();
+
+	sfd = socket(AF_INET,SOCK_DGRAM,0);
+	if (sfd == -1) goto start_daemon;
+
+	/* create request */
+	s = packet; len = 0;
+	*s++ = 'Q'; len++; /* Query */
+	*s++ = 4; len++;   /* Size of address in bytes (4 IPv4|16 IPv6) */
+	byte_copy(s, 4, &ip); s+=4; len+=4;
+	*s++ = 0; len++;   /* status */
+
+	i = sendrequest(sfd, packet, len, &servers[t]);
+	if (i <= 0) goto start_daemon;
+	t = 0;
+	do {
+		/* wait a seconds for answer */
+		i = timeoutread(1, sfd, packet, sizeof(packet));
+		if (i != -1) break;
+		if (i == -1 && errno != error_timeout) goto start_daemon;
+
+		if (t >= numservers) {
+			logit("pbscheck: no response from server");
+			goto start_daemon; /* no response */
+		}
+
+		i = sendrequest(sfd, packet, len, &servers[t]);
+		if (i <= 0) goto start_daemon;
+		t++;
+
+	} while(1);
+
+	if (packet[0] != 'R') goto start_daemon; /* R = Reply */
+	if (packet[1] != 4) goto start_daemon;
+	/* check address */
+	if (byte_diff(packet + 2, 4, &ip)) goto start_daemon;
+	if (*(packet + 2 + packet[1]) == 'R') {
+		if (!env_put("RELAYCLIENT=")) die_nomem();
+	}
+	setenv(packet + 3 + packet[1], i - packet[1] - 3);
+
+start_daemon:
+	if (sfd == -1) close(sfd); /* try to close socket */
+
+	/* start smtpd */
+	execvp(*childargs,childargs);
+	/* should never reach this point */
+	die_exec();
+	/* NOTREACHED */
+	return 1;
+}
+
+static void die(void)
+{
+	_exit(1);
+}
+
+static int safewrite(int fd, void *buf, int len)
+{
+	int r;
+	r = timeoutwrite(1200,fd,buf,len);
+	if (r <= 0) die();
+	return r;
+}
+
+static void putstr(const char *s)
+{
+	substdio_puts(&ssout,s);
+}
+
+static void flush(void)
+{
+	substdio_flush(&ssout);
+}
+
+static void errstr(const char *s)
+{
+	putstr(s);
+	putstr("\r\n");
+	flush();
+}
+
+static void logit(const char *s)
+{
+	substdio_puts(&sserr,s);
+	substdio_puts(&sserr,"\n");
+	substdio_flush(&sserr);  
+}
+
+static void die_usage(void)
+{
+	errstr("554 pop before smtp subprogram uncorrectly installed (#5.3.5)");
+	logit("usage: pbscheck subprogram ...");
+	die();
+}
+
+static void die_exec(void)
+{
+	errstr("554 unable to start smtp daemon (#5.3.5)");
+	logit("pbscheck: unable to start smtp daemon");
+	die();
+}
+
+static void die_badenv(void)
+{
+	errstr("554 unable to read $TCPREMOTEIP (#5.3.5)");
+	logit("pbscheck: unable to read $TCPREMOTEIP");
+	die();
+}
+
+static void die_control(void)
+{
+	errstr("554 unable to read controls (#5.3.5)");
+	logit("pbscheck unable to read controls");
+	die();
+}
+
+static void die_nomem(void)
+{
+	errstr("421 out of memory (#4.3.0)");
+	logit("pbscheck out of memory");
+	die();
+}
+
+static void die_envs(void)
+{
+	errstr("554 to many additional environments defined (#5.3.5)");
+	logit("pbscheck control/pbsenvs has to many entries");
+	die();
+}
+
+static void die_dir(void)
+{
+	errstr("421 chdir failed (#4.3.0)");
+	logit("pbscheck unable to open current directory");
+	die();
+}
+
+static void die_dirback(void)
+{
+	errstr("421 chdir failed (#4.3.0)");
+	logit("pbscheck unable to switch back to source directory");
+	die();
+}
+
diff -ruN qmail-1.03-orig/pbsdbd.c qmail-1.03-ldap-20060201-orig/pbsdbd.c
--- qmail-1.03-orig/pbsdbd.c	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/pbsdbd.c	2006-02-25 11:00:55.000000000 +0100
@@ -0,0 +1,486 @@
+/*
+ * Copyright (c) 2002-2004 Claudio Jeker,
+ *      Internet Business Solutions AG, CH-8005 Zürich, Switzerland
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Internet Business
+ *      Solutions AG and its contributors.
+ * 4. Neither the name of the author nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <unistd.h>
+#include "alloc.h"
+#include "auto_qmail.h"
+#include "byte.h"
+#include "control.h"
+#include "ip.h"
+#include "ndelay.h"
+#include "now.h"
+#include "stralloc.h"
+#include "strerr.h"
+#include "substdio.h"
+#include "uint32.h"
+
+static void die_control(void);
+static void die_nomem(void);
+static void init(void);
+static int socket_bind(int);
+static void cache_impossible(void);
+static void set4(unsigned long, uint32);
+static uint32 get4(unsigned long);
+unsigned long hash(const unsigned char *,unsigned int);
+void unlinkaddr(const unsigned char *, unsigned int);
+void setaddr(const unsigned char *, unsigned int,
+    unsigned long, char *, unsigned int);
+int checkaddr(const unsigned char *, unsigned int,
+    unsigned long, char **, unsigned int *);
+static int doit(void);
+
+struct ip_address ip;
+unsigned int port = 2821;
+stralloc addr = {0};
+stralloc secret = {0};
+unsigned int timeout = 600; /* 10 Min */
+
+unsigned long cachesize = 1048576; /* 1 MB */
+unsigned char *cache;
+unsigned long hashsize;
+unsigned int hashbits;
+unsigned long writer;
+unsigned long oldest;
+unsigned long unused;
+
+static unsigned char buf[1024];
+static unsigned int len;
+
+#define fatal "pbsdbd: fatal: "
+#define warning "pbsdbd: warning: "
+#define info "pbsdbd: info: "
+
+static void
+die_control(void)
+{
+       	strerr_die2x(111, fatal, "unable to read controls");
+}
+
+static void
+die_nomem(void)
+{
+       	strerr_die2x(111, fatal, "out of memory");
+}
+
+static void
+init(void)
+{
+	unsigned int l;
+
+	if (chdir(auto_qmail) == -1) die_control();
+
+	if (control_rldef(&addr,"control/pbsip",0, "0.0.0.0") == -1)
+		die_control();
+	if (!stralloc_0(&addr)) die_nomem();
+
+	l = ip_scan(addr.s, &ip);
+	if (l == 0 && l > 15) die_control();
+
+	if (control_rldef(&secret,"control/pbssecret",0,"") != 1)
+		die_control();
+
+	if (control_readint(&port,"control/pbsport") == -1) die_control();
+	if (port > 65000) die_control();
+
+	/* if a luser sets bad values it's his fault */
+	if (control_readulong(&cachesize,"control/pbscachesize") == -1)
+		die_control();
+	if (control_readint(&timeout,"control/pbstimeout") == -1)
+		die_control();
+
+	cache = alloc(cachesize);
+	if (!cache) die_nomem();
+
+	hashsize = 4;
+	while (hashsize <= (cachesize >> 5)) hashsize <<= 1;
+
+	writer = hashsize;
+	oldest = cachesize;
+	unused = cachesize;
+
+}
+
+static int
+socket_bind(int s)
+{
+	int opt = 1;
+	struct sockaddr_in soin;
+	char *x;
+
+	setsockopt(s,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof opt);
+
+	byte_zero(&soin,sizeof(soin));
+	byte_copy(&soin.sin_addr,4,&ip);
+	x = (char *) &soin.sin_port;
+	x[1] = port; port >>= 8; x[0] = port;
+	soin.sin_family = AF_INET;
+
+	return bind(s,(struct sockaddr *) &soin,sizeof soin);
+}
+
+static void
+cache_impossible(void)
+{
+	strerr_die2x(111, fatal, "cache corrupted");
+}
+
+static void
+set4(unsigned long pos, uint32 u)
+{
+	unsigned char *s;
+
+	if (pos > cachesize - 4) cache_impossible();
+
+	s = cache + pos;
+	s[3] = u & 255;
+	u >>= 8;
+	s[2] = u & 255;
+	u >>= 8;
+	s[1] = u & 255;
+	s[0] = u >> 8;  
+}
+
+static uint32
+get4(unsigned long pos)
+{
+	unsigned char *s;
+	uint32 result;  
+
+	if (pos > cachesize - 4) cache_impossible();
+	s = cache + pos;
+	result = s[0];
+	result <<= 8;
+	result += s[1];
+	result <<= 8;
+	result += s[2];
+	result <<= 8;
+	result += s[3];
+
+	return result;
+}
+
+unsigned long
+hash(const unsigned char *key,unsigned int keylen)
+{
+	unsigned long result = 5381;
+
+	while (keylen) {
+		result = (result << 5) + result;
+		result ^= *key;
+		++key;
+		--keylen;
+	}
+	result <<= 2;
+	result &= hashsize - 4;
+	return result;
+}
+
+void
+unlinkaddr(const unsigned char *key, unsigned int keylen)
+{
+	unsigned long pos;
+	unsigned long prevpos;
+	unsigned long nextpos;
+	unsigned int loop;
+
+	if (!cache) return;
+
+	prevpos = hash(key,keylen);
+	pos = get4(prevpos);
+	loop = 0;
+
+	while (pos) {
+		if (pos + 13 > cachesize) cache_impossible();
+		nextpos = prevpos ^ get4(pos);
+		if (nextpos == prevpos) cache_impossible();
+		if (*(cache + pos + 12) == keylen) {
+			if (pos + 13 + keylen > cachesize) cache_impossible();
+			if (byte_equal(key,keylen,cache + pos + 13)) {
+				set4(prevpos, get4(prevpos) ^ pos ^ nextpos);
+				if (nextpos != 0)
+					set4(nextpos,
+					    get4(nextpos) ^ pos ^ prevpos);
+				set4(pos, 0);
+				//strerr_warn2(info, "clearing entry.", 0);
+				return;
+			}
+		}
+		prevpos = pos;
+		pos = nextpos;
+		if (++loop > 100) {
+			strerr_warn2(warning, "hash flooding", 0);
+			return; /* to protect against hash flooding */
+		}
+	}
+}
+
+/* to be stored: 4-byte link, 4-byte timestamp, 4-byte envsize, 1-byte size,
+   size-byte Address and envsize-byte Environment */
+/* see also dnscache */
+void
+setaddr(const unsigned char *key, unsigned int keylen,
+    unsigned long timenow, char *env, unsigned int envlen)
+{
+	unsigned int entrylen;
+	unsigned int tmplen;
+	unsigned int keyhash;
+	unsigned long pos;
+
+	if (!cache) return;
+	if (keylen > 255) return;
+
+	entrylen = 13 + keylen + envlen;
+
+	unlinkaddr(key, keylen);
+
+	while (writer + entrylen > oldest) {
+		if (oldest == unused) {
+			if (writer <= hashsize) cache_impossible();
+			unused = writer;
+			oldest = hashsize;
+			writer = hashsize;
+			strerr_warn2(info, "reached end of cache, wrapping...", 0);
+		}
+
+		pos = get4(oldest);
+		if (!pos)
+			strerr_warn2(info, "skipping cleared entry", 0);
+		if (pos)
+			set4(pos,get4(pos) ^ oldest);
+
+		if (oldest + 13 > cachesize) cache_impossible();
+		tmplen = get4(oldest + 8);
+		oldest += 13 + tmplen + *(cache + oldest + 12);
+		if (oldest > unused) cache_impossible();
+		if (oldest == unused) {
+			unused = cachesize;
+			oldest = cachesize;
+		}
+	}
+
+	keyhash = hash(key,keylen);
+
+	pos = get4(keyhash);
+	if (pos)
+		set4(pos,get4(pos) ^ keyhash ^ writer);
+	set4(writer,pos ^ keyhash);
+	set4(writer + 4,timenow + timeout);
+	set4(writer + 8,envlen);
+	if (writer + 13 > cachesize) cache_impossible();
+	*(cache + writer + 12) = keylen;
+	byte_copy(cache + writer + 13,keylen,key);
+	byte_copy(cache + writer + 13 + keylen,envlen,env);
+
+	set4(keyhash,writer);
+
+	writer += entrylen;
+}
+
+int
+checkaddr(const unsigned char *key, unsigned int keylen,
+    unsigned long timenow, char **env, unsigned int *envlen)
+{
+	unsigned long pos;
+	unsigned long prevpos;
+	unsigned long nextpos;
+	unsigned long u;
+	unsigned int loop;
+
+	if (!cache) return 0;
+
+	prevpos = hash(key,keylen);
+	pos = get4(prevpos);
+	loop = 0;
+	*env = 0;
+	*envlen = 0;
+
+	while (pos) {
+		if (pos + 13 > cachesize) cache_impossible();
+		if (*(cache + pos + 12) == keylen) {
+			if (pos + 13 + keylen > cachesize) cache_impossible();
+			if (byte_equal(key,keylen,cache + pos + 13)) {
+				u = get4(pos + 4);
+				if (u < timenow) {
+					//strerr_warn2(info,
+					//    "cache hit but timed out", 0);
+					return 0;
+				}
+				*envlen = get4(pos + 8);
+				if (pos + 13 + keylen + *envlen > cachesize)
+					cache_impossible();
+				*env = cache + pos + 13 + keylen;
+				return 1;
+			}
+		}
+		nextpos = prevpos ^ get4(pos);
+		if (nextpos == prevpos) cache_impossible();
+		prevpos = pos;
+		pos = nextpos;
+		if (++loop > 100) {
+			strerr_warn2(warning, "hash flooding", 0);
+			return 0; /* to protect against hash flooding */
+		}
+	}
+
+	//strerr_warn2(info, "not in cache", 0);
+	return 0;
+}
+
+
+/*
+ * pbs packets have following format:
+ *   header:
+ *   1-byte type, 1-byte address-size, address-size-byte
+ *
+ *   secret used in type add packets:
+ *   1-byte secret-size, secret-size-bytes secret
+ *
+ *   may-relay byte used in respnse packets:
+ *   1-byte may-relay ('R' for may-relay and 'N' for may-not-relay)
+ *
+ *   optional environment vars for type add and result:
+ *   1-byte #-of-entries
+ *   environment vars entries
+ *   1-byte size, n-byte env-name, 1-byte '"', m-byte env-var
+ *   where n + m + 1 = size.
+ *
+ *   Allowed types are 'A' for add, 'Q' for query, 'R' response.
+ *   Type 'A' uses the header and secret plus optional environment vars.
+ *   Type 'Q' does only need the header.
+ *   Type 'R' needs the header and the may-relay byte and
+ *   optional environment vars.
+ */
+
+static int doit(void)
+{
+	unsigned char *sec;
+	unsigned int sec_len;
+	unsigned char *env;
+	unsigned long timenow;
+	unsigned int envlen;
+	unsigned int i;
+
+	if ((unsigned int)buf[1] + 2 >= len) {
+		strerr_warn2(warning, "bad packet", 0);
+		return 0;
+	}
+
+	timenow = now();
+
+	switch (buf[0]) {
+	case 'Q':
+		//strerr_warn2(info, "query packet", 0);
+		if (checkaddr(&buf[2], buf[1], timenow,
+			    (char**)&env, &envlen)) {
+			*(buf + 2 + buf[1]) = 'R';
+			if (envlen + buf[1] + 3 > 1024) {
+				strerr_warn2(warning, "environment would "
+				    "exceed package size, dropped", 0);
+				return 0;
+			}
+			byte_copy(buf+3+buf[1], envlen, env);
+			len += envlen;
+		} else {
+			*(buf + 2 + buf[1]) = 'N';
+		}
+		buf[0] = 'R';
+		return 1;
+	case 'A':
+		//strerr_warn2(info, "add packet", 0);
+		sec_len = *(buf + 2 + buf[1]);
+		sec = buf + 2 + buf[1] + 1;
+		if (buf + len < sec + sec_len) {
+			strerr_warn2(warning, "bad packet", 0);
+			return 0;
+		}
+		if (secret.len != sec_len ||
+		    byte_diff(secret.s, sec_len, sec)) {
+			strerr_warn2(warning, "no authorized add packet", 0);
+			return 0;
+		}
+		env = buf + 3 + buf[1] + *(buf + 2 + buf[1]);
+		envlen = 1;
+		for (i=0; i < *env; i++) {
+			envlen += env[envlen] + 1;
+			if (buf + len < env + envlen) {
+				strerr_warn2(warning, "environment would "
+				    "exceed package size, dropped", 0);
+				return 0;
+			}
+		}
+		if (buf + len != env + envlen) {
+			strerr_warn2(warning, "trailing garbadge at end "
+			    "of packet, dropped", 0);
+			return 0;
+		}
+		setaddr(&buf[2], buf[1], timenow, env, envlen);
+		return 0;
+	case 'R':
+		strerr_warn2(warning, "response recived", 0);
+		return 0;
+	default:
+		strerr_warn2(warning, "bad packet", 0);
+		return 0;
+	}
+}
+
+int main(int argc, char** argv)
+{
+	struct sockaddr_in sa;
+	unsigned int dummy;
+	int udp;
+
+	init();
+
+	udp = socket(AF_INET, SOCK_DGRAM, 0);
+	if (udp == -1)
+		strerr_die2sys(111,fatal,"unable to create UDP socket: ");
+	if (socket_bind(udp) == -1)
+		strerr_die2sys(111,fatal,"unable to bind UDP socket: ");
+
+	ndelay_off(udp);
+
+	for (;;) {
+		dummy = sizeof(sa);
+		len = recvfrom(udp, buf, sizeof(buf), 0,
+		    (struct sockaddr*) &sa, &dummy);
+		if (len < 0) continue;
+		if (!doit()) continue;
+		sendto(udp, buf, len, 0, (struct sockaddr*) &sa, sizeof(sa));
+		/* may block for buffer space; if it fails, too bad */
+	}
+}
+
diff -ruN qmail-1.03-orig/pbsexec.c qmail-1.03-ldap-20060201-orig/pbsexec.c
--- qmail-1.03-orig/pbsexec.c	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/pbsexec.c	2006-02-25 11:00:55.000000000 +0100
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2003-2004 Claudio Jeker,
+ *      Internet Business Solutions AG, CH-8005 Zürich, Switzerland
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Internet Business
+ *      Solutions AG and its contributors.
+ * 4. Neither the name of the author nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#include <unistd.h>
+#include "env.h"
+#include "open.h"
+#include "qldap-debug.h"
+#include "wait.h"
+
+#include "pbsexec.h"
+
+char *pbstool = 0;
+
+void
+pbsexec(void)
+{
+	char *(args[3]);
+	int child, wstat;
+
+	if (pbstool == 0 || *pbstool == 0) return;
+
+	if (env_get("NOPBS")) return;
+
+	switch (child = fork()) {
+	case -1:
+		return;
+	case 0:
+		/* the pbstool may not read or write to the connection */
+		close(0); open_read("/dev/null");
+		close(1); open_write("/dev/null");
+		close(3);
+		
+		args[0] = pbstool;
+		args[1] = 0;
+		execvp(*args, args);
+		_exit(111);
+	}
+
+	wait_pid(&wstat,child);
+	if (wait_crashed(wstat))
+		logit(2, "pbsexec: %s crashed\n", pbstool);
+	else if (wait_exitcode(wstat))
+		logit(2, "pbsexec: %s failed, exit code %d\n",
+		    pbstool, wait_exitcode(wstat));
+	else
+		logit(64, "pbsexec: %s OK\n", pbstool);
+
+	return;
+}
+
diff -ruN qmail-1.03-orig/pbsexec.h qmail-1.03-ldap-20060201-orig/pbsexec.h
--- qmail-1.03-orig/pbsexec.h	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/pbsexec.h	2006-02-25 11:00:55.000000000 +0100
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2003-2004 Claudio Jeker,
+ *      Internet Business Solutions AG, CH-8005 Zürich, Switzerland
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Internet Business
+ *      Solutions AG and its contributors.
+ * 4. Neither the name of the author nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#ifndef __PBSEXEC_H__
+#define __PBSEXEC_H__
+
+extern char *pbstool;
+
+void pbsexec(void);
+
+#endif
diff -ruN qmail-1.03-orig/POPBEFORESMTP qmail-1.03-ldap-20060201-orig/POPBEFORESMTP
--- qmail-1.03-orig/POPBEFORESMTP	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/POPBEFORESMTP	2006-02-25 11:00:55.000000000 +0100
@@ -0,0 +1,194 @@
+POPBEFORESMTP by Claudio Jeker <jeker@n-r-g.com> and 
+Andre Oppermann <opi@nrg4u.com>
+(c) 2002-2004 Internet Business Solutions Ltd.
+
+The POPBEFORESMTP tools are a part of the qmail-ldap patch.
+This patch for qmail comes with NO WARRANTY.
+
+RELEASE: current ($Date: 2004/04/16 13:24:16 $)
+
+POP-Before-SMTP:
+======================
+
+TOC:
+ HOW DOES IT WORK
+ INSTALL
+ CONFIG FILES
+ SETUP
+  - pbsadd
+  - pbscheck
+  - pbsdbd
+ EXAMPLES
+
+================================================================================
+
+HOW DOES IT WORK
+
+ From http://www.lifewithqmail.org/ldap:
+    As we all know, SMTP does not contain any authentication mechanisms by
+    default. So in practice you are allowing relaying through your server only
+    for some IP addresses, normally your corporate network. If your users are
+    coming from various, dynamic IP addresses they can't use your mailserver
+    for sending :-((
+    
+    To overcome this limitation there are 3 possibilities:
+    
+    -  relaying based on the envelope sender - a really bad idea, easy to abuse.
+    -  SMTP AUTH - great, but your clients need to support it. For a patch see
+       http://www.lifewithqmail.org/ldap
+    -  POP-before-SMTP - when the user gets his mail through pop3 or imap, his
+       IP address is recorded and the permission to relay is given for this IP
+       for a defined time.
+    
+    SMTP AUTH would be the best solution as username and password are supplied
+    when sending, but as long as too many clients are lacking support for it,
+    this is not an option for most of us.
+    
+ Most POP-before-SMTP solutions use the tcpserver tcprules cdb file to
+ store the allowed IP addresses. This does not work in a clustered setup.
+ Our solution uses two clients pbsadd and pbscheck and a server pbsdbd which 
+ stores the IP addresses in a database.
+ pbsadd has to be added just after auth_pop or auth_imap and will add new
+ allowed IP addresses to the cache.
+ pbscheck runs before qmail-smtpd and sets the RELAYCLIENT environment if the
+ IP address is allowed to relay.
+ pbsdbd is the Pop-Before-Smtp DataBase Daemon. pbsdbd uses a similar cache 
+ algorithm as djbdns' dnscache daemon.
+ pbsadd and pbscheck communicate over UDP with the pbsdbd server.
+ 
+================================================================================
+
+INSTALL
+
+ The Tools pbsadd, pbscheck and pbsdbd are installed in the qmail binary
+ directory, normally /var/qmail/bin.
+ 
+ NOTE: the tools can also be used on qmail systems without the qmail-ldap patch.
+ 
+================================================================================
+
+CONFIG FILES
+
+~control/pbsservers
+ 
+ A list of IP addresses of running pbsdbd servers.
+ This file is only used by the clients pbsadd and pbscheck.
+ Required
+ Example:
+   127.0.0.1
+   10.0.1.1
+   10.0.2.1
+ 
+~control/pbsip
+ 
+ The pbsdbd server's address is given through this control file.
+ This file is only needed for the pbsdbd server.
+ Default: 0.0.0.0
+ Example: 127.0.0.1
+ 
+~control/pbsport
+
+ The port where all pbsdbd servers are listening on.
+ This file if used is needed by all pbs tools and has to be in sync on all
+ cluster machines. 
+ Default: 2821
+ Example: 6666
+ Note: Ports > 1024 should be used so that the pbsdbd server can be run
+       unprivileged.
+ 
+~control/pbssecret
+
+ Shared secret used by pbsadd and pbsdbd to authenticate the client.
+ Required for pbsdbd and pbsadd.
+ Example: mekmitasdigoat
+ 
+~control/pbscachesize
+
+ Size in bytes used for the cache. Normally you do not need to set this
+ because the default value is big enough.
+ Default: 1048576 /* equal to 1 MB */
+
+~control/pbstimeout
+ 
+ Timeout in seconds until entries in the cache are invalidated.
+ Only used by the pbsdbd server.
+ Default: 600
+ Example: 900
+ 
+~control/pbsenv
+
+ Additional environment variables to include.
+ pbscheck will set these variables to the values pbsadd returned.
+ It is possible to rewrite the variables. A line like
+ USER=TCPREMOTEINFO will cause pbscheck to set the environment TCPREMOTEINFO
+ to the value set as USER in pbsadd. If you like to prepend some identifier
+ in front of the value you can this like this:
+ USER=TCPREMOTEINFO=[pbs]   this will add [pbs] in front of the value returned
+ by pbsadd.
+ Multiline.
+ Default: none
+ Example: HOST
+          TCPREMOTEIP=FROMIP
+          USER=TCPREMOTEINFO=[pbs]
+          
+
+================================================================================
+
+SETUP
+
+pbsadd:
+  usage: pbsadd subprogram ...
+  
+  pbsadd will try to add the IP address $TCPREMOTEIP to all pbsdbd servers
+  listed in ~control/pbsservers. Afterward the subprogram with its arguments
+  is started.
+  On non fatal errors the subprogram will be started without successfully 
+  update the database on the pbsdbd servers.
+  
+pbscheck:
+  usage: pbscheck subprogram ...
+  
+  pbscheck checks if the IP address $TCPREMOTEIP is allowed to relay.
+  It will send queries to the pbsdbd servers listed in ~control/pbsservers.
+  The first query will be sent to a randomly chosen server, if this timeouts
+  all servers will be tried one after another.
+  If the IP is allowed to relay the environment $RELAYCLIENT is set.
+  On non fatal errors the subprogram will be started without setting
+  $RELAYCLIENT.
+  
+pbsdbd:
+  usage: pbsdbd
+  
+  pbsdbd will listen on address specified in ~control/pbsip and the port 
+  specified in ~control/pbsport (default 2821).
+  IP addresses will only be added to the cache if the secret specified in
+  ~control/pbssecret is included in the add request.
+
+================================================================================
+
+EXAMPLES
+
+ First create all necessary ~control files.
+ 
+ NOTE: the following shell scripts are not finished. You have to edit them to
+ modify them for your needs.
+ 
+ The pbsdbd should be run as unprivileged user, this can be done with setuidgid.
+ 
+ #!/bin/sh
+ setuidgid qmaild pbsdbd
+ 
+ pbsadd has to be run after auth_pop, auth_imap or checkpassword in the pop3 or
+ imap tool chain.
+ 
+ #!/bin/sh
+ tcpserver 0 110 qmail-popup $HOST auth_pop pbsadd qmail-pop3d ./Maildir/
+ 
+ 
+ pbscheck has to be run before qmail-smtpd.
+ 
+ #!/bin/sh
+ tcpserver -x $SMTPRULES -v -u qmaild -g nofiles 0 25 pbscheck qmail-smtpd
+ 
+
+END :-)
diff -ruN qmail-1.03-orig/popfetch.pl qmail-1.03-ldap-20060201-orig/popfetch.pl
--- qmail-1.03-orig/popfetch.pl	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/popfetch.pl	2006-02-25 11:00:55.000000000 +0100
@@ -0,0 +1,94 @@
+#!/usr/bin/perl
+#
+# Copyright (c) 1999-2004 Andre Oppermann,
+#      Internet Business Solutions AG, CH-8005 Zürich, Switzerland
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+#    must display the following acknowledgement:
+#      This product includes software developed by Internet Business
+#      Solutions AG and its contributors.
+# 4. Neither the name of the author nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+
+# $localhost and $server need to changed
+# If a file by the name "done" exists in the maildir we don't try to
+# fetch the mails again.
+# by Ingo Oppermann
+
+use Mail::POP3Client;
+
+# Variables
+
+$path       = $ARGV[3];
+$mailpath   = "./".$path;
+$username   = $ARGV[0];
+$pw         = $ARGV[1];
+$server     = 'mail.pipeline.ch';
+$localhost  = "mail.schweizerinserate.ch";
+@filenames;
+
+# Main
+
+if(-e $mailpath."/done")
+{
+        ;
+}
+else
+{
+        $pop = new Mail::POP3Client($username,$pw,$server);
+        $numofmails = $pop->Count;
+        print $numofmails;
+        for($i = 1; $i <= $numofmails; $i++)
+        {
+                $curtime = time();
+                $random = rand();
+                $filename = $curtime.".".$$.".".$random.$localhost;
+                push(@filenames, $filename);
+                open(OUT, ">".$mailpath."/tmp/".$filename);
+                foreach($pop->Retrieve($i))
+                {
+                        print OUT $_, "\n";
+                }
+# Uncomment the next line if the retrieved mail should be deleted from
+# the old pop server
+        #       $pop->Delete($i);
+                close(OUT);
+        }
+        $pop->Close;
+
+        foreach(@filenames)
+        {
+                $filename = $_;
+                $program = "mv $mailpath/tmp/$filename $mailpath/new/$filename";
+                open(PROG, "|$program");
+                close(PROG);
+        }
+        open(CHECK, ">$mailpath/done");
+        print CHECK 1;
+        close(CHECK);
+}
+
+exec "$ARGV[2] $ARGV[3]";
+
diff -ruN qmail-1.03-orig/predate.c qmail-1.03-ldap-20060201-orig/predate.c
--- qmail-1.03-orig/predate.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/predate.c	2006-02-25 11:00:55.000000000 +0100
@@ -1,5 +1,6 @@
 #include <sys/types.h>
 #include <time.h>
+#include <unistd.h>
 #include "datetime.h"
 #include "fork.h"
 #include "wait.h"
@@ -10,17 +11,18 @@
 #include "subfd.h"
 #include "readwrite.h"
 #include "exit.h"
+#include "sig.h"
 
 #define FATAL "predate: fatal: "
 
-static char *montab[12] = {
+static const char *montab[12] = {
 "Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"
 };
 
 char num[FMT_ULONG];
 char outbuf[1024];
 
-void main(argc,argv)
+int main(argc,argv)
 int argc;
 char **argv;
 {
@@ -29,7 +31,7 @@
   struct datetime dt;
   datetime_sec utc;
   datetime_sec local;
-  int minutes;
+  unsigned int minutes;
   int pi[2];
   substdio ss;
   int wstat;
@@ -55,7 +57,7 @@
       strerr_die4sys(111,FATAL,"unable to run ",argv[1],": ");
   }
   close(pi[0]);
-  substdio_fdbuf(&ss,write,pi[1],outbuf,sizeof(outbuf));
+  substdio_fdbuf(&ss,subwrite,pi[1],outbuf,sizeof(outbuf));
 
   time(&now);
 
@@ -112,5 +114,5 @@
     strerr_die2sys(111,FATAL,"wait failed: ");
   if (wait_crashed(wstat))
     strerr_die2x(111,FATAL,"child crashed");
-  _exit(wait_exitcode(wstat));
+  return wait_exitcode(wstat);
 }
diff -ruN qmail-1.03-orig/preline.c qmail-1.03-ldap-20060201-orig/preline.c
--- qmail-1.03-orig/preline.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/preline.c	2006-02-25 11:00:55.000000000 +0100
@@ -1,3 +1,4 @@
+#include <unistd.h>
 #include "fd.h"
 #include "sgetopt.h"
 #include "readwrite.h"
@@ -23,10 +24,10 @@
 
 char outbuf[SUBSTDIO_OUTSIZE];
 char inbuf[SUBSTDIO_INSIZE];
-substdio ssout = SUBSTDIO_FDBUF(write,1,outbuf,sizeof outbuf);
-substdio ssin = SUBSTDIO_FDBUF(read,0,inbuf,sizeof inbuf);
+substdio ssout = SUBSTDIO_FDBUF(subwrite,1,outbuf,sizeof outbuf);
+substdio ssin = SUBSTDIO_FDBUF(subread,0,inbuf,sizeof inbuf);
 
-void main(argc,argv)
+int main(argc,argv)
 int argc;
 char **argv;
 {
@@ -86,5 +87,5 @@
     strerr_die2sys(111,FATAL,"wait failed: ");
   if (wait_crashed(wstat))
     strerr_die2x(111,FATAL,"child crashed");
-  _exit(wait_exitcode(wstat));
+  return wait_exitcode(wstat);
 }
diff -ruN qmail-1.03-orig/prioq.c qmail-1.03-ldap-20060201-orig/prioq.c
--- qmail-1.03-orig/prioq.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/prioq.c	2006-02-25 11:00:55.000000000 +0100
@@ -36,9 +36,9 @@
 void prioq_delmin(pq)
 prioq *pq;
 {
- int i;
- int j;
- int n;
+ unsigned int i;
+ unsigned int j;
+ unsigned int n;
  if (!pq->p) return;
  n = pq->len;
  if (!n) return;
diff -ruN qmail-1.03-orig/prioq.h qmail-1.03-ldap-20060201-orig/prioq.h
--- qmail-1.03-orig/prioq.h	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/prioq.h	2006-02-25 11:00:55.000000000 +0100
@@ -8,8 +8,8 @@
 
 GEN_ALLOC_typedef(prioq,struct prioq_elt,p,len,a)
 
-extern int prioq_insert();
-extern int prioq_min();
-extern void prioq_delmin();
+extern int prioq_insert(prioq *, struct prioq_elt *);
+extern int prioq_min(prioq *, struct prioq_elt *);
+extern void prioq_delmin(prioq *);
 
 #endif
diff -ruN qmail-1.03-orig/profile.patch qmail-1.03-ldap-20060201-orig/profile.patch
--- qmail-1.03-orig/profile.patch	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/profile.patch	2006-02-25 11:00:55.000000000 +0100
@@ -0,0 +1,62 @@
+diff -BbuN qmail-ldap/Makefile qmail-test/Makefile
+--- qmail-ldap/Makefile	Thu Jul 20 22:07:09 2000
++++ qmail-test/Makefile	Thu Jul 20 22:55:52 2000
+@@ -1402,12 +1402,13 @@
+ sig.a strerr.a getln.a wait.a case.a cdb.a fd.a open.a stralloc.a \
+ alloc.a substdio.a error.a str.a fs.a auto_qmail.o auto_uids.o \
+ auto_spawn.o auto_usera.o env.a qldap-ldaplib.o qldap-debug.o \
+-qldap-errno.o
++qldap-errno.o qldap-profile.o
+ 	./load qmail-lspawn spawn.o prot.o slurpclose.o coe.o control.o \
+-	check.o qldap-ldaplib.o qldap-debug.o sig.a strerr.a getln.a \
++	check.o qldap-ldaplib.o qldap-profile.o \
++	qldap-debug.o sig.a strerr.a getln.a \
+ 	wait.a case.a cdb.a fd.a open.a env.a stralloc.a alloc.a \
+ 	substdio.a str.a qldap-errno.o error.a fs.a auto_qmail.o \
+-	auto_uids.o auto_usera.o auto_spawn.o $(LDAPLIBS)
++	auto_uids.o auto_usera.o auto_spawn.o $(LDAPLIBS) $(LIBTAI)
+ 
+ qmail-lspawn.0: \
+ qmail-lspawn.8
+@@ -1419,7 +1420,8 @@
+ slurpclose.h auto_qmail.h auto_uids.h qlx.h qmail-ldap.h check.h \
+ qldap-ldaplib.h qldap-errno.h qldap-debug.h env.h auto_usera.h \
+ auto_uids.h fmt.h sig.h  
+-	./compile $(LDAPFLAGS) $(HDIRMAKE) $(LDAPINCLUDES) qmail-lspawn.c
++	./compile $(LDAPFLAGS) $(HDIRMAKE) $(LDAPINCLUDES) $(INCTAI) 
++	qmail-lspawn.c
+ 
+ qmail-newmrh: \
+ load qmail-newmrh.o cdbmss.o getln.a open.a cdbmake.a seek.a case.a \
+diff -BbuN qmail-ldap/qmail-lspawn.c qmail-test/qmail-lspawn.c
+--- qmail-ldap/qmail-lspawn.c	Mon Jul  3 13:22:01 2000
++++ qmail-test/qmail-lspawn.c	Thu Jul 20 22:55:53 2000
+@@ -31,6 +31,7 @@
+ #include "str.h"
+ #include <pwd.h>
+ #include <sys/types.h>
++#include "qldap-profile.h"
+ 
+ char *aliasempty;
+ 
+@@ -369,7 +370,9 @@
+    extra[6].what = 0;
+ 
+    /* do the search for the email address */
++   start_timing(0, "first ldap_lookup");
+    ret = ldap_lookup(&search, attrs, &info, extra);
++   stop_timing(0);
+    if (!stralloc_copys(&filter, "")) _exit(QLX_NOMEM); 
+    /* XXX doesn't free mem */
+    if ( ret != 0 && qldap_errno == LDAP_NOSUCH ) {
+@@ -391,8 +394,10 @@
+       
+       debug(16, "retry with filter '%s'\n", filter.s);
+       /* do the search for the email address */
++      start_timing(0, "first ldap_lookup");
+       ret = ldap_lookup(&search, attrs, &info, extra);
+       /* count the results, we must have exactly one */
++      stop_timing(0);
+    }
+    alloc_free(filter.s); filter.s = 0;
+    if ( ret != 0 ) {
diff -ruN qmail-1.03-orig/prot.c qmail-1.03-ldap-20060201-orig/prot.c
--- qmail-1.03-orig/prot.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/prot.c	2006-02-25 11:00:55.000000000 +0100
@@ -1,9 +1,10 @@
+#include <unistd.h>
 #include "hasshsgr.h"
 #include "prot.h"
 
 /* XXX: there are more portability problems here waiting to leap out at me */
 
-int prot_gid(gid) int gid;
+int prot_gid(gid) unsigned int gid;
 {
 #ifdef HASSHORTSETGROUPS
   short x[2];
@@ -15,7 +16,7 @@
   return setgid(gid); /* _should_ be redundant, but on some systems it isn't */
 }
 
-int prot_uid(uid) int uid;
+int prot_uid(uid) unsigned int uid;
 {
   return setuid(uid);
 }
diff -ruN qmail-1.03-orig/prot.h qmail-1.03-ldap-20060201-orig/prot.h
--- qmail-1.03-orig/prot.h	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/prot.h	2006-02-25 11:00:55.000000000 +0100
@@ -1,7 +1,7 @@
 #ifndef PROT_H
 #define PROT_H
 
-extern int prot_gid();
-extern int prot_uid();
+extern int prot_gid(unsigned int);
+extern int prot_uid(unsigned int);
 
 #endif
diff -ruN qmail-1.03-orig/qbiff.c qmail-1.03-ldap-20060201-orig/qbiff.c
--- qmail-1.03-orig/qbiff.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/qbiff.c	2006-02-25 11:00:55.000000000 +0100
@@ -1,5 +1,6 @@
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <unistd.h>
 #include <utmp.h>
 #ifndef UTMP_FILE
 #ifdef _PATH_UTMP
@@ -33,7 +34,7 @@
 stralloc tofrom = {0};
 stralloc text = {0};
 
-void doit(s,n) char *s; int n;
+void doit(s,n) char *s; unsigned int n;
 {
  if (!stralloc_catb(&text,s,n)) _exit(0);
  if (text.len > 78) text.len = 78;
@@ -41,7 +42,7 @@
 void dobody(h) stralloc *h; { doit(h->s,h->len); }
 void doheader(h) stralloc *h;
 {
- int i;
+ unsigned int i;
  if (hfield_known(h->s,h->len) == H_SUBJECT)
   {
    i = hfield_skipname(h->s,h->len);
@@ -50,13 +51,13 @@
 }
 void finishheader() { ; }
 
-void main()
+int main()
 {
  char *user;
  char *sender;
  char *userext;
  struct stat st;
- int i;
+ unsigned int i;
 
  if (chdir("/dev") == -1) _exit(0);
 
@@ -90,9 +91,9 @@
 
  fdutmp = open_read(UTMP_FILE);
  if (fdutmp == -1) _exit(0);
- substdio_fdbuf(&ssutmp,read,fdutmp,bufutmp,sizeof(bufutmp));
+ substdio_fdbuf(&ssutmp,subread,fdutmp,bufutmp,sizeof(bufutmp));
 
- while (substdio_get(&ssutmp,&ut,sizeof(ut)) == sizeof(ut))
+ while (substdio_get(&ssutmp,(char *)&ut,sizeof(ut)) == sizeof(ut))
    if (!str_diffn(ut.ut_name,user,sizeof(ut.ut_name)))
     {
      byte_copy(line,sizeof(ut.ut_line),ut.ut_line);
@@ -105,9 +106,9 @@
      if (fstat(fdtty,&st) == -1) { close(fdtty); continue; }
      if (!(st.st_mode & 0100)) { close(fdtty); continue; }
      if (st.st_uid != getuid()) { close(fdtty); continue; }
-     substdio_fdbuf(&sstty,write,fdtty,buftty,sizeof(buftty));
+     substdio_fdbuf(&sstty,subwrite,fdtty,buftty,sizeof(buftty));
      substdio_putflush(&sstty,woof.s,woof.len);
      close(fdtty);
     }
- _exit(0);
+ return 0;
 }
diff -ruN qmail-1.03-orig/qldap.c qmail-1.03-ldap-20060201-orig/qldap.c
--- qmail-1.03-orig/qldap.c	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/qldap.c	2006-02-25 11:00:55.000000000 +0100
@@ -0,0 +1,1057 @@
+/*
+ * Copyright (c) 2003-2004 Andre Oppermann, Claudio Jeker,
+ *      Internet Business Solutions AG, CH-8005 Zürich, Switzerland
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Internet Business
+ *      Solutions AG and its contributors.
+ * 4. Neither the name of the author nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#include <sys/time.h> /* for ldap search timeout */
+
+#include <lber.h>
+#include <ldap.h>
+
+#include "alloc.h"
+#include "byte.h"
+#include "case.h"
+#include "check.h"
+#include "control.h"
+#include "error.h"
+#include "fmt.h"
+#include "qldap-debug.h"
+#include "qldap-errno.h"
+#include "qmail-ldap.h"
+#include "scan.h"
+#include "str.h"
+#include "stralloc.h"
+
+#include "qldap.h"
+
+struct qldap {
+	int		state;
+#define NEW	0
+#define OPEN	1
+#define BIND	2
+#define SEARCH	3
+#define EXTRACT	4
+#define REBIND	5
+#define CLOSE	6
+#define ERROR	-1
+	LDAP		*ld;
+	LDAPMessage	*res; /* valid after a search */
+	LDAPMessage	*msg; /* valid after call to ldap_first_entry() */
+	/* should we store server, binddn, basedn, password, ... */
+};
+
+stralloc	ldap_server = {0};
+stralloc	basedn = {0};
+stralloc	objectclass = {0};
+stralloc	ldap_login = {0};
+stralloc	ldap_password = {0};
+stralloc	default_messagestore = {0};
+stralloc	dotmode = {0};
+unsigned int	ldap_timeout = QLDAP_TIMEOUT;	/* default timeout is 30 secs */
+int		rebind = 0;			/* default off */
+unsigned int	default_uid = 0;
+unsigned int	default_gid = 0;
+unsigned long	quotasize = 0;
+unsigned long	quotacount = 0;
+
+
+static  int qldap_close(qldap *);
+
+static int qldap_set_option(qldap *, int);
+static int check_next_state(qldap *, int);
+
+#define STATEIN(x, y)	((x)->state == (y))
+#define CHECK(x, y)							\
+	do {								\
+		if (check_next_state((x), (y)) == 0) {			\
+			logit(128, "qldap: bad state transition %i -> %i",\
+			    (x)->state, y);				\
+			(x)->state = ERROR;				\
+			return FAILED;					\
+		}							\
+	} while (0)
+
+
+int
+qldap_ctrl_login(void)
+{
+	if (control_rldef(&ldap_login, "control/ldaplogin", 0, "") == -1)
+		return -1;
+	if (!stralloc_0(&ldap_login)) return -1;
+	logit(64, "init_ldap: control/ldaplogin: %s\n", ldap_login.s);
+
+	if (control_rldef(&ldap_password, "control/ldappassword", 0, "") == -1)
+		return -1;
+	if (!stralloc_0(&ldap_password)) return -1;
+	logit(64, "init_ldap: control/ldappassword: %s\n", ldap_password.s);
+
+	return 0;
+}
+
+int
+qldap_ctrl_trylogin(void)
+{
+	if (control_rldef(&ldap_password, "control/ldappassword", 0, "") ==
+	    -1) {
+		if (!stralloc_catb(&ldap_password, "", 1)) return -1;
+		if (!stralloc_catb(&ldap_login, "", 1)) return -1;
+		return 0;
+	}
+	if (!stralloc_0(&ldap_password)) return -1;
+
+	if (control_rldef(&ldap_login, "control/ldaplogin", 0, "") == -1) {
+		if (!stralloc_catb(&ldap_password, "", 1)) return -1;
+		if (!stralloc_catb(&ldap_login, "", 1)) return -1;
+		return 0;
+	}
+	if (!stralloc_0(&ldap_login)) return -1;
+
+	logit(64, "init_ldap: control/ldaplogin: %s\n", ldap_login.s);
+	logit(64, "init_ldap: control/ldappassword: %s\n", ldap_password.s);
+
+	return 0;
+}
+
+int
+qldap_ctrl_generic(void)
+{
+	/* set defaults, so that a reread works */
+	ldap_timeout = QLDAP_TIMEOUT;	/* default timeout is 30 secs */
+	rebind = 0;			/* default off */
+	default_uid = 0;
+	default_gid = 0;
+	quotasize = 0;
+	quotacount = 0;
+
+	if (control_readfile(&ldap_server, "control/ldapserver", 0) != 1)
+		return -1; /* ... the errno should be set by control_* */
+	if (ldap_server.len)
+		byte_repl(ldap_server.s, ldap_server.len - 1, '\0', ' ');
+	else
+		if (!stralloc_0(&ldap_server)) return -1;
+	logit(64, "init_ldap: control/ldapserver: '%s'\n", ldap_server.s);
+
+	if (control_rldef(&basedn, "control/ldapbasedn", 0, "") == -1)
+		return -1;
+	if (!stralloc_0(&basedn)) return -1;
+	logit(64, "init_ldap: control/ldapbasedn: %s\n", basedn.s);
+
+	if (control_rldef(&objectclass, "control/ldapobjectclass", 0, "") == -1)
+		return -1;
+	logit(64, "init_ldap: control/ldapobjectclass: %S\n", &objectclass);
+
+	if (control_readint(&ldap_timeout, "control/ldaptimeout") == -1)
+		return -1;
+	logit(64, "init_ldap: control/ldaptimeout: %i\n", ldap_timeout);
+
+	if (control_readint(&rebind, "control/ldaprebind") == -1) return -1;
+	logit(64, "init_ldap: control/ldaprebind: %i\n", rebind);
+
+	
+	/* defaults */
+	if (control_readint(&default_uid, "control/ldapuid") == -1)
+		return -1;
+	if (default_uid != 0)
+		logit(64, "init_ldap: control/ldapuid: %i\n", default_uid);
+
+	if (control_readint(&default_gid, "control/ldapgid") == -1)
+		return -1;
+	if (default_gid != 0)
+		logit(64, "init_ldap: control/ldapgid: %i\n", default_gid);
+
+	if (control_rldef(&default_messagestore,
+		    "control/ldapmessagestore", 0, "") == -1)
+		return -1;
+	if (default_messagestore.len > 1) {
+		if (default_messagestore.s[default_messagestore.len-1] != '/')
+			if (!stralloc_append(&default_messagestore, "/"))
+				return -1;
+		logit(64, "init_ldap: control/ldapmessagestore: %S\n", 
+		    &default_messagestore);
+	} else
+		if (!stralloc_copys(&default_messagestore, "")) return -1;
+
+	if (control_rldef(&dotmode, "control/ldapdefaultdotmode",
+		    0, "ldaponly") == -1) return -1;
+	if (!stralloc_0(&dotmode)) return -1;
+	logit(64, "init_ldap: control/ldapdefaultdotmode: %s\n", dotmode.s);
+
+	if (control_readulong(&quotasize, "control/defaultquotasize") == -1) 
+		return -1;
+	if (control_readulong(&quotacount, "control/defaultquotacount") == -1) 
+		return -1;
+	logit(64, "init_ldap: control/defaultquotasize: %u\n", quotasize);
+	logit(64, "init_ldap: control/defaultquotacount: %u\n", quotacount);
+
+	return 0;
+}
+
+int
+qldap_need_rebind(void)
+{
+	return rebind;
+}
+
+char *
+qldap_basedn(void)
+{
+	return basedn.s;
+}
+
+qldap *
+qldap_new(void)
+{
+	qldap *q;
+
+	q = (qldap *)alloc(sizeof(qldap));
+	if (q == 0) return (qldap *)0;
+	byte_zero(q, sizeof(qldap));
+	return q;
+}
+
+/******  LDAP OPEN, BIND & CLOSE  *********************************************/
+
+int
+qldap_open(qldap *q)
+{
+	int rc;
+
+	CHECK(q, OPEN);
+	
+	/* allocate the connection */
+	if ((q->ld = ldap_init(ldap_server.s,LDAP_PORT)) == 0) {
+		logit(128, "qldap_open: init failed\n");
+		return ERRNO;
+	}
+	logit(128, "qldap_open: init successful\n");
+
+	rc = qldap_set_option(q, 0);
+	if (rc != OK)
+		logit(128, "qldap_open: qldap_set_option failed\n");
+	q->state = rc==OK?OPEN:ERROR;
+	return rc;
+}
+
+int
+qldap_bind(qldap *q, const char *binddn, const char *passwd)
+{
+	int rc, try = 0;
+	
+	CHECK(q, BIND);
+
+	/* bind or rebind to the server with credentials */
+	if (binddn == (char *)0) {
+		/* use default credentials */
+		binddn = ldap_login.s;
+		passwd = ldap_password.s;
+	}
+
+retry:
+	/* connect to the LDAP server */
+	rc = ldap_simple_bind_s(q->ld, binddn, passwd);
+	try++;
+	/* probably more detailed information should be returned, eg.:
+	   LDAP_STRONG_AUTH_NOT_SUPPORTED,
+	   LDAP_STRONG_AUTH_REQUIRED,
+	   *LDAP_INAPPROPRIATE_AUTH*,
+	   LDAP_AUTH_UNKNOWN
+	 */
+	switch (rc) {
+	case LDAP_SUCCESS:
+		logit(128, "qldap_bind: successful\n");
+		q->state = BIND;
+		return OK;
+	case LDAP_TIMELIMIT_EXCEEDED:
+	case LDAP_SERVER_DOWN:
+		logit(128, "qldap_bind: failed (%s)\n", ldap_err2string(rc));
+		q->state = ERROR;
+		return LDAP_BIND_UNREACH;
+	case LDAP_INVALID_CREDENTIALS:
+		logit(128, "qldap_bind: failed (%s)\n", ldap_err2string(rc));
+		q->state = ERROR;
+		return LDAP_BIND_AUTH;
+	case LDAP_PROTOCOL_ERROR:
+		logit(128, "qldap_bind: failed wrong protocol (%s)\n",
+		    ldap_err2string(rc));
+		/* bind failed try Version 2 */
+		if (try > 1) break;
+		logit(128, "qldap_bind: retrying bind with Version 1\n");
+		qldap_close(q);
+		rc = qldap_open(q);
+		logit(128, "qldap_bind: opened conection for Version 1\n");
+		qldap_set_option(q, 1);
+		logit(128, "qldap_bind: set options for Version 1\n");
+		if (rc != OK) break;
+		goto retry;
+	default:
+		logit(128, "qldap_bind: failed (%s)\n", ldap_err2string(rc));
+		break;
+	}
+	q->state = ERROR;
+	return FAILED;
+}
+
+int
+qldap_rebind(qldap *q, const char *binddn, const char *passwd)
+{
+	int rc;
+
+	CHECK(q, REBIND);
+
+	if (!STATEIN(q, OPEN)) {
+		qldap_close(q);
+		rc = qldap_open(q);
+		if (rc != OK) return rc;
+	}
+	return qldap_bind(q, binddn, passwd);
+}
+
+static  int
+qldap_close(qldap *q)
+{
+	CHECK(q, CLOSE);
+	
+	qldap_free_results(q); /* free results */
+	/* close and free ldap connection */
+	ldap_unbind_s(q->ld);
+	q->state = CLOSE;
+	return OK;
+}
+
+int
+qldap_free_results(qldap *q)
+{
+	if (STATEIN(q, SEARCH) || STATEIN(q, EXTRACT)) {
+		ldap_msgfree(q->res);
+		q->res = (LDAPMessage *)0;
+		q->msg = (LDAPMessage *)0;
+	}
+	return OK;
+}
+
+int
+qldap_free(qldap *q)
+{
+	qldap_free_results(q);
+	if (!STATEIN(q, NEW) && !STATEIN(q, CLOSE))
+		qldap_close(q);
+	byte_zero(q, sizeof(qldap));
+	alloc_free(q);
+	return OK;
+}
+
+/******  LDAP SEARCH & FILTER  ************************************************/
+
+int
+qldap_lookup(qldap *q, const char *filter, const char *attrs[])
+{
+	/* search a unique entry */
+	struct timeval	tv;
+	int		rc;
+	unsigned int	num_entries;
+	
+	CHECK(q, SEARCH);
+	
+	tv.tv_sec = ldap_timeout;
+	tv.tv_usec = 0;
+
+	rc = ldap_search_st(q->ld, basedn.s, LDAP_SCOPE_SUBTREE,
+		filter, (char **)attrs, 0, &tv, &q->res);
+	
+	switch (rc) {
+	/* probably more detailed information should be returned, eg.:
+	   LDAP_TIMELIMIT_EXCEEDED,
+	   LDAP_SIZELIMIT_EXCEEDED,
+	   LDAP_PARTIAL_RESULTS,
+	   LDAP_INSUFFICIENT_ACCESS,
+	   LDAP_BUSY,
+	   LDAP_UNAVAILABLE,
+	   LDAP_UNWILLING_TO_PERFORM,
+	   LDAP_TIMEOUT
+	 */
+
+	case LDAP_SUCCESS:
+		logit(128, "qldap_lookup: search for %s succeeded\n",
+		    filter);
+		break;
+	case LDAP_TIMEOUT:
+	case LDAP_TIMELIMIT_EXCEEDED:
+	case LDAP_BUSY:
+		logit(64, "qldap_lookup: search for %s failed (%s)\n", 
+		    filter, ldap_err2string(rc) );
+		return TIMEOUT;
+	case LDAP_NO_SUCH_OBJECT:
+		logit(64, "qldap_filter: search for %s failed (%s)\n", 
+		    filter, ldap_err2string(rc) );
+		return NOSUCH;
+	default:
+		logit(64, "qldap_lookup: search for %s failed (%s)\n", 
+		    filter, ldap_err2string(rc) );
+		return FAILED;
+	}
+
+	/* count the results, we must have exactly one */
+	num_entries = ldap_count_entries(q->ld, q->res);
+	if (num_entries != 1) {
+		if (num_entries > 1) {
+			logit(64, "qldap_lookup: Too many entries found (%i)\n", 
+			    num_entries);
+			return TOOMANY;
+		} else {
+			logit(64, "qldap_lookup: Nothing found\n"); 
+			return NOSUCH;
+		}
+	}
+	/* go to the first entry */
+	q->msg = ldap_first_entry(q->ld, q->res);
+	
+	/*
+	 * We already selected the first and only entry so
+	 * skip SEARCH state and move directly to EXTRACT state.
+	 */
+	q->state = EXTRACT;
+	return OK;
+}
+
+int
+qldap_filter(qldap *q, const char *filter, const char *attrs[],
+    char *bdn, int scope)
+{
+	
+	/* search a unique entry */
+	struct	timeval tv;
+	int	rc;
+	
+	/* search multiple entries */
+	CHECK(q, SEARCH);
+	
+	switch (scope) {
+	case SCOPE_BASE:
+		scope = LDAP_SCOPE_BASE;
+		break;
+	case SCOPE_ONELEVEL:
+		scope = LDAP_SCOPE_ONELEVEL;
+		break;
+	case SCOPE_SUBTREE:
+		scope = LDAP_SCOPE_SUBTREE;
+		break;
+	default:
+		return FAILED;
+	}
+
+	tv.tv_sec = ldap_timeout;
+	tv.tv_usec = 0;
+
+	rc = ldap_search_st(q->ld, bdn, scope, filter,
+	    (char **)attrs, 0, &tv, &q->res);
+	
+	switch (rc) {
+	/* probably more detailed information should be returned, eg.:
+	   LDAP_TIMELIMIT_EXCEEDED,
+	   LDAP_SIZELIMIT_EXCEEDED,
+	   LDAP_PARTIAL_RESULTS,
+	   LDAP_INSUFFICIENT_ACCESS,
+	   LDAP_BUSY,
+	   LDAP_UNAVAILABLE,
+	   LDAP_UNWILLING_TO_PERFORM,
+	   LDAP_TIMEOUT
+	 */
+
+	case LDAP_SUCCESS:
+		logit(128, "qldap_filter: search for %s succeeded\n",
+		    filter);
+		break;
+	case LDAP_TIMEOUT:
+	case LDAP_TIMELIMIT_EXCEEDED:
+	case LDAP_BUSY:
+		logit(64, "qldap_filter: search for %s failed (%s)\n", 
+		    filter, ldap_err2string(rc) );
+		return TIMEOUT;
+	case LDAP_NO_SUCH_OBJECT:
+		logit(64, "qldap_filter: search for %s failed (%s)\n", 
+		    filter, ldap_err2string(rc) );
+		return NOSUCH;
+	default:
+		logit(64, "qldap_filter: search for %s failed (%s)\n", 
+		    filter, ldap_err2string(rc) );
+		return FAILED;
+	}
+	
+	q->state = SEARCH;
+	return OK;
+}
+
+int
+qldap_count(qldap *q)
+{
+	CHECK(q, EXTRACT);
+	return ldap_count_entries(q->ld, q->res);
+}
+
+int
+qldap_first(qldap *q)
+{
+	CHECK(q, EXTRACT);
+	/* get first match of a qldap_filter search */
+
+	q->msg = ldap_first_entry(q->ld, q->res);
+	if (q->msg == (LDAPMessage *)0) {
+		if (ldap_count_entries(q->ld, q->res) == 0)
+			return NOSUCH;
+		else
+			return FAILED;
+	}
+	q->state = EXTRACT;
+	return OK;
+}
+
+int
+qldap_next(qldap *q)
+{
+	CHECK(q, EXTRACT);
+	/* get next match of a qldap_filter search */
+	if (q->msg == 0) return FAILED;
+
+	q->msg = ldap_next_entry(q->ld, q->msg);
+	if (q->msg == (LDAPMessage*)0)
+		return NOSUCH;
+	q->state = EXTRACT;
+	return OK;
+}
+
+/******  ATTRIBUTE EXTRACTION *************************************************/
+
+static stralloc ldap_attr = {0};
+
+int
+qldap_get_uid(qldap *q, unsigned int *uid)
+{
+	unsigned long	ul;
+	int		r;
+
+	/* get and check the uid */
+	r = qldap_get_attr(q, LDAP_QMAILUID, &ldap_attr, SINGLE_VALUE);
+	if (r == OK) {
+		if (ldap_attr.s[scan_ulong(ldap_attr.s, &ul)] != '\0')
+			r = BADVAL;
+		else if (UID_MIN <= ul && ul <= UID_MAX)
+			*uid = ul;
+		else
+			r = ILLVAL;
+	} else if (r == NOSUCH && default_uid != 0) {
+		*uid = default_uid;
+		return OK;
+	} else if (r == NOSUCH)
+		return NEEDED;
+	return r;
+}
+
+int
+qldap_get_gid(qldap *q, unsigned int *gid)
+{
+	unsigned long	ul;
+	int		r;
+
+	/* get and check the gid */
+	r = qldap_get_attr(q, LDAP_QMAILGID, &ldap_attr, SINGLE_VALUE);
+	if (r == OK) {
+		if (ldap_attr.s[scan_ulong(ldap_attr.s, &ul)] != '\0')
+			r = BADVAL;
+		else if (GID_MIN <= ul && ul <= GID_MAX)
+			*gid = ul;
+		else
+			r = ILLVAL;
+	} else if (r == NOSUCH && default_gid != 0) {
+		*gid = default_gid;
+		return OK;
+	} else if (r == NOSUCH)
+		return NEEDED;
+	return r;
+}
+
+int
+qldap_get_mailstore(qldap *q, stralloc *hd, stralloc *ms)
+{
+	int	r;
+	/* 
+	 * get and check the mailstores.
+	 * Both homedir and maildir are set from the three
+	 * values ~control/ldapmessagestore, homedirectory
+	 * and mailmessagestore.
+	 * ms is only filled with a value if both homedir
+	 * and maildir is used.
+	 */
+	r = qldap_get_attr(q, LDAP_HOMEDIR, hd, SINGLE_VALUE);
+	if (r == NOSUCH) {
+		if (!stralloc_copys(hd, "")) return ERRNO;
+	} else if (r != OK)
+		return r;
+	if (0 < hd->len) {
+		if (hd->s[0] != '/' || check_paths(hd->s) == 0) {
+			/* probably some log warning would be good */
+			return ILLVAL;
+		}
+	}
+	
+	r = qldap_get_attr(q, LDAP_MAILSTORE, ms, SINGLE_VALUE);
+	if (r == NOSUCH) {
+		if (!stralloc_copys(ms, "")) return ERRNO;
+	} else if (r != OK)
+		return r;
+	if (ms->len > 0)
+		if (check_paths(ms->s) == 0) {
+			/* probably some log warning would be good */
+			return ILLVAL;
+		}
+	
+	if (hd->len > 0 && ms->len > 0) return OK;
+	if (hd->len > 0) return OK;
+	if (ms->len > 0) {
+		if (ms->s[0] != '/') {
+			if (default_messagestore.s == 0 ||
+			    default_messagestore.len == 0)
+				return ILLVAL;
+			if (!stralloc_cat(hd, &default_messagestore))
+				return ERRNO;
+		}
+		if (!stralloc_cat(hd, ms))
+			return ERRNO;
+		if (!stralloc_copys(ms, "")) return ERRNO;
+		return OK;
+	}
+	return NEEDED;
+}
+
+int
+qldap_get_user(qldap *q, stralloc *user)
+{
+	int	r;
+
+	/* get the user name */
+	r = qldap_get_attr(q, LDAP_UID, user, SINGLE_VALUE);
+	if (r != OK) return r;
+	if (check_users(user->s) == 0) {
+		/* probably some log warning would be good */
+		return ILLVAL;
+	}
+	return r;
+}
+
+int
+qldap_get_status(qldap *q, int *status)
+{
+	int	r;
+	
+	/* default value */
+	*status = STATUS_UNDEF;
+	/* get and check the status of the account */
+	r = qldap_get_attr(q, LDAP_ISACTIVE, &ldap_attr, SINGLE_VALUE);
+	if (r == NOSUCH) {
+		return OK;
+	} else if (r == OK) {
+		if (!case_diffs(ldap_attr.s, ISACTIVE_BOUNCE))
+			*status = STATUS_BOUNCE;
+		else if (!case_diffs(ldap_attr.s, ISACTIVE_DELETE))
+			*status = STATUS_DELETE;
+		else if (!case_diffs(ldap_attr.s, ISACTIVE_NOACCESS))
+			*status = STATUS_NOACCESS;
+		else	*status = STATUS_OK; /* default to OK */
+		/* perhaps we should spill out a warning for unknown settings */
+		return OK;
+	}
+	return r;
+}
+
+int
+qldap_get_dotmode(qldap *q, stralloc *dm)
+{
+	int	r;
+
+	/* get and check the status of the account */
+	r = qldap_get_attr(q, LDAP_DOTMODE, &ldap_attr, SINGLE_VALUE);
+	if (r == NOSUCH) {
+		if (!stralloc_copy(dm, &dotmode)) return ERRNO;
+		return OK;
+	}
+	if (r != OK)
+		return r;
+
+	if (!case_diffs(DOTMODE_LDAPONLY, ldap_attr.s)) {
+		if (!stralloc_copys(dm, DOTMODE_LDAPONLY)) return ERRNO;
+	} else if (!str_diff(DOTMODE_LDAPWITHPROG, ldap_attr.s)) {
+		if (!stralloc_copys(dm, DOTMODE_LDAPWITHPROG)) return ERRNO;
+	} else if (!str_diff(DOTMODE_DOTONLY, ldap_attr.s)) {
+		if (!stralloc_copys(dm, DOTMODE_DOTONLY)) return ERRNO;
+	} else if (!str_diff(DOTMODE_BOTH, ldap_attr.s)) {
+		if (!stralloc_copys(dm, DOTMODE_BOTH)) return ERRNO;
+	} else if (!str_diff(DOTMODE_NONE, ldap_attr.s)) {
+		if (!stralloc_copys(dm, DOTMODE_NONE)) return ERRNO;
+	} else {
+		return ILLVAL;
+	}
+	if (!stralloc_0(dm)) return ERRNO;
+	return OK;
+}
+
+int
+qldap_get_quota(qldap *q, unsigned long *size, unsigned long *count,
+    unsigned long *max)
+/* XXX move to a quota file? Currently I don't think so. */
+{
+	int	r;
+	
+	*size = quotasize;
+	*count = quotacount;
+	*max = 0;
+	
+	/* First get the maximum mail size. */
+	r = qldap_get_ulong(q, LDAP_MAXMSIZE, max);
+	if (r != OK && r != NOSUCH)
+		return r;
+
+	r = qldap_get_ulong(q, LDAP_QUOTA_SIZE, size);
+	if (r != OK && r != NOSUCH)
+		return r;
+	r = qldap_get_ulong(q, LDAP_QUOTA_COUNT, count);
+	if (r != OK && r != NOSUCH)
+		return r;
+
+	return OK;
+}
+
+int
+qldap_get_dn(qldap *q, stralloc *dn)
+{
+	char *d;
+	
+	CHECK(q, EXTRACT);
+
+	d = ldap_get_dn(q->ld, q->msg);
+	if (d == (char *)0)
+		return NOSUCH;
+	if (!stralloc_copys(dn, d) || !stralloc_0(dn))
+		return ERRNO;
+#ifdef LDAP_OPT_PROTOCOL_VERSION
+	/*
+	 * OpenLDAP 1.x does not have ldap_memfree() use free() instead.
+	 */
+	ldap_memfree(d);
+#else
+	free(d);
+#endif
+	return OK;
+}
+
+int
+qldap_get_ulong(qldap *q, const char *attr, unsigned long *ul)
+{
+	unsigned long	ulval;
+	int		r;
+
+	r = qldap_get_attr(q, attr, &ldap_attr, SINGLE_VALUE);
+	if (r == OK) {
+		if (ldap_attr.s[scan_ulong(ldap_attr.s, &ulval)] != '\0')
+			return BADVAL;
+		*ul = ulval;
+	}
+	return r;
+}
+
+int
+qldap_get_bool(qldap *q, const char *attr, int *bool)
+{
+	int	r;
+
+	r = qldap_get_attr(q, attr, &ldap_attr, SINGLE_VALUE);
+	if (r == OK) {
+		if (!case_diffs("TRUE", ldap_attr.s))
+			*bool = 1;
+		else if (!case_diffs("1", ldap_attr.s))
+			*bool = 1;
+		else if (!case_diffs("FALSE", ldap_attr.s))
+			*bool = 0;
+		else if (!case_diffs("0", ldap_attr.s))
+			*bool = 0;
+		else
+			return BADVAL;
+	}
+	return r;
+}
+
+int
+qldap_get_attr(qldap *q, const char *attr, stralloc *val, int multi)
+{
+	char	**vals;
+	int	nvals, i, j, l, r;
+	char	sc = ':';
+	/*
+	 * extract value of attr if multivalue use ':' as
+	 * separator and escape the sep value with '\\'. 
+	 */
+	CHECK(q, EXTRACT);
+	
+	vals = ldap_get_values(q->ld, q->msg, attr);
+	if (vals == (char **)0) {
+#if 0
+		/*
+		 * XXX this does not work. ldap_result2error returns
+		 * the result of the bind action in other words success
+		 */
+		/* error occured maybe LDAP_NO_SUCH_ATTRIBUTE */
+		r = ldap_result2error(q->ld, q->msg, 0);
+		switch (r) {
+		case LDAP_NO_SUCH_ATTRIBUTE:
+			logit(128, "qldap_get_attr: %s\n",
+			    ldap_err2string(r));
+			return NOSUCH;
+		default:
+			logit(128, "qldap_get_attr: %s\n",
+			    ldap_err2string(r));
+			return FAILED;
+		}
+#endif
+		logit(128, "qldap_get_attr(%s): no such attribute\n", attr);
+		return NOSUCH;
+	}
+	nvals = ldap_count_values(vals);
+	
+	r = FAILED;
+	switch (multi) {
+	case SINGLE_VALUE:
+		if (nvals > 1) {
+			r = TOOMANY;
+			break;
+		}
+		if (!stralloc_copys(val, vals[0])) goto fail;
+		if (!stralloc_0(val)) goto fail;
+		r = OK;
+		break;
+	case MULTI_VALUE:
+		if (!stralloc_copys(val, "")) goto fail;
+		for (i = 0; i < nvals; i++) {
+			if (i != 0)
+				if (!stralloc_append(val, &sc))
+					goto fail;
+			l = str_len(vals[i]);
+			for (j = 0; j < l; j++) {
+				if (vals[i][j] == sc)
+					if (!stralloc_append(val, "\\"))
+						goto fail;
+				if (!stralloc_append(val, &vals[i][j]))
+					goto fail;
+			}
+		}
+		if (!stralloc_0(val)) goto fail;
+		r = OK;
+		break;
+	case OLDCS_VALUE:
+		if (!stralloc_copys(val, "")) goto fail;
+		for (i = 0; i < nvals; i++) {
+			if (i != 0) if (!stralloc_append(val, &sc)) goto fail;
+			byte_repl(vals[i], str_len(vals[i]), ',', sc);
+			if (!stralloc_cats(val, vals[i])) goto fail;
+		}
+		if (!stralloc_0(val)) goto fail;
+		r = OK;
+		break;
+	}
+	ldap_value_free(vals);
+
+	logit(128, "qldap_get_attr(%s): %s\n", attr, val->s);
+	return r;
+
+fail:
+	r = errno;
+	ldap_value_free(vals);
+	stralloc_copys(val, "");
+	errno = r;
+	return ERRNO;
+}
+
+/******  INTERNAL LDAP FUNCTIONS  *********************************************/
+
+/*
+ * The rebind procedure - this gets called when the application must
+ * perform a bind operation to follow a referral. Works only with OpenLDAP.
+ */
+#if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
+#if LDAP_VENDOR_VERSION >= 20100 /* Oh no! They changed again the api, honey. */
+static int dorebind(LDAP *, LDAP_CONST char *, ber_tag_t , ber_int_t, void *);
+#else
+static int dorebind(LDAP *, LDAP_CONST char *, int, ber_int_t);
+#endif
+
+#if LDAP_VENDOR_VERSION >= 20100 /* Oh no! They changed again the api, honey. */
+static int
+dorebind(LDAP *ld, LDAP_CONST char *url,
+    ber_tag_t request, ber_int_t msgid, void *dummy)
+#else
+static int
+dorebind(LDAP *ld, LDAP_CONST char *url, int request, ber_int_t msgid)
+#endif
+{
+	int		r;
+	LDAPURLDesc	*srv;
+
+	/* the url parse is just for debugging */
+	if( (r = ldap_url_parse(url, &srv)) != LDAP_SUCCESS) {
+		logit(64, "dorebind: parse url failed: %s\n",
+		    ldap_err2string(r));
+		return r;
+	}
+	/* Not request is defined in ldap.h - one of LDAP_REQ_XXXXX */
+	logit(64, "dorebind: referral - host %s:%d, dn \"%s\", "
+	    "request %d, msgid %d\n",
+	    srv->lud_host, srv->lud_port, srv->lud_dn, request, msgid);
+	ldap_free_urldesc(srv);
+
+	r = ldap_simple_bind_s(ld, ldap_login.s, ldap_password.s);
+	if (r != LDAP_SUCCESS) {
+		logit(64, "dorebind: ldap_simple_bind_s: %s\n",
+		    ldap_err2string(r));
+	}
+	return r;
+}
+#endif
+
+static int
+qldap_set_option(qldap *q, int forceV2)
+{
+#ifdef LDAP_OPT_PROTOCOL_VERSION
+	/*
+	 * OpenLDAP 1.x does not have ldap_set_option() so compile only if
+	 * available.
+	 */
+	int	rc, version;
+	
+	CHECK(q, OPEN);
+
+	if (forceV2 == 1) {
+		version = LDAP_VERSION2;
+		rc = ldap_set_option(q->ld,
+		    LDAP_OPT_PROTOCOL_VERSION, &version);
+		if (rc == LDAP_OPT_SUCCESS) {
+			logit(128, "qldap_set_option: LDAPv2 successful\n");
+			return OK;
+		} else {
+			logit(128, "qldap_set_option: LDAPv2 failed (%s)\n",
+			    ldap_err2string(rc));
+			return FAILED;
+		}
+	} else {
+		version = LDAP_VERSION3;
+		rc = ldap_set_option(q->ld,
+		    LDAP_OPT_PROTOCOL_VERSION, &version);
+		if (rc != LDAP_OPT_SUCCESS) {
+			logit(128, "qldap_set_option: failed (%s)\n",
+			    ldap_err2string(rc));
+			return qldap_set_option(q, 1);
+		}
+
+#if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
+		/*
+		 * currently we support referrals only with OpenLDAP >= 2.x
+		 * 1.x does not support it and the other SDKs have other
+		 * rebind functions.
+		 */
+#if LDAP_VENDOR_VERSION >= 20100 /* Oh no! They changed again the api, honey. */
+		rc = ldap_set_rebind_proc(q->ld, dorebind, (void *)0);
+#else
+		rc = ldap_set_rebind_proc(q->ld, dorebind);
+#endif
+		if (rc == LDAP_OPT_SUCCESS) {
+			rc = ldap_set_option(q->ld, LDAP_OPT_REFERRALS,
+			    LDAP_OPT_ON);
+		}
+		if (rc != LDAP_OPT_SUCCESS)
+			logit(128, "qldap_set_option: "
+			    "enabling referrals failed (%s)\n",
+			    ldap_err2string(rc));
+		else 
+			logit(128, "qldap_set_option: "
+			    "set referrals successful\n");
+		/* referral errors are ignored */
+#endif
+	}
+#endif
+	return OK;
+}
+
+static int
+check_next_state(qldap *q, int next)
+{
+	switch (next) {
+	case NEW:
+		/* NEW is a invalid next state */
+		return 0;
+	case OPEN:
+		/* current state is either NEW, OPEN or CLOSE */
+		if (STATEIN(q, NEW) || STATEIN(q, OPEN) || STATEIN(q, CLOSE))
+			return 1;
+		else
+			return 0;
+	case BIND:
+		/* current state is OPEN */
+		if (STATEIN(q, OPEN))
+			return 1;
+		else
+			return 0;
+	case SEARCH:
+		/* current state is one of BIND, SEARCH and EXTRACT */
+		if (STATEIN(q, BIND) || STATEIN(q, SEARCH) ||
+		    STATEIN(q, EXTRACT))
+			return 1;
+		else
+			return 0;
+	case EXTRACT:
+		/* current state is EXTRACT */
+		if (STATEIN(q, EXTRACT) || STATEIN(q, SEARCH))
+			return 1;
+		else
+			return 0;
+	case REBIND:
+		/* current state is either EXTRACT or OPEN */
+		if (STATEIN(q, EXTRACT) || STATEIN(q, OPEN))
+			return 1;
+		else
+			return 0;
+	case CLOSE:
+		/* all states allowed */ 
+		return 1;
+	case ERROR:
+		/* ERROR is a invalid next state */
+		return 0;
+	default:
+		/* bad state */
+		return 0;
+	}
+}
+
diff -ruN qmail-1.03-orig/qldap-cluster.c qmail-1.03-ldap-20060201-orig/qldap-cluster.c
--- qmail-1.03-orig/qldap-cluster.c	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/qldap-cluster.c	2006-02-25 11:00:55.000000000 +0100
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2003-2004 Claudio Jeker,
+ *      Internet Business Solutions AG, CH-8005 Zürich, Switzerland
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Internet Business
+ *      Solutions AG and its contributors.
+ * 4. Neither the name of the author nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#ifdef QLDAP_CLUSTER
+#include "constmap.h"
+#include "control.h"
+#include "qldap-debug.h"
+#include "str.h"
+#include "stralloc.h"
+
+#include "qldap-cluster.h"
+
+static int		clusteron;
+static stralloc		me = {0};
+static stralloc		mh = {0};	/* buffer for constmap */
+static struct constmap	mailhosts_map;
+
+
+int
+cluster_init(void)
+{
+	clusteron = 0;	/* default is off */
+	
+	if (control_readline(&me, "control/me") != 1)
+		return -1;
+	if (control_readint(&clusteron, "control/ldapcluster") == -1)
+		return -1;
+	logit(64, "init: control/ldapcluster: %i\n", clusteron);
+
+	if (clusteron == 0)
+		return 0;
+	
+	if (control_readfile(&mh,"control/ldapclusterhosts",0) == -1)
+		return -1;
+	logit(64, "init_ldap: control/ldapclusterhosts: read\n");
+	if (!stralloc_cat(&mh, &me) || !stralloc_0(&mh))
+		return -1;
+	if (mailhosts_map.num != 0) constmap_free(&mailhosts_map);
+	if (!constmap_init(&mailhosts_map, mh.s, mh.len,0))
+		return -1;
+	return 0;
+}
+
+int
+cluster(char *mailhost)
+/* returns 1 if mail/connection needs to be forwarded else 0 */
+{
+	if (clusteron == 0 || mailhost == (char *)0)
+		return 0;
+	if (constmap(&mailhosts_map, mailhost, str_len(mailhost)) == 0)
+		return 1;
+	else
+		return 0;
+}
+
+stralloc *
+cluster_me(void)
+{
+	return &me;
+}
+
+#endif
diff -ruN qmail-1.03-orig/qldap-cluster.h qmail-1.03-ldap-20060201-orig/qldap-cluster.h
--- qmail-1.03-orig/qldap-cluster.h	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/qldap-cluster.h	2006-02-25 11:00:55.000000000 +0100
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2003-2004 Claudio Jeker,
+ *      Internet Business Solutions AG, CH-8005 Zürich, Switzerland
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Internet Business
+ *      Solutions AG and its contributors.
+ * 4. Neither the name of the author nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#ifndef __QLDAP_CLUSTER_H__
+#define __QLDAP_CLUSTER_H__
+
+int cluster_init(void);
+int cluster(char *mailhost);
+stralloc *cluster_me(void);
+
+#endif
diff -ruN qmail-1.03-orig/qldap-debug.c qmail-1.03-ldap-20060201-orig/qldap-debug.c
--- qmail-1.03-orig/qldap-debug.c	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/qldap-debug.c	2006-02-25 11:00:55.000000000 +0100
@@ -0,0 +1,171 @@
+/*
+ * Copyright (c) 2000-2004 Claudio Jeker,
+ *      Internet Business Solutions AG, CH-8005 Zürich, Switzerland
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Internet Business
+ *      Solutions AG and its contributors.
+ * 4. Neither the name of the author nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#include "output.h"
+#include "qldap-debug.h"
+#include "env.h"
+#include "scan.h"
+#include "readwrite.h"
+
+#include <stdarg.h>
+
+#ifdef ENABLE_PROFILE
+#include <taia.h>
+#endif
+
+#ifdef DEBUG
+
+/* 
+ * Known LOGLEVELs: 
+ *  1 = Error, only errors are reported (not verbose)
+ *  2 = Warning, errors and warnings are reported (normaly not verbose)
+ *  4 = Info, print some information (login name and success or fail)
+ *  8 = Info^2 (more info), session forwarding and maildirmake ...
+ * 16 = Debug, more information about authentication etc.
+ * 32 = Debug^2 (more debug info), even more ...
+ * 64 = LDAP-Debug, show everything in the ldap-module
+ *128 = some more LDAP-Debug stuff (good for ldap test tool)
+ *256 = PASSWD-Debug, this shows the encrypted and clear text passwords
+ *      so use it with care 
+ *1024= profiling output (if compiled with profile support)
+ */
+
+#define LOGLEN 256
+static int addLOG;
+static unsigned long loglevel;
+substdio sslog;
+char logbuffer[LOGLEN];
+
+void
+log_init(int fd, unsigned long mask, int via_spawn)
+/* 
+ * Known LOGLEVELs: 
+ */
+{
+	char *a = env_get("LOGLEVEL");
+	
+	loglevel = 0;
+	addLOG = via_spawn;
+	if ( a && *a ) {
+		scan_ulong(a, &loglevel);
+	} else if ((a = env_get("DEBUGLEVEL")) && *a ) {
+		scan_ulong(a, &loglevel);
+	}
+	loglevel &= mask;
+
+	substdio_fdbuf(&sslog, subwrite, fd, logbuffer, sizeof(logbuffer) );
+/*	logit(4, "LOGLEVEL set to %i\n", loglevel);
+ */
+}
+
+void
+logit(unsigned long level, const char *fmt, ...)
+/* see va_output (output.c) */
+{
+	va_list ap;
+	char ch;
+
+	va_start(ap, fmt);
+	if ( ! ( loglevel & level ) ) return;
+	ch = 15;
+	if ( addLOG ) if ( substdio_put(&sslog, &ch, 1) ) return;
+	va_output(&sslog, fmt, ap);
+	va_end(ap);
+	ch = 16;
+	if ( addLOG ) if ( substdio_put(&sslog, &ch, 1) ) return;
+	if ( substdio_flush(&sslog) == -1 ) return;
+}
+
+/* use logstart, logadd and logend with care, if there is no corresponding
+   start or end starnge messages will be loged or some important messages 
+   will be lost */
+void
+logstart(unsigned long level, const char *fmt, ...)
+{
+	va_list ap;
+	char ch;
+
+	va_start(ap, fmt);
+	if ( ! ( loglevel & level ) ) return;
+	ch = 15;
+	if ( addLOG ) if ( substdio_put(&sslog, &ch, 1) ) return;
+	va_output(&sslog, fmt, ap);
+	va_end(ap);
+}
+
+void
+logadd(unsigned long level, const char *fmt, ...)
+{
+	va_list ap;
+
+	va_start(ap, fmt);
+	if ( ! ( loglevel & level ) ) return;
+	va_output(&sslog, fmt, ap);
+	va_end(ap);
+}
+
+void
+logend(unsigned long level, const char *fmt, ...)
+{
+	va_list ap;
+	char ch;
+
+	va_start(ap, fmt);
+	if ( ! ( loglevel & level ) ) return;
+	va_output(&sslog, fmt, ap);
+	va_end(ap);
+	ch = 16;
+	if ( addLOG ) if ( substdio_put(&sslog, &ch, 1) ) return;
+	if ( substdio_flush(&sslog) == -1 ) return;
+}
+
+void
+profile(const char *s)
+{
+#ifdef ENABLE_PROFILE
+	char buf[TAIA_PACK];
+	struct taia t;
+
+	taia_now(&t);
+	taia_pack(buf,&t);
+	logit(LOG_PROFILE, "PROFILE: %s @%s\n", s, buf); 
+#endif
+}
+#else /* DEBUG */
+void log_init(int fd, unsigned long mask, int via_spawn) {}
+void logit(unsigned long level, const char *fmt, ...) {}
+void logstart(unsigned long level, const char *fmt, ...) {}
+void logadd(unsigned long level, const char *fmt, ...) {}
+void logend(unsigned long level, const char *fmt, ...) {}
+void profile(const char *s) {}
+#endif
diff -ruN qmail-1.03-orig/qldap-debug.h qmail-1.03-ldap-20060201-orig/qldap-debug.h
--- qmail-1.03-orig/qldap-debug.h	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/qldap-debug.h	2006-02-25 11:00:55.000000000 +0100
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2000-2004 Claudio Jeker,
+ *      Internet Business Solutions AG, CH-8005 Zürich, Switzerland
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Internet Business
+ *      Solutions AG and its contributors.
+ * 4. Neither the name of the author nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#ifndef __QLDAP_DEBUG_H__
+#define __QLDAP_DEBUG_H__
+
+extern void log_init(int fd, unsigned long mask, int via_spawn);
+extern void logit(unsigned long level, const char *fmt, ...);
+extern void logstart(unsigned long level, const char *fmt, ...);
+extern void logadd(unsigned long level, const char *fmt, ...);
+extern void logend(unsigned long level, const char *fmt, ...);
+extern void profile(const char *s);
+
+#define PROFILE(s) profile(s)
+
+#endif
diff -ruN qmail-1.03-orig/qldap-errno.c qmail-1.03-ldap-20060201-orig/qldap-errno.c
--- qmail-1.03-orig/qldap-errno.c	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/qldap-errno.c	2006-02-25 11:00:55.000000000 +0100
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2000-2004 Claudio Jeker,
+ *      Internet Business Solutions AG, CH-8005 Zürich, Switzerland
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Internet Business
+ *      Solutions AG and its contributors.
+ * 4. Neither the name of the author nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#include "qldap-errno.h"
+#include "error.h"
+
+/* XXX TODO needs to be removed */
+int qldap_errno;
+
+const char *qldap_err_str(int enbr)
+/* returns a string that corresponds to the qldap_errno */
+{
+	switch (enbr) {
+	case OK:
+		return "successful";
+	case ERRNO:
+		return error_str(errno);
+	case FAILED:
+		return "unspecified error";
+	case PANIC:
+		return "PANIC! Fatal error";
+
+	case NOSUCH:
+		return "no such object";
+	case TOOMANY:
+		return "too many objects";
+	case TIMEOUT:
+		return "operation timed out";
+
+	case BADVAL:
+		return "bad value";
+	case ILLVAL:
+		return "illegal value";
+	case NEEDED:
+		return "needed value is missing";
+
+	case BADPASS:
+		return "authorization failed, wrong password";
+	case FORWARD:
+		return "session needs to be forwarded";
+
+	case BADCLUSTER:
+		return "misconfigured cluster";
+	case ACC_DISABLED:
+		return "account disabled";
+	case AUTH_EXEC:
+		return "unable to start subprogram";
+	case AUTH_CONF:
+		return "configuration error";
+	case AUTH_TYPE:
+		return "unsupported authentication mode";
+
+	case MAILDIR_NONEXIST:
+		return "maildir/homedir does not exist";
+	case MAILDIR_UNCONF:
+		return "no dirmaker script configured";
+	case MAILDIR_CORRUPT:
+		return "maildir seems to be corrupted";
+	case MAILDIR_CRASHED:
+		return "dirmaker script crashed";
+	case MAILDIR_FAILED:
+		return "automatic maildir/homedir creation failed";
+	case MAILDIR_HARD:
+		return "hard error in maildir/homedir creation";
+		
+	case LDAP_BIND_UNREACH:
+		return "ldap server down or unreachable";
+	case LDAP_BIND_AUTH:
+		return "wrong bind password for ldap server";
+	default:
+		return "unknown error occured";
+	}
+}
+
diff -ruN qmail-1.03-orig/qldap-errno.h qmail-1.03-ldap-20060201-orig/qldap-errno.h
--- qmail-1.03-orig/qldap-errno.h	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/qldap-errno.h	2006-02-25 11:00:55.000000000 +0100
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2000-2004 Claudio Jeker,
+ *      Internet Business Solutions AG, CH-8005 Zürich, Switzerland
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Internet Business
+ *      Solutions AG and its contributors.
+ * 4. Neither the name of the author nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#ifndef __QLDAP_ERRNO_H__
+#define __QLDAP_ERRNO_H__
+
+/* XXX TODO cleanup */
+
+extern int qldap_errno;
+
+/* generic errors */
+#define OK			0	/* all OK */
+#define ERRNO			1	/* check errno for more info */
+#define FAILED			2	/* generic failed message */
+#define PANIC			3	/* fatal error happend */
+
+#define NOSUCH			4	/* no such object */
+#define TOOMANY			5	/* too many objects */
+#define TIMEOUT			6	/* operation timed out */
+
+#define BADVAL			7	/* bad value */
+#define ILLVAL			8	/* illegal value (check failed) */
+#define NEEDED			9	/* needed value is missing */
+
+#define BADPASS			10	/* auth failed wrong password */
+#define FORWARD			11	/* session needs to be forwarded */
+
+/* auth_mod and checkpassword specific errors */
+#define BADCLUSTER		20	/* bad settings for clustering */
+#define ACC_DISABLED		21	/* account disabled */
+#define AUTH_EXEC		22	/* unable to start subprogram */
+#define AUTH_CONF		23	/* configuration error */
+#define AUTH_TYPE		24	/* unsuportet auth type */
+
+/* maildirmake specific errors */
+#define MAILDIR_NONEXIST	25	/* maildir/homedir does not exist */
+#define MAILDIR_UNCONF		26	/* no dirmaker script configured */
+#define MAILDIR_CORRUPT		27	/* maildir seems to be corrupted */
+#define MAILDIR_CRASHED		28	/* dirmaker script crashed */
+#define MAILDIR_FAILED		29	/* automatic maildir creation failed */
+#define MAILDIR_HARD		30	/* hard error in maildir creation */
+
+/* LDAP specific errnos */
+#define LDAP_BIND_UNREACH	31	/* ldap server down or unreachable */
+#define LDAP_BIND_AUTH		32	/* wrong bind password */
+
+const char *qldap_err_str(int enbr);
+/* returns a string that corresponds to the qldap_errno */
+
+#endif
diff -ruN qmail-1.03-orig/qldap-filter.c qmail-1.03-ldap-20060201-orig/qldap-filter.c
--- qmail-1.03-orig/qldap-filter.c	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/qldap-filter.c	2006-02-25 11:00:55.000000000 +0100
@@ -0,0 +1,210 @@
+/*
+ * Copyright (c) 2003-2004 Claudio Jeker,
+ *      Internet Business Solutions AG, CH-8005 Zürich, Switzerland
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Internet Business
+ *      Solutions AG and its contributors.
+ * 4. Neither the name of the author nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#include "auto_break.h"
+#include "qldap.h"
+#include "qmail-ldap.h"
+#include "str.h"
+#include "stralloc.h"
+
+static stralloc escapedstr = {0};
+/*
+ * For LDAP, '(', ')', '\', '*' and '\0' have to be escaped with '\'.
+ * We ignore the '\0' case because it is not possible to have a '\0' in s.
+ */
+char *
+filter_escape(char *s)
+{
+	char	x;
+
+	/* pre reserve some space */
+	if (!stralloc_ready(&escapedstr, str_len(s))) return 0;
+	if (!stralloc_copys(&escapedstr, "")) return 0;
+	do {
+		x = *s;
+		if (x == '*' || x == '(' || x == ')' || x == '\\')
+			if (!stralloc_append(&escapedstr, "\\")) return 0;
+		if (!stralloc_append(&escapedstr, s)) return 0;
+	} while (*s++);
+	return escapedstr.s;
+}
+
+static stralloc ocfilter = {0};
+extern stralloc	objectclass;
+
+char *
+filter_objectclass(char *searchfilter)
+{
+
+	if (searchfilter == (char *)0) return 0;
+	if (objectclass.s == (char *)0 || objectclass.len == 0)
+		return searchfilter;
+	/* (&(objectclass=...)%searchfilter%) */
+	if (!stralloc_copys(&ocfilter, "(&(") ||
+	    !stralloc_cats(&ocfilter, LDAP_OBJECTCLASS) ||
+	    !stralloc_cats(&ocfilter, "=") ||
+	    !stralloc_cat(&ocfilter, &objectclass) ||
+	    !stralloc_cats(&ocfilter, ")") ||
+	    !stralloc_cats(&ocfilter, searchfilter) ||
+	    !stralloc_cats(&ocfilter, ")") ||
+	    !stralloc_0(&ocfilter))
+		return 0;
+	return ocfilter.s;
+}
+
+static stralloc filter = {0};
+
+char *
+filter_uid(char *uid)
+{
+	char	*escaped;
+	
+	if (uid == (char *)0) return 0;
+	
+	escaped = filter_escape(uid);
+	if (escaped == (char *)0) return 0;
+	
+	if (!stralloc_copys(&filter,"(") ||
+	    !stralloc_cats(&filter, LDAP_UID) ||
+	    !stralloc_cats(&filter, "=") ||
+	    !stralloc_cats(&filter, escaped) ||
+	    !stralloc_cats(&filter, ")") ||
+	    !stralloc_0(&filter))
+		return (char *)0;
+	return filter_objectclass(filter.s);
+}
+
+static int extcnt;
+
+
+char *
+filter_mail(char *mail, int *done)
+{
+	static char		*escaped;
+	static unsigned int	at, ext, len = 0;
+#ifdef DASH_EXT
+	unsigned int 		i;
+#endif
+
+	if (mail == (char *)0) {
+		len = 0;
+		return 0;
+	}
+
+	if (len == 0) {
+		escaped = filter_escape(mail);
+		if (escaped == (char *)0) return 0;
+		len = str_len(escaped);
+		at = str_rchr(escaped, '@');
+		if (escaped[at] != '@') {
+			len = 0;
+			return 0;
+		}
+		ext = at;
+		extcnt = -1;
+		*done = 0;
+	} else {
+		if (extcnt == 0) {
+			*done = 1;
+			return 0;
+		}
+#ifdef DASH_EXT
+		/*
+		 * limit ext to the first DASH_EXT_LEVELS extensions.
+		 * We will only check for (DASH_EXT_LEVELS = 4):
+		 * a-b-c-d-e-f-g-...@foobar.com
+		 * a-b-c-d-catchall@foobar.com
+		 * a-b-c-catchall@foobar.com
+		 * a-b-catchall@foobar.com
+		 * a-catchall@foobar.com
+		 * catchall@foobar.com
+		 */
+		if (ext == at)
+			for (i = 0, ext = 0, extcnt = 1;
+			    ext < at && extcnt <= DASH_EXT_LEVELS; ext++)
+				if (escaped[ext] == *auto_break) extcnt++;
+		while (ext != 0 && --ext > 0) {
+			if (escaped[ext] == *auto_break) break;
+		}
+		extcnt--;
+#else
+		/* basic qmail-ldap behavior test for username@domain.com and
+		   catchall@domain.com */
+		ext = 0;
+		extcnt = 0;
+#endif
+	}
+	
+	/* build the search string for the email address */
+	if (!stralloc_copys(&filter, "(|(" )) return 0;
+	/* mail address */
+	if (!stralloc_cats(&filter, LDAP_MAIL)) return 0;
+	if (!stralloc_cats(&filter, "=")) return 0;
+	/* username till current '-' */
+	if (!stralloc_catb(&filter, escaped, ext)) return 0;
+	if (ext != at) { /* do not append catchall in the first round */
+		/* catchall or default */
+		if (extcnt > 0) /* add '-' */
+			if (!stralloc_cats(&filter, auto_break))
+				return 0;
+		if (!stralloc_cats(&filter, LDAP_CATCH_ALL)) return 0;
+	}
+	/* @damin.com */
+	if (!stralloc_catb(&filter, escaped+at, len-at)) return 0;
+
+	/* mailalternate address */
+	if (!stralloc_cats(&filter, ")(")) return 0;
+	if (!stralloc_cats(&filter, LDAP_MAILALTERNATE)) return 0;
+	if (!stralloc_cats(&filter, "=")) return 0;
+	/* username till current '-' */
+	if (!stralloc_catb(&filter, escaped, ext)) return 0;
+	if (ext != at) { /* do not append catchall in the first round */
+		/* catchall or default */
+		if (extcnt > 0) /* add '-' */
+			if (!stralloc_cats(&filter, auto_break)) return 0;
+		if (!stralloc_cats(&filter, LDAP_CATCH_ALL)) return 0;
+	}
+	/* @domain.com */
+	if (!stralloc_catb(&filter, escaped+at, len-at)) return 0;
+	if (!stralloc_cats(&filter, "))")) return 0;
+	if (!stralloc_0(&filter)) return 0;
+
+	if (extcnt == 0) *done = 1;
+	return filter_objectclass(filter.s);
+}
+
+int
+filter_mail_ext(void)
+{
+	return extcnt;
+}
diff -ruN qmail-1.03-orig/QLDAPGROUP qmail-1.03-ldap-20060201-orig/QLDAPGROUP
--- qmail-1.03-orig/QLDAPGROUP	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/QLDAPGROUP	2006-02-25 11:00:55.000000000 +0100
@@ -0,0 +1,170 @@
+QMAILGROUP by Claudio Jeker <jeker@n-r-g.com>
+(c) 2004 Internet Business Solutions Ltd.
+
+
+RELEASE: $Date: 2004/12/01 14:19:49 $ ($Revision: 1.3 $)
+
+qmail-group and qmail-secretary:
+====================================
+
+While it is possible to implement simple mail distributors via multiple
+mailFrowarding entries in qmail-ldap it is not possible to do more complex or
+dynamic mail distributors. qmail-group adds this capability -- with the help of
+qmail-secretary -- to qmail-ldap.
+
+qmail-group extends the basic qmailUser object with a new LDAP objectclass
+qmailGroup. The new object adds fields to specify members, senders and
+moderators for the list together with some standard settings. To define a
+mailing group both qmailUser and qmailGroup objects are necessary.
+
+LDAP Schema:
+
+In addition to the qmailUser attributes the following additional attributes are
+defined by qmailGroup:
+
+senderconfirm:
+  If this boolean attribute is set to true than an incomming mail needs to be
+  approved by the sender. This ensures that the sender is aware that he is
+  sending to a list and makes it almost impossible to send forged mails, spam,
+  mail viruses and other junk to be distributed to list. If sender confirmation
+  is used a confirmation message is sent to the sender. This needs to reply to
+  that message if he does not do that the mail will be deleted after 1 week.
+  By default senderconfirmation is turned off.
+
+membersonly:
+  If this boolean attribute is set to true than an incomming mail needs to come
+  from a member of the list. Only the envelope sender address is used for the
+  check. Because it is easy to forge the envelope sender address sender-
+  confirmation should be enabled too.
+
+dnmember:
+filtermember:
+rfc822member:
+  Members of the group are specified by these attributes. It is possible to
+  specify a member by a LDAP distinguish name, a LDAP filter definiton or by
+  a rfc822 email address.
+ Example:
+  dnmember: uid=joe,ou=example,o=qmail-ldap,c=CH
+  filetrmember: ((objectclass=qmailUser)(employeeType=accountant))
+  rfc822member: alice@qmail-ldap.org
+
+dnsender:
+filtersender:
+rfc822sender:
+  It is possible to limit the allowed users to send to the list. If membersonly
+  is set to true and one of the sender attributes is set, mails to the list are
+  enforced to come form on of the specified senders. See also membersonly.
+
+dnmoderator:
+rfc822moderator:
+  The mail group can be moderated -- mails need to be approved by one of the
+  specified moderators. An approval message is sent t each specified moderator.
+  Again to approve a message on of the moderators needs to reply the approval
+  message. If no approval was sent in one week the mail is deleted.
+
+confirmtext:
+  This attribute can be used to specify a own confirm text used if sender-
+  confirmation is used. The usual %HEADER% magic of qmail-reply et al. can be
+  used here.
+
+moderatortext:
+  This attribute can be used to specify a own approval text used if the list
+  is moderated. The usual %HEADER% magic of qmail-reply et al. can be used
+  here too.
+
+bounceadmin:
+  Bounceadmin can be set to one or multiple rfc822 email addresses. Mail
+  delivery errors are then forwarded to these addresses instead of the sender
+  of the original mail.
+
+To enable a mail-group at least following qmailUser attributes need to be set
+too:
+
+mail: main mailaddress of the list
+mailalternateaddress: needs to be set to list-catchall@domain.tld, this is used
+  for moderation and sender confirmation but also for bounce handling.
+mailmessagestore: A valid messagestore for sender confirmation and moderation
+  is needed.
+
+
+qmail-secretary:
+
+qmail-secretary is a helper program for qmail-group and ezmlm. It implements
+both moderation and sender confirmation. qmail-group calls qmail-secretary
+internally but for ezmlm the .qmail files need to be adapted.
+
+usage (non ezmlm mode):
+qmail-secretary [ -Z ] [ -c | -C ] [[ -m addr ] ... ] [ -M file ] maildir
+
+usage (ezmlm mode):
+qmail-secretary -z ezmlmdir [ -c | -C ] [[ -m addr ] ... ] [ -M file ]
+	maildir [ ezmlm-send ... ]
+
+Options:
+-C          Disable sender confirmation (default)
+-M file     Use file as a list of moderators. One per line.
+-Z          Non ezmlm mode (default).
+-c          Enable sender confirmation
+-m addr     Add addr to the list of moderators
+-z ezmlmdir Enable ezmlm mode and use ezmlmdir as base directory for
+            configuration.
+
+qmail-secretary uses the secified Maildir to store the messages that need
+approval. Messages that need to be confirmed are stored in maildir/new and
+messages waiting for moderation approval are stored in maildir/cur.
+
+In ezmlm mode following files from ezmlmdir are read:
+mailinglist  Address of the mailing list
+inhost       Incomming Host
+inlocal      Incomming Local Address part
+outhost      Outgoing Host
+outlocal     outgoing Local Address part
+text/approve The moderation approve request text
+text/confirm The sender confirmation request text
+
+In non ezmlm mode the information are extraceted from the environment. Mainly
+from:
+$LOCAL
+$SENDER
+$HOST
+$EXT
+$APPROVEMESS
+$CONFIRMMESS
+
+LOCAL, SENDER, HOST and EXT are set by qmail-local but APPROVEMESS and
+CONFIRMMESS can be set by the caller.
+
+Mails are tagged with a cryptographic hash. Sender confirmations are received
+by $LOCAL-confirm-<HASH>@$HOST and bounces end in $LOCAL-reject-<HASH>@$HOST.
+Moderation messages are received by $LOCAL-approve-<HASH>@$HOST and bounces
+end in $LOCAL-bounce-<HASH>@$HOST.
+
+Simple setup:
+Following qmail files should be set for sender confirmation..
+
+.qmail
+|qmail-secretary -c ./Maildir/secretary
+<other deliveries>
+
+.qmail-confirm-default
+|qmail-secretary -c ./Maildir/secretary
+
+.qmail-reject-default
+|qmail-secretary -c ./Maildir/secretary
+
+It is possible to just add a .qmail-default instead of .qmail-confirm-default
+and .qmail-reject-default.
+
+Simple ezmlm setup:
+.qmail
+|qmail-secretary -c -z ezmlmdir ezmlmdir/secretary/ ezmlm-send ezmlmdir
+|ezmlm-send ezmlmdir
+|ezmlm-warn ezmlmdir || exit 0
+
+.qmail-default
+|qmail-secretary -c -z ezmlmdir ezmlmdir/secretary/ ezmlm-send ezmlmdir
+|ezmlm-manage ezmlmdir
+|ezmlm-warn ezmlmdir || exit 0
+
+The other .qmail files don't need to be modified.
+
diff -ruN qmail-1.03-orig/qldap.h qmail-1.03-ldap-20060201-orig/qldap.h
--- qmail-1.03-orig/qldap.h	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/qldap.h	2006-02-25 11:00:55.000000000 +0100
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2003-2004 Andre Oppermann, Claudio Jeker,
+ *      Internet Business Solutions AG, CH-8005 Zürich, Switzerland
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Internet Business
+ *      Solutions AG and its contributors.
+ * 4. Neither the name of the author nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#ifndef __QLDAP_H__
+#define __QLDAP_H__
+
+#include "stralloc.h"
+
+#define SINGLE_VALUE	1
+#define MULTI_VALUE	2
+#define OLDCS_VALUE	3
+
+#define SCOPE_BASE	0x10
+#define SCOPE_ONELEVEL	0x20
+#define SCOPE_SUBTREE	0x30
+
+typedef struct qldap qldap;
+
+int qldap_ctrl_login(void);
+int qldap_ctrl_trylogin(void);
+int qldap_ctrl_generic(void);
+int qldap_need_rebind(void);
+char *qldap_basedn(void);
+qldap *qldap_new(void);
+
+/* possible errors:
+ * init: FAILED, ERRNO
+ * bind: FAILED, LDAP_BIND_UNREACH, LDAP_BIND_AUTH
+ * rebind: FAILED, ERRNO, LDAP_BIND_UNREACH, LDAP_BIND_AUTH
+ */
+int qldap_open(qldap *);
+int qldap_bind(qldap *, const char *, const char *);
+int qldap_rebind(qldap *, const char *, const char *);
+
+/* possible errors:
+ * all free functions return always OK
+ */
+int qldap_free_results(qldap *);
+int qldap_free(qldap *);
+
+/* possible errors:
+ * FAILED TIMEOUT TOOMANY NOSUCH
+ */
+int qldap_lookup(qldap *, const char *, const char *[]);
+
+/* possible errors:
+ * FAILED TIMEOUT NOSUCH
+ */
+int qldap_filter(qldap *, const char *, const char *[], char *, int);
+
+/*
+ * returns -1 on error
+ */
+int qldap_count(qldap *);
+
+/* possible errors:
+ * FAILED NOSUCH (no more results)
+ */
+int qldap_first(qldap *);
+int qldap_next(qldap *);
+
+/* possible errors of all get functions:
+ * FAILED ERRNO BADVAL ILLVAL NEEDED NOSUCH TOOMANY
+ */
+int qldap_get_uid(qldap *, unsigned int *);
+int qldap_get_gid(qldap *, unsigned int *);
+int qldap_get_mailstore(qldap *, stralloc *, stralloc *);
+int qldap_get_user(qldap *, stralloc *);
+int qldap_get_status(qldap *, int *);
+int qldap_get_dotmode(qldap *, stralloc *);
+int qldap_get_quota(qldap *, unsigned long *, unsigned long *, unsigned long *);
+
+int qldap_get_dn(qldap *, stralloc *);
+int qldap_get_ulong(qldap *, const char *, unsigned long *);
+int qldap_get_bool(qldap *, const char *, int *);
+int qldap_get_attr(qldap *, const char *, stralloc *, int);
+
+/* qldap-filter.c */
+char *filter_escape(char *);
+char *filter_objectclass(char *);
+char *filter_uid(char *);
+char *filter_mail(char *, int *);
+int filter_mail_ext(void);
+#endif
diff -ruN qmail-1.03-orig/QLDAPINSTALL qmail-1.03-ldap-20060201-orig/QLDAPINSTALL
--- qmail-1.03-orig/QLDAPINSTALL	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/QLDAPINSTALL	2006-02-25 11:00:55.000000000 +0100
@@ -0,0 +1,1325 @@
+QMAIL_LDAP by Andre Oppermann <opi@nrg4u.com>,
+Claudio Jeker <jeker@n-r-g.com> and Boris Lutz <lutz@n-r-g.com>
+(c) 1998-2004 Internet Business Solutions AG
+
+The qmail-ldap patch for qmail comes with NO WARRANTY.
+
+This patch is under the BSD license. See LICENSE.
+
+RELEASE: current ($Date: 2006/01/30 14:53:05 $)
+
+TOC:
+ INSTALL                        how to install the patch
+ CONFIG FILES                   all about the extra config file
+ DEFAULT LDAP FIELDS            all about the fields in ldap
+ EXAMPLES                       example ldif and slapd.conf
+ MAILINGLIST, BUGS & PROBLEMS   How to help us helping you
+
+TODO:
+
+ see QLDAPTODO
+
+NEWS:
+
+ see QLDAPNEWS
+
+IMPORTANT NEWS:
+
+ - From release 20030901 on we broke certain backwards compatibility with
+   release 20030801 and prior releases for clarity and cleanup reasons!!
+
+ - tuned qmail-verify and ~control/goodmailaddr, now RCPTCHECK can be endabled
+   in almost all situations. See the goodmailaddr and RCPTCHECK entries in this
+   document for more info.
+
+ - and as always a lot of smaller patches see QLDAPNEWS
+
+================================================================================
+
+INSTALL:
+
+1. Make sure you have fairly good knowledge of qmail and LDAP
+   READ THEIR FAQs. PLEASE.
+
+2. Read this document. THIS IS IMPORTANT, this is no 
+   ./configure; make; make install software.
+   If you are not familiar with compiling software you should definitifly
+   read http://www.lifewithqmail.org/ldap/ first.
+
+3. You need the following compiled and installed
+    - OpenLDAP 2.x or higher (others might also work)
+      OpenLDAP releases < 2.0 should no longer be used (you have been warned).
+   and
+    - OpenSSL 0.9.4 or higher if you want TLS SMTP encrytion
+
+   We recommend also using Dan Bernstein's toolset daemontools-0.76,
+   ucspi-tcp-0.88 and djbdns-1.05 to run qmail.
+
+   If you have problems with OpenLDAP look into their FAQ. The same for
+   OpenSSL.
+   You NEED knowledge of LDAP so READ their FAQ and/or man pages.
+
+4. Apply the qmail-ldap patches to a clean qmail-1.03 source tree
+   normaly "cd qmail-1.03_source_tree; patch -p1 < location_of_patch"
+   works ;-). There seems to be a problem with the original patch utility
+   on Solaris based systems, use the gnu patch utility instead.
+   A pre-compiled binary should be available at http://www.sunfreeware.com/
+   or on many mirrors around the world.
+
+   NOTE: the qmail-ldap patches need to be applied to a clean qmail-1.03 tree
+         not netqmail. All netqmail patches have been integrated into qmail-ldap
+         a long time ago.
+
+5. Edit the conf-* files and the top of the Makefile (only the top ;-) )
+   You can set/change:
+   - LDAPFLAGS=
+               -DALTQUEUE (to enable alternate queue selection via environment
+                variable QMAILQUEUE. Also known as qmailqueue patch.)
+               -DBIGBROTHER (turn on per address queue extra feature see the
+                section about the ~control/bigbrother control file)
+               -DBIGTODO (to enable the big todo patch, can be used together
+                with EXTERNAL_TODO)
+               -DBIND_8_COMPAT needed on system with new incompatible
+                bind9 header files. Currently this is necessary on MacOS X 10.3.
+               -DCLEARTEXTPASSWD (for cleartext passwords in ldap, bad idea)
+               -DDASH_EXT (turn on dash_ext support see 5.3)
+               -DDATA_COMPRESS (to enable smtp on the fly data compression.
+                It is needed to set ZLIB accordingly.)
+               -DEXTERNAL_TODO (to use the external high-performancer
+               -DQLDAP_CLUSTER (turns the cluster support on)
+                todo processing)
+               -DQMQP_COMPRESS (to enable QMQP on the fly data compression.
+                Can be used in clusters. It is needed to set ZLIB accordingly.
+                IMPORTANT: this breaks compatibility with the stock qmqp
+                protocol. So either all qmail-qmqpc/-qmqpd use the on the fly
+                compression or non.)
+               -DSMTPEXECCHECK (to enable Russell Nelsons antivirus patch
+	        for qmail-smtpd. To turn it on set the REJECTEXEC env-var.)
+               -DDUPEALIAS (to make migration from some X.400 messaging
+                systems easier. See QLDAPNEWS 20031101 for more information.)
+
+   - LDAPLIBS: the libraries you need for ldap, e.g. -lldap -llber
+     NOTE: on Solaris Systems you probably need also -lnsl -lsocket
+           newer OpenLDAP libs my need also -lresolv (DNS support).
+           It is also good to set the ld runpath with the -R switch
+           for more info ld(1) or gcc(1) and 
+           http://www.lifewithqmail.org/ldap/.
+   - LDAPINCLUDES: perhaps you need a special include-path for ldap
+     NOTE: if you need this you may run into shared library problems
+           see http://www.lifewithqmail.org/ldap/.
+
+   - ZLIB is used when DATA_COMPRESS and QMAP_COMPRESS is defined. Normaly
+     -lz should work, if libz is installed in a different location use
+     -L/path/to/zlibdir -lz
+   - MNW=-DMAKE_NETSCAPE_WORK (turns on the patch that fixes the problem 
+     with the Netscape download progress bar and qmail-pop3d)
+
+   - MDIRMAKE=-DAUTOMAILDIRMAKE (turns the auto-MAILdir-make-patch on)
+   - HDIRMAKE=-DAUTOHOMEDIRMAKE (compiles the auto-HOMEdir-make-patch 
+     into the release, you need the ~control/dirmaker file to turn the 
+     patch on, see CONFIG FILES)
+
+   - SHADOWLIBS=-lcrypt is needed on most systems (except my OpenBSD box :-) )
+     SHADOWLIBS=-lcrypt -lshadow , SHADOWOPTS=-DPW_SHADOW are needed on some 
+     Systems (Solaris, Linux) for local password lookups 
+     (just like the original djb-checkpassword. See Makefile.)
+   - DEBUG=-DDEBUG (compiles debugging into the auth modules and qmail-ldap, 
+     see also 10.)
+   - TLS* stuff for TLS (SMTP encryption) mostly self explaining
+
+5.1 Have a look at qmail-ldap.h, perhaps you want to change something there.
+     LDAP_CATCH_ALL: used for catching mails for a specific domain.
+                     Also used for extension nameing with DASH_EXT.
+     QUOTA_WARNING_LEVEL: triger level for quotawarning in percent.
+     *ID_{MAX,MIN}:  upper and lower limit for uid's and gid's.
+     RESTRICT_PROG:  restrict delivery programm pathes to non special shell
+                     characters. See also next section 5.2
+     ALIASDEVNULL:   replacement for the std. aliasempty for user with
+                     neither homeDirectory nor mailMessageStore defined.
+     QLDAP_TIMEOUT:  Default ldap search timeout. In seconds.
+     LDAP_*:         Names of the ldap fields used for lookups.
+     DOTMODE_*:      Names for the different dot modes.
+     MODE_*:         Names for the different delivery modes.
+     ISACTIVE_*:     Names for the account status.
+
+5.2 Have a look at check.c if you want to change the ldap field check behaviour
+    In the standart patch we check for this (in regexp form):
+     user: [a-zA-Z0-9@_.][a-zA-Z0-9@_.-]* (for the LDAP_UID field)
+     path: [a-zA-Z0-9@_./:=][a-zA-Z0-9@_.-/:=]* 
+           (for LDAP_MAILSTORE and LDAP_HOMEDIR)
+     prog: [a-zA-Z0-9@_./:=\\\t\n "'+,][a-zA-Z0-9@_.-/:=\\\t\n "'+,]* 
+           (for LDAP_PROGRAM with RESTRICT_PROG on, if RESTRICT_PROG is 0
+           then most shell escape characters are also allowed. e.g [$#!%&()*;])
+
+5.3 Note on DASH_EXT:
+    Finally we added a variation of Henning Brauer's dash-ext patch. The main
+    difference is the way it handels the extensions.
+    Example lookup scheme:
+      aaaa-bbbb-cccc@domain.tld
+      aaaa-bbbb-CATCHALL@domain.tld
+      aaaa-CATCHALL@domain.tld
+      CATCHALL@domain.tld
+    where CATCHALL is replaced with the value of LDAP_CATCH_ALL defined
+    in qmail-ldap.h. If CATCHALL is set to "default" instead of the standart
+    "catchall" it is almost stock qmails behaviour.
+    Note: Only up to four levels of dash extensions are checked to prevent
+    DoS attacks. You can change that in qmail-ldap.h via DASH_EXT_LEVELS.
+
+6.  Compile and install the stuff (it's the same as in standard qmail
+    install -> HINT: read the INSTALL and the FAQ file!!! :) ).
+    Now everything should be installed with correct permissions.
+
+6.1 If "make setup check" fails with an error like this:
+       /usr/local/lib/libldap.so: undefined reference to `res_query' 
+       /usr/local/lib/libldap.so: undefined reference to `dn_expand'
+       collect2: ld returned 1 exit status
+       make: *** [qmail-lspawn] Error 1
+    You have forgotten to add -lresolv to LDAPLIBS.
+
+6.2 If using TLS you can use 'make cert' or 'make cert-req' to create TLS 
+    certificates
+
+7.  Create the LDAP user database and start the LDAP server
+    See qmail.schema for definition of all fields for OpenLDAP 2.x
+
+8.  Create the proper ~control/ldap* files for qmail-ldap
+    At least ldapserver and ldapbasedn must exist (and also 'me')
+
+9.  Test and Enjoy!
+
+10. Debugging: as said befor you can compile qmail-lspawn and the auth modules 
+    with a flexible debugging facility (option DEBUG).
+    The debug output gets logged through splogger or your favorite logging tool 
+    connected to stderr for tcpserver-pop/imap chain.
+    To turn on debugging you need only to define the LOGLEVEL environment 
+    variable (e.g. with env, env LOGLEVEL=3 qmail-start ...)
+    There are these LOGLEVEL:
+    LOGLEVEL=1   -> Errors
+    LOGLEVEL=2   -> Warnings
+    LOGLEVEL=4   -> Info
+    LOGLEVEL=8   -> Info^2
+    LOGLEVEL=16  -> Debug
+    LOGLEVEL=32  -> Debug^2
+    LOGLEVEL=64  -> LDAP Debug
+    LOGLEVEL=128 -> LDAP Debug^2
+    LOGLEVEL=256 -> PASSWD, this level is normaly off because it shows
+                    critical data (unencrypted and crypted passwords). To
+                    turn it on edit checkpassword.c and increase the level
+                    for init_debug().
+
+     WARNING: on production machines don't use levels higher 3 or you will get 
+              incredible huge logfiles.
+     NOTE: too high debuglevels are reduced to the maximum allowed debug level
+           if the level parameter in init_debug() is smaler.
+           The LOGLEVEL is compare with a bit mask, so that
+           LOGLEVEL=3 will report warnings and errors but LOGLEVEL=2 will
+           only report warnings.
+           With the new log support the environment variable is LOGLEVEL but
+           the old DEBUGLEVEL is still supported.
+           The new log support will no longer add the log output to bounce
+           messages.
+
+11. NOTE ABOUT POP/IMAP services
+    The stock qmail recomends that you use a program by the name 'checkpassword'
+    to do the authentication, like this:
+
+       pop3 stream tcp nowait root \
+       /var/qmail/bin/qmail-popup qmail-popup \
+       YOURHOST /bin/checkpassword /var/qmail/bin/qmail-pop3d Maildir
+
+    With the use of the LDAP patch, this have been slightly altered. We now use
+    a program by the name 'auth_pop' instead... Something like this (replacement
+    inetd.conf line):
+
+       pop3 stream tcp nowait root \
+       /var/qmail/bin/qmail-popup qmail-popup \
+       YOURHOST /var/qmail/bin/auth_pop /var/qmail/bin/qmail-pop3d Maildir
+
+
+    Same goes for the command 'auth_imap' if your IMAP server can use an 
+    external program for authentication. auth_imap was designed for 
+    courier-IMAP and should work with it out of the box. 
+    There is also a auth_ldap modul in courier-imap that should work too.
+    You can get courier-imap from http://www.inter7.com
+
+    auth_pop and auth_imap are part of this patch and will be installed with the
+    other qmail programs.
+
+================================================================================
+
+CONFIG FILES:
+
+~control/aliasempty
+OR
+~control/defaultdelivery
+
+ Default delivery mode used by and only by the startup scripts.
+ Default: ./Maildir/
+ Example: ./
+ Note: If you have a more complex default delivery you need to edit the
+       runscripts because qmail-pop3d and the imapd do not understand this
+       complex format.
+
+~control/locals.cdb
+
+ Replaces locals and is read by qmail-send and qmail-smtpd on the fly.
+ Default: locals
+ Note: You don't have to -HUP qmail-send for changes in locals.cdb to
+       take effect. As soon as you regenerate locals.cdb it will become
+       active. Use bin/qmail-cdb to create the locals.cdb file.
+       Alternatively you can do "make" in ~control/ directory. See the
+       Makefile for more information.
+       If this file exists locals is ignored.
+
+~control/rcpthosts.cdb
+
+ Replaces rcpthosts and morercpthosts.cdb and is read by qmail-smtpd on the fly.
+ Default: rcpthosts and morercpthosts.cdb
+ Note: qmail-smtpd reads locals(.cdb) as well and there is no need anymore
+       to replicate all domains here too. Only domains you are doing queueing
+       for must be listed here. As soon as you regenerate rcpthosts.cdb it will
+       become active. Use bin/qmail-cdb to create the rcpthosts.cdb file.
+       Alternatively you can do "make" in ~control/ directory. See the
+       Makefile for more information.
+       If this file exists rcpthosts and morercpthosts.cdb are ignored.
+
+~control/ldapserver
+
+ List of Hostnames or IP addresses of LDAP servers. One per line.
+ An additional port can be supplied with the host:port notation.
+ Required
+ Example:
+   ldap.nrg4u.com
+   ldap2.nrg4u.com
+   ldap3.nrg4u.com:1234
+
+~control/ldapbasedn
+
+ The base DN from where the search in the LDAP tree begins
+ Normaly required
+ Default: NULL
+ Example: o=Internet Pipeline, c=CH
+ Note: Referrals are ignored
+
+~control/ldapobjectclass
+
+ The ldap objectclass the search will be limited to
+ Default: NULL, will search all objectclasses
+ Example: qmailUser
+ Note: Can specify more than one, must then be written in ldap search syntax
+
+~control/ldaplogin
+
+ Username for the LDAP server connection
+ Default: NULL
+ Example: cn=qmail-ldap, o=Internet Pipeline, c=CH
+ Note: The user must have enough rights to lookup all user information
+
+~control/ldappassword
+
+ Password for the LDAP server connection
+ Default: NULL
+ Note: The password is in clear text. The file should be owned by root and
+       mode (600) rw-------. If rcpt verify or auth_smtp is used then the
+       permissions must be adjusted so that the qmail-smtpd user -- normaly
+       qmaild -- has read access.
+
+~control/ldapgrouplogin
+ 
+ Username for the qmail-group LDAP server connection.
+ Default: use the login specified in ~control/ldaplogin
+ Example: cn=qmail-group, o=Internet Pipeline, c=CH
+ Note: The user must have enough rights to lookup the mail attribute.
+       Also the ldap limit used for this user must be enough high.
+
+~control/ldapgrouppassword
+
+ Password for the qmail-group LDAP server connection.
+ Default: NULL only if ~control/ldapgrouplogin is present else fall back to
+          ~control/ldappassword
+ Note: The password is in clear text. The file should not be readable for
+       all.
+
+~control/ldaplocaldelivery
+
+ To lookup the local passwd file if the LDAP lookup finds no match. This
+ affects qmail-lspawn and auth_* if the LDAP lookup returns nothing.
+ Default: enabled
+ Example: 1
+ Note: boolean, use 0 (zero) or 1 (one)
+
+~control/ldaprebind
+
+ Use the possibility of rebinding to the ldap-server to compare pop3 
+ and imap passwords. So you can make your acl more restrictive.
+ Default: disabled
+ Example: 1
+ Note: boolean, use 0 (zero) or 1 (one)
+
+~control/ldapcluster
+
+ Turn clustering on and off. Needs a qmail-ldap compiled with 
+ -DQLDAP_CLUSTER or nothing will happen. Also don't forget to set up
+ qmail-qmqpd on all servers in the cluster.
+ Default: disabled
+ Example: 1
+ Note: boolean, use 0 (zero) or 1 (one)
+ ATTN: the control files me, rcpthosts and locals have to be set carfully
+       or you will have big problems.
+
+~control/ldapclusterhosts
+
+ ldapclusterhosts contains a number of hostnames (FQDM) to check togehter
+ with ~control/me when clustering is on. This file is useful if you want to
+ run multiple instances of qmail-ldap on one machine.
+ Default: none, in other words just check with ~control/me
+ Example: customersmtp.nrg4u.com
+ Note: multiline
+
+~control/defaultquotasize
+
+ The default amount of disk space the user can use until all further messages
+ get bounced back to the sender. Size is a byte count.
+ Default: unlimited
+ Example: 1000000 (max 1000000 bytes size)
+ Note: is overridden by mailQuota*, make sure to have set ~control/quotowarning
+       otherwise you will not get quota warning messages
+
+~control/defaultquotacount
+
+ The default maximum amount of messages the user can have until all further
+ messages get bounced back to the sender. Count is a file count.
+ Default: unlimited
+ Example: 1000 (max 1000 Mails)
+ Note: is overridden by mailQuota*, make sure to have set ~control/quotowarning
+       otherwise you will not get quota warning messages
+
+~control/ldapdefaultdotmode
+
+ The default interpretation of .qmail files
+ Default: ldaponly
+ Example: both
+ Values: both, dotonly, ldaponly, ldapwithprog
+ Note: Works only for deliveries based on LDAP lookups.
+       Local mails use dotonly like in normal qmail.
+
+~control/ldapmessagestore
+
+ The default prefix for non absolute path's in mailMessageStore, without 
+ heading '/'.
+ Default: NULL
+ Example: /maildisk
+ Note: Used in virtual users environments
+
+~control/ldapuid
+
+ The default UID used in virtual users environments. This value will be
+ used for ldap entries with no LDAP_QMAILUID (see below) field
+ Default: NULL
+ Example: 1010
+ Note: should be a real UID, must be above 100
+
+~control/ldapgid
+
+ The default GID used in virtual users environments. This value will be
+ used for ldap entries with no LDAP_QMAILGID (see below) field
+ Default: NULL
+ Example: 1010
+ Note: should be a real GID, must be above 100
+
+~control/ldaptimeout
+
+ The time the ldap search waits for a response from the ldap server
+ Default: 30 seconds
+ Example: 60
+ Note: in seconds, if it gets no response within this time it will
+       continue either with the next specified ldap server or it will
+       defer the delivery and try again later.
+
+~control/custombouncetext
+
+ Additional custom text in bounce messages, e.g. for providing contact
+ information of your ISP or messages in your language
+ Default: NULL
+ Example: You can contact us at (555) 555 5555
+ Note: Multiline
+       It MUST NOT contain a blank line ("\n\n") anywhere otherwise you 
+       break qsmbf. Use a line with one or more spaces ("\n \n") instead.
+       See http://cr.yp.to/proto/qsbmf.txt for more info.
+
+~control/quotawarning
+
+ Custom text in quota warning message, e.g. for providing contact information
+ of your ISP
+ Default: NULL
+ Example: You can contact us at (555) 555 5555
+ Note: Multiline. Needs to be present to make qmail-quotawarn work.
+       Supports the %HEADER% magic similar to qmail-reply. The headers From:,
+       Subject:, the content type headers and headers starting with X- can be
+       set. The value of the To: header is forced to the recipient address.
+       The %SUBJECT% magic of qmail-reply is not useful for a quotawarning and
+       therefor disabled.
+
+~control/dirmaker
+
+ Absolute path to your program/script that creates missing homedirs
+ Default: none (off)
+ Example: /var/qmail/bin/create_homedir
+ Note: the script is executeded after the setuid/gid, it isn't running
+       under root for security reasons.
+       The command is executed with execve not system 
+       (so mkdir --mode=700 -p does not work!) use a shell script. 
+       $1 is the homedir-path and $2 is aliasempty.
+       If you use $2 have a look at the first and last char to ensure that
+       it is a path to the maildir and not a pipe or mailbox delivery.
+       Possible very simple shell script:
+
+       -cut-
+       #!/bin/sh
+       mkdir -m 700 -p $1
+       #EOF
+       -cut-
+
+~control/relaymailfrom
+
+ This file contains envelope sender addresses that are allowed to relay through
+ this server.
+ Default: none
+ Example: user@domain or @domain
+ Note: Use with care, the envelope senders address can easily be spoofed and
+       then you are an open relay again. It is better to use a scheme like
+       POP before SMTP.
+
+~control/rbllist
+
+ Rbllist contains a number of RBL's to check for the given senders IP address.
+ The file consists of four tab or space separated fields.
+   basedomain: base domain address to lookup (e.g. relays.ordb.org)
+   action: one of addheader or reject.
+           addheader will just create a X-RBL: header whereas
+           reject will reject the smtp connection instantly with a 553 error.
+   matchon: any or IP-Address, if a IP-Address is specified the action is only
+            taken if the returned address form basedomain is equal to
+            IP-Address. With any all returned IP-Address will match.
+   message: message to be included in X-RBL: headers and 553 errors.
+
+ Possible example:
+  # baseaddress    action    matchon      Message
+  #========================================================================
+       sbl.spamhaus.org reject    127.0.0.2 See http://www.spamhaus.org/SBL
+        relays.ordb.org addheader 127.0.0.2 See http://www.ordb.org/faq/
+          list.dsbl.org addheader 127.0.0.2 See http://dsbl.org/main
+         bl.spamcop.net addheader 127.0.0.2 See http://spamcop.net/
+        relays.ordb.org reject    any       see http://ordb.org
+  spamguard.leadmon.net addheader 127.0.0.2 address is a dialup address
+
+ Default: none
+ Note: Multiline. To activate RBL checks you have to set RBL in qmail-smtpd's
+       environment (with tcpserver). See this website for more information on
+       available RBLs: http://www.declude.com/JunkMail/Support/ip4r.htm
+       The environment variable RBLONLYHEADER overrides any rejects and only
+       adds headers. This can be set by ip-range with tcpserver.
+
+~control/goodmailaddr
+
+ This file contains local recipient addresses that are always accepted in
+ conjunction with sender or recipient verify checks. Address can be specified
+ in multiple forms. user@domain.org, @domain.org, user@ and versions in the
+ form foo-catchall@domain.org including catchall@domain.org (which is the same
+ as @domain.org).
+ Default: none
+ Example: foo-bar@domain.org, @otherdomain.org, postmaster@, abuse@,
+          list-sub-catchall@list.domain.org
+ Note: This is useful for things like <postmaster@domain.com> and other
+       addresses you always want to accept, even if they are not in the
+       ldap directory or when a lookup temporarly fails. See RCPTCHECK
+       and SENDERCHECK. Accounts mapped via the alias user (~alias/.qmail-*)
+       can be added here so that RCPTCHECK can be endabled by default.
+
+~control/badrcptto
+
+ This file contains local recipient addresses that are rejected.
+ Default: none
+ Example: user@domain or @domain
+ Note: This can be useful if a spammer sends lots of messages to a
+       nonexistant user from an invalid address as otherwise postmaster
+       will get lots of double bounces.
+
+~control/badmailfrom-unknown
+
+ This file contains blocked addresses for server without a PTR RR.
+ This is useful to stop some spammer that use fake hotmail or yahoo
+ addresses but mail from home-pc without a PTR RR dns record.
+ Example: @hotmail.com
+ Note: Syntax as in ~control/badmailfrom.
+
+~control/bouncemaxbytes
+
+ This file contains the maximal number of bytes to be included in a bounce
+ message.
+ Default: 0 (off)
+ Example: 102400 (equivalent to 10kB)
+
+~control/smtpclustercookie
+
+ This file contains a cookie (random string) that is the same on all
+ smtp MX clusters. It is to prevent outgoing mails looping back because
+ of incorrect or faked MX records pointing to some external ip address
+ which qmail-remote does not recognise as in reality 'itself' (as seen
+ from the cluster perspective). The external ip address can be for example
+ a load balancer or a NAT device.
+ Default: none
+ Example: cvkmd9078923hjv4nkd890q3g
+ Note: String will be truncated after 32 characters. If qmail-remote
+       sees the same string advertised in qmail-smtpd greeting it will
+       abort the delivery attempt, bounce the message and report a smtp
+       loop error.
+
+~control/cert.pem
+
+ Certificate for qmail-smtp tls option. This file can be generated via "make
+ cert" or "make cert-req". The file needs to be readable for qmail-smtpd -- in
+ other words it needs to be readable for user qmaild.
+
+~control/outgoingip
+
+ This file contains the IP qmail-remote should bind to.
+ Default: 0.0.0.0
+ Example: 192.168.12.88
+
+~control/qmqpcip
+
+ This file contains the IP qmail-qmqpc should bind to.
+ Default: 0.0.0.0
+ Example: 192.168.12.88
+
+~control/bigbrother
+
+ This file is only used if BIGBROTHER was defined in the Makefile.
+ For ISP that need to implement some surveillance method because of some
+ beloved authoroties (like here in switzerland), you can enable a per
+ address queue extra feature. To automatically forward all mail to and from
+ badguy@badplace.ch to bigbrother@admin.ch you need to add followong line to
+ ~control/bigbrother: badguy@badplace.ch:bigbrother@admin.ch.
+ bigbrother@admin.ch can be a local, ldap or remote address.
+ Default: none (off)
+ Example: badguy@badplace.ch:bigbrother@admin.ch
+ Note: An extra recipient will be added in qmail-send. If the bigbrother
+       address causes a bounce the sender will see this bounce.
+
+~control/signatures
+
+ This file contains content signatures for the REJECTEXEC functionality.
+ Default: none
+ Example: TVqQAAMAA  (block some windows executables, exe|com|pif|scr)
+ Example: UEsDBAoAAAAAA*****DKJx+eAFgAAABYAA**AAAA  (block MyDoom)
+ Note: These signatures are matched for in the first line of mime
+       attachments. Be sure to make them as specific as possible
+       to avoid to have a too broad filter and matching valid
+       content. The asterisk (*) is a single placeholder that will
+       match any single character at that position. The signature
+       is litteraly matches and no decoding of mime attachments is
+       being done. Normally the signature contains the base64
+       encoded version of the string you want to match. Lines
+       starting with a hash sign (#) are ignored and can be used
+       for comments.
+       The default file contains signatures of Windows executable
+       files (exe|com|pif|scr, etc) and common email Virii at the
+       time of the current release.
+
+~control/smtpcert
+
+ This file contains the location of the SSL certificate used for smtps STARTTLS
+ feature. The path may be relative to /var/qmail or whatever was specified in
+ conf-qmail.
+ Default: none
+ Example: control/cert.pem
+
+~control/remotecert
+
+ This file contains the location of the OPTIONAL SSL certificate used for
+ outgoing SMTP sessions. The path may be relative to /var/qmail or whatever
+ was specified in conf-qmail.
+ Default: none
+ Example: control/cert.pem
+ Note: Unlike ~control/smtpcert this file is completle optional for encrypion.
+       qmail-remote will use STARTTLS and SSL encryption even without a cert
+       file, as it is not neccessary for the client.
+
+~control/tarpitcount
+~control/tarpitdelay
+~control/maxrcptcount
+~control/rblonlyheader
+~control/ldapdefaultquota
+~control/ldapusername
+~control/ldappasswdappend
+ NO LONGER USED, PLEASE REMOVE THESE FILES
+
+================================================================================
+
+Environment variables setable via tcpserver, envdir or plain old env/sh:
+
+AUTHPREPEND
+
+ String that is prepended to the login in the received line.
+ Default: off
+ Affects: qmail-smtpd
+ Example: "Authenticated user: "
+ Note: Just for additional information in the received line. You can use this
+       to make tracking of (ab)users easier.
+
+AUTHREQUIRED
+
+ Allow sending of messages (for this host and relaying) only to authenticated
+ senders.
+ Default: off
+ Affects: qmail-smtpd
+ Example: "" (any value will do)
+ Note: Use this only if all clients support AMTP-AUTH. Be careful not to block
+       remote mail servers sending messages for local users. This is only useful
+       if you want to restrict certain IP ranges (for example you dial-up or
+       other customers) to be able to send only as existing and valid users.
+
+BLOCKRELAYPROBE
+
+ Rejects recipients with and "!", "%" or double-"@"
+ Default: off
+ Affects: qmail-smtpd
+ Example: "" (any value will do)
+ Note: This is quite useful to stop so called anti-spam probes of clueless
+       and overzealus wannabe RBL operators. These probes try to exploit
+       some ancient sendwhale bugs never existent in qmail. Unfortunatly
+       qmail accepts such stuff even if it doesn't relays it and bounces
+       it later. "!" is the old UUCP bang path. "%" is a sendwhale relaying
+       hack and double-"@" a sendwhale bug.
+       Beware if you actually use the qmail percent-hack! Then this can't
+       be used obviously!
+
+LDAPSOFTOK
+
+ Treat ldap soft errors (ldap server unavailable, etc) as if the check was
+ successful and continue.
+ Default: off
+ Affects: qmail-smtpd
+ Example: "" (any value will do)
+ Note: Normally qmail-smtp will give a 450 temporary error if the ldap server
+       could not be successfuly queried. This changes to treat such errors as
+       if they had been successful. This is useful when it is more important
+       to keep the service available, even if the ldap server can't be queried
+       for some reason (down, unreachable, insufficient query rights, etc).
+
+LOGLEVEL
+
+ Level of log verbosity in qmail-smtpd.
+ Default: 0 (NULL)
+ Affects: qmail-smtpd
+ Example: 3
+ Levels:
+     0 = no logging
+     1 = fatal errors
+     2 = accounting
+     3 = connection setup and smtp errors
+     4 = verbose
+ Note: integer value, everything will be logged through tcpserver
+
+POP3_LOGLEVEL
+
+ Level of log verbosity in qmail-pop3d.
+ Default: 0 (NULL)
+ Affects: qmail-pop3d
+ Example: 3
+ Levels:
+     0 = no logging
+     1 = fatal errors
+     2 = login/logout accounting
+     3 = session errors
+     4 = verbose
+ Note: integer value, everything will be logged through tcpserver
+ Note2: this is a hack so that this log level does not interfere with the one
+        of auth_pop.
+
+LOGLEVEL or DEBUGLEVEL
+
+ Level of log verbosity in qmail-lspawn, auth_*
+ Default: 0 (NULL)
+ Levels:
+    LOGLEVEL=1   -> Errors
+    LOGLEVEL=2   -> Warnings
+    LOGLEVEL=4   -> Info
+    LOGLEVEL=8   -> Info^2
+    LOGLEVEL=16  -> Debug
+    LOGLEVEL=32  -> Debug^2
+    LOGLEVEL=64  -> LDAP Debug
+    LOGLEVEL=128 -> LDAP Debug^2
+    LOGLEVEL=256 -> PASSWD, this level is normaly off because it shows
+                    critical data (unencrypted and crypted passwords). To
+                    turn it on edit checkpassword.c and increase the level
+                    for init_debug().
+ WARNING: on production machines don't use levels higher 3 or you will get 
+          incredible huge logfiles.
+ NOTE: too high debuglevels are reduced to the maximum allowed debug level
+       if the level parameter in init_debug() is smaler.
+       The LOGLEVEL is compare with a bit mask, so that
+       LOGLEVEL=3 will report warnings and errors but LOGLEVEL=2 will
+       only report warnings.
+       Both names are supported with LOGLEVEL having the higher priority.
+
+MAXRCPTCOUNT
+
+ Maxrcptcount is the maximum number of RCPT TOs you accept before permanently
+ rejecting this delivery attempt.
+ Default: 0 (which means no unlimited)
+ Affects: qmail-smtpd
+ Example: 5
+ Note: This is a hard limit. If you just want to give some pain for smaller
+       recipient numbers consider tarpit use as well.
+
+NOBOUNCE
+
+ Rejects null sender bounces
+ Default: off
+ Affects: qmail-smtpd
+ Example: "" (any value will do)
+ Note: Use only in extreme cases and only for certain IP ranges. Blocking
+       bounces is considered harmful and strictly prohibited by RFC2821.
+       This can be useful if a spammer used your domain as sender and you
+       get all the bounces. Otherwise don't enable this! You want to get
+       bounces!
+
+NOCOMPRESS
+
+ Disables the dynamoc data compression in qmail-qmqpd.
+ Default: off
+ Affects: qmail-qmqpd
+ Example: "" (any value will do)
+
+NOPBS
+
+ Disable adding of pbs data. NOPBS disables the execution of pbsadd in auth_*.
+ Default: off
+ Affects: auth_pop, auth_imap & pbsadd
+ Example: "" (any value will do)
+ Note: this is manly useful to hinder adding informations of forwarder sessions.
+
+QMAILQUEUE
+
+ Use this queueing program instead of the default qmail-queue program.
+ Default: off
+ Affects: qmail-smtpd, qmail-qmtpd, qmail-qmqpd, qmail-inject,
+          but also qmail-local, qmail-reply, qmail-send, qreceipt, 
+          condredirect, forward
+ Example: /var/scanner/bin/qmail-scanner-queue.pl
+ Note: Using this for something different than the mail incomming daemons
+       is dissuaded.
+
+RBL
+
+ If set turns on rbl checking. See also section about the ~control/rbllist
+ control file.
+ Default: none
+ Affects: qmail-smtpd
+ Example: "" (any value will do)
+
+RBLONLYHEADER
+
+ Rblonlyheader causes qmail-smtpd not to reject the message in any case but
+ just to add a line with it's findings to the mail header.
+ Default: none
+ Affects: qmail-smtpd
+ Example: "" (any value will do)
+ Note: Add's a
+       "X-RBL: (relays.ordb.org) matches with 127.0.0.2 and tells us go home"
+       header to the message for later filtering.
+
+RCPTCHECK
+
+ Check if the recipient (envelope "rcpt to:") of a message really exists. If not
+ give a 550 reject right now instead of bouncing later in qmail-lspawn.
+ If localdelivery is set users will additionaly be verified against ~/users/cdb
+ and the local /etc/passwd database.
+ Default: off
+ Affects: qmail-smtpd
+ Example: "" (any value will do)
+ Note: Only applies to recipients whose domain is listed in ~control/locals.
+       Recipients domains listed in ~control/rcpthosts are allowed without
+       further checks. If RELAYCLIENT is set, all other recipients are allowed
+       as well. Addresses or domains listed in ~control/goodmailaddr are
+       unconditionally allowed in all cases.
+
+REJECTEXEC
+
+ Reject DOS/Windows executables in mail attachements.
+ Default: off
+ Affects: qmail-smtpd
+ Example: "" (any value will do)
+ Note: This patch does not distinguish between valid applications and
+       evil viruses and trojans so handle with care. It is not a 100%
+       guaranteed protection but it handles a lot of unwanted stuff.
+       The file ~control/signatures contains signatures for matching
+       of mime attachments.
+
+RETURNMXCHECK
+
+ Rejects senders if they don't have a valid return MX
+ Default: off
+ Affects: qmail-smtpd
+ Example: "" (any value will do)
+ Note: This is quite useful even though it doesn't stops many spammers
+       today. But it ensures that you can send an email or a bounce
+       back to the sender. It is also useful for your own users/customers
+       because if they type a nonexistent sender into their "from" field
+       (typos!) it'll stop them the first time instead of getting help-
+       desk calls when nobody can reply to them.
+
+SANITYCHECK
+
+ Rejects senders without an @, no . in domain part or too long/short TLD
+ Default: off
+ Affects: qmail-smtpd
+ Example: "" (any value will do)
+ Note: Rejects stuff which you probably don't want on your mailserver
+       because it's highly likely that it'll bounce later.
+
+SENDERCHECK
+
+ Check if the sender (envelope "mail from:") of a message really exists (in the
+ ldap directory). If not give a 550 reject right now.
+ If localdelivery is set users will additionaly be verified against ~/users/cdb
+ and the local /etc/passwd database.
+ Default: off
+ Affects: qmail-smtpd
+ Example: "" or "LOOSE" or "STRICT"
+ Note: Only applies to senders whose domain is listed in ~control/locals.
+       Everything else is assumed to be an external message with a foreign
+       sender coming in, so no check applied. This is normal mode.
+       Setting to "LOOSE" will allow only senders which are listed either in
+       ~control/locals or ~control/rcpthosts. Setting to "STRICT" will only
+       allow senders which are listed in ~control/locals. With this you can
+       enforce for example that people from certain ip ranges can only send
+       if they have a valid existing email address with you.
+       Addresses or domains listed in ~control/goodmailaddr are unconditionally
+       allowed in all cases.
+
+SSLCERT
+
+ Path to the SSL certificate qmail-smtpd should use for STARTTLS. Overrides
+ ~control/smtpcert.
+ Default: none, ~control/smtpcert will be used
+ Example: /var/qmail/boot/qmail-smtpd/cert.pem
+
+SMTPAUTH
+
+ Enables SMTP-AUTH for remote clients. Authenticated clients are allowed to
+ relay through this server and their login is being recorded in the received
+ line.
+ Default: off
+ Affects: qmail-smtpd
+ Example: "TLSREQUIRED" or "" (any value will do)
+ Note: With SMTP-AUTH remote users can use this mail server for relaying.
+       SMTP is unencrypted and auth passwords are in clear text equivalent
+       base64 encoding. With TLSREQUIRED enabled SMTP-AUTH is only accepted
+       when the SMTP session is TLS encrypted to prevent password sniffing.
+       TLSREQUIRED requires TLS option to be compiled into qmail-ldap.
+
+SMTP550DISCONNECT
+
+ Disconnect the SMTP session if a 5xx is produced by the sender
+ Default: off
+ Affects: qmail-smtpd
+ Example: "" (any value will do)
+ Note: This is useful if you have a spammer trying different senders or
+       recipients in the same session separated by rset's. Be aware of
+       the fact that this option "breaks" RFC 2821 and may cause problems
+       with legitimate SMTP traffic.
+
+TARPITCOUNT
+
+ Tarpitcount is the number of RCPT TOs you accept before you start tarpitting.
+ Default: 0 (which means no tarpitting)
+ Affects: qmail-smtpd
+ Example: 5
+ Note: This number should be smaller than MAXRCPTCOUNT to have any effect.
+
+TARPITDELAY
+
+ Tarpitdelay is the number of seconds of delay to introduce after each
+ subsequent RCPT TO.
+ Default: 5
+ Affects: qmail-smtpd
+ Example: 10
+ Note: Connection which are tarpitted take a long time to finish. Be aware
+       that this ties up the available qmail-smtpd slots. Raise connection
+       limits with tcpserver if neccessary.
+
+421GREETING
+
+ Rejects a connection right away with a 421 in the greeting line and
+ starts in a dummy mode where only QUIT works unless 421GREETING is set -- in
+ that case the connection will closed immediatly after printing the greeting. 
+ Default: off
+ Affects: qmail-smtpd
+ Example: ""
+ Example: "Go away!"
+ Note: You can set this in tcpserver if you want to reject messages from
+       an ip address temporarily. If no string is given it will default
+       to "Service temporarily not available (#4.3.2)".
+       The timeout is reduced to 20 seconds to prevent starvation.
+
+550GREETING
+
+ Rejects a connection right away with a 550 in the greeting line and
+ starts in a dummy mode where only QUIT works unless 421GREETING is set -- in
+ that case the connection will closed immediatly after printing the greeting. 
+ Default: off
+ Affects: qmail-smtpd
+ Example: ""
+ Example: "Go away!"
+ Note: You can set this in tcpserver if you want to reject messages from
+       an ip address permanently. If no string is given it will default
+       to "Sorry, your message has been administratively denied. (#5.7.1)".
+       The timeout is reduced to 20 seconds to prevent starvation.
+       550GREETING has precedence over 421GREETING.
+
+
+================================================================================
+
+DEFAULT LDAP PARAMETER FIELDS:
+NOTE: keywords have to match exactly, so pay attention.
+      All fieldnames and keywords can be changed at compile time.
+      Just have a look at qmail-ldap.h.
+      
+LDAP_MAIL (default: "mail")
+
+ The users email address
+ Required
+ Example: jdoe@foo.bar
+
+
+LDAP_MAILALTERNATE (default: "mailAlternateAddress")
+
+ Secondary (alias) mailaddresses for the same user
+ Example: jd@foo.bar
+ Note: multifield
+
+
+LDAP_UID (default: "uid")
+
+ The username for POP3 and IMAP delivery
+ Required
+ Example: jdoe
+ Note: this name will also be set as $USER for qmail-local and program delivery.
+
+
+LDAP_QMAILUID (default: "qmailUID")
+
+ UID of the user on the mailsystem
+ Example: 1010
+ Note: Can be omitted in a virtual users environment
+       but only if it is defined via the control file ~control/ldapuid 
+
+LDAP_QMAILGID (default: "qmailGID")
+
+ GID of the user on the mailsystem
+ Example: 1010
+ Note: Can be omitted in a virtual users environment
+       but only if it is defined via the control file ~control/ldapgid 
+
+
+LDAP_PASSWD (default: "userPassword")
+
+ The password for POP3/IMAP/SMTP authentication
+ Example: {MD5}uSI59Zyfa5lapBLGfJrD+g==
+ Note: Can be encrypted with {SHA}, {SSHA}, {MD5}, {SMD5}, {MD4}, {RMD160},
+       {NS-MTA-MD5}, {crypt} crypt (without {crypt} prefix) or cleartext (only
+       if compiled with -DCLEARTEXTPASSWD (a bad idea on production systems)).
+       If you rebind to the ldapserver don't use {NS-MTA-MD5}, {RMD160} and
+       probably {MD4}. These algorithms are sometimes not supported by the 
+       ldap servers, so check with their documentation. When rebinding to
+       newer OpenLDAP versions (>2.2.23) crypt without {crypt} prefix will not
+       work. To generate passwords you can use the included tool 'digest'.
+
+
+LDAP_MAILSTORE (default: "mailMessageStore")
+and
+LDAP_HOMEDIR (default: "homeDirectory")
+
+ Path to the maildir/mbox on the mail system is extracted from those fields.
+ If LDAP_HOMEDIR is found this field is used as $HOME, using aliasempty or
+ mailMessagestore if defined as default delivery method.
+ If only LDAP_MAILSTORE is defined this will be used as $HOME and aliasempty
+ as default delivery method.
+ If neither LDAP_MAILSTORE nor LDAP_HOMEDIR is defined, ~alias (qmails alias 
+ user homedir) will be used as $HOME and ALIASDEVNULL (defined in qmail-ldap.h)
+ as default delivery method. Also the delivery mode is set to ldap only and 
+ forward only (LDAP_DOTMODE and LDAP_MODE).
+ Example: /home/jdoe/
+ Note: LDAP_MAILSTORE can be written relative in a virtual users environment
+       ldapmailstore will be prefixed to make the path absolute.
+       For more info have a look at the QLDAPNEWS file.
+       If you use "homeDirectory" in an incompatible way then redefine it in
+       qldap-ldap.h to something not used, like "noHomeDirectory".
+
+
+LDAP_QUOTA_SIZE (default: "mailQuotaSize")
+LDAP_QUOTA_COUNT (default: "mailQuotaCount")
+
+ The amount of space the user can use until all further messages get bounced.
+ There are two possible limits, size (a byte count) and count (a file count).
+ Example: max 1000000 bytes size and max 1000 Mails
+            mailQuotaSize: 1000000
+            mailQuotaCount: 1000
+ Note:  a value of 0 means unlimited quota for that limit (count or size).
+ Note2: overrides defaultquotasize and defaultquotacount per user.
+        the old string forma (1000000S,1000C) is no longer supported.
+
+LDAP_MAXMSIZE (default: "mailSizeMax")
+
+ The maximum size (in bytes) that a single message may have. Everything over
+ this size gets bounced.
+ Example: 102400
+ Note: mailSizeMax has no influence on the datasize control file for the
+       smtp daemon. The mailSizeMax decision is not take until the mail is
+       delivered localy (by qmail-lspawn).
+
+
+LDAP_FORWARDS (default: "mailForwardingAddress")
+
+ Address(es) to forward all incoming messages for this user to.
+ Example: jdoe@new.place
+ Note: multifield. Forwards are done in addition to local (maildir/mbox)
+       delivery. Forwardings can be disabled without having to remove
+       the entries. See deliveryMode for more information on both.
+
+
+LDAP_PROGRAM (default: "deliveryProgramPath")
+
+ Program to execute for all incoming mails. Gets the message as input on stdin.
+ Example: /usr/bin/program -c -s
+ Note: multifield. The same as |/usr/bin/program -c -s in .qmail
+       Works only with qmailDotMode set to ldapwithprog or both.
+       With ldaponly set deliveryProgramPath is silently ignored.
+       Before using it have a look at QLDAPNEWS, qmail-ldap.h, check.c and
+       see also 5.2.
+       Program delivery is done in addition to local (maildir/mbox) delivery.
+       Program delivery can be disabled without having to remove the
+       entries. See deliveryMode for more information on both.
+       A valid home-directory is needed so either LDAP_MAILSTORE or
+       LDAP_HOMEDIR needs to be defined.
+
+LDAP_MODE (default: "deliveryMode")
+
+ multi field entries of these keywords
+ - (no entry): default delivery, put message into maildir/mbox (localdelivery),
+   plus forward and program delivery if specified.
+ - noforward: do not forward (ignores forwarding entries in ldap and .qmail)
+ - nolocal: do not put message into maildir/mbox (ignores also .qmail)
+ - noprogram: do not do program deliveries (ignores deliveryprogrampath, .qmail)
+ - reply: send an auto_reply mail with text from mailReplyText
+ Default: no entry -> default
+ Example: noforward
+          noprogram
+ Note: The behaviour changed compared with previous qmail-ldap versions
+       (20030801 and earlier)!
+       Setting a mailForwardingAddress no longer disables local delivery.
+       This is the most important change.
+
+       Normal is no longer a real mode. It is just a placeholder for the
+       default behaviour.
+       Local delivery is now always done, except when explicitly disabled
+       with nolocal.
+
+       Noforward and noprogram disable forwardings and program deliveries
+       even if mailForwardingsAddress or deliveryProgramPath attributes
+       exist. This way you can keep programs and forwards but turn them
+       off if you don't need them, instead of removing their attributes.
+
+       If no mode to the contrary set, forwards, program deliveries, local
+       deliveries are all done if existent. Reply is not automatic and has
+       to be enabled explicitly.
+
+
+LDAP_REPLYTEXT (default: "mailReplyText")
+
+ A reply text for every incoming message (multiline)
+ Example: I'm on vacation until next monday
+ Example2: multiline base64
+   SGkgcW1haWwtbGRhcCBmYW5zLAoKaWYgSSBjb3VsZCBJIHdvdWxkIGJlIGlu
+   IHRoZSBtb3VudGFpbnMgc2tpaW5nIGJ1dCBJJ20gYXQgaG9tZQp3cml0aW5n
+   IHRoaXMgbWVzc2FnZSBmb3IgdGhlIFFMREFQSU5TVEFMTCBmaWxlLgpUbyBi
+   ZSBob25lc3QsIHRoZXJlIGlzIG5vdCBlbm91Z2ggc25vdyBhcm91bmQgdG8g
+   ZW5qb3kgc2tpaW5nLgoKdGhhbmtzIGZvciByZWFkaW5nIHRoZSBRTERBUElO
+   U1RBTEwgZmlsZQoKLS0KOndxIENsYXVkaW8K
+ Note: used only if deliveryMode is set to reply.
+       To use multiline text in ldap it has to be base64 in the ldif.
+       GUI tools like GQ are doing this correct, ldapadd can handle base64
+       inputs or a path to a file containing the reply text (man ldapadd).
+ Note2: It is now possible to add a header section to the reply.
+       If the replytext starts with a %HEADER% line all lines following until
+       the next empty line are treated as header. The fields From:, Subject:,
+       the content type headers and most X- headers can be set. To:, X-Mailer:
+       and Precedence: are ignored and set by qmail-reply. If %SUBJECT%
+       is used in the Subject field it is expanded with the Subject of the sent
+       mail. This expansion will only work for the first line of a multiline
+       Subject header.
+
+LDAP_DOTMODE (default: "qmailDotMode")
+
+ The default interpretation of .qmail files
+ Values: both, dotonly, ldaponly, ldapwithprog, none (just Maildir/box delivery)
+ Default: set by file ~control/ldapdefaultdotmode
+ Note: Works only for deliveries based on LDAP lookups,
+       overrides ~control/ldapdefaultdotmode.
+ 
+
+LDAP_MAILHOST (default: "mailHost")
+
+ On which qmail server the messagestore of this user is located
+ Example: qmail3.nrg4u.com
+ Note: Must be the same as the ~control/me hostname on the homeserver 
+       of the user.
+
+
+LDAP_ISACTIVE (default: "accountStatus")
+
+ The status of a user account.
+ Values: active (no restrictions),
+         noaccess (only mail delivery but no pop/imap access),
+         disabled (bounce incoming messages)
+         deleted (bounce incoming messages and mark for deletion,
+                  see LDAP_PURGE)
+ Default: no accountStatus is equal to active.
+
+
+LDAP_PURGE (default: "qmailAccountPurge")
+
+ If accountStatus set to 'deleted', the earliest date when the mailMessageStore
+ including all remaining content will be deleted from the filesystem.
+ Values: date and time in seconds since Jan. 1, 1970 (the epoch)
+ Default: not set
+ Note: This deletion has to be done by an external helper program, for example
+       periodically run from cron. A sample script is included under the name
+       qmailAccountPurge.sh. Handle automatic deletions with care!
+
+
+LDAP_QMAILUSER (default: "qmailUser")
+ NO LONGER USED, REMOVE IT SOMEWHEN FROM YOUR DATABASE
+ Replaced by LDAP_UID
+
+================================================================================
+
+EXAMPLE QLDAP LDIF FILE:
+
+dn: cn=Andre Oppermann, o=Internet Pipeline, c=CH
+objectClass: top
+objectClass: person
+objectClass: inetOrgPerson
+objectClass: qmailUser
+cn: Andre Oppermann
+sn: Oppermann
+mail: opi@opi.flirtbox.ch
+mailAlternateAddress: andre@opi.flirtbox.ch
+mailHost: opi.flirtbox.ch
+mailMessageStore: /usr/home/opi/Maildir/
+mailForwardingAddress: opi@nrg4u.com
+deliveryProgramPath: /usr/home/opi/bin/smsinformer -q
+deliveryMode: noprogram
+mailQuotaSize: 1000000
+mailQuotaCount: 1000
+qmailUID: 1001
+qmailGID: 1001
+uid: opi
+userPassword: {SMD5}b28a87511da157f147ed4766b0474a8a
+accountStatus: active
+
+================================================================================
+
+EXAMPLE SLAPD.CONF FILE:
+
+First copy qmail.schema to your OpenLDAP installation location and here is
+an example slapd.conf:
+
+#
+# ATTENTION: slapd run chrooted to /var/qmail/boot/slapd so all pathes
+# need to be relative to this chrooted dir.
+#
+
+ucdata-path ./ucdata
+
+# include needed schemas
+include ./schema/core.schema
+include ./schema/cosine.schema
+include        ./schema/nis.schema
+#include        ./schema/inetorgperson.schema
+include ./schema/qmail.schema
+
+# tuneing
+schemacheck     on
+idletimeout     60
+timelimit       60
+sizelimit       100
+defaultsearchbase "o=Internet Pipeline, c=CH"
+# for squirrelmail
+allow bind_v2
+
+#######################################################################
+# ldbm database definitions
+#######################################################################
+
+backend         ldbm
+database        ldbm
+suffix          "o=Internet Pipeline, c=CH"
+rootdn          "cn=root, o=Internet Pipeline, c=CH"
+rootpw          secret
+# remember you should run slapd chroot()-ed
+directory       ./ldapdb
+
+# Indices to maintain
+index           objectclass                             eq
+index           uid                                     eq,sub
+index           cn,sn,mail,mailAlternateAddress         pres,eq,approx,sub
+#index          default                                 none
+
+EXAMPLE RUN FILE:
+#!/bin/sh
+exec 2>&1
+
+PATH=$PATH:/usr/local/sbin:/usr/local/bin
+#
+# LDAP server
+# chuid to ldap and chroot to /var/qmail/boot/slapd
+#
+
+exec /usr/local/libexec/slapd -d 256 \
+        -u ldap -g ldap -r /var/qmail/boot/slapd -f ./slapd.conf \
+        -h "ldap:///"  # "ldaps:///"
+
+NOTES:
+An etc/passwd or etc/master.passwd and etc/group file is needed in the chroot
+directory because of OpenLDAP stupidity. Also ucdata and the needed schema
+files need to be added to the chroot.
+
+================================================================================
+
+MAILINGLIST, BUGS & PROBLEMS
+
+There is a qmail-ldap specific mailinglist at qmail-ldap@qmail-ldap.org.
+To subscribe just write a mail to qmail-ldap-subscribe@qmail-ldap.org.
+
+The qmail-ldap mailinglist archive can be found at
+http://marc.theaimsgroup.com/?l=qmail-ldap&r=1&w=2
+
+There is also a life with qmail-ldap homepage at:
+http://www.lifewithqmail.org/ldap
+
+If you have a problem with the patch or there seems to be a bug in the code
+please add some output of qmail-ldap with LOGLEVEL set to something higher
+then 2 (255 is a good setting to see all possible problems).
+It is impossible to know where the problem is when somebody writes a mail like:
+I have a problem with the patch. No mail gets send to the user in the ldap db.
+
+Normaly you get also a better response if you specify your problem in detail.
+It seems that often a "RTFM" is enough, but when you have read until here you 
+are probably not such a candidate.
+
+END :-)
+
diff -ruN qmail-1.03-orig/QLDAPNEWS qmail-1.03-ldap-20060201-orig/QLDAPNEWS
--- qmail-1.03-orig/QLDAPNEWS	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/QLDAPNEWS	2006-02-25 11:00:55.000000000 +0100
@@ -0,0 +1,1338 @@
+QMAIL_LDAP by Andre Oppermann <opi@nrg4u.com>,
+Claudio Jeker <jeker@n-r-g.com> and Boris Lutz <lutz@n-r-g.com>
+(c) 1999-2004 Internet Business Solutions AG
+
+RELEASE: $Date: 2006/02/01 15:59:19 $ ($Revision: 1.220 $)
+
+
+This is the NEWS FILE, so the QLDAPINSTALL file gets a bit cleaner.
+This file is NOT structured!!
+
+TODO:
+
+ see QLDAPTODO
+
+WARNING: If you are upgrading from 20030801a or earlier make sure that
+         you have read the news section for 20030901.
+
+NEWS for current stuff:
+
+ Rewritten forwarding code in auth_pop and auth_imap. The copyloop is now
+ using stdin and stdout for communicating with the client. This should fix
+ a problem with ssl encrypted sessions. Additionally write polling was
+ implemented. This should give better reaction on slow links.
+
+ ~control/goodmailaddr allows more ways to check if a address is allowed:
+   foobar@qmail-ldap.org        full match, user & domain
+   @qmail-ldap.org              match domain only (all users are allowed)
+   abuse@                       allow specific user for all domains
+   foo-catchall@qmail-ldap.org  allow addresses like foo-bar@qmail-ldap.org
+                                or foo-bar-baz@qmail-ldap.org
+				will only work if compiled with DASH_EXT
+   catchall@qmail-ldap.org      same as @qmail-ldap.org
+
+ Enhance qmail-verify to check against ~users/cdb and /etc/passwd if local-
+ delivery is enabled (like qmail-lspawn does). This makes RCPTCHECK usefull
+ in mixed user environments.
+
+ Minor enhancements in qmail-verify error handling.
+
+ Some cleanup in qmail-smtpd mostly log stuff.
+ 
+ Set RELAYCLIENT everytime we allow relaying because of some reason (SMTP AUTH
+ or relaymailfrom). Requested by many so that qmail-scanner can make additional
+ decisions based on RELAYCLIENT.
+
+ Just use malloc() instead of the code in alloc.c that code could be exploited
+ on 64-Bit systems with a lot of RAM and no limits.
+
+NEWS for 20050401a stuff:
+
+ Bug fix in qmail-local. qmail-local crashed when trying to access
+ .qmail files with dash extension. Found by s.arakawa.
+
+NEWS for 20050401 stuff:
+
+ Enable logging in qmail-verify. It is not perfect but far better than
+ before.
+
+ Correctly escape the AUTH= extension according to RFC2554 in xtext form.
+ Initial idea and problem found by Aiko Barz.
+
+ Add -t type option to digest to specify a specific algorithm to be used.
+ This makes digest usable for scripting.
+
+ Correctly parse multiline ~control/ldapserver files. OpenLDAP seems to
+ be a bit finically about what it accepts.
+
+ Use correct original sender address if using one of the qmail-secretary
+ modes -- like the moderator support of qmail-group. Previously all bounces
+ were sended to the moderator okey-ing a message.
+
+ Fix bug in the EHLO response parser of qmail-remote. Looks like authentication
+ only worked on TLS encrypted sessions. Reported by Amol Kulkarni.
+
+ Use SSL_CTX_use_certificate_chain_file() instead of
+ SSL_CTX_use_certificate_file() to load the TLS certificates. With this it
+ is possible to load the complete certificate chain instead of just the first
+ one. Idea and patch by Michel Minsoul.
+
+NEWS for 20041201 stuff:
+
+ Introduce a better extension handling to qmail-group. Qmail-group will now
+ only deliver mails if they are sent to the main address. This should fix
+ possible mail-loops. Also the extension -moderators is now supported and
+ mails to that email will be sent to all moderators.
+
+ Introduce the new qmailGroup ldap attribute "bounceadmin". Bounceadmin is a
+ list of rfc822 mail addresses where delivery errors are sent to. If no
+ bounceadmin is specified then the original sender of the mail will be used.
+
+ qmail-reply sends mail with empty envelope sender as it does not make sense
+ to get bounces for automatic replies. Prodded by Andre who had over 1000
+ failure notices after his vacation.
+
+ Only update the qmail-reply recent sent db if we would send a mail to this
+ user. Before every sender was added to the db and caused massive trashing.
+
+ Bugfix in qmail-group to make filtermember/filtersender work when
+ membersonly is turned on. Previously users specified via a filter where
+ always considered not member of the group. Reported by Flavio Fonseca.
+
+ Fix qmail-group so that senderconfirm and moderation can be used togehter.
+ This fixes a problem where qmail-secretary detected a mail loop when both
+ options where used.  Reported by George Lekatsas.
+
+ Source ~control/{aliasempty,defaultdelivery} with cat instead of head -1
+ so it is possible to define more than just a simple ./Maildir/ delivery
+ as default. Found by Michel H.
+
+NEWS for 20041101 stuff:
+
+ Don't forget to check also for accountStatus deleted in the auth tools and
+ deny access in this case.
+
+ Only send the AUTH option in MAIL FROM: if the session is authenticated.
+ Fixes a problem seen with some obscure mail server.
+
+NEWS for 20040801 stuff:
+
+ In qmail-smtpd if SSLCERT is set use this as the path to the certificate and
+ not as the path to a file containing the path to the certificate. Noticed by
+ Zachary Kotlarek.
+
+ Fix a security bug in the startup scripts. qmail-smtpd is run under the
+ user $USER. If $USER was set on invocation of the script, the value was not
+ reset to the default qmaild. In the worst-case qmail-smtpd was running as
+ root. Yikes! To install the new script you need to remove the old one before
+ make setup check. Also affected are the qmail-pbsdbd and qmail-qmqpd
+ run-scripts.
+
+ Fix a bug in smtp_auth handling where empty password caused a disconnect.
+ Noticed by Fabio Gomes.
+
+ Fix multiple bugs in qmail-smtps starttls handling. Noticed by Ted Zlatanov.
+
+NEWS for 20040701 stuff:
+
+ qmail-smtpd log level cleanup. Add a additional level for accounting and
+ remove some redundant messages.
+
+ Fix a bug in checkpassword.c that caused auth_pop and auth_imap to ignore
+ the per user quota if rebind was used. Reported by nbari at unixmexico.com
+
+ Add ~control/remotecert for qmail-remote similar to ~control/smtpcert
+ for qmail-smtpd. The big difference is that qmail-remote will use STARTTLS
+ and SSL encryption even without this file as a certificate is optional for
+ the client side. 
+
+ To enable SMTP STARTTLS the path to the cert file needs to be set in
+ ~control/smtpcert or set via the env var SSLCERT.
+
+ If the defaultdelivery aka aliasempty is not a local delivery qmail-local
+ may start additional programs while running qmail-reply. Reported by
+ Florian Pflug.
+
+ Fix the SIGHUP handling between qmail-send and qmail-local.
+
+ Messages sent from a moderator to a group only need to be approved by the
+ moderator himself.
+
+ qmail-todo started to spin if qmail-send exited non nicely (aka crashed).
+
+ Fix some path and 'sh' issues in the run scripts reported by Toni Mueller 
+ and Ted Zlatanov. While doing that add some ssl run scripts.
+
+ Fix QUOTATRASH option by including LDAPFLAGS to the maildir++.o target.
+ Reported by Zachary Denison.
+
+ Replaced the cdb functions with the public domain mmaped version from
+ tcpserver. This makes it possible to keep the file open and do extremly
+ fast searches.
+
+ Add license to files that are under our (Andre or mine) copyright. At least
+ it is now clear what is our stuff and what is coming from djb.
+
+NEWS for 20040401 stuff:
+
+ Added some qmail-group docu. See QLDAPGROUP.
+
+ Better 550GREETING support and added an additional 421GREETING mode to
+ qmail-smtpd.
+
+ Qmail-secretary should ignore mails with precedence set to list, junk or bulk.
+
+ Added Bruce Guenters qmail-qmqpc connect timeout patch.
+
+ Add SMTP AUTH support to qmail-remote. A user can be specified via
+ ~control/smtproutes. To authenticate all mails to inside.af.mil with
+ user joe-user something like this can be used.
+   inside.af.mil:firewall.af.mil joe-user eat@joe's
+
+ Don't let qmail-group or qmail-secretary inject mails with no recipients.
+
+ Print remote IP address in error messages for RBL rejects and denied
+ relaying attempts to make debugging based on the bounce messages far
+ easier.  Requested by Jason Eggleston.
+
+NEWS for 20040301 stuff:
+
+ Fix buffer overflow noticed by Georgi Guninski in qmail-qmtpd.c.
+ There is no easy way to exploit it. Additionally the same issue is
+ patched in qmail-qmqpd.c.
+
+ Fix an issue in qmail-remote.c with TLSDEBUG defined. Noticed by
+ Oskar Eyb and Rainer Hartenthaler.
+
+ Fix bugs in qmail-group. The moderation feature was broken and in some
+ header fields a char of the local address was chopped of. Noticed by
+ different people.
+
+ Fix endless loop in qmail-ldaplookup noticed by Tomas Kuliavas.
+
+ Fix bug in substdio_feed noticed by Stefan Paletta.
+
+ Fix qmail-inject -f "" bug noticed by Mesa de Ayuda.
+
+ Added LDAPFLAG -DBIND_8_COMPAT needed on systems with new incompatible
+ bind9 header files. Currently this is necessary on MacOS X 10.3.
+
+ Disable the too generic zip blocker signature in the example signature file.
+
+NEWS for 20040201 stuff:
+
+ Yet another bug fix in the maildirmake code of auth_mod.c. The previous fix
+ was definitifly not strong enough,
+
+ Bug fix in condwrite. The maildir child should not exit 99 on finish the
+ parent should exit 99 and the child 0.
+
+ In qmail-smtpd limit the accepted text line lenght to 10000 characters.
+ The RFC proposes a maximum of a 1000 but be nice to broken MTA/MUAs and it
+ does not really hurt us.
+
+ Enhanced qmail-smtpd execcheck. Basic idea is form Russel Nelsons
+ qmail-smtpd-viruscan-1.3 patch. MIME signatrues are now stored in the control
+ file ~control/signatures. Two enhancements where done to Russels patch.
+ First MIME forwarded messages are also completly scanned and secondly it is
+ possible to use a '*' in the signature as a anymatch character. This makes
+ the signatures more powerful.
+
+ It is now possible to limit the allowed senders to a qmail-group with
+ dnsender, rfc822sender and filtersender similar to dnmember, rfc822member
+ and filtermember. If membersonly is enabled and one of those sender attributes
+ is used only mails comming form this list of senders are passed to the group.
+
+ Ensure qmail-remote does not print the DDC percentage in error messages.
+
+ Add auto maildirmake capability to qmail-secretary.
+
+ qmail-verify, auth_smtp, qmail-group and qmail-ldaplookup only try to read
+ ~control/ldaplogin and ~control/ldappassword. If one of the files can not be
+ read use anonymous login or the alternate login credentials in case of
+ qmail-group and qmail-ldaplookup. 
+
+ Yet another cleanup round through the whole code. Fix many issues with integer
+ overflows inclusive the qmail-smtpd crash found by Georgi Guninski.
+ While doing that rename puts and log to putstr and logit so that it does not
+ conflict with gcc internals.
+
+ Bugfix in auth_mod.c reported by em (at) cmla.ens-cachan.fr
+
+ Yet another run script update. $ALIASEMPTY fix from Jo Geraerts and correct
+ $QMAIL idea from Ace Suares.
+
+ Do the same game in Makefile.cdb. Prepend %QMAIL%/bin infront of qmail-cdb.
+
+ Fix typo in qmail-secretary. Reported by Beni Schoedler.
+
+NEWS for 20040101 stuff:
+
+ Never fdcopy STDOUT with STDERR in qmail-popup. The copy was only skipped if
+ DEBUG was set. So it was not possible to use qmail-pop3d accounting/logging
+ if a non-DEBUG version was compiled. Report by Henning Brauer.
+
+ Once again I missed something in the run scripts. It would be good to run
+ awk scripts with awk. Remember to remove the old run scripts before a
+ make setup check.
+
+ Kill the qmail-verify zombies in qmail-smtps call infrastructure. Reported
+ by Kevin J. McCarthy.
+
+ auth_pop and auth_imap used always the default quota settings because
+ the quota attributes for the ldap search where missing. Thanks to Ricardo
+ Cerqueira for the report.
+
+ The envdir parsing in the runscripts was absolutly broken. First of
+ all I used a C-Style comentary in a shell script and then the simple
+ eval `env - envdir ./env env` does not work with environments with
+ spaces. So this was exchanged through a simple awk script. Fixed some
+ other runscript bogons too.
+ To install the new run scripts the old ones need to be removed `rm
+ /var/qmail/boot/*/run`
+
+NEWS for 20031201 stuff:
+
+ Do not overwrite rules file on new install (make setup check).
+
+ Make it possible to specify the number of concurrent connection of tcpserver
+ controlled daemons (qmail-smtpd, qmail-qmqpd, qmail-pop3d, qmail-imapd).
+ This can be achived by setting the CONCURRENCY environment variable.
+
+ qmail-reply does no longer reply to messages tagged with a spamassassin
+ "X-Spam-Status: Yes" header.
+
+ The dynamic data compression done in qmail-qmqpd can be explicitly disabled.
+ If the environment variable NOCOMPRESS is set the feature is disabled.
+
+ Sending a SIGHUP reloads now also the qmail-lspawn config. Sending a
+ SIGHUP directly to qmail-lspawn is no longer supported. qmail-send sends
+ upon receipt of a SIGHUP a empty message with delivery number 0xBEEF (48879)
+ to the qmail-lspawn process. This may cause trouble if you have a concurrency
+ bigger than this. The code should work even with higher values but I'm not
+ able to test this.
+
+ qmail-reply should clear the database if the reply text changes. So that
+ you get a new message after the change.
+
+ Fix in check.c:sanitypathcheckb(). Until now .. where not allowed in a
+ path. Now we check for the real thing(tm) "/../" and "^../".
+
+ Case sensitivity bug fix when using locals.cdb. While constmap uses case
+ insensitive compares cdb doesn't, this will cause trouble when using local.cdb
+ and the envelope recipient has uppercase letters in the domain part.
+ Thanks to Doug Council for the report.
+
+ Do not touch "down" files in service dirs on install else we would disable a
+ already enabled service without the knowledge of the user.
+
+NEWS for 20031101a stuff:
+
+ Nasty bugfix in qmail-qmqpd with compression turned on. On slow links large
+ mails could cause a transmission error.
+
+ Minor bug fixes in passwd.c, qmail-remote.c, qmail-smtpd.c and rcpthosts.c.
+ Thanks Toni Mueller, Vicente Aguilar and Neil Sequeira for the reports.
+
+NEWS for 20031101 stuff:
+
+ Basic daemontool run scripts installed in ~/boot. qmail-ldap installs now
+ daemontools run script for most services in ~/boot. A Makefile for cdb
+ updating is installed in ~control.
+
+ locals and rcpthosts can now be stored as cdb. This makes morercpthost.cdb
+ superfluous, also the hupping of qmail-send if the locals.cdb file changes
+ is no longer neccesary. If locals.cdb is present locals is ignored respectively
+ if rcpthosts.cdb is present rcpthosts and morercpthosts.cdb are ignored.
+
+ Important bug fix: if you removed rcpthosts, qmail-ldap became a open relay.
+ This is stock qmail behaviour but since we include locals in our rcpthost
+ check this old assumption is wrong. We also consider the stock qmail behaviour
+ as a design flaw because a mta should never be a open relay unless the 
+ luser want's so.
+
+ readwrite cleanup. Similar to other djb ware we wrap read() and write()
+ into the functions subread() and subwrite(). This solves the 64-bit troubles
+ with read and write. read() and write() should no longer be used together with
+ the substdio framework.
+
+ Huge cleanup. Bring qmail into the 21st century. Define all prototypes
+ and include the needed system include files. This commit fixes about 99%
+ of all compiler warnings and makes code developing lesser error-prone.
+ The Makefile dependencies need to be updated to reflect reality.
+ A few errors are still in the tree which are either hard to solve or
+ considered harmless -- mainly return type of main() in a few helper apps.
+ This cleanup brought some strange bugs to light which are now fixed.
+
+ Finally enabled the "send only one reply to each sender" feature
+ in qmail-reply.
+
+ Critical bugfix in auth_imap.c. A bug in the function that should invoke
+ the next authmodule caused auth_imap to end up in one infinit loop.
+
+ Add DUPEALIAS feature. When duplicate or overlapping mail or
+ mailAlternateAddress exist the mail will be forwarded to this local
+ user (like the alias user of qmail). It can be either bounced or
+ handled there with a script/program answering with some meaningful
+ reply. This compile time option is intended for migration of old
+ X.400 mail systems where a user was available under some short names
+ if nobody else had the same shortname.
+
+ Add some more features to qmail-ldaplookup. Password compare works now.
+ It is now also possible to use a different binddn and bindpw.
+ What is missing are local /etc/passwd lookups and group handling.
+
+ The objectclass of a group object can now be changed like all other ldap
+ values via qmail-ldap.h.
+
+ Fix in the qmail schema definitions: a ')' was missing.
+
+NEWS for 20031001 stuff:
+
+ Change NOPOP in accountStatus to NOACCESS as it is not just disabling
+ pop access but also imap and possibly others.
+
+ ~control/ldapserver is now read with control_readfile. Multiple servers
+ now have to be specified at one per line. Using # for comments is allowed
+ and empty lines are removed.
+
+ qmail-smtpd now reads ~control/locals and merges this with ~control/rcpthosts.
+ It is no longer neccessary to list a domain in both files. Anything listed
+ in locals is now automatically accepted by qmail-smtpd. rcpthosts is only
+ used and needed for domains we have to do spooling for.
+
+ New compile time option IGNOREVERISIGN to disable dns wildcard matches
+ on gtlds. With this the return mx check will work again with .com domains.
+ This version can also handle multiple A records. A big hurray to verisign
+ who added this broken feature to the internet.
+
+ Added auth_smtp and AUTH capabilities to qmail-smtpd. Enabled via the 
+ SMTPAUTH env var. If SMTPAUTH is set to TLSREQUIRED it is neccesairy to
+ do a STARTTLS before issuing an AUTH command. If AUTHREQUIRED is set any
+ user MUST successfully authenticate before issuing a MAIL FROM command.
+ The string in the env var AUTHPREPEND will be prepended to the userid in
+ the received line.
+
+ New tool qmail-verify which is used for email address verification. See
+ next two new features.
+
+ smtp recipient verify. This qmail-smtpd feature will look up every RCPT TO
+ address in ldap with qmail-verify to check the recipients existance. If it
+ does not exist, qmail-smtpd will answer directly with a 550 reply instead
+ of accepting the email and bouncing it later. Only addresses whose domain
+ part is listed in ~control/locals are checked (because only there we know
+ the definite answer). Relaying and rcpthosts works as before, recipient is
+ not checked for those. Addresses listed in new ~control/goodmailaddr will
+ be accepted in any case. This is very useful for important or special
+ (like postmaster or mail admin) addresses which must work under any
+ circumstances (or local addresses which are not in ldap). Enabled with
+ RCPTCHECK env var.
+
+ smtp sender verify. This qmail-smtpd feature will look up every MAIL FROM
+ address in ldap with qmail-verify to check the senders existance. If it
+ does not exist, qmail-smtpd will reject with 550 reply. In normal mode
+ only (envelope) senders whose domain part is listed in ~control/locals
+ are checked. Otherwise no-one else from outside could send mail to local
+ users anymore. In mode LOOSE it will only allow verified sender plus any
+ sender with its domain listed in ~control/rcpthosts. In STRICT mode it
+ will allow only ldap verified senders. With this you can, for example,
+ enforce that users within your network must use a valid sender which
+ exists in ldap and no other. Addresses listed in new ~control/goodmailaddr
+ will be accepted in any case. This is very useful for important or special
+ (like postmaster or mail admin) addresses which must work under any circum-
+ stances (or local addresses which are not in ldap). Enabled with SENDERCHECK
+ env var.
+
+ 550greeting to reject smtp connections right away in the smtp
+ greeting message. Use this to permanently reject all messages coming
+ from a particular ip address(range).
+
+ smtpclustercookie feature for (large) smtp MX clusters behind load
+ balancers or NAT devices. The cookie is presentented in the smtp
+ greeting as last string before \r\n. qmail-remote compares the
+ cookie with it's own and if they match assumes that the message
+ is looping. Cookies are set in ~control/smtpclustercookie. Length
+ is limited to 32 characters. Fill with some random printable chars.
+
+ qmail-smtpd now prints its hostname (~control/me) along with QP
+ when acking a message. Makes it easier to track which smtp MX cluster
+ member took the message.
+
+ qmail-smtpd greeting restructured due to the above things. It now
+ prints "220 [~control/me] ESMTP [~control/smtpgreeting] [~control/
+ smtpclustercookie]\r\n". You don't have to put the hostname of the
+ machine into smtpgreeting anymore. It is just a text. Can be empty.
+
+ qmail-qmqpd supports now both clear and ZLIB compressed communications
+ for intra-cluster forwards.
+
+ Added new tool condwrite. Works like condredirect but writes to a maildir
+ or mailfile instead of forwarding. The quota is respected and maildir are
+ created automatic if option is set. NOTE: The automatic maildir creation
+ is not capable to create valid IMAP subdirs (Maildir/.somedir).
+
+ auth_* sets now the MAILDIRQUOTA and DATASIZE environment vars.
+
+ New compile time option QUOTATRASH to include the Trash in the quota
+ calculation. The courier-imap secification tells explicitly to ignore
+ .Trash but in the last few weeks I had to find out that the courier
+ documentation should not be respected, because courier does not respect
+ it either.
+
+ qmail-reply will no longer send replies to mails tagged with a X-RBL header.
+ This should dramaticaly reduce reply bounces if used with the proper RBL.
+
+ Announce the EHLO STARTTLS option only if tls is compiled, enabled and
+ we have found a valid certificate in ~control/cert.pem for encryption.
+
+ Modernize qmail startup infratructure. First step is to redo the ~boot
+ directory and to add ~log directory. Create subdirs for qmail, qmail-smtpd,
+ qmail-qmqpd, qmail-pop3d, qmail-imapd and qmail-pbsd for supervise and
+ multilog.  Corresponding run files will come in the next release.
+
+ Fix bug in qmail-smtp addrparse function. If "mail from" or "rcpt to" did
+ neither contain a '<' nor a ':' the function returned a nullsender (bounce)
+ or recipient instead of a syntax error. This bug is also present in stock
+ qmail-1.03.
+
+ The copyloop used to forward pop3 and imap session can be simplified.
+ Neither pop3 nor imap are protocols which support half close so dump this
+ stuff. Half closing those forwarding sessions could be used as a DOS attack.
+
+ qmail-todo could end in an infinite loop if qmail-send died before sending
+ the synchronization flag. This can happen if qmail-lspawn died because of
+ a missing control file.
+
+ Print the dynamic data compression message in qmail-remote only if compressed
+ data was sent. Otherwise we get some junk number.
+
+ Fixing clustering. The cluster forwarding was broken during the rewrite
+ (20030901).
+
+ Fix error handling of qmail-quotawarning startup in qmail-local.
+
+ Bug fix in qldap_get_status reported by <krits at home dot pl>.
+
+ Removed some unneccesary verbositiy in qmail-secretary.
+
+ Bug fix in the maildir string creation. A specified count value will over-
+ write any size settings. Thanks to Neil Sequeira for reporting this issue.
+
+ SHADOWLIBS added in the digest link rule.
+
+ bug fix in auth_imap. courier-imap login program which is invoking
+ auth_imap did not adhere to its own specs and sends too much stuff.
+
+
+NEWS for 20030901 stuff:
+
+ WARNING: This release is NOT fully backwards compatible! We have made
+ certain changes for clarity and cleanup.
+
+ qmail-group added. This tool handles mailing groups stored in ldap. Members
+ can be defined as rfc822 addresses, via dn entries and via ldap filters.
+ qmail-group can restrict mails togheter with qmail-secretary. So it is
+ possible to moderate a list, to restrict the sender to be a list member or
+ to confirm each message (qsecretary).
+
+ qmail-ldaplookup has been rewritten. Not all functionality of the old tool
+ has been integrated yet. It is now possible to use search filters and to
+ show multiple entries.
+ 
+ Removed some qmail-smtpd control files (tarpitcount/delay, maxrcptcount,
+ rblonlyheader). The only and right way to set them is environment variables
+ with tcpserver.
+
+ Changed deliveryMode significantly. Before the setting of a forwarding
+ would have disabled local delivery. This is no longer the case. Each of
+ the modes has to be explicitly disabled (local, forward, program) or
+ enabled (reply). There are no longer contradicting modes which makes it
+ much more logical.
+ This change probably has a great impact on many administrative frontends!
+
+ Quota definitions are new format only. ~control/ldapdefaultquota and mailQuota
+ serve no meaning anymore. Also the string quota format (10000S,100C) is no
+ longer supported. Use ~control/defaultquota[size|count] and mailQuotaSize
+ and mailQuotaCount instead.
+
+ New tool qmail-secretary. This is the swiss army knife for mail group and
+ mailing list handling. It is used by the upcoming qmail-group tool but has
+ a compatibility modus for ezmlm (you may guess why ...).
+
+ New tool qmail-forward. This tool forwards a mail via qmail-qmqpc in a
+ much nicer way than qmail-lspawn befor. Some more or less ugly hacks could
+ be removed.
+
+ qmail-reply recent sender support finished. The code is still disabled
+ via NOTYET defines until I verified it.
+
+ The mailheader magic of qmail-reply is now also supported by qmail-ldaplookup
+ and qmail-secretary.
+
+ Fixed some problems with text control files, mainly quotawarning and
+ custombouncetext. Trailing white spaces and empty lines are no longer
+ cleared.
+
+ Rewrite of the homedirmake and maildirmake feature. Finaly auth_imap will
+ create the maildir for courier.
+
+ The environments passed between qmail-lspawn and qmail-local are now ':'
+ seperated and escaped. Nota bene the old csv stile definition of some
+ attributes mainly deliveryMode is still supported (the ',' are replaced
+ by ':' automagically).
+
+ major cleanup in qmail-lspawn ldap handling and exit-code handling code.
+ Also the forwarding code has been moved out so that this code is no longer
+ run under root.
+
+ NOPBS environment variable can now be used to disable pbsadd. This is useful
+ for nat-ed customers or if you have some local port forwarding and absolutly
+ neccessary for clusters (NOPBS set for all clusterhost IPs).
+
+ Integration for pbs tools in cluster environments. auth_* has a switch -d
+ to specify pbsadd or a other tool that is executed in all success cases be
+ it local access or session forwarding. The old way via chaning the processes
+ still works for non cluster setups.
+
+ new auth_pop, auth_imap and checkpassword implementation. The files are
+ now better seperated so that it should be possible to implement auth_smtp
+ without copying most of the auth* code. It is now possible to run the auth_*
+ tools without root priviledges and root priviledges are dropped as soon as
+ possible.
+
+ Salted versions of SHA and MD5 (SSHA and SMD5) implemented and major cleanup
+ of the hole passwd compare functions. The digest tool has been rewritten to
+ support the new algorithms and to support passwd verifying. Also the base64
+ and digest_* implementations have been cleaned up and stripped.
+
+ new and better structured ldap backend. This solves many issues we had
+ with the old hackish implementation. These are: functioning rebind, support
+ for multiple concurrent connections, more flexible support for ldap attribute
+ handling and upcomming filter functions that can handle mutliple results.
+
+ compile time option to enable ZLIB compression for QMQP cluster communication.
+ This is useful when cluster hosts are in different locations and have slow
+ or metered connections between them. All QMQP client/servers need to be
+ support the dynamic data compression, stock QMQP and compressed QMQP are
+ unable to understand each other. This may change for the server but not for the
+ client.  Enable in Makefile with -DQMQP_COMPRESSION switch.
+
+ cleaned up qmail.schema and added qmailGroup objectclass for mail groups.
+
+ major cleanup, actually a huge cleanup, currently over 75 modified, removed
+ or added files. The code is now much more modularized and protable.
+
+NEWS for 20030801 stuff:
+
+ Removed checking of client certificates from TLS in qmail-smtpd. It is
+ no longer possible to allow automatic relaying via TLS client certs.
+ TLS functionality for transport is not affected and continues to be
+ fully functional.
+
+ Some cleanup and clarification in smtpd and rbl logging.
+
+ Added Russell Nelsons antivirus patch for qmail-smtpd.
+ Compile qmail-ldap with the -DSMTPEXECCHECK option and turn it on with
+ the REJECTEXEC environment variable.
+
+ Added qmail-queue patch. Compile-time option via -DALTQUEUE.
+
+ On-the-fly SMTP session data compression via ESMTP DATAZ extension.
+ Saves a damn lot of bandwidth. This is currently draft. See
+ draft-oppermann-smtp-datacompression-00.txt.
+
+ Bug fix in Makefile (qmail-todo dependencies).
+
+ Better handling of SMTP mail-parameters mainly SIZE. Until now only the first
+ mail-parameter was used all others where ignored. Also specially escaped
+ or quoted mail addresses could result in strange outcomes.
+
+ New control/rbllist parser, it is no longer needed to use one tab as
+ separator. Lines starting with a # are comments and will be ignored.
+
+ New delivery mode noforward to disable all forwarding entries in ldap
+ and .qmail. The deliveryMode attributes need some major overhaul becasue
+ we have a few modes -- manly forwardonly, noforward, localdelivery,
+ normal and nombox -- that are exclusive. Anyway for now this should make
+ life a bit easier.
+
+ qmail-remote tries now higher MX servers if the previous server temporary
+ fails in the HELO/EHLO command exchange. >=500 errors result in a delivery
+ error.
+
+NEWS for 20030501 stuff:
+
+ gcc bug fix for OpenBSD sparc64 in digest_sha.c
+
+ Better copy loop in checkpasswords imap/pop3 forwarding this should solve
+ problems with large file downloads over imap.
+
+ Remove duplicate entries from pbsdbd cache, this should solve the "hash
+ flodding" error message.
+
+ Bug fix in rbl.c from Sami Farin.
+
+ Bad handling of return values. Per RFC a EHLO may return a 500, 502 or 
+ perhaps a 504. In this case retry with HELO.
+ Update: Some servers send some non RFC compliant error code so retry
+ with HELO in all cases.
+
+NEWS for 20030401 stuff:
+
+ Added big todo patch. Enable with -DBIGTODO in Makefile.
+
+ qmail-remote has a better look at the return codes of the helo/ehlo command.
+ This gives a better error handling in case of server that refuse the
+ connection with a >500 error in the begining.
+
+ qmail-local bug fix in .qmail parser (missing () around a ||).
+
+ Be more careful with closedir(). It is possible that the dirp is NULL.
+
+ Nasty bug fix in qmail-qmqpc.c. Due to this it was impossible to use 
+ qmail-qmqpc.
+
+NEWS for 20030301 stuff:
+
+ qmail-showctl updated so that all new control files are listed.
+
+ qmail-remote and qmail-qmqpc are now capable to bind to a specified port
+ for outgoing connections. You can use control/outgoingip and control/qmqpcip
+ to set the ip.
+
+ For ISP that need to implement some surveillance method because of some
+ beloved authoroties (like here in switzerland), we added the
+ BIGBROTHER switch. This enables a per address queue extra feature.
+ Just put a key pair like badguy@badplace.ch:bigbrother@admin.ch in
+ ~control/bigbrother to automaticaly forward all mail to or from
+ badguy to bigbrother. bigbrother can be a local, ldap or remote address.
+
+ Bug fix in qmail-local: flagforwardonly was set to 0 instead of 1 if 
+ deliverymode was forwardonly.
+
+ Bug fix in maildir++ code: At two places a closedir was missing. Thanks to
+ Reinin Oyama.
+
+ Bug fix because of a gratuitous recycling of a var in qmail-quotawarn if
+ the DOTMODE_NONE was used. Thanks to Chris Maxwell.
+
+ Don't print extended received header if the needed infos are not available.
+ This is for qmtp receives. Idea by Chris L. Mason.
+
+ Many bug fixes and enhancements in the NOTYET code of qmail-reply, inspired
+ by Neil Sequeira.
+
+NEWS for 20030101 stuff:
+
+ Retry the ldap_bind with LDAPv2 if ldap_bind fails with LDAP_PROTOCOL_ERROR.
+ This solves a problem with OpenLDAP > 2.0 client libs and a OpenLDAP 1.2
+ Server. Inspired by Henning Brauer.
+
+ New qmail-reply program. Now it is possible to define a header section
+ with %HEADER%. With this change it is possible to define special Content-type
+ and Content-Transfer-Encodings.
+
+ Bug fix in qmail-lspawn: LDAP_MAXMSIZE = 0 should be eq unlimited.
+ Thanks to Henning Brauer.
+
+ Finally added pop3d logging similar to the smtpd logging.
+
+ Added the badmailfrom-unkown feature from Maex (via Henning Brauer).
+
+ Added a fix in qmail-ldaplookup.c. Thanks to Kosh Naranek for the report.
+ 
+NEWS for 20021201a stuff:
+
+ Hot fix in qmail-local. If no quota was specified accounts with mailforwarding
+ didn't work.
+ 
+ Close directory file handle in pbsadd and pbscheck.
+
+ Nicer exit behaviour in qmail-todo (exit 0 if no error encountered).
+
+ Add caseIgnoreIA5SubstringsMatch for mailAlternateAddress in qmail.schema.
+ 
+NEWS for 20021201 stuff:
+
+ On exit qmail-todo behaves now like qmail-[rl]spawn and stays alive
+ until qmail-send exits. All zombies have been slayered.
+
+ On a -HUP qmail-send rereads more ~control files. Now bouncemaxbytes,
+ custombouncetext, locals and virtualdomains are reloaded.
+
+ There seems to be a tiny bug in qmail-1.03 qmail-clean program. Fixed.
+
+ Renamed QMAILQUOTA to MAILDIRQUOTA to work better with maildrop.
+
+ Bug fix in qldap-ldaplib.c, when the ldap lookup timed out the wrong error
+ was returned.
+
+ Minor bug fixes in the pbs tools inspired by Junjiro Okajima.
+
+ Don't use NULL in maildir++.c because it is often not defined.
+
+NEWS for 20021101 stuff:
+
+ New ldap fields added:
+ - mailQuotaSize and mailQuotaCount replace the cryptic mailQuota string.
+   mailQuotaSize specifies the maximum size in bytes and mailQuotaCount
+   is the maximum number of messages allowed.
+   Note: the old mailQuota string is still valid and used if neither 
+         mailQuotaSize nor mailQuotaCount are set.
+ - mailSizeMax specifies the maximum size of a single message the user may
+   receive. e.g. Dial-up customer prefer a small mailSizeMax.
+   Note: mailSizeMax is used in qmail-lspawn whereas databytes sets the
+         SMTP DATA limit. Therefor having a mailSizeMax bigger than databytes
+         does not make much sense.
+ The old mailQuota way of doing things is still supported.
+
+ Fixed some bugs and cleand up maildir++.c. The maildirsize parser is now
+ rock solid and does no longer freak out when lines start with spaces as in
+ the newer courier-imap releases.
+
+ quota_check() returns now also percentages over 100% (if over quota) and
+ the percentages calculation does not overflow with sizes over 40MB.
+ NOTE: quotas with sizes of around 4GB may overflow if large mails are
+ delivered and so the maildir size may get far over quota. This is a bug
+ and will get fixed somewhen (switch to 64bit quota numbers).
+
+ maildir++ quota API cleanup. quota_recalc() works now exactly like
+ quota_calc().
+
+ In qmail.schema 'ProgramDeliveryPath' was incorrectly specified as 
+ SINGLE-VALUE. Thanks to <andreas.schulze@web.de> for finding it.
+
+NEWS for 20021001 stuff:
+
+ Corrected qmail.schema contributed by Mike Jackson.
+
+ Documentation bug in POPBEFORESMTP fixed.
+
+ Add LDAPv3 protocol support.
+
+ Synchronize the external processor qmail-todo with qmail-send on startup.
+ There was a race condition on startup which caused some mails to be deliverd
+ twice.
+
+ In both auth_* tools the forwarding code was only sending a CR instead of
+ the needed CRLF.
+
+ Little fixes in the pbs tools.
+
+NEWS for 20020901 stuff:
+
+ Fixed bugs in pbscheck and pbsadd which caused unexpected behaviour if
+ multiple servers where specified.
+
+ Fixed multiple bugs in maildir++ quota handling.
+   bug in read5120(), if open failed it could cause a loop.
+   bug with handling of subdirectories (path concatenation).
+   bug with interpretation of quota strings for courier 0C means
+   no files allowed whereas for qmail-ldap it was unlimited.
+
+ Fixed some spelling errors.
+ 
+ Bugfix in auth_imap. The procedure for failed logons had a bug.
+
+NEWS for 20020801 stuff:
+
+ Fixed an error in the patch file.
+
+NEWS for 20020701 stuff:
+
+ Fix in qmail-reply: the wrong Return-Path was set because an interference of
+ qmail-locals environment and qmail-injects use of it. ($USER is used in
+ the Return-Path)
+
+ In both auth_* tools the forwarding code was sending LFCR instead of CRLF.
+
+ Fix buffer overflow in qmail-quotawarn.c. I changed the filename generation
+ without resizing the file name buffers, shame on me. 
+ NOTE: This overflow can not be exlpoited.
+
+ better handling of virtual/ldap .qmail handling.
+ The ldap .qmail arguments are now exected in the following way:
+   1. reply (deliveryMode: reply)
+   2. delivery programs (deliveryProgramPath)
+   3. forwards (mailForwardingAddress)
+   4. localdeliver (deliveryMode: localdelivery)
+ So it is possible to use a filter delivery program or other more complex
+ delivery options.
+
+NEWS for 20020501a stuff:
+
+ bounce messages are now qsbmf-compliant, wether custombouncetext is set or
+ not. Note that you may not have blank lines in custombouncetext.
+ Thanks to Henning Brauer for the patch and to Mike Jackson <mjj@pp.fi> for
+ the report.
+
+ The pop-before-smtp tools now support transaction of additional environment
+ variables. See POPBEFORESMTP for more info.
+
+ Use real rfc822 timestamps and more Maildir stile filename in qmail-quotawarn. 
+ This should fix order problems in mailclients.
+
+NEWS for 20020501 stuff:
+
+ ****** ATTENTION the format of ~control/rbllist has changed, see ******
+        QLDAPINSTALL for information about the new rbllist file.
+
+ Major overhaul of qmail-smtpd. Completely restructured anti-spam stuff and
+ replaced DENYMAIL environment variable (settable through tcpserver) with:
+  - SMTP550DISCONNECT to disconnect the smtp session immediatly after a fatal
+    5xx error
+  - NOBOUNCE to reject null sender bounces
+  - SANITYCHECK to reject messages without @, no . in TLD, too short/long TLD
+  - RETURNMXCHECK to check if the sender has an MX
+  - BLOCKRELAYPROBE to block rcptto containing !%@ before @ from Russell Nelson
+  - RBL to check RBLs
+  - RBLONLYHEADER to only add a X-RBL header
+
+ added bouncemaxbytes patch:
+ to turn it on write the amount of bytes to bounce in the file 
+ ~control/bouncemaxbytes.
+ Work inspired and mostly copied from Frank DENIS aka Jedi/Sector One.
+
+ Bug fix in qmail-send.c log handling:
+ If in one read a log entry and a delivery status notification was delivered the
+ status notification was dropped and therefor qmail-send did not close the job.
+
+ qmail-remote supports the smtp size extension as specified by rfc 1870.
+ If the EHLO extension size is set qmail-remote sends size in the mail from
+ commando. It does not parse the EHLO size argument to check if the size is
+ OK, the remote smtp server should decide if it is OK.
+
+ clean up in qmail-remote, the starttls option was not compared in a case
+ independend way as defined in rfc 2821. The tls debug option is now called
+ TLSDEBUG.
+
+ added Russ Nelson patch to qmail-remote to send using QMTP.
+ From his patch:
+  This patch to qmail-remote causes it to attempt qmtp first if the MX priority
+  indicates so.  Read http://cr.yp.to/proto/mxps.txt for more information.
+  If you want this qmail-remote to be able to send email to you using qmtp,
+  then you should be running a qmtpd on port 209, and you should have your
+  lowest MX priority be 12801.
+
+ added pop-before-smtp tools (see POPBEFORESMTP for more info).
+
+ reject any null sender (bounce) smtp session with more than one rcpt-to
+ (based on an idea of Charles Cazabon and some code of Henning Brauer)
+
+ updated QLDAPINSTALL (more about those nasty -lresolv and ld.so problems)
+
+ beautified the output of the recieved line (added an additional linebreak)
+
+ Add a precedence bulk header when we forward a message to more than one
+ recipient. So auto-reply programs at the recipients will not answer such
+ mails. A message forwarded to more than one recipient is now considered
+ a mailing list email.
+
+ Add an external TODO processor program. This moves the queue todo processing
+ out of qmail-send to avoid the silly qmail syndrome with high injection rates
+ (see EXTTODO for more info). Enable with -DEXTERNAL_TODO in Makefile.
+
+NEWS for 20011001 stuff:
+
+ added a variation of Henning Brauer's alternate mailhost patch.
+ For more info: mailto:<qmail-ldap-get.5350@qmail-ldap.org>
+
+ added a variation of Henning Brauer's dash-ext patch. The main
+ difference is the way it handels the extensions.
+ Example lookup scheme:
+   aaaa-bbbb-cccc@domain.tld
+   aaaa-bbbb-CATCHALL@domain.tld
+   aaaa-CATCHALL@domain.tld
+   CATCHALL@domain.tld
+ where CATCHALL is replaced with the value of LDAP_CATCH_ALL defined
+ in qmail-ldap.h. If CATCHALL is set to "default" instead of the standart
+ "catchall" it is allmost stock qmails behaviour.
+ The dash-ext stuff can be turned on with the -DDASH_EXT option in Makefile.
+
+ some rewrite of qmail-ldaplookup. See qmail-ldaplookup -h.
+
+ Makefile bug fixed, spawn.c was compiled without -DDEBUG. Not in 0802i.
+
+ Changes in qldap-ldaplib.*:
+  added qldap_open to open the ldap connection
+  added qldap_close to close the ldap connection
+  renamed ldap_lookup to qldap_lookup
+ Now it is possible to use one ldap (TCP) connection for multiple queries, so
+ the connection overhead with DASH_EXT is drastically reduced.
+
+ new debug/log handling. In qmail-lspawn the debug output is no 
+ longer added to bounce mails.
+
+ bug fix in the cleaned up NS-MTA code.
+
+ bugfix in catchall search string generation. Hopefully the last one.
+
+ bugfix in qmail-ldaplookup (ldap_value_free). Thanks to Sascha Gresk.
+
+ better handling of deliverymode in qmail-lspawn.c
+
+NEWS for 20010501 stuff:
+
+ bugfix in qmail-local.c by Mark Belnap. Problems with deliverymode reply.
+
+ disallow null passwords in auth_pop and auth_imap.
+
+ added RBLONLYHEADER logging control file and variable. With this it will
+ no longer reject a mail upon a RBL match but it will mark it with a "X-RBL:"
+ header.
+
+ major cleanup in digest_* and base64 to make the code more djb style.
+ Minor cleanup in some other files. compatibility.h is no longer needed. YES!
+
+ string fix in digest_md5.c (NS_MTA handling)
+
+ bugfix in catchall search string generation.
+
+ bugfixes in maildir++ support. Thanks to Franky Van Liedekerke.
+
+ bugfixes in qmail-reply
+
+ new attribute qmailAccountPurge for automatic purging of maildirs from
+ deleted accounts
+
+NEWS for 20010301
+
+ added 0.0.0.0 patch
+
+ some fixes for misc. stuff from Chris Noe
+  - with DEBUGLEVEL set, the default ldapGID is printed incorrectly
+  - The line above says 'without trailing slash' but the example has one :)
+  - Permanet -> Permanent
+  - Programm -> Program
+  - fix qmail-lspawn 'Out of memory' error when attempting local delivery
+    to a nonexistant user.
+
+ fix for qmail-reply.c from Jamie Blondin
+  - handle precedence flag in the right way
+
+ fix for qmail.schema mailReplyText from David E. Storey
+
+ fix for ldaptimeout to just defer message delivery instead of bouncing
+ sometimes
+
+NEWS for 20010201:
+
+ fix for ldapobjectclass bugfix
+
+ beautyfied qmail-reply.c. Now it should handel most messages in a correct
+ and nice way.
+
+ bugfix for the new ldapobjectclass and ldaptimeout stuff
+
+ bugfix in maildir++.c: algorithm has ignored all subdirs except .Trash
+
+NEWS for 20010101:
+
+ introduced ~control/objectclass to limit the ldap search to a specific
+ ldap objectclass as suggested in some recommended procedures.
+
+ bugfix in maildir++:
+    files with sizes containig 0 or 9 where claclculated wrong
+    if only one of C or S type where declared the quota of the other was ignored
+
+ changed ALIASEMPTY in qmail-ldap.h from /dev/null to |sh -c "cat > /dev/null"
+ direct writing to /dev/null resulted in a soft error. This shell call does the
+ same without an error.
+
+ introduced ~control/ldaptimeout to limit the time and ldap search might
+ take until the delivery attempt is being deferred and tried again later.
+ The default is 30 seconds.
+
+ works fine with OpenLDAP 2.x (2.0.7).
+
+ included the OpenLDAP 2.x LDAPv3 Schema definition file created by
+ David E. Storey. This version is based on the original work by David
+ but modified quite a lot by Andre. Also qmail-ldap has got it's own
+ offcially IANA assigned OID.
+
+NEWS for 20001201:
+
+ cluster loop protection enhanced, now also the users mailaddress is added:
+     Delivered-To: CLUSTERHOST host.name.as.in.control.me users@e-mail.addr
+
+ new maildir++ quota algorithm implemented. This one is simpler and should
+ therefor work much better. NOTE: The code was not tested under havy load.
+
+ major enhancements in qmail-reply.c. Fixed a bug that could crash qmail-reply
+ if a bad mail was sent. The output of qmail-reply was also beautified.
+
+ introduced MAXRCPTCOUNT to limit the maximum number of rcpt to's in one session.
+
+ introduced RBL support to check the senders IP against a number of RBL's, see
+ ~control/rbllist.
+
+ documented ~control/relaymailfrom to allow relaying based on the senders
+ mail address.
+
+ documented LOGLEVEL and DENYMAIL environment variables to qmail-smtpd.
+
+NEWS for 20001013:
+
+ possible fix for newer gcc. Problems with va_arg and unsigned chars. 
+ I don't have such a new gcc, so I don't know if this fixes the problem.
+
+ bug fix for the problem mentioned by Aleksander Dzierzanowski (mail to deleted
+ mailfiles bounce if there is a quota set).
+
+ cluster loop protection added. Now it should be impossible that mail loop
+ forever if the cluster was badly configured. It works via the Delivered-To line
+ and uses something like this: 
+     Delivered-To: CLUSTERHOST host.name.as.in.control.me
+
+ fixed multiple problems with suns cc.
+
+ fixed multiple problems and bugs in TLS support.
+
+ fixed a bug introduced with the bitmask support for debug outputs.
+
+ cleanup at different locations to respect the signedness of variables
+
+ added bitmask support for debug outputs, so DEBUGLEVEL=3 will print error and
+ warnings but DEBUGLEVEL=2 only warnings. Note: init_debug's 2nd argument has
+ changed, it's now a binary mask that is binary anded with the debuglevel. 
+ e.g.  to disable PASSWD outputs use something like -1^256 as 2nd argument.
+
+ added some defines for better testing:
+   use -DPORT_SMTP="alternate smtp port", -DPORT_LDAP="alternate ldap port" and
+       -DPORT_QMQP="alternate qmqp port" to change those ports.
+
+NEWS for 20000701 patch:
+
+ if the LDAP server is down put the message back into the queue instead of
+ bouncing
+
+ correct spelling errors in many files
+
+ forcing forwardonly and ldaponly when neither LDAP_MAILSTORE nor LDAP_HOMEDIR
+ is defined
+
+ bugfixes in hier.c and install-big.c to install qmail-ldaplookup with correct
+ 0700 permission, as told in the QLDAPINSTALL file
+
+ bug fix in checkpassword.c and qmail-ldaplookup.c with wrong index to the 
+ LDAP args array. Thanks to Ricardo Cerqueira
+
+ small bug fix in qmail-ldaplookup, fixed a wrong output.
+
+ added possible connection less LDAP support. Untested because slapd does not
+ support cladp until now. To turn it on use -DUSE_CLDAP as LDAPFLAGS
+
+NEWS for 20000601 patch:
+
+ update of the QLDAP* files
+
+ bug fix in maildir++.c and qmail-local.c, now quota_add should add the correct 
+ size of the mail. Until now only the message without DTLINE and RPLINE was 
+ sized
+
+ bugfixes in "empty file list :)"
+
+
+NEWS for 20000501 patch (and some also for 20000401):
+ 
+ Add the new control files and their meaning to qmail-showctl
+ You can use qmail-showctl to check your setup.
+
+ added new tool qmail-ldaplookup with this program you can check the ldap
+ db entries. Similar to the old checkpassword with debug support.
+ Usage: qmail-ldaplookup {-m mailaddress | -u userid [passwd]}
+ NOTE: because this tool could show critical data (like the hashed passwd)
+       it is installed with mode 000 (no rights for anybody)
+       You should only give root the permission to start it.
+
+ new mailMessageStore/homeDirectory handling.
+ Because a lot of people requested it and because I was also unhappy with it
+ I have rewritten/enhanced the mailMessageStore handling.
+ Now the homedir and aliasempty are set via both 
+ mailMessageStore (LDAP_MAILSTORE) and homeDirectory (LDAP_HOMEDIR).
+  It works like this:
+    IF LDAP_HOMEDIR exists it is used as $HOME (qmail-locals 3rd ARGV)
+      IF also LDAP_MAILSTORE exists LDAP_MAILSTORE is used as aliasempty
+        (last ARGV of qmail-local)
+      ELSE (no LDAP_MAILSTORE ) use the aliasempty specified 
+        in /var/qmail/rc or similar
+      FI
+    ELSE IF LDAP_MAILSTORE exists but no LDAP_HOMEDIR exists
+      IF LDAP_MAILSTORE is absolute use LDAP_MAILSTORE as 
+        $HOME and use standard aliasempty
+      ELSE (LDAP_MAILSTORE not absolute) use control/ldapmessagestore as
+        prefix to LDAP_MAILSTORE and use this as $HOME and use std. aliasempty
+    ELSE neither LDAP_MAILSTORE nor LDAP_HOMEDIR exists
+      use ~alias as $HOME and ALIASDEVNULL as aliasempty 
+    FI
+  
+  NOTE: the case neither LDAP_MAILSTORE nor LDAP_HOMEDIR is a bit special
+        ~alias is installed as root.qmail mode 02755 (rwxr-sr-x) so no user
+        can write to this directory. ALIASDEVNULL is defined in qmail-ldap.h
+        normally /dev/null can be used (forward-only and ldaponly will be forced
+        in the next release) or a special alert tool can be used 
+        ("|/var/qmail/bin/myalerttool")
+  NOTE2: if you use "homeDirectory" and "mailMessageStore" in an incompatible 
+        way and you want the old behavior back define LDAP_HOMEDIR in 
+        qmail-ldap.h as an nonexistent ldap db field like noHomeDirectory.
+
+ new check algorithm, I think it's faster and better.
+ Have a look at check.c. At the end of the file there is a array with all
+ ASCII chars (7bit). You can allow or deny char by adding:
+  DENY_ALL:   always deny this char
+  ALLOW_ALL:  always allow this char
+  ALLOW_USER: allow this char for username checks (chck_user)
+  DENY_USER:  deny this char for username checks (chck_user)
+  ALLOW_PATH: allow this char for path checks (chck_path)
+  DENY_PATH:  deny this char for path checks (chck_path)
+  ALLOW_PROG: allow this char for program checks (chck_prog)
+  DENY_PROG:  deny this char for program checks (chck_prog)
+  NOT_FIRST:  deny this char at the beginning of a string
+  SPACE:      alias to ALLOW_PROG
+  PARANOIA:   deny most shell special chars like '|' or '*' for program checks
+              can be turned on or of in qmail-ldap.h
+  Example:
+   /* 7  \007 ^G */ DENY_ALL, /* deny control chars */
+   /* 45 '-'     */ ALLOW_ALL|NOT_FIRST, /* allowed but not first */
+   /* 47 '/'     */ ALLOW_ALL&DENY_USER, /* allowed only for path and prog */
+   /* 58 ':'     */ ALLOW_PROG|ALLOW_PATH, /* like before */
+ 
+  As you can see ALLOWs have to be ORed together whereas DENYs have to be ANDed
+  NOT_FIRST has to be ORed and PARANOIA has to be ANDed.
+
+ getcwd and chdir no longer used in qldap-ldaplib.c init_ldap function. 
+
+ changed the connection forwarding under pop and imap. Now it should work 
+ correctly, or at least better then before ;-)
+
+ major cleanup in maildir++ support (mainly maildir++.c)
+ 
+ bugfixes in qmail-lspawn.c, qmail-reply.c and checkpassword.c
+ 
+
+NEWS for previous releases:
+
+ Added new debug facility that is usable for the auth tools and qmail-lspawn.
+ The debug-level can now be changed at runtime and everything gets logged via
+ splogger or any other logger connected to stderr of the execution chain.
+ You can set the debug level easily with the DEUBUGLEVEL environment variable.
+
+ Created a new auth tool for pop3 and imap. The old checkpassword is not 
+ needed anymore. The new programs are auth_pop and auth_imap.
+ To have the possibility to compare cleartextpasswords (password how are 
+ stored clear text in ldap) define CLEARTEXTPASSWORD. Because this setting
+ is a security disaster it is normally off. All other modes (hashed MD4, MD5,
+ SHA and the standard DES crypt) are not affected.
+ 
+ Rewritten qmail-lspawn and the auth tools. Both programs use now the same 
+ debug and ldap functions, which are now moved to new files (qldap-*).
+ The complete ldap lookup is now more flexible, so you can easier add your 
+ special stuff.
+
+ The qmailUser ldap field and the corresponding conf file are no longer used,
+ they have been replaced with the uid field.
+
+ Added maildir++ support, this means especially better quota support via the
+ maildir++ maildirsize file. For more info have a look at courier-imap
+ http://www.inter7.com/courierimap/
+
+ Added signal-handler for qmail-lspawn, now with a SIGHUP the qmail-lspawn
+ parent process reloads the his settings ( via the ~control files )
+
+ Added cluster support, use -DQLDAP_CLUSTER for enabling.
+
+ Removed PWOPTS=-DLOOK_UP_PASSWD because it was only for checkpassword
+ and with ldaplocaldelivery you get the same result on the fly.
+
+ Few minor bugfixes (qmail-qmqpd.c, qmail-qmtpd.c, receive.c)
+
+ Updated QLDAPINSTALL and added new QLDAPNEWS because QLDAPINSTALL was
+ getting to long.
+
+ Changed the make process, now with the make setup check also the qmail-ldap
+ parts are build and installed. Have fun ...
+
+ Few minor bugfixes (accountStatus, AUTO_MAILDIRMAKE)
+
+ Hack in the LDAP search filter escape function due to a bug in most LDAP
+ servers. Instead of escaping the wildchars we replace them with '_' as 
+ long as -DLDAP_ESCAPE_BUG is present. (see Makefile)
+
+ a catch all mail for one domain system is now available. The default
+ catchall account is "catchall@domain.com". You can change that to any
+ other sting in qmail-ldap.h at compile time. LDAP wildcards are not
+ allowed.
+ Due to a bug in the LDAP servers wildcards escaping does not work, so pay
+ attention.
+
+ rewritten qmail-locals qldap code, now supports better support for different 
+ dotModes. There are also some new settings.
+
+ fixed some old bugs in qmail-local
+
+ fixed already some bugs in new qmail-local code ;-)
+
+ added a log facility to qmail-lspawn.
+
+ added some experimental -extension support in qmail-lspawn.
+
+ Added a headerfile qmail-ldap.h where all parameters are set.
+ This includes some changes in qmail-local.c qmail-lspawn.c and checkpassword.c
+
+ qmail-lspawn checks no longer for "correct" mailaddresses, now the possible
+ mailaddress is escaped ('(', ')', '*') before added to the search filter.
+
+ all the stuff that was fixed in the subpatches. (XXX double check that)
+ 
+ Added some compile options in the Makefile for easier configuration (see 5.)
+
+ Added Christopher K. Davis' patch to handle oversized dns packets.
+
+ Added Chris Johnson's <cjohnson-qmail@palomine.net> tarpitting patch.
+
+ Added qmail-quotawarn and qmail-reply for better handling of quota-warnings
+ and auto reply
+
+ deliveryMode is now a comma separated list see LDAP PARAMETER FIELDS
+
+ Fixed a few things in qmail-local
+
+ Supports OpenLDAP now
+
+ WARNING: {SHA1} changed to {SHA} according to the standard
+
+ Integrated Lindsay Haisley update to Rask Lambertsen's excellent
+ antispam patch for qmail v1.01, based on Lionel Widdifield's patch.
+ Please read ANTISPAM for more information.
+
+ checkpassword now supports the password format used by Netscape
+ Mailserver pre-3.0 and Software.com's Post.Office (NS-MTA-MD5).
+ That string is hex encoded, the first 32 Octets are the MD5 hashed
+ password and the second 32 Octets are the salt to the MD5 function.
+
+ Added automatic homedir and maildir maker to qmail-local.
+ This can be enabled with ~control/dirmaker
+
+ qmail-smtpd does logging now. This can be set by an environment variable
+ in tcpserver: LOGLEVEL="X". "0" or not present = no logging, "1" = fatal
+ errors, "2" = connection setup and warnings, "3" = verbose.
+
+ Added fix for qmail-pop3d stat command bug found by Aaron Nabil
+ <nabil@spiritone.com>.
+
+ checkpassword compiled with QLDAPDEBUG now does complete LDAP debugging.
+  Usage: ./checkpassword POPLogin POPPassword
+
+ digest computes MD4, MD5, RMD160 and SHA passwords (compatible to Netscape)
+  Usage: ./digest POPPassword
+
+ solved a problem on big endian machines that caused wrong SHA, MD5, MD4, 
+ RMD160 passwords. (Added an endian testprogram to solve those probs)
+ 
+ added a working version of the "MAKE_NETSCAPE_WORK" patch under qmail-pop3d.
+ The download bar should now work correctly.
+ 
+ Fixed the bugs in qmail-lspawn. Changed stralloc_catb to stralloc_cat. 
+ Thanks to Franky Van Liedekerke <franky.van.liedekerke@telenet.be>
+ 
+
diff -ruN qmail-1.03-orig/QLDAPPICTURE qmail-1.03-ldap-20060201-orig/QLDAPPICTURE
--- qmail-1.03-orig/QLDAPPICTURE	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/QLDAPPICTURE	2006-02-25 11:00:55.000000000 +0100
@@ -0,0 +1,29 @@
+ 1. qmail-smtpd accepts connection
+
+    Is relayclient set?
+      Yes -> accept it anyway.
+      No  -> check if recipient domain is listed in rcpthosts else
+             deny
+
+    Does sender's domain have a valid MX or A record?
+      Yes -> accept for data
+      No  -> deny
+
+    Now the message gets queued.
+
+ 2. qmail-send takes a look at it
+
+    Is the recipients domain in virtualhosts or locals (doesn't matter
+    with qmail-ldap)?
+      Yes -> feed it to qmail-lspawn for local delivery
+      No  -> feed it to qmail-rspawn for remote delivery (relaying as
+             usual)
+
+ 3. qmail-lspawn gets it for local delivery
+
+    Is the recipients full email address found in the LDAP directory?
+      Yes -> check if all needed attributes are present
+               Yes -> deliver it to the maildir
+               No  -> bounce
+      No  -> try a standard qmail (UNIX user or ~users/assign) delivery
+
diff -ruN qmail-1.03-orig/qldap-profile.c qmail-1.03-ldap-20060201-orig/qldap-profile.c
--- qmail-1.03-orig/qldap-profile.c	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/qldap-profile.c	2006-02-25 11:00:55.000000000 +0100
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2000-2004 Claudio Jeker,
+ *      Internet Business Solutions AG, CH-8005 Zürich, Switzerland
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Internet Business
+ *      Solutions AG and its contributors.
+ * 4. Neither the name of the author nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#include "taia.h"
+#include "qldap-profile.h"
+#include "qldap-debug.h"
+
+struct profile_t {
+	struct taia start;
+	char *function;
+};
+	
+static struct profile_t profile_list[PROFILES_MAX];
+
+void start_timing(unsigned int profile, char *function)
+{
+	if (profile >= PROFILES_MAX) {
+		debug(0x400, "Max Number of profiles exceeded\n");
+		return;
+	}
+	
+	taia_now(&(profile_list[profile].start));
+
+}
+
+void stop_timing(unsigned int profile) 
+{
+	struct taia stop;
+	struct taia diff;
+	char nano[TAIA_FMTFRAC];
+	unsigned long sec;
+	
+	if (profile >= PROFILES_MAX) {
+		debug(0x400, "Max Number of profiles exceeded\n");
+		return;
+	}
+
+	taia_now(&stop);
+
+	taia_sub(&diff, &stop, &profile_list[profile].start);
+	nano[taia_fmtfrac(nano, &diff)] = 0; /* terminate to be sure */
+	nano[7] = 0; /* only the first 6-7 figures are != 0, (nano seconds) */
+	sec=(unsigned long) ((unsigned long long) diff.sec.x);
+	debug(0x400, "%s took %u.%s Sec\n", profile_list[profile].function, sec, nano);
+
+}
+
diff -ruN qmail-1.03-orig/qldap-profile.h qmail-1.03-ldap-20060201-orig/qldap-profile.h
--- qmail-1.03-orig/qldap-profile.h	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/qldap-profile.h	2006-02-25 11:00:55.000000000 +0100
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2000-2004 Claudio Jeker,
+ *      Internet Business Solutions AG, CH-8005 Zürich, Switzerland
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Internet Business
+ *      Solutions AG and its contributors.
+ * 4. Neither the name of the author nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#ifndef __QLDAP_PROFILE_H__
+#define __QLDAP_PROFILE_H__
+
+#define PROFILES_MAX 4 /* 4 concurrent profiles */
+
+void start_timing(int profile, char *function);
+/* start the timing of a function */
+
+void stop_timing(int profile);
+/* stop the timing of a function and print the difference */
+
+#endif
diff -ruN qmail-1.03-orig/QLDAPTODO qmail-1.03-ldap-20060201-orig/QLDAPTODO
--- qmail-1.03-orig/QLDAPTODO	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/QLDAPTODO	2006-02-25 11:00:55.000000000 +0100
@@ -0,0 +1,45 @@
+QMAIL-LDAP by Andre Oppermann <opi@nrg4u.com>,
+Claudio Jeker <jeker@n-r-g.com> and Boris Lutz <lutz@n-r-g.com>
+(c) 2000-2004 Internet Business Solutions AG
+
+RELEASE: $Date: 2004/08/03 20:27:44 $ ($Revision: 1.36 $)
+
+This is the TODO FILE, so the QLDAPINSTALL file gets a bit cleaner.
+This file is NOT structured!!
+
+NEWS:
+
+ see QLDAPNEWS
+
+TODO:
+
+ongoing - Debugging and testing, testing, testing
+done    - The big qmail-ldap picture
+ongoing - full code review by a third person
+planned - make it possible to have locals and rcpthosts in ldap
+          and perhaps also the rules for the tcpserver (certs?)
+          some people refer to this as ldap-control
+
+PS: planned means we see the use of the idea but there are a lot more
+    important things that need to be done first.
+
+ALSO ON THE LIST: (priority list)
+- update qmail-ldaplookup (mainly ldap login, passwd check and group handling)
+- cleanup the debug code, unify the debug levels
+- cleanup failures (hard vs. temporary)
+- use pbstools for enhanced tarpit idea
+- make full example for qmailaccountpurge.sh
+- docu cleanup
+- address rewriting (envelope only)
+
+older stuff still on the list:
+- add more and clearer documentation.
+- benchmarking the code
+- better TLS support (better written??) (tls for pop???)
+- 64bit counters for quota handling code.
+
+status unclear:
+- force to alias if only mail and mailforwardingaddress is set (no uid). (done)
+- test what happens if only uid and mail is defiend in ldap or similar uncommon
+  cases (seems to be no problem, or?)
+
diff -ruN qmail-1.03-orig/qlx.h qmail-1.03-ldap-20060201-orig/qlx.h
--- qmail-1.03-orig/qlx.h	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/qlx.h	2006-02-25 11:00:55.000000000 +0100
@@ -15,4 +15,28 @@
 #define QLX_EXECPW 121
 #define QLX_EXECHARD 126
 
+/* qmail-ldap specific exit codes */
+
+/* ldap specific errors */
+#define QLX_MAXSIZE 150
+#define QLX_LDAPFAIL 152	/* generic fail of ldap functions */
+#define QLX_LDAPAUTH 153	/* LDAP_BIND_AUTH */
+#define QLX_SEARCHTIMEOUT 154	/* TIMEOUT */
+#define QLX_BINDTIMEOUT 155	/* LDAP_BIND_UNREACH */
+#define QLX_TOOMANY 156
+#define QLX_NEEDED 157
+#define QLX_ILLVAL 158
+#define QLX_DISABLED 159
+#define QLX_DELETED 160
+
+/* cluster errors */
+#define QLX_CLUSTERSOFT 162
+#define QLX_CLUSTERHARD 163
+#define QLX_CLUSTERCRASHED 164
+#define QLX_CLUSTERLOOP 165
+/* dirmaker errors */
+#define QLX_DIRMAKESOFT 167
+#define QLX_DIRMAKEHARD 168
+#define QLX_DIRMAKECRASH 169
+
 #endif
diff -ruN qmail-1.03-orig/qmailAccountPurge.sh qmail-1.03-ldap-20060201-orig/qmailAccountPurge.sh
--- qmail-1.03-orig/qmailAccountPurge.sh	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/qmailAccountPurge.sh	2006-02-25 11:00:56.000000000 +0100
@@ -0,0 +1,22 @@
+#!/bin/sh
+
+case "$1" in
+
+show)
+
+        /usr/local/bin/ldapsearch \
+        -u -F "=" \
+        -h "`cat /var/qmail/control/ldapserver`" \
+        -b "`cat /var/qmail/control/ldapbasedn`" \
+        -S "mail" \
+        "(&(accountStatus=deleted)(qmailAccountPurge=<`/var/qmail/bin/gettimeofday`))" \
+        mail mailAlternateAddress uid mailMessageStore mailHost
+
+        ;;
+
+purge)
+
+	;;
+
+esac
+
diff -ruN qmail-1.03-orig/qmail.c qmail-1.03-ldap-20060201-orig/qmail.c
--- qmail-1.03-orig/qmail.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/qmail.c	2006-02-25 11:00:55.000000000 +0100
@@ -1,3 +1,4 @@
+#include <unistd.h>
 #include "substdio.h"
 #include "readwrite.h"
 #include "wait.h"
@@ -7,7 +8,24 @@
 #include "qmail.h"
 #include "auto_qmail.h"
 
+#ifdef ALTQUEUE
+#include "env.h"
+
+static char *binqqargs[2] = { 0, 0 } ;
+
+static void
+setup_qqargs(void)
+{
+  if(!binqqargs[0])
+    binqqargs[0] = (char *)env_get("QMAILQUEUE");
+  if(!binqqargs[0])
+    binqqargs[0] = (char *)"bin/qmail-queue";
+}
+
+#else
 static char *binqqargs[2] = { "bin/qmail-queue", 0 } ;
+#endif
+
 
 int qmail_open(qq)
 struct qmail *qq;
@@ -15,6 +33,10 @@
   int pim[2];
   int pie[2];
 
+#ifdef ALTQUEUE
+  setup_qqargs();
+#endif
+
   if (pipe(pim) == -1) return -1;
   if (pipe(pie) == -1) { close(pim[0]); close(pim[1]); return -1; }
  
@@ -35,7 +57,44 @@
 
   qq->fdm = pim[1]; close(pim[0]);
   qq->fde = pie[1]; close(pie[0]);
-  substdio_fdbuf(&qq->ss,write,qq->fdm,qq->buf,sizeof(qq->buf));
+  substdio_fdbuf(&qq->ss,subwrite,qq->fdm,qq->buf,sizeof(qq->buf));
+  qq->flagerr = 0;
+  return 0;
+}
+
+int qmail_remote(qq, host)
+struct qmail *qq;
+char *host;
+{
+  int pim[2];
+  int pie[2];
+  char *(args[3]);
+
+  args[0] = (char *)"bin/qmail-qmqpc";
+  args[1] = host;
+  args[2] = 0;
+
+  if (pipe(pim) == -1) return -1;
+  if (pipe(pie) == -1) { close(pim[0]); close(pim[1]); return -1; }
+ 
+  switch(qq->pid = vfork()) {
+    case -1:
+      close(pim[0]); close(pim[1]);
+      close(pie[0]); close(pie[1]);
+      return -1;
+    case 0:
+      close(pim[1]);
+      close(pie[1]);
+      if (fd_move(0,pim[0]) == -1) _exit(120);
+      if (fd_move(1,pie[0]) == -1) _exit(120);
+      if (chdir(auto_qmail) == -1) _exit(61);
+      execv(*args,args);
+      _exit(120);
+  }
+
+  qq->fdm = pim[1]; close(pim[0]);
+  qq->fde = pie[1]; close(pie[0]);
+  substdio_fdbuf(&qq->ss,subwrite,qq->fdm,qq->buf,sizeof(qq->buf));
   qq->flagerr = 0;
   return 0;
 }
@@ -50,34 +109,34 @@
   qq->flagerr = 1;
 }
 
-void qmail_put(qq,s,len) struct qmail *qq; char *s; int len;
+void qmail_put(qq,s,len) struct qmail *qq; const char *s; int len;
 {
   if (!qq->flagerr) if (substdio_put(&qq->ss,s,len) == -1) qq->flagerr = 1;
 }
 
-void qmail_puts(qq,s) struct qmail *qq; char *s;
+void qmail_puts(qq,s) struct qmail *qq; const char *s;
 {
   if (!qq->flagerr) if (substdio_puts(&qq->ss,s) == -1) qq->flagerr = 1;
 }
 
-void qmail_from(qq,s) struct qmail *qq; char *s;
+void qmail_from(qq,s) struct qmail *qq; const char *s;
 {
   if (substdio_flush(&qq->ss) == -1) qq->flagerr = 1;
   close(qq->fdm);
-  substdio_fdbuf(&qq->ss,write,qq->fde,qq->buf,sizeof(qq->buf));
+  substdio_fdbuf(&qq->ss,subwrite,qq->fde,qq->buf,sizeof(qq->buf));
   qmail_put(qq,"F",1);
   qmail_puts(qq,s);
   qmail_put(qq,"",1);
 }
 
-void qmail_to(qq,s) struct qmail *qq; char *s;
+void qmail_to(qq,s) struct qmail *qq; const char *s;
 {
   qmail_put(qq,"T",1);
   qmail_puts(qq,s);
   qmail_put(qq,"",1);
 }
 
-char *qmail_close(qq)
+const char *qmail_close(qq)
 struct qmail *qq;
 {
   int wstat;
@@ -87,7 +146,7 @@
   if (!qq->flagerr) if (substdio_flush(&qq->ss) == -1) qq->flagerr = 1;
   close(qq->fde);
 
-  if (wait_pid(&wstat,qq->pid) != qq->pid)
+  if ((unsigned long)wait_pid(&wstat,qq->pid) != qq->pid)
     return "Zqq waitpid surprise (#4.3.0)";
   if (wait_crashed(wstat))
     return "Zqq crashed (#4.3.0)";
diff -ruN qmail-1.03-orig/qmail-cdb.c qmail-1.03-ldap-20060201-orig/qmail-cdb.c
--- qmail-1.03-orig/qmail-cdb.c	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/qmail-cdb.c	2006-02-25 11:00:55.000000000 +0100
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2003-2004 Claudio Jeker,
+ *      Internet Business Solutions AG, CH-8005 Zürich, Switzerland
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Internet Business
+ *      Solutions AG and its contributors.
+ * 4. Neither the name of the author nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+/*
+ * Based on similar code by D. J. Bernstein
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <unistd.h>
+#include "auto_qmail.h"
+#include "case.h"
+#include "cdb_make.h"
+#include "exit.h"
+#include "getln.h"
+#include "open.h"
+#include "readwrite.h"
+#include "stralloc.h"
+#include "strerr.h"
+#include "substdio.h"
+
+#define FATAL "qmail-cdb: fatal: "
+
+void die_read(void)
+{
+  strerr_die2sys(111,FATAL,"unable to read from stdin: ");
+}
+void die_write(const char *f)
+{
+  strerr_die4sys(111,FATAL,"unable to write to ", f, ": ");
+}
+
+char inbuf[1024];
+substdio ssin;
+
+int fd;
+int fdtemp;
+
+struct cdb_make cdbm;
+stralloc line = {0};
+int match;
+
+int main(int argc, char **argv)
+{
+  umask(033);
+
+  if (argc != 3)
+    strerr_die1sys(111,"qmail-cdb: usage: qmail-cdb rules.cdb rules.tmp");
+
+  substdio_fdbuf(&ssin,subread,0,inbuf,sizeof inbuf);
+
+  fdtemp = open_trunc(argv[2]);
+  if (fdtemp == -1) die_write(argv[2]);
+
+  if (cdb_make_start(&cdbm,fdtemp) == -1) die_write(argv[2]);
+
+  for (;;) {
+    if (getln(&ssin,&line,&match,'\n') != 0) die_read();
+    case_lowerb(line.s,line.len);
+    while (line.len) {
+      if (line.s[line.len - 1] == ' ') { --line.len; continue; }
+      if (line.s[line.len - 1] == '\n') { --line.len; continue; }
+      if (line.s[line.len - 1] == '\t') { --line.len; continue; }
+      if (line.s[0] != '#')
+	if (cdb_make_add(&cdbm,line.s,line.len,"",0) == -1)
+	  die_write(argv[2]);
+      break;
+    }
+    if (!match) break;
+  }
+
+  if (cdb_make_finish(&cdbm) == -1) die_write(argv[2]);
+  if (fsync(fdtemp) == -1) die_write(argv[2]);
+  if (close(fdtemp) == -1) die_write(argv[2]); /* NFS stupidity */
+  if (rename(argv[2],argv[1]) == -1)
+    strerr_die5sys(111, FATAL, "unable to move ", argv[2], " to ", argv[1]);
+
+  return 0;
+}
diff -ruN qmail-1.03-orig/qmail-clean.c qmail-1.03-ldap-20060201-orig/qmail-clean.c
--- qmail-1.03-orig/qmail-clean.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/qmail-clean.c	2006-02-25 11:00:55.000000000 +0100
@@ -1,5 +1,6 @@
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <unistd.h>
 #include "readwrite.h"
 #include "sig.h"
 #include "now.h"
@@ -26,12 +27,12 @@
  DIR *dir;
  direntry *d;
  struct stat st;
- datetime_sec time;
+ datetime_sec tnow;
 
- time = now();
+ tnow = now();
  dir = opendir("pid");
  if (!dir) return;
- while (d = readdir(dir))
+ while ((d = readdir(dir)))
   {
    if (str_equal(d->d_name,".")) continue;
    if (str_equal(d->d_name,"..")) continue;
@@ -39,7 +40,7 @@
    if (!stralloc_cats(&line,d->d_name)) continue;
    if (!stralloc_0(&line)) continue;
    if (stat(line.s,&st) == -1) continue;
-   if (time < st.st_atime + OSSIFIED) continue;
+   if (tnow < st.st_atime + OSSIFIED) continue;
    unlink(line.s);
   }
  closedir(dir);
@@ -49,9 +50,9 @@
 
 void respond(s) char *s; { if (substdio_putflush(subfdoutsmall,s,1) == -1) _exit(100); }
 
-void main()
+int main()
 {
- int i;
+ unsigned int i;
  int match;
  int cleanuploop;
  unsigned long id;
@@ -73,26 +74,47 @@
    if (line.len < 7) { respond("x"); continue; }
    if (line.len > 100) { respond("x"); continue; }
    if (line.s[line.len - 1]) { respond("x"); continue; } /* impossible */
+#ifndef BIGTODO
    for (i = 5;i < line.len - 1;++i)
+#else
+   for (i = line.len - 2;i > 4;--i)
+    {
+      if (line.s[i] == '/') break;
+#endif
      if ((unsigned char) (line.s[i] - '0') > 9)
       { respond("x"); continue; }
+#ifndef BIGTODO
    if (!scan_ulong(line.s + 5,&id)) { respond("x"); continue; }
+#else
+    }
+   if (line.s[i] == '/')
+     if (!scan_ulong(line.s + i + 1,&id)) { respond("x"); continue; }
+#endif
    if (byte_equal(line.s,5,"foop/"))
     {
 #define U(prefix,flag) fmtqfn(fnbuf,prefix,id,flag); \
 if (unlink(fnbuf) == -1) if (errno != error_noent) { respond("!"); continue; }
+#ifndef BIGTODO
      U("intd/",0)
+#else
+     U("intd/",1)
+#endif
      U("mess/",1)
      respond("+");
     }
-   else if (byte_equal(line.s,4,"todo/"))
+   else if (byte_equal(line.s,5,"todo/"))
     {
+#ifndef BIGTODO
      U("intd/",0)
      U("todo/",0)
+#else
+     U("intd/",1)
+     U("todo/",1)
+#endif
      respond("+");
     }
    else
      respond("x");
   }
- _exit(0);
+ return 0;
 }
diff -ruN qmail-1.03-orig/qmail-forward.c qmail-1.03-ldap-20060201-orig/qmail-forward.c
--- qmail-1.03-orig/qmail-forward.c	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/qmail-forward.c	2006-02-25 11:00:55.000000000 +0100
@@ -0,0 +1,179 @@
+/*
+ * Copyright (c) 2003-2004 Claudio Jeker,
+ *      Internet Business Solutions AG, CH-8005 Zürich, Switzerland
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Internet Business
+ *      Solutions AG and its contributors.
+ * 4. Neither the name of the author nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#include <unistd.h>
+#include "auto_qmail.h"
+#include "control.h"
+#include "error.h"
+#include "fmt.h"
+#include "getln.h"
+#include "now.h"
+#include "qmail.h"
+#include "readwrite.h"
+#include "seek.h"
+#include "str.h"
+#include "stralloc.h"
+#include "strerr.h"
+#include "substdio.h"
+
+
+#define FATAL "qmail-forward: fatal: "
+
+void
+usage(void)
+{
+	strerr_die1x(100,
+	    "qmail-forward: usage: qmail-forward host sender recipient");
+}
+
+void
+temp_nomem(void)
+{
+	strerr_die2x(111, FATAL, "Out of memory. (#4.3.0)");
+}
+void
+temp_rewind(void)
+{
+	strerr_die2x(111, FATAL, "Unable to rewind message. (#4.3.0)");
+}
+void
+temp_read(void)
+{
+	strerr_die3x(111, "Unable to read message: ",
+	    error_str(errno), ". (#4.3.0)");
+}
+void
+temp_fork(void)
+{
+	strerr_die3x(111, "Unable to fork: ", error_str(errno), ". (#4.3.0)");
+}
+
+
+
+char buf[4096];
+
+stralloc me = {0};
+stralloc dtline = {0};
+stralloc messline = {0};
+
+void bouncexf(void)
+{
+	substdio ss;
+	int match;
+
+	if (seek_begin(0) == -1) temp_rewind();
+	substdio_fdbuf(&ss, subread, 0, buf, sizeof(buf));
+	for (;;)
+	{
+		if (getln(&ss, &messline, &match, '\n') != 0) temp_read();
+		if (!match) break;
+		if (messline.len <= 1)
+			break;
+		if (messline.len == dtline.len)
+			if (!str_diffn(messline.s, dtline.s, dtline.len))
+				strerr_die2x(100, FATAL, 
+				    "This message is looping: "
+				    "it already has my Cluster-Delivered-To "
+				    "line. (#5.4.6)\n");
+	}
+}
+
+char strnum1[FMT_ULONG];
+char strnum2[FMT_ULONG];
+
+int
+main (int argc, char **argv)
+{
+	struct qmail qqt;
+	substdio ss;
+	char *remote, *to, *from;
+	const char *qqx;
+	unsigned long qp;
+	datetime_sec when;
+	int match;
+	unsigned int i;
+	
+	if (!(remote = argv[1])) usage();
+	if (!(from = argv[2])) usage();
+	if (!(to = argv[3])) usage();
+	if (argv[4]) usage();
+	
+	if (chdir(auto_qmail) == -1)
+		strerr_die4sys(111, FATAL, "Unable to switch to ",
+		    auto_qmail, ": ");
+	if (control_init() == -1)
+		strerr_die2sys(111, FATAL, "Unable to read controls: ");
+	if (control_readline(&me, "control/me") != 1)
+		strerr_die2sys(111, FATAL, "Unable to read control/me: ");
+
+	
+	if (!stralloc_copys(&dtline, "Delivered-To: CLUSTERHOST "))
+		temp_nomem();
+	if (!stralloc_cat(&dtline, &me)) temp_nomem();
+	if (!stralloc_cats(&dtline, " ")) temp_nomem();
+	if (!stralloc_cats(&dtline, to)) temp_nomem();
+	for (i = 0; i < dtline.len; ++i)
+		if (dtline.s[i] == '\n')
+			dtline.s[i] = '_';
+	if (!stralloc_cats(&dtline, "\n")) temp_nomem();
+
+	bouncexf();
+	
+	if (seek_begin(0) == -1) temp_rewind();
+	substdio_fdbuf(&ss, subread, 0, buf, sizeof(buf));
+
+	if (qmail_remote(&qqt, remote) == -1) temp_fork();
+	qp = qmail_qp(&qqt);
+
+	qmail_put(&qqt, dtline.s, dtline.len);
+	do {
+		if (getln(&ss, &messline, &match, '\n') != 0) {
+			qmail_fail(&qqt);
+			break;
+		}
+		qmail_put(&qqt, messline.s, messline.len);
+	} while (match);
+	qmail_from(&qqt, from);
+	qmail_to(&qqt, to);
+	qqx = qmail_close(&qqt);
+	if (*qqx) 
+		strerr_die3x(*qqx == 'D' ? 100 : 111,
+		    "Unable to cluster-forward message: ", qqx + 1, ".");
+	when = now();
+	strnum1[fmt_ulong(strnum1, (unsigned long) when)] = 0;
+	strnum2[fmt_ulong(strnum2, qp)] = 0;
+	strerr_die5x(0, "qmail-forward: ok ", strnum1, " qp ", strnum2, ".");
+	/* NOTREACHED */
+	return 0;
+}
+
diff -ruN qmail-1.03-orig/qmail-getpw.c qmail-1.03-ldap-20060201-orig/qmail-getpw.c
--- qmail-1.03-orig/qmail-getpw.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/qmail-getpw.c	2006-02-25 11:00:55.000000000 +0100
@@ -18,7 +18,7 @@
 
 char *local;
 struct passwd *pw;
-char *dash;
+const char *dash;
 char *extension;
 
 int userext()
@@ -28,7 +28,7 @@
 
   extension = local + str_len(local);
   for (;;) {
-    if (extension - local < sizeof(username))
+    if ((unsigned long)(extension - local) < sizeof(username))
       if (!*extension || (*extension == *auto_break)) {
 	byte_copy(username,extension - local,local);
 	username[extension - local] = 0;
@@ -37,7 +37,7 @@
 	pw = getpwnam(username);
 	if (errno == error_txtbsy) _exit(QLX_SYS);
 	if (pw)
-	  if (pw->pw_uid)
+	  if (pw->pw_uid) {
 	    if (stat(pw->pw_dir,&st) == 0) {
 	      if (st.st_uid == pw->pw_uid) {
 		dash = "";
@@ -47,6 +47,7 @@
 	    }
 	    else
 	      if (error_temp(errno)) _exit(QLX_NFS);
+	  }
       }
     if (extension == local) return 0;
     --extension;
@@ -55,7 +56,7 @@
 
 char num[FMT_ULONG];
 
-void main(argc,argv)
+int main(argc,argv)
 int argc;
 char **argv;
 {
@@ -84,5 +85,5 @@
   substdio_put(subfdoutsmall,"",1);
   substdio_flush(subfdoutsmall);
 
-  _exit(0);
+  return 0;
 }
diff -ruN qmail-1.03-orig/qmail-group.c qmail-1.03-ldap-20060201-orig/qmail-group.c
--- qmail-1.03-orig/qmail-group.c	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/qmail-group.c	2006-02-25 11:00:55.000000000 +0100
@@ -0,0 +1,1008 @@
+/*
+ * Copyright (c) 2003-2004 Claudio Jeker,
+ *      Internet Business Solutions AG, CH-8005 Zürich, Switzerland
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Internet Business
+ *      Solutions AG and its contributors.
+ * 4. Neither the name of the author nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#include <unistd.h>
+
+#include "alloc.h"
+#include "auto_break.h"
+#include "byte.h"
+#include "case.h"
+#include "coe.h"
+#include "control.h"
+#include "env.h"
+#include "error.h"
+#include "fd.h"
+#include "fmt.h"
+#include "getln.h"
+#include "ndelay.h"
+#include "now.h"
+#include "open.h"
+#include "qldap.h"
+#include "qldap-errno.h"
+#include "qmail.h"
+#include "qmail-ldap.h"
+#include "read-ctrl.h"
+#include "readwrite.h"
+#include "seek.h"
+#include "sig.h"
+#include "str.h"
+#include "stralloc.h"
+#include "strerr.h"
+#include "substdio.h"
+#include "wait.h"
+
+#define FATAL "qmail-group: fatal: "
+
+void
+temp_nomem(void)
+{
+	strerr_die2x(111, FATAL, "Out of memory. (#4.3.0)");
+}
+void
+temp_qmail(char *fn)
+{
+	strerr_die4sys(111, FATAL, "Unable to open ", fn, ": ");
+}
+void
+temp_rewind(void)
+{
+	strerr_die2x(111, FATAL, "Unable to rewind message. (#4.3.0)");
+}
+void
+temp_read(void)
+{
+	strerr_die2x(111, FATAL, "Unable to read message. (#4.3.0)");
+}
+void
+temp_fork(void)
+{
+	strerr_die2sys(111, FATAL, "Unable to fork: ");
+}
+void usage(void)
+{
+	strerr_die1x(100, "qmail-group: usage: qmail-group Maildir");
+}
+
+void init(void);
+void bouncefx(void);
+void reset_sender(void);
+void blast(stralloc *, int);
+void reopen(void);
+void trydelete(void);
+void secretary(char *, int);
+void explode(qldap *);
+void subscribed(qldap *, int);
+qldap *ldapgroup(char *, int *, int *, int *);
+
+char *local;
+char *host;
+char *sender;
+stralloc base = {0};
+stralloc action = {0};
+char *ext;
+char *dname;
+
+stralloc recips = {0};
+stralloc bounceadmin = {0};
+stralloc moderators = {0};
+unsigned int nummoderators;
+
+
+int
+main(int argc, char **argv)
+{
+	qldap *qlc;
+	char *maildir;
+	int flagm, flagc, flags, flagS;
+	
+	if (argv[1] == 0) usage();
+	if (argv[2] != 0) usage();
+	maildir = argv[1];
+	
+	init();
+	/* filter out loops as soon as poosible */
+	bouncefx();
+	
+	flagc = flags = flagS = flagm = 0;
+	qlc = ldapgroup(dname, &flagc, &flags, &flagS);
+
+	/* need to distinguish between new messages and responses */
+	if (action.s) {
+		if (!case_diffs(action.s, "confirm") ||
+		    !case_diffs(action.s, "approve") ||
+		    !case_diffs(action.s, "reject"))
+			secretary(maildir, flagc);
+		else if (moderators.s && moderators.len &&
+		    !case_diffs(action.s, "moderators") && !(ext && *ext)) {
+			/* mail to moderators */
+			blast(&moderators, 0);
+		} else if (!case_diffs(action.s, "return")) {
+			/* bounce form subscribed user */
+			blast(&bounceadmin, 0);
+		} else if (!case_diffs(action.s, "bounce") && ext && *ext) {
+			/* bounce from moderator */
+			if (bounceadmin.s && bounceadmin.len)
+				blast(&bounceadmin, 0);
+			secretary(maildir, flagc);
+		} else
+			/* bad address */
+			strerr_die2x(100, FATAL, "Sorry, no mailbox here "
+			    "by that name. (#5.1.1)");
+	} else {
+		if (flags)
+			subscribed(qlc, flagS);
+		if (flagc || nummoderators)
+			secretary(maildir, flagc);
+	}
+
+	reopen();
+	explode(qlc);
+	qldap_free(qlc);
+	
+	/* does not return */
+	blast(&recips, 1);
+	return 111;
+}
+
+stralloc grouplogin = {0};
+stralloc grouppassword = {0};
+
+int
+init_controls(void)
+{
+	switch (control_readline(&grouplogin, "control/ldapgrouplogin")) {
+	case 0:
+		return 0;
+	case 1:
+		break;
+	default:
+		return -1;
+	}
+	if (!stralloc_0(&grouplogin)) return -1;
+
+	if (control_rldef(&grouppassword, "control/ldapgrouppassword",
+		    0, "") == -1)
+		return -1;
+	if (!stralloc_0(&grouppassword)) return -1;
+
+	return 0;
+}
+
+ctrlfunc ctrls[] = {
+	qldap_ctrl_trylogin,
+	qldap_ctrl_generic,
+	init_controls,
+	0
+};
+
+stralloc dtline = {0};
+
+void
+init(void)
+{
+	char *t;
+	unsigned int i;
+
+	/* read some control files */
+	if (read_controls(ctrls) == -1)
+		strerr_die2x(100, FATAL, "unable to read controls");
+
+	sender = env_get("SENDER");
+	if (!sender) strerr_die2x(100, FATAL, "SENDER not set");
+	local = env_get("LOCAL");
+	if (!local) strerr_die2x(100, FATAL, "LOCAL not set");
+	host = env_get("HOST");
+	if (!host) strerr_die2x(100, FATAL, "HOST not set");
+	dname = env_get(ENV_GROUP);
+	if (!dname) strerr_die2x(100, FATAL, "QLDAPGROUP not set");
+
+	
+	t = env_get("EXT");
+	if (t != 0 && *t != '\0') {
+		if (!stralloc_copyb(&base, local,
+			    str_len(local) - str_len(t) - 1))
+			temp_nomem();
+		ext = t;
+		ext += str_chr(ext, '-');
+		if (!stralloc_copyb(&action, t, ext - t)) temp_nomem();
+		if (!stralloc_0(&action)) temp_nomem();
+		if (*ext) ++ext;
+	} else {
+		if (!stralloc_copys(&base, local)) temp_nomem();
+		ext = 0;
+	}
+	if (!stralloc_copys(&dtline, "Delivered-To: ")) temp_nomem();
+	if (!stralloc_cat(&dtline, &base)) temp_nomem();
+	if (!stralloc_cats(&dtline, "@")) temp_nomem();
+	if (!stralloc_cats(&dtline, host)) temp_nomem();
+	for (i = 0; i < dtline.len; ++i)
+		if (dtline.s[i] == '\n')
+			dtline.s[i] = '_';
+	if (!stralloc_cats(&dtline,"\n")) temp_nomem();
+}
+
+char buf[4096];
+stralloc line = {0};
+
+void
+bouncefx(void)
+{
+	substdio	ss;
+	int		match;
+	
+	if (seek_begin(0) == -1) temp_rewind();
+	substdio_fdbuf(&ss, subread, 0, buf, sizeof(buf));
+	for (;;) {
+		if (getln(&ss, &line, &match, '\n') != 0) temp_read();
+		if (!match) break;
+		if (line.len <= 1) break;
+		if (line.len == dtline.len)
+			if (byte_equal(line.s, line.len, dtline.s))
+				strerr_die2x(100, FATAL,
+				    "this message is looping: "
+				    "it already has my Delivered-To line. "
+				    "(#5.4.6)");
+	}
+}
+
+void
+reset_sender(void)
+{
+	substdio	 ss;
+	char		*s;
+	int		 match;
+	unsigned int	 i;
+
+	if (seek_begin(0) == -1) temp_rewind();
+	substdio_fdbuf(&ss, subread, 0, buf, sizeof(buf));
+	for (;;) {
+		if (getln(&ss, &line, &match, '\n') != 0) temp_read();
+		if (!match) break;
+		if (line.len <= 1) break;
+		if (case_startb(line.s, line.len, "Return-Path:")) {
+			i = byte_chr(line.s, line.len, '<');
+			if (i >= line.len)
+				continue;
+			s = line.s + i + 1;
+			i = byte_rchr(line.s, line.len, '>');
+			if (i >= line.len)
+				continue;
+			line.s[i] = '\0';
+			if (!env_put2("SENDER",s)) temp_nomem();
+			break;
+		}
+	}
+	/* reget sender as it was possibly overwritten */
+	sender = env_get("SENDER");
+	if (!sender) strerr_die2x(100, FATAL, "SENDER not set");
+}
+
+
+char strnum1[FMT_ULONG];
+char strnum2[FMT_ULONG];
+
+void
+blast(stralloc *r, int flagb)
+{
+	struct qmail qqt;
+	substdio ss;
+	char *s, *smax;
+	const char *qqx;
+	unsigned long qp;
+	datetime_sec when;
+	int match;
+
+	if (r->s == (char *)0 || r->len == 0)
+		strerr_die2x(100, FATAL, "no recipients found in this group.");
+
+	if (seek_begin(0) == -1) temp_rewind();
+	substdio_fdbuf(&ss, subread, 0, buf, sizeof(buf));
+
+	if (qmail_open(&qqt) == -1) temp_fork();
+	qp = qmail_qp(&qqt);
+	/* mail header */
+	qmail_put(&qqt, dtline.s, dtline.len);
+	qmail_puts(&qqt,"Precedence: bulk\n");
+	do {
+		if (getln(&ss, &line, &match, '\n') != 0) {
+			qmail_fail(&qqt);
+			break;
+		}
+		qmail_put(&qqt, line.s, line.len);
+	} while (match);
+
+	if (flagb && bounceadmin.s && bounceadmin.len) {
+		if (!stralloc_copy(&line,&base)) temp_nomem();
+		if (!stralloc_cats(&line,"-return-@")) temp_nomem();
+		if (!stralloc_cats(&line,host)) temp_nomem();
+		if (!stralloc_cats(&line,"-@[]")) temp_nomem();
+		if (!stralloc_0(&line)) temp_nomem();
+		qmail_from(&qqt, line.s);
+	} else
+		/* if no bounce admin specified forward with sender address */
+		qmail_from(&qqt, sender);
+
+	for (s = r->s, smax = r->s + r->len; s < smax; s += str_len(s) + 1)
+		qmail_to(&qqt,s);
+	qqx = qmail_close(&qqt);
+	if (*qqx)
+		strerr_die3x(*qqx == 'D' ? 100 : 111,
+		    "Unable to blast message: ", qqx + 1, ".");
+	when = now();
+	strnum1[fmt_ulong(strnum1, (unsigned long) when)] = 0;
+	strnum2[fmt_ulong(strnum2, qp)] = 0;
+	trydelete();
+	strerr_die5x(0, "qmail-group: ok ", strnum1, " qp ", strnum2, ".");
+}
+
+stralloc fname = {0};
+char sbuf[1024];
+
+void
+reopen(void)
+{
+	int fd;
+
+	if (!(fname.s && fname.len > 1))
+		return;
+	if (!stralloc_0(&fname)) temp_nomem();
+	fd = open_read(fname.s);
+	if (fd == -1)
+		strerr_die2sys(111, FATAL, "Unable to reopen old message: ");
+	if (fd_move(0,fd) == -1) 
+		strerr_die2sys(111, FATAL,
+		    "Unable to reopen old message: fd_move: ");
+	reset_sender();
+}
+
+void
+trydelete(void)
+{
+	if (fname.s && fname.len > 1)
+		unlink(fname.s);
+}
+
+void
+secretary(char *maildir, int flagcheck)
+{
+	const char **args;
+	char *s, *smax;
+	int child, wstat;
+	unsigned int i, numargs;
+	int pi[2];
+	int r, j;
+
+	if (!stralloc_copys(&fname, "")) temp_nomem();
+
+	if (seek_begin(0) == -1) temp_rewind();
+
+	numargs = 4 + 2 * nummoderators;
+	
+	args = (const char **) alloc(numargs * sizeof(char *));
+	if (!args) temp_nomem();
+	i = 0;
+	args[i++] = "qmail-secretary";
+	if (flagcheck == 1)
+		args[i++] = "-Zc";
+	else 
+		args[i++] = "-ZC";
+	for (s = moderators.s, smax = moderators.s + moderators.len;
+	    s < smax; s += str_len(s) + 1) {
+		args[i++] = "-m";
+		args[i++] = s;
+		if (i + 2 > numargs)
+		       strerr_die2x(111, FATAL, "internal error.");	
+	}
+	args[i++] = maildir;
+	args[i++] = 0;
+	
+	if (pipe(pi) == -1)
+		strerr_die2sys(111, FATAL,
+		    "Unable to run secretary: pipe: ");
+	
+	coe(pi[0]);
+	switch(child = fork()) {
+	case -1:
+		temp_fork();
+	case 0:
+		if (fd_move(1,pi[1]) == -1) 
+			strerr_die2sys(111, FATAL,
+			    "Unable to run secretary: fd_move: ");
+		sig_pipedefault();
+		execvp(*args, (char **)args);
+		strerr_die3x(111,"Unable to run secretary: ",
+		    error_str(errno), ". (#4.3.0)");
+	}
+	close(pi[1]);
+	alloc_free(args);
+	
+	wait_pid(&wstat,child);
+	if (wait_crashed(wstat))
+		strerr_die2x(111, FATAL, "Aack, child crashed.");
+	switch(wait_exitcode(wstat)) {
+	case 100:
+	case 64: case 65: case 70:
+	case 76: case 77: case 78: case 112:
+		_exit(100);
+	case 0: case 99:
+		/* XXX a for(;;) loop would be great */
+		r = subread(pi[0], sbuf, sizeof(sbuf));
+		if (r == -1) /* read error on a readable pipe, be serious */
+			strerr_die2sys(111, FATAL,
+			    "Unable to read secretary result: ");
+		if (r == 0)
+			/* need to wait for confirmation */
+			_exit(0);
+		for (j = 0; j < r; j++) {
+			if (j == 0) {
+				if (sbuf[j] != 'K')
+					strerr_die2x(111, FATAL,
+					    "Strange secretary dialect");
+				else
+					continue;
+			}
+			if (!stralloc_append(&fname, &sbuf[j])) temp_nomem();
+		}
+		close(pi[0]);
+		return;
+	default: _exit(111);
+	}
+}
+
+/************ LDAP FUNCTIONS AND HELPER FUNCTIONS *************/
+
+stralloc ldapval = {0};
+stralloc tmpval = {0};
+
+static void getmoderators(qldap *);
+static int unescape(char *, stralloc *, unsigned int *);
+static void extract_addrs822(qldap *, const char *, stralloc *, unsigned int *);
+static void extract_addrsdn(qldap *, qldap *, const char *, stralloc *,
+    unsigned int *);
+static void extract_addrsfilter(qldap *, qldap *, const char *, stralloc *,
+    unsigned int *);
+static int getentry(qldap *, char *);
+
+static void
+getmoderators(qldap *q)
+{
+	qldap *sq;
+	int r;
+	
+	nummoderators = 0; sq = (qldap *)0;
+	if (!stralloc_copys(&moderators, "")) { r = ERRNO; goto fail; }
+
+	extract_addrs822(q, LDAP_GROUPMODERAT822,
+	    &moderators, &nummoderators);
+	
+	/* open a second connection and do some dn lookups */
+	sq = qldap_new();
+	if (sq == 0) temp_nomem();
+
+	r = qldap_open(sq);
+	if (r != OK) goto fail;
+	r = qldap_bind(sq, grouplogin.s, grouppassword.s);
+	if (r != OK) goto fail;
+	
+	extract_addrsdn(q, sq, LDAP_GROUPMODERATDN,
+	    &moderators, &nummoderators);
+	
+	qldap_free(sq);
+	return;
+	
+fail:
+	if (sq) qldap_free(sq);
+	qldap_free(q);
+	strerr_die3x(111, FATAL, "expand group: moderators: ",
+	    qldap_err_str(r));
+	/* NOTREACHED */
+}
+
+void
+explode(qldap *q)
+{
+	qldap *sq;
+	int r;
+
+	sq = 0;
+	if (!stralloc_copys(&recips, "")) { r = ERRNO; goto fail; }
+	extract_addrs822(q, LDAP_GROUPMEMBER822, &recips, 0);
+
+	/* open a second connection and do some dn lookups */
+	sq = qldap_new();
+	if (sq == 0) temp_nomem();
+
+	r = qldap_open(sq);
+	if (r != OK) goto fail;
+	r = qldap_bind(sq, grouplogin.s, grouppassword.s);
+	if (r != OK) goto fail;
+
+	extract_addrsdn(q, sq, LDAP_GROUPMEMBERDN, &recips, 0);
+	extract_addrsfilter(q, sq, LDAP_GROUPMEMBERFILTER, &recips, 0);
+	
+	qldap_free(sq);
+	return;
+fail:
+	if (sq) qldap_free(sq);
+	qldap_free(q);
+	strerr_die3x(111, FATAL, "expand group: members: ", qldap_err_str(r));
+	/* NOTREACHED */
+}
+
+stralloc founddn = {0};
+
+void
+subscribed(qldap *q, int flagS)
+{
+	qldap *sq;
+	const char *attrs[] = {
+		LDAP_MAIL,
+		0 };
+	char *s, *smax;
+	int r;
+
+	sq = 0;
+	if (!stralloc_copys(&recips, "")) { r = ERRNO; goto fail; }
+	extract_addrs822(q, flagS ? LDAP_GROUPSENDER822 : LDAP_GROUPMEMBER822,
+	    &recips, 0);
+	
+	for (s = recips.s, smax = recips.s + recips.len; s < smax;
+	    s += str_len(s) + 1)
+		if (!case_diffs(sender, s)) return;
+
+	/* open a second connection and do some dn lookups */
+	sq = qldap_new();
+	if (sq == 0) temp_nomem();
+
+	r = qldap_open(sq);
+	if (r != OK) goto fail;
+	r = qldap_bind(sq, grouplogin.s, grouppassword.s);
+	if (r != OK) goto fail;
+
+	r = getentry(sq, sender);
+	if (r == NOSUCH) {
+		qldap_free(sq);
+		qldap_free(q);
+		strerr_die2x(100, FATAL,
+		    "You are not allowed to post to this list. (#5.7.2)");
+	}
+	if (r != OK) goto fail;
+	
+	r = qldap_get_dn(sq, &founddn);
+	if (r != OK) goto fail;
+	
+	r = qldap_get_attr(q, flagS ? LDAP_GROUPSENDERDN : LDAP_GROUPMEMBERDN,
+	    &ldapval, MULTI_VALUE);
+	switch (r) {
+	case OK:
+		r = unescape(ldapval.s, &tmpval, 0);
+		if (r != OK) goto fail;
+		break;
+	case NOSUCH:
+		break;
+	default:
+		goto fail;
+	}
+
+	for (s = tmpval.s, smax = tmpval.s + tmpval.len;
+	    s < smax; s += str_len(s) + 1)
+		if (!case_diffs(s, founddn.s)) {
+			qldap_free(sq);
+			return;
+		}
+
+	r = qldap_get_attr(q,
+	    flagS ? LDAP_GROUPSENDERFILTER : LDAP_GROUPMEMBERFILTER,
+	    &ldapval, MULTI_VALUE);
+	switch (r) {
+	case OK:
+		r = unescape(ldapval.s, &tmpval, 0);
+		if (r != OK) goto fail;
+		break;
+	case NOSUCH:
+		break;
+	default:
+		goto fail;
+	}
+
+	for (s = tmpval.s, smax = tmpval.s + tmpval.len;
+	    s < smax; s += str_len(s) + 1) {
+		r = qldap_filter(sq, s, attrs, founddn.s, SCOPE_BASE);
+		if (r == NOSUCH) continue;
+		if (r != OK) goto fail;
+		if (qldap_count(sq) < 1) continue;
+		/* match found */
+		qldap_free(sq);
+		return;
+	}
+	qldap_free(sq);
+	qldap_free(q);
+	strerr_die2x(100, FATAL,
+	    "You are not allowed to post to this list. (#5.7.2)");
+fail:
+	if (sq) qldap_free(sq);
+	qldap_free(q);
+	strerr_die5x(111, FATAL, "sender ", sender, " verification failed: ",
+	    qldap_err_str(r));
+	/* NOTREACHED */
+}
+
+
+qldap *
+ldapgroup(char *dn, int *flagc, int *flags, int *flagS)
+{
+	qldap *q;
+	const char *attrs[] = {
+		LDAP_GROUPCONFIRM,
+		LDAP_GROUPMEMONLY,
+		LDAP_GROUPCONFRIMTEXT,
+		LDAP_GROUPMODERATTEXT,
+		LDAP_GROUPMODERATDN,
+		LDAP_GROUPMODERAT822,
+		LDAP_GROUPMEMBERDN,
+		LDAP_GROUPMEMBER822,
+		LDAP_GROUPMEMBERFILTER,
+		LDAP_GROUPSENDERDN,
+		LDAP_GROUPSENDER822,
+		LDAP_GROUPSENDERFILTER,
+		LDAP_GROUPBOUNCEADMIN,
+		0 };
+	int r;
+		
+	q = qldap_new();
+	if (q == 0) temp_nomem();
+
+	r = qldap_open(q);
+	if (r != OK) goto fail;
+	r = qldap_bind(q, grouplogin.s, grouppassword.s);
+	if (r != OK) goto fail;
+
+	r = qldap_filter(q, "objectclass=*", attrs, dn, SCOPE_BASE);
+	if (r != OK) goto fail;
+	r = qldap_count(q);
+	if (r != 1) {
+		/* TOOMANY should be impossible with SCOPE_BASE */
+		r = r==0 ? NOSUCH : TOOMANY;
+		goto fail;
+	}
+	r = qldap_first(q); /* and only */
+	if (r != OK) goto fail;
+	
+	r = qldap_get_bool(q, LDAP_GROUPCONFIRM, flagc);
+	if (r != OK && r != NOSUCH) goto fail;
+	
+	r = qldap_get_bool(q, LDAP_GROUPMEMONLY, flags);
+	if (r != OK && r != NOSUCH) goto fail;
+	
+	r = qldap_get_attr(q, LDAP_GROUPCONFRIMTEXT, &ldapval, SINGLE_VALUE);
+	switch (r) {
+	case OK:
+		if (!env_put2("CONFIRMMESS", ldapval.s)) {
+			r = ERRNO;
+			goto fail;
+		}
+		break;
+	case NOSUCH:
+		if (!env_unset("CONFIRMMESS")) {
+			r = ERRNO;
+			goto fail;
+		}
+		break;
+	default:
+		goto fail;
+	}
+	
+	r = qldap_get_attr(q, LDAP_GROUPMODERATTEXT, &ldapval, SINGLE_VALUE);
+	switch (r) {
+	case OK:
+		if (!env_put2("APPROVEMESS", ldapval.s)) {
+			r = ERRNO;
+			goto fail;
+		}
+		break;
+	case NOSUCH:
+		if (!env_unset("APPROVEMESS")) {
+			r = ERRNO;
+			goto fail;
+		}
+		break;
+	default:
+		goto fail;
+	}
+
+	r = qldap_get_attr(q, LDAP_GROUPBOUNCEADMIN, &ldapval, MULTI_VALUE);
+	switch (r) {
+	case OK:
+		r = unescape(ldapval.s, &bounceadmin, 0);
+		if (r != OK) goto fail;
+		break;
+	case NOSUCH:
+		break;
+	default:
+		goto fail;
+	}
+
+
+	getmoderators(q);
+	
+	if (*flags) {
+		r = qldap_get_attr(q, LDAP_GROUPSENDERDN,
+		    &ldapval, MULTI_VALUE);
+		switch (r) {
+		case OK:
+			*flagS = 1;
+			return q;
+		case NOSUCH:
+			break;
+		default:
+			goto fail;
+		}
+		r = qldap_get_attr(q, LDAP_GROUPSENDER822,
+		    &ldapval, MULTI_VALUE);
+		switch (r) {
+		case OK:
+			*flagS = 1;
+			return q;
+		case NOSUCH:
+			break;
+		default:
+			goto fail;
+		}
+		r = qldap_get_attr(q, LDAP_GROUPSENDERFILTER,
+		    &ldapval, MULTI_VALUE);
+		switch (r) {
+		case OK:
+			*flagS = 1;
+			return q;
+		case NOSUCH:
+			break;
+		default:
+			goto fail;
+		}
+	}
+
+	return q;
+fail:
+	qldap_free(q);
+	strerr_die3x(111, FATAL, "get ldap group entry: ", qldap_err_str(r));
+	/* NOTREACHED */
+	return 0;
+}
+
+static int
+unescape(char *s, stralloc *t, unsigned int *count)
+{
+	do {
+		if (s[0] == '\\' && s[1] == ':') s++;
+		else if (s[0] == ':') {
+			if (count) *count += 1;
+			if (!stralloc_0(t)) return ERRNO;
+			continue;
+		}
+		if (!stralloc_append(t, s)) return ERRNO;
+	} while (*s++);
+	if (count) *count += 1;
+	return OK;
+}
+
+static void
+extract_addrs822(qldap *q, const char *attr, stralloc *list,
+    unsigned int *numlist)
+{
+	int r;
+
+	r = qldap_get_attr(q, attr, &ldapval, MULTI_VALUE);
+	switch (r) {
+	case OK:
+		r = unescape(ldapval.s, list, numlist);
+		if (r != OK) goto fail;
+		break;
+	case NOSUCH:
+		break;
+	default:
+		goto fail;
+	}
+
+	return;
+fail:
+	qldap_free(q);
+	strerr_die5x(111, FATAL, "expand group attr: ", attr, ": ",
+	    qldap_err_str(r));
+	/* NOTREACHED */
+}
+	
+static void
+extract_addrsdn(qldap *q, qldap *sq, const char *attr,
+    stralloc *list, unsigned int *numlist)
+{
+	const char *attrs[] = {
+		LDAP_MAIL,
+		0 };
+	char *s, *smax;
+	int r;
+
+	if (!stralloc_copys(&tmpval, "")) { r = ERRNO; goto fail; }
+	r = qldap_get_attr(q, attr, &ldapval, MULTI_VALUE);
+	switch (r) {
+	case OK:
+		r = unescape(ldapval.s, &tmpval, 0);
+		if (r != OK) goto fail;
+		break;
+	case NOSUCH:
+		break;
+	default:
+		goto fail;
+	}
+
+	for (s = tmpval.s, smax = tmpval.s + tmpval.len;
+	    s < smax; s += str_len(s) + 1) {
+		r = qldap_filter(sq, "objectclass=*", attrs, s, SCOPE_BASE);
+		if (r == NOSUCH) continue;
+		if (r != OK) goto fail;
+		r = qldap_count(sq);
+		if (r > 1) {
+			/* TOOMANY should be impossible with SCOPE_BASE */
+			r = TOOMANY;
+			goto fail;
+		} else if (r <= 0)
+			continue;
+		r = qldap_first(sq); /* and only */
+		if (r != OK) goto fail;
+		/* get mail address */
+		r = qldap_get_attr(sq, LDAP_MAIL, &ldapval, SINGLE_VALUE);
+		switch (r) {
+		case OK:
+			if (!stralloc_cat(list, &ldapval)) {
+				r = ERRNO;
+				goto fail;
+			}
+			if (numlist) *numlist += 1;
+			break;
+		case NOSUCH:
+			/* WTF! Ignore. */
+			break;
+		default:
+			goto fail;
+		}
+		/* free stuff for next search */
+		qldap_free_results(sq);
+	}
+	return;
+	
+fail:
+	qldap_free(sq);
+	qldap_free(q);
+	strerr_die5x(111, FATAL, "expand group attr: ", attr, ": ",
+	    qldap_err_str(r));
+	/* NOTREACHED */
+}
+
+static void
+extract_addrsfilter(qldap *q, qldap *sq, const char *attr,
+    stralloc *list, unsigned int *numlist)
+{
+	const char *attrs[] = {
+		LDAP_MAIL,
+		0 };
+	char *s, *smax;
+	int r;
+
+	if (!stralloc_copys(&tmpval, "")) { r = ERRNO; goto fail; }
+	r = qldap_get_attr(q, attr, &ldapval, MULTI_VALUE);
+	switch (r) {
+	case OK:
+		r = unescape(ldapval.s, &tmpval, 0);
+		if (r != OK) goto fail;
+		break;
+	case NOSUCH:
+		break;
+	default:
+		goto fail;
+	}
+
+	for (s = tmpval.s, smax = tmpval.s + tmpval.len;
+	    s < smax; s += str_len(s) + 1) {
+		r = qldap_filter(sq, s, attrs, qldap_basedn(), SCOPE_SUBTREE);
+		if (r == NOSUCH) continue;
+		if (r != OK) goto fail;
+		r = qldap_first(sq);
+		if (r != OK && r != NOSUCH) goto fail;
+		if (r == NOSUCH) {
+			qldap_free_results(sq);
+			continue;
+		}
+		do {
+			/* get mail address */
+			r = qldap_get_attr(sq, LDAP_MAIL, &ldapval,
+			    SINGLE_VALUE);
+			switch (r) {
+			case OK:
+				if (!stralloc_cat(list, &ldapval)) {
+					r = ERRNO;
+					goto fail;
+				}
+				if (numlist) *numlist += 1;
+				break;
+			case NOSUCH:
+				/* WTF! Ignore. */
+				break;
+			default:
+				goto fail;
+			}
+			r = qldap_next(sq);
+		} while (r == OK);
+		if (r != NOSUCH) goto fail;
+		
+		/* free stuff for next search */
+		qldap_free_results(sq);
+	}
+	return;
+	
+fail:
+	qldap_free(sq);
+	qldap_free(q);
+	strerr_die5x(111, FATAL, "expand group attr: ", attr, ": ",
+	    qldap_err_str(r));
+	/* NOTREACHED */
+}
+
+stralloc filter = {0};
+
+static int
+getentry(qldap *sq, char *mail)
+{
+	const char *attrs[] = {
+		LDAP_MAIL,
+		0 };
+	char *f;
+	int done, rv;
+
+	done = 0;
+	do {
+		/* build the search string for the email address */
+		f = filter_mail(mail, &done);
+		if (f == (char *)0) return ERRNO;
+
+		/* do the search for the email address */
+		rv = qldap_lookup(sq, f, attrs);
+		switch (rv) {
+		case OK:
+			return OK;
+		case NOSUCH:
+			break;
+		default:
+			return rv;
+		}
+	} while (!done);
+	return NOSUCH;
+}
diff -ruN qmail-1.03-orig/qmail.h qmail-1.03-ldap-20060201-orig/qmail.h
--- qmail-1.03-orig/qmail.h	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/qmail.h	2006-02-25 11:00:55.000000000 +0100
@@ -12,13 +12,14 @@
   char buf[1024];
 } ;
 
-extern int qmail_open();
-extern void qmail_put();
-extern void qmail_puts();
-extern void qmail_from();
-extern void qmail_to();
-extern void qmail_fail();
-extern char *qmail_close();
-extern unsigned long qmail_qp();
+extern int qmail_open(struct qmail *);
+extern int qmail_remote(struct qmail *, char *);
+extern void qmail_put(struct qmail *, const char *, int);
+extern void qmail_puts(struct qmail *, const char *);
+extern void qmail_from(struct qmail *, const char *);
+extern void qmail_to(struct qmail *, const char *);
+extern void qmail_fail(struct qmail *);
+extern const char *qmail_close(struct qmail *);
+extern unsigned long qmail_qp(struct qmail *);
 
 #endif
diff -ruN qmail-1.03-orig/qmail-imapd.rules qmail-1.03-ldap-20060201-orig/qmail-imapd.rules
--- qmail-1.03-orig/qmail-imapd.rules	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/qmail-imapd.rules	2006-02-25 11:00:55.000000000 +0100
@@ -0,0 +1,6 @@
+#
+# IMAP Server rules.
+# Normaly you allow from everyware and the only useful env vars are probably
+# IMAPCAPAPBILITY, NOPBS and LOGLEVEL
+#
+:allow,IMAP_CAPABILITY="IMAP4rev1 CHILDREN NAMESPACE THREAD=ORDEREDSUBJECT THREAD=REFERENCES SORT QUOTA"
diff -ruN qmail-1.03-orig/qmail-imapd.sh qmail-1.03-ldap-20060201-orig/qmail-imapd.sh
--- qmail-1.03-orig/qmail-imapd.sh	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/qmail-imapd.sh	2006-02-25 11:00:55.000000000 +0100
@@ -0,0 +1,38 @@
+#!/bin/sh
+exec 2>&1
+#
+# IMAP service: this script is for courier-imap
+#
+QMAIL="%QMAIL%"
+ME="`head -1 $QMAIL/control/me`"
+if [ -e $QMAIL/control/defaultdelivery ]; then
+        ALIASEMPTY=`head -1 $QMAIL/control/defaultdelivery 2> /dev/null`
+else
+        ALIASEMPTY=`head -1 $QMAIL/control/aliasempty 2> /dev/null`
+fi
+ALIASEMPTY=${ALIASEMPTY:="./Maildir/"}
+
+PATH="$QMAIL/bin:$PATH"
+
+# source the environemt in ./env
+eval `env - PATH=$PATH envdir ./env awk '\
+	BEGIN { for (i in ENVIRON) \
+		if (i != "PATH") { \
+			printf "export %s=\"%s\"\\n", i, ENVIRON[i] \
+		} \
+	}'`
+
+# enforce some sane defaults
+COURIER=${COURIER:="/usr/local"}
+PBSTOOL=${PBSTOOL:="$QMAIL/bin/pbsadd"}
+
+if [ X${NOPBSR+"true"} = X"true" ]; then
+	unset PBSTOOL
+fi
+
+exec \
+	tcpserver -v -HRl $ME -x$QMAIL/control/qmail-imapd.cdb \
+	    ${CONCURRENCY:+"-c$CONCURRENCY"} ${BACKLOG:+"-b$BACKLOG"} 0 imap \
+	$COURIER/sbin/imaplogin \
+	$QMAIL/bin/auth_imap ${PBSTOOL:+"-d$PBSTOOL"} \
+	$COURIER/bin/imapd "$ALIASEMPTY"
diff -ruN qmail-1.03-orig/qmail-imapd-ssl.sh qmail-1.03-ldap-20060201-orig/qmail-imapd-ssl.sh
--- qmail-1.03-orig/qmail-imapd-ssl.sh	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/qmail-imapd-ssl.sh	2006-02-25 11:00:55.000000000 +0100
@@ -0,0 +1,40 @@
+#!/bin/sh
+exec 2>&1
+#
+# IMAP service: this script is for courier-imap
+#
+QMAIL="%QMAIL%"
+ME="`head -1 $QMAIL/control/me`"
+if [ -e $QMAIL/control/defaultdelivery ]; then
+        ALIASEMPTY=`head -1 $QMAIL/control/defaultdelivery 2> /dev/null`
+else
+        ALIASEMPTY=`head -1 $QMAIL/control/aliasempty 2> /dev/null`
+fi
+ALIASEMPTY=${ALIASEMPTY:="./Maildir/"}
+
+PATH="$QMAIL/bin:$PATH"
+
+# source the environemt in ./env
+eval `env - PATH=$PATH envdir ./env awk '\
+	BEGIN { for (i in ENVIRON) \
+		if (i != "PATH") { \
+			printf "export %s=\"%s\"\\n", i, ENVIRON[i] \
+		} \
+	}'`
+
+# enforce some sane defaults
+COURIER=${COURIER:="/usr/local"}
+TLSCERT=${TLSCERT:="$QMAIL/control/cert.pem"}
+PBSTOOL=${PBSTOOL:="$QMAIL/bin/pbsadd"}
+
+if [ X${NOPBS+"true"} = X"true" ]; then
+	unset PBSTOOL
+fi
+
+exec \
+	tcpserver -v -HRl $ME -x$QMAIL/control/qmail-imapd.cdb \
+	    ${CONCURRENCY:+"-c$CONCURRENCY"} ${BACKLOG:+"-b$BACKLOG"} \
+	    -s ${TLSCERT:+"-n$TLSCERT"} 0 imaps \
+	$COURIER/sbin/imaplogin \
+	$QMAIL/bin/auth_imap ${PBSTOOL:+"-d$PBSTOOL"}\
+	$COURIER/bin/imapd "$ALIASEMPTY"
diff -ruN qmail-1.03-orig/qmail-inject.c qmail-1.03-ldap-20060201-orig/qmail-inject.c
--- qmail-1.03-orig/qmail-inject.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/qmail-inject.c	2006-02-25 11:00:55.000000000 +0100
@@ -1,3 +1,4 @@
+#include <unistd.h>
 #include "sig.h"
 #include "substdio.h"
 #include "stralloc.h"
@@ -35,10 +36,10 @@
 int flaghackmess = 0;
 int flaghackrecip = 0;
 char *mailhost;
-char *mailuser;
+const char *mailuser;
 int mailusertokentype;
 char *mailrhost;
-char *mailruser;
+const char *mailruser;
 
 stralloc control_idhost = {0};
 stralloc control_defaultdomain = {0};
@@ -53,9 +54,9 @@
 int flagqueue;
 struct qmail qqt;
 
-void put(s,len) char *s; int len;
+void put(const char *s, unsigned int len)
 { if (flagqueue) qmail_put(&qqt,s,len); else substdio_put(subfdout,s,len); }
-void puts(s) char *s; { put(s,str_len(s)); }
+void putstr(const char *s) { put(s,str_len(s)); }
 
 void perm() { _exit(100); }
 void temp() { _exit(111); }
@@ -90,13 +91,13 @@
 
 void exitnicely()
 {
- char *qqx;
+ const char *qqx;
 
  if (!flagqueue) substdio_flush(subfdout);
 
  if (flagqueue)
   {
-   int i;
+   unsigned int i;
 
    if (!stralloc_0(&sender)) die_nomem();
    qmail_from(&qqt,sender.s);
@@ -106,7 +107,7 @@
      if (!stralloc_0(&reciplist.sa[i])) die_nomem();
      qmail_to(&qqt,reciplist.sa[i].s);
     }
-   if (flagrh)
+   if (flagrh) {
      if (flagresent)
        for (i = 0;i < hrrlist.len;++i)
 	{
@@ -119,9 +120,9 @@
          if (!stralloc_0(&hrlist.sa[i])) die_nomem();
 	 qmail_to(&qqt,hrlist.sa[i].s);
 	}
-
+   }
    qqx = qmail_close(&qqt);
-   if (*qqx)
+   if (*qqx) {
      if (*qqx == 'D') {
        substdio_puts(subfderr,"qmail-inject: fatal: ");
        substdio_puts(subfderr,qqx + 1);
@@ -136,6 +137,7 @@
        substdio_flush(subfderr);
        temp();
      }
+   }
   }
 
  _exit(0);
@@ -152,7 +154,7 @@
 
 void savedh_print()
 {
- int i;
+ unsigned int i;
 
  for (i = 0;i < savedh.len;++i)
    put(savedh.sa[i].s,savedh.sa[i].len);
@@ -177,7 +179,7 @@
 void rwextraat(addr)
 token822_alloc *addr;
 {
- int i;
+ unsigned int i;
  if (addr->t[0].type == TOKEN822_AT)
   {
    --addr->len;
@@ -189,7 +191,7 @@
 void rwextradot(addr)
 token822_alloc *addr;
 {
- int i;
+ unsigned int i;
  if (addr->t[0].type == TOKEN822_DOT)
   {
    --addr->len;
@@ -201,17 +203,17 @@
 void rwnoat(addr)
 token822_alloc *addr;
 {
- int i;
- int shift;
+ unsigned int i;
+ unsigned int shift;
 
  for (i = 0;i < addr->len;++i)
    if (addr->t[i].type == TOKEN822_AT)
      return;
  shift = defaulthost.len;
  if (!token822_readyplus(addr,shift)) die_nomem();
- for (i = addr->len - 1;i >= 0;--i)
-   addr->t[i + shift] = addr->t[i];
  addr->len += shift;
+ for (i = addr->len - 1;i >= shift;--i)
+   addr->t[i] = addr->t[i - shift];
  for (i = 0;i < shift;++i)
    addr->t[i] = defaulthost.t[shift - 1 - i];
 }
@@ -219,8 +221,8 @@
 void rwnodot(addr)
 token822_alloc *addr;
 {
- int i;
- int shift;
+ unsigned int i;
+ unsigned int shift;
  for (i = 0;i < addr->len;++i)
   {
    if (addr->t[i].type == TOKEN822_DOT)
@@ -237,9 +239,9 @@
   }
  shift = defaultdomain.len;
  if (!token822_readyplus(addr,shift)) die_nomem();
- for (i = addr->len - 1;i >= 0;--i)
-   addr->t[i + shift] = addr->t[i];
  addr->len += shift;
+ for (i = addr->len - 1;i >= shift;--i)
+   addr->t[i] = addr->t[i - shift];
  for (i = 0;i < shift;++i)
    addr->t[i] = defaultdomain.t[shift - 1 - i];
 }
@@ -247,8 +249,8 @@
 void rwplus(addr)
 token822_alloc *addr;
 {
- int i;
- int shift;
+ unsigned int i;
+ unsigned int shift;
 
  if (addr->t[0].type != TOKEN822_ATOM) return;
  if (!addr->t[0].slen) return;
@@ -258,9 +260,9 @@
 
  shift = plusdomain.len;
  if (!token822_readyplus(addr,shift)) die_nomem();
- for (i = addr->len - 1;i >= 0;--i)
-   addr->t[i + shift] = addr->t[i];
  addr->len += shift;
+ for (i = addr->len - 1;i >= shift;--i)
+   addr->t[i] = addr->t[i - shift];
  for (i = 0;i < shift;++i)
    addr->t[i] = plusdomain.t[shift - 1 - i];
 }
@@ -536,7 +538,7 @@
 
 void finishmft()
 {
-  int i;
+  unsigned int i;
   static stralloc sa = {0};
   static stralloc sa2 = {0};
 
@@ -549,16 +551,16 @@
 
   if (i == tocclist.len) return;
 
-  puts("Mail-Followup-To: ");
+  putstr("Mail-Followup-To: ");
   i = tocclist.len;
   while (i--) {
     if (!stralloc_copy(&sa,&tocclist.sa[i])) die_nomem();
     if (!stralloc_0(&sa)) die_nomem();
     if (!quote2(&sa2,sa.s)) die_nomem();
     put(sa2.s,sa2.len);
-    if (i) puts(",\n  ");
+    if (i) putstr(",\n  ");
   }
-  puts("\n");
+  putstr("\n");
 }
 
 void finishheader()
@@ -580,9 +582,9 @@
    if (!stralloc_0(&sa)) die_nomem();
    if (!quote2(&sa2,sa.s)) die_nomem();
 
-   puts("Return-Path: <");
+   putstr("Return-Path: <");
    put(sa2.s,sa2.len);
-   puts(">\n");
+   putstr(">\n");
   }
 
  /* could check at this point whether there are any recipients */
@@ -594,23 +596,23 @@
    if (!htypeseen[H_R_DATE])
     {
      if (!newfield_datemake(starttime)) die_nomem();
-     puts("Resent-");
+     putstr("Resent-");
      put(newfield_date.s,newfield_date.len);
     }
    if (!htypeseen[H_R_MESSAGEID])
     {
      if (!newfield_msgidmake(control_idhost.s,control_idhost.len,starttime)) die_nomem();
-     puts("Resent-");
+     putstr("Resent-");
      put(newfield_msgid.s,newfield_msgid.len);
     }
    if (!htypeseen[H_R_FROM])
     {
      defaultfrommake();
-     puts("Resent-");
+     putstr("Resent-");
      put(defaultfrom.s,defaultfrom.len);
     }
    if (!htypeseen[H_R_TO] && !htypeseen[H_R_CC])
-     puts("Resent-Cc: recipient list not shown: ;\n");
+     putstr("Resent-Cc: recipient list not shown: ;\n");
   }
  else
   {
@@ -630,7 +632,7 @@
      put(defaultfrom.s,defaultfrom.len);
     }
    if (!htypeseen[H_TO] && !htypeseen[H_CC])
-     puts("Cc: recipient list not shown: ;\n");
+     putstr("Cc: recipient list not shown: ;\n");
    finishmft();
   }
 
@@ -682,11 +684,11 @@
 #define RECIP_HEADER 3
 #define RECIP_AH 4
 
-void main(argc,argv)
+int main(argc,argv)
 int argc;
 char **argv;
 {
- int i;
+ unsigned int i;
  int opt;
  int recipstrategy;
 
@@ -770,4 +772,6 @@
  if (headerbody(subfdin,doheaderfield,finishheader,dobody) == -1)
    die_read();
  exitnicely();
+ /* NOTREACHED */
+ return 0;
 }
diff -ruN qmail-1.03-orig/qmail-ldap.h qmail-1.03-ldap-20060201-orig/qmail-ldap.h
--- qmail-1.03-orig/qmail-ldap.h	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/qmail-ldap.h	2006-02-25 11:00:55.000000000 +0100
@@ -0,0 +1,190 @@
+/*
+ * Copyright (c) 1999-2004 Andre Oppermann, Claudio Jeker,
+ *      Internet Business Solutions AG, CH-8005 Zürich, Switzerland
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Internet Business
+ *      Solutions AG and its contributors.
+ * 4. Neither the name of the author nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#ifndef _QMAIL_LDAP_H_
+#define _QMAIL_LDAP_H_
+
+/* this is the "catch all" string
+ * ATTN: escape the string correctly, remember
+ * '(', ')', '\', and '*' have to be escaped with '\'
+ */
+#define LDAP_CATCH_ALL "catchall"
+
+/* triger level for quotawarning (0-100) */
+#define QUOTA_WARNING_LEVEL 70
+
+/* reply subject for mails without subjects. */
+#define REPLY_SUBJ "Your Mail"
+/* timeout for one delivery per sender */
+#define REPLY_TIMEOUT 1209600 /* 1 Week */
+/* default content type (don't forget the '\n' at the end) */
+#define REPLY_CT "text/plain; charset=utf-8\n"
+/* default content transfer encoding (don't forget the '\n' at the end) */
+#define REPLY_CTE "8bit\n"
+
+/* the maximum and minimum uid allowed */
+#define UID_MIN 100
+#define UID_MAX 65535
+
+/* the maximum and minimum gid allowed */
+#define GID_MIN 100
+#define GID_MAX 65535
+
+/* if the sanitycheck function should be less restricted for
+ * program pathes, this means especially that most special chars
+ * of the shell are allowed (like &, &, ;, and <,|,>)
+ * You should know what you are doing when disallowing this  */
+/* 1 = restriced sanitycheck; 0 = less restriced sanitycheck */
+#define RESTRICT_PROG 1
+
+/* ALIASDEVNULL replacement for the std. aliasempty for user with
+ * neither homeDirectory nor mailMessageStore defined */
+#define ALIASDEVNULL "|echo \"Unable to deliver mail: account incorrectly configured. (#5.3.5)\"; exit 100"
+/* just echo a warning to notify the user and exit 100.
+ * It's up to the reader to write a simple script with
+ * postmaster notification. */
+
+/* Default ldap search timeout. In seconds */
+#define	QLDAP_TIMEOUT		30
+
+/* This needs DASH_EXT option.
+ * Limit dash ext to the first DASH_EXT_LEVELS extensions.
+ * Search only for (DASH_EXT_LEVELS = 4):
+ * a-b-c-d-e-f-g-...@foobar.com
+ * a-b-c-d-catchall@foobar.com
+ * a-b-c-catchall@foobar.com
+ * a-b-catchall@foobar.com
+ * a-catchall@foobar.com
+ * catchall@foobar.com
+ */
+#define DASH_EXT_LEVELS 4
+
+/*********************************************************************
+        ldap variables used in qmail-lspawn and auth_*
+*********************************************************************/
+#define LDAP_MAIL		"mail"
+#define LDAP_MAILALTERNATE	"mailAlternateAddress"
+#define LDAP_QMAILUID		"qmailUID"
+#define LDAP_QMAILGID		"qmailGID"
+#define LDAP_MAILSTORE		"mailMessageStore"
+#define LDAP_HOMEDIR		"homeDirectory"
+#define LDAP_QUOTA		"mailQuota"
+#define LDAP_QUOTA_SIZE		"mailQuotaSize"
+#define LDAP_QUOTA_COUNT	"mailQuotaCount"
+#define LDAP_MAXMSIZE		"mailSizeMax"
+#define LDAP_FORWARDS		"mailForwardingAddress"
+#define LDAP_PROGRAM		"deliveryProgramPath"
+#define LDAP_MAILHOST		"mailHost"
+#define LDAP_MODE		"deliveryMode"
+#define LDAP_REPLYTEXT		"mailReplyText"
+#define LDAP_DOTMODE		"qmailDotMode"
+#define LDAP_UID		"uid"
+#define LDAP_PASSWD		"userPassword"
+#define LDAP_OBJECTCLASS	"objectClass"
+#define LDAP_ISACTIVE		"accountStatus"
+#define LDAP_PURGE		"qmailAccountPurge"
+
+#define DOTMODE_LDAPONLY 	"ldaponly"
+#define DOTMODE_LDAPWITHPROG	"ldapwithprog"
+#define DOTMODE_DOTONLY		"dotonly"
+#define DOTMODE_BOTH		"both"
+#define DOTMODE_NONE		"none"
+
+#define MODE_FONLY		"forwardonly"
+#define MODE_NOFORWARD		"noforward"
+#define MODE_NOMBOX		"nombox"
+#define MODE_NOLOCAL		"nolocal"
+#define MODE_NOPROG		"noprogram"
+#define MODE_REPLY		"reply"
+/* these are silently ignored */
+#define MODE_LOCAL		"local"
+#define MODE_FORWARD		"forward"
+#define MODE_PROG		"program"
+#define MODE_NOREPLY		"noreply"
+
+#define ISACTIVE_BOUNCE		"disabled"
+#define ISACTIVE_DELETE		"deleted"
+#define ISACTIVE_NOACCESS	"noaccess"
+#define ISACTIVE_ACTIVE		"active"
+
+/*********************************************************************
+        ldap variables used in qmail-group
+*********************************************************************/
+#define LDAP_GROUPOBJECTCLASS	"qmailGroup"
+#define LDAP_GROUPMEMONLY	"membersonly"
+#define LDAP_GROUPCONFIRM	"senderconfirm"
+#define LDAP_GROUPCONFRIMTEXT	"confirmtext"
+#define LDAP_GROUPMODERATTEXT	"moderatortext"
+#define LDAP_GROUPMODERATDN	"dnmoderator"
+#define LDAP_GROUPMODERAT822	"rfc822moderator"
+#define LDAP_GROUPMEMBERDN	"dnmember"
+#define LDAP_GROUPMEMBER822	"rfc822member"
+#define LDAP_GROUPMEMBERFILTER	"filtermember"
+#define LDAP_GROUPSENDERDN	"dnsender"
+#define LDAP_GROUPSENDER822	"rfc822sender"
+#define LDAP_GROUPSENDERFILTER	"filtersender"
+#define LDAP_GROUPBOUNCEADMIN	"bounceadmin"
+
+
+/*********************************************************************
+                 normaly you can stop editing here
+*********************************************************************/
+/* the same values as ints */
+#define STATUS_DELETE		3
+#define STATUS_BOUNCE		2
+#define STATUS_NOACCESS		1
+#define STATUS_OK 		0
+#define STATUS_UNDEF 		-1
+
+/* environment variables used between qmail-lspan and qmail-local
+ * and some other tools
+ */
+#define ENV_HOMEDIRMAKE		"QLDAPAUTOHOMEDIRMAKE"
+
+#define ENV_QUOTA		"MAILDIRQUOTA"
+#define ENV_QUOTAWARNING 	"QMAILQUOTAWARNING"
+
+#define ENV_DOTMODE		"QMAILDOTMODE"
+#define ENV_MODE 		"QMAILMODE"
+#define ENV_REPLYTEXT		"QMAILREPLYTEXT"
+#define ENV_FORWARDS		"QMAILFORWARDS"
+#define ENV_PROGRAM		"QMAILDELIVERYPROGRAM"
+
+#define ENV_GROUP		"QLDAPGROUP"
+
+/* qmail-local.c only */
+#define DO_LDAP 	0x01
+#define DO_DOT  	0x02
+#define DO_BOTH 	(DO_LDAP | DO_DOT)
+
+#endif
diff -ruN qmail-1.03-orig/qmail-ldaplookup.c qmail-1.03-ldap-20060201-orig/qmail-ldaplookup.c
--- qmail-1.03-orig/qmail-ldaplookup.c	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/qmail-ldaplookup.c	2006-02-25 11:00:55.000000000 +0100
@@ -0,0 +1,548 @@
+/*
+ * Copyright (c) 2000-2004 Andre Oppermann, Claudio Jeker,
+ *      Internet Business Solutions AG, CH-8005 Zürich, Switzerland
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Internet Business
+ *      Solutions AG and its contributors.
+ * 4. Neither the name of the author nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#include <sys/types.h>
+#include <pwd.h>
+#include <unistd.h>
+
+#include "alloc.h"
+#include "auto_usera.h"
+#include "byte.h"
+#include "case.h"
+#include "env.h"
+#include "error.h"
+#include "localdelivery.h"
+#include "output.h"
+#include "passwd.h"
+#include "qldap.h"
+#include "qldap-cluster.h"
+#include "qldap-debug.h"
+#include "qldap-errno.h"
+#include "qmail-ldap.h"
+#include "read-ctrl.h"
+#include "scan.h"
+#include "sgetopt.h"
+#include "str.h"
+#include "stralloc.h"
+#include "strerr.h"
+#include "subfd.h"
+#include "substdio.h"
+#ifdef AUTOHOMEDIRMAKE
+#include "dirmaker.h"
+#endif
+
+#define FATAL "qmail-ldaplookup: fatal: "
+#define WARN "qmail-ldaplookup: warning: "
+
+void
+temp_nomem(void)
+{
+        strerr_die2x(111, FATAL, "Out of memory.");
+}
+
+void
+usage(void) 
+{
+	output(subfderr,
+	    "usage:"
+	    "\t%s [-d level] [-D binddn -w passwd] -u uid [-p passwd]\n"
+	    "\t%s [-d level] [-D binddn -w passwd] -m mail\n"
+	    "\t%s [-d level] [-D binddn -w passwd] -f ldapfilter\n",
+	    optprogname, optprogname, optprogname, optprogname);
+	output(subfderr, "options:\n"
+	    "\t-d level \tsets log-level to level\n"
+	    "\t-u uid   \tsearch for user id uid (pop3/imap lookup)\n"
+	    "\t-p passwd\tpassword for user id lookups (only by root)\n"
+	    "\t-m mail  \tlookup the mailaddress\n"
+	    "\t-D binddn\tbind DN\n"
+	    "\t-w passwd\tbind password\n");
+	_exit(1);
+}
+
+void fail(qldap *, const char *, int);
+void unescape(char *, stralloc *);
+
+
+ctrlfunc ctrls[] = {
+  qldap_ctrl_trylogin,
+  qldap_ctrl_generic,
+  localdelivery_init,
+#ifdef QLDAP_CLUSTER
+  cluster_init,
+#endif
+#ifdef AUTOHOMEDIRMAKE
+  dirmaker_init,
+#endif
+  0
+};
+
+stralloc dn = {0};
+stralloc foo = {0};
+stralloc bar = {0};
+
+int main(int argc, char **argv)
+{
+	enum { unset, uid, mail, filter } mode = unset;
+	qldap	*q, *qpw;
+	struct passwd *pw;
+	char	*passwd = 0, *value = 0;
+	char	*bindpw = 0, *binddn = 0;
+	char	*f, *s;
+	int	opt, r, done, status, id;
+	unsigned int j, slen;
+	unsigned long size, count, maxsize;
+	
+	const char *attrs[] = { LDAP_MAIL,
+				LDAP_MAILALTERNATE,
+				LDAP_UID,
+				LDAP_QMAILUID,
+				LDAP_QMAILGID,
+				LDAP_ISACTIVE,
+				LDAP_MAILHOST,
+				LDAP_MAILSTORE,
+				LDAP_HOMEDIR,
+				LDAP_QUOTA_SIZE,
+				LDAP_QUOTA_COUNT,
+				LDAP_FORWARDS,
+				LDAP_PROGRAM,
+				LDAP_MODE,
+				LDAP_REPLYTEXT,
+				LDAP_DOTMODE,
+				LDAP_MAXMSIZE,
+				LDAP_OBJECTCLASS,
+#if 0
+				LDAP_GROUPCONFIRM,
+				LDAP_GROUPMEMONLY,
+				LDAP_GROUPCONFRIMTEXT,
+				LDAP_GROUPMODERATTEXT,
+				LDAP_GROUPMODERATDN,
+				LDAP_GROUPMODERAT822,
+				LDAP_GROUPMEMBERDN,
+				LDAP_GROUPMEMBER822,
+				LDAP_GROUPMEMBERFILTER,
+#endif
+				LDAP_PASSWD,
+				0};
+
+	while ((opt = getopt(argc, argv, "d:D:u:m:p:f:w:")) != opteof)
+		switch (opt) {
+		case 'd':
+			if (env_put2("LOGLEVEL", optarg) == 0)
+				strerr_die2sys(1, FATAL, "setting loglevel: ");
+			break;
+		case 'D':
+			binddn = optarg;
+			break;
+		case 'u':
+			if (value != 0)
+				usage();
+			value = optarg;
+			mode = uid;
+			break;
+		case 'm':
+			if (value != 0)
+				usage();
+			value = optarg;
+			mode = mail;
+			break;
+		case 'f':
+			if (value != 0)
+				usage();
+			value = optarg;
+			mode = filter;
+			break;
+		case 'p':
+			if (geteuid() != 0)
+				strerr_die2x(1, FATAL,
+				    "only the superuser may comapre passwords");
+			passwd = optarg;
+			break;
+		case 'w':
+			bindpw = optarg;
+			break;
+		default:
+			usage();
+		}
+	if (argc != optind) usage();
+	if (bindpw && !binddn) usage();
+	
+	log_init(STDERR, -1, 0);
+
+	if (read_controls(ctrls) != 0)
+		strerr_die2sys(111, FATAL, "unable to read controls: ");
+	
+	q = qldap_new();
+	if (q == 0)
+		strerr_die2sys(111, FATAL, "qldap_new failed: ");
+	qpw = qldap_new();
+	if (qpw == 0)
+		strerr_die2sys(111, FATAL, "qldap_new failed: ");
+	
+	r = qldap_open(q);
+	if (r != OK) fail(q, "qldap_open", r);
+	r = qldap_open(qpw);
+	if (r != OK) fail(qpw, "qldap_open", r);
+	r = qldap_bind(q, binddn, bindpw);
+	if (r != OK) fail(q, "qldap_bind", r);
+
+	if (passwd == 0 || mode != uid || qldap_need_rebind() != 0)
+		attrs[sizeof(attrs)/4 - 2] = 0; /* password */
+	done = 0;
+	f = 0;
+	do {
+		switch (mode) {
+		case mail:
+			f = filter_mail(value, &done);
+			if (value == 0)
+				strerr_die2sys(1, FATAL, "building filter: ");
+			break;
+		case uid:
+			f = filter_uid(value);
+			done = 1;
+			if (value == 0)
+				strerr_die2sys(1, FATAL, "building filter: ");
+			break;
+		case filter:
+			f = value;
+			break;
+		default:
+			usage();
+		}
+		output(subfdout, "Searching ldap for: %s\nunder dn: %s\n",
+		    f, qldap_basedn());
+		r = qldap_filter(q, f, attrs, qldap_basedn(), SCOPE_SUBTREE);
+		if (r != OK) fail(q, "qldap_filter", r);
+
+		r = qldap_count(q);
+		switch (r) {
+		case -1:
+			fail(q, "qldap_count", FAILED);
+		case 0:
+			output(subfdout, "No entries found.\n");
+			qldap_free(q);
+			/* TODO hook for local lookups. */
+			return 0;
+		case 1:
+			output(subfdout, "Found %i entry:\n", r);
+			break;
+		default:
+			output(subfdout, "Found %i entries:\n", r);
+			if (mode == uid || mode == uid) {
+				output(subfdout,
+				    "Uh-oh: multiple entries found but "
+				    "should be unique!\n");
+				passwd = 0;
+			}
+			break;
+		}
+		output(subfdout, "\n");
+	} while (r == 0 && !done);
+
+	r = qldap_first(q);
+	if (r != OK) fail(q, "qldap_first", r);;
+	do {
+		r = qldap_get_dn(q, &dn);
+		if (r != OK) fail(q, "qldap_get_dn", r);
+		output(subfdout, "dn: %s\n"
+		    "-------------------------------------------------------\n",
+		    dn.s);
+		
+		r = qldap_get_attr(q, LDAP_OBJECTCLASS, &foo, MULTI_VALUE);
+		if (r != OK) fail(q, "qldap_get_attr(" LDAP_OBJECTCLASS ")", r);
+		unescape(foo.s, &bar);
+		s = bar.s;
+		slen = bar.len-1;
+		for(;;) {
+			output(subfdout, "%s: %s\n",LDAP_OBJECTCLASS ,s);
+			j = byte_chr(s,slen,0);
+			if (j++ >= slen) break;
+			s += j; slen -= j;
+		}
+		
+		r = qldap_get_attr(q, LDAP_MAIL, &foo, SINGLE_VALUE);
+		if (r != OK) fail(q, "qldap_get_attr(" LDAP_MAIL ")", r);
+		output(subfdout, "%s: %s\n", LDAP_MAIL, foo.s);
+
+		r = qldap_get_attr(q, LDAP_MAILALTERNATE, &foo, MULTI_VALUE);
+		if (r != OK && r != NOSUCH)
+			fail(q, "qldap_get_attr(" LDAP_MAILALTERNATE ")", r);
+		if (r == OK) {
+			unescape(foo.s, &bar);
+			s = bar.s;
+			slen = bar.len-1;
+			for(;;) {
+				output(subfdout, "%s: %s\n",
+				    LDAP_MAILALTERNATE, s);
+				j = byte_chr(s,slen,0);
+				if (j++ >= slen) break;
+				s += j; slen -= j;
+			}
+		}
+		
+		r = qldap_get_user(q, &foo);
+		if (r != OK && r != NOSUCH) fail(q, "qldap_get_user", r);
+		if (r == OK)
+			output(subfdout, "%s: %s\n", LDAP_UID, foo.s);
+		else
+			output(subfdout, "%s: undefined "
+			    "(forward only account required)\n", LDAP_UID);
+
+		r = qldap_get_status(q, &status);
+		if (r != OK) fail(q, "qldap_get_status", r);
+		switch (status) {
+		case STATUS_BOUNCE:
+			output(subfdout, "%s: %s\n",
+			    LDAP_ISACTIVE, ISACTIVE_BOUNCE);
+			break;
+		case STATUS_NOACCESS:
+			output(subfdout, "%s: %s\n",
+			    LDAP_ISACTIVE, ISACTIVE_NOACCESS);
+			break;
+		case STATUS_OK:
+			output(subfdout, "%s: %s\n",
+			    LDAP_ISACTIVE, ISACTIVE_ACTIVE);
+			break;
+		case STATUS_UNDEF:
+			output(subfdout, "%s: %s\n", LDAP_ISACTIVE,
+			    "undefined -> active");
+			break;
+		default:
+			strerr_warn2(WARN,
+			    "qldap_get_status returned unknown status", 0);
+		}
+		
+		r = qldap_get_attr(q, LDAP_MAILHOST, &foo, SINGLE_VALUE);
+		if (r != OK && r != NOSUCH)
+			fail(q, "qldap_get_attr(" LDAP_MAILHOST ")", r);
+		if (r == OK) {
+			output(subfdout, "%s: %s\n", LDAP_MAILHOST, foo.s);
+			/*
+			 * TODO we could check if we are in cluster mode and 
+			 * if we would redirect to a differnet host
+			 */
+		} else
+			output(subfdout, "%s: undefined\n", LDAP_MAILHOST);
+
+		/* get the path of the maildir or mbox */
+		r = qldap_get_mailstore(q, &foo, &bar);
+		switch (r) {
+		case OK:
+			output(subfdout, "homeDirectory: %s\n", foo.s);
+			if (bar.len > 0)
+				output(subfdout, "aliasEmpty: %s\n", bar.s);
+			else
+				output(subfdout, "aliasEmpty: using default\n");
+			break;
+		case NEEDED:
+			output(subfdout,
+			    "forward only delivery via alias user\n");
+			pw = getpwnam(auto_usera);
+			if (!pw)
+				strerr_die4x(100, FATAL,
+				    "Aiiieeeee, now alias user '",
+				    auto_usera, "'found in /etc/passwd.");
+			output(subfdout, "alias user: %s\n", pw->pw_name);
+			output(subfdout, "alias user uid: %i\n", pw->pw_uid);
+			output(subfdout, "alias user gid: %i\n", pw->pw_gid);
+			output(subfdout, "alias user home: %s\n", pw->pw_dir);
+			output(subfdout, "alias user aliasempty: %s\n",
+			    ALIASDEVNULL);
+			/* get the forwarding addresses */
+			r = qldap_get_attr(q, LDAP_FORWARDS, &foo, MULTI_VALUE);
+			if (r != OK)
+				fail(q, "qldap_get_attr("
+				    LDAP_FORWARDS ") for forward only user", r);
+			unescape(foo.s, &bar);
+			s = bar.s;
+			slen = bar.len-1;
+			for(;;) {
+				output(subfdout, "%s: %s\n", LDAP_FORWARDS, s);
+				j = byte_chr(s,slen,0);
+				if (j++ >= slen) break;
+				s += j; slen -= j;
+			}
+			goto next;
+		default:
+			fail(q, "qldap_get_mailstore", r);
+		}
+		
+		r = qldap_get_dotmode(q, &foo);
+		if (r != OK) fail(q, "qldap_get_dotmode", r);
+		output(subfdout, "%s: %s\n", LDAP_DOTMODE, foo.s);
+
+		r = qldap_get_uid(q, &id);
+		if (r != OK) fail(q, "qldap_get_uid", r);
+		output(subfdout, "%s: %i\n", LDAP_QMAILUID, id);
+		
+		r = qldap_get_gid(q, &id);
+		if (r != OK) fail(q, "qldap_get_gid", r);
+		output(subfdout, "%s: %i\n", LDAP_QMAILGID, id);
+		
+		r = qldap_get_quota(q, &size, &count, &maxsize);
+		if (r != OK) fail(q, "qldap_get_quota", r);
+		output(subfdout, "%s: %u%s\n", LDAP_QUOTA_SIZE, size,
+		    size==0?" (unlimited)":"");
+		output(subfdout, "%s: %u%s\n", LDAP_QUOTA_COUNT, count,
+		    count==0?" (unlimited)":"");
+		output(subfdout, "%s: %u%s\n", LDAP_MAXMSIZE, maxsize,
+		    maxsize==0?" (unlimited)":"");
+
+		r = qldap_get_attr(q, LDAP_MODE, &foo, MULTI_VALUE);
+		if (r != OK && r != NOSUCH)
+			fail(q, "qldap_get_attr(" LDAP_MODE ")", r);
+		if (r == OK) {
+			unescape(foo.s, &bar);
+			s = bar.s;
+			slen = bar.len-1;
+			for(;;) {
+				if (case_diffs(MODE_FORWARD, s) &&
+				    case_diffs(MODE_REPLY, s) &&
+				    case_diffs(MODE_NOLOCAL, s) &&
+				    case_diffs(MODE_NOMBOX, s) &&
+				    case_diffs(MODE_NOFORWARD, s) &&
+				    case_diffs(MODE_NOPROG, s) &&
+				    case_diffs(MODE_LOCAL, s) &&
+				    case_diffs(MODE_FORWARD, s) &&
+				    case_diffs(MODE_PROG, s) &&
+				    case_diffs(MODE_NOREPLY, s))
+					strerr_warn4(WARN,
+					    "undefined mail delivery mode: ",
+					    s," (ignored).", 0);
+				else if (!case_diffs(MODE_FORWARD, s))
+					strerr_warn4(WARN,
+					    "mail delivery mode: ",
+					    s," should not be used "
+					    "(used internally).", 0);
+				output(subfdout, "%s: %s\n", LDAP_MODE, s);
+				j = byte_chr(s,slen,0);
+				if (j++ >= slen) break;
+				s += j; slen -= j;
+			}
+		}
+
+		r = qldap_get_attr(q, LDAP_FORWARDS, &foo, MULTI_VALUE);
+		if (r != OK && r != NOSUCH)
+			fail(q, "qldap_get_attr(" LDAP_FORWARDS ")", r);
+		if (r == OK) {
+			unescape(foo.s, &bar);
+			s = bar.s;
+			slen = bar.len-1;
+			for(;;) {
+				output(subfdout, "%s: %s\n", LDAP_FORWARDS, s);
+				j = byte_chr(s,slen,0);
+				if (j++ >= slen) break;
+				s += j; slen -= j;
+			}
+		}
+
+		r = qldap_get_attr(q, LDAP_PROGRAM, &foo, MULTI_VALUE);
+		if (r != OK && r != NOSUCH)
+			fail(q, "qldap_get_attr(" LDAP_PROGRAM ")", r);
+		if (r == OK) {
+			unescape(foo.s, &bar);
+			s = bar.s;
+			slen = bar.len-1;
+			for(;;) {
+				output(subfdout, "%s: %s\n", LDAP_PROGRAM, s);
+				j = byte_chr(s,slen,0);
+				if (j++ >= slen) break;
+				s += j; slen -= j;
+			}
+		}
+
+		r = qldap_get_attr(q, LDAP_REPLYTEXT, &foo, SINGLE_VALUE);
+		if (r != OK && r != NOSUCH)
+			fail(q, "qldap_get_attr(" LDAP_REPLYTEXT ")", r);
+		if (r == OK)
+			output(subfdout, "%s:\n=== begin ===\n%s\n"
+			    "=== end ===\n", LDAP_REPLYTEXT, foo.s);
+		else
+			output(subfdout, "%s: undefined\n", LDAP_REPLYTEXT);
+
+		if (mode == uid && passwd != 0) {
+			if (qldap_need_rebind() == 0) {
+				r = qldap_get_attr(q, LDAP_PASSWD,
+				    &foo, SINGLE_VALUE);
+				if (r != OK) fail(q, "qldap_get_attr("
+				    LDAP_PASSWD ")", r);
+				r = cmp_passwd(passwd, foo.s);
+			} else {
+				r = qldap_rebind(qpw, dn.s, passwd);
+				switch (r) {
+				case OK:
+					r = OK;
+					break;
+				case LDAP_BIND_AUTH:
+					r = BADPASS;
+					break;
+				default:
+					break;
+				}
+			}
+			output(subfdout, "\nPASSWORD COMPARE was %s.\n",
+			    r == OK?"successful":"NOT successful");
+			if (r != OK)
+				output(subfdout, "\terror was: %s\n",
+				    qldap_err_str(r));
+		}
+
+next:
+		r = qldap_next(q);
+		output(subfdout, "\n\n");
+	} while (r == OK);
+	if (r != NOSUCH) fail(q, "qldap_next", r);
+	qldap_free(q);
+	return 0;
+}
+
+void
+fail(qldap *q, const char *f, int r)
+{
+	qldap_free(q);
+	strerr_die4x(111, FATAL, f ,": ", qldap_err_str(r));
+}
+
+void
+unescape(char *s, stralloc *t)
+{
+  if (!stralloc_copys(t, "")) temp_nomem();
+  do {
+    if (s[0] == '\\' && s[1] == ':') s++;
+    else if (s[0] == ':') {
+      if (!stralloc_0(t)) temp_nomem();
+      continue;
+    }
+    if (!stralloc_append(t, s)) temp_nomem();
+  } while (*s++);
+}
+
diff -ruN qmail-1.03-orig/qmail-local.c qmail-1.03-ldap-20060201-orig/qmail-local.c
--- qmail-1.03-orig/qmail-local.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/qmail-local.c	2006-02-25 11:00:55.000000000 +0100
@@ -1,5 +1,6 @@
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <unistd.h>
 #include "readwrite.h"
 #include "sig.h"
 #include "env.h"
@@ -29,6 +30,15 @@
 #include "gfrom.h"
 #include "auto_patrn.h"
 
+#include "qmail-ldap.h"
+#include "qldap-errno.h"
+#include "auto_qmail.h"
+#include "scan.h"
+#include "maildir++.h"
+#ifdef AUTOMAILDIRMAKE
+#include "mailmaker.h"
+#endif
+
 void usage() { strerr_die1x(100,"qmail-local: usage: qmail-local [ -nN ] user homedir local dash ext domain sender aliasempty"); }
 
 void temp_nomem() { strerr_die1x(111,"Out of memory. (#4.3.0)"); }
@@ -38,7 +48,7 @@
 void temp_read() { strerr_die3x(111,"Unable to read message: ",error_str(errno),". (#4.3.0)"); }
 void temp_slowlock()
 { strerr_die1x(111,"File has been locked for 30 seconds straight. (#4.3.0)"); }
-void temp_qmail(fn) char *fn;
+void temp_qmail(fn) const char *fn;
 { strerr_die5x(111,"Unable to open ",fn,": ",error_str(errno),". (#4.3.0)"); }
 
 int flagdoit;
@@ -53,6 +63,9 @@
 char *sender;
 char *aliasempty;
 
+/* define the global variables */
+char *quotastring;
+
 stralloc safeext = {0};
 stralloc ufline = {0};
 stralloc rpline = {0};
@@ -63,23 +76,24 @@
 stralloc cmds = {0};
 stralloc messline = {0};
 stralloc foo = {0};
+stralloc qapp = {0};
 
 char buf[1024];
 char outbuf[1024];
 
 /* child process */
-
 char fntmptph[80 + FMT_ULONG * 2];
-char fnnewtph[80 + FMT_ULONG * 2];
+char fnnewtph[83 + FMT_ULONG * 3];
 void tryunlinktmp() { unlink(fntmptph); }
 void sigalrm() { tryunlinktmp(); _exit(3); }
+int msfd = -1; /* global filedescriptor to the quota file */
 
 void maildir_child(dir)
 char *dir;
 {
  unsigned long pid;
- unsigned long time;
- char host[64];
+ unsigned long tnow;
+ char hostname[64];
  char *s;
  int loop;
  struct stat st;
@@ -88,18 +102,22 @@
  substdio ssout;
 
  sig_alarmcatch(sigalrm);
- if (chdir(dir) == -1) { if (error_temp(errno)) _exit(1); _exit(2); }
+ if (chdir(dir) == -1) {
+   if (error_temp(errno)) _exit(1); else _exit(2);
+ }
+
  pid = getpid();
- host[0] = 0;
- gethostname(host,sizeof(host));
+ hostname[0] = 0;
+ gethostname(hostname,sizeof(hostname));
  for (loop = 0;;++loop)
   {
-   time = now();
+   tnow = now();
    s = fntmptph;
    s += fmt_str(s,"tmp/");
-   s += fmt_ulong(s,time); *s++ = '.';
+   s += fmt_ulong(s,tnow); *s++ = '.';
    s += fmt_ulong(s,pid); *s++ = '.';
-   s += fmt_strn(s,host,sizeof(host)); *s++ = 0;
+   s += fmt_strn(s,hostname,sizeof(hostname)); 
+   *s++ = 0;
    if (stat(fntmptph,&st) == -1) if (errno == error_noent) break;
    /* really should never get to this point */
    if (loop == 2) _exit(1);
@@ -112,8 +130,8 @@
  fd = open_excl(fntmptph);
  if (fd == -1) _exit(1);
 
- substdio_fdbuf(&ss,read,0,buf,sizeof(buf));
- substdio_fdbuf(&ssout,write,fd,outbuf,sizeof(outbuf));
+ substdio_fdbuf(&ss,subread,0,buf,sizeof(buf));
+ substdio_fdbuf(&ssout,subwrite,fd,outbuf,sizeof(outbuf));
  if (substdio_put(&ssout,rpline.s,rpline.len) == -1) goto fail;
  if (substdio_put(&ssout,dtline.s,dtline.len) == -1) goto fail;
 
@@ -125,8 +143,21 @@
 
  if (substdio_flush(&ssout) == -1) goto fail;
  if (fsync(fd) == -1) goto fail;
+ if (fstat(fd, &st) == -1) goto fail;
  if (close(fd) == -1) goto fail; /* NFS dorks */
 
+ s = fnnewtph;
+ while( *s ) s++;
+ s += fmt_str(s,",S=");
+ s += fmt_ulong(s,(unsigned long) st.st_size);
+ *s++ = 0;
+
+ if( quotastring && *quotastring ) {
+   /* finally update the quota file "maildirsize" */
+   quota_add(msfd, (unsigned long) st.st_size, 1);
+   close(msfd);
+ }
+  
  if (link(fntmptph,fnnewtph) == -1) goto fail;
    /* if it was error_exist, almost certainly successful; i hate NFS */
  tryunlinktmp(); _exit(0);
@@ -136,12 +167,115 @@
 
 /* end child process */
 
+/* quota handling warning and bounce */
+void quota_bounce(const char *type)
+{
+	strerr_die3x(100, "The users ", type,
+	    " is over the allowed quota (size). (#5.2.2)");
+}
+
+void quota_warning(char *fn)
+{
+ int child;
+ char *(args[3]);
+ int wstat;
+
+ if (!stralloc_copys(&qapp, auto_qmail)) temp_nomem();
+ if (!stralloc_cats(&qapp, "/bin/qmail-quotawarn")) temp_nomem();
+ if (!stralloc_0(&qapp)) temp_nomem();
+
+ if (seek_begin(0) == -1) temp_rewind();
+
+ switch(child = fork())
+  {
+   case -1:
+     temp_fork();
+   case 0:
+     args[0] = qapp.s; args[1] = fn; args[2] = 0;
+     sig_pipedefault();
+     execv(*args,args);
+     _exit(2);
+  }
+
+ wait_pid(&wstat,child);
+ if (wait_crashed(wstat))
+   temp_childcrashed();
+ switch(wait_exitcode(wstat))
+  {
+   case 2:
+     strerr_die5x(111,"Unable to run quotawarn program: ",
+	 qapp.s, ": ",error_str(errno),". (#4.2.2)");
+   case 111: _exit(111);
+   case 0: break;
+   default: _exit(100);
+  }
+
+}
+/* end -- quota handling warning and bounce */
+
 void maildir(fn)
 char *fn;
 {
  int child;
  int wstat;
 
+ /* quota handling maildir */
+ struct stat mailst;
+ int perc;
+ quota_t q;
+ unsigned long mailsize;
+
+#ifdef AUTOMAILDIRMAKE
+ switch (maildir_make(fn)) {
+ case OK:
+   break;
+ case MAILDIR_CORRUPT:
+   strerr_die3x(111,"The maildir '", fn, "' seems to be corrupted. (#4.2.1)");
+ case ERRNO:
+ default:
+   strerr_die3x(111,"Unable to create maildir '", fn, "' (#4.3.0)");
+ }
+#endif
+
+ if (quotastring && *quotastring) {
+   if (fstat(0, &mailst) != 0)
+       strerr_die3x(111,"Can not stat mail for quota: ",
+	   error_str(errno),". (#4.3.0)");
+   mailsize = mailst.st_size;
+   quota_get(&q, quotastring);
+   if (quota_calc(fn, &msfd, &q) == -1) {
+     /* second chance */
+     sleep(3);
+     if (quota_calc(fn, &msfd, &q) == -1) {
+       strerr_die1x(111,
+	   "Temporary race condition while calculating quota. (#4.3.0)");
+     }
+   }
+   /* fd can be -1 when retval = 0 quota_add/rm take care of that */
+   
+   if (quota_check(&q, mailsize, 1, &perc) != 0) { /* 0 if OK */
+     if (quota_recalc(fn, &msfd, &q) == -1) {
+       /* second chance */
+       sleep(3);
+       if (quota_recalc(fn, &msfd, &q) == -1)
+	 strerr_die1x(111,
+	     "Temporary race condition while recalculating quota. (#4.3.0)");
+     }
+     if (quota_check(&q, mailsize, 1, &perc) != 0) {
+       /* bounce mail but drop a warning first */
+       quota_warning(fn);
+       quota_bounce("mailfolder");
+     }
+   }
+   /* fd can be -1 when retval = 0 quota_add/rm take care of that */
+
+   if (perc >= QUOTA_WARNING_LEVEL) 
+     /* drop a warning when mailbox is around 80% full */
+     quota_warning(fn);
+ }
+ 
+ /* end -- quota handling maildir */
+
  if (seek_begin(0) == -1) temp_rewind();
 
  switch(child = fork())
@@ -153,6 +287,8 @@
      _exit(111);
   }
 
+ if (msfd != -1) close(msfd); /* close the maildirsize fd in the parent */
+
  wait_pid(&wstat,child);
  if (wait_crashed(wstat))
    temp_childcrashed();
@@ -176,6 +312,32 @@
  seek_pos pos;
  int flaglocked;
 
+ /* quota handling mbox */
+ struct stat filest, mailst;
+ unsigned long totalsize;
+ quota_t q;
+
+ if( quotastring && *quotastring ) {
+   quota_get(&q, quotastring);
+   if (stat(fn, &filest) == -1) {
+     filest.st_size = 0;        /* size of nonexisting mailfile */
+     if ( errno != error_noent) { /* FALSE if file doesn't exist */
+       strerr_die5x(111,"Unable to quota ", fn, ": ",error_str(errno), ". (#4.3.0)");
+     }
+   }
+   if (fstat(0, &mailst) != 0)
+     strerr_die3x(111,"Unable to quota mail: ",error_str(errno), ". (#4.3.0)");
+   
+   totalsize = (unsigned long) filest.st_size + (unsigned long) mailst.st_size;
+   if (totalsize * 100 / q.quota_size >= QUOTA_WARNING_LEVEL)
+     /* drop a warning when mailbox is around 80% full */
+     quota_warning(fn);
+   if (totalsize > q.quota_size)
+     quota_bounce("mailbox");
+ }
+ 
+ /* end -- quota handling mbox */
+
  if (seek_begin(0) == -1) temp_rewind();
 
  fd = open_append(fn);
@@ -191,8 +353,8 @@
  seek_end(fd);
  pos = seek_cur(fd);
 
- substdio_fdbuf(&ss,read,0,buf,sizeof(buf));
- substdio_fdbuf(&ssout,write,fd,outbuf,sizeof(outbuf));
+ substdio_fdbuf(&ss,subread,0,buf,sizeof(buf));
+ substdio_fdbuf(&ssout,subwrite,fd,outbuf,sizeof(outbuf));
  if (substdio_put(&ssout,ufline.s,ufline.len)) goto writeerrs;
  if (substdio_put(&ssout,rpline.s,rpline.len)) goto writeerrs;
  if (substdio_put(&ssout,dtline.s,dtline.len)) goto writeerrs;
@@ -241,7 +403,8 @@
    case -1:
      temp_fork();
    case 0:
-     args[0] = "/bin/sh"; args[1] = "-c"; args[2] = prog; args[3] = 0;
+     args[0] = (char *)"/bin/sh"; args[1] = (char *)"-c";
+     args[2] = prog; args[3] = 0;
      sig_pipedefault();
      execv(*args,args);
      strerr_die3x(111,"Unable to run /bin/sh: ",error_str(errno),". (#4.3.0)");
@@ -266,16 +429,21 @@
 char **recips;
 {
  struct qmail qqt;
- char *qqx;
+ const char *qqx;
  substdio ss;
  int match;
 
  if (seek_begin(0) == -1) temp_rewind();
- substdio_fdbuf(&ss,read,0,buf,sizeof(buf));
+ substdio_fdbuf(&ss,subread,0,buf,sizeof(buf));
 
  if (qmail_open(&qqt) == -1) temp_fork();
  mailforward_qp = qmail_qp(&qqt);
+
  qmail_put(&qqt,dtline.s,dtline.len);
+
+ if (recips[1])
+   qmail_puts(&qqt,"Precedence: bulk\n");
+
  do
   {
    if (getln(&ss,&messline,&match,'\n') != 0) { qmail_fail(&qqt); break; }
@@ -295,7 +463,7 @@
  substdio ss;
 
  if (seek_begin(0) == -1) temp_rewind();
- substdio_fdbuf(&ss,read,0,buf,sizeof(buf));
+ substdio_fdbuf(&ss,subread,0,buf,sizeof(buf));
  for (;;)
   {
    if (getln(&ss,&messline,&match,'\n') != 0) temp_read();
@@ -316,11 +484,12 @@
    strerr_die3x(111,"Unable to stat home directory: ",error_str(errno),". (#4.3.0)");
  if (st.st_mode & auto_patrn)
    strerr_die1x(111,"Uh-oh: home directory is writable. (#4.7.0)");
- if (st.st_mode & 01000)
+ if (st.st_mode & 01000) {
    if (flagdoit)
      strerr_die1x(111,"Home directory is sticky: user is editing his .qmail file. (#4.2.1)");
    else
      strerr_warn1("Warning: home directory is sticky.",0);
+ }
 }
 
 int qmeox(dashowner)
@@ -380,7 +549,7 @@
 int *fd;
 int *cutable;
 {
-  int i;
+  unsigned int i;
 
   if (!stralloc_copys(&qme,".qmail")) temp_nomem();
   if (!stralloc_cats(&qme,dash)) temp_nomem();
@@ -395,7 +564,8 @@
     return;
   }
 
-  for (i = safeext.len;i >= 0;--i)
+  i = safeext.len;
+  do {
     if (!i || (safeext.s[i - 1] == '-')) {
       if (!stralloc_copys(&qme,".qmail")) temp_nomem();
       if (!stralloc_cats(&qme,dash)) temp_nomem();
@@ -407,6 +577,7 @@
         return;
       }
     }
+  } while (i-- != 0);
 
   *fd = -1;
 }
@@ -437,28 +608,52 @@
 void sayit(type,cmd,len)
 char *type;
 char *cmd;
-int len;
+unsigned int len;
 {
  substdio_puts(subfdoutsmall,type);
  substdio_put(subfdoutsmall,cmd,len);
  substdio_putsflush(subfdoutsmall,"\n");
 }
 
-void main(argc,argv)
+void unescape(char *s)
+{
+  if (!stralloc_copys(&foo, "")) temp_nomem();
+  do {
+    if (s[0] == '\\' && s[1] == ':') s++;
+    else if (s[0] == ':') {
+      if (!stralloc_0(&foo)) temp_nomem();
+      continue;
+    }
+    if (!stralloc_append(&foo, s)) temp_nomem();
+  } while (*s++);
+}
+
+int main(argc,argv)
 int argc;
 char **argv;
 {
  int opt;
- int i;
- int j;
- int k;
+ unsigned int i;
+ unsigned int j;
+ unsigned int k;
  int fd;
- int numforward;
+ unsigned int numforward;
  char **recips;
  datetime_sec starttime;
  int flagforwardonly;
  char *x;
 
+ /* set up the variables for qmail-ldap */
+ unsigned int slen;
+ int qmode;
+ int flagforwardonly2;
+ int flagnoforward;
+ int flagnolocal;
+ int flagnoprog;
+ int allowldapprog;
+ char *s;
+ char *rt;
+
  umask(077);
  sig_pipeignore();
 
@@ -531,7 +726,7 @@
  if (!stralloc_copys(&ufline,"From ")) temp_nomem();
  if (*sender)
   {
-   int len; int i; char ch;
+   unsigned int len; char ch;
 
    len = str_len(sender);
    if (!stralloc_readyplus(&ufline,len)) temp_nomem();
@@ -582,38 +777,168 @@
  if (!stralloc_0(&foo)) temp_nomem();
  if (!env_put2("HOST4",foo.s)) temp_nomem();
 
- flagforwardonly = 0;
- qmesearch(&fd,&flagforwardonly);
- if (fd == -1)
-   if (*dash)
-     strerr_die1x(100,"Sorry, no mailbox here by that name. (#5.1.1)");
-
- if (!stralloc_copys(&ueo,sender)) temp_nomem();
- if (str_diff(sender,""))
-   if (str_diff(sender,"#@[]"))
-     if (qmeox("-owner") == 0)
-      {
-       if (qmeox("-owner-default") == 0)
-	{
-         if (!stralloc_copys(&ueo,local)) temp_nomem();
-         if (!stralloc_cats(&ueo,"-owner-@")) temp_nomem();
-         if (!stralloc_cats(&ueo,host)) temp_nomem();
-         if (!stralloc_cats(&ueo,"-@[]")) temp_nomem();
-	}
-       else
-	{
-         if (!stralloc_copys(&ueo,local)) temp_nomem();
-         if (!stralloc_cats(&ueo,"-owner@")) temp_nomem();
-         if (!stralloc_cats(&ueo,host)) temp_nomem();
-	}
-      }
- if (!stralloc_0(&ueo)) temp_nomem();
- if (!env_put2("NEWSENDER",ueo.s)) temp_nomem();
+ flagforwardonly = 0; flagforwardonly2 = 0; allowldapprog = 0;
+ flagnoforward = 0; flagnolocal = 0; flagnoprog = 0;
 
+ if (env_get(ENV_GROUP)) {
+   if (flagdoit) {
+     ++count_program;
+     if (!stralloc_copys(&foo,"qmail-group ")) temp_nomem();
+     if (*aliasempty == '.' || *aliasempty == '/')
+       if (!stralloc_cats(&foo,aliasempty)) temp_nomem();
+     if (!stralloc_0(&foo)) temp_nomem();
+     mailprogram(foo.s);
+   } else
+     sayit("group delivery","",0);
+   count_print();
+   _exit(0);
+ }
+ /* quota, dotmode and forwarding handling - part 1 */
+ /* setting the quota */
+ if ((quotastring = env_get(ENV_QUOTA) ) && *quotastring) {
+   if (!flagdoit) sayit("quota defined as: ",quotastring,str_len(quotastring));
+ } else {
+   if (!flagdoit) sayit("unlimited quota",quotastring,0 );
+ }
+   
+ qmode = DO_DOT;  /* default is to use standard .qmail */
+ if ((s = env_get(ENV_DOTMODE))) {
+   if (!case_diffs(DOTMODE_LDAPONLY, s)) {
+     if (!flagdoit) sayit("DOTMODE_LDAPONLY ",s,0);
+     qmode = DO_LDAP;
+   } else if (!case_diffs(DOTMODE_LDAPWITHPROG, s)) {
+     if (!flagdoit) sayit("DOTMODE_LDAPWITHPROG ",s,0);
+     qmode = DO_LDAP;
+     allowldapprog = 1;
+   } else if (!case_diffs(DOTMODE_DOTONLY, s)) {
+     if (!flagdoit) sayit("DOTMODE_DOTONLY ",s,0);
+     qmode = DO_DOT;
+   } else if (!case_diffs(DOTMODE_BOTH, s)) {
+     if (!flagdoit) sayit("DOTMODE_BOTH ",s,0);
+     qmode = DO_BOTH;
+     allowldapprog = 1;
+   } else
+     strerr_die3x(100,"Error: Non valid dot-mode found: ", s, ". (#5.3.5)");
+ }
+	   
+ /* prepare the cmds string to hold all the commands from the 
+  * ldap server and the .qmail file */
  if (!stralloc_ready(&cmds,0)) temp_nomem();
  cmds.len = 0;
- if (fd != -1)
-   if (slurpclose(fd,&cmds,256) == -1) temp_nomem();
+ 
+ if (qmode & DO_LDAP) {
+   /* get the infos from the ldap server (environment) */
+   /* setting the NEWSENDER so echo and forward will work */
+   if (!stralloc_copys(&ueo,sender)) temp_nomem();
+   if (!stralloc_0(&ueo)) temp_nomem();
+   if (!env_put2("NEWSENDER",ueo.s)) temp_nomem();
+
+   if ((s = env_get(ENV_MODE))) {
+     unescape(s);
+     s = foo.s;
+     slen = foo.len-1;
+     for(;;) {
+       if (!case_diffs(MODE_FONLY, s)) {
+         if (!flagdoit) sayit("force forward only ",s,0);
+         flagforwardonly2 = 1;
+         flagnolocal = 1;
+         flagnoprog = 1;
+       } else if (!case_diffs(MODE_REPLY, s)) {
+         if(*sender) {
+           if ((rt = env_get(ENV_REPLYTEXT))) {
+	     ++count_forward;
+             if (flagdoit) {
+	       if (!stralloc_copys(&qapp,"qmail-reply ")) temp_nomem();
+	       if (*aliasempty == '.' || *aliasempty == '/')
+	         if (!stralloc_cats(&qapp,aliasempty)) temp_nomem();
+	       if (!stralloc_0(&qapp)) temp_nomem();
+               mailprogram(qapp.s);
+             } else {
+               sayit("reply to ",sender,str_len(sender));
+               sayit("replytext ",rt,str_len(rt));
+             }
+           } else {
+             strerr_warn1("Warning: Reply mode is on but there is no reply text.", 0);
+           }
+         }
+       } else if (!case_diffs(MODE_NOLOCAL, s) || !case_diffs(MODE_NOMBOX, s)) {
+         if (!flagdoit) sayit("no file delivery ",s,0);
+         flagnolocal = 1;
+       } else if (!case_diffs(MODE_NOFORWARD, s)) {
+	 if (!flagdoit) sayit("no mail forwarding ",s,0);
+	 flagnoforward = 1;
+       } else if (!case_diffs(MODE_NOPROG, s)) {
+         if (!flagdoit) sayit("no program delivery ",s,0);
+         flagnoprog = 1;
+       } else if (!case_diffs(MODE_LOCAL, s) ||
+		  !case_diffs(MODE_FORWARD, s) ||
+		  !case_diffs(MODE_PROG, s) ||
+		  !case_diffs(MODE_NOREPLY, s)) {
+	       /* ignore */;
+       } else strerr_warn3("Warning: undefined mail delivery mode: ",
+                     s," (ignored).", 0);
+       j = byte_chr(s,slen,0); if (j++ == slen) break; s += j; slen -= j;
+     }
+   }
+   if (allowldapprog && !flagnoprog && (s = env_get(ENV_PROGRAM))) {
+     unescape(s);
+     s = foo.s;
+     slen = foo.len-1;
+     for (;;) {
+       if (!stralloc_cats(&cmds, "|")) temp_nomem();
+       if (!stralloc_cats(&cmds, s)) temp_nomem();
+       if (!stralloc_cats(&cmds, "\n")) temp_nomem();
+       j = byte_chr(s,slen,0); if (j++ == slen) break; s += j; slen -= j;
+     }
+   }
+   if (!flagnoforward && (s = env_get(ENV_FORWARDS))) {
+     unescape(s);
+     s = foo.s;
+     slen = foo.len-1;
+     for (;;) {
+       if (!stralloc_cats(&cmds, "&")) temp_nomem();
+       if (!stralloc_cats(&cmds, s)) temp_nomem();
+       if (!stralloc_cats(&cmds, "\n")) temp_nomem();
+       j = byte_chr(s,slen,0); if (j++ == slen) break; s += j; slen -= j;
+     }
+   }
+   if (!flagnolocal) {
+     if (!stralloc_cats(&cmds,aliasempty)) temp_nomem();
+     if (!stralloc_cats(&cmds, "\n")) temp_nomem();
+   } 
+   if (!stralloc_cats(&cmds, "#\n")) temp_nomem();
+ } 
+ if (qmode & DO_DOT) { /* start dotqmail */
+   qmesearch(&fd,&flagforwardonly);
+   if (fd == -1)
+     if (*dash)
+       if (qmode == DO_DOT) /* XXX: OK ??? */
+         strerr_die1x(100,"Sorry, no mailbox here by that name. (#5.1.1)");
+
+   if (!stralloc_copys(&ueo,sender)) temp_nomem();
+   if (str_diff(sender,""))
+     if (str_diff(sender,"#@[]"))
+       if (qmeox("-owner") == 0) {
+         if (qmeox("-owner-default") == 0) {
+           if (!stralloc_copys(&ueo,local)) temp_nomem();
+           if (!stralloc_cats(&ueo,"-owner-@")) temp_nomem();
+           if (!stralloc_cats(&ueo,host)) temp_nomem();
+           if (!stralloc_cats(&ueo,"-@[]")) temp_nomem();
+         } else {
+           if (!stralloc_copys(&ueo,local)) temp_nomem();
+           if (!stralloc_cats(&ueo,"-owner@")) temp_nomem();
+           if (!stralloc_cats(&ueo,host)) temp_nomem();
+         }
+       }
+ 
+   if (!stralloc_0(&ueo)) temp_nomem();
+   if (!env_put2("NEWSENDER",ueo.s)) temp_nomem();
+
+   if (fd != -1)
+     if (slurpclose(fd,&cmds,256) == -1) temp_nomem();
+
+ } else if (!qmode & DO_LDAP) /* impossible see dotmode handling */
+   strerr_die1x(100,"Error: No valid delivery mode selected. (#5.3.5)");
 
  if (!cmds.len)
   {
@@ -633,6 +958,8 @@
      i = j + 1;
     }
 
+ if (flagnoforward) numforward = 0;
+ 
  recips = (char **) alloc((numforward + 1) * sizeof(char *));
  if (!recips) temp_nomem();
  numforward = 0;
@@ -645,7 +972,7 @@
     {
      cmds.s[j] = 0;
      k = j;
-     while ((k > i) && (cmds.s[k - 1] == ' ') || (cmds.s[k - 1] == '\t'))
+     while ((k > i) && ((cmds.s[k - 1] == ' ') || (cmds.s[k - 1] == '\t')))
        cmds.s[--k] = 0;
      switch(cmds.s[i])
       {
@@ -656,8 +983,14 @@
          break;
        case '.':
        case '/':
+	 if (flagnolocal) {
+	   if (flagdoit) break;
+	   else { sayit("disabled file delivery ", cmds.s + i, k - i); break; }
+	 }
 	 ++count_file;
 	 if (flagforwardonly) strerr_die1x(111,"Uh-oh: .qmail has file delivery but has x bit set. (#4.7.0)");
+	 if (flagforwardonly2) 
+	   strerr_die1x(111,"Uh-oh: user has file delivery but is not allowed to. (#4.7.0)");
 	 if (cmds.s[k - 1] == '/')
            if (flagdoit) maildir(cmds.s + i);
            else sayit("maildir ",cmds.s + i,k - i);
@@ -666,8 +999,14 @@
            else sayit("mbox ",cmds.s + i,k - i);
          break;
        case '|':
+	 if (flagnoprog) {
+	   if (flagdoit) break;
+	   else { sayit("disabled program ", cmds.s + i, k - i); break; }
+	 }
 	 ++count_program;
 	 if (flagforwardonly) strerr_die1x(111,"Uh-oh: .qmail has prog delivery but has x bit set. (#4.7.0)");
+	 if (flagforwardonly2)
+	   strerr_die1x(111,"Uh-oh: user has prog delivery but is not allowed to. (#4.7.0)");
          if (flagdoit) mailprogram(cmds.s + i + 1);
          else sayit("program ",cmds.s + i + 1,k - i - 1);
          break;
@@ -679,6 +1018,10 @@
          ++i;
        default:
 	 ++count_forward;
+	 if (flagnoforward) {
+	   if (flagdoit) break;
+	   else { sayit("disabled forward ", cmds.s + i, k - i); break; }
+	 }
          if (flagdoit) recips[numforward++] = cmds.s + i;
          else sayit("forward ",cmds.s + i,k - i);
          break;
@@ -687,12 +1030,12 @@
      if (flag99) break;
     }
 
- if (numforward) if (flagdoit)
+ if (numforward) if (flagdoit) if (!flagnoforward)
   {
    recips[numforward] = 0;
    mailforward(recips);
   }
 
  count_print();
- _exit(0);
+ return 0;
 }
diff -ruN qmail-1.03-orig/qmail-lspawn.c qmail-1.03-ldap-20060201-orig/qmail-lspawn.c
--- qmail-1.03-orig/qmail-lspawn.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/qmail-lspawn.c	2006-02-25 11:00:55.000000000 +0100
@@ -14,76 +14,615 @@
 #include "auto_uids.h"
 #include "qlx.h"
 
-char *aliasempty;
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <pwd.h>
+#include <unistd.h>
+#include "auto_break.h"
+#include "auto_usera.h"
+#include "byte.h"
+#include "check.h"
+#include "env.h"
+#include "fmt.h"
+#include "localdelivery.h"
+#include "open.h"
+#include "qldap.h"
+#include "qldap-debug.h"
+#include "qldap-errno.h"
+#include "qmail-ldap.h"
+#include "read-ctrl.h"
+#include "sig.h"
+#include "str.h"
+#ifdef QLDAP_CLUSTER
+#include "qldap-cluster.h"
+#include "getln.h"
+#include "seek.h"
+#endif
+#ifdef AUTOHOMEDIRMAKE
+#include "dirmaker.h"
+#endif
+
+const char *aliasempty;
+
+#ifdef QLDAP_CLUSTER
+/* declaration of the mail forwarder function */
+void forward_mail(char *, char *, char *, int , int);
+#endif
 
+#ifdef AUTOHOMEDIRMAKE
+void check_home(const char *home, const char *maildir)
+{
+  struct stat	st;
+
+  if (stat(home, &st) == 0) return;
+  if (errno == error_noent)
+    switch (dirmaker_make(home, maildir)) {
+    case 0:
+      break;
+    case ERRNO:
+     if (error_temp(errno)) _exit(QLX_DIRMAKESOFT);
+     _exit(QLX_DIRMAKEHARD);
+    case MAILDIR_CRASHED:
+      _exit(QLX_DIRMAKECRASH);
+    case MAILDIR_HARD:
+      _exit(QLX_DIRMAKEHARD);
+    case MAILDIR_UNCONF:
+      /* qmail-local will return a nice error */
+      break;
+    default:
+      _exit(QLX_DIRMAKESOFT);
+    }
+}
+#endif
+
+ctrlfunc ctrls[] = {
+  qldap_ctrl_login,
+  qldap_ctrl_generic,
+  localdelivery_init,
+#ifdef QLDAP_CLUSTER
+  cluster_init,
+#endif
+#ifdef AUTOHOMEDIRMAKE
+  dirmaker_init,
+#endif		
+  0
+};
+
+/* here it is not possible to log something */
 void initialize(argc,argv)
 int argc;
 char **argv;
 {
-  aliasempty = argv[1];
-  if (!aliasempty) _exit(100);
+   aliasempty = argv[1];
+   if (!aliasempty) {
+      _exit(100);
+   }
+   
+  if (read_controls(ctrls) == -1)
+    _exit(QLX_USAGE);
+
 }
 
-int truncreport = 3000;
+unsigned int truncreport = 3000;
 
 void report(ss,wstat,s,len)
 substdio *ss;
 int wstat;
 char *s;
-int len;
+unsigned int len;
 {
- int i;
- if (wait_crashed(wstat))
-  { substdio_puts(ss,"Zqmail-local crashed.\n"); return; }
- switch(wait_exitcode(wstat))
-  {
+   unsigned int i;
+   if (wait_crashed(wstat)) {
+      substdio_puts(ss,"Zqmail-local crashed.\n");
+      return;
+   }
+   switch(wait_exitcode(wstat)) {
    case QLX_CDB:
-     substdio_puts(ss,"ZTrouble reading users/cdb in qmail-lspawn.\n"); return;
+     substdio_puts(ss,"ZTrouble reading users/cdb in qmail-lspawn.\n");
+     return;
    case QLX_NOMEM:
-     substdio_puts(ss,"ZOut of memory in qmail-lspawn.\n"); return;
+     substdio_puts(ss,"ZOut of memory in qmail-lspawn.\n");
+     return;
    case QLX_SYS:
-     substdio_puts(ss,"ZTemporary failure in qmail-lspawn.\n"); return;
+     substdio_puts(ss,"ZTemporary failure in qmail-lspawn.\n");
+     return;
    case QLX_NOALIAS:
-     substdio_puts(ss,"ZUnable to find alias user!\n"); return;
+     substdio_puts(ss,"ZUnable to find alias user!\n");
+     return;
    case QLX_ROOT:
-     substdio_puts(ss,"ZNot allowed to perform deliveries as root.\n"); return;
+     substdio_puts(ss,"ZNot allowed to perform deliveries as root.\n");
+     return;
    case QLX_USAGE:
-     substdio_puts(ss,"ZInternal qmail-lspawn bug.\n"); return;
+     substdio_puts(ss,"ZInternal qmail-lspawn bug.\n");
+     return;
    case QLX_NFS:
-     substdio_puts(ss,"ZNFS failure in qmail-local.\n"); return;
+     substdio_puts(ss,"ZNFS failure in qmail-local.\n");
+     return;
    case QLX_EXECHARD:
-     substdio_puts(ss,"DUnable to run qmail-local.\n"); return;
+     substdio_puts(ss,"DUnable to run qmail-local.\n");
+     return;
    case QLX_EXECSOFT:
-     substdio_puts(ss,"ZUnable to run qmail-local.\n"); return;
+     substdio_puts(ss,"ZUnable to run qmail-local.\n");
+     return;
    case QLX_EXECPW:
-     substdio_puts(ss,"ZUnable to run qmail-getpw.\n"); return;
+     substdio_puts(ss,"ZUnable to run qmail-getpw.\n");
+     return;
    case 111: case 71: case 74: case 75:
-     substdio_put(ss,"Z",1); break;
+     substdio_put(ss,"Z",1);
+     break;
    case 0:
-     substdio_put(ss,"K",1); break;
+     substdio_put(ss,"K",1);
+     break;
+      
+   /* report LDAP errors */
+   case QLX_DISABLED:
+     substdio_puts(ss, "DMailaddress is administratively disabled. (#5.2.1)\n");
+     return;
+   case QLX_DELETED:
+     substdio_puts(ss, "DSorry, no mailbox here by that name. (#5.1.1)\n");
+     return;
+   case QLX_MAXSIZE:
+     substdio_puts(ss, "DThe message exeeded the maximum size the user accepts. (#5.2.3)\n");
+     return;
+   case QLX_LDAPFAIL:
+     substdio_puts(ss, "ZTemporary failure in LDAP lookup. (#4.4.3).\n");
+     return;
+   case QLX_LDAPAUTH:
+     substdio_puts(ss, "ZUnable to login into LDAP server, bad credentials. (#4.4.3)\n");
+     return;
+   case QLX_SEARCHTIMEOUT:
+     substdio_puts(ss, "ZTimeout while performing search on LDAP server. (#4.4.3)");
+     return;
+   case QLX_BINDTIMEOUT:
+     substdio_puts(ss, "ZUnable to contact LDAP server. (#4.4.3)");
+     return;
+   case QLX_TOOMANY:
+     substdio_puts(ss, "DToo many results returned but needs to be unique. (#5.3.5)\n");
+     return;
+   case QLX_NEEDED:
+     substdio_puts(ss, "DLDAP attribute is not given but mandatory. (#5.3.5)\n");
+     return;
+   case QLX_ILLVAL:
+     substdio_puts(ss, "DIllegal value in LDAP attribute. (#5.3.5)\n");
+     return;
+#ifdef QLDAP_CLUSTER
+   case QLX_CLUSTERSOFT:
+     substdio_puts(ss, "ZTemporary error while executing qmail-forward. (#4.4.4)\n");
+     return;
+   case QLX_CLUSTERHARD:
+     substdio_puts(ss, "DPermanent error while executing qmail-forward. (#5.4.4)\n");
+     return;
+#endif /* QLDAP_CLUSTER */
+#ifdef AUTOHOMEDIRMAKE
+   case QLX_DIRMAKECRASH:
+     substdio_puts(ss, "ZAutomatic homedir creator crashed (#4.3.0)\n");
+     return;
+   case QLX_DIRMAKESOFT:
+     substdio_puts(ss, "ZTemporary error in automatic homedir creation. (#4.3.0)\n");
+     return;
+   case QLX_DIRMAKEHARD:
+     substdio_puts(ss, "DPermanent error in automatic homedir creation. (#5.3.0)\n");
+     return;
+#endif
+
    case 100:
    default:
-     substdio_put(ss,"D",1); break;
+     substdio_put(ss,"D",1);
+     break;
   }
 
- for (i = 0;i < len;++i) if (!s[i]) break;
- substdio_put(ss,s,i);
+  for (i = 0;i < len;++i) if (!s[i]) break;
+  substdio_put(ss,s,i);
 }
 
-stralloc lower = {0};
 stralloc nughde = {0};
+stralloc host = {0};
+stralloc user = {0};
+stralloc homedir = {0};
+stralloc maildir = {0};
+stralloc foo = {0}; /* stralloc for temporary stuff */
+
+/* LDAP server query routines */
+
+void cae(qldap *q, int n)
+{
+  qldap_free(q);
+  _exit(n);
+}
+
+int qldap_get(stralloc *mail, unsigned int at, int fdmess)
+{
+   const char *attrs[] = {  /* LDAP_MAIL, */ /* not needed */
+                      /* LDAP_MAILALTERNATE, */
+                      LDAP_UID,
+                      LDAP_QMAILUID,
+                      LDAP_QMAILGID,
+                      LDAP_ISACTIVE,
+                      LDAP_MAILHOST,
+                      LDAP_MAILSTORE,
+                      LDAP_HOMEDIR,
+		      LDAP_QUOTA_SIZE,
+		      LDAP_QUOTA_COUNT,
+                      LDAP_FORWARDS,
+                      LDAP_PROGRAM,
+                      LDAP_MODE,
+                      LDAP_REPLYTEXT,
+                      LDAP_DOTMODE, 
+		      LDAP_MAXMSIZE,
+		      LDAP_OBJECTCLASS, 0};
+   char num[FMT_ULONG];
+   char *f;
+   struct passwd *pw;
+   struct qldap *q;
+   struct stat st;
+   unsigned long count;
+   unsigned long maxsize;
+   unsigned long size;
+   unsigned int len;
+   unsigned int id;
+   int done;
+   int status;
+   int rv;
+
+   /* TODO more debug output is needed */
+   q = qldap_new();
+   if (q == 0)
+     _exit(QLX_NOMEM);
+
+   rv = qldap_open(q);
+   if (rv != OK) goto fail;
+   rv = qldap_bind(q, 0, 0);
+   if (rv != OK) goto fail;
+
+   /*
+    * this handles the "catch all" and "-default" extension 
+    * but also the normal eMail address.
+    * Code handels also mail addresses with multiple '@' safely.
+    * at = index to last @ sign in mail address
+    * escaped = ldap escaped mailaddress
+    * len = length of escaped mailaddress
+    * i = position of current '-' or '@'
+    */
+   done = 0;
+   do {
+     f = filter_mail(mail->s, &done);
+     if (f == (char *)0) cae(q, QLX_NOMEM);
+     
+     logit(16, "ldapfilter: '%s'\n", f);
+  
+     /* do the search for the email address */
+     rv = qldap_lookup(q, f, attrs);
+     switch (rv) {
+     case OK:
+       break; /* something found */
+     case TIMEOUT:
+       /* don't try an other address, retry later, hopefully ... */
+       cae(q, QLX_SEARCHTIMEOUT);
+     case TOOMANY:
+#ifdef DUPEALIAS
+       /*
+        * we are going to deliver this to a special alias user for
+        * further processing
+        */
+       qldap_free(q);
+       return 3;
+#else
+       /* admin error, don't try a lower precedence addresses */
+       cae(q, QLX_TOOMANY);
+#endif
+     case FAILED:
+       /* ... again do not retry lower precedence addresses */
+       cae(q, QLX_LDAPFAIL);
+     case NOSUCH:
+       break;
+     }
+   } while (rv != OK && !done);
+
+   /* nothing found, try a local lookup or a alias delivery */
+   if (rv == NOSUCH) {
+     qldap_free(q);
+     return 1;
+   }
+
+   
+   /*
+    * Search was successful.
+    * Now go through the attributes and set the proper args for qmail-local.
+    * But first check account status, the mail size and forward the message
+    * to the correct cluster host if needed.
+    *
+    */
+
+   
+   /* check if the ldap entry is active */
+   rv = qldap_get_status(q, &status);
+   if (rv != OK) goto fail;
+   if (status == STATUS_BOUNCE) {
+     logit(2, "warning: %s's account status is bounce\n", mail->s);
+     cae(q, QLX_DISABLED); 
+   } else if (status == STATUS_DELETE) {
+     logit(2, "warning: %s's account status is deleted\n", mail->s);
+     cae(q, QLX_DELETED); 
+   }
+
+   /* get the quota for the user of that maildir mbox */
+   rv = qldap_get_quota(q, &size, &count, &maxsize);
+   if (rv != OK) goto fail;
+   /* check if incomming mail is smaller than max mail size */
+   if (maxsize != 0) {
+     if (fstat(fdmess, &st) != 0) {
+       logit(2, "warning: can not stat mail: %s\n", error_str(errno));
+       cae(q, QLX_SYS);
+     }
+     if ((unsigned long)st.st_size > maxsize) {
+       cae(q, QLX_MAXSIZE);
+     }
+   }
+  
+#ifdef QLDAP_CLUSTER
+   rv = qldap_get_attr(q, LDAP_MAILHOST, &host, SINGLE_VALUE);
+   if (rv != OK && rv != NOSUCH) goto fail;
+
+   /* check if the I'm the right host */
+   if (rv == OK && cluster(host.s) == 1) {
+     logit(8, "cluster: forwarding session to %s\n", host.s);
+     /* hostname is different, so I reconnect */
+     return 2;
+   }
+#endif
+
+   /* get the path of the maildir or mbox */
+   rv = qldap_get_mailstore(q, &homedir, &maildir);
+   switch (rv) {
+   case OK:
+     if (maildir.len > 0)
+       aliasempty = maildir.s;
+     break;
+   case NEEDED:
+     /*
+      * nothing defined use alias user for delivery and 
+      * ALIASDEVNULL as aliasempty
+      */
+     logit(32, "forward only delivery via alias user\n");
+     pw = getpwnam(auto_usera);
+     if (!pw) cae(q, QLX_NOALIAS);
+     if (!stralloc_copys(&nughde, pw->pw_name)) cae(q, QLX_NOMEM);
+     if (!stralloc_0(&nughde)) cae(q, QLX_NOMEM);
+     if (!stralloc_catb(&nughde,num,fmt_uint(num, pw->pw_uid))) 
+       cae(q, QLX_NOMEM);
+     if (!stralloc_0(&nughde)) cae(q, QLX_NOMEM);
+     if (!stralloc_catb(&nughde,num,fmt_uint(num, pw->pw_gid))) 
+       cae(q, QLX_NOMEM);
+     if (!stralloc_0(&nughde)) cae(q, QLX_NOMEM);
+     if (!stralloc_cats(&nughde, pw->pw_dir)) cae(q, QLX_NOMEM); 
+     if (!stralloc_0(&nughde)) cae(q, QLX_NOMEM);
+     if (!stralloc_cats(&nughde, "-")) cae(q, QLX_NOMEM);
+     if (!stralloc_0(&nughde)) cae(q, QLX_NOMEM);
+     if (!stralloc_catb(&nughde, mail->s, at)) cae(q, QLX_NOMEM);
+     if (!stralloc_0(&nughde)) cae(q, QLX_NOMEM);
+     aliasempty = ALIASDEVNULL;
+     /* get the forwarding addresses */
+     rv = qldap_get_attr(q, LDAP_FORWARDS, &foo, MULTI_VALUE);
+     if (rv != OK) goto fail;
+     if (!env_put2(ENV_FORWARDS, foo.s)) cae(q, QLX_NOMEM);
+     logit(32, "%s: %s\n", ENV_FORWARDS, foo.s);
+     /* setup strict env */
+     if (!env_put2(ENV_DOTMODE, DOTMODE_LDAPONLY)) _exit(QLX_NOMEM);
+     if (!env_put2(ENV_MODE, MODE_FONLY)) _exit(QLX_NOMEM);
+     qldap_free(q);
+     return 0;
+   default:
+     goto fail;
+   }
+
+   /* get the user name */
+   rv = qldap_get_user(q, &user);
+   if (rv != OK) goto fail;
+   if (!stralloc_copy(&nughde, &user)) _exit(QLX_NOMEM);
+
+   /* get the UID for delivery on the local system */
+   rv = qldap_get_uid(q, &id);
+   if (rv != OK) goto fail;
+   if (!stralloc_catb(&nughde,num,fmt_uint(num, id))) 
+     cae(q, QLX_NOMEM);
+   if (!stralloc_0(&nughde)) cae(q, QLX_NOMEM);
+
+   
+   /* get the GID for delivery on the local system */
+   rv = qldap_get_gid(q, &id);
+   if (rv != OK) goto fail;
+   if (!stralloc_catb(&nughde,num,fmt_uint(num, id))) 
+     cae(q, QLX_NOMEM);
+   if (!stralloc_0(&nughde)) cae(q, QLX_NOMEM);
+
+   /* homedir saved earlier */
+   if (!stralloc_cat(&nughde, &homedir)) cae(q, QLX_NOMEM);
+
+   /*
+    *  Fill up the dash-field and the extension field with the values
+    * used for the dash-ext search.
+    */
+   rv = filter_mail_ext();
+   if (rv != -1)
+     if (!stralloc_cats(&nughde,"-")) cae(q, QLX_NOMEM);
+   if (!stralloc_0(&nughde)) cae(q, QLX_NOMEM);
+   if (rv != -1) {
+     unsigned int ext;
+     int i;
+     for (ext = 0, i = 0; i < rv && ext < at; ext++)
+       if (mail->s[ext] == *auto_break) i++;
+     if (!stralloc_catb(&nughde, mail->s+ext,at-ext)) cae(q, QLX_NOMEM);
+   }
+   if (!stralloc_0(&nughde)) cae(q, QLX_NOMEM);
+
+   /*
+    * nughde is filled now setup the environment, with:
+    * quota string (already done while checking mail size)
+    * mail group handling
+    * mail forwarders
+    * delivery programs
+    * reply text
+    * delivery mode
+    * dot mode
+    */
+
+   rv = qldap_get_attr(q, LDAP_OBJECTCLASS, &foo, MULTI_VALUE);
+   if (rv != OK) goto fail; /* objectclass is a must */
+   if (!env_unset(ENV_GROUP)) cae(q, QLX_NOMEM);
+   for (len = 0; len < foo.len;
+        len += byte_chr(foo.s + len, foo.len - len, ':') + 1) {
+     if (case_startb(foo.s + len, foo.len - len, LDAP_GROUPOBJECTCLASS)) {
+       rv = qldap_get_dn(q, &foo);
+       if (rv != OK) goto fail;
+       logit(32, "%s: %s\n", ENV_GROUP, foo.s);
+       if (!env_put2(ENV_GROUP, foo.s )) cae(q, QLX_NOMEM);
+       break;
+     }
+   }
+
+   /*
+    * set the quota environment
+    */
+   if (size != 0 || count != 0) {
+     if (!stralloc_copys(&foo, "")) cae(q, QLX_NOMEM);
+     if (size != 0) {
+       if (!stralloc_catb(&foo, num, fmt_ulong(num, size))) cae(q, QLX_NOMEM);
+       if (!stralloc_append(&foo, "S")) cae(q, QLX_NOMEM);
+     }
+     if (count != 0) {
+       if (size != 0)
+	 if (!stralloc_append(&foo, ",")) cae(q, QLX_NOMEM);
+       if (!stralloc_catb(&foo, num, fmt_ulong(num, count))) cae(q, QLX_NOMEM);
+       if (!stralloc_append(&foo, "C")) cae(q, QLX_NOMEM);
+     }
+     if (!stralloc_0(&foo)) cae(q, QLX_NOMEM);
+     logit(32, "%s: %s\n", ENV_QUOTA, foo.s);
+     if (!env_put2(ENV_QUOTA, foo.s )) cae(q, QLX_NOMEM);
+   } else {
+     logit(32, "no quota set\n");
+     if (!env_unset(ENV_QUOTA)) cae(q, QLX_NOMEM);
+   }
+   
+   /*
+    * get the forwarding addresses and build a list
+    * equals to &jdoe@heaven.af.mil in .qmail
+    */
+   rv = qldap_get_attr(q, LDAP_FORWARDS, &foo, MULTI_VALUE);
+   switch (rv) {
+   case OK:
+     logit(32, "%s: %s\n", ENV_FORWARDS, foo.s);
+     if (!env_put2(ENV_FORWARDS, foo.s)) cae(q, QLX_NOMEM);
+     break;
+   case NOSUCH:
+     if (!env_unset(ENV_FORWARDS)) cae(q, QLX_NOMEM);
+     break;
+   default:
+     goto fail;
+   }
+
+   /*
+    * get the path of the local delivery program
+    * equals to |/usr/bin/program in .qmail
+    */
+   rv = qldap_get_attr(q, LDAP_PROGRAM, &foo, MULTI_VALUE);
+   switch (rv) {
+   case OK:
+     logit(32, "%s: %s\n", ENV_PROGRAM, foo.s);
+     if (check_progs(foo.s) == 0) cae(q, QLX_ILLVAL);
+     if (!env_put2(ENV_PROGRAM, foo.s)) cae(q, QLX_NOMEM);
+     break;
+   case NOSUCH:
+     if (!env_unset(ENV_PROGRAM)) cae(q, QLX_NOMEM);
+     break;
+   default:
+     goto fail;
+   }
+
+   /*
+    * prefetch the reply text so we can remove it if no deliverymode
+    * is set.
+    */
+   rv = qldap_get_attr(q, LDAP_REPLYTEXT, &foo, SINGLE_VALUE);
+   switch (rv) {
+   case OK:
+     logit(32, "%s: %s\n", ENV_REPLYTEXT, foo.s);
+     if (!env_put2(ENV_REPLYTEXT, foo.s)) cae(q, QLX_NOMEM);
+     break;
+   case NOSUCH:
+     if (!env_unset(ENV_REPLYTEXT)) cae(q, QLX_NOMEM);
+     break;
+   default:
+     goto fail;
+   }
+
+   /*
+    * get the deliverymode of the mailbox:
+    * reply, noprogram, noforward, nolocal (nombox)
+    */
+   rv = qldap_get_attr(q, LDAP_MODE, &foo, MULTI_VALUE);
+   switch (rv) {
+   case OK:
+     case_lowers(foo.s);
+     logit(32, "%s: %s\n", ENV_MODE, foo.s);
+     if (!env_put2(ENV_MODE, foo.s)) cae(q, QLX_NOMEM);
+     break;
+   case NOSUCH:
+     if (!env_unset(ENV_MODE)) cae(q, QLX_NOMEM);
+     if (!env_unset(ENV_REPLYTEXT)) cae(q, QLX_NOMEM);
+     break;
+   default:
+     goto fail;
+   }
+
+   /* get the mode of the .qmail interpretion: ldaponly, dotonly, both, none */
+   rv = qldap_get_dotmode(q, &foo);
+   if (rv != OK) goto fail;
+   logit(32, "%s: %s\n", ENV_DOTMODE, foo.s);
+   if (!env_put2(ENV_DOTMODE, foo.s)) cae(q, QLX_NOMEM);
+
+   /* ok, we finished, lets clean up and disconnect from the LDAP server */
+   qldap_free(q);
+   return 0;
+
+fail:
+   switch (rv) {
+   case LDAP_BIND_UNREACH:
+     cae(q, QLX_BINDTIMEOUT);
+   case LDAP_BIND_AUTH:
+     cae(q, QLX_LDAPAUTH);
+   case NOSUCH:
+   case NEEDED:
+     cae(q, QLX_NEEDED);
+   case BADVAL:
+   case ILLVAL:
+     cae(q, QLX_ILLVAL);
+   case ERRNO:
+     /* in most cases this error was a due to missing resources */
+     cae(q, QLX_NOMEM);
+   case TOOMANY:
+     cae(q, QLX_TOOMANY);
+   default:
+     cae(q, QLX_LDAPFAIL);
+   }
+   /* NOTREACHED */
+   return -1;
+}
+/* end -- LDAP server query routines */
+
+stralloc lower = {0};
 stralloc wildchars = {0};
+struct cdb cdb;
 
 void nughde_get(local)
 char *local;
 {
  char *(args[3]);
- int pi[2];
- int gpwpid;
- int gpwstat;
- int r;
- int fd;
- int flagwild;
+ int	pi[2],
+	gpwpid,
+	gpwstat,
+	r,
+	fd,
+	flagwild;
 
  if (!stralloc_copys(&lower,"!")) _exit(QLX_NOMEM);
  if (!stralloc_cats(&lower,local)) _exit(QLX_NOMEM);
@@ -102,11 +641,12 @@
    uint32 dlen;
    unsigned int i;
 
-   r = cdb_seek(fd,"",0,&dlen);
+   cdb_init(&cdb, fd);
+   r = cdb_seek(&cdb,"",0,&dlen);
    if (r != 1) _exit(QLX_CDB);
    if (!stralloc_ready(&wildchars,(unsigned int) dlen)) _exit(QLX_NOMEM);
    wildchars.len = dlen;
-   if (cdb_bread(fd,wildchars.s,wildchars.len) == -1) _exit(QLX_CDB);
+   if (cdb_bread(&cdb,wildchars.s,wildchars.len) == -1) _exit(QLX_CDB);
 
    i = lower.len;
    flagwild = 0;
@@ -116,16 +656,17 @@
      /* i > 0 */
      if (!flagwild || (i == 1) || (byte_chr(wildchars.s,wildchars.len,lower.s[i - 1]) < wildchars.len))
       {
-       r = cdb_seek(fd,lower.s,i,&dlen);
+       r = cdb_seek(&cdb,lower.s,i,&dlen);
        if (r == -1) _exit(QLX_CDB);
        if (r == 1)
         {
          if (!stralloc_ready(&nughde,(unsigned int) dlen)) _exit(QLX_NOMEM);
          nughde.len = dlen;
-         if (cdb_bread(fd,nughde.s,nughde.len) == -1) _exit(QLX_CDB);
+         if (cdb_bread(&cdb,nughde.s,nughde.len) == -1) _exit(QLX_CDB);
          if (flagwild)
 	   if (!stralloc_cats(&nughde,local + i - 1)) _exit(QLX_NOMEM);
          if (!stralloc_0(&nughde)) _exit(QLX_NOMEM);
+	 cdb_free(&cdb);
          close(fd);
          return;
         }
@@ -139,7 +680,7 @@
   }
 
  if (pipe(pi) == -1) _exit(QLX_SYS);
- args[0] = "bin/qmail-getpw";
+ args[0] = (char *)"bin/qmail-getpw";
  args[1] = local;
  args[2] = 0;
  switch(gpwpid = vfork())
@@ -165,34 +706,124 @@
   }
 }
 
+stralloc ra = {0};
+
 int spawn(fdmess,fdout,s,r,at)
 int fdmess; int fdout;
-char *s; char *r; int at;
+char *s; char *r; unsigned int at;
 {
  int f;
 
  if (!(f = fork()))
   {
    char *(args[11]);
-   unsigned long u;
-   int n;
-   int uid;
-   int gid;
    char *x;
+   unsigned long u;
    unsigned int xlen;
+   unsigned int n;
+   unsigned int uid;
+   unsigned int gid;
+   int rv;
    
+   log_init(fdout, -1, 1);
+
+   sig_hangupdefault(); /* clear the hup sig handler for the child */
+
+   /* copy the whole email address before the @ gets destroyed */
+   if (!stralloc_copys(&ra,r)) _exit(QLX_NOMEM);
+   if (!stralloc_0(&ra)) _exit(QLX_NOMEM);
+   logit(16, "mailaddr: %S\n", &ra);
+
    r[at] = 0;
    if (!r[0]) _exit(0); /* <> */
 
    if (chdir(auto_qmail) == -1) _exit(QLX_USAGE);
 
-   nughde_get(r);
+   /* do the address lookup */
+   rv = qldap_get(&ra, at, fdmess);
+   switch (rv) {
+   case 0:
+     logit(16, "LDAP lookup succeeded\n");
+     break;
+   case 1:
+     if (!stralloc_copys(&nughde,"")) _exit(QLX_NOMEM);
+     if (localdelivery()) {
+       /*
+	* Do the local address lookup.
+        * This is the standart qmail lookup funktion.
+	*/
+       logit(4, "LDAP lookup failed, using local db\n");
+       nughde_get(r);
+     } else {
+       /* the alias-user handling for LDAP only mode */
+       struct passwd *pw;
+       char num[FMT_ULONG];
+
+       logit(4, "LDAP lookup failed, using alias (no local db)\n");
+       pw = getpwnam(auto_usera);
+       if (!pw) _exit(QLX_NOALIAS);
+
+       if (!stralloc_copys(&nughde, pw->pw_name)) _exit(QLX_NOMEM);
+       if (!stralloc_0(&nughde)) _exit(QLX_NOMEM);
+       if (!stralloc_catb(&nughde,num,fmt_uint(num, pw->pw_uid))) 
+	 _exit(QLX_NOMEM);
+       if (!stralloc_0(&nughde)) _exit(QLX_NOMEM);
+       if (!stralloc_catb(&nughde,num,fmt_uint(num, pw->pw_gid))) 
+	 _exit(QLX_NOMEM);
+       if (!stralloc_0(&nughde)) _exit(QLX_NOMEM);
+       if (!stralloc_cats(&nughde, pw->pw_dir)) _exit(QLX_NOMEM); 
+       if (!stralloc_0(&nughde)) _exit(QLX_NOMEM);
+       if (!stralloc_cats(&nughde,"-")) _exit(QLX_NOMEM);
+       if (!stralloc_0(&nughde)) _exit(QLX_NOMEM);
+       if (!stralloc_cats(&nughde,r)) _exit(QLX_NOMEM);
+       if (!stralloc_0(&nughde)) _exit(QLX_NOMEM);
+     }
+     break;
+#ifdef QLDAP_CLUSTER
+   case 2:
+     /* hostname is different, so I reconnect */
+     forward_mail(host.s, ra.s, s, fdmess, fdout);
+     /* that's it. Function does not return */
+#endif
+#ifdef DUPEALIAS
+   case 3:
+     /* the alias-user handling for dupe handling */
+     {
+       struct passwd *pw;
+       char num[FMT_ULONG];
+
+       logit(4, "LDAP lookup got too many hits, using dupe alias\n");
+       pw = getpwnam("dupealias");
+       if (!pw) _exit(QLX_NOALIAS);
+
+       if (!stralloc_copys(&nughde, pw->pw_name)) _exit(QLX_NOMEM);
+       if (!stralloc_0(&nughde)) _exit(QLX_NOMEM);
+       if (!stralloc_catb(&nughde,num,fmt_uint(num, pw->pw_uid)))
+	 _exit(QLX_NOMEM);
+       if (!stralloc_0(&nughde)) _exit(QLX_NOMEM);
+       if (!stralloc_catb(&nughde,num,fmt_uint(num, pw->pw_gid)))
+	 _exit(QLX_NOMEM);
+       if (!stralloc_0(&nughde)) _exit(QLX_NOMEM);
+       if (!stralloc_cats(&nughde, pw->pw_dir)) _exit(QLX_NOMEM);
+       if (!stralloc_0(&nughde)) _exit(QLX_NOMEM);
+       if (!stralloc_cats(&nughde,"-")) _exit(QLX_NOMEM);
+       if (!stralloc_0(&nughde)) _exit(QLX_NOMEM);
+       if (!stralloc_cats(&nughde,r)) _exit(QLX_NOMEM);
+       if (!stralloc_0(&nughde)) _exit(QLX_NOMEM);
+     }
+     break;
+#endif
+   default:
+     logit(2, "warning: ldap lookup freaky return value (%i)\n", rv);
+     _exit(QLX_USAGE);
+     break;
+   } /* end switch */
 
    x = nughde.s;
    xlen = nughde.len;
 
-   args[0] = "bin/qmail-local";
-   args[1] = "--";
+   args[0] = (char *)"bin/qmail-local";
+   args[1] = (char *)"--";
    args[2] = x;
    n = byte_chr(x,xlen,0); if (n++ == xlen) _exit(QLX_USAGE); x += n; xlen -= n;
 
@@ -216,9 +847,13 @@
 
    args[7] = r + at + 1;
    args[8] = s;
-   args[9] = aliasempty;
+   args[9] = (char *)aliasempty;
    args[10] = 0;
 
+   logit(8, "executing 'qmail-local -- %s %s %s %s %s %s %s %s' under uid=%u, gid=%u\n",
+    args[2], args[3], args[4], args[5], args[6], args[7],
+    args[8], args[9], uid, gid);
+
    if (fd_move(0,fdmess) == -1) _exit(QLX_SYS);
    if (fd_move(1,fdout) == -1) _exit(QLX_SYS);
    if (fd_copy(2,1) == -1) _exit(QLX_SYS);
@@ -226,9 +861,42 @@
    if (prot_uid(uid) == -1) _exit(QLX_USAGE);
    if (!getuid()) _exit(QLX_ROOT);
 
+#ifdef AUTOHOMEDIRMAKE
+   check_home(args[3], aliasempty);
+#endif
+
    execv(*args,args);
    if (error_temp(errno)) _exit(QLX_EXECSOFT);
    _exit(QLX_EXECHARD);
   }
  return f;
 }
+
+#ifdef QLDAP_CLUSTER
+
+void forward_mail(char *remote, char *to, char *from, int fdmess, int fdout)
+{
+  char *(args[5]);
+
+  logit(8, "Forwarding to %s at host %s from %s ", to, remote, from);
+
+  if (fd_move(0,fdmess) == -1) _exit(QLX_SYS);
+  if (fd_move(1,fdout) == -1) _exit(QLX_SYS);
+  if (fd_copy(2,1) == -1) _exit(QLX_SYS);
+  if (prot_gid(auto_uida) == -1) _exit(QLX_USAGE);
+  if (prot_uid(auto_gidn) == -1) _exit(QLX_USAGE);
+  if (!getuid()) _exit(QLX_ROOT);
+
+  args[0] = (char *)"bin/qmail-forward";
+  args[1] = remote;
+  args[2] = from;
+  args[3] = to;
+  args[4] = 0;
+
+  execv(*args,args);
+  if (error_temp(errno)) _exit(QLX_CLUSTERSOFT);
+  _exit(QLX_CLUSTERHARD);
+}
+
+#endif
+
diff -ruN qmail-1.03-orig/qmail-newmrh.c qmail-1.03-ldap-20060201-orig/qmail-newmrh.c
--- qmail-1.03-orig/qmail-newmrh.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/qmail-newmrh.c	2006-02-25 11:00:55.000000000 +0100
@@ -1,3 +1,7 @@
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <unistd.h>
 #include "strerr.h"
 #include "stralloc.h"
 #include "substdio.h"
@@ -6,7 +10,8 @@
 #include "readwrite.h"
 #include "open.h"
 #include "auto_qmail.h"
-#include "cdbmss.h"
+#include "cdb_make.h"
+#include "case.h"
 
 #define FATAL "qmail-newmrh: fatal: "
 
@@ -25,11 +30,11 @@
 int fd;
 int fdtemp;
 
-struct cdbmss cdbmss;
+struct cdb_make cdbm;
 stralloc line = {0};
 int match;
 
-void main()
+int main()
 {
   umask(033);
   if (chdir(auto_qmail) == -1)
@@ -38,12 +43,12 @@
   fd = open_read("control/morercpthosts");
   if (fd == -1) die_read();
 
-  substdio_fdbuf(&ssin,read,fd,inbuf,sizeof inbuf);
+  substdio_fdbuf(&ssin,subread,fd,inbuf,sizeof inbuf);
 
   fdtemp = open_trunc("control/morercpthosts.tmp");
   if (fdtemp == -1) die_write();
 
-  if (cdbmss_start(&cdbmss,fdtemp) == -1) die_write();
+  if (cdb_make_start(&cdbm,fdtemp) == -1) die_write();
 
   for (;;) {
     if (getln(&ssin,&line,&match,'\n') != 0) die_read();
@@ -53,18 +58,18 @@
       if (line.s[line.len - 1] == '\n') { --line.len; continue; }
       if (line.s[line.len - 1] == '\t') { --line.len; continue; }
       if (line.s[0] != '#')
-	if (cdbmss_add(&cdbmss,line.s,line.len,"",0) == -1)
+	if (cdb_make_add(&cdbm,line.s,line.len,"",0) == -1)
 	  die_write();
       break;
     }
     if (!match) break;
   }
 
-  if (cdbmss_finish(&cdbmss) == -1) die_write();
+  if (cdb_make_finish(&cdbm) == -1) die_write();
   if (fsync(fdtemp) == -1) die_write();
   if (close(fdtemp) == -1) die_write(); /* NFS stupidity */
   if (rename("control/morercpthosts.tmp","control/morercpthosts.cdb") == -1)
     strerr_die2sys(111,FATAL,"unable to move control/morercpthosts.tmp to control/morercpthosts.cdb");
 
-  _exit(0);
+  return 0;
 }
diff -ruN qmail-1.03-orig/qmail-newu.c qmail-1.03-ldap-20060201-orig/qmail-newu.c
--- qmail-1.03-orig/qmail-newu.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/qmail-newu.c	2006-02-25 11:00:55.000000000 +0100
@@ -1,14 +1,19 @@
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <unistd.h>
 #include "stralloc.h"
 #include "subfd.h"
 #include "getln.h"
 #include "substdio.h"
-#include "cdbmss.h"
+#include "cdb_make.h"
 #include "exit.h"
 #include "readwrite.h"
 #include "open.h"
 #include "error.h"
 #include "case.h"
 #include "auto_qmail.h"
+#include "byte.h"
 
 void die_temp() { _exit(111); }
 
@@ -53,7 +58,7 @@
   die_temp();
 }
 
-struct cdbmss cdbmss;
+struct cdb_make cdbm;
 stralloc key = {0};
 stralloc data = {0};
 
@@ -68,10 +73,10 @@
 
 stralloc wildchars = {0};
 
-void main()
+int main()
 {
-  int i;
-  int numcolons;
+  unsigned int i;
+  unsigned int numcolons;
 
   umask(033);
   if (chdir(auto_qmail) == -1) die_chdir();
@@ -79,12 +84,12 @@
   fd = open_read("users/assign");
   if (fd == -1) die_opena();
 
-  substdio_fdbuf(&ssin,read,fd,inbuf,sizeof(inbuf));
+  substdio_fdbuf(&ssin,subread,fd,inbuf,sizeof(inbuf));
 
   fdtemp = open_trunc("users/cdb.tmp");
   if (fdtemp == -1) die_opent();
 
-  if (cdbmss_start(&cdbmss,fdtemp) == -1) die_writet();
+  if (cdb_make_start(&cdbm,fdtemp) == -1) die_writet();
 
   if (!stralloc_copys(&wildchars,"")) die_nomem();
 
@@ -123,15 +128,15 @@
     if (numcolons < 6) die_format();
     data.len = i;
 
-    if (cdbmss_add(&cdbmss,key.s,key.len,data.s,data.len) == -1) die_writet();
+    if (cdb_make_add(&cdbm,key.s,key.len,data.s,data.len) == -1) die_writet();
   }
 
-  if (cdbmss_add(&cdbmss,"",0,wildchars.s,wildchars.len) == -1) die_writet();
+  if (cdb_make_add(&cdbm,"",0,wildchars.s,wildchars.len) == -1) die_writet();
 
-  if (cdbmss_finish(&cdbmss) == -1) die_writet();
+  if (cdb_make_finish(&cdbm) == -1) die_writet();
   if (fsync(fdtemp) == -1) die_writet();
   if (close(fdtemp) == -1) die_writet(); /* NFS stupidity */
   if (rename("users/cdb.tmp","users/cdb") == -1) die_rename();
 
-  _exit(0);
+  return 0;
 }
diff -ruN qmail-1.03-orig/qmail-pbsdbd.sh qmail-1.03-ldap-20060201-orig/qmail-pbsdbd.sh
--- qmail-1.03-orig/qmail-pbsdbd.sh	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/qmail-pbsdbd.sh	2006-02-25 11:00:55.000000000 +0100
@@ -0,0 +1,25 @@
+#!/bin/sh
+exec 2>&1
+#
+# pop before smtp database daemon
+#
+QMAIL="%QMAIL%"
+QUSER="qmaild"
+
+PATH="$QMAIL/bin:$PATH"
+
+# source the environemt in ./env
+eval `env - PATH=$PATH envdir ./env awk '\
+	BEGIN { for (i in ENVIRON) \
+		if (i != "PATH") { \
+			printf "export %s=\"%s\"\\n", i, ENVIRON[i] \
+		} \
+	}'`
+
+# enforce some sane defaults
+QUSER=${QUSER:="qmaild"}
+
+exec \
+	setuidgid $QUSER \
+	$QMAIL/bin/pbsdbd
+
diff -ruN qmail-1.03-orig/qmail-pop3d.c qmail-1.03-ldap-20060201-orig/qmail-pop3d.c
--- qmail-1.03-orig/qmail-pop3d.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/qmail-pop3d.c	2006-02-25 11:00:55.000000000 +0100
@@ -1,10 +1,13 @@
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <stdio.h>
+#include <unistd.h>
 #include "commands.h"
 #include "sig.h"
 #include "getln.h"
 #include "stralloc.h"
 #include "substdio.h"
+#include "subfd.h"
 #include "alloc.h"
 #include "open.h"
 #include "prioq.h"
@@ -17,9 +20,48 @@
 #include "timeoutread.h"
 #include "timeoutwrite.h"
 
-void die() { _exit(0); }
+#include "env.h"
+#include "maildir++.h"
+#include "qmail-ldap.h"
 
-int saferead(fd,buf,len) int fd; char *buf; int len;
+int qfd;
+ 
+/* level 0 = no logging
+         1 = fatal errors
+         2 = login/logout accounting
+         3 = session errors
+	 4 = verbose
+ */
+int loglevel = 0;
+stralloc logs_pidhostinfo = {0};
+unsigned long log_bytes = 0;
+
+void logit(int l, const char *s)
+{
+	if(l <= loglevel)
+		substdio_puts(subfderr,s);
+}
+void logitf(int l, const char *s)
+{
+	if(l > loglevel) return;
+	substdio_puts(subfderr,s);
+	substdio_putsflush(subfderr,"\n");
+}
+
+void log_quit(void)
+{
+  char strnum[FMT_ULONG];
+
+  logit(2, "acct:");
+  logit(2, logs_pidhostinfo.s);
+  logit(2, "logout ");
+  strnum[fmt_ulong(strnum,log_bytes)] = 0;
+  logit(2, strnum); logitf(2, " bytes transferred");
+}
+
+void die(void) { log_quit(); _exit(0); }
+
+int saferead(int fd, void *buf, int len)
 {
   int r;
   r = timeoutread(1200,fd,buf,len);
@@ -27,7 +69,7 @@
   return r;
 }
 
-int safewrite(fd,buf,len) int fd; char *buf; int len;
+int safewrite(int fd, void *buf, int len)
 {
   int r;
   r = timeoutwrite(1200,fd,buf,len);
@@ -41,52 +83,94 @@
 char ssinbuf[128];
 substdio ssin = SUBSTDIO_FDBUF(saferead,0,ssinbuf,sizeof ssinbuf);
 
-void put(buf,len) char *buf; int len;
+void put(const char *buf, int len)
 {
   substdio_put(&ssout,buf,len);
 }
-void puts(s) char *s;
+void putstr(const char *s)
 {
   substdio_puts(&ssout,s);
 }
-void flush()
+void flush(void)
 {
   substdio_flush(&ssout);
 }
-void err(s) char *s;
+void err(const char *s)
 {
-  puts("-ERR ");
-  puts(s);
-  puts("\r\n");
+  putstr("-ERR ");
+  putstr(s);
+  putstr("\r\n");
   flush();
 }
 
-void die_nomem() { err("out of memory"); die(); }
-void die_nomaildir() { err("this user has no $HOME/Maildir"); die(); }
-void die_scan() { err("unable to scan $HOME/Maildir"); die(); }
-
-void err_syntax() { err("syntax error"); }
-void err_unimpl() { err("unimplemented"); }
-void err_deleted() { err("already deleted"); }
-void err_nozero() { err("messages are counted from 1"); }
-void err_toobig() { err("not that many messages"); }
-void err_nosuch() { err("unable to open that message"); }
-void err_nounlink() { err("unable to unlink all deleted messages"); }
+void die_nomem(void) { err("out of memory");
+	logitf(1, "panic: out of memory"); die(); }
+void die_nomaildir(void) { err("this user has no $HOME/Maildir");
+	logitf(1, "panic: this user has no $HOME/Maildir"); die(); }
+void die_scan(void) { err("unable to scan $HOME/Maildir");
+	logitf(1, "unable to scan $HOME/Maildir"); die(); }
+
+void err_syntax(void) { err("syntax error"); logitf(3, "error: syntax error"); }
+void err_unimpl(void) { err("unimplemented"); logitf(3, "error: unimplemented"); }
+void err_deleted(void) { err("already deleted"); logitf(3, "already deleted"); }
+void err_nozero(void) { err("messages are counted from 1"); logitf(3, "messages are counted from 1"); }
+void err_toobig(void) { err("not that many messages"); logitf(3, "not that many messages"); }
+void err_nosuch(void) { err("unable to open that message"); logitf(3, "unable to open that message"); }
+void err_nounlink(void) { err("unable to unlink all deleted messages"); logitf(3, "unable to unlink all deleted messages"); }
 
-void okay() { puts("+OK \r\n"); flush(); }
+void okay(void) { putstr("+OK \r\n"); flush(); }
 
-void printfn(fn) char *fn;
+void printfn(const char *fn)
 {
   fn += 4;
   put(fn,str_chr(fn,':'));
 }
 
+void log_init(void)
+{
+  char strnum[FMT_ULONG];
+  const char *remotehost;
+  const char *remoteip;
+  const char *remoteinfo;
+  const char *user;
+  char *l;
+  unsigned long v;
+  
+  l = env_get("POP3_LOGLEVEL");
+  if (l) { scan_ulong(l,&v); loglevel = v; };
+
+  remoteip = env_get("TCPREMOTEIP");
+  if (!remoteip) remoteip = "unknown";
+  remotehost = env_get("TCPREMOTEHOST");
+  if (!remotehost) remotehost = "unknown";
+  remoteinfo = env_get("TCPREMOTEINFO");
+  if (!remoteinfo) remoteinfo = "";
+  user = env_get("USER");
+  if (!user) user = "unknown";
+
+  if (!stralloc_copys(&logs_pidhostinfo, " pid ")) die_nomem();
+  strnum[fmt_ulong(strnum,getpid())] = 0;
+  if (!stralloc_cats(&logs_pidhostinfo, strnum)) die_nomem();
+  if (!stralloc_cats(&logs_pidhostinfo, ": ")) die_nomem();
+
+  if (!stralloc_cats(&logs_pidhostinfo, remotehost)) die_nomem();
+  if (!stralloc_cats(&logs_pidhostinfo, ":")) die_nomem();
+  if (!stralloc_cats(&logs_pidhostinfo, remoteip)) die_nomem();
+  if (!stralloc_cats(&logs_pidhostinfo, ":")) die_nomem();
+  if (!stralloc_cats(&logs_pidhostinfo, remoteinfo)) die_nomem();
+  if (!stralloc_cats(&logs_pidhostinfo, " ")) die_nomem();
+  if (!stralloc_cats(&logs_pidhostinfo, user)) die_nomem();
+  if (!stralloc_cats(&logs_pidhostinfo, " ")) die_nomem();
+  if (!stralloc_0(&logs_pidhostinfo)) die_nomem();
+
+  logit(2, "acct:"); logit(2, logs_pidhostinfo.s); logitf(2, "login");
+}
+
+
 char strnum[FMT_ULONG];
 stralloc line = {0};
 
-void blast(ssfrom,limit)
-substdio *ssfrom;
-unsigned long limit;
+void blast(substdio *ssfrom, unsigned long limit)
 {
   int match;
   int inheaders = 1;
@@ -103,6 +187,7 @@
         put(".",1);
     put(line.s,line.len);
     put("\r\n",2);
+    log_bytes += line.len + 2;
     if (!match) break;
   }
   put("\r\n.\r\n",5);
@@ -117,15 +202,15 @@
   unsigned long size;
   char *fn;
 } *m;
-int numm;
+unsigned int numm;
 
-int last = 0;
+unsigned int last = 0;
 
-void getlist()
+void getlist(void)
 {
   struct prioq_elt pe;
   struct stat st;
-  int i;
+  unsigned int i;
  
   maildir_clean(&line);
   if (maildir_scan(&pq,&filenames,1,1) == -1) die_scan();
@@ -146,42 +231,64 @@
   }
 }
 
-void pop3_stat()
+void pop3_stat(char *arg)
 {
-  int i;
+  unsigned int i;
   unsigned long total;
+  unsigned int count;
  
+  logitf(4, "comm: stat");
   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(" ");
+  count = 0;
+  for (i = 0;i < numm;++i) if (!m[i].flagdeleted) {
+    total += m[i].size;
+    count += 1;
+  }
+  putstr("+OK ");
+  put(strnum,fmt_uint(strnum,count));
+  putstr(" ");
   put(strnum,fmt_ulong(strnum,total));
-  puts("\r\n");
+  putstr("\r\n");
   flush();
 }
 
-void pop3_rset()
+void pop3_rset(char *arg)
 {
-  int i;
+  unsigned int i;
+
+  logitf(4, "comm: rset");
   for (i = 0;i < numm;++i) m[i].flagdeleted = 0;
   last = 0;
   okay();
 }
 
-void pop3_last()
+void pop3_last(char *arg)
 {
-  puts("+OK ");
+  logitf(4, "comm: last");
+  putstr("+OK ");
   put(strnum,fmt_uint(strnum,last));
-  puts("\r\n");
+  putstr("\r\n");
   flush();
 }
 
-void pop3_quit()
+void pop3_quit(char *arg)
 {
-  int i;
+  unsigned int i;
+  quota_t q;
+  
+  logitf(4, "comm: quit");
+/* qmail-ldap stuff */
+/* this is just minimal support, because pop3 can not produce new mail */
+  quota_get(&q, env_get(ENV_QUOTA));
+  if (quota_calc(".",&qfd, &q) == -1) {
+    /* second chance */
+    sleep(3);
+    quota_calc(".",&qfd, &q);
+  }
   for (i = 0;i < numm;++i)
     if (m[i].flagdeleted) {
+      if ( qfd != -1 ) quota_rm(qfd, m[i].size, 1);
+/* end qmail-ldap stuff */
       if (unlink(m[i].fn) == -1) err_nounlink();
     }
     else
@@ -193,10 +300,11 @@
 	rename(m[i].fn,line.s); /* if it fails, bummer */
       }
   okay();
+  if ( qfd != -1 ) close(qfd);
   die();
 }
 
-int msgno(arg) char *arg;
+unsigned int msgno(char *arg)
 {
   unsigned long u;
   if (!scan_ulong(arg,&u)) { err_syntax(); return -1; }
@@ -207,34 +315,34 @@
   return u;
 }
 
-void pop3_dele(arg) char *arg;
+void pop3_dele(char *arg)
 {
-  int i;
+  unsigned int i;
+
+  logit(4, "comm: dele: "); logitf(4, arg);
   i = msgno(arg);
-  if (i == -1) return;
+  if (i == (unsigned int)-1) return;
   m[i].flagdeleted = 1;
   if (i + 1 > last) last = i + 1;
   okay();
 }
 
-void list(i,flaguidl)
-int i;
-int flaguidl;
+void list(unsigned int i, int flaguidl)
 {
   put(strnum,fmt_uint(strnum,i + 1));
-  puts(" ");
+  putstr(" ");
   if (flaguidl) printfn(m[i].fn);
   else put(strnum,fmt_ulong(strnum,m[i].size));
-  puts("\r\n");
+  putstr("\r\n");
 }
 
-void dolisting(arg,flaguidl) char *arg; int flaguidl;
+void dolisting(char *arg, int flaguidl)
 {
   unsigned int i;
   if (*arg) {
     i = msgno(arg);
-    if (i == -1) return;
-    puts("+OK ");
+    if (i == (unsigned int)-1) return;
+    putstr("+OK ");
     list(i,flaguidl);
   }
   else {
@@ -242,24 +350,30 @@
     for (i = 0;i < numm;++i)
       if (!m[i].flagdeleted)
 	list(i,flaguidl);
-    puts(".\r\n");
+    putstr(".\r\n");
   }
   flush();
 }
 
-void pop3_uidl(arg) char *arg; { dolisting(arg,1); }
-void pop3_list(arg) char *arg; { dolisting(arg,0); }
+void pop3_uidl(char *arg) { 
+  logit(4, "comm: uidl: "); logitf(4, arg); dolisting(arg,1); }
+void pop3_list(char *arg) {
+  logit(4, "comm: list: "); logitf(4, arg); dolisting(arg,0); }
 
 substdio ssmsg; char ssmsgbuf[1024];
 
-void pop3_top(arg) char *arg;
+void pop3_top(char *arg)
 {
-  int i;
+  unsigned int i;
   unsigned long limit;
   int fd;
+#ifdef MAKE_NETSCAPE_WORK /* Based on a patch by sven@megabit.net */
+  char foo[FMT_ULONG];
+#endif
  
+  logit(4, "comm: retr/top: "); logitf(4, arg);
   i = msgno(arg);
-  if (i == -1) return;
+  if (i == (unsigned int)-1) return;
  
   arg += scan_ulong(arg,&limit);
   while (*arg == ' ') ++arg;
@@ -267,8 +381,19 @@
  
   fd = open_read(m[i].fn);
   if (fd == -1) { err_nosuch(); return; }
+
+#ifdef MAKE_NETSCAPE_WORK /* Based on a patch by sven@megabit.net */
+  putstr("+OK ");
+  foo[fmt_uint(foo,m[i].size)] = 0;
+  putstr(foo);
+
+  putstr(" octets \r\n");
+  flush();
+#else
   okay();
-  substdio_fdbuf(&ssmsg,read,fd,ssmsgbuf,sizeof(ssmsgbuf));
+#endif
+
+  substdio_fdbuf(&ssmsg,subread,fd,ssmsgbuf,sizeof(ssmsgbuf));
   blast(&ssmsg,limit);
   close(fd);
 }
@@ -287,19 +412,28 @@
 , { 0, err_unimpl, 0 }
 } ;
 
-void main(argc,argv)
-int argc;
-char **argv;
+int main(int argc, char **argv)
 {
+/* qmail-ldap stuff */
+  char *env;
+  
   sig_alarmcatch(die);
   sig_pipeignore();
- 
+  
+  /* if MAILDIR is defined us this as Maildir and not the argument */
+  if ( (env = env_get("MAILDIR") ) && *env ) argv[1] = env;
+
   if (!argv[1]) die_nomaildir();
-  if (chdir(argv[1]) == -1) die_nomaildir();
- 
+  if (chdir(argv[1]) == -1) {
+    die_nomaildir();
+  } 
+/* qmail-ldap stuff */
+
+  log_init();
   getlist();
 
   okay();
   commands(&ssin,pop3commands);
-  die();
+  log_quit();
+  return 0;
 }
diff -ruN qmail-1.03-orig/qmail-pop3d.rules qmail-1.03-ldap-20060201-orig/qmail-pop3d.rules
--- qmail-1.03-orig/qmail-pop3d.rules	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/qmail-pop3d.rules	2006-02-25 11:00:55.000000000 +0100
@@ -0,0 +1,9 @@
+#
+# POP3 Server rules.
+# Normaly you allow from everyware and the only useful env vars are
+# NOPBS, LOGLEVEL and POP3_LOGLEVEL.
+#
+# disable pop-befor-smtp on the loopback
+127.0.0.1:allow,NOPBS=""
+# default allow
+:allow
diff -ruN qmail-1.03-orig/qmail-pop3d.sh qmail-1.03-ldap-20060201-orig/qmail-pop3d.sh
--- qmail-1.03-orig/qmail-pop3d.sh	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/qmail-pop3d.sh	2006-02-25 11:00:55.000000000 +0100
@@ -0,0 +1,38 @@
+#!/bin/sh
+exec 2>&1
+#
+# POP3 service 
+#
+QMAIL="%QMAIL%"
+ME="`head -1 $QMAIL/control/me`"
+if [ -e $QMAIL/control/defaultdelivery ]; then
+        ALIASEMPTY=`head -1 $QMAIL/control/defaultdelivery 2> /dev/null`
+else
+        ALIASEMPTY=`head -1 $QMAIL/control/aliasempty 2> /dev/null`
+fi
+ALIASEMPTY=${ALIASEMPTY:="./Maildir/"}
+
+PATH="$QMAIL/bin:$PATH"
+
+# source the environemt in ./env
+eval `env - PATH=$PATH envdir ./env awk '\
+	BEGIN { for (i in ENVIRON) \
+		if (i != "PATH") { \
+			printf "export %s=\"%s\"\\n", i, ENVIRON[i] \
+		} \
+	}'`
+
+# enforce some sane defaults
+PBSTOOL=${PBSTOOL:="$QMAIL/bin/pbsadd"}
+
+if [ X${NOPBS+"true"} = X"true" ]; then
+	unset PBSTOOL
+fi
+
+exec \
+	tcpserver -v -HRl $ME -x$QMAIL/control/qmail-pop3d.cdb \
+	    ${CONCURRENCY:+"-c$CONCURRENCY"} ${BACKLOG:+"-b$BACKLOG"} 0 pop3 \
+	$QMAIL/bin/qmail-popup $ME \
+	$QMAIL/bin/auth_pop ${PBSTOOL:+"-d$PBSTOOL"} \
+	$QMAIL/bin/qmail-pop3d "$ALIASEMPTY"
+
diff -ruN qmail-1.03-orig/qmail-pop3d-ssl.sh qmail-1.03-ldap-20060201-orig/qmail-pop3d-ssl.sh
--- qmail-1.03-orig/qmail-pop3d-ssl.sh	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/qmail-pop3d-ssl.sh	2006-02-25 11:00:55.000000000 +0100
@@ -0,0 +1,40 @@
+#!/bin/sh
+exec 2>&1
+#
+# POP3 service 
+#
+QMAIL="%QMAIL%"
+ME="`head -1 $QMAIL/control/me`"
+if [ -e $QMAIL/control/defaultdelivery ]; then
+        ALIASEMPTY=`head -1 $QMAIL/control/defaultdelivery 2> /dev/null`
+else
+        ALIASEMPTY=`head -1 $QMAIL/control/aliasempty 2> /dev/null`
+fi
+ALIASEMPTY=${ALIASEMPTY:="./Maildir/"}
+
+PATH="$QMAIL/bin:$PATH"
+
+# source the environemt in ./env
+eval `env - PATH=$PATH envdir ./env awk '\
+	BEGIN { for (i in ENVIRON) \
+		if (i != "PATH") { \
+			printf "export %s=\"%s\"\\n", i, ENVIRON[i] \
+		} \
+	}'`
+
+# enforce some sane defaults
+TLSCERT=${TLSCERT:="$QMAIL/control/cert.pem"}
+PBSTOOL=${PBSTOOL:="$QMAIL/bin/pbsadd"}
+
+if [ X${NOPBS+"true"} = X"true" ]; then
+	unset PBSTOOL
+fi
+
+exec \
+	tcpserver -v -HRl $ME -x$QMAIL/control/qmail-pop3d.cdb \
+	    ${CONCURRENCY:+"-c$CONCURRENCY"} ${BACKLOG:+"-b$BACKLOG"} \
+	    -s ${TLSCERT:+"-n$TLSCERT"} 0 pop3s \
+	$QMAIL/bin/qmail-popup $ME \
+	$QMAIL/bin/auth_pop ${PBSTOOL:+"-d$PBSTOOL"}\
+	$QMAIL/bin/qmail-pop3d "$ALIASEMPTY"
+
diff -ruN qmail-1.03-orig/qmail-popup.c qmail-1.03-ldap-20060201-orig/qmail-popup.c
--- qmail-1.03-orig/qmail-popup.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/qmail-popup.c	2006-02-25 11:00:55.000000000 +0100
@@ -1,3 +1,4 @@
+#include <unistd.h>
 #include "commands.h"
 #include "fd.h"
 #include "sig.h"
@@ -14,9 +15,9 @@
 #include "timeoutread.h"
 #include "timeoutwrite.h"
 
-void die() { _exit(1); }
+void die(void) { _exit(1); }
 
-int saferead(fd,buf,len) int fd; char *buf; int len;
+int saferead(int fd, void *buf, int len)
 {
   int r;
   r = timeoutread(1200,fd,buf,len);
@@ -24,7 +25,7 @@
   return r;
 }
 
-int safewrite(fd,buf,len) int fd; char *buf; int len;
+int safewrite(int fd, void *buf, int len)
 {
   int r;
   r = timeoutwrite(1200,fd,buf,len);
@@ -38,36 +39,62 @@
 char ssinbuf[128];
 substdio ssin = SUBSTDIO_FDBUF(saferead,0,ssinbuf,sizeof ssinbuf);
 
-void puts(s) char *s;
+void putstr(const char *s)
 {
   substdio_puts(&ssout,s);
 }
-void flush()
+void flush(void)
 {
   substdio_flush(&ssout);
 }
-void err(s) char *s;
+void err(const char *s)
 {
-  puts("-ERR ");
-  puts(s);
-  puts("\r\n");
+  putstr("-ERR ");
+  putstr(s);
+  putstr("\r\n");
   flush();
 }
 
-void die_usage() { err("usage: popup hostname subprogram"); die(); }
-void die_nomem() { err("out of memory"); die(); }
-void die_pipe() { err("unable to open pipe"); die(); }
-void die_write() { err("unable to write pipe"); die(); }
-void die_fork() { err("unable to fork"); die(); }
-void die_childcrashed() { err("aack, child crashed"); }
-void die_badauth() { err("authorization failed"); }
-
-void err_syntax() { err("syntax error"); }
-void err_wantuser() { err("USER first"); }
-void err_authoriz() { err("authorization first"); }
+void die_usage(void) { err("usage: popup hostname subprogram"); die(); }
+void die_nomem(void) { err("out of memory"); die(); }
+void die_pipe(void) { err("unable to open pipe"); die(); }
+void die_write(void) { err("unable to write pipe"); die(); }
+void die_fork(void) { err("unable to fork"); die(); }
+void die_childcrashed(void) { err("aack, child crashed"); }
+void die_badauth(void) { err("authorization failed"); }
+
+/* checkpassword error exit codes:
+ * 1 = error in server configuration
+ * 2 = unable to contact authorization server
+ * 25= user record incorrect
+ * 3 = authorization failed
+ * 4 = account disabled
+ * 5 = mailhost is unreachable
+ * 6 = mailbox is corrupted
+ * 61= mailbox creation failed
+ * 62= the users mailbox does not exist
+ * 7 = unable to start subprogram
+ * 8 = out of memory
+ */
+
+void die_1(void) { err("error in server configuration"); die(); }
+void die_2(void) { err("unable to contact authorization server"); die(); }
+void die_25(void) { err("user record incorrect"); die(); }
+void die_3(void) { err("authorization failed"); die(); }
+void die_4(void) { err("account disabled"); die(); }
+void die_5(void) { err("mailhost is unreachable"); die(); }
+void die_6(void) { err("mailbox is corrupted"); die(); }
+void die_61(void) { err("mailbox could not be created"); die(); }
+void die_62(void) { err("the users mailbox does not exist"); die(); }
+void die_7(void) { err("unable to start subprogram"); die(); }
+void die_unknown(void) { err("temporary error"); die(); }
+
+void err_syntax(void) { err("syntax error"); }
+void err_wantuser(void) { err("USER first"); }
+void err_authoriz(void) { err("authorization first"); }
 
-void okay() { puts("+OK \r\n"); flush(); }
-void pop3_quit() { okay(); die(); }
+void okay(void) { putstr("+OK \r\n"); flush(); }
+void pop3_quit(void) { okay(); die(); }
 
 
 char unique[FMT_ULONG + FMT_ULONG + 3];
@@ -79,16 +106,13 @@
 char upbuf[128];
 
 
-void doanddie(user,userlen,pass)
-char *user;
-unsigned int userlen; /* including 0 byte */
-char *pass;
+void doanddie(char *user, unsigned int userlen /* including 0 byte */,
+    char *pass)
 {
   int child;
   int wstat;
   int pi[2];
  
-  if (fd_copy(2,1) == -1) die_pipe();
   close(3);
   if (pipe(pi) == -1) die_pipe();
   if (pi[0] != 3) die_pipe();
@@ -102,7 +126,7 @@
       _exit(1);
   }
   close(pi[0]);
-  substdio_fdbuf(&ssup,write,pi[1],upbuf,sizeof upbuf);
+  substdio_fdbuf(&ssup,subwrite,pi[1],upbuf,sizeof upbuf);
   if (substdio_put(&ssup,user,userlen) == -1) die_write();
   if (substdio_put(&ssup,pass,str_len(pass) + 1) == -1) die_write();
   if (substdio_puts(&ssup,"<") == -1) die_write();
@@ -115,10 +139,25 @@
   byte_zero(upbuf,sizeof upbuf);
   if (wait_pid(&wstat,child) == -1) die();
   if (wait_crashed(wstat)) die_childcrashed();
-  if (wait_exitcode(wstat)) die_badauth();
+  switch (wait_exitcode(wstat)) {
+    case 0: die();
+    case 1: die_1();
+    case 2: die_2();
+    case 25: die_25();
+    case 3: die_3();
+    case 4: die_4();
+    case 5: die_5();
+    case 6: die_6();
+    case 61: die_61();
+    case 62: die_62();
+    case 7: die_7();
+    case 8: die_nomem();
+    default: die_unknown();
+  }
   die();
 }
-void pop3_greet()
+
+void pop3_greet(void)
 {
   char *s;
   s = unique;
@@ -127,13 +166,13 @@
   s += fmt_ulong(s,(unsigned long) now());
   *s++ = '@';
   *s++ = 0;
-  puts("+OK <");
-  puts(unique);
-  puts(hostname);
-  puts(">\r\n");
+  putstr("+OK <");
+  putstr(unique);
+  putstr(hostname);
+  putstr(">\r\n");
   flush();
 }
-void pop3_user(arg) char *arg;
+void pop3_user(char *arg)
 {
   if (!*arg) { err_syntax(); return; }
   okay();
@@ -141,13 +180,13 @@
   if (!stralloc_copys(&username,arg)) die_nomem(); 
   if (!stralloc_0(&username)) die_nomem(); 
 }
-void pop3_pass(arg) char *arg;
+void pop3_pass(char *arg)
 {
   if (!seenuser) { err_wantuser(); return; }
   if (!*arg) { err_syntax(); return; }
   doanddie(username.s,username.len,arg);
 }
-void pop3_apop(arg) char *arg;
+void pop3_apop(char *arg)
 {
   char *space;
   space = arg + str_chr(arg,' ');
@@ -165,9 +204,7 @@
 , { 0, err_authoriz, 0 }
 } ;
 
-void main(argc,argv)
-int argc;
-char **argv;
+int main(int argc, char **argv)
 {
   sig_alarmcatch(die);
   sig_pipeignore();
@@ -179,5 +216,5 @@
  
   pop3_greet();
   commands(&ssin,pop3commands);
-  die();
+  return 1;
 }
diff -ruN qmail-1.03-orig/qmail-pw2u.c qmail-1.03-ldap-20060201-orig/qmail-pw2u.c
--- qmail-1.03-orig/qmail-pw2u.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/qmail-pw2u.c	2006-02-25 11:00:55.000000000 +0100
@@ -1,5 +1,6 @@
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <unistd.h>
 #include "substdio.h"
 #include "readwrite.h"
 #include "subfd.h"
@@ -16,6 +17,7 @@
 #include "auto_break.h"
 #include "auto_qmail.h"
 #include "auto_usera.h"
+#include "byte.h"
 
 void die_chdir()
 {
@@ -67,7 +69,7 @@
   _exit(111);
 }
 
-char *dashcolon = "-:";
+const char *dashcolon = "-:";
 int flagalias = 0;
 int flagnoupper = 1;
 int homestrategy = 2;
@@ -93,8 +95,8 @@
 void doaccount()
 {
   struct stat st;
-  int i;
-  char *mailnames;
+  unsigned int i;
+  const char *mailnames;
   char *x;
   unsigned int xlen;
 
@@ -194,21 +196,21 @@
 
 void dosubuser()
 {
-  int i;
+  unsigned int i;
   char *x;
   unsigned int xlen;
-  char *uugh;
+  const char *uughs;
 
   x = line.s; xlen = line.len; i = byte_chr(x,xlen,':'); if (i == xlen) return;
   if (!stralloc_copyb(&sub,x,i)) die_nomem();
   ++i; x += i; xlen -= i; i = byte_chr(x,xlen,':'); if (i == xlen) return;
-  uugh = constmap(&mapuser,x,i);
-  if (!uugh) die_user(x,i);
+  uughs = constmap(&mapuser,x,i);
+  if (!uughs) die_user(x,i);
   ++i; x += i; xlen -= i; i = byte_chr(x,xlen,':'); if (i == xlen) return;
 
   if (substdio_puts(subfdout,"=") == -1) die_write();
   if (substdio_put(subfdout,sub.s,sub.len) == -1) die_write();
-  if (substdio_puts(subfdout,uugh) == -1) die_write();
+  if (substdio_puts(subfdout,uughs) == -1) die_write();
   if (substdio_puts(subfdout,dashcolon) == -1) die_write();
   if (substdio_put(subfdout,x,i) == -1) die_write();
   if (substdio_puts(subfdout,":\n") == -1) die_write();
@@ -217,7 +219,7 @@
     if (substdio_puts(subfdout,"+") == -1) die_write();
     if (substdio_put(subfdout,sub.s,sub.len) == -1) die_write();
     if (substdio_put(subfdout,auto_break,1) == -1) die_write();
-    if (substdio_puts(subfdout,uugh) == -1) die_write();
+    if (substdio_puts(subfdout,uughs) == -1) die_write();
     if (substdio_puts(subfdout,dashcolon) == -1) die_write();
     if (substdio_put(subfdout,x,i) == -1) die_write();
     if (substdio_puts(subfdout,"-:\n") == -1) die_write();
@@ -228,7 +230,7 @@
 substdio ss;
 char ssbuf[SUBSTDIO_INSIZE];
 
-void main(argc,argv)
+int main(argc,argv)
 int argc;
 char **argv;
 {
@@ -280,7 +282,7 @@
     if (errno != error_noent) die_control();
   }
   else {
-    substdio_fdbuf(&ss,read,fd,ssbuf,sizeof(ssbuf));
+    substdio_fdbuf(&ss,subread,fd,ssbuf,sizeof(ssbuf));
 
     if (!constmap_init(&mapuser,allusers.s,allusers.len,1)) die_nomem();
 
@@ -298,7 +300,7 @@
     if (errno != error_noent) die_control();
   }
   else {
-    substdio_fdbuf(&ss,read,fd,ssbuf,sizeof(ssbuf));
+    substdio_fdbuf(&ss,subread,fd,ssbuf,sizeof(ssbuf));
     for (;;) {
       if (getln(&ss,&line,&match,'\n') == -1) die_read();
       if (substdio_put(subfdout,line.s,line.len) == -1) die_write();
@@ -308,5 +310,5 @@
 
   if (substdio_puts(subfdout,".\n") == -1) die_write();
   if (substdio_flush(subfdout) == -1) die_write();
-  _exit(0);
+  return 0;
 }
diff -ruN qmail-1.03-orig/qmail-qmqpc.c qmail-1.03-ldap-20060201-orig/qmail-qmqpc.c
--- qmail-1.03-orig/qmail-qmqpc.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/qmail-qmqpc.c	2006-02-25 11:00:55.000000000 +0100
@@ -2,6 +2,7 @@
 #include <sys/socket.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
+#include <unistd.h>
 #include "substdio.h"
 #include "getln.h"
 #include "readwrite.h"
@@ -17,33 +18,105 @@
 #include "auto_qmail.h"
 #include "control.h"
 #include "fmt.h"
+#ifdef QMQP_COMPRESS
+#include <zlib.h>
+#endif
 
+
+#ifndef PORT_QMQP /* this is for testing purposes */
 #define PORT_QMQP 628
+#endif
 
-void die_success() { _exit(0); }
-void die_perm() { _exit(31); }
-void nomem() { _exit(51); }
-void die_read() { if (errno == error_nomem) nomem(); _exit(54); }
-void die_control() { _exit(55); }
-void die_socket() { _exit(56); }
-void die_home() { _exit(61); }
-void die_temp() { _exit(71); }
-void die_conn() { _exit(74); }
-void die_format() { _exit(91); }
+void die_success(void) { _exit(0); }
+void die_perm(void) { _exit(31); }
+void nomem(void) { _exit(51); }
+void die_read(void) { if (errno == error_nomem) nomem(); _exit(54); }
+void die_control(void) { _exit(55); }
+void die_socket(void) { _exit(56); }
+void die_home(void) { _exit(61); }
+void die_temp(void) { _exit(71); }
+void die_conn(void) { _exit(74); }
+void die_format(void) { _exit(91); }
 
+int timeoutconnect = 60;
 int lasterror = 55;
 int qmqpfd;
 
-int saferead(fd,buf,len) int fd; char *buf; int len;
+#ifdef QMQP_COMPRESS
+z_stream stream;
+char zbuf[4096];
+
+void compression_init(void)
+{
+  stream.zalloc = Z_NULL;
+  stream.zfree = Z_NULL;
+  stream.opaque = Z_NULL;
+  stream.avail_out = sizeof(zbuf);
+  stream.next_out = zbuf;
+  if (deflateInit(&stream,Z_DEFAULT_COMPRESSION) != Z_OK)
+    die_format();
+}
+void compression_done(void)
+{
+  int r;
+
+  do {
+    r = deflate(&stream,Z_FINISH);
+    switch (r) {
+    case Z_OK:
+      if (stream.avail_out == 0) {
+	r = timeoutwrite(60,qmqpfd,zbuf,sizeof(zbuf));
+	if (r <= 0) die_conn();
+	stream.avail_out = sizeof(zbuf);
+	stream.next_out = zbuf;
+	r = Z_OK;
+      }
+      break;
+    case Z_STREAM_END:
+      break;
+    default:
+      die_format();
+    }
+  } while (r!=Z_STREAM_END);
+  if (stream.avail_out != sizeof(zbuf)) {
+    /* write left data */
+    r = timeoutwrite(60,qmqpfd,zbuf,sizeof(zbuf)-stream.avail_out);
+    if (r <= 0) die_conn();
+  }
+  if (deflateEnd(&stream) != Z_OK) die_format();
+}
+#endif
+
+int saferead(int fd, void *buf, int len)
 {
   int r;
   r = timeoutread(60,qmqpfd,buf,len);
   if (r <= 0) die_conn();
   return r;
 }
-int safewrite(fd,buf,len) int fd; char *buf; int len;
+int safewrite(int fd, void *buf, int len)
 {
   int r;
+#ifdef QMQP_COMPRESS
+  stream.avail_in = len;
+  stream.next_in = buf;
+  do {
+    r = deflate(&stream, 0);
+    switch (r) {
+    case Z_OK:
+      if (stream.avail_out == 0) {
+	r = timeoutwrite(60,qmqpfd,zbuf,sizeof(zbuf));
+	if (r <= 0) die_conn();
+	stream.avail_out = sizeof(zbuf);
+	stream.next_out = zbuf;
+      }
+      break;
+    default:
+      die_format();
+    }
+  } while (stream.avail_in != 0);
+  return len;
+#endif
   r = timeoutwrite(60,qmqpfd,buf,len);
   if (r <= 0) die_conn();
   return r;
@@ -52,7 +125,7 @@
 char buf[1024];
 substdio to = SUBSTDIO_FDBUF(safewrite,-1,buf,sizeof buf);
 substdio from = SUBSTDIO_FDBUF(saferead,-1,buf,sizeof buf);
-substdio envelope = SUBSTDIO_FDBUF(read,1,buf,sizeof buf);
+substdio envelope = SUBSTDIO_FDBUF(subread,1,buf,sizeof buf);
 /* WARNING: can use only one of these at a time! */
 
 stralloc beforemessage = {0};
@@ -68,7 +141,7 @@
 
   if (slurpclose(0,&message,1024) == -1) die_read();
 
-  strnum[fmt_ulong(strnum,(unsigned long) message.len)] = 0;
+  strnum[fmt_uint(strnum,message.len)] = 0;
   if (!stralloc_copys(&beforemessage,strnum)) nomem();
   if (!stralloc_cats(&beforemessage,":")) nomem();
   if (!stralloc_copys(&aftermessage,",")) nomem();
@@ -78,7 +151,7 @@
   if (line.len < 2) die_format();
   if (line.s[0] != 'F') die_format();
 
-  strnum[fmt_ulong(strnum,(unsigned long) line.len - 2)] = 0;
+  strnum[fmt_uint(strnum,line.len - 2)] = 0;
   if (!stralloc_cats(&aftermessage,strnum)) nomem();
   if (!stralloc_cats(&aftermessage,":")) nomem();
   if (!stralloc_catb(&aftermessage,line.s + 1,line.len - 2)) nomem();
@@ -90,7 +163,7 @@
     if (line.len < 2) break;
     if (line.s[0] != 'T') die_format();
 
-    strnum[fmt_ulong(strnum,(unsigned long) line.len - 2)] = 0;
+    strnum[fmt_uint(strnum,line.len - 2)] = 0;
     if (!stralloc_cats(&aftermessage,strnum)) nomem();
     if (!stralloc_cats(&aftermessage,":")) nomem();
     if (!stralloc_catb(&aftermessage,line.s + 1,line.len - 2)) nomem();
@@ -98,6 +171,8 @@
   }
 }
 
+struct ip_address outip;
+
 void doit(server)
 char *server;
 {
@@ -109,14 +184,18 @@
   qmqpfd = socket(AF_INET,SOCK_STREAM,0);
   if (qmqpfd == -1) die_socket();
 
-  if (timeoutconn(qmqpfd,&ip,PORT_QMQP,10) != 0) {
+  if (timeoutconn(qmqpfd,&ip,&outip,PORT_QMQP,timeoutconnect) != 0) {
     lasterror = 73;
     if (errno == error_timeout) lasterror = 72;
     close(qmqpfd);
     return;
   }
 
-  strnum[fmt_ulong(strnum,(unsigned long) (beforemessage.len + message.len + aftermessage.len))] = 0;
+#ifdef QMQP_COMPRESS
+  compression_init();
+#endif
+  strnum[fmt_uint(strnum, 
+         (beforemessage.len + message.len + aftermessage.len))] = 0;
   substdio_puts(&to,strnum);
   substdio_puts(&to,":");
   substdio_put(&to,beforemessage.s,beforemessage.len);
@@ -124,6 +203,9 @@
   substdio_put(&to,aftermessage.s,aftermessage.len);
   substdio_puts(&to,",");
   substdio_flush(&to);
+#ifdef QMQP_COMPRESS
+  compression_done();
+#endif
 
   for (;;) {
     substdio_get(&from,&ch,1);
@@ -134,18 +216,48 @@
 }
 
 stralloc servers = {0};
+stralloc outgoingip = {0};
+
+#include "dns.h"
+#include "ipalloc.h"
+
+ipalloc ia = {0};
 
-main()
+int main(argc,argv)
+int argc;
+char **argv;
 {
-  int i;
-  int j;
+  unsigned int i;
+  unsigned int j;
 
   sig_pipeignore();
 
   if (chdir(auto_qmail) == -1) die_home();
   if (control_init() == -1) die_control();
+  if ( argv[1] ) {
+    char temp[IPFMT];
+    if (!stralloc_copys(&servers,argv[1])) nomem();
+    dns_init(0);
+    switch (dns_ip(&ia,&servers)) {
+      case DNS_HARD: die_perm();
+      case DNS_SOFT: die_temp();
+      case DNS_MEM: nomem();
+    }
+
+    temp[ip_fmt(temp,&ia.ix[0].ip)]=0;
+    if (!stralloc_copys(&servers, temp)) nomem();
+    if (!stralloc_0(&servers)) nomem();
+  } else
   if (control_readfile(&servers,"control/qmqpservers",0) != 1) die_control();
 
+  if (control_readint(&timeoutconnect,"control/timeoutconnect") == -1)
+    die_control();
+
+  if (control_rldef(&outgoingip, "control/qmqpcip", 0, "0.0.0.0") == -1)
+	  die_control();
+  if (!stralloc_0(&outgoingip)) nomem();
+  if (!ip_scan(outgoingip.s,&outip)) die_control();
+
   getmess();
 
   i = 0;
@@ -155,5 +267,5 @@
       i = j + 1;
     }
 
-  _exit(lasterror);
+  return lasterror;
 }
diff -ruN qmail-1.03-orig/qmail-qmqpd.c qmail-1.03-ldap-20060201-orig/qmail-qmqpd.c
--- qmail-1.03-orig/qmail-qmqpd.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/qmail-qmqpd.c	2006-02-25 11:00:55.000000000 +0100
@@ -1,26 +1,132 @@
+#include <unistd.h>
 #include "auto_qmail.h"
+#include "byte.h"
 #include "qmail.h"
 #include "received.h"
 #include "sig.h"
+#include "subfd.h"
 #include "substdio.h"
 #include "readwrite.h"
 #include "exit.h"
 #include "now.h"
 #include "fmt.h"
 #include "env.h"
+#include "str.h"
+#ifdef QMQP_COMPRESS
+#include <zlib.h>
+
+z_stream stream;
+char zbuf[4096];
+int percent;
+int compressed = 0;
+extern substdio ssout;
+
+void out(const char *s1, const char *s2, const char *s3)
+{
+  char strnum[FMT_ULONG];
+  unsigned long len;
+
+  len = str_len(s1);
+  if (s2) len += str_len(s2);
+  if (s3) len += str_len(s3);
+  substdio_put(&ssout,strnum,fmt_ulong(strnum,len));
+  substdio_puts(&ssout,":");
+  substdio_puts(&ssout,s1);
+  substdio_puts(subfderr,s1+1);
+  if (s2) { substdio_puts(&ssout,s2); substdio_puts(subfderr,s2); }
+  if (s3) { substdio_puts(&ssout,s3); substdio_puts(subfderr,s3); }
+  substdio_puts(subfderr, "\n");
+  substdio_flush(subfderr);
+  substdio_puts(&ssout,",");
+  substdio_flush(&ssout);
+}
+void compression_init(int avail)
+{
+  stream.zalloc = Z_NULL;
+  stream.zfree = Z_NULL;
+  stream.opaque = Z_NULL;
+  stream.avail_in = avail;
+  stream.next_in = zbuf;
+  if (inflateInit(&stream) != Z_OK) {
+    out("ZInitalizing data compression failed: ", stream.msg, " #(4.3.0)");
+    _exit(111);
+  }
+}
+void compression_done(void)
+{
+  if (stream.avail_out != sizeof(zbuf)) {
+    /* there is some data left, ignore */
+  }
+  if (inflateEnd(&stream) != Z_OK) {
+    out("ZFinishing data compression failed: ", stream.msg, " #(4.3.0)");
+    _exit(111);
+  }
+  percent = 100 - (int)(100.0*stream.total_in/stream.total_out);
+}
+#endif
 
 void resources() { _exit(111); }
+void badproto() { _exit(100); }
 
-int safewrite(fd,buf,len) int fd; char *buf; int len;
+int safewrite(int fd, void *buf, int len)
 {
   int r;
   r = write(fd,buf,len);
   if (r <= 0) _exit(0);
   return r;
 }
-int saferead(fd,buf,len) int fd; char *buf; int len;
+int saferead(int fd, void *buf,int len)
 {
   int r;
+#ifdef QMQP_COMPRESS
+  if (compressed == 0) {
+    int i;
+    char ch;
+    r = read(0,zbuf,len);
+    if (r <= 0) _exit(0);
+    for (i = 0; i < r; i++) {
+      ch = zbuf[i];
+      if (ch >= '0' && ch <= '9') continue;
+      if (ch == ':') {
+	byte_copy(buf, r, zbuf);
+	compressed = -1;
+	return r;
+      }
+      compressed = 1;
+      compression_init(r);
+      break;
+    }
+  }
+  if (compressed < 0) goto uncompressed;
+  if (compressed == 2) _exit(0);
+  stream.avail_out = len;
+  stream.next_out = buf;
+  do {
+    if (stream.avail_in == 0) {
+      r = read(fd,zbuf,sizeof(zbuf));
+      if (r <= 0) _exit(0); /* XXX ??? */
+      stream.avail_in = r;
+      stream.next_in = zbuf;
+    }
+    r = inflate(&stream, 0);
+    switch (r) {
+    case Z_OK:
+      if (stream.avail_out == 0)
+	return len;
+      break;
+    case Z_STREAM_END:
+      compression_done();
+      compressed = 2;
+      return len - stream.avail_out;
+    default:
+      out("ZReceiving compressed data failed: ", stream.msg, " #(4.3.0)");
+      return -1;
+    }
+    if (stream.avail_out == (unsigned int)len) continue;
+    return len - stream.avail_out;
+  } while (1);
+uncompressed:
+#endif 
   r = read(fd,buf,len);
   if (r <= 0) _exit(0);
   return r;
@@ -47,8 +153,9 @@
 
   for (;;) {
     getbyte(&ch);
-    if (ch == ':') return len;
     if (len > 200000000) resources();
+    if (ch == ':') return len;
+    if (ch < '0' || ch > '9') badproto();
     len = 10 * len + (ch - '0');
   }
 }
@@ -57,17 +164,17 @@
 {
   char ch;
   getbyte(&ch);
-  if (ch != ',') _exit(100);
+  if (ch != ',') badproto();
 }
 
 struct qmail qq;
 
 void identify()
 {
-  char *remotehost;
-  char *remoteinfo;
-  char *remoteip;
-  char *local;
+  const char *remotehost;
+  const char *remoteinfo;
+  const char *remoteip;
+  const char *local;
 
   remotehost = env_get("TCPREMOTEHOST");
   if (!remotehost) remotehost = "unknown";
@@ -78,16 +185,21 @@
   if (!local) local = env_get("TCPLOCALIP");
   if (!local) local = "unknown";
  
-  received(&qq,"QMQP",local,remoteip,remotehost,remoteinfo,(char *) 0);
+#ifdef QMQP_COMPRESS
+  if (compressed > 0)
+    received(&qq,"compressed QMQP",local,remoteip,remotehost,remoteinfo,(char *) 0,(char *) 0,(char *) 0);
+  else
+#endif
+  received(&qq,"QMQP",local,remoteip,remotehost,remoteinfo,(char *) 0,(char *) 0,(char *) 0);
 }
 
-char buf[1000];
+char buf[1000 + 20 + FMT_ULONG];
 char strnum[FMT_ULONG];
 
-int getbuf()
+int getbuf(void)
 {
   unsigned long len;
-  int i;
+  unsigned long i;
 
   len = getlen();
   if (len >= 1000) {
@@ -105,9 +217,9 @@
 
 int flagok = 1;
 
-main()
+int main(int argc, char **argv)
 {
-  char *result;
+  const char *result;
   unsigned long qp;
   unsigned long len;
   char ch;
@@ -116,6 +228,10 @@
   sig_alarmcatch(resources);
   alarm(3600);
 
+#ifdef QMQP_COMPRESS
+  if (env_get("NOCOMPRESS")) compressed = -1;
+#endif
+
   bytesleft = getlen();
 
   len = getlen();
@@ -158,6 +274,17 @@
     len += fmt_ulong(buf + len,(unsigned long) now());
     len += fmt_str(buf + len," qp ");
     len += fmt_ulong(buf + len,qp);
+#ifdef QMQP_COMPRESS
+    if (compressed > 0) {
+      len += fmt_str(buf + len, " DDC saved ");
+      if (percent < 0) {
+        len += fmt_str(buf + len, "-");
+        percent *= -1;
+      }
+      len += fmt_uint(buf + len, percent);
+      len += fmt_str(buf + len, " percent");
+    }
+#endif
     buf[len] = 0;
     result = buf;
   }
@@ -165,10 +292,13 @@
   if (!flagok)
     result = "Dsorry, I can't accept addresses like that (#5.1.3)";
 
-  substdio_put(&ssout,strnum,fmt_ulong(strnum,(unsigned long) str_len(result)));
+  substdio_put(&ssout,strnum,fmt_uint(strnum,str_len(result)));
   substdio_puts(&ssout,":");
   substdio_puts(&ssout,result);
+  substdio_puts(subfderr,result + 1);
+  substdio_puts(subfderr, "\n");
+  substdio_flush(subfderr);
   substdio_puts(&ssout,",");
   substdio_flush(&ssout);
-  _exit(0);
+  return 0;
 }
diff -ruN qmail-1.03-orig/qmail-qmqpd.rules qmail-1.03-ldap-20060201-orig/qmail-qmqpd.rules
--- qmail-1.03-orig/qmail-qmqpd.rules	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/qmail-qmqpd.rules	2006-02-25 11:00:55.000000000 +0100
@@ -0,0 +1,10 @@
+#
+# QMQP (qmail mail queueing protocol) server rules.
+# QMQP is mainly used in clusters to forward mails. The protocol accepts all
+# mails by default and so it is necessary to disable this service by default.
+# Only allow it for cluster hosts.
+# Currently there are no useful env vars for qmail-qmqpd.
+#
+#192.168.0.2:allow
+:deny
+
diff -ruN qmail-1.03-orig/qmail-qmqpd.sh qmail-1.03-ldap-20060201-orig/qmail-qmqpd.sh
--- qmail-1.03-orig/qmail-qmqpd.sh	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/qmail-qmqpd.sh	2006-02-25 11:00:55.000000000 +0100
@@ -0,0 +1,28 @@
+#!/bin/sh
+exec 2>&1
+#
+# QMQP service 
+#
+QMAIL="%QMAIL%"
+ME="`head -1 $QMAIL/control/me`"
+QUSER="qmaild"
+
+PATH="$QMAIL/bin:$PATH"
+
+# source the environemt in ./env
+eval `env - PATH=$PATH envdir ./env awk '\
+	BEGIN { for (i in ENVIRON) \
+		if (i != "PATH") { \
+			printf "export %s=\"%s\"\\n", i, ENVIRON[i] \
+		} \
+	}'`
+
+# enforce some sane defaults
+QUSER=${QUSER:="qmaild"}
+
+exec \
+	envuidgid $QUSER \
+	tcpserver -v -URl $ME -x$QMAIL/control/qmail-qmqpd.cdb \
+	    ${CONCURRENCY:+"-c$CONCURRENCY"} ${BACKLOG:+"-b$BACKLOG"} 0 628 \
+	$QMAIL/bin/qmail-qmqpd
+
diff -ruN qmail-1.03-orig/qmail-qmtpd.c qmail-1.03-ldap-20060201-orig/qmail-qmtpd.c
--- qmail-1.03-orig/qmail-qmtpd.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/qmail-qmtpd.c	2006-02-25 11:00:55.000000000 +0100
@@ -1,3 +1,4 @@
+#include <unistd.h>
 #include "stralloc.h"
 #include "substdio.h"
 #include "qmail.h"
@@ -11,11 +12,12 @@
 #include "readwrite.h"
 #include "control.h"
 #include "received.h"
+#include "scan.h"
 
 void badproto() { _exit(100); }
 void resources() { _exit(111); }
 
-int safewrite(fd,buf,len) int fd; char *buf; int len;
+int safewrite(int fd, void *buf, int len)
 {
   int r;
   r = write(fd,buf,len);
@@ -26,7 +28,7 @@
 char ssoutbuf[256];
 substdio ssout = SUBSTDIO_FDBUF(safewrite,1,ssoutbuf,sizeof ssoutbuf);
 
-int saferead(fd,buf,len) int fd; char *buf; int len;
+int saferead(int fd, void *buf, int len)
 {
   int r;
   substdio_flush(&ssout);
@@ -38,14 +40,15 @@
 char ssinbuf[512];
 substdio ssin = SUBSTDIO_FDBUF(saferead,0,ssinbuf,sizeof ssinbuf);
 
-unsigned long getlen()
+unsigned long getlen(void)
 {
   unsigned long len = 0;
   char ch;
   for (;;) {
     substdio_get(&ssin,&ch,1);
-    if (ch == ':') return len;
     if (len > 200000000) resources();
+    if (ch == ':') return len;
+    if (ch < '0' || ch > '9') badproto();
     len = 10 * len + (ch - '0');
   }
 }
@@ -57,36 +60,35 @@
   if (ch != ',') badproto();
 }
 
-unsigned int databytes = 0;
-unsigned int bytestooverflow = 0;
+unsigned long databytes = 0;
+unsigned long bytestooverflow = 0;
 struct qmail qq;
 
 char buf[1000];
 char buf2[100];
 
-char *remotehost;
-char *remoteinfo;
-char *remoteip;
-char *local;
+const char *remotehost;
+const char *remoteinfo;
+const char *remoteip;
+const char *local;
 
 stralloc failure = {0};
 
 char *relayclient;
-int relayclientlen;
+unsigned int relayclientlen;
 
-main()
+int main()
 {
   char ch;
-  int i;
+  unsigned int i;
   unsigned long biglen;
   unsigned long len;
   int flagdos;
   int flagsenderok;
   int flagbother;
   unsigned long qp;
-  char *result;
+  const char *result;
   char *x;
-  unsigned long u;
  
   sig_pipeignore();
   sig_alarmcatch(resources);
@@ -99,9 +101,9 @@
   relayclient = env_get("RELAYCLIENT");
   relayclientlen = relayclient ? str_len(relayclient) : 0;
  
-  if (control_readint(&databytes,"control/databytes") == -1) resources();
+  if (control_readulong(&databytes,"control/databytes") == -1) resources();
   x = env_get("DATABYTES");
-  if (x) { scan_ulong(x,&u); databytes = u; }
+  if (x) scan_ulong(x,&databytes);
   if (!(databytes + 1)) --databytes;
  
   remotehost = env_get("TCPREMOTEHOST");
@@ -113,6 +115,7 @@
   if (!local) local = env_get("TCPLOCALIP");
   if (!local) local = "unknown";
  
+  flagdos = 0;
   for (;;) {
     if (!stralloc_copys(&failure,"")) resources();
     flagsenderok = 1;
@@ -130,7 +133,7 @@
     else if (ch == 13) flagdos = 1;
     else badproto();
  
-    received(&qq,"QMTP",local,remoteip,remotehost,remoteinfo,(char *) 0);
+    received(&qq,"QMTP",local,remoteip,remotehost,remoteinfo,(char *) 0,(char *) 0,(char *) 0);
  
     /* XXX: check for loops? only if len is big? */
  
@@ -192,8 +195,9 @@
         if (!biglen) badproto();
         substdio_get(&ssin,&ch,1);
         --biglen;
-        if (ch == ':') break;
         if (len > 200000000) resources();
+        if (ch == ':') break;
+	if (ch < '0' || ch > '9') badproto();
         len = 10 * len + (ch - '0');
       }
       if (len >= biglen) badproto();
@@ -265,4 +269,6 @@
  
     /* ssout will be flushed when we read from the network again */
   }
+  /* NOTREACHED */
+  return 0;
 }
diff -ruN qmail-1.03-orig/qmail-qread.c qmail-1.03-ldap-20060201-orig/qmail-qread.c
--- qmail-1.03-orig/qmail-qread.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/qmail-qread.c	2006-02-25 11:00:55.000000000 +0100
@@ -1,5 +1,6 @@
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <unistd.h>
 #include "stralloc.h"
 #include "substdio.h"
 #include "subfd.h"
@@ -20,9 +21,9 @@
 
 void die(n) int n; { substdio_flush(subfdout); _exit(n); }
 
-void warn(s1,s2) char *s1; char *s2;
+void warn(s1,s2) const char *s1; const char *s2;
 {
- char *x;
+ const char *x;
  x = error_str(errno);
  substdio_puts(subfdout,s1);
  substdio_puts(subfdout,s2);
@@ -105,7 +106,7 @@
 
 stralloc line = {0};
 
-void main()
+int main()
 {
  int channel;
  int match;
@@ -118,7 +119,7 @@
  if (chdir("queue") == -1) die_chdir();
  readsubdir_init(&rs,"info",die_opendir);
 
- while (x = readsubdir_next(&rs,&id))
+ while ((x = readsubdir_next(&rs,&id)))
    if (x > 0)
     {
      fmtqfn(fnmess,"mess/",id,1);
@@ -133,7 +134,7 @@
 
      fd = open_read(fninfo);
      if (fd == -1) { err(id); continue; }
-     substdio_fdbuf(&ss,read,fd,inbuf,sizeof(inbuf));
+     substdio_fdbuf(&ss,subread,fd,inbuf,sizeof(inbuf));
      if (getln(&ss,&sender,&match,0) == -1) die_nomem();
      if (fstat(fd,&st) == -1) { close(fd); err(id); continue; }
      close(fd);
@@ -172,4 +173,5 @@
     }
 
  die(0);
+ return 0;
 }
diff -ruN qmail-1.03-orig/qmail-qstat.sh qmail-1.03-ldap-20060201-orig/qmail-qstat.sh
--- qmail-1.03-orig/qmail-qstat.sh	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/qmail-qstat.sh	2006-02-25 11:00:55.000000000 +0100
@@ -1,7 +1,13 @@
 cd QMAIL
 messdirs=`echo queue/mess/* | wc -w`
 messfiles=`find queue/mess/* -print | wc -w`
+if test -d "queue/todo/0"
+then
+tododirs=`echo queue/todo/* | wc -w`
+todofiles=`find queue/todo/* -print | wc -w`
+else
 tododirs=`echo queue/todo | wc -w`
 todofiles=`find queue/todo -print | wc -w`
+fi
 echo messages in queue: `expr $messfiles - $messdirs`
 echo messages in queue but not yet preprocessed: `expr $todofiles - $tododirs`
diff -ruN qmail-1.03-orig/qmail-queue.c qmail-1.03-ldap-20060201-orig/qmail-queue.c
--- qmail-1.03-orig/qmail-queue.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/qmail-queue.c	2006-02-25 11:00:55.000000000 +0100
@@ -1,5 +1,6 @@
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <unistd.h>
 #include "readwrite.h"
 #include "sig.h"
 #include "exit.h"
@@ -20,6 +21,19 @@
 #define DEATH 86400 /* 24 hours; _must_ be below q-s's OSSIFIED (36 hours) */
 #define ADDR 1003
 
+#ifdef BIGBROTHER
+#include "byte.h"
+#include "constmap.h"
+#include "control.h"
+#include "stralloc.h"
+
+int bbon = 0;
+stralloc bbs = {0};
+stralloc bbaddr = {0};
+struct constmap mapbb;
+
+#endif
+
 char inbuf[2048];
 struct substdio ssin;
 char outbuf[256];
@@ -57,6 +71,9 @@
 void die(e) int e; { _exit(e); }
 void die_write() { cleanup(); die(53); }
 void die_read() { cleanup(); die(54); }
+#ifdef BIGBROTHER
+void die_bb() { cleanup(); die(51); }
+#endif
 void sigalrm() { /* thou shalt not clean up here */ die(52); }
 void sigbug() { die(81); }
 
@@ -151,14 +168,30 @@
 
 char tmp[FMT_ULONG];
 
-void main()
+int main()
 {
  unsigned int len;
  char ch;
+#ifdef BIGBROTHER
+ unsigned int xlen, n;
+ char *x;
+ const char *b;
+#endif
 
  sig_blocknone();
  umask(033);
  if (chdir(auto_qmail) == -1) die(61);
+
+#ifdef BIGBROTHER
+ if (control_init() == -1) die(55);
+ switch (control_readfile(&bbs,"control/bigbrother",0))
+  {
+   case -1: die(55);
+   case 0: bbon = 0; if (!constmap_init(&mapbb,"",0,1)) die(51); break;
+   case 1: bbon = 1; if (!constmap_init(&mapbb,bbs.s,bbs.len,1)) die(51); break;
+  } 
+#endif
+ 
  if (chdir("queue") == -1) die(62);
 
  mypid = getpid();
@@ -180,15 +213,20 @@
 
  messnum = pidst.st_ino;
  messfn = fnnum("mess/",1);
+#ifndef BIGTODO
  todofn = fnnum("todo/",0);
  intdfn = fnnum("intd/",0);
+#else
+ todofn = fnnum("todo/",1);
+ intdfn = fnnum("intd/",1);
+#endif
 
  if (link(pidfn,messfn) == -1) die(64);
  if (unlink(pidfn) == -1) die(63);
  flagmademess = 1;
 
- substdio_fdbuf(&ssout,write,messfd,outbuf,sizeof(outbuf));
- substdio_fdbuf(&ssin,read,0,inbuf,sizeof(inbuf));
+ substdio_fdbuf(&ssout,subwrite,messfd,outbuf,sizeof(outbuf));
+ substdio_fdbuf(&ssin,subread,0,inbuf,sizeof(inbuf));
 
  if (substdio_bput(&ssout,received,receivedlen) == -1) die_write();
 
@@ -205,8 +243,8 @@
  if (intdfd == -1) die(65);
  flagmadeintd = 1;
 
- substdio_fdbuf(&ssout,write,intdfd,outbuf,sizeof(outbuf));
- substdio_fdbuf(&ssin,read,1,inbuf,sizeof(inbuf));
+ substdio_fdbuf(&ssout,subwrite,intdfd,outbuf,sizeof(outbuf));
+ substdio_fdbuf(&ssin,subread,1,inbuf,sizeof(inbuf));
 
  if (substdio_bput(&ssout,"u",1) == -1) die_write();
  if (substdio_bput(&ssout,tmp,fmt_ulong(tmp,uid)) == -1) die_write();
@@ -223,6 +261,9 @@
   {
    if (substdio_get(&ssin,&ch,1) < 1) die_read();
    if (substdio_put(&ssout,&ch,1) == -1) die_write();
+#ifdef BIGBROTHER
+   if (bbon) if (!stralloc_catb(&bbaddr, &ch, 1)) die_bb();
+#endif
    if (!ch) break;
   }
  if (len >= ADDR) die(11);
@@ -239,16 +280,39 @@
     {
      if (substdio_get(&ssin,&ch,1) < 1) die_read();
      if (substdio_bput(&ssout,&ch,1) == -1) die_write();
+#ifdef BIGBROTHER
+     if (bbon) if (!stralloc_catb(&bbaddr, &ch, 1)) die_bb();
+#endif
      if (!ch) break;
     }
    if (len >= ADDR) die(11);
   }
-
+ 
+#ifdef BIGBROTHER
+ if (bbon) {
+   x = bbaddr.s;
+   xlen = bbaddr.len;
+   do
+    {
+     n = byte_chr(x,xlen,0);
+     if ((b = constmap(&mapbb, x, n))) {
+       if (*b) {
+         if (substdio_bput(&ssout,"T", 1) == -1) die_write();
+         if (substdio_bputs(&ssout,b) == -1) die_write();
+         if (substdio_bput(&ssout,"",1) == -1) die_write();
+       }
+     }
+     if (n++ >= xlen) break;
+     x += n; xlen -= n;
+    } while (xlen > 0);
+ }
+#endif
+ 
  if (substdio_flush(&ssout) == -1) die_write();
  if (fsync(intdfd) == -1) die_write();
 
  if (link(intdfn,todofn) == -1) die(66);
 
  triggerpull();
- die(0);
+ return 0;
 }
diff -ruN qmail-1.03-orig/qmail-quotawarn.c qmail-1.03-ldap-20060201-orig/qmail-quotawarn.c
--- qmail-1.03-orig/qmail-quotawarn.c	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/qmail-quotawarn.c	2006-02-25 11:00:55.000000000 +0100
@@ -0,0 +1,423 @@
+/*
+ * Copyright (c) 1999-2004 Claudio Jeker,
+ *      Internet Business Solutions AG, CH-8005 Zürich, Switzerland
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Internet Business
+ *      Solutions AG and its contributors.
+ * 4. Neither the name of the author nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <dirent.h>
+#include <unistd.h>
+
+#include "auto_qmail.h"
+#include "byte.h"
+#include "case.h"
+#include "control.h"
+#include "date822fmt.h"
+#include "datetime.h"
+#include "env.h"
+#include "error.h"
+#include "exit.h"
+#include "fmt.h"
+#include "getln.h"
+#include "mailmagic.h"
+#include "myctime.h"
+#include "newfield.h"
+#include "now.h"
+#include "open.h"
+#include "qmail-ldap.h"
+#include "readwrite.h"
+#include "seek.h"
+#include "sig.h"
+#include "str.h"
+#include "strerr.h"
+#include "stralloc.h"
+#include "substdio.h"
+#include "wait.h"
+#include "lock.h"
+
+/* global vars */
+stralloc warning = {0};
+stralloc me = {0};
+stralloc to = {0};
+stralloc from = {0};
+stralloc subject = {0};
+stralloc header = {0};
+stralloc qwline = {0};
+stralloc temp = {0};
+
+#define FATAL "qmail-quotawarn: fatal: "
+#define WARN  "qmail-quotawarn: warn: "
+
+void
+temp_nomem(void)
+{
+	strerr_die2x(111, FATAL, "Out of memory.");
+}
+void
+temp_qmail(char *fn)
+{
+	strerr_die4sys(111, FATAL, "Unable to open ", fn, ": ");
+}
+void
+temp_rewind(void)
+{
+	strerr_die2x(111, FATAL, "Unable to rewind message.");
+}
+void
+temp_slowlock()
+{
+	strerr_die2x(111, FATAL, 
+	    "File has been locked for 30 seconds straight. (#4.3.0)");
+}
+
+void check_maildir(void);
+void write_maildir(void);
+void check_mailfile(char* fn);
+void write_mailfile(char* fn);
+
+void
+readcontrol(void)
+{
+	int	fddir;
+
+	fddir = open_read(".");
+	if (fddir == -1)
+		strerr_die2sys(111, FATAL, "Unable to open cwd: ");
+	if (chdir(auto_qmail) == -1)
+		strerr_die4sys(111, FATAL, "Unable to switch to ",
+		    auto_qmail, ": ");
+
+	if (control_init() == -1)
+		strerr_die2sys(111, FATAL, "Unable to read controls: ");
+	if (control_readline(&me, "control/me") != 1)
+		strerr_die2sys(111, FATAL, "Unable to read control/me: ");
+	if (control_readrawfile(&warning, "control/quotawarning") == -1)
+		strerr_die2sys(111, FATAL,
+		    "Unable to read control/quotawarning: ");
+	else if (warning.len == 0)
+		_exit(0);
+	
+	if (fchdir(fddir) == -1)
+		strerr_die2sys(111,FATAL,"unable to switch back to cwd: ");
+	close(fddir);
+}
+
+int
+main(int argc, char **argv) 
+{
+	char *s;
+	char *fn;
+
+
+	if(!argv[1] || argv[2]) 
+		strerr_die1x(100,
+		    "qmail-quotawarn: usage: qmail-quotawarn mailbox.");
+
+	fn = argv[1];
+
+	readcontrol();
+	
+	if (!env_init()) temp_nomem();
+	if (!(s = env_get("USER")))
+		strerr_die1x(100, "UESR environment not present.");  
+	if (!stralloc_copys(&qwline, "Qmail-QuotaWarning: ")) temp_nomem();
+	if (!stralloc_cats(&qwline, s)) temp_nomem();
+	if (!stralloc_append(&qwline, "@")) temp_nomem();
+	if (!(s = env_get("HOST")))
+		strerr_die1x(100, "HOST environment not present.");  
+	if (!stralloc_cats(&qwline, s)) temp_nomem();
+	if (!stralloc_append(&qwline, "\n")) temp_nomem();
+
+	if (fn[str_len(fn)-1] == '/') {
+		if (chdir(fn) == -1)
+			strerr_die3sys(111, "Unable to switch to ", fn, ": ");
+		check_maildir();
+		write_maildir();
+	} else {
+		check_mailfile(fn);
+		write_mailfile(fn);
+	}
+	/* NOTREACHED */
+	return 1;
+}
+
+static char timebuf[DATE822FMT];
+
+struct mheader mheader[] = {
+	{ "From:", 0, ALLOW, 0 },
+	{ "To:", 0, FORCE, 0 },
+	{ "Subject:", "QUOTA-WARNING!\n", ALLOW, 0 },
+	{ "MIME-Version:", "1.0", FORCE, 0 },
+	{ "Content-Type:", "text/plain; charset=\"iso-8859-1\"\n", ALLOW, 0 },
+	{ "Content-Transfer-Encoding:", "8bit", ALLOW, 0 },
+	{ "X-", 0, ALLOW, 0 },
+	{ DEFAULT, 0, DENY, 0 },
+	{ 0, 0, 0, 0 }
+};
+
+int
+writemail(substdio *ssout, datetime_sec starttime)
+{
+	struct datetime dt;
+	char *t;
+	int offset;
+
+	/* store default To: From: Subject: */
+	if (! (t = env_get("RECIPIENT")))
+		strerr_die2x(111, FATAL, "RECIPIENT not present");
+	mheader[1].v = t;
+
+	if (!stralloc_copys(&from, "Qmail-QUOTAGUARD <MAILER-DAEMON@"))
+		temp_nomem();
+	if (!stralloc_cat(&from, &me)) temp_nomem();
+	if (!stralloc_cats(&from, ">\n")) temp_nomem();
+	if (!stralloc_0(&from)) temp_nomem();
+	mheader[0].v = from.s;
+	
+	
+	offset = headermagic(&warning, &header, 0, mheader);
+	if (offset == -1) {
+		if (errno == error_nomem) temp_nomem();
+		return 0;
+	}
+
+	/*
+	 * start writing header, first set:
+	 * Return-Path: Delivered-to: Qmail-QuotaWarning:
+	 * Received: Message-ID: Date:
+	 */
+	if (substdio_puts(ssout, "Return-Path: <>\n") == -1) return 0;
+
+	if (!(t = env_get("DTLINE")))
+		strerr_die2x(111, FATAL, "DTLINE not present");
+	if (substdio_puts(ssout, t) == -1) return 0;
+	/* Qmail-QuotaWarning: line */
+	if (substdio_put(ssout, qwline.s, qwline.len)) return 0;
+	/* Received: line */
+	if (substdio_puts(ssout,
+		    "Received: (directly through the "
+		    "qmail-quotawarning program);\n\t"))
+		return 0;
+	datetime_tai(&dt, starttime);
+	if (substdio_put(ssout, timebuf, date822fmt(timebuf, &dt))) return 0;
+	
+	/* message-id and date line */
+	if (!newfield_datemake(starttime)) temp_nomem();
+	if (!newfield_msgidmake(me.s, me.len, starttime)) temp_nomem();
+	if (substdio_put(ssout, newfield_msgid.s, newfield_msgid.len))
+		return 0;
+	if (substdio_put(ssout, newfield_date.s, newfield_date.len))
+		return 0;
+	
+	
+	/* To: From: and Subject: */
+	if (substdio_put(ssout, header.s, header.len)) return 0;
+	/* don't forget the single \n */
+	if (substdio_puts(ssout, "\n")) return 0;
+	/* the Warning */
+	if (substdio_put(ssout, warning.s + offset, warning.len - offset))
+		return 0;
+	if (warning.s[warning.len-1] == '\n')
+		if (substdio_bputs(ssout, "\n")) return 0;
+	
+	return 1;
+}
+
+void
+check_maildir(void)
+{
+	char const *(dirs[2]);
+	DIR *folder;
+	struct dirent *entry;
+	int i;
+	unsigned int j;
+
+	dirs[0]="new"; dirs[1]="cur"; 
+	for (i=0; i<2; i++) {
+		/* checking for old mail */
+		if ((folder = opendir(dirs[i])) == 0)
+			strerr_die3sys(111, "Unable to opendir ", dirs[i], ": ");
+		while ((entry = readdir(folder)) != 0) {
+			if (*entry->d_name == '.') continue;
+			j = str_rchr(entry->d_name, '.');
+			if (entry->d_name[j++] == '\0') continue;
+			if (!str_diffn("QUOTA_WARNING", &entry->d_name[j], 13))
+				_exit(0);
+		}
+		closedir(folder);
+	}
+}
+
+char fntmptph[80 + FMT_ULONG * 2];
+char fnnewtph[83 + FMT_ULONG * 3];
+void tryunlinktmp(void) { unlink(fntmptph); }
+void sigalrm(void)
+{
+	tryunlinktmp();
+	strerr_die1x(111, "Timeout on quota-warning delivery.");
+}
+
+char buf[1024];
+
+void
+write_maildir(void)
+{
+	char *s;
+	int loop;
+	int pid;
+	int fd;
+	datetime_sec starttime;
+	struct stat st;
+	substdio ssout;
+
+	sig_alarmcatch(sigalrm);
+
+	pid = getpid();
+	starttime = now();
+	for (loop = 0;;++loop) {
+		s = fntmptph;
+		s += fmt_str(s, "tmp/");
+		s += fmt_ulong(s, starttime); *s++ = '.';
+		s += fmt_ulong(s, pid); *s++ = '.';
+		s += fmt_str(s, "QUOTA_WARNING"); 
+		*s++ = 0;
+		if (stat(fntmptph, &st) == -1) if (errno == error_noent) break;
+		/* really should never get to this point */
+		if (loop == 2)
+			strerr_die2sys(111, FATAL, "Could not stat tmp file: ");
+		sleep(2);
+	}
+	str_copy(fnnewtph, fntmptph);
+	byte_copy(fnnewtph, 3, "new");
+
+	alarm(86400);
+	fd = open_excl(fntmptph);
+	if (fd == -1)
+		strerr_die2sys(111, FATAL, "Unable to open tmp file: ");
+
+	substdio_fdbuf(&ssout, subwrite, fd, buf, sizeof(buf));
+	if (writemail(&ssout, starttime) == 0) goto fail;
+	if (substdio_flush(&ssout) == -1) goto fail;
+
+	if (fsync(fd) == -1) goto fail;
+	if (fstat(fd, &st) == -1) goto fail;
+	if (close(fd) == -1) goto fail; /* NFS dorks */
+
+	s = fnnewtph;
+	while( *s ) s++;
+	s += fmt_str(s, ",S=");
+	s += fmt_ulong(s, (unsigned long) st.st_size);
+	*s++ = 0;
+
+	if (link(fntmptph, fnnewtph) == -1)
+		/* if error_exist unlink and exit(0),
+		 * strange things can happen */
+		if ( errno != error_exist) goto fail;
+
+	tryunlinktmp();
+	_exit(0);
+
+fail:
+	strerr_warn2(FATAL, "Writing Quota-Warning to maildir failed: ",
+	    &strerr_sys);
+	tryunlinktmp();
+	_exit(111);
+}
+
+void
+check_mailfile(char* fn)
+{
+	int fd;
+	int match;
+	substdio ss;
+
+	fd = open_read(fn);
+	if (seek_begin(fd) == -1) temp_rewind();
+
+	substdio_fdbuf(&ss, subread, fd, buf, sizeof(buf));
+	do {
+		if(getln(&ss, &temp, &match, '\n') != 0) {
+			strerr_warn2(WARN, "Unable to read message: ",
+			    &strerr_sys);
+			break;
+		}
+		if (temp.len == qwline.len)
+			if (!case_diffb(qwline.s, qwline.len, temp.s)) {
+				/* quota warning already in mailbox */
+				close(fd);
+				_exit(0);
+			}
+	} while (match);
+	/* no quota warning found */
+	close(fd);
+}
+
+void
+write_mailfile(char* fn)
+{
+	int fd;
+	substdio ssout;
+	seek_pos pos;
+	int flaglocked;
+	datetime_sec starttime;
+
+	starttime = now();
+
+	fd = open_append(fn);
+	if (fd == -1)
+		strerr_die4sys(111, FATAL, "Unable to open ", fn, ": ");
+
+	sig_alarmcatch(temp_slowlock);
+	alarm(30);
+	flaglocked = (lock_ex(fd) != -1);
+	alarm(0);
+	sig_alarmdefault();
+
+	seek_end(fd);
+	pos = seek_cur(fd);
+
+	substdio_fdbuf(&ssout, subwrite, fd, buf, sizeof(buf));
+	if (substdio_puts(&ssout, "From MAILER-DAEMON ")) goto writeerrs;
+	if (substdio_puts(&ssout, myctime(starttime))) goto writeerrs;
+	if (writemail(&ssout, starttime) == 0) goto writeerrs;
+	if (substdio_bputs(&ssout, "\n")) goto writeerrs;
+	if (substdio_flush(&ssout)) goto writeerrs;
+	if (fsync(fd) == -1) goto writeerrs;
+	close(fd);
+	_exit(0);
+
+writeerrs:
+	strerr_warn4(FATAL, "Unable to write ", fn, ": ", &strerr_sys);
+	if (flaglocked) seek_trunc(fd, pos);
+	close(fd);
+	_exit(111);
+}
+
diff -ruN qmail-1.03-orig/qmail-remote.c qmail-1.03-ldap-20060201-orig/qmail-remote.c
--- qmail-1.03-orig/qmail-remote.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/qmail-remote.c	2006-02-25 11:00:55.000000000 +0100
@@ -1,7 +1,10 @@
 #include <sys/types.h>
+#include <sys/stat.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
+#include <netinet/tcp.h>
 #include <arpa/inet.h>
+#include <unistd.h>
 #include "sig.h"
 #include "stralloc.h"
 #include "substdio.h"
@@ -14,6 +17,7 @@
 #include "dns.h"
 #include "alloc.h"
 #include "quote.h"
+#include "fmt.h"
 #include "ip.h"
 #include "ipalloc.h"
 #include "ipme.h"
@@ -28,65 +32,97 @@
 #include "timeoutconn.h"
 #include "timeoutread.h"
 #include "timeoutwrite.h"
+#include "base64.h"
+#include "xtext.h"
+#ifdef TLS_REMOTE /* openssl/ssh.h needs to be included befor zlib.h else ... */
+#include <sys/stat.h>
+#include <openssl/ssl.h>
+#ifdef TLSDEBUG
+#include <openssl/err.h>
+#endif
+#endif
+#ifdef DATA_COMPRESS
+#include <zlib.h>
+#endif
+
+#ifdef TLS_REMOTE
+SSL *ssl = 0;
+#endif
 
 #define HUGESMTPTEXT 5000
 
+#ifndef PORT_SMTP /* this is for testing purposes, so you can overwrite it */
 #define PORT_SMTP 25 /* silly rabbit, /etc/services is for users */
-unsigned long port = PORT_SMTP;
+#endif
+#ifndef PORT_QMTP /* this is for testing purposes, so you can overwrite it */
+#define PORT_QMTP 209 /* silly rabbit, /etc/services is for users */
+#endif
+unsigned long smtp_port = PORT_SMTP;
+unsigned long qmtp_port = PORT_QMTP;
 
 GEN_ALLOC_typedef(saa,stralloc,sa,len,a)
 GEN_ALLOC_readyplus(saa,stralloc,sa,len,a,i,n,x,10,saa_readyplus)
 static stralloc sauninit = {0};
 
 stralloc helohost = {0};
+stralloc outgoingip = {0};
 stralloc routes = {0};
 struct constmap maproutes;
 stralloc host = {0};
 stralloc sender = {0};
+stralloc auth_login = {0};
+stralloc auth_passwd = {0};
 
 saa reciplist = {0};
 
 struct ip_address partner;
+struct ip_address outip;
 
-void out(s) char *s; { if (substdio_puts(subfdoutsmall,s) == -1) _exit(0); }
-void zero() { if (substdio_put(subfdoutsmall,"\0",1) == -1) _exit(0); }
-void zerodie() { zero(); substdio_flush(subfdoutsmall); _exit(0); }
-void outsafe(sa) stralloc *sa; { int i; char ch;
+void out(const char *s) { if (substdio_puts(subfdoutsmall,s) == -1) _exit(0); }
+void zero(void) { if (substdio_put(subfdoutsmall,"\0",1) == -1) _exit(0); }
+void zerodie(void) { zero(); substdio_flush(subfdoutsmall); _exit(0); }
+void outsafe(stralloc *sa) { unsigned int i; char ch;
 for (i = 0;i < sa->len;++i) {
 ch = sa->s[i]; if (ch < 33) ch = '?'; if (ch > 126) ch = '?';
 if (substdio_put(subfdoutsmall,&ch,1) == -1) _exit(0); } }
 
-void temp_nomem() { out("ZOut of memory. (#4.3.0)\n"); zerodie(); }
-void temp_oserr() { out("Z\
+void temp_noip(void) { out("Zinvalid ipaddr in control/outgoingip (#4.3.0)\n"); zerodie(); }
+void temp_nomem(void) { out("ZOut of memory. (#4.3.0)\n"); zerodie(); }
+void temp_oserr(void) { out("Z\
 System resources temporarily unavailable. (#4.3.0)\n"); zerodie(); }
-void temp_noconn() { out("Z\
+void temp_noconn(void) { out("Z\
 Sorry, I wasn't able to establish an SMTP connection. (#4.4.1)\n"); zerodie(); }
-void temp_read() { out("ZUnable to read message. (#4.3.0)\n"); zerodie(); }
-void temp_dnscanon() { out("Z\
+void temp_read(void) { out("ZUnable to read message. (#4.3.0)\n"); zerodie(); }
+void temp_dnscanon(void) { out("Z\
 CNAME lookup failed temporarily. (#4.4.3)\n"); zerodie(); }
-void temp_dns() { out("Z\
+void temp_dns(void) { out("Z\
 Sorry, I couldn't find any host by that name. (#4.1.2)\n"); zerodie(); }
-void temp_chdir() { out("Z\
+void temp_chdir(void) { out("Z\
 Unable to switch to home directory. (#4.3.0)\n"); zerodie(); }
-void temp_control() { out("Z\
+void temp_control(void) { out("Z\
 Unable to read control files. (#4.3.0)\n"); zerodie(); }
-void perm_partialline() { out("D\
+void temp_proto(void) { out("Z\
+recipient did not talk proper QMTP (#4.3.0)\n"); zerodie(); }
+void perm_partialline(void) { out("D\
 SMTP cannot transfer messages with partial final lines. (#5.6.2)\n"); zerodie(); }
-void perm_usage() { out("D\
+void perm_usage(void) { out("D\
 I (qmail-remote) was invoked improperly. (#5.3.5)\n"); zerodie(); }
-void perm_dns() { out("D\
+void perm_dns(void) { out("D\
 Sorry, I couldn't find any host named ");
 outsafe(&host);
 out(". (#5.1.2)\n"); zerodie(); }
-void perm_nomx() { out("D\
+void perm_nomx(void) { out("D\
 Sorry, I couldn't find a mail exchanger or IP address. (#5.4.4)\n");
 zerodie(); }
-void perm_ambigmx() { out("D\
+void perm_ambigmx(void) { out("D\
 Sorry. Although I'm listed as a best-preference MX or A for that host,\n\
 it isn't in my control/locals file, so I don't treat it as local. (#5.4.6)\n");
 zerodie(); }
+void perm_looping(void) { out("D\
+Sorry. Message is looping within cluster, giving up. (#5.4.6)\n");
+zerodie(); }
 
-void outhost()
+void outhost(void)
 {
   char x[IPFMT];
   if (substdio_put(subfdoutsmall,x,ip_fmt(x,&partner)) == -1) _exit(0);
@@ -94,7 +130,7 @@
 
 int flagcritical = 0;
 
-void dropped() {
+void dropped(void) {
   out("ZConnected to ");
   outhost();
   out(" but connection died. ");
@@ -107,32 +143,174 @@
 int smtpfd;
 int timeout = 1200;
 
-int saferead(fd,buf,len) int fd; char *buf; int len;
+#ifdef TLS_REMOTE
+int flagtimedout = 0;
+void sigalrm(int sig)
+{
+ flagtimedout = 1;
+}
+int ssl_timeoutread(int tout, int fd, void *buf, int n)
+{
+ int r; int saveerrno;
+ if (flagtimedout) { errno = error_timeout; return -1; }
+ alarm(tout);
+ r = SSL_read(ssl,buf,n);
+ saveerrno = errno;
+ alarm(0);
+ if (flagtimedout) { errno = error_timeout; return -1; }
+ errno = saveerrno;
+ return r;
+}
+int ssl_timeoutwrite(int tout, int fd, void *buf, int n)
+{
+ int r; int saveerrno;
+ if (flagtimedout) { errno = error_timeout; return -1; }
+ alarm(tout);
+ r = SSL_write(ssl,buf,n);
+ saveerrno = errno;
+ alarm(0);
+ if (flagtimedout) { errno = error_timeout; return -1; }
+ errno = saveerrno;
+ return r;
+}
+#endif 
+
+#ifdef DATA_COMPRESS
+z_stream stream;
+char zbuf[4096];
+int compdata = 0;
+int wantcomp = 0;
+
+void compression_init(void)
+{
+  compdata = 1;
+  stream.zalloc = Z_NULL;
+  stream.zfree = Z_NULL;
+  stream.opaque = Z_NULL;
+  stream.avail_out = sizeof(zbuf);
+  stream.next_out = zbuf;
+  if (deflateInit(&stream,Z_DEFAULT_COMPRESSION) != Z_OK) {
+    out("ZInitalizing data compression failed: ");
+    out(stream.msg); out(" #(4.3.0)\n");
+    zerodie();
+  }
+}
+void compression_done(void)
+{
+  int r;
+
+  compdata = 0;
+  do {
+    r = deflate(&stream,Z_FINISH);
+    switch (r) {
+    case Z_OK:
+      if (stream.avail_out == 0) {
+#ifdef TLS_REMOTE
+	if (ssl)
+	  r = ssl_timeoutwrite(timeout,smtpfd,zbuf,sizeof(zbuf));
+	else
+#endif
+	r = timeoutwrite(timeout,smtpfd,zbuf,sizeof(zbuf));
+	if (r <= 0) dropped();
+	stream.avail_out = sizeof(zbuf);
+	stream.next_out = zbuf;
+	r = Z_OK;
+      }
+      break;
+    case Z_STREAM_END:
+      break;
+    default:
+      out("ZSending compressed data to "); outhost();
+      out("but compression failed: ");
+      out(stream.msg); out(" (#4.4.2)\n");
+      zerodie();
+    }
+  } while (r!=Z_STREAM_END);
+  if (stream.avail_out != sizeof(zbuf)) {
+    /* write left data */
+#ifdef TLS_REMOTE
+    if (ssl)
+      r = ssl_timeoutwrite(timeout,smtpfd,zbuf,sizeof(zbuf)-stream.avail_out);
+    else
+#endif
+    r = timeoutwrite(timeout,smtpfd,zbuf,sizeof(zbuf)-stream.avail_out);
+    if (r <= 0) dropped();
+  }
+  if (deflateEnd(&stream) != Z_OK) {
+    out("ZFinishing data compression failed: ");
+    if (stream.msg) out(stream.msg); else out("unknown error");
+    if (flagcritical) out(". Possible duplicate!");
+    out(" #(4.3.0)\n");
+    zerodie();
+  }
+}
+#endif
+
+int saferead(int fd, void *buf, int len)
 {
   int r;
+#ifdef TLS_REMOTE
+  if (ssl)
+    r = ssl_timeoutread(timeout,smtpfd,buf,len);
+  else
+#endif
   r = timeoutread(timeout,smtpfd,buf,len);
   if (r <= 0) dropped();
   return r;
 }
-int safewrite(fd,buf,len) int fd; char *buf; int len;
+int safewrite(int fd, void *buf, int len)
 {
   int r;
+#ifdef DATA_COMPRESS
+  if (compdata == 1) {
+    stream.avail_in = len;
+    stream.next_in = buf;
+    do {
+      r = deflate(&stream, 0);
+      switch (r) {
+      case Z_OK:
+	if (stream.avail_out == 0) {
+#ifdef TLS_REMOTE
+	  if (ssl)
+	    r = ssl_timeoutwrite(timeout,smtpfd,zbuf,sizeof(zbuf));
+	  else
+#endif
+	  r = timeoutwrite(timeout,smtpfd,zbuf,sizeof(zbuf));
+	  if (r <= 0) dropped();
+	  stream.avail_out = sizeof(zbuf);
+	  stream.next_out = zbuf;
+	}
+	break;
+      default:
+	out("ZSending compressed data to "); outhost();
+	out("but compression failed: ");
+	out(stream.msg); out(" (#4.4.2)\n");
+	zerodie();
+      }
+    } while (stream.avail_in != 0);
+    return len;
+  }
+#endif
+#ifdef TLS_REMOTE
+  if (ssl)
+    r = ssl_timeoutwrite(timeout,smtpfd,buf,len);
+  else
+#endif
   r = timeoutwrite(timeout,smtpfd,buf,len);
   if (r <= 0) dropped();
   return r;
 }
 
-char inbuf[1024];
-substdio ssin = SUBSTDIO_FDBUF(read,0,inbuf,sizeof inbuf);
-char smtptobuf[1024];
+char inbuf[1500];
+substdio ssin = SUBSTDIO_FDBUF(subread,0,inbuf,sizeof inbuf);
+char smtptobuf[1500];
 substdio smtpto = SUBSTDIO_FDBUF(safewrite,-1,smtptobuf,sizeof smtptobuf);
 char smtpfrombuf[128];
 substdio smtpfrom = SUBSTDIO_FDBUF(saferead,-1,smtpfrombuf,sizeof smtpfrombuf);
 
 stralloc smtptext = {0};
 
-void get(ch)
-char *ch;
+void get(char *ch)
 {
   substdio_get(&smtpfrom,ch,1);
   if (*ch != '\r')
@@ -140,7 +318,7 @@
      if (!stralloc_append(&smtptext,ch)) temp_nomem();
 }
 
-unsigned long smtpcode()
+unsigned long smtpcode(void)
 {
   unsigned char ch;
   unsigned long code;
@@ -163,9 +341,9 @@
   return code;
 }
 
-void outsmtptext()
+void outsmtptext(void)
 {
-  int i; 
+  unsigned int i; 
   if (smtptext.s) if (smtptext.len) {
     out("Remote host said: ");
     for (i = 0;i < smtptext.len;++i)
@@ -175,21 +353,62 @@
   }
 }
 
-void quit(prepend,append)
-char *prepend;
-char *append;
+void quit(const char *prepend, const char *append)
 {
+#ifdef DATA_COMPRESS
+  int r;
+  char num[FMT_ULONG];
+#endif
   substdio_putsflush(&smtpto,"QUIT\r\n");
   /* waiting for remote side is just too ridiculous */
   out(prepend);
   outhost();
   out(append);
   out(".\n");
+#ifdef DATA_COMPRESS
+  if (wantcomp == 2) {
+	  r = 100 - (int)(100.0*stream.total_out/stream.total_in);
+	  if (r < 0) {
+	    num[0] = '-'; r*= -1;
+	  } else
+	    num[0] = ' ';
+	  num[fmt_uint(num+1,r) + 1] = 0;
+	  out("DDC saved ");
+	  out(num); out(" percent.\n");
+  }
+#endif
+/* TAG */
+#if defined(TLS_REMOTE) && defined(TLSDEBUG)
+#define ONELINE_NAME(X) X509_NAME_oneline(X,NULL,0)
+
+ if (ssl) {
+  X509 *peer;
+
+  out("STARTTLS proto="); out(SSL_get_version(ssl));
+  out("; cipher="); out(SSL_CIPHER_get_name(SSL_get_current_cipher(ssl)));
+
+  /* we want certificate details */
+  peer=SSL_get_peer_certificate(ssl);
+  if (peer != NULL) {
+   char *str;
+
+   str=ONELINE_NAME(X509_get_subject_name(peer));
+   out("; subject="); out(str);
+   OPENSSL_free(str);
+   str=ONELINE_NAME(X509_get_issuer_name(peer));
+   out("; issuer="); out(str);
+   OPENSSL_free(str);
+   X509_free(peer);
+  }
+  out(";\n");
+ }
+#endif
+
   outsmtptext();
   zerodie();
 }
 
-void blast()
+void blast(void)
 {
   int r;
   char ch;
@@ -214,25 +433,221 @@
   substdio_flush(&smtpto);
 }
 
+stralloc cookie = {0};
 stralloc recip = {0};
+#ifdef TLS_REMOTE
+stralloc sslcert = {0};
+#endif
+stralloc xtext = {0};
 
-void smtp()
+void smtp(void)
 {
+  struct stat st;
+  unsigned long len;
   unsigned long code;
   int flagbother;
-  int i;
- 
-  if (smtpcode() != 220) quit("ZConnected to "," but greeting failed");
- 
-  substdio_puts(&smtpto,"HELO ");
+  int flagsize;
+  int flagauth;
+  unsigned int i, j;
+  char num[FMT_ULONG];
+#ifdef TLS_REMOTE
+  int flagtls;
+  SSL_CTX *ctx;
+  int saveerrno, r;
+#ifdef TLSDEBUG
+  char buf[1024];
+#endif
+
+  flagtls = 0;
+#endif
+
+  code = smtpcode();
+  if (code >= 500) quit("DConnected to "," but greeting failed");
+  if (code >= 400) return;
+  if (code != 220) quit("ZConnected to "," but greeting failed");
+
+  if (cookie.len > 0)
+    if (smtptext.len > cookie.len + 1)
+      if (!str_diffn(smtptext.s + smtptext.len - cookie.len - 1,
+		  cookie.s, cookie.len))
+        perm_looping();
+  
+  flagsize = 0;
+  flagauth = 0;
+  substdio_puts(&smtpto,"EHLO ");
   substdio_put(&smtpto,helohost.s,helohost.len);
   substdio_puts(&smtpto,"\r\n");
   substdio_flush(&smtpto);
-  if (smtpcode() != 250) quit("ZConnected to "," but my name was rejected");
- 
+
+  code = smtpcode();
+  if (code != 250) {
+   substdio_puts(&smtpto,"HELO ");
+   substdio_put(&smtpto,helohost.s,helohost.len);
+   substdio_puts(&smtpto,"\r\n");
+   substdio_flush(&smtpto);
+   code = smtpcode();
+   if (code >= 500) quit("DConnected to "," but my name was rejected");
+   if (code >= 400) return;
+   if (code != 250) quit("ZConnected to "," but my name was rejected");
+  }
+
+  /* extension handling */
+  for (i = 0; i < smtptext.len; i += str_chr(smtptext.s+i,'\n') + 1) {
+    if (i+8 < smtptext.len && !case_diffb("SIZE", 4, smtptext.s+i+4) )
+      flagsize = 1;
+#ifdef DATA_COMPRESS
+    else if (i+9 < smtptext.len && !case_diffb("DATAZ", 5, smtptext.s+i+4))
+            wantcomp = 1;
+#endif
+#ifdef TLS_REMOTE
+    else if (i+12 < smtptext.len && !case_diffb("STARTTLS", 8, smtptext.s+i+4))
+      flagtls = 1;
+#endif
+    else if (i+9 < smtptext.len && !case_diffb("AUTH ", 5, smtptext.s+i+4)) {
+      for (j = i+4; j < smtptext.len; j++)
+	if (smtptext.s[j] == ' ')
+	  if (j + 6 < smtptext.len && !case_diffb("LOGIN", 5, smtptext.s+j+1))
+	    flagauth = 1;
+    }
+  }
+
+#ifdef TLS_REMOTE
+  if (flagtls) {
+    substdio_puts(&smtpto,"STARTTLS\r\n");
+    substdio_flush(&smtpto);
+    if (smtpcode() == 220) {
+#ifdef TLSDEBUG
+      SSL_load_error_strings();
+#endif
+      SSLeay_add_ssl_algorithms();
+      if (!(ctx=SSL_CTX_new(SSLv23_client_method()))) {
+#ifdef TLSDEBUG
+        out("ZTLS not available: error initializing ctx");
+        out(": ");
+        out(ERR_error_string(ERR_get_error(), buf));
+        out("\n");
+#else
+        out("ZTLS not available: error initializing ctx\n");
+#endif
+        out("\n");
+        zerodie();
+      }
+
+      if (sslcert.s && *sslcert.s) {
+        SSL_CTX_use_RSAPrivateKey_file(ctx, sslcert.s, SSL_FILETYPE_PEM);
+        SSL_CTX_use_certificate_file(ctx, sslcert.s, SSL_FILETYPE_PEM);
+      }
+      /*SSL_CTX_set_options(ctx, SSL_OP_NO_TLSv1);*/
+
+      if (!(ssl=SSL_new(ctx))) {
+#ifdef TLSDEBUG
+        out("ZTLS not available: error initializing ssl");
+        out(": ");
+        out(ERR_error_string(ERR_get_error(), buf));
+#else
+        out("ZTLS not available: error initializing ssl");
+#endif
+        out("\n");
+        zerodie();
+      }
+      SSL_set_fd(ssl,smtpfd);
+
+      alarm(timeout);
+      r = SSL_connect(ssl); saveerrno = errno;
+      alarm(0); 
+      if (flagtimedout) {
+        out("ZTLS not available: connect timed out\n");
+        zerodie();
+      }
+      errno = saveerrno;
+      if (r<=0) {
+#ifdef TLSDEBUG
+        out("ZTLS not available: connect failed");
+        out(": ");
+        out(ERR_error_string(ERR_get_error(), buf));
+        out("\n");
+#else
+        out("ZTLS not available: connect failed\n");
+#endif
+        zerodie();
+      }
+
+      /* re-EHLO as per RFC */
+      substdio_puts(&smtpto,"EHLO ");
+      substdio_put(&smtpto,helohost.s,helohost.len);
+      substdio_puts(&smtpto,"\r\n");
+      substdio_flush(&smtpto);
+
+      if (smtpcode() != 250) {
+	quit("ZTLS connected to "," but my name was rejected");
+      }
+
+      /* extension handling */
+      for (i = 0; i < smtptext.len; i += str_chr(smtptext.s+i,'\n') + 1) {
+	if (i+8 < smtptext.len && !case_diffb("SIZE", 4, smtptext.s+i+4) )
+	  flagsize = 1;
+#ifdef DATA_COMPRESS
+	else if (i+9 < smtptext.len && !case_diffb("DATAZ", 5, smtptext.s+i+4))
+	  wantcomp = 1;
+#endif
+        else if (i+9 < smtptext.len &&
+	    !case_diffb("AUTH ", 5, smtptext.s+i+4)) {
+	  for (j = i+4; j < smtptext.len; j++)
+	    if (smtptext.s[j] == ' ')
+	      if (j + 6 < smtptext.len &&
+	          !case_diffb("LOGIN", 5, smtptext.s+j+1))
+		flagauth = 1;
+	}
+      }
+    } 
+  }
+#endif
+
+  if (flagauth && auth_login.len && auth_passwd.len) {
+    substdio_putsflush(&smtpto,"AUTH LOGIN\r\n");
+    code = smtpcode();
+    if (code >= 500)
+      quit("DConnected to "," but authentication was rejected (AUTH LOGIN)");
+    if (code >= 400)
+      quit("ZConnected to "," but authentication was rejected (AUTH LOGIN)");
+
+    substdio_put(&smtpto,auth_login.s,auth_login.len);
+    substdio_putsflush(&smtpto,"\r\n");
+    code = smtpcode();
+    if (code >= 500)
+      quit("DConnected to "," but authentication was rejected (username)");
+    if (code >= 400)
+      quit("ZConnected to "," but authentication was rejected (username)");
+
+    substdio_put(&smtpto,auth_passwd.s,auth_passwd.len);
+    substdio_putsflush(&smtpto,"\r\n");
+    code = smtpcode();
+    if (code >= 500)
+      quit("DConnected to "," but authentication was rejected (password)");
+    if (code >= 400)
+      quit("ZConnected to "," but authentication was rejected (password)");
+  } else if (auth_login.len && auth_passwd.len) {
+    quit("ZConnected to "," but no SMTP AUTH support detected but needed.");
+  }
+
   substdio_puts(&smtpto,"MAIL FROM:<");
   substdio_put(&smtpto,sender.s,sender.len);
-  substdio_puts(&smtpto,">\r\n");
+  substdio_puts(&smtpto,">");
+  if (flagsize) {
+    substdio_puts(&smtpto," SIZE=");
+    if (fstat(0,&st) == -1) quit("Z", " unable to fstat stdin");
+    len = st.st_size;
+    len += len>>5; /* add some size for the \r chars see rcf 1870 */
+    substdio_put(&smtpto,num,fmt_ulong(num,len+1));
+  }
+  if (flagauth && auth_login.len && auth_passwd.len) {
+    substdio_puts(&smtpto, " AUTH=<");
+    if (!xtext_quote(&xtext, &sender))
+	    temp_nomem();
+    substdio_put(&smtpto,xtext.s,xtext.len);
+    substdio_puts(&smtpto,">");
+  }
+  substdio_puts(&smtpto,"\r\n");
   substdio_flush(&smtpto);
   code = smtpcode();
   if (code >= 500) quit("DConnected to "," but sender was rejected");
@@ -260,19 +675,147 @@
   }
   if (!flagbother) quit("DGiving up on ","");
  
+#ifdef DATA_COMPRESS
+  if (wantcomp == 1) {
+    substdio_putsflush(&smtpto,"DATAZ\r\n");
+    compression_init();
+  } else
+#endif
   substdio_putsflush(&smtpto,"DATA\r\n");
   code = smtpcode();
+#ifdef DATA_COMPRESS
+  if (wantcomp == 1) {
+    if (code >= 500) quit("D"," failed on DATAZ command");
+    if (code >= 400) quit("Z"," failed on DATAZ command");
+  } else {
+#endif
   if (code >= 500) quit("D"," failed on DATA command");
   if (code >= 400) quit("Z"," failed on DATA command");
+#ifdef DATA_COMPRESS
+  }
+#endif
  
   blast();
+#ifdef DATA_COMPRESS
+  if (wantcomp == 1)
+    compression_done();
+#endif
   code = smtpcode();
   flagcritical = 0;
   if (code >= 500) quit("D"," failed after I sent the message");
   if (code >= 400) quit("Z"," failed after I sent the message");
+#ifdef DATA_COMPRESS
+  wantcomp++;
+#endif
   quit("K"," accepted message");
 }
 
+int qmtp_priority(int pref)
+{
+  if (pref < 12800) return 0;
+  if (pref > 13055) return 0;
+  if (pref % 16 == 1) return 1;
+  return 0;
+}
+
+void qmtp(void)
+{
+  struct stat st;
+  unsigned long len;
+  char *x;
+  unsigned int i;
+  int n;
+  unsigned char ch;
+  unsigned char rv;
+  char num[FMT_ULONG];
+  int flagbother;
+
+  if (fstat(0,&st) == -1) quit("Z", " unable to fstat stdin");
+  len = st.st_size;
+
+  /* the following code was substantially taken from serialmail's serialqmtp.c */
+  substdio_put(&smtpto,num,fmt_ulong(num,len+1));
+  substdio_put(&smtpto,":\n",2);
+  while (len > 0) {
+    n = substdio_feed(&ssin);
+    if (n <= 0) temp_read(); /* wise guy again */
+    x = substdio_PEEK(&ssin);
+    substdio_put(&smtpto,x,n);
+    substdio_SEEK(&ssin,n);
+    len -= n;
+  }
+  substdio_put(&smtpto,",",1);
+
+  len = sender.len;
+  substdio_put(&smtpto,num,fmt_ulong(num,len));
+  substdio_put(&smtpto,":",1);
+  substdio_put(&smtpto,sender.s,sender.len);
+  substdio_put(&smtpto,",",1);
+
+  len = 0;
+  for (i = 0;i < reciplist.len;++i)
+    len += fmt_ulong(num,reciplist.sa[i].len) + 1 + reciplist.sa[i].len + 1;
+  substdio_put(&smtpto,num,fmt_ulong(num,len));
+  substdio_put(&smtpto,":",1);
+  for (i = 0;i < reciplist.len;++i) {
+    substdio_put(&smtpto,num,fmt_ulong(num,reciplist.sa[i].len));
+    substdio_put(&smtpto,":",1);
+    substdio_put(&smtpto,reciplist.sa[i].s,reciplist.sa[i].len);
+    substdio_put(&smtpto,",",1);
+  }
+  substdio_put(&smtpto,",",1);
+  substdio_flush(&smtpto);
+
+  flagbother = 0;
+
+  for (i = 0;i < reciplist.len;++i) {
+    len = 0;
+    for (;;) {
+      get(&ch);
+      if (ch == ':') break;
+      if (len > 200000000) temp_proto();
+      if (ch - '0' > 9) temp_proto();
+      len = 10 * len + (ch - '0');
+    }
+    if (!len) temp_proto();
+    get(&ch); --len;
+    if ((ch != 'Z') && (ch != 'D') && (ch != 'K')) temp_proto();
+
+    rv = ch;
+    if (!stralloc_copys(&smtptext,"qmtp: ")) temp_nomem();
+
+    /* read message */
+    while (len > 0) {
+      get(&ch);
+      --len;
+    }
+    get(&ch);
+    if (ch != ',') temp_proto();
+    smtptext.s[smtptext.len-1] = '\n';
+
+    switch (rv) {
+      case 'K':
+        out("r"); zero();
+	flagbother = 1;
+	break;
+      case 'D':
+        out("h"); outhost(); out("  does not like recipient.\n");
+	outsmtptext(); zero();
+	break;
+      case 'Z':
+        out("h"); outhost(); out("  does not like recipient.\n");
+	outsmtptext(); zero();
+	break;
+    }
+  }
+  if (!flagbother) {
+    out("DGiving up on "); outhost(); out(".\n"); outsmtptext();
+  } else {
+    out("K");outhost();out(" accepted message.\n"); outsmtptext();
+  }
+  zerodie();
+}
+
 stralloc canonhost = {0};
 stralloc canonbox = {0};
 
@@ -282,7 +825,7 @@
 int *flagalias;
 int flagcname;
 {
-  int j;
+  unsigned int j;
  
   *flagalias = flagcname;
  
@@ -308,9 +851,12 @@
   if (!stralloc_cat(saout,&canonhost)) temp_nomem();
 }
 
-void getcontrols()
+void getcontrols(void)
 {
   if (control_init() == -1) temp_control();
+  if (control_rldef(&cookie,"control/smtpclustercookie",0,"") == -1)
+    temp_control();
+  if (cookie.len > 32) cookie.len = 32;
   if (control_readint(&timeout,"control/timeoutremote") == -1) temp_control();
   if (control_readint(&timeoutconnect,"control/timeoutconnect") == -1)
     temp_control();
@@ -324,21 +870,33 @@
     case 1:
       if (!constmap_init(&maproutes,routes.s,routes.len,1)) temp_nomem(); break;
   }
+  if (control_rldef(&outgoingip, "control/outgoingip", 0, "0.0.0.0") == -1)
+    temp_control();
+  if (!stralloc_0(&outgoingip)) temp_nomem();
+  if (!ip_scan(outgoingip.s, &outip)) temp_noip();
+
+#ifdef TLS_REMOTE
+  if (control_readline(&sslcert, "control/remotecert") == -1)
+    temp_control();
+  if (!stralloc_0(&sslcert)) temp_nomem();
+#endif
+
 }
 
-void main(argc,argv)
-int argc;
-char **argv;
+int main(int argc, char **argv)
 {
   static ipalloc ip = {0};
-  int i;
-  unsigned long random;
+  unsigned int i, j;
+  unsigned long randm;
   char **recips;
-  unsigned long prefme;
+  int prefme;
   int flagallaliases;
   int flagalias;
-  char *relayhost;
- 
+  const char *relayhost;
+
+#ifdef TLS_REMOTE
+  sig_alarmcatch(sigalrm);
+#endif
   sig_pipeignore();
   if (argc < 4) perm_usage();
   if (chdir(auto_qmail) == -1) temp_chdir();
@@ -346,21 +904,33 @@
  
  
   if (!stralloc_copys(&host,argv[1])) temp_nomem();
+  if (!stralloc_copys(&auth_login, "")) temp_nomem();
+  if (!stralloc_copys(&auth_passwd, "")) temp_nomem();
  
   relayhost = 0;
   for (i = 0;i <= host.len;++i)
     if ((i == 0) || (i == host.len) || (host.s[i] == '.'))
-      if (relayhost = constmap(&maproutes,host.s + i,host.len - i))
+      if ((relayhost = constmap(&maproutes,host.s + i,host.len - i)))
         break;
   if (relayhost && !*relayhost) relayhost = 0;
  
   if (relayhost) {
-    i = str_chr(relayhost,':');
-    if (relayhost[i]) {
-      scan_ulong(relayhost + i + 1,&port);
-      relayhost[i] = 0;
+    j = str_chr(relayhost,' ');
+    if (relayhost[j]) {
+      i = str_chr(relayhost + j + 1,' ');
+      if (relayhost[i]) {
+	if (b64_ntops(relayhost + j + 1, i, &auth_login) == -1)
+	  temp_nomem();
+	if (b64_ntops(relayhost + j + i + 2, str_len(relayhost + j + i + 2),
+	    &auth_passwd))
+	  temp_nomem();
+      }
     }
-    if (!stralloc_copys(&host,relayhost)) temp_nomem();
+    i = str_chr(relayhost,':');
+    if (relayhost[i])
+      scan_ulong(relayhost + i + 1,&smtp_port);
+    if (i > j) i = j;
+    if (!stralloc_copyb(&host,relayhost, i)) temp_nomem();
   }
 
 
@@ -381,8 +951,8 @@
   }
 
  
-  random = now() + (getpid() << 16);
-  switch (relayhost ? dns_ip(&ip,&host) : dns_mxip(&ip,&host,random)) {
+  randm = now() + (getpid() << 16);
+  switch (relayhost ? dns_ip(&ip,&host) : dns_mxip(&ip,&host,randm)) {
     case DNS_MEM: temp_nomem();
     case DNS_SOFT: temp_dns();
     case DNS_HARD: perm_dns();
@@ -413,15 +983,28 @@
  
     smtpfd = socket(AF_INET,SOCK_STREAM,0);
     if (smtpfd == -1) temp_oserr();
- 
-    if (timeoutconn(smtpfd,&ip.ix[i].ip,(unsigned int) port,timeoutconnect) == 0) {
+
+    if (qmtp_priority(ip.ix[i].pref)) {
+      if (timeoutconn(smtpfd,&ip.ix[i].ip,&outip,(unsigned int) qmtp_port,timeoutconnect) == 0) {
+	tcpto_err(&ip.ix[i].ip,0);
+	partner = ip.ix[i].ip;
+	qmtp(); /* does not return */
+      }
+      close(smtpfd);
+      smtpfd = socket(AF_INET,SOCK_STREAM,0);
+      if (smtpfd == -1) temp_oserr();
+    }
+    if (timeoutconn(smtpfd,&ip.ix[i].ip,&outip,(unsigned int) smtp_port,timeoutconnect) == 0) {
       tcpto_err(&ip.ix[i].ip,0);
       partner = ip.ix[i].ip;
-      smtp(); /* does not return */
+      smtp(); /* should not return unless the start code or the HELO code
+	         returns a temporary failure. */
     }
     tcpto_err(&ip.ix[i].ip,errno == error_timeout);
     close(smtpfd);
   }
   
   temp_noconn();
+  /* NOTREACHED */
+  return 0;
 }
diff -ruN qmail-1.03-orig/qmail-reply.c qmail-1.03-ldap-20060201-orig/qmail-reply.c
--- qmail-1.03-orig/qmail-reply.c	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/qmail-reply.c	2006-02-25 11:00:55.000000000 +0100
@@ -0,0 +1,868 @@
+/*
+ * Copyright (c) 1999-2004 Claudio Jeker,
+ *      Internet Business Solutions AG, CH-8005 Zürich, Switzerland
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Internet Business
+ *      Solutions AG and its contributors.
+ * 4. Neither the name of the author nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include "base64.h"
+#include "byte.h"
+#include "case.h"
+#include "control.h"
+#include "constmap.h"
+#include "digest_md5.h"
+#include "direntry.h"
+#include "env.h"
+#include "error.h"
+#include "exit.h"
+#include "fmt.h"
+#include "getln.h"
+#include "mailmagic.h"
+#include "newfield.h"
+#include "now.h"
+#include "open.h"
+#include "qmail.h"
+#include "qmail-ldap.h"
+#include "readwrite.h"
+#include "seek.h"
+#include "sgetopt.h"
+#include "sig.h"
+#include "str.h"
+#include "strerr.h"
+#include "stralloc.h"
+#include "substdio.h"
+
+#define FATAL "qmail-reply: fatal: "
+#define WARN  "qmail-reply: warn: "
+
+void
+temp_nomem(void)
+{
+	strerr_die2x(111, FATAL, "Out of memory.");
+}
+
+void
+temp_rewind(void)
+{
+	strerr_die2x(111, FATAL, "Unable to rewind message.");
+}
+
+void
+temp_fork(void)
+{
+	strerr_die2sys(111, FATAL, "Unable to fork: ");
+}
+
+void
+usage(void)
+{
+	strerr_die1x(100,
+	    "qmail-reply: usage: qmail-reply [-f mailfile] [-j junkfile] "
+	    "[maildir]");
+}
+
+stralloc replytext = {0};
+stralloc hashed = {0};
+
+void
+hashreplytext(void)
+{
+	MD5_CTX ctx;
+	unsigned char buffer[MD5_LEN];
+
+	MD5Init(&ctx);
+	MD5Update(&ctx, replytext.s, replytext.len);
+	MD5Final(buffer,&ctx);
+
+	if (hex_ntops(buffer, sizeof(buffer), &hashed) == -1) temp_nomem();
+	if (!stralloc_0(&hashed) == -1) temp_nomem();
+}
+
+void
+envmail(void)
+{
+	char *s;
+
+	if ((s = env_get(ENV_REPLYTEXT))) {
+		if (!stralloc_copys(&replytext, s)) temp_nomem();
+	} else {
+		strerr_die3x(100, FATAL, ENV_REPLYTEXT,
+		    " not present.");
+	}
+	hashreplytext();
+}
+
+char buffer[1024];
+stralloc line = {0};
+
+void
+readmail(char *file)
+{
+	substdio ss;
+	int fd;
+	int match;
+
+	if (!stralloc_copys(&replytext, "")) temp_nomem();
+
+	fd = open_read(file);
+	if (fd == -1)
+		strerr_die4sys(100, FATAL, "Unable to open '", file, "': ");
+ 
+	substdio_fdbuf(&ss, subread, fd, buffer, sizeof(buffer));
+	for (;;) {
+		if (getln(&ss, &line, &match, '\n') == -1)
+			strerr_die4sys(100, FATAL, "Unable to read '",
+			    file, "': ");
+		if (!match) {
+			close(fd);
+			return;
+		}
+		if (!stralloc_cat(&replytext, &line)) temp_nomem();
+	}
+	hashreplytext();
+}
+
+stralloc to={0};
+stralloc from={0};
+stralloc host={0};
+stralloc dtline={0};
+
+void
+get_env(void)
+{
+	char *s;
+	unsigned int i;
+
+	if ((s = env_get("DTLINE")) == (char *)0)
+		strerr_die2x(100, FATAL, "Environment DTLINE not present.");
+	if (!stralloc_copys(&dtline, s)) temp_nomem();
+
+	if ((s = env_get("SENDER")) == (char *)0)
+		strerr_die2x(100, FATAL, "Environment SENDER not present.");
+	if (!stralloc_copys(&to, s)) temp_nomem();
+
+	if ((s = env_get("RECIPIENT")) == (char *)0)
+		strerr_die2x(100, FATAL, "Environment RECIPIENT not present.");
+	if (!stralloc_copys(&from, s)) temp_nomem();
+
+	i = byte_chr(from.s, from.len, '@');
+	if (i == 0 || i >= from.len)
+	  strerr_die2x(100, FATAL, "Bad RECIPIENT address.");
+
+	if (!(s = env_get("HOST")))
+		strerr_die2x(100, FATAL, "Environment HOST not present.");
+	if (!stralloc_copys(&host, s)) temp_nomem();
+}
+
+stralloc junkfrom={0};
+struct constmap mapjunk;
+
+void
+junkread(char *path)
+{
+	if (control_readfile(&junkfrom, path, 0) != 1)
+		strerr_die4sys(100, FATAL, "Unable to read '", path, "': ");
+}
+
+int
+junksender(char *addr, unsigned int len)
+{
+	unsigned int		at, dash, i;
+	static const char	*(junkignore[]) = {
+		/* don't reply to bots */
+		"-request",
+		"daemon",
+		"-daemon",
+		"uucp",
+		"mailer-daemon",
+		"mailer",
+		/* don't bother admins */
+		"postmaster",
+		"root",
+		/* from vacation(1) */
+		"-relay",
+		0 } ;
+		/* TODO support for -return- dash extensions */
+	
+	for (i = 0; junkignore[i] != 0; i++) {
+		if (!stralloc_cats(&junkfrom, junkignore[i])) temp_nomem();
+		if (!stralloc_0(&junkfrom)) temp_nomem();
+	}
+
+	if (!constmap_init(&mapjunk, junkfrom.s, junkfrom.len, 0))
+		strerr_die2sys(111, FATAL, "Constmap_init: ");
+	
+	at = byte_rchr(addr, len, '@');
+	if (at >= len)
+		strerr_die2x(111, FATAL, "Bad SENDER address.");
+
+	/*
+	   1. user@host
+	   2. user
+	   3. @host
+	   4. -part
+	 */
+	if (constmap(&mapjunk, addr, len)) return 1;
+	if (constmap(&mapjunk, addr, at)) return 1;
+	if (constmap(&mapjunk, addr+at, len-at)) return 1;
+	
+	for (dash = 0; dash < at; dash++) {
+		dash += byte_chr(addr+dash, at-dash, '-');
+		if (constmap(&mapjunk, addr+dash, at-dash)) return 1;
+	}
+	return 0;
+}	
+
+datetime_sec
+get_stamp(char const *hex)
+{
+	unsigned long t;
+	unsigned char c;
+
+	t = 0;
+	while((c = *hex++)) {
+		if (c >= '0' && c <= '9')
+			c -= '0';
+		else if (c >= 'a')
+			c -= ('a' - 10);
+		else 
+			c -= ('A' - 10);
+		if (c > 15)
+			break;
+		t = (t<<4) + c;
+	}
+	
+	return (datetime_sec) t;	
+}
+
+char *
+stamp(datetime_sec tm)
+{
+	static char stampbuf[10];
+	static const char* digit = "0123456789abcdef";
+	char *s;
+	unsigned long t;
+
+	t = (unsigned long) tm;
+	s = stampbuf;
+	*s++ = ':';
+	*s++ = digit[(t >> 28) & 0x0f];
+	*s++ = digit[(t >> 24) & 0x0f];
+	*s++ = digit[(t >> 20) & 0x0f];
+	*s++ = digit[(t >> 16) & 0x0f];
+	*s++ = digit[(t >> 12) & 0x0f];
+	*s++ = digit[(t >>  8) & 0x0f];
+	*s++ = digit[(t >>  4) & 0x0f];
+	*s++ = digit[ t        & 0x0f];
+	*s = '\0';
+	return stampbuf;
+}
+
+stralloc rs = {0}; /* recent sender */
+datetime_sec timeout;
+#ifndef REPLY_TIMEOUT
+#define REPLY_TIMEOUT 1209600 /* 2 weeks */
+#endif
+#define MAX_SIZE (128 * 1024) /* 128kB space for recent sender db */
+
+int checkstamp(char *, unsigned int);
+
+int
+recent_lookup(char *buf, unsigned int len)
+{
+	char *s;
+	datetime_sec last;
+	unsigned int i, slen;
+	
+	switch (control_readfile(&rs,"qmail-reply.db",1)) {
+		case 1:
+			break;
+		case 0:
+			goto done;
+		default:
+			strerr_die2sys(111, FATAL,
+			    "Read database file failed: ");
+	}
+
+	slen = rs.len; s = rs.s;
+	if (!case_startb(s, slen, "QRDBv1:")) goto done;
+	s += 7; slen -= 7;
+	if (slen < hashed.len || case_diffb(s, hashed.len, hashed.s) != 0)
+		return 0;
+	s += hashed.len; slen -= hashed.len;
+
+	for (i = 0; i < slen; i += str_len(s+i) + 1) {
+		if (case_diffb(buf, len, s+i) == 0) {
+			/* match found, look at timeval */
+			i += len;
+			if (s[i++] != ':') {
+				strerr_warn2(WARN,
+				    "Database file corrupted", 0);
+				unlink("qmail-reply.db");
+				stralloc_copys(&rs, "");
+				return 0;
+			}
+			last = get_stamp(s+i);
+			if (last + timeout < now()) goto done;
+			else return 1;
+		}
+	}
+done:
+	return checkstamp(buf, len);
+}
+
+int
+trylock(void)
+{
+	struct stat st;
+	int fd;
+	
+retry:
+	if ((fd = open_excl("qmail-reply.lock")) == -1) {
+		if (errno == error_exist) {
+			if (stat("qmail-reply.lock", &st) == -1) {
+				strerr_warn2(WARN, "Unable to stat lock: ",
+				    &strerr_sys);
+				return -1;
+			}
+			/* ... should never get to this point */
+			if (st.st_mtime + 900 < now()) {
+				/* stale lock file */
+				if (unlink("qmail-reply.lock") == -1) {
+					strerr_warn2(WARN,
+					    "Unable to unlink lock: ",
+					    &strerr_sys);
+					return -1;
+				}
+				goto retry;
+			}
+			return 0;
+		}
+		strerr_warn2(WARN, "Unable to get lock: ", &strerr_sys);
+		return -1;
+	}
+	close(fd);
+	return 1;
+}
+
+void
+unlock(void)
+{
+	if (unlink("qmail-reply.lock") == -1)
+		strerr_warn2(WARN, "Unable to unlock: ", &strerr_sys);
+}
+
+stralloc sfs = {0};
+stralloc spath = {0};
+
+int
+checkstamp(char *buf, unsigned int len)
+{
+	struct stat st;
+	
+	if (!stralloc_copys(&spath, "tmp/@") ||
+	    !stralloc_catb(&spath, buf, len) ||
+	    !stralloc_0(&spath)) temp_nomem();
+	if (stat(spath.s,&st) == -1) {
+		if (errno == error_noent) return 0;
+		strerr_warn4(WARN, "Can't stat stamp file: ",
+		    spath.s, ": ", &strerr_sys);
+		return 0;
+	}
+	if (st.st_mtime + timeout < now()) return 0;
+	return 1;
+}
+
+void
+addstamps(void)
+{
+	DIR *dir;
+	direntry *d;
+	struct stat st;
+
+	if (!stralloc_copys(&sfs, "")) {
+		strerr_warn2(WARN, "Out of memory.", 0);
+		return;
+	}
+	dir = opendir("tmp");
+	if (!dir) {
+		strerr_warn2(WARN, "Unable to opendir ./tmp: ", &strerr_sys);
+		return;
+	}
+	while ((d = readdir(dir))) {
+		if (d->d_name[0] != '@') continue;
+		/* this is a possible stamp file */
+		if (d->d_name[str_chr(d->d_name+1, '@')+1] != '@') {
+			strerr_warn3(WARN, "Strange stamp file: ",
+			    d->d_name, 0);
+			continue;
+		}
+		if (!stralloc_copys(&spath, "tmp/") ||
+		    !stralloc_cats(&spath, d->d_name) ||
+		    !stralloc_0(&spath)) break;
+		if (stat(spath.s,&st) == -1) {
+			strerr_warn4(WARN, "Can't stat stamp file: ",
+			    d->d_name, ": ", &strerr_sys);
+			continue;
+		}
+		if (!stralloc_cat(&sfs, &spath)) break; 
+		if (!stralloc_cats(&rs, d->d_name+1) ||
+		    !stralloc_cats(&rs, stamp(st.st_mtime)) ||
+		    !stralloc_0(&rs)) break;
+	}
+	closedir(dir);
+	if (d) strerr_warn2(WARN, "Out of memory.", 0);
+}
+
+void
+deletestamps(void)
+{
+	unsigned int i;
+	char *s;
+
+	s = sfs.s;
+	for(i = 0; i < sfs.len; i += str_len(s+i) + 1) {
+		unlink(s + i);
+	}
+}
+
+char rsoutbuf[SUBSTDIO_OUTSIZE];
+char fntmptph[32 + 2*FMT_ULONG];
+
+void
+sigalrm(void)
+{
+	unlink(fntmptph);
+	unlock();
+	strerr_die2x(111, FATAL, "Timeout while writing db file");
+}
+
+void
+recent_update(char *buf, unsigned int len)
+{
+	struct stat st;
+	substdio ss;
+	char *s, *t;
+	datetime_sec tm, last;
+	unsigned long pid;
+	unsigned int slen, i, n;
+	int fd, loop;
+
+	addstamps();
+
+	/* first limit database length to MAX_SIZE */
+	s = rs.s; slen = rs.len;
+	/* hop over possible header */
+	if (case_startb(s, slen, "QRDBv1:")) {
+		i = str_len(s);
+		slen -= i;
+		s += i;
+	}
+	for(; slen > MAX_SIZE; ) {
+		i = str_len(s) + 1;
+		slen -= i;
+		s += i;
+	}
+
+	/* optain a temp file */
+	pid = getpid();
+	for (loop = 0;;++loop) {
+		tm = now();
+		t = fntmptph;
+		t += fmt_str(t, "tmp/qmail-reply.");
+		t += fmt_ulong(t, pid); *t++ = '.';
+		t += fmt_ulong(t, tm); *t++ = 0;
+
+		if (stat(fntmptph, &st) == -1) if (errno == error_noent) break;
+		/* ... should never get to this point */
+		if (loop == 2) {
+			strerr_warn2(WARN, "Could not stat tmp file:",
+			    &strerr_sys);
+			return;
+		}
+		sleep(2);
+	}
+
+	sig_alarmcatch(sigalrm);
+	alarm(600); /* give up after 10 min */
+	fd = open_excl(fntmptph);
+	if (fd == -1) {
+		strerr_warn2(WARN, "Unable to open tmp file: ", &strerr_sys);
+		return;
+	}
+	
+	substdio_fdbuf(&ss, subwrite, fd, rsoutbuf, sizeof(rsoutbuf));
+	
+	if (substdio_puts(&ss, "QRDBv1:") == -1) goto fail;
+	if (substdio_puts(&ss, hashed.s) == -1) goto fail;
+	if (substdio_put(&ss, "\n", 1) == -1) goto fail;
+
+	/* dump database */
+	for (i = 0; i < slen; i += str_len(s+i) + 1) {
+		n = byte_chr(s+i, slen, ':');
+		if (n++ < slen) {
+			last = get_stamp(s + i + n);
+			if (last + timeout < tm) continue;
+		} else goto fail; /* database corrupted */
+		if (substdio_puts(&ss, s+i) == -1) goto fail;
+		if (substdio_put(&ss, "\n", 1) == -1) goto fail;
+	}
+	if (substdio_flush(&ss) == -1) goto fail;
+	if (fsync(fd) == -1) goto fail;
+	if (close(fd) == -1) goto fail; /* NFS dorks */
+
+	if (unlink("qmail-reply.db") == -1 && errno != error_noent) goto fail;
+	if (link(fntmptph, "qmail-reply.db") == -1) goto fail;
+	/* if it was error_exist, almost certainly successful; i hate NFS */
+
+	unlink(fntmptph);
+	deletestamps();
+	sig_alarmdefault();
+	return;
+
+fail:
+	strerr_warn2(WARN, "Database update failed: ", &strerr_sys);
+	unlink(fntmptph);
+	sig_alarmdefault();
+	return;
+}
+
+void
+touchstamp(char *buf, unsigned int len)
+{
+	int fd;
+
+	if (!stralloc_copys(&sfs, "tmp/@")) temp_nomem();
+	if (!stralloc_catb(&sfs, buf, len)) temp_nomem();
+	if (!stralloc_0(&sfs)) temp_nomem();
+
+	if ((fd = open_trunc(sfs.s)) == -1)
+		strerr_warn4(WARN, "Unable to create stamp ",
+		    sfs.s, ": ", &strerr_sys);
+	close(fd);
+}
+
+int
+recent(char *buf, unsigned int len, char *dir)
+{
+	if (dir == 0) return 0;
+
+	if (chdir(dir) == -1) {
+		strerr_warn4(WARN, "Unable to switch to ", dir, ": ",
+		    &strerr_sys);
+		return 0;
+	}
+
+	switch (trylock()) {
+	case 0:
+		if (recent_lookup(buf, len) == 1)
+			return 1;
+		/* touch stamp file */
+		touchstamp(buf, len);
+		return 0;
+	case 1:
+		if (recent_lookup(buf, len) == 1) {
+			unlock();
+			return 1;
+		}
+		touchstamp(buf, len);
+		recent_update(buf, len);
+		unlock();
+		return 0;
+	default:
+		/* warning print in trylock() */
+		return 0;
+	}
+}
+
+unsigned int
+getfield(char *s, unsigned int len)
+{
+	unsigned int l;
+
+	l = len;
+	for(;;) {
+		if (l-- == 0) break; if (*s++ == ':') break;
+		if (l-- == 0) break; if (*s++ == ':') break;
+		if (l-- == 0) break; if (*s++ == ':') break;
+		if (l-- == 0) break; if (*s++ == ':') break;
+	}
+	for(;;) {
+		if (l == 0) break; if (*s != ' ' && *s != '\t') break;
+		l--; s++;
+		if (l == 0) break; if (*s != ' ' && *s != '\t') break;
+		l--; s++;
+		if (l == 0) break; if (*s != ' ' && *s != '\t') break;
+		l--; s++;
+		if (l == 0) break; if (*s != ' ' && *s != '\t') break;
+		l--; s++;
+	}
+	return len - l;
+}
+
+#ifndef REPLY_SUBJ
+#define REPLY_SUBJ "Your Mail"
+#endif
+
+stralloc subject = {0};
+
+int
+parseheader(/* TODO names for to/cc checking */ void)
+{
+	substdio ss;
+	char *s;
+	int match, subj_set;
+	unsigned int len, i;
+
+	subj_set = 0;
+	if (seek_begin(0) == -1) temp_rewind();
+	substdio_fdbuf(&ss, subread, 0, buffer, sizeof(buffer) );
+	do {
+		if(getln(&ss, &line, &match, '\n') != 0) {
+			strerr_warn3(WARN, "Unable to read message: ",
+			    error_str(errno), 0);
+			break; /* something bad happend, but we ignore it */
+		}
+		if (line.len == 0) /* something is wrong, bad message */
+			break;
+		s = line.s; len = line.len;
+		switch(*s) {
+		case '\n': /* end of header */
+			if (subj_set == 0)
+				if (!stralloc_copys(&subject, REPLY_SUBJ))
+					temp_nomem();
+			return 0;
+		case 'M':
+		case 'm': /* Mailing-List: */
+			if (case_startb(s, len, "Mailing-List:")) {
+				return 1;
+				/* don't reply to mailing-lists */
+			}
+			break;
+		case 'P':
+		case 'p': /* Precedence: */
+			if (case_startb(s, len, "Precedence:")) {
+				i = getfield(s, len);
+				if (i >= len) break;
+				s += i; len -= i;
+				if (case_startb(s, len, "junk") ||
+				    case_startb(s, len, "bulk") ||
+				    case_startb(s, len, "list"))
+					return 1;
+			}
+			break;
+		case 'S':
+		case 's': /* Subject: */
+			if (case_startb(s, len, "Subject:")) {
+				i = getfield(s, len);
+				if (i >= len) break;
+				s += i; len -= i;
+				
+				if (len > 1) {
+					/* subject has to be more than
+					   1 char (normaly a \n)
+					 */
+					if (!stralloc_copyb(&subject, s, len-1))
+						temp_nomem();
+					subj_set=1;
+				}
+			}
+			break;
+		case 'C':
+		case 'c': /* Cc: */
+		case 'T':
+		case 't': /* To: */
+			/*  TODO check if address is listed in To or Cc field */
+#if 0
+			if (case_diffb("To:"
+				    sizeof("To:") - 1, s) == 0 ||
+			    case_diffb("Cc:"
+				    sizeof("Cc:") - 1, s) == 0) {
+				i = getfield(s, len);
+				if (i >= len) break;
+				s += i; len -= i;
+			}
+#endif
+			break;
+		case 'X':
+		case 'x': /* X-RBL: */
+			if (case_startb(s, len, "X-RBL:")) {
+				return 1;
+				/* don't reply to messages tagged as spam */
+			}
+			if (case_startb(s, len, "X-Spam-Status: Yes")) {
+				return 1;
+				/* don't reply to messages tagged as spam */
+			}
+			break;
+		case ' ':
+		case '\t':
+			/* TODO multiline header Precedence, Subject, To and Cc */
+		default:
+			break;
+		}
+	} while (match);
+	strerr_warn2(WARN,
+	    "Premature end of header. The message has no body.", 0);
+	if ( subj_set == 0 )
+		if (!stralloc_copys(&subject, REPLY_SUBJ)) temp_nomem();
+
+	return 0;
+}
+
+stralloc header = {0};
+
+#ifndef REPLY_CT
+#define REPLY_CT "text/plain; charset=iso-8859-1\n"
+#endif
+#ifndef REPLY_CTE
+#define REPLY_CTE "8bit\n"
+#endif
+
+struct mheader mheader[] = {
+	{ "From:", 0, ALLOW, 0 }, /* envelope sender is fixed */
+	{ "To:", 0, FORCE, 0 },
+	{ "Subject:", "[Auto-Reply] %SUBJECT%\n", SUBJECT, 0 },
+	{ "MIME-Version:", "1.0", FORCE, 0 },
+	{ "Content-Type:", REPLY_CT, ALLOW, 0 },
+	{ "Content-Transfer-Encoding:", REPLY_CTE, ALLOW, 0 },
+	{ "X-Mailer:", "qmail-reply (by qmail-ldap)", FORCE, 0 },
+	{ "Precedence:", "junk", FORCE, 0 },
+	{ "X-", 0, ALLOW, 0 },
+	{ DEFAULT, 0, DENY, 0 },
+	{ 0, 0, 0, 0 }
+};
+
+void
+sendmail(void)
+{
+	struct qmail qqt;
+	const char *qqx;
+	datetime_sec starttime;
+	unsigned long qp;
+	int offset;
+	
+	if (!stralloc_0(&from)) temp_nomem();
+	if (!stralloc_0(&to)) temp_nomem();
+
+	mheader[0].v = from.s;
+	mheader[1].v = to.s;
+	offset = headermagic(&replytext, &header, &subject, mheader);
+	if (offset == -1)
+		strerr_die2sys(111, FATAL, "Header magic failed: ");
+	
+	if (qmail_open(&qqt) == -1) temp_fork();
+	qp = qmail_qp(&qqt);
+	qmail_put(&qqt,dtline.s,dtline.len);
+	
+	/* XXX Date: qmail uses GMT based dates which is sometimes confusing */
+	/* message-id and date line */
+	starttime = now();
+	if (!newfield_datemake(starttime)) goto fail_nomem;
+	if (!newfield_msgidmake(host.s, host.len, starttime)) goto fail_nomem;
+	qmail_put(&qqt, newfield_msgid.s, newfield_msgid.len);
+	qmail_put(&qqt, newfield_date.s, newfield_date.len);
+
+	/* write parsed header */
+	qmail_put(&qqt, header.s, header.len);
+	/* end of header marker */
+	qmail_puts(&qqt, "\n");
+
+	/* body */
+	qmail_put(&qqt, replytext.s + offset, replytext.len - offset);
+	/* add a empty newline, just to be sure */
+	qmail_puts(&qqt, "\n");
+	/* use <> as envelope sender as we are not interested in bounces */
+	qmail_from(&qqt, "");
+	qmail_to(&qqt, to.s);
+	qqx = qmail_close(&qqt);
+	if (!*qqx) return;
+	strerr_die4x(*qqx == 'D' ? 100 : 111, FATAL,
+	    "Unable to send reply message: ", qqx + 1, ".");
+
+fail_nomem:
+	qmail_fail(&qqt);
+	qmail_close(&qqt);
+	temp_nomem();
+}
+
+int
+main(int argc, char **argv)
+{
+	char *maildir;
+	int flagenv;
+	int opt;
+
+	if (!env_init()) temp_nomem();
+	
+	flagenv = 1;
+	timeout = REPLY_TIMEOUT;
+
+	while((opt = getopt(argc,argv,"f:j:")) != opteof)
+		switch (opt) {
+		case 'f':
+			readmail(optarg);
+			flagenv = 0;
+			break;
+		case 'j':
+			junkread(optarg);
+			break;
+		default:
+			usage();
+			/* NOTREACHED */
+		}
+	
+	/* if more arguments are used */
+	argc -= optind;
+	argv += optind;
+	maildir = *argv;
+	
+	if (flagenv == 1)
+		envmail();
+
+	/* get environment RECIPIENT, SENDER and DTLINE */
+	get_env();
+
+	/* check if a reply is needed */
+	if (junksender(to.s, to.len)) _exit(0);
+	/* parse header, exit if a precedence or mailinglist field
+	   has been found or the mail is not directly sent to us. */
+	if (parseheader()) _exit(0);
+	/* already sent a message recently? */
+	if (maildir && (*maildir == '.' || *maildir == '/') &&
+	    maildir[str_len(maildir)-1] == '/')
+		if (recent(to.s, to.len, maildir)) _exit(0);
+
+	sendmail();
+	return 0;
+}
+
diff -ruN qmail-1.03-orig/qmail-rspawn.c qmail-1.03-ldap-20060201-orig/qmail-rspawn.c
--- qmail-1.03-orig/qmail-rspawn.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/qmail-rspawn.c	2006-02-25 11:00:55.000000000 +0100
@@ -1,3 +1,4 @@
+#include <unistd.h>
 #include "fd.h"
 #include "wait.h"
 #include "substdio.h"
@@ -10,19 +11,25 @@
 int argc;
 char **argv;
 {
+#if 0
+ extern int flagreinit;
+
+ if (flagreinit)
+   return;
+#endif
  tcpto_clean();
 }
 
-int truncreport = 0;
+unsigned int truncreport = 0;
 
 void report(ss,wstat,s,len)
 substdio *ss;
 int wstat;
 char *s;
-int len;
+unsigned int len;
 {
- int j;
- int k;
+ unsigned int j;
+ unsigned int k;
  int result;
  int orr;
 
@@ -79,12 +86,12 @@
 
 int spawn(fdmess,fdout,s,r,at)
 int fdmess; int fdout;
-char *s; char *r; int at;
+char *s; char *r; unsigned int at;
 {
  int f;
  char *(args[5]);
 
- args[0] = "qmail-remote";
+ args[0] = (char *)"qmail-remote";
  args[1] = r + at + 1;
  args[2] = s;
  args[3] = r;
diff -ruN qmail-1.03-orig/qmail.schema qmail-1.03-ldap-20060201-orig/qmail.schema
--- qmail-1.03-orig/qmail.schema	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/qmail.schema	2006-02-25 11:00:55.000000000 +0100
@@ -0,0 +1,279 @@
+#
+# qmail-ldap (20030901) ldapv3 directory schema
+#
+# The offical qmail-ldap OID assigned by IANA is 7914
+#
+# Created by: David E. Storey <dave@tamos.net>
+# Modified and included into qmail-ldap by Andre Oppermann <opi@nrg4u.com>
+# Schema fixes by Mike Jackson <mjj@pp.fi>
+# Schema fixes by Christian Zoffoli (XMerlin) <czoffoli@xmerlin.org>
+#
+#
+# This schema depends on:
+#	- core.schema
+#	- cosine.schema
+#	- nis.schema
+#
+
+# Attribute Type Definitions
+
+attributetype ( 1.3.6.1.4.1.7914.1.2.1.1 NAME 'qmailUID'
+	DESC 'UID of the user on the mailsystem'
+	EQUALITY integerMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
+attributetype ( 1.3.6.1.4.1.7914.1.2.1.2 NAME 'qmailGID'
+	DESC 'GID of the user on the mailsystem'
+	EQUALITY integerMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
+attributetype ( 1.3.6.1.4.1.7914.1.2.1.3 NAME 'mailMessageStore'
+	DESC 'Path to the maildir/mbox on the mail system'
+	EQUALITY caseExactIA5Match
+	SUBSTR caseIgnoreIA5SubstringsMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} SINGLE-VALUE )
+
+attributetype ( 1.3.6.1.4.1.7914.1.2.1.4 NAME 'mailAlternateAddress'
+	DESC 'Secondary (alias) mailaddresses for the same user'
+	EQUALITY caseIgnoreIA5Match
+	SUBSTR caseIgnoreIA5SubstringsMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} )
+
+#
+# mailQuota format is no longer supported from qmail-ldap 20030901 on,
+# user mailQuotaSize and mailQuotaCount instead.
+#
+#attributetype ( 1.3.6.1.4.1.7914.1.2.1.5 NAME 'mailQuota'
+#	DESC 'The amount of space the user can use until all further messages get bounced.'
+#	SYNTAX 1.3.6.1.4.1.1466.115.121.1.44 SINGLE-VALUE )
+#
+
+attributetype ( 1.3.6.1.4.1.7914.1.2.1.6 NAME 'mailHost'
+	DESC 'On which qmail server the messagestore of this user is located.'
+	EQUALITY caseIgnoreIA5Match
+	SUBSTR caseIgnoreIA5SubstringsMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} SINGLE-VALUE)
+
+attributetype ( 1.3.6.1.4.1.7914.1.2.1.7 NAME 'mailForwardingAddress'
+	DESC 'Address(es) to forward all incoming messages to.'
+	EQUALITY caseIgnoreIA5Match
+	SUBSTR caseIgnoreIA5SubstringsMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} )
+
+attributetype ( 1.3.6.1.4.1.7914.1.2.1.8 NAME 'deliveryProgramPath'
+	DESC 'Program to execute for all incoming mails.'
+	EQUALITY caseExactIA5Match
+	SUBSTR caseIgnoreIA5SubstringsMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} )
+
+attributetype ( 1.3.6.1.4.1.7914.1.2.1.9 NAME 'qmailDotMode'
+	DESC 'Interpretation of .qmail files: both, dotonly, ldaponly, ldapwithprog'
+	EQUALITY caseIgnoreIA5Match
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{32} SINGLE-VALUE )
+
+attributetype ( 1.3.6.1.4.1.7914.1.2.1.10 NAME 'deliveryMode'
+	DESC 'multi field entries of: nolocal, noforward, noprogram, reply'
+	EQUALITY caseIgnoreIA5Match
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{32} )
+
+attributetype ( 1.3.6.1.4.1.7914.1.2.1.11 NAME 'mailReplyText'
+	DESC 'A reply text for every incoming message'
+	EQUALITY caseIgnoreMatch
+	SUBSTR caseIgnoreSubstringsMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{4096} SINGLE-VALUE )
+
+attributetype ( 1.3.6.1.4.1.7914.1.2.1.12 NAME 'accountStatus'
+	DESC 'The status of a user account: active, noaccess, disabled, deleted'
+	EQUALITY caseIgnoreIA5Match
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )
+
+attributetype ( 1.3.6.1.4.1.7914.1.2.1.14 NAME 'qmailAccountPurge'
+        DESC 'The earliest date when a mailMessageStore will be purged'
+        EQUALITY numericStringMatch
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 SINGLE-VALUE )
+
+attributetype ( 1.3.6.1.4.1.7914.1.2.1.15 NAME 'mailQuotaSize'
+	DESC 'The size of space the user can have until further messages get bounced.'
+	EQUALITY integerMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
+attributetype ( 1.3.6.1.4.1.7914.1.2.1.16 NAME 'mailQuotaCount'
+	DESC 'The number of messages the user can have until further messages get bounced.'
+	EQUALITY integerMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
+attributetype ( 1.3.6.1.4.1.7914.1.2.1.17 NAME 'mailSizeMax'
+	DESC 'The maximum size of a single messages the user accepts.'
+	EQUALITY integerMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
+#
+# qmailGroup attributes
+#
+
+attributetype ( 1.3.6.1.4.1.7914.1.3.1.1 NAME 'dnmember'
+	DESC 'Group member specified as distinguished name.'
+	EQUALITY distinguishedNameMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )
+
+attributetype ( 1.3.6.1.4.1.7914.1.3.1.2 NAME 'rfc822member'
+	DESC 'Group member specified as normal rf822 email address.'
+	EQUALITY caseIgnoreIA5Match
+	SUBSTR caseIgnoreIA5SubstringsMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} )
+
+attributetype ( 1.3.6.1.4.1.7914.1.3.1.3 NAME 'filtermember'
+	DESC 'Group member specified as ldap search filter.'
+	EQUALITY caseIgnoreIA5Match
+	SUBSTR caseIgnoreIA5SubstringsMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{512} )
+
+attributetype ( 1.3.6.1.4.1.7914.1.3.1.4 NAME 'senderconfirm'
+	DESC 'Sender to Group has to answer confirmation email.'
+	EQUALITY booleanMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 SINGLE-VALUE )
+
+attributetype ( 1.3.6.1.4.1.7914.1.3.1.5 NAME 'membersonly'
+	DESC 'Sender to Group must be group member itself.'
+	EQUALITY booleanMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 SINGLE-VALUE )
+
+attributetype ( 1.3.6.1.4.1.7914.1.3.1.6 NAME 'confirmtext'
+	DESC 'Text that will be sent with sender confirmation email.'
+	EQUALITY caseIgnoreMatch
+	SUBSTR caseIgnoreSubstringsMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{4096} SINGLE-VALUE )
+
+attributetype ( 1.3.6.1.4.1.7914.1.3.1.7 NAME 'dnmoderator'
+	DESC 'Group moderator specified as Distinguished name.'
+	EQUALITY distinguishedNameMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )
+
+attributetype ( 1.3.6.1.4.1.7914.1.3.1.8 NAME 'rfc822moderator'
+	DESC 'Group moderator specified as normal rfc822 email address.'
+	EQUALITY caseIgnoreIA5Match
+	SUBSTR caseIgnoreIA5SubstringsMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} )
+
+attributetype ( 1.3.6.1.4.1.7914.1.3.1.9 NAME 'moderatortext'
+	DESC 'Text that will be sent with request for moderation email.'
+	EQUALITY caseIgnoreMatch
+	SUBSTR caseIgnoreSubstringsMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{4096} SINGLE-VALUE )
+
+attributetype ( 1.3.6.1.4.1.7914.1.3.1.10 NAME 'dnsender'
+	DESC 'Allowed sender specified as distinguished name.'
+	EQUALITY distinguishedNameMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )
+
+attributetype ( 1.3.6.1.4.1.7914.1.3.1.11 NAME 'rfc822sender'
+	DESC 'Allowed sender specified as normal rf822 email address.'
+	EQUALITY caseIgnoreIA5Match
+	SUBSTR caseIgnoreIA5SubstringsMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} )
+
+attributetype ( 1.3.6.1.4.1.7914.1.3.1.12 NAME 'filtersender'
+	DESC 'Allowed sender specified as ldap search filter.'
+	EQUALITY caseIgnoreIA5Match
+	SUBSTR caseIgnoreIA5SubstringsMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{512} )
+
+attributetype ( 1.3.6.1.4.1.7914.1.3.1.13 NAME 'bounceadmin'
+	DESC 'rfc822 email address where bounces should be sent to.'
+	EQUALITY caseIgnoreIA5Match
+	SUBSTR caseIgnoreIA5SubstringsMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} )
+
+
+#
+# qldapAdmin Attributes
+#
+
+attributetype ( 1.3.6.1.4.1.7914.1.4.1.1 NAME 'qladnmanager'
+	DESC ''
+	EQUALITY distinguishedNameMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )
+
+attributetype ( 1.3.6.1.4.1.7914.1.4.1.2 NAME 'qlaDomainList'
+	DESC ''
+	EQUALITY caseIgnoreIA5Match
+	SUBSTR caseIgnoreIA5SubstringsMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} )
+
+attributetype ( 1.3.6.1.4.1.7914.1.4.1.3 NAME 'qlaUidPrefix'
+	DESC ''
+	EQUALITY caseIgnoreIA5Match
+	SUBSTR caseIgnoreIA5SubstringsMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} SINGLE-VALUE )
+
+attributetype ( 1.3.6.1.4.1.7914.1.4.1.4 NAME 'qlaQmailUid'
+	DESC ''
+	EQUALITY integerMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
+attributetype ( 1.3.6.1.4.1.7914.1.4.1.5 NAME 'qlaQmailGid'
+	DESC ''
+	EQUALITY integerMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
+attributetype ( 1.3.6.1.4.1.7914.1.4.1.6 NAME 'qlaMailMStorePrefix'
+	DESC ''
+	EQUALITY caseIgnoreIA5Match
+	SUBSTR caseIgnoreIA5SubstringsMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} SINGLE-VALUE )
+
+attributetype ( 1.3.6.1.4.1.7914.1.4.1.7 NAME 'qlaMailQuotaSize'
+	DESC ''
+	EQUALITY integerMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
+attributetype ( 1.3.6.1.4.1.7914.1.4.1.8 NAME 'qlaMailQuotaCount'
+	DESC ''
+	EQUALITY integerMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
+attributetype ( 1.3.6.1.4.1.7914.1.4.1.9 NAME 'qlaMailSizeMax'
+	DESC ''
+	EQUALITY integerMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
+attributetype ( 1.3.6.1.4.1.7914.1.4.1.10 NAME 'qlaMailHostList'
+	DESC ''
+	EQUALITY caseIgnoreIA5Match
+	SUBSTR caseIgnoreIA5SubstringsMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} )
+
+
+# Object Class Definitions
+
+objectclass ( 1.3.6.1.4.1.7914.1.2.2.1 NAME 'qmailUser'
+	DESC 'QMail-LDAP User'
+	SUP top
+	AUXILIARY
+	MUST ( mail )
+	MAY ( uid $ mailMessageStore $ homeDirectory $ userPassword $
+	      mailAlternateAddress $ qmailUID $ qmailGID $
+	      mailHost $ mailForwardingAddress $ deliveryProgramPath $
+	      qmailDotMode $ deliveryMode $ mailReplyText $
+	      accountStatus $ qmailAccountPurge $ 
+	      mailQuotaSize $ mailQuotaCount $ mailSizeMax ) )
+
+objectclass ( 1.3.6.1.4.1.7914.1.3.2.1 NAME 'qmailGroup'
+	DESC 'QMail-LDAP Group'
+	SUP top
+	AUXILIARY
+	MUST ( mail $ mailAlternateAddress $ mailMessageStore )
+	MAY ( dnmember $ rfc822member $ filtermember $ senderconfirm $
+	      membersonly $ confirmtext $ dnmoderator $ rfc822moderator $
+	      moderatortext $ dnsender $ rfc822sender $ filtersender $
+	      bounceadmin) )
+
+objectclass ( 1.3.6.1.4.1.7914.1.4.2.1 NAME 'qldapAdmin'
+	DESC 'QMail-LDAP Subtree Admin'
+	SUP top
+	AUXILIARY
+	MUST ( qlaDnManager $ qlaDomainList $ qlaMailMStorePrefix $
+	       qlaMailHostList )
+	MAY ( qlaUidPrefix $ qlaQmailUid $ qlaQmailGid $ qlaMailQuotaSize $
+	      qlaMailQuotaCount $ qlaMailSizeMax ) )
+
diff -ruN qmail-1.03-orig/qmail-secretary.c qmail-1.03-ldap-20060201-orig/qmail-secretary.c
--- qmail-1.03-orig/qmail-secretary.c	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/qmail-secretary.c	2006-02-25 11:00:55.000000000 +0100
@@ -0,0 +1,1172 @@
+/*
+ * Copyright (c) 2003-2004 Claudio Jeker,
+ *      Internet Business Solutions AG, CH-8005 Zürich, Switzerland
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Internet Business
+ *      Solutions AG and its contributors.
+ * 4. Neither the name of the author nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include "base64.h"
+#include "byte.h"
+#include "case.h"
+#include "control.h"
+#include "digest_sha1.h"
+#include "direntry.h"
+#include "env.h"
+#include "error.h"
+#include "fd.h"
+#include "fmt.h"
+#include "getln.h"
+#include "mailmagic.h"
+#include "newfield.h"
+#include "now.h"
+#include "open.h"
+#include "qmail.h"
+#include "quote.h"
+#include "readwrite.h"
+#include "seek.h"
+#include "sgetopt.h"
+#include "sig.h"
+#include "str.h"
+#include "stralloc.h"
+#include "strerr.h"
+#include "substdio.h"
+#include "wait.h"
+#ifdef AUTOMAILDIRMAKE
+#include "qldap-errno.h"
+#include "mailmaker.h"
+#endif
+
+#define FATAL "qmail-secretary: fatal: "
+#define WARN  "qmail-secretary: warn: "
+
+const char *confirmmess = "Hi,\n\n\
+I'm mailgroup secretary, an automated mail-handling program.\n\
+I received a message from you addressed to %LIST%\n\
+for which I'm responsible. The top of your message is shown below.\n\
+\n\
+I'm here to protect the address %LIST% from\n\
+all anonymous messages and bulk mail messages.\n\
+\n\
+If you reply to this notice, you are acknowledging that your message\n\
+identifies you and is not part of a bulk mailing.\n\
+I won't look at the contents of your reply. A simple OK is fine.\n\
+\n\
+If you do not reply to this notice, your message will be dropped\n\
+and the recipient will not receive it.\n\
+\n\
+I realize that this confirmation process is inconvenient. I'm sorry for\n\
+the hassle.\n\
+\n\
+Sincerely,\n\
+The mailgroup secretary program\n\
+\n\
+";
+
+const char *approvemess = "Hi,\n\n\
+I'm mailgroup secretary, an automated mail-handling program.\n\
+I need an approval that the attached message is allowed to be sent\n\
+to the %LIST% mailinglist.\n\
+\n\
+To approve a message you must reply to this message. I won't look at\n\
+the contents of your reply. A simple OK is fine.\n\
+\n\
+To deny a message no action must be taken. The message will be rejected\n\
+automaticaliy after a few days.\n\
+\n\
+Sincerely,\n\
+The mailgroup secretary program\n\
+\n\
+";
+
+void
+temp_nomem(void)
+{
+	strerr_die2x(111, FATAL, "Out of memory.");
+}
+void
+temp_qmail(const char *fn)
+{
+	strerr_die4sys(111, FATAL, "Unable to open ", fn, ": ");
+}
+void
+temp_rewind(void)
+{
+	strerr_die2x(111, FATAL, "Unable to rewind message.");
+}
+void
+temp_read(void)
+{
+	strerr_die2x(111, FATAL, "Unable to read message.");
+}
+void
+temp_fork(void)
+{
+	strerr_die2sys(111, FATAL, "Unable to fork: ");
+}
+void
+die_badaddr(void)
+{
+	strerr_die2x(100, FATAL,
+	    "I do not accept messages at this address (#5.1.1)");
+}
+void usage(void)
+{
+	strerr_die1x(100,
+	    "qmail-secretary: usage:\n    "
+	    "qmail-secretary [ -Z ] [ -c | -C ] [[ -m addr ] ... ] "
+	    "[ -M file ] maildir\n    "
+	    "qmail-secretary -z ezmlmdir [ -c | -C ] [[ -m addr ] ... ] "
+	    "[ -M file ]\n                    maildir [ ezmlm-send ... ]\n");
+}
+
+char *sender;
+char *host;
+char *local;
+
+stralloc mailinglist = {0};
+stralloc inhost = {0};
+stralloc inlocal = {0};
+stralloc outhost = {0};
+stralloc outlocal = {0};
+stralloc messline = {0};
+stralloc moderators = {0};
+stralloc hashid = {0};
+stralloc action = {0};
+stralloc dtline = {0};
+stralloc rpline = {0};
+stralloc confirmtext = {0};
+stralloc approvetext = {0};
+stralloc foo = {0};
+
+int flagconfirm = 0;
+int flagezmlm = 0;
+
+void nullsender(void);
+void qgroupinit(void);
+void ezmlminit(char *);
+void extractrcpt(stralloc *, stralloc *);
+void getconf_line(stralloc *, const char *, const char *);
+void getconf_file(stralloc *, const char *, const char *);
+void getconf_text(stralloc *, const char *, const char *, const char *);
+void blast(stralloc *, const char *, const char *, char **);
+char *replyaddr(stralloc *, const char *);
+char *fromaddr(const char *);
+char *moderatoraddr(void);
+void sendconfirm(stralloc *, int);
+void sendmoderator(stralloc *, int);
+int sendmail(struct qmail *, int, int, stralloc *, stralloc *, stralloc *);
+void attachmail(struct qmail *, int, unsigned int);
+void bouncefx(void);
+void createhash(int, stralloc *);
+char *createname(stralloc *, const char *, const char *, stralloc *);
+void checkmessage(stralloc *, const char *, const char *);
+void delmessage(stralloc *, const char *, const char *);
+int mvmessage(stralloc *, stralloc *, const char *);
+void savemessage(stralloc *, const char *, const char *);
+void reset_sender(void);
+void clean(const char *);
+
+int
+main(int argc, char **argv)
+{
+	char		*ezmlmdir;
+	char		*maildir;
+	char		*modfile;
+	int		opt;
+	unsigned int	i;
+	
+	sender = env_get("SENDER");
+	if (!sender) strerr_die2x(100, FATAL, "SENDER not set");
+	local = env_get("LOCAL");
+	if (!local) strerr_die2x(100, FATAL, "LOCAL not set");
+	host = env_get("HOST");
+	if (!host) strerr_die2x(100, FATAL, "HOST not set");
+
+	if (!stralloc_copys(&moderators, "")) temp_nomem();
+	modfile = 0;
+	ezmlmdir = 0;
+	
+	while((opt = getopt(argc,argv,"cCm:M:z:Z")) != opteof)
+	switch (opt) {
+	case 'c':
+		flagconfirm = 1;
+		break;
+	case 'C':
+		flagconfirm = 0;
+		break;
+	case 'm':
+		if (!stralloc_cats(&moderators, optarg)) temp_nomem();
+		if (!stralloc_0(&moderators)) temp_nomem();
+		break;
+	case 'M':
+		modfile = optarg;
+		break;
+	case 'z':
+		flagezmlm = 1;
+		ezmlmdir = optarg;
+		break;
+	case 'Z':
+		flagezmlm = 0;
+		break;
+	default:
+		usage();
+		/* NOTREACHED */
+	}
+	
+	argc -= optind;
+	argv += optind;
+	if (!(maildir = *argv++)) usage();
+	if (!flagezmlm && *argv) usage();
+	if (flagezmlm && !*argv) usage();
+
+	if (flagezmlm == 0)
+		qgroupinit();
+	else
+		ezmlminit(ezmlmdir); /* does a chdir to ezmlm dir */
+
+	if (modfile != 0) {
+		getconf_file(&messline, modfile, ezmlmdir);
+		if (!stralloc_cat(&moderators, &messline)) temp_nomem();
+		if (!stralloc_copys(&messline, "")) temp_nomem();
+	}
+	
+	if (!quote2(&foo,sender)) temp_nomem();
+	if (!stralloc_copys(&rpline,"Return-Path: <")) temp_nomem();
+	if (!stralloc_cat(&rpline,&foo)) temp_nomem();
+	for (i = 0;i < rpline.len;++i)
+		if (rpline.s[i] == '\n')
+			rpline.s[i] = '_';
+	if (!stralloc_cats(&rpline,">\n")) temp_nomem();
+
+	if (!stralloc_copys(&dtline, "Delivered-To: secretary for "))
+		temp_nomem();
+	if (!stralloc_cat(&dtline, &outlocal)) temp_nomem();
+	if (!stralloc_cats(&dtline, "@")) temp_nomem();
+	if (!stralloc_cat(&dtline, &outhost)) temp_nomem();
+	for (i = 0; i < dtline.len; ++i)
+		if (dtline.s[i] == '\n')
+			dtline.s[i] = '_';
+	if (!stralloc_cats(&dtline,"\n")) temp_nomem();
+	
+	
+	extractrcpt(&action, &hashid);
+#ifdef AUTOMAILDIRMAKE
+	switch (maildir_make(maildir)) {
+	case OK:
+		break;
+	case MAILDIR_CORRUPT:
+		strerr_die4x(111,FATAL, "The maildir '", maildir,
+		    "' seems to be corrupted. (#4.2.1)");
+	case ERRNO:
+	default:
+		strerr_die4x(111,FATAL, "Unable to create maildir '", maildir,
+		    "' (#4.3.0)");
+	}
+#endif
+
+	if (action.len == 0) {
+		nullsender();
+		bouncefx();
+		if (flagconfirm == 1) {
+			savemessage(&hashid, maildir, "new/");
+			sendconfirm(&hashid, 0);
+		} else {
+			savemessage(&hashid, maildir, "cur/");
+			sendmoderator(&hashid, 0);
+		}
+		clean(maildir);
+		_exit(99);
+	} else if (case_startb(action.s, action.len, "approve")) {
+		nullsender();
+		bouncefx();
+		if (hashid.len == 0)
+			strerr_die2x(100, FATAL, "Approve message without id.");
+		checkmessage(&hashid, maildir, "cur/");
+		blast(&hashid, maildir, "cur/", argv);
+		clean(maildir);
+		_exit(99);
+	} else if (case_startb(action.s, action.len, "confirm")) {
+		nullsender();
+		bouncefx();
+		if (hashid.len == 0)
+			strerr_die2x(100, FATAL, "Confirm message without id.");
+		checkmessage(&hashid, maildir, "new/");
+		if (moderators.len == 0)
+			blast(&hashid, maildir, "new/", argv);
+		else
+			sendmoderator(&hashid,
+			    mvmessage(&hashid, &hashid, maildir));
+		clean(maildir);
+		_exit(99);
+	} else if (case_startb(action.s, action.len, "reject")) {
+		delmessage(&hashid, maildir, "new/");
+		clean(maildir);
+		strerr_die2x(99, WARN, "confirmation to sender bounced.");
+	} else if (case_startb(action.s, action.len, "bounce")) {
+		clean(maildir);
+		strerr_die2x(99, WARN, "message to moderator bounced.");
+	} else if (case_startb(action.s, action.len, "moderators")) {
+		clean(maildir);
+		die_badaddr();
+	}
+	/* unknown action, pass mail to the next tool */
+	clean(maildir);
+	return 0;
+}
+
+void
+nullsender(void)
+{
+	if (!*sender)
+		strerr_die2x(100, FATAL,
+		    "I don't reply to bounce messages. (#5.7.2)");
+	if (!sender[str_chr(sender,'@')])
+		strerr_die2x(100, FATAL,
+		    "I don't reply to senders without host names."
+		    " (#5.7.2)");
+	if (str_diff(sender,"#@[]") == 0)
+		strerr_die2x(100, FATAL,
+		    "I don't reply to bounce messages. (#5.7.2)");
+}
+
+void
+qgroupinit(void)
+{
+	char *t;
+
+	/*
+	 * following vars need to be set:
+	 * inhost and outhost will be set to $HOST
+	 * inlocal and outlocal will set to the base address of the group
+	 * in other words: $LOCAL[0]..$LOCAL[strlen($LOCAL) - strlen($EXT) - 1]
+	 * but only if EXT is non null else inlocal and outlocal are eq $LOCAL
+	 */
+	if (!stralloc_copys(&inhost, host)) temp_nomem();
+	if (!stralloc_copys(&outhost, host)) temp_nomem();
+	
+	t = env_get("EXT");
+	if (t != 0 && *t != '\0') {
+		if (!stralloc_copyb(&inlocal, local,
+			    str_len(local) - str_len(t) - 1))
+			temp_nomem();
+		if (!stralloc_copy(&outlocal, &inlocal)) temp_nomem();
+	} else {
+		if (!stralloc_copys(&inlocal, local)) temp_nomem();
+		if (!stralloc_copys(&outlocal, local)) temp_nomem();
+	}
+	if (!stralloc_copy(&mailinglist, &outlocal)) temp_nomem();
+	if (!stralloc_append(&mailinglist, "@")) temp_nomem();
+	if (!stralloc_cat(&mailinglist, &outhost)) temp_nomem();
+	
+	t = env_get("APPROVEMESS");
+	if (t != 0) {
+		if (!stralloc_copys(&approvetext, t)) temp_nomem();
+	} else {
+		if (!stralloc_copys(&approvetext, approvemess)) temp_nomem();
+	}
+	t = env_get("CONFIRMMESS");
+	if (t != 0) {
+		if (!stralloc_copys(&confirmtext, t)) temp_nomem();
+	} else {
+		if (!stralloc_copys(&confirmtext, confirmmess)) temp_nomem();
+	}
+}
+
+void
+ezmlminit(char *dir)
+{
+	if (chdir(dir) == -1)
+		strerr_die4sys(111,FATAL,"unable to switch to ",dir,": ");
+
+	getconf_line(&mailinglist,"mailinglist", dir);
+	getconf_line(&inhost,"inhost", dir);
+	getconf_line(&inlocal,"inlocal", dir);
+	getconf_line(&outhost,"outhost", dir);
+	getconf_line(&outlocal,"outlocal", dir);
+
+	getconf_text(&approvetext, "text/approve", dir, approvemess);
+	getconf_text(&confirmtext, "text/confirm", dir, confirmmess);
+}
+
+void
+extractrcpt(stralloc *a, stralloc *h)
+{
+	char		*s;
+	unsigned int	i;
+
+	if (!stralloc_copys(a, "")) temp_nomem();
+	if (!stralloc_copys(h, "")) temp_nomem();
+
+	if (inhost.len != str_len(host)) die_badaddr();
+	if (case_diffb(inhost.s,inhost.len,host)) die_badaddr();
+	if (inlocal.len > str_len(local)) die_badaddr();
+	if (case_diffb(inlocal.s,inlocal.len,local)) die_badaddr();
+
+	/*
+	 * action is $LOCAL + inlocal.len + 1 but only if
+	 * $LOCAL + inlocal.len == '-'
+	 * and action.len is limited to str_chr(action.s, '-') - 1
+	 * hash is $LOCAL + inlocal.len + 1 + action.len + 1
+	 */
+	s = local + inlocal.len;
+	if (*s == '\0') return; /* no action, no hash */
+	if (*s != '-') /* WTF, give up and let a other tool try */
+		strerr_die2x(0, WARN, "mail address has bad extension.");
+	s++;
+	i = str_chr(s,'-');
+	if (!stralloc_copyb(a, s, i)) temp_nomem();
+	if (s[i] == '\0')
+		return; /* just a action (e.g. moderators) */
+	if (!stralloc_copys(h, s+i+1)) temp_nomem();
+}
+
+void
+getconf_line(stralloc *sa, const char *fn, const char *dir)
+{
+	switch (control_readline(sa, fn)) {
+	case 0:
+		strerr_die5x(100, FATAL, dir, "/", fn, " does not exist");
+	case 1:
+		return;
+	default:
+		strerr_die6sys(111, FATAL, "unable to read ",
+		    dir, "/", fn, ": ");
+	}
+}
+
+void
+getconf_file(stralloc *sa, const char *fn, const char *dir)
+{
+	switch (control_readfile(sa, fn, 0)) {
+	case 0:
+		strerr_die5x(100, FATAL, dir, "/", fn, " does not exist");
+	case 1:
+		return;
+	default:
+		strerr_die6sys(111, FATAL, "unable to read ",
+		    dir, "/", fn, ": ");
+	}
+}
+
+void
+getconf_text(stralloc *sa, const char *fn, const char *dir, const char *def)
+{
+	switch (control_readrawfile(sa, fn)) {
+	case 0:
+		if (!stralloc_copys(sa, def)) temp_nomem();
+	case 1:
+		return;
+	default:
+		strerr_die6sys(111, FATAL, "unable to read ",
+		    dir, "/", fn, ": ");
+	}
+}
+
+char *
+replyaddr(stralloc *h, const char *a)
+{
+	static stralloc addr;
+
+	if (!stralloc_copy(&addr, &outlocal)) temp_nomem();
+	if (!stralloc_cats(&addr, "-")) temp_nomem();
+	if (!stralloc_cats(&addr, a)) temp_nomem();
+	if (!stralloc_cats(&addr, "-")) temp_nomem();
+	if (!stralloc_cat(&addr, h)) temp_nomem();
+	if (!stralloc_cats(&addr, "@")) temp_nomem();
+	if (!stralloc_cat(&addr, &outhost)) temp_nomem();
+	if (!stralloc_0(&addr)) temp_nomem();
+
+	return addr.s;
+}
+
+char *
+fromaddr(const char *a)
+{
+	static stralloc from;
+
+	if (!stralloc_copys(&from, "The mailgroup secretary <"))
+		temp_nomem();
+	if (!stralloc_cats(&from, a)) temp_nomem();
+	if (!stralloc_cats(&from, ">\n")) temp_nomem();
+	if (!stralloc_0(&from)) temp_nomem();
+	
+	return from.s;
+}
+
+char *
+moderatoraddr(void)
+{
+	static stralloc modaddr;
+
+	if (!stralloc_copys(&modaddr, "The moderators of "))
+		temp_nomem();
+	if (!stralloc_cat(&modaddr, &mailinglist)) temp_nomem();
+	if (!stralloc_cats(&modaddr, " <")) temp_nomem();
+	if (!stralloc_cat(&modaddr, &outlocal)) temp_nomem();
+	if (!stralloc_cats(&modaddr, "-moderators@")) temp_nomem();
+	if (!stralloc_cat(&modaddr, &outhost)) temp_nomem();
+	if (!stralloc_cats(&modaddr, ">\n")) temp_nomem();
+	if (!stralloc_0(&modaddr)) temp_nomem();
+	
+	return modaddr.s;
+}
+
+struct mheader mheader[] = {
+	{ "To:", 0, FORCE, 0 },
+	{ "From:", 0, FORCE, 0 }, /* envelope sender is fixed */
+	{ "Subject:", 0, ALLOW, 0 },
+//	{ "Reply-To:", 0, FORCE, 0 }, /* controversial RFC2076 */
+	{ "MIME-Version:", "1.0", FORCE, 0 },
+	{ "Content-Type:", 0, FORCE, 0 },
+	{ "Content-Transfer-Encoding:", 0, FORCE, 0 },
+	{ "X-Mailer:", "qmail-secretary (by qmail-ldap)", FORCE, 0 },
+	{ "Precedence:", "junk", FORCE, 0 },
+	{ "X-", 0, ALLOW, 0 },
+	{ DEFAULT, 0, DENY, 0 },
+	{ 0, 0, 0, 0 }
+};
+
+stralloc header = {0};
+char strnum[FMT_ULONG];
+
+void
+sendconfirm(stralloc *hash, int fd)
+{
+	struct qmail qqt;
+	const char *qqx;
+	unsigned long qp;
+	int r;
+	
+	mheader[0].v = sender;
+	mheader[1].v = fromaddr(replyaddr(hash, "confirm"));
+	mheader[2].v = "Message sender confirmation";
+
+	r = headermagic(&confirmtext, &header, 0, mheader);
+	if (r == -1)
+		strerr_die2sys(111, FATAL, "Header magic failed: ");
+
+	if (qmail_open(&qqt) == -1) temp_fork();
+	qp = qmail_qp(&qqt);
+	
+	if (sendmail(&qqt, fd, 10*1024, &header, &confirmtext, hash) == -1)
+		goto fail_nomem;
+	
+	qmail_from(&qqt, replyaddr(hash, "reject"));
+	qmail_to(&qqt, sender);
+	qqx = qmail_close(&qqt);
+	if (!*qqx) {
+		strnum[fmt_ulong(strnum, qp)] = 0;
+		strerr_warn2("qmail-secretary: info: qp ", strnum, 0);
+		return;
+	}
+	strerr_die4x(*qqx == 'D' ? 100 : 111, FATAL,
+	    "Unable to send reply message: ", qqx + 1, ".");
+
+fail_nomem:
+	qmail_fail(&qqt);
+	qmail_close(&qqt);
+	temp_nomem();
+}
+
+void
+sendmoderator(stralloc *hash, int fd)
+{
+	struct qmail qqt;
+	char *s, *smax;
+	const char *qqx;
+	unsigned long qp;
+	int r;
+	
+	mheader[0].v = moderatoraddr();
+	mheader[1].v = fromaddr(replyaddr(hash, "approve"));
+	mheader[2].v = "Moderation request";
+
+	r = headermagic(&approvetext, &header, 0, mheader);
+	if (r == -1)
+		strerr_die2sys(111, FATAL, "Header magic failed: ");
+
+	if (moderators.s == NULL || moderators.len == 0)
+		strerr_die2x(100, FATAL,
+		    "no moderators found but needed.");
+
+	if (qmail_open(&qqt) == -1) temp_fork();
+	qp = qmail_qp(&qqt);
+
+	if (sendmail(&qqt, fd, 128*1024, &header, &approvetext, hash) == -1)
+		goto fail_nomem;
+
+	qmail_from(&qqt, replyaddr(hash, "bounce"));
+
+	/* first check if the mail is comming from a moderator */
+	for (s = moderators.s, smax = moderators.s + moderators.len; s < smax;
+	    s += str_len(s) + 1) {
+		if (!str_diff(sender, s)) {
+			qmail_to(&qqt, s);
+			break;
+		}
+	}
+	/* not from a moderator so send to all moderators */
+	if (s >= smax)
+		for (s = moderators.s, smax = moderators.s + moderators.len;
+		    s < smax; s += str_len(s) + 1) {
+			qmail_to(&qqt, s);
+		}
+
+	qqx = qmail_close(&qqt);
+	if (!*qqx) {
+		strnum[fmt_ulong(strnum,qmail_qp(&qqt))] = 0;
+		strerr_warn2("qmail-secretary: info: qp ", strnum, 0);
+		return;
+	}
+	strerr_die4x(*qqx == 'D' ? 100 : 111, FATAL,
+	    "Unable to send approve message: ", qqx + 1, ".");
+
+fail_nomem:
+	qmail_fail(&qqt);
+	qmail_close(&qqt);
+	temp_nomem();
+}
+
+struct mheader cheader[] = {
+	{ "Content-Type:", "text/plain; charset=\"iso-8859-1\"\n", ALLOW, 0 },
+	{ "Content-Transfer-Encoding:", "8bit", ALLOW, 0 },
+	{ DEFAULT, 0, DENY, 0 },
+	{ 0, 0, 0, 0 }
+};
+
+int
+sendmail(struct qmail *qq, int fd, int maxsize,
+    stralloc *head, stralloc *message, stralloc *hash)
+{
+	datetime_sec starttime;
+	int offset;
+	unsigned int len, i, j;
+	
+	/* mail header */
+	qmail_put(qq, dtline.s, dtline.len);
+	/* XXX Date: qmail uses GMT based dates which is sometimes confusing */
+	/* message-id and date line */
+	starttime = now();
+	if (!newfield_datemake(starttime)) return -1;
+	if (!newfield_msgidmake(inhost.s, inhost.len, starttime)) return -1;
+	qmail_put(qq, newfield_msgid.s, newfield_msgid.len);
+	qmail_put(qq, newfield_date.s, newfield_date.len);
+
+	if (flagezmlm) {
+		qmail_puts(qq, "Mailing-List: ");
+		qmail_put(qq, mailinglist.s, mailinglist.len);
+		qmail_puts(qq, "\n");
+	}
+	/* mime magic (multipart/mixed) header*/
+	mimemagichead(head, hash);
+	
+	/* write parsed header */
+	qmail_put(qq, head->s, head->len);
+
+	/* end of header marker */
+	qmail_puts(qq, "\n");
+
+	/* mime magic (first attachement secretary text)*/
+	qmail_puts(qq, mimemagic());
+	qmail_puts(qq, "\n");
+	
+	offset = headermagic(message, head, 0, cheader);
+	if (offset == -1) return -1;
+	qmail_put(qq, head->s, head->len);
+	qmail_puts(qq, "\n");
+	
+	/* body, expand %LIST% to list name. */
+	len = message->len;
+	for (i = offset; i < len; i += j) {
+		j = byte_chr(message->s + i, len - i, '%');
+		qmail_put(qq, message->s + i, j);
+		if (*(message->s + i + j) == '%') {
+			if (case_startb(message->s + i + j,
+				    len - i -j, "%LIST%")) {
+				qmail_put(qq, outlocal.s, outlocal.len);
+				qmail_puts(qq, "@");
+				qmail_put(qq, outhost.s, outhost.len);
+				i += 6;
+			} else {
+				qmail_put(qq, message->s + i + j, 1);
+				j++;
+			}
+		}
+	}
+	/* add a empty newline, just to be sure */
+	qmail_puts(qq, "\n");
+
+	/* mime magic (second attachement user message) */
+	qmail_puts(qq, mimemagic());
+	qmail_puts(qq, "\n");
+	qmail_puts(qq, "Content-Type: message/rfc822\n\n");
+	
+	/* attach ~10kB of message */
+	attachmail(qq, fd, maxsize);
+
+	/* mime magic end */
+	qmail_puts(qq, mimemagic());
+	qmail_puts(qq, "--\n\n");
+	return 0;
+}
+
+char buf[4096];
+
+void
+attachmail(struct qmail *qq, int fd, unsigned int maxsize)
+{
+	substdio	ss;
+	int		match;
+	
+	if (seek_begin(fd) == -1) {
+		qmail_fail(qq);
+		qmail_close(qq);
+		temp_rewind();
+	}
+	substdio_fdbuf(&ss, subread, fd, buf, sizeof(buf));
+	for (;;) {
+		if (getln(&ss, &messline, &match, '\n') != 0) {
+			qmail_fail(qq);
+			qmail_close(qq);
+			temp_read();
+		}
+		if (!match) break;
+		if (messline.len > maxsize && messline.len > 100)
+			messline.len = maxsize;
+		qmail_put(qq, messline.s, messline.len);
+		maxsize -= messline.len;
+		if (maxsize <= 0) {
+			qmail_puts(qq,"\n\n--- End of message stripped.\n");
+			break;
+		}
+	}
+	qmail_puts(qq, "\n");
+}
+
+void
+bouncefx(void)
+{
+	substdio	ss;
+	int		match;
+	unsigned int	l;
+
+	if (seek_begin(0) == -1) temp_rewind();
+	substdio_fdbuf(&ss, subread, 0, buf, sizeof(buf));
+	for (;;) {
+		if (getln(&ss, &messline, &match, '\n') != 0) temp_read();
+		if (!match) break;
+		if (messline.len <= 1) break;
+		if (case_startb(messline.s, messline.len, "mailing-list:"))
+			strerr_die2x(100, FATAL,
+			    "incoming message has Mailing-List. (#5.7.2)");
+		if (case_startb(messline.s, messline.len, "precedence:")) {
+			for (l = 11; l < messline.len; l++)
+				if (messline.s[l] != ' ' &&
+				    messline.s[l] != '\t')
+					break;
+			if (case_startb(messline.s + l, messline.len - l,
+			    "junk") ||
+			    case_startb(messline.s + l, messline.len - l,
+			    "bulk") ||
+			    case_startb(messline.s + l, messline.len - l,
+			    "list"))
+				strerr_die2x(100, FATAL,
+				    "incoming message has bad precedence. "
+				    "(#5.7.2)");
+		}
+		if (messline.len == dtline.len)
+			if (byte_equal(messline.s, messline.len, dtline.s))
+				strerr_die2x(100, FATAL,
+				    "this message is looping: "
+				    "it already has my Delivered-To line. "
+				    "(#5.4.6)");
+	}
+}
+
+unsigned char	sha1_hash[SHA1_LEN];
+
+void
+createhash(int fd, stralloc *hash)
+{
+	SHA1_CTX	ctx;
+	substdio	ss;
+	unsigned long	ul;
+	int		match;
+	
+	if (!stralloc_copys(hash, "")) temp_nomem();
+	SHA1Init(&ctx);
+	/*
+	 * XXX this is neither 64bit clean nor endian safe but
+	 * I don't care. The hash is calculated only once and needs
+	 * to include enough entropy to make it almost impossible to
+	 * guess or bruteforce attack the hash.
+	 */
+	ul = (unsigned long) now();
+	SHA1Update(&ctx, (unsigned char *)&ul, sizeof(unsigned long));
+	ul = (unsigned long) getpid();
+	SHA1Update(&ctx, (unsigned char *)&ul, sizeof(unsigned long));
+
+
+	if (seek_begin(fd) == -1) temp_rewind();
+	substdio_fdbuf(&ss, subread, fd, buf, sizeof(buf));
+	for (;;)
+	{
+		if (getln(&ss, &messline, &match, '\n') != 0) temp_read();
+		if (!match) break;
+		SHA1Update(&ctx, messline.s, messline.len);
+	}
+
+	SHA1Final(sha1_hash, &ctx);
+	if (hex_ntops(sha1_hash, sizeof(sha1_hash), hash) == -1)
+		temp_nomem();
+}
+
+stralloc fname = {0};
+stralloc nname = {0};
+
+char *
+createname(stralloc *sa, const char *maildir, const char *subdir, stralloc *h)
+{
+	if (!stralloc_copys(sa, maildir)) temp_nomem();
+	if (sa->s[sa->len-1] != '/')
+		if (!stralloc_append(sa, "/")) temp_nomem();
+	if (!stralloc_cats(sa, subdir)) temp_nomem();
+	if (sa->s[sa->len-1] != '/')
+		if (!stralloc_append(sa, "/")) temp_nomem();
+	if (!stralloc_cat(sa, h)) temp_nomem();
+	if (!stralloc_0(sa)) temp_nomem();
+	return sa->s;
+}
+
+void
+checkmessage(stralloc *hash, const char *maildir, const char *subdir)
+{
+	struct	stat	st;
+	char	*s;
+
+	s = createname(&fname, maildir, subdir, hash);
+	
+	if (stat(s,&st) == -1) {
+		if (errno == error_noent)
+			strerr_die2x(99, WARN,
+			    "Message no longer in repository.");
+		strerr_die2sys(111, FATAL,
+		    "Could not stat message: ");
+	}
+}
+
+void
+delmessage(stralloc *hash, const char *maildir, const char *subdir)
+{
+	struct	stat	st;
+	char	*s;
+
+	s = createname(&fname, maildir, subdir, hash);
+	
+	if (stat(s,&st) == -1) {
+		if (errno == error_noent) return;
+		strerr_die2sys(111, FATAL, "Could not stat message: ");
+	}
+	if (unlink(s) == -1)
+		strerr_warn2(WARN, "Could not unlink message: ", &strerr_sys);
+}
+
+int
+mvmessage(stralloc *hash, stralloc *newhash, const char *maildir)
+{
+	struct	stat	st;
+	char	*s, *t;
+	int	loop, fd;
+
+	s = createname(&fname, maildir, "new/", hash);
+	
+	if (stat(s,&st) == -1) {
+		if (errno == error_noent)
+			strerr_die2x(99, WARN,
+			    "Message no longer in repository.");
+		strerr_die2sys(111, FATAL,
+		    "Could not stat message: ");
+	}
+	for (loop = 0;; ++loop) {
+		createhash(0, hash);
+		t = createname(&nname, maildir, "cur/", hash);
+		if (stat(t, &st) == -1 && errno == error_noent)
+			break;
+		/* really should never get to this point */
+		if (loop == 2)
+			strerr_die2sys(111, FATAL, "Could not stat new file: ");
+		sleep(2);
+	}	
+
+	if (rename(s, t) == -1)
+		strerr_die2sys(111, FATAL, "Could not move file: ");
+
+	fd = open_read(t);
+	if (fd == -1)
+		strerr_die2sys(111, FATAL, "Unable to open message: ");
+	
+	return fd;
+}
+
+char outbuf[4096];
+
+void tryunlinktmp(void) { unlink(fname.s); }
+void sigalrm(void)
+{
+	tryunlinktmp();
+	strerr_die1x(111, "Timeout on maildir delivery.");
+}
+
+void
+savemessage(stralloc *hash, const char *maildir, const char *subdir)
+{
+	struct	stat	st;
+	substdio	ss, ssout;
+	char		*s, *t;
+	int		loop, fd;
+	
+	sig_alarmcatch(sigalrm);
+
+	for (loop = 0;; ++loop) {
+		createhash(0, hash);
+		s = createname(&nname, maildir, subdir, hash);
+		t = createname(&fname, maildir, "tmp/", hash);
+		if (stat(s, &st) == -1 && errno == error_noent)
+			if (stat(t, &st) == -1 && errno == error_noent)
+				break;
+		/* really should never get to this point */
+		if (loop == 2)
+			strerr_die2sys(111, FATAL, "Could not stat tmp file: ");
+		sleep(2);
+	}
+	alarm(86400);
+	fd = open_excl(t);
+	if (fd == -1)
+		strerr_die2sys(111, FATAL, "Unable to open tmp file: ");
+
+	if (seek_begin(0) == -1) temp_rewind();
+	substdio_fdbuf(&ss, subread, 0, buf, sizeof(buf));
+	substdio_fdbuf(&ssout, subwrite, fd, outbuf, sizeof(outbuf));
+	if (substdio_put(&ssout, rpline.s, rpline.len) == -1) goto fail;
+	if (substdio_put(&ssout, dtline.s, dtline.len) == -1) goto fail;
+
+	switch(substdio_copy(&ssout, &ss)) {
+	case -2:
+		strerr_warn2(FATAL, "Unable to read message: ",
+		    &strerr_sys);
+		tryunlinktmp();
+		_exit(111);
+	case -3:
+		goto fail;
+	}
+
+	if (substdio_flush(&ssout) == -1) goto fail;
+	if (fsync(fd) == -1) goto fail;
+	if (close(fd) == -1) goto fail; /* NFS dorks */
+
+	if (link(t, s) == -1) goto fail;
+	/* if it was error_exist, almost certainly successful; i hate NFS */
+	tryunlinktmp(); 
+	sig_alarmdefault();
+	return;
+
+fail:
+	strerr_warn2(FATAL, "Unable to store message: ",
+	    &strerr_sys);
+	tryunlinktmp();
+	_exit(111);
+}
+
+void
+blast(stralloc *hash, const char *maildir, const char *subdir, char **args)
+{
+	substdio ssout;
+	char *s;
+	int child, fd, wstat;
+
+	s = createname(&nname, maildir, subdir, hash);
+
+	if (flagezmlm) {
+		switch (child = fork()) {
+		case -1:
+			temp_fork();
+		case 0:
+			fd = open_read(s);
+			if (fd == -1)
+				strerr_die2sys(111, FATAL,
+				    "Unable to open message: ");
+			if (fd_move(0,fd) == -1)
+				strerr_die2sys(111, FATAL,
+				    "Unable to move fd: ");
+			reset_sender();
+			if (seek_begin(0) == -1) temp_rewind();
+
+			sig_pipedefault();
+			execv(*args, args);
+			strerr_die2sys(111, FATAL, "Unable to exec: ");
+		}
+		wait_pid(&wstat, child);
+		if (wait_crashed(wstat))
+			strerr_die2x(111, FATAL, "Aack, child crashed.");
+		switch(wait_exitcode(wstat)) {
+		case 0:
+		case 99:
+			if (unlink(s) == -1)
+				strerr_warn2(WARN,
+				    "Could not unlink message: ", &strerr_sys);
+			return;
+		case 100:
+		case 64:
+		case 65:
+		case 70:
+		case 76:
+		case 77:
+		case 78:
+		case 112:
+			_exit(100);
+		default:
+			_exit(111);
+		}
+	} else {
+		substdio_fdbuf(&ssout, subwrite, 1, outbuf, sizeof(outbuf));
+		if (substdio_puts(&ssout, "K") == -1) goto fail;
+		if (substdio_puts(&ssout, s) == -1) goto fail;
+		if (substdio_put(&ssout, "", 1) == -1) goto fail;
+		if (substdio_flush(&ssout) == -1) goto fail;
+		
+		return;
+fail:
+		strerr_die2x(111, FATAL, "Unable to write to stdout: ");
+	}
+}
+
+void
+reset_sender(void)
+{
+	substdio	 ss;
+	char		*s;
+	unsigned int	 i;
+	int		 match;
+
+	if (seek_begin(0) == -1) temp_rewind();
+	substdio_fdbuf(&ss, subread, 0, buf, sizeof(buf));
+	for (;;) {
+		if (getln(&ss, &messline, &match, '\n') != 0) temp_read();
+		if (!match) break;
+		if (messline.len <= 1) break;
+		if (case_startb(messline.s, messline.len, "Return-Path:")) {
+			i = byte_chr(messline.s, messline.len, '<');
+			if (i >= messline.len)
+				continue;
+			s = messline.s + i + 1;
+			i = byte_rchr(messline.s, messline.len, '>');
+			if (i >= messline.len)
+				continue;
+			messline.s[i] = '\0';
+			if (!env_put2("SENDER",s)) temp_nomem();
+			break;
+		}
+	}
+}
+
+static void clean_child(void);
+
+static void
+clean_child(void)
+{
+	char const *(dirs[3]);
+	struct stat st;
+	DIR *folder;
+	struct dirent *entry;
+	datetime_sec t;
+	unsigned int i;
+
+	t = now();
+
+	dirs[0]="new/"; dirs[1]="cur/"; dirs[2]="tmp/";
+	for (i=0; i<3; i++) {
+		/* checking for outdated mail */
+		if ((folder = opendir(dirs[i])) == 0) {
+			strerr_warn4(WARN, "Cleanup: Unable to opendir ",
+			    dirs[i], ": ", &strerr_sys);
+			_exit(2);
+		}
+		while ((entry = readdir(folder)) != 0) {
+			if (*entry->d_name == '.') continue;
+			if (!stralloc_copys(&fname, dirs[i])) _exit(1);
+			if (!stralloc_cats(&fname, entry->d_name)) _exit(1);
+			if (!stralloc_0(&fname)) _exit(1);
+			/* remove files after a week */
+			if (stat(fname.s,&st) == 0)
+				if (t > st.st_mtime + 604800)
+					unlink(fname.s);
+		}
+		closedir(folder);
+	}
+	_exit(0);
+}
+
+void
+clean(const char *maildir)
+{
+	int child, wstat;
+
+	switch (child = fork()) {
+	case -1:
+		strerr_warn2(WARN, "Cleanup: Unable to fork: ", &strerr_sys);
+		return;
+	case 0:
+		if (chdir(maildir) == -1)
+			_exit(3);
+		clean_child();
+	}
+
+	wait_pid(&wstat, child);
+	if (wait_crashed(wstat))
+		strerr_warn2(WARN, "Cleanup: Aack, child crashed.", 0);
+	switch(wait_exitcode(wstat)) {
+	case 0:
+		break;
+	case 1:
+		strerr_warn2(WARN, "Cleanup: Aack, child out of memory.", 0);
+		break;
+	case 2:
+		break;
+	case 3:
+		strerr_warn4(WARN, "Cleanup: Unable to switch to ",
+		    maildir, ": ", &strerr_sys);
+		break;
+	}
+}
+
diff -ruN qmail-1.03-orig/qmail-send.c qmail-1.03-ldap-20060201-orig/qmail-send.c
--- qmail-1.03-orig/qmail-send.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/qmail-send.c	2006-02-25 11:00:55.000000000 +0100
@@ -1,5 +1,7 @@
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <stdlib.h>
+#include <unistd.h>
 #include "readwrite.h"
 #include "sig.h"
 #include "direntry.h"
@@ -31,6 +33,7 @@
 #include "constmap.h"
 #include "fmtqfn.h"
 #include "readsubdir.h"
+#include "cdb.h"
 
 /* critical timing feature #1: if not triggered, do not busy-loop */
 /* critical timing feature #2: if triggered, respond within fixed time */
@@ -56,13 +59,15 @@
 stralloc doublebounceto = {0};
 stralloc doublebouncehost = {0};
 
+stralloc custombouncetext = {0};
+
 char strnum2[FMT_ULONG];
 char strnum3[FMT_ULONG];
 
 #define CHANNELS 2
-char *chanaddr[CHANNELS] = { "local/", "remote/" };
-char *chanstatusmsg[CHANNELS] = { " local ", " remote " };
-char *tochan[CHANNELS] = { " to local ", " to remote " };
+const char *chanaddr[CHANNELS] = { "local/", "remote/" };
+const char *chanstatusmsg[CHANNELS] = { " local ", " remote " };
+const char *tochan[CHANNELS] = { " to local ", " to remote " };
 int chanfdout[CHANNELS] = { 1, 3 };
 int chanfdin[CHANNELS] = { 2, 4 };
 int chanskip[CHANNELS] = { 10, 20 };
@@ -96,7 +101,11 @@
 }
 
 void fnmake_info(id) unsigned long id; { fn.len = fmtqfn(fn.s,"info/",id,1); }
+#ifndef BIGTODO
 void fnmake_todo(id) unsigned long id; { fn.len = fmtqfn(fn.s,"todo/",id,0); }
+#else
+void fnmake_todo(id) unsigned long id; { fn.len = fmtqfn(fn.s,"todo/",id,1); }
+#endif
 void fnmake_mess(id) unsigned long id; { fn.len = fmtqfn(fn.s,"mess/",id,1); }
 void fnmake_foop(id) unsigned long id; { fn.len = fmtqfn(fn.s,"foop/",id,0); }
 void fnmake_split(id) unsigned long id; { fn.len = fmtqfn(fn.s,"",id,1); }
@@ -108,18 +117,20 @@
 
 /* this file is too long ----------------------------------------- REWRITING */
 
+stralloc localscdb = {0};
 stralloc rwline = {0};
+struct cdb cdb;
 
 /* 1 if by land, 2 if by sea, 0 if out of memory. not allowed to barf. */
 /* may trash recip. must set up rwline, between a T and a \0. */
 int rewrite(recip)
 char *recip;
 {
-  int i;
-  int j;
-  char *x;
+  unsigned int i;
+  unsigned int j;
+  const char *x;
   static stralloc addr = {0};
-  int at;
+  unsigned int at;
 
   if (!stralloc_copys(&rwline,"T")) return 0;
   if (!stralloc_copys(&addr,recip)) return 0;
@@ -140,15 +151,35 @@
 
   at = byte_rchr(addr.s,addr.len,'@');
 
-  if (constmap(&maplocals,addr.s + at + 1,addr.len - at - 1)) {
-    if (!stralloc_cat(&rwline,&addr)) return 0;
-    if (!stralloc_0(&rwline)) return 0;
-    return 1;
-  }
+  if (localscdb.s && localscdb.len > 1) {
+    static stralloc lowaddr = {0};
+    int fd, r;
+    uint32 dlen;
+
+    if (!stralloc_copyb(&lowaddr,addr.s + at + 1,addr.len - at - 1)) return 0;
+    case_lowerb(lowaddr.s, lowaddr.len);
+    fd = open_read(localscdb.s);
+    if (fd == -1) return 0;
+    cdb_init(&cdb, fd);
+    r = cdb_seek(&cdb, lowaddr.s,lowaddr.len, &dlen);
+    cdb_free(&cdb);
+    close(fd);
+    if (r == -1) return 0;
+    if (r == 1) {
+      if (!stralloc_cat(&rwline,&addr)) return 0;
+      if (!stralloc_0(&rwline)) return 0;
+      return 1;
+    }
+  } else
+    if (constmap(&maplocals,addr.s + at + 1,addr.len - at - 1)) {
+      if (!stralloc_cat(&rwline,&addr)) return 0;
+      if (!stralloc_0(&rwline)) return 0;
+      return 1;
+    }
 
   for (i = 0;i <= addr.len;++i)
     if (!i || (i == at + 1) || (i == addr.len) || ((i > at) && (addr.s[i] == '.')))
-      if (x = constmap(&mapvdoms,addr.s + i,addr.len - i)) {
+      if ((x = constmap(&mapvdoms,addr.s + i,addr.len - i))) {
         if (!*x) break;
         if (!stralloc_cats(&rwline,x)) return 0;
         if (!stralloc_cats(&rwline,"-")) return 0;
@@ -167,9 +198,9 @@
 char *sender;
 char *recip;
 {
- int i;
- int j;
- int k;
+ unsigned int i;
+ unsigned int j;
+ unsigned int k;
 
  i = str_len(sender);
  if (i >= 4)
@@ -211,7 +242,7 @@
  fdinfo = open_read(fn.s);
  if (fdinfo == -1) return 0;
  if (fstat(fdinfo,&st) == -1) { close(fdinfo); return 0; }
- substdio_fdbuf(&ss,read,fdinfo,buf,sizeof(buf));
+ substdio_fdbuf(&ss,subread,fdinfo,buf,sizeof(buf));
  if (getln(&ss,&line,&match,'\0') == -1) { close(fdinfo); return 0; }
  close(fdinfo);
  if (!match) return 0;
@@ -230,12 +261,13 @@
 substdio ssfromqc; char ssfromqcbuf[1024];
 stralloc comm_buf[CHANNELS] = { {0}, {0} };
 int comm_pos[CHANNELS];
+int comm_needshup[CHANNELS];
 
 void comm_init()
 {
  int c;
- substdio_fdbuf(&sstoqc,write,5,sstoqcbuf,sizeof(sstoqcbuf));
- substdio_fdbuf(&ssfromqc,read,6,ssfromqcbuf,sizeof(ssfromqcbuf));
+ substdio_fdbuf(&sstoqc,subwrite,5,sstoqcbuf,sizeof(sstoqcbuf));
+ substdio_fdbuf(&ssfromqc,subread,6,ssfromqcbuf,sizeof(ssfromqcbuf));
  for (c = 0;c < CHANNELS;++c)
    if (ndelay_on(chanfdout[c]) == -1)
    /* this is so stupid: NDELAY semantics should be default on write */
@@ -250,9 +282,37 @@
  return 1;
 }
 
+void comm_hup(c)
+int c;
+{
+  unsigned int delnum = 0xbeef;
+  unsigned char ch;
+
+  /*
+   * send a empty message with delivery number 0xbeef (48879) to the
+   * spawn process. This may cause trouble if you have a concurrency
+   * bigger than this. Acctually it should be save but who has such
+   * a high concurrency anyway.
+   */
+  if (comm_buf[c].s && comm_buf[c].len) {
+    comm_needshup[c] = 1;
+    return;
+  }
+  while (!stralloc_copys(&comm_buf[c],"")) nomem();
+  ch = delnum;
+  while (!stralloc_append(&comm_buf[c],&ch)) nomem();
+  ch = delnum >> 8;
+  while (!stralloc_append(&comm_buf[c],&ch)) nomem();
+  while (!stralloc_0(&comm_buf[c])) nomem();
+  while (!stralloc_0(&comm_buf[c])) nomem();
+  while (!stralloc_0(&comm_buf[c])) nomem();
+  comm_pos[c] = 0;
+  comm_needshup[c] = 0;
+}
+
 void comm_write(c,delnum,id,sender,recip)
 int c;
-int delnum;
+unsigned int delnum;
 unsigned long id;
 char *sender;
 char *recip;
@@ -262,6 +322,8 @@
  while (!stralloc_copys(&comm_buf[c],"")) nomem();
  ch = delnum;
  while (!stralloc_append(&comm_buf[c],&ch)) nomem();
+ ch = delnum >> 8;
+ while (!stralloc_append(&comm_buf[c],&ch)) nomem();
  fnmake_split(id);
  while (!stralloc_cats(&comm_buf[c],fn.s)) nomem();
  while (!stralloc_0(&comm_buf[c])) nomem();
@@ -310,8 +372,11 @@
 	 else
 	  {
 	   comm_pos[c] += w;
-	   if (comm_pos[c] == len)
+	   if (comm_pos[c] == len) {
 	     comm_buf[c].len = 0;
+	     if (comm_needshup[c])
+	       comm_hup(c);
+	   }
 	  }
         }
 }
@@ -443,7 +508,7 @@
 
  readsubdir_init(&rs,"info",pausedir);
 
- while (x = readsubdir_next(&rs,&id))
+ while ((x = readsubdir_next(&rs,&id)))
    if (x > 0)
      pqadd(id);
 }
@@ -452,15 +517,16 @@
 {
  int c;
  struct prioq_elt pe;
- time_t ut[2]; /* XXX: more portable than utimbuf, but still worrisome */
+ struct timeval tvv[2];
 
  for (c = 0;c < CHANNELS;++c)
    while (prioq_min(&pqchan[c],&pe))
     {
      prioq_delmin(&pqchan[c]);
      fnmake_chanaddr(pe.id,c);
-     ut[0] = ut[1] = pe.dt;
-     if (utime(fn.s,ut) == -1)
+     tvv[0].tv_sec = tvv[1].tv_sec = pe.dt;
+     tvv[0].tv_usec = tvv[1].tv_usec = 0;
+     if (utimes(fn.s,tvv) == -1)
        log3("warning: unable to utime ",fn.s,"; message will be retried too soon\n");
     }
 }
@@ -468,7 +534,7 @@
 void pqrun()
 {
  int c;
- int i;
+ unsigned int i;
  for (c = 0;c < CHANNELS;++c)
    if (pqchan[c].p)
      if (pqchan[c].len)
@@ -492,12 +558,12 @@
  }
 ;
 
-int numjobs;
+unsigned int numjobs;
 struct job *jo;
 
 void job_init()
 {
- int j;
+ unsigned int j;
  while (!(jo = (struct job *) alloc(numjobs * sizeof(struct job)))) nomem();
  for (j = 0;j < numjobs;++j)
   {
@@ -508,7 +574,7 @@
 
 int job_avail()
 {
- int j;
+ unsigned int j;
  for (j = 0;j < numjobs;++j) if (!jo[j].refs) return 1;
  return 0;
 }
@@ -517,7 +583,7 @@
 unsigned long id;
 int channel;
 {
- int j;
+ unsigned int j;
  for (j = 0;j < numjobs;++j) if (!jo[j].refs) break;
  if (j == numjobs) return -1;
  jo[j].refs = 1;
@@ -574,10 +640,10 @@
 char *stripvdomprepend(recip)
 char *recip;
 {
- int i;
+ unsigned int i;
  char *domain;
- int domainlen;
- char *prepend;
+ unsigned int domainlen;
+ const char *prepend;
 
  i = str_rchr(recip,'@');
  if (!recip[i]) return recip;
@@ -586,7 +652,7 @@
 
  for (i = 0;i <= domainlen;++i)
    if ((i == 0) || (i == domainlen) || (domain[i] == '.'))
-     if (prepend = constmap(&mapvdoms,domain + i,domainlen - i))
+     if ((prepend = constmap(&mapvdoms,domain + i,domainlen - i)))
       {
        if (!*prepend) break;
        i = str_len(prepend);
@@ -598,6 +664,7 @@
 }
 
 stralloc bouncetext = {0};
+unsigned int bouncemaxbytes = 0;
 
 void addbounce(id,recip,report)
 unsigned long id;
@@ -605,7 +672,7 @@
 char *report;
 {
  int fd;
- int pos;
+ unsigned int pos;
  int w;
  while (!stralloc_copys(&bouncetext,"<")) nomem();
  while (!stralloc_cats(&bouncetext,stripvdomprepend(recip))) nomem();
@@ -650,7 +717,7 @@
 {
  struct qmail qqt;
  struct stat st;
- char *bouncesender;
+ const char *bouncesender;
  char *bouncerecip;
  int r;
  int fd;
@@ -710,18 +777,25 @@
    qmail_puts(&qqt,*sender.s ? ".\n\
 I'm afraid I wasn't able to deliver your message to the following addresses.\n\
 This is a permanent error; I've given up. Sorry it didn't work out.\n\
-\n\
 " : ".\n\
 I tried to deliver a bounce message to this address, but the bounce bounced!\n\
-\n\
 ");
 
+   if (custombouncetext.len > 1)
+   {
+     qmail_puts(&qqt,custombouncetext.s);
+     if (custombouncetext.s[custombouncetext.len-2] != '\n')
+       qmail_puts(&qqt,"\n"); /* I don't think we get here but anyway */
+   }
+
+   qmail_puts(&qqt,"\n");
+
    fd = open_read(fn2.s);
    if (fd == -1)
      qmail_fail(&qqt);
    else
     {
-     substdio_fdbuf(&ssread,read,fd,inbuf,sizeof(inbuf));
+     substdio_fdbuf(&ssread,subread,fd,inbuf,sizeof(inbuf));
      while ((r = substdio_get(&ssread,buf,sizeof(buf))) > 0)
        qmail_put(&qqt,buf,r);
      close(fd);
@@ -740,9 +814,20 @@
      qmail_fail(&qqt);
    else
     {
-     substdio_fdbuf(&ssread,read,fd,inbuf,sizeof(inbuf));
-     while ((r = substdio_get(&ssread,buf,sizeof(buf))) > 0)
+     unsigned int bytestogo;
+     unsigned int bytestoget;
+     bytestogo = bouncemaxbytes;
+     bytestoget = (bytestogo < sizeof(buf) && bouncemaxbytes != 0) ? bytestogo : sizeof(buf);
+     substdio_fdbuf(&ssread,subread,fd,inbuf,sizeof(inbuf));
+     while ((r = substdio_get(&ssread,buf,bytestoget)) > 0) {
        qmail_put(&qqt,buf,r);
+       bytestogo -= r;
+       if (bouncemaxbytes != 0 && bytestogo <= 0) {
+	 qmail_puts(&qqt,"\n\n--- End of message stripped.\n");
+	 break;
+       }
+       bytestoget = (bytestogo < sizeof(buf) && bouncemaxbytes != 0) ? bytestogo : sizeof(buf);
+     }
      close(fd);
      if (r == -1)
        qmail_fail(&qqt);
@@ -804,7 +889,7 @@
 void del_init()
 {
  int c;
- int i;
+ unsigned int i;
  for (c = 0;c < CHANNELS;++c)
   {
    flagspawnalive[c] = 1;
@@ -834,11 +919,11 @@
 }
 
 void del_start(j,mpos,recip)
-int j;
+unsigned int j;
 seek_pos mpos;
 char *recip;
 {
- int i;
+ unsigned int i;
  int c;
 
  c = jo[j].channel;
@@ -894,7 +979,7 @@
  int r;
  char ch;
  int i;
- int delnum;
+ unsigned int delnum;
  r = read(chanfdin[c],delbuf,sizeof(delbuf));
  if (r == -1) return;
  if (r == 0) { spawndied(c); return; }
@@ -906,50 +991,67 @@
      dline[c].len = REPORTMAX;
      /* qmail-lspawn and qmail-rspawn are responsible for keeping it short */
      /* but from a security point of view, we don't trust rspawn */
-   if (!ch && (dline[c].len > 1))
+   if (!ch && (dline[c].len > 2))
     {
-     delnum = (unsigned int) (unsigned char) dline[c].s[0];
+     delnum = (unsigned int)(unsigned char)dline[c].s[0];
+     delnum += (unsigned int)(unsigned char)dline[c].s[1] << 8;
+#if 0
+     /* A hup is sent as delivery num 0xBEEF = 48879 */
+     if (delnum == 0xBEEF) {
+       log1("sighup response: ");
+       logsafe(dline[c].s + 3);
+       log1("\n");
+     } else
+#endif
      if ((delnum < 0) || (delnum >= concurrency[c]) || !d[c][delnum].used)
        log1("warning: internal error: delivery report out of range\n");
      else
       {
        strnum3[fmt_ulong(strnum3,d[c][delnum].delid)] = 0;
-       if (dline[c].s[1] == 'Z')
+       if (dline[c].s[2] == 'Z')
 	 if (jo[d[c][delnum].j].flagdying)
 	  {
-	   dline[c].s[1] = 'D';
+	   dline[c].s[2] = 'D';
 	   --dline[c].len;
 	   while (!stralloc_cats(&dline[c],"I'm not going to try again; this message has been in the queue too long.\n")) nomem();
 	   while (!stralloc_0(&dline[c])) nomem();
 	  }
-       switch(dline[c].s[1])
+       switch(dline[c].s[2])
 	{
 	 case 'K':
 	   log3("delivery ",strnum3,": success: ");
-	   logsafe(dline[c].s + 2);
+	   logsafe(dline[c].s + 3);
 	   log1("\n");
 	   markdone(c,jo[d[c][delnum].j].id,d[c][delnum].mpos);
 	   --jo[d[c][delnum].j].numtodo;
 	   break;
 	 case 'Z':
 	   log3("delivery ",strnum3,": deferral: ");
-	   logsafe(dline[c].s + 2);
+	   logsafe(dline[c].s + 3);
 	   log1("\n");
 	   break;
 	 case 'D':
 	   log3("delivery ",strnum3,": failure: ");
-	   logsafe(dline[c].s + 2);
+	   logsafe(dline[c].s + 3);
 	   log1("\n");
-	   addbounce(jo[d[c][delnum].j].id,d[c][delnum].recip.s,dline[c].s + 2);
+	   addbounce(jo[d[c][delnum].j].id,d[c][delnum].recip.s,dline[c].s + 3);
 	   markdone(c,jo[d[c][delnum].j].id,d[c][delnum].mpos);
 	   --jo[d[c][delnum].j].numtodo;
 	   break;
+	 case 'L':
+	   log3("delivery ",strnum3,": log: ");
+	   logsafe(dline[c].s + 3);
+	   log1("\n");
+	   dline[c].len = 0;
+	   break;
 	 default:
 	   log3("delivery ",strnum3,": report mangled, will defer\n");
 	}
-       job_close(d[c][delnum].j);
-       d[c][delnum].used = 0; --concurrencyused[c];
-       del_status();
+       if (dline[c].s[2] != 'L') {
+	 job_close(d[c][delnum].j);
+	 d[c][delnum].used = 0; --concurrencyused[c];
+	 del_status();
+       }
       }
      dline[c].len = 0;
     }
@@ -1045,10 +1147,19 @@
 datetime_sec birth;
 int c;
 {
- int n;
+ unsigned int n;
 
  if (birth > recent) n = 0;
- else n = squareroot(recent - birth); /* no need to add fuzz to recent */
+ else {
+#ifdef notyet
+   /*
+    * add some fuzz to recent so that storms to a single host are
+    * dampened over the time.
+    */
+   recent += (int)random() % (((recent - birth) >> 2) + 1);
+#endif
+   n = squareroot(recent - birth);
+ }
  n += chanskip[c];
  return birth + n * n;
 }
@@ -1076,9 +1187,10 @@
    if (pass[c].fd == -1) goto trouble;
    if (!getinfo(&line,&birth,pe.id)) { close(pass[c].fd); goto trouble; }
    pass[c].id = pe.id;
-   substdio_fdbuf(&pass[c].ss,read,pass[c].fd,pass[c].buf,sizeof(pass[c].buf));
+   substdio_fdbuf(&pass[c].ss,subread,pass[c].fd,pass[c].buf,sizeof(pass[c].buf));
    pass[c].j = job_open(pe.id,c);
    jo[pass[c].j].retry = nextretry(birth,c);
+   /* XXX add fast timeouts for bounce double bounce here */
    jo[pass[c].j].flagdying = (recent > birth + lifetime);
    while (!stralloc_copy(&jo[pass[c].j].sender,&line)) nomem();
   }
@@ -1215,8 +1327,14 @@
 
 /* this file is too long ---------------------------------------------- TODO */
 
+#ifndef EXTERNAL_TODO
 datetime_sec nexttodorun;
+#ifndef BIGTODO
 DIR *tododir; /* if 0, have to opendir again */
+#else
+int flagtododir = 0; /* if 0, have to readsubdir_init again */
+readsubdir todosubdir;
+#endif
 stralloc todoline = {0};
 char todobuf[SUBSTDIO_INSIZE];
 char todobufinfo[512];
@@ -1224,7 +1342,11 @@
 
 void todo_init()
 {
+#ifndef BIGTODO
  tododir = 0;
+#else
+ flagtododir = 0;
+#endif
  nexttodorun = now();
  trigger_set();
 }
@@ -1236,7 +1358,11 @@
 {
  if (flagexitasap) return;
  trigger_selprep(nfds,rfds);
+#ifndef BIGTODO
  if (tododir) *wakeup = 0;
+#else
+ if (flagtododir) *wakeup = 0;
+#endif
  if (*wakeup > nexttodorun) *wakeup = nexttodorun;
 }
 
@@ -1253,8 +1379,10 @@
  char ch;
  int match;
  unsigned long id;
+#ifndef BIGTODO
  unsigned int len;
  direntry *d;
+#endif
  int c;
  unsigned long uid;
  unsigned long pid;
@@ -1265,21 +1393,31 @@
 
  if (flagexitasap) return;
 
+#ifndef BIGTODO
  if (!tododir)
+#else
+ if (!flagtododir)
+#endif
   {
    if (!trigger_pulled(rfds))
      if (recent < nexttodorun)
        return;
    trigger_set();
+#ifndef BIGTODO
    tododir = opendir("todo");
    if (!tododir)
     {
      pausedir("todo");
      return;
     }
+#else
+   readsubdir_init(&todosubdir, "todo", pausedir);
+   flagtododir = 1;
+#endif
    nexttodorun = recent + SLEEP_TODO;
   }
 
+#ifndef BIGTODO
  d = readdir(tododir);
  if (!d)
   {
@@ -1291,6 +1429,15 @@
  if (str_equal(d->d_name,"..")) return;
  len = scan_ulong(d->d_name,&id);
  if (!len || d->d_name[len]) return;
+#else
+ switch(readsubdir_next(&todosubdir, &id))
+  {
+   case 1: break;
+   case 0: flagtododir = 0;
+   default: return;
+  }
+#endif
+
 
  fnmake_todo(id);
 
@@ -1322,8 +1469,8 @@
 
  for (c = 0;c < CHANNELS;++c) flagchan[c] = 0;
 
- substdio_fdbuf(&ss,read,fd,todobuf,sizeof(todobuf));
- substdio_fdbuf(&ssinfo,write,fdinfo,todobufinfo,sizeof(todobufinfo));
+ substdio_fdbuf(&ss,subread,fd,todobuf,sizeof(todobuf));
+ substdio_fdbuf(&ssinfo,subwrite,fdinfo,todobufinfo,sizeof(todobufinfo));
 
  uid = 0;
  pid = 0;
@@ -1376,7 +1523,7 @@
 	 if (fdchan[c] == -1)
           { log3("warning: unable to create ",fn.s,"\n"); goto fail; }
 	 substdio_fdbuf(&sschan[c]
-	   ,write,fdchan[c],todobufchan[c],sizeof(todobufchan[c]));
+	   ,subwrite,fdchan[c],todobufchan[c],sizeof(todobufchan[c]));
 	 flagchan[c] = 1;
 	}
        if (substdio_bput(&sschan[c],rwline.s,rwline.len) == -1)
@@ -1438,10 +1585,156 @@
    if (fdchan[c] != -1) close(fdchan[c]);
 }
 
+#endif
+
+/* this file is too long ------------------------------------- EXTERNAL TODO */
+
+#ifdef EXTERNAL_TODO
+stralloc todoline = {0};
+char todobuf[2048];
+int todofdin;
+int todofdout;
+int flagtodoalive;
+
+void tododied() { log1("alert: oh no! lost qmail-todo connection! dying...\n");
+ flagexitasap = 1; flagtodoalive = 0; }
+
+void todo_init()
+{
+  todofdout = 7;
+  todofdin = 8;
+  flagtodoalive = 1;
+  /* sync with external todo */
+  if (write(todofdout, "S", 1) != 1) tododied();
+
+  return;
+}
+
+void todo_selprep(nfds,rfds,wakeup)
+int *nfds;
+fd_set *rfds;
+datetime_sec *wakeup;
+{
+  if (flagexitasap) {
+    if (flagtodoalive) {
+      write(todofdout, "X", 1);
+    }
+  }
+  if (flagtodoalive) {
+    FD_SET(todofdin,rfds);
+    if (*nfds <= todofdin)
+      *nfds = todofdin + 1;
+  }
+}
+
+void todo_del(char* s)
+{
+ int flagchan[CHANNELS];
+ struct prioq_elt pe;
+ unsigned long id;
+ unsigned int len;
+ int c;
+
+ for (c = 0;c < CHANNELS;++c) flagchan[c] = 0;
+ switch(*s++) {
+  case 'L':
+    flagchan[0] = 1;
+    break;
+  case 'R':
+    flagchan[1] = 1;
+    break;
+  case 'B':
+    flagchan[0] = 1;
+    flagchan[1] = 1;
+    break;
+  case 'X':
+    /*
+     * this is not an error but it is neither correct,
+     * sending messages with no recipients is plain stupid.
+     */
+    log1("warning: qmail-todo neither by land nor by sea...\n");
+    break;
+  default:
+    log1("warning: qmail-todo has a unknown feature or dialect.\n");
+    return;
+ }
+ 
+ len = scan_ulong(s,&id);
+ if (!len || s[len]) {
+  log1("warning: qmail-todo please don't muble.\n");
+  return;
+ }
+
+ pe.id = id; pe.dt = now();
+ for (c = 0;c < CHANNELS;++c)
+   if (flagchan[c])
+     while (!prioq_insert(&pqchan[c],&pe)) nomem();
+
+ for (c = 0;c < CHANNELS;++c) if (flagchan[c]) break;
+ if (c == CHANNELS)
+   while (!prioq_insert(&pqdone,&pe)) nomem();
+
+ return;
+}
+
+void todo_do(rfds)
+fd_set *rfds;
+{
+  int r;
+  char ch;
+  int i;
+  
+  if (!flagtodoalive) return;
+  if (!FD_ISSET(todofdin,rfds)) return;
+
+  r = read(todofdin,todobuf,sizeof(todobuf));
+  if (r == -1) return;
+  if (r == 0) {
+    if (flagexitasap)
+      flagtodoalive = 0;
+    else
+      tododied();
+    return;
+  }
+  for (i = 0;i < r;++i) {
+    ch = todobuf[i];
+    while (!stralloc_append(&todoline,&ch)) nomem();
+    if (todoline.len > REPORTMAX)
+      todoline.len = REPORTMAX;
+      /* qmail-todo is responsible for keeping it short */
+    if (!ch && (todoline.len > 1)) {
+      switch (todoline.s[0]) {
+	case 'D':
+	  if (flagexitasap) break;
+	  todo_del(todoline.s + 1);
+	  break;
+	case 'L':
+	  log1(todoline.s + 1);
+	  break;
+	case 'X':
+	  if (flagexitasap)
+	    flagtodoalive = 0;
+	  else
+	    tododied();
+	  break;
+	default:
+	  log1("warning: qmail-send unable to understand qmail-todo: report mangled\n");
+	  break;
+      }
+      todoline.len = 0;
+    }
+  }
+}
+
+#endif
 
 /* this file is too long ---------------------------------------------- MAIN */
 
-int getcontrols() { if (control_init() == -1) return 0;
+int getcontrols()
+{
+ struct stat st;
+
+ if (control_init() == -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;
@@ -1453,8 +1746,20 @@
  if (!stralloc_cats(&doublebounceto,"@")) return 0;
  if (!stralloc_cat(&doublebounceto,&doublebouncehost)) return 0;
  if (!stralloc_0(&doublebounceto)) return 0;
- if (control_readfile(&locals,"control/locals",1) != 1) return 0;
- if (!constmap_init(&maplocals,locals.s,locals.len,0)) return 0;
+ if (control_readint(&bouncemaxbytes,"control/bouncemaxbytes") == -1) return 0;
+ if (control_readrawfile(&custombouncetext,"control/custombouncetext") == -1) return 0;
+ if (!stralloc_0(&custombouncetext) ) return 0;
+
+ if (stat("control/locals.cdb", &st) == 0) {
+   if (!stralloc_copys(&localscdb, auto_qmail)) return 0;
+   if (!stralloc_cats(&localscdb, "/control/locals.cdb")) return 0;
+   if (!stralloc_0(&localscdb)) return 0;
+   if (!constmap_init(&maplocals,"",0,1)) return 0;
+ } else {
+   if (control_readfile(&locals,"control/locals",1) != 1) return 0;
+   if (!constmap_init(&maplocals,locals.s,locals.len,0)) return 0;
+ }
+
  switch(control_readfile(&percenthack,"control/percenthack",0))
   {
    case -1: return 0;
@@ -1471,23 +1776,45 @@
 
 stralloc newlocals = {0};
 stralloc newvdoms = {0};
+stralloc newcbtext = {0};
 
 void regetcontrols()
 {
+ struct stat st;
  int r;
 
- if (control_readfile(&newlocals,"control/locals",1) != 1)
-  { log1("alert: unable to reread control/locals\n"); return; }
+ if (control_readint(&bouncemaxbytes,"control/bouncemaxbytes") == -1)
+  { log1("alert: unable to reread control/bouncemaxbytes\n"); return; }
+ 
+ if (control_readrawfile(&newcbtext,"control/custombouncetext") == -1)
+  { log1("alert: unable to reread control/custombouncetext\n"); return; }
+ while (!stralloc_0(&newcbtext)) nomem();
+ while (!stralloc_copy(&custombouncetext,&newcbtext)) nomem();
+
+ if (stat("control/locals.cdb", &st) == 0) {
+   while (!stralloc_copys(&localscdb, auto_qmail)) nomem();
+   while (!stralloc_cats(&localscdb, "/control/locals.cdb")) nomem();
+   while  (!stralloc_0(&localscdb)) nomem();
+   
+   constmap_free(&maplocals);
+   while (!constmap_init(&maplocals,"",0,1)) nomem();
+ } else {
+   if (control_readfile(&newlocals,"control/locals",1) != 1)
+    { log1("alert: unable to reread control/locals\n"); return; }
+   
+   while (!stralloc_copys(&localscdb, "")) nomem();
+   
+   constmap_free(&maplocals);
+   while (!stralloc_copy(&locals,&newlocals)) nomem();
+   while (!constmap_init(&maplocals,locals.s,locals.len,0)) nomem();
+ }
+ 
  r = control_readfile(&newvdoms,"control/virtualdomains",0);
  if (r == -1)
   { log1("alert: unable to reread control/virtualdomains\n"); return; }
 
- constmap_free(&maplocals);
  constmap_free(&mapvdoms);
 
- while (!stralloc_copy(&locals,&newlocals)) nomem();
- while (!constmap_init(&maplocals,locals.s,locals.len,0)) nomem();
-
  if (r)
   {
    while (!stralloc_copy(&vdoms,&newvdoms)) nomem();
@@ -1504,15 +1831,22 @@
    log1("alert: unable to reread controls: unable to switch to home directory\n");
    return;
   }
+#ifdef EXTERNAL_TODO
+ write(todofdout, "H", 1);
+#endif
+ comm_hup(0); /* send hup to qmail-lspawn */
  regetcontrols();
  while (chdir("queue") == -1)
   {
    log1("alert: unable to switch back to queue directory; HELP! sleeping...\n");
    sleep(10);
   }
+#ifdef notyet
+ srandom(now());
+#endif
 }
 
-void main()
+int main()
 {
  int fd;
  datetime_sec wakeup;
@@ -1528,6 +1862,9 @@
   { log1("alert: cannot start: unable to read controls\n"); _exit(111); }
  if (chdir("queue") == -1)
   { log1("alert: cannot start: unable to switch to queue directory\n"); _exit(111); }
+#ifdef notyet
+ srandom(now() + (getpid() << 16));
+#endif
  sig_pipeignore();
  sig_termcatch(sigterm);
  sig_alarmcatch(sigalrm);
@@ -1544,15 +1881,22 @@
  numjobs = 0;
  for (c = 0;c < CHANNELS;++c)
   {
-   char ch;
-   int u;
+   char ch, ch1;
+   unsigned int u;
    int r;
    do
      r = read(chanfdin[c],&ch,1);
    while ((r == -1) && (errno == error_intr));
    if (r < 1)
+    { log1("alert: cannot start qmail-lspawn or it had an error! "
+	"Check if ~control/ldapserver exists.\n"); _exit(111); }
+   do
+     r = read(chanfdin[c],&ch1,1);
+   while ((r == -1) && (errno == error_intr));
+   if (r < 1)
     { log1("alert: cannot start: hath the daemon spawn no fire?\n"); _exit(111); }
    u = (unsigned int) (unsigned char) ch;
+   u += (unsigned int) ((unsigned char) ch1) << 8;
    if (concurrency[c] > u) concurrency[c] = u;
    numjobs += concurrency[c];
   }
@@ -1568,8 +1912,12 @@
  todo_init();
  cleanup_init();
 
+#ifdef EXTERNAL_TODO
+ while (!flagexitasap || !del_canexit() || flagtodoalive)
+#else
  while (!flagexitasap || !del_canexit())
-  {
+#endif
+ {
    recent = now();
 
    if (flagrunasap) { flagrunasap = 0; pqrun(); }
@@ -1608,5 +1956,5 @@
   }
  pqfinish();
  log1("status: exiting\n");
- _exit(0);
+ return 0;
 }
diff -ruN qmail-1.03-orig/qmail.sh qmail-1.03-ldap-20060201-orig/qmail.sh
--- qmail-1.03-orig/qmail.sh	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/qmail.sh	2006-02-25 11:00:55.000000000 +0100
@@ -0,0 +1,20 @@
+#!/bin/sh
+exec 2>&1
+#
+# qmail-send and friends
+#
+QMAIL="%QMAIL%"
+if [ -e $QMAIL/control/defaultdelivery ]; then
+	ALIASEMPTY=`cat $QMAIL/control/defaultdelivery 2> /dev/null`
+else
+	ALIASEMPTY=`cat $QMAIL/control/aliasempty 2> /dev/null`
+fi
+ALIASEMPTY=${ALIASEMPTY:="./Maildir/"}
+
+PATH="$QMAIL/bin:$PATH"
+
+# limit to prevent memory hogs
+ulimit -c 204800 
+
+exec envdir ./env qmail-start "$ALIASEMPTY"
+
diff -ruN qmail-1.03-orig/qmail-showctl.c qmail-1.03-ldap-20060201-orig/qmail-showctl.c
--- qmail-1.03-orig/qmail-showctl.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/qmail-showctl.c	2006-02-25 11:00:55.000000000 +0100
@@ -1,5 +1,6 @@
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <unistd.h>
 #include "substdio.h"
 #include "subfd.h"
 #include "exit.h"
@@ -15,10 +16,14 @@
 #include "auto_patrn.h"
 #include "auto_spawn.h"
 #include "auto_split.h"
+#include "byte.h"
 
 stralloc me = {0};
 int meok;
 
+stralloc ldapserver = {0};
+int ldapok;
+
 stralloc line = {0};
 char num[FMT_ULONG];
 
@@ -68,6 +73,36 @@
   }
 }
 
+void do_ulong(fn,def,pre,post)
+char *fn;
+char *def;
+char *pre;
+char *post;
+{
+  unsigned long i;
+  substdio_puts(subfdout,"\n");
+  substdio_puts(subfdout,fn);
+  substdio_puts(subfdout,": ");
+  switch(control_readulong(&i,fn)) {
+    case 0:
+      substdio_puts(subfdout,"(Default.) ");
+      substdio_puts(subfdout,pre);
+      substdio_puts(subfdout,def);
+      substdio_puts(subfdout,post);
+      substdio_puts(subfdout,".\n");
+      break;
+    case 1:
+      substdio_puts(subfdout,pre);
+      substdio_put(subfdout,num,fmt_ulong(num,i));
+      substdio_puts(subfdout,post);
+      substdio_puts(subfdout,".\n");
+      break;
+    default:
+      substdio_puts(subfdout,"Oops! Trouble reading this file.\n");
+      break;
+  }
+}
+
 void do_str(fn,flagme,def,pre)
 char *fn;
 int flagme;
@@ -106,13 +141,13 @@
 char *pre;
 char *post;
 {
-  int i;
-  int j;
+  unsigned int i;
+  unsigned int j;
 
   substdio_puts(subfdout,"\n");
   substdio_puts(subfdout,fn);
   substdio_puts(subfdout,": ");
-  switch(control_readfile(&line,fn)) {
+  switch(control_readfile(&line,fn, 0)) {
     case 0:
       substdio_puts(subfdout,"(Default.) ");
       substdio_puts(subfdout,def);
@@ -136,7 +171,7 @@
   }
 }
 
-void main()
+int main()
 {
   DIR *dir;
   direntry *d;
@@ -152,39 +187,39 @@
   substdio_puts(subfdout,".\n");
 
   substdio_puts(subfdout,"paternalism (in decimal): ");
-  substdio_put(subfdout,num,fmt_ulong(num,(unsigned long) auto_patrn));
+  substdio_put(subfdout,num,fmt_uint(num, auto_patrn));
   substdio_puts(subfdout,".\n");
 
   substdio_puts(subfdout,"silent concurrency limit: ");
-  substdio_put(subfdout,num,fmt_ulong(num,(unsigned long) auto_spawn));
+  substdio_put(subfdout,num,fmt_uint(num, auto_spawn));
   substdio_puts(subfdout,".\n");
 
   substdio_puts(subfdout,"subdirectory split: ");
-  substdio_put(subfdout,num,fmt_ulong(num,(unsigned long) auto_split));
+  substdio_put(subfdout,num,fmt_uint(num, auto_split));
   substdio_puts(subfdout,".\n");
 
   substdio_puts(subfdout,"user ids: ");
-  substdio_put(subfdout,num,fmt_ulong(num,(unsigned long) auto_uida));
+  substdio_put(subfdout,num,fmt_uint(num, auto_uida));
   substdio_puts(subfdout,", ");
-  substdio_put(subfdout,num,fmt_ulong(num,(unsigned long) auto_uidd));
+  substdio_put(subfdout,num,fmt_uint(num, auto_uidd));
   substdio_puts(subfdout,", ");
-  substdio_put(subfdout,num,fmt_ulong(num,(unsigned long) auto_uidl));
+  substdio_put(subfdout,num,fmt_uint(num, auto_uidl));
   substdio_puts(subfdout,", ");
-  substdio_put(subfdout,num,fmt_ulong(num,(unsigned long) auto_uido));
+  substdio_put(subfdout,num,fmt_uint(num, auto_uido));
   substdio_puts(subfdout,", ");
-  substdio_put(subfdout,num,fmt_ulong(num,(unsigned long) auto_uidp));
+  substdio_put(subfdout,num,fmt_uint(num, auto_uidp));
   substdio_puts(subfdout,", ");
-  substdio_put(subfdout,num,fmt_ulong(num,(unsigned long) auto_uidq));
+  substdio_put(subfdout,num,fmt_uint(num, auto_uidq));
   substdio_puts(subfdout,", ");
-  substdio_put(subfdout,num,fmt_ulong(num,(unsigned long) auto_uidr));
+  substdio_put(subfdout,num,fmt_uint(num, auto_uidr));
   substdio_puts(subfdout,", ");
-  substdio_put(subfdout,num,fmt_ulong(num,(unsigned long) auto_uids));
+  substdio_put(subfdout,num,fmt_uint(num, auto_uids));
   substdio_puts(subfdout,".\n");
 
   substdio_puts(subfdout,"group ids: ");
-  substdio_put(subfdout,num,fmt_ulong(num,(unsigned long) auto_gidn));
+  substdio_put(subfdout,num,fmt_uint(num, auto_gidn));
   substdio_puts(subfdout,", ");
-  substdio_put(subfdout,num,fmt_ulong(num,(unsigned long) auto_gidq));
+  substdio_put(subfdout,num,fmt_uint(num, auto_gidq));
   substdio_puts(subfdout,".\n");
 
   if (chdir(auto_qmail) == -1) {
@@ -213,27 +248,60 @@
     substdio_flush(subfdout);
     _exit(111);
   }
+  ldapok = control_readfile(&ldapserver,"ldapserver",0);
+  byte_repl(ldapserver.s, ldapserver.len, '\0', ' ');
+  if (ldapok == -1) {
+    substdio_puts(subfdout,"Oops! Trouble reading control/ldapserver.");
+    substdio_flush(subfdout);
+    _exit(111);
+  }
+  substdio_puts(subfdout,"me: My name is ");
+  substdio_put(subfdout, me.s, me.len);
+  substdio_puts(subfdout,"\nldapserver: My ldap server is ");
+  substdio_put(subfdout, ldapserver.s, ldapserver.len);
+  substdio_puts(subfdout,"\n\n");
+
 
   do_lst("badmailfrom","Any MAIL FROM is allowed.",""," not accepted in MAIL FROM.");
+  do_lst("badmailfrom-unknown","Any MAIL FROM from hosts without PTR is allowed.","",
+	 " not accepted in MAIL FROM from host without PTR.");
+  do_lst("badrcptto","Any RCPT TO is allowed.",""," not accepted in RCPT TO");
+  if (stat("bigbrother",&stmrh) == 0)
+    do_lst("bigbrother","No mail addresses are observed.","Observed mail address: ","");
   do_str("bouncefrom",0,"MAILER-DAEMON","Bounce user name is ");
   do_str("bouncehost",1,"bouncehost","Bounce host name is ");
+  do_ulong("bouncemaxbytes","0","Bounce data limit is "," bytes");
   do_int("concurrencylocal","10","Local concurrency is ","");
   do_int("concurrencyremote","20","Remote concurrency is ","");
-  do_int("databytes","0","SMTP DATA limit is "," bytes");
+  do_lst("custombouncetext","No custombouncetext.","","");
+  do_ulong("databytes","0","SMTP DATA limit is "," bytes");
   do_str("defaultdomain",1,"defaultdomain","Default domain name is ");
   do_str("defaulthost",1,"defaulthost","Default host name is ");
+  do_str("dirmaker",0,"not defined","Program to create homedirs ");
   do_str("doublebouncehost",1,"doublebouncehost","2B recipient host: ");
   do_str("doublebounceto",0,"postmaster","2B recipient user: ");
   do_str("envnoathost",1,"envnoathost","Presumed domain name is ");
+  do_lst("goodmailaddr","No good mail addresses.",""," is allowed in any case.");
   do_str("helohost",1,"helohost","SMTP client HELO host name is ");
   do_str("idhost",1,"idhost","Message-ID host name is ");
   do_str("localiphost",1,"localiphost","Local IP address becomes ");
   do_lst("locals","Messages for me are delivered locally.","Messages for "," are delivered locally.");
   do_str("me",0,"undefined! Uh-oh","My name is ");
+  do_str("outgoingip",0,"0.0.0.0","Bind qmail-remote to ");
+  do_ulong("pbscachesize","1048576","PBS cachesize is "," bytes");
+  do_lst("pbsenv","No environment variables will be passed.","Environment Variable: ","");
+  do_str("pbsip",0,"0.0.0.0","Bind PBS daemon to ");
+  do_int("pbsport","2821","PBS deamon listens on port ","");
+  do_str("pbssecret",0,"undefined! Uh-oh","PBS shared secret is ");
+  do_lst("pbsservers","No PBS servers.","PBS server ",".");
+  do_int("pbstimeout","600","PBS entries will be valid for "," seconds");  
   do_lst("percenthack","The percent hack is not allowed.","The percent hack is allowed for user%host@",".");
   do_str("plusdomain",1,"plusdomain","Plus domain name is ");
+  do_str("qmqpcip",0,"0.0.0.0","Bind qmail-qmqpc to ");
   do_lst("qmqpservers","No QMQP servers.","QMQP server: ",".");
   do_int("queuelifetime","604800","Message lifetime in the queue is "," seconds");
+  do_lst("quotawarning","No quotawarning.","","");
+  do_lst("rbllist","No RBL listed.","RBL to check: ",".");
 
   if (do_lst("rcpthosts","SMTP clients may send messages to any recipient.","SMTP clients may send messages to recipients at ","."))
     do_lst("morercpthosts","No effect.","SMTP clients may send messages to recipients at ",".");
@@ -255,6 +323,7 @@
       else
         substdio_puts(subfdout,"Modified recently enough; hopefully up to date.\n");
 
+  do_lst("relaymailfrom","Relaymailfrom not enabled.","Envelope senders allowed to relay: ",".");
   do_str("smtpgreeting",1,"smtpgreeting","SMTP greeting: 220 ");
   do_lst("smtproutes","No artificial SMTP routes.","SMTP route: ","");
   do_int("timeoutconnect","60","SMTP client connection timeout is "," seconds");
@@ -262,45 +331,111 @@
   do_int("timeoutsmtpd","1200","SMTP server data timeout is "," seconds");
   do_lst("virtualdomains","No virtual domains.","Virtual domain: ","");
 
-  while (d = readdir(dir)) {
+
+  substdio_puts(subfdout,"\n\n\nNow the qmail-ldap specific files:\n");
+  do_str("ldapbasedn",0,"NULL","LDAP basedn: ");
+  do_lst("ldapserver","undefined! Uh-oh","","");
+  do_str("ldaplogin",0,"NULL","LDAP login: ");
+  do_str("ldappassword",0,"NULL","LDAP password: ");
+  do_int("ldaptimeout","30","LDAP server timeout is "," seconds");
+  do_str("ldapuid",0,"not defined","Default UID is ");
+  do_str("ldapgid",0,"not defined","Default GID is ");
+  do_str("ldapobjectclass",0,"not defined","The objectclass to limit ldap filter is ");
+  do_str("ldapmessagestore",0,"not defined","Prefix for non absolute paths is ");
+  do_str("ldapdefaultdotmode",0,"ldaponly","Default dot mode for ldap users is ");
+  do_ulong("defaultquotasize","0","Mailbox size quota is "," bytes (0 is unlimited)");
+  do_ulong("defaultquotacount","0","Mailbox count quota is "," messages (0 is unlimited)");
+  do_int("ldaplocaldelivery","1","Local passwd lookup is "," (1 = on, 0 = off)");
+  do_int("ldaprebind","0","Ldap rebinding is "," (1 = on, 0 = off)");
+  do_int("ldapcluster","0","Clustering is "," (1 = on, 0 = off)");
+  do_lst("ldapclusterhosts","Messages for me are not redirected.",
+	 "Messages for "," are not redirected.");
+
+  substdio_puts(subfdout,"\n");
+  
+  
+  while ((d = readdir(dir))) {
     if (str_equal(d->d_name,".")) continue;
     if (str_equal(d->d_name,"..")) continue;
-    if (str_equal(d->d_name,"bouncefrom")) continue;
-    if (str_equal(d->d_name,"bouncehost")) continue;
     if (str_equal(d->d_name,"badmailfrom")) continue;
+    if (str_equal(d->d_name,"badmailfrom-unknown")) continue;
+    if (str_equal(d->d_name,"badrcptto")) continue;
+    if (str_equal(d->d_name,"bigbrother")) continue;
     if (str_equal(d->d_name,"bouncefrom")) continue;
     if (str_equal(d->d_name,"bouncehost")) continue;
+    if (str_equal(d->d_name,"bouncemaxbytes")) continue;
     if (str_equal(d->d_name,"concurrencylocal")) continue;
     if (str_equal(d->d_name,"concurrencyremote")) continue;
+    if (str_equal(d->d_name,"custombouncetext")) continue;
     if (str_equal(d->d_name,"databytes")) continue;
     if (str_equal(d->d_name,"defaultdomain")) continue;
     if (str_equal(d->d_name,"defaulthost")) continue;
+    if (str_equal(d->d_name,"defaultquotacount")) continue;
+    if (str_equal(d->d_name,"defaultquotasize")) continue;
+    if (str_equal(d->d_name,"dirmaker")) continue;
     if (str_equal(d->d_name,"doublebouncehost")) continue;
     if (str_equal(d->d_name,"doublebounceto")) continue;
     if (str_equal(d->d_name,"envnoathost")) continue;
     if (str_equal(d->d_name,"helohost")) continue;
+    if (str_equal(d->d_name,"goodmailaddr")) continue;
     if (str_equal(d->d_name,"idhost")) continue;
+    if (str_equal(d->d_name,"ldapbasedn")) continue;
+    if (str_equal(d->d_name,"ldapcluster")) continue;
+    if (str_equal(d->d_name,"ldapclusterhosts")) continue;
+    if (str_equal(d->d_name,"ldapdefaultdotmode")) continue;
+    if (str_equal(d->d_name,"ldapgid")) continue;
+    if (str_equal(d->d_name,"ldaplocaldelivery")) continue;
+    if (str_equal(d->d_name,"ldaplogin")) continue;
+    if (str_equal(d->d_name,"ldapmessagestore")) continue;
+    if (str_equal(d->d_name,"ldapobjectclass")) continue;
+    if (str_equal(d->d_name,"ldappassword")) continue;
+    if (str_equal(d->d_name,"ldaprebind")) continue;
+    if (str_equal(d->d_name,"ldapserver")) continue;
+    if (str_equal(d->d_name,"ldaptimeout")) continue;
+    if (str_equal(d->d_name,"ldapuid")) continue;
     if (str_equal(d->d_name,"localiphost")) continue;
     if (str_equal(d->d_name,"locals")) continue;
     if (str_equal(d->d_name,"me")) continue;
     if (str_equal(d->d_name,"morercpthosts")) continue;
     if (str_equal(d->d_name,"morercpthosts.cdb")) continue;
+    if (str_equal(d->d_name,"outgoingip")) continue;
+    if (str_equal(d->d_name,"pbscachesize")) continue;
+    if (str_equal(d->d_name,"pbsenv")) continue;
+    if (str_equal(d->d_name,"pbsip")) continue;
+    if (str_equal(d->d_name,"pbsport")) continue;
+    if (str_equal(d->d_name,"pbssecret")) continue;
+    if (str_equal(d->d_name,"pbsservers")) continue;
+    if (str_equal(d->d_name,"pbstimeout")) continue;
     if (str_equal(d->d_name,"percenthack")) continue;
     if (str_equal(d->d_name,"plusdomain")) continue;
+    if (str_equal(d->d_name,"qmqpcip")) continue;
     if (str_equal(d->d_name,"qmqpservers")) continue;
     if (str_equal(d->d_name,"queuelifetime")) continue;
+    if (str_equal(d->d_name,"quotawarning")) continue;
+    if (str_equal(d->d_name,"rbllist")) continue;
     if (str_equal(d->d_name,"rcpthosts")) continue;
+    if (str_equal(d->d_name,"relaymailfrom")) continue;
     if (str_equal(d->d_name,"smtpgreeting")) continue;
     if (str_equal(d->d_name,"smtproutes")) continue;
     if (str_equal(d->d_name,"timeoutconnect")) continue;
     if (str_equal(d->d_name,"timeoutremote")) continue;
     if (str_equal(d->d_name,"timeoutsmtpd")) continue;
     if (str_equal(d->d_name,"virtualdomains")) continue;
-    substdio_puts(subfdout,"\n");
+    if (str_equal(d->d_name,"ldapusername") ||
+	str_equal(d->d_name,"ldappasswdappend") ||
+	str_equal(d->d_name,"ldapdefaultquota") ||
+	str_equal(d->d_name,"rblonlyheader") ||
+	str_equal(d->d_name,"maxrcptcount") ||
+	str_equal(d->d_name,"tarpitdelay") ||
+	str_equal(d->d_name,"tarpitcount")) {
+        substdio_puts(subfdout,d->d_name);
+        substdio_puts(subfdout,": No longer used, please remove.\n");
+        continue;
+    }
     substdio_puts(subfdout,d->d_name);
     substdio_puts(subfdout,": I have no idea what this file does.\n");
   }
 
   substdio_flush(subfdout);
-  _exit(0);
+  return 0;
 }
diff -ruN qmail-1.03-orig/qmail-smtpd.c qmail-1.03-ldap-20060201-orig/qmail-smtpd.c
--- qmail-1.03-orig/qmail-smtpd.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/qmail-smtpd.c	2006-02-25 11:00:55.000000000 +0100
@@ -1,9 +1,12 @@
+#include <unistd.h>
 #include "sig.h"
 #include "readwrite.h"
 #include "stralloc.h"
 #include "substdio.h"
+#include "subfd.h"
 #include "alloc.h"
 #include "auto_qmail.h"
+#include "auto_break.h"
 #include "control.h"
 #include "received.h"
 #include "constmap.h"
@@ -20,72 +23,235 @@
 #include "now.h"
 #include "exit.h"
 #include "rcpthosts.h"
+#include "rbl.h"
 #include "timeoutread.h"
 #include "timeoutwrite.h"
 #include "commands.h"
+#include "dns.h"
+#include "smtpcall.h"
+#include "qmail-ldap.h"
+#include "limit.h"
+#ifdef SMTPEXECCHECK
+#include "execcheck.h"
+#endif
+#ifdef TLS_SMTPD
+#include <openssl/ssl.h>
+SSL *ssl = NULL;
+#endif
+#ifdef DATA_COMPRESS
+/* zlib needs to be after openssl includes or build will fail */
+#include <zlib.h>
+#endif
 
 #define MAXHOPS 100
-unsigned int databytes = 0;
+#define MAXLINELEN 10000
+unsigned long databytes = 0;
 int timeout = 1200;
 
-int safewrite(fd,buf,len) int fd; char *buf; int len;
+#ifdef TLS_SMTPD
+int flagtimedout = 0;
+void sigalrm()
+{
+ flagtimedout = 1;
+}
+int ssl_timeoutread(int tout, int fd, void *buf, int n)
+{
+ int r; int saveerrno;
+ if (flagtimedout) { errno = error_timeout; return -1; }
+ alarm(tout);
+ r = SSL_read(ssl,buf,n);
+ saveerrno = errno;
+ alarm(0);
+ if (flagtimedout) { errno = error_timeout; return -1; }
+ errno = saveerrno;
+ return r;
+}
+int ssl_timeoutwrite(int tout, int fd, const void *buf, int n)
+{
+ int r; int saveerrno;
+ if (flagtimedout) { errno = error_timeout; return -1; }
+ alarm(tout);
+ r = SSL_write(ssl,buf,n);
+ saveerrno = errno;
+ alarm(0);
+ if (flagtimedout) { errno = error_timeout; return -1; }
+ errno = saveerrno;
+ return r;
+}
+#endif
+
+void die_write(void);
+
+int safewrite(int fd, void *buf, int len)
 {
   int r;
+#ifdef TLS_SMTPD
+  if (ssl)
+    r = ssl_timeoutwrite(timeout,fd,buf,len);
+  else
+#endif
   r = timeoutwrite(timeout,fd,buf,len);
-  if (r <= 0) _exit(1);
+  if (r <= 0) die_write();
   return r;
 }
 
 char ssoutbuf[512];
 substdio ssout = SUBSTDIO_FDBUF(safewrite,1,ssoutbuf,sizeof ssoutbuf);
 
-void flush() { substdio_flush(&ssout); }
-void out(s) char *s; { substdio_puts(&ssout,s); }
+void flush(void) { substdio_flush(&ssout); }
+void out(const char *s) { substdio_puts(&ssout,s); }
+
+/* level 0 = no logging
+         1 = fatal errors
+         2 = connection setup and warnings
+         3 = verbose */
+
+int loglevel = 0;
+
+void logpid(int level)
+{
+  char pidstring[FMT_ULONG];
+  if (level > loglevel) return;
+  substdio_puts(subfderr,"qmail-smtpd ");
+  pidstring[fmt_uint(pidstring, getpid())] = 0;
+  substdio_puts(subfderr,pidstring);
+  substdio_puts(subfderr,": ");
+}
+
+void logline(int level, const char *string)
+{
+  if (level > loglevel) return;
+  logpid(level);
+  substdio_puts(subfderr,string);
+  substdio_puts(subfderr,"\n");
+  substdio_flush(subfderr);
+}
+
+void logline2(int level, const char *s1, const char *s2)
+{
+  if (level > loglevel) return;
+  logpid(level);
+  substdio_puts(subfderr,s1);
+  substdio_puts(subfderr,s2);
+  substdio_puts(subfderr,"\n");
+  substdio_flush(subfderr);
+}
+
+void logstring(int level, const char *string)
+{
+  if (level > loglevel) return;
+  substdio_puts(subfderr,string);
+}
+
+void logflush(int level)
+{
+  if (level > loglevel) return;
+  substdio_puts(subfderr,"\n");
+  substdio_flush(subfderr);
+}
 
-void die_read() { _exit(1); }
-void die_alarm() { out("451 timeout (#4.4.2)\r\n"); flush(); _exit(1); }
-void die_nomem() { out("421 out of memory (#4.3.0)\r\n"); flush(); _exit(1); }
-void die_control() { out("421 unable to read controls (#4.3.0)\r\n"); flush(); _exit(1); }
-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_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"); }
-void err_wantmail() { out("503 MAIL first (#5.5.1)\r\n"); }
-void err_wantrcpt() { out("503 RCPT first (#5.5.1)\r\n"); }
-void err_noop() { out("250 ok\r\n"); }
-void err_vrfy() { out("252 send some mail, i'll try my best\r\n"); }
-void err_qqt() { out("451 qqt failure (#4.3.0)\r\n"); }
+void cleanup(void);
 
+const char *remoteip;
 
+void die_read(void) { logline(1,"read error or connection closed"); cleanup(); _exit(1); }
+void die_write(void) { logline(1,"write error, connection closed"); cleanup(); _exit(1); }
+void die_alarm(void) { out("451 timeout (#4.4.2)\r\n"); logline(1,"connection timed out, closing connection"); flush(); cleanup(); _exit(1); }
+void die_nomem(void) { out("421 out of memory (#4.3.0)\r\n"); logline(1,"out of memory, closing connection"); flush(); cleanup(); _exit(1); }
+void die_control(void) { out("421 unable to read controls (#4.3.0)\r\n"); logline(1,"unable to read controls, closing connection"); flush(); _exit(1); }
+void die_ipme(void) { out("421 unable to figure out my IP addresses (#4.3.0)\r\n"); logline(1,"unable to figure out my IP address, closing connection"); flush(); _exit(1); }
+void straynewline(void) { out("451 See http://pobox.com/~djb/docs/smtplf.html.\r\n"); logline(1,"stray new line detected, closing connection"); flush(); _exit(1); }
+void oversizedline(void) { out("500 Text line too long."); logline(1,"Oversized line in data part, closing connection"); flush(); _exit(1); }
+void err_qqt(void) { out("451 qqt failure (#4.3.0)\r\n"); }
+void err_dns(void) { out("421 DNS temporary failure at return MX check, try again later (#4.3.0)\r\n"); }
+void err_soft(char *s) { out("451 "); out(s); out("\r\n"); logline2(1,"temporary verify error: ", s); }
+void err_bmf(void) { out("553 sorry, your mail was administratively denied. (#5.7.1)\r\n"); }
+void err_bmfunknown(void) { out("553 sorry, your mail from a host ["); out(remoteip); out("] without valid reverse DNS was administratively denied (#5.7.1)\r\n"); }
+void err_maxrcpt(void) { out("553 sorry, too many recipients (#5.7.1)\r\n"); }
+void err_nogateway(void) { out("553 sorry, relaying denied from your location ["); out(remoteip); out("] (#5.7.1)\r\n"); }
+void err_badbounce(void) { out("550 sorry, I don't accept bounce messages with more than one recipient. Go read RFC2821. (#5.7.1)\r\n"); }
+void err_unimpl(const char *arg) { out("502 unimplemented (#5.5.1)\r\n"); logline2(3,"unrecognized command: ",arg); }
+void err_size(void) { out("552 sorry, that message size exceeds my databytes limit (#5.3.4)\r\n"); logline(3,"message denied because: 'SMTP SIZE' too big"); }
+void err_syntax(void) { out("555 syntax error (#5.5.4)\r\n"); }
+void err_relay(void) { out("553 sorry, we don't relay for ["); out(remoteip); out("] (#5.7.1)\r\n"); }
+void err_wantmail(void) { out("503 MAIL first (#5.5.1)\r\n"); logline(4,"'mail from' first"); }
+void err_wantrcpt(void) { out("503 RCPT first (#5.5.1)\r\n"); logline(4,"'rcpt to' first"); }
+
+void err_noop(char *arg) { out("250 ok\r\n"); logline(4,"'noop'"); }
+void err_vrfy(char *arg) { out("252 send some mail, i'll try my best\r\n"); logline2(4,"vrfy for: ",arg); }
+
+void err_rbl(char *arg) { out("553 sorry, your mailserver ["); out(remoteip); out("] is rejected by "); out(arg); out("\r\n"); }
+void err_deny(void) { out("553 sorry, mail from your location ["); out(remoteip); out("] is administratively denied (#5.7.1)\r\n"); }
+void err_badrcptto(void) { out("553 sorry, mail to that recipient is not accepted (#5.7.1)\r\n"); }
+void err_554msg(const char *arg)
+{
+	out("554 "); out(arg); out("\r\n");
+	logline2(3,"message denied: ",arg);
+}
+
+
+stralloc me = {0};
 stralloc greeting = {0};
+stralloc cookie = {0};
 
-void smtp_greet(code) char *code;
+void smtp_greet(const char *code)
 {
   substdio_puts(&ssout,code);
+  substdio_puts(&ssout,me.s);
+  substdio_puts(&ssout," ESMTP ");
   substdio_put(&ssout,greeting.s,greeting.len);
+  if (cookie.len > 0) {
+    substdio_puts(&ssout," ");
+    substdio_put(&ssout,cookie.s,cookie.len);
+  }
+  out("\r\n");
 }
-void smtp_help()
+void smtp_line(const char *code)
 {
-  out("214 qmail home page: http://pobox.com/~djb/qmail.html\r\n");
+  substdio_puts(&ssout,code);
+  substdio_puts(&ssout,me.s);
+  substdio_puts(&ssout," ");
+  substdio_put(&ssout,greeting.s,greeting.len);
+  out("\r\n");
+}
+void smtp_help(char *arg)
+{
+  out("214-qmail home page: http://pobox.com/~djb/qmail.html\r\n");
+  out("214 qmail-ldap patch home page: http://www.nrg4u.com\r\n");
+  logline(4,"help requested");
 }
-void smtp_quit()
+void smtp_quit(char *arg)
 {
-  smtp_greet("221 "); out("\r\n"); flush(); _exit(0);
+  if (!stralloc_copys(&greeting,"Goodbye."))
+    die_nomem();
+  smtp_line("221 ");
+  logline(4,"quit, closing connection");
+  flush();
+  cleanup();
+  _exit(0);
+}
+void err_quit(void)
+{
+  logline(4,"force closing connection");
+  flush();
+  cleanup();
+  _exit(0);
 }
 
-char *remoteip;
-char *remotehost;
-char *remoteinfo;
-char *local;
-char *relayclient;
+const char *remotehost;
+const char *remoteinfo;
+const char *local;
+const char *relayclient;
+const char *relayok;
+const char *greeting550;
+const char *greeting421;
+int  spamflag = 0;
 
 stralloc helohost = {0};
 char *fakehelo; /* pointer into helohost, or 0 */
 
-void dohelo(arg) char *arg; {
+void dohelo(const char *arg)
+{
   if (!stralloc_copys(&helohost,arg)) die_nomem(); 
   if (!stralloc_0(&helohost)) die_nomem(); 
   fakehelo = case_diffs(remotehost,helohost.s) ? helohost.s : 0;
@@ -96,51 +262,224 @@
 int bmfok = 0;
 stralloc bmf = {0};
 struct constmap mapbmf;
+int bmfunknownok = 0;
+stralloc bmfunknown = {0};
+struct constmap mapbmfunknown;
+int rmfok = 0;
+stralloc rmf = {0};
+struct constmap maprmf;
+int brtok = 0;
+stralloc brt = {0};
+struct constmap mapbadrcptto;
+int gmaok = 0;
+stralloc gma = {0};
+struct constmap mapgma;
+int rblok = 0;
+int rbloh = 0;
+int errdisconnect = 0;
+int nobounce = 0;
+int sanitycheck = 0;
+int returnmxcheck = 0;
+int blockrelayprobe = 0;
+unsigned int tarpitcount = 0;
+unsigned int tarpitdelay = 5;
+unsigned int maxrcptcount = 0;
+int sendercheck = 0;
+int rcptcheck = 0;
+int ldapsoftok = 0;
+int flagauth = 0;
+int needauth = 0;
+int needssl = 0;
+int flagauthok = 0;
+const char *authprepend;
+#ifdef TLS_SMTPD
+stralloc sslcert = {0};
+#endif
+char smtpsize[FMT_ULONG];
 
-void setup()
+void setup(void)
 {
-  char *x;
+#ifdef TLS_SMTPD
+  char *sslpath;
+#endif
+  char *x, *l;
   unsigned long u;
- 
+
+  l = env_get("LOGLEVEL");
+  if (l) { scan_ulong(l,&u); loglevel = u > 4 ? 4 : u; }
+
   if (control_init() == -1) die_control();
-  if (control_rldef(&greeting,"control/smtpgreeting",1,(char *) 0) != 1)
+
+  if (control_readline(&me,"control/me") != 1)
+    die_control();
+  if (!stralloc_0(&me)) die_nomem();
+
+  if (control_rldef(&greeting,"control/smtpgreeting", 0, "") == -1)
     die_control();
+
+  if (control_rldef(&cookie,"control/smtpclustercookie", 0, "") == -1)
+    die_control();
+  if (cookie.len > 32) cookie.len = 32;
+
   liphostok = control_rldef(&liphost,"control/localiphost",1,(char *) 0);
   if (liphostok == -1) die_control();
+
   if (control_readint(&timeout,"control/timeoutsmtpd") == -1) die_control();
   if (timeout <= 0) timeout = 1;
 
+#ifdef TLS_SMTPD
+  sslpath = env_get("SSLCERT");
+  if (!sslpath) {
+    sslpath = (char *)"control/smtpcert";
+    if (control_readline(&sslcert, sslpath) == -1)
+      die_control();
+  } else
+    if (!stralloc_copys(&sslcert, sslpath)) die_nomem();
+  if (!stralloc_0(&sslcert)) die_nomem();
+#endif
+
+  x = env_get("TARPITCOUNT");
+  if (x) { scan_ulong(x,&u); tarpitcount = u >= UINT_MAX ? UINT_MAX - 1 : u; }
+
+  x = env_get("TARPITDELAY");
+  if (x) { scan_ulong(x,&u); tarpitdelay = u > INT_MAX ? INT_MAX : u; }
+
+  x = env_get("MAXRCPTCOUNT");
+  if (x) { scan_ulong(x,&u); maxrcptcount = u >= UINT_MAX ? UINT_MAX - 1 : u; };
+
   if (rcpthosts_init() == -1) die_control();
 
   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 (control_readint(&databytes,"control/databytes") == -1) die_control();
+
+  bmfunknownok = control_readfile(&bmfunknown,"control/badmailfrom-unknown",0);
+  if (bmfunknownok == -1) die_control();
+  if (bmfunknownok)
+    if (!constmap_init(&mapbmfunknown,bmfunknown.s,bmfunknown.len,0))
+      die_nomem();
+
+  rmfok = control_readfile(&rmf,"control/relaymailfrom",0);
+  if (rmfok == -1) die_control();
+  if (rmfok)
+    if (!constmap_init(&maprmf,rmf.s,rmf.len,0)) die_nomem();
+
+  brtok = control_readfile(&brt,"control/badrcptto",0);
+  if (brtok == -1) die_control();
+  if (brtok)
+    if (!constmap_init(&mapbadrcptto,brt.s,brt.len,0)) die_nomem();
+
+  gmaok = control_readfile(&gma,"control/goodmailaddr",0);
+  if (gmaok == -1) die_control();
+  if (gmaok)
+    if (!constmap_init(&mapgma,gma.s,gma.len,0)) die_nomem();
+
+  if (env_get("RBL")) {
+    rblok = rblinit();
+    if (rblok == -1) die_control();
+    if (env_get("RBLONLYHEADER")) rbloh = 1;
+  }
+
+  if (env_get("SMTP550DISCONNECT")) errdisconnect = 1;
+  if (env_get("NOBOUNCE")) nobounce = 1;
+  if (env_get("SANITYCHECK")) sanitycheck = 1;
+  if (env_get("RETURNMXCHECK")) returnmxcheck = 1;
+  if (env_get("BLOCKRELAYPROBE")) blockrelayprobe = 1;
+  if (env_get("SENDERCHECK")) {
+    sendercheck = 1;
+    if (!case_diffs("LOOSE",env_get("SENDERCHECK"))) sendercheck = 2;
+    if (!case_diffs("STRICT",env_get("SENDERCHECK"))) sendercheck = 3;
+  }
+  if (env_get("RCPTCHECK")) rcptcheck = 1;
+  if (env_get("LDAPSOFTOK")) ldapsoftok = 1;
+  greeting550 = env_get("550GREETING");
+  greeting421 = env_get("421GREETING");
+  relayok = relayclient = env_get("RELAYCLIENT");
+
+  if (env_get("SMTPAUTH")) {
+    flagauth = 1;
+    if (!case_diffs("TLSREQUIRED", env_get("SMTPAUTH"))) needssl = 1;
+  }
+  if (env_get("AUTHREQUIRED")) needauth = 1;
+  authprepend = env_get("AUTHPREPEND");
+
+#ifdef SMTPEXECCHECK
+  execcheck_setup();
+#endif
+
+  if (control_readulong(&databytes,"control/databytes") == -1) die_control();
   x = env_get("DATABYTES");
-  if (x) { scan_ulong(x,&u); databytes = u; }
-  if (!(databytes + 1)) --databytes;
+  if (x) scan_ulong(x,&databytes);
+  if (!(databytes + 1)) --databytes; /* poor man overflow detection */
  
   remoteip = env_get("TCPREMOTEIP");
   if (!remoteip) remoteip = "unknown";
-  local = env_get("TCPLOCALHOST");
-  if (!local) local = env_get("TCPLOCALIP");
-  if (!local) local = "unknown";
   remotehost = env_get("TCPREMOTEHOST");
   if (!remotehost) remotehost = "unknown";
   remoteinfo = env_get("TCPREMOTEINFO");
-  relayclient = env_get("RELAYCLIENT");
+
+  local = env_get("TCPLOCALHOST");
+  if (!local) local = env_get("TCPLOCALIP");
+  if (!local) local = "unknown";
+
+  logpid(2);
+  logstring(2,"connection from "); logstring(2,remoteip);
+  logstring(2," ("); logstring(2,remotehost);
+  if (remoteinfo) { logstring(2,", "); logstring(2,remoteinfo); }
+  logstring(2,") to "); logstring(2,local);
+  logflush(2);
+
+  logpid(3);
+  logstring(3, "enabled options: ");
+  if (databytes != 0) {
+    smtpsize[fmt_ulong(smtpsize, databytes)] = 0;
+    logstring(3,"max msg size: ");
+    logstring(3,smtpsize);
+    logstring(3," ");
+  }
+  if (greeting550) logstring(3,"greeting550 ");
+#ifdef TLS_SMTPD
+  if (sslcert.s && *sslcert.s) logstring(3, "starttls ");
+#endif
+  if (relayclient) logstring(3,"relayclient ");
+  if (sanitycheck) logstring(3,"sanitycheck ");
+  if (returnmxcheck) logstring(3,"returnmxcheck ");
+  if (blockrelayprobe) logstring(3,"blockrelayprobe ");
+  if (nobounce) logstring(3,"nobounce ");
+  if (rblok) logstring(3,"rblcheck ");
+  if (rbloh) logstring(3,"rblonlyheader ");
+  if (sendercheck) logstring(3,"sendercheck");
+  if (sendercheck == 1) logstring(3," ");
+  if (sendercheck == 2) logstring(3,"-loose ");
+  if (sendercheck == 3) logstring(3,"-strict ");
+  if (rcptcheck) logstring(3,"rcptcheck ");
+  if (ldapsoftok) logstring(3,"ldapsoftok ");
+  if (flagauth) logstring(3, "smtp-auth");
+  if (needssl) logstring(3, "-tls-required ");
+  else logstring(3, " ");
+  if (needauth) logstring(3, "authrequired ");
+#ifdef SMTPEXECCHECK
+  if (execcheck_on()) logstring(3, "rejectexecutables ");
+#endif
+  if (errdisconnect) logstring(3,"smtp550disconnect ");
+#ifdef ALTQUEUE
+  if (env_get("QMAILQUEUE")) {
+    logstring(3,"qmailqueue ");
+    logstring(3,env_get("QMAILQUEUE"));
+  }
+#endif
+  logflush(3);
+
   dohelo(remotehost);
 }
 
 
 stralloc addr = {0}; /* will be 0-terminated, if addrparse returns 1 */
 
-int addrparse(arg)
-char *arg;
+int addrparse(char *arg)
 {
-  int i;
+  unsigned int i;
   char ch;
   char terminator;
   struct ip_address ip;
@@ -155,6 +494,7 @@
     terminator = ' ';
     arg += str_chr(arg,':');
     if (*arg == ':') ++arg;
+    if (*arg == '\0') return 0;
     while (*arg == ' ') ++arg;
   }
 
@@ -164,7 +504,7 @@
   if (!stralloc_copys(&addr,"")) die_nomem();
   flagesc = 0;
   flagquoted = 0;
-  for (i = 0;ch = arg[i];++i) { /* copy arg to addr, stripping quotes */
+  for (i = 0;(ch = arg[i]);++i) { /* copy arg to addr, stripping quotes */
     if (flagesc) {
       if (!stralloc_append(&addr,&ch)) die_nomem();
       flagesc = 0;
@@ -197,78 +537,761 @@
   return 1;
 }
 
-int bmfcheck()
+stralloc checkhost = {0};
+ipalloc checkip = {0};
+
+int badmxcheck(char *dom)
+{
+  int ret = 0;
+  unsigned long r;
+
+  if (!*dom) return (DNS_HARD);
+  if (!stralloc_copys(&checkhost,dom)) return (DNS_SOFT);
+
+  r = now() + (getpid() << 16);
+  switch (dns_mxip(&checkip,&checkhost,r))
+  {
+    case DNS_MEM:
+    case DNS_SOFT:
+         ret = DNS_SOFT;
+         break;
+    case DNS_HARD:
+         ret = DNS_HARD;
+         break;
+    case 1:
+         if (checkip.len <= 0) ret = DNS_SOFT;
+         break;
+    default:
+         if (checkip.len <= 0) ret = DNS_HARD;
+         break;
+  }
+  return (ret);
+}
+
+stralloc parameter = {0};
+
+char *getparameter(char *arg, const char *name)
+{
+  unsigned int i;
+  char ch;
+  char terminator;
+  int flagesc;
+  int flagquoted;
+
+  terminator = '>';
+  i = str_chr(arg,'<');
+  if (arg[i])
+    arg += i + 1;
+  else { /* partner should go read rfc 821 */
+    terminator = ' ';
+    arg += str_chr(arg,':');
+    if (*arg == ':') ++arg;
+    while (*arg == ' ') ++arg;
+  }
+
+  flagesc = 0;
+  flagquoted = 0;
+  for (i = 0;(ch = arg[i]);++i) { /* skipping addr, respecting quotes */
+    if (flagesc) {
+      flagesc = 0;
+    } else {
+      if (!flagquoted && (ch == terminator)) break;
+      switch(ch) {
+        case '\\': flagesc = 1; break;
+        case '"': flagquoted = !flagquoted; break;
+        default: break;
+      }
+    }
+  }
+  if (!arg[i++]) return (char *)0; /* no parameters */
+  arg += i;
+  do {
+    while (*arg == ' ') if (!*arg++) return (char *)0;
+    if (case_diffb(arg, str_len(name), name) == 0) {
+      arg += str_len(name);
+      if (*arg++ == '=') {
+	i = str_chr(arg, ' ');
+	if (!stralloc_copyb(&parameter, arg, i)) die_nomem();
+	if (!stralloc_0(&parameter)) die_nomem();
+	return parameter.s;
+      }
+    }
+    while (*arg != ' ') if (!*arg++) return (char *)0;
+  } while (1);
+}
+
+int sizelimit(char *arg)
 {
-  int j;
+  char *size;
+  unsigned long sizebytes = 0;
+
+  size = getparameter(arg, "SIZE");
+  if (!size) return 1;
+
+  scan_ulong(size, &sizebytes);
+  return databytes >= sizebytes;
+}
+
+
+int bmfcheck(void)
+{
+  unsigned 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;
+    if (constmap(&mapbmf,addr.s, j + 1)) return 1;
+  }
+  return 0;
+}
+
+int bmfunknowncheck(void)
+{
+  unsigned int j;
+
+  if (!bmfunknownok) return 0;
+  if (case_diffs(remotehost,"unknown")) return 0;
+  if (constmap(&mapbmfunknown,addr.s,addr.len - 1)) return 1;
+  j = byte_rchr(addr.s,addr.len,'@');
+  if (j < addr.len)
+    if (constmap(&mapbmfunknown,addr.s + j,addr.len - j - 1)) return 1;
   return 0;
 }
 
-int addrallowed()
+int seenmail = 0;
+stralloc mailfrom = {0};
+stralloc rcptto = {0};
+unsigned int rcptcount;
+
+int rmfcheck(void)
+{
+  unsigned int j;
+
+  if (!rmfok) return 0;
+  if (constmap(&maprmf,addr.s,addr.len - 1)) return 1;
+  j = byte_rchr(addr.s,addr.len,'@');
+  if (j < addr.len)
+    if (constmap(&maprmf,addr.s + j,addr.len - j - 1)) return 1;
+  return 0;
+}
+
+int addrallowed(void)
 {
   int r;
-  r = rcpthosts(addr.s,str_len(addr.s));
+
+  r = rcpthosts(addr.s,addr.len - 1);
   if (r == -1) die_control();
   return r;
 }
 
+int addrlocals(void)
+{
+  int r;
 
-int seenmail = 0;
-int flagbarf; /* defined if seenmail */
-stralloc mailfrom = {0};
-stralloc rcptto = {0};
+  r = localhosts(addr.s, addr.len - 1);
+  if (r == -1) die_control();
+  return r;
+}
+
+int rcptdenied(void)
+{
+  unsigned int j;
+
+  if (!brtok) return 0;
+  if (constmap(&mapbadrcptto, addr.s, addr.len - 1)) return 1;
+  j = byte_rchr(addr.s,addr.len,'@');
+  if (j < addr.len)
+    if (constmap(&mapbadrcptto, addr.s + j, addr.len - j - 1))
+      return 1;
+  return 0;
+}
+
+stralloc gmaddr;
+
+int goodmailaddr(void)
+{
+  unsigned int at;
+#ifdef DASH_EXT
+  unsigned int ext;
+  int extcnt;
+#endif
+
+  if (!gmaok) return 0;
+  if (constmap(&mapgma, addr.s, addr.len - 1)) return 1;
+  at = byte_rchr(addr.s,addr.len,'@');
+  if (at < addr.len) {
+    if (constmap(&mapgma, addr.s + at, addr.len - at - 1))
+      return 1;
+    if (constmap(&mapgma, addr.s, at + 1))
+      return 1;
+#ifdef DASH_EXT
+    /* foo-catchall@domain.org */
+    for (ext = 0, extcnt = 1; ext < at && extcnt <= DASH_EXT_LEVELS; ext++)
+      if (addr.s[ext] == *auto_break)
+	extcnt++;
+    for (;;) {
+      if (addr.s[ext] == *auto_break) {
+	if (!stralloc_copyb(&gmaddr, addr.s, ext + 1))
+	  die_nomem();
+	if (!stralloc_cats(&gmaddr, LDAP_CATCH_ALL))
+	  die_nomem();
+	if (!stralloc_catb(&gmaddr, addr.s + at, addr.len - at - 1))
+	  die_nomem();
+	if (constmap(&mapgma, gmaddr.s, gmaddr.len))
+	  return 1;
+      }
+      if (ext == 0)
+	break;
+      ext--;
+    }
+#endif
+    /* catchall@domain.org */
+    if (!stralloc_copys(&gmaddr, LDAP_CATCH_ALL))
+      die_nomem();
+    if (!stralloc_catb(&gmaddr, addr.s + at, addr.len - at - 1))
+      die_nomem();
+    if (constmap(&mapgma, gmaddr.s, gmaddr.len))
+      return 1;
+  }
+  return 0;
+}
+
+struct call ccverify;
+stralloc verifyresponse;
+int flagverify = 0;
+
+void ldaplookupdone(void)
+{
+  if (flagverify != 1) return;
+  call_close(&ccverify);
+  flagverify = 0;
+  return;
+}
 
-void smtp_helo(arg) char *arg;
+int ldaplookup(char *address, char **s)
 {
-  smtp_greet("250 "); out("\r\n");
+  char ch;
+  
+  if (flagverify == -1) return -1;
+  if (flagverify == 0) {
+    if (call_open(&ccverify, "bin/qmail-verify", 30, 0) == -1) {
+      flagverify = -1;
+      return -1;
+    }
+    flagverify = 1;
+  }
+  call_puts(&ccverify, address); call_putflush(&ccverify, "", 1);
+  if (call_getc(&ccverify, &ch) != 1)
+    goto fail;
+  switch (ch) {
+  case 'K':
+    return 1;
+  case 'D':
+    /* get response */
+    if (!stralloc_copys(&verifyresponse, "")) die_nomem();
+    while (call_getc(&ccverify, &ch) == 1) {
+      if (!stralloc_append(&verifyresponse, &ch)) die_nomem();
+      if (ch == 0) {
+	*s = verifyresponse.s;
+	return 0;
+      }
+    }
+    break;
+  case 'Z':
+    /* soft error */
+    if (!stralloc_copys(&verifyresponse, "")) die_nomem();
+    while (call_getc(&ccverify, &ch) == 1) {
+      if (!stralloc_append(&verifyresponse, &ch)) die_nomem();
+      if (ch == 0) {
+	*s = verifyresponse.s;
+	return -1;
+      }
+    }
+    break;
+  default:
+    break;
+  }
+fail:
+  flagverify = -1;
+  call_close(&ccverify);
+  return -1;
+}
+
+int relayprobe(void) /* relay probes trying stupid old sendwhale bugs */
+{
+  unsigned int j;
+  for (j = byte_rchr(addr.s, addr.len, '@'); j-- > 0; ) {
+    if (addr.s[j] == '@') return 1; /* double @ */
+    if (addr.s[j] == '%') return 1; /* percent relaying */
+    if (addr.s[j] == '!') return 1; /* UUCP bang path */
+  }
+  return 0;
+}
+
+
+void smtp_helo(char *arg)
+{
+  smtp_line("250 ");
   seenmail = 0; dohelo(arg);
+  logline2(4, "remote helo: ", arg);
 }
-void smtp_ehlo(arg) char *arg;
+
+void smtp_ehlo(char *arg)
 {
-  smtp_greet("250-"); out("\r\n250-PIPELINING\r\n250 8BITMIME\r\n");
+  smtp_line("250-");
+  out("250-PIPELINING\r\n");
+  if (databytes != 0) {
+    smtpsize[fmt_ulong(smtpsize, databytes)] = 0;
+    out("250-SIZE "); out(smtpsize); out("\r\n");
+  }
+#ifdef DATA_COMPRESS
+  out("250-DATAZ\r\n");
+#endif
+#ifdef TLS_SMTPD
+  if (!ssl && sslcert.s && *sslcert.s)
+    out("250-STARTTLS\r\n");
+#endif
+#ifdef TLS_SMTPD
+  if (!needssl || ssl)
+#endif
+  if (flagauth)
+    out("250-AUTH LOGIN PLAIN\r\n");
+  out("250 8BITMIME\r\n");
+
   seenmail = 0; dohelo(arg);
+  logline2(4,"remote ehlo: ",arg);
 }
-void smtp_rset()
+
+void smtp_rset(char *arg)
 {
   seenmail = 0;
+  if (relayclient != NULL && relayok == NULL)
+	  env_unset("RELAYCLIENT");
+  relayclient = relayok; /* restore original relayclient setting */
   out("250 flushed\r\n");
+  logline(4,"remote rset");
 }
-void smtp_mail(arg) char *arg;
+
+struct qmail qqt;
+
+void smtp_mail(char *arg)
 {
-  if (!addrparse(arg)) { err_syntax(); return; }
-  flagbarf = bmfcheck();
+  unsigned int i,j;
+  char *rblname;
+  int bounceflag = 0;
+
+  /* address syntax check */
+  if (!addrparse(arg))
+  {
+    err_syntax(); 
+    logline2(3,"RFC2821 syntax error in mail from: ",arg);
+    if (errdisconnect) err_quit();
+    return;
+  }
+
+  logline2(4,"mail from: ",addr.s);
+
+  if (needauth && !flagauthok) {
+    out("530 authentication needed\r\n");
+    logline(3, "auth needed");
+    if (errdisconnect) err_quit();
+    return;
+  }
+
+  /* check if we are authenticated, if yes enable relaying */
+  if (flagauthok && relayclient == 0) {
+    relayclient = "";
+    if (!env_put("RELAYCLIENT=")) die_nomem();
+  }
+
+  /* smtp size check */
+  if (databytes && !sizelimit(arg))
+  {
+    err_size(); /* logging is done in error routine */
+    if (errdisconnect) err_quit();
+    return;
+  }
+
+  /* bad mailfrom check */
+  if (bmfcheck())
+  {
+    err_bmf();
+    logline2(3,"bad mailfrom: ",addr.s);
+    if (errdisconnect) err_quit();
+    return;
+  }
+  /* bad mailfrom unknown check */
+  if (bmfunknowncheck())
+  {
+    err_bmfunknown();
+    logline2(3,"bad mailfrom unknown: ",addr.s);
+    if (errdisconnect) err_quit();
+    return;
+  }
+
+  /* NOBOUNCE check */
+  if (!addr.s[0] || !str_diff("#@[]", addr.s))
+  {
+    bounceflag = 1;
+    if (nobounce)
+    {
+      err_554msg("RFC2821 bounces are administratively denied");
+      if (errdisconnect) err_quit();
+      return;
+    }
+  }
+
+  /* Sanity checks */
+  if (sanitycheck && !bounceflag)
+  {
+    /* Invalid Mailfrom */
+    if ((i=byte_rchr(addr.s,addr.len,'@')) >= addr.len)
+    {
+      err_554msg("mailfrom without @ is administratively denied");
+      if (errdisconnect) err_quit();
+      return;
+    }
+    if (i == 0 || addr.s[i+1] == '\0') {
+      err_554msg("mailfrom without user or domain part is "
+        "administratively denied");
+      if (errdisconnect) err_quit();
+      return;
+    }
+    /* No '.' in domain.TLD */
+    if ((j = byte_rchr(addr.s+i, addr.len-i, '.')) >= addr.len-i) {
+      err_554msg("mailfrom without . in domain part is "
+        "administratively denied");
+      if (errdisconnect) err_quit();
+      return;
+    }
+    /* check tld length */
+    j = addr.len-(i+1+j+1);
+    if (j < 2 || j > 6)
+    {
+      /* XXX: This needs adjustment when new TLD's are constituded.
+       * OK, now after the candidates are nominated we know new TLD's
+       * may contain up to six characters.
+       */
+      err_554msg("mailfrom without country or top level domain is "
+        "administratively denied");
+      if (errdisconnect) err_quit();
+      return;
+     }
+  }
+
+  /* relay mail from check (allow relaying based on evelope sender address) */
+  if (!relayclient) {
+    if (rmfcheck()) {
+      relayclient = "";
+      if (!env_put("RELAYCLIENT=")) die_nomem();
+      logline(4,"relaying allowed via relaymailfrom");
+    }
+  }
+
+  /* Check RBL only if relayclient is not set */
+  if (rblok && !relayclient)
+  {
+    switch(rblcheck(remoteip, &rblname, rbloh))
+    {
+      case 2: /* soft error lookup */
+        /*
+         * continue if  RBL DNS has a problem. if a RBL is unreachable
+         * we dont want to fail. accept message anyway. a false negative
+         * is better in this case than rejecting every message just
+         * because one RBL failed. play safe, might be an important mail.
+         */
+        break;
+      case 1: /* host is listed in RBL */
+        err_rbl(rblname);
+        if (errdisconnect) err_quit();
+        return;
+      default: /* ok, go ahead */
+        logline(4,"RBL checking completed");
+        break;
+    }
+  }
+
+  /* return MX check */
+  if (returnmxcheck && !bounceflag)
+  {
+    if ((i=byte_rchr(addr.s,addr.len,'@')) < addr.len)
+      switch (badmxcheck(&addr.s[i+1]))
+      {
+	case 0:
+	  break; /* valid */
+	case DNS_SOFT:
+	  err_dns();
+	  logline(3,"refused mailfrom because return MX lookup "
+            "failed temporarly");
+	  if (errdisconnect) err_quit();
+	  return;
+	case DNS_HARD:
+	default:
+	  err_554msg("refused mailfrom because return MX does not exist");
+	  if (errdisconnect) err_quit();
+	  return;
+      }
+  }
+
+  /* check if sender exists in ldap */
+  if (sendercheck && !bounceflag) {
+    if (!goodmailaddr()) { /* good mail addrs go through anyway */
+      logline(4,"sender verify, sender not in goodmailaddr");
+      if (addrlocals()) {
+	char *s;
+	logline(4,"sender verify, sender is local");
+        switch (ldaplookup(addr.s, &s)) {
+          case 1: /* valid */
+	    logline(4,"sender verify OK");
+            break;
+          case 0: /* invalid */
+	    logline2(2, "bad sender: ", addr.s);
+            err_554msg(s);
+            if (errdisconnect) err_quit();
+            return;
+          case -1:
+          default: /* other error, treat as soft 4xx */
+            if (ldapsoftok)
+              break;
+            err_soft(s);
+            if (errdisconnect) err_quit();
+            return;
+        }
+      } else {
+        /* not in addrlocals, ldap lookup is useless */
+        /* normal mode: let through, it's just an external mail coming in */
+        /* loose mode (2): see if sender is in rcpthosts, if no reject here */
+        /* strict mode (3): validated sender required so reject in any case */
+        if ((sendercheck == 2 && !addrallowed()) || sendercheck == 3) {
+          err_554msg("refused mailfrom because valid "
+            "local sender address required");
+          if (errdisconnect) err_quit();
+          return;
+        }
+      }
+    }
+  }
+
   seenmail = 1;
   if (!stralloc_copys(&rcptto,"")) die_nomem();
   if (!stralloc_copys(&mailfrom,addr.s)) die_nomem();
   if (!stralloc_0(&mailfrom)) die_nomem();
+  rcptcount = 0;
+  if (loglevel < 4)
+    logline2(2,"mail from: ",mailfrom.s);
   out("250 ok\r\n");
 }
-void smtp_rcpt(arg) char *arg; {
-  if (!seenmail) { err_wantmail(); return; }
-  if (!addrparse(arg)) { err_syntax(); return; }
-  if (flagbarf) { err_bmf(); return; }
+
+void smtp_rcpt(char *arg)
+{
+  if (!seenmail)
+  {
+    err_wantmail();
+    if (errdisconnect) err_quit();
+    return;
+  }
+
+  /* syntax check */
+  if (!addrparse(arg))
+  {
+    err_syntax();
+    logline2(3,"syntax error in 'rcpt to': ",arg);
+    if (errdisconnect) err_quit();
+    return;
+  }
+
+  logline2(4,"rcpt to: ",addr.s);
+
+  /* block stupid and bogus sendwhale bug relay probing */
+  /* don't enable this if you use percenthack */
+  if (blockrelayprobe && relayprobe()) {
+    err_relay();
+    logline(3,"'rcpt to' denied, looks like bogus sendwhale bug relay probe");
+    if (errdisconnect) err_quit();
+    return;
+  }
+
+  /* do we block this recipient */
+  if (rcptdenied()) {
+    err_badrcptto();
+    logline2(3,"'rcpt to' denied via badrcptto: ",addr.s);
+    if (errdisconnect) err_quit();
+    return;
+  }
+
+  /* is sender ip allowed to relay */
   if (relayclient) {
     --addr.len;
     if (!stralloc_cats(&addr,relayclient)) die_nomem();
     if (!stralloc_0(&addr)) die_nomem();
+  } else {
+    if (!addrallowed()) { 
+      err_nogateway();
+      logline2(3,"no mail relay for 'rcpt to': ",addr.s);
+      if (errdisconnect) err_quit();
+      return; 
+    }
   }
-  else
-    if (!addrallowed()) { err_nogateway(); return; }
+  ++rcptcount;
+
+  /* maximum recipient limit reached */
+  if (maxrcptcount && rcptcount > maxrcptcount) {
+    err_maxrcpt();
+    logline(3,"message denied because of more 'RCPT TO' than "
+      "allowed by MAXRCPTCOUNT");
+    if (errdisconnect) err_quit();
+    return;
+  }
+
+  /* only one recipient for bounce messages */
+  if (rcptcount > 1 && (!mailfrom.s[0] || !str_diff("#@[]", mailfrom.s))) {
+    err_badbounce();
+    logline(3,"bounce message denied because it has more than one recipient");
+    if (errdisconnect) err_quit();
+    return;
+  }
+
+  /* check if recipient exists in ldap */
+  if (rcptcheck) {
+    if (!goodmailaddr()) {
+      logline(4,"recipient verify, recipient not in goodmailaddr");
+      if (addrlocals()) {
+	char *s;
+	logline(4,"recipient verify, recipient is local");
+        switch (ldaplookup(addr.s, &s)) {
+          case 1: /* valid */
+	    logline(4,"recipient verify OK");
+            break;
+          case 0: /* invalid */
+	    logline2(2, "bad recipient: ", addr.s);
+            err_554msg(s);
+            if (errdisconnect) err_quit();
+            return;
+          case -1:
+          default: /* other error, treat as soft 4xx */
+            if (ldapsoftok)
+              break;
+            err_soft(s);
+            if (errdisconnect) err_quit();
+            return;
+        }
+      } /* else this is relaying, don't do anything */
+    }
+  }
+
+  if (loglevel < 4)
+    logline2(2,"rcpt to: ",addr.s);
   if (!stralloc_cats(&rcptto,"T")) die_nomem();
   if (!stralloc_cats(&rcptto,addr.s)) die_nomem();
   if (!stralloc_0(&rcptto)) die_nomem();
+  if (tarpitcount && tarpitdelay && rcptcount >= tarpitcount) {
+    logline(3,"tarpitting");
+    while (sleep(tarpitdelay));
+  }
   out("250 ok\r\n");
 }
 
+#ifdef DATA_COMPRESS
+z_stream stream;
+char zbuf[4096];
+int wantcomp = 0;
+int compdata = 0;
+
+int compression_init(void)
+{
+  compdata = 1;
+  stream.zalloc = Z_NULL;
+  stream.zfree = Z_NULL;
+  stream.opaque = Z_NULL;
+  stream.avail_in = 0;
+  stream.next_in = zbuf;
+  if (inflateInit(&stream) != Z_OK) {
+    out("451 Initalizing data compression failed: ");
+    out(stream.msg); out(" #(4.3.0)\r\n"); flush();
+    return -1;
+  }
+  return 0;
+}
+int compression_done(void)
+{
+  char num[FMT_ULONG + 1];
+  int r;
+
+  compdata = 0;
+  if (stream.avail_out != sizeof(zbuf)) {
+    /* there is some left data, ignore */
+  }
+  if (inflateEnd(&stream) != Z_OK) {
+    out("451 Finishing data compression failed: ");
+    out(stream.msg); out(" #(4.3.0)\r\n"); flush();
+    return -1;
+  }
+  r = 100 - (int)(100.0*stream.total_in/stream.total_out);
+  if (r < 0) {
+    num[0] = '-';
+    r *= -1;
+  } else
+    num[0] = ' ';
+  num[fmt_uint(num+1,r)+1] = 0;
+  logpid(3);
+  logstring(3,"DDC saved ");
+  logstring(3,num);
+  logstring(3," percent");
+  logflush(3);
+  return 0;
+}
+#endif
 
-int saferead(fd,buf,len) int fd; char *buf; int len;
+int saferead(int fd,void *buf,int len)
 {
   int r;
   flush();
+#ifdef DATA_COMPRESS
+  if (compdata) {
+    stream.avail_out = len;
+    stream.next_out = buf;
+    do {
+      if (stream.avail_in == 0) {
+#ifdef TLS_SMTPD
+	if (ssl)
+	  r = ssl_timeoutread(timeout,fd,zbuf,sizeof(zbuf));
+	else
+#endif
+	r = timeoutread(timeout,fd,zbuf,sizeof(zbuf));
+	if (r == -1) if (errno == error_timeout) die_alarm();
+	if (r <= 0) die_read();
+	stream.avail_in = r;
+	stream.next_in = zbuf;
+      }
+      r = inflate(&stream, 0);
+      switch (r) {
+      case Z_OK:
+	if (stream.avail_out == 0)
+	  return len;
+	break;
+      case Z_STREAM_END:
+	compdata = 0;
+	return len - stream.avail_out;
+      default:
+	out("451 Receiving compressed data failed: ");
+	out(stream.msg); out(" #(4.3.0)\r\n");
+	logline2(1, "compressed data read failed: ", stream.msg);
+	flush();
+	die_read();
+      }
+      if (stream.avail_out == (unsigned int)len) continue;
+      return len - stream.avail_out;
+    } while (1);
+  }
+#endif
+#ifdef TLS_SMTPD
+  if (ssl)
+    r = ssl_timeoutread(timeout,fd,buf,len);
+  else
+#endif
   r = timeoutread(timeout,fd,buf,len);
   if (r == -1) if (errno == error_timeout) die_alarm();
   if (r <= 0) die_read();
@@ -278,25 +1301,27 @@
 char ssinbuf[1024];
 substdio ssin = SUBSTDIO_FDBUF(saferead,0,ssinbuf,sizeof ssinbuf);
 
-struct qmail qqt;
-unsigned int bytestooverflow = 0;
+unsigned long bytestooverflow = 0;
+unsigned long bytesreceived = 0;
 
-void put(ch)
-char *ch;
+void put(const char *ch)
 {
+#ifdef SMTPEXECCHECK
+  execcheck_put(&qqt, ch);
+#endif
   if (bytestooverflow)
     if (!--bytestooverflow)
       qmail_fail(&qqt);
   qmail_put(&qqt,ch,1);
+  ++bytesreceived;
 }
 
-void blast(hops)
-int *hops;
+void blast(unsigned int *hops)
 {
   char ch;
   int state;
   int flaginheader;
-  int pos; /* number of bytes since most recent \n, if fih */
+  unsigned int pos; /* number of bytes since most recent \n, if fih */
   int flagmaybex; /* 1 if this line might match RECEIVED, if fih */
   int flagmaybey; /* 1 if this line might match \r\n, if fih */
   int flagmaybez; /* 1 if this line might match DELIVERED, if fih */
@@ -318,6 +1343,7 @@
         if (flagmaybey) if (pos == 1) flaginheader = 0;
       }
       ++pos;
+      if (pos > MAXLINELEN) oversizedline();
       if (ch == '\n') { pos = 0; flagmaybex = flagmaybey = flagmaybez = 1; }
     }
     switch(state) {
@@ -351,49 +1377,331 @@
   }
 }
 
-char accept_buf[FMT_ULONG];
-void acceptmessage(qp) unsigned long qp;
+void acceptmessage(unsigned long qp)
 {
+  static char buf[FMT_ULONG];
+
   datetime_sec when;
   when = now();
   out("250 ok ");
-  accept_buf[fmt_ulong(accept_buf,(unsigned long) when)] = 0;
-  out(accept_buf);
+  buf[fmt_ulong(buf,(unsigned long) when)] = 0;
+  out(buf);
+  logpid(2); logstring(2,"message queued: "); logstring(2,buf);
   out(" qp ");
-  accept_buf[fmt_ulong(accept_buf,qp)] = 0;
-  out(accept_buf);
+  buf[fmt_ulong(buf,qp)] = 0;
+  out(buf);
+  out(" by ");
+  out(me.s);
   out("\r\n");
+  logstring(2," qp "); logstring(2,buf);
+  buf[fmt_ulong(buf, bytesreceived)] = 0;
+  logstring(2, " size ");
+  logstring(2, buf);
+  logstring(2, " bytes");
+  logflush(2);
 }
 
-void smtp_data() {
-  int hops;
+#ifdef TLS_SMTPD
+stralloc protocolinfo = {0};
+#endif
+
+void smtp_data(char *arg) {
+  unsigned int hops;
   unsigned long qp;
-  char *qqx;
- 
-  if (!seenmail) { err_wantmail(); return; }
-  if (!rcptto.len) { err_wantrcpt(); return; }
+  const char *qqx;
+
+  ldaplookupdone();
+  if (!seenmail) {
+    err_wantmail();
+    if (errdisconnect) err_quit();
+    return;
+  }
+  if (!rcptto.len) {
+    err_wantrcpt();
+    if (errdisconnect) err_quit();
+    return;
+  }
   seenmail = 0;
   if (databytes) bytestooverflow = databytes + 1;
-  if (qmail_open(&qqt) == -1) { err_qqt(); return; }
+#ifdef SMTPEXECCHECK
+  execcheck_start();
+#endif
+  if (qmail_open(&qqt) == -1) {
+    err_qqt();
+    logline(1,"failed to start qmail-queue");
+    return;
+  }
   qp = qmail_qp(&qqt);
-  out("354 go ahead\r\n");
- 
-  received(&qqt,"SMTP",local,remoteip,remotehost,remoteinfo,fakehelo);
+  out("354 go ahead punk, make my day\r\n"); logline(4,"go ahead");
+  rblheader(&qqt);
+
+#ifdef TLS_SMTPD
+  if(ssl){
+    if (!stralloc_copys(&protocolinfo,
+       SSL_CIPHER_get_name(SSL_get_current_cipher(ssl)))) die_nomem();
+#ifdef DATA_COMPRESS
+    if (wantcomp) {
+      if (!stralloc_cats(&protocolinfo, " encrypted compressed SMTP"))
+	die_nomem();
+    } else
+#endif
+    if (!stralloc_cats(&protocolinfo, " encrypted SMTP")) die_nomem();
+  } else {
+#ifdef DATA_COMPRESS
+    if (wantcomp) {
+      if (!stralloc_copys(&protocolinfo,"compressed SMTP")) die_nomem();
+    } else
+#endif
+    if (!stralloc_copys(&protocolinfo,"SMTP")) die_nomem();
+  }
+  if (!stralloc_0(&protocolinfo)) die_nomem();
+  received(&qqt,protocolinfo.s,local,remoteip,remotehost,remoteinfo,fakehelo,mailfrom.s,&rcptto.s[1]);
+#else 
+#ifdef DATA_COMPRESS
+  if (wantcomp)
+    received(&qqt,"compressed SMTP",local,remoteip,remotehost,remoteinfo,fakehelo,mailfrom.s,&rcptto.s[1]);
+  else
+#endif
+    received(&qqt,"SMTP",local,remoteip,remotehost,remoteinfo,fakehelo,mailfrom.s,&rcptto.s[1]);
+#endif
+
+#ifdef DATA_COMPRESS
+  if (wantcomp) { if (compression_init() != 0) return; }
+#endif
   blast(&hops);
+#ifdef DATA_COMPRESS
+  if (wantcomp) { if (compression_done() != 0) return; }
+#endif
+
   hops = (hops >= MAXHOPS);
-  if (hops) qmail_fail(&qqt);
+  if (hops)
+    qmail_fail(&qqt);
   qmail_from(&qqt,mailfrom.s);
   qmail_put(&qqt,rcptto.s,rcptto.len);
  
   qqx = qmail_close(&qqt);
   if (!*qqx) { acceptmessage(qp); return; }
-  if (hops) { out("554 too many hops, this message is looping (#5.4.6)\r\n"); return; }
-  if (databytes) if (!bytestooverflow) { out("552 sorry, that message size exceeds my databytes limit (#5.3.4)\r\n"); return; }
-  if (*qqx == 'D') out("554 "); else out("451 ");
+  if (hops) {
+    out("554 too many hops, this message is looping (#5.4.6)\r\n");
+    logline(3,"too many hops, message is looping");
+    if (errdisconnect) err_quit();
+    return;
+  }
+  if (databytes) if (!bytestooverflow) {
+    out("552 sorry, that message size exceeds my databytes limit (#5.3.4)\r\n");
+    logline(3,"datasize limit exceeded");
+    if (errdisconnect) err_quit();
+    return;
+  }
+#ifdef SMTPEXECCHECK
+  if (execcheck_flag()) {
+    out("552 we don't accept email with this MIME content (#5.3.4)\r\n");
+    logline(3,"bad MIME attachement detected");
+    if (errdisconnect) err_quit();
+    return;
+  }
+#endif
+
+  logpid(1);
+  if (*qqx == 'D') {
+    out("554 "); logstring(1,"message permanently not accepted because: ");
+  } else {
+    out("451 "); logstring(1,"message temporarly not accepted because: ");
+  }
   out(qqx + 1);
+  logstring(1,qqx + 1); logflush(1);
   out("\r\n");
 }
 
+#ifdef DATA_COMPRESS
+void smtp_dataz(char *arg)
+{
+  wantcomp = 1;
+  smtp_data((char *)0);
+}
+#endif
+
+stralloc line = {0};
+
+void smtp_auth(char *arg)
+{
+  struct call cct;
+  char *type;
+  const char *status;
+
+  if (!flagauth) {
+    err_unimpl("AUTH without STARTTLS");
+    return;
+  }
+  if (flagauthok) {
+    out("503 you are already authenticated\r\n");
+    logline(3,"reauthentication attempt rejected");
+    if (errdisconnect) err_quit();
+    return;
+  }
+#ifdef TLS_SMTPD
+  if (needssl && !ssl) {
+    out("538 Encryption required for requested authentication mechanism");
+    logline(3,"TLS encryption required for authentication");
+    if (errdisconnect) err_quit();
+    return;
+  }
+#endif
+  type = arg;
+  while (*arg != '\0' && *arg != ' ') ++arg;
+  if (*arg) {
+    *arg++ = '\0';
+    while (*arg == ' ') ++arg;
+  }
+  
+  if (case_diffs(type, "login") == 0) {
+    logline(4,"auth login");
+    if (call_open(&cct, "bin/auth_smtp", 30, 1) == -1) goto fail;
+    call_puts(&cct, "login"); call_put(&cct, "", 1);
+    if (*arg) {
+      call_puts(&cct, arg); call_put(&cct, "", 1);
+    } else {
+      out("334 VXNlcm5hbWU6\r\n"); flush(); /* base64 for 'Username:' */
+      if (call_getln(&ssin, &line) == -1) die_read();
+      call_puts(&cct, line.s); call_put(&cct, "", 1);
+    }
+    out("334 UGFzc3dvcmQ6\r\n"); flush(); /* base64 for 'Password:' */
+    if (call_getln(&ssin, &line) == -1) die_read();
+    call_puts(&cct, line.s); call_putflush(&cct, "", 1);
+  } else if (case_diffs(type, "plain") == 0) {
+    logline(4,"auth plain");
+    if (call_open(&cct, "bin/auth_smtp", 30, 1) == -1) goto fail;
+    call_puts(&cct, "plain"); call_put(&cct, "", 1);
+    if (*arg) {
+      call_puts(&cct, arg); call_putflush(&cct, "", 1);
+    } else {
+      out("334 \r\n"); flush();
+      if (call_getln(&ssin, &line) == -1) die_read();
+      call_puts(&cct, line.s); call_putflush(&cct, "", 1);
+    }
+  } else {
+    out("504 authentication type not supported\r\n");
+    logstring(3,"authentication type ");
+    logstring(3,type);
+    logstring(3,": not supported");
+    logflush(3);
+    if (errdisconnect) err_quit();
+    return;
+  }
+fail:
+  status = auth_close(&cct, &line, authprepend);
+  switch (*status) {
+  case '2':
+    flagauthok = 1;
+    remoteinfo = line.s;
+    out(status);
+    logline2(2,"authentication success, user ", remoteinfo);
+    break;
+  case '4':
+  case '5':
+    sleep(1);
+    out(status); flush();
+    logline2(3, "authentication failed: ", status + 4);
+    sleep(4);
+    if (errdisconnect) err_quit();
+    break;
+  }
+}
+
+#ifdef TLS_SMTPD
+RSA *tmp_rsa_cb(SSL *s,int export,int keylength) 
+{
+  RSA* rsa;
+  BIO* in;
+
+  if (!export || keylength == 512)
+   if ((in=BIO_new(BIO_s_file_internal())))
+    if (BIO_read_filename(in,"control/rsa512.pem") > 0)
+     if ((rsa=PEM_read_bio_RSAPrivateKey(in,NULL,NULL,NULL)))
+      return rsa;
+  return (RSA_generate_key(export?keylength:512,RSA_F4,NULL,NULL));
+}
+
+void smtp_tls(char *arg) 
+{
+  SSL_CTX *ctx;
+
+  if (sslcert.s == 0 || *sslcert.s == '\0') {
+    err_unimpl("STARTTLS");
+    return;
+  }
+
+  if (*arg)
+  {
+    out("501 Syntax error (no parameters allowed) (#5.5.4)\r\n");
+    logline(3,"aborting TLS negotiations, no parameters to starttls allowed");
+    return;
+  }
+
+  SSLeay_add_ssl_algorithms();
+  if(!(ctx=SSL_CTX_new(SSLv23_server_method())))
+  {
+    out("454 TLS not available: unable to initialize ctx (#4.3.0)\r\n"); 
+    logline(3,"aborting TLS negotiations, "
+      "unable to initialize local SSL context");
+    return;
+  }
+  if(!SSL_CTX_use_RSAPrivateKey_file(ctx, sslcert.s, SSL_FILETYPE_PEM))
+  {
+    out("454 TLS not available: missing RSA private key (#4.3.0)\r\n");
+    logline2(3,"aborting TLS negotiations, "
+      "RSA private key invalid or unable to read ", sslcert.s);
+    return;
+  }
+  if(!SSL_CTX_use_certificate_chain_file(ctx, sslcert.s))
+  {
+    out("454 TLS not available: missing certificate (#4.3.0)\r\n"); 
+    logline2(3,"aborting TLS negotiations, "
+      "local cert invalid or unable to read ", sslcert.s);
+    return;
+  }
+  SSL_CTX_set_tmp_rsa_callback(ctx, tmp_rsa_cb);
+ 
+  out("220 ready for tls\r\n"); flush();
+
+  if(!(ssl=SSL_new(ctx))) 
+  {
+    logline(3,"aborting TLS connection, unable to set up SSL session");
+    die_read();
+  }
+  SSL_set_rfd(ssl,substdio_fileno(&ssin));
+  SSL_set_wfd(ssl,substdio_fileno(&ssout));
+  if(SSL_accept(ssl)<=0)
+  {
+    logline(3,"aborting TLS connection, unable to finish SSL accept");
+    die_read();
+  }
+  //substdio_fdbuf(&ssout,SSL_write,ssl,ssoutbuf,sizeof(ssoutbuf));
+
+  remotehost = env_get("TCPREMOTEHOST");
+  if (!remotehost) remotehost = "unknown";
+  dohelo(remotehost);
+}
+#endif
+
+void cleanup(void)
+{
+	ldaplookupdone();
+}
+
+void err_503or421(char *arg)
+{
+  if (greeting421)
+    out("421 Service temporarily not available (#4.3.2)\r\n");
+  else
+    out("503 bad sequence of commands (#5.5.1)\r\n");
+  if (errdisconnect) err_quit();
+}
+void err_badcommand(char *arg)
+{
+  out("503 bad sequence of commands (#5.5.1)\r\n");
+}
+
 struct commands smtpcommands[] = {
   { "rcpt", smtp_rcpt, 0 }
 , { "mail", smtp_mail, 0 }
@@ -403,19 +1711,54 @@
 , { "ehlo", smtp_ehlo, flush }
 , { "rset", smtp_rset, 0 }
 , { "help", smtp_help, flush }
+#ifdef TLS_SMTPD
+, { "starttls", smtp_tls, flush }
+#endif
+#ifdef DATA_COMPRESS
+, { "dataz", smtp_dataz, flush }
+#endif
+, { "auth", smtp_auth, flush }
 , { "noop", err_noop, flush }
 , { "vrfy", err_vrfy, flush }
 , { 0, err_unimpl, flush }
 } ;
 
-void main()
+struct commands smtprestricted[] = {
+  { "quit", smtp_quit, flush }
+, { "helo", err_503or421, flush }
+, { "ehlo", err_503or421, flush }
+, { 0, err_badcommand, flush }
+};
+
+int main(int argc, char **argv)
 {
+#ifdef TLS_SMTPD
+  sig_alarmcatch(sigalrm);
+#endif
   sig_pipeignore();
   if (chdir(auto_qmail) == -1) die_control();
   setup();
   if (ipme_init() != 1) die_ipme();
+  if (greeting550 || greeting421) {
+    if (!stralloc_copys(&greeting,greeting550 ? greeting550 : greeting421))
+      die_nomem();
+    timeout = 20; /* reduce timeout so the abuser is kicked out faster */
+    if (greeting.len == 0 && greeting550)
+      stralloc_copys(&greeting,
+	  "Sorry, your mail was administratively denied. (#5.7.1)");
+    else if (greeting.len == 0 && greeting421)
+      stralloc_copys(&greeting,
+	  "Service temporarily not available (#4.3.2)");
+
+    smtp_line(greeting550 ? "554 " : "421 ");
+    if (errdisconnect) err_quit();
+    if (commands(&ssin,smtprestricted) == 0) die_read();
+    die_nomem();
+  }
   smtp_greet("220 ");
-  out(" ESMTP\r\n");
-  if (commands(&ssin,&smtpcommands) == 0) die_read();
+  if (commands(&ssin,smtpcommands) == 0) die_read();
   die_nomem();
+  /* NOTREACHED */
+  return 1;
 }
+
diff -ruN qmail-1.03-orig/qmail-smtpd.rules qmail-1.03-ldap-20060201-orig/qmail-smtpd.rules
--- qmail-1.03-orig/qmail-smtpd.rules	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/qmail-smtpd.rules	2006-02-25 11:00:55.000000000 +0100
@@ -0,0 +1,29 @@
+#
+# SMTP server rules.
+# Default rule is to accept mails but not to relay. Do not even think of setting
+# RELAYCLIENT on the default rule.
+# Other useful stuff:
+#  AUTHPREPEND: String that is prepended to the login in the received line
+#  AUTHREQUIRED: Allow sending of messages only from authenticated senders.
+#  BLOCKRELAYPROBE: reject recipients with and "!", "%" or double-"@"
+#  LDAPSOFTOK: Ignore ldap soft errors in RCPTCHECK and SENDERCHECK
+#  LOGLEVEL: Level of log verbosity
+#  MAXRCPTCOUNT: maximum number of RCPT TOs you accept
+#  NOBOUNCE: Rejects null sender bounces, use only in extreme cases
+#  NOPBS: Disable pop-befor-smtp feature (pbscheck).
+#  QMAILQUEUE: alternate mail queueing program
+#  RBL: If set turns on rbl checking.
+#  RBLONLYHEADER: only tag messages filtered by rbl checking.
+#  RCPTCHECK: Check if the recipient of a message really exists.
+#  REJECTEXEC: Reject DOS/Windows executables in mail attachements.
+#  RETURNMXCHECK: Rejects senders if they don't have a valid return MX.
+#  SANITYCHECK: Rejects senders without an @, no . or too long/short TLD
+#  SENDERCHECK: Check if the sender of a message really exists.
+#  SMTPAUTH: Enables SMTP-AUTH for remote clients.
+#  550GREETING: Rejects a connection right away with an 550 error
+#  SMTP550DISCONNECT: Disconnect the SMTP session if a 5xx error happens
+#  TARPITCOUNT: number of RCPT TOs you accept before you start tarpitting.
+#  TARPITDELAY: number of seconds of delay to introduce while tarpitting
+#
+#192.168.0.:allow,RELAYCLIENT=""
+:allow
diff -ruN qmail-1.03-orig/qmail-smtpd.sh qmail-1.03-ldap-20060201-orig/qmail-smtpd.sh
--- qmail-1.03-orig/qmail-smtpd.sh	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/qmail-smtpd.sh	2006-02-25 11:00:55.000000000 +0100
@@ -0,0 +1,35 @@
+#!/bin/sh
+exec 2>&1
+#
+# SMTP service 
+#
+QMAIL="%QMAIL%"
+ME="`head -1 $QMAIL/control/me`"
+CONCURRENCY=${CONCURRENCY:=50}
+QUSER="qmaild"
+
+PATH="$QMAIL/bin:$PATH"
+
+# source the environemt in ./env
+eval `env - PATH=$PATH envdir ./env awk '\
+	BEGIN { for (i in ENVIRON) \
+		if (i != "PATH") { \
+			printf "export %s=\"%s\"\\n", i, ENVIRON[i] \
+		} \
+	}'`
+
+# enforce some sane defaults
+QUSER=${QUSER:="qmaild"}
+PBSTOOL=${PBSTOOL:="$QMAIL/bin/pbscheck"}
+
+if [ X${NOPBS+"true"} = X"true" ]; then
+	unset PBSTOOL
+fi
+
+exec \
+	envuidgid $QUSER \
+	tcpserver -v -URl $ME -x$QMAIL/control/qmail-smtpd.cdb \
+	    ${CONCURRENCY:+"-c$CONCURRENCY"} ${BACKLOG:+"-b$BACKLOG"} 0 smtp \
+	$PBSTOOL \
+	$QMAIL/bin/qmail-smtpd
+
diff -ruN qmail-1.03-orig/qmail-start.c qmail-1.03-ldap-20060201-orig/qmail-start.c
--- qmail-1.03-orig/qmail-start.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/qmail-start.c	2006-02-25 11:00:55.000000000 +0100
@@ -1,13 +1,19 @@
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
 #include "fd.h"
 #include "prot.h"
 #include "exit.h"
 #include "fork.h"
 #include "auto_uids.h"
 
-char *(qsargs[]) = { "qmail-send", 0 };
-char *(qcargs[]) = { "qmail-clean", 0 };
-char *(qlargs[]) = { "qmail-lspawn", "./Mailbox", 0 };
-char *(qrargs[]) = { "qmail-rspawn", 0 };
+const char *(qsargs[]) = { "qmail-send", 0 };
+const char *(qcargs[]) = { "qmail-clean", 0 };
+const char *(qlargs[]) = { "qmail-lspawn", "./Mailbox", 0 };
+const char *(qrargs[]) = { "qmail-rspawn", 0 };
+#ifdef EXTERNAL_TODO
+const char *(qtargs[]) = { "qmail-todo", 0};
+#endif
 
 void die() { _exit(111); }
 
@@ -18,16 +24,31 @@
 int pi4[2];
 int pi5[2];
 int pi6[2];
-
-void close23456() { close(2); close(3); close(4); close(5); close(6); }
+#ifdef EXTERNAL_TODO
+int pi7[2];
+int pi8[2];
+int pi9[2];
+int pi10[2];
+#endif
+
+void close23456() { 
+  close(2); close(3); close(4); close(5); close(6); 
+#ifdef EXTERNAL_TODO
+  close(7); close(8);
+#endif
+}
 
 void closepipes() {
   close(pi1[0]); close(pi1[1]); close(pi2[0]); close(pi2[1]);
   close(pi3[0]); close(pi3[1]); close(pi4[0]); close(pi4[1]);
   close(pi5[0]); close(pi5[1]); close(pi6[0]); close(pi6[1]);
+#ifdef EXTERNAL_TODO
+  close(pi7[0]); close(pi7[1]); close(pi8[0]); close(pi8[1]);
+	close(pi9[0]); close(pi9[1]); close(pi10[0]); close(pi10[1]);
+#endif
 }
 
-void main(argc,argv)
+int main(argc,argv)
 int argc;
 char **argv;
 {
@@ -40,6 +61,10 @@
   if (fd_copy(4,0) == -1) die();
   if (fd_copy(5,0) == -1) die();
   if (fd_copy(6,0) == -1) die();
+#ifdef EXTERNAL_TODO
+  if (fd_copy(7,0) == -1) die();
+  if (fd_copy(8,0) == -1) die();
+#endif
 
   if (argv[1]) {
     qlargs[1] = argv[1];
@@ -70,6 +95,12 @@
   if (pipe(pi4) == -1) die();
   if (pipe(pi5) == -1) die();
   if (pipe(pi6) == -1) die();
+#ifdef EXTERNAL_TODO
+  if (pipe(pi7) == -1) die();
+  if (pipe(pi8) == -1) die();
+  if (pipe(pi9) == -1) die();
+  if (pipe(pi10) == -1) die();
+#endif
  
   switch(fork()) {
     case -1: die();
@@ -78,7 +109,7 @@
       if (fd_copy(1,pi2[1]) == -1) die();
       close23456();
       closepipes();
-      execvp(*qlargs,qlargs);
+      execvp(*qlargs,(char **)qlargs);
       die();
   }
  
@@ -90,7 +121,7 @@
       if (fd_copy(1,pi4[1]) == -1) die();
       close23456();
       closepipes();
-      execvp(*qrargs,qrargs);
+      execvp(*qrargs,(char **)qrargs);
       die();
   }
  
@@ -102,9 +133,37 @@
       if (fd_copy(1,pi6[1]) == -1) die();
       close23456();
       closepipes();
-      execvp(*qcargs,qcargs);
+      execvp(*qcargs,(char **)qcargs);
+      die();
+  }
+
+#ifdef EXTERNAL_TODO
+  switch(fork()) {
+    case -1: die();
+    case 0:
+      if (prot_uid(auto_uids) == -1) die();
+      if (fd_copy(0,pi7[0]) == -1) die();
+      if (fd_copy(1,pi8[1]) == -1) die();
+      close23456();
+      if (fd_copy(2,pi9[1]) == -1) die();
+      if (fd_copy(3,pi10[0]) == -1) die();
+      closepipes();
+      execvp(*qtargs,(char **)qtargs);
+      die();
+  }
+
+  switch(fork()) {
+    case -1: die();
+    case 0:
+      if (prot_uid(auto_uidq) == -1) die();
+      if (fd_copy(0,pi9[0]) == -1) die();
+      if (fd_copy(1,pi10[1]) == -1) die();
+      close23456();
+      closepipes();
+      execvp(*qcargs,(char **)qcargs);
       die();
   }
+#endif
  
   if (prot_uid(auto_uids) == -1) die();
   if (fd_copy(0,1) == -1) die();
@@ -114,7 +173,11 @@
   if (fd_copy(4,pi4[0]) == -1) die();
   if (fd_copy(5,pi5[1]) == -1) die();
   if (fd_copy(6,pi6[0]) == -1) die();
+#ifdef EXTERNAL_TODO
+  if (fd_copy(7,pi7[1]) == -1) die();
+  if (fd_copy(8,pi8[0]) == -1) die();
+#endif
   closepipes();
-  execvp(*qsargs,qsargs);
-  die();
+  execvp(*qsargs,(char **)qsargs);
+  return 111;
 }
diff -ruN qmail-1.03-orig/qmail-tcpok.c qmail-1.03-ldap-20060201-orig/qmail-tcpok.c
--- qmail-1.03-orig/qmail-tcpok.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/qmail-tcpok.c	2006-02-25 11:00:55.000000000 +0100
@@ -1,3 +1,4 @@
+#include <unistd.h>
 #include "strerr.h"
 #include "substdio.h"
 #include "lock.h"
@@ -11,10 +12,10 @@
 char buf[1024]; /* XXX: must match size in tcpto_clean.c, tcpto.c */
 substdio ss;
 
-void main()
+int main()
 {
   int fd;
-  int i;
+  unsigned int i;
 
   if (chdir(auto_qmail) == -1)
     strerr_die4sys(111,FATAL,"unable to chdir to ",auto_qmail,": ");
@@ -27,9 +28,9 @@
   if (lock_ex(fd) == -1)
     strerr_die4sys(111,FATAL,"unable to lock ",auto_qmail,"/queue/lock/tcpto: ");
 
-  substdio_fdbuf(&ss,write,fd,buf,sizeof buf);
+  substdio_fdbuf(&ss,subwrite,fd,buf,sizeof buf);
   for (i = 0;i < sizeof buf;++i) substdio_put(&ss,"",1);
   if (substdio_flush(&ss) == -1)
     strerr_die4sys(111,FATAL,"unable to clear ",auto_qmail,"/queue/lock/tcpto: ");
-  _exit(0);
+  return 0;
 }
diff -ruN qmail-1.03-orig/qmail-tcpto.c qmail-1.03-ldap-20060201-orig/qmail-tcpto.c
--- qmail-1.03-orig/qmail-tcpto.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/qmail-tcpto.c	2006-02-25 11:00:55.000000000 +0100
@@ -1,5 +1,6 @@
 /* XXX: this program knows quite a bit about tcpto's internals */
 
+#include <unistd.h>
 #include "substdio.h"
 #include "subfd.h"
 #include "auto_qmail.h"
@@ -10,12 +11,15 @@
 #include "exit.h"
 #include "datetime.h"
 #include "now.h"
+#include "open.h"
+#include "readwrite.h"
+#include "byte.h"
 
 void die(n) int n; { substdio_flush(subfdout); _exit(n); }
 
-void warn(s) char *s;
+void warn(s) const char *s;
 {
- char *x;
+ const char *x;
  x = error_str(errno);
  substdio_puts(subfdout,s);
  substdio_puts(subfdout,": ");
@@ -32,7 +36,7 @@
 
 char tmp[FMT_ULONG + IPFMT];
 
-void main()
+int main()
 {
  int fdlock;
  int fd;
@@ -82,4 +86,6 @@
   }
 
  die(0);
+ /* NOTREACHED */
+ return 0;
 }
diff -ruN qmail-1.03-orig/qmail-todo.c qmail-1.03-ldap-20060201-orig/qmail-todo.c
--- qmail-1.03-orig/qmail-todo.c	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/qmail-todo.c	2006-02-25 11:00:55.000000000 +0100
@@ -0,0 +1,814 @@
+/*
+ * Copyright (c) 2002-2004 Andre Oppermann, Claudio Jeker,
+ *      Internet Business Solutions AG, CH-8005 Zürich, Switzerland
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Internet Business
+ *      Solutions AG and its contributors.
+ * 4. Neither the name of the author nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <string.h>
+#include <unistd.h>
+#include "alloc.h"
+#include "auto_qmail.h"
+#include "byte.h"
+#include "case.h"
+#include "cdb.h"
+#include "constmap.h"
+#include "control.h"
+#include "direntry.h"
+#include "error.h"
+#include "exit.h"
+#include "fmt.h"
+#include "fmtqfn.h"
+#include "getln.h"
+#include "open.h"
+#include "ndelay.h"
+#include "now.h"
+#include "readsubdir.h"
+#include "readwrite.h"
+#include "scan.h"
+#include "select.h"
+#include "sig.h"
+#include "str.h"
+#include "stralloc.h"
+#include "substdio.h"
+#include "trigger.h"
+
+/* critical timing feature #1: if not triggered, do not busy-loop */
+/* critical timing feature #2: if triggered, respond within fixed time */
+/* important timing feature: when triggered, respond instantly */
+#define SLEEP_TODO 1500 /* check todo/ every 25 minutes in any case */
+#define SLEEP_FUZZ 1 /* slop a bit on sleeps to avoid zeno effect */
+#define SLEEP_FOREVER 86400 /* absolute maximum time spent in select() */
+#define SLEEP_SYSFAIL 123
+
+stralloc percenthack = {0};
+struct constmap mappercenthack;
+stralloc locals = {0};
+struct constmap maplocals;
+stralloc vdoms = {0};
+struct constmap mapvdoms;
+stralloc envnoathost = {0};
+
+char strnum[FMT_ULONG];
+
+/* XXX not good, if qmail-send.c changes this has to be updated */
+#define CHANNELS 2
+const char *chanaddr[CHANNELS] = { "local/", "remote/" };
+
+datetime_sec recent;
+
+void log1(const char *);
+void log3(const char *, const char *, const char *);
+
+int flagstopasap = 0;
+void sigterm(void)
+{
+  if (flagstopasap == 0)
+    log1("status: qmail-todo stop processing asap\n");
+  flagstopasap = 1;
+}
+
+int flagreadasap = 0; void sighup(void) { flagreadasap = 1; }
+int flagsendalive = 1; void senddied(void) { flagsendalive = 0; }
+
+void nomem(void) { log1("alert: out of memory, sleeping...\n"); sleep(10); }
+void pausedir(const char *dir)
+{ log3("alert: unable to opendir ",dir,", sleeping...\n"); sleep(10); }
+
+void cleandied(void)
+{ 
+  log1("alert: qmail-todo: oh no! lost qmail-clean connection! dying...\n");
+  flagstopasap = 1;
+}
+
+
+/* this file is not so long ------------------------------------- FILENAMES */
+
+stralloc fn = {0};
+
+void fnmake_init(void)
+{
+ while (!stralloc_ready(&fn,FMTQFN)) nomem();
+}
+
+void fnmake_info(unsigned long id) { fn.len = fmtqfn(fn.s,"info/",id,1); }
+#ifndef BIGTODO
+void fnmake_todo(unsigned long id) { fn.len = fmtqfn(fn.s,"todo/",id,0); }
+#else
+void fnmake_todo(unsigned long id) { fn.len = fmtqfn(fn.s,"todo/",id,1); }
+#endif
+void fnmake_mess(unsigned long id) { fn.len = fmtqfn(fn.s,"mess/",id,1); }
+void fnmake_chanaddr(unsigned long id, int c)
+{ fn.len = fmtqfn(fn.s,chanaddr[c],id,1); }
+
+
+/* this file is not so long ------------------------------------- REWRITING */
+
+stralloc localscdb = {0};
+stralloc rwline = {0};
+struct cdb cdb;
+
+/* 1 if by land, 2 if by sea, 0 if out of memory. not allowed to barf. */
+/* may trash recip. must set up rwline, between a T and a \0. */
+int rewrite(char *recip)
+{
+  unsigned int i;
+  unsigned int j;
+  unsigned int at;
+  const char *x;
+  static stralloc addr = {0};
+
+  if (!stralloc_copys(&rwline,"T")) return 0;
+  if (!stralloc_copys(&addr,recip)) return 0;
+
+  i = byte_rchr(addr.s,addr.len,'@');
+  if (i == addr.len) {
+    if (!stralloc_cats(&addr,"@")) return 0;
+    if (!stralloc_cat(&addr,&envnoathost)) return 0;
+  }
+
+  while (constmap(&mappercenthack,addr.s + i + 1,addr.len - i - 1)) {
+    j = byte_rchr(addr.s,i,'%');
+    if (j == i) break;
+    addr.len = i;
+    i = j;
+    addr.s[i] = '@';
+  }
+
+  at = byte_rchr(addr.s,addr.len,'@');
+
+  if (localscdb.s && localscdb.len > 1) {
+    static stralloc lowaddr = {0};
+    int fd, r;
+    uint32 dlen;
+
+    if (!stralloc_copyb(&lowaddr,addr.s + at + 1,addr.len - at - 1)) return 0;
+    case_lowerb(lowaddr.s, lowaddr.len);
+    fd = open_read(localscdb.s);
+    if (fd == -1) return 0;
+    cdb_init(&cdb, fd);
+    r = cdb_seek(&cdb, lowaddr.s,lowaddr.len, &dlen);
+    cdb_free(&cdb);
+    close(fd);
+    if (r == -1) return 0;
+    if (r == 1) {
+      if (!stralloc_cat(&rwline,&addr)) return 0;
+      if (!stralloc_0(&rwline)) return 0;
+      return 1;
+    }
+  } else
+    if (constmap(&maplocals,addr.s + at + 1,addr.len - at - 1)) {
+      if (!stralloc_cat(&rwline,&addr)) return 0;
+      if (!stralloc_0(&rwline)) return 0;
+      return 1;
+    }
+
+  for (i = 0; i <= addr.len;++i)
+    if (!i || i == at + 1 || i == addr.len ||
+	(i > at && addr.s[i] == '.'))
+      if ((x = constmap(&mapvdoms,addr.s + i,addr.len - i))) {
+        if (!*x) break;
+        if (!stralloc_cats(&rwline,x)) return 0;
+        if (!stralloc_cats(&rwline,"-")) return 0;
+        if (!stralloc_cat(&rwline,&addr)) return 0;
+        if (!stralloc_0(&rwline)) return 0;
+        return 1;
+      }
+ 
+  if (!stralloc_cat(&rwline,&addr)) return 0;
+  if (!stralloc_0(&rwline)) return 0;
+  return 2;
+}
+
+/* this file is not so long --------------------------------- COMMUNICATION */
+
+substdio sstoqc; char sstoqcbuf[1024];
+substdio ssfromqc; char ssfromqcbuf[1024];
+stralloc comm_buf = {0};
+unsigned int comm_pos;
+int fdout = -1;
+int fdin = -1;
+
+void comm_init(void)
+{
+ substdio_fdbuf(&sstoqc,subwrite,2,sstoqcbuf,sizeof(sstoqcbuf));
+ substdio_fdbuf(&ssfromqc,subread,3,ssfromqcbuf,sizeof(ssfromqcbuf));
+
+ fdout = 1; /* stdout */
+ fdin = 0;  /* stdin */
+ if (ndelay_on(fdout) == -1)
+ /* this is so stupid: NDELAY semantics should be default on write */
+   senddied(); /* drastic, but better than risking deadlock */
+
+ while (!stralloc_ready(&comm_buf,1024)) nomem();
+}
+
+int comm_canwrite(void)
+{
+ /* XXX: could allow a bigger buffer; say 10 recipients */
+ /* XXX: returns true if there is something in the buffer */
+ if (!flagsendalive) return 0;
+ if (comm_buf.s && comm_buf.len) return 1;
+ return 0;
+}
+
+void log1(const char* x)
+{
+  unsigned int pos;
+  
+  pos = comm_buf.len;
+  if (!stralloc_cats(&comm_buf,"L")) goto fail;
+  if (!stralloc_cats(&comm_buf,x)) goto fail;
+  if (!stralloc_0(&comm_buf)) goto fail;
+  return;
+  
+fail:
+  /* either all or nothing */
+  comm_buf.len = pos;
+}
+
+void log3(const char *x, const char *y, const char *z)
+{
+  unsigned int pos;
+  
+  pos = comm_buf.len;
+  if (!stralloc_cats(&comm_buf,"L")) goto fail;
+  if (!stralloc_cats(&comm_buf,x)) goto fail;
+  if (!stralloc_cats(&comm_buf,y)) goto fail;
+  if (!stralloc_cats(&comm_buf,z)) goto fail;
+  if (!stralloc_0(&comm_buf)) goto fail;
+  return;
+  
+fail:
+  /* either all or nothing */
+  comm_buf.len = pos;
+}
+
+void comm_write(unsigned long id, int local, int remote)
+{
+  unsigned int pos;
+  const char *s;
+  
+  if (local && remote) s="B";
+  else if (local) s="L";
+  else if (remote) s="R";
+  else s="X";
+  
+  pos = comm_buf.len;
+  strnum[fmt_ulong(strnum,id)] = 0;
+  if (!stralloc_cats(&comm_buf,"D")) goto fail;
+  if (!stralloc_cats(&comm_buf,s)) goto fail;
+  if (!stralloc_cats(&comm_buf,strnum)) goto fail;
+  if (!stralloc_0(&comm_buf)) goto fail;
+  return;
+  
+fail:
+  /* either all or nothing */
+  comm_buf.len = pos;
+}
+
+static int issafe(char ch)
+{
+ if (ch == '%') return 0; /* general principle: allman's code is crap */
+ if (ch < 33) return 0;
+ if (ch > 126) return 0;
+ return 1;
+}
+
+void comm_info(unsigned long id, unsigned long size, char* from, unsigned long pid, unsigned long uid)
+{
+  unsigned int pos;
+  unsigned int i;
+  
+  pos = comm_buf.len;
+  if (!stralloc_cats(&comm_buf,"Linfo msg ")) goto fail;
+  strnum[fmt_ulong(strnum,id)] = 0;
+  if (!stralloc_cats(&comm_buf,strnum)) goto fail;
+  if (!stralloc_cats(&comm_buf,": bytes ")) goto fail;
+  strnum[fmt_ulong(strnum,size)] = 0;
+  if (!stralloc_cats(&comm_buf,strnum)) goto fail;
+  if (!stralloc_cats(&comm_buf," from <")) goto fail;
+  i = comm_buf.len;
+  if (!stralloc_cats(&comm_buf,from)) goto fail;
+  for (;i < comm_buf.len;++i)
+    if (comm_buf.s[i] == '\n')
+      comm_buf.s[i] = '/';
+    else
+      if (!issafe(comm_buf.s[i]))
+	comm_buf.s[i] = '_';
+  if (!stralloc_cats(&comm_buf,"> qp ")) goto fail;
+  strnum[fmt_ulong(strnum,pid)] = 0;
+  if (!stralloc_cats(&comm_buf,strnum)) goto fail;
+  if (!stralloc_cats(&comm_buf," uid ")) goto fail;
+  strnum[fmt_ulong(strnum,uid)] = 0;
+  if (!stralloc_cats(&comm_buf,strnum)) goto fail;
+  if (!stralloc_cats(&comm_buf,"\n")) goto fail;
+  if (!stralloc_0(&comm_buf)) goto fail;
+  return;
+  
+fail:
+  /* either all or nothing */
+  comm_buf.len = pos;
+}
+
+void comm_exit(void)
+{
+  /* if it fails exit, we have already stoped */
+  if (!stralloc_cats(&comm_buf,"X")) _exit(1);
+  if (!stralloc_0(&comm_buf)) _exit(1);
+}
+
+void comm_selprep(int *nfds, fd_set *wfds, fd_set *rfds)
+{
+  if (flagsendalive) {
+    if (flagstopasap && comm_canwrite() == 0)
+      comm_exit();
+    if (comm_canwrite()) {
+      FD_SET(fdout,wfds);
+      if (*nfds <= fdout)
+	*nfds = fdout + 1;
+    }
+    FD_SET(fdin,rfds);
+    if (*nfds <= fdin)
+      *nfds = fdin + 1;
+  }
+}
+
+void comm_do(fd_set *wfds, fd_set *rfds)
+{
+  /* first write then read */
+  if (flagsendalive)
+    if (comm_canwrite())
+      if (FD_ISSET(fdout,wfds)) {
+	int w;
+	unsigned int len;
+	len = comm_buf.len;
+	w = subwrite(fdout, comm_buf.s + comm_pos,len - comm_pos);
+	if (w <= 0) {
+	  if ((w == -1) && (errno == error_pipe))
+	    senddied();
+	} else {
+	  comm_pos += w;
+	  if (comm_pos == len) {
+	    comm_buf.len = 0;
+	    comm_pos = 0;
+	  }
+	}
+      }
+  if (flagsendalive)
+    if (FD_ISSET(fdin,rfds)) {
+      /* there are only two messages 'H' and 'X' */
+      char c;
+      int r;
+      r = read(fdin, &c, 1);
+      if (r <= 0) {
+	if (r != -1 || errno != error_intr)
+	  senddied();
+      } else {
+	switch(c) {
+	  case 'H':
+	    sighup();
+	    break;
+	  case 'X':
+	    sigterm();
+	    break;
+	  default:
+	    log1("warning: qmail-todo: qmail-send speaks an obscure dialect\n");
+	    break;
+	}
+      }
+    }
+}
+
+/* this file is not so long ------------------------------------------ TODO */
+
+datetime_sec nexttodorun;
+#ifndef BIGTODO
+DIR *tododir; /* if 0, have to opendir again */
+#else
+int flagtododir = 0; /* if 0, have to readsubdir_init again */
+readsubdir todosubdir;
+#endif
+stralloc todoline = {0};
+char todobuf[SUBSTDIO_INSIZE];
+char todobufinfo[512];
+char todobufchan[CHANNELS][1024];
+
+void todo_init(void)
+{
+#ifndef BIGTODO
+ tododir = 0;
+#else
+ flagtododir = 0;
+#endif
+ nexttodorun = now();
+ trigger_set();
+}
+
+void todo_selprep(int *nfds, fd_set *rfds, datetime_sec *wakeup)
+{
+ if (flagstopasap) return;
+ trigger_selprep(nfds,rfds);
+#ifndef BIGTODO
+ if (tododir) *wakeup = 0;
+#else
+ if (flagtododir) *wakeup = 0;
+#endif
+ if (*wakeup > nexttodorun) *wakeup = nexttodorun;
+}
+
+void todo_do(fd_set *rfds)
+{
+ struct stat st;
+ substdio ss; int fd;
+ substdio ssinfo; int fdinfo;
+ substdio sschan[CHANNELS];
+ int fdchan[CHANNELS];
+ int flagchan[CHANNELS];
+ char ch;
+ int match;
+ unsigned long id;
+#ifndef BIGTODO
+ unsigned int len;
+ direntry *d;
+#endif
+ int c;
+ unsigned long uid;
+ unsigned long pid;
+
+ fd = -1;
+ fdinfo = -1;
+ for (c = 0;c < CHANNELS;++c) fdchan[c] = -1;
+
+ if (flagstopasap) return;
+
+#ifndef BIGTODO
+ if (!tododir)
+#else
+ if (!flagtododir)
+#endif
+  {
+   if (!trigger_pulled(rfds))
+     if (recent < nexttodorun)
+       return;
+   trigger_set();
+#ifndef BIGTODO
+   tododir = opendir("todo");
+   if (!tododir)
+    {
+     pausedir("todo");
+     return;
+    }
+#else
+   readsubdir_init(&todosubdir, "todo", pausedir);
+   flagtododir = 1;
+#endif
+   nexttodorun = recent + SLEEP_TODO;
+  }
+
+#ifndef BIGTODO
+ d = readdir(tododir);
+ if (!d)
+  {
+   closedir(tododir);
+   tododir = 0;
+   return;
+  }
+ if (str_equal(d->d_name,".")) return;
+ if (str_equal(d->d_name,"..")) return;
+ len = scan_ulong(d->d_name,&id);
+ if (!len || d->d_name[len]) return;
+#else
+ switch(readsubdir_next(&todosubdir, &id))
+  {
+   case 1: break;
+   case 0: flagtododir = 0;
+   default: return;
+  }
+#endif
+
+ fnmake_todo(id);
+
+ fd = open_read(fn.s);
+ if (fd == -1) { log3("warning: qmail-todo: unable to open ",fn.s,"\n"); return; }
+
+ fnmake_mess(id);
+ /* just for the statistics */
+ if (stat(fn.s,&st) == -1)
+  { log3("warning: qmail-todo: unable to stat ",fn.s,"\n"); goto fail; }
+
+ for (c = 0;c < CHANNELS;++c)
+  {
+   fnmake_chanaddr(id,c);
+   if (unlink(fn.s) == -1) if (errno != error_noent)
+    { log3("warning: qmail-todo: unable to unlink ",fn.s,"\n"); goto fail; }
+  }
+
+ fnmake_info(id);
+ if (unlink(fn.s) == -1) if (errno != error_noent)
+  { log3("warning: qmail-todo: unable to unlink ",fn.s,"\n"); goto fail; }
+
+ fdinfo = open_excl(fn.s);
+ if (fdinfo == -1)
+  { log3("warning: qmail-todo: unable to create ",fn.s,"\n"); goto fail; }
+
+ strnum[fmt_ulong(strnum,id)] = 0;
+ log3("new msg ",strnum,"\n");
+
+ for (c = 0;c < CHANNELS;++c) flagchan[c] = 0;
+
+ substdio_fdbuf(&ss,subread,fd,todobuf,sizeof(todobuf));
+ substdio_fdbuf(&ssinfo,subwrite,fdinfo,todobufinfo,sizeof(todobufinfo));
+
+ uid = 0;
+ pid = 0;
+
+ for (;;)
+  {
+   if (getln(&ss,&todoline,&match,'\0') == -1)
+    {
+     /* perhaps we're out of memory, perhaps an I/O error */
+     fnmake_todo(id);
+     log3("warning: qmail-todo: trouble reading ",fn.s,"\n"); goto fail;
+    }
+   if (!match) break;
+
+   switch(todoline.s[0])
+    {
+     case 'u':
+       scan_ulong(todoline.s + 1,&uid);
+       break;
+     case 'p':
+       scan_ulong(todoline.s + 1,&pid);
+       break;
+     case 'F':
+       if (substdio_putflush(&ssinfo,todoline.s,todoline.len) == -1)
+	{
+	 fnmake_info(id);
+         log3("warning: qmail-todo: trouble writing to ",fn.s,"\n"); goto fail;
+	}
+	comm_info(id, (unsigned long) st.st_size, todoline.s + 1, pid, uid);
+       break;
+     case 'T':
+       switch(rewrite(todoline.s + 1))
+	{
+	 case 0: nomem(); goto fail;
+	 case 2: c = 1; break;
+	 default: c = 0; break;
+        }
+       if (fdchan[c] == -1)
+	{
+	 fnmake_chanaddr(id,c);
+	 fdchan[c] = open_excl(fn.s);
+	 if (fdchan[c] == -1)
+          { log3("warning: qmail-todo: unable to create ",fn.s,"\n"); goto fail; }
+	 substdio_fdbuf(&sschan[c],
+	     subwrite,fdchan[c],todobufchan[c],sizeof(todobufchan[c]));
+	 flagchan[c] = 1;
+	}
+       if (substdio_bput(&sschan[c],rwline.s,rwline.len) == -1)
+        {
+	 fnmake_chanaddr(id,c);
+         log3("warning: qmail-todo: trouble writing to ",fn.s,"\n"); goto fail;
+        }
+       break;
+     default:
+       fnmake_todo(id);
+       log3("warning: qmail-todo: unknown record type in ",fn.s,"\n"); goto fail;
+    }
+  }
+
+ close(fd); fd = -1;
+
+ fnmake_info(id);
+ if (substdio_flush(&ssinfo) == -1)
+  { log3("warning: qmail-todo: trouble writing to ",fn.s,"\n"); goto fail; }
+ if (fsync(fdinfo) == -1)
+  { log3("warning: qmail-todo: trouble fsyncing ",fn.s,"\n"); goto fail; }
+ close(fdinfo); fdinfo = -1;
+
+ for (c = 0;c < CHANNELS;++c)
+   if (fdchan[c] != -1)
+    {
+     fnmake_chanaddr(id,c);
+     if (substdio_flush(&sschan[c]) == -1)
+      { log3("warning: qmail-todo: trouble writing to ",fn.s,"\n"); goto fail; }
+     if (fsync(fdchan[c]) == -1)
+      { log3("warning: qmail-todo: trouble fsyncing ",fn.s,"\n"); goto fail; }
+     close(fdchan[c]); fdchan[c] = -1;
+    }
+
+ fnmake_todo(id);
+ if (substdio_putflush(&sstoqc,fn.s,fn.len) == -1) { cleandied(); return; }
+ if (substdio_get(&ssfromqc,&ch,1) != 1) { cleandied(); return; }
+ if (ch != '+')
+  {
+   log3("warning: qmail-clean unable to clean up ",fn.s,"\n");
+   return;
+  }
+
+ comm_write(id, flagchan[0], flagchan[1]);
+ 
+ return;
+ 
+ fail:
+ if (fd != -1) close(fd);
+ if (fdinfo != -1) close(fdinfo);
+ for (c = 0;c < CHANNELS;++c)
+   if (fdchan[c] != -1) close(fdchan[c]);
+}
+
+/* this file is too long ---------------------------------------------- MAIN */
+
+int getcontrols(void)
+{
+ struct stat st;
+ 
+ if (control_init() == -1) return 0;
+ if (control_rldef(&envnoathost,"control/envnoathost",1,"envnoathost") != 1) return 0;
+ 
+ if (stat("control/locals.cdb", &st) == 0) {
+   if (!stralloc_copys(&localscdb, auto_qmail)) return 0;
+   if (!stralloc_cats(&localscdb, "/control/locals.cdb")) return 0;
+   if (!stralloc_0(&localscdb)) return 0;
+   if (!constmap_init(&maplocals,"",0,1)) return 0;
+ } else {
+   if (control_readfile(&locals,"control/locals",1) != 1) return 0;
+   if (!constmap_init(&maplocals,locals.s,locals.len,0)) return 0;
+ }
+
+ switch(control_readfile(&percenthack,"control/percenthack",0))
+  {
+   case -1: return 0;
+   case 0: if (!constmap_init(&mappercenthack,"",0,0)) return 0; break;
+   case 1: if (!constmap_init(&mappercenthack,percenthack.s,percenthack.len,0)) return 0; break;
+  }
+ switch(control_readfile(&vdoms,"control/virtualdomains",0))
+  {
+   case -1: return 0;
+   case 0: if (!constmap_init(&mapvdoms,"",0,1)) return 0; break;
+   case 1: if (!constmap_init(&mapvdoms,vdoms.s,vdoms.len,1)) return 0; break;
+  }
+ return 1;
+}
+
+stralloc newlocals = {0};
+stralloc newvdoms = {0};
+
+void regetcontrols(void)
+{
+ struct stat st;
+ int r;
+
+ if (stat("control/locals.cdb", &st) == 0) {
+   while (!stralloc_copys(&localscdb, auto_qmail)) nomem();
+   while (!stralloc_cats(&localscdb, "/control/locals.cdb")) nomem();
+   while  (!stralloc_0(&localscdb)) nomem();
+   
+   constmap_free(&maplocals);
+   while (!constmap_init(&maplocals,"",0,1)) nomem();
+ } else {
+   if (control_readfile(&newlocals,"control/locals",1) != 1)
+    { log1("alert: qmail-todo: unable to reread control/locals\n"); return; }
+   
+   while (!stralloc_copys(&localscdb, "")) nomem();
+   
+   constmap_free(&maplocals);
+   while (!stralloc_copy(&locals,&newlocals)) nomem();
+   while (!constmap_init(&maplocals,locals.s,locals.len,0)) nomem();
+ }
+ 
+ r = control_readfile(&newvdoms,"control/virtualdomains",0);
+ if (r == -1)
+  { log1("alert: qmail-todo: unable to reread control/virtualdomains\n"); return; }
+
+ constmap_free(&mapvdoms);
+
+ if (r)
+  {
+   while (!stralloc_copy(&vdoms,&newvdoms)) nomem();
+   while (!constmap_init(&mapvdoms,vdoms.s,vdoms.len,1)) nomem();
+  }
+ else
+   while (!constmap_init(&mapvdoms,"",0,1)) nomem();
+}
+
+void reread(void)
+{
+ if (chdir(auto_qmail) == -1)
+  {
+   log1("alert: qmail-todo: unable to reread controls: unable to switch to home directory\n");
+   return;
+  }
+ regetcontrols();
+ while (chdir("queue") == -1)
+  {
+   log1("alert: qmail-todo: unable to switch back to queue directory; HELP! sleeping...\n");
+   sleep(10);
+  }
+}
+
+int main()
+{
+ datetime_sec wakeup;
+ fd_set rfds;
+ fd_set wfds;
+ int nfds;
+ struct timeval tv;
+ int r;
+ char c;
+
+ if (chdir(auto_qmail) == -1)
+  { log1("alert: qmail-todo: cannot start: unable to switch to home directory\n"); _exit(111); }
+ if (!getcontrols())
+  { log1("alert: qmail-todo: cannot start: unable to read controls\n"); _exit(111); }
+ if (chdir("queue") == -1)
+  { log1("alert: qmail-todo: cannot start: unable to switch to queue directory\n"); _exit(111); }
+ sig_pipeignore();
+ umask(077);
+
+ fnmake_init();
+
+ todo_init();
+ comm_init();
+ 
+ do {
+   r = read(fdin, &c, 1);
+   if ((r == -1) && (errno != error_intr))
+     _exit(100); /* read failed probably qmail-send died */
+   if (r == 0) /* Uh-oh, qmail-send died. */
+     _exit(100);
+ } while (r != 1); /* we assume it is a 'S' */
+ 
+ for (;;)
+  {
+   recent = now();
+
+   if (flagreadasap) { flagreadasap = 0; reread(); }
+   if (!flagsendalive) {
+     /* qmail-send finaly exited, so do the same. */
+     if (flagstopasap) _exit(0);
+     /*
+      * qmail-send died.
+      * We can not log and we can not work therefor _exit(1).
+      */
+     _exit(1);
+   }
+
+   wakeup = recent + SLEEP_FOREVER;
+   FD_ZERO(&rfds);
+   FD_ZERO(&wfds);
+   nfds = 1;
+
+   todo_selprep(&nfds,&rfds,&wakeup);
+   comm_selprep(&nfds,&wfds,&rfds);
+
+   if (wakeup <= recent) tv.tv_sec = 0;
+   else tv.tv_sec = wakeup - recent + SLEEP_FUZZ;
+   tv.tv_usec = 0;
+
+   if (select(nfds,&rfds,&wfds,(fd_set *) 0,&tv) == -1)
+     if (errno == error_intr)
+       ;
+     else
+       log1("warning: qmail-todo: trouble in select\n");
+   else
+    {
+     recent = now();
+
+     todo_do(&rfds);
+     comm_do(&wfds, &rfds);
+    }
+  }
+  /* NOTREACHED */
+  return 1;
+}
+
diff -ruN qmail-1.03-orig/qmail-verify.c qmail-1.03-ldap-20060201-orig/qmail-verify.c
--- qmail-1.03-orig/qmail-verify.c	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/qmail-verify.c	2006-02-25 11:00:55.000000000 +0100
@@ -0,0 +1,445 @@
+/*
+ * Copyright (c) 2003-2004 Claudio Jeker,
+ *      Internet Business Solutions AG, CH-8005 Zürich, Switzerland
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Internet Business
+ *      Solutions AG and its contributors.
+ * 4. Neither the name of the author nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <pwd.h>
+#include <unistd.h>
+#include "auto_break.h"
+#include "byte.h"
+#include "case.h"
+#include "cdb.h"
+#include "error.h"
+#include "getln.h"
+#include "localdelivery.h"
+#include "open.h"
+#include "output.h"
+#include "qldap.h"
+#include "qldap-debug.h"
+#include "qldap-errno.h"
+#include "qmail-ldap.h"
+#include "read-ctrl.h"
+#include "str.h"
+#include "stralloc.h"
+#include "subfd.h"
+#include "substdio.h"
+#include "timeoutread.h"
+
+struct qldap *q;
+
+void cleanup(void);
+void
+die_read(void)
+{
+	cleanup();
+	_exit(1);
+}
+void
+die_write(void)
+{
+	cleanup();
+	_exit(1);
+}
+void
+die_nomem(void)
+{
+	cleanup();
+	if (substdio_puts(subfdout, "ZOut of memory in qmail-verify.") == -1)
+		die_write();
+	if (substdio_putflush(subfdout, "", 1) == -1)
+		die_write();
+	_exit(111);
+}
+void
+die_timeout(void)
+{
+	cleanup();
+	_exit(111);
+}
+void
+die_temp(void)
+{
+	cleanup();
+	_exit(111);
+}
+void
+die_control(void)
+{
+	_exit(100);
+}
+void
+temp_fail(void)
+{
+	if (substdio_putflush(subfdout, "Z", 2) == -1)
+		die_write();
+	qldap_free_results(q);
+}
+
+int
+temp_sys(void)
+{
+	if (substdio_puts(subfdout,
+	    "ZTemporary failure in qmail-verify.") == -1)
+		die_write();
+	if (substdio_putflush(subfdout, "", 1) == -1)
+		die_write();
+	return -1;
+}
+
+int
+temp_nfs(void)
+{
+	if (substdio_puts(subfdout, "ZNFS failure in qmail-verify.") == -1)
+		die_write();
+	if (substdio_putflush(subfdout, "", 1) == -1)
+		die_write();
+	return -1;
+}
+
+void
+die_cdb(void)
+{
+	if (substdio_puts(subfdout,
+	    "ZTrouble reading users/cdb in qmail-verify.") == -1)
+		die_write();
+	if (substdio_putflush(subfdout, "", 1) == -1)
+		die_write();
+	_exit(111);
+}
+
+int lookup(stralloc *);
+int lookup_cdb(const char *);
+int lookup_passwd(const char *);
+
+
+int timeout = 5;
+int
+saferead(int fd, void *buf, int len)
+{
+	return timeoutread(timeout,fd,buf,len);
+}
+
+char ssinbuf[512];
+substdio ssin = SUBSTDIO_FDBUF(saferead,0,ssinbuf,sizeof ssinbuf);
+
+stralloc line = {0};
+ctrlfunc	ctrls[] = {
+		qldap_ctrl_trylogin,
+		qldap_ctrl_generic,
+		localdelivery_init,
+		0 };
+
+int
+main(int argc, char **argv)
+{
+	int match;
+	unsigned int at;
+
+	log_init(STDERR, ~256, 0);
+
+	if (read_controls(ctrls) == -1)
+		die_control();
+	
+	q = 0;
+	do {
+		if (getln(&ssin, &line, &match, '\0') != 0) {
+			if (errno != error_timeout)
+				die_read();
+			cleanup();
+			continue;
+		}
+		if (!match) {
+			cleanup(); /* other side closed pipe */
+			break;
+		}
+
+		logit(32, "qmail-verfiy: verifying %S\n", &line);
+
+		at = byte_rchr(line.s,line.len,'@');
+		if (at >= line.len) {
+			if (substdio_puts(subfdout, "DSorry, address must "
+			    "include host name. (#5.1.3)") == -1)
+				die_write();
+			if (substdio_putflush(subfdout, "", 1) == -1)
+				die_write();
+			continue;
+		}
+
+		switch (lookup(&line)) {
+		case 0:
+			if (localdelivery()) {
+				/*
+				 * Do the local address lookup.
+				 */
+				line.s[at] = '\0';
+				if (lookup_cdb(line.s) == 1)
+					break;
+				if (lookup_passwd(line.s) == 1)
+					break;
+			}
+			/* Sorry, no mailbox here by that name. */
+			if (substdio_puts(subfdout,
+			    "DSorry, no mailbox here by that name. "
+			    "(#5.1.1)") == -1)
+				die_write();
+			if (substdio_putflush(subfdout, "", 1) == -1)
+				die_write();
+			break;
+		case 1:
+		default:
+			break;
+		}
+	} while (1);
+
+	return 0;
+}
+
+int
+lookup(stralloc *mail)
+{
+	const char *attrs[] = {  LDAP_ISACTIVE, 0 };
+	char *f;
+	int done;
+	int status;
+	int rv;
+
+	if (q == 0) {
+		q = qldap_new();
+		if (q == 0)
+			die_nomem();
+
+		rv = qldap_open(q);
+		if (rv != OK) die_temp();
+		rv = qldap_bind(q, 0, 0);
+		if (rv != OK) die_temp();
+	}
+	
+	/*
+	 * this handles the "catch all" and "-default" extension 
+	 * but also the normal eMail address.
+	 * Code handels also mail addresses with multiple '@' safely.
+	 * at = index to last @ sign in mail address
+	 * escaped = ldap escaped mailaddress
+	 * len = length of escaped mailaddress
+	 * i = position of current '-' or '@'
+	 */
+	done = 0;
+	do {
+		f = filter_mail(mail->s, &done);
+		if (f == (char *)0) die_nomem();
+
+		logit(16, "ldapfilter: '%s'\n", f);
+
+		/* do the search for the email address */
+		rv = qldap_lookup(q, f, attrs);
+		switch (rv) {
+		case OK:
+			break; /* something found */
+		case TIMEOUT:
+			/* temporary error but give up so that the
+			 * ldap server can recover */
+			die_timeout();
+		case TOOMANY:
+#ifdef DUPEALIAS
+			if (substdio_putflush(subfdout, "K", 1) == -1)
+				die_write();
+			qldap_free_results(q);
+#else
+			/* admin error, also temporary */
+			temp_fail();
+#endif
+			return (-1);
+		case FAILED:
+			/* ... again temporary */
+			temp_fail();
+			return (-1);
+		case NOSUCH:
+			break;
+		}
+	} while (rv != OK && !done);
+	/* reset filter_mail */
+	filter_mail(0, 0);
+
+	/* nothing found, try a local lookup or a alias delivery */
+	if (rv == NOSUCH) {
+		qldap_free_results(q);
+		return (0);
+	}
+
+	/* check if the ldap entry is active */
+	rv = qldap_get_status(q, &status);
+	if (rv != OK) {
+		temp_fail();
+		return (-1);
+	}
+	if (status == STATUS_BOUNCE) {
+		/* Mailaddress is administratively disabled. (#5.2.1) */
+		if (substdio_puts(subfdout,
+			    "DMailaddress is administratively disabled. "
+			    "(#5.2.1)") == -1)
+			die_write();
+		if (substdio_putflush(subfdout, "", 1) == -1)
+			die_write();
+		qldap_free_results(q);
+		return (1);
+	} else if (status == STATUS_DELETE) {
+		/* Sorry, no mailbox here by that name. (#5.1.1) */
+		if (substdio_puts(subfdout,
+			    "DSorry, no mailbox here by that name. "
+			    "(#5.1.1)") == -1)
+			die_write();
+		if (substdio_putflush(subfdout, "", 1) == -1)
+			die_write();
+		qldap_free_results(q);
+		return (1);
+	}
+
+	/* OK */
+	if (substdio_putflush(subfdout, "K", 1) == -1)
+		die_write();
+	qldap_free_results(q);
+	return (1);
+}
+
+void
+cleanup(void)
+{
+	if (q != 0)
+		qldap_free(q);
+	q = 0;
+}
+
+stralloc lower = {0};
+stralloc wildchars = {0};
+struct cdb cdb;
+
+int
+lookup_cdb(const char *mail)
+{
+	int	fd;
+	int	flagwild;
+	int	r;
+
+	if (!stralloc_copys(&lower, "!")) die_nomem();
+	if (!stralloc_cats(&lower, mail)) die_nomem();
+	if (!stralloc_0(&lower)) die_nomem();
+	case_lowerb(lower.s, lower.len);
+
+	fd = open_read("users/cdb");
+	if (fd == -1)
+		if (errno != error_noent)
+			die_cdb();
+
+	if (fd != -1) {
+		uint32 dlen;
+		unsigned int i;
+
+		cdb_init(&cdb, fd);
+		r = cdb_seek(&cdb, "", 0, &dlen);
+		if (r != 1)
+			die_cdb();
+
+		if (!stralloc_ready(&wildchars, (unsigned int) dlen))
+			die_nomem();
+		wildchars.len = dlen;
+		if (cdb_bread(&cdb, wildchars.s, wildchars.len) == -1)
+			die_cdb();
+
+		i = lower.len;
+		flagwild = 0;
+
+		do {
+			/* i > 0 */
+			if (!flagwild || i == 1 || byte_chr(wildchars.s,
+			    wildchars.len, lower.s[i - 1]) < wildchars.len) {
+				r = cdb_seek(&cdb,lower.s,i,&dlen);
+				if (r == -1)
+					die_cdb();
+				if (r == 1) {
+					/* OK */
+					if (substdio_putflush(subfdout, "K",
+					    1) == -1)
+						die_write();
+					
+					cdb_free(&cdb);
+					close(fd);
+					return (1);
+				}
+			}
+			--i;
+			flagwild = 1;
+		} while (i);
+
+		close(fd);
+	}
+	return (0);
+}
+
+#define GETPW_USERLEN 32
+
+int
+lookup_passwd(const char *local)
+{
+	char username[GETPW_USERLEN];
+	struct stat st;
+	const char *extension;
+	struct passwd *pw;
+
+
+	extension = local + str_len(local);
+	for (; extension >= local; extension--) {
+		if ((unsigned long)(extension - local) < sizeof(username))
+			if (!*extension || (*extension == *auto_break)) {
+				byte_copy(username, extension - local, local);
+				username[extension - local] = 0;
+				case_lowers(username);
+				errno = 0;
+				pw = getpwnam(username);
+				if (errno == error_txtbsy)
+					return temp_sys();
+				if (pw && pw->pw_uid != 0) {
+					if (stat(pw->pw_dir,&st) == 0 &&
+					    st.st_uid == pw->pw_uid) {
+						/* OK */
+						if (substdio_putflush(subfdout,
+						    "K", 1) == -1)
+							die_write();
+						return (1);
+					} else if (error_temp(errno))
+						return temp_nfs();
+				}
+			}
+	}
+	return (0);
+}
+
diff -ruN qmail-1.03-orig/qreceipt.c qmail-1.03-ldap-20060201-orig/qreceipt.c
--- qmail-1.03-orig/qreceipt.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/qreceipt.c	2006-02-25 11:00:56.000000000 +0100
@@ -60,7 +60,7 @@
 
 void finishheader()
 {
- char *qqx;
+ const char *qqx;
 
  if (!flagreceipt) die_noreceipt();
  if (str_equal(returnpath,"")) die_noreceipt();
@@ -92,9 +92,10 @@
  qmail_to(&qqt,returnpath);
  qqx = qmail_close(&qqt);
 
- if (*qqx)
+ if (*qqx) {
    if (*qqx == 'D') die_qqperm();
    else die_qqtemp();
+ }
 }
 
 stralloc hfbuf = {0};
@@ -119,7 +120,7 @@
 
 void dobody(h) stralloc *h; { ; }
 
-void main(argc,argv)
+int main(argc,argv)
 int argc;
 char **argv;
 {
@@ -128,4 +129,6 @@
  if (!(returnpath = env_get("SENDER"))) die_usage();
  if (headerbody(subfdin,doheaderfield,finishheader,dobody) == -1) die_read();
  die_noreceipt();
+ /* NOTREACHED */
+ return 0;
 }
diff -ruN qmail-1.03-orig/qsmhook.c qmail-1.03-ldap-20060201-orig/qsmhook.c
--- qmail-1.03-orig/qsmhook.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/qsmhook.c	2006-02-25 11:00:56.000000000 +0100
@@ -1,3 +1,4 @@
+#include <unistd.h>
 #include "fd.h"
 #include "stralloc.h"
 #include "readwrite.h"
@@ -35,7 +36,7 @@
 substdio ssin;
 char inbuf[SUBSTDIO_INSIZE];
 
-void main(argc,argv)
+int main(argc,argv)
 int argc;
 char **argv;
 {
@@ -45,7 +46,7 @@
  int opt;
  char **arg;
  char *x;
- int i;
+ unsigned int i;
  int flagesc;
 
  sig_pipeignore();
@@ -78,7 +79,7 @@
 
  if (!*argv) die_usage();
 
- for (arg = argv;x = *arg;++arg)
+ for (arg = argv;(x = *arg);++arg)
   {
    if (!stralloc_copys(&newarg,"")) die_temp();
    flagesc = 0;
@@ -122,8 +123,8 @@
   }
  close(pi[0]);
 
- substdio_fdbuf(&ssout,write,pi[1],outbuf,sizeof(outbuf));
- substdio_fdbuf(&ssin,read,0,inbuf,sizeof(inbuf));
+ substdio_fdbuf(&ssout,subwrite,pi[1],outbuf,sizeof(outbuf));
+ substdio_fdbuf(&ssin,subread,0,inbuf,sizeof(inbuf));
  if (flagufline) substdio_bputs(&ssout,ufline);
  if (flagrpline) substdio_bputs(&ssout,rpline);
  if (flagdtline) substdio_bputs(&ssout,dtline);
@@ -133,5 +134,5 @@
 
  if (wait_pid(&wstat,pid) == -1) die_temp();
  if (wait_crashed(wstat)) die_temp();
- _exit(wait_exitcode(wstat));
+ return wait_exitcode(wstat);
 }
diff -ruN qmail-1.03-orig/qsutil.c qmail-1.03-ldap-20060201-orig/qsutil.c
--- qmail-1.03-orig/qsutil.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/qsutil.c	2006-02-25 11:00:56.000000000 +0100
@@ -1,3 +1,4 @@
+#include <unistd.h>
 #include "stralloc.h"
 #include "readwrite.h"
 #include "substdio.h"
@@ -6,22 +7,22 @@
 static stralloc foo = {0};
 
 static char errbuf[1];
-static struct substdio sserr = SUBSTDIO_FDBUF(write,0,errbuf,1);
+static struct substdio sserr = SUBSTDIO_FDBUF(subwrite,0,errbuf,1);
 
 void logsa(sa) stralloc *sa; {
  substdio_putflush(&sserr,sa->s,sa->len); }
-void log1(s1) char *s1; {
+void log1(s1) const char *s1; {
  substdio_putsflush(&sserr,s1); }
-void log2(s1,s2) char *s1; char *s2; {
+void log2(s1,s2) const char *s1; const char *s2; {
  substdio_putsflush(&sserr,s1);
  substdio_putsflush(&sserr,s2); }
-void log3(s1,s2,s3) char *s1; char *s2; char *s3; {
+void log3(s1,s2,s3) const char *s1; const char *s2; const char *s3; {
  substdio_putsflush(&sserr,s1);
  substdio_putsflush(&sserr,s2);
  substdio_putsflush(&sserr,s3); }
-void nomem() { log1("alert: out of memory, sleeping...\n"); sleep(10); }
+void nomem(void) { log1("alert: out of memory, sleeping...\n"); sleep(10); }
 
-void pausedir(dir) char *dir;
+void pausedir(dir) const char *dir;
 { log3("alert: unable to opendir ",dir,", sleeping...\n"); sleep(10); }
 
 static int issafe(ch) char ch;
@@ -32,11 +33,11 @@
  return 1;
 }
 
-void logsafe(s) char *s;
+void logsafe(s) const char *s;
 {
- int i;
+ unsigned int i;
  while (!stralloc_copys(&foo,s)) nomem();
- for (i = 0;i < foo.len;++i)
+ for (i = 0; i < foo.len;++i)
    if (foo.s[i] == '\n')
      foo.s[i] = '/';
    else
diff -ruN qmail-1.03-orig/qsutil.h qmail-1.03-ldap-20060201-orig/qsutil.h
--- qmail-1.03-orig/qsutil.h	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/qsutil.h	2006-02-25 11:00:56.000000000 +0100
@@ -1,12 +1,12 @@
 #ifndef QSUTIL_H
 #define QSUTIL_H
 
-extern void log1();
-extern void log2();
-extern void log3();
-extern void logsa();
-extern void nomem();
-extern void pausedir();
-extern void logsafe();
+extern void log1(const char *);
+extern void log2(const char *, const char *);
+extern void log3(const char *, const char *, const char *);
+extern void logsa(stralloc *);
+extern void nomem(void);
+extern void pausedir(const char *);
+extern void logsafe(const char *);
 
 #endif
diff -ruN qmail-1.03-orig/quote.c qmail-1.03-ldap-20060201-orig/quote.c
--- qmail-1.03-orig/quote.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/quote.c	2006-02-25 11:00:56.000000000 +0100
@@ -9,7 +9,7 @@
 no special encoding here for bytes above 127.
 */
 
-static char ok[128] = {
+static const char ok[128] = {
  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
 ,0,7,0,7,7,7,7,7,0,0,7,7,0,7,7,7 ,7,7,7,7,7,7,7,7,7,7,0,0,0,7,0,7
 ,0,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7 ,7,7,7,7,7,7,7,7,7,7,7,0,0,0,7,7
@@ -21,8 +21,8 @@
 stralloc *sain;
 {
  char ch;
- int i;
- int j;
+ unsigned int i;
+ unsigned int j;
 
  if (!stralloc_ready(saout,sain->len * 2 + 2)) return 0;
  j = 0;
@@ -40,11 +40,11 @@
 }
 
 int quote_need(s,n)
-char *s;
+const char *s;
 unsigned int n;
 {
  unsigned char uch;
- int i;
+ unsigned int i;
  if (!n) return 1;
  for (i = 0;i < n;++i)
   {
@@ -70,9 +70,9 @@
 
 int quote2(sa,s)
 stralloc *sa;
-char *s;
+const char *s;
 {
- int j;
+ unsigned int j;
  if (!*s) return stralloc_copys(sa,s);
  j = str_rchr(s,'@');
  if (!stralloc_copys(&foo,s)) return 0;
diff -ruN qmail-1.03-orig/quote.h qmail-1.03-ldap-20060201-orig/quote.h
--- qmail-1.03-orig/quote.h	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/quote.h	2006-02-25 11:00:56.000000000 +0100
@@ -1,8 +1,10 @@
 #ifndef QUOTE_H
 #define QUOTE_H
 
-extern int quote_need();
-extern int quote();
-extern int quote2();
+#include "stralloc.h"
+
+extern int quote_need(const char *, unsigned int);
+extern int quote(stralloc *, stralloc *);
+extern int quote2(stralloc *, const char *);
 
 #endif
diff -ruN qmail-1.03-orig/rbl.c qmail-1.03-ldap-20060201-orig/rbl.c
--- qmail-1.03-orig/rbl.c	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/rbl.c	2006-02-25 11:00:56.000000000 +0100
@@ -0,0 +1,261 @@
+/*
+ * Copyright (c) 2002-2004 Andre Oppermann,
+ *      Internet Business Solutions AG, CH-8005 Zürich, Switzerland
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Internet Business
+ *      Solutions AG and its contributors.
+ * 4. Neither the name of the author nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#include "alloc.h"
+#include "control.h"
+#include "dns.h"
+#include "env.h"
+#include "ipalloc.h"
+#include "qmail.h"
+#include "str.h"
+#include "stralloc.h"
+
+#include "rbl.h"
+
+static stralloc rblmessage = {0};
+int rblprintheader = 0;
+
+/* functions borrowed from qmail-smtpd.c */
+extern void safeput();
+extern void die_nomem();
+
+extern void logpid();
+extern void logline();
+extern void logstring();
+extern void logflush();
+
+void rblheader(struct qmail *qqt)
+{
+  if (!rblprintheader) return;
+  /* rblmessage is safe because it does not contain any remote info */
+  if (rblmessage.s) qmail_put(qqt,rblmessage.s,rblmessage.len);
+}
+
+struct rbl {
+  char *baseaddr;
+  char *action;
+  char *matchon;
+  char *message;
+} *rbl;
+
+unsigned int numrbl;
+
+static stralloc ip_reverse = {0};
+static stralloc rbl_tmp = {0};
+
+static int rbl_start(const char *remoteip)
+{
+  unsigned int i;
+  unsigned int j;
+  const char *ip_env;
+
+  ip_env = remoteip;
+  if (!ip_env) ip_env = "";
+
+  if (!stralloc_copys(&ip_reverse,"")) die_nomem();
+
+  i = str_len(ip_env);
+  while (i) {
+    for (j = i;j > 0;--j) {
+      if (ip_env[j - 1] == '.') break;
+      if (ip_env[j - 1] == ':') return 0; /* no IPv6 */
+    }
+    if (!stralloc_catb(&ip_reverse,ip_env + j,i - j)) die_nomem();
+    if (!stralloc_cats(&ip_reverse,".")) die_nomem();
+    if (!j) break;
+    i = j - 1;
+  }
+  return 1;
+}
+
+static char ipstr[IPFMT];
+
+static int rbl_lookup(char *base, char *matchon)
+{
+  ipalloc rblsa = {0};
+  unsigned int i;
+
+  if (!*base) return 2;
+
+  if (!stralloc_copy(&rbl_tmp,&ip_reverse)) die_nomem();
+  if (!stralloc_cats(&rbl_tmp,base)) die_nomem();
+
+  switch (dns_ip(&rblsa,&rbl_tmp)) {
+    case DNS_MEM:
+    case DNS_SOFT:
+      return 2; /* soft error */
+    case DNS_HARD:
+      return 0; /* found no match */
+    default: /* found match */
+      if (!str_diff("any", matchon))
+        return 1;
+      for (i = 0;i < rblsa.len;++i)
+      {
+	ipstr[ip_fmt(ipstr,&rblsa.ix[i].ip)]=0;
+	if (!str_diff(ipstr, matchon)) return 1;
+      }
+      return 0; /* found match but ignored */
+  }
+  return 1; /* should never get here */
+}
+
+void rbladdheader(char *base, char *matchon, char *message)
+{
+  /* all of base, matchon and message can be trusted because these
+     are under our control */
+  rblprintheader = 1;
+  if(!stralloc_cats(&rblmessage, "X-RBL: (")) die_nomem();
+  if(!stralloc_cats(&rblmessage, base)) die_nomem();
+  if(!stralloc_cats(&rblmessage, ") ")) die_nomem();
+  if (str_diff("any", matchon)) {
+    if(!stralloc_cats(&rblmessage, "matches with ")) die_nomem();
+    if(!stralloc_cats(&rblmessage, matchon)) die_nomem();
+    if(!stralloc_cats(&rblmessage, " and ")) die_nomem();
+  }
+  if(!stralloc_cats(&rblmessage, "tells us ")) die_nomem();
+  if(!stralloc_cats(&rblmessage, message)) die_nomem();
+  if(!stralloc_cats(&rblmessage, "\n")) die_nomem();
+}
+
+void
+rbllog(int level, const char* baseaddr, const char *msg)
+{
+	logpid(level);
+	logstring(level, "RBL check with '");
+	logstring(level, baseaddr);
+	logstring(level, "': ");
+	logstring(level, msg);
+        logflush(level);
+}
+
+int rblcheck(const char *remoteip, char** rblname, int rbloh)
+{
+  int r = 1;
+  unsigned int i;
+
+  if(!stralloc_copys(&rblmessage, "")) die_nomem();
+  if(!rbl_start(remoteip)) return 0;
+
+  for (i=0; i < numrbl; i++) {
+    r = rbl_lookup(rbl[i].baseaddr, rbl[i].matchon);
+
+    if (r == 2) {
+      rbllog(3,rbl[i].baseaddr, "temporary DNS error, ignored");
+    } else if (r == 1) {
+      *rblname = rbl[i].message;
+      if (rbloh) {
+        rbllog(3,rbl[i].baseaddr, "found match, tag header");
+	rbladdheader(rbl[i].baseaddr, rbl[i].matchon, rbl[i].message);
+	continue;
+      }
+      if (!str_diff("addheader", rbl[i].action)) {
+        rbllog(3,rbl[i].baseaddr, "found match, tag header");
+	rbladdheader(rbl[i].baseaddr, rbl[i].matchon, rbl[i].message);
+	continue;
+      } else {
+	/* default reject */
+        rbllog(2,rbl[i].baseaddr, "found match, reject sender");
+	rblprintheader = 0;
+	return 1;
+      }
+    }
+    /* continue */
+    rbllog(3,rbl[i].baseaddr, "no match found, continue.");
+  }
+  return 0; /* either tagged, soft error or allowed */
+}
+
+stralloc rbldata = {0};
+
+int rblinit(void)
+{
+  char** x;
+  int on;
+  unsigned int i;
+  unsigned int j;
+  unsigned int k;
+  unsigned int n;
+
+  on = control_readfile(&rbldata,"control/rbllist",0);
+  if (on == -1) return on;
+  if (!on) return on;
+
+  for(i=0, numrbl=0; i < rbldata.len; ++i)
+    if (rbldata.s[i] == '\0')
+	++numrbl;
+
+  rbl = (struct rbl*)alloc(numrbl*sizeof(struct rbl));
+  if (!rbl) return -1;
+
+  /* line format is "basedomain action matchon message"
+     message may have spaces */
+  x = (char **)&rbl[0];
+  for (i=0, j=0, k=0, n=0; i < rbldata.len; ++i) {
+    while (1) {
+      /* hop over spaces */
+      if (rbldata.s[i] != ' ' && rbldata.s[i] != '\t') break;
+      if (rbldata.s[i] == '\0') {
+	logline(1, "parse error in rbllist, unexpected end of line");
+	return -1;
+      }
+      i++;
+    }
+    j = i;
+    if (n == 3) {
+      /* message */
+      x[n] = rbldata.s + j;
+      n = 0;
+      x = (char **)&rbl[++k];
+      while (rbldata.s[i] != '\0') i++;
+    } else {
+      while (1) {
+        /* hop over argument */
+        if (rbldata.s[i] == ' ' || rbldata.s[i] == '\t') break;
+        if (rbldata.s[i] == '\0') {
+	  logline(1, "parse error in rbllist, unexpected end of line");
+	  return -1;
+        }
+        i++;
+      }
+      rbldata.s[i] = '\0';
+      x[n++] = rbldata.s + j;
+    }
+  }
+  if (k != numrbl) {
+    logline(1,"parse error in rbllist, unexpected end of file");
+    return -1;
+  }
+
+  return 1; /* everything fine */
+}
+
diff -ruN qmail-1.03-orig/rbl.h qmail-1.03-ldap-20060201-orig/rbl.h
--- qmail-1.03-orig/rbl.h	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/rbl.h	2006-02-25 11:00:56.000000000 +0100
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2002-2004 Claudio Jeker,
+ *      Internet Business Solutions AG, CH-8005 Zürich, Switzerland
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Internet Business
+ *      Solutions AG and its contributors.
+ * 4. Neither the name of the author nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#ifndef RBL_H
+#define RBL_H
+
+#include "qmail.h"
+
+extern void rblheader(struct qmail *);
+extern int rblcheck(const char *, char **, int);
+extern int rblinit(void);
+
+#endif
diff -ruN qmail-1.03-orig/rcpthosts.c qmail-1.03-ldap-20060201-orig/rcpthosts.c
--- qmail-1.03-orig/rcpthosts.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/rcpthosts.c	2006-02-25 11:00:56.000000000 +0100
@@ -1,5 +1,6 @@
 #include "cdb.h"
 #include "byte.h"
+#include "case.h"
 #include "open.h"
 #include "error.h"
 #include "control.h"
@@ -7,54 +8,126 @@
 #include "stralloc.h"
 #include "rcpthosts.h"
 
-static int flagrh = 0;
+static int flagrh = -1;
 static stralloc rh = {0};
 static struct constmap maprh;
+static int fdlo;
+static int fdrh;
 static int fdmrh;
+static struct cdb cdblo;
+static struct cdb cdbrh;
+static struct cdb cdbmrh;
+static stralloc locals = {0};
+static struct constmap maplocals;
 
-int rcpthosts_init()
+int rcpthosts_init(void)
 {
-  flagrh = control_readfile(&rh,"control/rcpthosts",0);
-  if (flagrh != 1) return flagrh;
-  if (!constmap_init(&maprh,rh.s,rh.len,0)) return flagrh = -1;
-  fdmrh = open_read("control/morercpthosts.cdb");
-  if (fdmrh == -1) if (errno != error_noent) return flagrh = -1;
-  return 0;
+	fdlo = open_read("control/locals.cdb");
+	if (fdlo == -1) {
+		if (errno != error_noent)
+			return -1;
+		if (control_readfile(&locals,"control/locals",1) != 1)
+			return -1;
+		if (!constmap_init(&maplocals,locals.s,locals.len,0))
+			return -1;
+	} else
+		cdb_init(&cdblo, fdlo);
+
+	fdrh = open_read("control/rcpthosts.cdb");
+	if (fdrh == -1) {
+		if (errno != error_noent) return -1;
+
+		if (control_readfile(&rh,"control/rcpthosts",0) == -1)
+			return -1;
+		if (!constmap_init(&maprh,rh.s,rh.len,0))
+			return -1;
+		fdmrh = open_read("control/morercpthosts.cdb");
+		if (fdmrh == -1) {
+			if (errno != error_noent)
+				return -1;
+		} else
+			cdb_init(&cdbmrh, fdmrh);
+	} else
+		cdb_init(&cdbrh, fdrh);
+
+	flagrh = 1;
+	return 0;
 }
 
 static stralloc host = {0};
 
-int rcpthosts(buf,len)
-char *buf;
-int len;
+int localhosts(char *buf, unsigned int len)
 {
-  int j;
-
-  if (flagrh != 1) return 1;
-
-  j = byte_rchr(buf,len,'@');
-  if (j >= len) return 1; /* presumably envnoathost is acceptable */
-
-  ++j; buf += j; len -= j;
+	unsigned int j;
+	uint32 dlen;
 
-  if (!stralloc_copyb(&host,buf,len)) return -1;
-  buf = host.s;
-  case_lowerb(buf,len);
+	if (flagrh < 0) return 0;
 
-  for (j = 0;j < len;++j)
-    if (!j || (buf[j] == '.'))
-      if (constmap(&maprh,buf + j,len - j)) return 1;
-
-  if (fdmrh != -1) {
-    uint32 dlen;
-    int r;
+	j = byte_rchr(buf,len,'@');
+	if (j >= len) return 0; /* envnoathost is not acceptable */
+	++j; buf += j; len -= j;
+
+	if (!stralloc_copyb(&host,buf,len)) return -1;
+	buf = host.s;
+	case_lowerb(buf,len);
+
+	/* if local.cdb available use this as source */
+	if (fdlo != -1) 
+		return cdb_seek(&cdblo, buf, len, &dlen);
+	else   
+		if (constmap(&maplocals, buf, len)) return 1;
+	return 0;
+}
 
-    for (j = 0;j < len;++j)
-      if (!j || (buf[j] == '.')) {
-	r = cdb_seek(fdmrh,buf + j,len - j,&dlen);
-	if (r) return r;
-      }
-  }
+int rcpthosts(char *buf, unsigned int len)
+{
+	unsigned int j;
+	int r;
+	uint32 dlen;
+
+	if (flagrh < 0) return 0;	/* uh-oh init failed so fail too,
+					 * never be a open relay!
+					 */
+
+	j = byte_rchr(buf,len,'@');
+	if (j >= len) return 1; /* presumably envnoathost is acceptable */
+
+	++j; buf += j; len -= j;
+
+	if (!stralloc_copyb(&host,buf,len)) return -1;
+	buf = host.s;
+	case_lowerb(buf,len);
+
+	/* first locals */
+	/* if local.cdb available use this as source */
+	if (fdlo != -1) {
+		r = cdb_seek(&cdblo, buf, len, &dlen);
+		if (r) return r;
+	} else   
+		if (constmap(&maplocals,buf,len)) return 1;
+
+	/* then rcpthosts */
+	for (j = 0;j < len;++j)
+		if (!j || (buf[j] == '.')) {
+			/* if rcpthosts.cdb available use this as source */
+			if (fdrh != -1) {
+				r = cdb_seek(&cdbrh, buf + j, len - j, &dlen);
+				if (r)
+					return r;
+			} else
+				if (constmap(&maprh,buf + j,len - j))
+					return 1;
+		}
+	/* finaly morercpthosts.cdb but only if not rcpthosts.cdb avail */
+	if (fdmrh != -1 && fdrh == -1) {
+		for (j = 0;j < len;++j)
+			if (!j || (buf[j] == '.')) {
+				r = cdb_seek(&cdbmrh,buf + j,len - j,&dlen);
+				if (r)
+					return r;
+			}
+	}
 
-  return 0;
+	return 0;
 }
+
diff -ruN qmail-1.03-orig/rcpthosts.h qmail-1.03-ldap-20060201-orig/rcpthosts.h
--- qmail-1.03-orig/rcpthosts.h	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/rcpthosts.h	2006-02-25 11:00:56.000000000 +0100
@@ -1,7 +1,8 @@
 #ifndef RCPTHOSTS_H
 #define RCPTHOSTS_H
 
-extern int rcpthosts_init();
-extern int rcpthosts();
+extern int rcpthosts_init(void);
+extern int rcpthosts(char *, unsigned int);
+extern int localhosts(char *, unsigned int);
 
 #endif
diff -ruN qmail-1.03-orig/read-ctrl.c qmail-1.03-ldap-20060201-orig/read-ctrl.c
--- qmail-1.03-orig/read-ctrl.c	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/read-ctrl.c	2006-02-25 11:00:56.000000000 +0100
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2003-2004 Claudio Jeker,
+ *      Internet Business Solutions AG, CH-8005 Zürich, Switzerland
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Internet Business
+ *      Solutions AG and its contributors.
+ * 4. Neither the name of the author nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#include <unistd.h>
+
+#include "auto_qmail.h"
+#include "control.h"
+#include "error.h"
+#include "open.h"
+
+#include "read-ctrl.h"
+
+/* TODO logging */
+int
+read_controls(ctrlfunc *f)
+{
+	int	i, fddir;
+	
+	fddir = open_read(".");
+	if (fddir == -1)
+		return -1;
+	if (chdir(auto_qmail) == -1)
+		return -1;
+	
+	if (control_init() == -1)
+		goto fail;
+	for (i = 0; f[i] != 0; i++) {
+		if (f[i]() == -1)
+			goto fail;
+	}
+
+	if (fchdir(fddir) == -1)
+		return -1;
+	close(fddir);
+	return 0;
+	
+fail:
+	i = errno;
+	if (fchdir(fddir) == -1)
+		return -1;
+	close(fddir);
+	errno = i;
+	return -1;
+}
+
diff -ruN qmail-1.03-orig/read-ctrl.h qmail-1.03-ldap-20060201-orig/read-ctrl.h
--- qmail-1.03-orig/read-ctrl.h	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/read-ctrl.h	2006-02-25 11:00:56.000000000 +0100
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2003-2004 Claudio Jeker,
+ *      Internet Business Solutions AG, CH-8005 Zürich, Switzerland
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Internet Business
+ *      Solutions AG and its contributors.
+ * 4. Neither the name of the author nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#ifndef __READ_CTRL_H__
+#define __READ_CTRL_H__
+
+typedef int (*ctrlfunc)(void);
+
+int read_controls(ctrlfunc *);
+
+#endif
diff -ruN qmail-1.03-orig/readsubdir.c qmail-1.03-ldap-20060201-orig/readsubdir.c
--- qmail-1.03-orig/readsubdir.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/readsubdir.c	2006-02-25 11:00:56.000000000 +0100
@@ -6,7 +6,7 @@
 
 void readsubdir_init(rs,name,pause)
 readsubdir *rs;
-char *name;
+const char *name;
 void (*pause)();
 {
  rs->name = name;
@@ -31,7 +31,7 @@
    len = 0;
    len += fmt_str(namepos + len,rs->name);
    namepos[len++] = '/';
-   len += fmt_ulong(namepos + len,(unsigned long) rs->pos);
+   len += fmt_uint(namepos + len, rs->pos);
    namepos[len] = 0;
    while (!(rs->dir = opendir(namepos))) rs->pause(namepos);
    rs->pos++;
diff -ruN qmail-1.03-orig/readsubdir.h qmail-1.03-ldap-20060201-orig/readsubdir.h
--- qmail-1.03-orig/readsubdir.h	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/readsubdir.h	2006-02-25 11:00:56.000000000 +0100
@@ -6,14 +6,14 @@
 typedef struct readsubdir
  {
   DIR *dir;
-  int pos;
-  char *name;
+  unsigned int pos;
+  const char *name;
   void (*pause)();
  }
 readsubdir;
 
-extern void readsubdir_init();
-extern int readsubdir_next();
+extern void readsubdir_init(readsubdir *, const char *, void (*)());
+extern int readsubdir_next(readsubdir *, unsigned long *);
 
 #define READSUBDIR_NAMELEN 10
 
diff -ruN qmail-1.03-orig/readwrite.c qmail-1.03-ldap-20060201-orig/readwrite.c
--- qmail-1.03-orig/readwrite.c	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/readwrite.c	2006-02-25 11:00:56.000000000 +0100
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2003-2004 Claudio Jeker,
+ *      Internet Business Solutions AG, CH-8005 Zürich, Switzerland
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Internet Business
+ *      Solutions AG and its contributors.
+ * 4. Neither the name of the author nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "readwrite.h"
+
+int
+subread(int fd, void *buf, int size)
+{
+	return (int)read(fd, buf, size);
+}
+
+int
+subwrite(int fd, void *buf, int size)
+{
+	return (int)write(fd, buf, size);
+}
+
diff -ruN qmail-1.03-orig/readwrite.h qmail-1.03-ldap-20060201-orig/readwrite.h
--- qmail-1.03-orig/readwrite.h	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/readwrite.h	2006-02-25 11:00:56.000000000 +0100
@@ -1,7 +1,7 @@
 #ifndef READWRITE_H
 #define READWRITE_H
 
-extern int read();
-extern int write();
+int subread(int, void *, int);
+int subwrite(int, void *, int);
 
 #endif
diff -ruN qmail-1.03-orig/received.c qmail-1.03-ldap-20060201-orig/received.c
--- qmail-1.03-orig/received.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/received.c	2006-02-25 11:00:56.000000000 +0100
@@ -15,6 +15,10 @@
   if (ch == '=') return 1;
   if (ch == ':') return 1;
   if (ch == '-') return 1;
+  if (ch == '_') return 1;
+  if (ch == '#') return 1;
+  if (ch == ']') return 1;
+  if (ch == '[') return 1;
   if ((ch >= 'a') && (ch <= 'z')) return 1;
   if ((ch >= 'A') && (ch <= 'Z')) return 1;
   if ((ch >= '0') && (ch <= '9')) return 1;
@@ -23,10 +27,10 @@
 
 void safeput(qqt,s)
 struct qmail *qqt;
-char *s;
+const char *s;
 {
   char ch;
-  while (ch = *s++) {
+  while ((ch = *s++)) {
     if (!issafe(ch)) ch = '?';
     qmail_put(qqt,&ch,1);
   }
@@ -37,14 +41,17 @@
 /* "Received: from relay1.uu.net (HELO uunet.uu.net) (7@192.48.96.5)\n" */
 /* "  by silverton.berkeley.edu with SMTP; 26 Sep 1995 04:46:54 -0000\n" */
 
-void received(qqt,protocol,local,remoteip,remotehost,remoteinfo,helo)
+void 
+received(qqt,protocol,local,remoteip,remotehost,remoteinfo,helo,mailfrom,rcptto)
 struct qmail *qqt;
-char *protocol;
-char *local;
-char *remoteip;
-char *remotehost;
-char *remoteinfo;
-char *helo;
+const char *protocol;
+const char *local;
+const char *remoteip;
+const char *remotehost;
+const char *remoteinfo;
+const char *helo;
+const char *mailfrom;
+const char *rcptto;
 {
   struct datetime dt;
 
@@ -60,12 +67,29 @@
     safeput(qqt,remoteinfo);
     qmail_puts(qqt,"@");
   }
+  qmail_puts(qqt,"[");
   safeput(qqt,remoteip);
-  qmail_puts(qqt,")\n  by ");
+  qmail_puts(qqt,"])");
+
+  if (mailfrom) {
+    qmail_puts(qqt,"\n          (envelope-sender <");
+    safeput(qqt,mailfrom);
+    qmail_puts(qqt,">)");
+  }
+  qmail_puts(qqt,"\n          by ");
+
   safeput(qqt,local);
-  qmail_puts(qqt," with ");
+  qmail_puts(qqt," (qmail-ldap-1.03) with ");
   qmail_puts(qqt,protocol);
+
+  if (rcptto) {
+    qmail_puts(qqt,"\n          for <");
+    safeput(qqt,rcptto);
+    qmail_puts(qqt,">");
+  }
   qmail_puts(qqt,"; ");
+  
   datetime_tai(&dt,now());
   qmail_put(qqt,buf,date822fmt(buf,&dt));
 }
+
diff -ruN qmail-1.03-orig/received.h qmail-1.03-ldap-20060201-orig/received.h
--- qmail-1.03-orig/received.h	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/received.h	2006-02-25 11:00:56.000000000 +0100
@@ -1,6 +1,9 @@
 #ifndef RECEIVED_H
 #define RECEIVED_H
 
-extern void received();
+#include "qmail.h"
+
+extern void received(struct qmail *, const char *, const char *, const char *,
+    const char *, const char *, const char *, const char *, const char *);
 
 #endif
diff -ruN qmail-1.03-orig/remoteinfo.c qmail-1.03-ldap-20060201-orig/remoteinfo.c
--- qmail-1.03-orig/remoteinfo.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/remoteinfo.c	2006-02-25 11:00:56.000000000 +0100
@@ -2,6 +2,7 @@
 #include <sys/socket.h>
 #include <netinet/in.h>
 #include <fcntl.h>
+#include <unistd.h>
 #include "byte.h"
 #include "substdio.h"
 #include "ip.h"
@@ -32,7 +33,6 @@
 {
   char *x;
   int s;
-  struct sockaddr_in sin;
   substdio ss;
   char buf[32];
   unsigned int len;
@@ -44,12 +44,7 @@
   s = socket(AF_INET,SOCK_STREAM,0);
   if (s == -1) return 0;
  
-  byte_zero(&sin,sizeof(sin));
-  sin.sin_family = AF_INET;
-  byte_copy(&sin.sin_addr,4,ipl);
-  sin.sin_port = 0;
-  if (bind(s,(struct sockaddr *) &sin,sizeof(sin)) == -1) { close(s); return 0; }
-  if (timeoutconn(s,ipr,113,timeout) == -1) { close(s); return 0; }
+  if (timeoutconn(s,ipr,ipl,113,timeout) == -1) { close(s); return 0; }
   fcntl(s,F_SETFL,fcntl(s,F_GETFL,0) & ~O_NDELAY);
  
   len = 0;
diff -ruN qmail-1.03-orig/remoteinfo.h qmail-1.03-ldap-20060201-orig/remoteinfo.h
--- qmail-1.03-orig/remoteinfo.h	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/remoteinfo.h	2006-02-25 11:00:56.000000000 +0100
@@ -1,6 +1,9 @@
 #ifndef REMOTEINFO_H
 #define REMOTEINFO_H
 
-extern char *remoteinfo_get();
+struct ip_address;
+
+extern char *remoteinfo_get(struct  ip_address *, unsigned long,
+    struct ip_address *, unsigned long, int);
 
 #endif
diff -ruN qmail-1.03-orig/scan_8long.c qmail-1.03-ldap-20060201-orig/scan_8long.c
--- qmail-1.03-orig/scan_8long.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/scan_8long.c	2006-02-25 11:00:56.000000000 +0100
@@ -1,6 +1,6 @@
 #include "scan.h"
 
-unsigned int scan_8long(s,u) register char *s; register unsigned long *u;
+unsigned int scan_8long(s,u) register const char *s; register unsigned long *u;
 {
   register unsigned int pos; register unsigned long result;
   register unsigned long c;
diff -ruN qmail-1.03-orig/scan.h qmail-1.03-ldap-20060201-orig/scan.h
--- qmail-1.03-orig/scan.h	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/scan.h	2006-02-25 11:00:56.000000000 +0100
@@ -1,16 +1,22 @@
 #ifndef SCAN_H
 #define SCAN_H
 
+/* XXX not available in qmail-1.03
 extern unsigned int scan_uint();
 extern unsigned int scan_xint();
 extern unsigned int scan_nbbint();
 extern unsigned int scan_ushort();
 extern unsigned int scan_xshort();
 extern unsigned int scan_nbbshort();
-extern unsigned int scan_ulong();
+*/
+extern unsigned int scan_ulong(const char *, unsigned long *);
+/* XXX not available in qmail-1.03
 extern unsigned int scan_xlong();
 extern unsigned int scan_nbblong();
+*/
+extern unsigned int scan_8long(const char *, unsigned long *);
 
+/* XXX not available in qmail-1.03
 extern unsigned int scan_plusminus();
 extern unsigned int scan_0x();
 
@@ -23,5 +29,6 @@
 extern unsigned int scan_memcmp();
 
 extern unsigned int scan_long();
+*/
 
 #endif
diff -ruN qmail-1.03-orig/scan_ulong.c qmail-1.03-ldap-20060201-orig/scan_ulong.c
--- qmail-1.03-orig/scan_ulong.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/scan_ulong.c	2006-02-25 11:00:56.000000000 +0100
@@ -1,6 +1,6 @@
 #include "scan.h"
 
-unsigned int scan_ulong(s,u) register char *s; register unsigned long *u;
+unsigned int scan_ulong(s,u) register const char *s; register unsigned long *u;
 {
   register unsigned int pos; register unsigned long result;
   register unsigned long c;
diff -ruN qmail-1.03-orig/seek_cur.c qmail-1.03-ldap-20060201-orig/seek_cur.c
--- qmail-1.03-orig/seek_cur.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/seek_cur.c	2006-02-25 11:00:56.000000000 +0100
@@ -1,4 +1,5 @@
 #include <sys/types.h>
+#include <unistd.h>
 #include "seek.h"
 
 #define CUR 1 /* sigh */
diff -ruN qmail-1.03-orig/seek_end.c qmail-1.03-ldap-20060201-orig/seek_end.c
--- qmail-1.03-orig/seek_end.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/seek_end.c	2006-02-25 11:00:56.000000000 +0100
@@ -1,4 +1,5 @@
 #include <sys/types.h>
+#include <unistd.h>
 #include "seek.h"
 
 #define END 2 /* sigh */
diff -ruN qmail-1.03-orig/seek.h qmail-1.03-ldap-20060201-orig/seek.h
--- qmail-1.03-orig/seek.h	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/seek.h	2006-02-25 11:00:56.000000000 +0100
@@ -3,12 +3,12 @@
 
 typedef unsigned long seek_pos;
 
-extern seek_pos seek_cur();
+extern seek_pos seek_cur(int fd);
 
-extern int seek_set();
-extern int seek_end();
+extern int seek_set(int fd, seek_pos);
+extern int seek_end(int fd);
 
-extern int seek_trunc();
+extern int seek_trunc(int fd, seek_pos);
 
 #define seek_begin(fd) (seek_set((fd),(seek_pos) 0))
 
diff -ruN qmail-1.03-orig/seek_set.c qmail-1.03-ldap-20060201-orig/seek_set.c
--- qmail-1.03-orig/seek_set.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/seek_set.c	2006-02-25 11:00:56.000000000 +0100
@@ -1,4 +1,5 @@
 #include <sys/types.h>
+#include <unistd.h>
 #include "seek.h"
 
 #define SET 0 /* sigh */
diff -ruN qmail-1.03-orig/seek_trunc.c qmail-1.03-ldap-20060201-orig/seek_trunc.c
--- qmail-1.03-orig/seek_trunc.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/seek_trunc.c	2006-02-25 11:00:56.000000000 +0100
@@ -1,4 +1,5 @@
 #include <sys/types.h>
+#include <unistd.h>
 #include "seek.h"
 
 int seek_trunc(fd,pos) int fd; seek_pos pos;
diff -ruN qmail-1.03-orig/select.h2 qmail-1.03-ldap-20060201-orig/select.h2
--- qmail-1.03-orig/select.h2	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/select.h2	2006-02-25 11:00:56.000000000 +0100
@@ -4,6 +4,7 @@
 #include <sys/types.h>
 #include <sys/time.h>
 #include <sys/select.h>
+#include <string.h> /* OpenBSD needs this for FD_ZERO */
 extern int select();
 
 #endif
diff -ruN qmail-1.03-orig/sendmail.c qmail-1.03-ldap-20060201-orig/sendmail.c
--- qmail-1.03-orig/sendmail.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/sendmail.c	2006-02-25 11:00:56.000000000 +0100
@@ -1,3 +1,4 @@
+#include <unistd.h>
 #include "sgetopt.h"
 #include "substdio.h"
 #include "subfd.h"
@@ -19,7 +20,7 @@
   _exit(100);
 }
 
-char *smtpdarg[] = { "bin/qmail-smtpd", 0 };
+const char *smtpdarg[] = { "bin/qmail-smtpd", 0 };
 void smtpd()
 {
   if (!env_get("PROTO")) {
@@ -32,29 +33,61 @@
     if (!env_put("TCPREMOTEHOST=localhost")) nomem();
     if (!env_put("TCPREMOTEINFO=sendmail-bs")) nomem();
   }
-  execv(*smtpdarg,smtpdarg);
+  execv(*smtpdarg,(char **)smtpdarg);
   substdio_putsflush(subfderr,"sendmail: fatal: unable to run qmail-smtpd\n");
   _exit(111);
 }
 
-char *qreadarg[] = { "bin/qmail-qread", 0 };
+const char *qreadarg[] = { "bin/qmail-qread", 0 };
 void mailq()
 {
-  execv(*qreadarg,qreadarg);
+  execv(*qreadarg,(char **)qreadarg);
   substdio_putsflush(subfderr,"sendmail: fatal: unable to run qmail-qread\n");
   _exit(111);
 }
 
+void do_sender(s)
+const char *s;
+{
+  char *x;
+  unsigned int n;
+  unsigned int a;
+  unsigned int i;
+  
+  env_unset("QMAILNAME");
+  env_unset("MAILNAME");
+  env_unset("NAME");
+  env_unset("QMAILHOST");
+  env_unset("MAILHOST");
+
+  n = str_len(s);
+  a = str_rchr(s, '@');
+  if (a == n)
+  {
+    env_put2("QMAILUSER", s);
+    return;
+  }
+  env_put2("QMAILHOST", s + a + 1);
+
+  x = alloc((a + 1) * sizeof(char));
+  if (!x) nomem();
+  for (i = 0; i < a; i++)
+    x[i] = s[i];
+  x[i] = 0;
+  env_put2("QMAILUSER", x);
+  alloc_free(x);
+}
+
 int flagh;
 char *sender;
 
-void main(argc,argv)
+int main(argc,argv)
 int argc;
 char **argv;
 {
   int opt;
-  char **qiargv;
-  char **arg;
+  const char **qiargv;
+  const char **arg;
   int i;
  
   if (chdir(auto_qmail) == -1) {
@@ -109,7 +142,7 @@
     _exit(100);
   }
 
-  qiargv = (char **) alloc((argc + 10) * sizeof(char *));
+  qiargv = (const char **) alloc((argc + 10) * sizeof(char *));
   if (!qiargv) nomem();
  
   arg = qiargv;
@@ -118,12 +151,13 @@
   if (sender) {
     *arg++ = "-f";
     *arg++ = sender;
+    do_sender(sender);
   }
   *arg++ = "--";
   for (i = 0;i < argc;++i) *arg++ = argv[i];
   *arg = 0;
  
-  execv(*qiargv,qiargv);
+  execv(*qiargv,(char **)qiargv);
   substdio_putsflush(subfderr,"sendmail: fatal: unable to run qmail-inject\n");
-  _exit(111);
+  return 111;
 }
diff -ruN qmail-1.03-orig/sgetopt.c qmail-1.03-ldap-20060201-orig/sgetopt.c
--- qmail-1.03-orig/sgetopt.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/sgetopt.c	2006-02-25 11:00:56.000000000 +0100
@@ -23,15 +23,15 @@
 #define optprogname sgetoptprogname
 
 int opterr = 1;
-char *optprogname = 0;
+const char *optprogname = 0;
 
 int getopt(argc,argv,opts)
 int argc;
 char **argv;
-char *opts;
+const char *opts;
 {
   int c;
-  char *s;
+  const char *s;
 
   if (!optprogname) {
     optprogname = *argv;
diff -ruN qmail-1.03-orig/sgetopt.h qmail-1.03-ldap-20060201-orig/sgetopt.h
--- qmail-1.03-orig/sgetopt.h	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/sgetopt.h	2006-02-25 11:00:56.000000000 +0100
@@ -14,8 +14,8 @@
 
 #include "subgetopt.h"
 
-extern int sgetoptmine();
+extern int sgetoptmine(int, char **, const char *);
 extern int sgetopterr;
-extern char *sgetoptprogname;
+extern const char *sgetoptprogname;
 
 #endif
diff -ruN qmail-1.03-orig/sig_alarm.c qmail-1.03-ldap-20060201-orig/sig_alarm.c
--- qmail-1.03-orig/sig_alarm.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/sig_alarm.c	2006-02-25 11:00:56.000000000 +0100
@@ -1,7 +1,7 @@
 #include <signal.h>
 #include "sig.h"
 
-void sig_alarmblock() { sig_block(SIGALRM); }
-void sig_alarmunblock() { sig_unblock(SIGALRM); }
+void sig_alarmblock(void) { sig_block(SIGALRM); }
+void sig_alarmunblock(void) { sig_unblock(SIGALRM); }
 void sig_alarmcatch(f) void (*f)(); { sig_catch(SIGALRM,f); }
-void sig_alarmdefault() { sig_catch(SIGALRM,SIG_DFL); }
+void sig_alarmdefault(void) { sig_catch(SIGALRM,SIG_DFL); }
diff -ruN qmail-1.03-orig/sig_block.c qmail-1.03-ldap-20060201-orig/sig_block.c
--- qmail-1.03-orig/sig_block.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/sig_block.c	2006-02-25 11:00:56.000000000 +0100
@@ -28,7 +28,7 @@
 #endif
 }
 
-void sig_blocknone()
+void sig_blocknone(void)
 {
 #ifdef HASSIGPROCMASK
   sigset_t ss;
diff -ruN qmail-1.03-orig/sig_child.c qmail-1.03-ldap-20060201-orig/sig_child.c
--- qmail-1.03-orig/sig_child.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/sig_child.c	2006-02-25 11:00:56.000000000 +0100
@@ -1,7 +1,7 @@
 #include <signal.h>
 #include "sig.h"
 
-void sig_childblock() { sig_block(SIGCHLD); }
-void sig_childunblock() { sig_unblock(SIGCHLD); }
+void sig_childblock(void) { sig_block(SIGCHLD); }
+void sig_childunblock(void) { sig_unblock(SIGCHLD); }
 void sig_childcatch(f) void (*f)(); { sig_catch(SIGCHLD,f); }
-void sig_childdefault() { sig_catch(SIGCHLD,SIG_DFL); }
+void sig_childdefault(void) { sig_catch(SIGCHLD,SIG_DFL); }
diff -ruN qmail-1.03-orig/sig.h qmail-1.03-ldap-20060201-orig/sig.h
--- qmail-1.03-orig/sig.h	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/sig.h	2006-02-25 11:00:56.000000000 +0100
@@ -1,43 +1,45 @@
 #ifndef SIG_H
 #define SIG_H
 
-extern void sig_catch();
-extern void sig_block();
-extern void sig_unblock();
-extern void sig_blocknone();
-extern void sig_pause();
+extern void sig_catch(int, void (*)());
+extern void sig_block(int);
+extern void sig_unblock(int);
+extern void sig_blocknone(void);
+extern void sig_pause(void);
 
 extern void sig_dfl();
 
-extern void sig_miscignore();
-extern void sig_bugcatch();
+extern void sig_miscignore(void);
+extern void sig_bugcatch(void (*)());
 
-extern void sig_pipeignore();
-extern void sig_pipedefault();
+extern void sig_pipeignore(void);
+extern void sig_pipedefault(void);
 
+/* XXX not available in qmail-1.03
 extern void sig_contblock();
 extern void sig_contunblock();
 extern void sig_contcatch();
 extern void sig_contdefault();
+*/
 
-extern void sig_termblock();
-extern void sig_termunblock();
-extern void sig_termcatch();
-extern void sig_termdefault();
-
-extern void sig_alarmblock();
-extern void sig_alarmunblock();
-extern void sig_alarmcatch();
-extern void sig_alarmdefault();
-
-extern void sig_childblock();
-extern void sig_childunblock();
-extern void sig_childcatch();
-extern void sig_childdefault();
-
-extern void sig_hangupblock();
-extern void sig_hangupunblock();
-extern void sig_hangupcatch();
-extern void sig_hangupdefault();
+extern void sig_termblock(void);
+extern void sig_termunblock(void);
+extern void sig_termcatch(void (*)());
+extern void sig_termdefault(void);
+
+extern void sig_alarmblock(void);
+extern void sig_alarmunblock(void);
+extern void sig_alarmcatch(void (*)());
+extern void sig_alarmdefault(void);
+
+extern void sig_childblock(void);
+extern void sig_childunblock(void);
+extern void sig_childcatch(void (*)());
+extern void sig_childdefault(void);
+
+extern void sig_hangupblock(void);
+extern void sig_hangupunblock(void);
+extern void sig_hangupcatch(void (*)());
+extern void sig_hangupdefault(void);
 
 #endif
diff -ruN qmail-1.03-orig/sig_hup.c qmail-1.03-ldap-20060201-orig/sig_hup.c
--- qmail-1.03-orig/sig_hup.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/sig_hup.c	2006-02-25 11:00:56.000000000 +0100
@@ -1,7 +1,7 @@
 #include <signal.h>
 #include "sig.h"
 
-void sig_hangupblock() { sig_block(SIGHUP); }
-void sig_hangupunblock() { sig_unblock(SIGHUP); }
+void sig_hangupblock(void) { sig_block(SIGHUP); }
+void sig_hangupunblock(void) { sig_unblock(SIGHUP); }
 void sig_hangupcatch(f) void (*f)(); { sig_catch(SIGHUP,f); }
-void sig_hangupdefault() { sig_catch(SIGHUP,SIG_DFL); }
+void sig_hangupdefault(void) { sig_catch(SIGHUP,SIG_DFL); }
diff -ruN qmail-1.03-orig/sig_misc.c qmail-1.03-ldap-20060201-orig/sig_misc.c
--- qmail-1.03-orig/sig_misc.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/sig_misc.c	2006-02-25 11:00:56.000000000 +0100
@@ -1,7 +1,7 @@
 #include <signal.h>
 #include "sig.h"
 
-void sig_miscignore()
+void sig_miscignore(void)
 {
   sig_catch(SIGVTALRM,SIG_IGN);
   sig_catch(SIGPROF,SIG_IGN);
diff -ruN qmail-1.03-orig/signatures qmail-1.03-ldap-20060201-orig/signatures
--- qmail-1.03-orig/signatures	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/signatures	2006-02-25 11:00:56.000000000 +0100
@@ -0,0 +1,66 @@
+# Windows executables seen in active virii
+TVqQAAMAA
+TVpQAAIAA
+TVoAAAEAA
+TVoAACQAA
+TVqQAAMAA
+TVoAAD8AA
+# Additional windows executable signatures not yet seen in virii
+TVpAALQAc
+TVpyAXkAX
+TVrmAU4AA
+TVrhARwAk
+TVoFAQUAA
+TVoAAAQAA
+TVoIARMAA
+TVouARsAA
+TVrQAT8AA
+# .GIF file found in the current fake Microsoft patch virus making the rounds.
+R0lGODlhaAA7APcAAP///+rp6puSp6GZrDUjUUc6Zn53mFJMdbGvvVtXh2xre8bF1x8cU4yLprOy
+
+# .ZIPfile signature seen in SoBig.E:
+# This signature is to generic and blocks valid zip files so disable it.
+#UEsDBBQAA
+
+# .ZIPfile signature of MyDoom:
+# nota bene * is a anymatch.
+UEsDBAoAAAAAA*****DKJx+eAFgAAABYAA**AAAA
+# .ZIPfile signatures of Beagle and friends:
+UEsDBAoAAQAAA*****Cf4kJRDDAAAAAwAAA*AAAA
+UEsDBAoAAQAAAi****Bcl5T9DzAAAAMwAAA*AAAA
+UEsDBAoAAAAAA*****CxG9oCAH4AAAB+AA**AAAA
+UEsDBAoAAAAAA*****BiZMYWCWMAAAljAAA*AAAA
+UEsDBAoAAAAAA******jiB3egHMAAIBzAAB*AAAA
+UEsDBAoAAQAAA******D+JTDGqkIAA6pCAA*AAAA
+UEsDBAoAAAAAA*****B+cADhaG0AAGhtAAB*AAAA
+UEsDBAoAAAAAA*****BdbrAiAFYAAABWAAA*AAAA
+UEsDBAoAAAAAA******FWheeAPQBAAD0AQ**AAAA
+UEsDBAoAAAAAA*****GpXle1AOABAADgAQA*AAAA
+UEsDBAoAAAAAA*****AnDhYmfXMAAH1zAABwAAAA
+UEsDBAoAAQAIA*****AZRqEfZFEAACROAAAMAAAA
+UEsDBAoAAQAIA*****DJkv0Bq1QAAAxRAAANAAAA
+UEsDBAoAAQAAA*****AZ45yiDFMAAABTAAAKAAAA
+UEsDBAoAAQAAA*****AOGOjBMVMAACVTAAANAAAA
+UEsDBAoAAAAAAAFYrj******/cEAAP3BAAAfAAAA
+UEsDBAoAAAAAA*****C93UuYwHAAAMBwAADXAAAA
+UEsDBAoAAQAAA*****DUdqQ1v1QAALNUAAAKAAAA
+UEsDBAoAAQAAA*****EsQ5lqlnsEAIp7BAAMAAAA
+UEsDBAoAAQAAA*****Epm2uEYuoAAFbqAAAJAAAA
+UEsDBAoAAQAAA*****HelFoJ1eUBAMnlAQAKAAAA
+UEsDBAoAAAAAA*****AjTTDoAIAAAACAAACjAAAA
+UEsDBAoAAAAAA*****BCNPQYAPwBAAD8AQAHAAAA
+UEsDBAoAAAAAA*****FZUaXpAHwAAAB8AABUAAAA
+UEsDBAoAAAAAA*****FxKYToA34AAAN+AABXAAAA
+UEsDBAoAAAAAA*****EAAAAAAAAAAAAAAAAFAAAA
+UEsDBBQAAAAIA*****FhTJoyVgAAAG8AAAAIAAAA
+UEsDBAoAAAAAA*****CHcNZsANAAAADQAAC*AAAA
+UEsDBAoAAAAAA*****H7vMVGA38AAAN/AABUAAAA
+UEsDBAoAAAAAA*****FbiToH6N0AAOjdAABPAAAA
+UEsDBAoAAAAAA***VzFZUaXpAHwAAAB8AAB*AAAA
+UEsDBAoAAAAAA****TFUnOUjAHoAAAB6AAA*AAAA
+
+# strange .hta virus I got
+PEhUTUw+DQo8SEVBRD4NCjxUSVRMRT5XaW5kb3dz
+# ... and a .vbs virus
+ZGltIGZpbGVzeXMsIGZpbGV0eHQsIGdldG5hbWUs
+
diff -ruN qmail-1.03-orig/sig_pause.c qmail-1.03-ldap-20060201-orig/sig_pause.c
--- qmail-1.03-orig/sig_pause.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/sig_pause.c	2006-02-25 11:00:56.000000000 +0100
@@ -2,7 +2,7 @@
 #include "sig.h"
 #include "hassgprm.h"
 
-void sig_pause()
+void sig_pause(void)
 {
 #ifdef HASSIGPROCMASK
   sigset_t ss;
diff -ruN qmail-1.03-orig/sig_pipe.c qmail-1.03-ldap-20060201-orig/sig_pipe.c
--- qmail-1.03-orig/sig_pipe.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/sig_pipe.c	2006-02-25 11:00:56.000000000 +0100
@@ -1,5 +1,5 @@
 #include <signal.h>
 #include "sig.h"
 
-void sig_pipeignore() { sig_catch(SIGPIPE,SIG_IGN); }
-void sig_pipedefault() { sig_catch(SIGPIPE,SIG_DFL); }
+void sig_pipeignore(void) { sig_catch(SIGPIPE,SIG_IGN); }
+void sig_pipedefault(void) { sig_catch(SIGPIPE,SIG_DFL); }
diff -ruN qmail-1.03-orig/sig_term.c qmail-1.03-ldap-20060201-orig/sig_term.c
--- qmail-1.03-orig/sig_term.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/sig_term.c	2006-02-25 11:00:56.000000000 +0100
@@ -1,7 +1,7 @@
 #include <signal.h>
 #include "sig.h"
 
-void sig_termblock() { sig_block(SIGTERM); }
-void sig_termunblock() { sig_unblock(SIGTERM); }
+void sig_termblock(void) { sig_block(SIGTERM); }
+void sig_termunblock(void) { sig_unblock(SIGTERM); }
 void sig_termcatch(f) void (*f)(); { sig_catch(SIGTERM,f); }
-void sig_termdefault() { sig_catch(SIGTERM,SIG_DFL); }
+void sig_termdefault(void) { sig_catch(SIGTERM,SIG_DFL); }
diff -ruN qmail-1.03-orig/slurpclose.c qmail-1.03-ldap-20060201-orig/slurpclose.c
--- qmail-1.03-orig/slurpclose.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/slurpclose.c	2006-02-25 11:00:56.000000000 +0100
@@ -1,3 +1,4 @@
+#include <unistd.h>
 #include "stralloc.h"
 #include "readwrite.h"
 #include "slurpclose.h"
@@ -6,7 +7,7 @@
 int slurpclose(fd,sa,bufsize)
 int fd;
 stralloc *sa;
-int bufsize;
+unsigned int bufsize;
 {
   int r;
   for (;;) {
diff -ruN qmail-1.03-orig/slurpclose.h qmail-1.03-ldap-20060201-orig/slurpclose.h
--- qmail-1.03-orig/slurpclose.h	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/slurpclose.h	2006-02-25 11:00:56.000000000 +0100
@@ -1,6 +1,8 @@
 #ifndef SLURPCLOSE_H
 #define SLURPCLOSE_H
 
-extern int slurpclose();
+#include "stralloc.h"
+
+extern int slurpclose(int, stralloc *, unsigned int);
 
 #endif
diff -ruN qmail-1.03-orig/smtpcall.c qmail-1.03-ldap-20060201-orig/smtpcall.c
--- qmail-1.03-orig/smtpcall.c	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/smtpcall.c	2006-02-25 11:00:56.000000000 +0100
@@ -0,0 +1,274 @@
+/*
+ * Copyright (c) 2003-2004 Claudio Jeker,
+ *      Internet Business Solutions AG, CH-8005 Zürich, Switzerland
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Internet Business
+ *      Solutions AG and its contributors.
+ * 4. Neither the name of the author nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#include <unistd.h>
+#include "auto_qmail.h"
+#include "coe.h"
+#include "fd.h"
+#include "substdio.h"
+#include "str.h"
+#include "stralloc.h"
+#include "timeoutread.h"
+#include "timeoutwrite.h"
+#include "wait.h"
+
+#include "smtpcall.h"
+
+int call_getln(substdio *ss, stralloc *l)
+{
+  int i;
+  if (!stralloc_copys(l, "")) return -1;
+  for (;;) {
+    if (!stralloc_readyplus(l,1)) return -1;
+    i = substdio_get(ss, l->s + l->len, 1);
+    if (i != 1) return i;
+    if (l->s[l->len] == '\n') break;
+    ++l->len;
+  }
+  if (l->len > 0) if (l->s[l->len-1] == '\r') --l->len;
+  l->s[l->len] = 0;
+  return l->len;
+}
+
+int
+call_getc(struct call *cc, char *c)
+{
+	int r;
+	if (cc->flagerr || cc->flagabort) return -1;
+	r = substdio_get(&cc->ssfrom, c, 1);
+	if (r == -1) {
+		cc->flagerr = 1;
+		return -1;
+	}
+	return r;
+}
+
+int
+call_put(struct call *cc, const char *s, unsigned int len)
+{
+	if (cc->flagerr || cc->flagabort) return -1;
+	if (cc->flagstar && str_diffn(s, "*", len) == 0) {
+		cc->flagabort = 1;
+		return -1;
+	}
+	if (substdio_put(&cc->ssto, s, len) == -1) {
+		cc->flagerr = 1;
+		return -1;
+	}
+	return 0;
+}
+
+int
+call_puts(struct call *cc, const char *s)
+{
+	if (cc->flagerr || cc->flagabort) return -1;
+	if (cc->flagstar && str_diff(s, "*") == 0) {
+		cc->flagabort = 1;
+		return -1;
+	}
+	if (substdio_puts(&cc->ssto, s) == -1) {
+		cc->flagerr = 1;
+		return -1;
+	}
+	return 0;
+}
+
+int
+call_flush(struct call *cc)
+{
+	if (cc->flagerr || cc->flagabort) return -1;
+	if (substdio_flush(&cc->ssto) == -1) {
+		cc->flagerr = 1;
+		return -1;
+	}
+	return 0;
+
+}
+
+int
+call_putflush(struct call *cc, const char *s, unsigned int len)
+{
+	if (call_put(cc, s, len) == -1) return -1;
+        if (call_flush(cc) == -1) return -1;
+	return 0;
+}
+
+int
+call_putsflush(struct call *cc, const char *s)
+{
+	if (call_puts(cc, s) == -1) return -1;
+        if (call_flush(cc) == -1) return -1;
+	return 0;
+}
+
+static int mytimeout = 10;
+
+static int
+mywrite(int fd, void *buf, int len)
+{
+	return timeoutwrite(mytimeout,fd,buf,len);
+}
+
+static int
+myread(int fd, void *buf, int len)
+{
+	return timeoutread(mytimeout,fd,buf,len);
+}
+
+int
+call_open(struct call *cc, const char *prog, int timeout, int flagstar)
+{
+  int pit[2];
+  int pif[2];
+  const char *(args[2]);
+
+  args[0] = prog;
+  args[1] = 0;
+
+  if (pipe(pit) == -1) return -1;
+  if (pipe(pif) == -1) { close(pit[0]); close(pit[1]); return -1; }
+ 
+  switch(cc->pid = vfork()) {
+    case -1:
+      close(pit[0]); close(pit[1]);
+      close(pif[0]); close(pif[1]);
+      return -1;
+    case 0:
+      close(pit[1]);
+      close(pif[0]);
+      if (fd_move(0,pit[0]) == -1) _exit(120);
+      if (fd_move(1,pif[1]) == -1) _exit(120);
+      if (chdir(auto_qmail) == -1) _exit(61);
+      execv(*args,(char **)args);
+      _exit(120);
+  }
+
+  if (timeout != 0) mytimeout = timeout;
+  cc->flagerr = 0;
+  cc->flagabort = 0;
+  cc->flagstar = flagstar;
+  cc->tofd = pit[1]; close(pit[0]);
+  cc->fromfd = pif[0]; close(pif[1]);
+  coe(cc->tofd); coe(cc->fromfd);
+  substdio_fdbuf(&cc->ssto, mywrite, cc->tofd,
+      cc->tobuf, sizeof(cc->tobuf));
+  substdio_fdbuf(&cc->ssfrom, myread, cc->fromfd,
+      cc->frombuf, sizeof(cc->frombuf));
+  return 0;
+}
+
+void
+call_close(struct call *cc)
+{
+	int wstat;
+	int r;
+	char ch;
+	
+	if ((long)cc->pid == -1) return; /* nothing running */
+	call_flush(cc);
+	close(cc->tofd);
+	while ((r = call_getc(cc, &ch)) == 1) ;
+	if (r == -1) ; /* bad thing happend but who cares */
+	close(cc->fromfd);
+      
+	wait_pid(&wstat,cc->pid); /* just kill the zombie */
+}
+
+const char *
+auth_close(struct call *cc, stralloc *user, const char *pre)
+{
+	const char *s;
+	int wstat;
+	int exitcode;
+	char c;
+
+	s = 0; c = 0;
+	if ((long)cc->pid == -1)
+		return "454 unable to start authentication process. "
+		    "(#4.3.0)\r\n";
+	
+	if (cc->flagabort)
+		s = "501 authentication exchange aborted. (#4.3.0)\r\n";
+	if (cc->flagerr)
+		s = "454 authentication process write failure. (#4.3.0)\r\n";
+	
+	if (!cc->flagerr && !cc->flagabort) {
+		if (call_getc(cc, &c) == -1) {
+			s = "454 authentication process read failure. "
+			    "(#4.3.0)\r\n";
+		} else
+		switch (c) {
+		case 'K':
+			if (!stralloc_copys(user, pre!=0?pre:"")) {
+				s = "421 out of memory (#4.3.0)\r\n"; 
+				break;
+			}
+			while (call_getc(cc, &c) == 1) {
+				if (!stralloc_append(user, &c)) {
+					s = "421 out of memory (#4.3.0)\r\n"; 
+					break;
+				}
+			}
+			if (cc->flagerr)
+				s = "454 authentication process read "
+				    "failure. (#4.3.0)\r\n";
+			else
+				s = "235 nice to meet you\r\n";
+			break;
+		case 'D':
+			s = "535 authentication failure\r\n";
+			break;
+		case 'Z':
+			s = "501 authentication exchange failed\r\n";
+			break;
+		default:
+			s = "454 authentication process failure. (#4.3.0)\r\n";
+			break;
+		}
+	}
+	close(cc->tofd);
+	close(cc->fromfd);
+      
+	if ((unsigned long)wait_pid(&wstat,cc->pid) != cc->pid)
+		return "454 authentication waitpid surprise (#4.3.0)\r\n";
+	if (wait_crashed(wstat))
+		return "454 authentication process crashed (#4.3.0)\r\n";
+	exitcode = wait_exitcode(wstat);
+	switch (exitcode) {
+	case 0:
+		return s;
+	default:
+		return "454 temporary authentication failure (#4.3.0)\r\n";
+	}
+}
+
diff -ruN qmail-1.03-orig/smtpcall.h qmail-1.03-ldap-20060201-orig/smtpcall.h
--- qmail-1.03-orig/smtpcall.h	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/smtpcall.h	2006-02-25 11:00:56.000000000 +0100
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2003-2004 Claudio Jeker,
+ *      Internet Business Solutions AG, CH-8005 Zürich, Switzerland
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Internet Business
+ *      Solutions AG and its contributors.
+ * 4. Neither the name of the author nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#ifndef __SMTPCALL_H__
+#define __SMTPCALL_H__
+
+#include "stralloc.h"
+#include "substdio.h"
+
+struct call {
+  int flagerr;
+  int flagabort;
+  int flagstar;
+  unsigned long pid;
+  int tofd;
+  int fromfd;
+  substdio ssto;
+  substdio ssfrom;
+  char tobuf[256];
+  char frombuf[128];
+} ;
+
+int call_getln(substdio *, stralloc *);
+int call_getc(struct call *, char *);
+int call_put(struct call *, const char *, unsigned int);
+int call_puts(struct call *, const char *);
+int call_flush(struct call *);
+int call_putflush(struct call *, const char *, unsigned int);
+int call_putsflush(struct call *, const char *);
+int call_open(struct call *, const char *, int, int);
+void call_close(struct call *);
+
+const char *auth_close(struct call *, stralloc *, const char *);
+
+#endif
diff -ruN qmail-1.03-orig/spawn.c qmail-1.03-ldap-20060201-orig/spawn.c
--- qmail-1.03-orig/spawn.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/spawn.c	2006-02-25 11:00:56.000000000 +0100
@@ -1,5 +1,8 @@
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <unistd.h>
+#include "readwrite.h"
+#include "alloc.h"
 #include "sig.h"
 #include "wait.h"
 #include "substdio.h"
@@ -15,11 +18,13 @@
 #include "auto_uids.h"
 #include "auto_spawn.h"
 
-extern int truncreport;
+extern unsigned int truncreport;
 extern int spawn();
 extern void report();
 extern void initialize();
 
+int flagreinit = 0;
+
 struct delivery
  {
   int used;
@@ -28,6 +33,9 @@
   int wstat; /* if !pid: status of child */
   int fdout; /* pipe output, -1 if !pid; delays eof until after death */
   stralloc output;
+#ifdef DEBUG
+  stralloc log;
+#endif
  }
 ;
 
@@ -37,7 +45,7 @@
 {
  int wstat;
  int pid;
- int i;
+ unsigned int i;
  while ((pid = wait_nohang(&wstat)) > 0)
    for (i = 0;i < auto_spawn;++i) if (d[i].used)
      if (d[i].pid == pid)
@@ -63,30 +71,44 @@
 int flagreading = 1;
 char outbuf[1024]; substdio ssout;
 
-int stage = 0; /* reading 0:delnum 1:messid 2:sender 3:recip */
+int stage = 0; /* reading 0:delnum 1:delnum2 2:messid 3:sender 4:recip */
 int flagabort = 0; /* if 1, everything except delnum is garbage */
-int delnum;
+unsigned int delnum;
 stralloc messid = {0};
 stralloc sender = {0};
 stralloc recip = {0};
 
 void err(s) char *s;
 {
- char ch; ch = delnum; substdio_put(&ssout,&ch,1);
+ unsigned char ch;
+ ch = delnum; substdio_put(&ssout,&ch,1);
+ ch = delnum >> 8; substdio_put(&ssout,&ch,1);
  substdio_puts(&ssout,s); substdio_putflush(&ssout,"",1);
 }
 
 void docmd()
 {
  int f;
- int i;
- int j;
+ unsigned int i;
+ unsigned int j;
  int fdmess;
  int pi[2];
  struct stat st;
 
+ /* SIGHUP HANDLING */
+ if (delnum == 0xbeef)
+   if (*messid.s == '\0' && *sender.s == '\0' && *recip.s == '\0') {
+#if 0
+     err("HHUP received\n");
+#endif
+     flagreinit = 1;
+     return;
+   }
+ 
  if (flagabort) { err("Zqmail-spawn out of memory. (#4.3.0)\n"); return; }
+#if 0 /* no longer possible, delnum is unsigned */
  if (delnum < 0) { err("ZInternal error: delnum negative. (#4.3.5)\n"); return; }
+#endif
  if (delnum >= auto_spawn) { err("ZInternal error: delnum too big. (#4.3.5)\n"); return; }
  if (d[delnum].used) { err("ZInternal error: delnum in use. (#4.3.5)\n"); return; }
  for (i = 0;i < messid.len;++i)
@@ -136,7 +158,7 @@
 {
  int i;
  int r;
- char ch;
+ unsigned char ch;
 
  r = read(0,cmdbuf,sizeof(cmdbuf));
  if (r == 0)
@@ -154,17 +176,20 @@
    switch(stage)
     {
      case 0:
-       delnum = (unsigned int) (unsigned char) ch;
-       messid.len = 0; stage = 1; break;
+       delnum = ch;
+       stage = 1; break;
      case 1:
+       delnum += (unsigned int)ch << 8;
+       messid.len = 0; stage = 2; break;
+     case 2:
        if (!stralloc_append(&messid,&ch)) flagabort = 1;
        if (ch) break;
-       sender.len = 0; stage = 2; break;
-     case 2:
+       sender.len = 0; stage = 3; break;
+     case 3:
        if (!stralloc_append(&sender,&ch)) flagabort = 1;
        if (ch) break;
-       recip.len = 0; stage = 3; break;
-     case 3:
+       recip.len = 0; stage = 4; break;
+     case 4:
        if (!stralloc_append(&recip,&ch)) flagabort = 1;
        if (ch) break;
        docmd();
@@ -175,12 +200,12 @@
 
 char inbuf[128];
 
-void main(argc,argv)
+int main(argc,argv)
 int argc;
 char **argv;
 {
- char ch;
- int i;
+ unsigned char ch;
+ unsigned int i;
  int r;
  fd_set rfds;
  int nfds;
@@ -201,12 +226,23 @@
 
  initialize(argc,argv);
 
- ch = auto_spawn; substdio_putflush(&ssout,&ch,1);
+ ch = auto_spawn; substdio_put(&ssout,&ch,1);
+ ch = auto_spawn >> 8; substdio_putflush(&ssout,&ch,1);
 
- for (i = 0;i < auto_spawn;++i) { d[i].used = 0; d[i].output.s = 0; }
+ for (i = 0;i < auto_spawn;++i) {
+   d[i].used = 0;
+   d[i].output.s = 0;
+#ifdef DEBUG
+   d[i].log.s = 0;
+#endif
+ }
 
  for (;;)
   {
+   if (flagreinit) {
+     initialize(argc,argv);
+     flagreinit = 0;
+   }
    if (!flagreading)
     {
      for (i = 0;i < auto_spawn;++i) if (d[i].used) break;
@@ -236,24 +272,87 @@
 	   continue; /* read error on a readable pipe? be serious */
 	 if (r == 0)
 	  {
-           ch = i; substdio_put(&ssout,&ch,1);
+	   unsigned char c; c = i; substdio_put(&ssout,&c,1);
+	   c = i >> 8; substdio_put(&ssout,&c,1);
 	   report(&ssout,d[i].wstat,d[i].output.s,d[i].output.len);
 	   substdio_put(&ssout,"",1);
 	   substdio_flush(&ssout);
 	   close(d[i].fdin); d[i].used = 0;
 	   continue;
 	  }
+#ifdef DEBUG
+#	 define IS_LOG(x) ( d[(x)].used & 0x8 )
+#	 define LOGON(x)  ( d[(x)].used |= 0x8 )
+#	 define LOGOFF(x) ( d[(x)].used = 1 )
+	 {
+	  unsigned int j;
+	  unsigned int b;
+	  unsigned int t;
+	  for (j=0, b=0; j < (unsigned int)r; j++) {
+	    if (inbuf[j] == 15) {
+	      while (!stralloc_readyplus(&d[i].output,j-b)) sleep(10); /*XXX*/
+	      byte_copy(d[i].output.s + d[i].output.len,j-b,inbuf+b);
+	      d[i].output.len += j-b;
+	      LOGON(i);
+	      b = j+1;
+	    } else if ( inbuf[j] == 16 ) {
+	      while (!stralloc_readyplus(&d[i].log,j-b)) sleep(10); /*XXX*/
+	      byte_copy(d[i].log.s + d[i].log.len,j-b,inbuf+b);
+	      d[i].log.len += j-b;
+	      b = j+1;
+	      LOGOFF(i);
+	      if (truncreport > 100)
+		if (d[i].log.len > truncreport) {
+		  const char *truncmess = "\nError report too long, sorry.\n";
+		  d[i].log.len = truncreport - str_len(truncmess) - 3;
+		  stralloc_cats(&d[i].log,truncmess);
+		}
+	      ch = i; substdio_put(&ssout,&ch,1);
+	      ch = i >> 8; substdio_put(&ssout,&ch,1);
+	      ch = 'L'; substdio_put(&ssout,&ch,1);
+	      for (t = 0;t < d[i].log.len; ++t) if (!d[i].log.s[t]) break;
+	      substdio_put(&ssout,d[i].log.s,t);
+	      substdio_put(&ssout,"",1);
+	      substdio_flush(&ssout);
+	      d[i].log.len = 0;
+	    }
+	  }
+	  if (b == (unsigned int)r) continue;
+	  if ( IS_LOG(i) )
+	   {
+	    while (!stralloc_readyplus(&d[i].log,r-b)) sleep(10); /*XXX*/
+	    byte_copy(d[i].log.s + d[i].log.len,r-b,inbuf+b);
+	    d[i].log.len += r-b;
+	   }
+	  else
+	   {
+	    while (!stralloc_readyplus(&d[i].output,r-b)) sleep(10); /*XXX*/
+	    byte_copy(d[i].output.s + d[i].output.len,r-b,inbuf+b);
+	    d[i].output.len += r-b;
+	    if (truncreport > 100)
+	      if (d[i].output.len > truncreport)
+	       {
+		const char *truncmess = "\nError report too long, sorry.\n";
+		d[i].output.len = truncreport - str_len(truncmess) - 3;
+		stralloc_cats(&d[i].output,truncmess);
+	       }
+	   }
+	 }
+#else
 	 while (!stralloc_readyplus(&d[i].output,r)) sleep(10); /*XXX*/
 	 byte_copy(d[i].output.s + d[i].output.len,r,inbuf);
 	 d[i].output.len += r;
 	 if (truncreport > 100)
 	   if (d[i].output.len > truncreport)
 	    {
-	     char *truncmess = "\nError report too long, sorry.\n";
+	     const char *truncmess = "\nError report too long, sorry.\n";
 	     d[i].output.len = truncreport - str_len(truncmess) - 3;
 	     stralloc_cats(&d[i].output,truncmess);
 	    }
+#endif
 	}
     }
   }
+ /* NOTREACHED */
+ return 0;
 }
diff -ruN qmail-1.03-orig/splogger.c qmail-1.03-ldap-20060201-orig/splogger.c
--- qmail-1.03-orig/splogger.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/splogger.c	2006-02-25 11:00:56.000000000 +0100
@@ -10,7 +10,7 @@
 #include "fmt.h"
 
 char buf[800]; /* syslog truncates long lines (or crashes); GPACIC */
-int bufpos = 0; /* 0 <= bufpos < sizeof(buf) */
+unsigned int bufpos = 0; /* 0 <= bufpos < sizeof(buf) */
 int flagcont = 0;
 int priority; /* defined if flagcont */
 char stamp[FMT_ULONG + FMT_ULONG + 3]; /* defined if flagcont */
@@ -45,7 +45,7 @@
   bufpos = 0;
 }
 
-void main(argc,argv)
+int main(argc,argv)
 int argc;
 char **argv;
 {
@@ -69,4 +69,6 @@
     if ((ch < 32) || (ch > 126)) ch = '?'; /* logger truncates at 0; GPACIC */
     buf[bufpos++] = ch;
   }
+  /* NOTREACHED */
+  return 0;
 }
diff -ruN qmail-1.03-orig/stralloc_arts.c qmail-1.03-ldap-20060201-orig/stralloc_arts.c
--- qmail-1.03-orig/stralloc_arts.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/stralloc_arts.c	2006-02-25 11:00:56.000000000 +0100
@@ -4,9 +4,9 @@
 
 int stralloc_starts(sa,s)
 stralloc *sa;
-char *s;
+const char *s;
 {
-  int len;
+  unsigned int len;
   len = str_len(s);
   return (sa->len >= len) && byte_equal(s,len,sa->s);
 }
diff -ruN qmail-1.03-orig/stralloc_catb.c qmail-1.03-ldap-20060201-orig/stralloc_catb.c
--- qmail-1.03-orig/stralloc_catb.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/stralloc_catb.c	2006-02-25 11:00:56.000000000 +0100
@@ -3,7 +3,7 @@
 
 int stralloc_catb(sa,s,n)
 stralloc *sa;
-char *s;
+const char *s;
 unsigned int n;
 {
   if (!sa->s) return stralloc_copyb(sa,s,n);
diff -ruN qmail-1.03-orig/stralloc_cats.c qmail-1.03-ldap-20060201-orig/stralloc_cats.c
--- qmail-1.03-orig/stralloc_cats.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/stralloc_cats.c	2006-02-25 11:00:56.000000000 +0100
@@ -4,7 +4,7 @@
 
 int stralloc_cats(sa,s)
 stralloc *sa;
-char *s;
+const char *s;
 {
   return stralloc_catb(sa,s,str_len(s));
 }
diff -ruN qmail-1.03-orig/stralloc.h qmail-1.03-ldap-20060201-orig/stralloc.h
--- qmail-1.03-orig/stralloc.h	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/stralloc.h	2006-02-25 11:00:56.000000000 +0100
@@ -5,16 +5,16 @@
 
 GEN_ALLOC_typedef(stralloc,char,s,len,a)
 
-extern int stralloc_ready();
-extern int stralloc_readyplus();
-extern int stralloc_copy();
-extern int stralloc_cat();
-extern int stralloc_copys();
-extern int stralloc_cats();
-extern int stralloc_copyb();
-extern int stralloc_catb();
-extern int stralloc_append(); /* beware: this takes a pointer to 1 char */
-extern int stralloc_starts();
+extern int stralloc_ready(stralloc *, unsigned int);
+extern int stralloc_readyplus(stralloc *, unsigned int);
+extern int stralloc_copy(stralloc *, stralloc *);
+extern int stralloc_cat(stralloc *, stralloc *);
+extern int stralloc_copys(stralloc *, const char *);
+extern int stralloc_cats(stralloc *, const char *);
+extern int stralloc_copyb(stralloc *, const char *, unsigned int);
+extern int stralloc_catb(stralloc *, const char *, unsigned int);
+extern int stralloc_append(stralloc *, const char *); /* beware: this takes a pointer to 1 char */
+extern int stralloc_starts(stralloc *, const char *);
 
 #define stralloc_0(sa) stralloc_append(sa,"")
 
diff -ruN qmail-1.03-orig/stralloc_opyb.c qmail-1.03-ldap-20060201-orig/stralloc_opyb.c
--- qmail-1.03-orig/stralloc_opyb.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/stralloc_opyb.c	2006-02-25 11:00:56.000000000 +0100
@@ -3,7 +3,7 @@
 
 int stralloc_copyb(sa,s,n)
 stralloc *sa;
-char *s;
+const char *s;
 unsigned int n;
 {
   if (!stralloc_ready(sa,n + 1)) return 0;
diff -ruN qmail-1.03-orig/stralloc_opys.c qmail-1.03-ldap-20060201-orig/stralloc_opys.c
--- qmail-1.03-orig/stralloc_opys.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/stralloc_opys.c	2006-02-25 11:00:56.000000000 +0100
@@ -4,7 +4,7 @@
 
 int stralloc_copys(sa,s)
 stralloc *sa;
-char *s;
+const char *s;
 {
   return stralloc_copyb(sa,s,str_len(s));
 }
diff -ruN qmail-1.03-orig/stralloc_pend.c qmail-1.03-ldap-20060201-orig/stralloc_pend.c
--- qmail-1.03-orig/stralloc_pend.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/stralloc_pend.c	2006-02-25 11:00:56.000000000 +0100
@@ -2,4 +2,4 @@
 #include "stralloc.h"
 #include "gen_allocdefs.h"
 
-GEN_ALLOC_append(stralloc,char,s,len,a,i,n,x,30,stralloc_readyplus,stralloc_append)
+GEN_ALLOC_append(stralloc,const char,s,len,a,i,n,x,30,stralloc_readyplus,stralloc_append)
diff -ruN qmail-1.03-orig/str_chr.c qmail-1.03-ldap-20060201-orig/str_chr.c
--- qmail-1.03-orig/str_chr.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/str_chr.c	2006-02-25 11:00:56.000000000 +0100
@@ -1,11 +1,11 @@
 #include "str.h"
 
 unsigned int str_chr(s,c)
-register char *s;
+register const char *s;
 int c;
 {
   register char ch;
-  register char *t;
+  register const char *t;
 
   ch = c;
   t = s;
diff -ruN qmail-1.03-orig/str_cpy.c qmail-1.03-ldap-20060201-orig/str_cpy.c
--- qmail-1.03-orig/str_cpy.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/str_cpy.c	2006-02-25 11:00:56.000000000 +0100
@@ -2,9 +2,9 @@
 
 unsigned int str_copy(s,t)
 register char *s;
-register char *t;
+register const char *t;
 {
-  register int len;
+  register unsigned int len;
 
   len = 0;
   for (;;) {
diff -ruN qmail-1.03-orig/str_diff.c qmail-1.03-ldap-20060201-orig/str_diff.c
--- qmail-1.03-orig/str_diff.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/str_diff.c	2006-02-25 11:00:56.000000000 +0100
@@ -1,8 +1,8 @@
 #include "str.h"
 
 int str_diff(s,t)
-register char *s;
-register char *t;
+register const char *s;
+register const char *t;
 {
   register char x;
 
diff -ruN qmail-1.03-orig/str_diffn.c qmail-1.03-ldap-20060201-orig/str_diffn.c
--- qmail-1.03-orig/str_diffn.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/str_diffn.c	2006-02-25 11:00:56.000000000 +0100
@@ -1,8 +1,8 @@
 #include "str.h"
 
 int str_diffn(s,t,len)
-register char *s;
-register char *t;
+register const char *s;
+register const char *t;
 unsigned int len;
 {
   register char x;
diff -ruN qmail-1.03-orig/strerr_die.c qmail-1.03-ldap-20060201-orig/strerr_die.c
--- qmail-1.03-orig/strerr_die.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/strerr_die.c	2006-02-25 11:00:56.000000000 +0100
@@ -4,7 +4,8 @@
 #include "strerr.h"
 
 void strerr_warn(x1,x2,x3,x4,x5,x6,se)
-char *x1; char *x2; char *x3; char *x4; char *x5; char *x6;
+const char *x1; const char *x2; const char *x3;
+const char *x4; const char *x5; const char *x6;
 struct strerr *se;
 {
   strerr_sysinit();
@@ -29,7 +30,8 @@
 
 void strerr_die(e,x1,x2,x3,x4,x5,x6,se)
 int e;
-char *x1; char *x2; char *x3; char *x4; char *x5; char *x6;
+const char *x1; const char *x2; const char *x3;
+const char *x4; const char *x5; const char *x6;
 struct strerr *se;
 {
   strerr_warn(x1,x2,x3,x4,x5,x6,se);
diff -ruN qmail-1.03-orig/strerr.h qmail-1.03-ldap-20060201-orig/strerr.h
--- qmail-1.03-orig/strerr.h	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/strerr.h	2006-02-25 11:00:56.000000000 +0100
@@ -4,18 +4,22 @@
 struct strerr
  {
   struct strerr *who;
-  char *x;
-  char *y;
-  char *z;
+  const char *x;
+  const char *y;
+  const char *z;
  }
 ;
 
 extern struct strerr strerr_sys;
-extern void strerr_sysinit();
+extern void strerr_sysinit(void);
 
+/* XXX not available in qmail-1.03
 extern char *strerr();
-extern void strerr_warn();
-extern void strerr_die();
+*/
+extern void strerr_warn(const char *, const char *, const char *,
+    const char *, const char *, const char *, struct strerr *);
+extern void strerr_die(int, const char *, const char *, const char *,
+    const char *, const char *, const char *, struct strerr *);
 
 #define STRERR(r,se,a) \
 { se.who = 0; se.x = a; se.y = 0; se.z = 0; return r; }
diff -ruN qmail-1.03-orig/strerr_sys.c qmail-1.03-ldap-20060201-orig/strerr_sys.c
--- qmail-1.03-orig/strerr_sys.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/strerr_sys.c	2006-02-25 11:00:56.000000000 +0100
@@ -3,7 +3,7 @@
 
 struct strerr strerr_sys;
 
-void strerr_sysinit()
+void strerr_sysinit(void)
 {
   strerr_sys.who = 0;
   strerr_sys.x = error_str(errno);
diff -ruN qmail-1.03-orig/str.h qmail-1.03-ldap-20060201-orig/str.h
--- qmail-1.03-orig/str.h	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/str.h	2006-02-25 11:00:56.000000000 +0100
@@ -1,13 +1,13 @@
 #ifndef STR_H
 #define STR_H
 
-extern unsigned int str_copy();
-extern int str_diff();
-extern int str_diffn();
-extern unsigned int str_len();
-extern unsigned int str_chr();
-extern unsigned int str_rchr();
-extern int str_start();
+extern unsigned int str_copy(char *, const char *);
+extern int str_diff(const char *, const char *);
+extern int str_diffn(const char *, const char *, unsigned int);
+extern unsigned int str_len(const char *);
+extern unsigned int str_chr(const char *, int);
+extern unsigned int str_rchr(const char *, int);
+extern int str_start(const char *, const char *);
 
 #define str_equal(s,t) (!str_diff((s),(t)))
 
diff -ruN qmail-1.03-orig/str_len.c qmail-1.03-ldap-20060201-orig/str_len.c
--- qmail-1.03-orig/str_len.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/str_len.c	2006-02-25 11:00:56.000000000 +0100
@@ -1,9 +1,9 @@
 #include "str.h"
 
 unsigned int str_len(s)
-register char *s;
+register const char *s;
 {
-  register char *t;
+  register const char *t;
 
   t = s;
   for (;;) {
diff -ruN qmail-1.03-orig/str_rchr.c qmail-1.03-ldap-20060201-orig/str_rchr.c
--- qmail-1.03-orig/str_rchr.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/str_rchr.c	2006-02-25 11:00:56.000000000 +0100
@@ -1,12 +1,12 @@
 #include "str.h"
 
 unsigned int str_rchr(s,c)
-register char *s;
+register const char *s;
 int c;
 {
   register char ch;
-  register char *t;
-  register char *u;
+  register const char *t;
+  register const char *u;
 
   ch = c;
   t = s;
diff -ruN qmail-1.03-orig/str_start.c qmail-1.03-ldap-20060201-orig/str_start.c
--- qmail-1.03-orig/str_start.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/str_start.c	2006-02-25 11:00:56.000000000 +0100
@@ -1,8 +1,8 @@
 #include "str.h"
 
 int str_start(s,t)
-register char *s;
-register char *t;
+register const char *s;
+register const char *t;
 {
   register char x;
 
diff -ruN qmail-1.03-orig/subfderr.c qmail-1.03-ldap-20060201-orig/subfderr.c
--- qmail-1.03-orig/subfderr.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/subfderr.c	2006-02-25 11:00:56.000000000 +0100
@@ -3,5 +3,5 @@
 #include "subfd.h"
 
 char subfd_errbuf[256];
-static substdio it = SUBSTDIO_FDBUF(write,2,subfd_errbuf,256);
+static substdio it = SUBSTDIO_FDBUF(subwrite,2,subfd_errbuf,256);
 substdio *subfderr = &it;
diff -ruN qmail-1.03-orig/subfd.h qmail-1.03-ldap-20060201-orig/subfd.h
--- qmail-1.03-orig/subfd.h	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/subfd.h	2006-02-25 11:00:56.000000000 +0100
@@ -9,7 +9,7 @@
 extern substdio *subfdoutsmall;
 extern substdio *subfderr;
 
-extern int subfd_read();
-extern int subfd_readsmall();
+extern int subfd_read(int, void *, int);
+extern int subfd_readsmall(int, void *, int);
 
 #endif
diff -ruN qmail-1.03-orig/subfdin.c qmail-1.03-ldap-20060201-orig/subfdin.c
--- qmail-1.03-orig/subfdin.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/subfdin.c	2006-02-25 11:00:56.000000000 +0100
@@ -2,10 +2,10 @@
 #include "substdio.h"
 #include "subfd.h"
 
-int subfd_read(fd,buf,len) int fd; char *buf; int len;
+int subfd_read(fd,buf,len) int fd; void *buf; int len;
 {
   if (substdio_flush(subfdout) == -1) return -1;
-  return read(fd,buf,len);
+  return subread(fd,buf,len);
 }
 
 char subfd_inbuf[SUBSTDIO_INSIZE];
diff -ruN qmail-1.03-orig/subfdins.c qmail-1.03-ldap-20060201-orig/subfdins.c
--- qmail-1.03-orig/subfdins.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/subfdins.c	2006-02-25 11:00:56.000000000 +0100
@@ -2,10 +2,10 @@
 #include "substdio.h"
 #include "subfd.h"
 
-int subfd_readsmall(fd,buf,len) int fd; char *buf; int len;
+int subfd_readsmall(fd,buf,len) int fd; void *buf; int len;
 {
   if (substdio_flush(subfdoutsmall) == -1) return -1;
-  return read(fd,buf,len);
+  return subread(fd,buf,len);
 }
 
 char subfd_inbufsmall[256];
diff -ruN qmail-1.03-orig/subfdout.c qmail-1.03-ldap-20060201-orig/subfdout.c
--- qmail-1.03-orig/subfdout.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/subfdout.c	2006-02-25 11:00:56.000000000 +0100
@@ -3,5 +3,5 @@
 #include "subfd.h"
 
 char subfd_outbuf[SUBSTDIO_OUTSIZE];
-static substdio it = SUBSTDIO_FDBUF(write,1,subfd_outbuf,SUBSTDIO_OUTSIZE);
+static substdio it = SUBSTDIO_FDBUF(subwrite,1,subfd_outbuf,SUBSTDIO_OUTSIZE);
 substdio *subfdout = &it;
diff -ruN qmail-1.03-orig/subfdouts.c qmail-1.03-ldap-20060201-orig/subfdouts.c
--- qmail-1.03-orig/subfdouts.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/subfdouts.c	2006-02-25 11:00:56.000000000 +0100
@@ -3,5 +3,5 @@
 #include "subfd.h"
 
 char subfd_outbufsmall[256];
-static substdio it = SUBSTDIO_FDBUF(write,1,subfd_outbufsmall,256);
+static substdio it = SUBSTDIO_FDBUF(subwrite,1,subfd_outbufsmall,256);
 substdio *subfdoutsmall = &it;
diff -ruN qmail-1.03-orig/subgetopt.c qmail-1.03-ldap-20060201-orig/subgetopt.c
--- qmail-1.03-orig/subgetopt.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/subgetopt.c	2006-02-25 11:00:56.000000000 +0100
@@ -28,10 +28,10 @@
 int sgopt(argc,argv,opts)
 int argc;
 char **argv;
-char *opts;
+const char *opts;
 {
   int c;
-  char *s;
+  const char *s;
 
   optarg = 0;
   if (!argv || (optind >= argc) || !argv[optind]) return optdone;
diff -ruN qmail-1.03-orig/subgetopt.h qmail-1.03-ldap-20060201-orig/subgetopt.h
--- qmail-1.03-orig/subgetopt.h	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/subgetopt.h	2006-02-25 11:00:56.000000000 +0100
@@ -13,7 +13,7 @@
 
 #define SUBGETOPTDONE -1
 
-extern int subgetopt();
+extern int subgetopt(int, char **, const char *);
 extern char *subgetoptarg;
 extern int subgetoptind;
 extern int subgetoptpos;
diff -ruN qmail-1.03-orig/substdi.c qmail-1.03-ldap-20060201-orig/substdi.c
--- qmail-1.03-orig/substdi.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/substdi.c	2006-02-25 11:00:56.000000000 +0100
@@ -6,7 +6,7 @@
 register int (*op)();
 register int fd;
 register char *buf;
-register int len;
+register unsigned int len;
 {
   register int r;
 
@@ -20,9 +20,9 @@
 static int getthis(s,buf,len)
 register substdio *s;
 register char *buf;
-register int len;
+register unsigned int len;
 {
-  register int r;
+  register unsigned int r;
   register int q;
  
   r = s->p;
@@ -53,12 +53,13 @@
 int substdio_bget(s,buf,len)
 register substdio *s;
 register char *buf;
-register int len;
+register unsigned int len;
 {
-  register int r;
+  unsigned int u;
+  int r;
  
   if (s->p > 0) return getthis(s,buf,len);
-  r = s->n; if (r <= len) return oneread(s->op,s->fd,buf,r);
+  u = s->n; if (u <= len) return oneread(s->op,s->fd,buf,u);
   r = substdio_feed(s); if (r <= 0) return r;
   return getthis(s,buf,len);
 }
@@ -66,7 +67,7 @@
 int substdio_get(s,buf,len)
 register substdio *s;
 register char *buf;
-register int len;
+register unsigned int len;
 {
   register int r;
  
@@ -84,7 +85,7 @@
 
 void substdio_seek(s,len)
 register substdio *s;
-register int len;
+register unsigned int len;
 {
   s->n += len;
   s->p -= len;
diff -ruN qmail-1.03-orig/substdio.c qmail-1.03-ldap-20060201-orig/substdio.c
--- qmail-1.03-orig/substdio.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/substdio.c	2006-02-25 11:00:56.000000000 +0100
@@ -5,7 +5,7 @@
 register int (*op)();
 register int fd;
 register char *buf;
-register int len;
+register unsigned int len;
 {
   s->x = buf;
   s->fd = fd;
diff -ruN qmail-1.03-orig/substdio.h qmail-1.03-ldap-20060201-orig/substdio.h
--- qmail-1.03-orig/substdio.h	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/substdio.h	2006-02-25 11:00:56.000000000 +0100
@@ -3,30 +3,30 @@
 
 typedef struct substdio {
   char *x;
-  int p;
-  int n;
+  unsigned int p;
+  unsigned int n;
   int fd;
-  int (*op)();
+  int (*op)(int, void *, int);
 } substdio;
 
 #define SUBSTDIO_FDBUF(op,fd,buf,len) { (buf), 0, (len), (fd), (op) }
 
-extern void substdio_fdbuf();
+extern void substdio_fdbuf(substdio *, int (*)(int, void *, int), int, char *, unsigned int);
 
-extern int substdio_flush();
-extern int substdio_put();
-extern int substdio_bput();
-extern int substdio_putflush();
-extern int substdio_puts();
-extern int substdio_bputs();
-extern int substdio_putsflush();
-
-extern int substdio_get();
-extern int substdio_bget();
-extern int substdio_feed();
+extern int substdio_flush(substdio *);
+extern int substdio_put(substdio *, const char *, unsigned int);
+extern int substdio_bput(substdio *, const char *, unsigned int);
+extern int substdio_putflush(substdio *, const char *, unsigned int);
+extern int substdio_puts(substdio *, const char *);
+extern int substdio_bputs(substdio *, const char *);
+extern int substdio_putsflush(substdio *, const char *);
+
+extern int substdio_get(substdio *, char *, unsigned int);
+extern int substdio_bget(substdio *, char *, unsigned int);
+extern int substdio_feed(substdio *);
 
-extern char *substdio_peek();
-extern void substdio_seek();
+extern char *substdio_peek(substdio *);
+extern void substdio_seek(substdio *, unsigned int);
 
 #define substdio_fileno(s) ((s)->fd)
 
@@ -42,6 +42,6 @@
     : substdio_bput((s),&(c),1) \
   )
 
-extern int substdio_copy();
+extern int substdio_copy(substdio *, substdio *);
 
 #endif
diff -ruN qmail-1.03-orig/substdo.c qmail-1.03-ldap-20060201-orig/substdo.c
--- qmail-1.03-orig/substdo.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/substdo.c	2006-02-25 11:00:56.000000000 +0100
@@ -6,8 +6,8 @@
 static int allwrite(op,fd,buf,len)
 register int (*op)();
 register int fd;
-register char *buf;
-register int len;
+register const char *buf;
+register unsigned int len;
 {
   register int w;
 
@@ -27,7 +27,7 @@
 int substdio_flush(s)
 register substdio *s;
 {
-  register int p;
+  register unsigned int p;
  
   p = s->p;
   if (!p) return 0;
@@ -37,10 +37,10 @@
 
 int substdio_bput(s,buf,len)
 register substdio *s;
-register char *buf;
-register int len;
+register const char *buf;
+register unsigned int len;
 {
-  register int n;
+  register unsigned int n;
  
   while (len > (n = s->n - s->p)) {
     byte_copy(s->x + s->p,n,buf); s->p += n; buf += n; len -= n;
@@ -54,10 +54,10 @@
 
 int substdio_put(s,buf,len)
 register substdio *s;
-register char *buf;
-register int len;
+register const char *buf;
+register unsigned int len;
 {
-  register int n;
+  register unsigned int n;
  
   n = s->n;
   if (len > n - s->p) {
@@ -79,8 +79,8 @@
 
 int substdio_putflush(s,buf,len)
 register substdio *s;
-register char *buf;
-register int len;
+register const char *buf;
+register unsigned int len;
 {
   if (substdio_flush(s) == -1) return -1;
   return allwrite(s->op,s->fd,buf,len);
@@ -88,21 +88,21 @@
 
 int substdio_bputs(s,buf)
 register substdio *s;
-register char *buf;
+register const char *buf;
 {
   return substdio_bput(s,buf,str_len(buf));
 }
 
 int substdio_puts(s,buf)
 register substdio *s;
-register char *buf;
+register const char *buf;
 {
   return substdio_put(s,buf,str_len(buf));
 }
 
 int substdio_putsflush(s,buf)
 register substdio *s;
-register char *buf;
+register const char *buf;
 {
   return substdio_putflush(s,buf,str_len(buf));
 }
diff -ruN qmail-1.03-orig/TARGETS qmail-1.03-ldap-20060201-orig/TARGETS
--- qmail-1.03-orig/TARGETS	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/TARGETS	2006-02-25 11:00:55.000000000 +0100
@@ -147,9 +147,8 @@
 prot.o
 coe.o
 cdb_hash.o
-cdb_unpack.o
-cdb_seek.o
 cdb.a
+cdb.o
 auto-uid.o
 auto-uid
 auto-gid.o
@@ -221,10 +220,7 @@
 qmail-showctl.o
 qmail-showctl
 qmail-newu.o
-cdbmss.o
-cdbmake_pack.o
-cdbmake_hash.o
-cdbmake_add.o
+cdb_make.o
 cdbmake.a
 qmail-newu
 qmail-pw2u.o
@@ -385,3 +381,82 @@
 man
 setup
 check
+auth_imap
+Makefile.cdb-p
+auth_imap.o
+auth_mod.o
+auth_pop
+auth_pop.o
+auth_smtp
+auth_smtp.o
+auto_userl.c
+auto_userl.o
+base64.o
+byte_repl.o
+case_startb.o
+check.o
+checkpassword.o
+condwrite
+condwrite.o
+digest
+digest.o
+digest_md4.o
+digest_md5.o
+digest_rmd160.o
+digest_sha1.o
+dirmaker.o
+endian
+endian.o
+execcheck.o
+localdelivery.o
+locallookup.o
+maildir++.o
+mailmagic.o
+mailmaker.o
+output.o
+passwd.o
+pbsadd
+pbsadd.o
+pbscheck
+pbscheck.o
+pbsdbd
+pbsdbd.o
+pbsexec.o
+qldap-cluster.o
+qldap-debug.o
+qldap-errno.o
+qldap-filter.o
+qldap-profile.o
+qldap.a
+qldap.o
+qmail-cdb
+qmail-cdb.o
+qmail-forward
+qmail-forward.o
+qmail-group
+qmail-group.o
+qmail-imapd-ssl.run
+qmail-imapd.run
+qmail-ldaplookup
+qmail-ldaplookup.o
+qmail-pbsdbd.run
+qmail-pop3d-ssl.run
+qmail-pop3d.run
+qmail-qmqpd.run
+qmail-quotawarn
+qmail-quotawarn.o
+qmail-reply
+qmail-reply.o
+qmail-secretary
+qmail-secretary.o
+qmail-smtpd.run
+qmail-todo
+qmail-todo.o
+qmail-verify
+qmail-verify.o
+qmail.run
+rbl.o
+read-ctrl.o
+readwrite.o
+smtpcall.o
+xtext.o
diff -ruN qmail-1.03-orig/tcp-env.c qmail-1.03-ldap-20060201-orig/tcp-env.c
--- qmail-1.03-orig/tcp-env.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/tcp-env.c	2006-02-25 11:00:56.000000000 +0100
@@ -2,6 +2,7 @@
 #include <sys/socket.h>
 #include <sys/param.h>
 #include <netinet/in.h>
+#include <unistd.h>
 #include "sig.h"
 #include "stralloc.h"
 #include "str.h"
@@ -30,7 +31,7 @@
 
 char temp[IPFMT + FMT_ULONG];
 
-void main(argc,argv)
+int main(argc,argv)
 int argc;
 char *argv[];
 {
@@ -125,5 +126,5 @@
 
  sig_pipedefault();
  execvp(*argv,argv);
- die();
+ return 111;
 }
diff -ruN qmail-1.03-orig/tcpto.c qmail-1.03-ldap-20060201-orig/tcpto.c
--- qmail-1.03-orig/tcpto.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/tcpto.c	2006-02-25 11:00:56.000000000 +0100
@@ -1,3 +1,4 @@
+#include <unistd.h>
 #include "tcpto.h"
 #include "open.h"
 #include "lock.h"
@@ -77,6 +78,7 @@
  int firstpos;
  datetime_sec lastwhen;
 
+ firstwhen = 0;
  if (!flagerr)
    if (!flagwasthere)
      return; /* could have been added, but not worth the effort to check */
diff -ruN qmail-1.03-orig/tcpto_clean.c qmail-1.03-ldap-20060201-orig/tcpto_clean.c
--- qmail-1.03-orig/tcpto_clean.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/tcpto_clean.c	2006-02-25 11:00:56.000000000 +0100
@@ -1,3 +1,4 @@
+#include <unistd.h>
 #include "tcpto.h"
 #include "open.h"
 #include "substdio.h"
@@ -5,15 +6,15 @@
 
 char tcpto_cleanbuf[1024];
 
-void tcpto_clean() /* running from queue/mess */
+void tcpto_clean(void) /* running from queue/mess */
 {
  int fd;
- int i;
+ unsigned int i;
  substdio ss;
 
  fd = open_write("../lock/tcpto");
  if (fd == -1) return;
- substdio_fdbuf(&ss,write,fd,tcpto_cleanbuf,sizeof(tcpto_cleanbuf));
+ substdio_fdbuf(&ss,subwrite,fd,tcpto_cleanbuf,sizeof(tcpto_cleanbuf));
  for (i = 0;i < sizeof(tcpto_cleanbuf);++i) substdio_put(&ss,"",1);
  substdio_flush(&ss); /* if it fails, bummer */
  close(fd);
diff -ruN qmail-1.03-orig/tcpto.h qmail-1.03-ldap-20060201-orig/tcpto.h
--- qmail-1.03-orig/tcpto.h	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/tcpto.h	2006-02-25 11:00:56.000000000 +0100
@@ -1,8 +1,10 @@
 #ifndef TCPTO_H
 #define TCPTO_H
 
-extern int tcpto();
-extern void tcpto_err();
-extern void tcpto_clean();
+struct ip_address;
+
+extern int tcpto(struct ip_address *);
+extern void tcpto_err(struct ip_address *, int);
+extern void tcpto_clean(void);
 
 #endif
diff -ruN qmail-1.03-orig/timeoutconn.c qmail-1.03-ldap-20060201-orig/timeoutconn.c
--- qmail-1.03-orig/timeoutconn.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/timeoutconn.c	2006-02-25 11:00:56.000000000 +0100
@@ -10,29 +10,32 @@
 #include "byte.h"
 #include "timeoutconn.h"
 
-int timeoutconn(s,ip,port,timeout)
-int s;
-struct ip_address *ip;
-unsigned int port;
-int timeout;
+int timeoutconn(int s, struct ip_address *ip, struct ip_address *outip,
+    unsigned int port, int timeout)
 {
   char ch;
-  struct sockaddr_in sin;
+  struct sockaddr_in s_in;
   char *x;
   fd_set wfds;
   struct timeval tv;
  
-  byte_zero(&sin,sizeof(sin));
-  byte_copy(&sin.sin_addr,4,ip);
-  x = (char *) &sin.sin_port;
-  x[1] = port; port >>= 8; x[0] = port;
-  sin.sin_family = AF_INET;
  
   if (ndelay_on(s) == -1) return -1;
  
-  /* XXX: could bind s */
+  /* bind() an outgoing ipaddr */
+  byte_zero(&s_in,sizeof(s_in));
+  byte_copy(&s_in.sin_addr.s_addr,4,outip);
+  s_in.sin_family = AF_INET;
+
+  if (bind(s,(struct sockaddr *) &s_in,sizeof(s_in)) == -1) return -1;
+  
+  byte_zero(&s_in,sizeof(s_in));
+  byte_copy(&s_in.sin_addr,4,ip);
+  x = (char *) &s_in.sin_port;
+  x[1] = port; port >>= 8; x[0] = port;
+  s_in.sin_family = AF_INET;
  
-  if (connect(s,(struct sockaddr *) &sin,sizeof(sin)) == 0) {
+  if (connect(s,(struct sockaddr *) &s_in,sizeof(s_in)) == 0) {
     ndelay_off(s);
     return 0;
   }
@@ -45,9 +48,9 @@
   if (select(s + 1,(fd_set *) 0,&wfds,(fd_set *) 0,&tv) == -1) return -1;
   if (FD_ISSET(s,&wfds)) {
     int dummy;
-    dummy = sizeof(sin);
-    if (getpeername(s,(struct sockaddr *) &sin,&dummy) == -1) {
-      read(s,&ch,1);
+    dummy = sizeof(s_in);
+    if (getpeername(s,(struct sockaddr *) &s_in,&dummy) == -1) {
+      subread(s,&ch,1);
       return -1;
     }
     ndelay_off(s);
diff -ruN qmail-1.03-orig/timeoutconn.h qmail-1.03-ldap-20060201-orig/timeoutconn.h
--- qmail-1.03-orig/timeoutconn.h	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/timeoutconn.h	2006-02-25 11:00:56.000000000 +0100
@@ -1,6 +1,9 @@
 #ifndef TIMEOUTCONN_H
 #define TIMEOUTCONN_H
 
-extern int timeoutconn();
+struct ip_address;
+
+extern int timeoutconn(int, struct ip_address *,
+    struct ip_address *, unsigned int, int);
 
 #endif
diff -ruN qmail-1.03-orig/timeoutread.c qmail-1.03-ldap-20060201-orig/timeoutread.c
--- qmail-1.03-orig/timeoutread.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/timeoutread.c	2006-02-25 11:00:56.000000000 +0100
@@ -15,7 +15,7 @@
   FD_SET(fd,&rfds);
 
   if (select(fd + 1,&rfds,(fd_set *) 0,(fd_set *) 0,&tv) == -1) return -1;
-  if (FD_ISSET(fd,&rfds)) return read(fd,buf,len);
+  if (FD_ISSET(fd,&rfds)) return subread(fd,buf,len);
 
   errno = error_timeout;
   return -1;
diff -ruN qmail-1.03-orig/timeoutread.h qmail-1.03-ldap-20060201-orig/timeoutread.h
--- qmail-1.03-orig/timeoutread.h	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/timeoutread.h	2006-02-25 11:00:56.000000000 +0100
@@ -1,6 +1,6 @@
 #ifndef TIMEOUTREAD_H
 #define TIMEOUTREAD_H
 
-extern int timeoutread();
+extern int timeoutread(int, int, char *, int);
 
 #endif
diff -ruN qmail-1.03-orig/timeoutwrite.c qmail-1.03-ldap-20060201-orig/timeoutwrite.c
--- qmail-1.03-orig/timeoutwrite.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/timeoutwrite.c	2006-02-25 11:00:56.000000000 +0100
@@ -3,7 +3,7 @@
 #include "error.h"
 #include "readwrite.h"
 
-int timeoutwrite(t,fd,buf,len) int t; int fd; char *buf; int len;
+int timeoutwrite(t,fd,buf,len) int t; int fd; const void *buf; int len;
 {
   fd_set wfds;
   struct timeval tv;
@@ -15,7 +15,7 @@
   FD_SET(fd,&wfds);
 
   if (select(fd + 1,(fd_set *) 0,&wfds,(fd_set *) 0,&tv) == -1) return -1;
-  if (FD_ISSET(fd,&wfds)) return write(fd,buf,len);
+  if (FD_ISSET(fd,&wfds)) return subwrite(fd,(void *)buf,len);
 
   errno = error_timeout;
   return -1;
diff -ruN qmail-1.03-orig/timeoutwrite.h qmail-1.03-ldap-20060201-orig/timeoutwrite.h
--- qmail-1.03-orig/timeoutwrite.h	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/timeoutwrite.h	2006-02-25 11:00:56.000000000 +0100
@@ -1,6 +1,6 @@
 #ifndef TIMEOUTWRITE_H
 #define TIMEOUTWRITE_H
 
-extern int timeoutwrite();
+extern int timeoutwrite(int, int, const void *, int);
 
 #endif
diff -ruN qmail-1.03-orig/TLS.readme qmail-1.03-ldap-20060201-orig/TLS.readme
--- qmail-1.03-orig/TLS.readme	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/TLS.readme	2006-02-25 11:00:55.000000000 +0100
@@ -0,0 +1,71 @@
+Frederik Vermeulen <jos-tls@kotnet.org> 20000112
+http://www.esat.kuleuven.ac.be/~vermeule/qmail/tls.patch
+
+This patch implements RFC2487 in qmail. This means you can 
+get SSL or TLS encrypted and authenticated SMTP between 
+the MTAs and between MTA and an MUA like Netscape4.5. 
+The code is considered experimental.
+
+Usage: - install OpenSSL-0.9.4 http://www.openssl.org/
+       - apply patch to qmail-1.03 http://www.qmail.org/ 
+         Makefile and conf-cc were patched for appropriate
+         linking. Apart from that, the patches to qmail-remote.c
+         and qmail-smtpd.c can be applied separately.
+       - provide a certificate in /var/qmail/control/cert.pem.
+         "make cert" makes a self-signed certificate.
+         "make cert-req" makes a certificate request.
+       - replace qmail-smtpd and/or qmail-remote binary
+       - verify operation (header information should show
+         something like
+         "Received [..] with DES-CBC3-SHA encrypted SMTP;")
+         If you don't have a server to test with, you can test
+         by sending mail to ping@linux.student.kuleuven.ac.be,
+         which will bounce your mail.
+
+Optional: - when TLSDEBUG is defined, some extra SSL info will be logged
+          - when a 512 RSA key is provided in /var/qmail/control/rsa512.pem,
+            this key will be used instead of on-the-fly generation by
+       	    qmail-smtpd. Daily replacement can be done by crontab:
+       	    01 01 * * * /usr/local/ssl/bin/openssl genrsa \
+       	     -out /var/qmail/control/rsa512.new 512 > /dev/null 2>&1;\
+       	     chmod 600 /var/qmail/control/rsa512.new; chown qmaild.qmail \
+       	     /var/qmail/control/rsa512.new; /bin/mv -f \
+       	     /var/qmail/control/rsa512.new /var/qmail/control/rsa512.pem
+          - server authentication:
+	    qmail-remote requires authentication from servers for which
+	    /var/qmail/control/tlshosts/host.dom.ain.pem exists.
+	    The .pem file contains the validating CA certificates
+	    (or self-signed server certificate with openssl-0.9.5).
+	    CommonName has to match.
+            WARNING: this option may cause mail to be delayed, bounced,
+	    doublebounced, and lost.
+          - client authentication:
+	    when relay rules would reject an incoming mail, 
+	    qmail-smtpd can allow the mail based on a presented cert.
+	    Certs are verified against a CA list in 
+	    /var/qmail/control/clientca.pem (eg. http://www.modssl.org/
+	    source/cvs/exp/mod_ssl/pkg.mod_ssl/pkg.sslcfg/ca-bundle.crt)
+            and the cert email-address has to match a line in
+	    /var/qmail/control/tlsclients. This email-address is logged
+	    in the headers.
+
+Copyright: Same terms as qmail
+           Links with OpenSSL
+           Inspiration and code from examples in SSLeay (E. Young
+           <eay@cryptsoft.com> and T. Hudson <tjh@cryptsoft.com>),
+           stunnel (M. Trojnara <mtrojnar@ddc.daewoo.com.pl>),
+	   Postfix/TLS (L. Jaenicke <Lutz.Jaenicke@aet.tu-cottbus.de>),
+	   and modssl (R. Engelschall <rse@engelschall.com>).
+           Debug code from Jean-Philippe Donnio <jpdonnio@cpod.fr>
+           Openssl usage consulting from Bodo M"oller <bmoeller@acm.org>
+
+
+Interoperability: - Netscape 4.5 and higher
+                  - Microsoft Outlook 5
+		  - Microsoft Exchange Internet Mail Server 5.5.2448.0
+                  - Postfix/TLS
+                    http://www.aet.TU-Cottbus.DE/personen/jaenicke/pfixtls/
+                  - Sendmail-TLS http://opensource.3gi.com/sendmail-tls/
+
+Patches: mailto:<jos-tls@kotnet.org>
+
diff -ruN qmail-1.03-orig/token822.c qmail-1.03-ldap-20060201-orig/token822.c
--- qmail-1.03-orig/token822.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/token822.c	2006-02-25 11:00:56.000000000 +0100
@@ -9,10 +9,11 @@
 void token822_reverse(ta)
 token822_alloc *ta;
 {
- int i;
- int n;
+ unsigned int i;
+ unsigned int n;
  struct token822 temp;
 
+ if (ta->len == 0) return;
  n = ta->len - 1;
  for (i = 0;i + i < n;++i)
   {
@@ -65,7 +66,7 @@
 static void atomcheck(t)
 struct token822 *t;
 {
- int i;
+ unsigned int i;
  char ch;
  for (i = 0;i < t->slen;++i)
   {
@@ -84,10 +85,10 @@
 unsigned int linelen;
 {
  struct token822 *t;
- int len;
+ unsigned int len;
  int ch;
- int i;
- int j;
+ unsigned int i;
+ unsigned int j;
  int lasttype;
  int newtype;
  char *s;
@@ -145,7 +146,7 @@
        *s++ = ',';
 #define NSUW \
  s[0] = '\n'; s[1] = ' '; \
- if (linee && (!linelen || (s - lineb <= linelen))) \
+ if (linee && (!linelen || ((unsigned long)(s - lineb) <= linelen))) \
   { while (linee < s) { linee[0] = linee[2]; ++linee; } linee -= 2; } \
  else { if (linee) lineb = linee + 1; linee = s; s += 2; }
        NSUW
@@ -184,9 +185,9 @@
 token822_alloc *ta;
 {
  struct token822 *t;
- int len;
- int i;
- int j;
+ unsigned int len;
+ unsigned int i;
+ unsigned int j;
  char *s;
 
  len = 0;
@@ -240,12 +241,12 @@
 stralloc *sa;
 stralloc *buf;
 {
- int i;
- int salen;
- int level;
+ unsigned int i;
+ unsigned int salen;
+ unsigned int level;
  struct token822 *t;
- int numtoks;
- int numchars;
+ unsigned int numtoks;
+ unsigned int numchars;
  char *cbuf;
 
  salen = sa->len;
@@ -403,7 +404,7 @@
 token822_alloc *taaddr;
 int (*callback)();
 {
- int i;
+ unsigned int i;
 
  if (callback(taaddr) != 1)
    return 0;
diff -ruN qmail-1.03-orig/token822.h qmail-1.03-ldap-20060201-orig/token822.h
--- qmail-1.03-orig/token822.h	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/token822.h	2006-02-25 11:00:56.000000000 +0100
@@ -4,23 +4,28 @@
 struct token822
  {
   int type;
-  char *s;
-  int slen;
+  const char *s;
+  unsigned int slen;
  }
 ;
 
 #include "gen_alloc.h"
+#include "stralloc.h"
+
 GEN_ALLOC_typedef(token822_alloc,struct token822,t,len,a)
 
-extern int token822_parse();
-extern int token822_addrlist();
-extern int token822_unquote();
-extern int token822_unparse();
+extern int token822_parse(token822_alloc *, stralloc *, stralloc *);
+extern int token822_addrlist(token822_alloc *, token822_alloc *,
+    token822_alloc *, int (*)());
+extern int token822_unquote(stralloc *, token822_alloc *);
+extern int token822_unparse(stralloc *, token822_alloc *, unsigned int);
+/* XXX not available in qmail-1.03
 extern void token822_free();
-extern void token822_reverse();
-extern int token822_ready();
-extern int token822_readyplus();
-extern int token822_append();
+*/
+extern void token822_reverse(token822_alloc *);
+extern int token822_ready(token822_alloc *, unsigned int);
+extern int token822_readyplus(token822_alloc *, unsigned int);
+extern int token822_append(token822_alloc *, struct token822 *);
 
 #define TOKEN822_ATOM 1
 #define TOKEN822_QUOTE 2
diff -ruN qmail-1.03-orig/trigger.c qmail-1.03-ldap-20060201-orig/trigger.c
--- qmail-1.03-orig/trigger.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/trigger.c	2006-02-25 11:00:56.000000000 +0100
@@ -1,3 +1,4 @@
+#include <unistd.h>
 #include "select.h"
 #include "open.h"
 #include "trigger.h"
@@ -8,7 +9,7 @@
 static int fdw = -1;
 #endif
 
-void trigger_set()
+void trigger_set(void)
 {
  if (fd != -1)
    close(fd);
diff -ruN qmail-1.03-orig/trigger.h qmail-1.03-ldap-20060201-orig/trigger.h
--- qmail-1.03-orig/trigger.h	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/trigger.h	2006-02-25 11:00:56.000000000 +0100
@@ -1,8 +1,10 @@
 #ifndef TRIGGER_H
 #define TRIGGER_H
 
-extern void trigger_set();
-extern void trigger_selprep();
-extern int trigger_pulled();
+#include "select.h"
+
+extern void trigger_set(void);
+extern void trigger_selprep(int *, fd_set *);
+extern int trigger_pulled(fd_set *);
 
 #endif
diff -ruN qmail-1.03-orig/triggerpull.c qmail-1.03-ldap-20060201-orig/triggerpull.c
--- qmail-1.03-orig/triggerpull.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/triggerpull.c	2006-02-25 11:00:56.000000000 +0100
@@ -1,8 +1,10 @@
+#include <unistd.h>
+#include "readwrite.h"
 #include "ndelay.h"
 #include "open.h"
 #include "triggerpull.h"
 
-void triggerpull()
+void triggerpull(void)
 {
  int fd;
 
diff -ruN qmail-1.03-orig/triggerpull.h qmail-1.03-ldap-20060201-orig/triggerpull.h
--- qmail-1.03-orig/triggerpull.h	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/triggerpull.h	2006-02-25 11:00:56.000000000 +0100
@@ -1,6 +1,6 @@
 #ifndef TRIGGERPULL_H
 #define TRIGGERPULL_H
 
-extern void triggerpull();
+extern void triggerpull(void);
 
 #endif
diff -ruN qmail-1.03-orig/wait.h qmail-1.03-ldap-20060201-orig/wait.h
--- qmail-1.03-orig/wait.h	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-ldap-20060201-orig/wait.h	2006-02-25 11:00:56.000000000 +0100
@@ -1,11 +1,12 @@
 #ifndef WAIT_H
 #define WAIT_H
 
-extern int wait_pid();
-extern int wait_nohang();
+extern int wait_pid(int *, int);
+extern int wait_nohang(int *);
+/* XXX not available in qmail-1.03
 extern int wait_stop();
 extern int wait_stopnohang();
-
+*/
 #define wait_crashed(w) ((w) & 127)
 #define wait_exitcode(w) ((w) >> 8)
 #define wait_stopsig(w) ((w) >> 8)
diff -ruN qmail-1.03-orig/xtext.c qmail-1.03-ldap-20060201-orig/xtext.c
--- qmail-1.03-orig/xtext.c	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/xtext.c	2006-02-25 11:00:56.000000000 +0100
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2005 Claudio Jeker,
+ *      Internet Business Solutions AG, CH-8005 Zürich, Switzerland
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Internet Business
+ *      Solutions AG and its contributors.
+ * 4. Neither the name of the author nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include "stralloc.h"
+#include "xtext.h"
+
+static int xtext_doit(stralloc *, stralloc *);
+static const char ioHexArray[] = "0123456789abcdef";
+
+static int
+xtext_doit(stralloc *saout, stralloc *sain)
+{
+	unsigned int	n;
+	char		x[3];
+	unsigned char	c;
+
+	if (!stralloc_ready(saout,sain->len))
+		return (0);
+	x[0] = '+';
+	for (n = 0; n < sain->len; n++) {
+		c = sain->s[n];
+		if (c < 33 || c > 126 || c == '=' || c == '+') {
+			x[1] = ioHexArray[(c >> 4) & 0x0f];
+			x[2] = ioHexArray[c & 0x0f];
+			if (!stralloc_catb(saout, x, sizeof(x)))
+				return (0);
+		} else
+			if (!stralloc_append(saout, &c))
+				return (0);
+	}
+	return (1);
+}
+
+int
+xtext_needed(const char *s, unsigned int n)
+{
+	unsigned char	c;
+
+	for (; n > 0; n--) {
+		c = *s++;
+		if (c < 33 || c > 126 || c == '=' || c == '+')
+			return (1);
+	}
+	return (0);
+}
+
+int
+xtext_quote(stralloc *saout, stralloc *sain)
+{
+	if (xtext_needed(sain->s, sain->len))
+		return (xtext_doit(saout, sain));
+	return (stralloc_copy(saout,sain));
+}
+
diff -ruN qmail-1.03-orig/xtext.h qmail-1.03-ldap-20060201-orig/xtext.h
--- qmail-1.03-orig/xtext.h	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-ldap-20060201-orig/xtext.h	2006-02-25 11:00:56.000000000 +0100
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2005 Claudio Jeker,
+ *      Internet Business Solutions AG, CH-8005 Zürich, Switzerland
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Internet Business
+ *      Solutions AG and its contributors.
+ * 4. Neither the name of the author nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#ifndef _XTEXT_H_
+#define _XTEXT_H_
+
+int xtext_needed(const char *, unsigned int);
+int xtext_quote(stralloc *, stralloc *);
+
+#endif
