]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
snapshot-20020101
authorWietse Venema <wietse@porcupine.org>
Tue, 1 Jan 2002 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <viktor@dukhovni.org>
Tue, 5 Feb 2013 06:27:45 +0000 (06:27 +0000)
27 files changed:
postfix/HISTORY
postfix/INSTALL.sh
postfix/RELEASE_NOTES
postfix/conf/master.cf
postfix/conf/sample-misc.cf
postfix/html/postdrop.1.html
postfix/html/postqueue.1.html
postfix/man/man1/postdrop.1
postfix/man/man1/postqueue.1
postfix/src/global/Makefile.in
postfix/src/global/flush_clnt.c
postfix/src/global/mail_conf.c
postfix/src/global/mail_params.c
postfix/src/global/mail_params.h
postfix/src/global/mail_version.h
postfix/src/postconf/postconf.c
postfix/src/postdrop/postdrop.c
postfix/src/postqueue/postqueue.c
postfix/src/sendmail/sendmail.c
postfix/src/util/Makefile.in
postfix/src/util/dict.c
postfix/src/util/iostuff.h
postfix/src/util/msg.c
postfix/src/util/msg.h
postfix/src/util/sock_empty_wait.c [deleted file]
postfix/src/util/split_nameval.c [new file with mode: 0644]
postfix/src/util/stringops.h

index 9cf5f1d44d657b4ccf0f05b884c4bc04a8414979..c2254003e753c8e01fbf4e3ebb2212f0c21ef6b9 100644 (file)
@@ -5875,7 +5875,19 @@ Apologies for any names omitted.
        Cleanup: the code for "mailq", "sendmail -q", and for
        "sendmail -qRsite" was moved from the sendmail command to
        a new set-gid postqueue command. The pickup and qmgr FIFOs
-       are no longer world writable.
+       are no longer world writable. Files: sendmail/sendmail.c,
+       postqueue/postqueue.c.
+
+20020101
+
+       Security: new alternate_config_directory parameter that
+       lists directories that a set-gid command will accept as
+       its configuration directory. The list must be specified in
+       the default main.cf file. File: global/mail_conf.c.
+
+       Cleanup: "sendmail -qRsite" is no longer implemented by
+       connecting to the SMTP port. It is now implemented by
+       talking to the fast flush service. File: postqueue/postqueue.c.
 
 Open problems:
 
index 0470d728cb58578cc9f7f1c3ce6bfeb3c56a4c7c..5db0ac701f7b22f83ca5d6465d94247c1b27f5da 100644 (file)
@@ -3,44 +3,59 @@
 # Sample Postfix installation script. Run this from the top-level
 # Postfix source directory.
 
-PATH=/bin:/usr/bin:/usr/sbin:/usr/etc:/sbin:/etc
+PATH=/bin:/usr/bin:/usr/sbin:/usr/etc:/sbin:/etc:/usr/contrib/bin:/usr/gnu/bin:/usr/ucb:/usr/bsd
 umask 022
 
-test -t 0 &&
-cat <<EOF
+test -t 0 && cat <<EOF
 
 Warning: this script replaces existing sendmail or Postfix programs.
 Make backups if you want to be able to recover.
 
-In addition to doing a fresh install, this script can change an
-existing installation from using a world-writable maildrop to a
-group-writable one. It cannot be used to change Postfix queue
-file/directory ownership.
-
 Before installing files, this script prompts you for some definitions.
 Most definitions will be remembered, so you have to specify them
 only once. All definitions have a reasonable default value.
+EOF
 
-    install_root - prefix for installed file names (for package building)
+install_root_text="the prefix for installed file names. This is
+useful only if you are building ready-to-install packages for other
+machines."
 
-    tempdir - where to write scratch files while installing Postfix
+tempdir_text="directory for scratch files while installing Postfix.
+You must must have write permission in this directory."
 
-    config_directory - directory with Postfix configuration files.
-    daemon_directory - directory with Postfix daemon programs.
-    command_directory - directory with Postfix administrative commands.
-    queue_directory - directory with Postfix queues.
+config_directory_text="the directory with Postfix configuration
+files. For security reasons this directory must be owned by the
+super-user."
 
-    sendmail_path - full pathname of the Postfix sendmail command.
-    newaliases_path - full pathname of the Postfix newaliases command.
-    mailq_path - full pathname of the Postfix mailq command.
+daemon_directory_text="the directory with Postfix daemon programs.
+This directory should not be in the command search path of any
+users."
 
-    mail_owner - Postfix queue account (with unique user/group id numbers).
+command_directory_text="the directory with Postfix administrative
+commands.  This directory should be in the command search path of
+adminstrative users."
 
-    setgid - group for submission (with a unique group id number).
+queue_directory_text="the directory with Postfix queues."
 
-    manpages - "no" or path to man tree. Example: /usr/local/man.
+sendmail_path_text="the full pathname of the Postfix sendmail
+command. This is the Sendmail-compatible mail posting interface."
 
-EOF
+newaliases_path_text="the full pathname of the Postfix newaliases
+command.  This is the Sendmail-compatible command to build alias
+databases."
+
+mailq_path_text="the full pathname of the Postfix mailq command.
+This is the Sendmail-compatible mail queue listing command."
+
+mail_owner_text="the owner of the Postfix queue. Specify a user
+account with numerical user ID and group ID values that are not
+used by any other user accounts."
+
+setgid_text="the group for mail submission and queue management
+commands.  Specify a group name with a numerical group ID that is
+not shared with other accounts, not even with the Postfix account."
+
+manpages_text="where to install the Postfix on-line manual pages."
 
 # By now, shells must have functions. Ultrix users must use sh5 or lose.
 # The following shell functions replace files/symlinks while minimizing
@@ -131,6 +146,8 @@ for name in install_root tempdir config_directory
 do
     while :
     do
+       echo
+       eval echo Please specify \$${name}_text | fmt
        eval echo \$n "$name: [\$$name]\  \$c"
        read ans
        case $ans in
@@ -188,6 +205,8 @@ for name in daemon_directory command_directory \
 do
     while :
     do
+       echo
+       eval echo Please specify \$${name}_text | fmt
        eval echo \$n "$name: [\$$name]\  \$c"
        read ans
        case $ans in
@@ -199,6 +218,16 @@ done
 
 # Sanity checks
 
+case $manpages in
+ no) echo Error: manpages no longer accepts "no" values. 1>&2
+     echo Error: re-run this script in interactive mode. 1>&2; exit 1;;
+esac
+
+case $setgid in
+ no) echo Error: setgid no longer accepts "no" values. 1>&2
+     echo Error: re-run this script in interactive mode. 1>&2; exit 1;;
+esac
+
 for path in $daemon_directory $command_directory \
     $queue_directory $sendmail_path $newaliases_path $mailq_path $manpages
 do
@@ -372,20 +401,25 @@ grep "^pickup[    ]*fifo[         ]*n[    ]*n" \
        ed $CONFIG_DIRECTORY/master.cf <<EOF
 /^pickup[      ]*fifo[         ]*n[    ]*n/
 s/\(n[         ]*\)n/\1-/
+p
 w
 q
 EOF
 }
-grep "^cleanup[        ]*unix[         ]*-" \
-    $CONFIG_DIRECTORY/master.cf >/dev/null && {
-       echo changing master.cf, making the cleanup service public
-       ed $CONFIG_DIRECTORY/master.cf <<EOF
-/^cleanup[     ]*unix[         ]*-/
+for name in cleanup flush
+do
+    grep "^$name[      ]*unix[         ]*-" \
+       $CONFIG_DIRECTORY/master.cf >/dev/null && {
+           echo changing master.cf, making the $name service public
+           ed $CONFIG_DIRECTORY/master.cf <<EOF
+/^$name[       ]*unix[         ]*-/
 s/-/n/
+p
 w
 q
 EOF
-}
+    }
+done
 
 found=`bin/postconf -c $CONFIG_DIRECTORY -h hash_queue_names`
 missing=
index c247f9cc52723fc36d119bcf0233579d4b9b4fc9..728715bdd760add34793f7089453a4dbe30c99e6 100644 (file)
@@ -1,26 +1,32 @@
-Incompatible changes with snapshot-20011230
+Incompatible changes with snapshot-200201XX
 ===========================================
 
-This release modifies the existing master.cf file, making the local
-pickup unprivileged, and making the cleanup service "public" (for
-future performance improvements of local mail submission).
+If you run multiple Postfix instances then you have to specify
+their configuration directories in the default main.cf file as
+"alternate_config_directory = /dir1 /dir2 ...". Otherwise, some
+Postfix sendmail commands will no longer work (namely, the ones
+that are now implemented by set-group ID client programs).
+
+This release modifies the existing master.cf file. The local pickup
+service is now unprivileged, and the cleanup and flush service are
+now "public".
 
 Should you have to back out to a previous release, then you have
 to edit the master.cf file, making the pickup service "privileged",
-and making the cleanup service "private".
+and making the cleanup and flush service "private".
 
-Major changes with snapshot-20011230
+Major changes with snapshot-200201XX
 ====================================
 
 Simplification of the local Postfix security model.
 
-- The world-writable maildrop directory is gone. Postfix now uses
-  the set-gid postdrop command for local mail submissions.  The
-  local mail pickup daemon is now an unprivileged process.
+- The world-writable maildrop directory is gone. Postfix now always
+  uses the set-gid postdrop command for local mail submissions.
+  The local mail pickup daemon is now an unprivileged process.
 
-- The world-writable pickup and queue manager FIFOs are gone.
-  Postfix now uses the new set-gid postqueue command for all the
-  queue operations that were implemented by the Postfix sendmail
+- The world-accessible pickup and queue manager server FIFOs are
+  gone.  Postfix now uses a new set-gid postqueue command for all
+  the queue operations that were implemented by the Postfix sendmail
   command.
 
 Incompatible changes with snapshot-20011226
