]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
snapshot-20001126
authorWietse Venema <wietse@porcupine.org>
Sun, 26 Nov 2000 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <viktor@dukhovni.org>
Tue, 5 Feb 2013 06:26:56 +0000 (06:26 +0000)
64 files changed:
postfix/HISTORY
postfix/RELEASE_NOTES
postfix/conf/aliases
postfix/html/aliases.5.html
postfix/html/local.8.html
postfix/html/postconf.1.html
postfix/html/postlock.1.html
postfix/man/man1/postconf.1
postfix/man/man1/postlock.1
postfix/man/man5/aliases.5
postfix/man/man8/local.8
postfix/proto/aliases
postfix/src/bounce/Makefile.in
postfix/src/bounce/bounce_append_service.c
postfix/src/bounce/bounce_notify_service.c
postfix/src/flush/flush.c
postfix/src/global/Makefile.in
postfix/src/global/deliver_flock.c
postfix/src/global/deliver_flock.h
postfix/src/global/deliver_request.c
postfix/src/global/dot_lockfile.c
postfix/src/global/ext_prop.c
postfix/src/global/mail_conf.h
postfix/src/global/mail_params.c
postfix/src/global/mail_params.h
postfix/src/global/mail_version.h
postfix/src/global/mbox_conf.c [new file with mode: 0644]
postfix/src/global/mbox_conf.h [new file with mode: 0644]
postfix/src/global/mbox_open.c [new file with mode: 0644]
postfix/src/global/mbox_open.h [new file with mode: 0644]
postfix/src/global/mkmap_open.c
postfix/src/lmtp/lmtp.c
postfix/src/local/Makefile.in
postfix/src/local/file.c
postfix/src/local/local.c
postfix/src/local/local.h
postfix/src/local/mailbox.c
postfix/src/master/master.c
postfix/src/master/multi_server.c
postfix/src/master/single_server.c
postfix/src/master/trigger_server.c
postfix/src/nqmgr/qmgr_message.c
postfix/src/postconf/Makefile.in
postfix/src/postconf/postconf.c
postfix/src/postlock/Makefile.in
postfix/src/postlock/postlock.c
postfix/src/qmgr/qmgr_message.c
postfix/src/smtp/smtp.c
postfix/src/smtp/smtp_sasl_glue.c
postfix/src/smtpd/smtpd_state.c
postfix/src/util/Makefile.in
postfix/src/util/argv.c
postfix/src/util/dict_db.c
postfix/src/util/dict_dbm.c
postfix/src/util/myflock.c
postfix/src/util/myflock.h
postfix/src/util/name_mask.c
postfix/src/util/name_mask.h
postfix/src/util/open_lock.c
postfix/src/util/safe_open.c
postfix/src/util/safe_open.h
postfix/src/util/set_eugid.c
postfix/src/util/set_ugid.c
postfix/src/util/sys_defs.h

index f54f46ded9b644f9afebf213ded5f779c17a5a4d..1125197cb3aac0627a02e81e5d433b33521c05ed 100644 (file)
@@ -4522,3 +4522,19 @@ Apologies for any names omitted.
        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.
index 3ee7d1a1ab9f68795dfd41aff4d994bbe54c0c57..582a8ceaa2c9352adf1468b6a5af20c4cd98d069 100644 (file)
@@ -1,3 +1,21 @@
+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
 ===========================================
 
index 9e36acefc56f97c69b1b8306a0c7961393e16e6b..a836b8700c5ec51c7c32b49fff1089616ef4e5f5 100644 (file)
@@ -154,12 +154,18 @@ decode:           root
 #               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
@@ -170,7 +176,7 @@ decode:             root
 #        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)
index 8eef3755058c4d5917b9a653ac618dd94fd64d23..50b5aaa3f91b2870c34c2f49a72f55fc4aff957f 100644 (file)
@@ -141,12 +141,18 @@ ALIASES(5)                                             ALIASES(5)
               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>
@@ -157,7 +163,7 @@ ALIASES(5)                                             ALIASES(5)
        <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>
@@ -181,12 +187,6 @@ ALIASES(5)                                             ALIASES(5)
 
 
 
-
-
-
-
-
-
 
 
 
index 2eb0be78678568e005129d2fa0669057d647d02a..fabb9c4baf3563946e0340c9e188a03aa44bac41 100644 (file)
@@ -417,44 +417,44 @@ LOCAL(8)                                                 LOCAL(8)
        <b>stale</b><i>_</i><b>lock</b><i>_</i><b>time</b>
               Limit the time after which a stale lock is removed.
 
+       <b>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.
-
-
 
 
 
@@ -467,20 +467,25 @@ LOCAL(8)                                                 LOCAL(8)
 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>
@@ -491,7 +496,7 @@ LOCAL(8)                                                 LOCAL(8)
        <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>
@@ -514,11 +519,6 @@ LOCAL(8)                                                 LOCAL(8)
 
 
 
-
-
-
-
-
 
 
 
