diff --git a/postfix/.indent.pro b/postfix/.indent.pro
new file mode 100644
index 000000000..e59d396ad
--- /dev/null
+++ b/postfix/.indent.pro
@@ -0,0 +1,89 @@
+-TALIAS_TOKEN
+-TARGV
+-TBH_TABLE
+-TBINHASH
+-TBINHASH_INFO
+-TBOUNCE_STAT
+-TCLEANUP_STATE
+-TCLIENT_LIST
+-TCONFIG_BOOL_FN_TABLE
+-TCONFIG_BOOL_TABLE
+-TCONFIG_INT_FN_TABLE
+-TCONFIG_INT_TABLE
+-TCONFIG_STR_FN_TABLE
+-TCONFIG_STR_TABLE
+-TDELIVER_ATTR
+-TDELIVER_REQUEST
+-TDICT
+-TDICT_DB
+-TDICT_DBM
+-TDICT_ENV
+-TDICT_HT
+-TDICT_LDAP
+-TDICT_NI
+-TDICT_NIS
+-TDICT_NISPLUS
+-TDICT_NODE
+-TDICT_OPEN_INFO
+-TDNS_FIXED
+-TDNS_REPLY
+-TDNS_RR
+-TDOMAIN_LIST
+-TEXPAND_ATTR
+-TFILE
+-TFORWARD_INFO
+-THEADER_OPTS
+-THTABLE
+-THTABLE_INFO
+-TINET_ADDR_LIST
+-TINT_TABLE
+-TLOCAL_STATE
+-TMAC_HEAD
+-TMAC_PARSE
+-TMAIL_PRINT
+-TMAIL_SCAN
+-TMAPS
+-TMASTER_PROC
+-TMASTER_SERV
+-TMASTER_STATUS
+-TMBLOCK
+-TMKMAP
+-TMKMAP_OPEN_INFO
+-TMULTI_SERVER
+-TMVECT
+-TNAMADR_LIST
+-TNAME_MASK
+-TPEER_NAME
+-TPICKUP_INFO
+-TPIPE_ATTR
+-TPIPE_PARAMS
+-TQMGR_ENTRY
+-TQMGR_MESSAGE
+-TQMGR_QUEUE
+-TQMGR_RCPT_LIST
+-TQMGR_RECIPIENT
+-TQMGR_SCAN
+-TQMGR_TRANSPORT
+-TRECIPIENT
+-TRECIPIENT_LIST
+-TREC_TYPE_NAME
+-TRESOLVE_REPLY
+-TSCAN_DIR
+-TSINGLE_SERVER
+-TSMTPD_STATE
+-TSMTPD_TOKEN
+-TSMTP_ADDR
+-TSMTP_CMD
+-TSMTP_RESP
+-TSMTP_SESSION
+-TSMTP_STATE
+-TSOCKADDR_SIZE
+-TSTRING_TABLE
+-TSYS_EXITS_TABLE
+-TTOK822
+-TTRIGGER_SERVER
+-TUSER_ATTR
+-TVBUF
+-TVSTREAM
+-TVSTRING
+-TWAIT_STATUS_T
diff --git a/postfix/.printfck b/postfix/.printfck
new file mode 100644
index 000000000..9ed900cb0
--- /dev/null
+++ b/postfix/.printfck
@@ -0,0 +1,24 @@
+been_here_xt 2 0
+bounce_append 5 0
+cleanup_out_format 1 0
+defer_append 5 0
+mail_command 1 0
+mail_print 1 0
+msg_error 0 0
+msg_fatal 0 0
+msg_info 0 0
+msg_panic 0 0
+msg_warn 0 0
+opened 3 0
+qmgr_message_bounce 2 0
+rec_fprintf 2 0
+sent 4 0
+smtp_cmd 1 0
+smtp_mesg_fail 2 0
+smtp_printf 1 0
+smtp_rcpt_fail 3 0
+smtp_site_fail 2 0
+udp_syslog 1 0
+vstream_fprintf 1 0
+vstream_printf 0 0
+vstring_sprintf 1 0
diff --git a/postfix/0README b/postfix/0README
new file mode 100644
index 000000000..0ba0a5255
--- /dev/null
+++ b/postfix/0README
@@ -0,0 +1,148 @@
+Purpose of this document
+========================
+
+This document provides a road map of the Postfix mail system source
+code distribution. I suggest that you take a few minutes to read
+it, and then proceed with the installation instructions.
+
+Introduction
+============
+
+This is the first public release of the Postfix mail system. Thank
+you for your interest in this project. Send me a postcard if you
+like it. My postal address is below.
+
+You must read the LICENSE file, if you didn't do so already. A copy
+of the LICENSE must be distributed with every original, modified,
+complete, source, or binary copy of this software or parts thereof.
+I suggest that you keep a copy of the file in /etc/postfix/LICENSE.
+
+Purpose of the Postfix mail system
+==================================
+
+Postfix aims to be an alternative to the widely-used sendmail
+program. Sendmail is responsible for 70% of all e-mail delivered
+on the Internet. With an estimated 100 million users, that's an
+estimated 10 billion (10^10) messages daily. A stunning number.
+
+Although IBM supported the Postfix development, it abstains from
+control over its evolution. The goal is to have Postfix installed
+on as many systems as possible. To this end, the software is given
+away with no strings attached to it, so that it can evolve with
+input from and under control by its users.
+
+In other words, IBM releases Postfix only once. I will be around
+to guide its development for a limited time.
+
+On-line resources devoted to the Postfix mail system
+====================================================
+
+Web sites:
+
+ http://www.ibm.com/alphaworks/ the original distribution site
+ http://www.postfix.org/ post-release information
+
+Mail addresses (please do NOT send mail to my address at work):
+
+ postfix-XXX@postfix.org Postfix mailing lists
+ wietse@porcupine.org the original author
+
+In order to subscribe to a mailing list, see http://www.postfix.org/.
+
+Acknowledgements
+================
+
+This release could not have happened without the input from a team
+of competent alpha testers. Their names appear in numerous places
+in the HISTORY file. I appreciate the input from my colleagues at
+the IBM Global Security Analysis Laboratory: Paul Karger, Dave
+Safford, Douglas Schales, and Leendert van Doorn. I also appreciate
+the support by Charles Palmer under whose leadership I began this
+project, and who had the privilege to name the software, twice.
+
+If you wish to express your appreciation for the Postfix software,
+you are welcome to send a postcard to:
+
+ Wietse Venema
+ IBM T.J Watson Research Center
+ P.O. Box 704,
+ Yorktown Heights, NY 10598
+ USA
+
+Roadmap of the Postfix source distribution
+==========================================
+
+Point your browser at html/index.html for Postfix documentation,
+for manual pages, and for the unavoidable Postfix FAQ. Expect to
+see updated versions on-line at http://www.postfix.org/
+
+Point your MANPATH environment variable at the `man' directory (use
+an absolute path) for UNIX-style on-line manual pages. These pages
+are also available through the HTML interface, which allows you to
+navigate faster.
+
+The COMPATIBILITY file lists features that Postfix does or does
+not yet implement, and how well it works with other software.
+
+The HISTORY file gives a detailed log of changes to the software.
+
+The INSTALL file provides a step-by-step guide for building and
+installing Postfix on many popular UNIX platforms.
+
+The PORTING file discusses how to go about porting Postfix to other
+UNIX platforms. Some people are looking into a port to Windows NT.
+We'll see. This software uses every trick in the book that I learned
+about UNIX.
+
+The TODO file lists things that still need to be done. If you want
+to set your teeth into one of those problems, drop me a note at
+wietse@porcupine.org to avoid duplication of effort.
+
+Documentation:
+
+ html/ HTML format
+ man/ UNIX on-line manual page format
+
+Library routines:
+
+ dns/ DNS client library
+ global/ Postfix-specific support routines
+ util/ General-purpose support routines
+
+Command-line utilities:
+
+ postalias/ Alias database management
+ postcat/ List Postfix queue file
+ postconf/ Configuration utility
+ postfix/ Postfix administrative interface
+ postkick/ Postfix IPC for shell scripts
+ postlock/ Postfix locking for shell scripts
+ postlog/ Postfix logging for shell scripts
+ postmap/ Postfix lookup table management
+ sendmail/ Sendmail compatibility interface
+
+Postfix daemons:
+
+ bounce/ Bounce or defer mail
+ cleanup/ Canonicalize and enqueue mail
+ local/ Local delivery
+ master/ Postfix resident superserver
+ pickup/ Local pickup
+ pipe/ Pipe delivery
+ qmgr/ Queue manager
+ showq/ List Postfix queue status
+ smtp/ SMTP client
+ smtpd/ SMTP server
+ trivial-rewrite/ Address rewriting and resolving
+
+Test programs:
+
+ fsstone/ Measure file system overhead
+ smtpstone/ SMTP server torture test
+
+Miscellaneous:
+
+ bin/ Installed programs
+ conf/ Sample configuration files
+ include/ Installed include files
+ lib/ Installed object libraries
diff --git a/postfix/COMPATIBILITY b/postfix/COMPATIBILITY
new file mode 100644
index 000000000..1cb895c60
--- /dev/null
+++ b/postfix/COMPATIBILITY
@@ -0,0 +1,55 @@
+.forward yes (empty files; can enable/disable mail to /file or |command)
+/usr/mail yes (compile time option)
+/usr/spool/mail yes (compile time option)
+/var/mail yes (compile time option)
+/var/spool/mail yes (compile time option)
+:include: yes (mail to /file and |command is off by default)
+aliases yes (can enable/disable mail to /file or |command)
+bare newlines yes (but will send CRLF)
+blacklisting yes (client name/addr; helo hostname; mail from; rcpt to)
+content filter no
+db tables yes (compile time option)
+dbm tables yes (compile time option)
+delivered-to yes
+dsn not yet
+errors-to: yes
+esmtp yes
+etrn support yes (flushes entire queue)
+fcntl locking yes (compile time)
+flock locking yes (compile time)
+home mailbox yes
+ident lookup no
+ldap tables yes (contributed)
+luser relay not yet
+m4 config no
+mail to command yes (configurable for .forward, aliases, :include:)
+mail to file yes (configurable for .forward, aliases, :include:)
+maildir yes (with procmail)
+mailertable yes (it's called transport)
+mailq yes
+majordomo yes (edit approve script to delete /delivered-to/i)
+mime conversion not yet; postfix uses just-send-eight
+missing <> yes (most common address forms)
+netinfo tables yes (contributed)
+newaliases yes (main alias database only)
+nis tables yes
+nis+ tables not yet
+pipeline option yes (server and client)
+pop/imap yes (with third-party daemons that use /var[/spool]/mail)
+rbl support yes
+return-receipt: not yet
+sendmail -q yes
+sendmail -qRxxx no
+sendmail -qSxxx no
+sendmail -qtime ignored
+sendmail -v no
+sendmail.cf no (uses table-driven address rewriting)
+size option yes, server and client
+smarthost yes
+tcp wrapper no (use built-in blacklist facility)
+user+extension yes (also: .forward+extension)
+user-extension yes (also: .forward-extension)
+user.lock yes (compile time)
+uucp support yes (sends user@domain recipients)
+virtual domains yes
+year 2000 safe yes
diff --git a/postfix/HISTORY b/postfix/HISTORY
new file mode 100644
index 000000000..468f02cc5
--- /dev/null
+++ b/postfix/HISTORY
@@ -0,0 +1,2001 @@
+In addition to the names listed below, the following people provided
+useful inputs on many occasions: Paul D. Robertson, Simon J. Mudd.
+Apologies for any names omitted.
+
+19980105
+
+ The compiled-in default value for resolve_smtp_sender was
+ wrong (from the days that it was a boolean), causing smtpd
+ to dump core when the variable was not set in main.cf.
+
+ The INSTALL instructions now have separate sections for
+ the three basic ways of running vmailer.
+
+ The INSTALL instructions now have discusses how to deal
+ with chrooted processes.
+
+ Ported to RedHat 5.0. My, these people have re-organized
+ their include files quite a bit, haven't they.
+
+19980106
+
+ On RedHat Linux 4.2/5.0, when a FIFO listener opens the
+ FIFO with mode O_RDONLY, the FIFO remains forever readable
+ after the writer has closed it. Workaround: open the FIFO
+ mode O_RDWR.
+
+ Test program: util/fifo_rdonly_bug.c
+
+ Unfortunately, the above fix triggers a bug on BSD/OS 3.1
+ where opening the FIFO mode O_RDWR causes select() to claim
+ that the FIFO is readable even before any data is written
+ to it, causing read() to block or to fail.
+
+ Test program: util/fifo_rdwr_bug.c
+
+ printfck (check arguments of printf-like function calls)
+ found a missing argument in local/command.c
+
+ Miscellaneous Makefile cleanups that I didn't finish before
+ the first alpha release.
+
+19980107
+
+ Sometimes the DNS will claim that a domain does not exist,
+ when in fact it does. Thus, it is a bad idea to reject mail
+ from apparently non-existent domains. I have changed the
+ smtpd so that it produces a soft error responses when a
+ resolve_smtp_sender test fails with HOST_NOT_FOUND. Note:
+ by default, this test is still disabled.
+
+ The DB and DBM read routines will now automagically figure
+ out if (key, value) pairs were written including a terminating
+ null byte or not. The DB and DBM write routines will use
+ this result to determine how to write, and will fall back
+ to per-system defaults otherwise.
+
+ Renamed the README to MUSINGS, and wrote up a README that
+ reflects the current status of the software.
+
+ Added -d (don't disconnect) and -c (show running counter)
+ option to te smtp-source test program. These tools are
+ great torture tests for the mail software, and for the
+ system that it runs on.
+
+ Turned down the process_limit parameter (# of parallel smtp
+ clients or servers) to avoid unpleasant surprises. You can
+ crank up the process_limit parameter in main.cf.
+
+19980111
+
+ Feature: when run by the superuser, mailq now shows the
+ mail queue even when the mail system is down. To this end,
+ mailq (sendmail -bp) runs the showq program directly instead
+ of connecting to the UNIX-domain service socket, and drops
+ privileges etc. as usual.
+
+19980119
+
+ Bugfix: Edwin Kremer spotted an oversight in the negated
+ host matching code (for name or address patterns prefixed
+ by !).
+
+ Bugfix: upon receipt of a SIGHUP signal, the master now
+ disconnects from its child processes, so that the current
+ generation of child processes commits suicide, and so that
+ the next generation of child processes will use the new
+ configuration settings.
+
+ Bugfix: the smtp server now skips the sender DNS domain
+ lookup test for foo@[address]
+
+ Bugfix: don't append the local domain to foo@[address]
+
+19980120
+
+ Bugfix: old low-priority bug in some list walk code that
+ caused the master to drop core when a service was turned
+ off in master.cf.
+
+ Robustness: the mail system should be able to start up and
+ to accept local postings even while the naming service is
+ down. For this reason, the mail system no longer uses
+ gethostbyname() to look up its own machine name. Sites
+ that use short hostnames will have to specify their FQDN
+ in main.cf (this will eventually be done by the system
+ installation/configuration procedure). Should the config
+ language support backtics so one can say `domainname`? What
+ about $name stuff between the backtics?
+
+ Security: the master now creates FIFOs and UNIX-domain
+ sockets as the mail owner instead of as root, for better
+ protection against subverted mail systems. chmod() is
+ susceptible to race conditions. fchmod(), although safer,
+ often does not work on sockets.
+
+ Portability: anticipate that all major UNIXes will create
+ UNIX-domain sockets with permissions modified by the process
+ umask (required by POSIX). For this reason, we always
+ chmod() UNIX-domain sockets, unless the system allows us
+ to use the safer fchmod() instead.
+
+ Portability: the semi-resident servers now properly handle
+ EWOULDBLOCK returns from accept() in addition to EGAIN
+ (on some systems, EAGAIN and EWOULDBLOCK have different
+ values).
+
+ Bugfix: the semi-resident servers now properly handle EINTR
+ returns From accept().
+
+ Bugfix: Edwin Kremer found that mynetworks() would compute
+ (32 - mask) instead of mask.
+
+19980121
+
+ Feature: /etc/vmailer/relocated is used by the local delivery
+ program and specifies what mail should be bounced with a
+ "user has moved to XXX" message. The main.cf configuration
+ parameter is "relocated_maps". Just like the "virtual_maps"
+ config parameter, this feature is off by default, and the
+ parameter can have values such as "files" or "files, nis"
+ (on hosts equipped with NIS).
+
+19980123
+
+ Cleanup: virtual domain support moved from the queue manager
+ to the resolve service, where it belongs.
+
+ Feature: /etc/vmailer/canonical is used by the rewrite
+ service for all addresses, and maps a canonical address
+ (user@domain) to another address. Typical use is to generate
+ Firstname.Lastname@domain addresses, or to clean up dirty
+ addresses from non-RFC 822 mail systems. The main.cf
+ configuration parameter is "canonical_maps". Just like
+ the "virtual_maps" config parameter, this feature is off
+ by default, and the parameter can have values such as
+ "files" or "files, nis" (on hosts equipped with NIS).
+
+19980124
+
+ HPUX10 port and many little fixes from Pieter Schoenmakers.
+
+ Bugfix: isolated an old mysterious bug that could make the
+ master deaf for new connections while no child process was
+ running. A typical result was that no pickup daemon would
+ be started after the previous one had terminated voluntarily.
+
+ Bugfix: the NIS lookup code did not mystrdup() the NIS map
+ name and would access free()d memory.
+
+19980125
+
+ Bugfix: the vstream routines would sometimes ignore flushing
+ errors. The error would still be reported by vstream_fclose()
+ and vstream_ferror().
+
+ Feature: time limit on delivery to shell commands. Config
+ parameter: command_time_limit. Default value: 100 sec. The
+ idea is to prevent one bad .forward file or alias file
+ entry from slowly using up all local delivery process slots.
+
+19980126
+
+ Code cleanup: in preparation for SMTP extensions such as
+ SIZE, allow an extended SMTP command to have a variable
+ number of options.
+
+19980127
+
+ Bugfix: moved canonical map lookups away from the rewriting
+ module to the cleanup service, so that canonical map lookups
+ do not interfere with address rewriting on behalf of other
+ programs. Back to an older trivial-rewrite program version.
+
+ Bugfix: moved virtual map lookups away from the resolver
+ back to the queue manager, so that virtual domain lookup
+ does not interfere with address resolution on behalf of
+ other programs. Back to an older qmgr program version.
+
+19980131
+
+ Feature: integrated and adapted Guido van Rooij's SIZE
+ option (RFC 1870), carefully avoiding potential problems
+ due to overflow (by multiplying large numbers) or unsigned
+ underflow (by subtracting numbers).
+
+ Code cleanup: cleaned up the code that parses the server
+ response to the HELO/EHLO command, so that we can more
+ reliably recognize what options a server supports.
+
+19980201
+
+ Portability: integrated the IRIX 6 port by Oved Ben-Aroya.
+
+ Portability: the software now figures out by itself if a
+ server should open its FIFO read-write or read-only, to
+ avoid getting stuck with a FIFO that stays readable forever.
+
+ Bugfix: the cleanup service would terminate with a fatal
+ vstream_fseek() error when the queue file was too large.
+
+ Bugfix: the cleanup service could be killed by a signal
+ when the queue file became too large.
+
+19980203
+
+ Portability: some systems have statfs(), some have statvfs(),
+ and the relevant include files are in a different place on
+ almost every system.
+
+ Portability: the makedefs script now nukes the -O compiler
+ flag when building on AIX with IBM's own compiler...
+
+19980204
+
+ Portability: HP-UX 9.x support by Pieter Schoenmakers.
+
+ Portability: added SYSV-style ulimit() file size limit
+ support for HP-UX 9.x.
+
+ Portability: added some #includes that appeared to be
+ missing according to the Digital UNIX cc compiler.
+
+ Bugfix: sys_defs.h now correctly specifies NIS support for
+ LINUX2, HPUX9 and HPUX10.
+
+ Security: fixed a file descriptor leak in the local delivery
+ agent that could give shell commands access to the VMailer
+ IPC streams. This should not cause a vulnerability, given
+ the design and implementation of the mailer, but it would
+ be like asking for trouble.
+
+ Bugfix: the sendmail -B (body type) option did not take a
+ value.
+
+19980205
+
+ Bugfix (SUNOS5): should not have deleted the SVID_GETTOD
+ definition from util/sys_defs.h.
+
+ Bugfix (HPUX9): forgot to specify whether to use statfs()
+ or statvfs().
+
+ Bugfix (HPUX9): don't try to raise the file size ulimit.
+
+ Bugfix (HPUX9): must specify file size limit in 512-blocks.
+
+19980207
+
+ Robustness: the master process now raises the file size
+ limit when it is started with a limit that is less than
+ VMailer's file size limit. File: util/file_limit.c.
+
+ Security: the dns lookup routines now screen all result
+ names with valid_hostname(). Bad names are treated as
+ transient errors.
+
+ Feature: qmail compatibility: when the home_mailbox parameter
+ is set, mail is delivered to ~/$home_mailbox instead of to
+ /var[/spool]/mail/username. This hopefully makes it easier
+ to lure people away from qmail :-)
+
+ Robustness: several testers by accident configured relayhost
+ the same as myhostname. The programs now explicitly check
+ for this mistake.
+
+ Bugfix: deliver_request_read() would free unallocated memory
+ when it received an incomplete delivery request from the
+ queue manager.
+
+ Robustness: local_destination_concurrency=1 prevents parallel
+ delivery to the same user (with possibly disastrous effects
+ when that user has an expensive pipeline in the .forward
+ or procmail config file). Each transport can have its own
+ XXX_destination_concurrency parameter, to limit the number
+ of simultaneous deliveries to the same destination.
+
+19980208
+
+ Robustness: added "slow open" mode, to gradually increase
+ the number of simultaneous connections to the same site as
+ long as delivery succeeds, and to gradually decrease the
+ number of connections while delivery fails. Brad Knowles
+ provided the inspiration to do this.
+
+ This also solves the "thundering herd" problem (making a
+ bunch of connections to a dead host when it was time to
+ retry that host). Let's see when other mailers fix this.
+
+ Feature: Added $smtpd_banner and $mail_version, for those
+ who want to show the world what software version they are
+ running.
+
+ Bugfix: vmailer-script now properly labels each syslog
+ entry.
+
+19980210
+
+ Portability: merged in NEXTSTEP 3 port from Pieter Schoenmakers
+
+ Bugfix: the local delivery program now checks that a
+ destination is a regular file before locking it.
+
+19980211
+
+ Robustness: the local delivery agent sets HOME, LOGNAME,
+ and SHELL when delivering to a user shell command. PATH is
+ always set, and TZ is passed through if it is set.
+
+19980212
+
+ Feature: mailq (sendmail -bp) now also lists the maildrop
+ queue (with mail that hasn't been picked up yet).
+
+19980213
+
+ Feature: the smtpd now says: 502 HELP not implemented. This
+ should impress the heck out of the competition :-)
+
+19980214
+
+ Feature: local delivery to configurable system-wide command
+ (e.g. procmail) avoids the need for per-user ~/.forward
+ shell commands. Config parameter: mailbox_command.
+
+19980215
+
+ Performance: avoid running a shell when a command contains
+ no shell magic characters or built-in shell commands. This
+ speeds up delivery to all commands. File: util/exec_command.c.
+
+ Bugfix: the local delivery agent, after reading EOF from
+ a child process, now sends SIGKILL only when the child does
+ not terminate within a limited amount of time. This avoids
+ some problems with procmail. File: util/timed_wait.c.
+
+19980217
+
+ Portability: folded in NetInfo support from Pieter
+ Schoenmakers.
+
+19980218
+
+ Feature: new vmlock command to run a command while keeping
+ an exclusive lock on a mailbox.
+
+ Feature: with "recipient_delimiter = +", mail for local
+ address "user+foo" is delivered to "foo", with a "Delivered-To:
+ user+foo@domain" message header. Files: qmgr/qmgr_message.c,
+ local/recipient.c. This must be the cheapest feature.
+
+19980219
+
+ Code cleanup: moved error handling into functions that
+ should always succeed (non_blocking(), close_on_exec()).
+
+19980223
+
+ Bugfix: null pointer bug in the cleanup program after
+ processing a From: header with no mail address (or with
+ only a comment).
+
+19980226
+
+ Robustness: now detects when getpwnam() returns a name that
+ differs from the requested name.
+
+ Feature: Added %p support to the vbuf_print formatting
+ module.
+
+ Code cleanup: revamped the alias/include/.forward loop
+ detection and duplicate suppression code in the local
+ delivery agent. This must be the fourth iteration, and
+ again the code has been simplified.
+
+19980228
+
+ Robustness: don't treat anything starting with whitespace
+ as a header record. Instead, explicitly test for leading
+ whitespace where we permit it. Files: global/is_header.c,
+ bounce/bounce_flush_service.c, local/delivered.c.
+
+19980301
+
+ Compatibility: the sendmail program now accepts the -N
+ command-line option (delivery status notification) but
+ ignores it entirely, just like many other sendmail options.
+
+ Bugfix: dns_lookup.c was too conservative with buffer sizes
+ and would incorrectly report "malformed name server reply".
+
+19980302
+
+ Bugfix: the local delivery agent was not null-byte clean.
+
+19980307
+
+ Feature: integrated Pieter Schoenmaker's code for transport
+ lookup tables that list (transport, nexthop) by destination.
+
+19980309
+
+ Bugfix: delivery agents no longer rename corrupt queue
+ files, because programs might fall over each other doing
+ so. Instead, when a delivery agent detects queue file
+ corruption, it chmods the queue file, simulates a soft
+ error, and lets the queue manager take care of the problem.
+
+ Bugfix: the SMTP server implemented VRFY incorrectly.
+
+ Feature: first shot at a pipe mailer, which can be used to
+ extend VMailer with external mail transports such as UUCP
+ (provided that the remote site understands domain addressing,
+ because VMailer version 1 does not rewrite addresses).
+
+ Cleanup: extended the master/child interface so that the
+ service name (from master.cf) is passed on to the child.
+ The pipe mailer needs the service name so it can look up
+ service-specific configuration parameters (privilege level,
+ recipient limit, time limit, and so on).
+
+19980310-12
+
+ Cleanup: factored out the pipe_command() code, so it can
+ be shared between pipe mailer and local delivery agent.
+
+19980314
+
+ Compatibility: the sendmail program now parses each
+ command-line recipient as if it were an RFC 822 message
+ header; some MUAs specify comma-separated recipients in a
+ command-line argument; and some MUAs even specify "word
+ word
" forms as command-line arguments.
+
+19980315
+
+ Bugfix: VMailer's queue processing randomization wasn't
+ adequate for unloaded systems with small backlogs.
+
+ Bugfix: smtpd now uses double-buffered stream I/O to prevent
+ loss of input sent ahead of responses.
+
+19980316
+
+ Bugfix: the smtpd anti-relay code didn't treat all hosts
+ listed in $mydestinations as local, so it would accept mail
+ only for hosts listed in $relay_domains (default: my own
+ domain).
+
+ Bugfix: smtpd now replies with 502 when given an unknown
+ command.
+
+19980318
+
+ Cleanup: resolve/rewrite clients now automatically disconnect
+ after a configurable amount of idle time (ipc_idle).
+
+19980322
+
+ Tolerance: VRFY now permits user@domain, even though the
+ RFC requires that special characters such as @ be escaped.
+
+19980325
+
+ Bugfix: a recipient delimiter of "-" could interfere with
+ special addresses such as owner-xxx or double-bounce.
+
+ Tolerance: the SMTP client now permits blank lines in SMTP
+ server responses.
+
+ Tolerance: the SMTP client now falls back to SMTP when it
+ apparently mistook an SMTP server as ESMTP capable.
+
+ Bugfix: eliminated strtok() calls in favor of mystrtok().
+ Symptom: master.cf parsing would break if $inet_interfaces
+ was more than one word.
+
+19980328
+
+ Bugfix: user->addr patterns in canonical and virtual tables
+ matched only $myorigin, not hosts listed in $mydestination
+ or addresses listed in $inet_interfaces. The man pages
+ were wrong too. File: global/addr_match.c.
+
+19980401
+
+ Robustness: FIFO file permissions now default to 0622. On
+ some systems, opening a FIFO read-only could deafen the
+ pickup daemon. Only the listener end (which is opened as
+ root) needs read access anyway, so there should not be a
+ loss of functionality by making FIFOs non-readable for
+ non-mail processes.
+
+19980402
+
+ Compatibility: sendmail -I and -c options added.
+
+19980403
+
+ Feature: virtual lookups are now recursive. File:
+ qmgr/qmgr_message.c
+
+19980405
+
+ Implemented sendmail -bs (stand-alone) mode. This mode runs
+ as the user and therefore deposits into the maildrop queue.
+
+19980406
+
+ The pickup service now removes malformed maildrop files.
+
+19980407
+
+ The pickup service now guards against maildrop files with
+ time stamps dated into the future.
+
+19980408
+
+ Bugfix: in the canonical and virtual maps, foo->address
+ would match foo@$myorigin only. This has been fixed to also
+ match hosts listed in main.cf:$mydestination and the
+ addresses listed in main.cf:$inet_interfaces.
+
+ Bugfix: added double buffering support to the VMailer SMTP
+ server. This makes the SMTP server robust against SMTP
+ clients that talk ahead of time, and should have been in
+ there from day one.
+
+19980409
+
+ Bugfix: the VMailer SMTP client now recognizes its own
+ hostname in the SMTP greeting banner only when that name
+ appears as the first word on the first line.
+
+19980410
+
+ Feature: smtpd now logs the local queue ID along with the
+ client name/address, and pickup now logs the local queue
+ ID along with the message owner.
+
+ Bugfix: still didn't do virtual/canonical lookups right
+ (code used the non-case-folded key instead of the case
+ folded one).
+
+19980418
+
+ Bugfix: the SMTP server did not flush the "250 OK queued
+ as XXXX" message from the SMTP conversation history.
+
+19980419
+
+ Bugfix: qmgr would not notice that a malformed message has
+ multiple senders, and would leak memory (Tom Ptacek).
+
+19980421
+
+ Portability: in the mantools scripts, the expr pattern no
+ longer has ^ at the beginning, and the scripts now use the
+ expand program instead of my own detab utility.
+
+19980425
+
+ NetBSD 1.x patch by Soren S. Jorvang.
+
+19980511
+
+ Feature: the SMTP server now logs the protocol (SMTP or
+ ESMTP) as part of the Received: header.
+
+ Feature: smtpd now logs the last command when a session is
+ aborted due to timeout, unexpected EOF, or too many client
+ errors.
+
+19980514
+
+ Bugfix: the queue manager did not update the counter for
+ in-core message structures, so the in-core message limit
+ had no effect. This can be bad when you have a large backlog
+ with many messages eligible for delivery.
+
+ Robustness: the queue manager now also limits the total
+ number of in-core recipient structures, so that it won't
+ use excessive amounts of memory on sites that have large
+ mailing lists.
+
+19980518
+
+ Bugfix: the SMTP client did not notice that the DNS client
+ received a truncated response. As a result, a backup MX
+ host could incorrectly claim that it was the best MX host
+ and declare a mailer loop.
+
+ Added start_msg/stop_msg entries to the vmailer startup
+ script, for easy installation.
+
+ Cleanup: VMailer databases are now explicitly specified as
+ type:name, for example, hash:/etc/aliases or nis:mail.aliases,
+ instead of implicitly as "files", "nis" and so on. Test
+ program: util/dict_open. This change allowed me to
+ eliminate a lot of redundant code from mkmap_xxx.c, and
+ from everything that does map lookups.
+
+19980525
+
+ Bugfix: local/dotforward.c compared the result of opening
+ a user's ~/.forward against the wrong error value.
+
+19980526
+
+ Bugfix: the smtpd VRFY command could look at free()d memory.
+
+ Robustness: the smtpd program had a fixed limit on the
+ number of token structures. The code now dynamically
+ allocates token structures.
+
+ Bugfix: the queue manager still used the deprecated parameter
+ name xxx_deliver_concurrency for concurrency control, but
+ the documentation talks about the preferred parameter name
+ xxx_destination_concurrency. Fix: try xxx_destination_concurrency
+ first, then fall back to xxx_deliver_concurrency.
+
+19980621-19980702
+
+ Cleanup: the string read routines now report the last
+ character read or VSTREAM_EOF. This change is necessary
+ for the implementation of the long SMTP line bugfix.
+
+ Bugfix: the smtp server exited the DATA command prematurely
+ when the client sent long lines. Reason: the smtp server
+ did not remember that it broke long lines, so that '.'
+ could appear to be the first character on a line when in
+ fact it wasn't.
+
+ Bugfix: the queue manager made lots of stupid errors while
+ reading $qmgr_message_recipient_limit chunks of recipients
+ from a queue file. This code has been restructured.
+
+19980706
+
+ Performance: the cleanup program now always adds return-receipt
+ and errors-to records to a queue file, so that the queue
+ manager does not have to plow through huge lists of
+ recipients.
+
+ Robustness: the initial destination concurrency now defaults
+ to 2, so that one bad message or one bad connection does
+ not stop all mail to a site. The configuration parameter
+ is called initial_destination_concurrency.
+
+ Performance: the per-message recipient limit is now enforced
+ by the queue manager instead of by the transport. Thus, a
+ large list of recipients for the same site is now mapped
+ onto several delivery requests which can be handled in
+ parallel, instead of being mapped onto one delivery request
+ that is sent to limited numbers of recipients, one group
+ after the other.
+
+19980707
+
+ Cleanup: the queue manager now does an additional recipient
+ sort after the recipients have been resolved, so that the
+ code can do better aggregation of recipients by next hop
+ destination.
+
+ Feature: lines in the master.cf file can now be continued
+ in the same manner as lines in the main.cf file, i.e. by
+ starting the next line with whitespace.
+
+ Feature: the smtp client now warns that a message may be
+ delivered multiple times when the response to "." is not
+ received (the problem described in RFC 1047).
+
+ Cleanup: when the queue manager changes its little mind
+ after contacting a delivery agent (for example, it decides
+ to skip the host because a transport or host goes bad),
+ the delivery agent no longer complains about premature EOF.
+ File: global/deliver_request.c
+
+19980709
+
+ Bugfix: when breaking long lines, the SMTP client did not
+ escape leading dots in secondary etc. line fragments. Fix:
+ don't break lines. This change makes VMailer line-length
+ transparent. Files: global/smtp_stream.c, smtp/smtp_proto.c.
+
+19980712
+
+ Cleanup: the queue manager to deliver agent protocol now
+ distinguishes between domain-specific soft errors and
+ recipient-specific soft errors. Result: many soft errors
+ with SMTP delivery no longer affect other mail the same
+ domain.
+
+19980713
+
+ Feature: the file modification time stamp of deferred queue
+ files is set to the nearest wakeup time of their recipient
+ hosts, or if delivery was deferred due to a non-host problem,
+ the time stamp is set into the future by the configurable
+ minimal backoff time.
+
+ Bugfix: the SMTP client and the MAILQ command would report
+ as message size the total queue file size. That would
+ grossly overestimate the size of a message with many
+ recipients.
+
+ Bugfix: the 19980709 fix screwed up locally-posted mail
+ that didn't end in newline.
+
+19980714
+
+ Robustness: the makedefs script now defaults to no optimization
+ when compiling for purify.
+
+19980715
+
+ Robustness: the makedefs script now defaults to no optimization
+ when compiling with gcc 2.8, until this compiler is known
+ to be OK.
+
+ Workaround: when sending multiple messages over the same
+ SMTP connection, some SMTP servers need an RSET command
+ before the second etc. MAIL FROM command. The VMailer SMTP
+ client now sends a redundant RSET command just in case.
+
+ The queue manager now logs explicitly when delivery is
+ deferred because of a "dead" message transport.
+
+19980716
+
+ Feature: mailq and mail bounces now finally report why mail
+ was deferred (the reason was logged to the syslog file
+ only). Changes were made to the bounce service (generalized
+ to be usable for defer logs), showq service (to show reasons)
+ and the queue manager.
+
+ As a result the defer directory (with one log per deferred
+ message) may contain many files; also, this directory is
+ accessed each time a message is let into the active queue,
+ in order to delete its old defer log. This means that hashed
+ directories are now a must.
+
+19980718-20
+
+ Feature: configurable timeout for establishing smtp
+ connections. Parameter: smtp_connect_timeout (default 0,
+ which means use the timeout as wired into the kernel).
+ Inspired by code from Lamont Jones. For a clean but far
+ from trivial implementation, see util/timed_connect.c
+
+ Cleaned up the interfaces that implement read/write deadlines.
+ Instead of returning -2, the routines now set errno to
+ ETIMEDOUT; the readable/writable tests are now separate.
+
+19980722
+
+ Feature: the default indexed file type (hash, btree, dbm)
+ is now configurable with the "database_type" parameter.
+ The default value for this parameter is system specific.
+
+ Feature: selectively turn on verbose logging for hosts that
+ match the patterns specified via the "debug_peer_list"
+ config parameter. Syntax is like the "bad_smtp_clients"
+ parameter (see global/peer_list.c). The verbose logging
+ level is specified with "debug_peer_level" (default 2).
+
+ Security: the local delivery agent no longer delivers to
+ files that have execute permission enabled.
+
+19980723
+
+ Workarounds for Solaris 2.x UNIX-domain sockets: they lose
+ data when you close them immediately after writing to them.
+ This could screw up the delivery agent to queue manager
+ protocol.
+
+19980724
+
+ Cleanup: spent most of the day cleaning up queue manager
+ code that defers mail when a site or transport dies, and
+ fixed a few obscure problems in the process.
+
+19980726
+
+ Feature: the admin can now configure what classes of problems
+ result in mail to the postmaster. Configuration parameter:
+ "notify_classes". Default is backwards compatible: bounce,
+ policy, protocol, resource, and software.
+
+19980726-28
+
+ Feature: the admin can now configure what smtp server access
+ control restrictions must be applied, and in what order.
+ Configuration parameters: smtpd_client_restrictions,
+ smtpd_helo_restrictions, smtpd_mail_restrictions and
+ smtpd_rcpt_restrictions. Defaults are intended to be
+ backwards compatible. The bad_senders and bad_clients lists
+ are gone and have become db (dbm, nis, etc) maps. Files:
+ smtpd/smtpd_check.c, config/main.cf.
+
+1998029-31
+
+ Feature: hashed queues. Rewrote parts of the mail queue
+ API. Configuration parameters: "hash_queue_names" specifies
+ what queue directories will be hashed (default: the defer
+ log drectory), "hash_queue_depth" specifies the number of
+ subdirectories used for hashing (default 2).
+
+19980802
+
+ Bugfix: the pipe mailer should expand command-line arguments
+ with $recipient once for every recipient (producing one
+ command-line argument per recipient), instead of replacing
+ $recipient by of all recipients (i.e. producing only one
+ command-line argument). This is required for compatibility
+ with programs that expect to be run from sendmail, such as
+ uux. Thanks to Ollivier Robert for helping me to get this
+ right.
+
+ Code cleanup: for the above, cleaned up the macro expansion
+ code in dict.c and factored out the parsing into a separate
+ module, mac_parse.c.
+
+19980803
+
+ "|command" and /file/name destinations in alias databases
+ are now executed with the privileges of the database owner
+ (unless root or vmailer). Thus, with: "alias_maps =
+ hash:/etc/aliases, hash:/home/majordomo/aliases", and with
+ /home/majordomo/aliases* owned by the majordomo account,
+ you no longer need the majordomo set-uid wrapper program,
+ and you no longer need root privileges in order to install
+ a new mailing list.
+
+19980804
+
+ Added support for the real-time blackhole list. Example:
+ "client_restrictions = permit_mynetworks, reject_maps_rbl"
+
+ All SMTP server "reject" status codes are now configurable:
+ unknown_client_reject_code, mynetworks_reject_code,
+ invalid_hostname_reject_code, unknown_hostname_reject_code,
+ unknown_address_reject_code, relay_domains_reject_code,
+ access_map_reject_code, maps_rbl_reject_code. Default values
+ are documented in the smtpd/smtpd_check.c man page.
+
+19980806-8
+
+ Code cleanup: after eye balling line-by line diffs, started
+ deleting code that duplicated functionality because it was
+ at the wrong abstraction level (smtp_trouble.c), moved
+ functionality that was in the wrong place (dictionary
+ reference counts in maps.c instead of dict.c), simplified
+ code that was too complex (password-file structure cache)
+ and fixed some code that was just wrong.
+
+19980808
+
+ Robustness: the number of queue manager in-core structures
+ for dead hosts is limited; the limit scales with the limit
+ on the number of in-core recipient structures. The idea is
+ to not run out of memory under conditions of stress.
+
+19980809
+
+ Feature: mail to files and commands can now be restricted
+ by class: alias, forward file or include file. The default
+ restrictions are: "allow_mail_to_files = alias, forward"
+ and allow_mail_to_commands = alias, forward". The idea is
+ to protect against buggy mailing list managers that allow
+ intruders to subscribe /file/name or "|command".
+
+19980810-12
+
+ Cleanup: deleted a couple hundred lines of code from the
+ local delivery agent. It will never be a great program;
+ sendmail compatibility is asking a severe toll.
+
+19980814
+
+ Cleanup: made the program shut up about some benign error
+ conditions that were reported by Daniel Eisenbud.
+
+19980814-7
+
+ Documentation: made a start of HTML docs that describe all
+ configuration parameters.
+
+ Feature: while documenting things, added smtpd_helo_required.
+
+19980817
+
+ Bugfix: at startup the queue manager now updates the time
+ stamps of active queue files some time into the future.
+ This eliminates duplicate deliveries after "vmailer reload".
+
+ Bugfix: the local delivery agent now applies the recipient
+ delimiter after looking in the alias database, instead of
+ before.
+
+ Documentation bugfixes by Matt Shibla, Tom Limoncelli,
+ Eilon Gishri.
+
+19980819
+
+ GLIBC fixes from Myrdraal.
+
+ Bugfix: applied showq buffer reallocation workaround in
+ the wrong place.
+
+ Bugfix: can't use shorts in varargs lists. SunOS 4 has
+ short uid_t and gid_t. pipe_command() would complain.
+
+ Bugfix: can't use signed char in ctype macros. All ctype
+ arguments are now casted to unsigned char. Thanks, Casper
+ Dik.
+
+19980820
+
+ Bugfix: save the alias lookup result before looking up the
+ owner. The previous alpha release did this right.
+
+ Cleanup: mail_trigger() no longer complains when the trigger
+ FIFO or socket is unavailable. This change is necessary to
+ shut up the sendmail mail posting program, so that it can
+ be used on mail clients that mount their maildrop via NFS.
+
+ Experiment: pickup and pipe now run as vmailer most of the
+ time, and switch to user privileges only temporarily.
+ Files: util/set_eugid.c global/pipe_command.c pipe/pipe.c
+ pickup/pickup.c. Is this more secure/ What about someone
+ manipulating such a process while not root? It still has
+ ruid == 0.
+
+19980822
+
+ Portability: with GNU make, commands such as "(false;true)"
+ and "while :; do false; done" don't fail. Workaround: use
+ "set -e" all over the place. Problem found by Jeff Wolfe.
+
+ Feature: "check_XXX_access maptype:mapname" (XXX = client,
+ helo, sender, recipient). Now you can make recipient and
+ other SPAM restrictions dependent on client or sender access
+ tables lookup results.
+
+19980823
+
+ Bugfix: smtpd access table lookup keys were case sensitive.
+
+ Added "permit" and "reject" operators. These are useful at
+ the end of SPAM restriction lists (smtpd_XXX_restrictions).
+
+ Added a first implementation of the permit_mx_backup SPAM
+ restriction. This permits mail relaying to any domain that
+ lists this mail system as an MX host (including mail for
+ the local machine). Thanks to Ollivier Robert for useful
+ discussions.
+
+19980824
+
+ Bugfix: transport table lookup keys were case sensitive.
+
+19980825
+
+ Portability: sa_len is some ugly #define on some SGI systems,
+ so we must rename identifiers (file util/connect.c).
+
+ Bugfix: uucp delivery errors are now sent to the sender.
+ Thanks, Mark Delany.
+
+ Bugfix: the pipe delivery agent now replaces empty sender
+ by the mailer daemon address. Mark Delany, again.
+
+ Portability: GNU getopt looks at all command-line arguments.
+ Fix: insert -- into the pipe/uucp definition in master.cf.
+
+ Bugfix: the smtp server command tokenizer silently discarded
+ the [] around [text], so that HELO [x.x.x.x] was read as
+ if the client had sent: HELO x.x.x.x. Thanks, Peter Bivesand.
+
+ Bugfix: the HELO unknown hostname/bad hostname restrictions
+ would have treated [text] as a domain name anyway.
+
+ Bugfix: the $local_duplicate_filter_limit value was not
+ picked up by the local delivery agent. This means the local
+ delivery agent could run out of memory on large mailing
+ list deliveries.
+
+19980826
+
+ Performance: mkmap/mkalias now run with the same speed as
+ sendmail. VMailer now uses a 4096-entry cache with 1 Mbyte
+ of memory for DB lookups. File: util/dict_db.c.
+
+19980902
+
+ Robustness: the reject_unknown_hostname restriction for
+ HELO/EHLO hostnames will now permit names that have an MX
+ record instead of an A record.
+
+19980903
+
+ Feature: appending @$myorigin to an unqualified address is
+ configurable with the boolean append_at_myorigin parameter
+ (default: yes).
+
+ Feature: appending .$mydomain to user@host is configurable
+ with the boolean append_dot_mydomain parameter (default:
+ yes).
+
+ Feature: site!user is rewritten to user@site, under control
+ of the boolean parameter swap_bangpath (default: yes).
+
+ Feature: permit a naked IP address in HELO commands (i.e. an
+ address without the enclosing [] as required by the RFC), by
+ specifying "permit_naked_ip_address" as one of the restrictions
+ in the "smtpd_helo_restrictions" config parameter.
+
+19980904
+
+ Code cleanup: when an SMTP client aborts a session after
+ sending MAIL FROM, the cleanup service no longer warns that
+ it is "skipping further client input". Files: cleanup/*.c.
+ Thanks, Daniel Eisenbud, for prodding.
+
+ Code cleanup: when an SMTP server disconnects in the middle
+ of a session, don't try to send QUIT over the non-existing
+ connection. Files: global/smtp_stream.c, smtp/smtp.c.
+ Thanks, Daniel Eisenbud, for prodding, again.
+
+ Code cleanup: the VMailer version number has moved from
+ mail_params.h (which is included by lots of modules) to a
+ separate file global/mail_version.h, so that a version
+ change no longer results in massive recompilation.
+
+ Bugfix: Errors-To was flagged as a sender address, so
+ the address never was picked up.
+
+ Code cleanup: support for Errors-To: headers completed.
+
+19980905
+
+ Feature: per-message exponential delivery backoff, by
+ looking at the amount of time a message has been queued.
+ Thanks, Mark Delany.
+
+19980906
+
+ Code cleanup: ripped out the per-host exponential backoff
+ code. It was broken by 19980818. It was probably a bad idea
+ anyway, because it required per-host, in-core, state kept
+ by the queue manager. All we do now is to keep state for
+ $minimal_backoff_time seconds, but only for a limited number
+ of hosts. Daniel Eisenbud spotted the problem.
+
+ Lost feature: the SMTP session transcripts now show who
+ said what. This feature was inadvertently dropped during
+ development. Thanks, Daniel Eisenbud, for reminding.
+
+ Documentation: the hard-coded rewriting process of the
+ trivial-rewrite program is described in html/rewrite.html.
+
+ Feature: the local delivery agent now does alias lookups
+ before and after chopping off the recipient subaddress.
+ This allows you to forward user-anything to another user,
+ without losing the ability to redirect specific user-foo
+ addresses.
+
+19980909
+
+ Feature: the smtp client now logs a warning that a server
+ sends a greeting banner with the client's hostname, which
+ could imply a mailer loop.
+
+19980910
+
+ Feature: separate canonical maps for sender and recipient
+ address rewriting, so that you can rewrite an ugly sender
+ address and still forward mail to that same ugly address
+ without creating a mailer loop. Files: cleanup_envelope.c,
+ cleanup_message.c, cleanup_rewrite.c.
+
+19980911
+
+ Feature: virtual maps now support multiple addresses on
+ the right-hand side. In the case of virtual domains this
+ can eliminate the need for address expansion via local
+ aliases, making virtual domains much easier to administer.
+ This required that I moved the virtual table lookups from
+ the queue manager to the cleanup service, so that every
+ recipient has an on-disk status record. Files: qmgr.c,
+ qmgr_message.c, cleanup_envelope.c, cleanup_rewrite.c,
+ cleanup_virtual.c.
+
+ Feature: sendmail/mailq/newaliases pass on the -v flag to
+ the program that they end up running, to make debugging a
+ little easier.
+
+19980914
+
+ Bugfix: some anti-spam measures didn't recognize some
+ addresses as local and would do too much work. File:
+ smtpd_check.c.
+
+ Bugfix: the smtp sender/recipient table lookup restriction
+ destroyed global data, so that other restrictions could
+ break. File: smtpd_check.c.
+
+ Bugfix: after vmailer reload, single-threaded servers could
+ exit before flushing unwritten data to the client. Example:
+ cleanup would exit before acking success to pickup, so the
+ message would be delivered twice. Bug reported by Brian Candler.
+
+ Cleanup: removed spurious error output from vmailer-script.
+ Reported by Brian Candler.
+
+ Tolerance: ignore non-numeric SMTP server responses. There's
+ lot of brain damage out there on the net.
+
+19980915
+
+ Feature: the smtp-sink benchmark tool now announces itself
+ with a neutral name so that it can be run on the same
+ machine as VMailer, without causing Postfix to complain
+ about a mailer loop.
+
+ Robustness: on LINUX, vmailer-script now does chattr +S to
+ force synchronous directory updates. Fix developed with
+ Chris Wedgwood.
+
+19980916
+
+ Bugfix: when transforming an RFC 822 address to external
+ form, there is no need to quote " characters in comments.
+ This didn't break anything, it just looked ugly. File:
+ global/tok822_parse.c
+
+19980917
+
+ Workaround: with deliveries to /file/name, use fsync() and
+ ftruncate() only on regular files. File: local/file.c
+
+ Workaround: the plumbing code in master_spawn.c didn't
+ check if it was dup2()/close()ing a descriptor to itself
+ then closing it. Will have to redo the plumbing later.
+
+19980918
+
+ Workaround: on multiprocessor Solaris machines, one-second
+ rollover appears to happen on different CPUs at slightly
+ different times. Made the queue manager more tolerant for
+ such things. Problem reported by Daniel Eisenbud.
+
+ Workaround: in preparation for deployment with a network-shared
+ maildrop directory. make pickup more tolerant against clock
+ drift between clients and servers.
+
+19980921
+
+ New vstream_popen() module that opens a two-way channel
+ across a socketpair-based pipe. This module isn't being
+ used yet; it is here only to complete the vstream code.
+
+19980922
+
+ Code cleanup: the xxx_server_main() interface for master
+ child processes now uses a name-value argument list instead
+ of an ugly and inflexible data structure.
+
+ Bugfix: moved the test if a non-interactive process is run
+ by hand, so that the "don't do this" error message can be
+ printed to stderr before any significant processing.
+
+ Bugfix: smtpd now can talk to unix-domain sockets without
+ bailing out on a peer lookup problem. Files: smtpd/smtpd.c,
+ util/peer_name.c.
+
+ Safety: by default, the postmaster is no longer informed
+ of protocol problems, policy violations or bounces.
+
+ Safety: the SMTP server now sleeps before sending a [45]xx
+ error response, in order to prevent clients from hammering
+ the server with a connect/error/disconnect loop. Parameter:
+ smtpd_error_sleep_time (default: 5).
+
+ Feature: the logging facility is compile-time configurable
+ (e.g., make makefiles "CCARGS=-DLOG_FACILITY=LOG_LOCAL1").
+
+19980923
+
+ Bugfix: changed virtual/canonical map search order from
+ (user@domain, @domain, user) to (user@domain, user, @domain)
+ so the search order is most specific to least specific.
+ File: global/addr_map.c, lots of documentation.
+
+ Bugfix: after the change of 19980910, cleanup_message
+ extracted recipients from Reply-To: etc. headers. Found
+ by Lamont Jones.
+
+19980925
+
+ Bugfix: the change in virtual/canonical map search order
+ broke @domain entries; they would never be looked up if
+ the address matched $myorigin or $mydestinations. Found
+ by Chip Christian who now regrets asking for the change.
+
+ Bugfix: cleanup initialized an error mask incorrectly, so
+ that it would keep writing to a file larger than the queue
+ file size limit, and so it would treat the error as a
+ recoverable one instead of sending a bounce. Thanks, Pieter
+ Schoenmakers.
+
+ Bugfix: the "queue file cleanup on fatal error" action was
+ no longer enabled in the sendmail mail posting agent.
+
+ Feature: the sendmail mail posting program now returns
+ EX_UNAVAILABLE when the size of the input exceeds the queue
+ file size limit. NB THIS CHANGE HAS BEEN WITHDRAWN.
+
+19980926
+
+ Code cleanup: the dotlock file locking routine is no longer
+ derived from Eric Allman's 4.3BSD port of mail.local.
+
+ Code cleanup: the retry strategy of the file locking routines
+ dot_lockfile() and deliver_flock() is now configurable
+ (deliver_flock_attempts, deliver_flock_delay, deliver_flock_stale).
+
+ Code cleanup: the master.pid lock file is now created with
+ symlink paranoia, and is properly locked so that PID rollover
+ will not cause false matches.
+
+ Bugfix: the vbuf_print() formatting engine did not know
+ about the '+' format specifier.
+
+ Cleanup: replaced unnecessary instances of stdio calls by
+ vstream ones.
+
+19980929-19981002
+
+ Compatibility: added support for "sendmail -q". This required
+ a change to the queue manager trigger protocol, and a code
+ reorganization of the way queue scans were done. The queue
+ manager socket now has become public.
+
+10091002
+
+ SMTPD now logs "lost connection after end-of-message" instead
+ of "lost connection after DATA".
+
+10091005
+
+ More bullet proofing: timeouts on all triggers.
+
+19981006
+
+ Bugfix: make the number of cleanup processes unlimited, in
+ order to avoid deadlock. The number of instances needed is
+ one per smtp/pickup process, and an indeterminate number
+ per local delivery agent. Thanks, Thanks, David Miller and
+ Terry Lorrah for cleueing me in.
+
+ Bugfix: "sendmail -t" extracted recipients weren't subjected
+ to virtual mapping. Daniel Eisenbud strikes again.
+
+19981007
+
+ Compatibility: if the first input line ends in CRLF, the
+ sendmail posting agent will treat all CRLF as LF. Otherwise,
+ CRLF is left alone. This is a compromise between sendmail
+ compatibility (all lines end in CRLF) and binary transparency
+ (some, but not all, lines contain CRLF).
+
+19981008
+
+ Robustness: stop recursive virtual expansion when the
+ left-hand side appears in its own expansion.
+
+19981009
+
+ Portability: trigger servers such as pickup and qmgr can
+ now use either FIFOs or UNIX-domain sockets; hopefully at
+ least one of them works properly. Trigger clients were
+ already capable of using either form of local IPC.
+
+19981011
+
+ Feature: masquerading. Strip subdomains from domains listed
+ in $masquerade_domains. Exception: envelope recipients are
+ left alone, in order to not screw up routing.
+
+19981015
+
+ Code cleanup: moved the recipient duplicate filter from
+ the user-level sendmail posting agent to the semi-resident
+ cleanup service, so that the filter operates on the output
+ from address canonicalization and of virtual expansion,
+ instead of operating on their inputs.
+
+19981016
+
+ Bugfix: after kill()ing a bunch of child processes, wait()
+ sometimes fails before all children have been reaped, and
+ must be called again, or the master will SIGSEGV later.
+ Problem reported by Scott Cotton.
+
+ Workaround: don't log a complaint when an SMTP client goes
+ away without sending QUIT.
+
+19981018
+
+ Workaround: Solaris 2.5 ioctl SIOCGIFCONF returns a hard
+ error (EINVAL) when the result buffer is not large enough.
+ This can happen on systems with many real or virtual
+ interfaces. File: util/inet_addr_local.c. Problem reported
+ by Scott Cotton.
+
+ Workaround: the optional HELO/EHLO hostname syntax check
+ now allows a single trailing dot.
+
+ Workaround: with UNIX-domain sockets, LINUX connect() blocks
+ until the server calls accept(). File: qmgr/qmgr_transport.c.
+ Terry Lorrah and Scott Cotton provided the necessary evidence.
+
+19981020
+
+ Robustness: recursive canonical mapping terminates when
+ the result stops changing.
+
+ Code cleanup: reorganized the address rewriting and mapping
+ code in the cleanup service, to make it easier to implement
+ the previous enhancement.
+
+19981022
+
+ Code cleanup: more general queue scanning programming
+ interface, in preparation for hashed queues. File:
+ qmgr/qmgr_scan.c.
+
+ Bugfix: a non-FIFO server with a process limit of 1 has a
+ too short listen queue. Until now this was not a problem
+ because only FIFO servers had a process limit of 1, and
+ FIFOs have no listen queue. Fix: always configure a listen
+ queue of proc_limit or more. File: master/master_listen.c.
+
+19981023
+
+ Feature: by popular request, mail delay is logged when
+ delivering, bouncing or deferring mail.
+
+19981024
+
+ Cleanup: double-bounce mail is now absorbed by the queue
+ manager, instead of the local delivery agent, so that the
+ mail system will not go mad when no local delivery agent
+ is configured.
+
+19981025
+
+ Cleanup: moved the relocated table from the local delivery
+ agent to the queue manager, so that the table can also be
+ used for virtual addresses.
+
+ Code reorg: in order for the queue manager to absorb
+ recipients, the queue file has to stay open until all
+ recipients have been assigned to a destination queue.
+
+19981026
+
+ vmlogger command, so that vmailer-script logging becomes
+ consistent with the rest of the VMailer system.
+
+ Code reorg: logger interface now can handle multiple output
+ handlers (e.g. syslog and stderr stream).
+
+ Bugfix: a first line starting with whitespace is no longer
+ treated as an extension of our own Received: header. Files:
+ smtpd/smtpd.c, pickup/pickup.c.
+
+19981027
+
+ Bugfix: the bang-path swapping code went into a loop on an
+ address consisting of just a single !. Eilon Gishri had
+ the privilege of finding this one.
+
+ Workaround: the non-blocking UNIX-domain socket connect is
+ now enabled only on systems that need it. It may cause
+ kernel trouble on Solaris 2.x.
+
+ Bugfix: the resolver didn't implement bangpath swapping,
+ so that mail for site!user@mydomain would be delivered to
+ a local user named "site!user".
+
+19981028
+
+ Cleanup: a VSTREAM can now use different file descriptors
+ for reading and writing. This was necessary to prevent
+ "sendmail -bs" and showq from writing to stdin. Eilon Gishri
+ observed the problem.
+
+19981029
+
+ The RFC 822 address manipulation routines no longer give
+ special attention to 8-bit data. Files: global/tok822_parse.c,
+ global/quote_822_local.c.
+
+ Bugfix: host:port and other non-domain stuff is no longer
+ allowed in mail addresses. File: qmgr/qmgr_message.c.
+
+ Workaround: LINUX accept() wakes up before the three-way
+ handshake is complete, so it can fail with ECONNRESET.
+ Files: master/single_server.c, master/multi_server.c.
+
+ Feature: when delivering to user+foo, try ~user/.forward+foo
+ before trying ~user/.forward.
+
+ Bugfix: smtpd in "sendmail -bs" (stand-alone) mode didn't
+ clean up when terminated by a signal.
+
+ Bugfix: smtpd in "sendmail -bs" (stand-alone) mode should
+ not try to enforce spam controls because it cannot access
+ the address rewriting machinery.
+
+ Cleanup: the percent hack (user%domain -> user@domain) is
+ now configurable (allow_percent_hack, default: yes).
+
+ Bugfix: daemons in -S (stand-alone) mode didn't change
+ directory to the queue. This was no problem with daemons
+ run by the sendmail compatibility program.
+
+19981030
+
+ Feature: when virtual/canonical/relocated lookup fails for
+ an address that contains the optional recipient delimiter
+ (e.g., user+foo@domain), the search is done again with the
+ unextended address (e.g., user@domain). File: global/addr_find.c.
+
+ Code reorg: the address searching is now implemented by a
+ separate module global/addr_find.c, so that the same code
+ can be used for both (non-mapping) relocated table lookups
+ and for canonical and virtual mapping. The actual mapping
+ is still done in the global/addr_map.c module.
+
+ Robustness: the SMTP client now skips hosts that don't send
+ greeting banner text. File: smtp/smtp_connect.c
+
+ Feature: preliminary support to disable delivered-to. This
+ is desirable for mailing list managers that don't want to
+ advertise internal aliases.
+
+ Generic support: when the recipient_feature_delimiter
+ configuration parameter is set, the local delivery agent
+ uses it to split the recipient localpart into fields. Any
+ field that has a known name such as "nodelivered" enables
+ the corresponding delivery feature.
+
+19981031
+
+ Code reorg: address splitting on recipient delimiter is
+ now centralized in global/split_addr.c, which knows about
+ all reserved names that should never be split.
+
+ Robustness: when a request for an internal service cannot
+ be satisfied because the master has terminated, terminate
+ instead of trying to reach the service every 30 seconds.
+
+ Safety: the local delivery agent now runs as vmailer most
+ of the time, just like pickup and pipe. Files: local/local.c,
+ local/mailbox.c
+
+19981101
+
+ Compatibility: the tokenizer for alias/forward/etc.
+ expansion now updates an optional counter with the number
+ of destinations found; If no destinations is found in a
+ .forward file, deliver to the mailbox instead. Thanks,
+ Daniel Eisenbud, for showing the way to go.
+
+ Robustness: the pickup daemon should always include a
+ posting-time record, even when the sendmail posting agent
+ didn't. However, just like before, user-provided posting
+ times will be ignored. Ollivier Robert found this one.
+
+ Robustness: duplicate entries in aliases or maps now cause
+ a warning instead of a fatal error (and an incomplete file).
+
+ Robustness: mkmap now prints a warning when an entry is
+ in "key: value" format, which is the format expected for
+ alias databases, not for maps.
+
+ Portability: on LINUX, prepend "+" to the getopt() options
+ string so that getopt() will stop at the first non-option
+ argument. Suggestion by Marco d'Itri.
+
+19981103
+
+ Cleaned up the set_eugid() and open_as() implementations,
+ and added stat_as() and fstat_as() so that the local delivery
+ agent would look up include files and .forward files with
+ the right privileges.
+
+19981104
+
+ Bugfix: the :include: routine now stat()s/open()s files
+ included by root-owned aliases as root, not as nobody.
+
+ Bugfix: the master crashed when a service with wakeup timer
+ was disabled or renamed. Fix: eliminate some pathological
+ coupling between process management and wakeup management.
+
+ Feature: partial implementation of ETRN (causes a full
+ deferred queue scan). Thanks Lamont Jones for reminding me
+ that things can be useful already before they are perfect.
+
+ Cleanup: simplified the SMTPD tokenizer.
+
+ Bugfix: sendmail -bs didn't properly notify the mail system
+ of new mail.
+
+ Compatibility: the MAIL FROM and RCPT TO commands now accept
+ the most common address forms without enclosing <>. The <>
+ is still needed for addresses that contain a "string", an
+ [address], or a colon (:).
+
+19981105
+
+ Bugfix: "master -t" would claim that the master runs when
+ in fact the pid directory does not exist, causing trouble
+ with first time startup (reported by several).
+
+ Portability: added a sane_accept() module that maps all
+ beneficial accept() error results to EAGAIN. According to
+ private communication with Alan Cox, Linux 2.0.x accept()
+ can return a variety of error conditions, so we play safe
+ and allow for any error that may happen because SYN+ACK
+ could not be sent.
+
+ Portability: NETBSD1 uses dotlock files (Perry Metzger).
+
+ Bugfix: the local delivery agent did not canonicalize
+ owner-foo sender addresses, so that local users would see
+ owner-foo instead of owner-foo@$myorigin (Perry Metzger).
+
+ OPENSTEP4 support, similar to NEXTSTEP3 (Gerben Wierda).
+
+19981106
+
+ Portability: the master startup would take a long time on
+ AIX because AIX has a very large per-process open file
+ limit. Fix is to check the status of only the first couple
+ hundred file descriptors instead. File: master/master.c.
+
+ Bugfix: mail to user@[net.work.addr.ess] was broken because
+ of a reversed test. File: qmgr/qmgr_message.c.
+
+19981107
+
+ Compatibility: don't clobber the envelope sender address
+ when an alias has no owner-foo alias (problem diagnosed by
+ Christophe Kalt).
+
+ Bugfix: mail to local users in include files would be
+ delivered directly if the alias didn't have an owner-foo
+ alias, and if the alias database and include file were
+ owned by root.
+
+ Feature: with user+foo addresses, any +foo address extension
+ that is not explicitly matched in canonical, virtual or
+ alias databases is propagated to the table lookup result.
+
+19981108
+
+ Bugfix: minor memory leak in the user+foo table lookup code.
+
+ Configurability: specify virtual.domain in the virtual map,
+ and mail for unknown@virtual.domain will bounce automatically.
+ The $relay_domains default value now includes $virtual_maps,
+ so the SMTP server will accept mail for the domain. Marco
+ d'Itri put me on the right track.
+
+ Configurability: The mydestinations configuration parameter
+ now accepts /file/name expressions and type:name lookup tables.
+
+ Code cleanup: in order to make the previous two enhancements
+ possible, revised the string/host/address matching engine
+ so it can handle any mixture of strings, /file/name patterns
+ and type:name lookup tables. Files: util/match_{list,ops}.c,
+ global/{domain,namadr,string}_list.c.
+
+19981110
+
+ Code cleanup: replaced remaining isxxx() calls by ISXXX().
+
+19981111
+
+ Bugfix: the "bounce unknown virtual user" code was in the
+ wrong place. Problem tackled with help of Chip Christian.
+
+ Portability: reportedly, Solaris 2.5.1 can hang waiting
+ for a UNIX-domain connection to be accepted, to it gets
+ the same workaround that was designed for LINUX. Problem
+ reported by Scott Cotton.
+
+19981112
+
+ Management: "vmailer stop" now allows delivery agents to
+ finish what they are doing, like "vmailer reload".
+
+ Management; "vmailer abort" causes immediate termination.
+
+ Workaround: zombie processes pile up with HP-UX. Reason:
+ select() does not return upon SIGCHLD when SA_RESTART is
+ specified to sigaction(). Workaround: shorten the select()
+ timer to 10 seconds, #ifdef BRAINDEAD_SELECT_RESTARTS.
+ Thanks, Lamont Jones.
+
+19981117
+
+ Rename: VMailer is now Postfix. Sigh.
+
+19981118
+
+ Cleanup: generalized the safe_open() routine so that it is
+ no longer limited to mailbox files, lock files, etc.
+
+ Bugfix (found during code review): vstream*printf() could
+ run off the end of a stream buffer after an I/O error,
+ because vbuf_print() ignored the result from VBUF_SPACE().
+
+ Bugfix (found during code review): resolve_local() could
+ clobber its argument, but the docs didn't say so.
+
+19981121
+
+ Cleanup: the is_header() routine now allows 8-bit data in
+ header labels.
+
+19981123
+
+ Bugfix (found during code review): the mail_queue_enter()
+ path argument wasn't optional. File: global/mail_queue.c
+
+19981124
+
+ Cleanup: eliminated redundant tests for a zero result from
+ vstream_fdopen(). Unlike the stdio fdopen() routine, the
+ vstream_fdopen() routine either succeeds or never returns.
+
+ Bugfix: the queue manager now looks at the clock before
+ examining a file time stamp, to avoid spurious complaints
+ about time warps on busy machines. File: qmgr/qmgr_active.c.
+
+19981125
+
+ Compatibility: allow trailing dot at the end of user@domain.
+ Address canonicalization now strips it off. Issue brought
+ forward by Eilon Gishri. File: trivial-rewrite/rewrite.c.
+
+ Robustness: changed DNS lookup order of MAIL FROM etc.
+ domains from MX then A to A then MX, just in case the MX
+ lookup fails with a server error.
+
+ Renamed vmcat, vmlock, vmlogger, vmtrigger to postcat,
+ postlock, postlog, postkick. Also renamed mkmap and mkalias
+ to postmap and postalias.
+
+19981126
+
+ Workaround: Lamont Jones found a way for HP-UX to terminate
+ select() after SIGCHLD. The code is #ifdef USE_SIG_RETURN.
+ Files: util/sys_defs.h, master/master_sig.c.
+
+ Bugfix: the Delivered-To: loop detection code had stopped
+ working, when long ago the is_header() routine was changed.
+ File: local/delivered.c.
+
+19981128
+
+ Bugfix: postcat opened queue files read-write, where only
+ read access was needed. File: postcat/postcat.c.
+
+19981129
+
+ Safety: added a sleep(1) to all fatal and panic exits.
+ File: util/msg.c.
+
+19981201
+
+ Robustness: postcat now insists that a file starts with a
+ time record.
+
+ Consistency: added "-c config_dir" command-line options
+ where appropriate.
+
+19981202
+
+ Man pages, on-line version.
+
+19981203
+
+ Man pages, html version; overview documentation.
+
+19981206
+
+ Sendmail silently accepted the unsupported -qRsite and
+ -qSsite options. It now prints an error message and
+ terminates.
+
+ Separated the contributed tree from the IBM code; moved
+ the LDAP and NEXTSTEP/OPENSTEP code to the contributed
+ source tree because obviously I didn't write it.
+
+19981206-9
+
+ Had to write a postconf configuration utility in order to
+ reliably find out about all configuration parameters and
+ their defaults.
+
+ Documentation bugfixes by Matt Shibla, Scott Drassinower,
+ Greg A. Woods.
+
+19981209
+
+ On machines with short hostnames, postconf -d cored while
+ reporting a fatal error. It should not report that error
+ in the first place. Thanks, Eilon Gishri.
+
+ Changed the FAQ entry about rejecting mail for *.my.domain
+ on a firewall. Chip Christian was right, I was wrong.
+
+19981214
+
+ Portability: with GNU getopt, optind is not initially 1,
+ breaking an assumption in sendmail/sendmail.c. Liviu Daia.
+
+ Annoyance: on non-networked systems, don't warn that only
+ one network interface was found. File: global/inet_addr_local.c.
+ Reported by several.
+
+ Bugfix: on non-networked systems, the smtp client assumed
+ that it was running in virtual host mode, and would bind
+ to the loopback interface. File smtp/smtp_connect.c. Liviu
+ Daia, again.
+
+19981220
+
+ Robustness: when looking up an A or MX record, do not give
+ up when the A query fails because of a server error. File
+ dns/dns_lookup.c. Reported by Scott Drassinower.
+
+19981221
+
+ Bugfix: "bounce mail for non-existent virtual user" didn't
+ work when a non-default relay host was configured in main.cf
+ or in the transport table. File: qmgr/qmgr_message.c.
+
+ Bugfix: the maildrop directory should not be world-readable.
+ Files: conf/postfix-script, showq/showq.c.
+
+ Documentation: fixed several omissions and errors.
+
+ Documentation: removed references to the broken recipient
+ feature delimiter configuration parameter.
+
+ Bugfix: write mailbox file as the recipient, so that file
+ quota work as expected.
+
+ Bugfix: pickup would die when it tried to remove a non-file
+ in the maildrop directory (Jeff Wolfe).
+
+19981222
+
+ Sendmail no longer logs the queue ID when it is unable to
+ notify the pickup daemon. This is a late addition to the
+ "unreadable maildrop queue" patch.
+
+ user.lock files are now created as root, so that postfix
+ needs no group directory write permission.
+
+19981224
+
+ Security: allow queue file link counts > 1, to avoid
+ non-delivery of maildrop files with links to a non-maildrop
+ directory. Files: global/mail_open_ok.c, and anything
+ that calls this code (qmgr, pickup, showq). If multiple
+ hard links are a problem, see the set-gid "postdrop" utility
+ below.
+
+19981225
+
+ Robustness: the queue manager no longer aborts when a queue
+ file suddenly disappears (e.g. because the file was removed
+ by hand).
+
+ Feature: when a writable maildrop directory is a problem,
+ sites can make the new "postdrop" utility set-gid. This command
+ is never used when the maildrop directory is world-writable.
+
+ Robustness: make the queue file creation routine more
+ resistant against denial of service race attack. File:
+ global/mail_queue.c
+
+19981226
+
+ New suid_priv module to enable/disable privileges in a
+ set-uid/gid program. In the end I decided to not use it.
+
+19981228
+
+ Robustness: make the pickup daemon more resistant against
+ non-file race attack.
+
+ Cleanup: generic mail_stream.c interface for writing queue
+ file streams to files, daemons or commands. This simplifies
+ the code in smtpd and in sendmail that must be able to pipe
+ mail through the postdrop command. The cleanup daemon has
+ been modified to use the same interface. Result: less code.
+
+ Feature: smtpd now logs the only recipient in Received:
+ headers.
+
+ Feature: separate command and daemon directories. Both
+ default to $program_directory. Install conf/postfix-script
+ if you want to use this feature.
+
+19981230
+
+ Patch to avoid conflict with non-writable top-level Makefile
+ (Lamont Jones).
+
+19981231
+
+ Portability: port to UnixWare 7 by Ronald Joe Record, SCO.
+
+19990104
+
+ Bugfix: fencepost (Jon Ribbens, Oaktree Internet Solutions
+ Ltd.) Files: quote_82[12]_local.c.
+
+ Bugfix: wrong default for relay_domains (Juergen Kirschbaum,
+ Bayerische Landesbank). File: mail_params.h.
+
+ Bugfix: changed 5xx response for "too may recipients" to
+ 4xx. File: smtpd.c.
+
+19990106
+
+ Feature: defer_transports specifies the names of transports
+ that should be used only when "sendmail -q" (or equivalent)
+ is issued. For example, "defer_transports = smtp" is useful
+ for sites that are disconnected most of the time. File:
+ qmgr_message.c.
+
+19990107
+
+ Feature: local_command_shell specifies a non-default shell
+ for delivery to command by the local delivery agent. For
+ example, "local_command_shell = /some/where/smrsh -c"
+ restricts what may appear in "|command" destinations.
+ File: global/pipe_command.c.
+
+19990112-16
+
+ Feature: SMTP command pipelining support based on an initial
+ version by Jon Ribbens, Oaktree Internet Solutions Ltd.
+ This one took several days of massaging before I felt
+ comfortable about it. Files: smtp.c, smtp_proto.c.
+
+ Bugfix: the SMTP server would flush responses one-by-one,
+ which caused suboptimal performance with pipelined clients.
+ The vstream routines now flush the write buffer when the
+ read() routine is called, instead of flushing when the
+ application changes from writing to reading. Delayed flush
+ prevents the SMTP server from flushing responses one-by-one
+ and thus triggering Nagle's algorithm. File: util/vstream.c.
+
+19990117
+
+ Bugfixes and enhancements to the smtpstone tools by Drew
+ Derbyshire, Kendra Electronic Wonderworks: send helo command,
+ send message headers, format the message content to lines
+ < 80, work around NT stacks, make "." recognition more
+ robust. Files: smtp-source.c, smtp-sink.c.
+
+ Strategy: look at the deferred queue only when the incoming
+ queue is empty; limit the number of recipients read from
+ a queue file depending on the number of recipients already
+ in core. Files: qmgr.c, qmgr_message.c.
+
+ Feature: postponed anti-UCE restrictions. The decision to
+ reject junk mail on the basis of the client name/address,
+ HELO hostname or sender address can now be postponed until
+ the RCPT TO command (or HELO or MAIL FROM if you like).
+ File: smtpd_check.c.
+
+19990118
+
+ Feature: incremental updates of alias databases and of
+ other lookup tables. Both postalias and postmap now take
+ a -i option for incremental updates from standard input.
+ Files: global/mkmap_*.c, post{map,alias}/post{map,alias}.c.
+
+ Compatibility: newaliases can now update multiple alias
+ databases: list them in the "alias_database" parameter in
+ main.cf. By the same token, postalias can now update multiple
+ maps in one command. Files: post{map,alias}/post{map,alias}.c
+
+ Feature: mail to <> is now sent to the address specified
+ with the "empty_address_recipient" configuration parameter
+ which defaults to MAILER-DAEMON (idea by Lamont Jones,
+ Hewlett-Packard). File: cleanup/cleanup_envelope.c.
+
+ Compatibility: the transport table now uses .domain.name
+ to match subdomains, just like sendmail mailer tables
+ (patch by Lamont Jones, Hewlett-Packard).
+
+ Feature: mailq now ends with a total queue size summary
+ (Eilon Gishri, Israel Inter University Computation Center).
+
+19990119
+
+ Feature: address masquerade exceptions for user names listed
+ in the "masquerade_exceptions" configuration parameter.
+ File: cleanup/cleanup_masquerade.c.
+
+ Feature: qmail-style maildir support, based on initial code
+ by Kevin W. Brown, Quantum Internet Services Inc.
+
+ Workaround: Solaris 2.something connect() fails with
+ ECONNREFUSED when the system is busy (Chris Cappuccio,
+ Empire Net). File: global/mail_connect.c.
+
+ Feature: the cleanup service now adds a Return-Path: header
+ when none is present. This header is needed for some mail
+ delivery programs (see below). File: cleanup_message.c.
+
+ Feature: the pipe mailer now supports $user, $extension
+ and $mailbox macros in command-line expansions. This, plus
+ the Return-Path: header (see above), should be sufficient
+ to support cyrus IMAP out of the box. Based on initial
+ code by Joerg Henne, Cogito Informationssysteme GMBH.
+ File: pipe/pipe.c.
+
+ Bugfix: with address extensions enabled, canonical and
+ virtual lookups now are done in the proper order:
+ user+foo@domain, user@domain, user+foo, user, @domain.
+ File: global/mail_addr_find.c.
+
+19990119
+
+ Feature: the local mailer now prepends a Received: message
+ header with the queue ID to forwarded mail, in order to
+ make message tracing easier. File: local/forward.c.
+
+ Cleanup: after "postfix reload", no more broken pipe
+ complaints from resolve/rewrite clients.
+
+19990121
+
+ Feature: pickup (again) logs uid and sender address.
+ On repeated request by Scott Cotton, Internet, IC Group, Inc.
+
+ Portability: doze() function for systems without usleep().
+
+ Cleanup: clients are logged as host[address].
+
+19990122
+
+ Maildir support changed: specify "home_mailbox = Maildir/".
+ The magic is the trailing /. Suggested by Daniel Eisenbud,
+ University of California at Berkeley.
+
+ Maildir support from aliases, :include: and .forward files.
+ Specify /file/name/ - the trailing / is required. Suggested
+ by Daniel Eisenbud, University of California at Berkeley.
+
+ Workaround: watchdog timer to prevent the queue manager
+ from locking up on some systems.
+
+ Bugfix: in Received: headers, the "for "
+ information was in the wrong place. Pointed out by Jon
+ Ribbens, Oaktree Internet Solutions Ltd.
diff --git a/postfix/INSTALL b/postfix/INSTALL
new file mode 100644
index 000000000..8404fa4c3
--- /dev/null
+++ b/postfix/INSTALL
@@ -0,0 +1,504 @@
+Purpose of this document
+========================
+
+This document describes how to build, install and configure a
+Postfix system so that it can do one of the following:
+
+ - Send mail only, without changing an existing sendmail
+ installation.
+
+ - Send and receive mail via a virtual host interface, still
+ without any change to an existing sendmail installation.
+
+ - Replace sendmail altogether.
+
+Typographical conventions
+=========================
+
+In the instructions below, a command written as
+
+ # command
+
+should be executed as the superuser.
+
+A command written as
+
+ % command
+
+should be executed as an unprivileged user.
+
+Documentation
+=============
+
+Documentation is available as HTML web pages (point your browser
+to html/index.html) and as UNIX-style manpages (point your MANPATH
+environment variable to the `man' subdirectory; be sure to use an
+absolute path).
+
+The sample configuration files in the `conf' directory have extensive
+comments, but they may not describe every nuance of every feature.
+
+Many files have their own built-in manual page. Tools to extract
+those embedded manual pages are available in the contributed software
+from http://www.postfix.org/
+
+Building on a supported system
+==============================
+
+If your system is supported, it is one of
+
+ AIX 4.1.x
+ AIX 4.2.0
+ BSD/OS 2.x
+ BSD/OS 3.x
+ BSD/OS 4.x
+ FreeBSD 2.x
+ FreeBSD 3.x
+ HP-UX 9.x
+ HP-UX 10.x
+ HP-UX 11.x
+ IRIX 5.x
+ IRIX 6.x
+ Linux Debian 1.3.1
+ Linux Debian 2.x
+ Linux RedHat 4.2
+ Linux RedHat 5.x
+ Linux Slackware 3.5
+ Linux SuSE 5.x
+ NEXTSTEP 3.x
+ NetBSD 1.x
+ OPENSTEP 4.x
+ OSF1.V4 aka Digital UNIX V4
+ OpenBSD 2.x
+ SunOS 4.1.x
+ SunOS 5.4..5.7 (Solaris 2.4..7)
+
+or something closely resemblant. Some platforms such as Ultrix 4
+might work, but that has not been verified. It is sufficiently
+similar to SunOS 4 that my guesses should be mostly right.
+
+Download the contributed software from http://www.postfix.org/ if
+you wish to include support for LDAP (light-weight directory access
+protocol) lookups, for NEXTSTEP version 3 or for OPENSTEP version 4.
+
+If at any time in the build process you get messages like: "make:
+don't know how to ..." you should be able to recover by running
+the following command from the Postfix top-level directory:
+
+ % make -f Makefile.init makefiles
+
+If you copied the Postfix source code after building it on another
+machine, it is a good idea to cd into the top-level directory and
+
+ % make tidy
+
+first. This will get rid of any system dependencies left over from
+compiling the software elsewhere.
+
+To build with GCC, or with the native compiler if people told me
+that is better for your system, just cd into the top-level Postfix
+directory of the source tree and type:
+
+ % make
+
+To build with a non-default compiler, you need to specify the name
+of the compiler:
+
+ % make makefiles CC=/opt/SUNWspro/bin/cc
+ % make
+
+ % make makefiles CC="purify cc"
+ % make
+
+and so on. On some cases, optimization is turned off automatically.
+
+In order to build with non-default settings, for example, with a
+configuration directory other than /etc/postfix, use:
+
+ % make makefiles CCARGS=-DDEF_CONFIG_DIR=\\\\\\\"/some/where\\\\\\\"
+ % make
+
+That's seven backslashes :-) But at least this works with sh and csh.
+
+In any case, if the command
+
+ % make
+
+produces compiler error messages, it may be time to examine the
+FAQ document.
+
+Porting to on an unsupported system
+===================================
+
+- Choose a SYSTEMTYPE name for the new system. Please use a name
+that includes the major version of the operating system (such as
+SUNOS4 or LINUX2), so that different releases of the same system
+can be supported without confusion.
+
+- Add a case statement to the "makedefs" shell script in the
+top-level directory that recognizes the new system reliably, and
+that emits the right system-specific information. Be sure to make
+the code robust against user PATH settings; if the system offers
+multiple UNIX flavors (e.g. BSD and SYSV) be sure to build for the
+native flavor, not the emulated one.
+
+- Add an #ifdef SYSTEMTYPE section to the central util/sys_defs.h
+include file. You may have to invent new feature macros. Please
+choose sensible feature macro names such as HAS_DBM or
+FIONREAD_IN_SYS_FILIO_H. I strongly recommend against #ifdef
+SYSTEMTYPE dependencies in individual source files. This may seem
+to be the quickest solution, but it will create a mess that becomes
+increasingly difficult to maintain over time. Moreover, with the
+next port you'd have to place #ifdefs all over the source code
+again.
+
+Installing the software after successful compilation
+====================================================
+
+There is no automated installation procedure. The Postfix system
+is sufficiently complex, and UNIX systems are sufficiently different,
+that I feel uncomfortable providing an out-of-the-box procedure.
+
+Installing Postfix by hand takes only a few steps.
+
+- Configuration directory. This name is wired into the programs,
+ but it can be overruled by setting the MAIL_CONFIG environment
+ variable. This text assumes that you have chosen the default
+ location.
+
+ As superuser, execute the commands:
+
+ # mkdir /etc/postfix
+ # chmod 755 /etc/postfix
+ # cp /some/where/postfix/conf/* /etc/postfix
+ # chmod 644 /etc/postfix/*
+ # chmod 755 /etc/postfix/postfix-script
+
+ This also installs the LICENSE file, as required.
+
+- Spool directory. The pathname is configurable in /etc/postfix/main.cf.
+ This text assumes that you have chosen the default location.
+
+ As superuser, execute the commands:
+
+ # mkdir /var/spool/postfix
+ # chmod 755 /var/spool/postfix
+
+- Program directory. The pathname is configurable in /etc/postfix/main.cf.
+ I recommend that you install the programs in a separate directory,
+ not in a place that contains other software.
+
+ As superuser, execute the commands:
+
+ # mkdir /some/where/bin
+ # cp bin/* /some/where/bin
+
+ Alternative 1: leave the programs in the Postfix source tree.
+
+ Alternative 2: use separate program and daemon directories (again,
+ configurable in /etc/postfix/main.cf):
+
+ # mkdir /some/where/sbin /some/where/libexec
+ # cp bin/sendmail bin/post* /some/where/sbin
+ # cp `ls bin/*|egrep -v 'post|fsstone|smtp-|sendmail'` /some/where/libexec
+
+- On-line manual pages:
+
+ # mkdir /some/where/man
+ # (cd man; tar cf - .) | (cd /some/where/man; tar xvf -)
+
+ Alternative: leave the manpages in the Postfix source tree.
+
+ You may wish to update your MANPATH so you can view the Postfix
+ manual pages. For example:
+
+ # export MANPATH
+ # MANPATH=/some/where/man:/usr/share/man:/usr/local/man
+
+- Next, review the "To chroot or not to chroot" section, and proceed
+ to the section on how you wish to run Postfix on your particular
+ machine:
+
+ - Send mail only, without changing an existing sendmail
+ installation.
+
+ - Send and receive mail via a virtual host interface, still
+ without any change to an existing sendmail installation.
+
+ - Replace sendmail altogether.
+
+To chroot or not to chroot
+==========================
+
+Most Postfix daemons can run in a chroot jail, that is, in a chroot
+environment at fixed low privilege. This provides a significant
+barrier against intrusion. The barrier is not impenetrable, but
+every little bit helps.
+
+The file /etc/postfix/master.cf by default runs no Postfix daemons
+in a chroot jail. However, with the exception of the `local' and
+`pipe' daemons, every Postfix daemon can run chrooted.
+
+- The contributed source code from http://www.postfix.org/ has
+ scripts for setting up chroot environments for Postfix systems.
+
+Configuring Postfix to send mail only
+=====================================
+
+If you are going to use Postfix to send mail only, there is no need
+to change your sendmail setup. Instead, set up your mail user agent
+so that it calls the Postfix sendmail program directly.
+
+Follow the instructions in the "Mandatory configuration file edits"
+section below.
+
+You must comment out the smtp inet service in /etc/postfix/master.cf,
+in order to avoid conflicts with the sendmail daemon.
+
+Start the Postfix system:
+
+ # postfix start
+
+or, if you feel nostalgic,
+
+ # /some/where/bin/sendmail -bd -qwhatever
+
+and watch your syslog file for any error messages.
+
+When it is run for the first time, the Postfix startup shell script
+will create a bunch of subdirectories below the Postfix spool
+directory.
+
+In order to inspect the mail queue, use
+
+ % /some/where/bin/sendmail -bp
+
+See also the "Care and feeding" section below.
+
+Configuring Postfix to send and receive mail (virtual interface)
+================================================================
+
+Alternatively, you can use the Postfix system to send AND receive
+mail while leaving your sendmail setup intact, by running Postfix
+on a virtual interface address. Simply configure your mail user
+agent to directly invoke the Postfix sendmail program.
+
+The contributed source code from http://www.postfix.org/ gives
+examples for setting up virtual interfaces for a variety of UNIX
+versions.
+
+In the /etc/postfix/main.cf file, I would specify
+
+ myhostname = virtual.host.name
+ inet_interfaces = $myhostname
+ mydestination = $myhostname
+
+You still have to do the "Mandatory configuration file edits"
+described below. After those edits, start the mail system:
+
+ # /some/where/bin/postfix start
+
+or, if you feel nostalgic,
+
+ # /some/where/bin/sendmail -bd -qwhatever
+
+and watch your syslog file for any error messages.
+
+When it is run for the first time, the Postfix startup shell script
+will create a bunch of subdirectories below the Postfix spool
+directory.
+
+In order to inspect the mail queue, use
+
+ % /some/where/bin/sendmail -bp
+
+See also the "Care and feeding" section below.
+
+Turning off sendmail forever
+============================
+
+If you are going to REPLACE sendmail by Postfix, execute the
+following commands. The text assumes that your sendmail is in
+/usr/sbin, and that mailq and newaliases are in /usr/bin.
+
+First, move the existing sendmail, mailq and newaliases commands
+out of the way:
+
+ # mv /usr/sbin/sendmail /usr/sbin/sendmail.OFF
+ # mv /usr/bin/mailq /usr/bin/mailq.OFF
+ # mv /usr/bin/newaliases /usr/bin/newaliases.OFF
+ # chmod 555 /usr/sbin/sendmail.OFF /usr/bin/mailq.OFF \
+ /usr/bin/newaliases.OFF
+
+Then, drop in the new Postfix sendmail and support programs, and
+set up links for the mailq and newaliases commands:
+
+ # ln -s /some/where/bin/sendmail /some/where/bin/post* /usr/sbin
+ # chmod 755 /usr/sbin/sendmail /usr/sbin/post*
+ # ln -s /usr/sbin/sendmail /usr/bin/mailq
+ # ln -s /usr/sbin/sendmail /usr/bin/newaliases
+
+Be sure to keep the old sendmail running for at least a couple
+days to flush any unsent mail.
+
+After you have visited the "Mandatory configuration file edits"
+section below, you can start the Postfix system with
+
+ # postfix start
+
+But the good old sendmail way works just as well:
+
+ # sendmail -bd -qwhatever
+
+and watch the syslog file for any complaints from the mail system.
+
+When it is run for the first time, the Postfix startup shell script
+will create a bunch of subdirectories below the Postfix spool
+directory.
+
+See also the "Care and feeding" section below.
+
+Mandatory configuration file edits
+==================================
+
+By default, all Postfix configuration files are in /etc/postfix, and
+must be owned by root.
+
+Whenever you make a change to a config file, execute the following
+command in order to refresh a running mail system:
+
+ # postfix reload
+
+In /etc/postfix/main.cf you will have to set up a minimal number of
+configuration parameters. Postfix configuration parameters
+resemble shell variables. You specify a variable as
+
+ parameter = value
+
+and you use it by putting a $ in front of it:
+
+ other_parameter = $parameter
+
+You can use $parameter before it is given a value. The Postfix
+configuration language uses lazy evaluation, and does not look at
+a parameter value until it is needed at runtime.
+
+First of all you have to specify the userid that owns the Postfix
+queue and processes. The default setting,
+
+ mail_owner = postfix
+
+should be appropriate for your system. I would recommend that you
+create a dedicated user account "postfix", that is not in the same
+group as other accounts. Make sure it is a locked account that
+no-one can log into. It does not need an executable login shell,
+nor does it need an existing home directory.
+
+Secondly, you should specify what domain name will be appended to
+a local address. The "myorigin" parameter defaults to the local
+hostname, but that is probably OK only for very small sites.
+
+Some examples:
+
+ myorigin = $myhostname
+ myorigin = $mydomain
+
+In the first case, local mail goes out as user@$myhostname, in
+the second case the sender address is user@$mydomain.
+
+Next you nee to specify what mail addresses are local to the Postfix
+system.
+
+Some examples:
+
+ mydestination = $myhostname, localhost.$mydomain
+ mydestination = $myhostname, localhost.$mydomain, $mydomain
+ mydestination = $myhostname
+
+The first example is appropriate for a workstation, the second is
+appropriate for the mailserver for an entire domain. The third
+example should be used when running on a virtual host interface.
+
+If you're behind a firewall, you should set up a relayhost. If
+you can, specify the organizational domain name so that Postfix
+can use DNS lookups, and so that it can fall back to a secondary
+MX host when the primary MX host is down. Otherwise just specify
+a hard-coded hostname.
+
+Some examples:
+
+ relayhost = $mydomain
+ relayhost = mail.$mydomain
+
+If you haven't used sendmail prior to using Postfix, you will have
+to build the alias database (with: sendmail -bi, or: newaliases).
+
+Finally, specify the program and queue directories.
+
+ program_directory = /some/where/bin
+ queue_directory = /var/spool/postfix
+
+For further configuration information I suggest that you browse
+the configuration documentation in the html subdirectory.
+
+Security: writable versus protected maildrop directory
+======================================================
+
+Postfix offers a choice of submission mechanims.
+
+1 - Postfix can use a world-writable, sticky, mode 1733 maildrop
+ directory where local users can submit mail. This approach
+ avoids the need for set-uid or set-gid software. Mail can be
+ posted even while the mail system is down. Queue files in the
+ maildrop directory have no read/write/execute permission for
+ other users. The maildrop directory is not used for mail
+ received via the network.
+
+ With directory world write permission come opportunities for
+ annoyance: a local user can make hard links to someone else's
+ maildrop files so they don't go away and may be delivered
+ multiple times; a local user can fill the maildrop directory
+ with junk and try to crash the mail system; and a local user
+ can hard link someone else's files into the maildrop directory
+ and try to have them delivered as mail. However, Postfix queue
+ files have a specific format; less than one in 10^12 non-Postfix
+ files would be recognized as a valid Postfix queue file.
+
+ In order to enable this mode, step into /etc/postfix and:
+
+ # cp postfix-script-nosgid postfix-script
+
+2 - On systems with many users it may be desirable to revoke maildrop
+ directory world write permission, and to enable set-gid privileges
+ on a small "postdrop" command that is provided for this purpose.
+
+ In order to revoke world-write permission, create a group
+ "maildrop" that is unique and that does not share its group ID
+ with any other user, certainly not with the postfix account,
+ then execute the following commands to make "postdrop" set-gid,
+ and to make maildrop non-writable for unprivileged users:
+
+ # chgrp maildrop /var/spool/postfix/maildrop /some/where/postdrop
+ # chmod 730 /var/spool/postfix/maildrop
+ # chmod 2755 /some/where/postdrop
+
+ The sendmail posting program will automatically invoke the
+ postdrop command when maildrop directory write permission is
+ restricted.
+
+ In order to enable this mode, step into /etc/postfix and:
+
+ # cp postfix-script-sgid postfix-script
+
+Care and feeding of the Postfix system
+======================================
+
+The Postfix programs log all problems to the syslog daemon.
+Hopefully, the number of problems will be small, but it is a good
+idea to run every night before the syslog files are rotated:
+
+ # postfix check
+ # egrep '(reject|warning|error|fatal|panic):' /some/log/file
+
+The second line looks for problem reports from the mail software,
+and reports how effective the anti-relay and anti-UCE blocks are.
diff --git a/postfix/LICENSE b/postfix/LICENSE
new file mode 100644
index 000000000..5e83ceb25
--- /dev/null
+++ b/postfix/LICENSE
@@ -0,0 +1,59 @@
+Please read this carefully. You must agree to the following terms and
+conditions before installing the Secure Mailer or any related
+documentation ("Software"). If you do not agree to these terms
+and conditions, you may not install or use the Software.
+
+Permission to reproduce and create derivative works from the Software
+("Software Derivative Works") is hereby granted to you under the
+copyrights of International Business Machines Corporation ("IBM"). IBM
+also grants you the right to distribute the Software and Software
+Derivative Works.
+
+You grant IBM a world-wide, royalty-free right to use, copy,
+distribute, sublicense and prepare derivative works based upon any
+feedback, including materials, error corrections, Software Derivatives,
+enhancements, suggestions and the like that you provide to IBM relating
+to the Software.
+
+IBM licenses the Software to you on an "AS IS" basis, without warranty
+of any kind. IBM HEREBY EXPRESSLY DISCLAIMS ALL WARRANTIES OR
+CONDITIONS, EITHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OR CONDITIONS OF MERCHANTABILITY, NON
+INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE. You are solely
+responsible for determining the appropriateness of using this Software
+and assume all risks associated with the use and distribution of this
+Software, including but not limited to the risks of program errors,
+damage to or loss of data, programs or equipment, and unavailability or
+interruption of operations. IBM WILL NOT BE LIABLE FOR ANY DIRECT
+DAMAGES OR FOR ANY SPECIAL, INCIDENTAL, OR INDIRECT DAMAGES OR FOR ANY
+ECONOMIC CONSEQUENTIAL DAMAGES (INCLUDING LOST PROFITS OR SAVINGS),
+EVEN IF IBM HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. IBM
+will not be liable for the loss of, or damage to, your records or data,
+or any damages claimed by you based on a third party claim. You may
+not use the name "IBM" or any other IBM trademark without the prior
+written consent of IBM.
+
+You agree to distribute the Software and any Software Derivatives under
+a license agreement that: 1) is sufficient to notify all licensees of
+the Software and Software Derivatives that IBM assumes no liability for
+any claim that may arise regarding the Software or Software
+Derivatives, and 2) that disclaims all warranties, both express and
+implied, from IBM regarding the Software and Software Derivatives. (If
+you include this Agreement with any distribution of the Software or
+Software Derivatives you will have met this requirement.) You agree
+that you will not delete any copyright notices in the Software.
+
+In the event an intellectual property claim is made or appears likely
+to be made with respect to the Software, you agree to permit IBM to
+enable you to continue to use the Software, or to modify it, or replace
+it with software that is at least functionally equivalent. If IBM
+determines that none of these alternatives is reasonably available, you
+agree, at IBM's request, upon notice to you, to discontinue further
+distribution of the Software and to delete or destroy all copies of the
+Software you possess. This is IBM's entire obligation to you regarding
+any claim of infringement.
+
+This Agreement is the exclusive statement of your rights in the
+Software as provided by IBM. Except for the licenses granted to you in
+the second paragraph above, no other licenses are granted hereunder, by
+estoppel, implication or otherwise.
diff --git a/postfix/Makefile b/postfix/Makefile
new file mode 100644
index 000000000..424db7120
--- /dev/null
+++ b/postfix/Makefile
@@ -0,0 +1,18 @@
+# Usage:
+# make makefiles [CC=compiler] [OPT=compiler-flags] [DEBUG=debug-flags]
+#
+# The defaults are: CC=gcc, OPT=-O, and DEBUG=-g. Examples:
+#
+# make makefiles
+# make makefiles CC="purify cc"
+# make makefiles CC=cc OPT=
+#
+SHELL = /bin/sh
+
+default: update
+
+update depend printfck clean tidy depend_update: Makefiles
+ $(MAKE) $@
+
+makefiles Makefiles:
+ $(MAKE) -f Makefile.in Makefiles
diff --git a/postfix/Makefile.in b/postfix/Makefile.in
new file mode 100644
index 000000000..e718d0104
--- /dev/null
+++ b/postfix/Makefile.in
@@ -0,0 +1,42 @@
+SHELL = /bin/sh
+WARN = -Wmissing-prototypes
+OPTS = "CC=$(CC)"
+DIRS = util global dns master postfix smtpstone fsstone sendmail \
+ pickup cleanup smtpd local trivial-rewrite qmgr smtp bounce pipe \
+ showq postalias postcat postconf postdrop postkick postlock postlog \
+ postmap # man html
+
+default: update
+
+makefiles Makefiles:
+ set -e; for i in $(DIRS); do \
+ (set -e; echo "[$$i]"; cd $$i; rm -f Makefile; \
+ $(MAKE) -f Makefile.in Makefile); \
+ done;
+ rm -f Makefile; (set -e; sh makedefs; cat Makefile.in) >Makefile
+
+update printfck:
+ set -e; for i in $(DIRS); do \
+ (set -e; echo "[$$i]"; cd $$i; $(MAKE) $(OPTS) $@) || exit 1; \
+ done
+
+depend clean:
+ set -e; for i in $(DIRS); do \
+ (set -e; echo "[$$i]"; cd $$i; $(MAKE) $@) || exit 1; \
+ done
+
+depend_update:
+ set -e; for i in $(DIRS); do \
+ (set -e; echo "[$$i]"; cd $$i; $(MAKE) depend && $(MAKE) $(OPTS) update) \
+ || exit 1; \
+ done
+
+tidy: clean
+ rm -f Makefile */Makefile
+ cp Makefile.init Makefile
+ -rm -f *core */*core .nfs* .pure bin/* lib/* include/* */.nfs* */.pure \
+ *.out */*.out */*.db */*.a *~ */*~ *- */*- *.orig */*.orig *.bak \
+ */*.bak make.err
+ find . -type s -print | xargs rm -f
+ find . -type d -print | xargs chmod 755
+ find . -type f -print | xargs chmod a+r
diff --git a/postfix/Makefile.init b/postfix/Makefile.init
new file mode 100644
index 000000000..424db7120
--- /dev/null
+++ b/postfix/Makefile.init
@@ -0,0 +1,18 @@
+# Usage:
+# make makefiles [CC=compiler] [OPT=compiler-flags] [DEBUG=debug-flags]
+#
+# The defaults are: CC=gcc, OPT=-O, and DEBUG=-g. Examples:
+#
+# make makefiles
+# make makefiles CC="purify cc"
+# make makefiles CC=cc OPT=
+#
+SHELL = /bin/sh
+
+default: update
+
+update depend printfck clean tidy depend_update: Makefiles
+ $(MAKE) $@
+
+makefiles Makefiles:
+ $(MAKE) -f Makefile.in Makefiles
diff --git a/postfix/PORTING b/postfix/PORTING
new file mode 100644
index 000000000..46df4486f
--- /dev/null
+++ b/postfix/PORTING
@@ -0,0 +1,23 @@
+In order to port software to a new platform:
+
+- Choose a SYSTEMTYPE name for the new system. Please use a name
+that includes the major version of the operating system (such as
+SUNOS4 or LINUX2), so that different releases of the same system
+can be supported without confusion.
+
+- Add a case statement to the "makedefs" shell script in the
+top-level directory that recognizes the new system reliably, and
+that emits the right system-specific information. Be sure to make
+the code robust against user PATH settings; if the system offers
+multiple UNIX flavors (e.g. BSD and SYSV) be sure to build for the
+native flavor, not the emulated one.
+
+- Add an #ifdef SYSTEMTYPE section to the central util/sys_defs.h
+include file. You may have to invent new feature macros. Please
+choose sensible feature macro names such as HAS_DBM or
+FIONREAD_IN_SYS_FILIO_H. I strongly recommend against #ifdef
+SYSTEMTYPE dependencies in individual source files. This may seem
+to be the quickest solution, but it will create a mess that becomes
+increasingly difficult to maintain over time. Moreover, with the
+next port you'd have to place #ifdefs all over the source code
+again.
diff --git a/postfix/RELEASE_NOTES b/postfix/RELEASE_NOTES
new file mode 100644
index 000000000..be41fe925
--- /dev/null
+++ b/postfix/RELEASE_NOTES
@@ -0,0 +1,62 @@
+This release introduces lots of new functionality in response to feedback
+from users.
+
+Incompatible changes:
+=====================
+
+- The syntax of the transport table has changed. An entry like:
+
+ customer.org smtp:[gateway.customer.org]
+
+ no longer forwards mail for anything.customer.org. For that you
+ need to specify:
+
+ customer.org smtp:[gateway.customer.org]
+ .customer.org smtp:[gateway.customer.org]
+
+ This change makes tranport tables more compatible with
+ sendmail mailer tables.
+
+- The format of syslog records has changed. A client is now always
+logged as hostname[address]; the pickup daemon logs queue file uid
+and sender address.
+
+Major changes over the previous version:
+========================================
+
+- Junk mail restrictions can now be postoned to the RCPT TO command.
+Specify: "smtpd_recipient_restrictions = reject_maps_rbl...".
+
+- More flexible interface for delivery to e.g., cyrus IMAP without
+need for PERL scripts to munge recipient addresses. In addition to
+$sender, $nexthop and $recipient, the pipe mailer now also supports
+$user, $extension and $mailbox.
+
+- New mail now has precedence over deferred mail, plus some other
+tweaks to make bulk mail go faster. But it ain't no cure for massive
+network outages.
+
+- Watchdog timer for systems that cause the Postfix queue manager
+to lock up, so it recovers without human intervention.
+
+- Delivery to qmail-style maildir files, which is good for NFS
+environments. Specify "home_mailbox = Maildir/", or specify
+/file/name/ in aliases or in .forward files. The trailing / is
+required to turn on maildir delivery.
+
+- Incremental updates of aliases and maps. Specify "postmap -i
+mapname" and it will read new entries from stdin.
+
+- Newaliases will now update more than one alias database.
+Specify the names with the main.cf "alias_database" parameter.
+
+- Address masquerading exceptions to prevent users from being
+masqueraded. Specify "masquerade_exceptions = root".
+
+- A pipelined SMTP client. Deliveries to Postfix, qmail, LSOFT,
+zmailer, and exim (once it's fixed) speed up by some 30% for short
+messages with one recipient, with more for multi-recipient mails.
+
+- Hook for local delivery to "|command" via the smrsh restricted
+shell, to restrict what commands may be used in .forward etc. files.
+Specify "local_command_shell = /some/where/smrsh -c".
diff --git a/postfix/TODO b/postfix/TODO
new file mode 100644
index 000000000..280c4c224
--- /dev/null
+++ b/postfix/TODO
@@ -0,0 +1,274 @@
+
+one queue per rcpt hurts when delivering to agents that don't
+get stuck on shell commands or mailbox locks
+
+xxx: bounced as yyy (bounced mail); xxx forwarded as zzz (mail
+expanded via :include:).
+
+postconf -f filename
+
+more general relocated feature - perhaps better to bounce recipients
+at the SMTP port.
+
+use $mydomain when hostname is not FQDN.
+
+generic daemon that listens on fifo and runs command
+
+make sendmail/smtpd/cleanup output directory/fifo configurable
+
+if postdrop scrutinizes input, skip the overhead in the pickup
+daemon.
+
+luser relay
+
+add a threshold to sendmail etc. stderr logging, so that class
+"info" messages don't go to stderr.
+
+need a configurable mailbox locking method with system-specific
+default, so people don't have to recompile just to turn of fcntl()
+locks to work around SUN mailtool.
+
+implement an UCE control to accept mail if the sender domain sender
+lists us as MX host (rafal wiosna). By the same token, implement
+a control to accept mail when the client hostname/parent domain
+lists us as their MX host.
+
+with recipient delimiter enabled, append the unmatched recipient
+of @virtual.domain patterns as extension to right-hand recipient,
+for qmail-like virtual mapping.
+
+received: headers should be generated by the cleanup daemon, and
+client attributes ("with", "from", etc.) should be passed along
+with the message. This guarantees that forwarded/aliased mail gets
+stamped with the queue ID.
+
+trivial-rewrite etc.: after reload, close the listen socket and
+wait until all clients disconnect.
+
+In qmgr_entry.c, turn off random walk by default.
+
+toss double-bounce mail even when mail for the local machine is
+redirected to another box. See mail_addr_double_bounce().
+
+represent peer as object, not as name + addr arguments
+
+ignore sender: header when different from envelope?
+
+smtp client: optionally log every MX host contacted
+
+remote showq access (cookie in maildrop or print some text to inform
+the user)
+
+defer: explain mail was bounced after N days
+
+multiple rewrite processes?
+
+log relay address in addition to host.
+
+gethostbyaddr() uses native name services, which can be slow.
+
+can we detect a client that ignores error responses?
+
+way to block inbound mail based on recipient suffix?
+
+when client begins with non-SMTP data, log warning
+
+when non-SMTP follows ".", log warning.
+
+On linux syslogd needs -/file/name
+
+can Postfix implement one switchboard instead of having all these
+little lookup tables?
+
+make canonical/virtual/etc. table lookup order configurable
+
+allow /file/name or maptype_mapname in $mydestination
+
+make protocol errors soft errore? There are a lot of broken mailers
+out there that sometimes croak and sometimes work.
+
+require @ in sender/rcpt (another restriction)
+
+figure out a way to pump recipients into qmgr before concurrency
+starts to drop.
+
+pass on client etc/ attributes along with message to delivery agent
+
+pass on configurable info into external process environment
+
+scrutinize file opens in delivery agents just like in qmgr (better:
+open the file and see if someone compromised the vmailer account
+and is racing against us).
+
+cleanup: don't run out of memory with large amounts of bcc addresses
+
+cleanup: permit non-empty extra segment, so that mail posting
+software can pass in bcc recipients.
+
+suspend/resume signals + master status (suspended/running) in PID
+file. Maybe use FIFO instead. But, that means requests do not
+arrive when the master is stuck.
+
+postedit queue-id command...
+
+more flexible mail queue list command
+
+multiple queues may make ETRN processing less painful because there
+is less delayed mail to plow through.
+
+qmgr: configurable incoming/deferred mixing ratio so we can prioritize
+new mail over old mail
+
+Replace [my.own.ip.addr] by domain name so that delivered-to has
+the desired effect.
+
+Received: header and bounce text will be configurable with ${name}
+macros. This requires that everything must cope with newlines in
+config parameters (including the SMTP greeting bannner, yuck).
+
+Pass along the client hostname/posting user with queue files, to
+be logged by the queue manager.
+
+showq: don't use mail_open_ok() - it assumes coordinated queue
+access.
+
+trivial-rewrite: optionally, use DNS to fully qualify hostnames.
+
+smtp: optionally deal with MX records containing an address instead
+of a name.
+
+pickup/cleanup/qmgr/local: add options record to control internal
+features such as canonical/virtual mapping, VERPs etcetera.
+
+smtpd: when deciding if a destination is local, also look at the
+virtual map. Perhaps we should move canonical and virtual lookups
+back into the rewrite service, but under a different name, so they
+do not get in the way if we do not want them.
+
+Queue manager: do not allocate queue slots when a destination
+already has more than some threshold. This is to prevent a dead or
+slow destination from filling up the queue manager's active queue,
+preventing delivery to other destinations. However, such `fairness'
+strategies should not cause Postfix to lose the benchmark race, so
+we must be fair and smart at the same time :-)
+
+Add hook for (domain, user database) support. This is needed if
+you have lots of real domains and can't afford a separate master.cf
+delivery agent entry for each domain.
+
+Add support for DBZ databases, using the code from INN. Reportedly,
+GDB handles large numbers of keys poorly.
+
+Make the number of time bits in the queue ID configurable, or at
+least a little larger.
+
+Change the front-end to cleanup protocol so that the front-end
+sends the expected message size, and so that the cleanup service
+can report if there is enough space. This is useful only for the
+SMTP server, because pickup can't produce bounce requests: the
+bounce service can't read the maildrop file.
+
+On systems with functional UNIX-domain sockets, use that instead
+of FIFOs to trigger the pickup and qmgr services. This allows for
+some coupling between front-end programs and queue manager, so that
+a burst of inbound mail does not lock out the queue manager from
+accessing the queue, causing outbound delivery to stop.
+
+There is a need to run `master' services outside the "master"
+environment, either for testing (new config files) or for production.
+For consistency reasons, programs file names should be taken from
+the master.cf file.
+
+ - The showq service. Used by the super user when the mail system
+ is down.
+
+ - The smtpd service for "sendmail -bs" emulation. Used by some
+ mail posting agents. Output to the maildrop, so that messages
+ can be posted even when the mail system is down.
+
+ - The rewrite engine for "sendmail -bt" emulation, for off-line
+ testing of configuration files. Requires a method to override
+ the location of the rewriting rules file. Or, perhaps there
+ should be an official place (/etc/vmailer/testbed?) for playing
+ with config files.
+
+postfix-script: detect and/or build missing alias database. In
+order to do this we must extract the alias_maps parameter from the
+main.cf file, and create any missing files with the right ownerships.
+
+SunOS 5.4 sendmail seems to include the null byte in alias keys
+and values, like almost every UNIX system; SunOS 5.5 sendmail does
+not include these nulls. Need to add support for SunOS 5.4. NIS
+alias maps always include the null terminator...
+
+implement the return-receipt-to notification service.
+
+Implement real address rewriting.
+
+default alias for mail to non-existent users. How useful is this
+when the postmaster already gets notices of mail that could not be
+delivered by the local mail system? And how do we pass around the
+original envelope recipient once it has been "aliased" to the
+address for non-existent users?
+
+owner-default alias to capture all mailing list errors. Or perhaps
+they should just set up the appropriate owner-foo aliases in their
+alias database?
+
+make mail_params module the main config interface; no calls from
+config.c to routines in mail_params.c
+
+resolve/rewrite clients should share connection
+
+postfix-script: make sure permissions of queue (and anything below)
+are sane.
+
+bounce/defer: provide attribute-value interface, for better logging
+(expanded-from etc.) and non-delivery reports.
+
+Postfix-Options: header, to turn on qmail-like VERPs. But, these
+must be accessible only for locally-posted mail (not mail that
+arrives via UUCP).
+
+Maintain per-client short-term host status, so we can slow down
+unreasonable clients
+
+Make archiving delivered mail a REAL option (queue manager). What
+about one archive per day. The magic could be put into the mail
+queue name routines. Just make it aware of the date.
+
+Will the mail system be faster when we avoid moving new messages
+incoming->active? How would one detect the arrival of new files?
+
+pickup: pass file descriptor to cleanup instead of copying data.
+This violates the principle that all front-end programs protect
+the mail system against unreasonably-long inputs.
+
+True ETRN means kick the host out of the queue manager's "dead
+hosts" table & move mail from the "hold" queue for that site to
+the incoming queue.
+
+Option to make a copy of all mail passing through the mail system.
+
+The message ID is built by concatenating the time of day in seconds
+with the queue id. We must ensure that a queue id is unique for at
+least one second, otherwise multiple messages will have the same
+message ID. Queue ids will always collide after a while. The NFS
+generation number for the queue file would be useful, but there is
+no portable interface to get it, and we cannot depend on the system
+having NFS support enabled. If a 1-microsecond resolution is
+sufficient, we could compose the queue ID from the inode number
+plus 6 decimal digits or 5 hex ones for the time in microseconds.
+Or, use a smarter encoding with more bits per character.
+
+postfix-script: make sure that each queue file matches its file id
+or we might lose mail.
+
+postfix-script: do database fixups as the unprivileged user
+
+Put a version file in the conf directory or add option to vmail
+control command to print the version (requires vmconf tool that
+can query main.cf.).
+
+Maintain a pool of pre-allocated queue files, to eliminate file
+creation and deletion overhead.
diff --git a/postfix/bin/.keep b/postfix/bin/.keep
new file mode 100644
index 000000000..e69de29bb
diff --git a/postfix/bounce/.indent.pro b/postfix/bounce/.indent.pro
new file mode 100644
index 000000000..e59d396ad
--- /dev/null
+++ b/postfix/bounce/.indent.pro
@@ -0,0 +1,89 @@
+-TALIAS_TOKEN
+-TARGV
+-TBH_TABLE
+-TBINHASH
+-TBINHASH_INFO
+-TBOUNCE_STAT
+-TCLEANUP_STATE
+-TCLIENT_LIST
+-TCONFIG_BOOL_FN_TABLE
+-TCONFIG_BOOL_TABLE
+-TCONFIG_INT_FN_TABLE
+-TCONFIG_INT_TABLE
+-TCONFIG_STR_FN_TABLE
+-TCONFIG_STR_TABLE
+-TDELIVER_ATTR
+-TDELIVER_REQUEST
+-TDICT
+-TDICT_DB
+-TDICT_DBM
+-TDICT_ENV
+-TDICT_HT
+-TDICT_LDAP
+-TDICT_NI
+-TDICT_NIS
+-TDICT_NISPLUS
+-TDICT_NODE
+-TDICT_OPEN_INFO
+-TDNS_FIXED
+-TDNS_REPLY
+-TDNS_RR
+-TDOMAIN_LIST
+-TEXPAND_ATTR
+-TFILE
+-TFORWARD_INFO
+-THEADER_OPTS
+-THTABLE
+-THTABLE_INFO
+-TINET_ADDR_LIST
+-TINT_TABLE
+-TLOCAL_STATE
+-TMAC_HEAD
+-TMAC_PARSE
+-TMAIL_PRINT
+-TMAIL_SCAN
+-TMAPS
+-TMASTER_PROC
+-TMASTER_SERV
+-TMASTER_STATUS
+-TMBLOCK
+-TMKMAP
+-TMKMAP_OPEN_INFO
+-TMULTI_SERVER
+-TMVECT
+-TNAMADR_LIST
+-TNAME_MASK
+-TPEER_NAME
+-TPICKUP_INFO
+-TPIPE_ATTR
+-TPIPE_PARAMS
+-TQMGR_ENTRY
+-TQMGR_MESSAGE
+-TQMGR_QUEUE
+-TQMGR_RCPT_LIST
+-TQMGR_RECIPIENT
+-TQMGR_SCAN
+-TQMGR_TRANSPORT
+-TRECIPIENT
+-TRECIPIENT_LIST
+-TREC_TYPE_NAME
+-TRESOLVE_REPLY
+-TSCAN_DIR
+-TSINGLE_SERVER
+-TSMTPD_STATE
+-TSMTPD_TOKEN
+-TSMTP_ADDR
+-TSMTP_CMD
+-TSMTP_RESP
+-TSMTP_SESSION
+-TSMTP_STATE
+-TSOCKADDR_SIZE
+-TSTRING_TABLE
+-TSYS_EXITS_TABLE
+-TTOK822
+-TTRIGGER_SERVER
+-TUSER_ATTR
+-TVBUF
+-TVSTREAM
+-TVSTRING
+-TWAIT_STATUS_T
diff --git a/postfix/bounce/.printfck b/postfix/bounce/.printfck
new file mode 100644
index 000000000..9ed900cb0
--- /dev/null
+++ b/postfix/bounce/.printfck
@@ -0,0 +1,24 @@
+been_here_xt 2 0
+bounce_append 5 0
+cleanup_out_format 1 0
+defer_append 5 0
+mail_command 1 0
+mail_print 1 0
+msg_error 0 0
+msg_fatal 0 0
+msg_info 0 0
+msg_panic 0 0
+msg_warn 0 0
+opened 3 0
+qmgr_message_bounce 2 0
+rec_fprintf 2 0
+sent 4 0
+smtp_cmd 1 0
+smtp_mesg_fail 2 0
+smtp_printf 1 0
+smtp_rcpt_fail 3 0
+smtp_site_fail 2 0
+udp_syslog 1 0
+vstream_fprintf 1 0
+vstream_printf 0 0
+vstring_sprintf 1 0
diff --git a/postfix/bounce/Makefile.in b/postfix/bounce/Makefile.in
new file mode 100644
index 000000000..3279399a6
--- /dev/null
+++ b/postfix/bounce/Makefile.in
@@ -0,0 +1,121 @@
+SHELL = /bin/sh
+SRCS = bounce.c bounce_append_service.c bounce_flush_service.c \
+ bounce_cleanup.c
+OBJS = bounce.o bounce_append_service.o bounce_flush_service.o \
+ bounce_cleanup.o
+HDRS =
+TESTSRC =
+WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
+ -Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
+ -Wunused
+DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
+CFLAGS = $(DEBUG) $(OPT) $(DEFS)
+TESTPROG=
+PROG = bounce
+INC_DIR = ../include
+LIBS = ../lib/libmaster.a ../lib/libglobal.a ../lib/libutil.a
+
+.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) sh ../makedefs; cat $?) >$@
+
+test: $(TESTPROG)
+
+update: ../bin/$(PROG)
+
+../bin/$(PROG): $(PROG)
+ cp $(PROG) ../bin
+
+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
+
+# do not edit below this line - it is generated by 'make depend'
+bounce.o: bounce.c
+bounce.o: ../include/sys_defs.h
+bounce.o: ../include/msg.h
+bounce.o: ../include/vstring.h
+bounce.o: ../include/vbuf.h
+bounce.o: ../include/vstream.h
+bounce.o: ../include/stringops.h
+bounce.o: ../include/mail_proto.h
+bounce.o: ../include/iostuff.h
+bounce.o: ../include/mail_queue.h
+bounce.o: ../include/mail_params.h
+bounce.o: ../include/config.h
+bounce.o: ../include/bounce.h
+bounce.o: ../include/mail_server.h
+bounce.o: bounce_service.h
+bounce_append_service.o: bounce_append_service.c
+bounce_append_service.o: ../include/sys_defs.h
+bounce_append_service.o: ../include/msg.h
+bounce_append_service.o: ../include/vstring.h
+bounce_append_service.o: ../include/vbuf.h
+bounce_append_service.o: ../include/vstream.h
+bounce_append_service.o: ../include/stringops.h
+bounce_append_service.o: ../include/mail_queue.h
+bounce_append_service.o: ../include/quote_822_local.h
+bounce_append_service.o: ../include/deliver_flock.h
+bounce_append_service.o: bounce_service.h
+bounce_cleanup.o: bounce_cleanup.c
+bounce_cleanup.o: ../include/sys_defs.h
+bounce_cleanup.o: ../include/msg.h
+bounce_cleanup.o: ../include/mymalloc.h
+bounce_cleanup.o: ../include/vstring.h
+bounce_cleanup.o: ../include/vbuf.h
+bounce_cleanup.o: ../include/mail_queue.h
+bounce_cleanup.o: ../include/vstream.h
+bounce_cleanup.o: bounce_service.h
+bounce_flush_service.o: bounce_flush_service.c
+bounce_flush_service.o: ../include/sys_defs.h
+bounce_flush_service.o: ../include/msg.h
+bounce_flush_service.o: ../include/vstring.h
+bounce_flush_service.o: ../include/vbuf.h
+bounce_flush_service.o: ../include/vstream.h
+bounce_flush_service.o: ../include/vstring_vstream.h
+bounce_flush_service.o: ../include/mymalloc.h
+bounce_flush_service.o: ../include/stringops.h
+bounce_flush_service.o: ../include/events.h
+bounce_flush_service.o: ../include/line_wrap.h
+bounce_flush_service.o: ../include/name_mask.h
+bounce_flush_service.o: ../include/mail_queue.h
+bounce_flush_service.o: ../include/mail_proto.h
+bounce_flush_service.o: ../include/iostuff.h
+bounce_flush_service.o: ../include/quote_822_local.h
+bounce_flush_service.o: ../include/mail_params.h
+bounce_flush_service.o: ../include/canon_addr.h
+bounce_flush_service.o: ../include/is_header.h
+bounce_flush_service.o: ../include/record.h
+bounce_flush_service.o: ../include/rec_type.h
+bounce_flush_service.o: ../include/config.h
+bounce_flush_service.o: ../include/post_mail.h
+bounce_flush_service.o: ../include/cleanup_user.h
+bounce_flush_service.o: ../include/mail_addr.h
+bounce_flush_service.o: ../include/mark_corrupt.h
+bounce_flush_service.o: ../include/mail_error.h
+bounce_flush_service.o: bounce_service.h
diff --git a/postfix/bounce/bounce.c b/postfix/bounce/bounce.c
new file mode 100644
index 000000000..1698130d7
--- /dev/null
+++ b/postfix/bounce/bounce.c
@@ -0,0 +1,281 @@
+/*++
+/* NAME
+/* bounce 8
+/* SUMMARY
+/* Postfix message bounce or defer daemon
+/* SYNOPSIS
+/* \fBbounce\fR [generic Postfix daemon options]
+/* DESCRIPTION
+/* The \fBbounce\fR daemon maintains per-message log files with
+/* non-delivery status information. Each log file is named after the
+/* queue file that it corresponds to, and is kept in a queue subdirectory
+/* named after the service name in the \fBmaster.cf\fR file (either
+/* \fBbounce\fR or \fBdefer\fR).
+/* This program expects to be run from the \fBmaster\fR(8) process
+/* manager.
+/*
+/* The \fBbounce\fR daemon processes two types of service requests:
+/* .IP \(bu
+/* Append a recipient status record to a per-message log file.
+/* .IP \(bu
+/* Post a bounce message, with a copy of a log file and of the
+/* corresponding message. When the bounce is posted successfully,
+/* the log file is deleted.
+/* .PP
+/* The software does a best effort to notify the sender that there
+/* was a problem. A notification is sent even when the log file
+/* or original message cannot be read.
+/*
+/* Optionally, a client can request that the per-message log file be
+/* deleted when the requested operation fails.
+/* This is used by clients that cannot retry transactions by
+/* themselves, and that depend on retry logic in their own client.
+/* STANDARDS
+/* RFC 822 (ARPA Internet Text Messages)
+/* DIAGNOSTICS
+/* Problems and transactions are logged to \fBsyslogd\fR(8).
+/* BUGS
+/* The log files use an ad-hoc, unstructured format. This will have
+/* to change in order to easily support standard delivery status
+/* notifications.
+/* 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.
+/* .IP \fBbounce_size_limit\fR
+/* Limit the amount of original message context that is sent in
+/* a non-delivery notification.
+/* .IP \fBmail_name\fR
+/* Use this mail system name in the introductory text at the
+/* start of a bounce message.
+/* .IP \fBnotify_classes\fR
+/* Notify the postmaster of bounced mail when this parameter
+/* includes the \fBbounce\fR class. For privacy reasons, the message
+/* body is not included.
+/* SEE ALSO
+/* master(8) process manager
+/* qmgr(8) queue manager
+/* syslogd(8) system logging
+/* 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
+
+/* Utility library. */
+
+#include
+#include
+#include
+#include
+
+/* Global library. */
+
+#include
+#include
+#include
+#include
+#include
+
+/* Single-threaded server skeleton. */
+
+#include
+
+/* Application-specific. */
+
+#include "bounce_service.h"
+
+ /*
+ * Tunables.
+ */
+int var_bounce_limit;
+char *var_notify_classes;
+
+ /*
+ * We're single threaded, so we can avoid some memory allocation overhead.
+ */
+static VSTRING *queue_id;
+static VSTRING *queue_name;
+static VSTRING *recipient;
+static VSTRING *sender;
+static VSTRING *why;
+
+#define STR vstring_str
+
+/* bounce_append_proto - bounce_append server protocol */
+
+static int bounce_append_proto(char *service_name, VSTREAM *client)
+{
+ int flags;
+
+ /*
+ * Read the and validate the client request.
+ */
+ if (mail_command_read(client, "%d %s %s %s",
+ &flags, queue_id, recipient, why) != 4) {
+ msg_warn("malformed request");
+ return (-1);
+ }
+ if (mail_queue_id_ok(STR(queue_id)) == 0) {
+ msg_warn("malformed queue id: %s", printable(STR(queue_id), '?'));
+ return (-1);
+ }
+ if (msg_verbose)
+ msg_info("bounce_append_proto: service=%s id=%s to=%s why=%s",
+ service_name, STR(queue_id), STR(recipient), STR(why));
+
+ /*
+ * On request by the client, set up a trap to delete the log file in case
+ * of errors.
+ */
+ if (flags & BOUNCE_FLAG_CLEAN)
+ bounce_cleanup_register(service_name, STR(queue_id));
+
+ /*
+ * Execute the request.
+ */
+ return (bounce_append_service(service_name, STR(queue_id),
+ STR(recipient), STR(why)));
+}
+
+/* bounce_flush_proto - bounce_flush server protocol */
+
+static int bounce_flush_proto(char *service_name, VSTREAM *client)
+{
+ int flags;
+
+ /*
+ * Read and validate the client request.
+ */
+ if (mail_command_read(client, "%d %s %s %s",
+ &flags, queue_name, queue_id, sender) != 4) {
+ msg_warn("malformed request");
+ return (-1);
+ }
+ if (mail_queue_name_ok(STR(queue_name)) == 0) {
+ msg_warn("malformed queue name: %s", printable(STR(queue_name), '?'));
+ return (-1);
+ }
+ if (mail_queue_id_ok(STR(queue_id)) == 0) {
+ msg_warn("malformed queue id: %s", printable(STR(queue_id), '?'));
+ return (-1);
+ }
+ if (msg_verbose)
+ msg_info("bounce_flush_proto: service=%s queue=%s id=%s sender=%s",
+ service_name, STR(queue_name), STR(queue_id), STR(sender));
+
+ /*
+ * On request by the client, set up a trap to delete the log file in case
+ * of errors.
+ */
+ if (flags & BOUNCE_FLAG_CLEAN)
+ bounce_cleanup_register(service_name, STR(queue_id));
+
+ /*
+ * Execute the request.
+ */
+ return (bounce_flush_service(service_name, STR(queue_name),
+ STR(queue_id), STR(sender)));
+}
+
+/* bounce_service - parse bounce command type and delegate */
+
+static void bounce_service(VSTREAM *client, char *service_name, char **argv)
+{
+ int command;
+ int status;
+
+ /*
+ * Sanity check. This service takes no command-line arguments. The
+ * service name should be usable as a subdirectory name.
+ */
+ if (argv[0])
+ msg_fatal("unexpected command-line argument: %s", argv[0]);
+ if (mail_queue_name_ok(service_name) == 0)
+ msg_fatal("malformed service name: %s", service_name);
+
+ /*
+ * Read and validate the first parameter of the client request. Let the
+ * request-specific protocol routines take care of the remainder.
+ */
+ if (mail_scan(client, "%d", &command) != 1) {
+ msg_warn("malformed request");
+ status = -1;
+ } else if (command == BOUNCE_CMD_FLUSH) {
+ status = bounce_flush_proto(service_name, client);
+ } else if (command == BOUNCE_CMD_APPEND) {
+ status = bounce_append_proto(service_name, client);
+ } else {
+ msg_warn("unknown command: %d", command);
+ status = -1;
+ }
+
+ /*
+ * When the request has completed, send the completion status to the
+ * client.
+ */
+ mail_print(client, "%d", status);
+ vstream_fflush(client);
+
+ /*
+ * When a cleanup trap was set, delete the log file in case of error.
+ * This includes errors while sending the completion status to the
+ * client.
+ */
+ if (bounce_cleanup_path) {
+ if (status || vstream_ferror(client))
+ bounce_cleanup_log();
+ bounce_cleanup_unregister();
+ }
+}
+
+/* post_jail_init - initialize after entering chroot jail */
+
+static void post_jail_init(void)
+{
+
+ /*
+ * Initialize. We're single threaded so we can reuse some memory upon
+ * successive requests.
+ */
+ queue_id = vstring_alloc(10);
+ queue_name = vstring_alloc(10);
+ recipient = vstring_alloc(10);
+ sender = vstring_alloc(10);
+ why = vstring_alloc(10);
+}
+
+/* main - the main program */
+
+int main(int argc, char **argv)
+{
+ static CONFIG_INT_TABLE int_table[] = {
+ VAR_BOUNCE_LIMIT, DEF_BOUNCE_LIMIT, &var_bounce_limit, 1, 0,
+ 0,
+ };
+ static CONFIG_STR_TABLE str_table[] = {
+ VAR_NOTIFY_CLASSES, DEF_NOTIFY_CLASSES, &var_notify_classes, 0, 0,
+ 0,
+ };
+
+ /*
+ * Pass control to the single-threaded service skeleton.
+ */
+ single_server_main(argc, argv, bounce_service,
+ MAIL_SERVER_INT_TABLE, int_table,
+ MAIL_SERVER_STR_TABLE, str_table,
+ MAIL_SERVER_POST_INIT, post_jail_init,
+ 0);
+}
diff --git a/postfix/bounce/bounce_append_service.c b/postfix/bounce/bounce_append_service.c
new file mode 100644
index 000000000..36e613891
--- /dev/null
+++ b/postfix/bounce/bounce_append_service.c
@@ -0,0 +1,124 @@
+/*++
+/* NAME
+/* bounce_append_service 3
+/* SUMMARY
+/* append record to bounce log, server side
+/* SYNOPSIS
+/* #include "bounce_service.h"
+/*
+/* int bounce_append_service(queue_id, recipient, why)
+/* char *queue_id;
+/* char *recipient;
+/* char *why;
+/* DESCRIPTION
+/* This module implements the server side of the bounce_append()
+/* (append bounce log) request. This routine either succeeds or
+/* it raises a fatal error.
+/* DIAGNOSTICS
+/* Fatal errors: all file access errors; memory allocation errors.
+/* BUGS
+/* SEE ALSO
+/* bounce(3) basic bounce service client interface
+/* 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
+#include
+#include
+#include
+#include
+#include
+
+/* Utility library. */
+
+#include
+#include
+#include
+#include
+
+/* Global library. */
+
+#include
+#include
+#include
+
+/* Application-specific. */
+
+#include "bounce_service.h"
+
+/* bounce_append_service - append bounce log */
+
+int bounce_append_service(char *service, char *queue_id,
+ char *recipient, char *why)
+{
+ VSTRING *in_buf = vstring_alloc(100);
+ VSTRING *out_buf = vstring_alloc(100);
+ VSTREAM *log;
+ long orig_length;
+
+ /*
+ * This code is paranoid for a good reason. Once the bounce service takes
+ * responsibility, the mail system will make no further attempts to
+ * deliver this recipient. Whenever file access fails, assume that the
+ * system is under stress or that something has been mis-configured, and
+ * force a backoff by raising a fatal run-time error.
+ */
+ log = mail_queue_open(service, queue_id,
+ O_WRONLY | O_APPEND | O_CREAT, 0600);
+ if (log == 0)
+ msg_fatal("open file %s %s: %m", service, queue_id);
+
+ /*
+ * Lock out other processes to avoid truncating someone else's data in
+ * case of trouble.
+ */
+ if (deliver_flock(vstream_fileno(log), (VSTRING *) 0) < 0)
+ msg_fatal("lock file %s %s: %m", service, queue_id);
+
+ /*
+ * Now, go for it. Append a record. Truncate the log to the original
+ * length when the append operation fails. We use the plain stream-lf
+ * file format because we do not need anything more complicated. As a
+ * benefit, we can still recover some data when the file is a little
+ * garbled.
+ */
+ if ((orig_length = vstream_fseek(log, 0L, SEEK_END)) < 0)
+ msg_fatal("seek file %s %s: %m", service, queue_id);
+
+ if (*recipient)
+ vstream_fprintf(log, "<%s>: ",
+ printable(vstring_str(quote_822_local(in_buf, recipient)), '?'));
+ vstream_fputs(printable(why, '?'), log);
+ vstream_fputs("\n\n", log);
+
+ if (vstream_fflush(log) != 0 || fsync(vstream_fileno(log)) < 0) {
+#ifndef NO_TRUNCATE
+ if (ftruncate(vstream_fileno(log), (off_t) orig_length) < 0)
+ msg_fatal("truncate file %s %s: %m", service, queue_id);
+#endif
+ msg_fatal("append file %s %s: %m", service, queue_id);
+ }
+
+ /*
+ * Darn. If closing the log detects a problem, the only way to undo the
+ * damage is to open the log once more, and to truncate the log to the
+ * original length. But, this could happen only when the log is kept on a
+ * remote file system, and that is not recommended practice anyway.
+ */
+ if (vstream_fclose(log) != 0)
+ msg_warn("append file %s %s: %m", service, queue_id);
+
+ vstring_free(in_buf);
+ vstring_free(out_buf);
+ return (0);
+}
diff --git a/postfix/bounce/bounce_cleanup.c b/postfix/bounce/bounce_cleanup.c
new file mode 100644
index 000000000..483d21ae1
--- /dev/null
+++ b/postfix/bounce/bounce_cleanup.c
@@ -0,0 +1,177 @@
+/*++
+/* NAME
+/* bounce_cleanup 3
+/* SUMMARY
+/* cleanup logfile upon error
+/* SYNOPSIS
+/* #include "bounce_service.h"
+/*
+/* int bounce_cleanup_registered()
+/*
+/* void bounce_cleanup_register(queue_id)
+/* char *queue_id;
+/*
+/* void bounce_cleanup_log(void)
+/*
+/* void bounce_cleanup_unregister(void)
+/* DESCRIPTION
+/* This module implements support for deleting the current
+/* bounce logfile in case of errors, and upon the arrival
+/* of a SIGTERM signal (shutdown).
+/*
+/* bounce_cleanup_register() registers a callback routine with the
+/* run-time error handler, for automatic logfile removal in case
+/* of a fatal run-time error.
+/*
+/* bounce_cleanup_unregister() cleans up storage used by
+/* bounce_cleanup_register().
+/*
+/* In-between bounce_cleanup_register() and bounce_cleanup_unregister()
+/* calls, a call of bounce_cleanup_log() will delete the registered
+/* bounce logfile.
+/*
+/* bounce_cleanup_registered() returns non-zero when a cleanup
+/* trap has been set.
+/* DIAGNOSTICS
+/* Fatal error: all file access errors. Panic: nested calls of
+/* bounce_cleanup_register(); any calls of bounce_cleanup_unregister()
+/* or bounce_cleanup_log() without preceding bounce_cleanup_register()
+/* call.
+/* BUGS
+/* SEE ALSO
+/* master(8) process 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
+/*--*/
+
+/* System library. */
+
+#include
+#include
+#include
+#include
+
+/* Utility library. */
+
+#include
+#include
+#include
+
+/* Global library. */
+
+#include
+
+/* Application-specific. */
+
+#include "bounce_service.h"
+
+ /*
+ * Support for removing a logfile when an update fails. In order to do this,
+ * we save a copy of the currently-open logfile name, and register a
+ * callback function pointer with the run-time error handler. The saved
+ * pathname is made global so that the application can see whether or not a
+ * trap was set up.
+ */
+static MSG_CLEANUP_FN bounce_cleanup_func; /* saved callback */
+VSTRING *bounce_cleanup_path; /* saved path name */
+
+/* bounce_cleanup_callback - run-time callback to cleanup logfile */
+
+static void bounce_cleanup_callback(void)
+{
+
+ /*
+ * Remove the logfile.
+ */
+ if (bounce_cleanup_path)
+ bounce_cleanup_log();
+
+ /*
+ * Execute the saved cleanup action.
+ */
+ if (bounce_cleanup_func)
+ bounce_cleanup_func();
+}
+
+/* bounce_cleanup_log - clean up the logfile */
+
+void bounce_cleanup_log(void)
+{
+ char *myname = "bounce_cleanup_log";
+
+ /*
+ * Sanity checks.
+ */
+ if (bounce_cleanup_path == 0)
+ msg_panic("%s: no cleanup context", myname);
+
+ /*
+ * This function may be called before a logfile is created or after it
+ * has been deleted, so do not complain.
+ */
+ (void) unlink(vstring_str(bounce_cleanup_path));
+}
+
+/* bounce_cleanup_sig - signal handler */
+
+static void bounce_cleanup_sig(int sig)
+{
+
+ /*
+ * Running as a signal handler - don't do complicated stuff.
+ */
+ if (bounce_cleanup_path)
+ (void) unlink(vstring_str(bounce_cleanup_path));
+ exit(sig);
+}
+
+/* bounce_cleanup_register - register logfile to clean up */
+
+void bounce_cleanup_register(char *service, char *queue_id)
+{
+ char *myname = "bounce_cleanup_register";
+
+ /*
+ * Sanity checks.
+ */
+ if (bounce_cleanup_path)
+ msg_panic("%s: nested call", myname);
+
+ /*
+ * Save a copy of the logfile path, and of the last callback function
+ * pointer registered with the run-time error handler.
+ */
+ bounce_cleanup_path = vstring_alloc(10);
+ (void) mail_queue_path(bounce_cleanup_path, service, queue_id);
+ bounce_cleanup_func = msg_cleanup(bounce_cleanup_callback);
+ signal(SIGTERM, bounce_cleanup_sig);
+}
+
+/* bounce_cleanup_unregister - unregister logfile to clean up */
+
+void bounce_cleanup_unregister(void)
+{
+ char *myname = "bounce_cleanup_unregister";
+
+ /*
+ * Sanity checks.
+ */
+ if (bounce_cleanup_path == 0)
+ msg_panic("%s: no cleanup context", myname);
+
+ /*
+ * Restore the saved callback function pointer, and release storage for
+ * the saved logfile pathname.
+ */
+ signal(SIGTERM, SIG_DFL);
+ (void) msg_cleanup(bounce_cleanup_func);
+ vstring_free(bounce_cleanup_path);
+ bounce_cleanup_path = 0;
+}
diff --git a/postfix/bounce/bounce_flush_service.c b/postfix/bounce/bounce_flush_service.c
new file mode 100644
index 000000000..32f79d764
--- /dev/null
+++ b/postfix/bounce/bounce_flush_service.c
@@ -0,0 +1,359 @@
+/*++
+/* NAME
+/* bounce_flush_service 3
+/* SUMMARY
+/* send non-delivery report to sender, server side
+/* SYNOPSIS
+/* #include "bounce_service.h"
+/*
+/* int bounce_flush_service(queue_name, queue_id, sender)
+/* char *queue_name;
+/* char *queue_id;
+/* char *sender;
+/* DESCRIPTION
+/* This module implements the server side of the bounce_flush()
+/* (send bounce message) request.
+/*
+/* When a message bounces, a full copy is sent to the originator,
+/* and a copy of the diagnostics with message headers is sent to
+/* the postmaster. The result is non-zero when the operation
+/* should be tried again.
+/*
+/* When a single bounce is sent, the sender address is the empty
+/* address. When a double bounce is sent, the sender is taken
+/* from the configuration parameter \fIdouble_bounce_sender\fR.
+/* DIAGNOSTICS
+/* Fatal error: error opening existing file. Warnings: corrupt
+/* message file. A corrupt message is saved to the "corrupt"
+/* queue for further inspection.
+/* BUGS
+/* SEE ALSO
+/* bounce(3) basic bounce service client interface
+/* 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
+#include
+#include
+#include
+#include
+
+#ifdef STRCASECMP_IN_STRINGS_H
+#include
+#endif
+
+/* Utility library. */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+/* Global library. */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+/* Application-specific. */
+
+#include "bounce_service.h"
+
+#define STR vstring_str
+
+/* bounce_header - generate bounce message header */
+
+static int bounce_header(VSTREAM *bounce, VSTRING *buf, char *dest)
+{
+
+ /*
+ * Print a minimal bounce header. The cleanup service will add other
+ * headers and will make all addresses fully qualified.
+ */
+ post_mail_fprintf(bounce, "From: %s (Mail Delivery System)",
+ MAIL_ADDR_MAIL_DAEMON);
+ post_mail_fprintf(bounce, *dest == 0 ?
+ "Subject: Postmaster Copy: Undelivered Mail" :
+ "Subject: Undelivered Mail Returned to Sender");
+ quote_822_local(buf, *dest == 0 ? mail_addr_postmaster() : dest);
+ post_mail_fprintf(bounce, "To: %s", STR(buf));
+ post_mail_fputs(bounce, "");
+ return (vstream_ferror(bounce));
+}
+
+/* bounce_boilerplate - generate boiler-plate text */
+
+static int bounce_boilerplate(VSTREAM *bounce, VSTRING *buf)
+{
+
+ /*
+ * Print the message body with the problem report. XXX For now, we use a
+ * fixed bounce template. We could use a site-specific parametrized
+ * template with ${name} macros and we could do wonderful things such as
+ * word wrapping to make the text look nicer. No matter how hard we would
+ * try, receiving bounced mail will always suck.
+ */
+ post_mail_fprintf(bounce, "This is the %s program at host %s.",
+ var_mail_name, var_myhostname);
+ post_mail_fputs(bounce, "");
+ post_mail_fprintf(bounce,
+ "I'm sorry to have to inform you that the message returned");
+ post_mail_fprintf(bounce,
+ "below could not be delivered to one or more destinations.");
+ post_mail_fputs(bounce, "");
+ post_mail_fprintf(bounce,
+ "For further assistance, please contact <%s>",
+ STR(canon_addr_external(buf, MAIL_ADDR_POSTMASTER)));
+ post_mail_fputs(bounce, "");
+ post_mail_fprintf(bounce,
+ "If you do so, please include this problem report. You can");
+ post_mail_fprintf(bounce,
+ "delete your own text from the message returned below.");
+ post_mail_fputs(bounce, "");
+ post_mail_fprintf(bounce, "\t\t\tThe %s program", var_mail_name);
+ return (vstream_ferror(bounce));
+}
+
+/* bounce_print - line_wrap callback */
+
+static void bounce_print(const char *str, int len, int indent, char *context)
+{
+ VSTREAM *bounce = (VSTREAM *) context;
+
+ post_mail_fprintf(bounce, "%*s%.*s", indent, "", len, str);
+}
+
+/* bounce_diagnostics - send bounce log report */
+
+static int bounce_diagnostics(char *service, VSTREAM *bounce, VSTRING *buf, char *queue_id)
+{
+ VSTREAM *log;
+
+ /*
+ * If the bounce log cannot be found, do not raise a fatal run-time
+ * error. There is nothing we can do about the error, and all we are
+ * doing is to inform the sender of a delivery problem, Bouncing a
+ * message does not have to be a perfect job. But if the system IS
+ * running out of resources, raise a fatal run-time error and force a
+ * backoff.
+ */
+ if ((log = mail_queue_open(service, queue_id, O_RDONLY, 0)) == 0) {
+ if (errno != ENOENT)
+ msg_fatal("open %s %s: %m", service, queue_id);
+ post_mail_fputs(bounce, "");
+ post_mail_fputs(bounce, "\t--- Delivery error report unavailable ---");
+ post_mail_fputs(bounce, "");
+ }
+
+ /*
+ * Append a copy of the delivery error log. Again, we're doing a best
+ * effort, so there is no point raising a fatal run-time error in case of
+ * a logfile read error. Wrap long lines, filter non-printable
+ * characters, and prepend one blank, so this data can safely be piped
+ * into other programs.
+ */
+ else {
+
+#define LENGTH 79
+#define INDENT 4
+ post_mail_fputs(bounce, "");
+ post_mail_fputs(bounce, "\t--- Delivery error report follows ---");
+ post_mail_fputs(bounce, "");
+ while (vstream_ferror(bounce) == 0 && vstring_fgets_nonl(buf, log)) {
+ printable(STR(buf), '_');
+ line_wrap(STR(buf), LENGTH, INDENT, bounce_print, (char *) bounce);
+ if (vstream_ferror(bounce) != 0)
+ break;
+ }
+ if (vstream_fclose(log))
+ msg_warn("read bounce log %s: %m", queue_id);
+ }
+ return (vstream_ferror(bounce));
+}
+
+/* bounce_original - send a copy of the original to the victim */
+
+static int bounce_original(char *service, VSTREAM *bounce, VSTRING *buf,
+ char *queue_name, char *queue_id, int headers_only)
+{
+ int status = 0;
+ VSTREAM *src;
+ int rec_type;
+ int bounce_length;
+
+ /*
+ * If the original message cannot be found, do not raise a run-time
+ * error. There is nothing we can do about the error, and all we are
+ * doing is to inform the sender of a delivery problem. Bouncing a
+ * message does not have to be a perfect job. But if the system IS
+ * running out of resources, raise a fatal run-time error and force a
+ * backoff.
+ */
+ if ((src = mail_queue_open(queue_name, queue_id, O_RDONLY, 0)) == 0) {
+ if (errno != ENOENT)
+ msg_fatal("open %s %s: %m", service, queue_id);
+ post_mail_fputs(bounce, "\t--- Undelivered message unavailable ---");
+ return (vstream_ferror(bounce));
+ }
+
+ /*
+ * Append a copy of the rejected message.
+ */
+ post_mail_fputs(bounce, "\t--- Undelivered message follows ---");
+ post_mail_fputs(bounce, "");
+
+ /*
+ * Skip over the original message envelope records. If the envelope is
+ * corrupted just send whatever we can (remember this is a best effort,
+ * it does not have to be perfect).
+ */
+ while ((rec_type = rec_get(src, buf, 0)) > 0)
+ if (rec_type == REC_TYPE_MESG)
+ break;
+
+ /*
+ * Copy the original message contents. Limit the amount of bounced text
+ * so there is a better chance of the bounce making it back. We're doing
+ * raw record output here so that we don't throw away binary transparency
+ * yet.
+ */
+#define IS_HEADER(s) (ISSPACE(*(s)) || is_header(s))
+
+ bounce_length = 0;
+ while (status == 0 && (rec_type = rec_get(src, buf, 0)) > 0) {
+ if (rec_type != REC_TYPE_NORM && rec_type != REC_TYPE_CONT)
+ break;
+ if (headers_only && !IS_HEADER(vstring_str(buf)))
+ break;
+ if (var_bounce_limit == 0 || bounce_length < var_bounce_limit) {
+ bounce_length += VSTRING_LEN(buf);
+ status = (REC_PUT_BUF(bounce, rec_type, buf) != rec_type);
+ }
+ }
+ if (headers_only == 0 && rec_type != REC_TYPE_XTRA)
+ status |= mark_corrupt(src);
+ if (vstream_fclose(src))
+ msg_warn("read message file %s %s: %m", queue_name, queue_id);
+ return (status);
+}
+
+/* bounce_flush_service - send a bounce */
+
+int bounce_flush_service(char *service, char *queue_name,
+ char *queue_id, char *recipient)
+{
+ VSTRING *buf = vstring_alloc(100);
+ const char *double_bounce_addr;
+ int status = 1;
+ VSTREAM *bounce;
+
+#define NULL_RECIPIENT MAIL_ADDR_EMPTY /* special address */
+#define NULL_SENDER MAIL_ADDR_EMPTY /* special address */
+#define TO_POSTMASTER(addr) (*(addr) == 0)
+#define NULL_CLEANUP_FLAGS 0
+#define BOUNCE_HEADERS 1
+#define BOUNCE_ALL 0
+
+ /*
+ * The choice of sender address depends on recipient address. For a
+ * single bounce (typically a non-delivery notification to the message
+ * originator), the sender address is the empty string. For a double
+ * bounce (typically a failed single bounce, or a postmaster notification
+ * that was produced by any of the mail processes) the sender address is
+ * defined by the var_double_bounce_sender configuration variable. When a
+ * double bounce cannot be delivered, the local delivery agent gives
+ * special treatment to the resulting bounce message.
+ */
+ double_bounce_addr = mail_addr_double_bounce();
+
+ /*
+ * Connect to the cleanup service, and request that the cleanup service
+ * takes no special actions in case of problems.
+ */
+ if ((bounce = post_mail_fopen_nowait(TO_POSTMASTER(recipient) ?
+ double_bounce_addr : NULL_SENDER,
+ recipient, NULL_CLEANUP_FLAGS,
+ "BOUNCE")) != 0) {
+
+ /*
+ * Send the bounce message header, some boilerplate text that
+ * pretends that we are a polite mail system, the text with reason
+ * for the bounce, and a copy of the original message.
+ */
+ if (bounce_header(bounce, buf, recipient) == 0
+ && bounce_boilerplate(bounce, buf) == 0
+ && bounce_diagnostics(service, bounce, buf, queue_id) == 0)
+ bounce_original(service, bounce, buf, queue_name, queue_id, BOUNCE_ALL);
+
+ /*
+ * Finish the bounce, and retrieve the completion status.
+ */
+ status = post_mail_fclose(bounce);
+ }
+
+ /*
+ * If not sending to the postmaster or double-bounce pseudo accounts,
+ * send a postmaster copy as if it is a double bounce, so it will not
+ * bounce in case of error. This time, block while waiting for resources
+ * to become available. We know they were available just a split second
+ * ago.
+ */
+ if (status == 0 && !TO_POSTMASTER(recipient)
+ && strcasecmp(recipient, double_bounce_addr) != 0
+ && (MAIL_ERROR_BOUNCE & name_mask(mail_error_masks, var_notify_classes))) {
+
+ /*
+ * Send the text with reason for the bounce, and the headers of the
+ * original message. Don't bother sending the boiler-plate text.
+ */
+ bounce = post_mail_fopen(double_bounce_addr, NULL_RECIPIENT,
+ NULL_CLEANUP_FLAGS, "BOUNCE");
+ if (bounce_header(bounce, buf, NULL_RECIPIENT) == 0
+ && bounce_diagnostics(service, bounce, buf, queue_id) == 0)
+ bounce_original(service, bounce, buf, queue_name, queue_id, BOUNCE_HEADERS);
+
+ /*
+ * Finish the bounce, and update the completion status.
+ */
+ status |= post_mail_fclose(bounce);
+ }
+
+ /*
+ * Examine the completion status. Delete the bounce log file only when
+ * the bounce was posted successfully.
+ */
+ if (status == 0 && mail_queue_remove(service, queue_id) && errno != ENOENT)
+ msg_fatal("remove %s %s: %m", service, queue_id);
+
+ /*
+ * Cleanup.
+ */
+ vstring_free(buf);
+
+ return (status);
+}
diff --git a/postfix/bounce/bounce_service.h b/postfix/bounce/bounce_service.h
new file mode 100644
index 000000000..8584b9810
--- /dev/null
+++ b/postfix/bounce/bounce_service.h
@@ -0,0 +1,45 @@
+/*++
+/* NAME
+/* bounce_service 3h
+/* SUMMARY
+/* bounce message service
+/* SYNOPSIS
+/* #include
+/* DESCRIPTION
+/* .nf
+
+ /*
+ * Utility library.
+ */
+#include
+
+ /*
+ * bounce_append_service.c
+ */
+extern int bounce_append_service(char *, char *, char *, char *);
+
+ /*
+ * bounce_flush_service.c
+ */
+extern int bounce_flush_service(char *, char *, char *, char *);
+
+ /*
+ * bounce_cleanup.c
+ */
+extern VSTRING *bounce_cleanup_path;
+extern void bounce_cleanup_register(char *, char *);
+extern void bounce_cleanup_log(void);
+extern void bounce_cleanup_unregister(void);
+
+#define bounce_cleanup_registered() (bounce_cleanup_path != 0)
+
+/* 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
+/*--*/
diff --git a/postfix/cleanup/.indent.pro b/postfix/cleanup/.indent.pro
new file mode 100644
index 000000000..e59d396ad
--- /dev/null
+++ b/postfix/cleanup/.indent.pro
@@ -0,0 +1,89 @@
+-TALIAS_TOKEN
+-TARGV
+-TBH_TABLE
+-TBINHASH
+-TBINHASH_INFO
+-TBOUNCE_STAT
+-TCLEANUP_STATE
+-TCLIENT_LIST
+-TCONFIG_BOOL_FN_TABLE
+-TCONFIG_BOOL_TABLE
+-TCONFIG_INT_FN_TABLE
+-TCONFIG_INT_TABLE
+-TCONFIG_STR_FN_TABLE
+-TCONFIG_STR_TABLE
+-TDELIVER_ATTR
+-TDELIVER_REQUEST
+-TDICT
+-TDICT_DB
+-TDICT_DBM
+-TDICT_ENV
+-TDICT_HT
+-TDICT_LDAP
+-TDICT_NI
+-TDICT_NIS
+-TDICT_NISPLUS
+-TDICT_NODE
+-TDICT_OPEN_INFO
+-TDNS_FIXED
+-TDNS_REPLY
+-TDNS_RR
+-TDOMAIN_LIST
+-TEXPAND_ATTR
+-TFILE
+-TFORWARD_INFO
+-THEADER_OPTS
+-THTABLE
+-THTABLE_INFO
+-TINET_ADDR_LIST
+-TINT_TABLE
+-TLOCAL_STATE
+-TMAC_HEAD
+-TMAC_PARSE
+-TMAIL_PRINT
+-TMAIL_SCAN
+-TMAPS
+-TMASTER_PROC
+-TMASTER_SERV
+-TMASTER_STATUS
+-TMBLOCK
+-TMKMAP
+-TMKMAP_OPEN_INFO
+-TMULTI_SERVER
+-TMVECT
+-TNAMADR_LIST
+-TNAME_MASK
+-TPEER_NAME
+-TPICKUP_INFO
+-TPIPE_ATTR
+-TPIPE_PARAMS
+-TQMGR_ENTRY
+-TQMGR_MESSAGE
+-TQMGR_QUEUE
+-TQMGR_RCPT_LIST
+-TQMGR_RECIPIENT
+-TQMGR_SCAN
+-TQMGR_TRANSPORT
+-TRECIPIENT
+-TRECIPIENT_LIST
+-TREC_TYPE_NAME
+-TRESOLVE_REPLY
+-TSCAN_DIR
+-TSINGLE_SERVER
+-TSMTPD_STATE
+-TSMTPD_TOKEN
+-TSMTP_ADDR
+-TSMTP_CMD
+-TSMTP_RESP
+-TSMTP_SESSION
+-TSMTP_STATE
+-TSOCKADDR_SIZE
+-TSTRING_TABLE
+-TSYS_EXITS_TABLE
+-TTOK822
+-TTRIGGER_SERVER
+-TUSER_ATTR
+-TVBUF
+-TVSTREAM
+-TVSTRING
+-TWAIT_STATUS_T
diff --git a/postfix/cleanup/.printfck b/postfix/cleanup/.printfck
new file mode 100644
index 000000000..9ed900cb0
--- /dev/null
+++ b/postfix/cleanup/.printfck
@@ -0,0 +1,24 @@
+been_here_xt 2 0
+bounce_append 5 0
+cleanup_out_format 1 0
+defer_append 5 0
+mail_command 1 0
+mail_print 1 0
+msg_error 0 0
+msg_fatal 0 0
+msg_info 0 0
+msg_panic 0 0
+msg_warn 0 0
+opened 3 0
+qmgr_message_bounce 2 0
+rec_fprintf 2 0
+sent 4 0
+smtp_cmd 1 0
+smtp_mesg_fail 2 0
+smtp_printf 1 0
+smtp_rcpt_fail 3 0
+smtp_site_fail 2 0
+udp_syslog 1 0
+vstream_fprintf 1 0
+vstream_printf 0 0
+vstring_sprintf 1 0
diff --git a/postfix/cleanup/Makefile.in b/postfix/cleanup/Makefile.in
new file mode 100644
index 000000000..1eb83bc7a
--- /dev/null
+++ b/postfix/cleanup/Makefile.in
@@ -0,0 +1,273 @@
+SHELL = /bin/sh
+SRCS = cleanup.c cleanup_out.c cleanup_envelope.c cleanup_message.c \
+ cleanup_extracted.c cleanup_state.c cleanup_skip.c cleanup_rewrite.c \
+ cleanup_map11.c cleanup_map1n.c cleanup_masquerade.c \
+ cleanup_out_recipient.c
+OBJS = cleanup.o cleanup_out.o cleanup_envelope.o cleanup_message.o \
+ cleanup_extracted.o cleanup_state.o cleanup_skip.o cleanup_rewrite.o \
+ cleanup_map11.o cleanup_map1n.o cleanup_masquerade.o \
+ cleanup_out_recipient.o
+HDRS =
+TESTSRC =
+WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
+ -Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
+ -Wunused
+DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
+CFLAGS = $(DEBUG) $(OPT) $(DEFS)
+TESTPROG=
+PROG = cleanup
+INC_DIR = ../include
+LIBS = ../lib/libmaster.a ../lib/libglobal.a ../lib/libutil.a
+
+.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) sh ../makedefs; cat $?) >$@
+
+test: $(TESTPROG)
+
+update: ../bin/$(PROG)
+
+../bin/$(PROG): $(PROG)
+ cp $(PROG) ../bin
+
+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
+
+# do not edit below this line - it is generated by 'make depend'
+cleanup.o: cleanup.c
+cleanup.o: ../include/sys_defs.h
+cleanup.o: ../include/msg.h
+cleanup.o: ../include/vstring.h
+cleanup.o: ../include/vbuf.h
+cleanup.o: ../include/vstream.h
+cleanup.o: ../include/mymalloc.h
+cleanup.o: ../include/iostuff.h
+cleanup.o: ../include/config.h
+cleanup.o: ../include/cleanup_user.h
+cleanup.o: ../include/mail_queue.h
+cleanup.o: ../include/mail_proto.h
+cleanup.o: ../include/opened.h
+cleanup.o: ../include/bounce.h
+cleanup.o: ../include/mail_params.h
+cleanup.o: ../include/mail_stream.h
+cleanup.o: ../include/mail_addr.h
+cleanup.o: ../include/mail_server.h
+cleanup.o: cleanup.h
+cleanup.o: ../include/argv.h
+cleanup.o: ../include/maps.h
+cleanup.o: ../include/tok822.h
+cleanup.o: ../include/resolve_clnt.h
+cleanup.o: ../include/been_here.h
+cleanup_envelope.o: cleanup_envelope.c
+cleanup_envelope.o: ../include/sys_defs.h
+cleanup_envelope.o: ../include/msg.h
+cleanup_envelope.o: ../include/vstring.h
+cleanup_envelope.o: ../include/vbuf.h
+cleanup_envelope.o: ../include/vstream.h
+cleanup_envelope.o: ../include/mymalloc.h
+cleanup_envelope.o: ../include/record.h
+cleanup_envelope.o: ../include/rec_type.h
+cleanup_envelope.o: ../include/cleanup_user.h
+cleanup_envelope.o: ../include/tok822.h
+cleanup_envelope.o: ../include/resolve_clnt.h
+cleanup_envelope.o: ../include/mail_params.h
+cleanup_envelope.o: cleanup.h
+cleanup_envelope.o: ../include/argv.h
+cleanup_envelope.o: ../include/maps.h
+cleanup_envelope.o: ../include/been_here.h
+cleanup_envelope.o: ../include/mail_stream.h
+cleanup_extracted.o: cleanup_extracted.c
+cleanup_extracted.o: ../include/sys_defs.h
+cleanup_extracted.o: ../include/msg.h
+cleanup_extracted.o: ../include/vstring.h
+cleanup_extracted.o: ../include/vbuf.h
+cleanup_extracted.o: ../include/vstream.h
+cleanup_extracted.o: ../include/argv.h
+cleanup_extracted.o: ../include/mymalloc.h
+cleanup_extracted.o: ../include/cleanup_user.h
+cleanup_extracted.o: ../include/record.h
+cleanup_extracted.o: ../include/rec_type.h
+cleanup_extracted.o: cleanup.h
+cleanup_extracted.o: ../include/maps.h
+cleanup_extracted.o: ../include/tok822.h
+cleanup_extracted.o: ../include/resolve_clnt.h
+cleanup_extracted.o: ../include/been_here.h
+cleanup_extracted.o: ../include/mail_stream.h
+cleanup_map11.o: cleanup_map11.c
+cleanup_map11.o: ../include/sys_defs.h
+cleanup_map11.o: ../include/msg.h
+cleanup_map11.o: ../include/vstring.h
+cleanup_map11.o: ../include/vbuf.h
+cleanup_map11.o: ../include/dict.h
+cleanup_map11.o: ../include/vstream.h
+cleanup_map11.o: ../include/mymalloc.h
+cleanup_map11.o: ../include/cleanup_user.h
+cleanup_map11.o: ../include/mail_addr_map.h
+cleanup_map11.o: ../include/argv.h
+cleanup_map11.o: ../include/maps.h
+cleanup_map11.o: ../include/quote_822_local.h
+cleanup_map11.o: cleanup.h
+cleanup_map11.o: ../include/tok822.h
+cleanup_map11.o: ../include/resolve_clnt.h
+cleanup_map11.o: ../include/been_here.h
+cleanup_map11.o: ../include/mail_stream.h
+cleanup_map1n.o: cleanup_map1n.c
+cleanup_map1n.o: ../include/sys_defs.h
+cleanup_map1n.o: ../include/mymalloc.h
+cleanup_map1n.o: ../include/msg.h
+cleanup_map1n.o: ../include/argv.h
+cleanup_map1n.o: ../include/vstring.h
+cleanup_map1n.o: ../include/vbuf.h
+cleanup_map1n.o: ../include/dict.h
+cleanup_map1n.o: ../include/vstream.h
+cleanup_map1n.o: ../include/mail_addr_map.h
+cleanup_map1n.o: ../include/maps.h
+cleanup_map1n.o: ../include/cleanup_user.h
+cleanup_map1n.o: ../include/quote_822_local.h
+cleanup_map1n.o: cleanup.h
+cleanup_map1n.o: ../include/tok822.h
+cleanup_map1n.o: ../include/resolve_clnt.h
+cleanup_map1n.o: ../include/been_here.h
+cleanup_map1n.o: ../include/mail_stream.h
+cleanup_masquerade.o: cleanup_masquerade.c
+cleanup_masquerade.o: ../include/sys_defs.h
+cleanup_masquerade.o: ../include/msg.h
+cleanup_masquerade.o: ../include/vstring.h
+cleanup_masquerade.o: ../include/vbuf.h
+cleanup_masquerade.o: ../include/argv.h
+cleanup_masquerade.o: ../include/htable.h
+cleanup_masquerade.o: ../include/mymalloc.h
+cleanup_masquerade.o: ../include/stringops.h
+cleanup_masquerade.o: ../include/mail_params.h
+cleanup_masquerade.o: ../include/tok822.h
+cleanup_masquerade.o: ../include/resolve_clnt.h
+cleanup_masquerade.o: ../include/quote_822_local.h
+cleanup_masquerade.o: cleanup.h
+cleanup_masquerade.o: ../include/vstream.h
+cleanup_masquerade.o: ../include/maps.h
+cleanup_masquerade.o: ../include/been_here.h
+cleanup_masquerade.o: ../include/mail_stream.h
+cleanup_message.o: cleanup_message.c
+cleanup_message.o: ../include/sys_defs.h
+cleanup_message.o: ../include/msg.h
+cleanup_message.o: ../include/vstring.h
+cleanup_message.o: ../include/vbuf.h
+cleanup_message.o: ../include/vstream.h
+cleanup_message.o: ../include/argv.h
+cleanup_message.o: ../include/split_at.h
+cleanup_message.o: ../include/mymalloc.h
+cleanup_message.o: ../include/record.h
+cleanup_message.o: ../include/rec_type.h
+cleanup_message.o: ../include/cleanup_user.h
+cleanup_message.o: ../include/tok822.h
+cleanup_message.o: ../include/resolve_clnt.h
+cleanup_message.o: ../include/header_opts.h
+cleanup_message.o: ../include/quote_822_local.h
+cleanup_message.o: ../include/mail_params.h
+cleanup_message.o: ../include/mail_date.h
+cleanup_message.o: ../include/mail_addr.h
+cleanup_message.o: ../include/is_header.h
+cleanup_message.o: cleanup.h
+cleanup_message.o: ../include/maps.h
+cleanup_message.o: ../include/been_here.h
+cleanup_message.o: ../include/mail_stream.h
+cleanup_out.o: cleanup_out.c
+cleanup_out.o: ../include/sys_defs.h
+cleanup_out.o: ../include/msg.h
+cleanup_out.o: ../include/vstring.h
+cleanup_out.o: ../include/vbuf.h
+cleanup_out.o: ../include/vstream.h
+cleanup_out.o: ../include/record.h
+cleanup_out.o: ../include/rec_type.h
+cleanup_out.o: ../include/cleanup_user.h
+cleanup_out.o: cleanup.h
+cleanup_out.o: ../include/argv.h
+cleanup_out.o: ../include/maps.h
+cleanup_out.o: ../include/tok822.h
+cleanup_out.o: ../include/resolve_clnt.h
+cleanup_out.o: ../include/been_here.h
+cleanup_out.o: ../include/mail_stream.h
+cleanup_out_recipient.o: cleanup_out_recipient.c
+cleanup_out_recipient.o: ../include/sys_defs.h
+cleanup_out_recipient.o: ../include/argv.h
+cleanup_out_recipient.o: ../include/been_here.h
+cleanup_out_recipient.o: ../include/mail_params.h
+cleanup_out_recipient.o: ../include/rec_type.h
+cleanup_out_recipient.o: cleanup.h
+cleanup_out_recipient.o: ../include/vstring.h
+cleanup_out_recipient.o: ../include/vbuf.h
+cleanup_out_recipient.o: ../include/vstream.h
+cleanup_out_recipient.o: ../include/maps.h
+cleanup_out_recipient.o: ../include/tok822.h
+cleanup_out_recipient.o: ../include/resolve_clnt.h
+cleanup_out_recipient.o: ../include/mail_stream.h
+cleanup_rewrite.o: cleanup_rewrite.c
+cleanup_rewrite.o: ../include/sys_defs.h
+cleanup_rewrite.o: ../include/msg.h
+cleanup_rewrite.o: ../include/vstring.h
+cleanup_rewrite.o: ../include/vbuf.h
+cleanup_rewrite.o: ../include/tok822.h
+cleanup_rewrite.o: ../include/resolve_clnt.h
+cleanup_rewrite.o: ../include/rewrite_clnt.h
+cleanup_rewrite.o: ../include/quote_822_local.h
+cleanup_rewrite.o: cleanup.h
+cleanup_rewrite.o: ../include/vstream.h
+cleanup_rewrite.o: ../include/argv.h
+cleanup_rewrite.o: ../include/maps.h
+cleanup_rewrite.o: ../include/been_here.h
+cleanup_rewrite.o: ../include/mail_stream.h
+cleanup_skip.o: cleanup_skip.c
+cleanup_skip.o: ../include/sys_defs.h
+cleanup_skip.o: ../include/msg.h
+cleanup_skip.o: ../include/vstream.h
+cleanup_skip.o: ../include/vbuf.h
+cleanup_skip.o: ../include/record.h
+cleanup_skip.o: ../include/vstring.h
+cleanup_skip.o: ../include/rec_type.h
+cleanup_skip.o: cleanup.h
+cleanup_skip.o: ../include/argv.h
+cleanup_skip.o: ../include/maps.h
+cleanup_skip.o: ../include/tok822.h
+cleanup_skip.o: ../include/resolve_clnt.h
+cleanup_skip.o: ../include/been_here.h
+cleanup_skip.o: ../include/mail_stream.h
+cleanup_state.o: cleanup_state.c
+cleanup_state.o: ../include/sys_defs.h
+cleanup_state.o: ../include/mymalloc.h
+cleanup_state.o: ../include/vstring.h
+cleanup_state.o: ../include/vbuf.h
+cleanup_state.o: ../include/vstream.h
+cleanup_state.o: ../include/been_here.h
+cleanup_state.o: ../include/mail_params.h
+cleanup_state.o: cleanup.h
+cleanup_state.o: ../include/argv.h
+cleanup_state.o: ../include/maps.h
+cleanup_state.o: ../include/tok822.h
+cleanup_state.o: ../include/resolve_clnt.h
+cleanup_state.o: ../include/mail_stream.h
diff --git a/postfix/cleanup/cleanup.c b/postfix/cleanup/cleanup.c
new file mode 100644
index 000000000..72c64d665
--- /dev/null
+++ b/postfix/cleanup/cleanup.c
@@ -0,0 +1,443 @@
+/*++
+/* NAME
+/* cleanup 8
+/* SUMMARY
+/* canonicalize and enqueue Postfix message
+/* SYNOPSIS
+/* \fBcleanup\fR [generic Postfix daemon options]
+/* DESCRIPTION
+/* The \fBcleanup\fR daemon processes inbound mail, inserts it
+/* into the \fBincoming\fR mail queue, and informs the queue
+/* manager of its arrival.
+/*
+/* The \fBcleanup\fR daemon always performs the following transformations:
+/* .IP \(bu
+/* Insert missing message headers: (\fBResent-\fR) \fBFrom:\fR,
+/* \fBMessage-Id:\fR, and \fBDate:\fR.
+/* .IP \(bu
+/* Extract envelope recipient addresses from (\fBResent-\fR) \fBTo:\fR,
+/* \fBCc:\fR and \fBBcc:\fR message headers when no recipients are
+/* specified in the message envelope.
+/* .IP \(bu
+/* Transform envelope and header addresses to the standard
+/* \fIuser@fully-qualified-domain\fR form that is expected by other
+/* Postfix programs.
+/* This task is delegated to the \fBtrivial-rewrite\fR(8) daemon.
+/* .IP \(bu
+/* Eliminate duplicate envelope recipient addresses.
+/* .PP
+/* The following address transformations are optional:
+/* .IP \(bu
+/* Optionally, rewrite all envelope and header addresses according
+/* to the mappings specified in the \fBcanonical\fR(5) lookup tables.
+/* .IP \(bu
+/* Optionally, masquerade envelope sender addresses and message
+/* header addresses (i.e. strip host or domain information below
+/* all domains listed in the \fBmasquerade_domains\fR parameter,
+/* except for user names listed in \fBmasquerade_exceptions\fR).
+/* Address masquerading does not affect envelope recipients.
+/* .IP \(bu
+/* Optionally, expand envelope recipients according to information
+/* found in the \fBvirtual\fR(5) lookup tables.
+/* .PP
+/* The \fBcleanup\fR daemon performs sanity checks on the content of
+/* each message. When it finds a problem, by default it returns a
+/* diagnostic status to the client, and leaves it up to the client
+/* to deal with the problem. Alternatively, the client can request
+/* the \fBcleanup\fR daemon to bounce the message back to the sender
+/* in case of trouble.
+/* STANDARDS
+/* RFC 822 (ARPA Internet Text Messages)
+/* DIAGNOSTICS
+/* Problems and transactions are logged to \fBsyslogd\fR(8).
+/* BUGS
+/* Table-driven rewriting rules make it hard to express \fBif then
+/* else\fR and other logical relationships.
+/* 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 Miscellaneous
+/* .ad
+/* .fi
+/* .IP \fBhopcount_limit\fR
+/* Limit the number of \fBReceived:\fR message headers.
+/* .SH "Address transformations"
+/* .ad
+/* .fi
+/* .IP \fBempty_address_recipient\fR
+/* The destination for undeliverable mail from <>. This
+/* substitution is done before all other address rewriting.
+/* .IP \fBcanonical_maps\fR
+/* Address mapping lookup table for sender and recipient addresses
+/* in envelopes and headers.
+/* .IP \fBrecipient_canonical_maps\fR
+/* Address mapping lookup table for envelope and header recipient
+/* addresses.
+/* .IP \fBsender_canonical_maps\fR
+/* Address mapping lookup table for envelope and header sender
+/* addresses.
+/* .IP \fBmasquerade_domains\fR
+/* List of domains that hide their subdomain structure.
+/* .IP \fBmasquerade_exceptions\fR
+/* List of user names that are not subject to address masquerading.
+/* .IP \fBvirtual_maps\fR
+/* Address mapping lookup table for envelope recipient addresses.
+/* .SH "Resource controls"
+/* .ad
+/* .fi
+/* .IP \fBduplicate_filter_limit\fR
+/* Limit the number of envelope recipients that are remembered.
+/* .IP \fBheader_size_limit\fR
+/* Limit the amount of memory in bytes used to process a message header.
+/* SEE ALSO
+/* canonical(5) canonical address lookup table format
+/* qmgr(8) queue manager daemon
+/* syslogd(8) system logging
+/* trivial-rewrite(8) address rewriting
+/* virtual(5) virtual address lookup table format
+/* FILES
+/* /etc/postfix/canonical*, canonical mapping table
+/* /etc/postfix/virtual*, virtual mapping table
+/* 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
+#include
+#include
+#include
+#include
+#include
+
+/* Utility library. */
+
+#include
+#include
+#include
+#include
+#include
+
+/* Global library. */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+/* Single-threaded server skeleton. */
+
+#include
+
+/* Application-specific. */
+
+#include "cleanup.h"
+
+ /*
+ * Global state: any queue files that we have open, so that the error
+ * handler can clean up in case of trouble.
+ */
+char *cleanup_path; /* queue file name */
+
+ /*
+ * Tunable parameters.
+ */
+int var_hopcount_limit; /* max mailer hop count */
+int var_header_limit; /* max header length */
+char *var_canonical_maps; /* common canonical maps */
+char *var_send_canon_maps; /* sender canonical maps */
+char *var_rcpt_canon_maps; /* recipient canonical maps */
+char *var_virtual_maps; /* virtual maps */
+char *var_masq_domains; /* masquerade domains */
+char *var_masq_exceptions; /* users not masqueraded */
+int var_dup_filter_limit; /* recipient dup filter */
+char *var_empty_addr; /* destination of bounced bounces */
+
+ /*
+ * Mappings.
+ */
+MAPS *cleanup_comm_canon_maps;
+MAPS *cleanup_send_canon_maps;
+MAPS *cleanup_rcpt_canon_maps;
+MAPS *cleanup_virtual_maps;
+ARGV *cleanup_masq_domains;
+
+/* cleanup_service - process one request to inject a message into the queue */
+
+static void cleanup_service(VSTREAM *src, char *unused_service, char **argv)
+{
+ char *junk;
+ static char *log_queues[] = {
+ MAIL_QUEUE_DEFER,
+ MAIL_QUEUE_BOUNCE,
+ 0,
+ };
+ char **cpp;
+
+ /*
+ * Sanity check. This service takes no command-line arguments.
+ */
+ if (argv[0])
+ msg_fatal("unexpected command-line argument: %s", argv[0]);
+
+ /*
+ * Initialize.
+ */
+ cleanup_state_alloc();
+ cleanup_src = src;
+
+ /*
+ * Open the queue file. Send the queue ID to the client so they can use
+ * it for logging purposes. For example, the SMTP server sends the queue
+ * id to the SMTP client after completion of the DATA command; and when
+ * the local delivery agent forwards a message, it logs the new queue id
+ * together with the old one. All this is done to make it easier for mail
+ * admins to follow a message while it hops from machine to machine.
+ *
+ * Save the queue file name, so that the runtime error handler can clean up
+ * in case of problems.
+ */
+ cleanup_handle = mail_stream_file(MAIL_QUEUE_INCOMING,
+ MAIL_CLASS_PUBLIC, MAIL_SERVICE_QUEUE);
+ cleanup_dst = cleanup_handle->stream;
+ cleanup_path = mystrdup(VSTREAM_PATH(cleanup_dst));
+ cleanup_queue_id = mystrdup(cleanup_handle->id);
+ if (msg_verbose)
+ msg_info("cleanup_service: open %s", cleanup_path);
+
+ /*
+ * If there is a time to get rid of spurious bounce/defer log files, this
+ * is it. The down side is that this costs performance for every message,
+ * while the probability of spurious bounce/defer log files is quite low.
+ * Perhaps we should put the queue file ID inside the defer and bounce
+ * files, so that the bounce and defer daemons can figure out if a file
+ * is a left-over from a previous message instance. For now, we play safe
+ * and check each time a new queue file is created.
+ */
+ for (cpp = log_queues; *cpp; cpp++) {
+ if (mail_queue_remove(*cpp, cleanup_queue_id) == 0)
+ msg_warn("%s: removed spurious %s log", *cpp, cleanup_queue_id);
+ else if (errno != ENOENT)
+ msg_fatal("%s: remove %s log: %m", *cpp, cleanup_queue_id);
+ }
+
+ /*
+ * Send the queue id to the client. Read client processing options. If we
+ * can't read the client processing options we can pretty much forget
+ * about the whole operation.
+ */
+ mail_print(cleanup_src, "%s", cleanup_queue_id);
+ if (mail_scan(src, "%d", &cleanup_flags) != 1) {
+ cleanup_errs |= CLEANUP_STAT_BAD;
+ cleanup_flags = 0;
+ }
+
+ /*
+ * If the client requests us to do the bouncing in case of problems,
+ * throw away the input only in case of real show-stopper errors, such as
+ * unrecognizable data (which should never happen) or insufficient space
+ * for the queue file (which will happen occasionally). Otherwise, throw
+ * away the input after any error. See the CLEANUP_OUT_OK() definition.
+ */
+ if (cleanup_flags & CLEANUP_FLAG_BOUNCE) {
+ cleanup_err_mask =
+ (CLEANUP_STAT_BAD | CLEANUP_STAT_WRITE | CLEANUP_STAT_SIZE);
+ } else {
+ cleanup_err_mask = ~0;
+ }
+
+ /*
+ * First, copy the envelope records to the queue file. Then, copy the
+ * message content (headers and body). Finally, attach any information
+ * extracted from message headers.
+ */
+ cleanup_envelope();
+ if (CLEANUP_OUT_OK())
+ cleanup_message();
+ if (CLEANUP_OUT_OK())
+ cleanup_extracted();
+
+ /*
+ * Now that we have captured the entire message, see if there are any
+ * other errors. For example, if the message needs to be bounced for lack
+ * of recipients. We want to turn on the execute bits on a file only when
+ * we want the queue manager to process it.
+ */
+ if (cleanup_recip == 0)
+ cleanup_errs |= CLEANUP_STAT_RCPT;
+
+ /*
+ * If there are no errors, be very picky about queue file write errors
+ * because we are about to tell the sender that it can throw away its
+ * copy of the message.
+ */
+ if (cleanup_errs == 0)
+ cleanup_errs |= mail_stream_finish(cleanup_handle);
+ else
+ mail_stream_cleanup(cleanup_handle);
+ cleanup_handle = 0;
+ cleanup_dst = 0;
+
+ /*
+ * If there was an error, remove the queue file, after optionally
+ * bouncing it. An incomplete message should never be bounced: it was
+ * canceled by the client, and may not even have an address to bounce to.
+ * That last test is redundant but we keep it just for robustness.
+ *
+ * If we are responsible for bouncing a message, we must must report success
+ * to the client unless the bounce message file could not be written
+ * (which is just as bad as not being able to write the message queue
+ * file in the first place).
+ *
+ * Do not log the arrival of a message that will be bounced by the client.
+ */
+#define CAN_BOUNCE() \
+ ((cleanup_errs & (CLEANUP_STAT_BAD | CLEANUP_STAT_WRITE)) == 0 \
+ && cleanup_sender != 0 \
+ && (cleanup_flags & CLEANUP_FLAG_BOUNCE) != 0)
+
+ if (cleanup_errs) {
+ if (CAN_BOUNCE()) {
+ if (bounce_append(BOUNCE_FLAG_CLEAN,
+ cleanup_queue_id, cleanup_recip ?
+ cleanup_recip : "", "cleanup", cleanup_time,
+ "%s", cleanup_strerror(cleanup_errs)) == 0
+ && bounce_flush(BOUNCE_FLAG_CLEAN,
+ MAIL_QUEUE_INCOMING,
+ cleanup_queue_id, cleanup_sender) == 0) {
+ cleanup_errs = 0;
+ } else {
+ msg_warn("%s: bounce message failure", cleanup_queue_id);
+ cleanup_errs = CLEANUP_STAT_WRITE;
+ }
+ }
+ if (REMOVE(cleanup_path))
+ msg_warn("remove %s: %m", cleanup_path);
+ }
+
+ /*
+ * Report the completion status back to the client. Order of operations
+ * matters very much: make sure that our queue file will not be deleted
+ * by the error handler AFTER we have taken responsibility for delivery.
+ * Better to deliver twice than to lose mail.
+ */
+ junk = cleanup_path;
+ cleanup_path = 0; /* don't delete upon error */
+ mail_print(cleanup_src, "%d", cleanup_errs);/* we're committed now */
+ if (msg_verbose)
+ msg_info("cleanup_service: status %d", cleanup_errs);
+ myfree(junk);
+
+ /*
+ * Cleanup internal state. This is simply complementary to the
+ * initializations at the beginning of this routine.
+ */
+ cleanup_state_free();
+}
+
+/* cleanup_all - callback for the runtime error handler */
+
+static void cleanup_all(void)
+{
+ if (cleanup_path && REMOVE(cleanup_path))
+ msg_warn("cleanup_all: remove %s: %m", cleanup_path);
+}
+
+/* cleanup_sig - cleanup after signal */
+
+static void cleanup_sig(int sig)
+{
+ cleanup_all();
+ exit(sig);
+}
+
+/* pre_jail_init - initialize before entering the chroot jail */
+
+static void pre_jail_init(void)
+{
+ if (*var_canonical_maps)
+ cleanup_comm_canon_maps =
+ maps_create(VAR_CANONICAL_MAPS, var_canonical_maps);
+ if (*var_send_canon_maps)
+ cleanup_send_canon_maps =
+ maps_create(VAR_SEND_CANON_MAPS, var_send_canon_maps);
+ if (*var_rcpt_canon_maps)
+ cleanup_rcpt_canon_maps =
+ maps_create(VAR_RCPT_CANON_MAPS, var_rcpt_canon_maps);
+ if (*var_virtual_maps)
+ cleanup_virtual_maps = maps_create(VAR_VIRTUAL_MAPS, var_virtual_maps);
+ if (*var_masq_domains)
+ cleanup_masq_domains = argv_split(var_masq_domains, " ,\t\r\n");
+}
+
+/* post_jail_init - initialize after entering the chroot jail */
+
+static void post_jail_init(void)
+{
+
+ /*
+ * Optionally set the file size resource limit. XXX This limits the
+ * message content to somewhat less than requested, because the total
+ * queue file size also includes envelope information. Unless people set
+ * really low limit, the difference is going to matter only when a queue
+ * file has lots of recipients.
+ */
+ if (var_message_limit > 0)
+ set_file_limit((off_t) var_message_limit);
+}
+
+/* main - the main program */
+
+int main(int argc, char **argv)
+{
+ static CONFIG_INT_TABLE int_table[] = {
+ VAR_HOPCOUNT_LIMIT, DEF_HOPCOUNT_LIMIT, &var_hopcount_limit, 1, 0,
+ VAR_HEADER_LIMIT, DEF_HEADER_LIMIT, &var_header_limit, 1, 0,
+ VAR_DUP_FILTER_LIMIT, DEF_DUP_FILTER_LIMIT, &var_dup_filter_limit, 0, 0,
+ 0,
+ };
+ static CONFIG_STR_TABLE str_table[] = {
+ VAR_CANONICAL_MAPS, DEF_CANONICAL_MAPS, &var_canonical_maps, 0, 0,
+ VAR_SEND_CANON_MAPS, DEF_SEND_CANON_MAPS, &var_send_canon_maps, 0, 0,
+ VAR_RCPT_CANON_MAPS, DEF_RCPT_CANON_MAPS, &var_rcpt_canon_maps, 0, 0,
+ VAR_VIRTUAL_MAPS, DEF_VIRTUAL_MAPS, &var_virtual_maps, 0, 0,
+ VAR_MASQ_DOMAINS, DEF_MASQ_DOMAINS, &var_masq_domains, 0, 0,
+ VAR_EMPTY_ADDR, DEF_EMPTY_ADDR, &var_empty_addr, 1, 0,
+ VAR_MASQ_EXCEPTIONS, DEF_MASQ_EXCEPTIONS, &var_masq_exceptions, 0, 0,
+ 0,
+ };
+
+ /*
+ * Clean up an incomplete queue file in case of a fatal run-time error,
+ * or after receiving SIGTERM from the master at shutdown time.
+ */
+ signal(SIGTERM, cleanup_sig);
+ msg_cleanup(cleanup_all);
+
+ /*
+ * Pass control to the single-threaded service skeleton.
+ */
+ single_server_main(argc, argv, cleanup_service,
+ MAIL_SERVER_INT_TABLE, int_table,
+ MAIL_SERVER_STR_TABLE, str_table,
+ MAIL_SERVER_PRE_INIT, pre_jail_init,
+ MAIL_SERVER_POST_INIT, post_jail_init,
+ 0);
+}
diff --git a/postfix/cleanup/cleanup.h b/postfix/cleanup/cleanup.h
new file mode 100644
index 000000000..56e42c28f
--- /dev/null
+++ b/postfix/cleanup/cleanup.h
@@ -0,0 +1,160 @@
+/*++
+/* NAME
+/* cleanup 3h
+/* SUMMARY
+/* canonicalize and enqueue message
+/* SYNOPSIS
+/* #include "cleanup.h"
+/* DESCRIPTION
+/* .nf
+
+ /*
+ * Utility library.
+ */
+#include
+#include
+#include
+
+ /*
+ * Global library.
+ */
+#include
+#include
+#include
+#include
+
+ /*
+ * These state variables are accessed by many functions, and there is only
+ * one instance of each. Rather than passing around lots and lots of
+ * parameters, or passing them around as part of a huge structure, we just
+ * make the variables global, because that is what they are.
+ */
+extern VSTRING *cleanup_inbuf; /* read buffer */
+extern VSTRING *cleanup_temp1; /* scratch buffer, local use only */
+extern VSTRING *cleanup_temp2; /* scratch buffer, local use only */
+extern VSTREAM *cleanup_src; /* current input stream */
+extern VSTREAM *cleanup_dst; /* current output stream */
+extern MAIL_STREAM *cleanup_handle; /* mail stream handle */
+extern char *cleanup_queue_id; /* queue file basename */
+extern time_t cleanup_time; /* posting time */
+extern char *cleanup_fullname; /* envelope sender full name */
+extern char *cleanup_sender; /* envelope sender address */
+extern char *cleanup_from; /* From: address */
+extern char *cleanup_resent_from; /* Resent-From: address */
+extern char *cleanup_recip; /* envelope recipient address */
+extern char *cleanup_return_receipt; /* return-receipt address */
+extern char *cleanup_errors_to; /* errors-to address */
+extern int cleanup_flags; /* processing options */
+extern int cleanup_errs; /* any badness experienced */
+extern int cleanup_err_mask; /* allowed badness */
+extern VSTRING *cleanup_header_buf; /* multi-record header */
+extern int cleanup_headers_seen; /* which headers were seen */
+extern int cleanup_hop_count; /* count of received: headers */
+extern ARGV *cleanup_recipients; /* recipients from regular headers */
+extern ARGV *cleanup_resent_recip; /* recipients from resent headers */
+extern char *cleanup_resent; /* any resent- header seen */
+extern BH_TABLE *cleanup_dups; /* recipient dup filter */
+
+ /*
+ * Mappings.
+ */
+extern MAPS *cleanup_comm_canon_maps;
+extern MAPS *cleanup_send_canon_maps;
+extern MAPS *cleanup_rcpt_canon_maps;
+extern MAPS *cleanup_virtual_maps;
+extern ARGV *cleanup_masq_domains;
+
+ /*
+ * Saved queue file name, so the file can be removed in case of a fatal
+ * run-time error.
+ */
+extern char *cleanup_path;
+
+ /*
+ * Tunable parameters.
+ */
+extern int var_bounce_limit; /* max bounce message size */
+extern int var_message_limit; /* max message size */
+extern int var_hopcount_limit; /* max mailer hop count */
+extern int var_header_limit; /* max header length */
+
+ /*
+ * cleanup_state.c
+ */
+extern void cleanup_state_alloc(void);
+extern void cleanup_state_free(void);
+
+ /*
+ * cleanup_out.c
+ */
+extern void cleanup_out(int, char *, int);
+extern void cleanup_out_string(int, char *);
+extern void cleanup_out_format(int, char *,...);
+
+#define CLEANUP_OUT_BUF(t, b) \
+ cleanup_out((t), vstring_str((b)), VSTRING_LEN((b)))
+
+#define CLEANUP_OUT_OK() \
+ ((cleanup_errs & cleanup_err_mask) == 0)
+
+ /*
+ * cleanup_envelope.c
+ */
+extern void cleanup_envelope(void);
+
+ /*
+ * cleanup_message.c
+ */
+extern void cleanup_message(void);
+
+ /*
+ * cleanup_extracted.c
+ */
+extern void cleanup_extracted(void);
+
+ /*
+ * cleanup_skip.o
+ */
+extern void cleanup_skip(void);
+
+ /*
+ * cleanup_rewrite.c
+ */
+extern void cleanup_rewrite_external(VSTRING *, const char *);
+extern void cleanup_rewrite_internal(VSTRING *, const char *);
+extern void cleanup_rewrite_tree(TOK822 *);
+
+ /*
+ * cleanup_map11.c
+ */
+extern void cleanup_map11_external(VSTRING *, MAPS *);
+extern void cleanup_map11_internal(VSTRING *, MAPS *);
+extern void cleanup_map11_tree(TOK822 *, MAPS *);
+
+ /*
+ * cleanup_map1n.c
+ */
+ARGV *cleanup_map1n_internal(char *, MAPS *);
+
+ /*
+ * cleanup_masquerade.c
+ */
+extern void cleanup_masquerade_external(VSTRING *, ARGV *);
+extern void cleanup_masquerade_internal(VSTRING *, ARGV *);
+extern void cleanup_masquerade_tree(TOK822 *, ARGV *);
+
+ /*
+ * Cleanup_recipient.c
+ */
+extern void cleanup_out_recipient(char *);
+
+/* 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
+/*--*/
diff --git a/postfix/cleanup/cleanup_envelope.c b/postfix/cleanup/cleanup_envelope.c
new file mode 100644
index 000000000..5824139f5
--- /dev/null
+++ b/postfix/cleanup/cleanup_envelope.c
@@ -0,0 +1,132 @@
+/*++
+/* NAME
+/* cleanup_envelope 3
+/* SUMMARY
+/* process envelope segment
+/* SYNOPSIS
+/* #include
+/*
+/* void cleanup_envelope()
+/* DESCRIPTION
+/* This module processes the envelope segment of a mail message.
+/* While copying records from input to output it validates the
+/* message structure, rewrites sender/recipient addresses
+/* to canonical form, and expands recipients according to
+/* entries in the virtual table.
+/* 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
+#include
+#include
+
+/* Utility library. */
+
+#include
+#include
+#include
+#include
+
+/* Global library. */
+
+#include
+#include
+#include
+#include
+#include
+
+/* Application-specific. */
+
+#include "cleanup.h"
+
+#define STR vstring_str
+
+/* cleanup_envelope - process envelope segment */
+
+void cleanup_envelope(void)
+{
+ VSTRING *clean_addr = vstring_alloc(100);
+ int type = 0;
+
+ /*
+ * The message content size record goes first, so it can easily be
+ * updated in place. This information takes precedence over any size
+ * estimate provided by the client. Size goes first so that it it easy to
+ * produce queue file reports.
+ */
+ cleanup_out_format(REC_TYPE_SIZE, REC_TYPE_SIZE_FORMAT, 0L);
+
+ /*
+ * XXX Rely on the front-end programs to enforce record size limits.
+ */
+ while (CLEANUP_OUT_OK()) {
+ if ((type = rec_get(cleanup_src, cleanup_inbuf, 0)) < 0) {
+ cleanup_errs |= CLEANUP_STAT_BAD;
+ break;
+ }
+ if (type == REC_TYPE_MESG) {
+ if (cleanup_sender == 0 || cleanup_time == 0) {
+ msg_warn("missing sender or time envelope record");
+ cleanup_errs |= CLEANUP_STAT_BAD;
+ }
+ break;
+ }
+ if (strchr(REC_TYPE_ENVELOPE, type) == 0) {
+ msg_warn("unexpected record type %d in envelope", type);
+ cleanup_errs |= CLEANUP_STAT_BAD;
+ break;
+ }
+ if (msg_verbose)
+ msg_info("envelope %c %s", type, STR(cleanup_inbuf));
+
+ if (type == REC_TYPE_TIME) {
+ cleanup_time = atol(STR(cleanup_inbuf));
+ CLEANUP_OUT_BUF(type, cleanup_inbuf);
+ } else if (type == REC_TYPE_FULL) {
+ cleanup_fullname = mystrdup(STR(cleanup_inbuf));
+ } else if (type == REC_TYPE_FROM) {
+ cleanup_rewrite_internal(clean_addr, STR(cleanup_inbuf));
+ if (cleanup_send_canon_maps)
+ cleanup_map11_internal(clean_addr, cleanup_send_canon_maps);
+ if (cleanup_comm_canon_maps)
+ cleanup_map11_internal(clean_addr, cleanup_comm_canon_maps);
+ if (cleanup_masq_domains)
+ cleanup_masquerade_internal(clean_addr, cleanup_masq_domains);
+ CLEANUP_OUT_BUF(type, clean_addr);
+ if (cleanup_sender == 0)
+ cleanup_sender = mystrdup(STR(clean_addr));
+ } else if (type == REC_TYPE_RCPT) {
+ cleanup_rewrite_internal(clean_addr, *STR(cleanup_inbuf) ?
+ STR(cleanup_inbuf) : var_empty_addr);
+ if (cleanup_rcpt_canon_maps)
+ cleanup_map11_internal(clean_addr, cleanup_rcpt_canon_maps);
+ if (cleanup_comm_canon_maps)
+ cleanup_map11_internal(clean_addr, cleanup_comm_canon_maps);
+ cleanup_out_recipient(STR(clean_addr));
+ if (cleanup_recip == 0)
+ cleanup_recip = mystrdup(STR(clean_addr));
+ } else {
+ CLEANUP_OUT_BUF(type, cleanup_inbuf);
+ }
+ }
+
+ /*
+ * XXX Keep reading in case of trouble, so that the sender is ready to
+ * receive our status report.
+ */
+ if (!CLEANUP_OUT_OK())
+ if (type >= 0)
+ cleanup_skip();
+
+ vstring_free(clean_addr);
+}
diff --git a/postfix/cleanup/cleanup_extracted.c b/postfix/cleanup/cleanup_extracted.c
new file mode 100644
index 000000000..783e93b59
--- /dev/null
+++ b/postfix/cleanup/cleanup_extracted.c
@@ -0,0 +1,116 @@
+/*++
+/* NAME
+/* cleanup_extracted 3
+/* SUMMARY
+/* process extracted segment
+/* SYNOPSIS
+/* #include "cleanup.h"
+/*
+/* void cleanup_extracted(void)
+/* DESCRIPTION
+/* This module processes message segments for information
+/* extracted from message content. It requires that the input
+/* contains no extracted information, and writes extracted
+/* information records to the output.
+/* 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
+
+/* Utility library. */
+
+#include
+#include
+#include
+#include
+#include
+
+/* Global library. */
+
+#include
+#include
+#include
+
+/* Application-specific. */
+
+#include "cleanup.h"
+
+/* cleanup_extracted - generate segment with header-extracted information */
+
+void cleanup_extracted(void)
+{
+ ARGV *rcpt;
+ char **cpp;
+ int type;
+
+ /*
+ * Do not complain in case of premature EOF - most likely the client
+ * aborted the operation.
+ *
+ * XXX Rely on the front-end programs to enforce record size limits.
+ */
+ if ((type = rec_get(cleanup_src, cleanup_inbuf, 0)) < 0) {
+ cleanup_errs |= CLEANUP_STAT_BAD;
+ return;
+ }
+
+ /*
+ * Require that the client sends an empty record group. It is OUR job to
+ * extract information from message headers. Clients can specify options
+ * via special message header lines.
+ *
+ * XXX Keep reading in case of trouble, so that the sender is ready for our
+ * status report.
+ */
+ if (type != REC_TYPE_END) {
+ msg_warn("unexpected record type %d in extracted segment", type);
+ cleanup_errs |= CLEANUP_STAT_BAD;
+ if (type >= 0)
+ cleanup_skip();
+ return;
+ }
+
+ /*
+ * Start the extracted segment.
+ */
+ cleanup_out_string(REC_TYPE_XTRA, "");
+
+ /*
+ * Always emit Return-Receipt-To and Errors-To records, and always emit
+ * them ahead of extracted recipients, so that the queue manager does not
+ * waste lots of time searching through large numbers of recipient
+ * addresses.
+ */
+ cleanup_out_string(REC_TYPE_RRTO, cleanup_return_receipt ?
+ cleanup_return_receipt : "");
+
+ cleanup_out_string(REC_TYPE_ERTO, cleanup_errors_to ?
+ cleanup_errors_to : cleanup_sender);
+
+ /*
+ * Optionally account for missing recipient envelope records.
+ */
+ if (cleanup_recip == 0) {
+ rcpt = (cleanup_resent[0] ? cleanup_resent_recip : cleanup_recipients);
+ argv_terminate(rcpt);
+ for (cpp = rcpt->argv; CLEANUP_OUT_OK() && *cpp; cpp++)
+ cleanup_out_recipient(*cpp);
+ if (rcpt->argv[0])
+ cleanup_recip = mystrdup(rcpt->argv[0]);
+ }
+
+ /*
+ * Terminate the extracted segment.
+ */
+ cleanup_out_string(REC_TYPE_END, "");
+}
diff --git a/postfix/cleanup/cleanup_map11.c b/postfix/cleanup/cleanup_map11.c
new file mode 100644
index 000000000..cac495f9a
--- /dev/null
+++ b/postfix/cleanup/cleanup_map11.c
@@ -0,0 +1,158 @@
+/*++
+/* NAME
+/* cleanup_map11 3
+/* SUMMARY
+/* one-to-one mapping
+/* SYNOPSIS
+/* #include
+/*
+/* void cleanup_map11_external(addr, maps)
+/* VSTRING *addr;
+/* MAPS *maps;
+/*
+/* void cleanup_map11_internal(addr, maps)
+/* VSTRING *addr;
+/* MAPS *maps;
+/*
+/* void cleanup_map11_tree(tree, maps)
+/* TOK822 *tree;
+/* MAPS *maps;
+/* DESCRIPTION
+/* This module performs one-to-one map lookups.
+/*
+/* If an address has a mapping, the lookup result is
+/* subjected to another iteration of rewriting and mapping.
+/* Recursion continues until an address maps onto itself,
+/* or until an unreasonable recursion level is reached.
+/*
+/* cleanup_map11_external() looks up the external (quoted) string
+/* form of an address in the maps specified via the \fImaps\fR argument.
+/*
+/* cleanup_map11_internal() is a wrapper around the
+/* cleanup_map11_external() routine that transforms from
+/* internal (quoted) string form to external form and back.
+/*
+/* cleanup_map11_tree() is a wrapper around the
+/* cleanup_map11_external() routine that transforms from
+/* internal parse tree form to external form and back.
+/* DIAGNOSTICS
+/* Recoverable errors: the global \fIcleanup_errs\fR flag is updated.
+/* SEE ALSO
+/* mail_addr_find(3) address lookups
+/* mail_addr_map(3) address mappings
+/* 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
+#include
+
+#ifdef STRCASECMP_IN_STRINGS_H
+#include
+#endif
+
+/* Utility library. */
+
+#include
+#include
+#include
+#include
+
+/* Global library. */
+
+#include
+#include
+#include
+
+/* Application-specific. */
+
+#include "cleanup.h"
+
+#define STR vstring_str
+#define MAX_RECURSION 10
+
+/* cleanup_map11_external - one-to-one table lookups */
+
+void cleanup_map11_external(VSTRING *addr, MAPS *maps)
+{
+ int count;
+ int expand_to_self;
+ ARGV *new_addr;
+ char *saved_addr;
+
+ /*
+ * Produce sensible output even in the face of a recoverable error. This
+ * simplifies error recovery considerably because we can do delayed error
+ * checking in one place, instead of having error handling code all over
+ * the place.
+ */
+ for (count = 0; count < MAX_RECURSION; count++) {
+ if ((new_addr = mail_addr_map(maps, STR(addr))) != 0) {
+ if (new_addr->argc > 1)
+ msg_warn("multi-valued %s entry for %s",
+ maps->title, STR(addr));
+ saved_addr = mystrdup(STR(addr));
+ vstring_strcpy(addr, new_addr->argv[0]);
+ expand_to_self = !strcasecmp(saved_addr, STR(addr));
+ myfree(saved_addr);
+ argv_free(new_addr);
+ if (expand_to_self)
+ return;
+ } else if (dict_errno != 0) {
+ msg_warn("%s: %s map lookup problem for %s",
+ cleanup_queue_id, maps->title, STR(addr));
+ cleanup_errs |= CLEANUP_STAT_WRITE;
+ return;
+ } else {
+ return;
+ }
+ }
+ msg_warn("%s: unreasonable %s map nesting for %s",
+ cleanup_queue_id, maps->title, STR(addr));
+}
+
+/* cleanup_map11_tree - rewrite address node */
+
+void cleanup_map11_tree(TOK822 *tree, MAPS *maps)
+{
+ VSTRING *temp = vstring_alloc(100);
+
+ /*
+ * Produce sensible output even in the face of a recoverable error. This
+ * simplifies error recovery considerably because we can do delayed error
+ * checking in one place, instead of having error handling code all over
+ * the place.
+ */
+ tok822_externalize(temp, tree->head, TOK822_STR_DEFL);
+ cleanup_map11_external(temp, maps);
+ tok822_free_tree(tree->head);
+ tree->head = tok822_scan(STR(temp), &tree->tail);
+ vstring_free(temp);
+}
+
+/* cleanup_map11_internal - rewrite address internal form */
+
+void cleanup_map11_internal(VSTRING *addr, MAPS *maps)
+{
+ VSTRING *temp = vstring_alloc(100);
+
+ /*
+ * Produce sensible output even in the face of a recoverable error. This
+ * simplifies error recovery considerably because we can do delayed error
+ * checking in one place, instead of having error handling code all over
+ * the place.
+ */
+ quote_822_local(temp, STR(addr));
+ cleanup_map11_external(temp, maps);
+ unquote_822_local(addr, STR(temp));
+ vstring_free(temp);
+}
diff --git a/postfix/cleanup/cleanup_map1n.c b/postfix/cleanup/cleanup_map1n.c
new file mode 100644
index 000000000..2addef510
--- /dev/null
+++ b/postfix/cleanup/cleanup_map1n.c
@@ -0,0 +1,133 @@
+/*++
+/* NAME
+/* cleanup_map1n 3
+/* SUMMARY
+/* one-to-many address mapping
+/* SYNOPSIS
+/* #include
+/*
+/* ARGV *cleanup_map1n_internal(addr)
+/* char *addr;
+/* DESCRIPTION
+/* This module implements one-to-many table mapping via table lookup.
+/* The process is recursive. The recursion terminates when the
+/* left-hand side appears in its own expansion, or when a maximal
+/* nesting level is reached.
+/*
+/* cleanup_map1n_internal() is the interface for addresses in
+/* internal (unquoted) form.
+/* DIAGNOSTICS
+/* Recoverable errors: the global \fIcleanup_errs\fR flag is updated.
+/* SEE ALSO
+/* mail_addr_map(3) address mappings
+/* mail_addr_find(3) address lookups
+/* 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
+#include
+
+#ifdef STRCASECMP_IN_STRINGS_H
+#include
+#endif
+
+/* Utility library. */
+
+#include
+#include
+#include
+#include
+#include
+
+/* Global library. */
+
+#include
+#include
+#include
+
+/* Application-specific. */
+
+#include "cleanup.h"
+
+/* cleanup_map1n_internal - one-to-many table lookups */
+
+ARGV *cleanup_map1n_internal(char *addr, MAPS *maps)
+{
+ ARGV *argv;
+ ARGV *lookup;
+ int count;
+ int i;
+ int arg;
+ int expand_to_self;
+ char *saved_lhs;
+
+ /*
+ * Initialize.
+ */
+ argv = argv_alloc(1);
+ argv_add(argv, addr, ARGV_END);
+ argv_terminate(argv);
+
+ /*
+ * Rewrite the address vector in place. With each map lookup result,
+ * split it into separate addresses, then rewrite and flatten each
+ * address, and repeat the process. Beware: argv is being changed, so we
+ * must index the array explicitly, instead of running along it with a
+ * pointer.
+ */
+#define UPDATE(ptr,new) { myfree(ptr); ptr = mystrdup(new); }
+#define MAX_RECURSION 1000
+#define MAX_EXPANSION 1000
+#define STR vstring_str
+
+ for (expand_to_self = 0, arg = 0; arg < argv->argc; arg++) {
+ if (argv->argc > MAX_EXPANSION) {
+ msg_warn("%s: unreasonable %s map expansion size for %s",
+ cleanup_queue_id, maps->title, addr);
+ break;
+ }
+ for (count = 0; /* void */ ; count++) {
+ if (count >= MAX_RECURSION) {
+ msg_warn("%s: unreasonable %s map nesting for %s",
+ cleanup_queue_id, maps->title, addr);
+ break;
+ }
+ if ((lookup = mail_addr_map(maps, argv->argv[arg])) != 0) {
+ saved_lhs = mystrdup(argv->argv[arg]);
+ for (i = 0; i < lookup->argc; i++) {
+ unquote_822_local(cleanup_temp1, lookup->argv[i]);
+ if (strcasecmp(saved_lhs, STR(cleanup_temp1)) == 0)
+ expand_to_self = 1;
+ if (i == 0) {
+ UPDATE(argv->argv[arg], STR(cleanup_temp1));
+ } else {
+ argv_add(argv, STR(cleanup_temp1), ARGV_END);
+ argv_terminate(argv);
+ }
+ }
+ myfree(saved_lhs);
+ argv_free(lookup);
+ if (expand_to_self)
+ return (argv);
+ } else if (dict_errno != 0) {
+ msg_warn("%s: %s map lookup problem for %s",
+ cleanup_queue_id, maps->title, addr);
+ cleanup_errs |= CLEANUP_STAT_WRITE;
+ return (argv);
+ } else {
+ break;
+ }
+ }
+ }
+ return (argv);
+}
diff --git a/postfix/cleanup/cleanup_masquerade.c b/postfix/cleanup/cleanup_masquerade.c
new file mode 100644
index 000000000..d00ecb795
--- /dev/null
+++ b/postfix/cleanup/cleanup_masquerade.c
@@ -0,0 +1,173 @@
+/*++
+/* NAME
+/* cleanup_masquerade 3
+/* SUMMARY
+/* address masquerading
+/* SYNOPSIS
+/* #include
+/*
+/* void cleanup_masquerade_external(addr, masq_domains)
+/* VSTRING *addr;
+/* ARGV *masq_domains;
+/*
+/* void cleanup_masquerade_internal(addr, masq_domains)
+/* VSTRING *addr;
+/* ARGV *masq_domains;
+/*
+/* void cleanup_masquerade_tree(tree, masq_domains)
+/* TOK822 *tree;
+/* ARGV *masq_domains;
+/* DESCRIPTION
+/* This module masquerades addresses, that is, it strips subdomains
+/* below domain names that are listed in the masquerade_domains
+/* configuration parameter, except for user names listed in the
+/* masquerade_exceptions configuration parameter.
+/*
+/* cleanup_masquerade_external() rewrites the external (quoted) string
+/* form of an address.
+/*
+/* cleanup_masquerade_internal() is a wrapper around the
+/* cleanup_masquerade_external() routine that transforms from
+/* internal (quoted) string form to external form and back.
+/*
+/* cleanup_masquerade_tree() is a wrapper around the
+/* cleanup_masquerade_external() routine that transforms from
+/* internal parse tree form to external form and back.
+/* DIAGNOSTICS
+/* 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
+#include
+
+#ifdef STRCASECMP_IN_STRINGS_H
+#include
+#endif
+
+/* Utility library. */
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+/* Global library. */
+
+#include
+#include
+#include
+
+/* Application-specific. */
+
+#include "cleanup.h"
+
+#define STR vstring_str
+
+/* cleanup_masquerade_external - masquerade address external form */
+
+void cleanup_masquerade_external(VSTRING *addr, ARGV *masq_domains)
+{
+ char *domain;
+ int domain_len;
+ char **masqp;
+ int masq_len;
+ char *parent;
+
+ /* Stuff for excluded names. */
+ static HTABLE *masq_except_table = 0;
+ char *saved_names;
+ char *name;
+ char *ptr;
+ int excluded;
+
+ /*
+ * First time, build a lookup table for excluded names.
+ */
+ if (*var_masq_exceptions && masq_except_table == 0) {
+ masq_except_table = htable_create(5);
+ ptr = saved_names = mystrdup(var_masq_exceptions);
+ while ((name = mystrtok(&ptr, ", \t\r\n")) != 0)
+ htable_enter(masq_except_table, name, (char *) 0);
+ myfree(saved_names);
+ }
+
+ /*
+ * Find the domain part.
+ */
+ if ((domain = strrchr(STR(addr), '@')) == 0)
+ return;
+ domain += 1;
+ domain_len = strlen(domain);
+
+ /*
+ * Don't masquerade excluded names (regardless of domain).
+ */
+ if (masq_except_table) {
+ name = mystrndup(STR(addr), domain - 1 - STR(addr));
+ excluded = (htable_locate(masq_except_table, name) != 0);
+ myfree(name);
+ if (excluded)
+ return;
+ }
+
+ /*
+ * If any parent domain matches the list of masquerade domains, replace
+ * the domain in the address and terminate. If the domain matches a
+ * masquerade domain, leave it alone. Order of specification matters.
+ */
+ for (masqp = masq_domains->argv; *masqp; masqp++) {
+ masq_len = strlen(*masqp);
+ if (masq_len == domain_len) {
+ if (strcasecmp(*masqp, domain) == 0)
+ break;
+ } else if (masq_len < domain_len) {
+ parent = domain + domain_len - masq_len;
+ if (parent[-1] == '.' && strcasecmp(*masqp, parent) == 0) {
+ if (msg_verbose)
+ msg_info("masquerade: %s -> %s", domain, *masqp);
+ vstring_truncate(addr, domain - STR(addr));
+ vstring_strcat(addr, *masqp);
+ break;
+ }
+ }
+ }
+}
+
+/* cleanup_masquerade_tree - masquerade address node */
+
+void cleanup_masquerade_tree(TOK822 *tree, ARGV *masq_domains)
+{
+ VSTRING *temp = vstring_alloc(100);
+
+ tok822_externalize(temp, tree->head, TOK822_STR_DEFL);
+ cleanup_masquerade_external(temp, masq_domains);
+ tok822_free_tree(tree->head);
+ tree->head = tok822_scan(STR(temp), &tree->tail);
+
+ vstring_free(temp);
+}
+
+/* cleanup_masquerade_internal - masquerade address internal form */
+
+void cleanup_masquerade_internal(VSTRING *addr, ARGV *masq_domains)
+{
+ VSTRING *temp = vstring_alloc(100);
+
+ quote_822_local(temp, STR(addr));
+ cleanup_masquerade_external(temp, masq_domains);
+ unquote_822_local(addr, STR(temp));
+
+ vstring_free(temp);
+}
diff --git a/postfix/cleanup/cleanup_message.c b/postfix/cleanup/cleanup_message.c
new file mode 100644
index 000000000..e357f52a9
--- /dev/null
+++ b/postfix/cleanup/cleanup_message.c
@@ -0,0 +1,491 @@
+/*++
+/* NAME
+/* cleanup_message 3
+/* SUMMARY
+/* process message segment
+/* SYNOPSIS
+/* #include "cleanup.h"
+/*
+/* void cleanup_message(void)
+/* DESCRIPTION
+/* This module processes message content segments.
+/* While copying records from input to output, it validates
+/* the input, rewrites sender/recipient addresses to canonical
+/* form, inserts missing message headers, and extracts information
+/* from message headers to be used later when generating the extracted
+/* output segment.
+/* 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
+#include
+#include
+#include
+#include
+#include
+
+#ifdef STRCASECMP_IN_STRINGS_H
+#include
+#endif
+
+/* Utility library. */
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+/* Global library. */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+/* Application-specific. */
+
+#include "cleanup.h"
+
+/* cleanup_out_header - output one header as a bunch of records */
+
+static void cleanup_out_header(void)
+{
+ char *start = vstring_str(cleanup_header_buf);
+ char *line;
+ char *next_line;
+
+ /*
+ * Prepend a tab to continued header lines that went through the address
+ * rewriting machinery. See cleanup_fold_header() below for the form of
+ * such header lines. NB: This code destroys the header. We could try to
+ * avoid clobbering it, but we're not going to use the data any further.
+ */
+ for (line = start; line; line = next_line) {
+ next_line = split_at(line, '\n');
+ if (line == start || ISSPACE(*line)) {
+ cleanup_out_string(REC_TYPE_NORM, line);
+ } else {
+ cleanup_out_format(REC_TYPE_NORM, "\t%s", line);
+ }
+ }
+}
+
+/* cleanup_fold_header - wrap address list header */
+
+static void cleanup_fold_header(void)
+{
+ char *start_line = vstring_str(cleanup_header_buf);
+ char *end_line;
+ char *next_line;
+ char *line;
+
+ /*
+ * A rewritten address list contains one address per line. The code below
+ * replaces newlines by spaces, to fit as many addresses on a line as
+ * possible (without rearranging the order of addresses). Prepending
+ * white space to the beginning of lines is delegated to the output
+ * routine.
+ */
+ for (line = start_line; line != 0; line = next_line) {
+ end_line = line + strcspn(line, "\n");
+ if (line > start_line) {
+ if (end_line - start_line < 70) { /* TAB counts as one */
+ line[-1] = ' ';
+ } else {
+ start_line = line;
+ }
+ }
+ next_line = *end_line ? end_line + 1 : 0;
+ }
+ cleanup_out_header();
+}
+
+/* cleanup_extract_internal - save unquoted copy of extracted address */
+
+static char *cleanup_extract_internal(VSTRING *buffer, TOK822 *addr)
+{
+
+ /*
+ * A little routine to stash away a copy of an address that we extracted
+ * from a message header line.
+ */
+ tok822_internalize(buffer, addr->head, TOK822_STR_DEFL);
+ return (mystrdup(vstring_str(buffer)));
+}
+
+/* cleanup_rewrite_sender - sender address rewriting */
+
+static void cleanup_rewrite_sender(HEADER_OPTS *hdr_opts)
+{
+ TOK822 *tree;
+ TOK822 **addr_list;
+ TOK822 **tpp;
+
+ if (msg_verbose)
+ msg_info("rewrite_sender: %s", hdr_opts->name);
+
+ /*
+ * Parse the header line, rewrite each address found, save copies of
+ * sender addresses, and regenerate the header line. Finally, pipe the
+ * result through the header line folding routine.
+ */
+ tree = tok822_parse(vstring_str(cleanup_header_buf)
+ + strlen(hdr_opts->name) + 1);
+ addr_list = tok822_grep(tree, TOK822_ADDR);
+ for (tpp = addr_list; *tpp; tpp++) {
+ cleanup_rewrite_tree(*tpp);
+ if (cleanup_send_canon_maps)
+ cleanup_map11_tree(*tpp, cleanup_send_canon_maps);
+ if (cleanup_comm_canon_maps)
+ cleanup_map11_tree(*tpp, cleanup_comm_canon_maps);
+ if (cleanup_masq_domains)
+ cleanup_masquerade_tree(*tpp, cleanup_masq_domains);
+ if (hdr_opts->type == HDR_FROM && cleanup_from == 0)
+ cleanup_from = cleanup_extract_internal(cleanup_header_buf, *tpp);
+ if (hdr_opts->type == HDR_RESENT_FROM && cleanup_resent_from == 0)
+ cleanup_resent_from =
+ cleanup_extract_internal(cleanup_header_buf, *tpp);
+ }
+ vstring_sprintf(cleanup_header_buf, "%s: ", hdr_opts->name);
+ tok822_externalize(cleanup_header_buf, tree, TOK822_STR_HEAD);
+ myfree((char *) addr_list);
+ tok822_free_tree(tree);
+ if ((hdr_opts->flags & HDR_OPT_DROP) == 0)
+ cleanup_fold_header();
+}
+
+/* cleanup_rewrite_recip - recipient address rewriting */
+
+static void cleanup_rewrite_recip(HEADER_OPTS *hdr_opts)
+{
+ TOK822 *tree;
+ TOK822 **addr_list;
+ TOK822 **tpp;
+
+ if (msg_verbose)
+ msg_info("rewrite_recip: %s", hdr_opts->name);
+
+ /*
+ * Parse the header line, rewrite each address found, save copies of
+ * recipient addresses, and regenerate the header line. Finally, pipe the
+ * result through the header line folding routine.
+ */
+ tree = tok822_parse(vstring_str(cleanup_header_buf)
+ + strlen(hdr_opts->name) + 1);
+ addr_list = tok822_grep(tree, TOK822_ADDR);
+ for (tpp = addr_list; *tpp; tpp++) {
+ cleanup_rewrite_tree(*tpp);
+ if (cleanup_rcpt_canon_maps)
+ cleanup_map11_tree(*tpp, cleanup_rcpt_canon_maps);
+ if (cleanup_comm_canon_maps)
+ cleanup_map11_tree(*tpp, cleanup_comm_canon_maps);
+ if (cleanup_masq_domains)
+ cleanup_masquerade_tree(*tpp, cleanup_masq_domains);
+ if (hdr_opts->type == HDR_RETURN_RECEIPT_TO && !cleanup_return_receipt)
+ cleanup_return_receipt =
+ cleanup_extract_internal(cleanup_header_buf, *tpp);
+ if (hdr_opts->type == HDR_ERRORS_TO && !cleanup_errors_to)
+ cleanup_errors_to =
+ cleanup_extract_internal(cleanup_header_buf, *tpp);
+ tok822_internalize(cleanup_temp1, tpp[0]->head, TOK822_STR_DEFL);
+ if (cleanup_recip == 0 && (hdr_opts->flags & HDR_OPT_EXTRACT) != 0)
+ argv_add((hdr_opts->flags & HDR_OPT_RR) ?
+ cleanup_resent_recip : cleanup_recipients,
+ vstring_str(cleanup_temp1), (char *) 0);
+ }
+ vstring_sprintf(cleanup_header_buf, "%s: ", hdr_opts->name);
+ tok822_externalize(cleanup_header_buf, tree, TOK822_STR_HEAD);
+ myfree((char *) addr_list);
+ tok822_free_tree(tree);
+ if ((hdr_opts->flags & HDR_OPT_DROP) == 0)
+ cleanup_fold_header();
+}
+
+/* cleanup_header - process one complete header line */
+
+static void cleanup_header(void)
+{
+ HEADER_OPTS *hdr_opts;
+
+
+ /*
+ * If this is an "unknown" header, just copy it to the output without
+ * even bothering to fold long lines. XXX Should split header lines that
+ * do not fit a REC_TYPE_NORM record.
+ */
+ if ((hdr_opts = header_opts_find(vstring_str(cleanup_header_buf))) == 0) {
+ cleanup_out_header();
+ }
+
+ /*
+ * Known header. Remember that we have seen at least one. Find out what
+ * we should do with this header: delete, count, rewrite. Note that we
+ * should examine headers even when they will be deleted from the output,
+ * because the addresses in those headers might be needed elsewhere.
+ */
+ else {
+ cleanup_headers_seen |= (1 << hdr_opts->type);
+ if (hdr_opts->type == HDR_MESSAGE_ID)
+ msg_info("%s: message-id=%s", cleanup_queue_id,
+ vstring_str(cleanup_header_buf) + strlen(hdr_opts->name) + 2);
+ if (hdr_opts->type == HDR_RESENT_MESSAGE_ID)
+ msg_info("%s: resent-message-id=%s", cleanup_queue_id,
+ vstring_str(cleanup_header_buf) + strlen(hdr_opts->name) + 2);
+ if (hdr_opts->type == HDR_RECEIVED)
+ if (++cleanup_hop_count >= var_hopcount_limit)
+ cleanup_errs |= CLEANUP_STAT_HOPS;
+ if (CLEANUP_OUT_OK()) {
+ if (hdr_opts->flags & HDR_OPT_RR)
+ cleanup_resent = "Resent-";
+ if (hdr_opts->flags & HDR_OPT_SENDER) {
+ cleanup_rewrite_sender(hdr_opts);
+ } else if (hdr_opts->flags & HDR_OPT_RECIP) {
+ cleanup_rewrite_recip(hdr_opts);
+ } else if ((hdr_opts->flags & HDR_OPT_DROP) == 0) {
+ cleanup_out_header();
+ }
+ }
+ }
+}
+
+/* cleanup_missing_headers - insert missing message headers */
+
+static void cleanup_missing_headers(void)
+{
+ char time_stamp[1024]; /* XXX locale dependent? */
+ struct tm *tp;
+ TOK822 *token;
+ char *from;
+
+ /*
+ * Add a missing Return-Path: header when the sender address is not
+ * empty. XXX Shouldn't this depend on the delivery transport being used?
+ * But, it is very tempting to use RFC822 as the basis for our canonical
+ * message representation. And, it is easy to delete an unwanted header.
+ */
+ if (*cleanup_sender != 0
+ && (cleanup_headers_seen & (1 << HDR_RETURN_PATH)) == 0) {
+ quote_822_local(cleanup_temp1, cleanup_sender);
+ cleanup_out_format(REC_TYPE_NORM, "Return-Path: <%s>",
+ vstring_str(cleanup_temp1));
+ }
+
+ /*
+ * Add a missing (Resent-)Message-Id: header. The message ID gives the
+ * time in GMT units, plus the local queue ID.
+ */
+ if ((cleanup_headers_seen & (1 << (cleanup_resent[0] ?
+ HDR_RESENT_MESSAGE_ID : HDR_MESSAGE_ID))) == 0) {
+ tp = gmtime(&cleanup_time);
+ strftime(time_stamp, sizeof(time_stamp), "%Y%m%d%H%M%S", tp);
+ cleanup_out_format(REC_TYPE_NORM, "%sMessage-Id: <%s.%s@%s>",
+ cleanup_resent, time_stamp, cleanup_queue_id, var_myhostname);
+ msg_info("%s: %smessage-id=<%s.%s@%s>",
+ cleanup_queue_id, *cleanup_resent ? "resent-" : "",
+ time_stamp, cleanup_queue_id, var_myhostname);
+ }
+
+ /*
+ * Add a missing (Resent-)Date: header. The date is in local time units,
+ * with the GMT offset at the end.
+ */
+ if ((cleanup_headers_seen & (1 << (cleanup_resent[0] ?
+ HDR_RESENT_DATE : HDR_DATE))) == 0) {
+ cleanup_out_format(REC_TYPE_NORM, "%sDate: %s",
+ cleanup_resent, mail_date(cleanup_time));
+ }
+
+ /*
+ * Add a missing (Resent-)From: header. If a (Resent-)From: header is
+ * present, see if we need a (Resent-)Sender: header.
+ */
+#define NOT_SPECIAL_SENDER(addr) (*(addr) != 0 \
+ && strcasecmp(addr, mail_addr_double_bounce()) != 0)
+
+ if ((cleanup_headers_seen & (1 << (cleanup_resent[0] ?
+ HDR_RESENT_FROM : HDR_FROM))) == 0) {
+ quote_822_local(cleanup_temp1, cleanup_sender);
+ vstring_sprintf(cleanup_temp2, "%sFrom: %s",
+ cleanup_resent, vstring_str(cleanup_temp1));
+ if (cleanup_fullname && *cleanup_fullname) {
+ vstring_strcat(cleanup_temp2, " (");
+ token = tok822_alloc(TOK822_COMMENT, cleanup_fullname);
+ tok822_externalize(cleanup_temp2, token, TOK822_STR_NONE);
+ tok822_free(token);
+ vstring_strcat(cleanup_temp2, ")");
+ }
+ CLEANUP_OUT_BUF(REC_TYPE_NORM, cleanup_temp2);
+ } else if ((cleanup_headers_seen & (1 << (cleanup_resent[0] ?
+ HDR_RESENT_SENDER : HDR_SENDER))) == 0
+ && NOT_SPECIAL_SENDER(cleanup_sender)) {
+ from = (cleanup_resent[0] ? cleanup_resent_from : cleanup_from);
+ if (from == 0 || strcasecmp(cleanup_sender, from) != 0) {
+ quote_822_local(cleanup_temp1, cleanup_sender);
+ cleanup_out_format(REC_TYPE_NORM, "%sSender: %s",
+ cleanup_resent, vstring_str(cleanup_temp1));
+ }
+ }
+}
+
+/* cleanup_message - process message content segment */
+
+void cleanup_message(void)
+{
+ char *myname = "cleanup_message";
+ long mesg_offset;
+ long data_offset;
+ long xtra_offset;
+ int in_header;
+ char *start;
+ int type = 0;
+
+ /*
+ * Write a dummy start-of-content segment marker. We'll update it with
+ * real file offset information after reaching the end of the message
+ * content.
+ */
+ if ((mesg_offset = vstream_ftell(cleanup_dst)) < 0)
+ msg_fatal("%s: vstream_ftell %s: %m", myname, cleanup_path);
+ cleanup_out_format(REC_TYPE_MESG, REC_TYPE_MESG_FORMAT, 0);
+ if ((data_offset = vstream_ftell(cleanup_dst)) < 0)
+ msg_fatal("%s: vstream_ftell %s: %m", myname, cleanup_path);
+
+ /*
+ * An unannounced end-of-input condition most likely means that the
+ * client did not want to send this message after all. Don't complain,
+ * just stop generating any further output.
+ *
+ * XXX Rely on the front-end programs to enforce record size limits.
+ */
+ in_header = 1;
+
+ while (CLEANUP_OUT_OK()) {
+
+ if ((type = rec_get(cleanup_src, cleanup_inbuf, 0)) < 0) {
+ cleanup_errs |= CLEANUP_STAT_BAD;
+ break;
+ }
+ if (strchr(REC_TYPE_CONTENT, type) == 0) {
+ msg_warn("%s: unexpected record type %d", myname, type);
+ cleanup_errs |= CLEANUP_STAT_BAD;
+ break;
+ }
+ start = vstring_str(cleanup_inbuf);
+
+ /*
+ * First, deal with header information that we have accumulated from
+ * previous input records. A whole record that starts with whitespace
+ * is a continuation of previous data.
+ *
+ * XXX Silently switch to body processing when some message header
+ * requires an unreasonable amount of storage, or when a message
+ * header record does not fit in a REC_TYPE_NORM type record.
+ */
+ if (VSTRING_LEN(cleanup_header_buf) > 0) {
+ if (VSTRING_LEN(cleanup_header_buf) < var_header_limit
+ && type == REC_TYPE_NORM && ISSPACE(*start)) {
+ VSTRING_ADDCH(cleanup_header_buf, '\n');
+ vstring_strcat(cleanup_header_buf, start);
+ continue;
+ }
+
+ /*
+ * No more input to append to this saved header. Do output
+ * processing and reset the saved header buffer.
+ */
+ VSTRING_TERMINATE(cleanup_header_buf);
+ cleanup_header();
+ VSTRING_RESET(cleanup_header_buf);
+ }
+
+ /*
+ * Switch to body processing if we didn't read a header or if the
+ * saved header requires an unreasonable amount of storage. Generate
+ * missing headers. Add one blank line when the message headers are
+ * immediately followed by a non-empty message body.
+ */
+ if (in_header
+ && (VSTRING_LEN(cleanup_header_buf) >= var_header_limit
+ || type != REC_TYPE_NORM
+ || !is_header(start))) {
+ in_header = 0;
+ cleanup_missing_headers();
+ if (type != REC_TYPE_XTRA && *start)/* output blank line */
+ cleanup_out_string(REC_TYPE_NORM, "");
+ }
+
+ /*
+ * If this is a header record, save it until we know that the header
+ * is complete. If this is a body record, copy it to the output
+ * immediately.
+ */
+ if (type == REC_TYPE_NORM || type == REC_TYPE_CONT) {
+ if (in_header) {
+ vstring_strcpy(cleanup_header_buf, start);
+ } else {
+ CLEANUP_OUT_BUF(type, cleanup_inbuf);
+ }
+ }
+
+ /*
+ * If we have reached the end of the message content segment, update
+ * the start-of-content marker, now that we know how large the
+ * message content segment is, and update the content size indicator
+ * at the beginning of the message envelope segment. vstream_fseek()
+ * implicitly flushes the stream, which may fail for various reasons.
+ */
+ else if (type == REC_TYPE_XTRA) {
+ if ((xtra_offset = vstream_ftell(cleanup_dst)) < 0)
+ msg_fatal("%s: vstream_ftell %s: %m", myname, cleanup_path);
+ if (vstream_fseek(cleanup_dst, mesg_offset, SEEK_SET) < 0) {
+ msg_warn("%s: write queue file: %m", cleanup_queue_id);
+ if (errno == EFBIG)
+ cleanup_errs |= CLEANUP_STAT_SIZE;
+ else
+ cleanup_errs |= CLEANUP_STAT_WRITE;
+ break;
+ }
+ cleanup_out_format(REC_TYPE_MESG, REC_TYPE_MESG_FORMAT, xtra_offset);
+ if (vstream_fseek(cleanup_dst, 0L, SEEK_SET) < 0)
+ msg_fatal("%s: vstream_fseek %s: %m", myname, cleanup_path);
+ cleanup_out_format(REC_TYPE_SIZE, REC_TYPE_SIZE_FORMAT,
+ xtra_offset - data_offset);
+ if (vstream_fseek(cleanup_dst, xtra_offset, SEEK_SET) < 0)
+ msg_fatal("%s: vstream_fseek %s: %m", myname, cleanup_path);
+ break;
+ }
+
+ /*
+ * This should never happen.
+ */
+ else {
+ msg_panic("%s: unexpected record type: %d", myname, type);
+ }
+ }
+
+ /*
+ * Keep reading in case of problems, so that the sender is ready to
+ * receive our status report.
+ */
+ if (CLEANUP_OUT_OK() == 0)
+ if (type >= 0)
+ cleanup_skip();
+}
diff --git a/postfix/cleanup/cleanup_out.c b/postfix/cleanup/cleanup_out.c
new file mode 100644
index 000000000..dd51383e6
--- /dev/null
+++ b/postfix/cleanup/cleanup_out.c
@@ -0,0 +1,117 @@
+/*++
+/* NAME
+/* cleanup_out 3
+/* SUMMARY
+/* record output support
+/* SYNOPSIS
+/* #include "cleanup.h"
+/*
+/* int CLEANUP_OUT_OK()
+/*
+/* void cleanup_out(type, data, len)
+/* int type;
+/* char *data;
+/* int len;
+/*
+/* void cleanup_out_string(type, str)
+/* int type;
+/* char *str;
+/*
+/* void CLEANUP_OUT_BUF(type, buf)
+/* int type;
+/* VSTRING *buf;
+/*
+/* void cleanup_out_format(type, format, ...)
+/* int type;
+/* char *format;
+/* DESCRIPTION
+/* This module writes records to the output stream.
+/*
+/* CLEANUP_OUT_OK() is a macro that evaluates to non-zero
+/* as long as it makes sense to produce output. All output
+/* routines below check for this condition.
+/*
+/* cleanup_out() is the main record output routine. It writes
+/* one record of the specified type, with the specified data
+/* and length to the output stream.
+/*
+/* cleanup_out_string() outputs one string as a record.
+/*
+/* CLEANUP_OUT_BUF() is an unsafe macro that outputs
+/* one string buffer as a record.
+/*
+/* cleanup_out_format() formats its arguments and writes
+/* the result as a record.
+/* 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
+#include
+#include /* 44BSD stdarg.h uses abort() */
+#include
+#include
+
+/* Utility library. */
+
+#include
+#include
+#include
+
+/* Global library. */
+
+#include
+#include
+#include
+
+/* Application-specific. */
+
+#include "cleanup.h"
+
+/* cleanup_out - output one single record */
+
+void cleanup_out(int type, char *string, int len)
+{
+ if (CLEANUP_OUT_OK()) {
+ if (rec_put(cleanup_dst, type, string, len) < 0) {
+ if (errno == EFBIG) {
+ msg_warn("queue file size limit exceeded");
+ cleanup_errs |= CLEANUP_STAT_SIZE;
+ } else {
+ msg_warn("%s: write queue file: %m", cleanup_queue_id);
+ cleanup_errs |= CLEANUP_STAT_WRITE;
+ }
+ }
+ }
+}
+
+/* cleanup_out_string - output string to one single record */
+
+void cleanup_out_string(int type, char *string)
+{
+ cleanup_out(type, string, strlen(string));
+}
+
+/* cleanup_out_format - output one formatted record */
+
+void cleanup_out_format(int type, char *fmt,...)
+{
+ static VSTRING *vp;
+ va_list ap;
+
+ if (vp == 0)
+ vp = vstring_alloc(100);
+ va_start(ap, fmt);
+ vstring_vsprintf(vp, fmt, ap);
+ va_end(ap);
+ CLEANUP_OUT_BUF(type, vp);
+}
diff --git a/postfix/cleanup/cleanup_out_recipient.c b/postfix/cleanup/cleanup_out_recipient.c
new file mode 100644
index 000000000..e1899a20b
--- /dev/null
+++ b/postfix/cleanup/cleanup_out_recipient.c
@@ -0,0 +1,72 @@
+/*++
+/* NAME
+/* cleanup_out_recipient 3
+/* SUMMARY
+/* envelope recipient output filter
+/* SYNOPSIS
+/* #include "cleanup.h"
+/*
+/* void cleanup_out_recipient(recipient)
+/* char *recipient;
+/* DESCRIPTION
+/* This module implements an envelope recipient output filter.
+/*
+/* cleanup_out_recipient() performs virtual table expansion
+/* and recipient duplicate filtering, and appends the
+/* resulting recipients to the output stream.
+/* CONFIGURATION
+/* .ad
+/* .fi
+/* .IP local_duplicate_filter_limit
+/* Upper bound to the size of the recipient duplicate filter.
+/* Zero means no limit; this may cause the mail system to
+/* become stuck.
+/* .IP virtual_maps
+/* list of virtual address lookup tables.
+/* 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
+
+/* Utility library. */
+
+#include
+
+/* Global library. */
+
+#include
+#include
+#include
+
+/* Application-specific. */
+
+#include "cleanup.h"
+
+/* cleanup_out_recipient - envelope recipient output filter */
+
+void cleanup_out_recipient(char *recip)
+{
+ ARGV *argv;
+ char **cpp;
+
+ if (cleanup_virtual_maps == 0) {
+ if (been_here_fixed(cleanup_dups, recip) == 0)
+ cleanup_out_string(REC_TYPE_RCPT, recip);
+ } else {
+ argv = cleanup_map1n_internal(recip, cleanup_virtual_maps);
+ for (cpp = argv->argv; *cpp; cpp++)
+ if (been_here_fixed(cleanup_dups, *cpp) == 0)
+ cleanup_out_string(REC_TYPE_RCPT, *cpp);
+ argv_free(argv);
+ }
+}
diff --git a/postfix/cleanup/cleanup_rewrite.c b/postfix/cleanup/cleanup_rewrite.c
new file mode 100644
index 000000000..31cc6ef44
--- /dev/null
+++ b/postfix/cleanup/cleanup_rewrite.c
@@ -0,0 +1,99 @@
+/*++
+/* NAME
+/* cleanup_rewrite 3
+/* SUMMARY
+/* address canonicalization
+/* SYNOPSIS
+/* #include
+/*
+/* void cleanup_rewrite_external(result, addr)
+/* VSTRING *result;
+/* const char *addr;
+/*
+/* void cleanup_rewrite_internal(result, addr)
+/* VSTRING *result;
+/* const char *addr;
+/*
+/* void cleanup_rewrite_tree(tree)
+/* TOK822 *tree;
+/* DESCRIPTION
+/* This module rewrites addresses to canonical form, adding missing
+/* domains and stripping source routes etc., and performs
+/* \fIcanonical\fR map lookups to map addresses to official form.
+/*
+/* cleanup_rewrite_init() performs one-time initialization.
+/*
+/* cleanup_rewrite_external() rewrites the external (quoted) string
+/* form of an address.
+/*
+/* cleanup_rewrite_internal() is a wrapper around the
+/* cleanup_rewrite_external() routine that transforms from
+/* internal (quoted) string form to external form and back.
+/*
+/* cleanup_rewrite_tree() is a wrapper around the
+/* cleanup_rewrite_external() routine that transforms from
+/* internal parse tree form to external form and back.
+/* DIAGNOSTICS
+/* 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
+
+/* Utility library. */
+
+#include
+#include
+
+/* Global library. */
+
+#include
+#include
+#include
+
+/* Application-specific. */
+
+#include "cleanup.h"
+
+#define STR vstring_str
+
+/* cleanup_rewrite_external - rewrite address external form */
+
+void cleanup_rewrite_external(VSTRING *result, const char *addr)
+{
+ rewrite_clnt(REWRITE_CANON, addr, result);
+}
+
+/* cleanup_rewrite_tree - rewrite address node */
+
+void cleanup_rewrite_tree(TOK822 *tree)
+{
+ VSTRING *temp = vstring_alloc(100);
+
+ tok822_externalize(temp, tree->head, TOK822_STR_DEFL);
+ cleanup_rewrite_external(temp, STR(temp));
+ tok822_free_tree(tree->head);
+ tree->head = tok822_scan(STR(temp), &tree->tail);
+ vstring_free(temp);
+}
+
+/* cleanup_rewrite_internal - rewrite address internal form */
+
+void cleanup_rewrite_internal(VSTRING *result, const char *addr)
+{
+ VSTRING *temp = vstring_alloc(100);
+
+ quote_822_local(temp, addr);
+ cleanup_rewrite_external(temp, STR(temp));
+ unquote_822_local(result, STR(temp));
+ vstring_free(temp);
+}
diff --git a/postfix/cleanup/cleanup_skip.c b/postfix/cleanup/cleanup_skip.c
new file mode 100644
index 000000000..00f73aa4b
--- /dev/null
+++ b/postfix/cleanup/cleanup_skip.c
@@ -0,0 +1,57 @@
+/*++
+/* NAME
+/* cleanup_skip 3
+/* SUMMARY
+/* skip further input
+/* SYNOPSIS
+/* #include "cleanup.h"
+/*
+/* void cleanup_skip(void)
+/* DESCRIPTION
+/* cleanup_skip() skips client input. This function is used after
+/* detecting an error. The idea is to drain input from the client
+/* so the client is ready to read the cleanup service status report.
+/* 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
+
+/* Utility library. */
+
+#include
+#include
+
+/* Global library. */
+
+#include
+#include
+
+/* Application-specific. */
+
+#include "cleanup.h"
+
+/* cleanup_skip - skip further client input */
+
+void cleanup_skip(void)
+{
+ int type;
+
+ msg_warn("skipping further client input");
+
+ /*
+ * XXX Rely on the front-end programs to enforce record size limits.
+ */
+ while ((type = rec_get(cleanup_src, cleanup_inbuf, 0)) > 0
+ && type != REC_TYPE_END)
+ /* void */ ;
+}
diff --git a/postfix/cleanup/cleanup_state.c b/postfix/cleanup/cleanup_state.c
new file mode 100644
index 000000000..fe73981e1
--- /dev/null
+++ b/postfix/cleanup/cleanup_state.c
@@ -0,0 +1,138 @@
+/*++
+/* NAME
+/* cleanup_state 3
+/* SUMMARY
+/* per-message state variables
+/* SYNOPSIS
+/* #include "cleanup.h"
+/*
+/* void cleanup_state_alloc(void)
+/*
+/* void cleanup_state_free(void)
+/* DESCRIPTION
+/* This module maintains about two dozen global (ugh) state variables
+/* that are used by many routines in the course of processing one
+/* message. Using globals seems to make more sense than passing around
+/* large parameter lists, or passing around a structure with a large
+/* number of components. We can get away with this because we need only
+/* one instance at a time.
+/*
+/* cleanup_state_alloc() initializes the per-message state variables.
+/*
+/* cleanup_state_free() cleans up.
+/* 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
+
+/* Utility library. */
+
+#include
+#include
+#include
+
+/* Global library. */
+
+#include
+#include
+
+/* Application-specific. */
+
+#include "cleanup.h"
+
+ /*
+ * These variables are accessed by many functions, and there is only one
+ * instance of each. Rather than passing around lots and lots of parameters,
+ * or passing them around in a structure, we just make the variables global,
+ * because that is what they are.
+ */
+VSTRING *cleanup_inbuf; /* read buffer */
+VSTRING *cleanup_temp1; /* scratch buffer, local use only */
+VSTRING *cleanup_temp2; /* scratch buffer, local use only */
+VSTREAM *cleanup_src; /* current input stream */
+VSTREAM *cleanup_dst; /* current output stream */
+MAIL_STREAM *cleanup_handle; /* mail stream handle */
+char *cleanup_queue_id; /* queue file basename */
+time_t cleanup_time; /* posting time */
+char *cleanup_fullname; /* envelope sender full name */
+char *cleanup_sender; /* envelope sender address */
+char *cleanup_from; /* From: address */
+char *cleanup_resent_from; /* Resent-From: address */
+char *cleanup_recip; /* envelope recipient address */
+char *cleanup_return_receipt; /* return-receipt address */
+char *cleanup_errors_to; /* errors-to address */
+int cleanup_flags; /* processing options */
+int cleanup_errs; /* any badness experienced */
+int cleanup_err_mask; /* allowed badness */
+VSTRING *cleanup_header_buf; /* multi-record header */
+int cleanup_headers_seen; /* which headers were seen */
+int cleanup_hop_count; /* count of received: headers */
+ARGV *cleanup_recipients; /* recipients from regular headers */
+ARGV *cleanup_resent_recip; /* recipients from resent headers */
+char *cleanup_resent; /* any resent- header seen */
+BH_TABLE *cleanup_dups; /* recipient dup filter */
+
+/* cleanup_state_alloc - initialize global state */
+
+void cleanup_state_alloc(void)
+{
+ cleanup_hop_count = 0;
+ cleanup_headers_seen = 0;
+ cleanup_time = 0;
+ cleanup_errs = 0;
+ cleanup_from = 0;
+ cleanup_fullname = 0;
+ cleanup_header_buf = vstring_alloc(100);
+ cleanup_queue_id = 0;
+ cleanup_recip = 0;
+ cleanup_return_receipt = 0;
+ cleanup_errors_to = 0;
+ cleanup_recipients = argv_alloc(2);
+ cleanup_resent = "";
+ cleanup_resent_from = 0;
+ cleanup_resent_recip = argv_alloc(2);
+ cleanup_sender = 0;
+ cleanup_temp1 = vstring_alloc(10);
+ cleanup_temp2 = vstring_alloc(10);
+ cleanup_inbuf = vstring_alloc(100);
+ cleanup_dups = been_here_init(var_dup_filter_limit, BH_FLAG_FOLD);
+}
+
+/* cleanup_state_free - destroy global state */
+
+void cleanup_state_free(void)
+{
+ if (cleanup_fullname)
+ myfree(cleanup_fullname);
+ if (cleanup_sender)
+ myfree(cleanup_sender);
+ if (cleanup_from)
+ myfree(cleanup_from);
+ if (cleanup_resent_from)
+ myfree(cleanup_resent_from);
+ if (cleanup_recip)
+ myfree(cleanup_recip);
+ if (cleanup_return_receipt)
+ myfree(cleanup_return_receipt);
+ if (cleanup_errors_to)
+ myfree(cleanup_errors_to);
+ vstring_free(cleanup_header_buf);
+ argv_free(cleanup_recipients);
+ argv_free(cleanup_resent_recip);
+ vstring_free(cleanup_temp1);
+ vstring_free(cleanup_temp2);
+ vstring_free(cleanup_inbuf);
+ if (cleanup_queue_id)
+ myfree(cleanup_queue_id);
+ been_here_free(cleanup_dups);
+}
diff --git a/postfix/conf/LICENSE b/postfix/conf/LICENSE
new file mode 100644
index 000000000..5e83ceb25
--- /dev/null
+++ b/postfix/conf/LICENSE
@@ -0,0 +1,59 @@
+Please read this carefully. You must agree to the following terms and
+conditions before installing the Secure Mailer or any related
+documentation ("Software"). If you do not agree to these terms
+and conditions, you may not install or use the Software.
+
+Permission to reproduce and create derivative works from the Software
+("Software Derivative Works") is hereby granted to you under the
+copyrights of International Business Machines Corporation ("IBM"). IBM
+also grants you the right to distribute the Software and Software
+Derivative Works.
+
+You grant IBM a world-wide, royalty-free right to use, copy,
+distribute, sublicense and prepare derivative works based upon any
+feedback, including materials, error corrections, Software Derivatives,
+enhancements, suggestions and the like that you provide to IBM relating
+to the Software.
+
+IBM licenses the Software to you on an "AS IS" basis, without warranty
+of any kind. IBM HEREBY EXPRESSLY DISCLAIMS ALL WARRANTIES OR
+CONDITIONS, EITHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OR CONDITIONS OF MERCHANTABILITY, NON
+INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE. You are solely
+responsible for determining the appropriateness of using this Software
+and assume all risks associated with the use and distribution of this
+Software, including but not limited to the risks of program errors,
+damage to or loss of data, programs or equipment, and unavailability or
+interruption of operations. IBM WILL NOT BE LIABLE FOR ANY DIRECT
+DAMAGES OR FOR ANY SPECIAL, INCIDENTAL, OR INDIRECT DAMAGES OR FOR ANY
+ECONOMIC CONSEQUENTIAL DAMAGES (INCLUDING LOST PROFITS OR SAVINGS),
+EVEN IF IBM HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. IBM
+will not be liable for the loss of, or damage to, your records or data,
+or any damages claimed by you based on a third party claim. You may
+not use the name "IBM" or any other IBM trademark without the prior
+written consent of IBM.
+
+You agree to distribute the Software and any Software Derivatives under
+a license agreement that: 1) is sufficient to notify all licensees of
+the Software and Software Derivatives that IBM assumes no liability for
+any claim that may arise regarding the Software or Software
+Derivatives, and 2) that disclaims all warranties, both express and
+implied, from IBM regarding the Software and Software Derivatives. (If
+you include this Agreement with any distribution of the Software or
+Software Derivatives you will have met this requirement.) You agree
+that you will not delete any copyright notices in the Software.
+
+In the event an intellectual property claim is made or appears likely
+to be made with respect to the Software, you agree to permit IBM to
+enable you to continue to use the Software, or to modify it, or replace
+it with software that is at least functionally equivalent. If IBM
+determines that none of these alternatives is reasonably available, you
+agree, at IBM's request, upon notice to you, to discontinue further
+distribution of the Software and to delete or destroy all copies of the
+Software you possess. This is IBM's entire obligation to you regarding
+any claim of infringement.
+
+This Agreement is the exclusive statement of your rights in the
+Software as provided by IBM. Except for the licenses granted to you in
+the second paragraph above, no other licenses are granted hereunder, by
+estoppel, implication or otherwise.
diff --git a/postfix/conf/access b/postfix/conf/access
new file mode 100644
index 000000000..f4ca6ea31
--- /dev/null
+++ b/postfix/conf/access
@@ -0,0 +1,69 @@
+#++
+# NAME
+# access 5
+# SUMMARY
+# format of Postfix access table
+# SYNOPSIS
+# \fBpostmap /etc/postfix/access\fR
+# DESCRIPTION
+# The optional \fBaccess\fR table directs the Postfix SMTP server
+# to selectively reject or accept mail from or to specific hosts,
+# domains, networks, host addresses or mail addresses.
+#
+# The table 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. After an update
+# it may take a minute or so before the change becomes visible.
+# Issue a \fBpostfix reload\fR command to eliminate the delay.
+#
+# The format of the access table is as follows:
+# .IP "blanks and comments"
+# Blank lines are ignored, as are lines beginning with `#'.
+# .IP "\fIpattern action\fR"
+# When \fIpattern\fR matches a mail address, domain or host address,
+# perform the corresponding \fIaction\fR.
+# PATTERNS
+# Patterns are tried in the order as listed below:
+# .ad
+# .fi
+# .IP \fIuser\fR@\fIdomain\fR
+# Matches the specified mail address.
+# .IP \fIdomain.name\fR
+# Matches the \fIdomain.name\fR itself and any subdomain thereof,
+# either in hostnames or in mail addresses. Top-level domains will
+# never be matched.
+# .IP \fIuser\fR@
+# Matches all mail addresses with the specified user part.
+# .IP \fInet.work.addr.ess\fR
+# .IP \fInet.work.addr\fR
+# .IP \fInet.work\fR
+# .IP \fInet\fR
+# Matches any host address in the specified network. A network
+# address is a sequence of one or more octets separated by ".".
+# ACTIONS
+# .ad
+# .fi
+# .IP "[\fB45\fR]\fIXX text\fR"
+# Reject the address etc. that matches the pattern, and respond with
+# the numerical code and text.
+# .IP \fBREJECT\fR
+# Reject the address etc. that matches the pattern. A generic
+# error response message is generated.
+# .IP \fBOK\fR
+# .IP "\fIAny other text\fR"
+# Accept the address etc. that matches the pattern.
+# BUGS
+# The table format does not understand quoting conventions.
+# SEE ALSO
+# postmap(1) create mapping table
+# smtpd(8) smtp server
+# 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
+#--
diff --git a/postfix/conf/aliases b/postfix/conf/aliases
new file mode 100644
index 000000000..4199c3087
--- /dev/null
+++ b/postfix/conf/aliases
@@ -0,0 +1,115 @@
+#++
+# NAME
+# aliases 5
+# SUMMARY
+# format of the Postfix alias database
+# SYNOPSIS
+# .fi
+# \fBpostalias\fR [\fB-c\fR \fIconfig_dir\fR] [\fB-v\fR]
+# [\fIfile_type\fR:]\fIinput_file\fR
+# DESCRIPTION
+# The \fBaliases\fR file provides a system-wide mechanism to
+# redirect mail for local recipients.
+#
+# The file serves as input to the \fBpostalias\fR(1) command. The
+# result, an indexed file in \fBdbm\fR or \fBdb\fR format, is
+# used for fast lookup by the mail system. After an update
+# it may take a minute or so before the change becomes visible.
+# Issue a \fBpostfix reload\fR command to eliminate the delay.
+#
+# The input and output file formats are expected to be compatible
+# with Sendmail version 8, and are expected to be suitable for the
+# use as NIS maps.
+#
+# Users can control delivery of their own mail by setting
+# up \fB.forward\fR files in their home directory.
+# Lines in per-user \fB.forward\fR files have the same syntax
+# as the right-hand side of \fBaliases\fR entries.
+#
+# The format of the alias database input file is as follows:
+# .IP \(bu
+# An alias definition has the form
+# .sp
+# .ti +5
+# \fIname\fR: \fIvalue1\fR, \fIvalue2\fR, \fI...\fR
+# .IP \(bu
+# Lines that begin with whitespace continue the previous line.
+# .IP \(bu
+# Blank lines are ignored, as are lines beginning with `#'.
+# .PP
+# The \fIname\fR is a local address (no domain part).
+# Use double quotes when the name contains any special characters
+# such as whitespace, `#', `:', or `@'. The \fIname\fR is folded to
+# lowercase, in order to make database lookups case insensitive.
+# .PP
+# In addition, when an alias exists for \fBowner-\fIname\fR, delivery
+# diagnostics are directed to that address, instead of to the originator.
+# This is typically used to direct delivery errors to the owner of
+# a mailing list, who is in a better position to deal with mailing
+# list delivery problems than the originator of the undelivered mail.
+# .PP
+# The \fIvalue\fR contains one or more of the following:
+# .IP \fIaddress\fR
+# Mail is forwarded to \fIaddress\fR, which is compatible
+# with the RFC 822 standard.
+# .IP \fI/file/name\fR
+# Mail is appended to \fI/file/name\fR. See \fBlocal\fR(8)
+# for details of delivery to file.
+# Delivery is not limited to regular files. For example, to dispose
+# of unwanted mail, deflect it to \fB/dev/null\fR.
+# .IP "|\fIcommand\fR"
+# Mail is piped into \fIcommand\fR. Commands that contain special
+# characters, such as whitespace, should be enclosed between double
+# quotes. See \fBlocal\fR(8) for details of delivery to command.
+# .sp
+# When the command fails, a limited amount of command output is
+# mailed back to the sender. The file \fB/usr/include/sysexits.h\fR
+# defines the expected exit status codes. For example, use
+# \fB|"exit 67"\fR to simulate a "user unknown" error, and
+# \fB|"exit 0"\fR to implement an expensive black hole.
+# .IP \fB:include:\fI/file/name\fR
+# Mail is sent to the destinations listed in the named file.
+# Lines in \fB:include:\fR files have the same syntax
+# as the right-hand side of alias entries.
+# .sp
+# A destination can be any destination that is described in this
+# manual page. However, delivery to "|\fIcommand\fR" and
+# \fI/file/name\fR is disallowed by default. To enable, edit the
+# \fBallow_mail_to_commands\fR and \fBallow_mail_to_files\fR
+# configuration parameters.
+# ADDRESS EXTENSION
+# .ad
+# .fi
+# When alias database search fails, and the recipient localpart
+# contains the optional recipient delimiter (e.g., \fIuser+foo\fR),
+# the search is repeated for the unextended address (e.g., \fIuser\fR).
+# CONFIGURATION PARAMETERS
+# .ad
+# .fi
+# The following \fBmain.cf\fR parameters are especially relevant to
+# this topic. See the Postfix \fBmain.cf\fR file for syntax details
+# and for default values. Use the \fBpostfix reload\fR command after
+# a configuration change.
+# .IP \fBalias_maps\fR
+# List of alias databases.
+# .IP \fBallow_mail_to_commands\fR
+# Restrict the usage of mail delivery to external command.
+# .IP \fBallow_mail_to_files\fR
+# Restrict the usage of mail delivery to external file.
+# .IP \fBrecipient_delimiter\fR
+# Delimiter that separates recipients from address extensions.
+# STANDARDS
+# RFC 822 (ARPA Internet Text Messages)
+# SEE ALSO
+# local(8) local delivery agent
+# postalias(1) alias database management
+# 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
+#--
diff --git a/postfix/conf/canonical b/postfix/conf/canonical
new file mode 100644
index 000000000..9cfde8d63
--- /dev/null
+++ b/postfix/conf/canonical
@@ -0,0 +1,110 @@
+#++
+# NAME
+# canonical 5
+# SUMMARY
+# format of Postfix canonical table
+# SYNOPSIS
+# \fBpostmap /etc/postfix/canonical\fR
+# DESCRIPTION
+# The optional \fBcanonical\fR file specifies an address mapping for
+# local and non-local addresses. The mapping is used by the
+# \fBcleanup\fR(8) daemon. The address mapping is recursive.
+#
+# The file 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. After an update
+# it may take a minute or so before the change becomes visible.
+# Issue a \fBpostfix reload\fR command to eliminate the delay.
+#
+# The \fBcanonical\fR mapping affects both message header addresses
+# (i.e. addresses that appear inside messages) and message envelope
+# addresses (for example, the addresses that are used in SMTP protocol
+# commands). Think Sendmail rule set \fBS3\fR, if you like.
+#
+# Typically, one would use the \fBcanonical\fR table to replace login
+# names by \fIFirstname.Lastname\fR, or to clean up addresses produced
+# by legacy mail systems.
+#
+# The \fBcanonical\fR mapping is not to be confused with \fIvirtual
+# domain\fR support. Use the \fBvirtual\fR(5) map for that purpose.
+#
+# The \fBcanonical\fR mapping is not to be confused with local aliasing.
+# Use the \fBaliases\fR(5) map for that purpose.
+#
+# The format of the \fBcanonical\fR table is as follows, mappings
+# being tried in the order as listed in this manual page:
+# .IP "blanks and comments"
+# Blank lines are ignored, as are lines beginning with `#'.
+# .IP "\fIuser\fR@\fIdomain address\fR"
+# \fIuser\fR@\fIdomain\fR is replaced by \fIaddress\fR. This form
+# has the highest precedence.
+# .sp
+# This form useful to clean up addresses produced by legacy mail systems.
+# It can also be used to produce \fIFirstname.Lastname\fR style
+# addresses, but see below for a simpler solution.
+# .IP "\fIuser address\fR"
+# \fIuser\fR@\fIsite\fR is replaced by \fIaddress\fR when \fIsite\fR is
+# equal to $\fBmyorigin\fR, when \fIsite\fR is listed in
+# $\fBmydestination\fR, or when it is listed in $\fBinet_interfaces\fR.
+# .sp
+# This form is useful for replacing login names by
+# \fIFirstname.Lastname\fR.
+# .IP "@\fIdomain address\fR"
+# Every address in \fIdomain\fR is replaced by \fIaddress\fR.
+# This form has the lowest precedence.
+# .PP
+# In all the above forms, when \fIaddress\fR has the form
+# @\fIotherdomain\fR, the result is the same user in \fIotherdomain\fR.
+# ADDRESS EXTENSION
+# .fi
+# .ad
+# When table lookup fails, and the address localpart contains the
+# optional recipient delimiter (e.g., \fIuser+foo\fR@\fIdomain\fR), the
+# search is repeated for the unextended address (e.g.
+# \fIuser\fR@\fIdomain\fR), and the unmatched extension is propagated
+# to the result of table lookup. The matching order is:
+# \fIuser+foo\fR@\fIdomain\fR, \fIuser\fR@\fIdomain\fR,
+# \fIuser+foo\fR, \fIuser\fR, and @\fIdomain\fR.
+# BUGS
+# The table format does not understand quoting conventions.
+# CONFIGURATION PARAMETERS
+# .ad
+# .fi
+# The following \fBmain.cf\fR parameters are especially relevant to
+# this topic. See the Postfix \fBmain.cf\fR file for syntax details
+# and for default values. Use the \fBpostfix reload\fR command after
+# a configuration change.
+# .IP \fBcanonical_maps\fR
+# List of canonical mapping tables.
+# .IP \fBrecipient_canonical_maps\fR
+# Address mapping lookup table for envelope and header recipient
+# addresses.
+# .IP \fBsender_canonical_maps\fR
+# Address mapping lookup table for envelope and header sender
+# addresses.
+# .PP
+# Other parameters of interest:
+# .IP \fBinet_interfaces\fR
+# The network interface addresses that this system receives mail on.
+# .IP \fBmasquerade_domains\fR
+# List of domains that hide their subdomain structure.
+# .IP \fBmasquerade_exceptions\fR
+# List of user names that are not subject to address masquerading.
+# .IP \fBmydestination\fR
+# List of domains that this mail system considers local.
+# .IP \fBmyorigin\fR
+# The domain that is appended to locally-posted mail.
+# SEE ALSO
+# cleanup(8) canonicalize and enqueue mail
+# postmap(1) create mapping table
+# virtual(5) virtual domain mapping
+# 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
+#--
diff --git a/postfix/conf/main.cf b/postfix/conf/main.cf
new file mode 100644
index 000000000..dcdd3cea3
--- /dev/null
+++ b/postfix/conf/main.cf
@@ -0,0 +1,322 @@
+# Global Postfix configuration file. This file lists only a subset
+# of all 100+ parameters. See the sample-xxx.cf files for a full list.
+#
+# The general format is lines with parameter = value pairs. Lines
+# that begin with whitespace continue the previous line. A value can
+# contain references to other $names or ${name}s.
+
+# LOCAL PATHNAME INFORMATION
+#
+# The queue_directory specifies the location of the Postfix queue.
+# This is also the root directory of Postfix daemons that run chrooted.
+# The contributed source code from http://www.postfix.org/ has examples
+# for setting up Postfix chroot environments on different UNIX systems.
+#
+queue_directory = /var/spool/postfix
+
+# The program_directory parameter specifies the default location of
+# Postfix support programs and daemons. This setting can be overruled
+# with the command_directory and daemon_directory parameters.
+#
+program_directory = /some/where/postfix/bin
+
+# The command_directory parameter specifies the location of all
+# postXXX commands. The default value is $program_directory.
+#
+#command_directory = /usr/sbin
+
+# The daemon_directory parameter specifies the location of all Postfix
+# daemon programs (i.e. programs listed in the master.cf file). The
+# default value is $program_directory. This directory must be owned
+# by root.
+#
+#daemon_directory = /usr/libexec/postfix
+
+# QUEUE AND PROCESS OWNERSHIP
+#
+# The mail_owner parameter specifies the owner of the Postfix queue
+# and of most Postfix daemon processes. Specify the name of a user
+# account THAT DOES NOT SHARE A GROUP WITH OTHER ACCOUNTS AND THAT
+# OWNS NO OTHER FILES OR PROCESSES ON THE SYSTEM. In particular,
+# don't specify nobody or daemon. PLEASE USE A DEDICATED USER.
+#
+#mail_owner = postfix
+
+# The default_privs parameter specifies the default rights used by
+# the local delivery agent for delivery to external file or command.
+# These rights are used in the absence of a recipient user context.
+# DO NOT SPECIFY A PRIVILEGED USER OR THE POSTFIX OWNER.
+#
+#default_privs = nobody
+
+# INTERNET HOST AND DOMAIN NAMES
+#
+# The myhostname parameter specifies the internet hostname of this
+# mail system. The default is to use the fully-qualified domain name
+# from gethostname(). $myhostname is used as a default value for many
+# other configuration parameters.
+#
+#myhostname = host.domain.name
+#myhostname = virtual.domain.name
+
+# The mydomain parameter specifies the local internet domain name.
+# The default is to use $myhostname minus the first component.
+# $mydomain is used as a default value for many other configuration
+# parameters.
+#
+#mydomain = domain.name
+
+# SENDING MAIL
+#
+# The myorigin parameter specifies the domain that locally-posted
+# mail appears to come from. The default is to append $myhostname,
+# which is fine for small sites. If you run a domain with multiple
+# machines, you should (1) change this to $mydomain and (2) set up
+# a domain-wide alias database that aliases each user to
+# user@that.users.mailhost.
+#
+#myorigin = $myhostname
+#myorigin = $mydomain
+
+# RECEIVING MAIL
+
+# The inet_interfaces parameter specifies the network interface
+# addresses that this mail system receives mail on. By default,
+# the software claims all active interfaces on the machine. The
+# parameter also controls delivery of mail to user@[ip.address].
+#
+#inet_interfaces = all
+#inet_interfaces = $myhostname
+#inet_interfaces = $myhostname, localhost
+
+# The mydestination parameter specifies the list of domains that this
+# machine considers itself the final destination for.
+#
+# The default is $myhostname + localhost.$mydomain. On a mail domain
+# gateway, you should also include $mydomain. Do not specify the
+# names of domains that this machine is backup MX host for. Specify
+# those names via the relay_domains or permit_mx_backup settings for
+# the SMTP server (see sample-smtpd.cf.
+#
+# The local machine is always the final destination for mail addressed
+# to user@[the.net.work.address] of an interface that the mail system
+# receives mail on (see the inet_interfaces parameter).
+#
+# Specify a list of host or domain names, /file/name or type:table
+# patterns, separated by commas and/or whitespace. A /file/name
+# pattern is replaced by its contents; a type:table is matched when
+# a name matches a lookup key. Continue long lines by starting the
+# next line with whitespace.
+#
+#mydestination = $myhostname, localhost.$mydomain
+#mydestination = $myhostname, localhost.$mydomain $mydomain
+#mydestination = $myhostname, localhost.$mydomain, $mydomain,
+# mail.$mydomain, www.$mydomain, ftp.$mydomain
+
+# INTERNET VERSUS INTRANET
+#
+# The relayhost parameter specifies the default host to send mail to
+# when no entry is matched in the optional transport(5) table. When
+# no relayhost is given, mail is routed directly to the destination.
+#
+# On an intranet, specify the organizational domain name. If your
+# internal DNS uses no MX records, specify the name of the intranet
+# gateway host instead.
+#
+# Specify a domain, host, host:port, [address] or [address:port].
+# Use the form [destination] to turn off MX lookups. See also the
+# default_transport parameter if you're connected via UUCP.
+#
+#relayhost = $mydomain
+#relayhost = gateway.my.domain
+#relayhost = uucphost
+#relayhost = [mail.$mydomain:9999]
+
+# DEFAULT TRANSPORT
+#
+# The default_transport parameter specifies the default message
+# delivery transport to use when no transport is explicitly given in
+# the optional transport(5) table.
+#
+#default_transport = smtp
+#default_transport = uucp
+
+# ADDRESS REWRITING
+#
+# Insert text from sample-rewrite.cf if you need to do address
+# masquerading.
+#
+# Insert text from sample-canonical.cf if you need to do address
+# rewriting, or if you need username->Firstname.Lastname mapping.
+
+# ADDRESS REDIRECTION (VIRTUAL DOMAIN)
+#
+# Insert text from sample-virtual.cf if you need virtual domain support.
+
+# "USER HAS MOVED" BOUNCE MESSAGES
+#
+# Insert text from sample-relocated.cf if you need "user has moved"
+# style bounce messages. Alternatively, you can bounce recipients
+# with an SMTP server access table. See sample-smtpd.cf.
+
+# TRANSPORT MAP
+#
+# Insert text from sample-transport.cf if you need explicit routing.
+
+# ALIAS DATABASE
+#
+# The alias_maps parameter specifies the list of alias databases used
+# by the local delivery agent. The default list is system dependent.
+# On systems with NIS, the default is to search the local alias
+# database, then the NIS alias database. See aliases(5) for syntax
+# details.
+#
+# If you change the alias database, run "postalias /etc/aliases" (or
+# wherever your system stores the mail alias file), or simply run
+# "newaliases" to build the necessary DBM or DB file.
+#
+# It will take a minute or so before changes become visible. Use
+# "postfix reload" to eliminate the delay.
+#
+#alias_maps = dbm:/etc/aliases
+#alias_maps = hash:/etc/aliases
+#alias_maps = hash:/etc/aliases, nis:mail.aliases
+
+# The alias_database parameter specifies the alias database(s) that
+# are built with "newaliases" or "sendmail -bi". This is a separate
+# configuration parameter, because alias_maps (see above) may specify
+# tables that are not necessarily all under control by Postfix.
+#
+#alias_database = dbm:/etc/aliases
+#alias_database = dbm:/etc/mail/aliases
+#alias_database = hash:/etc/aliases
+#alias_database = hash:/etc/aliases, hash:/opt/majordomo/aliases
+
+# ADDRESS EXTENSIONS (e.g., user+foo)
+#
+# The recipient_delimiter parameter specifies the separator between
+# user names and address extensions (user+foo). See canonical(5),
+# local(8), relocated(5) and virtual(5) for the effects this has on
+# aliases, canonical, virtual, relocated and .forward file lookups.
+# Basically, the software tries user+foo and .forward+foo before
+# trying user and .forward.
+#
+# recipient_delimiter = +
+
+# DELIVERY TO MAILBOX
+#
+# The home_mailbox parameter specifies the optional pathname of a
+# mailbox relative to a user's home directory. The default is to
+# deliver to the UNIX-style /var/spool/mail/user or /var/mail/user.
+# Specify "Maildir/" for qmail-style delivery (the / is required).
+#
+#home_mailbox = Mailbox
+#home_mailbox = Maildir/
+
+# The mailbox_command specifies the optional external command to use
+# instead of mailbox delivery. The command is run with proper HOME,
+# SHELL and LOGNAME settings.
+#
+# Avoid shell meta characters because they will force Postfix to run
+# an expensive shell process. Procmail alone is expensive enough.
+#
+#mailbox_command = /some/where/procmail
+
+# JUNK MAIL CONTROLS
+#
+# The controls listed here are only a very small subset. See the file
+# sample-smtpd.cf for an elaborate list of anti-UCE controls.
+
+# The relay_domains parameter restricts what domains (and subdomains
+# thereof) this mail system will relay mail from or to. See the
+# smtpd_recipient_restrictions restriction in the file sample-smtpd.cf.
+#
+# By default, Postfix relays mail only from or to sites in or below
+# $mydestination, or in the optional virtual domain list.
+#
+# Specify a list of hosts or domains, /file/name patterns or type:name
+# lookup tables, separated by commas and/or whitespace. Continue
+# long lines by starting the next line with whitespace. A file name
+# is replaced by its contents; a type:name table is matched when a
+# (parent) domain appears as lookup key.
+#
+# NOTE: Postfix will not automatically forward mail for domains that
+# list this system as their primary or backup MX host. See the
+# permit_mx_backup restriction in the file sample-smtpd.cf.
+#
+#relay_domains = $mydestination, $virtual_domains
+
+# The mynetworks parameter specifies the list of networks that are
+# local to this machine. The list is used by the anti-UCE software
+# to distinguish local clients from strangers. See permit_mynetworks
+# and smtpd_recipient_restrictions in the file sample-smtpd.cf file.
+#
+# The default is all networks attached to the machine: a complete
+# class A network, a complete class B network, and so on. If you want
+# stricter control, specify a list of network/mask patterns, where
+# the mask specifies the number of bits in the network part of a host
+# address. You can also specify the absolute pathname of a pattern
+# file instead of listing the patterns here.
+#
+#mynetworks = 168.100.189.0/28, 127.0.0.0/8
+#mynetworks = $config_directory/mynetworks
+
+# SHOW SOFTWARE VERSION OR NOT
+#
+# The smtpd_banner parameter specifies the text that follows the 220
+# status code in the SMTP greeting banner. Some people like to see
+# the mail version advertised. By default, Postfix shows no version.
+#
+# You MUST specify the $myhostname at the start of the text. When
+# the SMTP client sees its own hostname at the start of an SMTP
+# greeting banner it will report a mailer loop. That's better than
+# having a machine meltdown.
+#
+#smtpd_banner = $myhostname ESMTP $mail_name
+#smtpd_banner = $myhostname ESMTP $mail_name ($mail_version)
+
+# PARALLEL DELIVERY TO THE SAME DESTINATION
+#
+# How many parallel deliveries to the same user or domain? With local
+# delivery, it does not make sense to do massively parallel delivery
+# to the same user, because mailbox updates must happen sequentially,
+# and expensive pipelines in .forward files can cause disasters when
+# too many are run at the same time. With SMTP deliveries, 10
+# simultaneous connections to the same domain could be sufficient to
+# raise eyebrows.
+#
+# Each message delivery transport has its XXX_destination_concurrency_limit
+# parameter. The default is $default_destination_concurrency_limit.
+
+local_destination_concurrency_limit = 2
+default_destination_concurrency_limit = 10
+
+# DEBUGGING CONTROL
+#
+# The debug_peer_level parameter specifies the increment in verbose
+# logging level when an SMTP client or server host name or address
+# matches a pattern in the debug_peer_list parameter.
+#
+debug_peer_level = 2
+
+# The debug_peer_list parameter specifies an optional list of domain
+# or network patterns, /file/name patterns or type:name tables. When
+# an SMTP client or server host name or address matches a pattern,
+# increase the verbose logging level by the amount specified in the
+# debug_peer_level parameter.
+#
+# debug_peer_list = 127.0.0.1
+# debug_peer_list = some.domain
+
+# The debugger_command specifies the external command that is executed
+# when a Postfix daemon program is run with the -D option.
+#
+# Use "command .. & sleep 5" so that the debugger can attach before
+# the process marches on. If you use an X-based debugger, be sure to
+# set up your XAUTHORITY environment variable before starting Postfix.
+#
+debugger_command =
+ PATH=/usr/bin:/usr/X11R6/bin
+ xxgdb $daemon_directory/$process_name $process_id & sleep 5
+
+# Other configurable parameters.
diff --git a/postfix/conf/master.cf b/postfix/conf/master.cf
new file mode 100644
index 000000000..595cbca3f
--- /dev/null
+++ b/postfix/conf/master.cf
@@ -0,0 +1,61 @@
+#
+# Postfix master process configuration file. Each line describes how
+# a mailer component program should be run. The fields that make up
+# each line are described below. A "-" field value requests that a
+# default value be used for that field.
+#
+# Service: any name that is valid for the specified transport type
+# (the next field). With INET transports, a service is specified as
+# host:port. The host part (and colon) may be omitted. Either host
+# or port may be given in symbolic form or in numeric form.
+#
+# Transport type: "inet" for Internet sockets, "unix" for UNIX-domain
+# sockets, "fifo" for named pipes.
+#
+# Private: whether or not access is restricted to the mail system.
+# Default is private service. Internet (inet) sockets can't be private.
+#
+# Unprivileged: whether the service runs with root privileges or as
+# the owner of the Postfix system (the owner name is controlled by the
+# mail_owner configuration variable in the main.cf file).
+#
+# Chroot: whether or not the service runs chrooted to the mail queue
+# directory (pathname is controlled by the queue_directory configuration
+# variable in the main.cf file). Presently, all Postfix daemons can run
+# chrooted, except for the pipe and local daemons. The contributed
+# source code from http://www.postfix.org/ describes how to set up
+# a Postfix chroot environment for your type of machine.
+#
+# Wakeup time: automatically wake up the named service after the
+# specified number of seconds. Specify 0 for no wakeup. Presently,
+# only the local pickup and queue manager daemons need a wakeup timer.
+#
+# Max procs: the maximum number of processes that may execute this
+# service simultaneously. Default is to use a globally configurable
+# limit (the default_process_limit configuration parameter in main.cf).
+#
+# Command + args: the command to be executed. The command name is
+# relative to the Postfix program directory (pathname is controlled by
+# the program_directory configuration variable). Adding one or more
+# -v options turns on verbose logging for that service; adding a -D
+# option enables symbolic debugging (see the debugger_command variable
+# in the main.cf configuration file).
+#
+# ==========================================================================
+# service type private unpriv chroot wakeup maxproc command + args
+# (yes) (yes) (yes) (never) (50)
+# ==========================================================================
+smtp inet n - n - - smtpd
+pickup fifo n n n 60 1 pickup
+cleanup unix - - n - 0 cleanup
+qmgr fifo n - n 300 1 qmgr
+rewrite unix - - n - - trivial-rewrite
+bounce unix - - n - 0 bounce
+defer unix - - n - 0 bounce
+smtp unix - - n - - smtp
+showq unix n - n - - showq
+local unix - n n - - local
+#local unix - n n - - pipe
+# user=cyrus argv=/cyrus/bin/deliver -e -q -m ${extension} ${user}
+uucp unix - n n - - pipe
+ flags=F user=uucp argv=uux -r -n -z -a$sender - $nexthop!rmail ($recipient)
diff --git a/postfix/conf/postfix-script-nosgid b/postfix/conf/postfix-script-nosgid
new file mode 100755
index 000000000..a4545bf7d
--- /dev/null
+++ b/postfix/conf/postfix-script-nosgid
@@ -0,0 +1,218 @@
+#!/bin/sh
+
+#++
+# NAME
+# postfix-script 1
+# SUMMARY
+# execute Postfix administrative commands
+# SYNOPSIS
+# \fBpostfix-script\fR \fIcommand\fR
+# DESCRIPTION
+# The \fBfBpostfix-script\fR script executes Postfix administrative
+# commands in an environtment that is set up by the \fBpostfix\fR(1)
+# command.
+# SEE ALSO
+# master(8) Postfix master program
+# postfix(1) Postfix administrative interface
+# 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
+#--
+
+# Avoid POSIX death due to SIGHUP when some parent process exits.
+
+trap '' 1
+
+case $daemon_directory in
+"") echo This script must be run by the postfix command. 1>&2
+ echo Do not run directly. 1>&2
+ exit 1
+esac
+
+LOGGER="$command_directory/postlog -t postfix-script"
+INFO="$LOGGER -p info"
+WARN="$LOGGER -p warn"
+ERROR="$LOGGER -p error"
+FATAL="$LOGGER -p fatal"
+PANIC="$LOGGER -p panic"
+
+umask 022
+
+#
+# LINUX by default does not synchronously update directories -
+# that's dangerous for mail.
+#
+if [ -x /usr/bin/chattr ]
+then
+ CHATTR="/usr/bin/chattr +S"
+else
+ CHATTR=:
+fi
+
+#
+# Can't do much without these in place.
+#
+cd $command_directory || {
+ $FATAL no Postfix command directory $command_directory!
+ exit 1
+}
+cd $daemon_directory || {
+ $FATAL no Postfix daemon directory $daemon_directory!
+ exit 1
+}
+cd $config_directory || {
+ $FATAL no Postfix configuration directory $config_directory!
+ exit 1
+}
+cd $queue_directory || {
+ $FATAL no Postfix queue directory $queue_directory!
+ exit 1
+}
+
+#
+# Parse JCL
+#
+case $1 in
+
+start_msg)
+
+ echo "Start postfix"
+ ;;
+
+stop_msg)
+
+ echo "Stop postfix"
+ ;;
+
+start)
+
+ $daemon_directory/master -t 2>/dev/null || {
+ $FATAL the Postfix mail system is already running
+ exit 1
+ }
+ $config_directory/postfix-script check || {
+ $FATAL Postfix integrity check failed!
+ exit 1
+ }
+ $INFO starting the Postfix mail system
+ $daemon_directory/master &
+ ;;
+
+drain)
+
+ $daemon_directory/master -t 2>/dev/null && {
+ $FATAL the Postfix mail system is not running
+ exit 1
+ }
+ $INFO stopping the Postfix mail system
+ kill -9 `sed 1q pid/master.pid`
+ ;;
+
+stop)
+
+ $daemon_directory/master -t 2>/dev/null && {
+ $FATAL the Postfix mail system is not running
+ exit 1
+ }
+ $INFO stopping the Postfix mail system
+ kill `sed 1q pid/master.pid`
+ ;;
+
+abort)
+
+ $daemon_directory/master -t 2>/dev/null && {
+ $FATAL the Postfix mail system is not running
+ exit 1
+ }
+ $INFO aborting the Postfix mail system
+ kill `sed 1q pid/master.pid`
+ ;;
+
+reload)
+
+ $daemon_directory/master -t 2>/dev/null && {
+ $FATAL the Postfix mail system is not running
+ exit 1
+ }
+ $INFO refreshing the Postfix mail system
+ kill -HUP `cat pid/master.pid`
+ ;;
+
+flush)
+
+ cd $queue_directory || {
+ $FATAL no Postfix queue directory $queue_directory!
+ exit 1
+ }
+ $command_directory/postkick public qmgr DFA
+ ;;
+
+check)
+
+ for dir in $daemon_directory $config_directory $queue_directory
+ do
+ ls -lLd $dir | (grep root >/dev/null ||
+ $WARN not owned by root: $dir)
+ done
+
+ find $daemon_directory/* $config_directory/* ! -user root \
+ -exec $WARN not owned by root: {} \;
+
+ find $queue_directory/* $config_directory/* -name '*core' \
+ -exec $WARN core file: {} \; 2>/dev/null
+
+ test -d maildrop || {
+ $WARN creating missing Postfix maildrop directory
+ mkdir maildrop || exit 1
+ chmod 1733 maildrop
+ chown $mail_owner maildrop
+ }
+ test -d pid || {
+ $WARN creating missing Postfix pid directory
+ mkdir pid || exit 1
+ chmod 755 pid
+ chown $mail_owner pid
+ }
+ for dir in incoming active bounce defer deferred saved corrupt; do
+ test -d $dir || {
+ $WARN creating missing Postfix $dir directory
+ mkdir $dir || exit 1
+ chmod 700 $dir; $CHATTR $dir
+ chown $mail_owner $dir
+ }
+ done
+ test -d public || {
+ $WARN creating missing Postfix public directory
+ mkdir public || exit 1
+ chmod 755 public
+ chown $mail_owner public
+ }
+ test -d private || {
+ $WARN creating missing Postfix private directory
+ mkdir private || exit 1
+ chmod 700 private
+ chown $mail_owner private
+ }
+ find `ls -d $queue_directory/* | \
+ egrep '/(incoming|active|defer|deferred|bounce|saved|corrupt|public|private)$'` \
+ ! \( -type p -o -type s \) ! -user $mail_owner \
+ -exec $WARN not owned by $mail_owner: {} \;
+
+ find corrupt -type f -exec $WARN damaged message: {} \;
+
+ # XXX also: look for weird stuff, weird permissions, etc.
+ ;;
+
+*)
+
+ $FATAL "usage: postfix start (or stop, reload, abort, flush, or check)"
+ exit 1
+ ;;
+
+esac
diff --git a/postfix/conf/postfix-script-sgid b/postfix/conf/postfix-script-sgid
new file mode 100755
index 000000000..7e6b9861c
--- /dev/null
+++ b/postfix/conf/postfix-script-sgid
@@ -0,0 +1,219 @@
+#!/bin/sh
+
+#++
+# NAME
+# postfix-script 1
+# SUMMARY
+# execute Postfix administrative commands
+# SYNOPSIS
+# \fBpostfix-script\fR \fIcommand\fR
+# DESCRIPTION
+# The \fBfBpostfix-script\fR script executes Postfix administrative
+# commands in an environtment that is set up by the \fBpostfix\fR(1)
+# command.
+# SEE ALSO
+# master(8) Postfix master program
+# postfix(1) Postfix administrative interface
+# 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
+#--
+
+# Avoid POSIX death due to SIGHUP when some parent process exits.
+
+trap '' 1
+
+case $daemon_directory in
+"") echo This script must be run by the postfix command. 1>&2
+ echo Do not run directly. 1>&2
+ exit 1
+esac
+
+LOGGER="$command_directory/postlog -t postfix-script"
+INFO="$LOGGER -p info"
+WARN="$LOGGER -p warn"
+ERROR="$LOGGER -p error"
+FATAL="$LOGGER -p fatal"
+PANIC="$LOGGER -p panic"
+
+umask 022
+
+#
+# LINUX by default does not synchronously update directories -
+# that's dangerous for mail.
+#
+if [ -x /usr/bin/chattr ]
+then
+ CHATTR="/usr/bin/chattr +S"
+else
+ CHATTR=:
+fi
+
+#
+# Can't do much without these in place.
+#
+cd $command_directory || {
+ $FATAL no Postfix command directory $command_directory!
+ exit 1
+}
+cd $daemon_directory || {
+ $FATAL no Postfix daemon directory $daemon_directory!
+ exit 1
+}
+cd $config_directory || {
+ $FATAL no Postfix configuration directory $config_directory!
+ exit 1
+}
+cd $queue_directory || {
+ $FATAL no Postfix queue directory $queue_directory!
+ exit 1
+}
+
+#
+# Parse JCL
+#
+case $1 in
+
+start_msg)
+
+ echo "Start postfix"
+ ;;
+
+stop_msg)
+
+ echo "Stop postfix"
+ ;;
+
+start)
+
+ $daemon_directory/master -t 2>/dev/null || {
+ $FATAL the Postfix mail system is already running
+ exit 1
+ }
+ $config_directory/postfix-script check || {
+ $FATAL Postfix integrity check failed!
+ exit 1
+ }
+ $INFO starting the Postfix mail system
+ $daemon_directory/master &
+ ;;
+
+drain)
+
+ $daemon_directory/master -t 2>/dev/null && {
+ $FATAL the Postfix mail system is not running
+ exit 1
+ }
+ $INFO stopping the Postfix mail system
+ kill -9 `sed 1q pid/master.pid`
+ ;;
+
+stop)
+
+ $daemon_directory/master -t 2>/dev/null && {
+ $FATAL the Postfix mail system is not running
+ exit 1
+ }
+ $INFO stopping the Postfix mail system
+ kill `sed 1q pid/master.pid`
+ ;;
+
+abort)
+
+ $daemon_directory/master -t 2>/dev/null && {
+ $FATAL the Postfix mail system is not running
+ exit 1
+ }
+ $INFO aborting the Postfix mail system
+ kill `sed 1q pid/master.pid`
+ ;;
+
+reload)
+
+ $daemon_directory/master -t 2>/dev/null && {
+ $FATAL the Postfix mail system is not running
+ exit 1
+ }
+ $INFO refreshing the Postfix mail system
+ kill -HUP `cat pid/master.pid`
+ ;;
+
+flush)
+
+ cd $queue_directory || {
+ $FATAL no Postfix queue directory $queue_directory!
+ exit 1
+ }
+ $command_directory/postkick public qmgr DFA
+ ;;
+
+check)
+
+ for dir in $daemon_directory $config_directory $queue_directory
+ do
+ ls -lLd $dir | (grep root >/dev/null ||
+ $WARN not owned by root: $dir)
+ done
+
+ find $daemon_directory/* $config_directory/* ! -user root \
+ -exec $WARN not owned by root: {} \;
+
+ find $queue_directory/* $config_directory/* -name '*core' \
+ -exec $WARN core file: {} \; 2>/dev/null
+
+ test -d maildrop || {
+ $WARN creating missing Postfix maildrop directory
+ mkdir maildrop || exit 1
+ chmod 730 maildrop
+ chown $mail_owner maildrop
+ chgrp maildrop maildrop
+ }
+ test -d pid || {
+ $WARN creating missing Postfix pid directory
+ mkdir pid || exit 1
+ chmod 755 pid
+ chown $mail_owner pid
+ }
+ for dir in incoming active bounce defer deferred saved corrupt; do
+ test -d $dir || {
+ $WARN creating missing Postfix $dir directory
+ mkdir $dir || exit 1
+ chmod 700 $dir; $CHATTR $dir
+ chown $mail_owner $dir
+ }
+ done
+ test -d public || {
+ $WARN creating missing Postfix public directory
+ mkdir public || exit 1
+ chmod 755 public
+ chown $mail_owner public
+ }
+ test -d private || {
+ $WARN creating missing Postfix private directory
+ mkdir private || exit 1
+ chmod 700 private
+ chown $mail_owner private
+ }
+ find `ls -d $queue_directory/* | \
+ egrep '/(incoming|active|defer|deferred|bounce|saved|corrupt|public|private)$'` \
+ ! \( -type p -o -type s \) ! -user $mail_owner \
+ -exec $WARN not owned by $mail_owner: {} \;
+
+ find corrupt -type f -exec $WARN damaged message: {} \;
+
+ # XXX also: look for weird stuff, weird permissions, etc.
+ ;;
+
+*)
+
+ $FATAL "usage: postfix start (or stop, reload, abort, flush, or check)"
+ exit 1
+ ;;
+
+esac
diff --git a/postfix/conf/relocated b/postfix/conf/relocated
new file mode 100644
index 000000000..ed1a40c66
--- /dev/null
+++ b/postfix/conf/relocated
@@ -0,0 +1,78 @@
+#++
+# NAME
+# relocated 5
+# SUMMARY
+# format of Postfix relocated table
+# SYNOPSIS
+# \fBpostmap /etc/postfix/relocated\fR
+# DESCRIPTION
+# The optional \fBrelocated\fR file provides the information that is
+# used in "user has moved to \fInew_location\fR" bounce messages.
+#
+# The file 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. After an update
+# issue a \fBpostfix reload\fR command to make the change visible.
+#
+# Table lookups are case insensitive.
+#
+# The format of the table is as follows:
+# .IP \(bu
+# Blank lines are ignored, as are lines beginning with `#'.
+# .IP \(bu
+# An entry has one of the following form:
+# .ti +5
+# \fIkey new_location\fR
+# .br
+# Where \fInew_location\fR specifies contact information such as
+# an email address, or perhaps a street address or telephone number.
+# .PP
+# The \fIkey\fR field is one of the following:
+# .IP \fIuser\fR@\fIdomain\fR
+# Matches \fIuser\fR@\fIdomain\fR. This form has precedence over all
+# other forms.
+# .IP \fIuser\fR
+# Matches \fIuser\fR@\fIsite\fR when \fIsite\fR is $\fBmyorigin\fR,
+# when \fIsite\fR is listed in $\fBmydestination\fR, or when \fIsite\fR
+# is listed in $\fBinet_interfaces\fR.
+# .IP @\fIdomain\fR
+# Matches every address in \fIdomain\fR. This form has the lowest
+# precedence.
+# ADDRESS EXTENSION
+# .fi
+# .ad
+# When the search fails, and the address localpart contains the
+# optional recipient delimiter (e.g., \fIuser+foo\fR@\fIdomain\fR),
+# the search is repeated for the unextended address (e.g.
+# \fIuser\fR@\fIdomain\fR).
+# BUGS
+# The table format does not understand quoting conventions.
+# CONFIGURATION PARAMETERS
+# .ad
+# .fi
+# The following \fBmain.cf\fR parameters are especially relevant to
+# this topic. See the Postfix \fBmain.cf\fR file for syntax details
+# and for default values. Use the \fBpostfix reload\fR command after
+# a configuration change.
+# .IP \fBrelocated_maps\fR
+# List of lookup tables for relocated users or sites.
+# .PP
+# Other parameters of interest:
+# .IP \fBinet_interfaces\fR
+# The network interface addresses that this system receives mail on.
+# .IP \fBmydestination\fR
+# List of domains that this mail system considers local.
+# .IP \fBmyorigin\fR
+# The domain that is appended to locally-posted mail.
+# SEE ALSO
+# postmap(1) create lookup table
+# 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
+#--
diff --git a/postfix/conf/sample-aliases.cf b/postfix/conf/sample-aliases.cf
new file mode 100644
index 000000000..b75c94261
--- /dev/null
+++ b/postfix/conf/sample-aliases.cf
@@ -0,0 +1,32 @@
+# This file contains example settings of Postfix configuration
+# parameters that control alias database lookups.
+#
+# See the sample-local.cf file for examples of other parameters
+# that control local delivery.
+
+# The alias_database parameter specifies the alias database that is
+# built with "newaliases" or "sendmail -bi". This is a separate
+# configuration parameter, because the alias_maps parameter may
+# specify multiple tables, not necessarily all under control by
+# Postfix.
+#
+# alias_database = dbm:/etc/aliases
+# alias_database = dbm:/etc/mail/aliases
+alias_database = hash:/etc/aliases
+
+# The alias_maps parameter specifies the list of alias databases used
+# by the local delivery agent. The default list is system dependent.
+# On systems with NIS, the default is to search the local alias
+# database, then the NIS alias database. See aliases(5) for syntax
+# details.
+#
+# If you change the alias database, run "postalias /etc/aliases" (or
+# wherever your system stores the mail alias file), or simply run
+# "newaliases" to build the necessary DBM or DB file.
+#
+# It will take a minute or so before changes become visible. Use
+# "postfix reload" to eliminate the delay.
+#
+# alias_maps = dbm:/etc/aliases, nis:mail.aliases
+# alias_maps = hash:/etc/aliases
+alias_maps = hash:/etc/aliases
diff --git a/postfix/conf/sample-canonical.cf b/postfix/conf/sample-canonical.cf
new file mode 100644
index 000000000..65c8fdd84
--- /dev/null
+++ b/postfix/conf/sample-canonical.cf
@@ -0,0 +1,45 @@
+# This file contains example settings of Postfix configuration
+# parameters that control canonical address map lookups.
+
+# The canonical_maps parameter specifies optional address mapping
+# lookup tables. The mapping is applied to both sender and recipient
+# addresses, in both envelopes and in headers. This is typically used
+# to clean up dirty addresses from legacy mail systems, or to replace
+# login names by Firstname.Lastname. See canonical(5) for details.
+#
+# By default, no canonical address mapping is done.
+#
+# If you use this feature, run "postmap /etc/postfix/canonical" to
+# build the necessary DBM or DB file after every change. The changes
+# will become visible after a minute or so. Use "postfix reload"
+# to eliminate the delay.
+#
+# canonical_maps = dbm:/etc/postfix/canonical
+# canonical_maps = hash:/etc/postfix/canonical
+# canonical_maps = hash:/etc/postfix/canonical, nis:canonical
+# canonical_maps = hash:/etc/postfix/canonical, netinfo:/canonical
+canonical_maps =
+
+# The recipient_canonical_maps parameter specifies optional address
+# mapping lookup tables for envelope and header RECIPIENT addresses.
+#
+# By default, no recipient-only address mapping is done.
+#
+# $recipient_canonical_maps is used before $canonical_maps lookups.
+#
+# recipient_canonical_maps = hash:/etc/postfix/recipient_canonical
+recipient_canonical_maps =
+
+# The sender_canonical_maps parameter specifies optional address
+# mapping lookup tables for envelope and header SENDER addresses.
+#
+# For example, you want to rewrite the SENDER address user@ugly.domain
+# to user@pretty.domain, while still being able to send mail to the
+# RECIPIENT address user@ugly.domain.
+#
+# By default, no sender-only address mapping is done.
+#
+# $sender_canonical_maps is used before $canonical_maps lookups.
+#
+# sender_canonical_maps = hash:/etc/postfix/sender_canonical
+sender_canonical_maps =
diff --git a/postfix/conf/sample-debug.cf b/postfix/conf/sample-debug.cf
new file mode 100644
index 000000000..056e22fbf
--- /dev/null
+++ b/postfix/conf/sample-debug.cf
@@ -0,0 +1,29 @@
+# This file contains example settings of Postfix configuration
+# parameters that control debugging features.
+
+# The debug_peer_level parameter specifies the increment in verbose
+# logging level when an SMTP client or server host name or address
+# matches a pattern in the debug_peer_list parameter.
+#
+debug_peer_level = 2
+
+# The debug_peer_list parameter specifies an optional list of domain
+# or network patterns, /file/name patterns or type:name tables. When
+# an SMTP client or server host name or address matches a pattern,
+# increase the verbose logging level by the amount specified in the
+# debug_peer_level parameter.
+#
+# debug_peer_list = 127.0.0.1
+# debug_peer_list = some.domain
+debug_peer_list =
+
+# The debugger_command specifies the external command that is executed
+# when a Postfix daemon program is run with the -D option.
+#
+# Use "command .. & sleep 5" so that the debugger can attach before
+# the process marches on. If you use an X-based debugger, be sure to
+# set up your XAUTHORITY environment variable before starting Postfix.
+#
+debugger_command =
+ PATH=/usr/bin:/usr/X11R6/bin
+ xxgdb $program_directory/$process_name $process_id & sleep 5
diff --git a/postfix/conf/sample-ldap.cf b/postfix/conf/sample-ldap.cf
new file mode 100644
index 000000000..f68aee6a5
--- /dev/null
+++ b/postfix/conf/sample-ldap.cf
@@ -0,0 +1,16 @@
+# This file contains example settings of Postfix configuration
+# parameters that control LDAP lookups. Source code for LDAP
+# lookup is available separately from http://www.postfix.org/
+
+# The ldap_lookup_timeout parameter specifies the timeout for LDAP
+# database lookups.
+#
+ldap_lookup_timeout = 10
+
+# The ldap_search_base parameter specifies the LDAP database to search.
+#
+ldap_search_base =
+
+# The ldap_server_host parameter specifies the LDAP server hostname.
+#
+ldap_server_host =
diff --git a/postfix/conf/sample-local.cf b/postfix/conf/sample-local.cf
new file mode 100644
index 000000000..66f978029
--- /dev/null
+++ b/postfix/conf/sample-local.cf
@@ -0,0 +1,93 @@
+# This file contains example settings of Postfix configuration
+# parameters that control local delivery.
+#
+# See the sample-aliases.cf file for parameters that are specific to
+# alias database lookup.
+
+#
+# SECURITY CONTROLS
+#
+
+# The local_command_shell parameter controls what shell will be used
+# for delivery to external command. By default, external commands
+# are executed directly; commands are given to given to /bin/sh only
+# when they contain shell meta characters or shell built-in commands.
+#
+# Specify a different shell when you need more control over what
+# programs can be run from e.g. .forward files.
+#
+# "sendmail's restricted shell" (smrsh) is what most people will use
+# (smrsh is part of recent sendmail distributions)
+#
+# Note: when a shell is specified, it is invoked even when the
+# command contains no shell built-in commands or meta characters.
+#
+#local_command_shell = /some/where/smrsh -c
+
+# The allow_mail_to_commands parameter restricts mail delivery to
+# external commands. The default is to disallow delivery to "|command"
+# in :include: files.
+#
+# allow_mail_to_commands = alias,forward,include
+allow_mail_to_commands = alias,forward
+
+# The allow_mail_to_files parameter restricts mail delivery to external
+# file. The default is to disallow delivery to /file/name in :include:
+# files.
+#
+# allow_mail_to_files = alias,forward,include
+allow_mail_to_files = alias,forward
+
+# The default_privs parameter specifies the default rights used by
+# the local delivery agent for delivery to external file or command.
+# These rights are used in the absence of a recipient user context.
+# DO NOT SPECIFY A PRIVILEGED USER OR THE POSTFIX OWNER.
+#
+default_privs = nobody
+
+#
+# MAILBOX DELIVERY CONTROLS
+#
+
+# The home_mailbox parameter specifies the optional pathname of a
+# mailbox relative to a user's home directory. The default is to
+# deliver to the UNIX-style /var/spool/mail/user or /var/mail/user.
+# Specify "Maildir/" for qmail-style delivery (the / is required).
+#
+# home_mailbox = Mailbox
+# home_mailbox = Maildir/
+home_mailbox =
+
+# The mailbox_command specifies the optional external command to use
+# instead of mailbox delivery. The command is run with proper HOME,
+# SHELL and LOGNAME settings.
+#
+# Avoid shell meta characters because they will force Postfix to run
+# an expensive shell process. Procmail alone is expensive enough.
+#
+# mailbox_command = /some/where/procmail
+mailbox_command =
+
+#
+# RATE CONTROLS
+#
+
+# The local_destination_concurrency_limit parameter limits the number
+# of parallel deliveries to the same local recipient.
+#
+# The default limit is taken from the default_destination_concurrency_limit
+# parameter. I recommend a low limit of 2, just in case someone has
+# an expensive shell command in a .forward file or in an alias (e.g.,
+# a mailing list manager). You don't want to run lots of those.
+#
+local_destination_concurrency_limit = 2
+
+# The local_destination_recipient_limit parameter limits the number
+# of recipients per local message delivery. The default limit is
+# taken from the default_destination_recipient_limit parameter.
+#
+# However, the queue manager by design limits the number of recipients
+# per local delivery request to exactly 1, so this parameter has no
+# effect.
+#
+local_destination_recipient_limit = 1
diff --git a/postfix/conf/sample-misc.cf b/postfix/conf/sample-misc.cf
new file mode 100644
index 000000000..c211f0133
--- /dev/null
+++ b/postfix/conf/sample-misc.cf
@@ -0,0 +1,232 @@
+# This file contains example settings for miscellaneous Postfix
+# configuration parameters.
+
+# The default_database_type parameter specifies the default database
+# type to use in postalias(1) and postmap(1) commands. On many UNIX
+# systems the default type is either `dbm' or `hash'. The default is
+# determined when the Postfix system is built.
+#
+# default_database_type = hash
+# default_database_type = dbm
+
+# The default_transport parameter specifies the default message
+# delivery transport to use when no transport is explicitly given in
+# the optional transport(5) table.
+#
+# default_transport = uucp
+default_transport = smtp
+
+# The double_bounce_sender parameter specifies the sender address
+# for mail that must be discarded when it cannot be delivered. This
+# must be a unique name. All mail to this name is silently discarded,
+# in order to terminate mail bounce loops.
+#
+double_bounce_sender = double-bounce
+
+# The hash_queue_depth parameter specifies the number of subdirectory
+# levels below the queue directories listed in the hash_queue_names
+# parameter.
+#
+# Multiple subdirectory levels can speed up directory searches by
+# reducing the number of files per directory.
+#
+hash_queue_depth = 2
+
+# The hash_queue_names parameter specifies the names of queue
+# directories that are split across multiple subdirectory levels.
+# Currently, hashing cannot be used for the maildrop, incoming, active
+# or deferred directories. Hashing MUST be used for the defer logfile
+# directory, or mail system performance will suffer.
+#
+hash_queue_names = defer
+
+# The hopcount_limit parameter limits the number of Received: message
+# headers. A message that exceeds the limit is bounced.
+#
+hopcount_limit = 50
+
+# The inet_interfaces parameter specifies the network interface
+# addresses that this mail system receives mail on. By default,
+# the software claims all active interfaces on the machine. The
+# parameter also controls delivery of mail to user@[ip.address].
+#
+inet_interfaces = all
+
+# The ipc_idle parameter bounds the idle time in seconds after which
+# an internal IPC client disconnects. The purpose is to allow servers
+# to terminate voluntarily. Currently this is used by the address
+# resolving and rewriting clients.
+#
+ipc_idle = 100
+
+# The ipc_timeout parameter specifies a timeout in seconds for I/O
+# on internal communication channels. The purpose is to break out
+# of deadlock situations. If the timeout is exceeded the software
+# aborts with a fatal error.
+#
+ipc_timeout = 3600
+
+# The mail_name parameter specifies the mail system name that is used
+# in Received: headers, in the SMTP greeting banner, and in bounced
+# mail.
+#
+mail_name = Postfix
+
+# The mail_owner parameter specifies the owner of the Postfix queue
+# and of most Postfix daemon processes. Specify the name of a user
+# account THAT DOES NOT SHARE A GROUP WITH OTHER ACCOUNTS AND THAT
+# OWNS NO OTHER FILES OR PROCESSES ON THE SYSTEM. In particular,
+# don't specify nobody or daemon. PLEASE USE A DEDICATED USER.
+#
+mail_owner = postfix
+
+# The mail_version parameter specifies the official version of the
+# mail system. The version string can be used in, for example, the
+# SMTP greeting banner.
+#
+mail_version = 19981207
+
+# The max_idle parameter limits the time in seconds that a Postfix
+# daemon process waits for the next service request before exiting.
+# This parameter is ignored by the Postfix queue manager.
+#
+max_idle = 100
+
+# The max_use parameter limits the number of service requests handled
+# by a Postfix daemon process before exiting. This parameter is
+# ignored by the Postfix queue manager.
+#
+max_use = 100
+
+# The mydestination parameter specifies the list of domains that this
+# machine considers itself the final destination for.
+#
+# The default is $myhostname + localhost.$mydomain. On a mail domain
+# gateway, you should also include $mydomain. Do not specify the
+# names of domains that this machine is backup MX host for. Specify
+# those names via the relay_domains or permit_mx_backup settings for
+# the SMTP server (see sample-smtpd.cf.
+#
+# The local machine is always the final destination for mail addressed
+# to user@[the.net.work.address] of an interface that the mail system
+# receives mail on (see the inet_interfaces parameter).
+#
+# Specify a list of host or domain names, /file/name or type:table
+# patterns, separated by commas and/or whitespace. A /file/name
+# pattern is replaced by its contents; a type:table is matched when
+# a name matches a lookup key. Continue long lines by starting the
+# next line with whitespace.
+#
+# mydestination = $myhostname, localhost.$mydomain $mydomain
+# mydestination = $myhostname, localhost.$mydomain www.$mydomain, ftp.$mydomain
+mydestination = $myhostname, localhost.$mydomain
+
+# The mydomain parameter specifies the local internet domain name.
+# The default is to use $myhostname minus the first component.
+# $mydomain is used as a default value for many other configuration
+# parameters.
+#
+#mydomain = domain.name
+
+# The myhostname parameter specifies the internet hostname of this
+# mail system. The default is to use the fully-qualified domain name
+# from gethostname(). $myhostname is used as a default value for many
+# other configuration parameters.
+#
+#myhostname = host.domain.name
+
+# The myorigin parameter specifies the domain that locally-posted
+# mail appears to come from. The default is to append $myhostname,
+# which is fine for small sites. If you run a domain with multiple
+# machines, you should (1) change this to $mydomain and (2) set up
+# a domain-wide alias database that aliases each user to
+# user@that.users.mailhost.
+#
+# myorigin = $mydomain
+myorigin = $myhostname
+
+# The mynetworks parameter specifies the list of networks that are
+# local to this machine. The list is used by the anti-UCE software
+# to distinguish local clients from strangers. See permit_mynetworks
+# in the sample-smtpd.cf file.
+#
+# The default is all networks attached to the machine: a complete
+# class A network, a complete class B network, and so on. If you want
+# stricter control, specify a list of network/mask patterns, where
+# the mask specifies the number of bits in the network part of a host
+# address. You can also specify the absolute pathname of a pattern
+# file instead of listing the patterns here.
+#
+#mynetworks = 168.100.189.0/28, 127.0.0.0/8
+
+# The notify_classes parameter specifies the list of error classes
+# that are reported to the postmaster. The default is to report only
+# the most serious problems. The paranoid may wish to turn on the
+# policy (anti-UCE violations) and protocol error (broken mailers)
+# reports.
+#
+# notify_classes = bounce,policy,protocol,resource,software
+notify_classes = resource,software
+
+# The process_id_directory specifies a lock file directory relative
+# to the Postfix queue directory. This facility is used by the master
+# daemon to lock out other master daemon instances.
+#
+process_id_directory = pid
+
+# The program_directory parameter specifies the location of Postfix
+# support programs and daemons. This directory must be owned by root.
+#
+program_directory = /usr/libexec/postfix
+
+# The queue_directory specifies the location of the Postfix queue.
+# This is also the root directory of Postfix daemons that run chrooted.
+# The contributed source code from http://www.postfix.org/ has examples
+# for setting up Postfix chroot environments on different UNIX systems.
+#
+queue_directory = /var/spool/postfix
+
+# The recipient_delimiter parameter specifies the separator between
+# user names and address extensions (user+foo). See canonical(5),
+# local(8), relocated(5) and virtual(5) for the effects this has on
+# aliases, canonical, virtual, relocated and .forward file lookups.
+# Basically, the software tries user+foo and .forward+foo before
+# trying user and .forward.
+#
+# recipient_delimiter = +
+recipient_delimiter =
+
+# The relayhost parameter specifies the default host to send mail to
+# when no entry is matched in the optional transport(5) table. When
+# no relayhost is given, mail is routed directly to the destination.
+#
+# On an intranet, specify the organizational domain name. If your
+# internal DNS uses no MX records, specify the name of the intranet
+# gateway host instead.
+#
+# Specify a domain, host, host:port, [address] or [address:port].
+# Use the form [destination] to turn off MX lookups. See also the
+# default_transport parameter if you're connected via UUCP.
+#
+# relayhost = $mydomain
+# relayhost = gateway.my.domain
+# relayhost = uucphost
+relayhost =
+
+# The relocated_maps parameter specifies optional tables with contact
+# information for users, hosts or domains that no longer exist. See
+# relocated(5) for details.
+#
+# By default, this feature is disabled.
+#
+# Specify the types and names of databases to use. After change,
+# run "postmap /etc/postfix/relocated", then "postfix reload".
+#
+# relocated_maps = hash:/etc/postfix/relocated
+relocated_maps =
+
+# The trigger_timeout parameter limits the time to send a trigger to
+# a Postfix daemon. This prevents programs from getting stuck when the
+# mail system is under heavy load.
+#
+trigger_timeout = 10
diff --git a/postfix/conf/sample-rate.cf b/postfix/conf/sample-rate.cf
new file mode 100644
index 000000000..e95094dcd
--- /dev/null
+++ b/postfix/conf/sample-rate.cf
@@ -0,0 +1,56 @@
+# This file contains example settings of Postfix parameters that
+# control delivery rates.
+
+# The default_destination_concurrency_limit parameter specifies a
+# default limit on the number of parallel deliveries to the same
+# destination. This is the default limit for delivery via SMTP, via
+# the local delivery agent and via the pipe mailer.
+#
+default_destination_concurrency_limit = 10
+
+# The default_destination_recipient_limit parameter specifies a
+# default limit on the number of recipients per message delivery.
+# This is the default limit for delivery via SMTP, via the local
+# delivery agent and via the pipe mailer.
+#
+default_destination_recipient_limit = 50
+
+# The initial_destination_concurrency parameter specifies the initial
+# per-destination concurrency level for parallel delivery to the same
+# destination. This limit applies to delivery via SMTP, via the local
+# delivery agent and via the pipe mailer.
+#
+# With concurrency of 1, one bad message is enough to block all mail
+# to a site. A concurrency of 2 seems a reasonable choice.
+#
+initial_destination_concurrency = 2
+
+# The maximal_backoff_time parameter specifies the maximal time in
+# seconds between attempts to deliver a deferred message.
+#
+maximal_backoff_time = 4000
+
+# The maximal_queue_lifetime parameter specifies the maximal time in
+# days a message is queued before it is sent back as undeliverable.
+#
+maximal_queue_lifetime = 5
+
+# The minimal_backoff_time parameter specifies the minimal time in
+# seconds between attempts to deliver a deferred message. This
+# parameter also limits the time an unreachable destination is kept
+# in the short-term, in-memory destination status cache.
+#
+minimal_backoff_time = 1000
+
+# The queue_run_delay parameter specifies the time in seconds
+# between deferred queue scans by the queue manager.
+#
+queue_run_delay = 1000
+
+# The defer_transports parameter specifies the names of transports
+# that should not be delivered to unless someone issues "sendmail
+# -q" or equivalent. Specify zero or more names of mail delivery
+# transports names that appear in the first field of master.cf).
+#
+#defer_transports = smtp
+#defer_transports =
diff --git a/postfix/conf/sample-relocated.cf b/postfix/conf/sample-relocated.cf
new file mode 100644
index 000000000..aeea31ad0
--- /dev/null
+++ b/postfix/conf/sample-relocated.cf
@@ -0,0 +1,18 @@
+# This file contains example settings of Postfix configuration
+# parameters that control relocated database lookups.
+
+# The relocated_maps parameter specifies optional lookup tables with
+# new contact information for users or even domains that no longer
+# exist.
+#
+# By default, this feature is disabled.
+#
+# If you use this feature, run "postmap /etc/postfix/relocated" to
+# build the necessary DBM or DB file after change, then "postfix
+# reload" to make the changes visible.
+#
+# relocated_maps = dbm:/etc/postfix/relocated
+# relocated_maps = hash:/etc/postfix/relocated
+# relocated_maps = hash:/etc/postfix/relocated, nis:virtual
+# relocated_maps = hash:/etc/postfix/relocated, netinfo:/relocated
+relocated_maps =
diff --git a/postfix/conf/sample-resource.cf b/postfix/conf/sample-resource.cf
new file mode 100644
index 000000000..846355cdc
--- /dev/null
+++ b/postfix/conf/sample-resource.cf
@@ -0,0 +1,97 @@
+# This file contains example settings of general Postfix resource
+# control parameters.
+#
+# Controls that are specific to message delivery transports are
+# described in the respective sample-transportname.cf file.
+
+# The bounce_size_limit parameter limits the amount of original
+# message context in bytes that is sent in a non-delivery notification.
+#
+bounce_size_limit = 50000
+
+# The command_time_limit parameter limits the amount of time for
+# delivery to external commands. This limit is used by the local
+# delivery agent, and is the default time limit for delivery by the
+# pipe mailer.
+#
+# Note: if you set this time limit to a large value you must update the
+# global ipc_timeout parameter as well. See sample-misc.cf for details.
+#
+command_time_limit = 1000
+
+# The default_process_limit parameter specifies the default limit
+# on the number of Postfix child processes that provide a given
+# service.
+#
+default_process_limit = 50
+
+# The deliver_lock_attempts parameter limits the number of attempts
+# to acquire an exclusive lock on a mailbox or other file.
+#
+deliver_lock_attempts = 5
+
+# The deliver_lock_delay parameter limits the time in seconds between
+# attempts to acquire an exclusive lock.
+#
+deliver_lock_delay = 1
+
+# The duplicate_filter_limit parameter limits the number of addresses
+# remembered by the duplicate filter for alias, virtual, etc.
+# expansion.
+#
+duplicate_filter_limit = 1000
+
+# The fork_attempts parameter limits the number of attempts to
+# fork() a process.
+#
+fork_attempts = 5
+
+# The fork_delay parameter specifies the delay in seconds between
+# fork() attempts.
+#
+fork_delay = 1
+
+# The header_size_limit parameter limits the amount of memory in
+# bytes used for processing a message header. If a header is larger,
+# the remainder of the entire message is treated as message body.
+#
+header_size_limit = 102400
+
+# The line_length_limit parameter limits the amount of memory in
+# bytes used for handling input lines. Longer lines are chopped up
+# into pieces and reconstructed upon delivery.
+#
+line_length_limit = 2048
+
+# The message_size_limit parameter limits the total size in bytes of
+# a message, including envelope information.
+#
+message_size_limit = 10240000
+
+# The qmgr_message_active_limit parameter limits the number of
+# messages in the active queue.
+#
+qmgr_message_active_limit = 1000
+
+# The qmgr_message_recipient_limit parameter limits the number of
+# in-memory recipients. This parameter also limits the size of the
+# short-term, in-memory destination status cache.
+#
+qmgr_message_recipient_limit = 1000
+
+# The queue_minfree parameter specifies the minimal amount of free
+# space in bytes in the queue file system. This is currently used by
+# the SMTP server to decide if it will accept any mail at all.
+#
+queue_minfree = 0
+
+# The stale_lock_time parameter limits the time after which a stale
+# lock is removed. This is used for delivery to file or mailbox.
+#
+stale_lock_time = 500
+
+# The transport_retry_time parameter specifies the time in seconds
+# between attempts by the queue manager to contact a broken message
+# delivery transport.
+#
+transport_retry_time = 60
diff --git a/postfix/conf/sample-rewrite.cf b/postfix/conf/sample-rewrite.cf
new file mode 100644
index 000000000..16ab6da8e
--- /dev/null
+++ b/postfix/conf/sample-rewrite.cf
@@ -0,0 +1,48 @@
+# This file contains example settings of Postfix configuration
+# parameters that control address rewriting.
+
+# The allow_percent_hack parameter controls the rewriting of the form
+# "user%domain" to "user@domain". This is enabled by default.
+#
+# allow_percent_hack = no
+allow_percent_hack = yes
+
+# The append_at_myorigin controls the rewriting of the form "user" to
+# "user@$mydomain". This should not be turned off.
+#
+append_at_myorigin = yes
+
+# The append_dot_mydomain controls the rewriting of the form
+# "user@host" to "user@host.$mydomain". This is enabled by default.
+#
+# append_dot_mydomain = no
+append_dot_mydomain = yes
+
+# The empty_address_recipient specifies the destination for mail from
+# <> that is undeliverable (typically, bounce notifications and
+# other notifications). By default, such mail is sent to MAILER-DAEMON.
+#
+empty_address_recipient = MAILER-DAEMON
+
+# The masquerade_domains parameter gives an optional list of domains
+# that must have their subdomain structure stripped off.
+#
+# By default, address masquerading is disabled.
+#
+# masquerade_domains = $mydomain
+masquerade_domains =
+
+# The masquerade_exceptions parameter gives an optional list of user
+# names that are not subjected to address masquerading.
+#
+# By default, address masquerading makes no exceptions.
+#
+#masquerade_exceptions = root
+masquerade_exceptions =
+
+# The swap_bangpath parameter controls the rewriting of the form
+# "site!user" to "user@site". This is necessary if your machine is
+# connected to UUCP networks. It is enabled by default.
+#
+# swap_bangpath = no
+swap_bangpath = yes
diff --git a/postfix/conf/sample-smtp.cf b/postfix/conf/sample-smtp.cf
new file mode 100644
index 000000000..e1868b4b4
--- /dev/null
+++ b/postfix/conf/sample-smtp.cf
@@ -0,0 +1,104 @@
+# This file contains example settings of Postfix configuration
+# parameters that control the SMTP client program.
+
+#
+# RATE CONTROLS
+#
+
+# The smtp_destination_concurrency_limit parameter limits the number
+# of parallel deliveries to the same destination via the smtp delivery
+# agent.
+#
+# The default limit is the default_destination_concurrency_limit
+# parameter. It is probably safer to limit the concurrency to 10.
+#
+smtp_destination_concurrency_limit = 10
+
+# The smtp_destination_recipient_limit parameter limits the number
+# of recipients per delivery via the smtp delivery agent.
+#
+# The default is taken from the default_destination_recipient_limit
+# parameter.
+#
+smtp_destination_recipient_limit = $default_destination_recipient_limit
+
+#
+# TIMEOUT CONTROLS
+#
+# Note: if you set SMTP timeouts to large values you must update the
+# global ipc_timeout parameter as well. See sample-misc.cf for details.
+#
+
+# The smtp_connect_timeout parameter specifies the SMTP client
+# timeout in seconds for completing a TCP connection.
+#
+# When no connection can be made within the deadline, the SMTP client
+# tries the next address on the mail exchanger list. Specify 0 to
+# disable the timeout.
+#
+# smtp_connect_timeout = 30
+smtp_connect_timeout = 0
+
+# The smtp_helo_timeout parameter specifies the SMTP client timeout
+# in seconds for receiving the SMTP greeting banner.
+#
+# When the server drops the connection without sending a greeting
+# banner, or when it sends no greeting banner within the deadline,
+# the SMTP client tries the next address on the mail exchanger list.
+#
+smtp_helo_timeout = 300
+
+# The smtp_mail_timeout parameter specifies the SMTP client timeout
+# in seconds for sending the SMTP MAIL FROM command, and for receiving
+# the server response.
+#
+# In case of problems the client does NOT try the next address on
+# the mail exchanger list.
+#
+smtp_mail_timeout = 300
+
+# The smtp_rcpt_timeout parameter specifies the SMTP client timeout
+# in seconds for sending the SMTP RCPT TO command, and for receiving
+# the server response.
+#
+# In case of problems the client does NOT try the next address on
+# the mail exchanger list.
+#
+smtp_rcpt_timeout = 300
+
+# The smtp_data_init_timeout parameter specifies the SMTP client
+# timeout in seconds for sending the SMTP DATA command, and for
+# receiving the server response.
+#
+# In case of problems the client does NOT try the next address on
+# the mail exchanger list.
+#
+smtp_data_init_timeout = 120
+
+# The smtp_data_xfer_timeout parameter specifies the SMTP client
+# timeout in seconds for sending the SMTP message content. When
+# the connection stalls for more than $smtp_data_xfer_timeout the
+# SMTP client terminates the transfer.
+#
+# In case of problems the client does NOT try the next address on
+# the mail exchanger list.
+#
+smtp_data_xfer_timeout = 180
+
+# The smtp_data_done_timeout parameter specifies the SMTP client
+# timeout in seconds for sending the SMTP ".", and for receiving
+# the server response.
+#
+# When no response is received within the deadline, a warning is
+# logged that the mail may be delivered multiple times.
+#
+# In case of problems the client does NOT try the next address on
+# the mail exchanger list.
+#
+smtp_data_done_timeout = 600
+
+# The smtp_quit_timeout parameter specifies the SMTP client timeout
+# in seconds for sending the SMTP QUIT command, and for receiving
+# the server response.
+#
+smtp_quit_timeout = 300
diff --git a/postfix/conf/sample-smtpd.cf b/postfix/conf/sample-smtpd.cf
new file mode 100644
index 000000000..51c4e87f3
--- /dev/null
+++ b/postfix/conf/sample-smtpd.cf
@@ -0,0 +1,272 @@
+# This file contains example settings of Postfix configuration parameters
+# that control the SMTP server program.
+
+#
+# MISCELLANEOUS
+#
+
+# The smtpd_banner parameter specifies the text that follows the 220
+# status code in the SMTP greeting banner. Some people like to see
+# the mail version advertised. By default, Postfix shows no version.
+#
+# You MUST specify the $myhostname at the start of the text. When
+# the SMTP client sees its own hostname at the start of an SMTP
+# greeting banner it will report a mailer loop. That's better than
+# having a machine meltdown.
+#
+# smtpd_banner = $myhostname ESMTP $mail_name ($mail_version)
+smtpd_banner = $myhostname ESMTP $mail_name
+
+# The smtpd_recipient_limit parameter restricts the number of recipients
+# that the SMTP server accepts per message delivery.
+#
+smtpd_recipient_limit = 1000
+
+# The smtpd_timeout parameter limits the time in seconds to send an
+# SMTP server response and to receive an SMTP client request.
+#
+# Note: if you set SMTP timeouts to large values you must update the
+# global ipc_timeout parameter as well. See sample-misc.cf for details.
+#
+smtpd_timeout = 300
+
+#
+# TARPIT CONTROLS
+#
+
+# The smtpd_error_sleep_time parameter specifies the time in seconds
+# the SMTP server waits before sending a 4xx or 5xx SMTP server error
+# response. This prevents naive clients from going into an error -
+# disconnect - connect - error loop.
+#
+smtpd_error_sleep_time = 5
+
+# The smtpd_soft_error_limit parameter specifies an error count lower
+# limit. When an SMTP client has made this number of errors within
+# a session, the server waits error_count seconds before responding
+# to any client request.
+#
+smtpd_soft_error_limit = 10
+
+# The smtpd_hard_error_limit parameter specifies an error count upper
+# limit. The SMTP server disconnects after an SMTP client makes this
+# number of errors within a session.
+#
+smtpd_hard_error_limit = 100
+
+#
+# UCE RESTRICTIONS
+#
+
+# The smtpd_client_restrictions parameter specifies optional restrictions
+# on SMTP client host names and addresses.
+#
+# The default is to allow connections from any host. The following
+# restrictions are available:
+#
+# reject_unknown_client:reject the request if the client hostname is unknown.
+# permit_mynetworks: permit if the client address matches $mynetworks.
+# maptype:mapname: look up client name, parent domains, client address,
+# or networks obtained by stripping octets.
+# Reject if result is REJECT or "[45]xx text"
+# Permit otherwise.
+# reject_maps_rbl:reject if the client is listed under $maps_rbl_domains.
+# reject: reject the request. Place this at the end of a restriction.
+# permit: permit the request. Place this at the end of a restriction.
+#
+# Restrictions are applied in the order as specified; the first
+# restriction that matches wins.
+#
+# Specify a list of restrictions, separated by commas and/or whitespace.
+# Continue long lines by starting the next line with whitespace.
+#
+smtpd_client_restrictions =
+
+# The smtpd_helo_required parameter optionally turns on the requirement
+# that SMTP clients must introduce themselves at the beginning of an
+# SMTP session.
+#
+# smtpd_helo_required = yes
+smtpd_helo_required = no
+
+# The smtpd_helo_restrictions parameter specifies optional restrictions
+# on what SMTP clients can send in SMTP HELO and EHLO commands.
+#
+# The default is to permit everything. The following restrictions
+# are available:
+#
+# reject_unknown_client:reject the request if the client hostname is unknown.
+# permit_mynetworks: permit if the client address matches $mynetworks.
+# reject_invalid_hostname: reject HELO hostname with bad syntax.
+# reject_unknown_hostname: reject HELO hostname without DNS A record.
+# maptype:mapname: look up HELO hostname or parent domains.
+# Reject if result is REJECT or "[45]xx text"
+# Permit otherwise.
+# check_client_access maptype:mapname: see smtpd_client_restrictions.
+# reject: reject the request. Place this at the end of a restriction.
+# permit: permit the request. Place this at the end of a restriction.
+#
+# Restrictions are applied in the order as specified; the first
+# restriction that matches wins.
+#
+# Specify a list of restrictions, separated by commas and/or whitespace.
+# Continue long lines by starting the next line with whitespace.
+#
+# smtpd_helo_restrictions = reject_invalid_hostname
+# smtpd_helo_restrictions = permit_mynetworks, reject_unknown_hostname
+smtpd_helo_restrictions =
+
+# The smtpd_sender_restrictions parameter specifies optional restrictions
+# on sender addresses that SMTP clients can send in MAIL FROM commands.
+#
+# The default is to permit any sender address. The following
+# restrictions are available:
+#
+# reject_unknown_client:reject the request if the client hostname is unknown.
+# permit_mynetworks: permit if the client address matches $mynetworks.
+# reject_unknown_address:reject if the sender domain has no A or MX record.
+# maptype:mapname: look up sender address, parent domain, or localpart@.
+# Reject if result is REJECT or "[45]xx text"
+# Permit otherwise.
+# check_client_access maptype:mapname: see smtpd_client_restrictions.
+# check_helo_access maptype:mapname: see smtpd_helo_restrictions.
+# reject: reject the request. Place this at the end of a restriction.
+# permit: permit the request. Place this at the end of a restriction.
+#
+# Restrictions are applied in the order as specified; the first
+# restriction that matches wins.
+#
+# Specify a list of restrictions, separated by commas and/or whitespace.
+# Continue long lines by starting the next line with whitespace.
+#
+# smtpd_sender_restrictions = reject_unknown_address
+# smtpd_sender_restrictions = reject_unknown_address, hash:/etc/postfix/access
+smtpd_sender_restrictions =
+
+# The smtpd_recipient_restrictions parameter specifies restrictions on
+# recipient addresses that SMTP clients can send in RCPT TO commands.
+#
+# The default is to permit any destination from clients that match
+# $mynetworks, and to otherwise permit only mail from or to domains
+# listed in $relay_domains.
+#
+# The following restrictions are available:
+#
+# reject_unknown_client:reject the request if the client hostname is unknown.
+# permit_mynetworks: permit if the client address matches $mynetworks.
+# check_relay_domains: permit only mail from/to domains in $relay_domains.
+# permit_mx_backup: accept mail for sites that list me as MX host.
+# maptype:mapname: look up recipient address, parent domain, or localpart@.
+# Reject if result is REJECT or "[45]xx text"
+# Permit otherwise.
+# check_client_access maptype:mapname: see smtpd_client_restrictions.
+# check_helo_access maptype:mapname: see smtpd_helo_restrictions.
+# check_sender_access maptype:mapname: see smtpd_sender_restrictions.
+# reject: reject the request. Place this at the end of a restriction.
+# permit: permit the request. Place this at the end of a restriction.
+#
+# Restrictions are applied in the order as specified; the first
+# restriction that matches wins.
+#
+# Specify a list of restrictions, separated by commas and/or whitespace.
+# Continue long lines by starting the next line with whitespace.
+#
+smtpd_recipient_restrictions = permit_mynetworks,check_relay_domains
+
+#
+# ADDITIONAL UCE CONTROLS
+#
+
+# The maps_rbl_domains parameter specifies an optional list of DNS
+# domains that publish the network addresses of blacklisted hosts.
+#
+# By default, RBL blacklist lookups are disabled. See the
+# smtpd_client_restrictions parameter.
+#
+# The real-time blackhole list works as follows: reverse the client
+# network address, and reject service if it is listed below any of
+# the following domains.
+#
+maps_rbl_domains = rbl.maps.vix.com
+
+# The relay_domains parameter restricts what domains (and subdomains
+# thereof) this mail system will relay mail from or to.
+#
+# By default, Postfix relays mail only from or to sites in or below
+# $mydestination, or in the optional virtual domain list.
+#
+# Specify a list of hosts or domains, /file/name patterns or type:name
+# lookup tables, separated by commas and/or whitespace. Continue
+# long lines by starting the next line with whitespace. A file name
+# is replaced by its contents; a type:name table is matched when a
+# (parent) domain appears as lookup key.
+#
+# NOTE: Postfix will not automatically forward mail for domains that
+# list this system as their primary or backup MX host. See the
+# permit_mx_backup restriction, in the description of the
+# smtpd_recipient_restrictions parameter.
+#
+relay_domains = $mydestination, $virtual_domains
+
+#
+# RESPONSE CODES
+#
+
+# The access_map_reject_code parameter specifies the SMTP server
+# response code when a client violates an access map restriction.
+#
+# Do not change this unless you have a complete understanding of RFC 822.
+#
+access_map_reject_code = 550
+
+# The invalid_hostname_reject_code parameter specifies the SMTP server
+# response when a client violates the reject_invalid_hostname anti-UCE
+# restriction.
+#
+# Do not change this unless you have a complete understanding of RFC 822.
+#
+invalid_hostname_reject_code = 501
+
+# The maps_rbl_reject_code parameter specifies the SMTP server response
+# when a client violates the maps_rbl_domains restriction.
+#
+# Do not change this unless you have a complete understanding of RFC 822.
+#
+maps_rbl_reject_code = 550
+
+# The reject_code parameter specifies the SMTP server response code
+# when an SMTP client matches a reject restriction.
+#
+# Do not change this unless you have a complete understanding of RFC 822.
+#
+reject_code = 550
+
+# The relay_domains_reject_code parameter specifies the SMTP server
+# response when a client attempts to violate the mail relay policy.
+#
+# Do not change this unless you have a complete understanding of RFC 822.
+#
+relay_domains_reject_code = 550
+
+# The unknown_address_reject_code parameter specifies the SMTP server
+# response when a client violates the reject_unknown_address restriction.
+#
+# Do not change this unless you have a complete understanding of RFC 822.
+#
+unknown_address_reject_code = 450
+
+# The unknown_client_reject_code parameter specifies the SMTP server
+# response when a client without address to name mapping violates
+# the reject_unknown_clients restriction.
+#
+# Do not change this unless you have a complete understanding of RFC 822.
+#
+unknown_client_reject_code = 450
+
+# The unknown_hostname_reject_code parameter specifies the SMTP server
+# response when a client violates the reject_unknown_hostname
+# restriction.
+#
+# Do not change this unless you have a complete understanding of RFC 822.
+#
+unknown_hostname_reject_code = 450
diff --git a/postfix/conf/sample-transport.cf b/postfix/conf/sample-transport.cf
new file mode 100644
index 000000000..0600dc30c
--- /dev/null
+++ b/postfix/conf/sample-transport.cf
@@ -0,0 +1,15 @@
+# This file contains example settings of Postfix configuration
+# parameters that control the optional transport table lookups.
+
+# The transport_maps parameter specifies optional tables with domain
+# to (transport, nexthop) mappings. See transport(5) for syntax details.
+#
+# By default, this feature is disabled. Specify the types of databases
+# to use. If you use this feature, run "postmap /etc/postfix/transport"
+# after change, then "postfix reload".
+#
+# transport_maps = dbm:/etc/postfix/transport
+# transport_maps = hash:/etc/postfix/transport
+# transport_maps = hash:/etc/postfix/transport, nis:transport
+# transport_maps = hash:/etc/postfix/transport, netinfo:/transport
+transport_maps =
diff --git a/postfix/conf/sample-virtual.cf b/postfix/conf/sample-virtual.cf
new file mode 100644
index 000000000..bfea4df49
--- /dev/null
+++ b/postfix/conf/sample-virtual.cf
@@ -0,0 +1,20 @@
+# This file contains example settings of Postfix configuration
+# parameters that control virtual database lookups.
+
+# The virtual_maps parameter specifies optional lookup tables to
+# redirect specific addresses or even complete domains to another
+# address. This is typically used to implement virtual domain support.
+#
+# By default, no address redirection is done.
+#
+# If you use this feature, run "postmap /etc/postfix/virtual" to
+# build the necessary DBM or DB file after change.
+#
+# It will take a minute or so before the change becomes visible.
+# Use "postfix reload" to eliminate the delay.
+#
+# virtual_maps = dbm:/etc/postfix/virtual
+# virtual_maps = hash:/etc/postfix/virtual
+# virtual_maps = hash:/etc/postfix/virtual, nis:virtual
+# virtual_maps = hash:/etc/postfix/virtual, netinfo:/virtual
+virtual_maps =
diff --git a/postfix/conf/transport b/postfix/conf/transport
new file mode 100644
index 000000000..524c84d00
--- /dev/null
+++ b/postfix/conf/transport
@@ -0,0 +1,101 @@
+#++
+# NAME
+# transport 5
+# SUMMARY
+# format of Postfix transport table
+# SYNOPSIS
+# \fBpostmap /etc/postfix/transport\fR
+# DESCRIPTION
+# The optional \fBtransport\fR file specifies a mapping from domain
+# hierarchies to message delivery transports and/or relay hosts. The
+# mapping is used by the \fBtrivial-rewrite\fR(8) daemon.
+#
+# The file 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. After updating this table,
+# issue the \fBpostfix reload\fR command to make the change visible.
+#
+# The format of the transport table is as follows:
+# .IP "blanks and comments"
+# Blank lines are ignored, as are lines beginning with `#'.
+# .IP "\fIdomain transport\fR:\fInexthop\fR"
+# Mail for \fIdomain\fR is delivered through \fItransport\fR to
+# \fInexthop\fR.
+# .IP "\fI.domain transport\fR:\fInexthop\fR"
+# Mail for any subdomain of \fIdomain\fR is delivered through
+# \fItransport\fR to \fInexthop\fR.
+#
+# The interpretation of the \fInexthop\fR field is transport
+# dependent. In the case of SMTP, specify \fIhost\fR:\fIservice\fR for a
+# non-default server port, and use [\fIhost\fR] or [\fIhost\fR:\fIport\fR]
+# in order to disable MX (mail exchanger) DNS lookups. The [] form
+# can also be used with IP addresses instead of hostnames.
+# EXAMPLES
+# .ad
+# In order to send mail for \fBfoo.org\fR and its subdomains
+# via the \fBuucp\fR transport to the UUCP host named \fBfoo\fR:
+#
+# .ti +5
+# \fBfoo.org uucp:foo\fR
+# .ti +5
+# \fB\&.foo.org uucp:foo\fR
+#
+# When no \fInexthop\fR host name is specified, the destination domain
+# name is used instead. For example, the following directs mail for
+# \fIuser\fR@\fBfoo.org\fR via the \fBslow\fR transport to a mail
+# exchanger for \fBfoo.org\fR. The \fBslow\fR transport could be
+# something that runs at most one delivery process at a time:
+#
+# .ti +5
+# \fBfoo.org slow:\fR
+#
+# When no \fItransport\fR is specified, the default transport is
+# used, as specified via the \fBdefault_transport\fR configuration
+# parameter. The following sends all mail for \fBfoo.org\fR and its
+# subdomains to host \fBgateway.foo.org\fR:
+#
+# .ti +5
+# \fBfoo.org :[gateway.foo.org]\fR
+# .ti +5
+# \fB\&.foo.org :[gateway.foo.org]\fR
+#
+# In the above example, the [] are used to suppress MX lookups.
+# The result would likely point to your local machine.
+#
+# In the case of delivery via SMTP, one may specify
+# \fIhostname\fR:\fIservice\fR instead of just a host:
+#
+# .ti +5
+# \fBfoo.org smtp:bar.org:2025\fR
+#
+# This directs mail for \fIuser\fR@\fBfoo.org\fR to host \fBbar.org\fR
+# port \fB2025\fR. Instead of a numerical port a symbolic name may be
+# used. Specify [] around the destination in order to disable MX lookups.
+# CONFIGURATION PARAMETERS
+# .ad
+# .fi
+# The following \fBmain.cf\fR parameters are especially relevant to
+# this topic. See the Postfix \fBmain.cf\fR file for syntax details
+# and for default values. Use the \fBpostfix reload\fR command after
+# a configuration change.
+# .IP \fBtransport_maps\fR
+# List of transport lookup tables.
+# .PP
+# Other parameters of interest:
+# .IP \fBdefault_transport\fR
+# The transport to use when no transport is explicitly specified.
+# .IP \fBrelayhost\fR
+# The default host to send to when no transport table entry matches.
+# SEE ALSO
+# postmap(1) create mapping table
+# trivial-rewrite(8) rewrite and resolve addresses
+# 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
+#--
diff --git a/postfix/conf/virtual b/postfix/conf/virtual
new file mode 100644
index 000000000..a0e6dda49
--- /dev/null
+++ b/postfix/conf/virtual
@@ -0,0 +1,102 @@
+#++
+# NAME
+# virtual 5
+# SUMMARY
+# format of Postfix virtual table
+# SYNOPSIS
+# \fBpostmap /etc/postfix/virtual\fR
+# DESCRIPTION
+# The optional \fBvirtual\fR table specifies redirections for local
+# and non-local recipients or domains. The redirections are used by
+# the \fBcleanup\fR(8) daemon. The redirections are recursive.
+#
+# The \fBvirtual\fR redirection is applied only to the recipient
+# envelope address, and does not affect message headers.
+# Think Sendmail rule set \fBS0\fR, if you like. Use \fBcanonical\fR(5)
+# mapping to rewrite header and envelope addresses in general.
+#
+# The file 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. After an update
+# it may take a minute or so before the change becomes visible.
+# Issue a \fBpostfix reload\fR command to eliminate the delay.
+#
+# Typical support for a virtual domain looks like the following:
+#
+# .in +4
+# .nf
+# \fIvirtual.domain anything\fR (right-hand content does not matter)
+# \fIuser1@virtual.domain address1\fR
+# \fIuser2@virtual.domain address2, address3\fR
+# .fi
+# .in -4
+#
+# With this, the SMTP server accepts mail for \fIvirtual.domain\fR
+# (provided that the \fBrelay_domains\fR parameter includes
+# $\fBvirtual_maps\fR), and mail for \fIunknown\fR@\fIvirtual.domain\fR
+# is bounced as undeliverable.
+#
+# The format of the virtual table is as follows, mappings being
+# tried in the order as listed in this manual page:
+# .IP "blanks and comments"
+# Blank lines are ignored, as are lines beginning with `#'.
+# .IP "\fIuser\fR@\fIdomain address, address, ...\fR"
+# Mail for \fIuser\fR@\fIdomain\fR is redirected to \fIaddress\fR.
+# This form has the highest precedence.
+# .IP "\fIuser address, address, ...\fR"
+# Mail for \fIuser\fR@\fIsite\fR is redirected to \fIaddress\fR when
+# \fIsite\fR is equal to $\fBmyorigin\fR, when \fIsite\fR is listed in
+# $\fRmydestination\fR, or when it is listed in $\fIinet_interfaces\fR.
+# .sp
+# This functionality overlaps with functionality of the local
+# \fIalias\fR(5) database. The difference is that \fBvirtual\fR
+# mapping can be applied to non-local addresses.
+# .IP "@\fIdomain address, address, ...\fR"
+# Mail for any user in \fIdomain\fR is redirected to \fIaddress\fR.
+# This form has the lowest precedence.
+# .PP
+# In all the above forms, when \fIaddress\fR has the form
+# @\fIotherdomain\fR, the result is the same user in \fIotherdomain\fR.
+# This works for the first address in the expansion only.
+# ADDRESS EXTENSION
+# .fi
+# .ad
+# When the search fails, and the address localpart contains the
+# optional recipient delimiter (e.g., \fIuser+foo\fR@\fIdomain\fR),
+# the search is repeated for the unextended address (e.g.
+# \fIuser\fR@\fIdomain\fR), and the unmatched address extension is
+# propagated to the result of expansion. The matching order is:
+# \fIuser+foo\fR@\fIdomain\fR, \fIuser\fR@\fIdomain\fR,
+# \fIuser+foo\fR, \fIuser\fR, and @\fIdomain\fR.
+# BUGS
+# The table format does not understand quoting conventions.
+# CONFIGURATION PARAMETERS
+# .ad
+# .fi
+# The following \fBmain.cf\fR parameters are especially relevant to
+# this topic. See the Postfix \fBmain.cf\fR file for syntax details
+# and for default values. Use the \fBpostfix reload\fR command after
+# a configuration change.
+# .IP \fBvirtual_maps\fR
+# List of virtual mapping tables.
+# .PP
+# Other parameters of interest:
+# .IP \fBinet_interfaces\fR
+# The network interface addresses that this system receives mail on.
+# .IP \fBmydestination\fR
+# List of domains that this mail system considers local.
+# .IP \fBmyorigin\fR
+# The domain that is appended to locally-posted mail.
+# SEE ALSO
+# cleanup(8) canonicalize and enqueue mail
+# postmap(1) create mapping table
+# 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
+#--
diff --git a/postfix/dns/.indent.pro b/postfix/dns/.indent.pro
new file mode 100644
index 000000000..e59d396ad
--- /dev/null
+++ b/postfix/dns/.indent.pro
@@ -0,0 +1,89 @@
+-TALIAS_TOKEN
+-TARGV
+-TBH_TABLE
+-TBINHASH
+-TBINHASH_INFO
+-TBOUNCE_STAT
+-TCLEANUP_STATE
+-TCLIENT_LIST
+-TCONFIG_BOOL_FN_TABLE
+-TCONFIG_BOOL_TABLE
+-TCONFIG_INT_FN_TABLE
+-TCONFIG_INT_TABLE
+-TCONFIG_STR_FN_TABLE
+-TCONFIG_STR_TABLE
+-TDELIVER_ATTR
+-TDELIVER_REQUEST
+-TDICT
+-TDICT_DB
+-TDICT_DBM
+-TDICT_ENV
+-TDICT_HT
+-TDICT_LDAP
+-TDICT_NI
+-TDICT_NIS
+-TDICT_NISPLUS
+-TDICT_NODE
+-TDICT_OPEN_INFO
+-TDNS_FIXED
+-TDNS_REPLY
+-TDNS_RR
+-TDOMAIN_LIST
+-TEXPAND_ATTR
+-TFILE
+-TFORWARD_INFO
+-THEADER_OPTS
+-THTABLE
+-THTABLE_INFO
+-TINET_ADDR_LIST
+-TINT_TABLE
+-TLOCAL_STATE
+-TMAC_HEAD
+-TMAC_PARSE
+-TMAIL_PRINT
+-TMAIL_SCAN
+-TMAPS
+-TMASTER_PROC
+-TMASTER_SERV
+-TMASTER_STATUS
+-TMBLOCK
+-TMKMAP
+-TMKMAP_OPEN_INFO
+-TMULTI_SERVER
+-TMVECT
+-TNAMADR_LIST
+-TNAME_MASK
+-TPEER_NAME
+-TPICKUP_INFO
+-TPIPE_ATTR
+-TPIPE_PARAMS
+-TQMGR_ENTRY
+-TQMGR_MESSAGE
+-TQMGR_QUEUE
+-TQMGR_RCPT_LIST
+-TQMGR_RECIPIENT
+-TQMGR_SCAN
+-TQMGR_TRANSPORT
+-TRECIPIENT
+-TRECIPIENT_LIST
+-TREC_TYPE_NAME
+-TRESOLVE_REPLY
+-TSCAN_DIR
+-TSINGLE_SERVER
+-TSMTPD_STATE
+-TSMTPD_TOKEN
+-TSMTP_ADDR
+-TSMTP_CMD
+-TSMTP_RESP
+-TSMTP_SESSION
+-TSMTP_STATE
+-TSOCKADDR_SIZE
+-TSTRING_TABLE
+-TSYS_EXITS_TABLE
+-TTOK822
+-TTRIGGER_SERVER
+-TUSER_ATTR
+-TVBUF
+-TVSTREAM
+-TVSTRING
+-TWAIT_STATUS_T
diff --git a/postfix/dns/.printfck b/postfix/dns/.printfck
new file mode 100644
index 000000000..9ed900cb0
--- /dev/null
+++ b/postfix/dns/.printfck
@@ -0,0 +1,24 @@
+been_here_xt 2 0
+bounce_append 5 0
+cleanup_out_format 1 0
+defer_append 5 0
+mail_command 1 0
+mail_print 1 0
+msg_error 0 0
+msg_fatal 0 0
+msg_info 0 0
+msg_panic 0 0
+msg_warn 0 0
+opened 3 0
+qmgr_message_bounce 2 0
+rec_fprintf 2 0
+sent 4 0
+smtp_cmd 1 0
+smtp_mesg_fail 2 0
+smtp_printf 1 0
+smtp_rcpt_fail 3 0
+smtp_site_fail 2 0
+udp_syslog 1 0
+vstream_fprintf 1 0
+vstream_printf 0 0
+vstring_sprintf 1 0
diff --git a/postfix/dns/Makefile.in b/postfix/dns/Makefile.in
new file mode 100644
index 000000000..f44595382
--- /dev/null
+++ b/postfix/dns/Makefile.in
@@ -0,0 +1,103 @@
+SHELL = /bin/sh
+SRCS = dns_lookup.c dns_rr.c dns_strerror.c dns_strtype.c
+OBJS = dns_lookup.o dns_rr.o dns_strerror.o dns_strtype.o
+HDRS = dns.h
+TESTSRC = test_dns_lookup.c test_alias_token.c
+WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
+ -Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
+ -Wunused
+DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
+CFLAGS = $(DEBUG) $(OPT) $(DEFS)
+INCL =
+LIB = libdns.a
+TESTPROG= test_dns_lookup
+LIBS = ../lib/libutil.a
+LIB_DIR = ../lib
+INC_DIR = ../include
+
+.c.o:; $(CC) $(CFLAGS) -c $*.c
+
+all: $(LIB)
+
+Makefile: Makefile.in
+ (set -e; echo "# DO NOT EDIT"; $(OPTS) sh ../makedefs; cat $?) >$@
+
+test: $(TESTPROG)
+
+$(LIB): $(OBJS)
+ $(AR) $(ARFL) $(LIB) $?
+ $(RANLIB) $(LIB)
+
+$(LIB_DIR)/$(LIB): $(LIB)
+ cp $(LIB) $(LIB_DIR)
+ $(RANLIB) $(LIB_DIR)/$(LIB)
+
+update: $(LIB_DIR)/$(LIB) $(HDRS)
+ -for i in $(HDRS); \
+ do \
+ cmp -s $$i $(INC_DIR)/$$i 2>/dev/null || cp $$i $(INC_DIR); \
+ done
+ cd $(INC_DIR); chmod 644 $(HDRS)
+
+test_dns_lookup: test_dns_lookup.c $(LIB) $(LIBS)
+ $(CC) $(CFLAGS) -o $@ $@.c $(LIB) $(LIBS) $(SYSLIBS)
+
+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 $(LIB) *core $(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
+
+# do not edit below this line - it is generated by 'make depend'
+dns_lookup.o: dns_lookup.c
+dns_lookup.o: ../include/sys_defs.h
+dns_lookup.o: ../include/mymalloc.h
+dns_lookup.o: ../include/vstring.h
+dns_lookup.o: ../include/vbuf.h
+dns_lookup.o: ../include/msg.h
+dns_lookup.o: ../include/valid_hostname.h
+dns_lookup.o: dns.h
+dns_rr.o: dns_rr.c
+dns_rr.o: ../include/sys_defs.h
+dns_rr.o: ../include/msg.h
+dns_rr.o: ../include/mymalloc.h
+dns_rr.o: dns.h
+dns_rr.o: ../include/vstring.h
+dns_rr.o: ../include/vbuf.h
+dns_strerror.o: dns_strerror.c
+dns_strerror.o: ../include/sys_defs.h
+dns_strerror.o: ../include/vstring.h
+dns_strerror.o: ../include/vbuf.h
+dns_strerror.o: dns.h
+dns_strtype.o: dns_strtype.c
+dns_strtype.o: ../include/sys_defs.h
+dns_strtype.o: ../include/vstring.h
+dns_strtype.o: ../include/vbuf.h
+dns_strtype.o: dns.h
+test_dns_lookup.o: test_dns_lookup.c
+test_dns_lookup.o: ../include/sys_defs.h
+test_dns_lookup.o: ../include/vstring.h
+test_dns_lookup.o: ../include/vbuf.h
+test_dns_lookup.o: ../include/msg.h
+test_dns_lookup.o: ../include/msg_vstream.h
+test_dns_lookup.o: ../include/vstream.h
+test_dns_lookup.o: dns.h
diff --git a/postfix/dns/dns.h b/postfix/dns/dns.h
new file mode 100644
index 000000000..f2cf03366
--- /dev/null
+++ b/postfix/dns/dns.h
@@ -0,0 +1,135 @@
+#ifndef _DNS_H_INCLUDED_
+#define _DNS_H_INCLUDED_
+
+/*++
+/* NAME
+/* dns 3h
+/* SUMMARY
+/* domain name service lookup
+/* SYNOPSIS
+/* #include
+/* DESCRIPTION
+/* .nf
+
+ /*
+ * System library.
+ */
+#include
+#include
+#ifdef RESOLVE_H_NEEDS_STDIO_H
+#include
+#endif
+#include
+
+ /*
+ * Name server compatibility. These undocumented macros appear in the file
+ * , but since they are undocumented we should not count on
+ * their presence, and so they are included here just in case.
+ */
+#ifndef GETSHORT
+
+#define GETSHORT(s, cp) { \
+ unsigned char *t_cp = (u_char *)(cp); \
+ (s) = ((unsigned)t_cp[0] << 8) \
+ | ((unsigned)t_cp[1]) \
+ ; \
+ (cp) += 2; \
+}
+
+#define GETLONG(l, cp) { \
+ unsigned char *t_cp = (u_char *)(cp); \
+ (l) = ((unsigned)t_cp[0] << 24) \
+ | ((unsigned)t_cp[1] << 16) \
+ | ((unsigned)t_cp[2] << 8) \
+ | ((unsigned)t_cp[3]) \
+ ; \
+ (cp) += 4; \
+}
+
+#endif
+
+ /*
+ * Utility library.
+ */
+#include
+
+ /*
+ * Structure for fixed resource record data.
+ */
+typedef struct DNS_FIXED {
+ unsigned short type; /* T_A, T_CNAME, etc. */
+ unsigned short class; /* T_A, T_CNAME, etc. */
+ unsigned int ttl; /* always */
+ unsigned length; /* record length */
+} DNS_FIXED;
+
+ /*
+ * Structure of a DNS resource record after expansion. The components are
+ * named after the things one can expect to find in a DNS resource record.
+ */
+typedef struct DNS_RR {
+ char *name; /* name, mystrdup()ed */
+ unsigned short type; /* T_A, T_CNAME, etc. */
+ unsigned short class; /* T_A, T_CNAME, etc. */
+ unsigned int ttl; /* always */
+ unsigned short pref; /* T_MX only */
+ struct DNS_RR *next; /* linkage */
+ unsigned data_len; /* actual data size */
+ char data[1]; /* actually a bunch of data */
+} DNS_RR;
+
+ /*
+ * dns_strerror.c
+ */
+extern const char *dns_strerror(unsigned);
+
+ /*
+ * dns_strtype.c
+ */
+extern const char *dns_strtype(unsigned);
+extern unsigned dns_type(const char *);
+
+ /*
+ * dns_rr.c
+ */
+extern DNS_RR *dns_rr_create(const char *, DNS_FIXED *, unsigned,
+ const char *, unsigned);
+extern void dns_rr_free(DNS_RR *);
+extern DNS_RR *dns_rr_append(DNS_RR *, DNS_RR *);
+extern DNS_RR *dns_rr_sort(DNS_RR *, int (*) (DNS_RR *, DNS_RR *));
+
+ /*
+ * dns_lookup.c
+ */
+extern int dns_lookup(const char *, unsigned, unsigned, DNS_RR **,
+ VSTRING *, VSTRING *);
+extern int dns_lookup_types(const char *, unsigned, DNS_RR **,
+ VSTRING *, VSTRING *,...);
+
+ /*
+ * Status codes. Failures must have negative codes so they will not collide
+ * with valid counts of answer records etc.
+ */
+#define DNS_FAIL (-4) /* query failed, don't retry */
+#define DNS_NOTFOUND (-3) /* query ok, data not found */
+#define DNS_RETRY (-2) /* query failed, try again */
+#define DNS_RECURSE (-1) /* recursion needed */
+#define DNS_OK 0 /* query succeeded */
+
+ /*
+ * How long can a DNS name be?
+ */
+#define DNS_NAME_LEN 1024
+
+/* 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
+/*--*/
+
+#endif
diff --git a/postfix/dns/dns_lookup.c b/postfix/dns/dns_lookup.c
new file mode 100644
index 000000000..865e6c640
--- /dev/null
+++ b/postfix/dns/dns_lookup.c
@@ -0,0 +1,475 @@
+/*++
+/* NAME
+/* dns_lookup 3
+/* SUMMARY
+/* domain name service lookup
+/* SYNOPSIS
+/* #include
+/*
+/* int dns_lookup(name, type, flags, list, fqdn, why)
+/* const char *name;
+/* unsigned type;
+/* unsigned flags;
+/* DNS_RR **list;
+/* VSTRING *fqdn;
+/* VSTRING *why;
+/*
+/* int dns_lookup_types(name, flags, list, fqdn, why, type, ...)
+/* const char *name;
+/* unsigned flags;
+/* DNS_RR **list;
+/* VSTRING *fqdn;
+/* VSTRING *why;
+/* unsigned type;
+/* DESCRIPTION
+/* dns_lookup() looks up DNS resource records. When requested to
+/* look up data other than type CNAME, it will follow a limited
+/* number of CNAME indirections. All result names (including
+/* null terminator) will fit a buffer of size DNS_NAME_LEN.
+/* All name results are validated by \fIvalid_hostname\fR();
+/* an invalid name is reported as a transient error.
+/*
+/* dns_lookup_types() allows the user to specify a null-terminated
+/* list of resource types. This function calls dns_lookup() for each
+/* listed type in the specified order, until the list is exhausted or
+/* until the search result becomes not equal to DNS_NOTFOUND.
+/* INPUTS
+/* .ad
+/* .fi
+/* .IP name
+/* The name to be looked up in the domain name system.
+/* .IP type
+/* The resource record type to be looked up (T_A, T_MX etc.).
+/* .IP flags
+/* A bitwise OR of:
+/* .RS
+/* .IP RES_DEBUG
+/* Print debugging information.
+/* .IP RES_DNSRCH
+/* Search local domain and parent domains.
+/* .IP RES_DEFNAMES
+/* Append local domain to unqualified names.
+/* .RE
+/* OUTPUTS
+/* .ad
+/* .fi
+/* .IP list
+/* A null pointer, or a pointer to a variable that receives a
+/* list of requested resource records.
+/* .IP fqdn
+/* A null pointer, or storage for the fully-qualified domain
+/* name found for \fIname\fR.
+/* .IP why
+/* A null pointer, or storage for the reason for failure.
+/* DIAGNOSTICS
+/* dns_lookup() returns one of the following codes and sets the
+/* \fIwhy\fR argument accordingly:
+/* .IP DNS_OK
+/* The DNS query succeeded.
+/* .IP DNS_NOTFOUND
+/* The DNS query succeeded; the requested information was not found.
+/* .IP DNS_RETRY
+/* The query failed; the problem is transient.
+/* .IP DNS_FAIL
+/* The query failed.
+/* BUGS
+/* dns_lookup() implements a subset of all possible resource types:
+/* CNAME, MX, A, and some records with similar formatting requirements.
+/* It is unwise to specify the T_ANY wildcard resource type.
+/*
+/* It takes a surprising amount of code to accomplish what appears
+/* to be a simple task. Later versions of the mail system may implement
+/* their own DNS client software.
+/* SEE ALSO
+/* dns_rr(3) resource record memory and list management
+/* 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
+#include
+#include /* BSDI stdarg.h uses abort() */
+#include
+#include
+
+/* Utility library. */
+
+#include
+#include
+#include
+#include
+
+/* DNS library. */
+
+#include "dns.h"
+
+/* Local stuff. */
+
+ /*
+ * Structure to keep track of things while decoding a name server reply.
+ */
+#define DNS_REPLY_SIZE 4096 /* in case we're using TCP */
+
+typedef struct DNS_REPLY {
+ unsigned char buf[DNS_REPLY_SIZE]; /* raw reply data */
+ int query_count; /* number of queries */
+ int answer_count; /* number of answers */
+ unsigned char *query_start; /* start of query data */
+ unsigned char *answer_start; /* start of answer data */
+ unsigned char *end; /* first byte past reply */
+} DNS_REPLY;
+
+#define INET_ADDR_LEN 4 /* XXX */
+
+/* dns_query - query name server and pre-parse the reply */
+
+static int dns_query(const char *name, int type, int flags,
+ DNS_REPLY *reply, VSTRING *why)
+{
+ HEADER *reply_header;
+ int len;
+
+ /*
+ * Initialize the name service.
+ */
+ if ((_res.options & RES_INIT) == 0 && res_init() < 0) {
+ if (why)
+ vstring_strcpy(why, "Name service initialization failure");
+ return (DNS_FAIL);
+ }
+
+ /*
+ * Set search options: debugging, parent domain search, append local
+ * domain. Do not allow the user to control other features.
+ */
+#define USER_FLAGS (RES_DEBUG | RES_DNSRCH | RES_DEFNAMES)
+
+ if ((flags & USER_FLAGS) != flags)
+ msg_panic("dns_query: bad flags: %d", flags);
+ _res.options &= ~(USER_FLAGS);
+ _res.options |= flags;
+
+ /*
+ * Perform the lookup. Claim that the information cannot be found if and
+ * only if the name server told us so.
+ */
+ len = res_search((char *) name, C_IN, type, reply->buf, sizeof(reply->buf));
+ if (len < 0) {
+ if (why)
+ vstring_sprintf(why, "Name service error for domain %s: %s",
+ name, dns_strerror(h_errno));
+ if (msg_verbose)
+ msg_info("dns_query: %s (%s): %s",
+ name, dns_strtype(type), dns_strerror(h_errno));
+ switch (h_errno) {
+ case NO_RECOVERY:
+ return (DNS_FAIL);
+ case HOST_NOT_FOUND:
+ case NO_DATA:
+ return (DNS_NOTFOUND);
+ default:
+ return (DNS_RETRY);
+ }
+ }
+ if (msg_verbose)
+ msg_info("dns_query: %s (%s): OK", name, dns_strtype(type));
+
+ /*
+ * Initialize the reply structure. Some structure members are filled on
+ * the fly while the reply is being parsed.
+ */
+ if ((reply->end = reply->buf + len) > reply->buf + sizeof(reply->buf))
+ reply->end = reply->buf + sizeof(reply->buf);
+ reply_header = (HEADER *) reply->buf;
+ reply->query_start = reply->buf + sizeof(HEADER);
+ reply->answer_start = 0;
+ reply->query_count = ntohs(reply_header->qdcount);
+ reply->answer_count = ntohs(reply_header->ancount);
+ return (DNS_OK);
+}
+
+/* dns_skip_query - skip query data in name server reply */
+
+static int dns_skip_query(DNS_REPLY *reply)
+{
+ int query_count = reply->query_count;
+ unsigned char *pos = reply->query_start;
+ char temp[DNS_NAME_LEN];
+ int len;
+
+ /*
+ * For each query, skip over the domain name and over the fixed query
+ * data.
+ */
+ while (query_count-- > 0) {
+ if (pos >= reply->end)
+ return DNS_RETRY;
+ len = dn_expand(reply->buf, reply->end, pos, temp, DNS_NAME_LEN);
+ if (len < 0)
+ return (DNS_RETRY);
+ pos += len + QFIXEDSZ;
+ }
+ reply->answer_start = pos;
+ return (DNS_OK);
+}
+
+/* dns_get_fixed - extract fixed data from resource record */
+
+static int dns_get_fixed(unsigned char *pos, DNS_FIXED *fixed)
+{
+ GETSHORT(fixed->type, pos);
+ GETSHORT(fixed->class, pos);
+ GETLONG(fixed->ttl, pos);
+ GETSHORT(fixed->length, pos);
+
+ if (fixed->class != C_IN) {
+ msg_warn("dns_get_fixed: bad class: %u", fixed->class);
+ return (DNS_RETRY);
+ }
+ return (DNS_OK);
+}
+
+/* dns_get_rr - extract resource record from name server reply */
+
+static DNS_RR *dns_get_rr(DNS_REPLY *reply, unsigned char *pos,
+ char *rr_name, DNS_FIXED *fixed)
+{
+ char temp[DNS_NAME_LEN];
+ int data_len = fixed->length;
+ unsigned pref = 0;
+
+ if (pos + fixed->length > reply->end)
+ return (0);
+
+ switch (fixed->type) {
+ default:
+ msg_panic("dns_get_rr: don't know how to extract resource type %s",
+ dns_strtype(fixed->type));
+ case T_CNAME:
+ case T_MB:
+ case T_MG:
+ case T_MR:
+ case T_NS:
+ case T_PTR:
+ if (dn_expand(reply->buf, reply->end, pos, temp, sizeof(temp)) < 0)
+ return (0);
+ if (!valid_hostname(temp))
+ return (0);
+ data_len = strlen(temp) + 1;
+ break;
+ case T_MX:
+ GETSHORT(pref, pos);
+ if (dn_expand(reply->buf, reply->end, pos, temp, sizeof(temp)) < 0)
+ return (0);
+ if (!valid_hostname(temp))
+ return (0);
+ data_len = strlen(temp) + 1;
+ break;
+ case T_A:
+ if (fixed->length != INET_ADDR_LEN) {
+ msg_warn("extract_answer: bad address length: %d", fixed->length);
+ return (0);
+ }
+ if (fixed->length > sizeof(temp))
+ msg_panic("dns_get_rr: length %d > DNS_NAME_LEN",
+ fixed->length);
+ memcpy(temp, pos, fixed->length);
+ data_len = fixed->length;
+ break;
+ }
+ return (dns_rr_create(rr_name, fixed, pref, temp, data_len));
+}
+
+/* dns_get_alias - extract CNAME from name server reply */
+
+static int dns_get_alias(DNS_REPLY *reply, unsigned char *pos,
+ DNS_FIXED *fixed, char *cname, int c_len)
+{
+ if (fixed->type != T_CNAME)
+ msg_panic("dns_get_alias: bad type %s", dns_strtype(fixed->type));
+ if (dn_expand(reply->buf, reply->end, pos, cname, c_len) < 0)
+ return (DNS_RETRY);
+ if (!valid_hostname(cname))
+ return (DNS_RETRY);
+ return (DNS_OK);
+}
+
+/* dns_get_answer - extract answers from name server reply */
+
+static int dns_get_answer(DNS_REPLY *reply, int type,
+ DNS_RR **rrlist, VSTRING *fqdn, char *cname, int c_len)
+{
+ char rr_name[DNS_NAME_LEN];
+ unsigned char *pos;
+ int answer_count = reply->answer_count;
+ int len;
+ DNS_FIXED fixed;
+ DNS_RR *rr;
+ int resource_found = 0;
+ int cname_found = 0;
+
+ /*
+ * Initialize. Skip over the name server query if we haven't yet.
+ */
+ if (reply->answer_start == 0)
+ if (dns_skip_query(reply) < 0)
+ return (DNS_RETRY);
+ pos = reply->answer_start;
+ if (rrlist)
+ *rrlist = 0;
+
+ /*
+ * Either this, or use a GOTO for emergency exits. The purpose is to
+ * prevent incomplete answers from being passed back to the caller.
+ */
+#define CORRUPT { \
+ if (rrlist && *rrlist) { \
+ dns_rr_free(*rrlist); \
+ *rrlist = 0; \
+ } \
+ return (DNS_RETRY); \
+ }
+
+ /*
+ * Iterate over all answers.
+ */
+ while (answer_count-- > 0) {
+
+ /*
+ * Optionally extract the fully-qualified domain name.
+ */
+ if (pos >= reply->end)
+ CORRUPT;
+ len = dn_expand(reply->buf, reply->end, pos, rr_name, DNS_NAME_LEN);
+ if (len < 0)
+ CORRUPT;
+ if (!valid_hostname(rr_name))
+ CORRUPT;
+ if (fqdn)
+ vstring_strcpy(fqdn, rr_name);
+ pos += len;
+
+ /*
+ * Extract the fixed reply data: type, class, ttl, length.
+ */
+ if (pos + RRFIXEDSZ > reply->end)
+ CORRUPT;
+ if (dns_get_fixed(pos, &fixed) != DNS_OK)
+ CORRUPT;
+ if (msg_verbose)
+ msg_info("dns_get_answer: type %s for %s",
+ dns_strtype(fixed.type), rr_name);
+ pos += RRFIXEDSZ;
+
+ /*
+ * Optionally extract the requested resource or CNAME data.
+ */
+ if (pos + fixed.length > reply->end)
+ CORRUPT;
+ if (type == fixed.type || type == T_ANY) { /* requested type */
+ resource_found++;
+ if (rrlist) {
+ if ((rr = dns_get_rr(reply, pos, rr_name, &fixed)) == 0)
+ CORRUPT;
+ *rrlist = dns_rr_append(*rrlist, rr);
+ }
+ } else if (fixed.type == T_CNAME) { /* cname resource */
+ cname_found++;
+ if (cname && c_len > 0)
+ if (dns_get_alias(reply, pos, &fixed, cname, c_len) != DNS_OK)
+ CORRUPT;
+ }
+ pos += fixed.length;
+ }
+
+ /*
+ * See what answer we came up with. Report success when the requested
+ * information was found. Otherwise, when a CNAME was found, report that
+ * more recursion is needed. Otherwise report failure.
+ */
+ if (resource_found)
+ return (DNS_OK);
+ if (cname_found)
+ return (DNS_RECURSE);
+ return (DNS_NOTFOUND);
+}
+
+/* dns_lookup - DNS lookup user interface */
+
+int dns_lookup(const char *name, unsigned type, unsigned flags,
+ DNS_RR **rrlist, VSTRING *fqdn, VSTRING *why)
+{
+ char cname[DNS_NAME_LEN];
+ int c_len = sizeof(cname);
+ DNS_REPLY reply;
+ int count;
+ int status;
+
+ /*
+ * Perform the lookup. Follow CNAME chains, but only up to a
+ * pre-determined maximum.
+ */
+ for (count = 0; count < 10; count++) {
+
+ /*
+ * Perform the DNS lookup, and pre-parse the name server reply.
+ */
+ if ((status = dns_query(name, type, flags, &reply, why)) != DNS_OK)
+ return (status);
+
+ /*
+ * Extract resource records of the requested type. Pick up CNAME
+ * information just in case the requested data is not found.
+ */
+ status = dns_get_answer(&reply, type, rrlist, fqdn, cname, c_len);
+ switch (status) {
+ default:
+ if (why)
+ vstring_sprintf(why, "%s: Malformed name server reply", name);
+ case DNS_NOTFOUND:
+ case DNS_OK:
+ return (status);
+ case DNS_RECURSE:
+ if (msg_verbose)
+ msg_info("dns_lookup: %s aliased to %s", name, cname);
+ name = cname;
+ }
+ }
+ if (why)
+ vstring_sprintf(why, "Name server loop for %s", name);
+ msg_warn("dns_lookup: Name server loop for %s", name);
+ return (DNS_NOTFOUND);
+}
+
+/* dns_lookup_types - DNS lookup interface with multiple types */
+
+int dns_lookup_types(const char *name, unsigned flags, DNS_RR **rrlist,
+ VSTRING *fqdn, VSTRING *why,...)
+{
+ va_list ap;
+ unsigned type;
+ int status = DNS_NOTFOUND;
+ int soft_err = 0;
+
+ va_start(ap, why);
+ while ((type = va_arg(ap, unsigned)) != 0) {
+ if (msg_verbose)
+ msg_info("lookup %s type %d flags %d", name, type, flags);
+ status = dns_lookup(name, type, flags, rrlist, fqdn, why);
+ if (status == DNS_OK)
+ break;
+ if (status == DNS_RETRY)
+ soft_err = 1;
+ }
+ va_end(ap);
+ return ((status == DNS_OK || soft_err == 0) ? status : DNS_RETRY);
+}
diff --git a/postfix/dns/dns_rr.c b/postfix/dns/dns_rr.c
new file mode 100644
index 000000000..e6bb5f7a5
--- /dev/null
+++ b/postfix/dns/dns_rr.c
@@ -0,0 +1,173 @@
+/*++
+/* NAME
+/* dns_rr 3
+/* SUMMARY
+/* resource record memory and list management
+/* SYNOPSIS
+/* #include
+/*
+/* DNS_RR *dns_rr_create(name, fixed, preference, data, data_len)
+/* const char *name;
+/* DNS_FIXED *fixed;
+/* unsigned preference;
+/* const char *data;
+/* unsigned len;
+/*
+/* void dns_rr_free(list)
+/* DNS_RR *list;
+/*
+/* DNS_RR *dns_rr_append(list, record)
+/* DNS_RR *list;
+/* DNS_RR *record;
+/*
+/* DNS_RR *dns_rr_sort(list, compar)
+/* DNS_RR *list
+/* int (*compar)(DNS_RR *, DNS_RR *);
+/* DESCRIPTION
+/* The routines in this module maintain memory for DNS resource record
+/* information, and maintain lists of DNS resource records.
+/*
+/* dns_rr_create() creates and initializes one resource record.
+/* The \fIname\fR record specifies the record name.
+/* The \fIfixed\fR argument specifies generic resource record
+/* information such as resource type and time to live;
+/* \fIpreference\fR is used for MX records; \fIdata\fR is a null
+/* pointer or specifies optional resource-specific data;
+/* \fIdata_len\fR is the amount of resource-specific data.
+/*
+/* dns_rr_free() releases the resource used by of zero or more
+/* resource records.
+/*
+/* dns_rr_append() appends a resource record to a (list of) resource
+/* record(s).
+/*
+/* dns_rr_sort() sorts a list of resource records into ascending
+/* order according to a user-specified criterion. The result is the
+/* sorted 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
+#include
+#include
+
+/* Utility library. */
+
+#include
+#include
+
+/* DNS library. */
+
+#include "dns.h"
+
+/* dns_rr_create - fill in resource record structure */
+
+DNS_RR *dns_rr_create(const char *name, DNS_FIXED *fixed, unsigned pref,
+ const char *data, unsigned data_len)
+{
+ DNS_RR *rr;
+
+ rr = (DNS_RR *) mymalloc(sizeof(*rr) + data_len - 1);
+ rr->name = mystrdup(name);
+ rr->type = fixed->type;
+ rr->class = fixed->class;
+ rr->ttl = fixed->ttl;
+ rr->pref = pref;
+ if (data && data_len > 0)
+ memcpy(rr->data, data, data_len);
+ rr->data_len = data_len;
+ rr->next = 0;
+ return (rr);
+}
+
+/* dns_rr_free - destroy resource record structure */
+
+void dns_rr_free(DNS_RR *rr)
+{
+ if (rr) {
+ if (rr->next)
+ dns_rr_free(rr->next);
+ myfree(rr->name);
+ myfree((char *) rr);
+ }
+}
+
+/* dns_rr_append - append resource record to list */
+
+DNS_RR *dns_rr_append(DNS_RR *list, DNS_RR *rr)
+{
+ if (list == 0) {
+ list = rr;
+ } else {
+ list->next = dns_rr_append(list->next, rr);
+ }
+ return (list);
+}
+
+/* dns_rr_sort_callback - glue function */
+
+static int (*dns_rr_sort_user) (DNS_RR *, DNS_RR *);
+
+static int dns_rr_sort_callback(const void *a, const void *b)
+{
+ DNS_RR *aa = *(DNS_RR **) a;
+ DNS_RR *bb = *(DNS_RR **) b;
+
+ return (dns_rr_sort_user(aa, bb));
+}
+
+/* dns_rr_sort - sort resource record list */
+
+DNS_RR *dns_rr_sort(DNS_RR *list, int (*compar) (DNS_RR *, DNS_RR *))
+{
+ int (*saved_user) (DNS_RR *, DNS_RR *);
+ DNS_RR **rr_array;
+ DNS_RR *rr;
+ int len;
+ int i;
+
+ /*
+ * Save state and initialize.
+ */
+ saved_user = dns_rr_sort_user;
+ dns_rr_sort_user = compar;
+
+ /*
+ * Build linear array with pointers to each list element.
+ */
+ for (len = 0, rr = list; rr != 0; len++, rr = rr->next)
+ /* void */ ;
+ rr_array = (DNS_RR **) mymalloc(len * sizeof(*rr_array));
+ for (len = 0, rr = list; rr != 0; len++, rr = rr->next)
+ rr_array[len] = rr;
+
+ /*
+ * Sort by user-specified criterion.
+ */
+ qsort((char *) rr_array, len, sizeof(*rr_array), dns_rr_sort_callback);
+
+ /*
+ * Fix the links.
+ */
+ for (i = 0; i < len - 1; i++)
+ rr_array[i]->next = rr_array[i + 1];
+ rr_array[i]->next = 0;
+ list = rr_array[0];
+
+ /*
+ * Cleanup.
+ */
+ myfree((char *) rr_array);
+ dns_rr_sort_user = saved_user;
+ return (list);
+}
diff --git a/postfix/dns/dns_strerror.c b/postfix/dns/dns_strerror.c
new file mode 100644
index 000000000..9e56d3b86
--- /dev/null
+++ b/postfix/dns/dns_strerror.c
@@ -0,0 +1,69 @@
+/*++
+/* NAME
+/* dns_strerror 3
+/* SUMMARY
+/* name service lookup error code to string
+/* SYNOPSIS
+/* #include
+/*
+/* const char *dns_strerror(code)
+/* int code;
+/* DESCRIPTION
+/* dns_strerror() maps a name service lookup error to printable string.
+/* The result is for read-only purposes, and unknown codes share a
+/* common string buffer.
+/* 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
+#include
+
+/* Utility library. */
+
+#include
+
+/* DNS library. */
+
+#include "dns.h"
+
+ /*
+ * Mapping from error code to printable string. The herror() routine does
+ * something similar, but has output only to the stderr stream.
+ */
+struct dns_error_map {
+ unsigned error;
+ const char *text;
+};
+
+static struct dns_error_map dns_error_map[] = {
+ HOST_NOT_FOUND, "Host not found",
+ TRY_AGAIN, "Host not found, try again",
+ NO_RECOVERY, "Non-recoverable error",
+ NO_DATA, "Host found but no data record of requested type",
+};
+
+/* dns_strerror - map resolver error code to printable string */
+
+const char *dns_strerror(unsigned error)
+{
+ static VSTRING *unknown = 0;
+ unsigned i;
+
+ for (i = 0; i < sizeof(dns_error_map) / sizeof(dns_error_map[0]); i++)
+ if (dns_error_map[i].error == error)
+ return (dns_error_map[i].text);
+ if (unknown == 0)
+ unknown = vstring_alloc(sizeof("Unknown error XXXXXX"));
+ vstring_sprintf(unknown, "Unknown error %u", error);
+ return (vstring_str(unknown));
+}
diff --git a/postfix/dns/dns_strtype.c b/postfix/dns/dns_strtype.c
new file mode 100644
index 000000000..8e78de463
--- /dev/null
+++ b/postfix/dns/dns_strtype.c
@@ -0,0 +1,200 @@
+/*++
+/* NAME
+/* dns_strtype 3
+/* SUMMARY
+/* name service lookup type codes and printable forms
+/* SYNOPSIS
+/* #include
+/*
+/* const char *dns_strtype(code)
+/* int code;
+/*
+/* int dns_type(strval)
+/* const char *strval;
+/* DESCRIPTION
+/* dns_strtype() maps a name service lookup type to printable string.
+/* The result is for read-only purposes, and unknown codes share a
+/* common string buffer.
+/*
+/* dns_type() converts a name service lookup string value to a numeric
+/* code. A null result means the code was not found. The input can be
+/* in lower case, upper case or mixed case.
+/* 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
+#include
+
+#ifdef STRCASECMP_IN_STRINGS_H
+#include
+#endif
+
+/* Utility library. */
+
+#include
+
+/* DNS library. */
+
+#include "dns.h"
+
+ /*
+ * Mapping from type code to printable string. Some names are possibly not
+ * defined on every platform, so I have #ifdef-ed them all just to be safe.
+ */
+struct dns_type_map {
+ unsigned type;
+ const char *text;
+};
+
+static struct dns_type_map dns_type_map[] = {
+#ifdef T_A
+ T_A, "A",
+#endif
+#ifdef T_NS
+ T_NS, "NS",
+#endif
+#ifdef T_MD
+ T_MD, "MD",
+#endif
+#ifdef T_MF
+ T_MF, "MF",
+#endif
+#ifdef T_CNAME
+ T_CNAME, "CNAME",
+#endif
+#ifdef T_SOA
+ T_SOA, "SOA",
+#endif
+#ifdef T_MB
+ T_MB, "MB",
+#endif
+#ifdef T_MG
+ T_MG, "MG",
+#endif
+#ifdef T_MR
+ T_MR, "MR",
+#endif
+#ifdef T_NULL
+ T_NULL, "NULL",
+#endif
+#ifdef T_WKS
+ T_WKS, "WKS",
+#endif
+#ifdef T_PTR
+ T_PTR, "PTR",
+#endif
+#ifdef T_HINFO
+ T_HINFO, "HINFO",
+#endif
+#ifdef T_MINFO
+ T_MINFO, "MINFO",
+#endif
+#ifdef T_MX
+ T_MX, "MX",
+#endif
+#ifdef T_TXT
+ T_TXT, "TXT",
+#endif
+#ifdef T_RP
+ T_RP, "RP",
+#endif
+#ifdef T_AFSDB
+ T_AFSDB, "AFSDB",
+#endif
+#ifdef T_X25
+ T_X25, "X25",
+#endif
+#ifdef T_ISDN
+ T_ISDN, "ISDN",
+#endif
+#ifdef T_RT
+ T_RT, "RT",
+#endif
+#ifdef T_NSAP
+ T_NSAP, "NSAP",
+#endif
+#ifdef T_NSAP_PTR
+ T_NSAP_PTR, "NSAP_PTR",
+#endif
+#ifdef T_SIG
+ T_SIG, "SIG",
+#endif
+#ifdef T_KEY
+ T_KEY, "KEY",
+#endif
+#ifdef T_PX
+ T_PX, "PX",
+#endif
+#ifdef T_GPOS
+ T_GPOS, "GPOS",
+#endif
+#ifdef T_AAAA
+ T_AAAA, "AAAA",
+#endif
+#ifdef T_LOC
+ T_LOC, "LOC",
+#endif
+#ifdef T_UINFO
+ T_UINFO, "UINFO",
+#endif
+#ifdef T_UID
+ T_UID, "UID",
+#endif
+#ifdef T_GID
+ T_GID, "GID",
+#endif
+#ifdef T_UNSPEC
+ T_UNSPEC, "UNSPEC",
+#endif
+#ifdef T_AXFR
+ T_AXFR, "AXFR",
+#endif
+#ifdef T_MAILB
+ T_MAILB, "MAILB",
+#endif
+#ifdef T_MAILA
+ T_MAILA, "MAILA",
+#endif
+#ifdef T_ANY
+ T_ANY, "ANY",
+#endif
+};
+
+/* dns_strtype - translate DNS query type to string */
+
+const char *dns_strtype(unsigned type)
+{
+ static VSTRING *unknown = 0;
+ unsigned i;
+
+ for (i = 0; i < sizeof(dns_type_map) / sizeof(dns_type_map[0]); i++)
+ if (dns_type_map[i].type == type)
+ return (dns_type_map[i].text);
+ if (unknown == 0)
+ unknown = vstring_alloc(sizeof("Unknown type XXXXXX"));
+ vstring_sprintf(unknown, "Unknown type %u", type);
+ return (vstring_str(unknown));
+}
+
+/* dns_type - translate string to DNS query type */
+
+unsigned dns_type(const char *text)
+{
+ unsigned i;
+
+ for (i = 0; i < sizeof(dns_type_map) / sizeof(dns_type_map[0]); i++)
+ if (strcasecmp(dns_type_map[i].text, text) == 0)
+ return (dns_type_map[i].type);
+ return (0);
+}
+
diff --git a/postfix/dns/test_dns_lookup.c b/postfix/dns/test_dns_lookup.c
new file mode 100644
index 000000000..5f1a9e63e
--- /dev/null
+++ b/postfix/dns/test_dns_lookup.c
@@ -0,0 +1,95 @@
+/*++
+/* NAME
+/* test_dns_lookup 1
+/* SUMMARY
+/* DNS lookup test program
+/* SYNOPSIS
+/* test_dns_lookup query-type domain-name
+/* DESCRIPTION
+/* test_dns_lookup performs a DNS query of the specified resource
+/* type for the specified resource name.
+/* DIAGNOSTICS
+/* Problems are reported to the standard error stream.
+/* 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
+#include
+#include
+#include
+
+/* Utility library. */
+
+#include
+#include
+#include
+
+/* Application-specific. */
+
+#include "dns.h"
+
+static void print_rr(DNS_RR *rr)
+{
+ struct in_addr addr;
+
+ while (rr) {
+ printf("%s: ttl: %9d ", rr->name, rr->ttl);
+ switch (rr->type) {
+ case T_A:
+ memcpy((char *) &addr.s_addr, rr->data, sizeof(addr.s_addr));
+ printf("%s: %s\n", dns_strtype(rr->type), inet_ntoa(addr));
+ break;
+ case T_CNAME:
+ case T_MB:
+ case T_MG:
+ case T_MR:
+ case T_NS:
+ case T_PTR:
+ printf("%s: %s\n", dns_strtype(rr->type), rr->data);
+ break;
+ case T_MX:
+ printf("pref: %d %s: %s\n",
+ rr->pref, dns_strtype(rr->type), rr->data);
+ break;
+ default:
+ msg_fatal("print_rr: don't know how to print type %s",
+ dns_strtype(rr->type));
+ }
+ rr = rr->next;
+ }
+}
+
+int main(int argc, char **argv)
+{
+ int type;
+ char *name;
+ VSTRING *fqdn = vstring_alloc(100);
+ VSTRING *why = vstring_alloc(100);
+ DNS_RR *rr;
+
+ msg_vstream_init(argv[0], VSTREAM_ERR);
+ if (argc != 3)
+ msg_fatal("usage: %s type name", argv[0]);
+ if ((type = dns_type(argv[1])) == 0)
+ msg_fatal("invalid query type: %s", argv[1]);
+ name = argv[2];
+ msg_verbose = 1;
+ switch (dns_lookup_types(name, RES_DEFNAMES | RES_DEBUG, &rr, fqdn, why, type, 0)) {
+ default:
+ msg_fatal("%s", vstring_str(why));
+ case DNS_OK:
+ printf("%s: fqdn: %s\n", name, vstring_str(fqdn));
+ print_rr(rr);
+ }
+ exit(0);
+}
diff --git a/postfix/fsstone/.indent.pro b/postfix/fsstone/.indent.pro
new file mode 100644
index 000000000..e59d396ad
--- /dev/null
+++ b/postfix/fsstone/.indent.pro
@@ -0,0 +1,89 @@
+-TALIAS_TOKEN
+-TARGV
+-TBH_TABLE
+-TBINHASH
+-TBINHASH_INFO
+-TBOUNCE_STAT
+-TCLEANUP_STATE
+-TCLIENT_LIST
+-TCONFIG_BOOL_FN_TABLE
+-TCONFIG_BOOL_TABLE
+-TCONFIG_INT_FN_TABLE
+-TCONFIG_INT_TABLE
+-TCONFIG_STR_FN_TABLE
+-TCONFIG_STR_TABLE
+-TDELIVER_ATTR
+-TDELIVER_REQUEST
+-TDICT
+-TDICT_DB
+-TDICT_DBM
+-TDICT_ENV
+-TDICT_HT
+-TDICT_LDAP
+-TDICT_NI
+-TDICT_NIS
+-TDICT_NISPLUS
+-TDICT_NODE
+-TDICT_OPEN_INFO
+-TDNS_FIXED
+-TDNS_REPLY
+-TDNS_RR
+-TDOMAIN_LIST
+-TEXPAND_ATTR
+-TFILE
+-TFORWARD_INFO
+-THEADER_OPTS
+-THTABLE
+-THTABLE_INFO
+-TINET_ADDR_LIST
+-TINT_TABLE
+-TLOCAL_STATE
+-TMAC_HEAD
+-TMAC_PARSE
+-TMAIL_PRINT
+-TMAIL_SCAN
+-TMAPS
+-TMASTER_PROC
+-TMASTER_SERV
+-TMASTER_STATUS
+-TMBLOCK
+-TMKMAP
+-TMKMAP_OPEN_INFO
+-TMULTI_SERVER
+-TMVECT
+-TNAMADR_LIST
+-TNAME_MASK
+-TPEER_NAME
+-TPICKUP_INFO
+-TPIPE_ATTR
+-TPIPE_PARAMS
+-TQMGR_ENTRY
+-TQMGR_MESSAGE
+-TQMGR_QUEUE
+-TQMGR_RCPT_LIST
+-TQMGR_RECIPIENT
+-TQMGR_SCAN
+-TQMGR_TRANSPORT
+-TRECIPIENT
+-TRECIPIENT_LIST
+-TREC_TYPE_NAME
+-TRESOLVE_REPLY
+-TSCAN_DIR
+-TSINGLE_SERVER
+-TSMTPD_STATE
+-TSMTPD_TOKEN
+-TSMTP_ADDR
+-TSMTP_CMD
+-TSMTP_RESP
+-TSMTP_SESSION
+-TSMTP_STATE
+-TSOCKADDR_SIZE
+-TSTRING_TABLE
+-TSYS_EXITS_TABLE
+-TTOK822
+-TTRIGGER_SERVER
+-TUSER_ATTR
+-TVBUF
+-TVSTREAM
+-TVSTRING
+-TWAIT_STATUS_T
diff --git a/postfix/fsstone/.printfck b/postfix/fsstone/.printfck
new file mode 100644
index 000000000..9ed900cb0
--- /dev/null
+++ b/postfix/fsstone/.printfck
@@ -0,0 +1,24 @@
+been_here_xt 2 0
+bounce_append 5 0
+cleanup_out_format 1 0
+defer_append 5 0
+mail_command 1 0
+mail_print 1 0
+msg_error 0 0
+msg_fatal 0 0
+msg_info 0 0
+msg_panic 0 0
+msg_warn 0 0
+opened 3 0
+qmgr_message_bounce 2 0
+rec_fprintf 2 0
+sent 4 0
+smtp_cmd 1 0
+smtp_mesg_fail 2 0
+smtp_printf 1 0
+smtp_rcpt_fail 3 0
+smtp_site_fail 2 0
+udp_syslog 1 0
+vstream_fprintf 1 0
+vstream_printf 0 0
+vstring_sprintf 1 0
diff --git a/postfix/fsstone/Makefile.in b/postfix/fsstone/Makefile.in
new file mode 100644
index 000000000..cba53254e
--- /dev/null
+++ b/postfix/fsstone/Makefile.in
@@ -0,0 +1,62 @@
+SHELL = /bin/sh
+SRCS = fsstone.c
+OBJS = fsstone.o
+HDRS =
+TESTSRC =
+WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
+ -Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
+ -Wunused
+DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
+CFLAGS = $(DEBUG) $(OPT) $(DEFS)
+TESTPROG=
+PROG = fsstone
+INC_DIR = ../include
+LIBS = ../lib/libglobal.a ../lib/libutil.a
+
+.c.o:; $(CC) $(CFLAGS) -c $*.c
+
+all: $(PROG)
+
+Makefile: Makefile.in
+ (set -e; echo "# DO NOT EDIT"; $(OPTS) sh ../makedefs; cat $?) >$@
+
+fsstone: fsstone.o $(LIBS)
+ $(CC) $(CFLAGS) -o $@ fsstone.o $(LIBS) $(SYSLIBS)
+
+test: $(TESTPROG)
+
+update: ../bin/fsstone
+
+../bin/fsstone: fsstone
+ cp $? $@
+
+printfck: $(OBJS) $(PROG)
+ rm -rf printfck
+ mkdir 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
+
+# do not edit below this line - it is generated by 'make depend'
+fsstone.o: fsstone.c
+fsstone.o: ../include/sys_defs.h
+fsstone.o: ../include/msg.h
+fsstone.o: ../include/msg_vstream.h
+fsstone.o: ../include/vstream.h
+fsstone.o: ../include/vbuf.h
diff --git a/postfix/fsstone/fsstone.c b/postfix/fsstone/fsstone.c
new file mode 100644
index 000000000..1257417dd
--- /dev/null
+++ b/postfix/fsstone/fsstone.c
@@ -0,0 +1,211 @@
+/*++
+/* NAME
+/* fsstone 1
+/* SUMMARY
+/* measure directory operation overhead
+/* SYNOPSIS
+/* \fBfsstone\fR [\fB-c\fR] [\fB-r\fR] \fImsg_count files_per_dir\fR
+/* DESCRIPTION
+/* The \fBfsstone\fR command measures the cost of creating, renaming
+/* and deleting queue files versus appending messages to existing
+/* files and truncating them after use.
+/*
+/* The program simulates the arrival of \fImsg_count\fR short messages,
+/* and arranges for at most \fIfiles_per_dir\fR simultaneous files
+/* in the same directory.
+/*
+/* Options:
+/* .IP \fB-c\fR
+/* Create and delete files.
+/* .IP \fB-r\fR
+/* Rename files twice (requires \fB-c\fR).
+/* DIAGNOSTICS
+/* Problems are reported to the standard error stream.
+/* BUGS
+/* The \fB-r\fR option renames files within the same directory.
+/* For a more realistic simulation, the program should rename files
+/* between directories, and should also have an option to use
+/* hashed directories as implemented with, for example, the
+/* \fBdir_forest\fR(3) module.
+/* 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
+#include
+#include
+#include
+#include
+
+/* Utility library. */
+
+#include
+#include
+
+/* rename_file - rename a file */
+
+static void rename_file(int old, int new)
+{
+ char new_path[BUFSIZ];
+ char old_path[BUFSIZ];
+
+ sprintf(new_path, "%06d", new);
+ sprintf(old_path, "%06d", old);
+ if (rename(old_path, new_path))
+ msg_fatal("rename %s to %s: %m", old_path, new_path);
+}
+
+/* make_file - create a little file and use it */
+
+static void make_file(int seqno)
+{
+ char path[BUFSIZ];
+ FILE *fp;
+ int i;
+
+ sprintf(path, "%06d", seqno);
+ if ((fp = fopen(path, "w")) == 0)
+ msg_fatal("open %s: %m", path);
+ for (i = 0; i < 400; i++)
+ fprintf(fp, "hello");
+ if (fsync(fileno(fp)))
+ msg_fatal("fsync: %m");
+ if (fclose(fp))
+ msg_fatal("fclose: %m");
+ if ((fp = fopen(path, "r")) == 0)
+ msg_fatal("open %s: %m", path);
+ while (fgets(path, sizeof(path), fp))
+ /* void */ ;
+ if (fclose(fp))
+ msg_fatal("fclose: %m");
+}
+
+/* use_file - use existing file */
+
+static void use_file(int seqno)
+{
+ char path[BUFSIZ];
+ FILE *fp;
+ int i;
+
+ sprintf(path, "%06d", seqno);
+ if ((fp = fopen(path, "w")) == 0)
+ msg_fatal("open %s: %m", path);
+ for (i = 0; i < 400; i++)
+ fprintf(fp, "hello");
+ if (fsync(fileno(fp)))
+ msg_fatal("fsync: %m");
+ if (fclose(fp))
+ msg_fatal("fclose: %m");
+ if ((fp = fopen(path, "r+")) == 0)
+ msg_fatal("open %s: %m", path);
+ while (fgets(path, sizeof(path), fp))
+ /* void */ ;
+ if (ftruncate(fileno(fp), (off_t) 0))
+ msg_fatal("ftruncate: %m");;
+ if (fclose(fp))
+ msg_fatal("fclose: %m");
+}
+
+/* remove_file - delete specified file */
+
+static void remove_file(int seq)
+{
+ char path[BUFSIZ];
+
+ sprintf(path, "%06d", seq);
+ if (remove(path))
+ msg_fatal("remove %s: %m", path);
+}
+
+/* remove_silent - delete specified file, silently */
+
+static void remove_silent(int seq)
+{
+ char path[BUFSIZ];
+
+ sprintf(path, "%06d", seq);
+ (void) remove(path);
+}
+
+/* usage - explain */
+
+static void usage(char *myname)
+{
+ msg_fatal("usage: %s [-c [-r]] messages directory_entries", myname);
+}
+
+int main(int argc, char **argv)
+{
+ int op_count;
+ int max_file;
+ time_t start;
+ int do_rename = 0;
+ int do_create = 0;
+ int seq;
+ int ch;
+
+ msg_vstream_init(argv[0], VSTREAM_ERR);
+ while ((ch = GETOPT(argc, argv, "cr")) != EOF) {
+ switch (ch) {
+ case 'c':
+ do_create++;
+ break;
+ case 'r':
+ do_rename++;
+ break;
+ default:
+ usage(argv[0]);
+ }
+ }
+
+ if (argc - optind != 2 || (do_rename && !do_create))
+ usage(argv[0]);
+ if ((op_count = atoi(argv[optind])) <= 0)
+ usage(argv[0]);
+ if ((max_file = atoi(argv[optind + 1])) <= 0)
+ usage(argv[0]);
+
+ /*
+ * Populate the directory with little files.
+ */
+ for (seq = 0; seq < max_file; seq++)
+ make_file(seq);
+
+ /*
+ * Simulate arrival and delivery of mail messages.
+ */
+ start = time((time_t *) 0);
+ while (op_count > 0) {
+ seq %= max_file;
+ if (do_create) {
+ remove_file(seq);
+ make_file(seq);
+ if (do_rename) {
+ rename_file(seq, seq + max_file);
+ rename_file(seq + max_file, seq);
+ }
+ } else {
+ use_file(seq);
+ }
+ seq++;
+ op_count--;
+ }
+ printf("elapsed time: %ld\n", (long) time((time_t *) 0) - start);
+
+ /*
+ * Clean up directory fillers.
+ */
+ for (seq = 0; seq < max_file; seq++)
+ remove_silent(seq);
+ return (0);
+}
diff --git a/postfix/global/.indent.pro b/postfix/global/.indent.pro
new file mode 100644
index 000000000..e59d396ad
--- /dev/null
+++ b/postfix/global/.indent.pro
@@ -0,0 +1,89 @@
+-TALIAS_TOKEN
+-TARGV
+-TBH_TABLE
+-TBINHASH
+-TBINHASH_INFO
+-TBOUNCE_STAT
+-TCLEANUP_STATE
+-TCLIENT_LIST
+-TCONFIG_BOOL_FN_TABLE
+-TCONFIG_BOOL_TABLE
+-TCONFIG_INT_FN_TABLE
+-TCONFIG_INT_TABLE
+-TCONFIG_STR_FN_TABLE
+-TCONFIG_STR_TABLE
+-TDELIVER_ATTR
+-TDELIVER_REQUEST
+-TDICT
+-TDICT_DB
+-TDICT_DBM
+-TDICT_ENV
+-TDICT_HT
+-TDICT_LDAP
+-TDICT_NI
+-TDICT_NIS
+-TDICT_NISPLUS
+-TDICT_NODE
+-TDICT_OPEN_INFO
+-TDNS_FIXED
+-TDNS_REPLY
+-TDNS_RR
+-TDOMAIN_LIST
+-TEXPAND_ATTR
+-TFILE
+-TFORWARD_INFO
+-THEADER_OPTS
+-THTABLE
+-THTABLE_INFO
+-TINET_ADDR_LIST
+-TINT_TABLE
+-TLOCAL_STATE
+-TMAC_HEAD
+-TMAC_PARSE
+-TMAIL_PRINT
+-TMAIL_SCAN
+-TMAPS
+-TMASTER_PROC
+-TMASTER_SERV
+-TMASTER_STATUS
+-TMBLOCK
+-TMKMAP
+-TMKMAP_OPEN_INFO
+-TMULTI_SERVER
+-TMVECT
+-TNAMADR_LIST
+-TNAME_MASK
+-TPEER_NAME
+-TPICKUP_INFO
+-TPIPE_ATTR
+-TPIPE_PARAMS
+-TQMGR_ENTRY
+-TQMGR_MESSAGE
+-TQMGR_QUEUE
+-TQMGR_RCPT_LIST
+-TQMGR_RECIPIENT
+-TQMGR_SCAN
+-TQMGR_TRANSPORT
+-TRECIPIENT
+-TRECIPIENT_LIST
+-TREC_TYPE_NAME
+-TRESOLVE_REPLY
+-TSCAN_DIR
+-TSINGLE_SERVER
+-TSMTPD_STATE
+-TSMTPD_TOKEN
+-TSMTP_ADDR
+-TSMTP_CMD
+-TSMTP_RESP
+-TSMTP_SESSION
+-TSMTP_STATE
+-TSOCKADDR_SIZE
+-TSTRING_TABLE
+-TSYS_EXITS_TABLE
+-TTOK822
+-TTRIGGER_SERVER
+-TUSER_ATTR
+-TVBUF
+-TVSTREAM
+-TVSTRING
+-TWAIT_STATUS_T
diff --git a/postfix/global/.printfck b/postfix/global/.printfck
new file mode 100644
index 000000000..9ed900cb0
--- /dev/null
+++ b/postfix/global/.printfck
@@ -0,0 +1,24 @@
+been_here_xt 2 0
+bounce_append 5 0
+cleanup_out_format 1 0
+defer_append 5 0
+mail_command 1 0
+mail_print 1 0
+msg_error 0 0
+msg_fatal 0 0
+msg_info 0 0
+msg_panic 0 0
+msg_warn 0 0
+opened 3 0
+qmgr_message_bounce 2 0
+rec_fprintf 2 0
+sent 4 0
+smtp_cmd 1 0
+smtp_mesg_fail 2 0
+smtp_printf 1 0
+smtp_rcpt_fail 3 0
+smtp_site_fail 2 0
+udp_syslog 1 0
+vstream_fprintf 1 0
+vstream_printf 0 0
+vstring_sprintf 1 0
diff --git a/postfix/global/Makefile.in b/postfix/global/Makefile.in
new file mode 100644
index 000000000..3fe66c8fb
--- /dev/null
+++ b/postfix/global/Makefile.in
@@ -0,0 +1,842 @@
+SHELL = /bin/sh
+SRCS = been_here.c bounce.c canon_addr.c clean_env.c cleanup_strerror.c \
+ config.c config_bool.c config_int.c config_str.c debug_peer.c \
+ debug_process.c defer.c deliver_completed.c deliver_flock.c \
+ deliver_request.c domain_list.c dot_lockfile.c file_id.c \
+ header_opts.c is_header.c mail_addr.c mail_addr_crunch.c \
+ mail_addr_find.c mail_addr_map.c mail_command_read.c \
+ mail_command_write.c mail_connect.c mail_copy.c mail_date.c \
+ mail_error.c mail_flush.c mail_open_ok.c mail_params.c \
+ mail_pathname.c mail_print.c mail_queue.c mail_run.c mail_scan.c \
+ mail_task.c mail_trigger.c maps.c mark_corrupt.c mkmap_db.c \
+ mkmap_dbm.c mkmap_open.c mynetworks.c mypwd.c namadr_list.c \
+ off_cvt.c opened.c own_inet_addr.c pipe_command.c post_mail.c \
+ quote_822_local.c rec_streamlf.c rec_type.c recipient_list.c \
+ record.c remove.c resolve_clnt.c resolve_local.c rewrite_clnt.c \
+ sent.c smtp_stream.c split_addr.c string_list.c sys_exits.c \
+ timed_ipc.c tok822_find.c tok822_node.c tok822_parse.c \
+ tok822_resolve.c tok822_rewrite.c tok822_tree.c mail_stream.c
+OBJS = been_here.o bounce.o canon_addr.o clean_env.o cleanup_strerror.o \
+ config.o config_bool.o config_int.o config_str.o debug_peer.o \
+ debug_process.o defer.o deliver_completed.o deliver_flock.o \
+ deliver_request.o domain_list.o dot_lockfile.o file_id.o \
+ header_opts.o is_header.o mail_addr.o mail_addr_crunch.o \
+ mail_addr_find.o mail_addr_map.o mail_command_read.o \
+ mail_command_write.o mail_connect.o mail_copy.o mail_date.o \
+ mail_error.o mail_flush.o mail_open_ok.o mail_params.o \
+ mail_pathname.o mail_print.o mail_queue.o mail_run.o mail_scan.o \
+ mail_task.o mail_trigger.o maps.o mark_corrupt.o mkmap_db.o \
+ mkmap_dbm.o mkmap_open.o mynetworks.o mypwd.o namadr_list.o \
+ off_cvt.o opened.o own_inet_addr.o pipe_command.o post_mail.o \
+ quote_822_local.o rec_streamlf.o rec_type.o recipient_list.o \
+ record.o remove.o resolve_clnt.o resolve_local.o rewrite_clnt.o \
+ sent.o smtp_stream.o split_addr.o string_list.o sys_exits.o \
+ timed_ipc.o tok822_find.o tok822_node.o tok822_parse.o \
+ tok822_resolve.o tok822_rewrite.o tok822_tree.o mail_stream.o
+HDRS = been_here.h bounce.h canon_addr.h clean_env.h cleanup_user.h \
+ config.h debug_peer.h debug_process.h defer.h deliver_completed.h \
+ deliver_flock.h deliver_request.h domain_list.h dot_lockfile.h \
+ file_id.h header_opts.h is_header.h mail_addr.h mail_addr_crunch.h \
+ mail_addr_find.h mail_addr_map.h mail_copy.h mail_date.h \
+ mail_error.h mail_flush.h mail_open_ok.h mail_params.h \
+ mail_proto.h mail_queue.h mail_run.h mail_task.h mail_version.h \
+ maps.h mark_corrupt.h mkmap.h mynetworks.h mypwd.h namadr_list.h \
+ off_cvt.h opened.h own_inet_addr.h pipe_command.h post_mail.h \
+ quote_822_local.h rec_streamlf.h rec_type.h recipient_list.h \
+ record.h resolve_clnt.h resolve_local.h rewrite_clnt.h sent.h \
+ smtp_stream.h split_addr.h string_list.h sys_exits.h timed_ipc.h \
+ tok822.h mail_stream.h
+TESTSRC = rec2stream.c stream2rec.c recdump.c
+WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
+ -Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
+ -Wunused
+DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
+CFLAGS = $(DEBUG) $(OPT) $(DEFS)
+INCL =
+LIB = libglobal.a
+TESTPROG= domain_list dot_lockfile mail_addr_crunch mail_addr_find \
+ mail_addr_map mail_date maps mynetworks mypwd namadr_list \
+ off_cvt quote_822_local rec2stream recdump resolve_clnt \
+ resolve_local rewrite_clnt stream2rec string_list tok822_parse
+
+LIBS = ../lib/libutil.a
+LIB_DIR = ../lib
+INC_DIR = ../include
+MAKES =
+
+.c.o:; $(CC) $(CFLAGS) -c $*.c
+
+all: $(LIB)
+
+Makefile: Makefile.in
+ (set -e; echo "# DO NOT EDIT"; $(OPTS) sh ../makedefs; cat $?) >$@
+
+test: $(TESTPROG)
+
+$(LIB): $(OBJS)
+ $(AR) $(ARFL) $(LIB) $?
+ $(RANLIB) $(LIB)
+
+$(LIB_DIR)/$(LIB): $(LIB)
+ cp $(LIB) $(LIB_DIR)
+ $(RANLIB) $(LIB_DIR)/$(LIB)
+
+update: $(LIB_DIR)/$(LIB) $(HDRS)
+ -for i in $(HDRS); \
+ do \
+ cmp -s $$i $(INC_DIR)/$$i 2>/dev/null || cp $$i $(INC_DIR); \
+ done
+ cd $(INC_DIR); chmod 644 $(HDRS)
+
+dot_lockfile: $(LIB) $(LIBS)
+ mv $@.o junk
+ $(CC) -DTEST $(CFLAGS) -o $@ $@.c $(LIB) $(LIBS) $(SYSLIBS)
+ mv junk $@.o
+
+tok822_parse: $(LIB) $(LIBS)
+ mv $@.o junk
+ $(CC) -DTEST $(CFLAGS) -o $@ $@.c $(LIB) $(LIBS) $(SYSLIBS)
+ mv junk $@.o
+
+rec2stream: rec2stream.c $(LIB) $(LIBS)
+ $(CC) $(CFLAGS) -o $@ $@.c $(LIB) $(LIBS) $(SYSLIBS)
+
+stream2rec: stream2rec.c $(LIB) $(LIBS)
+ $(CC) $(CFLAGS) -o $@ $@.c $(LIB) $(LIBS) $(SYSLIBS)
+
+recdump: recdump.c $(LIB) $(LIBS)
+ $(CC) $(CFLAGS) -o $@ $@.c $(LIB) $(LIBS) $(SYSLIBS)
+
+namadr_list: $(LIB) $(LIBS)
+ mv $@.o junk
+ $(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(LIBS) $(SYSLIBS)
+ mv junk $@.o
+
+domain_list: $(LIB) $(LIBS)
+ mv $@.o junk
+ $(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(LIBS) $(SYSLIBS)
+ mv junk $@.o
+
+mynetworks: $(LIB) $(LIBS)
+ mv $@.o junk
+ $(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(LIBS) $(SYSLIBS)
+ mv junk $@.o
+
+resolve_clnt: $(LIB) $(LIBS)
+ mv $@.o junk
+ $(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(LIBS) $(SYSLIBS)
+ mv junk $@.o
+
+rewrite_clnt: $(LIB) $(LIBS)
+ mv $@.o junk
+ $(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(LIBS) $(SYSLIBS)
+ mv junk $@.o
+
+quote_822_local: $(LIB) $(LIBS)
+ mv $@.o junk
+ $(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(LIBS) $(SYSLIBS)
+ mv junk $@.o
+
+off_cvt: $(LIB) $(LIBS)
+ mv $@.o junk
+ $(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(LIBS) $(SYSLIBS)
+ mv junk $@.o
+
+mail_addr_map: $(LIB) $(LIBS)
+ mv $@.o junk
+ $(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(LIBS) $(SYSLIBS)
+ mv junk $@.o
+
+mail_addr_find: $(LIB) $(LIBS)
+ mv $@.o junk
+ $(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(LIBS) $(SYSLIBS)
+ mv junk $@.o
+
+maps: $(LIB) $(LIBS)
+ mv $@.o junk
+ $(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(LIBS) $(SYSLIBS)
+ mv junk $@.o
+
+mypwd: $(LIB) $(LIBS)
+ mv $@.o junk
+ $(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(LIBS) $(SYSLIBS)
+ mv junk $@.o
+
+mail_date: $(LIB) $(LIBS)
+ mv $@.o junk
+ $(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(LIBS) $(SYSLIBS)
+ mv junk $@.o
+
+resolve_local: $(LIB) $(LIBS)
+ mv $@.o junk
+ $(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(LIBS) $(SYSLIBS)
+ mv junk $@.o
+
+mail_addr_crunch: $(LIB) $(LIBS)
+ mv $@.o junk
+ $(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(LIBS) $(SYSLIBS)
+ mv junk $@.o
+
+string_list: $(LIB) $(LIBS)
+ mv $@.o junk
+ $(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(LIBS) $(SYSLIBS)
+ mv junk $@.o
+
+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 $(LIB) *core $(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
+
+# do not edit below this line - it is generated by 'make depend'
+been_here.o: been_here.c
+been_here.o: ../include/sys_defs.h
+been_here.o: ../include/msg.h
+been_here.o: ../include/mymalloc.h
+been_here.o: ../include/htable.h
+been_here.o: ../include/vstring.h
+been_here.o: ../include/vbuf.h
+been_here.o: ../include/stringops.h
+been_here.o: been_here.h
+bounce.o: bounce.c
+bounce.o: ../include/sys_defs.h
+bounce.o: ../include/msg.h
+bounce.o: ../include/vstring.h
+bounce.o: ../include/vbuf.h
+bounce.o: mail_proto.h
+bounce.o: ../include/vstream.h
+bounce.o: ../include/iostuff.h
+bounce.o: defer.h
+bounce.o: bounce.h
+canon_addr.o: canon_addr.c
+canon_addr.o: ../include/sys_defs.h
+canon_addr.o: ../include/vstring.h
+canon_addr.o: ../include/vbuf.h
+canon_addr.o: ../include/mymalloc.h
+canon_addr.o: rewrite_clnt.h
+canon_addr.o: canon_addr.h
+clean_env.o: clean_env.c
+clean_env.o: ../include/sys_defs.h
+clean_env.o: ../include/msg.h
+clean_env.o: clean_env.h
+cleanup_strerror.o: cleanup_strerror.c
+cleanup_strerror.o: ../include/sys_defs.h
+cleanup_strerror.o: ../include/vstring.h
+cleanup_strerror.o: ../include/vbuf.h
+cleanup_strerror.o: cleanup_user.h
+config.o: config.c
+config.o: ../include/sys_defs.h
+config.o: ../include/msg.h
+config.o: ../include/mymalloc.h
+config.o: ../include/vstream.h
+config.o: ../include/vbuf.h
+config.o: ../include/vstring.h
+config.o: ../include/dict.h
+config.o: ../include/safe.h
+config.o: ../include/stringops.h
+config.o: mail_params.h
+config.o: config.h
+config_bool.o: config_bool.c
+config_bool.o: ../include/sys_defs.h
+config_bool.o: ../include/msg.h
+config_bool.o: ../include/dict.h
+config_bool.o: ../include/vstream.h
+config_bool.o: ../include/vbuf.h
+config_bool.o: config.h
+config_int.o: config_int.c
+config_int.o: ../include/sys_defs.h
+config_int.o: ../include/msg.h
+config_int.o: ../include/mymalloc.h
+config_int.o: ../include/dict.h
+config_int.o: ../include/vstream.h
+config_int.o: ../include/vbuf.h
+config_int.o: ../include/stringops.h
+config_int.o: config.h
+config_str.o: config_str.c
+config_str.o: ../include/sys_defs.h
+config_str.o: ../include/msg.h
+config_str.o: ../include/mymalloc.h
+config_str.o: config.h
+debug_peer.o: debug_peer.c
+debug_peer.o: ../include/sys_defs.h
+debug_peer.o: ../include/msg.h
+debug_peer.o: mail_params.h
+debug_peer.o: namadr_list.h
+debug_peer.o: debug_peer.h
+debug_process.o: debug_process.c
+debug_process.o: ../include/sys_defs.h
+debug_process.o: ../include/msg.h
+debug_process.o: mail_params.h
+debug_process.o: config.h
+debug_process.o: debug_process.h
+defer.o: defer.c
+defer.o: ../include/sys_defs.h
+defer.o: ../include/msg.h
+defer.o: ../include/vstring.h
+defer.o: ../include/vbuf.h
+defer.o: mail_queue.h
+defer.o: ../include/vstream.h
+defer.o: mail_proto.h
+defer.o: ../include/iostuff.h
+defer.o: bounce.h
+defer.o: defer.h
+deliver_completed.o: deliver_completed.c
+deliver_completed.o: ../include/sys_defs.h
+deliver_completed.o: ../include/msg.h
+deliver_completed.o: ../include/vstream.h
+deliver_completed.o: ../include/vbuf.h
+deliver_completed.o: record.h
+deliver_completed.o: ../include/vstring.h
+deliver_completed.o: rec_type.h
+deliver_completed.o: deliver_completed.h
+deliver_flock.o: deliver_flock.c
+deliver_flock.o: ../include/sys_defs.h
+deliver_flock.o: ../include/vstring.h
+deliver_flock.o: ../include/vbuf.h
+deliver_flock.o: ../include/myflock.h
+deliver_flock.o: mail_params.h
+deliver_flock.o: deliver_flock.h
+deliver_request.o: deliver_request.c
+deliver_request.o: ../include/sys_defs.h
+deliver_request.o: ../include/msg.h
+deliver_request.o: ../include/vstream.h
+deliver_request.o: ../include/vbuf.h
+deliver_request.o: ../include/vstring.h
+deliver_request.o: ../include/mymalloc.h
+deliver_request.o: ../include/iostuff.h
+deliver_request.o: mail_queue.h
+deliver_request.o: mail_proto.h
+deliver_request.o: mail_open_ok.h
+deliver_request.o: recipient_list.h
+deliver_request.o: deliver_request.h
+domain_list.o: domain_list.c
+domain_list.o: ../include/sys_defs.h
+domain_list.o: ../include/match_list.h
+domain_list.o: ../include/match_ops.h
+domain_list.o: domain_list.h
+dot_lockfile.o: dot_lockfile.c
+dot_lockfile.o: ../include/sys_defs.h
+dot_lockfile.o: ../include/vstring.h
+dot_lockfile.o: ../include/vbuf.h
+dot_lockfile.o: ../include/stringops.h
+dot_lockfile.o: ../include/mymalloc.h
+dot_lockfile.o: mail_params.h
+dot_lockfile.o: dot_lockfile.h
+file_id.o: file_id.c
+file_id.o: ../include/sys_defs.h
+file_id.o: ../include/msg.h
+file_id.o: ../include/vstring.h
+file_id.o: ../include/vbuf.h
+file_id.o: file_id.h
+header_opts.o: header_opts.c
+header_opts.o: ../include/sys_defs.h
+header_opts.o: ../include/msg.h
+header_opts.o: ../include/htable.h
+header_opts.o: ../include/vstring.h
+header_opts.o: ../include/vbuf.h
+header_opts.o: header_opts.h
+is_header.o: is_header.c
+is_header.o: ../include/sys_defs.h
+is_header.o: is_header.h
+mail_addr.o: mail_addr.c
+mail_addr.o: ../include/sys_defs.h
+mail_addr.o: ../include/stringops.h
+mail_addr.o: mail_params.h
+mail_addr.o: mail_addr.h
+mail_addr_crunch.o: mail_addr_crunch.c
+mail_addr_crunch.o: ../include/sys_defs.h
+mail_addr_crunch.o: ../include/mymalloc.h
+mail_addr_crunch.o: ../include/argv.h
+mail_addr_crunch.o: ../include/vstring.h
+mail_addr_crunch.o: ../include/vbuf.h
+mail_addr_crunch.o: tok822.h
+mail_addr_crunch.o: resolve_clnt.h
+mail_addr_crunch.o: canon_addr.h
+mail_addr_crunch.o: mail_addr_crunch.h
+mail_addr_find.o: mail_addr_find.c
+mail_addr_find.o: ../include/sys_defs.h
+mail_addr_find.o: ../include/msg.h
+mail_addr_find.o: ../include/dict.h
+mail_addr_find.o: ../include/vstream.h
+mail_addr_find.o: ../include/vbuf.h
+mail_addr_find.o: ../include/stringops.h
+mail_addr_find.o: ../include/mymalloc.h
+mail_addr_find.o: ../include/vstring.h
+mail_addr_find.o: mail_params.h
+mail_addr_find.o: split_addr.h
+mail_addr_find.o: mail_addr_find.h
+mail_addr_find.o: maps.h
+mail_addr_find.o: resolve_local.h
+mail_addr_map.o: mail_addr_map.c
+mail_addr_map.o: ../include/sys_defs.h
+mail_addr_map.o: ../include/msg.h
+mail_addr_map.o: ../include/vstring.h
+mail_addr_map.o: ../include/vbuf.h
+mail_addr_map.o: ../include/dict.h
+mail_addr_map.o: ../include/vstream.h
+mail_addr_map.o: ../include/argv.h
+mail_addr_map.o: ../include/mymalloc.h
+mail_addr_map.o: mail_addr_find.h
+mail_addr_map.o: maps.h
+mail_addr_map.o: mail_addr_crunch.h
+mail_addr_map.o: mail_addr_map.h
+mail_command_read.o: mail_command_read.c
+mail_command_read.o: ../include/sys_defs.h
+mail_command_read.o: ../include/vstring.h
+mail_command_read.o: ../include/vbuf.h
+mail_command_read.o: ../include/vstream.h
+mail_command_read.o: mail_proto.h
+mail_command_read.o: ../include/iostuff.h
+mail_command_write.o: mail_command_write.c
+mail_command_write.o: ../include/sys_defs.h
+mail_command_write.o: ../include/vstream.h
+mail_command_write.o: ../include/vbuf.h
+mail_command_write.o: mail_proto.h
+mail_command_write.o: ../include/iostuff.h
+mail_connect.o: mail_connect.c
+mail_connect.o: ../include/sys_defs.h
+mail_connect.o: ../include/msg.h
+mail_connect.o: ../include/vstream.h
+mail_connect.o: ../include/vbuf.h
+mail_connect.o: ../include/connect.h
+mail_connect.o: ../include/iostuff.h
+mail_connect.o: ../include/mymalloc.h
+mail_connect.o: timed_ipc.h
+mail_connect.o: mail_proto.h
+mail_copy.o: mail_copy.c
+mail_copy.o: ../include/sys_defs.h
+mail_copy.o: ../include/msg.h
+mail_copy.o: ../include/htable.h
+mail_copy.o: ../include/vstream.h
+mail_copy.o: ../include/vbuf.h
+mail_copy.o: ../include/vstring.h
+mail_copy.o: ../include/vstring_vstream.h
+mail_copy.o: ../include/stringops.h
+mail_copy.o: quote_822_local.h
+mail_copy.o: record.h
+mail_copy.o: rec_type.h
+mail_copy.o: mail_queue.h
+mail_copy.o: mail_addr.h
+mail_copy.o: mail_copy.h
+mail_copy.o: mark_corrupt.h
+mail_date.o: mail_date.c
+mail_date.o: ../include/sys_defs.h
+mail_date.o: ../include/msg.h
+mail_date.o: ../include/vstring.h
+mail_date.o: ../include/vbuf.h
+mail_date.o: mail_date.h
+mail_error.o: mail_error.c
+mail_error.o: ../include/sys_defs.h
+mail_error.o: mail_error.h
+mail_error.o: ../include/name_mask.h
+mail_flush.o: mail_flush.c
+mail_flush.o: ../include/sys_defs.h
+mail_flush.o: mail_proto.h
+mail_flush.o: ../include/vstream.h
+mail_flush.o: ../include/vbuf.h
+mail_flush.o: ../include/iostuff.h
+mail_flush.o: mail_flush.h
+mail_open_ok.o: mail_open_ok.c
+mail_open_ok.o: ../include/sys_defs.h
+mail_open_ok.o: ../include/msg.h
+mail_open_ok.o: mail_queue.h
+mail_open_ok.o: ../include/vstring.h
+mail_open_ok.o: ../include/vbuf.h
+mail_open_ok.o: ../include/vstream.h
+mail_open_ok.o: mail_open_ok.h
+mail_params.o: mail_params.c
+mail_params.o: ../include/sys_defs.h
+mail_params.o: ../include/msg.h
+mail_params.o: ../include/get_hostname.h
+mail_params.o: ../include/valid_hostname.h
+mail_params.o: mynetworks.h
+mail_params.o: config.h
+mail_params.o: mail_version.h
+mail_params.o: mail_params.h
+mail_pathname.o: mail_pathname.c
+mail_pathname.o: ../include/sys_defs.h
+mail_pathname.o: ../include/stringops.h
+mail_pathname.o: mail_proto.h
+mail_pathname.o: ../include/vstream.h
+mail_pathname.o: ../include/vbuf.h
+mail_pathname.o: ../include/iostuff.h
+mail_print.o: mail_print.c
+mail_print.o: ../include/sys_defs.h
+mail_print.o: ../include/msg.h
+mail_print.o: ../include/mymalloc.h
+mail_print.o: ../include/vstream.h
+mail_print.o: ../include/vbuf.h
+mail_print.o: mail_proto.h
+mail_print.o: ../include/iostuff.h
+mail_queue.o: mail_queue.c
+mail_queue.o: ../include/sys_defs.h
+mail_queue.o: ../include/msg.h
+mail_queue.o: ../include/vstring.h
+mail_queue.o: ../include/vbuf.h
+mail_queue.o: ../include/vstream.h
+mail_queue.o: ../include/mymalloc.h
+mail_queue.o: ../include/argv.h
+mail_queue.o: ../include/dir_forest.h
+mail_queue.o: ../include/make_dirs.h
+mail_queue.o: ../include/split_at.h
+mail_queue.o: file_id.h
+mail_queue.o: mail_params.h
+mail_queue.o: mail_queue.h
+mail_run.o: mail_run.c
+mail_run.o: ../include/sys_defs.h
+mail_run.o: ../include/msg.h
+mail_run.o: ../include/stringops.h
+mail_run.o: ../include/mymalloc.h
+mail_run.o: mail_params.h
+mail_run.o: mail_run.h
+mail_scan.o: mail_scan.c
+mail_scan.o: ../include/sys_defs.h
+mail_scan.o: ../include/msg.h
+mail_scan.o: ../include/vstring.h
+mail_scan.o: ../include/vbuf.h
+mail_scan.o: ../include/vstream.h
+mail_scan.o: ../include/vstring_vstream.h
+mail_scan.o: ../include/mymalloc.h
+mail_scan.o: mail_proto.h
+mail_scan.o: ../include/iostuff.h
+mail_stream.o: mail_stream.c
+mail_stream.o: ../include/sys_defs.h
+mail_stream.o: ../include/msg.h
+mail_stream.o: ../include/mymalloc.h
+mail_stream.o: ../include/vstring.h
+mail_stream.o: ../include/vbuf.h
+mail_stream.o: ../include/vstream.h
+mail_stream.o: ../include/stringops.h
+mail_stream.o: cleanup_user.h
+mail_stream.o: mail_proto.h
+mail_stream.o: ../include/iostuff.h
+mail_stream.o: mail_queue.h
+mail_stream.o: opened.h
+mail_stream.o: mail_stream.h
+mail_task.o: mail_task.c
+mail_task.o: ../include/sys_defs.h
+mail_task.o: ../include/vstring.h
+mail_task.o: ../include/vbuf.h
+mail_task.o: mail_params.h
+mail_task.o: mail_task.h
+mail_trigger.o: mail_trigger.c
+mail_trigger.o: ../include/sys_defs.h
+mail_trigger.o: ../include/msg.h
+mail_trigger.o: ../include/mymalloc.h
+mail_trigger.o: ../include/iostuff.h
+mail_trigger.o: ../include/trigger.h
+mail_trigger.o: mail_params.h
+mail_trigger.o: mail_proto.h
+mail_trigger.o: ../include/vstream.h
+mail_trigger.o: ../include/vbuf.h
+maps.o: maps.c
+maps.o: ../include/sys_defs.h
+maps.o: ../include/argv.h
+maps.o: ../include/mymalloc.h
+maps.o: ../include/msg.h
+maps.o: ../include/dict.h
+maps.o: ../include/vstream.h
+maps.o: ../include/vbuf.h
+maps.o: ../include/stringops.h
+maps.o: ../include/split_at.h
+maps.o: config.h
+maps.o: maps.h
+mark_corrupt.o: mark_corrupt.c
+mark_corrupt.o: ../include/sys_defs.h
+mark_corrupt.o: ../include/msg.h
+mark_corrupt.o: ../include/vstream.h
+mark_corrupt.o: ../include/vbuf.h
+mark_corrupt.o: mail_queue.h
+mark_corrupt.o: ../include/vstring.h
+mark_corrupt.o: mark_corrupt.h
+mkmap_db.o: mkmap_db.c
+mkmap_db.o: ../include/sys_defs.h
+mkmap_db.o: ../include/msg.h
+mkmap_db.o: ../include/mymalloc.h
+mkmap_db.o: ../include/stringops.h
+mkmap_db.o: ../include/dict.h
+mkmap_db.o: ../include/vstream.h
+mkmap_db.o: ../include/vbuf.h
+mkmap_db.o: ../include/dict_db.h
+mkmap_db.o: mkmap.h
+mkmap_dbm.o: mkmap_dbm.c
+mkmap_dbm.o: ../include/sys_defs.h
+mkmap_dbm.o: ../include/msg.h
+mkmap_dbm.o: ../include/mymalloc.h
+mkmap_dbm.o: ../include/stringops.h
+mkmap_dbm.o: ../include/dict.h
+mkmap_dbm.o: ../include/vstream.h
+mkmap_dbm.o: ../include/vbuf.h
+mkmap_dbm.o: ../include/dict_dbm.h
+mkmap_dbm.o: mkmap.h
+mkmap_open.o: mkmap_open.c
+mkmap_open.o: ../include/sys_defs.h
+mkmap_open.o: ../include/msg.h
+mkmap_open.o: ../include/dict.h
+mkmap_open.o: ../include/vstream.h
+mkmap_open.o: ../include/vbuf.h
+mkmap_open.o: ../include/sigdelay.h
+mkmap_open.o: ../include/mymalloc.h
+mkmap_open.o: ../include/myflock.h
+mkmap_open.o: mkmap.h
+mynetworks.o: mynetworks.c
+mynetworks.o: ../include/sys_defs.h
+mynetworks.o: ../include/msg.h
+mynetworks.o: ../include/vstring.h
+mynetworks.o: ../include/vbuf.h
+mynetworks.o: ../include/inet_addr_list.h
+mynetworks.o: own_inet_addr.h
+mynetworks.o: mynetworks.h
+mypwd.o: mypwd.c
+mypwd.o: ../include/sys_defs.h
+mypwd.o: ../include/mymalloc.h
+mypwd.o: ../include/htable.h
+mypwd.o: ../include/binhash.h
+mypwd.o: ../include/msg.h
+mypwd.o: mypwd.h
+namadr_list.o: namadr_list.c
+namadr_list.o: ../include/sys_defs.h
+namadr_list.o: ../include/match_list.h
+namadr_list.o: ../include/match_ops.h
+namadr_list.o: namadr_list.h
+off_cvt.o: off_cvt.c
+off_cvt.o: ../include/sys_defs.h
+off_cvt.o: ../include/msg.h
+off_cvt.o: ../include/vstring.h
+off_cvt.o: ../include/vbuf.h
+off_cvt.o: off_cvt.h
+opened.o: opened.c
+opened.o: ../include/sys_defs.h
+opened.o: ../include/msg.h
+opened.o: ../include/vstring.h
+opened.o: ../include/vbuf.h
+opened.o: opened.h
+own_inet_addr.o: own_inet_addr.c
+own_inet_addr.o: ../include/sys_defs.h
+own_inet_addr.o: ../include/msg.h
+own_inet_addr.o: ../include/mymalloc.h
+own_inet_addr.o: ../include/inet_addr_list.h
+own_inet_addr.o: ../include/inet_addr_local.h
+own_inet_addr.o: ../include/inet_addr_host.h
+own_inet_addr.o: ../include/stringops.h
+own_inet_addr.o: mail_params.h
+own_inet_addr.o: own_inet_addr.h
+pipe_command.o: pipe_command.c
+pipe_command.o: ../include/sys_defs.h
+pipe_command.o: ../include/msg.h
+pipe_command.o: ../include/vstream.h
+pipe_command.o: ../include/vbuf.h
+pipe_command.o: ../include/vstring.h
+pipe_command.o: ../include/stringops.h
+pipe_command.o: ../include/iostuff.h
+pipe_command.o: ../include/timed_wait.h
+pipe_command.o: ../include/set_ugid.h
+pipe_command.o: ../include/argv.h
+pipe_command.o: mail_params.h
+pipe_command.o: mail_copy.h
+pipe_command.o: clean_env.h
+pipe_command.o: pipe_command.h
+pipe_command.o: ../include/exec_command.h
+pipe_command.o: sys_exits.h
+post_mail.o: post_mail.c
+post_mail.o: ../include/sys_defs.h
+post_mail.o: ../include/msg.h
+post_mail.o: ../include/vstream.h
+post_mail.o: ../include/vbuf.h
+post_mail.o: ../include/vstring.h
+post_mail.o: mail_params.h
+post_mail.o: record.h
+post_mail.o: rec_type.h
+post_mail.o: mail_proto.h
+post_mail.o: ../include/iostuff.h
+post_mail.o: cleanup_user.h
+post_mail.o: post_mail.h
+post_mail.o: mail_date.h
+quote_822_local.o: quote_822_local.c
+quote_822_local.o: ../include/sys_defs.h
+quote_822_local.o: ../include/vstring.h
+quote_822_local.o: ../include/vbuf.h
+quote_822_local.o: quote_822_local.h
+rec2stream.o: rec2stream.c
+rec2stream.o: ../include/sys_defs.h
+rec2stream.o: ../include/vstring.h
+rec2stream.o: ../include/vbuf.h
+rec2stream.o: ../include/vstream.h
+rec2stream.o: record.h
+rec2stream.o: rec_streamlf.h
+rec2stream.o: rec_type.h
+rec_streamlf.o: rec_streamlf.c
+rec_streamlf.o: ../include/sys_defs.h
+rec_streamlf.o: ../include/vstring.h
+rec_streamlf.o: ../include/vbuf.h
+rec_streamlf.o: ../include/vstream.h
+rec_streamlf.o: record.h
+rec_streamlf.o: rec_type.h
+rec_streamlf.o: rec_streamlf.h
+rec_type.o: rec_type.c
+rec_type.o: rec_type.h
+recdump.o: recdump.c
+recdump.o: ../include/sys_defs.h
+recdump.o: ../include/msg_vstream.h
+recdump.o: ../include/vstream.h
+recdump.o: ../include/vbuf.h
+recdump.o: record.h
+recdump.o: ../include/vstring.h
+recdump.o: rec_streamlf.h
+recdump.o: rec_type.h
+recipient_list.o: recipient_list.c
+recipient_list.o: ../include/mymalloc.h
+recipient_list.o: recipient_list.h
+record.o: record.c
+record.o: ../include/sys_defs.h
+record.o: ../include/msg.h
+record.o: ../include/mymalloc.h
+record.o: ../include/vstream.h
+record.o: ../include/vbuf.h
+record.o: ../include/vstring.h
+record.o: record.h
+remove.o: remove.c
+remove.o: ../include/sys_defs.h
+remove.o: ../include/vstring.h
+remove.o: ../include/vbuf.h
+remove.o: mail_params.h
+resolve_clnt.o: resolve_clnt.c
+resolve_clnt.o: ../include/sys_defs.h
+resolve_clnt.o: ../include/msg.h
+resolve_clnt.o: ../include/vstream.h
+resolve_clnt.o: ../include/vbuf.h
+resolve_clnt.o: ../include/vstring.h
+resolve_clnt.o: ../include/vstring_vstream.h
+resolve_clnt.o: ../include/events.h
+resolve_clnt.o: ../include/iostuff.h
+resolve_clnt.o: mail_proto.h
+resolve_clnt.o: mail_params.h
+resolve_clnt.o: resolve_clnt.h
+resolve_local.o: resolve_local.c
+resolve_local.o: ../include/sys_defs.h
+resolve_local.o: ../include/msg.h
+resolve_local.o: ../include/mymalloc.h
+resolve_local.o: string_list.h
+resolve_local.o: mail_params.h
+resolve_local.o: own_inet_addr.h
+resolve_local.o: resolve_local.h
+rewrite_clnt.o: rewrite_clnt.c
+rewrite_clnt.o: ../include/sys_defs.h
+rewrite_clnt.o: ../include/msg.h
+rewrite_clnt.o: ../include/vstring.h
+rewrite_clnt.o: ../include/vbuf.h
+rewrite_clnt.o: ../include/vstream.h
+rewrite_clnt.o: ../include/vstring_vstream.h
+rewrite_clnt.o: ../include/events.h
+rewrite_clnt.o: ../include/iostuff.h
+rewrite_clnt.o: quote_822_local.h
+rewrite_clnt.o: mail_proto.h
+rewrite_clnt.o: mail_params.h
+rewrite_clnt.o: rewrite_clnt.h
+sent.o: sent.c
+sent.o: ../include/sys_defs.h
+sent.o: ../include/msg.h
+sent.o: ../include/vstring.h
+sent.o: ../include/vbuf.h
+sent.o: sent.h
+smtp_stream.o: smtp_stream.c
+smtp_stream.o: ../include/sys_defs.h
+smtp_stream.o: ../include/vstring.h
+smtp_stream.o: ../include/vbuf.h
+smtp_stream.o: ../include/vstream.h
+smtp_stream.o: ../include/vstring_vstream.h
+smtp_stream.o: ../include/msg.h
+smtp_stream.o: ../include/iostuff.h
+smtp_stream.o: smtp_stream.h
+split_addr.o: split_addr.c
+split_addr.o: ../include/sys_defs.h
+split_addr.o: ../include/split_at.h
+split_addr.o: mail_params.h
+split_addr.o: mail_addr.h
+split_addr.o: split_addr.h
+stream2rec.o: stream2rec.c
+stream2rec.o: ../include/sys_defs.h
+stream2rec.o: ../include/vstream.h
+stream2rec.o: ../include/vbuf.h
+stream2rec.o: ../include/vstring.h
+stream2rec.o: record.h
+stream2rec.o: rec_streamlf.h
+stream2rec.o: rec_type.h
+string_list.o: string_list.c
+string_list.o: ../include/sys_defs.h
+string_list.o: ../include/match_list.h
+string_list.o: ../include/match_ops.h
+string_list.o: string_list.h
+sys_exits.o: sys_exits.c
+sys_exits.o: ../include/sys_defs.h
+sys_exits.o: ../include/msg.h
+sys_exits.o: sys_exits.h
+timed_ipc.o: timed_ipc.c
+timed_ipc.o: ../include/sys_defs.h
+timed_ipc.o: ../include/msg.h
+timed_ipc.o: ../include/vstream.h
+timed_ipc.o: ../include/vbuf.h
+timed_ipc.o: ../include/iostuff.h
+timed_ipc.o: mail_params.h
+timed_ipc.o: timed_ipc.h
+tok822_find.o: tok822_find.c
+tok822_find.o: ../include/sys_defs.h
+tok822_find.o: ../include/vstring.h
+tok822_find.o: ../include/vbuf.h
+tok822_find.o: tok822.h
+tok822_find.o: resolve_clnt.h
+tok822_node.o: tok822_node.c
+tok822_node.o: ../include/sys_defs.h
+tok822_node.o: ../include/mymalloc.h
+tok822_node.o: ../include/vstring.h
+tok822_node.o: ../include/vbuf.h
+tok822_node.o: tok822.h
+tok822_node.o: resolve_clnt.h
+tok822_parse.o: tok822_parse.c
+tok822_parse.o: ../include/sys_defs.h
+tok822_parse.o: ../include/vstring.h
+tok822_parse.o: ../include/vbuf.h
+tok822_parse.o: ../include/msg.h
+tok822_parse.o: tok822.h
+tok822_parse.o: resolve_clnt.h
+tok822_resolve.o: tok822_resolve.c
+tok822_resolve.o: ../include/sys_defs.h
+tok822_resolve.o: ../include/vstring.h
+tok822_resolve.o: ../include/vbuf.h
+tok822_resolve.o: ../include/msg.h
+tok822_resolve.o: resolve_clnt.h
+tok822_resolve.o: tok822.h
+tok822_rewrite.o: tok822_rewrite.c
+tok822_rewrite.o: ../include/sys_defs.h
+tok822_rewrite.o: ../include/vstring.h
+tok822_rewrite.o: ../include/vbuf.h
+tok822_rewrite.o: ../include/msg.h
+tok822_rewrite.o: rewrite_clnt.h
+tok822_rewrite.o: tok822.h
+tok822_rewrite.o: resolve_clnt.h
+tok822_tree.o: tok822_tree.c
+tok822_tree.o: ../include/sys_defs.h
+tok822_tree.o: ../include/mymalloc.h
+tok822_tree.o: ../include/vstring.h
+tok822_tree.o: ../include/vbuf.h
+tok822_tree.o: tok822.h
+tok822_tree.o: resolve_clnt.h
diff --git a/postfix/global/been_here.c b/postfix/global/been_here.c
new file mode 100644
index 000000000..572c78ebc
--- /dev/null
+++ b/postfix/global/been_here.c
@@ -0,0 +1,175 @@
+/*++
+/* NAME
+/* been_here 3
+/* SUMMARY
+/* detect repeated occurrence of string
+/* SYNOPSIS
+/* #include