index 7ff376a40ddc75fbafd24509bd4e4bef5fd5e553..622615671d2e8ceba6ad69be7362fb982792cf86 100644 (file)
@@ -77,7 +77,7 @@ qmgr    fifo  n       -       n       300     1       qmgr
 rewrite          unix  -       -       n       -       -       trivial-rewrite
 bounce   unix  -       -       n       -       0       bounce
 defer    unix  -       -       n       -       0       bounce
-flush    unix  -       -       n       1000?   0       flush
+flush    unix  n       -       n       1000?   0       flush
 smtp     unix  -       -       n       -       -       smtp
 showq     unix n       -       n       -       -       showq
 error     unix -       -       n       -       -       error
index f756321660bcc69659b67944da9fb65b47aec7f0..d848d911975293e66535ed3002c164f3ba901f11 100644 (file)
@@ -286,6 +286,8 @@ parent_domain_matches_subdomains = debug_peer_list,fast_flush_domains,
 # to the Postfix queue directory. This facility is used by the master
 # daemon to lock out other master daemon instances.
 #
+# Note: this is a read-only variable.
+#
 process_id_directory = pid
 
 # The program_directory parameter specifies the location of Postfix
index 49a4b5601dc226261b44bc8c1153dbc6587d0d27..f8fa8a2db5f01e97f9cc2023dad2f876283e66de 100644 (file)
@@ -6,7 +6,7 @@ POSTDROP(1)                                           POSTDROP(1)
        postdrop - Postfix mail posting utility
 
 <b>SYNOPSIS</b>
-       <b>postdrop</b> [<i>option</i> <i>...</i>]
+       <b>postdrop</b> [<i>-rv</i>] [<b>-c</b> <i>config_dir</i>]
 
 <b>DESCRIPTION</b>
        The <b>postdrop</b> command creates a file in the <b>maildrop</b> direc-
@@ -14,25 +14,46 @@ POSTDROP(1)                                           POSTDROP(1)
 
        Options:
 
+       <b>-c</b>     The <b>main.cf</b> configuration  file  is  in  the  named
+              directory  instead  of  the  default  configuration
+              directory. See  also  the  MAIL_CONFIG  environment
+              setting below.
+
+       <b>-r</b>     Use  a  Postfix-internal  protocol  for reading the
+              message from standard input, and for reporting sta-
+              tus  information  on  standard output. This is cur-
+              rently the only supported method.
+
        <b>-v</b>     Enable verbose logging for debugging purposes. Mul-
               tiple  <b>-v</b>  options  make  the software increasingly
               verbose.
 
 <b>SECURITY</b>
-       The command is designed to run  with  set-gid  privileges,
-       and  with  group  write  permission  to the <b>maildrop</b> queue
-       directory.
+       The command is designed to run with  set-group  ID  privi-
+       leges,  so  that it can write to the <b>maildrop</b> queue direc-
+       tory and so that it can connect  to  Postfix  daemon  pro-
+       cesses.
 
 <b>DIAGNOSTICS</b>
-       Fatal errors: malformed input, I/O error, out  of  memory.
-       Problems  are  logged  to  <b>syslogd</b>(8)  and to the standard
-       error stream.  When the input is incomplete, or  when  the
-       process  receives  a  HUP,  INT,  QUIT or TERM signal, the
+       Fatal  errors:  malformed input, I/O error, out of memory.
+       Problems are logged to  <b>syslogd</b>(8)  and  to  the  standard
+       error  stream.   When the input is incomplete, or when the
+       process receives a HUP, INT,  QUIT  or  TERM  signal,  the
        queue file is deleted.
 
 <b>ENVIRONMENT</b>
-       The program deletes most environment information,  because
-       the C library can't be trusted.
+       MAIL_CONFIG
+              Directory  with the <b>main.cf</b> file. In order to avoid
+              exploitation of set-group ID privileges, it is  not
+              possible to specify arbitrary directory names.
+
+              A  non-standard  directory  is  allowed only if the
+              name is listed in the standard <b>main.cf</b> file, in the
+              <b>alternate</b><i>_</i><b>config</b><i>_</i><b>directory</b>  configuration parameter
+              value.
+
+              Only the super-user is allowed to specify arbitrary
+              directory names.
 
 <b>FILES</b>
        /var/spool/postfix, mail queue
index 0387d7662fb87613e3b65d66bc833c959408f27b..9df608b874cfe2b4a2dd5dcb7afd45dbd95c64ee 100644 (file)
@@ -6,9 +6,9 @@ POSTQUEUE(1)                                         POSTQUEUE(1)
        postqueue - Postfix queue control
 
 <b>SYNOPSIS</b>
-       <b>postqueue</b> <b>-f</b>
-       <b>postqueue</b> <b>-p</b>
-       <b>postqueue</b> <b>-s</b> <i>site</i>
+       <b>postqueue</b> [<b>-c</b> <i>config_dir</i>] <b>-f</b>
+       <b>postqueue</b> [<b>-c</b> <i>config_dir</i>] <b>-p</b>
+       <b>postqueue</b> [<b>-c</b> <i>config_dir</i>] <b>-s</b> <i>site</i>
 
 <b>DESCRIPTION</b>
        The  <b>postqueue</b>  program implements the Postfix user inter-
@@ -18,43 +18,59 @@ POSTQUEUE(1)                                         POSTQUEUE(1)
 
        The following options are recognized:
 
-       <b>-f</b>     Flush the queue:  attempt  to  deliver  all  queued
+       <b>-c</b>     The <b>main.cf</b> configuration  file  is  in  the  named
+              directory  instead  of  the  default  configuration
+              directory. See  also  the  MAIL_CONFIG  environment
+              setting below.
+
+       <b>-f</b>     Flush  the  queue:  attempt  to  deliver all queued
               mail.
 
-              This  option implements the traditional <b>sendmail</b> <b>-q</b>
-              command, by contacting the Postfix <a href="qmgr.8.html"><b>qmgr</b>(8)</a>  daemon.
+              This option implements the traditional <b>sendmail</b>  <b>-q</b>
+              command,  by contacting the Postfix <a href="qmgr.8.html"><b>qmgr</b>(8)</a> daemon.
 
        <b>-p</b>     Produce a traditional sendmail-style queue listing.
 
-              This option implements the traditional  <b>mailq</b>  com-
+              This  option  implements the traditional <b>mailq</b> com-
               mand, by contacting the Postfix <a href="showq.8.html"><b>showq</b>(8)</a> daemon.
 
        <b>-s</b> <i>site</i>
-              Schedule  immediate  delivery  of  all mail that is
-              queued for the named <i>site</i>. The site must be  eligi-
+              Schedule immediate delivery of  all  mail  that  is
+              queued  for the named <i>site</i>. The site must be eligi-
               ble for the "fast flush" service.  See <a href="flushd.8.html"><b>flush</b>(8)</a> for
               more information about the "fast flush" service.
 
-              This option  implements  the  traditional  <b>sendmail</b>
-              <b>-qR</b><i>site</i>  command,  by connecting to the SMTP server
-              at <b>$myhostname</b>.
+              This  option  implements  the  traditional <b>sendmail</b>
+              <b>-qR</b><i>site</i> command, by contacting the Postfix <a href="flushd.8.html"><b>flush</b>(8)</a>
+              daemon.
 
        <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>SECURITY</b>
-       By design, this program is set-user (or group) id, so that
-       it  can  connect  to public, but protected, Postfix daemon
-       processes.
+       This  program  is designed to run with set-group ID privi-
+       leges, so that it can connect to Postfix daemon processes.
 
 <b>DIAGNOSTICS</b>
-       Problems are logged to  <b>syslogd</b>(8)  and  to  the  standard
+       Problems  are  logged  to  <b>syslogd</b>(8)  and to the standard
        error stream.
 
 <b>ENVIRONMENT</b>
-       The  program deletes most environment information, because
-       the C library can't be trusted.
+       MAIL_CONFIG
+              Directory with the <b>main.cf</b> file.
+
+              In order to  avoid  exploitation  of  set-group  ID
+              privileges, it is not possible to specify arbitrary
+              directory names.
+
+              A non-standard directory is  allowed  only  if  the
+              name is listed in the standard <b>main.cf</b> file, in the
+              <b>alternate</b><i>_</i><b>config</b><i>_</i><b>directory</b> configuration  parameter
+              value.
+
+              Only the super-user is allowed to specify arbitrary
+              directory names.
 
 <b>FILES</b>
        /var/spool/postfix, mail queue
index 3b980708aacf7e7c45cc2261e7d86569c9b7e918..5e456e9d57d0f8dde7c7e577fae2b82d260c65d1 100644 (file)
@@ -8,7 +8,7 @@ Postfix mail posting utility
 .SH SYNOPSIS
 .na
 .nf
-\fBpostdrop\fR [\fIoption ...\fR]
+\fBpostdrop\fR [\fI-rv\fR] [\fB-c \fIconfig_dir\fR]
 .SH DESCRIPTION
 .ad
 .fi
@@ -16,6 +16,14 @@ The \fBpostdrop\fR command creates a file in the \fBmaildrop\fR
 directory and copies its standard input to the file.
 
 Options:
+.IP \fB-c \fIconfig_dir\fR
+The \fBmain.cf\fR configuration file is in the named directory
+instead of the default configuration directory. See also the
+MAIL_CONFIG environment setting below.
+.IP \fB-r\fR
+Use a Postfix-internal protocol for reading the message from
+standard input, and for reporting status information on standard
+output. This is currently the only supported method.
 .IP \fB-v\fR
 Enable verbose logging for debugging purposes. Multiple \fB-v\fR
 options make the software increasingly verbose.
@@ -24,8 +32,9 @@ options make the software increasingly verbose.
 .nf
 .ad
 .fi
-The command is designed to run with set-gid privileges, and with
-group write permission to the \fBmaildrop\fR queue directory.
+The command is designed to run with set-group ID privileges, so
+that it can write to the \fBmaildrop\fR queue directory and so that
+it can connect to Postfix daemon processes.
 .SH DIAGNOSTICS
 .ad
 .fi
@@ -38,8 +47,16 @@ INT, QUIT or TERM signal, the queue file is deleted.
 .nf
 .ad
 .fi