index 294544500b4126a34ed31b4322aaec6863c40902..042956fa72250038db3aba73be5bcc9d67e5c6ac 100644 (file)
@@ -9,7 +9,7 @@ POSTCONF(1)                                           POSTCONF(1)
        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>]
 
@@ -40,29 +40,95 @@ POSTCONF(1)                                           POSTCONF(1)
 
        <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>
index 1a7b5356de69421e1e9778522dee6ad60616a4e2..8cc19092f14a9e72c9d1b888f0b6d2a0a0b4ab35 100644 (file)
@@ -9,56 +9,56 @@ POSTLOCK(1)                                           POSTLOCK(1)
        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
 
 
 
@@ -71,21 +71,32 @@ POSTLOCK(1)                                           POSTLOCK(1)
 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-
@@ -113,17 +124,6 @@ POSTLOCK(1)                                           POSTLOCK(1)
 
 
 
-
-
-
-
-
-
-
-
-
-
-
 
 
 
index babab721a2f9c8635300abf60df3bb65acadf335..eabc01bfecc0826e143b68609fbcc8101495037e 100644 (file)
@@ -9,7 +9,7 @@ Postfix configuration utility
 .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]
@@ -38,6 +38,8 @@ Show parameter values only, not the ``name = '' label
 that normally precedes the value.
 .IP \fB-m\fR
 List the names of all supported lookup table types.
+.IP \fB-l\fR
+List the names of all supported mailbox locking methods.
 .IP \fB-n\fR
 Print non-default parameter settings only.
 .IP \fB-v\fR
index 6cec0621cc63cf10560f9e278440d4a2497b93ef..decf75b940836f7c5e5ae324b1e0fe05d935cda5 100644 (file)
@@ -9,8 +9,8 @@ lock mail folder and execute command
 .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
@@ -22,6 +22,9 @@ Options:
 .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.
@@ -36,8 +39,7 @@ interpretation by a shell command interpreter.
 .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
@@ -73,6 +75,11 @@ Time in seconds between successive attempts to acquire
 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
index 49edca84304fe441ac2e1ef6197e9db6b1149824..8eab116ac018d4a683a70d26833bd511129cab48 100644 (file)
@@ -107,6 +107,10 @@ List of alias databases.
 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.
index 67fc0ee056d5a76d1e09a4e3e044ddc0202fb848..d7a9450dc607acdaaa81e461d586e129086d427b 100644 (file)
@@ -348,6 +348,11 @@ Time in seconds between successive attempts to acquire
 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
index cc9680b01b1b643086015f1d4eb1c012f9ce5db2..a8b4209589a5a165220fcc9c4ea12d6fd99f815d 100644 (file)
 #      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.
index 6557cf0e5f0975bfbee77e393b659805ba01d95d..4172afd76ce0eeaa1a215b9cd3973a1d797b1cf7 100644 (file)
@@ -82,6 +82,7 @@ bounce_append_service.o: ../../include/stringops.h
 bounce_append_service.o: ../../include/mail_queue.h
 bounce_append_service.o: ../../include/quote_822_local.h
 bounce_append_service.o: ../../include/deliver_flock.h
+bounce_append_service.o: ../../include/myflock.h
 bounce_append_service.o: bounce_service.h
 bounce_append_service.o: ../../include/bounce_log.h
 bounce_cleanup.o: bounce_cleanup.c
