summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--vda/postfix-2.4.6-vda-ng-r2.patch.gzbin12397 -> 0 bytes
-rw-r--r--vda/postfix-2.5.1-vda-ng-r1.patch.gzbin0 -> 28964 bytes
-rw-r--r--vda/postfix-2.5.1-vda-ng.patch2084
3 files changed, 2031 insertions, 53 deletions
diff --git a/vda/postfix-2.4.6-vda-ng-r2.patch.gz b/vda/postfix-2.4.6-vda-ng-r2.patch.gz
deleted file mode 100644
index 714653f..0000000
--- a/vda/postfix-2.4.6-vda-ng-r2.patch.gz
+++ /dev/null
Binary files differ
diff --git a/vda/postfix-2.5.1-vda-ng-r1.patch.gz b/vda/postfix-2.5.1-vda-ng-r1.patch.gz
new file mode 100644
index 0000000..e16ea02
--- /dev/null
+++ b/vda/postfix-2.5.1-vda-ng-r1.patch.gz
Binary files differ
diff --git a/vda/postfix-2.5.1-vda-ng.patch b/vda/postfix-2.5.1-vda-ng.patch
index f73fafe..f3b5731 100644
--- a/vda/postfix-2.5.1-vda-ng.patch
+++ b/vda/postfix-2.5.1-vda-ng.patch
@@ -1,6 +1,6 @@
-diff -Nru postfix-2.4.6/README_FILES/VDA_README postfix-2.4.6-vda-ng/README_FILES/VDA_README
---- postfix-2.4.6/README_FILES/VDA_README 1970-01-01 01:00:00.000000000 +0100
-+++ postfix-2.4.6-vda-ng/README_FILES/VDA_README 2007-11-24 12:48:53.000000000 +0100
+diff -Nru postfix-2.5.1/README_FILES/VDA_README postfix-2.5.1-vda-ng/README_FILES/VDA_README
+--- postfix-2.5.1/README_FILES/VDA_README 1970-01-01 01:00:00.000000000 +0100
++++ postfix-2.5.1-vda-ng/README_FILES/VDA_README 2008-03-15 15:06:00.007734561 +0100
@@ -0,0 +1,97 @@
+Installation:
+
@@ -99,10 +99,1453 @@ diff -Nru postfix-2.4.6/README_FILES/VDA_README postfix-2.4.6-vda-ng/README_FILE
+user2@domain.com.br # M2007022617 /^subject:.*Viagra.*/m REJECT /^subject:.*trash.*/m MOVE SpamFolder /^subject:.*pharmacy.*/m DISCARD
+
+More informations can be found at http://vda.sourceforge.net
-diff -Nru postfix-2.4.6/src/global/mail_params.h postfix-2.4.6-vda-ng/src/global/mail_params.h
---- postfix-2.4.6/src/global/mail_params.h 2007-07-11 01:47:45.000000000 +0200
-+++ postfix-2.4.6-vda-ng/src/global/mail_params.h 2007-11-24 12:48:53.000000000 +0100
-@@ -2106,6 +2106,54 @@
+diff -Nru postfix-2.5.1/postfix-2.4.6-vda-ng.patch postfix-2.5.1-vda-ng/postfix-2.4.6-vda-ng.patch
+--- postfix-2.5.1/postfix-2.4.6-vda-ng.patch 1970-01-01 01:00:00.000000000 +0100
++++ postfix-2.5.1-vda-ng/postfix-2.4.6-vda-ng.patch 2008-03-15 15:05:52.167991798 +0100
+@@ -0,0 +1,1439 @@
++diff -Nru postfix-2.4.6/README_FILES/VDA_README postfix-2.4.6-vda-ng/README_FILES/VDA_README
++--- postfix-2.4.6/README_FILES/VDA_README 1970-01-01 01:00:00.000000000 +0100
+++++ postfix-2.4.6-vda-ng/README_FILES/VDA_README 2007-11-24 12:48:53.000000000 +0100
++@@ -0,0 +1,97 @@
+++Installation:
+++
+++1 - Get the Postfix source code ( http://www.postfix.org/ )
+++2 - Get this software ( http://vda.sourceforge.net ) for your Postfix version
+++3 - Unpack the source code: tar -xvzf postfix-VERSION.tar.gz
+++4 - Unpack the patch: gunzip postfix-VERSION-vda-ng-rREV.patch.gz
+++5 - Apply the patch: cd postfix-VERSION; patch -p1 < ../postfix-VERSION-vda-ng-rREV.patch
+++6 - Configure
+++7 - Make
+++
+++Configuration:
+++
+++#### Postfix main.cf
+++
+++# I use only virtual as local delivery
+++mailbox_transport = virtual
+++
+++# Base directory where the mailboxes are located
+++virtual_mailbox_base = /var/virtualmail
+++
+++# Virtual users maps
+++virtual_mailbox_maps = hash:/etc/postfix/vmailbox
+++transport_maps = hash:/etc/postfix/vtransport
+++
+++# Minimal permitted UID value (for virtual_uid_maps)
+++virtual_minimum_uid = 1000
+++
+++# GIDs and UIDs to run as
+++# Can also be stored in hash, mysql, ...
+++virtual_uid_maps = static:4000
+++virtual_gid_maps = static:4000
+++
+++# A maximum size limit for a mailbox
+++virtual_mailbox_limit = 100000000
+++
+++# Quota values maps
+++virtual_mailbox_limit_maps = hash:/etc/postfix/vquota
+++
+++# Limit only the INBOX
+++# (useful for when you have IMAP users)
+++virtual_mailbox_limit_inbox = no
+++
+++# Enable limits smaller than maximum message size
+++virtual_mailbox_limit_override = yes
+++
+++# Enable Maildir++ extensions for faster maildir quota calculation
+++# (maildirsize file and ",S=<size>" filename extension)
+++# Needs Maildir++ compatible IMAP servers, like Courier-IMAP
+++virtual_maildir_extended = yes
+++
+++# Always bounce the message when quota reached
+++virtual_overquota_bounce = yes
+++
+++# Custom message to send when bouncing
+++#virtual_maildir_limit_message = "Sorry, maximum quota reached!"
+++
+++# Custom message maps for the bounces
+++#virtual_maildir_limit_message_maps = hash:/etc/postfix/vmsg
+++
+++# Also count the Trash folder when calculating quotas?
+++virtual_trash_count = yes
+++
+++# The name of the Trash folder
+++# (if it doesn't need to be calculated)
+++#virtual_trash_name = ".Trash"
+++
+++# Enable the Maildirfilter feature
+++virtual_maildir_filter = yes
+++
+++# Maildirfilter maps
+++virtual_maildir_filter_maps = hash:/etc/postfix/vfilter
+++
+++#### Mailbox users file - vmailbox
+++user@domain.com.br /path/to/mailbox - path relative to virtual_mailbox_base
+++user1@domain.com.br /domain.com.br/user1 - no trailing slash, user has a MAILBOX
+++user2@domain.com.br /domain.com.br/user2 - no trailing slash, user has a MAILBOX
+++user1@domain.net.br /domain.net.br/user1/ - trailing slash, user has a MAILDIR
+++user2@domain.net.br /domain.net.br/user2/ - trailing slash, user has a MAILDIR
+++
+++#### Quota users file - vquota
+++user@domain.com.br QUOTA IN BYTES
+++user1@domain.com.br 2048000
+++user2@domain.com.br 2048000
+++user1@domain.net.br 5192000
+++user2@domain.net.br 0 - NO QUOTA
+++
+++#### Maildirfilter file - vfilter
+++# ATTENTION: the syntax for maildirfilter values is the following:
+++# the # sign, followed by a space, followed by a M (uppercase), then a modification time value
+++# (you need to change this when you change the regexps) made of a maximum of 10 digits, then a
+++# space again and an arbitrary number of regexps (a regexp always starts with /^ and ends with
+++# a space) and their corresponding actions
+++user@domain.com.br # M<timestamp> regexp1 action1 regexp2 action2 ...
+++user1@domain.net.br # M2007022701 /^subject:.*BAD.*/m DISCARD /^from:.*user@domain.com.br*/m MOVE Trash
+++user2@domain.com.br # M2007022617 /^subject:.*Viagra.*/m REJECT /^subject:.*trash.*/m MOVE SpamFolder /^subject:.*pharmacy.*/m DISCARD
+++
+++More informations can be found at http://vda.sourceforge.net
++diff -Nru postfix-2.4.6/src/global/mail_params.h postfix-2.4.6-vda-ng/src/global/mail_params.h
++--- postfix-2.4.6/src/global/mail_params.h 2007-07-11 01:47:45.000000000 +0200
+++++ postfix-2.4.6-vda-ng/src/global/mail_params.h 2007-11-24 12:48:53.000000000 +0100
++@@ -2106,6 +2106,54 @@
++ #define DEF_VIRT_GID_MAPS ""
++ extern char *var_virt_gid_maps;
++
+++#define VAR_VIRT_MAILBOX_LIMIT_MAPS "virtual_mailbox_limit_maps"
+++#define DEF_VIRT_MAILBOX_LIMIT_MAPS ""
+++extern char *var_virt_mailbox_limit_maps;
+++
+++#define VAR_VIRT_MAILBOX_LIMIT_INBOX "virtual_mailbox_limit_inbox"
+++#define DEF_VIRT_MAILBOX_LIMIT_INBOX 0
+++extern bool var_virt_mailbox_limit_inbox;
+++
+++#define VAR_VIRT_MAILBOX_LIMIT_OVERRIDE "virtual_mailbox_limit_override"
+++#define DEF_VIRT_MAILBOX_LIMIT_OVERRIDE 0
+++extern bool var_virt_mailbox_limit_override;
+++
+++#define VAR_VIRT_MAILDIR_EXTENDED "virtual_maildir_extended"
+++#define DEF_VIRT_MAILDIR_EXTENDED 0
+++extern bool var_virt_maildir_extended;
+++
+++#define VAR_VIRT_OVERQUOTA_BOUNCE "virtual_overquota_bounce"
+++#define DEF_VIRT_OVERQUOTA_BOUNCE 0
+++extern bool var_virt_overquota_bounce;
+++
+++#define VAR_VIRT_MAILDIR_LIMIT_MESSAGE "virtual_maildir_limit_message"
+++#define DEF_VIRT_MAILDIR_LIMIT_MESSAGE "Sorry, the user's maildir has overdrawn his diskspace quota, please try again later."
+++extern char *var_virt_maildir_limit_message;
+++
+++#define VAR_VIRT_MAILDIR_LIMIT_MESSAGE_MAPS "virtual_maildir_limit_message_maps"
+++#define DEF_VIRT_MAILDIR_LIMIT_MESSAGE_MAPS ""
+++extern char *var_virt_maildir_limit_message_maps;
+++
+++#define VAR_VIRT_MAILDIR_SUFFIX "virtual_maildir_suffix"
+++#define DEF_VIRT_MAILDIR_SUFFIX ""
+++extern char *var_virt_maildir_suffix;
+++
+++#define VAR_VIRT_TRASH_COUNT "virtual_trash_count"
+++#define DEF_VIRT_TRASH_COUNT 0
+++extern bool var_virt_trash_count;
+++
+++#define VAR_VIRT_TRASH_NAME "virtual_trash_name"
+++#define DEF_VIRT_TRASH_NAME ".Trash"
+++extern char *var_virt_trash_name;
+++
+++#define VAR_VIRT_MAILDIR_FILTER "virtual_maildir_filter"
+++#define DEF_VIRT_MAILDIR_FILTER 0
+++extern bool var_virt_maildir_filter;
+++
+++#define VAR_VIRT_MAILDIR_FILTER_MAPS "virtual_maildir_filter_maps"
+++#define DEF_VIRT_MAILDIR_FILTER_MAPS ""
+++extern char *var_virt_maildir_filter_maps;
+++
++ #define VAR_VIRT_MINUID "virtual_minimum_uid"
++ #define DEF_VIRT_MINUID 100
++ extern int var_virt_minimum_uid;
++diff -Nru postfix-2.4.6/src/util/file_limit.c postfix-2.4.6-vda-ng/src/util/file_limit.c
++--- postfix-2.4.6/src/util/file_limit.c 2003-10-22 20:48:36.000000000 +0200
+++++ postfix-2.4.6-vda-ng/src/util/file_limit.c 2007-11-24 12:48:53.000000000 +0100
++@@ -85,7 +85,11 @@
++ #else
++ struct rlimit rlim;
++
++- rlim.rlim_cur = rlim.rlim_max = limit;
+++ /* rlim_max can only be changed by root. */
+++ if (getrlimit(RLIMIT_FSIZE, &rlim) < 0)
+++ msg_fatal("getrlimit: %m");
+++ rlim.rlim_cur = limit;
+++
++ if (setrlimit(RLIMIT_FSIZE, &rlim) < 0)
++ msg_fatal("setrlimit: %m");
++ #ifdef SIGXFSZ
++diff -Nru postfix-2.4.6/src/virtual/mailbox.c postfix-2.4.6-vda-ng/src/virtual/mailbox.c
++--- postfix-2.4.6/src/virtual/mailbox.c 2006-06-26 14:59:19.000000000 +0200
+++++ postfix-2.4.6-vda-ng/src/virtual/mailbox.c 2007-11-26 12:30:21.000000000 +0100
++@@ -70,6 +70,70 @@
++ #define YES 1
++ #define NO 0
++
+++/* change_mailbox_limit - change limit for mailbox file */
+++static int change_mailbox_limit(LOCAL_STATE state, USER_ATTR usr_attr)
+++{
+++ char *myname = "change_mailbox_limit";
+++ const char *limit_res;
+++ long n = 0;
+++ int status = NO;
+++
+++ /*
+++ * Look up the virtual mailbox limit size for this user.
+++ * Fall back to virtual_mailbox_limit in case lookup failed.
+++ * If virtual mailbox limit size is negative, fall back to virtual_mailbox_limit.
+++ * If it's 0, set the mailbox limit to 0, which means unlimited.
+++ * If it's more than 0 (positive int), check if the value is smaller than the maximum message size,
+++ * if it is and the virtual mailbox limit can't be overridden, fall back to virtual_mailbox_limit and
+++ * warn the user, else use the value directly as the mailbox limit.
+++ */
+++ if (*var_virt_mailbox_limit_maps != 0 && (limit_res = mail_addr_find(virtual_mailbox_limit_maps, state.msg_attr.user, (char **) NULL)) != 0) {
+++ n = atol(limit_res);
+++ if (n > 0) {
+++ if ((n < var_message_limit) && (!var_virt_mailbox_limit_override)) {
+++ set_file_limit(var_virt_mailbox_limit);
+++ status = NO;
+++
+++ msg_warn("%s: recipient %s - virtual mailbox limit is "
+++ "smaller than %s in %s - falling back to %s",
+++ myname,
+++ state.msg_attr.user,
+++ VAR_MESSAGE_LIMIT,
+++ virtual_mailbox_limit_maps->title,
+++ VAR_VIRT_MAILBOX_LIMIT);
+++ }
+++ else {
+++ set_file_limit((off_t) n);
+++ status = YES;
+++
+++ if (msg_verbose)
+++ msg_info("%s: set virtual mailbox limit size for %s to %ld",
+++ myname, usr_attr.mailbox, n);
+++ }
+++ }
+++ else if (n == 0) {
+++ set_file_limit(OFF_T_MAX);
+++ status = YES;
+++
+++ if (msg_verbose)
+++ msg_info("%s: set virtual mailbox limit size for %s to %ld",
+++ myname, usr_attr.mailbox, OFF_T_MAX);
+++ }
+++ else {
+++ /* Invalid limit size (negative). Use default virtual_mailbox_limit. */
+++ set_file_limit(var_virt_mailbox_limit);
+++ status = NO;
+++ }
+++ }
+++ else {
+++ /* There is no limit in the maps. Use default virtual_mailbox_limit. */
+++ set_file_limit(var_virt_mailbox_limit);
+++ status = NO;
+++ }
+++
+++ return(status);
+++}
+++
++ /* deliver_mailbox_file - deliver to recipient mailbox */
++
++ static int deliver_mailbox_file(LOCAL_STATE state, USER_ATTR usr_attr)
++@@ -207,62 +271,72 @@
++ * Look up the mailbox owner rights. Defer in case of trouble.
++ */
++ uid_res = mail_addr_find(virtual_uid_maps, state.msg_attr.user,
++- IGNORE_EXTENSION);
++- if (uid_res == 0) {
++- msg_warn("recipient %s: not found in %s",
++- state.msg_attr.user, virtual_uid_maps->title);
++- dsb_simple(why, "4.3.5", "mail system configuration error");
++- *statusp = defer_append(BOUNCE_FLAGS(state.request),
++- BOUNCE_ATTR(state.msg_attr));
++- RETURN(YES);
+++ IGNORE_EXTENSION);
+++
+++ if ((uid_res = mail_addr_find(virtual_uid_maps, state.msg_attr.user, (char **) 0)) == 0) {
+++ if ((uid_res = maps_find(virtual_uid_maps, strchr(state.msg_attr.user, '@'), DICT_FLAG_FIXED)) == 0) {
+++ msg_warn("recipient %s: not found in %s", state.msg_attr.user, virtual_uid_maps->title);
+++ dsb_simple(why, "4.3.5", "mail system configuration error");
+++ *statusp = defer_append(BOUNCE_FLAGS(state.request), BOUNCE_ATTR(state.msg_attr));
+++ RETURN(YES);
+++ }
++ }
+++
++ if ((n = atol(uid_res)) < var_virt_minimum_uid) {
++- msg_warn("recipient %s: bad uid %s in %s",
++- state.msg_attr.user, uid_res, virtual_uid_maps->title);
++- dsb_simple(why, "4.3.5", "mail system configuration error");
++- *statusp = defer_append(BOUNCE_FLAGS(state.request),
++- BOUNCE_ATTR(state.msg_attr));
++- RETURN(YES);
+++ msg_warn("recipient %s: bad uid %s in %s", state.msg_attr.user, uid_res, virtual_uid_maps->title);
+++ dsb_simple(why, "4.3.5", "mail system configuration error");
+++ *statusp = defer_append(BOUNCE_FLAGS(state.request), BOUNCE_ATTR(state.msg_attr));
+++ RETURN(YES);
++ }
+++
++ usr_attr.uid = (uid_t) n;
++
++ /*
++ * Look up the mailbox group rights. Defer in case of trouble.
++ */
++ gid_res = mail_addr_find(virtual_gid_maps, state.msg_attr.user,
++- IGNORE_EXTENSION);
++- if (gid_res == 0) {
++- msg_warn("recipient %s: not found in %s",
++- state.msg_attr.user, virtual_gid_maps->title);
++- dsb_simple(why, "4.3.5", "mail system configuration error");
++- *statusp = defer_append(BOUNCE_FLAGS(state.request),
++- BOUNCE_ATTR(state.msg_attr));
++- RETURN(YES);
+++ IGNORE_EXTENSION);
+++
+++ if ((gid_res = mail_addr_find(virtual_gid_maps, state.msg_attr.user, (char **) 0)) == 0) {
+++ if ((gid_res = maps_find(virtual_gid_maps, strchr(state.msg_attr.user, '@'), DICT_FLAG_FIXED)) == 0) {
+++ msg_warn("recipient %s: not found in %s", state.msg_attr.user, virtual_gid_maps->title);
+++ dsb_simple(why, "4.3.5", "mail system configuration error");
+++ *statusp = defer_append(BOUNCE_FLAGS(state.request), BOUNCE_ATTR(state.msg_attr));
+++ RETURN(YES);
+++ }
++ }
+++
++ if ((n = atol(gid_res)) <= 0) {
++- msg_warn("recipient %s: bad gid %s in %s",
++- state.msg_attr.user, gid_res, virtual_gid_maps->title);
++- dsb_simple(why, "4.3.5", "mail system configuration error");
++- *statusp = defer_append(BOUNCE_FLAGS(state.request),
++- BOUNCE_ATTR(state.msg_attr));
++- RETURN(YES);
+++ msg_warn("recipient %s: bad gid %s in %s", state.msg_attr.user, gid_res, virtual_gid_maps->title);
+++ dsb_simple(why, "4.3.5", "mail system configuration error");
+++ *statusp = defer_append(BOUNCE_FLAGS(state.request), BOUNCE_ATTR(state.msg_attr));
+++ RETURN(YES);
++ }
+++
++ usr_attr.gid = (gid_t) n;
++
++ if (msg_verbose)
++- msg_info("%s[%d]: set user_attr: %s, uid = %u, gid = %u",
++- myname, state.level, usr_attr.mailbox,
++- (unsigned) usr_attr.uid, (unsigned) usr_attr.gid);
+++ msg_info("%s[%d]: set user_attr: %s, uid = %u, gid = %u",
+++ myname, state.level, usr_attr.mailbox,
+++ (unsigned) usr_attr.uid, (unsigned) usr_attr.gid);
++
++ /*
++ * Deliver to mailbox or to maildir.
++ */
++ #define LAST_CHAR(s) (s[strlen(s) - 1])
++
++- if (LAST_CHAR(usr_attr.mailbox) == '/')
++- *statusp = deliver_maildir(state, usr_attr);
++- else
++- *statusp = deliver_mailbox_file(state, usr_attr);
+++ if (LAST_CHAR(usr_attr.mailbox) == '/') {
+++ *statusp = deliver_maildir(state, usr_attr);
+++ }
+++ else {
+++ int changed_limit;
+++
+++ changed_limit = change_mailbox_limit(state, usr_attr);
+++ *statusp = deliver_mailbox_file(state, usr_attr);
+++
+++ if (changed_limit)
+++ set_file_limit(var_virt_mailbox_limit);
+++ }
++
++ /*
++ * Cleanup.
++diff -Nru postfix-2.4.6/src/virtual/maildir.c postfix-2.4.6-vda-ng/src/virtual/maildir.c
++--- postfix-2.4.6/src/virtual/maildir.c 2006-06-26 14:59:19.000000000 +0200
+++++ postfix-2.4.6-vda-ng/src/virtual/maildir.c 2007-11-24 13:20:57.000000000 +0100
++@@ -63,28 +63,406 @@
++ #include <mbox_open.h>
++ #include <dsn_util.h>
++
+++/* Patch library. */
+++
+++#include <sys/types.h> /* opendir(3), stat(2) */
+++#include <sys/stat.h> /* stat(2) */
+++#include <dirent.h> /* opendir(3) */
+++#include <unistd.h> /* stat(2) */
+++#include <stdlib.h> /* atol(3) */
+++#include <string.h> /* strrchr(3) */
+++#include <vstring_vstream.h>
+++#include <dict.h>
+++#include <dict_regexp.h>
+++#include <ctype.h>
+++#include <stdio.h>
+++#include <sys_defs.h>
+++#include <mail_addr_find.h>
+++
++ /* Application-specific. */
++
++ #include "virtual.h"
++
++-/* deliver_maildir - delivery to maildir-style mailbox */
+++/* Maildirsize maximal size. */
+++
+++#define SIZEFILE_MAX 5120
+++
+++/*
+++ * Chris Stratford <chriss@pipex.net>
+++ * Read the maildirsize file to get quota info.
+++ *
+++ * Arguments:
+++ * dirname: the maildir
+++ * countptr: number of messages
+++ *
+++ * Returns the size of all mails as read from maildirsize,
+++ * zero if it couldn't read the file.
+++ */
+++static long read_maildirsize(char *dirname, long *countptr)
+++{
+++ struct stat statbuf;
+++ VSTRING *sizefilename = vstring_alloc(1024);
+++ VSTREAM *sizefile;
+++ char *p;
+++ int len, first;
+++ long sum = 0, count = 0;
+++
+++ vstring_sprintf(sizefilename, "%s/%s", dirname, "maildirsize");
+++
+++ sizefile = vstream_fopen(STR(sizefilename), O_RDONLY, 0);
+++ if (!sizefile || (stat(STR(sizefilename), &statbuf) < 0) || (statbuf.st_size > SIZEFILE_MAX)) {
+++ if (sizefile) {
+++ vstream_fclose(sizefile);
+++ unlink(STR(sizefilename));
+++ }
+++ vstring_free(sizefilename);
+++
+++ return 0;
+++ }
+++
+++ VSTRING *sizebuf = vstring_alloc(SIZEFILE_MAX);
+++ len = vstream_fread(sizefile, STR(sizebuf), SIZEFILE_MAX);
+++
+++ p = STR(sizebuf);
+++ *(p + len) = '\0';
+++ first = 1;
+++
+++ while (*p) {
+++ long n = 0, c = 0;
+++ char *q = p;
+++
+++ while (*p) {
+++ if (*p++ == '\n') {
+++ p[-1] = 0;
+++ break;
+++ }
+++ }
+++
+++ if (first) {
+++ first = 0;
+++ continue;
+++ }
+++
+++ if(sscanf(q, "%ld %ld", &n, &c) == 2) {
+++ sum += n;
+++ count += c;
+++ }
+++ else {
+++ vstream_fclose(sizefile);
+++ unlink(STR(sizefilename));
+++
+++ msg_warn("read_maildirsize: invalid line '%s' found in %s, removing maildirsize file", q, STR(sizefilename));
+++
+++ vstring_free(sizefilename);
+++ vstring_free(sizebuf);
+++
+++ return 0;
+++ }
+++ }
+++
+++ vstream_fclose(sizefile);
+++ vstring_free(sizefilename);
+++ vstring_free(sizebuf);
+++
+++ *countptr = count;
+++
+++ return sum;
+++}
+++
+++/*
+++ * Gives the size of the file according to the Maildir++ extension
+++ * present in the filename (code taken from courier-imap).
+++ *
+++ * Arguments:
+++ * n: filename
+++ *
+++ * Returns the size given in ",S=<size>" in the filename,
+++ * zero if it cannot find ",S=<size>" in the filename.
+++ */
+++static long maildir_parsequota(const char *n)
+++{
+++ const char *o;
+++ int yes = 0;
++
++-int deliver_maildir(LOCAL_STATE state, USER_ATTR usr_attr)
+++ if ((o = strrchr(n, '/')) == 0)
+++ o = n;
+++
+++ for (; *o; o++) {
+++ if (*o == ':')
+++ break;
+++ }
+++
+++ for (; o >= n; --o) {
+++ if (*o == '/')
+++ break;
+++
+++ if (*o == ',' && o[1] == 'S' && o[2] == '=') {
+++ yes = 1;
+++ o += 3;
+++ break;
+++ }
+++ }
+++
+++ if (yes) {
+++ long s = 0;
+++
+++ while (*o >= '0' && *o <= '9')
+++ s = s*10 + (*o++ - '0');
+++
+++ return s;
+++ }
+++
+++ return 0;
+++}
+++
+++/*
+++ * Computes quota usage for a directory (taken from exim).
+++ *
+++ * This function is called to determine the exact quota usage of a virtual
+++ * maildir box. To achieve maximum possible speed while doing this, it takes
+++ * advantage of the maildirsize file and the Maildir++ extensions to filenames,
+++ * when applicable and configured to be used. In all other cases it simply
+++ * stats all the files as needed to get the size information.
+++ *
+++ * Arguments:
+++ * dirname: the name of the directory
+++ * countptr: where to add the file count (because this function recurses)
+++ *
+++ * Returns the sum of the sizes of all measurable files,
+++ * zero if the directory could not be opened.
+++ */
+++static long check_dir_size(char *dirname, long *countptr)
+++{
+++ char *myname = "check_dir_size";
+++ DIR *dir;
+++ long sum = 0;
+++ struct dirent *ent;
+++ struct stat statbuf;
+++
+++ if (!var_virt_mailbox_limit_inbox && var_virt_maildir_extended && (sum = read_maildirsize(dirname, countptr))) {
+++ if (msg_verbose)
+++ msg_info("%s: maildirsize used: dir=%s sum=%ld count=%ld", myname, dirname, sum, *countptr);
+++ return sum;
+++ }
+++
+++ dir = opendir(dirname);
+++ if (dir == NULL) {
+++ if (make_dirs(dirname, 0700) == 0) { /* Try to create the dirs. */
+++ dir = opendir(dirname); /* Reopen the dir. */
+++ if (dir == NULL) {
+++ msg_warn("%s: cannot reopen directory: %s", myname, dirname);
+++ return 0;
+++ }
+++ }
+++ else {
+++ msg_warn("%s: cannot open directory: %s", myname, dirname);
+++ return 0;
+++ }
+++ }
+++
+++ while ((ent = readdir(dir)) != NULL) {
+++ char *name = ent->d_name;
+++ long tmpsum = 0;
+++ VSTRING *buffer;
+++
+++ if (var_virt_trash_count) {
+++ if(strcmp(name, ".") == 0 || strcmp(name, "..") == 0)
+++ continue;
+++ }
+++ else {
+++ if(strcmp(name, ".") == 0 || strcmp(name, "..") == 0 || strcmp(name, var_virt_trash_name) == 0)
+++ continue;
+++ }
+++
+++ /*
+++ * Here comes the real logic behind this function.
+++ * Optimized to be the most efficient possible,
+++ * depending on the settings given.
+++ * See above for a more detailed description.
+++ */
+++ if (var_virt_mailbox_limit_inbox) {
+++ if (var_virt_maildir_extended && (tmpsum = maildir_parsequota(name))) {
+++ sum += tmpsum;
+++ (*countptr)++;
+++ }
+++ else {
+++ buffer = vstring_alloc(1024);
+++ vstring_sprintf(buffer, "%s/%s", dirname, name);
+++
+++ if (stat(STR(buffer), &statbuf) < 0) {
+++ vstring_free(buffer);
+++ continue;
+++ }
+++ if ((statbuf.st_mode & S_IFREG) != 0) {
+++ sum += (long) statbuf.st_size;
+++ (*countptr)++;
+++ }
+++
+++ vstring_free(buffer);
+++ }
+++ }
+++ else {
+++ buffer = vstring_alloc(1024);
+++ vstring_sprintf(buffer, "%s/%s", dirname, name);
+++
+++ if (stat(STR(buffer), &statbuf) < 0) {
+++ vstring_free(buffer);
+++ continue;
+++ }
+++ if ((statbuf.st_mode & S_IFREG) != 0) {
+++ if (strcmp(dirname + strlen(dirname) - 3, "new") == 0 || strcmp(dirname + strlen(dirname) - 3, "cur") == 0 || strcmp(dirname + strlen(dirname) - 3, "tmp") == 0) {
+++ sum += (long) statbuf.st_size;
+++ (*countptr)++;
+++ }
+++ }
+++ else if ((statbuf.st_mode & S_IFDIR) != 0) {
+++ sum += check_dir_size(STR(buffer), countptr);
+++ }
+++
+++ vstring_free(buffer);
+++ }
+++ }
+++ closedir(dir);
+++
+++ if (msg_verbose)
+++ msg_info("%s: full scan done: dir=%s sum=%ld count=%ld", myname, dirname, sum, *countptr);
+++
+++ return sum;
+++}
+++
+++/* Cut all occurrences of pattern from string. */
+++static char *strcut(char *str, const char *pat)
+++{
+++ char *ptr, *loc, *ret;
+++ ret = str;
+++ loc = str;
+++
+++ /* No match, return original string. */
+++ if (!strstr(loc, pat))
+++ return(str);
+++
+++ while (*loc && (ptr = strstr(loc, pat))) {
+++ while (loc < ptr)
+++ *str++ = *loc++;
+++ loc += strlen(pat);
+++ }
+++
+++ while (*loc)
+++ *str++ = *loc++;
+++
+++ *str = 0;
+++
+++ return(ret);
+++}
+++
+++/* Check if maildirfilter file is up-to-date compared to SQL, (re)write it if not. */
+++static long sql2file(char *filename, char *user)
+++{
+++ char *myname = "sql2file";
+++ char *filter_sqlres;
+++ char filter_fileres[128];
+++ long sqlmtime = 0, filemtime = 0, retval = 0;
+++ int filterfile, size_sqlres, i;
+++ struct stat statbuf;
+++
+++ if (*var_virt_maildir_filter_maps != 0) {
+++ filter_sqlres = (char *) mymalloc(16000);
+++ filter_sqlres = (char *) mail_addr_find(virtual_maildir_filter_maps, user, (char **) 0);
+++
+++ if (filter_sqlres) {
+++ strcut(filter_sqlres, "\r");
+++ if (filter_sqlres[0] == '#' && filter_sqlres[1] == ' ' && filter_sqlres[2] == 'M') {
+++ size_sqlres = strlen(filter_sqlres);
+++
+++ for (i = 4; i <= size_sqlres; i++) {
+++ if(filter_sqlres[i] == '/' && filter_sqlres[i+1] == '^') {
+++ filter_sqlres[i-1] = '\n';
+++ }
+++ }
+++
+++ filter_sqlres[(size_sqlres+1)] = '\0';
+++
+++ sqlmtime = atol(filter_sqlres+3);
+++ retval = sqlmtime;
+++
+++ filterfile = open(filename, O_RDONLY, 0);
+++ if (filterfile) {
+++ read(filterfile, (void *) filter_fileres, 127);
+++ close(filterfile);
+++
+++ filemtime = atol(filter_fileres+3);
+++ }
+++
+++ if (msg_verbose)
+++ msg_info("%s: filter data: sql_size=%d sql_mtime=%ld file_mtime=%ld", myname, strlen(filter_sqlres), sqlmtime, filemtime);
+++ }
+++ if (sqlmtime != filemtime && sqlmtime != 0) {
+++ if ((filterfile = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0640))) {
+++ if (msg_verbose)
+++ msg_info("%s: updating filter file: %s", myname, filename);
+++ write(filterfile, filter_sqlres, strlen(filter_sqlres));
+++ close(filterfile);
+++ }
+++ else {
+++ msg_warn("%s: can't create filter file: %s", myname, filename);
+++ retval = 0;
+++ }
+++ }
+++ }
+++ }
+++ else {
+++ if (stat(filename, &statbuf) == 0)
+++ retval = (long) statbuf.st_mtime;
+++ if (msg_verbose)
+++ msg_info("%s: processing filter file: file_mtime=%ld", myname, retval);
+++ }
+++
+++ return retval;
+++}
+++
+++/* deliver_maildir - delivery to maildir-style mailbox */
+++int deliver_maildir(LOCAL_STATE state, USER_ATTR usr_attr)
++ {
++ const char *myname = "deliver_maildir";
++- char *newdir;
++- char *tmpdir;
++- char *curdir;
++- char *tmpfile;
++- char *newfile;
+++ char *newdir;
+++ char *tmpdir;
+++ char *curdir;
+++ char *newfile;
+++ char *tmpfile;
++ DSN_BUF *why = state.msg_attr.why;
++ VSTRING *buf;
++ VSTREAM *dst;
++- int mail_copy_status;
++- int deliver_status;
++- int copy_flags;
++- struct stat st;
++- struct timeval starttime;
+++ int mail_copy_status;
+++ int deliver_status;
+++ int copy_flags;
+++ struct stat st;
+++ struct timeval starttime;
+++
+++ /* Maildir Quota. */
+++ const char *limit_res; /* Limit from map. */
+++ char *sizefilename = (char *) 0; /* Maildirsize file name. */
+++ VSTRING *filequota; /* Quota setting from the maildirsize file. */
+++ VSTREAM *sizefile; /* Maildirsize file handle. */
+++ long n = 0; /* Limit in long integer format. */
+++ long saved_count = 0; /* The total number of files. */
+++ long saved_size = 0; /* The total quota of all files. */
+++ struct stat mail_stat; /* To check the size of the mail to be written. */
+++ struct stat sizefile_stat; /* To check the size of the maildirsize file. */
+++ time_t tm; /* To check the age of the maildirsize file. */
+++
+++ /* Maildir Filters. */
+++ const char *value, *cmd_text; /* Filter values. */
+++ char *filtername;
+++ char *header;
+++ char *bkpnewfile;
+++ char *mdffilename = (char *) 0; /* Maildirfolder file name. */
+++ VSTRING *fltstr;
+++ VSTREAM *tmpfilter;
+++ VSTREAM *mdffile; /* Maildirfolder file handle. */
+++ DICT *FILTERS;
+++ long sqlmtime; /* Latest modification time from sql2file(). */
+++ int cmd_len;
+++ struct stat mdffile_stat; /* To check if the maildirfolder file exists. */
++
++ GETTIMEOFDAY(&starttime);
++
++@@ -93,15 +471,14 @@
++ */
++ state.level++;
++ if (msg_verbose)
++- MSG_LOG_STATE(myname, state);
+++ MSG_LOG_STATE(myname, state);
++
++ /*
++ * Don't deliver trace-only requests.
++ */
++ if (DEL_REQ_TRACE_ONLY(state.request->flags)) {
++- dsb_simple(why, "2.0.0", "delivers to maildir");
++- return (sent(BOUNCE_FLAGS(state.request),
++- SENT_ATTR(state.msg_attr)));
+++ dsb_simple(why, "2.0.0", "delivers to maildir");
+++ return (sent(BOUNCE_FLAGS(state.request), SENT_ATTR(state.msg_attr)));
++ }
++
++ /*
++@@ -109,17 +486,91 @@
++ * attribute to reflect the final recipient.
++ */
++ if (vstream_fseek(state.msg_attr.fp, state.msg_attr.offset, SEEK_SET) < 0)
++- msg_fatal("seek message file %s: %m", VSTREAM_PATH(state.msg_attr.fp));
+++ msg_fatal("seek message file %s: %m", VSTREAM_PATH(state.msg_attr.fp));
++ state.msg_attr.delivered = state.msg_attr.rcpt.address;
++ mail_copy_status = MAIL_COPY_STAT_WRITE;
++ buf = vstring_alloc(100);
++
++- copy_flags = MAIL_COPY_TOFILE | MAIL_COPY_RETURN_PATH
++- | MAIL_COPY_DELIVERED | MAIL_COPY_ORIG_RCPT;
+++ copy_flags = MAIL_COPY_TOFILE | MAIL_COPY_RETURN_PATH | MAIL_COPY_DELIVERED | MAIL_COPY_ORIG_RCPT;
++
++- newdir = concatenate(usr_attr.mailbox, "new/", (char *) 0);
++- tmpdir = concatenate(usr_attr.mailbox, "tmp/", (char *) 0);
++- curdir = concatenate(usr_attr.mailbox, "cur/", (char *) 0);
+++ /*
+++ * Concatenate the maildir suffix (if set).
+++ */
+++ if (*var_virt_maildir_suffix == 0) {
+++ newdir = concatenate(usr_attr.mailbox, "new/", (char *) 0);
+++ tmpdir = concatenate(usr_attr.mailbox, "tmp/", (char *) 0);
+++ curdir = concatenate(usr_attr.mailbox, "cur/", (char *) 0);
+++ }
+++ else {
+++ newdir = concatenate(usr_attr.mailbox, var_virt_maildir_suffix, (char *) 0);
+++ tmpdir = concatenate(usr_attr.mailbox, var_virt_maildir_suffix, (char *) 0);
+++ curdir = concatenate(usr_attr.mailbox, var_virt_maildir_suffix, (char *) 0);
+++ newdir = concatenate(newdir, "new/", (char *) 0);
+++ tmpdir = concatenate(tmpdir, "tmp/", (char *) 0);
+++ curdir = concatenate(curdir, "cur/", (char *) 0);
+++ }
+++
+++ /*
+++ * Look up the virtual maildir limit size for this user.
+++ * Fall back to virtual_mailbox_limit in case lookup failed.
+++ * If virtual maildir limit size is negative, fall back to virtual_mailbox_limit.
+++ * If it's 0, set the mailbox limit to 0, which means unlimited.
+++ * If it's more than 0 (positive int), check if the value is smaller than the maximum message size,
+++ * if it is and the virtual maildir limit can't be overridden, fall back to virtual_mailbox_limit and
+++ * warn the user, else use the value directly as the maildir limit.
+++ */
+++ if (*var_virt_mailbox_limit_maps != 0 && (limit_res = mail_addr_find(virtual_mailbox_limit_maps, state.msg_attr.user, (char **) NULL)) != 0) {
+++ n = atol(limit_res);
+++ if (n > 0) {
+++ if ((n < var_message_limit) && (!var_virt_mailbox_limit_override)) {
+++ n = var_virt_mailbox_limit;
+++
+++ msg_warn("%s: recipient %s - virtual maildir limit is "
+++ "smaller than %s in %s - falling back to %s",
+++ myname,
+++ state.msg_attr.user,
+++ VAR_MESSAGE_LIMIT,
+++ virtual_mailbox_limit_maps->title,
+++ VAR_VIRT_MAILBOX_LIMIT);
+++ }
+++ else {
+++ if (msg_verbose)
+++ msg_info("%s: set virtual maildir limit size for %s to %ld",
+++ myname, usr_attr.mailbox, n);
+++ }
+++ }
+++ else if (n == 0) {
+++ if (msg_verbose)
+++ msg_info("%s: set virtual maildir limit size for %s to %ld",
+++ myname, usr_attr.mailbox, n);
+++ }
+++ else {
+++ /* Invalid limit size (negative). Use default virtual_mailbox_limit. */
+++ n = var_virt_mailbox_limit;
+++ }
+++ }
+++ else {
+++ /* There is no limit in the maps. Use default virtual_mailbox_limit. */
+++ n = var_virt_mailbox_limit;
+++ }
+++
+++ /*
+++ * Check quota before delivering the mail.
+++ */
+++ if (n != 0) {
+++ set_eugid(usr_attr.uid, usr_attr.gid);
+++ if (var_virt_mailbox_limit_inbox) {
+++ /* Check Inbox only (new, cur and tmp dirs). */
+++ saved_size = check_dir_size(newdir, &saved_count);
+++ saved_size += check_dir_size(curdir, &saved_count);
+++ saved_size += check_dir_size(tmpdir, &saved_count);
+++ }
+++ else {
+++ /* Check all boxes. */
+++ saved_size = check_dir_size(usr_attr.mailbox, &saved_count);
+++ }
+++ set_eugid(var_owner_uid, var_owner_gid);
+++ }
++
++ /*
++ * Create and write the file as the recipient, so that file quota work.
++@@ -174,46 +625,296 @@
++ * [...]
++ */
++ set_eugid(usr_attr.uid, usr_attr.gid);
++- vstring_sprintf(buf, "%lu.P%d.%s",
++- (unsigned long) starttime.tv_sec, var_pid, get_hostname());
+++ vstring_sprintf(buf, "%lu.P%d.%s", (unsigned long) starttime.tv_sec, var_pid, get_hostname());
++ tmpfile = concatenate(tmpdir, STR(buf), (char *) 0);
++ newfile = 0;
+++ bkpnewfile = 0;
++ if ((dst = vstream_fopen(tmpfile, O_WRONLY | O_CREAT | O_EXCL, 0600)) == 0
++- && (errno != ENOENT
++- || make_dirs(tmpdir, 0700) < 0
++- || (dst = vstream_fopen(tmpfile, O_WRONLY | O_CREAT | O_EXCL, 0600)) == 0)) {
++- dsb_simple(why, mbox_dsn(errno, "4.2.0"),
++- "create maildir file %s: %m", tmpfile);
++- } else if (fstat(vstream_fileno(dst), &st) < 0) {
++-
++- /*
++- * Coverity 200604: file descriptor leak in code that never executes.
++- * Code replaced by msg_fatal(), as it is not worthwhile to continue
++- * after an impossible error condition.
++- */
++- msg_fatal("fstat %s: %m", tmpfile);
++- } else {
++- vstring_sprintf(buf, "%lu.V%lxI%lxM%lu.%s",
++- (unsigned long) starttime.tv_sec,
++- (unsigned long) st.st_dev,
++- (unsigned long) st.st_ino,
++- (unsigned long) starttime.tv_usec,
++- get_hostname());
++- newfile = concatenate(newdir, STR(buf), (char *) 0);
++- if ((mail_copy_status = mail_copy(COPY_ATTR(state.msg_attr),
++- dst, copy_flags, "\n",
++- why)) == 0) {
++- if (sane_link(tmpfile, newfile) < 0
++- && (errno != ENOENT
++- || (make_dirs(curdir, 0700), make_dirs(newdir, 0700)) < 0
++- || sane_link(tmpfile, newfile) < 0)) {
++- dsb_simple(why, mbox_dsn(errno, "4.2.0"),
++- "create maildir file %s: %m", newfile);
++- mail_copy_status = MAIL_COPY_STAT_WRITE;
++- }
++- }
++- if (unlink(tmpfile) < 0)
++- msg_warn("remove %s: %m", tmpfile);
+++ && (errno != ENOENT
+++ || make_dirs(tmpdir, 0700) < 0
+++ || (dst = vstream_fopen(tmpfile, O_WRONLY | O_CREAT | O_EXCL, 0600)) == 0)) {
+++ dsb_simple(why, mbox_dsn(errno, "4.2.0"), "create maildir file %s: %m", tmpfile);
+++ }
+++ else if (fstat(vstream_fileno(dst), &st) < 0) {
+++ /*
+++ * Coverity 200604: file descriptor leak in code that never executes.
+++ * Code replaced by msg_fatal(), as it is not worthwhile to continue
+++ * after an impossible error condition.
+++ */
+++ msg_fatal("fstat %s: %m", tmpfile);
+++ }
+++ else {
+++ vstring_sprintf(buf, "%lu.V%lxI%lxM%lu.%s",
+++ (unsigned long) starttime.tv_sec,
+++ (unsigned long) st.st_dev,
+++ (unsigned long) st.st_ino,
+++ (unsigned long) starttime.tv_usec,
+++ get_hostname());
+++ newfile = concatenate(newdir, STR(buf), (char *) 0);
+++ bkpnewfile = concatenate(STR(buf), (char *) 0); /* Will need it later, if we MOVE to other folders. */
+++
+++ if ((mail_copy_status = mail_copy(COPY_ATTR(state.msg_attr), dst, copy_flags, "\n", why)) == 0) {
+++ /*
+++ * Add a ",S=<sizeoffile>" to the newly written file according to the
+++ * Maildir++ specifications: http://www.inter7.com/courierimap/README.maildirquota.html
+++ * This needs a stat(2) of the tempfile and modification of the
+++ * name of the file.
+++ */
+++ if (stat(tmpfile, &mail_stat) == 0) {
+++ if (n != 0) {
+++ saved_size += (long) mail_stat.st_size;
+++ saved_count++;
+++ }
+++ if (var_virt_maildir_extended) {
+++ /* Append the size of the file to newfile. */
+++ vstring_sprintf(buf, ",S=%ld", (long) mail_stat.st_size);
+++ newfile = concatenate(newfile, STR(buf), (char *) 0);
+++ bkpnewfile = concatenate(bkpnewfile, STR(buf), (char *) 0);
+++ }
+++ }
+++
+++ /*
+++ * Now we have the maildir size in saved_size, compare it to the max
+++ * quota value and eventually issue a message that we've overdrawn it.
+++ */
+++ if (saved_size > n) {
+++ mail_copy_status = MAIL_COPY_STAT_WRITE;
+++ if (((long) mail_stat.st_size > n) || (var_virt_overquota_bounce))
+++ errno = EFBIG;
+++ else
+++ errno = EDQUOT;
+++ }
+++ else {
+++ /* Maildirfilter code by rk@demiurg.net. */
+++ if (var_virt_maildir_filter) {
+++ if (msg_verbose)
+++ msg_info("%s: loading DICT filters", myname);
+++
+++#define STREQUAL(x,y,l) (strncasecmp((x), (y), (l)) == 0 && (y)[l] == 0)
+++#define MAIL_COPY_STAT_REJECT (1<<3)
+++#define MAIL_COPY_STAT_DISCARD (1<<4)
+++
+++ /* Read filters. */
+++ filtername = concatenate("regexp:", usr_attr.mailbox, "maildirfilter", (char *) 0);
+++ sqlmtime = sql2file(strchr(filtername, '/'), state.msg_attr.user);
+++
+++ /* Check if this filter is already registered as dictionary. */
+++ if (msg_verbose)
+++ msg_info("%s: checking DICT filters for %s", myname, filtername);
+++
+++ if ((FILTERS = dict_handle(filtername))) {
+++ if (msg_verbose)
+++ msg_info("%s: DICT filter found", myname);
+++
+++ /*
+++ * If we have mtime in our DICT structure, check it against sqlmtime
+++ * and reload the filters if they differ.
+++ */
+++ if (FILTERS->mtime > 0 && sqlmtime > 0 && FILTERS->mtime != sqlmtime) {
+++ if (msg_verbose)
+++ msg_info("%s: reloading DICT filters (dict_mtime=%ld != sql_mtime=%ld)",
+++ myname, FILTERS->mtime, sqlmtime);
+++
+++ dict_unregister(filtername);
+++ FILTERS = dict_open(filtername, O_RDONLY, DICT_FLAG_LOCK);
+++ dict_register(filtername, FILTERS);
+++ FILTERS->mtime = sqlmtime;
+++ }
+++ }
+++ else {
+++ if (sqlmtime > 0) {
+++ /* Registering filter as new dictionary. */
+++ if (msg_verbose)
+++ msg_info("%s: loading DICT filters from %s (mtime=%ld)",
+++ myname, filtername, sqlmtime);
+++
+++ FILTERS = dict_open(filtername, O_RDONLY, DICT_FLAG_LOCK);
+++ dict_register(filtername, FILTERS);
+++ FILTERS->mtime = sqlmtime;
+++ }
+++ }
+++
+++ if (FILTERS && (tmpfilter = vstream_fopen(tmpfile, O_RDONLY, 0))) {
+++ fltstr = vstring_alloc(1024);
+++ header = (char *) malloc(8192); /* !!!INSECURE!!! See 7168-hack below. */
+++ header[0] = 0;
+++ vstring_get_nonl_bound(fltstr, tmpfilter, 1023);
+++ header = concatenate(header, STR(fltstr), (char *) 0);
+++
+++ while(!vstream_feof(tmpfilter) && fltstr->vbuf.data[0] && strlen(header) < 7168 ) {
+++ vstring_get_nonl_bound(fltstr, tmpfilter, 1023);
+++ /* Glue multiline headers, replacing leading TAB with space. */
+++ if (msg_verbose)
+++ msg_info("%s: fltstr value: %s", myname, STR(fltstr));
+++
+++ if (fltstr->vbuf.data[0] == ' ' || fltstr->vbuf.data[0] == '\t' ) {
+++ if (fltstr->vbuf.data[0] == '\t')
+++ fltstr->vbuf.data[0] = ' ';
+++ header = concatenate(header, STR(fltstr), (char *) 0);
+++ }
+++ else {
+++ header = concatenate(header, "\n", STR(fltstr), (char *) 0);
+++ }
+++ }
+++
+++ if (msg_verbose)
+++ msg_info("%s: checking filter CMD for %s", myname, filtername);
+++
+++ /* Check whole header part with regexp maps. */
+++ if ((value = dict_get(FILTERS, lowercase(header))) != 0) {
+++ if (msg_verbose)
+++ msg_info("%s: preparing filter CMD", myname);
+++
+++ cmd_text = value + strcspn(value, " \t");
+++ cmd_len = cmd_text - value;
+++ while (*cmd_text && ISSPACE(*cmd_text))
+++ cmd_text++;
+++
+++ if (msg_verbose)
+++ msg_info("%s: executing filter CMD", myname);
+++
+++ if (STREQUAL(value, "REJECT", cmd_len)) {
+++ if (msg_verbose)
+++ msg_info("%s: executing filter CMD REJECT", myname);
+++
+++ mail_copy_status = MAIL_COPY_STAT_REJECT;
+++ vstring_sprintf(why->reason, "%s", cmd_text);
+++ dsb_simple(why, "5.0.0", "User filter - REJECT");
+++ }
+++
+++ if (STREQUAL(value, "DISCARD", cmd_len)) {
+++ if (msg_verbose)
+++ msg_info("%s: executing filter CMD DISCARD", myname);
+++
+++ mail_copy_status = MAIL_COPY_STAT_DISCARD;
+++ vstring_sprintf(why->reason, "%s", cmd_text);
+++ dsb_simple(why, "5.0.0", "User filter - DISCARD");
+++ }
+++
+++ if (var_virt_maildir_extended) {
+++ if (STREQUAL(value, "MOVE", cmd_len)) {
+++ if (msg_verbose)
+++ msg_info("%s: executing filter CMD MOVE", myname);
+++
+++ strcut((char *) cmd_text, " ");
+++ strcut((char *) cmd_text, "\t");
+++ strcut((char *) cmd_text, "/");
+++ strcut((char *) cmd_text, "..");
+++
+++ if (*var_virt_maildir_suffix == 0) {
+++ newfile = concatenate(usr_attr.mailbox, (char *) 0);
+++ }
+++ else {
+++ newfile = concatenate(usr_attr.mailbox, var_virt_maildir_suffix, (char *) 0);
+++ }
+++
+++ if (cmd_text[0] != '.') {
+++ newfile = concatenate(newfile, ".", (char *) 0);
+++ }
+++ newdir = concatenate(newfile, cmd_text, "/", "new/", (char *) 0);
+++ tmpdir = concatenate(newfile, cmd_text, "/", "tmp/", (char *) 0);
+++ curdir = concatenate(newfile, cmd_text, "/", "cur/", (char *) 0);
+++ mdffilename = concatenate(newfile, cmd_text, "/", "maildirfolder", (char *) 0);
+++ newfile = concatenate(newfile, cmd_text, "/", "new/", bkpnewfile, (char *) 0);
+++ }
+++ }
+++
+++ if (STREQUAL(value, "LOG", cmd_len) || STREQUAL(value, "WARN", cmd_len)) {
+++ msg_warn("%s: header check warning: %s", myname, cmd_text);
+++ }
+++
+++ if (STREQUAL(value, "INFO", cmd_len)) {
+++ msg_info("%s: header check info: %s", myname, cmd_text);
+++ }
+++
+++ if (msg_verbose)
+++ msg_info("%s: exiting filter CMD", myname);
+++ } /* End-Of-Check */
+++
+++ myfree(header);
+++ vstring_free(fltstr);
+++ vstream_fclose(tmpfilter);
+++ }
+++
+++ myfree(filtername);
+++ } /* End-Of-Maildirfilter */
+++
+++ /* Deliver to curdir. */
+++ if (mail_copy_status == 0) {
+++ if (sane_link(tmpfile, newfile) < 0
+++ && (errno != ENOENT
+++ || (make_dirs(curdir, 0700), make_dirs(newdir, 0700), make_dirs(tmpdir, 0700)) < 0
+++ || sane_link(tmpfile, newfile) < 0)) {
+++ dsb_simple(why, mbox_dsn(errno, "4.2.0"), "create maildir file %s: %m", newfile);
+++ mail_copy_status = MAIL_COPY_STAT_WRITE;
+++ }
+++
+++ if (var_virt_maildir_extended) {
+++ time(&tm);
+++
+++ if (*var_virt_maildir_suffix == 0) {
+++ sizefilename = concatenate(usr_attr.mailbox, "maildirsize", (char *) 0);
+++ }
+++ else {
+++ sizefilename = concatenate(usr_attr.mailbox, var_virt_maildir_suffix, (char *) 0);
+++ sizefilename = concatenate(sizefilename, "maildirsize", (char *) 0);
+++ }
+++
+++ /* Check if the quota in the file is the same as the current one, if not, delete the file. */
+++ sizefile = vstream_fopen(sizefilename, O_RDONLY, 0);
+++ if (sizefile) {
+++ filequota = vstring_alloc(128);
+++ vstring_get_null_bound(filequota, sizefile, 127);
+++ vstream_fclose(sizefile);
+++ if (atol(vstring_export(filequota)) != n)
+++ unlink(sizefilename);
+++ }
+++
+++ /* Open maildirsize file to append this transaction. */
+++ sizefile = vstream_fopen(sizefilename, O_WRONLY | O_APPEND, 0640);
+++
+++ /* If the open fails (maildirsize doesn't exist), or it's too large, or too old, overwrite it. */
+++ if(!sizefile || (stat(sizefilename, &sizefile_stat) < 0) || (sizefile_stat.st_size > SIZEFILE_MAX) || (sizefile_stat.st_mtime + 15*60 < tm)) {
+++ /* If the file exists, sizefile has been opened above, so close it first. */
+++ if (sizefile) {
+++ vstream_fclose(sizefile);
+++ sizefile = vstream_fopen(sizefilename, O_WRONLY | O_TRUNC, 0640);
+++ }
+++ else {
+++ sizefile = vstream_fopen(sizefilename, O_WRONLY | O_CREAT, 0640);
+++ }
+++
+++ /* If the creation worked, write to the file, otherwise just give up. */
+++ if (sizefile) {
+++ vstream_fprintf(sizefile, "%ldS\n%ld %ld\n", n, saved_size, saved_count);
+++ vstream_fclose(sizefile);
+++ }
+++ }
+++ else {
+++ /* We opened maildirsize, so let's just append this transaction and close it. */
+++ vstream_fprintf(sizefile, "%ld 1\n", (long) mail_stat.st_size);
+++ vstream_fclose(sizefile);
+++ }
+++
+++ /*
+++ * 1) mdffilename != 0, so the maildirfilter code went through the MOVE to subfolder rule.
+++ * 2) stat() failed, maybe the file does not exist? Try to create it.
+++ */
+++ if (mdffilename && (stat(mdffilename, &mdffile_stat) < 0)) {
+++ mdffile = vstream_fopen(mdffilename, O_WRONLY | O_CREAT, 0600);
+++ if (mdffile) {
+++ vstream_fclose(mdffile);
+++ }
+++ else {
+++ msg_warn("Cannot create maildirfolder file '%s': %s", mdffilename, strerror(errno));
+++ }
+++ }
+++ }
+++ }
+++ }
+++ }
+++ if (unlink(tmpfile) < 0)
+++ msg_warn("remove %s: %m", tmpfile);
++ }
++ set_eugid(var_owner_uid, var_owner_gid);
++
++@@ -223,31 +924,64 @@
++ * location possibly under user control.
++ */
++ if (mail_copy_status & MAIL_COPY_STAT_CORRUPT) {
++- deliver_status = DEL_STAT_DEFER;
++- } else if (mail_copy_status != 0) {
++- if (errno == EACCES) {
++- msg_warn("maildir access problem for UID/GID=%lu/%lu: %s",
++- (long) usr_attr.uid, (long) usr_attr.gid,
++- STR(why->reason));
++- msg_warn("perhaps you need to create the maildirs in advance");
++- }
++- vstring_sprintf_prepend(why->reason, "maildir delivery failed: ");
++- deliver_status =
++- (STR(why->status)[0] == '4' ?
++- defer_append : bounce_append)
++- (BOUNCE_FLAGS(state.request),
++- BOUNCE_ATTR(state.msg_attr));
++- } else {
++- dsb_simple(why, "2.0.0", "delivered to maildir");
++- deliver_status = sent(BOUNCE_FLAGS(state.request),
++- SENT_ATTR(state.msg_attr));
+++ deliver_status = DEL_STAT_DEFER;
+++ }
+++ else if (mail_copy_status != 0) {
+++ if (errno == EACCES) {
+++ msg_warn("maildir access problem for UID/GID=%lu/%lu: %s",
+++ (long) usr_attr.uid, (long) usr_attr.gid, STR(why->reason));
+++ msg_warn("perhaps you need to create the maildirs in advance");
+++ }
+++
+++ /* Support per-recipient bounce messages. */
+++ const char *limit_message;
+++ int errnored = errno; /* Seems like mail_addr_find resets errno ... */
+++
+++ if (*var_virt_maildir_limit_message_maps != 0 && (limit_message = mail_addr_find(virtual_maildir_limit_message_maps, state.msg_attr.user, (char **) NULL)) != 0) {
+++ errno = errnored;
+++ if (errno == EFBIG) {
+++ dsb_simple(why, "5.2.3", limit_message);
+++ }
+++ if (errno == EDQUOT) {
+++ dsb_simple(why, "4.2.2", limit_message);
+++ }
+++ }
+++ else {
+++ errno = errnored;
+++ if (errno == EFBIG) {
+++ dsb_simple(why, "5.2.3", var_virt_maildir_limit_message);
+++ }
+++ if (errno == EDQUOT) {
+++ dsb_simple(why, "4.2.2", var_virt_maildir_limit_message);
+++ }
+++ }
+++
+++ vstring_sprintf_prepend(why->reason, "maildir delivery failed: ");
+++ deliver_status =
+++ (STR(why->status)[0] == '4' ? defer_append : bounce_append)
+++ (BOUNCE_FLAGS(state.request), BOUNCE_ATTR(state.msg_attr));
++ }
+++ else {
+++ dsb_simple(why, "2.0.0", "delivered to maildir");
+++ deliver_status = sent(BOUNCE_FLAGS(state.request), SENT_ATTR(state.msg_attr));
+++ }
+++
++ vstring_free(buf);
+++
++ myfree(newdir);
++ myfree(tmpdir);
++ myfree(curdir);
+++
+++ if (sizefilename)
+++ myfree(sizefilename);
+++ if (mdffilename)
+++ myfree(mdffilename);
+++
++ myfree(tmpfile);
++ if (newfile)
++- myfree(newfile);
+++ myfree(newfile);
+++ if (bkpnewfile)
+++ myfree(bkpnewfile);
+++
++ return (deliver_status);
++ }
++diff -Nru postfix-2.4.6/src/virtual/virtual.c postfix-2.4.6-vda-ng/src/virtual/virtual.c
++--- postfix-2.4.6/src/virtual/virtual.c 2007-03-27 02:07:43.000000000 +0200
+++++ postfix-2.4.6-vda-ng/src/virtual/virtual.c 2007-11-24 12:48:53.000000000 +0100
++@@ -330,12 +330,28 @@
++ int var_virt_mailbox_limit;
++ char *var_mail_spool_dir; /* XXX dependency fix */
++
+++char *var_virt_mailbox_limit_maps;
+++bool var_virt_mailbox_limit_inbox;
+++bool var_virt_mailbox_limit_override;
+++bool var_virt_maildir_extended;
+++bool var_virt_overquota_bounce;
+++char *var_virt_maildir_limit_message;
+++char *var_virt_maildir_limit_message_maps;
+++char *var_virt_maildir_suffix;
+++bool var_virt_trash_count;
+++char *var_virt_trash_name;
+++bool var_virt_maildir_filter;
+++char *var_virt_maildir_filter_maps;
+++
++ /*
++ * Mappings.
++ */
++ MAPS *virtual_mailbox_maps;
++ MAPS *virtual_uid_maps;
++ MAPS *virtual_gid_maps;
+++MAPS *virtual_mailbox_limit_maps;
+++MAPS *virtual_maildir_limit_message_maps;
+++MAPS *virtual_maildir_filter_maps;
++
++ /*
++ * Bit masks.
++@@ -445,15 +461,24 @@
++ */
++ virtual_mailbox_maps =
++ maps_create(VAR_VIRT_MAILBOX_MAPS, var_virt_mailbox_maps,
++- DICT_FLAG_LOCK | DICT_FLAG_PARANOID);
++-
+++ DICT_FLAG_LOCK);
++ virtual_uid_maps =
++ maps_create(VAR_VIRT_UID_MAPS, var_virt_uid_maps,
++- DICT_FLAG_LOCK | DICT_FLAG_PARANOID);
++-
+++ DICT_FLAG_LOCK);
++ virtual_gid_maps =
++ maps_create(VAR_VIRT_GID_MAPS, var_virt_gid_maps,
++- DICT_FLAG_LOCK | DICT_FLAG_PARANOID);
+++ DICT_FLAG_LOCK);
+++ virtual_mailbox_limit_maps =
+++ maps_create(VAR_VIRT_MAILBOX_LIMIT_MAPS, var_virt_mailbox_limit_maps,
+++ DICT_FLAG_LOCK);
+++
+++ virtual_maildir_limit_message_maps =
+++ maps_create(VAR_VIRT_MAILDIR_LIMIT_MESSAGE_MAPS, var_virt_maildir_limit_message_maps,
+++ DICT_FLAG_LOCK);
+++
+++ virtual_maildir_filter_maps =
+++ maps_create(VAR_VIRT_MAILDIR_FILTER_MAPS, var_virt_maildir_filter_maps,
+++ DICT_FLAG_LOCK);
++
++ virtual_mbox_lock_mask = mbox_lock_mask(var_virt_mailbox_lock);
++ }
++@@ -495,16 +520,33 @@
++ VAR_VIRT_MAILBOX_LIMIT, DEF_VIRT_MAILBOX_LIMIT, &var_virt_mailbox_limit, 0, 0,
++ 0,
++ };
++- static CONFIG_STR_TABLE str_table[] = {
++- VAR_MAIL_SPOOL_DIR, DEF_MAIL_SPOOL_DIR, &var_mail_spool_dir, 0, 0,
++- VAR_VIRT_MAILBOX_MAPS, DEF_VIRT_MAILBOX_MAPS, &var_virt_mailbox_maps, 0, 0,
++- VAR_VIRT_UID_MAPS, DEF_VIRT_UID_MAPS, &var_virt_uid_maps, 0, 0,
++- VAR_VIRT_GID_MAPS, DEF_VIRT_GID_MAPS, &var_virt_gid_maps, 0, 0,
++- VAR_VIRT_MAILBOX_BASE, DEF_VIRT_MAILBOX_BASE, &var_virt_mailbox_base, 1, 0,
++- VAR_VIRT_MAILBOX_LOCK, DEF_VIRT_MAILBOX_LOCK, &var_virt_mailbox_lock, 1, 0,
++- 0,
+++
+++ static CONFIG_BOOL_TABLE bool_table[] = {
+++ VAR_VIRT_MAILBOX_LIMIT_INBOX, DEF_VIRT_MAILBOX_LIMIT_INBOX, &var_virt_mailbox_limit_inbox,
+++ VAR_VIRT_MAILBOX_LIMIT_OVERRIDE, DEF_VIRT_MAILBOX_LIMIT_OVERRIDE, &var_virt_mailbox_limit_override,
+++ VAR_VIRT_MAILDIR_EXTENDED, DEF_VIRT_MAILDIR_EXTENDED, &var_virt_maildir_extended,
+++ VAR_VIRT_OVERQUOTA_BOUNCE, DEF_VIRT_OVERQUOTA_BOUNCE, &var_virt_overquota_bounce,
+++ VAR_VIRT_TRASH_COUNT, DEF_VIRT_TRASH_COUNT, &var_virt_trash_count,
+++ VAR_VIRT_MAILDIR_FILTER, DEF_VIRT_MAILDIR_FILTER, &var_virt_maildir_filter,
+++ 0,
++ };
++
+++ static CONFIG_STR_TABLE str_table[] = {
+++ VAR_MAIL_SPOOL_DIR, DEF_MAIL_SPOOL_DIR, &var_mail_spool_dir, 0, 0,
+++ VAR_VIRT_MAILBOX_MAPS, DEF_VIRT_MAILBOX_MAPS, &var_virt_mailbox_maps, 0, 0,
+++ VAR_VIRT_UID_MAPS, DEF_VIRT_UID_MAPS, &var_virt_uid_maps, 0, 0,
+++ VAR_VIRT_GID_MAPS, DEF_VIRT_GID_MAPS, &var_virt_gid_maps, 0, 0,
+++ VAR_VIRT_MAILBOX_LIMIT_MAPS, DEF_VIRT_MAILBOX_LIMIT_MAPS, &var_virt_mailbox_limit_maps, 0, 0,
+++ VAR_VIRT_MAILBOX_BASE, DEF_VIRT_MAILBOX_BASE, &var_virt_mailbox_base, 1, 0,
+++ VAR_VIRT_MAILBOX_LOCK, DEF_VIRT_MAILBOX_LOCK, &var_virt_mailbox_lock, 1, 0,
+++ VAR_VIRT_MAILDIR_LIMIT_MESSAGE, DEF_VIRT_MAILDIR_LIMIT_MESSAGE, &var_virt_maildir_limit_message, 1, 0,
+++ VAR_VIRT_MAILDIR_LIMIT_MESSAGE_MAPS, DEF_VIRT_MAILDIR_LIMIT_MESSAGE_MAPS, &var_virt_maildir_limit_message_maps, 0, 0,
+++ VAR_VIRT_MAILDIR_SUFFIX, DEF_VIRT_MAILDIR_SUFFIX, &var_virt_maildir_suffix, 0, 0,
+++ VAR_VIRT_TRASH_NAME, DEF_VIRT_TRASH_NAME, &var_virt_trash_name, 0, 0,
+++ VAR_VIRT_MAILDIR_FILTER_MAPS, DEF_VIRT_MAILDIR_FILTER_MAPS, &var_virt_maildir_filter_maps, 0, 0,
+++ 0,
+++ };
+++
++ /*
++ * Fingerprint executables and core dumps.
++ */
++@@ -516,6 +558,7 @@
++ MAIL_SERVER_PRE_INIT, pre_init,
++ MAIL_SERVER_POST_INIT, post_init,
++ MAIL_SERVER_PRE_ACCEPT, pre_accept,
+++ MAIL_SERVER_BOOL_TABLE, bool_table,
++ MAIL_SERVER_PRIVILEGED,
++ 0);
++ }
++diff -Nru postfix-2.4.6/src/virtual/virtual.h postfix-2.4.6-vda-ng/src/virtual/virtual.h
++--- postfix-2.4.6/src/virtual/virtual.h 2006-01-08 00:59:47.000000000 +0100
+++++ postfix-2.4.6-vda-ng/src/virtual/virtual.h 2007-11-24 12:48:53.000000000 +0100
++@@ -34,6 +34,9 @@
++ extern MAPS *virtual_mailbox_maps;
++ extern MAPS *virtual_uid_maps;
++ extern MAPS *virtual_gid_maps;
+++extern MAPS *virtual_mailbox_limit_maps;
+++extern MAPS *virtual_maildir_limit_message_maps;
+++extern MAPS *virtual_maildir_filter_maps;
++
++ /*
++ * User attributes: these control the privileges for delivery to external
+diff -Nru postfix-2.5.1/src/global/mail_params.h postfix-2.5.1-vda-ng/src/global/mail_params.h
+--- postfix-2.5.1/src/global/mail_params.h 2008-01-24 02:10:19.000000000 +0100
++++ postfix-2.5.1-vda-ng/src/global/mail_params.h 2008-03-15 15:06:00.095731675 +0100
+@@ -2167,6 +2167,54 @@
#define DEF_VIRT_GID_MAPS ""
extern char *var_virt_gid_maps;
@@ -157,9 +1600,9 @@ diff -Nru postfix-2.4.6/src/global/mail_params.h postfix-2.4.6-vda-ng/src/global
#define VAR_VIRT_MINUID "virtual_minimum_uid"
#define DEF_VIRT_MINUID 100
extern int var_virt_minimum_uid;
-diff -Nru postfix-2.4.6/src/util/file_limit.c postfix-2.4.6-vda-ng/src/util/file_limit.c
---- postfix-2.4.6/src/util/file_limit.c 2003-10-22 20:48:36.000000000 +0200
-+++ postfix-2.4.6-vda-ng/src/util/file_limit.c 2007-11-24 12:48:53.000000000 +0100
+diff -Nru postfix-2.5.1/src/util/file_limit.c postfix-2.5.1-vda-ng/src/util/file_limit.c
+--- postfix-2.5.1/src/util/file_limit.c 2003-10-22 20:48:36.000000000 +0200
++++ postfix-2.5.1-vda-ng/src/util/file_limit.c 2008-03-15 15:06:00.539717108 +0100
@@ -85,7 +85,11 @@
#else
struct rlimit rlim;
@@ -173,9 +1616,9 @@ diff -Nru postfix-2.4.6/src/util/file_limit.c postfix-2.4.6-vda-ng/src/util/file
if (setrlimit(RLIMIT_FSIZE, &rlim) < 0)
msg_fatal("setrlimit: %m");
#ifdef SIGXFSZ
-diff -Nru postfix-2.4.6/src/virtual/mailbox.c postfix-2.4.6-vda-ng/src/virtual/mailbox.c
---- postfix-2.4.6/src/virtual/mailbox.c 2006-06-26 14:59:19.000000000 +0200
-+++ postfix-2.4.6-vda-ng/src/virtual/mailbox.c 2007-11-26 12:30:21.000000000 +0100
+diff -Nru postfix-2.5.1/src/virtual/mailbox.c postfix-2.5.1-vda-ng/src/virtual/mailbox.c
+--- postfix-2.5.1/src/virtual/mailbox.c 2006-06-26 14:59:19.000000000 +0200
++++ postfix-2.5.1-vda-ng/src/virtual/mailbox.c 2008-03-15 15:06:00.951703589 +0100
@@ -70,6 +70,70 @@
#define YES 1
#define NO 0
@@ -355,9 +1798,9 @@ diff -Nru postfix-2.4.6/src/virtual/mailbox.c postfix-2.4.6-vda-ng/src/virtual/m
/*
* Cleanup.
-diff -Nru postfix-2.4.6/src/virtual/maildir.c postfix-2.4.6-vda-ng/src/virtual/maildir.c
---- postfix-2.4.6/src/virtual/maildir.c 2006-06-26 14:59:19.000000000 +0200
-+++ postfix-2.4.6-vda-ng/src/virtual/maildir.c 2007-11-24 13:20:57.000000000 +0100
+diff -Nru postfix-2.5.1/src/virtual/maildir.c postfix-2.5.1-vda-ng/src/virtual/maildir.c
+--- postfix-2.5.1/src/virtual/maildir.c 2006-06-26 14:59:19.000000000 +0200
++++ postfix-2.5.1-vda-ng/src/virtual/maildir.c 2008-03-15 15:06:01.303692043 +0100
@@ -63,28 +63,406 @@
#include <mbox_open.h>
#include <dsn_util.h>
@@ -1312,9 +2755,9 @@ diff -Nru postfix-2.4.6/src/virtual/maildir.c postfix-2.4.6-vda-ng/src/virtual/m
+
return (deliver_status);
}
-diff -Nru postfix-2.4.6/src/virtual/virtual.c postfix-2.4.6-vda-ng/src/virtual/virtual.c
---- postfix-2.4.6/src/virtual/virtual.c 2007-03-27 02:07:43.000000000 +0200
-+++ postfix-2.4.6-vda-ng/src/virtual/virtual.c 2007-11-24 12:48:53.000000000 +0100
+diff -Nru postfix-2.5.1/src/virtual/virtual.c postfix-2.5.1-vda-ng/src/virtual/virtual.c
+--- postfix-2.5.1/src/virtual/virtual.c 2008-01-08 21:35:08.000000000 +0100
++++ postfix-2.5.1-vda-ng/src/virtual/virtual.c 2008-03-15 15:12:30.906943990 +0100
@@ -330,12 +330,28 @@
int var_virt_mailbox_limit;
char *var_mail_spool_dir; /* XXX dependency fix */
@@ -1374,11 +2817,16 @@ diff -Nru postfix-2.4.6/src/virtual/virtual.c postfix-2.4.6-vda-ng/src/virtual/v
virtual_mbox_lock_mask = mbox_lock_mask(var_virt_mailbox_lock);
}
-@@ -495,16 +520,33 @@
- VAR_VIRT_MAILBOX_LIMIT, DEF_VIRT_MAILBOX_LIMIT, &var_virt_mailbox_limit, 0, 0,
- 0,
- };
-- static CONFIG_STR_TABLE str_table[] = {
+@@ -490,20 +515,37 @@
+
+ int main(int argc, char **argv)
+ {
+- static const CONFIG_INT_TABLE int_table[] = {
+- VAR_VIRT_MINUID, DEF_VIRT_MINUID, &var_virt_minimum_uid, 1, 0,
+- VAR_VIRT_MAILBOX_LIMIT, DEF_VIRT_MAILBOX_LIMIT, &var_virt_mailbox_limit, 0, 0,
+- 0,
+- };
+- static const CONFIG_STR_TABLE str_table[] = {
- VAR_MAIL_SPOOL_DIR, DEF_MAIL_SPOOL_DIR, &var_mail_spool_dir, 0, 0,
- VAR_VIRT_MAILBOX_MAPS, DEF_VIRT_MAILBOX_MAPS, &var_virt_mailbox_maps, 0, 0,
- VAR_VIRT_UID_MAPS, DEF_VIRT_UID_MAPS, &var_virt_uid_maps, 0, 0,
@@ -1386,47 +2834,577 @@ diff -Nru postfix-2.4.6/src/virtual/virtual.c postfix-2.4.6-vda-ng/src/virtual/v
- VAR_VIRT_MAILBOX_BASE, DEF_VIRT_MAILBOX_BASE, &var_virt_mailbox_base, 1, 0,
- VAR_VIRT_MAILBOX_LOCK, DEF_VIRT_MAILBOX_LOCK, &var_virt_mailbox_lock, 1, 0,
- 0,
+- };
++ static const CONFIG_INT_TABLE int_table[] = {
++ VAR_VIRT_MINUID, DEF_VIRT_MINUID, &var_virt_minimum_uid, 1, 0,
++ VAR_VIRT_MAILBOX_LIMIT, DEF_VIRT_MAILBOX_LIMIT, &var_virt_mailbox_limit, 0, 0,
++ 0,
++ };
+
-+ static CONFIG_BOOL_TABLE bool_table[] = {
-+ VAR_VIRT_MAILBOX_LIMIT_INBOX, DEF_VIRT_MAILBOX_LIMIT_INBOX, &var_virt_mailbox_limit_inbox,
-+ VAR_VIRT_MAILBOX_LIMIT_OVERRIDE, DEF_VIRT_MAILBOX_LIMIT_OVERRIDE, &var_virt_mailbox_limit_override,
-+ VAR_VIRT_MAILDIR_EXTENDED, DEF_VIRT_MAILDIR_EXTENDED, &var_virt_maildir_extended,
-+ VAR_VIRT_OVERQUOTA_BOUNCE, DEF_VIRT_OVERQUOTA_BOUNCE, &var_virt_overquota_bounce,
-+ VAR_VIRT_TRASH_COUNT, DEF_VIRT_TRASH_COUNT, &var_virt_trash_count,
-+ VAR_VIRT_MAILDIR_FILTER, DEF_VIRT_MAILDIR_FILTER, &var_virt_maildir_filter,
-+ 0,
- };
-
-+ static CONFIG_STR_TABLE str_table[] = {
-+ VAR_MAIL_SPOOL_DIR, DEF_MAIL_SPOOL_DIR, &var_mail_spool_dir, 0, 0,
-+ VAR_VIRT_MAILBOX_MAPS, DEF_VIRT_MAILBOX_MAPS, &var_virt_mailbox_maps, 0, 0,
-+ VAR_VIRT_UID_MAPS, DEF_VIRT_UID_MAPS, &var_virt_uid_maps, 0, 0,
-+ VAR_VIRT_GID_MAPS, DEF_VIRT_GID_MAPS, &var_virt_gid_maps, 0, 0,
-+ VAR_VIRT_MAILBOX_LIMIT_MAPS, DEF_VIRT_MAILBOX_LIMIT_MAPS, &var_virt_mailbox_limit_maps, 0, 0,
-+ VAR_VIRT_MAILBOX_BASE, DEF_VIRT_MAILBOX_BASE, &var_virt_mailbox_base, 1, 0,
-+ VAR_VIRT_MAILBOX_LOCK, DEF_VIRT_MAILBOX_LOCK, &var_virt_mailbox_lock, 1, 0,
-+ VAR_VIRT_MAILDIR_LIMIT_MESSAGE, DEF_VIRT_MAILDIR_LIMIT_MESSAGE, &var_virt_maildir_limit_message, 1, 0,
-+ VAR_VIRT_MAILDIR_LIMIT_MESSAGE_MAPS, DEF_VIRT_MAILDIR_LIMIT_MESSAGE_MAPS, &var_virt_maildir_limit_message_maps, 0, 0,
-+ VAR_VIRT_MAILDIR_SUFFIX, DEF_VIRT_MAILDIR_SUFFIX, &var_virt_maildir_suffix, 0, 0,
-+ VAR_VIRT_TRASH_NAME, DEF_VIRT_TRASH_NAME, &var_virt_trash_name, 0, 0,
-+ VAR_VIRT_MAILDIR_FILTER_MAPS, DEF_VIRT_MAILDIR_FILTER_MAPS, &var_virt_maildir_filter_maps, 0, 0,
-+ 0,
++ static const CONFIG_BOOL_TABLE bool_table[] = {
++ VAR_VIRT_MAILBOX_LIMIT_INBOX, DEF_VIRT_MAILBOX_LIMIT_INBOX, &var_virt_mailbox_limit_inbox,
++ VAR_VIRT_MAILBOX_LIMIT_OVERRIDE, DEF_VIRT_MAILBOX_LIMIT_OVERRIDE, &var_virt_mailbox_limit_override,
++ VAR_VIRT_MAILDIR_EXTENDED, DEF_VIRT_MAILDIR_EXTENDED, &var_virt_maildir_extended,
++ VAR_VIRT_OVERQUOTA_BOUNCE, DEF_VIRT_OVERQUOTA_BOUNCE, &var_virt_overquota_bounce,
++ VAR_VIRT_TRASH_COUNT, DEF_VIRT_TRASH_COUNT, &var_virt_trash_count,
++ VAR_VIRT_MAILDIR_FILTER, DEF_VIRT_MAILDIR_FILTER, &var_virt_maildir_filter,
++ 0,
+ };
+
++ static const CONFIG_STR_TABLE str_table[] = {
++ VAR_MAIL_SPOOL_DIR, DEF_MAIL_SPOOL_DIR, &var_mail_spool_dir, 0, 0,
++ VAR_VIRT_MAILBOX_MAPS, DEF_VIRT_MAILBOX_MAPS, &var_virt_mailbox_maps, 0, 0,
++ VAR_VIRT_UID_MAPS, DEF_VIRT_UID_MAPS, &var_virt_uid_maps, 0, 0,
++ VAR_VIRT_GID_MAPS, DEF_VIRT_GID_MAPS, &var_virt_gid_maps, 0, 0,
++ VAR_VIRT_MAILBOX_LIMIT_MAPS, DEF_VIRT_MAILBOX_LIMIT_MAPS, &var_virt_mailbox_limit_maps, 0, 0,
++ VAR_VIRT_MAILBOX_BASE, DEF_VIRT_MAILBOX_BASE, &var_virt_mailbox_base, 1, 0,
++ VAR_VIRT_MAILBOX_LOCK, DEF_VIRT_MAILBOX_LOCK, &var_virt_mailbox_lock, 1, 0,
++ VAR_VIRT_MAILDIR_LIMIT_MESSAGE, DEF_VIRT_MAILDIR_LIMIT_MESSAGE, &var_virt_maildir_limit_message, 1, 0,
++ VAR_VIRT_MAILDIR_LIMIT_MESSAGE_MAPS, DEF_VIRT_MAILDIR_LIMIT_MESSAGE_MAPS, &var_virt_maildir_limit_message_maps, 0, 0,
++ VAR_VIRT_MAILDIR_SUFFIX, DEF_VIRT_MAILDIR_SUFFIX, &var_virt_maildir_suffix, 0, 0,
++ VAR_VIRT_TRASH_NAME, DEF_VIRT_TRASH_NAME, &var_virt_trash_name, 0, 0,
++ VAR_VIRT_MAILDIR_FILTER_MAPS, DEF_VIRT_MAILDIR_FILTER_MAPS, &var_virt_maildir_filter_maps, 0, 0,
++ 0,
++ };
+
/*
* Fingerprint executables and core dumps.
- */
@@ -516,6 +558,7 @@
MAIL_SERVER_PRE_INIT, pre_init,
MAIL_SERVER_POST_INIT, post_init,
MAIL_SERVER_PRE_ACCEPT, pre_accept,
-+ MAIL_SERVER_BOOL_TABLE, bool_table,
++ MAIL_SERVER_BOOL_TABLE, bool_table,
MAIL_SERVER_PRIVILEGED,
0);
}
-diff -Nru postfix-2.4.6/src/virtual/virtual.h postfix-2.4.6-vda-ng/src/virtual/virtual.h
---- postfix-2.4.6/src/virtual/virtual.h 2006-01-08 00:59:47.000000000 +0100
-+++ postfix-2.4.6-vda-ng/src/virtual/virtual.h 2007-11-24 12:48:53.000000000 +0100
+diff -Nru postfix-2.5.1/src/virtual/virtual.c.orig postfix-2.5.1-vda-ng/src/virtual/virtual.c.orig
+--- postfix-2.5.1/src/virtual/virtual.c.orig 1970-01-01 01:00:00.000000000 +0100
++++ postfix-2.5.1-vda-ng/src/virtual/virtual.c.orig 2008-03-15 15:05:24.128912042 +0100
+@@ -0,0 +1,521 @@
++/*++
++/* NAME
++/* virtual 8
++/* SUMMARY
++/* Postfix virtual domain mail delivery agent
++/* SYNOPSIS
++/* \fBvirtual\fR [generic Postfix daemon options]
++/* DESCRIPTION
++/* The \fBvirtual\fR(8) delivery agent is designed for virtual mail
++/* hosting services. Originally based on the Postfix \fBlocal\fR(8)
++/* delivery
++/* agent, this agent looks up recipients with map lookups of their
++/* full recipient address, instead of using hard-coded unix password
++/* file lookups of the address local part only.
++/*
++/* This delivery agent only delivers mail. Other features such as
++/* mail forwarding, out-of-office notifications, etc., must be
++/* configured via virtual_alias maps or via similar lookup mechanisms.
++/* MAILBOX LOCATION
++/* .ad
++/* .fi
++/* The mailbox location is controlled by the \fBvirtual_mailbox_base\fR
++/* and \fBvirtual_mailbox_maps\fR configuration parameters (see below).
++/* The \fBvirtual_mailbox_maps\fR table is indexed by the recipient
++/* address as described under TABLE SEARCH ORDER below.
++/*
++/* The mailbox pathname is constructed as follows:
++/*
++/* .nf
++/* \fB$virtual_mailbox_base/$virtual_mailbox_maps(\fIrecipient\fB)\fR
++/* .fi
++/*
++/* where \fIrecipient\fR is the full recipient address.
++/* UNIX MAILBOX FORMAT
++/* .ad
++/* .fi
++/* When the mailbox location does not end in \fB/\fR, the message
++/* is delivered in UNIX mailbox format. This format stores multiple
++/* messages in one textfile.
++/*
++/* The \fBvirtual\fR(8) delivery agent prepends a "\fBFrom \fIsender
++/* time_stamp\fR" envelope header to each message, prepends a
++/* \fBDelivered-To:\fR message header with the envelope recipient
++/* address,
++/* prepends an \fBX-Original-To:\fR header with the recipient address as
++/* given to Postfix,
++/* prepends a \fBReturn-Path:\fR message header with the
++/* envelope sender address, prepends a \fB>\fR character to lines
++/* beginning with "\fBFrom \fR", and appends an empty line.
++/*
++/* The mailbox is locked for exclusive access while delivery is in
++/* progress. In case of problems, an attempt is made to truncate the
++/* mailbox to its original length.
++/* QMAIL MAILDIR FORMAT
++/* .ad
++/* .fi
++/* When the mailbox location ends in \fB/\fR, the message is delivered
++/* in qmail \fBmaildir\fR format. This format stores one message per file.
++/*
++/* The \fBvirtual\fR(8) delivery agent prepends a \fBDelivered-To:\fR
++/* message header with the final envelope recipient address,
++/* prepends an \fBX-Original-To:\fR header with the recipient address as
++/* given to Postfix, and prepends a
++/* \fBReturn-Path:\fR message header with the envelope sender address.
++/*
++/* By definition, \fBmaildir\fR format does not require application-level
++/* file locking during mail delivery or retrieval.
++/* MAILBOX OWNERSHIP
++/* .ad
++/* .fi
++/* Mailbox ownership is controlled by the \fBvirtual_uid_maps\fR
++/* and \fBvirtual_gid_maps\fR lookup tables, which are indexed
++/* with the full recipient address. Each table provides
++/* a string with the numerical user and group ID, respectively.
++/*
++/* The \fBvirtual_minimum_uid\fR parameter imposes a lower bound on
++/* numerical user ID values that may be specified in any
++/* \fBvirtual_uid_maps\fR.
++/* CASE FOLDING
++/* .ad
++/* .fi
++/* All delivery decisions are made using the full recipient
++/* address, folded to lower case. See also the next section
++/* for a few exceptions with optional address extensions.
++/* TABLE SEARCH ORDER
++/* .ad
++/* .fi
++/* Normally, a lookup table is specified as a text file that
++/* serves as input to the \fBpostmap\fR(1) command. The result, an
++/* indexed file in \fBdbm\fR or \fBdb\fR format, is used for fast
++/* searching by the mail system.
++/*
++/* The search order is as follows. The search stops
++/* upon the first successful lookup.
++/* .IP \(bu
++/* When the recipient has an optional address extension the
++/* \fIuser+extension@domain.tld\fR address is looked up first.
++/* .sp
++/* With Postfix versions before 2.1, the optional address extension
++/* is always ignored.
++/* .IP \(bu
++/* The \fIuser@domain.tld\fR address, without address extension,
++/* is looked up next.
++/* .IP \(bu
++/* Finally, the recipient \fI@domain\fR is looked up.
++/* .PP
++/* When the table is provided via other means such as NIS, LDAP
++/* or SQL, the same lookups are done as for ordinary indexed files.
++/*
++/* Alternatively, a table can be provided as a regular-expression
++/* map where patterns are given as regular expressions. In that case,
++/* only the full recipient address is given to the regular-expression
++/* map.
++/* SECURITY
++/* .ad
++/* .fi
++/* The \fBvirtual\fR(8) delivery agent is not security sensitive, provided
++/* that the lookup tables with recipient user/group ID information are
++/* adequately protected. This program is not designed to run chrooted.
++/*
++/* The \fBvirtual\fR(8) delivery agent disallows regular expression
++/* substitution of $1 etc. in regular expression lookup tables,
++/* because that would open a security hole.
++/*
++/* The \fBvirtual\fR(8) delivery agent will silently ignore requests
++/* to use the \fBproxymap\fR(8) server. Instead it will open the
++/* table directly. Before Postfix version 2.2, the virtual
++/* delivery agent will terminate with a fatal error.
++/* STANDARDS
++/* RFC 822 (ARPA Internet Text Messages)
++/* DIAGNOSTICS
++/* Mail bounces when the recipient has no mailbox or when the
++/* recipient is over disk quota. In all other cases, mail for
++/* an existing recipient is deferred and a warning is logged.
++/*
++/* Problems and transactions are logged to \fBsyslogd\fR(8).
++/* Corrupted message files are marked so that the queue
++/* manager can move them to the \fBcorrupt\fR queue afterwards.
++/*
++/* Depending on the setting of the \fBnotify_classes\fR parameter,
++/* the postmaster is notified of bounces and of other trouble.
++/* BUGS
++/* This delivery agent supports address extensions in email
++/* addresses and in lookup table keys, but does not propagate
++/* address extension information to the result of table lookup.
++/*
++/* Postfix should have lookup tables that can return multiple result
++/* attributes. In order to avoid the inconvenience of maintaining
++/* three tables, use an LDAP or MYSQL database.
++/* CONFIGURATION PARAMETERS
++/* .ad
++/* .fi
++/* Changes to \fBmain.cf\fR are picked up automatically, as
++/* \fBvirtual\fR(8)
++/* processes run for only a limited amount of time. Use the command
++/* "\fBpostfix reload\fR" to speed up a change.
++/*
++/* The text below provides only a parameter summary. See
++/* \fBpostconf\fR(5) for more details including examples.
++/* MAILBOX DELIVERY CONTROLS
++/* .ad
++/* .fi
++/* .IP "\fBvirtual_mailbox_base (empty)\fR"
++/* A prefix that the \fBvirtual\fR(8) delivery agent prepends to all pathname
++/* results from $virtual_mailbox_maps table lookups.
++/* .IP "\fBvirtual_mailbox_maps (empty)\fR"
++/* Optional lookup tables with all valid addresses in the domains that
++/* match $virtual_mailbox_domains.
++/* .IP "\fBvirtual_minimum_uid (100)\fR"
++/* The minimum user ID value that the \fBvirtual\fR(8) delivery agent accepts
++/* as a result from $virtual_uid_maps table lookup.
++/* .IP "\fBvirtual_uid_maps (empty)\fR"
++/* Lookup tables with the per-recipient user ID that the \fBvirtual\fR(8)
++/* delivery agent uses while writing to the recipient's mailbox.
++/* .IP "\fBvirtual_gid_maps (empty)\fR"
++/* Lookup tables with the per-recipient group ID for \fBvirtual\fR(8) mailbox
++/* delivery.
++/* .PP
++/* Available in Postfix version 2.0 and later:
++/* .IP "\fBvirtual_mailbox_domains ($virtual_mailbox_maps)\fR"
++/* Postfix is final destination for the specified list of domains;
++/* mail is delivered via the $virtual_transport mail delivery transport.
++/* .IP "\fBvirtual_transport (virtual)\fR"
++/* The default mail delivery transport and next-hop destination for
++/* final delivery to domains listed with $virtual_mailbox_domains.
++/* LOCKING CONTROLS
++/* .ad
++/* .fi
++/* .IP "\fBvirtual_mailbox_lock (see 'postconf -d' output)\fR"
++/* How to lock a UNIX-style \fBvirtual\fR(8) mailbox before attempting
++/* delivery.
++/* .IP "\fBdeliver_lock_attempts (20)\fR"
++/* The maximal number of attempts to acquire an exclusive lock on a
++/* mailbox file or \fBbounce\fR(8) logfile.
++/* .IP "\fBdeliver_lock_delay (1s)\fR"
++/* The time between attempts to acquire an exclusive lock on a mailbox
++/* file or \fBbounce\fR(8) logfile.
++/* .IP "\fBstale_lock_time (500s)\fR"
++/* The time after which a stale exclusive mailbox lockfile is removed.
++/* RESOURCE AND RATE CONTROLS
++/* .ad
++/* .fi
++/* .IP "\fBvirtual_destination_concurrency_limit ($default_destination_concurrency_limit)\fR"
++/* The maximal number of parallel deliveries to the same destination
++/* via the virtual message delivery transport.
++/* .IP "\fBvirtual_destination_recipient_limit ($default_destination_recipient_limit)\fR"
++/* The maximal number of recipients per delivery via the virtual
++/* message delivery transport.
++/* .IP "\fBvirtual_mailbox_limit (51200000)\fR"
++/* The maximal size in bytes of an individual mailbox or maildir file,
++/* or zero (no limit).
++/* MISCELLANEOUS CONTROLS
++/* .ad
++/* .fi
++/* .IP "\fBconfig_directory (see 'postconf -d' output)\fR"
++/* The default location of the Postfix main.cf and master.cf
++/* configuration files.
++/* .IP "\fBdaemon_timeout (18000s)\fR"
++/* How much time a Postfix daemon process may take to handle a
++/* request before it is terminated by a built-in watchdog timer.
++/* .IP "\fBdelay_logging_resolution_limit (2)\fR"
++/* The maximal number of digits after the decimal point when logging
++/* sub-second delay values.
++/* .IP "\fBipc_timeout (3600s)\fR"
++/* The time limit for sending or receiving information over an internal
++/* communication channel.
++/* .IP "\fBmax_idle (100s)\fR"
++/* The maximum amount of time that an idle Postfix daemon process waits
++/* for an incoming connection before terminating voluntarily.
++/* .IP "\fBmax_use (100)\fR"
++/* The maximal number of incoming connections that a Postfix daemon
++/* process will service before terminating voluntarily.
++/* .IP "\fBprocess_id (read-only)\fR"
++/* The process ID of a Postfix command or daemon process.
++/* .IP "\fBprocess_name (read-only)\fR"
++/* The process name of a Postfix command or daemon process.
++/* .IP "\fBqueue_directory (see 'postconf -d' output)\fR"
++/* The location of the Postfix top-level queue directory.
++/* .IP "\fBsyslog_facility (mail)\fR"
++/* The syslog facility of Postfix logging.
++/* .IP "\fBsyslog_name (postfix)\fR"
++/* The mail system name that is prepended to the process name in syslog
++/* records, so that "smtpd" becomes, for example, "postfix/smtpd".
++/* SEE ALSO
++/* qmgr(8), queue manager
++/* bounce(8), delivery status reports
++/* postconf(5), configuration parameters
++/* syslogd(8), system logging
++/* README_FILES
++/* Use "\fBpostconf readme_directory\fR" or
++/* "\fBpostconf html_directory\fR" to locate this information.
++/* VIRTUAL_README, domain hosting howto
++/* LICENSE
++/* .ad
++/* .fi
++/* The Secure Mailer license must be distributed with this software.
++/* HISTORY
++/* .ad
++/* .fi
++/* This delivery agent was originally based on the Postfix local delivery
++/* agent. Modifications mainly consisted of removing code that either
++/* was not applicable or that was not safe in this context: aliases,
++/* ~user/.forward files, delivery to "|command" or to /file/name.
++/*
++/* The \fBDelivered-To:\fR message header appears in the \fBqmail\fR
++/* system by Daniel Bernstein.
++/*
++/* The \fBmaildir\fR structure appears in the \fBqmail\fR system
++/* by Daniel Bernstein.
++/* AUTHOR(S)
++/* Wietse Venema
++/* IBM T.J. Watson Research
++/* P.O. Box 704
++/* Yorktown Heights, NY 10598, USA
++/*
++/* Andrew McNamara
++/* andrewm@connect.com.au
++/* connect.com.au Pty. Ltd.
++/* Level 3, 213 Miller St
++/* North Sydney 2060, NSW, Australia
++/*--*/
++
++/* System library. */
++
++#include <sys_defs.h>
++#include <stdlib.h>
++#ifdef USE_PATHS_H
++#include <paths.h> /* XXX mail_spool_dir dependency */
++#endif
++
++/* Utility library. */
++
++#include <msg.h>
++#include <vstring.h>
++#include <vstream.h>
++#include <iostuff.h>
++#include <set_eugid.h>
++#include <dict.h>
++
++/* Global library. */
++
++#include <mail_queue.h>
++#include <recipient_list.h>
++#include <deliver_request.h>
++#include <deliver_completed.h>
++#include <mail_params.h>
++#include <mail_version.h>
++#include <mail_conf.h>
++#include <mail_params.h>
++#include <mail_addr_find.h>
++#include <flush_clnt.h>
++
++/* Single server skeleton. */
++
++#include <mail_server.h>
++
++/* Application-specific. */
++
++#include "virtual.h"
++
++ /*
++ * Tunable parameters.
++ */
++char *var_virt_mailbox_maps;
++char *var_virt_uid_maps;
++char *var_virt_gid_maps;
++int var_virt_minimum_uid;
++char *var_virt_mailbox_base;
++char *var_virt_mailbox_lock;
++int var_virt_mailbox_limit;
++char *var_mail_spool_dir; /* XXX dependency fix */
++
++ /*
++ * Mappings.
++ */
++MAPS *virtual_mailbox_maps;
++MAPS *virtual_uid_maps;
++MAPS *virtual_gid_maps;
++
++ /*
++ * Bit masks.
++ */
++int virtual_mbox_lock_mask;
++
++/* local_deliver - deliver message with extreme prejudice */
++
++static int local_deliver(DELIVER_REQUEST *rqst, char *service)
++{
++ const char *myname = "local_deliver";
++ RECIPIENT *rcpt_end = rqst->rcpt_list.info + rqst->rcpt_list.len;
++ RECIPIENT *rcpt;
++ int rcpt_stat;
++ int msg_stat;
++ LOCAL_STATE state;
++ USER_ATTR usr_attr;
++
++ if (msg_verbose)
++ msg_info("local_deliver: %s from %s", rqst->queue_id, rqst->sender);
++
++ /*
++ * Initialize the delivery attributes that are not recipient specific.
++ */
++ state.level = 0;
++ deliver_attr_init(&state.msg_attr);
++ state.msg_attr.queue_name = rqst->queue_name;
++ state.msg_attr.queue_id = rqst->queue_id;
++ state.msg_attr.fp = rqst->fp;
++ state.msg_attr.offset = rqst->data_offset;
++ state.msg_attr.sender = rqst->sender;
++ state.msg_attr.dsn_envid = rqst->dsn_envid;
++ state.msg_attr.dsn_ret = rqst->dsn_ret;
++ state.msg_attr.relay = service;
++ state.msg_attr.msg_stats = rqst->msg_stats;
++ RESET_USER_ATTR(usr_attr, state.level);
++ state.request = rqst;
++
++ /*
++ * Iterate over each recipient named in the delivery request. When the
++ * mail delivery status for a given recipient is definite (i.e. bounced
++ * or delivered), update the message queue file and cross off the
++ * recipient. Update the per-message delivery status.
++ */
++ for (msg_stat = 0, rcpt = rqst->rcpt_list.info; rcpt < rcpt_end; rcpt++) {
++ state.msg_attr.rcpt = *rcpt;
++ rcpt_stat = deliver_recipient(state, usr_attr);
++ if (rcpt_stat == 0 && (rqst->flags & DEL_REQ_FLAG_SUCCESS))
++ deliver_completed(state.msg_attr.fp, rcpt->offset);
++ msg_stat |= rcpt_stat;
++ }
++
++ deliver_attr_free(&state.msg_attr);
++ return (msg_stat);
++}
++
++/* local_service - perform service for client */
++
++static void local_service(VSTREAM *stream, char *service, char **argv)
++{
++ DELIVER_REQUEST *request;
++ int status;
++
++ /*
++ * Sanity check. This service takes no command-line arguments.
++ */
++ if (argv[0])
++ msg_fatal("unexpected command-line argument: %s", argv[0]);
++
++ /*
++ * This routine runs whenever a client connects to the UNIX-domain socket
++ * that is dedicated to local mail delivery service. What we see below is
++ * a little protocol to (1) tell the client that we are ready, (2) read a
++ * delivery request from the client, and (3) report the completion status
++ * of that request.
++ */
++ if ((request = deliver_request_read(stream)) != 0) {
++ status = local_deliver(request, service);
++ deliver_request_done(stream, request, status);
++ }
++}
++
++/* pre_accept - see if tables have changed */
++
++static void pre_accept(char *unused_name, char **unused_argv)
++{
++ const char *table;
++
++ if ((table = dict_changed_name()) != 0) {
++ msg_info("table %s has changed -- restarting", table);
++ exit(0);
++ }
++}
++
++/* post_init - post-jail initialization */
++
++static void post_init(char *unused_name, char **unused_argv)
++{
++
++ /*
++ * Drop privileges most of the time.
++ */
++ set_eugid(var_owner_uid, var_owner_gid);
++
++ /*
++ * No case folding needed: the recipient address is case folded.
++ */
++ virtual_mailbox_maps =
++ maps_create(VAR_VIRT_MAILBOX_MAPS, var_virt_mailbox_maps,
++ DICT_FLAG_LOCK | DICT_FLAG_PARANOID);
++
++ virtual_uid_maps =
++ maps_create(VAR_VIRT_UID_MAPS, var_virt_uid_maps,
++ DICT_FLAG_LOCK | DICT_FLAG_PARANOID);
++
++ virtual_gid_maps =
++ maps_create(VAR_VIRT_GID_MAPS, var_virt_gid_maps,
++ DICT_FLAG_LOCK | DICT_FLAG_PARANOID);
++
++ virtual_mbox_lock_mask = mbox_lock_mask(var_virt_mailbox_lock);
++}
++
++/* pre_init - pre-jail initialization */
++
++static void pre_init(char *unused_name, char **unused_argv)
++{
++
++ /*
++ * Reset the file size limit from the message size limit to the mailbox
++ * size limit.
++ *
++ * We can't have mailbox size limit smaller than the message size limit,
++ * because that prohibits the delivery agent from updating the queue
++ * file.
++ */
++ if (var_virt_mailbox_limit) {
++ if (var_virt_mailbox_limit < var_message_limit || var_message_limit == 0)
++ msg_fatal("main.cf configuration error: %s is smaller than %s",
++ VAR_VIRT_MAILBOX_LIMIT, VAR_MESSAGE_LIMIT);
++ set_file_limit(var_virt_mailbox_limit);
++ }
++
++ /*
++ * flush client.
++ */
++ flush_init();
++}
++
++MAIL_VERSION_STAMP_DECLARE;
++
++/* main - pass control to the single-threaded skeleton */
++
++int main(int argc, char **argv)
++{
++ static const CONFIG_INT_TABLE int_table[] = {
++ VAR_VIRT_MINUID, DEF_VIRT_MINUID, &var_virt_minimum_uid, 1, 0,
++ VAR_VIRT_MAILBOX_LIMIT, DEF_VIRT_MAILBOX_LIMIT, &var_virt_mailbox_limit, 0, 0,
++ 0,
++ };
++ static const CONFIG_STR_TABLE str_table[] = {
++ VAR_MAIL_SPOOL_DIR, DEF_MAIL_SPOOL_DIR, &var_mail_spool_dir, 0, 0,
++ VAR_VIRT_MAILBOX_MAPS, DEF_VIRT_MAILBOX_MAPS, &var_virt_mailbox_maps, 0, 0,
++ VAR_VIRT_UID_MAPS, DEF_VIRT_UID_MAPS, &var_virt_uid_maps, 0, 0,
++ VAR_VIRT_GID_MAPS, DEF_VIRT_GID_MAPS, &var_virt_gid_maps, 0, 0,
++ VAR_VIRT_MAILBOX_BASE, DEF_VIRT_MAILBOX_BASE, &var_virt_mailbox_base, 1, 0,
++ VAR_VIRT_MAILBOX_LOCK, DEF_VIRT_MAILBOX_LOCK, &var_virt_mailbox_lock, 1, 0,
++ 0,
++ };
++
++ /*
++ * Fingerprint executables and core dumps.
++ */
++ MAIL_VERSION_STAMP_ALLOCATE;
++
++ single_server_main(argc, argv, local_service,
++ MAIL_SERVER_INT_TABLE, int_table,
++ MAIL_SERVER_STR_TABLE, str_table,
++ MAIL_SERVER_PRE_INIT, pre_init,
++ MAIL_SERVER_POST_INIT, post_init,
++ MAIL_SERVER_PRE_ACCEPT, pre_accept,
++ MAIL_SERVER_PRIVILEGED,
++ 0);
++}
+diff -Nru postfix-2.5.1/src/virtual/virtual.h postfix-2.5.1-vda-ng/src/virtual/virtual.h
+--- postfix-2.5.1/src/virtual/virtual.h 2006-01-08 00:59:47.000000000 +0100
++++ postfix-2.5.1-vda-ng/src/virtual/virtual.h 2008-03-15 15:06:02.103665796 +0100
@@ -34,6 +34,9 @@
extern MAPS *virtual_mailbox_maps;
extern MAPS *virtual_uid_maps;