-The program deletes most environment information, because the C
-library can't be trusted.
+.IP MAIL_CONFIG
+Directory with the \fBmain.cf\fR file. In order to avoid exploitation
+of set-group ID privileges, it is not possible to specify arbitrary
+directory names.
+
+A non-standard directory is allowed only if the name is listed in the
+standard \fBmain.cf\fR file, in the \fBalternate_config_directory\fR
+configuration parameter value.
+
+Only the super-user is allowed to specify arbitrary directory names.
 .SH FILES
 .na
 .nf
index c7fea395e5821d1e7973ef3c7ecf8ee6f214226d..b1fa423b677ae7e8dc242db939259cd73e2251c8 100644 (file)
@@ -8,11 +8,11 @@ Postfix queue control
 .SH SYNOPSIS
 .na
 .nf
-\fBpostqueue\fR \fB-f\fR
+\fBpostqueue\fR [\fB-c \fIconfig_dir\fR] \fB-f\fR
 .br
-\fBpostqueue\fR \fB-p\fR
+\fBpostqueue\fR [\fB-c \fIconfig_dir\fR] \fB-p\fR
 .br
-\fBpostqueue\fR \fB-s \fIsite\fR
+\fBpostqueue\fR [\fB-c \fIconfig_dir\fR] \fB-s \fIsite\fR
 .SH DESCRIPTION
 .ad
 .fi
@@ -21,6 +21,10 @@ for queue management. It implements all the operations that are
 traditionally available via the \fBsendmail\fR(1) command.
 
 The following options are recognized:
+.IP \fB-c \fIconfig_dir\fR
+The \fBmain.cf\fR configuration file is in the named directory
+instead of the default configuration directory. See also the
+MAIL_CONFIG environment setting below.
 .IP \fB-f\fR
 Flush the queue: attempt to deliver all queued mail.
 
@@ -38,7 +42,7 @@ See \fBflush\fR(8) for more information about the "fast flush"
 service.
 
 This option implements the traditional \fBsendmail -qR\fIsite\fR
-command, by connecting to the SMTP server at \fB$myhostname\fR.
+command, by contacting the Postfix \fBflush\fR(8) daemon.
 .IP \fB-v\fR
 Enable verbose logging for debugging purposes. Multiple \fB-v\fR
 options make the software increasingly verbose.
@@ -47,8 +51,8 @@ options make the software increasingly verbose.
 .nf
 .ad
 .fi
-By design, this program is set-user (or group) id, so that it
-can connect to public, but protected, Postfix daemon processes.
+This program is designed to run with set-group ID privileges, so
+that it can connect to Postfix daemon processes.
 .SH DIAGNOSTICS
 .ad
 .fi
@@ -59,8 +63,17 @@ stream.
 .nf
 .ad
 .fi
-The program deletes most environment information, because the C
-library can't be trusted.
+.IP MAIL_CONFIG
+Directory with the \fBmain.cf\fR file.
+
+In order to avoid exploitation of set-group ID privileges, it is not
+possible to specify arbitrary directory names.
+
+A non-standard directory is allowed only if the name is listed in the
+standard \fBmain.cf\fR file, in the \fBalternate_config_directory\fR
+configuration parameter value.
+
+Only the super-user is allowed to specify arbitrary directory names.
 .SH FILES
 .na
 .nf
index 33f7f37229d7ae47c6b833554f08f2712a73ffd1..73b3d1236fd32e188928999f6e5746751f649430 100644 (file)
@@ -513,6 +513,7 @@ mail_conf.o: ../../include/dict.h
 mail_conf.o: ../../include/argv.h
 mail_conf.o: ../../include/safe.h
 mail_conf.o: ../../include/stringops.h
+mail_conf.o: ../../include/safe_open.h
 mail_conf.o: mail_params.h
 mail_conf.o: mail_conf.h
 mail_conf_bool.o: mail_conf_bool.c
index 56852b1b0992261063de6472c775cf203ea94d1c..8f35b6c5bbf30918d70247d2f227ff3cf7480a94 100644 (file)
@@ -100,7 +100,7 @@ int     flush_purge(void)
     if (*var_fflush_domains == 0)
        status = FLUSH_STAT_DENY;
     else