index 36e6138916c0d354c42773ce84890c4d81427c1e..09a2d87f1f9c6a2ce46dbd4d5255e1202dc6696b 100644 (file)
@@ -82,7 +82,7 @@ int     bounce_append_service(char *service, char *queue_id,
      * Lock out other processes to avoid truncating someone else's data in
      * case of trouble.
      */
-    if (deliver_flock(vstream_fileno(log), (VSTRING *) 0) < 0)
+    if (deliver_flock(vstream_fileno(log), INTERNAL_LOCK, (VSTRING *) 0) < 0)
        msg_fatal("lock file  %s %s: %m", service, queue_id);
 
     /*
index 4f668841d64761cf709dbf0730d5b5e5b88d8d40..35e10a45cb9ff74a5176deed7546fc6caf6ab4ee 100644 (file)
@@ -84,7 +84,8 @@ int     bounce_notify_service(char *service, char *queue_name,
     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;
 
     /*
@@ -162,8 +163,8 @@ int     bounce_notify_service(char *service, char *queue_name,
      */
     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
index cca42d38a2abb7a8940cd36245af642a4c0cdf09..8f284a0d946552ebfa92094541292bb978fea167 100644 (file)
@@ -222,7 +222,7 @@ static int flush_add_service(const char *site, const char *queue_id)
      * 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);
 
     /*
@@ -236,7 +236,7 @@ static int flush_add_service(const char *site, const char *queue_id)
     /*
      * 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)
@@ -286,7 +286,7 @@ static int flush_send_service(const char *site)
      * 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);
 
     /*
@@ -361,7 +361,7 @@ static int flush_send_service(const char *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)
index 084e664a8fdab11c9c1e144934d548d7a09203c0..cd6e5ed3d60866f6f1390b9feeb3777a61b50b5e 100644 (file)
@@ -18,7 +18,7 @@ SRCS  = been_here.c bounce.c canon_addr.c cleanup_strerror.c clnt_stream.c \
        sent.c smtp_stream.c split_addr.c string_list.c sys_exits.c \
        timed_ipc.c tok822_find.c tok822_node.c tok822_parse.c \
        tok822_resolve.c tok822_rewrite.c tok822_tree.c 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 \
@@ -38,7 +38,7 @@ OBJS  = been_here.o bounce.o canon_addr.o cleanup_strerror.o clnt_stream.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 \
@@ -53,7 +53,8 @@ HDRS  = been_here.h bounce.h canon_addr.h cleanup_user.h clnt_stream.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 \
@@ -385,6 +386,7 @@ dot_lockfile_as.o: dot_lockfile_as.h
 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
@@ -701,6 +703,25 @@ mark_corrupt.o: ../../include/vbuf.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
index 5df58ada3d9bdf4a1fcf4c751c6d1ed6ca54e6be..ca7a6afff39a2afda12752cd8848f46b06b92764 100644 (file)
@@ -6,8 +6,9 @@
 /* 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
@@ -17,6 +18,8 @@
 /*     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);
 }
index 6bb2bdcebeb9f1d7af8270cf53eadb74a41b5828..f167725bdd7b19c9a92c80668463a5c850fddccb 100644 (file)
  /*
   * 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
index fee68b991942e78115e7514a9b8cd81d0af3b898..63c20c4fee45146e2dac36e40fb73414143a1d97 100644 (file)
@@ -226,7 +226,7 @@ static int deliver_request_get(VSTREAM *stream, DELIVER_REQUEST *request)
      * 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);
@@ -234,7 +234,7 @@ static int deliver_request_get(VSTREAM *stream, DELIVER_REQUEST *request)
        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);
 
index 6921298d8ce229473804e930a5626f7f6d4bc243..41ffd4267f49ef977e46aaa666a89d419bd6ccd7 100644 (file)
@@ -19,7 +19,8 @@
 /*     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
@@ -75,11 +81,7 @@ int     dot_lockfile(const char *path, VSTRING *why)
 
     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
@@ -90,6 +92,8 @@ int     dot_lockfile(const char *path, VSTRING *why)
            status = 0;
            break;
        }
+       if (count >= var_flock_tries)
+           break;
 
        /*
         * We can deal only with "file exists" errors. Any other error means
@@ -107,7 +111,8 @@ int     dot_lockfile(const char *path, VSTRING *why)
                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);
@@ -121,10 +126,12 @@ int     dot_lockfile(const char *path, VSTRING *why)
 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
index 41fa8f0e15709d55250db76f1a035886c77ba7c1..ebdc8f2716f6325e89d3ba168df99baa3fd8fd7c 100644 (file)
@@ -53,6 +53,7 @@
 
 /* Global library. */
 
+#include <mail_params.h>
 #include <ext_prop.h>
 
 /* ext_prop_mask - compute extension propagation mask */
@@ -68,5 +69,5 @@ int     ext_prop_mask(const char *pattern)
        0,
     };
 
-    return (name_mask(table, pattern));
+    return (name_mask(VAR_PROP_EXTENSION, table, pattern));
 }
index 60bd859e220600bf0a58b675d65904e8164f0512..5ebf43d700659f48ee594fdb3b208f69d081fc0a 100644 (file)
@@ -46,6 +46,7 @@ extern const char *mail_conf_lookup_eval(const char *);
 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);
 
@@ -58,6 +59,7 @@ extern int get_mail_conf_time2(const char *, const char *, const char *, int, in
 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);
 
@@ -67,6 +69,7 @@ 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 *);
 
  /*
@@ -95,6 +98,12 @@ typedef struct {
     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 */
@@ -107,6 +116,7 @@ typedef struct {
 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 *);
 
