-TEXPAND_ATTR
-TFILE
-TFORWARD_INFO
--TFW_CONTEXT
-THEADER_OPTS
-THTABLE
-THTABLE_INFO
-TINET_ADDR_LIST
-TINT_TABLE
-TLOCAL_STATE
+-TMAC_EXP_CONTEXT
-TMAC_HEAD
-TMAC_PARSE
-TMAIL_PRINT
Cleanup: "disable_dns_lookups = yes" now should disable
all DNS lookups by the SMTP client.
+19990428
+
+ Bugfix: with DBM files, Postfix was watching the "dir" file
+ modification time for changes. It should be watching the
+ "pag" file instead.
+
+19990429
+
+ Cleanup: all callbacks in the master to server API now pass
+ on the service name and the application-specific argument
+ vector. Files: master/*server.c.
+
+19990504
+
+ Feature: conditional macro expansion. ${name?text} expands
+ to text when name is defined, otherwise the result is empty.
+ ${name:text} expands to text when name is undefined,
+ otherwise the result is empty. File: util/mac_expand.c.
+
+ Feature: conditional macro expansion in forward_path and
+ mailbox_command of $user, $home, $shell, $recipient,
+ $extension, $domain, and $recipient_delimiter. Files:
+ local/command.c, local/dotforward.c, local/local_expand.c.
-Purpose of this document
-========================
+1 - 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:
- Replace sendmail altogether.
-Typographical conventions
-=========================
+2 - Typographical conventions
+=============================
In the instructions below, a command written as
should be executed as an unprivileged user.
-Documentation
-=============
+3 - Documentation
+=================
Documentation is available as HTML web pages (point your browser
to html/index.html) and as UNIX-style manpages (point your MANPATH
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/
+those embedded manual pages are available in the mantools directory.
-Building on a supported system
-==============================
+4 - Building on a supported system
+==================================
If your system is supported, it is one of
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.
+need a bit of work because their shell is a bit brain damaged.
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
produces compiler error messages, it may be time to examine the
FAQ document.
-Porting to on an unsupported system
-===================================
+5 - 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
next port you'd have to place #ifdefs all over the source code
again.
-Installing the software after successful compilation
-====================================================
+6 - Installing the software after successful compilation
+========================================================
There is no automated installation procedure. The Postfix system
is sufficiently complex, and UNIX systems are sufficiently different,
variable. This text assumes that you have chosen the default
location.
- As superuser, execute the commands:
+ As superuser, execute the commands from the Postfix source directory:
# mkdir /etc/postfix
# chmod 755 /etc/postfix
- # cp /some/where/postfix/conf/* /etc/postfix
+ # cp conf/* /etc/postfix
# chmod 644 /etc/postfix/*
# chmod 755 /etc/postfix/postfix-script*
# 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.
+- Command directory. The pathname is configurable in /etc/postfix/main.cf.
+ Usually I install in /usr/sbin or in /usr/etc, depending on the system.
- As superuser, execute the commands:
+ If you are replacing an existing sendmail installation with
+ Postfix, you need to keep the old sendmail program running for
+ some time in order to flush the mail queue. As superuser, execute
+ the following commands (your sendmail may be in a different place):
+
+ # mv /usr/sbin/sendmail /usr/sbin/sendmail.OFF
+ # chmod 755 /usr/sbin/sendmail.OFF
+
+ As superuser, execute the commands from the Postfix source directory:
+
+ # mkdir $command_directory
+ # cp bin/* $command_directory
+
+ Alternative: leave the command executables in the Postfix source tree.
- # mkdir /some/where/bin
- # cp bin/* /some/where/bin
+- Daemon directory. The pathname is configurable in /etc/postfix/main.cf.
+ Usually I install in /usr/libexec/postfix or in /usr/lib/postfix.
- Alternative 1: leave the programs in the Postfix source tree.
+ As superuser, execute the commands from the Postfix source directory:
- Alternative 2: use separate program and daemon directories (again,
- configurable in /etc/postfix/main.cf):
+ # mkdir $daemon_directory
+ # cp libexec/* $daemon_directory
- # 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
+ Alternative: leave the daemon executables in the Postfix source tree.
- On-line manual pages:
# 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:
+- Proceed to the section on how you wish to run Postfix on your
+ particular machine:
- Send mail only, without changing an existing sendmail
- installation.
+ installation (section 7).
- Send and receive mail via a virtual host interface, still
- without any change to an existing sendmail installation.
+ without any change to an existing sendmail installation
+ (section 8).
- - Replace sendmail altogether.
+ - Replace sendmail altogether (section 9).
-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
-=====================================
+7 - 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.
+to change your existing 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.
+in section 10, review the "To chroot or not to chroot" text in
+section 11, and choose a security model according to section 12.
-You must comment out the smtp inet service in /etc/postfix/master.cf,
-in order to avoid conflicts with the sendmail daemon.
+You MUST comment out the `smtp inet' entry in /etc/postfix/master.cf,
+in order to avoid conflicts with the real sendmail.
Start the Postfix system:
# postfix start
-or, if you feel nostalgic,
+or, if you feel nostalgic, use the Postfix sendmail command:
- # /some/where/bin/sendmail -bd -qwhatever
+ # sendmail -bd -qwhatever
and watch your syslog file for any error messages.
In order to inspect the mail queue, use
- % /some/where/bin/sendmail -bp
+ % sendmail -bp
-See also the "Care and feeding" section below.
+See also the "Care and feeding" section 13 below.
-Configuring Postfix to send and receive mail (virtual interface)
-================================================================
+8 - 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.
+The examples/virtual-setup directory gives instructions for setting
+up virtual interfaces for a variety of UNIX versions.
In the /etc/postfix/main.cf file, I would specify
inet_interfaces = $myhostname
mydestination = $myhostname
-You still have to do the "Mandatory configuration file edits"
-described below. After those edits, start the mail system:
+Follow the instructions in the "Mandatory configuration file edits"
+in section 10, review the "To chroot or not to chroot" text in
+section 11, and choose a security model according to section 12.
+
+Start the mail system:
- # /some/where/bin/postfix start
+ # postfix start
-or, if you feel nostalgic,
+or, if you feel nostalgic, use the Postfix sendmail program:
- # /some/where/bin/sendmail -bd -qwhatever
+ # sendmail -bd -qwhatever
and watch your syslog file for any error messages.
In order to inspect the mail queue, use
- % /some/where/bin/sendmail -bp
+ % sendmail -bp
-See also the "Care and feeding" section below.
+See also the "Care and feeding" section 13 below.
-Turning off sendmail forever
-============================
+9 - 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.
+following commands. The text assumes that on your system, 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:
+ # chmod 755 /usr/bin/newaliases.OFF /usr/bin/mailq.OFF
- # 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.
+days to flush any unsent mail. To do so, stop the sendmail daemon
+and restart it as:
+
+ # /usr/sbin/sendmail.OFF -q
After you have visited the "Mandatory configuration file edits"
section below, you can start the Postfix system with
will create a bunch of subdirectories below the Postfix spool
directory.
-See also the "Care and feeding" section below.
+See also the "Care and feeding" section 13 below.
-Mandatory configuration file edits
-==================================
+10 - Mandatory configuration file edits
+=======================================
-By default, all Postfix configuration files are in /etc/postfix, and
-must be owned by root.
+By default, Postfix configuration files are in /etc/postfix, and
+must be owned by root. Giving someone else write permission to
+main.cf or master.cf means giving root privileges to that person.
Whenever you make a change to a config file, execute the following
command in order to refresh a running mail system:
parameter = value
-and you use it by putting a $ in front of it:
+and you use it by putting a $ in front of its name:
other_parameter = $parameter
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,
+queue and most Postfix 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.
+group as other accounts. Preferably, this is an account that no-one
+can log into. The account does not need an executable login shell,
+and needs no existing home directory. My password file entry looks
+like this:
-Secondly, you should specify what domain name will be appended to
-a local address. The "myorigin" parameter defaults to the local
+ postfix:*:12345:12345:postfix:/no/where:/no/shell
+
+Secondly, you must specify what domain 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:
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.
+Next you need to specify what mail addresses are local to the
+Postfix system.
Some examples:
relayhost = $mydomain
relayhost = mail.$mydomain
+ relayhost = [mail.$mydomain]
+
+The form enclosed with [] eliminates DNS MX lookups.
+
+By default, the SMTP client will do DNS lookups for sender and
+recipient addresses even when you specify a relay host. If your
+machine has no access to a DNS server, turn off SMTP client DNS
+lookups like this:
+
+ disable_dns_lookups = yes
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.
+Finally, specify the program, daemon and queue directories. For
+example,
- program_directory = /some/where/bin
+ command_directory = /usr/sbin
+ daemon_directory = /usr/libexec/postfix
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
-======================================================
+11 - 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 examples/chroot-setup directory has a collection of scripts
+for setting up chroot environments for Postfix systems.
+
+12 - Security: writable versus protected maildrop directory
+===========================================================
Postfix offers a choice of submission mechanims.
# cp postfix-script-sgid postfix-script
-Care and feeding of the Postfix system
-======================================
+13 - Care and feeding of the Postfix system
+===========================================
+
+The Postfix programs log all problems to the syslog daemon. The
+names of logfiles are specified in /etc/syslog.conf. Note: the
+syslogd will not create files. You must create them ahead of time
+before (re)starting syslogd. At the very least you need something
+like:
+
+ mail.err /dev/console
+ mail.debug /var/log/maillog
-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:
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
+ -rm -f *core */*core .nfs* .pure bin/* lib/* include/* libexec/* \
+ */.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
-Incompatible changes with snapshot-19990427:
+Incompatible changes with snapshot-19990504:
===========================================
-- If an address extension (+foo) matches a user's .forward+foo file
-name, the +foo extension is no longer appended to recipient addresses
-listed in the .forward+foo file. This is more consistent with the
-way Postfix expands aliases.
+- File system reorganization: daemon executables are in the libexec
+subdirectory, command executables in the bin subdirectory. The
+INSTALL instructions now install daemons and commands into separate
+directories.
-Major changes with snapshot-19990427:
+- The local delivery agent no longer appends address extensions to
+addresses found in aliases, :include: files or .forward files.
+
+Major changes with snapshot-19990504:
=====================================
In addition to several little bugfixes, none related to security,
lots of internal code cleanup, lots of new functionality, and lots
of Solaris workarounds.
+- Specify "forward_path = /var/forward/$user" to avoid looking up
+.forward files in user home directories. The default value is
+$home/.forward$recipient_delimiter$extension,$home/.forward. Initial
+forward_path code by Philip A. Prindeville, Mirapoint, Inc., USA.
+
+- Conditional macro expansion in forward_path and mailbox_command.
+$name expands to itself. ${name?value} expands to value when $name
+is defined. ${name:value} expands to value when $name is not
+defined. With ${name?value} and ${name:value}, the value is subject
+to $name expansion. Available macros are: $user, $shell, $home,
+$recipient, $extension, $domain, and $recipient_delimiter.
+
- POSIX regular expression support, enabled by default on 4.4BSD,
-LINUX, and HP-UX. See conf/sample-regexp.cf. Initial code by Lamont
-Jones, Hewlett-Packard, borrowing heavily from the PCRE implementation
-by Andrew McNamara, connect.com.au Pty. Ltd., Australia.
+LINUX, HP-UX, and Solaris 2.5 and later. See conf/sample-regexp.cf.
+Initial code by Lamont Jones, Hewlett-Packard, borrowing heavily
+from the PCRE implementation by Andrew McNamara, connect.com.au
+Pty. Ltd., Australia.
- Regular expression checks for message headers. This requires
support for POSIX or for PCRE regular expressions. Specify
the SMTP access table, or to the canonical, virtual, transport or
aliases tables.
-- forward_path configuration parameter for .forward files (default:
-$home/.forward$recipient_delimiter$extension,$home/.forward).
-Macros: $user (login name), $home (home directory), $recipient_delimiter,
-$domain (recipient domain), and $extension (address extension).
-Initial code by Philip A. Prindeville, Mirapoint, Inc., USA.
+- New error mailer. Specify ".domain.name error:domain is undeliverable"
+in the transport table to bounce entire domains.
- No more Postfix lockups on Solaris (knock on wood). The code no
longer uses Solaris UNIX-domain sockets, because they are still
- MIME-encapsulated bounce messages, making it easier to recover
bounced mail. Initial implementation by Philip A. Prindeville,
-Mirapoint, Inc., USA. Support for RFC 1894 (DSN) will have to wait
-until Postfix internals have been revised to support RFC 1893.
+Mirapoint, Inc., USA. Support for RFC 1892 (multipart/report) and
+RFC 1894 (DSN) will have to wait until Postfix internals have been
+revised to support RFC 1893.
- Separately configurable "postmaster" addresses for single bounces
(bounce_notice_recipient), double bounces (2bounce_notice_recipient),
-TEXPAND_ATTR
-TFILE
-TFORWARD_INFO
--TFW_CONTEXT
-THEADER_OPTS
-THTABLE
-THTABLE_INFO
-TINET_ADDR_LIST
-TINT_TABLE
-TLOCAL_STATE
+-TMAC_EXP_CONTEXT
-TMAC_HEAD
-TMAC_PARSE
-TMAIL_PRINT
test: $(TESTPROG)
-update: ../bin/$(PROG)
+update: ../libexec/$(PROG)
-../bin/$(PROG): $(PROG)
- cp $(PROG) ../bin
+../libexec/$(PROG): $(PROG)
+ cp $(PROG) ../libexec
printfck: $(OBJS) $(PROG)
rm -rf printfck
/* post_jail_init - initialize after entering chroot jail */
-static void post_jail_init(void)
+static void post_jail_init(char *unused_name, char **unused_argv)
{
/*
-TEXPAND_ATTR
-TFILE
-TFORWARD_INFO
--TFW_CONTEXT
-THEADER_OPTS
-THTABLE
-THTABLE_INFO
-TINET_ADDR_LIST
-TINT_TABLE
-TLOCAL_STATE
+-TMAC_EXP_CONTEXT
-TMAC_HEAD
-TMAC_PARSE
-TMAIL_PRINT
test: $(TESTPROG)
-update: ../bin/$(PROG)
+update: ../libexec/$(PROG)
-../bin/$(PROG): $(PROG)
- cp $(PROG) ../bin
+../libexec/$(PROG): $(PROG)
+ cp $(PROG) ../libexec
printfck: $(OBJS) $(PROG)
rm -rf printfck
/* pre_jail_init - initialize before entering the chroot jail */
-static void pre_jail_init(void)
+static void pre_jail_init(char *unused_name, char **unused_argv)
{
if (*var_canonical_maps)
cleanup_comm_canon_maps =
/* pre_accept - see if tables have changed */
-static void pre_accept(void)
+static void pre_accept(char *unused_name, char **unused_argv)
{
if (dict_changed()) {
msg_info("table has changed -- exiting");
/* post_jail_init - initialize after entering the chroot jail */
-static void post_jail_init(void)
+static void post_jail_init(char *unused_name, char **unused_argv)
{
/*
+#
+# >>>>>>>>>> The program "newaliases" must be run after
+# >> NOTE >> this file is updated for any changes to
+# >>>>>>>>>> show through to sendmail.
+#
+
+# Basic system aliases -- these MUST be present
+MAILER-DAEMON: postmaster
+postmaster: root
+
+# General redirections for pseudo accounts
+bin: root
+daemon: root
+named: root
+nobody: root
+operator: root
+uucp: root
+www: root
+ftp-bugs: root
+
+# Put your local aliases here.
+
+# Well-known aliases -- these should be filled in!
+# root:
+# manager:
+# dumper:
+# operator:
+
#++
# NAME
# aliases 5
# command to use instead of mailbox delivery. The command is run as
# the recipient with proper HOME, SHELL and LOGNAME settings.
# Exception: delivery for root is done as $default_user.
+#
+# The following expansions are done on mailbox_command: $user (recipient
+# username), $shell (recipient shell), $home (recipient home directory),
+# $recipient (full recipient address), $extension (recipient address
+# extension), $domain (recipient domain), $recipient_delimiter. Specify
+# ${name?value} or ${name:value} to expand value only when $name does
+# (does not) exist.
#
# Avoid shell meta characters because they will force Postfix to run
# an expensive shell process. Procmail alone is expensive enough.
# 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.
+# The default is a list of all networks attached to the machine: a
+# complete class A network (X.0.0.0/8), a complete class B network
+# (X.X.0.0/16), 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
mail_name = Postfix
mail_owner = postfix
mail_spool_directory = /var/mail
-mail_version = Snapshot-19990427
+mail_version = Snapshot-19990504
mailbox_command =
mailbox_transport =
maps_rbl_domains = rbl.maps.vix.com
--- /dev/null
+#!/bin/sh
+
+echo Please read the SECURITY notes at the end of the INSTALL document 1>&2
#local_command_shell = /some/where/smrsh -c
# The forward_path parameter specifies a search list. The first file
-# that is found is used. In the path you can specify $user (login
-# name), $home (home directory), $recipient_delimiter, $domain
-# (recipient domain), and $extension (address extension).
+# that is found is used.
+#
+# The following expansions are done on forward_path: $user (recipient
+# username), $shell (recipient shell), $home (recipient home directory),
+# $recipient (full recipient address), $extension (recipient address
+# extension), $domain (recipient domain), $recipient_delimiter. Specify
+# ${name?value} or ${name:value} to expand value only when $name does
+# (does not) exist.
#
#forward_path = /var/forward/$user
forward_path = $home/.forward$recipient_delimiter$extension,$home/.forward
# as the recipient with proper HOME, SHELL and LOGNAME settings.
# Exception: delivery for root is done as $default_user.
#
+# The following expansions are done on mailbox_command: $user (recipient
+# username), $shell (recipient shell), $home (recipient home directory),
+# $recipient (full recipient address), $extension (recipient address
+# extension), $domain (recipient domain), $recipient_delimiter. Specify
+# ${name?value} or ${name:value} to expand value only when $name does
+# (does not) exist.
+#
# Avoid shell meta characters because they will force Postfix to run
# an expensive shell process. Procmail alone is expensive enough.
#
# 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.
+# 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 a list of all networks attached to the machine: a
+# complete class A network (X.0.0.0/8), a complete class B network
+# (X.X.0.0/16), 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
# smtpd_banner = $myhostname ESMTP $mail_name ($mail_version)
smtpd_banner = $myhostname ESMTP $mail_name
+# The smtpd_etrn_restrictions parameter restricts what clients are
+# allowed to issue the ETRN command. The present Postfix ETRN differs
+# from other ETRN implementations in that it flushes mail for all
+# destinations. This will change in the future.
+#
+# The default is to allow ETRN 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.
+# check_client_access maptype:mapname
+# 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.
+smtpd_etrn_restrictions =
+
# The smtpd_recipient_limit parameter restricts the number of recipients
# that the SMTP server accepts per message delivery.
#
-TEXPAND_ATTR
-TFILE
-TFORWARD_INFO
--TFW_CONTEXT
-THEADER_OPTS
-THTABLE
-THTABLE_INFO
-TINET_ADDR_LIST
-TINT_TABLE
-TLOCAL_STATE
+-TMAC_EXP_CONTEXT
-TMAC_HEAD
-TMAC_PARSE
-TMAIL_PRINT
-TEXPAND_ATTR
-TFILE
-TFORWARD_INFO
--TFW_CONTEXT
-THEADER_OPTS
-THTABLE
-THTABLE_INFO
-TINET_ADDR_LIST
-TINT_TABLE
-TLOCAL_STATE
+-TMAC_EXP_CONTEXT
-TMAC_HEAD
-TMAC_PARSE
-TMAIL_PRINT
--- /dev/null
+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
+post_mail_fprintf 1 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
test: $(TESTPROG)
-update: ../bin/$(PROG)
+update: ../libexec/$(PROG)
-../bin/$(PROG): $(PROG)
- cp $(PROG) ../bin
+../libexec/$(PROG): $(PROG)
+ cp $(PROG) ../libexec
printfck: $(OBJS) $(PROG)
rm -rf printfck
--- /dev/null
+In order to set up Postfix on a virtual interface address on my own
+BSD/OS or FreeBSD systems I would use:
+
+ # ifconfig interface-name alias virtual.host.addr netmask some.net.mask
+ # route add virtual.host.addr localhost
--- /dev/null
+In order to set up Postfix on a virtual interface address on my own
+BSD/OS or FreeBSD systems I would use:
+
+ # ifconfig interface-name alias virtual.host.addr netmask some.net.mask
+ # route add virtual.host.addr localhost
--- /dev/null
+On linux virtual interfaces can be set up with:
+ifconfig interface-name:alias-num virtual.host.addr
+route add virtual.host.addr dev interface-name:alias-num
-TEXPAND_ATTR
-TFILE
-TFORWARD_INFO
--TFW_CONTEXT
-THEADER_OPTS
-THTABLE
-THTABLE_INFO
-TINET_ADDR_LIST
-TINT_TABLE
-TLOCAL_STATE
+-TMAC_EXP_CONTEXT
-TMAC_HEAD
-TMAC_PARSE
-TMAIL_PRINT
test: $(TESTPROG)
-update: ../bin/fsstone
+update: ../libexec/fsstone
-../bin/fsstone: fsstone
+../libexec/fsstone: fsstone
cp $? $@
printfck: $(OBJS) $(PROG)
-TEXPAND_ATTR
-TFILE
-TFORWARD_INFO
--TFW_CONTEXT
-THEADER_OPTS
-THTABLE
-THTABLE_INFO
-TINET_ADDR_LIST
-TINT_TABLE
-TLOCAL_STATE
+-TMAC_EXP_CONTEXT
-TMAC_HEAD
-TMAC_PARSE
-TMAIL_PRINT
* Version of this program.
*/
#define VAR_MAIL_VERSION "mail_version"
-#define DEF_MAIL_VERSION "Snapshot-19990427"
+#define DEF_MAIL_VERSION "Snapshot-19990504"
extern char *var_mail_version;
/* LICENSE
# For now, just hard-coded rules for daemons, commands, config files.
-DAEMONS = bounce.8.html cleanup.8.html defer.8.html local.8.html \
+DAEMONS = bounce.8.html cleanup.8.html defer.8.html error.8.html local.8.html \
master.8.html pickup.8.html pipe.8.html qmgr.8.html showq.8.html \
smtp.8.html smtpd.8.html trivial-rewrite.8.html
COMMANDS= mailq.1.html newaliases.1.html postalias.1.html postcat.1.html \
rm -f $@
ln -s $? $@
+error.8.html: ../error/error.c
+ srctoman $? | nroff -man | man2html | postlink >$@
+
cleanup.8.html: ../cleanup/cleanup.c
srctoman $? | nroff -man | man2html | postlink >$@
--- /dev/null
+<html> <head> </head> <body> <pre>
+
+
+
+ERROR(8) ERROR(8)
+
+
+<b>NAME</b>
+ error - Postfix error mailer
+
+<b>SYNOPSIS</b>
+ <b>error</b> [generic Postfix daemon options]
+
+<b>DESCRIPTION</b>
+ The Postfix error mailer processes message delivery
+ requests from the queue manager. Each request specifies a
+ queue file, a sender address, a domain or host name that
+ is treated as the reason for non-delivery, and recipient
+ information. This program expects to be run from the <a href="master.8.html"><b>mas-</b>
+ <b>ter</b>(8)</a> process manager.
+
+ The error mailer client forces all recipients to bounce,
+ using the domain or host information as the reason for
+ non-delivery, updates the queue file and marks recipients
+ as finished, or it informs the queue manager that delivery
+ should be tried again at a later time.
+
+ Delivery problem reports are sent to the <a href="bounce.8.html"><b>bounce</b>(8)</a> or
+ <a href="defer.8.html"><b>defer</b>(8)</a> daemon as appropriate.
+
+<b>SECURITY</b>
+ The error mailer is not security-sensitive. It does not
+ talk to the network, and can be run chrooted at fixed low
+ privilege.
+
+<b>STANDARDS</b>
+ None.
+
+<b>DIAGNOSTICS</b>
+ Problems and transactions are logged to <b>syslogd</b>(8).
+
+ Depending on the setting of the <b>notify</b><i>_</i><b>classes</b> parameter,
+ the postmaster is notified of bounces and of other trou-
+ ble.
+
+<b>BUGS</b>
+<b>CONFIGURATION</b> <b>PARAMETERS</b>
+ The following <b>main.cf</b> parameters are especially relevant
+ to this program. See the Postfix <b>main.cf</b> file for syntax
+ details and for default values. Use the <b>postfix</b> <b>reload</b>
+ command after a configuration change.
+
+<b>Miscellaneous</b>
+ <b>bounce</b><i>_</i><b>notice</b><i>_</i><b>recipient</b>
+ Postmaster for bounce error notices.
+
+ <b>notify</b><i>_</i><b>classes</b>
+ When this parameter includes the <b>bounce</b> class, send
+ mail to the postmaster with with the headers of the
+ bounced mail.
+
+
+
+
+ 1
+
+
+
+
+
+ERROR(8) ERROR(8)
+
+
+<b>SEE</b> <b>ALSO</b>
+ <a href="bounce.8.html">bounce(8)</a> non-delivery status reports
+ <a href="master.8.html">master(8)</a> process manager
+ <a href="qmgr.8.html">qmgr(8)</a> queue manager
+ syslogd(8) system logging
+
+<b>LICENSE</b>
+ The Secure Mailer license must be distributed with this
+ software.
+
+<b>AUTHOR(S)</b>
+ Wietse Venema
+ IBM T.J. Watson Research
+ P.O. Box 704
+ Yorktown Heights, NY 10598, USA
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 2
+
+
+</pre> </body> </html>
mailbox owned by the user <i>name</i>, or it is sent back as
undeliverable.
- An alias or ~/.<b>forward</b> file may list any combination of
- external commands, destination file names, <b>:include:</b>
- directives, or mail addresses. See <a href="aliases.5.html"><b>aliases</b>(5)</a> for a pre-
- cise description. Each line in a user's .<b>forward</b> file has
+ The system administrator can specify a comma/space sepa-
+ rated list of ~/.<b>forward</b> like files through the <b>for-</b>
+ <b>ward</b><i>_</i><b>path</b> configuration parameter. Upon delivery, the
+ local delivery agent tries each pathname in the list until
+ a file is found. The <b>forward</b><i>_</i><b>path</b> parameter is subject to
+ interpolation of <b>$user</b> (recipient username), <b>$home</b> (recip-
+ ient home directory), <b>$shell</b> (recipient shell), <b>$recipient</b>
+ (complete recipient address), <b>$extension</b> (recipient
+ address extension), <b>$domain</b> (recipient domain) and <b>$recip-</b>
+ <b>ient</b><i>_</i><b>delimiter.</b> The forms <i>${name?value}</i> and <i>${name:value}</i>
+ expand conditionally to <i>value</i> when <i>$name</i> is (is not)
+ defined.
+
+ An alias or ~/.<b>forward</b> file may list any combination of
+ external commands, destination file names, <b>:include:</b>
+ directives, or mail addresses. See <a href="aliases.5.html"><b>aliases</b>(5)</a> for a pre-
+ cise description. Each line in a user's .<b>forward</b> file has
the same syntax as the right-hand part of an alias.
- When an address is found in its own alias expansion,
- delivery is made to the user instead. When a user is
+ When an address is found in its own alias expansion,
+ delivery is made to the user instead. When a user is
listed in the user's own ~/.<b>forward</b> file, delivery is made
- to the user's mailbox instead. An empty ~/.<b>forward</b> file
+ to the user's mailbox instead. An empty ~/.<b>forward</b> file
means do not forward mail.
- In order to prevent the mail system from using up unrea-
- sonable amounts of memory, input records read from
- <b>:include:</b> or from ~/.<b>forward</b> files are broken up into
- chunks of length <b>line</b><i>_</i><b>length</b><i>_</i><b>limit</b>.
-
- While expanding aliases, ~/.<b>forward</b> files, and so on, the
- program attempts to avoid duplicate deliveries. The <b>dupli-</b>
- <b>cate</b><i>_</i><b>filter</b><i>_</i><b>limit</b> configuration parameter limits the num-
- ber of remembered recipients.
-
-<b>MAIL</b> <b>FORWARDING</b>
- For the sake of reliability, forwarded mail is re-submit-
- ted as a new message, so that each recipient has a sepa-
- rate on-file delivery status record.
+ In order to prevent the mail system from using up
LOCAL(8) LOCAL(8)
+ unreasonable amounts of memory, input records read from
+ <b>:include:</b> or from ~/.<b>forward</b> files are broken up into
+ chunks of length <b>line</b><i>_</i><b>length</b><i>_</i><b>limit</b>.
+
+ While expanding aliases, ~/.<b>forward</b> files, and so on, the
+ program attempts to avoid duplicate deliveries. The <b>dupli-</b>
+ <b>cate</b><i>_</i><b>filter</b><i>_</i><b>limit</b> configuration parameter limits the num-
+ ber of remembered recipients.
+
+<b>MAIL</b> <b>FORWARDING</b>
+ For the sake of reliability, forwarded mail is re-submit-
+ ted as a new message, so that each recipient has a sepa-
+ rate on-file delivery status record.
+
In order to stop mail forwarding loops early, the software
- adds a <b>Delivered-To:</b> header with the envelope recipient
- address. If mail arrives for a recipient that is already
- listed in a <b>Delivered-To:</b> header, the message is bounced.
+ adds a <b>Delivered-To:</b> header with the envelope recipient
+ address. If mail arrives for a recipient that is already
+ listed in a <b>Delivered-To:</b> header, the message is bounced.
<b>MAILBOX</b> <b>DELIVERY</b>
- The default per-user mailbox is a file in the UNIX mail
- spool directory (<b>/var/mail/</b><i>user</i> or <b>/var/spool/mail/</b><i>user</i>);
- the location can be specified with the <b>mail</b><i>_</i><b>spool</b><i>_</i><b>direc-</b>
+ The default per-user mailbox is a file in the UNIX mail
+ spool directory (<b>/var/mail/</b><i>user</i> or <b>/var/spool/mail/</b><i>user</i>);
+ the location can be specified with the <b>mail</b><i>_</i><b>spool</b><i>_</i><b>direc-</b>
<b>tory</b> configuration parameter.
- Alternatively, the per-user mailbox can be a file in the
- user's home directory with a name specified via the
- <b>home</b><i>_</i><b>mailbox</b> configuration parameter. Specify a relative
+ Alternatively, the per-user mailbox can be a file in the
+ user's home directory with a name specified via the
+ <b>home</b><i>_</i><b>mailbox</b> configuration parameter. Specify a relative
path name. Specify a name ending in <b>/</b> for <b>qmail</b>-compatible
<b>maildir</b> delivery.
- Mailbox delivery can be delegated to an external command
- specified with the <b>mailbox</b><i>_</i><b>command</b> configuration parame-
- ter. The command executes with the privileges of the
- recipient user (exception: in case of delivery as root,
+ Mailbox delivery can be delegated to an external command
+ specified with the <b>mailbox</b><i>_</i><b>command</b> configuration parame-
+ ter. The command executes with the privileges of the
+ recipient user (exception: in case of delivery as root,
the command executes with the privileges of <b>default</b><i>_</i><b>user</b>).
-
- Mailbox delivery can be delegated to alternative message
- transports specified in the <b>master.cf</b> file. The <b>mail-</b>
- <b>box</b><i>_</i><b>transport</b> configuration parameter specifies a message
- transport that is to be used for all local recipients,
- regardless of whether they are found in the UNIX passwd
- database. The <b>fallback</b><i>_</i><b>transport</b> parameter specifies a
+ The command is subject to interpolation of <b>$user</b> (recipi-
+ ent username), <b>$home</b> (recipient home directory), <b>$shell</b>
+ (recipient shell), <b>$recipient</b> (complete recipient
+ address), <b>$extension</b> (recipient address extension),
+ <b>$domain</b> (recipient domain) and <b>$recipient</b><i>_</i><b>delimiter.</b> The
+ forms <i>${name?value}</i> and <i>${name:value}</i> expand conditionally
+ to <i>value</i> when <i>$name</i> is (is not) defined. In the result of
+ <i>name</i> expansion, characters that have special meaning to
+ the shell are censored and replaced by underscores.
+
+ Mailbox delivery can be delegated to alternative message
+ transports specified in the <b>master.cf</b> file. The <b>mail-</b>
+ <b>box</b><i>_</i><b>transport</b> configuration parameter specifies a message
+ transport that is to be used for all local recipients,
+ regardless of whether they are found in the UNIX passwd
+ database. The <b>fallback</b><i>_</i><b>transport</b> parameter specifies a
message transport for recipients that are not found in the
UNIX passwd database.
- In the case of UNIX-style mailbox delivery, the <b>local</b> dae-
- mon prepends a "<b>From</b> <i>sender</i> <i>time_stamp</i>" envelope header to
- each message, prepends a <b>Delivered-To:</b> header with the
- envelope recipient address, prepends a <b>Return-Path:</b> header
- with the envelope sender address, prepends a > character
- to lines beginning with "<b>From</b> ", and appends an empty
- line. The mailbox is locked for exclusive access while
- delivery is in progress. In case of problems, an attempt
- is made to truncate the mailbox to its original length.
-
- In the case of <b>maildir</b> delivery, the local daemon prepends
- a <b>Delivered-To:</b> header with the envelope recipient address
- and prepends a <b>Return-Path:</b> header with the envelope
- sender address.
-<b>EXTERNAL</b> <b>COMMAND</b> <b>DELIVERY</b>
- The <b>allow</b><i>_</i><b>mail</b><i>_</i><b>to</b><i>_</i><b>commands</b> configuration parameter
- restricts delivery to external commands. The default set-
- ting (<b>alias,</b> <b>forward</b>) forbids command destinations in
- <b>:include:</b> files.
- The command is executed directly where possible.
+ 2
- 2
+LOCAL(8) LOCAL(8)
+ In the case of UNIX-style mailbox delivery, the <b>local</b> dae-
+ mon prepends a "<b>From</b> <i>sender</i> <i>time_stamp</i>" envelope header to
+ each message, prepends a <b>Delivered-To:</b> header with the
+ envelope recipient address, prepends a <b>Return-Path:</b> header
+ with the envelope sender address, prepends a > character
+ to lines beginning with "<b>From</b> ", and appends an empty
+ line. The mailbox is locked for exclusive access while
+ delivery is in progress. In case of problems, an attempt
+ is made to truncate the mailbox to its original length.
-LOCAL(8) LOCAL(8)
+ In the case of <b>maildir</b> delivery, the local daemon prepends
+ a <b>Delivered-To:</b> header with the envelope recipient address
+ and prepends a <b>Return-Path:</b> header with the envelope
+ sender address.
+<b>EXTERNAL</b> <b>COMMAND</b> <b>DELIVERY</b>
+ The <b>allow</b><i>_</i><b>mail</b><i>_</i><b>to</b><i>_</i><b>commands</b> configuration parameter
+ restricts delivery to external commands. The default set-
+ ting (<b>alias,</b> <b>forward</b>) forbids command destinations in
+ <b>:include:</b> files.
- Assistance by the shell (<b>/bin/sh</b> on UNIX systems) is used
- only when the command contains shell magic characters, or
- when the command invokes a shell built-in command.
+ The command is executed directly where possible. Assis-
+ tance by the shell (<b>/bin/sh</b> on UNIX systems) is used only
+ when the command contains shell magic characters, or when
+ the command invokes a shell built-in command.
- A limited amount of command output (standard output and
- standard error) is captured for inclusion with non-deliv-
- ery status reports. A command is forcibly terminated if
- it does not complete within <b>command</b><i>_</i><b>time</b><i>_</i><b>limit</b> seconds.
- Command exit status codes are expected to follow the con-
+ A limited amount of command output (standard output and
+ standard error) is captured for inclusion with non-deliv-
+ ery status reports. A command is forcibly terminated if
+ it does not complete within <b>command</b><i>_</i><b>time</b><i>_</i><b>limit</b> seconds.
+ Command exit status codes are expected to follow the con-
ventions defined in <<b>sysexits.h</b>>.
When mail is delivered on behalf of a user, the <b>HOME</b>, <b>LOG-</b>
The current working directory is the mail queue directory.
The <b>local</b> daemon prepends a "<b>From</b> <i>sender</i> <i>time_stamp</i>" enve-
- lope header to each message, prepends a <b>Delivered-To:</b>
- header with the recipient envelope address, prepends a
- <b>Return-Path:</b> header with the sender envelope address, and
+ lope header to each message, prepends a <b>Delivered-To:</b>
+ header with the recipient envelope address, prepends a
+ <b>Return-Path:</b> header with the sender envelope address, and
appends an empty line.
<b>EXTERNAL</b> <b>FILE</b> <b>DELIVERY</b>
- The <b>allow</b><i>_</i><b>mail</b><i>_</i><b>to</b><i>_</i><b>files</b> configuration parameter restricts
- delivery to external files. The default setting (<b>alias,</b>
- <b>forward</b>) forbids file destinations in <b>:include:</b> files.
+ The <b>allow</b><i>_</i><b>mail</b><i>_</i><b>to</b><i>_</i><b>files</b> configuration parameter restricts
+ delivery to external files. The default setting (<b>alias,</b>
+ <b>forward</b>) forbids file destinations in <b>:include:</b> files.
Specify a pathname ending in <b>/</b> for <b>qmail</b>-compatible
<b>maildir</b> delivery.
- The <b>local</b> daemon prepends a "<b>From</b> <i>sender</i> <i>time_stamp</i>" enve-
- lope header to each message, prepends a <b>Delivered-To:</b>
- header with the recipient envelope address, prepends a >
- character to lines beginning with "<b>From</b> ", and appends an
- empty line. The envelope sender address is available in
- the <b>Return-Path:</b> header. When the destination is a regu-
- lar file, it is locked for exclusive access while delivery
- is in progress. In case of problems, an attempt is made to
- truncate a regular file to its original length.
- In the case of <b>maildir</b> delivery, the local daemon prepends
- a <b>Delivered-To:</b> header with the envelope recipient
- address. The envelope sender address is available in the
- <b>Return-Path:</b> header.
-<b>ADDRESS</b> <b>EXTENSION</b>
- The optional <b>recipient</b><i>_</i><b>delimiter</b> configuration parameter
- specifies how to separate address extensions from local
- recipient names.
- For example, with "<b>recipient</b><i>_</i><b>delimiter</b> <b>=</b> <b>+</b>", mail for
- <i>name</i>+<i>foo</i> is delivered to the alias <i>name</i>+<i>foo</i> or to the
+ 3
- 3
+LOCAL(8) LOCAL(8)
+ The <b>local</b> daemon prepends a "<b>From</b> <i>sender</i> <i>time_stamp</i>" enve-
+ lope header to each message, prepends a <b>Delivered-To:</b>
+ header with the recipient envelope address, prepends a >
+ character to lines beginning with "<b>From</b> ", and appends an
+ empty line. The envelope sender address is available in
+ the <b>Return-Path:</b> header. When the destination is a regu-
+ lar file, it is locked for exclusive access while delivery
+ is in progress. In case of problems, an attempt is made to
+ truncate a regular file to its original length.
-LOCAL(8) LOCAL(8)
+ In the case of <b>maildir</b> delivery, the local daemon prepends
+ a <b>Delivered-To:</b> header with the envelope recipient
+ address. The envelope sender address is available in the
+ <b>Return-Path:</b> header.
+<b>ADDRESS</b> <b>EXTENSION</b>
+ The optional <b>recipient</b><i>_</i><b>delimiter</b> configuration parameter
+ specifies how to separate address extensions from local
+ recipient names.
- alias <i>name</i>, to the destinations listed in ~<i>name</i>/.<b>for-</b>
+ For example, with "<b>recipient</b><i>_</i><b>delimiter</b> <b>=</b> <b>+</b>", mail for
+ <i>name</i>+<i>foo</i> is delivered to the alias <i>name</i>+<i>foo</i> or to the
+ alias <i>name</i>, to the destinations listed in ~<i>name</i>/.<b>for-</b>
<b>ward</b>+<i>foo</i> or in ~<i>name</i>/.<b>forward</b>, to the mailbox owned by the
user <i>name</i>, or it is sent back as undeliverable.
- In all cases the <b>local</b> daemon prepends a `<b>Delivered-To:</b>
+ In all cases the <b>local</b> daemon prepends a `<b>Delivered-To:</b>
<i>name</i>+<i>foo</i>' header line.
<b>DELIVERY</b> <b>RIGHTS</b>
- Deliveries to external files and external commands are
+ Deliveries to external files and external commands are
made with the rights of the receiving user on whose behalf
- the delivery is made. In the absence of a user context,
- the <b>local</b> daemon uses the owner rights of the <b>:include:</b>
+ the delivery is made. In the absence of a user context,
+ the <b>local</b> daemon uses the owner rights of the <b>:include:</b>
file or alias database. When those files are owned by the
superuser, delivery is made with the rights specified with
the <b>default</b><i>_</i><b>privs</b> configuration parameter.
RFC 822 (ARPA Internet Text Messages)
<b>DIAGNOSTICS</b>
- Problems and transactions are logged to <b>syslogd</b>(8). Cor-
- rupted message files are marked so that the queue manager
+ Problems and transactions are logged to <b>syslogd</b>(8). Cor-
+ rupted message files are marked so that the queue manager
can move them to the <b>corrupt</b> queue afterwards.
- Depending on the setting of the <b>notify</b><i>_</i><b>classes</b> parameter,
- the postmaster is notified of bounces and of other trou-
+ Depending on the setting of the <b>notify</b><i>_</i><b>classes</b> parameter,
+ the postmaster is notified of bounces and of other trou-
ble.
<b>BUGS</b>
- For security reasons, the message delivery status of
- external commands or of external files is never check-
+ For security reasons, the message delivery status of
+ external commands or of external files is never check-
pointed to file. As a result, the program may occasionally
+
+
+
+ 4
+
+
+
+
+
+LOCAL(8) LOCAL(8)
+
+
deliver more than once to a command or external file. Bet-
ter safe than sorry.
- Mutually-recursive aliases or ~/.<b>forward</b> files are not
- detected early. The resulting mail forwarding loop is
+ Mutually-recursive aliases or ~/.<b>forward</b> files are not
+ detected early. The resulting mail forwarding loop is
broken by the use of the <b>Delivered-To:</b> message header.
<b>CONFIGURATION</b> <b>PARAMETERS</b>
- The following <b>main.cf</b> parameters are especially relevant
- to this program. See the Postfix <b>main.cf</b> file for syntax
- details and for default values. Use the <b>postfix</b> <b>reload</b>
+ The following <b>main.cf</b> parameters are especially relevant
+ to this program. See the Postfix <b>main.cf</b> file for syntax
+ details and for default values. Use the <b>postfix</b> <b>reload</b>
command after a configuration change.
<b>Miscellaneous</b>
List of alias databases.
<b>forward</b><i>_</i><b>path</b>
- Search list for .forward files. The following
+ Search list for .forward files. The following
macros are recognized: <b>$home</b> (home directory),
<b>$user</b> (login name), <b>$extension</b> (address extension),
<b>$recipient</b><i>_</i><b>delimiter</b> (address extension delimiter).
-
-
- 4
-
-
-
-
-
-LOCAL(8) LOCAL(8)
-
-
<b>local</b><i>_</i><b>command</b><i>_</i><b>shell</b>
- Shell to use for external command execution (for
- example, /some/where/smrsh -c). When a shell is
+ Shell to use for external command execution (for
+ example, /some/where/smrsh -c). When a shell is
specified, it is invoked even when the command con-
- tains no shell built-in commands or meta charac-
+ tains no shell built-in commands or meta charac-
ters.
<b>owner</b><i>_</i><b>request</b><i>_</i><b>special</b>
<b>Mailbox</b> <b>delivery</b>
<b>fallback</b><i>_</i><b>transport</b>
Message transport for recipients that are not found
- in the UNIX passwd database. This parameter over-
+ in the UNIX passwd database. This parameter over-
rides <b>luser</b><i>_</i><b>relay</b>.
<b>home</b><i>_</i><b>mailbox</b>
- Pathname of a mailbox relative to a user's home
+ Pathname of a mailbox relative to a user's home
directory. Specify a path ending in <b>/</b> for maildir-
style delivery.
<b>luser</b><i>_</i><b>relay</b>
- Destination (<i>@domain</i> or <i>address</i>) for non-existent
- users. The <i>address</i> can be any destination that is
+ Destination (<i>@domain</i> or <i>address</i>) for non-existent
+ users. The <i>address</i> can be any destination that is
valid in an alias file.
+
+
+
+
+ 5
+
+
+
+
+
+LOCAL(8) LOCAL(8)
+
+
<b>mail</b><i>_</i><b>spool</b><i>_</i><b>directory</b>
- Directory with UNIX-style mailboxes. The default
+ Directory with UNIX-style mailboxes. The default
pathname is system dependent.
<b>mailbox</b><i>_</i><b>command</b>
- External command to use for mailbox delivery. The
+ External command to use for mailbox delivery. The
command executes with the recipient privileges
(exception: root).
<b>mailbox</b><i>_</i><b>transport</b>
- Message transport to use for mailbox delivery to
+ Message transport to use for mailbox delivery to
all local recipients, whether or not they are found
- in the UNIX passwd database. This parameter over-
- rides all other configuration parameters that con-
+ in the UNIX passwd database. This parameter over-
+ rides all other configuration parameters that con-
trol mailbox delivery, including <b>luser</b><i>_</i><b>relay</b>.
<b>Locking</b> <b>controls</b>
<b>deliver</b><i>_</i><b>lock</b><i>_</i><b>attempts</b>
- Limit the number of attempts to acquire an exclu-
+ Limit the number of attempts to acquire an exclu-
sive lock on a mailbox or external file.
<b>deliver</b><i>_</i><b>lock</b><i>_</i><b>delay</b>
- Time in seconds between successive attempts to
+ Time in seconds between successive attempts to
acquire an exclusive lock.
-
-
- 5
-
-
-
-
-
-LOCAL(8) LOCAL(8)
-
-
<b>stale</b><i>_</i><b>lock</b><i>_</i><b>time</b>
Limit the time after which a stale lock is removed.
<b>Resource</b> <b>controls</b>
<b>command</b><i>_</i><b>time</b><i>_</i><b>limit</b>
- Limit the amount of time for delivery to external
+ Limit the amount of time for delivery to external
command.
<b>duplicate</b><i>_</i><b>filter</b><i>_</i><b>limit</b>
- Limit the size of the duplicate filter for results
+ Limit the size of the duplicate filter for results
from alias etc. expansion.
<b>line</b><i>_</i><b>length</b><i>_</i><b>limit</b>
- Limit the amount of memory used for processing a
+ Limit the amount of memory used for processing a
partial input line.
<b>local</b><i>_</i><b>destination</b><i>_</i><b>concurrency</b><i>_</i><b>limit</b>
Limit the number of parallel deliveries to the same
- user. The default limit is taken from the
+ user. The default limit is taken from the
<b>default</b><i>_</i><b>destination</b><i>_</i><b>concurrency</b><i>_</i><b>limit</b> parameter.
<b>local</b><i>_</i><b>destination</b><i>_</i><b>recipient</b><i>_</i><b>limit</b>
- Limit the number of recipients per message deliv-
- ery. The default limit is taken from the
+ Limit the number of recipients per message deliv-
+ ery. The default limit is taken from the
<b>default</b><i>_</i><b>destination</b><i>_</i><b>recipient</b><i>_</i><b>limit</b> parameter.
<b>Security</b> <b>controls</b>
<b>allow</b><i>_</i><b>mail</b><i>_</i><b>to</b><i>_</i><b>commands</b>
- Restrict the usage of mail delivery to external
+ Restrict the usage of mail delivery to external
+
+
+
+ 6
+
+
+
+
+
+LOCAL(8) LOCAL(8)
+
+
command.
<b>allow</b><i>_</i><b>mail</b><i>_</i><b>to</b><i>_</i><b>files</b>
- Restrict the usage of mail delivery to external
+ Restrict the usage of mail delivery to external
file.
<b>default</b><i>_</i><b>privs</b>
- Default rights for delivery to external file or
+ Default rights for delivery to external file or
command.
<b>HISTORY</b>
- The <b>Delivered-To:</b> header appears in the <b>qmail</b> system by
+ The <b>Delivered-To:</b> header appears in the <b>qmail</b> system by
Daniel Bernstein.
- The <i>maildir</i> structure appears in the <b>qmail</b> system by
+ The <i>maildir</i> structure appears in the <b>qmail</b> system by
Daniel Bernstein.
<b>SEE</b> <b>ALSO</b>
syslogd(8) system logging
<a href="qmgr.8.html">qmgr(8)</a> queue manager
-
-
-
-
- 6
-
-
-
-
-
-LOCAL(8) LOCAL(8)
-
-
<b>LICENSE</b>
- The Secure Mailer license must be distributed with this
+ The Secure Mailer license must be distributed with this
software.
<b>AUTHOR(S)</b>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
ging level by the amount specified in the
<b>debug</b><i>_</i><b>peer</b><i>_</i><b>level</b> parameter.
+ <b>disable</b><i>_</i><b>dns</b><i>_</i><b>lookups</b>
+ Disable DNS lookups. This means that mail must be
+ forwarded via a smart relay host.
+
<b>error</b><i>_</i><b>notice</b><i>_</i><b>recipient</b>
- Recipient of protocol/policy/resource/software
+ Recipient of protocol/policy/resource/software
error notices.
<b>fallback</b><i>_</i><b>relay</b>
- Hosts to hand off mail to if a message destination
+ Hosts to hand off mail to if a message destination
is not found or if a destination is unreachable.
<b>ignore</b><i>_</i><b>mx</b><i>_</i><b>lookup</b><i>_</i><b>error</b>
<b>inet</b><i>_</i><b>interfaces</b>
The network interface addresses that this mail sys-
- tem receives mail on. When any of those addresses
+ tem receives mail on. When any of those addresses
appears in the list of mail exchangers for a remote
- destination, the list is truncated to avoid mail
+ destination, the list is truncated to avoid mail
delivery loops.
<b>notify</b><i>_</i><b>classes</b>
- When this parameter includes the <b>protocol</b> class,
- send mail to the postmaster with transcripts of
+ When this parameter includes the <b>protocol</b> class,
+ send mail to the postmaster with transcripts of
SMTP sessions with protocol errors.
<b>smtp</b><i>_</i><b>skip</b><i>_</i><b>4xx</b><i>_</i><b>greeting</b>
- Skip servers that greet us with a 4xx status code.
+ Skip servers that greet us with a 4xx status code.
<b>smtp</b><i>_</i><b>skip</b><i>_</i><b>quit</b><i>_</i><b>response</b>
- Do not wait for the server response after sending
+ Do not wait for the server response after sending
QUIT.
-<b>Resource</b> <b>controls</b>
- <b>smtp</b><i>_</i><b>destination</b><i>_</i><b>concurrency</b><i>_</i><b>limit</b>
- Limit the number of parallel deliveries to the same
-
2
SMTP(8) SMTP(8)
- destination. The default limit is taken from the
+<b>Resource</b> <b>controls</b>
+ <b>smtp</b><i>_</i><b>destination</b><i>_</i><b>concurrency</b><i>_</i><b>limit</b>
+ Limit the number of parallel deliveries to the same
+ destination. The default limit is taken from the
<b>default</b><i>_</i><b>destination</b><i>_</i><b>concurrency</b><i>_</i><b>limit</b> parameter.
<b>smtp</b><i>_</i><b>destination</b><i>_</i><b>recipient</b><i>_</i><b>limit</b>
- Limit the number of recipients per message deliv-
- ery. The default limit is taken from the
+ Limit the number of recipients per message deliv-
+ ery. The default limit is taken from the
<b>default</b><i>_</i><b>destination</b><i>_</i><b>recipient</b><i>_</i><b>limit</b> parameter.
<b>Timeout</b> <b>controls</b>
<b>smtp</b><i>_</i><b>connect</b><i>_</i><b>timeout</b>
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
+ the SMTP client tries the next address on the mail
exchanger list.
<b>smtp</b><i>_</i><b>helo</b><i>_</i><b>timeout</b>
- Timeout in seconds for receiving the SMTP greeting
+ Timeout in seconds for receiving the SMTP greeting
banner. When the server drops the connection with-
- out sending a greeting banner, or when it sends no
+ out 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.
<b>smtp</b><i>_</i><b>helo</b><i>_</i><b>timeout</b>
- Timeout in seconds for sending the <b>HELO</b> command,
+ Timeout in seconds for sending the <b>HELO</b> command,
and for receiving the server response.
<b>smtp</b><i>_</i><b>mail</b><i>_</i><b>timeout</b>
- Timeout in seconds for sending the <b>MAIL</b> <b>FROM</b> com-
+ Timeout in seconds for sending the <b>MAIL</b> <b>FROM</b> com-
mand, and for receiving the server response.
<b>smtp</b><i>_</i><b>rcpt</b><i>_</i><b>timeout</b>
and for receiving the server response.
<b>smtp</b><i>_</i><b>data</b><i>_</i><b>init</b><i>_</i><b>timeout</b>
- Timeout in seconds for sending the <b>DATA</b> command,
+ Timeout in seconds for sending the <b>DATA</b> command,
and for receiving the server response.
<b>smtp</b><i>_</i><b>data</b><i>_</i><b>xfer</b><i>_</i><b>timeout</b>
<b>smtp</b><i>_</i><b>data</b><i>_</i><b>done</b><i>_</i><b>timeout</b>
Timeout in seconds for sending the "<b>.</b>" command, and
for receiving the server response. When no response
- is received, a warning is logged that the mail may
+ is received, a warning is logged that the mail may
be delivered multiple times.
<b>smtp</b><i>_</i><b>quit</b><i>_</i><b>timeout</b>
- Timeout in seconds for sending the <b>QUIT</b> command,
+ Timeout in seconds for sending the <b>QUIT</b> command,
and for receiving the server response.
-<b>SEE</b> <b>ALSO</b>
- <a href="bounce.8.html">bounce(8)</a> non-delivery status reports
-
3
SMTP(8) SMTP(8)
+<b>SEE</b> <b>ALSO</b>
+ <a href="bounce.8.html">bounce(8)</a> non-delivery status reports
<a href="master.8.html">master(8)</a> process manager
<a href="qmgr.8.html">qmgr(8)</a> queue manager
syslogd(8) system logging
<b>LICENSE</b>
- The Secure Mailer license must be distributed with this
+ The Secure Mailer license must be distributed with this
software.
<b>AUTHOR(S)</b>
-
-
-TEXPAND_ATTR
-TFILE
-TFORWARD_INFO
--TFW_CONTEXT
-THEADER_OPTS
-THTABLE
-THTABLE_INFO
-TINET_ADDR_LIST
-TINT_TABLE
-TLOCAL_STATE
+-TMAC_EXP_CONTEXT
-TMAC_HEAD
-TMAC_PARSE
-TMAIL_PRINT
SHELL = /bin/sh
SRCS = alias.c command.c delivered.c dotforward.c file.c forward.c \
include.c indirect.c local.c mailbox.c recipient.c resolve.c token.c \
- deliver_attr.c feature.c maildir.c biff_notify.c unknown.c
+ deliver_attr.c feature.c maildir.c biff_notify.c unknown.c \
+ local_expand.c
OBJS = alias.o command.o delivered.o dotforward.o file.o forward.o \
include.o indirect.o local.o mailbox.o recipient.o resolve.o token.o \
- deliver_attr.o feature.o maildir.o biff_notify.o unknown.o
+ deliver_attr.o feature.o maildir.o biff_notify.o unknown.o \
+ local_expand.o
HDRS = local.h
TESTSRC =
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
test: $(TESTPROG)
-update: ../bin/$(PROG)
+update: ../libexec/$(PROG)
-../bin/$(PROG): $(PROG)
- cp $(PROG) ../bin
+../libexec/$(PROG): $(PROG)
+ cp $(PROG) ../libexec
printfck: $(OBJS) $(PROG)
rm -rf printfck
local.o: local.h
local.o: ../include/tok822.h
local.o: ../include/resolve_clnt.h
+local_expand.o: local_expand.c
+local_expand.o: ../include/sys_defs.h
+local_expand.o: ../include/vstring.h
+local_expand.o: ../include/vbuf.h
+local_expand.o: ../include/mac_expand.h
+local_expand.o: ../include/mail_params.h
+local_expand.o: local.h
+local_expand.o: ../include/htable.h
+local_expand.o: ../include/vstream.h
+local_expand.o: ../include/been_here.h
+local_expand.o: ../include/tok822.h
+local_expand.o: ../include/resolve_clnt.h
+local_expand.o: ../include/deliver_request.h
+local_expand.o: ../include/recipient_list.h
mailbox.o: mailbox.c
mailbox.o: ../include/sys_defs.h
mailbox.o: ../include/msg.h
/* .IP usr_attr
/* Attributes describing user rights and environment.
/* .IP command
-/* The shell command to be executed. If possible, the command
-/* is executed without actually invoking a shell.
+/* The shell command to be executed, after $name expansion of recipient
+/* attributes. If possible, the command is executed without actually
+/* invoking a shell.
/* DIAGNOSTICS
/* deliver_command() returns non-zero when delivery should be
/* tried again,
int deliver_status;
ARGV *env;
int copy_flags;
+ static char *ok_chars = "1234567890!@%-_=+:,./\
+abcdefghijklmnopqrstuvwxyz\
+ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ VSTRING *expanded_cmd;
/*
* Make verbose logging easier to understand.
argv_add(env, "SHELL", usr_attr.shell, ARGV_END);
argv_terminate(env);
+ expanded_cmd = vstring_alloc(10);
+ if (command == var_mailbox_command)
+ local_expand(expanded_cmd, command, state, usr_attr, ok_chars);
+ else
+ vstring_strcpy(expanded_cmd, command);
+
cmd_status = pipe_command(state.msg_attr.fp, why,
PIPE_CMD_UID, usr_attr.uid,
PIPE_CMD_GID, usr_attr.gid,
- PIPE_CMD_COMMAND, command,
+ PIPE_CMD_COMMAND, vstring_str(expanded_cmd),
PIPE_CMD_COPY_FLAGS, copy_flags,
PIPE_CMD_SENDER, state.msg_attr.sender,
PIPE_CMD_DELIVERED, state.msg_attr.delivered,
PIPE_CMD_END);
argv_free(env);
+ vstring_free(expanded_cmd);
/*
* Depending on the result, bounce or defer the message.
#define NO 0
#define YES 1
- /*
- * A little helper structure for message-specific context.
- */
-typedef struct {
- int flags; /* see below */
- struct mypasswd *pwd; /* recipient */
- char *extension; /* address extension */
- char *domain; /* recipient's domain */
- char *recipient; /* recipient */
- VSTRING *path; /* result */
-} FW_CONTEXT;
-
-#define FW_FLAG_FAILURE (1<<0) /* $name not available */
-#define FW_FLAG_HOME (1<<1) /* expanded $home */
-#define FW_FLAG_USER (1<<2) /* expanded $user */
-#define FW_FLAG_EXTENSION (1<<3) /* expanded $extension */
-#define FW_FLAG_DELIMITER (1<<4) /* expanded $recipient_delimiter */
-#define FW_FLAG_DOMAIN (1<<5) /* expanded $domain */
-#define FW_FLAG_RECIPIENT (1<<6) /* expanded $recipient */
-#define FW_FLAG_OTHER (1<<7) /* expanded text */
-
-/* dotforward_parse_callback - callback for mac_parse */
-
-static void dotforward_parse_callback(int type, VSTRING *buf, char *context)
-{
- char *myname = "dotforward_parse_callback";
- FW_CONTEXT *fw_context = (FW_CONTEXT *) context;
- char *ptr;
- int flg;
-
- if (fw_context->flags & FW_FLAG_FAILURE)
- return;
-
- /*
- * Find out what data to substitute.
- */
- if (type == MAC_PARSE_VARNAME) {
- if (strcmp(vstring_str(buf), "home") == 0) {
- flg = FW_FLAG_HOME;
- ptr = fw_context->pwd->pw_dir;
- } else if (strcmp(vstring_str(buf), "user") == 0) {
- flg = FW_FLAG_USER;
- ptr = fw_context->pwd->pw_name;
- } else if (strcmp(vstring_str(buf), "extension") == 0) {
- flg = FW_FLAG_EXTENSION;
- ptr = fw_context->extension;
- } else if (strcmp(vstring_str(buf), "recipient_delimiter") == 0) {
- flg = FW_FLAG_DELIMITER;
- ptr = var_rcpt_delim;
- } else if (strcmp(vstring_str(buf), "domain") == 0) {
- flg = FW_FLAG_DOMAIN;
- ptr = fw_context->domain;
- } else if (strcmp(vstring_str(buf), "recipient") == 0) {
- flg = FW_FLAG_RECIPIENT;
- ptr = fw_context->recipient;
- } else
- msg_fatal("unknown macro $%s in %s", vstring_str(buf),
- VAR_FORWARD_PATH);
- } else {
- flg = FW_FLAG_OTHER;
- ptr = vstring_str(buf);
- }
-
- /*
- * Append the data, or record that the data was not available.
- */
- if (msg_verbose)
- msg_info("%s: %s = %s", myname, vstring_str(buf),
- ptr ? ptr : "(unavailable)");
- if (ptr == 0) {
- fw_context->flags |= FW_FLAG_FAILURE;
- } else {
- fw_context->flags |= flg;
- vstring_strcat(fw_context->path, ptr);
- }
-}
-
/* deliver_dotforward - expand contents of .forward file */
int deliver_dotforward(LOCAL_STATE state, USER_ATTR usr_attr, int *statusp)
char *saved_forward_path;
char *lhs;
char *next;
- char *domain;
const char *forward_path;
- FW_CONTEXT fw_context;
/*
* Make verbose logging easier to understand.
path = vstring_alloc(100);
saved_forward_path = mystrdup(forward_path);
next = saved_forward_path;
-
- if ((domain = strrchr(state.msg_attr.recipient, '@')) != 0)
- domain++;
-
- fw_context.pwd = mypwd;
- fw_context.extension = state.msg_attr.extension;
- fw_context.path = path;
- fw_context.domain = domain;
- fw_context.recipient = state.msg_attr.recipient;
-
lookup_status = -1;
while ((lhs = mystrtok(&next, ", \t\r\n")) != 0) {
- fw_context.flags = 0;
VSTRING_RESET(path);
- mac_parse(lhs, dotforward_parse_callback, (char *) &fw_context);
- if ((fw_context.flags & FW_FLAG_FAILURE) == 0) {
+ if (local_expand(path, lhs, state, usr_attr, (char *) 0) == 0) {
lookup_status =
lstat_as(STR(path), &st, usr_attr.uid, usr_attr.gid);
if (msg_verbose)
msg_info("%s: path %s status %d", myname,
STR(path), lookup_status);
- if (lookup_status >= 0) {
- if (fw_context.flags & FW_FLAG_EXTENSION)
- state.msg_attr.extension = 0;
+ if (lookup_status >= 0)
break;
- }
}
}
/* destinations in ~\fIname\fR/.\fBforward\fR, to the mailbox owned
/* by the user \fIname\fR, or it is sent back as undeliverable.
/*
+/* The system administrator can specify a comma/space separated list
+/* of ~\fR/.\fBforward\fR like files through the \fBforward_path\fR
+/* configuration parameter. Upon delivery, the local delivery agent
+/* tries each pathname in the list until a file is found.
+/* The \fBforward_path\fR parameter is subject to interpolation of
+/* \fB$user\fR (recipient username), \fB$home\fR (recipient home
+/* directory), \fB$shell\fR (recipient shell), \fB$recipient\fR
+/* (complete recipient address), \fB$extension\fR (recipient address
+/* extension), \fB$domain\fR (recipient domain) and
+/* \fB$recipient_delimiter.\fR The forms \fI${name?value}\fR and
+/* \fI${name:value}\fR expand conditionally to \fIvalue\fR when
+/* \fI$name\fR is (is not) defined.
+/*
/* An alias or ~/.\fBforward\fR file may list any combination of external
/* commands, destination file names, \fB:include:\fR directives, or
/* mail addresses.
/* executes with the privileges of the recipient user (exception: in
/* case of delivery as root, the command executes with the privileges
/* of \fBdefault_user\fR).
+/* The command is subject to interpolation of \fB$user\fR (recipient
+/* username), \fB$home\fR (recipient home directory), \fB$shell\fR
+/* (recipient shell), \fB$recipient\fR (complete recipient address),
+/* \fB$extension\fR (recipient address extension), \fB$domain\fR
+/* (recipient domain) and \fB$recipient_delimiter.\fR The forms
+/* \fI${name?value}\fR and \fI${name:value}\fR expand conditionally to
+/* \fIvalue\fR when \fI$name\fR is (is not) defined. In the result
+/* of \fIname\fR expansion, characters that have special meaning to
+/* the shell are censored and replaced by underscores.
/*
/* Mailbox delivery can be delegated to alternative message transports
/* specified in the \fBmaster.cf\fR file.
/* pre_accept - see if tables have changed */
-static void pre_accept(void)
+static void pre_accept(char *unused_name, char **unused_argv)
{
if (dict_changed()) {
msg_info("table has changed -- exiting");
/* post_init - post-jail initialization */
-static void post_init(void)
+static void post_init(char *unused_name, char **unused_argv)
{
/*
static CONFIG_STR_TABLE str_table[] = {
VAR_ALIAS_MAPS, DEF_ALIAS_MAPS, &var_alias_maps, 0, 0,
VAR_HOME_MAILBOX, DEF_HOME_MAILBOX, &var_home_mailbox, 0, 0,
- VAR_MAILBOX_COMMAND, DEF_MAILBOX_COMMAND, &var_mailbox_command, 0, 0,
VAR_ALLOW_COMMANDS, DEF_ALLOW_COMMANDS, &var_allow_commands, 0, 0,
VAR_ALLOW_FILES, DEF_ALLOW_FILES, &var_allow_files, 0, 0,
VAR_RCPT_FDELIM, DEF_RCPT_FDELIM, &var_rcpt_fdelim, 0, 0,
/* Suppress $name expansion upon loading. */
static CONFIG_STR_TABLE raw_table[] = {
VAR_FORWARD_PATH, DEF_FORWARD_PATH, &var_forward_path, 0, 0,
+ VAR_MAILBOX_COMMAND, DEF_MAILBOX_COMMAND, &var_mailbox_command, 0, 0,
0,
};
*/
extern int feature_control(const char *);
+ /*
+ * local_expand.c
+ */
+int local_expand(VSTRING *, const char *, LOCAL_STATE, USER_ATTR, const char *);
+
/* LICENSE
/* .ad
/* .fi
--- /dev/null
+/*++
+/* NAME
+/* local_expand 3
+/* SUMMARY
+/* expand $name based on delivery attributes
+/* SYNOPSIS
+/* #include "local.h"
+/*
+/* int local_expand(result, pattern, state, usr_attr, filter)
+/* VSTRING *result;
+/* const char *pattern;
+/* LOCAL_STATE state;
+/* USER_ATTR usr_attr;
+/* const char *filter;
+/* DESCRIPTION
+/* local_expand() expands $name instances on the basis of message
+/* delivery attributes.
+/*
+/* Macros:
+/* .IP $domain
+/* The recipient address domain.
+/* .IP $extension
+/* The recipient address extension.
+/* .IP $home
+/* The recipient home directory.
+/* .IP $recipient
+/* The full recipient address.
+/* .IP $recipient_delimiter
+/* The recipient delimiter.
+/* .IP $shell
+/* The recipient shell program.
+/* .IP $user
+/* The recipient user name.
+/* .PP
+/* Arguments:
+/* .IP result
+/* Storage for the result. The result is truncated upon entry.
+/* .IP pattern
+/* The input with zero or more $name references.
+/* .IP state
+/* Message delivery attributes (sender, recipient etc.).
+/* Attributes describing alias, include or forward expansion.
+/* A table with the results from expanding aliases or lists.
+/* A table with delivered-to: addresses taken from the message.
+/* .IP usr_attr
+/* Attributes describing user rights and environment.
+/* .IP filter
+/* A null pointer, or a null-terminated list of characters that
+/* are allowed to appear in the result if a $name expansion.
+/* DIAGNOSTICS
+/* Fatal errors: out of memory.
+/* SEE ALSO
+/* mac_expand(3) macro expansion
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* IBM T.J. Watson Research
+/* P.O. Box 704
+/* Yorktown Heights, NY 10598, USA
+/*--*/
+
+/* System library. */
+
+#include <sys_defs.h>
+#include <string.h>
+
+/* Utility library. */
+
+#include <vstring.h>
+#include <mac_expand.h>
+
+/* Global library. */
+
+#include <mail_params.h>
+
+/* Application-specific. */
+
+#include "local.h"
+
+/* local_expand - expand contents of .forward file */
+
+int local_expand(VSTRING *result, const char *pattern,
+ LOCAL_STATE state, USER_ATTR usr_attr, const char *filter)
+{
+ char *domain;
+
+ /*
+ * Impedance matching between the local delivery agent data structures
+ * and the mac_expand() interface. The CPU cycles wasted will be
+ * negligible.
+ */
+ if ((domain = strrchr(state.msg_attr.recipient, '@')) != 0)
+ domain++;
+
+ return (mac_expand(result, pattern, MAC_EXP_FLAG_NONE,
+ MAC_EXP_ARG_FILTER, filter,
+ MAC_EXP_ARG_ATTR, "user", usr_attr.logname,
+ MAC_EXP_ARG_ATTR, "home", usr_attr.home,
+ MAC_EXP_ARG_ATTR, "shell", usr_attr.shell,
+ MAC_EXP_ARG_ATTR, "domain", domain,
+ MAC_EXP_ARG_ATTR, "recipient", state.msg_attr.recipient,
+ MAC_EXP_ARG_ATTR, "extension", state.msg_attr.extension,
+ MAC_EXP_ARG_ATTR, "recipient_delimiter",
+ *var_rcpt_delim ? var_rcpt_delim : 0,
+ 0));
+}
tok822_resolve(addr, &reply);
state.msg_attr.recipient = STR(reply.recipient);
+#if 0
/*
* Splice in the optional unmatched address extension.
*/
VSTRING_SKIP(reply.recipient);
}
}
+#endif
/*
* Delivery to a local or non-local address. For a while there was some
# For now, just hard-coded rules for daemons, commands, config files.
-DAEMONS = man8/bounce.8 man8/defer.8 man8/cleanup.8 man8/local.8 \
+DAEMONS = man8/bounce.8 man8/defer.8 man8/cleanup.8 man8/error.8 man8/local.8 \
man8/master.8 man8/pickup.8 man8/pipe.8 man8/qmgr.8 man8/showq.8 \
man8/smtp.8 man8/smtpd.8 man8/trivial-rewrite.8
COMMANDS= man1/postalias.1 man1/postcat.1 man1/postconf.1 man1/postfix.1 \
man8/cleanup.8: ../cleanup/cleanup.c
srctoman $? >$@
+man8/error.8: ../error/error.c
+ srctoman $? >$@
+
man8/local.8: ../local/local.c
srctoman $? >$@
--- /dev/null
+.TH ERROR 8
+.ad
+.fi
+.SH NAME
+error
+\-
+Postfix error mailer
+.SH SYNOPSIS
+.na
+.nf
+\fBerror\fR [generic Postfix daemon options]
+.SH DESCRIPTION
+.ad
+.fi
+The Postfix error mailer processes message delivery requests from
+the queue manager. Each request specifies a queue file, a sender
+address, a domain or host name that is treated as the reason for
+non-delivery, and recipient information.
+This program expects to be run from the \fBmaster\fR(8) process
+manager.
+
+The error mailer client forces all recipients to bounce, using the
+domain or host information as the reason for non-delivery, updates
+the queue file and marks recipients as finished, or it informs the
+queue manager that delivery should be tried again at a later time.
+
+Delivery problem reports are sent to the \fBbounce\fR(8) or
+\fBdefer\fR(8) daemon as appropriate.
+.SH SECURITY
+.na
+.nf
+.ad
+.fi
+The error mailer is not security-sensitive. It does not talk
+to the network, and can be run chrooted at fixed low privilege.
+.SH STANDARDS
+.na
+.nf
+None.
+.SH DIAGNOSTICS
+.ad
+.fi
+Problems and transactions are logged to \fBsyslogd\fR(8).
+
+Depending on the setting of the \fBnotify_classes\fR parameter,
+the postmaster is notified of bounces and of other trouble.
+.SH BUGS
+.ad
+.fi
+.SH CONFIGURATION PARAMETERS
+.na
+.nf
+.ad
+.fi
+The following \fBmain.cf\fR parameters are especially relevant to
+this program. See the Postfix \fBmain.cf\fR file for syntax details
+and for default values. Use the \fBpostfix reload\fR command after
+a configuration change.
+.SH Miscellaneous
+.ad
+.fi
+.IP \fBbounce_notice_recipient\fR
+Postmaster for bounce error notices.
+.IP \fBnotify_classes\fR
+When this parameter includes the \fBbounce\fR class, send mail to the
+postmaster with with the headers of the bounced mail.
+.SH SEE ALSO
+.na
+.nf
+bounce(8) non-delivery status reports
+master(8) process manager
+qmgr(8) queue manager
+syslogd(8) system logging
+.SH LICENSE
+.na
+.nf
+.ad
+.fi
+The Secure Mailer license must be distributed with this software.
+.SH AUTHOR(S)
+.na
+.nf
+Wietse Venema
+IBM T.J. Watson Research
+P.O. Box 704
+Yorktown Heights, NY 10598, USA
destinations in ~\fIname\fR/.\fBforward\fR, to the mailbox owned
by the user \fIname\fR, or it is sent back as undeliverable.
+The system administrator can specify a comma/space separated list
+of ~\fR/.\fBforward\fR like files through the \fBforward_path\fR
+configuration parameter. Upon delivery, the local delivery agent
+tries each pathname in the list until a file is found.
+The \fBforward_path\fR parameter is subject to interpolation of
+\fB$user\fR (recipient username), \fB$home\fR (recipient home
+directory), \fB$shell\fR (recipient shell), \fB$recipient\fR
+(complete recipient address), \fB$extension\fR (recipient address
+extension), \fB$domain\fR (recipient domain) and
+\fB$recipient_delimiter.\fR The forms \fI${name?value}\fR and
+\fI${name:value}\fR expand conditionally to \fIvalue\fR when
+\fI$name\fR is (is not) defined.
+
An alias or ~/.\fBforward\fR file may list any combination of external
commands, destination file names, \fB:include:\fR directives, or
mail addresses.
executes with the privileges of the recipient user (exception: in
case of delivery as root, the command executes with the privileges
of \fBdefault_user\fR).
+The command is subject to interpolation of \fB$user\fR (recipient
+username), \fB$home\fR (recipient home directory), \fB$shell\fR
+(recipient shell), \fB$recipient\fR (complete recipient address),
+\fB$extension\fR (recipient address extension), \fB$domain\fR
+(recipient domain) and \fB$recipient_delimiter.\fR The forms
+\fI${name?value}\fR and \fI${name:value}\fR expand conditionally to
+\fIvalue\fR when \fI$name\fR is (is not) defined. In the result
+of \fIname\fR expansion, characters that have special meaning to
+the shell are censored and replaced by underscores.
Mailbox delivery can be delegated to alternative message transports
specified in the \fBmaster.cf\fR file.
List of domain or network patterns. When a remote host matches
a pattern, increase the verbose logging level by the amount
specified in the \fBdebug_peer_level\fR parameter.
+.IP \fBdisable_dns_lookups\fR
+Disable DNS lookups. This means that mail must be forwarded
+via a smart relay host.
.IP \fBerror_notice_recipient\fR
Recipient of protocol/policy/resource/software error notices.
.IP \fBfallback_relay\fR
-TEXPAND_ATTR
-TFILE
-TFORWARD_INFO
--TFW_CONTEXT
-THEADER_OPTS
-THTABLE
-THTABLE_INFO
-TINET_ADDR_LIST
-TINT_TABLE
-TLOCAL_STATE
+-TMAC_EXP_CONTEXT
-TMAC_HEAD
-TMAC_PARSE
-TMAIL_PRINT
LIBS = ../lib/libglobal.a ../lib/libutil.a
LIB_DIR = ../lib
INC_DIR = ../include
-BIN_DIR = ../bin
+BIN_DIR = ../libexec
.c.o:; $(CC) $(CFLAGS) -c $*.c
#define MAIL_SERVER_EXIT 13
#define MAIL_SERVER_PRE_ACCEPT 14
-typedef void (*MAIL_SERVER_INIT_FN) (void);
-typedef int (*MAIL_SERVER_LOOP_FN) (void);
-typedef void (*MAIL_SERVER_EXIT_FN) (void);
-typedef void (*MAIL_SERVER_ACCEPT_FN) (void);
+typedef void (*MAIL_SERVER_INIT_FN) (char *, char **);
+typedef int (*MAIL_SERVER_LOOP_FN) (char *, char **);
+typedef void (*MAIL_SERVER_EXIT_FN) (char *, char **);
+typedef void (*MAIL_SERVER_ACCEPT_FN) (char *, char **);
/*
* single_server.c
/* order as specified, and multiple instances of the same type
/* are allowed. Raw parameters are not subjected to $name
/* evaluation.
-/* .IP "MAIL_SERVER_PRE_INIT (void *(void))"
+/* .IP "MAIL_SERVER_PRE_INIT (void *(char *service_name char **argv))"
/* A pointer to a function that is called once
/* by the skeleton after it has read the global configuration file
/* and after it has processed command-line arguments, but before
/* the skeleton has optionally relinquished the process privileges.
-/* .IP "MAIL_SERVER_POST_INIT (void *(void))"
+/* .IP "MAIL_SERVER_POST_INIT (void *(char *service_name char **argv))"
/* A pointer to a function that is called once
/* by the skeleton after it has optionally relinquished the process
/* privileges, but before servicing client connection requests.
-/* .IP "MAIL_SERVER_LOOP (int *(void))"
+/* .IP "MAIL_SERVER_LOOP (int *(char *service_name char **argv))"
/* A pointer to function that is executed from
/* within the event loop, whenever an I/O or timer event has happened,
/* or whenever nothing has happened for a specified amount of time.
/* The result value of the function specifies how long to wait until
/* the next event. Specify -1 to wait for "as long as it takes".
-/* .IP "MAIL_SERVER_EXIT (void *(void))"
+/* .IP "MAIL_SERVER_EXIT (void *(char *service_name char **argv))"
/* A pointer to function that is executed immediately before normal
/* process termination.
-/* .IP "MAIL_SERVER_PRE_ACCEPT (void *(void))"
+/* .IP "MAIL_SERVER_PRE_ACCEPT (void *(char *service_name char **argv))"
/* Function to be executed prior to accepting a new connection.
/* .PP
/* multi_server_disconnect() should be called by the application
static char *multi_server_name;
static char **multi_server_argv;
static void (*multi_server_accept) (int, char *);
-static void (*multi_server_onexit) (void);
-static void (*multi_server_pre_accept) (void);
+static void (*multi_server_onexit) (char *, char **);
+static void (*multi_server_pre_accept) (char *, char **);
static VSTREAM *multi_server_lock;
/* multi_server_exit - normal termination */
static NORETURN multi_server_exit(void)
{
if (multi_server_onexit)
- multi_server_onexit();
+ multi_server_onexit(multi_server_name, multi_server_argv);
exit(0);
}
time_left = event_cancel_timer(multi_server_timeout, (char *) 0);
if (multi_server_pre_accept)
- multi_server_pre_accept();
+ multi_server_pre_accept(multi_server_name, multi_server_argv);
fd = LOCAL_ACCEPT(listen_fd);
if (multi_server_lock != 0
&& myflock(vstream_fileno(multi_server_lock), MYFLOCK_NONE) < 0)
time_left = event_cancel_timer(multi_server_timeout, (char *) 0);
if (multi_server_pre_accept)
- multi_server_pre_accept();
+ multi_server_pre_accept(multi_server_name, multi_server_argv);
fd = inet_accept(listen_fd);
if (multi_server_lock != 0
&& myflock(vstream_fileno(multi_server_lock), MYFLOCK_NONE) < 0)
* Run pre-jail initialization.
*/
if (pre_init)
- pre_init();
+ pre_init(multi_server_name, multi_server_argv);
/*
* Optionally, restrict the damage that this process can do.
* Run post-jail initialization.
*/
if (post_init)
- post_init();
+ post_init(multi_server_name, multi_server_argv);
/*
* Are we running as a one-shot server with the client connection on
event_enable_read(MASTER_STATUS_FD, multi_server_abort, (char *) 0);
close_on_exec(MASTER_STATUS_FD, CLOSE_ON_EXEC);
while (var_use_limit == 0 || use_count < var_use_limit || client_count > 0) {
- delay = loop ? loop() : -1;
+ delay = loop ? loop(multi_server_name, multi_server_argv) : -1;
if (multi_server_lock != 0
&& myflock(vstream_fileno(multi_server_lock), MYFLOCK_EXCLUSIVE) < 0)
msg_fatal("select lock: %m");
/* order as specified, and multiple instances of the same type
/* are allowed. Raw parameters are not subjected to $name
/* evaluation.
-/* .IP "MAIL_SERVER_PRE_INIT (void *(void))"
+/* .IP "MAIL_SERVER_PRE_INIT (void *(char *service_name char **argv))"
/* A pointer to a function that is called once
/* by the skeleton after it has read the global configuration file
/* and after it has processed command-line arguments, but before
/* the skeleton has optionally relinquished the process privileges.
-/* .IP "MAIL_SERVER_POST_INIT (void *(void))"
+/* .IP "MAIL_SERVER_POST_INIT (void *(char *service_name char **argv))"
/* A pointer to a function that is called once
/* by the skeleton after it has optionally relinquished the process
/* privileges, but before servicing client connection requests.
-/* .IP "MAIL_SERVER_LOOP (int *(void))"
+/* .IP "MAIL_SERVER_LOOP (int *(char *service_name char **argv))"
/* A pointer to function that is executed from
/* within the event loop, whenever an I/O or timer event has happened,
/* or whenever nothing has happened for a specified amount of time.
/* .IP "MAIL_SERVER_EXIT (void *(void))"
/* A pointer to function that is executed immediately before normal
/* process termination.
-/* .IP "MAIL_SERVER_PRE_ACCEPT (void *(void))"
+/* .IP "MAIL_SERVER_PRE_ACCEPT (void *(char *service_name char **argv))"
/* Function to be executed prior to accepting a new connection.
/* .PP
/* The var_use_limit variable limits the number of clients that
static char *single_server_name;
static char **single_server_argv;
static void (*single_server_accept) (int, char *);
-static void (*single_server_onexit) (void);
-static void (*single_server_pre_accept) (void);
+static void (*single_server_onexit) (char *, char **);
+static void (*single_server_pre_accept) (char *, char **);
static VSTREAM *single_server_lock;
/* single_server_exit - normal termination */
static NORETURN single_server_exit(void)
{
if (single_server_onexit)
- single_server_onexit();
+ single_server_onexit(single_server_name, single_server_argv);
exit(0);
}
time_left = event_cancel_timer(single_server_timeout, (char *) 0);
if (single_server_pre_accept)
- single_server_pre_accept();
+ single_server_pre_accept(single_server_name, single_server_argv);
fd = LOCAL_ACCEPT(listen_fd);
if (single_server_lock != 0
&& myflock(vstream_fileno(single_server_lock), MYFLOCK_NONE) < 0)
time_left = event_cancel_timer(single_server_timeout, (char *) 0);
if (single_server_pre_accept)
- single_server_pre_accept();
+ single_server_pre_accept(single_server_name, single_server_argv);
fd = inet_accept(listen_fd);
if (single_server_lock != 0
&& myflock(vstream_fileno(single_server_lock), MYFLOCK_NONE) < 0)
* Run pre-jail initialization.
*/
if (pre_init)
- pre_init();
+ pre_init(single_server_name, single_server_argv);
/*
* Optionally, restrict the damage that this process can do.
* Run post-jail initialization.
*/
if (post_init)
- post_init();
+ post_init(single_server_name, single_server_argv);
/*
* Are we running as a one-shot server with the client connection on
event_enable_read(MASTER_STATUS_FD, single_server_abort, (char *) 0);
close_on_exec(MASTER_STATUS_FD, CLOSE_ON_EXEC);
while (var_use_limit == 0 || use_count < var_use_limit) {
- delay = loop ? loop() : -1;
+ delay = loop ? loop(single_server_name, single_server_argv) : -1;
if (single_server_lock != 0
&& myflock(vstream_fileno(single_server_lock), MYFLOCK_EXCLUSIVE) < 0)
msg_fatal("select lock: %m");
/* order as specified, and multiple instances of the same type
/* are allowed. Raw parameters are not subjected to $name
/* evaluation.
-/* .IP "MAIL_SERVER_PRE_INIT (void *(void))"
+/* .IP "MAIL_SERVER_PRE_INIT (void *(char *service_name, char **argv))"
/* A pointer to a function that is called once
/* by the skeleton after it has read the global configuration file
/* and after it has processed command-line arguments, but before
/* the skeleton has optionally relinquished the process privileges.
-/* .IP "MAIL_SERVER_POST_INIT (void *(void))"
+/* .IP "MAIL_SERVER_POST_INIT (void *(char *service_name, char **argv))"
/* A pointer to a function that is called once
/* by the skeleton after it has optionally relinquished the process
/* privileges, but before servicing client connection requests.
-/* .IP "MAIL_SERVER_LOOP (int *(void))"
+/* .IP "MAIL_SERVER_LOOP (int *(char *service_name, char **argv))"
/* A pointer to function that is executed from
/* within the event loop, whenever an I/O or timer event has happened,
/* or whenever nothing has happened for a specified amount of time.
/* The result value of the function specifies how long to wait until
/* the next event. Specify -1 to wait for "as long as it takes".
-/* .IP "MAIL_SERVER_EXIT (void *(void))"
+/* .IP "MAIL_SERVER_EXIT (void *(char *service_name, char **argv))"
/* A pointer to function that is executed immediately before normal
/* process termination.
-/* .IP "MAIL_SERVER_PRE_ACCEPT (void *(void))"
+/* .IP "MAIL_SERVER_PRE_ACCEPT (void *(char *service_name, char **argv))"
/* Function to be executed prior to accepting a new request.
/* .PP
/* The var_use_limit variable limits the number of clients that
static char *trigger_server_name;
static char **trigger_server_argv;
static void (*trigger_server_accept) (int, char *);
-static void (*trigger_server_onexit) (void);
-static void (*trigger_server_pre_accept) (void);
+static void (*trigger_server_onexit) (char *, char **);
+static void (*trigger_server_pre_accept) (char *, char **);
static VSTREAM *trigger_server_lock;
/* trigger_server_exit - normal termination */
static NORETURN trigger_server_exit(void)
{
if (trigger_server_onexit)
- trigger_server_onexit();
+ trigger_server_onexit(trigger_server_name, trigger_server_argv);
exit(0);
}
* non-blocking so we won't get stuck when multiple processes wake up.
*/
if (trigger_server_pre_accept)
- trigger_server_pre_accept();
+ trigger_server_pre_accept(trigger_server_name, trigger_server_argv);
trigger_server_wakeup(listen_fd);
}
time_left = event_cancel_timer(trigger_server_timeout, (char *) 0);
if (trigger_server_pre_accept)
- trigger_server_pre_accept();
+ trigger_server_pre_accept(trigger_server_name, trigger_server_argv);
fd = LOCAL_ACCEPT(listen_fd);
if (trigger_server_lock != 0
&& myflock(vstream_fileno(trigger_server_lock), MYFLOCK_NONE) < 0)
* Run pre-jail initialization.
*/
if (pre_init)
- pre_init();
+ pre_init(trigger_server_name, trigger_server_argv);
/*
* Optionally, restrict the damage that this process can do.
* Run post-jail initialization.
*/
if (post_init)
- post_init();
+ post_init(trigger_server_name, trigger_server_argv);
/*
* Are we running as a one-shot server with the client connection on
event_enable_read(MASTER_STATUS_FD, trigger_server_abort, (char *) 0);
close_on_exec(MASTER_STATUS_FD, CLOSE_ON_EXEC);
while (var_use_limit == 0 || use_count < var_use_limit) {
- delay = loop ? loop() : -1;
+ delay = loop ? loop(trigger_server_name, trigger_server_argv) : -1;
if (trigger_server_lock != 0
&& myflock(vstream_fileno(trigger_server_lock), MYFLOCK_EXCLUSIVE) < 0)
msg_fatal("select lock: %m");
-TEXPAND_ATTR
-TFILE
-TFORWARD_INFO
--TFW_CONTEXT
-THEADER_OPTS
-THTABLE
-THTABLE_INFO
-TINET_ADDR_LIST
-TINT_TABLE
-TLOCAL_STATE
+-TMAC_EXP_CONTEXT
-TMAC_HEAD
-TMAC_PARSE
-TMAIL_PRINT
test: $(TESTPROG)
-update: ../bin/$(PROG)
+update: ../libexec/$(PROG)
-../bin/$(PROG): $(PROG)
- cp $(PROG) ../bin
+../libexec/$(PROG): $(PROG)
+ cp $(PROG) ../libexec
printfck: $(OBJS) $(PROG)
rm -rf printfck
/* drop_privileges - drop privileges most of the time */
-static void drop_privileges(void)
+static void drop_privileges(char *unused_name, char **unused_argv)
{
set_eugid(var_owner_uid, var_owner_gid);
}
-TEXPAND_ATTR
-TFILE
-TFORWARD_INFO
--TFW_CONTEXT
-THEADER_OPTS
-THTABLE
-THTABLE_INFO
-TINET_ADDR_LIST
-TINT_TABLE
-TLOCAL_STATE
+-TMAC_EXP_CONTEXT
-TMAC_HEAD
-TMAC_PARSE
-TMAIL_PRINT
test: $(TESTPROG)
-update: ../bin/$(PROG)
+update: ../libexec/$(PROG)
-../bin/$(PROG): $(PROG)
- cp $(PROG) ../bin
+../libexec/$(PROG): $(PROG)
+ cp $(PROG) ../libexec
printfck: $(OBJS) $(PROG)
rm -rf printfck
/* pre_accept - see if tables have changed */
-static void pre_accept(void)
+static void pre_accept(char *unused_name, char **unused_argv)
{
if (dict_changed()) {
msg_info("table has changed -- exiting");
/* drop_privileges - drop privileges most of the time */
-static void drop_privileges(void)
+static void drop_privileges(char *unused_name, char **unused_argv)
{
set_eugid(var_owner_uid, var_owner_gid);
}
-TEXPAND_ATTR
-TFILE
-TFORWARD_INFO
--TFW_CONTEXT
-THEADER_OPTS
-THTABLE
-THTABLE_INFO
-TINET_ADDR_LIST
-TINT_TABLE
-TLOCAL_STATE
+-TMAC_EXP_CONTEXT
-TMAC_HEAD
-TMAC_PARSE
-TMAIL_PRINT
-TEXPAND_ATTR
-TFILE
-TFORWARD_INFO
--TFW_CONTEXT
-THEADER_OPTS
-THTABLE
-THTABLE_INFO
-TINET_ADDR_LIST
-TINT_TABLE
-TLOCAL_STATE
+-TMAC_EXP_CONTEXT
-TMAC_HEAD
-TMAC_PARSE
-TMAIL_PRINT
-TEXPAND_ATTR
-TFILE
-TFORWARD_INFO
--TFW_CONTEXT
-THEADER_OPTS
-THTABLE
-THTABLE_INFO
-TINET_ADDR_LIST
-TINT_TABLE
-TLOCAL_STATE
+-TMAC_EXP_CONTEXT
-TMAC_HEAD
-TMAC_PARSE
-TMAIL_PRINT
-TEXPAND_ATTR
-TFILE
-TFORWARD_INFO
--TFW_CONTEXT
-THEADER_OPTS
-THTABLE
-THTABLE_INFO
-TINET_ADDR_LIST
-TINT_TABLE
-TLOCAL_STATE
+-TMAC_EXP_CONTEXT
-TMAC_HEAD
-TMAC_PARSE
-TMAIL_PRINT
-TEXPAND_ATTR
-TFILE
-TFORWARD_INFO
--TFW_CONTEXT
-THEADER_OPTS
-THTABLE
-THTABLE_INFO
-TINET_ADDR_LIST
-TINT_TABLE
-TLOCAL_STATE
+-TMAC_EXP_CONTEXT
-TMAC_HEAD
-TMAC_PARSE
-TMAIL_PRINT
-TEXPAND_ATTR
-TFILE
-TFORWARD_INFO
--TFW_CONTEXT
-THEADER_OPTS
-THTABLE
-THTABLE_INFO
-TINET_ADDR_LIST
-TINT_TABLE
-TLOCAL_STATE
+-TMAC_EXP_CONTEXT
-TMAC_HEAD
-TMAC_PARSE
-TMAIL_PRINT
-TEXPAND_ATTR
-TFILE
-TFORWARD_INFO
--TFW_CONTEXT
-THEADER_OPTS
-THTABLE
-THTABLE_INFO
-TINET_ADDR_LIST
-TINT_TABLE
-TLOCAL_STATE
+-TMAC_EXP_CONTEXT
-TMAC_HEAD
-TMAC_PARSE
-TMAIL_PRINT
-TEXPAND_ATTR
-TFILE
-TFORWARD_INFO
--TFW_CONTEXT
-THEADER_OPTS
-THTABLE
-THTABLE_INFO
-TINET_ADDR_LIST
-TINT_TABLE
-TLOCAL_STATE
+-TMAC_EXP_CONTEXT
-TMAC_HEAD
-TMAC_PARSE
-TMAIL_PRINT
-TEXPAND_ATTR
-TFILE
-TFORWARD_INFO
--TFW_CONTEXT
-THEADER_OPTS
-THTABLE
-THTABLE_INFO
-TINET_ADDR_LIST
-TINT_TABLE
-TLOCAL_STATE
+-TMAC_EXP_CONTEXT
-TMAC_HEAD
-TMAC_PARSE
-TMAIL_PRINT
-TEXPAND_ATTR
-TFILE
-TFORWARD_INFO
--TFW_CONTEXT
-THEADER_OPTS
-THTABLE
-THTABLE_INFO
-TINET_ADDR_LIST
-TINT_TABLE
-TLOCAL_STATE
+-TMAC_EXP_CONTEXT
-TMAC_HEAD
-TMAC_PARSE
-TMAIL_PRINT
-TEXPAND_ATTR
-TFILE
-TFORWARD_INFO
--TFW_CONTEXT
-THEADER_OPTS
-THTABLE
-THTABLE_INFO
-TINET_ADDR_LIST
-TINT_TABLE
-TLOCAL_STATE
+-TMAC_EXP_CONTEXT
-TMAC_HEAD
-TMAC_PARSE
-TMAIL_PRINT
test: $(TESTPROG)
-update: ../bin/$(PROG)
+update: ../libexec/$(PROG)
-../bin/$(PROG): $(PROG)
- cp $(PROG) ../bin
+../libexec/$(PROG): $(PROG)
+ cp $(PROG) ../libexec
printfck: $(OBJS) $(PROG)
rm -rf printfck
/* qmgr_loop - queue manager main loop */
-static int qmgr_loop(void)
+static int qmgr_loop(char *unused_name, char **unused_argv)
{
char *in_path = 0;
char *df_path = 0;
/* pre_accept - see if tables have changed */
-static void pre_accept(void)
+static void pre_accept(char *unused_name, char **unused_argv)
{
if (dict_changed()) {
msg_info("table has changed -- exiting");
/* qmgr_pre_init - pre-jail initialization */
-static void qmgr_pre_init(void)
+static void qmgr_pre_init(char *unused_name, char **unused_argv)
{
if (*var_relocated_maps)
qmgr_relocated = maps_create("relocated", var_relocated_maps,
/* qmgr_post_init - post-jail initialization */
-static void qmgr_post_init(void)
+static void qmgr_post_init(char *unused_name, char **unused_argv)
{
/*
-TEXPAND_ATTR
-TFILE
-TFORWARD_INFO
--TFW_CONTEXT
-THEADER_OPTS
-THTABLE
-THTABLE_INFO
-TINET_ADDR_LIST
-TINT_TABLE
-TLOCAL_STATE
+-TMAC_EXP_CONTEXT
-TMAC_HEAD
-TMAC_PARSE
-TMAIL_PRINT
-TEXPAND_ATTR
-TFILE
-TFORWARD_INFO
--TFW_CONTEXT
-THEADER_OPTS
-THTABLE
-THTABLE_INFO
-TINET_ADDR_LIST
-TINT_TABLE
-TLOCAL_STATE
+-TMAC_EXP_CONTEXT
-TMAC_HEAD
-TMAC_PARSE
-TMAIL_PRINT
test: $(TESTPROG)
-update: ../bin/$(PROG)
+update: ../libexec/$(PROG)
-../bin/$(PROG): $(PROG)
- cp $(PROG) ../bin
+../libexec/$(PROG): $(PROG)
+ cp $(PROG) ../libexec
printfck: $(OBJS) $(PROG)
rm -rf printfck
-TEXPAND_ATTR
-TFILE
-TFORWARD_INFO
--TFW_CONTEXT
-THEADER_OPTS
-THTABLE
-THTABLE_INFO
-TINET_ADDR_LIST
-TINT_TABLE
-TLOCAL_STATE
+-TMAC_EXP_CONTEXT
-TMAC_HEAD
-TMAC_PARSE
-TMAIL_PRINT
test: $(TESTPROG)
-update: ../bin/$(PROG)
+update: ../libexec/$(PROG)
-../bin/$(PROG): $(PROG)
- cp $(PROG) ../bin
+../libexec/$(PROG): $(PROG)
+ cp $(PROG) ../libexec
printfck: $(OBJS) $(PROG)
rm -rf printfck
}
}
+/* pre_init - pre-jail initialization */
+
+static void pre_init(char *unused_name, char **unused_argv)
+{
+ debug_peer_init();
+}
+
/* pre_accept - see if tables have changed */
-static void pre_accept(void)
+static void pre_accept(char *unused_name, char **unused_argv)
{
if (dict_changed()) {
msg_info("table has changed -- exiting");
MAIL_SERVER_INT_TABLE, int_table,
MAIL_SERVER_STR_TABLE, str_table,
MAIL_SERVER_BOOL_TABLE, bool_table,
- MAIL_SERVER_PRE_INIT, debug_peer_init,
+ MAIL_SERVER_PRE_INIT, pre_init,
MAIL_SERVER_PRE_ACCEPT, pre_accept,
0);
}
-TEXPAND_ATTR
-TFILE
-TFORWARD_INFO
--TFW_CONTEXT
-THEADER_OPTS
-THTABLE
-THTABLE_INFO
-TINET_ADDR_LIST
-TINT_TABLE
-TLOCAL_STATE
+-TMAC_EXP_CONTEXT
-TMAC_HEAD
-TMAC_PARSE
-TMAIL_PRINT
test: $(TESTPROG)
-update: ../bin/$(PROG)
+update: ../libexec/$(PROG)
-../bin/$(PROG): $(PROG)
- cp $(PROG) ../bin
+../libexec/$(PROG): $(PROG)
+ cp $(PROG) ../libexec
SMTPD_CHECK_OBJ = smtpd_state.o
/* pre_accept - see if tables have changed */
-static void pre_accept(void)
+static void pre_accept(char *unused_name, char **unused_argv)
{
if (dict_changed()) {
msg_info("lookup table has changed -- exiting");
/* post_jail_init - post-jail initialization */
-static void post_jail_init(void)
+static void post_jail_init(char *unused_name, char **unused_argv)
{
/*
/* pre_jail_init - pre-jail initialization */
-static void pre_jail_init(void)
+static void pre_jail_init(char *unused_name, char **unused_argv)
{
/*
-TEXPAND_ATTR
-TFILE
-TFORWARD_INFO
--TFW_CONTEXT
-THEADER_OPTS
-THTABLE
-THTABLE_INFO
-TINET_ADDR_LIST
-TINT_TABLE
-TLOCAL_STATE
+-TMAC_EXP_CONTEXT
-TMAC_HEAD
-TMAC_PARSE
-TMAIL_PRINT
-TEXPAND_ATTR
-TFILE
-TFORWARD_INFO
--TFW_CONTEXT
-THEADER_OPTS
-THTABLE
-THTABLE_INFO
-TINET_ADDR_LIST
-TINT_TABLE
-TLOCAL_STATE
+-TMAC_EXP_CONTEXT
-TMAC_HEAD
-TMAC_PARSE
-TMAIL_PRINT
LIBS = ../lib/libmaster.a ../lib/libglobal.a ../lib/libutil.a
LIB_DIR = ../lib
INC_DIR = ../include
-BIN_DIR = ../bin
+BIN_DIR = ../libexec
.c.o:; $(CC) $(CFLAGS) -c $*.c
/* pre_accept - see if tables have changed */
-static void pre_accept(void)
+static void pre_accept(char *unused_name, char **unused_argv)
{
if (dict_changed()) {
msg_info("table has changed -- exiting");
/* pre_jail_init - initialize before entering chroot jail */
-static void pre_jail_init(void)
+static void pre_jail_init(char *unused_name, char **unused_argv)
{
command = vstring_alloc(100);
rewrite_init();
-TEXPAND_ATTR
-TFILE
-TFORWARD_INFO
--TFW_CONTEXT
-THEADER_OPTS
-THTABLE
-THTABLE_INFO
-TINET_ADDR_LIST
-TINT_TABLE
-TLOCAL_STATE
+-TMAC_EXP_CONTEXT
-TMAC_HEAD
-TMAC_PARSE
-TMAIL_PRINT
unsafe.c username.c valid_hostname.c vbuf.c vbuf_print.c \
vstream.c vstream_popen.c vstring.c vstring_vstream.c writable.c \
write_buf.c write_wait.c dict_unix.c dict_pcre.c stream_listen.c \
- stream_connect.c stream_trigger.c dict_regexp.c watch_fd.c \
+ stream_connect.c stream_trigger.c dict_regexp.c mac_expand.c \
clean_env.c
OBJS = argv.o argv_split.o attr.o basename.o binhash.o chroot_uid.o \
close_on_exec.o concatenate.o dict.o dict_db.o dict_dbm.o \
unsafe.o username.o valid_hostname.o vbuf.o vbuf_print.o \
vstream.o vstream_popen.o vstring.o vstring_vstream.o writable.o \
write_buf.o write_wait.o dict_unix.o dict_pcre.o stream_listen.o \
- stream_connect.o stream_trigger.o dict_regexp.o watch_fd.o \
+ stream_connect.o stream_trigger.o dict_regexp.o mac_expand.o \
clean_env.o
HDRS = argv.h attr.h binhash.h chroot_uid.h connect.h dict.h dict_db.h \
dict_dbm.h dict_env.h dict_ht.h dict_ldap.h dict_ni.h dict_nis.h \
sigdelay.h split_at.h stat_as.h stringops.h sys_defs.h \
timed_connect.h timed_wait.h trigger.h username.h valid_hostname.h \
vbuf.h vbuf_print.h vstream.h vstring.h vstring_vstream.h \
- dict_unix.h dict_pcre.h dict_regexp.h watch_fd.h clean_env.h
+ dict_unix.h dict_pcre.h dict_regexp.h mac_expand.h clean_env.h
TESTSRC = fifo_open.c fifo_rdwr_bug.c fifo_rdonly_bug.c select_bug.c \
stream_test.c
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
fifo_rdwr_bug fifo_trigger fsspace fullname inet_addr_host \
inet_addr_local mac_parse make_dirs msg_syslog \
mystrtok peer_name sigdelay translit valid_hostname vstream_popen \
- vstring vstring_vstream doze select_bug stream_test
+ vstring vstring_vstream doze select_bug stream_test mac_expand
LIB_DIR = ../lib
INC_DIR = ../include
$(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(SYSLIBS)
mv junk $@.o
+mac_expand: $(LIB)
+ mv $@.o junk
+ $(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(SYSLIBS)
+ mv junk $@.o
+
depend: $(MAKES)
(sed '1,/^# do not edit/!d' Makefile.in; \
set -e; for i in [a-z][a-z0-9]*.c; do \
stream_test: stream_test.c $(LIB)
$(CC) $(CFLAGS) -o $@ $@.c $(LIB) $(SYSLIBS)
-tests: valid_hostname_test
+tests: valid_hostname_test mac_expand_test
valid_hostname_test: valid_hostname valid_hostname.in valid_hostname.ref
./valid_hostname <valid_hostname.in 2>valid_hostname.tmp
diff valid_hostname.ref valid_hostname.tmp
rm -f valid_hostname.tmp
+mac_expand_test: mac_expand mac_expand.in mac_expand.ref
+ ./mac_expand <mac_expand.in >mac_expand.tmp
+ diff mac_expand.ref mac_expand.tmp
+ rm -f mac_expand.tmp
+
# do not edit below this line - it is generated by 'make depend'
argv.o: argv.c
argv.o: mymalloc.h
lstat_as.o: msg.h
lstat_as.o: set_eugid.h
lstat_as.o: lstat_as.h
+mac_expand.o: mac_expand.c
+mac_expand.o: sys_defs.h
+mac_expand.o: msg.h
+mac_expand.o: vstring.h
+mac_expand.o: vbuf.h
+mac_expand.o: mymalloc.h
+mac_expand.o: htable.h
+mac_expand.o: mac_parse.h
+mac_expand.o: mac_expand.h
mac_parse.o: mac_parse.c
mac_parse.o: sys_defs.h
mac_parse.o: msg.h
vstring_vstream.o: vbuf.h
vstring_vstream.o: vstream.h
vstring_vstream.o: vstring_vstream.h
-watch_fd.o: watch_fd.c
-watch_fd.o: sys_defs.h
-watch_fd.o: msg.h
-watch_fd.o: binhash.h
-watch_fd.o: mymalloc.h
-watch_fd.o: watch_fd.h
writable.o: writable.c
writable.o: sys_defs.h
writable.o: msg.h
dict_dbm->dict.lookup = dict_dbm_lookup;
dict_dbm->dict.update = dict_dbm_update;
dict_dbm->dict.close = dict_dbm_close;
- dict_dbm->dict.fd = dbm_dirfno(dbm);
+ dict_dbm->dict.fd = dbm_pagfno(dbm);
if (fstat(dict_dbm->dict.fd, &st) < 0)
msg_fatal("dict_dbm_open: fstat: %m");
dict_dbm->dict.mtime = st.st_mtime;
--- /dev/null
+/*++
+/* NAME
+/* mac_expand 3
+/* SUMMARY
+/* attribute expansion
+/* SYNOPSIS
+/* #include <mac_expand.h>
+/*
+/* int mac_expand(result, pattern, flags, key, ...)
+/* VSTRING *result;
+/* const char *pattern;
+/* int flags;
+/* int key;
+/* DESCRIPTION
+/* mac_expand() expands $name instances in \fBpattern\fR
+/* and stores the result into \fBresult\fR.
+/*
+/* The following expansions are done:
+/* .IP "$name, ${name}, $(name)"
+/* The result is the value of the named parameter. Optionally, the
+/* result is subjected to further expansions.
+/* .IP "${name?text}, $(name?text)"
+/* If the named parameter is defined, the result is the given text,
+/* after another iteration of $name expansion. Otherwise, the result is
+/* empty.
+/* .IP "${name:text}, $(name:text)"
+/* If the named parameter is undefined, the result is the given text,
+/* after another iteration of $name expansion. Otherwise, the result is
+/* empty.
+/* .PP
+/* Arguments:
+/* .IP result
+/* Storage for the result of expansion. The result is not truncated
+/* upon entry.
+/* .IP pattern
+/* The string to be expanded.
+/* .IP flags
+/* Bit-wise OR of zero or more of the following:
+/* .RS
+/* .IP MAC_EXP_FLAG_RECURSE
+/* Expand $name recursively.
+/* .RE
+/* The constant MAC_EXP_FLAG_NONE specifies a manifest null value.
+/* .IP key
+/* The attribute information is specified as a null-terminated list.
+/* Attributes are defined left to right; only the last definition
+/* of an attribute is remembered.
+/* The following keys are understood (types of arguments indicated
+/* in parentheses):
+/* .RS
+/* .IP "MAC_EXP_ARG_ATTR (char *, char *)"
+/* The next two arguments specify an attribute name and its attribute
+/* string value. Specify a null string value for an attribute that is
+/* known but unset.
+/* .IP "MAC_EXP_ARG_TABLE (HTABLE *)"
+/* The next argument is a hash table with attribute names and values.
+/* Specify a null string value for an attribute that is known but unset.
+/* .IP "MAC_EXP_ARG_FILTER (char *)"
+/* The next argument specifies a null-terminated list of characters
+/* that are allowed to appear in $name expansions. By default, illegal
+/* characters are replaced by underscore. Only the last specified
+/* filter takes effect.
+/* .IP "MAC_EXP_ARG_CLOBBER (int)"
+/* Character value to be used when the result of expansion is not
+/* allowed according to the MAC_EXP_ARG_FILTER argument. Only the
+/* last specified replacement value takes effect.
+/* .RE
+/* .IP MAC_EXP_ARG_END
+/* A manifest constant that indicates the end of the argument list.
+/* DIAGNOSTICS
+/* Fatal errors: out of memory. Warnings: syntax errors, unreasonable
+/* macro nesting.
+/*
+/* The result value is the binary OR of zero or more of the following:
+/* .IP MAC_EXP_FLAG_UNDEF
+/* The pattern contains a reference to an unknown parameter or to
+/* a parameter whose value is not defined.
+/* A zero-length string was used as replacement.
+/* SEE ALSO
+/* mac_parse(3) locate macro references in string.
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* IBM T.J. Watson Research
+/* P.O. Box 704
+/* Yorktown Heights, NY 10598, USA
+/*--*/
+
+/* System library. */
+
+#include <sys_defs.h>
+#include <setjmp.h>
+#include <ctype.h>
+#include <string.h>
+
+/* Utility library. */
+
+#include <msg.h>
+#include <vstring.h>
+#include <mymalloc.h>
+#include <htable.h>
+#include <mac_parse.h>
+#include <mac_expand.h>
+
+ /*
+ * Little helper structure.
+ */
+typedef struct {
+ HTABLE *table; /* private symbol table */
+ VSTRING *result; /* result buffer */
+ const char *filter; /* safe character list */
+ int clobber; /* safe replacement */
+ int flags; /* findings, features */
+ int level; /* nesting level */
+ jmp_buf jbuf; /* escape */
+} MAC_EXP_CONTEXT;
+
+/* mac_expand_callback - callback for mac_parse */
+
+static void mac_expand_callback(int type, VSTRING *buf, char *ptr)
+{
+ char *myname = "mac_expand_callback";
+ MAC_EXP_CONTEXT *context = (MAC_EXP_CONTEXT *) ptr;
+ HTABLE_INFO *ht;
+ char *text;
+ char *cp;
+ int ch;
+
+ if (context->level++ > 100) {
+ msg_warn("unreasonable macro call nesting: \"%s\"", vstring_str(buf));
+ longjmp(context->jbuf, 1);
+ }
+
+ /*
+ * $Name reference.
+ */
+ if (type == MAC_PARSE_VARNAME) {
+
+ /*
+ * Look for the ? or : delimiter. In case of a syntax error, return
+ * without doing damage. We do not have enough context to produce an
+ * understandable error message, so don't try.
+ */
+ for (cp = vstring_str(buf); (ch = *cp) != 0; cp++) {
+ if (ch == '?' || ch == ':') {
+ *cp++ = 0;
+ break;
+ }
+ if (!ISALNUM(ch) && ch != '_') {
+ msg_warn("macro name syntax error: \"%s\"", vstring_str(buf));
+ longjmp(context->jbuf, 1);
+ }
+ }
+
+ /*
+ * Look up the named parameter.
+ */
+ text = (ht = htable_locate(context->table, vstring_str(buf))) == 0 ?
+ 0 : ht->value;
+
+ /*
+ * Perform the requested substitution.
+ */
+ switch (ch) {
+ case '?':
+ if (text != 0)
+ mac_parse(cp, mac_expand_callback, (char *) context);
+ break;
+ case ':':
+ if (text == 0)
+ mac_parse(cp, mac_expand_callback, (char *) context);
+ break;
+ default:
+ if (text == 0) {
+ context->flags |= MAC_EXP_FLAG_UNDEF;
+ break;
+ }
+ if (context->filter) {
+ vstring_strcpy(buf, text);
+ text = vstring_str(buf);
+ for (cp = text; (cp += strspn(cp, context->filter))[0];)
+ *cp++ = context->clobber;
+ }
+ if (context->flags & MAC_EXP_FLAG_RECURSE)
+ mac_parse(text, mac_expand_callback, (char *) context);
+ else
+ vstring_strcat(context->result, text);
+ break;
+ }
+ }
+
+ /*
+ * Literal text.
+ */
+ else {
+ text = vstring_str(buf);
+ vstring_strcat(context->result, text);
+ }
+
+ /*
+ * Give the poor tester a clue of what is going on.
+ */
+ if (msg_verbose)
+ msg_info("%s: %s = %s", myname, vstring_str(buf),
+ text ? text : "(undef)");
+
+ context->level--;
+}
+
+/* mac_expand - expand $name instances */
+
+int mac_expand(VSTRING *result, const char *pattern, int flags, int key,...)
+{
+ MAC_EXP_CONTEXT context;
+ va_list ap;
+ HTABLE_INFO **ht_info;
+ HTABLE_INFO **ht;
+ HTABLE *table;
+ char *name;
+ char *value;
+
+#define HTABLE_CLOBBER(t, n, v) do { \
+ HTABLE_INFO *_ht; \
+ if ((_ht = htable_locate(t, n)) != 0) \
+ _ht->value = v; \
+ else \
+ htable_enter(t, n, v); \
+ } while(0);
+
+ /*
+ * Inititalize.
+ */
+ context.table = htable_create(0);
+ context.result = result;
+ context.flags = flags;
+ context.filter = 0;
+ context.clobber = '_';
+ context.level = 0;
+
+ /*
+ * Stash away the attributes.
+ */
+ for (va_start(ap, key); key != 0; key = va_arg(ap, int)) {
+ switch (key) {
+ case MAC_EXP_ARG_ATTR:
+ name = va_arg(ap, char *);
+ value = va_arg(ap, char *);
+ HTABLE_CLOBBER(context.table, name, value);
+ break;
+ case MAC_EXP_ARG_TABLE:
+ table = va_arg(ap, HTABLE *);
+ ht_info = htable_list(table);
+ for (ht = ht_info; *ht; ht++)
+ HTABLE_CLOBBER(context.table, ht[0]->key, ht[0]->value);
+ myfree((char *) ht_info);
+ break;
+ case MAC_EXP_ARG_FILTER:
+ context.filter = va_arg(ap, char *);
+ break;
+ case MAC_EXP_ARG_CLOBBER:
+ context.clobber = va_arg(ap, int);
+ break;
+ }
+ }
+ va_end(ap);
+
+ /*
+ * Do the substitutions.
+ */
+ if (setjmp(context.jbuf) == 0)
+ mac_parse(pattern, mac_expand_callback, (char *) &context);
+ VSTRING_TERMINATE(result);
+
+ /*
+ * Clean up.
+ */
+ htable_free(context.table, (void (*) (char *)) 0);
+ return (context.flags & MAC_EXP_FLAG_UNDEF);
+}
+
+#ifdef TEST
+
+ /*
+ * This code certainly deserves a stand-alone test program.
+ */
+#include <stringops.h>
+#include <vstream.h>
+#include <vstring_vstream.h>
+
+static void nfree(char *ptr)
+{
+ if (ptr)
+ myfree(ptr);
+}
+
+int main(int unused_argc, char **unused_argv)
+{
+ VSTRING *buf = vstring_alloc(100);
+ VSTRING *result = vstring_alloc(100);
+ char *cp;
+ char *name;
+ char *value;
+ HTABLE *table;
+ int stat;
+
+ while (!vstream_feof(VSTREAM_IN)) {
+
+ table = htable_create(0);
+
+ /*
+ * Read a block of definitions, terminated with an empty line.
+ */
+ while (vstring_get_nonl(buf, VSTREAM_IN) != VSTREAM_EOF) {
+ if (VSTRING_LEN(buf) == 0)
+ break;
+ cp = vstring_str(buf);
+ name = mystrtok(&cp, " \t\r\n=");
+ value = mystrtok(&cp, " \t\r\n=");
+ htable_enter(table, name, value ? mystrdup(value) : 0);
+ }
+
+ /*
+ * Read a block of patterns, terminated with an empty line or EOF.
+ */
+ while (vstring_get_nonl(buf, VSTREAM_IN) != VSTREAM_EOF) {
+ if (VSTRING_LEN(buf) == 0)
+ break;
+ cp = vstring_str(buf);
+ VSTRING_RESET(result);
+ stat = mac_expand(result, vstring_str(buf), MAC_EXP_FLAG_NONE,
+ MAC_EXP_ARG_TABLE, table,
+ MAC_EXP_ARG_END);
+ vstream_printf("stat=%d result=%s\n", stat, vstring_str(result));
+ vstream_fflush(VSTREAM_OUT);
+ }
+ htable_free(table, nfree);
+ vstream_printf("\n");
+ }
+
+ /*
+ * Clean up.
+ */
+ vstring_free(buf);
+ vstring_free(result);
+ exit(0);
+}
+
+#endif
--- /dev/null
+#ifndef _MAC_EXPAND_H_INCLUDED_
+#define _MAC_EXPAND_H_INCLUDED_
+
+/*++
+/* NAME
+/* mac_expand 3h
+/* SUMMARY
+/* expand macro references in string
+/* SYNOPSIS
+/* #include <mac_expand.h>
+ DESCRIPTION
+ .nf
+
+ /*
+ * Utility library.
+ */
+#include <vstring.h>
+
+ /*
+ * External interface.
+ */
+#define MAC_EXP_FLAG_NONE (0)
+#define MAC_EXP_FLAG_UNDEF (1<<0)
+#define MAC_EXP_FLAG_RECURSE (1<<1)
+
+#define MAC_EXP_ARG_END 0
+#define MAC_EXP_ARG_ATTR 1
+#define MAC_EXP_ARG_TABLE 2
+#define MAC_EXP_ARG_FILTER 3
+#define MAC_EXP_ARG_CLOBBER 4
+
+extern int mac_expand(VSTRING *, const char *, int, int,...);
+
+/* 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
--- /dev/null
+name1 = name1-value
+name2 =
+
+${name1?name 1 defined, |$name1|$name2|}
+${name1:name 1 undefined, |$name1|$name2|}
+${name2?name 2 defined, |$name1|$name2|}
+${name2:name 2 undefined, |$name1|$name2|}
+|$name1|$name2|
+$(name1
+$(name )
+
+name2 = name2-value
+
+${name1?name 1 defined, |$name1|$name2|}
+${name1:name 1 undefined, |$name1|$name2|}
+${name2?name 2 defined, |$name1|$name2|}
+${name2:name 2 undefined, |$name1|$name2|}
+|$name1|$name2|
--- /dev/null
+stat=1 result=name 1 defined, |name1-value||
+stat=0 result=
+stat=0 result=
+stat=1 result=name 2 undefined, |name1-value||
+stat=1 result=|name1-value||
+stat=0 result=name1-value
+stat=0 result=
+
+stat=0 result=
+stat=1 result=name 1 undefined, ||name2-value|
+stat=1 result=name 2 defined, ||name2-value|
+stat=0 result=
+stat=1 result=||name2-value|
/* SEE ALSO
/* dict(3) dictionary interface.
/* DIAGNOSTICS
-/* Fatal errors: out of memory, malformed macro name.
+/* Fatal errors: out of memory. malformed macro name.
/* LICENSE
/* .ad
/* .fi
level = 1;
vp += 1;
for (ep = vp; level > 0; ep++) {
- if (*ep == 0)
- msg_fatal("incomplete macro: %s", value);
+ if (*ep == 0) {
+ msg_warn("truncated macro reference: \"%s\"", value);
+ break;
+ }
if (*ep == *pp)
level++;
if (*ep == close_paren[pp - open_paren])
level--;
}
- vstring_strncat(buf, vp, ep - vp - 1);
+ vstring_strncat(buf, vp, level > 0 ? ep - vp : ep - vp - 1);
vp = ep;
} else { /* plain $x */
SKIP(vp, ep, ISALNUM(*ep) || *ep == '_');
vp = ep;
}
if (VSTRING_LEN(buf) == 0)
- msg_fatal("empty macro name: %s", value);
+ msg_warn("empty macro name: \"%s\"", value);
MAC_PARSE_ACTION(MAC_PARSE_VARNAME, buf, context);
}
}
+++ /dev/null
-/*++
-/* NAME
-/* watch_fd 3
-/* SUMMARY
-/* monitor file descriptors for change
-/* SYNOPSIS
-/* #include <watch_fd.h>
-/*
-/* void watch_fd_register(fd)
-/* int fd;
-/*
-/* void watch_fd_remove(fd)
-/* int fd;
-/*
-/* int watch_fd_changed()
-/* DESCRIPTION
-/* This module monitors file modification times of arbitrary file
-/* descriptors.
-/*
-/* watch_fd_register() records information about the specified
-/* file descriptor.
-/*
-/* watch_fd_remove() releases storage allocated by watch_fd_register().
-/*
-/* watch_fd_changed() returns non-zero if any of the registered
-/* SEE ALSO
-/* msg(3) diagnostics interface
-/* DIAGNOSTICS
-/* Problems are reported via the msg(3) diagnostics routines:
-/* the requested amount of memory is not available; improper use
-/* is detected; other fatal errors.
-/* LICENSE
-/* .ad
-/* .fi
-/* The Secure Mailer license must be distributed with this software.
-/* AUTHOR(S)
-/* Wietse Venema
-/* IBM T.J. Watson Research
-/* P.O. Box 704
-/* Yorktown Heights, NY 10598, USA
-/*--*/
-
-/* System library. */
-
-#include <sys_defs.h>
-#include <sys/stat.h>
-
-/* Utility library. */
-
-#include <msg.h>
-#include <binhash.h>
-#include <mymalloc.h>
-#include <watch_fd.h>
-
-/* Application-specific. */
-
-typedef struct {
- int fd; /* file descriptor */
- time_t mtime; /* initial modification time */
-} WATCH_FD;
-
-static BINHASH *watch_fd_table;
-
-/* watch_fd_register - register file descriptor */
-
-void watch_fd_register(int fd)
-{
- char *myname = "watch_fd_enter";
- WATCH_FD *info;
- struct stat st;
-
- if (fstat(fd, &st) < 0)
- msg_fatal("%s: fstat: %m", myname);
-
- info = (WATCH_FD *) mymalloc(sizeof(*info));
- info->fd = fd;
- info->mtime = st.st_mtime;
-
- if (watch_fd_table == 0)
- watch_fd_table = binhash_create(0);
- if (binhash_find(watch_fd_table, (char *) &fd, sizeof(fd)))
- msg_panic("%s: entry %d exists", myname, fd);
- binhash_enter(watch_fd_table, (char *) &fd, sizeof(fd), (char *) info);
-}
-
-/* watch_fd_remove - remove file descriptor */
-
-void watch_fd_remove(int fd)
-{
- binhash_delete(watch_fd_table, (char *) &fd, sizeof(fd), myfree);
-}
-
-/* watch_fd_changed - see if any file has changed */
-
-int watch_fd_changed(void)
-{
- char *myname = "watch_fd_changed";
- struct stat st;
- BINHASH_INFO **ht_info_list;
- BINHASH_INFO **ht;
- BINHASH_INFO *h;
- WATCH_FD *info;
- int status;
-
- ht_info_list = binhash_list(watch_fd_table);
- for (status = 0, ht = ht_info_list; status == 0 && (h = *ht) != 0; ht++) {
- info = (WATCH_FD *) h->value;
- if (fstat(info->fd, &st) < 0)
- msg_fatal("%s: fstat: %m", myname);
- status = (st.st_mtime != info->mtime);
- }
- myfree((char *) ht_info_list);
- return (status);
-}
+++ /dev/null
-#ifndef _WATCH_FD_H_INCLUDED_
-#define _WATCH_FD_H_INCLUDED_
-
-/*++
-/* NAME
-/* watch_fd 3h
-/* SUMMARY
-/* monitor file descriptors for change
-/* SYNOPSIS
-/* #include "watch_fd.h"
- DESCRIPTION
- .nf
-
- /*
- * External interface.
- */
-extern void watch_fd_register(int);
-extern void watch_fd_remove(int);
-extern int watch_fd_changed(void);
-
-/* 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