# Exit codes from <sysexits.h>
EX_TEMPFAIL=75
EX_UNAVAILABLE=69
+ STATUS=$EX_TEMPFAIL
cd $INSPECT_DIR || { echo $INSPECT_DIR does not exist; exit $EX_TEMPFAIL; }
# Clean up when done or when aborting.
- trap "rm -f in.$$; exit" 0 1 2 3 15
+ trap "rm -f in.$$; exit $STATUS" 0 1 2 3 15
cat >in.$$ || { echo Cannot save mail to file; exit $EX_TEMPFAIL; }
$SENDMAIL "$@" <in.$$
- exit $?
+ STATUS=$?
The idea is to first capture the message to file and then run the
content through run a third-party content filter program. If the
Bugfix: reorganized some code in the MYSQL client to end
a number of memory allocation/deallocation problems.
This code needs more work. File: dict_mysql.c.
+
+20001218
+
+ Bugfix: the MYSQL client did not provide function pointers
+ for unimplemented operations, causing "postmap -d" to dump
+ core instead if issuing an error message. This is what I
+ get for accepting code that I cannot test myself.
src/lmtp src/trivial-rewrite src/qmgr src/smtp src/bounce src/pipe \
src/showq src/postalias src/postcat src/postconf src/postdrop \
src/postkick src/postlock src/postlog src/postmap src/postsuper \
- src/nqmgr src/spawn src/flush # src/base64 proto man html
+ src/nqmgr src/spawn src/flush src/virtual # src/base64 proto man html
default: update
--- /dev/null
+[Code contribued by Andrew McNamara ]
+
+Code created by Andrew McNamara <andrew@connect.com.au> and adapted to
+snapshot 20001121 by Xavier Beaudouin.
+
+Code is maintened now by Xavier Beaudouin <kiwi@oav.net>
+
+[Original Message]
+I've run out of time to fiddle further at the moment, so I've decided to
+post my virtual local delivery agent. Note that this is still a work in
+progress, so don't bet your business on it.
+
+I'll repeat what I said last time:
+
+ This code is designed for ISP's who offer virtual mail hosting. It
+ looks up the location, uid and gid of user mailboxes via separate maps,
+ and the mailbox location map can specify either mailbox or maildir
+ delivery (controlled by trailing slash on mailbox name).
+
+ The agent does not support aliases or .forwards (use the virtual table
+ instead), and therefore doesn't support file or program aliases. This
+ choice was made to simplify and streamline the code (it allowed me to
+ dispense with 70% of local's code - mostly the bits that are a security
+ headache) - if you need this functionality, this agent isn't for you.
+
+ It also doesn't support writing to a common spool as root and then
+ chowning the mailbox to the user - I felt this functionality didn't fit
+ with my overall aims.
+
+Some other notes:
+
+- It's still called "virtual" - I had some concerns that this would
+ confuse people, but I'll leave that call up to Wietse - if he wants
+ to integrate it, he can specify the name.
+
+- I've retained the three separate map lookups at this time. When
+ postfix supports maps that return multiple values, we can consider
+ changing it then.
+
+- Specify "virtual:" as the target in the transport table for domains
+ for which you want this agent used.
+
+- The attached file is a gzipped tar that should be unpacked in the
+ base postfix directory (where the INSTALL and HISTORY files live) -
+ it adds a "virtual" subdirectory, and a "virtual.patch" file. The
+ patch updates the top level Makefile.in to build the new agent, and
+ global/mail_params.h to add the new config parameters.
+
+New config options are:
+
+virtual_mailbox_base
+
+ Specifies a path that is prepended to all mailbox paths. This is
+ a safety measure to ensure an out of control map doesn't litter the
+ filesystem with mailboxes (or worse). While it could be set to "/",
+ this isn't recommended.
+
+virtual_mailbox_maps
+
+ Recipients are looked up in this map to determine the path to their
+ mailbox. If the returned path ends in a slash ("/"), maildir-style
+ delivery is carried out, otherwise the path is assumed to specify a
+ mailbox file. Note that virtual_mailbox_base is unconditionally
+ prepended to this path.
+
+virtual_minimum_uid
+
+ Specifies a minimum uid that will be accepted as a return from a
+ virtual_uid_maps lookup. Returned values less than this will be
+ rejected, and the message will be deferred.
+
+virtual_uid_maps
+
+ Recipients are looked up in this map to determine the UID to be
+ used when writing to the target mailbox.
+
+virtual_gid_maps
+
+ Recipients are looked up in this map to determine the GID to be
+ used when writing to the target mailbox.
+
+virtual_usedotlock
+
+ Use dot-locking when writing to mailboxes - defaults to off.
+
+[ - Exemple configuration - ]
+
+In main.cf file :
+--/---
+ virtual_mailbox_base = /var/mail/vhosts
+ virtual_mailbox_maps = dbm:/etc/postfix/vmailbox
+ virtual_minimum_uid = 100
+ virtual_uid_maps = dbm:/etc/postfix/vuid
+ virtual_gid_maps = dbm:/etc/postfix/vgid
+ virtual_usedotlock = no
+--/---
+
+In vmailbox file :
+
+--/---
+testuser@fakedom.com testuser/
+--/---
+
+In vuid file :
+
+--/---
+testuser@fakedom.com 5000
+--/---
+
+In vgid file :
+
+--/---
+testuser@fakedom.com 5000
+--/---
+
+Don't forget to add in master.cf the entry for the agent, that should be
+like :
+
+--/---
+virtual unix - n n - - virtual
+--/---
+
+NOTES :
+-------
+
+1- Don't forget to add dbm:/etc/posfix/vmailbox into your
+local_recipent_maps in main.cf like :
+
+--/---
+local_recipient_maps = $alias_maps dbm:/etc/posfix/vmailbox unix:passwd.byname
+--/---
+
+2- If you use only the virtual localdelivery you can add the following line
+into main.cf
+
+--/---
+mailbox_transport = virtual
+--/---
+
+Otherwise you can use transport_maps :
+
+In main.cf file :
+
+--/---
+transport_maps=dbm:/etc/postfix/transport
+--/---
+
+In transport file :
+
+--/---
+fakedom.com virtual:
+--/---
+
+
DAEMONS = bounce.8.html cleanup.8.html defer.8.html error.8.html local.8.html \
lmtp.8.html master.8.html pickup.8.html pipe.8.html qmgr.8.html \
showq.8.html smtp.8.html smtpd.8.html trivial-rewrite.8.html \
- nqmgr.8.html spawn.8.html flush.8.html
+ nqmgr.8.html spawn.8.html flush.8.html virtual.8.html
COMMANDS= mailq.1.html newaliases.1.html postalias.1.html postcat.1.html \
postconf.1.html postfix.1.html postkick.1.html postlock.1.html \
postlog.1.html postdrop.1.html postmap.1.html sendmail.1.html \
trivial-rewrite.8.html: ../src/trivial-rewrite/trivial-rewrite.c
srctoman $? | nroff -man | man2html | postlink >$@
+virtual.8.html: ../src/virtual/virtual.c
+ srctoman $? | nroff -man | man2html | postlink >$@
+
postalias.1.html: ../src/postalias/postalias.c
srctoman $? | nroff -man | man2html | postlink >$@
--- /dev/null
+<html> <head> </head> <body> <pre>
+
+
+
+VIRTUAL(8) VIRTUAL(8)
+
+
+<b>NAME</b>
+ virtual - Postfix virtual mail delivery
+
+<b>SYNOPSIS</b>
+ <b>virtual</b> [generic Postfix daemon options]
+
+<b>DESCRIPTION</b>
+ The <b>virtual</b> daemon processes delivery requests from the
+ Postfix queue manager to deliver mail to virtual local
+ recipients. Each delivery request specifies a queue file,
+ a sender address, a domain or host to deliver to, and one
+ or more recipients. This program expects to be run from
+ the <a href="master.8.html"><b>master</b>(8)</a> process manager.
+
+ This daemon is designed for ISP's offering virtual mail
+ hosting services. Originally based on the local delivery
+ agent, this agent locates user mailboxes via map lookups
+ of the full recipient address, rather than hard-coded unix
+ password file searches of the local part only.
+
+ The <b>virtual</b> daemon updates queue files and marks recipi-
+ ents as finished, or it informs the queue manager that
+ delivery should be tried again at a later time. Delivery
+ problem reports are sent to the <a href="bounce.8.html"><b>bounce</b>(8)</a> or <a href="defer.8.html"><b>defer</b>(8)</a> dae-
+ mon as appropriate.
+
+<b>MAILBOX</b> <b>DELIVERY</b>
+ The default per-user mailbox is a file in the UNIX mail
+ spool directory (<b>/var/mail/</b><i>user</i> or <b>/var/spool/mail/</b><i>user</i>);
+ the location can be specified with the <b>mail</b><i>_</i><b>spool</b><i>_</i><b>direc-</b>
+ <b>tory</b> configuration parameter.
+
+ In the case of UNIX-style mailbox delivery, the <b>local</b> dae-
+ mon prepends a "<b>From</b> <i>sender</i> <i>time_stamp</i>" envelope header to
+ each message, prepends a <b>Delivered-To:</b> header with the
+ envelope recipient address, prepends a <b>Return-Path:</b> header
+ with the envelope sender address, prepends a > character
+ to lines beginning with "<b>From</b> ", 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.
+
+ In the case of <b>maildir</b> delivery, the local daemon prepends
+ a <b>Delivered-To:</b> header with the envelope recipient address
+ and prepends a <b>Return-Path:</b> header with the envelope
+ sender address.
+
+<b>DELIVERY</b> <b>RIGHTS</b>
+ Deliveries to mailboxes are made with the rights of the
+ receiving user on whose behalf the delivery is made.
+
+<b>STANDARDS</b>
+ <a href="http://www.faqs.org/rfcs/rfc822.html">RFC 822</a> (ARPA Internet Text Messages)
+
+
+
+
+ 1
+
+
+
+
+
+VIRTUAL(8) VIRTUAL(8)
+
+
+<b>DIAGNOSTICS</b>
+ Problems and transactions are logged to <b>syslogd</b>(8). Cor-
+ rupted message files are marked so that the queue manager
+ can move them to the <b>corrupt</b> queue afterwards.
+
+ Depending on the setting of the <b>notify</b><i>_</i><b>classes</b> parameter,
+ the postmaster is notified of bounces and of other trou-
+ ble.
+
+<b>CONFIGURATION</b> <b>PARAMETERS</b>
+ The following <b>main.cf</b> parameters are especially relevant
+ to this program. See the Postfix <b>main.cf</b> file for syntax
+ details and for default values. Use the <b>postfix</b> <b>reload</b>
+ command after a configuration change.
+
+<b>Mailbox</b> <b>delivery</b>
+ <b>virtual</b><i>_</i><b>mailbox</b><i>_</i><b>base</b>
+ Specifies a path that is prepended to all mailbox
+ paths. This is a safety measure to ensure an out of
+ control map doesn't litter the filesystem with
+ mailboxes. While it could be set to "/", this isn't
+ recommended.
+
+ <b>virtual</b><i>_</i><b>mailbox</b><i>_</i><b>maps</b>
+ Recipients are looked up in this map to determine
+ the path to their mailbox. If the returned path
+ ends in a slash ("/"), maildir-style delivery is
+ carried out, otherwise the path is assumed to spec-
+ ify a mailbox file. Note that <b>virtual</b><i>_</i><b>mailbox</b><i>_</i><b>base</b>
+ is unconditionally prepended to this path.
+
+ <b>virtual</b><i>_</i><b>minimum</b><i>_</i><b>uid</b>
+ Specifies a minimum uid that will be accepted as a
+ return from a <b>virtual</b><i>_</i><b>uid</b><i>_</i><b>maps</b> lookup. Returned
+ values less than this will be rejected, and the
+ message will be deferred.
+
+ <b>virtual</b><i>_</i><b>uid</b><i>_</i><b>maps</b>
+ Recipients are looked up in this map to determine
+ the UID to be used when writing to the target mail-
+ box.
+
+ <b>virtual</b><i>_</i><b>gid</b><i>_</i><b>maps</b>
+ Recipients are looked up in this map to determine
+ the GID to be used when writing to the target mail-
+ box.
+
+<b>Locking</b> <b>controls</b>
+ <b>mailbox</b><i>_</i><b>delivery</b><i>_</i><b>lock</b>
+ How to lock UNIX-style mailboxes: one or more of
+ <b>flock</b>, <b>fcntl</b> or <b>dotlock</b>.
+
+ <b>deliver</b><i>_</i><b>lock</b><i>_</i><b>attempts</b>
+ Limit the number of attempts to acquire an
+
+
+
+ 2
+
+
+
+
+
+VIRTUAL(8) VIRTUAL(8)
+
+
+ exclusive lock on a mailbox file.
+
+ <b>deliver</b><i>_</i><b>lock</b><i>_</i><b>delay</b>
+ Time in seconds between successive attempts to
+ acquire an exclusive lock on a mailbox file.
+
+ <b>stale</b><i>_</i><b>lock</b><i>_</i><b>time</b>
+ Limit the time after which a stale lockfile is
+ removed.
+
+<b>Resource</b> <b>controls</b>
+ <b>virtual</b><i>_</i><b>destination</b><i>_</i><b>concurrency</b><i>_</i><b>limit</b>
+ Limit the number of parallel deliveries to the same
+ domain. The default limit is taken from the
+ <b>default</b><i>_</i><b>destination</b><i>_</i><b>concurrency</b><i>_</i><b>limit</b> parameter.
+
+ <b>virtual</b><i>_</i><b>destination</b><i>_</i><b>recipient</b><i>_</i><b>limit</b>
+ Limit the number of recipients per message deliv-
+ ery. The default limit is taken from the
+ <b>default</b><i>_</i><b>destination</b><i>_</i><b>recipient</b><i>_</i><b>limit</b> parameter.
+
+<b>HISTORY</b>
+ This agent was originally based on the local delivery
+ agent. Modifications mainly consisted of removing code
+ that wasn't applicable or wasn't safe in this context
+ (aliases, .forwards, program aliases).
+
+ The <b>Delivered-To:</b> header appears in the <b>qmail</b> system by
+ Daniel Bernstein.
+
+ The <i>maildir</i> structure appears in the <b>qmail</b> system by
+ Daniel Bernstein.
+
+<b>SEE</b> <b>ALSO</b>
+ <a href="bounce.8.html">bounce(8)</a> non-delivery status reports
+ syslogd(8) system logging
+ <a href="qmgr.8.html">qmgr(8)</a> queue manager
+
+<b>LICENSE</b>
+ The Secure Mailer license must be distributed with this
+ software.
+
+<b>AUTHOR(S)</b>
+ 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
+
+
+
+
+ 3
+
+
+</pre> </body> </html>
DAEMONS = man8/bounce.8 man8/defer.8 man8/cleanup.8 man8/error.8 man8/local.8 \
man8/lmtp.8 man8/master.8 man8/pickup.8 man8/pipe.8 man8/qmgr.8 \
man8/showq.8 man8/smtp.8 man8/smtpd.8 man8/trivial-rewrite.8 \
- man8/nqmgr.8 man8/spawn.8 man8/flush.8
+ man8/nqmgr.8 man8/spawn.8 man8/flush.8 man8/virtual.8
COMMANDS= man1/postalias.1 man1/postcat.1 man1/postconf.1 man1/postfix.1 \
man1/postkick.1 man1/postlock.1 man1/postlog.1 man1/postdrop.1 \
man1/postmap.1 man1/sendmail.1 man1/mailq.1 man1/newaliases.1 \
man8/trivial-rewrite.8: ../src/trivial-rewrite/trivial-rewrite.c
../mantools/srctoman $? >$@
+man8/virtual.8: ../src/virtual/virtual.c
+ ../mantools/srctoman $? >$@
+
man1/postalias.1: ../src/postalias/postalias.c
../mantools/srctoman $? >$@
--- /dev/null
+.TH VIRTUAL 8
+.ad
+.fi
+.SH NAME
+virtual
+\-
+Postfix virtual mail delivery
+.SH SYNOPSIS
+.na
+.nf
+\fBvirtual\fR [generic Postfix daemon options]
+.SH DESCRIPTION
+.ad
+.fi
+The \fBvirtual\fR daemon processes delivery requests from the
+Postfix queue manager to deliver mail to virtual local recipients.
+Each delivery request specifies a queue file, a sender address,
+a domain or host to deliver to, and one or more recipients.
+This program expects to be run from the \fBmaster\fR(8) process
+manager.
+
+This daemon is designed for ISP's offering virtual mail hosting
+services. Originally based on the local delivery agent, this agent
+locates user mailboxes via map lookups of the full recipient
+address, rather than hard-coded unix password file searches of
+the local part only.
+
+The \fBvirtual\fR daemon updates queue files and marks recipients
+as finished, or it informs the queue manager that delivery should
+be tried again at a later time. Delivery problem reports are sent
+to the \fBbounce\fR(8) or \fBdefer\fR(8) daemon as appropriate.
+.SH MAILBOX DELIVERY
+.na
+.nf
+.ad
+.fi
+The default per-user mailbox is a file in the UNIX mail spool
+directory (\fB/var/mail/\fIuser\fR or \fB/var/spool/mail/\fIuser\fR);
+the location can be specified with the \fBmail_spool_directory\fR
+configuration parameter.
+
+In the case of UNIX-style mailbox delivery,
+the \fBlocal\fR daemon prepends a "\fBFrom \fIsender time_stamp\fR"
+envelope header to each message, prepends a \fBDelivered-To:\fR header
+with the envelope recipient address, prepends a \fBReturn-Path:\fR
+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.
+
+In the case of \fBmaildir\fR delivery, the local daemon prepends
+a \fBDelivered-To:\fR header with the envelope recipient address
+and prepends a \fBReturn-Path:\fR header with the envelope sender
+address.
+.SH DELIVERY RIGHTS
+.na
+.nf
+.ad
+.fi
+Deliveries to mailboxes are made with the rights of the receiving
+user on whose behalf the delivery is made.
+.SH STANDARDS
+.na
+.nf
+RFC 822 (ARPA Internet Text Messages)
+.SH DIAGNOSTICS
+.ad
+.fi
+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.
+.SH CONFIGURATION PARAMETERS
+.na
+.nf
+.ad
+.fi
+The following \fBmain.cf\fR parameters are especially relevant to
+this program. See the Postfix \fBmain.cf\fR file for syntax details
+and for default values. Use the \fBpostfix reload\fR command after
+a configuration change.
+.SH Mailbox delivery
+.ad
+.fi
+.IP \fBvirtual_mailbox_base\fR
+Specifies a path that is prepended to all mailbox paths. This is
+a safety measure to ensure an out of control map doesn't litter
+the filesystem with mailboxes. While it could be set to "/",
+this isn't recommended.
+.IP \fBvirtual_mailbox_maps\fR
+Recipients are looked up in this map to determine the path
+to their mailbox. If the returned path ends in a slash
+("/"), maildir-style delivery is carried out, otherwise
+the path is assumed to specify a mailbox file. Note that
+\fBvirtual_mailbox_base\fR is unconditionally prepended to
+this path.
+.IP \fBvirtual_minimum_uid\fR
+Specifies a minimum uid that will be accepted as a return from
+a \fBvirtual_uid_maps\fR lookup. Returned values less than this
+will be rejected, and the message will be deferred.
+.IP \fBvirtual_uid_maps\fR
+Recipients are looked up in this map to determine the UID to be
+used when writing to the target mailbox.
+.IP \fBvirtual_gid_maps\fR
+Recipients are looked up in this map to determine the GID to be
+used when writing to the target mailbox.
+.SH "Locking controls"
+.ad
+.fi
+.IP \fBmailbox_delivery_lock\fR
+How to lock UNIX-style mailboxes: one or more of \fBflock\fR,
+\fBfcntl\fR or \fBdotlock\fR.
+.IP \fBdeliver_lock_attempts\fR
+Limit the number of attempts to acquire an exclusive lock
+on a mailbox file.
+.IP \fBdeliver_lock_delay\fR
+Time in seconds between successive attempts to acquire
+an exclusive lock on a mailbox file.
+.IP \fBstale_lock_time\fR
+Limit the time after which a stale lockfile is removed.
+.SH "Resource controls"
+.ad
+.fi
+.IP \fBvirtual_destination_concurrency_limit\fR
+Limit the number of parallel deliveries to the same domain.
+The default limit is taken from the
+\fBdefault_destination_concurrency_limit\fR parameter.
+.IP \fBvirtual_destination_recipient_limit\fR
+Limit the number of recipients per message delivery.
+The default limit is taken from the
+\fBdefault_destination_recipient_limit\fR parameter.
+.SH HISTORY
+.na
+.nf
+.ad
+.fi
+This agent was originally based on the local delivery
+agent. Modifications mainly consisted of removing code that wasn't
+applicable or wasn't safe in this context (aliases, .forwards,
+program aliases).
+
+The \fBDelivered-To:\fR header appears in the \fBqmail\fR system
+by Daniel Bernstein.
+
+The \fImaildir\fR structure appears in the \fBqmail\fR system
+by Daniel Bernstein.
+.SH SEE ALSO
+.na
+.nf
+bounce(8) non-delivery status reports
+syslogd(8) system logging
+qmgr(8) queue manager
+.SH LICENSE
+.na
+.nf
+.ad
+.fi
+The Secure Mailer license must be distributed with this software.
+.SH AUTHOR(S)
+.na
+.nf
+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
int max; /* max length or zero */
} CONFIG_STR_TABLE;
+typedef struct {
+ const char *name; /* config variable name */
+ const char *defval; /* default value or null */
+ char **target; /* pointer to global variable */
+ int min; /* min length or zero */
+ int max; /* max length or zero */
+} CONFIG_RAW_TABLE;
+
typedef struct {
const char *name; /* config variable name */
int defval; /* default value */
extern void get_mail_conf_int_table(CONFIG_INT_TABLE *);
extern void get_mail_conf_bool_table(CONFIG_BOOL_TABLE *);
extern void get_mail_conf_time_table(CONFIG_TIME_TABLE *);
-extern void get_mail_conf_raw_table(CONFIG_STR_TABLE *);
+extern void get_mail_conf_raw_table(CONFIG_RAW_TABLE *);
/*
* Tables to initialize parameters from the global configuration file or
int max; /* upper bound or zero */
} CONFIG_STR_FN_TABLE;
+typedef struct {
+ const char *name; /* config variable name */
+ const char *(*defval) (void); /* default value provider */
+ char **target; /* pointer to global variable */
+ int min; /* lower bound or zero */
+ int max; /* upper bound or zero */
+} CONFIG_RAW_FN_TABLE;
+
typedef struct {
const char *name; /* config variable name */
int (*defval) (void); /* default value provider */
extern void get_mail_conf_str_fn_table(CONFIG_STR_FN_TABLE *);
extern void get_mail_conf_int_fn_table(CONFIG_INT_FN_TABLE *);
extern void get_mail_conf_bool_fn_table(CONFIG_BOOL_FN_TABLE *);
-extern void get_mail_conf_raw_fn_table(CONFIG_STR_FN_TABLE *);
+extern void get_mail_conf_raw_fn_table(CONFIG_RAW_FN_TABLE *);
/* LICENSE
/* .ad
/* int max;
/*
/* void get_mail_conf_raw_table(table)
-/* CONFIG_STR_TABLE *table;
+/* CONFIG_RAW_TABLE *table;
/*
/* void get_mail_conf_raw_fn_table(table)
-/* CONFIG_STR_TABLE *table;
+/* CONFIG_RAW_TABLE *table;
/* DESCRIPTION
/* This module implements support for string-valued global
/* configuration parameters that are loaded without $name expansion.
/* get_mail_conf_raw_table - look up table of strings */
-void get_mail_conf_raw_table(CONFIG_STR_TABLE *table)
+void get_mail_conf_raw_table(CONFIG_RAW_TABLE *table)
{
while (table->name) {
if (table->target[0])
/* get_mail_conf_raw_fn_table - look up strings, defaults are functions */
-void get_mail_conf_raw_fn_table(CONFIG_STR_FN_TABLE *table)
+void get_mail_conf_raw_fn_table(CONFIG_RAW_FN_TABLE *table)
{
while (table->name) {
if (table->target[0])
#define DEF_EXPORT_ENVIRON "TZ"
extern char *var_export_environ;
+ /*
+ * Tunables for the "virtual" local delivery agent
+ */
+#define VAR_VIRT_MAILBOX_MAPS "virtual_mailbox_maps"
+#define DEF_VIRT_MAILBOX_MAPS ""
+extern char *var_mailbox_maps;
+#define VAR_VIRT_UID_MAPS "virtual_uid_maps"
+#define DEF_VIRT_UID_MAPS ""
+extern char *var_uid_maps;
+#define VAR_VIRT_GID_MAPS "virtual_gid_maps"
+#define DEF_VIRT_GID_MAPS ""
+extern char *var_gid_maps;
+#define VAR_VIRT_USEDOTLOCK "virtual_usedotlock"
+#define DEF_VIRT_USEDOTLOCK 0
+extern bool var_virt_usedotlock;
+#define VAR_VIRT_MINUID "virtual_minimum_uid"
+#define DEF_VIRT_MINUID 100
+extern int var_virt_minimum_uid;
+#define VAR_VIRT_MAILBOX_BASE "virtual_mailbox_base"
+#define DEF_VIRT_MAILBOX_BASE ""
+extern char *var_virt_mailbox_base;
+
/* LICENSE
/* .ad
/* .fi
* Version of this program.
*/
#define VAR_MAIL_VERSION "mail_version"
-#define DEF_MAIL_VERSION "Snapshot-20001217"
+#define DEF_MAIL_VERSION "Snapshot-20001221"
extern char *var_mail_version;
/* LICENSE
};
/* Suppress $name expansion upon loading. */
- static CONFIG_STR_TABLE raw_table[] = {
+ static CONFIG_RAW_TABLE raw_table[] = {
VAR_FORWARD_PATH, DEF_FORWARD_PATH, &var_forward_path, 0, 0,
VAR_MAILBOX_COMMAND, DEF_MAILBOX_COMMAND, &var_mailbox_command, 0, 0,
VAR_LUSER_RELAY, DEF_LUSER_RELAY, &var_luser_relay, 0, 0,
/* global Postfix configuration file. Tables are loaded in the
/* order as specified, and multiple instances of the same type
/* are allowed.
-/* .IP "MAIL_SERVER_RAW_TABLE (CONFIG_STR_TABLE *)"
+/* .IP "MAIL_SERVER_RAW_TABLE (CONFIG_RAW_TABLE *)"
/* A table with configurable parameters, to be loaded from the
/* global Postfix configuration file. Tables are loaded in the
/* order as specified, and multiple instances of the same type
get_mail_conf_time_table(va_arg(ap, CONFIG_TIME_TABLE *));
break;
case MAIL_SERVER_RAW_TABLE:
- get_mail_conf_raw_table(va_arg(ap, CONFIG_STR_TABLE *));
+ get_mail_conf_raw_table(va_arg(ap, CONFIG_RAW_TABLE *));
break;
case MAIL_SERVER_PRE_INIT:
pre_init = va_arg(ap, MAIL_SERVER_INIT_FN);
/* global Postfix configuration file. Tables are loaded in the
/* order as specified, and multiple instances of the same type
/* are allowed.
-/* .IP "MAIL_SERVER_RAW_TABLE (CONFIG_STR_TABLE *)"
+/* .IP "MAIL_SERVER_RAW_TABLE (CONFIG_RAW_TABLE *)"
/* A table with configurable parameters, to be loaded from the
/* global Postfix configuration file. Tables are loaded in the
/* order as specified, and multiple instances of the same type
get_mail_conf_time_table(va_arg(ap, CONFIG_TIME_TABLE *));
break;
case MAIL_SERVER_RAW_TABLE:
- get_mail_conf_raw_table(va_arg(ap, CONFIG_STR_TABLE *));
+ get_mail_conf_raw_table(va_arg(ap, CONFIG_RAW_TABLE *));
break;
case MAIL_SERVER_PRE_INIT:
pre_init = va_arg(ap, MAIL_SERVER_INIT_FN);
/* global Postfix configuration file. Tables are loaded in the
/* order as specified, and multiple instances of the same type
/* are allowed.
-/* .IP "MAIL_SERVER_RAW_TABLE (CONFIG_STR_TABLE *)"
+/* .IP "MAIL_SERVER_RAW_TABLE (CONFIG_RAW_TABLE *)"
/* A table with configurable parameters, to be loaded from the
/* global Postfix configuration file. Tables are loaded in the
/* order as specified, and multiple instances of the same type
get_mail_conf_time_table(va_arg(ap, CONFIG_TIME_TABLE *));
break;
case MAIL_SERVER_RAW_TABLE:
- get_mail_conf_raw_table(va_arg(ap, CONFIG_STR_TABLE *));
+ get_mail_conf_raw_table(va_arg(ap, CONFIG_RAW_TABLE *));
break;
case MAIL_SERVER_PRE_INIT:
pre_init = va_arg(ap, MAIL_SERVER_INIT_FN);
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
TESTPROG=
MAKES = bool_table.h bool_vars.h int_table.h int_vars.h str_table.h \
- str_vars.h time_table.h time_vars.h
+ str_vars.h time_table.h time_vars.h raw_table.h raw_vars.h
PROG = postconf
SAMPLES = ../../conf/main.cf.default
INC_DIR = ../../include
print | "sed 's/[ ][ ]*/ /g' | sort -u >str_table.h"
}
}
+/^(static| )*CONFIG_RAW_TABLE .*\{/,/\};/ {
+ if ($1 ~ /VAR/) {
+ print "char *" substr($3,2,length($3)-2) ";" > "raw_vars.h"
+ print | "sed 's/[ ][ ]*/ /g' | sort -u >raw_table.h"
+ }
+}
/^(static| )*CONFIG_BOOL_TABLE .*\{/,/\};/ {
if ($1 ~ /VAR/) {
print "int " substr($3,2,length($3)-2) ";" > "bool_vars.h"
/* .IP \fB-h\fR
/* Show parameter values only, not the ``name = '' label
/* that normally precedes the value.
-/* .IP \fB-m\fR
-/* List the names of all supported lookup table types.
/* .IP \fB-l\fR
/* List the names of all supported mailbox locking methods.
+/* .IP \fB-m\fR
+/* List the names of all supported lookup table types.
/* .IP \fB-n\fR
/* Print non-default parameter settings only.
/* .IP \fB-v\fR
#define SHOW_MAPS (1<<3) /* show map types */
#define EDIT_MAIN (1<<4) /* edit main.cf */
#define SHOW_LOCKS (1<<5) /* show mailbox lock methods */
+#define SHOW_EVAL (1<<6) /* expand right-hand sides */
/*
* Lookup table for in-core parameter info.
#include "bool_vars.h"
#include "int_vars.h"
#include "str_vars.h"
+#include "raw_vars.h"
/*
* Manually extracted.
0,
};
+static CONFIG_RAW_TABLE raw_table[] = {
+#include "raw_table.h"
+ 0,
+};
+
/*
* Parameters with default values obtained via function calls.
*/
myfree(path);
}
+/* set_parameters - set parameter values from default or explicit setting */
+
+static void set_parameters(void)
+{
+
+ /*
+ * Populate the configuration parameter dictionary with default settings
+ * or with actual settings.
+ *
+ * Iterate over each entry in str_fn_table, str_fn_table_2, time_table,
+ * bool_table, int_table, str_table, and raw_table. Look up each
+ * parameter name in the configuration parameter dictionary. If the
+ * parameter is not set, take the default value, or take the value from
+ * in main.c, without doing $name expansions. This includes converting
+ * default values from numeric/boolean internal forms to external string
+ * form.
+ *
+ * Once the configuration parameter dictionary is populated, printing a
+ * parameter setting is a matter of querying the configuration parameter
+ * dictionary, optionally expanding of $name values, and printing the
+ * result.
+ */
+}
+
/* hash_parameters - hash all parameter names so we can find and sort them */
static void hash_parameters(void)
CONFIG_INT_TABLE *cit;
CONFIG_STR_TABLE *cst;
CONFIG_STR_FN_TABLE *csft;
+ CONFIG_RAW_TABLE *rst;
param_table = htable_create(100);
htable_enter(param_table, csft->name, (char *) csft);
for (csft = str_fn_table_2; csft->name; csft++)
htable_enter(param_table, csft->name, (char *) csft);
+ for (rst = raw_table; rst->name; rst++)
+ htable_enter(param_table, rst->name, (char *) rst);
}
/* show_strval - show string-valued parameter */
static void show_strval(int mode, const char *name, const char *value)
{
+ if (mode & SHOW_EVAL)
+ value = mail_conf_eval(value);
+
if (mode & SHOW_NAME) {
vstream_printf("%s = %s\n", name, value);
} else {
}
}
+/* print_raw - print raw string parameter */
+
+static void print_raw(int mode, CONFIG_RAW_TABLE * rst)
+{
+ const char *value;
+
+ if (mode & SHOW_EVAL)
+ msg_warn("parameter %s expands at run-time", rst->name);
+ mode &= ~SHOW_EVAL;
+
+ if (mode & SHOW_DEFS) {
+ show_strval(mode, rst->name, rst->defval);
+ } else {
+ value = dict_lookup(CONFIG_DICT, rst->name);
+ if ((mode & SHOW_NONDEF) == 0) {
+ if (value == 0) {
+ show_strval(mode, rst->name, rst->defval);
+ } else {
+ show_strval(mode, rst->name, value);
+ }
+ } else {
+ if (value != 0)
+ show_strval(mode, rst->name, value);
+ }
+ }
+}
+
/* print_parameter - show specific parameter */
static void print_parameter(int mode, char *ptr)
#define INSIDE(p,t) (ptr >= (char *) t && ptr < ((char *) t) + sizeof(t))
/*
- * This is gross, but the best we can do on short notice.
+ * This is gross, but the best we can do on short notice. Instead of
+ * guessing we should use a tagged union. This is what code looks like
+ * when written under the pressure of a first public release.
*/
if (INSIDE(ptr, time_table))
print_time(mode, (CONFIG_TIME_TABLE *) ptr);
print_str_fn(mode, (CONFIG_STR_FN_TABLE *) ptr);
if (INSIDE(ptr, str_fn_table_2))
print_str_fn_2(mode, (CONFIG_STR_FN_TABLE *) ptr);
+ if (INSIDE(ptr, raw_table))
+ print_raw(mode, (CONFIG_RAW_TABLE *) ptr);
if (msg_verbose)
vstream_fflush(VSTREAM_OUT);
}
case 'd':
mode |= SHOW_DEFS;
break;
+ case 'E':
+ mode |= SHOW_EVAL;
+ break;
case 'e':
mode |= EDIT_MAIN;
break;
* If showing non-default values, read main.cf.
*/
else {
- if ((mode & SHOW_DEFS) == 0)
+ if ((mode & SHOW_DEFS) == 0) {
read_parameters();
+ set_parameters();
+ }
/*
* Throw together all parameters and show the asked values.
dict_db.o: dict_db.h
dict_dbm.o: dict_dbm.c
dict_dbm.o: sys_defs.h
+dict_dbm.o: msg.h
+dict_dbm.o: mymalloc.h
+dict_dbm.o: htable.h
+dict_dbm.o: iostuff.h
+dict_dbm.o: vstring.h
+dict_dbm.o: vbuf.h
+dict_dbm.o: myflock.h
+dict_dbm.o: stringops.h
+dict_dbm.o: dict.h
+dict_dbm.o: vstream.h
+dict_dbm.o: argv.h
+dict_dbm.o: dict_dbm.h
dict_env.o: dict_env.c
dict_env.o: sys_defs.h
dict_env.o: mymalloc.h
dict_ldap.o: sys_defs.h
dict_mysql.o: dict_mysql.c
dict_mysql.o: sys_defs.h
+dict_mysql.o: dict.h
+dict_mysql.o: vstream.h
+dict_mysql.o: vbuf.h
+dict_mysql.o: argv.h
+dict_mysql.o: msg.h
+dict_mysql.o: mymalloc.h
+dict_mysql.o: dict_mysql.h
+dict_mysql.o: vstring.h
dict_ni.o: dict_ni.c
dict_ni.o: sys_defs.h
dict_nis.o: dict_nis.c
static void plmysql_connect_single(HOST *, char *, char *, char *);
static int plmysql_ready_reconn(HOST *);
static void dict_mysql_update(DICT *, const char *, const char *);
+static void dict_mysql_delete(struct DICT *, const char *);
+static void dict_mysql_sequence(struct DICT *, const int, const char **, const char **);
static const char *dict_mysql_lookup(DICT *, const char *);
DICT *dict_mysql_open(const char *, int, int);
static void dict_mysql_close(DICT *);
dict_mysql = (DICT_MYSQL *) mymalloc(sizeof(DICT_MYSQL));
dict_mysql->dict.lookup = dict_mysql_lookup;
dict_mysql->dict.update = dict_mysql_update;
+ dict_mysql->dict.delete = dict_mysql_delete;
+ dict_mysql->dict.sequence = dict_mysql_sequence;
dict_mysql->dict.close = dict_mysql_close;
dict_mysql->dict.fd = -1; /* there's no file descriptor
* for locking */
msg_fatal("dict_mysql_update: attempt to update mysql database");
}
+static void dict_mysql_delete(DICT *unused_dict, const char *unused_name)
+{
+ msg_fatal("dict_mysql_delete: attempt to delete mysql database entry");
+}
+
+static void dict_mysql_sequence(DICT *unused_dict, const int unused_function,
+ const char **unused_key, const char **unused_value)
+{
+ msg_fatal("dict_mysql_sequence: attempt to iterate over mysql database");
+}
+
#endif
--- /dev/null
+../../.indent.pro
\ No newline at end of file
--- /dev/null
+SHELL = /bin/sh
+SRCS = virtual.c mailbox.c recipient.c deliver_attr.c maildir.c unknown.c
+OBJS = virtual.o mailbox.o recipient.o deliver_attr.o maildir.o unknown.o
+HDRS = virtual.h
+TESTSRC =
+WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
+ -Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
+ -Wunused
+DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE) -I..
+CFLAGS = $(DEBUG) $(OPT) $(DEFS)
+PROG = virtual
+TESTPROG=
+INC_DIR = ../../include
+LIBS = ../../lib/libmaster.a ../../lib/libglobal.a ../../lib/libutil.a $(AUXLIBS)
+
+.c.o:; $(CC) $(CFLAGS) -c $*.c
+
+$(PROG): $(OBJS) $(LIBS)
+ $(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
+
+Makefile: Makefile.in
+ (set -e; echo "# DO NOT EDIT"; $(OPTS) $(SHELL) ../../makedefs; cat $?) >$@
+
+test: $(TESTPROG)
+
+update: ../../libexec/$(PROG)
+
+../../libexec/$(PROG): $(PROG)
+ cp $(PROG) ../../libexec
+
+printfck: $(OBJS) $(PROG)
+ rm -rf printfck
+ mkdir printfck
+ cp *.h printfck
+ sed '1,/^# do not edit/!d' Makefile >printfck/Makefile
+ set -e; for i in *.c; do printfck -f .printfck $$i >printfck/$$i; done
+ cd printfck; make "INC_DIR=../../include" `cd ..; ls *.o`
+
+lint:
+ lint $(DEFS) $(SRCS) $(LINTFIX)
+
+clean:
+ rm -f *.o *core $(PROG) $(TESTPROG) junk
+ rm -rf printfck
+
+tidy: clean
+
+depend: $(MAKES)
+ (sed '1,/^# do not edit/!d' Makefile.in; \
+ set -e; for i in [a-z][a-z0-9]*.c; do \
+ $(CC) -E $(DEFS) $(INCL) $$i | sed -n -e '/^# *1 *"\([^"]*\)".*/{' \
+ -e 's//'`echo $$i|sed 's/c$$/o/'`': \1/' -e 'p' -e '}'; \
+ done) | grep -v '[.][o][:][ ][/]' >$$$$ && mv $$$$ Makefile.in
+ @make -f Makefile.in Makefile
+deliver_attr.o: deliver_attr.c
+deliver_attr.o: ../../include/sys_defs.h
+deliver_attr.o: ../../include/msg.h
+deliver_attr.o: ../../include/vstream.h
+deliver_attr.o: ../../include/vbuf.h
+deliver_attr.o: virtual.h
+deliver_attr.o: ../../include/htable.h
+deliver_attr.o: ../../include/vstring.h
+deliver_attr.o: ../../include/been_here.h
+deliver_attr.o: ../../include/tok822.h
+deliver_attr.o: ../../include/resolve_clnt.h
+deliver_attr.o: ../../include/deliver_request.h
+deliver_attr.o: ../../include/recipient_list.h
+deliver_attr.o: ../../include/maps.h
+deliver_attr.o: ../../include/dict.h
+deliver_attr.o: ../../include/argv.h
+mailbox.o: mailbox.c
+mailbox.o: ../../include/sys_defs.h
+mailbox.o: ../../include/msg.h
+mailbox.o: ../../include/htable.h
+mailbox.o: ../../include/vstring.h
+mailbox.o: ../../include/vbuf.h
+mailbox.o: ../../include/vstream.h
+mailbox.o: ../../include/mymalloc.h
+mailbox.o: ../../include/stringops.h
+mailbox.o: ../../include/set_eugid.h
+mailbox.o: ../../include/mail_copy.h
+mailbox.o: ../../include/safe_open.h
+mailbox.o: ../../include/deliver_flock.h
+mailbox.o: ../../include/dot_lockfile.h
+mailbox.o: ../../include/defer.h
+mailbox.o: ../../include/bounce.h
+mailbox.o: ../../include/sent.h
+mailbox.o: ../../include/mypwd.h
+mailbox.o: ../../include/mail_params.h
+mailbox.o: ../../include/deliver_pass.h
+mailbox.o: ../../include/deliver_request.h
+mailbox.o: ../../include/recipient_list.h
+mailbox.o: ../../include/mail_proto.h
+mailbox.o: ../../include/iostuff.h
+mailbox.o: virtual.h
+mailbox.o: ../../include/been_here.h
+mailbox.o: ../../include/tok822.h
+mailbox.o: ../../include/resolve_clnt.h
+mailbox.o: ../../include/maps.h
+mailbox.o: ../../include/dict.h
+mailbox.o: ../../include/argv.h
+maildir.o: maildir.c
+maildir.o: ../../include/sys_defs.h
+maildir.o: ../../include/msg.h
+maildir.o: ../../include/mymalloc.h
+maildir.o: ../../include/stringops.h
+maildir.o: ../../include/vstring.h
+maildir.o: ../../include/vbuf.h
+maildir.o: ../../include/vstream.h
+maildir.o: ../../include/make_dirs.h
+maildir.o: ../../include/set_eugid.h
+maildir.o: ../../include/get_hostname.h
+maildir.o: ../../include/mail_copy.h
+maildir.o: ../../include/bounce.h
+maildir.o: ../../include/sent.h
+maildir.o: ../../include/mail_params.h
+maildir.o: virtual.h
+maildir.o: ../../include/htable.h
+maildir.o: ../../include/been_here.h
+maildir.o: ../../include/tok822.h
+maildir.o: ../../include/resolve_clnt.h
+maildir.o: ../../include/deliver_request.h
+maildir.o: ../../include/recipient_list.h
+maildir.o: ../../include/maps.h
+maildir.o: ../../include/dict.h
+maildir.o: ../../include/argv.h
+recipient.o: recipient.c
+recipient.o: ../../include/sys_defs.h
+recipient.o: ../../include/msg.h
+recipient.o: ../../include/mymalloc.h
+recipient.o: ../../include/htable.h
+recipient.o: ../../include/split_at.h
+recipient.o: ../../include/stringops.h
+recipient.o: ../../include/vstring.h
+recipient.o: ../../include/vbuf.h
+recipient.o: ../../include/dict.h
+recipient.o: ../../include/vstream.h
+recipient.o: ../../include/argv.h
+recipient.o: ../../include/bounce.h
+recipient.o: ../../include/mail_params.h
+recipient.o: ../../include/split_addr.h
+recipient.o: ../../include/ext_prop.h
+recipient.o: virtual.h
+recipient.o: ../../include/been_here.h
+recipient.o: ../../include/tok822.h
+recipient.o: ../../include/resolve_clnt.h
+recipient.o: ../../include/deliver_request.h
+recipient.o: ../../include/recipient_list.h
+recipient.o: ../../include/maps.h
+unknown.o: unknown.c
+unknown.o: ../../include/sys_defs.h
+unknown.o: ../../include/msg.h
+unknown.o: ../../include/stringops.h
+unknown.o: ../../include/vstring.h
+unknown.o: ../../include/vbuf.h
+unknown.o: ../../include/mymalloc.h
+unknown.o: ../../include/mail_params.h
+unknown.o: ../../include/mail_proto.h
+unknown.o: ../../include/vstream.h
+unknown.o: ../../include/iostuff.h
+unknown.o: ../../include/bounce.h
+unknown.o: virtual.h
+unknown.o: ../../include/htable.h
+unknown.o: ../../include/been_here.h
+unknown.o: ../../include/tok822.h
+unknown.o: ../../include/resolve_clnt.h
+unknown.o: ../../include/deliver_request.h
+unknown.o: ../../include/recipient_list.h
+unknown.o: ../../include/maps.h
+unknown.o: ../../include/dict.h
+unknown.o: ../../include/argv.h
+virtual.o: virtual.c
+virtual.o: ../../include/sys_defs.h
+virtual.o: ../../include/msg.h
+virtual.o: ../../include/mymalloc.h
+virtual.o: ../../include/htable.h
+virtual.o: ../../include/vstring.h
+virtual.o: ../../include/vbuf.h
+virtual.o: ../../include/vstream.h
+virtual.o: ../../include/iostuff.h
+virtual.o: ../../include/name_mask.h
+virtual.o: ../../include/set_eugid.h
+virtual.o: ../../include/dict.h
+virtual.o: ../../include/argv.h
+virtual.o: ../../include/mail_queue.h
+virtual.o: ../../include/recipient_list.h
+virtual.o: ../../include/deliver_request.h
+virtual.o: ../../include/deliver_completed.h
+virtual.o: ../../include/mail_params.h
+virtual.o: ../../include/mail_addr.h
+virtual.o: ../../include/mail_conf.h
+virtual.o: ../../include/ext_prop.h
+virtual.o: ../../include/mail_server.h
+virtual.o: virtual.h
+virtual.o: ../../include/been_here.h
+virtual.o: ../../include/tok822.h
+virtual.o: ../../include/resolve_clnt.h
+virtual.o: ../../include/maps.h
+deliver_attr.o: deliver_attr.c
+deliver_attr.o: ../../include/sys_defs.h
+deliver_attr.o: ../../include/msg.h
+deliver_attr.o: ../../include/vstream.h
+deliver_attr.o: ../../include/vbuf.h
+deliver_attr.o: virtual.h
+deliver_attr.o: ../../include/vstring.h
+deliver_attr.o: ../../include/deliver_request.h
+deliver_attr.o: ../../include/recipient_list.h
+deliver_attr.o: ../../include/maps.h
+deliver_attr.o: ../../include/dict.h
+deliver_attr.o: ../../include/argv.h
+deliver_attr.o: ../../include/mbox_conf.h
+mailbox.o: mailbox.c
+mailbox.o: ../../include/sys_defs.h
+mailbox.o: ../../include/msg.h
+mailbox.o: ../../include/vstring.h
+mailbox.o: ../../include/vbuf.h
+mailbox.o: ../../include/vstream.h
+mailbox.o: ../../include/mymalloc.h
+mailbox.o: ../../include/stringops.h
+mailbox.o: ../../include/set_eugid.h
+mailbox.o: ../../include/mail_copy.h
+mailbox.o: ../../include/mbox_open.h
+mailbox.o: ../../include/safe_open.h
+mailbox.o: ../../include/defer.h
+mailbox.o: ../../include/bounce.h
+mailbox.o: ../../include/sent.h
+mailbox.o: ../../include/mypwd.h
+mailbox.o: ../../include/mail_params.h
+mailbox.o: virtual.h
+mailbox.o: ../../include/deliver_request.h
+mailbox.o: ../../include/recipient_list.h
+mailbox.o: ../../include/maps.h
+mailbox.o: ../../include/dict.h
+mailbox.o: ../../include/argv.h
+mailbox.o: ../../include/mbox_conf.h
+maildir.o: maildir.c
+maildir.o: ../../include/sys_defs.h
+maildir.o: ../../include/msg.h
+maildir.o: ../../include/mymalloc.h
+maildir.o: ../../include/stringops.h
+maildir.o: ../../include/vstring.h
+maildir.o: ../../include/vbuf.h
+maildir.o: ../../include/vstream.h
+maildir.o: ../../include/make_dirs.h
+maildir.o: ../../include/set_eugid.h
+maildir.o: ../../include/get_hostname.h
+maildir.o: ../../include/sane_fsops.h
+maildir.o: ../../include/mail_copy.h
+maildir.o: ../../include/bounce.h
+maildir.o: ../../include/sent.h
+maildir.o: ../../include/mail_params.h
+maildir.o: virtual.h
+maildir.o: ../../include/deliver_request.h
+maildir.o: ../../include/recipient_list.h
+maildir.o: ../../include/maps.h
+maildir.o: ../../include/dict.h
+maildir.o: ../../include/argv.h
+maildir.o: ../../include/mbox_conf.h
+recipient.o: recipient.c
+recipient.o: ../../include/sys_defs.h
+recipient.o: ../../include/msg.h
+recipient.o: ../../include/mymalloc.h
+recipient.o: ../../include/htable.h
+recipient.o: ../../include/split_at.h
+recipient.o: ../../include/stringops.h
+recipient.o: ../../include/vstring.h
+recipient.o: ../../include/vbuf.h
+recipient.o: ../../include/dict.h
+recipient.o: ../../include/vstream.h
+recipient.o: ../../include/argv.h
+recipient.o: ../../include/bounce.h
+recipient.o: ../../include/mail_params.h
+recipient.o: ../../include/split_addr.h
+recipient.o: ../../include/ext_prop.h
+recipient.o: virtual.h
+recipient.o: ../../include/deliver_request.h
+recipient.o: ../../include/recipient_list.h
+recipient.o: ../../include/maps.h
+recipient.o: ../../include/mbox_conf.h
+unknown.o: unknown.c
+unknown.o: ../../include/sys_defs.h
+unknown.o: ../../include/msg.h
+unknown.o: ../../include/stringops.h
+unknown.o: ../../include/vstring.h
+unknown.o: ../../include/vbuf.h
+unknown.o: ../../include/mymalloc.h
+unknown.o: ../../include/mail_params.h
+unknown.o: ../../include/mail_proto.h
+unknown.o: ../../include/vstream.h
+unknown.o: ../../include/iostuff.h
+unknown.o: ../../include/bounce.h
+unknown.o: virtual.h
+unknown.o: ../../include/deliver_request.h
+unknown.o: ../../include/recipient_list.h
+unknown.o: ../../include/maps.h
+unknown.o: ../../include/dict.h
+unknown.o: ../../include/argv.h
+unknown.o: ../../include/mbox_conf.h
+virtual.o: virtual.c
+virtual.o: ../../include/sys_defs.h
+virtual.o: ../../include/msg.h
+virtual.o: ../../include/mymalloc.h
+virtual.o: ../../include/htable.h
+virtual.o: ../../include/vstring.h
+virtual.o: ../../include/vbuf.h
+virtual.o: ../../include/vstream.h
+virtual.o: ../../include/iostuff.h
+virtual.o: ../../include/name_mask.h
+virtual.o: ../../include/set_eugid.h
+virtual.o: ../../include/dict.h
+virtual.o: ../../include/argv.h
+virtual.o: ../../include/mail_queue.h
+virtual.o: ../../include/recipient_list.h
+virtual.o: ../../include/deliver_request.h
+virtual.o: ../../include/deliver_completed.h
+virtual.o: ../../include/mail_params.h
+virtual.o: ../../include/mail_addr.h
+virtual.o: ../../include/mail_conf.h
+virtual.o: ../../include/mail_server.h
+virtual.o: virtual.h
+virtual.o: ../../include/maps.h
+virtual.o: ../../include/mbox_conf.h
+deliver_attr.o: deliver_attr.c
+deliver_attr.o: ../../include/sys_defs.h
+deliver_attr.o: ../../include/msg.h
+deliver_attr.o: ../../include/vstream.h
+deliver_attr.o: ../../include/vbuf.h
+deliver_attr.o: virtual.h
+deliver_attr.o: ../../include/vstring.h
+deliver_attr.o: ../../include/deliver_request.h
+deliver_attr.o: ../../include/recipient_list.h
+deliver_attr.o: ../../include/maps.h
+deliver_attr.o: ../../include/dict.h
+deliver_attr.o: ../../include/argv.h
+deliver_attr.o: ../../include/mbox_conf.h
+mailbox.o: mailbox.c
+mailbox.o: ../../include/sys_defs.h
+mailbox.o: ../../include/msg.h
+mailbox.o: ../../include/vstring.h
+mailbox.o: ../../include/vbuf.h
+mailbox.o: ../../include/vstream.h
+mailbox.o: ../../include/mymalloc.h
+mailbox.o: ../../include/stringops.h
+mailbox.o: ../../include/set_eugid.h
+mailbox.o: ../../include/mail_copy.h
+mailbox.o: ../../include/mbox_open.h
+mailbox.o: ../../include/safe_open.h
+mailbox.o: ../../include/defer.h
+mailbox.o: ../../include/bounce.h
+mailbox.o: ../../include/sent.h
+mailbox.o: ../../include/mypwd.h
+mailbox.o: ../../include/mail_params.h
+mailbox.o: virtual.h
+mailbox.o: ../../include/deliver_request.h
+mailbox.o: ../../include/recipient_list.h
+mailbox.o: ../../include/maps.h
+mailbox.o: ../../include/dict.h
+mailbox.o: ../../include/argv.h
+mailbox.o: ../../include/mbox_conf.h
+maildir.o: maildir.c
+maildir.o: ../../include/sys_defs.h
+maildir.o: ../../include/msg.h
+maildir.o: ../../include/mymalloc.h
+maildir.o: ../../include/stringops.h
+maildir.o: ../../include/vstring.h
+maildir.o: ../../include/vbuf.h
+maildir.o: ../../include/vstream.h
+maildir.o: ../../include/make_dirs.h
+maildir.o: ../../include/set_eugid.h
+maildir.o: ../../include/get_hostname.h
+maildir.o: ../../include/sane_fsops.h
+maildir.o: ../../include/mail_copy.h
+maildir.o: ../../include/bounce.h
+maildir.o: ../../include/sent.h
+maildir.o: ../../include/mail_params.h
+maildir.o: virtual.h
+maildir.o: ../../include/deliver_request.h
+maildir.o: ../../include/recipient_list.h
+maildir.o: ../../include/maps.h
+maildir.o: ../../include/dict.h
+maildir.o: ../../include/argv.h
+maildir.o: ../../include/mbox_conf.h
+recipient.o: recipient.c
+recipient.o: ../../include/sys_defs.h
+recipient.o: ../../include/msg.h
+recipient.o: ../../include/mymalloc.h
+recipient.o: ../../include/stringops.h
+recipient.o: ../../include/vstring.h
+recipient.o: ../../include/vbuf.h
+recipient.o: ../../include/bounce.h
+recipient.o: virtual.h
+recipient.o: ../../include/vstream.h
+recipient.o: ../../include/deliver_request.h
+recipient.o: ../../include/recipient_list.h
+recipient.o: ../../include/maps.h
+recipient.o: ../../include/dict.h
+recipient.o: ../../include/argv.h
+recipient.o: ../../include/mbox_conf.h
+unknown.o: unknown.c
+unknown.o: ../../include/sys_defs.h
+unknown.o: ../../include/msg.h
+unknown.o: ../../include/stringops.h
+unknown.o: ../../include/vstring.h
+unknown.o: ../../include/vbuf.h
+unknown.o: ../../include/mymalloc.h
+unknown.o: ../../include/mail_params.h
+unknown.o: ../../include/mail_proto.h
+unknown.o: ../../include/vstream.h
+unknown.o: ../../include/iostuff.h
+unknown.o: ../../include/bounce.h
+unknown.o: virtual.h
+unknown.o: ../../include/deliver_request.h
+unknown.o: ../../include/recipient_list.h
+unknown.o: ../../include/maps.h
+unknown.o: ../../include/dict.h
+unknown.o: ../../include/argv.h
+unknown.o: ../../include/mbox_conf.h
+virtual.o: virtual.c
+virtual.o: ../../include/sys_defs.h
+virtual.o: ../../include/msg.h
+virtual.o: ../../include/mymalloc.h
+virtual.o: ../../include/htable.h
+virtual.o: ../../include/vstring.h
+virtual.o: ../../include/vbuf.h
+virtual.o: ../../include/vstream.h
+virtual.o: ../../include/iostuff.h
+virtual.o: ../../include/name_mask.h
+virtual.o: ../../include/set_eugid.h
+virtual.o: ../../include/dict.h
+virtual.o: ../../include/argv.h
+virtual.o: ../../include/mail_queue.h
+virtual.o: ../../include/recipient_list.h
+virtual.o: ../../include/deliver_request.h
+virtual.o: ../../include/deliver_completed.h
+virtual.o: ../../include/mail_params.h
+virtual.o: ../../include/mail_addr.h
+virtual.o: ../../include/mail_conf.h
+virtual.o: ../../include/mail_server.h
+virtual.o: virtual.h
+virtual.o: ../../include/maps.h
+virtual.o: ../../include/mbox_conf.h
--- /dev/null
+/*++
+/* NAME
+/* deliver_attr 3
+/* SUMMARY
+/* initialize message delivery attributes
+/* SYNOPSIS
+/* #include "virtual.h"
+/*
+/* void deliver_attr_init(attrp)
+/* DELIVER_ATTR *attrp;
+/*
+/* void deliver_attr_dump(attrp)
+/* DELIVER_ATTR *attrp;
+/* DESCRIPTION
+/* deliver_attr_init() initializes a structure with message delivery
+/* attributes to a known initial state (all zeros).
+/*
+/* deliver_attr_dump() logs the contents of the given attribute list.
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* IBM T.J. Watson Research
+/* P.O. Box 704
+/* Yorktown Heights, NY 10598, USA
+/*--*/
+
+/* System library. */
+
+#include <sys_defs.h>
+
+/* Utility library. */
+
+#include <msg.h>
+#include <vstream.h>
+
+/* Application-specific. */
+
+#include "virtual.h"
+
+/* deliver_attr_init - set message delivery attributes to all-zero state */
+
+void deliver_attr_init(DELIVER_ATTR *attrp)
+{
+ attrp->level = 0;
+ attrp->fp = 0;
+ attrp->queue_name = 0;
+ attrp->queue_id = 0;
+ attrp->offset = 0;
+ attrp->sender = 0;
+ attrp->recipient = 0;
+ attrp->user = 0;
+ attrp->delivered = 0;
+ attrp->relay = 0;
+}
+
+/* deliver_attr_dump - log message delivery attributes */
+
+void deliver_attr_dump(DELIVER_ATTR *attrp)
+{
+ msg_info("level: %d", attrp->level);
+ msg_info("path: %s", VSTREAM_PATH(attrp->fp));
+ msg_info("fp: 0x%lx", (long) attrp->fp);
+ msg_info("queue_name: %s", attrp->queue_name ? attrp->queue_name : "null");
+ msg_info("queue_id: %s", attrp->queue_id ? attrp->queue_id : "null");
+ msg_info("offset: %ld", attrp->offset);
+ msg_info("sender: %s", attrp->sender ? attrp->sender : "null");
+ msg_info("recipient: %s", attrp->recipient ? attrp->recipient : "null");
+ msg_info("user: %s", attrp->user ? attrp->user : "null");
+ msg_info("delivered: %s", attrp->delivered ? attrp->delivered : "null");
+ msg_info("relay: %s", attrp->relay ? attrp->relay : "null");
+}
--- /dev/null
+/*++
+/* NAME
+/* mailbox 3
+/* SUMMARY
+/* mailbox delivery
+/* SYNOPSIS
+/* #include "virtual.h"
+/*
+/* int deliver_mailbox(state, usr_attr, statusp)
+/* LOCAL_STATE state;
+/* USER_ATTR usr_attr;
+/* int *statusp;
+/* DESCRIPTION
+/* deliver_mailbox() delivers to UNIX-style mailbox or to maildir.
+/*
+/* A zero result means that the named user was not found.
+/*
+/* Arguments:
+/* .IP state
+/* The attributes that specify the message, recipient and more.
+/* .IP usr_attr
+/* Attributes describing user rights and mailbox location.
+/* .IP statusp
+/* Delivery status: see below.
+/* DIAGNOSTICS
+/* The message delivery status is non-zero when delivery should be tried
+/* again.
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* IBM T.J. Watson Research
+/* P.O. Box 704
+/* Yorktown Heights, NY 10598, USA
+/*--*/
+
+/* System library. */
+
+#include <sys_defs.h>
+#include <sys/stat.h>
+#include <stdlib.h>
+#include <errno.h>
+
+/* Utility library. */
+
+#include <msg.h>
+#include <vstring.h>
+#include <vstream.h>
+#include <mymalloc.h>
+#include <stringops.h>
+#include <set_eugid.h>
+
+/* Global library. */
+
+#include <mail_copy.h>
+#include <mbox_open.h>
+#include <defer.h>
+#include <sent.h>
+#include <mail_params.h>
+
+#ifndef EDQUOT
+#define EDQUOT EFBIG
+#endif
+
+/* Application-specific. */
+
+#include "virtual.h"
+
+#define YES 1
+#define NO 0
+
+/* deliver_mailbox_file - deliver to recipient mailbox */
+
+static int deliver_mailbox_file(LOCAL_STATE state, USER_ATTR usr_attr)
+{
+ char *myname = "deliver_mailbox_file";
+ VSTRING *why;
+ MBOX *mp;
+ int status;
+ int copy_flags;
+ long end;
+ struct stat st;
+
+ /*
+ * Make verbose logging easier to understand.
+ */
+ state.level++;
+ if (msg_verbose)
+ MSG_LOG_STATE(myname, state);
+
+ /*
+ * Initialize. Assume the operation will fail. Set the delivered
+ * 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));
+ state.msg_attr.delivered = state.msg_attr.recipient;
+ status = -1;
+ why = vstring_alloc(100);
+
+ /*
+ * Lock the mailbox and open/create the mailbox file.
+ *
+ * Write the file as the recipient, so that file quota work.
+ */
+ copy_flags = MAIL_COPY_MBOX;
+
+ set_eugid(usr_attr.uid, usr_attr.gid);
+ mp = mbox_open(usr_attr.mailbox, O_APPEND | O_WRONLY | O_CREAT,
+ S_IRUSR | S_IWUSR, &st, -1, -1,
+ virtual_mbox_lock_mask, why);
+ if (mp != 0) {
+ if (S_ISREG(st.st_mode) == 0) {
+ vstream_fclose(mp->fp);
+ vstring_sprintf(why, "destination is not a regular file");
+ errno = 0;
+ } else {
+ end = vstream_fseek(mp->fp, (off_t) 0, SEEK_END);
+ status = mail_copy(COPY_ATTR(state.msg_attr), mp->fp,
+ copy_flags, "\n", why);
+ }
+ mbox_release(mp);
+ }
+ set_eugid(var_owner_uid, var_owner_gid);
+
+ /*
+ * As the mail system, bounce, defer delivery, or report success.
+ */
+ if (status != 0)
+ status = (errno == EDQUOT ? bounce_append : defer_append)
+ (BOUNCE_FLAG_KEEP, BOUNCE_ATTR(state.msg_attr),
+ "cannot access mailbox for %s. %s",
+ usr_attr.mailbox, state.msg_attr.recipient, vstring_str(why));
+ else
+ sent(SENT_ATTR(state.msg_attr), "mailbox");
+
+ vstring_free(why);
+ return (status);
+}
+
+/* deliver_mailbox - deliver to recipient mailbox */
+
+int deliver_mailbox(LOCAL_STATE state, USER_ATTR usr_attr, int *statusp)
+{
+ char *myname = "deliver_mailbox";
+ const char *result;
+ long n;
+
+ /*
+ * Make verbose logging easier to understand.
+ */
+ state.level++;
+ if (msg_verbose)
+ MSG_LOG_STATE(myname, state);
+
+ /*
+ * Sanity check.
+ */
+ if (*var_virt_mailbox_base != '/')
+ msg_fatal("do not specify relative pathname: %s = %s",
+ VAR_VIRT_MAILBOX_BASE, var_virt_mailbox_base);
+
+ /*
+ * Look up the mailbox location and rights of the recipient user.
+ */
+ result = maps_find(virtual_mailbox_maps, state.msg_attr.user, 0);
+ if (result == 0) {
+ if (dict_errno == 0)
+ return (NO);
+
+ *statusp = defer_append(BOUNCE_FLAG_KEEP, BOUNCE_ATTR(state.msg_attr),
+ "%s: lookup %s: %m",
+ virtual_mailbox_maps->title, state.msg_attr.user);
+ return (YES);
+ }
+ usr_attr.mailbox = concatenate(var_virt_mailbox_base, "/", result, (char *) 0);
+
+ if ((result = maps_find(virtual_uid_maps, state.msg_attr.user, 0)) == 0) {
+ myfree(usr_attr.mailbox);
+ *statusp = defer_append(BOUNCE_FLAG_KEEP, BOUNCE_ATTR(state.msg_attr),
+ "recipient %s: uid not found in %s",
+ state.msg_attr.user, virtual_uid_maps->title);
+ return (YES);
+ }
+ if ((n = atol(result)) < var_virt_minimum_uid) {
+ myfree(usr_attr.mailbox);
+ *statusp = defer_append(BOUNCE_FLAG_KEEP, BOUNCE_ATTR(state.msg_attr),
+ "recipient %s: bad uid %s in %s",
+ state.msg_attr.user, result, virtual_uid_maps->title);
+ return (YES);
+ }
+ usr_attr.uid = (uid_t) n;
+
+ if ((result = maps_find(virtual_gid_maps, state.msg_attr.user, 0)) == 0) {
+ myfree(usr_attr.mailbox);
+ *statusp = defer_append(BOUNCE_FLAG_KEEP, BOUNCE_ATTR(state.msg_attr),
+ "recipient %s: gid not found in %s",
+ state.msg_attr.user, virtual_gid_maps->title);
+ return (YES);
+ }
+ if ((n = atol(result)) <= 0) {
+ myfree(usr_attr.mailbox);
+ *statusp = defer_append(BOUNCE_FLAG_KEEP, BOUNCE_ATTR(state.msg_attr),
+ "recipient %s: bad gid %s in %s",
+ state.msg_attr.user, result, virtual_gid_maps->title);
+ return (YES);
+ }
+ usr_attr.gid = (gid_t) n;
+
+ if (msg_verbose)
+ msg_info("%s[%d]: set user_attr: %s, uid = %d, gid = %d",
+ myname, state.level,
+ usr_attr.mailbox, usr_attr.uid, usr_attr.gid);
+
+ /*
+ * Deliver to mailbox or to external command.
+ */
+#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);
+
+ /*
+ * Cleanup.
+ */
+ myfree(usr_attr.mailbox);
+ return (YES);
+}
--- /dev/null
+/*++
+/* NAME
+/* maildir 3
+/* SUMMARY
+/* delivery to maildir
+/* SYNOPSIS
+/* #include "virtual.h"
+/*
+/* int deliver_maildir(state, usr_attr)
+/* LOCAL_STATE state;
+/* USER_ATTR usr_attr;
+/* DESCRIPTION
+/* deliver_maildir() delivers a message to a qmail-style maildir.
+/*
+/* Arguments:
+/* .IP state
+/* The attributes that specify the message, recipient and more.
+/* .IP usr_attr
+/* Attributes describing user rights and environment information.
+/* DIAGNOSTICS
+/* deliver_maildir() always succeeds or it bounces the message.
+/* SEE ALSO
+/* bounce(3)
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* IBM T.J. Watson Research
+/* P.O. Box 704
+/* Yorktown Heights, NY 10598, USA
+/*--*/
+
+/* System library. */
+
+#include "sys_defs.h"
+#include <errno.h>
+
+/* Utility library. */
+
+#include <msg.h>
+#include <mymalloc.h>
+#include <stringops.h>
+#include <vstream.h>
+#include <vstring.h>
+#include <make_dirs.h>
+#include <set_eugid.h>
+#include <get_hostname.h>
+#include <sane_fsops.h>
+
+/* Global library. */
+
+#include <mail_copy.h>
+#include <bounce.h>
+#include <sent.h>
+#include <mail_params.h>
+
+/* Application-specific. */
+
+#include "virtual.h"
+
+/* deliver_maildir - delivery to maildir-style mailbox */
+
+int deliver_maildir(LOCAL_STATE state, USER_ATTR usr_attr)
+{
+ char *myname = "deliver_maildir";
+ char *newdir;
+ char *tmpdir;
+ char *curdir;
+ char *tmpfile;
+ char *newfile;
+ VSTRING *why;
+ VSTRING *buf;
+ VSTREAM *dst;
+ int status;
+ int copy_flags;
+ static int count;
+
+ /*
+ * Make verbose logging easier to understand.
+ */
+ state.level++;
+ if (msg_verbose)
+ MSG_LOG_STATE(myname, state);
+
+ /*
+ * Initialize. Assume the operation will fail. Set the delivered
+ * 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));
+ state.msg_attr.delivered = state.msg_attr.recipient;
+ status = -1;
+ buf = vstring_alloc(100);
+ why = vstring_alloc(100);
+
+ copy_flags = MAIL_COPY_TOFILE | MAIL_COPY_RETURN_PATH | MAIL_COPY_DELIVERED;
+
+ newdir = concatenate(usr_attr.mailbox, "new/", (char *) 0);
+ tmpdir = concatenate(usr_attr.mailbox, "tmp/", (char *) 0);
+ curdir = concatenate(usr_attr.mailbox, "cur/", (char *) 0);
+
+ /*
+ * Create and write the file as the recipient, so that file quota work.
+ * Create any missing directories on the fly. The file name is chosen
+ * according to ftp://koobera.math.uic.edu/www/proto/maildir.html:
+ *
+ * "A unique name has three pieces, separated by dots. On the left is the
+ * result of time(). On the right is the result of gethostname(). In the
+ * middle is something that doesn't repeat within one second on a single
+ * host. I fork a new process for each delivery, so I just use the
+ * process ID. If you're delivering several messages from one process,
+ * use starttime.pid_count.host, where starttime is the time that your
+ * process started, and count is the number of messages you've
+ * delivered."
+ */
+#define STR vstring_str
+
+ set_eugid(usr_attr.uid, usr_attr.gid);
+ vstring_sprintf(buf, "%ld.%d_%d.%s", (long) var_starttime,
+ var_pid, count++, get_hostname());
+ tmpfile = concatenate(tmpdir, STR(buf), (char *) 0);
+ newfile = concatenate(newdir, STR(buf), (char *) 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)) {
+ vstring_sprintf(why, "create %s: %m", tmpfile);
+ } else {
+ if (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)) {
+ vstring_sprintf(why, "link to %s: %m", newfile);
+ } else {
+ status = 0;
+ }
+ }
+ if (unlink(tmpfile) < 0)
+ msg_warn("remove %s: %m", tmpfile);
+ }
+ set_eugid(var_owner_uid, var_owner_gid);
+
+ if (status)
+ bounce_append(BOUNCE_FLAG_KEEP, BOUNCE_ATTR(state.msg_attr),
+ "maildir delivery failed: %s", vstring_str(why));
+ else
+ sent(SENT_ATTR(state.msg_attr), "maildir");
+ vstring_free(buf);
+ vstring_free(why);
+ myfree(newdir);
+ myfree(tmpdir);
+ myfree(curdir);
+ myfree(tmpfile);
+ myfree(newfile);
+ return (0);
+}
--- /dev/null
+/*++
+/* NAME
+/* recipient 3
+/* SUMMARY
+/* deliver to one local recipient
+/* SYNOPSIS
+/* #include "virtual.h"
+/*
+/* int deliver_recipient(state, usr_attr)
+/* LOCAL_STATE state;
+/* USER_ATTR *usr_attr;
+/* DESCRIPTION
+/* deliver_recipient() delivers a message to a local recipient.
+/*
+/* Arguments:
+/* .IP state
+/* The attributes that specify the message, sender, and more.
+/* .IP usr_attr
+/* Attributes describing user rights and mailbox location.
+/* DIAGNOSTICS
+/* deliver_recipient() returns non-zero when delivery should be
+/* tried again.
+/* SEE ALSO
+/* mailbox(3) delivery to UNIX-style mailbox
+/* maildir(3) delivery to qmail-style maildir
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* IBM T.J. Watson Research
+/* P.O. Box 704
+/* Yorktown Heights, NY 10598, USA
+/*--*/
+
+/* System library. */
+
+#include <sys_defs.h>
+
+/* Utility library. */
+
+#include <msg.h>
+#include <mymalloc.h>
+#include <stringops.h>
+
+/* Global library. */
+
+#include <bounce.h>
+
+/* Application-specific. */
+
+#include "virtual.h"
+
+/* deliver_recipient - deliver one local recipient */
+
+int deliver_recipient(LOCAL_STATE state, USER_ATTR usr_attr)
+{
+ char *myname = "deliver_recipient";
+ int rcpt_stat;
+
+ /*
+ * Make verbose logging easier to understand.
+ */
+ state.level++;
+ if (msg_verbose)
+ MSG_LOG_STATE(myname, state);
+
+ /*
+ * Set up the recipient-specific attributes. The recipient's lookup
+ * handle is the full address.
+ */
+ if (state.msg_attr.delivered == 0)
+ state.msg_attr.delivered = state.msg_attr.recipient;
+ state.msg_attr.user = mystrdup(state.msg_attr.recipient);
+ lowercase(state.msg_attr.user);
+
+ /*
+ * Deliver
+ */
+ if (msg_verbose)
+ deliver_attr_dump(&state.msg_attr);
+
+ if (deliver_mailbox(state, usr_attr, &rcpt_stat) == 0)
+ rcpt_stat = deliver_unknown(state);
+
+ /*
+ * Cleanup.
+ */
+ myfree(state.msg_attr.user);
+
+ return (rcpt_stat);
+}
--- /dev/null
+/*++
+/* NAME
+/* unknown 3
+/* SUMMARY
+/* delivery of unknown recipients
+/* SYNOPSIS
+/* #include "virtual.h"
+/*
+/* int deliver_unknown(state)
+/* LOCAL_STATE state;
+/* DESCRIPTION
+/* deliver_unknown() delivers a message for unknown recipients.
+/* .PP
+/* Arguments:
+/* .IP state
+/* Message delivery attributes (sender, recipient etc.).
+/* .IP usr_attr
+/* Attributes describing user rights and mailbox location.
+/* DIAGNOSTICS
+/* The result status is non-zero when delivery should be tried again.
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* IBM T.J. Watson Research
+/* P.O. Box 704
+/* Yorktown Heights, NY 10598, USA
+/*--*/
+
+/* System library. */
+
+#include <sys_defs.h>
+
+/* Utility library. */
+
+#include <msg.h>
+
+/* Global library. */
+
+#include <bounce.h>
+
+/* Application-specific. */
+
+#include "virtual.h"
+
+/* deliver_unknown - delivery for unknown recipients */
+
+int deliver_unknown(LOCAL_STATE state)
+{
+ char *myname = "deliver_unknown";
+
+ /*
+ * Make verbose logging easier to understand.
+ */
+ state.level++;
+ if (msg_verbose)
+ MSG_LOG_STATE(myname, state);
+
+ return (bounce_append(BOUNCE_FLAG_KEEP, BOUNCE_ATTR(state.msg_attr),
+ "unknown user: \"%s\"", state.msg_attr.user));
+
+}
--- /dev/null
+/*++
+/* NAME
+/* virtual 8
+/* SUMMARY
+/* Postfix virtual domain mail delivery agent
+/* SYNOPSIS
+/* \fBvirtual\fR [generic Postfix daemon options]
+/* DESCRIPTION
+/* This daemon is designed for ISP's offering virtual mail hosting
+/* services. Originally based on the local delivery agent, this agent
+/* locates user mailboxes via map lookups of the full recipient
+/* address, rather than hard-coded unix password file searches of
+/* the local part only.
+/*
+/* The \fBvirtual\fR daemon processes delivery requests from the
+/* Postfix queue manager to deliver mail to virtual local recipients.
+/* Each delivery request specifies a queue file, a sender address,
+/* a domain or host to deliver to, and one or more recipients.
+/* This program expects to be run from the \fBmaster\fR(8) process
+/* manager.
+/*
+/* The \fBvirtual\fR daemon updates queue files and marks recipients
+/* as finished, or it informs the queue manager that delivery should
+/* be tried again at a later time. Delivery problem reports are sent
+/* to the \fBbounce\fR(8) or \fBdefer\fR(8) daemon as appropriate.
+/* MAILBOX DELIVERY
+/* .ad
+/* .fi
+/* The \fBvirtual\fR delivery agent can deliver to UNIX-style mailbox
+/* file or to qmail-style maildir files. The pathname and delivery
+/* mailbox style are controlled by the $\fBvirtual_mailbox_base\fR
+/* and \fB$virtual_mailbox_maps\fR parameters (see below).
+/*
+/* In the case of UNIX-style mailbox delivery,
+/* the \fBlocal\fR daemon prepends a "\fBFrom \fIsender time_stamp\fR"
+/* envelope header to each message, prepends a \fBDelivered-To:\fR header
+/* with the envelope recipient address, prepends a \fBReturn-Path:\fR
+/* 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.
+/*
+/* In the case of \fBmaildir\fR delivery, the local daemon prepends
+/* a \fBDelivered-To:\fR header with the envelope recipient address
+/* and prepends a \fBReturn-Path:\fR header with the envelope sender
+/* address.
+/* DELIVERY RIGHTS
+/* .ad
+/* .fi
+/* Deliveries to mailboxes are made with the UID and GID that are listed
+/* for the recipient in the tables listed in the \fB$virtual_uid_maps\fR
+/* and \fB$virtual_gid_maps\fR, respectively.
+/*
+/* The \fBvirtual_minimum_uid\fR parameter specifies a lower bound on
+/* UID values that may be specified in \fB$virtual_uid_maps\fR. Mail
+/* will not be delivered when an invalid UID is found.
+/* STANDARDS
+/* RFC 822 (ARPA Internet Text Messages)
+/* DIAGNOSTICS
+/* 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.
+/* CONFIGURATION PARAMETERS
+/* .ad
+/* .fi
+/* The following \fBmain.cf\fR parameters are especially relevant to
+/* this program. See the Postfix \fBmain.cf\fR file for syntax details
+/* and for default values. Use the \fBpostfix reload\fR command after
+/* a configuration change.
+/* .SH Mailbox delivery
+/* .ad
+/* .fi
+/* .IP \fBvirtual_mailbox_base\fR
+/* Specifies a path that is prepended to all mailbox or maildir paths.
+/* This is a safety measure to ensure that an out of control map in
+/* \fBvirtual_mailbox_maps\fR doesn't litter the filesystem with mailboxes.
+/* While it could be set to "/", this setting isn't recommended.
+/* .IP \fBvirtual_mailbox_maps\fR
+/* Recipients are looked up in this map to determine the path to
+/* their mailbox or maildir. If the returned path ends in a slash
+/* ("/"), maildir-style delivery is carried out, otherwise the
+/* path is assumed to specify a mailbox file.
+/*
+/* Note that \fBvirtual_mailbox_base\fR is unconditionally prepended
+/* to this path.
+/* .IP \fBvirtual_minimum_uid\fR
+/* Specifies a minimum uid that will be accepted as a return from
+/* a \fBvirtual_uid_maps\fR lookup. Returned values less than this
+/* will be rejected, and the message will be deferred.
+/* .IP \fBvirtual_uid_maps\fR
+/* Recipients are looked up in this map to determine the UID to be
+/* used when writing to the target mailbox.
+/* .IP \fBvirtual_gid_maps\fR
+/* Recipients are looked up in this map to determine the GID to be
+/* used when writing to the target mailbox.
+/* .SH "Locking controls"
+/* .ad
+/* .fi
+/* .IP \fBmailbox_delivery_lock\fR
+/* How to lock UNIX-style mailboxes: one or more of \fBflock\fR,
+/* \fBfcntl\fR or \fBdotlock\fR.
+/* .IP \fBdeliver_lock_attempts\fR
+/* Limit the number of attempts to acquire an exclusive lock
+/* on a mailbox file.
+/* .IP \fBdeliver_lock_delay\fR
+/* Time in seconds between successive attempts to acquire
+/* an exclusive lock on a mailbox file.
+/* .IP \fBstale_lock_time\fR
+/* Limit the time after which a stale lockfile is removed.
+/* .SH "Resource controls"
+/* .ad
+/* .fi
+/* .IP \fBvirtual_destination_concurrency_limit\fR
+/* Limit the number of parallel deliveries to the same domain.
+/* The default limit is taken from the
+/* \fBdefault_destination_concurrency_limit\fR parameter.
+/* .IP \fBvirtual_destination_recipient_limit\fR
+/* Limit the number of recipients per message delivery.
+/* The default limit is taken from the
+/* \fBdefault_destination_recipient_limit\fR parameter.
+/* HISTORY
+/* .ad
+/* .fi
+/* This agent was originally based on the local delivery
+/* agent. Modifications mainly consisted of removing code that wasn't
+/* applicable or wasn't safe in this context (aliases, .forwards,
+/* program aliases).
+/*
+/* The \fBDelivered-To:\fR header appears in the \fBqmail\fR system
+/* by Daniel Bernstein.
+/*
+/* The \fImaildir\fR structure appears in the \fBqmail\fR system
+/* by Daniel Bernstein.
+/* SEE ALSO
+/* bounce(8) non-delivery status reports
+/* syslogd(8) system logging
+/* qmgr(8) queue manager
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* 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>
+
+/* 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_conf.h>
+#include <mail_params.h>
+
+/* Single server skeleton. */
+
+#include <mail_server.h>
+
+/* Application-specific. */
+
+#include "virtual.h"
+
+ /*
+ * Tunable parameters.
+ */
+char *var_mailbox_maps;
+char *var_uid_maps;
+char *var_gid_maps;
+int var_virt_minimum_uid;
+char *var_virt_mailbox_base;
+char *var_mailbox_lock;
+
+ /*
+ * 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)
+{
+ 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.
+ * While messages are being delivered and while aliases or forward files
+ * are being expanded, this attribute list is being changed constantly.
+ * For this reason, the list is passed on by value (except when it is
+ * being initialized :-), so that there is no need to undo attribute
+ * changes made by lower-level routines. The alias/include/forward
+ * expansion attribute list is part of a tree with self and parent
+ * references (see the EXPAND_ATTR definitions). The user-specific
+ * attributes are security sensitive, and are therefore kept separate.
+ * All this results in a noticeable level of clumsiness, but passing
+ * things around by value gives good protection against accidental change
+ * by subroutines.
+ */
+ 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.relay = service;
+ state.msg_attr.arrival_time = rqst->arrival_time;
+ 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.recipient = rcpt->address;
+ rcpt_stat = deliver_recipient(state, usr_attr);
+ if (rcpt_stat == 0)
+ deliver_completed(state.msg_attr.fp, rcpt->offset);
+ msg_stat |= rcpt_stat;
+ }
+
+ 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)
+{
+ if (dict_changed()) {
+ msg_info("table has changed -- exiting");
+ 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);
+
+ virtual_mailbox_maps =
+ maps_create(VAR_VIRT_MAILBOX_MAPS, var_mailbox_maps,
+ DICT_FLAG_LOCK);
+
+ virtual_uid_maps =
+ maps_create(VAR_VIRT_UID_MAPS, var_uid_maps, DICT_FLAG_LOCK);
+
+ virtual_gid_maps =
+ maps_create(VAR_VIRT_UID_MAPS, var_gid_maps, DICT_FLAG_LOCK);
+
+ virtual_mbox_lock_mask = mbox_lock_mask(var_mailbox_lock);
+}
+
+/* main - pass control to the single-threaded skeleton */
+
+int main(int argc, char **argv)
+{
+ static CONFIG_INT_TABLE int_table[] = {
+ VAR_VIRT_MINUID, DEF_VIRT_MINUID, &var_virt_minimum_uid, 1, 0,
+ 0,
+ };
+ static CONFIG_STR_TABLE str_table[] = {
+ VAR_VIRT_MAILBOX_MAPS, DEF_VIRT_MAILBOX_MAPS, &var_mailbox_maps, 0, 0,
+ VAR_VIRT_UID_MAPS, DEF_VIRT_UID_MAPS, &var_uid_maps, 0, 0,
+ VAR_VIRT_GID_MAPS, DEF_VIRT_GID_MAPS, &var_gid_maps, 0, 0,
+ VAR_VIRT_MAILBOX_BASE, DEF_VIRT_MAILBOX_BASE, &var_virt_mailbox_base, 0, 0,
+ VAR_MAILBOX_LOCK, DEF_MAILBOX_LOCK, &var_mailbox_lock, 1, 0,
+ 0,
+ };
+
+ single_server_main(argc, argv, local_service,
+ MAIL_SERVER_INT_TABLE, int_table,
+ MAIL_SERVER_STR_TABLE, str_table,
+ MAIL_SERVER_POST_INIT, post_init,
+ MAIL_SERVER_PRE_ACCEPT, pre_accept,
+ 0);
+}
--- /dev/null
+/*++
+/* NAME
+/* virtual 3h
+/* SUMMARY
+/* virtual mail delivery
+/* SYNOPSIS
+/* #include "virtual.h"
+/* DESCRIPTION
+/* .nf
+
+ /*
+ * System library.
+ */
+#include <unistd.h>
+
+ /*
+ * Utility library.
+ */
+#include <vstream.h>
+#include <vstring.h>
+
+ /*
+ * Global library.
+ */
+#include <deliver_request.h>
+#include <maps.h>
+#include <mbox_conf.h>
+
+ /*
+ * Mappings.
+ */
+extern MAPS *virtual_mailbox_maps;
+extern MAPS *virtual_uid_maps;
+extern MAPS *virtual_gid_maps;
+
+ /*
+ * User attributes: these control the privileges for delivery to external
+ * commands, external files, or mailboxes, and the initial environment of
+ * external commands.
+ */
+typedef struct USER_ATTR {
+ uid_t uid; /* file/command access */
+ gid_t gid; /* file/command access */
+ char *mailbox; /* mailbox file or directory */
+} USER_ATTR;
+
+ /*
+ * Critical macros. Not for obscurity, but to ensure consistency.
+ */
+#define RESET_USER_ATTR(usr_attr, level) { \
+ usr_attr.uid = 0; usr_attr.gid = 0; usr_attr.mailbox = 0; \
+ if (msg_verbose) \
+ msg_info("%s[%d]: reset user_attr", myname, level); \
+ }
+
+ /*
+ * The delivery attributes are inherited from files, from aliases, and from
+ * whatnot. Some of the information is changed on the fly. DELIVER_ATTR
+ * structres are therefore passed by value, so there is no need to undo
+ * changes.
+ */
+typedef struct DELIVER_ATTR {
+ int level; /* recursion level */
+ VSTREAM *fp; /* open queue file */
+ char *queue_name; /* mail queue id */
+ char *queue_id; /* mail queue id */
+ long offset; /* data offset */
+ char *sender; /* taken from envelope */
+ char *recipient; /* taken from resolver */
+ char *user; /* recipient lookup handle */
+ char *delivered; /* for loop detection */
+ char *relay; /* relay host */
+ long arrival_time; /* arrival time */
+} DELIVER_ATTR;
+
+extern void deliver_attr_init(DELIVER_ATTR *);
+extern void deliver_attr_dump(DELIVER_ATTR *);
+
+#define FEATURE_NODELIVERED (1<<0) /* no delivered-to */
+
+ /*
+ * Rather than schlepping around dozens of arguments, here is one that has
+ * all. Well, almost. The user attributes are just a bit too sensitive, so
+ * they are passed around separately.
+ */
+typedef struct LOCAL_STATE {
+ int level; /* nesting level, for logging */
+ DELIVER_ATTR msg_attr; /* message attributes */
+ DELIVER_REQUEST *request; /* as from queue manager */
+} LOCAL_STATE;
+
+ /*
+ * Bundle up some often-user attributes.
+ */
+#define BOUNCE_ATTR(attr) attr.queue_id, attr.recipient, attr.relay, \
+ attr.arrival_time
+#define SENT_ATTR(attr) attr.queue_id, attr.recipient, attr.relay, \
+ attr.arrival_time
+#define COPY_ATTR(attr) attr.sender, attr.delivered, attr.fp
+
+#define MSG_LOG_STATE(m, p) \
+ msg_info("%s[%d]: recip %s deliver %s", m, \
+ p.level, \
+ p.msg_attr.recipient ? p.msg_attr.recipient : "", \
+ p.msg_attr.delivered ? p.msg_attr.delivered : "")
+
+ /*
+ * "inner" nodes of the delivery graph.
+ */
+extern int deliver_recipient(LOCAL_STATE, USER_ATTR);
+
+ /*
+ * "leaf" nodes of the delivery graph.
+ */
+extern int deliver_mailbox(LOCAL_STATE, USER_ATTR, int *);
+extern int deliver_file(LOCAL_STATE, USER_ATTR, char *);
+extern int deliver_maildir(LOCAL_STATE, USER_ATTR);
+extern int deliver_unknown(LOCAL_STATE);
+
+ /*
+ * Mailbox lock protocol.
+ */
+extern int virtual_mbox_lock_mask;
+
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* IBM T.J. Watson Research
+/* P.O. Box 704
+/* Yorktown Heights, NY 10598, USA
+/*--*/