@@ -136,6 +146,12 @@ typedef struct {
     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 */
@@ -148,6 +164,7 @@ typedef struct {
 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 *);
 
index ea70c598f8304bfae416247ff64f88802e95114c..df1ca9363516094b166b054cc36e6e7c0f1af035 100644 (file)
@@ -51,7 +51,6 @@
 /*     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;
@@ -159,7 +158,6 @@ int     var_fork_delay;
 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;
@@ -308,7 +306,6 @@ void    mail_params_init()
        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,
     };
 
index e2ffa5d53206ef6f58cc6fe869e71c393b519276..4476010cb39039da1ed86908a90dbc0d48cc0e05 100644 (file)
@@ -365,6 +365,15 @@ extern char *var_fallback_transport;
 #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;
index 852072839c3b2d67774f27f3f28bb37dbb6fb62d..e0067e4afdbf643927bbfc4e2237fb299d66c846 100644 (file)
@@ -15,7 +15,7 @@
   * 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
diff --git a/postfix/src/global/mbox_conf.c b/postfix/src/global/mbox_conf.c
new file mode 100644 (file)
index 0000000..ba3b0cd
--- /dev/null
@@ -0,0 +1,97 @@
+/*++
+/* 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);
+}
diff --git a/postfix/src/global/mbox_conf.h b/postfix/src/global/mbox_conf.h
new file mode 100644 (file)
index 0000000..46e447b
--- /dev/null
@@ -0,0 +1,41 @@
+#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
diff --git a/postfix/src/global/mbox_open.c b/postfix/src/global/mbox_open.c
new file mode 100644 (file)
index 0000000..3647448
--- /dev/null
@@ -0,0 +1,137 @@
+/*++
+/* 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);
+}
diff --git a/postfix/src/global/mbox_open.h b/postfix/src/global/mbox_open.h
new file mode 100644 (file)
index 0000000..7e98772
--- /dev/null
@@ -0,0 +1,38 @@
+#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
index 899c0b65ad2af948106cc3f2a817f9e14766b45b..ad7a903cb4352562af47b4ca81bc5cd8443866df 100644 (file)
@@ -148,7 +148,7 @@ MKMAP  *mkmap_open(const char *type, const char *path,
      * 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);
 
     /*
index 6dd99c6855473522b4debcf0c84f47d4436c6af9..ae11338c5ecd955b04fef4fe49cb5c3f1e703858 100644 (file)
@@ -368,7 +368,8 @@ static int deliver_message(DELIVER_REQUEST *request, char **unused_argv)
      * 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);
 
     /*
@@ -390,7 +391,7 @@ static int deliver_message(DELIVER_REQUEST *request, char **unused_argv)
 
 /* 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;
index 76e5fd2a8b9fc31dd3fae80285fb476210c12905..826c7e102fca4b5fcb30a3983438d45306d6d23f 100644 (file)
@@ -85,6 +85,7 @@ alias.o: ../../include/tok822.h
 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
@@ -109,6 +110,7 @@ command.o: ../../include/tok822.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
@@ -122,6 +124,8 @@ deliver_attr.o: ../../include/tok822.h
 deliver_attr.o: ../../include/resolve_clnt.h
 deliver_attr.o: ../../include/deliver_request.h
 deliver_attr.o: ../../include/recipient_list.h
+deliver_attr.o: ../../include/mbox_conf.h
+deliver_attr.o: ../../include/argv.h
 delivered.o: delivered.c
 delivered.o: ../../include/sys_defs.h
 delivered.o: ../../include/msg.h
@@ -142,6 +146,8 @@ delivered.o: ../../include/tok822.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
@@ -167,6 +173,8 @@ dotforward.o: ../../include/tok822.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
@@ -175,14 +183,18 @@ file.o: ../../include/vstring.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
@@ -214,6 +226,7 @@ forward.o: ../../include/tok822.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
@@ -236,6 +249,8 @@ include.o: ../../include/tok822.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
@@ -252,6 +267,8 @@ indirect.o: ../../include/tok822.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
@@ -277,6 +294,7 @@ local.o: ../../include/mail_server.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
@@ -292,6 +310,8 @@ local_expand.o: ../../include/tok822.h
 local_expand.o: ../../include/resolve_clnt.h
 local_expand.o: ../../include/deliver_request.h
 local_expand.o: ../../include/recipient_list.h
+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
@@ -305,6 +325,8 @@ mailbox.o: ../../include/set_eugid.h
 mailbox.o: ../../include/mail_copy.h
 mailbox.o: ../../include/safe_open.h
 mailbox.o: ../../include/deliver_flock.h
+mailbox.o: ../../include/myflock.h
+mailbox.o: ../../include/dot_lockfile.h
 mailbox.o: ../../include/defer.h
 mailbox.o: ../../include/bounce.h
 mailbox.o: ../../include/sent.h
@@ -316,9 +338,12 @@ mailbox.o: ../../include/deliver_request.h
 mailbox.o: ../../include/recipient_list.h
 mailbox.o: ../../include/mail_proto.h
 mailbox.o: ../../include/iostuff.h
+mailbox.o: ../../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
@@ -343,6 +368,8 @@ maildir.o: ../../include/tok822.h
 maildir.o: ../../include/resolve_clnt.h
 maildir.o: ../../include/deliver_request.h
 maildir.o: ../../include/recipient_list.h
+maildir.o: ../../include/mbox_conf.h
+maildir.o: ../../include/argv.h
 recipient.o: recipient.c
 recipient.o: ../../include/sys_defs.h
 recipient.o: ../../include/msg.h
@@ -368,6 +395,7 @@ recipient.o: ../../include/tok822.h
 recipient.o: ../../include/resolve_clnt.h
 recipient.o: ../../include/deliver_request.h
 recipient.o: ../../include/recipient_list.h
+recipient.o: ../../include/mbox_conf.h
 resolve.o: resolve.c
 resolve.o: ../../include/sys_defs.h
 resolve.o: ../../include/msg.h
@@ -385,6 +413,8 @@ resolve.o: local.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
@@ -404,6 +434,8 @@ token.o: local.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
@@ -423,3 +455,5 @@ unknown.o: ../../include/tok822.h
 unknown.o: ../../include/resolve_clnt.h
 unknown.o: ../../include/deliver_request.h
 unknown.o: ../../include/recipient_list.h
+unknown.o: ../../include/mbox_conf.h
+unknown.o: ../../include/argv.h
index 9da354453613a581a4eb0725606c5f922367c1af..f3b0af1c14481b294e31bdebc02330868e0098ec 100644 (file)
@@ -59,7 +59,7 @@
 #include <vstring.h>
 #include <vstream.h>
 #include <deliver_flock.h>
-#include <open_as.h>
+#include <set_eugid.h>
 
 /* Global library. */
 
@@ -69,7 +69,8 @@
 #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. */
 
@@ -83,17 +84,11 @@ int     deliver_file(LOCAL_STATE state, USER_ATTR usr_attr, char *path)
 {
     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.
      */
@@ -145,43 +140,25 @@ int     deliver_file(LOCAL_STATE state, USER_ATTR usr_attr, char *path)
     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),
@@ -190,14 +167,12 @@ int     deliver_file(LOCAL_STATE state, USER_ATTR usr_attr, char *path)
     } 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);
 }