-       status = mail_command_client(MAIL_CLASS_PRIVATE, MAIL_SERVICE_FLUSH,
+       status = mail_command_client(MAIL_CLASS_PUBLIC, MAIL_SERVICE_FLUSH,
                              ATTR_TYPE_STR, MAIL_ATTR_REQ, FLUSH_REQ_PURGE,
                                     ATTR_TYPE_END);
 
@@ -126,7 +126,7 @@ int     flush_refresh(void)
     if (*var_fflush_domains == 0)
        status = FLUSH_STAT_DENY;
     else
-       status = mail_command_client(MAIL_CLASS_PRIVATE, MAIL_SERVICE_FLUSH,
+       status = mail_command_client(MAIL_CLASS_PUBLIC, MAIL_SERVICE_FLUSH,
                            ATTR_TYPE_STR, MAIL_ATTR_REQ, FLUSH_REQ_REFRESH,
                                     ATTR_TYPE_END);
 
@@ -152,7 +152,7 @@ int     flush_send(const char *site)
     if (*var_fflush_domains == 0)
        status = FLUSH_STAT_DENY;
     else
-       status = mail_command_client(MAIL_CLASS_PRIVATE, MAIL_SERVICE_FLUSH,
+       status = mail_command_client(MAIL_CLASS_PUBLIC, MAIL_SERVICE_FLUSH,
                               ATTR_TYPE_STR, MAIL_ATTR_REQ, FLUSH_REQ_SEND,
                                     ATTR_TYPE_STR, MAIL_ATTR_SITE, site,
                                     ATTR_TYPE_END);
@@ -179,7 +179,7 @@ int     flush_add(const char *site, const char *queue_id)
     if (*var_fflush_domains == 0)
        status = FLUSH_STAT_DENY;
     else
-       status = mail_command_client(MAIL_CLASS_PRIVATE, MAIL_SERVICE_FLUSH,
+       status = mail_command_client(MAIL_CLASS_PUBLIC, MAIL_SERVICE_FLUSH,
                                ATTR_TYPE_STR, MAIL_ATTR_REQ, FLUSH_REQ_ADD,
                                     ATTR_TYPE_STR, MAIL_ATTR_SITE, site,
                                 ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, queue_id,
index 2af13f29c55ebad309c52f60ccf68871f4cfe01e..7e473477b62acf1c3acdcadbafa165f76b0534b9 100644 (file)
@@ -73,6 +73,7 @@
 /* System library. */
 
 #include <sys_defs.h>
+#include <unistd.h>
 #include <stdlib.h>
 
 /* Utility library. */
 #include <dict.h>
 #include <safe.h>
 #include <stringops.h>
+#include <readlline.h>
 
 /* Global library. */
 
 #include "mail_params.h"
 #include "mail_conf.h"
 
+/* mail_conf_checkdir - authorize non-default directory */
+
+static void mail_conf_checkdir(const char *config_dir)
+{
+    VSTRING *buf;
+    VSTREAM *fp;
+    char   *path;
+    char   *name;
+    char   *value;
+    char   *cp;
+    int     found = 0;
+
+    /*
+     * If running set-[ug]id, require that a non-default configuration
+     * directory name is blessed as a bona fide configuration directory in
+     * the default main.cf file.
+     */
+    path = concatenate(DEF_CONFIG_DIR, "/", "main.cf", (char *) 0);
+    if ((fp = vstream_fopen(path, O_RDONLY, 0)) == 0)
+       msg_fatal("open file %s: %m", path);
+
+    buf = vstring_alloc(1);
+    while (found == 0 && readlline(buf, fp, (int *) 0)) {
+       if (split_nameval(vstring_str(buf), &name, &value) == 0
+           && strcmp(name, VAR_CONFIG_DIRS) == 0) {
+           while (found == 0 && (cp = mystrtok(&value, "\t\r\n")) != 0)
+               if (strcmp(cp, config_dir) == 0)
+                   found = 1;
+       }
+    }
+    if (vstream_fclose(fp))
+       msg_fatal("read file %s: %m", path);
+    vstring_free(buf);
+
+    if (found == 0) {
+       msg_error("untrusted configuration directory name: %s", config_dir);
+       msg_fatal("specify \"%s = %s\" in %s",
+                 VAR_CONFIG_DIRS, config_dir, path);
+    }
+    myfree(path);
+}
+
 /* mail_conf_read - read global configuration file */
 
 void    mail_conf_read(void)
@@ -114,9 +158,19 @@ void    mail_conf_suck(void)
     dict_unknown_allowed = 1;
     if (var_config_dir)
        myfree(var_config_dir);
-    var_config_dir = mystrdup((config_dir = safe_getenv(CONF_ENV_PATH)) != 0 ?
-                             config_dir : DEF_CONFIG_DIR);     /* XXX */
+    if ((config_dir = getenv(CONF_ENV_PATH)) == 0)
+       config_dir = DEF_CONFIG_DIR;
+    var_config_dir = mystrdup(config_dir);
     set_mail_conf_str(VAR_CONFIG_DIR, var_config_dir);
+
+    /*
+     * If the configuration directory name comes from a different trust
+     * domain, require that it is listed in the default main.cf file.
+     */
+    if (strcmp(var_config_dir, DEF_CONFIG_DIR) != 0    /* non-default */
+       && safe_getenv(CONF_ENV_PATH) == 0      /* non-default */
+       && geteuid() != 0)                      /* untrusted */
+       mail_conf_checkdir(var_config_dir);
     path = concatenate(var_config_dir, "/", "main.cf", (char *) 0);
     dict_load_file(CONFIG_DICT, path);
     myfree(path);
index 019a0fe89b90bc1180f6bdd2677298b21bfbb513..0200dca378c2e39c4e2e3afbadd1cf535f719e12 100644 (file)
@@ -65,6 +65,7 @@
 /*     char    *var_verp_delims;
 /*     char    *var_verp_filter;
 /*     char    *var_par_dom_match;
+/*     char    *var_config_dirs;
 /*
 /*     char    *var_import_environ;
 /*     char    *var_export_environ;
@@ -190,6 +191,7 @@ char   *var_verp_delims;
 char   *var_verp_filter;
 int     var_in_flow_delay;
 char   *var_par_dom_match;
+char   *var_config_dirs;
 
 char   *var_import_environ;
 char   *var_export_environ;
@@ -318,6 +320,7 @@ void    mail_params_init()
        VAR_VERP_DELIMS, DEF_VERP_DELIMS, &var_verp_delims, 2, 2,
        VAR_VERP_FILTER, DEF_VERP_FILTER, &var_verp_filter, 1, 0,
        VAR_PAR_DOM_MATCH, DEF_PAR_DOM_MATCH, &var_par_dom_match, 0, 0,
+       VAR_CONFIG_DIRS, DEF_CONFIG_DIRS, &var_config_dirs, 0, 0,
        0,
     };
     static CONFIG_STR_FN_TABLE function_str_defaults_2[] = {
index 3d9f5e89e6cbf93f5046baf80c3d132ac32e0791..60b6a2d90ceace16ff5ba5a5bbcb99b7454d8cd6 100644 (file)
@@ -202,6 +202,10 @@ extern time_t var_starttime;
 #endif
 extern char *var_config_dir;
 
+#define VAR_CONFIG_DIRS                "alternate_config_directory"
+#define DEF_CONFIG_DIRS                ""
+extern char *var_config_dirs;
+
  /*
   * Preferred type of indexed files. The DEF_DB_TYPE macro value is system
   * dependent. It is defined in <sys_defs.h>.
index ced149a490edec2f05105f70eac2404b782d900d..8e4410526b3ae92040354891bac87dfbc12d0abf 100644 (file)
@@ -15,7 +15,7 @@
   * Version of this program.
   */
 #define VAR_MAIL_VERSION       "mail_version"
-#define DEF_MAIL_VERSION       "Snapshot-20011230"
+#define DEF_MAIL_VERSION       "Snapshot-20020101"
 extern char *var_mail_version;
 
 /* LICENSE
index c5f6a37a3894f7c26a5c76499942c430f11f6965..5df775206f47364956c4668c44dde9242777766b 100644 (file)
@@ -280,7 +280,6 @@ static void edit_parameters(int argc, char **argv)
     VSTRING *buf = vstring_alloc(100);
     VSTRING *key = vstring_alloc(10);
     char   *cp;
-    char   *ep;
     char   *edit_key;
     char   *edit_val;
     HTABLE *table;
@@ -292,18 +291,7 @@ static void edit_parameters(int argc, char **argv)
     HTABLE_INFO **ht_info;
     HTABLE_INFO **ht;
     int     interesting;
-
-    /*
-     * Ugly macros to make complex expressions less unreadable.
-     */
-#define SKIP(start, var, cond) \
-        for (var = start; *var && (cond); var++);
-
-#define TRIM(s) { \
-        char *p; \
-        for (p = (s) + strlen(s); p > (s) && ISSPACE(p[-1]); p--); \
-        *p = 0; \
-    }
+    const char *err;
 
     /*
      * Store command-line parameters for quick lookup.
@@ -312,17 +300,12 @@ static void edit_parameters(int argc, char **argv)
     while ((cp = *argv++) != 0) {
        if (strchr(cp, '\n') != 0)
            msg_fatal("edit accepts no multi-line input");
-       SKIP(cp, edit_key, ISSPACE(*edit_key)); /* find key begin */
-       if (*edit_key == '#')
+       while (ISSPACE(*cp))
+            cp++;
+       if (*cp == '#')
            msg_fatal("edit accepts no comment input");
-       SKIP(edit_key, ep, !ISSPACE(*ep) && *ep != '=');        /* key end */
-       SKIP(ep, cp, ISSPACE(*cp));             /* skip blanks before '=' */
-       if (*cp != '=')                         /* need '=' */
-           msg_fatal("missing '=' after attribute name: \"%s\"", edit_key);
-       *ep = 0;                                /* terminate key */
-       cp++;                                   /* skip over '=' */
-       SKIP(cp, edit_val, ISSPACE(*edit_val)); /* skip leading blanks */
-       TRIM(edit_val);                         /* trim trailing blanks */
+       if ((err = split_nameval(cp, &edit_key, &edit_val)) != 0)
+           msg_fatal("%s: \"%s\"", err, cp);
        cvalue = (struct cvalue *) mymalloc(sizeof(*cvalue));
        cvalue->value = edit_val;
        cvalue->found = 0;
@@ -366,7 +349,8 @@ static void edit_parameters(int argc, char **argv)
 
     interesting = 0;
     while (vstring_get(buf, src) != VSTREAM_EOF) {
-       SKIP(STR(buf), cp, ISSPACE(*cp) /* including newline */ );
+       for (cp = STR(buf); ISSPACE(*cp) /* including newline */ ; cp++)
+             /* void */ ;
        /* Copy comment, all-whitespace, or empty line. */
        if (*cp == '#' || *cp == 0) {
            vstream_fputs(STR(buf), dst);
index 1dc606f40ab40a06326f21b4fce6a7aaa2ffac6a..0176bee50693cb4d491da163025171a1a0f11e88 100644 (file)
@@ -4,20 +4,29 @@
 /* SUMMARY
 /*     Postfix mail posting utility
 /* SYNOPSIS
-/*     \fBpostdrop\fR [\fIoption ...\fR]
+/*     \fBpostdrop\fR [\fI-rv\fR] [\fB-c \fIconfig_dir\fR]
 /* DESCRIPTION
 /*     The \fBpostdrop\fR command creates a file in the \fBmaildrop\fR
 /*     directory and copies its standard input to the file.
 /*
 /*     Options:
+/* .IP \fB-c \fIconfig_dir\fR
+/*     The \fBmain.cf\fR configuration file is in the named directory
+/*     instead of the default configuration directory. See also the
+/*     MAIL_CONFIG environment setting below.
+/* .IP \fB-r\fR
+/*     Use a Postfix-internal protocol for reading the message from
+/*     standard input, and for reporting status information on standard
+/*     output. This is currently the only supported method.
 /* .IP \fB-v\fR
 /*     Enable verbose logging for debugging purposes. Multiple \fB-v\fR
 /*     options make the software increasingly verbose.
 /* SECURITY
 /* .ad
 /* .fi
-/*     The command is designed to run with set-gid privileges, and with
-/*     group write permission to the \fBmaildrop\fR queue directory.
+/*     The command is designed to run with set-group ID privileges, so
+/*     that it can write to the \fBmaildrop\fR queue directory and so that
+/*     it can connect to Postfix daemon processes.
 /* DIAGNOSTICS
 /*     Fatal errors: malformed input, I/O error, out of memory. Problems
 /*     are logged to \fBsyslogd\fR(8) and to the standard error stream.
 /* ENVIRONMENT
 /* .ad
 /* .fi
-/*     The program deletes most environment information, because the C
-/*     library can't be trusted.
+/* .IP MAIL_CONFIG
+/*     Directory with the \fBmain.cf\fR file. In order to avoid exploitation
+/*     of set-group ID privileges, it is not possible to specify arbitrary
+/*     directory names.
+/*
+/*     A non-standard directory is allowed only if the name is listed in the
+/*     standard \fBmain.cf\fR file, in the \fBalternate_config_directory\fR
+/*     configuration parameter value.
+/*
+/*     Only the super-user is allowed to specify arbitrary directory names.
 /* FILES
 /*     /var/spool/postfix, mail queue
 /*     /etc/postfix, configuration files
@@ -186,6 +203,27 @@ int     main(int argc, char **argv)
     msg_syslog_init(mail_task(argv[0]), LOG_PID, LOG_FACILITY);
     set_mail_conf_str(VAR_PROCNAME, var_procname = mystrdup(argv[0]));
 
+    /*
+     * Parse JCL. This program is set-gid and must sanitize all command-line
+     * arguments. The configuration directory argument is validated by the
+     * mail configuration read routine.
+     */
+    while ((c = GETOPT(argc, argv, "c:rv")) > 0) {
+       switch (c) {
+       case 'c':
+           if (setenv(CONF_ENV_PATH, optarg, 1) < 0)
+               msg_fatal("out of memory");
+           break;
+       case 'r':                               /* forward compatibility */
+           break;
+       case 'v':
+           msg_verbose++;
+           break;
+       default:
+           msg_fatal("usage: %s [-c config_dir] [-v]", argv[0]);
+       }
+    }
+
     /*
      * Read the global configuration file and extract configuration
      * information. Some claim that the user should supply the working
@@ -229,19 +267,6 @@ int     main(int argc, char **argv)
     signal(SIGTERM, postdrop_sig);
     msg_cleanup(postdrop_cleanup);
 
-    /*
-     * Parse JCL.
-     */
-    while ((c = GETOPT(argc, argv, "v")) > 0) {
-       switch (c) {
-       case 'v':
-           msg_verbose++;
-           break;
-       default:
-           msg_fatal("usage: %s [-v]", argv[0]);
-       }
-    }
-
     /*
      * Create queue file. mail_stream_file() never fails. Send the queue ID
      * to the caller. Stash away a copy of the queue file name so we can
index 85796b0033436ff9c3908a6d54430fab2e9490ea..69cae635cbaafc66bd2c0121d4fa9955b3c06e40 100644 (file)
@@ -4,17 +4,21 @@
 /* SUMMARY
 /*     Postfix queue control
 /* SYNOPSIS
-/*     \fBpostqueue\fR \fB-f\fR
+/*     \fBpostqueue\fR [\fB-c \fIconfig_dir\fR] \fB-f\fR
 /* .br
-/*     \fBpostqueue\fR \fB-p\fR
+/*     \fBpostqueue\fR [\fB-c \fIconfig_dir\fR] \fB-p\fR
 /* .br
-/*     \fBpostqueue\fR \fB-s \fIsite\fR
+/*     \fBpostqueue\fR [\fB-c \fIconfig_dir\fR] \fB-s \fIsite\fR
 /* DESCRIPTION
 /*     The \fBpostqueue\fR program implements the Postfix user interface
 /*     for queue management. It implements all the operations that are
 /*     traditionally available via the \fBsendmail\fR(1) command.
 /*
 /*     The following options are recognized:
+/* .IP \fB-c \fIconfig_dir\fR
+/*     The \fBmain.cf\fR configuration file is in the named directory
+/*     instead of the default configuration directory. See also the
+/*     MAIL_CONFIG environment setting below.
 /* .IP \fB-f\fR
 /*     Flush the queue: attempt to deliver all queued mail.
 /*
 /*     service.
 /*
 /*     This option implements the traditional \fBsendmail -qR\fIsite\fR
-/*     command, by connecting to the SMTP server at \fB$myhostname\fR.
+/*     command, by contacting the Postfix \fBflush\fR(8) daemon.
 /* .IP \fB-v\fR
 /*     Enable verbose logging for debugging purposes. Multiple \fB-v\fR
 /*     options make the software increasingly verbose.
 /* SECURITY
 /* .ad
 /* .fi
-/*     By design, this program is set-user (or group) id, so that it
-/*     can connect to public, but protected, Postfix daemon processes.
+/*     This program is designed to run with set-group ID privileges, so
+/*     that it can connect to Postfix daemon processes.
 /* DIAGNOSTICS
 /*     Problems are logged to \fBsyslogd\fR(8) and to the standard error
 /*     stream.
 /* ENVIRONMENT
 /* .ad
 /* .fi
-/*     The program deletes most environment information, because the C
-/*     library can't be trusted.
+/* .IP MAIL_CONFIG
+/*     Directory with the \fBmain.cf\fR file.
+/*
+/*     In order to avoid exploitation of set-group ID privileges, it is not
+/*     possible to specify arbitrary directory names.
+/*
+/*     A non-standard directory is allowed only if the name is listed in the
+/*     standard \fBmain.cf\fR file, in the \fBalternate_config_directory\fR
+/*     configuration parameter value.
+/*
+/*     Only the super-user is allowed to specify arbitrary directory names.
 /* FILES
 /*     /var/spool/postfix, mail queue
 /*     /etc/postfix, configuration files
 #include <unistd.h>
 #include <string.h>
 #include <stdlib.h>
-#include <errno.h>
 #include <signal.h>
 #include <sysexits.h>
 
 #include <argv.h>
 #include <safe.h>
 #include <connect.h>
+#include <valid_hostname.h>
 
 /* Global library. */
 
 #include <debug_process.h>
 #include <mail_run.h>
 #include <mail_flush.h>
+#include <flush_clnt.h>
 #include <smtp_stream.h>
 
 /* Application-specific. */
 #define PQ_MODE_FLUSH_QUEUE    2       /* flush queue */
 #define PQ_MODE_FLUSH_SITE     3       /* flush site */
 
- /*
-  * Error handlers.
-  */
-static void postqueue_cleanup(void);
-static NORETURN PRINTFLIKE(2, 3) fatal_error(int, const char *,...);
-
  /*
   * Silly little macros (SLMs).
   */
@@ -184,8 +192,8 @@ static void show_queue(void)
      * showq daemon.
      */
     else {
-       fatal_error(EX_UNAVAILABLE,
-                   "Queue report unavailable - mail system is down");
+       msg_fatal_status(EX_UNAVAILABLE,
+                        "Queue report unavailable - mail system is down");
     }
 }
 
@@ -198,107 +206,39 @@ static void flush_queue(void)
      * Trigger the flush queue service.
      */
     if (mail_flush_deferred() < 0)
-       fatal_error(EX_UNAVAILABLE,
-                   "Cannot flush mail queue - mail system is down");
-}
-
-/* chat - send command and examine reply */
-
-static void chat(VSTREAM * fp, VSTRING * buf, const char *fmt,...)
-{
-    va_list ap;
-
-    smtp_get(buf, fp, var_line_limit);
-    if (STR(buf)[0] != '2')
-       fatal_error(EX_UNAVAILABLE, "server rejected ETRN request: %s",
-                   STR(buf));
-
-    if (msg_verbose)
-       msg_info("<<< %s", STR(buf));
-
-    if (msg_verbose) {
-       va_start(ap, fmt);
-       vstring_vsprintf(buf, fmt, ap);
-       va_end(ap);
-       msg_info(">>> %s", STR(buf));
-    }
-    va_start(ap, fmt);
-    smtp_vprintf(fp, fmt, ap);
-    va_end(ap);
+       msg_fatal_status(EX_UNAVAILABLE,
+                        "Cannot flush mail queue - mail system is down");
 }
 
 /* flush_site - flush mail for site */
 
 static void flush_site(const char *site)
 {
-    VSTRING *buf = vstring_alloc(10);
-    VSTREAM *fp;
-    int     sock;
     int     status;
 
-    /*
-     * Make connection to the local SMTP server. Translate "connection
-     * refused" into something less misleading.
-     */
-    vstring_sprintf(buf, "%s:smtp", var_myhostname);
-    if ((sock = inet_connect(STR(buf), BLOCKING, 10)) < 0) {
-       if (errno == ECONNREFUSED)
-           fatal_error(EX_UNAVAILABLE, "mail service at %s is down",
-                       var_myhostname);
-       fatal_error(EX_UNAVAILABLE, "connect to mail service at %s: %m",
-                   var_myhostname);
-    }
-    fp = vstream_fdopen(sock, O_RDWR);
-
-    /*
-     * Prepare for trouble.
-     */
-    vstream_control(fp, VSTREAM_CTL_EXCEPT, VSTREAM_CTL_END);
-    status = vstream_setjmp(fp);
-    if (status != 0) {
-       switch (status) {
-       case SMTP_ERR_EOF:
-           fatal_error(EX_UNAVAILABLE, "server at %s aborted connection",
-                       var_myhostname);
-       case SMTP_ERR_TIME:
-           fatal_error(EX_IOERR,
-                  "timeout while talking to server at %s", var_myhostname);
-       }
+    switch (status = flush_send(site)) {
+    case FLUSH_STAT_OK:
+       exit(0);
+    case FLUSH_STAT_BAD:
+       msg_fatal_status(EX_USAGE, "Invalid request: \"%s\"", site);
+    case FLUSH_STAT_FAIL:
+       msg_fatal_status(EX_UNAVAILABLE,
+                        "Cannot flush mail queue - mail system is down");
+    case FLUSH_STAT_DENY:
+       msg_fatal_status(EX_UNAVAILABLE,
+                  "Flush service is not configured for destination \"%s\"",
+                        site);
+    default:
+       msg_fatal_status(EX_SOFTWARE,
+                        "Unknown flush server reply status %d", status);
     }
-    smtp_timeout_setup(fp, 60);
-
-    /*
-     * Chat with the SMTP server.
-     */
-    chat(fp, buf, "helo %s", var_myhostname);
-    chat(fp, buf, "etrn %s", site);
-    chat(fp, buf, "quit");
-
-    vstream_fclose(fp);
-    vstring_free(buf);
-}
-
-static int fatal_status;
-
-/* postqueue_cleanup - callback for the runtime error handler */
-
-static NORETURN postqueue_cleanup(void)
-{
-    exit(fatal_status > 0 ? fatal_status : 1);
 }
 
-/* fatal_error - give up and notify parent */
+/* usage - scream and die */
 
-static void fatal_error(int status, const char *fmt,...)
+static NORETURN usage(void)
 {
-    VSTRING *text = vstring_alloc(10);
-    va_list ap;
-
-    fatal_status = status;
-    va_start(ap, fmt);
-    vstring_vsprintf(text, fmt, ap);
-    va_end(ap);
-    msg_fatal("%s", vstring_str(text));
+    msg_fatal_status(EX_USAGE, "usage: specify one of -f, -p, or -s");
 }
 
 /* main - the main program */
@@ -310,9 +250,9 @@ int     main(int argc, char **argv)
     int     c;
     int     fd;
     int     mode = PQ_MODE_DEFAULT;
-    int     debug_me = 0;
     char   *site_to_flush = 0;
     ARGV   *import_env;
+    char   *last;
 
     /*
      * Be consistent with file permissions.
@@ -327,7 +267,7 @@ int     main(int argc, char **argv)
     for (fd = 0; fd < 3; fd++)
        if (fstat(fd, &st) == -1
            && (close(fd), open("/dev/null", O_RDWR, 0)) != fd)
-           fatal_error(EX_UNAVAILABLE, "open /dev/null: %m");
+           msg_fatal_status(EX_UNAVAILABLE, "open /dev/null: %m");
 
     /*
      * Initialize. Set up logging, read the global configuration file and
@@ -341,47 +281,76 @@ int     main(int argc, char **argv)
     set_mail_conf_str(VAR_PROCNAME, var_procname = mystrdup(argv[0]));
 
     /*
-     * Further initialization...
+     * Parse JCL. This program is set-gid and must sanitize all command-line
+     * parameters. The configuration directory argument is validated by the
+     * mail configuration read routine.
      */
-    mail_conf_read();
-
-    /*
-     * Strip the environment so we don't have to trust the C library.
-     */
-    import_env = argv_split(var_import_environ, ", \t\r\n");
-    clean_env(import_env->argv);
-    argv_free(import_env);
-
-    if (chdir(var_queue_dir))
-       fatal_error(EX_UNAVAILABLE, "chdir %s: %m", var_queue_dir);
-
-    signal(SIGPIPE, SIG_IGN);
-    msg_cleanup(postqueue_cleanup);
-
-    /*
-     * Parse JCL.
-     */
-    while ((c = GETOPT(argc, argv, "fps:v")) > 0) {
+    while ((c = GETOPT(argc, argv, "c:fps:v")) > 0) {
        switch (c) {
+       case 'c':                               /* non-default configuration */
+           if (setenv(CONF_ENV_PATH, optarg, 1) < 0)
+               msg_fatal_status(EX_UNAVAILABLE, "out of memory");
+           break;
        case 'f':                               /* flush queue */
+           if (mode != PQ_MODE_DEFAULT)
+               usage();
            mode = PQ_MODE_FLUSH_QUEUE;
            break;
        case 'p':                               /* traditional mailq */
+           if (mode != PQ_MODE_DEFAULT)
+               usage();
            mode = PQ_MODE_MAILQ_LIST;
            break;
            break;
        case 's':                               /* flush site */
+           if (mode != PQ_MODE_DEFAULT)
+               usage();
            mode = PQ_MODE_FLUSH_SITE;
-           site_to_flush = optarg;
+           if (*optarg == '[' && *(last = optarg + strlen(optarg) - 1) == ']') {
+
+               *last = 0;
+               if (valid_hostaddr(optarg + 1, DONT_GRIPE))
+                   site_to_flush = optarg;
+               else
+                   site_to_flush = 0;
+               *last = ']';
+           } else {
+               if (valid_hostname(optarg, DONT_GRIPE)
+                   || valid_hostaddr(optarg, DONT_GRIPE))
+                   site_to_flush = optarg;
+               else
+                   site_to_flush = 0;
+           }
+           if (site_to_flush == 0)
+               msg_fatal_status(EX_USAGE,
+                                "Cannot flush mail queue - invalid destination: \"%.100s%s\"",
+                                optarg, strlen(optarg) > 100 ? "..." : "");
            break;
        case 'v':
            msg_verbose++;
            break;
        default:
-           fatal_error(EX_USAGE, "usage: %s -[fpsv]", argv[0]);
+           usage();
        }
     }
 
+    /*
+     * Further initialization...
+     */
+    mail_conf_read();
+
+    /*
+     * Strip the environment so we don't have to trust the C library.
+     */
+    import_env = argv_split(var_import_environ, ", \t\r\n");
+    clean_env(import_env->argv);
+    argv_free(import_env);
+
+    if (chdir(var_queue_dir))
+       msg_fatal_status(EX_UNAVAILABLE, "chdir %s: %m", var_queue_dir);
+
+    signal(SIGPIPE, SIG_IGN);
+
     /*
      * Start processing.
      */
@@ -402,7 +371,7 @@ int     main(int argc, char **argv)
        exit(0);
        break;
     case PQ_MODE_DEFAULT:
-       fatal_error(EX_USAGE, "usage: %s -[fpsv]", argv[0]);
-       break;
+       usage();
+       /* NOTREACHED */
     }
 }
index ba9367d12d0fcf55bc2d1649471e6c93462fbd94..54cb2443f2de331998421f0c42e9fb642aad1d8a 100644 (file)
 #define SM_MODE_USER           5       /* user (stand-alone) mode */
 #define SM_MODE_FLUSHQ         6       /* user (stand-alone) mode */
 
- /*
-  * Queue file name. Global, so that the cleanup routine can find it when
-  * called by the run-time error handler.
-  */
-static void sendmail_cleanup(void);
-static NORETURN PRINTFLIKE(2, 3) fatal_error(int, const char *,...);
-
  /*
   * Flag parade.
   */
@@ -393,7 +386,7 @@ static void enqueue(const int flags, const char *sender, const char *full_name,
            msg_warn("-f option specified malformed sender: %s", sender);
     } else {
        if ((sender = username()) == 0)
-           fatal_error(EX_OSERR, "unable to find out your login name");
+           msg_fatal_status(EX_OSERR, "unable to find out your login name");
        saved_sender = mystrdup(sender);
     }
 
@@ -402,11 +395,11 @@ static void enqueue(const int flags, const char *sender, const char *full_name,
      * the content. XXX Make postdrop a manifest constant.
      */
     errno = 0;
-    postdrop_command = concatenate(var_command_dir, "/postdrop",
+    postdrop_command = concatenate(var_command_dir, "/postdrop -r",
                              msg_verbose ? " -v" : (char *) 0, (char *) 0);
     if ((handle = mail_stream_command(postdrop_command)) == 0)
-       fatal_error(EX_UNAVAILABLE, "%s(%ld): unable to execute %s: %m",
-                   saved_sender, (long) uid, postdrop_command);
+       msg_fatal_status(EX_UNAVAILABLE, "%s(%ld): unable to execute %s: %m",
+                        saved_sender, (long) uid, postdrop_command);
     myfree(postdrop_command);
     dst = handle->stream;
 
@@ -438,9 +431,9 @@ static void enqueue(const int flags, const char *sender, const char *full_name,
                if (tp->type == TOK822_ADDR) {
                    tok822_internalize(buf, tp->head, TOK822_STR_DEFL);
                    if (REC_PUT_BUF(dst, REC_TYPE_RCPT, buf) < 0)
-                       fatal_error(EX_TEMPFAIL,
+                       msg_fatal_status(EX_TEMPFAIL,
                                    "%s(%ld): error writing queue file: %m",
-                                   saved_sender, (long) uid);
+                                        saved_sender, (long) uid);
                }
            }
            tok822_free_tree(tree);
@@ -481,8 +474,9 @@ static void enqueue(const int flags, const char *sender, const char *full_name,
        if ((flags & SM_FLAG_AEOF) && VSTRING_LEN(buf) == 1 && *STR(buf) == '.')
            break;
        if (REC_PUT_BUF(dst, type, buf) < 0)
-           fatal_error(EX_TEMPFAIL, "%s(%ld): error writing queue file: %m",
-                       saved_sender, (long) uid);
+           msg_fatal_status(EX_TEMPFAIL,
+                            "%s(%ld): error writing queue file: %m",
+                            saved_sender, (long) uid);
     }
 
     /*
@@ -503,13 +497,13 @@ static void enqueue(const int flags, const char *sender, const char *full_name,
      * handler from removing the file.
      */
     if (vstream_ferror(VSTREAM_IN))
-       fatal_error(EX_DATAERR, "%s(%ld): error reading input: %m",
-                   saved_sender, (long) uid);
+       msg_fatal_status(EX_DATAERR, "%s(%ld): error reading input: %m",
+                        saved_sender, (long) uid);
     if ((status = mail_stream_finish(handle, (VSTRING *) 0)) != 0)
-       fatal_error((status & CLEANUP_STAT_BAD) ? EX_SOFTWARE :
-                   (status & CLEANUP_STAT_WRITE) ? EX_TEMPFAIL :
-                   EX_UNAVAILABLE, "%s(%ld): %s", saved_sender,
-                   (long) uid, cleanup_strerror(status));
+       msg_fatal_status((status & CLEANUP_STAT_BAD) ? EX_SOFTWARE :
+                        (status & CLEANUP_STAT_WRITE) ? EX_TEMPFAIL :
+                        EX_UNAVAILABLE, "%s(%ld): %s", saved_sender,
+                        (long) uid, cleanup_strerror(status));
 
     /*
      * Cleanup. Not really necessary as we're about to exit, but good for
@@ -519,35 +513,6 @@ static void enqueue(const int flags, const char *sender, const char *full_name,
     myfree(saved_sender);
 }
 
-static int fatal_status;
-
-/* sendmail_cleanup - callback for the runtime error handler */
-
-static NORETURN sendmail_cleanup(void)
-{
-
-    /*
-     * We're possibly running from a signal handler, so we should not be
-     * doing complicated things such as memory of buffer management, but if
-     * for some reason we can't cleanup it is even worse to just die quietly.
-     */
-    exit(fatal_status > 0 ? fatal_status : 1);
-}
-
-/* fatal_error - give up and notify parent */
-
-static void fatal_error(int status, const char *fmt,...)
-{
-    VSTRING *text = vstring_alloc(10);
-    va_list ap;
-
-    fatal_status = status;
-    va_start(ap, fmt);
-    vstring_vsprintf(text, fmt, ap);
-    va_end(ap);
-    msg_fatal("%s", vstring_str(text));
-}
-
 /* main - the main program */
 
 int     main(int argc, char **argv)
@@ -580,7 +545,7 @@ int     main(int argc, char **argv)
     for (fd = 0; fd < 3; fd++)
        if (fstat(fd, &st) == -1
            && (close(fd), open("/dev/null", O_RDWR, 0)) != fd)
-           fatal_error(EX_UNAVAILABLE, "open /dev/null: %m");
+           msg_fatal_status(EX_UNAVAILABLE, "open /dev/null: %m");
 
     /*
      * The CDE desktop calendar manager leaks a parent file descriptor into
@@ -628,7 +593,7 @@ int     main(int argc, char **argv)
      */
     mail_conf_read();
     if (chdir(var_queue_dir))
-       fatal_error(EX_UNAVAILABLE, "chdir %s: %m", var_queue_dir);
+       msg_fatal_status(EX_UNAVAILABLE, "chdir %s: %m", var_queue_dir);
 
     /*
      * Stop run-away process accidents by limiting the queue file size. This
@@ -638,7 +603,6 @@ int     main(int argc, char **argv)
        set_file_limit((off_t) var_message_limit);
 
     signal(SIGPIPE, SIG_IGN);
-    msg_cleanup(sendmail_cleanup);
 
     /*
      * Optionally start the debugger on ourself. This must be done after
@@ -692,7 +656,7 @@ int     main(int argc, char **argv)
                msg_info("-%c option ignored", c);
            break;
        case 'n':
-           fatal_error(EX_USAGE, "-%c option not supported", c);
+           msg_fatal_status(EX_USAGE, "-%c option not supported", c);
        case 'F':                               /* full name */
            full_name = optarg;
            break;
@@ -701,14 +665,14 @@ int     main(int argc, char **argv)
            break;
        case 'V':                               /* VERP */
            if (verp_delims_verify(optarg) != 0)
-               fatal_error(EX_USAGE, "-V requires two characters from %s",
-                           var_verp_filter);
+               msg_fatal_status(EX_USAGE, "-V requires two characters from %s",
+                                var_verp_filter);
            verp_delims = optarg;
            break;
        case 'b':
            switch (*optarg) {
            default:
-               fatal_error(EX_USAGE, "unsupported: -%c%c", c, *optarg);
+               msg_fatal_status(EX_USAGE, "unsupported: -%c%c", c, *optarg);
            case 'd':                           /* daemon mode */
                if (mode == SM_MODE_FLUSHQ)
                    msg_warn("ignoring -q option in daemon mode");
@@ -742,7 +706,7 @@ int     main(int argc, char **argv)
                break;
            case 'A':
                if (optarg[1] == 0)
-                   fatal_error(EX_USAGE, "-oA requires pathname");
+                   msg_fatal_status(EX_USAGE, "-oA requires pathname");
                myfree(var_alias_db_map);
                var_alias_db_map = mystrdup(optarg + 1);
                set_mail_conf_str(VAR_ALIAS_DB_MAP, var_alias_db_map);
@@ -772,7 +736,8 @@ int     main(int argc, char **argv)
                if (*site_to_flush == 0)
                    msg_fatal("specify: -qRsitename");
            } else {
-               fatal_error(EX_USAGE, "-q%c is not implemented", optarg[0]);
+               msg_fatal_status(EX_USAGE, "-q%c is not implemented",
+                                optarg[0]);
            }
            break;
        case 't':
@@ -782,7 +747,7 @@ int     main(int argc, char **argv)
            msg_verbose++;
            break;
        case '?':
-           fatal_error(EX_USAGE, "usage: %s [options]", argv[0]);
+           msg_fatal_status(EX_USAGE, "usage: %s [options]", argv[0]);
        }
     }
 
index fccaead71ee1e9d2e13e9bbee16b6e218fd04b10..1eb00cbe3948da44f7350d3f8ba99b3ec0e86245 100644 (file)
@@ -19,8 +19,8 @@ SRCS  = alldig.c argv.c argv_split.c attr_print0.c attr_print64.c \
        read_wait.c readable.c readlline.c ring.c safe_getenv.c \
        safe_open.c sane_accept.c sane_link.c sane_rename.c \
        sane_socketpair.c sane_time.c scan_dir.c set_eugid.c set_ugid.c \
-       sigdelay.c skipblanks.c sock_empty_wait.c spawn_command.c \
-       split_at.c stat_as.c stream_connect.c stream_listen.c \
+       sigdelay.c skipblanks.c spawn_command.c split_at.c \
+       split_nameval.c stat_as.c stream_connect.c stream_listen.c \
        stream_trigger.c sys_compat.c timed_connect.c timed_read.c \
        timed_wait.c timed_write.c translit.c trimblanks.c unescape.c \
        unix_connect.c unix_listen.c unix_trigger.c unsafe.c username.c \
@@ -47,8 +47,8 @@ OBJS  = alldig.o argv.o argv_split.o attr_print0.o attr_print64.o \
        read_wait.o readable.o readlline.o ring.o safe_getenv.o \
        safe_open.o sane_accept.o sane_link.o sane_rename.o \
        sane_socketpair.o sane_time.o scan_dir.o set_eugid.o set_ugid.o \
-       sigdelay.o skipblanks.o sock_empty_wait.o spawn_command.o \
-       split_at.o stat_as.o stream_connect.o stream_listen.o \
+       sigdelay.o skipblanks.o spawn_command.o split_at.o \
+       split_nameval.o stat_as.o stream_connect.o stream_listen.o \
        stream_trigger.o sys_compat.o timed_connect.o timed_read.o \
        timed_wait.o timed_write.o translit.o trimblanks.o unescape.o \
        unix_connect.o unix_listen.o unix_trigger.o unsafe.o username.o \
@@ -1038,10 +1038,6 @@ skipblanks.o: sys_defs.h
 skipblanks.o: stringops.h
 skipblanks.o: vstring.h
 skipblanks.o: vbuf.h
-sock_empty_wait.o: sock_empty_wait.c
-sock_empty_wait.o: sys_defs.h
-sock_empty_wait.o: msg.h
-sock_empty_wait.o: iostuff.h
 spawn_command.o: spawn_command.c
 spawn_command.o: sys_defs.h
 spawn_command.o: msg.h
@@ -1054,6 +1050,12 @@ spawn_command.o: clean_env.h
 split_at.o: split_at.c
 split_at.o: sys_defs.h
 split_at.o: split_at.h
+split_nameval.o: split_nameval.c
+split_nameval.o: sys_defs.h
+split_nameval.o: msg.h
+split_nameval.o: stringops.h
+split_nameval.o: vstring.h
+split_nameval.o: vbuf.h
 stat_as.o: stat_as.c
 stat_as.o: sys_defs.h
 stat_as.o: msg.h
index 80184516d9296642096a5279f7e906d4abad3826..5fd308879833603d119bd2e3727d47c14872b196 100644 (file)
 #include "vstring.h"
 #include "readlline.h"
 #include "mac_parse.h"
+#include "stringops.h"
 #include "dict.h"
 #include "dict_ht.h"
 
@@ -372,40 +373,18 @@ void    dict_load_file(const char *dict_name, const char *path)
 void    dict_load_fp(const char *dict_name, VSTREAM *fp)
 {
     VSTRING *buf;
-    char   *start;
     char   *member;
     char   *val;
-    char   *cp;
-    char   *ep;
     int     lineno;
-
-    /*
-     * Ugly macros to make complex expressions less unreadable.
-     */
-#define SKIP(start, var, cond) \
-       for (var = start; *var && (cond); var++);
-
-#define TRIM(s) { \
-       char *p; \
-       for (p = (s) + strlen(s); p > (s) && ISSPACE(p[-1]); p--); \
-       *p = 0; \
-    }
+    const char *err;
 
     buf = vstring_alloc(100);
     lineno = 0;
 
     while (readlline(buf, fp, &lineno)) {
-       start = STR(buf);
-       SKIP(start, member, ISSPACE(*member));  /* find member begin */
-       SKIP(member, ep, !ISSPACE(*ep) && *ep != '=');  /* find member end */
-       SKIP(ep, cp, ISSPACE(*cp));             /* skip blanks before '=' */
-       if (*cp != '=')                         /* need '=' */
-           msg_fatal("%s, line %d: missing '=' after attribute name: \"%s\"",
-                     VSTREAM_PATH(fp), lineno, member);
-       *ep = 0;                                /* terminate member name */
-       cp++;                                   /* skip over '=' */
-       SKIP(cp, val, ISSPACE(*val));           /* skip leading blanks */
-       TRIM(val);                              /* trim trailing blanks */
+       if ((err = split_nameval(STR(buf), &member, &val)) != 0)
+           msg_fatal("%s, line %d: %s: \"%s\"",
+                     VSTREAM_PATH(fp), lineno, err, STR(buf));
        dict_update(dict_name, member, val);
     }
     vstring_free(buf);
index ac9681b1d0fed6a46c1f08631c72f1319f573bc6..7da0f297db022e0f913aff5deeaa75ad43fe8e52 100644 (file)
@@ -29,9 +29,6 @@ extern int timed_write(int, void *, unsigned, int, void *);
 extern void doze(unsigned);
 extern void rand_sleep(unsigned, unsigned);
 extern int duplex_pipe(int *);
-extern int sock_empty_wait(int, int);
-extern int sock_maximize_send_lowat(int);
-extern void sock_set_send_lowat(int, int);
 
 #define BLOCKING       0
 #define NON_BLOCKING   1
index 08379a90b86a894dcf4a421212d44e6e81e0618a..683359b2b377c00280e8f8cb97cafeb1c53066ec 100644 (file)
 /*     NORETURN msg_fatal(format, ...)
 /*     const char *format;
 /*
+/*     NORETURN msg_fatal_status(status, format, ...)
+/*     int     status;
+/*     const char *format;
+/*
 /*     NORETURN msg_panic(format, ...)
 /*     const char *format;
 /*
 /*     msg_fatal() reports an unrecoverable error and terminates the program
 /*     with a non-zero exit status.
 /*
+/*     msg_fatal_status() reports an unrecoverable error and terminates the 
+/*     program with the specified exit status.
+/*
 /*     msg_panic() reports an internal inconsistency, terminates the
 /*     program immediately (i.e. without calling the optional user-specified
 /*     cleanup routine), and forces a core dump when possible.
 /*
-/*     msg_cleanup() specifies a function that msg_fatal() should
+/*     msg_cleanup() specifies a function that msg_fatal[_status]() should
 /*     invoke before terminating the program, and returns the
 /*     current function pointer. Specify a null argument to disable
 /*     this feature.
@@ -163,6 +170,23 @@ NORETURN msg_fatal(const char *fmt,...)
     exit(1);
 }
 
+/* msg_fatal_status - report error and terminate gracefully */
+
+NORETURN msg_fatal_status(int status, const char *fmt,...)
+{
+    va_list ap;
+
+    if (msg_exiting++ == 0) {
+       va_start(ap, fmt);
+       msg_vprintf(MSG_FATAL, fmt, ap);
+       va_end(ap);
+       if (msg_cleanup_fn)
+           msg_cleanup_fn();
+    }
+    sleep(1);
+    exit(status);
+}
+
 /* msg_panic - report error and dump core */
 
 NORETURN msg_panic(const char *fmt,...)
index fae8a2327c9689534d7817c69d5875390ff6d283..42198a2a71b899a25a22cdd92dbc7932df774709 100644 (file)
@@ -22,6 +22,7 @@ extern void PRINTFLIKE(1, 2) msg_info(const char *,...);
 extern void PRINTFLIKE(1, 2) msg_warn(const char *,...);
 extern void PRINTFLIKE(1, 2) msg_error(const char *,...);
 extern NORETURN PRINTFLIKE(1, 2) msg_fatal(const char *,...);
+extern NORETURN PRINTFLIKE(2, 3) msg_fatal_status(int, const char *,...);
 extern NORETURN PRINTFLIKE(1, 2) msg_panic(const char *,...);
 
 extern int msg_error_limit(int);
diff --git a/postfix/src/util/sock_empty_wait.c b/postfix/src/util/sock_empty_wait.c
deleted file mode 100644 (file)
index 8cc6819..0000000
+++ /dev/null
@@ -1,207 +0,0 @@
-/*++
-/* NAME
-/*     sock_empty_wait 3
-/* SUMMARY
-/*     wait until socket send buffer is near empty
-/* SYNOPSIS
-/*     #include <iostuff.h>
-/*
-/*     int     sock_empty_wait(fd, timeout)
-/*     int     fd;
-/*     int     timeout;
-/* AUXILIARY ROUTINES
-/*     int     sock_maximize_send_lowat(fd)
-/*     int     fd;
-/*
-/*     void    sock_set_send_lowat(fd, send_lowat)
-/*     int     fd;
-/*     int     send_lowat;
-/* DESCRIPTION
-/*     sock_empty_wait() blocks the process until the specified socket's
-/*     send buffer is near empty, in the hope that the contents of the
-/*     next write() operation will not be merged with preceding data.
-/*
-/*     sock_maximize_send_lowat() maximizes the socket send buffer
-/*     low-water mark, which controls how much free buffer space must
-/*     be available before the socket is considered writable.
-/*     The result value is the old low-water mark value.
-/*
-/*     sock_set_send_lowat() sets the socket send buffer low-water mark
-/*     to the specified value.
-/*
-/*     Arguments:
-/* .IP fd
-/*     File descriptor in the range 0..FD_SETSIZE.
-/* .IP timeout
-/*     If positive, deadline in seconds. A zero value effects a poll.
-/*     A negative value means wait until something happens.
-/* DIAGNOSTICS
-/*     sock_maximize_send_lowat() returns -1 if the kernel does not
-/*     support access to or control over the send buffer low-water mark.
-/*     Otherwise, all system call errors are fatal.
-/*
-/*     A zero result means success.  When the specified deadline is
-/*     exceeded, sock_empty_wait() returns -1 and sets errno to ETIMEDOUT.
-/* BUGS
-/*     Linux and Solaris do not provide the necessary support. Until
-/*     they become better citizens they are punished by having to sleep
-/*     for 10 seconds, and even then there is no reasonable way to find
-/*     out if all the written data was acknowledged by the remote TCP.
-/* 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/socket.h>
-#include <errno.h>
-#include <unistd.h>
-#include <string.h>
-
-/* Utility library. */
-
-#include <msg.h>
-#include <iostuff.h>
-
-/* sock_maximize_send_lowat - maximize the send buffer low-water mark */
-
-int     sock_maximize_send_lowat(int fd)
-{
-    char   *myname = "sock_maximize_send_lowat";
-    int     send_buffer_size;
-    int     saved_low_water_mark;
-    int     want_low_water_mark;
-    int     got_low_water_mark;
-    SOCKOPT_SIZE optlen;
-
-    /*
-     * Get the send buffer size. If this succeeds then we know the file
-     * handle is a socket.
-     */
-    optlen = sizeof(send_buffer_size);
-    if (getsockopt(fd, SOL_SOCKET, SO_SNDBUF,
-                  (char *) &send_buffer_size, &optlen) < 0)
-       msg_fatal("%s: getsockopt SO_SNDBUF: %m", myname);
-
-    /*
-     * Save the send buffer low-water mark. XXX Solaris 8 does not support
-     * this operation.
-     */
-    optlen = sizeof(saved_low_water_mark);
-    if (getsockopt(fd, SOL_SOCKET, SO_SNDLOWAT,
-                  (char *) &saved_low_water_mark, &optlen) < 0) {
-       if (msg_verbose)
-           msg_info("%s: getsockopt SO_SNDLOWAT: %m", myname);
-       return (-1);
-    }
-
-    /*
-     * Max out the send buffer low-water mark. XXX Linux 2.4.14 does not
-     * support this operation.
-     */
-    want_low_water_mark = send_buffer_size;
-    if (setsockopt(fd, SOL_SOCKET, SO_SNDLOWAT,
-                  (char *) &want_low_water_mark,
-                  sizeof(want_low_water_mark)) < 0) {
-       if (msg_verbose)
-           msg_info("%s: setsockopt SO_SNDLOWAT: %m", myname);
-       return (-1);
-    }
-
-    /*
-     * Make sure the kernel did not cheat.
-     */
-    optlen = sizeof(got_low_water_mark);
-    if (getsockopt(fd, SOL_SOCKET, SO_SNDLOWAT,
-                  (char *) &got_low_water_mark, &optlen) < 0)
-       msg_fatal("%s: getsockopt SO_SNDLOWAT: %m", myname);
-    if (got_low_water_mark == 1)
-       return (-1);
-
-    /*
-     * Make debugging a bit easier.
-     */
-    if (msg_verbose) {
-       msg_info("%s: send buffer %d, low-water mark was %d, wanted %d, got %d",
-                myname, send_buffer_size, saved_low_water_mark,
-                want_low_water_mark, got_low_water_mark);
-
-    }
-    return (saved_low_water_mark);
-}
-
-/* sock_set_send_lowat - restore socket send buffer low-water mark */
-
-void    sock_set_send_lowat(int fd, int want_low_water_mark)
-{
-    char   *myname = "sock_set_send_lowat";
-    int     got_low_water_mark;
-    SOCKOPT_SIZE optlen;
-
-    /*
-     * Set the send buffer low-water mark.
-     */
-    if (setsockopt(fd, SOL_SOCKET, SO_SNDLOWAT,
-                  (char *) &want_low_water_mark,
-                  sizeof(want_low_water_mark)) < 0)
-       msg_fatal("%s: setsockopt SO_SNDLOWAT: %m", myname);
-
-    /*
-     * Make debugging a bit easier.
-     */
-    if (msg_verbose) {
-       optlen = sizeof(got_low_water_mark);
-       if (getsockopt(fd, SOL_SOCKET, SO_SNDLOWAT,
-                      (char *) &got_low_water_mark, &optlen) < 0)
-           msg_fatal("%s: getsockopt SO_SNDLOWAT: %m", myname);
-       msg_info("%s: low-water mark wanted %d, got %d",
-                myname, want_low_water_mark, got_low_water_mark);
-    }
-}
-
-/* sock_empty_wait - wait until socket send buffer is near empty */
-
-int     sock_empty_wait(int fd, int timeout)
-{
-    int     saved_errno;
-    int     saved_low_water_mark;
-    int     result;
-
-    /*
-     * Max out the send buffer low-water mark.
-     */
-    saved_low_water_mark = sock_maximize_send_lowat(fd);
-
-    /*
-     * Wait until the socket is considered writable.
-     */
-    result = write_wait(fd, timeout);
-
-    /*
-     * Work around systems that have no functional SO_SNDLOWAT control.
-     */
-    if (result == 0 && saved_low_water_mark <= 0)
-       sleep(10);
-
-    /*
-     * Restore the send buffer low-water mark.
-     */
-    if (saved_low_water_mark > 0) {
-       saved_errno = errno;
-       sock_set_send_lowat(fd, saved_low_water_mark);
-       errno = saved_errno;
-    }
-
-    /*
-     * Done.
-     */
-    return (result);
-}
diff --git a/postfix/src/util/split_nameval.c b/postfix/src/util/split_nameval.c
new file mode 100644 (file)
index 0000000..f3e519b
--- /dev/null
@@ -0,0 +1,94 @@
+/*++
+/* NAME
+/*     split_nameval 3
+/* SUMMARY
+/*     name-value splitter
+/* SYNOPSIS
+/*     #include <split_nameval.h>
+/*
+/*     const char *split_nameval(buf, name, value)
+/*     char    *buf;
+/*     char    **name;
+/*     char    **value;
+/* DESCRIPTION
+/*     split_nameval() takes a logical line from readlline() and expects
+/*     text of the form "name = value" or "name =". The buffer
+/*     argument is broken up into name and value substrings.
+/*
+/*     Arguments:
+/* .IP buf
+/*     Result from readlline() or equivalent. The buffer is modified.
+/* .IP name
+/*     Upon successful completion, this is set to the name
+/*     substring.
+/* .IP value
+/*     Upon successful completion, this is set to the value
+/*     substring.
+/* FEATURES
+/* SEE ALSO
+/*     dict(3) mid-level dictionary routines
+/* BUGS
+/* DIAGNOSTICS
+/*     Fatal errors: out of memory.
+/*
+/*     The result is a null pointer in case of success, a string
+/*     describing the error otherwise: missing '=' after attribute
+/*     name; missing attribute 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 libraries. */
+
+#include "sys_defs.h"
+#include <ctype.h>
+#include <string.h>
+
+/* Utility library. */
+
+#include <msg.h>
+#include <stringops.h>
+
+/* split_nameval - split text into name and value */
+
+const char *split_nameval(char *buf, char **name, char **value)
+{
+    char   *np;                                /* name substring */
+    char   *vp;                                /* value substring */
+    char   *cp;
+    char   *ep;
+
+    /*
+     * Ugly macros to make complex expressions less unreadable.
+     */
+#define SKIP(start, var, cond) \
+       for (var = start; *var && (cond); var++);
+
+#define TRIM(s) { \
+       char *p; \
+       for (p = (s) + strlen(s); p > (s) && ISSPACE(p[-1]); p--); \
+       *p = 0; \
+    }
+
+    SKIP(buf, np, ISSPACE(*np));               /* find name begin */
+    if (*np == 0)
+       return ("missing attribute name");
+    SKIP(np, ep, !ISSPACE(*ep) && *ep != '='); /* find name end */
+    SKIP(ep, cp, ISSPACE(*cp));                        /* skip blanks before '=' */
+    if (*cp != '=')                            /* need '=' */
+       return ("missing '=' after attribute name");
+    *ep = 0;                                   /* terminate name */
+    cp++;                                      /* skip over '=' */
+    SKIP(cp, vp, ISSPACE(*vp));                        /* skip leading blanks */
+    TRIM(vp);                                  /* trim trailing blanks */
+    *name = np;
+    *value = vp;
+    return (0);
+}
index ca68380584f4b72d22ec85dc0cc4c0144b926176..0cd80c797d13158a6e5cd6b83a40b54b07aa8f98 100644 (file)
@@ -31,6 +31,7 @@ extern char *basename(const char *);
 #endif
 extern VSTRING *unescape(VSTRING *, const char *);
 extern int alldig(const char *);
+extern const char *split_nameval(char *, char **, char **);
 
 /* LICENSE
 /* .ad