-TLMTP_STATE
-TLOCAL_EXP
-TLOCAL_STATE
+-TLOGWRITER
-TLONG_NAME_MASK
-TMAC_EXP_CONTEXT
-TMAC_EXP_OP_INFO
-Tgeneral_name_stack_t
-Tiana_digest
-Toff_t
+-Tpem_load_state_t
-Tregex_t
-Tregmatch_t
-Tsasl_conn_t
-Ttime_t
-Ttlsa_filter
-Tx509_stack_t
--Tpem_load_state_t
dict_open.c, and updated the -F description in the postmap
manpage. Files: util/dict_open.c, postmap/postmap.c.
+20190121
+
+ Logging: support for internal logging file, without using
+ syslog (it uses the new postlogd daemon instead). This
+ solves a usability problem for MacOS, may help getting
+ around systemd, and solves 99% of the problem for logging
+ to stdout in a container (hopefully we have 100% soon).
+ Enable by setting, for example, "maillog_file =
+ /var/log/postfix.log"). This works fine for daemons, and
+ with some limitations for non-daemon programs. See
+ RELEASE_NOTES for more details. Files: conf/master.cf,
+ conf/post-install, conf/postfix-files, conf/postfix-script,
+ mantools/postlink, proto/master, proto/postconf.proto,
+ global/mail_params.c, global/mail_params.h, global/mail_proto.h,
+ global/maillog_client.c, global/maillog_client.h,
+ master/dgram_server.c, master/event_server.c, master/mail_server.h,
+ master/master.c, master/master.h, master/master_ent.c,
+ master/master_listen.c, master/master_proto.h,
+ master/master_wakeup.c, master/multi_server.c,
+ master/single_server.c, master/trigger_server.c,
+ postalias/postalias.c, postconf/postconf_master.c,
+ postdrop/postdrop.c, postfix/postfix.c, postkick/postkick.c,
+ postlog/postlog.c, postlogd/postlogd.c, postmap/postmap.c,
+ postmulti/postmulti.c, postqueue/postqueue.c,
+ postsuper/postsuper.c, sendmail/sendmail.c, util/connect.h,
+ util/listen.h, util/logwriter.c, util/logwriter.h,
+ util/msg_logger.c, util/msg_logger.h, util/msg_output.c,
+ util/msg_output.h, util/unix_dgram_connect.c,
+ util/unix_dgram_listen.c.
+
+ Safety: temporary postlogd fix to avoid recursion when main.cf
+ has "maillog_file =" but master(8) still still tells its child
+ processes to send logs to postlogd. File: postlogd/postlogd.c.
+
+20190126
+
+ Safety: Postfix programs will log to either syslog or postlog
+ but not both; and postlogd forwards postlog logging to
+ syslog, when a configuration change removes the maillog_file
+ pathname, but some programs still use the old configuration.
+ Files: util/msg_syslog.[hc], util/msg_logger.c,
+ global/maillog_client.c, postlogd/postlogd.c,
+
+ Bugfix (introduced: Postfix 20110109, Postfix 2.10): watchdog
+ pipe file descriptor leak. This pipe provides one source
+ of liveness, data from this pipe is discarded, and therefore
+ this does not enable privilege escalation or DOS. File:
+ util/watchdog.c.
+
+ Feature: stdout logging support; requires "postfix start-fg"
+ and "maillog_file = /dev/stdout". Files: master/master.c,
+ conf/postfix-script.
+
20190127
+ Safety: when maillog_file is specified, 'postfix check' now
+ requires that the postlog service is enabled in master.cf.
+ Otherwise 'postfix start' etc. will log a fatal error. File:
+ conf/postfix-script.
+
Documentation: added policy_context example. File:
proto/SMTPD_POLICY_README.html.
+
+20190128
+
+ Testing: run libtls tests under Valgrind. File tls/Makefile.in.
src/postsuper src/qmqpd src/spawn src/flush src/verify \
src/virtual src/proxymap src/anvil src/scache src/discard src/tlsmgr \
src/postmulti src/postscreen src/dnsblog src/tlsproxy \
- src/posttls-finger
+ src/posttls-finger src/postlogd
MANDIRS = proto man html
LIBEXEC = libexec/post-install libexec/postfix-script libexec/postfix-wrapper \
libexec/postmulti-script libexec/postfix-tls-script
[TODO: summary of SNI and chain-file support]
+Incompatible changes with snapshot 20190126-nonprod
+====================================================
+
+This introduces a new master.cf service type 'unix-dgram' that is
+used by the new postlogd(8) daemon. This type is not supported by
+older Postfix versions. Before backing out to an Postfix 3.3 or
+earlier, edit the master.cf file and remove the postlog entry.
+
+Major changes with snapshot 20190126-nonprod
+============================================
+
+Support for logging to file or stdout. This disables syslog logging.
+
+- Logging to file solves a usability problem for MacOS users, and
+ may also be useful on LINUX when systemd is getting in the way.
+
+- Logging to stdout is useful when Postfix runs in a container, as
+ it eliminates a syslogd dependency.
+
+To enable Postfix logging to file or stdout:
+--------------------------------------------
+
+Add the following line to master.cf (no whitespace at the start of the line):
+ postlog unix-dgram n - n - 1 postlogd
+
+To write logs to Postfix logfile:
+ # postfix stop
+ # postconf maillog_file=/var/log/postfix.log
+ # postfix start
+
+To write logs to stdout, typically while Postfix runs in a container:
+ # postconf maillog_file=/dev/stdout
+ # postfix start-fg
+
+To rotate a Postfix logfile with a daily cronjob:
+-------------------------------------------------
+
+The following applies when the maillog_file parameter specifies a
+reguar file.
+
+- Rename the current logfile in the same directory, appending the
+ current date to file file name. The following adds a suffix
+ of the form YYYYMMDD to file name:
+ # mv postfix.log postfix.log.$(date +%Y%M%d)
+
+- DO NOT YET COMPRESS THE FILE. POSTFIX STILL WRITES TO IT.
+
+- Reload Postfix, so that postlogd(8) will start writing to a new
+ file:
+ # postfix reload
+
+- Compress the old file, and move it elsewhere if needed.
+
+Limitations of logging to Postfix logfile or stdout:
+----------------------------------------------------
+
+Background:
+
+- Logging to Postfix logfile or stdout requires the Postfix postlogd(8)
+ service. This program ensures that simultaneous logging from
+ different programs will not get mixed up.
+
+Limitations:
+
+- Non-daemon Postfix programs may log to syslogd(8) before they
+ have processed command-line options and main.cf parameters.
+
+- If Postfix is down, the non-daemon programs postfix(1), postsuper(1),
+ postmulti(1), and postlog(1), will log directly to $maillog_file.
+ These programs expect to run with root privileges, for example
+ during Postfix start-up, reload, or shutdown.
+
+- Other non-daemon Postfix programs will never write directly to
+ $maillog_file (also, logging to stdout would interfere with the
+ operation of some of these programs). These programs can log to
+ postlogd(8) if they are run by the super-user, or if their
+ executable file has set-gid permission. Do not set this permision
+ on programs other than postdrop(1) and postqueue(1).
+
Major changes with snapshot 20180826
====================================
Wish list:
+ Add maillog_file to postfix(1) exports?
+
+ postfix rotate-log command: mv postfix.log postfix.log.$(date
+ +%Y%M%d-%H%M%S) to avoid data loss if called repeatedly.
+
In smtpd(8) and postscreen(8), set the ehlo_discard_mask
to ~0 so that STARTTLS, BDAT, DSN, etc. work only for clients
that send EHLO.
lmtp unix - - n - - lmtp
anvil unix - - n - 1 anvil
scache unix - - n - 1 scache
+postlog unix-dgram n - n - 1 postlogd
#
# ====================================================================
# Interfaces to non-Postfix software. Be sure to examine the manual
# permit_mynetworks permit_sasl_authenticated \
# defer_unauth_destination" || exit 1
# }
+
+ # Postfix 3.4
+ # Add a postlog service entry.
+
+ grep '^postlog' $config_directory/master.cf >/dev/null || {
+ echo Editing $config_directory/master.cf, adding missing entry for postlog unix-domain datagram service
+ cat >>$config_directory/master.cf <<EOF || exit 1
+postlog unix-dgram n - n - 1 postlogd
+EOF
+ }
}
# A reminder if this is the first time Postfix is being installed.
$daemon_directory/postfix-tls-script:f:root:-:755
$daemon_directory/postfix-wrapper:f:root:-:755
$daemon_directory/postmulti-script:f:root:-:755
+$daemon_directory/postlogd:f:root:-:755
$daemon_directory/postscreen:f:root:-:755
$daemon_directory/proxymap:f:root:-:755
$daemon_directory/qmgr:f:root:-:755
$manpage_directory/man8/oqmgr.8:f:root:-:644:
$manpage_directory/man8/pickup.8:f:root:-:644
$manpage_directory/man8/pipe.8:f:root:-:644
+$manpage_directory/man8/postlogd.8:f:root:-:644
$manpage_directory/man8/postscreen.8:f:root:-:644
$manpage_directory/man8/proxymap.8:f:root:-:644
$manpage_directory/man8/qmgr.8:f:root:-:644
$html_directory/postlog.1.html:f:root:-:644
$html_directory/postmap.1.html:f:root:-:644
$html_directory/postmulti.1.html:f:root:-:644
+$html_directory/postlogd.8.html:f:root:-:644
$html_directory/postqueue.1.html:f:root:-:644
$html_directory/postscreen.8.html:f:root:-:644
$html_directory/postsuper.1.html:f:root:-:644
# Foreground this so it can be stopped. All inodes are cached.
$daemon_directory/postfix-script check-warn
fi
- $INFO starting the Postfix mail system
+ $INFO starting the Postfix mail system || exit 1
case $1 in
start)
# NOTE: wait in foreground process to get the initialization status.
1) exec $daemon_directory/master -i
$FATAL "cannot start-fg the master daemon"
exit 1;;
- *) $daemon_directory/master;;
+ *) $daemon_directory/master -s;;
esac
;;
*) $FATAL "start-fg does not support multi_instance_directories"
exit 1
}
+ maillog_file=`$command_directory/postconf -h maillog_file` || {
+ $FATAL cannot execute $command_directory/postconf!
+ exit 1
+ }
+ test -n "$maillog_file" && {
+ $command_directory/postconf -M postlog/unix-dgram 2>/dev/null \
+ | grep . >/dev/null || {
+ $FATAL "missing 'postlog' service in master.cf - run 'postfix upgrade-configuration'"
+ exit 1
+ }
+ }
+
# See if all queue files are in the right place. This is slow.
# We must scan all queues for mis-named queue files before the
# mail system can run.
oqmgr.8.html spawn.8.html flush.8.html virtual.8.html qmqpd.8.html \
trace.8.html verify.8.html proxymap.8.html anvil.8.html \
scache.8.html discard.8.html tlsmgr.8.html postscreen.8.html \
- dnsblog.8.html tlsproxy.8.html
+ dnsblog.8.html tlsproxy.8.html postlogd.8.html
COMMANDS= mailq.1.html newaliases.1.html postalias.1.html postcat.1.html \
postconf.1.html postfix.1.html postkick.1.html postlock.1.html \
postlog.1.html postdrop.1.html postmap.1.html postmulti.1.html \
PATH=../mantools:$$PATH; \
srctoman $? | $(AWK) | $(NROFF) -man | uniq | $(MAN2HTML) | postlink >$@
+postlogd.8.html: ../src/postlogd/postlogd.c
+ PATH=../mantools:$$PATH; \
+ srctoman $? | $(AWK) | $(NROFF) -man | uniq | $(MAN2HTML) | postlink >$@
+
postscreen.8.html: ../src/postscreen/postscreen.c
PATH=../mantools:$$PATH; \
srctoman $? | $(AWK) | $(NROFF) -man | uniq | $(MAN2HTML) | postlink >$@
hard-coding loopback IP address information in <a href="master.5.html">master.cf</a>
or in <a href="postconf.5.html">main.cf</a>.
- <b>unix</b> The service listens on a UNIX-domain socket and is acces-
- sible for local clients only.
+ <b>unix</b> The service listens on a UNIX-domain stream socket and is
+ accessible for local clients only.
The service name is a pathname relative to the Postfix
queue directory (pathname controlled with the
On Solaris 8 and earlier systems the <b>unix</b> type is imple-
mented with streams sockets.
- <b>fifo</b> The service listens on a FIFO (named pipe) and is acces-
- sible for local clients only.
+ <b>unix-dgram</b>
+ The service listens on a UNIX-domain datagram socket and
+ is accessible for local clients only.
The service name is a pathname relative to the Postfix
queue directory (pathname controlled with the
<b><a href="postconf.5.html#queue_directory">queue_directory</a></b> configuration parameter in <a href="postconf.5.html">main.cf</a>).
- <b>pass</b> The service listens on a UNIX-domain socket, and is
- accessible to local clients only. It receives one open
- connection (file descriptor passing) per connection
- request.
+ <b>fifo</b> (obsolete)
+ The service listens on a FIFO (named pipe) and is acces-
+ sible for local clients only.
The service name is a pathname relative to the Postfix
queue directory (pathname controlled with the
<b><a href="postconf.5.html#queue_directory">queue_directory</a></b> configuration parameter in <a href="postconf.5.html">main.cf</a>).
- On Solaris 8 and earlier systems the <b>pass</b> type is imple-
+ <b>pass</b> The service listens on a UNIX-domain stream socket, and
+ is accessible to local clients only. It receives one open
+ connection (file descriptor passing) per connection
+ request.
+
+ The service name is a pathname relative to the Postfix
+ queue directory (pathname controlled with the
+ <b><a href="postconf.5.html#queue_directory">queue_directory</a></b> configuration parameter in <a href="postconf.5.html">main.cf</a>).
+
+ On Solaris 8 and earlier systems the <b>pass</b> type is imple-
mented with streams sockets.
This feature is available as of Postfix version 2.5.
<b>Private (default: y)</b>
- Whether or not access is restricted to the mail system. Inter-
+ Whether or not access is restricted to the mail system. Inter-
net (type <b>inet</b>) services can't be private.
<b>Unprivileged (default: y)</b>
the Postfix system (the owner name is controlled by the
<b><a href="postconf.5.html#mail_owner">mail_owner</a></b> configuration variable in the <a href="postconf.5.html">main.cf</a> file).
- The <a href="local.8.html"><b>local</b>(8)</a>, <a href="pipe.8.html"><b>pipe</b>(8)</a>, <a href="spawn.8.html"><b>spawn</b>(8)</a>, and <a href="virtual.8.html"><b>virtual</b>(8)</a> daemons require
+ The <a href="local.8.html"><b>local</b>(8)</a>, <a href="pipe.8.html"><b>pipe</b>(8)</a>, <a href="spawn.8.html"><b>spawn</b>(8)</a>, and <a href="virtual.8.html"><b>virtual</b>(8)</a> daemons require
privileges.
<b>Chroot (default: Postfix</b> ><b>= 3.0: n, Postfix</b> <<b>3.0: y)</b>
- Whether or not the service runs chrooted to the mail queue
+ Whether or not the service runs chrooted to the mail queue
directory (pathname is controlled by the <b><a href="postconf.5.html#queue_directory">queue_directory</a></b> config-
uration variable in the <a href="postconf.5.html">main.cf</a> file).
- Chroot should not be used with the <a href="local.8.html"><b>local</b>(8)</a>, <a href="pipe.8.html"><b>pipe</b>(8)</a>, <a href="spawn.8.html"><b>spawn</b>(8)</a>,
+ Chroot should not be used with the <a href="local.8.html"><b>local</b>(8)</a>, <a href="pipe.8.html"><b>pipe</b>(8)</a>, <a href="spawn.8.html"><b>spawn</b>(8)</a>,
and <a href="virtual.8.html"><b>virtual</b>(8)</a> daemons. Although the <a href="proxymap.8.html"><b>proxymap</b>(8)</a> server can run
- chrooted, doing so defeats most of the purpose of having that
+ chrooted, doing so defeats most of the purpose of having that
service in the first place.
The files in the examples/chroot-setup subdirectory of the Post-
- fix source show how to set up a Postfix chroot environment on a
- variety of systems. See also <a href="BASIC_CONFIGURATION_README.html">BASIC_CONFIGURATION_README</a> for
+ fix source show how to set up a Postfix chroot environment on a
+ variety of systems. See also <a href="BASIC_CONFIGURATION_README.html">BASIC_CONFIGURATION_README</a> for
issues related to running daemons chrooted.
<b>Wake up time (default: 0)</b>
Automatically wake up the named service after the specified num-
- ber of seconds. The wake up is implemented by connecting to the
- service and sending a wake up request. A ? at the end of the
- wake-up time field requests that no wake up events be sent
+ ber of seconds. The wake up is implemented by connecting to the
+ service and sending a wake up request. A ? at the end of the
+ wake-up time field requests that no wake up events be sent
before the first time a service is used. Specify 0 for no auto-
matic wake up.
- The <a href="pickup.8.html"><b>pickup</b>(8)</a>, <a href="qmgr.8.html"><b>qmgr</b>(8)</a> and <a href="flush.8.html"><b>flush</b>(8)</a> daemons require a wake up
+ The <a href="pickup.8.html"><b>pickup</b>(8)</a>, <a href="qmgr.8.html"><b>qmgr</b>(8)</a> and <a href="flush.8.html"><b>flush</b>(8)</a> daemons require a wake up
timer.
<b>Process limit (default: $<a href="postconf.5.html#default_process_limit">default_process_limit</a>)</b>
- The maximum number of processes that may execute this service
+ The maximum number of processes that may execute this service
simultaneously. Specify 0 for no process count limit.
- NOTE: Some Postfix services must be configured as a sin-
- gle-process service (for example, <a href="qmgr.8.html"><b>qmgr</b>(8)</a>) and some services
- must be configured with no process limit (for example,
+ NOTE: Some Postfix services must be configured as a sin-
+ gle-process service (for example, <a href="qmgr.8.html"><b>qmgr</b>(8)</a>) and some services
+ must be configured with no process limit (for example,
<a href="cleanup.8.html"><b>cleanup</b>(8)</a>). These limits must not be changed.
<b>Command name + arguments</b>
- The command to be executed. Characters that are special to the
- shell such as ">" or "|" have no special meaning here, and
- quotes cannot be used to protect arguments containing white-
- space. To protect whitespace, use "{" and "}" as described
+ The command to be executed. Characters that are special to the
+ shell such as ">" or "|" have no special meaning here, and
+ quotes cannot be used to protect arguments containing white-
+ space. To protect whitespace, use "{" and "}" as described
below.
- The command name is relative to the Postfix daemon directory
- (pathname is controlled by the <b><a href="postconf.5.html#daemon_directory">daemon_directory</a></b> configuration
+ The command name is relative to the Postfix daemon directory
+ (pathname is controlled by the <b><a href="postconf.5.html#daemon_directory">daemon_directory</a></b> configuration
variable).
- The command argument syntax for specific commands is specified
+ The command argument syntax for specific commands is specified
in the respective daemon manual page.
- The following command-line options have the same effect for all
+ The following command-line options have the same effect for all
daemon programs:
- <b>-D</b> Run the daemon under control by the command specified
+ <b>-D</b> Run the daemon under control by the command specified
with the <b><a href="postconf.5.html#debugger_command">debugger_command</a></b> variable in the <a href="postconf.5.html">main.cf</a> config-
uration file. See <a href="DEBUG_README.html">DEBUG_README</a> for hints and tips.
<b>-o {</b> <i>name</i> = <i>value</i> <b>}</b> (long form, Postfix >= 3.0)
<b>-o</b> <i>name</i>=<i>value</i> (short form)
- Override the named <a href="postconf.5.html">main.cf</a> configuration parameter. The
- parameter value can refer to other parameters as <i>$name</i>
- etc., just like in <a href="postconf.5.html">main.cf</a>. See <a href="postconf.5.html"><b>postconf</b>(5)</a> for syntax.
+ Override the named <a href="postconf.5.html">main.cf</a> configuration parameter. The
+ parameter value can refer to other parameters as <i>$name</i>
+ etc., just like in <a href="postconf.5.html">main.cf</a>. See <a href="postconf.5.html"><b>postconf</b>(5)</a> for syntax.
- NOTE 1: With the "long form" shown above, whitespace
- after "{", around "=", and before "}" is ignored, and
+ NOTE 1: With the "long form" shown above, whitespace
+ after "{", around "=", and before "}" is ignored, and
whitespace within the parameter value is preserved.
NOTE 2: with the "short form" shown above, do not specify
- whitespace around the "=" or in parameter values. To
- specify a parameter value that contains whitespace, use
- the long form described above, or use commas instead of
+ whitespace around the "=" or in parameter values. To
+ specify a parameter value that contains whitespace, use
+ the long form described above, or use commas instead of
spaces, or specify the value in <a href="postconf.5.html">main.cf</a>. Example:
/etc/postfix/<a href="master.5.html">master.cf</a>:
submission_xxx_yyy = text with whitespace...
NOTE 3: Over-zealous use of parameter overrides makes the
- Postfix configuration hard to understand and maintain.
- At a certain point, it might be easier to configure mul-
+ Postfix configuration hard to understand and maintain.
+ At a certain point, it might be easier to configure mul-
tiple instances of Postfix, instead of configuring multi-
ple personalities via <a href="master.5.html">master.cf</a>.
- <b>-v</b> Increase the verbose logging level. Specify multiple <b>-v</b>
- options to make a Postfix daemon process increasingly
+ <b>-v</b> Increase the verbose logging level. Specify multiple <b>-v</b>
+ options to make a Postfix daemon process increasingly
verbose.
Other command-line arguments
Specify "{" and "}" around command arguments that contain
- whitespace (Postfix 3.0 and later). Whitespace after "{"
+ whitespace (Postfix 3.0 and later). Whitespace after "{"
and before "}" is ignored.
<b>SEE ALSO</b>
Terminate the master process after <i>exit</i><b>_</b><i>time</i> seconds. Child pro-
cesses terminate at their convenience.
- <b>-i</b> Enable <b>init</b> mode: do not attempt to become a session or process
- group leader; and to force termination, set an explicit signal
- handler instead of relying on the default signal action. This
- mode is allowed only if the process ID equals 1.
+ <b>-i</b> Enable <b>init</b> mode: do not become a session or process group
+ leader; similar to <b>-s</b>, do not redirect stdout to /dev/null, so
+ that "<a href="postconf.5.html#maillog_file">maillog_file</a> = /dev/stdout" works. This mode is allowed
+ only if the process ID equals 1.
- <b>-t</b> Test mode. Return a zero exit status when the <b>master.pid</b> lock
- file does not exist or when that file is not locked. This is
+ <b>-s</b> Do not redirect stdout to /dev/null, so that "<a href="postconf.5.html#maillog_file">maillog_file</a> =
+ /dev/stdout" works.
+
+ <b>-t</b> Test mode. Return a zero exit status when the <b>master.pid</b> lock
+ file does not exist or when that file is not locked. This is
evidence that the <a href="master.8.html"><b>master</b>(8)</a> daemon is not running.
- <b>-v</b> Enable verbose logging for debugging purposes. This option is
+ <b>-v</b> Enable verbose logging for debugging purposes. This option is
passed on to child processes. Multiple <b>-v</b> options make the soft-
ware increasingly verbose.
<b>-w</b> Wait in a dummy foreground process, while the real master daemon
- initializes in a background process. The dummy foreground
- process returns a zero exit status only if the master daemon
- initialization is successful, and if it completes in a reason-
+ initializes in a background process. The dummy foreground
+ process returns a zero exit status only if the master daemon
+ initialization is successful, and if it completes in a reason-
able amount of time.
This feature is available in Postfix 2.10 and later.
Signals:
<b>SIGHUP</b> Upon receipt of a <b>HUP</b> signal (e.g., after "<b>postfix reload</b>"), the
- master process re-reads its configuration files. If a service
- has been removed from the <a href="master.5.html"><b>master.cf</b></a> file, its running processes
- are terminated immediately. Otherwise, running processes are
- allowed to terminate as soon as is convenient, so that changes
+ master process re-reads its configuration files. If a service
+ has been removed from the <a href="master.5.html"><b>master.cf</b></a> file, its running processes
+ are terminated immediately. Otherwise, running processes are
+ allowed to terminate as soon as is convenient, so that changes
in configuration settings affect only new service requests.
<b>SIGTERM</b>
Upon receipt of a <b>TERM</b> signal (e.g., after "<b>postfix abort</b>"), the
- master process passes the signal on to its child processes and
- terminates. This is useful for an emergency shutdown. Normally
- one would terminate only the master ("<b>postfix stop</b>") and allow
+ master process passes the signal on to its child processes and
+ terminates. This is useful for an emergency shutdown. Normally
+ one would terminate only the master ("<b>postfix stop</b>") and allow
running processes to finish what they are doing.
<b>DIAGNOSTICS</b>
- Problems are reported to <b>syslogd</b>(8). The exit status is non-zero in
- case of problems, including problems while initializing as a master
+ Problems are reported to <b>syslogd</b>(8). The exit status is non-zero in
+ case of problems, including problems while initializing as a master
daemon process in the background.
<b>ENVIRONMENT</b>
<b>MAIL_DEBUG</b>
- After initialization, start a debugger as specified with the
+ After initialization, start a debugger as specified with the
<b><a href="postconf.5.html#debugger_command">debugger_command</a></b> configuration parameter in the <a href="postconf.5.html"><b>main.cf</b></a> configu-
ration file.
Directory with Postfix configuration files.
<b>CONFIGURATION PARAMETERS</b>
- Unlike most Postfix daemon processes, the <a href="master.8.html"><b>master</b>(8)</a> server does not
- automatically pick up changes to <a href="postconf.5.html"><b>main.cf</b></a>. Changes to <a href="master.5.html"><b>master.cf</b></a> are
- never picked up automatically. Use the "<b>postfix reload</b>" command after
+ Unlike most Postfix daemon processes, the <a href="master.8.html"><b>master</b>(8)</a> server does not
+ automatically pick up changes to <a href="postconf.5.html"><b>main.cf</b></a>. Changes to <a href="master.5.html"><b>master.cf</b></a> are
+ never picked up automatically. Use the "<b>postfix reload</b>" command after
a configuration change.
<b>RESOURCE AND RATE CONTROLS</b>
<b><a href="postconf.5.html#default_process_limit">default_process_limit</a> (100)</b>
- The default maximal number of Postfix child processes that pro-
+ The default maximal number of Postfix child processes that pro-
vide a given service.
<b><a href="postconf.5.html#max_idle">max_idle</a> (100s)</b>
- The maximum amount of time that an idle Postfix daemon process
+ The maximum amount of time that an idle Postfix daemon process
waits for an incoming connection before terminating voluntarily.
<b><a href="postconf.5.html#max_use">max_use</a> (100)</b>
process will service before terminating voluntarily.
<b><a href="postconf.5.html#service_throttle_time">service_throttle_time</a> (60s)</b>
- How long the Postfix <a href="master.8.html"><b>master</b>(8)</a> waits before forking a server
+ How long the Postfix <a href="master.8.html"><b>master</b>(8)</a> waits before forking a server
that appears to be malfunctioning.
Available in Postfix version 2.6 and later:
<b><a href="postconf.5.html#master_service_disable">master_service_disable</a> (empty)</b>
- Selectively disable <a href="master.8.html"><b>master</b>(8)</a> listener ports by service type or
+ Selectively disable <a href="master.8.html"><b>master</b>(8)</a> listener ports by service type or
by service name and type.
<b>MISCELLANEOUS CONTROLS</b>
<b><a href="postconf.5.html#config_directory">config_directory</a> (see 'postconf -d' output)</b>
- The default location of the Postfix <a href="postconf.5.html">main.cf</a> and <a href="master.5.html">master.cf</a> con-
+ The default location of the Postfix <a href="postconf.5.html">main.cf</a> and <a href="master.5.html">master.cf</a> con-
figuration files.
<b><a href="postconf.5.html#daemon_directory">daemon_directory</a> (see 'postconf -d' output)</b>
invoked with the -D option.
<b><a href="postconf.5.html#inet_interfaces">inet_interfaces</a> (all)</b>
- The network interface addresses that this mail system receives
+ The network interface addresses that this mail system receives
mail on.
<b><a href="postconf.5.html#inet_protocols">inet_protocols</a> (all)</b>
- The Internet protocols Postfix will attempt to use when making
+ The Internet protocols Postfix will attempt to use when making
or accepting connections.
<b><a href="postconf.5.html#import_environment">import_environment</a> (see 'postconf -d' output)</b>
- The list of environment parameters that a privileged Postfix
- process will import from a non-Postfix parent process, or
+ The list of environment parameters that a privileged Postfix
+ process will import from a non-Postfix parent process, or
name=value environment overrides.
<b><a href="postconf.5.html#mail_owner">mail_owner</a> (postfix)</b>
- The UNIX system account that owns the Postfix queue and most
+ The UNIX system account that owns the Postfix queue and most
Postfix daemon processes.
<b><a href="postconf.5.html#process_id">process_id</a> (read-only)</b>
The syslog facility of Postfix logging.
<b><a href="postconf.5.html#syslog_name">syslog_name</a> (see 'postconf -d' output)</b>
- A prefix that is prepended to the process name in syslog
+ A prefix that is prepended to the process name in syslog
records, so that, for example, "smtpd" becomes "prefix/smtpd".
Available in Postfix 3.3 and later:
The <a href="master.5.html">master.cf</a> service name of a Postfix daemon process.
<b>FILES</b>
- To expand the directory names below into their actual values, use the
+ To expand the directory names below into their actual values, use the
command "<b>postconf <a href="postconf.5.html#config_directory">config_directory</a></b>" etc.
$<a href="postconf.5.html#config_directory">config_directory</a>/<a href="postconf.5.html">main.cf</a>, global configuration file.
<p> This feature is available in Postfix 2.3 and later. </p>
+</DD>
+
+<DT><b><a name="maillog_file">maillog_file</a>
+(default: empty)</b></DT><DD>
+
+<p> The name of an optional logfile that is written by the Postfix
+<a href="postlogd.8.html">postlogd(8)</a> service. A non-empty value disables logging to syslogd(8).
+Specify "/dev/stdout" for logging to standard output. Stdout logging
+requires that Postfix is started with "postfix start-fg". </p>
+
+<p> Note: Some Postfix non-daemon programs may still log information
+to syslogd(8), before they have processed their configuration
+parameters and command-line options. </p>
+
+<p> This feature is available in Postfix 3.4 and later. </p>
+
+
</DD>
<DT><b><a name="mailq_path">mailq_path</a>
<p> This feature is available in Postfix 2.3 and later. </p>
+</DD>
+
+<DT><b><a name="postlog_service_name">postlog_service_name</a>
+(default: postlog)</b></DT><DD>
+
+<p> The name of the <a href="postlogd.8.html">postlogd(8)</a> service entry in <a href="master.5.html">master.cf</a>.
+This service appends logfile records to the file specified
+with the <a href="postconf.5.html#maillog_file">maillog_file</a> parameter. </p>
+
+<p> This feature is available in Postfix 3.4 and later. </p>
+
+
+</DD>
+
+<DT><b><a name="postlogd_watchdog_timeout">postlogd_watchdog_timeout</a>
+(default: 10s)</b></DT><DD>
+
+<p> How much time a <a href="postlogd.8.html">postlogd(8)</a> process may take to process a request
+before it is terminated by a built-in watchdog timer. This is a
+safety mechanism that prevents <a href="postlogd.8.html">postlogd(8)</a> from becoming non-responsive
+due to a bug in Postfix itself or in system software. This limit
+cannot be set under 10s. </p>
+
+<p> Specify a non-zero time value (an integral value plus an optional
+one-letter suffix that specifies the time unit). Time units: s
+(seconds), m (minutes), h (hours), d (days), w (weeks). </p>
+
+<p> This feature is available in Postfix 3.4 and later. </p>
+
+
</DD>
<DT><b><a name="postmulti_control_commands">postmulti_control_commands</a>
one-letter suffix that specifies the time unit). Time units: s
(seconds), m (minutes), h (hours), d (days), w (weeks). </p>
-<p> This feature is available in Postfix 2.8. </p>
+<p> This feature is available in Postfix 2.8 and later </p>
</DD>
<b><a href="postconf.5.html#alternate_config_directories">alternate_config_directories</a> (empty)</b>
A list of non-default Postfix configuration directories that may
- be specified with "-c <a href="postconf.5.html#config_directory">config_directory</a>" on the command line, or
- via the MAIL_CONFIG environment parameter.
+ be specified with "-c <a href="postconf.5.html#config_directory">config_directory</a>" on the command line (in
+ the case of <a href="sendmail.1.html"><b>sendmail</b>(1)</a>, with the "-C" option), or via the
+ MAIL_CONFIG environment parameter.
<b><a href="postconf.5.html#config_directory">config_directory</a> (see 'postconf -d' output)</b>
- The default location of the Postfix <a href="postconf.5.html">main.cf</a> and <a href="master.5.html">master.cf</a> con-
+ The default location of the Postfix <a href="postconf.5.html">main.cf</a> and <a href="master.5.html">master.cf</a> con-
figuration files.
<b><a href="postconf.5.html#import_environment">import_environment</a> (see 'postconf -d' output)</b>
- The list of environment parameters that a Postfix process will
- import from a non-Postfix parent process.
+ The list of environment parameters that a privileged Postfix
+ process will import from a non-Postfix parent process, or
+ name=value environment overrides.
<b><a href="postconf.5.html#queue_directory">queue_directory</a> (see 'postconf -d' output)</b>
The location of the Postfix top-level queue directory.
<li> <a href="pipe.8.html">pipe(8)</a>, deliver mail to non-Postfix command
+<li> <a href="postlogd.8.html">postlogd(8)</a>, Postfix internal logging service
+
<li> <a href="postscreen.8.html">postscreen(8)</a>, Postfix zombie blocker
<li> <a href="proxymap.8.html">proxymap(8)</a>, Postfix lookup table proxy server
<b>MAIL_DEBUG</b>
This is set when the -D command-line option is present.
+ When the internal logging service is enabled (by setting a non-empty
+ <a href="postconf.5.html#maillog_file">maillog_file</a> parameter value) the <a href="postfix.1.html">postfix(1)</a> command exports settings
+ that are used by child processes before they have processed <a href="postconf.5.html">main.cf</a> or
+ command-line settings.
+
+ <b>POSTLOG_SERVICE</b>
+ The name of the public postlog service endpoint.
+
+ <b>POSTLOG_HOSTNAME</b>
+ The hostname to prepend to internal logging.
+
<b>CONFIGURATION PARAMETERS</b>
The following <a href="postconf.5.html"><b>main.cf</b></a> configuration parameters are exported as environ-
ment variables with the same names:
<b><a href="postconf.5.html#config_directory">config_directory</a> (see 'postconf -d' output)</b>
- The default location of the Postfix <a href="postconf.5.html">main.cf</a> and <a href="master.5.html">master.cf</a> con-
+ The default location of the Postfix <a href="postconf.5.html">main.cf</a> and <a href="master.5.html">master.cf</a> con-
figuration files.
<b><a href="postconf.5.html#command_directory">command_directory</a> (see 'postconf -d' output)</b>
The directory with Postfix support programs and daemon programs.
<b><a href="postconf.5.html#html_directory">html_directory</a> (see 'postconf -d' output)</b>
- The location of Postfix HTML files that describe how to build,
+ The location of Postfix HTML files that describe how to build,
configure or operate a specific Postfix subsystem or feature.
<b><a href="postconf.5.html#mail_owner">mail_owner</a> (postfix)</b>
- The UNIX system account that owns the Postfix queue and most
+ The UNIX system account that owns the Postfix queue and most
Postfix daemon processes.
<b><a href="postconf.5.html#mailq_path">mailq_path</a> (see 'postconf -d' output)</b>
- Sendmail compatibility feature that specifies where the Postfix
+ Sendmail compatibility feature that specifies where the Postfix
<a href="mailq.1.html"><b>mailq</b>(1)</a> command is installed.
<b><a href="postconf.5.html#manpage_directory">manpage_directory</a> (see 'postconf -d' output)</b>
Where the Postfix manual pages are installed.
<b><a href="postconf.5.html#newaliases_path">newaliases_path</a> (see 'postconf -d' output)</b>
- Sendmail compatibility feature that specifies the location of
+ Sendmail compatibility feature that specifies the location of
the <a href="newaliases.1.html"><b>newaliases</b>(1)</a> command.
<b><a href="postconf.5.html#queue_directory">queue_directory</a> (see 'postconf -d' output)</b>
configure or operate a specific Postfix subsystem or feature.
<b><a href="postconf.5.html#sendmail_path">sendmail_path</a> (see 'postconf -d' output)</b>
- A Sendmail compatibility feature that specifies the location of
+ A Sendmail compatibility feature that specifies the location of
the Postfix <a href="sendmail.1.html"><b>sendmail</b>(1)</a> command.
<b><a href="postconf.5.html#setgid_group">setgid_group</a> (postdrop)</b>
- The group ownership of set-gid Postfix commands and of
+ The group ownership of set-gid Postfix commands and of
group-writable Postfix directories.
Available in Postfix version 2.5 and later:
<b><a href="postconf.5.html#data_directory">data_directory</a> (see 'postconf -d' output)</b>
- The directory with Postfix-writable data files (for example:
+ The directory with Postfix-writable data files (for example:
caches, pseudo-random numbers).
Available in Postfix version 3.0 and later:
<b><a href="postconf.5.html#meta_directory">meta_directory</a> (see 'postconf -d' output)</b>
- The location of non-executable files that are shared among mul-
- tiple Postfix instances, such as postfix-files, dynamicmaps.cf,
- and the multi-instance template files <a href="postconf.5.html">main.cf</a>.proto and <a href="master.5.html">mas-
+ The location of non-executable files that are shared among mul-
+ tiple Postfix instances, such as postfix-files, dynamicmaps.cf,
+ and the multi-instance template files <a href="postconf.5.html">main.cf</a>.proto and <a href="master.5.html">mas-
ter.cf</a>.proto.
<b><a href="postconf.5.html#shlib_directory">shlib_directory</a> (see 'postconf -d' output)</b>
- The location of Postfix dynamically-linked libraries (libpost-
- fix-*.so), and the default location of Postfix database plugins
- (postfix-*.so) that have a relative pathname in the dynam-
+ The location of Postfix dynamically-linked libraries (libpost-
+ fix-*.so), and the default location of Postfix database plugins
+ (postfix-*.so) that have a relative pathname in the dynam-
icmaps.cf file.
Available in Postfix version 3.1 and later:
Other configuration parameters:
<b><a href="postconf.5.html#import_environment">import_environment</a> (see 'postconf -d' output)</b>
- The list of environment parameters that a privileged Postfix
- process will import from a non-Postfix parent process, or
+ The list of environment parameters that a privileged Postfix
+ process will import from a non-Postfix parent process, or
name=value environment overrides.
<b><a href="postconf.5.html#syslog_facility">syslog_facility</a> (mail)</b>
The syslog facility of Postfix logging.
<b><a href="postconf.5.html#syslog_name">syslog_name</a> (see 'postconf -d' output)</b>
- A prefix that is prepended to the process name in syslog
+ A prefix that is prepended to the process name in syslog
records, so that, for example, "smtpd" becomes "prefix/smtpd".
Available in Postfix version 2.6 and later:
<b><a href="postconf.5.html#multi_instance_directories">multi_instance_directories</a> (empty)</b>
- An optional list of non-default Postfix configuration directo-
- ries; these directories belong to additional Postfix instances
- that share the Postfix executable files and documentation with
- the default Postfix instance, and that are started, stopped,
+ An optional list of non-default Postfix configuration directo-
+ ries; these directories belong to additional Postfix instances
+ that share the Postfix executable files and documentation with
+ the default Postfix instance, and that are started, stopped,
etc., together with the default Postfix instance.
<b><a href="postconf.5.html#multi_instance_wrapper">multi_instance_wrapper</a> (empty)</b>
- The pathname of a multi-instance manager command that the <a href="postfix.1.html"><b>post-</b></a>
- <a href="postfix.1.html"><b>fix</b>(1)</a> command invokes when the <a href="postconf.5.html#multi_instance_directories">multi_instance_directories</a>
+ The pathname of a multi-instance manager command that the <a href="postfix.1.html"><b>post-</b></a>
+ <a href="postfix.1.html"><b>fix</b>(1)</a> command invokes when the <a href="postconf.5.html#multi_instance_directories">multi_instance_directories</a>
parameter value is non-empty.
<b><a href="postconf.5.html#multi_instance_group">multi_instance_group</a> (empty)</b>
The optional instance name of this Postfix instance.
<b><a href="postconf.5.html#multi_instance_enable">multi_instance_enable</a> (no)</b>
- Allow this Postfix instance to be started, stopped, etc., by a
+ Allow this Postfix instance to be started, stopped, etc., by a
multi-instance manager.
+ Available in Postfix version 3.4 and later:
+
+ <b><a href="postconf.5.html#maillog_file">maillog_file</a> (empty)</b>
+ The name of an optional logfile that is written by the Postfix
+ <a href="postlogd.8.html"><b>postlogd</b>(8)</a> service.
+
+ <b><a href="postconf.5.html#postlog_service_name">postlog_service_name</a> (postlog)</b>
+ The name of the <a href="postlogd.8.html"><b>postlogd</b>(8)</a> service entry in <a href="master.5.html">master.cf</a>.
+
<b>FILES</b>
Prior to Postfix version 2.6, all of the following files were in <b>$<a href="postconf.5.html#config_directory">con</a>-</b>
<b><a href="postconf.5.html#config_directory">fig_directory</a></b>. Some files are now in <b>$<a href="postconf.5.html#daemon_directory">daemon_directory</a></b> so that they can
<a href="qmgr.8.html">oqmgr(8)</a>, old Postfix queue manager
<a href="pickup.8.html">pickup(8)</a>, Postfix local mail pickup
<a href="pipe.8.html">pipe(8)</a>, deliver mail to non-Postfix command
+ <a href="postlogd.8.html">postlogd(8)</a>, Postfix internal logging service
<a href="postscreen.8.html">postscreen(8)</a>, Postfix zombie blocker
<a href="proxymap.8.html">proxymap(8)</a>, Postfix lookup table proxy server
<a href="qmgr.8.html">qmgr(8)</a>, Postfix queue manager
record. If no <i>text</i> is specified on the command line, <a href="postlog.1.html"><b>postlog</b>(1)</a> reads
from standard input and logs each input line as one record.
- Logging is sent to <b>syslogd</b>(8); when the standard error stream is con-
- nected to a terminal, logging is sent there as well.
+ By default, logging is sent to <b>syslogd</b>(8); when the standard error
+ stream is connected to a terminal, logging is sent there as well.
The following options are implemented:
Read the <a href="postconf.5.html"><b>main.cf</b></a> configuration file in the named directory
instead of the default configuration directory.
- <b>-i</b> Include the process ID in the logging tag.
+ <b>-i</b> (obsolete)
+ Include the process ID in the logging tag. This flag is ignored
+ as of Postfix 3.4, where the PID is always included.
<b>-p</b> <i>priority</i> (default: <b>info</b>)
- Specifies the logging severity: <b>info</b>, <b>warn</b>, <b>error</b>, <b>fatal</b>, or
- <b>panic</b>. With Postfix 3.1 and later, the program will pause for 1
- second after reporting a <b>fatal</b> or <b>panic</b> condition, just like
+ Specifies the logging severity: <b>info</b>, <b>warn</b>, <b>error</b>, <b>fatal</b>, or
+ <b>panic</b>. With Postfix 3.1 and later, the program will pause for 1
+ second after reporting a <b>fatal</b> or <b>panic</b> condition, just like
other Postfix programs.
- <b>-t</b> <i>tag</i> Specifies the logging tag, that is, the identifying name that
- appears at the beginning of each logging record. A default tag
+ <b>-t</b> <i>tag</i> Specifies the logging tag, that is, the identifying name that
+ appears at the beginning of each logging record. A default tag
is used when none is specified.
- <b>-v</b> Enable verbose logging for debugging purposes. Multiple <b>-v</b>
+ <b>-v</b> Enable verbose logging for debugging purposes. Multiple <b>-v</b>
options make the software increasingly verbose.
<b>ENVIRONMENT</b>
Directory with the <a href="postconf.5.html"><b>main.cf</b></a> file.
<b>CONFIGURATION PARAMETERS</b>
- The following <a href="postconf.5.html"><b>main.cf</b></a> parameters are especially relevant to this pro-
+ The following <a href="postconf.5.html"><b>main.cf</b></a> parameters are especially relevant to this pro-
gram.
- The text below provides only a parameter summary. See <a href="postconf.5.html"><b>postconf</b>(5)</a> for
+ The text below provides only a parameter summary. See <a href="postconf.5.html"><b>postconf</b>(5)</a> for
more details including examples.
<b><a href="postconf.5.html#config_directory">config_directory</a> (see 'postconf -d' output)</b>
- The default location of the Postfix <a href="postconf.5.html">main.cf</a> and <a href="master.5.html">master.cf</a> con-
+ The default location of the Postfix <a href="postconf.5.html">main.cf</a> and <a href="master.5.html">master.cf</a> con-
figuration files.
<b><a href="postconf.5.html#import_environment">import_environment</a> (see 'postconf -d' output)</b>
- The list of environment parameters that a privileged Postfix
- process will import from a non-Postfix parent process, or
+ The list of environment parameters that a privileged Postfix
+ process will import from a non-Postfix parent process, or
name=value environment overrides.
<b><a href="postconf.5.html#syslog_facility">syslog_facility</a> (mail)</b>
The syslog facility of Postfix logging.
<b><a href="postconf.5.html#syslog_name">syslog_name</a> (see 'postconf -d' output)</b>
- A prefix that is prepended to the process name in syslog
+ A prefix that is prepended to the process name in syslog
records, so that, for example, "smtpd" becomes "prefix/smtpd".
+ Available in Postfix 3.4 and later:
+
+ <b><a href="postconf.5.html#maillog_file">maillog_file</a> (empty)</b>
+ The name of an optional logfile that is written by the Postfix
+ <a href="postlogd.8.html"><b>postlogd</b>(8)</a> service.
+
+ <b><a href="postconf.5.html#postlog_service_name">postlog_service_name</a> (postlog)</b>
+ The name of the <a href="postlogd.8.html"><b>postlogd</b>(8)</a> service entry in <a href="master.5.html">master.cf</a>.
+
<b>SEE ALSO</b>
<a href="postconf.5.html">postconf(5)</a>, configuration parameters
syslogd(8), syslog daemon
+ <a href="postlogd.8.html">postlogd(8)</a>, internal logging service
<b>LICENSE</b>
The Secure Mailer license must be distributed with this software.
--- /dev/null
+<!doctype html public "-//W3C//DTD HTML 4.01 Transitional//EN"
+ "http://www.w3.org/TR/html4/loose.dtd">
+<html> <head>
+<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
+<title> Postfix manual - postlogd(8) </title>
+</head> <body> <pre>
+POSTLOGD(8) POSTLOGD(8)
+
+<b>NAME</b>
+ postlogd - Postfix internal log server
+
+<b>SYNOPSIS</b>
+ <b>postlogd</b> [generic Postfix daemon options]
+
+<b>DESCRIPTION</b>
+ This program logs events on behalf of Postfix programs when the maillog
+ configuration parameter specifies a non-empty value.
+
+<b>BUGS</b>
+ Non-daemon Postfix programs don't know that they should log to the
+ internal logging service before they have processed command-line
+ options and <a href="postconf.5.html">main.cf</a> parameters. These programs still log earlier events
+ to the syslog service.
+
+ If Postfix is down, the non-daemon programs <a href="postfix.1.html"><b>postfix</b>(1)</a>, <a href="postsuper.1.html"><b>postsuper</b>(1)</a>,
+ <a href="postmulti.1.html"><b>postmulti</b>(1)</a>, and <a href="postlog.1.html"><b>postlog</b>(1)</a>, will log directly to <b>$<a href="postconf.5.html#maillog_file">maillog_file</a></b>. These
+ programs expect to run with root privileges, for example during Postfix
+ start-up, reload, or shutdown.
+
+ Other non-daemon Postfix programs will never write directly to <b>$<a href="postconf.5.html#maillog_file">mail</a>-</b>
+ <b><a href="postconf.5.html#maillog_file">log_file</a></b> (also, logging to stdout would interfere with the operation of
+ some of these programs). These programs can log to <a href="postlogd.8.html"><b>postlogd</b>(8)</a> if they
+ are run by the super-user, or if their executable file has set-gid per-
+ mission. Do not set this permision on programs other than <a href="postdrop.1.html"><b>postdrop</b>(1)</a>
+ and <a href="postqueue.1.html"><b>postqueue</b>(1)</a>.
+
+<b>CONFIGURATION PARAMETERS</b>
+ Changes to <a href="postconf.5.html"><b>main.cf</b></a> are picked up automatically, as <a href="postlogd.8.html"><b>postlogd</b>(8)</a> pro-
+ cesses run for only a limited amount of time. Use the command "<b>postfix</b>
+ <b>reload</b>" to speed up a change.
+
+ The text below provides only a parameter summary. See <a href="postconf.5.html"><b>postconf</b>(5)</a> for
+ more details including examples.
+
+ <b><a href="postconf.5.html#config_directory">config_directory</a> (see 'postconf -d' output)</b>
+ The default location of the Postfix <a href="postconf.5.html">main.cf</a> and <a href="master.5.html">master.cf</a> con-
+ figuration files.
+
+ <b><a href="postconf.5.html#maillog_file">maillog_file</a> (empty)</b>
+ The name of an optional logfile that is written by the Postfix
+ <a href="postlogd.8.html"><b>postlogd</b>(8)</a> service.
+
+ <b><a href="postconf.5.html#process_id">process_id</a> (read-only)</b>
+ The process ID of a Postfix command or daemon process.
+
+ <b><a href="postconf.5.html#process_name">process_name</a> (read-only)</b>
+ The process name of a Postfix command or daemon process.
+
+ <b><a href="postconf.5.html#syslog_name">syslog_name</a> (see 'postconf -d' output)</b>
+ A prefix that is prepended to the process name in syslog
+ records, so that, for example, "smtpd" becomes "prefix/smtpd".
+
+ <b><a href="postconf.5.html#service_name">service_name</a> (read-only)</b>
+ The <a href="master.5.html">master.cf</a> service name of a Postfix daemon process.
+
+ <b><a href="postconf.5.html#postlogd_watchdog_timeout">postlogd_watchdog_timeout</a> (10s)</b>
+ How much time a <a href="postlogd.8.html"><b>postlogd</b>(8)</a> process may take to process a
+ request before it is terminated by a built-in watchdog timer.
+
+<b>SEE ALSO</b>
+ <a href="postconf.5.html">postconf(5)</a>, configuration parameters
+ syslogd(5), system logging
+
+<b>LICENSE</b>
+ The Secure Mailer license must be distributed with this software.
+
+<b>HISTORY</b>
+ This service was introduced with Postfix version 3.4.
+
+<b>AUTHOR(S)</b>
+ Wietse Venema
+ Google, Inc.
+ 111 8th Avenue
+ New York, NY 10011, USA
+
+ POSTLOGD(8)
+</pre> </body> </html>
P.O. Box 704
Yorktown Heights, NY 10598, USA
+ Wietse Venema
+ Google, Inc.
+ 111 8th Avenue
+ New York, NY 10011, USA
+
POSTMULTI(1)
</pre> </body> </html>
man8/oqmgr.8 man8/spawn.8 man8/flush.8 man8/virtual.8 man8/qmqpd.8 \
man8/verify.8 man8/trace.8 man8/proxymap.8 man8/anvil.8 \
man8/scache.8 man8/discard.8 man8/tlsmgr.8 man8/postscreen.8 \
- man8/dnsblog.8 man8/tlsproxy.8
+ man8/dnsblog.8 man8/tlsproxy.8 man8/postlogd.8
COMMANDS= man1/postalias.1 man1/postcat.1 man1/postconf.1 man1/postfix.1 \
man1/postkick.1 man1/postlock.1 man1/postlog.1 man1/postdrop.1 \
man1/postmap.1 man1/postmulti.1 man1/postqueue.1 man1/postsuper.1 \
(cmp -s junk $? || mv junk $?) && rm -f junk
../mantools/srctoman $? >$@
+man8/postlogd.8: ../src/postlogd/postlogd.c
+ ../mantools/fixman ../proto/postconf.proto $? >junk && \
+ (cmp -s junk $? || mv junk $?) && rm -f junk
+ ../mantools/srctoman $? >$@
+
man8/postscreen.8: ../src/postscreen/postscreen.c
../mantools/fixman ../proto/postconf.proto $? >junk && \
(cmp -s junk $? || mv junk $?) && rm -f junk
\fBpostconf\fR(5) for more details including examples.
.IP "\fBalternate_config_directories (empty)\fR"
A list of non\-default Postfix configuration directories that may
-be specified with "\-c config_directory" on the command line, or
-via the MAIL_CONFIG environment parameter.
+be specified with "\-c config_directory" on the command line (in the
+case of \fBsendmail\fR(1), with the "\-C" option), or via the MAIL_CONFIG
+environment parameter.
.IP "\fBconfig_directory (see 'postconf -d' output)\fR"
The default location of the Postfix main.cf and master.cf
configuration files.
.IP "\fBimport_environment (see 'postconf -d' output)\fR"
-The list of environment parameters that a Postfix process will
-import from a non\-Postfix parent process.
+The list of environment parameters that a privileged Postfix
+process will import from a non\-Postfix parent process, or name=value
+environment overrides.
.IP "\fBqueue_directory (see 'postconf -d' output)\fR"
The location of the Postfix top\-level queue directory.
.IP "\fBsyslog_facility (mail)\fR"
This is set when the \-v command\-line option is present.
.IP \fBMAIL_DEBUG\fR
This is set when the \-D command\-line option is present.
+.PP
+When the internal logging service is enabled (by setting a
+non\-empty maillog_file parameter value) the postfix(1)
+command exports settings that are used by child processes
+before they have processed main.cf or command\-line settings.
+.IP \fBPOSTLOG_SERVICE
+The name of the public postlog service endpoint.
+.IP \fBPOSTLOG_HOSTNAME
+The hostname to prepend to internal logging.
.SH "CONFIGURATION PARAMETERS"
.na
.nf
.IP "\fBmulti_instance_enable (no)\fR"
Allow this Postfix instance to be started, stopped, etc., by a
multi\-instance manager.
+.PP
+Available in Postfix version 3.4 and later:
+.IP "\fBmaillog_file (empty)\fR"
+The name of an optional logfile that is written by the Postfix
+\fBpostlogd\fR(8) service.
+.IP "\fBpostlog_service_name (postlog)\fR"
+The name of the \fBpostlogd\fR(8) service entry in master.cf.
.SH "FILES"
.na
.nf
oqmgr(8), old Postfix queue manager
pickup(8), Postfix local mail pickup
pipe(8), deliver mail to non\-Postfix command
+postlogd(8), Postfix internal logging service
postscreen(8), Postfix zombie blocker
proxymap(8), Postfix lookup table proxy server
qmgr(8), Postfix queue manager
line, \fBpostlog\fR(1) reads from standard input and logs each input
line as one record.
-Logging is sent to \fBsyslogd\fR(8); when the standard error stream
-is connected to a terminal, logging is sent there as well.
+By default, logging is sent to \fBsyslogd\fR(8); when the
+standard error stream is connected to a terminal, logging
+is sent there as well.
The following options are implemented:
.IP "\fB\-c \fIconfig_dir\fR"
Read the \fBmain.cf\fR configuration file in the named directory
instead of the default configuration directory.
-.IP \fB\-i\fR
-Include the process ID in the logging tag.
+.IP "\fB\-i\fR (obsolete)"
+Include the process ID in the logging tag. This flag is ignored as
+of Postfix 3.4, where the PID is always included.
.IP "\fB\-p \fIpriority\fR (default: \fBinfo\fR)"
Specifies the logging severity: \fBinfo\fR, \fBwarn\fR,
\fBerror\fR, \fBfatal\fR, or \fBpanic\fR. With Postfix 3.1
.IP "\fBsyslog_name (see 'postconf -d' output)\fR"
A prefix that is prepended to the process name in syslog
records, so that, for example, "smtpd" becomes "prefix/smtpd".
+.PP
+Available in Postfix 3.4 and later:
+.IP "\fBmaillog_file (empty)\fR"
+The name of an optional logfile that is written by the Postfix
+\fBpostlogd\fR(8) service.
+.IP "\fBpostlog_service_name (postlog)\fR"
+The name of the \fBpostlogd\fR(8) service entry in master.cf.
.SH "SEE ALSO"
.na
.nf
postconf(5), configuration parameters
syslogd(8), syslog daemon
+postlogd(8), internal logging service
.SH "LICENSE"
.na
.nf
IBM T.J. Watson Research
P.O. Box 704
Yorktown Heights, NY 10598, USA
+
+Wietse Venema
+Google, Inc.
+111 8th Avenue
+New York, NY 10011, USA
of hard\-coding loopback IP address information in master.cf
or in main.cf.
.IP \fBunix\fR
-The service listens on a UNIX\-domain socket and is accessible
-for local clients only.
+The service listens on a UNIX\-domain stream socket and is
+accessible for local clients only.
The service name is a pathname relative to the Postfix
queue directory (pathname controlled with the \fBqueue_directory\fR
.sp
On Solaris 8 and earlier systems the \fBunix\fR type is
implemented with streams sockets.
-.IP \fBfifo\fR
+.IP \fBunix\-dgram\fR
+The service listens on a UNIX\-domain datagram socket and is
+accessible for local clients only.
+
+The service name is a pathname relative to the Postfix
+queue directory (pathname controlled with the \fBqueue_directory\fR
+configuration parameter in main.cf).
+.IP "\fBfifo\fR (obsolete)"
The service listens on a FIFO (named pipe) and is accessible
for local clients only.
queue directory (pathname controlled with the \fBqueue_directory\fR
configuration parameter in main.cf).
.IP \fBpass\fR
-The service listens on a UNIX\-domain socket, and is accessible
-to local clients only. It receives one open connection (file
-descriptor passing) per connection request.
+The service listens on a UNIX\-domain stream socket, and is
+accessible to local clients only. It receives one open
+connection (file descriptor passing) per connection request.
The service name is a pathname relative to the Postfix
queue directory (pathname controlled with the \fBqueue_directory\fR
substitutions in regular expression maps.
.PP
This feature is available in Postfix 2.3 and later.
+.SH maillog_file (default: empty)
+The name of an optional logfile that is written by the Postfix
+\fBpostlogd\fR(8) service. A non\-empty value disables logging to \fBsyslogd\fR(8).
+Specify "/dev/stdout" for logging to standard output. Stdout logging
+requires that Postfix is started with "postfix start\-fg".
+.PP
+Note: Some Postfix non\-daemon programs may still log information
+to \fBsyslogd\fR(8), before they have processed their configuration
+parameters and command\-line options.
+.PP
+This feature is available in Postfix 3.4 and later.
.SH mailq_path (default: see "postconf \-d" output)
Sendmail compatibility feature that specifies where the Postfix
\fBmailq\fR(1) command is installed. This command can be used to
is rejected by the \fBreject_plaintext_session\fR restriction.
.PP
This feature is available in Postfix 2.3 and later.
+.SH postlog_service_name (default: postlog)
+The name of the \fBpostlogd\fR(8) service entry in master.cf.
+This service appends logfile records to the file specified
+with the maillog_file parameter.
+.PP
+This feature is available in Postfix 3.4 and later.
+.SH postlogd_watchdog_timeout (default: 10s)
+How much time a \fBpostlogd\fR(8) process may take to process a request
+before it is terminated by a built\-in watchdog timer. This is a
+safety mechanism that prevents \fBpostlogd\fR(8) from becoming non\-responsive
+due to a bug in Postfix itself or in system software. This limit
+cannot be set under 10s.
+.PP
+Specify a non\-zero time value (an integral value plus an optional
+one\-letter suffix that specifies the time unit). Time units: s
+(seconds), m (minutes), h (hours), d (days), w (weeks).
+.PP
+This feature is available in Postfix 3.4 and later.
.SH postmulti_control_commands (default: reload flush)
The \fBpostfix\fR(1) commands that the \fBpostmulti\fR(1) instance manager
treats as "control" commands, that operate on running instances. For
one\-letter suffix that specifies the time unit). Time units: s
(seconds), m (minutes), h (hours), d (days), w (weeks).
.PP
-This feature is available in Postfix 2.8.
+This feature is available in Postfix 2.8 and later
.SH trace_service_name (default: trace)
The name of the trace service. This service is implemented by the
\fBbounce\fR(8) daemon and maintains a record
Terminate the master process after \fIexit_time\fR seconds. Child
processes terminate at their convenience.
.IP \fB\-i\fR
-Enable \fBinit\fR mode: do not attempt to become a session
-or process group leader; and to force termination, set an
-explicit signal handler instead of relying on the default
-signal action. This mode is allowed only if the process ID
-equals 1.
+Enable \fBinit\fR mode: do not become a session or process
+group leader; similar to \fB\-s\fR, do not redirect stdout
+to /dev/null, so that "maillog_file = /dev/stdout" works.
+This mode is allowed only if the process ID equals 1.
+.IP \fB\-s\fR
+Do not redirect stdout to /dev/null, so that "maillog_file
+= /dev/stdout" works.
.IP \fB\-t\fR
Test mode. Return a zero exit status when the \fBmaster.pid\fR lock
file does not exist or when that file is not locked. This is evidence
--- /dev/null
+.TH POSTLOGD 8
+.ad
+.fi
+.SH NAME
+postlogd
+\-
+Postfix internal log server
+.SH "SYNOPSIS"
+.na
+.nf
+\fBpostlogd\fR [generic Postfix daemon options]
+.SH DESCRIPTION
+.ad
+.fi
+This program logs events on behalf of Postfix programs
+when the maillog configuration parameter specifies a non\-empty
+value.
+.SH BUGS
+.ad
+.fi
+Non\-daemon Postfix programs don't know that they should log
+to the internal logging service before they have processed
+command\-line options and main.cf parameters. These programs
+still log earlier events to the syslog service.
+
+If Postfix is down, the non\-daemon programs \fBpostfix\fR(1),
+\fBpostsuper\fR(1), \fBpostmulti\fR(1), and \fBpostlog\fR(1),
+will log directly to \fB$maillog_file\fR. These programs
+expect to run with root privileges, for example during
+Postfix start\-up, reload, or shutdown.
+
+Other non\-daemon Postfix programs will never write directly to
+\fB$maillog_file\fR (also, logging to stdout would interfere
+with the operation of some of these programs). These programs
+can log to \fBpostlogd\fR(8) if they are run by the super\-user,
+or if their executable file has set\-gid permission. Do not
+set this permision on programs other than \fBpostdrop\fR(1)
+and \fBpostqueue\fR(1).
+.SH "CONFIGURATION PARAMETERS"
+.na
+.nf
+.ad
+.fi
+Changes to \fBmain.cf\fR are picked up automatically, as
+\fBpostlogd\fR(8) processes run for only a limited amount
+of time. Use the command "\fBpostfix reload\fR" to speed
+up a change.
+
+The text below provides only a parameter summary. See
+\fBpostconf\fR(5) for more details including examples.
+.IP "\fBconfig_directory (see 'postconf -d' output)\fR"
+The default location of the Postfix main.cf and master.cf
+configuration files.
+.IP "\fBmaillog_file (empty)\fR"
+The name of an optional logfile that is written by the Postfix
+\fBpostlogd\fR(8) service.
+.IP "\fBprocess_id (read\-only)\fR"
+The process ID of a Postfix command or daemon process.
+.IP "\fBprocess_name (read\-only)\fR"
+The process name of a Postfix command or daemon process.
+.IP "\fBsyslog_name (see 'postconf -d' output)\fR"
+A prefix that is prepended to the process name in syslog
+records, so that, for example, "smtpd" becomes "prefix/smtpd".
+.IP "\fBservice_name (read\-only)\fR"
+The master.cf service name of a Postfix daemon process.
+.IP "\fBpostlogd_watchdog_timeout (10s)\fR"
+How much time a \fBpostlogd\fR(8) process may take to process a request
+before it is terminated by a built\-in watchdog timer.
+.SH "SEE ALSO"
+.na
+.nf
+postconf(5), configuration parameters
+syslogd(5), system logging
+.SH "LICENSE"
+.na
+.nf
+.ad
+.fi
+The Secure Mailer license must be distributed with this software.
+.SH HISTORY
+.ad
+.fi
+.ad
+.fi
+This service was introduced with Postfix version 3.4.
+.SH "AUTHOR(S)"
+.na
+.nf
+Wietse Venema
+Google, Inc.
+111 8th Avenue
+New York, NY 10011, USA
s/[<bB>]*mas[-<\/bB>]*\n* *[<bB>]*ter[<\/bB>]*\(8\)/<a href="master.8.html">$&<\/a>/g;
s/[<bB>]*pickup[<\/bB>]*\(8\)/<a href="pickup.8.html">$&<\/a>/g;
s/[<bB>]*pipe[<\/bB>]*\(8\)/<a href="pipe.8.html">$&<\/a>/g;
+ s/[<bB>]*postlogd[<\/bB>]*\(8\)/<a href="postlogd.8.html">$&<\/a>/g;
s/[<bB>]*postscreen[<\/bB>]*\(8\)/<a href="postscreen.8.html">$&<\/a>/g;
s/[<bB>]*oqmgr[<\/bB>]*\(8\)/<a href="qmgr.8.html">$&<\/a>/g;
s/[<bB>]*\bqmgr[<\/bB>]*\(8\)/<a href="qmgr.8.html">$&<\/a>/g;
s;\bsmtputf8_autodetect_classes\b;<a href="postconf.5.html#smtputf8_autodetect_classes">$&</a>;g;
s;\benable_idna2003_compatibility\b;<a href="postconf.5.html#enable_idna2003_compatibility">$&</a>;g;
+ # Internal logging.
+ s;\bmail[-</bB>]*\n*[ <bB>]*log_file\b;<a href="postconf.5.html#maillog_file">$&</a>;g;
+ s;\bpostlog_service_name\b;<a href="postconf.5.html#postlog_service_name">$&</a>;g;
+ s;\bpostlogd_watchdog_timeout\b;<a href="postconf.5.html#postlogd_watchdog_timeout">$&</a>;g;
+
# Service-defined parameters...
s;\bpolicy_time_limit\b;<a href="postconf.5.html#transport_time_limit">$&</a>;g;
# of hard-coding loopback IP address information in master.cf
# or in main.cf.
# .IP \fBunix\fR
-# The service listens on a UNIX-domain socket and is accessible
-# for local clients only.
+# The service listens on a UNIX-domain stream socket and is
+# accessible for local clients only.
#
# The service name is a pathname relative to the Postfix
# queue directory (pathname controlled with the \fBqueue_directory\fR
# .sp
# On Solaris 8 and earlier systems the \fBunix\fR type is
# implemented with streams sockets.
-# .IP \fBfifo\fR
+# .IP \fBunix-dgram\fR
+# The service listens on a UNIX-domain datagram socket and is
+# accessible for local clients only.
+#
+# The service name is a pathname relative to the Postfix
+# queue directory (pathname controlled with the \fBqueue_directory\fR
+# configuration parameter in main.cf).
+# .IP "\fBfifo\fR (obsolete)"
# The service listens on a FIFO (named pipe) and is accessible
# for local clients only.
#
# queue directory (pathname controlled with the \fBqueue_directory\fR
# configuration parameter in main.cf).
# .IP \fBpass\fR
-# The service listens on a UNIX-domain socket, and is accessible
-# to local clients only. It receives one open connection (file
-# descriptor passing) per connection request.
+# The service listens on a UNIX-domain stream socket, and is
+# accessible to local clients only. It receives one open
+# connection (file descriptor passing) per connection request.
#
# The service name is a pathname relative to the Postfix
# queue directory (pathname controlled with the \fBqueue_directory\fR
one-letter suffix that specifies the time unit). Time units: s
(seconds), m (minutes), h (hours), d (days), w (weeks). </p>
-<p> This feature is available in Postfix 2.8. </p>
+<p> This feature is available in Postfix 2.8 and later </p>
%PARAM postscreen_discard_ehlo_keywords $smtpd_discard_ehlo_keywords
parameter. See there for details. </p>
<p> This feature is available in Postfix 3.4 and later. </p>
+
+%PARAM maillog_file
+
+<p> The name of an optional logfile that is written by the Postfix
+postlogd(8) service. A non-empty value disables logging to syslogd(8).
+Specify "/dev/stdout" for logging to standard output. Stdout logging
+requires that Postfix is started with "postfix start-fg". </p>
+
+<p> Note: Some Postfix non-daemon programs may still log information
+to syslogd(8), before they have processed their configuration
+parameters and command-line options. </p>
+
+<p> This feature is available in Postfix 3.4 and later. </p>
+
+%PARAM postlog_service_name postlog
+
+<p> The name of the postlogd(8) service entry in master.cf.
+This service appends logfile records to the file specified
+with the maillog_file parameter. </p>
+
+<p> This feature is available in Postfix 3.4 and later. </p>
+
+%PARAM postlogd_watchdog_timeout 10s
+
+<p> How much time a postlogd(8) process may take to process a request
+before it is terminated by a built-in watchdog timer. This is a
+safety mechanism that prevents postlogd(8) from becoming non-responsive
+due to a bug in Postfix itself or in system software. This limit
+cannot be set under 10s. </p>
+
+<p> Specify a non-zero time value (an integral value plus an optional
+one-letter suffix that specifies the time unit). Time units: s
+(seconds), m (minutes), h (hours), d (days), w (weeks). </p>
+
+<p> This feature is available in Postfix 3.4 and later. </p>
dict_memcache.c mail_version.c memcache_proto.c server_acl.c \
mkmap_fail.c haproxy_srvr.c dsn_filter.c dynamicmaps.c uxtext.c \
smtputf8.c mail_conf_over.c mail_parm_split.c midna_adomain.c \
- mail_addr_form.c quote_flags.c
+ mail_addr_form.c quote_flags.c maillog_client.c
OBJS = abounce.o anvil_clnt.o been_here.o bounce.o bounce_log.o \
canon_addr.o cfg_parser.o cleanup_strerror.o cleanup_strflags.o \
clnt_stream.o conv_time.o db_common.o debug_peer.o debug_process.o \
dict_memcache.o mail_version.o memcache_proto.o server_acl.o \
mkmap_fail.o haproxy_srvr.o dsn_filter.o dynamicmaps.o uxtext.o \
smtputf8.o attr_override.o mail_parm_split.o midna_adomain.o \
- $(NON_PLUGIN_MAP_OBJ) mail_addr_form.o quote_flags.o
+ $(NON_PLUGIN_MAP_OBJ) mail_addr_form.o quote_flags.o maillog_client.o
# MAP_OBJ is for maps that may be dynamically loaded with dynamicmaps.cf.
# When hard-linking these maps, makedefs sets NON_PLUGIN_MAP_OBJ=$(MAP_OBJ),
# otherwise it sets the PLUGIN_* macros.
addr_match_list.h smtp_reply_footer.h safe_ultostr.h \
verify_sender_addr.h dict_memcache.h memcache_proto.h server_acl.h \
haproxy_srvr.h dsn_filter.h dynamicmaps.h uxtext.h smtputf8.h \
- attr_override.h mail_parm_split.h midna_adomain.h mail_addr_form.h
+ attr_override.h mail_parm_split.h midna_adomain.h mail_addr_form.h \
+ maillog_client.h
TESTSRC = rec2stream.c stream2rec.c recdump.c
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
mail_version.o: ../../include/vstring.h
mail_version.o: mail_version.c
mail_version.o: mail_version.h
+maillog_client.o: ../../include/attr.h
+maillog_client.o: ../../include/check_arg.h
+maillog_client.o: ../../include/htable.h
+maillog_client.o: ../../include/iostuff.h
+maillog_client.o: ../../include/logwriter.h
+maillog_client.o: ../../include/msg.h
+maillog_client.o: ../../include/msg_logger.h
+maillog_client.o: ../../include/msg_syslog.h
+maillog_client.o: ../../include/mymalloc.h
+maillog_client.o: ../../include/nvtable.h
+maillog_client.o: ../../include/safe.h
+maillog_client.o: ../../include/stringops.h
+maillog_client.o: ../../include/sys_defs.h
+maillog_client.o: ../../include/vbuf.h
+maillog_client.o: ../../include/vstream.h
+maillog_client.o: ../../include/vstring.h
+maillog_client.o: mail_params.h
+maillog_client.o: mail_proto.h
+maillog_client.o: maillog_client.c
+maillog_client.o: maillog_client.h
maps.o: ../../include/argv.h
maps.o: ../../include/check_arg.h
maps.o: ../../include/dict.h
/* int warn_compat_break_relay_domains;
/* int warn_compat_break_flush_domains;
/* int warn_compat_break_mynetworks_style;
+/*
+/* char *var_maillog_file;
+/* char *var_postlog_service;
/* DESCRIPTION
/* This module (actually the associated include file) defines
/* the names and defaults of all mail configuration parameters.
char *var_drop_hdrs;
bool var_enable_orcpt;
+char *var_maillog_file;
+char *var_postlog_service;
+
const char null_format_string[1] = "";
/*
/* multi_instance_wrapper may have dependencies but not dependents. */
VAR_MULTI_GROUP, DEF_MULTI_GROUP, &var_multi_group, 0, 0,
VAR_MULTI_NAME, DEF_MULTI_NAME, &var_multi_name, 0, 0,
+ VAR_MAILLOG_FILE, DEF_MAILLOG_FILE, &var_maillog_file, 0, 0,
+ VAR_POSTLOG_SERVICE, DEF_POSTLOG_SERVICE, &var_postlog_service, 1, 0,
0,
};
static const CONFIG_BOOL_TABLE first_bool_defaults[] = {
*/
get_mail_conf_str_table(first_str_defaults);
- if (!msg_syslog_facility(var_syslog_facility))
+ if (!msg_syslog_set_facility(var_syslog_facility))
msg_fatal("file %s/%s: parameter %s: unrecognized value: %s",
var_config_dir, MAIN_CONF_FILE,
VAR_SYSLOG_FACILITY, var_syslog_facility);
* and what Postfix exports to the external world.
*/
#define VAR_IMPORT_ENVIRON "import_environment"
-#define DEF_IMPORT_ENVIRON "MAIL_CONFIG MAIL_DEBUG MAIL_LOGTAG TZ XAUTHORITY DISPLAY LANG=C"
+#define DEF_IMPORT_ENVIRON "MAIL_CONFIG MAIL_DEBUG MAIL_LOGTAG " \
+ "TZ XAUTHORITY DISPLAY LANG=C " \
+ "POSTLOG_SERVICE POSTLOG_HOSTNAME"
extern char *var_import_environ;
#define VAR_EXPORT_ENVIRON "export_environment"
#define DEF_DNS_NCACHE_TTL_FIX 0
extern bool var_dns_ncache_ttl_fix;
+ /*
+ * Logging. As systems evolve over time, logging becomes more challenging.
+ */
+#define VAR_MAILLOG_FILE "maillog_file"
+#define DEF_MAILLOG_FILE ""
+extern char *var_maillog_file;
+
+#define VAR_POSTLOG_SERVICE "postlog_service_name"
+#define DEF_POSTLOG_SERVICE MAIL_SERVICE_POSTLOG
+extern char *var_postlog_service;
+
+#define VAR_POSTLOGD_WATCHDOG "postlogd_watchdog_timeout"
+#define DEF_POSTLOGD_WATCHDOG "10s"
+extern int var_postlogd_watchdog;
+
/* LICENSE
/* .ad
/* .fi
#define MAIL_SERVICE_SCACHE "scache"
#define MAIL_SERVICE_DNSBLOG "dnsblog"
#define MAIL_SERVICE_TLSPROXY "tlsproxy"
+#define MAIL_SERVICE_POSTLOG "postlog"
/*
* Mail source classes. Used to specify policy decisions for content
/* are easier to recognize. The mail system name is specified
/* with the "syslog_name" configuration parameter.
/*
-/* The result is volatile. Make a copy of the result if it is
-/* to be used for any appreciable amount of time.
+/* The result is overwritten with each call.
+/*
+/* A null argv0 argument requests that the current
+/* result is returned.
/* LICENSE
/* .ad
/* .fi
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
+/*
+/* Wietse Venema
+/* Google, Inc.
+/* 111 8th Avenue
+/* New York, NY 10011, USA
/*--*/
/* System library. */
const char *slash;
const char *tag;
- if (canon_name == 0)
- canon_name = vstring_alloc(10);
- if ((slash = strrchr(argv0, '/')) != 0 && slash[1])
- argv0 = slash + 1;
- /* Setenv()-ed from main.cf, or inherited from master. */
- if ((tag = safe_getenv(CONF_ENV_LOGTAG)) == 0)
- /* Check main.cf settings directly, in case set-gid. */
- tag = var_syslog_name ? var_syslog_name :
- mail_conf_eval(DEF_SYSLOG_NAME);
- vstring_sprintf(canon_name, "%s/%s", tag, argv0);
+ if (argv0) {
+ if (canon_name == 0)
+ canon_name = vstring_alloc(10);
+ if ((slash = strrchr(argv0, '/')) != 0 && slash[1])
+ argv0 = slash + 1;
+ /* Setenv()-ed from main.cf, or inherited from master. */
+ if ((tag = safe_getenv(CONF_ENV_LOGTAG)) == 0)
+ /* Check main.cf settings directly, in case set-gid. */
+ tag = var_syslog_name ? var_syslog_name :
+ mail_conf_eval(DEF_SYSLOG_NAME);
+ vstring_sprintf(canon_name, "%s/%s", tag, argv0);
+ }
return (vstring_str(canon_name));
}
* Patches change both the patchlevel and the release date. Snapshots have no
* patchlevel; they change the release date only.
*/
-#define MAIL_RELEASE_DATE "20190127"
+#define MAIL_RELEASE_DATE "20190129"
#define MAIL_VERSION_NUMBER "3.4"
#ifdef SNAPSHOT
--- /dev/null
+/*++
+/* NAME
+/* maillog_client 3
+/* SUMMARY
+/* choose between syslog client and postlog client
+/* SYNOPSIS
+/* #include <maillog_client.h>
+/*
+/* int maillog_client_init(
+/* const char *progname,
+/* int flags)
+/* DESCRIPTION
+/* maillog_client_init() chooses between logging to the syslog
+/* service or to the internal postlog service.
+/*
+/* maillog_client_init() may be called before configuration
+/* parameters are initialized. During this time, logging is
+/* controlled by the presence or absence of POSTLOG_SERVICE
+/* in the process environment (this is ignored if a program
+/* runs with set-uid or set-gid permissions).
+/*
+/* maillog_client_init() may also be called after configuration
+/* parameters are initialized. During this time, logging is
+/* controlled by the "maillog_file" parameter value.
+/*
+/* Arguments:
+/* .IP progname
+/* The program name that will be prepended to logfile records.
+/* .IP flags
+/* Specify one of the following:
+/* .RS
+/* .IP MAILLOG_CLIENT_FLAG_NONE
+/* No special processing.
+/* .IP MAILLOG_CLIENT_FLAG_LOGWRITER_FALLBACK
+/* Try to fall back to writing the "maillog_file" directly,
+/* if logging to the internal postlog service is enabled, but
+/* the postlog service is unavailable. If the fallback fails,
+/* die with a fatal error.
+/* .RE
+/* ENVIRONMENT
+/* .ad
+/* .fi
+/* When logging to the internal postlog service is enabled,
+/* each process exports the following information, to help
+/* initialize the logging in a child process, before the child
+/* has initialized its configuration parameters.
+/* .IP POSTLOG_SERVICE
+/* The pathname of the public postlog service endpoint, usually
+/* "$queue_directory/public/$postlog_service_name".
+/* .IP POSTLOG_HOSTNAME
+/* The hostname to prepend to information that is sent to the
+/* internal postlog logging service, usually "$myhostname".
+/* CONFIGURATION PARAMETERS
+/* .ad
+/* .fi
+/* .IP "maillog_file (empty)"
+/* The name of an optional logfile. If the value is empty, or
+/* unitialized and the process environment does not specify
+/* POSTLOG_SERVICE, the program will log to the syslog service
+/* instead.
+/* .IP "myhostname (default: see postconf -d output)"
+/* The internet hostname of this mail system.
+/* .IP "postlog_service_name (postlog)"
+/* The name of the internal postlog logging service.
+/* SEE ALSO
+/* msg_syslog(3) syslog client
+/* msg_logger(3) internal logger
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this
+/* software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* Google, Inc.
+/* 111 8th Avenue
+/* New York, NY 10011, USA
+/*--*/
+
+ /*
+ * System library.
+ */
+#include <sys_defs.h>
+
+ /*
+ * Utility library.
+ */
+#include <logwriter.h>
+#include <msg_logger.h>
+#include <msg_syslog.h>
+#include <safe.h>
+#include <stringops.h>
+
+ /*
+ * Global library.
+ */
+#include <mail_params.h>
+#include <mail_proto.h>
+#include <maillog_client.h>
+#include <msg.h>
+
+ /*
+ * Using logging to debug logging is painful.
+ */
+#define MAILLOG_CLIENT_DEBUG 0
+
+ /*
+ * Application-specific.
+ */
+static int maillog_client_flags;
+
+#define POSTLOG_SERVICE_ENV "POSTLOG_SERVICE"
+#define POSTLOG_HOSTNAME_ENV "POSTLOG_HOSTNAME"
+
+/* maillog_client_logwriter_fallback - fall back to logfile writer or bust */
+
+static void maillog_client_logwriter_fallback(const char *text)
+{
+ static int fallback_guard = 0;
+
+ /*
+ * Guard against recursive calls.
+ *
+ * If an error happened before the maillog_file parameter was initialized,
+ * or if maillog_file logging is disabled, then we cannot fall back to a
+ * logfile. All we can do is to hope that stderr logging will bring out
+ * the bad news.
+ */
+ if (fallback_guard == 0 && var_maillog_file && *var_maillog_file
+ && logwriter_one_shot(var_maillog_file, text, strlen(text)) < 0) {
+ fallback_guard = 1;
+ msg_fatal("logfile '%s' write error: %m", var_maillog_file);
+ }
+}
+
+/* maillog_client_init - set up syslog or internal log client */
+
+void maillog_client_init(const char *progname, int flags)
+{
+ char *import_service_path;
+ char *import_hostname;
+
+ /*
+ * Crucially, only one logger mode can be in effect at any time,
+ * otherwise postlogd(8) may go into a loop.
+ */
+ enum {
+ MAILLOG_CLIENT_MODE_SYSLOG, MAILLOG_CLIENT_MODE_POSTLOG,
+ } logger_mode;
+
+ /*
+ * Security: this code may run before the import_environment setting has
+ * taken effect. It has to guard against privilege escalation attacks on
+ * setgid programs, using malicious environment settings.
+ *
+ * Import the postlog service name and hostname from the environment.
+ *
+ * - These will be used and kept if the process has not yet initialized its
+ * configuration parameters.
+ *
+ * - These will be set or updated if the configuration enables postlog
+ * logging.
+ *
+ * - These will be removed if the configuration does not enable postlog
+ * logging.
+ */
+ if ((import_service_path = safe_getenv(POSTLOG_SERVICE_ENV)) != 0
+ && *import_service_path == 0)
+ import_service_path = 0;
+ if ((import_hostname = safe_getenv(POSTLOG_HOSTNAME_ENV)) != 0
+ && *import_hostname == 0)
+ import_hostname = 0;
+
+#if MAILLOG_CLIENT_DEBUG
+#define STRING_OR_NULL(s) ((s) ? (s) : "(null)")
+ msg_syslog_init(progname, LOG_PID, LOG_FACILITY);
+ msg_info("import_service_path=%s", STRING_OR_NULL(import_service_path));
+ msg_info("import_hostname=%s", STRING_OR_NULL(import_hostname));
+#endif
+
+ /*
+ * Before configuration parameters are initialized, the logging mode is
+ * controlled by the presence or absence of POSTLOG_SERVICE in the
+ * process environment. After configuration parameters are initialized,
+ * the logging mode is controlled by the "maillog_file" parameter value.
+ *
+ * The configured mode may change after a process is started. The
+ * postlogd(8) server will proxy logging to syslogd where needed.
+ */
+ if (var_maillog_file ? *var_maillog_file == 0 : import_service_path == 0) {
+ logger_mode = MAILLOG_CLIENT_MODE_SYSLOG;
+ } else {
+ /* var_maillog_file ? *var_maillog_file : import_service_path != 0 */
+ logger_mode = MAILLOG_CLIENT_MODE_POSTLOG;
+ }
+
+ /*
+ * Postlog logging is enabled. Update the 'progname' as that may have
+ * changed since an earlier call, and update the environment settings if
+ * they differ from configuration settings. This blends two code paths,
+ * one code path where configuration parameters are initialized (the
+ * preferred path), and one code path that uses imports from environment.
+ */
+ if (logger_mode == MAILLOG_CLIENT_MODE_POSTLOG) {
+ char *myhostname;
+ char *service_path;
+
+ if (var_myhostname && *var_myhostname) {
+ myhostname = var_myhostname;
+ } else if ((myhostname = import_hostname) == 0) {
+ myhostname = "amnesiac";
+ }
+#if MAILLOG_CLIENT_DEBUG
+ msg_info("myhostname=%s", STRING_OR_NULL(myhostname));
+#endif
+ if (var_postlog_service) {
+ service_path = concatenate(var_queue_dir, "/", MAIL_CLASS_PUBLIC,
+ "/", var_postlog_service, (char *) 0);
+ } else {
+ service_path = import_service_path;
+ }
+ maillog_client_flags = flags;
+ msg_logger_init(progname, myhostname, service_path,
+ (flags & MAILLOG_CLIENT_FLAG_LOGWRITER_FALLBACK) ?
+ maillog_client_logwriter_fallback :
+ (MSG_LOGGER_FALLBACK_FN) 0);
+
+ /*
+ * Export or update the exported postlog service pathname and the
+ * hostname, so that a child process can bootstrap postlog logging
+ * before it has processed main.cf and command-line options.
+ */
+ if (import_service_path == 0
+ || strcmp(service_path, import_service_path) != 0) {
+#if MAILLOG_CLIENT_DEBUG
+ msg_info("export %s=%s", POSTLOG_SERVICE_ENV, service_path);
+#endif
+ if (setenv(POSTLOG_SERVICE_ENV, service_path, 1) < 0)
+ msg_fatal("setenv: %m");
+ }
+ if (import_hostname == 0 || strcmp(myhostname, import_hostname) != 0) {
+#if MAILLOG_CLIENT_DEBUG
+ msg_info("export %s=%s", POSTLOG_HOSTNAME_ENV, myhostname);
+#endif
+ if (setenv(POSTLOG_HOSTNAME_ENV, myhostname, 1) < 0)
+ msg_fatal("setenv: %m");
+ }
+ if (service_path != import_service_path)
+ myfree(service_path);
+ }
+
+ /*
+ * Postlog logging is disabled. Silence the msg_logger client, and remove
+ * the environment settings that bootstrap postlog logging in a child
+ * process.
+ */
+ else {
+ msg_logger_control(CA_MSG_LOGGER_CTL_DISABLE, CA_MSG_LOGGER_CTL_END);
+ if ((import_service_path && unsetenv(POSTLOG_SERVICE_ENV))
+ || (import_hostname && unsetenv(POSTLOG_HOSTNAME_ENV)))
+ msg_fatal("unsetenv: %m");
+ }
+
+ /*
+ * Syslog logging is enabled. Update the 'progname' as that may have
+ * changed since an earlier call.
+ */
+ if (logger_mode == MAILLOG_CLIENT_MODE_SYSLOG) {
+ msg_syslog_init(progname, LOG_PID, LOG_FACILITY);
+ }
+
+ /*
+ * Syslog logging is disabled, silence the syslog client.
+ */
+ else {
+ msg_syslog_disable();
+ }
+}
--- /dev/null
+#ifndef _MAILLOG_CLIENT_H_INCLUDED_
+#define _MAILLOG_CLIENT_H_INCLUDED_
+
+/*++
+/* NAME
+/* maillog_client 3h
+/* SUMMARY
+/* choose between syslog client and postlog client
+/* SYNOPSIS
+/* #include <maillog_client.h>
+/* DESCRIPTION
+/* .nf
+
+ /*
+ * External interface.
+ */
+#define MAILLOG_CLIENT_FLAG_NONE (0)
+#define MAILLOG_CLIENT_FLAG_LOGWRITER_FALLBACK (1<<0)
+
+extern void maillog_client_init(const char *, int);
+
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* Google, Inc.
+/* 111 8th Avenue
+/* New York, NY 10011, USA
+/*--*/
+
+#endif
master_spawn.c master_service.c master_status.c master_listen.c \
master_proto.c single_server.c multi_server.c master_vars.c \
master_wakeup.c master_flow.c master_watch.c mail_flow.c \
- master_monitor.c
+ master_monitor.c dgram_server.c
OBJS = master.o master_conf.o master_ent.o master_sig.o master_avail.o \
master_spawn.o master_service.o master_status.o master_listen.o \
master_vars.o master_wakeup.o master_watch.o master_flow.o \
master_monitor.o
LIB_OBJ = single_server.o multi_server.o trigger_server.o master_proto.o \
- mail_flow.o event_server.o
+ mail_flow.o event_server.o dgram_server.o
HDRS = mail_server.h master_proto.h mail_flow.h
INT_HDR = master.h
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
@$(EXPORT) make -f Makefile.in Makefile 1>&2
# do not edit below this line - it is generated by 'make depend'
+dgram_server.o: ../../include/argv.h
+dgram_server.o: ../../include/attr.h
+dgram_server.o: ../../include/bounce.h
+dgram_server.o: ../../include/check_arg.h
+dgram_server.o: ../../include/chroot_uid.h
+dgram_server.o: ../../include/debug_process.h
+dgram_server.o: ../../include/deliver_request.h
+dgram_server.o: ../../include/dict.h
+dgram_server.o: ../../include/dsn.h
+dgram_server.o: ../../include/dsn_buf.h
+dgram_server.o: ../../include/events.h
+dgram_server.o: ../../include/htable.h
+dgram_server.o: ../../include/iostuff.h
+dgram_server.o: ../../include/listen.h
+dgram_server.o: ../../include/mail_conf.h
+dgram_server.o: ../../include/mail_dict.h
+dgram_server.o: ../../include/mail_params.h
+dgram_server.o: ../../include/mail_task.h
+dgram_server.o: ../../include/mail_version.h
+dgram_server.o: ../../include/maillog_client.h
+dgram_server.o: ../../include/msg.h
+dgram_server.o: ../../include/msg_stats.h
+dgram_server.o: ../../include/msg_vstream.h
+dgram_server.o: ../../include/myflock.h
+dgram_server.o: ../../include/mymalloc.h
+dgram_server.o: ../../include/nvtable.h
+dgram_server.o: ../../include/recipient_list.h
+dgram_server.o: ../../include/resolve_local.h
+dgram_server.o: ../../include/safe_open.h
+dgram_server.o: ../../include/sane_accept.h
+dgram_server.o: ../../include/split_at.h
+dgram_server.o: ../../include/stringops.h
+dgram_server.o: ../../include/sys_defs.h
+dgram_server.o: ../../include/vbuf.h
+dgram_server.o: ../../include/vstream.h
+dgram_server.o: ../../include/vstring.h
+dgram_server.o: ../../include/watchdog.h
+dgram_server.o: dgram_server.c
+dgram_server.o: mail_flow.h
+dgram_server.o: mail_server.h
+dgram_server.o: master_proto.h
event_server.o: ../../include/argv.h
event_server.o: ../../include/attr.h
event_server.o: ../../include/bounce.h
event_server.o: ../../include/mail_params.h
event_server.o: ../../include/mail_task.h
event_server.o: ../../include/mail_version.h
+event_server.o: ../../include/maillog_client.h
event_server.o: ../../include/msg.h
event_server.o: ../../include/msg_stats.h
-event_server.o: ../../include/msg_syslog.h
event_server.o: ../../include/msg_vstream.h
event_server.o: ../../include/myflock.h
event_server.o: ../../include/mymalloc.h
master.o: ../../include/mail_parm_split.h
master.o: ../../include/mail_task.h
master.o: ../../include/mail_version.h
+master.o: ../../include/maillog_client.h
master.o: ../../include/msg.h
-master.o: ../../include/msg_syslog.h
master.o: ../../include/myflock.h
master.o: ../../include/mymalloc.h
master.o: ../../include/open_lock.h
multi_server.o: ../../include/mail_params.h
multi_server.o: ../../include/mail_task.h
multi_server.o: ../../include/mail_version.h
+multi_server.o: ../../include/maillog_client.h
multi_server.o: ../../include/msg.h
multi_server.o: ../../include/msg_stats.h
-multi_server.o: ../../include/msg_syslog.h
multi_server.o: ../../include/msg_vstream.h
multi_server.o: ../../include/myflock.h
multi_server.o: ../../include/mymalloc.h
single_server.o: ../../include/mail_params.h
single_server.o: ../../include/mail_task.h
single_server.o: ../../include/mail_version.h
+single_server.o: ../../include/maillog_client.h
single_server.o: ../../include/msg.h
single_server.o: ../../include/msg_stats.h
-single_server.o: ../../include/msg_syslog.h
single_server.o: ../../include/msg_vstream.h
single_server.o: ../../include/myflock.h
single_server.o: ../../include/mymalloc.h
trigger_server.o: ../../include/mail_params.h
trigger_server.o: ../../include/mail_task.h
trigger_server.o: ../../include/mail_version.h
+trigger_server.o: ../../include/maillog_client.h
trigger_server.o: ../../include/msg.h
trigger_server.o: ../../include/msg_stats.h
-trigger_server.o: ../../include/msg_syslog.h
trigger_server.o: ../../include/msg_vstream.h
trigger_server.o: ../../include/myflock.h
trigger_server.o: ../../include/mymalloc.h
--- /dev/null
+/*++
+/* NAME
+/* dgram_server 3
+/* SUMMARY
+/* skeleton datagram server subsystem
+/* SYNOPSIS
+/* #include <mail_server.h>
+/*
+/* NORETURN dgram_server_main(argc, argv, service, key, value, ...)
+/* int argc;
+/* char **argv;
+/* void (*service)(char *buf, int len, char *service_name, char **argv);
+/* int key;
+/* DESCRIPTION
+/* This module implements a skeleton for mail subsystem programs
+/* that wake up on client request and perform some activity
+/* without further client interaction. This module supports
+/* local IPC via a UNIX-domain datagram socket. The resulting
+/* program expects to be run from the \fBmaster\fR process.
+/*
+/* dgram_server_main() is the skeleton entry point. It should
+/* be called from the application main program. The skeleton
+/* does the generic command-line options processing, initialization
+/* of configurable parameters, and receiving datagrams. The
+/* skeleton never returns.
+/*
+/* Arguments:
+/* .IP "void (*service)(char *buf, int len, char *service_name, char **argv)"
+/* A pointer to a function that is called by the skeleton each
+/* time a client sends a datagram to the program's service
+/* port. The function is run after the program has irrevocably
+/* dropped its privileges. The buffer argument specifies the
+/* data read from the datagram port; this data corresponds to
+/* request. The len argument specifies how much client data
+/* is available. The maximal size of the buffer is specified
+/* via the DGRAM_BUF_SIZE manifest constant. The service name
+/* argument corresponds to the service name in the master.cf
+/* file. The argv argument specifies command-line arguments
+/* left over after options processing.
+/* .PP
+/* Optional arguments are specified as a null-terminated list
+/* with macros that have zero or more arguments:
+/* .IP "CA_MAIL_SERVER_INT_TABLE(CONFIG_INT_TABLE *)"
+/* A table with configurable parameters, to be loaded from the
+/* global Postfix configuration file. Tables are loaded in the
+/* order as specified, and multiple instances of the same type
+/* are allowed.
+/* .IP "CA_MAIL_SERVER_LONG_TABLE(CONFIG_LONG_TABLE *)"
+/* A table with configurable parameters, to be loaded from the
+/* global Postfix configuration file. Tables are loaded in the
+/* order as specified, and multiple instances of the same type
+/* are allowed.
+/* .IP "CA_MAIL_SERVER_STR_TABLE(CONFIG_STR_TABLE *)"
+/* A table with configurable parameters, to be loaded from the
+/* global Postfix configuration file. Tables are loaded in the
+/* order as specified, and multiple instances of the same type
+/* are allowed.
+/* .IP "CA_MAIL_SERVER_BOOL_TABLE(CONFIG_BOOL_TABLE *)"
+/* A table with configurable parameters, to be loaded from the
+/* global Postfix configuration file. Tables are loaded in the
+/* order as specified, and multiple instances of the same type
+/* are allowed.
+/* .IP "CA_MAIL_SERVER_TIME_TABLE(CONFIG_TIME_TABLE *)"
+/* A table with configurable parameters, to be loaded from the
+/* global Postfix configuration file. Tables are loaded in the
+/* order as specified, and multiple instances of the same type
+/* are allowed.
+/* .IP "CA_MAIL_SERVER_RAW_TABLE(CONFIG_RAW_TABLE *)"
+/* A table with configurable parameters, to be loaded from the
+/* global Postfix configuration file. Tables are loaded in the
+/* order as specified, and multiple instances of the same type
+/* are allowed. Raw parameters are not subjected to $name
+/* evaluation.
+/* .IP "CA_MAIL_SERVER_NINT_TABLE(CONFIG_NINT_TABLE *)"
+/* A table with configurable parameters, to be loaded from the
+/* global Postfix configuration file. Tables are loaded in the
+/* order as specified, and multiple instances of the same type
+/* are allowed.
+/* .IP "CA_MAIL_SERVER_NBOOL_TABLE(CONFIG_NBOOL_TABLE *)"
+/* A table with configurable parameters, to be loaded from the
+/* global Postfix configuration file. Tables are loaded in the
+/* order as specified, and multiple instances of the same type
+/* are allowed.
+/* .IP "CA_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.
+/* .sp
+/* Only the last instance of this parameter type is remembered.
+/* .IP "CA_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.
+/* .sp
+/* Only the last instance of this parameter type is remembered.
+/* .IP "CA_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".
+/* .sp
+/* Only the last instance of this parameter type is remembered.
+/* .IP "CA_MAIL_SERVER_EXIT(void *(char *service_name, char **argv))"
+/* A pointer to function that is executed immediately before normal
+/* process termination.
+/* .sp
+/* Only the last instance of this parameter type is remembered.
+/* .IP "CA_MAIL_SERVER_PRE_ACCEPT(void *(char *service_name, char **argv))"
+/* Function to be executed prior to accepting a new request.
+/* .sp
+/* Only the last instance of this parameter type is remembered.
+/* .IP "CA_MAIL_SERVER_IN_FLOW_DELAY(none)"
+/* Pause $in_flow_delay seconds when no "mail flow control token"
+/* is available. A token is consumed for each connection request.
+/* .IP CA_MAIL_SERVER_SOLITARY
+/* This service must be configured with process limit of 1.
+/* .IP CA_MAIL_SERVER_UNLIMITED
+/* This service must be configured with process limit of 0.
+/* .IP CA_MAIL_SERVER_PRIVILEGED
+/* This service must be configured as privileged.
+/* .IP "CA_MAIL_SERVER_WATCHDOG(int *)"
+/* Override the default 1000s watchdog timeout. The value is
+/* used after command-line and main.cf file processing.
+/* .IP "CA_MAIL_SERVER_BOUNCE_INIT(const char *, const char **)"
+/* Initialize the DSN filter for the bounce/defer service
+/* clients with the specified map source and map names.
+/* .PP
+/* The var_use_limit variable limits the number of clients that
+/* a server can service before it commits suicide.
+/* This value is taken from the global \fBmain.cf\fR configuration
+/* file. Setting \fBvar_use_limit\fR to zero disables the client limit.
+/*
+/* The var_idle_limit variable limits the time that a service
+/* receives no client connection requests before it commits suicide.
+/* This value is taken from the global \fBmain.cf\fR configuration
+/* file. Setting \fBvar_use_limit\fR to zero disables the idle limit.
+/* DIAGNOSTICS
+/* Problems and transactions are logged to \fBsyslogd\fR(8).
+/* SEE ALSO
+/* master(8), master process
+/* syslogd(8) system logging
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* Google, Inc.
+/* 111 8th Avenue
+/* New York, NY 10011, USA
+/*--*/
+
+/* System library. */
+
+#include <sys_defs.h>
+#include <sys/socket.h>
+#include <unistd.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#ifdef STRCASECMP_IN_STRINGS_H
+#include <strings.h>
+#endif
+#include <time.h>
+
+/* Utility library. */
+
+#include <msg.h>
+#include <msg_vstream.h>
+#include <chroot_uid.h>
+#include <vstring.h>
+#include <vstream.h>
+#include <msg_vstream.h>
+#include <mymalloc.h>
+#include <events.h>
+#include <iostuff.h>
+#include <stringops.h>
+#include <sane_accept.h>
+#include <myflock.h>
+#include <safe_open.h>
+#include <listen.h>
+#include <watchdog.h>
+#include <split_at.h>
+
+/* Global library. */
+
+#include <mail_params.h>
+#include <mail_task.h>
+#include <debug_process.h>
+#include <mail_conf.h>
+#include <mail_dict.h>
+#include <resolve_local.h>
+#include <mail_flow.h>
+#include <mail_version.h>
+#include <bounce.h>
+#include <maillog_client.h>
+
+/* Process manager. */
+
+#include "master_proto.h"
+
+/* Application-specific */
+
+#include "mail_server.h"
+
+ /*
+ * Global state.
+ */
+static int use_count;
+
+static DGRAM_SERVER_FN dgram_server_service;
+static char *dgram_server_name;
+static char **dgram_server_argv;
+static void (*dgram_server_accept) (int, void *);
+static void (*dgram_server_onexit) (char *, char **);
+static void (*dgram_server_pre_accept) (char *, char **);
+static VSTREAM *dgram_server_lock;
+static int dgram_server_in_flow_delay;
+static unsigned dgram_server_generation;
+static int dgram_server_watchdog = 1000;
+
+/* dgram_server_exit - normal termination */
+
+static NORETURN dgram_server_exit(void)
+{
+ if (dgram_server_onexit)
+ dgram_server_onexit(dgram_server_name, dgram_server_argv);
+ exit(0);
+}
+
+/* dgram_server_abort - terminate after abnormal master exit */
+
+static void dgram_server_abort(int unused_event, void *unused_context)
+{
+ if (msg_verbose)
+ msg_info("master disconnect -- exiting");
+ dgram_server_exit();
+}
+
+/* dgram_server_timeout - idle time exceeded */
+
+static void dgram_server_timeout(int unused_event, void *unused_context)
+{
+ if (msg_verbose)
+ msg_info("idle timeout -- exiting");
+ dgram_server_exit();
+}
+
+/* dgram_server_wakeup - wake up application */
+
+static void dgram_server_wakeup(int fd)
+{
+ char buf[DGRAM_BUF_SIZE];
+ ssize_t len;
+
+ /*
+ * Commit suicide when the master process disconnected from us, after
+ * handling the client request.
+ */
+ if (master_notify(var_pid, dgram_server_generation, MASTER_STAT_TAKEN) < 0)
+ /* void */ ;
+ if (dgram_server_in_flow_delay && mail_flow_get(1) < 0)
+ doze(var_in_flow_delay * 1000000);
+ if ((len = recv(fd, buf, sizeof(buf), 0)) >= 0)
+ dgram_server_service(buf, len, dgram_server_name, dgram_server_argv);
+ if (master_notify(var_pid, dgram_server_generation, MASTER_STAT_AVAIL) < 0)
+ dgram_server_abort(EVENT_NULL_TYPE, EVENT_NULL_CONTEXT);
+ if (var_idle_limit > 0)
+ event_request_timer(dgram_server_timeout, (void *) 0, var_idle_limit);
+ /* Avoid integer wrap-around in a persistent process. */
+ if (use_count < INT_MAX)
+ use_count++;
+}
+
+/* dgram_server_accept_unix - handle UNIX-domain socket event */
+
+static void dgram_server_accept_unix(int unused_event, void *context)
+{
+ const char *myname = "dgram_server_accept";
+ int listen_fd = CAST_ANY_PTR_TO_INT(context);
+
+ if (dgram_server_lock != 0
+ && myflock(vstream_fileno(dgram_server_lock), INTERNAL_LOCK,
+ MYFLOCK_OP_NONE) < 0)
+ msg_fatal("select unlock: %m");
+
+ if (msg_verbose)
+ msg_info("%s: request arrived", myname);
+
+ /*
+ * Read whatever the other side wrote. The socket is non-blocking so we
+ * won't get stuck when multiple processes wake up.
+ */
+ if (dgram_server_pre_accept)
+ dgram_server_pre_accept(dgram_server_name, dgram_server_argv);
+ dgram_server_wakeup(listen_fd);
+}
+
+/* dgram_server_main - the real main program */
+
+NORETURN dgram_server_main(int argc, char **argv, DGRAM_SERVER_FN service,...)
+{
+ const char *myname = "dgram_server_main";
+ char *root_dir = 0;
+ char *user_name = 0;
+ int debug_me = 0;
+ int daemon_mode = 1;
+ char *service_name = basename(argv[0]);
+ int delay;
+ int c;
+ int socket_count = 1;
+ int fd;
+ va_list ap;
+ MAIL_SERVER_INIT_FN pre_init = 0;
+ MAIL_SERVER_INIT_FN post_init = 0;
+ MAIL_SERVER_LOOP_FN loop = 0;
+ int key;
+ char *transport = 0;
+ char *lock_path;
+ VSTRING *why;
+ int alone = 0;
+ int zerolimit = 0;
+ WATCHDOG *watchdog;
+ char *oname_val;
+ char *oname;
+ char *oval;
+ const char *err;
+ char *generation;
+ int msg_vstream_needed = 0;
+ const char *dsn_filter_title;
+ const char **dsn_filter_maps;
+
+ /*
+ * Process environment options as early as we can.
+ */
+ if (getenv(CONF_ENV_VERB))
+ msg_verbose = 1;
+ if (getenv(CONF_ENV_DEBUG))
+ debug_me = 1;
+
+ /*
+ * Don't die when a process goes away unexpectedly.
+ */
+ signal(SIGPIPE, SIG_IGN);
+
+ /*
+ * Don't die for frivolous reasons.
+ */
+#ifdef SIGXFSZ
+ signal(SIGXFSZ, SIG_IGN);
+#endif
+
+ /*
+ * May need this every now and then.
+ */
+ var_procname = mystrdup(basename(argv[0]));
+ set_mail_conf_str(VAR_PROCNAME, var_procname);
+
+ /*
+ * Initialize logging and exit handler. Do the syslog first, so that its
+ * initialization completes before we enter the optional chroot jail.
+ */
+ maillog_client_init(mail_task(var_procname), MAILLOG_CLIENT_FLAG_NONE);
+ if (msg_verbose)
+ msg_info("daemon started");
+
+ /*
+ * Check the Postfix library version as soon as we enable logging.
+ */
+ MAIL_VERSION_CHECK;
+
+ /*
+ * Initialize from the configuration file. Allow command-line options to
+ * override compiled-in defaults or configured parameter values.
+ */
+ mail_conf_suck();
+
+ /*
+ * After database open error, continue execution with reduced
+ * functionality.
+ */
+ dict_allow_surrogate = 1;
+
+ /*
+ * Pick up policy settings from master process. Shut up error messages to
+ * stderr, because no-one is going to see them.
+ */
+ opterr = 0;
+ while ((c = GETOPT(argc, argv, "cdDi:lm:n:o:s:t:uvVz")) > 0) {
+ switch (c) {
+ case 'c':
+ root_dir = "setme";
+ break;
+ case 'd':
+ daemon_mode = 0;
+ break;
+ case 'D':
+ debug_me = 1;
+ break;
+ case 'i':
+ mail_conf_update(VAR_MAX_IDLE, optarg);
+ break;
+ case 'l':
+ alone = 1;
+ break;
+ case 'm':
+ mail_conf_update(VAR_MAX_USE, optarg);
+ break;
+ case 'n':
+ service_name = optarg;
+ break;
+ case 'o':
+ oname_val = mystrdup(optarg);
+ if ((err = split_nameval(oname_val, &oname, &oval)) != 0)
+ msg_fatal("invalid \"-o %s\" option value: %s", optarg, err);
+ mail_conf_update(oname, oval);
+ myfree(oname_val);
+ break;
+ case 's':
+ if ((socket_count = atoi(optarg)) <= 0)
+ msg_fatal("invalid socket_count: %s", optarg);
+ break;
+ case 't':
+ transport = optarg;
+ break;
+ case 'u':
+ user_name = "setme";
+ break;
+ case 'v':
+ msg_verbose++;
+ break;
+ case 'V':
+ if (++msg_vstream_needed == 1)
+ msg_vstream_init(mail_task(var_procname), VSTREAM_ERR);
+ break;
+ case 'z':
+ zerolimit = 1;
+ break;
+ default:
+ msg_fatal("invalid option: %c", optopt);
+ break;
+ }
+ }
+ set_mail_conf_str(VAR_SERVNAME, service_name);
+
+ /*
+ * Initialize generic parameters and re-initialize logging in case of a
+ * non-default program name or logging destination.
+ */
+ mail_params_init();
+ maillog_client_init(mail_task(var_procname), MAILLOG_CLIENT_FLAG_NONE);
+
+ /*
+ * Register higher-level dictionaries and initialize the support for
+ * dynamically-loaded dictionarles.
+ */
+ mail_dict_init();
+
+ /*
+ * If not connected to stdin, stdin must not be a terminal.
+ */
+ if (daemon_mode && isatty(STDIN_FILENO)) {
+ msg_vstream_init(var_procname, VSTREAM_ERR);
+ msg_fatal("do not run this command by hand");
+ }
+
+ /*
+ * Application-specific initialization.
+ */
+ va_start(ap, service);
+ while ((key = va_arg(ap, int)) != 0) {
+ switch (key) {
+ case MAIL_SERVER_INT_TABLE:
+ get_mail_conf_int_table(va_arg(ap, CONFIG_INT_TABLE *));
+ break;
+ case MAIL_SERVER_LONG_TABLE:
+ get_mail_conf_long_table(va_arg(ap, CONFIG_LONG_TABLE *));
+ break;
+ case MAIL_SERVER_STR_TABLE:
+ get_mail_conf_str_table(va_arg(ap, CONFIG_STR_TABLE *));
+ break;
+ case MAIL_SERVER_BOOL_TABLE:
+ get_mail_conf_bool_table(va_arg(ap, CONFIG_BOOL_TABLE *));
+ break;
+ case MAIL_SERVER_TIME_TABLE:
+ get_mail_conf_time_table(va_arg(ap, CONFIG_TIME_TABLE *));
+ break;
+ case MAIL_SERVER_RAW_TABLE:
+ get_mail_conf_raw_table(va_arg(ap, CONFIG_RAW_TABLE *));
+ break;
+ case MAIL_SERVER_NINT_TABLE:
+ get_mail_conf_nint_table(va_arg(ap, CONFIG_NINT_TABLE *));
+ break;
+ case MAIL_SERVER_NBOOL_TABLE:
+ get_mail_conf_nbool_table(va_arg(ap, CONFIG_NBOOL_TABLE *));
+ break;
+ case MAIL_SERVER_PRE_INIT:
+ pre_init = va_arg(ap, MAIL_SERVER_INIT_FN);
+ break;
+ case MAIL_SERVER_POST_INIT:
+ post_init = va_arg(ap, MAIL_SERVER_INIT_FN);
+ break;
+ case MAIL_SERVER_LOOP:
+ loop = va_arg(ap, MAIL_SERVER_LOOP_FN);
+ break;
+ case MAIL_SERVER_EXIT:
+ dgram_server_onexit = va_arg(ap, MAIL_SERVER_EXIT_FN);
+ break;
+ case MAIL_SERVER_PRE_ACCEPT:
+ dgram_server_pre_accept = va_arg(ap, MAIL_SERVER_ACCEPT_FN);
+ break;
+ case MAIL_SERVER_IN_FLOW_DELAY:
+ dgram_server_in_flow_delay = 1;
+ break;
+ case MAIL_SERVER_SOLITARY:
+ if (!alone)
+ msg_fatal("service %s requires a process limit of 1",
+ service_name);
+ break;
+ case MAIL_SERVER_UNLIMITED:
+ if (!zerolimit)
+ msg_fatal("service %s requires a process limit of 0",
+ service_name);
+ break;
+ case MAIL_SERVER_PRIVILEGED:
+ if (user_name)
+ msg_fatal("service %s requires privileged operation",
+ service_name);
+ break;
+ case MAIL_SERVER_WATCHDOG:
+ dgram_server_watchdog = *va_arg(ap, int *);
+ break;
+ case MAIL_SERVER_BOUNCE_INIT:
+ dsn_filter_title = va_arg(ap, const char *);
+ dsn_filter_maps = va_arg(ap, const char **);
+ bounce_client_init(dsn_filter_title, *dsn_filter_maps);
+ break;
+ default:
+ msg_panic("%s: unknown argument type: %d", myname, key);
+ }
+ }
+ va_end(ap);
+
+ if (root_dir)
+ root_dir = var_queue_dir;
+ if (user_name)
+ user_name = var_mail_owner;
+
+ /*
+ * Can options be required?
+ */
+ if (transport == 0)
+ msg_fatal("no transport type specified");
+ else if (strcasecmp(transport, MASTER_XPORT_NAME_UXDG) == 0)
+ dgram_server_accept = dgram_server_accept_unix;
+ else
+ msg_fatal("unsupported transport type: %s", transport);
+
+ /*
+ * Retrieve process generation from environment.
+ */
+ if ((generation = getenv(MASTER_GEN_NAME)) != 0) {
+ if (!alldig(generation))
+ msg_fatal("bad generation: %s", generation);
+ OCTAL_TO_UNSIGNED(dgram_server_generation, generation);
+ if (msg_verbose)
+ msg_info("process generation: %s (%o)",
+ generation, dgram_server_generation);
+ }
+
+ /*
+ * Optionally start the debugger on ourself.
+ */
+ if (debug_me)
+ debug_process();
+
+ /*
+ * Traditionally, BSD select() can't handle multiple processes selecting
+ * on the same socket, and wakes up every process in select(). See TCP/IP
+ * Illustrated volume 2 page 532. We avoid select() collisions with an
+ * external lock file.
+ */
+ if (!alone) {
+ lock_path = concatenate(DEF_PID_DIR, "/", transport,
+ ".", service_name, (char *) 0);
+ why = vstring_alloc(1);
+ if ((dgram_server_lock = safe_open(lock_path, O_CREAT | O_RDWR, 0600,
+ (struct stat *) 0, -1, -1, why)) == 0)
+ msg_fatal("open lock file %s: %s", lock_path, vstring_str(why));
+ close_on_exec(vstream_fileno(dgram_server_lock), CLOSE_ON_EXEC);
+ myfree(lock_path);
+ vstring_free(why);
+ }
+
+ /*
+ * Set up call-back info.
+ */
+ dgram_server_service = service;
+ dgram_server_name = service_name;
+ dgram_server_argv = argv + optind;
+
+ /*
+ * Run pre-jail initialization.
+ */
+ if (chdir(var_queue_dir) < 0)
+ msg_fatal("chdir(\"%s\"): %m", var_queue_dir);
+ if (pre_init)
+ pre_init(dgram_server_name, dgram_server_argv);
+
+ /*
+ * Optionally, restrict the damage that this process can do.
+ */
+ resolve_local_init();
+ tzset();
+ chroot_uid(root_dir, user_name);
+
+ /*
+ * Run post-jail initialization.
+ */
+ if (post_init)
+ post_init(dgram_server_name, dgram_server_argv);
+
+ /*
+ * Running as a semi-resident server. Service requests. Terminate when we
+ * have serviced a sufficient number of requests, when no-one has been
+ * talking to us for a configurable amount of time, or when the master
+ * process terminated abnormally.
+ */
+ if (var_idle_limit > 0)
+ event_request_timer(dgram_server_timeout, (void *) 0, var_idle_limit);
+ for (fd = MASTER_LISTEN_FD; fd < MASTER_LISTEN_FD + socket_count; fd++) {
+ event_enable_read(fd, dgram_server_accept, CAST_INT_TO_VOID_PTR(fd));
+ close_on_exec(fd, CLOSE_ON_EXEC);
+ }
+ event_enable_read(MASTER_STATUS_FD, dgram_server_abort, (void *) 0);
+ close_on_exec(MASTER_STATUS_FD, CLOSE_ON_EXEC);
+ close_on_exec(MASTER_FLOW_READ, CLOSE_ON_EXEC);
+ close_on_exec(MASTER_FLOW_WRITE, CLOSE_ON_EXEC);
+ watchdog = watchdog_create(dgram_server_watchdog,
+ (WATCHDOG_FN) 0, (void *) 0);
+
+ /*
+ * The event loop, at last.
+ */
+ while (var_use_limit == 0 || use_count < var_use_limit) {
+ if (dgram_server_lock != 0) {
+ watchdog_stop(watchdog);
+ if (myflock(vstream_fileno(dgram_server_lock), INTERNAL_LOCK,
+ MYFLOCK_OP_EXCLUSIVE) < 0)
+ msg_fatal("select lock: %m");
+ }
+ watchdog_start(watchdog);
+ delay = loop ? loop(dgram_server_name, dgram_server_argv) : -1;
+ event_loop(delay);
+ }
+ dgram_server_exit();
+}
#include <sys/time.h> /* select() */
#include <unistd.h>
#include <signal.h>
-#include <syslog.h>
#include <stdlib.h>
#include <limits.h>
#include <string.h>
/* Utility library. */
#include <msg.h>
-#include <msg_syslog.h>
#include <msg_vstream.h>
#include <chroot_uid.h>
#include <listen.h>
#include <mail_flow.h>
#include <mail_version.h>
#include <bounce.h>
+#include <maillog_client.h>
/* Process manager. */
const char *err;
char *generation;
int msg_vstream_needed = 0;
- int redo_syslog_init = 0;
const char *dsn_filter_title;
const char **dsn_filter_maps;
int retire_me_from_flags = 0;
* Initialize logging and exit handler. Do the syslog first, so that its
* initialization completes before we enter the optional chroot jail.
*/
- msg_syslog_init(mail_task(var_procname), LOG_PID, LOG_FACILITY);
+ maillog_client_init(mail_task(var_procname), MAILLOG_CLIENT_FLAG_NONE);
if (msg_verbose)
msg_info("daemon started");
if ((err = split_nameval(oname_val, &oname, &oval)) != 0)
msg_fatal("invalid \"-o %s\" option value: %s", optarg, err);
mail_conf_update(oname, oval);
- if (strcmp(oname, VAR_SYSLOG_NAME) == 0)
- redo_syslog_init = 1;
myfree(oname_val);
break;
case 'r':
set_mail_conf_str(VAR_SERVNAME, service_name);
/*
- * Initialize generic parameters.
+ * Initialize generic parameters and re-initialize logging in case of a
+ * non-default program name or logging destination.
*/
mail_params_init();
- if (redo_syslog_init)
- msg_syslog_init(mail_task(var_procname), LOG_PID, LOG_FACILITY);
+ maillog_client_init(mail_task(var_procname), MAILLOG_CLIENT_FLAG_NONE);
/*
* Register higher-level dictionaries and initialize the support for
#define TRIGGER_BUF_SIZE 1024
+ /*
+ * dgram_server.c
+ */
+typedef void (*DGRAM_SERVER_FN) (char *, ssize_t, char *, char **);
+extern NORETURN dgram_server_main(int, char **, DGRAM_SERVER_FN,...);
+
+#define DGRAM_BUF_SIZE 4096
+
/* LICENSE
/* .ad
/* .fi
/* Terminate the master process after \fIexit_time\fR seconds. Child
/* processes terminate at their convenience.
/* .IP \fB-i\fR
-/* Enable \fBinit\fR mode: do not attempt to become a session
-/* or process group leader; and to force termination, set an
-/* explicit signal handler instead of relying on the default
-/* signal action. This mode is allowed only if the process ID
-/* equals 1.
+/* Enable \fBinit\fR mode: do not become a session or process
+/* group leader; similar to \fB-s\fR, do not redirect stdout
+/* to /dev/null, so that "maillog_file = /dev/stdout" works.
+/* This mode is allowed only if the process ID equals 1.
+/* .IP \fB-s\fR
+/* Do not redirect stdout to /dev/null, so that "maillog_file
+/* = /dev/stdout" works.
/* .IP \fB-t\fR
/* Test mode. Return a zero exit status when the \fBmaster.pid\fR lock
/* file does not exist or when that file is not locked. This is evidence
#include <sys_defs.h>
#include <sys/stat.h>
-#include <syslog.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
#include <events.h>
#include <msg.h>
-#include <msg_syslog.h>
#include <vstring.h>
#include <mymalloc.h>
#include <iostuff.h>
#include <open_lock.h>
#include <inet_proto.h>
#include <mail_parm_split.h>
+#include <maillog_client.h>
/* Application-specific. */
VSTRING *data_lock_path;
off_t inherited_limit;
int debug_me = 0;
+ int keep_stdout = 0;
int ch;
int fd;
int n;
/*
* Initialize logging and exit handler.
*/
- msg_syslog_init(mail_task(var_procname), LOG_PID, LOG_FACILITY);
+ maillog_client_init(mail_task(var_procname),
+ MAILLOG_CLIENT_FLAG_LOGWRITER_FALLBACK);
/*
* Check the Postfix library version as soon as we enable logging.
/*
* Process JCL.
*/
- while ((ch = GETOPT(argc, argv, "c:Dde:itvw")) > 0) {
+ while ((ch = GETOPT(argc, argv, "c:Dde:istvw")) > 0) {
switch (ch) {
case 'c':
if (setenv(CONF_ENV_PATH, optarg, 1) < 0)
if (getpid() != 1)
msg_fatal("-i is allowed only for PID 1 process");
init_mode = 1;
+ keep_stdout = 1;
break;
case 'D':
- debug_me = 1;
+ debug_me = 1;
+ break;
+ case 's':
+ keep_stdout = 1;
break;
case 't':
test_lock = 1;
*/
if (master_detach)
for (fd = 0; fd < 3; fd++) {
+ if (fd == STDOUT_FILENO && keep_stdout)
+ continue;
(void) close(fd);
if (open("/dev/null", O_RDWR, 0) != fd)
msg_fatal("open /dev/null: %m");
master_config();
master_sigsetup();
master_flow_init();
+ maillog_client_init(mail_task(var_procname),
+ MAILLOG_CLIENT_FLAG_LOGWRITER_FALLBACK);
msg_info("daemon started -- version %s, configuration %s",
var_mail_version, var_config_dir);
master_gotsighup = 0; /* this first */
master_vars_init(); /* then this */
master_refresh(); /* then this */
+ maillog_client_init(mail_task(var_procname),
+ MAILLOG_CLIENT_FLAG_LOGWRITER_FALLBACK);
}
if (master_gotsigchld) {
if (msg_verbose)
#define MASTER_LIMIT_OK(limit, count) ((limit) == 0 || ((count) < (limit)))
/*
- * Service types.
+ * Service types, stream sockets unless indicated otherwise.
*/
#define MASTER_SERV_TYPE_UNIX 1 /* AF_UNIX domain socket */
#define MASTER_SERV_TYPE_INET 2 /* AF_INET domain socket */
#define MASTER_SERV_TYPE_FIFO 3 /* fifo (named pipe) */
#define MASTER_SERV_TYPE_PASS 4 /* AF_UNIX domain socket */
+#define MASTER_SERV_TYPE_UXDG 5 /* AF_UNIX domain datagram socket */
/*
* Default process management policy values. This is only the bare minimum.
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
+/*
+/* Wietse Venema
+/* Google, Inc.
+/* 111 8th Avenue
+/* New York, NY 10011, USA
/*--*/
/* System libraries. */
serv->type = MASTER_SERV_TYPE_UNIX;
serv->listen_fd_count = 1;
serv->flags |= MASTER_FLAG_LOCAL_ONLY;
+ } else if (STR_SAME(transport, MASTER_XPORT_NAME_UXDG)) {
+ serv->type = MASTER_SERV_TYPE_UXDG;
+ serv->listen_fd_count = 1;
+ serv->flags |= MASTER_FLAG_LOCAL_ONLY;
} else if (STR_SAME(transport, MASTER_XPORT_NAME_FIFO)) {
serv->type = MASTER_SERV_TYPE_FIFO;
serv->listen_fd_count = 1;
} else if (serv->type == MASTER_SERV_TYPE_UNIX) {
serv->name = mail_pathname(private ? MAIL_CLASS_PRIVATE :
MAIL_CLASS_PUBLIC, name);
+ } else if (serv->type == MASTER_SERV_TYPE_UXDG) {
+ serv->name = mail_pathname(private ? MAIL_CLASS_PRIVATE :
+ MAIL_CLASS_PUBLIC, name);
} else if (serv->type == MASTER_SERV_TYPE_FIFO) {
serv->name = mail_pathname(private ? MAIL_CLASS_PRIVATE :
MAIL_CLASS_PUBLIC, name);
#ifdef MASTER_SERV_TYPE_PASS
serv->type == MASTER_SERV_TYPE_PASS ? MASTER_XPORT_NAME_PASS :
#endif
+ serv->type == MASTER_SERV_TYPE_UXDG ? MASTER_XPORT_NAME_UXDG :
"unknown transport type");
msg_info("listen_fd_count: %d", serv->listen_fd_count);
msg_info("wakeup: %d", serv->wakeup_time);
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
+/*
+/* Wietse Venema
+/* Google, Inc.
+/* 111 8th Avenue
+/* New York, NY 10011, USA
/*--*/
/* System library. */
set_ugid(getuid(), getgid());
break;
+ /*
+ * UNIX-domain datagram listener endpoints always come as singlets.
+ */
+ case MASTER_SERV_TYPE_UXDG:
+ set_eugid(var_owner_uid, var_owner_gid);
+ serv->listen_fd[0] =
+ unix_dgram_listen(serv->name, NON_BLOCKING);
+ close_on_exec(serv->listen_fd[0], CLOSE_ON_EXEC);
+ set_ugid(getuid(), getgid());
+ break;
+
/*
* FIFO listener endpoints always come as singlets.
*/
#define MASTER_XPORT_NAME_FIFO "fifo" /* local IPC */
#define MASTER_XPORT_NAME_INET "inet" /* non-local IPC */
#define MASTER_XPORT_NAME_PASS "pass" /* local IPC */
+#define MASTER_XPORT_NAME_UXDG "unix-dgram" /* local IPC */
/*
* Format of a status message sent by a child process to the process
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
+/*
+/* Wietse Venema
+/* Google, Inc.
+/* 111 8th Avenue
+/* New York, NY 10011, USA
/*--*/
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
+/*
+/* Wietse Venema
+/* Google, Inc.
+/* 111 8th Avenue
+/* New York, NY 10011, USA
/*--*/
/* System library. */
#include <sys_defs.h>
#include <unistd.h>
#include <string.h>
+#include <errno.h>
/* Utility library. */
case MASTER_SERV_TYPE_UNIX:
status = LOCAL_TRIGGER(serv->name, &wakeup, sizeof(wakeup), BRIEFLY);
break;
+ case MASTER_SERV_TYPE_UXDG:
+ status = -1;
+ errno = EOPNOTSUPP;
+ break;
#ifdef MASTER_SERV_TYPE_PASS
case MASTER_SERV_TYPE_PASS:
status = pass_trigger(serv->name, &wakeup, sizeof(wakeup), BRIEFLY);
#include <sys/time.h> /* select() */
#include <unistd.h>
#include <signal.h>
-#include <syslog.h>
#include <stdlib.h>
#include <limits.h>
#include <string.h>
/* Utility library. */
#include <msg.h>
-#include <msg_syslog.h>
#include <msg_vstream.h>
#include <chroot_uid.h>
#include <listen.h>
#include <mail_flow.h>
#include <mail_version.h>
#include <bounce.h>
+#include <maillog_client.h>
/* Process manager. */
const char *err;
char *generation;
int msg_vstream_needed = 0;
- int redo_syslog_init = 0;
const char *dsn_filter_title;
const char **dsn_filter_maps;
* Initialize logging and exit handler. Do the syslog first, so that its
* initialization completes before we enter the optional chroot jail.
*/
- msg_syslog_init(mail_task(var_procname), LOG_PID, LOG_FACILITY);
+ maillog_client_init(mail_task(var_procname), MAILLOG_CLIENT_FLAG_NONE);
if (msg_verbose)
msg_info("daemon started");
if ((err = split_nameval(oname_val, &oname, &oval)) != 0)
msg_fatal("invalid \"-o %s\" option value: %s", optarg, err);
mail_conf_update(oname, oval);
- if (strcmp(oname, VAR_SYSLOG_NAME) == 0)
- redo_syslog_init = 1;
myfree(oname_val);
break;
case 's':
set_mail_conf_str(VAR_SERVNAME, service_name);
/*
- * Initialize generic parameters.
+ * Initialize generic parameters and re-initialize logging in case of a
+ * non-default program name or logging destination.
*/
mail_params_init();
- if (redo_syslog_init)
- msg_syslog_init(mail_task(var_procname), LOG_PID, LOG_FACILITY);
+ maillog_client_init(mail_task(var_procname), MAILLOG_CLIENT_FLAG_NONE);
/*
* Register higher-level dictionaries and initialize the support for
#include <sys/socket.h>
#include <unistd.h>
#include <signal.h>
-#include <syslog.h>
#include <stdlib.h>
#include <limits.h>
#include <string.h>
/* Utility library. */
#include <msg.h>
-#include <msg_syslog.h>
#include <msg_vstream.h>
#include <chroot_uid.h>
#include <vstring.h>
#include <mail_flow.h>
#include <mail_version.h>
#include <bounce.h>
+#include <maillog_client.h>
/* Process manager. */
const char *err;
char *generation;
int msg_vstream_needed = 0;
- int redo_syslog_init = 0;
const char *dsn_filter_title;
const char **dsn_filter_maps;
int retire_me_from_flags = 0;
* Initialize logging and exit handler. Do the syslog first, so that its
* initialization completes before we enter the optional chroot jail.
*/
- msg_syslog_init(mail_task(var_procname), LOG_PID, LOG_FACILITY);
+ maillog_client_init(mail_task(var_procname), MAILLOG_CLIENT_FLAG_NONE);
if (msg_verbose)
msg_info("daemon started");
if ((err = split_nameval(oname_val, &oname, &oval)) != 0)
msg_fatal("invalid \"-o %s\" option value: %s", optarg, err);
mail_conf_update(oname, oval);
- if (strcmp(oname, VAR_SYSLOG_NAME) == 0)
- redo_syslog_init = 1;
myfree(oname_val);
break;
case 'r':
* Initialize generic parameters.
*/
mail_params_init();
- if (redo_syslog_init)
- msg_syslog_init(mail_task(var_procname), LOG_PID, LOG_FACILITY);
+ maillog_client_init(mail_task(var_procname), MAILLOG_CLIENT_FLAG_NONE);
/*
* Register higher-level dictionaries and initialize the support for
#include <sys/socket.h>
#include <unistd.h>
#include <signal.h>
-#include <syslog.h>
#include <stdlib.h>
#include <limits.h>
#include <string.h>
/* Utility library. */
#include <msg.h>
-#include <msg_syslog.h>
#include <msg_vstream.h>
#include <chroot_uid.h>
#include <vstring.h>
#include <mail_flow.h>
#include <mail_version.h>
#include <bounce.h>
+#include <maillog_client.h>
/* Process manager. */
const char *err;
char *generation;
int msg_vstream_needed = 0;
- int redo_syslog_init = 0;
const char *dsn_filter_title;
const char **dsn_filter_maps;
* Initialize logging and exit handler. Do the syslog first, so that its
* initialization completes before we enter the optional chroot jail.
*/
- msg_syslog_init(mail_task(var_procname), LOG_PID, LOG_FACILITY);
+ maillog_client_init(mail_task(var_procname), MAILLOG_CLIENT_FLAG_NONE);
if (msg_verbose)
msg_info("daemon started");
if ((err = split_nameval(oname_val, &oname, &oval)) != 0)
msg_fatal("invalid \"-o %s\" option value: %s", optarg, err);
mail_conf_update(oname, oval);
- if (strcmp(oname, VAR_SYSLOG_NAME) == 0)
- redo_syslog_init = 1;
myfree(oname_val);
break;
case 's':
set_mail_conf_str(VAR_SERVNAME, service_name);
/*
- * Initialize generic parameters.
+ * Initialize generic parameters and re-initialize logging in case of a
+ * non-default program name or logging destination.
*/
mail_params_init();
- if (redo_syslog_init)
- msg_syslog_init(mail_task(var_procname), LOG_PID, LOG_FACILITY);
+ maillog_client_init(mail_task(var_procname), MAILLOG_CLIENT_FLAG_NONE);
/*
* Register higher-level dictionaries and initialize the support for
postalias.o: ../../include/mail_parm_split.h
postalias.o: ../../include/mail_task.h
postalias.o: ../../include/mail_version.h
+postalias.o: ../../include/maillog_client.h
postalias.o: ../../include/mkmap.h
postalias.o: ../../include/msg.h
-postalias.o: ../../include/msg_syslog.h
postalias.o: ../../include/msg_vstream.h
postalias.o: ../../include/myflock.h
postalias.o: ../../include/mymalloc.h
/* found to the standard output stream. The exit status is zero
/* when the requested information was found.
/*
-/* Note: this performs a single query with the key as specified,
-/* and does not make iterative queries with substrings of the
+/* Note: this performs a single query with the key as specified,
+/* and does not make iterative queries with substrings of the
/* key as described in the aliases(5) manual page.
/*
/* If a key value of \fB-\fR is specified, the program reads key
#include <vstring.h>
#include <vstream.h>
#include <msg_vstream.h>
-#include <msg_syslog.h>
#include <readlline.h>
#include <stringops.h>
#include <split_at.h>
#include <mail_task.h>
#include <dict_proxy.h>
#include <mail_parm_split.h>
+#include <maillog_client.h>
/* Application-specific. */
dicts[n] = 0;
/*
- * Perform all queries. Open maps on the fly, to avoid opening unnecessary
- * maps.
+ * Perform all queries. Open maps on the fly, to avoid opening
+ * unnecessary maps.
*/
while (vstring_get_nonl(keybuf, in) != VSTREAM_EOF) {
for (n = 0; n < map_count; n++) {
msg_verbose = 1;
/*
- * Initialize. Set up logging, read the global configuration file and
- * extract configuration information.
+ * Initialize. Set up logging. Read the global configuration file after
+ * parsing command-line arguments.
*/
if ((slash = strrchr(argv[0], '/')) != 0 && slash[1])
argv[0] = slash + 1;
msg_vstream_init(argv[0], VSTREAM_ERR);
- msg_syslog_init(mail_task(argv[0]), LOG_PID, LOG_FACILITY);
+ maillog_client_init(mail_task(argv[0]), MAILLOG_CLIENT_FLAG_NONE);
/*
* Check the Postfix library version as soon as we enable logging.
update_env(import_env->argv);
argv_free(import_env);
/* Re-evaluate mail_task() after reading main.cf. */
- msg_syslog_init(mail_task(argv[0]), LOG_PID, LOG_FACILITY);
+ maillog_client_init(mail_task(argv[0]), MAILLOG_CLIENT_FLAG_NONE);
mail_dict_init();
/*
MASTER_XPORT_NAME_FIFO,
MASTER_XPORT_NAME_INET,
MASTER_XPORT_NAME_PASS,
+ MASTER_XPORT_NAME_UXDG,
0,
};
postdrop.o: ../../include/mail_stream.h
postdrop.o: ../../include/mail_task.h
postdrop.o: ../../include/mail_version.h
+postdrop.o: ../../include/maillog_client.h
postdrop.o: ../../include/msg.h
-postdrop.o: ../../include/msg_syslog.h
postdrop.o: ../../include/msg_vstream.h
postdrop.o: ../../include/mymalloc.h
postdrop.o: ../../include/nvtable.h
/* \fBpostconf\fR(5) for more details including examples.
/* .IP "\fBalternate_config_directories (empty)\fR"
/* A list of non-default Postfix configuration directories that may
-/* be specified with "-c config_directory" on the command line, or
-/* via the MAIL_CONFIG environment parameter.
+/* be specified with "-c config_directory" on the command line (in the
+/* case of \fBsendmail\fR(1), with the "-C" option), or via the MAIL_CONFIG
+/* environment parameter.
/* .IP "\fBconfig_directory (see 'postconf -d' output)\fR"
/* The default location of the Postfix main.cf and master.cf
/* configuration files.
/* .IP "\fBimport_environment (see 'postconf -d' output)\fR"
-/* The list of environment parameters that a Postfix process will
-/* import from a non-Postfix parent process.
+/* The list of environment parameters that a privileged Postfix
+/* process will import from a non-Postfix parent process, or name=value
+/* environment overrides.
/* .IP "\fBqueue_directory (see 'postconf -d' output)\fR"
/* The location of the Postfix top-level queue directory.
/* .IP "\fBsyslog_facility (mail)\fR"
#include <string.h>
#include <stdlib.h>
#include <signal.h>
-#include <syslog.h>
#include <errno.h>
#include <warn_stat.h>
#include <vstream.h>
#include <vstring.h>
#include <msg_vstream.h>
-#include <msg_syslog.h>
#include <argv.h>
#include <iostuff.h>
#include <stringops.h>
#include <user_acl.h>
#include <rec_attr_map.h>
#include <mail_parm_split.h>
+#include <maillog_client.h>
/* Application-specific. */
/*
* This is the fatal error handler. Don't try to do anything fancy.
*
- * msg_vstream does not allocate memory, but msg_syslog may indirectly in
- * syslog(), so it should not be called from a user-triggered signal
- * handler.
+ * To avoid privilege escalation in a set-gid program, Postfix logging
+ * functions must not be called from a user-triggered signal handler,
+ * because Postfix logging functions may allocate memory on the fly (as
+ * does the syslog() library function), and the memory allocator is not
+ * reentrant.
*
* Assume atomic signal() updates, even when emulated with sigaction(). We
* use the in-kernel SIGINT handler address as an atomic variable to
*/
argv[0] = "postdrop";
msg_vstream_init(argv[0], VSTREAM_ERR);
- msg_syslog_init(mail_task("postdrop"), LOG_PID, LOG_FACILITY);
+ maillog_client_init(mail_task("postdrop"), MAILLOG_CLIENT_FLAG_NONE);
set_mail_conf_str(VAR_PROCNAME, var_procname = mystrdup(argv[0]));
/*
/*
* Read the global configuration file and extract configuration
- * information. Some claim that the user should supply the working
- * directory instead. That might be OK, given that this command needs
- * write permission in a subdirectory called "maildrop". However we still
- * need to reliably detect incomplete input, and so we must perform
- * record-level I/O. With that, we should also take the opportunity to
- * perform some sanity checks on the input.
+ * information.
*/
mail_conf_read();
/* Re-evaluate mail_task() after reading main.cf. */
- msg_syslog_init(mail_task("postdrop"), LOG_PID, LOG_FACILITY);
+ maillog_client_init(mail_task("postdrop"), MAILLOG_CLIENT_FLAG_NONE);
get_mail_conf_str_table(str_table);
/*
postfix.o: ../../include/mail_params.h
postfix.o: ../../include/mail_parm_split.h
postfix.o: ../../include/mail_version.h
+postfix.o: ../../include/maillog_client.h
postfix.o: ../../include/msg.h
-postfix.o: ../../include/msg_syslog.h
postfix.o: ../../include/msg_vstream.h
postfix.o: ../../include/safe.h
postfix.o: ../../include/stringops.h
/* This is set when the -v command-line option is present.
/* .IP \fBMAIL_DEBUG\fR
/* This is set when the -D command-line option is present.
+/* .PP
+/* When the internal logging service is enabled (by setting a
+/* non-empty maillog_file parameter value) the postfix(1)
+/* command exports settings that are used by child processes
+/* before they have processed main.cf or command-line settings.
+/* .IP \fBPOSTLOG_SERVICE
+/* The name of the public postlog service endpoint.
+/* .IP \fBPOSTLOG_HOSTNAME
+/* The hostname to prepend to internal logging.
/* CONFIGURATION PARAMETERS
/* .ad
/* .fi
/* .IP "\fBmulti_instance_enable (no)\fR"
/* Allow this Postfix instance to be started, stopped, etc., by a
/* multi-instance manager.
+/* .PP
+/* Available in Postfix version 3.4 and later:
+/* .IP "\fBmaillog_file (empty)\fR"
+/* The name of an optional logfile that is written by the Postfix
+/* \fBpostlogd\fR(8) service.
+/* .IP "\fBpostlog_service_name (postlog)\fR"
+/* The name of the \fBpostlogd\fR(8) service entry in master.cf.
/* FILES
/* .ad
/* .fi
/* oqmgr(8), old Postfix queue manager
/* pickup(8), Postfix local mail pickup
/* pipe(8), deliver mail to non-Postfix command
+/* postlogd(8), Postfix internal logging service
/* postscreen(8), Postfix zombie blocker
/* proxymap(8), Postfix lookup table proxy server
/* qmgr(8), Postfix queue manager
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
-#include <syslog.h>
#ifdef USE_PATHS_H
#include <paths.h>
#endif
#include <msg.h>
#include <msg_vstream.h>
-#include <msg_syslog.h>
#include <stringops.h>
#include <clean_env.h>
#include <argv.h>
#include <mail_params.h>
#include <mail_version.h>
#include <mail_parm_split.h>
+#include <maillog_client.h>
/* Additional installation parameters. */
argv[0] = slash + 1;
if (isatty(STDERR_FILENO))
msg_vstream_init(argv[0], VSTREAM_ERR);
- msg_syslog_init(argv[0], LOG_PID, LOG_FACILITY);
+ maillog_client_init(argv[0], MAILLOG_CLIENT_FLAG_LOGWRITER_FALLBACK);
/*
* Check the Postfix library version as soon as we enable logging.
mail_conf_read();
get_mail_conf_str_table(str_table);
+ /*
+ * Environment import filter, to enforce consistent behavior whether this
+ * command is started by hand, or at system boot time. This is necessary
+ * because some shell scripts use environment settings to override
+ * main.cf settings.
+ */
+ import_env = mail_parm_split(VAR_IMPORT_ENVIRON, var_import_environ);
+ clean_env(import_env->argv);
+ argv_free(import_env);
+
+ /*
+ * This is after calling clean_env(), to ensure that POSTLOG_XXX exports
+ * will work, even if import_environment would remove them.
+ */
+ maillog_client_init(argv[0], MAILLOG_CLIENT_FLAG_LOGWRITER_FALLBACK);
+
/*
* Alert the sysadmin that the backwards-compatible settings are still in
* effect.
VAR_COMPAT_LEVEL "=%d\" and \"postfix reload\"",
CUR_COMPAT_LEVEL);
}
-
- /*
- * Environment import filter, to enforce consistent behavior whether this
- * command is started by hand, or at system boot time. This is necessary
- * because some shell scripts use environment settings to override
- * main.cf settings.
- */
- import_env = mail_parm_split(VAR_IMPORT_ENVIRON, var_import_environ);
- clean_env(import_env->argv);
- argv_free(import_env);
-
check_setenv("PATH", ROOT_PATH); /* sys_defs.h */
check_setenv(CONF_ENV_PATH, var_config_dir);/* mail_conf.h */
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
-#include <syslog.h>
#include <string.h>
#include <stdlib.h>
msg_verbose = 1;
/*
- * Initialize. Set up logging, read the global configuration file and
- * extract configuration information.
+ * Initialize. Set up logging. Read the global configuration file after
+ * parsing command-line arguments.
*/
if ((slash = strrchr(argv[0], '/')) != 0 && slash[1])
argv[0] = slash + 1;
postlog.o: ../../include/mail_parm_split.h
postlog.o: ../../include/mail_task.h
postlog.o: ../../include/mail_version.h
+postlog.o: ../../include/maillog_client.h
postlog.o: ../../include/msg.h
postlog.o: ../../include/msg_output.h
-postlog.o: ../../include/msg_syslog.h
postlog.o: ../../include/msg_vstream.h
postlog.o: ../../include/sys_defs.h
postlog.o: ../../include/vbuf.h
/* line, \fBpostlog\fR(1) reads from standard input and logs each input
/* line as one record.
/*
-/* Logging is sent to \fBsyslogd\fR(8); when the standard error stream
-/* is connected to a terminal, logging is sent there as well.
+/* By default, logging is sent to \fBsyslogd\fR(8); when the
+/* standard error stream is connected to a terminal, logging
+/* is sent there as well.
/*
/* The following options are implemented:
/* .IP "\fB-c \fIconfig_dir\fR"
/* Read the \fBmain.cf\fR configuration file in the named directory
/* instead of the default configuration directory.
-/* .IP \fB-i\fR
-/* Include the process ID in the logging tag.
+/* .IP "\fB-i\fR (obsolete)"
+/* Include the process ID in the logging tag. This flag is ignored as
+/* of Postfix 3.4, where the PID is always included.
/* .IP "\fB-p \fIpriority\fR (default: \fBinfo\fR)"
/* Specifies the logging severity: \fBinfo\fR, \fBwarn\fR,
/* \fBerror\fR, \fBfatal\fR, or \fBpanic\fR. With Postfix 3.1
/* .IP "\fBsyslog_name (see 'postconf -d' output)\fR"
/* A prefix that is prepended to the process name in syslog
/* records, so that, for example, "smtpd" becomes "prefix/smtpd".
+/* .PP
+/* Available in Postfix 3.4 and later:
+/* .IP "\fBmaillog_file (empty)\fR"
+/* The name of an optional logfile that is written by the Postfix
+/* \fBpostlogd\fR(8) service.
+/* .IP "\fBpostlog_service_name (postlog)\fR"
+/* The name of the \fBpostlogd\fR(8) service entry in master.cf.
/* SEE ALSO
/* postconf(5), configuration parameters
/* syslogd(8), syslog daemon
+/* postlogd(8), internal logging service
/* LICENSE
/* .ad
/* .fi
#include <sys_defs.h>
#include <sys/stat.h>
#include <string.h>
-#include <syslog.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <vstring_vstream.h>
#include <msg_output.h>
#include <msg_vstream.h>
-#include <msg_syslog.h>
#include <warn_stat.h>
#include <clean_env.h>
#include <mail_conf.h>
#include <mail_task.h>
#include <mail_parm_split.h>
+#include <maillog_client.h>
/* Application-specific. */
if (*argv)
vstring_strcat(buf, " ");
}
- msg_text(level, vstring_str(buf));
+ msg_printf(level, "%s", vstring_str(buf));
vstring_free(buf);
}
VSTRING *buf = vstring_alloc(100);
while (vstring_get_nonl(buf, fp) != VSTREAM_EOF)
- msg_text(level, vstring_str(buf));
+ msg_printf(level, "%s", vstring_str(buf));
vstring_free(buf);
}
int fd;
int ch;
const char *tag;
- int log_flags = 0;
int level = MSG_INFO;
ARGV *import_env;
tag = mail_task(argv[0]);
if (isatty(STDERR_FILENO))
msg_vstream_init(tag, VSTREAM_ERR);
- msg_syslog_init(tag, LOG_PID, LOG_FACILITY);
+ maillog_client_init(tag, MAILLOG_CLIENT_FLAG_LOGWRITER_FALLBACK);
/*
* Check the Postfix library version as soon as we enable logging.
msg_fatal("out of memory");
break;
case 'i':
- log_flags |= LOG_PID;
break;
case 'p':
level = level_map(optarg);
*/
if (isatty(STDERR_FILENO))
msg_vstream_init(tag, VSTREAM_ERR);
- msg_syslog_init(tag, LOG_PID, LOG_FACILITY);
+ maillog_client_init(tag, MAILLOG_CLIENT_FLAG_LOGWRITER_FALLBACK);
/*
* Log the command line or log lines from standard input.
--- /dev/null
+SHELL = /bin/sh
+SRCS = postlogd.c
+OBJS = postlogd.o
+HDRS =
+TESTSRC =
+DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
+CFLAGS = $(DEBUG) $(OPT) $(DEFS)
+TESTPROG=
+PROG = postlogd
+INC_DIR = ../../include
+LIBS = ../../lib/lib$(LIB_PREFIX)dns$(LIB_SUFFIX) \
+ ../../lib/lib$(LIB_PREFIX)master$(LIB_SUFFIX) \
+ ../../lib/lib$(LIB_PREFIX)global$(LIB_SUFFIX) \
+ ../../lib/lib$(LIB_PREFIX)util$(LIB_SUFFIX)
+
+.c.o:; $(CC) $(CFLAGS) -c $*.c
+
+$(PROG): $(OBJS) $(LIBS)
+ $(CC) $(CFLAGS) $(SHLIB_RPATH) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
+
+$(OBJS): ../../conf/makedefs.out
+
+Makefile: Makefile.in
+ cat ../../conf/makedefs.out $? >$@
+
+test: $(TESTPROG)
+
+tests: test
+
+root_tests:
+
+update: ../../libexec/$(PROG)
+
+../../libexec/$(PROG): $(PROG)
+ cp $(PROG) ../../libexec
+
+printfck: $(OBJS) $(PROG)
+ rm -rf printfck
+ mkdir printfck
+ sed '1,/^# do not edit/!d' Makefile >printfck/Makefile
+ set -e; for i in *.c; do printfck -f .printfck $$i >printfck/$$i; done
+ cd printfck; make "INC_DIR=../../../include" `cd ..; ls *.o`
+
+lint:
+ lint $(DEFS) $(SRCS) $(LINTFIX)
+
+clean:
+ rm -f *.o *core $(PROG) $(TESTPROG) junk
+ rm -rf printfck
+
+tidy: clean
+
+depend: $(MAKES)
+ (sed '1,/^# do not edit/!d' Makefile.in; \
+ set -e; for i in [a-z][a-z0-9]*.c; do \
+ $(CC) -E $(DEFS) $(INCL) $$i | grep -v '[<>]' | sed -n -e '/^# *1 *"\([^"]*\)".*/{' \
+ -e 's//'`echo $$i|sed 's/c$$/o/'`': \1/' \
+ -e 's/o: \.\//o: /' -e p -e '}' ; \
+ done | LANG=C sort -u) | grep -v '[.][o][:][ ][/]' >$$$$ && mv $$$$ Makefile.in
+ @$(EXPORT) make -f Makefile.in Makefile 1>&2
+
+# do not edit below this line - it is generated by 'make depend'
+postlogd.o: ../../include/check_arg.h
+postlogd.o: ../../include/logwriter.h
+postlogd.o: ../../include/mail_conf.h
+postlogd.o: ../../include/mail_params.h
+postlogd.o: ../../include/mail_server.h
+postlogd.o: ../../include/mail_version.h
+postlogd.o: ../../include/msg.h
+postlogd.o: ../../include/msg_logger.h
+postlogd.o: ../../include/sys_defs.h
+postlogd.o: ../../include/vbuf.h
+postlogd.o: ../../include/vstream.h
+postlogd.o: postlogd.c
--- /dev/null
+/*++
+/* NAME
+/* postlogd 8
+/* SUMMARY
+/* Postfix internal log server
+/* SYNOPSIS
+/* \fBpostlogd\fR [generic Postfix daemon options]
+/* DESCRIPTION
+/* This program logs events on behalf of Postfix programs
+/* when the maillog configuration parameter specifies a non-empty
+/* value.
+/* BUGS
+/* Non-daemon Postfix programs don't know that they should log
+/* to the internal logging service before they have processed
+/* command-line options and main.cf parameters. These programs
+/* still log earlier events to the syslog service.
+/*
+/* If Postfix is down, the non-daemon programs \fBpostfix\fR(1),
+/* \fBpostsuper\fR(1), \fBpostmulti\fR(1), and \fBpostlog\fR(1),
+/* will log directly to \fB$maillog_file\fR. These programs
+/* expect to run with root privileges, for example during
+/* Postfix start-up, reload, or shutdown.
+/*
+/* Other non-daemon Postfix programs will never write directly to
+/* \fB$maillog_file\fR (also, logging to stdout would interfere
+/* with the operation of some of these programs). These programs
+/* can log to \fBpostlogd\fR(8) if they are run by the super-user,
+/* or if their executable file has set-gid permission. Do not
+/* set this permision on programs other than \fBpostdrop\fR(1)
+/* and \fBpostqueue\fR(1).
+/* CONFIGURATION PARAMETERS
+/* .ad
+/* .fi
+/* Changes to \fBmain.cf\fR are picked up automatically, as
+/* \fBpostlogd\fR(8) processes run for only a limited amount
+/* of time. Use the command "\fBpostfix reload\fR" to speed
+/* up a change.
+/*
+/* The text below provides only a parameter summary. See
+/* \fBpostconf\fR(5) for more details including examples.
+/* .IP "\fBconfig_directory (see 'postconf -d' output)\fR"
+/* The default location of the Postfix main.cf and master.cf
+/* configuration files.
+/* .IP "\fBmaillog_file (empty)\fR"
+/* The name of an optional logfile that is written by the Postfix
+/* \fBpostlogd\fR(8) service.
+/* .IP "\fBprocess_id (read-only)\fR"
+/* The process ID of a Postfix command or daemon process.
+/* .IP "\fBprocess_name (read-only)\fR"
+/* The process name of a Postfix command or daemon process.
+/* .IP "\fBsyslog_name (see 'postconf -d' output)\fR"
+/* A prefix that is prepended to the process name in syslog
+/* records, so that, for example, "smtpd" becomes "prefix/smtpd".
+/* .IP "\fBservice_name (read-only)\fR"
+/* The master.cf service name of a Postfix daemon process.
+/* .IP "\fBpostlogd_watchdog_timeout (10s)\fR"
+/* How much time a \fBpostlogd\fR(8) process may take to process a request
+/* before it is terminated by a built-in watchdog timer.
+/* SEE ALSO
+/* postconf(5), configuration parameters
+/* syslogd(5), system logging
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* HISTORY
+/* .ad
+/* .fi
+/* This service was introduced with Postfix version 3.4.
+/* AUTHOR(S)
+/* Wietse Venema
+/* Google, Inc.
+/* 111 8th Avenue
+/* New York, NY 10011, USA
+/*--*/
+
+ /*
+ * System library.
+ */
+#include <sys_defs.h>
+
+ /*
+ * Utility library.
+ */
+#include <logwriter.h>
+#include <msg.h>
+#include <msg_logger.h>
+#include <stringops.h>
+#include <vstream.h>
+
+ /*
+ * Global library.
+ */
+#include <mail_params.h>
+#include <mail_task.h>
+#include <mail_version.h>
+#include <maillog_client.h>
+
+ /*
+ * Server skeleton.
+ */
+#include <mail_server.h>
+
+ /*
+ * Tunable parameters.
+ */
+int var_postlogd_watchdog;
+
+ /*
+ * Silly little macros.
+ */
+#define STR(x) vstring_str(x)
+#define LEN(x) VSTRING_LEN(x)
+
+ /*
+ * Logfile stream.
+ */
+static VSTREAM *postlogd_stream = 0;
+
+/* postlogd_fallback - log messages from postlogd(8) itself */
+
+static void postlogd_fallback(const char *buf)
+{
+ (void) logwriter_write(postlogd_stream, buf, strlen(buf));
+}
+
+/* postlogd_service - perform service for client */
+
+static void postlogd_service(char *buf, ssize_t len, char *unused_service,
+ char **unused_argv)
+{
+
+ if (postlogd_stream) {
+ (void) logwriter_write(postlogd_stream, buf, len);
+ }
+
+ /*
+ * After a configuration change that removes the maillog_file pathname,
+ * this service may still receive messages (after "postfix reload" or
+ * after process refresh) from programs that use the old maillog_file
+ * setting. Redirect those messages to the current logging mechanism.
+ */
+ else {
+ char *bp = buf;
+ char *progname_pid;
+
+ /*
+ * Avoid surprises: strip off the date, time, host, and program[pid]:
+ * prefix that were prepended by msg_logger(3). Then, hope that the
+ * current logging driver suppresses its own PID, when it sees that
+ * there is a PID embedded in the 'program name'.
+ */
+ (void) mystrtok(&bp, CHARS_SPACE); /* month */
+ (void) mystrtok(&bp, CHARS_SPACE); /* day */
+ (void) mystrtok(&bp, CHARS_SPACE); /* time */
+ (void) mystrtok(&bp, CHARS_SPACE); /* host */
+ progname_pid = mystrtok(&bp, ":" CHARS_SPACE); /* name[pid] sans ':' */
+ bp += strspn(bp, CHARS_SPACE);
+ if (progname_pid)
+ maillog_client_init(progname_pid, MAILLOG_CLIENT_FLAG_NONE);
+ msg_info("%.*s", (int) (len - (bp - buf)), bp);
+
+ /*
+ * Restore the program name, in case postlogd(8) needs to log
+ * something about itself. We have to call maillog_client_init() in
+ * any case, because neither msg_syslog_init() nor openlog() make a
+ * copy of the name argument. We can't leave that pointing into the
+ * middle of the above message buffer.
+ */
+ maillog_client_init(mail_task((char *) 0), MAILLOG_CLIENT_FLAG_NONE);
+ }
+}
+
+/* pre_jail_init - pre-jail handling */
+
+static void pre_jail_init(char *unused_service_name, char **argv)
+{
+
+ /*
+ * During process initialization, the postlogd daemon will log events to
+ * the postlog socket, so that they can be logged to file later. Once the
+ * postlogd daemon is handling requests, it will stop logging to the
+ * postlog socket and will instead write to the logfile, to avoid
+ * infinite recursion.
+ */
+
+ /*
+ * Sanity check. This service takes no command-line arguments.
+ */
+ if (argv[0])
+ msg_fatal("unexpected command-line argument: %s", argv[0]);
+
+ /*
+ * After a configuration change that removes the maillog_file pathname,
+ * this service may still receive messages from processes that still use
+ * the old configuration. Those messages will have to be redirected to
+ * the current logging subsystem.
+ */
+ if (*var_maillog_file != 0) {
+
+ /*
+ * Instantiate the logwriter or bust.
+ */
+ postlogd_stream = logwriter_open_or_die(var_maillog_file);
+
+ /*
+ * Inform the msg_logger client to stop using the postlog socket, and
+ * to call our logwriter.
+ */
+ msg_logger_control(CA_MSG_LOGGER_CTL_FALLBACK_ONLY,
+ CA_MSG_LOGGER_CTL_FALLBACK_FN(postlogd_fallback),
+ CA_MSG_LOGGER_CTL_END);
+ }
+}
+
+/* post_jail_init - post-jail initialization */
+
+static void post_jail_init(char *unused_name, char **unused_argv)
+{
+
+ /*
+ * Prevent automatic process suicide after a limited number of client
+ * requests. It is OK to terminate after a limited amount of idle time.
+ */
+ var_use_limit = 0;
+}
+
+MAIL_VERSION_STAMP_DECLARE;
+
+/* main - pass control to the multi-threaded skeleton */
+
+int main(int argc, char **argv)
+{
+ static const CONFIG_TIME_TABLE time_table[] = {
+ VAR_POSTLOGD_WATCHDOG, DEF_POSTLOGD_WATCHDOG, &var_postlogd_watchdog, 10, 0,
+ 0,
+ };
+
+ /*
+ * Fingerprint executables and core dumps.
+ */
+ MAIL_VERSION_STAMP_ALLOCATE;
+
+ dgram_server_main(argc, argv, postlogd_service,
+ CA_MAIL_SERVER_TIME_TABLE(time_table),
+ CA_MAIL_SERVER_PRE_INIT(pre_jail_init),
+ CA_MAIL_SERVER_POST_INIT(post_jail_init),
+ CA_MAIL_SERVER_SOLITARY,
+ CA_MAIL_SERVER_WATCHDOG(&var_postlogd_watchdog),
+ 0);
+}
postmap.o: ../../include/mail_parm_split.h
postmap.o: ../../include/mail_task.h
postmap.o: ../../include/mail_version.h
+postmap.o: ../../include/maillog_client.h
postmap.o: ../../include/mime_state.h
postmap.o: ../../include/mkmap.h
postmap.o: ../../include/msg.h
-postmap.o: ../../include/msg_syslog.h
postmap.o: ../../include/msg_vstream.h
postmap.o: ../../include/myflock.h
postmap.o: ../../include/mymalloc.h
#include <vstring.h>
#include <vstream.h>
#include <msg_vstream.h>
-#include <msg_syslog.h>
#include <readlline.h>
#include <stringops.h>
#include <split_at.h>
#include <mime_state.h>
#include <rec_type.h>
#include <mail_parm_split.h>
+#include <maillog_client.h>
/* Application-specific. */
msg_verbose = 1;
/*
- * Initialize. Set up logging, read the global configuration file and
- * extract configuration information.
+ * Initialize. Set up logging. Read the global configuration file after
+ * parsing command-line arguments.
*/
if ((slash = strrchr(argv[0], '/')) != 0 && slash[1])
argv[0] = slash + 1;
msg_vstream_init(argv[0], VSTREAM_ERR);
- msg_syslog_init(mail_task(argv[0]), LOG_PID, LOG_FACILITY);
+ maillog_client_init(mail_task(argv[0]), MAILLOG_CLIENT_FLAG_NONE);
/*
* Check the Postfix library version as soon as we enable logging.
update_env(import_env->argv);
argv_free(import_env);
/* Re-evaluate mail_task() after reading main.cf. */
- msg_syslog_init(mail_task(argv[0]), LOG_PID, LOG_FACILITY);
+ maillog_client_init(mail_task(argv[0]), MAILLOG_CLIENT_FLAG_NONE);
mail_dict_init();
if ((query == 0 || strcmp(query, "-") != 0)
&& (postmap_flags & POSTMAP_FLAG_ANY_KEY))
postmulti.o: ../../include/mail_params.h
postmulti.o: ../../include/mail_parm_split.h
postmulti.o: ../../include/mail_version.h
+postmulti.o: ../../include/maillog_client.h
postmulti.o: ../../include/msg.h
-postmulti.o: ../../include/msg_syslog.h
postmulti.o: ../../include/msg_vstream.h
postmulti.o: ../../include/mymalloc.h
postmulti.o: ../../include/name_code.h
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
+/*
+/* Wietse Venema
+/* Google, Inc.
+/* 111 8th Avenue
+/* New York, NY 10011, USA
/*--*/
/* System library. */
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
-#include <syslog.h>
#include <errno.h>
#include <ctype.h>
#ifdef USE_PATHS_H
#include <msg.h>
#include <msg_vstream.h>
-#include <msg_syslog.h>
#include <vstream.h>
#include <vstring_vstream.h>
#include <stringops.h>
#include <mail_params.h>
#include <mail_conf.h>
#include <mail_parm_split.h>
+#include <maillog_client.h>
/* Application-specific. */
argv[0] = slash + 1;
if (isatty(STDERR_FILENO))
msg_vstream_init(argv[0], VSTREAM_ERR);
- msg_syslog_init(argv[0], LOG_PID, LOG_FACILITY);
+ maillog_client_init(argv[0], MAILLOG_CLIENT_FLAG_LOGWRITER_FALLBACK);
/*
* Check the Postfix library version as soon as we enable logging.
*/
MAIL_VERSION_CHECK;
+ /*
+ * Process main.cf parameters. This is done before the GETOPT() loop to
+ * improve logging. This assumes that no command-line option can affect
+ * parameter processing.
+ */
+ mail_conf_read();
+ get_mail_conf_str_table(str_table);
+ maillog_client_init(argv[0], MAILLOG_CLIENT_FLAG_LOGWRITER_FALLBACK);
+
if ((config_dir = getenv(CONF_ENV_PATH)) != 0
&& strcmp(config_dir, DEF_CONFIG_DIR) != 0)
msg_fatal("Non-default configuration directory: %s=%s",
CONF_ENV_PATH, config_dir);
/*
- * Parse switches.
+ * Parse switches. Move the above mail_conf_read() block after this loop,
+ * if any command-line option can affect parameter processing.
*/
while ((ch = GETOPT(argc, argv, "ae:g:i:G:I:lpRvx")) > 0) {
switch (ch) {
EDIT_CMD_STR(cmd_mode));
}
- /*
- * Process main.cf parameters.
- */
- mail_conf_read();
- get_mail_conf_str_table(str_table);
-
/*
* Sanity checks.
*/
postqueue.o: ../../include/mail_run.h
postqueue.o: ../../include/mail_task.h
postqueue.o: ../../include/mail_version.h
+postqueue.o: ../../include/maillog_client.h
postqueue.o: ../../include/msg.h
-postqueue.o: ../../include/msg_syslog.h
postqueue.o: ../../include/msg_vstream.h
postqueue.o: ../../include/mymalloc.h
postqueue.o: ../../include/nvtable.h
#include <clean_env.h>
#include <vstream.h>
#include <msg_vstream.h>
-#include <msg_syslog.h>
#include <argv.h>
#include <safe.h>
#include <connect.h>
#include <valid_mailhost_addr.h>
#include <mail_dict.h>
#include <mail_parm_split.h>
+#include <maillog_client.h>
/* Application-specific. */
msg_fatal_status(EX_UNAVAILABLE, "open /dev/null: %m");
/*
- * Initialize. Set up logging, read the global configuration file and
- * extract configuration information. Set up signal handlers so that we
- * can clean up incomplete output.
- * Censor the process name: it is provided by the user.
+ * Initialize. Set up logging. Read the global configuration file after
+ * parsing command-line arguments. Censor the process name: it is
+ * provided by the user.
*/
argv[0] = "postqueue";
msg_vstream_init(argv[0], VSTREAM_ERR);
msg_cleanup(unavailable);
- msg_syslog_init(mail_task("postqueue"), LOG_PID, LOG_FACILITY);
+ maillog_client_init(mail_task("postqueue"), MAILLOG_CLIENT_FLAG_NONE);
set_mail_conf_str(VAR_PROCNAME, var_procname = mystrdup(argv[0]));
/*
*/
mail_conf_read();
/* Re-evaluate mail_task() after reading main.cf. */
- msg_syslog_init(mail_task("postqueue"), LOG_PID, LOG_FACILITY);
+ maillog_client_init(mail_task("postqueue"), MAILLOG_CLIENT_FLAG_NONE);
mail_dict_init(); /* proxy, sql, ldap */
get_mail_conf_str_table(str_table);
postsuper.o: ../../include/mail_queue.h
postsuper.o: ../../include/mail_task.h
postsuper.o: ../../include/mail_version.h
+postsuper.o: ../../include/maillog_client.h
postsuper.o: ../../include/msg.h
-postsuper.o: ../../include/msg_syslog.h
postsuper.o: ../../include/msg_vstream.h
postsuper.o: ../../include/mymalloc.h
postsuper.o: ../../include/myrand.h
#include <mymalloc.h>
#include <msg.h>
-#include <msg_syslog.h>
#include <vstream.h>
#include <msg_vstream.h>
#include <scan_dir.h>
#include <mail_open_ok.h>
#include <file_id.h>
#include <mail_parm_split.h>
+#include <maillog_client.h>
/* Application-specific. */
if ((slash = strrchr(argv[0], '/')) != 0 && slash[1])
argv[0] = slash + 1;
msg_vstream_init(argv[0], VSTREAM_ERR);
- msg_syslog_init(mail_task(argv[0]), LOG_PID, LOG_FACILITY);
+ maillog_client_init(mail_task(argv[0]),
+ MAILLOG_CLIENT_FLAG_LOGWRITER_FALLBACK);
set_mail_conf_str(VAR_PROCNAME, var_procname = mystrdup(argv[0]));
/*
update_env(import_env->argv);
argv_free(import_env);
/* Re-evaluate mail_task() after reading main.cf. */
- msg_syslog_init(mail_task(argv[0]), LOG_PID, LOG_FACILITY);
+ maillog_client_init(mail_task(argv[0]),
+ MAILLOG_CLIENT_FLAG_LOGWRITER_FALLBACK);
if (chdir(var_queue_dir))
msg_fatal("chdir %s: %m", var_queue_dir);
sendmail.o: ../../include/mail_stream.h
sendmail.o: ../../include/mail_task.h
sendmail.o: ../../include/mail_version.h
+sendmail.o: ../../include/maillog_client.h
sendmail.o: ../../include/mime_state.h
sendmail.o: ../../include/msg.h
sendmail.o: ../../include/msg_stats.h
-sendmail.o: ../../include/msg_syslog.h
sendmail.o: ../../include/msg_vstream.h
sendmail.o: ../../include/mymalloc.h
sendmail.o: ../../include/name_code.h
#include <stdlib.h>
#include <signal.h>
#include <fcntl.h>
-#include <syslog.h>
#include <time.h>
#include <errno.h>
#include <ctype.h>
#include <mymalloc.h>
#include <vstream.h>
#include <msg_vstream.h>
-#include <msg_syslog.h>
#include <vstring_vstream.h>
#include <username.h>
#include <fullname.h>
#include <name_code.h>
#include <warn_stat.h>
#include <clean_env.h>
+#include <maillog_client.h>
/* Global library. */
debug_me = 1;
/*
- * Initialize. Set up logging, read the global configuration file and
- * extract configuration information. Set up signal handlers so that we
- * can clean up incomplete output.
+ * Initialize. Set up logging. Read the global configuration file after
+ * command-line processing. Set up signal handlers so that we can clean
+ * up incomplete output.
*/
if ((slash = strrchr(argv[0], '/')) != 0 && slash[1])
argv[0] = slash + 1;
msg_vstream_init(argv[0], VSTREAM_ERR);
msg_cleanup(tempfail);
- msg_syslog_init(mail_task("sendmail"), LOG_PID, LOG_FACILITY);
+ maillog_client_init(mail_task("sendmail"), MAILLOG_CLIENT_FLAG_NONE);
set_mail_conf_str(VAR_PROCNAME, var_procname = mystrdup(argv[0]));
/*
update_env(import_env->argv);
argv_free(import_env);
/* Re-evaluate mail_task() after reading main.cf. */
- msg_syslog_init(mail_task("sendmail"), LOG_PID, LOG_FACILITY);
+ maillog_client_init(mail_task("sendmail"), MAILLOG_CLIENT_FLAG_NONE);
get_mail_conf_str_table(str_table);
mail_dict_init();
tls_certkey_tests: test
@echo Testing loading of keys and certs
- @export LD_LIBRARY_PATH=../../lib; \
- for pem in goodchains.pem; do \
- ./tls_certkey $$pem > $$pem.out 2>&1 || exit 1; \
+ @for pem in goodchains.pem; do \
+ $(SHLIB_ENV) $(VALGRIND) ./tls_certkey $$pem > $$pem.out 2>&1 || exit 1; \
diff $$pem.ref $$pem.out || exit 1; \
echo " $$pem: OK"; \
done; \
for pem in *-mixed-*.pem ; do \
- ./tls_certkey -m $$pem > $$pem.out 2>&1 || exit 1; \
+ $(SHLIB_ENV) $(VALGRIND) ./tls_certkey -m $$pem > $$pem.out 2>&1 || exit 1; \
diff $$pem.ref $$pem.out || exit 1; \
echo " $$pem: OK"; \
done; \
for pem in bad-*.pem; do \
- ./tls_certkey $$pem > $$pem.out 2>&1 && exit 1 || : ok; \
+ $(SHLIB_ENV) $(VALGRIND) ./tls_certkey $$pem > $$pem.out 2>&1 && exit 1 || : ok; \
egrep -v 'TLS library problem' $$pem.out | diff $$pem.ref - || \
exit 1; \
echo " $$pem: OK"; \
poll_fd.c timecmp.c slmdb.c dict_pipe.c dict_random.c \
valid_utf8_hostname.c midna_domain.c argv_splitq.c balpar.c dict_union.c \
extpar.c dict_inline.c casefold.c dict_utf8.c strcasecmp_utf8.c \
- split_qnameval.c argv_attr_print.c argv_attr_scan.c dict_file.c
+ split_qnameval.c argv_attr_print.c argv_attr_scan.c dict_file.c \
+ msg_logger.c logwriter.c unix_dgram_connect.c unix_dgram_listen.c
OBJS = alldig.o allprint.o argv.o argv_split.o attr_clnt.o attr_print0.o \
attr_print64.o attr_print_plain.o attr_scan0.o attr_scan64.o \
attr_scan_plain.o auto_clnt.o base64_code.o basename.o binhash.o \
poll_fd.o timecmp.o $(NON_PLUGIN_MAP_OBJ) dict_pipe.o dict_random.o \
valid_utf8_hostname.o midna_domain.o argv_splitq.o balpar.o dict_union.o \
extpar.o dict_inline.o casefold.o dict_utf8.o strcasecmp_utf8.o \
- split_qnameval.o argv_attr_print.o argv_attr_scan.o dict_file.o
+ split_qnameval.o argv_attr_print.o argv_attr_scan.o dict_file.o \
+ msg_logger.o logwriter.o unix_dgram_connect.o unix_dgram_listen.o
# MAP_OBJ is for maps that may be dynamically loaded with dynamicmaps.cf.
# When hard-linking these, makedefs sets NON_PLUGIN_MAP_OBJ=$(MAP_OBJ),
# otherwise it sets the PLUGIN_* macros.
dict_fail.h warn_stat.h dict_sockmap.h line_number.h timecmp.h \
slmdb.h compat_va_copy.h dict_pipe.h dict_random.h \
valid_utf8_hostname.h midna_domain.h dict_union.h dict_inline.h \
- check_arg.h argv_attr.h
+ check_arg.h argv_attr.h msg_logger.h logwriter.h
TESTSRC = fifo_open.c fifo_rdwr_bug.c fifo_rdonly_bug.c select_bug.c \
stream_test.c dup2_pass_on_exec.c
DEFS = -I. -D$(SYSTYPE)
myaddrinfo myaddrinfo4 inet_proto sane_basename format_tv \
valid_utf8_string ip_match base32_code msg_rate_delay netstring \
vstream timecmp dict_cache midna_domain casefold strcasecmp_utf8 \
- vbuf_print split_qnameval vstream
+ vbuf_print split_qnameval vstream msg_logger
PLUGIN_MAP_SO = $(LIB_PREFIX)pcre$(LIB_SUFFIX)
LIB_DIR = ../../lib
$(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(SYSLIBS)
mv junk $@.o
+msg_logger: msg_logger.c $(LIB)
+ mv $@.o junk
+ $(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(SYSLIBS)
+ mv junk $@.o
+
msg_syslog: msg_syslog.c $(LIB)
mv $@.o junk
$(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(SYSLIBS)
load_lib.o: load_lib.h
load_lib.o: msg.h
load_lib.o: sys_defs.h
+logwriter.o: check_arg.h
+logwriter.o: iostuff.h
+logwriter.o: logwriter.c
+logwriter.o: logwriter.h
+logwriter.o: msg.h
+logwriter.o: mymalloc.h
+logwriter.o: safe_open.h
+logwriter.o: sys_defs.h
+logwriter.o: vbuf.h
+logwriter.o: vstream.h
+logwriter.o: vstring.h
lowercase.o: check_arg.h
lowercase.o: lowercase.c
lowercase.o: stringops.h
msg.o: msg.h
msg.o: msg_output.h
msg.o: sys_defs.h
+msg_logger.o: check_arg.h
+msg_logger.o: connect.h
+msg_logger.o: iostuff.h
+msg_logger.o: logwriter.h
+msg_logger.o: msg.h
+msg_logger.o: msg_logger.c
+msg_logger.o: msg_logger.h
+msg_logger.o: msg_output.h
+msg_logger.o: mymalloc.h
+msg_logger.o: safe.h
+msg_logger.o: sys_defs.h
+msg_logger.o: vbuf.h
+msg_logger.o: vstream.h
+msg_logger.o: vstring.h
msg_output.o: check_arg.h
msg_output.o: msg_output.c
msg_output.o: msg_output.h
msg_syslog.o: msg_output.h
msg_syslog.o: msg_syslog.c
msg_syslog.o: msg_syslog.h
+msg_syslog.o: mymalloc.h
msg_syslog.o: safe.h
msg_syslog.o: stringops.h
msg_syslog.o: sys_defs.h
unix_connect.o: sys_defs.h
unix_connect.o: timed_connect.h
unix_connect.o: unix_connect.c
+unix_dgram_connect.o: connect.h
+unix_dgram_connect.o: iostuff.h
+unix_dgram_connect.o: msg.h
+unix_dgram_connect.o: sys_defs.h
+unix_dgram_connect.o: unix_dgram_connect.c
+unix_dgram_listen.o: htable.h
+unix_dgram_listen.o: iostuff.h
+unix_dgram_listen.o: listen.h
+unix_dgram_listen.o: msg.h
+unix_dgram_listen.o: sys_defs.h
+unix_dgram_listen.o: unix_dgram_listen.c
unix_listen.o: htable.h
unix_listen.o: iostuff.h
unix_listen.o: listen.h
extern int unix_connect(const char *, int, int);
extern int inet_connect(const char *, int, int);
extern int stream_connect(const char *, int, int);
+extern int unix_dgram_connect(const char *, int);
/* LICENSE
/* .ad
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
+/*
+/* Wietse Venema
+/* Google, Inc.
+/* 111 8th Avenue
+/* New York, NY 10011, USA
/*--*/
#endif
extern int inet_listen(const char *, int, int);
extern int fifo_listen(const char *, int, int);
extern int stream_listen(const char *, int, int);
+extern int unix_dgram_listen(const char *, int);
extern int inet_accept(int);
extern int unix_accept(int);
--- /dev/null
+/*++
+/* NAME
+/* logwriter 3
+/* SUMMARY
+/* logfile writer
+/* SYNOPSIS
+/* #include <logwriter.h>
+/*
+/* VSTREAM *logwriter_open_or_die(
+/* const char *path)
+/*
+/* int logwriter_write(
+/* VSTREAM *file,
+/* const char *buffer.
+/* ssize_t buflen)
+/*
+/* int logwriter_close(
+/* VSTREAM *file)
+/*
+/* int logwriter_one_shot(
+/* const char *path,
+/* const char *buffer,
+/* ssize_t buflen)
+/* DESCRIPTION
+/* This module manages a logfile writer.
+/*
+/* logwriter_open_or_die() safely opens the specified file in
+/* write+append mode. File open/create errors are fatal.
+/*
+/* logwriter_write() writes the buffer plus newline to the
+/* open logfile. The result is zero if successful, VSTREAM_EOF
+/* if the operation failed.
+/*
+/* logwriter_close() closes the logfile and destroys the VSTREAM
+/* instance. The result is zero if there were no errors writing
+/* the file, VSTREAM_EOF otherwise.
+/*
+/* logwriter_one_shot() combines all the above operations. The
+/* result is zero if successful, VSTREAM_EOF if any operation
+/* failed.
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* Google, Inc.
+/* 111 8th Avenue
+/* New York, NY 10011, USA
+/*--*/
+
+ /*
+ * System library.
+ */
+#include <sys_defs.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+
+ /*
+ * Utility library.
+ */
+#include <iostuff.h>
+#include <logwriter.h>
+#include <msg.h>
+#include <mymalloc.h>
+#include <safe_open.h>
+#include <vstream.h>
+
+ /*
+ * Application-specific.
+ */
+
+/* logwriter_open_or_die - open logfile */
+
+VSTREAM *logwriter_open_or_die(const char *path)
+{
+ VSTREAM *fp;
+ VSTRING *why = vstring_alloc(100);
+
+#define NO_STATP ((struct stat *) 0)
+#define NO_CHOWN (-1)
+#define NO_CHGRP (-1)
+
+ fp = safe_open(path, O_CREAT | O_WRONLY | O_APPEND, 0644,
+ NO_STATP, NO_CHOWN, NO_CHGRP, why);
+ if (fp == 0)
+ msg_fatal("open logfile '%s': %s", path, vstring_str(why));
+ close_on_exec(vstream_fileno(fp), CLOSE_ON_EXEC);
+ vstring_free(why);
+ return (fp);
+}
+
+/* logwriter_write - append to logfile */
+
+int logwriter_write(VSTREAM *fp, const char *buf, ssize_t len)
+{
+ if (len < 0)
+ msg_panic("logwriter_write: negative length %ld", (long) len);
+ if (vstream_fwrite(fp, buf, len) != len)
+ return (VSTREAM_EOF);
+ VSTREAM_PUTC('\n', fp);
+ return (vstream_fflush(fp));
+}
+
+/* logwriter_close - close logfile */
+
+int logwriter_close(VSTREAM *fp)
+{
+ return (vstream_fclose(fp));
+}
+
+/* logwriter_one_shot - one-shot logwriter */
+
+int logwriter_one_shot(const char *path, const char *buf, ssize_t len)
+{
+ VSTREAM *fp;
+ int err;
+
+ fp = logwriter_open_or_die(path);
+ err = logwriter_write(fp, buf, len);
+ err |= logwriter_close(fp);
+ return (err ? VSTREAM_EOF : 0);
+}
--- /dev/null
+#ifndef _LOGWRITER_H_INCLUDED_
+#define _LOGWRITER_H_INCLUDED_
+
+/*++
+/* NAME
+/* logwriter 3h
+/* SUMMARY
+/* logfile writer
+/* SYNOPSIS
+/* #include <logwriter.h>
+/* DESCRIPTION
+/* .nf
+
+ /*
+ * Utility library.
+ */
+#include <vstream.h>
+
+ /*
+ * External interface.
+ */
+extern VSTREAM *logwriter_open_or_die(const char *);
+extern int logwriter_write(VSTREAM *, const char *, ssize_t);
+extern int logwriter_close(VSTREAM *);
+extern int logwriter_one_shot(const char *, const char *, ssize_t);
+
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* Google, Inc.
+/* 111 8th Avenue
+/* New York, NY 10011, USA
+/*--*/
+
+#endif
--- /dev/null
+/*++
+/* NAME
+/* msg_logger 3
+/* SUMMARY
+/* direct diagnostics to logger service
+/* SYNOPSIS
+/* #include <msg_logger.h>
+/*
+/* void msg_logger_init(
+/* const char *progname,
+/* const char *hostname,
+/* const char *unix_path,
+/* void (*fallback)(const char *))
+/*
+/* void msg_logger_control(
+/* int key,...)
+/* DESCRIPTION
+/* This module implements support to report msg(3) diagnostics
+/* through a logger daemon, with an optional fallback mechanism.
+/* The log record format is like traditional syslog:
+/*
+/* .nf
+/* Mmm dd host progname[pid]: text...
+/* .fi
+/*
+/* msg_logger_init() arranges that subsequent msg(3) calls
+/* will write to an internal logging service. This function
+/* may also be used to update msg_logger settings.
+/*
+/* Arguments:
+/* .IP progname
+/* The program name that is prepended to a log record.
+/* .IP hostname
+/* The host name that is prepended to a log record. Only the
+/* first hostname label will be used.
+/* .IP unix_path
+/* Pathname of a unix-domain datagram service endpoint. A
+/* typical use case is the pathname of the postlog socket.
+/* .IP fallback
+/* Null pointer, or pointer to function that will be called
+/* with a formatted message when the logger service is not
+/* (yet) available. A typical use case is to pass the record
+/* to the logwriter(3) module.
+/* .PP
+/* msg_logger_control() makes adjustments to the msg_logger
+/* client. These adjustments remain in effect until the next
+/* msg_logger_init() or msg_logger_control() call. The arguments
+/* are a list of macros with zero or more arguments, terminated
+/* with CA_MSG_LOGGER_CTL_END which has none. The following
+/* lists the names and the types of the corresponding value
+/* arguments.
+/*
+/* Arguments:
+/* .IP CA_MSG_LOGGER_CTL_FALLBACK_ONLY
+/* Disable the logging socket, and use the fallback function
+/* only. This remains in effect until the next msg_logger_init()
+/* call.
+/* .IP CA_MSG_LOGGER_CTL_FALLBACK(void (*)(const char *))
+/* Override the fallback setting (see above) with the specified
+/* function pointer. This remains in effect until the next
+/* msg_logger_init() or msg_logger_control() call.
+/* .IP CA_MSG_LOGGER_CTL_DISABLE
+/* Disable the msg_logger. This remains in effect until the
+/* next msg_logger_init() call.
+/* SEE ALSO
+/* msg(3) diagnostics module
+/* BUGS
+/* Output records are truncated to ~2000 characters, because
+/* unlimited logging is a liability.
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* Google, Inc.
+/* 111 8th Avenue
+/* New York, NY 10011, USA
+/*--*/
+
+ /*
+ * System libraries.
+ */
+#include <sys_defs.h>
+#include <sys/socket.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+ /*
+ * Application-specific.
+ */
+#include <connect.h>
+#include <logwriter.h>
+#include <msg.h>
+#include <msg_logger.h>
+#include <msg_output.h>
+#include <mymalloc.h>
+#include <safe.h>
+#include <vstream.h>
+#include <vstring.h>
+
+ /*
+ * Saved state from msg_logger_init().
+ */
+static char *msg_logger_progname;
+static char *msg_logger_hostname;
+static char *msg_logger_unix_path;
+static void (*msg_logger_fallback_fn) (const char *);
+static int msg_logger_fallback_only_override = 0;
+static int msg_logger_enable = 0;
+
+ /*
+ * Other state.
+ */
+#define MSG_LOGGER_SOCK_NONE (-1)
+
+static VSTRING *msg_logger_buf;
+static int msg_logger_sock = MSG_LOGGER_SOCK_NONE;
+
+ /*
+ * Safety limit.
+ */
+#define MSG_LOGGER_RECLEN 2000
+
+ /*
+ * SLMs.
+ */
+#define STR(x) vstring_str(x)
+#define LEN(x) VSTRING_LEN(x)
+
+
+/* msg_logger_print - log info to service or file */
+
+static void msg_logger_print(int level, const char *text)
+{
+ time_t now;
+ struct tm *lt;
+ ssize_t len;
+
+ /*
+ * This test is simple enough that we don't bother with unregistering the
+ * msg_logger_print() function.
+ */
+ if (msg_logger_enable == 0)
+ return;
+
+ /*
+ * TODO: this should be a reusable NAME_CODE table plus lookup function.
+ */
+ static int log_level[] = {
+ MSG_INFO, MSG_WARN, MSG_ERROR, MSG_FATAL, MSG_PANIC,
+ };
+ static char *severity_name[] = {
+ "info", "warning", "error", "fatal", "panic",
+ };
+
+ /*
+ * Note: there is code in postlogd(8) that attempts to strip off
+ * information that is prepended here. If the formatting below is
+ * changed, then postlogd needs to be updated as well.
+ */
+
+ /*
+ * Format the time stamp.
+ */
+ if (time(&now) < 0)
+ msg_fatal("no time: %m");
+ lt = localtime(&now);
+ VSTRING_RESET(msg_logger_buf);
+ if ((len = strftime(vstring_str(msg_logger_buf),
+ vstring_avail(msg_logger_buf),
+ "%b %d %H:%M:%S ", lt)) == 0)
+ msg_fatal("strftime: %m");
+ vstring_set_payload_size(msg_logger_buf, len);
+
+ /*
+ * Format the host name (first name label only).
+ */
+ vstring_sprintf_append(msg_logger_buf, "%.*s ",
+ (int) strcspn(msg_logger_hostname, "."),
+ msg_logger_hostname);
+
+ /*
+ * Format the message.
+ */
+ if (level < 0 || level >= (int) (sizeof(log_level) / sizeof(log_level[0])))
+ msg_panic("msg_logger_print: invalid severity level: %d", level);
+
+ if (level == MSG_INFO) {
+ vstring_sprintf_append(msg_logger_buf, "%s[%ld]: %.*s",
+ msg_logger_progname, (long) getpid(),
+ (int) MSG_LOGGER_RECLEN, text);
+ } else {
+ vstring_sprintf_append(msg_logger_buf, "%s[%ld]: %s: %.*s",
+ msg_logger_progname, (long) getpid(),
+ severity_name[level], (int) MSG_LOGGER_RECLEN, text);
+ }
+
+ /*
+ * Connect to logging service, or fall back to direct log. Many systems
+ * will report ENOENT if the endpoint does not exist, ECONNREFUSED if no
+ * server has opened the endpoint.
+ */
+ if (msg_logger_fallback_only_override == 0
+ && msg_logger_sock == MSG_LOGGER_SOCK_NONE) {
+ msg_logger_sock = unix_dgram_connect(msg_logger_unix_path, BLOCKING);
+ if (msg_logger_sock >= 0)
+ close_on_exec(msg_logger_sock, CLOSE_ON_EXEC);
+ }
+ if (msg_logger_sock != MSG_LOGGER_SOCK_NONE) {
+ send(msg_logger_sock, STR(msg_logger_buf), LEN(msg_logger_buf), 0);
+ } else if (msg_logger_fallback_fn) {
+ msg_logger_fallback_fn(STR(msg_logger_buf));
+ }
+}
+
+/* msg_logger_init - initialize */
+
+void msg_logger_init(const char *progname, const char *hostname,
+ const char *unix_path, void (*fallback) (const char *))
+{
+ static int first_call = 1;
+ extern char **environ;
+
+ /*
+ * XXX If this program is set-gid, then TZ must not be trusted. This
+ * scrubbing code is in the wrong place.
+ */
+ if (first_call) {
+ if (unsafe())
+ while (getenv("TZ")) /* There may be multiple. */
+ if (unsetenv("TZ") < 0) { /* Desperate measures. */
+ environ[0] = 0;
+ msg_fatal("unsetenv: %m");
+ }
+ tzset();
+ }
+
+ /*
+ * Save the request info. Use free-after-update because this data will be
+ * accessed when mystrdup() runs out of memory.
+ */
+#define UPDATE_AND_FREE(dst, src) do { \
+ if ((dst) == 0 || strcmp((dst), (src)) != 0) { \
+ char *_bak = (dst); \
+ (dst) = mystrdup(src); \
+ if ((_bak)) myfree(_bak); \
+ } \
+ } while (0)
+
+ UPDATE_AND_FREE(msg_logger_progname, progname);
+ UPDATE_AND_FREE(msg_logger_hostname, hostname);
+ UPDATE_AND_FREE(msg_logger_unix_path, unix_path);
+ msg_logger_fallback_fn = fallback;
+
+ /*
+ * One-time activity: register the output handler, and allocate a buffer.
+ */
+ if (first_call) {
+ first_call = 0;
+ msg_output(msg_logger_print);
+ msg_logger_buf = vstring_alloc(2048);
+ }
+
+ /*
+ * Always.
+ */
+ msg_logger_enable = 1;
+ msg_logger_fallback_only_override = 0;
+}
+
+/* msg_logger_control - tweak the client */
+
+void msg_logger_control(int name,...)
+{
+ const char *myname = "msg_logger_control";
+ va_list ap;
+
+ /*
+ * Overrides remain in effect until the next msg_logger_init() or
+ * msg_logger_control() call,
+ */
+ for (va_start(ap, name); name != MSG_LOGGER_CTL_END; name = va_arg(ap, int)) {
+ switch (name) {
+ case MSG_LOGGER_CTL_FALLBACK_ONLY:
+ msg_logger_fallback_only_override = 1;
+ if (msg_logger_sock != MSG_LOGGER_SOCK_NONE) {
+ (void) close(msg_logger_sock);
+ msg_logger_sock = MSG_LOGGER_SOCK_NONE;
+ }
+ break;
+ case MSG_LOGGER_CTL_FALLBACK_FN:
+ msg_logger_fallback_fn = va_arg(ap, MSG_LOGGER_FALLBACK_FN);
+ break;
+ case MSG_LOGGER_CTL_DISABLE:
+ msg_logger_enable = 0;
+ break;
+ default:
+ msg_panic("%s: bad name %d", myname, name);
+ }
+ }
+ va_end(ap);
+}
+
+#ifdef TEST
+
+ /*
+ * Proof-of-concept program to test the msg_logger module.
+ *
+ * Usage: msg_logger hostname unix_path fallback_path text...
+ */
+static char *fallback_path;
+
+static void fallback(const char *msg)
+{
+ if (logwriter_one_shot(fallback_path, msg) != 0)
+ msg_fatal("unable to fall back to directly write %s: %m",
+ fallback_path);
+}
+
+int main(int argc, char **argv)
+{
+ VSTRING *vp = vstring_alloc(256);
+
+ if (argc < 4)
+ msg_fatal("usage: %s host port path text to log", argv[0]);
+ msg_logger_init(argv[0], argv[1], argv[2], fallback);
+ fallback_path = argv[3];
+ argc -= 3;
+ argv += 3;
+ while (--argc && *++argv) {
+ vstring_strcat(vp, *argv);
+ if (argv[1])
+ vstring_strcat(vp, " ");
+ }
+ msg_warn("static text");
+ msg_warn("dynamic text: >%s<", vstring_str(vp));
+ msg_warn("dynamic numeric: >%d<", 42);
+ msg_warn("error text: >%m<");
+ msg_warn("dynamic: >%s<: error: >%m<", vstring_str(vp));
+ vstring_free(vp);
+ return (0);
+}
+
+#endif
--- /dev/null
+#ifndef _MSG_LOGGER_H_INCLUDED_
+#define _MSG_LOGGER_H_INCLUDED_
+
+/*++
+/* NAME
+/* msg_logger 3h
+/* SUMMARY
+/* direct diagnostics to logger service
+/* SYNOPSIS
+/* #include <msg_logger.h>
+/* DESCRIPTION
+/* .nf
+
+ /*
+ * System library.
+ */
+#include <stdarg.h>
+
+ /*
+ * Utility library.
+ */
+#include <check_arg.h>
+
+ /*
+ * External interface.
+ */
+typedef void (*MSG_LOGGER_FALLBACK_FN) (const char *);
+
+extern void msg_logger_init(const char *, const char *, const char *,
+ MSG_LOGGER_FALLBACK_FN);
+extern void msg_logger_control(int,...);
+
+/* Internal-only API: type-unchecked arguments. */
+#define MSG_LOGGER_CTL_END 0
+#define MSG_LOGGER_CTL_FALLBACK_ONLY 1
+#define MSG_LOGGER_CTL_FALLBACK_FN 2
+#define MSG_LOGGER_CTL_DISABLE 3
+
+/* Safer API: type-checked arguments, external use. */
+#define CA_MSG_LOGGER_CTL_END MSG_LOGGER_CTL_END
+#define CA_MSG_LOGGER_CTL_FALLBACK_ONLY MSG_LOGGER_CTL_FALLBACK_ONLY
+#define CA_MSG_LOGGER_CTL_FALLBACK_FN(v) \
+ MSG_LOGGER_CTL_FALLBACK_FN, CHECK_VAL(MSG_LOGGER_CTL, \
+ MSG_LOGGER_FALLBACK_FN, (v))
+#define CA_MSG_LOGGER_CTL_DISABLE MSG_LOGGER_CTL_DISABLE
+
+CHECK_VAL_HELPER_DCL(MSG_LOGGER_CTL, MSG_LOGGER_FALLBACK_FN);
+
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* Google, Inc.
+/* 111 8th Avenue
+/* New York, NY 10011, USA
+/*--*/
+
+#endif
/* int level;
/* const char *format;
/* va_list ap;
-/*
-/* void msg_text(level, text)
-/* int level;
-/* const char *text;
/* DESCRIPTION
/* This module implements low-level output management for the
/* msg(3) diagnostics interface.
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
+/*
+/* Wietse Venema
+/* Google, Inc.
+/* 111 8th Avenue
+/* New York, NY 10011, USA
/*--*/
/* System library. */
/*
* Global scope, to discourage the compiler from doing smart things.
*/
-volatile int msg_vprintf_lock;
-volatile int msg_text_lock;
+volatile int msg_vprintf_level;
/*
- * Private state.
+ * Private state. Allow one nested call, so that one logging error can be
+ * reported to stderr before bailing out.
*/
+#define MSG_OUT_NESTING_LIMIT 2
static MSG_OUTPUT_FN *msg_output_fn = 0;
static int msg_output_fn_count = 0;
-static VSTRING *msg_buffer = 0;
+static VSTRING *msg_buffers[MSG_OUT_NESTING_LIMIT];
/* msg_output - specify output handler */
void msg_output(MSG_OUTPUT_FN output_fn)
{
+ int i;
/*
- * Allocate all resources during initialization.
+ * Allocate all resources during initialization. This may result in a
+ * recursive call due to memory allocation error.
*/
- if (msg_buffer == 0)
- msg_buffer = vstring_alloc(100);
+ if (msg_buffers[MSG_OUT_NESTING_LIMIT - 1] == 0) {
+ for (i = 0; i < MSG_OUT_NESTING_LIMIT; i++)
+ msg_buffers[i] = vstring_alloc(100);
+ }
/*
* We're not doing this often, so avoid complexity and allocate memory
void msg_vprintf(int level, const char *format, va_list ap)
{
int saved_errno = errno;
-
- if (msg_vprintf_lock == 0) {
- msg_vprintf_lock = 1;
- /* On-the-fly initialization for debugging test programs only. */
- if (msg_output_fn_count == 0)
- msg_vstream_init("unknown", VSTREAM_ERR);
- /* OK if terminating signal handler hijacks control before next stmt. */
- vstring_vsprintf(msg_buffer, percentm(format, errno), ap);
- msg_text(level, vstring_str(msg_buffer));
- msg_vprintf_lock = 0;
- }
- errno = saved_errno;
-}
-
-/* msg_text - sanitize and log pre-formatted text */
-
-void msg_text(int level, const char *text)
-{
+ VSTRING *vp;
int i;
- /*
- * Sanitize the text. Use a private copy if necessary.
- */
- if (msg_text_lock == 0) {
- msg_text_lock = 1;
- /* OK if terminating signal handler hijacks control before next stmt. */
- if (text != vstring_str(msg_buffer))
- vstring_strcpy(msg_buffer, text);
- printable(vstring_str(msg_buffer), '?');
- /* On-the-fly initialization for debugging test programs only. */
+ if (msg_vprintf_level < MSG_OUT_NESTING_LIMIT) {
+ msg_vprintf_level += 1;
+ /* On-the-fly initialization for test programs and startup errors. */
if (msg_output_fn_count == 0)
msg_vstream_init("unknown", VSTREAM_ERR);
+ vp = msg_buffers[msg_vprintf_level - 1];
+ /* OK if terminating signal handler hijacks control before next stmt. */
+ vstring_vsprintf(vp, percentm(format, errno), ap);
+ printable(vstring_str(vp), '?');
for (i = 0; i < msg_output_fn_count; i++)
- msg_output_fn[i] (level, vstring_str(msg_buffer));
- msg_text_lock = 0;
+ msg_output_fn[i] (level, vstring_str(vp));
+ msg_vprintf_level -= 1;
}
+ errno = saved_errno;
}
extern void msg_output(MSG_OUTPUT_FN);
extern void PRINTFLIKE(2, 3) msg_printf(int, const char *,...);
extern void msg_vprintf(int, const char *, va_list);
-extern void msg_text(int, const char *);
#define MSG_INFO 0 /* informative */
#define MSG_WARN 1 /* warning (non-fatal) */
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
+/*
+/* Wietse Venema
+/* Google, Inc.
+/* 111 8th Avenue
+/* New York, NY 10011, USA
/*--*/
#endif
/* int log_opt;
/* int facility;
/*
-/* int msg_syslog_facility(facility_name)
+/* int msg_syslog_set_facility(facility_name)
/* const char *facility_name;
+/*
+/* void msg_syslog_disable(void)
/* DESCRIPTION
/* This module implements support to report msg(3) diagnostics
/* via the syslog daemon.
/*
/* msg_syslog_init() is a wrapper around the openlog(3) routine
/* that directs subsequent msg(3) output to the syslog daemon.
+/* This function may also be called to update msg_syslog
+/* settings. If the program name appears to contain a process ID
+/* then msg_syslog_init will attempt to suppress its own PID.
/*
-/* msg_syslog_facility() is a helper routine that overrides the
+/* msg_syslog_set_facility() is a helper routine that overrides the
/* logging facility that is specified with msg_syslog_init().
/* The result is zero in case of an unknown facility name.
+/*
+/* msg_syslog_disable() turns off the msg_syslog client,
+/* until a subsequent msg_syslog_init() call.
/* SEE ALSO
/* syslog(3) syslog library
/* msg(3) diagnostics module
#include "msg_output.h"
#include "msg_syslog.h"
#include "safe.h"
+#include <mymalloc.h>
/*
* Stay a little below the 2048-byte limit of older syslog()
0,
};
-static int syslog_facility;
+static int msg_syslog_facility;
+static int msg_syslog_enable;
/* msg_syslog_print - log info to syslog daemon */
"info", "warning", "error", "fatal", "panic",
};
+ if (msg_syslog_enable == 0)
+ return;
+
if (level < 0 || level >= (int) (sizeof(log_level) / sizeof(log_level[0])))
msg_panic("msg_syslog_print: invalid severity level: %d", level);
if (level == MSG_INFO) {
- syslog(syslog_facility | log_level[level], "%.*s",
+ syslog(msg_syslog_facility | log_level[level], "%.*s",
(int) MSG_SYSLOG_RECLEN, text);
} else {
- syslog(syslog_facility | log_level[level], "%s: %.*s",
+ syslog(msg_syslog_facility | log_level[level], "%s: %.*s",
severity_name[level], (int) MSG_SYSLOG_RECLEN, text);
}
}
* XXX If this program is set-gid, then TZ must not be trusted. This
* scrubbing code is in the wrong place.
*/
- if (unsafe())
- while (getenv("TZ")) /* There may be multiple. */
- if (unsetenv("TZ") < 0) { /* Desperate measures. */
- environ[0] = 0;
- msg_fatal("unsetenv: %m");
- }
- tzset();
+ if (first_call) {
+ if (unsafe())
+ while (getenv("TZ")) /* There may be multiple. */
+ if (unsetenv("TZ") < 0) { /* Desperate measures. */
+ environ[0] = 0;
+ msg_fatal("unsetenv: %m");
+ }
+ tzset();
+ }
+ /* Hack for internal logging forwarding after config change. */
+ if (strchr(name, '[') != 0)
+ logopt &= ~LOG_PID;
openlog(name, LOG_NDELAY | logopt, facility);
if (first_call) {
first_call = 0;
msg_output(msg_syslog_print);
}
+ msg_syslog_enable = 1;
}
-/* msg_syslog_facility - set logging facility by name */
+/* msg_syslog_set_facility - set logging facility by name */
-int msg_syslog_facility(const char *facility_name)
+int msg_syslog_set_facility(const char *facility_name)
{
struct facility_list *fnp;
for (fnp = facility_list; fnp->name; ++fnp) {
if (!strcmp(fnp->name, facility_name)) {
- syslog_facility = fnp->facility;
+ msg_syslog_facility = fnp->facility;
return (1);
}
}
return 0;
}
+/* msg_syslog_disable - disable the msg_syslog client */
+
+void msg_syslog_disable(void)
+{
+ msg_syslog_enable = 0;
+}
+
#ifdef TEST
/*
* External interface.
*/
extern void msg_syslog_init(const char *, int, int);
-extern int msg_syslog_facility(const char *);
+extern int msg_syslog_set_facility(const char *);
+extern void msg_syslog_disable(void);
/* LICENSE
/* .ad
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
+/*
+/* Wietse Venema
+/* Google, Inc.
+/* 111 8th Avenue
+/* New York, NY 10011, USA
/*--*/
#endif
--- /dev/null
+/*++
+/* NAME
+/* unix_dgram_connect 3
+/* SUMMARY
+/* connect to UNIX-domain datagram server
+/* SYNOPSIS
+/* #include <connect.h>
+/*
+/* int unix_dgram_connect(
+/* const char *path,
+/* int block_mode)
+/* DESCRIPTION
+/* unix_dgram_connect() connects to the specified UNIX-domain
+/* datagram server, and returns the resulting file descriptor.
+/*
+/* Arguments:
+/* .IP path
+/* Null-terminated string with connection destination.`
+/* .IP block_mode
+/* Either NON_BLOCKING for a non-blocking socket, or BLOCKING for
+/* blocking mode.
+/* DIAGNOSIICS
+/* Fatal errors: path too large, can't create socket.
+/*
+/* Other errors result in a -1 result value, with errno indicating
+/* why the service is unavailable.
+/* .sp
+/* ENOENT: the named socket does not exist.
+/* .sp
+/* ECONNREFUSED: the named socket is not open.
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* Google, Inc.
+/* 111 8th Avenue
+/* New York, NY 10011, USA
+/*--*/
+
+ /*
+ * System library.
+ */
+#include <sys_defs.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <unistd.h>
+#include <string.h>
+
+ /*
+ * Utility library.
+ */
+#include <msg.h>
+#include <connect.h>
+#include <iostuff.h>
+
+/* unix_dgram_connect - connect to UNIX-domain datagram service */
+
+int unix_dgram_connect(const char *path, int block_mode)
+{
+ const char myname[] = "unix_dgram_connect";
+ struct sockaddr_un sun;
+ ssize_t path_len;
+ int sock;
+
+ /*
+ * Translate address information to internal form.
+ */
+ if ((path_len = strlen(path)) >= sizeof(sun.sun_path))
+ msg_fatal("%s: unix-domain name too long: %s", myname, path);
+ memset((void *) &sun, 0, sizeof(sun));
+ sun.sun_family = AF_UNIX;
+#ifdef HAS_SUN_LEN
+ sun.sun_len = path_len + 1;
+#endif
+ memcpy(sun.sun_path, path, path_len + 1);
+
+ /*
+ * Create a client socket.
+ */
+ if ((sock = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0)
+ msg_fatal("%s: socket: %m", myname);
+ if (connect(sock, (struct sockaddr *) &sun, sizeof(sun)) < 0) {
+ close(sock);
+ return (-1);
+ }
+ non_blocking(sock, block_mode);
+ return (sock);
+}
--- /dev/null
+/*++
+/* NAME
+/* unix_dgram_listen 3
+/* SUMMARY
+/* listen to UNIX-domain datagram server
+/* SYNOPSIS
+/* #include <listen.h>
+/*
+/* int unix_dgram_listen(
+/* const char *path,
+/* int block_mode)
+/* DESCRIPTION
+/* unix_dgram_listen() binds to the specified UNIX-domain
+/* datagram endpoint, and returns the resulting file descriptor.
+/*
+/* Arguments:
+/* .IP path
+/* Null-terminated string with connection destination.
+/* .IP backlog
+/* Either NON_BLOCKING for a non-blocking socket, or BLOCKING for
+/* blocking mode.
+/* DIAGNOSIICS
+/* Fatal errors: path too large, can't create socket.
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* Google, Inc.
+/* 111 8th Avenue
+/* New York, NY 10011, USA
+/*--*/
+
+ /*
+ * System library.
+ */
+#include <sys_defs.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+
+ /*
+ * Utility library.
+ */
+#include <iostuff.h>
+#include <listen.h>
+#include <msg.h>
+
+/* unix_dgram_listen - bind to UNIX-domain datagram endpoint */
+
+int unix_dgram_listen(const char *path, int block_mode)
+{
+ const char myname[] = "unix_dgram_listen";
+#undef sun
+ struct sockaddr_un sun;
+ ssize_t path_len;
+ int sock;
+
+ /*
+ * Translate address information to internal form.
+ */
+ if ((path_len = strlen(path)) >= sizeof(sun.sun_path))
+ msg_fatal("%s: unix-domain name too long: %s", myname, path);
+ memset((void *) &sun, 0, sizeof(sun));
+ sun.sun_family = AF_UNIX;
+#ifdef HAS_SUN_LEN
+ sun.sun_len = path_len + 1;
+#endif
+ memcpy(sun.sun_path, path, path_len + 1);
+
+ /*
+ * Create a 'server' socket.
+ */
+ if ((sock = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0)
+ msg_fatal("%s: socket: %m", myname);
+ if (unlink(path) < 0 && errno != ENOENT)
+ msg_fatal( "remove %s: %m", path);
+ if (bind(sock, (struct sockaddr *) & sun, sizeof(sun)) < 0)
+ msg_fatal( "bind: %s: %m", path);
+#ifdef FCHMOD_UNIX_SOCKETS
+ if (fchmod(sock, 0666) < 0)
+ msg_fatal("fchmod socket %s: %m", path);
+#else
+ if (chmod(path, 0666) < 0)
+ msg_fatal("chmod socket %s: %m", path);
+#endif
+ non_blocking(sock, block_mode);
+ return (sock);
+}
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
+/*
+/* Wietse Venema
+/* Google, Inc.
+/* 111 8th Avenue
+/* New York, NY 10011, USA
/*--*/
/* System library. */
msg_fatal("%s: pipe: %m", myname);
non_blocking(watchdog_pipe[0], NON_BLOCKING);
non_blocking(watchdog_pipe[1], NON_BLOCKING);
+ close_on_exec(watchdog_pipe[0], CLOSE_ON_EXEC); /* Fix 20190126 */
+ close_on_exec(watchdog_pipe[1], CLOSE_ON_EXEC); /* Fix 20190126 */
event_enable_read(watchdog_pipe[0], watchdog_read, (void *) 0);
}
#endif