index a38fc3c32255f9159c0e7adf89c5832250a032f7..241dcca644e1cbf00619874a15c0e40d9e288129 100644 (file)
 /* .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
@@ -446,11 +451,14 @@ char   *var_prop_extension;
 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 */
 
@@ -570,10 +578,21 @@ static void local_mask_init(void)
        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 */
@@ -620,12 +639,14 @@ int     main(int argc, char **argv)
        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,
     };
 
index b24376f7158f0f7d85623b3b40f313ef0a263c17..4843179e0d513fd0363765cb983837df5378568b 100644 (file)
@@ -21,6 +21,7 @@
 #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
@@ -168,6 +169,11 @@ extern int local_cmd_deliver_mask;
   */
 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.
   */
index a0d29314f5f687f632499c8b4f2f9b425223a523..cc8267a07864638b2bd24196e48a9cb28e119300 100644 (file)
 #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
@@ -181,41 +180,41 @@ static int deliver_mailbox_file(LOCAL_STATE state, USER_ATTR usr_attr)
        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);
index 33b21573bb65ce801debae76bc02da33e40ba3ca..6c2ea49e07c0525b8c00a0044297f55e88426dd9 100644 (file)
@@ -335,7 +335,8 @@ int     main(int argc, char **argv)
     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 */
index 7a1c5dab645eecdb885f89b21f213ac272fceaa1..6006c0978de694aae6d1986fea9f414da422b4f9 100644 (file)
@@ -220,7 +220,7 @@ static void multi_server_timeout(int unused_event, char *unused_context)
 
 /* 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));
@@ -237,7 +237,8 @@ static void multi_server_execute(int unused_event, char *context)
     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");
 
     /*
@@ -290,7 +291,8 @@ static void multi_server_accept_local(int unused_event, char *context)
        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)
@@ -324,7 +326,8 @@ static void multi_server_accept_inet(int unused_event, char *context)
        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)
@@ -545,7 +548,7 @@ NORETURN multi_server_main(int argc, char **argv, MULTI_SERVER_FN service,...)
                                ".", 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);
@@ -616,7 +619,8 @@ NORETURN multi_server_main(int argc, char **argv, MULTI_SERVER_FN service,...)
     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);
index b1319c33d489ad4e77c4eb6e81fbd3a5acc6a2a6..13f6f147c64f8f7e95199a46f446606ae7269fbc 100644 (file)
@@ -263,7 +263,8 @@ static void single_server_accept_local(int unused_event, char *context)
        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)
@@ -296,7 +297,8 @@ static void single_server_accept_inet(int unused_event, char *context)
        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)
@@ -517,7 +519,7 @@ NORETURN single_server_main(int argc, char **argv, SINGLE_SERVER_FN service,...)
                                ".", 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);
@@ -588,7 +590,8 @@ NORETURN single_server_main(int argc, char **argv, SINGLE_SERVER_FN service,...)
     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);
index 8a958ff45108e2d4022609e58d0e5d17a5162184..86dd4000835e5d11c4f85e4c9157b10a1d575afb 100644 (file)
@@ -248,7 +248,8 @@ static void trigger_server_accept_fifo(int unused_event, char *context)
     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)
@@ -289,7 +290,8 @@ static void trigger_server_accept_local(int unused_event, char *context)
        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)
@@ -531,7 +533,7 @@ NORETURN trigger_server_main(int argc, char **argv, TRIGGER_SERVER_FN service,..
                                ".", 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);
@@ -599,7 +601,8 @@ NORETURN trigger_server_main(int argc, char **argv, TRIGGER_SERVER_FN service,..
     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);
index 4ae7ca5507489601ac9528774e20dfc0c0a0504b..91b261354fe61be6dde286b1a3e8065155f4d883 100644 (file)
@@ -880,13 +880,13 @@ QMGR_MESSAGE *qmgr_message_alloc(const char *queue_name, const char *queue_id,
      * 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);
index d6720d5cd30b7ef5158c6d0e71504778aa0fb022..edeca6216af42e566dc0b69831f5d9b3d32bac67 100644 (file)
@@ -88,6 +88,7 @@ postconf.o: ../../include/iostuff.h
 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
index 71d8735777acad62805efa133708bbfe86f5aa3f..8a5409bbbbefff0843f61f8caa6a7b5f16ccf8e8 100644 (file)
@@ -5,7 +5,7 @@
 /*     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]
@@ -32,6 +32,8 @@
 /*     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
@@ -93,6 +95,7 @@
 #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.
@@ -310,7 +314,7 @@ static void edit_parameters(int argc, char **argv)
     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);
@@ -631,6 +635,19 @@ static void show_maps(void)
     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)
@@ -696,7 +713,7 @@ int     main(int argc, char **argv)
     /*
      * 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)
@@ -711,6 +728,9 @@ int     main(int argc, char **argv)
        case 'h':
            mode &= ~SHOW_NAME;
            break;
+       case 'l':
+           mode |= SHOW_LOCKS;
+           break;
        case 'm':
            mode |= SHOW_MAPS;
            break;
@@ -721,17 +741,17 @@ int     main(int argc, char **argv)
            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
@@ -740,6 +760,13 @@ int     main(int argc, char **argv)
        show_maps();
     }
 
+    /*
+     * If showing locking methods, show them and exit
+     */
+    if (mode & SHOW_LOCKS) {
+       show_locks();
+    }
+
     /*
      * Edit main.cf.
      */
