Compatibility: Postfix now retries delivery when an external
command is killed by a signal, because people expect such
behavior from Sendmail. File: global/pipe_command.c.
+
+20001123-6
+
+ Feature: mailbox locking is now configurable. The configuration
+ parameter name is "mailbox_delivery_lock". Depending on
+ the operating system one can specify one or more of "flock",
+ "fcntl" and "dotlock". The default setting is system
+ dependent. All mailbox file opens are now done by the
+ mbox_open() routine. This affects the operation of the
+ postlock command, and of local delivery to mailbox or
+ /file/name. Files: util/safe_open.c, util/myflock.c,
+ global/deliver_flock.c, global/mbox_conf.c, global/mbox_open.c.
+ local/mailbox.c, local/file.c, postlock/postlock.c. The
+ old sun_mailtool_compatibility parameter is being phased
+ out (it just turns off flock/fcntl locks). It still works,
+ but a warning is logged as a reminder that it goes away.
+Incompatible changes with snapshot-2000XXXX
+===========================================
+
+The "sun_mailtool_compatibility" is going away (a compatibility mode
+that turns of kernel locks on mailbox files). It still works, but
+a warning is logged. Instead, specify the mailbox locking strategy
+via the new "mailbox_delivery_lock" parameter.
+
+Major changes with snapshot-2000XXXX
+====================================
+
+The locking style for delivery to mailbox is now fully configurable
+at runtime. The new configuration parameter is "mailbox_delivery_lock".
+Depending on the operating system type, mailboxes can be locked
+with one or more of "flock", "fcntl" or "dotlock". The default
+setting of "mailbox_delivery_lock" is therefore system dependent.
+The command "postconf -l" shows the available locking styles.
+
Incompatible changes with snapshot-20001121
===========================================
# Restrict the usage of mail delivery to external
# file.
#
+# expand_owner_alias
+# When delivering to an alias that has an owner- com-
+# panion alias, set the envelope sender address to
+# the right-hand side of the owner alias, instead
+# using of the left-hand side address.
+#
# owner_request_special
# Give special treatment to owner-xxx and xxx-request
# addresses.
#
# recipient_delimiter
-# Delimiter that separates recipients from address
+# Delimiter that separates recipients from address
# extensions.
#
# STANDARDS
# postalias(1) alias database management
#
# LICENSE
-# The Secure Mailer license must be distributed with this
+# The Secure Mailer license must be distributed with this
# software.
#
# AUTHOR(S)
Restrict the usage of mail delivery to external
file.
+ <b>expand</b><i>_</i><b>owner</b><i>_</i><b>alias</b>
+ When delivering to an alias that has an <b>owner-</b> com-
+ panion alias, set the envelope sender address to
+ the right-hand side of the owner alias, instead
+ using of the left-hand side address.
+
<b>owner</b><i>_</i><b>request</b><i>_</i><b>special</b>
Give special treatment to <b>owner-</b><i>xxx</i> and <i>xxx</i><b>-request</b>
addresses.
<b>recipient</b><i>_</i><b>delimiter</b>
- Delimiter that separates recipients from address
+ Delimiter that separates recipients from address
extensions.
<b>STANDARDS</b>
<a href="postalias.1.html">postalias(1)</a> alias database management
<b>LICENSE</b>
- The Secure Mailer license must be distributed with this
+ The Secure Mailer license must be distributed with this
software.
<b>AUTHOR(S)</b>
-
-
-
-
-
-
<b>stale</b><i>_</i><b>lock</b><i>_</i><b>time</b>
Limit the time after which a stale lock is removed.
+ <b>mailbox</b><i>__</i><b>delivery</b><i>_</i><b>lock</b>
+ What file locking method(s) to use when delivering
+ to a UNIX-style mailbox. The default setting is
+ system dependent. For a list of available file
+ locking methods, use the <b>postconf</b> <b>-l</b> command.
+
<b>Resource</b> <b>controls</b>
<b>command</b><i>_</i><b>time</b><i>_</i><b>limit</b>
- Limit the amount of time for delivery to external
+ Limit the amount of time for delivery to external
command.
<b>duplicate</b><i>_</i><b>filter</b><i>_</i><b>limit</b>
- Limit the size of the duplicate filter for results
+ Limit the size of the duplicate filter for results
from alias etc. expansion.
<b>line</b><i>_</i><b>length</b><i>_</i><b>limit</b>
- Limit the amount of memory used for processing a
+ Limit the amount of memory used for processing a
partial input line.
<b>local</b><i>_</i><b>destination</b><i>_</i><b>concurrency</b><i>_</i><b>limit</b>
Limit the number of parallel deliveries to the same
- user. The default limit is taken from the
+ user. The default limit is taken from the
<b>default</b><i>_</i><b>destination</b><i>_</i><b>concurrency</b><i>_</i><b>limit</b> parameter.
<b>local</b><i>_</i><b>destination</b><i>_</i><b>recipient</b><i>_</i><b>limit</b>
- Limit the number of recipients per message deliv-
- ery. The default limit is taken from the
+ Limit the number of recipients per message deliv-
+ ery. The default limit is taken from the
<b>default</b><i>_</i><b>destination</b><i>_</i><b>recipient</b><i>_</i><b>limit</b> parameter.
<b>Security</b> <b>controls</b>
<b>allow</b><i>_</i><b>mail</b><i>_</i><b>to</b><i>_</i><b>commands</b>
- Restrict the usage of mail delivery to external
+ Restrict the usage of mail delivery to external
command.
<b>allow</b><i>_</i><b>mail</b><i>_</i><b>to</b><i>_</i><b>files</b>
- Restrict the usage of mail delivery to external
+ Restrict the usage of mail delivery to external
file.
- <b>command</b><i>_</i><b>expansion</b><i>_</i><b>filter</b>
- What characters are allowed to appear in $name
- expansions of mailbox_command. Illegal characters
- are replaced by underscores.
-
-
LOCAL(8) LOCAL(8)
+ <b>command</b><i>_</i><b>expansion</b><i>_</i><b>filter</b>
+ What characters are allowed to appear in $name
+ expansions of mailbox_command. Illegal characters
+ are replaced by underscores.
+
<b>default</b><i>_</i><b>privs</b>
- Default rights for delivery to external file or
+ Default rights for delivery to external file or
command.
<b>forward</b><i>_</i><b>expansion</b><i>_</i><b>filter</b>
- What characters are allowed to appear in $name
- expansions of forward_path. Illegal characters are
+ What characters are allowed to appear in $name
+ expansions of forward_path. Illegal characters are
replaced by underscores.
<b>HISTORY</b>
- The <b>Delivered-To:</b> header appears in the <b>qmail</b> system by
+ The <b>Delivered-To:</b> header appears in the <b>qmail</b> system by
Daniel Bernstein.
- The <i>maildir</i> structure appears in the <b>qmail</b> system by
+ The <i>maildir</i> structure appears in the <b>qmail</b> system by
Daniel Bernstein.
<b>SEE</b> <b>ALSO</b>
<a href="qmgr.8.html">qmgr(8)</a> queue manager
<b>LICENSE</b>
- The Secure Mailer license must be distributed with this
+ The Secure Mailer license must be distributed with this
software.
<b>AUTHOR(S)</b>
-
-
-
-
-
postconf - Postfix configuration utility
<b>SYNOPSIS</b>
- <b>postconf</b> [<b>-dhmnv</b>] [<b>-c</b> <i>config_dir</i>] [<i>parameter</i> <i>...</i>]
+ <b>postconf</b> [<b>-dhmlnv</b>] [<b>-c</b> <i>config_dir</i>] [<i>parameter</i> <i>...</i>]
<b>postconf</b> [<b>-ev</b>] [<b>-c</b> <i>config_dir</i>] [<i>parameter=value</i> <i>...</i>]
<b>-m</b> List the names of all supported lookup table types.
+ <b>-l</b> List the names of all supported mailbox locking
+ methods.
+
<b>-n</b> Print non-default parameter settings only.
<b>-v</b> Enable verbose logging for debugging purposes. Mul-
- tiple <b>-v</b> options make the software increasingly
+ tiple <b>-v</b> options make the software increasingly
verbose.
<b>DIAGNOSTICS</b>
Problems are reported to the standard error stream.
<b>LICENSE</b>
- The Secure Mailer license must be distributed with this
+ The Secure Mailer license must be distributed with this
software.
<b>AUTHOR(S)</b>
Wietse Venema
IBM T.J. Watson Research
+
+
+
+ 1
+
+
+
+
+
+POSTCONF(1) POSTCONF(1)
+
+
P.O. Box 704
Yorktown Heights, NY 10598, USA
- 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 2
</pre> </body> </html>
postlock - lock mail folder and execute command
<b>SYNOPSIS</b>
- <b>postlock</b> [<b>-c</b> <i>config_dir</i><b>]</b> <b>[-v</b>] <i>file</i> <i>command...</i>
+ <b>postlock</b> [<b>-c</b> <i>config_dir</i><b>]</b> <b>[-l</b> <i>lock_style</i><b>]</b> <b>[-v</b>] <i>file</i> <i>com-</i>
+ <i>mand...</i>
<b>DESCRIPTION</b>
- The <b>postlock</b> command locks <i>file</i> for exclusive access, and
- executes <i>command</i>. The locking method is compatible with
+ The <b>postlock</b> command locks <i>file</i> for exclusive access, and
+ executes <i>command</i>. The locking method is compatible with
the Postfix UNIX-style local delivery agent.
Options:
<b>-c</b> <i>config_dir</i>
- Read the <b>main.cf</b> configuration file in the named
+ Read the <b>main.cf</b> configuration file in the named
directory instead of the default configuration
directory.
+ <b>-l</b> <i>lock_style</i>
+ Override the locking method specified via the <b>mail-</b>
+ <b>box</b><i>_</i><b>delivery</b><i>_</i><b>lock</b> configuration parameter (see
+ below).
+
<b>-v</b> Enable verbose logging for debugging purposes. Mul-
- tiple <b>-v</b> options make the software increasingly
+ tiple <b>-v</b> options make the software increasingly
verbose.
Arguments:
- <i>file</i> A mailbox file. The user should have read/write
+ <i>file</i> A mailbox file. The user should have read/write
permission.
<i>command...</i>
- The command to execute while <i>file</i> is locked for
- exclusive access. The command is executed
- directly, i.e. without interpretation by a shell
+ The command to execute while <i>file</i> is locked for
+ exclusive access. The command is executed
+ directly, i.e. without interpretation by a shell
command interpreter.
<b>DIAGNOSTICS</b>
- The result status is 75 (EX_TEMPFAIL) when the file is
- locked by another process, 255 (on some systems: -1) when
- <b>postlock</b> could not perform the requested operation. Oth-
- erwise, the exit status is the exit status from the com-
- mand.
+ The result status is 75 (EX_TEMPFAIL) when <b>postlock</b> could
+ not perform the requested operation. Otherwise, the exit
+ status is the exit status from the command.
<b>BUGS</b>
- With remote file systems, the ability to acquire a lock
- does not necessarily eliminate access conflicts. Avoid
+ With remote file systems, the ability to acquire a lock
+ does not necessarily eliminate access conflicts. Avoid
file access by processes running on different machines.
<b>ENVIRONMENT</b>
<b>MAIL</b><i>_</i><b>CONFIG</b>
Directory with Postfix configuration files.
- <b>MAIL</b><i>_</i><b>VERBOSE</b>
- Enable verbose logging for debugging purposes.
-<b>CONFIGURATION</b> <b>PARAMETERS</b>
- The following <b>main.cf</b> parameters are especially relevant
POSTLOCK(1) POSTLOCK(1)
- to this program. See the Postfix <b>main.cf</b> file for syntax
+ <b>MAIL</b><i>_</i><b>VERBOSE</b>
+ Enable verbose logging for debugging purposes.
+
+<b>CONFIGURATION</b> <b>PARAMETERS</b>
+ The following <b>main.cf</b> parameters are especially relevant
+ to this program. See the Postfix <b>main.cf</b> file for syntax
details and for default values.
<b>Locking</b> <b>controls</b>
<b>deliver</b><i>_</i><b>lock</b><i>_</i><b>attempts</b>
- Limit the number of attempts to acquire an exclu-
+ Limit the number of attempts to acquire an exclu-
sive lock.
<b>deliver</b><i>_</i><b>lock</b><i>_</i><b>delay</b>
- Time in seconds between successive attempts to
+ Time in seconds between successive attempts to
acquire an exclusive lock.
<b>stale</b><i>_</i><b>lock</b><i>_</i><b>time</b>
Limit the time after which a stale lock is removed.
+ <b>mailbox</b><i>_</i><b>delivery</b><i>_</i><b>lock</b>
+ What file locking method(s) to use when delivering
+ to a UNIX-style mailbox. The default setting is
+ system dependent. For a list of available file
+ locking methods, use the <b>postconf</b> <b>-l</b> command.
+
<b>Resource</b> <b>controls</b>
<b>fork</b><i>_</i><b>attempts</b>
Number of attempts to <b>fork</b>() a process before giv-
-
-
-
-
-
-
-
-
-
-
-
.na
.nf
.fi
-\fBpostconf\fR [\fB-dhmnv\fR] [\fB-c \fIconfig_dir\fR]
+\fBpostconf\fR [\fB-dhmlnv\fR] [\fB-c \fIconfig_dir\fR]
[\fIparameter ...\fR]
\fBpostconf\fR [\fB-ev\fR] [\fB-c \fIconfig_dir\fR]
that normally precedes the value.
.IP \fB-m\fR
List the names of all supported lookup table types.
+.IP \fB-l\fR
+List the names of all supported mailbox locking methods.
.IP \fB-n\fR
Print non-default parameter settings only.
.IP \fB-v\fR
.na
.nf
.fi
-\fBpostlock\fR [\fB-c \fIconfig_dir\fB] [\fB-v\fR]
-\fIfile command...\fR
+\fBpostlock\fR [\fB-c \fIconfig_dir\fB] [\fB-l \fIlock_style\fB]
+[\fB-v\fR] \fIfile command...\fR
.SH DESCRIPTION
.ad
.fi
.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-l \fIlock_style\fR"
+Override the locking method specified via the
+\fBmailbox_delivery_lock\fR configuration parameter (see below).
.IP \fB-v\fR
Enable verbose logging for debugging purposes. Multiple \fB-v\fR
options make the software increasingly verbose.
.SH DIAGNOSTICS
.ad
.fi
-The result status is 75 (EX_TEMPFAIL) when the file is locked by
-another process, 255 (on some systems: -1) when \fBpostlock\fR
+The result status is 75 (EX_TEMPFAIL) when \fBpostlock\fR
could not perform the requested operation. Otherwise, the
exit status is the exit status from the command.
.SH BUGS
an exclusive lock.
.IP \fBstale_lock_time\fR
Limit the time after which a stale lock is removed.
+.IP \fBmailbox_delivery_lock\fR
+What file locking method(s) to use when delivering to a UNIX-style
+mailbox.
+The default setting is system dependent. For a list of available
+file locking methods, use the \fBpostconf -l\fR command.
.SH "Resource controls"
.ad
.fi
Restrict the usage of mail delivery to external command.
.IP \fBallow_mail_to_files\fR
Restrict the usage of mail delivery to external file.
+.IP \fBexpand_owner_alias\fR
+When delivering to an alias that has an \fBowner-\fR companion alias,
+set the envelope sender address to the right-hand side of the
+owner alias, instead using of the left-hand side address.
.IP \fBowner_request_special\fR
Give special treatment to \fBowner-\fIxxx\fR and \fIxxx\fB-request\fR
addresses.
an exclusive lock.
.IP \fBstale_lock_time\fR
Limit the time after which a stale lock is removed.
+.IP \fBmailbox__delivery_lock\fR
+What file locking method(s) to use when delivering to a UNIX-style
+mailbox.
+The default setting is system dependent. For a list of available
+file locking methods, use the \fBpostconf -l\fR command.
.SH "Resource controls"
.ad
.fi
# Restrict the usage of mail delivery to external command.
# .IP \fBallow_mail_to_files\fR
# Restrict the usage of mail delivery to external file.
+# .IP \fBexpand_owner_alias\fR
+# When delivering to an alias that has an \fBowner-\fR companion alias,
+# set the envelope sender address to the right-hand side of the
+# owner alias, instead using of the left-hand side address.
# .IP \fBowner_request_special\fR
# Give special treatment to \fBowner-\fIxxx\fR and \fIxxx\fB-request\fR
# addresses.
bounce_append_service.o: ../../include/mail_queue.h
bounce_append_service.o: ../../include/quote_822_local.h
bounce_append_service.o: ../../include/deliver_flock.h
+bounce_append_service.o: ../../include/myflock.h
bounce_append_service.o: bounce_service.h
bounce_append_service.o: ../../include/bounce_log.h
bounce_cleanup.o: bounce_cleanup.c
* Lock out other processes to avoid truncating someone else's data in
* case of trouble.
*/
- if (deliver_flock(vstream_fileno(log), (VSTRING *) 0) < 0)
+ if (deliver_flock(vstream_fileno(log), INTERNAL_LOCK, (VSTRING *) 0) < 0)
msg_fatal("lock file %s %s: %m", service, queue_id);
/*
int bounce_status = 1;
int postmaster_status = 1;
VSTREAM *bounce;
- int notify_mask = name_mask(mail_error_masks, var_notify_classes);
+ int notify_mask = name_mask(VAR_NOTIFY_CLASSES, mail_error_masks,
+ var_notify_classes);
char *postmaster;
/*
*/
else {
if ((bounce = post_mail_fopen_nowait(NULL_SENDER, recipient,
- NULL_CLEANUP_FLAGS,
- "BOUNCE")) != 0) {
+ NULL_CLEANUP_FLAGS,
+ "BOUNCE")) != 0) {
/*
* Send the bounce message header, some boilerplate text that
* concurrent access. If the lock takes too long, the Postfix watchdog
* will eventually take care of the problem, but it will take a while.
*/
- if (myflock(vstream_fileno(log), MYFLOCK_EXCLUSIVE) < 0)
+ if (myflock(vstream_fileno(log), INTERNAL_LOCK, MYFLOCK_OP_EXCLUSIVE) < 0)
msg_fatal("%s: lock fast flush log for site %s: %m", myname, site);
/*
/*
* Clean up.
*/
- if (myflock(vstream_fileno(log), MYFLOCK_NONE) < 0)
+ if (myflock(vstream_fileno(log), INTERNAL_LOCK, MYFLOCK_OP_NONE) < 0)
msg_fatal("%s: unlock fast flush log for site %s: %m",
myname, site);
if (vstream_fclose(log) != 0)
* significant amount of time. If things really get stuck the Postfix
* watchdog will take care of it.
*/
- if (myflock(vstream_fileno(log), MYFLOCK_EXCLUSIVE) < 0)
+ if (myflock(vstream_fileno(log), INTERNAL_LOCK, MYFLOCK_OP_EXCLUSIVE) < 0)
msg_fatal("%s: lock fast flush log for site %s: %m", myname, site);
/*
/*
* Request delivery and clean up.
*/
- if (myflock(vstream_fileno(log), MYFLOCK_NONE) < 0)
+ if (myflock(vstream_fileno(log), INTERNAL_LOCK, MYFLOCK_OP_NONE) < 0)
msg_fatal("%s: unlock fast flush log for site %s: %m",
myname, site);
if (vstream_fclose(log) != 0)
sent.c smtp_stream.c split_addr.c string_list.c sys_exits.c \
timed_ipc.c tok822_find.c tok822_node.c tok822_parse.c \
tok822_resolve.c tok822_rewrite.c tok822_tree.c xtext.c bounce_log.c \
- flush_clnt.c mail_conf_time.c
+ flush_clnt.c mail_conf_time.c mbox_conf.c mbox_open.c
OBJS = been_here.o bounce.o canon_addr.o cleanup_strerror.o clnt_stream.o \
debug_peer.o debug_process.o defer.o deliver_completed.o \
deliver_flock.o deliver_pass.o deliver_request.o domain_list.o \
sent.o smtp_stream.o split_addr.o string_list.o sys_exits.o \
timed_ipc.o tok822_find.o tok822_node.o tok822_parse.o \
tok822_resolve.o tok822_rewrite.o tok822_tree.o xtext.o bounce_log.o \
- flush_clnt.o mail_conf_time.o
+ flush_clnt.o mail_conf_time.o mbox_conf.o mbox_open.o
HDRS = been_here.h bounce.h canon_addr.h cleanup_user.h clnt_stream.h \
config.h debug_peer.h debug_process.h defer.h deliver_completed.h \
deliver_flock.h deliver_pass.h deliver_request.h domain_list.h \
quote_821_local.h quote_822_local.h rec_streamlf.h rec_type.h \
recipient_list.h record.h resolve_clnt.h resolve_local.h \
rewrite_clnt.h sent.h smtp_stream.h split_addr.h string_list.h \
- sys_exits.h timed_ipc.h tok822.h xtext.h bounce_log.h flush_clnt.h
+ sys_exits.h timed_ipc.h tok822.h xtext.h bounce_log.h flush_clnt.h \
+ mbox_conf.h mbox_open.h
TESTSRC = rec2stream.c stream2rec.c recdump.c
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
-Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
ext_prop.o: ext_prop.c
ext_prop.o: ../../include/sys_defs.h
ext_prop.o: ../../include/name_mask.h
+ext_prop.o: mail_params.h
ext_prop.o: ext_prop.h
file_id.o: file_id.c
file_id.o: ../../include/sys_defs.h
mark_corrupt.o: mail_queue.h
mark_corrupt.o: ../../include/vstring.h
mark_corrupt.o: mark_corrupt.h
+mbox_conf.o: mbox_conf.c
+mbox_conf.o: ../../include/sys_defs.h
+mbox_conf.o: ../../include/name_mask.h
+mbox_conf.o: ../../include/argv.h
+mbox_conf.o: mail_params.h
+mbox_conf.o: mbox_conf.h
+mbox_open.o: mbox_open.c
+mbox_open.o: ../../include/sys_defs.h
+mbox_open.o: ../../include/msg.h
+mbox_open.o: ../../include/vstream.h
+mbox_open.o: ../../include/vbuf.h
+mbox_open.o: ../../include/vstring.h
+mbox_open.o: ../../include/safe_open.h
+mbox_open.o: dot_lockfile.h
+mbox_open.o: deliver_flock.h
+mbox_open.o: ../../include/myflock.h
+mbox_open.o: mbox_conf.h
+mbox_open.o: ../../include/argv.h
+mbox_open.o: mbox_open.h
mkmap_db.o: mkmap_db.c
mkmap_db.o: ../../include/sys_defs.h
mkmap_db.o: ../../include/msg.h
/* SYNOPSIS
/* #include <deliver_flock.h>
/*
-/* int deliver_flock(fd, why)
+/* int deliver_flock(fd, lock_style, why)
/* int fd;
+/* int lock_style;
/* VSTRING *why;
/* DESCRIPTION
/* deliver_flock() sets one exclusive kernel lock on an open file
/* Arguments:
/* .IP fd
/* A file descriptor that is associated with an open file.
+/* .IP lock_style
+/* A locking style defined in myflock(3).
/* .IP why
/* A null pointer, or storage for diagnostics.
/* DIAGNOSTICS
/* deliver_flock - lock open file for mail delivery*/
-int deliver_flock(int fd, VSTRING *why)
+int deliver_flock(int fd, int lock_style, VSTRING *why)
{
int i;
- if (var_mailtool_compat)
- return (0);
-
for (i = 0; /* void */ ; i++) {
if (i >= var_flock_tries)
break;
if (i > 0)
sleep(var_flock_delay);
- if (myflock(fd, MYFLOCK_EXCLUSIVE | MYFLOCK_NOWAIT) == 0)
+ if (myflock(fd, lock_style, MYFLOCK_OP_EXCLUSIVE | MYFLOCK_OP_NOWAIT) == 0)
return (0);
}
if (why)
- vstring_sprintf(why, "unable to lock exclusively: %m");
+ vstring_sprintf(why, "unable to lock for exclusive access: %m");
return (-1);
}
/*
* Utility library.
*/
+#include <myflock.h>
#include <vstring.h>
/*
* External interface.
*/
-extern int deliver_flock(int, VSTRING *);
+extern int deliver_flock(int, int, VSTRING *);
/* LICENSE
/* .ad
* raising a fatal error which forces the mail system to back off, and
* retry later.
*/
-#define DELIVER_LOCK_MODE (MYFLOCK_SHARED | MYFLOCK_NOWAIT)
+#define DELIVER_LOCK_MODE (MYFLOCK_OP_SHARED | MYFLOCK_OP_NOWAIT)
request->fp =
mail_queue_open(request->queue_name, request->queue_id, O_RDWR, 0);
msg_fatal("open %s %s: %m", request->queue_name, request->queue_id);
if (msg_verbose)
msg_info("%s: file %s", myname, VSTREAM_PATH(request->fp));
- if (myflock(vstream_fileno(request->fp), DELIVER_LOCK_MODE) < 0)
+ if (myflock(vstream_fileno(request->fp), INTERNAL_LOCK, DELIVER_LOCK_MODE) < 0)
msg_fatal("shared lock %s: %m", VSTREAM_PATH(request->fp));
close_on_exec(vstream_fileno(request->fp), CLOSE_ON_EXEC);
/* means no lock file could be created.
/*
/* dot_unlockfile() attempts to remove the lock file created by
-/* dot_lockfile().
+/* dot_lockfile(). The operation always succeeds, and therefore
+/* it preserves the errno value.
/*
/* Arguments:
/* .IP path
/* .IP why
/* A null pointer, or storage for the reason why a lock file could
/* not be created.
+/* DIAGNOSTICS
+/* dot_lockfile() returns 0 upon success. In case of failure, the
+/* result is -1, and the errno variable is set appropriately:
+/* EEXIST when a "fresh" lock file already exists; other values as
+/* appropriate.
/* CONFIGURATION PARAMETERS
/* deliver_lock_attempts, how many times to try to create a lock
/* deliver_lock_delay, how long to wait between attempts
lock_file = concatenate(path, ".lock", (char *) 0);
- for (count = 0; /* void */ ; count++) {
- if (count >= var_flock_tries)
- break;
- if (count > 0)
- sleep(var_flock_delay);
+ for (count = 1; /* void */ ; count++) {
/*
* Attempt to create the lock. This code relies on O_EXCL | O_CREAT
status = 0;
break;
}
+ if (count >= var_flock_tries)
+ break;
/*
* We can deal only with "file exists" errors. Any other error means
if (unlink(lock_file) < 0)
if (errno != ENOENT)
break;
- errno = EEXIST;
+
+ sleep(var_flock_delay);
}
if (status && why)
vstring_sprintf(why, "unable to create lock file %s: %m", lock_file);
void dot_unlockfile(const char *path)
{
char *lock_file;
+ int saved_errno = errno;
lock_file = concatenate(path, ".lock", (char *) 0);
(void) unlink(lock_file);
myfree(lock_file);
+ errno = saved_errno;
}
#ifdef TEST
/* Global library. */
+#include <mail_params.h>
#include <ext_prop.h>
/* ext_prop_mask - compute extension propagation mask */
0,
};
- return (name_mask(table, pattern));
+ return (name_mask(VAR_PROP_EXTENSION, table, pattern));
}
extern char *get_mail_conf_str(const char *, const char *, int, int);
extern int get_mail_conf_int(const char *, int, int, int);
extern int get_mail_conf_bool(const char *, int);
+extern int get_mail_conf_lock(const char *, int);
extern int get_mail_conf_time(const char *, const char *, int, int, int);
extern char *get_mail_conf_raw(const char *, const char *, int, int);
extern char *get_mail_conf_str_fn(const char *, const char *(*) (void), int, int);
extern int get_mail_conf_int_fn(const char *, int (*) (void), int, int);
extern int get_mail_conf_bool_fn(const char *, int (*) (void));
+extern int get_mail_conf_lock_fn(const char *, int (*) (void));
extern int get_mail_conf_time_fn(const char *, const char *(*) (void), int, int, int);
extern char *get_mail_conf_raw_fn(const char *, const char *(*) (void), int, int);
extern void set_mail_conf_str(const char *, const char *);
extern void set_mail_conf_int(const char *, int);
extern void set_mail_conf_bool(const char *, int);
+extern void set_mail_conf_lock(const char *, int);
extern void set_mail_conf_time(const char *, const char *);
/*
int *target; /* pointer to global variable */
} CONFIG_BOOL_TABLE;
+typedef struct {
+ const char *name; /* config variable name */
+ int defval; /* default value */
+ int *target; /* pointer to global variable */
+} CONFIG_LOCK_TABLE;
+
typedef struct {
const char *name; /* config variable name */
const char *defval; /* default value */
extern void get_mail_conf_str_table(CONFIG_STR_TABLE *);
extern void get_mail_conf_int_table(CONFIG_INT_TABLE *);
extern void get_mail_conf_bool_table(CONFIG_BOOL_TABLE *);
+extern void get_mail_conf_lock_table(CONFIG_LOCK_TABLE *);
extern void get_mail_conf_time_table(CONFIG_TIME_TABLE *);
extern void get_mail_conf_raw_table(CONFIG_STR_TABLE *);
int *target; /* pointer to global variable */
} CONFIG_BOOL_FN_TABLE;
+typedef struct {
+ const char *name; /* config variable name */
+ int (*defval) (void); /* default value provider */
+ int *target; /* pointer to global variable */
+} CONFIG_LOCK_FN_TABLE;
+
typedef struct {
const char *name; /* config variable name */
const char *(*defval) (void); /* default value provider */
extern void get_mail_conf_str_fn_table(CONFIG_STR_FN_TABLE *);
extern void get_mail_conf_int_fn_table(CONFIG_INT_FN_TABLE *);
extern void get_mail_conf_bool_fn_table(CONFIG_BOOL_FN_TABLE *);
+extern void get_mail_conf_lock_fn_table(CONFIG_LOCK_FN_TABLE *);
extern void get_mail_conf_time_fn_table(CONFIG_TIME_FN_TABLE *);
extern void get_mail_conf_raw_fn_table(CONFIG_STR_FN_TABLE *);
/* int var_flock_tries;
/* int var_flock_delay;
/* int var_flock_stale;
-/* int var_mailtool_compat;
/* int var_disable_dns;
/* int var_soft_bounce;
/* time_t var_starttime;
int var_flock_tries;
int var_flock_delay;
int var_flock_stale;
-int var_mailtool_compat;
int var_disable_dns;
int var_soft_bounce;
time_t var_starttime;
VAR_DISABLE_DNS, DEF_DISABLE_DNS, &var_disable_dns,
VAR_SOFT_BOUNCE, DEF_SOFT_BOUNCE, &var_soft_bounce,
VAR_OWNREQ_SPECIAL, DEF_OWNREQ_SPECIAL, &var_ownreq_special,
- VAR_MAILTOOL_COMPAT, DEF_MAILTOOL_COMPAT, &var_mailtool_compat,
0,
};
#define DEF_FORWARD_PATH "$home/.forward${recipient_delimiter}${extension},$home/.forward"
extern char *var_forward_path;
+ /*
+ * Mailbox locking. DEF_MAILBOX_LOCK is defined in sys_defs.h.
+ */
+#define VAR_MAILBOX_LOCK "mailbox_delivery_lock"
+extern char *var_mailbox_lock;
+
+ /*
+ * Miscellaneous.
+ */
#define VAR_PROP_EXTENSION "propagate_unmatched_extensions"
#define DEF_PROP_EXTENSION "canonical, virtual"
extern char *var_prop_extension;
* Version of this program.
*/
#define VAR_MAIL_VERSION "mail_version"
-#define DEF_MAIL_VERSION "Snapshot-20001121"
+#define DEF_MAIL_VERSION "Snapshot-20001126"
extern char *var_mail_version;
/* LICENSE
--- /dev/null
+/*++
+/* NAME
+/* mbox_conf 3
+/* SUMMARY
+/* mailbox lock configuration
+/* SYNOPSIS
+/* #include <mbox_conf.h>
+/*
+/* int mbox_lock_mask(string)
+/* const char *string;
+/*
+/* ARGV *mbox_lock_names()
+/* DESCRIPTION
+/* The functions in this module translate between external
+/* mailbox locking method names and internal forms.
+/*
+/* mbox_lock_mask() translates a string with locking method names
+/* into a bit mask. Names are separated by comma or whitespace.
+/* The following gives the method names and corresponding bit
+/* mask value:
+/* .IP "flock (MBOX_FLOCK_LOCK)"
+/* Use flock() style lock after opening the file. This is the mailbox
+/* locking method traditionally used on BSD-ish systems (including
+/* Ultrix and SunOS).
+/* .IP "fcntl (MBOX_FCNTL_LOCK)"
+/* Use fcntl() style lock after opening the file. This is the mailbox
+/* locking method on System-V-ish systems (Solaris, AIX, IRIX, HP-UX).
+/* .IP "dotlock (MBOX_DOT_LOCK)"
+/* Create a lock file with the name \fIfilename\fB.lock\fR. This
+/* method pre-dates kernel locks.
+/* .PP
+/* mbox_lock_names() returns an array with the names of available
+/* mailbox locking methods. The result should be given to argv_free().
+/* DIAGNOSTICS
+/* Fatal errors: undefined locking method name.
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* IBM T.J. Watson Research
+/* P.O. Box 704
+/* Yorktown Heights, NY 10598, USA
+/*--*/
+
+/* System library. */
+
+#include <sys_defs.h>
+
+/* Utility library. */
+
+#include <name_mask.h>
+#include <argv.h>
+
+/* Global library. */
+
+#include <mail_params.h>
+#include <mbox_conf.h>
+
+ /*
+ * The table with available mailbox locking methods. Some systems have
+ * flock() locks; all POSIX-compatible systems should have fcntl() locks.
+ * Even though some systems do not use dotlock files, it can be necessary
+ * when accessing mailbox files over NFS.
+ */
+static NAME_MASK mbox_mask[] = {
+#ifdef HAS_FLOCK_LOCK
+ "flock", MBOX_FLOCK_LOCK,
+#endif
+#ifdef HAS_FCNTL_LOCK
+ "fcntl", MBOX_FCNTL_LOCK,
+#endif
+ "dotlock", MBOX_DOT_LOCK,
+ 0,
+};
+
+/* mbox_lock_mask - translate mailbox lock names to bit mask */
+
+int mbox_lock_mask(const char *string)
+{
+ return (name_mask(VAR_MAILBOX_LOCK, mbox_mask, string));
+}
+
+/* mbox_lock_names - return available mailbox lock method names */
+
+ARGV *mbox_lock_names(void)
+{
+ NAME_MASK *np;
+ ARGV *argv;
+
+ argv = argv_alloc(2);
+ for (np = mbox_mask; np->name != 0; np++)
+ argv_add(argv, np->name, ARGV_END);
+ argv_terminate(argv);
+ return (argv);
+}
--- /dev/null
+#ifndef _MBOX_CONF_H_INCLUDED_
+#define _MBOX_CONF_H_INCLUDED_
+
+/*++
+/* NAME
+/* mbox_conf 3h
+/* SUMMARY
+/* mailbox lock configuration
+/* SYNOPSIS
+/* #include <mbox_conf.h>
+/* DESCRIPTION
+/* .nf
+
+ /*
+ * Utility library.
+ */
+#include <argv.h>
+
+ /*
+ * External interface.
+ */
+#define MBOX_FLOCK_LOCK (1<<0)
+#define MBOX_FCNTL_LOCK (1<<1)
+#define MBOX_DOT_LOCK (1<<2)
+#define MBOX_DOT_LOCK_MAY_FAIL (1<<3) /* XXX internal only */
+
+extern int mbox_lock_mask(const char *);
+extern ARGV *mbox_lock_names(void);
+
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* IBM T.J. Watson Research
+/* P.O. Box 704
+/* Yorktown Heights, NY 10598, USA
+/*--*/
+
+#endif
--- /dev/null
+/*++
+/* NAME
+/* mbox_open 3
+/* SUMMARY
+/* mailbox access
+/* SYNOPSIS
+/* #include <mbox_open.h>
+/*
+/* int mbox_open(path, flags, mode, st, user, group, lock_style, why)
+/* const char *path;
+/* int flags;
+/* int mode;
+/* struct stat *st;
+/* uid_t user;
+/* gid_t group;
+/* int lock_style;
+/* VSTRING *why;
+/*
+/* void mbox_release(path, lock_style)
+/* const char *path;
+/* int lock_style;
+/* DESCRIPTION
+/* This module manages access to UNIX mailbox-style files.
+/*
+/* mbox_open() acquires exclusive access to the named file.
+/* The \fBpath, flags, mode, st, user, group, why\fR arguments
+/* are passed to the \fBsafe_open\fR() routine. Attempts to change
+/* file ownership will succeed only if the process runs with
+/* adequate effective privileges.
+/* The \fBlock_style\fR argument specifies a lock style from
+/* mbox_lock_mask(). Kernel locks are applied to regular files only.
+/*
+/* mbox_release() releases the named mailbox. It is up to the
+/* application to close the file.
+/* DIAGNOSTICS
+/* mbox_open() returns a null pointer in case of problems, and
+/* sets errno to EAGAIN if someone else has exclusive access.
+/* Other errors are likely to have a more permanent nature.
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* IBM T.J. Watson Research
+/* P.O. Box 704
+/* Yorktown Heights, NY 10598, USA
+/*--*/
+
+/* System library. */
+
+#include <sys_defs.h>
+#include <sys/stat.h>
+#include <errno.h>
+
+/* Utility library. */
+
+#include <msg.h>
+#include <vstream.h>
+#include <vstring.h>
+#include <safe_open.h>
+
+/* Global library. */
+
+#include <dot_lockfile.h>
+#include <deliver_flock.h>
+#include <mbox_conf.h>
+#include <mbox_open.h>
+
+/* mbox_open - open mailbox-style file for exclusive access */
+
+VSTREAM *mbox_open(const char *path, int flags, int mode, struct stat * st,
+ uid_t chown_uid, gid_t chown_gid,
+ int lock_style, VSTRING *why)
+{
+ struct stat local_statbuf;
+ VSTREAM *fp;
+
+ /*
+ * Create dotlock file. This locking method does not work well over NFS:
+ * creating files atomically is a problem, and a successful operation can
+ * fail with EEXIST.
+ */
+ if ((lock_style & MBOX_DOT_LOCK) && dot_lockfile(path, why) < 0) {
+ if (errno == EEXIST) {
+ errno = EAGAIN;
+ return (0);
+ }
+
+ /*
+ * If file.lock can't be created, ignore the problem. We need this so
+ * that Postfix can deliver as unprivileged user to /dev/null
+ * aliases.
+ */
+ if ((lock_style & MBOX_DOT_LOCK_MAY_FAIL) == 0)
+ return (0);
+ }
+
+ /*
+ * Open or create the target file.
+ */
+ if (st == 0)
+ st = &local_statbuf;
+ if ((fp = safe_open(path, flags, mode, st, chown_uid, chown_gid, why)) == 0) {
+ if (lock_style & MBOX_DOT_LOCK)
+ dot_unlockfile(path);
+ return (0);
+ }
+
+ /*
+ * Acquire kernel locks, but only if the target is a regular file, in
+ * case we're running on some overly pedantic system. flock() locks do
+ * not work over NFS; fcntl() locks are supposed to work over NFS, but in
+ * the real world, NFS lock daemons often have serious problems.
+ */
+#define LOCK_FAIL(mbox_lock, myflock_style) ((lock_style & (mbox_lock)) != 0 \
+ && deliver_flock(vstream_fileno(fp), (myflock_style), why) < 0)
+
+ if (S_ISREG(st->st_mode)
+ && (LOCK_FAIL(MBOX_FLOCK_LOCK, MYFLOCK_STYLE_FLOCK)
+ || LOCK_FAIL(MBOX_FCNTL_LOCK, MYFLOCK_STYLE_FCNTL))) {
+ if (myflock_locked(vstream_fileno(fp)))
+ errno = EAGAIN;
+ if (lock_style & MBOX_DOT_LOCK)
+ dot_unlockfile(path);
+ return (0);
+ }
+ return (fp);
+}
+
+/* mbox_release - release mailbox exclusive access */
+
+void mbox_release(const char *path, int lock_style)
+{
+ if (lock_style & MBOX_DOT_LOCK)
+ dot_unlockfile(path);
+}
--- /dev/null
+#ifndef _MBOX_OPEN_H_INCLUDED_
+#define _MBOX_OPEN_H_INCLUDED_
+
+/*++
+/* NAME
+/* mbox_open 3h
+/* SUMMARY
+/* mailbox access
+/* SYNOPSIS
+/* #include <mbox_open.h>
+/* DESCRIPTION
+/* .nf
+
+ /*
+ * Utility library.
+ */
+#include <vstream.h>
+#include <vstring.h>
+#include <safe_open.h>
+
+ /*
+ * External interface.
+ */
+extern VSTREAM *mbox_open(const char *, int, int, struct stat *, uid_t, gid_t, int, VSTRING *);
+extern void mbox_release(const char *, int);
+
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* IBM T.J. Watson Research
+/* P.O. Box 704
+/* Yorktown Heights, NY 10598, USA
+/*--*/
+
+#endif
* Get an exclusive lock - we're going to change the database so we can't
* have any spectators.
*/
- if (myflock(mkmap->lock_fd, MYFLOCK_EXCLUSIVE) < 0)
+ if (myflock(mkmap->lock_fd, INTERNAL_LOCK, MYFLOCK_OP_EXCLUSIVE) < 0)
msg_fatal("lock %s: %m", mkmap->lock_file);
/*
* session or with delivering mail.
*/
if (state->history != 0
- && (state->error_mask & name_mask(mail_error_masks, var_notify_classes)))
+ && (state->error_mask & name_mask(VAR_NOTIFY_CLASSES, mail_error_masks,
+ var_notify_classes)))
lmtp_chat_notify(state);
/*
/* lmtp_service - perform service for client */
-static void lmtp_service(VSTREAM *client_stream, char *unused_service, char **argv)
+static void lmtp_service(VSTREAM * client_stream, char *unused_service, char **argv)
{
DELIVER_REQUEST *request;
int status;
alias.o: ../../include/resolve_clnt.h
alias.o: ../../include/deliver_request.h
alias.o: ../../include/recipient_list.h
+alias.o: ../../include/mbox_conf.h
biff_notify.o: biff_notify.c
biff_notify.o: ../../include/sys_defs.h
biff_notify.o: ../../include/msg.h
command.o: ../../include/resolve_clnt.h
command.o: ../../include/deliver_request.h
command.o: ../../include/recipient_list.h
+command.o: ../../include/mbox_conf.h
deliver_attr.o: deliver_attr.c
deliver_attr.o: ../../include/sys_defs.h
deliver_attr.o: ../../include/msg.h
deliver_attr.o: ../../include/resolve_clnt.h
deliver_attr.o: ../../include/deliver_request.h
deliver_attr.o: ../../include/recipient_list.h
+deliver_attr.o: ../../include/mbox_conf.h
+deliver_attr.o: ../../include/argv.h
delivered.o: delivered.c
delivered.o: ../../include/sys_defs.h
delivered.o: ../../include/msg.h
delivered.o: ../../include/resolve_clnt.h
delivered.o: ../../include/deliver_request.h
delivered.o: ../../include/recipient_list.h
+delivered.o: ../../include/mbox_conf.h
+delivered.o: ../../include/argv.h
dotforward.o: dotforward.c
dotforward.o: ../../include/sys_defs.h
dotforward.o: ../../include/msg.h
dotforward.o: ../../include/resolve_clnt.h
dotforward.o: ../../include/deliver_request.h
dotforward.o: ../../include/recipient_list.h
+dotforward.o: ../../include/mbox_conf.h
+dotforward.o: ../../include/argv.h
file.o: file.c
file.o: ../../include/sys_defs.h
file.o: ../../include/msg.h
file.o: ../../include/vbuf.h
file.o: ../../include/vstream.h
file.o: ../../include/deliver_flock.h
-file.o: ../../include/open_as.h
+file.o: ../../include/myflock.h
+file.o: ../../include/set_eugid.h
file.o: ../../include/mail_copy.h
file.o: ../../include/bounce.h
file.o: ../../include/defer.h
file.o: ../../include/sent.h
file.o: ../../include/been_here.h
file.o: ../../include/mail_params.h
-file.o: ../../include/dot_lockfile_as.h
+file.o: ../../include/mbox_conf.h
+file.o: ../../include/argv.h
+file.o: ../../include/mbox_open.h
+file.o: ../../include/safe_open.h
file.o: local.h
file.o: ../../include/tok822.h
file.o: ../../include/resolve_clnt.h
forward.o: ../../include/resolve_clnt.h
forward.o: ../../include/deliver_request.h
forward.o: ../../include/recipient_list.h
+forward.o: ../../include/mbox_conf.h
include.o: include.c
include.o: ../../include/sys_defs.h
include.o: ../../include/msg.h
include.o: ../../include/resolve_clnt.h
include.o: ../../include/deliver_request.h
include.o: ../../include/recipient_list.h
+include.o: ../../include/mbox_conf.h
+include.o: ../../include/argv.h
indirect.o: indirect.c
indirect.o: ../../include/sys_defs.h
indirect.o: ../../include/msg.h
indirect.o: ../../include/resolve_clnt.h
indirect.o: ../../include/deliver_request.h
indirect.o: ../../include/recipient_list.h
+indirect.o: ../../include/mbox_conf.h
+indirect.o: ../../include/argv.h
local.o: local.c
local.o: ../../include/sys_defs.h
local.o: ../../include/msg.h
local.o: local.h
local.o: ../../include/tok822.h
local.o: ../../include/resolve_clnt.h
+local.o: ../../include/mbox_conf.h
local_expand.o: local_expand.c
local_expand.o: ../../include/sys_defs.h
local_expand.o: ../../include/vstring.h
local_expand.o: ../../include/resolve_clnt.h
local_expand.o: ../../include/deliver_request.h
local_expand.o: ../../include/recipient_list.h
+local_expand.o: ../../include/mbox_conf.h
+local_expand.o: ../../include/argv.h
mailbox.o: mailbox.c
mailbox.o: ../../include/sys_defs.h
mailbox.o: ../../include/msg.h
mailbox.o: ../../include/mail_copy.h
mailbox.o: ../../include/safe_open.h
mailbox.o: ../../include/deliver_flock.h
+mailbox.o: ../../include/myflock.h
+mailbox.o: ../../include/dot_lockfile.h
mailbox.o: ../../include/defer.h
mailbox.o: ../../include/bounce.h
mailbox.o: ../../include/sent.h
mailbox.o: ../../include/recipient_list.h
mailbox.o: ../../include/mail_proto.h
mailbox.o: ../../include/iostuff.h
+mailbox.o: ../../include/mbox_open.h
mailbox.o: local.h
mailbox.o: ../../include/tok822.h
mailbox.o: ../../include/resolve_clnt.h
+mailbox.o: ../../include/mbox_conf.h
+mailbox.o: ../../include/argv.h
mailbox.o: biff_notify.h
maildir.o: maildir.c
maildir.o: ../../include/sys_defs.h
maildir.o: ../../include/resolve_clnt.h
maildir.o: ../../include/deliver_request.h
maildir.o: ../../include/recipient_list.h
+maildir.o: ../../include/mbox_conf.h
+maildir.o: ../../include/argv.h
recipient.o: recipient.c
recipient.o: ../../include/sys_defs.h
recipient.o: ../../include/msg.h
recipient.o: ../../include/resolve_clnt.h
recipient.o: ../../include/deliver_request.h
recipient.o: ../../include/recipient_list.h
+recipient.o: ../../include/mbox_conf.h
resolve.o: resolve.c
resolve.o: ../../include/sys_defs.h
resolve.o: ../../include/msg.h
resolve.o: ../../include/been_here.h
resolve.o: ../../include/deliver_request.h
resolve.o: ../../include/recipient_list.h
+resolve.o: ../../include/mbox_conf.h
+resolve.o: ../../include/argv.h
token.o: token.c
token.o: ../../include/sys_defs.h
token.o: ../../include/msg.h
token.o: ../../include/been_here.h
token.o: ../../include/deliver_request.h
token.o: ../../include/recipient_list.h
+token.o: ../../include/mbox_conf.h
+token.o: ../../include/argv.h
unknown.o: unknown.c
unknown.o: ../../include/sys_defs.h
unknown.o: ../../include/msg.h
unknown.o: ../../include/resolve_clnt.h
unknown.o: ../../include/deliver_request.h
unknown.o: ../../include/recipient_list.h
+unknown.o: ../../include/mbox_conf.h
+unknown.o: ../../include/argv.h
#include <vstring.h>
#include <vstream.h>
#include <deliver_flock.h>
-#include <open_as.h>
+#include <set_eugid.h>
/* Global library. */
#include <sent.h>
#include <been_here.h>
#include <mail_params.h>
-#include <dot_lockfile_as.h>
+#include <mbox_conf.h>
+#include <mbox_open.h>
/* Application-specific. */
{
char *myname = "deliver_file";
struct stat st;
- int fd;
VSTREAM *dst;
VSTRING *why;
int status;
int copy_flags;
-#ifdef USE_DOT_LOCK
- int lock = -1;
-
-#endif
-
/*
* Make verbose logging easier to understand.
*/
why = vstring_alloc(100);
/*
- * Open or create the file, lock it, and append the message. Open the
- * file as the specified user. XXX Since we cannot set a lockfile before
- * creating the destination, there is a small chance that we truncate an
- * existing file.
+ * As the specified user, open or create the file, lock it, and append
+ * the message. XXX We may attempt to create a lockfile for /dev/null.
*/
copy_flags = MAIL_COPY_MBOX;
if ((local_deliver_hdr_mask & DELIVER_HDR_FILE) == 0)
copy_flags &= ~MAIL_COPY_DELIVERED;
-#define FOPEN_AS(p,u,g) ( \
- (fd = open_as(p,O_APPEND|O_CREAT|O_WRONLY,0600,u,g)) >= 0 ? \
- vstream_fdopen(fd, O_WRONLY) : 0)
-
- if ((dst = FOPEN_AS(path, usr_attr.uid, usr_attr.gid)) == 0) {
- status = bounce_append(BOUNCE_FLAG_KEEP, BOUNCE_ATTR(state.msg_attr),
- "cannot open destination file %s: %m", path);
- } else if (fstat(vstream_fileno(dst), &st) < 0) {
- vstream_fclose(dst);
- status = defer_append(BOUNCE_FLAG_KEEP, BOUNCE_ATTR(state.msg_attr),
- "cannot fstat file %s: %m", path);
- } else if (S_ISREG(st.st_mode) && deliver_flock(vstream_fileno(dst), why) < 0) {
- vstream_fclose(dst);
- status = defer_append(BOUNCE_FLAG_KEEP, BOUNCE_ATTR(state.msg_attr),
- "cannot lock destination file %s: %s",
- path, STR(why));
+ set_eugid(usr_attr.uid, usr_attr.gid);
+ dst = mbox_open(path, O_APPEND | O_CREAT | O_WRONLY,
+ S_IRUSR | S_IWUSR, &st, -1, -1,
+ local_mbox_lock_mask | MBOX_DOT_LOCK_MAY_FAIL, why);
+ if (dst == 0) {
+ status = (errno == EAGAIN ? defer_append : bounce_append)
+ (BOUNCE_FLAG_KEEP, BOUNCE_ATTR(state.msg_attr),
+ "cannot access destination file %s: %s", path, STR(why));
} else if (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)) {
vstream_fclose(dst);
status = bounce_append(BOUNCE_FLAG_KEEP, BOUNCE_ATTR(state.msg_attr),
"executable destination file %s", path);
-#ifdef USE_DOT_LOCK
- } else if ((lock = dot_lockfile_as(path, why, usr_attr.uid, usr_attr.gid)) < 0
- && errno == EEXIST) {
- vstream_fclose(dst);
- status = defer_append(BOUNCE_FLAG_KEEP, BOUNCE_ATTR(state.msg_attr),
- "cannot append destination file %s: %s",
- path, STR(why));
-#endif
} else if (mail_copy(COPY_ATTR(state.msg_attr), dst, S_ISREG(st.st_mode) ?
copy_flags : (copy_flags & ~MAIL_COPY_TOFILE), "\n", why)) {
status = defer_append(BOUNCE_FLAG_KEEP, BOUNCE_ATTR(state.msg_attr),
} else {
status = sent(SENT_ATTR(state.msg_attr), "%s", path);
}
+ mbox_release(path, local_mbox_lock_mask);
+ set_eugid(var_owner_uid, var_owner_gid);
/*
* Clean up.
*/
-#ifdef USE_DOT_LOCK
- if (lock == 0)
- dot_unlockfile_as(path, usr_attr.uid, usr_attr.gid);
-#endif
vstring_free(why);
return (status);
}
/* .IP \fBrecipient_delimiter\fR
/* Separator between username and address extension.
/* .IP \fBtest_home_directory\fR
-/* Require that a recipient's home directory is accessible by the
+/* Require that a recipient's home directory is accessible by the
/* recipient before attempting delivery.
/* .SH Mailbox delivery
/* .ad
/* an exclusive lock.
/* .IP \fBstale_lock_time\fR
/* Limit the time after which a stale lock is removed.
+/* .IP \fBmailbox__delivery_lock\fR
+/* What file locking method(s) to use when delivering to a UNIX-style
+/* mailbox.
+/* The default setting is system dependent. For a list of available
+/* file locking methods, use the \fBpostconf -l\fR command.
/* .SH "Resource controls"
/* .ad
/* .fi
int var_exp_own_alias;
char *var_deliver_hdr;
int var_stat_home_dir;
+int var_mailtool_compat;
+char *var_mailbox_lock;
int local_cmd_deliver_mask;
int local_file_deliver_mask;
int local_ext_prop_mask;
int local_deliver_hdr_mask;
+int local_mbox_lock_mask;
/* local_deliver - deliver message with extreme prejudice */
0,
};
- local_file_deliver_mask = name_mask(file_mask, var_allow_files);
- local_cmd_deliver_mask = name_mask(command_mask, var_allow_commands);
+ local_file_deliver_mask = name_mask(VAR_ALLOW_FILES, file_mask,
+ var_allow_files);
+ local_cmd_deliver_mask = name_mask(VAR_ALLOW_COMMANDS, command_mask,
+ var_allow_commands);
local_ext_prop_mask = ext_prop_mask(var_prop_extension);
- local_deliver_hdr_mask = name_mask(deliver_mask, var_deliver_hdr);
+ local_deliver_hdr_mask = name_mask(VAR_DELIVER_HDR, deliver_mask,
+ var_deliver_hdr);
+ local_mbox_lock_mask = mbox_lock_mask(var_mailbox_lock);
+ if (var_mailtool_compat) {
+ msg_warn("%s: deprecated parameter, use \"%s = dotlock\" instead",
+ VAR_MAILTOOL_COMPAT, VAR_MAILBOX_LOCK);
+ local_mbox_lock_mask &= MBOX_DOT_LOCK;
+ }
+ if (local_mbox_lock_mask == 0)
+ msg_fatal("no applicable mailbox locking method");
}
/* pre_accept - see if tables have changed */
VAR_FWD_EXP_FILTER, DEF_FWD_EXP_FILTER, &var_fwd_exp_filter, 1, 0,
VAR_PROP_EXTENSION, DEF_PROP_EXTENSION, &var_prop_extension, 0, 0,
VAR_DELIVER_HDR, DEF_DELIVER_HDR, &var_deliver_hdr, 0, 0,
+ VAR_MAILBOX_LOCK, DEF_MAILBOX_LOCK, &var_mailbox_lock, 1, 0,
0,
};
static CONFIG_BOOL_TABLE bool_table[] = {
VAR_BIFF, DEF_BIFF, &var_biff,
VAR_EXP_OWN_ALIAS, DEF_EXP_OWN_ALIAS, &var_exp_own_alias,
VAR_STAT_HOME_DIR, DEF_STAT_HOME_DIR, &var_stat_home_dir,
+ VAR_MAILTOOL_COMPAT, DEF_MAILTOOL_COMPAT, &var_mailtool_compat,
0,
};
#include <been_here.h>
#include <tok822.h>
#include <deliver_request.h>
+#include <mbox_conf.h>
/*
* User attributes: these control the privileges for delivery to external
*/
extern int local_ext_prop_mask;
+ /*
+ * Mailbox lock protocol.
+ */
+extern int local_mbox_lock_mask;
+
/*
* When to prepend a Delivered-To: header upon external delivery.
*/
#include <mail_copy.h>
#include <safe_open.h>
#include <deliver_flock.h>
-#ifdef USE_DOT_LOCK
#include <dot_lockfile.h>
-#endif
#include <defer.h>
#include <sent.h>
#include <mypwd.h>
#include <been_here.h>
#include <mail_params.h>
#include <deliver_pass.h>
+#include <mbox_open.h>
#ifndef EDQUOT
#define EDQUOT EFBIG
copy_flags &= ~MAIL_COPY_DELIVERED;
set_eugid(spool_uid, spool_gid);
-#ifdef USE_DOT_LOCK
- if (dot_lockfile(mailbox, why) >= 0) {
-#endif
- dst = safe_open(mailbox, O_APPEND | O_WRONLY | O_CREAT,
- S_IRUSR | S_IWUSR, chown_uid, chown_gid, why);
- set_eugid(usr_attr.uid, usr_attr.gid);
- if (dst != 0) {
+ dst = mbox_open(mailbox, O_APPEND | O_WRONLY | O_CREAT,
+ S_IRUSR | S_IWUSR, &st, chown_uid, chown_gid,
+ local_mbox_lock_mask, why);
+ if (dst != 0) {
+ if (spool_uid != usr_attr.uid || spool_gid != usr_attr.gid)
+ set_eugid(usr_attr.uid, usr_attr.gid);
+ if (S_ISREG(st.st_mode) == 0) {
+ vstring_sprintf(why, "file %s should be a regular file", mailbox);
+ errno = 0;
+ } else {
end = vstream_fseek(dst, (off_t) 0, SEEK_END);
- if (deliver_flock(vstream_fileno(dst), why) < 0)
- vstream_fclose(dst);
- else if (mail_copy(COPY_ATTR(state.msg_attr), dst,
- copy_flags, "\n", why) == 0) {
- status = 0;
- if (var_biff) {
- biff = vstring_alloc(100);
- vstring_sprintf(biff, "%s@%ld", usr_attr.logname,
- (long) end);
- biff_notify(vstring_str(biff), VSTRING_LEN(biff) + 1);
- vstring_free(biff);
- }
- }
+ status = mail_copy(COPY_ATTR(state.msg_attr), dst,
+ copy_flags, "\n", why);
}
-#ifdef USE_DOT_LOCK
- set_eugid(spool_uid, spool_gid);
- dot_unlockfile(mailbox);
+ if (spool_uid != usr_attr.uid || spool_gid != usr_attr.gid)
+ set_eugid(spool_uid, spool_gid);
+ mbox_release(mailbox, local_mbox_lock_mask);
}
-#endif
set_eugid(var_owner_uid, var_owner_gid);
- if (status)
- status = (errno == EDQUOT ? bounce_append : defer_append)
+ if (status != 0) {
+ status = (errno == EAGAIN || errno == ENOSPC ?
+ defer_append : bounce_append)
(BOUNCE_FLAG_KEEP, BOUNCE_ATTR(state.msg_attr),
- "cannot append to file %s: %s", mailbox, vstring_str(why));
- else
+ "cannot access mailbox for user %s. %s",
+ state.msg_attr.user, vstring_str(why));
+ } else {
sent(SENT_ATTR(state.msg_attr), "mailbox");
+ if (var_biff) {
+ biff = vstring_alloc(100);
+ vstring_sprintf(biff, "%s@%ld", usr_attr.logname, (long) end);
+ biff_notify(vstring_str(biff), VSTRING_LEN(biff) + 1);
+ vstring_free(biff);
+ }
+ }
myfree(mailbox);
vstring_free(why);
return (status);
watchdog = watchdog_create(1000, (WATCHDOG_FN) 0, (char *) 0);
for (;;) {
#ifdef HAS_VOLATILE_LOCKS
- if (myflock(vstream_fileno(lock_fp), MYFLOCK_EXCLUSIVE) < 0)
+ if (myflock(vstream_fileno(lock_fp), INTERNAL_LOCK,
+ MYFLOCK_OP_EXCLUSIVE) < 0)
msg_fatal("refresh exclusive lock: %m");
#endif
watchdog_start(watchdog); /* same as trigger servers */
/* multi_server_disconnect - terminate client session */
-void multi_server_disconnect(VSTREAM *stream)
+void multi_server_disconnect(VSTREAM * stream)
{
if (msg_verbose)
msg_info("connection closed fd %d", vstream_fileno(stream));
VSTREAM *stream = (VSTREAM *) context;
if (multi_server_lock != 0
- && myflock(vstream_fileno(multi_server_lock), MYFLOCK_NONE) < 0)
+ && myflock(vstream_fileno(multi_server_lock), INTERNAL_LOCK,
+ MYFLOCK_OP_NONE) < 0)
msg_fatal("select unlock: %m");
/*
multi_server_pre_accept(multi_server_name, multi_server_argv);
fd = LOCAL_ACCEPT(listen_fd);
if (multi_server_lock != 0
- && myflock(vstream_fileno(multi_server_lock), MYFLOCK_NONE) < 0)
+ && myflock(vstream_fileno(multi_server_lock), INTERNAL_LOCK,
+ MYFLOCK_OP_NONE) < 0)
msg_fatal("select unlock: %m");
if (fd < 0) {
if (errno != EAGAIN)
multi_server_pre_accept(multi_server_name, multi_server_argv);
fd = inet_accept(listen_fd);
if (multi_server_lock != 0
- && myflock(vstream_fileno(multi_server_lock), MYFLOCK_NONE) < 0)
+ && myflock(vstream_fileno(multi_server_lock), INTERNAL_LOCK,
+ MYFLOCK_OP_NONE) < 0)
msg_fatal("select unlock: %m");
if (fd < 0) {
if (errno != EAGAIN)
".", service_name, (char *) 0);
why = vstring_alloc(1);
if ((multi_server_lock = safe_open(lock_path, O_CREAT | O_RDWR, 0600,
- -1, -1, why)) == 0)
+ (struct stat *) 0, -1, -1, why)) == 0)
msg_fatal("%s", vstring_str(why));
close_on_exec(vstream_fileno(multi_server_lock), CLOSE_ON_EXEC);
myfree(lock_path);
while (var_use_limit == 0 || use_count < var_use_limit || client_count > 0) {
if (multi_server_lock != 0) {
watchdog_stop(watchdog);
- if (myflock(vstream_fileno(multi_server_lock), MYFLOCK_EXCLUSIVE) < 0)
+ if (myflock(vstream_fileno(multi_server_lock), INTERNAL_LOCK,
+ MYFLOCK_OP_EXCLUSIVE) < 0)
msg_fatal("select lock: %m");
}
watchdog_start(watchdog);
single_server_pre_accept(single_server_name, single_server_argv);
fd = LOCAL_ACCEPT(listen_fd);
if (single_server_lock != 0
- && myflock(vstream_fileno(single_server_lock), MYFLOCK_NONE) < 0)
+ && myflock(vstream_fileno(single_server_lock), INTERNAL_LOCK,
+ MYFLOCK_OP_NONE) < 0)
msg_fatal("select unlock: %m");
if (fd < 0) {
if (errno != EAGAIN)
single_server_pre_accept(single_server_name, single_server_argv);
fd = inet_accept(listen_fd);
if (single_server_lock != 0
- && myflock(vstream_fileno(single_server_lock), MYFLOCK_NONE) < 0)
+ && myflock(vstream_fileno(single_server_lock), INTERNAL_LOCK,
+ MYFLOCK_OP_NONE) < 0)
msg_fatal("select unlock: %m");
if (fd < 0) {
if (errno != EAGAIN)
".", service_name, (char *) 0);
why = vstring_alloc(1);
if ((single_server_lock = safe_open(lock_path, O_CREAT | O_RDWR, 0600,
- -1, -1, why)) == 0)
+ (struct stat *) 0, -1, -1, why)) == 0)
msg_fatal("%s", vstring_str(why));
close_on_exec(vstream_fileno(single_server_lock), CLOSE_ON_EXEC);
myfree(lock_path);
while (var_use_limit == 0 || use_count < var_use_limit) {
if (single_server_lock != 0) {
watchdog_stop(watchdog);
- if (myflock(vstream_fileno(single_server_lock), MYFLOCK_EXCLUSIVE) < 0)
+ if (myflock(vstream_fileno(single_server_lock), INTERNAL_LOCK,
+ MYFLOCK_OP_EXCLUSIVE) < 0)
msg_fatal("select lock: %m");
}
watchdog_start(watchdog);
int listen_fd = CAST_CHAR_PTR_TO_INT(context);
if (trigger_server_lock != 0
- && myflock(vstream_fileno(trigger_server_lock), MYFLOCK_NONE) < 0)
+ && myflock(vstream_fileno(trigger_server_lock), INTERNAL_LOCK,
+ MYFLOCK_OP_NONE) < 0)
msg_fatal("select unlock: %m");
if (msg_verbose)
trigger_server_pre_accept(trigger_server_name, trigger_server_argv);
fd = LOCAL_ACCEPT(listen_fd);
if (trigger_server_lock != 0
- && myflock(vstream_fileno(trigger_server_lock), MYFLOCK_NONE) < 0)
+ && myflock(vstream_fileno(trigger_server_lock), INTERNAL_LOCK,
+ MYFLOCK_OP_NONE) < 0)
msg_fatal("select unlock: %m");
if (fd < 0) {
if (errno != EAGAIN)
".", service_name, (char *) 0);
why = vstring_alloc(1);
if ((trigger_server_lock = safe_open(lock_path, O_CREAT | O_RDWR, 0600,
- -1, -1, why)) == 0)
+ (struct stat *) 0, -1, -1, why)) == 0)
msg_fatal("%s", vstring_str(why));
close_on_exec(vstream_fileno(trigger_server_lock), CLOSE_ON_EXEC);
myfree(lock_path);
while (var_use_limit == 0 || use_count < var_use_limit) {
if (trigger_server_lock != 0) {
watchdog_stop(watchdog);
- if (myflock(vstream_fileno(trigger_server_lock), MYFLOCK_EXCLUSIVE) < 0)
+ if (myflock(vstream_fileno(trigger_server_lock), INTERNAL_LOCK,
+ MYFLOCK_OP_EXCLUSIVE) < 0)
msg_fatal("select lock: %m");
}
watchdog_start(watchdog);
* Extract message envelope information: time of arrival, sender address,
* recipient addresses. Skip files with malformed envelope information.
*/
-#define QMGR_LOCK_MODE (MYFLOCK_EXCLUSIVE | MYFLOCK_NOWAIT)
+#define QMGR_LOCK_MODE (MYFLOCK_OP_EXCLUSIVE | MYFLOCK_OP_NOWAIT)
if (qmgr_message_open(message) < 0) {
qmgr_message_free(message);
return (0);
}
- if (myflock(vstream_fileno(message->fp), QMGR_LOCK_MODE) < 0) {
+ if (myflock(vstream_fileno(message->fp), INTERNAL_LOCK, QMGR_LOCK_MODE) < 0) {
msg_info("%s: skipped, still being delivered", queue_id);
qmgr_message_close(message);
qmgr_message_free(message);
postconf.o: ../../include/mail_version.h
postconf.o: ../../include/mail_params.h
postconf.o: ../../include/mail_addr.h
+postconf.o: ../../include/mbox_conf.h
postconf.o: time_vars.h
postconf.o: bool_vars.h
postconf.o: int_vars.h
/* Postfix configuration utility
/* SYNOPSIS
/* .fi
-/* \fBpostconf\fR [\fB-dhmnv\fR] [\fB-c \fIconfig_dir\fR]
+/* \fBpostconf\fR [\fB-dhmlnv\fR] [\fB-c \fIconfig_dir\fR]
/* [\fIparameter ...\fR]
/*
/* \fBpostconf\fR [\fB-ev\fR] [\fB-c \fIconfig_dir\fR]
/* that normally precedes the value.
/* .IP \fB-m\fR
/* List the names of all supported lookup table types.
+/* .IP \fB-l\fR
+/* List the names of all supported mailbox locking methods.
/* .IP \fB-n\fR
/* Print non-default parameter settings only.
/* .IP \fB-v\fR
#include <mail_version.h>
#include <mail_params.h>
#include <mail_addr.h>
+#include <mbox_conf.h>
/*
* What we're supposed to be doing.
#define SHOW_NAME (1<<2) /* show parameter name */
#define SHOW_MAPS (1<<3) /* show map types */
#define EDIT_MAIN (1<<4) /* edit main.cf */
+#define SHOW_LOCKS (1<<5) /* show mailbox lock methods */
/*
* Lookup table for in-core parameter info.
temp = concatenate(path, ".tmp", (char *) 0);
if ((dst = vstream_fopen(temp, O_CREAT | O_WRONLY, 0644)) == 0)
msg_fatal("open %s: %m", temp);
- if (myflock(vstream_fileno(dst), MYFLOCK_EXCLUSIVE) < 0)
+ if (myflock(vstream_fileno(dst), INTERNAL_LOCK, MYFLOCK_OP_EXCLUSIVE) < 0)
msg_fatal("lock %s: %m", temp);
if (ftruncate(vstream_fileno(dst), 0) < 0)
msg_fatal("truncate %s: %m", temp);
argv_free(maps_argv);
}
+/* show_locks - show available mailbox locking methods */
+
+static void show_locks(void)
+{
+ ARGV *maps_argv;
+ int i;
+
+ maps_argv = mbox_lock_names();
+ for (i = 0; i < maps_argv->argc; i++)
+ vstream_printf("%s\n", maps_argv->argv[i]);
+ argv_free(maps_argv);
+}
+
/* show_parameters - show parameter info */
static void show_parameters(int mode, char **names)
/*
* Parse JCL.
*/
- while ((ch = GETOPT(argc, argv, "c:dehnmv")) > 0) {
+ while ((ch = GETOPT(argc, argv, "c:dehmlnv")) > 0) {
switch (ch) {
case 'c':
if (setenv(CONF_ENV_PATH, optarg, 1) < 0)
case 'h':
mode &= ~SHOW_NAME;
break;
+ case 'l':
+ mode |= SHOW_LOCKS;
+ break;
case 'm':
mode |= SHOW_MAPS;
break;
msg_verbose++;
break;
default:
- msg_fatal("usage: %s [-c config_dir] [-d (defaults)] [-e (edit)] [-h (no names)] [-m (map types) [-n (non-defaults)] [-v] [name...]", argv[0]);
+ msg_fatal("usage: %s [-c config_dir] [-d (defaults)] [-e (edit)] [-h (no names)] [-l (lock types)] [-m (map types) [-n (non-defaults)] [-v] [name...]", argv[0]);
}
}
/*
* Sanity check.
*/
- junk = (mode & (SHOW_DEFS | SHOW_NONDEF | SHOW_MAPS | EDIT_MAIN));
+ junk = (mode & (SHOW_DEFS | SHOW_NONDEF | SHOW_MAPS | SHOW_LOCKS | EDIT_MAIN));
if (junk != 0 && junk != SHOW_DEFS && junk != SHOW_NONDEF
- && junk != SHOW_MAPS && junk != EDIT_MAIN)
- msg_fatal("specify one of -d, -e, -n and -m");
+ && junk != SHOW_MAPS && junk != SHOW_LOCKS && junk != EDIT_MAIN)
+ msg_fatal("specify one of -d, -e, -m, -l and -n");
/*
* If showing map types, show them and exit
show_maps();
}
+ /*
+ * If showing locking methods, show them and exit
+ */
+ if (mode & SHOW_LOCKS) {
+ show_locks();
+ }
+
/*
* Edit main.cf.
*/
postlock.o: ../../include/vstream.h
postlock.o: ../../include/msg_vstream.h
postlock.o: ../../include/iostuff.h
+postlock.o: ../../include/safe_open.h
postlock.o: ../../include/mail_params.h
postlock.o: ../../include/dot_lockfile.h
postlock.o: ../../include/deliver_flock.h
+postlock.o: ../../include/myflock.h
postlock.o: ../../include/mail_conf.h
postlock.o: ../../include/sys_exits.h
+postlock.o: ../../include/mbox_conf.h
+postlock.o: ../../include/argv.h
+postlock.o: ../../include/mbox_open.h
/* lock mail folder and execute command
/* SYNOPSIS
/* .fi
-/* \fBpostlock\fR [\fB-c \fIconfig_dir\fB] [\fB-v\fR]
-/* \fIfile command...\fR
+/* \fBpostlock\fR [\fB-c \fIconfig_dir\fB] [\fB-l \fIlock_style\fB]
+/* [\fB-v\fR] \fIfile command...\fR
/* DESCRIPTION
/* The \fBpostlock\fR command locks \fIfile\fR for exclusive
/* access, and executes \fIcommand\fR. The locking method is
/* .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-l \fIlock_style\fR"
+/* Override the locking method specified via the
+/* \fBmailbox_delivery_lock\fR configuration parameter (see below).
/* .IP \fB-v\fR
/* Enable verbose logging for debugging purposes. Multiple \fB-v\fR
/* options make the software increasingly verbose.
/* access. The command is executed directly, i.e. without
/* interpretation by a shell command interpreter.
/* DIAGNOSTICS
-/* The result status is 75 (EX_TEMPFAIL) when the file is locked by
-/* another process, 255 (on some systems: -1) when \fBpostlock\fR
+/* The result status is 75 (EX_TEMPFAIL) when \fBpostlock\fR
/* could not perform the requested operation. Otherwise, the
/* exit status is the exit status from the command.
/* BUGS
/* an exclusive lock.
/* .IP \fBstale_lock_time\fR
/* Limit the time after which a stale lock is removed.
+/* .IP \fBmailbox_delivery_lock\fR
+/* What file locking method(s) to use when delivering to a UNIX-style
+/* mailbox.
+/* The default setting is system dependent. For a list of available
+/* file locking methods, use the \fBpostconf -l\fR command.
/* .SH "Resource controls"
/* .ad
/* .fi
#include <vstream.h>
#include <msg_vstream.h>
#include <iostuff.h>
+#include <safe_open.h>
/* Global library. */
#include <deliver_flock.h>
#include <mail_conf.h>
#include <sys_exits.h>
+#include <mbox_conf.h>
+#include <mbox_open.h>
/* Application-specific. */
static NORETURN usage(char *myname)
{
- msg_fatal("usage: %s [-c config_dir] [-v] folder command...", myname);
+ msg_fatal("usage: %s [-c config_dir] [-l lock_style] [-v] folder command...", myname);
}
-/* fatal_exit - as promised, return 255 in case of unexpected problems */
+/* fatal_exit - all failures are deemed recoverable */
static void fatal_exit(void)
{
- exit(255);
+ exit(EX_TEMPFAIL);
}
/* main - go for it */
int count;
WAIT_STATUS_T status;
pid_t pid;
+ int mbox_lock;
+ char *lock_style = 0;
+ VSTREAM *fp;
/*
* Be consistent with file permissions.
/*
* Parse JCL.
*/
- while ((ch = GETOPT(argc, argv, "c:v")) > 0) {
+ while ((ch = GETOPT(argc, argv, "c:l:v")) > 0) {
switch (ch) {
default:
usage(argv[0]);
if (setenv(CONF_ENV_PATH, optarg, 1) < 0)
msg_fatal("out of memory");
break;
+ case 'l':
+ lock_style = optarg;
+ break;
case 'v':
msg_verbose++;
break;
* Read the config file.
*/
mail_conf_read();
+ mbox_lock = mbox_lock_mask(lock_style ? lock_style :
+ get_mail_conf_str(VAR_MAILBOX_LOCK, DEF_MAILBOX_LOCK, 1, 0));
/*
* Lock the folder for exclusive access. Lose the lock upon exit. The
* command is not supposed to disappear into the background.
*/
- if ((fd = open(folder, O_RDWR, 0)) < 0)
- msg_fatal("open %s: %m", folder);
- close_on_exec(fd, CLOSE_ON_EXEC);
why = vstring_alloc(1);
-#ifdef USE_DOT_LOCK
- if (dot_lockfile(folder, why) < 0) {
- if (errno == EEXIST) {
- msg_warn("%s", vstring_str(why));
- exit(EX_TEMPFAIL);
- }
+ if ((fp = mbox_open(folder, O_APPEND | O_WRONLY | O_CREAT,
+ S_IRUSR | S_IWUSR, (struct stat *) 0,
+ -1, -1, mbox_lock, why)) == 0)
msg_fatal("%s", vstring_str(why));
- }
-#endif
- if (deliver_flock(fd, why) < 0) {
- if (errno == EAGAIN) {
- msg_warn("file %s: %s", folder, vstring_str(why));
-#ifdef USE_DOT_LOCK
- dot_unlockfile(folder);
-#endif
- exit(EX_TEMPFAIL);
- }
- msg_fatal("file %s: %s", folder, vstring_str(why));
- }
+ close_on_exec(vstream_fileno(fp), CLOSE_ON_EXEC);
/*
* Run the command. Remove the lock after completion.
case 0:
execvp(command[0], command);
msg_fatal("execvp %s: %m", command[0]);
- /* NOTREACHED */
default:
if (waitpid(pid, &status, 0) < 0)
msg_fatal("waitpid: %m");
-#ifdef USE_DOT_LOCK
- dot_unlockfile(folder);
-#endif
+ mbox_release(folder, mbox_lock);
exit(WIFEXITED(status) ? WEXITSTATUS(status) : 1);
- /* NOTREACHED */
}
if (count + 1 < var_fork_tries)
sleep(var_fork_delay);
}
- msg_fatal("fork %s: %m", command[0]);
- /* NOTREACHED */
-
+ mbox_release(folder, mbox_lock);
+ exit(EX_TEMPFAIL);
}
* Extract message envelope information: time of arrival, sender address,
* recipient addresses. Skip files with malformed envelope information.
*/
-#define QMGR_LOCK_MODE (MYFLOCK_EXCLUSIVE | MYFLOCK_NOWAIT)
+#define QMGR_LOCK_MODE (MYFLOCK_OP_EXCLUSIVE | MYFLOCK_OP_NOWAIT)
if (qmgr_message_open(message) < 0) {
qmgr_message_free(message);
return (0);
}
- if (myflock(vstream_fileno(message->fp), QMGR_LOCK_MODE) < 0) {
+ if (myflock(vstream_fileno(message->fp), INTERNAL_LOCK, QMGR_LOCK_MODE) < 0) {
msg_info("%s: skipped, still being delivered", queue_id);
qmgr_message_close(message);
qmgr_message_free(message);
if (smtp_helo(state) == 0)
smtp_xfer(state);
if (state->history != 0
- && (state->error_mask & name_mask(mail_error_masks, var_notify_classes)))
+ && (state->error_mask & name_mask(VAR_NOTIFY_CLASSES,
+ mail_error_masks, var_notify_classes)))
smtp_chat_notify(state);
smtp_session_free(state->session);
debug_peer_restore();
- }
+}
- /*
- * Clean up.
- */
- vstring_free(why);
- smtp_chat_reset(state);
- result = state->status;
- smtp_state_free(state);
+ /*
+ * Clean up.
+ */
+vstring_free(why);
+smtp_chat_reset(state);
+result = state->status;
+smtp_state_free(state);
- return (result);
+return (result);
}
/* smtp_service - perform service for client */
/*
* Configuration parameters.
*/
- smtp_sasl_sec_opts = name_mask(smtp_sasl_sec_mask, var_smtp_sasl_opts);
+ smtp_sasl_sec_opts = name_mask(VAR_SMTP_SASL_OPTS, smtp_sasl_sec_mask,
+ var_smtp_sasl_opts);
}
/* smtp_sasl_connect - per-session client initialization */
state->buffer = vstring_alloc(100);
state->error_count = 0;
state->error_mask = 0;
- state->notify_mask = name_mask(mail_error_masks, var_notify_classes);
+ state->notify_mask = name_mask(VAR_NOTIFY_CLASSES, mail_error_masks,
+ var_notify_classes);
state->helo_name = 0;
state->queue_id = 0;
state->cleanup = 0;
stream_connect.c stream_trigger.c dict_regexp.c mac_expand.c \
clean_env.c watchdog.c spawn_command.c duplex_pipe.c sane_rename.c \
sane_link.c unescape.c timed_read.c timed_write.c dict_tcp.c \
- hex_quote.c
+ hex_quote.c
OBJS = argv.o argv_split.o attr.o basename.o binhash.o chroot_uid.o \
close_on_exec.o concatenate.o dict.o dict_db.o dict_dbm.o \
dict_env.o dict_ht.o dict_ldap.o dict_mysql.o dict_ni.o dict_nis.o \
stream_connect.o stream_trigger.o dict_regexp.o mac_expand.o \
clean_env.o watchdog.o spawn_command.o duplex_pipe.o sane_rename.o \
sane_link.o unescape.o timed_read.o timed_write.o dict_tcp.o \
- hex_quote.o
+ hex_quote.o
HDRS = argv.h attr.h binhash.h chroot_uid.h connect.h dict.h dict_db.h \
dict_dbm.h dict_env.h dict_ht.h dict_ldap.h dict_mysql.h \
dict_ni.h dict_nis.h dict_nisplus.h dir_forest.h events.h \
inet_addr_host inet_addr_local mac_parse make_dirs msg_syslog \
mystrtok sigdelay translit valid_hostname vstream_popen \
vstring vstring_vstream doze select_bug stream_test mac_expand \
- watchdog unescape hex_quote
+ watchdog unescape hex_quote name_mask
LIB_DIR = ../../lib
INC_DIR = ../../include
$(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(SYSLIBS)
mv junk $@.o
+name_mask: $(LIB)
+ mv $@.o junk
+ $(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(SYSLIBS)
+ mv junk $@.o
+
depend: $(MAKES)
(sed '1,/^# do not edit/!d' Makefile.in; \
set -e; for i in [a-z][a-z0-9]*.c; do \
myflock.o: myflock.c
myflock.o: sys_defs.h
myflock.o: msg.h
+myflock.o: vstring.h
+myflock.o: vbuf.h
myflock.o: myflock.h
mymalloc.o: mymalloc.c
mymalloc.o: sys_defs.h
/* void argv_terminate(argvp);
/* ARGV *argvp;
/* DESCRIPTION
-/* The functions in this module functions manipulate arrays of string
+/* The functions in this module manipulate arrays of string
/* pointers. An ARGV structure contains the following members:
/* .IP len
/* The length of the \fIargv\fR array member.
/*
* Acquire a shared lock.
*/
- if ((dict->flags & DICT_FLAG_LOCK) && myflock(dict->fd, MYFLOCK_SHARED) < 0)
+ if ((dict->flags & DICT_FLAG_LOCK)
+ && myflock(dict->fd, INTERNAL_LOCK, MYFLOCK_OP_SHARED) < 0)
msg_fatal("%s: lock dictionary: %m", dict_db->path);
/*
/*
* Release the shared lock.
*/
- if ((dict->flags & DICT_FLAG_LOCK) && myflock(dict->fd, MYFLOCK_NONE) < 0)
+ if ((dict->flags & DICT_FLAG_LOCK)
+ && myflock(dict->fd, INTERNAL_LOCK, MYFLOCK_OP_NONE) < 0)
msg_fatal("%s: unlock dictionary: %m", dict_db->path);
return (result);
/*
* Acquire an exclusive lock.
*/
- if ((dict->flags & DICT_FLAG_LOCK) && myflock(dict->fd, MYFLOCK_EXCLUSIVE) < 0)
+ if ((dict->flags & DICT_FLAG_LOCK)
+ && myflock(dict->fd, INTERNAL_LOCK, MYFLOCK_OP_EXCLUSIVE) < 0)
msg_fatal("%s: lock dictionary: %m", dict_db->path);
/*
/*
* Release the exclusive lock.
*/
- if ((dict->flags & DICT_FLAG_LOCK) && myflock(dict->fd, MYFLOCK_NONE) < 0)
+ if ((dict->flags & DICT_FLAG_LOCK)
+ && myflock(dict->fd, INTERNAL_LOCK, MYFLOCK_OP_NONE) < 0)
msg_fatal("%s: unlock dictionary: %m", dict_db->path);
}
/*
* Acquire an exclusive lock.
*/
- if ((dict->flags & DICT_FLAG_LOCK) && myflock(dict->fd, MYFLOCK_EXCLUSIVE) < 0)
+ if ((dict->flags & DICT_FLAG_LOCK)
+ && myflock(dict->fd, INTERNAL_LOCK, MYFLOCK_OP_EXCLUSIVE) < 0)
msg_fatal("%s: lock dictionary: %m", dict_db->path);
/*
/*
* Release the exclusive lock.
*/
- if ((dict->flags & DICT_FLAG_LOCK) && myflock(dict->fd, MYFLOCK_NONE) < 0)
+ if ((dict->flags & DICT_FLAG_LOCK)
+ && myflock(dict->fd, INTERNAL_LOCK, MYFLOCK_OP_NONE) < 0)
msg_fatal("%s: unlock dictionary: %m", dict_db->path);
return status;
/*
* Acquire an exclusive lock.
*/
- if ((dict->flags & DICT_FLAG_LOCK) && myflock(dict->fd, MYFLOCK_EXCLUSIVE) < 0)
+ if ((dict->flags & DICT_FLAG_LOCK)
+ && myflock(dict->fd, INTERNAL_LOCK, MYFLOCK_OP_EXCLUSIVE) < 0)
msg_fatal("%s: lock dictionary: %m", dict_db->path);
if ((status = db->seq(db, &db_key, &db_value, db_function)) < 0)
/*
* Release the exclusive lock.
*/
- if ((dict->flags & DICT_FLAG_LOCK) && myflock(dict->fd, MYFLOCK_NONE) < 0)
+ if ((dict->flags & DICT_FLAG_LOCK)
+ && myflock(dict->fd, INTERNAL_LOCK, MYFLOCK_OP_NONE) < 0)
msg_fatal("%s: unlock dictionary: %m", dict_db->path);
if (status == 0) {
if (dict_flags & DICT_FLAG_LOCK) {
if ((lock_fd = open(db_path, open_flags, 0644)) < 0)
msg_fatal("open database %s: %m", db_path);
- if (myflock(lock_fd, MYFLOCK_SHARED) < 0)
+ if (myflock(lock_fd, INTERNAL_LOCK, MYFLOCK_OP_SHARED) < 0)
msg_fatal("shared-lock database %s for open: %m", db_path);
}
msg_fatal("get database file descriptor: %m");
#endif
if (dict_flags & DICT_FLAG_LOCK) {
- if (myflock(lock_fd, MYFLOCK_NONE) < 0)
+ if (myflock(lock_fd, INTERNAL_LOCK, MYFLOCK_OP_NONE) < 0)
msg_fatal("unlock database %s for open: %m", db_path);
if (close(lock_fd) < 0)
msg_fatal("close database %s: %m", db_path);
}
-
dict_db = (DICT_DB *) mymalloc(sizeof(*dict_db));
dict_db->dict.lookup = dict_db_lookup;
dict_db->dict.update = dict_db_update;
/*
* Acquire an exclusive lock.
*/
- if ((dict->flags & DICT_FLAG_LOCK) && myflock(dict->fd, MYFLOCK_SHARED) < 0)
+ if ((dict->flags & DICT_FLAG_LOCK)
+ && myflock(dict->fd, INTERNAL_LOCK, MYFLOCK_OP_SHARED) < 0)
msg_fatal("%s: lock dictionary: %m", dict_dbm->path);
/*
/*
* Release the exclusive lock.
*/
- if ((dict->flags & DICT_FLAG_LOCK) && myflock(dict->fd, MYFLOCK_NONE) < 0)
+ if ((dict->flags & DICT_FLAG_LOCK)
+ && myflock(dict->fd, INTERNAL_LOCK, MYFLOCK_OP_NONE) < 0)
msg_fatal("%s: unlock dictionary: %m", dict_dbm->path);
return (result);
/*
* Acquire an exclusive lock.
*/
- if ((dict->flags & DICT_FLAG_LOCK) && myflock(dict->fd, MYFLOCK_EXCLUSIVE) < 0)
+ if ((dict->flags & DICT_FLAG_LOCK)
+ && myflock(dict->fd, INTERNAL_LOCK, MYFLOCK_OP_EXCLUSIVE) < 0)
msg_fatal("%s: lock dictionary: %m", dict_dbm->path);
/*
/*
* Release the exclusive lock.
*/
- if ((dict->flags & DICT_FLAG_LOCK) && myflock(dict->fd, MYFLOCK_NONE) < 0)
+ if ((dict->flags & DICT_FLAG_LOCK)
+ && myflock(dict->fd, INTERNAL_LOCK, MYFLOCK_OP_NONE) < 0)
msg_fatal("%s: unlock dictionary: %m", dict_dbm->path);
}
/*
* Acquire an exclusive lock.
*/
- if ((dict->flags & DICT_FLAG_LOCK) && myflock(dict->fd, MYFLOCK_EXCLUSIVE) < 0)
+ if ((dict->flags & DICT_FLAG_LOCK)
+ && myflock(dict->fd, INTERNAL_LOCK, MYFLOCK_OP_EXCLUSIVE) < 0)
msg_fatal("%s: lock dictionary: %m", dict_dbm->path);
/*
/*
* Release the exclusive lock.
*/
- if ((dict->flags & DICT_FLAG_LOCK) && myflock(dict->fd, MYFLOCK_NONE) < 0)
+ if ((dict->flags & DICT_FLAG_LOCK)
+ && myflock(dict->fd, INTERNAL_LOCK, MYFLOCK_OP_NONE) < 0)
msg_fatal("%s: unlock dictionary: %m", dict_dbm->path);
return (status);
/*
* Acquire an exclusive lock.
*/
- if ((dict->flags & DICT_FLAG_LOCK) && myflock(dict->fd, MYFLOCK_EXCLUSIVE) < 0)
+ if ((dict->flags & DICT_FLAG_LOCK)
+ && myflock(dict->fd, INTERNAL_LOCK, MYFLOCK_OP_EXCLUSIVE) < 0)
msg_fatal("%s: lock dictionary: %m", dict_dbm->path);
/*
/*
* Release the exclusive lock.
*/
- if ((dict->flags & DICT_FLAG_LOCK) && myflock(dict->fd, MYFLOCK_NONE) < 0)
+ if ((dict->flags & DICT_FLAG_LOCK)
+ && myflock(dict->fd, INTERNAL_LOCK, MYFLOCK_OP_NONE) < 0)
msg_fatal("%s: unlock dictionary: %m", dict_dbm->path);
if (dbm_key.dptr != 0 && dbm_key.dsize > 0) {
dbm_path = concatenate(path, ".pag", (char *) 0);
if ((lock_fd = open(dbm_path, open_flags, 0644)) < 0)
msg_fatal("open database %s: %m", dbm_path);
- if (myflock(lock_fd, MYFLOCK_SHARED) < 0)
+ if (myflock(lock_fd, INTERNAL_LOCK, MYFLOCK_OP_SHARED) < 0)
msg_fatal("shared-lock database %s for open: %m", dbm_path);
}
msg_fatal("open database %s.{dir,pag}: %m", path);
if (dict_flags & DICT_FLAG_LOCK) {
- if (myflock(lock_fd, MYFLOCK_NONE) < 0)
+ if (myflock(lock_fd, INTERNAL_LOCK, MYFLOCK_OP_NONE) < 0)
msg_fatal("unlock database %s for open: %m", dbm_path);
if (close(lock_fd) < 0)
msg_fatal("close database %s: %m", dbm_path);
/* SYNOPSIS
/* #include <myflock.h>
/*
-/* int myflock(fd, how)
+/* int myflock(fd, lock_style, operation)
/* int fd;
-/* int how;
+/* int lock_style;
+/* int operation;
/*
/* int myflock_locked(err)
/* int err;
/* DESCRIPTION
/* myflock() locks or unlocks an entire open file. Depending
-/* on the operating system environment, this function uses the
-/* fcntl() or flock() system calls, so the usual caveats apply.
+/* on the value of the \fIlock_style\fR argument, this function uses
+/* either the fcntl() or the flock() system call.
/*
/* In the case of a blocking request, a call that fails due to
/* transient problems is tried again once per second.
/* Arguments:
/* .IP fd
/* The open file to be locked/unlocked.
-/* .IP how
+/* .IP lock_style
/* One of the following values:
/* .RS
-/* .IP MYFLOCK_NONE
+/* .IP MYFLOCK_STYLE_FLOCK
+/* Use BSD-style flock() locks.
+/* .IP MYFLOCK_STYLE_FCNTL
+/* Use POSIX-style fcntl() locks.
+/* .RE
+/* .IP operation
+/* One of the following values:
+/* .RS
+/* .IP MYFLOCK_OP_NONE
/* Releases any locks the process has on the specified open file.
-/* .IP MYFLOCK_SHARED
+/* .IP MYFLOCK_OP_SHARED
/* Attempts to acquire a shared lock on the specified open file.
/* This is appropriate for read-only access.
-/* .IP MYFLOCK_EXCLUSIVE
+/* .IP MYFLOCK_OP_EXCLUSIVE
/* Attempts to acquire an exclusive lock on the specified open
/* file. This is appropriate for write access.
/* .PP
-/* In addition, setting the MYFLOCK_NOWAIT bit causes the
+/* In addition, setting the MYFLOCK_OP_NOWAIT bit causes the
/* call to return immediately when the requested lock cannot
-/* be acquired. See the myflock_locked() function on how to deal
+/* be acquired. See the myflock_locked() function on lock_style to deal
/* with a negative result.
/* .RE
/* DIAGNOSTICS
/* myflock() returns 0 in case of success, -1 in case of failure.
/* A problem description is returned via the global \fIerrno\fR
/* variable.
+/*
+/* Panic: attempts to use an unsupported file locking method.
+/* to use multiple locking methods, or none.
/* LICENSE
/* .ad
/* .fi
#include <errno.h>
#include <unistd.h>
-#ifdef USE_FCNTL_LOCK
+#ifdef HAS_FCNTL_LOCK
#include <fcntl.h>
#include <string.h>
#endif
-#ifdef USE_FLOCK_LOCK
+#ifdef HAS_FLOCK_LOCK
#include <sys/file.h>
#endif
/* Utility library. */
#include "msg.h"
+#include "vstring.h"
#include "myflock.h"
/* myflock - lock/unlock entire open file */
-int myflock(int fd, int how)
+int myflock(int fd, int lock_style, int operation)
{
+ switch (lock_style) {
- /*
- * flock() does exactly what we need. Too bad it is not standard.
- */
-#ifdef USE_FLOCK_LOCK
- static int lock_ops[] = {
- LOCK_UN, LOCK_SH, LOCK_EX, -1,
- -1, LOCK_SH | LOCK_NB, LOCK_EX | LOCK_NB, -1
- };
+ /*
+ * flock() does exactly what we need. Too bad it is not standard.
+ */
+#ifdef HAS_FLOCK_LOCK
+ case MYFLOCK_STYLE_FLOCK:
+ {
+ static int lock_ops[] = {
+ LOCK_UN, LOCK_SH, LOCK_EX, -1,
+ -1, LOCK_SH | LOCK_NB, LOCK_EX | LOCK_NB, -1
+ };
- if ((how & (MYFLOCK_BITS)) != how)
- msg_panic("myflock: improper request type: %d", how);
- return (flock(fd, lock_ops[how]));
+ if ((operation & (MYFLOCK_OP_BITS)) != operation)
+ msg_panic("myflock: improper operation type: 0x%x", operation);
+ return (flock(fd, lock_ops[operation]));
+ }
#endif
- /*
- * fcntl() is standard and does more than we need, but we can handle it.
- */
-#ifdef USE_FCNTL_LOCK
- struct flock lock;
- int request;
- static int lock_ops[] = {
- F_UNLCK, F_RDLCK, F_WRLCK
- };
- int ret;
+ /*
+ * fcntl() is standard and does more than we need, but we can handle
+ * it.
+ */
+#ifdef HAS_FCNTL_LOCK
+ case MYFLOCK_STYLE_FCNTL:
+ {
+ struct flock lock;
+ int request;
+ static int lock_ops[] = {
+ F_UNLCK, F_RDLCK, F_WRLCK
+ };
+ int ret;
- if ((how & (MYFLOCK_BITS)) != how)
- msg_panic("myflock: improper request type: %d", how);
- memset((char *) &lock, 0, sizeof(lock));
- lock.l_type = lock_ops[how & ~MYFLOCK_NOWAIT];
- request = (how & MYFLOCK_NOWAIT) ? F_SETLK : F_SETLKW;
- while ((ret = fcntl(fd, request, &lock)) < 0
- && request == F_SETLKW
- && (errno == EINTR || errno == ENOLCK || errno == EDEADLK))
- sleep(1);
- return (ret);
+ if ((operation & (MYFLOCK_OP_BITS)) != operation)
+ msg_panic("myflock: improper operation type: 0x%x", operation);
+ memset((char *) &lock, 0, sizeof(lock));
+ lock.l_type = lock_ops[operation & ~MYFLOCK_OP_NOWAIT];
+ request = (operation & MYFLOCK_OP_NOWAIT) ? F_SETLK : F_SETLKW;
+ while ((ret = fcntl(fd, request, &lock)) < 0
+ && request == F_SETLKW
+ && (errno == EINTR || errno == ENOLCK || errno == EDEADLK))
+ sleep(1);
+ return (ret);
+ }
#endif
+ default:
+ msg_panic("myflock: unsupported lock style: 0x%x", lock_style);
+ }
}
/* myflock_locked - were we locked out or what? */
/*
* External interface.
*/
-extern int myflock(int, int);
+extern int myflock(int, int, int);
extern int myflock_locked(int);
-#define MYFLOCK_NONE 0
-#define MYFLOCK_SHARED 1
-#define MYFLOCK_EXCLUSIVE 2
-#define MYFLOCK_LOCK_MASK (MYFLOCK_SHARED | MYFLOCK_EXCLUSIVE)
-#define MYFLOCK_NOWAIT 4
-#define MYFLOCK_BITS (MYFLOCK_LOCK_MASK | MYFLOCK_NOWAIT)
+ /*
+ * Lock styles.
+ */
+#define MYFLOCK_STYLE_FLOCK 1
+#define MYFLOCK_STYLE_FCNTL 2
+
+ /*
+ * Lock request types.
+ */
+#define MYFLOCK_OP_NONE 0
+#define MYFLOCK_OP_SHARED 1
+#define MYFLOCK_OP_EXCLUSIVE 2
+#define MYFLOCK_OP_NOWAIT 4
+#define MYFLOCK_OP_BITS \
+ (MYFLOCK_OP_SHARED | MYFLOCK_OP_EXCLUSIVE | MYFLOCK_OP_NOWAIT)
/* LICENSE
/* .ad
/* SYNOPSIS
/* #include <name_mask.h>
/*
-/* int name_mask(table, names)
+/* int name_mask(context, table, names)
+/* const char *context;
/* NAME_MASK *table;
/* const char *names;
+/*
+/* const char *str_name_mask(context, table, mask)
+/* const char *context;
+/* NAME_MASK *table;
+/* int mask;
/* DESCRIPTION
/* name_mask() takes a null-terminated \fItable\fR with (name, mask)
/* values and computes the bit-wise OR of the masks that correspond
/* to the names listed in the \fInames\fR argument, separated by
/* comma and/or whitespace characters.
+/*
+/* str_name_mask() translates a mask into its equivalent names.
+/* The result is written to a static buffer that is overwritten
+/* upon each call.
+/*
+/* The \fIcontext\fR argument specifies what kind of names and
+/* masks are being manipulated, in order to make error messages
+/* more understandable. Typically, this would be the name of a
+/* user-configurable parameter.
/* DIAGNOSTICS
/* Fatal: the \fInames\fR argument specifies a name not found in
/* \fItable\fR.
#include <mymalloc.h>
#include <stringops.h>
#include <name_mask.h>
+#include <vstring.h>
+
+#define STR(x) vstring_str(x)
/* name_mask - compute mask corresponding to list of names */
-int name_mask(NAME_MASK *table, const char *names)
+int name_mask(const char *context, NAME_MASK * table, const char *names)
{
char *myname = "name_mask";
char *saved_names = mystrdup(names);
while ((name = mystrtok(&bp, ", \t\r\n")) != 0) {
for (np = table; /* void */ ; np++) {
if (np->name == 0)
- msg_fatal("unknown name \"%s\" in \"%s\"", name, names);
+ msg_fatal("unknown %s value \"%s\" in \"%s\"",
+ context, name, names);
if (strcmp(name, np->name) == 0) {
if (msg_verbose)
msg_info("%s: %s", myname, name);
myfree(saved_names);
return (result);
}
+
+/* str_name_mask - mask to string */
+
+const char *str_name_mask(const char *context, NAME_MASK * table, int mask)
+{
+ char *myname = "name_mask";
+ NAME_MASK *np;
+ int len;
+ static VSTRING *buf = 0;
+
+ if (buf == 0)
+ buf = vstring_alloc(1);
+
+ VSTRING_RESET(buf);
+
+ for (np = table; mask != 0; np++) {
+ if (np->name == 0)
+ msg_panic("%s: invalid %s bitmask: 0x%x", myname, context, mask);
+ if (mask & np->mask) {
+ mask &= ~np->mask;
+ vstring_sprintf_append(buf, "%s ", np->name);
+ }
+ }
+ if ((len = VSTRING_LEN(buf)) > 0)
+ vstring_truncate(buf, len - 1);
+
+ return (STR(buf));
+}
+
+#ifdef TEST
+
+ /*
+ * Stand-alone test program.
+ */
+
+#include <vstream.h>
+
+int main(int argc, char **argv)
+{
+ static NAME_MASK table[] = {
+ "zero", 1 << 0,
+ "one", 1 << 1,
+ "two", 1 << 2,
+ "three", 1 << 3,
+ 0, 0,
+ };
+ int mask;
+ VSTRING *buf = vstring_alloc(1);
+
+ while (--argc && *++argv) {
+ mask = name_mask(table, *argv);
+ vstream_printf("%s -> 0x%x -> %s\n",
+ *argv, mask, str_name_mask(buf, table, mask));
+ vstream_fflush(VSTREAM_OUT);
+ }
+ vstring_free(buf);
+ exit(0);
+}
+
+#endif
int mask;
} NAME_MASK;
-extern int name_mask(NAME_MASK *, const char *);
+extern int name_mask(const char *, NAME_MASK *, const char *);
+extern const char *str_name_mask(const char *, NAME_MASK *, int);
/* LICENSE
/* .ad
* don't have the O_LOCK open() flag, or the flag does not do what we
* want, so we roll our own lock.
*/
- if ((fp = safe_open(path, flags, mode, -1, -1, why)) == 0)
+ if ((fp = safe_open(path, flags, mode, (struct stat *) 0, -1, -1, why)) == 0)
return (0);
- if (myflock(vstream_fileno(fp), MYFLOCK_EXCLUSIVE | MYFLOCK_NOWAIT) < 0) {
+ if (myflock(vstream_fileno(fp), INTERNAL_LOCK,
+ MYFLOCK_OP_EXCLUSIVE | MYFLOCK_OP_NOWAIT) < 0) {
vstring_sprintf(why, "file %s: unable to lock: %m", path);
vstream_fclose(fp);
return (0);
/* SYNOPSIS
/* #include <safe_open.h>
/*
-/* VSTREAM *safe_open(path, flags, mode, user, group, why)
+/* VSTREAM *safe_open(path, flags, mode, st, user, group, why)
/* const char *path;
/* int flags;
/* int mode;
+/* struct stat *st;
/* uid_t user;
/* gid_t group;
/* VSTRING *why;
/* safe_open() carefully opens or creates a file in a directory
/* that may be writable by untrusted users. If a file is created
/* it is given the specified ownership and permission attributes.
-/* If an existing file is opened it must be a regular file with
-/* only one hard link.
+/* If an existing file is opened it must not be a symbolic link,
+/* it must not be a directory, and it must have only one hard link.
/*
/* Arguments:
/* .IP "path, flags, mode"
/* must appear either in combination with O_CREAT, or not at all.
/* .sp
/* No change is made to the permissions of an existing file.
+/* .IP st
+/* Null pointer, or pointer to storage for the attributes of the
+/* opened file.
/* .IP "user, group"
/* File ownership for a file created by safe_open(). Specify -1
/* in order to disable user and/or group ownership change.
/* safe_open_exist - open existing file */
-static VSTREAM *safe_open_exist(const char *path, int flags, VSTRING *why)
+static VSTREAM *safe_open_exist(const char *path, int flags,
+ struct stat * fstat_st, VSTRING *why)
{
- struct stat fstat_st;
+ struct stat local_statbuf;
struct stat lstat_st;
VSTREAM *fp;
/*
* Examine the modes from the open file: it must have exactly one hard
* link (so that someone can't lure us into clobbering a sensitive file
- * by making a hard link to it), and it must be a regular file.
+ * by making a hard link to it), and it must be a non-symlink file.
*/
- if (fstat(vstream_fileno(fp), &fstat_st) < 0) {
- vstring_sprintf(why, "file %s: bad status: %m", path);
- } else if (S_ISREG(fstat_st.st_mode) == 0) {
- vstring_sprintf(why, "file %s: must be a regular file", path);
- } else if (fstat_st.st_nlink != 1) {
- vstring_sprintf(why, "file %s: must have one hard link", path);
+ if (fstat_st == 0)
+ fstat_st = &local_statbuf;
+ if (fstat(vstream_fileno(fp), fstat_st) < 0) {
+ msg_fatal("file %s: bad status after open: %m", path);
+ } else if (fstat_st->st_nlink != 1) {
+ vstring_sprintf(why, "file %s: should not have multiple links", path);
+ } else if (S_ISDIR(fstat_st->st_mode)) {
+ vstring_sprintf(why, "file %s: should not be a directory", path);
}
/*
* on systems that have one.
*/
else if (lstat(path, &lstat_st) < 0
- || fstat_st.st_dev != lstat_st.st_dev
- || fstat_st.st_ino != lstat_st.st_ino
+ || fstat_st->st_dev != lstat_st.st_dev
+ || fstat_st->st_ino != lstat_st.st_ino
#ifdef HAS_ST_GEN
- || fstat_st.st_gen != lstat_st.st_gen
+ || fstat_st->st_gen != lstat_st.st_gen
#endif
- || fstat_st.st_nlink != lstat_st.st_nlink
- || fstat_st.st_mode != lstat_st.st_mode) {
- vstring_sprintf(why, "file %s: status has changed", path);
+ || fstat_st->st_nlink != lstat_st.st_nlink
+ || fstat_st->st_mode != lstat_st.st_mode) {
+ vstring_sprintf(why, "file %s: %s", path, S_ISLNK(lstat_st.st_mode) ?
+ "should not be a symbolic link" : "status changed after opening");
}
/*
/* safe_open_create - create new file */
static VSTREAM *safe_open_create(const char *path, int flags, int mode,
- uid_t user, uid_t group, VSTRING *why)
+ struct stat * st, uid_t user, uid_t group, VSTRING *why)
{
VSTREAM *fp;
* follow symbolic links.
*/
if ((fp = vstream_fopen(path, flags | (O_CREAT | O_EXCL), mode)) == 0) {
- vstring_sprintf(why, "error opening file %s: %m", path);
+ vstring_sprintf(why, "file %s: cannot open: %m", path);
return (0);
}
if (CHANGE_OWNER(user, group)
&& fchown(vstream_fileno(fp), user, group) < 0) {
- vstring_sprintf(why, "error changing ownership of %s: %m", path);
+ vstring_sprintf(why, "file %s: cannot change ownership: %m", path);
}
+ /*
+ * Optionally look up the file attributes.
+ */
+ if (st != 0 && fstat(vstream_fileno(fp), st) < 0)
+ msg_fatal("file %s: cannot get status after open: %m", path);
+
/*
* We are almost there...
*/
/* safe_open - safely open or create file */
VSTREAM *safe_open(const char *path, int flags, int mode,
- uid_t user, gid_t group, VSTRING *why)
+ struct stat * st, uid_t user, gid_t group, VSTRING *why)
{
VSTREAM *fp;
* Open an existing file, carefully.
*/
case 0:
- return (safe_open_exist(path, flags, why));
+ return (safe_open_exist(path, flags, st, why));
/*
* Create a new file, carefully.
*/
case O_CREAT | O_EXCL:
- return (safe_open_create(path, flags, mode, user, group, why));
+ return (safe_open_create(path, flags, mode, st, user, group, why));
/*
* Open an existing file or create a new one, carefully. When opening
* only. Any other error means we better give up trying.
*/
case O_CREAT:
- if ((fp = safe_open_exist(path, flags, why)) == 0)
+ if ((fp = safe_open_exist(path, flags, st, why)) == 0)
if (errno == ENOENT)
- fp = safe_open_create(path, flags, mode, user, group, why);
+ fp = safe_open_create(path, flags, mode, st, user, group, why);
return (fp);
/*
/*
* System library.
*/
+#include <sys/stat.h>
#include <fcntl.h>
/*
/*
* External interface.
*/
-extern VSTREAM *safe_open(const char *, int, int, uid_t, gid_t, VSTRING *);
+extern VSTREAM *safe_open(const char *, int, int, struct stat *, uid_t, gid_t, VSTRING *);
/* LICENSE
/* .ad
#include <sys_defs.h>
#include <unistd.h>
#include <grp.h>
+#include <errno.h>
/* Utility library. */
void set_eugid(uid_t euid, gid_t egid)
{
+ int saved_errno = errno;
+
if (geteuid() != 0)
if (seteuid(0))
msg_fatal("set_eugid: seteuid(0): %m");
msg_fatal("set_eugid: seteuid(%ld): %m", (long) euid);
if (msg_verbose)
msg_info("set_eugid: euid %ld egid %ld", (long) euid, (long) egid);
+ errno = saved_errno;
}
#include <sys_defs.h>
#include <unistd.h>
#include <grp.h>
+#include <errno.h>
/* Utility library. */
void set_ugid(uid_t uid, gid_t gid)
{
+ int saved_errno = errno;
+
if (geteuid() != 0)
if (seteuid(0) < 0)
msg_fatal("seteuid(0): %m");
msg_fatal("setuid(%ld): %m", (long) uid);
if (msg_verbose > 1)
msg_info("setugid: uid %ld gid %ld", (long) uid, (long) gid);
+ errno = saved_errno;
}
* directory. Adding support for a new system type means updating the
* makedefs script, and adding a section below for the new system.
*/
+
+ /*
+ * 4.4BSD and close derivatives.
+ */
#if defined(FREEBSD2) || defined(FREEBSD3) || defined(FREEBSD4) \
|| defined(FREEBSD5) \
|| defined(BSDI2) || defined(BSDI3) || defined(BSDI4) \
#include <sys/types.h>
#include <sys/param.h>
#define USE_PATHS_H
-#define USE_FLOCK_LOCK
+#define HAS_FLOCK_LOCK
+#define HAS_FCNTL_LOCK
+#define INTERNAL_LOCK MYFLOCK_STYLE_FLOCK
#define HAS_SUN_LEN
#define HAS_FSYNC
#define HAS_DB
#endif
#if defined(NETBSD1)
-#define USE_DOT_LOCK
+#define DEF_MAILBOX_LOCK "flock, dotlock"
#endif
+#ifndef DEF_MAILBOX_LOCK
+#define DEF_MAILBOX_LOCK "flock"
+#endif
+
+ /*
+ * UNIX on MAC.
+ */
#if defined(RHAPSODY5) || defined(MACOSX)
#define SUPPORTED
#include <sys/types.h>
#define USE_PATHS_H
-#define USE_FLOCK_LOCK
+#define HAS_FLOCK_LOCK
+#define HAS_FCNTL_LOCK
+#define INTERNAL_LOCK MYFLOCK_STYLE_FLOCK
+#define DEF_MAILBOX_LOCK "flock"
#define HAS_SUN_LEN
#define HAS_FSYNC
#define HAS_DB
#define HAS_NETINFO
#endif
+ /*
+ * Ultrix 4.x, a sort of 4.[1-2] BSD system with System V.2 compatibility
+ * and POSIX.
+ */
#ifdef ULTRIX4
#define SUPPORTED
/* Ultrix by default has only 64 descriptors per process */
#define _PATH_BSHELL "/bin/sh"
#define _PATH_DEFPATH "/bin:/usr/bin:/usr/ucb"
#define _PATH_STDPATH "/bin:/usr/bin:/usr/etc:/usr/ucb"
-#define USE_FLOCK_LOCK
-#define USE_DOT_LOCK
+#define HAS_FLOCK_LOCK
+#define HAS_FCNTL_LOCK
+#define INTERNAL_LOCK MYFLOCK_STYLE_FLOCK
+#define DEF_MAILBOX_LOCK "flock, dotlock"
#define HAS_FSYNC
/* might be set by makedef */
#ifdef HAS_DB
#define NO_HERRNO
#endif
+ /*
+ * OSF, then Digital UNIX, then Compaq. A BSD-flavored hybrid.
+ */
#ifdef OSF1
#define SUPPORTED
#include <sys/types.h>
#define MISSING_SETENV
#define USE_PATHS_H
#define _PATH_DEFPATH "/usr/bin:/usr/ucb"
-#define USE_FLOCK_LOCK
-#define USE_DOT_LOCK
+#define HAS_FLOCK_LOCK
+#define HAS_FCNTL_LOCK
+#define INTERNAL_LOCK MYFLOCK_STYLE_FLOCK
+#define DEF_MAILBOX_LOCK "flock, dotlock"
#define HAS_FSYNC
#define HAVE_BASENAME
#define HAS_DBM
#define HAS_POSIX_REGEXP
#endif
+ /*
+ * SunOS 4.x, a mostly 4.[2-3] BSD system with System V.2 compatibility and
+ * POSIX support.
+ */
#ifdef SUNOS4
#define SUPPORTED
#include <sys/types.h>
#define _PATH_BSHELL "/bin/sh"
#define _PATH_DEFPATH "/usr/bin:/usr/ucb"
#define _PATH_STDPATH "/usr/bin:/usr/etc:/usr/ucb"
-#define USE_FLOCK_LOCK
-#define USE_DOT_LOCK
+#define HAS_FLOCK_LOCK
+#define HAS_FCNTL_LOCK
+#define INTERNAL_LOCK MYFLOCK_STYLE_FLOCK
+#define DEF_MAILBOX_LOCK "flock, dotlock"
#define HAS_FSYNC
#define HAS_DBM
#define DEF_DB_TYPE "dbm"
#define NO_HERRNO
#endif
+ /*
+ * SunOS 5.x, mostly System V Release 4.
+ */
#ifdef SUNOS5
#define SUPPORTED
#define _SVID_GETTOD /* Solaris 2.5, XSH4.2 versus SVID */
#define _PATH_BSHELL "/bin/sh"
#define _PATH_DEFPATH "/usr/bin:/usr/ucb"
#define _PATH_STDPATH "/usr/bin:/usr/sbin:/usr/ucb"
-#define USE_FCNTL_LOCK
-#define USE_DOT_LOCK
+#define HAS_FCNTL_LOCK
+#define INTERNAL_LOCK MYFLOCK_STYLE_FCNTL
+#define DEF_MAILBOX_LOCK "fcntl, dotlock"
#define HAS_FSYNC
#define HAS_DBM
#define DEF_DB_TYPE "dbm"
#define HAS_VOLATILE_LOCKS
#endif
+ /*
+ * UnixWare, System Release 4.
+ */
#ifdef UW7 /* UnixWare 7 */
#define SUPPORTED
#include <sys/types.h>
#define _PATH_DEFPATH "/usr/bin:/usr/ucb"
#define _PATH_STDPATH "/usr/bin:/usr/sbin:/usr/ucb"
#define MISSING_SETENV
-#define USE_FCNTL_LOCK
-#define USE_DOT_LOCK
+#define HAS_FCNTL_LOCK
+#define INTERNAL_LOCK MYFLOCK_STYLE_FCNTL
+#define DEF_MAILBOX_LOCK "fcntl, dotlock"
#define HAS_FSYNC
#define HAS_DBM
#define DEF_DB_TYPE "dbm"
#define _PATH_DEFPATH "/usr/bin:/usr/ucb"
#define _PATH_STDPATH "/usr/bin:/usr/sbin:/usr/ucb"
#define MISSING_SETENV
-#define USE_FCNTL_LOCK
-#define USE_DOT_LOCK
+#define HAS_FCNTL_LOCK
+#define INTERNAL_LOCK MYFLOCK_STYLE_FCNTL
+#define DEF_MAILBOX_LOCK "fcntl, dotlock"
#define HAS_FSYNC
#define HAS_DBM
#define DEF_DB_TYPE "dbm"
#define UNIX_DOMAIN_CONNECT_BLOCKS_FOR_ACCEPT
#endif
+ /*
+ * AIX: a SYSV-flavored hybrid. NB: fcntl() and flock() access the same
+ * underlying locking primitives.
+ */
#ifdef AIX4
#define SUPPORTED
#include <sys/types.h>
#define _PATH_MAILDIR "/var/spool/mail" /* paths.h lies */
#define _PATH_DEFPATH "/usr/bin:/usr/ucb"
#define _PATH_STDPATH "/usr/bin:/usr/sbin:/usr/ucb"
-#define USE_FCNTL_LOCK
-#define USE_DOT_LOCK
+#define HAS_FCNTL_LOCK
+#define INTERNAL_LOCK MYFLOCK_STYLE_FCNTL
+#define DEF_MAILBOX_LOCK "fcntl, dotlock"
#define USE_SYS_SELECT_H
#define HAS_FSYNC
#define HAS_DBM
#define _PATH_MAILDIR "/var/spool/mail" /* paths.h lies */
#define _PATH_DEFPATH "/usr/bin:/usr/ucb"
#define _PATH_STDPATH "/usr/bin:/usr/sbin:/usr/ucb"
-#define USE_FCNTL_LOCK
-#define USE_DOT_LOCK
+#define HAS_FCNTL_LOCK
+#define INTERNAL_LOCK MYFLOCK_STYLE_FCNTL
+#define DEF_MAILBOX_LOCK "fcntl, dotlock"
#define USE_SYS_SELECT_H
#define HAS_FSYNC
#define HAS_DBM
#endif
+ /*
+ * IRIX, a mix of System V Releases.
+ */
#if defined(IRIX5) || defined(IRIX6)
#define SUPPORTED
#include <sys/types.h>
#define _PATH_BSHELL "/bin/sh"
#define _PATH_DEFPATH "/usr/bin:/usr/bsd"
#define _PATH_STDPATH "/usr/bin:/usr/sbin:/usr/bsd"
-#define USE_FCNTL_LOCK
-#define USE_DOT_LOCK
+#define HAS_FCNTL_LOCK
+#define INTERNAL_LOCK MYFLOCK_STYLE_FCNTL
+#define DEF_MAILBOX_LOCK "fcntl, dotlock"
#define HAS_FSYNC
#define HAS_DBM
#define DEF_DB_TYPE "dbm"
#define MISSING_USLEEP
#endif
+ /*
+ * LINUX.
+ */
#ifdef LINUX2
#define SUPPORTED
#include <sys/types.h>
#define USE_PATHS_H
-#define USE_FLOCK_LOCK
-#define USE_DOT_LOCK
+#define HAS_FLOCK_LOCK
+#define HAS_FCNTL_LOCK
+#define INTERNAL_LOCK MYFLOCK_STYLE_FLOCK
+#define DEF_MAILBOX_LOCK "flock, dotlock"
#define HAS_FSYNC
#define HAS_DB
#define DEF_DB_TYPE "hash"
#define USE_SIG_RETURN
#include <sys/types.h>
#define HAS_DBM
-#define USE_FCNTL_LOCK
+#define HAS_FCNTL_LOCK
+#define INTERNAL_LOCK MYFLOCK_STYLE_FCNTL
+#define DEF_MAILBOX_LOCK "fcntl, dotlock"
#define HAS_FSYNC
#define DEF_DB_TYPE "dbm"
#define ALIAS_DB_MAP "dbm:/etc/mail/aliases"
#define USE_SIG_RETURN
#include <sys/types.h>
#define HAS_DBM
-#define USE_FCNTL_LOCK
+#define HAS_FCNTL_LOCK
+#define INTERNAL_LOCK MYFLOCK_STYLE_FCNTL
+#define DEF_MAILBOX_LOCK "fcntl, dotlock"
#define HAS_FSYNC
#define DEF_DB_TYPE "dbm"
#define ALIAS_DB_MAP "dbm:/etc/mail/aliases"
#define USE_SIG_RETURN
#include <sys/types.h>
#define HAS_DBM
-#define USE_FCNTL_LOCK
+#define HAS_FCNTL_LOCK
+#define INTERNAL_LOCK MYFLOCK_STYLE_FCNTL
+#define DEF_MAILBOX_LOCK "fcntl, dotlock"
#define HAS_FSYNC
#define HAS_NIS
#define MISSING_SETENV
#define SUPPORTED
#include <sys/types.h>
#define HAS_DBM
-#define USE_FLOCK_LOCK
+#define HAS_FLOCK_LOCK
+#define INTERNAL_LOCK MYFLOCK_STYLE_FLOCK
+#define DEF_MAILBOX_LOCK "flock, dotlock"
#define USE_STATFS
#define HAVE_SYS_DIR_H
#define STATFS_IN_SYS_VFS_H
#define SUPPORTED
#include <sys/types.h>
#define HAS_DBM
-#define USE_FLOCK_LOCK
+#define HAS_FLOCK_LOCK
+#define INTERNAL_LOCK MYFLOCK_STYLE_FLOCK
+#define DEF_MAILBOX_LOCK "flock, dotlock"
#define USE_STATFS
#define HAVE_SYS_DIR_H
#define STATFS_IN_SYS_VFS_H
#define _PATH_DEFPATH "/usr/bin:/usr/ucb"
#define _PATH_BSHELL "/bin/sh"
#define _PATH_MAILDIR "/var/spool/mail"
-#define USE_FCNTL_LOCK
-#define USE_DOT_LOCK
+#define HAS_FCNTL_LOCK
+#define INTERNAL_LOCK MYFLOCK_STYLE_FCNTL
+#define DEF_MAILBOX_LOCK "fcntl, dotlock"
#define HAS_FSYNC
#define FIONREAD_IN_SYS_FILIO_H
#define USE_SYS_SOCKIO_H
#define _PATH_DEFPATH "/usr/bin:/usr/ucb"
#define _PATH_STDPATH "/usr/bin:/usr/sbin:/usr/ucb"
#define MISSING_SETENV
-#define USE_FCNTL_LOCK
-#define USE_DOT_LOCK
+#define HAS_FCNTL_LOCK
+#define INTERNAL_LOCK MYFLOCK_STYLE_FCNTL
+#define DEF_MAILBOX_LOCK "fcntl, dotlock"
#define HAS_FSYNC
#define DEF_DB_TYPE "hash"
#define ALIAS_DB_MAP "hash:/etc/aliases"
#define _PATH_BSHELL "/bin/sh"
#define _PATH_DEFPATH "/bin:/usr/bin"
#define USE_PATHS_H
-#define USE_FCNTL_LOCK
-#define USE_DOT_LOCK
+#define HAS_FCNTL_LOCK
+#define INTERNAL_LOCK MYFLOCK_STYLE_FCNTL
+#define DEF_MAILBOX_LOCK "fcntl, dotlock"
#define HAS_FSYNC
#define HAS_DBM
#define DEF_DB_TYPE "dbm"
#endif
#define OPTIND (optind > 0 ? optind : 1)
-#if defined(USE_FCNTL_LOCK) && defined(USE_FLOCK_LOCK)
-#error "define USE_FCNTL_LOCK or USE_FLOCK_LOCK, not both"
+#if !defined(HAS_FCNTL_LOCK) && !defined(HAS_FLOCK_LOCK)
+#error "define HAS_FCNTL_LOCK and/or HAS_FLOCK_LOCK"
+#endif
+
+#if !defined(DEF_MAILBOX_LOCK)
+#error "define DEF_MAILBOX_LOCK"
#endif
-#if !defined(USE_FCNTL_LOCK) && !defined(USE_FLOCK_LOCK)
-#error "define USE_FCNTL_LOCK or USE_FLOCK_LOCK"
+#if !defined(INTERNAL_LOCK)
+#error "define INTERNAL_LOCK"
#endif
#if defined(USE_STATFS) && defined(USE_STATVFS)