index 3ce69b3e6c09f0af90681814c4eb3bf755e29e4a..8f88fff7cee1480ab7eb92e586a31ba3e7cc1668 100644 (file)
@@ -61,8 +61,13 @@ postlock.o: ../../include/vbuf.h
 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
index b810d88293a84489ebb6161521e9f4f2e02edf8b..c721db84da9a72d8ae09d0dcfeaaaad9f0cc1de2 100644 (file)
@@ -5,8 +5,8 @@
 /*     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
@@ -16,6 +16,9 @@
 /* .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.
@@ -28,8 +31,7 @@
 /*     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 */
@@ -132,6 +142,9 @@ int     main(int argc, char **argv)
     int     count;
     WAIT_STATUS_T status;
     pid_t   pid;
+    int     mbox_lock;
+    char   *lock_style = 0;
+    VSTREAM *fp;
 
     /*
      * Be consistent with file permissions.
@@ -165,7 +178,7 @@ int     main(int argc, char **argv)
     /*
      * 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]);
@@ -174,6 +187,9 @@ int     main(int argc, char **argv)
            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;
@@ -188,34 +204,19 @@ int     main(int argc, char **argv)
      * 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.
@@ -228,20 +229,15 @@ int     main(int argc, char **argv)
        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);
 }
index 23af5d6fe009b575eb8eaf17dc729a785fb2c93a..6e532a5b9841c2d2f50dea17ae19bf3384313d6b 100644 (file)
@@ -748,13 +748,13 @@ QMGR_MESSAGE *qmgr_message_alloc(const char *queue_name, const char *queue_id,
      * 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);
index 59017b1dc3c3e3c52bc285fc64bc46f85a66f5d6..82c5d973969f75df8cc3d78a0d7f749e97f2f241 100644 (file)
@@ -302,21 +302,22 @@ static int deliver_message(DELIVER_REQUEST *request)
        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 */
index b0e085fb3aa8dc566341c4dd058c3c67001bd9a7..6336e2e5e486f9568bc78195f4f0e50809471262 100644 (file)
@@ -274,7 +274,8 @@ void    smtp_sasl_initialize(void)
     /*
      * 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 */
index 4e98a8f282e429115f774be6e3fc36ae5e3891cb..ca492963487f621014c416b0e4630265033e54a0 100644 (file)
@@ -73,7 +73,8 @@ void    smtpd_state_init(SMTPD_STATE *state, VSTREAM *stream)
     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;
index 92c710ad2733edb39f69253059b7fdd142ef4057..5abc233a7e20fcc1154ad0ff376a5ac4a730ce2f 100644 (file)
@@ -22,7 +22,7 @@ SRCS  = argv.c argv_split.c attr.c basename.c binhash.c chroot_uid.c \
        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 \
@@ -46,7 +46,7 @@ OBJS  = argv.o argv_split.o attr.o basename.o binhash.o chroot_uid.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 \
@@ -77,7 +77,7 @@ TESTPROG= dict_open dup2_pass_on_exec events exec_command fifo_open \
        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
@@ -256,6 +256,11 @@ hex_quote: $(LIB)
        $(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 \
@@ -710,6 +715,8 @@ mvect.o: mvect.h
 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
index 5886fad9c8671604bf579eb4e2f4d82d956c3d82..65c3aceb002991931ca46291e4045f6190fb4d9f 100644 (file)
@@ -19,7 +19,7 @@
 /*     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.
index 95a3e305df97587ac2b0db18013a12ba4f5d37c2..c75fb077892ae14cc3a62c103c642fae456bc7f9 100644 (file)
@@ -158,7 +158,8 @@ static const char *dict_db_lookup(DICT *dict, const char *name)
     /*
      * 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);
 
     /*
@@ -197,7 +198,8 @@ static const char *dict_db_lookup(DICT *dict, const char *name)
     /*
      * 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);
@@ -244,7 +246,8 @@ static void dict_db_update(DICT *dict, const char *name, const char *value)
     /*
      * 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);
 
     /*
@@ -268,7 +271,8 @@ static void dict_db_update(DICT *dict, const char *name, const char *value)
     /*
      * 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);
 }
 
@@ -285,7 +289,8 @@ static int dict_db_delete(DICT *dict, const char *name)
     /*
      * 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);
 
     /*
@@ -320,7 +325,8 @@ static int dict_db_delete(DICT *dict, const char *name)
     /*
      * 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;
@@ -361,7 +367,8 @@ static int dict_db_sequence(DICT *dict, const int function,
     /*
      * 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)
@@ -370,7 +377,8 @@ static int dict_db_sequence(DICT *dict, const int function,
     /*
      * 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) {
@@ -436,7 +444,7 @@ static DICT *dict_db_open(const char *path, int open_flags, int type,
     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);
     }
 
@@ -496,12 +504,11 @@ static DICT *dict_db_open(const char *path, int open_flags, int type,
        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;
index 6ed13d0da79a0ffd04f83e2c648ddbadbaa1712b..c870f32a9bbb96266eedcbd64484c1050351a774 100644 (file)
@@ -84,7 +84,8 @@ static const char *dict_dbm_lookup(DICT *dict, const char *name)
     /*
      * 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);
 
     /*
@@ -121,7 +122,8 @@ static const char *dict_dbm_lookup(DICT *dict, const char *name)
     /*
      * 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);
@@ -165,7 +167,8 @@ static void dict_dbm_update(DICT *dict, const char *name, const char *value)
     /*
      * 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);
 
     /*
@@ -186,7 +189,8 @@ static void dict_dbm_update(DICT *dict, const char *name, const char *value)
     /*
      * 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);
 }
 
@@ -202,7 +206,8 @@ static int dict_dbm_delete(DICT *dict, const char *name)
     /*
      * 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);
 
     /*
@@ -242,7 +247,8 @@ static int dict_dbm_delete(DICT *dict, const char *name)
     /*
      * 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);
@@ -264,7 +270,8 @@ static int dict_dbm_sequence(DICT *dict, const int function,
     /*
      * 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);
 
     /*
@@ -284,7 +291,8 @@ static int dict_dbm_sequence(DICT *dict, const int function,
     /*
      * 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) {
@@ -369,7 +377,7 @@ DICT   *dict_dbm_open(const char *path, int open_flags, int dict_flags)
        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);
     }
 
@@ -380,7 +388,7 @@ DICT   *dict_dbm_open(const char *path, int open_flags, int dict_flags)
        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);
index 19a5cabd8600ad7bba629bcff74e2eebe4beae51..69688d48ab2e94172e99462e65c14f4168034e63 100644 (file)
@@ -6,16 +6,17 @@
 /* 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? */
index 7d43efeae94f3e547df52cd977a9a521abbdd876..b65ed2962cc7d22748a9a3a8505334eb138c779c 100644 (file)
  /*
   * 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
index 1d01439eac524978e5306b889fafd225f916d91a..52e9cf7692daa50ec26da8a29c463d1a873e4366 100644 (file)
@@ -6,14 +6,29 @@
 /* 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);
@@ -58,7 +76,8 @@ int     name_mask(NAME_MASK *table, const char *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);
@@ -70,3 +89,63 @@ int     name_mask(NAME_MASK *table, const char *names)
     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
index 2387f39219e83d2c749efd443a9e92866dc6e6f5..fafd7cd882ca430a452ed419f9b29edbc43b5278 100644 (file)
@@ -19,7 +19,8 @@ typedef struct {
     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
index ec30700ee603df2d4b7714746c2eec208e92b214..028b6604d761e575c411c0c3dc1ed5b5f82df2ec 100644 (file)
@@ -64,9 +64,10 @@ VSTREAM *open_lock(const char *path, int flags, int mode, VSTRING *why)
      * 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);
index 07dce44e3149fbf4a355319f032898ae3b09da5f..ca7bf8368048a72c705553be6e505f07d10b02c1 100644 (file)
@@ -6,10 +6,11 @@
 /* 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;
@@ -17,8 +18,8 @@
 /*     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"
@@ -26,6 +27,9 @@
 /*     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;
 
@@ -99,14 +104,16 @@ static VSTREAM *safe_open_exist(const char *path, int flags, VSTRING *why)
     /*
      * 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);
     }
 
     /*
@@ -121,14 +128,15 @@ static VSTREAM *safe_open_exist(const char *path, int flags, VSTRING *why)
      * 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");
     }
 
     /*
@@ -150,7 +158,7 @@ static VSTREAM *safe_open_exist(const char *path, int flags, VSTRING *why)
 /* 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;
 
@@ -159,7 +167,7 @@ static VSTREAM *safe_open_create(const char *path, int flags, int mode,
      * 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);
     }
 
@@ -172,9 +180,15 @@ static VSTREAM *safe_open_create(const char *path, int flags, int mode,
 
     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...
      */
@@ -192,7 +206,7 @@ static VSTREAM *safe_open_create(const char *path, int flags, int mode,
 /* 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;
 
@@ -202,13 +216,13 @@ VSTREAM *safe_open(const char *path, int flags, int mode,
         * 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
@@ -216,9 +230,9 @@ VSTREAM *safe_open(const char *path, int flags, int mode,
         * 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);
 
        /*
index 02964f8ba256fdac119254cd810491a5469b1e57..7bee82c09625b8b8de19beb664b7b619acbfc519 100644 (file)
@@ -14,6 +14,7 @@
  /*
   * System library.
   */
+#include <sys/stat.h>
 #include <fcntl.h>
 
  /*
@@ -25,7 +26,7 @@
  /*
   * 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
index d89fa0e354ca7f82ef674705a1aa809f11a4772b..f71b6b4e7431f7088f4f1eb99e0ecb5a6020a9f0 100644 (file)
@@ -33,6 +33,7 @@
 #include <sys_defs.h>
 #include <unistd.h>
 #include <grp.h>
+#include <errno.h>
 
 /* Utility library. */
 
@@ -43,6 +44,8 @@
 
 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");
@@ -54,4 +57,5 @@ void    set_eugid(uid_t euid, gid_t egid)
        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;
 }
index 7aae533a96e50113a66bbdb7d55e6773d1175b1d..bbcb901331c3343dc62cacffa9c157662d8fe4a9 100644 (file)
@@ -33,6 +33,7 @@
 #include <sys_defs.h>
 #include <unistd.h>
 #include <grp.h>
+#include <errno.h>
 
 /* Utility library. */
 
@@ -43,6 +44,8 @@
 
 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");
@@ -54,4 +57,5 @@ void    set_ugid(uid_t uid, gid_t gid)
        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;
 }
index 206209a496d8b2f0eaddfc72a53eff6acaa0252b..77bbbe9d6fa74558591ea5347ceef42886f28621 100644 (file)
   * 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) \
@@ -27,7 +31,9 @@
 #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
@@ -123,14 +145,19 @@ extern int h_errno;
 #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
@@ -148,6 +175,10 @@ extern int opterr;                 /* XXX use <getopt.h> */
 #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>
@@ -159,8 +190,10 @@ extern int opterr;                 /* XXX use <getopt.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"
@@ -178,6 +211,9 @@ extern int opterr;
 #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 */
@@ -187,8 +223,9 @@ extern int opterr;
 #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"
@@ -208,6 +245,9 @@ extern int opterr;
 #define HAS_VOLATILE_LOCKS
 #endif
 
+ /*
+  * UnixWare, System Release 4.
+  */
 #ifdef UW7                             /* UnixWare 7 */
 #define SUPPORTED
 #include <sys/types.h>
@@ -216,8 +256,9 @@ extern int opterr;
 #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"
@@ -241,8 +282,9 @@ extern int opterr;
 #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"
@@ -259,6 +301,10 @@ extern int opterr;
 #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>
@@ -267,8 +313,9 @@ extern int opterr;
 #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
@@ -299,8 +346,9 @@ extern int initgroups(const char *, int);
 #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
@@ -323,6 +371,9 @@ extern int initgroups(const char *, int);
 
 #endif
 
+ /*
+  * IRIX, a mix of System V Releases.
+  */
 #if defined(IRIX5) || defined(IRIX6)
 #define SUPPORTED
 #include <sys/types.h>
@@ -331,8 +382,9 @@ extern int initgroups(const char *, int);
 #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"
@@ -351,12 +403,17 @@ extern int initgroups(const char *, int);
 #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"
@@ -380,7 +437,9 @@ extern int initgroups(const char *, int);
 #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"
@@ -408,7 +467,9 @@ extern int h_errno;                 /* <netdb.h> imports too much stuff */
 #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"
@@ -436,7 +497,9 @@ extern int h_errno;                 /* <netdb.h> imports too much stuff */
 #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
@@ -468,7 +531,9 @@ extern int h_errno;
 #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
@@ -516,7 +581,9 @@ extern int opterr;
 #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
@@ -567,8 +634,9 @@ extern int opterr;
 #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
@@ -595,8 +663,9 @@ extern int opterr;                  /* XXX use <getopt.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"
@@ -625,8 +694,9 @@ extern int h_errno;
 #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"
@@ -672,12 +742,16 @@ extern int dup2_pass_on_exec(int oldd, int newd);
 #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)