diff --git a/contrib/sendmail/KNOWNBUGS b/contrib/sendmail/KNOWNBUGS
index c13be19ba10f..6c7adb11fdf2 100644
--- a/contrib/sendmail/KNOWNBUGS
+++ b/contrib/sendmail/KNOWNBUGS
@@ -29,10 +29,10 @@ This list is not guaranteed to be complete.
* Null bytes are not handled properly in headers.
Sendmail should handle full binary data. As it stands, it handles
- all values in the body, but only 0x01-0x80 and 0xA0-0xFF in
- the header. Notably missing is 0x00, which would require a major
- restructuring of the code -- for example, almost no C library support
- could be used to handle strings.
+ all values in the body, but not 0x00 in the header. Changing
+ this would require a major restructuring of the code -- for
+ example, almost no C library support could be used to handle
+ strings.
* Header checks are not called if header value is too long or empty.
@@ -170,7 +170,7 @@ Kresolve sequence dnsmx canon
When sendmail is doing 8->7 bit MIME conversions, and the message
contains certain MIME body types that cannot be converted to 7-bit,
- sendmail will strip the message to 7-bit.
+ sendmail will pass the message as 8-bit.
* 7->8 bit MIME conversion
@@ -235,9 +235,9 @@ Kresolve sequence dnsmx canon
Sendmail will deliver to a fail if the file is owned by the DefaultUser
or has the set-user-ID bit set. Unfortunately, some systems clear that bit
- when a file is modified. Sendmail compensates by resetting the file mode
+ when a file is modified. Sendmail compensates by resetting the file mode
back to it's original settings. Unfortunately, there's still a
- permission failure race as sendmail checks the permissions before locking
+ permission failure race as sendmail checks the permissions before locking
the file. This is unavoidable as sendmail must verify the file is safe
to open before opening it. A file can not be locked until it is open.
@@ -247,4 +247,4 @@ Kresolve sequence dnsmx canon
be used if set instead of LOCAL_RELAY ($R). This will be fixed in a
future version.
-$Revision: 8.57 $, Last updated $Date: 2004/12/02 23:39:01 $
+$Revision: 8.59 $, Last updated $Date: 2007/02/21 23:13:58 $
diff --git a/contrib/sendmail/PGPKEYS b/contrib/sendmail/PGPKEYS
index d509926244c4..a6d7f5e1403b 100644
--- a/contrib/sendmail/PGPKEYS
+++ b/contrib/sendmail/PGPKEYS
@@ -141,6 +141,82 @@ gpExpdV7qPrw9k01j5rod5PjZlG8zV0=
=SR28
-----END PGP PUBLIC KEY BLOCK-----
+Type Bits KeyID Created Expires Algorithm Use
+pub 1024 0x7093B841 2006-12-16 ---------- RSA Sign & Encrypt
+f16 Fingerprint16 = D9 FD C5 6B EE 1E 7A A8 CE 27 D9 B9 55 8B 56 B6
+uid Sendmail Signing Key/2007
+
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: GnuPG v1.4.5 (OpenBSD)
+
+mQCNA0WDjKsAAAEEAOoLs+uE8cm6SP0S4gvfZrUHd74I9DWSbbiYCwsLoYUm0gcp
+Tp+rTcLBDTrw93cti1vpEAlIz7f/kH+J+OoU0WNAZgBMsSCFZecJvmkrSldCsRJf
+UwBh5FWgDWmb/iNZSAwUpisCa+BGnpKhUkC9g09h7Ss683GApJdDARhwk7hBAAUR
+tDFTZW5kbWFpbCBTaWduaW5nIEtleS8yMDA3IDxzZW5kbWFpbEBTZW5kbWFpbC5P
+Ukc+iQCVAwUQRYOMq5dDARhwk7hBAQFdSAQAuS8Etdrnf9+50VYoFC66SUsf8MLi
+hvH2k8GeAH11weE/8Aij7eR7MerlnyJ5NJVupVDeqK+q7ToaGlb5hq0ya3rbYgwx
+CpzxWTHfvS4/DWs15ajlR3QHkDRZC5pUBAHO0MqC1YskcbndWkmpMhlExb3YVvC6
+5+RyKUmxqw1Rp96JAJUDBRBFg44uHnuzyK+VliUBAcjWA/4kZeVmOOikqAzGRm3i
+coFOr5BUnhxFWTcO5DtnKSvEBPRaj1b7Xz9O0sfEwrGARDigcH2V4yMSxQLJ9Tyx
+S4xjFryTXYPX3+HPLmU97c8VyDF/ANCgdldVW761hXd4i3JCfHm9LMWQBWz4XQaD
+iz56GHoFwvn/nrGmBi/3K+1+/YkAlQMFEEWDjnC92o/WP+p9/QEBIoQEAKitPCB9
+Lab/vs6QhHEW4UdoPTK8EcgsRQTjx+xZ0/XPC3PiLjTXM7cZk7o+oQrp5PGX1RqM
+RV8bzPtJCNiwCctuYpKuYuGjljw8IhZmVxChH/5ifOo7Bw1cxGMWPGlex9x3Xel1
+P4BGi7cOvGGRasEBs5gjtpq795+tDjexh0MwiQCVAwUQRYOOfnxLZ22gDhVjAQHV
+IAQAhE48oNTvzCPAyFf5EEGOsnZBDazqujZS84eAiFvIQfcDcBHCFOaK4wAKsZa4
+YhuYBxu8bz20Kecqfbfnsqyh4b3iJmXiHiL8gIpUzEBBOKesswlzAd7+6hA3/JqN
+8a6djrSo/+GEC6QExnLk98qTnfrfHNbTk/hk4Pxf9343uziJAJUDBRBFg46u1uCh
+/k++Kt0BAS3ZA/9FxlTjvDfI+ujW/Bj+OoWnwCm2OGiLjuWKoiVZjoz2Msp6ZE6I
+1YbqJOwchBpqaHLNyY8x0eiXLYqbrk2kwST1PCAaGQoizK9ClPyptf2V/LUjyyCi
+ppmRNH0rG+WSKsdof4rXRP8FmMicQAW4cme3n5/bq7Z7yQQ4RvSTCMru4IkAlQMF
+EEWDjsuJaWK4Z4wKAwEBKOMEAIRl9rOD0eDvtDe5Uv7j4lIYGxe8xSRKstLzIl6T
+K9spRcrqJk+6OmZHU6MMzkf44z8CB9VWcmozXFxjV+ZkO4SgyJKLZdRc0KGOB+ua
+HL8q5WGMAJ2bLpmJPVoR0PK1Vf97e1kSOWdvIOfwxe8Y1IqoxnGAJmdQh6IJyBc0
+tF6MiQCVAwUQRYOO/XCgJE0e+ZJRAQHhGwP/az5s1kZ6HoJRqg1v/8DOSZEeWECP
+wBw5mgW5dGfPNZ0/Ot9lOy95jlHMu80/YDmpQ6WqsqpnV1hTmj+hYOSPRTqun72l
+IiPh1l0vLl00kw+LxR7T7jPSWvX2l8SjZ176KIFqj3jZpPvMk2W5cE4sjYpvOxRA
+BhheDkERTnUIY+iJAJUDBRBFg48VwCnKQBb0zOkBAVKaBACEb12dzj1pQDFog8h+
+aN9spewVBI0vrxu/3PPZY0tVZJl3S71TXRVmXLYEgeVi5BL8uDuiM14NylUk0lgT
+bVL/VxPsKf9HJVjdfZSbFjUBxxClTIvayTwtMSebO2AcjCiFbMpp2R6VDc791Fp/
+xvuLVr3plYLSQIL9FcBG2wJR1IkAlQMFEEWDj3PvWJZk1DLhnQEBS80D/j05Rlv3
+98Zt+L0hR0+R3qyuf1cFMNyxU5l4Iaf7qr9JRHltHo7iGE8fCGiX1Z3f5BGL03XA
+r1QLusj7nk41W0K5tr3r33qSMjFWLpcOziLbzEAMDQbX0qJQmqCXT+cafiVpao0u
+MqT84L2rKLQxldQM/fvOWExuioiZPKGyE3YuiQCVAwUQRYOPicGcHSUS00YdAQEU
+PwP/Z4PmlZZIhle8P9Bv4c6pkuFkU6LBjF4bWf5bJ675s9Xyh6YwZ5SfFw0deaDZ
+IPXQJQsjcHvbVGoTOxiQtm7y3ae+0TMDbuZSgFD6Fl/IdIdwP2Ob5yoBr1+q353C
+qyLSEI6mX1P4sQwkI272ndSpHowJpuBv6lPr+sZ2uEFzVQSJAJUDBRBFg4+Qb1KT
+2KObplUBAcTnA/9ueiH0gfV1H+8WOm6vUAcvaJ7aCBJ9gdUjheIEY/KDUH/pkGAg
+3E8NDxojTWe88COlIOSqa61UQThSwrtTIx0oWc0E3Bza0cL2xR4apKfNPGWM1/Tp
+kyoD+WYLoVpomT1MA8dBPYUKNuLVunohVscRwmHuUsz8bTTaE4abEnUmwYkAlQMF
+EEWDj5qcHL3i41xWNQEBOJIEALestUaN+JpQ6JvH2zqBFIXPsBoISVuTP/CNlez0
+LSSg9Oi1anMISRNj6cpu8iYYWJxInL05pDCV5MYySB2SzVT8HgrR+3yUdVFgJGBN
+2RYdfXdFqC/d68/50muZzPo+LIwKX+G33B4y0uMSdmK76UhGNW9rfWdQgce7sBph
+1Z1YiQCVAwUQRYOPqTgi20fMN08tAQE7KAQAtYpp2c7OzXPXNJRbodNihpRq1RXd
+qo1nJ7qVHuLVb663GMfy4TwcXytdzJjXAaMf/Rn50skQ+4YGrbIxXC3UbY9NK3xw
+UzebQlzFrjEtPmS0UVyf8GJl6yQ3xuBYZ4Pe+X2hioBDDFZ+Gjn1DA2IQjoZitE5
+B0c9nlknPcv644SJAJUDBRBFg4+zIYPhsTlvB4kBAefCBADFjYutzx72jDt26otM
+k44ZLD6Szv90TKLtRYM5FNhtw9VKFkg+hSo15WzUHKBsnyqBT8Qq6YKz50Wx2vts
+8g2hJ8+g0A+3YuAgNnDp7h7xGS6Fgc5yGnqC0bG7T7TE/YSLfGz97vC0vbm6S6HG
+9Pg+IwKl9dtoE2fkU/BMU2XO+YkAlQMFEEWDj7rI1e0plfYXcQEBi4EEAJ1tRaXf
+aKj9+hVE9lTRbDukb9dsVtAKHP/rRixumf6+v5SCh4g0FzMURJ3jqlwfj2/rPrq2
+MQh1NwhLjVjaEziDCLGxV/TqpK1Yn0vpjmdsaOe01XOxi2+uy/7uo/ArGqtjHSen
+7TmYODY3aKQR19eVehId4TCR1sLO9GmhnYDjiQCVAwUQRY71+s8etQMiMnoBAQGq
+ygP+NdG19Qz0Tf4F4pBRAZiJdIz9hGEzx/Z7rjQhLgzaaGxOQmv2iG/92Fw9/H+M
+ATmTMfbz5gxpLkBsiULI15tgKQWsFwY/pphRKcL9z4+WeTmUkv+tPxVfRYE3YuUc
+QS/3A3DMIv/mcJYA6fiwsf3omzEU8VCyH0uARSJrwQcdmwCJAJUDBRBFjvsM4dT8
+FObQdHEBAeC5A/98yBTBWjhCYvB2XLbbL9dN0DKtV9oqXKhrPI9BAjRi/IeAi04b
+ktzwUC45TLQXlVB1EK27b2mjNwPFcOtM+IrO00gIf1lNh222lSJUISv5rLnHp02j
+xmyQfblYVQ9iPNiJMWNzID59+ntX+MXO71NwyA7UovMTvCcaFWhTrfGk4okAlQMF
+EEWPCSBfHshviAyeVQEBS3wD/04nsshuG5NkdqgL8+E0RycXqXchIJ9GP+Vu9sxB
+aGAh8qzp6xDh6r7A36JCwuUpZWCOC10z4/+QjMwZBQiLH4+deQk7j7L5LxDAWIs6
+DImewMQsg2zF3XlD/Sz+TjKUA1HMwmDOagrygwpbZRYlhJscov/aUeBmUTmaEsP4
+cETBiEYEEBECAAYFAkWPz+8ACgkQOIoVOB4I2B3ysQCgoPb3snzfJrbqM6T/Y+tu
+YfUd59IAnifkpVQIfhZf1aWIPNYXnlYnpVrZiEYEEBECAAYFAkWPshcACgkQorv7
+JAz5Vve5KACg7oh+VFz6UxqjfkiimQ6l/8uI9msAnRB9DBRE6Ebh9CjV15bvm7Y7
+as8y
+=w7F1
+-----END PGP PUBLIC KEY BLOCK-----
+
Type Bits KeyID Created Expires Algorithm Use
pub 1024 0xAF959625 2005-12-31 ---------- RSA Sign & Encrypt
f16 Fingerprint16 = E3 F4 97 BC 9F DF 3F 1D 9B 0D DF D5 77 9A C9 79
@@ -1653,4 +1729,4 @@ DnF3FZZEzV7oqPwC2jzv/1dD6GFhtgy0cnyoPGUJCyc=
=nES8
-----END PGP PUBLIC KEY BLOCK-----
-$Revision: 8.24 $, Last updated $Date: 2006/05/01 19:10:19 $
+$Revision: 8.25 $, Last updated $Date: 2007/01/02 22:38:08 $
diff --git a/contrib/sendmail/RELEASE_NOTES b/contrib/sendmail/RELEASE_NOTES
index 83283c3380cf..64ddbccfea73 100644
--- a/contrib/sendmail/RELEASE_NOTES
+++ b/contrib/sendmail/RELEASE_NOTES
@@ -1,11 +1,279 @@
SENDMAIL RELEASE NOTES
- $Id: RELEASE_NOTES,v 8.1777.2.15 2006/08/07 17:22:09 ca Exp $
+ $Id: RELEASE_NOTES,v 8.1888 2007/04/03 23:28:40 ca Exp $
This listing shows the version of the sendmail binary, the version
of the sendmail configuration files, the date of release, and a
summary of the changes in that release.
+8.14.1/8.14.1 2007/04/03
+ Even though a milter rejects a recipient the MTA will still keep
+ it in its list of recipients and deliver to it if the
+ transaction is accepted. This is a regression introduced
+ in 8.14.0 due to the change for SMFIP_RCPT_REJ. Bug
+ found by Andy Fiddaman.
+ The new DaemonPortOptions which begin with a lower case character
+ could not be set in 8.14.0.
+ If a server shut down the connection in response to a STARTTLS
+ command, sendmail would log a misleading error message
+ due to an internal inconsistency. Problem found by
+ Werner Wiethege.
+ Document how some sendmail.cf options change the behavior of mailq.
+ Noted by Paul Menchini of the North Carolina School of
+ Science and Mathematics.
+ CONFIG: Add confSOFT_BOUNCE m4 option for setting SoftBounce.
+ CONFIG: 8.14.0's RELEASE_NOTES failed to mention the addition
+ of the confMAX_NOOP_COMMANDS and confSHARED_MEMORY_KEY_FILE
+ m4 options for setting MaxNOOPCommands and
+ SharedMemoryKeyFile.
+ CONFIG: Add confMILTER_MACROS_EOH and confMILTER_MACROS_DATA m4
+ options for setting Milter.macros.eoh and Milter.macros.data.
+ CONTRIB: Use flock() and fcntl() in qtool.pl if necessary.
+ Patch from Daniel Carroll of Mesa State College.
+ LIBMILTER: Make sure an unknown command does not affect the
+ currently available macros. Problem found by Andy Fiddaman.
+ LIBMILTER: The MTA did not offer SMFIF_SETSYMLIST during option
+ negotiation. Problem reported by Bryan Costales.
+ LIBMILTER: Fix several minor errors in the documentation.
+ Patches from Bryan Costales.
+ PORTABILITY FIXES:
+ AIX 5.{1,2}: libsm/util.c failed to compile due to
+ redefinition of several macros, e.g., SIG_ERR.
+ Patch from Jim Pirzyk with assistance by Bob
+ Booth, University of Illinois at Urbana-Champaign.
+ Add support for QNX.6. Patch from Sean Boudreau of QNX
+ Software Systems.
+ New Files:
+ devtools/M4/depend/QNX6.m4
+ devtools/OS/QNX.6.x
+ include/sm/os/sm_os_qnx.h
+
+ New Files added in 8.14.0, but not shown in the release notes entry:
+ libmilter/docs/smfi_chgfrom.html
+ libmilter/docs/smfi_version.html
+
+8.14.0/8.14.0 2007/01/31
+ Header field values are now 8 bit clean. Notes:
+ - header field names are still restricted to 7 bit.
+ - RFC 2822 allows only 7 bit (US-ASCII) characters in
+ headers.
+ Preserve spaces after the colon in a header. Previously, any
+ number of spaces after the colon would be changed to
+ exactly one space.
+ In some cases of deeply nested aliases/forwarding, mail can
+ be silently lost. Moreover, the MaxAliasRecursion
+ limit may be reached too early, e.g., the counter
+ may be off by a factor of 4 in case of a sequence of
+ .forward files that refer to others. Patch from
+ Motonori Nakamura of Kyoto University.
+ Fix a regression in 8.13.8: if InputMailFilters is set then
+ "sendmail -bs" can trigger an assertion because the
+ hostname of the client is undefined. It is now set
+ to "localhost" for the xxfi_connect() callback.
+ Avoid referencing a freed variable during cleanup when terminating.
+ Problem reported and diagnosed by Joe Maimon.
+ New option HeloName to set the name for the HELO/EHLO command.
+ Patch from Nik Clayton.
+ New option SoftBounce to issue temporary errors (4xy) instead of
+ permanent errors (5xy). This can be useful for testing.
+ New suboptions for DaemonPortOptions to set them individually
+ per daemon socket:
+ DeliveryMode DeliveryMode
+ refuseLA RefuseLA
+ delayLA DelayLA
+ queueLA QueueLA
+ children MaxDaemonChildren
+ New option -K for LDAP maps to replace %1 through %9 in the
+ lookup key with the LDAP escaped contents of the
+ arguments specified in the map lookup. Loosely based
+ on patch from Wolfgang Hottgenroth.
+ Log the time after which a greet_pause delay triggered. Patch
+ from Nik Clayton.
+ If a client is rejected via TCP wrapper or some other check
+ performed by validate_connection() (in conf.c) then do
+ not also invoke greet_pause. Problem noted by Jim Pirzyk
+ of the University of Illinois at Urbana-Champaign.
+ If a client terminates the SMTP connection during a pause
+ introduced by greet_pause, then a misleading message
+ was logged previously. Problem noted by Vernon Schryver
+ et.al., patch from Matej Vela.
+ New command "mstat" for control socket to provide "machine
+ readable" status.
+ New named config file rule check_eom which is called at the end
+ of a message, its parameter is the size of the message.
+ If the macro {addr_type} indicates that the current address
+ is a header address it also distinguishes between
+ recipient and sender addresses (as it is done for
+ envelope addresses).
+ When a macro is set in check_relay, then its value is accessible
+ by all transactions in the same SMTP session.
+ Increase size of key for ldap lookups to 1024 (MAXKEY).
+ New option MaxNOOPCommands to override default of 20 for the
+ number of "useless" commands before the SMTP server will
+ slow down responding.
+ New option SharedMemoryKeyFile: if shared memory support is
+ enabled, the MTA can be asked to select a shared memory
+ key itself by setting SharedMemoryKey to -1 and specifying
+ a file where to store the selected key.
+ Try to deal with open HTTP proxies that are used to send spam
+ by recognizing some commands from them. If the first command
+ from the client is GET, POST, CONNECT, or USER, then the
+ connection is terminated immediately.
+ New PrivacyOptions noactualrecipient to avoid putting
+ X-Actual-Recipient lines in DSNs revealing the actual
+ account that addresses map to. Patch from Dan Harkless.
+ New options B, z, and Z for DNS maps:
+ -B: specify a domain that is always appended to queries.
+ -z: specify the delimiter at which to cut off the result of
+ a query if it is too long.
+ -Z: specify the maximum number of entries to be concatenated
+ to form the result of a lookup.
+ New target "check" in the Makefile of libsm: instead of running tests
+ implicitly while building libsm, they must be explicitly
+ started by using "make check".
+ Fixed some inconsistent checks for NULL pointers that have been
+ reported by the SATURN tool which has been developed by
+ Isil Dillig and Thomas Dillig of Stanford University.
+ Fix a potential race condition caused by a signal handler for
+ terminated child processes. Problem noted by David F. Skoll.
+ When a milter deleted a recipient, that recipient could cause a
+ queue group selection. This has been disabled as it was not
+ intended.
+ New operator 'r' for the arith map to return a random number.
+ Patch from Motonori Nakamura of Kyoto University.
+ New compile time option MILTER_NO_NAGLE to turn off the Nagle
+ algorithm for communication with libmilter ("cork" on Linux),
+ which may improve the communication performance on some
+ operating systems. Patch from John Gardiner Myers of
+ Proofpoint.
+ If sendmail received input that contained a CR without subsequent LF
+ (thus violating RFC 2821 (2.3.7)), it could previously
+ generate an additional blank line in the output as the last
+ line.
+ Restarting persistent queue runners by sending a HUP signal to
+ the "queue control process" (QCP) works now.
+ Increase the length of an input line to 12288 to deal with
+ really long lines during SMTP AUTH negotiations.
+ Problem noted by Werner Wiethege.
+ If ARPANET mode (-ba) was selected STARTTLS would fail (due to
+ a missing initialization call for that case). Problem
+ noted by Neil Rickert of Northern Illinois University.
+ If sendmail is linked against a library that initializes Cyrus-SASL
+ before sendmail did it (such as libnss-ldap), then SMTP AUTH
+ could fail for the sendmail client. A patch by Moritz Both
+ works around the API design flaw of Cyrus-SASLv2.
+ CONFIG: Make it possible to unset the StatusFile option by
+ undefining STATUS_FILE. By not setting StatusFile,
+ the MTA will not attempt to open a statistics file on
+ each delivery.
+ CONFIG: New FEATURE(`require_rdns') to reject messages from SMTP
+ clients whose IP address does not have proper reverse DNS.
+ Contributed by Neil Rickert of Northern Illinois University
+ and John Beck of Sun Microsystems.
+ CONFIG: New FEATURE(`block_bad_helo') to reject messages from SMTP
+ clients which provide a HELO/EHLO argument which is either
+ unqualified, or is one of our own names (i.e., the server
+ name instead of the client name). Contributed by Neil
+ Rickert of Northern Illinois University and John Beck of
+ Sun Microsystems.
+ CONFIG: New FEATURE(`badmx') to reject envelope sender addresses
+ (MAIL) whose domain part resolves to a "bad" MX record.
+ Based on contribution from William Dell Wisner.
+ CONFIG: New macros SMTP_MAILER_LL and RELAY_MAILER_LL to override
+ the maximum line length of the smtp mailers.
+ CONFIG: New option `relaytofulladdress' for FEATURE(`access_db')
+ to allow entries in the access map to be of the form
+ To:user@example.com RELAY
+ CONFIG: New subsuboptions eoh and data to specify the list of
+ macros a milter should receive at those stages in the
+ SMTP dialogue.
+ CONFIG: New option confHELO_NAME for HeloName to set the name
+ for the HELO/EHLO command.
+ CONFIG: dnsbl and enhdnsbl can now also discard or quarantine
+ messages by using those values as second argument.
+ Patches from Nelson Fung.
+ CONTRIB: cidrexpand uses a hash symbol as comment character and
+ ignores everything after it unless it is in quotes or
+ preceeded by a backslash.
+ DEVTOOLS: New macro confMKDIR: if set to a program that creates
+ directories, then it used for "make install" to create
+ the required installation directories.
+ DEVTOOLS: New macro confCCLINK to specify the linker to use for
+ executables (defaults to confCC).
+ LIBMILTER: A new version of the milter API has been created that
+ has several changes which are listed below and documented
+ in the webpages reachable via libmilter/docs/index.html.
+ LIBMILTER: The meaning of the version macro SMFI_VERSION has been
+ changed. It now refers only to the version of libmilter,
+ not to the protocol version (which is used only internally,
+ it is not user/milter-programmer visible). Additionally,
+ a version function smfi_version() has been introduced such
+ that a milter program can check the libmilter version also
+ at runtime which is useful if a shared library is used.
+ LIBMILTER: A new callback xxfi_negotiate() can be used to
+ dynamically (i.e., at runtime) determine the available
+ protocol actions and features of the MTA and also to
+ specify which of these a milter wants to use. This allows
+ for more flexibility than hardcoding these flags in the
+ xxfi_flags field of the smfiDesc structure.
+ LIBMILTER: A new callback xxfi_data() is available so milters
+ can act on the DATA command.
+ LIBMILTER: A new callback xxfi_unknown() is available so milters
+ can receive also unknown SMTP commands.
+ LIBMILTER: A new return code SMFIS_NOREPLY has been added which
+ can be used by the xxfi_header() callback provided the
+ milter requested the SMFIP_NOHREPL protocol action.
+ LIBMILTER: The new return code SMFIS_SKIP can be used in the
+ xxfi_body() callback to skip over further body chunks
+ and directly advance to the xxfi_eom() callback. This
+ is useful if a milter can make a decision based on the
+ body chunks it already received without reading the entire
+ rest of the body and the milter wants to invoke functions
+ that are only available from the xxfi_eom() callback.
+ LIBMILTER: A new function smfi_addrcpt_par() can be used to add
+ new recipients including ESMTP parameters.
+ LIBMILTER: A new function smfi_chgfrom() can be used to change the
+ envelope sender including ESMTP parameters.
+ LIBMILTER: A milter can now request to be informed about rejected
+ recipients (RCPT) too. This requires to set the protocol
+ flag SMFIP_RCPT_REJ during option negotiation. Whether
+ a RCPT has been rejected can be checked by comparing the
+ value of the macro {rcpt_mailer} with "error".
+ LIBMILTER: A milter can now override the list of macros that it
+ wants to receive from the MTA for each protocol step
+ by invoking the function smfi_setsymlist() during option
+ negotiation.
+ LIBMILTER: A milter can receive header field values with all
+ leading spaces by requesting the SMFIP_HDR_LEADSPC
+ protocol action. Also, if the flag is set then the MTA
+ does not add a leading space to headers that are added,
+ inserted, or replaced.
+ LIBMILTER: If a milter sets the reply code to "421" for the HELO
+ callback, the SMTP server will terminate the SMTP session
+ with that error to match the behavior of all other callbacks.
+ New Files:
+ cf/feature/badmx.m4
+ cf/feature/block_bad_helo.m4
+ cf/feature/require_rdns.m4
+ devtools/M4/UNIX/check.m4
+ include/sm/misc.h
+ include/sm/sendmail.h
+ include/sm/tailq.h
+ libmilter/docs/smfi_addrcpt_par.html
+ libmilter/docs/smfi_setsymlist.html
+ libmilter/docs/xxfi_data.html
+ libmilter/docs/xxfi_negotiate.html
+ libmilter/docs/xxfi_unknown.html
+ libmilter/example.c
+ libmilter/monitor.c
+ libmilter/worker.c
+ libsm/memstat.c
+ libsm/t-memstat.c
+ libsm/t-qic.c
+ libsm/util.c
+ sendmail/daemon.h
+ sendmail/map.h
+
8.13.8/8.13.8 2006/08/09
Fix a regression in 8.13.7: if shared memory is activated, then
the server can erroneously report that there is
@@ -1317,7 +1585,7 @@ summary of the changes in that release.
Properly count message size for mailstats during mail collection.
Problem noted by Werner Wiethege.
Log complete response from LMTP delivery agent on failure. Based on
- patch from by Motonori Nakamura of Kyoto University.
+ patch from Motonori Nakamura of Kyoto University.
Provide workaround for getopt() implementations that do not catch
missing arguments.
Fix the message size calculation if the message body is replaced by
diff --git a/contrib/sendmail/cf/README b/contrib/sendmail/cf/README
index fce316e53a87..81689ad8009a 100644
--- a/contrib/sendmail/cf/README
+++ b/contrib/sendmail/cf/README
@@ -397,6 +397,9 @@ SMTP_MAILER_CHARSET [undefined] If defined, messages containing 8-bit data
that ARRIVE from an address that resolves to one of
the SMTP mailers and which are converted to MIME will
be labeled with this character set.
+SMTP_MAILER_LL [990] The maximum line length for SMTP mailers
+ (except the relay mailer).
+RELAY_MAILER_LL [2040] The maximum line length for the relay mailer.
UUCP_MAILER_PATH [/usr/bin/uux] The program used to send UUCP mail.
UUCP_MAILER_FLAGS [undefined] Flags added to UUCP mailer. Default
flags are `DFMhuU' (and `m' for uucp-new mailer,
@@ -1031,12 +1034,6 @@ ldap_routing Implement LDAP-based e-mail recipient routing according to
See the LDAP ROUTING section below for more information.
-nodns If you aren't running DNS at your site (for example,
- you are UUCP-only connected). It's hard to consider
- this a "feature", but hey, it had to go somewhere.
- Actually, as of 8.7 this is a no-op -- remove "dns" from
- the hosts service switch entry instead.
-
nullclient This is a special case -- it creates a configuration file
containing nothing but support for forwarding all mail to a
central hub via a local SMTP-based network. The argument
@@ -1241,12 +1238,15 @@ use_client_ptr If this feature is enabled then check_relay will override
versions when delay_checks was not in use. See doc/op/op.*
about check_relay, {client_name}, and {client_ptr}.
-dnsbl Turns on rejection of hosts found in an DNS based rejection
- list. The first is used as the domain in which blocked
- hosts are listed. A second argument can be used to change
- the default error message. Without that second argument,
- the error message will be
+dnsbl Turns on rejection, discarding, or quarantining of hosts
+ found in a DNS based list. The first argument is used as
+ the domain in which blocked hosts are listed. A second
+ argument can be used to change the default error message,
+ or select one of the operations `discard' and `quarantine'.
+ Without that second argument, the error message will be
+
Rejected: IP-ADDRESS listed at SERVER
+
where IP-ADDRESS and SERVER are replaced by the appropriate
information. By default, temporary lookup failures are
ignored. This behavior can be changed by specifying a
@@ -1485,6 +1485,81 @@ greet_pause Adds the greet_pause ruleset which enables open proxy
R$* $: $&{daemon_flags}
R$* a $* $# 0
+block_bad_helo Reject messages from SMTP clients which provide a HELO/EHLO
+ argument which is either unqualified, or is one of our own
+ names (i.e., the server name instead of the client name).
+ This check is performed at RCPT stage and disabled for the
+ following cases:
+ - authenticated sessions,
+ - connections from IP addresses in class $={R}.
+ Currently access_db lookups can not be used to
+ (selectively) disable this test, moreover,
+ FEATURE(`delay_checks')
+ is required.
+
+require_rdns Reject mail from connecting SMTP clients without proper
+ rDNS (reverse DNS), functional gethostbyaddr() resolution.
+ Note: this feature will cause false positives, i.e., there
+ are legitimate MTAs that do not have proper DNS entries.
+ Rejecting mails from those MTAs is a local policy decision.
+
+ The basic policy is to reject message with a 5xx error if
+ the IP address fails to resolve. However, if this is a
+ temporary failure, a 4xx temporary failure is returned.
+ If the look-up succeeds, but returns an apparently forged
+ value, this is treated as a temporary failure with a 4xx
+ error code.
+
+ EXCEPTIONS:
+
+ Exceptions based on access entries are discussed below.
+ Any IP address matched using $=R (the "relay-domains" file)
+ is excepted from the rules. Since we have explicitly
+ allowed relaying for this host, based on IP address, we
+ ignore the rDNS failure.
+
+ The philosophical assumption here is that most users do
+ not control their rDNS. They should be able to send mail
+ through their ISP, whether or not they have valid rDNS.
+ The class $=R, roughly speaking, contains those IP addresses
+ and address ranges for which we are the ISP, or are acting
+ as if the ISP.
+
+ If `delay_checks' is in effect (recommended), then any
+ sender who has authenticated is also excepted from the
+ restrictions. This happens because the rules produced by
+ this FEATURE() will not be applied to authenticated senders
+ (assuming `delay_checks').
+
+ ACCESS MAP ENTRIES:
+
+ Entries such as
+ Connect:1.2.3.4 OK
+ Connect:1.2 RELAY
+ will whitelist IP address 1.2.3.4, so that the rDNS
+ blocking does apply to that IP address
+
+ Entries such as
+ Connect:1.2.3.4 REJECT
+ will have the effect of forcing a temporary failure for
+ that address to be treated as a permanent failure.
+
+badmx Reject envelope sender addresses (MAIL) whose domain part
+ resolves to a "bad" MX record. By default these are
+ MX records which resolve to A records that match the
+ regular expression:
+
+ ^(127\.|10\.|0\.0\.0\.0)
+
+ This default regular expression can be overridden by
+ specifying an argument, e.g.,
+
+ FEATURE(`badmx', `^127\.0\.0\.1')
+
+ Note: this feature requires that the sendmail binary
+ has been compiled with the options MAP_REGEX and
+ DNSMAP.
+
+-------+
| HACKS |
+-------+
@@ -2426,10 +2501,15 @@ definition for the database; for example
FEATURE(`access_db', `hash -T /etc/mail/access_map')
Notice: If a second argument is specified it must contain the option
-`-T' as shown above. The optional third and fourth parameters
-may be `skip' or `lookupdotdomain'. The former enables SKIP as
-value part (see below), the latter is another way to enable the
-feature of the same name (see above).
+`-T' as shown above. The optional parameters may be
+
+ `skip' enables SKIP as value part (see below).
+ `lookupdotdomain' another way to enable the feature of the
+ same name (see above).
+ `relaytofulladdress' enable entries of the form
+ To:user@example.com RELAY
+ to allow relaying to just a specific
+ e-mail address instead of an entire domain.
Remember, since /etc/mail/access is a database, after creating the text
file as described below, you must use makemap to create the database
@@ -2497,7 +2577,8 @@ The value part of the map can contain:
name is unresolvable. "Accept" does not mean
"relay", but at most acceptance for local
recipients. That is, OK allows less than RELAY.
- RELAY Accept mail addressed to the indicated domain or
+ RELAY Accept mail addressed to the indicated domain
+ (or address if `relaytofulladdress' is set) or
received from the indicated domain for relaying
through your SMTP server. RELAY also serves as
an implicit OK for the other checks.
@@ -2628,7 +2709,7 @@ maintained in DNS. To use such a database, specify
FEATURE(`dnsbl', `dnsbl.example.com')
This will cause sendmail to reject mail from any site listed in the
-DNS based blacklist. You must select an DNSB based blacklist domain
+DNS based blacklist. You must select a DNS based blacklist domain
to check by specifying an argument to the FEATURE. The default
error message is
@@ -2636,10 +2717,18 @@ error message is
where IP-ADDRESS and SERVER are replaced by the appropriate
information. A second argument can be used to specify a different
-text. By default, temporary lookup failures are ignored and hence
-cause the connection not to be rejected by the DNS based rejection
-list. This behavior can be changed by specifying a third argument,
-which must be either `t' or a full error message. For example:
+text or action. For example,
+
+ FEATURE(`dnsbl', `dnsbl.example.com', `quarantine')
+
+would quarantine the message if the client IP address is listed
+at `dnsbl.example.com'.
+
+By default, temporary lookup failures are ignored
+and hence cause the connection not to be rejected by the DNS based
+rejection list. This behavior can be changed by specifying a third
+argument, which must be either `t' or a full error message. For
+example:
FEATURE(`dnsbl', `dnsbl.example.com', `',
`"451 Temporary lookup failure for " $&{client_addr} " in dnsbl.example.com"')
@@ -4033,6 +4122,11 @@ confDOUBLE_BOUNCE_ADDRESS DoubleBounceAddress
"double bounce" error message to this
address. If it expands to an empty
string, double bounces are dropped.
+confSOFT_BOUNCE SoftBounce [False] If set, issue temporary errors
+ (4xy) instead of permanent errors
+ (5xy). This can be useful during
+ testing of a new configuration to
+ avoid erroneous bouncing of mails.
confDEAD_LETTER_DROP DeadLetterDrop [undefined] Filename to save bounce
messages which could not be returned
to the user or sent to postmaster.
@@ -4197,6 +4291,11 @@ confREQUIRES_DIR_FSYNC RequiresDirfsync [true] RequiresDirfsync can
flag REQUIRES_DIR_FSYNC at runtime.
See sendmail/README for details.
confSHARED_MEMORY_KEY SharedMemoryKey [0] Key for shared memory.
+confSHARED_MEMORY_KEY_FILE
+ SharedMemoryKeyFile
+ [undefined] File where the
+ automatically selected key for
+ shared memory is stored.
confFAST_SPLIT FastSplit [1] If set to a value greater than
zero, the initial MX lookups on
addresses is suppressed when they
@@ -4210,6 +4309,11 @@ confMAILBOX_DATABASE MailboxDatabase [pw] Type of lookup to find
information about local mailboxes.
confDEQUOTE_OPTS - [empty] Additional options for the
dequote map.
+confMAX_NOOP_COMMANDS MaxNOOPCommands [20] Maximum number of "useless"
+ commands before the SMTP server
+ will slow down responding.
+confHELO_NAME HeloName If defined, use as name for EHLO/HELO
+ command (instead of $j).
confINPUT_MAIL_FILTERS InputMailFilters
A comma separated list of filters
which determines which filters and
@@ -4241,7 +4345,14 @@ confMILTER_MACROS_ENVRCPT Milter.macros.envrcpt
milters after RCPT TO command.
confMILTER_MACROS_EOM Milter.macros.eom
[{msg_id}] Macros to transmit to
- milters after DATA command.
+ milters after the terminating
+ DATA '.' is received.
+confMILTER_MACROS_EOH Milter.macros.eoh
+ Macros to transmit to milters
+ after the end of headers.
+confMILTER_MACROS_DATA Milter.macros.data
+ Macros to transmit to milters
+ after DATA command is received.
See also the description of OSTYPE for some parameters that can be
@@ -4588,4 +4699,4 @@ M4 DIVERSIONS
8 DNS based blacklists
9 special local rulesets (1 and 2)
-$Revision: 8.706 $, Last updated $Date: 2006/04/18 22:31:06 $
+$Revision: 8.722 $, Last updated $Date: 2007/04/03 21:26:58 $
diff --git a/contrib/sendmail/cf/cf/knecht.mc b/contrib/sendmail/cf/cf/knecht.mc
index 597bc5e49617..29d29113d58e 100644
--- a/contrib/sendmail/cf/cf/knecht.mc
+++ b/contrib/sendmail/cf/cf/knecht.mc
@@ -19,7 +19,7 @@ divert(-1)
#
divert(0)
-VERSIONID(`$Id: knecht.mc,v 8.61 2005/10/06 05:56:03 ca Exp $')
+VERSIONID(`$Id: knecht.mc,v 8.62 2006/09/27 19:48:59 eric Exp $')
OSTYPE(bsd4.4)
DOMAIN(generic)
@@ -30,6 +30,7 @@ define(`confHOST_STATUS_DIRECTORY', `.hoststat')
define(`confTO_ICONNECT', `10s')
define(`confTO_QUEUEWARN', `8h')
define(`confMIN_QUEUE_AGE', `27m')
+define(`confTRUSTED_USER', `smtrust')
define(`confTRUSTED_USERS', ``www listmgr'')
define(`confPRIVACY_FLAGS', ``authwarnings,noexpn,novrfy'')
@@ -42,6 +43,7 @@ define(`confCLIENT_CERT', `CERT_DIR/MYcert.pem')
define(`confCLIENT_KEY', `CERT_DIR/MYkey.pem')
define(`CYRUS_MAILER_PATH', `/usr/local/cyrus/bin/deliver')
+define(`CYRUS_MAILER_FLAGS', `fAh5@/:|')
FEATURE(`access_db')
FEATURE(`blacklist_recipients')
@@ -64,10 +66,16 @@ define(`confFAST_SPLIT', `10')
dnl # 10 runners, split into at most 15 recipients per envelope
QUEUE_GROUP(`mqueue', `P=/var/spool/mqueue, R=5, r=15, F=f')
-
dnl # enable spam assassin
INPUT_MAIL_FILTER(`spamassassin', `S=local:/var/run/spamass-milter.sock, F=, T=C:15m;S:4m;R:4m;E:10m')
+dnl # enable DomainKeys and DKIM
+INPUT_MAIL_FILTER(`dkim-filter', `S=unix:/var/run/smtrust/dkim.sock, F=T, T=R:2m')
+dnl INPUT_MAIL_FILTER(`dk-filter', `S=unix:/var/run/smtrust/dk.sock, F=T, T=R:2m')
+
+define(`confMILTER_MACROS_CONNECT', `j, {daemon_name}')
+define(`confMILTER_MACROS_ENVFROM', `i, {auth_type}')
+
dnl # enable some DNSBLs
dnl FEATURE(`dnsbl', `dnsbl.sorbs.net', `"550 Mail from " $`'&{client_addr} " refused - see http://www.dnsbl.sorbs.net/"')
FEATURE(`dnsbl', `sbl-xbl.spamhaus.org', `"550 Mail from " $`'&{client_addr} " refused - see http://www.spamhaus.org/sbl/"')
diff --git a/contrib/sendmail/cf/cf/submit.cf b/contrib/sendmail/cf/cf/submit.cf
index f5d078a9c4c5..b70e79d6521c 100644
--- a/contrib/sendmail/cf/cf/submit.cf
+++ b/contrib/sendmail/cf/cf/submit.cf
@@ -16,8 +16,8 @@
#####
##### SENDMAIL CONFIGURATION FILE
#####
-##### built by ca@nother.smi.sendmail.com on Mon Aug 7 10:37:32 PDT 2006
-##### in /extra/home/ca/sm-8.13.8/OpenSource/sendmail-8.13.8/cf/cf
+##### built by ca@nother.smi.sendmail.com on Tue Apr 3 16:32:55 PDT 2007
+##### in /extra/home/ca/sm-8.14.1/OpenSource/sendmail-8.14.1/cf/cf
##### using ../ as configuration include directory
#####
######################################################################
@@ -35,7 +35,7 @@
##### $Id: no_default_msa.m4,v 8.2 2001/02/14 05:03:22 gshapiro Exp $ #####
-##### $Id: proto.m4,v 8.719 2006/03/30 20:50:13 ca Exp $ #####
+##### $Id: proto.m4,v 8.730 2007/02/01 18:50:03 ca Exp $ #####
# level 10 config file format
V10/Berkeley
@@ -114,7 +114,7 @@ D{MTAHost}[127.0.0.1]
# Configuration version number
-DZ8.13.8/Submit
+DZ8.14.1/Submit
###############
@@ -260,10 +260,11 @@ O PrivacyOptions=goaway,noetrn,restrictqrun
# queue directory
O QueueDirectory=/var/spool/clientmqueue
-# key for shared memory; 0 to turn off
+# key for shared memory; 0 to turn off, -1 to auto-select
#O SharedMemoryKey=0
-
+# file to store auto-selected key for shared memory (SharedMemoryKey = -1)
+#O SharedMemoryKeyFile
# timeouts (many of these)
#O Timeout.initial=5m
@@ -423,6 +424,9 @@ O DontInitGroups=True
# where do errors that occur when sending errors get sent?
#O DoubleBounceAddress=postmaster
+# issue temporary errors (4xy) instead of permanent errors (5xy)?
+#O SoftBounce=False
+
# where to save bounces if all else fails
#O DeadLetterDrop=/var/tmp/dead.letter
@@ -519,6 +523,12 @@ O PidFile=/var/spool/clientmqueue/sm-client.pid
# Random data source (required for systems without /dev/urandom under OpenSSL)
#O RandFile
+# Maximum number of "useless" commands before slowing down
+#O MaxNOOPCommands=20
+
+# Name to use for EHLO (defaults to $j)
+#O HeloName
+
############################
# QUEUE GROUP DEFINITIONS #
############################
@@ -1042,10 +1052,12 @@ R $+> $* $#error $@ 5.5.4 $: "553 Domain name required for sender address " $
...remote is not
# check results
R> $* $: @ $1 mark address: nothing known about it
-R<$={ResOk}> $* $@ domain ok: stop
+R<$={ResOk}> $* $: @ $2 domain ok
R $* $#error $@ 4.1.8 $: "451 Domain of sender address " $&f " does not resolve"
R $* $#error $@ 5.1.8 $: "553 Domain of sender address " $&f " does not exist"
+
+
######################################################################
### check_rcpt -- check SMTP `RCPT TO:' command argument
######################################################################
@@ -1148,6 +1160,7 @@ R> $* $=R $@ RELAY
+
######################################################################
### trust_auth: is user trusted to authenticate as someone else?
###
@@ -1335,7 +1348,7 @@ Mprog, P=[IPC], F=lmDFMuXk5, S=EnvFromL/HdrFromL, R=EnvToL/HdrToL, D=$z:/,
### SMTP Mailer specification ###
#####################################
-##### $Id: smtp.m4,v 8.64 2001/04/03 01:52:54 gshapiro Exp $ #####
+##### $Id: smtp.m4,v 8.65 2006/07/12 21:08:10 ca Exp $ #####
#
# common sender and masquerading recipient rewriting
diff --git a/contrib/sendmail/cf/feature/access_db.m4 b/contrib/sendmail/cf/feature/access_db.m4
index 5488a452745e..8aa90c82e055 100644
--- a/contrib/sendmail/cf/feature/access_db.m4
+++ b/contrib/sendmail/cf/feature/access_db.m4
@@ -1,6 +1,6 @@
divert(-1)
#
-# Copyright (c) 1998-2002, 2004 Sendmail, Inc. and its suppliers.
+# Copyright (c) 1998-2002, 2004, 2006 Sendmail, Inc. and its suppliers.
# All rights reserved.
#
# By using this file, you agree to the terms and conditions set
@@ -10,15 +10,20 @@ divert(-1)
#
divert(0)
-VERSIONID(`$Id: access_db.m4,v 8.26 2004/06/24 18:10:02 ca Exp $')
+VERSIONID(`$Id: access_db.m4,v 8.27 2006/07/06 21:10:10 ca Exp $')
divert(-1)
define(`_ACCESS_TABLE_', `')
define(`_TAG_DELIM_', `:')dnl should be in OperatorChars
ifelse(lower(_ARG2_),`skip',`define(`_ACCESS_SKIP_', `1')')
ifelse(lower(_ARG2_),`lookupdotdomain',`define(`_LOOKUPDOTDOMAIN_', `1')')
+ifelse(lower(_ARG2_),`relaytofulladdress',`define(`_RELAY_FULL_ADDR_', `1')')
ifelse(lower(_ARG3_),`skip',`define(`_ACCESS_SKIP_', `1')')
ifelse(lower(_ARG3_),`lookupdotdomain',`define(`_LOOKUPDOTDOMAIN_', `1')')
+ifelse(lower(_ARG3_),`relaytofulladdress',`define(`_RELAY_FULL_ADDR_', `1')')
+ifelse(lower(_ARG4_),`skip',`define(`_ACCESS_SKIP_', `1')')
+ifelse(lower(_ARG4_),`lookupdotdomain',`define(`_LOOKUPDOTDOMAIN_', `1')')
+ifelse(lower(_ARG4_),`relaytofulladdress',`define(`_RELAY_FULL_ADDR_', `1')')
define(`_ATMPF_', `')dnl
dnl check whether arg contains -T`'_ATMPF_
dnl unless it is a sequence map
diff --git a/contrib/sendmail/cf/feature/badmx.m4 b/contrib/sendmail/cf/feature/badmx.m4
new file mode 100644
index 000000000000..dc0dc8827a7a
--- /dev/null
+++ b/contrib/sendmail/cf/feature/badmx.m4
@@ -0,0 +1,22 @@
+divert(-1)
+#
+# Copyright (c) 2006 Sendmail, Inc. and its suppliers.
+# All rights reserved.
+#
+# By using this file, you agree to the terms and conditions set
+# forth in the LICENSE file which can be found at the top level of
+# the sendmail distribution.
+#
+#
+
+divert(0)
+VERSIONID(`$Id: badmx.m4,v 1.1 2006/12/16 00:56:32 ca Exp $')
+divert(-1)
+
+define(`_BADMX_CHK_', 1)
+
+LOCAL_CONFIG
+Kmxlist bestmx -z: -T
+Kbadmx regex -a ^(([0-9]{1,3}\.){3}[0-9]){0,1}\.$
+KdnsA dns -R A -a. -T
+KBadMXIP regex -a ifelse(defn(`_ARG_'), `', `^(127\.|10\.|0\.0\.0\.0)', `_ARG_')
diff --git a/contrib/sendmail/cf/feature/block_bad_helo.m4 b/contrib/sendmail/cf/feature/block_bad_helo.m4
new file mode 100644
index 000000000000..6f6d79265ebe
--- /dev/null
+++ b/contrib/sendmail/cf/feature/block_bad_helo.m4
@@ -0,0 +1,18 @@
+divert(-1)
+#
+# Copyright (c) 2006 Sendmail, Inc. and its suppliers.
+# All rights reserved.
+#
+# By using this file, you agree to the terms and conditions set
+# forth in the LICENSE file which can be found at the top level of
+# the sendmail distribution.
+#
+#
+
+divert(0)dnl
+VERSIONID(`$Id: block_bad_helo.m4,v 1.1 2006/06/15 22:49:30 ca Exp $')
+divert(-1)
+
+define(`_BLOCK_BAD_HELO_', `')dnl
+RELAY_DOMAIN(`127.0.0.1')dnl
+LOCAL_DOMAIN(`[127.0.0.1]')dnl
diff --git a/contrib/sendmail/cf/feature/dnsbl.m4 b/contrib/sendmail/cf/feature/dnsbl.m4
index ffaa88c6d970..be0e2be9ef93 100644
--- a/contrib/sendmail/cf/feature/dnsbl.m4
+++ b/contrib/sendmail/cf/feature/dnsbl.m4
@@ -1,6 +1,6 @@
divert(-1)
#
-# Copyright (c) 1998-2002, 2005, 2006 Sendmail, Inc. and its suppliers.
+# Copyright (c) 1998-2002, 2005-2007 Sendmail, Inc. and its suppliers.
# All rights reserved.
#
# By using this file, you agree to the terms and conditions set
@@ -12,7 +12,7 @@ divert(-1)
ifdef(`DNSBL_MAP', `', `define(`DNSBL_MAP', `dns -R A')')
divert(0)
ifdef(`_DNSBL_R_',`dnl',`dnl
-VERSIONID(`$Id: dnsbl.m4,v 8.32 2006/03/29 22:50:16 ca Exp $')
+VERSIONID(`$Id: dnsbl.m4,v 8.33 2007/01/05 18:49:29 ca Exp $')
define(`_DNSBL_R_',`')
ifelse(defn(`_ARG_'), `',
`errprint(`*** ERROR: missing argument for FEATURE(`dnsbl')')')
@@ -31,5 +31,9 @@ R>OK $: OKSOFAR
ifelse(len(X`'_ARG3_),`1',
`R>$+ $: TMPOK',
`R>$+ $#error $@ 4.4.3 $: _DNSBL_MSG_TMP_')
-R>$+ $#error $@ 5.7.1 $: _DNSBL_MSG_
+ifelse(`X'_ARG2_,`Xquarantine',
+`R>$+ $#error $@ quarantine $: _DNSBL_SRV_',
+`X'_ARG2_,`Xdiscard',
+`R>$+ $#discard $: _DNSBL_SRV_',
+`R>$+ $#error $@ 5.7.1 $: _DNSBL_MSG_')
divert(-1)
diff --git a/contrib/sendmail/cf/feature/enhdnsbl.m4 b/contrib/sendmail/cf/feature/enhdnsbl.m4
index 63a4f15acb23..bb467ef3eeb3 100644
--- a/contrib/sendmail/cf/feature/enhdnsbl.m4
+++ b/contrib/sendmail/cf/feature/enhdnsbl.m4
@@ -1,6 +1,6 @@
divert(-1)
#
-# Copyright (c) 2000-2002, 2005, 2006 Sendmail, Inc. and its suppliers.
+# Copyright (c) 2000-2002, 2005-2007 Sendmail, Inc. and its suppliers.
# All rights reserved.
#
# By using this file, you agree to the terms and conditions set
@@ -13,7 +13,7 @@ ifelse(defn(`_ARG_'), `',
`errprint(`*** ERROR: missing argument for FEATURE(`enhdnsbl')')')
divert(0)
ifdef(`_EDNSBL_R_',`dnl',`dnl
-VERSIONID(`$Id: enhdnsbl.m4,v 1.11 2006/03/31 19:56:16 ca Exp $')
+VERSIONID(`$Id: enhdnsbl.m4,v 1.12 2007/01/08 18:22:05 ca Exp $')
LOCAL_CONFIG
define(`_EDNSBL_R_',`')dnl
# map for enhanced DNS based blacklist lookups
@@ -21,9 +21,16 @@ Kednsbl dns -R A -a. -T -r`'ifdef(`EDNSBL_TO',`EDNSBL_TO',`5')
')
divert(-1)
define(`_EDNSBL_SRV_', `_ARG_')dnl
-define(`_EDNSBL_MSG_', `ifelse(len(X`'_ARG2_),`1',`"550 Rejected: " $`'&{client_addr} " listed at '_EDNSBL_SRV_`"',`_ARG2_')')dnl
+define(`_EDNSBL_MSG_',
+ `ifelse(len(X`'_ARG2_),`1',`"550 Rejected: " $`'&{client_addr} " listed at '_EDNSBL_SRV_`"',
+ X`'_ARG2_,`Xquarantine',`_EDNSBL_SRV_',
+ `_ARG2_')')dnl
define(`_EDNSBL_MSG_TMP_', `ifelse(_ARG3_,`t',`"451 Temporary lookup failure of " $`'&{client_addr} " at '_EDNSBL_SRV_`"',`_ARG3_')')dnl
define(`_EDNSBL_MATCH_', `ifelse(len(X`'_ARG4_),`1',`$`'+',_ARG4_)')dnl
+define(`_EDNSBL_ACTION_',
+ `ifelse(X`'_ARG2_,`Xquarantine',`$`'#error $`'@ quarantine',
+ X`'_ARG2_,`Xdiscard',`$`'#discard',
+ `$`'#error $`'@ 5.7.1')')dnl
divert(8)
# DNS based IP address spam list _EDNSBL_SRV_
R$* $: $&{client_addr}
@@ -32,15 +39,15 @@ R>OK $: OKSOFAR
ifelse(len(X`'_ARG3_),`1',
`R>$+ $: TMPOK',
`R>$+ $#error $@ 4.4.3 $: _EDNSBL_MSG_TMP_')
-R>_EDNSBL_MATCH_ $#error $@ 5.7.1 $: _EDNSBL_MSG_
+R>_EDNSBL_MATCH_ _EDNSBL_ACTION_ $: _EDNSBL_MSG_
ifelse(len(X`'_ARG5_),`1',`dnl',
-`R>_ARG5_ $#error $@ 5.7.1 $: _EDNSBL_MSG_')
+`R>_ARG5_ _EDNSBL_ACTION_ $: _EDNSBL_MSG_')
ifelse(len(X`'_ARG6_),`1',`dnl',
-`R>_ARG6_ $#error $@ 5.7.1 $: _EDNSBL_MSG_')
+`R>_ARG6_ _EDNSBL_ACTION_ $: _EDNSBL_MSG_')
ifelse(len(X`'_ARG7_),`1',`dnl',
-`R>_ARG7_ $#error $@ 5.7.1 $: _EDNSBL_MSG_')
+`R>_ARG7_ _EDNSBL_ACTION_ $: _EDNSBL_MSG_')
ifelse(len(X`'_ARG8_),`1',`dnl',
-`R>_ARG8_ $#error $@ 5.7.1 $: _EDNSBL_MSG_')
+`R>_ARG8_ _EDNSBL_ACTION_ $: _EDNSBL_MSG_')
ifelse(len(X`'_ARG9_),`1',`dnl',
-`R>_ARG9_ $#error $@ 5.7.1 $: _EDNSBL_MSG_')
+`R>_ARG9_ _EDNSBL_ACTION_ $: _EDNSBL_MSG_')
divert(-1)
diff --git a/contrib/sendmail/cf/feature/require_rdns.m4 b/contrib/sendmail/cf/feature/require_rdns.m4
new file mode 100644
index 000000000000..4c70d3a68c72
--- /dev/null
+++ b/contrib/sendmail/cf/feature/require_rdns.m4
@@ -0,0 +1,16 @@
+divert(-1)
+#
+# Copyright (c) 2006 Sendmail, Inc. and its suppliers.
+# All rights reserved.
+#
+# By using this file, you agree to the terms and conditions set
+# forth in the LICENSE file which can be found at the top level of
+# the sendmail distribution.
+#
+#
+
+divert(0)dnl
+VERSIONID(`$Id: require_rdns.m4,v 1.1 2006/06/15 22:49:30 ca Exp $')
+divert(-1)
+
+define(`_REQUIRE_RDNS_', `')
diff --git a/contrib/sendmail/cf/m4/proto.m4 b/contrib/sendmail/cf/m4/proto.m4
index afe4e7dc5bad..d7f7f0811bbd 100644
--- a/contrib/sendmail/cf/m4/proto.m4
+++ b/contrib/sendmail/cf/m4/proto.m4
@@ -1,6 +1,6 @@
divert(-1)
#
-# Copyright (c) 1998-2006 Sendmail, Inc. and its suppliers.
+# Copyright (c) 1998-2007 Sendmail, Inc. and its suppliers.
# All rights reserved.
# Copyright (c) 1983, 1995 Eric P. Allman. All rights reserved.
# Copyright (c) 1988, 1993
@@ -13,7 +13,7 @@ divert(-1)
#
divert(0)
-VERSIONID(`$Id: proto.m4,v 8.719 2006/03/30 20:50:13 ca Exp $')
+VERSIONID(`$Id: proto.m4,v 8.730 2007/02/01 18:50:03 ca Exp $')
# level CF_LEVEL config file format
V`'CF_LEVEL/ifdef(`VENDOR_NAME', `VENDOR_NAME', `Berkeley')
@@ -396,12 +396,11 @@ _OPTION(FastSplit, `confFAST_SPLIT', `1')
# queue directory
O QueueDirectory=ifdef(`QUEUE_DIR', QUEUE_DIR, `/var/spool/mqueue')
-# key for shared memory; 0 to turn off
+# key for shared memory; 0 to turn off, -1 to auto-select
_OPTION(SharedMemoryKey, `confSHARED_MEMORY_KEY', `0')
-ifdef(`confSHARED_MEMORY_KEY_FILE', `dnl
-# file to store key for shared memory (if SharedMemoryKey = -1)
-O SharedMemoryKeyFile=confSHARED_MEMORY_KEY_FILE')
+# file to store auto-selected key for shared memory (SharedMemoryKey = -1)
+_OPTION(SharedMemoryKeyFile, `confSHARED_MEMORY_KEY_FILE', `')
# timeouts (many of these)
_OPTION(Timeout.initial, `confTO_INITIAL', `5m')
@@ -452,7 +451,7 @@ _OPTION(DontPruneRoutes, `confDONT_PRUNE_ROUTES', `False')
_OPTION(SuperSafe, `confSAFE_QUEUE', `True')
# status file
-O StatusFile=ifdef(`STATUS_FILE', `STATUS_FILE', `MAIL_SETTINGS_DIR`'statistics')
+_OPTION(StatusFile, `STATUS_FILE')
# time zone handling:
# if undefined, use system default
@@ -565,6 +564,9 @@ ifdef(`confUNSAFE_GROUP_WRITES',
# where do errors that occur when sending errors get sent?
_OPTION(DoubleBounceAddress, `confDOUBLE_BOUNCE_ADDRESS', `postmaster')
+# issue temporary errors (4xy) instead of permanent errors (5xy)?
+_OPTION(SoftBounce, `confSOFT_BOUNCE', `False')
+
# where to save bounces if all else fails
_OPTION(DeadLetterDrop, `confDEAD_LETTER_DROP', `/var/tmp/dead.letter')
@@ -648,7 +650,9 @@ _OPTION(Milter.macros.connect, `confMILTER_MACROS_CONNECT', `')
_OPTION(Milter.macros.helo, `confMILTER_MACROS_HELO', `')
_OPTION(Milter.macros.envfrom, `confMILTER_MACROS_ENVFROM', `')
_OPTION(Milter.macros.envrcpt, `confMILTER_MACROS_ENVRCPT', `')
-_OPTION(Milter.macros.eom, `confMILTER_MACROS_EOM', `')')
+_OPTION(Milter.macros.eom, `confMILTER_MACROS_EOM', `')
+_OPTION(Milter.macros.eoh, `confMILTER_MACROS_EOH', `')
+_OPTION(Milter.macros.data, `confMILTER_MACROS_DATA', `')')
# CA directory
_OPTION(CACertPath, `confCACERT_PATH', `')
@@ -669,6 +673,12 @@ _OPTION(DHParameters, `confDH_PARAMETERS', `')
# Random data source (required for systems without /dev/urandom under OpenSSL)
_OPTION(RandFile, `confRAND_FILE', `')
+# Maximum number of "useless" commands before slowing down
+_OPTION(MaxNOOPCommands, `confMAX_NOOP_COMMANDS', `20')
+
+# Name to use for EHLO (defaults to $j)
+_OPTION(HeloName, `confHELO_NAME')
+
############################
`# QUEUE GROUP DEFINITIONS #'
############################
@@ -1782,6 +1792,14 @@ ifdef(`_CONN_CONTROL_IMMEDIATE_',`',`dnl
dnl workspace: ignored...
R$* $: $>"ConnControl" dummy')', `dnl')
undivert(8)
+ifdef(`_REQUIRE_RDNS_', `dnl
+R$* $: $&{client_addr} $| $&{client_resolve}
+R$=R $* $@ RELAY We relay for these
+R$* $| OK $@ OK Resolves.
+R$* $| FAIL $#error $@ 5.7.1 $: 550 Fix reverse DNS for $1
+R$* $| TEMP $#error $@ 4.1.8 $: 451 Client IP address $1 does not resolve
+R$* $| FORGED $#error $@ 4.1.8 $: 451 Possibly forged hostname for $1
+', `dnl')
######################################################################
### check_mail -- check SMTP ``MAIL FROM:'' command argument
@@ -1907,7 +1925,7 @@ R $+> $* $#error $@ 5.5.4 $: "_CODE553 Domain name required for sender addres
...remote is not')
# check results
R> $* $: @ $1 mark address: nothing known about it
-R<$={ResOk}> $* $@ <_RES_OK_> domain ok: stop
+R<$={ResOk}> $* $: @ $2 domain ok
R $* $#error $@ 4.1.8 $: "451 Domain of sender address " $&f " does not resolve"
R $* $#error $@ 5.1.8 $: "_CODE553 Domain of sender address " $&f " does not exist"
ifdef(`_ACCESS_TABLE_', `dnl
@@ -1922,6 +1940,34 @@ ifdef(`_ATMPF_', `R<_ATMPF_> $* $#error $@ 4.3.0 $: "451 Temporary system failu
dnl generic error from access map
R<$+> $* $#error $: $1 error from access db',
`dnl')
+dnl workspace: @ CanonicalAddress (i.e. address in canonical form localpart<@host>)
+
+ifdef(`_BADMX_CHK_', `dnl
+R@ $*<@$+>$* $: $1<@$2>$3 $| $>BadMX $2
+R$* $| $#$* $#$2
+
+SBadMX
+# Look up MX records and ferret away a copy of the original address.
+# input: domain part of address to check
+R$+ $:<$1><:$(mxlist $1$):><:>
+# workspace: <: mxlist-result $><:>
+R<$+><:$*:><$*> $#error $@ 4.1.2 $: "450 MX lookup failure for "$1
+# workspace:
+# Recursively run badmx check on each mx.
+R<$*><:$+:$*><:$*> <$1><:$3><: $4 $(badmx $2 $):>
+# See if any of them fail.
+R<$*><$*><$*:$*> $#error $@ 5.1.2 $:"550 Illegal MX record for recipient host "$1
+# Reverse the mxlists so we can use the same argument order again.
+R<$*><$*><$*> $:<$1><$3><$2>
+R<$*><:$+:$*><:$*> <$1><:$3><:$4 $(dnsA $2 $) :>
+
+# Reverse the lists so we can use the same argument order again.
+R<$*><$*><$*> $:<$1><$3><$2>
+R<$*><:$+:$*><:$*> <$1><:$3><:$4 $(BadMXIP $2 $) :>
+
+R<$*><$*><$*:$*> $#error $@ 5.1.2 $:"550 Invalid MX record for recipient host "$1',
+`dnl')
+
######################################################################
### check_rcpt -- check SMTP ``RCPT TO:'' command argument
@@ -2312,6 +2358,7 @@ ifdef(`_SPAM_HATER_',
R $+ $: $1 spam hater: continue checks
R<$*> $+ $@ $>"Delay_TLS_Clt2" NOSPAMHATER everyone else: stop
dnl',`dnl')
+
dnl run further checks: check_mail
dnl should we "clean up" $&f?
ifdef(`_FFR_MAIL_MACRO',
@@ -2325,6 +2372,27 @@ R$* $| $#$* $#$2
R$* $| $* $: $1
', `dnl')
+ifdef(`_BLOCK_BAD_HELO_', `dnl
+R$* $: $1 $| <$&{auth_authen}> Get auth info
+dnl Bypass the test for users who have authenticated.
+R$* $| <$+> $: $1 skip if auth
+R$* $| <$*> $: $1 $| <$&{client_addr}> [$&s] Get connection info
+dnl Bypass for local clients -- IP address starts with $=R
+R$* $| <$=R $*> [$*] $: $1 skip if local client
+dnl Bypass a "sendmail -bs" session, which use 0 for client ip address
+R$* $| <0> [$*] $: $1 skip if sendmail -bs
+dnl Reject our IP - assumes "[ip]" is in class $=w
+R$* $| <$*> $=w $#error $@ 5.7.1 $:"550 bogus HELO name used: " $&s
+dnl Reject our hostname
+R$* $| <$*> [$=w] $#error $@ 5.7.1 $:"550 bogus HELO name used: " $&s
+dnl Pass anything else with a "." in the domain parameter
+R$* $| <$*> [$+.$+] $: $1 qualified domain ok
+dnl Reject if there was no "." or only an initial or final "."
+R$* $| <$*> [$*] $#error $@ 5.7.1 $:"550 bogus HELO name used: " $&s
+dnl Clean up the workspace
+R$* $| $* $: $1
+', `dnl')
+
ifdef(`_ACCESS_TABLE_', `dnl', `divert(-1)')
######################################################################
### F: LookUpFull -- search for an entry in access database
diff --git a/contrib/sendmail/cf/m4/version.m4 b/contrib/sendmail/cf/m4/version.m4
index df22ee049e90..b81bdcce94ae 100644
--- a/contrib/sendmail/cf/m4/version.m4
+++ b/contrib/sendmail/cf/m4/version.m4
@@ -1,6 +1,6 @@
divert(-1)
#
-# Copyright (c) 1998-2006 Sendmail, Inc. and its suppliers.
+# Copyright (c) 1998-2007 Sendmail, Inc. and its suppliers.
# All rights reserved.
# Copyright (c) 1983 Eric P. Allman. All rights reserved.
# Copyright (c) 1988, 1993
@@ -11,8 +11,8 @@ divert(-1)
# the sendmail distribution.
#
#
-VERSIONID(`$Id: version.m4,v 8.150.2.8 2006/07/26 17:24:02 ca Exp $')
+VERSIONID(`$Id: version.m4,v 8.178 2007/04/03 21:21:18 ca Exp $')
#
divert(0)
# Configuration version number
-DZ8.13.8`'ifdef(`confCF_VERSION', `/confCF_VERSION')
+DZ8.14.1`'ifdef(`confCF_VERSION', `/confCF_VERSION')
diff --git a/contrib/sendmail/cf/mailer/smtp.m4 b/contrib/sendmail/cf/mailer/smtp.m4
index 2bf5a82e259a..7010461c83c9 100644
--- a/contrib/sendmail/cf/mailer/smtp.m4
+++ b/contrib/sendmail/cf/mailer/smtp.m4
@@ -1,6 +1,6 @@
PUSHDIVERT(-1)
#
-# Copyright (c) 1998-2001 Sendmail, Inc. and its suppliers.
+# Copyright (c) 1998-2001, 2006 Sendmail, Inc. and its suppliers.
# All rights reserved.
# Copyright (c) 1983 Eric P. Allman. All rights reserved.
# Copyright (c) 1988, 1993
@@ -13,6 +13,8 @@ PUSHDIVERT(-1)
#
_DEFIFNOT(`_DEF_SMTP_MAILER_FLAGS', `mDFMuX')
_DEFIFNOT(`SMTP_MAILER_FLAGS',`')
+_DEFIFNOT(`SMTP_MAILER_LL',`990')
+_DEFIFNOT(`RELAY_MAILER_LL',`2040')
_DEFIFNOT(`RELAY_MAILER_FLAGS', `SMTP_MAILER_FLAGS')
ifdef(`SMTP_MAILER_ARGS',, `define(`SMTP_MAILER_ARGS', `TCP $h')')
ifdef(`ESMTP_MAILER_ARGS',, `define(`ESMTP_MAILER_ARGS', `TCP $h')')
@@ -29,7 +31,7 @@ POPDIVERT
### SMTP Mailer specification ###
#####################################
-VERSIONID(`$Id: smtp.m4,v 8.64 2001/04/03 01:52:54 gshapiro Exp $')
+VERSIONID(`$Id: smtp.m4,v 8.65 2006/07/12 21:08:10 ca Exp $')
#
# common sender and masquerading recipient rewriting
@@ -105,18 +107,18 @@ SMasqRelay
R$+ $: $>MasqSMTP $1
R$+ $: $>MasqHdr $1
-Msmtp, P=[IPC], F=_MODMF_(CONCAT(_DEF_SMTP_MAILER_FLAGS, SMTP_MAILER_FLAGS), `SMTP'), S=EnvFromSMTP/HdrFromSMTP, R=ifdef(`_ALL_MASQUERADE_', `EnvToSMTP/HdrFromSMTP', `EnvToSMTP'), E=\r\n, L=990,
+Msmtp, P=[IPC], F=_MODMF_(CONCAT(_DEF_SMTP_MAILER_FLAGS, SMTP_MAILER_FLAGS), `SMTP'), S=EnvFromSMTP/HdrFromSMTP, R=ifdef(`_ALL_MASQUERADE_', `EnvToSMTP/HdrFromSMTP', `EnvToSMTP'), E=\r\n, L=SMTP_MAILER_LL,
_OPTINS(`SMTP_MAILER_MAX', `M=', `, ')_OPTINS(`SMTP_MAILER_MAXMSGS', `m=', `, ')_OPTINS(`SMTP_MAILER_MAXRCPTS', `r=', `, ')_OPTINS(`SMTP_MAILER_CHARSET', `C=', `, ')T=DNS/RFC822/SMTP,_SMTP_QGRP
A=SMTP_MAILER_ARGS
-Mesmtp, P=[IPC], F=_MODMF_(CONCAT(_DEF_SMTP_MAILER_FLAGS, `a', SMTP_MAILER_FLAGS), `ESMTP'), S=EnvFromSMTP/HdrFromSMTP, R=ifdef(`_ALL_MASQUERADE_', `EnvToSMTP/HdrFromSMTP', `EnvToSMTP'), E=\r\n, L=990,
+Mesmtp, P=[IPC], F=_MODMF_(CONCAT(_DEF_SMTP_MAILER_FLAGS, `a', SMTP_MAILER_FLAGS), `ESMTP'), S=EnvFromSMTP/HdrFromSMTP, R=ifdef(`_ALL_MASQUERADE_', `EnvToSMTP/HdrFromSMTP', `EnvToSMTP'), E=\r\n, L=SMTP_MAILER_LL,
_OPTINS(`SMTP_MAILER_MAX', `M=', `, ')_OPTINS(`SMTP_MAILER_MAXMSGS', `m=', `, ')_OPTINS(`SMTP_MAILER_MAXRCPTS', `r=', `, ')_OPTINS(`SMTP_MAILER_CHARSET', `C=', `, ')T=DNS/RFC822/SMTP,_ESMTP_QGRP
A=ESMTP_MAILER_ARGS
-Msmtp8, P=[IPC], F=_MODMF_(CONCAT(_DEF_SMTP_MAILER_FLAGS, `8', SMTP_MAILER_FLAGS), `SMTP8'), S=EnvFromSMTP/HdrFromSMTP, R=ifdef(`_ALL_MASQUERADE_', `EnvToSMTP/HdrFromSMTP', `EnvToSMTP'), E=\r\n, L=990,
+Msmtp8, P=[IPC], F=_MODMF_(CONCAT(_DEF_SMTP_MAILER_FLAGS, `8', SMTP_MAILER_FLAGS), `SMTP8'), S=EnvFromSMTP/HdrFromSMTP, R=ifdef(`_ALL_MASQUERADE_', `EnvToSMTP/HdrFromSMTP', `EnvToSMTP'), E=\r\n, L=SMTP_MAILER_LL,
_OPTINS(`SMTP_MAILER_MAX', `M=', `, ')_OPTINS(`SMTP_MAILER_MAXMSGS', `m=', `, ')_OPTINS(`SMTP_MAILER_MAXRCPTS', `r=', `, ')_OPTINS(`SMTP_MAILER_CHARSET', `C=', `, ')T=DNS/RFC822/SMTP,_SMTP8_QGRP
A=SMTP8_MAILER_ARGS
-Mdsmtp, P=[IPC], F=_MODMF_(CONCAT(_DEF_SMTP_MAILER_FLAGS, `a%', SMTP_MAILER_FLAGS), `DSMTP'), S=EnvFromSMTP/HdrFromSMTP, R=ifdef(`_ALL_MASQUERADE_', `EnvToSMTP/HdrFromSMTP', `EnvToSMTP'), E=\r\n, L=990,
+Mdsmtp, P=[IPC], F=_MODMF_(CONCAT(_DEF_SMTP_MAILER_FLAGS, `a%', SMTP_MAILER_FLAGS), `DSMTP'), S=EnvFromSMTP/HdrFromSMTP, R=ifdef(`_ALL_MASQUERADE_', `EnvToSMTP/HdrFromSMTP', `EnvToSMTP'), E=\r\n, L=SMTP_MAILER_LL,
_OPTINS(`SMTP_MAILER_MAX', `M=', `, ')_OPTINS(`SMTP_MAILER_MAXMSGS', `m=', `, ')_OPTINS(`SMTP_MAILER_MAXRCPTS', `r=', `, ')_OPTINS(`SMTP_MAILER_CHARSET', `C=', `, ')T=DNS/RFC822/SMTP,_DSMTP_QGRP
A=DSMTP_MAILER_ARGS
-Mrelay, P=[IPC], F=_MODMF_(CONCAT(_DEF_SMTP_MAILER_FLAGS, `a8', RELAY_MAILER_FLAGS), `RELAY'), S=EnvFromSMTP/HdrFromSMTP, R=ifdef(`_ALL_MASQUERADE_', `MasqSMTP/MasqRelay', `MasqSMTP'), E=\r\n, L=2040,
+Mrelay, P=[IPC], F=_MODMF_(CONCAT(_DEF_SMTP_MAILER_FLAGS, `a8', RELAY_MAILER_FLAGS), `RELAY'), S=EnvFromSMTP/HdrFromSMTP, R=ifdef(`_ALL_MASQUERADE_', `MasqSMTP/MasqRelay', `MasqSMTP'), E=\r\n, L=RELAY_MAILER_LL,
_OPTINS(`RELAY_MAILER_CHARSET', `C=', `, ')_OPTINS(`RELAY_MAILER_MAXMSGS', `m=', `, ')_OPTINS(`SMTP_MAILER_MAXRCPTS', `r=', `, ')T=DNS/RFC822/SMTP,_RELAY_QGRP
A=RELAY_MAILER_ARGS
diff --git a/contrib/sendmail/contrib/cidrexpand b/contrib/sendmail/contrib/cidrexpand
index 882534a2e35d..f277481ca567 100755
--- a/contrib/sendmail/contrib/cidrexpand
+++ b/contrib/sendmail/contrib/cidrexpand
@@ -1,13 +1,13 @@
#!/usr/bin/perl -w
-# $Id: cidrexpand,v 8.4.2.1 2006/08/07 17:22:10 ca Exp $
+# $Id: cidrexpand,v 8.8 2006/08/07 17:18:37 ca Exp $
#
# v 0.4
#
# 17 July 2000 Derek J. Balling (dredd@megacity.org)
-#
+#
# Acts as a preparser on /etc/mail/access_db to allow you to use address/bit
-# notation.
+# notation.
#
# If you have two overlapping CIDR blocks with conflicting actions
# e.g. 10.2.3.128/25 REJECT and 10.2.3.143 ACCEPT
@@ -25,15 +25,25 @@
# Added code to deal with the prefix tags that may now be included in
# the access_db
#
-# Added clarification in the notes for what to do if you have
+# Added clarification in the notes for what to do if you have
# exceptions to a larger CIDR block.
#
+# 26 Jul 2006 Richard Rognlie (richard@sendmail.com>
+# Added code to strip "comments" (anything after a non-escaped #)
+# # characters after a \ or within quotes (single and double) are
+# left intact.
+#
+# e.g.
+# From:1.2.3.4 550 Die spammer # spammed us 2006.07.26
+# becomes
+# From:1.2.3.4 550 Die spammer
+#
# 3 August 2006
#
# Corrected a bug to have it handle the special case of "0.0.0.0/0"
# since Net::CIDR doesn't handle it properly.
#
-# usage:
+# usage:
# cidrexpand < /etc/mail/access | makemap -r hash /etc/mail/access
#
#
@@ -43,32 +53,59 @@
use strict;
use Net::CIDR;
+use Getopt::Std;
+
+our ($opt_c,$opt_t);
+getopts('ct:');
my $spaceregex = '\s+';
-
-while (my $arg = shift @ARGV)
+if ($opt_t)
{
- if ($arg eq '-t')
- {
- $spaceregex = shift;
- }
+ $spaceregex = $opt_t;
}
-use strict;
-
-my $SENDMAIL = 1;
-
while (<>)
{
+ chomp;
my ($prefix,$left,$right,$space);
+ if ( (/\#/) && $opt_c )
+ {
+ # print "checking...\n";
+ my $i;
+ my $qtype='';
+ for ($i=0 ; $i)
}
}
}
-
+
sub expand_network
{
my $left_input = shift;
diff --git a/contrib/sendmail/contrib/qtool.pl b/contrib/sendmail/contrib/qtool.pl
index ba944c2e14eb..d6a63ec17eba 100755
--- a/contrib/sendmail/contrib/qtool.pl
+++ b/contrib/sendmail/contrib/qtool.pl
@@ -3,7 +3,7 @@
## Copyright (c) 1998-2002 Sendmail, Inc. and its suppliers.
## All rights reserved.
##
-## $Id: qtool.pl,v 8.28 2002/06/27 23:06:16 gshapiro Exp $
+## $Id: qtool.pl,v 8.29 2007/02/16 01:12:08 ca Exp $
##
use strict;
use File::Basename;
@@ -69,6 +69,12 @@ my $new_condition;
my $qprefix;
my $queuegroups = 0;
my $conditions = new Compound();
+my $fcntl_struct = 's H60';
+my $fcntl_structlockp = pack($fcntl_struct, Fcntl::F_WRLCK,
+ "000000000000000000000000000000000000000000000000000000000000");
+my $fcntl_structunlockp = pack($fcntl_struct, Fcntl::F_UNLCK,
+ "000000000000000000000000000000000000000000000000000000000000");
+my $lock_both = -1;
Getopt::Std::getopts('bC:de:Qs:', \%opts);
@@ -340,7 +346,9 @@ sub add_source
## Opens a file for read/write and uses flock to obtain a lock on the
## file. The flock is Perl's flock which defaults to flock on systems
## that support it. On systems without flock it falls back to fcntl
-## locking.
+## locking. This script will also call fcntl explicitly if flock
+## uses BSD semantics (i.e. if both flock() and fcntl() can successfully
+## lock the file at the same time)
##
## Parameters:
## file_name -- The name of the file to open and lock.
@@ -358,6 +366,24 @@ sub lock_file
my $file_name = shift;
my $result;
+ if ($lock_both == -1)
+ {
+ if (open(DEVNULL, '>/dev/null'))
+ {
+ my $flock_status = flock(DEVNULL, Fcntl::LOCK_EX | Fcntl::LOCK_NB);
+ my $fcntl_status = fcntl (DEVNULL, Fcntl::F_SETLK, $fcntl_structlockp);
+ close(DEVNULL);
+
+ $lock_both = ($flock_status && $fcntl_status);
+ }
+ else
+ {
+ # Couldn't open /dev/null. Windows system?
+ $lock_both = 0;
+ }
+ }
+
+
$result = sysopen(FILE_TO_LOCK, $file_name, Fcntl::O_RDWR);
if (!$result)
{
@@ -370,6 +396,15 @@ sub lock_file
return (undef, "Could not obtain lock on '$file_name': $!");
}
+ if ($lock_both)
+ {
+ my $result2 = fcntl (FILE_TO_LOCK, Fcntl::F_SETLK, $fcntl_structlockp);
+ if (!$result2)
+ {
+ return (undef, "Could not obtain fcntl lock on '$file_name': $!");
+ }
+ }
+
return (\*FILE_TO_LOCK, undef);
}
@@ -396,6 +431,14 @@ sub unlock_file
{
return "Unlock failed on '$result': $!";
}
+ if ($lock_both)
+ {
+ my $result2 = fcntl ($file, Fcntl::F_SETLK, $fcntl_structunlockp);
+ if (!$result2)
+ {
+ return (undef, "Fcntl unlock failed on '$result': $!");
+ }
+ }
return undef;
}
diff --git a/contrib/sendmail/doc/op/op.me b/contrib/sendmail/doc/op/op.me
index 3f4f0a58cefb..c3a6d56eca9b 100644
--- a/contrib/sendmail/doc/op/op.me
+++ b/contrib/sendmail/doc/op/op.me
@@ -9,7 +9,7 @@
.\" the sendmail distribution.
.\"
.\"
-.\" $Id: op.me,v 8.708 2005/11/12 02:08:04 ca Exp $
+.\" $Id: op.me,v 8.739 2007/03/22 17:56:01 ca Exp $
.\"
.\" eqn op.me | pic | troff -me
.\"
@@ -90,10 +90,10 @@ Sendmail, Inc.
.de Ve
Version \\$2
..
-.Ve $Revision: 8.708 $
+.Ve $Revision: 8.739 $
.rm Ve
.sp
-For Sendmail Version 8.13
+For Sendmail Version 8.14
.)l
.(f
Sendmail is a trademark of Sendmail, Inc.
@@ -982,7 +982,7 @@ This should be a link to /usr/\*(SD/sendmail.
.sh 3 "sendmail.pid"
.pp
.i sendmail
-stores its current pid in the file specifed by the
+stores its current pid in the file specified by the
.b PidFile
option (default is _PATH_SENDMAILPID).
.i sendmail
@@ -4259,6 +4259,13 @@ It can accept or reject mail transfer between these two addresses
much like the
.i checkcompat()
function.
+Note:
+while other
+.i check_*
+rulesets are invoked during the SMTP mail receiption stage
+(i.e., in the SMTP server),
+.i check_compat
+is invoked during the mail delivery stage.
.sh 4 "check_eoh"
.pp
The
@@ -4310,6 +4317,13 @@ Keep in mind the Message-Id: header is not a required header and
is not a guaranteed spam indicator.
This ruleset is an example and
should probably not be used in production.
+.sh 4 "check_eom"
+.pp
+The
+.i check_eom
+ruleset is called after the end of a message,
+its parameter is the message size.
+It can accept or reject the message.
.sh 4 "check_etrn"
.pp
The
@@ -4827,9 +4841,6 @@ This macro contains up to three characters, the first
is either `e' or `h' for envelope/header address,
the second is a space,
and the third is either `s' or `r' for sender/recipient address.
-Notice: for header addresses no distinction is currently made
-between sender and recipient addresses, i.e., the macro contains
-only `h'.
.ip ${alg_bits}
The maximum keylength (in bits) of the symmetric encryption algorithm
used for a TLS connection.
@@ -4878,6 +4889,18 @@ IPv6 addresses are tagged with "IPv6:" before the address.
Defined in the SMTP server only.
.ip ${client_connections}
The number of open connections in the SMTP server for the client IP address.
+.ip ${client_flags}
+The flags specified by the
+Modifier= part of
+.b ClientPortOptions
+where flags are separated from each other by spaces
+and upper case flags are doubled.
+That is,
+Modifier=hA
+will be represented as
+"h AA" in
+.b ${client_flags} ,
+which is required for testing the flags in rulesets.
.ip ${client_name}
The host name of the SMTP client.
This may be the client's bracketed IP address
@@ -6666,6 +6689,7 @@ A running
daemon can be controlled through this named socket.
Available commands are:
.i help,
+.i mstat,
.i restart,
.i shutdown,
and
@@ -6711,6 +6735,11 @@ Listen Size of listen queue (defaults to 10)
Modifier Options (flags) for the daemon
SndBufSize Size of TCP send buffer
RcvBufSize Size of TCP receive buffer
+children maximum number of children per daemon, see \fBMaxDaemonChildren\fP.
+DeliveryMode Delivery mode per daemon, see \fBDeliveryMode\fP.
+refuseLA RefuseLA per daemon
+delayLA DelayLA per daemon
+queueLA QueueLA per daemon
.)b
The
.i Name
@@ -7176,11 +7205,9 @@ will search first in /var/forward/\c
and then in
.i ~username /.forward
(but only if the first file does not exist).
-.ip HelpFile=\fIfile\fP
-[H]
-Specify the help file
-for SMTP.
-If no file name is specified, "helpfile" is used.
+.ip HeloName=\fIname\fP
+[no short name]
+Set the name to be used for HELO/EHLO (instead of $j).
.ip HoldExpensive
[c]
If an outgoing mailer is marked as being expensive,
@@ -7305,7 +7332,7 @@ If the limit should be enforced, then a
.b DeliveryMode
other than background must be used.
If not set, there is no limit to the number of children --
-that is, the system load averaging controls this.
+that is, the system load average controls this.
.ip MaxHeadersLength=\fIN\fP
[no short name]
The maximum length of the sum of all headers.
@@ -7346,6 +7373,13 @@ will be used.
By default,
these values are 2048 and 1024, respectively.
To allow any length, a value of 0 can be specified.
+.ip MaxNOOPCommands=\fIN\fP
+Override the default of
+.b MAXNOOPCOMMANDS
+for the number of
+.i useless
+commands, see Section
+"Measures against Denial of Service Attacks".
.ip MaxQueueChildren=\fIN\fP
[no short name]
When set, this limits the number of concurrent queue runner processes to
@@ -7385,6 +7419,16 @@ highest priority jobs)
this should be set as high as possible to avoid
.q losing
jobs that happen to fall late in the queue directory.
+Note: this option also restricts the number of entries printed by
+.i mailq .
+That is, if
+.i MaxQueueRunSize
+is set to a value
+.b N
+larger than zero,
+then only
+.b N
+entries are printed per queue group.
.ip MaxRecipientsPerMessage=\fIN\fP
[no short name]
The maximum number of recipients that will be accepted per message
@@ -7428,9 +7472,11 @@ after a certain event occurred.
.(b
.ta \w'envfrom'u+3n
connect After session connection start
-helo After HELO command
-envfrom After MAIL FROM command
-envrcpt After RCPT TO command
+helo After EHLO/HELO command
+envfrom After MAIL From command
+envrcpt After RCPT To command
+data After DATA command.
+eoh After DATA command and header
eom After DATA command and terminating ``.''
.)b
By default the lists of macros are empty.
@@ -7560,7 +7606,7 @@ The
.i opt ions
can be selected from:
.(b
-.ta \w'needvrfyhelo'u+3n
+.ta \w'noactualrecipient'u+3n
public Allow open access
needmailhelo Insist on HELO or EHLO command before MAIL
needexpnhelo Insist on HELO or EHLO command before EXPN
@@ -7577,6 +7623,8 @@ nobodyreturn Don't return the body of a message with DSNs
goaway Disallow essentially all SMTP status queries
authwarnings Put X-Authentication-Warning: headers in messages
and log warnings
+noactualrecipient Don't put X-Actual-Recipient lines in DSNs
+ which reveal the actual account that addresses map to.
.)b
.(f
\**N.B.:
@@ -7914,20 +7962,6 @@ UNIX-style
lines at the front of headers.
Normally they are assumed redundant
and discarded.
-.ip SharedMemoryKey
-[no short name]
-Key to use for shared memory segment;
-if not set (or 0), shared memory will not be used.
-Requires support for shared memory to be compiled into
-.i sendmail .
-If this option is set,
-.i sendmail
-can share some data between different instances.
-For example, the number of entries in a queue directory
-or the available space in a file system.
-This allows for more efficient program execution, since only
-one process needs to update the data instead of each individual
-process gathering the data each time it is required.
.ip SendMimeErrors
[j]
If set, send error messages in MIME format
@@ -7986,6 +8020,34 @@ The default file is
[7]
Strip input to seven bits for compatibility with old systems.
This shouldn't be necessary.
+.ip SharedMemoryKey
+[no short name]
+Key to use for shared memory segment;
+if not set (or 0), shared memory will not be used.
+If set to
+-1
+.i sendmail
+can select a key itself provided that also
+.b SharedMemoryKeyFile
+is set.
+Requires support for shared memory to be compiled into
+.i sendmail .
+If this option is set,
+.i sendmail
+can share some data between different instances.
+For example, the number of entries in a queue directory
+or the available space in a file system.
+This allows for more efficient program execution, since only
+one process needs to update the data instead of each individual
+process gathering the data each time it is required.
+.ip SharedMemoryKeyFile
+[no short name]
+If
+.b SharedMemoryKey
+is set to
+-1
+then the automatically selected shared memory key will be stored
+in the specified file.
.ip SingleLineFromHeader
[no short name]
If set, From: lines that have embedded newlines are unwrapped
@@ -8023,6 +8085,10 @@ option.
The message printed when the SMTP server starts up.
Defaults to
.q "$j Sendmail $v ready at $b".
+.ip SoftBounce
+If set, issue temporary errors (4xy) instead of permanent errors (5xy).
+This can be useful during testing of a new configuration to avoid
+erroneous bouncing of mails.
.ip StatusFile=\fIfile\fP
[S]
Log summary statistics in the named
@@ -8817,16 +8883,21 @@ R$\- $: $(storage {MyMacro} $) $1
.)b
.ip arith
Perform simple arithmetic operations.
-The operation is given as key, currently +, -, *, /, %,
+The operation is given as key, currently
++, -, *, /, %,
|, & (bitwise OR, AND),
-l (for less than), and = are supported.
+l (for less than), =,
+and r (for random) are supported.
The two operands are given as arguments.
The lookup returns the result of the computation,
-i.e.
+i.e.,
.sm TRUE
or
.sm FALSE
for comparisons, integer values otherwise.
+The r operator returns a pseudo-random number whose value
+lies between the first and second operand
+(which requires that the first operand is smaller than the second).
All options which are possible for maps are ignored.
A simple example is:
.(b
@@ -8983,6 +9054,10 @@ For LDAP maps this is an LDAP filter string
in which %s is replaced with the literal contents of the lookup key
and %0 is replaced with the LDAP escaped contents of the lookup key
according to RFC 2254.
+If the flag
+.b \-K
+is used, then %1 through %9 are replaced with the LDAP escaped contents
+of the arguments specified in the map lookup.
.ip "\-v\fIvalcol\fP"
The value column name (for NIS+) or number
(for text lookups).
@@ -9007,6 +9082,8 @@ to combine multiple values
into a single return string.
If not set,
the LDAP lookup will only return the first match found.
+For DNS maps this is the separator character at which
+the result of a query is cut off if is too long.
.ip "\-t"
Normally, when a map attempts to do a lookup
and the server fails
@@ -9072,6 +9149,10 @@ delay: specify the resolver's retransmission time interval (in seconds).
.ip "\-r"
retry: specify the number of times to retransmit a resolver query.
.pp
+The dns map has another flag:
+.ip "\-B"
+basedomain: specify a domain that is always appended to queries.
+.pp
The following additional flags are present in the ldap map only:
.ip "\-R"
Do not auto chase referrals. sendmail must be compiled with
@@ -9130,7 +9211,7 @@ LDAP search base.
.ip "\-l\fItimelimit\fP"
Time limit for LDAP queries.
.ip "\-Z\fIsizelimit\fP"
-Size (number of matches) limit for LDAP queries.
+Size (number of matches) limit for LDAP or DNS queries.
.ip "\-d\fIdistinguished_name\fP"
The distinguished name to use to login to the LDAP server.
.ip "\-M\fImethod\fP"
@@ -9158,6 +9239,10 @@ For example,
will cause
.i sendmail
to use LDAPv3 when communicating with the LDAP server.
+.ip "\-K"
+Treat the LDAP search key as multi-argument and
+replace %1 through %9 in the key with
+the LDAP escaped contents of the lookup arguments specified in the map lookup.
.pp
The
.i dbm
@@ -11339,7 +11424,7 @@ replace it with a blank sheet for double-sided output.
.\".sz 10
.\"Eric Allman
.\".sp
-.\"Version $Revision: 8.708 $
+.\"Version $Revision: 8.739 $
.\".ce 0
.bp 3
.ce
diff --git a/contrib/sendmail/editmap/Makefile.m4 b/contrib/sendmail/editmap/Makefile.m4
index d9c611ca4fdc..120aa7827d3c 100644
--- a/contrib/sendmail/editmap/Makefile.m4
+++ b/contrib/sendmail/editmap/Makefile.m4
@@ -1,7 +1,8 @@
-dnl $Id: Makefile.m4,v 1.5 2002/06/21 22:01:30 ca Exp $
+dnl $Id: Makefile.m4,v 1.6 2006/06/28 21:08:01 ca Exp $
include(confBUILDTOOLSDIR`/M4/switch.m4')
define(`confREQUIRE_LIBSM', `true')
+define(`confREQUIRE_SM_OS_H', `true')
# sendmail dir
SMSRCDIR= ifdef(`confSMSRCDIR', `confSMSRCDIR', `${SRCDIR}/sendmail')
PREPENDDEF(`confENVDEF', `confMAPDEF')
diff --git a/contrib/sendmail/include/libmilter/mfapi.h b/contrib/sendmail/include/libmilter/mfapi.h
index 6b85403d0e7f..4338645dc85a 100644
--- a/contrib/sendmail/include/libmilter/mfapi.h
+++ b/contrib/sendmail/include/libmilter/mfapi.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999-2004 Sendmail, Inc. and its suppliers.
+ * Copyright (c) 1999-2004, 2006 Sendmail, Inc. and its suppliers.
* All rights reserved.
*
* By using this file, you agree to the terms and conditions set
@@ -7,7 +7,7 @@
* the sendmail distribution.
*
*
- * $Id: mfapi.h,v 8.61 2006/05/04 17:02:01 ca Exp $
+ * $Id: mfapi.h,v 8.77 2006/11/02 02:44:07 ca Exp $
*/
/*
@@ -18,9 +18,13 @@
# define _LIBMILTER_MFAPI_H 1
#ifndef SMFI_VERSION
-# define SMFI_VERSION 2 /* version number */
+# define SMFI_VERSION 0x01000000 /* libmilter version number */
#endif /* ! SMFI_VERSION */
+#define SM_LM_VRS_MAJOR(v) (((v) & 0x7f000000) >> 24)
+#define SM_LM_VRS_MINOR(v) (((v) & 0x007fff00) >> 8)
+#define SM_LM_VRS_PLVL(v) ((v) & 0x0000007f)
+
# include
# include
@@ -40,11 +44,14 @@ extern "C" {
/*
** libmilter functions return one of the following to indicate
-** success/failure:
+** success/failure(/continue):
*/
#define MI_SUCCESS 0
#define MI_FAILURE (-1)
+#if _FFR_WORKERS_POOL
+# define MI_CONTINUE 1
+#endif /* _FFR_WORKERS_POOL */
/* "forward" declarations */
typedef struct smfi_str SMFICTX;
@@ -128,15 +135,24 @@ struct smfiDesc
/* connection cleanup */
sfsistat (*xxfi_close) SM__P((SMFICTX *));
-#if SMFI_VERSION > 2
/* any unrecognized or unimplemented command filter */
- sfsistat (*xxfi_unknown) SM__P((SMFICTX *, char *));
-#endif /* SMFI_VERSION > 2 */
+ sfsistat (*xxfi_unknown) SM__P((SMFICTX *, const char *));
-#if SMFI_VERSION > 3
/* SMTP DATA command filter */
sfsistat (*xxfi_data) SM__P((SMFICTX *));
-#endif /* SMFI_VERSION > 3 */
+
+ /* negotiation callback */
+ sfsistat (*xxfi_negotiate) SM__P((SMFICTX *,
+ unsigned long, unsigned long,
+ unsigned long, unsigned long,
+ unsigned long *, unsigned long *,
+ unsigned long *, unsigned long *));
+
+#if 0
+ /* signal handler callback, not yet implemented. */
+ int (*xxfi_signal) SM__P((int));
+#endif
+
};
LIBMILTER_API int smfi_opensocket __P((bool));
@@ -150,6 +166,7 @@ LIBMILTER_API int smfi_stop __P((void));
#if _FFR_MAXDATASIZE
LIBMILTER_API size_t smfi_setmaxdatasize __P((size_t));
#endif /* _FFR_MAXDATASIZE */
+LIBMILTER_API int smfi_version __P((unsigned int *, unsigned int *, unsigned int *));
/*
** What the filter might do -- values to be ORed together for
@@ -165,6 +182,33 @@ LIBMILTER_API size_t smfi_setmaxdatasize __P((size_t));
#define SMFIF_CHGHDRS 0x00000010L /* filter may change/delete headers */
#define SMFIF_QUARANTINE 0x00000020L /* filter may quarantine envelope */
+/* filter may change "from" (envelope sender) */
+#define SMFIF_CHGFROM 0x00000040L
+#define SMFIF_ADDRCPT_PAR 0x00000080L /* add recipients incl. args */
+
+/* filter can send set of symbols (macros) that it wants */
+#define SMFIF_SETSYMLIST 0x00000100L
+
+
+/*
+** Macro "places";
+** Notes:
+** - must be coordinated with libmilter/engine.c and sendmail/milter.c
+** - the order MUST NOT be changed as it would break compatibility between
+** different versions. It's ok to append new entries however
+** (hence the list is not sorted by the SMT protocol steps).
+*/
+
+#define SMFIM_FIRST 0 /* Do NOT use, internal marker only */
+#define SMFIM_CONNECT 0 /* connect */
+#define SMFIM_HELO 1 /* HELO/EHLO */
+#define SMFIM_ENVFROM 2 /* MAIL From */
+#define SMFIM_ENVRCPT 3 /* RCPT To */
+#define SMFIM_DATA 4 /* DATA */
+#define SMFIM_EOM 5 /* end of message (final dot) */
+#define SMFIM_EOH 6 /* end of header */
+#define SMFIM_LAST 6 /* Do NOT use, internal marker only */
+
/*
** Continue processing message/connection.
*/
@@ -209,6 +253,21 @@ LIBMILTER_API size_t smfi_setmaxdatasize __P((size_t));
#define SMFIS_TEMPFAIL 4
+/*
+** Do not send a reply to the MTA
+*/
+
+#define SMFIS_NOREPLY 7
+
+/*
+** Skip over rest of same callbacks, e.g., body.
+*/
+
+#define SMFIS_SKIP 8
+
+/* xxfi_negotiate: use all existing protocol options/actions */
+#define SMFIS_ALL_OPTS 10
+
#if 0
/*
** Filter Routine Details
@@ -261,12 +320,12 @@ extern sfsistat xxfi_envrcpt __P((SMFICTX *, char **));
/* unknown command filter */
-extern sfsistat *xxfi_unknown __P((SMFICTX *, char *));
+extern sfsistat *xxfi_unknown __P((SMFICTX *, const char *));
/*
** xxfi_unknown(ctx, arg) Invoked when SMTP command is not recognized or not
** implemented.
-** char *arg; Null-terminated SMTP command
+** const char *arg; Null-terminated SMTP command
*/
/* header filter */
@@ -414,6 +473,17 @@ LIBMILTER_API int smfi_insheader __P((SMFICTX *, int, char *, char *));
** char *headerv; Header field value
*/
+LIBMILTER_API int smfi_chgfrom __P((SMFICTX *, char *, char *));
+
+/*
+** Modify envelope sender address
+**
+** SMFICTX *ctx; Opaque context structure
+** char *mail; New envelope sender address
+** char *args; ESMTP arguments
+*/
+
+
LIBMILTER_API int smfi_addrcpt __P((SMFICTX *, char *));
/*
@@ -423,6 +493,17 @@ LIBMILTER_API int smfi_addrcpt __P((SMFICTX *, char *));
** char *rcpt; Recipient to be added
*/
+LIBMILTER_API int smfi_addrcpt_par __P((SMFICTX *, char *, char *));
+
+/*
+** Add a recipient to the envelope
+**
+** SMFICTX *ctx; Opaque context structure
+** char *rcpt; Recipient to be added
+** char *args; ESMTP arguments
+*/
+
+
LIBMILTER_API int smfi_delrcpt __P((SMFICTX *, char *));
/*
@@ -486,6 +567,27 @@ LIBMILTER_API int smfi_setpriv __P((SMFICTX *, void *));
LIBMILTER_API void *smfi_getpriv __P((SMFICTX *));
+/*
+** Get the private data pointer
+**
+** SMFICTX *ctx; Opaque context structure
+** void *privatedata; Pointer to private data area
+*/
+
+LIBMILTER_API int smfi_setsymlist __P((SMFICTX *, int, char *));
+
+/*
+** Set list of symbols (macros) to receive
+**
+** SMFICTX *ctx; Opaque context structure
+** int where; where in the SMTP dialogue should the macros be sent
+** char *macros; list of macros (space separated)
+*/
+
+#if _FFR_THREAD_MONITOR
+LIBMILTER_API int smfi_set_max_exec_time __P((unsigned int));
+#endif /* _FFR_THREAD_MONITOR */
+
#ifdef __cplusplus
}
#endif /* __cplusplus */
diff --git a/contrib/sendmail/include/libmilter/mfdef.h b/contrib/sendmail/include/libmilter/mfdef.h
index 5b1ddff4e1c8..674856707de4 100644
--- a/contrib/sendmail/include/libmilter/mfdef.h
+++ b/contrib/sendmail/include/libmilter/mfdef.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999-2005 Sendmail, Inc. and its suppliers.
+ * Copyright (c) 1999-2007 Sendmail, Inc. and its suppliers.
* All rights reserved.
*
* By using this file, you agree to the terms and conditions set
@@ -7,7 +7,7 @@
* the sendmail distribution.
*
*
- * $Id: mfdef.h,v 8.22 2005/08/05 21:49:04 ca Exp $
+ * $Id: mfdef.h,v 8.38 2007/03/27 18:53:48 ca Exp $
*/
/*
@@ -17,83 +17,94 @@
#ifndef _LIBMILTER_MFDEF_H
# define _LIBMILTER_MFDEF_H 1
+#ifndef SMFI_PROT_VERSION
+# define SMFI_PROT_VERSION 6 /* MTA - libmilter protocol version */
+#endif /* SMFI_PROT_VERSION */
+
/* Shared protocol constants */
-# define MILTER_LEN_BYTES 4 /* length of 32 bit integer in bytes */
-# define MILTER_OPTLEN (MILTER_LEN_BYTES * 3) /* length of options */
-# define MILTER_CHUNK_SIZE 65535 /* body chunk size */
-# define MILTER_MAX_DATA_SIZE 65535 /* default milter command data limit */
+#define MILTER_LEN_BYTES 4 /* length of 32 bit integer in bytes */
+#define MILTER_OPTLEN (MILTER_LEN_BYTES * 3) /* length of options */
+#define MILTER_CHUNK_SIZE 65535 /* body chunk size */
+#define MILTER_MAX_DATA_SIZE 65535 /* default milter command data limit */
/* These apply to SMFIF_* flags */
#define SMFI_V1_ACTS 0x0000000FL /* The actions of V1 filter */
#define SMFI_V2_ACTS 0x0000003FL /* The actions of V2 filter */
-#define SMFI_CURR_ACTS SMFI_V2_ACTS /* The current version */
+#define SMFI_CURR_ACTS 0x000001FFL /* actions of current version */
/* address families */
-# define SMFIA_UNKNOWN 'U' /* unknown */
-# define SMFIA_UNIX 'L' /* unix/local */
-# define SMFIA_INET '4' /* inet */
-# define SMFIA_INET6 '6' /* inet6 */
+#define SMFIA_UNKNOWN 'U' /* unknown */
+#define SMFIA_UNIX 'L' /* unix/local */
+#define SMFIA_INET '4' /* inet */
+#define SMFIA_INET6 '6' /* inet6 */
/* commands: don't use anything smaller than ' ' */
-# define SMFIC_ABORT 'A' /* Abort */
-# define SMFIC_BODY 'B' /* Body chunk */
-# define SMFIC_CONNECT 'C' /* Connection information */
-# define SMFIC_MACRO 'D' /* Define macro */
-# define SMFIC_BODYEOB 'E' /* final body chunk (End) */
-# define SMFIC_HELO 'H' /* HELO/EHLO */
-# define SMFIC_HEADER 'L' /* Header */
-# define SMFIC_MAIL 'M' /* MAIL from */
-# define SMFIC_EOH 'N' /* EOH */
-# define SMFIC_OPTNEG 'O' /* Option negotiation */
-# define SMFIC_QUIT 'Q' /* QUIT */
-# define SMFIC_RCPT 'R' /* RCPT to */
-# if SMFI_VERSION > 3
-# define SMFIC_DATA 'T' /* DATA */
-# endif /* SMFI_VERSION > 3 */
-# if SMFI_VERSION > 2
-# define SMFIC_UNKNOWN 'U' /* Any unknown command */
-# endif /* SMFI_VERSION > 2 */
+#define SMFIC_ABORT 'A' /* Abort */
+#define SMFIC_BODY 'B' /* Body chunk */
+#define SMFIC_CONNECT 'C' /* Connection information */
+#define SMFIC_MACRO 'D' /* Define macro */
+#define SMFIC_BODYEOB 'E' /* final body chunk (End) */
+#define SMFIC_HELO 'H' /* HELO/EHLO */
+#define SMFIC_QUIT_NC 'K' /* QUIT but new connection follows */
+#define SMFIC_HEADER 'L' /* Header */
+#define SMFIC_MAIL 'M' /* MAIL from */
+#define SMFIC_EOH 'N' /* EOH */
+#define SMFIC_OPTNEG 'O' /* Option negotiation */
+#define SMFIC_QUIT 'Q' /* QUIT */
+#define SMFIC_RCPT 'R' /* RCPT to */
+#define SMFIC_DATA 'T' /* DATA */
+#define SMFIC_UNKNOWN 'U' /* Any unknown command */
/* actions (replies) */
-# define SMFIR_ADDRCPT '+' /* add recipient */
-# define SMFIR_DELRCPT '-' /* remove recipient */
-# define SMFIR_ACCEPT 'a' /* accept */
-# define SMFIR_REPLBODY 'b' /* replace body (chunk) */
-# define SMFIR_CONTINUE 'c' /* continue */
-# define SMFIR_DISCARD 'd' /* discard */
-# define SMFIR_CONN_FAIL 'f' /* cause a connection failure */
-# define SMFIR_CHGHEADER 'm' /* change header */
-# define SMFIR_PROGRESS 'p' /* progress */
-# define SMFIR_REJECT 'r' /* reject */
-# define SMFIR_TEMPFAIL 't' /* tempfail */
-# define SMFIR_SHUTDOWN '4' /* 421: shutdown (internal to MTA) */
-# define SMFIR_ADDHEADER 'h' /* add header */
-# define SMFIR_INSHEADER 'i' /* insert header */
-# define SMFIR_REPLYCODE 'y' /* reply code etc */
-# define SMFIR_QUARANTINE 'q' /* quarantine */
+#define SMFIR_ADDRCPT '+' /* add recipient */
+#define SMFIR_DELRCPT '-' /* remove recipient */
+#define SMFIR_ADDRCPT_PAR '2' /* add recipient (incl. ESMTP args) */
+#define SMFIR_SHUTDOWN '4' /* 421: shutdown (internal to MTA) */
+#define SMFIR_ACCEPT 'a' /* accept */
+#define SMFIR_REPLBODY 'b' /* replace body (chunk) */
+#define SMFIR_CONTINUE 'c' /* continue */
+#define SMFIR_DISCARD 'd' /* discard */
+#define SMFIR_CHGFROM 'e' /* change envelope sender (from) */
+#define SMFIR_CONN_FAIL 'f' /* cause a connection failure */
+#define SMFIR_ADDHEADER 'h' /* add header */
+#define SMFIR_INSHEADER 'i' /* insert header */
+#define SMFIR_SETSYMLIST 'l' /* set list of symbols (macros) */
+#define SMFIR_CHGHEADER 'm' /* change header */
+#define SMFIR_PROGRESS 'p' /* progress */
+#define SMFIR_QUARANTINE 'q' /* quarantine */
+#define SMFIR_REJECT 'r' /* reject */
+#define SMFIR_SKIP 's' /* skip */
+#define SMFIR_TEMPFAIL 't' /* tempfail */
+#define SMFIR_REPLYCODE 'y' /* reply code etc */
/* What the MTA can send/filter wants in protocol */
-# define SMFIP_NOCONNECT 0x00000001L /* MTA should not send connect info */
-# define SMFIP_NOHELO 0x00000002L /* MTA should not send HELO info */
-# define SMFIP_NOMAIL 0x00000004L /* MTA should not send MAIL info */
-# define SMFIP_NORCPT 0x00000008L /* MTA should not send RCPT info */
-# define SMFIP_NOBODY 0x00000010L /* MTA should not send body */
-# define SMFIP_NOHDRS 0x00000020L /* MTA should not send headers */
-# define SMFIP_NOEOH 0x00000040L /* MTA should not send EOH */
-# if _FFR_MILTER_NOHDR_RESP
-# define SMFIP_NOHREPL 0x00000080L /* No reply for headers */
-# endif /* _FFR_MILTER_NOHDR_RESP */
-# define SMFIP_NOUNKNOWN 0x00000100L /* MTA should not send unknown command */
-# define SMFIP_NODATA 0x00000200L /* MTA should not send DATA */
+#define SMFIP_NOCONNECT 0x00000001L /* MTA should not send connect info */
+#define SMFIP_NOHELO 0x00000002L /* MTA should not send HELO info */
+#define SMFIP_NOMAIL 0x00000004L /* MTA should not send MAIL info */
+#define SMFIP_NORCPT 0x00000008L /* MTA should not send RCPT info */
+#define SMFIP_NOBODY 0x00000010L /* MTA should not send body */
+#define SMFIP_NOHDRS 0x00000020L /* MTA should not send headers */
+#define SMFIP_NOEOH 0x00000040L /* MTA should not send EOH */
+#define SMFIP_NR_HDR 0x00000080L /* No reply for headers */
+#define SMFIP_NOHREPL SMFIP_NR_HDR /* No reply for headers */
+#define SMFIP_NOUNKNOWN 0x00000100L /* MTA should not send unknown commands */
+#define SMFIP_NODATA 0x00000200L /* MTA should not send DATA */
+#define SMFIP_SKIP 0x00000400L /* MTA understands SMFIS_SKIP */
+#define SMFIP_RCPT_REJ 0x00000800L /* MTA should also send rejected RCPTs */
+#define SMFIP_NR_CONN 0x00001000L /* No reply for connect */
+#define SMFIP_NR_HELO 0x00002000L /* No reply for HELO */
+#define SMFIP_NR_MAIL 0x00004000L /* No reply for MAIL */
+#define SMFIP_NR_RCPT 0x00008000L /* No reply for RCPT */
+#define SMFIP_NR_DATA 0x00010000L /* No reply for DATA */
+#define SMFIP_NR_UNKN 0x00020000L /* No reply for UNKN */
+#define SMFIP_NR_EOH 0x00040000L /* No reply for eoh */
+#define SMFIP_NR_BODY 0x00080000L /* No reply for body chunk */
+#define SMFIP_HDR_LEADSPC 0x00100000L /* header value leading space */
-# define SMFI_V1_PROT 0x0000003FL /* The protocol of V1 filter */
-# define SMFI_V2_PROT 0x0000007FL /* The protocol of V2 filter */
+#define SMFI_V1_PROT 0x0000003FL /* The protocol of V1 filter */
+#define SMFI_V2_PROT 0x0000007FL /* The protocol of V2 filter */
-/* Note: the "current" version is now determined dynamically in milter.c */
-# if _FFR_MILTER_NOHDR_RESP
-# define SMFI_CURR_PROT 0x000000FFL
-# else /* _FFR_MILTER_NOHDR_RESP */
-# define SMFI_CURR_PROT SMFI_V2_PROT
-# endif /* _FFR_MILTER_NOHDR_RESP */
+/* all defined protocol bits */
+#define SMFI_CURR_PROT 0x001FFFFFL
#endif /* !_LIBMILTER_MFDEF_H */
diff --git a/contrib/sendmail/include/libmilter/milter.h b/contrib/sendmail/include/libmilter/milter.h
index 5178f75620fa..061a4dbb8597 100644
--- a/contrib/sendmail/include/libmilter/milter.h
+++ b/contrib/sendmail/include/libmilter/milter.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999-2003 Sendmail, Inc. and its suppliers.
+ * Copyright (c) 1999-2003, 2006 Sendmail, Inc. and its suppliers.
* All rights reserved.
*
* By using this file, you agree to the terms and conditions set
@@ -7,7 +7,7 @@
* the sendmail distribution.
*
*
- * $Id: milter.h,v 8.39 2003/12/02 00:21:42 msk Exp $
+ * $Id: milter.h,v 8.41 2006/05/22 23:23:55 ca Exp $
*/
/*
@@ -25,31 +25,4 @@
typedef pthread_t sthread_t;
typedef int socket_t;
-# define MAX_MACROS_ENTRIES 5 /* max size of macro pointer array */
-
-/*
-** context for milter
-** implementation hint:
-** macros are stored in mac_buf[] as sequence of:
-** macro_name \0 macro_value
-** (just as read from the MTA)
-** mac_ptr is a list of pointers into mac_buf to the beginning of each
-** entry, i.e., macro_name, macro_value, ...
-*/
-
-struct smfi_str
-{
- sthread_t ctx_id; /* thread id */
- socket_t ctx_sd; /* socket descriptor */
- int ctx_dbg; /* debug level */
- time_t ctx_timeout; /* timeout */
- int ctx_state; /* state */
- smfiDesc_ptr ctx_smfi; /* filter description */
- unsigned long ctx_pflags; /* protocol flags */
- char **ctx_mac_ptr[MAX_MACROS_ENTRIES];
- char *ctx_mac_buf[MAX_MACROS_ENTRIES];
- char *ctx_reply; /* reply code */
- void *ctx_privdata; /* private data */
-};
-
#endif /* ! _LIBMILTER_MILTER_H */
diff --git a/contrib/sendmail/include/sm/conf.h b/contrib/sendmail/include/sm/conf.h
index 919ff0db8e3d..4f05f33ccedf 100644
--- a/contrib/sendmail/include/sm/conf.h
+++ b/contrib/sendmail/include/sm/conf.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998-2006 Sendmail, Inc. and its suppliers.
+ * Copyright (c) 1998-2007 Sendmail, Inc. and its suppliers.
* All rights reserved.
* Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved.
* Copyright (c) 1988, 1993
@@ -10,14 +10,16 @@
* the sendmail distribution.
*
*
- * $Id: conf.h,v 1.128 2006/01/27 18:43:44 ca Exp $
+ * $Id: conf.h,v 1.132 2007/03/21 23:56:18 ca Exp $
*/
/*
** CONF.H -- All user-configurable parameters for sendmail
**
-** Send updates to sendmail@Sendmail.ORG so they will be
-** included in the next release.
+** Send updates to Sendmail.ORG so they will be
+** included in the next release; see
+** http://www.sendmail.org/email-addresses.html
+** for current e-mail address.
*/
#ifndef SM_CONF_H
@@ -160,6 +162,8 @@ extern void hard_syslog();
*/
# ifdef _AIX5
+# include
+# include
# define _AIX4 40300
# define SOCKADDR_LEN_T socklen_t /* e.g., arg#3 to accept, getsockname */
# define SOCKOPT_LEN_T socklen_t /* arg#5 to getsockopt */
@@ -444,6 +448,7 @@ typedef int pid_t;
# define SMRSH_CMDDIR "/var/adm/sm.bin"
# endif /* ! SMRSH_CMDDIR */
# define SL_FUDGE 34 /* fudge offset for SyslogPrefixLen */
+# define HASLDAPGETALIASBYNAME 1 /* added in S8 */
# endif /* SOLARIS >= 20800 || (SOLARIS < 10000 && SOLARIS >= 208) */
# if SOLARIS >= 20900 || (SOLARIS < 10000 && SOLARIS >= 209)
# define HASURANDOMDEV 1 /* /dev/[u]random added in S9 */
@@ -852,36 +857,64 @@ extern unsigned int sleepX __P((unsigned int seconds));
# endif /* __bsdi__ */
+# if defined(__QNX__)
+# if defined(__QNXNTO__)
+/* QNX 6 */
+# include
+# define HASUNSETENV 1 /* has unsetenv(3) call */
+# define HASINITGROUPS 1 /* has initgroups(3) call */
+# define HASSETSID 1 /* has POSIX setsid(2) call */
+# define USESETEUID 1 /* has usable seteuid(2) call */
+# define HASFCHMOD 1 /* has fchmod(2) syscall */
+# define HASFCHOWN 1 /* has fchown(2) syscall */
+# define HASUNAME 1 /* has uname(2) syscall */
+# define HASSTRERROR 1 /* has strerror(3) */
+# define BSD4_4_SOCKADDR /* has sa_len */
+# define ERRLIST_PREDEFINED /* don't declare sys_errlist */
+# define NETLINK 1 /* supports AF_LINK */
+# define GIDSET_T gid_t
+# define QUAD_T uint64_t
+# define HASSNPRINTF 1 /* has snprintf(3) (all versions?) */
+# define HASGETUSERSHELL 0
+
+/*
+** We have a strrev() that doesn't allocate anything.
+** Make sure the one here is used.
+*/
+
+# define strrev strrev_sendmail
+
+# else /* defined(__QNXNTO__) */
+
/*
** QNX 4.2x
** Contributed by Glen McCready .
**
-** Should work with all versions of QNX.
+** Should work with all versions of QNX 4.
*/
-# if defined(__QNX__)
-# include
-# include
-# undef NGROUPS_MAX
-# define HASSETSID 1 /* has POSIX setsid(2) call */
-# define USESETEUID 1 /* has usable seteuid(2) call */
-# define HASFCHMOD 1 /* has fchmod(2) syscall */
-# define HASGETDTABLESIZE 1 /* has getdtablesize(2) call */
-# define HASSETREUID 1 /* has setreuid(2) call */
-# define HASSTRERROR 1 /* has strerror(3) */
-# define HASFLOCK 0
-# undef HASINITGROUPS /* has initgroups(3) call */
-# define SM_CONF_GETOPT 0 /* need a replacement for getopt(3) */
-# define IP_SRCROUTE 1 /* can check IP source routing */
-# define TZ_TYPE TZ_TMNAME /* use tmname variable */
-# define GIDSET_T gid_t
-# define LA_TYPE LA_ZERO
-# define SFS_TYPE SFS_NONE
-# define SPT_TYPE SPT_REUSEARGV
-# define SPT_PADCHAR '\0' /* pad process title with nulls */
-# define HASGETUSERSHELL 0
-# define E_PSEUDOBASE 512
-# define _FILE_H_INCLUDED
+# include
+# include
+# undef NGROUPS_MAX
+# define HASSETSID 1 /* has POSIX setsid(2) call */
+# define USESETEUID 1 /* has usable seteuid(2) call */
+# define HASFCHMOD 1 /* has fchmod(2) syscall */
+# define HASGETDTABLESIZE 1 /* has getdtablesize(2) call */
+# define HASSETREUID 1 /* has setreuid(2) call */
+# define HASSTRERROR 1 /* has strerror(3) */
+# define HASFLOCK 0
+# undef HASINITGROUPS /* has initgroups(3) call */
+# define SM_CONF_GETOPT 0 /* need a replacement for getopt(3) */
+# define IP_SRCROUTE 1 /* can check IP source routing */
+# define TZ_TYPE TZ_TMNAME /* use tmname variable */
+# define GIDSET_T gid_t
+# define LA_TYPE LA_ZERO
+# define SFS_TYPE SFS_NONE
+# define SPT_TYPE SPT_REUSEARGV
+# define SPT_PADCHAR '\0' /* pad process title with nulls */
+# define HASGETUSERSHELL 0
+# define _FILE_H_INCLUDED
+# endif /* defined(__QNXNTO__) */
# endif /* defined(__QNX__) */
diff --git a/contrib/sendmail/include/sm/errstring.h b/contrib/sendmail/include/sm/errstring.h
index 2b937328fd72..1d415260c6d3 100644
--- a/contrib/sendmail/include/sm/errstring.h
+++ b/contrib/sendmail/include/sm/errstring.h
@@ -6,7 +6,7 @@
* forth in the LICENSE file which can be found at the top level of
* the sendmail distribution.
*
- * $Id: errstring.h,v 1.9 2003/12/10 03:19:06 gshapiro Exp $
+ * $Id: errstring.h,v 1.10 2007/03/21 23:56:19 ca Exp $
*/
/*
@@ -16,6 +16,10 @@
#ifndef SM_ERRSTRING_H
# define SM_ERRSTRING_H
+#if defined(__QNX__)
+# define E_PSEUDOBASE 512
+#endif /* defined(__QNX__) */
+
#include
#if NEEDINTERRNO
extern int errno;
diff --git a/contrib/sendmail/include/sm/heap.h b/contrib/sendmail/include/sm/heap.h
index 8b5637015375..cd346b3553d5 100644
--- a/contrib/sendmail/include/sm/heap.h
+++ b/contrib/sendmail/include/sm/heap.h
@@ -1,12 +1,12 @@
/*
- * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers.
+ * Copyright (c) 2000-2001, 2006 Sendmail, Inc. and its suppliers.
* All rights reserved.
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the sendmail distribution.
*
- * $Id: heap.h,v 1.22 2001/09/04 22:41:55 ca Exp $
+ * $Id: heap.h,v 1.23 2006/08/15 00:53:46 ca Exp $
*/
/*
@@ -91,6 +91,16 @@ sm_fcalloc __P((
# define sm_heap_setgroup(g) (SmHeapGroup = (g))
# define sm_heap_newgroup() (SmHeapGroup = ++SmHeapMaxGroup)
+#define SM_FREE(ptr) \
+ do \
+ { \
+ if ((ptr) != NULL) \
+ { \
+ sm_free(ptr); \
+ (ptr) = NULL; \
+ } \
+ } while (0)
+
extern int SmHeapGroup;
extern int SmHeapMaxGroup;
diff --git a/contrib/sendmail/include/sm/ldap.h b/contrib/sendmail/include/sm/ldap.h
index 7db8355be8b7..63292f1f5845 100644
--- a/contrib/sendmail/include/sm/ldap.h
+++ b/contrib/sendmail/include/sm/ldap.h
@@ -1,12 +1,12 @@
/*
- * Copyright (c) 2001-2003, 2005 Sendmail, Inc. and its suppliers.
+ * Copyright (c) 2001-2003, 2005, 2006 Sendmail, Inc. and its suppliers.
* All rights reserved.
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the sendmail distribution.
*
- * $Id: ldap.h,v 1.28 2005/06/23 23:11:21 ca Exp $
+ * $Id: ldap.h,v 1.32 2006/08/30 22:56:58 ca Exp $
*/
#ifndef SM_LDAP_H
@@ -17,7 +17,7 @@
/*
** NOTE: These should be changed from LDAPMAP_* to SM_LDAP_*
-** in the next major release (8.13) of sendmail.
+** in the next major release (8.x+1) of sendmail.
*/
# ifndef LDAPMAP_MAX_ATTR
@@ -32,6 +32,13 @@
# if LDAPMAP
+/* maximum number of arguments in a map lookup, see sendmail.h: MAX_MAP_ARGS */
+# define SM_LDAP_ARGS 10
+
+/* error codes from sm_ldap_search*() */
+# define SM_LDAP_ERR (-1) /* generic error: ldap_search(3) */
+# define SM_LDAP_ERR_ARG_MISS (-2) /* an argument is missing */
+
/* Attribute types */
# define SM_LDAP_ATTR_NONE (-1)
# define SM_LDAP_ATTR_OBJCLASS 0
@@ -75,6 +82,7 @@ struct sm_ldap_struct
int ldap_attr_type[LDAPMAP_MAX_ATTR + 1];
char *ldap_attr_needobjclass[LDAPMAP_MAX_ATTR + 1];
bool ldap_attrsonly;
+ bool ldap_multi_args;
/* args for ldap_result */
struct timeval ldap_timeout;
@@ -91,18 +99,18 @@ typedef struct sm_ldap_struct SM_LDAP_STRUCT;
struct sm_ldap_recurse_entry
{
- char *lr_search;
- int lr_type;
- LDAPURLDesc *lr_ludp;
- char **lr_attrs;
- bool lr_done;
+ char *lr_search;
+ int lr_type;
+ LDAPURLDesc *lr_ludp;
+ char **lr_attrs;
+ bool lr_done;
};
struct sm_ldap_recurse_list
{
- int lr_size;
- int lr_cnt;
- struct sm_ldap_recurse_entry **lr_data;
+ int lrl_size;
+ int lrl_cnt;
+ struct sm_ldap_recurse_entry **lrl_data;
};
typedef struct sm_ldap_recurse_entry SM_LDAP_RECURSE_ENTRY;
@@ -112,6 +120,7 @@ typedef struct sm_ldap_recurse_list SM_LDAP_RECURSE_LIST;
extern void sm_ldap_clear __P((SM_LDAP_STRUCT *));
extern bool sm_ldap_start __P((char *, SM_LDAP_STRUCT *));
extern int sm_ldap_search __P((SM_LDAP_STRUCT *, char *));
+extern int sm_ldap_search_m __P((SM_LDAP_STRUCT *, char **));
extern int sm_ldap_results __P((SM_LDAP_STRUCT *, int, int, int,
SM_RPOOL_T *, char **, int *, int *,
SM_LDAP_RECURSE_LIST *));
diff --git a/contrib/sendmail/include/sm/misc.h b/contrib/sendmail/include/sm/misc.h
new file mode 100644
index 000000000000..a9d66379bcf2
--- /dev/null
+++ b/contrib/sendmail/include/sm/misc.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2006 Sendmail, Inc. and its suppliers.
+ * All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set
+ * forth in the LICENSE file which can be found at the top level of
+ * the sendmail distribution.
+ *
+ * $Id: misc.h,v 1.1 2006/06/28 23:57:59 ca Exp $
+ */
+
+#ifndef SM_MISC_H
+# define SM_MISC_H 1
+
+int sm_memstat_open __P((void));
+int sm_memstat_close __P((void));
+int sm_memstat_get __P((char *, long *));
+
+#endif /* ! SM_MISC_H */
diff --git a/contrib/sendmail/include/sm/os/sm_os_qnx.h b/contrib/sendmail/include/sm/os/sm_os_qnx.h
new file mode 100644
index 000000000000..976982768393
--- /dev/null
+++ b/contrib/sendmail/include/sm/os/sm_os_qnx.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2007 Sendmail, Inc. and its suppliers.
+ * All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set
+ * forth in the LICENSE file which can be found at the top level of
+ * the sendmail distribution.
+ *
+ * $Id: sm_os_qnx.h,v 1.1 2007/03/21 23:56:20 ca Exp $
+ */
+
+/*
+** sm_os_qnx.h -- platform definitions for QNX
+*/
+
+#define SM_CONF_SYS_CDEFS_H 1
+
+#ifndef SM_CONF_SETITIMER
+# define SM_CONF_SETITIMER 0
+#endif /* SM_CONF_SETITIMER */
diff --git a/contrib/sendmail/include/sm/sendmail.h b/contrib/sendmail/include/sm/sendmail.h
new file mode 100644
index 000000000000..3008934a94b6
--- /dev/null
+++ b/contrib/sendmail/include/sm/sendmail.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2006 Sendmail, Inc. and its suppliers.
+ * All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set
+ * forth in the LICENSE file which can be found at the top level of
+ * the sendmail distribution.
+ */
+
+/*
+** SENDMAIL.H -- MTA-specific definitions for sendmail.
+*/
+
+#ifndef _SM_SENDMAIL_H
+# define _SM_SENDMAIL_H 1
+
+/* "out of band" indicator */
+#define METAQUOTE ((unsigned char)0377) /* quotes the next octet */
+
+extern int dequote_internal_chars __P((char *, char *, int));
+extern char *quote_internal_chars __P((char *, char *, int *));
+extern char *str2prt __P((char *));
+
+#endif /* ! _SM_SENDMAIL_H */
diff --git a/contrib/sendmail/include/sm/tailq.h b/contrib/sendmail/include/sm/tailq.h
new file mode 100644
index 000000000000..cfb09be8d0bb
--- /dev/null
+++ b/contrib/sendmail/include/sm/tailq.h
@@ -0,0 +1,153 @@
+/* $OpenBSD: queue.h,v 1.30 2005/10/25 06:37:47 otto Exp $ */
+/* $NetBSD: queue.h,v 1.11 1996/05/16 05:17:14 mycroft Exp $ */
+
+/*
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)queue.h 8.5 (Berkeley) 8/20/94
+ */
+
+#ifndef SM_TAILQ_H_
+#define SM_TAILQ_H_
+
+/*
+ * This file is a modified copy of queue.h from a BSD system:
+ * we only need tail queues here.
+ *
+ * A tail queue is headed by a pair of pointers, one to the head of the
+ * list and the other to the tail of the list. The elements are doubly
+ * linked so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before or
+ * after an existing element, at the head of the list, or at the end of
+ * the list. A tail queue may be traversed in either direction.
+ */
+
+/*
+ * Tail queue definitions.
+ */
+#define SM_TAILQ_HEAD(name, type) \
+struct name { \
+ struct type *tqh_first; /* first element */ \
+ struct type **tqh_last; /* addr of last next element */ \
+}
+
+#define SM_TAILQ_HEAD_INITIALIZER(head) \
+ { NULL, &(head).tqh_first }
+
+#define SM_TAILQ_ENTRY(type) \
+struct { \
+ struct type *tqe_next; /* next element */ \
+ struct type **tqe_prev; /* address of previous next element */ \
+}
+
+/*
+ * tail queue access methods
+ */
+#define SM_TAILQ_FIRST(head) ((head)->tqh_first)
+#define SM_TAILQ_END(head) NULL
+#define SM_TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
+#define SM_TAILQ_LAST(head, headname) \
+ (*(((struct headname *)((head)->tqh_last))->tqh_last))
+/* XXX */
+#define SM_TAILQ_PREV(elm, headname, field) \
+ (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
+#define SM_TAILQ_EMPTY(head) \
+ (SM_TAILQ_FIRST(head) == SM_TAILQ_END(head))
+
+#define SM_TAILQ_FOREACH(var, head, field) \
+ for((var) = SM_TAILQ_FIRST(head); \
+ (var) != SM_TAILQ_END(head); \
+ (var) = SM_TAILQ_NEXT(var, field))
+
+#define SM_TAILQ_FOREACH_REVERSE(var, head, headname, field) \
+ for((var) = SM_TAILQ_LAST(head, headname); \
+ (var) != SM_TAILQ_END(head); \
+ (var) = SM_TAILQ_PREV(var, headname, field))
+
+/*
+ * Tail queue functions.
+ */
+#define SM_TAILQ_INIT(head) do { \
+ (head)->tqh_first = NULL; \
+ (head)->tqh_last = &(head)->tqh_first; \
+} while (0)
+
+#define SM_TAILQ_INSERT_HEAD(head, elm, field) do { \
+ if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \
+ (head)->tqh_first->field.tqe_prev = \
+ &(elm)->field.tqe_next; \
+ else \
+ (head)->tqh_last = &(elm)->field.tqe_next; \
+ (head)->tqh_first = (elm); \
+ (elm)->field.tqe_prev = &(head)->tqh_first; \
+} while (0)
+
+#define SM_TAILQ_INSERT_TAIL(head, elm, field) do { \
+ (elm)->field.tqe_next = NULL; \
+ (elm)->field.tqe_prev = (head)->tqh_last; \
+ *(head)->tqh_last = (elm); \
+ (head)->tqh_last = &(elm)->field.tqe_next; \
+} while (0)
+
+#define SM_TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
+ if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\
+ (elm)->field.tqe_next->field.tqe_prev = \
+ &(elm)->field.tqe_next; \
+ else \
+ (head)->tqh_last = &(elm)->field.tqe_next; \
+ (listelm)->field.tqe_next = (elm); \
+ (elm)->field.tqe_prev = &(listelm)->field.tqe_next; \
+} while (0)
+
+#define SM_TAILQ_INSERT_BEFORE(listelm, elm, field) do { \
+ (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \
+ (elm)->field.tqe_next = (listelm); \
+ *(listelm)->field.tqe_prev = (elm); \
+ (listelm)->field.tqe_prev = &(elm)->field.tqe_next; \
+} while (0)
+
+#define SM_TAILQ_REMOVE(head, elm, field) do { \
+ if (((elm)->field.tqe_next) != NULL) \
+ (elm)->field.tqe_next->field.tqe_prev = \
+ (elm)->field.tqe_prev; \
+ else \
+ (head)->tqh_last = (elm)->field.tqe_prev; \
+ *(elm)->field.tqe_prev = (elm)->field.tqe_next; \
+} while (0)
+
+#define SM_TAILQ_REPLACE(head, elm, elm2, field) do { \
+ if (((elm2)->field.tqe_next = (elm)->field.tqe_next) != NULL) \
+ (elm2)->field.tqe_next->field.tqe_prev = \
+ &(elm2)->field.tqe_next; \
+ else \
+ (head)->tqh_last = &(elm2)->field.tqe_next; \
+ (elm2)->field.tqe_prev = (elm)->field.tqe_prev; \
+ *(elm2)->field.tqe_prev = (elm2); \
+} while (0)
+
+#endif /* !SM_TAILQ_H_ */
diff --git a/contrib/sendmail/libmilter/Makefile b/contrib/sendmail/libmilter/Makefile
index 04277eb6e2c9..b5bfba403447 100644
--- a/contrib/sendmail/libmilter/Makefile
+++ b/contrib/sendmail/libmilter/Makefile
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 8.1 1999/11/04 00:03:40 ca Exp $
+# $Id: Makefile,v 8.2 2006/05/23 21:55:55 ca Exp $
SHELL= /bin/sh
BUILD= ./Build
@@ -6,6 +6,8 @@ OPTIONS= $(CONFIG) $(FLAGS)
all: FRC
$(SHELL) $(BUILD) $(OPTIONS) $@
+check: FRC
+ $(SHELL) $(BUILD) $(OPTIONS) $@
clean: FRC
$(SHELL) $(BUILD) $(OPTIONS) $@
install: FRC
diff --git a/contrib/sendmail/libmilter/Makefile.m4 b/contrib/sendmail/libmilter/Makefile.m4
index 5bc1a92a4a39..7902c2f600b1 100644
--- a/contrib/sendmail/libmilter/Makefile.m4
+++ b/contrib/sendmail/libmilter/Makefile.m4
@@ -1,19 +1,19 @@
-dnl $Id: Makefile.m4,v 8.31 2002/06/21 22:01:31 ca Exp $
+dnl $Id: Makefile.m4,v 8.78 2007/02/05 19:21:29 ca Exp $
include(confBUILDTOOLSDIR`/M4/switch.m4')
dnl only required for compilation of EXTRAS
-define(`confREQUIRE_LIBSM', `true')
+define(`confREQUIRE_SM_OS_H', `true')
define(`confMT', `true')
# sendmail dir
-SMSRCDIR= ifdef(`confSMSRCDIR', `confSMSRCDIR', `${SRCDIR}/sendmail')
+SMSRCDIR=ifdef(`confSMSRCDIR', `confSMSRCDIR', `${SRCDIR}/sendmail')
PREPENDDEF(`confINCDIRS', `-I${SMSRCDIR} ')
bldPRODUCT_START(`library', `libmilter')
define(`bldINSTALLABLE', `true')
define(`LIBMILTER_EXTRAS', `errstring.c strl.c')
APPENDDEF(`confENVDEF', `-DNOT_SENDMAIL -Dsm_snprintf=snprintf')
-define(`bldSOURCES', `main.c engine.c listener.c handler.c comm.c smfi.c signal.c sm_gethost.c LIBMILTER_EXTRAS ')
+define(`bldSOURCES', `main.c engine.c listener.c worker.c handler.c comm.c smfi.c signal.c sm_gethost.c monitor.c LIBMILTER_EXTRAS ')
define(`confBEFORE', `LIBMILTER_EXTRAS')
bldPUSH_INSTALL_TARGET(`install-mfapi')
bldPRODUCT_END
diff --git a/contrib/sendmail/libmilter/README b/contrib/sendmail/libmilter/README
index 1aadc4f4e2c9..e9c2cb1376e4 100644
--- a/contrib/sendmail/libmilter/README
+++ b/contrib/sendmail/libmilter/README
@@ -90,8 +90,10 @@ IPv4 socket on port 3333 of localhost. The current flags (F=) are:
R Reject connection if filter unavailable
T Temporary fail connection if filter unavailable
+ 4 Shut down connection if filter unavailable
+ (with a 421 temporary error).
-If neither F=R nor F=T is specified, the message is passed through sendmail
+If none of these is specified, the message is passed through sendmail
in case of filter errors as if the failing filters were not present.
Finally, you can override the default timeouts used by sendmail when
@@ -164,7 +166,7 @@ connected via one of these options, the session can be continued through
the use of standard SMTP commands.
% sendmail -bs
-220 test.sendmail.com ESMTP Sendmail 8.11.0/8.11.0; Tue, 10 Nov 1970 13:05:23 -0500 (EST)
+220 test.sendmail.com ESMTP Sendmail 8.14.0/8.14.0; Thu, 22 Jun 2006 13:05:23 -0500 (EST)
HELO localhost
250 test.sendmail.com Hello testy@localhost, pleased to meet you
MAIL From:
@@ -225,248 +227,8 @@ Feedback about problems (and possible fixes) is welcome.
| SOURCE FOR SAMPLE FILTER |
+--------------------------+
-Note that the filter below may not be thread safe on some operating
+Note that the filter example.c may not be thread safe on some operating
systems. You should check your system man pages for the functions used
below to verify the functions are thread safe.
-/* A trivial filter that logs all email to a file. */
-
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include "libmilter/mfapi.h"
-
-#ifndef true
-typedef int bool;
-# define false 0
-# define true 1
-#endif /* ! true */
-
-struct mlfiPriv
-{
- char *mlfi_fname;
- FILE *mlfi_fp;
-};
-
-#define MLFIPRIV ((struct mlfiPriv *) smfi_getpriv(ctx))
-
-extern sfsistat mlfi_cleanup(SMFICTX *, bool);
-
-sfsistat
-mlfi_envfrom(ctx, envfrom)
- SMFICTX *ctx;
- char **envfrom;
-{
- struct mlfiPriv *priv;
- int fd = -1;
-
- /* allocate some private memory */
- priv = malloc(sizeof *priv);
- if (priv == NULL)
- {
- /* can't accept this message right now */
- return SMFIS_TEMPFAIL;
- }
- memset(priv, '\0', sizeof *priv);
-
- /* open a file to store this message */
- priv->mlfi_fname = strdup("/tmp/msg.XXXXXXXX");
- if (priv->mlfi_fname == NULL)
- {
- free(priv);
- return SMFIS_TEMPFAIL;
- }
- if ((fd = mkstemp(priv->mlfi_fname)) < 0 ||
- (priv->mlfi_fp = fdopen(fd, "w+")) == NULL)
- {
- if (fd >= 0)
- (void) close(fd);
- free(priv->mlfi_fname);
- free(priv);
- return SMFIS_TEMPFAIL;
- }
-
- /* save the private data */
- smfi_setpriv(ctx, priv);
-
- /* continue processing */
- return SMFIS_CONTINUE;
-}
-
-sfsistat
-mlfi_header(ctx, headerf, headerv)
- SMFICTX *ctx;
- char *headerf;
- char *headerv;
-{
- /* write the header to the log file */
- fprintf(MLFIPRIV->mlfi_fp, "%s: %s\r\n", headerf, headerv);
-
- /* continue processing */
- return SMFIS_CONTINUE;
-}
-
-sfsistat
-mlfi_eoh(ctx)
- SMFICTX *ctx;
-{
- /* output the blank line between the header and the body */
- fprintf(MLFIPRIV->mlfi_fp, "\r\n");
-
- /* continue processing */
- return SMFIS_CONTINUE;
-}
-
-sfsistat
-mlfi_body(ctx, bodyp, bodylen)
- SMFICTX *ctx;
- u_char *bodyp;
- size_t bodylen;
-{
- /* output body block to log file */
- if (fwrite(bodyp, bodylen, 1, MLFIPRIV->mlfi_fp) <= 0)
- {
- /* write failed */
- (void) mlfi_cleanup(ctx, false);
- return SMFIS_TEMPFAIL;
- }
-
- /* continue processing */
- return SMFIS_CONTINUE;
-}
-
-sfsistat
-mlfi_eom(ctx)
- SMFICTX *ctx;
-{
- return mlfi_cleanup(ctx, true);
-}
-
-sfsistat
-mlfi_close(ctx)
- SMFICTX *ctx;
-{
- return SMFIS_ACCEPT;
-}
-
-sfsistat
-mlfi_abort(ctx)
- SMFICTX *ctx;
-{
- return mlfi_cleanup(ctx, false);
-}
-
-sfsistat
-mlfi_cleanup(ctx, ok)
- SMFICTX *ctx;
- bool ok;
-{
- sfsistat rstat = SMFIS_CONTINUE;
- struct mlfiPriv *priv = MLFIPRIV;
- char *p;
- char host[512];
- char hbuf[1024];
-
- if (priv == NULL)
- return rstat;
-
- /* close the archive file */
- if (priv->mlfi_fp != NULL && fclose(priv->mlfi_fp) == EOF)
- {
- /* failed; we have to wait until later */
- rstat = SMFIS_TEMPFAIL;
- (void) unlink(priv->mlfi_fname);
- }
- else if (ok)
- {
- /* add a header to the message announcing our presence */
- if (gethostname(host, sizeof host) < 0)
- snprintf(host, sizeof host, "localhost");
- p = strrchr(priv->mlfi_fname, '/');
- if (p == NULL)
- p = priv->mlfi_fname;
- else
- p++;
- snprintf(hbuf, sizeof hbuf, "%s@%s", p, host);
- smfi_addheader(ctx, "X-Archived", hbuf);
- }
- else
- {
- /* message was aborted -- delete the archive file */
- (void) unlink(priv->mlfi_fname);
- }
-
- /* release private memory */
- free(priv->mlfi_fname);
- free(priv);
- smfi_setpriv(ctx, NULL);
-
- /* return status */
- return rstat;
-}
-
-struct smfiDesc smfilter =
-{
- "SampleFilter", /* filter name */
- SMFI_VERSION, /* version code -- do not change */
- SMFIF_ADDHDRS, /* flags */
- NULL, /* connection info filter */
- NULL, /* SMTP HELO command filter */
- mlfi_envfrom, /* envelope sender filter */
- NULL, /* envelope recipient filter */
- mlfi_header, /* header filter */
- mlfi_eoh, /* end of header */
- mlfi_body, /* body block filter */
- mlfi_eom, /* end of message */
- mlfi_abort, /* message aborted */
- mlfi_close /* connection cleanup */
-};
-
-
-int
-main(argc, argv)
- int argc;
- char *argv[];
-{
- bool setconn = false;
- int c;
- const char *args = "p:";
-
- /* Process command line options */
- while ((c = getopt(argc, argv, args)) != -1)
- {
- switch (c)
- {
- case 'p':
- if (optarg == NULL || *optarg == '\0')
- {
- (void) fprintf(stderr, "Illegal conn: %s\n",
- optarg);
- exit(EX_USAGE);
- }
- (void) smfi_setconn(optarg);
- setconn = true;
- break;
-
- }
- }
- if (!setconn)
- {
- fprintf(stderr, "%s: Missing required -p argument\n", argv[0]);
- exit(EX_USAGE);
- }
- if (smfi_register(smfilter) == MI_FAILURE)
- {
- fprintf(stderr, "smfi_register failed\n");
- exit(EX_UNAVAILABLE);
- }
- return smfi_main();
-}
-
-/* eof */
-
-$Revision: 8.41 $, Last updated $Date: 2005/04/27 22:47:42 $
+$Revision: 8.42 $, Last updated $Date: 2006/06/29 17:10:16 $
diff --git a/contrib/sendmail/libmilter/comm.c b/contrib/sendmail/libmilter/comm.c
index accb95614817..a7a44dffa7bd 100644
--- a/contrib/sendmail/libmilter/comm.c
+++ b/contrib/sendmail/libmilter/comm.c
@@ -9,7 +9,7 @@
*/
#include
-SM_RCSID("@(#)$Id: comm.c,v 8.66 2004/08/20 20:38:35 ca Exp $")
+SM_RCSID("@(#)$Id: comm.c,v 8.67 2006/11/02 17:54:44 ca Exp $")
#include "libmilter.h"
#include
@@ -352,7 +352,7 @@ mi_wr_cmd(sd, timeout, cmd, buf, len)
iov[1].iov_len = len;
iovcnt = 2;
}
-
+
l = retry_writev(sd, iov, iovcnt, timeout);
if (l == MI_FAILURE)
return MI_FAILURE;
diff --git a/contrib/sendmail/libmilter/docs/api.html b/contrib/sendmail/libmilter/docs/api.html
index 23c4de41b42d..4214df4dd87a 100644
--- a/contrib/sendmail/libmilter/docs/api.html
+++ b/contrib/sendmail/libmilter/docs/api.html
@@ -1,233 +1,320 @@
-
-Milter API
-
+
+Milter API
+
-Milter API
+Milter API
-Contents
-
- - Library Control Functions
-
- Data Access Functions
-
- Message Modification Functions
-
- Callbacks
-
+Contents
+
-Library Control Functions
+
-Before handing control to libmilter (by calling smfi_main), a filter may call the following
-functions to set libmilter parameters. In particular, the filter must
-call smfi_register to register its
-callbacks. Each function will return either MI_SUCCESS or MI_FAILURE to
+Before handing control to libmilter (by calling
+smfi_main), a filter may call the following
+functions to set libmilter parameters.
+In particular, the filter must call
+smfi_register to register its callbacks.
+Each function will return either MI_SUCCESS or MI_FAILURE to
indicate the status of the operation.
-
+
+
None of these functions communicate with the MTA. All alter the
-library's state, some of which is communicated to the MTA inside smfi_main.
-
-
Function | Description |
+library's state, some of which is communicated to the MTA inside
+smfi_main.
-smfi_opensocket | Try to create the interface socket. |
+
+
+smfi_main | Hand control to libmilter. |
-Data Access Functions
+
+
+
The following functions may be called from within the filter-defined callbacks
to access information about the current connection or message.
-
-
Function | Description |
-smfi_getsymval | Return the value
-of a symbol. |
+
+
+
-Message Modification Functions
+
The following functions change a message's contents and attributes.
-They may only be called in xxfi_eom.
+They may only be called in xxfi_eom.
All of these functions may invoke additional communication with the MTA.
They will return either MI_SUCCESS or MI_FAILURE to indicate the status of
the operation.
-
+
A filter must have set the appropriate flag (listed below) in the
-description passed to smfi_register
+description passed to smfi_register
to call any message modification function. Failure to do so will
cause the MTA to treat a call to the function as a failure of the
filter, terminating its connection.
-
+
Note that the status returned indicates only whether or not the
filter's message was successfully sent to the MTA, not whether or not
-the MTA performed the requested operation. For example, smfi_addheader, when called with an
+the MTA performed the requested operation. For example,
+smfi_addheader, when called with an
illegal header name, will return MI_SUCCESS even though the MTA may
later refuse to add the illegal header.
-
-
Function | Description | SMFIF_* flag |
-smfi_addheader | Add a header to
-the message. | SMFIF_ADDHDRS |
+
+
+smfi_delrcpt | Delete a recipient
+from the envelope. | SMFIF_DELRCPT |
-Other Message Handling Functions
+smfi_replacebody | Replace the
+body of the message. | SMFIF_CHGBODY |
+
+
+
+Other Message Handling Functions
The following functions provide special case handling instructions for
milter or the MTA, without altering the content or status of the message.
-They too may only be called in xxfi_eom.
+They too may only be called in xxfi_eom.
All of these functions may invoke additional communication with the MTA.
They will return either MI_SUCCESS or MI_FAILURE to indicate the status of
the operation.
-
+
Note that the status returned indicates only whether or not the
filter's message was successfully sent to the MTA, not whether or not
the MTA performed the requested operation.
-
-
Function | Description |
-smfi_progress | Report operation in progress. |
+
+
+
-
+
The filter should implement one or more of the following callbacks,
-which are registered via smfi_register:
-
-
+
+
The above callbacks should all return one of the following return values,
having the indicated meanings. Any return other than one of the below
values constitutes an error, and will cause sendmail to terminate its
connection to the offending filter.
-
Milter distinguishes between recipient-,
+
Milter distinguishes between recipient-,
message-, and connection-oriented routines. Recipient-oriented
callbacks may affect the processing of a single message recipient;
message-oriented callbacks, a single message; connection-oriented
callbacks, an entire connection (during which multiple messages may be
delivered to multiple sets of recipients).
-xxfi_envrcpt is recipient-oriented.
-xxfi_connect,
-xxfi_helo and
-xxfi_close are connection-oriented. All
+xxfi_envrcpt is recipient-oriented.
+xxfi_connect,
+xxfi_helo and
+xxfi_close are connection-oriented. All
other callbacks are message-oriented.
-
-
- Return value | Description |
-
- SMFIS_CONTINUE |
- Continue processing the current connection, message, or recipient.
- |
-
-
- SMFIS_REJECT |
- For a connection-oriented routine, reject this connection; call xxfi_close.
+
+
+ Return value | Description |
+
+ SMFIS_CONTINUE |
+ Continue processing the current connection, message, or recipient.
+ |
+
+
+ SMFIS_REJECT |
+ For a connection-oriented routine, reject this connection; call xxfi_close.
For a message-oriented routine (except
- xxfi_eom or
- xxfi_abort), reject this message.
+ xxfi_eom or
+ xxfi_abort), reject this message.
For a recipient-oriented routine, reject the current recipient (but continue processing the current message).
- |
-
-
- SMFIS_DISCARD |
- For a message- or recipient-oriented routine, accept this message, but silently discard it.
+ |
+
+
+ SMFIS_DISCARD |
+ For a message- or recipient-oriented routine, accept this message, but silently discard it.
SMFIS_DISCARD should not be returned by a connection-oriented routine.
- |
-
-
- SMFIS_ACCEPT |
- For a connection-oriented routine, accept this connection without further filter processing; call xxfi_close.
- For a message- or recipient-oriented routine, accept this message without further filtering.
- |
-
-
- SMFIS_TEMPFAIL |
- Return a temporary failure, i.e., the corresponding SMTP command will return an appropriate 4xx status code.
- For a message-oriented routine (except xxfi_envfrom), fail for this message.
- For a connection-oriented routine, fail for this connection; call xxfi_close.
+ |
+
+
+ SMFIS_ACCEPT |
+ For a connection-oriented routine, accept this connection without further filter processing; call xxfi_close.
+ For a message- or recipient-oriented routine, accept this message without further filtering.
+ |
+
+
+ SMFIS_TEMPFAIL |
+ Return a temporary failure, i.e., the corresponding SMTP command will return an appropriate 4xx status code.
+ For a message-oriented routine (except xxfi_envfrom), fail for this message.
+ For a connection-oriented routine, fail for this connection; call xxfi_close.
For a recipient-oriented routine, only fail for the current recipient; continue message processing.
- |
-
-
+ |
+
-
-
-Copyright (c) 2000, 2003 Sendmail, Inc. and its suppliers.
+
+ SMFIS_SKIP |
+ Skip further callbacks of the same type in this transaction.
+ Currently this return value is only allowed in
+ xxfi_body().
+ It can be used if a milter has received sufficiently many
+ body chunks to make a decision, but still wants to invoke
+ message modification functions that are only allowed to be called from
+ xxfi_eom().
+ Note: the milter must
+ negotiate
+ this behavior with the MTA, i.e., it must check whether
+ the protocol action
+ SMFIP_SKIP
+ is available and if so, the milter must request it.
+ |
+
+
+
+ SMFIS_NOREPLY |
+ Do not send a reply back to the MTA.
+ The milter must
+ negotiate
+ this behavior with the MTA, i.e., it must check whether
+ the appropriate protocol action
+ SMFIP_NR_*
+ is available and if so, the milter must request it.
+ If you set the
+ SMFIP_NR_*
+ protocol action for a callback, that callback must
+ always reply with
+ SMFIS_NOREPLY.
+ Using any other reply code is a violation of the API.
+ If in some cases your callback may return another value
+ (e.g., due to some resource shortages), then you
+ must not set
+ SMFIP_NR_*
+ and you must use
+ SMFIS_CONTINUE as the default return code.
+ (Alternatively you can try to delay reporting the problem to
+ a later callback for which
+ SMFIP_NR_*
+ is not set.)
+ |
+
+
+
+
+
+
+
+
Function | Description |
+
+smfi_version | libmilter (runtime) version info |
+
+smfi_setsymlist |
+Set the list of macros that the milter wants to receive from the MTA
+for a protocol stage.
+ |
+
+
+
+
+
Constant | Description |
+
+SMFI_VERSION | libmilter (compile time) version info |
+
+
+
+
+
+
+Copyright (c) 2000, 2003, 2006 Sendmail, Inc. and its suppliers.
All rights reserved.
-
+
By using this file, you agree to the terms and conditions set
forth in the LICENSE.
-
-
-
+
+
+
diff --git a/contrib/sendmail/libmilter/docs/design.html b/contrib/sendmail/libmilter/docs/design.html
index 3cf289829d88..f2e5f11d8e07 100644
--- a/contrib/sendmail/libmilter/docs/design.html
+++ b/contrib/sendmail/libmilter/docs/design.html
@@ -1,23 +1,23 @@
-
-
-Architecture
-
-
+
+
+Architecture
+
+
-Architecture
+Architecture
-Contents
+Contents
-
- - Design Goals
-
- Implementing Filtering Policies
-
- MTA - Filter Communication
-
+
+ - Design Goals
+
- Implementing Filtering Policies
+
- MTA - Filter Communication
+
-Goals
+Goals
The Sendmail Content Management API (Milter) provides an interface for
third-party software to validate and modify messages as they pass
@@ -28,7 +28,7 @@ recipients, headers, and body. The MTA configuration file specifies
which filters are to be applied, and in what order, allowing an
administrator to combine multiple independently-developed filters.
-
+
We expect to see both vendor-supplied, configurable mail filtering
applications and a multiplicity of script-like filters designed by and
for MTA administrators. A certain degree of coding sophistication and
@@ -37,7 +37,7 @@ allows filters to exercise fine-grained control at the SMTP level.
However, as will be seen in the example, many filtering applications
can be written with relatively little protocol knowledge.
-
+
Given these expectations, the API is designed to achieve the following
goals:
@@ -47,7 +47,7 @@ goals:
(of course, they can if required, but that is a local issue);
this will simplify coding
and limit the impact of security flaws in the filter program.
-
+
Reliability.
Coding failures in a Milter process that cause that process
to hang or core-dump
@@ -59,7 +59,7 @@ goals:
The latter failure mode will generally have sendmail return
a 4xx SMTP code (although in later phases of the SMTP protocol
it may cause the mail to be queued for later processing).
-
+
Simplicity.
The API should make implementation of a new filter
no more difficult than absolutely necessary.
@@ -70,12 +70,12 @@ goals:
Provide all interfaces required
while avoiding unnecessary pedanticism.
-
+
Performance.
Simple filters should not seriously impact overall MTA performance.
-Implementing Filtering Policies
+Implementing Filtering Policies
Milter is designed to allow a server administrator to combine
third-party filters to implement a desired mail filtering policy. For
@@ -87,16 +87,16 @@ engine, then via a large-scale spam-catching service, and finally
append the desired footer if the message still met requisite criteria.
Any of these filters could be added or changed independently.
-
+
Thus the site administrator, not the filter writer, controls the
overall mail filtering environment. In particular, he/she must decide
which filters are run, in what order they are run, and how they
communicate with the MTA. These parameters, as well as the
actions to be taken if a filter becomes unavailable, are selectable
-during MTA configuration. Further
-details are available later in this document.
+during MTA configuration. Further
+details are available later in this document.
-
MTA - Filter communication
+MTA - Filter communication
Filters run as separate processes, outside of the sendmail address
space. The benefits of this are threefold:
@@ -112,36 +112,36 @@ space. The benefits of this are threefold:
the parallelism inherent in multiple processes.
-
+
Each filter may communicate with multiple MTAs at the same time over
-local or remote connections, using multiple threads of execution. Figure 1 illustrates a possible network of
+local or remote connections, using multiple threads of execution.
+Figure 1 illustrates a possible network of
communication channels between a site's filters, its MTAs, and other
MTAs on the network:
-
-
-
![](figure1.jpg)
-
Figure 1: A set of MTA's interacting with a set of filters.
-
-
+
+
+
![](figure1.jpg)
+
Figure 1: A set of MTA's interacting with a set of filters.
+
+
The Milter library (libmilter) implements the communication protocol.
It accepts connections from various MTAs, passes the relevant data to
the filter through callbacks, then makes appropriate responses based
on return codes. A filter may also send data to the MTA as a result
-of library calls. Figure 2 shows a single
+of library calls. Figure 2 shows a single
filter process processing messages from two MTAs:
-
-
-
![](figure2.jpg)
-
Figure 2: A filter handling simultaneous requests from two MTA's.
-
-
-
+
+
+
![](figure2.jpg)
+
Figure 2: A filter handling simultaneous requests from two MTA's.
+
+
+
Copyright (c) 2000, 2003 Sendmail, Inc. and its suppliers.
All rights reserved.
-
+
By using this file, you agree to the terms and conditions set
forth in the LICENSE.
-
-
-
+
+
+
diff --git a/contrib/sendmail/libmilter/docs/index.html b/contrib/sendmail/libmilter/docs/index.html
index 3c39abf478f5..517d2f6315d7 100644
--- a/contrib/sendmail/libmilter/docs/index.html
+++ b/contrib/sendmail/libmilter/docs/index.html
@@ -1,22 +1,22 @@
-
-
-Filtering Mail with Sendmail
-
-
+
+
+Filtering Mail with Sendmail
+
+
-Filtering Mail with Sendmail
+Filtering Mail with Sendmail
-Introduction
+Introduction
Sendmail's Content Management API (milter) provides third-party
@@ -26,67 +26,67 @@ content and meta-information. Filtering policies implemented by
Milter-conformant filters may then be centrally configured and
composed in an end-user's MTA configuration file.
-
+
Possible uses for filters include spam rejection, virus
filtering, and content control. In general, Milter seeks to address
site-wide filtering concerns in a scalable way. Individual users' mail
filtering needs (e.g. sorting messages by subject) are left to
-client-level programs such as Procmail.
+client-level programs such as Procmail.
This document is a technical introduction intended for those
interested in developing Milter filters. It includes:
-
-- A description of Milter's design goals.
+
+- A description of Milter's design goals.
-
- An explanation of Milter application architecture, including
+
- An explanation of Milter application architecture, including
interactions between the support library and user code, and between
filters and the MTA.
-
- A specification of the C application programming interface.
-
- An example of a simple Milter filter.
-
+ - A specification of the C application programming interface.
+
- An example of a simple Milter filter.
+
-Contents
+Contents
-
+
-
-
+
+
Copyright (c) 2000, 2001, 2003 Sendmail, Inc. and its suppliers.
All rights reserved.
-
+
By using this file, you agree to the terms and conditions set
forth in the LICENSE.
-
-
-
+
+
+
diff --git a/contrib/sendmail/libmilter/docs/installation.html b/contrib/sendmail/libmilter/docs/installation.html
index 5353ea74a6d0..07142e9c412b 100644
--- a/contrib/sendmail/libmilter/docs/installation.html
+++ b/contrib/sendmail/libmilter/docs/installation.html
@@ -1,96 +1,90 @@
-
-Installation and Configuration
-
-
+
+Installation and Configuration
+
+
-Installation
-Contents
-
+Installation
+Contents
+
-
+
To compile a filter, modify the Makefile provided with the sample program, or:
-
- - Put the include and Sendmail directories in your include path
+
+ - Put the include and Sendmail directories in your include path
(e.g. -I/path/to/include -I/path/to/sendmail).
-
- Make sure libmilter.a is in your library path, and link your
+
- Make sure libmilter.a is in your library path, and link your
application with it (e.g. "-lmilter").
-
- Compile with pthreads, either by using -pthread for gcc, or
+
- Compile with pthreads, either by using -pthread for gcc, or
linking with a pthreads support library (-lpthread).
-
+
Your compile command line will look like
-
+
cc -I/path/to/include -I/path/to/sendmail -c myfile.c
-
+
and your linking command line will look something like
-
+
cc -o myfilter [object-files] -L[library-location] -lmilter -pthread
-
+
-
+
-First, you must compile sendmail with MILTER defined.
-If you use a sendmail version older than 8.12 please see
+If you use a sendmail version older than 8.13 please see
the instructions for your version.
-To do this, add the following lines to your build
-configuration file (devtools/Site/config.site.m4)
-
-APPENDDEF(`conf_sendmail_ENVDEF', `-DMILTER')
-
-
-then type ./Build -c
in your sendmail directory.
+The default compilation options for sendmail enable support
+for milters since 8.13.
Next, you must add the desired filters to your sendmail configuration
(.mc) file.
Mail filters have three equates:
-The required S=
equate specifies the socket where
-sendmail should look for the filter; The optional F=
and
-T=
equates specify flags and timeouts, respectively. All
-equates names, equate field names, and flag values are case sensitive.
+The required S=
equate specifies the socket where
+sendmail should look for the filter; the optional F=
and
+T=
equates specify flags and timeouts, respectively.
+All equates names, equate field names, and flag values are case sensitive.
-The current flags (F=
) are:
-
-
-
-Flag | Meaning |
+The current flags (F=
) are:
+
+
+
+Flag | Meaning |
-
+
R | Reject connection if filter unavailable |
-
+
T | Temporary fail connection if filter unavailable |
If a filter is unavailable or unresponsive and no flags have been
specified, the MTA will continue normal handling of the current
-connection. The MTA will try to contact the filter again on each new
connection.
+The MTA will try to contact the filter again on each new connection.
-There are three fields inside of the T=
equate: S, R, and
-E. Note the separator between each is a ";" (semicolon), as ","
-(comma) already separates equates. The value of each field is a
-decimal number followed by a single letter designating the units ("s"
-for seconds, "m" for minutes). The fields have the following
-meanings:
-
+There are three fields inside of the T=
equate: S, R, and E.
+Note the separator between each is a ";" (semicolon), as ","
+(comma) already separates equates.
+The value of each field is a decimal number followed by a single letter
+designating the units ("s" for seconds, "m" for minutes).
+The fields have the following meanings:
+
Flag | Meaning |
C | Timeout for connecting to a filter. If set to 0, the
- system's connect() timeout will be used.
+ system's connect(2) timeout will be used.
Default: 5m |
@@ -106,27 +100,28 @@ meanings:
-
-The following sendmail.mc example specifies three filters. The first
-two rendezvous on Unix-domain sockets in the /var/run directory; the
-third uses an IP socket on port 999.
-
+
+The following sendmail.mc example specifies three filters.
+The first two rendezvous on Unix-domain sockets in the /var/run directory;
+the third uses an IP socket on port 999.
+
INPUT_MAIL_FILTER(`filter1', `S=unix:/var/run/f1.sock, F=R')
INPUT_MAIL_FILTER(`filter2', `S=unix:/var/run/f2.sock, F=T, T=S:1s;R:1s;E:5m')
INPUT_MAIL_FILTER(`filter3', `S=inet:999@localhost, T=C:2m')
define(`confINPUT_MAIL_FILTERS', `filter2,filter1,filter3')
-
+
m4 ../m4/cf.m4 myconfig.mc > myconfig.cf
-
+
By default, the filters would be run in the order declared,
i.e. "filter1, filter2, filter3"; however, since
-confINPUT_MAIL_FILTERS
is defined, the filters will be
-run "filter2, filter1, filter3". Also note that a filter can be
-defined without adding it to the input filter list by using
+confINPUT_MAIL_FILTERS
is defined, the filters will be
+run "filter2, filter1, filter3".
+Also note that a filter can be defined
+without adding it to the input filter list by using
MAIL_FILTER() instead of INPUT_MAIL_FILTER().
-
+
The above macros will result in the following lines being added to
your .cf file:
@@ -136,34 +131,35 @@ your .cf file:
O InputMailFilters=filter2,filter1,filter3
-
-Finally, the sendmail macros accessible via smfi_getsymval can be configured by
+
+Finally, the sendmail macros accessible via
+smfi_getsymval can be configured by
defining the following m4 variables (or cf options):
-
-
-In .mc file | In .cf file |
-Default Value |
-
-confMILTER_MACROS_CONNECT | Milter.macros.connect |
-j, _, {daemon_name}, {if_name}, {if_addr} |
-confMILTER_MACROS_HELO | Milter.macros.helo |
-{tls_version}, {cipher}, {cipher_bits}, {cert_subject},
-{cert_issuer} |
-confMILTER_MACROS_ENVFROM | Milter.macros.envfrom |
-i, {auth_type}, {auth_authen}, {auth_ssf}, {auth_author},
-{mail_mailer}, {mail_host}, {mail_addr} |
-confMILTER_MACROS_ENVRCPT | Milter.macros.envrcpt |
-{rcpt_mailer}, {rcpt_host}, {rcpt_addr} |
-
+
+
+In .mc file | In .cf file |
+Default Value |
+
+confMILTER_MACROS_CONNECT | Milter.macros.connect |
+j, _, {daemon_name}, {if_name}, {if_addr} |
+confMILTER_MACROS_HELO | Milter.macros.helo |
+{tls_version}, {cipher}, {cipher_bits}, {cert_subject},
+{cert_issuer} |
+confMILTER_MACROS_ENVFROM | Milter.macros.envfrom |
+i, {auth_type}, {auth_authen}, {auth_ssf}, {auth_author},
+{mail_mailer}, {mail_host}, {mail_addr} |
+confMILTER_MACROS_ENVRCPT | Milter.macros.envrcpt |
+{rcpt_mailer}, {rcpt_host}, {rcpt_addr} |
+
For information about available macros and their meanings, please
consult the sendmail documentation.
-
-
-Copyright (c) 2000-2003 Sendmail, Inc. and its suppliers.
+
+
+Copyright (c) 2000-2003, 2006 Sendmail, Inc. and its suppliers.
All rights reserved.
-
+
By using this file, you agree to the terms and conditions set
forth in the LICENSE.
-
-
+
+
+
diff --git a/contrib/sendmail/libmilter/docs/other.html b/contrib/sendmail/libmilter/docs/other.html
index 22ef8229adbe..c33b5368d0bc 100644
--- a/contrib/sendmail/libmilter/docs/other.html
+++ b/contrib/sendmail/libmilter/docs/other.html
@@ -1,18 +1,18 @@
-
-Other Resources
-
-
+
+Other Resources
+
+
FAQ? Mailing list? More sample filters?
-
-
+
+
Copyright (c) 2000, 2003 Sendmail, Inc. and its suppliers.
All rights reserved.
-
+
By using this file, you agree to the terms and conditions set
forth in the LICENSE.
-
-
-
+
+
+
diff --git a/contrib/sendmail/libmilter/docs/overview.html b/contrib/sendmail/libmilter/docs/overview.html
index f06fbdf22f87..b7e80dfdbed7 100644
--- a/contrib/sendmail/libmilter/docs/overview.html
+++ b/contrib/sendmail/libmilter/docs/overview.html
@@ -1,194 +1,215 @@
-
-
-Technical Overview
-
-
+
+
+Technical Overview
+
+
-Technical Overview
+Technical Overview
-Contents
+Contents
-
- - Initialization
-
- Control flow
-
- Multithreading
-
- Resource Management
-
- Signal Handling
-
+
-Initialization
+
-In addition to its own initialization, libmilter expects a filter to initialize several parameters before calling smfi_main:
-
+
+If the filter fails to initialize libmilter,
+or if one or more of the parameters it has passed are invalid,
+a subsequent call to smfi_main will fail.
-
Control flow
+
-
+
The following pseudocode describes the filtering process from the
-perspective of a set of N
MTA's, each corresponding to a
-connection. Callbacks are shown beside the processing stages in which
-they are invoked; if no callbacks are defined for a particular stage,
-that stage may be bypassed. Though it is not shown, processing may be
-aborted at any time during a message, in which case the xxfi_abort callback is invoked and control
-returns to MESSAGE
.
-
-
+perspective of a set of N
MTA's,
+each corresponding to a connection.
+Callbacks are shown beside the processing stages in which they are invoked;
+if no callbacks are defined for a particular stage,
+that stage may be bypassed.
+Though it is not shown,
+processing may be aborted at any time during a message,
+in which case the
+xxfi_abort callback is invoked and control
+returns to MESSAGE
.
+
+
For each of N connections
{
For each filter
- process connection/helo (xxfi_connect, xxfi_helo)
+ process connection/helo (xxfi_connect, xxfi_helo)
MESSAGE:For each message in this connection (sequentially)
{
For each filter
- process sender (xxfi_envfrom)
+ process sender (xxfi_envfrom)
For each recipient
{
For each filter
- process recipient (xxfi_envrcpt)
+ process recipient (xxfi_envrcpt)
}
For each filter
{
+ process DATA (xxfi_data)
For each header
- process header (xxfi_header)
- process end of headers (xxfi_eoh)
+ process header (xxfi_header)
+ process end of headers (xxfi_eoh)
For each body block
- process this body block (xxfi_body)
- process end of message (xxfi_eom)
+ process this body block (xxfi_body)
+ process end of message (xxfi_eom)
}
}
For each filter
- process end of connection (xxfi_close)
+ process end of connection (xxfi_close)
}
-
+
Note: Filters are contacted in order defined in config file.
To write a filter, a vendor supplies callbacks to process relevant
-parts of a message transaction. The library then controls all
-sequencing, threading, and protocol exchange with the MTA. Figure 3 outlines control flow for a filter
+parts of a message transaction.
+The library then controls all sequencing, threading,
+and protocol exchange with the MTA.
+Figure 3 outlines control flow for a filter
process, showing where different callbacks are invoked.
-
-
-
-SMTP Commands | Milter Callbacks |
-(open SMTP connection) | xxfi_connect |
-HELO ... | xxfi_helo |
-MAIL From: ... | xxfi_envfrom |
-RCPT To: ... | xxfi_envrcpt |
-[more RCPTs] | [xxfi_envrcpt] |
-DATA | |
-Header: ... | xxfi_header |
-[more headers] | [xxfi_header] |
- | xxfi_eoh |
-body... | xxfi_body |
-[more body...] | [xxfi_body] |
-. | xxfi_eom |
-QUIT | xxfi_close |
-(close SMTP connection) | |
-
-
Figure 3: Milter callbacks related to an SMTP transaction.
-
-
+
+
+
+
+SMTP Commands | Milter Callbacks |
+(open SMTP connection) | xxfi_connect |
+HELO ... | xxfi_helo |
+MAIL From: ... | xxfi_envfrom |
+RCPT To: ... | xxfi_envrcpt |
+[more RCPTs] | [xxfi_envrcpt] |
+DATA | xxfi_data |
+Header: ... | xxfi_header |
+[more headers] | [xxfi_header] |
+ | xxfi_eoh |
+body... | xxfi_body |
+[more body...] | [xxfi_body] |
+. | xxfi_eom |
+QUIT | xxfi_close |
+(close SMTP connection) | |
+
+
Figure 3: Milter callbacks related to an SMTP transaction.
+
+
+
Note that although only a single message is shown above, multiple
-messages may be sent in a single connection. Note also that a message
-and/or connection may be aborted by either the remote host or the MTA
-at any point during the SMTP transaction. If this occurs during a
-message (between the MAIL command and the final "."), the filter's xxfi_abort routine will be called. xxfi_close is called any time the
+messages may be sent in a single connection.
+Note also that a message or connection may be aborted by
+either the remote host or the MTA
+at any point during the SMTP transaction.
+f this occurs during a message (between the MAIL command and the final "."),
+the filter's
+xxfi_abort routine will be called.
+xxfi_close is called any time the
connection closes.
-
Multithreading
+
-
+
A single filter process may handle any number of connections
-simultaneously. All filtering callbacks must therefore be reentrant,
+simultaneously.
+All filtering callbacks must therefore be reentrant,
and use some appropriate external synchronization methods to access
-global data. Furthermore, since there is not a one-to-one
-correspondence between threads and connections (N connections mapped
-onto M threads, M <= N), connection-specific data must be accessed
-through the handles provided by the Milter library. The programmer
-cannot rely on library-supplied thread-specific data blocks
-(e.g. pthread_getspecific()) to store connection-specific data. See
-the API documentation for smfi_setpriv and smfi_getpriv for details.
+global data.
+Furthermore, since there is not a one-to-one correspondence
+between threads and connections
+(N connections mapped onto M threads, M <= N),
+connection-specific data must be accessed
+through the handles provided by the Milter library.
+The programmer cannot rely on library-supplied thread-specific data blocks
+(e.g., pthread_getspecific(3)
) to store connection-specific data.
+See the API documentation for
+smfi_setpriv and
+smfi_getpriv for details.
-
Resource management
+
-Since filters are likely to be long-lived, and to handle many
-connections, proper deallocation of per-connection resources is
-important. The lifetime of a connection is bracketed by calls to the
-callbacks xxfi_connect and xxfi_close. Therefore connection-specific
-resources (accessed via smfi_getpriv
-and smfi_setpriv) may be allocated in
-xxfi_connect, and should be freed in
-xxfi_close. For further information see
-the discussion of message- versus
-connection-oriented routines. In particular, note that there is only
-one connection-specific data pointer per connection.
-
+Since filters are likely to be long-lived,
+and to handle many connections,
+proper deallocation of per-connection resources is important.
+The lifetime of a connection is bracketed by calls to the
+callbacks xxfi_connect and
+xxfi_close.
+Therefore connection-specific
+resources (accessed via smfi_getpriv
+and smfi_setpriv) may be allocated in
+xxfi_connect,
+and should be freed in
+xxfi_close.
+For further information see
+the discussion of message- versus
+connection-oriented routines.
+In particular,
+note that there is only one connection-specific data pointer per connection.
+
-Each message is bracketed by calls to xxfi_envfrom and xxfi_eom (or xxfi_abort), implying that message-specific
-resources can be allocated and reclaimed in these routines. Since the
-messages in a connection are processed sequentially by each filter,
+Each message is bracketed by calls to
+xxfi_envfrom and
+xxfi_eom (or
+xxfi_abort),
+implying that message-specific resources can be allocated
+and reclaimed in these routines.
+Since the messages in a connection are processed sequentially by each filter,
there will be only one active message associated with a given
-connection and filter (and connection-private data block). These
-resources must still be accessed through smfi_getpriv and smfi_setpriv, and must be reclaimed
-in xxfi_abort.
+connection and filter (and connection-private data block).
+These resources must still be accessed through
+smfi_getpriv and
+smfi_setpriv,
+and must be reclaimed in
+xxfi_abort.
-
Signal Handling
+
-libmilter takes care of signal handling, the filters are
-not influenced directly by signals.
+libmilter takes care of signal handling,
+the filters are not influenced directly by signals.
There are basically two types of signal handlers:
-
-- Stop: no new connections from the MTA will be accepted,
+
+- Stop: no new connections from the MTA will be accepted,
but existing connections are allowed to continue.
-
- Abort: all filters will be stopped as soon as the next
+
- Abort: all filters will be stopped as soon as the next
communication with the MTA happens.
-
+
-Filters are not terminated asynchronously (except by
-signals that can't be caught).
+Filters are not terminated asynchronously
+(except by signals that can't be caught).
In the case of Abort the
-xxfi_abort callback is invoked.
+xxfi_abort callback is invoked.
-
-
-Copyright (c) 2000, 2001, 2003 Sendmail, Inc. and its suppliers.
+
+
+Copyright (c) 2000, 2001, 2003, 2006 Sendmail, Inc. and its suppliers.
All rights reserved.
-
+
By using this file, you agree to the terms and conditions set
forth in the LICENSE.
-
-
-
+
+
+
diff --git a/contrib/sendmail/libmilter/docs/sample.html b/contrib/sendmail/libmilter/docs/sample.html
index 29ee67ab7c1d..48e25c597969 100644
--- a/contrib/sendmail/libmilter/docs/sample.html
+++ b/contrib/sendmail/libmilter/docs/sample.html
@@ -1,26 +1,26 @@
-
-A Sample Filter
-
+
+A Sample Filter
+
-A Sample Filter
+A Sample Filter
The following sample logs each message to a separate temporary file,
-adds a recipient given with the -a flag, and rejects a disallowed
-recipient address given with the -r flag. It recognizes the following
-options:
-
-
-
--p port | The port through which the MTA will connect to the filter. |
--t sec | The timeout value. |
--r addr | A recipient to reject. |
--a addr | A recipient to add. |
-
-
-
-
+adds a recipient given with the -a flag,
+and rejects a disallowed recipient address given with the -r flag.
+It recognizes the following options:
+
+
+
+-p port | The port through which the MTA will connect to the filter. |
+-t sec | The timeout value. |
+-r addr | A recipient to reject. |
+-a addr | A recipient to add. |
+
+
+
+
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
@@ -47,7 +47,7 @@ struct mlfiPriv
FILE *mlfi_fp;
};
-#define MLFIPRIV ((struct mlfiPriv *) smfi_getpriv(ctx))
+#define MLFIPRIV ((struct mlfiPriv *) smfi_getpriv(ctx))
extern sfsistat mlfi_cleanup(SMFICTX *, bool);
@@ -56,7 +56,7 @@ char *add = NULL;
char *reject = NULL;
sfsistat
-mlfi_connect(ctx, hostname, hostaddr)
+mlfi_connect(ctx, hostname, hostaddr)
SMFICTX *ctx;
char *hostname;
_SOCK_ADDR *hostaddr;
@@ -74,9 +74,9 @@ sfsistat
memset(priv, '\0', sizeof *priv);
/* save the private data */
- smfi_setpriv(ctx, priv);
+ smfi_setpriv(ctx, priv);
- ident = smfi_getsymval(ctx, "_");
+ ident = smfi_getsymval(ctx, "_");
if (ident == NULL)
ident = "???";
if ((priv->mlfi_connectfrom = strdup(ident)) == NULL)
@@ -90,7 +90,7 @@ sfsistat
}
sfsistat
-mlfi_helo(ctx, helohost)
+mlfi_helo(ctx, helohost)
SMFICTX *ctx;
char *helohost;
{
@@ -99,7 +99,7 @@ sfsistat
char *buf;
struct mlfiPriv *priv = MLFIPRIV;
- tls = smfi_getsymval(ctx, "{tls_version}");
+ tls = smfi_getsymval(ctx, "{tls_version}");
if (tls == NULL)
tls = "No TLS";
if (helohost == NULL)
@@ -120,14 +120,14 @@ sfsistat
}
sfsistat
-mlfi_envfrom(ctx, argv)
+mlfi_envfrom(ctx, argv)
SMFICTX *ctx;
char **argv;
{
int fd = -1;
int argc = 0;
struct mlfiPriv *priv = MLFIPRIV;
- char *mailaddr = smfi_getsymval(ctx, "{mail_addr}");
+ char *mailaddr = smfi_getsymval(ctx, "{mail_addr}");
/* open a file to store this message */
if ((priv->mlfi_fname = strdup("/tmp/msg.XXXXXX")) == NULL)
@@ -174,12 +174,12 @@ sfsistat
}
sfsistat
-mlfi_envrcpt(ctx, argv)
+mlfi_envrcpt(ctx, argv)
SMFICTX *ctx;
char **argv;
{
struct mlfiPriv *priv = MLFIPRIV;
- char *rcptaddr = smfi_getsymval(ctx, "{rcpt_addr}");
+ char *rcptaddr = smfi_getsymval(ctx, "{rcpt_addr}");
int argc = 0;
/* count the arguments */
@@ -211,7 +211,7 @@ sfsistat
}
sfsistat
-mlfi_header(ctx, headerf, headerv)
+mlfi_header(ctx, headerf, headerv)
SMFICTX *ctx;
char *headerf;
unsigned char *headerv;
@@ -228,7 +228,7 @@ sfsistat
}
sfsistat
-mlfi_eoh(ctx)
+mlfi_eoh(ctx)
SMFICTX *ctx;
{
/* output the blank line between the header and the body */
@@ -243,7 +243,7 @@ sfsistat
}
sfsistat
-mlfi_body(ctx, bodyp, bodylen)
+mlfi_body(ctx, bodyp, bodylen)
SMFICTX *ctx;
unsigned char *bodyp;
size_t bodylen;
@@ -265,19 +265,19 @@ sfsistat
}
sfsistat
-mlfi_eom(ctx)
+mlfi_eom(ctx)
SMFICTX *ctx;
{
bool ok = TRUE;
/* change recipients, if requested */
if (add != NULL)
- ok = (smfi_addrcpt(ctx, add) == MI_SUCCESS);
+ ok = (smfi_addrcpt(ctx, add) == MI_SUCCESS);
return mlfi_cleanup(ctx, ok);
}
sfsistat
-mlfi_abort(ctx)
+mlfi_abort(ctx)
SMFICTX *ctx;
{
return mlfi_cleanup(ctx, FALSE);
@@ -317,7 +317,7 @@ mlfi_cleanup(ctx, ok)
else
p++;
snprintf(hbuf, sizeof hbuf, "%s@%s", p, host);
- if (smfi_addheader(ctx, "X-Archived", hbuf) != MI_SUCCESS)
+ if (smfi_addheader(ctx, "X-Archived", hbuf) != MI_SUCCESS)
{
/* failed; we have to wait until later */
fprintf(stderr,
@@ -346,7 +346,7 @@ mlfi_cleanup(ctx, ok)
}
sfsistat
-mlfi_close(ctx)
+mlfi_close(ctx)
SMFICTX *ctx;
{
struct mlfiPriv *priv = MLFIPRIV;
@@ -358,26 +358,59 @@ sfsistat
if (priv->mlfi_helofrom != NULL)
free(priv->mlfi_helofrom);
free(priv);
- smfi_setpriv(ctx, NULL);
+ smfi_setpriv(ctx, NULL);
return SMFIS_CONTINUE;
}
+sfsistat
+mlfi_unknown(ctx, cmd)
+ SMFICTX *ctx;
+ char *cmd;
+{
+ return SMFIS_CONTINUE;
+}
+
+sfsistat
+mlfi_data(ctx)
+ SMFICTX *ctx;
+{
+ return SMFIS_CONTINUE;
+}
+
+sfsistat
+mlfi_negotiate(ctx, f0, f1, f2, f3, pf0, pf1, pf2, pf3)
+ SMFICTX *ctx;
+ unsigned long f0;
+ unsigned long f1;
+ unsigned long f2;
+ unsigned long f3;
+ unsigned long *pf0;
+ unsigned long *pf1;
+ unsigned long *pf2;
+ unsigned long *pf3;
+{
+ return SMFIS_ALL_OPTS;
+}
+
struct smfiDesc smfilter =
{
"SampleFilter", /* filter name */
SMFI_VERSION, /* version code -- do not change */
SMFIF_ADDHDRS|SMFIF_ADDRCPT,
/* flags */
- mlfi_connect, /* connection info filter */
- mlfi_helo, /* SMTP HELO command filter */
- mlfi_envfrom, /* envelope sender filter */
- mlfi_envrcpt, /* envelope recipient filter */
- mlfi_header, /* header filter */
- mlfi_eoh, /* end of header */
- mlfi_body, /* body block filter */
- mlfi_eom, /* end of message */
- mlfi_abort, /* message aborted */
- mlfi_close, /* connection cleanup */
+ mlfi_connect, /* connection info filter */
+ mlfi_helo, /* SMTP HELO command filter */
+ mlfi_envfrom, /* envelope sender filter */
+ mlfi_envrcpt, /* envelope recipient filter */
+ mlfi_header, /* header filter */
+ mlfi_eoh, /* end of header */
+ mlfi_body, /* body block filter */
+ mlfi_eom, /* end of message */
+ mlfi_abort, /* message aborted */
+ mlfi_close, /* connection cleanup */
+ mlfi_unknown, /* unknown SMTP commands */
+ mlfi_data, /* DATA command */
+ mlfi_negotiate /* Once, at the start of each SMTP connection */
};
static void
@@ -411,7 +444,7 @@ main(argc, argv)
optarg);
exit(EX_USAGE);
}
- if (smfi_setconn(optarg) == MI_FAILURE)
+ if (smfi_setconn(optarg) == MI_FAILURE)
{
(void) fprintf(stderr,
"smfi_setconn failed\n");
@@ -438,7 +471,7 @@ main(argc, argv)
optarg);
exit(EX_USAGE);
}
- if (smfi_settimeout(atoi(optarg)) == MI_FAILURE)
+ if (smfi_settimeout(atoi(optarg)) == MI_FAILURE)
{
(void) fprintf(stderr,
"smfi_settimeout failed\n");
@@ -481,24 +514,24 @@ main(argc, argv)
usage(argv[0]);
exit(EX_USAGE);
}
- if (smfi_register(smfilter) == MI_FAILURE)
+ if (smfi_register(smfilter) == MI_FAILURE)
{
fprintf(stderr, "smfi_register failed\n");
exit(EX_UNAVAILABLE);
}
- return smfi_main();
+ return smfi_main();
}
/* eof */
-
-
-
-Copyright (c) 2000-2004 Sendmail, Inc. and its suppliers.
+
+
+
+Copyright (c) 2000-2004, 2006 Sendmail, Inc. and its suppliers.
All rights reserved.
-
+
By using this file, you agree to the terms and conditions set
forth in the LICENSE.
-
-
-
+
+
+
diff --git a/contrib/sendmail/libmilter/docs/smfi_addheader.html b/contrib/sendmail/libmilter/docs/smfi_addheader.html
index e1fe69d648c8..d068f9fdb934 100644
--- a/contrib/sendmail/libmilter/docs/smfi_addheader.html
+++ b/contrib/sendmail/libmilter/docs/smfi_addheader.html
@@ -1,98 +1,106 @@
-
-smfi_addheader
-
+
+smfi_addheader
+
-smfi_addheader
+smfi_addheader
-
+
-SYNOPSIS |
-
+SYNOPSIS |
+
#include <libmilter/mfapi.h>
int smfi_addheader(
SMFICTX *ctx,
char *headerf,
char *headerv
);
-
+
Add a header to the current message.
- |
+ |
-DESCRIPTION |
-
-
-Called When |
-Called only from xxfi_eom. |
-
-
-Effects |
-Adds a header to the current message. |
-
-
+ |
---|
DESCRIPTION |
+
+
+Called When |
+Called only from xxfi_eom. |
+
+
+Effects |
+Adds a header to the current message. |
+
+
- |
---|
ARGUMENTS |
-
- Argument | Description |
- ctx |
- Opaque context structure.
- |
- headerf |
- The header name, a non-NULL, null-terminated string.
- |
- headerv |
- The header value to be added, a non-NULL, null-terminated string. This may be the empty string.
- |
-
- |
+ARGUMENTS |
+
+ Argument | Description |
+ ctx |
+ Opaque context structure.
+ |
+ headerf |
+ The header name, a non-NULL, null-terminated string.
+ |
+ headerv |
+ The header value to be added, a non-NULL, null-terminated string.
+ This may be the empty string.
+ |
+
+ |
-
-RETURN VALUES |
+
+RETURN VALUES |
-smfi_addheader returns MI_FAILURE if:
-- headerf or headerv is NULL.
-
- Adding headers in the current connection state is invalid.
-
- Memory allocation fails.
-
- A network error occurs.
-
- SMFIF_ADDHDRS was not set when smfi_register was called.
-
+ | smfi_addheader returns MI_FAILURE if:
+- headerf or headerv is NULL.
+
- Adding headers in the current connection state is invalid.
+
- Memory allocation fails.
+
- A network error occurs.
+
- SMFIF_ADDHDRS was not set when smfi_register was called.
+
Otherwise, it returns MI_SUCCESS.
- |
-
+
+
-
-NOTES |
-
-- smfi_addheader does not change a message's existing headers.
-To change a header's current value, use smfi_chgheader.
-
- A filter which calls smfi_addheader must have set the SMFIF_ADDHDRS flag in the smfiDesc_str passed to smfi_register.
-
- For smfi_addheader, filter order is important. Later filters will see the header changes made by earlier ones.
-
- Neither the name nor the value of the header is checked for
- standards compliance. However, each line of the header must be under
- 2048 characters and should be under 998 characters. If longer headers
- are needed, make them multi-line. To make a multi-line header, insert
- a line feed (ASCII 0x0a, or \n in C) followed by at least
- one whitespace character such as a space (ASCII 0x20) or tab (ASCII 0x09,
- or \t in C). The line feed should NOT be preceded by a
- carriage return (ASCII 0x0d); the MTA will add this automatically.
- It is the filter writer's responsibility to ensure that no standards
- are violated.
-
- |
-
+
+NOTES |
+
+- smfi_addheader does not change a message's existing headers.
+To change a header's current value, use
+smfi_chgheader.
+
- A filter which calls smfi_addheader must have set the SMFIF_ADDHDRS
+ flag in the smfiDesc_str passed to
+ smfi_register.
+
- For smfi_addheader, filter order is important.
+ Later filters will see the header changes made by earlier ones.
+
- Neither the name nor the value of the header is checked for
+ standards compliance.
+ However, each line of the header must be under 2048 characters
+ and should be under 998 characters.
+ If longer headers are needed, make them multi-line.
+ To make a multi-line header,
+ insert a line feed (ASCII 0x0a, or \n in C)
+ followed by at least one whitespace character
+ such as a space (ASCII 0x20) or tab (ASCII 0x09, or \t in C).
+ The line feed should NOT be preceded by a carriage return (ASCII 0x0d);
+ the MTA will add this automatically.
+ It is the filter writer's responsibility to ensure that no standards
+ are violated.
+
- The MTA adds a leading space to an added header value.
+
+ |
+
-
-EXAMPLE |
+
+EXAMPLE |
-
-
+
+
int ret;
SMFICTX *ctx;
@@ -100,19 +108,19 @@ href="smfi_chgheader.html">smfi_chgheader.
ret = smfi_addheader(ctx, "Content-Type",
"multipart/mixed;\n\tboundary=\"foobar\"");
-
- |
- |
+
+
+
-
+
-
-
-Copyright (c) 2000-2003 Sendmail, Inc. and its suppliers.
+
+
+Copyright (c) 2000-2003, 2006 Sendmail, Inc. and its suppliers.
All rights reserved.
-
+
By using this file, you agree to the terms and conditions set
forth in the LICENSE.
-
-
-
+
+
+
diff --git a/contrib/sendmail/libmilter/docs/smfi_addrcpt.html b/contrib/sendmail/libmilter/docs/smfi_addrcpt.html
index 05770bf28d11..cf997e570d07 100644
--- a/contrib/sendmail/libmilter/docs/smfi_addrcpt.html
+++ b/contrib/sendmail/libmilter/docs/smfi_addrcpt.html
@@ -1,83 +1,83 @@
-
-smfi_addrcpt
-
+
+smfi_addrcpt
+
-smfi_addrcpt
+smfi_addrcpt
-
+
-SYNOPSIS |
-
+SYNOPSIS |
+
#include <libmilter/mfapi.h>
int smfi_addrcpt(
SMFICTX *ctx,
char *rcpt
);
-
+
Add a recipient for the current message.
- |
+ |
-DESCRIPTION |
-
-
-Called When |
-Called only from xxfi_eom. |
-
-
-Effects |
-Add a recipient to the message envelope. |
-
-
+ |
---|
DESCRIPTION |
+
+
+Called When |
+Called only from xxfi_eom. |
+
+
+Effects |
+Add a recipient to the message envelope. |
+
+
- |
---|
ARGUMENTS |
-
- Argument | Description |
- ctx |
- Opaque context structure.
- |
- rcpt |
- The new recipient's address.
- |
-
- |
+ARGUMENTS |
+
+ Argument | Description |
+ ctx |
+ Opaque context structure.
+ |
+ rcpt |
+ The new recipient's address.
+ |
+
+ |
-
-RETURN VALUES |
+
+RETURN VALUES |
-smfi_addrcpt will fail and return MI_FAILURE if:
-- rcpt is NULL.
-
- Adding recipients in the current connection state is invalid.
-
- A network error occurs.
-
- SMFIF_ADDRCPT was not set when smfi_register was called.
-
+ | smfi_addrcpt will fail and return MI_FAILURE if:
+- rcpt is NULL.
+
- Adding recipients in the current connection state is invalid.
+
- A network error occurs.
+
- SMFIF_ADDRCPT was not set when smfi_register was called.
+
Otherwise, it will return MI_SUCCESS.
- |
-
+
+
-
-NOTES |
-
+ |
+NOTES |
+
A filter which calls smfi_addrcpt must have set the SMFIF_ADDRCPT flag
in the smfiDesc_str passed to
-smfi_register.
- |
-
+smfi_register.
+
+
-
+
-
-
+
+
Copyright (c) 2000, 2003 Sendmail, Inc. and its suppliers.
All rights reserved.
-
+
By using this file, you agree to the terms and conditions set
forth in the LICENSE.
-
-
-
+
+
+
diff --git a/contrib/sendmail/libmilter/docs/smfi_addrcpt_par.html b/contrib/sendmail/libmilter/docs/smfi_addrcpt_par.html
new file mode 100644
index 000000000000..776b02ceab6a
--- /dev/null
+++ b/contrib/sendmail/libmilter/docs/smfi_addrcpt_par.html
@@ -0,0 +1,88 @@
+
+smfi_addrcpt_par
+
+
+smfi_addrcpt_par
+
+
+
+SYNOPSIS |
+
+#include <libmilter/mfapi.h>
+int smfi_addrcpt_par(
+ SMFICTX *ctx,
+ char *rcpt,
+ char *args
+);
+
+Add a recipient for the current message including ESMTP arguments.
+ |
+
+
+DESCRIPTION |
+
+
+Called When |
+Called only from xxfi_eom. |
+
+
+Effects |
+Add a recipient to the message envelope. |
+
+
+
+
+ |
---|
ARGUMENTS |
+
+ Argument | Description |
+ ctx |
+ Opaque context structure.
+ |
+ rcpt |
+ The new recipient's address.
+ |
+ args |
+ The new recipient's ESMTP parameters.
+ |
+
+ |
+
+
+
+RETURN VALUES |
+
+smfi_addrcpt will fail and return MI_FAILURE if:
+- rcpt is NULL.
+
- Adding recipients in the current connection state is invalid.
+
- A network error occurs.
+
- SMFIF_ADDRCPT_PAR was not set when
+ smfi_register was called.
+
+Otherwise, it will return MI_SUCCESS.
+ |
+
+
+
+
+NOTES |
+
+A filter which calls smfi_addrcpt must have set the SMFIF_ADDRCPT_PAR flag
+in the smfiDesc_str passed to
+smfi_register.
+ |
+
+
+
+
+
+
+Copyright (c) 2006 Sendmail, Inc. and its suppliers.
+All rights reserved.
+
+By using this file, you agree to the terms and conditions set
+forth in the LICENSE.
+
+
+
diff --git a/contrib/sendmail/libmilter/docs/smfi_chgfrom.html b/contrib/sendmail/libmilter/docs/smfi_chgfrom.html
new file mode 100644
index 000000000000..e8249e0f0eb8
--- /dev/null
+++ b/contrib/sendmail/libmilter/docs/smfi_chgfrom.html
@@ -0,0 +1,94 @@
+
+smfi_chgfrom
+
+
+smfi_chgfrom
+
+
+
+SYNOPSIS |
+
+#include <libmilter/mfapi.h>
+int smfi_chgfrom(
+ SMFICTX *ctx,
+ const char *mail,
+ char *args
+);
+
+Change the envelope sender (MAIL From) of the current message.
+ |
+
+
+DESCRIPTION |
+
+
+Called When |
+Called only from xxfi_eom. |
+
+
+Effects |
+Change the envelope sender (MAIL From) of the current message. |
+
+
+
+
+ |
---|
ARGUMENTS |
+
+ Argument | Description |
+ ctx |
+ Opaque context structure.
+ |
+ mail |
+ The new sender address.
+ |
+ args |
+ ESMTP arguments.
+ |
+
+ |
+
+
+
+RETURN VALUES |
+
+smfi_chgfrom will fail and return MI_FAILURE if:
+- mail is NULL.
+
- Changing the sender in the current connection state is invalid.
+
- A network error occurs.
+
- SMFIF_CHGFROM was not set when smfi_register was called.
+
+Otherwise, it will return MI_SUCCESS.
+ |
+
+
+
+
+NOTES |
+
+A filter which calls smfi_chgfrom must have set the SMFIF_CHGFROM flag
+in the smfiDesc_str passed to
+smfi_register.
+
+Even though all ESMTP arguments could be set via this call,
+it does not make sense to do so for many of them,
+e.g., SIZE and BODY.
+Setting those may cause problems, proper care must be taken.
+Moreover, there is no feedback from the MTA to the milter
+whether the call was successful.
+ |
+
+
+
+
+
+
+Copyright (c) 2006 Sendmail, Inc. and its suppliers.
+All rights reserved.
+
+By using this file, you agree to the terms and conditions set
+forth in the LICENSE.
+
+
+
diff --git a/contrib/sendmail/libmilter/docs/smfi_chgheader.html b/contrib/sendmail/libmilter/docs/smfi_chgheader.html
index 5c7e50794945..0701a3671aaf 100644
--- a/contrib/sendmail/libmilter/docs/smfi_chgheader.html
+++ b/contrib/sendmail/libmilter/docs/smfi_chgheader.html
@@ -1,15 +1,15 @@
-
-smfi_chgheader
-
+
+smfi_chgheader
+
-smfi_chgheader
+smfi_chgheader
-
+
-SYNOPSIS |
-
+SYNOPSIS |
+
#include <libmilter/mfapi.h>
int smfi_chgheader(
SMFICTX *ctx,
@@ -17,84 +17,84 @@ int smfi_chgheader(
mi_int32 hdridx,
char *headerv
);
-
+
Change or delete a message header.
- |
+ |
-DESCRIPTION |
-
-
-Called When |
-Called only from xxfi_eom. |
-
-
-Effects |
-Changes a header's value for the current message. |
-
-
+ |
---|
DESCRIPTION |
+
+
+Called When |
+Called only from xxfi_eom. |
+
+
+Effects |
+Changes a header's value for the current message. |
+
+
- |
---|
ARGUMENTS |
-
- Argument | Description |
- ctx |
- Opaque context structure.
- |
- headerf |
- The header name, a non-NULL, null-terminated string.
- |
- hdridx |
- Header index value (1-based). A hdridx value of 1 will modify the first occurrence of a header named headerf. If hdridx is greater than the number of times headerf appears, a new copy of headerf will be added.
- |
- headerv |
- The new value of the given header. headerv == NULL implies that the header should be deleted.
- |
-
- |
+ARGUMENTS |
+
+ Argument | Description |
+ ctx |
+ Opaque context structure.
+ |
+ headerf |
+ The header name, a non-NULL, null-terminated string.
+ |
+ hdridx |
+ Header index value (1-based). A hdridx value of 1 will modify the first occurrence of a header named headerf. If hdridx is greater than the number of times headerf appears, a new copy of headerf will be added.
+ |
+ headerv |
+ The new value of the given header. headerv == NULL implies that the header should be deleted.
+ |
+
+ |
-
-RETURN VALUES |
+
+RETURN VALUES |
-
+ |
smfi_chgheader will return MI_FAILURE if
-- headerf is NULL
-
- Modifying headers in the current connection state is invalid.
-
- Memory allocation fails.
-
- A network error occurs.
-
- SMFIF_CHGHDRS was not set when smfi_register was called.
-
+- headerf is NULL
+
- Modifying headers in the current connection state is invalid.
+
- Memory allocation fails.
+
- A network error occurs.
+
- SMFIF_CHGHDRS was not set when smfi_register was called.
+
Otherwise, it returns MI_SUCCESS.
- |
+
-
-NOTES |
-
-- While smfi_chgheader may be used to add new headers, it is more efficient and far safer to use smfi_addheader.
-
- A filter which calls smfi_chgheader must have set the SMFIF_CHGHDRS flag in the smfiDesc_str passed to smfi_register.
-
- For smfi_chgheader, filter order is important. Later filters will see the header changes made by earlier ones.
-
- Neither the name nor the value of the header is checked for
+
+NOTES |
+
+- While smfi_chgheader may be used to add new headers, it is more efficient and far safer to use smfi_addheader.
+
- A filter which calls smfi_chgheader must have set the SMFIF_CHGHDRS flag in the smfiDesc_str passed to smfi_register.
+
- For smfi_chgheader, filter order is important. Later filters will see the header changes made by earlier ones.
+
- Neither the name nor the value of the header is checked for
standards compliance. However, each line of the header must be under
2048 characters and should be under 998 characters. If longer headers
are needed, make them multi-line. To make a multi-line header, insert
- a line feed (ASCII 0x0a, or \n in C) followed by at least
+ a line feed (ASCII 0x0a, or \n in C) followed by at least
one whitespace character such as a space (ASCII 0x20) or tab (ASCII 0x09,
- or \t in C). The line feed should NOT be preceded by a
+ or \t in C). The line feed should NOT be preceded by a
carriage return (ASCII 0x0d); the MTA will add this automatically.
- It is the filter writer's responsibility to ensure that no standards
- are violated.
-
- |
-
+ It is the filter writer's responsibility to ensure that no standards
+ are violated.
+
+ |
+
-
-EXAMPLE |
+
+EXAMPLE |
-
-
+
+
int ret;
SMFICTX *ctx;
@@ -102,19 +102,19 @@ Otherwise, it returns MI_SUCCESS.
ret = smfi_chgheader(ctx, "Content-Type", 1,
"multipart/mixed;\n\tboundary=\"foobar\"");
-
- |
- |
+
+
+
-
+
-
-
+
+
Copyright (c) 2000-2003 Sendmail, Inc. and its suppliers.
All rights reserved.
-
+
By using this file, you agree to the terms and conditions set
forth in the LICENSE.
-
-
-
+
+
+
diff --git a/contrib/sendmail/libmilter/docs/smfi_delrcpt.html b/contrib/sendmail/libmilter/docs/smfi_delrcpt.html
index 7776a4369a86..c43dcd6f4a44 100644
--- a/contrib/sendmail/libmilter/docs/smfi_delrcpt.html
+++ b/contrib/sendmail/libmilter/docs/smfi_delrcpt.html
@@ -1,82 +1,82 @@
-
-smfi_delrcpt
-
+
+smfi_delrcpt
+
-smfi_delrcpt
+smfi_delrcpt
-
+
-SYNOPSIS |
-
+SYNOPSIS |
+
#include <libmilter/mfapi.h>
int smfi_delrcpt(
SMFICTX *ctx;
char *rcpt;
);
-
+
Remove a recipient from the current message's envelope.
- |
+ |
-DESCRIPTION |
-
-
-Called When |
-Called only from xxfi_eom. |
-
-
-Effects |
-smfi_delrcpt removes the named recipient from the current message's envelope. |
-
-
+ |
---|
DESCRIPTION |
+
+
+Called When |
+Called only from xxfi_eom. |
+
+
+Effects |
+smfi_delrcpt removes the named recipient from the current message's envelope. |
+
+
- |
---|
ARGUMENTS |
-
- Argument | Description |
- ctx |
- Opaque context structure.
- |
- rcpt |
- The recipient address to be removed, a non-NULL, null-terminated string.
- |
-
- |
+ARGUMENTS |
+
+ Argument | Description |
+ ctx |
+ Opaque context structure.
+ |
+ rcpt |
+ The recipient address to be removed, a non-NULL, null-terminated string.
+ |
+
+ |
-
-RETURN VALUES |
+
+RETURN VALUES |
-smfi_delrcpt will fail and return MI_FAILURE if:
-
- - rcpt is NULL.
-
- Deleting recipients in the current connection state is invalid.
-
- A network error occurs.
-
- SMFIF_DELRCPT was not set when smfi_register was called.
-
+ | smfi_delrcpt will fail and return MI_FAILURE if:
+
+ - rcpt is NULL.
+
- Deleting recipients in the current connection state is invalid.
+
- A network error occurs.
+
- SMFIF_DELRCPT was not set when smfi_register was called.
+
Otherwise, it will return MI_SUCCESS
- |
-
+
+
-
-NOTES |
-
+ |
+NOTES |
+
The addresses to be removed must match exactly. For example, an address and its expanded form do not match.
- |
-
+
+
-
+
-
-
+
+
Copyright (c) 2000, 2003 Sendmail, Inc. and its suppliers.
All rights reserved.
-
+
By using this file, you agree to the terms and conditions set
forth in the LICENSE.
-
-
-
+
+
+
diff --git a/contrib/sendmail/libmilter/docs/smfi_getpriv.html b/contrib/sendmail/libmilter/docs/smfi_getpriv.html
index 3d9f9850388c..9584b9ee90d4 100644
--- a/contrib/sendmail/libmilter/docs/smfi_getpriv.html
+++ b/contrib/sendmail/libmilter/docs/smfi_getpriv.html
@@ -1,62 +1,62 @@
-
-smfi_getpriv
-
+
+smfi_getpriv
+
-smfi_getpriv
+smfi_getpriv
-
+
-SYNOPSIS |
-
+SYNOPSIS |
+
#include <libmilter/mfapi.h>
void* smfi_getpriv(
SMFICTX *ctx
);
-
+
Get the connection-specific data pointer for this connection.
- |
+ |
-DESCRIPTION |
-
-
-Called When |
-smfi_getpriv may be called in any of the xxfi_* callbacks. |
-
-
-Effects |
-None. |
-
-
+ |
---|
DESCRIPTION |
+
+
+Called When |
+smfi_getpriv may be called in any of the xxfi_* callbacks. |
+
+
+Effects |
+None. |
+
+
- |
---|
ARGUMENTS |
-
- Argument | Description |
- ctx |
- Opaque context structure.
- |
-
- |
+ARGUMENTS |
+
+ Argument | Description |
+ ctx |
+ Opaque context structure.
+ |
+
+ |
-
-RETURN VALUES |
+
+RETURN VALUES |
-smfi_getpriv returns the private data pointer stored by a prior call to smfi_setpriv, or NULL if none has been set. |
-
+smfi_getpriv returns the private data pointer stored by a prior call to smfi_setpriv, or NULL if none has been set. |
+
-
+
-
-
+
+
Copyright (c) 2000, 2003 Sendmail, Inc. and its suppliers.
All rights reserved.
-
+
By using this file, you agree to the terms and conditions set
forth in the LICENSE.
-
-
-
+
+
+
diff --git a/contrib/sendmail/libmilter/docs/smfi_getsymval.html b/contrib/sendmail/libmilter/docs/smfi_getsymval.html
index 0e9bc58f6560..671dbfa575a4 100644
--- a/contrib/sendmail/libmilter/docs/smfi_getsymval.html
+++ b/contrib/sendmail/libmilter/docs/smfi_getsymval.html
@@ -1,99 +1,105 @@
-
-smfi_getsymval
-
+
+smfi_getsymval
+
-smfi_getsymval
+smfi_getsymval
-
+
-SYNOPSIS |
-
+SYNOPSIS |
+
#include <libmilter/mfapi.h>
char* smfi_getsymval(
SMFICTX *ctx,
char *symname
);
-
+
Get the value of a sendmail macro.
- |
+ |
-DESCRIPTION |
-
-
-Called When |
-smfi_getsymval may be called from within any of the xxfi_* callbacks. Which macros are defined will depend on when it is called. |
-
-
-Effects |
-None. |
-
-
+ |
---|
DESCRIPTION |
+
+
+Called When |
+smfi_getsymval may be called from within any of the xxfi_* callbacks. Which macros are defined will depend on when it is called. |
+
+
+Effects |
+None. |
+
+
- |
---|
ARGUMENTS |
-
- Argument | Description |
- ctx |
- The opaque context structure.
- |
- symname |
- The name of a sendmail macro.
+ | ARGUMENTS |
+
+ Argument | Description |
+ ctx |
+ The opaque context structure.
+ |
+ symname |
+ The name of a sendmail macro.
Single letter macros can optionally be enclosed in braces ("{" and "}"),
longer macro names must be enclosed in braces, just as in a
- sendmail.cf file.
- See below for default macros.
- |
-
- |
+ sendmail.cf file.
+ See below for default macros.
+
+
+ |
-
-RETURN VALUES |
+
+RETURN VALUES |
-smfi_getsymval returns the value of the given macro as a null-terminated string, or NULL if the macro is not defined. |
-
+smfi_getsymval returns the value of the given macro as a null-terminated string, or NULL if the macro is not defined. |
+
-
-NOTES |
-
+ |
+NOTES |
+
By default, the following macros are valid in the given contexts:
-
-Sent With | Macros |
-xxfi_connect | daemon_name, if_name, if_addr, j, _ |
-xxfi_helo | tls_version, cipher, cipher_bits, cert_subject, cert_issuer |
-xxfi_envfrom | i, auth_type, auth_authen, auth_ssf, auth_author,
- mail_mailer, mail_host, mail_addr |
-xxfi_envrcpt | rcpt_mailer, rcpt_host, rcpt_addr |
-
-
-All macros stay in effect from the point they are received until the
-end of the connection for the first two sets, the end of the message
-for the third (xxfi_envfrom), and just for each recipient for the
-final set (xxfi_envrcpt).
-
+
+Sent With | Macros |
+xxfi_connect | daemon_name, if_name, if_addr, j, _ |
+xxfi_helo | tls_version, cipher, cipher_bits, cert_subject, cert_issuer |
+xxfi_envfrom | i, auth_type, auth_authen, auth_ssf, auth_author,
+ mail_mailer, mail_host, mail_addr |
+xxfi_envrcpt | rcpt_mailer, rcpt_host, rcpt_addr |
+
+xxfi_data | (none) |
+xxfi_eoh | (none) |
+xxfi_eom | msg_id |
+
+
+All macros stay in effect from the point they are received
+until the end of the connection for the first two sets,
+the end of the message for the third (xxfi_envfrom) and last (xxfi_eom),
+and just for each recipient for xxfi_envrcpt.
+
The macro list can be changed using the confMILTER_MACROS_* options in
-sendmail.mc. The scopes of such macros will be determined by when
-they are set by sendmail. For descriptions of macros' values, please
-see the "Sendmail Installation and Operation Guide" provided with your
-sendmail distribution.
+sendmail.mc.
+The scopes of such macros will be determined by when they are set by sendmail.
+For descriptions of macros' values,
+please see the
+"Sendmail Installation and Operation Guide"
+provided with your sendmail distribution.
- |
-
+
+
-
+
-
-
-Copyright (c) 2000, 2002-2003 Sendmail, Inc. and its suppliers.
+
+
+Copyright (c) 2000, 2002-2003, 2007 Sendmail, Inc. and its suppliers.
All rights reserved.
-
+
By using this file, you agree to the terms and conditions set
forth in the LICENSE.
-
-
-
+
+
+
diff --git a/contrib/sendmail/libmilter/docs/smfi_insheader.html b/contrib/sendmail/libmilter/docs/smfi_insheader.html
index 837a1fd9b07d..a4ba77f33d4f 100644
--- a/contrib/sendmail/libmilter/docs/smfi_insheader.html
+++ b/contrib/sendmail/libmilter/docs/smfi_insheader.html
@@ -1,15 +1,15 @@
-
-smfi_insheader
-
+
+smfi_insheader
+
-smfi_insheader
+smfi_insheader
-
+
-SYNOPSIS |
-
+SYNOPSIS |
+
#include <libmilter/mfapi.h>
int smfi_insheader(
SMFICTX *ctx,
@@ -17,107 +17,129 @@ int smfi_insheader(
char *headerf,
char *headerv
);
-
+
Prepend a header to the current message.
- |
+ |
-DESCRIPTION |
-
-
-Called When |
-Called only from xxfi_eom. |
-
-
-Effects |
-Prepends a header to the current message. |
-
-
+ |
---|
DESCRIPTION |
+
+
+Called When |
+Called only from xxfi_eom. |
+
+
+Effects |
+Prepends a header to the current message. |
+
+
- |
---|
ARGUMENTS |
-
- Argument | Description |
- ctx |
- Opaque context structure.
- |
- hdridx |
- The location in the internal header list where this header should
+ | ARGUMENTS |
+
+ Argument | Description |
+ ctx |
+ Opaque context structure.
+ |
+ hdridx |
+ The location in the internal header list where this header should
be inserted; 0 makes it the topmost header, etc.
- |
- headerf |
- The header name, a non-NULL, null-terminated string.
- |
- headerv |
- The header value to be added, a non-NULL, null-terminated string. This may be the empty string.
- |
-
- |
+
+ headerf |
+ The header name, a non-NULL, null-terminated string.
+ |
+ headerv |
+ The header value to be added, a non-NULL, null-terminated string. This may be the empty string.
+ |
+
+ |
-
-RETURN VALUES |
+
+RETURN VALUES |
-smfi_insheader returns MI_FAILURE if:
-- headerf or headerv is NULL.
-
- Adding headers in the current connection state is invalid.
-
- Memory allocation fails.
-
- A network error occurs.
-
- SMFIF_ADDHDRS was not set when smfi_register was called.
-
+ | smfi_insheader returns MI_FAILURE if:
+- headerf or headerv is NULL.
+
- Adding headers in the current connection state is invalid.
+
- Memory allocation fails.
+
- A network error occurs.
+
- SMFIF_ADDHDRS was not set when smfi_register was called.
+
Otherwise, it returns MI_SUCCESS.
- |
-
+
+
-
-NOTES |
-
-- smfi_insheader does not change a message's existing headers.
-To change a header's current value, use smfi_chgheader.
-
- A filter which calls smfi_insheader must have set the SMFIF_ADDHDRS flag in the smfiDesc_str passed to smfi_register.
-
- For smfi_insheader, filter order is important. Later filters will see the header changes made by earlier ones.
-
- If hdridx is a number larger than the number of headers in the message, the header will simply be appended.
-
- Neither the name nor the value of the header is checked for
- standards compliance. However, each line of the header must be under
- 2048 characters and should be under 998 characters. If longer headers
- are needed, make them multi-line. To make a multi-line header, insert
- a line feed (ASCII 0x0a, or \n in C) followed by at least
- one whitespace character such as a space (ASCII 0x20) or tab (ASCII 0x09,
- or \t in C). The line feed should NOT be preceded by a
- carriage return (ASCII 0x0d); the MTA will add this automatically.
- It is the filter writer's responsibility to ensure that no standards
- are violated.
-
- |
-
+
+NOTES |
+
+
+ - smfi_insheader does not change a message's existing headers.
+ To change a header's current value, use
+ smfi_chgheader.
+
- A filter which calls smfi_insheader must have set the SMFIF_ADDHDRS
+ flag in the smfiDesc_str passed to
+ smfi_register.
+
- For smfi_insheader, filter order is important.
+ Later filters will see the header changes made by earlier ones.
+
- A filter will receive only headers that have been sent
+ by the SMTP client and those header modifications by earlier filters.
+ It will not receive the headers that are inserted by sendmail
+ itself.
+ This makes the header insertion position highly dependent on
+ the headers that exist in the incoming message
+ and those that are configured to be added by sendmail.
+ For example, sendmail will always add a
+
Received: header to the beginning of the headers.
+ Setting hdridx to 0 will actually insert the header
+ before this Received: header.
+ However, later filters can be easily confused as they receive
+ the added header, but not the Received: header,
+ thus making it hard to insert a header at a fixed position.
+ - If hdridx is a number larger than the number of headers in the message,
+ the header will simply be appended.
+
- Neither the name nor the value of the header is checked for
+ standards compliance.
+ However, each line of the header must be under 2048 characters
+ and should be under 998 characters.
+ If longer headers are needed, make them multi-line.
+ To make a multi-line header,
+ insert a line feed (ASCII 0x0a, or \n in C)
+ followed by at least one whitespace character
+ such as a space (ASCII 0x20) or tab (ASCII 0x09, or \t in C).
+ The line feed should NOT be preceded by a carriage return (ASCII 0x0d);
+ the MTA will add this automatically.
+ It is the filter writer's responsibility to ensure that no standards
+ are violated.
+
+ |
+
-
-EXAMPLE |
+
+EXAMPLE |
-
-
+
+
int ret;
SMFICTX *ctx;
...
ret = smfi_insheader(ctx, 0, "First", "See me?");
-
- |
- |
+
+
+
-
+
-
-
-Copyright (c) 2004 Sendmail, Inc. and its suppliers.
+
+
+Copyright (c) 2004, 2006 Sendmail, Inc. and its suppliers.
All rights reserved.
-
+
By using this file, you agree to the terms and conditions set
forth in the LICENSE.
-
-
-
+
+
+
diff --git a/contrib/sendmail/libmilter/docs/smfi_main.html b/contrib/sendmail/libmilter/docs/smfi_main.html
index 4e772a10d62d..a749386512d1 100644
--- a/contrib/sendmail/libmilter/docs/smfi_main.html
+++ b/contrib/sendmail/libmilter/docs/smfi_main.html
@@ -1,51 +1,51 @@
-
-smfi_main
-
+
+smfi_main
+
-smfi_main
+smfi_main
-
+
-SYNOPSIS |
-
+SYNOPSIS |
+
#include <libmilter/mfapi.h>
int smfi_main(
);
-
+
Hand control to libmilter event loop.
- |
+ |
-DESCRIPTION |
-
-
-Called When |
-smfi_main is called after a filter's initialization is complete. |
-
-
-Effects |
-smfi_main hands control to the Milter event loop. |
-
-
+ |
---|
DESCRIPTION |
+
+
+Called When |
+smfi_main is called after a filter's initialization is complete. |
+
+
+Effects |
+smfi_main hands control to the Milter event loop. |
+
+
- |
---|
-RETURN VALUES |
+
+RETURN VALUES |
-smfi_main will return MI_FAILURE if it fails to establish a connection. This may occur for any of a variety of reasons (e.g. invalid address passed to smfi_setconn). The reason for the failure will be logged. Otherwise, smfi_main will return MI_SUCCESS. |
-
+smfi_main will return MI_FAILURE if it fails to establish a connection. This may occur for any of a variety of reasons (e.g. invalid address passed to smfi_setconn). The reason for the failure will be logged. Otherwise, smfi_main will return MI_SUCCESS. |
+
-
+
-
-
+
+
Copyright (c) 2000, 2003 Sendmail, Inc. and its suppliers.
All rights reserved.
-
+
By using this file, you agree to the terms and conditions set
forth in the LICENSE.
-
-
-
+
+
+
diff --git a/contrib/sendmail/libmilter/docs/smfi_opensocket.html b/contrib/sendmail/libmilter/docs/smfi_opensocket.html
index 914ae5036b14..151af07a91ae 100644
--- a/contrib/sendmail/libmilter/docs/smfi_opensocket.html
+++ b/contrib/sendmail/libmilter/docs/smfi_opensocket.html
@@ -1,78 +1,78 @@
-
-smfi_opensocket
-
+
+smfi_opensocket
+
-smfi_opensocket
+smfi_opensocket
-
+
-SYNOPSIS |
-
+SYNOPSIS |
+
#include <libmilter/mfapi.h>
int smfi_opensocket(
bool rmsocket
);
-
+
Attempt to create the interface socket MTAs will use to connect to the
filter.
- |
+ |
-DESCRIPTION |
-
-
-Called When |
-Called only from program mainline, before calling
-smfi_main(). |
-
-
-Effects |
-smfi_opensocket attempts to create the socket specified previously by
-a call to smfi_setconn() which will be the interface between MTAs
+ | DESCRIPTION |
+
+
+Called When |
+Called only from program mainline, before calling
+smfi_main(). |
+
+
+Effects |
+smfi_opensocket attempts to create the socket specified previously by
+a call to smfi_setconn() which will be the interface between MTAs
and the filter. This allows the calling application to ensure that the
-socket can be created. If this is not called, smfi_main() will
-do so implicitly. |
-
-
+socket can be created. If this is not called, smfi_main() will
+do so implicitly. |
+
+
- |
---|
ARGUMENTS |
-
- Argument | Description |
- rmsocket |
- A flag indicating whether or not the library should try to
+ | ARGUMENTS |
+
+ Argument | Description |
+ rmsocket |
+ A flag indicating whether or not the library should try to
remove any existing UNIX domain socket before trying to create
a new one.
- |
-
- |
+
+
+ |
-
-RETURN VALUES |
+
+RETURN VALUES |
-smfi_opensocket will fail and return MI_FAILURE if:
-
- - The interface socket could not be created for any reason.
-
- rmsocket was true, and either the socket could
+
smfi_opensocket will fail and return MI_FAILURE if:
+
+ - The interface socket could not be created for any reason.
+
- rmsocket was true, and either the socket could
not be examined, or exists and could not be removed.
-
- smfi_setconn() has not been called.
-
+ - smfi_setconn() has not been called.
+
Otherwise, it will return MI_SUCCESS
-
|
- |
+
+
-
+
-
-
+
+
Copyright (c) 2003 Sendmail, Inc. and its suppliers.
All rights reserved.
-
+
By using this file, you agree to the terms and conditions set
forth in the LICENSE.
-
-
-
+
+
+
diff --git a/contrib/sendmail/libmilter/docs/smfi_progress.html b/contrib/sendmail/libmilter/docs/smfi_progress.html
index 85f12195b519..801bdf335fda 100644
--- a/contrib/sendmail/libmilter/docs/smfi_progress.html
+++ b/contrib/sendmail/libmilter/docs/smfi_progress.html
@@ -1,68 +1,68 @@
-
-smfi_progress
-
+
+smfi_progress
+
-smfi_progress
+smfi_progress
-
+
-SYNOPSIS |
-
+SYNOPSIS |
+
#include <libmilter/mfapi.h>
int smfi_progress(
SMFICTX *ctx;
);
-
+
Notify the MTA that an operation is still in progress.
- |
+ |
-DESCRIPTION |
-
-
-Called When |
-Called only from xxfi_eom. |
-
-
-Effects |
-smfi_progress notifies the MTA that the filter is still working
-on a message, causing the MTA to re-start its timeouts. |
-
-
+ |
---|
DESCRIPTION |
+
+
+Called When |
+Called only from xxfi_eom. |
+
+
+Effects |
+smfi_progress notifies the MTA that the filter is still working
+on a message, causing the MTA to re-start its timeouts. |
+
+
- |
---|
ARGUMENTS |
-
- Argument | Description |
- ctx |
- Opaque context structure.
- |
-
- |
+ARGUMENTS |
+
+ Argument | Description |
+ ctx |
+ Opaque context structure.
+ |
+
+ |
-
-RETURN VALUES |
+
+RETURN VALUES |
-smfi_progress will fail and return MI_FAILURE if:
-
- - A network error occurs.
-
+ | smfi_progress will fail and return MI_FAILURE if:
+
+ - A network error occurs.
+
Otherwise, it will return MI_SUCCESS
- |
-
+
+
-
+
-
-
+
+
Copyright (c) 2003 Sendmail, Inc. and its suppliers.
All rights reserved.
-
+
By using this file, you agree to the terms and conditions set
forth in the LICENSE.
-
-
-
+
+
+
diff --git a/contrib/sendmail/libmilter/docs/smfi_quarantine.html b/contrib/sendmail/libmilter/docs/smfi_quarantine.html
index 066cce81d739..656a480d0122 100644
--- a/contrib/sendmail/libmilter/docs/smfi_quarantine.html
+++ b/contrib/sendmail/libmilter/docs/smfi_quarantine.html
@@ -1,73 +1,73 @@
-
-smfi_quarantine
-
+
+smfi_quarantine
+
-smfi_quarantine
+smfi_quarantine
-
+
-SYNOPSIS |
-
+SYNOPSIS |
+
#include <libmilter/mfapi.h>
int smfi_quarantine(
SMFICTX *ctx;
char *reason;
);
-
+
Quarantine the message using the given reason.
- |
+ |
-DESCRIPTION |
-
-
-Called When |
-Called only from xxfi_eom. |
-
-
-Effects |
-smfi_quarantine quarantines the message using the given reason. |
-
-
+ |
---|
DESCRIPTION |
+
+
+Called When |
+Called only from xxfi_eom. |
+
+
+Effects |
+smfi_quarantine quarantines the message using the given reason. |
+
+
- |
---|
ARGUMENTS |
-
- Argument | Description |
- ctx |
- Opaque context structure.
- |
- reason |
- The quarantine reason, a non-NULL and non-empty null-terminated string.
- |
-
- |
+ARGUMENTS |
+
+ Argument | Description |
+ ctx |
+ Opaque context structure.
+ |
+ reason |
+ The quarantine reason, a non-NULL and non-empty null-terminated string.
+ |
+
+ |
-
-RETURN VALUES |
+
+RETURN VALUES |
-smfi_quarantine will fail and return MI_FAILURE if:
-
- - reason is NULL or empty.
-
- A network error occurs.
-
- SMFIF_QUARANTINE was not set when smfi_register was called.
-
+ | smfi_quarantine will fail and return MI_FAILURE if:
+
+ - reason is NULL or empty.
+
- A network error occurs.
+
- SMFIF_QUARANTINE was not set when smfi_register was called.
+
Otherwise, it will return MI_SUCCESS
- |
-
+
+
-
+
-
-
+
+
Copyright (c) 2002-2003 Sendmail, Inc. and its suppliers.
All rights reserved.
-
+
By using this file, you agree to the terms and conditions set
forth in the LICENSE.
-
-
-
+
+
+
diff --git a/contrib/sendmail/libmilter/docs/smfi_register.html b/contrib/sendmail/libmilter/docs/smfi_register.html
index 3f6ed8301ee2..1a359188f8e8 100644
--- a/contrib/sendmail/libmilter/docs/smfi_register.html
+++ b/contrib/sendmail/libmilter/docs/smfi_register.html
@@ -1,113 +1,129 @@
-
-smfi_register
-
+
+smfi_register
+
-smfi_register
+smfi_register
-
+
-SYNOPSIS |
-
+SYNOPSIS |
+
#include <libmilter/mfapi.h>
int smfi_register(
smfiDesc descr
);
-
+
Register a set of filter callbacks.
- |
+ |
-DESCRIPTION |
-
-
-Called When |
-smfi_register must be called before smfi_main |
-
-
-Effects |
-smfi_register creates a filter using the information given in the
-smfiDesc argument. Multiple calls to smfi_register within a
-single process are not allowed. |
-
-
+ |
---|
DESCRIPTION |
+
+
+Called When |
+smfi_register must be called before smfi_main |
+
+
+Effects |
+smfi_register creates a filter using the information given in the
+smfiDesc argument.
+Multiple (successful) calls to smfi_register within a
+single process are not allowed,
+i.e., only one filter can be successfully registered.
+Note, however, that the library may not check whether this restriction
+is obeyed.
+ |
+
+
- |
---|
ARGUMENTS |
-
- Argument | Description |
- descr |
-
-A filter descriptor of type smfiDesc describing the filter's
-functions. The structure has the following members:
-
+ARGUMENTS |
+
+ Argument | Description |
+ descr |
+
+A filter descriptor of type smfiDesc describing the filter's functions.
+The structure has the following members:
+
struct smfiDesc
{
char *xxfi_name; /* filter name */
int xxfi_version; /* version code -- do not change */
- unsigned long xxfi_flags; /* flags */
+ unsigned long xxfi_flags; /* flags */
/* connection info filter */
- sfsistat (*xxfi_connect)(SMFICTX *, char *, _SOCK_ADDR *);
+ sfsistat (*xxfi_connect)(SMFICTX *, char *, _SOCK_ADDR *);
/* SMTP HELO command filter */
- sfsistat (*xxfi_helo)(SMFICTX *, char *);
+ sfsistat (*xxfi_helo)(SMFICTX *, char *);
/* envelope sender filter */
- sfsistat (*xxfi_envfrom)(SMFICTX *, char **);
+ sfsistat (*xxfi_envfrom)(SMFICTX *, char **);
/* envelope recipient filter */
- sfsistat (*xxfi_envrcpt)(SMFICTX *, char **);
+ sfsistat (*xxfi_envrcpt)(SMFICTX *, char **);
/* header filter */
- sfsistat (*xxfi_header)(SMFICTX *, char *, char *);
+ sfsistat (*xxfi_header)(SMFICTX *, char *, char *);
/* end of header */
- sfsistat (*xxfi_eoh)(SMFICTX *);
+ sfsistat (*xxfi_eoh)(SMFICTX *);
/* body block */
- sfsistat (*xxfi_body)(SMFICTX *, unsigned char *, size_t);
+ sfsistat (*xxfi_body)(SMFICTX *, unsigned char *, size_t);
/* end of message */
- sfsistat (*xxfi_eom)(SMFICTX *);
+ sfsistat (*xxfi_eom)(SMFICTX *);
/* message aborted */
- sfsistat (*xxfi_abort)(SMFICTX *);
+ sfsistat (*xxfi_abort)(SMFICTX *);
/* connection cleanup */
- sfsistat (*xxfi_close)(SMFICTX *);
-};
-
+ sfsistat (*xxfi_close)(SMFICTX *);
-A NULL value for any callback function indicates that the filter does
-not wish to process the given type of information, simply returning
-SMFIS_CONTINUE.
- |
-
- |
+ /* any unrecognized or unimplemented command filter */
+ sfsistat (*xxfi_unknown)(SMFICTX *, const char *);
+
+ /* SMTP DATA command filter */
+ sfsistat (*xxfi_data)(SMFICTX *);
+
+ /* negotiation callback */
+ sfsistat (*xxfi_negotiate)(SMFICTX *,
+ unsigned long, unsigned long, unsigned long, unsigned long,
+ unsigned long *, unsigned long *, unsigned long *, unsigned long *);
+};
+
+
+A NULL value for any callback function indicates that the filter
+does not wish to process the given type of information,
+simply returning SMFIS_CONTINUE.
+ |
+
+ |
-
-RETURN VALUES |
+
+RETURN VALUES |
-
+ |
smfi_register may return MI_FAILURE for any of the following reasons:
-
-- memory allocation failed.
-
- incompatible version or illegal flags value.
-
+
+- memory allocation failed.
+
- incompatible version or illegal flags value.
+
- |
-
+
+
-
-NOTES |
-
+ |
+NOTES |
+
-
-The xxfi_flags field should contain the bitwise OR of zero or more of
+The xxfi_flags
+field should contain the bitwise OR of zero or more of
the following values, describing the actions the filter may take:
-Flag | Description |
+Flag | Description |
SMFIF_ADDHDRS
|
- This filter may add headers.
+ This filter may add headers.
|
@@ -115,7 +131,8 @@ the following values, describing the actions the filter may take:
SMFIF_CHGHDRS
- This filter may change and/or delete headers.
+ This filter may
+ change and/or delete headers.
|
@@ -123,7 +140,8 @@ the following values, describing the actions the filter may take:
SMFIF_CHGBODY
- This filter may replace the body during filtering.
+ This filter may
+ replace the body during filtering.
This may have significant performance impact
if other filters do body filtering after this filter.
|
@@ -133,7 +151,18 @@ the following values, describing the actions the filter may take:
SMFIF_ADDRCPT
- This filter may add recipients to the message.
+ This filter may
+ add recipients
+ to the message.
+ |
+
+
+
+ SMFIF_ADDRCPT_PAR
+ |
+
+ This filter may
+ add recipients including ESMTP args.
|
@@ -141,23 +170,55 @@ the following values, describing the actions the filter may take:
SMFIF_DELRCPT
- This filter may remove recipients from the message.
+ This filter may
+ remove recipients from the message.
|
+
+
+ SMFIF_QUARANTINE
+ |
+
+ This filter may
+ quarantine a message.
+ |
+
+
+
+
+ SMFIF_CHGFROM
+ |
+
+ This filter may
+ change the envelope sender (MAIL).
+ |
+
+
+
+
+ SMFIF_SETSYMLIST
+ |
+
+ This filter can
+ send a set of symbols (macros)
+ that it wants.
+ |
+
+
- |
-
+
+
-
+
-
-
-Copyright (c) 2000-2001, 2003 Sendmail, Inc. and its suppliers.
+
+
+Copyright (c) 2000-2001, 2003, 2006 Sendmail, Inc. and its suppliers.
All rights reserved.
-
+
By using this file, you agree to the terms and conditions set
forth in the LICENSE.
-
-
-
+
+
+
diff --git a/contrib/sendmail/libmilter/docs/smfi_replacebody.html b/contrib/sendmail/libmilter/docs/smfi_replacebody.html
index 91ac8822ec9a..bc8d5ac673e1 100644
--- a/contrib/sendmail/libmilter/docs/smfi_replacebody.html
+++ b/contrib/sendmail/libmilter/docs/smfi_replacebody.html
@@ -1,93 +1,93 @@
-
-smfi_replacebody
-
+
+smfi_replacebody
+
-smfi_replacebody
+smfi_replacebody
-
+
-SYNOPSIS |
-
+SYNOPSIS |
+
#include <libmilter/mfapi.h>
int smfi_replacebody(
SMFICTX *ctx,
unsigned char *bodyp,
int bodylen
);
-
+
Replace message-body data.
- |
+ |
-DESCRIPTION |
-
-
-Called When |
-Called only from xxfi_eom. smfi_replacebody may be called more than once. |
-
-
-Effects |
-smfi_replacebody replaces the body of the current message. If called
+ | DESCRIPTION |
+
+
+Called When |
+Called only from xxfi_eom. smfi_replacebody may be called more than once. |
+
+
+Effects |
+smfi_replacebody replaces the body of the current message. If called
more than once, subsequent calls result in data being appended to the new
body.
- |
-
-
+ |
+
+
- |
---|
ARGUMENTS |
-
- Argument | Description |
- ctx |
- Opaque context structure.
- |
- bodyp |
- A pointer to the start of the new body data, which does not have to be null-terminated. If bodyp is NULL, it is treated as having length == 0. Body data should be in CR/LF form.
- |
- bodylen |
- The number of data bytes pointed to by bodyp.
- |
-
- |
+ARGUMENTS |
+
+ Argument | Description |
+ ctx |
+ Opaque context structure.
+ |
+ bodyp |
+ A pointer to the start of the new body data, which does not have to be null-terminated. If bodyp is NULL, it is treated as having length == 0. Body data should be in CR/LF form.
+ |
+ bodylen |
+ The number of data bytes pointed to by bodyp.
+ |
+
+ |
-
-RETURN VALUES |
+
+RETURN VALUES |
-smfi_replacebody fails and returns MI_FAILURE if:
-
- - bodyp == NULL and bodylen > 0.
-
- Changing the body in the current connection state is invalid.
-
- A network error occurs.
-
- SMFIF_CHGBODY was not set when smfi_register was called.
-
+ | smfi_replacebody fails and returns MI_FAILURE if:
+
+ - bodyp == NULL and bodylen > 0.
+
- Changing the body in the current connection state is invalid.
+
- A network error occurs.
+
- SMFIF_CHGBODY was not set when smfi_register was called.
+
Otherwise, it will return MI_SUCCESS.
- |
-
+
+
-
-NOTES |
-
-
- - Since the message body may be very large, setting SMFIF_CHGBODY may significantly affect filter performance.
-
- If a filter sets SMFIF_CHGBODY but does not call smfi_replacebody, the original body remains unchanged.
-
- For smfi_replacebody, filter order is important. Later filters will see the new body contents created by earlier ones.
-
- |
-
+
+NOTES |
+
+
+ - Since the message body may be very large, setting SMFIF_CHGBODY may significantly affect filter performance.
+
- If a filter sets SMFIF_CHGBODY but does not call smfi_replacebody, the original body remains unchanged.
+
- For smfi_replacebody, filter order is important. Later filters will see the new body contents created by earlier ones.
+
+ |
+
-
+
-
-
+
+
Copyright (c) 2000-2001, 2003 Sendmail, Inc. and its suppliers.
All rights reserved.
-
+
By using this file, you agree to the terms and conditions set
forth in the LICENSE.
-
-
-
+
+
+
diff --git a/contrib/sendmail/libmilter/docs/smfi_setbacklog.html b/contrib/sendmail/libmilter/docs/smfi_setbacklog.html
index 79d8d527209b..8353cac269db 100644
--- a/contrib/sendmail/libmilter/docs/smfi_setbacklog.html
+++ b/contrib/sendmail/libmilter/docs/smfi_setbacklog.html
@@ -1,63 +1,64 @@
-
-smfi_setbacklog
-
+
+smfi_setbacklog
+
-smfi_setbacklog
+smfi_setbacklog
-
+
-SYNOPSIS |
-
+SYNOPSIS |
+
#include <libmilter/mfapi.h>
int smfi_setbacklog(
int obacklog
);
-
-Set the filter's listen backlog value.
- |
+
+Set the filter's listen(2) backlog value.
+ |
-DESCRIPTION |
-
-
-Called When |
-smfi_setbacklog should only be called before smfi_main. |
-
-
-Effects |
-Sets the incoming socket backlog used by listen(). If smfi_setbacklog is not called, the operating system default is used. |
-
-
+ |
---|
DESCRIPTION |
+
+
+Called When |
+smfi_setbacklog should only be called before smfi_main. |
+
+
+Effects |
+Sets the incoming socket backlog used by listen(2) .
+If smfi_setbacklog is not called, the operating system default is used. |
+
+
- |
---|
ARGUMENTS |
-
- Argument | Description |
- obacklog |
- The number of incoming connections to allow in the listen queue.
- |
-
- |
+ARGUMENTS |
+
+ Argument | Description |
+ obacklog |
+ The number of incoming connections to allow in the listen queue.
+ |
+
+ |
-
-RETURN VALUES |
+
+RETURN VALUES |
-smfi_setbacklog returns MI_FAILURE if obacklog is less than or equal
-to zero. |
-
+smfi_setbacklog returns MI_FAILURE if obacklog is less than or equal
+to zero. |
+
-
+
-
-
+
+
Copyright (c) 2002-2003 Sendmail, Inc. and its suppliers.
All rights reserved.
-
+
By using this file, you agree to the terms and conditions set
forth in the LICENSE.
-
-
-
+
+
+
diff --git a/contrib/sendmail/libmilter/docs/smfi_setconn.html b/contrib/sendmail/libmilter/docs/smfi_setconn.html
index 07461ccced2f..70a510e3ea1d 100644
--- a/contrib/sendmail/libmilter/docs/smfi_setconn.html
+++ b/contrib/sendmail/libmilter/docs/smfi_setconn.html
@@ -1,92 +1,93 @@
-
-smfi_setconn
-
+
+smfi_setconn
+
-smfi_setconn
+smfi_setconn
-
+
-SYNOPSIS |
-
+SYNOPSIS |
+
#include <libmilter/mfapi.h>
int smfi_setconn(
char *oconn;
);
-
+
Set the socket through which this filter should communicate with sendmail.
- |
+ |
-DESCRIPTION |
-
-
-Called When |
-smfi_setconn must be called once before smfi_main. |
-
-
-Effects |
-Sets the socket through which the filter communicates with sendmail. |
-
-
+ |
---|
DESCRIPTION |
+
+
+Called When |
+smfi_setconn must be called once before smfi_main. |
+
+
+Effects |
+Sets the socket through which the filter communicates with sendmail. |
+
+
- |
---|
ARGUMENTS |
-
- Argument | Description |
- oconn |
- The address of the desired communication socket.
+ | ARGUMENTS |
+
+ Argument | Description |
+ oconn |
+ The address of the desired communication socket.
The address should be a NULL-terminated string in "proto:address"
format:
-
- {unix|local}:/path/to/file -- A named pipe.
- inet:port@{hostname|ip-address} -- An IPV4 socket.
- inet6:port@{hostname|ip-address} -- An IPV6 socket.
-
- |
-
- |
+
+ {unix|local}:/path/to/file -- A named pipe.
+ inet:port@{hostname|ip-address} -- An IPV4 socket.
+ inet6:port@{hostname|ip-address} -- An IPV6 socket.
+
+
+
+ |
-
-RETURN VALUES |
+
+RETURN VALUES |
-smfi_setconn will not fail on an invalid address.
-The failure will only be detected in smfi_main | .
+smfi_setconn will not fail on an invalid address.
+The failure will only be detected in smfi_main.
Nevertheless, smfi_setconn may fail for other reasons, e.g.,
due to a lack of memory.
- |
+
+
-
-NOTES |
+
+NOTES |
-
-
- - If possible, filters should not run as root when communicating
+
+
+ - If possible, filters should not run as root when communicating
over unix/local domain sockets.
-
- Unix/local sockets should have their permissions set to
+
- Unix/local sockets should have their permissions set to
0600 (read/write permission only for the socket's owner) or
0660 (read/write permission for the socket's owner and group)
which is useful if the sendmail RunAsUser option is used.
The permissions for a unix/local domain socket are determined as
- usual by
umask , which should be set to 007 or 077.
+ usual by umask , which should be set to 007 or 077.
Note some operating systems (e.g, Solaris) don't use the
permissions of the socket. On those systems, place the socket in a
protected directory.
-
- |
- |
+
+
+
-
+
-
-
+
+
Copyright (c) 2000, 2003 Sendmail, Inc. and its suppliers.
All rights reserved.
-
+
By using this file, you agree to the terms and conditions set
forth in the LICENSE.
-
-
-
+
+
+
diff --git a/contrib/sendmail/libmilter/docs/smfi_setdbg.html b/contrib/sendmail/libmilter/docs/smfi_setdbg.html
index 3203f0ff8bfd..e001d3f7bb1d 100644
--- a/contrib/sendmail/libmilter/docs/smfi_setdbg.html
+++ b/contrib/sendmail/libmilter/docs/smfi_setdbg.html
@@ -1,67 +1,67 @@
-
-smfi_setdbg
-
+
+smfi_setdbg
+
-smfi_setdbg
+smfi_setdbg
-
+
-SYNOPSIS |
-
+SYNOPSIS |
+
#include <libmilter/mfapi.h>
int smfi_setdbg(
int level;
);
-
+
Set the debugging (tracing) level for the milter library.
- |
+ |
-DESCRIPTION |
-
-
-Called When |
-Called from any any routine at any time. |
-
-
-Effects |
-smfi_setdbg sets the milter library's internal debugging level
+ | DESCRIPTION |
+
+
+Called When |
+Called from any any routine at any time. |
+
+
+Effects |
+smfi_setdbg sets the milter library's internal debugging level
to a new level so that code details may be traced.
A level of zero turns off debugging. The greater
(more positive) the level the more detailed the debugging. Six is
-the current, highest, useful value. |
-
-
+the current, highest, useful value. |
+
+
- |
---|
ARGUMENTS |
-
- Argument | Description |
- level |
- The new debugging level
- |
-
- |
+ARGUMENTS |
+
+ Argument | Description |
+ level |
+ The new debugging level
+ |
+
+ |
-
-RETURN VALUES |
+
+RETURN VALUES |
-smfi_setdbg returns MI_SUCCESS by default.
- |
-
+smfi_setdbg returns MI_SUCCESS by default.
+ |
+
-
+
-
-
+
+
Copyright (c) 2003 Sendmail, Inc. and its suppliers.
All rights reserved.
-
+
By using this file, you agree to the terms and conditions set
forth in the LICENSE.
-
-
-
+
+
+
diff --git a/contrib/sendmail/libmilter/docs/smfi_setmlreply.html b/contrib/sendmail/libmilter/docs/smfi_setmlreply.html
index 060c81d4d944..b01bacf9b5b4 100644
--- a/contrib/sendmail/libmilter/docs/smfi_setmlreply.html
+++ b/contrib/sendmail/libmilter/docs/smfi_setmlreply.html
@@ -1,15 +1,15 @@
-
-smfi_setmlreply
-
+
+smfi_setmlreply
+
-smfi_setmlreply
+smfi_setmlreply
-
+
-SYNOPSIS |
-
+SYNOPSIS |
+
#include <libmilter/mfapi.h>
int smfi_setmlreply(
SMFICTX *ctx,
@@ -17,131 +17,129 @@ int smfi_setmlreply(
char *xcode,
...
);
-
+
Set the default SMTP error reply code to a multi-line response. Only 4XX
and 5XX replies are accepted.
- |
+ |
-DESCRIPTION |
-
-
-Called When |
-smfi_setmlreply may be called from any of the xxfi_ callbacks
-other than xxfi_connect. |
-
-
-Effects |
-Directly set the SMTP error reply code for this connection to the given
+ | DESCRIPTION |
+
+
+Called When |
+smfi_setmlreply may be called from any of the xxfi_ callbacks
+other than xxfi_connect. |
+
+
+Effects |
+Directly set the SMTP error reply code for this connection to the given
lines after the xcode. The list of arguments must be NULL terminated.
This code will be used on subsequent error replies resulting from actions
-taken by this filter. |
-
-
+taken by this filter. |
+
+
- |
---|
ARGUMENTS |
-
- Argument | Description |
- ctx |
- Opaque context structure.
- |
- rcode |
- The three-digit (RFC 821/2821) SMTP reply code, as a
+ | ARGUMENTS |
+
+ Argument | Description |
+ ctx |
+ Opaque context structure.
+ |
+ rcode |
+ The three-digit (RFC 821/2821) SMTP reply code, as a
null-terminated string. rcode cannot be NULL, and must be a valid
4XX or 5XX reply code.
- |
- xcode |
- The extended (RFC 1893/2034) reply code. If xcode is NULL, no
+ |
+ xcode |
+ The extended (RFC 1893/2034) reply code. If xcode is NULL, no
extended code is used. Otherwise, xcode must conform to RFC 1893/2034.
- |
- ... |
- The remainder of the arguments are single lines of text, up to
+ |
+ ... |
+ The remainder of the arguments are single lines of text, up to
32 arguments, which will be used as the text part of the SMTP
reply. The list must be NULL terminated.
- |
-
- |
+
+
+ |
-
-RETURN VALUES |
-
+ |
+RETURN VALUES |
+
For example, the code:
-
+
ret = smfi_setmlreply(ctx, "550", "5.7.0",
"Spammer access rejected",
"Please see our policy at:",
"http://www.example.com/spampolicy.html",
NULL);
-
+
would give the SMTP response:
-
+
550-5.7.0 Spammer access rejected
550-5.7.0 Please see our policy at:
550 5.7.0 http://www.example.com/spampolicy.html
- |
-
+
+
+
-
-RETURN VALUES |
+
+RETURN VALUES |
-smfi_setmlreply will fail and return MI_FAILURE if:
-
- - The rcode or xcode argument is invalid.
-
- A memory-allocation failure occurs.
-
- If any text line contains a carraige return or line feed.
-
- The length of any text line is more than MAXREPLYLEN (980).
-
- More than 32 lines of text replies are given.
-
+ | smfi_setmlreply will fail and return MI_FAILURE if:
+
+ - The rcode or xcode argument is invalid.
+
- A memory-allocation failure occurs.
+
- If any text line contains a carraige return or line feed.
+
- The length of any text line is more than MAXREPLYLEN (980).
+
- More than 32 lines of text replies are given.
+
Otherwise, it return MI_SUCCESS.
- |
-
+
+
-
-NOTES |
-
-
-- Values passed to smfi_setmlreply are not checked for standards compliance.
-
- The message parameter should contain only printable characters,
+
+NOTES |
+
+
+- Values passed to smfi_setmlreply are not checked for standards compliance.
+
- The message parameter should contain only printable characters,
other characters may lead to undefined behavior.
For example, CR or LF will cause the call to fail,
single '%' characters will cause the text to be ignored
(if there really should be a '%' in the string,
-use '%%' just like for printf(3)).
-
- For details about reply codes and their meanings, please see RFC's
-821/
-2821
+use '%%' just like for printf(3)).
+
- For details about reply codes and their meanings, please see RFC's
+821/
+2821
and
-1893/
-2034.
-
- If the reply code (rcode) given is a '4XX' code but SMFI_REJECT is used
+1893/
+2034.
+
- If the reply code (rcode) given is a '4XX' code but SMFI_REJECT is used
for the message, the custom reply is not used.
-
- Similarly, if the reply code (rcode) given is a '5XX' code but
+
- Similarly, if the reply code (rcode) given is a '5XX' code but
SMFI_TEMPFAIL is used for the message, the custom reply is not used.
Note: in neither of the last two cases an error is returned to the milter,
libmilter silently ignores the reply code.
- -
-If the milter returns SMFI_TEMPFAIL
-and sets the reply code to '421',
-then the SMTP server will terminate the SMTP session with a 421
-error code.
-
- |
-
+ - If the milter returns SMFI_TEMPFAIL and sets the reply code to '421',
+then the SMTP server will terminate the SMTP session with a 421 error code.
+
+ |
+
-
+
-
-
+
+
Copyright (c) 2000, 2002-2003 Sendmail, Inc. and its suppliers.
All rights reserved.
-
+
By using this file, you agree to the terms and conditions set
forth in the LICENSE.
-
-
-
+
+
+
diff --git a/contrib/sendmail/libmilter/docs/smfi_setpriv.html b/contrib/sendmail/libmilter/docs/smfi_setpriv.html
index 61e30a9841b1..1c287ebb10d6 100644
--- a/contrib/sendmail/libmilter/docs/smfi_setpriv.html
+++ b/contrib/sendmail/libmilter/docs/smfi_setpriv.html
@@ -1,80 +1,80 @@
-
-smfi_setpriv
-
+
+smfi_setpriv
+
-smfi_setpriv
+smfi_setpriv
-
+
-SYNOPSIS |
-
+SYNOPSIS |
+
#include <libmilter/mfapi.h>
int smfi_setpriv(
SMFICTX *ctx,
void *privatedata
);
-
+
Set the private data pointer for this connection.
- |
+ |
-DESCRIPTION |
-
-
-Called When |
-smfi_setpriv may be called in any of the xxfi_* callbacks. |
-
-
-Effects |
-Sets the private data pointer for the context ctx. |
-
-
+ |
---|
DESCRIPTION |
+
+
+Called When |
+smfi_setpriv may be called in any of the xxfi_* callbacks. |
+
+
+Effects |
+Sets the private data pointer for the context ctx. |
+
+
- |
---|
ARGUMENTS |
-
- Argument | Description |
- ctx |
- Opaque context structure.
- |
- privatedata |
- Pointer to private data. This value will be returned by subsequent calls to smfi_getpriv using ctx.
- |
-
- |
+ARGUMENTS |
+
+ Argument | Description |
+ ctx |
+ Opaque context structure.
+ |
+ privatedata |
+ Pointer to private data. This value will be returned by subsequent calls to smfi_getpriv using ctx.
+ |
+
+ |
-
-RETURN VALUES |
+
+RETURN VALUES |
-smfi_setpriv returns MI_FAILURE if ctx is an invalid context.
-Otherwise, it returns MI_SUCCESS. |
-
+smfi_setpriv returns MI_FAILURE if ctx is an invalid context.
+Otherwise, it returns MI_SUCCESS. |
+
-
-NOTES |
+
+NOTES |
-There is only one private data pointer per connection; multiple
+ | There is only one private data pointer per connection; multiple
calls to smfi_setpriv with different values will cause previous values
to be lost.
Before a filter terminates it should release the private data
and set the pointer to NULL.
- |
+
-
+
-
+
-
-
+
+
Copyright (c) 2000-2001, 2003 Sendmail, Inc. and its suppliers.
All rights reserved.
-
+
By using this file, you agree to the terms and conditions set
forth in the LICENSE.
-
-
-
+
+
+
diff --git a/contrib/sendmail/libmilter/docs/smfi_setreply.html b/contrib/sendmail/libmilter/docs/smfi_setreply.html
index f62196b7a6cb..d857815993de 100644
--- a/contrib/sendmail/libmilter/docs/smfi_setreply.html
+++ b/contrib/sendmail/libmilter/docs/smfi_setreply.html
@@ -1,15 +1,15 @@
-
-smfi_setreply
-
+
+smfi_setreply
+
-smfi_setreply
+smfi_setreply
-
+
-SYNOPSIS |
-
+SYNOPSIS |
+
#include <libmilter/mfapi.h>
int smfi_setreply(
SMFICTX *ctx,
@@ -17,104 +17,101 @@ int smfi_setreply(
char *xcode,
char *message
);
-
+
Set the default SMTP error reply code. Only 4XX and 5XX replies are accepted.
- |
+ |
-DESCRIPTION |
-
-
-Called When |
-smfi_setreply may be called from any of the xxfi_ callbacks
-other than xxfi_connect. |
-
-
-Effects |
-Directly set the SMTP error reply code for this connection. This code
+ | DESCRIPTION |
+
+
+Called When |
+smfi_setreply may be called from any of the xxfi_ callbacks
+other than xxfi_connect. |
+
+
+Effects |
+Directly set the SMTP error reply code for this connection. This code
will be used on subsequent error replies resulting from actions taken by
-this filter. |
-
-
+this filter. |
+
+
- |
---|
ARGUMENTS |
-
- Argument | Description |
- ctx |
- Opaque context structure.
- |
- rcode |
- The three-digit (RFC 821/2821) SMTP reply code, as a
+ | ARGUMENTS |
+
+ Argument | Description |
+ ctx |
+ Opaque context structure.
+ |
+ rcode |
+ The three-digit (RFC 821/2821) SMTP reply code, as a
null-terminated string. rcode cannot be NULL, and must be a valid
4XX or 5XX reply code.
- |
- xcode |
- The extended (RFC 1893/2034) reply code. If xcode is NULL, no
+ |
+ xcode |
+ The extended (RFC 1893/2034) reply code. If xcode is NULL, no
extended code is used. Otherwise, xcode must conform to RFC 1893/2034.
- |
- message |
- The text part of the SMTP reply. If message is NULL, an empty message is used.
- |
-
- |
+
+ message |
+ The text part of the SMTP reply. If message is NULL, an empty message is used.
+ |
+
+ |
-
-RETURN VALUES |
+
+RETURN VALUES |
-smfi_setreply will fail and return MI_FAILURE if:
-
- - The rcode or xcode argument is invalid.
-
- A memory-allocation failure occurs.
-
+ | smfi_setreply will fail and return MI_FAILURE if:
+
+ - The rcode or xcode argument is invalid.
+
- A memory-allocation failure occurs.
+
Otherwise, it return MI_SUCCESS.
- |
-
+
+
-
-NOTES |
-
-
-- Values passed to smfi_setreply are not checked for standards compliance.
-
- The message parameter should contain only printable characters,
+
+NOTES |
+
+
+- Values passed to smfi_setreply are not checked for standards compliance.
+
- The message parameter should contain only printable characters,
other characters may lead to undefined behavior.
For example, CR or LF will cause the call to fail,
single '%' characters will cause the text to be ignored
(if there really should be a '%' in the string,
-use '%%' just like for printf(3)).
-
- For details about reply codes and their meanings, please see RFC's
-821/
-2821
+use '%%' just like for printf(3)).
+
- For details about reply codes and their meanings, please see RFC's
+821/
+2821
and
-1893/
-2034.
-
- If the reply code (rcode) given is a '4XX' code but SMFI_REJECT is used
+1893/
+2034.
+
- If the reply code (rcode) given is a '4XX' code but SMFI_REJECT is used
for the message, the custom reply is not used.
-
- Similarly, if the reply code (rcode) given is a '5XX' code but
+
- Similarly, if the reply code (rcode) given is a '5XX' code but
SMFI_TEMPFAIL is used for the message, the custom reply is not used.
Note: in neither of the last two cases an error is returned to the milter,
libmilter silently ignores the reply code.
- -
-If the milter returns SMFI_TEMPFAIL
-and sets the reply code to '421',
-then the SMTP server will terminate the SMTP session with a 421
-error code.
-
- |
-
+ - If the milter returns SMFI_TEMPFAIL and sets the reply code to '421',
+then the SMTP server will terminate the SMTP session with a 421 error code.
+
+ |
+
-
+
-
-
+
+
Copyright (c) 2000, 2002-2003 Sendmail, Inc. and its suppliers.
All rights reserved.
-
+
By using this file, you agree to the terms and conditions set
forth in the LICENSE.
-
-
-
+
+
+
diff --git a/contrib/sendmail/libmilter/docs/smfi_setsymlist.html b/contrib/sendmail/libmilter/docs/smfi_setsymlist.html
new file mode 100644
index 000000000000..7e8edff6c68f
--- /dev/null
+++ b/contrib/sendmail/libmilter/docs/smfi_setsymlist.html
@@ -0,0 +1,107 @@
+
+smfi_setsymlist
+
+
+smfi_setsymlist
+
+
+
+SYNOPSIS |
+
+#include <libmilter/mfapi.h>
+int smfi_setsymlist(
+ SMFICTX *ctx,
+ int stage,
+ char *macros
+);
+
+Set the list of macros that the milter wants to receive from the MTA
+for a protocol stage.
+ |
+
+
+DESCRIPTION |
+
+
+Called When |
+This function must only be called during
+xxfi_negotiate().
+ |
+
+
+Effects |
+This function can be used to override the list of macros that the
+milter wants to receive from the MTA.
+ |
+
+
+
+
+ |
---|
ARGUMENTS |
+
+ Argument | Description |
+
+ ctx |
+ the opaque context structure.
+ |
+
+ stage |
+ the protocol stage during which the macro list should be used.
+ See the file
+ include/libmilter/mfapi.h for legal values,
+ look for the C macros with the prefix
+ SMFIM_ .
+ Available protocol stages are at least
+ the initial connection, HELO/EHLO, MAIL, RCPT, DATA,
+ end of header, and
+ the end of a message.
+ |
+
+ macros |
+ list of macros (separated by space).
+ Example: "{rcpt_mailer} {rcpt_host}"
+ |
+
+
+ |
+
+
+
+RETURN VALUES |
+
+MI_FAILURE is returned if
+
+- there is not enough free memory to make a copy of the macro list,
+
macros is NULL or empty,
+stage is not a valid protocol stage,
+- the macro list for
+
stage has been set before.
+
+Otherwise MI_SUCCESS is returned.
+ |
+
+
+
+
+NOTES |
+There is an internal limit on the number of macros that can be
+set (currently 5),
+however, this limit is not enforced by libmilter, only by the MTA,
+but a possible violation of this restriction is not communicated back to
+the milter. |
+
+
+
+
+
+
+Copyright (c) 2006 Sendmail, Inc. and its suppliers.
+All rights reserved.
+
+By using this file, you agree to the terms and conditions set
+forth in the LICENSE.
+
+
+
diff --git a/contrib/sendmail/libmilter/docs/smfi_settimeout.html b/contrib/sendmail/libmilter/docs/smfi_settimeout.html
index 08f01ed97801..97d41cb1dd65 100644
--- a/contrib/sendmail/libmilter/docs/smfi_settimeout.html
+++ b/contrib/sendmail/libmilter/docs/smfi_settimeout.html
@@ -1,66 +1,66 @@
-
-smfi_settimeout
-
+
+smfi_settimeout
+
-smfi_settimeout
+smfi_settimeout
-
+
-SYNOPSIS |
-
+SYNOPSIS |
+
#include <libmilter/mfapi.h>
int smfi_settimeout(
int otimeout
);
-
-Set the filter's connection timeout value.
- |
+
+Set the filter's I/O timeout value.
+ |
-DESCRIPTION |
-
-
-Called When |
-smfi_settimeout should only be called before smfi_main. |
-
-
-Effects |
-Sets the number of seconds libmilter will wait for an MTA connection before
-timing out a socket.
+ | DESCRIPTION |
+
+
+Called When |
+smfi_settimeout should only be called before smfi_main. |
+
+
+Effects |
+Sets the number of seconds libmilter will wait
+for an MTA communication (read or write) before timing out.
If smfi_settimeout is not called, a default timeout of 7210 seconds is used.
- |
-
-
+ |
+
+
- |
---|
ARGUMENTS |
-
- Argument | Description |
- otimeout |
- The number of seconds to wait before timing out (> 0). Zero means
-no wait, not "wait forever".
- |
-
- |
+ARGUMENTS |
+
+ Argument | Description |
+ otimeout |
+ The number of seconds to wait before timing out (> 0).
+ Zero means no wait, not "wait forever".
+ |
+
+ |
-
-RETURN VALUES |
+
+RETURN VALUES |
-smfi_settimeout always returns MI_SUCCESS. |
-
+smfi_settimeout always returns MI_SUCCESS. |
+
-
+
-
-
-Copyright (c) 2000, 2002-2003 Sendmail, Inc. and its suppliers.
+
+
+Copyright (c) 2000, 2002-2003, 2006 Sendmail, Inc. and its suppliers.
All rights reserved.
-
+
By using this file, you agree to the terms and conditions set
forth in the LICENSE.
-
-
-
+
+
+
diff --git a/contrib/sendmail/libmilter/docs/smfi_stop.html b/contrib/sendmail/libmilter/docs/smfi_stop.html
index 05e17be4e6ac..87ecdb271752 100644
--- a/contrib/sendmail/libmilter/docs/smfi_stop.html
+++ b/contrib/sendmail/libmilter/docs/smfi_stop.html
@@ -1,74 +1,74 @@
-
-smfi_stop
-
+
+smfi_stop
+
-smfi_stop
+smfi_stop
-
+
-SYNOPSIS |
-
+SYNOPSIS |
+
#include <libmilter/mfapi.h>
int smfi_stop(void);
-
+
Shutdown the milter.
No connections will be accepted after this call.
- |
+ |
-DESCRIPTION |
-
-
-Called When |
-Called from any of the Callback routines
-or any error-handling routines at any time. |
-
-
-Effects |
-The smfi_stop routine prevents that new connections
+ | DESCRIPTION |
+
+
+Called When |
+Called from any of the Callback routines
+or any error-handling routines at any time. |
+
+
+Effects |
+The smfi_stop routine prevents that new connections
will be accepted,
however, it does not wait for existing connections (threads) to terminate.
It will cause
-smfi_main to return to the calling program,
+smfi_main to return to the calling program,
which may then exit or warm-restart.
- |
-
-
+ |
+
+
- |
---|
ARGUMENTS |
-
- Argument | Description |
- void |
- Takes no arguement.
- |
-
- |
+ARGUMENTS |
+
+ Argument | Description |
+ void |
+ Takes no arguement.
+ |
+
+ |
-
-RETURN VALUES |
+
+RETURN VALUES |
-smfi_stop always returns SMFI_CONTINUE. But note:
-
- - Another internal routine may already have asked the milter to abort.
-
- Another routine may already have asked the milter to stop.
-
- There is no way to cancel the stop process once it has begun.
-
- |
-
+smfi_stop always returns SMFI_CONTINUE. But note:
+
+ - Another internal routine may already have asked the milter to abort.
+
- Another routine may already have asked the milter to stop.
+
- There is no way to cancel the stop process once it has begun.
+
+ |
+
-
+
-
-
+
+
Copyright (c) 2003, 2005 Sendmail, Inc. and its suppliers.
All rights reserved.
-
+
By using this file, you agree to the terms and conditions set
forth in the LICENSE.
-
-
-
+
+
+
diff --git a/contrib/sendmail/libmilter/docs/smfi_version.html b/contrib/sendmail/libmilter/docs/smfi_version.html
new file mode 100644
index 000000000000..3c1fc0520a23
--- /dev/null
+++ b/contrib/sendmail/libmilter/docs/smfi_version.html
@@ -0,0 +1,86 @@
+
+smfi_version()
+
+
+smfi_version()
+
+
+
+SYNOPSIS |
+
+#include <libmilter/mfapi.h>
+int smfi_version(
+ unsigned int *pmajor,
+ unsigned int *pminor,
+ unsigned int *ppl
+);
+
+Get the (runtime) version of libmilter.
+ |
+
+
+DESCRIPTION |
+
+
+Called When |
+smfi_version may be called at any time. |
+
+
+Effects |
+None. |
+
+
+
+
+ |
---|
ARGUMENTS |
+
+ Argument | Description |
+ pmajor |
+ Pointer to an unsigned int variable to store major version number.
+ |
+ pminor |
+ Pointer to an unsigned int variable to store minor version number.
+ |
+ ppl |
+ Pointer to an unsigned int variable to store patch level number.
+ |
+
+ |
+
+
+
+RETURN VALUES |
+smfi_version returns MI_SUCCESS. |
+
+
+
+
+Note: the compile time version of libmilter is available in the macro
+SMFI_VERSION
.
+A milter can check this macro to determine which functions to use
+(at compile time via C preprocessor statements).
+Using this macro and the
+smfi_version()
+function,
+a milter can determine at runtime whether it has been (dynamically)
+linked against the expected libmilter version.
+To extract the major and minor version as well as the current patch level
+from this macro, the macros
+SM_LM_VRS_MAJOR(v)
,
+SM_LM_VRS_MINOR(v)
, and
+SM_LM_VRS_PLVL(v)
+can be used, respectively.
+
+
+
+
+Copyright (c) 2006, 2007 Sendmail, Inc. and its suppliers.
+All rights reserved.
+
+By using this file, you agree to the terms and conditions set
+forth in the LICENSE.
+
+
+
diff --git a/contrib/sendmail/libmilter/docs/xxfi_abort.html b/contrib/sendmail/libmilter/docs/xxfi_abort.html
index 3db1117c0d1a..0664dc107e49 100644
--- a/contrib/sendmail/libmilter/docs/xxfi_abort.html
+++ b/contrib/sendmail/libmilter/docs/xxfi_abort.html
@@ -1,83 +1,83 @@
-
-xxfi_abort
-
+
+xxfi_abort
+
-xxfi_abort
+xxfi_abort
-
+
-SYNOPSIS |
-
+SYNOPSIS |
+
#include <libmilter/mfapi.h>
sfsistat (*xxfi_abort)(
- SMFICTX * ctx
+ SMFICTX *ctx
);
-
+
Handle the current message's being aborted.
- |
+ |
-DESCRIPTION |
-
-
-Called When |
-xxfi_abort may be called at any time during message processing (i.e. between some message-oriented routine and xxfi_eom). |
-
-
-Default Behavior |
-Do nothing; return SMFIS_CONTINUE. |
-
-
+ |
---|
DESCRIPTION |
+
+
+Called When |
+xxfi_abort may be called at any time during message processing (i.e. between some message-oriented routine and xxfi_eom). |
+
+
+Default Behavior |
+Do nothing; return SMFIS_CONTINUE. |
+
+
- |
---|
ARGUMENTS |
-
- Argument | Description |
- ctx |
- Opaque context structure.
- |
-
- |
+ARGUMENTS |
+
+ Argument | Description |
+ ctx |
+ Opaque context structure.
+ |
+
+ |
-
-NOTES |
-
-
-- xxfi_abort must reclaim any resources allocated on a per-message
+
+NOTES |
+
+
+- xxfi_abort must reclaim any resources allocated on a per-message
basis, and must be tolerant of being called between any two
message-oriented callbacks.
-
- Calls to xxfi_abort and xxfi_eom are
+
- Calls to xxfi_abort and xxfi_eom are
mutually exclusive.
-
- xxfi_abort is not responsible for reclaiming connection-specific
-data, since xxfi_close is always called
+
- xxfi_abort is not responsible for reclaiming connection-specific
+data, since xxfi_close is always called
when a connection is closed.
-
- Since the current message is already being aborted, the return
+
- Since the current message is already being aborted, the return
value is currently ignored.
-
- xxfi_abort is only called if the message is aborted outside the
-filter's control and the filter has not completed its
+
- xxfi_abort is only called if the message is aborted outside the
+filter's control and the filter has not completed its
message-oriented processing. For example, if a filter has already
returned SMFIS_ACCEPT, SMFIS_REJECT, or SMFIS_DISCARD from a
message-oriented routine, xxfi_abort will not be called even if the
message is later aborted outside its control.
-
- |
-
- |
+
+
+
+
-
-
+
+
Copyright (c) 2000, 2003 Sendmail, Inc. and its suppliers.
All rights reserved.
-
+
By using this file, you agree to the terms and conditions set
forth in the LICENSE.
-
-
-
+
+
+
diff --git a/contrib/sendmail/libmilter/docs/xxfi_body.html b/contrib/sendmail/libmilter/docs/xxfi_body.html
index 044e9ce22f33..0a5f0f3da7ca 100644
--- a/contrib/sendmail/libmilter/docs/xxfi_body.html
+++ b/contrib/sendmail/libmilter/docs/xxfi_body.html
@@ -1,83 +1,97 @@
-
-xxfi_body
-
+
+xxfi_body
+
-xxfi_body
+xxfi_body
-
+
-SYNOPSIS |
-
+SYNOPSIS |
+
#include <libmilter/mfapi.h>
sfsistat (*xxfi_body)(
- SMFICTX * ctx,
- unsigned char * bodyp,
+ SMFICTX *ctx,
+ unsigned char *bodyp,
size_t len
);
-
+
Handle a piece of a message's body.
- |
+ |
-DESCRIPTION |
-
-
-Called When |
-xxfi_body is called zero or more times between xxfi_eoh and xxfi_eom. |
-
-
-Default Behavior |
-Do nothing; return SMFIS_CONTINUE. |
-
-
+ |
---|
DESCRIPTION |
+
+
+Called When |
+xxfi_body is called zero or more times between xxfi_eoh and xxfi_eom. |
+
+
+Default Behavior |
+Do nothing; return SMFIS_CONTINUE. |
+
+
- |
---|
ARGUMENTS |
-
- Argument | Description |
- ctx |
- Opaque context structure.
- |
- bodyp |
- Pointer to the start of this block of body data. bodyp is not valid outside this call to xxfi_body.
- |
- len |
- The amount of data pointed to by bodyp.
- |
-
- |
+ARGUMENTS |
+
+ Argument | Description |
+ ctx |
+ Opaque context structure.
+ |
+ bodyp |
+ Pointer to the start of this block of body data. bodyp is not valid outside this call to xxfi_body.
+ |
+ len |
+ The amount of data pointed to by bodyp.
+ |
+
+ |
-
-NOTES |
-
-
-- bodyp points to a sequence of bytes.
-It is not a C string (a sequence of characters that is terminated by '\0').
-Therefore, do not use the usual C string functions like strlen() on this byte block.
+
+NOTES |
+
+
+- bodyp points to a sequence of bytes.
+It is not a C string (a sequence of characters that is terminated by '\0').
+Therefore, do not use the usual C string functions like
strlen(3)
+on this byte block.
Moreover, the byte sequence may contain '\0' characters inside the block.
Hence even if a trailing '\0' is added, C string functions may still fail
to work as expected.
- - Since message bodies can be very large, defining xxfi_body can
+
- Since message bodies can be very large, defining xxfi_body can
significantly impact filter performance.
-
- End-of-lines are represented as received from SMTP (normally CR/LF).
-
- Later filters will see body changes made by earlier ones.
-
- Message bodies may be sent in multiple chunks, with one call to
+
- End-of-lines are represented as received from SMTP (normally CR/LF).
+
- Later filters will see body changes made by earlier ones.
+
- Message bodies may be sent in multiple chunks, with one call to
xxfi_body per chunk.
-
- |
-
- |
+Return
+SMFIS_SKIP
+if a milter has received sufficiently many
+body chunks to make a decision,
+but still wants to invoke
+message modification functions that are only allowed to be called from
+xxfi_eom().
+Note: the milter must
+negotiate
+this behavior with the MTA, i.e., it must check whether
+the protocol action
+SMFIP_SKIP
+is available and if so, the milter must request it.
+
+
+
+
-
-
-Copyright (c) 2000-2003 Sendmail, Inc. and its suppliers.
+
+
+Copyright (c) 2000-2003, 2007 Sendmail, Inc. and its suppliers.
All rights reserved.
-
+
By using this file, you agree to the terms and conditions set
forth in the LICENSE.
-
-
-
+
+
+
diff --git a/contrib/sendmail/libmilter/docs/xxfi_close.html b/contrib/sendmail/libmilter/docs/xxfi_close.html
index 99b36e66acc7..2c2ae778f0da 100644
--- a/contrib/sendmail/libmilter/docs/xxfi_close.html
+++ b/contrib/sendmail/libmilter/docs/xxfi_close.html
@@ -1,52 +1,52 @@
-
-xxfi_close
-
+
+xxfi_close
+
-xxfi_close
+xxfi_close
-
+
-SYNOPSIS |
-
+SYNOPSIS |
+
#include <libmilter/mfapi.h>
sfsistat (*xxfi_close)(
- SMFICTX * ctx
+ SMFICTX *ctx
);
-
+
The current connection is being closed.
- |
+ |
-DESCRIPTION |
-
-
-Called When |
-xxfi_close is always called once at the end of each connection. |
-
-
-Default Behavior |
-Do nothing; return SMFIS_CONTINUE. |
-
-
+ |
---|
DESCRIPTION |
+
+
+Called When |
+xxfi_close is always called once at the end of each connection. |
+
+
+Default Behavior |
+Do nothing; return SMFIS_CONTINUE. |
+
+
- |
---|
ARGUMENTS |
-
- Argument | Description |
- ctx |
- Opaque context structure.
- |
-
- |
+ARGUMENTS |
+
+ Argument | Description |
+ ctx |
+ Opaque context structure.
+ |
+
+ |
-
-NOTES |
-
-
-- xxfi_close may be called "out-of-order", i.e. before even the
+
+NOTES |
+
+
+- xxfi_close may be called "out-of-order", i.e. before even the
xxfi_connect is called.
After a connection is established by the MTA to the filter,
if the MTA decides this connection's traffic will be discarded
@@ -58,24 +58,24 @@ and developers should anticipate this possibility when crafting their
xxfi_close code.
In particular, it is incorrect to assume the private context pointer
will be something other than NULL in this callback.
-
- xxfi_close is called on close even if the previous mail
+
- xxfi_close is called on close even if the previous mail
transaction was aborted.
-
- xxfi_close is responsible for freeing any resources allocated on a
+
- xxfi_close is responsible for freeing any resources allocated on a
per-connection basis.
-
- Since the connection is already closing, the return value is
+
- Since the connection is already closing, the return value is
currently ignored.
-
- |
-
- |
+
+
+
+
-
-
+
+
Copyright (c) 2000, 2003, 2004 Sendmail, Inc. and its suppliers.
All rights reserved.
-
+
By using this file, you agree to the terms and conditions set
forth in the LICENSE.
-
-
-
+
+
+
diff --git a/contrib/sendmail/libmilter/docs/xxfi_connect.html b/contrib/sendmail/libmilter/docs/xxfi_connect.html
index b39bc946f1bc..87d5eeb0b53c 100644
--- a/contrib/sendmail/libmilter/docs/xxfi_connect.html
+++ b/contrib/sendmail/libmilter/docs/xxfi_connect.html
@@ -1,113 +1,121 @@
-
-xxfi_connect
-
+
+xxfi_connect
+
-xxfi_connect
+xxfi_connect
-
+
-SYNOPSIS |
-
+SYNOPSIS |
+
#include <libmilter/mfapi.h>
sfsistat (*xxfi_connect)(
SMFICTX *ctx,
char *hostname,
_SOCK_ADDR *hostaddr);
-
- |
+
+ |
-DESCRIPTION |
-
-
-Called When |
-Once, at the start of each SMTP connection. |
-
-
-Default Behavior |
-Do nothing; return SMFIS_CONTINUE. |
-
-
+ |
---|
DESCRIPTION |
+
+
+Called When |
+Once, at the start of each SMTP connection. |
+
+
+Default Behavior |
+Do nothing; return SMFIS_CONTINUE. |
+
+
- |
---|
ARGUMENTS |
-
- Argument | Description |
- ctx |
- the opaque context structure.
- |
- hostname |
- the host name of the message sender, as determined by a
- reverse lookup on the host address. If the reverse lookup
- fails, hostname will contain the message sender's IP
- address enclosed in square brackets (e.g. `[a.b.c.d]').
- |
- hostaddr |
- the host address, as determined by a getpeername() call on the SMTP socket.
- NULL if the type is not supported in the current version or if
+ | ARGUMENTS |
+
+ Argument | Description |
+ ctx |
+ the opaque context structure.
+ |
+ hostname |
+ the host name of the message sender, as determined by a
+ reverse lookup on the host address.
+ If the reverse lookup fails
+ or if none of the IP addresses of the resolved host name
+ matches the original IP address,
+ hostname will contain the message sender's IP
+ address enclosed in square brackets (e.g. `[a.b.c.d]').
+ If the SMTP connection is made via stdin the value is
+ localhost .
+ |
+ hostaddr |
+ the host address,
+ as determined by a getpeername(2) call on the SMTP socket.
+ NULL if the type is not supported in the current version or if
the SMTP connection is made via stdin.
- |
-
- |
+
+
+ |
-
-NOTES |
-If an earlier filter rejects the connection in its xxfi_connect()
-routine, this filter's xxfi_connect() will not be called. |
-
-
+
+NOTES |
+If an earlier filter rejects the connection in its xxfi_connect()
+routine, this filter's xxfi_connect() will not be called. |
+
+
-
-
-Copyright (c) 2000-2001, 2003 Sendmail, Inc. and its suppliers.
+
+
+Copyright (c) 2000-2001, 2003, 2007 Sendmail, Inc. and its suppliers.
All rights reserved.
-
+
By using this file, you agree to the terms and conditions set
forth in the LICENSE.
-
-
-
+
+
+
diff --git a/contrib/sendmail/libmilter/docs/xxfi_data.html b/contrib/sendmail/libmilter/docs/xxfi_data.html
new file mode 100644
index 000000000000..2633ee5f0f56
--- /dev/null
+++ b/contrib/sendmail/libmilter/docs/xxfi_data.html
@@ -0,0 +1,89 @@
+
+xxfi_data
+
+
+xxfi_data
+
+
+
+SYNOPSIS |
+
+#include <libmilter/mfapi.h>
+sfsistat (*xxfi_data)(
+ SMFICTX *ctx
+);
+
+Handle the DATA command.
+ |
+
+
+DESCRIPTION |
+
+
+Called When |
+xxfi_data is called when the client uses the DATA command.
+ |
+
+Default Behavior |
+Do nothing; return SMFIS_CONTINUE. |
+
+
+
+
+ |
---|
ARGUMENTS |
+
+ Argument | Description |
+ ctx |
+ Opaque context structure.
+ |
+
+ |
+
+
+
+SPECIAL RETURN VALUES |
+
+ Return value | Description |
+
+ SMFIS_TEMPFAIL |
+ Reject this message with a temporary error.
+ |
+
+
+ SMFIS_REJECT |
+ Reject this message.
+ |
+
+
+ SMFIS_DISCARD |
+ Accept and silently discard this message.
+ |
+
+
+ SMFIS_ACCEPT |
+ Accept this message.
+ |
+
+
+ |
+
+
+
+NOTES |
+For more details on ESMTP responses, please see RFC
+1869. |
+
+
+
+
+
+Copyright (c) 2006 Sendmail, Inc. and its suppliers.
+All rights reserved.
+
+By using this file, you agree to the terms and conditions set
+forth in the LICENSE.
+
+
+
diff --git a/contrib/sendmail/libmilter/docs/xxfi_envfrom.html b/contrib/sendmail/libmilter/docs/xxfi_envfrom.html
index df9e0fc2cd95..6ae88cff6fc0 100644
--- a/contrib/sendmail/libmilter/docs/xxfi_envfrom.html
+++ b/contrib/sendmail/libmilter/docs/xxfi_envfrom.html
@@ -1,95 +1,97 @@
-
-xxfi_envfrom
-
+
+xxfi_envfrom
+
-xxfi_envfrom
+xxfi_envfrom
-
+
-SYNOPSIS |
-
+SYNOPSIS |
+
#include <libmilter/mfapi.h>
sfsistat (*xxfi_envfrom)(
- SMFICTX * ctx,
- char ** argv
+ SMFICTX *ctx,
+ char **argv
);
-
-Handle the envelope FROM command.
- |
+
+Handle the MAIL (envelope sender) command.
+ |
-DESCRIPTION |
-
-
-Called When |
-xxfi_envfrom is called once at the beginning of each message, before xxfi_envrcpt. |
-
-
-Default Behavior |
-Do nothing; return SMFIS_CONTINUE. |
-
-
+ |
---|
DESCRIPTION |
+
+
+Called When |
+xxfi_envfrom is called once at the beginning of each message
+(MAIL command),
+before xxfi_envrcpt. |
+
+
+Default Behavior |
+Do nothing; return SMFIS_CONTINUE. |
+
+
- |
---|
ARGUMENTS |
-
- Argument | Description |
- ctx |
- Opaque context structure.
- |
- argv |
- Null-terminated SMTP command arguments;
+ | ARGUMENTS |
+
+ Argument | Description |
+ ctx |
+ Opaque context structure.
+ |
+ argv |
+ Null-terminated SMTP command arguments;
argv[0] is guaranteed to be the sender address.
Later arguments are the ESMTP arguments.
- |
-
- |
+
+
+ |
-
-SPECIAL RETURN VALUES |
-
- Return value | Description |
-
- SMFIS_TEMPFAIL |
- Reject this sender and message with a temporary error; a new sender (and hence a new message) may subsequently be specified. xxfi_abort is not called.
- |
-
-
- SMFIS_REJECT |
- Reject this sender and message; a new sender/message may be specified. xxfi_abort is not called.
- |
-
-
- SMFIS_DISCARD |
- Accept and silently discard this message. xxfi_abort is not called.
- |
-
-
- SMFIS_ACCEPT |
- Accept this message. xxfi_abort is not called.
- |
-
-
- |
+
+SPECIAL RETURN VALUES |
+
+ Return value | Description |
+
+ SMFIS_TEMPFAIL |
+ Reject this sender and message with a temporary error; a new sender (and hence a new message) may subsequently be specified. xxfi_abort is not called.
+ |
+
+
+ SMFIS_REJECT |
+ Reject this sender and message; a new sender/message may be specified. xxfi_abort is not called.
+ |
+
+
+ SMFIS_DISCARD |
+ Accept and silently discard this message. xxfi_abort is not called.
+ |
+
+
+ SMFIS_ACCEPT |
+ Accept this message. xxfi_abort is not called.
+ |
+
+
+ |
-
-NOTES |
-For more details on ESTMP responses, please see RFC
-1869. |
-
-
+
+NOTES |
+For more details on ESMTP responses, please see RFC
+1869. |
+
+
-
-
-Copyright (c) 2000, 2003 Sendmail, Inc. and its suppliers.
+
+
+Copyright (c) 2000, 2003, 2006 Sendmail, Inc. and its suppliers.
All rights reserved.
-
+
By using this file, you agree to the terms and conditions set
forth in the LICENSE.
-
-
-
+
+
+
diff --git a/contrib/sendmail/libmilter/docs/xxfi_envrcpt.html b/contrib/sendmail/libmilter/docs/xxfi_envrcpt.html
index e0c609421b91..9fb4ce873a8d 100644
--- a/contrib/sendmail/libmilter/docs/xxfi_envrcpt.html
+++ b/contrib/sendmail/libmilter/docs/xxfi_envrcpt.html
@@ -1,97 +1,97 @@
-
-xxfi_envrcpt
-
+
+xxfi_envrcpt
+
-xxfi_envrcpt
+xxfi_envrcpt
-
+
-SYNOPSIS |
-
+SYNOPSIS |
+
#include <libmilter/mfapi.h>
sfsistat (*xxfi_envrcpt)(
- SMFICTX * ctx,
- char ** argv
+ SMFICTX *ctx,
+ char **argv
);
-
+
Handle the envelope RCPT command.
- |
+ |
-DESCRIPTION |
-
-
-Called When |
-xxfi_envrcpt is called once per recipient, hence one or more times per message, immediately after xxfi_envfrom. |
-
-
-Default Behavior |
-Do nothing; return SMFIS_CONTINUE. |
-
-
+ |
---|
DESCRIPTION |
+
+
+Called When |
+xxfi_envrcpt is called once per recipient, hence one or more times per message, immediately after xxfi_envfrom. |
+
+
+Default Behavior |
+Do nothing; return SMFIS_CONTINUE. |
+
+
- |
---|
ARGUMENTS |
-
- Argument | Description |
- ctx |
- Opaque context structure.
- |
- argv |
- Null-terminated SMTP command arguments;
+ | ARGUMENTS |
+
+ Argument | Description |
+ ctx |
+ Opaque context structure.
+ |
+ argv |
+ Null-terminated SMTP command arguments;
argv[0] is guaranteed to be the recipient address.
Later arguments are the ESMTP arguments.
- |
-
- |
+
+
+ |
-
-SPECIAL RETURN VALUES |
-
- Return value | Description |
-
- SMFIS_TEMPFAIL |
- Temporarily fail for this particular recipient; further recipients
- may still be sent. xxfi_abort is not called.
- |
-
-
- SMFIS_REJECT |
- Reject this particular recipient; further recipients may still be sent.
- xxfi_abort is not called.
- |
-
-
- SMFIS_DISCARD |
- Accept and discard the message. xxfi_abort will be called.
- |
-
-
- SMFIS_ACCEPT |
- Accept recipient. xxfi_abort will not be called.
- |
-
-
- |
+
+SPECIAL RETURN VALUES |
+
+ Return value | Description |
+
+ SMFIS_TEMPFAIL |
+ Temporarily fail for this particular recipient; further recipients
+ may still be sent. xxfi_abort is not called.
+ |
+
+
+ SMFIS_REJECT |
+ Reject this particular recipient; further recipients may still be sent.
+ xxfi_abort is not called.
+ |
+
+
+ SMFIS_DISCARD |
+ Accept and discard the message. xxfi_abort will be called.
+ |
+
+
+ SMFIS_ACCEPT |
+ Accept recipient. xxfi_abort will not be called.
+ |
+
+
+ |
-
-NOTES |
-For more details on ESTMP responses, please see RFC
-1869. |
-
-
+
+NOTES |
+For more details on ESMTP responses, please see RFC
+1869. |
+
+
-
-
+
+
Copyright (c) 2000, 2003 Sendmail, Inc. and its suppliers.
All rights reserved.
-
+
By using this file, you agree to the terms and conditions set
forth in the LICENSE.
-
-
-
+
+
+
diff --git a/contrib/sendmail/libmilter/docs/xxfi_eoh.html b/contrib/sendmail/libmilter/docs/xxfi_eoh.html
index 350ca969f56f..2a74e7af57c5 100644
--- a/contrib/sendmail/libmilter/docs/xxfi_eoh.html
+++ b/contrib/sendmail/libmilter/docs/xxfi_eoh.html
@@ -1,56 +1,56 @@
-
-xxfi_eoh
-
+
+xxfi_eoh
+
-xxfi_eoh
+xxfi_eoh
-
+
-SYNOPSIS |
-
+SYNOPSIS |
+
#include <libmilter/mfapi.h>
sfsistat (*xxfi_eoh)(
- SMFICTX * ctx
+ SMFICTX *ctx
);
-
+
Handle the end of message headers.
- |
+ |
-DESCRIPTION |
-
-
-Called When |
-xxfi_eoh is called once after all headers have been sent and processed.
- |
-
-
-Default Behavior |
-Do nothing; return SMFIS_CONTINUE. |
-
-
+ |
---|
DESCRIPTION |
+
+
+Called When |
+xxfi_eoh is called once after all headers have been sent and processed.
+ |
+
+
+Default Behavior |
+Do nothing; return SMFIS_CONTINUE. |
+
+
- |
---|
ARGUMENTS |
-
- Argument | Description |
- ctx |
- Opaque context structure.
- |
-
- |
+ARGUMENTS |
+
+ Argument | Description |
+ ctx |
+ Opaque context structure.
+ |
+
+ |
-
+
-
-
+
+
Copyright (c) 2000, 2003 Sendmail, Inc. and its suppliers.
All rights reserved.
-
+
By using this file, you agree to the terms and conditions set
forth in the LICENSE.
-
-
-
+
+
+
diff --git a/contrib/sendmail/libmilter/docs/xxfi_eom.html b/contrib/sendmail/libmilter/docs/xxfi_eom.html
index 78c6943babb1..b5aee8b856b5 100644
--- a/contrib/sendmail/libmilter/docs/xxfi_eom.html
+++ b/contrib/sendmail/libmilter/docs/xxfi_eom.html
@@ -1,61 +1,62 @@
-
-xxfi_eom
-
+
+xxfi_eom
+
-xxfi_eom
+xxfi_eom
-
+
-SYNOPSIS |
-
+SYNOPSIS |
+
#include <libmilter/mfapi.h>
sfsistat (*xxfi_eom)(
- SMFICTX * ctx
+ SMFICTX *ctx
);
-
+
End of a message.
- |
+ |
-DESCRIPTION |
-
-
-Called When |
-xxfi_eom is called once after all calls to xxfi_body for a given message. |
-
-
-Default Behavior |
-Do nothing; return SMFIS_CONTINUE. |
-
-
+ |
---|
DESCRIPTION |
+
+
+Called When |
+xxfi_eom is called once after all calls to xxfi_body for a given message. |
+
+
+Default Behavior |
+Do nothing; return SMFIS_CONTINUE. |
+
+
- |
---|
ARGUMENTS |
-
- Argument | Description |
- ctx |
- Opaque context structure.
- |
-
- |
+ARGUMENTS |
+
+ Argument | Description |
+ ctx |
+ Opaque context structure.
+ |
+
+ |
-
-NOTES |
-A filter is required to make all its modifications to the message headers, body, and envelope in xxfi_eom. Modifications are made via the smfi_* routines.
- |
-
-
+
+NOTES |
+A filter is required to make all its modifications to the message headers, body, and envelope in xxfi_eom.
+Modifications are made via the smfi_* routines.
+ |
+
+
-
-
+
+
Copyright (c) 2000, 2003 Sendmail, Inc. and its suppliers.
All rights reserved.
-
+
By using this file, you agree to the terms and conditions set
forth in the LICENSE.
-
-
-
+
+
+
diff --git a/contrib/sendmail/libmilter/docs/xxfi_header.html b/contrib/sendmail/libmilter/docs/xxfi_header.html
index 2111a739fdd9..8a5462fc3ff4 100644
--- a/contrib/sendmail/libmilter/docs/xxfi_header.html
+++ b/contrib/sendmail/libmilter/docs/xxfi_header.html
@@ -1,78 +1,111 @@
-
-xxfi_header
-
+
+xxfi_header
+
-xxfi_header
+xxfi_header
-
+
-SYNOPSIS |
-
+SYNOPSIS |
+
#include <libmilter/mfapi.h>
sfsistat (*xxfi_header)(
- SMFICTX * ctx,
- char * headerf,
- char * headerv
+ SMFICTX *ctx,
+ char *headerf,
+ char *headerv
);
-
+
Handle a message header.
- |
+ |
-DESCRIPTION |
-
-
-Called When |
-xxfi_header is called zero or more times between xxfi_envrcpt and xxfi_eoh, once per message header. |
-
-
-Default Behavior |
-Do nothing; return SMFIS_CONTINUE. |
-
-
+ |
---|
DESCRIPTION |
+
+
+Called When |
+xxfi_header is called once for each message header. |
+
+
+Default Behavior |
+Do nothing; return SMFIS_CONTINUE. |
+
+
- |
---|
ARGUMENTS |
-
- Argument | Description |
- ctx |
- Opaque context structure.
- |
- headerf |
- Header field name.
- |
- headerv |
- Header field value.
+ | ARGUMENTS |
+
+ Argument | Description |
+ ctx |
+ Opaque context structure.
+ |
+ headerf |
+ Header field name.
+ |
+ headerv |
+ Header field value.
The content of the header may include folded white space,
i.e., multiple lines with following white space
where lines are separated by LF (not CR/LF).
The trailing line terminator (CR/LF) is removed.
- |
-
- |
+
+
+ |
-
-NOTES |
-
-
-- Later filters will see header changes/additions made by earlier ones.
-
- For much more detail about header format, please see
-RFC 822
-
- |
-
-
+
+NOTES |
+
+
+- Starting with sendmail 8.14, spaces after the colon in a header
+field are preserved if requested using the flag
+
SMFIP_HDR_LEADSPC .
+That is, the header
-
-
+
+From: sender <f@example.com>
+To: user <t@example.com>
+Subject:no
+
+
+will be sent to a milter as
+
+
+"From", " sender <f@example.com>"
+"To", " user <t@example.com>"
+"Subject", "no"
+
+
+while previously
+(or without the flag
+SMFIP_HDR_LEADSPC )
+it was:
+
+
+"From", "sender <f@example.com>"
+"To", "user <t@example.com>"
+"Subject", "no"
+
+
+
+- Later filters will see header changes/additions made by earlier ones.
+
- For much more detail about header format, please see
+RFC 822
+and
+RFC 2822
+
+ |
+
+
+
+
+
Copyright (c) 2000, 2003, 2006 Sendmail, Inc. and its suppliers.
All rights reserved.
-
+
By using this file, you agree to the terms and conditions set
forth in the LICENSE.
-
-
-
+
+
+
diff --git a/contrib/sendmail/libmilter/docs/xxfi_helo.html b/contrib/sendmail/libmilter/docs/xxfi_helo.html
index e31585a4edc3..613cb1949a2b 100644
--- a/contrib/sendmail/libmilter/docs/xxfi_helo.html
+++ b/contrib/sendmail/libmilter/docs/xxfi_helo.html
@@ -1,64 +1,64 @@
-
-xxfi_helo
-
+
+xxfi_helo
+
-xxfi_helo
+xxfi_helo
-
+
-SYNOPSIS |
-
+SYNOPSIS |
+
#include <libmilter/mfapi.h>
sfsistat (*xxfi_helo)(
- SMFICTX * ctx,
- char * helohost
+ SMFICTX *ctx,
+ char *helohost
);
-
+
Handle the HELO/EHLO command.
- |
+ |
-DESCRIPTION |
-
-
-Called When | xxfi_helo is called whenever the client
+ | DESCRIPTION |
+
+
+Called When | xxfi_helo is called whenever the client
sends a HELO/EHLO command.
It may therefore be called several times or even not at all;
some restrictions can be imposed by the MTA configuration.
- |
-
-
-Default Behavior |
-Do nothing; return SMFIS_CONTINUE. |
-
-
+ |
+
+
+Default Behavior |
+Do nothing; return SMFIS_CONTINUE. |
+
+
- |
---|
ARGUMENTS |
-
- Argument | Description |
- ctx |
- Opaque context structure.
- |
- helohost |
- Value passed to HELO/EHLO command, which should be
+ | ARGUMENTS |
+
+ Argument | Description |
+ ctx |
+ Opaque context structure.
+ |
+ helohost |
+ Value passed to HELO/EHLO command, which should be
the domain name of the sending host (but is, in practice,
anything the sending host wants to send).
- |
-
- |
+
+
+ |
-
+
-
-
+
+
Copyright (c) 2000, 2003, 2005 Sendmail, Inc. and its suppliers.
All rights reserved.
-
+
By using this file, you agree to the terms and conditions set
forth in the LICENSE.
-
-
-
+
+
+
diff --git a/contrib/sendmail/libmilter/docs/xxfi_negotiate.html b/contrib/sendmail/libmilter/docs/xxfi_negotiate.html
new file mode 100644
index 000000000000..0f69f70791f1
--- /dev/null
+++ b/contrib/sendmail/libmilter/docs/xxfi_negotiate.html
@@ -0,0 +1,277 @@
+
+xxfi_negotiate
+
+
+xxfi_negotiate
+
+
+
+SYNOPSIS |
+
+#include <libmilter/mfapi.h>
+#include <libmilter/mfdef.h>
+sfsistat (*xxfi_negotiate)(
+ SMFICTX *ctx,
+ unsigned long f0,
+ unsigned long f1,
+ unsigned long f2,
+ unsigned long f3,
+ unsigned long *pf0,
+ unsigned long *pf1,
+ unsigned long *pf2,
+ unsigned long *pf3);
+
+ |
+
+DESCRIPTION |
+
+
+Called When |
+Once, at the start of each SMTP connection. |
+
+
+Default Behavior |
+Return SMFIS_ALL_OPTS to change nothing. |
+
+
+
+ |
---|
ARGUMENTS |
+
+ Argument | Description |
+ ctx |
+ the opaque context structure.
+ |
+ f0 |
+ the actions offered by the MTA.
+ |
+ f1 |
+ the protocol steps offered by the MTA.
+ | f2 |
+ for future extensions.
+ |
+ f3 |
+ for future extensions.
+ |
+ pf0 |
+ the actions requested by the milter.
+ |
+ pf1 |
+ the protocol steps requested by the milter.
+ | pf2 |
+ for future extensions.
+ |
+ pf3 |
+ for future extensions.
+ |
+
+ |
+
+
+
+SPECIAL RETURN VALUES |
+
+ Return value | Description |
+
+ SMFIS_ALL_OPTS |
+
+If a milter just wants to inspect the available protocol steps
+and actions, then it can return
+SMFIS_ALL_OPTS
+and the MTA will make all protocol steps and actions available
+to the milter.
+In this case, no values should be assigned to the output parameters
+pf0 - pf3
+as they will be ignored.
+ |
+
+
+ SMFIS_REJECT |
+ Milter startup fails and it will not be contacted again
+(for the current connection).
+ |
+
+
+ SMFIS_CONTINUE |
+ Continue processing.
+ In this case the milter must set all output parameters
+ pf0 - pf3 .
+ See below for an explanation how to set those output parameters.
+ |
+
+
+ |
+
+
+
+NOTES |
+This function allows a milter to dynamically determine and
+request operations and actions during startup.
+In previous versions, the actions (f0) were fixed in the
+flags field of the
+smfiDesc
+structure
+and the protocol steps (f1) were implicitly derived by checking whether
+a callback was defined.
+Due to the extensions in the new milter version,
+such a static selection will not work if a milter requires
+new actions that are not available when talking to an older MTA.
+Hence in the negotiation callback a milter can determine
+which operations are available and dynamically select
+those which it needs and which are offered.
+If some operations are not available, the milter may either fall back
+to an older mode or abort the session and ask the user to upgrade.
+
+
+
+
+Protocol steps
+(f1 , *pf1 ):
+
+SMFIP_RCPT_REJ :
+By setting this bit, a milter can request that the
+MTA should also send RCPT commands that have been rejected
+because the user is unknown (or similar reasons), but not those
+which have been rejected because of syntax errors etc.
+If a milter requests this protocol step,
+then it should check the macro
+{rcpt_mailer} :
+if that is set to
+error ,
+then the recipient will be rejected by the MTA.
+Usually the macros
+{rcpt_host} and {rcpt_addr}
+will contain an enhanced status code and an error text
+in that case, respectively.
+
+SMFIP_SKIP
+indicates that the MTA understand the
+SMFIS_SKIP
+return code.
+
+SMFIP_NR_*
+indicates that the MTA understand the
+SMFIS_NOREPLY
+return code.
+There are flags for various protocol stages:
+
+
+
+SMFIP_HDR_LEADSPC
+indicates that the MTA can send header values with leading space intact.
+If this protocol step is requested, then the MTA will also not add a leading
+space to headers when they are added, inserted, or changed.
+
+
+- The MTA can be instructed not to send information about
+various SMTP stages, these flags start with:
+
SMFIP_NO* .
+
+
+For each of these xxfi_* callbacks that a milter does not use
+the corresponding flag should be set in
+*pf1 .
+
+
+
+
+The available actions
+(f0 , *pf0 )
+are
+
+described
+elsewhere (xxfi_flags).
+
+
+If a milter returns SMFIS_CONTINUE, then it must
+set the desired actions and protocol steps
+via the (output) parameters
+pf0
+and
+pf1
+(which correspond to
+f0
+and
+f1 , respectively).
+The (output) parameters
+pf2 and
+pf3
+should be set to 0 for compatibility with future versions.
+
+ |
+
+
+
+
+
+Copyright (c) 2006 Sendmail, Inc. and its suppliers.
+All rights reserved.
+
+By using this file, you agree to the terms and conditions set
+forth in the LICENSE.
+
+
+
diff --git a/contrib/sendmail/libmilter/docs/xxfi_unknown.html b/contrib/sendmail/libmilter/docs/xxfi_unknown.html
new file mode 100644
index 000000000000..b1cd38a12978
--- /dev/null
+++ b/contrib/sendmail/libmilter/docs/xxfi_unknown.html
@@ -0,0 +1,84 @@
+
+xxfi_unknown
+
+
+xxfi_unknown
+
+
+
+SYNOPSIS |
+
+#include <libmilter/mfapi.h>
+sfsistat (*xxfi_unknown)(
+ SMFICTX *ctx,
+ const char *arg
+);
+
+Handle unknown and unimplemented SMTP commands.
+ |
+
+
+DESCRIPTION |
+
+
+Called When |
+xxfi_unknown is called when the client uses an SMTP command
+that is either unknown or not implemented by the MTA.
+ |
+
+Default Behavior |
+Do nothing; return SMFIS_CONTINUE. |
+
+
+
+
+ |
---|
ARGUMENTS |
+
+ Argument | Description |
+ ctx |
+ Opaque context structure.
+ |
+ arg |
+ SMTP command including all arguments.
+ |
+
+ |
+
+
+
+SPECIAL RETURN VALUES |
+
+ Return value | Description |
+
+ SMFIS_TEMPFAIL |
+ Reject this message with a temporary error.
+ |
+
+
+ SMFIS_REJECT |
+ Reject this message.
+ |
+
+
+ |
+
+
+
+NOTES |
+The SMTP command will always be rejected by the server,
+it is only possible to return a different error code.
+ |
+
+
+
+
+Copyright (c) 2006 Sendmail, Inc. and its suppliers.
+All rights reserved.
+
+By using this file, you agree to the terms and conditions set
+forth in the LICENSE.
+
+
+
diff --git a/contrib/sendmail/libmilter/engine.c b/contrib/sendmail/libmilter/engine.c
index 8b4bed07adf3..a61cf56130c0 100644
--- a/contrib/sendmail/libmilter/engine.c
+++ b/contrib/sendmail/libmilter/engine.c
@@ -9,7 +9,7 @@
*/
#include
-SM_RCSID("@(#)$Id: engine.c,v 8.121 2006/04/18 21:01:46 ca Exp $")
+SM_RCSID("@(#)$Id: engine.c,v 8.157 2007/03/26 18:10:04 ca Exp $")
#include "libmilter.h"
@@ -56,7 +56,7 @@ typedef struct cmdfct_t cmdfct;
/* not needed right now, done via return code instead */
#define CT_KEEP 0x0004 /* keep buffer (contains symbols) */
-#define CT_END 0x0008 /* start replying */
+#define CT_END 0x0008 /* last command of session, stop replying */
/* index in macro array: macros only for these commands */
#define CI_NONE (-1)
@@ -64,9 +64,33 @@ typedef struct cmdfct_t cmdfct;
#define CI_HELO 1
#define CI_MAIL 2
#define CI_RCPT 3
-#define CI_EOM 4
-#if CI_EOM >= MAX_MACROS_ENTRIES
-ERROR: do not compile with CI_EOM >= MAX_MACROS_ENTRIES
+#define CI_DATA 4
+#define CI_EOM 5
+#define CI_EOH 6
+#define CI_LAST CI_EOH
+#if CI_LAST < CI_DATA
+ERROR: do not compile with CI_LAST < CI_DATA
+#endif
+#if CI_LAST < CI_EOM
+ERROR: do not compile with CI_LAST < CI_EOM
+#endif
+#if CI_LAST < CI_EOH
+ERROR: do not compile with CI_LAST < CI_EOH
+#endif
+#if CI_LAST < CI_ENVRCPT
+ERROR: do not compile with CI_LAST < CI_ENVRCPT
+#endif
+#if CI_LAST < CI_ENVFROM
+ERROR: do not compile with CI_LAST < CI_ENVFROM
+#endif
+#if CI_LAST < CI_HELO
+ERROR: do not compile with CI_LAST < CI_HELO
+#endif
+#if CI_LAST < CI_CONNECT
+ERROR: do not compile with CI_LAST < CI_CONNECT
+#endif
+#if CI_LAST >= MAX_MACROS_ENTRIES
+ERROR: do not compile with CI_LAST >= MAX_MACROS_ENTRIES
#endif
/* function prototypes */
@@ -80,12 +104,8 @@ static int st_helo __P((genarg *));
static int st_header __P((genarg *));
static int st_sender __P((genarg *));
static int st_rcpt __P((genarg *));
-#if SMFI_VERSION > 2
static int st_unknown __P((genarg *));
-#endif /* SMFI_VERSION > 2 */
-#if SMFI_VERSION > 3
static int st_data __P((genarg *));
-#endif /* SMFI_VERSION > 3 */
static int st_eoh __P((genarg *));
static int st_quit __P((genarg *));
static int sendreply __P((sfsistat, socket_t, struct timeval *, SMFICTX_PTR));
@@ -94,6 +114,10 @@ static bool trans_ok __P((int, int));
static char **dec_argv __P((char *, size_t));
static int dec_arg2 __P((char *, size_t, char **, char **));
+#if _FFR_WORKERS_POOL
+static bool mi_rd_socket_ready __P((int));
+#endif /* _FFR_WORKERS_POOL */
+
/* states */
#define ST_NONE (-1)
#define ST_INIT 0 /* initial state */
@@ -110,8 +134,9 @@ static int dec_arg2 __P((char *, size_t, char **, char **));
#define ST_QUIT 11 /* quit */
#define ST_ABRT 12 /* abort */
#define ST_UNKN 13 /* unknown SMTP command */
-#define ST_LAST ST_UNKN /* last valid state */
-#define ST_SKIP 15 /* not a state but required for the state table */
+#define ST_Q_NC 14 /* quit, new connection follows */
+#define ST_LAST ST_Q_NC /* last valid state */
+#define ST_SKIP 16 /* not a state but required for the state table */
/* in a mail transaction? must be before eom according to spec. */
#define ST_IN_MAIL(st) ((st) >= ST_MAIL && (st) < ST_ENDM)
@@ -138,32 +163,35 @@ static int dec_arg2 __P((char *, size_t, char **, char **));
#define NX_HDRS (MI_MASK(ST_EOHS) | MI_MASK(ST_HDRS) | MI_MASK(ST_ABRT))
#define NX_EOHS (MI_MASK(ST_BODY) | MI_MASK(ST_ENDM) | MI_MASK(ST_ABRT))
#define NX_BODY (MI_MASK(ST_ENDM) | MI_MASK(ST_BODY) | MI_MASK(ST_ABRT))
-#define NX_ENDM (MI_MASK(ST_QUIT) | MI_MASK(ST_MAIL) | MI_MASK(ST_UNKN))
+#define NX_ENDM (MI_MASK(ST_QUIT) | MI_MASK(ST_MAIL) | MI_MASK(ST_UNKN) | \
+ MI_MASK(ST_Q_NC))
#define NX_QUIT 0
#define NX_ABRT 0
#define NX_UNKN (MI_MASK(ST_HELO) | MI_MASK(ST_MAIL) | \
MI_MASK(ST_RCPT) | MI_MASK(ST_ABRT) | \
MI_MASK(ST_DATA) | \
MI_MASK(ST_BODY) | MI_MASK(ST_UNKN) | \
- MI_MASK(ST_ABRT) | MI_MASK(ST_QUIT))
+ MI_MASK(ST_ABRT) | MI_MASK(ST_QUIT) | MI_MASK(ST_Q_NC))
+#define NX_Q_NC (MI_MASK(ST_CONN) | MI_MASK(ST_UNKN))
#define NX_SKIP MI_MASK(ST_SKIP)
static int next_states[] =
{
- NX_INIT,
- NX_OPTS,
- NX_CONN,
- NX_HELO,
- NX_MAIL,
- NX_RCPT,
- NX_DATA,
- NX_HDRS,
- NX_EOHS,
- NX_BODY,
- NX_ENDM,
- NX_QUIT,
- NX_ABRT,
- NX_UNKN
+ NX_INIT
+ , NX_OPTS
+ , NX_CONN
+ , NX_HELO
+ , NX_MAIL
+ , NX_RCPT
+ , NX_DATA
+ , NX_HDRS
+ , NX_EOHS
+ , NX_BODY
+ , NX_ENDM
+ , NX_QUIT
+ , NX_ABRT
+ , NX_UNKN
+ , NX_Q_NC
};
#define SIZE_NEXT_STATES (sizeof(next_states) / sizeof(next_states[0]))
@@ -171,31 +199,32 @@ static int next_states[] =
/* commands received by milter */
static cmdfct cmds[] =
{
-{SMFIC_ABORT, CM_ARG0, ST_ABRT, CT_CONT, CI_NONE, st_abortfct },
-{SMFIC_MACRO, CM_ARGV, ST_NONE, CT_KEEP, CI_NONE, st_macros },
-{SMFIC_BODY, CM_ARG1, ST_BODY, CT_CONT, CI_NONE, st_bodychunk },
-{SMFIC_CONNECT, CM_ARG2, ST_CONN, CT_CONT, CI_CONN, st_connectinfo },
-{SMFIC_BODYEOB, CM_ARG1, ST_ENDM, CT_CONT, CI_EOM, st_bodyend },
-{SMFIC_HELO, CM_ARG1, ST_HELO, CT_CONT, CI_HELO, st_helo },
-{SMFIC_HEADER, CM_ARG2, ST_HDRS, CT_CONT, CI_NONE, st_header },
-{SMFIC_MAIL, CM_ARGV, ST_MAIL, CT_CONT, CI_MAIL, st_sender },
-{SMFIC_OPTNEG, CM_ARGO, ST_OPTS, CT_CONT, CI_NONE, st_optionneg },
-{SMFIC_EOH, CM_ARG0, ST_EOHS, CT_CONT, CI_NONE, st_eoh },
-{SMFIC_QUIT, CM_ARG0, ST_QUIT, CT_END, CI_NONE, st_quit },
-#if SMFI_VERSION > 3
-{SMFIC_DATA, CM_ARG0, ST_DATA, CT_CONT, CI_NONE, st_data },
-#endif /* SMFI_VERSION > 3 */
-{SMFIC_RCPT, CM_ARGV, ST_RCPT, CT_IGNO, CI_RCPT, st_rcpt }
-#if SMFI_VERSION > 2
-,{SMFIC_UNKNOWN,CM_ARG1, ST_UNKN, CT_IGNO, CI_NONE, st_unknown }
-#endif /* SMFI_VERSION > 2 */
+ {SMFIC_ABORT, CM_ARG0, ST_ABRT, CT_CONT, CI_NONE, st_abortfct }
+, {SMFIC_MACRO, CM_ARGV, ST_NONE, CT_KEEP, CI_NONE, st_macros }
+, {SMFIC_BODY, CM_ARG1, ST_BODY, CT_CONT, CI_NONE, st_bodychunk }
+, {SMFIC_CONNECT, CM_ARG2, ST_CONN, CT_CONT, CI_CONN, st_connectinfo }
+, {SMFIC_BODYEOB, CM_ARG1, ST_ENDM, CT_CONT, CI_EOM, st_bodyend }
+, {SMFIC_HELO, CM_ARG1, ST_HELO, CT_CONT, CI_HELO, st_helo }
+, {SMFIC_HEADER, CM_ARG2, ST_HDRS, CT_CONT, CI_NONE, st_header }
+, {SMFIC_MAIL, CM_ARGV, ST_MAIL, CT_CONT, CI_MAIL, st_sender }
+, {SMFIC_OPTNEG, CM_ARGO, ST_OPTS, CT_CONT, CI_NONE, st_optionneg }
+, {SMFIC_EOH, CM_ARG0, ST_EOHS, CT_CONT, CI_EOH, st_eoh }
+, {SMFIC_QUIT, CM_ARG0, ST_QUIT, CT_END, CI_NONE, st_quit }
+, {SMFIC_DATA, CM_ARG0, ST_DATA, CT_CONT, CI_DATA, st_data }
+, {SMFIC_RCPT, CM_ARGV, ST_RCPT, CT_IGNO, CI_RCPT, st_rcpt }
+, {SMFIC_UNKNOWN, CM_ARG1, ST_UNKN, CT_IGNO, CI_NONE, st_unknown }
+, {SMFIC_QUIT_NC, CM_ARG0, ST_Q_NC, CT_CONT, CI_NONE, st_quit }
};
-/* additional (internal) reply codes */
+/*
+** Additional (internal) reply codes;
+** must be coordinated wit libmilter/mfapi.h
+*/
+
#define _SMFIS_KEEP 20
#define _SMFIS_ABORT 21
#define _SMFIS_OPTIONS 22
-#define _SMFIS_NOREPLY 23
+#define _SMFIS_NOREPLY SMFIS_NOREPLY
#define _SMFIS_FAIL (-1)
#define _SMFIS_NONE (-2)
@@ -208,6 +237,7 @@ static cmdfct cmds[] =
** Returns:
** MI_FAILURE/MI_SUCCESS
*/
+
int
mi_engine(ctx)
SMFICTX_PTR ctx;
@@ -232,8 +262,17 @@ mi_engine(ctx)
arg.a_ctx = ctx;
sd = ctx->ctx_sd;
fi_abort = ctx->ctx_smfi->xxfi_abort;
+#if _FFR_WORKERS_POOL
+ curstate = ctx->ctx_state;
+ if (curstate == ST_INIT)
+ {
+ mi_clr_macros(ctx, 0);
+ fix_stm(ctx);
+ }
+#else /* _FFR_WORKERS_POOL */
mi_clr_macros(ctx, 0);
fix_stm(ctx);
+#endif /* _FFR_WORKERS_POOL */
r = _SMFIS_NONE;
do
{
@@ -244,8 +283,8 @@ mi_engine(ctx)
if (mi_stop() == MILTER_ABRT)
{
if (ctx->ctx_dbg > 3)
- sm_dprintf("[%d] milter_abort\n",
- (int) ctx->ctx_id);
+ sm_dprintf("[%ld] milter_abort\n",
+ (long) ctx->ctx_id);
ret = MI_FAILURE;
break;
}
@@ -260,14 +299,23 @@ mi_engine(ctx)
** if the code "break"s out of the loop.
*/
+#if _FFR_WORKERS_POOL
+ /* Is the socket ready to be read ??? */
+ if (!mi_rd_socket_ready(sd))
+ {
+ ret = MI_CONTINUE;
+ break;
+ }
+#endif /* _FFR_WORKERS_POOL */
+
r = _SMFIS_NONE;
if ((buf = mi_rd_cmd(sd, &timeout, &cmd, &len,
ctx->ctx_smfi->xxfi_name)) == NULL &&
cmd < SMFIC_VALIDCMD)
{
if (ctx->ctx_dbg > 5)
- sm_dprintf("[%d] mi_engine: mi_rd_cmd error (%x)\n",
- (int) ctx->ctx_id, (int) cmd);
+ sm_dprintf("[%ld] mi_engine: mi_rd_cmd error (%x)\n",
+ (long) ctx->ctx_id, (int) cmd);
/*
** eof is currently treated as failure ->
@@ -279,8 +327,8 @@ mi_engine(ctx)
break;
}
if (ctx->ctx_dbg > 4)
- sm_dprintf("[%d] got cmd '%c' len %d\n",
- (int) ctx->ctx_id, cmd, (int) len);
+ sm_dprintf("[%ld] got cmd '%c' len %d\n",
+ (long) ctx->ctx_id, cmd, (int) len);
for (i = 0; i < ncmds; i++)
{
if (cmd == cmds[i].cm_cmd)
@@ -290,8 +338,8 @@ mi_engine(ctx)
{
/* unknown command */
if (ctx->ctx_dbg > 1)
- sm_dprintf("[%d] cmd '%c' unknown\n",
- (int) ctx->ctx_id, cmd);
+ sm_dprintf("[%ld] cmd '%c' unknown\n",
+ (long) ctx->ctx_id, cmd);
ret = MI_FAILURE;
break;
}
@@ -299,8 +347,8 @@ mi_engine(ctx)
{
/* stop for now */
if (ctx->ctx_dbg > 1)
- sm_dprintf("[%d] cmd '%c' not impl\n",
- (int) ctx->ctx_id, cmd);
+ sm_dprintf("[%ld] cmd '%c' not impl\n",
+ (long) ctx->ctx_id, cmd);
ret = MI_FAILURE;
break;
}
@@ -308,15 +356,15 @@ mi_engine(ctx)
/* is new state ok? */
newstate = cmds[i].cm_next;
if (ctx->ctx_dbg > 5)
- sm_dprintf("[%d] cur %x new %x nextmask %x\n",
- (int) ctx->ctx_id,
+ sm_dprintf("[%ld] cur %x new %x nextmask %x\n",
+ (long) ctx->ctx_id,
curstate, newstate, next_states[curstate]);
if (newstate != ST_NONE && !trans_ok(curstate, newstate))
{
if (ctx->ctx_dbg > 1)
- sm_dprintf("[%d] abort: cur %d (%x) new %d (%x) next %x\n",
- (int) ctx->ctx_id,
+ sm_dprintf("[%ld] abort: cur %d (%x) new %d (%x) next %x\n",
+ (long) ctx->ctx_id,
curstate, MI_MASK(curstate),
newstate, MI_MASK(newstate),
next_states[curstate]);
@@ -352,7 +400,9 @@ mi_engine(ctx)
call_abort = ST_IN_MAIL(curstate);
/* call function to deal with command */
+ MI_MONITOR_BEGIN(ctx, cmd);
r = (*f)(&arg);
+ MI_MONITOR_END(ctx, cmd);
if (r != _SMFIS_KEEP && buf != NULL)
{
free(buf);
@@ -383,28 +433,164 @@ mi_engine(ctx)
else if (r == _SMFIS_ABORT)
{
if (ctx->ctx_dbg > 5)
- sm_dprintf("[%d] function returned abort\n",
- (int) ctx->ctx_id);
+ sm_dprintf("[%ld] function returned abort\n",
+ (long) ctx->ctx_id);
ret = MI_FAILURE;
break;
}
} while (!bitset(CT_END, cmds[i].cm_todo));
- if (ret != MI_SUCCESS)
+ ctx->ctx_state = curstate;
+
+ if (ret == MI_FAILURE)
{
/* call abort only if in a mail transaction */
if (fi_abort != NULL && call_abort)
(void) (*fi_abort)(ctx);
}
- /* close must always be called */
- if ((fi_close = ctx->ctx_smfi->xxfi_close) != NULL)
- (void) (*fi_close)(ctx);
+ /* has close been called? */
+ if (ctx->ctx_state != ST_QUIT
+#if _FFR_WORKERS_POOL
+ && ret != MI_CONTINUE
+#endif /* _FFR_WORKERS_POOL */
+ )
+ {
+ if ((fi_close = ctx->ctx_smfi->xxfi_close) != NULL)
+ (void) (*fi_close)(ctx);
+ }
if (r != _SMFIS_KEEP && buf != NULL)
free(buf);
+#if !_FFR_WORKERS_POOL
mi_clr_macros(ctx, 0);
+#endif /* _FFR_WORKERS_POOL */
return ret;
}
+
+static size_t milter_addsymlist __P((SMFICTX_PTR, char *, char **));
+
+static size_t
+milter_addsymlist(ctx, buf, newbuf)
+ SMFICTX_PTR ctx;
+ char *buf;
+ char **newbuf;
+{
+ size_t len;
+ int i;
+ mi_int32 v;
+ char *buffer;
+
+ SM_ASSERT(ctx != NULL);
+ SM_ASSERT(buf != NULL);
+ SM_ASSERT(newbuf != NULL);
+ len = 0;
+ for (i = 0; i < MAX_MACROS_ENTRIES; i++)
+ {
+ if (ctx->ctx_mac_list[i] != NULL)
+ {
+ len += strlen(ctx->ctx_mac_list[i]) + 1 +
+ MILTER_LEN_BYTES;
+ }
+ }
+ if (len > 0)
+ {
+ size_t offset;
+
+ SM_ASSERT(len + MILTER_OPTLEN > len);
+ len += MILTER_OPTLEN;
+ buffer = malloc(len);
+ if (buffer != NULL)
+ {
+ (void) memcpy(buffer, buf, MILTER_OPTLEN);
+ offset = MILTER_OPTLEN;
+ for (i = 0; i < MAX_MACROS_ENTRIES; i++)
+ {
+ size_t l;
+
+ if (ctx->ctx_mac_list[i] == NULL)
+ continue;
+
+ SM_ASSERT(offset + MILTER_LEN_BYTES < len);
+ v = htonl(i);
+ (void) memcpy(buffer + offset, (void *) &v,
+ MILTER_LEN_BYTES);
+ offset += MILTER_LEN_BYTES;
+ l = strlen(ctx->ctx_mac_list[i]) + 1;
+ SM_ASSERT(offset + l <= len);
+ (void) memcpy(buffer + offset,
+ ctx->ctx_mac_list[i], l);
+ offset += l;
+ }
+ }
+ else
+ {
+ /* oops ... */
+ }
+ }
+ else
+ {
+ len = MILTER_OPTLEN;
+ buffer = buf;
+ }
+ *newbuf = buffer;
+ return len;
+}
+
+/*
+** GET_NR_BIT -- get "no reply" bit matching state
+**
+** Parameters:
+** state -- current protocol stage
+**
+** Returns:
+** 0: no matching bit
+** >0: the matching "no reply" bit
+*/
+
+static unsigned long get_nr_bit __P((int));
+
+static unsigned long
+get_nr_bit(state)
+ int state;
+{
+ unsigned long bit;
+
+ switch (state)
+ {
+ case ST_CONN:
+ bit = SMFIP_NR_CONN;
+ break;
+ case ST_HELO:
+ bit = SMFIP_NR_HELO;
+ break;
+ case ST_MAIL:
+ bit = SMFIP_NR_MAIL;
+ break;
+ case ST_RCPT:
+ bit = SMFIP_NR_RCPT;
+ break;
+ case ST_DATA:
+ bit = SMFIP_NR_DATA;
+ break;
+ case ST_UNKN:
+ bit = SMFIP_NR_UNKN;
+ break;
+ case ST_HDRS:
+ bit = SMFIP_NR_HDR;
+ break;
+ case ST_EOHS:
+ bit = SMFIP_NR_EOH;
+ break;
+ case ST_BODY:
+ bit = SMFIP_NR_BODY;
+ break;
+ default:
+ bit = 0;
+ break;
+ }
+ return bit;
+}
+
/*
** SENDREPLY -- send a reply to the MTA
**
@@ -425,7 +611,42 @@ sendreply(r, sd, timeout_ptr, ctx)
struct timeval *timeout_ptr;
SMFICTX_PTR ctx;
{
- int ret = MI_SUCCESS;
+ int ret;
+ unsigned long bit;
+
+ ret = MI_SUCCESS;
+
+ bit = get_nr_bit(ctx->ctx_state);
+ if (bit != 0 && (ctx->ctx_pflags & bit) != 0 && r != SMFIS_NOREPLY)
+ {
+ if (r >= SMFIS_CONTINUE && r < _SMFIS_KEEP)
+ {
+ /* milter said it wouldn't reply, but it lied... */
+ smi_log(SMI_LOG_ERR,
+ "%s: milter claimed not to reply in state %d but did anyway %d\n",
+ ctx->ctx_smfi->xxfi_name,
+ ctx->ctx_state, r);
+
+ }
+
+ /*
+ ** Force specified behavior, otherwise libmilter
+ ** and MTA will fail to communicate properly.
+ */
+
+ switch (r)
+ {
+ case SMFIS_CONTINUE:
+ case SMFIS_TEMPFAIL:
+ case SMFIS_REJECT:
+ case SMFIS_DISCARD:
+ case SMFIS_ACCEPT:
+ case SMFIS_SKIP:
+ case _SMFIS_OPTIONS:
+ r = SMFIS_NOREPLY;
+ break;
+ }
+ }
switch (r)
{
@@ -456,21 +677,45 @@ sendreply(r, sd, timeout_ptr, ctx)
case SMFIS_ACCEPT:
ret = mi_wr_cmd(sd, timeout_ptr, SMFIR_ACCEPT, NULL, 0);
break;
+ case SMFIS_SKIP:
+ ret = mi_wr_cmd(sd, timeout_ptr, SMFIR_SKIP, NULL, 0);
+ break;
case _SMFIS_OPTIONS:
{
- char buf[MILTER_OPTLEN];
mi_int32 v;
+ size_t len;
+ char *buffer;
+ char buf[MILTER_OPTLEN];
- v = htonl(ctx->ctx_smfi->xxfi_version);
- (void) memcpy(&(buf[0]), (void *) &v, MILTER_LEN_BYTES);
- v = htonl(ctx->ctx_smfi->xxfi_flags);
+ v = htonl(ctx->ctx_prot_vers2mta);
+ (void) memcpy(&(buf[0]), (void *) &v,
+ MILTER_LEN_BYTES);
+ v = htonl(ctx->ctx_aflags);
(void) memcpy(&(buf[MILTER_LEN_BYTES]), (void *) &v,
MILTER_LEN_BYTES);
- v = htonl(ctx->ctx_pflags);
- (void) memcpy(&(buf[MILTER_LEN_BYTES * 2]), (void *) &v,
- MILTER_LEN_BYTES);
- ret = mi_wr_cmd(sd, timeout_ptr, SMFIC_OPTNEG, buf,
- MILTER_OPTLEN);
+ v = htonl(ctx->ctx_pflags2mta);
+ (void) memcpy(&(buf[MILTER_LEN_BYTES * 2]),
+ (void *) &v, MILTER_LEN_BYTES);
+ len = milter_addsymlist(ctx, buf, &buffer);
+ if (buffer != NULL)
+ ret = mi_wr_cmd(sd, timeout_ptr, SMFIC_OPTNEG,
+ buffer, len);
+ else
+ ret = MI_FAILURE;
+ }
+ break;
+ case SMFIS_NOREPLY:
+ if (bit != 0 &&
+ (ctx->ctx_pflags & bit) != 0 &&
+ (ctx->ctx_mta_pflags & bit) == 0)
+ {
+ /*
+ ** milter doesn't want to send a reply,
+ ** but the MTA doesn't have that feature: fake it.
+ */
+
+ ret = mi_wr_cmd(sd, timeout_ptr, SMFIR_CONTINUE, NULL,
+ 0);
}
break;
default: /* don't send a reply */
@@ -489,6 +734,7 @@ sendreply(r, sd, timeout_ptr, ctx)
** Returns:
** None.
*/
+
void
mi_clr_macros(ctx, m)
SMFICTX_PTR ctx;
@@ -510,6 +756,7 @@ mi_clr_macros(ctx, m)
}
}
}
+
/*
** ST_OPTIONNEG -- negotiate options
**
@@ -524,36 +771,51 @@ static int
st_optionneg(g)
genarg *g;
{
- mi_int32 i, v;
+ mi_int32 i, v, fake_pflags;
+ SMFICTX_PTR ctx;
+ int (*fi_negotiate) __P((SMFICTX *,
+ unsigned long, unsigned long,
+ unsigned long, unsigned long,
+ unsigned long *, unsigned long *,
+ unsigned long *, unsigned long *));
if (g == NULL || g->a_ctx->ctx_smfi == NULL)
return SMFIS_CONTINUE;
- mi_clr_macros(g->a_ctx, g->a_idx + 1);
+ ctx = g->a_ctx;
+ mi_clr_macros(ctx, g->a_idx + 1);
+ ctx->ctx_prot_vers = SMFI_PROT_VERSION;
/* check for minimum length */
if (g->a_len < MILTER_OPTLEN)
{
smi_log(SMI_LOG_ERR,
- "%s: st_optionneg[%d]: len too short %d < %d",
- g->a_ctx->ctx_smfi->xxfi_name,
- (int) g->a_ctx->ctx_id, (int) g->a_len,
+ "%s: st_optionneg[%ld]: len too short %d < %d",
+ ctx->ctx_smfi->xxfi_name,
+ (long) ctx->ctx_id, (int) g->a_len,
MILTER_OPTLEN);
return _SMFIS_ABORT;
}
- (void) memcpy((void *) &i, (void *) &(g->a_buf[0]),
- MILTER_LEN_BYTES);
+ /* protocol version */
+ (void) memcpy((void *) &i, (void *) &(g->a_buf[0]), MILTER_LEN_BYTES);
v = ntohl(i);
- if (v < g->a_ctx->ctx_smfi->xxfi_version)
+
+#define SMFI_PROT_VERSION_MIN 2
+
+ /* check for minimum version */
+ if (v < SMFI_PROT_VERSION_MIN)
{
- /* hard failure for now! */
smi_log(SMI_LOG_ERR,
- "%s: st_optionneg[%d]: version mismatch MTA: %d < milter: %d",
- g->a_ctx->ctx_smfi->xxfi_name,
- (int) g->a_ctx->ctx_id, (int) v,
- g->a_ctx->ctx_smfi->xxfi_version);
+ "%s: st_optionneg[%ld]: protocol version too old %d < %d",
+ ctx->ctx_smfi->xxfi_name,
+ (long) ctx->ctx_id, v, SMFI_PROT_VERSION_MIN);
return _SMFIS_ABORT;
}
+ ctx->ctx_mta_prot_vers = v;
+ if (ctx->ctx_prot_vers < ctx->ctx_mta_prot_vers)
+ ctx->ctx_prot_vers2mta = ctx->ctx_prot_vers;
+ else
+ ctx->ctx_prot_vers2mta = ctx->ctx_mta_prot_vers;
(void) memcpy((void *) &i, (void *) &(g->a_buf[MILTER_LEN_BYTES]),
MILTER_LEN_BYTES);
@@ -562,15 +824,7 @@ st_optionneg(g)
/* no flags? set to default value for V1 actions */
if (v == 0)
v = SMFI_V1_ACTS;
- i = g->a_ctx->ctx_smfi->xxfi_flags;
- if ((v & i) != i)
- {
- smi_log(SMI_LOG_ERR,
- "%s: st_optionneg[%d]: 0x%x does not fulfill action requirements 0x%x",
- g->a_ctx->ctx_smfi->xxfi_name,
- (int) g->a_ctx->ctx_id, v, i);
- return _SMFIS_ABORT;
- }
+ ctx->ctx_mta_aflags = v; /* MTA action flags */
(void) memcpy((void *) &i, (void *) &(g->a_buf[MILTER_LEN_BYTES * 2]),
MILTER_LEN_BYTES);
@@ -579,18 +833,185 @@ st_optionneg(g)
/* no flags? set to default value for V1 protocol */
if (v == 0)
v = SMFI_V1_PROT;
- i = g->a_ctx->ctx_pflags;
- if ((v & i) != i)
+ ctx->ctx_mta_pflags = v; /* MTA protocol flags */
+
+ /*
+ ** Copy flags from milter struct into libmilter context;
+ ** this variable will be used later on to check whether
+ ** the MTA "actions" can fulfill the milter requirements,
+ ** but it may be overwritten by the negotiate callback.
+ */
+
+ ctx->ctx_aflags = ctx->ctx_smfi->xxfi_flags;
+ fake_pflags = SMFIP_NR_CONN
+ |SMFIP_NR_HELO
+ |SMFIP_NR_MAIL
+ |SMFIP_NR_RCPT
+ |SMFIP_NR_DATA
+ |SMFIP_NR_UNKN
+ |SMFIP_NR_HDR
+ |SMFIP_NR_EOH
+ |SMFIP_NR_BODY
+ ;
+
+ if (g->a_ctx->ctx_smfi != NULL &&
+ (fi_negotiate = g->a_ctx->ctx_smfi->xxfi_negotiate) != NULL)
+ {
+ int r;
+ unsigned long m_aflags, m_pflags, m_f2, m_f3;
+
+ /*
+ ** let milter decide whether the features offered by the
+ ** MTA are "good enough".
+ ** Notes:
+ ** - libmilter can "fake" some features (e.g., SMFIP_NR_HDR)
+ ** - m_f2, m_f3 are for future extensions
+ */
+
+ m_f2 = m_f3 = 0;
+ m_aflags = ctx->ctx_mta_aflags;
+ m_pflags = ctx->ctx_pflags;
+ if ((SMFIP_SKIP & ctx->ctx_mta_pflags) != 0)
+ m_pflags |= SMFIP_SKIP;
+ r = fi_negotiate(g->a_ctx,
+ ctx->ctx_mta_aflags,
+ ctx->ctx_mta_pflags|fake_pflags,
+ 0, 0,
+ &m_aflags, &m_pflags, &m_f2, &m_f3);
+
+ /*
+ ** Types of protocol flags (pflags):
+ ** 1. do NOT send protocol step X
+ ** 2. MTA can do/understand something extra (SKIP,
+ ** send unknown RCPTs)
+ ** 3. MTA can deal with "no reply" for various protocol steps
+ ** Note: this mean that it isn't possible to simply set all
+ ** flags to get "everything":
+ ** setting a flag of type 1 turns off a step
+ ** (it should be the other way around:
+ ** a flag means a protocol step can be sent)
+ ** setting a flag of type 3 requires that milter
+ ** never sends a reply for the corresponding step.
+ ** Summary: the "negation" of protocol flags is causing
+ ** problems, but at least for type 3 there is no simple
+ ** solution.
+ **
+ ** What should "all options" mean?
+ ** send all protocol steps _except_ those for which there is
+ ** no callback (currently registered in ctx_pflags)
+ ** expect SKIP as return code? Yes
+ ** send unknown RCPTs? No,
+ ** must be explicitly requested?
+ ** "no reply" for some protocol steps? No,
+ ** must be explicitly requested.
+ */
+
+ if (SMFIS_ALL_OPTS == r)
+ {
+ ctx->ctx_aflags = ctx->ctx_mta_aflags;
+ ctx->ctx_pflags2mta = ctx->ctx_pflags;
+ if ((SMFIP_SKIP & ctx->ctx_mta_pflags) != 0)
+ ctx->ctx_pflags2mta |= SMFIP_SKIP;
+ }
+ else if (r != SMFIS_CONTINUE)
+ {
+ smi_log(SMI_LOG_ERR,
+ "%s: st_optionneg[%ld]: xxfi_negotiate returned %d (protocol options=0x%lx, actions=0x%lx)",
+ ctx->ctx_smfi->xxfi_name,
+ (long) ctx->ctx_id, r, ctx->ctx_mta_pflags,
+ ctx->ctx_mta_aflags);
+ return _SMFIS_ABORT;
+ }
+ else
+ {
+ ctx->ctx_aflags = m_aflags;
+ ctx->ctx_pflags = m_pflags;
+ ctx->ctx_pflags2mta = m_pflags;
+ }
+
+ /* check whether some flags need to be "faked" */
+ i = ctx->ctx_pflags2mta;
+ if ((ctx->ctx_mta_pflags & i) != i)
+ {
+ unsigned int idx;
+ unsigned long b;
+
+ /*
+ ** If some behavior can be faked (set in fake_pflags),
+ ** but the MTA doesn't support it, then unset
+ ** that flag in the value that is sent to the MTA.
+ */
+
+ for (idx = 0; idx < 32; idx++)
+ {
+ b = 1 << idx;
+ if ((ctx->ctx_mta_pflags & b) != b &&
+ (fake_pflags & b) == b)
+ ctx->ctx_pflags2mta &= ~b;
+ }
+ }
+ }
+ else
+ {
+ /*
+ ** Set the protocol flags based on the values determined
+ ** in mi_listener() which checked the defined callbacks.
+ */
+
+ ctx->ctx_pflags2mta = ctx->ctx_pflags;
+ }
+
+ /* check whether actions and protocol requirements can be satisfied */
+ i = ctx->ctx_aflags;
+ if ((i & ctx->ctx_mta_aflags) != i)
{
smi_log(SMI_LOG_ERR,
- "%s: st_optionneg[%d]: 0x%x does not fulfill protocol requirements 0x%x",
- g->a_ctx->ctx_smfi->xxfi_name,
- (int) g->a_ctx->ctx_id, v, i);
+ "%s: st_optionneg[%ld]: 0x%lx does not fulfill action requirements 0x%x",
+ ctx->ctx_smfi->xxfi_name,
+ (long) ctx->ctx_id, ctx->ctx_mta_aflags, i);
return _SMFIS_ABORT;
}
+ i = ctx->ctx_pflags2mta;
+ if ((ctx->ctx_mta_pflags & i) != i)
+ {
+ /*
+ ** Older MTAs do not support some protocol steps.
+ ** As this protocol is a bit "wierd" (it asks for steps
+ ** NOT to be taken/sent) we have to check whether we
+ ** should turn off those "negative" requests.
+ ** Currently these are only SMFIP_NODATA and SMFIP_NOUNKNOWN.
+ */
+
+ if (bitset(SMFIP_NODATA, ctx->ctx_pflags2mta) &&
+ !bitset(SMFIP_NODATA, ctx->ctx_mta_pflags))
+ ctx->ctx_pflags2mta &= ~SMFIP_NODATA;
+ if (bitset(SMFIP_NOUNKNOWN, ctx->ctx_pflags2mta) &&
+ !bitset(SMFIP_NOUNKNOWN, ctx->ctx_mta_pflags))
+ ctx->ctx_pflags2mta &= ~SMFIP_NOUNKNOWN;
+ i = ctx->ctx_pflags2mta;
+ }
+
+ if ((ctx->ctx_mta_pflags & i) != i)
+ {
+ smi_log(SMI_LOG_ERR,
+ "%s: st_optionneg[%ld]: 0x%lx does not fulfill protocol requirements 0x%x",
+ ctx->ctx_smfi->xxfi_name,
+ (long) ctx->ctx_id, ctx->ctx_mta_pflags, i);
+ return _SMFIS_ABORT;
+ }
+
+ if (ctx->ctx_dbg > 3)
+ sm_dprintf("[%ld] milter_negotiate:"
+ " mta_actions=0x%lx, mta_flags=0x%lx"
+ " actions=0x%lx, flags=0x%lx\n"
+ , (long) ctx->ctx_id
+ , ctx->ctx_mta_aflags, ctx->ctx_mta_pflags
+ , ctx->ctx_aflags, ctx->ctx_pflags);
+
return _SMFIS_OPTIONS;
}
+
/*
** ST_CONNECTINFO -- receive connection information
**
@@ -636,9 +1057,9 @@ st_connectinfo(g)
if (i + sizeof port >= l)
{
smi_log(SMI_LOG_ERR,
- "%s: connect[%d]: wrong len %d >= %d",
+ "%s: connect[%ld]: wrong len %d >= %d",
g->a_ctx->ctx_smfi->xxfi_name,
- (int) g->a_ctx->ctx_id, (int) i, (int) l);
+ (long) g->a_ctx->ctx_id, (int) i, (int) l);
return _SMFIS_ABORT;
}
(void) memcpy((void *) &port, (void *) (s + i),
@@ -655,9 +1076,9 @@ st_connectinfo(g)
!= 1)
{
smi_log(SMI_LOG_ERR,
- "%s: connect[%d]: inet_aton failed",
+ "%s: connect[%ld]: inet_aton failed",
g->a_ctx->ctx_smfi->xxfi_name,
- (int) g->a_ctx->ctx_id);
+ (long) g->a_ctx->ctx_id);
return _SMFIS_ABORT;
}
sockaddr.sa.sa_family = AF_INET;
@@ -673,9 +1094,9 @@ st_connectinfo(g)
&sockaddr.sin6.sin6_addr) != 1)
{
smi_log(SMI_LOG_ERR,
- "%s: connect[%d]: mi_inet_pton failed",
+ "%s: connect[%ld]: mi_inet_pton failed",
g->a_ctx->ctx_smfi->xxfi_name,
- (int) g->a_ctx->ctx_id);
+ (long) g->a_ctx->ctx_id);
return _SMFIS_ABORT;
}
sockaddr.sa.sa_family = AF_INET6;
@@ -692,9 +1113,9 @@ st_connectinfo(g)
sizeof sockaddr.sunix.sun_path)
{
smi_log(SMI_LOG_ERR,
- "%s: connect[%d]: path too long",
+ "%s: connect[%ld]: path too long",
g->a_ctx->ctx_smfi->xxfi_name,
- (int) g->a_ctx->ctx_id);
+ (long) g->a_ctx->ctx_id);
return _SMFIS_ABORT;
}
sockaddr.sunix.sun_family = AF_UNIX;
@@ -703,9 +1124,9 @@ st_connectinfo(g)
# endif /* NETUNIX */
{
smi_log(SMI_LOG_ERR,
- "%s: connect[%d]: unknown family %d",
+ "%s: connect[%ld]: unknown family %d",
g->a_ctx->ctx_smfi->xxfi_name,
- (int) g->a_ctx->ctx_id, family);
+ (long) g->a_ctx->ctx_id, family);
return _SMFIS_ABORT;
}
}
@@ -737,7 +1158,6 @@ st_eoh(g)
return SMFIS_CONTINUE;
}
-#if SMFI_VERSION > 3
/*
** ST_DATA -- DATA command
**
@@ -761,7 +1181,6 @@ st_data(g)
return (*fi_data)(g->a_ctx);
return SMFIS_CONTINUE;
}
-#endif /* SMFI_VERSION > 3 */
/*
** ST_HELO -- helo/ehlo command
@@ -772,6 +1191,7 @@ st_data(g)
** Returns:
** continue or filter-specified value
*/
+
static int
st_helo(g)
genarg *g;
@@ -791,6 +1211,7 @@ st_helo(g)
}
return SMFIS_CONTINUE;
}
+
/*
** ST_HEADER -- header line
**
@@ -852,6 +1273,7 @@ st_sender(g)
{
ARGV_FCT(fi_envfrom, xxfi_envfrom, CI_MAIL)
}
+
/*
** ST_RCPT -- RCPT TO command
**
@@ -869,7 +1291,6 @@ st_rcpt(g)
ARGV_FCT(fi_envrcpt, xxfi_envrcpt, CI_RCPT)
}
-#if SMFI_VERSION > 2
/*
** ST_UNKNOWN -- unrecognized or unimplemented command
**
@@ -884,17 +1305,15 @@ static int
st_unknown(g)
genarg *g;
{
- sfsistat (*fi_unknown) __P((SMFICTX *, char *));
+ sfsistat (*fi_unknown) __P((SMFICTX *, const char *));
if (g == NULL)
return _SMFIS_ABORT;
- mi_clr_macros(g->a_ctx, g->a_idx + 1);
if (g->a_ctx->ctx_smfi != NULL &&
(fi_unknown = g->a_ctx->ctx_smfi->xxfi_unknown) != NULL)
- return (*fi_unknown)(g->a_ctx, g->a_buf);
+ return (*fi_unknown)(g->a_ctx, (const char *) g->a_buf);
return SMFIS_CONTINUE;
}
-#endif /* SMFI_VERSION > 2 */
/*
** ST_MACROS -- deal with macros received from the MTA
@@ -934,9 +1353,15 @@ st_macros(g)
case SMFIC_RCPT:
i = CI_RCPT;
break;
+ case SMFIC_DATA:
+ i = CI_DATA;
+ break;
case SMFIC_BODYEOB:
i = CI_EOM;
break;
+ case SMFIC_EOH:
+ i = CI_EOH;
+ break;
default:
free(argv);
return _SMFIS_FAIL;
@@ -949,6 +1374,7 @@ st_macros(g)
g->a_ctx->ctx_mac_buf[i] = g->a_buf;
return _SMFIS_KEEP;
}
+
/*
** ST_QUIT -- quit command
**
@@ -964,8 +1390,17 @@ static int
st_quit(g)
genarg *g;
{
+ sfsistat (*fi_close) __P((SMFICTX *));
+
+ if (g == NULL)
+ return _SMFIS_ABORT;
+ if (g->a_ctx->ctx_smfi != NULL &&
+ (fi_close = g->a_ctx->ctx_smfi->xxfi_close) != NULL)
+ (void) (*fi_close)(g->a_ctx);
+ mi_clr_macros(g->a_ctx, 0);
return _SMFIS_NOREPLY;
}
+
/*
** ST_BODYCHUNK -- deal with a piece of the mail body
**
@@ -990,6 +1425,7 @@ st_bodychunk(g)
g->a_len);
return SMFIS_CONTINUE;
}
+
/*
** ST_BODYEND -- deal with the last piece of the mail body
**
@@ -1037,6 +1473,7 @@ st_bodyend(g)
return (*fi_eom)(g->a_ctx);
return r;
}
+
/*
** ST_ABORTFCT -- deal with aborts
**
@@ -1060,6 +1497,7 @@ st_abortfct(g)
(void) (*fi_abort)(g->a_ctx);
return _SMFIS_NOREPLY;
}
+
/*
** TRANS_OK -- is the state transition ok?
**
@@ -1109,6 +1547,7 @@ trans_ok(old, new)
} while (s < SIZE_NEXT_STATES);
return false;
}
+
/*
** FIX_STM -- add "skip" bits to the state transition table
**
@@ -1145,7 +1584,12 @@ fix_stm(ctx)
next_states[ST_EOHS] |= NX_SKIP;
if (bitset(SMFIP_NOBODY, fl))
next_states[ST_BODY] |= NX_SKIP;
+ if (bitset(SMFIP_NODATA, fl))
+ next_states[ST_DATA] |= NX_SKIP;
+ if (bitset(SMFIP_NOUNKNOWN, fl))
+ next_states[ST_UNKN] |= NX_SKIP;
}
+
/*
** DEC_ARGV -- split a buffer into a list of strings, NULL terminated
**
@@ -1196,6 +1640,7 @@ dec_argv(buf, len)
s[elem] = NULL;
return s;
}
+
/*
** DEC_ARG2 -- split a buffer into two strings
**
@@ -1228,6 +1673,7 @@ dec_arg2(buf, len, s1, s2)
*s2 = buf + i + 1;
return MI_SUCCESS;
}
+
/*
** SENDOK -- is it ok for the filter to send stuff to the MTA?
**
@@ -1248,9 +1694,81 @@ mi_sendok(ctx, flag)
return false;
/* did the milter request this operation? */
- if (flag != 0 && !bitset(flag, ctx->ctx_smfi->xxfi_flags))
+ if (flag != 0 && !bitset(flag, ctx->ctx_aflags))
return false;
/* are we in the correct state? It must be "End of Message". */
return ctx->ctx_state == ST_ENDM;
}
+
+#if _FFR_WORKERS_POOL
+/*
+** MI_RD_SOCKET_READY - checks if the socket is ready for read(2)
+**
+** Parameters:
+** sd -- socket_t
+**
+** Returns:
+** true iff socket is ready for read(2)
+*/
+
+#define MI_RD_CMD_TO 1
+#define MI_RD_MAX_ERR 16
+
+static bool
+mi_rd_socket_ready (sd)
+ socket_t sd;
+{
+ int n;
+ int nerr = 0;
+#if SM_CONF_POLL
+ struct pollfd pfd;
+#else /* SM_CONF_POLL */
+ fd_set rd_set, exc_set;
+#endif /* SM_CONF_POLL */
+
+ do
+ {
+#if SM_CONF_POLL
+ pfd.fd = sd;
+ pfd.events = POLLIN;
+ pfd.revents = 0;
+
+ n = poll(&pfd, 1, MI_RD_CMD_TO);
+#else /* SM_CONF_POLL */
+ struct timeval timeout;
+
+ FD_ZERO(&rd_set);
+ FD_ZERO(&exc_set);
+ FD_SET(sd, &rd_set);
+ FD_SET(sd, &exc_set);
+
+ timeout.tv_sec = MI_RD_CMD_TO / 1000;
+ timeout.tv_usec = 0;
+ n = select(sd + 1, &rd_set, NULL, &exc_set, &timeout);
+#endif /* SM_CONF_POLL */
+
+ if (n < 0)
+ {
+ if (errno == EINTR)
+ {
+ nerr++;
+ continue;
+ }
+ return true;
+ }
+
+ if (n == 0)
+ return false;
+ break;
+ } while (nerr < MI_RD_MAX_ERR);
+ if (nerr >= MI_RD_MAX_ERR)
+ return false;
+
+#if SM_CONF_POLL
+ return (pfd.revents != 0);
+#else /* SM_CONF_POLL */
+ return FD_ISSET(sd, &rd_set) || FD_ISSET(sd, &exc_set);
+#endif /* SM_CONF_POLL */
+}
+#endif /* _FFR_WORKERS_POOL */
diff --git a/contrib/sendmail/libmilter/example.c b/contrib/sendmail/libmilter/example.c
new file mode 100644
index 000000000000..5a09f1da9735
--- /dev/null
+++ b/contrib/sendmail/libmilter/example.c
@@ -0,0 +1,298 @@
+/*
+ * Copyright (c) 2006 Sendmail, Inc. and its suppliers.
+ * All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set
+ * forth in the LICENSE file which can be found at the top level of
+ * the sendmail distribution.
+ *
+ * $Id: example.c,v 8.3 2006/12/20 21:22:34 ca Exp $
+ */
+
+/*
+** A trivial example filter that logs all email to a file.
+** This milter also has some callbacks which it does not really use,
+** but they are defined to serve as an example.
+*/
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "libmilter/mfapi.h"
+#include "libmilter/mfdef.h"
+
+#ifndef true
+# define false 0
+# define true 1
+#endif /* ! true */
+
+struct mlfiPriv
+{
+ char *mlfi_fname;
+ FILE *mlfi_fp;
+};
+
+#define MLFIPRIV ((struct mlfiPriv *) smfi_getpriv(ctx))
+
+static unsigned long mta_caps = 0;
+
+sfsistat
+mlfi_cleanup(ctx, ok)
+ SMFICTX *ctx;
+ bool ok;
+{
+ sfsistat rstat = SMFIS_CONTINUE;
+ struct mlfiPriv *priv = MLFIPRIV;
+ char *p;
+ char host[512];
+ char hbuf[1024];
+
+ if (priv == NULL)
+ return rstat;
+
+ /* close the archive file */
+ if (priv->mlfi_fp != NULL && fclose(priv->mlfi_fp) == EOF)
+ {
+ /* failed; we have to wait until later */
+ rstat = SMFIS_TEMPFAIL;
+ (void) unlink(priv->mlfi_fname);
+ }
+ else if (ok)
+ {
+ /* add a header to the message announcing our presence */
+ if (gethostname(host, sizeof host) < 0)
+ snprintf(host, sizeof host, "localhost");
+ p = strrchr(priv->mlfi_fname, '/');
+ if (p == NULL)
+ p = priv->mlfi_fname;
+ else
+ p++;
+ snprintf(hbuf, sizeof hbuf, "%s@%s", p, host);
+ smfi_addheader(ctx, "X-Archived", hbuf);
+ }
+ else
+ {
+ /* message was aborted -- delete the archive file */
+ (void) unlink(priv->mlfi_fname);
+ }
+
+ /* release private memory */
+ free(priv->mlfi_fname);
+ free(priv);
+ smfi_setpriv(ctx, NULL);
+
+ /* return status */
+ return rstat;
+}
+
+
+sfsistat
+mlfi_envfrom(ctx, envfrom)
+ SMFICTX *ctx;
+ char **envfrom;
+{
+ struct mlfiPriv *priv;
+ int fd = -1;
+
+ /* allocate some private memory */
+ priv = malloc(sizeof *priv);
+ if (priv == NULL)
+ {
+ /* can't accept this message right now */
+ return SMFIS_TEMPFAIL;
+ }
+ memset(priv, '\0', sizeof *priv);
+
+ /* open a file to store this message */
+ priv->mlfi_fname = strdup("/tmp/msg.XXXXXXXX");
+ if (priv->mlfi_fname == NULL)
+ {
+ free(priv);
+ return SMFIS_TEMPFAIL;
+ }
+ if ((fd = mkstemp(priv->mlfi_fname)) < 0 ||
+ (priv->mlfi_fp = fdopen(fd, "w+")) == NULL)
+ {
+ if (fd >= 0)
+ (void) close(fd);
+ free(priv->mlfi_fname);
+ free(priv);
+ return SMFIS_TEMPFAIL;
+ }
+
+ /* save the private data */
+ smfi_setpriv(ctx, priv);
+
+ /* continue processing */
+ return SMFIS_CONTINUE;
+}
+
+sfsistat
+mlfi_header(ctx, headerf, headerv)
+ SMFICTX *ctx;
+ char *headerf;
+ char *headerv;
+{
+ /* write the header to the log file */
+ fprintf(MLFIPRIV->mlfi_fp, "%s: %s\r\n", headerf, headerv);
+
+ /* continue processing */
+ return ((mta_caps & SMFIP_NR_HDR) != 0)
+ ? SMFIS_NOREPLY : SMFIS_CONTINUE;
+}
+
+sfsistat
+mlfi_eoh(ctx)
+ SMFICTX *ctx;
+{
+ /* output the blank line between the header and the body */
+ fprintf(MLFIPRIV->mlfi_fp, "\r\n");
+
+ /* continue processing */
+ return SMFIS_CONTINUE;
+}
+
+sfsistat
+mlfi_body(ctx, bodyp, bodylen)
+ SMFICTX *ctx;
+ u_char *bodyp;
+ size_t bodylen;
+{
+ /* output body block to log file */
+ if (fwrite(bodyp, bodylen, 1, MLFIPRIV->mlfi_fp) <= 0)
+ {
+ /* write failed */
+ (void) mlfi_cleanup(ctx, false);
+ return SMFIS_TEMPFAIL;
+ }
+
+ /* continue processing */
+ return SMFIS_CONTINUE;
+}
+
+sfsistat
+mlfi_eom(ctx)
+ SMFICTX *ctx;
+{
+ return mlfi_cleanup(ctx, true);
+}
+
+sfsistat
+mlfi_close(ctx)
+ SMFICTX *ctx;
+{
+ return SMFIS_ACCEPT;
+}
+
+sfsistat
+mlfi_abort(ctx)
+ SMFICTX *ctx;
+{
+ return mlfi_cleanup(ctx, false);
+}
+
+sfsistat
+mlfi_unknown(ctx, cmd)
+ SMFICTX *ctx;
+ char *cmd;
+{
+ return SMFIS_CONTINUE;
+}
+
+sfsistat
+mlfi_data(ctx)
+ SMFICTX *ctx;
+{
+ return SMFIS_CONTINUE;
+}
+
+sfsistat
+mlfi_negotiate(ctx, f0, f1, f2, f3, pf0, pf1, pf2, pf3)
+ SMFICTX *ctx;
+ unsigned long f0;
+ unsigned long f1;
+ unsigned long f2;
+ unsigned long f3;
+ unsigned long *pf0;
+ unsigned long *pf1;
+ unsigned long *pf2;
+ unsigned long *pf3;
+{
+ /* milter actions: add headers */
+ *pf0 = SMFIF_ADDHDRS;
+
+ /* milter protocol steps: all but connect, HELO, RCPT */
+ *pf1 = SMFIP_NOCONNECT|SMFIP_NOHELO|SMFIP_NORCPT;
+ mta_caps = f1;
+ if ((mta_caps & SMFIP_NR_HDR) != 0)
+ *pf1 |= SMFIP_NR_HDR;
+ *pf2 = 0;
+ *pf3 = 0;
+ return SMFIS_CONTINUE;
+}
+
+struct smfiDesc smfilter =
+{
+ "SampleFilter", /* filter name */
+ SMFI_VERSION, /* version code -- do not change */
+ SMFIF_ADDHDRS, /* flags */
+ NULL, /* connection info filter */
+ NULL, /* SMTP HELO command filter */
+ mlfi_envfrom, /* envelope sender filter */
+ NULL, /* envelope recipient filter */
+ mlfi_header, /* header filter */
+ mlfi_eoh, /* end of header */
+ mlfi_body, /* body block filter */
+ mlfi_eom, /* end of message */
+ mlfi_abort, /* message aborted */
+ mlfi_close, /* connection cleanup */
+ mlfi_unknown, /* unknown/unimplemented SMTP commands */
+ mlfi_data, /* DATA command filter */
+ mlfi_negotiate /* option negotation at connection startup */
+};
+
+int
+main(argc, argv)
+ int argc;
+ char *argv[];
+{
+ bool setconn;
+ int c;
+
+ setconn = false;
+
+ /* Process command line options */
+ while ((c = getopt(argc, argv, "p:")) != -1)
+ {
+ switch (c)
+ {
+ case 'p':
+ if (optarg == NULL || *optarg == '\0')
+ {
+ (void) fprintf(stderr, "Illegal conn: %s\n",
+ optarg);
+ exit(EX_USAGE);
+ }
+ (void) smfi_setconn(optarg);
+ setconn = true;
+ break;
+
+ }
+ }
+ if (!setconn)
+ {
+ fprintf(stderr, "%s: Missing required -p argument\n", argv[0]);
+ exit(EX_USAGE);
+ }
+ if (smfi_register(smfilter) == MI_FAILURE)
+ {
+ fprintf(stderr, "smfi_register failed\n");
+ exit(EX_UNAVAILABLE);
+ }
+ return smfi_main();
+}
+
diff --git a/contrib/sendmail/libmilter/handler.c b/contrib/sendmail/libmilter/handler.c
index 3acfc5fca379..5fd4b2630a91 100644
--- a/contrib/sendmail/libmilter/handler.c
+++ b/contrib/sendmail/libmilter/handler.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999-2003 Sendmail, Inc. and its suppliers.
+ * Copyright (c) 1999-2003, 2006 Sendmail, Inc. and its suppliers.
* All rights reserved.
*
* By using this file, you agree to the terms and conditions set
@@ -9,11 +9,11 @@
*/
#include
-SM_RCSID("@(#)$Id: handler.c,v 8.36 2003/09/08 21:27:14 yuri Exp $")
+SM_RCSID("@(#)$Id: handler.c,v 8.38 2006/11/02 02:38:22 ca Exp $")
#include "libmilter.h"
-
+#if !_FFR_WORKERS_POOL
/*
** HANDLE_SESSION -- Handle a connected session in its own context
**
@@ -64,3 +64,4 @@ mi_handle_session(ctx)
ctx = NULL;
return ret;
}
+#endif /* !_FFR_WORKERS_POOL */
diff --git a/contrib/sendmail/libmilter/libmilter.h b/contrib/sendmail/libmilter/libmilter.h
index 9cebdc22942f..5a1240974924 100644
--- a/contrib/sendmail/libmilter/libmilter.h
+++ b/contrib/sendmail/libmilter/libmilter.h
@@ -19,19 +19,108 @@
#ifdef _DEFINE
# define EXTERN
# define INIT(x) = x
-SM_IDSTR(MilterlId, "@(#)$Id: libmilter.h,v 8.51 2006/01/04 02:24:37 ca Exp $")
+SM_IDSTR(MilterlId, "@(#)$Id: libmilter.h,v 8.74 2006/12/19 18:19:52 ca Exp $")
#else /* _DEFINE */
# define EXTERN extern
# define INIT(x)
#endif /* _DEFINE */
+#include "sm/tailq.h"
+
#define NOT_SENDMAIL 1
#define _SOCK_ADDR union bigsockaddr
#include "sendmail.h"
+#ifdef SM_ASSERT
+#undef SM_ASSERT
+#endif
+#ifndef SM_ASSERT
+#include
+#define SM_ASSERT(x) assert(x)
+#endif
+
#include "libmilter/milter.h"
+#define MAX_MACROS_ENTRIES 7 /* max size of macro pointer array */
+
+typedef SM_TAILQ_HEAD(, smfi_str) smfi_hd_T;
+typedef struct smfi_str smfi_str_S;
+
+/*
+** Context for one milter session.
+**
+** Notes:
+** There is a 1-1 correlation between a sendmail SMTP server process,
+** an SMTP session, and an milter context. Due to the nature of SMTP
+** session handling in sendmail 8, this libmilter implementation deals
+** only with a single SMTP session per MTA - libmilter connection.
+**
+** There is no "global" context for libmilter, global variables are
+** just that (they are not "collected" in a context).
+**
+** Implementation hint:
+** macros are stored in mac_buf[] as sequence of:
+** macro_name \0 macro_value
+** (just as read from the MTA)
+** mac_ptr is a list of pointers into mac_buf to the beginning of each
+** entry, i.e., macro_name, macro_value, ...
+*/
+
+struct smfi_str
+{
+ sthread_t ctx_id; /* thread id */
+ socket_t ctx_sd; /* socket descriptor */
+ int ctx_dbg; /* debug level */
+ time_t ctx_timeout; /* timeout */
+ int ctx_state; /* state */
+ smfiDesc_ptr ctx_smfi; /* filter description */
+
+ int ctx_prot_vers; /* libmilter protocol version */
+ unsigned long ctx_aflags; /* milter action flags */
+
+ unsigned long ctx_pflags; /* milter protocol flags */
+
+ /*
+ ** milter protocol flags that are sent to the MTA;
+ ** this is the same as ctx_pflags except for those flags that
+ ** are not offered by the MTA but emulated in libmilter.
+ */
+
+ unsigned long ctx_pflags2mta;
+
+ /*
+ ** milter protocol version that is sent to the MTA;
+ ** this is the same as ctx_prot_vers unless the
+ ** MTA protocol version (ctx_mta_prot_vers) is smaller
+ ** but still "acceptable".
+ */
+
+ int ctx_prot_vers2mta;
+
+ char **ctx_mac_ptr[MAX_MACROS_ENTRIES];
+ char *ctx_mac_buf[MAX_MACROS_ENTRIES];
+ char *ctx_mac_list[MAX_MACROS_ENTRIES];
+ char *ctx_reply; /* reply code */
+ void *ctx_privdata; /* private data */
+
+ int ctx_mta_prot_vers; /* MTA protocol version */
+ unsigned long ctx_mta_pflags; /* MTA protocol flags */
+ unsigned long ctx_mta_aflags; /* MTA action flags */
+
+#if _FFR_THREAD_MONITOR
+ time_t ctx_start; /* start time of thread */
+ SM_TAILQ_ENTRY(smfi_str) ctx_mon_link;
+#endif /* _FFR_THREAD_MONITOR */
+
+#if _FFR_WORKERS_POOL
+ long ctx_sid; /* session identifier */
+ int ctx_wstate; /* state of the session (worker pool) */
+ int ctx_wait; /* elapsed time waiting for sm cmd */
+ SM_TAILQ_ENTRY(smfi_str) ctx_link;
+#endif /* _FFR_WORKERS_POOL */
+};
+
# define ValidSocket(sd) ((sd) >= 0)
# define INVALID_SOCKET (-1)
# define closesocket close
@@ -49,6 +138,34 @@ typedef pthread_mutex_t smutex_t;
# define smutex_unlock(mp) (pthread_mutex_unlock(mp) == 0)
# define smutex_trylock(mp) (pthread_mutex_trylock(mp) == 0)
+#if _FFR_WORKERS_POOL
+/* SM_CONF_POLL shall be defined with _FFR_WORKERS_POOL */
+# if !SM_CONF_POLL
+# define SM_CONF_POLL 1
+# endif /* SM_CONF_POLL */
+#endif /* _FFR_WORKERS_POOL */
+
+typedef pthread_cond_t scond_t;
+#define scond_init(cp) pthread_cond_init(cp, NULL)
+#define scond_destroy(cp) pthread_cond_destroy(cp)
+#define scond_wait(cp, mp) pthread_cond_wait(cp, mp)
+#define scond_signal(cp) pthread_cond_signal(cp)
+#define scond_broadcast(cp) pthread_cond_broadcast(cp)
+#define scond_timedwait(cp, mp, to) \
+ do \
+ { \
+ struct timespec timeout; \
+ struct timeval now; \
+ gettimeofday(&now, NULL); \
+ timeout.tv_sec = now.tv_sec + to; \
+ timeout.tv_nsec = now.tv_usec / 1000; \
+ r = pthread_cond_timedwait(cp,mp,&timeout); \
+ if (r != 0 && r != ETIMEDOUT) \
+ smi_log(SMI_LOG_ERR, \
+ "pthread_cond_timedwait error %d", r); \
+ } while (0)
+
+
#if SM_CONF_POLL
# include
@@ -117,10 +234,6 @@ typedef pthread_mutex_t smutex_t;
#include
-/* version info */
-#define MILTER_PRODUCT_NAME "libmilter"
-#define MILTER_VERSION 100
-
/* some defaults */
#define MI_TIMEOUT 7210 /* default timeout for read/write */
#define MI_CHK_TIME 5 /* checking whether to terminate */
@@ -184,4 +297,38 @@ extern int mi_wr_cmd __P((socket_t, struct timeval *, int, char *, size_t));
extern bool mi_sendok __P((SMFICTX_PTR, int));
+#if _FFR_THREAD_MONITOR
+extern bool Monitor;
+
+#define MI_MONITOR_INIT() mi_monitor_init()
+#define MI_MONITOR_BEGIN(ctx, cmd) \
+ do \
+ { \
+ if (Monitor) \
+ mi_monitor_work_begin(ctx, cmd);\
+ } while (0)
+
+#define MI_MONITOR_END(ctx, cmd) \
+ do \
+ { \
+ if (Monitor) \
+ mi_monitor_work_end(ctx, cmd); \
+ } while (0)
+
+int mi_monitor_init __P((void));
+int mi_monitor_work_begin __P((SMFICTX_PTR, int));
+int mi_monitor_work_end __P((SMFICTX_PTR, int));
+
+#else /* _FFR_THREAD_MONITOR */
+#define MI_MONITOR_INIT() MI_SUCCESS
+#define MI_MONITOR_BEGIN(ctx, cmd)
+#define MI_MONITOR_END(ctx, cmd)
+#endif /* _FFR_THREAD_MONITOR */
+
+#if _FFR_WORKERS_POOL
+extern int mi_pool_manager_init __P((void));
+extern int mi_pool_controller_init __P((void));
+extern int mi_start_session __P((SMFICTX_PTR));
+#endif /* _FFR_WORKERS_POOL */
+
#endif /* ! _LIBMILTER_H */
diff --git a/contrib/sendmail/libmilter/listener.c b/contrib/sendmail/libmilter/listener.c
index 4429edfbfbda..cf98361afa27 100644
--- a/contrib/sendmail/libmilter/listener.c
+++ b/contrib/sendmail/libmilter/listener.c
@@ -9,7 +9,7 @@
*/
#include
-SM_RCSID("@(#)$Id: listener.c,v 8.115 2006/01/24 00:48:39 ca Exp $")
+SM_RCSID("@(#)$Id: listener.c,v 8.122 2006/11/02 17:54:44 ca Exp $")
/*
** listener.c -- threaded network listener
@@ -25,6 +25,10 @@ SM_RCSID("@(#)$Id: listener.c,v 8.115 2006/01/24 00:48:39 ca Exp $")
# if NETINET || NETINET6
# include
# endif /* NETINET || NETINET6 */
+# if SM_CONF_POLL
+# undef SM_FD_OK_SELECT
+# define SM_FD_OK_SELECT(fd) true
+# endif /* SM_CONF_POLL */
static smutex_t L_Mutex;
static int L_family;
@@ -32,7 +36,9 @@ static SOCKADDR_LEN_T L_socksize;
static socket_t listenfd = INVALID_SOCKET;
static socket_t mi_milteropen __P((char *, int, bool, char *));
+#if !_FFR_WORKERS_POOL
static void *mi_thread_handle_wrapper __P((void *));
+#endif /* !_FFR_WORKERS_POOL */
/*
** MI_OPENSOCKET -- create the socket where this filter and the MTA will meet
@@ -80,7 +86,6 @@ mi_opensocket(conn, backlog, dbg, rmsocket, smfi)
(void) smutex_unlock(&L_Mutex);
return MI_FAILURE;
}
-#if !SM_CONF_POLL
if (!SM_FD_OK_SELECT(listenfd))
{
smi_log(SMI_LOG_ERR, "%s: fd %d is larger than FD_SETSIZE %d",
@@ -88,7 +93,6 @@ mi_opensocket(conn, backlog, dbg, rmsocket, smfi)
(void) smutex_unlock(&L_Mutex);
return MI_FAILURE;
}
-#endif /* !SM_CONF_POLL */
(void) smutex_unlock(&L_Mutex);
return MI_SUCCESS;
}
@@ -549,6 +553,8 @@ mi_milteropen(conn, backlog, rmsocket, name)
L_family = addr.sa.sa_family;
return sock;
}
+
+#if !_FFR_WORKERS_POOL
/*
** MI_THREAD_HANDLE_WRAPPER -- small wrapper to handle session
**
@@ -563,8 +569,16 @@ static void *
mi_thread_handle_wrapper(arg)
void *arg;
{
+ /*
+ ** Note: on some systems this generates a compiler warning:
+ ** cast to pointer from integer of different size
+ ** You can safely ignore this warning as the result of this function
+ ** is not used anywhere.
+ */
+
return (void *) mi_handle_session(arg);
}
+#endif /* _FFR_WORKERS_POOL */
/*
** MI_CLOSENER -- close listen socket
@@ -714,7 +728,9 @@ mi_listener(conn, dbg, smfi, timeout, backlog)
int acnt = 0; /* error count for accept() failures */
int scnt = 0; /* error count for select() failures */
int save_errno = 0;
+#if !_FFR_WORKERS_POOL
sthread_t thread_id;
+#endif /* !_FFR_WORKERS_POOL */
_SOCK_ADDR cliaddr;
SOCKADDR_LEN_T clilen;
SMFICTX_PTR ctx;
@@ -724,6 +740,11 @@ mi_listener(conn, dbg, smfi, timeout, backlog)
if (mi_opensocket(conn, backlog, dbg, false, smfi) == MI_FAILURE)
return MI_FAILURE;
+#if _FFR_WORKERS_POOL
+ if (mi_pool_controller_init() == MI_FAILURE)
+ return MI_FAILURE;
+#endif /* _FFR_WORKERS_POOL */
+
clilen = L_socksize;
while ((mistop = mi_stop()) == MILTER_CONT)
{
@@ -786,9 +807,8 @@ mi_listener(conn, dbg, smfi, timeout, backlog)
(void) smutex_unlock(&L_Mutex);
/*
- ** If remote side closes before
- ** accept() finishes, sockaddr
- ** might not be fully filled in.
+ ** If remote side closes before accept() finishes,
+ ** sockaddr might not be fully filled in.
*/
if (ValidSocket(connfd) &&
@@ -803,7 +823,6 @@ mi_listener(conn, dbg, smfi, timeout, backlog)
save_errno = EINVAL;
}
-#if !SM_CONF_POLL
/* check if acceptable for select() */
if (ValidSocket(connfd) && !SM_FD_OK_SELECT(connfd))
{
@@ -811,7 +830,6 @@ mi_listener(conn, dbg, smfi, timeout, backlog)
connfd = INVALID_SOCKET;
save_errno = ERANGE;
}
-#endif /* !SM_CONF_POLL */
if (!ValidSocket(connfd))
{
@@ -858,11 +876,7 @@ mi_listener(conn, dbg, smfi, timeout, backlog)
acnt = 0; /* reset error counter for accept() */
#if _FFR_DUP_FD
dupfd = fcntl(connfd, F_DUPFD, 256);
- if (ValidSocket(dupfd)
-# if !SM_CONF_POLL
- && SM_FD_OK_SELECT(dupfd)
-# endif /* !SM_CONF_POLL */
- )
+ if (ValidSocket(dupfd) && SM_FD_OK_SELECT(dupfd))
{
close(connfd);
connfd = dupfd;
@@ -899,12 +913,6 @@ mi_listener(conn, dbg, smfi, timeout, backlog)
ctx->ctx_dbg = dbg;
ctx->ctx_timeout = timeout;
ctx->ctx_smfi = smfi;
-#if 0
- if (smfi->xxfi_eoh == NULL)
- if (smfi->xxfi_eom == NULL)
- if (smfi->xxfi_abort == NULL)
- if (smfi->xxfi_close == NULL)
-#endif /* 0 */
if (smfi->xxfi_connect == NULL)
ctx->ctx_pflags |= SMFIP_NOCONNECT;
if (smfi->xxfi_helo == NULL)
@@ -919,14 +927,24 @@ mi_listener(conn, dbg, smfi, timeout, backlog)
ctx->ctx_pflags |= SMFIP_NOEOH;
if (smfi->xxfi_body == NULL)
ctx->ctx_pflags |= SMFIP_NOBODY;
+ if (smfi->xxfi_data == NULL)
+ ctx->ctx_pflags |= SMFIP_NODATA;
+ if (smfi->xxfi_unknown == NULL)
+ ctx->ctx_pflags |= SMFIP_NOUNKNOWN;
+#if _FFR_WORKERS_POOL
+# define LOG_CRT_FAIL "%s: mi_start_session() failed: %d, %s"
+ if ((r = mi_start_session(ctx)) != MI_SUCCESS)
+#else /* _FFR_WORKERS_POOL */
+# define LOG_CRT_FAIL "%s: thread_create() failed: %d, %s"
if ((r = thread_create(&thread_id,
mi_thread_handle_wrapper,
(void *) ctx)) != 0)
+#endif /* _FFR_WORKERS_POOL */
{
tcnt++;
smi_log(SMI_LOG_ERR,
- "%s: thread_create() failed: %d, %s",
+ LOG_CRT_FAIL,
smfi->xxfi_name, r,
tcnt >= MAX_FAILS_T ? "abort" : "try again");
MI_SLEEP(tcnt);
diff --git a/contrib/sendmail/libmilter/main.c b/contrib/sendmail/libmilter/main.c
index 8692127b834a..d3150d140cd5 100644
--- a/contrib/sendmail/libmilter/main.c
+++ b/contrib/sendmail/libmilter/main.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999-2003 Sendmail, Inc. and its suppliers.
+ * Copyright (c) 1999-2003, 2006 Sendmail, Inc. and its suppliers.
* All rights reserved.
*
* By using this file, you agree to the terms and conditions set
@@ -9,7 +9,7 @@
*/
#include
-SM_RCSID("@(#)$Id: main.c,v 8.79 2003/10/20 22:25:09 ca Exp $")
+SM_RCSID("@(#)$Id: main.c,v 8.81 2006/11/02 18:31:43 ca Exp $")
#define _DEFINE 1
#include "libmilter.h"
@@ -232,7 +232,7 @@ smfi_main()
smfi->xxfi_name);
return MI_FAILURE;
}
- r = MI_SUCCESS;
+ r = MI_MONITOR_INIT();
/* Startup the listener */
if (mi_listener(conn, dbg, smfi, timeout, backlog) != MI_SUCCESS)
diff --git a/contrib/sendmail/libmilter/monitor.c b/contrib/sendmail/libmilter/monitor.c
new file mode 100644
index 000000000000..3d23f0c27e4a
--- /dev/null
+++ b/contrib/sendmail/libmilter/monitor.c
@@ -0,0 +1,225 @@
+/*
+ * Copyright (c) 2006 Sendmail, Inc. and its suppliers.
+ * All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set
+ * forth in the LICENSE file which can be found at the top level of
+ * the sendmail distribution.
+ *
+ */
+
+#include "libmilter.h"
+
+#if _FFR_THREAD_MONITOR
+
+/*
+** Thread Monitoring
+** Todo: more error checking (return code from function calls)
+** add comments.
+*/
+
+bool Monitor = false; /* use monitoring? */
+static unsigned int Mon_exec_time = 0;
+
+/* mutex protects Mon_cur_ctx, Mon_ctx_head, and ctx_start */
+static smutex_t Mon_mutex;
+static scond_t Mon_cv;
+
+/*
+** Current ctx to monitor.
+** Invariant:
+** Mon_cur_ctx == NULL || Mon_cur_ctx is thread which was started the longest
+** time ago.
+**
+** Basically the entries in the list are ordered by time because new
+** entries are appended at the end. However, due to the concurrent
+** execution (multi-threaded) and no guaranteed order of wakeups
+** after a mutex_lock() attempt, the order might not be strict,
+** i.e., if the list contains e1 and e2 (in that order) then
+** the the start time of e2 can be (slightly) smaller than that of e1.
+** However, this slight inaccurracy should not matter for the proper
+** working of this algorithm.
+*/
+
+static SMFICTX_PTR Mon_cur_ctx = NULL;
+static smfi_hd_T Mon_ctx_head; /* head of the linked list of active contexts */
+
+/*
+** SMFI_SET_MAX_EXEC_TIME -- set maximum execution time for a thread
+**
+** Parameters:
+** tm -- maximum execution time for a thread
+**
+** Returns:
+** MI_SUCCESS
+*/
+
+int
+smfi_set_max_exec_time(tm)
+ unsigned int tm;
+{
+ Mon_exec_time = tm;
+ return MI_SUCCESS;
+}
+
+/*
+** MI_MONITOR_THREAD -- monitoring thread
+**
+** Parameters:
+** arg -- ignored (required by pthread_create())
+**
+** Returns:
+** NULL on termination.
+*/
+
+static void *
+mi_monitor_thread(arg)
+ void *arg;
+{
+ sthread_t tid;
+ int r;
+ time_t now, end;
+
+ SM_ASSERT(Monitor);
+ SM_ASSERT(Mon_exec_time > 0);
+ tid = (sthread_t) sthread_get_id();
+ if (pthread_detach(tid) != 0)
+ {
+ /* log an error */
+ return (void *)1;
+ }
+
+/*
+** NOTE: this is "flow through" code,
+** do NOT use do { } while ("break" is used here!)
+*/
+
+#define MON_CHK_STOP \
+ now = time(NULL); \
+ end = Mon_cur_ctx->ctx_start + Mon_exec_time; \
+ if (now > end) \
+ { \
+ smi_log(SMI_LOG_ERR, \
+ "WARNING: monitor timeout triggered, now=%ld, end=%ld, tid=%ld, state=0x%x",\
+ (long) now, (long) end, \
+ (long) Mon_cur_ctx->ctx_id, Mon_cur_ctx->ctx_state);\
+ mi_stop_milters(MILTER_STOP); \
+ break; \
+ }
+
+ (void) smutex_lock(&Mon_mutex);
+ while (mi_stop() == MILTER_CONT)
+ {
+ if (Mon_cur_ctx != NULL && Mon_cur_ctx->ctx_start > 0)
+ {
+ struct timespec abstime;
+
+ MON_CHK_STOP;
+ abstime.tv_sec = end;
+ abstime.tv_nsec = 0;
+ r = pthread_cond_timedwait(&Mon_cv, &Mon_mutex,
+ &abstime);
+ }
+ else
+ r = pthread_cond_wait(&Mon_cv, &Mon_mutex);
+ if (mi_stop() != MILTER_CONT)
+ break;
+ if (Mon_cur_ctx != NULL && Mon_cur_ctx->ctx_start > 0)
+ {
+ MON_CHK_STOP;
+ }
+ }
+ (void) smutex_unlock(&Mon_mutex);
+
+ return NULL;
+}
+
+/*
+** MI_MONITOR_INIT -- initialize monitoring thread
+**
+** Parameters: none
+**
+** Returns:
+** MI_SUCCESS/MI_FAILURE
+*/
+
+int
+mi_monitor_init()
+{
+ int r;
+ sthread_t tid;
+
+ SM_ASSERT(!Monitor);
+ if (Mon_exec_time <= 0)
+ return MI_SUCCESS;
+ Monitor = true;
+ if (!smutex_init(&Mon_mutex))
+ return MI_FAILURE;
+ if (scond_init(&Mon_cv) != 0)
+ return MI_FAILURE;
+ SM_TAILQ_INIT(&Mon_ctx_head);
+
+ r = thread_create(&tid, mi_monitor_thread, (void *)NULL);
+ if (r != 0)
+ return r;
+ return MI_SUCCESS;
+}
+
+/*
+** MI_MONITOR_WORK_BEGIN -- record start of thread execution
+**
+** Parameters:
+** ctx -- session context
+** cmd -- milter command char
+**
+** Returns:
+** 0
+*/
+
+int
+mi_monitor_work_begin(ctx, cmd)
+ SMFICTX_PTR ctx;
+ int cmd;
+{
+ (void) smutex_lock(&Mon_mutex);
+ if (NULL == Mon_cur_ctx)
+ {
+ Mon_cur_ctx = ctx;
+ (void) scond_signal(&Mon_cv);
+ }
+ ctx->ctx_start = time(NULL);
+ SM_TAILQ_INSERT_TAIL(&Mon_ctx_head, ctx, ctx_mon_link);
+ (void) smutex_unlock(&Mon_mutex);
+ return 0;
+}
+
+/*
+** MI_MONITOR_WORK_END -- record end of thread execution
+**
+** Parameters:
+** ctx -- session context
+** cmd -- milter command char
+**
+** Returns:
+** 0
+*/
+
+int
+mi_monitor_work_end(ctx, cmd)
+ SMFICTX_PTR ctx;
+ int cmd;
+{
+ (void) smutex_lock(&Mon_mutex);
+ ctx->ctx_start = 0;
+ SM_TAILQ_REMOVE(&Mon_ctx_head, ctx, ctx_mon_link);
+ if (Mon_cur_ctx == ctx)
+ {
+ if (SM_TAILQ_EMPTY(&Mon_ctx_head))
+ Mon_cur_ctx = NULL;
+ else
+ Mon_cur_ctx = SM_TAILQ_FIRST(&Mon_ctx_head);
+ }
+ (void) smutex_unlock(&Mon_mutex);
+ return 0;
+}
+#endif /* _FFR_THREAD_MONITOR */
diff --git a/contrib/sendmail/libmilter/smfi.c b/contrib/sendmail/libmilter/smfi.c
index 63bf1743df95..856c4a9641f9 100644
--- a/contrib/sendmail/libmilter/smfi.c
+++ b/contrib/sendmail/libmilter/smfi.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999-2005 Sendmail, Inc. and its suppliers.
+ * Copyright (c) 1999-2006 Sendmail, Inc. and its suppliers.
* All rights reserved.
*
* By using this file, you agree to the terms and conditions set
@@ -9,7 +9,7 @@
*/
#include
-SM_RCSID("@(#)$Id: smfi.c,v 8.74 2005/03/30 00:44:07 ca Exp $")
+SM_RCSID("@(#)$Id: smfi.c,v 8.82 2007/01/20 06:37:19 ca Exp $")
#include
#include "libmilter.h"
@@ -30,7 +30,6 @@ static int myisenhsc __P((const char *, int));
** headerf -- Header field name
** headerv -- Header field value
**
-**
** Returns:
** MI_SUCCESS/MI_FAILURE
*/
@@ -153,6 +152,221 @@ smfi_chgheader(ctx, headerf, hdridx, headerv)
return smfi_header(ctx, SMFIR_CHGHEADER, hdridx, headerf, headerv);
}
+#if 0
+/*
+** BUF_CRT_SEND -- construct buffer to send from arguments
+**
+** Parameters:
+** ctx -- Opaque context structure
+** cmd -- command
+** arg0 -- first argument
+** argv -- list of arguments (NULL terminated)
+**
+** Returns:
+** MI_SUCCESS/MI_FAILURE
+*/
+
+static int
+buf_crt_send __P((SMFICTX *, int cmd, char *, char **));
+
+static int
+buf_crt_send(ctx, cmd, arg0, argv)
+ SMFICTX *ctx;
+ int cmd;
+ char *arg0;
+ char **argv;
+{
+ size_t len, l0, l1, offset;
+ int r;
+ char *buf, *arg, **argvl;
+ struct timeval timeout;
+
+ if (arg0 == NULL || *arg0 == '\0')
+ return MI_FAILURE;
+ timeout.tv_sec = ctx->ctx_timeout;
+ timeout.tv_usec = 0;
+ l0 = strlen(arg0) + 1;
+ len = l0;
+ argvl = argv;
+ while (argvl != NULL && (arg = *argv) != NULL && *arg != '\0')
+ {
+ l1 = strlen(arg) + 1;
+ len += l1;
+ SM_ASSERT(len > l1);
+ }
+
+ buf = malloc(len);
+ if (buf == NULL)
+ return MI_FAILURE;
+ (void) memcpy(buf, arg0, l0);
+ offset = l0;
+
+ argvl = argv;
+ while (argvl != NULL && (arg = *argv) != NULL && *arg != '\0')
+ {
+ l1 = strlen(arg) + 1;
+ SM_ASSERT(offset < len);
+ SM_ASSERT(offset + l1 <= len);
+ (void) memcpy(buf + offset, arg, l1);
+ offset += l1;
+ SM_ASSERT(offset > l1);
+ }
+
+ r = mi_wr_cmd(ctx->ctx_sd, &timeout, cmd, buf, len);
+ free(buf);
+ return r;
+}
+#endif /* 0 */
+
+/*
+** SEND2 -- construct buffer to send from arguments
+**
+** Parameters:
+** ctx -- Opaque context structure
+** cmd -- command
+** arg0 -- first argument
+** argv -- list of arguments (NULL terminated)
+**
+** Returns:
+** MI_SUCCESS/MI_FAILURE
+*/
+
+static int
+send2 __P((SMFICTX *, int cmd, char *, char *));
+
+static int
+send2(ctx, cmd, arg0, arg1)
+ SMFICTX *ctx;
+ int cmd;
+ char *arg0;
+ char *arg1;
+{
+ size_t len, l0, l1, offset;
+ int r;
+ char *buf;
+ struct timeval timeout;
+
+ if (arg0 == NULL || *arg0 == '\0')
+ return MI_FAILURE;
+ timeout.tv_sec = ctx->ctx_timeout;
+ timeout.tv_usec = 0;
+ l0 = strlen(arg0) + 1;
+ len = l0;
+ if (arg1 != NULL)
+ {
+ l1 = strlen(arg1) + 1;
+ len += l1;
+ SM_ASSERT(len > l1);
+ }
+
+ buf = malloc(len);
+ if (buf == NULL)
+ return MI_FAILURE;
+ (void) memcpy(buf, arg0, l0);
+ offset = l0;
+
+ if (arg1 != NULL)
+ {
+ l1 = strlen(arg1) + 1;
+ SM_ASSERT(offset < len);
+ SM_ASSERT(offset + l1 <= len);
+ (void) memcpy(buf + offset, arg1, l1);
+ offset += l1;
+ SM_ASSERT(offset > l1);
+ }
+
+ r = mi_wr_cmd(ctx->ctx_sd, &timeout, cmd, buf, len);
+ free(buf);
+ return r;
+}
+
+/*
+** SMFI_CHGFROM -- change enveloper sender ("from") address
+**
+** Parameters:
+** ctx -- Opaque context structure
+** from -- new envelope sender address ("MAIL From")
+** args -- ESMTP arguments
+**
+** Returns:
+** MI_SUCCESS/MI_FAILURE
+*/
+
+int
+smfi_chgfrom(ctx, from, args)
+ SMFICTX *ctx;
+ char *from;
+ char *args;
+{
+ if (from == NULL || *from == '\0')
+ return MI_FAILURE;
+ if (!mi_sendok(ctx, SMFIF_CHGFROM))
+ return MI_FAILURE;
+ return send2(ctx, SMFIR_CHGFROM, from, args);
+}
+
+/*
+** SMFI_SETSYMLIST -- set list of macros that the MTA should send.
+**
+** Parameters:
+** ctx -- Opaque context structure
+** where -- SMTP stage
+** macros -- list of macros
+**
+** Returns:
+** MI_SUCCESS/MI_FAILURE
+*/
+
+int
+smfi_setsymlist(ctx, where, macros)
+ SMFICTX *ctx;
+ int where;
+ char *macros;
+{
+ SM_ASSERT(ctx != NULL);
+
+ if (macros == NULL || *macros == '\0')
+ return MI_FAILURE;
+ if (where < SMFIM_FIRST || where > SMFIM_LAST)
+ return MI_FAILURE;
+ if (where < 0 || where >= MAX_MACROS_ENTRIES)
+ return MI_FAILURE;
+
+ if (ctx->ctx_mac_list[where] != NULL)
+ return MI_FAILURE;
+
+ ctx->ctx_mac_list[where] = strdup(macros);
+ if (ctx->ctx_mac_list[where] == NULL)
+ return MI_FAILURE;
+
+ return MI_SUCCESS;
+}
+
+/*
+** SMFI_ADDRCPT_PAR -- send an additional recipient to the MTA
+**
+** Parameters:
+** ctx -- Opaque context structure
+** rcpt -- recipient address
+** args -- ESMTP arguments
+**
+** Returns:
+** MI_SUCCESS/MI_FAILURE
+*/
+
+int
+smfi_addrcpt_par(ctx, rcpt, args)
+ SMFICTX *ctx;
+ char *rcpt;
+ char *args;
+{
+ if (rcpt == NULL || *rcpt == '\0')
+ return MI_FAILURE;
+ if (!mi_sendok(ctx, SMFIF_ADDRCPT_PAR))
+ return MI_FAILURE;
+ return send2(ctx, SMFIR_ADDRCPT_PAR, rcpt, args);
+}
+
/*
** SMFI_ADDRCPT -- send an additional recipient to the MTA
**
@@ -646,3 +860,30 @@ smfi_progress(ctx)
return mi_wr_cmd(ctx->ctx_sd, &timeout, SMFIR_PROGRESS, NULL, 0);
}
+
+/*
+** SMFI_VERSION -- return (runtime) version of libmilter
+**
+** Parameters:
+** major -- (pointer to) major version
+** minor -- (pointer to) minor version
+** patchlevel -- (pointer to) patchlevel version
+**
+** Return value:
+** MI_SUCCESS
+*/
+
+int
+smfi_version(major, minor, patchlevel)
+ unsigned int *major;
+ unsigned int *minor;
+ unsigned int *patchlevel;
+{
+ if (major != NULL)
+ *major = SM_LM_VRS_MAJOR(SMFI_VERSION);
+ if (minor != NULL)
+ *minor = SM_LM_VRS_MINOR(SMFI_VERSION);
+ if (patchlevel != NULL)
+ *patchlevel = SM_LM_VRS_MINOR(SMFI_VERSION);
+ return MI_SUCCESS;
+}
diff --git a/contrib/sendmail/libmilter/worker.c b/contrib/sendmail/libmilter/worker.c
new file mode 100644
index 000000000000..04026783f32a
--- /dev/null
+++ b/contrib/sendmail/libmilter/worker.c
@@ -0,0 +1,792 @@
+/*
+ * Copyright (c) 2003-2004, 2006 Sendmail, Inc. and its suppliers.
+ * All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set
+ * forth in the LICENSE file which can be found at the top level of
+ * the sendmail distribution.
+ *
+ * Contributed by Jose Marcio Martins da Cruz - Ecole des Mines de Paris
+ * Jose-Marcio.Martins@ensmp.fr
+ */
+
+#include
+SM_RCSID("@(#)$Id: worker.c,v 8.9 2006/12/18 18:26:51 ca Exp $")
+
+#include "libmilter.h"
+
+#if _FFR_WORKERS_POOL
+
+typedef struct taskmgr_S taskmgr_T;
+
+#define TM_SIGNATURE 0x23021957
+
+struct taskmgr_S
+{
+ long tm_signature; /* has the controller been initialized */
+ sthread_t tm_tid; /* thread id of controller */
+ smfi_hd_T tm_ctx_head; /* head of the linked list of contexts */
+
+ int tm_nb_workers; /* number of workers in the pool */
+ int tm_nb_idle; /* number of workers waiting */
+
+ int tm_p[2]; /* poll control pipe */
+
+ smutex_t tm_w_mutex; /* linked list access mutex */
+ scond_t tm_w_cond; /* */
+};
+
+static taskmgr_T Tskmgr = {0};
+
+#define WRK_CTX_HEAD Tskmgr.tm_ctx_head
+
+#define RD_PIPE (Tskmgr.tm_p[0])
+#define WR_PIPE (Tskmgr.tm_p[1])
+
+#define PIPE_SEND_SIGNAL() \
+ do \
+ { \
+ char evt = 0x5a; \
+ int fd = WR_PIPE; \
+ if (write(fd, &evt, sizeof(evt)) != sizeof(evt)) \
+ smi_log(SMI_LOG_ERR, \
+ "Error writing to event pipe: %s", \
+ sm_errstring(errno)); \
+ } while (0)
+
+#ifndef USE_PIPE_WAKE_POLL
+# define USE_PIPE_WAKE_POLL 1
+#endif /* USE_PIPE_WAKE_POLL */
+
+/* poll check periodicity (default 10000 - 10 s) */
+#define POLL_TIMEOUT 10000
+
+/* worker conditional wait timeout (default 10 s) */
+#define COND_TIMEOUT 10
+
+/* functions */
+static int mi_close_session __P((SMFICTX_PTR));
+
+static void *mi_worker __P((void *));
+static void *mi_pool_controller __P((void *));
+
+static int mi_list_add_ctx __P((SMFICTX_PTR));
+static int mi_list_del_ctx __P((SMFICTX_PTR));
+
+/*
+** periodicity of cleaning up old sessions (timedout)
+** sessions list will be checked to find old inactive
+** sessions each DT_CHECK_OLD_SESSIONS sec
+*/
+
+#define DT_CHECK_OLD_SESSIONS 600
+
+#ifndef OLD_SESSION_TIMEOUT
+# define OLD_SESSION_TIMEOUT ctx->ctx_timeout
+#endif /* OLD_SESSION_TIMEOUT */
+
+/* session states - with respect to the pool of workers */
+#define WKST_INIT 0 /* initial state */
+#define WKST_READY_TO_RUN 1 /* command ready do be read */
+#define WKST_RUNNING 2 /* session running on a worker */
+#define WKST_READY_TO_WAIT 3 /* session just finished by a worker */
+#define WKST_WAITING 4 /* waiting for new command */
+#define WKST_CLOSING 5 /* session finished */
+
+#ifndef MIN_WORKERS
+# define MIN_WORKERS 2 /* minimum number of threads to keep around */
+#endif
+
+#define MIN_IDLE 1 /* minimum number of idle threads */
+
+
+/*
+** Macros for threads and mutex management
+*/
+
+#define TASKMGR_LOCK() \
+ do \
+ { \
+ if (!smutex_lock(&Tskmgr.tm_w_mutex)) \
+ smi_log(SMI_LOG_ERR, "TASKMGR_LOCK error"); \
+ } while (0)
+
+#define TASKMGR_UNLOCK() \
+ do \
+ { \
+ if (!smutex_unlock(&Tskmgr.tm_w_mutex)) \
+ smi_log(SMI_LOG_ERR, "TASKMGR_UNLOCK error"); \
+ } while (0)
+
+#define TASKMGR_COND_WAIT() \
+ scond_timedwait(&Tskmgr.tm_w_cond, &Tskmgr.tm_w_mutex, COND_TIMEOUT)
+
+#define TASKMGR_COND_SIGNAL() \
+ do \
+ { \
+ if (scond_signal(&Tskmgr.tm_w_cond) != 0) \
+ smi_log(SMI_LOG_ERR, "TASKMGR_COND_SIGNAL error"); \
+ } while (0)
+
+#define LAUNCH_WORKER(ctx) \
+ do \
+ { \
+ int r; \
+ sthread_t tid; \
+ \
+ if ((r = thread_create(&tid, mi_worker, ctx)) != 0) \
+ smi_log(SMI_LOG_ERR, "LAUNCH_WORKER error: %s",\
+ sm_errstring(r)); \
+ } while (0)
+
+#if POOL_DEBUG
+# define POOL_LEV_DPRINTF(lev, x) \
+ do { \
+ if ((lev) < ctx->ctx_dbg) \
+ sm_dprintf x; \
+ } while (0)
+#else /* POOL_DEBUG */
+# define POOL_LEV_DPRINTF(lev, x)
+#endif /* POOL_DEBUG */
+
+/*
+** MI_START_SESSION -- Start a session in the pool of workers
+**
+** Parameters:
+** ctx -- context structure
+**
+** Returns:
+** MI_SUCCESS/MI_FAILURE
+*/
+
+int
+mi_start_session(ctx)
+ SMFICTX_PTR ctx;
+{
+ static long id = 0;
+
+ SM_ASSERT(Tskmgr.tm_signature == TM_SIGNATURE);
+ SM_ASSERT(ctx != NULL);
+ POOL_LEV_DPRINTF(4, ("PIPE r=[%d] w=[%d]", RD_PIPE, WR_PIPE));
+ TASKMGR_LOCK();
+
+ if (mi_list_add_ctx(ctx) != MI_SUCCESS)
+ {
+ TASKMGR_UNLOCK();
+ return MI_FAILURE;
+ }
+
+ ctx->ctx_sid = id++;
+
+ /* if there is an idle worker, signal it, otherwise start new worker */
+ if (Tskmgr.tm_nb_idle > 0)
+ {
+ ctx->ctx_wstate = WKST_READY_TO_RUN;
+ TASKMGR_COND_SIGNAL();
+ }
+ else
+ {
+ ctx->ctx_wstate = WKST_RUNNING;
+ LAUNCH_WORKER(ctx);
+ }
+ TASKMGR_UNLOCK();
+ return MI_SUCCESS;
+}
+
+/*
+** MI_CLOSE_SESSION -- Close a session and clean up data structures
+**
+** Parameters:
+** ctx -- context structure
+**
+** Returns:
+** MI_SUCCESS/MI_FAILURE
+*/
+
+static int
+mi_close_session(ctx)
+ SMFICTX_PTR ctx;
+{
+ SM_ASSERT(ctx != NULL);
+
+ (void) mi_list_del_ctx(ctx);
+ if (ValidSocket(ctx->ctx_sd))
+ {
+ (void) closesocket(ctx->ctx_sd);
+ ctx->ctx_sd = INVALID_SOCKET;
+ }
+ if (ctx->ctx_reply != NULL)
+ {
+ free(ctx->ctx_reply);
+ ctx->ctx_reply = NULL;
+ }
+ if (ctx->ctx_privdata != NULL)
+ {
+ smi_log(SMI_LOG_WARN, "%s: private data not NULL",
+ ctx->ctx_smfi->xxfi_name);
+ }
+ mi_clr_macros(ctx, 0);
+ free(ctx);
+
+ return MI_SUCCESS;
+}
+
+/*
+** MI_POOL_CONTROLER_INIT -- Launch the worker pool controller
+** Must be called before starting sessions.
+**
+** Parameters:
+** none
+**
+** Returns:
+** MI_SUCCESS/MI_FAILURE
+*/
+
+int
+mi_pool_controller_init()
+{
+ sthread_t tid;
+ int r, i;
+
+ if (Tskmgr.tm_signature == TM_SIGNATURE)
+ return MI_SUCCESS;
+
+ SM_TAILQ_INIT(&WRK_CTX_HEAD);
+ Tskmgr.tm_tid = (sthread_t) -1;
+ Tskmgr.tm_nb_workers = 0;
+ Tskmgr.tm_nb_idle = 0;
+
+ if (pipe(Tskmgr.tm_p) != 0)
+ {
+ smi_log(SMI_LOG_ERR, "can't create event pipe: %s",
+ sm_errstring(r));
+ return MI_FAILURE;
+ }
+
+ POOL_LEV_DPRINTF(4, ("PIPE r=[%d] w=[%d]", RD_PIPE, WR_PIPE));
+
+ (void) smutex_init(&Tskmgr.tm_w_mutex);
+ (void) scond_init(&Tskmgr.tm_w_cond);
+
+ /* Launch the pool controller */
+ if ((r = thread_create(&tid, mi_pool_controller, (void *) NULL)) != 0)
+ {
+ smi_log(SMI_LOG_ERR, "can't create controller thread: %s",
+ sm_errstring(r));
+ return MI_FAILURE;
+ }
+ Tskmgr.tm_tid = tid;
+ Tskmgr.tm_signature = TM_SIGNATURE;
+
+ /* Create the pool of workers */
+ for (i = 0; i < MIN_WORKERS; i++)
+ {
+ if ((r = thread_create(&tid, mi_worker, (void *) NULL)) != 0)
+ {
+ smi_log(SMI_LOG_ERR, "can't create workers crew: %s",
+ sm_errstring(r));
+ return MI_FAILURE;
+ }
+ }
+
+ return MI_SUCCESS;
+}
+
+/*
+** MI_POOL_CONTROLLER -- manage the pool of workers
+** This thread must be running when listener begins
+** starting sessions
+**
+** Parameters:
+** arg -- unused
+**
+** Returns:
+** NULL
+**
+** Control flow:
+** for (;;)
+** Look for timed out sessions
+** Select sessions to wait for sendmail command
+** Poll set of file descriptors
+** if timeout
+** continue
+** For each file descriptor ready
+** launch new thread if no worker available
+** else
+** signal waiting worker
+*/
+
+/* Poll structure array (pollfd) size step */
+#define PFD_STEP 256
+
+#define WAIT_FD(i) (pfd[i].fd)
+#define WAITFN "POLL"
+
+static void *
+mi_pool_controller(arg)
+ void *arg;
+{
+ struct pollfd *pfd = NULL;
+ int dim_pfd = 0;
+ bool rebuild_set = true;
+ int pcnt = 0; /* error count for poll() failures */
+
+ Tskmgr.tm_tid = sthread_get_id();
+ if (pthread_detach(Tskmgr.tm_tid) != 0)
+ {
+ smi_log(SMI_LOG_ERR, "Failed to detach pool controller thread");
+ return NULL;
+ }
+
+ pfd = (struct pollfd *) malloc(PFD_STEP * sizeof(struct pollfd));
+ if (pfd == NULL)
+ {
+ smi_log(SMI_LOG_ERR, "Failed to malloc pollfd array: %s",
+ sm_errstring(errno));
+ return NULL;
+ }
+ dim_pfd = PFD_STEP;
+
+ for (;;)
+ {
+ SMFICTX_PTR ctx;
+ int nfd, rfd, i;
+ time_t now;
+ time_t lastcheck;
+
+ POOL_LEV_DPRINTF(4, ("Let's %s again...", WAITFN));
+
+ if (mi_stop() != MILTER_CONT)
+ break;
+
+ TASKMGR_LOCK();
+
+ now = time(NULL);
+
+ /* check for timed out sessions? */
+ if (lastcheck + DT_CHECK_OLD_SESSIONS < now)
+ {
+ SM_TAILQ_FOREACH(ctx, &WRK_CTX_HEAD, ctx_link)
+ {
+ if (ctx->ctx_wstate == WKST_WAITING)
+ {
+ if (ctx->ctx_wait == 0)
+ {
+ ctx->ctx_wait = now;
+ continue;
+ }
+
+ /* if session timed out, close it */
+ if (ctx->ctx_wait + OLD_SESSION_TIMEOUT
+ < now)
+ {
+ sfsistat (*fi_close) __P((SMFICTX *));
+
+ POOL_LEV_DPRINTF(4,
+ ("Closing old connection: sd=%d id=%d",
+ ctx->ctx_sd,
+ ctx->ctx_sid));
+
+ if ((fi_close = ctx->ctx_smfi->xxfi_close) != NULL)
+ (void) (*fi_close)(ctx);
+
+ mi_close_session(ctx);
+ ctx = SM_TAILQ_FIRST(&WRK_CTX_HEAD);
+ continue;
+ }
+ }
+ }
+ lastcheck = now;
+ }
+
+ if (rebuild_set)
+ {
+ /*
+ ** Initialize poll set.
+ ** Insert into the poll set the file descriptors of
+ ** all sessions waiting for a command from sendmail.
+ */
+
+ nfd = 0;
+
+ /* begin with worker pipe */
+ pfd[nfd].fd = RD_PIPE;
+ pfd[nfd].events = MI_POLL_RD_FLAGS;
+ pfd[nfd].revents = 0;
+ nfd++;
+
+ SM_TAILQ_FOREACH(ctx, &WRK_CTX_HEAD, ctx_link)
+ {
+ /*
+ ** update ctx_wait - start of wait moment -
+ ** for timeout
+ */
+
+ if (ctx->ctx_wstate == WKST_READY_TO_WAIT)
+ ctx->ctx_wait = now;
+
+ /* add the session to the pollfd array? */
+ if ((ctx->ctx_wstate == WKST_READY_TO_WAIT) ||
+ (ctx->ctx_wstate == WKST_WAITING))
+ {
+ /*
+ ** Resize the pollfd array if it
+ ** isn't large enough.
+ */
+
+ if (nfd >= dim_pfd)
+ {
+ struct pollfd *tpfd;
+ size_t new;
+
+ new = (dim_pfd + PFD_STEP) *
+ sizeof(*tpfd);
+ tpfd = (struct pollfd *)
+ realloc(pfd, new);
+ if (tpfd != NULL)
+ {
+ pfd = tpfd;
+ dim_pfd += PFD_STEP;
+ }
+ else
+ {
+ smi_log(SMI_LOG_ERR,
+ "Failed to realloc pollfd array:%s",
+ sm_errstring(errno));
+ }
+ }
+
+ /* add the session to pollfd array */
+ if (nfd < dim_pfd)
+ {
+ ctx->ctx_wstate = WKST_WAITING;
+ pfd[nfd].fd = ctx->ctx_sd;
+ pfd[nfd].events = MI_POLL_RD_FLAGS;
+ pfd[nfd].revents = 0;
+ nfd++;
+ }
+ }
+ }
+ }
+
+ TASKMGR_UNLOCK();
+
+ /* Everything is ready, let's wait for an event */
+ rfd = poll(pfd, nfd, POLL_TIMEOUT);
+
+ POOL_LEV_DPRINTF(4, ("%s returned: at epoch %d value %d",
+ WAITFN, now, nfd));
+
+ /* timeout */
+ if (rfd == 0)
+ continue;
+
+ rebuild_set = true;
+
+ /* error */
+ if (rfd < 0)
+ {
+ if (errno == EINTR)
+ continue;
+ pcnt++;
+ smi_log(SMI_LOG_ERR,
+ "%s() failed (%s), %s",
+ WAITFN, sm_errstring(errno),
+ pcnt >= MAX_FAILS_S ? "abort" : "try again");
+
+ if (pcnt >= MAX_FAILS_S)
+ goto err;
+ }
+ pcnt = 0;
+
+ /* something happened */
+ for (i = 0; i < nfd; i++)
+ {
+ if (pfd[i].revents == 0)
+ continue;
+
+ POOL_LEV_DPRINTF(4, ("%s event on pfd[%d/%d]=%d ",
+ WAITFN, i, nfd,
+ WAIT_FD(i)));
+
+ /* has a worker signaled an end of task ? */
+ if (WAIT_FD(i) == RD_PIPE)
+ {
+ char evt = 0;
+ int r = 0;
+
+ POOL_LEV_DPRINTF(4,
+ ("PIPE WILL READ evt = %08X %08X",
+ pfd[i].events, pfd[i].revents));
+
+ if ((pfd[i].revents & MI_POLL_RD_FLAGS) != 0)
+ {
+ r = read(RD_PIPE, &evt, sizeof(evt));
+ if (r == sizeof(evt))
+ {
+ /* Do nothing */
+ }
+ }
+
+ POOL_LEV_DPRINTF(4,
+ ("PIPE DONE READ i=[%d] fd=[%d] r=[%d] evt=[%d]",
+ i, RD_PIPE, r, evt));
+
+ if ((pfd[i].revents & ~MI_POLL_RD_FLAGS) != 0)
+ {
+ /* Exception handling */
+ }
+ continue;
+ }
+
+ /* no ! sendmail wants to send a command */
+ SM_TAILQ_FOREACH(ctx, &WRK_CTX_HEAD, ctx_link)
+ {
+ if (ctx->ctx_wstate != WKST_WAITING)
+ continue;
+
+ POOL_LEV_DPRINTF(4,
+ ("Checking context sd=%d - fd=%d ",
+ ctx->ctx_sd , WAIT_FD(i)));
+
+ if (ctx->ctx_sd == pfd[i].fd)
+ {
+ TASKMGR_LOCK();
+
+ POOL_LEV_DPRINTF(4,
+ ("TASK: found %d for fd[%d]=%d",
+ ctx->ctx_sid, i, WAIT_FD(i)));
+
+ if (Tskmgr.tm_nb_idle > 0)
+ {
+ ctx->ctx_wstate = WKST_READY_TO_RUN;
+ TASKMGR_COND_SIGNAL();
+ }
+ else
+ {
+ ctx->ctx_wstate = WKST_RUNNING;
+ LAUNCH_WORKER(ctx);
+ }
+ TASKMGR_UNLOCK();
+ break;
+ }
+ }
+
+ POOL_LEV_DPRINTF(4,
+ ("TASK %s FOUND - Checking PIPE for fd[%d]",
+ ctx != NULL ? "" : "NOT", WAIT_FD(i)));
+ }
+ }
+
+ err:
+ if (pfd != NULL)
+ free(pfd);
+
+ Tskmgr.tm_signature = 0;
+ for (;;)
+ {
+ SMFICTX_PTR ctx;
+
+ ctx = SM_TAILQ_FIRST(&WRK_CTX_HEAD);
+ if (ctx == NULL)
+ break;
+ mi_close_session(ctx);
+ }
+
+ (void) smutex_destroy(&Tskmgr.tm_w_mutex);
+ (void) scond_destroy(&Tskmgr.tm_w_cond);
+
+ return NULL;
+}
+
+/*
+** Look for a task ready to run.
+** Value of ctx is NULL or a pointer to a task ready to run.
+*/
+
+#define GET_TASK_READY_TO_RUN() \
+ SM_TAILQ_FOREACH(ctx, &WRK_CTX_HEAD, ctx_link) \
+ { \
+ if (ctx->ctx_wstate == WKST_READY_TO_RUN) \
+ { \
+ ctx->ctx_wstate = WKST_RUNNING; \
+ break; \
+ } \
+ }
+
+/*
+** MI_WORKER -- worker thread
+** executes tasks distributed by the mi_pool_controller
+** or by mi_start_session
+**
+** Parameters:
+** arg -- pointer to context structure
+**
+** Returns:
+** NULL pointer
+*/
+
+static void *
+mi_worker(arg)
+ void *arg;
+{
+ SMFICTX_PTR ctx;
+ bool done;
+ sthread_t t_id;
+ int r;
+
+ ctx = (SMFICTX_PTR) arg;
+ done = false;
+ if (ctx != NULL)
+ ctx->ctx_wstate = WKST_RUNNING;
+
+ t_id = sthread_get_id();
+ if (pthread_detach(t_id) != 0)
+ {
+ smi_log(SMI_LOG_ERR, "Failed to detach worker thread");
+ if (ctx != NULL)
+ ctx->ctx_wstate = WKST_READY_TO_RUN;
+ return NULL;
+ }
+
+ TASKMGR_LOCK();
+ Tskmgr.tm_nb_workers++;
+ TASKMGR_UNLOCK();
+
+ while (!done)
+ {
+ if (mi_stop() != MILTER_CONT)
+ break;
+
+ /* let's handle next task... */
+ if (ctx != NULL)
+ {
+ int res;
+
+ POOL_LEV_DPRINTF(4,
+ ("worker %d: new task -> let's handle it",
+ t_id));
+ res = mi_engine(ctx);
+ POOL_LEV_DPRINTF(4,
+ ("worker %d: mi_engine returned %d", t_id, res));
+
+ TASKMGR_LOCK();
+ if (res != MI_CONTINUE)
+ {
+ ctx->ctx_wstate = WKST_CLOSING;
+
+ /*
+ ** Delete context from linked list of
+ ** sessions and close session.
+ */
+
+ mi_close_session(ctx);
+ }
+ else
+ {
+ ctx->ctx_wstate = WKST_READY_TO_WAIT;
+
+ POOL_LEV_DPRINTF(4,
+ ("writing to event pipe..."));
+
+ /*
+ ** Signal task controller to add new session
+ ** to poll set.
+ */
+
+ PIPE_SEND_SIGNAL();
+ }
+ TASKMGR_UNLOCK();
+ ctx = NULL;
+
+ }
+
+ /* check if there is any task waiting to be served */
+ TASKMGR_LOCK();
+
+ GET_TASK_READY_TO_RUN();
+
+ /* Got a task? */
+ if (ctx != NULL)
+ {
+ TASKMGR_UNLOCK();
+ continue;
+ }
+
+ /*
+ ** if not, let's check if there is enough idle workers
+ ** if yes: quit
+ */
+
+ if (Tskmgr.tm_nb_workers > MIN_WORKERS &&
+ Tskmgr.tm_nb_idle > MIN_IDLE)
+ done = true;
+
+ POOL_LEV_DPRINTF(4, ("worker %d: checking ... %d %d", t_id,
+ Tskmgr.tm_nb_workers, Tskmgr.tm_nb_idle + 1));
+
+ if (done)
+ {
+ POOL_LEV_DPRINTF(4, ("worker %d: quitting... ", t_id));
+ Tskmgr.tm_nb_workers--;
+ TASKMGR_UNLOCK();
+ continue;
+ }
+
+ /*
+ ** if no task ready to run, wait for another one
+ */
+
+ Tskmgr.tm_nb_idle++;
+ TASKMGR_COND_WAIT();
+ Tskmgr.tm_nb_idle--;
+
+ /* look for a task */
+ GET_TASK_READY_TO_RUN();
+
+ TASKMGR_UNLOCK();
+ }
+ return NULL;
+}
+
+/*
+** MI_LIST_ADD_CTX -- add new session to linked list
+**
+** Parameters:
+** ctx -- context structure
+**
+** Returns:
+** MI_FAILURE/MI_SUCCESS
+*/
+
+static int
+mi_list_add_ctx(ctx)
+ SMFICTX_PTR ctx;
+{
+ SM_ASSERT(ctx != NULL);
+ SM_TAILQ_INSERT_TAIL(&WRK_CTX_HEAD, ctx, ctx_link);
+ return MI_SUCCESS;
+}
+
+/*
+** MI_LIST_DEL_CTX -- remove session from linked list when finished
+**
+** Parameters:
+** ctx -- context structure
+**
+** Returns:
+** MI_FAILURE/MI_SUCCESS
+*/
+
+static int
+mi_list_del_ctx(ctx)
+ SMFICTX_PTR ctx;
+{
+ SM_ASSERT(ctx != NULL);
+ if (SM_TAILQ_EMPTY(&WRK_CTX_HEAD))
+ return MI_FAILURE;
+
+ SM_TAILQ_REMOVE(&WRK_CTX_HEAD, ctx, ctx_link);
+ return MI_SUCCESS;
+}
+#endif /* _FFR_WORKERS_POOL */
diff --git a/contrib/sendmail/libsm/Makefile b/contrib/sendmail/libsm/Makefile
index c6c1a293d5b8..e7b64ca39dd5 100644
--- a/contrib/sendmail/libsm/Makefile
+++ b/contrib/sendmail/libsm/Makefile
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.1 2000/03/27 19:26:48 dmoen Exp $
+# $Id: Makefile,v 1.2 2006/08/16 21:06:30 ca Exp $
SHELL= /bin/sh
BUILD= ./Build
@@ -10,6 +10,8 @@ clean: FRC
$(SHELL) $(BUILD) $(OPTIONS) $@
install: FRC
$(SHELL) $(BUILD) $(OPTIONS) $@
+check: FRC
+ $(SHELL) $(BUILD) $(OPTIONS) $@
fresh: FRC
$(SHELL) $(BUILD) $(OPTIONS) -c
diff --git a/contrib/sendmail/libsm/Makefile.m4 b/contrib/sendmail/libsm/Makefile.m4
index 1bd3cab01a01..da5dd5519c41 100644
--- a/contrib/sendmail/libsm/Makefile.m4
+++ b/contrib/sendmail/libsm/Makefile.m4
@@ -1,38 +1,44 @@
-dnl $Id: Makefile.m4,v 1.70 2005/12/22 18:31:11 ca Exp $
+dnl $Id: Makefile.m4,v 1.72 2006/08/16 21:06:31 ca Exp $
define(`confREQUIRE_LIBUNIX')
include(confBUILDTOOLSDIR`/M4/switch.m4')
define(`confREQUIRE_LIBSM', `true')
+define(`confREQUIRE_SM_OS_H', `true')
PREPENDDEF(`confENVDEF', `confMAPDEF')
bldPRODUCT_START(`library', `libsm')
-define(`bldSOURCES', ` assert.c debug.c errstring.c exc.c heap.c match.c rpool.c strdup.c strerror.c strl.c clrerr.c fclose.c feof.c ferror.c fflush.c fget.c fpos.c findfp.c flags.c fopen.c fprintf.c fpurge.c fput.c fread.c fscanf.c fseek.c fvwrite.c fwalk.c fwrite.c get.c makebuf.c put.c refill.c rewind.c setvbuf.c smstdio.c snprintf.c sscanf.c stdio.c strio.c ungetc.c vasprintf.c vfprintf.c vfscanf.c vprintf.c vsnprintf.c wbuf.c wsetup.c string.c stringf.c xtrap.c strto.c test.c path.c strcasecmp.c strrevcmp.c signal.c clock.c config.c shm.c sem.c mbdb.c strexit.c cf.c ldap.c niprop.c mpeix.c memstat.c ')
+define(`bldSOURCES', ` assert.c debug.c errstring.c exc.c heap.c match.c rpool.c strdup.c strerror.c strl.c clrerr.c fclose.c feof.c ferror.c fflush.c fget.c fpos.c findfp.c flags.c fopen.c fprintf.c fpurge.c fput.c fread.c fscanf.c fseek.c fvwrite.c fwalk.c fwrite.c get.c makebuf.c put.c refill.c rewind.c setvbuf.c smstdio.c snprintf.c sscanf.c stdio.c strio.c ungetc.c vasprintf.c vfprintf.c vfscanf.c vprintf.c vsnprintf.c wbuf.c wsetup.c string.c stringf.c xtrap.c strto.c test.c path.c strcasecmp.c strrevcmp.c signal.c clock.c config.c shm.c sem.c mbdb.c strexit.c cf.c ldap.c niprop.c mpeix.c memstat.c util.c ')
bldPRODUCT_END
dnl msg.c
dnl syslogio.c
-include(confBUILDTOOLSDIR`/M4/'bldM4_TYPE_DIR`/sm-test.m4')
-smtest(`t-event', `run')
-smtest(`t-exc', `run')
-smtest(`t-rpool', `run')
-smtest(`t-string', `run')
-smtest(`t-smstdio', `run')
-smtest(`t-match', `run')
-smtest(`t-strio', `run')
-smtest(`t-heap', `run')
-smtest(`t-fopen', `run')
-smtest(`t-strl', `run')
-smtest(`t-strrevcmp', `run')
-smtest(`t-types', `run')
-smtest(`t-path', `run')
-smtest(`t-float', `run')
-smtest(`t-scanf', `run')
-smtest(`t-shm', `run')
-smtest(`t-sem', `run')
-dnl smtest(`t-msg', `run')
-smtest(`t-cf')
-smtest(`b-strcmp')
+define(`confCHECK_LIBS',`libsm.a')dnl
+include(confBUILDTOOLSDIR`/M4/'bldM4_TYPE_DIR`/check.m4')
+smcheck(`t-event', `compile-run')
+smcheck(`t-exc', `compile-run')
+smcheck(`t-rpool', `compile-run')
+smcheck(`t-string', `compile-run')
+smcheck(`t-smstdio', `compile-run')
+smcheck(`t-match', `compile-run')
+smcheck(`t-strio', `compile-run')
+smcheck(`t-heap', `compile-run')
+smcheck(`t-fopen', `compile-run')
+smcheck(`t-strl', `compile-run')
+smcheck(`t-strrevcmp', `compile-run')
+smcheck(`t-types', `compile-run')
+smcheck(`t-path', `compile-run')
+smcheck(`t-float', `compile-run')
+smcheck(`t-scanf', `compile-run')
+smcheck(`t-shm', `compile-run')
+smcheck(`t-sem', `compile-run')
+dnl smcheck(`t-msg', `compile-run')
+smcheck(`t-cf')
+smcheck(`b-strcmp')
dnl SM_CONF_STRL cannot be turned off
-dnl smtest(`b-strl')
-smtest(`t-memstat')
+dnl smcheck(`b-strl')
+smcheck(`t-memstat')
+
+smcheck(`t-qic', `compile-run')
+divert(bldTARGETS_SECTION)
+divert(0)
bldFINISH
diff --git a/contrib/sendmail/libsm/config.c b/contrib/sendmail/libsm/config.c
index a5e13270a096..c96a7386cf89 100644
--- a/contrib/sendmail/libsm/config.c
+++ b/contrib/sendmail/libsm/config.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000-2003 Sendmail, Inc. and its suppliers.
+ * Copyright (c) 2000-2003, 2007 Sendmail, Inc. and its suppliers.
* All rights reserved.
*
* By using this file, you agree to the terms and conditions set
@@ -9,7 +9,7 @@
*/
#include
-SM_RCSID("@(#)$Id: config.c,v 1.30 2003/12/10 03:19:07 gshapiro Exp $")
+SM_RCSID("@(#)$Id: config.c,v 1.31 2007/03/14 21:21:49 ca Exp $")
#include
#include
@@ -247,5 +247,14 @@ char *SmCompileOptions[] =
#if SM_VA_STD
"SM_VA_STD",
#endif /* SM_VA_STD */
+#if USEKSTAT
+ "USEKSTAT",
+#endif /* USEKSTAT */
+#if USEPROCMEMINFO
+ "USEPROCMEMINFO",
+#endif /* USEPROCMEMINFO */
+#if USESWAPCTL
+ "USESWAPCTL",
+#endif /* USESWAPCTL */
NULL
};
diff --git a/contrib/sendmail/libsm/exc.c b/contrib/sendmail/libsm/exc.c
index 26ad020ba753..0bcf17a68400 100644
--- a/contrib/sendmail/libsm/exc.c
+++ b/contrib/sendmail/libsm/exc.c
@@ -9,7 +9,7 @@
*/
#include
-SM_RCSID("@(#)$Id: exc.c,v 1.48 2003/12/05 22:45:24 ca Exp $")
+SM_RCSID("@(#)$Id: exc.c,v 1.49 2006/12/19 19:28:09 ca Exp $")
/*
** exception handling
@@ -229,7 +229,9 @@ const SM_EXC_TYPE_T SmEtypeErr =
** an out-of-memory exception so that exc is not leaked.
*/
-SM_EXC_T *
+static SM_EXC_T *sm_exc_vnew_x __P((const SM_EXC_TYPE_T *, va_list SM_NONVOLATILE));
+
+static SM_EXC_T *
sm_exc_vnew_x(etype, ap)
const SM_EXC_TYPE_T *etype;
va_list SM_NONVOLATILE ap;
@@ -418,26 +420,6 @@ sm_exc_new_x(etype, va_alist)
return exc;
}
-/*
-** SM_ADDREF -- Add a reference to an exception object.
-**
-** Parameters:
-** exc -- exception object.
-**
-** Returns:
-** exc itself.
-*/
-
-SM_EXC_T *
-sm_addref(exc)
- SM_EXC_T *exc;
-{
- SM_REQUIRE_ISA(exc, SmExcMagic);
- if (exc->exc_refcount != 0)
- ++exc->exc_refcount;
- return exc;
-}
-
/*
** SM_EXC_FREE -- Destroy a reference to an exception object.
**
diff --git a/contrib/sendmail/libsm/exc.html b/contrib/sendmail/libsm/exc.html
index a2990363ce8c..669ebe213236 100644
--- a/contrib/sendmail/libsm/exc.html
+++ b/contrib/sendmail/libsm/exc.html
@@ -8,7 +8,7 @@
libsm : Exception Handling
-
$Id: exc.html,v 1.12 2001/02/13 21:21:25 gshapiro Exp $
+
$Id: exc.html,v 1.13 2006/06/20 17:18:16 ca Exp $
Introduction
@@ -28,7 +28,7 @@ Here are the basic concepts:
Errors are not represented by a single integer error code,
- because that you can't represent everything that an error handler
+ because then you can't represent everything that an error handler
might need to know about an error by a single integer.
Instead, errors are represented by exception objects.
An exception object contains an exception code and an array
diff --git a/contrib/sendmail/libsm/findfp.c b/contrib/sendmail/libsm/findfp.c
index 115ed22fa85b..1658929ad05e 100644
--- a/contrib/sendmail/libsm/findfp.c
+++ b/contrib/sendmail/libsm/findfp.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000-2002 Sendmail, Inc. and its suppliers.
+ * Copyright (c) 2000-2002, 2006 Sendmail, Inc. and its suppliers.
* All rights reserved.
* Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
@@ -13,7 +13,7 @@
*/
#include
-SM_RCSID("@(#)$Id: findfp.c,v 1.66 2002/02/20 02:40:24 ca Exp $")
+SM_RCSID("@(#)$Id: findfp.c,v 1.67 2006/08/28 21:24:46 ca Exp $")
#include
#include
#include
@@ -365,6 +365,11 @@ sm_io_getinfo(fp, what, valp)
switch (what)
{
case SM_IO_WHAT_VECTORS:
+ if (valp == NULL)
+ {
+ errno = EINVAL;
+ return -1;
+ }
/* This is the "generic" available for all */
v->f_close = fp->f_close;
diff --git a/contrib/sendmail/libsm/flags.c b/contrib/sendmail/libsm/flags.c
index 94ecd5cbe9e1..97c38fa5ffd1 100644
--- a/contrib/sendmail/libsm/flags.c
+++ b/contrib/sendmail/libsm/flags.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000-2001, 2004 Sendmail, Inc. and its suppliers.
+ * Copyright (c) 2000-2001, 2004, 2006 Sendmail, Inc. and its suppliers.
* All rights reserved.
* Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
@@ -13,11 +13,12 @@
*/
#include
-SM_RCSID("@(#)$Id: flags.c,v 1.22 2004/03/03 19:20:29 ca Exp $")
+SM_RCSID("@(#)$Id: flags.c,v 1.23 2006/12/19 19:44:23 ca Exp $")
#include
#include
#include
#include
+#include "local.h"
/*
** SM_FLAGS -- translate external (user) flags into internal flags
@@ -31,9 +32,9 @@ SM_RCSID("@(#)$Id: flags.c,v 1.22 2004/03/03 19:20:29 ca Exp $")
int
sm_flags(flags)
- register int flags;
+ int flags;
{
- register int ret;
+ int ret;
switch(SM_IO_MODE(flags))
{
diff --git a/contrib/sendmail/libsm/ldap.c b/contrib/sendmail/libsm/ldap.c
index 76e91b33bf46..83b7644515dd 100644
--- a/contrib/sendmail/libsm/ldap.c
+++ b/contrib/sendmail/libsm/ldap.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001-2005 Sendmail, Inc. and its suppliers.
+ * Copyright (c) 2001-2006 Sendmail, Inc. and its suppliers.
* All rights reserved.
*
* By using this file, you agree to the terms and conditions set
@@ -7,8 +7,11 @@
* the sendmail distribution.
*/
+/* some "deprecated" calls are used, e.g., ldap_get_values() */
+#define LDAP_DEPRECATED 1
+
#include
-SM_RCSID("@(#)$Id: ldap.c,v 1.67 2005/12/14 00:08:03 ca Exp $")
+SM_RCSID("@(#)$Id: ldap.c,v 1.78 2006/08/30 22:56:59 ca Exp $")
#if LDAPMAP
# include
@@ -95,6 +98,7 @@ sm_ldap_clear(lmap)
lmap->ldap_res = NULL;
lmap->ldap_next = NULL;
lmap->ldap_pid = 0;
+ lmap->ldap_multi_args = false;
}
/*
@@ -280,35 +284,67 @@ ldaptimeout(unused)
}
/*
-** SM_LDAP_SEARCH -- initiate LDAP search
+** SM_LDAP_SEARCH_M -- initiate multi-key LDAP search
**
** Initiate an LDAP search, return the msgid.
** The calling function must collect the results.
**
** Parameters:
** lmap -- LDAP map information
-** key -- key to substitute in LDAP filter
+** argv -- key vector of substitutions in LDAP filter
+** NOTE: argv must have SM_LDAP_ARGS elements to prevent
+** out of bound array references
**
** Returns:
-** -1 on failure, msgid on success
+** <0 on failure (SM_LDAP_ERR*), msgid on success
**
*/
int
-sm_ldap_search(lmap, key)
+sm_ldap_search_m(lmap, argv)
SM_LDAP_STRUCT *lmap;
- char *key;
+ char **argv;
{
int msgid;
char *fp, *p, *q;
char filter[LDAPMAP_MAX_FILTER + 1];
- /* substitute key into filter, perhaps multiple times */
+ SM_REQUIRE(lmap != NULL);
+ SM_REQUIRE(argv != NULL);
+ SM_REQUIRE(argv[0] != NULL);
+
memset(filter, '\0', sizeof filter);
fp = filter;
p = lmap->ldap_filter;
while ((q = strchr(p, '%')) != NULL)
{
+ char *key;
+
+ if (lmap->ldap_multi_args)
+ {
+#if SM_LDAP_ARGS < 10
+# ERROR _SM_LDAP_ARGS must be 10
+#endif /* SM_LDAP_ARGS < 10 */
+ if (q[1] == 's')
+ key = argv[0];
+ else if (q[1] >= '0' && q[1] <= '9')
+ {
+ key = argv[q[1] - '0'];
+ if (key == NULL)
+ {
+# if SM_LDAP_ERROR_ON_MISSING_ARGS
+ return SM_LDAP_ERR_ARG_MISS;
+# else /* SM_LDAP_ERROR_ON_MISSING_ARGS */
+ key = "";
+# endif /* SM_LDAP_ERROR_ON_MISSING_ARGS */
+ }
+ }
+ else
+ key = NULL;
+ }
+ else
+ key = argv[0];
+
if (q[1] == 's')
{
(void) sm_snprintf(fp, SPACELEFT(filter, fp),
@@ -316,7 +352,8 @@ sm_ldap_search(lmap, key)
fp += strlen(fp);
p = q + 2;
}
- else if (q[1] == '0')
+ else if (q[1] == '0' ||
+ (lmap->ldap_multi_args && q[1] >= '0' && q[1] <= '9'))
{
char *k = key;
@@ -367,6 +404,34 @@ sm_ldap_search(lmap, key)
return msgid;
}
+/*
+** SM_LDAP_SEARCH -- initiate LDAP search
+**
+** Initiate an LDAP search, return the msgid.
+** The calling function must collect the results.
+** Note this is just a wrapper into sm_ldap_search_m()
+**
+** Parameters:
+** lmap -- LDAP map information
+** key -- key to substitute in LDAP filter
+**
+** Returns:
+** <0 on failure, msgid on success
+**
+*/
+
+int
+sm_ldap_search(lmap, key)
+ SM_LDAP_STRUCT *lmap;
+ char *key;
+{
+ char *argv[SM_LDAP_ARGS];
+
+ memset(argv, '\0', sizeof argv);
+ argv[0] = key;
+ return sm_ldap_search_m(lmap, argv);
+}
+
/*
** SM_LDAP_HAS_OBJECTCLASS -- determine if an LDAP entry is part of a
** particular objectClass
@@ -480,29 +545,29 @@ sm_ldap_add_recurse(top, item, type, rpool)
{
/* Allocate an initial SM_LDAP_RECURSE_LIST struct */
*top = sm_rpool_malloc_x(rpool, sizeof **top);
- (*top)->lr_cnt = 0;
- (*top)->lr_size = 0;
- (*top)->lr_data = NULL;
+ (*top)->lrl_cnt = 0;
+ (*top)->lrl_size = 0;
+ (*top)->lrl_data = NULL;
}
- if ((*top)->lr_cnt >= (*top)->lr_size)
+ if ((*top)->lrl_cnt >= (*top)->lrl_size)
{
/* Grow the list of SM_LDAP_RECURSE_ENTRY ptrs */
- olddata = (*top)->lr_data;
- if ((*top)->lr_size == 0)
+ olddata = (*top)->lrl_data;
+ if ((*top)->lrl_size == 0)
{
oldsizeb = 0;
- (*top)->lr_size = 256;
+ (*top)->lrl_size = 256;
}
else
{
- oldsizeb = (*top)->lr_size * sizeof *((*top)->lr_data);
- (*top)->lr_size *= 2;
+ oldsizeb = (*top)->lrl_size * sizeof *((*top)->lrl_data);
+ (*top)->lrl_size *= 2;
}
- (*top)->lr_data = sm_rpool_malloc_x(rpool,
- (*top)->lr_size * sizeof *((*top)->lr_data));
+ (*top)->lrl_data = sm_rpool_malloc_x(rpool,
+ (*top)->lrl_size * sizeof *((*top)->lrl_data));
if (oldsizeb > 0)
- memcpy((*top)->lr_data, olddata, oldsizeb);
+ memcpy((*top)->lrl_data, olddata, oldsizeb);
}
/*
@@ -511,7 +576,7 @@ sm_ldap_add_recurse(top, item, type, rpool)
*/
n = 0;
- m = (*top)->lr_cnt - 1;
+ m = (*top)->lrl_cnt - 1;
if (m < 0)
insertat = 0;
else
@@ -521,21 +586,21 @@ sm_ldap_add_recurse(top, item, type, rpool)
{
p = (m + n) / 2;
- rc = sm_strcasecmp(item, (*top)->lr_data[p]->lr_search);
+ rc = sm_strcasecmp(item, (*top)->lrl_data[p]->lr_search);
if (rc == 0)
- rc = type - (*top)->lr_data[p]->lr_type;
+ rc = type - (*top)->lrl_data[p]->lr_type;
if (rc < 0)
m = p - 1;
else if (rc > 0)
n = p + 1;
else
- return (*top)->lr_data[p];
+ return (*top)->lrl_data[p];
if (m == -1)
insertat = 0;
- else if (n >= (*top)->lr_cnt)
- insertat = (*top)->lr_cnt;
+ else if (n >= (*top)->lrl_cnt)
+ insertat = (*top)->lrl_cnt;
else if (m < n)
insertat = m + 1;
}
@@ -548,10 +613,10 @@ sm_ldap_add_recurse(top, item, type, rpool)
newe = sm_rpool_malloc_x(rpool, sizeof *newe);
if (newe != NULL)
{
- moveb = ((*top)->lr_cnt - insertat) * sizeof *((*top)->lr_data);
+ moveb = ((*top)->lrl_cnt - insertat) * sizeof *((*top)->lrl_data);
if (moveb > 0)
- memmove(&((*top)->lr_data[insertat + 1]),
- &((*top)->lr_data[insertat]),
+ memmove(&((*top)->lrl_data[insertat + 1]),
+ &((*top)->lrl_data[insertat]),
moveb);
newe->lr_search = sm_rpool_strdup_x(rpool, item);
@@ -560,8 +625,8 @@ sm_ldap_add_recurse(top, item, type, rpool)
newe->lr_attrs = NULL;
newe->lr_done = false;
- ((*top)->lr_data)[insertat] = newe;
- (*top)->lr_cnt++;
+ ((*top)->lrl_data)[insertat] = newe;
+ (*top)->lrl_cnt++;
}
return newe;
}
@@ -1082,13 +1147,14 @@ sm_ldap_results(lmap, msgid, flags, delim, rpool, result,
** will be expanded by the top level.
*/
- for (rlidx = 0; recurse != NULL && rlidx < recurse->lr_cnt; rlidx++)
+ for (rlidx = 0; recurse != NULL && rlidx < recurse->lrl_cnt;
+ rlidx++)
{
int newflags;
int sid;
int status;
- rl = recurse->lr_data[rlidx];
+ rl = recurse->lrl_data[rlidx];
newflags = flags;
if (rl->lr_done)
diff --git a/contrib/sendmail/libsm/local.h b/contrib/sendmail/libsm/local.h
index 7c7798eee662..b0625a56e347 100644
--- a/contrib/sendmail/libsm/local.h
+++ b/contrib/sendmail/libsm/local.h
@@ -11,7 +11,7 @@
* forth in the LICENSE file which can be found at the top level of
* the sendmail distribution.
*
- * $Id: local.h,v 1.57 2006/02/28 18:48:25 ca Exp $
+ * $Id: local.h,v 1.58 2006/12/19 19:44:23 ca Exp $
*/
/*
@@ -102,6 +102,8 @@ extern const char SmFileMagic[];
#define sm_io_flockfile(fp) ((void) 0)
#define sm_io_funlockfile(fp) ((void) 0)
+int sm_flags __P((int));
+
#ifndef FDSET_CAST
# define FDSET_CAST /* empty cast for fd_set arg to select */
#endif
diff --git a/contrib/sendmail/libsm/memstat.c b/contrib/sendmail/libsm/memstat.c
index 6c2a4d17278a..80391d757b3a 100644
--- a/contrib/sendmail/libsm/memstat.c
+++ b/contrib/sendmail/libsm/memstat.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005 Sendmail, Inc. and its suppliers.
+ * Copyright (c) 2005-2007 Sendmail, Inc. and its suppliers.
* All rights reserved.
*
* By using this file, you agree to the terms and conditions set
@@ -8,9 +8,10 @@
*/
#include
-SM_RCSID("@(#)$Id: memstat.c,v 1.4 2005/12/10 00:38:48 ca Exp $")
+SM_RCSID("@(#)$Id: memstat.c,v 1.6 2007/03/20 23:26:12 ca Exp $")
#include
+#include
#if USESWAPCTL
#include
@@ -265,6 +266,8 @@ sm_memstat_get(resource, pvalue)
return -1; /* try to reopen? */
rewind(fp);
l = strlen(resource);
+ if (l >= sizeof(buf))
+ return EINVAL;
while (fgets(buf, sizeof(buf), fp) != NULL)
{
if (strncmp(buf, resource, l) == 0 && buf[l] == ':')
diff --git a/contrib/sendmail/libsm/snprintf.c b/contrib/sendmail/libsm/snprintf.c
index 5ee3006e6ed5..cdb7688a55c2 100644
--- a/contrib/sendmail/libsm/snprintf.c
+++ b/contrib/sendmail/libsm/snprintf.c
@@ -13,10 +13,11 @@
*/
#include
-SM_RCSID("@(#)$Id: snprintf.c,v 1.23 2001/09/11 04:04:49 gshapiro Exp $")
+SM_RCSID("@(#)$Id: snprintf.c,v 1.24 2006/10/12 21:50:10 ca Exp $")
#include
#include
#include
+#include
#include "local.h"
/*
diff --git a/contrib/sendmail/libsm/t-memstat.c b/contrib/sendmail/libsm/t-memstat.c
index b3bd91891904..3bfe39415066 100644
--- a/contrib/sendmail/libsm/t-memstat.c
+++ b/contrib/sendmail/libsm/t-memstat.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2006 Sendmail, Inc. and its suppliers.
+ * Copyright (c) 2005-2007 Sendmail, Inc. and its suppliers.
* All rights reserved.
*
* By using this file, you agree to the terms and conditions set
@@ -8,7 +8,9 @@
*/
#include
-SM_IDSTR(id, "@(#)$Id: t-memstat.c,v 1.6 2006/03/27 22:34:47 ca Exp $")
+SM_IDSTR(id, "@(#)$Id: t-memstat.c,v 1.9 2007/03/14 21:41:09 ca Exp $")
+
+#include
/*
** Simple test program for memstat
@@ -23,6 +25,18 @@ SM_IDSTR(id, "@(#)$Id: t-memstat.c,v 1.6 2006/03/27 22:34:47 ca Exp $")
extern char *optarg;
extern int optind;
+void
+usage(prg)
+ char *prg;
+{
+ fprintf(stderr, "usage: %s [options]\n", prg);
+ fprintf(stderr, "options:\n");
+ fprintf(stderr, "-l n loop n times\n");
+ fprintf(stderr, "-m n allocate n bytes per iteration\n");
+ fprintf(stderr, "-r name use name as resource to query\n");
+ fprintf(stderr, "-s n sleep n seconds per iteration\n");
+}
+
int
main(argc, argv)
int argc;
@@ -56,7 +70,8 @@ main(argc, argv)
break;
default:
- break;
+ usage(argv[0]);
+ exit(1);
}
}
diff --git a/contrib/sendmail/libsm/t-qic.c b/contrib/sendmail/libsm/t-qic.c
new file mode 100644
index 000000000000..8a8e0c89e4aa
--- /dev/null
+++ b/contrib/sendmail/libsm/t-qic.c
@@ -0,0 +1,235 @@
+/*
+ * Copyright (c) 2006 Sendmail, Inc. and its suppliers.
+ * All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set
+ * forth in the LICENSE file which can be found at the top level of
+ * the sendmail distribution.
+ */
+
+#include
+SM_IDSTR(id, "@(#)$Id: t-qic.c,v 1.9 2006/08/24 21:26:13 ca Exp $")
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+extern bool SmTestVerbose;
+
+
+void
+show_diff(s1, s2)
+ const char *s1;
+ const char *s2;
+{
+ int i;
+
+ for (i = 0; s1[i] != '\0' && s2[i] != '\0'; i++)
+ {
+ if (s1[i] != s2[i])
+ {
+ fprintf(stderr, "i=%d, s1[]=%u, s2[]=%u\n",
+ i, (unsigned char) s1[i],
+ (unsigned char) s2[i]);
+ return;
+ }
+ }
+ if (s1[i] != s2[i])
+ {
+ fprintf(stderr, "i=%d, s1[]=%u, s2[]=%u\n",
+ i, (unsigned char) s1[i], (unsigned char) s2[i]);
+ }
+}
+
+char *quote_unquote __P((char *, char *, int, int));
+
+char *
+quote_unquote(in, out, outlen, exp)
+ char *in;
+ char *out;
+ int outlen;
+ int exp;
+{
+ char *obp, *bp;
+ char line_back[1024];
+ char line_in[1024];
+ int cmp;
+
+ sm_strlcpy(line_in, in, sizeof(line_in));
+ obp = quote_internal_chars(in, out, &outlen);
+ bp = str2prt(line_in);
+ dequote_internal_chars(obp, line_back, sizeof(line_back));
+ cmp = strcmp(line_in, line_back);
+ SM_TEST(exp == cmp);
+ if (cmp != exp && !SmTestVerbose)
+ {
+ fprintf(stderr, "in: %s\n", bp);
+ bp = str2prt(line_back);
+ fprintf(stderr, "out:%s\n", bp);
+ fprintf(stderr, "cmp=%d\n", cmp);
+ show_diff(in, line_back);
+ }
+ if (SmTestVerbose)
+ {
+ fprintf(stderr, "%s -> ", bp);
+ bp = str2prt(obp);
+ fprintf(stderr, "%s\n", bp);
+ fprintf(stderr, "cmp=%d\n", cmp);
+ }
+ return obp;
+}
+
+struct sm_qic_S
+{
+ char *qic_in;
+ char *qic_out;
+ int qic_exp;
+};
+
+typedef struct sm_qic_S sm_qic_T;
+
+
+int
+main(argc, argv)
+ int argc;
+ char *argv[];
+{
+ char line_in[1024], line[256], line_out[32], *obp;
+ int i, los, cmp;
+ sm_qic_T inout[] = {
+ { "", "", 0 }
+ , { "abcdef", "abcdef", 0 }
+ , { "01234567890123456789", "01234567890123456789", 0 }
+ , { "01234567890123456789\001", "01234567890123456789\001",
+ 0 }
+ , { "012345\2067890123456789", "012345\377\2067890123456789",
+ 0 }
+ , { "\377", "\377\377", 0 }
+ , { "\240", "\240", 0 }
+ , { "\220", "\377\220", 0 }
+ , { "\240\220", "\240\377\220", 0 }
+ , { "\377\377", "\377\377\377\377", 0 }
+ , { "\377a\377b", "\377\377a\377\377b", 0 }
+ , { "\376a\377b", "\376a\377\377b", 0 }
+ , { "\200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217\220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237\240",
+ "\377\200\377\201\377\202\377\203\377\204\377\205\377\206\377\207\377\210\377\211\377\212\377\213\377\214\377\215\377\216\377\217\377\220\377\221\377\222\377\223\377\224\377\225\377\226\377\227\377\230\377\231\377\232\377\233\377\234\377\235\377\236\377\237\240",
+ 0 }
+ , { NULL, NULL, 0 }
+ };
+
+ sm_test_begin(argc, argv, "test meta quoting");
+ for (i = 0; i < sizeof(line_out); i++)
+ line_out[i] = '\0';
+ for (i = 0; i < sizeof(line_in); i++)
+ line_in[i] = '\0';
+ for (i = 0; i < sizeof(line_in) / 2; i++)
+ {
+ char ch;
+
+ ch = 0200 + i;
+ if ('\0' == ch)
+ ch = '0';
+ line_in[i] = ch;
+ }
+ los = sizeof(line_out) / 2;
+ obp = quote_unquote(line_in, line_out, los, 0);
+ if (obp != line_out)
+ SM_FREE(obp);
+
+ for (i = 0; i < sizeof(line_in); i++)
+ line_in[i] = '\0';
+ for (i = 0; i < sizeof(line_in) / 2; i++)
+ {
+ char ch;
+
+ ch = 0200 + i;
+ if ('\0' == ch)
+ ch = '0';
+ line_in[i] = ch;
+ }
+ los = sizeof(line_in);
+ obp = quote_unquote(line_in, line_in, los, 0);
+ if (obp != line_in)
+ SM_FREE(obp);
+
+ for (i = 0; inout[i].qic_in != NULL; i++)
+ {
+ los = sizeof(line_out) / 2;
+ obp = quote_unquote(inout[i].qic_in, line_out, los,
+ inout[i].qic_exp);
+ cmp = strcmp(inout[i].qic_out, obp);
+ SM_TEST(inout[i].qic_exp == cmp);
+ if (inout[i].qic_exp != cmp && !SmTestVerbose)
+ {
+ char *bp;
+
+ bp = str2prt(obp);
+ fprintf(stderr, "got: %s\n", bp);
+ bp = str2prt(inout[i].qic_out);
+ fprintf(stderr, "exp:%s\n", bp);
+ fprintf(stderr, "cmp=%d\n", cmp);
+ show_diff(inout[i].qic_in, inout[i].qic_out);
+ }
+ if (obp != line_out)
+ SM_FREE(obp);
+ }
+
+ /* use same buffer for in and out */
+ for (i = 0; inout[i].qic_in != NULL; i++)
+ {
+ bool same;
+
+ same = strcmp(inout[i].qic_in, inout[i].qic_out) == 0;
+ los = sm_strlcpy(line, inout[i].qic_in, sizeof(line));
+ SM_TEST(los + 1 < sizeof(line));
+ ++los;
+ obp = quote_unquote(line, line, los, inout[i].qic_exp);
+ cmp = strcmp(inout[i].qic_out, obp);
+ SM_TEST(inout[i].qic_exp == cmp);
+ if (inout[i].qic_exp != cmp && !SmTestVerbose)
+ {
+ char *bp;
+
+ bp = str2prt(obp);
+ fprintf(stderr, "got: %s\n", bp);
+ bp = str2prt(inout[i].qic_out);
+ fprintf(stderr, "exp:%s\n", bp);
+ fprintf(stderr, "cmp=%d\n", cmp);
+ show_diff(inout[i].qic_in, inout[i].qic_out);
+ }
+ if (obp != line)
+ {
+ SM_TEST(!same);
+ if (same)
+ show_diff(obp, inout[i].qic_out);
+ SM_FREE(obp);
+ }
+ }
+
+ /* use NULL buffer for out */
+ for (i = 0; inout[i].qic_in != NULL; i++)
+ {
+ los = 0;
+ obp = quote_unquote(inout[i].qic_in, NULL, los,
+ inout[i].qic_exp);
+ SM_TEST(obp != NULL);
+ cmp = strcmp(inout[i].qic_out, obp);
+ SM_TEST(inout[i].qic_exp == cmp);
+ if (inout[i].qic_exp != cmp && !SmTestVerbose)
+ {
+ char *bp;
+
+ bp = str2prt(obp);
+ fprintf(stderr, "got: %s\n", bp);
+ bp = str2prt(inout[i].qic_out);
+ fprintf(stderr, "exp:%s\n", bp);
+ fprintf(stderr, "cmp=%d\n", cmp);
+ show_diff(inout[i].qic_in, inout[i].qic_out);
+ }
+ }
+
+ return sm_test_end();
+}
diff --git a/contrib/sendmail/libsm/t-sem.c b/contrib/sendmail/libsm/t-sem.c
index cba784a8c93c..24d056365fab 100644
--- a/contrib/sendmail/libsm/t-sem.c
+++ b/contrib/sendmail/libsm/t-sem.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000-2001, 2005-2006 Sendmail, Inc. and its suppliers.
+ * Copyright (c) 2000-2001, 2005-2007 Sendmail, Inc. and its suppliers.
* All rights reserved.
*
* By using this file, you agree to the terms and conditions set
@@ -8,7 +8,7 @@
*/
#include
-SM_RCSID("@(#)$Id: t-sem.c,v 1.15 2006/03/13 20:40:43 msk Exp $")
+SM_RCSID("@(#)$Id: t-sem.c,v 1.16 2007/03/21 23:22:10 ca Exp $")
#include
@@ -22,6 +22,8 @@ SM_RCSID("@(#)$Id: t-sem.c,v 1.15 2006/03/13 20:40:43 msk Exp $")
# include
# include
+# define T_SM_SEM_KEY (4321L)
+
static void
delay(t, s)
int t;
@@ -58,7 +60,7 @@ seminter(owner)
int semid;
int t;
- semid = sm_sem_start(SM_SEM_KEY, SM_NSEM, 0, owner);
+ semid = sm_sem_start(T_SM_SEM_KEY, SM_NSEM, 0, owner);
if (semid < 0)
{
perror("sm_sem_start failed");
@@ -145,7 +147,7 @@ semtest(owner)
int semid, r;
int cnt = 0;
- semid = sm_sem_start(SM_SEM_KEY, 1, 0, owner);
+ semid = sm_sem_start(T_SM_SEM_KEY, 1, 0, owner);
if (semid < 0)
{
perror("sm_sem_start failed");
diff --git a/contrib/sendmail/libsm/util.c b/contrib/sendmail/libsm/util.c
new file mode 100644
index 000000000000..2b99a493422d
--- /dev/null
+++ b/contrib/sendmail/libsm/util.c
@@ -0,0 +1,250 @@
+/*
+ * Copyright (c) 2006 Sendmail, Inc. and its suppliers.
+ * All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set
+ * forth in the LICENSE file which can be found at the top level of
+ * the sendmail distribution.
+ *
+ */
+
+#include
+
+SM_RCSID("@(#)$Id: util.c,v 1.9 2006/08/30 18:35:51 ca Exp $")
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+/*
+** STR2PRT -- convert "unprintable" characters in a string to \oct
+**
+** Parameters:
+** s -- string to convert
+**
+** Returns:
+** converted string.
+** This is a static local buffer, string must be copied
+** before this function is called again!
+*/
+
+char *
+str2prt(s)
+ char *s;
+{
+ int l;
+ char c, *h;
+ bool ok;
+ static int len = 0;
+ static char *buf = NULL;
+
+ if (s == NULL)
+ return NULL;
+ ok = true;
+ for (h = s, l = 1; *h != '\0'; h++, l++)
+ {
+ if (*h == '\\')
+ {
+ ++l;
+ ok = false;
+ }
+ else if (!(isascii(*h) && isprint(*h)))
+ {
+ l += 3;
+ ok = false;
+ }
+ }
+ if (ok)
+ return s;
+ if (l > len)
+ {
+ char *nbuf = sm_pmalloc_x(l);
+
+ if (buf != NULL)
+ sm_free(buf);
+ len = l;
+ buf = nbuf;
+ }
+ for (h = buf; *s != '\0' && l > 0; s++, l--)
+ {
+ c = *s;
+ if (isascii(c) && isprint(c) && c != '\\')
+ {
+ *h++ = c;
+ }
+ else
+ {
+ *h++ = '\\';
+ --l;
+ switch (c)
+ {
+ case '\\':
+ *h++ = '\\';
+ break;
+ case '\t':
+ *h++ = 't';
+ break;
+ case '\n':
+ *h++ = 'n';
+ break;
+ case '\r':
+ *h++ = 'r';
+ break;
+ default:
+ SM_ASSERT(l >= 2);
+ (void) sm_snprintf(h, l, "%03o",
+ (unsigned int)((unsigned char) c));
+
+ /*
+ ** XXX since l is unsigned this may
+ ** wrap around if the calculation is screwed
+ ** up...
+ */
+
+ l -= 2;
+ h += 3;
+ break;
+ }
+ }
+ }
+ *h = '\0';
+ buf[len - 1] = '\0';
+ return buf;
+}
+
+/*
+** QUOTE_INTERNAL_CHARS -- do quoting of internal characters
+**
+** Necessary to make sure that we don't have metacharacters such
+** as the internal versions of "$*" or "$&" in a string.
+** The input and output pointers can be the same.
+**
+** Parameters:
+** ibp -- a pointer to the string to translate
+** obp -- a pointer to an output buffer
+** bsp -- pointer to the length of the output buffer
+**
+** Returns:
+** A possibly new bp (if the buffer needed to grow); if
+** it is different, *bsp will updated to the size of
+** the new buffer and the caller is responsible for
+** freeing the memory.
+*/
+
+#define SM_MM_QUOTE(ch) (((ch) & 0377) == METAQUOTE || (((ch) & 0340) == 0200))
+
+char *
+quote_internal_chars(ibp, obp, bsp)
+ char *ibp;
+ char *obp;
+ int *bsp;
+{
+ char *ip, *op;
+ int bufused, olen;
+ bool buffer_same, needs_quoting;
+
+ buffer_same = ibp == obp;
+ needs_quoting = false;
+
+ /* determine length of output string (starts at 1 for trailing '\0') */
+ for (ip = ibp, olen = 1; *ip != '\0'; ip++, olen++)
+ {
+ if (SM_MM_QUOTE(*ip))
+ {
+ olen++;
+ needs_quoting = true;
+ }
+ }
+
+ /* is the output buffer big enough? */
+ if (olen > *bsp)
+ {
+ obp = sm_malloc_x(olen);
+ buffer_same = false;
+ *bsp = olen;
+ }
+
+ /*
+ ** shortcut: no change needed?
+ ** Note: we don't check this first as some bozo may use the same
+ ** buffers but restrict the size of the output buffer to less
+ ** than the length of the input buffer in which case we need to
+ ** allocate a new buffer.
+ */
+
+ if (!needs_quoting)
+ {
+ if (!buffer_same)
+ {
+ bufused = sm_strlcpy(obp, ibp, *bsp);
+ SM_ASSERT(bufused <= olen);
+ }
+ return obp;
+ }
+
+ if (buffer_same)
+ {
+ obp = sm_malloc_x(olen);
+ buffer_same = false;
+ *bsp = olen;
+ }
+
+ for (ip = ibp, op = obp, bufused = 0; *ip != '\0'; ip++)
+ {
+ if (SM_MM_QUOTE(*ip))
+ {
+ SM_ASSERT(bufused < olen);
+ op[bufused++] = METAQUOTE;
+ }
+ SM_ASSERT(bufused < olen);
+ op[bufused++] = *ip;
+ }
+ op[bufused] = '\0';
+ return obp;
+}
+
+/*
+** DEQUOTE_INTERNAL_CHARS -- undo the effect of quote_internal_chars
+**
+** Parameters:
+** ibp -- a pointer to the string to be translated.
+** obp -- a pointer to the output buffer. Can be the
+** same as ibp.
+** obs -- the size of the output buffer.
+**
+** Returns:
+** number of character added to obp
+*/
+
+int
+dequote_internal_chars(ibp, obp, obs)
+ char *ibp;
+ char *obp;
+ int obs;
+{
+ char *ip, *op;
+ int len;
+ bool quoted;
+
+ quoted = false;
+ len = 0;
+ for (ip = ibp, op = obp; *ip != '\0'; ip++)
+ {
+ if ((*ip & 0377) == METAQUOTE && !quoted)
+ {
+ quoted = true;
+ continue;
+ }
+ if (op < &obp[obs - 1])
+ {
+ *op++ = *ip;
+ ++len;
+ }
+ quoted = false;
+ }
+ *op = '\0';
+ return len;
+}
diff --git a/contrib/sendmail/libsm/vfscanf.c b/contrib/sendmail/libsm/vfscanf.c
index 235ee4254623..8701ef7bf8c5 100644
--- a/contrib/sendmail/libsm/vfscanf.c
+++ b/contrib/sendmail/libsm/vfscanf.c
@@ -13,7 +13,7 @@
*/
#include
-SM_IDSTR(id, "@(#)$Id: vfscanf.c,v 1.53 2005/06/14 23:07:20 ca Exp $")
+SM_IDSTR(id, "@(#)$Id: vfscanf.c,v 1.54 2006/10/12 22:03:52 ca Exp $")
#include
#include
@@ -122,7 +122,9 @@ sm_vfscanf(fp, timeout, fmt0, ap)
int nassigned; /* number of fields assigned */
int nread; /* number of characters consumed from fp */
int base; /* base argument to strtoll/strtoull */
- ULONGLONG_T (*ccfn)(); /* conversion function (strtoll/strtoull) */
+
+ /* conversion function (strtoll/strtoull) */
+ ULONGLONG_T (*ccfn) __P((const char *, char **, int));
char ccltab[256]; /* character class table for %[...] */
char buf[BUF]; /* buffer for numeric conversions */
SM_EVENT *evt = NULL;
diff --git a/contrib/sendmail/libsmdb/Makefile.m4 b/contrib/sendmail/libsmdb/Makefile.m4
index caadfe8c88c6..85f7084cc0ff 100644
--- a/contrib/sendmail/libsmdb/Makefile.m4
+++ b/contrib/sendmail/libsmdb/Makefile.m4
@@ -1,7 +1,7 @@
-dnl $Id: Makefile.m4,v 8.14 2002/06/21 22:01:34 ca Exp $
+dnl $Id: Makefile.m4,v 8.15 2006/06/28 21:08:01 ca Exp $
include(confBUILDTOOLSDIR`/M4/switch.m4')
-define(`confREQUIRE_LIBSM', `true')
+define(`confREQUIRE_SM_OS_H', `true')
# sendmail dir
SMSRCDIR= ifdef(`confSMSRCDIR', `confSMSRCDIR', `${SRCDIR}/sendmail')
PREPENDDEF(`confENVDEF', `confMAPDEF')
diff --git a/contrib/sendmail/libsmutil/Makefile.m4 b/contrib/sendmail/libsmutil/Makefile.m4
index ea3730562923..1e7dcb4a3265 100644
--- a/contrib/sendmail/libsmutil/Makefile.m4
+++ b/contrib/sendmail/libsmutil/Makefile.m4
@@ -1,7 +1,7 @@
-dnl $Id: Makefile.m4,v 8.17 2002/06/21 22:01:34 ca Exp $
+dnl $Id: Makefile.m4,v 8.18 2006/06/28 21:02:39 ca Exp $
include(confBUILDTOOLSDIR`/M4/switch.m4')
-define(`confREQUIRE_LIBSM', `true')
+define(`confREQUIRE_SM_OS_H', `true')
# sendmail dir
SMSRCDIR= ifdef(`confSMSRCDIR', `confSMSRCDIR', `${SRCDIR}/sendmail')
PREPENDDEF(`confENVDEF', `confMAPDEF')
diff --git a/contrib/sendmail/mail.local/Makefile.m4 b/contrib/sendmail/mail.local/Makefile.m4
index c9af26fc590a..4f1e763a4389 100644
--- a/contrib/sendmail/mail.local/Makefile.m4
+++ b/contrib/sendmail/mail.local/Makefile.m4
@@ -1,7 +1,8 @@
-dnl $Id: Makefile.m4,v 8.51 2004/11/18 22:29:52 ca Exp $
+dnl $Id: Makefile.m4,v 8.52 2006/06/28 21:08:02 ca Exp $
include(confBUILDTOOLSDIR`/M4/switch.m4')
define(`confREQUIRE_LIBSM', `true')
+define(`confREQUIRE_SM_OS_H', `true')
# sendmail dir
SMSRCDIR= ifdef(`confSMSRCDIR', `confSMSRCDIR', `${SRCDIR}/sendmail')
PREPENDDEF(`confENVDEF', `confMAPDEF')
diff --git a/contrib/sendmail/mailstats/Makefile.m4 b/contrib/sendmail/mailstats/Makefile.m4
index 61f56924b538..1d454120b9f9 100644
--- a/contrib/sendmail/mailstats/Makefile.m4
+++ b/contrib/sendmail/mailstats/Makefile.m4
@@ -1,7 +1,8 @@
-dnl $Id: Makefile.m4,v 8.35 2002/06/21 22:01:40 ca Exp $
+dnl $Id: Makefile.m4,v 8.36 2006/06/28 21:08:02 ca Exp $
include(confBUILDTOOLSDIR`/M4/switch.m4')
define(`confREQUIRE_LIBSM', `true')
+define(`confREQUIRE_SM_OS_H', `true')
# sendmail dir
SMSRCDIR= ifdef(`confSMSRCDIR', `confSMSRCDIR', `${SRCDIR}/sendmail')
PREPENDDEF(`confENVDEF', `confMAPDEF')
diff --git a/contrib/sendmail/makemap/Makefile.m4 b/contrib/sendmail/makemap/Makefile.m4
index a4664cf4369e..9d5baf9e6047 100644
--- a/contrib/sendmail/makemap/Makefile.m4
+++ b/contrib/sendmail/makemap/Makefile.m4
@@ -1,7 +1,8 @@
-dnl $Id: Makefile.m4,v 8.43 2002/06/21 22:01:44 ca Exp $
+dnl $Id: Makefile.m4,v 8.44 2006/06/28 21:08:03 ca Exp $
include(confBUILDTOOLSDIR`/M4/switch.m4')
define(`confREQUIRE_LIBSM', `true')
+define(`confREQUIRE_SM_OS_H', `true')
# sendmail dir
SMSRCDIR= ifdef(`confSMSRCDIR', `confSMSRCDIR', `${SRCDIR}/sendmail')
PREPENDDEF(`confENVDEF', `confMAPDEF')
diff --git a/contrib/sendmail/praliases/Makefile.m4 b/contrib/sendmail/praliases/Makefile.m4
index 2ba5c7eb06a0..d6ebeedb6dac 100644
--- a/contrib/sendmail/praliases/Makefile.m4
+++ b/contrib/sendmail/praliases/Makefile.m4
@@ -1,7 +1,8 @@
-dnl $Id: Makefile.m4,v 8.35 2002/06/21 22:01:47 ca Exp $
+dnl $Id: Makefile.m4,v 8.36 2006/06/28 21:08:03 ca Exp $
include(confBUILDTOOLSDIR`/M4/switch.m4')
define(`confREQUIRE_LIBSM', `true')
+define(`confREQUIRE_SM_OS_H', `true')
# sendmail dir
SMSRCDIR= ifdef(`confSMSRCDIR', `confSMSRCDIR', `${SRCDIR}/sendmail')
PREPENDDEF(`confENVDEF', `confMAPDEF')
diff --git a/contrib/sendmail/rmail/Makefile.m4 b/contrib/sendmail/rmail/Makefile.m4
index f8ee2ff54be9..ed4250d367ea 100644
--- a/contrib/sendmail/rmail/Makefile.m4
+++ b/contrib/sendmail/rmail/Makefile.m4
@@ -1,7 +1,8 @@
-dnl $Id: Makefile.m4,v 8.43 2002/06/21 22:01:49 ca Exp $
+dnl $Id: Makefile.m4,v 8.44 2006/06/28 21:08:04 ca Exp $
include(confBUILDTOOLSDIR`/M4/switch.m4')
define(`confREQUIRE_LIBSM', `true')
+define(`confREQUIRE_SM_OS_H', `true')
# sendmail dir
SMSRCDIR= ifdef(`confSMSRCDIR', `confSMSRCDIR', `${SRCDIR}/sendmail')
PREPENDDEF(`confENVDEF', `confMAPDEF')
diff --git a/contrib/sendmail/smrsh/Makefile.m4 b/contrib/sendmail/smrsh/Makefile.m4
index 1fa55349b02b..0f773275ea24 100644
--- a/contrib/sendmail/smrsh/Makefile.m4
+++ b/contrib/sendmail/smrsh/Makefile.m4
@@ -1,7 +1,8 @@
-dnl $Id: Makefile.m4,v 8.35 2002/06/21 22:01:52 ca Exp $
+dnl $Id: Makefile.m4,v 8.36 2006/06/28 21:08:04 ca Exp $
include(confBUILDTOOLSDIR`/M4/switch.m4')
define(`confREQUIRE_LIBSM', `true')
+define(`confREQUIRE_SM_OS_H', `true')
# sendmail dir
SMSRCDIR= ifdef(`confSMSRCDIR', `confSMSRCDIR', `${SRCDIR}/sendmail')
PREPENDDEF(`confENVDEF', `confMAPDEF')
diff --git a/contrib/sendmail/src/Makefile b/contrib/sendmail/src/Makefile
index c86bbf5e2204..a5633c791d7f 100644
--- a/contrib/sendmail/src/Makefile
+++ b/contrib/sendmail/src/Makefile
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 8.11 1999/09/23 22:36:42 ca Exp $
+# $Id: Makefile,v 8.12 2006/08/29 22:00:11 ca Exp $
SHELL= /bin/sh
BUILD= ./Build
@@ -6,6 +6,8 @@ OPTIONS= $(CONFIG) $(FLAGS)
all: FRC
$(SHELL) $(BUILD) $(OPTIONS) $@
+check: FRC
+ $(SHELL) $(BUILD) $(OPTIONS) $@
clean: FRC
$(SHELL) $(BUILD) $(OPTIONS) $@
install: FRC
diff --git a/contrib/sendmail/src/Makefile.m4 b/contrib/sendmail/src/Makefile.m4
index 5cf0f78411ab..10c11222674c 100644
--- a/contrib/sendmail/src/Makefile.m4
+++ b/contrib/sendmail/src/Makefile.m4
@@ -1,7 +1,8 @@
-dnl $Id: Makefile.m4,v 8.96 2003/08/08 20:31:17 ca Exp $
+dnl $Id: Makefile.m4,v 8.107 2007/01/09 00:04:09 ca Exp $
include(confBUILDTOOLSDIR`/M4/switch.m4')
define(`confREQUIRE_LIBSM', `true')
+define(`confREQUIRE_SM_OS_H', `true')
bldPRODUCT_START(`executable', `sendmail')
define(`bldBIN_TYPE', `G')
define(`bldINSTALL_DIR', `')
@@ -10,6 +11,7 @@ PREPENDDEF(`confENVDEF', `confMAPDEF')
bldPUSH_SMLIB(`sm')
bldPUSH_SMLIB(`smutil')
+
dnl hack: /etc/mail is not defined as "location of .cf" in the build system
define(`bldTARGET_INST_DEP', ifdef(`confINST_DEP', `confINST_DEP',
`${DESTDIR}/etc/mail/submit.cf ${DESTDIR}${MSPQ}'))dnl
diff --git a/contrib/sendmail/src/README b/contrib/sendmail/src/README
index 1ed29b110d79..2039674381d8 100644
--- a/contrib/sendmail/src/README
+++ b/contrib/sendmail/src/README
@@ -9,7 +9,7 @@
# the sendmail distribution.
#
#
-# $Id: README,v 8.389 2006/05/02 16:58:50 ca Exp $
+# $Id: README,v 8.390 2006/11/13 22:27:27 ca Exp $
#
This directory contains the source files for sendmail(TM).
@@ -508,6 +508,9 @@ HASSNPRINTF Set this to 1 if your OS has a working snprintf(3), i.e.,
size were unlimited.
LDAP_REFERRALS Set this if you want to use the -R flag (do not auto chase
referrals) for LDAP maps (requires -DLDAPMAP).
+MILTER_NO_NAGLE Turn off Nagle algorithm for communication with libmilter
+ ("cork" on Linux). On some operating systems this may
+ improve the interprocess communication performance.
+-----------------------+
@@ -1844,4 +1847,4 @@ util.c Some general purpose routines used by sendmail.
version.c The version number and information about this
version of sendmail.
-(Version $Revision: 8.389 $, last update $Date: 2006/05/02 16:58:50 $ )
+(Version $Revision: 8.390 $, last update $Date: 2006/11/13 22:27:27 $ )
diff --git a/contrib/sendmail/src/TRACEFLAGS b/contrib/sendmail/src/TRACEFLAGS
index 820cf208161d..a6249fd2c477 100644
--- a/contrib/sendmail/src/TRACEFLAGS
+++ b/contrib/sendmail/src/TRACEFLAGS
@@ -1,4 +1,4 @@
-# $Id: TRACEFLAGS,v 8.44 2006/02/27 18:52:41 ca Exp $
+# $Id: TRACEFLAGS,v 8.47 2006/09/11 22:36:32 ca Exp $
0, 4 main.c main canonical name, UUCP node name, a.k.a.s
0, 15 main.c main print configuration
0, 44 util.c printav print address of each string
@@ -27,6 +27,7 @@
20 parseaddr.c parseaddr
21 parseaddr.c rewrite
22 parseaddr.c prescan
+23 main.c testmodeline
24 parseaddr.c buildaddr, allocaddr
25 recipient.c sendtolist
26 recipient.c recipient
@@ -69,6 +70,7 @@
56 mci.c persistent host status
57 util.c snprintf
58 bf.c bf* routines
+59 parseaddr.c cataddr
60 map.c
61 conf.c sm_gethostbyname
62 multiple file descriptor checking
@@ -88,6 +90,7 @@
81 sun remote mode
83 collect.c timeout
84 deliver.c timeout
+85 map.c dprintf map
91 mci.c syslogging of MCI cache information
93,>99 * Prevent daemon connection fork for profiling/debugging
94,>99 srvrsmtp.c cause commands to fail (for protocol testing)
diff --git a/contrib/sendmail/src/TUNING b/contrib/sendmail/src/TUNING
index 6ccff9a19407..fe9e6947af6a 100644
--- a/contrib/sendmail/src/TUNING
+++ b/contrib/sendmail/src/TUNING
@@ -5,7 +5,7 @@
# forth in the LICENSE file which can be found at the top level of
# the sendmail distribution.
#
-# $Id: TUNING,v 1.19 2003/01/25 23:06:02 ca Exp $
+# $Id: TUNING,v 1.21 2006/09/25 16:45:05 ca Exp $
#
********************************************
@@ -39,7 +39,7 @@ Depending on your requirements, these may need different options
to optimize sendmail for the particular purpose. It is also possible
to configure sendmail to achieve good performance in all cases, but
it will not be optimal for any specific purpose. For example, it
-is non-trivival to combine low latency (fast delivery of incoming
+is non-trivial to combine low latency (fast delivery of incoming
mail) with high overall throughput.
Before we explore the different scenarios, a basic discussion about
@@ -49,7 +49,7 @@ disk I/O, delivery modes, and queue control is required.
* Disk I/O
-----------------------------------------------
-In general mail will be written to disk up before a delivery attempt
+In general mail will be written to disk before a delivery attempt
is made. This is required for reliability and should only be changed
in a few specific cases that are mentioned later on. To achieve
better disk I/O performance the queue directories can be spread
@@ -76,7 +76,7 @@ interactive: incoming mail will be immediately delivered by the same process
queue: incoming mail will be queued and delivered by a queue runner later on
The first offers the lowest latency without the disadvantage of the
-second, which keep the connection from the sender open until the
+second, which keeps the connection from the sender open until the
delivery to the next hop succeeded or failed. However, it does not
allow for a good control over the number of delivery processes other
than limiting the total number of direct children of the daemon
@@ -95,7 +95,7 @@ other two modes. However, this mode is probably also best for
concurrent delivery since the number of queue runners can be specified
on a queue group basis. Persistent queue runners (-qp) can be used
to minimize the overhead for creating processes because they just
-sleep for the specified interval (which shold be short) instead of
+sleep for the specified interval (which should be short) instead of
exiting after a queue run.
@@ -139,7 +139,7 @@ should be added to the .mc file.
* Mailing Lists and Large Aliases (1-n Mailing)
-----------------------------------------------
-Before 8.12 sendmail delivers an e-mail sequentially to all its
+Before 8.12 sendmail would deliver an e-mail sequentially to all its
recipients. For mailing lists or large aliases the overall delivery
time can be substantial, especially if some of the recipients are
located at hosts that are slow to accept e-mail. Some mailing list
@@ -148,9 +148,9 @@ fewer recipients. sendmail 8.12 can do this itself, either across
queue groups or within a queue directory. The latter is controlled
by the 'r=' field of a queue group declaration.
-Let's assume a simple example: a mailing lists where most of
-the recipients are at three domains: the local one (local.domain)
-and two remotes (one.domain, two.domain) and the rest is splittered
+Let's assume a simple example: a mailing list where most of the
+recipients are at three domains: the local one (local.domain) and
+two remotes (one.domain, two.domain) and the rest is splittered
over several other domains. For this case it is useful to specify
three queue groups:
@@ -209,10 +209,10 @@ For high volume mail it is necessary to be able to control the load
on the system. Therefore the 'queue' delivery mode should be used,
and all options related to number of processes and the load should
be set to reasonable values. It is important not to accept mail
-faster than it can be delivered otherwise the system will be
+faster than it can be delivered; otherwise the system will be
overwhelmed. Hence RefuseLA should be lower than QueueLA, the number
of daemon children should probably be lower than the number of queue
-runnners (MaxChildren vs. MaxQueueChildren). DelayLA is a new option
+runners (MaxChildren vs. MaxQueueChildren). DelayLA is a new option
in 8.12 which allows delaying connections instead of rejecting them.
This may result in a smoother load distribution depending on how
the mails are submitted to sendmail.
diff --git a/contrib/sendmail/src/alias.c b/contrib/sendmail/src/alias.c
index 3c052123a4b5..3eae4baf4bbf 100644
--- a/contrib/sendmail/src/alias.c
+++ b/contrib/sendmail/src/alias.c
@@ -13,7 +13,7 @@
#include
-SM_RCSID("@(#)$Id: alias.c,v 8.217 2003/07/28 17:47:18 ca Exp $")
+SM_RCSID("@(#)$Id: alias.c,v 8.219 2006/10/24 18:04:09 ca Exp $")
#define SEPARATOR ':'
# define ALIAS_SPEC_SEPARATORS " ,/:"
@@ -90,7 +90,7 @@ alias(a, sendq, aliaslevel, e)
if (e->e_sender != NULL && *e->e_sender == '\0')
{
/* Look for owner of alias */
- (void) sm_strlcpyn(obuf, sizeof obuf, 2, "owner-", a->q_user);
+ (void) sm_strlcpyn(obuf, sizeof(obuf), 2, "owner-", a->q_user);
if (aliaslookup(obuf, &status, a->q_host) != NULL)
{
if (LogLevel > 8)
@@ -107,7 +107,8 @@ alias(a, sendq, aliaslevel, e)
{
a->q_state = QS_QUEUEUP;
if (e->e_message == NULL)
- e->e_message = "alias database unavailable";
+ e->e_message = sm_rpool_strdup_x(e->e_rpool,
+ "alias database unavailable");
/* XXX msg only per recipient? */
if (a->q_message == NULL)
@@ -164,10 +165,10 @@ alias(a, sendq, aliaslevel, e)
*/
if (strncmp(a->q_user, "owner-", 6) == 0 ||
- strlen(a->q_user) > sizeof obuf - 7)
- (void) sm_strlcpy(obuf, "owner-owner", sizeof obuf);
+ strlen(a->q_user) > sizeof(obuf) - 7)
+ (void) sm_strlcpy(obuf, "owner-owner", sizeof(obuf));
else
- (void) sm_strlcpyn(obuf, sizeof obuf, 2, "owner-", a->q_user);
+ (void) sm_strlcpyn(obuf, sizeof(obuf), 2, "owner-", a->q_user);
owner = aliaslookup(obuf, &status, a->q_host);
if (owner == NULL)
return;
@@ -287,7 +288,7 @@ setalias(spec)
if (AliasFileMap == NULL)
{
(void) sm_strlcpy(buf, "aliases.files sequence",
- sizeof buf);
+ sizeof(buf));
AliasFileMap = makemapentry(buf);
if (AliasFileMap == NULL)
{
@@ -295,10 +296,10 @@ setalias(spec)
return;
}
}
- (void) sm_snprintf(buf, sizeof buf, "Alias%d", NAliasFileMaps);
+ (void) sm_snprintf(buf, sizeof(buf), "Alias%d", NAliasFileMaps);
s = stab(buf, ST_MAP, ST_ENTER);
map = &s->s_map;
- memset(map, '\0', sizeof *map);
+ memset(map, '\0', sizeof(*map));
map->map_mname = s->s_name;
p = strpbrk(p, ALIAS_SPEC_SEPARATORS);
if (p != NULL && *p == SEPARATOR)
@@ -458,8 +459,8 @@ aliaswait(map, ext, isopen)
return isopen;
}
mtime = stb.st_mtime;
- if (sm_strlcpyn(buf, sizeof buf, 2,
- map->map_file, ext == NULL ? "" : ext) >= sizeof buf)
+ if (sm_strlcpyn(buf, sizeof(buf), 2,
+ map->map_file, ext == NULL ? "" : ext) >= sizeof(buf))
{
if (LogLevel > 3)
sm_syslog(LOG_INFO, NOQID,
@@ -656,7 +657,7 @@ readaliases(map, af, announcestats, logstats)
LineNumber = 0;
naliases = bytes = longest = 0;
skipping = false;
- while (sm_io_fgets(af, SM_TIME_DEFAULT, line, sizeof line) != NULL)
+ while (sm_io_fgets(af, SM_TIME_DEFAULT, line, sizeof(line)) != NULL)
{
int lhssize, rhssize;
int c;
@@ -779,7 +780,7 @@ readaliases(map, af, announcestats, logstats)
/* read continuation line */
if (sm_io_fgets(af, SM_TIME_DEFAULT, p,
- sizeof line - (p-line)) == NULL)
+ sizeof(line) - (p-line)) == NULL)
break;
LineNumber++;
@@ -928,7 +929,7 @@ forward(user, sendq, aliaslevel, e)
ep = strchr(pp, SEPARATOR);
if (ep != NULL)
*ep = '\0';
- expand(pp, buf, sizeof buf, e);
+ expand(pp, buf, sizeof(buf), e);
if (ep != NULL)
*ep++ = SEPARATOR;
if (buf[0] == '\0')
diff --git a/contrib/sendmail/src/arpadate.c b/contrib/sendmail/src/arpadate.c
index 16082cd259af..5d3d7a6d3120 100644
--- a/contrib/sendmail/src/arpadate.c
+++ b/contrib/sendmail/src/arpadate.c
@@ -13,7 +13,7 @@
#include
-SM_RCSID("@(#)$Id: arpadate.c,v 8.30 2001/09/11 04:05:12 gshapiro Exp $")
+SM_RCSID("@(#)$Id: arpadate.c,v 8.31 2006/08/15 23:24:55 ca Exp $")
/*
** ARPADATE -- Create date in ARPANET format
@@ -192,7 +192,7 @@ arpadate(ud)
{
*q++ = ' ';
*q++ = '(';
- while (*tz != '\0' && q < &b[sizeof b - 3])
+ while (*tz != '\0' && q < &b[sizeof(b) - 3])
*q++ = *tz++;
*q++ = ')';
}
diff --git a/contrib/sendmail/src/collect.c b/contrib/sendmail/src/collect.c
index 534ce9c2e476..56fed0a66476 100644
--- a/contrib/sendmail/src/collect.c
+++ b/contrib/sendmail/src/collect.c
@@ -13,7 +13,7 @@
#include
-SM_RCSID("@(#)$Id: collect.c,v 8.273 2006/03/31 18:51:47 ca Exp $")
+SM_RCSID("@(#)$Id: collect.c,v 8.280 2006/11/29 00:20:40 ca Exp $")
static void eatfrom __P((char *volatile, ENVELOPE *));
static void collect_doheader __P((ENVELOPE *));
@@ -53,13 +53,13 @@ collect_eoh(e, numhdrs, hdrslen)
char hsize[16];
/* call the end-of-header check ruleset */
- (void) sm_snprintf(hnum, sizeof hnum, "%d", numhdrs);
- (void) sm_snprintf(hsize, sizeof hsize, "%d", hdrslen);
+ (void) sm_snprintf(hnum, sizeof(hnum), "%d", numhdrs);
+ (void) sm_snprintf(hsize, sizeof(hsize), "%d", hdrslen);
if (tTd(30, 10))
sm_dprintf("collect: rscheck(\"check_eoh\", \"%s $| %s\")\n",
hnum, hsize);
(void) rscheck("check_eoh", hnum, hsize, e, RSF_UNSTRUCTURED|RSF_COUNT,
- 3, NULL, e->e_id);
+ 3, NULL, e->e_id, NULL);
/*
** Process the header,
@@ -144,11 +144,11 @@ collect_doheader(e)
break;
case NRA_ADD_BCC:
- addheader("Bcc", " ", 0, e);
+ addheader("Bcc", " ", 0, e, true);
break;
case NRA_ADD_TO_UNDISCLOSED:
- addheader("To", "undisclosed-recipients:;", 0, e);
+ addheader("To", "undisclosed-recipients:;", 0, e, true);
break;
}
@@ -161,7 +161,7 @@ collect_doheader(e)
if (tTd(30, 3))
sm_dprintf("Adding %s: %s\n",
hdr, q->q_paddr);
- addheader(hdr, q->q_paddr, 0, e);
+ addheader(hdr, q->q_paddr, 0, e, true);
}
}
}
@@ -315,7 +315,7 @@ collect(fp, smtpmode, hdrp, e, rsetsize)
numhdrs = 0;
HasEightBits = false;
buf = bp = bufbuf;
- buflen = sizeof bufbuf;
+ buflen = sizeof(bufbuf);
pbp = peekbuf;
istate = IS_BOL;
mstate = SaveFrom ? MS_HEADER : MS_UFROM;
@@ -552,25 +552,7 @@ collect(fp, smtpmode, hdrp, e, rsetsize)
sm_free(obuf); /* XXX */
}
- /*
- ** XXX Notice: the logic here is broken.
- ** An input to sendmail that doesn't contain a
- ** header but starts immediately with the body whose
- ** first line contain characters which match the
- ** following "if" will cause problems: those
- ** characters will NOT appear in the output...
- ** Do we care?
- */
-
- if (c >= 0200 && c <= 0237)
- {
-#if 0 /* causes complaints -- figure out something for 8.n+1 */
- usrerr("Illegal character 0x%x in header", c);
-#else /* 0 */
- /* EMPTY */
-#endif /* 0 */
- }
- else if (c != '\0')
+ if (c != '\0')
{
*bp++ = c;
++hdrslen;
@@ -599,7 +581,7 @@ collect(fp, smtpmode, hdrp, e, rsetsize)
nextstate:
if (tTd(30, 35))
- sm_dprintf("nextstate, istate=%d, mstate=%d, line = \"%s\"\n",
+ sm_dprintf("nextstate, istate=%d, mstate=%d, line=\"%s\"\n",
istate, mstate, buf);
switch (mstate)
{
diff --git a/contrib/sendmail/src/control.c b/contrib/sendmail/src/control.c
index 0d7ee0b43be6..0b525f71472e 100644
--- a/contrib/sendmail/src/control.c
+++ b/contrib/sendmail/src/control.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998-2004 Sendmail, Inc. and its suppliers.
+ * Copyright (c) 1998-2004, 2006 Sendmail, Inc. and its suppliers.
* All rights reserved.
*
* By using this file, you agree to the terms and conditions set
@@ -10,7 +10,7 @@
#include
-SM_RCSID("@(#)$Id: control.c,v 8.126 2004/08/04 20:54:00 ca Exp $")
+SM_RCSID("@(#)$Id: control.c,v 8.128 2006/08/15 23:24:56 ca Exp $")
#include
@@ -21,9 +21,7 @@ SM_RCSID("@(#)$Id: control.c,v 8.126 2004/08/04 20:54:00 ca Exp $")
#define CMDHELP 3 /* help */
#define CMDSTATUS 4 /* daemon status */
#define CMDMEMDUMP 5 /* dump memory, to find memory leaks */
-#if _FFR_CONTROL_MSTAT
-# define CMDMSTAT 6 /* daemon status, more info, tagged data */
-#endif /* _FFR_CONTROL_MSTAT */
+#define CMDMSTAT 6 /* daemon status, more info, tagged data */
struct cmd
{
@@ -38,9 +36,7 @@ static struct cmd CmdTab[] =
{ "shutdown", CMDSHUTDOWN },
{ "status", CMDSTATUS },
{ "memdump", CMDMEMDUMP },
-#if _FFR_CONTROL_MSTAT
{ "mstat", CMDMSTAT },
-#endif /* _FFR_CONTROL_MSTAT */
{ NULL, CMDERROR }
};
@@ -74,7 +70,7 @@ opencontrolsocket()
if (ControlSocketName == NULL || *ControlSocketName == '\0')
return 0;
- if (strlen(ControlSocketName) >= sizeof controladdr.sun_path)
+ if (strlen(ControlSocketName) >= sizeof(controladdr.sun_path))
{
errno = ENAMETOOLONG;
return -1;
@@ -101,13 +97,13 @@ opencontrolsocket()
}
(void) unlink(ControlSocketName);
- memset(&controladdr, '\0', sizeof controladdr);
+ memset(&controladdr, '\0', sizeof(controladdr));
controladdr.sun_family = AF_UNIX;
(void) sm_strlcpy(controladdr.sun_path, ControlSocketName,
- sizeof controladdr.sun_path);
+ sizeof(controladdr.sun_path));
if (bind(ControlSocket, (struct sockaddr *) &controladdr,
- sizeof controladdr) < 0)
+ sizeof(controladdr)) < 0)
{
save_errno = errno;
clrcontrol();
@@ -305,7 +301,7 @@ control_command(sock, e)
(void) sm_io_setvbuf(s, SM_TIME_DEFAULT, NULL,
SM_IO_NBF, SM_IO_BUFSIZ);
- if (sm_io_fgets(s, SM_TIME_DEFAULT, inp, sizeof inp) == NULL)
+ if (sm_io_fgets(s, SM_TIME_DEFAULT, inp, sizeof(inp)) == NULL)
{
(void) sm_io_close(s, SM_TIME_DEFAULT);
exit(EX_IOERR);
@@ -323,7 +319,7 @@ control_command(sock, e)
cmd = cmdbuf;
while (*p != '\0' &&
!(isascii(*p) && isspace(*p)) &&
- cmd < &cmdbuf[sizeof cmdbuf - 2])
+ cmd < &cmdbuf[sizeof(cmdbuf) - 2])
*cmd++ = *p++;
*cmd = '\0';
@@ -390,7 +386,6 @@ control_command(sock, e)
proc_list_display(s, "");
break;
-# if _FFR_CONTROL_MSTAT
case CMDMSTAT: /* daemon status, extended, tagged format */
proc_list_probe();
(void) sm_io_fprintf(s, SM_TIME_DEFAULT,
@@ -401,7 +396,6 @@ control_command(sock, e)
disk_status(s, "D:");
proc_list_display(s, "P:");
break;
-# endif /* _FFR_CONTROL_MSTAT */
case CMDMEMDUMP: /* daemon memory dump, to find memory leaks */
# if SM_HEAP_CHECK
diff --git a/contrib/sendmail/src/daemon.c b/contrib/sendmail/src/daemon.c
index 6d366d9a143b..76b5b582607a 100644
--- a/contrib/sendmail/src/daemon.c
+++ b/contrib/sendmail/src/daemon.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998-2006 Sendmail, Inc. and its suppliers.
+ * Copyright (c) 1998-2007 Sendmail, Inc. and its suppliers.
* All rights reserved.
* Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved.
* Copyright (c) 1988, 1993
@@ -12,8 +12,9 @@
*/
#include
+#include "map.h"
-SM_RCSID("@(#)$Id: daemon.c,v 8.666 2006/04/18 01:23:42 ca Exp $")
+SM_RCSID("@(#)$Id: daemon.c,v 8.678 2007/03/08 00:33:40 ca Exp $")
#if defined(SOCK_STREAM) || defined(__GNU_LIBRARY__)
# define USE_SOCK_STREAM 1
@@ -58,37 +59,8 @@ SM_RCSID("@(#)$Id: daemon.c,v 8.666 2006/04/18 01:23:42 ca Exp $")
#include
-/* structure to describe a daemon or a client */
-struct daemon
-{
- int d_socket; /* fd for socket */
- SOCKADDR d_addr; /* socket for incoming */
- unsigned short d_port; /* port number */
- int d_listenqueue; /* size of listen queue */
- int d_tcprcvbufsize; /* size of TCP receive buffer */
- int d_tcpsndbufsize; /* size of TCP send buffer */
- time_t d_refuse_connections_until;
- bool d_firsttime;
- int d_socksize;
- BITMAP256 d_flags; /* flags; see sendmail.h */
- char *d_mflags; /* flags for use in macro */
- char *d_name; /* user-supplied name */
-#if MILTER
- char *d_inputfilterlist;
- struct milter *d_inputfilters[MAXFILTERS];
-#endif /* MILTER */
-#if _FFR_SS_PER_DAEMON
- int d_supersafe;
-#endif /* _FFR_SS_PER_DAEMON */
-#if _FFR_DM_PER_DAEMON
- int d_dm; /* DeliveryMode */
-#endif /* _FFR_DM_PER_DAEMON */
-};
-
-typedef struct daemon DAEMON_T;
-
-#define SAFE_NOTSET (-1) /* SuperSafe (per daemon) option not set */
-/* see also sendmail.h: SuperSafe values */
+#define DAEMON_C 1
+#include
static void connecttimeout __P((int));
static int opendaemonsocket __P((DAEMON_T *, bool));
@@ -128,7 +100,6 @@ static void authtimeout __P((int));
** Convert the entry in hbuf into a canonical form.
*/
-static DAEMON_T Daemons[MAXDAEMONS];
static int NDaemons = 0; /* actual number of daemons */
static time_t NextDiskSpaceCheck = 0;
@@ -165,7 +136,7 @@ getrequests(e)
#endif /* XDEBUG */
char status[MAXLINE];
SOCKADDR sa;
- SOCKADDR_LEN_T len = sizeof sa;
+ SOCKADDR_LEN_T len = sizeof(sa);
#if _FFR_QUEUE_RUN_PARANOIA
time_t lastrun;
#endif /* _FFR_QUEUE_RUN_PARANOIA */
@@ -173,7 +144,6 @@ getrequests(e)
extern int ControlSocket;
# endif /* NETUNIX */
extern ENVELOPE BlankEnvelope;
- extern bool refuseconnections __P((char *, ENVELOPE *, int, bool));
/* initialize data for function that generates queue ids */
@@ -218,7 +188,7 @@ getrequests(e)
{
char jbuf[MAXHOSTNAMELEN];
- expand("\201j", jbuf, sizeof jbuf, e);
+ expand("\201j", jbuf, sizeof(jbuf), e);
j_has_dot = strchr(jbuf, '.') != NULL;
}
#endif /* XDEBUG */
@@ -263,8 +233,7 @@ getrequests(e)
continue;
if (bitnset(D_DISABLE, Daemons[idx].d_flags))
continue;
- if (refuseconnections(Daemons[idx].d_name, e, idx,
- curdaemon == idx))
+ if (refuseconnections(e, idx, curdaemon == idx))
{
if (Daemons[idx].d_socket >= 0)
{
@@ -300,7 +269,7 @@ getrequests(e)
{
char jbuf[MAXHOSTNAMELEN];
- expand("\201j", jbuf, sizeof jbuf, e);
+ expand("\201j", jbuf, sizeof(jbuf), e);
if (!wordinclass(jbuf, 'w'))
{
dumpstate("daemon lost $j");
@@ -423,7 +392,7 @@ getrequests(e)
{
lotherend = Daemons[idx].d_socksize;
memset(&RealHostAddr, '\0',
- sizeof RealHostAddr);
+ sizeof(RealHostAddr));
t = accept(Daemons[idx].d_socket,
(struct sockaddr *)&RealHostAddr,
&lotherend);
@@ -457,8 +426,8 @@ getrequests(e)
{
struct sockaddr_un sa_un;
- lotherend = sizeof sa_un;
- memset(&sa_un, '\0', sizeof sa_un);
+ lotherend = sizeof(sa_un);
+ memset(&sa_un, '\0', sizeof(sa_un));
t = accept(ControlSocket,
(struct sockaddr *)&sa_un,
&lotherend);
@@ -627,9 +596,9 @@ getrequests(e)
/* XXX get some better "random" data? */
seed = get_random();
RAND_seed((void *) &NextDiskSpaceCheck,
- sizeof NextDiskSpaceCheck);
- RAND_seed((void *) &now, sizeof now);
- RAND_seed((void *) &seed, sizeof seed);
+ sizeof(NextDiskSpaceCheck));
+ RAND_seed((void *) &now, sizeof(now));
+ RAND_seed((void *) &seed, sizeof(seed));
#else /* STARTTLS */
(void) get_random();
#endif /* STARTTLS */
@@ -720,7 +689,7 @@ getrequests(e)
macdefine(&BlankEnvelope.e_macro, A_TEMP,
macid("{daemon_addr}"),
anynet_ntoa(&Daemons[curdaemon].d_addr));
- (void) sm_snprintf(status, sizeof status, "%d",
+ (void) sm_snprintf(status, sizeof(status), "%d",
ntohs(Daemons[curdaemon].d_port));
macdefine(&BlankEnvelope.e_macro, A_TEMP,
macid("{daemon_port}"), status);
@@ -752,19 +721,36 @@ getrequests(e)
/* Add parent process as first child item */
proc_list_add(CurrentPid, "daemon child",
PROC_DAEMON_CHILD, 0, -1, NULL);
-
/* don't schedule queue runs if ETRN */
QueueIntvl = 0;
+
+ /*
+ ** Hack: override global variables if
+ ** the corresponding DaemonPortOption
+ ** is set.
+ */
#if _FFR_SS_PER_DAEMON
if (Daemons[curdaemon].d_supersafe !=
- SAFE_NOTSET)
- SuperSafe = Daemons[curdaemon].d_supersafe;
+ DPO_NOTSET)
+ SuperSafe = Daemons[curdaemon].
+ d_supersafe;
#endif /* _FFR_SS_PER_DAEMON */
-#if _FFR_DM_PER_DAEMON
if (Daemons[curdaemon].d_dm != DM_NOTSET)
set_delivery_mode(
Daemons[curdaemon].d_dm, e);
-#endif /* _FFR_DM_PER_DAEMON */
+
+ if (Daemons[curdaemon].d_refuseLA !=
+ DPO_NOTSET)
+ RefuseLA = Daemons[curdaemon].
+ d_refuseLA;
+ if (Daemons[curdaemon].d_queueLA != DPO_NOTSET)
+ QueueLA = Daemons[curdaemon].d_queueLA;
+ if (Daemons[curdaemon].d_delayLA != DPO_NOTSET)
+ DelayLA = Daemons[curdaemon].d_delayLA;
+ if (Daemons[curdaemon].d_maxchildren !=
+ DPO_NOTSET)
+ MaxChildren = Daemons[curdaemon].
+ d_maxchildren;
sm_setproctitle(true, e, "startup with %s",
anynet_ntoa(&RealHostAddr));
@@ -909,13 +895,13 @@ getrequests(e)
/* parent -- keep track of children */
if (control)
{
- (void) sm_snprintf(status, sizeof status,
+ (void) sm_snprintf(status, sizeof(status),
"control socket server child");
proc_list_add(pid, status, PROC_CONTROL, 0, -1, NULL);
}
else
{
- (void) sm_snprintf(status, sizeof status,
+ (void) sm_snprintf(status, sizeof(status),
"SMTP server child for %s",
anynet_ntoa(&RealHostAddr));
proc_list_add(pid, status, PROC_DAEMON, 0, -1,
@@ -1138,12 +1124,12 @@ opendaemonsocket(d, firsttime)
if (tTd(15, 101))
(void) setsockopt(d->d_socket, SOL_SOCKET,
SO_DEBUG, (char *)&on,
- sizeof on);
+ sizeof(on));
(void) setsockopt(d->d_socket, SOL_SOCKET,
- SO_REUSEADDR, (char *)&on, sizeof on);
+ SO_REUSEADDR, (char *)&on, sizeof(on));
(void) setsockopt(d->d_socket, SOL_SOCKET,
- SO_KEEPALIVE, (char *)&on, sizeof on);
+ SO_KEEPALIVE, (char *)&on, sizeof(on));
#ifdef SO_RCVBUF
if (d->d_tcprcvbufsize > 0)
@@ -1184,30 +1170,30 @@ opendaemonsocket(d, firsttime)
#if _FFR_DAEMON_NETUNIX
# ifdef NETUNIX
case AF_UNIX:
- socksize = sizeof d->d_addr.sunix;
+ socksize = sizeof(d->d_addr.sunix);
break;
# endif /* NETUNIX */
#endif /* _FFR_DAEMON_NETUNIX */
#if NETINET
case AF_INET:
- socksize = sizeof d->d_addr.sin;
+ socksize = sizeof(d->d_addr.sin);
break;
#endif /* NETINET */
#if NETINET6
case AF_INET6:
- socksize = sizeof d->d_addr.sin6;
+ socksize = sizeof(d->d_addr.sin6);
break;
#endif /* NETINET6 */
#if NETISO
case AF_ISO:
- socksize = sizeof d->d_addr.siso;
+ socksize = sizeof(d->d_addr.siso);
break;
#endif /* NETISO */
default:
- socksize = sizeof d->d_addr;
+ socksize = sizeof(d->d_addr);
break;
}
@@ -1260,7 +1246,7 @@ setupdaemon(daemonaddr)
if (daemonaddr->sa.sa_family == AF_UNSPEC)
{
- memset(daemonaddr, '\0', sizeof *daemonaddr);
+ memset(daemonaddr, '\0', sizeof(*daemonaddr));
#if NETINET
daemonaddr->sa.sa_family = AF_INET;
#endif /* NETINET */
@@ -1456,11 +1442,13 @@ setsockaddroptions(p, d)
d->d_addr.sa.sa_family = AF_INET;
#endif /* NETINET */
#if _FFR_SS_PER_DAEMON
- d->d_supersafe = SAFE_NOTSET;
+ d->d_supersafe = DPO_NOTSET;
#endif /* _FFR_SS_PER_DAEMON */
-#if _FFR_DM_PER_DAEMON
d->d_dm = DM_NOTSET;
-#endif /* _FFR_DM_PER_DAEMON */
+ d->d_refuseLA = DPO_NOTSET;
+ d->d_queueLA = DPO_NOTSET;
+ d->d_delayLA = DPO_NOTSET;
+ d->d_maxchildren = DPO_NOTSET;
while (p != NULL)
{
@@ -1480,16 +1468,20 @@ setsockaddroptions(p, d)
continue;
while (isascii(*++v) && isspace(*v))
continue;
- if (isascii(*f) && islower(*f))
- *f = toupper(*f);
switch (*f)
{
case 'A': /* address */
+#if !_FFR_DPO_CS
+ case 'a':
+#endif /* !_FFR_DPO_CS */
addr = v;
break;
-#if _FFR_DM_PER_DAEMON
+ case 'c':
+ d->d_maxchildren = atoi(v);
+ break;
+
case 'D': /* DeliveryMode */
switch (*v)
{
@@ -1505,9 +1497,15 @@ setsockaddroptions(p, d)
break;
}
break;
-#endif /* _FFR_DM_PER_DAEMON */
+
+ case 'd': /* delayLA */
+ d->d_delayLA = atoi(v);
+ break;
case 'F': /* address family */
+#if !_FFR_DPO_CS
+ case 'f':
+#endif /* !_FFR_DPO_CS */
if (isascii(*v) && isdigit(*v))
d->d_addr.sa.sa_family = atoi(v);
#if _FFR_DAEMON_NETUNIX
@@ -1544,31 +1542,57 @@ setsockaddroptions(p, d)
#if MILTER
case 'I':
+# if !_FFR_DPO_CS
+ case 'i':
+# endif /* !_FFR_DPO_CS */
d->d_inputfilterlist = v;
break;
#endif /* MILTER */
case 'L': /* listen queue size */
+#if !_FFR_DPO_CS
+ case 'l':
+#endif /* !_FFR_DPO_CS */
d->d_listenqueue = atoi(v);
break;
case 'M': /* modifiers (flags) */
+#if !_FFR_DPO_CS
+ case 'm':
+#endif /* !_FFR_DPO_CS */
d->d_mflags = getmodifiers(v, d->d_flags);
break;
case 'N': /* name */
+#if !_FFR_DPO_CS
+ case 'n':
+#endif /* !_FFR_DPO_CS */
d->d_name = v;
break;
case 'P': /* port */
+#if !_FFR_DPO_CS
+ case 'p':
+#endif /* !_FFR_DPO_CS */
port = v;
break;
+ case 'q':
+ d->d_queueLA = atoi(v);
+ break;
+
case 'R': /* receive buffer size */
d->d_tcprcvbufsize = atoi(v);
break;
+ case 'r':
+ d->d_refuseLA = atoi(v);
+ break;
+
case 'S': /* send buffer size */
+#if !_FFR_DPO_CS
+ case 's':
+#endif /* !_FFR_DPO_CS */
d->d_tcpsndbufsize = atoi(v);
break;
@@ -1860,7 +1884,7 @@ setdaemonoptions(p)
{
char num[30];
- (void) sm_snprintf(num, sizeof num, "Daemon%d", NDaemons);
+ (void) sm_snprintf(num, sizeof(num), "Daemon%d", NDaemons);
Daemons[NDaemons].d_name = newstr(num);
}
@@ -1916,7 +1940,7 @@ setclientoptions(p)
int family;
DAEMON_T d;
- memset(&d, '\0', sizeof d);
+ memset(&d, '\0', sizeof(d));
setsockaddroptions(p, &d);
/* grab what we need */
@@ -1929,7 +1953,7 @@ setclientoptions(p)
{
char num[30];
- (void) sm_snprintf(num, sizeof num, "Client%d", family);
+ (void) sm_snprintf(num, sizeof(num), "Client%d", family);
ClientSettings[family].d_name = newstr(num);
}
}
@@ -2125,7 +2149,7 @@ makeconnection(host, port, mci, e, enough)
char p6[INET6_ADDRSTRLEN];
#endif /* NETINET6 */
- memset(&clt_addr, '\0', sizeof clt_addr);
+ memset(&clt_addr, '\0', sizeof(clt_addr));
/* infer the address family from the address itself */
clt_addr.sa.sa_family = addr_family(p);
@@ -2138,7 +2162,7 @@ makeconnection(host, port, mci, e, enough)
clt_addr.sin.sin_addr.s_addr != INADDR_LOOPBACK)
{
clt_bind = true;
- socksize = sizeof (struct sockaddr_in);
+ socksize = sizeof(struct sockaddr_in);
}
break;
#endif /* NETINET */
@@ -2146,16 +2170,16 @@ makeconnection(host, port, mci, e, enough)
#if NETINET6
case AF_INET6:
if (inet_addr(p) != INADDR_NONE)
- (void) sm_snprintf(p6, sizeof p6,
+ (void) sm_snprintf(p6, sizeof(p6),
"IPv6:::ffff:%s", p);
else
- (void) sm_strlcpy(p6, p, sizeof p6);
+ (void) sm_strlcpy(p6, p, sizeof(p6));
if (anynet_pton(AF_INET6, p6,
&clt_addr.sin6.sin6_addr) == 1 &&
!IN6_IS_ADDR_LOOPBACK(&clt_addr.sin6.sin6_addr))
{
clt_bind = true;
- socksize = sizeof (struct sockaddr_in6);
+ socksize = sizeof(struct sockaddr_in6);
}
break;
#endif /* NETINET6 */
@@ -2185,7 +2209,7 @@ makeconnection(host, port, mci, e, enough)
clt_bind = true;
if (clt_addr.sin.sin_port != 0)
clt_bind = true;
- socksize = sizeof (struct sockaddr_in);
+ socksize = sizeof(struct sockaddr_in);
break;
#endif /* NETINET */
#if NETINET6
@@ -2194,14 +2218,14 @@ makeconnection(host, port, mci, e, enough)
clt_addr.sin6.sin6_addr = in6addr_any;
else
clt_bind = true;
- socksize = sizeof (struct sockaddr_in6);
+ socksize = sizeof(struct sockaddr_in6);
if (clt_addr.sin6.sin6_port != 0)
clt_bind = true;
break;
#endif /* NETINET6 */
#if NETISO
case AF_ISO:
- socksize = sizeof clt_addr.siso;
+ socksize = sizeof(clt_addr.siso);
clt_bind = true;
break;
#endif /* NETISO */
@@ -2217,8 +2241,8 @@ makeconnection(host, port, mci, e, enough)
SM_SET_H_ERRNO(0);
errno = 0;
- memset(&CurHostAddr, '\0', sizeof CurHostAddr);
- memset(&addr, '\0', sizeof addr);
+ memset(&CurHostAddr, '\0', sizeof(CurHostAddr));
+ memset(&addr, '\0', sizeof(addr));
SmtpPhase = mci->mci_phase = "initial connection";
CurHostName = host;
@@ -2236,7 +2260,7 @@ makeconnection(host, port, mci, e, enough)
*p = '\0';
#if NETINET6
- memset(&hid6, '\0', sizeof hid6);
+ memset(&hid6, '\0', sizeof(hid6));
#endif /* NETINET6 */
#if NETINET
if (family == AF_INET &&
@@ -2336,6 +2360,14 @@ makeconnection(host, port, mci, e, enough)
# endif /* NETINET6 */
{
if (errno == ETIMEDOUT ||
+# if _FFR_GETHBN_ExFILE
+# ifdef EMFILE
+ errno == EMFILE ||
+# endif /* EMFILE */
+# ifdef ENFILE
+ errno == ENFILE ||
+# endif /* ENFILE */
+# endif /* _FFR_GETHBN_ExFILE */
h_errno == TRY_AGAIN ||
(errno == ECONNREFUSED && UseNameServer))
{
@@ -2387,7 +2419,7 @@ makeconnection(host, port, mci, e, enough)
#endif /* NETINET6 */
default:
- if (hp->h_length > sizeof addr.sa.sa_data)
+ if (hp->h_length > sizeof(addr.sa.sa_data))
{
syserr("makeconnection: long sa_data: family %d len %d",
hp->h_addrtype, hp->h_length);
@@ -2444,14 +2476,14 @@ makeconnection(host, port, mci, e, enough)
#if NETINET
case AF_INET:
addr.sin.sin_port = port;
- addrlen = sizeof (struct sockaddr_in);
+ addrlen = sizeof(struct sockaddr_in);
break;
#endif /* NETINET */
#if NETINET6
case AF_INET6:
addr.sin6.sin6_port = port;
- addrlen = sizeof (struct sockaddr_in6);
+ addrlen = sizeof(struct sockaddr_in6);
break;
#endif /* NETINET6 */
@@ -2459,7 +2491,7 @@ makeconnection(host, port, mci, e, enough)
case AF_ISO:
/* assume two byte transport selector */
memmove(TSEL((struct sockaddr_iso *) &addr), (char *) &port, 2);
- addrlen = sizeof (struct sockaddr_iso);
+ addrlen = sizeof(struct sockaddr_iso);
break;
#endif /* NETISO */
@@ -2556,7 +2588,7 @@ makeconnection(host, port, mci, e, enough)
int on = 1;
(void) setsockopt(s, SOL_SOCKET, SO_DEBUG,
- (char *)&on, sizeof on);
+ (char *)&on, sizeof(on));
}
if (e->e_xfp != NULL) /* for debugging */
(void) sm_io_flush(e->e_xfp, SM_TIME_DEFAULT);
@@ -2574,7 +2606,7 @@ makeconnection(host, port, mci, e, enough)
(void) setsockopt(s, SOL_SOCKET,
SO_REUSEADDR,
(char *) &on,
- sizeof on);
+ sizeof(on));
break;
#endif /* NETINET */
@@ -2584,7 +2616,7 @@ makeconnection(host, port, mci, e, enough)
(void) setsockopt(s, SOL_SOCKET,
SO_REUSEADDR,
(char *) &on,
- sizeof on);
+ sizeof(on));
break;
#endif /* NETINET6 */
}
@@ -2795,7 +2827,7 @@ makeconnection(host, port, mci, e, enough)
}
/* find out name for Interface through which we connect */
- len = sizeof addr;
+ len = sizeof(addr);
if (getsockname(s, &addr.sa, &len) == 0)
{
char *name;
@@ -2833,11 +2865,9 @@ makeconnection(host, port, mci, e, enough)
macid("{if_family_out}"), NULL);
}
-#if _FFR_HELONAME
/* Use the configured HeloName as appropriate */
if (HeloName != NULL && HeloName[0] != '\0')
mci->mci_heloname = newstr(HeloName);
-#endif /* _FFR_HELONAME */
mci_setstat(mci, EX_OK, NULL, NULL);
return EX_OK;
@@ -2897,10 +2927,10 @@ makeconnection_ds(mux_path, mci)
}
/* prepare address structure */
- memset(&unix_addr, '\0', sizeof unix_addr);
+ memset(&unix_addr, '\0', sizeof(unix_addr));
unix_addr.sun_family = AF_UNIX;
- if (strlen(mux_path) >= sizeof unix_addr.sun_path)
+ if (strlen(mux_path) >= sizeof(unix_addr.sun_path))
{
syserr("makeconnection_ds: domain socket name %s too long",
mux_path);
@@ -2911,7 +2941,7 @@ makeconnection_ds(mux_path, mci)
return EX_UNAVAILABLE;
}
(void) sm_strlcpy(unix_addr.sun_path, mux_path,
- sizeof unix_addr.sun_path);
+ sizeof(unix_addr.sun_path));
/* initialize domain socket */
sock = socket(AF_UNIX, SOCK_STREAM, 0);
@@ -3372,7 +3402,7 @@ getauthinfo(fd, may_be_forged)
static char hbuf[MAXNAME + MAXAUTHINFO + 11];
*may_be_forged = false;
- falen = sizeof RealHostAddr;
+ falen = sizeof(RealHostAddr);
if (isatty(fd) || (i = getpeername(fd, &RealHostAddr.sa, &falen)) < 0 ||
falen <= 0 || RealHostAddr.sa.sa_family == 0)
{
@@ -3388,7 +3418,7 @@ getauthinfo(fd, may_be_forged)
return NULL;
errno = 0;
}
- (void) sm_strlcpyn(hbuf, sizeof hbuf, 2, RealUserName,
+ (void) sm_strlcpyn(hbuf, sizeof(hbuf), 2, RealUserName,
"@localhost");
if (tTd(9, 1))
sm_dprintf("getauthinfo: %s\n", hbuf);
@@ -3454,7 +3484,7 @@ getauthinfo(fd, may_be_forged)
if (TimeOuts.to_ident == 0)
goto noident;
- lalen = sizeof la;
+ lalen = sizeof(la);
switch (RealHostAddr.sa.sa_family)
{
#if NETINET
@@ -3469,7 +3499,7 @@ getauthinfo(fd, may_be_forged)
port = RealHostAddr.sin.sin_port;
/* create ident query */
- (void) sm_snprintf(ibuf, sizeof ibuf, "%d,%d\r\n",
+ (void) sm_snprintf(ibuf, sizeof(ibuf), "%d,%d\r\n",
ntohs(RealHostAddr.sin.sin_port),
ntohs(la.sin.sin_port));
@@ -3517,7 +3547,7 @@ getauthinfo(fd, may_be_forged)
port = RealHostAddr.sin6.sin6_port;
/* create ident query */
- (void) sm_snprintf(ibuf, sizeof ibuf, "%d,%d\r\n",
+ (void) sm_snprintf(ibuf, sizeof(ibuf), "%d,%d\r\n",
ntohs(RealHostAddr.sin6.sin6_port),
ntohs(la.sin6.sin6_port));
@@ -3576,7 +3606,7 @@ getauthinfo(fd, may_be_forged)
/* get result */
p = &ibuf[0];
- nleft = sizeof ibuf - 1;
+ nleft = sizeof(ibuf) - 1;
while ((i = read(s, p, nleft)) > 0)
{
char *s;
@@ -3659,13 +3689,13 @@ getauthinfo(fd, may_be_forged)
if (sm_strncasecmp(ostype, "other", 5) == 0 &&
(ostype[5] == ' ' || ostype[5] == '\0'))
{
- (void) sm_strlcpy(hbuf, "IDENT:", sizeof hbuf);
+ (void) sm_strlcpy(hbuf, "IDENT:", sizeof(hbuf));
cleanstrcpy(&hbuf[6], p, MAXAUTHINFO);
}
else
cleanstrcpy(hbuf, p, MAXAUTHINFO);
len = strlen(hbuf);
- (void) sm_strlcpyn(&hbuf[len], sizeof hbuf - len, 2, "@",
+ (void) sm_strlcpyn(&hbuf[len], sizeof(hbuf) - len, 2, "@",
RealHostName == NULL ? "localhost" : RealHostName);
goto postident;
@@ -3698,7 +3728,7 @@ getauthinfo(fd, may_be_forged)
sm_dprintf("getauthinfo: NULL\n");
return NULL;
}
- (void) sm_strlcpy(hbuf, RealHostName, sizeof hbuf);
+ (void) sm_strlcpy(hbuf, RealHostName, sizeof(hbuf));
postident:
#if IP_SRCROUTE
@@ -3727,7 +3757,7 @@ getauthinfo(fd, may_be_forged)
int l;
struct IPOPTION ipopt;
- ipoptlen = sizeof ipopt;
+ ipoptlen = sizeof(ipopt);
if (getsockopt(fd, IPPROTO_IP, IP_OPTIONS,
(char *) &ipopt, &ipoptlen) < 0)
goto noipsr;
@@ -3760,7 +3790,7 @@ getauthinfo(fd, may_be_forged)
*/
p = &hbuf[strlen(hbuf)];
- l = sizeof hbuf - (hbuf - p) - 6;
+ l = sizeof(hbuf) - (hbuf - p) - 6;
(void) sm_snprintf(p, SPACELEFT(hbuf, p),
" [%s@%.*s",
*o == IPOPT_SSRR ? "!" : "",
@@ -3979,8 +4009,8 @@ host_map_lookup(map, name, av, statp)
{
int ttl;
- (void) sm_strlcpy(hbuf, name, sizeof hbuf);
- if (getcanonname(hbuf, sizeof hbuf - 1, !HasWildcardMX, &ttl))
+ (void) sm_strlcpy(hbuf, name, sizeof(hbuf));
+ if (getcanonname(hbuf, sizeof(hbuf) - 1, !HasWildcardMX, &ttl))
{
ans = hbuf;
if (ttl > 0)
@@ -4022,7 +4052,7 @@ host_map_lookup(map, name, av, statp)
static char n[MAXNAME + 1];
/* hp->h_name is about to disappear */
- (void) sm_strlcpy(n, ans, sizeof n);
+ (void) sm_strlcpy(n, ans, sizeof(n));
ans = n;
}
freehostent(hp);
@@ -4289,10 +4319,10 @@ anynet_ntoa(sap)
# if NETUNIX
case AF_UNIX:
if (sap->sunix.sun_path[0] != '\0')
- (void) sm_snprintf(buf, sizeof buf, "[UNIX: %.64s]",
+ (void) sm_snprintf(buf, sizeof(buf), "[UNIX: %.64s]",
sap->sunix.sun_path);
else
- (void) sm_strlcpy(buf, "[UNIX: localhost]", sizeof buf);
+ (void) sm_strlcpy(buf, "[UNIX: localhost]", sizeof(buf));
return buf;
# endif /* NETUNIX */
@@ -4303,7 +4333,7 @@ anynet_ntoa(sap)
# if NETINET6
case AF_INET6:
- ap = anynet_ntop(&sap->sin6.sin6_addr, buf, sizeof buf);
+ ap = anynet_ntop(&sap->sin6.sin6_addr, buf, sizeof(buf));
if (ap != NULL)
return ap;
break;
@@ -4311,7 +4341,7 @@ anynet_ntoa(sap)
# if NETLINK
case AF_LINK:
- (void) sm_snprintf(buf, sizeof buf, "[LINK: %s]",
+ (void) sm_snprintf(buf, sizeof(buf), "[LINK: %s]",
link_ntoa((struct sockaddr_dl *) &sap->sa));
return buf;
# endif /* NETLINK */
@@ -4322,10 +4352,10 @@ anynet_ntoa(sap)
}
/* unknown family -- just dump bytes */
- (void) sm_snprintf(buf, sizeof buf, "Family %d: ", sap->sa.sa_family);
+ (void) sm_snprintf(buf, sizeof(buf), "Family %d: ", sap->sa.sa_family);
bp = &buf[strlen(buf)];
ap = sap->sa.sa_data;
- for (l = sizeof sap->sa.sa_data; --l >= 0; )
+ for (l = sizeof(sap->sa.sa_data); --l >= 0; )
{
(void) sm_snprintf(bp, SPACELEFT(buf, bp), "%02x:",
*ap++ & 0377);
@@ -4385,7 +4415,7 @@ hostnamebyanyaddr(sap)
# if NETISO
case AF_ISO:
hp = sm_gethostbyaddr((char *) &sap->siso.siso_addr,
- sizeof sap->siso.siso_addr, AF_ISO);
+ sizeof(sap->siso.siso_addr), AF_ISO);
break;
# endif /* NETISO */
@@ -4396,7 +4426,7 @@ hostnamebyanyaddr(sap)
# endif /* NETUNIX */
default:
- hp = sm_gethostbyaddr(sap->sa.sa_data, sizeof sap->sa.sa_data,
+ hp = sm_gethostbyaddr(sap->sa.sa_data, sizeof(sap->sa.sa_data),
sap->sa.sa_family);
break;
}
@@ -4424,7 +4454,7 @@ hostnamebyanyaddr(sap)
static char n[MAXNAME + 1];
/* Copy the string, hp->h_name is about to disappear */
- (void) sm_strlcpy(n, name, sizeof n);
+ (void) sm_strlcpy(n, name, sizeof(n));
name = n;
}
freehostent(hp);
@@ -4448,7 +4478,7 @@ hostnamebyanyaddr(sap)
{
static char buf[203];
- (void) sm_snprintf(buf, sizeof buf, "[%.200s]",
+ (void) sm_snprintf(buf, sizeof(buf), "[%.200s]",
anynet_ntoa(sap));
return buf;
}
diff --git a/contrib/sendmail/src/daemon.h b/contrib/sendmail/src/daemon.h
new file mode 100644
index 000000000000..d8fa291690a9
--- /dev/null
+++ b/contrib/sendmail/src/daemon.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2006 Sendmail, Inc. and its suppliers.
+ * All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set
+ * forth in the LICENSE file which can be found at the top level of
+ * the sendmail distribution.
+ *
+ * $Id: daemon.h,v 8.3 2006/07/13 22:57:03 ca Exp $
+ */
+
+#ifndef DAEMON_H
+#define DAEMON_H 1
+
+#if DAEMON_C
+# define EXTERN
+#else
+# define EXTERN extern
+#endif
+
+/* structure to describe a daemon or a client */
+struct daemon
+{
+ int d_socket; /* fd for socket */
+ SOCKADDR d_addr; /* socket for incoming */
+ unsigned short d_port; /* port number */
+ int d_listenqueue; /* size of listen queue */
+ int d_tcprcvbufsize; /* size of TCP receive buffer */
+ int d_tcpsndbufsize; /* size of TCP send buffer */
+ time_t d_refuse_connections_until;
+ bool d_firsttime;
+ int d_socksize;
+ BITMAP256 d_flags; /* flags; see sendmail.h */
+ char *d_mflags; /* flags for use in macro */
+ char *d_name; /* user-supplied name */
+
+ int d_dm; /* DeliveryMode */
+ int d_refuseLA;
+ int d_queueLA;
+ int d_delayLA;
+ int d_maxchildren;
+
+#if MILTER
+ char *d_inputfilterlist;
+ struct milter *d_inputfilters[MAXFILTERS];
+#endif /* MILTER */
+#if _FFR_SS_PER_DAEMON
+ int d_supersafe;
+#endif /* _FFR_SS_PER_DAEMON */
+};
+
+typedef struct daemon DAEMON_T;
+
+EXTERN DAEMON_T Daemons[MAXDAEMONS];
+
+#define DPO_NOTSET (-1) /* daemon option (int) not set */
+/* see also sendmail.h: SuperSafe values */
+
+extern bool refuseconnections __P((ENVELOPE *, int, bool));
+
+#undef EXTERN
+#endif /* ! DAEMON_H */
diff --git a/contrib/sendmail/src/deliver.c b/contrib/sendmail/src/deliver.c
index 6454da7fe7b6..01d5258071e7 100644
--- a/contrib/sendmail/src/deliver.c
+++ b/contrib/sendmail/src/deliver.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998-2006 Sendmail, Inc. and its suppliers.
+ * Copyright (c) 1998-2007 Sendmail, Inc. and its suppliers.
* All rights reserved.
* Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved.
* Copyright (c) 1988, 1993
@@ -14,7 +14,7 @@
#include
#include
-SM_RCSID("@(#)$Id: deliver.c,v 8.1003.2.1 2006/05/23 01:32:08 ca Exp $")
+SM_RCSID("@(#)$Id: deliver.c,v 8.1012 2007/03/29 21:20:15 ca Exp $")
#if HASSETUSERCONTEXT
# include
@@ -34,7 +34,6 @@ static void mailfiletimeout __P((int));
static void endwaittimeout __P((int));
static int parse_hostsignature __P((char *, char **, MAILER *));
static void sendenvelope __P((ENVELOPE *, int));
-extern MCI *mci_new __P((SM_RPOOL_T *));
static int coloncmp __P((const char *, const char *));
#if STARTTLS
@@ -383,7 +382,7 @@ sendall(e, mode)
*/
ee = (ENVELOPE *) sm_rpool_malloc_x(e->e_rpool,
- sizeof *ee);
+ sizeof(*ee));
STRUCTCOPY(*e, *ee);
ee->e_message = NULL;
ee->e_id = NULL;
@@ -884,7 +883,7 @@ sendenvelope(e, mode)
#if XDEBUG
char wbuf[MAXNAME + 20];
- (void) sm_snprintf(wbuf, sizeof wbuf, "sendall(%.*s)",
+ (void) sm_snprintf(wbuf, sizeof(wbuf), "sendall(%.*s)",
MAXNAME, q->q_paddr);
checkfd012(wbuf);
#endif /* XDEBUG */
@@ -959,7 +958,7 @@ sync_dir(filename, panic)
dirp = strrchr(filename, '/');
if (dirp != NULL)
{
- if (sm_strlcpy(dir, filename, sizeof dir) >= sizeof dir)
+ if (sm_strlcpy(dir, filename, sizeof(dir)) >= sizeof(dir))
return;
dir[dirp - filename] = '\0';
dirp = dir;
@@ -1012,8 +1011,8 @@ dup_queue_file(e, ee, type)
** Make sure both are in the same directory.
*/
- (void) sm_strlcpy(f1buf, queuename(e, type), sizeof f1buf);
- (void) sm_strlcpy(f2buf, queuename(ee, type), sizeof f2buf);
+ (void) sm_strlcpy(f1buf, queuename(e, type), sizeof(f1buf));
+ (void) sm_strlcpy(f2buf, queuename(ee, type), sizeof(f2buf));
/* Force the df to disk if it's not there yet */
if (type == DATAFL_LETTER && e->e_dfp != NULL &&
@@ -1192,6 +1191,8 @@ coloncmp(a, b)
** true iff FallbackSmartHost should be tried.
*/
+static bool should_try_fbsh __P((ENVELOPE *, bool *, char *, size_t, int));
+
static bool
should_try_fbsh(e, tried_fallbacksmarthost, hostbuf, hbsz, status)
ENVELOPE *e;
@@ -1333,11 +1334,13 @@ deliver(e, firstto)
char cbuf[MAXPATHLEN];
errno = 0;
+ SM_REQUIRE(firstto != NULL); /* same as to */
if (!QS_IS_OK(to->q_state))
return 0;
suidwarn = geteuid() == 0;
+ SM_REQUIRE(e != NULL);
m = to->q_mailer;
host = to->q_host;
CurEnv = e; /* just in case */
@@ -1382,6 +1385,7 @@ deliver(e, firstto)
/* rewrite from address, using rewriting rules */
rcode = EX_OK;
+ SM_ASSERT(e->e_from.q_mailer != NULL);
if (bitnset(M_UDBENVELOPE, e->e_from.q_mailer->m_flags))
p = e->e_sender;
else
@@ -1441,7 +1445,7 @@ deliver(e, firstto)
break;
/* this entry is safe -- go ahead and process it */
- expand(*mvp, buf, sizeof buf, e);
+ expand(*mvp, buf, sizeof(buf), e);
*pvp++ = sm_rpool_strdup_x(e->e_rpool, buf);
if (pvp >= &pv[MAXPV - 3])
{
@@ -1595,7 +1599,7 @@ deliver(e, firstto)
quarantine = (e->e_quarmsg != NULL);
rcode = rscheck("check_compat", e->e_from.q_paddr, to->q_paddr,
e, RSF_RMCOMM|RSF_COUNT, 3, NULL,
- e->e_id);
+ e->e_id, NULL);
if (rcode == EX_OK)
{
/* do in-code checking if not discarding */
@@ -1698,7 +1702,7 @@ deliver(e, firstto)
if (p == NULL && ctladdr != NULL)
p = ctladdr->q_home;
macdefine(&e->e_macro, A_PERM, 'z', p);
- expand(m->m_argv[1], buf, sizeof buf, e);
+ expand(m->m_argv[1], buf, sizeof(buf), e);
if (strlen(buf) > 0)
rcode = mailfile(buf, m, ctladdr, SFF_CREAT, e);
else
@@ -1754,18 +1758,18 @@ deliver(e, firstto)
notify[0] = '\0';
if (bitset(QPINGONSUCCESS, to->q_flags))
(void) sm_strlcat(notify, "SUCCESS,",
- sizeof notify);
+ sizeof(notify));
if (bitset(QPINGONFAILURE, to->q_flags))
(void) sm_strlcat(notify, "FAILURE,",
- sizeof notify);
+ sizeof(notify));
if (bitset(QPINGONDELAY, to->q_flags))
(void) sm_strlcat(notify, "DELAY,",
- sizeof notify);
+ sizeof(notify));
/* Set to NEVER or drop trailing comma */
if (notify[0] == '\0')
(void) sm_strlcat(notify, "NEVER",
- sizeof notify);
+ sizeof(notify));
else
notify[strlen(notify) - 1] = '\0';
@@ -1782,7 +1786,7 @@ deliver(e, firstto)
if (!clever)
{
- expand(*mvp, buf, sizeof buf, e);
+ expand(*mvp, buf, sizeof(buf), e);
*pvp++ = sm_rpool_strdup_x(e->e_rpool, buf);
if (pvp >= &pv[MAXPV - 2])
{
@@ -1829,7 +1833,7 @@ deliver(e, firstto)
{
while (*++mvp != NULL)
{
- expand(*mvp, buf, sizeof buf, e);
+ expand(*mvp, buf, sizeof(buf), e);
*pvp++ = sm_rpool_strdup_x(e->e_rpool, buf);
if (pvp >= &pv[MAXPV])
syserr("554 5.3.0 deliver: pv overflow after $u for %s",
@@ -1883,7 +1887,7 @@ deliver(e, firstto)
char wbuf[MAXLINE];
/* make absolutely certain 0, 1, and 2 are in use */
- (void) sm_snprintf(wbuf, sizeof wbuf, "%s... openmailer(%s)",
+ (void) sm_snprintf(wbuf, sizeof(wbuf), "%s... openmailer(%s)",
shortenstring(e->e_to, MAXSHORTSTR),
m->m_name);
checkfd012(wbuf);
@@ -2060,7 +2064,7 @@ deliver(e, firstto)
continue;
}
(void) sm_strlcpy(hostbuf, mxhosts[hostnum],
- sizeof hostbuf);
+ sizeof(hostbuf));
hostnum++;
if (endp != NULL)
*endp = sep;
@@ -2098,7 +2102,7 @@ deliver(e, firstto)
/* Try FallbackSmartHost? */
if (should_try_fbsh(e, &tried_fallbacksmarthost,
- hostbuf, sizeof hostbuf,
+ hostbuf, sizeof(hostbuf),
mci->mci_exitstat))
goto one_last_try;
@@ -2190,7 +2194,7 @@ deliver(e, firstto)
{
/* Try FallbackSmartHost? */
if (should_try_fbsh(e, &tried_fallbacksmarthost,
- hostbuf, sizeof hostbuf, i))
+ hostbuf, sizeof(hostbuf), i))
goto one_last_try;
if (tTd(11, 1))
@@ -2527,7 +2531,7 @@ deliver(e, firstto)
/* change root to some "safe" directory */
if (m->m_rootdir != NULL)
{
- expand(m->m_rootdir, cbuf, sizeof cbuf, e);
+ expand(m->m_rootdir, cbuf, sizeof(cbuf), e);
if (tTd(11, 20))
sm_dprintf("openmailer: chroot %s\n",
cbuf);
@@ -2664,7 +2668,7 @@ deliver(e, firstto)
q = strchr(p, ':');
if (q != NULL)
*q = '\0';
- expand(p, cbuf, sizeof cbuf, e);
+ expand(p, cbuf, sizeof(cbuf), e);
if (q != NULL)
*q++ = ':';
if (tTd(11, 20))
@@ -2945,16 +2949,19 @@ deliver(e, firstto)
if (usetls)
usetls = !iscltflgset(e, D_NOTLS);
+ host = macvalue(macid("{server_name}"), e);
if (usetls)
{
- host = macvalue(macid("{server_name}"), e);
olderrors = Errors;
QuickAbort = false;
SuprErrs = true;
if (rscheck("try_tls", host, NULL, e,
- RSF_RMCOMM, 7, host, NOQID) != EX_OK
+ RSF_RMCOMM, 7, host, NOQID, NULL)
+ != EX_OK
|| Errors > olderrors)
+ {
usetls = false;
+ }
SuprErrs = saveSuprErrs;
QuickAbort = saveQuickAbort;
}
@@ -3024,7 +3031,7 @@ deliver(e, firstto)
if (rscheck("tls_server",
macvalue(macid("{verify}"), e),
NULL, e, RSF_RMCOMM|RSF_COUNT, 5,
- host, NOQID) != EX_OK ||
+ host, NOQID, NULL) != EX_OK ||
Errors > olderrors ||
rcode == EX_SOFTWARE)
{
@@ -3041,7 +3048,7 @@ deliver(e, firstto)
{
p = "403 4.7.0 server not authenticated.";
(void) sm_strlcpy(enhsc, "4.7.0",
- sizeof enhsc);
+ sizeof(enhsc));
}
SuprErrs = saveSuprErrs;
QuickAbort = saveQuickAbort;
@@ -3079,8 +3086,18 @@ deliver(e, firstto)
*/
(void) sm_strlcpy(SmtpError, p,
- sizeof SmtpError);
+ sizeof(SmtpError));
}
+ else if (mci->mci_state == MCIS_CLOSED)
+ {
+ /* connection close caused by 421 */
+ mci->mci_errno = 0;
+ rcode = EX_TEMPFAIL;
+ mci_setstat(mci, rcode, NULL, "421");
+ }
+ else
+ rcode = 0;
+
QuickAbort = saveQuickAbort;
SuprErrs = saveSuprErrs;
if (DONE_STARTTLS(mci->mci_flags) &&
@@ -3171,7 +3188,7 @@ deliver(e, firstto)
(void) sm_strlcpy(SmtpError,
"Temporary AUTH failure",
- sizeof SmtpError);
+ sizeof(SmtpError));
}
}
# endif /* SASL */
@@ -3233,7 +3250,7 @@ deliver(e, firstto)
rcode = EX_DATAERR;
/* Need an e_message for error */
- (void) sm_snprintf(SmtpError, sizeof SmtpError,
+ (void) sm_snprintf(SmtpError, sizeof(SmtpError),
"Message is too large; %ld bytes max",
mci->mci_maxsize);
goto give_up;
@@ -3297,7 +3314,7 @@ deliver(e, firstto)
** We set SmtpError as
*/
- (void) sm_snprintf(SmtpError, sizeof SmtpError,
+ (void) sm_snprintf(SmtpError, sizeof(SmtpError),
"%s mailer (%s) exited with EX_TEMPFAIL",
m->m_name, m->m_mailer);
}
@@ -3337,7 +3354,7 @@ deliver(e, firstto)
# if STARTTLS
i = rscheck("tls_rcpt", to->q_user, NULL, e,
RSF_RMCOMM|RSF_COUNT, 3,
- mci->mci_host, e->e_id);
+ mci->mci_host, e->e_id, NULL);
if (i != EX_OK)
{
markfailure(e, to, mci, i, false);
@@ -3612,7 +3629,7 @@ cleanup: ;
char wbuf[MAXLINE];
/* make absolutely certain 0, 1, and 2 are in use */
- (void) sm_snprintf(wbuf, sizeof wbuf,
+ (void) sm_snprintf(wbuf, sizeof(wbuf),
"%s... end of deliver(%s)",
e->e_to == NULL ? "NO-TO-LIST"
: shortenstring(e->e_to,
@@ -3756,7 +3773,7 @@ markfailure(e, q, mci, rcode, ovr)
{
char buf[16];
- (void) sm_snprintf(buf, sizeof buf, "%d", rcode);
+ (void) sm_snprintf(buf, sizeof(buf), "%d", rcode);
q->q_rstatus = sm_rpool_strdup_x(e->e_rpool, buf);
}
@@ -3830,7 +3847,7 @@ endmailer(mci, e, pv)
if (mci->mci_in != NULL && mci->mci_state != MCIS_ERROR &&
e->e_xfp != NULL)
{
- while (sfgets(buf, sizeof buf, mci->mci_in,
+ while (sfgets(buf, sizeof(buf), mci->mci_in,
TimeOuts.to_quit, "Draining Input") != NULL)
(void) sm_io_fputs(e->e_xfp, SM_TIME_DEFAULT, buf);
}
@@ -3980,7 +3997,7 @@ giveresponse(status, dsn, m, mci, ctladdr, xstart, e, to)
statmsg = "250 2.0.0 Sent";
if (e->e_statmsg != NULL)
{
- (void) sm_snprintf(buf, sizeof buf, "%s (%s)",
+ (void) sm_snprintf(buf, sizeof(buf), "%s (%s)",
statmsg,
shortenstring(e->e_statmsg, 403));
statmsg = buf;
@@ -3988,7 +4005,7 @@ giveresponse(status, dsn, m, mci, ctladdr, xstart, e, to)
}
else if (exmsg == NULL)
{
- (void) sm_snprintf(buf, sizeof buf,
+ (void) sm_snprintf(buf, sizeof(buf),
"554 5.3.0 unknown mailer error %d",
status);
status = EX_UNAVAILABLE;
@@ -4054,7 +4071,7 @@ giveresponse(status, dsn, m, mci, ctladdr, xstart, e, to)
else if (status == EX_NOHOST && h_errno != 0)
{
statmsg = sm_errstring(h_errno + E_DNSBASE);
- (void) sm_snprintf(buf, sizeof buf, "%s (%s)", exmsg + 1,
+ (void) sm_snprintf(buf, sizeof(buf), "%s (%s)", exmsg + 1,
statmsg);
statmsg = buf;
usestat = true;
@@ -4065,14 +4082,14 @@ giveresponse(status, dsn, m, mci, ctladdr, xstart, e, to)
statmsg = exmsg;
if (*statmsg++ == ':' && errnum != 0)
{
- (void) sm_snprintf(buf, sizeof buf, "%s: %s", statmsg,
+ (void) sm_snprintf(buf, sizeof(buf), "%s: %s", statmsg,
sm_errstring(errnum));
statmsg = buf;
usestat = true;
}
else if (bitnset(M_LMTP, m->m_flags) && e->e_statmsg != NULL)
{
- (void) sm_snprintf(buf, sizeof buf, "%s (%s)", statmsg,
+ (void) sm_snprintf(buf, sizeof(buf), "%s (%s)", statmsg,
shortenstring(e->e_statmsg, 403));
statmsg = buf;
usestat = true;
@@ -4091,7 +4108,7 @@ giveresponse(status, dsn, m, mci, ctladdr, xstart, e, to)
{
if (dsn == NULL)
{
- (void) sm_snprintf(dsnbuf, sizeof dsnbuf,
+ (void) sm_snprintf(dsnbuf, sizeof(dsnbuf),
"%.*s", off, statmsg + 4);
dsn = dsnbuf;
}
@@ -4112,11 +4129,11 @@ giveresponse(status, dsn, m, mci, ctladdr, xstart, e, to)
Errors++;
if ((off = isenhsc(statmsg + 4, ' ')) > 0 &&
- off < sizeof mbuf - 4)
+ off < sizeof(mbuf) - 4)
{
if (dsn == NULL)
{
- (void) sm_snprintf(dsnbuf, sizeof dsnbuf,
+ (void) sm_snprintf(dsnbuf, sizeof(dsnbuf),
"%.*s", off, statmsg + 4);
dsn = dsnbuf;
}
@@ -4124,12 +4141,12 @@ giveresponse(status, dsn, m, mci, ctladdr, xstart, e, to)
/* copy only part of statmsg to mbuf */
(void) sm_strlcpy(mbuf, statmsg, off);
- (void) sm_strlcat(mbuf, " %s", sizeof mbuf);
+ (void) sm_strlcat(mbuf, " %s", sizeof(mbuf));
}
else
{
dsnbuf[0] = '\0';
- (void) sm_snprintf(mbuf, sizeof mbuf, "%.3s %%s",
+ (void) sm_snprintf(mbuf, sizeof(mbuf), "%.3s %%s",
statmsg);
off = 4;
}
@@ -4315,10 +4332,10 @@ logdelivery(m, mci, dsn, status, ctladdr, xstart, e)
# endif /* (STATLEN) > 203 */
/* stat: max 210 bytes */
- if ((bp - buf) > (sizeof buf - ((STATLEN) + 20)))
+ if ((bp - buf) > (sizeof(buf) - ((STATLEN) + 20)))
{
/* desperation move -- truncate data */
- bp = buf + sizeof buf - ((STATLEN) + 17);
+ bp = buf + sizeof(buf) - ((STATLEN) + 17);
(void) sm_strlcpy(bp, "...", SPACELEFT(buf, bp));
bp += 3;
}
@@ -4434,7 +4451,7 @@ logdelivery(m, mci, dsn, status, ctladdr, xstart, e)
{
p = macvalue('h', e);
if (p != NULL && p[0] != '\0')
- (void) sm_snprintf(buf, sizeof buf, "relay=%.100s", p);
+ (void) sm_snprintf(buf, sizeof(buf), "relay=%.100s", p);
}
if (buf[0] != '\0')
sm_syslog(LOG_INFO, e->e_id, "%.1000s", buf);
@@ -4481,7 +4498,7 @@ putfromline(mci, e)
{
char *bang;
- expand("\201g", buf, sizeof buf, e);
+ expand("\201g", buf, sizeof(buf), e);
bang = strchr(buf, '!');
if (bang == NULL)
{
@@ -4495,25 +4512,25 @@ putfromline(mci, e)
at = strrchr(buf, '@');
if (at == NULL)
{
- expand("\201k", hname, sizeof hname, e);
+ expand("\201k", hname, sizeof(hname), e);
at = hname;
}
else
*at++ = '\0';
- (void) sm_snprintf(xbuf, sizeof xbuf,
+ (void) sm_snprintf(xbuf, sizeof(xbuf),
"From %.800s \201d remote from %.100s\n",
buf, at);
}
else
{
*bang++ = '\0';
- (void) sm_snprintf(xbuf, sizeof xbuf,
+ (void) sm_snprintf(xbuf, sizeof(xbuf),
"From %.800s \201d remote from %.100s\n",
bang, buf);
template = xbuf;
}
}
- expand(template, buf, sizeof buf, e);
+ expand(template, buf, sizeof(buf), e);
return putxline(buf, strlen(buf), mci, PXLF_HEADER);
}
@@ -4620,7 +4637,7 @@ putbody(mci, e, separator)
if (hvalue("Content-Type", e->e_header) == NULL)
{
- (void) sm_snprintf(buf, sizeof buf,
+ (void) sm_snprintf(buf, sizeof(buf),
"Content-Type: text/plain; charset=%s",
defcharset(e));
if (!putline(buf, mci))
@@ -4688,9 +4705,9 @@ putbody(mci, e, separator)
}
/* determine end of buffer; allow for short mailer lines */
- buflim = &buf[sizeof buf - 1];
+ buflim = &buf[sizeof(buf) - 1];
if (mci->mci_mailer->m_linelimit > 0 &&
- mci->mci_mailer->m_linelimit < sizeof buf - 1)
+ mci->mci_mailer->m_linelimit < sizeof(buf) - 1)
buflim = &buf[mci->mci_mailer->m_linelimit - 1];
/* copy temp file to output with mapping */
@@ -4836,6 +4853,7 @@ putbody(mci, e, separator)
SM_TIME_DEFAULT,
mci->mci_mailer->m_eol);
}
+ pos = 0;
ostate = OSTATE_HEAD;
continue;
}
@@ -5135,13 +5153,13 @@ mailfile(filename, mailer, ctladdr, sfflags, e)
if (strncmp(SafeFileEnv, filename, len) == 0)
filename += len;
- if (len + strlen(filename) + 1 >= sizeof targetfile)
+ if (len + strlen(filename) + 1 >= sizeof(targetfile))
{
syserr("mailfile: filename too long (%s/%s)",
SafeFileEnv, filename);
return EX_CANTCREAT;
}
- (void) sm_strlcpy(targetfile, SafeFileEnv, sizeof targetfile);
+ (void) sm_strlcpy(targetfile, SafeFileEnv, sizeof(targetfile));
realfile = targetfile + len;
if (*filename == '/')
filename++;
@@ -5150,20 +5168,20 @@ mailfile(filename, mailer, ctladdr, sfflags, e)
/* paranoia: trailing / should be removed in readcf */
if (targetfile[len - 1] != '/')
(void) sm_strlcat(targetfile,
- "/", sizeof targetfile);
+ "/", sizeof(targetfile));
(void) sm_strlcat(targetfile, filename,
- sizeof targetfile);
+ sizeof(targetfile));
}
}
else if (mailer->m_rootdir != NULL)
{
- expand(mailer->m_rootdir, targetfile, sizeof targetfile, e);
+ expand(mailer->m_rootdir, targetfile, sizeof(targetfile), e);
len = strlen(targetfile);
if (strncmp(targetfile, filename, len) == 0)
filename += len;
- if (len + strlen(filename) + 1 >= sizeof targetfile)
+ if (len + strlen(filename) + 1 >= sizeof(targetfile))
{
syserr("mailfile: filename too long (%s/%s)",
targetfile, filename);
@@ -5171,18 +5189,18 @@ mailfile(filename, mailer, ctladdr, sfflags, e)
}
realfile = targetfile + len;
if (targetfile[len - 1] != '/')
- (void) sm_strlcat(targetfile, "/", sizeof targetfile);
+ (void) sm_strlcat(targetfile, "/", sizeof(targetfile));
if (*filename == '/')
(void) sm_strlcat(targetfile, filename + 1,
- sizeof targetfile);
+ sizeof(targetfile));
else
(void) sm_strlcat(targetfile, filename,
- sizeof targetfile);
+ sizeof(targetfile));
}
else
{
- if (sm_strlcpy(targetfile, filename, sizeof targetfile) >=
- sizeof targetfile)
+ if (sm_strlcpy(targetfile, filename, sizeof(targetfile)) >=
+ sizeof(targetfile))
{
syserr("mailfile: filename too long (%s)", filename);
return EX_CANTCREAT;
@@ -5460,7 +5478,7 @@ mailfile(filename, mailer, ctladdr, sfflags, e)
q = strchr(p, ':');
if (q != NULL)
*q = '\0';
- expand(p, buf, sizeof buf, e);
+ expand(p, buf, sizeof(buf), e);
if (q != NULL)
*q++ = ':';
if (tTd(11, 20))
@@ -5544,7 +5562,7 @@ mailfile(filename, mailer, ctladdr, sfflags, e)
if (ev != NULL)
sm_clrevent(ev);
- memset(&mcibuf, '\0', sizeof mcibuf);
+ memset(&mcibuf, '\0', sizeof(mcibuf));
mcibuf.mci_mailer = mailer;
mcibuf.mci_out = f;
if (bitnset(M_7BITS, mailer->m_flags))
diff --git a/contrib/sendmail/src/domain.c b/contrib/sendmail/src/domain.c
index 81e64d1e5967..394b0d3f9fba 100644
--- a/contrib/sendmail/src/domain.c
+++ b/contrib/sendmail/src/domain.c
@@ -12,11 +12,12 @@
*/
#include
+#include "map.h"
#if NAMED_BIND
-SM_RCSID("@(#)$Id: domain.c,v 8.199 2006/04/18 00:00:34 ca Exp $ (with name server)")
+SM_RCSID("@(#)$Id: domain.c,v 8.202 2006/12/19 01:15:07 ca Exp $ (with name server)")
#else /* NAMED_BIND */
-SM_RCSID("@(#)$Id: domain.c,v 8.199 2006/04/18 00:00:34 ca Exp $ (without name server)")
+SM_RCSID("@(#)$Id: domain.c,v 8.202 2006/12/19 01:15:07 ca Exp $ (without name server)")
#endif /* NAMED_BIND */
#if NAMED_BIND
@@ -276,7 +277,7 @@ getmxrr(host, mxhosts, mxprefs, droplocalhost, rcode, tryfallback, pttl)
{
if (tTd(8, 1))
sm_dprintf("getmxrr: res_search(%s) failed (errno=%d, h_errno=%d)\n",
- host == NULL ? "" : host, errno, h_errno);
+ host, errno, h_errno);
switch (h_errno)
{
case NO_DATA:
@@ -524,14 +525,14 @@ getmxrr(host, mxhosts, mxprefs, droplocalhost, rcode, tryfallback, pttl)
h = NULL;
# endif /* NETINET6 */
}
- if (strlen(host) >= sizeof MXHostBuf)
+ if (strlen(host) >= sizeof(MXHostBuf))
{
*rcode = EX_CONFIG;
syserr("Host name %s too long",
shortenstring(host, MAXSHORTSTR));
return -1;
}
- (void) sm_strlcpy(MXHostBuf, host, sizeof MXHostBuf);
+ (void) sm_strlcpy(MXHostBuf, host, sizeof(MXHostBuf));
mxhosts[0] = MXHostBuf;
prefs[0] = 0;
if (host[0] == '[')
@@ -568,7 +569,7 @@ getmxrr(host, mxhosts, mxprefs, droplocalhost, rcode, tryfallback, pttl)
}
}
if (trycanon &&
- getcanonname(mxhosts[0], sizeof MXHostBuf - 2, false, pttl))
+ getcanonname(mxhosts[0], sizeof(MXHostBuf) - 2, false, pttl))
{
/* XXX MXHostBuf == "" ? is that possible? */
bp = &MXHostBuf[strlen(MXHostBuf)];
@@ -730,14 +731,14 @@ bestmx_map_lookup(map, name, av, statp)
return NULL;
}
slen = strlen(mxhosts[i]);
- if (len + slen + 2 > sizeof buf)
+ if (len + slen + 2 > sizeof(buf))
break;
if (i > 0)
{
*p++ = map->map_coldelim;
len++;
}
- (void) sm_strlcpy(p, mxhosts[i], sizeof buf - len);
+ (void) sm_strlcpy(p, mxhosts[i], sizeof(buf) - len);
p += slen;
len += slen;
}
@@ -1005,7 +1006,7 @@ dns_getcanonname(host, hbsize, trymx, statp, pttl)
ap += n)
{
n = dn_expand((unsigned char *) &answer, eom, ap,
- (RES_UNC_T) nbuf, sizeof nbuf);
+ (RES_UNC_T) nbuf, sizeof(nbuf));
if (n < 0)
break;
ap += n;
@@ -1070,7 +1071,7 @@ dns_getcanonname(host, hbsize, trymx, statp, pttl)
char ebuf[MAXLINE];
(void) sm_snprintf(ebuf,
- sizeof ebuf,
+ sizeof(ebuf),
"Deferred: DNS failure: CNAME loop for %.100s",
host);
CurEnv->e_message =
@@ -1149,7 +1150,7 @@ dns_getcanonname(host, hbsize, trymx, statp, pttl)
** Otherwise append the saved domain name.
*/
- (void) sm_snprintf(nbuf, sizeof nbuf, "%.*s%s%.*s", MAXDNAME, host,
+ (void) sm_snprintf(nbuf, sizeof(nbuf), "%.*s%s%.*s", MAXDNAME, host,
*mxmatch == '\0' ? "" : ".",
MAXDNAME, mxmatch);
(void) sm_strlcpy(host, nbuf, hbsize);
diff --git a/contrib/sendmail/src/envelope.c b/contrib/sendmail/src/envelope.c
index 50009a464ba2..a607a153042a 100644
--- a/contrib/sendmail/src/envelope.c
+++ b/contrib/sendmail/src/envelope.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998-2003 Sendmail, Inc. and its suppliers.
+ * Copyright (c) 1998-2003, 2006 Sendmail, Inc. and its suppliers.
* All rights reserved.
* Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved.
* Copyright (c) 1988, 1993
@@ -13,7 +13,7 @@
#include
-SM_RCSID("@(#)$Id: envelope.c,v 8.296 2006/03/31 18:53:50 ca Exp $")
+SM_RCSID("@(#)$Id: envelope.c,v 8.302 2006/11/10 23:12:52 ca Exp $")
/*
** CLRSESSENVELOPE -- clear session oriented data in an envelope
@@ -75,9 +75,7 @@ newenvelope(e, parent, rpool)
register ENVELOPE *parent;
SM_RPOOL_T *rpool;
{
-#if _FFR_DM_PER_DAEMON
- int sendmode;
-#endif /* _FFR_DM_PER_DAEMON */
+ int sendmode;
/*
** This code used to read:
@@ -88,12 +86,10 @@ newenvelope(e, parent, rpool)
** This meant macvalue() could go into an infinite loop.
*/
-#if _FFR_DM_PER_DAEMON
if (parent != NULL)
sendmode = parent->e_sendmode;
else
sendmode = DM_NOTSET;
-#endif /* _FFR_DM_PER_DAEMON */
if (e == parent)
parent = e->e_parent;
@@ -101,11 +97,11 @@ newenvelope(e, parent, rpool)
if (e == CurEnv)
memmove((char *) &e->e_from,
(char *) &NullAddress,
- sizeof e->e_from);
+ sizeof(e->e_from));
else
memmove((char *) &e->e_from,
(char *) &CurEnv->e_from,
- sizeof e->e_from);
+ sizeof(e->e_from));
e->e_parent = parent;
assign_queueid(e);
e->e_ctime = curtime();
@@ -130,10 +126,8 @@ newenvelope(e, parent, rpool)
e->e_putbody = putbody;
if (CurEnv->e_xfp != NULL)
(void) sm_io_flush(CurEnv->e_xfp, SM_TIME_DEFAULT);
-#if _FFR_DM_PER_DAEMON
if (sendmode != DM_NOTSET)
e->e_sendmode = sendmode;
-#endif /* _FFR_DM_PER_DAEMON */
return e;
}
@@ -289,13 +283,13 @@ dropenvelope(e, fulldrop, split)
{
if (msg_timeout == MSG_NOT_BY)
{
- (void) sm_snprintf(buf, sizeof buf,
+ (void) sm_snprintf(buf, sizeof(buf),
"delivery time expired %lds",
e->e_deliver_by);
}
else
{
- (void) sm_snprintf(buf, sizeof buf,
+ (void) sm_snprintf(buf, sizeof(buf),
"Cannot send message for %s",
pintvl(TimeOuts.to_q_return[e->e_timeoutclass],
false));
@@ -387,12 +381,12 @@ dropenvelope(e, fulldrop, split)
{
if (msg_timeout == MSG_WARN_BY)
{
- (void) sm_snprintf(buf, sizeof buf,
+ (void) sm_snprintf(buf, sizeof(buf),
"Warning: Delivery time (%lds) exceeded",
e->e_deliver_by);
}
else
- (void) sm_snprintf(buf, sizeof buf,
+ (void) sm_snprintf(buf, sizeof(buf),
"Warning: could not send message for past %s",
pintvl(TimeOuts.to_q_warning[e->e_timeoutclass],
false));
@@ -488,7 +482,7 @@ dropenvelope(e, fulldrop, split)
if (failure_return)
{
- expand(PostMasterCopy, pcopy, sizeof pcopy, e);
+ expand(PostMasterCopy, pcopy, sizeof(pcopy), e);
if (tTd(50, 8))
sm_dprintf("dropenvelope(%s): sending postmaster copy to %s\n",
@@ -706,8 +700,8 @@ clearenvelope(e, fullclear, rpool)
nhp = &e->e_header;
while (bh != NULL)
{
- *nhp = (HDR *) sm_rpool_malloc_x(rpool, sizeof *bh);
- memmove((char *) *nhp, (char *) bh, sizeof *bh);
+ *nhp = (HDR *) sm_rpool_malloc_x(rpool, sizeof(*bh));
+ memmove((char *) *nhp, (char *) bh, sizeof(*bh));
bh = bh->h_link;
nhp = &(*nhp)->h_link;
}
@@ -766,11 +760,11 @@ initsys(e)
*/
/* process id */
- (void) sm_snprintf(buf, sizeof buf, "%d", (int) CurrentPid);
+ (void) sm_snprintf(buf, sizeof(buf), "%d", (int) CurrentPid);
macdefine(&e->e_macro, A_TEMP, 'p', buf);
/* hop count */
- (void) sm_snprintf(buf, sizeof buf, "%d", e->e_hopcount);
+ (void) sm_snprintf(buf, sizeof(buf), "%d", e->e_hopcount);
macdefine(&e->e_macro, A_TEMP, 'c', buf);
/* time as integer, unix time, arpa time */
@@ -788,7 +782,7 @@ initsys(e)
{
if (strrchr(p, '/') != NULL)
p = strrchr(p, '/') + 1;
- (void) sm_strlcpy(ybuf, sizeof ybuf, p);
+ (void) sm_strlcpy(ybuf, sizeof(ybuf), p);
macdefine(&e->e_macro, A_PERM, 'y', ybuf);
}
}
@@ -817,14 +811,14 @@ settime(e)
register struct tm *tm;
now = curtime();
- (void) sm_snprintf(buf, sizeof buf, "%ld", (long) now);
+ (void) sm_snprintf(buf, sizeof(buf), "%ld", (long) now);
macdefine(&e->e_macro, A_TEMP, macid("{time}"), buf);
tm = gmtime(&now);
- (void) sm_snprintf(buf, sizeof buf, "%04d%02d%02d%02d%02d",
+ (void) sm_snprintf(buf, sizeof(buf), "%04d%02d%02d%02d%02d",
tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
tm->tm_hour, tm->tm_min);
macdefine(&e->e_macro, A_TEMP, 't', buf);
- (void) sm_strlcpy(buf, ctime(&now), sizeof buf);
+ (void) sm_strlcpy(buf, ctime(&now), sizeof(buf));
p = strchr(buf, '\n');
if (p != NULL)
*p = '\0';
@@ -1013,7 +1007,7 @@ setsender(from, e, delimptr, delimchar, internal)
if (host == NULL)
host = MyHostName;
- (void) sm_snprintf(ebuf, sizeof ebuf,
+ (void) sm_snprintf(ebuf, sizeof(ebuf),
"%.*s@%.*s", MAXNAME,
realname, MAXNAME, host);
p = ebuf;
@@ -1041,7 +1035,7 @@ setsender(from, e, delimptr, delimchar, internal)
char nbuf[100];
SuprErrs = true;
- expand("\201n", nbuf, sizeof nbuf, e);
+ expand("\201n", nbuf, sizeof(nbuf), e);
from = sm_rpool_strdup_x(e->e_rpool, nbuf);
if (parseaddr(from, &e->e_from, RF_COPYALL, ' ',
NULL, e, false) == NULL &&
@@ -1152,7 +1146,8 @@ setsender(from, e, delimptr, delimchar, internal)
** links in the net.
*/
- pvp = prescan(from, delimchar, pvpbuf, sizeof pvpbuf, NULL, NULL, false);
+ pvp = prescan(from, delimchar, pvpbuf, sizeof(pvpbuf), NULL,
+ IntTokenTab, false);
if (pvp == NULL)
{
/* don't need to give error -- prescan did that already */
@@ -1167,11 +1162,11 @@ setsender(from, e, delimptr, delimchar, internal)
(void) REWRITE(pvp, 4, e);
macdefine(&e->e_macro, A_PERM, macid("{addr_type}"), NULL);
bp = buf + 1;
- cataddr(pvp, NULL, bp, sizeof buf - 2, '\0');
+ cataddr(pvp, NULL, bp, sizeof(buf) - 2, '\0', false);
if (*bp == '@' && !bitnset(M_NOBRACKET, e->e_from.q_mailer->m_flags))
{
/* heuristic: route-addr: add angle brackets */
- (void) sm_strlcat(bp, ">", sizeof buf - 1);
+ (void) sm_strlcat(bp, ">", sizeof(buf) - 1);
*--bp = '<';
}
e->e_sender = sm_rpool_strdup_x(e->e_rpool, bp);
diff --git a/contrib/sendmail/src/helpfile b/contrib/sendmail/src/helpfile
index d5d55e83b5ce..941dc2a164c3 100644
--- a/contrib/sendmail/src/helpfile
+++ b/contrib/sendmail/src/helpfile
@@ -1,6 +1,6 @@
#vers 2
cpyr
-cpyr Copyright (c) 1998-2000, 2002, 2004-2006 Sendmail, Inc. and its suppliers.
+cpyr Copyright (c) 1998-2000, 2002, 2004-2007 Sendmail, Inc. and its suppliers.
cpyr All rights reserved.
cpyr Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved.
cpyr Copyright (c) 1988, 1993
@@ -11,7 +11,7 @@ cpyr By using this file, you agree to the terms and conditions set
cpyr forth in the LICENSE file which can be found at the top level of
cpyr the sendmail distribution.
cpyr
-cpyr $$Id: helpfile,v 8.47 2006/04/26 18:22:54 ca Exp $$
+cpyr $$Id: helpfile,v 8.48 2007/02/01 18:29:44 ca Exp $$
cpyr
smtp This is sendmail version $v
smtp Topics:
@@ -133,4 +133,5 @@ control help This message.
control restart Restart sendmail.
control shutdown Shutdown sendmail.
control status Show sendmail status.
+control mstat Show sendmail status (machine readable format).
control memdump Dump allocated memory list (for debugging only).
diff --git a/contrib/sendmail/src/macro.c b/contrib/sendmail/src/macro.c
index af8f6d5b1945..8f0642fc274e 100644
--- a/contrib/sendmail/src/macro.c
+++ b/contrib/sendmail/src/macro.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998-2001, 2003 Sendmail, Inc. and its suppliers.
+ * Copyright (c) 1998-2001, 2003, 2006 Sendmail, Inc. and its suppliers.
* All rights reserved.
* Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved.
* Copyright (c) 1988, 1993
@@ -13,14 +13,17 @@
#include
-SM_RCSID("@(#)$Id: macro.c,v 8.88 2003/09/05 23:11:18 ca Exp $")
+SM_RCSID("@(#)$Id: macro.c,v 8.102 2006/12/21 23:06:10 ca Exp $")
+#include
#if MAXMACROID != (BITMAPBITS - 1)
ERROR Read the comment in conf.h
#endif /* MAXMACROID != (BITMAPBITS - 1) */
static char *MacroName[MAXMACROID + 1]; /* macro id to name table */
int NextMacroId = 0240; /* codes for long named macros */
+/* see sendmail.h: Special characters in rewriting rules. */
+
/*
** INITMACROS -- initialize the macro system
@@ -67,10 +70,10 @@ struct metamac MetaMacros[] =
void
initmacros(e)
- register ENVELOPE *e;
+ ENVELOPE *e;
{
- register struct metamac *m;
- register int c;
+ struct metamac *m;
+ int c;
char buf[5];
for (m = MetaMacros; m->metaname != '\0'; m++)
@@ -94,13 +97,19 @@ initmacros(e)
MACBINDING("opMode", MID_OPMODE);
/*XXX should probably add equivalents for all short macros here XXX*/
}
+
/*
-** EXPAND -- macro expand a string using $x escapes.
+** EXPAND/DOEXPAND -- macro expand a string using $x escapes.
+**
+** After expansion, the expansion will be in external form (that is,
+** there will be no sendmail metacharacters and METAQUOTEs will have
+** been stripped out).
**
** Parameters:
** s -- the string to expand.
** buf -- the place to put the expansion.
** bufsize -- the size of the buffer.
+** explevel -- the depth of expansion (doexpand only)
** e -- envelope in which to work.
**
** Returns:
@@ -110,22 +119,25 @@ initmacros(e)
** none.
*/
-void
-expand(s, buf, bufsize, e)
- register char *s;
- register char *buf;
+static void doexpand __P(( char *, char *, size_t, int, ENVELOPE *));
+
+static void
+doexpand(s, buf, bufsize, explevel, e)
+ char *s;
+ char *buf;
size_t bufsize;
- register ENVELOPE *e;
+ int explevel;
+ ENVELOPE *e;
{
- register char *xp;
- register char *q;
+ char *xp;
+ char *q;
bool skipping; /* set if conditionally skipping output */
bool recurse; /* set if recursion required */
size_t i;
int skiplev; /* skipping nesting level */
int iflev; /* if nesting level */
+ bool quotenext; /* quote the following character */
char xbuf[MACBUFSIZE];
- static int explevel = 0;
if (tTd(35, 24))
{
@@ -138,6 +150,7 @@ expand(s, buf, bufsize, e)
skipping = false;
skiplev = 0;
iflev = 0;
+ quotenext = false;
if (s == NULL)
s = "";
for (xp = xbuf; *s != '\0'; s++)
@@ -150,12 +163,19 @@ expand(s, buf, bufsize, e)
*/
q = NULL;
- c = *s;
- switch (c & 0377)
+ c = *s & 0377;
+
+ if (quotenext)
+ {
+ quotenext = false;
+ goto simpleinterpolate;
+ }
+
+ switch (c)
{
case CONDIF: /* see if var set */
iflev++;
- c = *++s;
+ c = *++s & 0377;
if (skipping)
skiplev++;
else
@@ -196,33 +216,45 @@ expand(s, buf, bufsize, e)
if (q == NULL)
continue;
break;
+
+ case METAQUOTE:
+ /* next octet completely quoted */
+ quotenext = true;
+ break;
}
/*
** Interpolate q or output one character
*/
- if (skipping || xp >= &xbuf[sizeof xbuf - 1])
+ simpleinterpolate:
+ if (skipping || xp >= &xbuf[sizeof(xbuf) - 1])
continue;
if (q == NULL)
*xp++ = c;
else
{
/* copy to end of q or max space remaining in buf */
- while ((c = *q++) != '\0' && xp < &xbuf[sizeof xbuf - 1])
+ bool hiderecurse = false;
+
+ while ((c = *q++) != '\0' &&
+ xp < &xbuf[sizeof(xbuf) - 1])
{
/* check for any sendmail metacharacters */
- if ((c & 0340) == 0200)
+ if (!hiderecurse && (c & 0340) == 0200)
recurse = true;
*xp++ = c;
+
+ /* give quoted characters a free ride */
+ hiderecurse = (c & 0377) == METAQUOTE;
}
}
}
*xp = '\0';
- if (tTd(35, 24))
+ if (tTd(35, 28))
{
- sm_dprintf("expand ==> ");
+ sm_dprintf("expand(%d) ==> ", explevel);
xputs(sm_debug_file(), xbuf);
sm_dprintf("\n");
}
@@ -232,9 +264,7 @@ expand(s, buf, bufsize, e)
{
if (explevel < MaxMacroRecursion)
{
- explevel++;
- expand(xbuf, buf, bufsize, e);
- explevel--;
+ doexpand(xbuf, buf, bufsize, explevel + 1, e);
return;
}
syserr("expand: recursion too deep (%d max)",
@@ -242,11 +272,34 @@ expand(s, buf, bufsize, e)
}
/* copy results out */
- i = xp - xbuf;
- if (i >= bufsize)
- i = bufsize - 1;
- memmove(buf, xbuf, i);
- buf[i] = '\0';
+ if (explevel == 0)
+ (void) sm_strlcpy(buf, xbuf, bufsize);
+ else
+ {
+ /* leave in internal form */
+ i = xp - xbuf;
+ if (i >= bufsize)
+ i = bufsize - 1;
+ memmove(buf, xbuf, i);
+ buf[i] = '\0';
+ }
+
+ if (tTd(35, 24))
+ {
+ sm_dprintf("expand ==> ");
+ xputs(sm_debug_file(), buf);
+ sm_dprintf("\n");
+ }
+}
+
+void
+expand(s, buf, bufsize, e)
+ char *s;
+ char *buf;
+ size_t bufsize;
+ ENVELOPE *e;
+{
+ doexpand(s, buf, bufsize, 0, e);
}
/*
@@ -407,19 +460,19 @@ macset(mac, i, value)
char *
macvalue(n, e)
int n;
- register ENVELOPE *e;
+ ENVELOPE *e;
{
n = bitidx(n);
if (e != NULL && e->e_mci != NULL)
{
- register char *p = e->e_mci->mci_macro.mac_table[n];
+ char *p = e->e_mci->mci_macro.mac_table[n];
if (p != NULL)
return p;
}
while (e != NULL)
{
- register char *p = e->e_macro.mac_table[n];
+ char *p = e->e_macro.mac_table[n];
if (p != NULL)
return p;
@@ -429,6 +482,7 @@ macvalue(n, e)
}
return GlobalMacros.mac_table[n];
}
+
/*
** MACNAME -- return the name of a macro given its internal id
**
@@ -440,6 +494,9 @@ macvalue(n, e)
**
** Side Effects:
** none.
+**
+** WARNING:
+** Not thread-safe.
*/
char *
@@ -448,8 +505,12 @@ macname(n)
{
static char mbuf[2];
- n = bitidx(n);
- if (bitset(0200, n))
+ n = (int)(unsigned char)n;
+ if (n > MAXMACROID)
+ return "***OUT OF RANGE MACRO***";
+
+ /* if not ASCII printable, look up the name */
+ if (n <= 0x20 || n > 0x7f)
{
char *p = MacroName[n];
@@ -457,10 +518,13 @@ macname(n)
return p;
return "***UNDEFINED MACRO***";
}
+
+ /* if in the ASCII graphic range, just return the id directly */
mbuf[0] = n;
mbuf[1] = '\0';
return mbuf;
}
+
/*
** MACID_PARSE -- return id of macro identified by its name
**
@@ -472,7 +536,7 @@ macname(n)
**
** Returns:
** 0 -- An error was detected.
-** 1..255 -- The internal id code for this macro.
+** 1..MAXMACROID -- The internal id code for this macro.
**
** Side Effects:
** If this is a new macro name, a new id is allocated.
@@ -481,11 +545,11 @@ macname(n)
int
macid_parse(p, ep)
- register char *p;
+ char *p;
char **ep;
{
int mid;
- register char *bp;
+ char *bp;
char mbuf[MAXMACNAMELEN + 1];
if (tTd(35, 14))
@@ -510,11 +574,18 @@ macid_parse(p, ep)
if (ep != NULL)
*ep = p + 1;
if (tTd(35, 14))
- sm_dprintf("%c\n", bitidx(*p));
+ {
+ char buf[2];
+
+ buf[0] = *p;
+ buf[1] = '\0';
+ xputs(sm_debug_file(), buf);
+ sm_dprintf("\n");
+ }
return bitidx(*p);
}
bp = mbuf;
- while (*++p != '\0' && *p != '}' && bp < &mbuf[sizeof mbuf - 1])
+ while (*++p != '\0' && *p != '}' && bp < &mbuf[sizeof(mbuf) - 1])
{
if (isascii(*p) && (isalnum(*p) || *p == '_'))
*bp++ = *p;
@@ -530,7 +601,7 @@ macid_parse(p, ep)
else if (*p != '}')
{
syserr("Macro/class name ({%s}) too long (%d chars max)",
- mbuf, (int) (sizeof mbuf - 1));
+ mbuf, (int) (sizeof(mbuf) - 1));
}
else if (mbuf[1] == '\0')
{
@@ -540,7 +611,7 @@ macid_parse(p, ep)
}
else
{
- register STAB *s;
+ STAB *s;
s = stab(mbuf, ST_MACRO, ST_ENTER);
if (s->s_macro != 0)
@@ -574,6 +645,7 @@ macid_parse(p, ep)
sm_dprintf("0x%x\n", mid);
return mid;
}
+
/*
** WORDINCLASS -- tell if a word is in a specific class
**
@@ -591,7 +663,7 @@ wordinclass(str, cl)
char *str;
int cl;
{
- register STAB *s;
+ STAB *s;
s = stab(str, ST_CLASS, ST_FIND);
return s != NULL && bitnset(bitidx(cl), s->s_class);
diff --git a/contrib/sendmail/src/main.c b/contrib/sendmail/src/main.c
index 0d6928d19996..c11de46ed047 100644
--- a/contrib/sendmail/src/main.c
+++ b/contrib/sendmail/src/main.c
@@ -13,6 +13,7 @@
#define _DEFINE
#include
+#include
#include
#include
@@ -25,7 +26,7 @@ SM_UNUSED(static char copyright[]) =
The Regents of the University of California. All rights reserved.\n";
#endif /* ! lint */
-SM_RCSID("@(#)$Id: main.c,v 8.944.2.2 2006/08/03 22:05:03 ca Exp $")
+SM_RCSID("@(#)$Id: main.c,v 8.962 2006/12/19 19:47:37 ca Exp $")
#if NETINET || NETINET6
@@ -231,7 +232,7 @@ main(argc, argv, envp)
starttime = curtime();
/* avoid null pointer dereferences */
- TermEscape.te_rv_on = TermEscape.te_rv_off = "";
+ TermEscape.te_rv_on = TermEscape.te_under_on = TermEscape.te_normal = "";
RealUid = getuid();
RealGid = getgid();
@@ -305,7 +306,7 @@ main(argc, argv, envp)
checkfd012("after openlog");
#endif /* XDEBUG */
- tTsetup(tTdvect, sizeof tTdvect, "0-99.1,*_trace_*.1");
+ tTsetup(tTdvect, sizeof(tTdvect), "0-99.1,*_trace_*.1");
#ifdef NGROUPS_MAX
/* save initial group set for future checks */
@@ -477,7 +478,7 @@ main(argc, argv, envp)
"WARNING: Can not use -d with -q. Disabling debugging.\n");
sm_debug_close();
sm_debug_setfile(NULL);
- (void) memset(tTdvect, '\0', sizeof tTdvect);
+ (void) memset(tTdvect, '\0', sizeof(tTdvect));
}
#if LOG
@@ -521,9 +522,9 @@ main(argc, argv, envp)
pw = sm_getpwuid(RealUid);
if (pw != NULL)
- (void) sm_strlcpy(rnamebuf, pw->pw_name, sizeof rnamebuf);
+ (void) sm_strlcpy(rnamebuf, pw->pw_name, sizeof(rnamebuf));
else
- (void) sm_snprintf(rnamebuf, sizeof rnamebuf, "Unknown UID %d",
+ (void) sm_snprintf(rnamebuf, sizeof(rnamebuf), "Unknown UID %d",
(int) RealUid);
RealUserName = rnamebuf;
@@ -567,7 +568,7 @@ main(argc, argv, envp)
j = 0;
for (av = argv; *av != NULL; )
j += strlen(*av++) + 1;
- SaveArgv = (char **) xalloc(sizeof (char *) * (argc + 1));
+ SaveArgv = (char **) xalloc(sizeof(char *) * (argc + 1));
CommandLineArgs = xalloc(j);
p = CommandLineArgs;
for (av = argv, i = 0; *av != NULL; )
@@ -691,7 +692,7 @@ main(argc, argv, envp)
macdefine(&BlankEnvelope.e_macro, A_PERM, 'v', Version);
/* hostname */
- hp = myhostname(jbuf, sizeof jbuf);
+ hp = myhostname(jbuf, sizeof(jbuf));
if (jbuf[0] != '\0')
{
struct utsname utsname;
@@ -752,7 +753,7 @@ main(argc, argv, envp)
break;
memmove(&ia, hp->h_addr_list[i], INADDRSZ);
- (void) sm_snprintf(ipbuf, sizeof ipbuf,
+ (void) sm_snprintf(ipbuf, sizeof(ipbuf),
"[%.100s]", inet_ntoa(ia));
break;
# endif /* NETINET */
@@ -763,9 +764,9 @@ main(argc, argv, envp)
break;
memmove(&ia6, hp->h_addr_list[i], IN6ADDRSZ);
- addr = anynet_ntop(&ia6, buf6, sizeof buf6);
+ addr = anynet_ntop(&ia6, buf6, sizeof(buf6));
if (addr != NULL)
- (void) sm_snprintf(ipbuf, sizeof ipbuf,
+ (void) sm_snprintf(ipbuf, sizeof(ipbuf),
"[%.100s]", addr);
break;
# endif /* NETINET6 */
@@ -863,7 +864,7 @@ main(argc, argv, envp)
CHECK_AGAINST_OPMODE(j);
BlankEnvelope.e_hopcount = (short) strtol(optarg, &ep,
10);
- (void) sm_snprintf(buf, sizeof buf, "%d",
+ (void) sm_snprintf(buf, sizeof(buf), "%d",
BlankEnvelope.e_hopcount);
macdefine(&BlankEnvelope.e_macro, A_TEMP, 'c', buf);
@@ -1006,7 +1007,7 @@ main(argc, argv, envp)
break;
case 'I': /* Limit by ID */
- new = (QUEUE_CHAR *) xalloc(sizeof *new);
+ new = (QUEUE_CHAR *) xalloc(sizeof(*new));
new->queue_match = newstr(&optarg[1]);
new->queue_negate = negate;
new->queue_next = QueueLimitId;
@@ -1014,7 +1015,7 @@ main(argc, argv, envp)
break;
case 'R': /* Limit by recipient */
- new = (QUEUE_CHAR *) xalloc(sizeof *new);
+ new = (QUEUE_CHAR *) xalloc(sizeof(*new));
new->queue_match = newstr(&optarg[1]);
new->queue_negate = negate;
new->queue_next = QueueLimitRecipient;
@@ -1022,7 +1023,7 @@ main(argc, argv, envp)
break;
case 'S': /* Limit by sender */
- new = (QUEUE_CHAR *) xalloc(sizeof *new);
+ new = (QUEUE_CHAR *) xalloc(sizeof(*new));
new->queue_match = newstr(&optarg[1]);
new->queue_negate = negate;
new->queue_next = QueueLimitSender;
@@ -1036,7 +1037,7 @@ main(argc, argv, envp)
case 'Q': /* Limit by quarantine message */
if (optarg[1] != '\0')
{
- new = (QUEUE_CHAR *) xalloc(sizeof *new);
+ new = (QUEUE_CHAR *) xalloc(sizeof(*new));
new->queue_match = newstr(&optarg[1]);
new->queue_negate = negate;
new->queue_next = QueueLimitQuarantine;
@@ -1230,11 +1231,11 @@ main(argc, argv, envp)
mbuf[0] = '\0';
if (bitset(1 << STDIN_FILENO, MissingFds))
- (void) sm_strlcat(mbuf, ", stdin", sizeof mbuf);
+ (void) sm_strlcat(mbuf, ", stdin", sizeof(mbuf));
if (bitset(1 << STDOUT_FILENO, MissingFds))
- (void) sm_strlcat(mbuf, ", stdout", sizeof mbuf);
+ (void) sm_strlcat(mbuf, ", stdout", sizeof(mbuf));
if (bitset(1 << STDERR_FILENO, MissingFds))
- (void) sm_strlcat(mbuf, ", stderr", sizeof mbuf);
+ (void) sm_strlcat(mbuf, ", stderr", sizeof(mbuf));
/* Notice: fill_errno is from high above: fill_fd() */
sm_syslog(LOG_WARNING, NOQID,
@@ -1377,7 +1378,7 @@ main(argc, argv, envp)
HoldErrs = true;
/* set up the $=m class now, after .cf has a chance to redefine $m */
- expand("\201m", jbuf, sizeof jbuf, &BlankEnvelope);
+ expand("\201m", jbuf, sizeof(jbuf), &BlankEnvelope);
if (jbuf[0] != '\0')
setclass('m', jbuf);
@@ -1392,7 +1393,7 @@ main(argc, argv, envp)
/* Now we know which .cf file we use */
sm_dprintf(" Conf file:\t%s (selected)\n",
getcfname(OpMode, SubmitMode, cftype, conffile));
- expand(PidFile, pidpath, sizeof pidpath, &BlankEnvelope);
+ expand(PidFile, pidpath, sizeof(pidpath), &BlankEnvelope);
sm_dprintf(" Pid file:\t%s (selected)\n", pidpath);
}
@@ -1739,7 +1740,7 @@ main(argc, argv, envp)
SmtpError[0] = '\0';
/* our name for SMTP codes */
- expand("\201j", jbuf, sizeof jbuf, &BlankEnvelope);
+ expand("\201j", jbuf, sizeof(jbuf), &BlankEnvelope);
if (jbuf[0] == '\0')
PSTRSET(MyHostName, "localhost");
else
@@ -2082,7 +2083,7 @@ main(argc, argv, envp)
"> ");
(void) sm_io_flush(smioout, SM_TIME_DEFAULT);
if (sm_io_fgets(smioin, SM_TIME_DEFAULT, buf,
- sizeof buf) == NULL)
+ sizeof(buf)) == NULL)
testmodeline("/quit", &MainEnvelope);
p = strchr(buf, '\n');
if (p != NULL)
@@ -2112,7 +2113,8 @@ main(argc, argv, envp)
#if STARTTLS
tls_ok = true;
- if (OpMode == MD_QUEUERUN || OpMode == MD_DELIVER)
+ if (OpMode == MD_QUEUERUN || OpMode == MD_DELIVER ||
+ OpMode == MD_ARPAFTP)
{
/* check whether STARTTLS is turned off for the client */
if (chkclientmodifiers(D_NOTLS))
@@ -2324,7 +2326,7 @@ main(argc, argv, envp)
dtype[0] = '\0';
if (OpMode == MD_DAEMON)
{
- (void) sm_strlcat(dtype, "+SMTP", sizeof dtype);
+ (void) sm_strlcat(dtype, "+SMTP", sizeof(dtype));
DaemonPid = CurrentPid;
}
if (QueueIntvl > 0)
@@ -2334,10 +2336,10 @@ main(argc, argv, envp)
? "+persistent-queueing@"
: "+queueing@",
pintvl(QueueIntvl, true),
- sizeof dtype);
+ sizeof(dtype));
}
if (tTd(0, 1))
- (void) sm_strlcat(dtype, "+debugging", sizeof dtype);
+ (void) sm_strlcat(dtype, "+debugging", sizeof(dtype));
sm_syslog(LOG_INFO, NOQID,
"starting daemon (%s): %s", Version, dtype + 1);
@@ -2435,8 +2437,9 @@ main(argc, argv, envp)
}
sm_syslog(LOG_ERR, NOQID,
- "persistent queue runner=%d died, signal=%d",
- group, WTERMSIG(status));
+ "persistent queue runner=%d died, pid=%ld, signal=%d",
+ group, (long) ret,
+ WTERMSIG(status));
}
/*
@@ -2454,6 +2457,7 @@ main(argc, argv, envp)
mark_work_group_restart(group,
-1);
}
+ CHECK_RESTART;
}
finis(true, true, ExitStat);
/* NOTREACHED */
@@ -2472,7 +2476,7 @@ main(argc, argv, envp)
/* set the title to make it easier to find */
qtype[0] = '\0';
- (void) sm_strlcpyn(qtype, sizeof qtype, 4,
+ (void) sm_strlcpyn(qtype, sizeof(qtype), 4,
"Queue runner@",
pintvl(QueueIntvl, true),
" for ",
@@ -2541,7 +2545,7 @@ main(argc, argv, envp)
{
char ipbuf[103];
- (void) sm_snprintf(ipbuf, sizeof ipbuf, "[%.100s]",
+ (void) sm_snprintf(ipbuf, sizeof(ipbuf), "[%.100s]",
anynet_ntoa(&RealHostAddr));
macdefine(&BlankEnvelope.e_macro, A_TEMP,
macid("{client_name}"), ipbuf);
@@ -2559,18 +2563,18 @@ main(argc, argv, envp)
{
#if NETINET
case AF_INET:
- (void) sm_snprintf(pbuf, sizeof pbuf, "%d",
+ (void) sm_snprintf(pbuf, sizeof(pbuf), "%d",
RealHostAddr.sin.sin_port);
break;
#endif /* NETINET */
#if NETINET6
case AF_INET6:
- (void) sm_snprintf(pbuf, sizeof pbuf, "%d",
+ (void) sm_snprintf(pbuf, sizeof(pbuf), "%d",
RealHostAddr.sin6.sin6_port);
break;
#endif /* NETINET6 */
default:
- (void) sm_snprintf(pbuf, sizeof pbuf, "0");
+ (void) sm_snprintf(pbuf, sizeof(pbuf), "0");
break;
}
macdefine(&BlankEnvelope.e_macro, A_TEMP,
@@ -2578,17 +2582,24 @@ main(argc, argv, envp)
if (OpMode == MD_DAEMON)
{
+ ENVELOPE *saved_env;
+
/* validate the connection */
HoldErrs = true;
+ saved_env = CurEnv;
+ CurEnv = &BlankEnvelope;
nullserver = validate_connection(&RealHostAddr,
macvalue(macid("{client_name}"),
- &MainEnvelope),
- &MainEnvelope);
+ &BlankEnvelope),
+ &BlankEnvelope);
+ if (bitset(EF_DISCARD, BlankEnvelope.e_flags))
+ MainEnvelope.e_flags |= EF_DISCARD;
+ CurEnv = saved_env;
HoldErrs = false;
}
else if (p_flags == NULL)
{
- p_flags = (BITMAP256 *) xalloc(sizeof *p_flags);
+ p_flags = (BITMAP256 *) xalloc(sizeof(*p_flags));
clrbitmap(p_flags);
}
#if STARTTLS
@@ -2769,7 +2780,7 @@ main(argc, argv, envp)
}
/* set message size */
- (void) sm_snprintf(buf, sizeof buf, "%ld",
+ (void) sm_snprintf(buf, sizeof(buf), "%ld",
MainEnvelope.e_msgsize);
macdefine(&MainEnvelope.e_macro, A_TEMP,
macid("{msg_size}"), buf);
@@ -2909,8 +2920,15 @@ finis(drop, cleanup, exitstat)
sm_rpool_free(CurEnv->e_rpool);
CurEnv->e_rpool = NULL;
- /* this may have pointed to the rpool */
+ /* these may have pointed to the rpool */
CurEnv->e_to = NULL;
+ CurEnv->e_message = NULL;
+ CurEnv->e_statmsg = NULL;
+ CurEnv->e_quarmsg = NULL;
+ CurEnv->e_bodytype = NULL;
+ CurEnv->e_id = NULL;
+ CurEnv->e_envid = NULL;
+ CurEnv->e_auth_param = NULL;
}
else
poststats(StatFile);
@@ -2961,7 +2979,7 @@ finis(drop, cleanup, exitstat)
if (DaemonPid == pid || PidFilePid == pid)
{
/* blow away the pid file */
- expand(PidFile, pidpath, sizeof pidpath, CurEnv);
+ expand(PidFile, pidpath, sizeof(pidpath), CurEnv);
(void) unlink(pidpath);
}
@@ -3418,7 +3436,7 @@ auth_warning(e, msg, va_alist)
{
struct hostent *hp;
- hp = myhostname(hostbuf, sizeof hostbuf);
+ hp = myhostname(hostbuf, sizeof(hostbuf));
#if NETINET6
if (hp != NULL)
{
@@ -3428,12 +3446,12 @@ auth_warning(e, msg, va_alist)
#endif /* NETINET6 */
}
- (void) sm_strlcpyn(buf, sizeof buf, 2, hostbuf, ": ");
+ (void) sm_strlcpyn(buf, sizeof(buf), 2, hostbuf, ": ");
p = &buf[strlen(buf)];
SM_VA_START(ap, msg);
(void) sm_vsnprintf(p, SPACELEFT(buf, p), msg, ap);
SM_VA_END(ap);
- addheader("X-Authentication-Warning", buf, 0, e);
+ addheader("X-Authentication-Warning", buf, 0, e, true);
if (LogLevel > 3)
sm_syslog(LOG_INFO, e->e_id,
"Authentication-Warning: %.400s",
@@ -3589,9 +3607,6 @@ sigusr1(sig)
int sig;
{
int save_errno = errno;
-# if SM_HEAP_CHECK
- extern void dumpstab __P((void));
-# endif /* SM_HEAP_CHECK */
FIX_SYSV_SIGNAL(sig, sigusr1);
errno = save_errno;
@@ -3896,6 +3911,69 @@ sm_printoptions(options)
}
sm_dprintf("\n");
}
+
+/*
+** TO8BIT -- convert \octal sequences in a test mode input line
+**
+** Parameters:
+** str -- the input line.
+**
+** Returns:
+** none.
+**
+** Side Effects:
+** replaces \0octal in str with octal value.
+*/
+
+static bool to8bit __P((char *));
+
+static bool
+to8bit(str)
+ char *str;
+{
+ int c, len;
+ char *out, *in;
+ bool changed;
+
+ if (str == NULL)
+ return false;
+ in = out = str;
+ changed = false;
+ len = 0;
+ while ((c = (*str++ & 0377)) != '\0')
+ {
+ int oct, nxtc;
+
+ ++len;
+ if (c == '\\' &&
+ (nxtc = (*str & 0377)) == '0')
+ {
+ oct = 0;
+ while ((nxtc = (*str & 0377)) != '\0' &&
+ isascii(nxtc) && isdigit(nxtc))
+ {
+ oct <<= 3;
+ oct += nxtc - '0';
+ ++str;
+ ++len;
+ }
+ changed = true;
+ c = oct;
+ }
+ *out++ = c;
+ }
+ *out++ = c;
+ if (changed)
+ {
+ char *q;
+
+ q = quote_internal_chars(in, in, &len);
+ if (q != in)
+ sm_strlcpy(in, q, len);
+ }
+ return changed;
+}
+
/*
** TESTMODELINE -- process a test mode input line
**
@@ -3925,14 +4003,20 @@ testmodeline(line, e)
char **s;
struct rewrite *rw;
ADDRESS a;
+ char *lbp;
+ auto int lbs;
static int tryflags = RF_COPYNONE;
char exbuf[MAXLINE];
+ char lbuf[MAXLINE];
extern unsigned char TokTypeNoC[];
+ bool eightbit;
/* skip leading spaces */
while (*line == ' ')
line++;
+ lbp = NULL;
+ eightbit = false;
switch (line[0])
{
case '#':
@@ -3950,8 +4034,11 @@ testmodeline(line, e)
mid = macid_parse(&line[2], &delimptr);
if (mid == 0)
return;
- translate_dollars(delimptr);
- macdefine(&e->e_macro, A_TEMP, mid, delimptr);
+ lbs = sizeof(lbuf);
+ lbp = translate_dollars(delimptr, lbuf, &lbs);
+ macdefine(&e->e_macro, A_TEMP, mid, lbp);
+ if (lbp != lbuf)
+ SM_FREE(lbp);
break;
case 'C':
@@ -3961,8 +4048,11 @@ testmodeline(line, e)
mid = macid_parse(&line[2], &delimptr);
if (mid == 0)
return;
- translate_dollars(delimptr);
- expand(delimptr, exbuf, sizeof exbuf, e);
+ lbs = sizeof(lbuf);
+ lbp = translate_dollars(delimptr, lbuf, &lbs);
+ expand(lbp, exbuf, sizeof(exbuf), e);
+ if (lbp != lbuf)
+ SM_FREE(lbp);
p = exbuf;
while (*p != '\0')
{
@@ -4158,13 +4248,13 @@ testmodeline(line, e)
"Usage: /canon address\n");
return;
}
- else if (sm_strlcpy(host, p, sizeof host) >= sizeof host)
+ else if (sm_strlcpy(host, p, sizeof(host)) >= sizeof(host))
{
(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
"Name too long\n");
return;
}
- (void) getcanonname(host, sizeof host, !HasWildcardMX,
+ (void) getcanonname(host, sizeof(host), !HasWildcardMX,
NULL);
(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
"getcanonname(%s) returns %s\n",
@@ -4332,12 +4422,21 @@ testmodeline(line, e)
a.q_user);
e->e_to = NULL;
}
+ else if (sm_strcasecmp(&line[1], "header") == 0)
+ {
+ unsigned long ul;
+
+ ul = chompheader(p, CHHDR_CHECK|CHHDR_USER, NULL, e);
+ (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
+ "ul = %lu\n", ul);
+ }
else
{
(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
"Unknown \"/\" command %s\n",
line);
}
+ (void) sm_io_flush(smioout, SM_TIME_DEFAULT);
return;
}
@@ -4353,6 +4452,8 @@ testmodeline(line, e)
return;
}
*p = '\0';
+ if (tTd(23, 101))
+ eightbit = to8bit(p + 1);
if (invalidaddr(p + 1, NULL, true))
return;
do
@@ -4360,8 +4461,8 @@ testmodeline(line, e)
register char **pvp;
char pvpbuf[PSBUFSIZE];
- pvp = prescan(++p, ',', pvpbuf, sizeof pvpbuf, &delimptr,
- ConfigLevel >= 9 ? TokTypeNoC : NULL, false);
+ pvp = prescan(++p, ',', pvpbuf, sizeof(pvpbuf), &delimptr,
+ ConfigLevel >= 9 ? TokTypeNoC : ExtTokenTab, false);
if (pvp == NULL)
continue;
p = q;
@@ -4382,10 +4483,19 @@ testmodeline(line, e)
(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
"== Ruleset %s (%d) status %d\n",
p, rs, status);
+ else if (eightbit)
+ {
+ cataddr(pvp, NULL, exbuf, sizeof(exbuf), '\0',
+ true);
+ (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
+ "cataddr: %s\n",
+ str2prt(exbuf));
+ }
while (*p != '\0' && *p++ != ',')
continue;
}
} while (*(p = delimptr) != '\0');
+ (void) sm_io_flush(smioout, SM_TIME_DEFAULT);
}
static void
diff --git a/contrib/sendmail/src/map.c b/contrib/sendmail/src/map.c
index 9a7bf7a558c8..510b7c9a44b0 100644
--- a/contrib/sendmail/src/map.c
+++ b/contrib/sendmail/src/map.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998-2005 Sendmail, Inc. and its suppliers.
+ * Copyright (c) 1998-2006 Sendmail, Inc. and its suppliers.
* All rights reserved.
* Copyright (c) 1992, 1995-1997 Eric P. Allman. All rights reserved.
* Copyright (c) 1992, 1993
@@ -13,7 +13,7 @@
#include
-SM_RCSID("@(#)$Id: map.c,v 8.672 2006/04/18 01:26:41 ca Exp $")
+SM_RCSID("@(#)$Id: map.c,v 8.696 2007/04/03 21:33:14 ca Exp $")
#if LDAPMAP
# include
@@ -39,6 +39,8 @@ SM_RCSID("@(#)$Id: map.c,v 8.672 2006/04/18 01:26:41 ca Exp $")
# endif /* NDBM */
#endif /* NIS */
+#include "map.h"
+
#if NEWDB
# if DB_VERSION_MAJOR < 2
static bool db_map_open __P((MAP *, int, char *, DBTYPE, const void *));
@@ -659,6 +661,50 @@ map_close(s, bogus)
}
map->map_mflags &= ~(MF_OPEN|MF_WRITABLE|MF_OPENBOGUS|MF_CLOSING);
}
+
+#if defined(SUN_EXTENSIONS) && defined(SUN_INIT_DOMAIN)
+extern int getdomainname();
+
+/* this is mainly for backward compatibility in Sun environment */
+static char *
+sun_init_domain()
+{
+ /*
+ ** Get the domain name from the kernel.
+ ** If it does not start with a leading dot, then remove
+ ** the first component. Since leading dots are funny Unix
+ ** files, we treat a leading "+" the same as a leading dot.
+ ** Finally, force there to be at least one dot in the domain name
+ ** (i.e. top-level domains are not allowed, like "com", must be
+ ** something like "sun.com").
+ */
+
+ char buf[MAXNAME];
+ char *period, *autodomain;
+
+ if (getdomainname(buf, sizeof buf) < 0)
+ return NULL;
+
+ if (buf[0] == '\0')
+ return NULL;
+
+ if (tTd(0, 20))
+ printf("domainname = %s\n", buf);
+
+ if (buf[0] == '+')
+ buf[0] = '.';
+ period = strchr(buf, '.');
+ if (period == NULL)
+ autodomain = buf;
+ else
+ autodomain = period + 1;
+ if (strchr(autodomain, '.') == NULL)
+ return newstr(buf);
+ else
+ return newstr(autodomain);
+}
+#endif /* SUN_EXTENSIONS && SUN_INIT_DOMAIN */
+
/*
** GETCANONNAME -- look up name using service switch
**
@@ -687,6 +733,10 @@ getcanonname(host, hbsize, trymx, pttl)
auto int status;
char *maptype[MAXMAPSTACK];
short mapreturn[MAXMAPACTIONS];
+#if defined(SUN_EXTENSIONS) && defined(SUN_INIT_DOMAIN)
+ bool should_try_nis_domain = false;
+ static char *nis_domain = NULL;
+#endif
nmaps = switch_map_find("hosts", maptype, mapreturn);
if (pttl != 0)
@@ -706,12 +756,20 @@ getcanonname(host, hbsize, trymx, pttl)
else if (strcmp("nis", maptype[mapno]) == 0)
{
found = nis_getcanonname(host, hbsize, &status);
+# if defined(SUN_EXTENSIONS) && defined(SUN_INIT_DOMAIN)
+ if (nis_domain == NULL)
+ nis_domain = sun_init_domain();
+# endif /* defined(SUN_EXTENSIONS) && defined(SUN_INIT_DOMAIN) */
}
#endif /* NIS */
#if NISPLUS
else if (strcmp("nisplus", maptype[mapno]) == 0)
{
found = nisplus_getcanonname(host, hbsize, &status);
+# if defined(SUN_EXTENSIONS) && defined(SUN_INIT_DOMAIN)
+ if (nis_domain == NULL)
+ nis_domain = sun_init_domain();
+# endif /* defined(SUN_EXTENSIONS) && defined(SUN_INIT_DOMAIN) */
}
#endif /* NISPLUS */
#if NAMED_BIND
@@ -744,6 +802,12 @@ getcanonname(host, hbsize, trymx, pttl)
(macvalue('m', CurEnv) != NULL || strchr(host, '.') != NULL))
break;
+#if defined(SUN_EXTENSIONS) && defined(SUN_INIT_DOMAIN)
+ if (found)
+ should_try_nis_domain = true;
+ /* but don't break, as we need to try all methods first */
+#endif /* defined(SUN_EXTENSIONS) && defined(SUN_INIT_DOMAIN) */
+
/* see if we should continue */
if (status == EX_TEMPFAIL)
{
@@ -784,11 +848,33 @@ getcanonname(host, hbsize, trymx, pttl)
(void) sm_strlcat(host, d, hbsize);
}
else
+ {
+#if defined(SUN_EXTENSIONS) && defined(SUN_INIT_DOMAIN)
+ if (VendorCode == VENDOR_SUN &&
+ should_try_nis_domain)
+ {
+ goto try_nis_domain;
+ }
+#endif /* defined(SUN_EXTENSIONS) && defined(SUN_INIT_DOMAIN) */
return false;
+ }
}
return true;
}
+#if defined(SUN_EXTENSIONS) && defined(SUN_INIT_DOMAIN)
+ if (VendorCode == VENDOR_SUN && should_try_nis_domain)
+ {
+ try_nis_domain:
+ if (nis_domain != NULL &&
+ strlen(nis_domain) + strlen(host) + 1 < hbsize)
+ {
+ (void) sm_strlcat2(host, ".", nis_domain, hbsize);
+ return true;
+ }
+ }
+#endif /* defined(SUN_EXTENSIONS) && defined(SUN_INIT_DOMAIN) */
+
if (tTd(38, 20))
sm_dprintf("getcanonname(%s), failed, status=%d\n", host,
status);
@@ -835,7 +921,7 @@ extract_canonname(name, dot, line, cbuf, cbuflen)
{
char nbuf[MAXNAME + 1];
- p = get_column(line, i, '\0', nbuf, sizeof nbuf);
+ p = get_column(line, i, '\0', nbuf, sizeof(nbuf));
if (p == NULL)
break;
if (*p == '\0')
@@ -918,17 +1004,7 @@ dns_map_open(map, mode)
** false -- otherwise.
*/
-# if _FFR_DNSMAP_MULTILIMIT
-# if !_FFR_DNSMAP_MULTI
- ERROR README: You must define _FFR_DNSMAP_MULTI to use _FFR_DNSMAP_MULTILIMIT
-# endif /* ! _FFR_DNSMAP_MULTI */
-# endif /* _FFR_DNSMAP_MULTILIMIT */
-
-# if _FFR_DNSMAP_MULTI
-# if _FFR_DNSMAP_MULTILIMIT
-# define map_sizelimit map_lockfd /* overload field */
-# endif /* _FFR_DNSMAP_MULTILIMIT */
-# endif /* _FFR_DNSMAP_MULTI */
+#define map_sizelimit map_lockfd /* overload field */
struct dns_map
{
@@ -943,7 +1019,7 @@ dns_map_parseargs(map,args)
register char *p = args;
struct dns_map *map_p;
- map_p = (struct dns_map *) xalloc(sizeof *map_p);
+ map_p = (struct dns_map *) xalloc(sizeof(*map_p));
map_p->dns_m_type = -1;
map->map_mflags |= MF_TRY0NULL|MF_TRY1NULL;
@@ -1016,7 +1092,6 @@ dns_map_parseargs(map,args)
map->map_retry = atoi(p);
break;
-# if _FFR_DNSMAP_MULTI
case 'z':
if (*++p != '\\')
map->map_coldelim = *p;
@@ -1038,14 +1113,11 @@ dns_map_parseargs(map,args)
}
break;
-# if _FFR_DNSMAP_MULTILIMIT
case 'Z':
while (isascii(*++p) && isspace(*p))
continue;
map->map_sizelimit = atoi(p);
break;
-# endif /* _FFR_DNSMAP_MULTILIMIT */
-# endif /* _FFR_DNSMAP_MULTI */
/* Start of dns_map specific args */
case 'R': /* search field */
@@ -1066,7 +1138,6 @@ dns_map_parseargs(map,args)
}
break;
-# if _FFR_DNSMAP_BASE
case 'B': /* base domain */
{
char *h;
@@ -1087,8 +1158,6 @@ dns_map_parseargs(map,args)
*h = ' ';
}
break;
-# endif /* _FFR_DNSMAP_BASE */
-
}
while (*p != '\0' && !(isascii(*p) && isspace(*p)))
p++;
@@ -1103,7 +1172,7 @@ dns_map_parseargs(map,args)
map->map_tapp = newstr(map->map_tapp);
/*
- ** Assumption: assert(sizeof int <= sizeof(ARBPTR_T));
+ ** Assumption: assert(sizeof(int) <= sizeof(ARBPTR_T));
** Even if this assumption is wrong, we use only one byte,
** so it doesn't really matter.
*/
@@ -1133,11 +1202,7 @@ dns_map_lookup(map, name, av, statp)
char **av;
int *statp;
{
-# if _FFR_DNSMAP_MULTI
-# if _FFR_DNSMAP_MULTILIMIT
int resnum = 0;
-# endif /* _FFR_DNSMAP_MULTILIMIT */
-# endif /* _FFR_DNSMAP_MULTI */
char *vp = NULL, *result = NULL;
size_t vsize;
struct dns_map *map_p;
@@ -1152,7 +1217,6 @@ dns_map_lookup(map, name, av, statp)
map->map_mname, name);
map_p = (struct dns_map *)(map->map_db1);
-# if _FFR_DNSMAP_BASE
if (map->map_file != NULL && *map->map_file != '\0')
{
size_t len;
@@ -1171,7 +1235,6 @@ dns_map_lookup(map, name, av, statp)
sm_free(appdomain);
}
else
-# endif /* _FFR_DNSMAP_BASE */
{
r = dns_lookup_int(name, C_IN, map_p->dns_m_type,
map->map_timeout, map->map_retry);
@@ -1232,7 +1295,7 @@ dns_map_lookup(map, name, av, statp)
case T_AAAA:
type = "T_AAAA";
value = anynet_ntop(rr->rr_u.rr_aaaa, buf6,
- sizeof buf6);
+ sizeof(buf6));
break;
# endif /* NETINET6 */
}
@@ -1263,12 +1326,9 @@ dns_map_lookup(map, name, av, statp)
type != NULL ? type : "",
rr->rr_type,
value != NULL ? value : "");
-# if _FFR_DNSMAP_MULTI
if (value != NULL &&
(map->map_coldelim == '\0' ||
-# if _FFR_DNSMAP_MULTILIMIT
map->map_sizelimit == 1 ||
-# endif /* _FFR_DNSMAP_MULTILIMIT */
bitset(MF_MATCHONLY, map->map_mflags)))
{
/* Only care about the first match */
@@ -1292,16 +1352,10 @@ dns_map_lookup(map, name, av, statp)
vp, map->map_coldelim, value);
sm_free(vp);
vp = new;
-# if _FFR_DNSMAP_MULTILIMIT
if (map->map_sizelimit > 0 &&
++resnum >= map->map_sizelimit)
break;
-# endif /* _FFR_DNSMAP_MULTILIMIT */
}
-# else /* _FFR_DNSMAP_MULTI */
- vp = value;
- break;
-# endif /* _FFR_DNSMAP_MULTI */
}
if (vp == NULL)
{
@@ -1312,10 +1366,8 @@ dns_map_lookup(map, name, av, statp)
goto cleanup;
}
-# if _FFR_DNSMAP_MULTI
/* Cleanly truncate for rulesets */
truncate_at_delim(vp, PSBUFSIZE / 2, map->map_coldelim);
-# endif /* _FFR_DNSMAP_MULTI */
vsize = strlen(vp);
@@ -1328,10 +1380,8 @@ dns_map_lookup(map, name, av, statp)
result = map_rewrite(map, vp, vsize, av);
cleanup:
-# if _FFR_DNSMAP_MULTI
if (vp != NULL)
sm_free(vp);
-# endif /* _FFR_DNSMAP_MULTI */
if (r != NULL)
dns_free_data(r);
return result;
@@ -1373,10 +1423,10 @@ ndbm_map_open(map, mode)
mode &= O_ACCMODE;
/* do initial file and directory checks */
- if (sm_strlcpyn(dirfile, sizeof dirfile, 2,
- map->map_file, ".dir") >= sizeof dirfile ||
- sm_strlcpyn(pagfile, sizeof pagfile, 2,
- map->map_file, ".pag") >= sizeof pagfile)
+ if (sm_strlcpyn(dirfile, sizeof(dirfile), 2,
+ map->map_file, ".dir") >= sizeof(dirfile) ||
+ sm_strlcpyn(pagfile, sizeof(pagfile), 2,
+ map->map_file, ".pag") >= sizeof(pagfile))
{
errno = 0;
if (!bitset(MF_OPTIONAL, map->map_mflags))
@@ -1632,8 +1682,8 @@ ndbm_map_lookup(map, name, av, statp)
key.dsize = strlen(name);
if (!bitset(MF_NOFOLDCASE, map->map_mflags))
{
- if (key.dsize > sizeof keybuf - 1)
- key.dsize = sizeof keybuf - 1;
+ if (key.dsize > sizeof(keybuf) - 1)
+ key.dsize = sizeof(keybuf) - 1;
memmove(keybuf, key.dptr, key.dsize);
keybuf[key.dsize] = '\0';
makelower(keybuf);
@@ -1729,8 +1779,8 @@ ndbm_map_store(map, lhs, rhs)
key.dptr = lhs;
if (!bitset(MF_NOFOLDCASE, map->map_mflags))
{
- if (key.dsize > sizeof keybuf - 1)
- key.dsize = sizeof keybuf - 1;
+ if (key.dsize > sizeof(keybuf) - 1)
+ key.dsize = sizeof(keybuf) - 1;
memmove(keybuf, key.dptr, key.dsize);
keybuf[key.dsize] = '\0';
makelower(keybuf);
@@ -1814,10 +1864,10 @@ ndbm_map_close(map)
map->map_mflags |= MF_NOFOLDCASE;
- (void) sm_snprintf(buf, sizeof buf, "%010ld", curtime());
+ (void) sm_snprintf(buf, sizeof(buf), "%010ld", curtime());
ndbm_map_store(map, "YP_LAST_MODIFIED", buf);
- (void) gethostname(buf, sizeof buf);
+ (void) gethostname(buf, sizeof(buf));
ndbm_map_store(map, "YP_MASTER_NAME", buf);
map->map_mflags = save_mflags;
@@ -1890,7 +1940,7 @@ bt_map_open(map, mode)
map->map_mname, map->map_file, mode);
# if DB_VERSION_MAJOR < 3
- memset(&btinfo, '\0', sizeof btinfo);
+ memset(&btinfo, '\0', sizeof(btinfo));
# ifdef DB_CACHE_SIZE
btinfo.db_cachesize = DB_CACHE_SIZE;
# endif /* DB_CACHE_SIZE */
@@ -1919,7 +1969,7 @@ hash_map_open(map, mode)
map->map_mname, map->map_file, mode);
# if DB_VERSION_MAJOR < 3
- memset(&hinfo, '\0', sizeof hinfo);
+ memset(&hinfo, '\0', sizeof(hinfo));
# ifdef DB_HASH_NELEM
hinfo.h_nelem = DB_HASH_NELEM;
# endif /* DB_HASH_NELEM */
@@ -1958,7 +2008,7 @@ db_map_open(map, mode, mapclassname, dbtype, openinfo)
char buf[MAXPATHLEN];
/* do initial file and directory checks */
- if (sm_strlcpy(buf, map->map_file, sizeof buf) >= sizeof buf)
+ if (sm_strlcpy(buf, map->map_file, sizeof(buf)) >= sizeof(buf))
{
errno = 0;
if (!bitset(MF_OPTIONAL, map->map_mflags))
@@ -1969,7 +2019,7 @@ db_map_open(map, mode, mapclassname, dbtype, openinfo)
i = strlen(buf);
if (i < 3 || strcmp(&buf[i - 3], ".db") != 0)
{
- if (sm_strlcat(buf, ".db", sizeof buf) >= sizeof buf)
+ if (sm_strlcat(buf, ".db", sizeof(buf)) >= sizeof(buf))
{
errno = 0;
if (!bitset(MF_OPTIONAL, map->map_mflags))
@@ -2258,14 +2308,14 @@ db_map_lookup(map, name, av, statp)
char keybuf[MAXNAME + 1];
char buf[MAXPATHLEN];
- memset(&key, '\0', sizeof key);
- memset(&val, '\0', sizeof val);
+ memset(&key, '\0', sizeof(key));
+ memset(&val, '\0', sizeof(val));
if (tTd(38, 20))
sm_dprintf("db_map_lookup(%s, %s)\n",
map->map_mname, name);
- if (sm_strlcpy(buf, map->map_file, sizeof buf) >= sizeof buf)
+ if (sm_strlcpy(buf, map->map_file, sizeof(buf)) >= sizeof(buf))
{
errno = 0;
if (!bitset(MF_OPTIONAL, map->map_mflags))
@@ -2278,8 +2328,8 @@ db_map_lookup(map, name, av, statp)
buf[i - 3] = '\0';
key.size = strlen(name);
- if (key.size > sizeof keybuf - 1)
- key.size = sizeof keybuf - 1;
+ if (key.size > sizeof(keybuf) - 1)
+ key.size = sizeof(keybuf) - 1;
key.data = keybuf;
memmove(keybuf, name, key.size);
keybuf[key.size] = '\0';
@@ -2417,8 +2467,8 @@ db_map_store(map, lhs, rhs)
register DB *db = map->map_db2;
char keybuf[MAXNAME + 1];
- memset(&key, '\0', sizeof key);
- memset(&data, '\0', sizeof data);
+ memset(&key, '\0', sizeof(key));
+ memset(&data, '\0', sizeof(data));
if (tTd(38, 12))
sm_dprintf("db_map_store(%s, %s, %s)\n",
@@ -2428,8 +2478,8 @@ db_map_store(map, lhs, rhs)
key.data = lhs;
if (!bitset(MF_NOFOLDCASE, map->map_mflags))
{
- if (key.size > sizeof keybuf - 1)
- key.size = sizeof keybuf - 1;
+ if (key.size > sizeof(keybuf) - 1)
+ key.size = sizeof(keybuf) - 1;
memmove(keybuf, key.data, key.size);
keybuf[key.size] = '\0';
makelower(keybuf);
@@ -2474,7 +2524,7 @@ db_map_store(map, lhs, rhs)
static int bufsiz = 0;
DBT old;
- memset(&old, '\0', sizeof old);
+ memset(&old, '\0', sizeof(old));
old.data = db_map_lookup(map, key.data,
(char **) NULL, &status);
@@ -2688,8 +2738,8 @@ nis_map_lookup(map, name, av, statp)
map->map_mname, name);
buflen = strlen(name);
- if (buflen > sizeof keybuf - 1)
- buflen = sizeof keybuf - 1;
+ if (buflen > sizeof(keybuf) - 1)
+ buflen = sizeof(keybuf) - 1;
memmove(keybuf, name, buflen);
keybuf[buflen] = '\0';
if (!bitset(MF_NOFOLDCASE, map->map_mflags))
@@ -2757,7 +2807,7 @@ nis_getcanonname(name, hbsize, statp)
if (tTd(38, 20))
sm_dprintf("nis_getcanonname(%s)\n", name);
- if (sm_strlcpy(nbuf, name, sizeof nbuf) >= sizeof nbuf)
+ if (sm_strlcpy(nbuf, name, sizeof(nbuf)) >= sizeof(nbuf))
{
*statp = EX_UNAVAILABLE;
return false;
@@ -2798,14 +2848,14 @@ nis_getcanonname(name, hbsize, statp)
sm_free(vp);
return false;
}
- (void) sm_strlcpy(host_record, vp, sizeof host_record);
+ (void) sm_strlcpy(host_record, vp, sizeof(host_record));
sm_free(vp);
if (tTd(38, 44))
sm_dprintf("got record `%s'\n", host_record);
vp = strpbrk(host_record, "#\n");
if (vp != NULL)
*vp = '\0';
- if (!extract_canonname(nbuf, NULL, host_record, cbuf, sizeof cbuf))
+ if (!extract_canonname(nbuf, NULL, host_record, cbuf, sizeof(cbuf)))
{
/* this should not happen, but.... */
*statp = EX_NOHOST;
@@ -2877,12 +2927,12 @@ nisplus_map_open(map, mode)
if (!PARTIAL_NAME(map->map_file))
{
map->map_domain = newstr("");
- (void) sm_strlcpy(qbuf, map->map_file, sizeof qbuf);
+ (void) sm_strlcpy(qbuf, map->map_file, sizeof(qbuf));
}
else
{
/* check to see if this map actually exists */
- (void) sm_strlcpyn(qbuf, sizeof qbuf, 3,
+ (void) sm_strlcpyn(qbuf, sizeof(qbuf), 3,
map->map_file, ".", map->map_domain);
}
@@ -3021,7 +3071,7 @@ nisplus_map_lookup(map, name, av, statp)
** NIS+ parser choke on them.
*/
- skleft = sizeof search_key - 4;
+ skleft = sizeof(search_key) - 4;
skp = search_key;
for (p = name; *p != '\0' && skleft > 0; p++)
{
@@ -3054,11 +3104,11 @@ nisplus_map_lookup(map, name, av, statp)
/* construct the query */
if (PARTIAL_NAME(map->map_file))
- (void) sm_snprintf(qbuf, sizeof qbuf, "[%s=%s],%s.%s",
+ (void) sm_snprintf(qbuf, sizeof(qbuf), "[%s=%s],%s.%s",
map->map_keycolnm, search_key, map->map_file,
map->map_domain);
else
- (void) sm_snprintf(qbuf, sizeof qbuf, "[%s=%s],%s",
+ (void) sm_snprintf(qbuf, sizeof(qbuf), "[%s=%s],%s",
map->map_keycolnm, search_key, map->map_file);
if (tTd(38, 20))
@@ -3135,7 +3185,7 @@ nisplus_getcanonname(name, hbsize, statp)
char nbuf[MAXNAME + 1];
char qbuf[MAXLINE + NIS_MAXNAMELEN];
- if (sm_strlcpy(nbuf, name, sizeof nbuf) >= sizeof nbuf)
+ if (sm_strlcpy(nbuf, name, sizeof(nbuf)) >= sizeof(nbuf))
{
*statp = EX_UNAVAILABLE;
return false;
@@ -3146,14 +3196,14 @@ nisplus_getcanonname(name, hbsize, statp)
if (p == NULL)
{
/* single token */
- (void) sm_snprintf(qbuf, sizeof qbuf,
+ (void) sm_snprintf(qbuf, sizeof(qbuf),
"[name=%s],hosts.org_dir", nbuf);
}
else if (p[1] != '\0')
{
/* multi token -- take only first token in nbuf */
*p = '\0';
- (void) sm_snprintf(qbuf, sizeof qbuf,
+ (void) sm_snprintf(qbuf, sizeof(qbuf),
"[name=%s],hosts.org_dir.%s", nbuf, &p[1]);
}
else
@@ -3247,7 +3297,7 @@ nisplus_default_domain()
return default_domain;
p = nis_local_directory();
- (void) sm_strlcpy(default_domain, p, sizeof default_domain);
+ (void) sm_strlcpy(default_domain, p, sizeof(default_domain));
return default_domain;
}
@@ -3318,6 +3368,15 @@ ldapmap_open(map, mode)
if (tTd(38, 2))
sm_dprintf("ldapmap_open(%s, %d): ", map->map_mname, mode);
+#if defined(SUN_EXTENSIONS) && defined(SUN_SIMPLIFIED_LDAP) && \
+ HASLDAPGETALIASBYNAME
+ if (VendorCode == VENDOR_SUN &&
+ strcmp(map->map_mname, "aliases.ldap") == 0)
+ {
+ return true;
+ }
+#endif /* defined(SUN_EXTENSIONS) && defined(SUN_SIMPLIFIED_LDAP) && ... */
+
mode &= O_ACCMODE;
/* sendmail doesn't have the ability to write to LDAP (yet) */
@@ -3471,6 +3530,9 @@ sunet_id_hash(str)
*p_last = '\0';
return str;
}
+# define SM_CONVERT_ID(str) sunet_id_hash(str)
+# else /* SUNET_ID */
+# define SM_CONVERT_ID(str) makelower(str)
# endif /* SUNET_ID */
/*
@@ -3485,6 +3547,7 @@ ldapmap_lookup(map, name, av, statp)
int *statp;
{
int flags;
+ int i;
int plen = 0;
int psize = 0;
int msgid;
@@ -3493,39 +3556,122 @@ ldapmap_lookup(map, name, av, statp)
char *result = NULL;
SM_RPOOL_T *rpool;
SM_LDAP_STRUCT *lmap = NULL;
+ char *argv[SM_LDAP_ARGS];
char keybuf[MAXKEY];
+#if SM_LDAP_ARGS != MAX_MAP_ARGS
+# ERROR _SM_LDAP_ARGS must be the same as _MAX_MAP_ARGS
+#endif /* SM_LDAP_ARGS != MAX_MAP_ARGS */
- if (tTd(38, 20))
- sm_dprintf("ldapmap_lookup(%s, %s)\n", map->map_mname, name);
+#if defined(SUN_EXTENSIONS) && defined(SUN_SIMPLIFIED_LDAP) && \
+ HASLDAPGETALIASBYNAME
+ if (VendorCode == VENDOR_SUN &&
+ strcmp(map->map_mname, "aliases.ldap") == 0)
+ {
+ char answer[MAXNAME + 1];
+ int rc;
+
+ rc = __getldapaliasbyname(name, answer, sizeof(answer));
+ if (rc != 0)
+ {
+ if (tTd(38, 20))
+ sm_dprintf("getldapaliasbyname(%.100s) failed, errno=%d\n",
+ name, errno);
+ *statp = EX_NOTFOUND;
+ return NULL;
+ }
+ *statp = EX_OK;
+ if (tTd(38, 20))
+ sm_dprintf("getldapaliasbyname(%.100s) => %s\n", name,
+ answer);
+ if (bitset(MF_MATCHONLY, map->map_mflags))
+ result = map_rewrite(map, name, strlen(name), NULL);
+ else
+ result = map_rewrite(map, answer, strlen(answer), av);
+ return result;
+ }
+#endif /* defined(SUN_EXTENSIONS) && defined(SUN_SIMPLIFIED_LDAP) && ... */
/* Get ldap struct pointer from map */
lmap = (SM_LDAP_STRUCT *) map->map_db1;
sm_ldap_setopts(lmap->ldap_ld, lmap);
- (void) sm_strlcpy(keybuf, name, sizeof keybuf);
-
- if (!bitset(MF_NOFOLDCASE, map->map_mflags))
+ if (lmap->ldap_multi_args)
{
-# ifdef SUNET_ID
- sunet_id_hash(keybuf);
-# else /* SUNET_ID */
- makelower(keybuf);
-# endif /* SUNET_ID */
+ SM_REQUIRE(av != NULL);
+ memset(argv, '\0', sizeof(argv));
+ for (i = 0; i < SM_LDAP_ARGS && av[i] != NULL; i++)
+ {
+ argv[i] = sm_strdup(av[i]);
+ if (argv[i] == NULL)
+ {
+ int save_errno, j;
+
+ save_errno = errno;
+ for (j = 0; j < i && argv[j] != NULL; j++)
+ SM_FREE(argv[j]);
+ *statp = EX_TEMPFAIL;
+ errno = save_errno;
+ return NULL;
+ }
+
+ if (!bitset(MF_NOFOLDCASE, map->map_mflags))
+ SM_CONVERT_ID(av[i]);
+ }
+ }
+ else
+ {
+ (void) sm_strlcpy(keybuf, name, sizeof(keybuf));
+
+ if (!bitset(MF_NOFOLDCASE, map->map_mflags))
+ SM_CONVERT_ID(keybuf);
}
- msgid = sm_ldap_search(lmap, keybuf);
- if (msgid == -1)
+ if (tTd(38, 20))
+ {
+ if (lmap->ldap_multi_args)
+ {
+ sm_dprintf("ldapmap_lookup(%s, argv)\n",
+ map->map_mname);
+ for (i = 0; i < SM_LDAP_ARGS; i++)
+ {
+ sm_dprintf(" argv[%d] = %s\n", i,
+ argv[i] == NULL ? "NULL" : argv[i]);
+ }
+ }
+ else
+ {
+ sm_dprintf("ldapmap_lookup(%s, %s)\n",
+ map->map_mname, name);
+ }
+ }
+
+ if (lmap->ldap_multi_args)
+ {
+ msgid = sm_ldap_search_m(lmap, argv);
+
+ /* free the argv array and its content, no longer needed */
+ for (i = 0; i < SM_LDAP_ARGS && argv[i] != NULL; i++)
+ SM_FREE(argv[i]);
+ }
+ else
+ msgid = sm_ldap_search(lmap, keybuf);
+ if (msgid == SM_LDAP_ERR)
{
errno = sm_ldap_geterrno(lmap->ldap_ld) + E_LDAPBASE;
save_errno = errno;
if (!bitset(MF_OPTIONAL, map->map_mflags))
{
+ /*
+ ** Do not include keybuf as this error may be shown
+ ** to outsiders.
+ */
+
if (bitset(MF_NODEFER, map->map_mflags))
- syserr("Error in ldap_search using %s in map %s",
- keybuf, map->map_mname);
+ syserr("Error in ldap_search in map %s",
+ map->map_mname);
else
- syserr("451 4.3.5 Error in ldap_search using %s in map %s",
- keybuf, map->map_mname);
+ syserr("451 4.3.5 Error in ldap_search in map %s",
+ map->map_mname);
}
*statp = EX_TEMPFAIL;
switch (save_errno - E_LDAPBASE)
@@ -3542,6 +3688,19 @@ ldapmap_lookup(map, name, av, statp)
errno = save_errno;
return NULL;
}
+#if SM_LDAP_ERROR_ON_MISSING_ARGS
+ else if (msgid == SM_LDAP_ERR_ARG_MISS)
+ {
+ if (bitset(MF_NODEFER, map->map_mflags))
+ syserr("Error in ldap_search in map %s, too few arguments",
+ map->map_mname);
+ else
+ syserr("554 5.3.5 Error in ldap_search in map %s, too few arguments",
+ map->map_mname);
+ *statp = EX_CONFIG;
+ return NULL;
+ }
+#endif /* SM_LDAP_ERROR_ON_MISSING_ARGS */
*statp = EX_NOTFOUND;
vp = NULL;
@@ -3722,7 +3881,7 @@ ldapmap_parseargs(map, args)
if (lmap == NULL || lmap != LDAPDefaults)
{
/* We need to alloc an SM_LDAP_STRUCT struct */
- lmap = (SM_LDAP_STRUCT *) xalloc(sizeof *lmap);
+ lmap = (SM_LDAP_STRUCT *) xalloc(sizeof(*lmap));
if (LDAPDefaults == NULL)
sm_ldap_clear(lmap);
else
@@ -3746,11 +3905,11 @@ ldapmap_parseargs(map, args)
char lcbuf[MAXLINE];
/* Get $j */
- expand("\201j", jbuf, sizeof jbuf, &BlankEnvelope);
+ expand("\201j", jbuf, sizeof(jbuf), &BlankEnvelope);
if (jbuf[0] == '\0')
{
(void) sm_strlcpy(jbuf, "localhost",
- sizeof jbuf);
+ sizeof(jbuf));
}
lc = macvalue(macid("{sendmailMTACluster}"), CurEnv);
@@ -3758,14 +3917,14 @@ ldapmap_parseargs(map, args)
lc = "";
else
{
- expand(lc, lcbuf, sizeof lcbuf, CurEnv);
+ expand(lc, lcbuf, sizeof(lcbuf), CurEnv);
lc = lcbuf;
}
- n = sm_snprintf(ldapfilt, sizeof ldapfilt,
+ n = sm_snprintf(ldapfilt, sizeof(ldapfilt),
"(&(objectClass=sendmailMTAAliasObject)(sendmailMTAAliasGrouping=aliases)(|(sendmailMTACluster=%s)(sendmailMTAHost=%s))(sendmailMTAKey=%%0))",
lc, jbuf);
- if (n >= sizeof ldapfilt)
+ if (n >= sizeof(ldapfilt))
{
syserr("%s: Default LDAP string too long",
map->map_mname);
@@ -4138,6 +4297,10 @@ ldapmap_parseargs(map, args)
# endif /* LDAP_VERSION_MIN */
break;
+ case 'K':
+ lmap->ldap_multi_args = true;
+ break;
+
default:
syserr("Illegal option %c map %s", *p, map->map_mname);
break;
@@ -4228,7 +4391,7 @@ ldapmap_parseargs(map, args)
ldapmap_dequote(lmap->ldap_secret));
return false;
}
- lmap->ldap_secret = sfgets(m_tmp, sizeof m_tmp,
+ lmap->ldap_secret = sfgets(m_tmp, sizeof(m_tmp),
sfd, TimeOuts.to_fileopen,
"ldapmap_parseargs");
(void) sm_io_close(sfd, SM_TIME_DEFAULT);
@@ -4257,7 +4420,7 @@ ldapmap_parseargs(map, args)
** stashed
*/
- (void) sm_snprintf(m_tmp, sizeof m_tmp,
+ (void) sm_snprintf(m_tmp, sizeof(m_tmp),
"KRBTKFILE=%s",
ldapmap_dequote(lmap->ldap_secret));
lmap->ldap_secret = m_tmp;
@@ -4481,10 +4644,10 @@ ldapmap_set_defaults(spec)
/* Allocate and set the default values */
if (LDAPDefaults == NULL)
- LDAPDefaults = (SM_LDAP_STRUCT *) xalloc(sizeof *LDAPDefaults);
+ LDAPDefaults = (SM_LDAP_STRUCT *) xalloc(sizeof(*LDAPDefaults));
sm_ldap_clear(LDAPDefaults);
- memset(&map, '\0', sizeof map);
+ memset(&map, '\0', sizeof(map));
/* look up the class */
class = stab("ldap", ST_MAPCLASS, ST_FIND);
@@ -4535,7 +4698,7 @@ ldapmap_set_defaults(spec)
/*
** Support for the CCSO Nameserver (ph/qi).
** This code is intended to replace the so-called "ph mailer".
-** Contributed by Mark D. Roth . Contact him for support.
+** Contributed by Mark D. Roth. Contact him for support.
*/
/* what version of the ph map code we're running */
@@ -4572,11 +4735,11 @@ ph_map_parseargs(map, args)
PH_MAP_STRUCT *pmap = NULL;
/* initialize version string */
- (void) sm_snprintf(phmap_id, sizeof phmap_id,
+ (void) sm_snprintf(phmap_id, sizeof(phmap_id),
"sendmail-%s phmap-20010529 libphclient-%s",
Version, libphclient_version);
- pmap = (PH_MAP_STRUCT *) xalloc(sizeof *pmap);
+ pmap = (PH_MAP_STRUCT *) xalloc(sizeof(*pmap));
/* defaults */
pmap->ph_servers = NULL;
@@ -4961,6 +5124,7 @@ ph_map_lookup(map, key, args, pstat)
return NULL;
}
#endif /* PH_MAP */
+
/*
** syslog map
*/
@@ -5099,6 +5263,99 @@ syslog_map_lookup(map, string, args, statp)
return "";
}
+#if _FFR_DPRINTF_MAP
+/*
+** dprintf map
+*/
+
+#define map_dbg_level map_lockfd /* overload field */
+
+/*
+** DPRINTF_MAP_PARSEARGS -- check for priority level to dprintf messages.
+*/
+
+bool
+dprintf_map_parseargs(map, args)
+ MAP *map;
+ char *args;
+{
+ char *p = args;
+ char *dbg_level = NULL;
+
+ /* there is no check whether there is really an argument */
+ while (*p != '\0')
+ {
+ while (isascii(*p) && isspace(*p))
+ p++;
+ if (*p != '-')
+ break;
+ ++p;
+ if (*p == 'D')
+ {
+ map->map_mflags |= MF_DEFER;
+ ++p;
+ }
+ else if (*p == 'S')
+ {
+ map->map_spacesub = *++p;
+ if (*p != '\0')
+ p++;
+ }
+ else if (*p == 'd')
+ {
+ while (*++p != '\0' && isascii(*p) && isspace(*p))
+ continue;
+ if (*p == '\0')
+ break;
+ dbg_level = p;
+ while (*p != '\0' && !(isascii(*p) && isspace(*p)))
+ p++;
+ if (*p != '\0')
+ *p++ = '\0';
+ }
+ else
+ {
+ syserr("Illegal option %c map dprintf", *p);
+ ++p;
+ }
+ }
+
+ if (dbg_level == NULL)
+ map->map_dbg_level = 0;
+ else
+ {
+ if (!(isascii(*dbg_level) && isdigit(*dbg_level)))
+ {
+ syserr("dprintf map \"%s\", file %s: -d should specify a number, not %s",
+ map->map_mname, map->map_file,
+ dbg_level);
+ return false;
+ }
+ map->map_dbg_level = atoi(dbg_level);
+ }
+ return true;
+}
+
+/*
+** DPRINTF_MAP_LOOKUP -- rewrite and print message. Always return empty string
+*/
+
+char *
+dprintf_map_lookup(map, string, args, statp)
+ MAP *map;
+ char *string;
+ char **args;
+ int *statp;
+{
+ char *ptr = map_rewrite(map, string, strlen(string), args);
+
+ if (ptr != NULL && tTd(85, map->map_dbg_level))
+ sm_dprintf("%s\n", ptr);
+ *statp = EX_OK;
+ return "";
+}
+#endif /* _FFR_DPRINTF_MAP */
+
/*
** HESIOD Modules
*/
@@ -5166,12 +5423,12 @@ hes_map_lookup(map, name, av, statp)
char nbuf[MAXNAME];
nl = strlen(name);
- if (nl < sizeof nbuf - 1)
+ if (nl < sizeof(nbuf) - 1)
np = nbuf;
else
np = xalloc(strlen(name) + 2);
np[0] = '\\';
- (void) sm_strlcpy(&np[1], name, (sizeof nbuf) - 1);
+ (void) sm_strlcpy(&np[1], name, (sizeof(nbuf)) - 1);
# ifdef HESIOD_INIT
hp = hesiod_resolve(HesiodContext, np, map->map_file);
# else /* HESIOD_INIT */
@@ -5352,7 +5609,7 @@ ni_getcanonname(name, hbsize, statp)
if (tTd(38, 20))
sm_dprintf("ni_getcanonname(%s)\n", name);
- if (sm_strlcpy(nbuf, name, sizeof nbuf) >= sizeof nbuf)
+ if (sm_strlcpy(nbuf, name, sizeof(nbuf)) >= sizeof(nbuf))
{
*statp = EX_UNAVAILABLE;
return false;
@@ -5527,8 +5784,8 @@ text_map_lookup(map, name, av, statp)
sm_dprintf("text_map_lookup(%s, %s)\n", map->map_mname, name);
buflen = strlen(name);
- if (buflen > sizeof search_key - 1)
- buflen = sizeof search_key - 1; /* XXX just cut if off? */
+ if (buflen > sizeof(search_key) - 1)
+ buflen = sizeof(search_key) - 1; /* XXX just cut if off? */
memmove(search_key, name, buflen);
search_key[buflen] = '\0';
if (!bitset(MF_NOFOLDCASE, map->map_mflags))
@@ -5544,7 +5801,7 @@ text_map_lookup(map, name, av, statp)
key_idx = map->map_keycolno;
delim = map->map_coldelim;
while (sm_io_fgets(f, SM_TIME_DEFAULT,
- linebuf, sizeof linebuf) != NULL)
+ linebuf, sizeof(linebuf)) != NULL)
{
char *p;
@@ -5554,7 +5811,7 @@ text_map_lookup(map, name, av, statp)
p = strchr(linebuf, '\n');
if (p != NULL)
*p = '\0';
- p = get_column(linebuf, key_idx, delim, buf, sizeof buf);
+ p = get_column(linebuf, key_idx, delim, buf, sizeof(buf));
if (p != NULL && sm_strcasecmp(search_key, p) == 0)
{
found_it = true;
@@ -5567,7 +5824,7 @@ text_map_lookup(map, name, av, statp)
*statp = EX_NOTFOUND;
return NULL;
}
- vp = get_column(linebuf, map->map_valcolno, delim, buf, sizeof buf);
+ vp = get_column(linebuf, map->map_valcolno, delim, buf, sizeof(buf));
if (vp == NULL)
{
*statp = EX_NOTFOUND;
@@ -5601,7 +5858,7 @@ text_getcanonname(name, hbsize, statp)
if (tTd(38, 20))
sm_dprintf("text_getcanonname(%s)\n", name);
- if (sm_strlcpy(nbuf, name, sizeof nbuf) >= sizeof nbuf)
+ if (sm_strlcpy(nbuf, name, sizeof(nbuf)) >= sizeof(nbuf))
{
*statp = EX_UNAVAILABLE;
return false;
@@ -5618,7 +5875,7 @@ text_getcanonname(name, hbsize, statp)
found = false;
while (!found &&
sm_io_fgets(f, SM_TIME_DEFAULT,
- linebuf, sizeof linebuf) != NULL)
+ linebuf, sizeof(linebuf)) != NULL)
{
char *p = strpbrk(linebuf, "#\n");
@@ -5626,7 +5883,7 @@ text_getcanonname(name, hbsize, statp)
*p = '\0';
if (linebuf[0] != '\0')
found = extract_canonname(nbuf, dot, linebuf,
- cbuf, sizeof cbuf);
+ cbuf, sizeof(cbuf));
}
(void) sm_io_close(f, SM_TIME_DEFAULT);
if (!found)
@@ -5970,13 +6227,13 @@ user_map_lookup(map, key, av, statp)
break;
case 3:
- (void) sm_snprintf(buf, sizeof buf, "%d",
+ (void) sm_snprintf(buf, sizeof(buf), "%d",
(int) user.mbdb_uid);
rwval = buf;
break;
case 4:
- (void) sm_snprintf(buf, sizeof buf, "%d",
+ (void) sm_snprintf(buf, sizeof(buf), "%d",
(int) user.mbdb_gid);
rwval = buf;
break;
@@ -6033,7 +6290,7 @@ prog_map_lookup(map, name, av, statp)
argv[i++] = map->map_file;
if (map->map_rebuild != NULL)
{
- (void) sm_strlcpy(buf, map->map_rebuild, sizeof buf);
+ (void) sm_strlcpy(buf, map->map_rebuild, sizeof(buf));
for (p = strtok(buf, " \t"); p != NULL; p = strtok(NULL, " \t"))
{
if (i >= MAXPV - 1)
@@ -6064,7 +6321,7 @@ prog_map_lookup(map, name, av, statp)
*statp = EX_OSFILE;
return NULL;
}
- i = read(fd, buf, sizeof buf - 1);
+ i = read(fd, buf, sizeof(buf) - 1);
if (i < 0)
{
syserr("prog_map_lookup(%s): read error %s",
@@ -6092,7 +6349,7 @@ prog_map_lookup(map, name, av, statp)
rval = map_rewrite(map, buf, strlen(buf), av);
/* now flush any additional output */
- while ((i = read(fd, buf, sizeof buf)) > 0)
+ while ((i = read(fd, buf, sizeof(buf))) > 0)
continue;
}
@@ -6239,7 +6496,7 @@ switch_map_open(map, mode)
if (maptype[mapno] == NULL)
continue;
- (void) sm_strlcpyn(nbuf, sizeof nbuf, 3,
+ (void) sm_strlcpyn(nbuf, sizeof(nbuf), 3,
map->map_mname, ".", maptype[mapno]);
s = stab(nbuf, ST_MAP, ST_FIND);
if (s == NULL)
@@ -6561,7 +6818,7 @@ regex_map_init(map, ap)
pflags = REG_ICASE | REG_EXTENDED | REG_NOSUB;
p = ap;
- map_p = (struct regex_map *) xnalloc(sizeof *map_p);
+ map_p = (struct regex_map *) xnalloc(sizeof(*map_p));
map_p->regex_pattern_buf = (regex_t *)xnalloc(sizeof(regex_t));
for (;;)
@@ -6629,7 +6886,7 @@ regex_map_init(map, ap)
char errbuf[ERRBUF_SIZE];
(void) regerror(regerr, map_p->regex_pattern_buf,
- errbuf, sizeof errbuf);
+ errbuf, sizeof(errbuf));
syserr("pattern-compile-error: %s", errbuf);
sm_free(map_p->regex_pattern_buf); /* XXX */
sm_free(map_p); /* XXX */
@@ -6884,10 +7141,10 @@ ns_map_t_find(mapname)
/* if we are looking at a NULL ns_map_list_t, then create a new one */
if (ns_map == NULL)
{
- ns_map = (ns_map_list_t *) xalloc(sizeof *ns_map);
+ ns_map = (ns_map_list_t *) xalloc(sizeof(*ns_map));
ns_map->mapname = newstr(mapname);
- ns_map->map = (ns_map_t *) xalloc(sizeof *ns_map->map);
- memset(ns_map->map, '\0', sizeof *ns_map->map);
+ ns_map->map = (ns_map_t *) xalloc(sizeof(*ns_map->map));
+ memset(ns_map->map, '\0', sizeof(*ns_map->map));
ns_map->next = ns_maps;
ns_maps = ns_map;
}
@@ -6911,8 +7168,8 @@ nsd_map_lookup(map, name, av, statp)
sm_dprintf("nsd_map_lookup(%s, %s)\n", map->map_mname, name);
buflen = strlen(name);
- if (buflen > sizeof keybuf - 1)
- buflen = sizeof keybuf - 1; /* XXX simply cut off? */
+ if (buflen > sizeof(keybuf) - 1)
+ buflen = sizeof(keybuf) - 1; /* XXX simply cut off? */
memmove(keybuf, name, buflen);
keybuf[buflen] = '\0';
if (!bitset(MF_NOFOLDCASE, map->map_mflags))
@@ -6927,7 +7184,7 @@ nsd_map_lookup(map, name, av, statp)
return NULL;
}
r = ns_lookup(ns_map, NULL, map->map_file, keybuf, NULL,
- buf, sizeof buf);
+ buf, sizeof(buf));
if (r == NS_UNAVAIL || r == NS_TRYAGAIN)
{
*statp = EX_TEMPFAIL;
@@ -7038,6 +7295,13 @@ arith_map_lookup(map, name, av, statp)
boolres = true;
break;
+ case 'r':
+ r = v[1] - v[0] + 1;
+ if (r <= 0)
+ return NULL;
+ r = get_random() % r + v[0];
+ break;
+
default:
/* XXX */
*statp = EX_CONFIG;
@@ -7048,10 +7312,10 @@ arith_map_lookup(map, name, av, statp)
return NULL;
}
if (boolres)
- (void) sm_snprintf(result, sizeof result,
+ (void) sm_snprintf(result, sizeof(result),
res ? "TRUE" : "FALSE");
else
- (void) sm_snprintf(result, sizeof result, "%ld", r);
+ (void) sm_snprintf(result, sizeof(result), "%ld", r);
return result;
}
*statp = EX_CONFIG;
@@ -7129,7 +7393,7 @@ socket_map_open(map, mode)
/* XXX It should be put in a library... */
/* protocol:filename or protocol:port@host */
- memset(&addr, '\0', sizeof addr);
+ memset(&addr, '\0', sizeof(addr));
p = map->map_file;
colon = strchr(p, ':');
if (colon != NULL)
@@ -7213,7 +7477,7 @@ socket_map_open(map, mode)
long sff = SFF_SAFEDIRPATH|SFF_OPENASROOT|SFF_NOLINK|SFF_EXECOK;
at = colon;
- if (strlen(colon) >= sizeof addr.sunix.sun_path)
+ if (strlen(colon) >= sizeof(addr.sunix.sun_path))
{
syserr("socket map \"%s\": local socket name %s too long",
map->map_mname, colon);
@@ -7231,8 +7495,8 @@ socket_map_open(map, mode)
}
(void) sm_strlcpy(addr.sunix.sun_path, colon,
- sizeof addr.sunix.sun_path);
- addrlen = sizeof (struct sockaddr_un);
+ sizeof(addr.sunix.sun_path));
+ addrlen = sizeof(struct sockaddr_un);
}
else
# endif /* NETUNIX */
@@ -7305,7 +7569,7 @@ socket_map_open(map, mode)
}
# endif /* NETINET */
# if NETINET6
- (void) memset(&hid6, '\0', sizeof hid6);
+ (void) memset(&hid6, '\0', sizeof(hid6));
if (addr.sa.sa_family == AF_INET6 &&
anynet_pton(AF_INET6, &at[1],
&hid6.sin6_addr) == 1)
@@ -7347,7 +7611,7 @@ socket_map_open(map, mode)
memmove(&addr.sin.sin_addr,
hp->h_addr, INADDRSZ);
addr.sin.sin_port = port;
- addrlen = sizeof (struct sockaddr_in);
+ addrlen = sizeof(struct sockaddr_in);
addrno = 1;
break;
# endif /* NETINET */
@@ -7357,7 +7621,7 @@ socket_map_open(map, mode)
memmove(&addr.sin6.sin6_addr,
hp->h_addr, IN6ADDRSZ);
addr.sin6.sin6_port = port;
- addrlen = sizeof (struct sockaddr_in6);
+ addrlen = sizeof(struct sockaddr_in6);
addrno = 1;
break;
# endif /* NETINET6 */
@@ -7584,8 +7848,8 @@ socket_map_lookup(map, name, av, statp)
if (!bitset(MF_NOFOLDCASE, map->map_mflags))
{
nettolen = strlen(name);
- if (nettolen > sizeof keybuf - 1)
- nettolen = sizeof keybuf - 1;
+ if (nettolen > sizeof(keybuf) - 1)
+ nettolen = sizeof(keybuf) - 1;
memmove(keybuf, name, nettolen);
keybuf[nettolen] = '\0';
makelower(keybuf);
diff --git a/contrib/sendmail/src/map.h b/contrib/sendmail/src/map.h
new file mode 100644
index 000000000000..dda99992be2c
--- /dev/null
+++ b/contrib/sendmail/src/map.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2006 Sendmail, Inc. and its suppliers.
+ * All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set
+ * forth in the LICENSE file which can be found at the top level of
+ * the sendmail distribution.
+ *
+ * $Id: map.h,v 8.3 2006/12/19 19:49:51 ca Exp $
+ */
+
+#ifndef _MAP_H
+# define _MAP_H 1
+
+extern char *arith_map_lookup __P((MAP *, char *, char **, int *));
+
+extern char *bestmx_map_lookup __P((MAP *, char *, char **, int *));
+
+extern char *bogus_map_lookup __P((MAP *, char *, char **, int *));
+
+extern bool bt_map_open __P((MAP *, int));
+
+extern char *db_map_lookup __P((MAP *, char *, char **, int *));
+
+extern void db_map_store __P((MAP *, char *, char *));
+extern void db_map_close __P((MAP *));
+
+extern bool dequote_init __P((MAP *, char *));
+extern char *dequote_map __P((MAP *, char *, char **, int *));
+
+extern bool dns_map_open __P((MAP *, int));
+extern bool dns_map_parseargs __P((MAP *, char *));
+extern char *dns_map_lookup __P((MAP *, char *, char **, int *));
+
+extern bool dprintf_map_parseargs __P((MAP *, char *));
+extern char *dprintf_map_lookup __P((MAP *, char *, char **, int *));
+
+extern bool hash_map_open __P((MAP *, int));
+
+extern bool host_map_init __P((MAP *, char *));
+extern char *host_map_lookup __P((MAP *, char *, char **, int *));
+
+extern char *impl_map_lookup __P((MAP *, char *, char **, int *));
+extern void impl_map_store __P((MAP *, char *, char *));
+extern bool impl_map_open __P((MAP *, int));
+extern void impl_map_close __P((MAP *));
+
+extern char *macro_map_lookup __P((MAP *, char *, char **, int *));
+
+extern bool map_parseargs __P((MAP *, char *));
+
+extern bool nis_map_open __P((MAP *, int));
+extern char *nis_map_lookup __P((MAP *, char *, char **, int *));
+
+extern bool null_map_open __P((MAP *, int));
+extern void null_map_close __P((MAP *));
+extern char *null_map_lookup __P((MAP *, char *, char **, int *));
+extern void null_map_store __P((MAP *, char *, char *));
+
+extern char *prog_map_lookup __P((MAP *, char *, char **, int *));
+
+extern bool regex_map_init __P((MAP *, char *));
+extern char *regex_map_lookup __P((MAP *, char *, char **, int *));
+
+extern char *seq_map_lookup __P((MAP *, char *, char **, int *));
+extern void seq_map_store __P((MAP *, char *, char *));
+extern bool seq_map_parse __P((MAP *, char *));
+
+extern char *stab_map_lookup __P((MAP *, char *, char **, int *));
+extern void stab_map_store __P((MAP *, char *, char *));
+extern bool stab_map_open __P((MAP *, int));
+
+extern bool switch_map_open __P((MAP *, int));
+
+extern bool syslog_map_parseargs __P((MAP *, char *));
+extern char *syslog_map_lookup __P((MAP *, char *, char **, int *));
+
+extern bool text_map_open __P((MAP *, int));
+extern char *text_map_lookup __P((MAP *, char *, char **, int *));
+
+extern char *udb_map_lookup __P((MAP *, char *, char **, int *));
+
+extern bool user_map_open __P((MAP *, int));
+extern char *user_map_lookup __P((MAP *, char *, char **, int *));
+
+#endif /* ! _MAP_H */
diff --git a/contrib/sendmail/src/milter.c b/contrib/sendmail/src/milter.c
index 19fd59d54ef3..67d5eaefdeac 100644
--- a/contrib/sendmail/src/milter.c
+++ b/contrib/sendmail/src/milter.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999-2005 Sendmail, Inc. and its suppliers.
+ * Copyright (c) 1999-2006 Sendmail, Inc. and its suppliers.
* All rights reserved.
*
* By using this file, you agree to the terms and conditions set
@@ -10,9 +10,10 @@
#include
-SM_RCSID("@(#)$Id: milter.c,v 8.232 2005/08/05 21:49:04 ca Exp $")
+SM_RCSID("@(#)$Id: milter.c,v 8.267 2007/02/27 22:21:12 ca Exp $")
#if MILTER
+# include
# include
# include
@@ -22,9 +23,9 @@ SM_RCSID("@(#)$Id: milter.c,v 8.232 2005/08/05 21:49:04 ca Exp $")
# if NETINET || NETINET6
# include
-# if _FFR_MILTER_NAGLE
+# if MILTER_NO_NAGLE
# include
-# endif /* _FFR_MILTER_NAGLE */
+# endif /* MILTER_NO_NAGLE */
# endif /* NETINET || NETINET6 */
# include
@@ -33,6 +34,49 @@ static void milter_connect_timeout __P((int));
static void milter_error __P((struct milter *, ENVELOPE *));
static int milter_open __P((struct milter *, bool, ENVELOPE *));
static void milter_parse_timeouts __P((char *, struct milter *));
+static char *milter_sysread __P((struct milter *, char *, ssize_t, time_t,
+ ENVELOPE *, const char *));
+static char *milter_read __P((struct milter *, char *, ssize_t *, time_t,
+ ENVELOPE *, const char *));
+static char *milter_write __P((struct milter *, int, char *, ssize_t,
+ time_t, ENVELOPE *, const char *));
+static char *milter_send_command __P((struct milter *, int, void *,
+ ssize_t, ENVELOPE *, char *, const char *));
+static char *milter_command __P((int, void *, ssize_t, char **,
+ ENVELOPE *, char *, const char *, bool));
+static char *milter_body __P((struct milter *, ENVELOPE *, char *));
+static int milter_reopen_df __P((ENVELOPE *));
+static int milter_reset_df __P((ENVELOPE *));
+static void milter_quit_filter __P((struct milter *, ENVELOPE *));
+static void milter_abort_filter __P((struct milter *, ENVELOPE *));
+static void milter_send_macros __P((struct milter *, char **, int,
+ ENVELOPE *));
+static int milter_negotiate __P((struct milter *, ENVELOPE *));
+static void milter_per_connection_check __P((ENVELOPE *));
+static char *milter_headers __P((struct milter *, ENVELOPE *, char *));
+static void milter_addheader __P((struct milter *, char *, ssize_t,
+ ENVELOPE *));
+static void milter_insheader __P((struct milter *, char *, ssize_t,
+ ENVELOPE *));
+static void milter_changeheader __P((struct milter *, char *, ssize_t,
+ ENVELOPE *));
+static void milter_chgfrom __P((char *, ssize_t, ENVELOPE *));
+static void milter_addrcpt __P((char *, ssize_t, ENVELOPE *));
+static void milter_addrcpt_par __P((char *, ssize_t, ENVELOPE *));
+static void milter_delrcpt __P((char *, ssize_t, ENVELOPE *));
+static int milter_replbody __P((char *, ssize_t, bool, ENVELOPE *));
+static int milter_set_macros __P((char *, char **, char *, int));
+
+
+/* milter states */
+# define SMFS_CLOSED 'C' /* closed for all further actions */
+# define SMFS_OPEN 'O' /* connected to remote milter filter */
+# define SMFS_INMSG 'M' /* currently servicing a message */
+# define SMFS_DONE 'D' /* done with current message */
+# define SMFS_CLOSABLE 'Q' /* done with current connection */
+# define SMFS_ERROR 'E' /* error state */
+# define SMFS_READY 'R' /* ready for action */
+# define SMFS_SKIP 'S' /* skip body */
static char *MilterConnectMacros[MAXFILTERMACROS + 1];
static char *MilterHeloMacros[MAXFILTERMACROS + 1];
@@ -40,6 +84,7 @@ static char *MilterEnvFromMacros[MAXFILTERMACROS + 1];
static char *MilterEnvRcptMacros[MAXFILTERMACROS + 1];
static char *MilterDataMacros[MAXFILTERMACROS + 1];
static char *MilterEOMMacros[MAXFILTERMACROS + 1];
+static char *MilterEOHMacros[MAXFILTERMACROS + 1];
static size_t MilterMaxDataSize = MILTER_MAX_DATA_SIZE;
# define MILTER_CHECK_DONE_MSG() \
@@ -146,7 +191,7 @@ static size_t MilterMaxDataSize = MILTER_MAX_DATA_SIZE;
** Assumes 'm' is a milter structure for the current socket.
*/
-# define MILTER_TIMEOUT(routine, secs, write, started) \
+# define MILTER_TIMEOUT(routine, secs, write, started, function) \
{ \
int ret; \
int save_errno; \
@@ -184,14 +229,14 @@ static size_t MilterMaxDataSize = MILTER_MAX_DATA_SIZE;
{ \
case 0: \
if (tTd(64, 5)) \
- sm_dprintf("milter_%s(%s): timeout\n", (routine), \
- m->mf_name); \
+ sm_dprintf("milter_%s(%s): timeout, where=%s\n", \
+ (routine), m->mf_name, (function)); \
if (MilterLogLevel > 0) \
sm_syslog(LOG_ERR, e->e_id, \
- "Milter (%s): %s %s %s %s", \
- m->mf_name, "timeout", \
+ "Milter (%s): timeout %s data %s, where=%s", \
+ m->mf_name, \
started ? "during" : "before", \
- "data", (routine)); \
+ (routine), (function)); \
milter_error(m, e); \
return NULL; \
\
@@ -246,12 +291,13 @@ static size_t MilterMaxDataSize = MILTER_MAX_DATA_SIZE;
*/
static char *
-milter_sysread(m, buf, sz, to, e)
+milter_sysread(m, buf, sz, to, e, where)
struct milter *m;
char *buf;
ssize_t sz;
time_t to;
ENVELOPE *e;
+ const char *where;
{
time_t readstart = 0;
ssize_t len, curl;
@@ -272,22 +318,22 @@ milter_sysread(m, buf, sz, to, e)
if (now - readstart >= to)
{
if (tTd(64, 5))
- sm_dprintf("milter_read (%s): %s %s %s",
- m->mf_name, "timeout",
+ sm_dprintf("milter_sys_read (%s): timeout %s data read in %s",
+ m->mf_name,
started ? "during" : "before",
- "data read");
+ where);
if (MilterLogLevel > 0)
sm_syslog(LOG_ERR, e->e_id,
- "Milter (%s): %s %s %s",
- m->mf_name, "timeout",
+ "Milter (%s): timeout %s data read in %s",
+ m->mf_name,
started ? "during" : "before",
- "data read");
+ where);
milter_error(m, e);
return NULL;
}
to -= now - readstart;
readstart = now;
- MILTER_TIMEOUT("read", to, false, started);
+ MILTER_TIMEOUT("read", to, false, started, where);
}
len = read(m->mf_sock, buf + curl, sz - curl);
@@ -297,7 +343,7 @@ milter_sysread(m, buf, sz, to, e)
int save_errno = errno;
if (tTd(64, 5))
- sm_dprintf("milter_read(%s): read returned %ld: %s\n",
+ sm_dprintf("milter_sys_read(%s): read returned %ld: %s\n",
m->mf_name, (long) len,
sm_errstring(save_errno));
if (MilterLogLevel > 0)
@@ -319,11 +365,11 @@ milter_sysread(m, buf, sz, to, e)
if (curl != sz)
{
if (tTd(64, 5))
- sm_dprintf("milter_read(%s): cmd read returned %ld, expecting %ld\n",
+ sm_dprintf("milter_sys_read(%s): cmd read returned %ld, expecting %ld\n",
m->mf_name, (long) curl, (long) sz);
if (MilterLogLevel > 0)
sm_syslog(LOG_ERR, e->e_id,
- "milter_read(%s): cmd read returned %ld, expecting %ld",
+ "milter_sys_read(%s): cmd read returned %ld, expecting %ld",
m->mf_name, (long) curl, (long) sz);
milter_error(m, e);
return NULL;
@@ -332,21 +378,20 @@ milter_sysread(m, buf, sz, to, e)
}
static char *
-milter_read(m, cmd, rlen, to, e)
+milter_read(m, cmd, rlen, to, e, where)
struct milter *m;
char *cmd;
ssize_t *rlen;
time_t to;
ENVELOPE *e;
+ const char *where;
{
time_t readstart = 0;
ssize_t expl;
mi_int32 i;
-# if _FFR_MILTER_NAGLE
-# ifdef TCP_CORK
+# if MILTER_NO_NAGLE && defined(TCP_CORK)
int cork = 0;
-# endif
-# endif /* _FFR_MILTER_NAGLE */
+# endif /* MILTER_NO_NAGLE && defined(TCP_CORK) */
char *buf;
char data[MILTER_LEN_BYTES + 1];
@@ -354,8 +399,8 @@ milter_read(m, cmd, rlen, to, e)
{
if (MilterLogLevel > 0)
sm_syslog(LOG_ERR, e->e_id,
- "milter_read(%s): socket closed",
- m->mf_name);
+ "milter_read(%s): socket closed, where=%s",
+ m->mf_name, where);
milter_error(m, e);
return NULL;
}
@@ -366,23 +411,19 @@ milter_read(m, cmd, rlen, to, e)
if (to > 0)
readstart = curtime();
-# if _FFR_MILTER_NAGLE
-# ifdef TCP_CORK
+# if MILTER_NO_NAGLE && defined(TCP_CORK)
setsockopt(m->mf_sock, IPPROTO_TCP, TCP_CORK, (char *)&cork,
sizeof(cork));
-# endif
-# endif /* _FFR_MILTER_NAGLE */
+# endif /* MILTER_NO_NAGLE && defined(TCP_CORK) */
- if (milter_sysread(m, data, sizeof data, to, e) == NULL)
+ if (milter_sysread(m, data, sizeof(data), to, e, where) == NULL)
return NULL;
-# if _FFR_MILTER_NAGLE
-# ifdef TCP_CORK
+# if MILTER_NO_NAGLE && defined(TCP_CORK)
cork = 1;
setsockopt(m->mf_sock, IPPROTO_TCP, TCP_CORK, (char *)&cork,
sizeof(cork));
-# endif
-# endif /* _FFR_MILTER_NAGLE */
+# endif /* MILTER_NO_NAGLE && defined(TCP_CORK) */
/* reset timeout */
if (to > 0)
@@ -393,12 +434,12 @@ milter_read(m, cmd, rlen, to, e)
if (now - readstart >= to)
{
if (tTd(64, 5))
- sm_dprintf("milter_read(%s): timeout before data read\n",
- m->mf_name);
+ sm_dprintf("milter_read(%s): timeout before data read, where=%s\n",
+ m->mf_name, where);
if (MilterLogLevel > 0)
sm_syslog(LOG_ERR, e->e_id,
- "Milter read(%s): timeout before data read",
- m->mf_name);
+ "Milter read(%s): timeout before data read, where=%s",
+ m->mf_name, where);
milter_error(m, e);
return NULL;
}
@@ -417,12 +458,12 @@ milter_read(m, cmd, rlen, to, e)
if (expl < 0)
{
if (tTd(64, 5))
- sm_dprintf("milter_read(%s): read size %ld out of range\n",
- m->mf_name, (long) expl);
+ sm_dprintf("milter_read(%s): read size %ld out of range, where=%s\n",
+ m->mf_name, (long) expl, where);
if (MilterLogLevel > 0)
sm_syslog(LOG_ERR, e->e_id,
- "milter_read(%s): read size %ld out of range",
- m->mf_name, (long) expl);
+ "milter_read(%s): read size %ld out of range, where=%s",
+ m->mf_name, (long) expl, where);
milter_error(m, e);
return NULL;
}
@@ -432,7 +473,7 @@ milter_read(m, cmd, rlen, to, e)
buf = (char *) xalloc(expl);
- if (milter_sysread(m, buf, expl, to, e) == NULL)
+ if (milter_sysread(m, buf, expl, to, e, where) == NULL)
{
sm_free(buf); /* XXX */
return NULL;
@@ -463,18 +504,20 @@ milter_read(m, cmd, rlen, to, e)
*/
static char *
-milter_write(m, cmd, buf, len, to, e)
+milter_write(m, cmd, buf, len, to, e, where)
struct milter *m;
- char cmd;
+ int cmd;
char *buf;
ssize_t len;
time_t to;
ENVELOPE *e;
+ const char *where;
{
time_t writestart = (time_t) 0;
ssize_t sl, i;
int num_vectors;
mi_int32 nl;
+ char command = (char) cmd;
char data[MILTER_LEN_BYTES + 1];
bool started = false;
struct iovec vector[2];
@@ -509,11 +552,11 @@ milter_write(m, cmd, buf, len, to, e)
if (tTd(64, 20))
sm_dprintf("milter_write(%s): cmd %c, len %ld\n",
- m->mf_name, cmd, (long) len);
+ m->mf_name, command, (long) len);
- nl = htonl(len + 1); /* add 1 for the cmd char */
+ nl = htonl(len + 1); /* add 1 for the command char */
(void) memcpy(data, (char *) &nl, MILTER_LEN_BYTES);
- data[MILTER_LEN_BYTES] = cmd;
+ data[MILTER_LEN_BYTES] = command;
sl = MILTER_LEN_BYTES + 1;
/* set up the vector for the size / command */
@@ -552,7 +595,7 @@ milter_write(m, cmd, buf, len, to, e)
if (to > 0)
{
writestart = curtime();
- MILTER_TIMEOUT("write", to, true, started);
+ MILTER_TIMEOUT("write", to, true, started, where);
}
/* write the vector(s) */
@@ -563,12 +606,12 @@ milter_write(m, cmd, buf, len, to, e)
if (tTd(64, 5))
sm_dprintf("milter_write(%s): write(%c) returned %ld, expected %ld: %s\n",
- m->mf_name, cmd, (long) i, (long) sl,
+ m->mf_name, command, (long) i, (long) sl,
sm_errstring(save_errno));
if (MilterLogLevel > 0)
sm_syslog(LOG_ERR, e->e_id,
"Milter (%s): write(%c) returned %ld, expected %ld: %s",
- m->mf_name, cmd, (long) i, (long) sl,
+ m->mf_name, command, (long) i, (long) sl,
sm_errstring(save_errno));
milter_error(m, e);
return NULL;
@@ -629,7 +672,7 @@ milter_open(m, parseonly, e)
}
/* protocol:filename or protocol:port@host */
- memset(&addr, '\0', sizeof addr);
+ memset(&addr, '\0', sizeof(addr));
p = m->mf_conn;
colon = strchr(p, ':');
if (colon != NULL)
@@ -709,7 +752,7 @@ milter_open(m, parseonly, e)
long sff = SFF_SAFEDIRPATH|SFF_OPENASROOT|SFF_NOLINK|SFF_EXECOK;
at = colon;
- if (strlen(colon) >= sizeof addr.sunix.sun_path)
+ if (strlen(colon) >= sizeof(addr.sunix.sun_path))
{
if (tTd(64, 5))
sm_dprintf("X%s: local socket name %s too long\n",
@@ -762,8 +805,8 @@ milter_open(m, parseonly, e)
}
(void) sm_strlcpy(addr.sunix.sun_path, colon,
- sizeof addr.sunix.sun_path);
- addrlen = sizeof (struct sockaddr_un);
+ sizeof(addr.sunix.sun_path));
+ addrlen = sizeof(struct sockaddr_un);
}
else
# endif /* NETUNIX */
@@ -815,7 +858,7 @@ milter_open(m, parseonly, e)
milter_error(m, e);
return -1;
# else /* NO_GETSERVBYNAME */
- register struct servent *sp;
+ struct servent *sp;
sp = getservbyname(colon, "tcp");
if (sp == NULL)
@@ -865,7 +908,7 @@ milter_open(m, parseonly, e)
}
# endif /* NETINET */
# if NETINET6
- (void) memset(&hid6, '\0', sizeof hid6);
+ (void) memset(&hid6, '\0', sizeof(hid6));
if (addr.sa.sa_family == AF_INET6 &&
anynet_pton(AF_INET6, &at[1],
&hid6.sin6_addr) == 1)
@@ -936,7 +979,7 @@ milter_open(m, parseonly, e)
memmove(&addr.sin.sin_addr,
hp->h_addr, INADDRSZ);
addr.sin.sin_port = port;
- addrlen = sizeof (struct sockaddr_in);
+ addrlen = sizeof(struct sockaddr_in);
addrno = 1;
break;
# endif /* NETINET */
@@ -946,7 +989,7 @@ milter_open(m, parseonly, e)
memmove(&addr.sin6.sin6_addr,
hp->h_addr, IN6ADDRSZ);
addr.sin6.sin6_port = port;
- addrlen = sizeof (struct sockaddr_in6);
+ addrlen = sizeof(struct sockaddr_in6);
addrno = 1;
break;
# endif /* NETINET6 */
@@ -1134,16 +1177,14 @@ milter_open(m, parseonly, e)
hp = NULL;
}
# endif /* NETINET6 */
-# if _FFR_MILTER_NAGLE
-# ifndef TCP_CORK
+# if MILTER_NO_NAGLE && !defined(TCP_CORK)
{
int nodelay = 1;
setsockopt(m->mf_sock, IPPROTO_TCP, TCP_NODELAY,
(char *)&nodelay, sizeof(nodelay));
}
-# endif /* TCP_CORK */
-# endif /* _FFR_MILTER_NAGLE */
+# endif /* MILTER_NO_NAGLE && !defined(TCP_CORK) */
return sock;
}
@@ -1160,6 +1201,7 @@ milter_connect_timeout(ignore)
errno = ETIMEDOUT;
longjmp(MilterConnectTimeout, 1);
}
+
/*
** MILTER_SETUP -- setup structure for a mail filter
**
@@ -1175,8 +1217,8 @@ milter_setup(line)
char *line;
{
char fcode;
- register char *p;
- register struct milter *m;
+ char *p;
+ struct milter *m;
STAB *s;
/* collect the filter name */
@@ -1191,8 +1233,8 @@ milter_setup(line)
syserr("name required for mail filter");
return;
}
- m = (struct milter *) xalloc(sizeof *m);
- memset((char *) m, '\0', sizeof *m);
+ m = (struct milter *) xalloc(sizeof(*m));
+ memset((char *) m, '\0', sizeof(*m));
m->mf_name = newstr(line);
m->mf_state = SMFS_READY;
m->mf_sock = -1;
@@ -1200,6 +1242,11 @@ milter_setup(line)
m->mf_timeout[SMFTO_WRITE] = (time_t) 10;
m->mf_timeout[SMFTO_READ] = (time_t) 10;
m->mf_timeout[SMFTO_EOM] = (time_t) 300;
+#if _FFR_MILTER_CHECK
+ m->mf_mta_prot_version = SMFI_PROT_VERSION;
+ m->mf_mta_prot_flags = SMFI_CURR_PROT;
+ m->mf_mta_actions = SMFI_CURR_ACTS;
+#endif /* _FFR_MILTER_CHECK */
/* now scan through and assign info from the fields */
while (*p != '\0')
@@ -1247,6 +1294,18 @@ milter_setup(line)
milter_parse_timeouts(p, m);
break;
+#if _FFR_MILTER_CHECK
+ case 'a':
+ m->mf_mta_actions = strtoul(p, NULL, 0);
+ break;
+ case 'f':
+ m->mf_mta_prot_flags = strtoul(p, NULL, 0);
+ break;
+ case 'v':
+ m->mf_mta_prot_version = strtoul(p, NULL, 0);
+ break;
+#endif /* _FFR_MILTER_CHECK */
+
default:
syserr("X%s: unknown filter equate %c=",
m->mf_name, fcode);
@@ -1265,6 +1324,7 @@ milter_setup(line)
else
s->s_milter = m;
}
+
/*
** MILTER_CONFIG -- parse option list into an array and check config
**
@@ -1286,7 +1346,7 @@ milter_config(spec, list, max)
int max;
{
int numitems = 0;
- register char *p;
+ char *p;
/* leave one for the NULL signifying the end of the list */
max--;
@@ -1327,6 +1387,7 @@ milter_config(spec, list, max)
if (MilterLogLevel == -1)
MilterLogLevel = LogLevel;
}
+
/*
** MILTER_PARSE_TIMEOUTS -- parse timeout list
**
@@ -1347,7 +1408,7 @@ milter_parse_timeouts(spec, m)
{
char fcode;
int tcode;
- register char *p;
+ char *p;
p = spec;
@@ -1414,6 +1475,63 @@ milter_parse_timeouts(spec, m)
p = delimptr;
}
}
+
+/*
+** MILTER_SET_MACROS -- set milter macros
+**
+** Parameters:
+** name -- name of milter.
+** macros -- where to store macros.
+** val -- the value of the option.
+** nummac -- current number of macros
+**
+** Returns:
+** new number of macros
+*/
+
+static int
+milter_set_macros(name, macros, val, nummac)
+ char *name;
+ char **macros;
+ char *val;
+ int nummac;
+{
+ char *p;
+
+ p = newstr(val);
+ while (*p != '\0')
+ {
+ char *macro;
+
+ /* Skip leading commas, spaces */
+ while (*p != '\0' &&
+ (*p == ',' || (isascii(*p) && isspace(*p))))
+ p++;
+
+ if (*p == '\0')
+ break;
+
+ /* Find end of macro */
+ macro = p;
+ while (*p != '\0' && *p != ',' &&
+ isascii(*p) && !isspace(*p))
+ p++;
+ if (*p != '\0')
+ *p++ = '\0';
+
+ if (nummac >= MAXFILTERMACROS)
+ {
+ syserr("milter_set_option: too many macros in Milter.%s (max %d)",
+ name, MAXFILTERMACROS);
+ macros[nummac] = NULL;
+ return -1;
+ }
+ macros[nummac++] = macro;
+ }
+ macros[nummac] = NULL;
+ return nummac;
+}
+
/*
** MILTER_SET_OPTION -- set an individual milter option
**
@@ -1436,25 +1554,28 @@ static struct milteropt
unsigned char mo_code; /* code for option */
} MilterOptTab[] =
{
-# define MO_MACROS_CONNECT 0x01
+# define MO_MACROS_CONNECT SMFIM_CONNECT
{ "macros.connect", MO_MACROS_CONNECT },
-# define MO_MACROS_HELO 0x02
+# define MO_MACROS_HELO SMFIM_HELO
{ "macros.helo", MO_MACROS_HELO },
-# define MO_MACROS_ENVFROM 0x03
+# define MO_MACROS_ENVFROM SMFIM_ENVFROM
{ "macros.envfrom", MO_MACROS_ENVFROM },
-# define MO_MACROS_ENVRCPT 0x04
+# define MO_MACROS_ENVRCPT SMFIM_ENVRCPT
{ "macros.envrcpt", MO_MACROS_ENVRCPT },
-# define MO_MACROS_DATA 0x05
+# define MO_MACROS_DATA SMFIM_DATA
{ "macros.data", MO_MACROS_DATA },
-# define MO_MACROS_EOM 0x06
+# define MO_MACROS_EOM SMFIM_EOM
{ "macros.eom", MO_MACROS_EOM },
+# define MO_MACROS_EOH SMFIM_EOH
+ { "macros.eoh", MO_MACROS_EOH },
+
# define MO_LOGLEVEL 0x07
{ "loglevel", MO_LOGLEVEL },
# if _FFR_MAXDATASIZE
-# define MO_MAXDATASIZE 0x08
+# define MO_MAXDATASIZE 0x08
{ "maxdatasize", MO_MAXDATASIZE },
# endif /* _FFR_MAXDATASIZE */
- { NULL, 0 },
+ { NULL, (unsigned char)-1 },
};
void
@@ -1463,11 +1584,11 @@ milter_set_option(name, val, sticky)
char *val;
bool sticky;
{
- int nummac = 0;
- register struct milteropt *mo;
- char *p;
+ int nummac, r;
+ struct milteropt *mo;
char **macros = NULL;
+ nummac = 0;
if (tTd(37, 2) || tTd(64, 5))
sm_dprintf("milter_set_option(%s = %s)", name, val);
@@ -1535,6 +1656,11 @@ milter_set_option(name, val, sticky)
macros = MilterEnvRcptMacros;
/* FALLTHROUGH */
+ case MO_MACROS_EOH:
+ if (macros == NULL)
+ macros = MilterEOHMacros;
+ /* FALLTHROUGH */
+
case MO_MACROS_EOM:
if (macros == NULL)
macros = MilterEOMMacros;
@@ -1544,37 +1670,9 @@ milter_set_option(name, val, sticky)
if (macros == NULL)
macros = MilterDataMacros;
- p = newstr(val);
- while (*p != '\0')
- {
- char *macro;
-
- /* Skip leading commas, spaces */
- while (*p != '\0' &&
- (*p == ',' || (isascii(*p) && isspace(*p))))
- p++;
-
- if (*p == '\0')
- break;
-
- /* Find end of macro */
- macro = p;
- while (*p != '\0' && *p != ',' &&
- isascii(*p) && !isspace(*p))
- p++;
- if (*p != '\0')
- *p++ = '\0';
-
- if (nummac >= MAXFILTERMACROS)
- {
- syserr("milter_set_option: too many macros in Milter.%s (max %d)",
- name, MAXFILTERMACROS);
- macros[nummac] = NULL;
- break;
- }
- macros[nummac++] = macro;
- }
- macros[nummac] = NULL;
+ r = milter_set_macros(name, macros, val, nummac);
+ if (r >= 0)
+ nummac = r;
break;
default:
@@ -1584,6 +1682,7 @@ milter_set_option(name, val, sticky)
if (sticky)
setbitn(mo->mo_code, StickyMilterOpt);
}
+
/*
** MILTER_REOPEN_DF -- open & truncate the data file (for replbody)
**
@@ -1600,7 +1699,7 @@ milter_reopen_df(e)
{
char dfname[MAXPATHLEN];
- (void) sm_strlcpy(dfname, queuename(e, DATAFL_LETTER), sizeof dfname);
+ (void) sm_strlcpy(dfname, queuename(e, DATAFL_LETTER), sizeof(dfname));
/*
** In SuperSafe == SAFE_REALLY mode, e->e_dfp is a read-only FP so
@@ -1638,6 +1737,7 @@ milter_reopen_df(e)
}
return 0;
}
+
/*
** MILTER_RESET_DF -- re-open read-only the data file (for replbody)
**
@@ -1655,7 +1755,7 @@ milter_reset_df(e)
int afd;
char dfname[MAXPATHLEN];
- (void) sm_strlcpy(dfname, queuename(e, DATAFL_LETTER), sizeof dfname);
+ (void) sm_strlcpy(dfname, queuename(e, DATAFL_LETTER), sizeof(dfname));
if (sm_io_flush(e->e_dfp, SM_TIME_DEFAULT) != 0 ||
sm_io_error(e->e_dfp))
@@ -1689,6 +1789,7 @@ milter_reset_df(e)
e->e_flags |= EF_HAS_DF;
return 0;
}
+
/*
** MILTER_CAN_DELRCPTS -- can any milter filters delete recipients?
**
@@ -1723,6 +1824,7 @@ milter_can_delrcpts()
return can;
}
+
/*
** MILTER_QUIT_FILTER -- close down a single filter
**
@@ -1759,7 +1861,7 @@ milter_quit_filter(m, e)
}
(void) milter_write(m, SMFIC_QUIT, (char *) NULL, 0,
- m->mf_timeout[SMFTO_WRITE], e);
+ m->mf_timeout[SMFTO_WRITE], e, "quit_filter");
if (m->mf_sock >= 0)
{
(void) close(m->mf_sock);
@@ -1768,6 +1870,7 @@ milter_quit_filter(m, e)
if (m->mf_state != SMFS_ERROR)
m->mf_state = SMFS_CLOSED;
}
+
/*
** MILTER_ABORT_FILTER -- tell filter to abort current message
**
@@ -1795,10 +1898,11 @@ milter_abort_filter(m, e)
return;
(void) milter_write(m, SMFIC_ABORT, (char *) NULL, 0,
- m->mf_timeout[SMFTO_WRITE], e);
+ m->mf_timeout[SMFTO_WRITE], e, "abort_filter");
if (m->mf_state != SMFS_ERROR)
m->mf_state = SMFS_DONE;
}
+
/*
** MILTER_SEND_MACROS -- provide macros to the filters
**
@@ -1816,11 +1920,12 @@ static void
milter_send_macros(m, macros, cmd, e)
struct milter *m;
char **macros;
- char cmd;
+ int cmd;
ENVELOPE *e;
{
int i;
int mid;
+ char command = (char) cmd;
char *v;
char *buf, *bp;
char exp[MAXLINE];
@@ -1849,7 +1954,7 @@ milter_send_macros(m, macros, cmd, e)
buf = (char *) xalloc(s);
bp = buf;
- *bp++ = cmd;
+ *bp++ = command;
for (i = 0; macros[i] != NULL; i++)
{
mid = macid(macros[i]);
@@ -1862,7 +1967,7 @@ milter_send_macros(m, macros, cmd, e)
if (tTd(64, 10))
sm_dprintf("milter_send_macros(%s, %c): %s=%s\n",
- m->mf_name, cmd, macros[i], exp);
+ m->mf_name, command, macros[i], exp);
(void) sm_strlcpy(bp, macros[i], s - (bp - buf));
bp += strlen(bp) + 1;
@@ -1870,7 +1975,7 @@ milter_send_macros(m, macros, cmd, e)
bp += strlen(bp) + 1;
}
(void) milter_write(m, SMFIC_MACRO, buf, s,
- m->mf_timeout[SMFTO_WRITE], e);
+ m->mf_timeout[SMFTO_WRITE], e, "send_macros");
sm_free(buf);
}
@@ -1879,7 +1984,7 @@ milter_send_macros(m, macros, cmd, e)
**
** Parameters:
** m -- current milter filter
-** command -- command to send.
+** cmd -- command to send.
** data -- optional command data.
** sz -- length of buf.
** e -- current envelope (for e->e_id).
@@ -1890,20 +1995,20 @@ milter_send_macros(m, macros, cmd, e)
*/
static char *
-milter_send_command(m, command, data, sz, e, state)
+milter_send_command(m, cmd, data, sz, e, state, where)
struct milter *m;
- char command;
+ int cmd;
void *data;
ssize_t sz;
ENVELOPE *e;
char *state;
+ const char *where;
{
char rcmd;
ssize_t rlen;
unsigned long skipflag;
-#if _FFR_MILTER_NOHDR_RESP
unsigned long norespflag = 0;
-#endif /* _FFR_MILTER_NOHDR_RESP */
+ char command = (char) cmd;
char *action;
char *defresponse;
char *response;
@@ -1917,64 +2022,66 @@ milter_send_command(m, command, data, sz, e, state)
{
case SMFIC_CONNECT:
skipflag = SMFIP_NOCONNECT;
+ norespflag = SMFIP_NR_CONN;
action = "connect";
defresponse = "554 Command rejected";
break;
case SMFIC_HELO:
skipflag = SMFIP_NOHELO;
+ norespflag = SMFIP_NR_HELO;
action = "helo";
defresponse = "550 Command rejected";
break;
case SMFIC_MAIL:
skipflag = SMFIP_NOMAIL;
+ norespflag = SMFIP_NR_MAIL;
action = "mail";
defresponse = "550 5.7.1 Command rejected";
break;
case SMFIC_RCPT:
skipflag = SMFIP_NORCPT;
+ norespflag = SMFIP_NR_RCPT;
action = "rcpt";
defresponse = "550 5.7.1 Command rejected";
break;
case SMFIC_HEADER:
skipflag = SMFIP_NOHDRS;
-#if _FFR_MILTER_NOHDR_RESP
- norespflag = SMFIP_NOHREPL;
-#endif /* _FFR_MILTER_NOHDR_RESP */
+ norespflag = SMFIP_NR_HDR;
action = "header";
defresponse = "550 5.7.1 Command rejected";
break;
case SMFIC_BODY:
skipflag = SMFIP_NOBODY;
+ norespflag = SMFIP_NR_BODY;
action = "body";
defresponse = "554 5.7.1 Command rejected";
break;
case SMFIC_EOH:
skipflag = SMFIP_NOEOH;
+ norespflag = SMFIP_NR_EOH;
action = "eoh";
defresponse = "550 5.7.1 Command rejected";
break;
-#if SMFI_VERSION > 2
case SMFIC_UNKNOWN:
skipflag = SMFIP_NOUNKNOWN;
+ norespflag = SMFIP_NR_UNKN;
action = "unknown";
defresponse = "550 5.7.1 Command rejected";
break;
-#endif /* SMFI_VERSION > 2 */
-#if SMFI_VERSION > 3
case SMFIC_DATA:
skipflag = SMFIP_NODATA;
+ norespflag = SMFIP_NR_DATA;
action = "data";
defresponse = "550 5.7.1 Command rejected";
break;
-#endif /* SMFI_VERSION > 3 */
case SMFIC_BODYEOB:
case SMFIC_OPTNEG:
@@ -1991,29 +2098,30 @@ milter_send_command(m, command, data, sz, e, state)
break;
}
+ if (tTd(64, 10))
+ sm_dprintf("milter_send_command(%s): skip=%lx, pflags=%x\n",
+ m->mf_name, skipflag, m->mf_pflags);
+
/* check if filter wants this command */
- if (skipflag != 0 &&
- bitset(skipflag, m->mf_pflags))
+ if (skipflag != 0 && bitset(skipflag, m->mf_pflags))
return NULL;
/* send the command to the filter */
(void) milter_write(m, command, data, sz,
- m->mf_timeout[SMFTO_WRITE], e);
+ m->mf_timeout[SMFTO_WRITE], e, where);
if (m->mf_state == SMFS_ERROR)
{
MILTER_CHECK_ERROR(false, return NULL);
return NULL;
}
-#if _FFR_MILTER_NOHDR_RESP
/* check if filter sends response to this command */
if (norespflag != 0 && bitset(norespflag, m->mf_pflags))
return NULL;
-#endif /* _FFR_MILTER_NOHDR_RESP */
/* get the response from the filter */
response = milter_read(m, &rcmd, &rlen,
- m->mf_timeout[SMFTO_READ], e);
+ m->mf_timeout[SMFTO_READ], e, where);
if (m->mf_state == SMFS_ERROR)
{
MILTER_CHECK_ERROR(false, return NULL);
@@ -2029,28 +2137,32 @@ milter_send_command(m, command, data, sz, e, state)
case SMFIR_REPLYCODE:
MILTER_CHECK_REPLYCODE(defresponse);
if (MilterLogLevel > 10)
- sm_syslog(LOG_INFO, e->e_id, "milter=%s, action=%s, reject=%s",
+ sm_syslog(LOG_INFO, e->e_id,
+ "milter=%s, action=%s, reject=%s",
m->mf_name, action, response);
*state = rcmd;
break;
case SMFIR_REJECT:
if (MilterLogLevel > 10)
- sm_syslog(LOG_INFO, e->e_id, "milter=%s, action=%s, reject",
+ sm_syslog(LOG_INFO, e->e_id,
+ "milter=%s, action=%s, reject",
m->mf_name, action);
*state = rcmd;
break;
case SMFIR_DISCARD:
if (MilterLogLevel > 10)
- sm_syslog(LOG_INFO, e->e_id, "milter=%s, action=%s, discard",
+ sm_syslog(LOG_INFO, e->e_id,
+ "milter=%s, action=%s, discard",
m->mf_name, action);
*state = rcmd;
break;
case SMFIR_TEMPFAIL:
if (MilterLogLevel > 10)
- sm_syslog(LOG_INFO, e->e_id, "milter=%s, action=%s, tempfail",
+ sm_syslog(LOG_INFO, e->e_id,
+ "milter=%s, action=%s, tempfail",
m->mf_name, action);
*state = rcmd;
break;
@@ -2063,7 +2175,8 @@ milter_send_command(m, command, data, sz, e, state)
else
m->mf_state = SMFS_DONE;
if (MilterLogLevel > 10)
- sm_syslog(LOG_INFO, e->e_id, "milter=%s, action=%s, accepted",
+ sm_syslog(LOG_INFO, e->e_id,
+ "milter=%s, action=%s, accepted",
m->mf_name, action);
break;
@@ -2072,10 +2185,19 @@ milter_send_command(m, command, data, sz, e, state)
if (command == SMFIC_MAIL)
m->mf_state = SMFS_INMSG;
if (MilterLogLevel > 12)
- sm_syslog(LOG_INFO, e->e_id, "milter=%s, action=%s, continue",
+ sm_syslog(LOG_INFO, e->e_id,
+ "milter=%s, action=%s, continue",
m->mf_name, action);
break;
+ case SMFIR_SKIP:
+ if (MilterLogLevel > 12)
+ sm_syslog(LOG_INFO, e->e_id,
+ "milter=%s, action=%s, skip",
+ m->mf_name, action);
+ m->mf_state = SMFS_SKIP;
+ break;
+
default:
/* Invalid response to command */
if (MilterLogLevel > 0)
@@ -2086,8 +2208,7 @@ milter_send_command(m, command, data, sz, e, state)
break;
}
- if (*state != SMFIR_REPLYCODE &&
- response != NULL)
+ if (*state != SMFIR_REPLYCODE && response != NULL)
{
sm_free(response); /* XXX */
response = NULL;
@@ -2099,33 +2220,38 @@ milter_send_command(m, command, data, sz, e, state)
** MILTER_COMMAND -- send a command and return the response for each filter
**
** Parameters:
-** command -- command to send.
+** cmd -- command to send.
** data -- optional command data.
** sz -- length of buf.
** macros -- macros to send for filter smfi_getsymval().
** e -- current envelope (for macro access).
** state -- return state word.
+** where -- description of calling function (logging).
+** cmd_error -- did the SMTP command cause an error?
**
** Returns:
** response string (may be NULL)
*/
static char *
-milter_command(command, data, sz, macros, e, state)
- char command;
+milter_command(cmd, data, sz, macros, e, state, where, cmd_error)
+ int cmd;
void *data;
ssize_t sz;
char **macros;
ENVELOPE *e;
char *state;
+ const char *where;
+ bool cmd_error;
{
int i;
+ char command = (char) cmd;
char *response = NULL;
time_t tn = 0;
if (tTd(64, 10))
sm_dprintf("milter_command: cmd %c len %ld\n",
- (char) command, (long) sz);
+ command, (long) sz);
*state = SMFIR_CONTINUE;
for (i = 0; InputFilters[i] != NULL; i++)
@@ -2158,7 +2284,22 @@ milter_command(command, data, sz, macros, e, state)
if (MilterLogLevel > 21)
tn = curtime();
- response = milter_send_command(m, command, data, sz, e, state);
+ /*
+ ** send the command if
+ ** there is no error
+ ** or it's RCPT and the client asked for it:
+ ** !cmd_error ||
+ ** where == "rcpt" && m->mf_pflags & SMFIP_RCPT_REJ != 0
+ ** negate that condition and use continue
+ */
+
+ if (cmd_error &&
+ (strcmp(where, "rcpt") != 0 ||
+ (m->mf_pflags & SMFIP_RCPT_REJ) == 0))
+ continue;
+
+ response = milter_send_command(m, command, data, sz, e, state,
+ where);
if (MilterLogLevel > 21)
{
@@ -2173,6 +2314,92 @@ milter_command(command, data, sz, macros, e, state)
}
return response;
}
+
+static int milter_getsymlist __P((struct milter *, char *, int, int));
+
+static int
+milter_getsymlist(m, buf, rlen, offset)
+ struct milter *m;
+ char *buf;
+ int rlen;
+ int offset;
+{
+ int i, r, nummac;
+ mi_int32 v;
+
+ SM_ASSERT(m != NULL);
+ SM_ASSERT(buf != NULL);
+
+ while (offset + MILTER_LEN_BYTES < rlen)
+ {
+ size_t len;
+ char **macros;
+
+ nummac = 0;
+ (void) memcpy((char *) &v, buf + offset, MILTER_LEN_BYTES);
+ i = ntohl(v);
+ if (i < SMFIM_FIRST || i > SMFIM_LAST)
+ return -1;
+ offset += MILTER_LEN_BYTES;
+ macros = NULL;
+
+ switch (i)
+ {
+ case MO_MACROS_CONNECT:
+ if (macros == NULL)
+ macros = MilterConnectMacros;
+ /* FALLTHROUGH */
+
+ case MO_MACROS_HELO:
+ if (macros == NULL)
+ macros = MilterHeloMacros;
+ /* FALLTHROUGH */
+
+ case MO_MACROS_ENVFROM:
+ if (macros == NULL)
+ macros = MilterEnvFromMacros;
+ /* FALLTHROUGH */
+
+ case MO_MACROS_ENVRCPT:
+ if (macros == NULL)
+ macros = MilterEnvRcptMacros;
+ /* FALLTHROUGH */
+
+ case MO_MACROS_EOM:
+ if (macros == NULL)
+ macros = MilterEOMMacros;
+ /* FALLTHROUGH */
+
+ case MO_MACROS_EOH:
+ if (macros == NULL)
+ macros = MilterEOHMacros;
+ /* FALLTHROUGH */
+
+ case MO_MACROS_DATA:
+ if (macros == NULL)
+ macros = MilterDataMacros;
+
+ len = strlen(buf + offset);
+ if (len > 0)
+ {
+ r = milter_set_macros(m->mf_name, macros,
+ buf + offset, nummac);
+ if (r >= 0)
+ nummac = r;
+ }
+ break;
+
+ default:
+ return -1;
+ }
+ if (len == 0)
+ return -1;
+ offset += len + 1;
+ }
+
+ return 0;
+}
+
/*
** MILTER_NEGOTIATE -- get version and flags from filter
**
@@ -2190,10 +2417,8 @@ milter_negotiate(m, e)
ENVELOPE *e;
{
char rcmd;
- mi_int32 fvers;
- mi_int32 fflags;
- mi_int32 pflags;
- mi_int32 curr_prot;
+ mi_int32 fvers, fflags, pflags;
+ mi_int32 mta_prot_vers, mta_prot_flags, mta_actions;
ssize_t rlen;
char *response;
char data[MILTER_OPTLEN];
@@ -2209,32 +2434,36 @@ milter_negotiate(m, e)
return -1;
}
- fvers = htonl(SMFI_VERSION);
- fflags = htonl(SMFI_CURR_ACTS);
- curr_prot = SMFI_V2_PROT
-#if _FFR_MILTER_NOHDR_RESP
- | SMFIP_NOHREPL
-#endif /* _FFR_MILTER_NOHDR_RESP */
-#if SMFI_VERSION >= 3
- | SMFIP_NOUNKNOWN
-# if SMFI_VERSION >= 4
- | SMFIP_NODATA
-# endif /* SMFI_VERSION >= 4 */
-#endif /* SMFI_VERSION >= 3 */
- ;
- pflags = htonl(curr_prot);
+#if _FFR_MILTER_CHECK
+ mta_prot_vers = m->mf_mta_prot_version;
+ mta_prot_flags = m->mf_mta_prot_flags;
+ mta_actions = m->mf_mta_actions;
+#else /* _FFR_MILTER_CHECK */
+ mta_prot_vers = SMFI_PROT_VERSION;
+ mta_prot_flags = SMFI_CURR_PROT;
+ mta_actions = SMFI_CURR_ACTS;
+#endif /* _FFR_MILTER_CHECK */
+
+ fvers = htonl(mta_prot_vers);
+ pflags = htonl(mta_prot_flags);
+ fflags = htonl(mta_actions);
(void) memcpy(data, (char *) &fvers, MILTER_LEN_BYTES);
(void) memcpy(data + MILTER_LEN_BYTES,
(char *) &fflags, MILTER_LEN_BYTES);
(void) memcpy(data + (MILTER_LEN_BYTES * 2),
(char *) &pflags, MILTER_LEN_BYTES);
- (void) milter_write(m, SMFIC_OPTNEG, data, sizeof data,
- m->mf_timeout[SMFTO_WRITE], e);
+ (void) milter_write(m, SMFIC_OPTNEG, data, sizeof(data),
+ m->mf_timeout[SMFTO_WRITE], e, "negotiate");
if (m->mf_state == SMFS_ERROR)
return -1;
- response = milter_read(m, &rcmd, &rlen, m->mf_timeout[SMFTO_READ], e);
+ if (tTd(64, 5))
+ sm_dprintf("milter_negotiate(%s): send: version %lu, fflags 0x%lx, pflags 0x%lx\n",
+ m->mf_name, ntohl(fvers), ntohl(fflags), ntohl(pflags));
+
+ response = milter_read(m, &rcmd, &rlen, m->mf_timeout[SMFTO_READ], e,
+ "negotiate");
if (m->mf_state == SMFS_ERROR)
return -1;
@@ -2273,7 +2502,7 @@ milter_negotiate(m, e)
(void) memcpy((char *) &fvers, response, MILTER_LEN_BYTES);
/* Now make sure we have enough for the feature bitmap */
- if (rlen != MILTER_OPTLEN)
+ if (rlen < MILTER_OPTLEN)
{
if (tTd(64, 5))
sm_dprintf("milter_negotiate(%s): did not return enough info\n",
@@ -2292,8 +2521,6 @@ milter_negotiate(m, e)
MILTER_LEN_BYTES);
(void) memcpy((char *) &pflags, response + (MILTER_LEN_BYTES * 2),
MILTER_LEN_BYTES);
- sm_free(response); /* XXX */
- response = NULL;
m->mf_fvers = ntohl(fvers);
m->mf_fflags = ntohl(fflags);
@@ -2311,39 +2538,39 @@ milter_negotiate(m, e)
"Milter (%s): negotiate: version %d != MTA milter version %d",
m->mf_name, m->mf_fvers, SMFI_VERSION);
milter_error(m, e);
- return -1;
+ goto error;
}
/* check for filter feature mismatch */
- if ((m->mf_fflags & SMFI_CURR_ACTS) != m->mf_fflags)
+ if ((m->mf_fflags & mta_actions) != m->mf_fflags)
{
if (tTd(64, 5))
sm_dprintf("milter_negotiate(%s): filter abilities 0x%x != MTA milter abilities 0x%lx\n",
m->mf_name, m->mf_fflags,
- SMFI_CURR_ACTS);
+ (unsigned long) mta_actions);
if (MilterLogLevel > 0)
sm_syslog(LOG_ERR, e->e_id,
"Milter (%s): negotiate: filter abilities 0x%x != MTA milter abilities 0x%lx",
m->mf_name, m->mf_fflags,
- (unsigned long) SMFI_CURR_ACTS);
+ (unsigned long) mta_actions);
milter_error(m, e);
- return -1;
+ goto error;
}
/* check for protocol feature mismatch */
- if ((m->mf_pflags & curr_prot) != m->mf_pflags)
+ if ((m->mf_pflags & mta_prot_flags) != m->mf_pflags)
{
if (tTd(64, 5))
sm_dprintf("milter_negotiate(%s): protocol abilities 0x%x != MTA milter abilities 0x%lx\n",
m->mf_name, m->mf_pflags,
- (unsigned long) curr_prot);
+ (unsigned long) mta_prot_flags);
if (MilterLogLevel > 0)
sm_syslog(LOG_ERR, e->e_id,
"Milter (%s): negotiate: protocol abilities 0x%x != MTA milter abilities 0x%lx",
m->mf_name, m->mf_pflags,
- (unsigned long) curr_prot);
+ (unsigned long) mta_prot_flags);
milter_error(m, e);
- return -1;
+ goto error;
}
if (m->mf_fvers <= 2)
@@ -2351,11 +2578,22 @@ milter_negotiate(m, e)
if (m->mf_fvers <= 3)
m->mf_pflags |= SMFIP_NODATA;
+ if (rlen > MILTER_OPTLEN)
+ {
+ milter_getsymlist(m, response, rlen, MILTER_OPTLEN);
+ }
+
if (tTd(64, 5))
- sm_dprintf("milter_negotiate(%s): version %u, fflags 0x%x, pflags 0x%x\n",
+ sm_dprintf("milter_negotiate(%s): received: version %u, fflags 0x%x, pflags 0x%x\n",
m->mf_name, m->mf_fvers, m->mf_fflags, m->mf_pflags);
return 0;
+
+ error:
+ if (response != NULL)
+ sm_free(response); /* XXX */
+ return -1;
}
+
/*
** MILTER_PER_CONNECTION_CHECK -- checks on per-connection commands
**
@@ -2383,6 +2621,7 @@ milter_per_connection_check(e)
milter_quit_filter(m, e);
}
}
+
/*
** MILTER_ERROR -- Put a milter filter into error state
**
@@ -2415,6 +2654,7 @@ milter_error(m, e)
sm_syslog(LOG_INFO, e->e_id, "Milter (%s): to error state",
m->mf_name);
}
+
/*
** MILTER_HEADERS -- send headers to a single milter filter
**
@@ -2442,8 +2682,8 @@ milter_headers(m, e, state)
for (h = e->e_header; h != NULL; h = h->h_link)
{
- char *buf;
- ssize_t s;
+ int len_n, len_v, len_t, len_f;
+ char *buf, *hv;
/* don't send over deleted headers */
if (h->h_value == NULL)
@@ -2458,23 +2698,39 @@ milter_headers(m, e, state)
continue;
if (tTd(64, 10))
- sm_dprintf("milter_headers: %s: %s\n",
+ sm_dprintf("milter_headers: %s:%s\n",
h->h_field, h->h_value);
if (MilterLogLevel > 21)
sm_syslog(LOG_INFO, e->e_id, "Milter (%s): header, %s",
m->mf_name, h->h_field);
- s = strlen(h->h_field) + 1 + strlen(h->h_value) + 1;
- if (s < 0)
+ if (bitset(SMFIP_HDR_LEADSPC, m->mf_pflags)
+ || *(h->h_value) != ' ')
+ hv = h->h_value;
+ else
+ hv = h->h_value + 1;
+ len_f = strlen(h->h_field) + 1;
+ len_t = len_f + strlen(hv) + 1;
+ if (len_t < 0)
continue;
- buf = (char *) xalloc(s);
- (void) sm_snprintf(buf, s, "%s%c%s",
- h->h_field, '\0', h->h_value);
+ buf = (char *) xalloc(len_t);
+
+ /*
+ ** Note: currently the call to dequote_internal_chars()
+ ** is not required as h_field is supposed to be 7-bit US-ASCII.
+ */
+
+ len_n = dequote_internal_chars(h->h_field, buf, len_f);
+ SM_ASSERT(len_n < len_f);
+ len_v = dequote_internal_chars(hv, buf + len_n + 1,
+ len_t - len_n - 1);
+ SM_ASSERT(len_t >= len_n + 1 + len_v + 1);
+ len_t = len_n + 1 + len_v + 1;
/* send it over */
response = milter_send_command(m, SMFIC_HEADER, buf,
- s, e, state);
- sm_free(buf); /* XXX */
+ len_t, e, state, "header");
+ sm_free(buf);
if (m->mf_state == SMFS_ERROR ||
m->mf_state == SMFS_DONE ||
*state != SMFIR_CONTINUE)
@@ -2485,6 +2741,7 @@ milter_headers(m, e, state)
m->mf_name);
return response;
}
+
/*
** MILTER_BODY -- send the body to a filter
**
@@ -2532,11 +2789,13 @@ milter_body(m, e, state)
/* Change LF to CRLF */
if (c == '\n')
{
+#if !_FFR_MILTER_CONVERT_ALL_LF_TO_CRLF
/* Not a CRLF already? */
if (prevchar != '\r')
+#endif /* !_FFR_MILTER_CONVERT_ALL_LF_TO_CRLF */
{
/* Room for CR now? */
- if (bp + 2 > &buf[sizeof buf])
+ if (bp + 2 > &buf[sizeof(buf)])
{
/* No room, buffer LF */
bufchar = c;
@@ -2554,11 +2813,12 @@ milter_body(m, e, state)
}
*bp++ = (char) c;
prevchar = c;
- if (bp >= &buf[sizeof buf])
+ if (bp >= &buf[sizeof(buf)])
{
/* send chunk */
response = milter_send_command(m, SMFIC_BODY, buf,
- bp - buf, e, state);
+ bp - buf, e, state,
+ "body chunk");
bp = buf;
if (bufchar != '\0')
{
@@ -2569,6 +2829,7 @@ milter_body(m, e, state)
}
if (m->mf_state == SMFS_ERROR ||
m->mf_state == SMFS_DONE ||
+ m->mf_state == SMFS_SKIP ||
*state != SMFIR_CONTINUE)
break;
}
@@ -2578,7 +2839,8 @@ milter_body(m, e, state)
{
ExitStat = EX_IOERR;
if (*state == SMFIR_CONTINUE ||
- *state == SMFIR_ACCEPT)
+ *state == SMFIR_ACCEPT ||
+ m->mf_state == SMFS_SKIP)
{
*state = SMFIR_TEMPFAIL;
if (response != NULL)
@@ -2597,16 +2859,23 @@ milter_body(m, e, state)
if (bp > buf &&
m->mf_state != SMFS_ERROR &&
m->mf_state != SMFS_DONE &&
+ m->mf_state != SMFS_SKIP &&
*state == SMFIR_CONTINUE)
{
/* send chunk */
response = milter_send_command(m, SMFIC_BODY, buf, bp - buf,
- e, state);
+ e, state, "last body chunk");
bp = buf;
}
if (MilterLogLevel > 17)
sm_syslog(LOG_INFO, e->e_id, "Milter (%s): body, sent",
m->mf_name);
+ if (m->mf_state == SMFS_SKIP)
+ {
+ *state = SMFIR_CONTINUE;
+ m->mf_state = SMFS_READY;
+ }
+
return response;
}
@@ -2614,10 +2883,42 @@ milter_body(m, e, state)
** Actions
*/
+/*
+** ADDLEADINGSPACE -- Add a leading space to a string
+**
+** Parameters:
+** str -- string
+** rp -- resource pool for allocations
+**
+** Returns:
+** pointer to new string
+*/
+
+static char *addleadingspace __P((char *, SM_RPOOL_T *));
+
+static char *
+addleadingspace(str, rp)
+ char *str;
+ SM_RPOOL_T *rp;
+{
+ size_t l;
+ char *new;
+
+ SM_ASSERT(str != NULL);
+ l = strlen(str);
+ SM_ASSERT(l + 2 > l);
+ new = sm_rpool_malloc_x(rp, l + 2);
+ new[0] = ' ';
+ new[1] = '\0';
+ sm_strlcpy(new + 1, str, l + 1);
+ return new;
+}
+
/*
** MILTER_ADDHEADER -- Add the supplied header to the message
**
** Parameters:
+** m -- current filter.
** response -- encoded form of header/value.
** rlen -- length of response.
** e -- current envelope.
@@ -2627,12 +2928,14 @@ milter_body(m, e, state)
*/
static void
-milter_addheader(response, rlen, e)
+milter_addheader(m, response, rlen, e)
+ struct milter *m;
char *response;
ssize_t rlen;
ENVELOPE *e;
{
- char *val;
+ int mh_v_len;
+ char *val, *mh_value;
HDR *h;
if (tTd(64, 10))
@@ -2649,7 +2952,8 @@ milter_addheader(response, rlen, e)
if (rlen < 2 || strlen(response) + 1 >= (size_t) rlen)
{
if (tTd(64, 10))
- sm_dprintf("didn't follow protocol (total len)\n");
+ sm_dprintf("didn't follow protocol (total len %d != rlen %d)\n",
+ (int) strlen(response), (int) (rlen - 1));
return;
}
@@ -2679,6 +2983,9 @@ milter_addheader(response, rlen, e)
break;
}
+ mh_v_len = 0;
+ mh_value = quote_internal_chars(val, NULL, &mh_v_len);
+
/* add to e_msgsize */
e->e_msgsize += strlen(response) + 2 + strlen(val);
@@ -2686,28 +2993,39 @@ milter_addheader(response, rlen, e)
{
if (tTd(64, 10))
sm_dprintf("Replace default header %s value with %s\n",
- h->h_field, val);
+ h->h_field, mh_value);
if (MilterLogLevel > 8)
sm_syslog(LOG_INFO, e->e_id,
"Milter change: default header %s value with %s",
- h->h_field, val);
- h->h_value = newstr(val);
+ h->h_field, mh_value);
+ if (bitset(SMFIP_HDR_LEADSPC, m->mf_pflags))
+ h->h_value = mh_value;
+ else
+ {
+ h->h_value = addleadingspace (mh_value, e->e_rpool);
+ SM_FREE(mh_value);
+ }
h->h_flags |= H_USER;
}
else
{
if (tTd(64, 10))
- sm_dprintf("Add %s: %s\n", response, val);
+ sm_dprintf("Add %s: %s\n", response, mh_value);
if (MilterLogLevel > 8)
- sm_syslog(LOG_INFO, e->e_id, "Milter add: header: %s: %s",
- response, val);
- addheader(newstr(response), val, H_USER, e);
+ sm_syslog(LOG_INFO, e->e_id,
+ "Milter add: header: %s: %s",
+ response, mh_value);
+ addheader(newstr(response), mh_value, H_USER, e,
+ !bitset(SMFIP_HDR_LEADSPC, m->mf_pflags));
+ SM_FREE(mh_value);
}
}
+
/*
** MILTER_INSHEADER -- Insert the supplied header
**
** Parameters:
+** m -- current filter.
** response -- encoded form of header/value.
** rlen -- length of response.
** e -- current envelope.
@@ -2722,14 +3040,15 @@ milter_addheader(response, rlen, e)
*/
static void
-milter_insheader(response, rlen, e)
+milter_insheader(m, response, rlen, e)
+ struct milter *m;
char *response;
ssize_t rlen;
ENVELOPE *e;
{
mi_int32 idx, i;
- char *field;
- char *val;
+ int mh_v_len;
+ char *field, *val, *mh_value;
if (tTd(64, 10))
sm_dprintf("milter_insheader: ");
@@ -2775,17 +3094,23 @@ milter_insheader(response, rlen, e)
e->e_msgsize += strlen(response) + 2 + strlen(val);
if (tTd(64, 10))
- sm_dprintf("Insert (%d) %s: %s\n", idx, response, val);
+ sm_dprintf("Insert (%d) %s: %s\n", idx, field, val);
if (MilterLogLevel > 8)
sm_syslog(LOG_INFO, e->e_id,
"Milter insert (%d): header: %s: %s",
idx, field, val);
- insheader(idx, newstr(field), val, H_USER, e);
+ mh_v_len = 0;
+ mh_value = quote_internal_chars(val, NULL, &mh_v_len);
+ insheader(idx, newstr(field), mh_value, H_USER, e,
+ !bitset(SMFIP_HDR_LEADSPC, m->mf_pflags));
+ SM_FREE(mh_value);
}
+
/*
** MILTER_CHANGEHEADER -- Change the supplied header in the message
**
** Parameters:
+** m -- current filter.
** response -- encoded form of header/index/value.
** rlen -- length of response.
** e -- current envelope.
@@ -2795,13 +3120,15 @@ milter_insheader(response, rlen, e)
*/
static void
-milter_changeheader(response, rlen, e)
+milter_changeheader(m, response, rlen, e)
+ struct milter *m;
char *response;
ssize_t rlen;
ENVELOPE *e;
{
mi_int32 i, index;
- char *field, *val;
+ int mh_v_len;
+ char *field, *val, *mh_value;
HDR *h, *sysheader;
if (tTd(64, 10))
@@ -2844,13 +3171,15 @@ milter_changeheader(response, rlen, e)
return;
}
+ mh_v_len = 0;
+ mh_value = quote_internal_chars(val, NULL, &mh_v_len);
+
sysheader = NULL;
for (h = e->e_header; h != NULL; h = h->h_link)
{
if (sm_strcasecmp(h->h_field, field) == 0)
{
- if (bitset(H_USER, h->h_flags) &&
- --index <= 0)
+ if (bitset(H_USER, h->h_flags) && --index <= 0)
{
sysheader = NULL;
break;
@@ -2889,12 +3218,13 @@ milter_changeheader(response, rlen, e)
{
/* treat modify value with no existing header as add */
if (tTd(64, 10))
- sm_dprintf("Add %s: %s\n", field, val);
+ sm_dprintf("Add %s: %s\n", field, mh_value);
if (MilterLogLevel > 8)
sm_syslog(LOG_INFO, e->e_id,
"Milter change (add): header: %s: %s"
- , field, val);
- addheader(newstr(field), val, H_USER, e);
+ , field, mh_value);
+ addheader(newstr(field), mh_value, H_USER, e,
+ !bitset(SMFIP_HDR_LEADSPC, m->mf_pflags));
}
return;
}
@@ -2903,7 +3233,7 @@ milter_changeheader(response, rlen, e)
{
if (*val == '\0')
{
- sm_dprintf("Delete%s %s: %s\n",
+ sm_dprintf("Delete%s %s:%s\n",
h == sysheader ? " (default header)" : "",
field,
h->h_value == NULL ? "" : h->h_value);
@@ -2914,7 +3244,7 @@ milter_changeheader(response, rlen, e)
h == sysheader ? " (default header)" : "",
field,
h->h_value == NULL ? "" : h->h_value,
- val);
+ mh_value);
}
}
@@ -2923,7 +3253,7 @@ milter_changeheader(response, rlen, e)
if (*val == '\0')
{
sm_syslog(LOG_INFO, e->e_id,
- "Milter delete: header%s %s: %s",
+ "Milter delete: header%s %s:%s",
h == sysheader ? " (default header)" : "",
field,
h->h_value == NULL ? "" : h->h_value);
@@ -2935,7 +3265,7 @@ milter_changeheader(response, rlen, e)
h == sysheader ? " (default header)" : "",
field,
h->h_value == NULL ? "" : h->h_value,
- val);
+ mh_value);
}
}
@@ -2965,14 +3295,237 @@ milter_changeheader(response, rlen, e)
e->e_msgsize -= l;
}
h->h_value = NULL;
+ SM_FREE(mh_value);
}
else
{
- h->h_value = newstr(val);
+ if (bitset(SMFIP_HDR_LEADSPC, m->mf_pflags))
+ h->h_value = mh_value;
+ else
+ {
+ h->h_value = addleadingspace (mh_value, e->e_rpool);
+ SM_FREE(mh_value);
+ }
h->h_flags |= H_USER;
e->e_msgsize += strlen(h->h_value);
}
}
+
+/*
+** MILTER_SPLIT_RESPONSE -- Split response into fields.
+**
+** Parameters:
+** response -- encoded repsonse.
+** rlen -- length of response.
+** pargc -- number of arguments (ouput)
+**
+** Returns:
+** array of pointers to the individual strings
+*/
+
+static char **milter_split_response __P((char *, ssize_t, int *));
+
+static char **
+milter_split_response(response, rlen, pargc)
+ char *response;
+ ssize_t rlen;
+ int *pargc;
+{
+ char **s;
+ size_t i;
+ int elem, nelem;
+
+ SM_ASSERT(response != NULL);
+ SM_ASSERT(pargc != NULL);
+ *pargc = 0;
+ if (rlen < 2 || strlen(response) >= (size_t) rlen)
+ {
+ if (tTd(64, 10))
+ sm_dprintf("didn't follow protocol (total len %d != rlen %d)\n",
+ (int) strlen(response), (int) (rlen - 1));
+ return NULL;
+ }
+
+ nelem = 0;
+ for (i = 0; i < rlen; i++)
+ {
+ if (response[i] == '\0')
+ ++nelem;
+ }
+ if (nelem == 0)
+ return NULL;
+
+ /* last entry is only for the name */
+ s = (char **)malloc(nelem * (sizeof(*s)));
+ if (s == NULL)
+ return NULL;
+ s[0] = response;
+ for (i = 0, elem = 0; i < rlen && elem < nelem; i++)
+ {
+ if (response[i] == '\0')
+ {
+ ++elem;
+ if (i + 1 >= rlen)
+ s[elem] = NULL;
+ else
+ s[elem] = &(response[i + 1]);
+ }
+ }
+ *pargc = nelem;
+
+ if (tTd(64, 10))
+ {
+ for (elem = 0; elem < nelem; elem++)
+ sm_dprintf("argv[%d]=\"%s\"\n", elem, s[elem]);
+ }
+
+ /* overwrite last entry (already done above, just paranoia) */
+ s[elem] = NULL;
+ return s;
+}
+
+/*
+** MILTER_CHGFROM -- Change the envelope sender address
+**
+** Parameters:
+** response -- encoded form of recipient address.
+** rlen -- length of response.
+** e -- current envelope.
+**
+** Returns:
+** none
+*/
+
+static void
+milter_chgfrom(response, rlen, e)
+ char *response;
+ ssize_t rlen;
+ ENVELOPE *e;
+{
+ int olderrors, argc;
+ char **argv;
+
+ if (tTd(64, 10))
+ sm_dprintf("milter_chgfrom: ");
+
+ /* sanity checks */
+ if (response == NULL)
+ {
+ if (tTd(64, 10))
+ sm_dprintf("NULL response\n");
+ return;
+ }
+
+ if (*response == '\0' ||
+ strlen(response) + 1 > (size_t) rlen)
+ {
+ if (tTd(64, 10))
+ sm_dprintf("didn't follow protocol (total len %d != rlen %d)\n",
+ (int) strlen(response), (int) (rlen - 1));
+ return;
+ }
+
+ if (tTd(64, 10))
+ sm_dprintf("%s\n", response);
+ if (MilterLogLevel > 8)
+ sm_syslog(LOG_INFO, e->e_id, "Milter chgfrom: %s", response);
+ argv = milter_split_response(response, rlen, &argc);
+ if (argc < 1 || argc > 2)
+ {
+ if (tTd(64, 10))
+ sm_dprintf("didn't follow protocol argc=%d\n", argc);
+ return;
+ }
+
+ olderrors = Errors;
+ setsender(argv[0], e, NULL, '\0', false);
+ if (argc == 2)
+ {
+ reset_mail_esmtp_args(e);
+
+ /*
+ ** need "features" here: how to get those? via e?
+ ** "fake" it for now: allow everything.
+ */
+
+ parse_esmtp_args(e, NULL, argv[0], argv[1], "MAIL", NULL,
+ mail_esmtp_args);
+ }
+ Errors = olderrors;
+ return;
+}
+
+/*
+** MILTER_ADDRCPT_PAR -- Add the supplied recipient to the message
+**
+** Parameters:
+** response -- encoded form of recipient address.
+** rlen -- length of response.
+** e -- current envelope.
+**
+** Returns:
+** none
+*/
+
+static void
+milter_addrcpt_par(response, rlen, e)
+ char *response;
+ ssize_t rlen;
+ ENVELOPE *e;
+{
+ int olderrors, argc;
+ char *delimptr;
+ char **argv;
+ ADDRESS *a;
+
+ if (tTd(64, 10))
+ sm_dprintf("milter_addrcpt_par: ");
+
+ /* sanity checks */
+ if (response == NULL)
+ {
+ if (tTd(64, 10))
+ sm_dprintf("NULL response\n");
+ return;
+ }
+
+ if (tTd(64, 10))
+ sm_dprintf("%s\n", response);
+ if (MilterLogLevel > 8)
+ sm_syslog(LOG_INFO, e->e_id, "Milter add: rcpt: %s", response);
+
+ argv = milter_split_response(response, rlen, &argc);
+ if (argc < 1 || argc > 2)
+ {
+ if (tTd(64, 10))
+ sm_dprintf("didn't follow protocol argc=%d\n", argc);
+ return;
+ }
+ olderrors = Errors;
+
+ /* how to set ESMTP arguments? */
+ a = parseaddr(argv[0], NULLADDR, RF_COPYALL, ' ', &delimptr, e, true);
+
+ if (a != NULL && olderrors == Errors)
+ {
+ parse_esmtp_args(e, a, argv[0], argv[1], "RCPT", NULL,
+ rcpt_esmtp_args);
+ if (olderrors == Errors)
+ a = recipient(a, &e->e_sendqueue, 0, e);
+ else
+ sm_dprintf("olderrors=%d, Errors=%d\n",
+ olderrors, Errors);
+ }
+ else
+ {
+ sm_dprintf("a=%p, olderrors=%d, Errors=%d\n",
+ a, olderrors, Errors);
+ }
+
+ Errors = olderrors;
+ return;
+}
+
/*
** MILTER_ADDRCPT -- Add the supplied recipient to the message
**
@@ -3022,6 +3575,7 @@ milter_addrcpt(response, rlen, e)
Errors = olderrors;
return;
}
+
/*
** MILTER_DELRCPT -- Delete the supplied recipient from the message
**
@@ -3055,7 +3609,8 @@ milter_delrcpt(response, rlen, e)
strlen(response) + 1 != (size_t) rlen)
{
if (tTd(64, 10))
- sm_dprintf("didn't follow protocol (total len)\n");
+ sm_dprintf("didn't follow protocol (total len %d != rlen %d)\n",
+ (int) strlen(response), (int) (rlen - 1));
return;
}
@@ -3067,6 +3622,7 @@ milter_delrcpt(response, rlen, e)
(void) removefromlist(response, &e->e_sendqueue, e);
return;
}
+
/*
** MILTER_REPLBODY -- Replace the current data file with new body
**
@@ -3100,7 +3656,7 @@ milter_replbody(response, rlen, newfilter, e)
char dfname[MAXPATHLEN];
(void) sm_strlcpy(dfname, queuename(e, DATAFL_LETTER),
- sizeof dfname);
+ sizeof(dfname));
/* Reset prevchar */
prevchar = '\0';
@@ -3303,6 +3859,7 @@ milter_init(e, state)
return true;
}
+
/*
** MILTER_CONNECT -- send connection info to milter filters
**
@@ -3365,7 +3922,7 @@ milter_connect(hostname, addr, e, state)
family = SMFIA_INET6;
port = addr.sin6.sin6_port;
sockinfo = anynet_ntop(&addr.sin6.sin6_addr, buf6,
- sizeof buf6);
+ sizeof(buf6));
if (sockinfo == NULL)
sockinfo = "";
break;
@@ -3387,19 +3944,19 @@ milter_connect(hostname, addr, e, state)
(void) memcpy(bp, hostname, strlen(hostname));
bp += strlen(hostname);
*bp++ = '\0';
- (void) memcpy(bp, &family, sizeof family);
- bp += sizeof family;
+ (void) memcpy(bp, &family, sizeof(family));
+ bp += sizeof(family);
if (family != SMFIA_UNKNOWN)
{
- (void) memcpy(bp, &port, sizeof port);
- bp += sizeof port;
+ (void) memcpy(bp, &port, sizeof(port));
+ bp += sizeof(port);
/* include trailing '\0' */
(void) memcpy(bp, sockinfo, strlen(sockinfo) + 1);
}
- response = milter_command(SMFIC_CONNECT, buf, s,
- MilterConnectMacros, e, state);
+ response = milter_command(SMFIC_CONNECT, buf, s, MilterConnectMacros,
+ e, state, "connect", false);
sm_free(buf); /* XXX */
/*
@@ -3442,6 +3999,7 @@ milter_connect(hostname, addr, e, state)
}
return response;
}
+
/*
** MILTER_HELO -- send SMTP HELO/EHLO command info to milter filters
**
@@ -3486,10 +4044,11 @@ milter_helo(helo, e, state)
}
response = milter_command(SMFIC_HELO, helo, strlen(helo) + 1,
- MilterHeloMacros, e, state);
+ MilterHeloMacros, e, state, "helo", false);
milter_per_connection_check(e);
return response;
}
+
/*
** MILTER_ENVFROM -- send SMTP MAIL command info to milter filters
**
@@ -3570,11 +4129,11 @@ milter_envfrom(args, e, state)
}
if (MilterLogLevel > 14)
- sm_syslog(LOG_INFO, e->e_id, "Milter: senders: %s", buf);
+ sm_syslog(LOG_INFO, e->e_id, "Milter: sender: %s", buf);
/* send it over */
- response = milter_command(SMFIC_MAIL, buf, s,
- MilterEnvFromMacros, e, state);
+ response = milter_command(SMFIC_MAIL, buf, s, MilterEnvFromMacros,
+ e, state, "mail", false);
sm_free(buf); /* XXX */
/*
@@ -3585,7 +4144,7 @@ milter_envfrom(args, e, state)
MILTER_CHECK_DONE_MSG();
if (MilterLogLevel > 10 && *state == SMFIR_REJECT)
- sm_syslog(LOG_INFO, e->e_id, "Milter: reject, senders");
+ sm_syslog(LOG_INFO, e->e_id, "Milter: reject, sender");
return response;
}
@@ -3596,16 +4155,18 @@ milter_envfrom(args, e, state)
** args -- SMTP MAIL command args (args[0] == recipient).
** e -- current envelope.
** state -- return state from response.
+** rcpt_error -- does RCPT have an error?
**
** Returns:
** response string (may be NULL)
*/
char *
-milter_envrcpt(args, e, state)
+milter_envrcpt(args, e, state, rcpt_error)
char **args;
ENVELOPE *e;
char *state;
+ bool rcpt_error;
{
int i;
char *buf, *bp;
@@ -3652,13 +4213,12 @@ milter_envrcpt(args, e, state)
sm_syslog(LOG_INFO, e->e_id, "Milter: rcpts: %s", buf);
/* send it over */
- response = milter_command(SMFIC_RCPT, buf, s,
- MilterEnvRcptMacros, e, state);
+ response = milter_command(SMFIC_RCPT, buf, s, MilterEnvRcptMacros,
+ e, state, "rcpt", rcpt_error);
sm_free(buf); /* XXX */
return response;
}
-#if SMFI_VERSION > 3
/*
** MILTER_DATA_CMD -- send SMTP DATA command info to milter filters
**
@@ -3679,9 +4239,9 @@ milter_data_cmd(e, state)
sm_dprintf("milter_data_cmd\n");
/* send it over */
- return milter_command(SMFIC_DATA, NULL, 0, MilterDataMacros, e, state);
+ return milter_command(SMFIC_DATA, NULL, 0, MilterDataMacros, e, state,
+ "data", false);
}
-#endif /* SMFI_VERSION > 3 */
/*
** MILTER_DATA -- send message headers/body and gather final message results
@@ -3789,9 +4349,16 @@ milter_data(e, state)
if (tTd(64, 10))
sm_dprintf("milter_data: eoh\n");
+ if (MilterEOHMacros[0] != NULL)
+ {
+ milter_send_macros(m, MilterEOHMacros,
+ SMFIC_EOH, e);
+ MILTER_CHECK_RESULTS();
+ }
+
/* send it over */
response = milter_send_command(m, SMFIC_EOH, NULL, 0,
- e, state);
+ e, state, "eoh");
MILTER_CHECK_RESULTS();
}
@@ -3813,7 +4380,7 @@ milter_data(e, state)
/* send the final body chunk */
(void) milter_write(m, SMFIC_BODYEOB, NULL, 0,
- m->mf_timeout[SMFTO_WRITE], e);
+ m->mf_timeout[SMFTO_WRITE], e, "eom");
/* Get time EOM sent for timeout */
eomsent = curtime();
@@ -3838,7 +4405,8 @@ milter_data(e, state)
}
response = milter_read(m, &rcmd, &rlen,
- m->mf_timeout[SMFTO_READ], e);
+ m->mf_timeout[SMFTO_READ], e,
+ "body");
if (m->mf_state == SMFS_ERROR)
break;
@@ -3922,7 +4490,7 @@ milter_data(e, state)
"milter_data(%s): lied about adding headers, honoring request anyway",
m->mf_name);
}
- milter_addheader(response, rlen, e);
+ milter_addheader(m, response, rlen, e);
break;
case SMFIR_INSHEADER:
@@ -3933,7 +4501,7 @@ milter_data(e, state)
"milter_data(%s): lied about adding headers, honoring request anyway",
m->mf_name);
}
- milter_insheader(response, rlen, e);
+ milter_insheader(m, response, rlen, e);
break;
case SMFIR_CHGHEADER:
@@ -3944,7 +4512,18 @@ milter_data(e, state)
"milter_data(%s): lied about changing headers, honoring request anyway",
m->mf_name);
}
- milter_changeheader(response, rlen, e);
+ milter_changeheader(m, response, rlen, e);
+ break;
+
+ case SMFIR_CHGFROM:
+ if (!bitset(SMFIF_CHGFROM, m->mf_fflags))
+ {
+ if (MilterLogLevel > 9)
+ sm_syslog(LOG_WARNING, e->e_id,
+ "milter_data(%s) lied about changing sender, honoring request anyway",
+ m->mf_name);
+ }
+ milter_chgfrom(response, rlen, e);
break;
case SMFIR_ADDRCPT:
@@ -3958,6 +4537,17 @@ milter_data(e, state)
milter_addrcpt(response, rlen, e);
break;
+ case SMFIR_ADDRCPT_PAR:
+ if (!bitset(SMFIF_ADDRCPT_PAR, m->mf_fflags))
+ {
+ if (MilterLogLevel > 9)
+ sm_syslog(LOG_WARNING, e->e_id,
+ "milter_data(%s) lied about adding recipients with parameters, honoring request anyway",
+ m->mf_name);
+ }
+ milter_addrcpt_par(response, rlen, e);
+ break;
+
case SMFIR_DELRCPT:
if (!bitset(SMFIF_DELRCPT, m->mf_fflags))
{
@@ -4086,13 +4676,12 @@ milter_data(e, state)
return response;
}
-#if SMFI_VERSION > 2
/*
** MILTER_UNKNOWN -- send any unrecognized or unimplemented command
** string to milter filters
**
** Parameters:
-** cmd -- the string itself.
+** smtpcmd -- the string itself.
** e -- current envelope.
** state -- return state from response.
**
@@ -4102,18 +4691,17 @@ milter_data(e, state)
*/
char *
-milter_unknown(cmd, e, state)
- char *cmd;
+milter_unknown(smtpcmd, e, state)
+ char *smtpcmd;
ENVELOPE *e;
char *state;
{
if (tTd(64, 10))
- sm_dprintf("milter_unknown(%s)\n", cmd);
+ sm_dprintf("milter_unknown(%s)\n", smtpcmd);
- return milter_command(SMFIC_UNKNOWN, cmd, strlen(cmd) + 1,
- NULL, e, state);
+ return milter_command(SMFIC_UNKNOWN, smtpcmd, strlen(smtpcmd) + 1,
+ NULL, e, state, "unknown", false);
}
-#endif /* SMFI_VERSION > 2 */
/*
** MILTER_QUIT -- informs the filter(s) we are done and closes connection(s)
@@ -4137,6 +4725,7 @@ milter_quit(e)
for (i = 0; InputFilters[i] != NULL; i++)
milter_quit_filter(InputFilters[i], e);
}
+
/*
** MILTER_ABORT -- informs the filter(s) that we are aborting current message
**
diff --git a/contrib/sendmail/src/mime.c b/contrib/sendmail/src/mime.c
index c73fbf294074..48540a00b64e 100644
--- a/contrib/sendmail/src/mime.c
+++ b/contrib/sendmail/src/mime.c
@@ -14,7 +14,7 @@
#include
#include
-SM_RCSID("@(#)$Id: mime.c,v 8.142.2.1 2006/05/23 01:32:08 ca Exp $")
+SM_RCSID("@(#)$Id: mime.c,v 8.146 2006/08/16 16:52:11 ca Exp $")
/*
** MIME support.
@@ -151,7 +151,7 @@ mime8to7(mci, header, e, boundaries, flags, level)
MapNLtoCRLF = true;
p = hvalue("Content-Transfer-Encoding", header);
if (p == NULL ||
- (pvp = prescan(p, '\0', pvpbuf, sizeof pvpbuf, NULL,
+ (pvp = prescan(p, '\0', pvpbuf, sizeof(pvpbuf), NULL,
MimeTokenTab, false)) == NULL ||
pvp[0] == NULL)
{
@@ -159,7 +159,7 @@ mime8to7(mci, header, e, boundaries, flags, level)
}
else
{
- cataddr(pvp, NULL, buf, sizeof buf, '\0');
+ cataddr(pvp, NULL, buf, sizeof(buf), '\0', false);
cte = sm_rpool_strdup_x(e->e_rpool, buf);
}
@@ -173,7 +173,7 @@ mime8to7(mci, header, e, boundaries, flags, level)
p = "text/plain";
}
if (p != NULL &&
- (pvp = prescan(p, '\0', pvpbuf, sizeof pvpbuf, NULL,
+ (pvp = prescan(p, '\0', pvpbuf, sizeof(pvpbuf), NULL,
MimeTokenTab, false)) != NULL &&
pvp[0] != NULL)
{
@@ -238,7 +238,7 @@ mime8to7(mci, header, e, boundaries, flags, level)
** just copy it through.
*/
- (void) sm_snprintf(buf, sizeof buf, "%.100s/%.100s", type, subtype);
+ (void) sm_snprintf(buf, sizeof(buf), "%.100s/%.100s", type, subtype);
if (wordinclass(buf, 'n') || (cte != NULL && !wordinclass(cte, 'e')))
flags |= M87F_NO8BIT;
@@ -283,7 +283,7 @@ mime8to7(mci, header, e, boundaries, flags, level)
p = argv[i].a_value;
stripquotes(p);
}
- if (sm_strlcpy(bbuf, p, sizeof bbuf) >= sizeof bbuf)
+ if (sm_strlcpy(bbuf, p, sizeof(bbuf)) >= sizeof(bbuf))
{
usrerr("mime8to7: multipart boundary \"%s\" too long",
p);
@@ -322,7 +322,7 @@ mime8to7(mci, header, e, boundaries, flags, level)
goto writeerr;
mci->mci_flags &= ~MCIF_INHEADER;
bt = MBT_FINAL;
- while (sm_io_fgets(e->e_dfp, SM_TIME_DEFAULT, buf, sizeof buf)
+ while (sm_io_fgets(e->e_dfp, SM_TIME_DEFAULT, buf, sizeof(buf))
!= NULL)
{
bt = mimeboundary(buf, boundaries);
@@ -340,7 +340,7 @@ mime8to7(mci, header, e, boundaries, flags, level)
{
auto HDR *hdr = NULL;
- (void) sm_strlcpyn(buf, sizeof buf, 2, "--", bbuf);
+ (void) sm_strlcpyn(buf, sizeof(buf), 2, "--", bbuf);
if (!putline(buf, mci))
goto writeerr;
if (tTd(43, 35))
@@ -357,7 +357,7 @@ mime8to7(mci, header, e, boundaries, flags, level)
if (bt == SM_IO_EOF)
goto writeerr;
}
- (void) sm_strlcpyn(buf, sizeof buf, 3, "--", bbuf, "--");
+ (void) sm_strlcpyn(buf, sizeof(buf), 3, "--", bbuf, "--");
if (!putline(buf, mci))
goto writeerr;
if (tTd(43, 35))
@@ -366,7 +366,7 @@ mime8to7(mci, header, e, boundaries, flags, level)
mci->mci_flags &= ~MCIF_INMIME;
/* skip the late "comment" epilogue */
- while (sm_io_fgets(e->e_dfp, SM_TIME_DEFAULT, buf, sizeof buf)
+ while (sm_io_fgets(e->e_dfp, SM_TIME_DEFAULT, buf, sizeof(buf))
!= NULL)
{
bt = mimeboundary(buf, boundaries);
@@ -443,7 +443,7 @@ mime8to7(mci, header, e, boundaries, flags, level)
DATAFL_LETTER, e->e_id);
/* do a scan of this body type to count character types */
- while (sm_io_fgets(e->e_dfp, SM_TIME_DEFAULT, buf, sizeof buf)
+ while (sm_io_fgets(e->e_dfp, SM_TIME_DEFAULT, buf, sizeof(buf))
!= NULL)
{
if (mimeboundary(buf, boundaries) != MBT_NOTSEP)
@@ -512,7 +512,7 @@ mime8to7(mci, header, e, boundaries, flags, level)
** situation.
*/
- (void) sm_snprintf(buf, sizeof buf,
+ (void) sm_snprintf(buf, sizeof(buf),
"Content-Transfer-Encoding: %.200s", cte);
if (!putline(buf, mci))
goto writeerr;
@@ -522,7 +522,7 @@ mime8to7(mci, header, e, boundaries, flags, level)
if (!putline("", mci))
goto writeerr;
mci->mci_flags &= ~MCIF_INHEADER;
- while (sm_io_fgets(e->e_dfp, SM_TIME_DEFAULT, buf, sizeof buf)
+ while (sm_io_fgets(e->e_dfp, SM_TIME_DEFAULT, buf, sizeof(buf))
!= NULL)
{
bt = mimeboundary(buf, boundaries);
@@ -544,7 +544,7 @@ mime8to7(mci, header, e, boundaries, flags, level)
sm_dprintf(" ...Content-Transfer-Encoding: base64\n");
if (!putline("Content-Transfer-Encoding: base64", mci))
goto writeerr;
- (void) sm_snprintf(buf, sizeof buf,
+ (void) sm_snprintf(buf, sizeof(buf),
"X-MIME-Autoconverted: from 8bit to base64 by %s id %s",
MyHostName, e->e_id);
if (!putline(buf, mci) || !putline("", mci))
@@ -614,7 +614,7 @@ mime8to7(mci, header, e, boundaries, flags, level)
if (!putline("Content-Transfer-Encoding: quoted-printable",
mci))
goto writeerr;
- (void) sm_snprintf(buf, sizeof buf,
+ (void) sm_snprintf(buf, sizeof(buf),
"X-MIME-Autoconverted: from 8bit to quoted-printable by %s id %s",
MyHostName, e->e_id);
if (!putline(buf, mci) || !putline("", mci))
@@ -798,7 +798,7 @@ mime_getchar(fp, boundaries, btp)
/* got "--", now check for rest of separator */
*bp++ = '-';
- while (bp < &buf[sizeof buf - 2] &&
+ while (bp < &buf[sizeof(buf) - 2] &&
(c = sm_io_getc(fp, SM_TIME_DEFAULT)) != SM_IO_EOF &&
c != '\n')
{
@@ -816,7 +816,7 @@ mime_getchar(fp, boundaries, btp)
return SM_IO_EOF;
}
- if (bp < &buf[sizeof buf - 2] && c != SM_IO_EOF)
+ if (bp < &buf[sizeof(buf) - 2] && c != SM_IO_EOF)
*bp++ = c;
}
@@ -1041,7 +1041,7 @@ mime7to8(mci, header, e)
p = hvalue("Content-Transfer-Encoding", header);
if (p == NULL ||
- (pvp = prescan(p, '\0', pvpbuf, sizeof pvpbuf, NULL,
+ (pvp = prescan(p, '\0', pvpbuf, sizeof(pvpbuf), NULL,
MimeTokenTab, false)) == NULL ||
pvp[0] == NULL)
{
@@ -1054,7 +1054,7 @@ mime7to8(mci, header, e)
/* cheap failsafe algorithm -- should work on text/plain */
if (p != NULL)
{
- (void) sm_snprintf(buf, sizeof buf,
+ (void) sm_snprintf(buf, sizeof(buf),
"Content-Transfer-Encoding: %s", p);
if (!putline(buf, mci))
goto writeerr;
@@ -1062,7 +1062,7 @@ mime7to8(mci, header, e)
if (!putline("", mci))
goto writeerr;
mci->mci_flags &= ~MCIF_INHEADER;
- while (sm_io_fgets(e->e_dfp, SM_TIME_DEFAULT, buf, sizeof buf)
+ while (sm_io_fgets(e->e_dfp, SM_TIME_DEFAULT, buf, sizeof(buf))
!= NULL)
{
if (!putline(buf, mci))
@@ -1070,13 +1070,13 @@ mime7to8(mci, header, e)
}
return true;
}
- cataddr(pvp, NULL, buf, sizeof buf, '\0');
+ cataddr(pvp, NULL, buf, sizeof(buf), '\0', false);
cte = sm_rpool_strdup_x(e->e_rpool, buf);
mci->mci_flags |= MCIF_INHEADER;
if (!putline("Content-Transfer-Encoding: 8bit", mci))
goto writeerr;
- (void) sm_snprintf(buf, sizeof buf,
+ (void) sm_snprintf(buf, sizeof(buf),
"X-MIME-Autoconverted: from %.200s to 8bit by %s id %s",
cte, MyHostName, e->e_id);
if (!putline(buf, mci) || !putline("", mci))
@@ -1173,7 +1173,7 @@ mime7to8(mci, header, e)
pxflags |= PXLF_NOADDEOL;
fbufp = fbuf;
while (sm_io_fgets(e->e_dfp, SM_TIME_DEFAULT, buf,
- sizeof buf) != NULL)
+ sizeof(buf)) != NULL)
{
off = mime_fromqp((unsigned char *) buf, &fbufp,
&fbuf[MAXLINE] - fbufp);
diff --git a/contrib/sendmail/src/parseaddr.c b/contrib/sendmail/src/parseaddr.c
index dea3e1fe7187..9a14ec991aac 100644
--- a/contrib/sendmail/src/parseaddr.c
+++ b/contrib/sendmail/src/parseaddr.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998-2005 Sendmail, Inc. and its suppliers.
+ * Copyright (c) 1998-2006 Sendmail, Inc. and its suppliers.
* All rights reserved.
* Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved.
* Copyright (c) 1988, 1993
@@ -13,7 +13,10 @@
#include
-SM_RCSID("@(#)$Id: parseaddr.c,v 8.384 2006/04/18 01:28:47 ca Exp $")
+SM_RCSID("@(#)$Id: parseaddr.c,v 8.400 2006/12/21 00:24:06 ca Exp $")
+
+#include
+#include "map.h"
static void allocaddr __P((ADDRESS *, int, char *, ENVELOPE *));
static int callsubr __P((char**, int, ENVELOPE *));
@@ -90,7 +93,8 @@ parseaddr(addr, a, flags, delim, delimptr, e, isrcpt)
if (delimptr == NULL)
delimptr = &delimptrbuf;
- pvp = prescan(addr, delim, pvpbuf, sizeof pvpbuf, delimptr, NULL, false);
+ pvp = prescan(addr, delim, pvpbuf, sizeof(pvpbuf), delimptr,
+ ExtTokenTab, false);
if (pvp == NULL)
{
if (tTd(20, 1))
@@ -176,7 +180,7 @@ parseaddr(addr, a, flags, delim, delimptr, e, isrcpt)
*/
if ((a->q_qgrp == NOAQGRP || a->q_qgrp == ENVQGRP) &&
- !bitset(RF_SENDERADDR|RF_HEADERADDR, flags) &&
+ !bitset(RF_SENDERADDR|RF_HEADERADDR|RF_RM_ADDR, flags) &&
OpMode != MD_INITALIAS)
{
int r;
@@ -268,7 +272,7 @@ invalidaddr(addr, delimptr, isrcpt)
}
for (; *addr != '\0'; addr++)
{
- if ((*addr & 0340) == 0200)
+ if (!EightBitAddrOK && (*addr & 0340) == 0200)
{
setstat(EX_USAGE);
result = true;
@@ -345,7 +349,7 @@ hasctrlchar(addr, isrcpt, complain)
}
result = "too long";
}
- if (!quoted && (*addr < 32 || *addr == 127))
+ if (!EightBitAddrOK && !quoted && (*addr < 32 || *addr == 127))
{
result = "non-printable character";
*addr = BAD_CHAR_REPLACEMENT;
@@ -363,7 +367,7 @@ hasctrlchar(addr, isrcpt, complain)
break;
}
}
- if ((*addr & 0340) == 0200)
+ if (!EightBitAddrOK && (*addr & 0340) == 0200)
{
setstat(EX_USAGE);
result = "8-bit character";
@@ -431,6 +435,7 @@ allocaddr(a, flags, paddr, e)
a->q_paddr = sm_rpool_strdup_x(e->e_rpool, a->q_user);
a->q_qgrp = NOAQGRP;
}
+
/*
** PRESCAN -- Prescan name and make it canonical
**
@@ -491,11 +496,51 @@ static short StateTab[NSTATES][NSTATES] =
/*QST*/ { QST, QST, OPR, QST, QST, QST },
/*SPC*/ { OPR, ATM, QST, SPC|M, ONE, ILL|MB },
/*ONE*/ { OPR, OPR, OPR, OPR, OPR, ILL|MB },
- /*ILL*/ { OPR|B, ATM|B, QST|B, SPC|MB, ONE|B, ILL|M },
+ /*ILL*/ { OPR|B, ATM|B, QST|B, SPC|MB, ONE|B, ILL|M }
};
-/* token type table -- it gets modified with $o characters */
-static unsigned char TokTypeTab[256] =
+/* these all get modified with the OperatorChars */
+
+/* token type table for external strings */
+unsigned char ExtTokenTab[256] =
+{
+ /* nul soh stx etx eot enq ack bel bs ht nl vt np cr so si */
+ ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,SPC,SPC,SPC,SPC,SPC,ATM,ATM,
+ /* dle dc1 dc2 dc3 dc4 nak syn etb can em sub esc fs gs rs us */
+ ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,
+ /* sp ! " # $ % & ' ( ) * + , - . / */
+ SPC,ATM,QST,ATM,ATM,ATM,ATM,ATM, SPC,SPC,ATM,ATM,ATM,ATM,ATM,ATM,
+ /* 0 1 2 3 4 5 6 7 8 9 : ; < = > ? */
+ ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,
+ /* @ A B C D E F G H I J K L M N O */
+ ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,
+ /* P Q R S T U V W X Y Z [ \ ] ^ _ */
+ ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,
+ /* ` a b c d e f g h i j k l m n o */
+ ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,
+ /* p q r s t u v w x y z { | } ~ del */
+ ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,
+
+ /* nul soh stx etx eot enq ack bel bs ht nl vt np cr so si */
+ ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,
+ /* dle dc1 dc2 dc3 dc4 nak syn etb can em sub esc fs gs rs us */
+ ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,
+ /* sp ! " # $ % & ' ( ) * + , - . / */
+ ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,
+ /* 0 1 2 3 4 5 6 7 8 9 : ; < = > ? */
+ ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,
+ /* @ A B C D E F G H I J K L M N O */
+ ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,
+ /* P Q R S T U V W X Y Z [ \ ] ^ _ */
+ ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,
+ /* ` a b c d e f g h i j k l m n o */
+ ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,
+ /* p q r s t u v w x y z { | } ~ del */
+ ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM
+};
+
+/* token type table for internal strings */
+unsigned char IntTokenTab[256] =
{
/* nul soh stx etx eot enq ack bel bs ht nl vt np cr so si */
ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,SPC,SPC,SPC,SPC,SPC,ATM,ATM,
@@ -529,7 +574,7 @@ static unsigned char TokTypeTab[256] =
/* ` a b c d e f g h i j k l m n o */
ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,
/* p q r s t u v w x y z { | } ~ del */
- ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,
+ ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ONE
};
/* token type table for MIME parsing */
@@ -567,7 +612,7 @@ unsigned char MimeTokenTab[256] =
/* ` a b c d e f g h i j k l m n o */
ILL,ILL,ILL,ILL,ILL,ILL,ILL,ILL, ILL,ILL,ILL,ILL,ILL,ILL,ILL,ILL,
/* p q r s t u v w x y z { | } ~ del */
- ILL,ILL,ILL,ILL,ILL,ILL,ILL,ILL, ILL,ILL,ILL,ILL,ILL,ILL,ILL,ILL,
+ ILL,ILL,ILL,ILL,ILL,ILL,ILL,ILL, ILL,ILL,ILL,ILL,ILL,ILL,ILL,ONE
};
/* token type table: don't strip comments */
@@ -605,7 +650,7 @@ unsigned char TokTypeNoC[256] =
/* ` a b c d e f g h i j k l m n o */
ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,
/* p q r s t u v w x y z { | } ~ del */
- ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,
+ ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ONE
};
@@ -649,19 +694,21 @@ prescan(addr, delim, pvpbuf, pvpbsize, delimptr, toktab, ignore)
if (OperatorChars == NULL)
OperatorChars = ".:@[]";
}
- expand(OperatorChars, obuf, sizeof obuf - sizeof DELIMCHARS,
+ expand(OperatorChars, obuf, sizeof(obuf) - sizeof(DELIMCHARS),
CurEnv);
- (void) sm_strlcat(obuf, DELIMCHARS, sizeof obuf);
+ (void) sm_strlcat(obuf, DELIMCHARS, sizeof(obuf));
for (p = obuf; *p != '\0'; p++)
{
- if (TokTypeTab[*p & 0xff] == ATM)
- TokTypeTab[*p & 0xff] = OPR;
+ if (IntTokenTab[*p & 0xff] == ATM)
+ IntTokenTab[*p & 0xff] = OPR;
+ if (ExtTokenTab[*p & 0xff] == ATM)
+ ExtTokenTab[*p & 0xff] = OPR;
if (TokTypeNoC[*p & 0xff] == ATM)
TokTypeNoC[*p & 0xff] = OPR;
}
}
if (toktab == NULL)
- toktab = TokTypeTab;
+ toktab = ExtTokenTab;
/* make sure error messages don't have garbage on them */
errno = 0;
@@ -712,7 +759,8 @@ prescan(addr, delim, pvpbuf, pvpbsize, delimptr, toktab, ignore)
/* squirrel it away */
#if !ALLOW_255
- if ((char) c == (char) -1 && !tTd(82, 101))
+ if ((char) c == (char) -1 && !tTd(82, 101) &&
+ !EightBitAddrOK)
c &= 0x7f;
#endif /* !ALLOW_255 */
*q++ = c;
@@ -995,7 +1043,7 @@ rewrite(pvp, ruleset, reclevel, e, maxatom)
rulename = RuleSetNames[ruleset];
if (rulename == NULL)
{
- (void) sm_snprintf(name, sizeof name, "%d", ruleset);
+ (void) sm_snprintf(name, sizeof(name), "%d", ruleset);
rulename = name;
}
if (OpMode == MD_TEST)
@@ -1081,14 +1129,15 @@ rewrite(pvp, ruleset, reclevel, e, maxatom)
/* end-of-pattern before end-of-address */
goto backup;
}
- if (ap == NULL && (*rp & 0377) != MATCHZANY &&
- (*rp & 0377) != MATCHZERO)
+ if (ap == NULL &&
+ (rp[0] & 0377) != MATCHZANY &&
+ (rp[0] & 0377) != MATCHZERO)
{
/* end-of-input with patterns left */
goto backup;
}
- switch (*rp & 0377)
+ switch (rp[0] & 0377)
{
case MATCHCLASS:
/* match any phrase in a class */
@@ -1100,7 +1149,7 @@ rewrite(pvp, ruleset, reclevel, e, maxatom)
goto backup;
mlp->match_last = avp++;
cataddr(mlp->match_first, mlp->match_last,
- buf, sizeof buf, '\0');
+ buf, sizeof(buf), '\0', true);
if (!wordinclass(buf, rp[1]))
{
if (tTd(21, 36))
@@ -1215,8 +1264,9 @@ rewrite(pvp, ruleset, reclevel, e, maxatom)
/* run off the end -- back up again */
continue;
}
- if ((*rp & 0377) == MATCHANY ||
- (*rp & 0377) == MATCHZANY)
+
+ if ((rp[0] & 0377) == MATCHANY ||
+ (rp[0] & 0377) == MATCHZANY)
{
/* extend binding and continue */
mlp->match_last = avp++;
@@ -1224,7 +1274,7 @@ rewrite(pvp, ruleset, reclevel, e, maxatom)
mlp++;
break;
}
- if ((*rp & 0377) == MATCHCLASS)
+ if ((rp[0] & 0377) == MATCHCLASS)
{
/* extend binding and try again */
mlp->match_last = avp;
@@ -1263,14 +1313,14 @@ rewrite(pvp, ruleset, reclevel, e, maxatom)
rp = *rvp;
if (rp != NULL)
{
- if ((*rp & 0377) == CANONUSER)
+ if ((rp[0] & 0377) == CANONUSER)
{
rvp++;
rwr = rwr->r_next;
ruleno++;
loopcount = 0;
}
- else if ((*rp & 0377) == CANONHOST)
+ else if ((rp[0] & 0377) == CANONHOST)
{
rvp++;
rwr = NULL;
@@ -1284,7 +1334,7 @@ rewrite(pvp, ruleset, reclevel, e, maxatom)
register char **pp;
rp = *rvp;
- if ((*rp & 0377) == MATCHREPL)
+ if ((rp[0] & 0377) == MATCHREPL)
{
/* substitute from LHS */
m = &mlist[rp[1] - '1'];
@@ -1327,9 +1377,9 @@ rewrite(pvp, ruleset, reclevel, e, maxatom)
rulename, ruleno);
return EX_DATAERR;
}
- if ((*rp & 0377) != MACRODEXPAND)
+ if ((rp[0] & 0377) != MACRODEXPAND)
{
- /* vanilla replacement */
+ /* vanilla replacement from RHS */
*avp++ = rp;
}
else
@@ -1351,7 +1401,7 @@ rewrite(pvp, ruleset, reclevel, e, maxatom)
/* save the remainder of the input */
for (xpvp = pvp; *xpvp != NULL; xpvp++)
- trsize += sizeof *xpvp;
+ trsize += sizeof(*xpvp);
if (trsize > pvpb1_size)
{
if (pvpb1 != NULL)
@@ -1367,7 +1417,7 @@ rewrite(pvp, ruleset, reclevel, e, maxatom)
/* scan the new replacement */
xpvp = prescan(mval, '\0', pvpbuf,
- sizeof pvpbuf, NULL,
+ sizeof(pvpbuf), NULL,
NULL, false);
if (xpvp == NULL)
{
@@ -1421,23 +1471,13 @@ rewrite(pvp, ruleset, reclevel, e, maxatom)
char pvpbuf[PSBUFSIZE];
char *nullpvp[1];
- if ((**rvp & 0377) != HOSTBEGIN &&
- (**rvp & 0377) != LOOKUPBEGIN)
- continue;
-
- /*
- ** Got a hostname/keyword lookup.
- **
- ** This could be optimized fairly easily.
- */
-
hbrvp = rvp;
- if ((**rvp & 0377) == HOSTBEGIN)
+ if ((rvp[0][0] & 0377) == HOSTBEGIN)
{
endtoken = HOSTEND;
mapname = "host";
}
- else
+ else if ((rvp[0][0] & 0377) == LOOKUPBEGIN)
{
endtoken = LOOKUPEND;
mapname = *++rvp;
@@ -1448,6 +1488,15 @@ rewrite(pvp, ruleset, reclevel, e, maxatom)
SM_ASSERT(0);
}
}
+ else
+ continue;
+
+ /*
+ ** Got a hostname/keyword lookup.
+ **
+ ** This could be optimized fairly easily.
+ */
+
map = stab(mapname, ST_MAP, ST_FIND);
if (map == NULL)
syserr("554 5.3.0 rewrite: map %s not found",
@@ -1466,9 +1515,9 @@ rewrite(pvp, ruleset, reclevel, e, maxatom)
arg_rvp = argvect;
xpvp = NULL;
replac = pvpbuf;
- while (*rvp != NULL && (**rvp & 0377) != endtoken)
+ while (*rvp != NULL && ((rvp[0][0] & 0377) != endtoken))
{
- int nodetype = **rvp & 0377;
+ int nodetype = rvp[0][0] & 0377;
if (nodetype != CANONHOST &&
nodetype != CANONUSER)
@@ -1482,8 +1531,8 @@ rewrite(pvp, ruleset, reclevel, e, maxatom)
if (xpvp != NULL)
{
cataddr(xpvp, NULL, replac,
- &pvpbuf[sizeof pvpbuf] - replac,
- '\0');
+ &pvpbuf[sizeof(pvpbuf)] - replac,
+ '\0', false);
if (arg_rvp <
&argvect[MAX_MAP_ARGS - 1])
*++arg_rvp = replac;
@@ -1506,8 +1555,8 @@ rewrite(pvp, ruleset, reclevel, e, maxatom)
if (xpvp != NULL)
{
cataddr(xpvp, NULL, replac,
- &pvpbuf[sizeof pvpbuf] - replac,
- '\0');
+ &pvpbuf[sizeof(pvpbuf)] - replac,
+ '\0', false);
if (arg_rvp < &argvect[MAX_MAP_ARGS - 1])
*++arg_rvp = replac;
}
@@ -1517,12 +1566,13 @@ rewrite(pvp, ruleset, reclevel, e, maxatom)
*++arg_rvp = NULL;
/* save the remainder of the input string */
- trsize = (avp - rvp + 1) * sizeof *rvp;
+ trsize = (avp - rvp + 1) * sizeof(*rvp);
memmove((char *) pvpb1, (char *) rvp, trsize);
/* look it up */
- cataddr(key_rvp, NULL, cbuf, sizeof cbuf,
- map == NULL ? '\0' : map->s_map.map_spacesub);
+ cataddr(key_rvp, NULL, cbuf, sizeof(cbuf),
+ map == NULL ? '\0' : map->s_map.map_spacesub,
+ true);
argvect[0] = cbuf;
replac = map_lookup(map, cbuf, argvect, &rstat, e);
@@ -1530,8 +1580,8 @@ rewrite(pvp, ruleset, reclevel, e, maxatom)
if (replac == NULL && default_rvp != NULL)
{
/* create the default */
- cataddr(default_rvp, NULL, cbuf, sizeof cbuf,
- '\0');
+ cataddr(default_rvp, NULL, cbuf, sizeof(cbuf),
+ '\0', false);
replac = cbuf;
}
@@ -1549,7 +1599,8 @@ rewrite(pvp, ruleset, reclevel, e, maxatom)
{
/* scan the new replacement */
xpvp = prescan(replac, '\0', pvpbuf,
- sizeof pvpbuf, NULL, NULL, false);
+ sizeof(pvpbuf), NULL, NULL,
+ false);
if (xpvp == NULL)
{
/* prescan already printed error */
@@ -1584,7 +1635,7 @@ rewrite(pvp, ruleset, reclevel, e, maxatom)
for (avp = npvp; *avp++ != NULL;)
continue;
memmove((char *) pvp, (char *) npvp,
- (int) (avp - npvp) * sizeof *avp);
+ (int) (avp - npvp) * sizeof(*avp));
if (tTd(21, 4))
{
@@ -1648,7 +1699,7 @@ callsubr(pvp, reclevel, e)
for (avp = pvp, j = 0; *avp != NULL; avp++, j++)
{
- if ((**avp & 0377) == CALLSUBR && avp[1] != NULL)
+ if ((avp[0][0] & 0377) == CALLSUBR && avp[1] != NULL)
{
stripquotes(avp[1]);
subr = strtorwset(avp[1], NULL, ST_FIND);
@@ -1767,7 +1818,8 @@ map_lookup(smap, key, argvect, pstat, e)
if (tTd(60, 1))
{
- sm_dprintf("map_lookup(%s, %s", smap->s_name, key);
+ sm_dprintf("map_lookup(%s, ", smap->s_name);
+ xputs(sm_debug_file(), key);
if (tTd(60, 5))
{
int i;
@@ -1794,7 +1846,7 @@ map_lookup(smap, key, argvect, pstat, e)
{
char mbuf[320];
- (void) sm_snprintf(mbuf, sizeof mbuf,
+ (void) sm_snprintf(mbuf, sizeof(mbuf),
"%.80s map: lookup (%s): deferred",
smap->s_name,
shortenstring(key, MAXSHORTSTR));
@@ -1919,8 +1971,8 @@ buildaddr(tv, a, flags, e)
maxatom = MAXATOM;
if (a == NULL)
- a = (ADDRESS *) sm_rpool_malloc_x(e->e_rpool, sizeof *a);
- memset((char *) a, '\0', sizeof *a);
+ a = (ADDRESS *) sm_rpool_malloc_x(e->e_rpool, sizeof(*a));
+ memset((char *) a, '\0', sizeof(*a));
hbuf[0] = '\0';
/* set up default error return flags */
@@ -1976,8 +2028,8 @@ buildaddr(tv, a, flags, e)
if (tv == hostp)
hostp = NULL;
else if (hostp != NULL)
- cataddr(hostp, tv - 1, hbuf, sizeof hbuf, '\0');
- cataddr(++tv, NULL, ubuf, sizeof ubuf, ' ');
+ cataddr(hostp, tv - 1, hbuf, sizeof(hbuf), '\0', false);
+ cataddr(++tv, NULL, ubuf, sizeof(ubuf), ' ', false);
--maxatom;
/* save away the host name */
@@ -2032,7 +2084,7 @@ buildaddr(tv, a, flags, e)
off = 4;
ubuf[3] = '\0';
}
- (void) sm_strlcpyn(fmt, sizeof fmt, 2, ubuf, " %s");
+ (void) sm_strlcpyn(fmt, sizeof(fmt), 2, ubuf, " %s");
if (off > 4)
usrerr(fmt, ubuf + off);
else if (isenhsc(hbuf, '\0') > 0)
@@ -2119,7 +2171,7 @@ buildaddr(tv, a, flags, e)
(void) rewrite(tv, 4, 0, e, maxatom);
/* save the result for the command line/RCPT argument */
- cataddr(tv, NULL, ubuf, sizeof ubuf, '\0');
+ cataddr(tv, NULL, ubuf, sizeof(ubuf), '\0', true);
a->q_user = sm_rpool_strdup_x(e->e_rpool, ubuf);
/*
@@ -2150,26 +2202,49 @@ buildaddr(tv, a, flags, e)
** sz -- size of buf.
** spacesub -- the space separator character; if '\0',
** use SpaceSub.
+** external -- convert to external form?
+** (no metacharacters; METAQUOTEs removed, see below)
**
** Returns:
** none.
**
** Side Effects:
** Destroys buf.
+**
+** Notes:
+** There are two formats for strings: internal and external.
+** The external format is just an eight-bit clean string (no
+** null bytes, everything else OK). The internal format can
+** include sendmail metacharacters. The special character
+** METAQUOTE essentially quotes the character following, stripping
+** it of all special semantics.
+**
+** The cataddr routine needs to be aware of whether it is producing
+** an internal or external form as output (it only takes internal
+** form as input).
+**
+** The parseaddr routine has a similar issue on input, but that
+** is flagged on the basis of which token table is passed in.
*/
void
-cataddr(pvp, evp, buf, sz, spacesub)
+cataddr(pvp, evp, buf, sz, spacesub, external)
char **pvp;
char **evp;
char *buf;
register int sz;
int spacesub;
+ bool external;
{
- bool oatomtok = false;
- bool natomtok = false;
- register int i;
- register char *p;
+ bool oatomtok, natomtok;
+ char *p;
+
+ oatomtok = natomtok = false;
+ if (tTd(59, 14))
+ {
+ sm_dprintf("cataddr(%d) <==", external);
+ printav(sm_debug_file(), pvp);
+ }
if (sz <= 0)
return;
@@ -2186,19 +2261,37 @@ cataddr(pvp, evp, buf, sz, spacesub)
sz -= 2;
while (*pvp != NULL && sz > 0)
{
- natomtok = (TokTypeTab[**pvp & 0xff] == ATM);
+ char *q;
+
+ natomtok = (ExtTokenTab[**pvp & 0xff] == ATM);
if (oatomtok && natomtok)
{
*p++ = spacesub;
if (--sz <= 0)
break;
}
- i = sm_strlcpy(p, *pvp, sz);
- sz -= i;
+ for (q = *pvp; *q != '\0'; )
+ {
+ int c;
+
+ if (--sz <= 0)
+ break;
+ *p++ = c = *q++;
+
+ /*
+ ** If the current character (c) is METAQUOTE and we
+ ** want the "external" form and the next character
+ ** is not NUL, then overwrite METAQUOTE with that
+ ** character (i.e., METAQUOTE ch is changed to
+ ** ch). p[-1] is used because p is advanced (above).
+ */
+
+ if ((c & 0377) == METAQUOTE && external && *q != '\0')
+ p[-1] = *q++;
+ }
if (sz <= 0)
break;
oatomtok = natomtok;
- p += i;
if (pvp++ == evp)
break;
}
@@ -2220,7 +2313,11 @@ cataddr(pvp, evp, buf, sz, spacesub)
usrerr("cataddr: string too long");
#endif
*p = '\0';
+
+ if (tTd(59, 14))
+ sm_dprintf(" cataddr => %s\n", str2prt(buf));
}
+
/*
** SAMEADDR -- Determine if two addresses are the same
**
@@ -2544,7 +2641,11 @@ remotename(name, m, flags, pstat, e)
char addrtype[4];
if (tTd(12, 1))
- sm_dprintf("remotename(%s)\n", name);
+ {
+ sm_dprintf("remotename(");
+ xputs(sm_debug_file(), name);
+ sm_dprintf(")\n");
+ }
/* don't do anything if we are tagging it as special */
if (bitset(RF_SENDERADDR, flags))
@@ -2584,7 +2685,7 @@ remotename(name, m, flags, pstat, e)
** domain will be appended.
*/
- pvp = prescan(name, '\0', pvpbuf, sizeof pvpbuf, NULL, NULL, false);
+ pvp = prescan(name, '\0', pvpbuf, sizeof(pvpbuf), NULL, NULL, false);
if (pvp == NULL)
return name;
if (REWRITE(pvp, 3, e) == EX_TEMPFAIL)
@@ -2658,22 +2759,26 @@ remotename(name, m, flags, pstat, e)
** Now restore the comment information we had at the beginning.
*/
- cataddr(pvp, NULL, lbuf, sizeof lbuf, '\0');
+ cataddr(pvp, NULL, lbuf, sizeof(lbuf), '\0', false);
oldg = macget(&e->e_macro, 'g');
macset(&e->e_macro, 'g', lbuf);
SM_TRY
/* need to make sure route-addrs have */
if (bitset(RF_CANONICAL, flags) && lbuf[0] == '@')
- expand("<\201g>", buf, sizeof buf, e);
+ expand("<\201g>", buf, sizeof(buf), e);
else
- expand(fancy, buf, sizeof buf, e);
+ expand(fancy, buf, sizeof(buf), e);
SM_FINALLY
macset(&e->e_macro, 'g', oldg);
SM_END_TRY
if (tTd(12, 1))
- sm_dprintf("remotename => `%s'\n", buf);
+ {
+ sm_dprintf("remotename => `");
+ xputs(sm_debug_file(), buf);
+ sm_dprintf("'\n");
+ }
return buf;
}
/*
@@ -2711,7 +2816,8 @@ maplocaluser(a, sendq, aliaslevel, e)
sm_dprintf("maplocaluser: ");
printaddr(sm_debug_file(), a, false);
}
- pvp = prescan(a->q_user, '\0', pvpbuf, sizeof pvpbuf, NULL, NULL, false);
+ pvp = prescan(a->q_user, '\0', pvpbuf, sizeof(pvpbuf), NULL, NULL,
+ false);
if (pvp == NULL)
{
if (tTd(29, 9))
@@ -2940,6 +3046,8 @@ dequote_map(map, name, av, statp)
** logl -- logging level.
** host -- NULL or relay host.
** logid -- id for sm_syslog.
+** addr -- if not NULL and ruleset returns $#error:
+** store mailer triple here.
**
** Returns:
** EX_OK -- if the rwset doesn't resolve to $#error
@@ -2947,7 +3055,7 @@ dequote_map(map, name, av, statp)
*/
int
-rscheck(rwset, p1, p2, e, flags, logl, host, logid)
+rscheck(rwset, p1, p2, e, flags, logl, host, logid, addr)
char *rwset;
char *p1;
char *p2;
@@ -2956,6 +3064,7 @@ rscheck(rwset, p1, p2, e, flags, logl, host, logid)
int logl;
char *host;
char *logid;
+ ADDRESS *addr;
{
char *volatile buf;
size_t bufsize;
@@ -2964,7 +3073,6 @@ rscheck(rwset, p1, p2, e, flags, logl, host, logid)
char **pvp;
int rsno;
bool volatile discard = false;
- auto ADDRESS a1;
bool saveQuickAbort = QuickAbort;
bool saveSuprErrs = SuprErrs;
bool quarantine = false;
@@ -2984,24 +3092,24 @@ rscheck(rwset, p1, p2, e, flags, logl, host, logid)
if (p2 != NULL)
{
bufsize = strlen(p1) + strlen(p2) + 2;
- if (bufsize > sizeof buf0)
+ if (bufsize > sizeof(buf0))
buf = sm_malloc_x(bufsize);
else
{
buf = buf0;
- bufsize = sizeof buf0;
+ bufsize = sizeof(buf0);
}
(void) sm_snprintf(buf, bufsize, "%s%c%s", p1, CONDELSE, p2);
}
else
{
bufsize = strlen(p1) + 1;
- if (bufsize > sizeof buf0)
+ if (bufsize > sizeof(buf0))
buf = sm_malloc_x(bufsize);
else
{
buf = buf0;
- bufsize = sizeof buf0;
+ bufsize = sizeof(buf0);
}
(void) sm_strlcpy(buf, p1, bufsize);
}
@@ -3009,8 +3117,9 @@ rscheck(rwset, p1, p2, e, flags, logl, host, logid)
{
SuprErrs = true;
QuickAbort = false;
- pvp = prescan(buf, '\0', pvpbuf, sizeof pvpbuf, NULL,
- bitset(RSF_RMCOMM, flags) ? NULL : TokTypeNoC,
+ pvp = prescan(buf, '\0', pvpbuf, sizeof(pvpbuf), NULL,
+ bitset(RSF_RMCOMM, flags) ?
+ IntTokenTab : TokTypeNoC,
bitset(RSF_RMCOMM, flags) ? false : true);
SuprErrs = saveSuprErrs;
if (pvp == NULL)
@@ -3055,7 +3164,7 @@ rscheck(rwset, p1, p2, e, flags, logl, host, logid)
else
{
cataddr(&(pvp[5]), NULL, ubuf,
- sizeof ubuf, ' ');
+ sizeof(ubuf), ' ', true);
e->e_quarmsg = sm_rpool_strdup_x(e->e_rpool,
ubuf);
}
@@ -3065,6 +3174,7 @@ rscheck(rwset, p1, p2, e, flags, logl, host, logid)
}
else
{
+ auto ADDRESS a1;
int savelogusrerrs = LogUsrErrs;
static bool logged = false;
@@ -3072,6 +3182,12 @@ rscheck(rwset, p1, p2, e, flags, logl, host, logid)
saveexitstat = ExitStat;
LogUsrErrs = false;
(void) buildaddr(pvp, &a1, 0, e);
+ if (addr != NULL)
+ {
+ addr->q_mailer = a1.q_mailer;
+ addr->q_user = a1.q_user;
+ addr->q_host = a1.q_host;
+ }
LogUsrErrs = savelogusrerrs;
rstat = ExitStat;
ExitStat = saveexitstat;
@@ -3192,24 +3308,24 @@ rscap(rwset, p1, p2, e, pvp, pvpbuf, size)
if (p2 != NULL)
{
bufsize = strlen(p1) + strlen(p2) + 2;
- if (bufsize > sizeof buf0)
+ if (bufsize > sizeof(buf0))
buf = sm_malloc_x(bufsize);
else
{
buf = buf0;
- bufsize = sizeof buf0;
+ bufsize = sizeof(buf0);
}
(void) sm_snprintf(buf, bufsize, "%s%c%s", p1, CONDELSE, p2);
}
else
{
bufsize = strlen(p1) + 1;
- if (bufsize > sizeof buf0)
+ if (bufsize > sizeof(buf0))
buf = sm_malloc_x(bufsize);
else
{
buf = buf0;
- bufsize = sizeof buf0;
+ bufsize = sizeof(buf0);
}
(void) sm_strlcpy(buf, p1, bufsize);
}
@@ -3217,7 +3333,8 @@ rscap(rwset, p1, p2, e, pvp, pvpbuf, size)
{
SuprErrs = true;
QuickAbort = false;
- *pvp = prescan(buf, '\0', pvpbuf, size, NULL, NULL, false);
+ *pvp = prescan(buf, '\0', pvpbuf, size, NULL, IntTokenTab,
+ false);
if (*pvp != NULL)
rstat = rewrite(*pvp, rsno, 0, e, size);
else
diff --git a/contrib/sendmail/src/queue.c b/contrib/sendmail/src/queue.c
index 6fd23158ad4e..e0919d5df8ff 100644
--- a/contrib/sendmail/src/queue.c
+++ b/contrib/sendmail/src/queue.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998-2006 Sendmail, Inc. and its suppliers.
+ * Copyright (c) 1998-2007 Sendmail, Inc. and its suppliers.
* All rights reserved.
* Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved.
* Copyright (c) 1988, 1993
@@ -14,7 +14,7 @@
#include
#include
-SM_RCSID("@(#)$Id: queue.c,v 8.954.2.5 2006/07/31 21:44:18 ca Exp $")
+SM_RCSID("@(#)$Id: queue.c,v 8.972 2007/03/29 22:55:17 ca Exp $")
#include
@@ -147,6 +147,13 @@ static ADDRESS *setctluser __P((char *, int, ENVELOPE *));
static int sm_strshufflecmp __P((char *, char *));
static void init_shuffle_alphabet __P(());
#endif /* _FFR_RHS */
+
+/*
+** Note: workcmpf?() don't use a prototype because it will cause a conflict
+** with the qsort() call (which expects something like
+** int (*compar)(const void *, const void *), not (WORK *, WORK *))
+*/
+
static int workcmpf0();
static int workcmpf1();
static int workcmpf2();
@@ -182,7 +189,7 @@ struct filesys_shared
/* probably kept in shared memory */
static FILESYS FileSys[MAXFILESYS]; /* queue file systems */
-static char *FSPath[MAXFILESYS]; /* pathnames for file systems */
+static const char *FSPath[MAXFILESYS]; /* pathnames for file systems */
#if SM_CONF_SHM
@@ -373,7 +380,7 @@ queueup(e, announce, msync)
newid = (e->e_id == NULL) || !bitset(EF_INQUEUE, e->e_flags);
- (void) sm_strlcpy(tf, queuename(e, NEWQFL_LETTER), sizeof tf);
+ (void) sm_strlcpy(tf, queuename(e, NEWQFL_LETTER), sizeof(tf));
tfp = e->e_lockfp;
if (tfp == NULL && newid)
{
@@ -383,7 +390,7 @@ queueup(e, announce, msync)
** is reused (e.g., because the clock is set back).
*/
- (void) sm_strlcpy(tf, queuename(e, ANYQFL_LETTER), sizeof tf);
+ (void) sm_strlcpy(tf, queuename(e, ANYQFL_LETTER), sizeof(tf));
OPEN_TF;
if (tfd < 0 ||
#if !SM_OPEN_EXLOCK
@@ -502,7 +509,7 @@ queueup(e, announce, msync)
** If there is no data file yet, create one.
*/
- (void) sm_strlcpy(df, queuename(e, DATAFL_LETTER), sizeof df);
+ (void) sm_strlcpy(df, queuename(e, DATAFL_LETTER), sizeof(df));
if (bitset(EF_HAS_DF, e->e_flags))
{
if (e->e_dfp != NULL &&
@@ -563,7 +570,7 @@ queueup(e, announce, msync)
e->e_dfino = ST_INODE(stbuf);
}
e->e_flags |= EF_HAS_DF;
- memset(&mcibuf, '\0', sizeof mcibuf);
+ memset(&mcibuf, '\0', sizeof(mcibuf));
mcibuf.mci_out = dfp;
mcibuf.mci_mailer = FileMailer;
(*e->e_putbody)(&mcibuf, e, NULL);
@@ -764,11 +771,11 @@ queueup(e, announce, msync)
** no effect on the addresses as they are output.
*/
- memset((char *) &nullmailer, '\0', sizeof nullmailer);
+ memset((char *) &nullmailer, '\0', sizeof(nullmailer));
nullmailer.m_re_rwset = nullmailer.m_rh_rwset =
nullmailer.m_se_rwset = nullmailer.m_sh_rwset = -1;
nullmailer.m_eol = "\n";
- memset(&mcibuf, '\0', sizeof mcibuf);
+ memset(&mcibuf, '\0', sizeof(mcibuf));
mcibuf.mci_mailer = &nullmailer;
mcibuf.mci_out = tfp;
@@ -786,9 +793,11 @@ queueup(e, announce, msync)
/* expand macros; if null, don't output header at all */
if (bitset(H_DEFAULT, h->h_flags))
{
- (void) expand(h->h_value, buf, sizeof buf, e);
+ (void) expand(h->h_value, buf, sizeof(buf), e);
if (buf[0] == '\0')
continue;
+ if (buf[0] == ' ' && buf[1] == '\0')
+ continue;
}
/* output this header */
@@ -822,7 +831,7 @@ queueup(e, announce, msync)
if (bitset(H_DEFAULT, h->h_flags) &&
!bitset(H_BINDLATE, h->h_flags))
{
- (void) sm_io_fprintf(tfp, SM_TIME_DEFAULT, "%s: %s\n",
+ (void) sm_io_fprintf(tfp, SM_TIME_DEFAULT, "%s:%s\n",
h->h_field,
denlstring(buf, false, true));
}
@@ -843,7 +852,7 @@ queueup(e, announce, msync)
}
else
{
- (void) sm_io_fprintf(tfp, SM_TIME_DEFAULT, "%s: %s\n",
+ (void) sm_io_fprintf(tfp, SM_TIME_DEFAULT, "%s:%s\n",
h->h_field,
denlstring(h->h_value, false,
true));
@@ -878,7 +887,7 @@ queueup(e, announce, msync)
/* rename (locked) tf to be (locked) [qh]f */
(void) sm_strlcpy(qf, queuename(e, ANYQFL_LETTER),
- sizeof qf);
+ sizeof(qf));
if (rename(tf, qf) < 0)
syserr("cannot rename(%s, %s), uid=%d",
tf, qf, (int) geteuid());
@@ -1870,7 +1879,6 @@ run_work_group(wgrp, flags)
time_t now;
bool full, more;
SM_RPOOL_T *rpool;
- extern void rmexpstab __P((void));
extern ENVELOPE BlankEnvelope;
extern SIGFUNC_DECL reapchild __P((int));
@@ -2476,9 +2484,9 @@ gatherq(qgrp, qdir, doall, full, more)
wn = WorkListCount - 1;
num_ent = 0;
if (qdir == NOQDIR)
- (void) sm_strlcpy(qd, ".", sizeof qd);
+ (void) sm_strlcpy(qd, ".", sizeof(qd));
else
- (void) sm_strlcpyn(qd, sizeof qd, 2,
+ (void) sm_strlcpyn(qd, sizeof(qd), 2,
Queue[qgrp]->qg_qpaths[qdir].qp_name,
(bitset(QP_SUBQF,
Queue[qgrp]->qg_qpaths[qdir].qp_subdirs)
@@ -2617,7 +2625,7 @@ gatherq(qgrp, qdir, doall, full, more)
SM_ASSERT(wn >= 0);
w = &WorkList[wn];
- (void) sm_strlcpyn(qf, sizeof qf, 3, qd, "/", d->d_name);
+ (void) sm_strlcpyn(qf, sizeof(qf), 3, qd, "/", d->d_name);
if (stat(qf, &sbuf) < 0)
{
if (errno != ENOENT)
@@ -2714,7 +2722,7 @@ gatherq(qgrp, qdir, doall, full, more)
i |= NEED_QUARANTINE;
while (cf != NULL && i != 0 &&
sm_io_fgets(cf, SM_TIME_DEFAULT, lbuf,
- sizeof lbuf) != NULL)
+ sizeof(lbuf)) != NULL)
{
int c;
time_t age;
@@ -2947,7 +2955,7 @@ sortq(max)
** based on host name, lock status, and priority.
*/
- qsort((char *) WorkList, wc, sizeof *WorkList, workcmpf1);
+ qsort((char *) WorkList, wc, sizeof(*WorkList), workcmpf1);
/*
** If one message to host is locked, "lock" all messages
@@ -2983,7 +2991,7 @@ sortq(max)
** based on lock status, host name, and priority.
*/
- qsort((char *) WorkList, wc, sizeof *WorkList, workcmpf2);
+ qsort((char *) WorkList, wc, sizeof(*WorkList), workcmpf2);
}
else if (QueueSortOrder == QSO_BYTIME)
{
@@ -2991,7 +2999,7 @@ sortq(max)
** Simple sort based on submission time only.
*/
- qsort((char *) WorkList, wc, sizeof *WorkList, workcmpf3);
+ qsort((char *) WorkList, wc, sizeof(*WorkList), workcmpf3);
}
else if (QueueSortOrder == QSO_BYFILENAME)
{
@@ -2999,7 +3007,7 @@ sortq(max)
** Sort based on queue filename.
*/
- qsort((char *) WorkList, wc, sizeof *WorkList, workcmpf4);
+ qsort((char *) WorkList, wc, sizeof(*WorkList), workcmpf4);
}
else if (QueueSortOrder == QSO_RANDOM)
{
@@ -3012,7 +3020,7 @@ sortq(max)
randi = get_rand_mod(MAXQFNAME);
if (randi < 2)
randi = 3;
- qsort((char *) WorkList, wc, sizeof *WorkList, workcmpf5);
+ qsort((char *) WorkList, wc, sizeof(*WorkList), workcmpf5);
}
else if (QueueSortOrder == QSO_BYMODTIME)
{
@@ -3021,7 +3029,7 @@ sortq(max)
** This puts the oldest items first.
*/
- qsort((char *) WorkList, wc, sizeof *WorkList, workcmpf6);
+ qsort((char *) WorkList, wc, sizeof(*WorkList), workcmpf6);
}
#if _FFR_RHS
else if (QueueSortOrder == QSO_BYSHUFFLE)
@@ -3031,7 +3039,7 @@ sortq(max)
*/
init_shuffle_alphabet();
- qsort((char *) WorkList, wc, sizeof *WorkList, workcmpf7);
+ qsort((char *) WorkList, wc, sizeof(*WorkList), workcmpf7);
}
#endif /* _FFR_RHS */
else if (QueueSortOrder == QSO_BYPRIORITY)
@@ -3040,7 +3048,7 @@ sortq(max)
** Simple sort based on queue priority only.
*/
- qsort((char *) WorkList, wc, sizeof *WorkList, workcmpf0);
+ qsort((char *) WorkList, wc, sizeof(*WorkList), workcmpf0);
}
/* else don't sort at all */
@@ -3057,7 +3065,7 @@ sortq(max)
for (i = wc; --i >= 0; )
{
- w = (WORK *) xalloc(sizeof *w);
+ w = (WORK *) xalloc(sizeof(*w));
w->w_qgrp = WorkList[i].w_qgrp;
w->w_qdir = WorkList[i].w_qdir;
w->w_name = WorkList[i].w_name;
@@ -3125,7 +3133,7 @@ grow_wlist(qgrp, qdir)
sm_dprintf("grow_wlist: WorkListSize=%d\n", WorkListSize);
if (WorkList == NULL)
{
- WorkList = (WORK *) xalloc((sizeof *WorkList) *
+ WorkList = (WORK *) xalloc((sizeof(*WorkList)) *
(QUEUESEGSIZE + 1));
WorkListSize = QUEUESEGSIZE;
}
@@ -3898,13 +3906,15 @@ readqf(e, openonly)
char *err;
char qf[MAXPATHLEN];
char buf[MAXLINE];
+ int bufsize;
/*
** Read and process the file.
*/
+ SM_REQUIRE(e != NULL);
bp = NULL;
- (void) sm_strlcpy(qf, queuename(e, ANYQFL_LETTER), sizeof qf);
+ (void) sm_strlcpy(qf, queuename(e, ANYQFL_LETTER), sizeof(qf));
qfp = sm_io_open(SmFtStdio, SM_TIME_DEFAULT, qf, SM_IO_RDWR_B, NULL);
if (qfp == NULL)
{
@@ -4118,7 +4128,8 @@ readqf(e, openonly)
#endif /* _FFR_QUEUE_MACRO */
e->e_dfino = -1;
e->e_msgsize = -1;
- while ((bp = fgetfolded(buf, sizeof buf, qfp)) != NULL)
+ while (bufsize = sizeof(buf),
+ (bp = fgetfolded(buf, &bufsize, qfp)) != NULL)
{
unsigned long qflags;
ADDRESS *q;
@@ -4296,6 +4307,8 @@ readqf(e, openonly)
howlong);
e->e_id = NULL;
unlockqueue(e);
+ if (bp != buf)
+ sm_free(bp);
return false;
}
macdefine(&e->e_macro, A_TEMP,
@@ -4471,10 +4484,7 @@ readqf(e, openonly)
}
if (bp != buf)
- {
- sm_free(bp); /* XXX */
- bp = NULL;
- }
+ SM_FREE(bp);
}
/*
@@ -4496,6 +4506,17 @@ readqf(e, openonly)
(void) sm_io_close(qfp, SM_TIME_DEFAULT);
return false;
}
+
+#if _FFR_QF_PARANOIA
+ /* Check to make sure key fields were read */
+ if (e->e_from.q_mailer == NULL)
+ {
+ syserr("readqf: %s: sender not specified in queue file", qf);
+ (void) sm_io_close(qfp, SM_TIME_DEFAULT);
+ return false;
+ }
+ /* other checks? */
+#endif /* _FFR_QF_PARANOIA */
/* possibly set ${dsn_ret} macro */
if (bitset(EF_RET_PARAM, e->e_flags))
@@ -4528,7 +4549,7 @@ readqf(e, openonly)
e->e_msgsize = st.st_size + hdrsize;
e->e_dfdev = st.st_dev;
e->e_dfino = ST_INODE(st);
- (void) sm_snprintf(buf, sizeof buf, "%ld",
+ (void) sm_snprintf(buf, sizeof(buf), "%ld",
e->e_msgsize);
macdefine(&e->e_macro, A_TEMP, macid("{msg_size}"),
buf);
@@ -4547,11 +4568,8 @@ readqf(e, openonly)
** queueup() with bogus data.
*/
- if (bp != NULL && bp != buf)
- {
- sm_free(bp); /* XXX */
- bp = NULL;
- }
+ if (bp != buf)
+ SM_FREE(bp);
if (qfp != NULL)
(void) sm_io_close(qfp, SM_TIME_DEFAULT);
e->e_lockfp = NULL;
@@ -4573,6 +4591,8 @@ readqf(e, openonly)
** Prints a string on stdout.
*/
+static void prtstr __P((char *, int));
+
static void
prtstr(s, ml)
char *s;
@@ -4749,17 +4769,17 @@ print_single_queue(qgrp, qdir)
if (qdir == NOQDIR)
{
- (void) sm_strlcpy(qd, ".", sizeof qd);
- (void) sm_strlcpy(qddf, ".", sizeof qddf);
+ (void) sm_strlcpy(qd, ".", sizeof(qd));
+ (void) sm_strlcpy(qddf, ".", sizeof(qddf));
}
else
{
- (void) sm_strlcpyn(qd, sizeof qd, 2,
+ (void) sm_strlcpyn(qd, sizeof(qd), 2,
Queue[qgrp]->qg_qpaths[qdir].qp_name,
(bitset(QP_SUBQF,
Queue[qgrp]->qg_qpaths[qdir].qp_subdirs)
? "/qf" : ""));
- (void) sm_strlcpyn(qddf, sizeof qddf, 2,
+ (void) sm_strlcpyn(qddf, sizeof(qddf), 2,
Queue[qgrp]->qg_qpaths[qdir].qp_name,
(bitset(QP_SUBDF,
Queue[qgrp]->qg_qpaths[qdir].qp_subdirs)
@@ -4852,7 +4872,7 @@ print_single_queue(qgrp, qdir)
(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "%13s",
w->w_name + 2);
- (void) sm_strlcpyn(qf, sizeof qf, 3, qd, "/", w->w_name);
+ (void) sm_strlcpyn(qf, sizeof(qf), 3, qd, "/", w->w_name);
f = sm_io_open(SmFtStdio, SM_TIME_DEFAULT, qf, SM_IO_RDONLY_B,
NULL);
if (f == NULL)
@@ -4871,7 +4891,7 @@ print_single_queue(qgrp, qdir)
continue;
}
w->w_name[0] = DATAFL_LETTER;
- (void) sm_strlcpyn(qf, sizeof qf, 3, qddf, "/", w->w_name);
+ (void) sm_strlcpyn(qf, sizeof(qf), 3, qddf, "/", w->w_name);
if (stat(qf, &st) >= 0)
dfsize = st.st_size;
else
@@ -4919,7 +4939,7 @@ print_single_queue(qgrp, qdir)
quarmsg[0] = '\0';
statmsg[0] = bodytype[0] = '\0';
qfver = 0;
- while (sm_io_fgets(f, SM_TIME_DEFAULT, buf, sizeof buf) != NULL)
+ while (sm_io_fgets(f, SM_TIME_DEFAULT, buf, sizeof(buf)) != NULL)
{
register int i;
register char *p;
@@ -4935,22 +4955,22 @@ print_single_queue(qgrp, qdir)
break;
case 'M': /* error message */
- if ((i = strlen(&buf[1])) >= sizeof statmsg)
- i = sizeof statmsg - 1;
+ if ((i = strlen(&buf[1])) >= sizeof(statmsg))
+ i = sizeof(statmsg) - 1;
memmove(statmsg, &buf[1], i);
statmsg[i] = '\0';
break;
case 'q': /* quarantine reason */
- if ((i = strlen(&buf[1])) >= sizeof quarmsg)
- i = sizeof quarmsg - 1;
+ if ((i = strlen(&buf[1])) >= sizeof(quarmsg))
+ i = sizeof(quarmsg) - 1;
memmove(quarmsg, &buf[1], i);
quarmsg[i] = '\0';
break;
case 'B': /* body type */
- if ((i = strlen(&buf[1])) >= sizeof bodytype)
- i = sizeof bodytype - 1;
+ if ((i = strlen(&buf[1])) >= sizeof(bodytype))
+ i = sizeof(bodytype) - 1;
memmove(bodytype, &buf[1], i);
bodytype[i] = '\0';
break;
@@ -5206,7 +5226,7 @@ queuename(e, type)
/* xf files always have a valid qd and qg picked above */
if ((qd == NOQDIR || qg == NOQGRP) && type != XSCRPT_LETTER)
- (void) sm_strlcpyn(buf, sizeof buf, 2, pref, e->e_id);
+ (void) sm_strlcpyn(buf, sizeof(buf), 2, pref, e->e_id);
else
{
switch (type)
@@ -5234,7 +5254,7 @@ queuename(e, type)
sm_abort("queuename: bad queue file type %d", type);
}
- (void) sm_strlcpyn(buf, sizeof buf, 4,
+ (void) sm_strlcpyn(buf, sizeof(buf), 4,
Queue[qg]->qg_qpaths[qd].qp_name,
sub, pref, e->e_id);
}
@@ -5361,7 +5381,7 @@ assign_queueid(e)
idbuf[5] = QueueIdChars[tm->tm_sec % QIC_LEN_R];
idbuf[6] = QueueIdChars[seq / QIC_LEN];
idbuf[7] = QueueIdChars[seq % QIC_LEN];
- (void) sm_snprintf(&idbuf[8], sizeof idbuf - 8, "%06d",
+ (void) sm_snprintf(&idbuf[8], sizeof(idbuf) - 8, "%06d",
(int) LastQueuePid);
e->e_id = sm_rpool_strdup_x(e->e_rpool, idbuf);
macdefine(&e->e_macro, A_PERM, 'i', e->e_id);
@@ -5484,8 +5504,8 @@ setctluser(user, qfver, e)
** Set up addr fields for controlling user.
*/
- a = (ADDRESS *) sm_rpool_malloc_x(e->e_rpool, sizeof *a);
- memset((char *) a, '\0', sizeof *a);
+ a = (ADDRESS *) sm_rpool_malloc_x(e->e_rpool, sizeof(*a));
+ memset((char *) a, '\0', sizeof(*a));
if (*user == ':')
{
@@ -5558,7 +5578,7 @@ loseqfile(e, why)
if (e == NULL || e->e_id == NULL)
return;
p = queuename(e, ANYQFL_LETTER);
- if (sm_strlcpy(buf, p, sizeof buf) >= sizeof buf)
+ if (sm_strlcpy(buf, p, sizeof(buf)) >= sizeof(buf))
return;
if (!bitset(EF_INQUEUE, e->e_flags))
queueup(e, false, true);
@@ -5633,7 +5653,7 @@ qid_printname(e)
if (e->e_qdir == NOQDIR)
return id;
- (void) sm_snprintf(idbuf, sizeof idbuf, "%.32s/%s",
+ (void) sm_snprintf(idbuf, sizeof(idbuf), "%.32s/%s",
Queue[e->e_qgrp]->qg_qpaths[e->e_qdir].qp_name,
id);
return idbuf;
@@ -5665,7 +5685,7 @@ qid_printqueue(qgrp, qdir)
else
subdir = Queue[qgrp]->qg_qpaths[qdir].qp_name;
- (void) sm_strlcpyn(dir, sizeof dir, 4,
+ (void) sm_strlcpyn(dir, sizeof(dir), 4,
Queue[qgrp]->qg_qdir,
subdir == NULL ? "" : "/",
subdir == NULL ? "" : subdir,
@@ -5871,6 +5891,8 @@ setnewqueue(e)
** is it a queue directory?
*/
+static bool chkqdir __P((char *, long));
+
static bool
chkqdir(name, sff)
char *name;
@@ -6018,11 +6040,11 @@ multiqueue_cache(basedir, blen, qg, qn, phash)
}
/* qpath: directory of current workgroup */
- len = sm_strlcpy(qpath, qg->qg_qdir, sizeof qpath);
- if (len >= sizeof qpath)
+ len = sm_strlcpy(qpath, qg->qg_qdir, sizeof(qpath));
+ if (len >= sizeof(qpath))
{
syserr("QueuePath %.256s too long (%d max)",
- qg->qg_qdir, (int) sizeof qpath);
+ qg->qg_qdir, (int) sizeof(qpath));
ExitStat = EX_CONFIG;
return qn;
}
@@ -6042,11 +6064,11 @@ multiqueue_cache(basedir, blen, qg, qn, phash)
{
/* Copy subdirectory into prefix for later use */
- if (sm_strlcpy(prefix, qg->qg_qdir + blen, sizeof prefix) >=
- sizeof prefix)
+ if (sm_strlcpy(prefix, qg->qg_qdir + blen, sizeof(prefix)) >=
+ sizeof(prefix))
{
syserr("QueuePath %.256s too long (%d max)",
- qg->qg_qdir, (int) sizeof qpath);
+ qg->qg_qdir, (int) sizeof(qpath));
ExitStat = EX_CONFIG;
return qn;
}
@@ -6083,7 +6105,7 @@ multiqueue_cache(basedir, blen, qg, qn, phash)
** Change to //foo*
*/
- (void) sm_strlcpy(qpath + 1, qpath, sizeof qpath - 1);
+ (void) sm_strlcpy(qpath + 1, qpath, sizeof(qpath) - 1);
++cp;
}
delim = cp;
@@ -6096,8 +6118,8 @@ multiqueue_cache(basedir, blen, qg, qn, phash)
** so they can be opened without chdir().
*/
- off = sm_strlcpyn(relpath, sizeof relpath, 2, prefix, "/");
- SM_ASSERT(off < sizeof relpath);
+ off = sm_strlcpyn(relpath, sizeof(relpath), 2, prefix, "/");
+ SM_ASSERT(off < sizeof(relpath));
if (tTd(41, 2))
sm_dprintf("multiqueue_cache: prefix=\"%s%s\"\n",
@@ -6136,6 +6158,11 @@ multiqueue_cache(basedir, blen, qg, qn, phash)
}
while ((d = readdir(dp)) != NULL)
{
+ /* Skip . and .. directories */
+ if (strcmp(d->d_name, ".") == 0 ||
+ strcmp(d->d_name, "..") == 0)
+ continue;
+
i = strlen(d->d_name);
if (i < len || strncmp(d->d_name, cp, len) != 0)
{
@@ -6156,14 +6183,14 @@ multiqueue_cache(basedir, blen, qg, qn, phash)
if (qg->qg_qpaths == NULL)
{
slotsleft = INITIAL_SLOTS;
- qg->qg_qpaths = (QPATHS *)xalloc((sizeof *qg->qg_qpaths) *
+ qg->qg_qpaths = (QPATHS *)xalloc((sizeof(*qg->qg_qpaths)) *
slotsleft);
qg->qg_numqueues = 0;
}
else if (slotsleft < 1)
{
qg->qg_qpaths = (QPATHS *)sm_realloc((char *)qg->qg_qpaths,
- (sizeof *qg->qg_qpaths) *
+ (sizeof(*qg->qg_qpaths)) *
(qg->qg_numqueues +
ADD_SLOTS));
if (qg->qg_qpaths == NULL)
@@ -6178,7 +6205,7 @@ multiqueue_cache(basedir, blen, qg, qn, phash)
qg->qg_qpaths[qg->qg_numqueues].qp_subdirs = QP_NOSUB;
#define CHKRSUBDIR(name, flag) \
- (void) sm_strlcpyn(subdir, sizeof subdir, 3, relpath, "/", name); \
+ (void) sm_strlcpyn(subdir, sizeof(subdir), 3, relpath, "/", name); \
if (chkqdir(subdir, sff)) \
qg->qg_qpaths[qg->qg_numqueues].qp_subdirs |= flag; \
else
@@ -6217,7 +6244,7 @@ multiqueue_cache(basedir, blen, qg, qn, phash)
}
if (qg->qg_numqueues == 0)
{
- qg->qg_qpaths = (QPATHS *) xalloc(sizeof *qg->qg_qpaths);
+ qg->qg_qpaths = (QPATHS *) xalloc(sizeof(*qg->qg_qpaths));
/* test path to get warning messages */
i = safedirpath(qpath, RunAsUid, RunAsGid, NULL, sff, 0, 0);
@@ -6236,7 +6263,7 @@ multiqueue_cache(basedir, blen, qg, qn, phash)
/* check subdirs */
#define CHKSUBDIR(name, flag) \
- (void) sm_strlcpyn(subdir, sizeof subdir, 3, qg->qg_qdir, "/", name); \
+ (void) sm_strlcpyn(subdir, sizeof(subdir), 3, qg->qg_qdir, "/", name); \
if (chkqdir(subdir, sff)) \
qg->qg_qpaths[0].qp_subdirs |= flag; \
else
@@ -6290,7 +6317,7 @@ multiqueue_cache(basedir, blen, qg, qn, phash)
** FSF_NOT_FOUND: not in list
*/
-static short filesys_find __P((char *, char *, bool));
+static short filesys_find __P((const char *, const char *, bool));
#define FSF_NOT_FOUND (-1)
#define FSF_STAT_FAIL (-2)
@@ -6298,8 +6325,8 @@ static short filesys_find __P((char *, char *, bool));
static short
filesys_find(name, path, add)
- char *name;
- char *path;
+ const char *name;
+ const char *path;
bool add;
{
struct stat st;
@@ -6378,7 +6405,7 @@ filesys_setup(add)
QPATHS *qp = &Queue[i]->qg_qpaths[j];
char qddf[MAXPATHLEN];
- (void) sm_strlcpyn(qddf, sizeof qddf, 2, qp->qp_name,
+ (void) sm_strlcpyn(qddf, sizeof(qddf), 2, qp->qp_name,
(bitset(QP_SUBDF, qp->qp_subdirs)
? "/df" : ""));
fs = filesys_find(qp->qp_name, qddf, add);
@@ -6419,6 +6446,12 @@ filesys_update()
static time_t nextupdate = 0;
#if SM_CONF_SHM
+ /*
+ ** Only the daemon updates the shared memory, i.e.,
+ ** if shared memory is available but the pid is not the
+ ** one of the daemon, then don't do anything.
+ */
+
if (ShmId != SM_SHM_NO_ID && DaemonPid != CurrentPid)
return;
#endif /* SM_CONF_SHM */
@@ -6486,7 +6519,6 @@ filesys_free(fsize)
}
#endif /* _FFR_ANY_FREE_FS */
-#if _FFR_CONTROL_MSTAT
/*
** DISK_STATUS -- show amount of free space in queue directories
**
@@ -6524,7 +6556,6 @@ disk_status(out, prefix)
free);
}
}
-#endif /* _FFR_CONTROL_MSTAT */
#if SM_CONF_SHM
@@ -6666,8 +6697,6 @@ upd_qs(e, count, space, where)
}
-#if _FFR_SELECT_SHM
-
static bool write_key_file __P((char *, long));
static long read_key_file __P((char *, long));
@@ -6771,7 +6800,6 @@ read_key_file(keypath, key)
}
return key;
}
-#endif /* _FFR_SELECT_SHM */
/*
** INIT_SHM -- initialize shared memory structure
@@ -6802,17 +6830,13 @@ init_shm(qn, owner, hash)
int i;
int count;
int save_errno;
-#if _FFR_SELECT_SHM
bool keyselect;
-#endif /* _FFR_SELECT_SHM */
PtrFileSys = &FileSys[0];
PNumFileSys = &Numfilesys;
-#if _FFR_SELECT_SHM
/* if this "key" is specified: select one yourself */
-# define SEL_SHM_KEY ((key_t) -1)
-# define FIRST_SHM_KEY 25
-#endif /* _FFR_SELECT_SHM */
+#define SEL_SHM_KEY ((key_t) -1)
+#define FIRST_SHM_KEY 25
/* This allows us to disable shared memory at runtime. */
if (ShmKey == 0)
@@ -6820,7 +6844,6 @@ init_shm(qn, owner, hash)
count = 0;
shms = SM_T_SIZE + qn * sizeof(QUEUE_SHM_T);
-#if _FFR_SELECT_SHM
keyselect = ShmKey == SEL_SHM_KEY;
if (keyselect)
{
@@ -6828,13 +6851,16 @@ init_shm(qn, owner, hash)
ShmKey = FIRST_SHM_KEY;
else
{
+ errno = 0;
ShmKey = read_key_file(ShmKeyFile, ShmKey);
keyselect = false;
if (ShmKey == SEL_SHM_KEY)
+ {
+ save_errno = (errno != 0) ? errno : EINVAL;
goto error;
+ }
}
}
-#endif /* _FFR_SELECT_SHM */
for (;;)
{
/* allow read/write access for group? */
@@ -6846,7 +6872,6 @@ init_shm(qn, owner, hash)
break;
if (++count >= 3)
{
-#if _FFR_SELECT_SHM
if (keyselect)
{
++ShmKey;
@@ -6856,23 +6881,19 @@ init_shm(qn, owner, hash)
break;
continue;
}
-#endif /* _FFR_SELECT_SHM */
break;
}
-#if _FFR_SELECT_SHM
+
/* only sleep if we are at the first key */
if (!keyselect || ShmKey == SEL_SHM_KEY)
-#endif /* _FFR_SELECT_SHM */
- sleep(count);
+ sleep(count);
}
if (Pshm != NULL)
{
int *p;
-#if _FFR_SELECT_SHM
if (keyselect)
(void) write_key_file(ShmKeyFile, (long) ShmKey);
-#endif /* _FFR_SELECT_SHM */
if (owner && RunAsUid != 0)
{
i = sm_shmsetowner(ShmId, RunAsUid, RunAsGid, 0660);
@@ -6942,10 +6963,10 @@ init_shm(qn, owner, hash)
/*
-** SETUP_QUEUES -- setup all queue groups
+** SETUP_QUEUES -- set up all queue groups
**
** Parameters:
-** owner -- owner of shared memory.
+** owner -- owner of shared memory?
**
** Returns:
** none.
@@ -6975,13 +6996,13 @@ setup_queues(owner)
hashval = 0;
errno = 0;
- len = sm_strlcpy(basedir, QueueDir, sizeof basedir);
+ len = sm_strlcpy(basedir, QueueDir, sizeof(basedir));
/* Provide space for trailing '/' */
- if (len >= sizeof basedir - 1)
+ if (len >= sizeof(basedir) - 1)
{
syserr("QueueDirectory: path too long: %d, max %d",
- len, (int) sizeof basedir - 1);
+ len, (int) sizeof(basedir) - 1);
ExitStat = EX_CONFIG;
return;
}
@@ -7232,8 +7253,8 @@ makequeue(line, qdef)
char fcode;
/* allocate a queue and set up defaults */
- qg = (QUEUEGRP *) xalloc(sizeof *qg);
- memset((char *) qg, '\0', sizeof *qg);
+ qg = (QUEUEGRP *) xalloc(sizeof(*qg));
+ memset((char *) qg, '\0', sizeof(*qg));
if (line[0] == '\0')
{
@@ -7743,8 +7764,8 @@ dup_df(old, new)
SM_REQUIRE(ISVALIDQGRP(old->e_qgrp) && ISVALIDQDIR(old->e_qdir));
SM_REQUIRE(ISVALIDQGRP(new->e_qgrp) && ISVALIDQDIR(new->e_qdir));
- (void) sm_strlcpy(opath, queuename(old, DATAFL_LETTER), sizeof opath);
- (void) sm_strlcpy(npath, queuename(new, DATAFL_LETTER), sizeof npath);
+ (void) sm_strlcpy(opath, queuename(old, DATAFL_LETTER), sizeof(opath));
+ (void) sm_strlcpy(npath, queuename(new, DATAFL_LETTER), sizeof(npath));
if (old->e_dfp != NULL)
{
@@ -7789,7 +7810,7 @@ dup_df(old, new)
new->e_dfqgrp = old->e_dfqgrp;
new->e_dfqdir = old->e_dfqdir;
- (void) sm_strlcpy(npath, queuename(new, DATAFL_LETTER), sizeof npath);
+ (void) sm_strlcpy(npath, queuename(new, DATAFL_LETTER), sizeof(npath));
if (link(opath, npath) == 0)
{
new->e_flags |= EF_HAS_DF;
@@ -7830,7 +7851,7 @@ split_env(e, sendqueue, qgrp, qdir)
{
ENVELOPE *ee;
- ee = (ENVELOPE *) sm_rpool_malloc_x(e->e_rpool, sizeof *ee);
+ ee = (ENVELOPE *) sm_rpool_malloc_x(e->e_rpool, sizeof(*ee));
STRUCTCOPY(*e, *ee);
ee->e_message = NULL; /* XXX use original message? */
ee->e_id = NULL;
@@ -7933,6 +7954,7 @@ e_filesys_compare(p1, p2)
return 0;
}
+static int split_across_queue_groups __P((ENVELOPE *));
static int
split_across_queue_groups(e)
ENVELOPE *e;
@@ -8423,14 +8445,15 @@ quarantine_queue_item(qgrp, qdir, e, reason)
MODE_T oldumask = 0;
SM_FILE_T *oldqfp, *tempqfp;
char *bp;
+ int bufsize;
char oldqf[MAXPATHLEN];
char tempqf[MAXPATHLEN];
char newqf[MAXPATHLEN];
char buf[MAXLINE];
oldtype = queue_letter(e, ANYQFL_LETTER);
- (void) sm_strlcpy(oldqf, queuename(e, ANYQFL_LETTER), sizeof oldqf);
- (void) sm_strlcpy(tempqf, queuename(e, NEWQFL_LETTER), sizeof tempqf);
+ (void) sm_strlcpy(oldqf, queuename(e, ANYQFL_LETTER), sizeof(oldqf));
+ (void) sm_strlcpy(tempqf, queuename(e, NEWQFL_LETTER), sizeof(tempqf));
/*
** Instead of duplicating all the open
@@ -8491,7 +8514,8 @@ quarantine_queue_item(qgrp, qdir, e, reason)
}
/* Copy the data over, changing the quarantine reason */
- while ((bp = fgetfolded(buf, sizeof buf, oldqfp)) != NULL)
+ while (bufsize = sizeof(buf),
+ (bp = fgetfolded(buf, &bufsize, oldqfp)) != NULL)
{
if (tTd(40, 4))
sm_dprintf("+++++ %s\n", bp);
@@ -8510,7 +8534,6 @@ quarantine_queue_item(qgrp, qdir, e, reason)
}
sm_syslog(LOG_INFO, e->e_id, "unquarantine");
dirty = true;
- continue;
}
else if (strcmp(reason, &bp[1]) == 0)
{
@@ -8581,6 +8604,8 @@ quarantine_queue_item(qgrp, qdir, e, reason)
"%s\n", bp);
break;
}
+ if (bp != buf)
+ sm_free(bp);
}
/* Make sure we read the whole old file */
@@ -8633,12 +8658,12 @@ quarantine_queue_item(qgrp, qdir, e, reason)
if (oldtype == newtype)
{
/* going to rename tempqf to oldqf */
- (void) sm_strlcpy(newqf, oldqf, sizeof newqf);
+ (void) sm_strlcpy(newqf, oldqf, sizeof(newqf));
}
else
{
/* going to rename tempqf to new name based on newtype */
- (void) sm_strlcpy(newqf, queuename(e, newtype), sizeof newqf);
+ (void) sm_strlcpy(newqf, queuename(e, newtype), sizeof(newqf));
}
save_errno = 0;
diff --git a/contrib/sendmail/src/ratectrl.c b/contrib/sendmail/src/ratectrl.c
index 3185eae7bfff..22f9803efb5f 100644
--- a/contrib/sendmail/src/ratectrl.c
+++ b/contrib/sendmail/src/ratectrl.c
@@ -45,7 +45,7 @@
*/
#include
-SM_RCSID("@(#)$Id: ratectrl.c,v 8.10 2005/06/14 23:07:23 ca Exp $")
+SM_RCSID("@(#)$Id: ratectrl.c,v 8.11 2006/08/15 23:24:57 ca Exp $")
/*
** stuff included - given some warnings (inet_ntoa)
@@ -245,7 +245,7 @@ client_rate(now, saddr, update)
if (!CHashAryOK)
{
- memset(CHashAry, 0, sizeof (CHashAry));
+ memset(CHashAry, 0, sizeof(CHashAry));
CHashAryOK = true;
}
@@ -386,7 +386,7 @@ client_rate(now, saddr, update)
#endif /* NETINET6 */
#if 1
memset(chBest->ch_Times, '\0',
- sizeof (chBest->ch_Times));
+ sizeof(chBest->ch_Times));
#endif /* 1 */
}
diff --git a/contrib/sendmail/src/readcf.c b/contrib/sendmail/src/readcf.c
index f4a37593bea3..bd57d802090f 100644
--- a/contrib/sendmail/src/readcf.c
+++ b/contrib/sendmail/src/readcf.c
@@ -12,8 +12,9 @@
*/
#include
+#include
-SM_RCSID("@(#)$Id: readcf.c,v 8.651 2006/03/02 19:17:09 ca Exp $")
+SM_RCSID("@(#)$Id: readcf.c,v 8.663 2006/10/05 20:58:59 ca Exp $")
#if NETINET || NETINET6
# include
@@ -103,6 +104,7 @@ readcf(cfname, safe, e)
long sff = SFF_OPENASROOT;
struct stat statb;
char buf[MAXLINE];
+ int bufsize;
char exbuf[MAXLINE];
char pvpbuf[MAXLINE + MAXATOM];
static char *null_list[1] = { NULL };
@@ -148,8 +150,11 @@ readcf(cfname, safe, e)
xla_zero();
#endif /* XLA */
- while ((bp = fgetfolded(buf, sizeof buf, cf)) != NULL)
+ while (bufsize = sizeof(buf),
+ (bp = fgetfolded(buf, &bufsize, cf)) != NULL)
{
+ char *nbp;
+
if (bp[0] == '#')
{
if (bp != buf)
@@ -158,7 +163,10 @@ readcf(cfname, safe, e)
}
/* do macro expansion mappings */
- translate_dollars(bp);
+ nbp = translate_dollars(bp, bp, &bufsize);
+ if (nbp != bp && bp != buf)
+ sm_free(bp);
+ bp = nbp;
/* interpret this line */
errno = 0;
@@ -187,21 +195,21 @@ readcf(cfname, safe, e)
if (rwp == NULL)
{
RewriteRules[ruleset] = rwp =
- (struct rewrite *) xalloc(sizeof *rwp);
+ (struct rewrite *) xalloc(sizeof(*rwp));
}
else
{
- rwp->r_next = (struct rewrite *) xalloc(sizeof *rwp);
+ rwp->r_next = (struct rewrite *) xalloc(sizeof(*rwp));
rwp = rwp->r_next;
}
rwp->r_next = NULL;
/* expand and save the LHS */
*p = '\0';
- expand(&bp[1], exbuf, sizeof exbuf, e);
+ expand(&bp[1], exbuf, sizeof(exbuf), e);
rwp->r_lhs = prescan(exbuf, '\t', pvpbuf,
- sizeof pvpbuf, NULL,
- ConfigLevel >= 9 ? TokTypeNoC : NULL,
+ sizeof(pvpbuf), NULL,
+ ConfigLevel >= 9 ? TokTypeNoC : IntTokenTab,
true);
nfuzzy = 0;
if (rwp->r_lhs != NULL)
@@ -216,7 +224,7 @@ readcf(cfname, safe, e)
char *botch;
botch = NULL;
- switch (**ap & 0377)
+ switch (ap[0][0] & 0377)
{
case MATCHZANY:
case MATCHANY:
@@ -227,7 +235,7 @@ readcf(cfname, safe, e)
break;
case MATCHREPL:
- botch = "$0-$9";
+ botch = "$1-$9";
break;
case CANONUSER:
@@ -286,10 +294,10 @@ readcf(cfname, safe, e)
while (*p != '\0' && *p != '\t')
p++;
*p = '\0';
- expand(q, exbuf, sizeof exbuf, e);
+ expand(q, exbuf, sizeof(exbuf), e);
rwp->r_rhs = prescan(exbuf, '\t', pvpbuf,
- sizeof pvpbuf, NULL,
- ConfigLevel >= 9 ? TokTypeNoC : NULL,
+ sizeof(pvpbuf), NULL,
+ ConfigLevel >= 9 ? TokTypeNoC : IntTokenTab,
true);
if (rwp->r_rhs != NULL)
{
@@ -312,13 +320,14 @@ readcf(cfname, safe, e)
char *botch;
botch = NULL;
- switch (**ap & 0377)
+ switch (ap[0][0] & 0377)
{
case MATCHREPL:
- if ((*ap)[1] <= '0' || (*ap)[1] > nfuzzy)
+ if (ap[0][1] <= '0' ||
+ ap[0][1] > nfuzzy)
{
syserr("replacement $%c out of bounds",
- (*ap)[1]);
+ ap[0][1]);
}
break;
@@ -354,34 +363,34 @@ readcf(cfname, safe, e)
/* FALLTHROUGH */
case LOOKUPBEGIN:
/* see above... */
- if ((**ap & 0377) == LOOKUPBEGIN)
+ if ((ap[0][0] & 0377) == LOOKUPBEGIN)
endtoken = LOOKUPEND;
if (inmap)
syserr("cannot nest map lookups");
inmap = true;
args = 0;
#if _FFR_EXTRA_MAP_CHECK
- if (*(ap + 1) == NULL)
+ if (ap[1] == NULL)
{
syserr("syntax error in map lookup");
break;
}
- nexttoken = **(ap + 1) & 0377;
+ nexttoken = ap[1][0] & 0377;
if (nexttoken == CANONHOST ||
nexttoken == CANONUSER ||
- nexttoken == endtoken)
+ nexttoken == endtoken))
{
syserr("missing map name for lookup");
break;
}
- if (*(ap + 2) == NULL)
+ if (ap[2] == NULL)
{
syserr("syntax error in map lookup");
break;
}
- if ((**ap & 0377) == HOSTBEGIN)
+ if (ap[0][0] == HOSTBEGIN)
break;
- nexttoken = **(ap + 2) & 0377;
+ nexttoken = ap[2][0] & 0377;
if (nexttoken == CANONHOST ||
nexttoken == CANONUSER ||
nexttoken == endtoken)
@@ -394,7 +403,7 @@ readcf(cfname, safe, e)
case HOSTEND:
case LOOKUPEND:
- if ((**ap & 0377) != endtoken)
+ if ((ap[0][0] & 0377) != endtoken)
break;
inmap = false;
endtoken = 0;
@@ -416,10 +425,9 @@ readcf(cfname, safe, e)
** check if map is defined.
*/
- ep = *(ap + 1);
- if ((*ep & 0377) != MACRODEXPAND &&
- stab(ep, ST_MAP,
- ST_FIND) == NULL)
+ ep = ap[1];
+ if ((ep[0] & 0377) != MACRODEXPAND &&
+ stab(ep, ST_MAP, ST_FIND) == NULL)
{
(void) sm_io_fprintf(smioout,
SM_TIME_DEFAULT,
@@ -446,7 +454,7 @@ readcf(cfname, safe, e)
break;
case 'S': /* select rewriting set */
- expand(&bp[1], exbuf, sizeof exbuf, e);
+ expand(&bp[1], exbuf, sizeof(exbuf), e);
ruleset = strtorwset(exbuf, NULL, ST_ENTER);
if (ruleset < 0)
break;
@@ -486,7 +494,7 @@ readcf(cfname, safe, e)
mid = macid_parse(&bp[1], &ep);
if (mid == 0)
break;
- expand(ep, exbuf, sizeof exbuf, e);
+ expand(ep, exbuf, sizeof(exbuf), e);
p = exbuf;
}
else
@@ -671,7 +679,7 @@ readcf(cfname, safe, e)
break;
case 'K':
- expand(&bp[1], exbuf, sizeof exbuf, e);
+ expand(&bp[1], exbuf, sizeof(exbuf), e);
(void) makemapentry(exbuf);
break;
@@ -733,6 +741,7 @@ readcf(cfname, safe, e)
}
}
}
+
/*
** TRANSLATE_DOLLARS -- convert $x into internal form
**
@@ -740,20 +749,35 @@ readcf(cfname, safe, e)
** to turn it into internal form.
**
** Parameters:
-** bp -- the buffer to translate.
+** ibp -- the buffer to translate.
+** obp -- where to put the translation; may be the same as obp
+** bsp -- a pointer to the size of obp; will be updated if
+** the buffer needs to be replaced.
**
** Returns:
-** None. The buffer is translated in place. Since the
-** translations always make the buffer shorter, this is
-** safe without a size parameter.
+** The buffer pointer; may differ from obp if the expansion
+** is larger then *bsp, in which case this will point to
+** malloc()ed memory which must be free()d by the caller.
*/
-void
-translate_dollars(bp)
- char *bp;
+char *
+translate_dollars(ibp, obp, bsp)
+ char *ibp;
+ char *obp;
+ int *bsp;
{
register char *p;
auto char *ep;
+ char *bp;
+
+ if (tTd(37, 53))
+ {
+ sm_dprintf("translate_dollars(");
+ xputs(sm_debug_file(), ibp);
+ sm_dprintf(")\n");
+ }
+
+ bp = quote_internal_chars(ibp, obp, bsp);
for (p = bp; *p != '\0'; p++)
{
@@ -777,7 +801,9 @@ translate_dollars(bp)
/* delete leading white space */
while (isascii(*p) && isspace(*p) &&
*p != '\n' && p > bp)
+ {
p--;
+ }
if ((e = strchr(++p, '\n')) != NULL)
(void) sm_strlcpy(p, e, strlen(p));
else
@@ -813,6 +839,15 @@ translate_dollars(bp)
/* strip trailing white space from the line */
while (--p > bp && isascii(*p) && isspace(*p))
*p = '\0';
+
+ if (tTd(37, 53))
+ {
+ sm_dprintf(" translate_dollars => ");
+ xputs(sm_debug_file(), bp);
+ sm_dprintf("\n");
+ }
+
+ return bp;
}
/*
** TOOMANY -- signal too many of some option
@@ -944,11 +979,11 @@ fileclass(class, filename, fmt, ismap, safe, optional)
char lcbuf[MAXLINE];
/* Get $j */
- expand("\201j", jbuf, sizeof jbuf, &BlankEnvelope);
+ expand("\201j", jbuf, sizeof(jbuf), &BlankEnvelope);
if (jbuf[0] == '\0')
{
(void) sm_strlcpy(jbuf, "localhost",
- sizeof jbuf);
+ sizeof(jbuf));
}
/* impose the default schema */
@@ -957,15 +992,15 @@ fileclass(class, filename, fmt, ismap, safe, optional)
lc = "";
else
{
- expand(lc, lcbuf, sizeof lcbuf, CurEnv);
+ expand(lc, lcbuf, sizeof(lcbuf), CurEnv);
lc = lcbuf;
}
cl = "ldap";
- n = sm_snprintf(buf, sizeof buf,
+ n = sm_snprintf(buf, sizeof(buf),
"-k (&(objectClass=sendmailMTAClass)(sendmailMTAClassName=%s)(|(sendmailMTACluster=%s)(sendmailMTAHost=%s))) -v sendmailMTAClassValue,sendmailMTAClassSearch:FILTER:sendmailMTAClass,sendmailMTAClassURL:URL:sendmailMTAClass",
mn, lc, jbuf);
- if (n >= sizeof buf)
+ if (n >= sizeof(buf))
{
syserr("fileclass: F{%s}: Default LDAP string too long",
mn);
@@ -996,7 +1031,7 @@ fileclass(class, filename, fmt, ismap, safe, optional)
sm_free(mn);
return;
}
- memset(&map, '\0', sizeof map);
+ memset(&map, '\0', sizeof(map));
map.map_class = &mapclass->s_mapclass;
map.map_mname = mn;
map.map_mflags |= MF_FILECLASS;
@@ -1095,7 +1130,7 @@ fileclass(class, filename, fmt, ismap, safe, optional)
return;
}
- while (sm_io_fgets(f, SM_TIME_DEFAULT, buf, sizeof buf) != NULL)
+ while (sm_io_fgets(f, SM_TIME_DEFAULT, buf, sizeof(buf)) != NULL)
{
#if SCANF
char wordbuf[MAXLINE + 1];
@@ -1170,8 +1205,8 @@ makemailer(line)
static int nextmailer = 0; /* "free" index into Mailer struct */
/* allocate a mailer and set up defaults */
- m = (struct mailer *) xalloc(sizeof *m);
- memset((char *) m, '\0', sizeof *m);
+ m = (struct mailer *) xalloc(sizeof(*m));
+ memset((char *) m, '\0', sizeof(*m));
errno = 0; /* avoid bogus error text */
/* collect the mailer name */
@@ -1630,7 +1665,7 @@ munchstring(p, delimptr, delim)
bool quotemode = false;
static char buf[MAXLINE];
- for (q = buf; *p != '\0' && q < &buf[sizeof buf - 1]; p++)
+ for (q = buf; *p != '\0' && q < &buf[sizeof(buf) - 1]; p++)
{
if (backslash)
{
@@ -1708,7 +1743,7 @@ extrquotstr(p, delimptr, delimbuf, st)
bool quotemode = false;
static char buf[MAXLINE];
- for (q = buf; *p != '\0' && q < &buf[sizeof buf - 1]; p++)
+ for (q = buf; *p != '\0' && q < &buf[sizeof(buf) - 1]; p++)
{
if (backslash)
{
@@ -1770,8 +1805,8 @@ makeargv(p)
argv[i++] = NULL;
/* now make a copy of the argv */
- avp = (char **) xalloc(sizeof *avp * i);
- memmove((char *) avp, (char *) argv, sizeof *avp * i);
+ avp = (char **) xalloc(sizeof(*avp) * i);
+ memmove((char *) avp, (char *) argv, sizeof(*avp) * i);
return avp;
}
@@ -2163,14 +2198,10 @@ static struct optioninfo
{ "DelayLA", O_DELAY_LA, OI_NONE },
#define O_FASTSPLIT 0xce
{ "FastSplit", O_FASTSPLIT, OI_NONE },
-#if _FFR_SOFT_BOUNCE
-# define O_SOFTBOUNCE 0xcf
+#define O_SOFTBOUNCE 0xcf
{ "SoftBounce", O_SOFTBOUNCE, OI_NONE },
-#endif /* _FFR_SOFT_BOUNCE */
-#if _FFR_SELECT_SHM
-# define O_SHMKEYFILE 0xd0
+#define O_SHMKEYFILE 0xd0
{ "SharedMemoryKeyFile", O_SHMKEYFILE, OI_NONE },
-#endif /* _FFR_SELECT_SHM */
#define O_REJECTLOGINTERVAL 0xd1
{ "RejectLogInterval", O_REJECTLOGINTERVAL, OI_NONE },
#define O_REQUIRES_DIR_FSYNC 0xd2
@@ -2187,10 +2218,8 @@ static struct optioninfo
# define O_CRLPATH 0xd7
{ "CRLPath", O_CRLPATH, OI_NONE },
#endif /* _FFR_CRLPATH */
-#if _FFR_HELONAME
-# define O_HELONAME 0xd8
+#define O_HELONAME 0xd8
{ "HeloName", O_HELONAME, OI_NONE },
-#endif /* _FFR_HELONAME */
#if _FFR_MEMSTAT
# define O_REFUSELOWMEM 0xd9
{ "RefuseLowMem", O_REFUSELOWMEM, OI_NONE },
@@ -2199,10 +2228,8 @@ static struct optioninfo
# define O_MEMRESOURCE 0xdb
{ "MemoryResource", O_MEMRESOURCE, OI_NONE },
#endif /* _FFR_MEMSTAT */
-#if _FFR_MAXNOOPCOMMANDS
-# define O_MAXNOOPCOMMANDS 0xdc
+#define O_MAXNOOPCOMMANDS 0xdc
{ "MaxNOOPCommands", O_MAXNOOPCOMMANDS, OI_NONE },
-#endif /* _FFR_MAXNOOPCOMMANDS */
#if _FFR_MSG_ACCEPT
# define O_MSG_ACCEPT 0xdd
{ "MessageAccept", O_MSG_ACCEPT, OI_NONE },
@@ -2211,6 +2238,13 @@ static struct optioninfo
# define O_CHK_Q_RUNNERS 0xde
{ "CheckQueueRunners", O_CHK_Q_RUNNERS, OI_NONE },
#endif /* _FFR_QUEUE_RUN_PARANOIA */
+#if _FFR_EIGHT_BIT_ADDR_OK
+# if !ALLOW_255
+# ERROR FFR_EIGHT_BIT_ADDR_OK requires _ALLOW_255
+# endif /* !ALLOW_255 */
+# define O_EIGHT_BIT_ADDR_OK 0xdf
+ { "EightBitAddrOK", O_EIGHT_BIT_ADDR_OK, OI_NONE },
+#endif /* _FFR_EIGHT_BIT_ADDR_OK */
{ NULL, '\0', OI_NONE }
};
@@ -2222,7 +2256,7 @@ static struct optioninfo
/* set a string option by expanding the value and assigning it */
/* WARNING this belongs ONLY into a case statement! */
#define SET_STRING_EXP(str) \
- expand(val, exbuf, sizeof exbuf, e); \
+ expand(val, exbuf, sizeof(exbuf), e); \
newval = sm_pstrdup_x(exbuf); \
if (str != NULL) \
sm_free(str); \
@@ -2251,10 +2285,10 @@ setoption(opt, val, safe, sticky, e)
#if _FFR_ALLOW_SASLINFO
extern unsigned int SubmitMode;
#endif /* _FFR_ALLOW_SASLINFO */
-#if STARTTLS || (_FFR_SELECT_SHM && SM_CONF_SHM)
+#if STARTTLS || SM_CONF_SHM
char *newval;
char exbuf[MAXLINE];
-#endif /* STARTTLS || (_FFR_SELECT_SHM && SM_CONF_SHM) */
+#endif /* STARTTLS || SM_CONF_SHM */
errno = 0;
if (opt == ' ')
@@ -3038,17 +3072,15 @@ setoption(opt, val, safe, sticky, e)
#endif /* SM_CONF_SHM */
break;
-#if _FFR_SELECT_SHM
case O_SHMKEYFILE: /* shared memory key file */
-# if SM_CONF_SHM
+#if SM_CONF_SHM
SET_STRING_EXP(ShmKeyFile);
-# else /* SM_CONF_SHM */
+#else /* SM_CONF_SHM */
(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
"Warning: Option: %s requires shared memory support (-DSM_CONF_SHM)\n",
OPTNAME);
break;
-# endif /* SM_CONF_SHM */
-#endif /* _FFR_SELECT_SHM */
+#endif /* SM_CONF_SHM */
#if _FFR_MAX_FORWARD_ENTRIES
case O_MAXFORWARD: /* max # of forward entries */
@@ -3061,9 +3093,9 @@ setoption(opt, val, safe, sticky, e)
break;
case O_MUSTQUOTE: /* must quote these characters in phrases */
- (void) sm_strlcpy(buf, "@,;:\\()[]", sizeof buf);
- if (strlen(val) < sizeof buf - 10)
- (void) sm_strlcat(buf, val, sizeof buf);
+ (void) sm_strlcpy(buf, "@,;:\\()[]", sizeof(buf));
+ if (strlen(val) < sizeof(buf) - 10)
+ (void) sm_strlcat(buf, val, sizeof(buf));
else
(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
"Warning: MustQuoteChars too long, ignored.\n");
@@ -3371,6 +3403,16 @@ setoption(opt, val, safe, sticky, e)
else if (MaxMimeFieldLength < 40)
(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
"Warning: MaxMimeHeaderLength: field length limit set lower than 40\n");
+
+ /*
+ ** Headers field values now include leading space, so let's
+ ** adjust the values to be "backward compatible".
+ */
+
+ if (MaxMimeHeaderLength > 0)
+ MaxMimeHeaderLength++;
+ if (MaxMimeFieldLength > 0)
+ MaxMimeFieldLength++;
break;
case O_CONTROLSOCKET:
@@ -3702,11 +3744,9 @@ setoption(opt, val, safe, sticky, e)
UseMSP = atobool(val);
break;
-#if _FFR_SOFT_BOUNCE
case O_SOFTBOUNCE:
SoftBounce = atobool(val);
break;
-#endif /* _FFR_SOFT_BOUNCE */
case O_REJECTLOGINTERVAL: /* time btwn log msgs while refusing */
RejectLogInterval = convtime(val, 'h');
@@ -3729,11 +3769,10 @@ setoption(opt, val, safe, sticky, e)
FallbackSmartHost = newstr(val);
break;
-#if _FFR_HELONAME
case O_HELONAME:
HeloName = newstr(val);
break;
-#endif /* _FFR_HELONAME */
+
#if _FFR_MEMSTAT
case O_REFUSELOWMEM:
RefuseLowMem = atoi(val);
@@ -3746,11 +3785,9 @@ setoption(opt, val, safe, sticky, e)
break;
#endif /* _FFR_MEMSTAT */
-#if _FFR_MAXNOOPCOMMANDS
case O_MAXNOOPCOMMANDS:
MaxNOOPCommands = atoi(val);
break;
-#endif /* _FFR_MAXNOOPCOMMANDS */
#if _FFR_MSG_ACCEPT
case O_MSG_ACCEPT:
@@ -3764,6 +3801,12 @@ setoption(opt, val, safe, sticky, e)
break;
#endif /* _FFR_QUEUE_RUN_PARANOIA */
+#if _FFR_EIGHT_BIT_ADDR_OK
+ case O_EIGHT_BIT_ADDR_OK:
+ EightBitAddrOK = atobool(val);
+ break;
+#endif /* _FFR_EIGHT_BIT_ADDR_OK */
+
default:
if (tTd(37, 1))
{
@@ -3807,7 +3850,7 @@ setclass(class, str)
{
register STAB *s;
- if ((*str & 0377) == MATCHCLASS)
+ if ((str[0] & 0377) == MATCHCLASS)
{
int mid;
diff --git a/contrib/sendmail/src/recipient.c b/contrib/sendmail/src/recipient.c
index d952a8b96ab2..ea30adcd02a8 100644
--- a/contrib/sendmail/src/recipient.c
+++ b/contrib/sendmail/src/recipient.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998-2003 Sendmail, Inc. and its suppliers.
+ * Copyright (c) 1998-2003, 2006 Sendmail, Inc. and its suppliers.
* All rights reserved.
* Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved.
* Copyright (c) 1988, 1993
@@ -13,7 +13,7 @@
#include
-SM_RCSID("@(#)$Id: recipient.c,v 8.337 2004/08/03 19:57:23 ca Exp $")
+SM_RCSID("@(#)$Id: recipient.c,v 8.348 2007/03/19 21:33:09 ca Exp $")
static void includetimeout __P((int));
static ADDRESS *self_reference __P((ADDRESS *));
@@ -200,10 +200,10 @@ sendtolist(list, ctladdr, sendq, aliaslevel, e)
/* make sure we have enough space to copy the string */
i = strlen(list) + 1;
- if (i <= sizeof buf)
+ if (i <= sizeof(buf))
{
bufp = buf;
- i = sizeof buf;
+ i = sizeof(buf);
}
else
bufp = sm_malloc_x(i);
@@ -309,6 +309,7 @@ sendtolist(list, ctladdr, sendq, aliaslevel, e)
SM_END_TRY
return naddrs;
}
+
#if MILTER
/*
** REMOVEFROMLIST -- Remove addresses from a send list.
@@ -364,10 +365,10 @@ removefromlist(list, sendq, e)
/* make sure we have enough space to copy the string */
i = strlen(list) + 1;
- if (i <= sizeof buf)
+ if (i <= sizeof(buf))
{
bufp = buf;
- i = sizeof buf;
+ i = sizeof(buf);
}
else
bufp = sm_malloc_x(i);
@@ -387,7 +388,7 @@ removefromlist(list, sendq, e)
/* parse the address */
while ((isascii(*p) && isspace(*p)) || *p == ',')
p++;
- if (parseaddr(p, &a, RF_COPYALL,
+ if (parseaddr(p, &a, RF_COPYALL|RF_RM_ADDR,
delimiter, &delimptr, e, true) == NULL)
{
p = delimptr;
@@ -423,10 +424,10 @@ removefromlist(list, sendq, e)
return naddrs;
}
#endif /* MILTER */
+
/*
** RECIPIENT -- Designate a message recipient
-**
-** Saves the named person for future mailing.
+** Saves the named person for future mailing (after some checks).
**
** Parameters:
** new -- the (preparsed) address header for the recipient.
@@ -503,13 +504,13 @@ recipient(new, sendq, aliaslevel, e)
p = "rfc822";
if (sm_strcasecmp(p, "rfc822") != 0)
{
- (void) sm_snprintf(frbuf, sizeof frbuf, "%s; %.800s",
+ (void) sm_snprintf(frbuf, sizeof(frbuf), "%s; %.800s",
q->q_mailer->m_addrtype,
q->q_user);
}
else if (strchr(q->q_user, '@') != NULL)
{
- (void) sm_snprintf(frbuf, sizeof frbuf, "%s; %.800s",
+ (void) sm_snprintf(frbuf, sizeof(frbuf), "%s; %.800s",
p, q->q_user);
}
else if (strchr(q->q_paddr, '@') != NULL)
@@ -528,7 +529,7 @@ recipient(new, sendq, aliaslevel, e)
qp[strlen(qp) - 1] = '\0';
qp++;
}
- (void) sm_snprintf(frbuf, sizeof frbuf, "%s; %.800s",
+ (void) sm_snprintf(frbuf, sizeof(frbuf), "%s; %.800s",
p, qp);
/* undo damage */
@@ -537,7 +538,7 @@ recipient(new, sendq, aliaslevel, e)
}
else
{
- (void) sm_snprintf(frbuf, sizeof frbuf,
+ (void) sm_snprintf(frbuf, sizeof(frbuf),
"%s; %.700s@%.100s",
p, q->q_user, MyHostName);
}
@@ -562,7 +563,7 @@ recipient(new, sendq, aliaslevel, e)
p = e->e_from.q_mailer->m_addrtype;
if (p == NULL)
p = "rfc822";
- (void) sm_strlcpyn(obuf, sizeof obuf, 2, p, ";");
+ (void) sm_strlcpyn(obuf, sizeof(obuf), 2, p, ";");
qp = q->q_paddr;
@@ -577,9 +578,9 @@ recipient(new, sendq, aliaslevel, e)
qp++;
}
- p = xtextify(denlstring(qp, true, false), NULL);
+ p = xtextify(denlstring(qp, true, false), "=");
- if (sm_strlcat(obuf, p, sizeof obuf) >= sizeof obuf)
+ if (sm_strlcat(obuf, p, sizeof(obuf)) >= sizeof(obuf))
{
/* if too big, don't use it */
obuf[0] = '\0';
@@ -601,6 +602,18 @@ recipient(new, sendq, aliaslevel, e)
{
new->q_state = QS_BADADDR;
new->q_status = "5.4.6";
+ if (new->q_alias != NULL)
+ {
+ new->q_alias->q_state = QS_BADADDR;
+ new->q_alias->q_status = "5.4.6";
+ }
+ if ((SuprErrs || !LogUsrErrs) && LogLevel > 0)
+ {
+ sm_syslog(LOG_ERR, e->e_id,
+ "aliasing/forwarding loop broken: %s (%d aliases deep; %d max)",
+ FileName != NULL ? FileName : "", aliaslevel,
+ MaxAliasRecursion);
+ }
usrerrenh(new->q_status,
"554 aliasing/forwarding loop broken (%d aliases deep; %d max)",
aliaslevel, MaxAliasRecursion);
@@ -613,7 +626,7 @@ recipient(new, sendq, aliaslevel, e)
/* get unquoted user for file, program or user.name check */
i = strlen(new->q_user);
- if (i >= sizeof buf0)
+ if (i >= sizeof(buf0))
{
buflen = i + 1;
buf = xalloc(buflen);
@@ -621,7 +634,7 @@ recipient(new, sendq, aliaslevel, e)
else
{
buf = buf0;
- buflen = sizeof buf0;
+ buflen = sizeof(buf0);
}
(void) sm_strlcpy(buf, new->q_user, buflen);
for (p = buf; *p != '\0' && !quoted; p++)
@@ -904,7 +917,8 @@ recipient(new, sendq, aliaslevel, e)
{
new->q_state = QS_QUEUEUP;
if (e->e_message == NULL)
- e->e_message = "Deferred: user database error";
+ e->e_message = sm_rpool_strdup_x(e->e_rpool,
+ "Deferred: user database error");
if (new->q_message == NULL)
new->q_message = "Deferred: user database error";
if (LogLevel > 8)
@@ -1106,10 +1120,11 @@ recipient(new, sendq, aliaslevel, e)
}
}
new->q_flags |= QRCPTOK;
- (void) sm_snprintf(buf0, sizeof buf0, "%d", e->e_nrcpts);
+ (void) sm_snprintf(buf0, sizeof(buf0), "%d", e->e_nrcpts);
macdefine(&e->e_macro, A_TEMP, macid("{nrcpts}"), buf0);
return new;
}
+
/*
** FINDUSER -- find the password entry for a user.
**
@@ -1222,7 +1237,7 @@ finduser(name, fuzzyp, user)
}
# endif /* 0 */
- sm_pwfullname(pw->pw_gecos, pw->pw_name, buf, sizeof buf);
+ sm_pwfullname(pw->pw_gecos, pw->pw_name, buf, sizeof(buf));
if (strchr(buf, ' ') != NULL && sm_strcasecmp(buf, name) == 0)
{
if (tTd(29, 4))
@@ -1248,6 +1263,7 @@ finduser(name, fuzzyp, user)
return EX_NOUSER;
#endif /* MATCHGECOS */
}
+
/*
** WRITABLE -- predicate returning if the file is writable.
**
@@ -1351,6 +1367,7 @@ writable(filename, ctladdr, flags)
errno = safefile(filename, euid, egid, user, flags, S_IWRITE, NULL);
return errno == 0;
}
+
/*
** INCLUDE -- handle :include: specification.
**
@@ -1801,7 +1818,7 @@ include(fname, forwarding, ctladdr, sendq, aliaslevel, e)
LineNumber = 0;
ctladdr->q_flags &= ~QSELFREF;
nincludes = 0;
- while (sm_io_fgets(fp, SM_TIME_DEFAULT, buf, sizeof buf) != NULL &&
+ while (sm_io_fgets(fp, SM_TIME_DEFAULT, buf, sizeof(buf)) != NULL &&
!maxreached)
{
fixcrlf(buf, true);
@@ -1858,12 +1875,16 @@ include(fname, forwarding, ctladdr, sendq, aliaslevel, e)
sm_dprintf("include: read error: %s\n", sm_errstring(errno));
if (nincludes > 0 && !bitset(QSELFREF, ctladdr->q_flags))
{
- if (tTd(27, 5))
+ if (aliaslevel <= MaxAliasRecursion ||
+ ctladdr->q_state != QS_BADADDR)
{
- sm_dprintf("include: QS_DONTSEND ");
- printaddr(sm_debug_file(), ctladdr, false);
+ ctladdr->q_state = QS_DONTSEND;
+ if (tTd(27, 5))
+ {
+ sm_dprintf("include: QS_DONTSEND ");
+ printaddr(sm_debug_file(), ctladdr, false);
+ }
}
- ctladdr->q_state = QS_DONTSEND;
}
(void) sm_io_close(fp, SM_TIME_DEFAULT);
@@ -1886,6 +1907,7 @@ includetimeout(ignore)
errno = ETIMEDOUT;
longjmp(CtxIncludeTimeout, 1);
}
+
/*
** SENDTOARGV -- send to an argument vector.
**
@@ -1911,6 +1933,7 @@ sendtoargv(argv, e)
while ((p = *argv++) != NULL)
(void) sendtolist(p, NULLADDR, &e->e_sendqueue, 0, e);
}
+
/*
** GETCTLADDR -- get controlling address from an address header.
**
@@ -1931,6 +1954,7 @@ getctladdr(a)
a = a->q_alias;
return a;
}
+
/*
** SELF_REFERENCE -- check to see if an address references itself
**
diff --git a/contrib/sendmail/src/sasl.c b/contrib/sendmail/src/sasl.c
index 9e368ff4bda2..6f9e4a50df99 100644
--- a/contrib/sendmail/src/sasl.c
+++ b/contrib/sendmail/src/sasl.c
@@ -9,7 +9,7 @@
*/
#include
-SM_RCSID("@(#)$Id: sasl.c,v 8.21 2004/11/22 23:09:00 gshapiro Exp $")
+SM_RCSID("@(#)$Id: sasl.c,v 8.22 2006/08/15 23:24:57 ca Exp $")
#if SASL
# include
@@ -258,7 +258,7 @@ iptostring(addr, addrlen, out, outlen)
niflags |= NI_WITHSCOPEID;
# endif /* NI_WITHSCOPEID */
if (getnameinfo((struct sockaddr *) addr, addrlen,
- hbuf, sizeof hbuf, pbuf, sizeof pbuf, niflags) != 0)
+ hbuf, sizeof(hbuf), pbuf, sizeof(pbuf), niflags) != 0)
return false;
# else /* NETINET6 */
if (addr->sa.sa_family != AF_INET)
@@ -272,7 +272,7 @@ iptostring(addr, addrlen, out, outlen)
errno = ENOMEM;
return false;
}
- sm_snprintf(pbuf, sizeof pbuf, "%d", ntohs(addr->sin.sin_port));
+ sm_snprintf(pbuf, sizeof(pbuf), "%d", ntohs(addr->sin.sin_port));
# endif /* NETINET6 */
if (outlen < strlen(hbuf) + strlen(pbuf) + 2)
diff --git a/contrib/sendmail/src/sendmail.h b/contrib/sendmail/src/sendmail.h
index c1c9d84a4f8e..51f2426dbf66 100644
--- a/contrib/sendmail/src/sendmail.h
+++ b/contrib/sendmail/src/sendmail.h
@@ -52,7 +52,7 @@
#ifdef _DEFINE
# ifndef lint
-SM_UNUSED(static char SmailId[]) = "@(#)$Id: sendmail.h,v 8.1008.2.1 2006/05/23 01:32:07 ca Exp $";
+SM_UNUSED(static char SmailId[]) = "@(#)$Id: sendmail.h,v 8.1042 2007/02/27 22:21:13 ca Exp $";
# endif /* ! lint */
#endif /* _DEFINE */
@@ -70,6 +70,7 @@ SM_UNUSED(static char SmailId[]) = "@(#)$Id: sendmail.h,v 8.1008.2.1 2006/05/23
#include
#include
#include
+#include
#ifdef LOG
# include
@@ -332,7 +333,7 @@ typedef struct address ADDRESS;
extern ADDRESS NullAddress; /* a null (template) address [main.c] */
/* functions */
-extern void cataddr __P((char **, char **, char *, int, int));
+extern void cataddr __P((char **, char **, char *, int, int, bool));
extern char *crackaddr __P((char *, ENVELOPE *));
extern bool emptyaddr __P((ADDRESS *));
extern ADDRESS *getctladdr __P((ADDRESS *));
@@ -351,10 +352,24 @@ extern int sendtolist __P((char *, ADDRESS *, ADDRESS **, int, ENVELOPE *));
extern int removefromlist __P((char *, ADDRESS **, ENVELOPE *));
#endif /* MILTER */
extern void setsender __P((char *, ENVELOPE *, char **, int, bool));
+typedef void esmtp_args_F __P((ADDRESS *, char *, char *, ENVELOPE *));
+extern void parse_esmtp_args __P((ENVELOPE *, ADDRESS *, char *, char *,
+ char *, char *args[], esmtp_args_F));
+extern esmtp_args_F mail_esmtp_args;
+extern esmtp_args_F rcpt_esmtp_args;
+extern void reset_mail_esmtp_args __P((ENVELOPE *));
/* macro to simplify the common call to rewrite() */
#define REWRITE(pvp, rs, env) rewrite(pvp, rs, 0, env, MAXATOM)
+/*
+** Token Tables for prescan
+*/
+
+extern unsigned char ExtTokenTab[256]; /* external strings */
+extern unsigned char IntTokenTab[256]; /* internal strings */
+
+
/*
** Mailer definition structure.
** Every mailer known to the system is declared in this
@@ -740,7 +755,7 @@ extern int mci_purge_persistent __P((char *, char *));
extern MCI **mci_scan __P((MCI *));
extern void mci_setstat __P((MCI *, int, char *, char *));
extern void mci_store_persistent __P((MCI *));
-extern int mci_traverse_persistent __P((int (*)(), char *));
+extern int mci_traverse_persistent __P((int (*)(char *, char *), char *));
extern void mci_unlock_host __P((MCI *));
EXTERN int MaxMciCache; /* maximum entries in MCI cache */
@@ -807,13 +822,13 @@ extern struct hdrinfo HdrInfo[];
#define CHHDR_QUEUE 0x0008 /* header from queue file */
/* functions */
-extern void addheader __P((char *, char *, int, ENVELOPE *));
+extern void addheader __P((char *, char *, int, ENVELOPE *, bool));
extern unsigned long chompheader __P((char *, int, HDR **, ENVELOPE *));
extern bool commaize __P((HDR *, char *, bool, MCI *, ENVELOPE *));
extern HDR *copyheader __P((HDR *, SM_RPOOL_T *));
extern void eatheader __P((ENVELOPE *, bool, bool));
extern char *hvalue __P((char *, HDR *));
-extern void insheader __P((int, char *, char *, int, ENVELOPE *));
+extern void insheader __P((int, char *, char *, int, ENVELOPE *, bool));
extern bool isheader __P((char *));
extern bool putfromline __P((MCI *, ENVELOPE *));
extern void setupheaders __P((void));
@@ -887,9 +902,8 @@ struct envelope
int e_xfqdir; /* index into queue directories (xf) */
SM_FILE_T *e_xfp; /* transcript file */
SM_FILE_T *e_lockfp; /* the lock file for this message */
- char *e_message; /* error message; readonly; NULL, or
- * static storage, or allocated from
- * e_rpool */
+ char *e_message; /* error message; readonly; NULL,
+ * or allocated from e_rpool */
char *e_statmsg; /* stat msg (changes per delivery).
* readonly. NULL or allocated from
* e_rpool. */
@@ -911,6 +925,7 @@ struct envelope
long e_deliver_by; /* deliver by */
int e_dlvr_flag; /* deliver by flag */
SM_RPOOL_T *e_rpool; /* resource pool for this envelope */
+ unsigned int e_features; /* server features */
};
/* values for e_flags */
@@ -1022,34 +1037,37 @@ struct rewrite
** cannot conflict.
*/
+/* "out of band" indicator */
+/* sm/sendmail.h #define METAQUOTE ((unsigned char)0377) quotes the next octet */
+
/* left hand side items */
#define MATCHZANY ((unsigned char)0220) /* match zero or more tokens */
#define MATCHANY ((unsigned char)0221) /* match one or more tokens */
#define MATCHONE ((unsigned char)0222) /* match exactly one token */
#define MATCHCLASS ((unsigned char)0223) /* match one token in a class */
-#define MATCHNCLASS ((unsigned char)0224) /* match anything not in class */
-#define MATCHREPL ((unsigned char)0225) /* replacement on RHS for above */
+#define MATCHNCLASS ((unsigned char)0224) /* match tokens not in class */
/* right hand side items */
+#define MATCHREPL ((unsigned char)0225) /* RHS replacement for above */
#define CANONNET ((unsigned char)0226) /* canonical net, next token */
#define CANONHOST ((unsigned char)0227) /* canonical host, next token */
#define CANONUSER ((unsigned char)0230) /* canonical user, next N tokens */
#define CALLSUBR ((unsigned char)0231) /* call another rewriting set */
-/* conditionals in macros */
+/* conditionals in macros (anywhere) */
#define CONDIF ((unsigned char)0232) /* conditional if-then */
#define CONDELSE ((unsigned char)0233) /* conditional else */
#define CONDFI ((unsigned char)0234) /* conditional fi */
-/* bracket characters for host name lookup */
+/* bracket characters for RHS host name lookup */
#define HOSTBEGIN ((unsigned char)0235) /* hostname lookup begin */
-#define HOSTEND ((unsigned char)0236) /* hostname lookup end */
+#define HOSTEND ((unsigned char)0236) /* hostname lookup end */
-/* bracket characters for generalized lookup */
+/* bracket characters for RHS generalized lookup */
#define LOOKUPBEGIN ((unsigned char)0205) /* generalized lookup begin */
#define LOOKUPEND ((unsigned char)0206) /* generalized lookup end */
-/* macro substitution character */
+/* macro substitution characters (anywhere) */
#define MACROEXPAND ((unsigned char)0201) /* macro expansion */
#define MACRODEXPAND ((unsigned char)0202) /* deferred macro expansion */
@@ -1098,11 +1116,11 @@ extern int macid_parse __P((char *, char **));
#define macid(name) macid_parse(name, NULL)
extern char *macname __P((int));
extern char *macvalue __P((int, ENVELOPE *));
-extern int rscheck __P((char *, char *, char *, ENVELOPE *, int, int, char *, char *));
+extern int rscheck __P((char *, char *, char *, ENVELOPE *, int, int, char *, char *, ADDRESS *));
extern int rscap __P((char *, char *, char *, ENVELOPE *, char ***, char *, int));
extern void setclass __P((int, char *));
extern int strtorwset __P((char *, char **, int));
-extern void translate_dollars __P((char *));
+extern char *translate_dollars __P((char *, char *, int *));
extern bool wordinclass __P((char *, int));
/*
@@ -1279,9 +1297,9 @@ extern char *map_rewrite __P((MAP *, const char *, size_t, char **));
extern char *ni_propval __P((char *, char *, char *, char *, int));
#endif /* NETINFO */
extern bool openmap __P((MAP *));
+extern int udbexpand __P((ADDRESS *, ADDRESS **, int, ENVELOPE *));
#if USERDB
extern void _udbx_close __P((void));
-extern int udbexpand __P((ADDRESS *, ADDRESS **, int, ENVELOPE *));
extern char *udbsender __P((char *, SM_RPOOL_T *));
#endif /* USERDB */
@@ -1587,6 +1605,7 @@ extern void set_delivery_mode __P((int, ENVELOPE *));
#define PXLF_STRIP8BIT 0x0002 /* strip 8th bit */
#define PXLF_HEADER 0x0004 /* map newlines in headers */
#define PXLF_NOADDEOL 0x0008 /* if EOL not present, don't add one */
+#define PXLF_STRIPMQUOTE 0x0010 /* strip METAQUOTEs */
/*
** Privacy flags
@@ -1607,11 +1626,9 @@ extern void set_delivery_mode __P((int, ENVELOPE *));
#define PRIV_NOETRN 0x00080000 /* disallow ETRN command */
#define PRIV_NOBODYRETN 0x00100000 /* do not return bodies on bounces */
#define PRIV_NORECEIPTS 0x00200000 /* disallow return receipts */
-#if _FFR_PRIV_NOACTUALRECIPIENT
-# define PRIV_NOACTUALRECIPIENT 0x00400000 /* no X-Actual-Recipient in DSNs */
-#endif /* _FFR_PRIV_NOACTUALRECIPIENT */
+#define PRIV_NOACTUALRECIPIENT 0x00400000 /* no X-Actual-Recipient in DSNs */
-/* don't give no info, anyway, anyhow */
+/* don't give no info, anyway, anyhow (in the main SMTP transaction) */
#define PRIV_GOAWAY 0x0000ffff
/* struct defining such things */
@@ -1636,6 +1653,7 @@ EXTERN unsigned long PrivacyFlags; /* privacy flags */
#define RF_COPYPADDR 0x020 /* copy print address */
#define RF_COPYALL (RF_COPYPARSE|RF_COPYPADDR)
#define RF_COPYNONE 0
+#define RF_RM_ADDR 0x040 /* address to be removed */
/*
** Flags passed to rscheck
@@ -1699,6 +1717,12 @@ struct milter
int mf_sock; /* connected socket */
char mf_state; /* state of filter */
time_t mf_timeout[SMFTO_NUM_TO]; /* timeouts */
+#if _FFR_MILTER_CHECK
+ /* for testing only */
+ mi_int32 mf_mta_prot_version;
+ mi_int32 mf_mta_prot_flags;
+ mi_int32 mf_mta_actions;
+#endif /* _FFR_MILTER_CHECK */
};
/* MTA flags */
@@ -1706,15 +1730,6 @@ struct milter
# define SMF_TEMPFAIL 'T' /* tempfail connection on failure */
# define SMF_TEMPDROP '4' /* 421 connection on failure */
-/* states */
-# define SMFS_CLOSED 'C' /* closed for all further actions */
-# define SMFS_OPEN 'O' /* connected to remote milter filter */
-# define SMFS_INMSG 'M' /* currently servicing a message */
-# define SMFS_DONE 'D' /* done with current message */
-# define SMFS_CLOSABLE 'Q' /* done with current connection */
-# define SMFS_ERROR 'E' /* error state */
-# define SMFS_READY 'R' /* ready for action */
-
EXTERN struct milter *InputFilters[MAXFILTERS];
EXTERN char *InputFilterList;
EXTERN int MilterLogLevel;
@@ -1759,7 +1774,8 @@ extern void vendor_set_uid __P((UID_T));
struct termescape
{
char *te_rv_on; /* turn reverse-video on */
- char *te_rv_off; /* turn reverse-video off */
+ char *te_under_on; /* turn underlining on */
+ char *te_normal; /* revert to normal output */
};
/*
@@ -2162,6 +2178,7 @@ EXTERN bool DontPruneRoutes; /* don't prune source routes */
EXTERN bool ForkQueueRuns; /* fork for each job when running the queue */
EXTERN bool FromFlag; /* if set, "From" person is explicit */
EXTERN bool GrabTo; /* if set, get recipients from msg */
+EXTERN bool EightBitAddrOK; /* we'll let 8-bit addresses through */
EXTERN bool HasEightBits; /* has at least one eight bit input byte */
EXTERN bool HasWildcardMX; /* don't use MX records when canonifying */
EXTERN bool HoldErrs; /* only output errors to transcript */
@@ -2184,9 +2201,7 @@ EXTERN bool SendMIMEErrors; /* send error messages in MIME format */
EXTERN bool SevenBitInput; /* force 7-bit data on input */
EXTERN bool SingleLineFromHeader; /* force From: header to be one line */
EXTERN bool SingleThreadDelivery; /* single thread hosts on delivery */
-#if _FFR_SOFT_BOUNCE
EXTERN bool SoftBounce; /* replace 5xy by 4xy (for testing) */
-#endif /* _FFR_SOFT_BOUNCE */
EXTERN bool volatile StopRequest; /* stop sending output */
EXTERN bool SuprErrs; /* set if we are suppressing errors */
EXTERN bool TryNullMXList; /* if we are the best MX, try host directly */
@@ -2256,9 +2271,7 @@ EXTERN gid_t RunAsGid; /* GID to become for bulk of run */
EXTERN gid_t EffGid; /* effective gid */
#if SM_CONF_SHM
EXTERN key_t ShmKey; /* shared memory key */
-# if _FFR_SELECT_SHM
EXTERN char *ShmKeyFile; /* shared memory key file */
-# endif /* _FFR_SELECT_SHM */
#endif /* SM_CONF_SHM */
EXTERN pid_t CurrentPid; /* current process id */
EXTERN pid_t DaemonPid; /* process id of daemon */
@@ -2291,9 +2304,7 @@ EXTERN char *FallbackMX; /* fall back MX host */
EXTERN char *FallbackSmartHost; /* fall back smart host */
EXTERN char *FileName; /* name to print on error messages */
EXTERN char *ForwardPath; /* path to search for .forward files */
-#if _FFR_HELONAME
EXTERN char *HeloName; /* hostname to announce in HELO */
-#endif /* _FFR_HELONAME */
EXTERN char *HelpFile; /* location of SMTP help file */
EXTERN char *HostStatDir; /* location of host status information */
EXTERN char *HostsFile; /* path to /etc/hosts file */
@@ -2432,7 +2443,7 @@ extern char *milter_connect __P((char *, SOCKADDR, ENVELOPE *, char *));
extern char *milter_helo __P((char *, ENVELOPE *, char *));
extern char *milter_envfrom __P((char **, ENVELOPE *, char *));
extern char *milter_data_cmd __P((ENVELOPE *, char *));
-extern char *milter_envrcpt __P((char **, ENVELOPE *, char *));
+extern char *milter_envrcpt __P((char **, ENVELOPE *, char *, bool));
extern char *milter_data __P((ENVELOPE *, char *));
extern char *milter_unknown __P((char *, ENVELOPE *, char *));
#endif /* MILTER */
@@ -2473,25 +2484,26 @@ extern char *defcharset __P((ENVELOPE *));
extern char *denlstring __P((char *, bool, bool));
extern void dferror __P((SM_FILE_T *volatile, char *, ENVELOPE *));
extern void disconnect __P((int, ENVELOPE *));
-#if _FFR_CONTROL_MSTAT
extern void disk_status __P((SM_FILE_T *, char *));
-#endif /* _FFR_CONTROL_MSTAT */
extern bool dns_getcanonname __P((char *, int, bool, int *, int *));
extern pid_t dofork __P((void));
extern int drop_privileges __P((bool));
extern int dsntoexitstat __P((char *));
extern void dumpfd __P((int, bool, bool));
+#if SM_HEAP_CHECK
+extern void dumpstab __P((void));
+#endif /* SM_HEAP_CHECK */
extern void dumpstate __P((char *));
extern bool enoughdiskspace __P((long, ENVELOPE *));
extern char *exitstat __P((char *));
extern void fatal_error __P((SM_EXC_T *));
-extern char *fgetfolded __P((char *, int, SM_FILE_T *));
+extern char *fgetfolded __P((char *, int *, SM_FILE_T *));
extern void fill_fd __P((int, char *));
extern char *find_character __P((char *, int));
extern int finduser __P((char *, bool *, SM_MBDB_T *));
extern void finis __P((bool, bool, volatile int));
extern void fixcrlf __P((char *, bool));
-extern long freediskspace __P((char *, long *));
+extern long freediskspace __P((const char *, long *));
#if NETINET6 && NEEDSGETIPNODE
extern void freehostent __P((struct hostent *));
#endif /* NETINET6 && NEEDSGETIPNODE */
@@ -2522,7 +2534,8 @@ extern int makeconnection __P((char *, volatile unsigned int, MCI *, ENVELOPE *,
extern void makeworkgroups __P((void));
extern void markfailure __P((ENVELOPE *, ADDRESS *, MCI *, int, bool));
extern void mark_work_group_restart __P((int, int));
-extern char * munchstring __P((char *, char **, int));
+extern MCI *mci_new __P((SM_RPOOL_T *));
+extern char *munchstring __P((char *, char **, int));
extern struct hostent *myhostname __P((char *, int));
extern char *newstr __P((const char *));
#if NISPLUS
@@ -2548,6 +2561,7 @@ extern void resetlimits __P((void));
extern void restart_daemon __P((void));
extern void restart_marked_work_groups __P((void));
extern bool rfc822_string __P((char *));
+extern void rmexpstab __P((void));
extern bool savemail __P((ENVELOPE *, bool));
extern void seed_random __P((void));
extern void sendtoargv __P((char **, ENVELOPE *));
@@ -2577,15 +2591,15 @@ extern void sm_setproctitle __P((bool, ENVELOPE *, const char *, ...));
extern pid_t sm_wait __P((int *));
extern bool split_by_recipient __P((ENVELOPE *e));
extern void stop_sendmail __P((void));
-extern char *str2prt __P((char *));
extern void stripbackslash __P((char *));
extern bool strreplnonprt __P((char *, int));
extern bool strcontainedin __P((bool, char *, char *));
extern int switch_map_find __P((char *, char *[], short []));
+#if STARTTLS
+extern void tls_set_verify __P((SSL_CTX *, SSL *, bool));
+#endif /* STARTTLS */
extern bool transienterror __P((int));
-#if _FFR_BESTMX_BETTER_TRUNCATION || _FFR_DNSMAP_MULTI
extern void truncate_at_delim __P((char *, size_t, int));
-#endif /* _FFR_BESTMX_BETTER_TRUNCATION || _FFR_DNSMAP_MULTI */
extern void tTflag __P((char *));
extern void tTsetup __P((unsigned char *, unsigned int, char *));
extern SIGFUNC_DECL tick __P((int));
@@ -2623,4 +2637,5 @@ extern int xunlink __P((char *));
extern char *xuntextify __P((char *));
+#undef EXTERN
#endif /* ! _SENDMAIL_H */
diff --git a/contrib/sendmail/src/sm_resolve.c b/contrib/sendmail/src/sm_resolve.c
index affd3e579b50..d2cf96d57e28 100644
--- a/contrib/sendmail/src/sm_resolve.c
+++ b/contrib/sendmail/src/sm_resolve.c
@@ -46,7 +46,7 @@
# if NAMED_BIND
# include "sm_resolve.h"
-SM_RCSID("$Id: sm_resolve.c,v 8.33 2004/08/04 21:17:57 ca Exp $")
+SM_RCSID("$Id: sm_resolve.c,v 8.34 2006/08/15 23:24:58 ca Exp $")
static struct stot
{
@@ -184,7 +184,7 @@ parse_dns_reply(data, len)
/* doesn't work on Crays? */
memcpy(&r->dns_r_h, p, sizeof(r->dns_r_h));
p += sizeof(r->dns_r_h);
- status = dn_expand(data, data + len, p, host, sizeof host);
+ status = dn_expand(data, data + len, p, host, sizeof(host));
if (status < 0)
{
dns_free_data(r);
@@ -204,7 +204,7 @@ parse_dns_reply(data, len)
{
int type, class, ttl, size, txtlen;
- status = dn_expand(data, data + len, p, host, sizeof host);
+ status = dn_expand(data, data + len, p, host, sizeof(host));
if (status < 0)
{
dns_free_data(r);
@@ -252,7 +252,7 @@ parse_dns_reply(data, len)
case T_CNAME:
case T_PTR:
status = dn_expand(data, data + len, p, host,
- sizeof host);
+ sizeof(host));
if (status < 0)
{
dns_free_data(r);
@@ -269,7 +269,7 @@ parse_dns_reply(data, len)
case T_MX:
case T_AFSDB:
status = dn_expand(data, data + len, p + 2, host,
- sizeof host);
+ sizeof(host));
if (status < 0)
{
dns_free_data(r);
@@ -290,7 +290,7 @@ parse_dns_reply(data, len)
case T_SRV:
status = dn_expand(data, data + len, p + 6, host,
- sizeof host);
+ sizeof(host));
if (status < 0)
{
dns_free_data(r);
@@ -409,7 +409,7 @@ dns_lookup_int(domain, rr_class, rr_type, retrans, retry)
}
errno = 0;
SM_SET_H_ERRNO(0);
- len = res_search(domain, rr_class, rr_type, reply, sizeof reply);
+ len = res_search(domain, rr_class, rr_type, reply, sizeof(reply));
if (tTd(8, 16))
{
_res.options = old_options;
diff --git a/contrib/sendmail/src/srvrsmtp.c b/contrib/sendmail/src/srvrsmtp.c
index d95b5a5b7225..1f067b1d852d 100644
--- a/contrib/sendmail/src/srvrsmtp.c
+++ b/contrib/sendmail/src/srvrsmtp.c
@@ -17,7 +17,7 @@
# include
#endif /* MILTER */
-SM_RCSID("@(#)$Id: srvrsmtp.c,v 8.924.2.5 2006/07/07 16:29:39 ca Exp $")
+SM_RCSID("@(#)$Id: srvrsmtp.c,v 8.960 2007/02/07 20:18:47 ca Exp $")
#include
#include
@@ -36,15 +36,15 @@ static SSL_CTX *srv_ctx = NULL; /* TLS server context */
static SSL *srv_ssl = NULL; /* per connection context */
static bool tls_ok_srv = false;
-#if _FFR_DM_ONE
-static bool NotFirstDelivery = false;
-#endif /* _FFR_DM_ONE */
-extern void tls_set_verify __P((SSL_CTX *, SSL *, bool));
# define TLS_VERIFY_CLIENT() tls_set_verify(srv_ctx, srv_ssl, \
bitset(SRV_VRFY_CLT, features))
#endif /* STARTTLS */
+#if _FFR_DM_ONE
+static bool NotFirstDelivery = false;
+#endif /* _FFR_DM_ONE */
+
/* server features */
#define SRV_NONE 0x0000 /* none... */
#define SRV_OFFER_TLS 0x0001 /* offer STARTTLS */
@@ -70,10 +70,7 @@ static unsigned int srvfeatures __P((ENVELOPE *, char *, unsigned int));
#define STOP_ATTACK ((time_t) -1)
static time_t checksmtpattack __P((volatile unsigned int *, unsigned int,
bool, char *, ENVELOPE *));
-static void mail_esmtp_args __P((char *, char *, ENVELOPE *, unsigned int));
static void printvrfyaddr __P((ADDRESS *, bool, bool));
-static void rcpt_esmtp_args __P((ADDRESS *, char *, char *, ENVELOPE *,
- unsigned int));
static char *skipword __P((char *volatile, char *));
static void setup_smtpd_io __P((void));
@@ -115,7 +112,7 @@ extern ENVELOPE BlankEnvelope;
do \
{ \
char buf[16]; \
- (void) sm_snprintf(buf, sizeof buf, "%d", \
+ (void) sm_snprintf(buf, sizeof(buf), "%d", \
BadRcptThrottle > 0 && n_badrcpts > BadRcptThrottle \
? n_badrcpts - 1 : n_badrcpts); \
macdefine(&e->e_macro, A_TEMP, macid("{nbadrcpts}"), buf); \
@@ -124,6 +121,88 @@ extern ENVELOPE BlankEnvelope;
#define SKIP_SPACE(s) while (isascii(*s) && isspace(*s)) \
(s)++
+/*
+** PARSE_ESMTP_ARGS -- parse EMSTP arguments (for MAIL, RCPT)
+**
+** Parameters:
+** e -- the envelope
+** addr_st -- address (RCPT only)
+** p -- read buffer
+** delimptr -- current position in read buffer
+** which -- MAIL/RCPT
+** args -- arguments (output)
+** esmtp_args -- function to process a single ESMTP argument
+**
+** Returns:
+** none
+*/
+
+void
+parse_esmtp_args(e, addr_st, p, delimptr, which, args, esmtp_args)
+ ENVELOPE *e;
+ ADDRESS *addr_st;
+ char *p;
+ char *delimptr;
+ char *which;
+ char *args[];
+ esmtp_args_F esmtp_args;
+{
+ int argno;
+
+ argno = 0;
+ if (args != NULL)
+ args[argno++] = p;
+ p = delimptr;
+ while (p != NULL && *p != '\0')
+ {
+ char *kp;
+ char *vp = NULL;
+ char *equal = NULL;
+
+ /* locate the beginning of the keyword */
+ SKIP_SPACE(p);
+ if (*p == '\0')
+ break;
+ kp = p;
+
+ /* skip to the value portion */
+ while ((isascii(*p) && isalnum(*p)) || *p == '-')
+ p++;
+ if (*p == '=')
+ {
+ equal = p;
+ *p++ = '\0';
+ vp = p;
+
+ /* skip to the end of the value */
+ while (*p != '\0' && *p != ' ' &&
+ !(isascii(*p) && iscntrl(*p)) &&
+ *p != '=')
+ p++;
+ }
+
+ if (*p != '\0')
+ *p++ = '\0';
+
+ if (tTd(19, 1))
+ sm_dprintf("%s: got arg %s=\"%s\"\n", which, kp,
+ vp == NULL ? "" : vp);
+
+ esmtp_args(addr_st, kp, vp, e);
+ if (equal != NULL)
+ *equal = '=';
+ if (args != NULL)
+ args[argno] = kp;
+ argno++;
+ if (argno >= MAXSMTPARGS - 1)
+ usrerr("501 5.5.4 Too many parameters");
+ if (Errors > 0)
+ break;
+ }
+ if (args != NULL)
+ args[argno] = NULL;
+}
+
/*
** SMTP -- run the SMTP protocol.
**
@@ -291,6 +370,7 @@ static bool smtp_data __P((SMTP_T *, ENVELOPE *));
{ \
int savelogusrerrs = LogUsrErrs; \
\
+ milter_cmd_fail = true; \
switch (state) \
{ \
case SMFIR_SHUTDOWN: \
@@ -351,6 +431,7 @@ static bool smtp_data __P((SMTP_T *, ENVELOPE *));
"Milter: %s=%s, discard", \
str, addr); \
e->e_flags |= EF_DISCARD; \
+ milter_cmd_fail = false; \
break; \
\
case SMFIR_TEMPFAIL: \
@@ -363,6 +444,9 @@ static bool smtp_data __P((SMTP_T *, ENVELOPE *));
} \
usrerr(MSG_TEMPFAIL); \
break; \
+ default: \
+ milter_cmd_fail = false; \
+ break; \
} \
LogUsrErrs = savelogusrerrs; \
if (response != NULL) \
@@ -402,6 +486,7 @@ do \
sm_rpool_free(e->e_rpool); \
e = newenvelope(e, CurEnv, sm_rpool_new_x(NULL)); \
CurEnv = e; \
+ e->e_features = features; \
\
/* put back discard bit */ \
if (smtp.sm_discard) \
@@ -448,6 +533,7 @@ do \
qid_printname(e), CurSmtpClient, inp); \
}
+static bool SevenBitInput_Saved; /* saved version of SevenBitInput */
void
smtp(nullserver, d_flags, e)
@@ -473,11 +559,8 @@ smtp(nullserver, d_flags, e)
volatile unsigned int n_etrn = 0; /* count of ETRN */
volatile unsigned int n_noop = 0; /* count of NOOP/VERB/etc */
volatile unsigned int n_helo = 0; /* count of HELO/EHLO */
- volatile int save_sevenbitinput;
bool ok;
-#if _FFR_BLOCK_PROXIES
volatile bool first;
-#endif /* _FFR_BLOCK_PROXIES */
volatile bool tempfail = false;
volatile time_t wt; /* timeout after too many commands */
volatile time_t previous; /* time after checksmtpattack() */
@@ -488,9 +571,11 @@ smtp(nullserver, d_flags, e)
char *greetcode = "220";
char *hostname; /* my hostname ($j) */
QUEUE_CHAR *new;
- int argno;
char *args[MAXSMTPARGS];
- char inp[MAXLINE];
+ char inp[MAXINPLINE];
+#if MAXINPLINE < MAXLINE
+ ERROR _MAXINPLINE must NOT be less than _MAXLINE: MAXINPLINE < MAXLINE
+#endif /* MAXINPLINE < MAXLINE */
char cmdbuf[MAXLINE];
#if SASL
sasl_conn_t *conn;
@@ -502,7 +587,7 @@ smtp(nullserver, d_flags, e)
char *user;
char *in, *out2;
# if SASL >= 20000
- char *auth_id;
+ char *auth_id = NULL;
const char *out;
sasl_ssf_t ext_ssf;
char localip[60], remoteip[60];
@@ -521,6 +606,7 @@ smtp(nullserver, d_flags, e)
char *mechlist;
volatile unsigned int n_mechs;
unsigned int len;
+#else /* SASL */
#endif /* SASL */
int r;
#if STARTTLS
@@ -538,12 +624,22 @@ smtp(nullserver, d_flags, e)
# endif /* _FFR_NO_PIPE */
#endif /* PIPELINING */
volatile time_t log_delay = (time_t) 0;
+#if MILTER
+ volatile bool milter_cmd_done, milter_cmd_safe;
+ volatile bool milter_rcpt_added, milter_cmd_fail;
+ ADDRESS addr_st;
+# define p_addr_st &addr_st
+#else /* MILTER */
+# define p_addr_st NULL
+#endif /* MILTER */
+ size_t inplen;
- save_sevenbitinput = SevenBitInput;
+ SevenBitInput_Saved = SevenBitInput;
smtp.sm_nrcpts = 0;
#if MILTER
smtp.sm_milterize = (nullserver == NULL);
smtp.sm_milterlist = false;
+ addr = NULL;
#endif /* MILTER */
/* setup I/O fd correctly for the SMTP server */
@@ -641,6 +737,7 @@ smtp(nullserver, d_flags, e)
goto doquit;
}
+ e->e_features = features;
hostname = macvalue('j', e);
#if SASL
if (AuthRealm == NULL)
@@ -704,7 +801,7 @@ smtp(nullserver, d_flags, e)
&addrsize) == 0)
{
if (iptostring(&saddr_r, addrsize,
- remoteip, sizeof remoteip))
+ remoteip, sizeof(remoteip)))
{
sasl_setprop(conn, SASL_IPREMOTEPORT,
remoteip);
@@ -718,7 +815,7 @@ smtp(nullserver, d_flags, e)
{
if (iptostring(&saddr_l, addrsize,
localip,
- sizeof localip))
+ sizeof(localip)))
{
sasl_setprop(conn,
SASL_IPLOCALPORT,
@@ -764,7 +861,7 @@ smtp(nullserver, d_flags, e)
# endif /* 0 */
/* set properties */
- (void) memset(&ssp, '\0', sizeof ssp);
+ (void) memset(&ssp, '\0', sizeof(ssp));
/* XXX should these be options settable via .cf ? */
/* ssp.min_ssf = 0; is default due to memset() */
@@ -852,7 +949,9 @@ smtp(nullserver, d_flags, e)
char *response;
q = macvalue(macid("{client_name}"), e);
- SM_ASSERT(q != NULL);
+ SM_ASSERT(q != NULL || OpMode == MD_SMTP);
+ if (q == NULL)
+ q = "localhost";
response = milter_connect(q, RealHostAddr, e, &state);
switch (state)
{
@@ -907,7 +1006,7 @@ smtp(nullserver, d_flags, e)
#if STARTTLS
!smtps &&
#endif /* STARTTLS */
- *greetcode == '2')
+ *greetcode == '2' && nullserver == NULL)
{
time_t msecs = 0;
char **pvp;
@@ -929,9 +1028,8 @@ smtp(nullserver, d_flags, e)
int fd;
fd_set readfds;
struct timeval timeout;
-#if _FFR_LOG_GREET_PAUSE
struct timeval bp, ep, tp; /* {begin,end,total}pause */
-#endif /* _FFR_LOG_GREET_PAUSE */
+ int eoftest;
/* pause for a moment */
timeout.tv_sec = msecs / 1000;
@@ -948,31 +1046,25 @@ smtp(nullserver, d_flags, e)
fd = sm_io_getinfo(InChannel, SM_IO_WHAT_FD, NULL);
FD_ZERO(&readfds);
SM_FD_SET(fd, &readfds);
-#if _FFR_LOG_GREET_PAUSE
gettimeofday(&bp, NULL);
-#endif /* _FFR_LOG_GREET_PAUSE */
if (select(fd + 1, FDSET_CAST &readfds,
NULL, NULL, &timeout) > 0 &&
- FD_ISSET(fd, &readfds))
+ FD_ISSET(fd, &readfds) &&
+ (eoftest = sm_io_getc(InChannel, SM_TIME_DEFAULT))
+ != SM_IO_EOF)
{
-#if _FFR_LOG_GREET_PAUSE
+ sm_io_ungetc(InChannel, SM_TIME_DEFAULT,
+ eoftest);
gettimeofday(&ep, NULL);
timersub(&ep, &bp, &tp);
-#endif /* _FFR_LOG_GREET_PAUSE */
greetcode = "554";
nullserver = "Command rejected";
sm_syslog(LOG_INFO, e->e_id,
-#if _FFR_LOG_GREET_PAUSE
- "rejecting commands from %s [%s] after %d seconds due to pre-greeting traffic",
-#else /* _FFR_LOG_GREET_PAUSE */
- "rejecting commands from %s [%s] due to pre-greeting traffic",
-#endif /* _FFR_LOG_GREET_PAUSE */
+ "rejecting commands from %s [%s] due to pre-greeting traffic after %d seconds",
peerhostname,
- anynet_ntoa(&RealHostAddr)
-#if _FFR_LOG_GREET_PAUSE
- , (int) tp.tv_sec +
+ anynet_ntoa(&RealHostAddr),
+ (int) tp.tv_sec +
(tp.tv_usec >= 500000 ? 1 : 0)
-#endif /* _FFR_LOG_GREET_PAUSE */
);
}
}
@@ -992,10 +1084,10 @@ smtp(nullserver, d_flags, e)
/* output the first line, inserting "ESMTP" as second word */
if (*greetcode == '5')
- (void) sm_snprintf(inp, sizeof inp, "%s not accepting messages",
- hostname);
+ (void) sm_snprintf(inp, sizeof(inp),
+ "%s not accepting messages", hostname);
else
- expand(SmtpGreeting, inp, sizeof inp, e);
+ expand(SmtpGreeting, inp, sizeof(inp), e);
p = strchr(inp, '\n');
if (p != NULL)
@@ -1004,10 +1096,10 @@ smtp(nullserver, d_flags, e)
if (id == NULL)
id = &inp[strlen(inp)];
if (p == NULL)
- (void) sm_snprintf(cmdbuf, sizeof cmdbuf,
+ (void) sm_snprintf(cmdbuf, sizeof(cmdbuf),
"%s %%.*s ESMTP%%s", greetcode);
else
- (void) sm_snprintf(cmdbuf, sizeof cmdbuf,
+ (void) sm_snprintf(cmdbuf, sizeof(cmdbuf),
"%s-%%.*s ESMTP%%s", greetcode);
message(cmdbuf, (int) (id - inp), inp, id);
@@ -1017,14 +1109,14 @@ smtp(nullserver, d_flags, e)
*p++ = '\0';
if (isascii(*id) && isspace(*id))
id++;
- (void) sm_strlcpyn(cmdbuf, sizeof cmdbuf, 2, greetcode, "-%s");
+ (void) sm_strlcpyn(cmdbuf, sizeof(cmdbuf), 2, greetcode, "-%s");
message(cmdbuf, id);
}
if (id != NULL)
{
if (isascii(*id) && isspace(*id))
id++;
- (void) sm_strlcpyn(cmdbuf, sizeof cmdbuf, 2, greetcode, " %s");
+ (void) sm_strlcpyn(cmdbuf, sizeof(cmdbuf), 2, greetcode, " %s");
message(cmdbuf, id);
}
@@ -1040,9 +1132,7 @@ smtp(nullserver, d_flags, e)
/* sendinghost's storage must outlive the current envelope */
if (sendinghost != NULL)
sendinghost = sm_strdup_x(sendinghost);
-#if _FFR_BLOCK_PROXIES
first = true;
-#endif /* _FFR_BLOCK_PROXIES */
gothello = false;
smtp.sm_gotmail = false;
for (;;)
@@ -1055,6 +1145,9 @@ smtp(nullserver, d_flags, e)
LogUsrErrs = false;
OnlyOneError = true;
e->e_flags &= ~(EF_VRFYONLY|EF_GLOBALERRS);
+#if MILTER
+ milter_cmd_fail = false;
+#endif /* MILTER */
/* setup for the read */
e->e_to = NULL;
@@ -1065,16 +1158,10 @@ smtp(nullserver, d_flags, e)
/* read the input line */
SmtpPhase = "server cmd read";
sm_setproctitle(true, e, "server %s cmd read", CurSmtpClient);
-#if SASL
- /*
- ** XXX SMTP AUTH requires accepting any length,
- ** at least for challenge/response
- */
-#endif /* SASL */
/* handle errors */
if (sm_io_error(OutChannel) ||
- (p = sfgets(inp, sizeof inp, InChannel,
+ (p = sfgets(inp, sizeof(inp), InChannel,
TimeOuts.to_nextcommand, SmtpPhase)) == NULL)
{
char *d;
@@ -1107,16 +1194,36 @@ smtp(nullserver, d_flags, e)
goto doquit;
}
-#if _FFR_BLOCK_PROXIES
+ /* also used by "proxy" check below */
+ inplen = strlen(inp);
+#if SASL
+ /*
+ ** SMTP AUTH requires accepting any length,
+ ** at least for challenge/response. However, not imposing
+ ** a limit is a bad idea (denial of service).
+ */
+
+ if (authenticating != SASL_PROC_AUTH
+ && sm_strncasecmp(inp, "AUTH ", 5) != 0
+ && inplen > MAXLINE)
+ {
+ message("421 4.7.0 %s Command too long, possible attack %s",
+ MyHostName, CurSmtpClient);
+ sm_syslog(LOG_INFO, e->e_id,
+ "%s: SMTP violation, input too long: %lu",
+ CurSmtpClient, (unsigned long) inplen);
+ goto doquit;
+ }
+#endif /* SASL */
+
if (first)
{
- size_t inplen, cmdlen;
+ size_t cmdlen;
int idx;
char *http_cmd;
static char *http_cmds[] = { "GET", "POST",
"CONNECT", "USER", NULL };
- inplen = strlen(inp);
for (idx = 0; (http_cmd = http_cmds[idx]) != NULL;
idx++)
{
@@ -1136,7 +1243,6 @@ smtp(nullserver, d_flags, e)
}
first = false;
}
-#endif /* _FFR_BLOCK_PROXIES */
/* clean up end of line */
fixcrlf(inp, true);
@@ -1270,7 +1376,7 @@ smtp(nullserver, d_flags, e)
{
char pbuf[8];
- (void) sm_snprintf(pbuf, sizeof pbuf,
+ (void) sm_snprintf(pbuf, sizeof(pbuf),
"%u", *ssf);
macdefine(&BlankEnvelope.e_macro,
A_TEMP,
@@ -1386,7 +1492,7 @@ smtp(nullserver, d_flags, e)
cmd = cmdbuf;
while (*p != '\0' &&
!(isascii(*p) && isspace(*p)) &&
- cmd < &cmdbuf[sizeof cmdbuf - 2])
+ cmd < &cmdbuf[sizeof(cmdbuf) - 2])
*cmd++ = *p++;
*cmd = '\0';
@@ -1801,7 +1907,7 @@ smtp(nullserver, d_flags, e)
macvalue(macid("{verify}"), e),
"STARTTLS", e,
RSF_RMCOMM|RSF_COUNT,
- 5, NULL, NOQID) != EX_OK ||
+ 5, NULL, NOQID, NULL) != EX_OK ||
Errors > 0)
{
extern char MsgBuf[];
@@ -1992,15 +2098,6 @@ smtp(nullserver, d_flags, e)
response = milter_helo(p, e, &state);
switch (state)
{
- case SMFIR_REPLYCODE:
- if (MilterLogLevel > 3)
- sm_syslog(LOG_INFO, e->e_id,
- "Milter: helo=%s, reject=%s",
- p, response);
- nullserver = newstr(response);
- smtp.sm_milterize = false;
- break;
-
case SMFIR_REJECT:
if (MilterLogLevel > 3)
sm_syslog(LOG_INFO, e->e_id,
@@ -2019,17 +2116,36 @@ smtp(nullserver, d_flags, e)
smtp.sm_milterize = false;
break;
- case SMFIR_SHUTDOWN:
+ case SMFIR_REPLYCODE:
if (MilterLogLevel > 3)
+ sm_syslog(LOG_INFO, e->e_id,
+ "Milter: helo=%s, reject=%s",
+ p, response);
+ if (strncmp(response, "421 ", 4) != 0
+ && strncmp(response, "421-", 4) != 0)
+ {
+ nullserver = newstr(response);
+ smtp.sm_milterize = false;
+ break;
+ }
+ /* FALLTHROUGH */
+
+ case SMFIR_SHUTDOWN:
+ if (MilterLogLevel > 3 &&
+ response == NULL)
sm_syslog(LOG_INFO, e->e_id,
"Milter: helo=%s, reject=421 4.7.0 %s closing connection",
p, MyHostName);
tempfail = true;
smtp.sm_milterize = false;
- message("421 4.7.0 %s closing connection",
- MyHostName);
+ if (response != NULL)
+ usrerr(response);
+ else
+ message("421 4.7.0 %s closing connection",
+ MyHostName);
/* arrange to ignore send list */
e->e_sendqueue = NULL;
+ lognullconnection = false;
goto doquit;
}
if (response != NULL)
@@ -2258,59 +2374,13 @@ smtp(nullserver, d_flags, e)
}
/* reset to default value */
- SevenBitInput = save_sevenbitinput;
+ SevenBitInput = SevenBitInput_Saved;
/* now parse ESMTP arguments */
e->e_msgsize = 0;
addr = p;
- argno = 0;
- args[argno++] = p;
- p = delimptr;
- while (p != NULL && *p != '\0')
- {
- char *kp;
- char *vp = NULL;
- char *equal = NULL;
-
- /* locate the beginning of the keyword */
- SKIP_SPACE(p);
- if (*p == '\0')
- break;
- kp = p;
-
- /* skip to the value portion */
- while ((isascii(*p) && isalnum(*p)) || *p == '-')
- p++;
- if (*p == '=')
- {
- equal = p;
- *p++ = '\0';
- vp = p;
-
- /* skip to the end of the value */
- while (*p != '\0' && *p != ' ' &&
- !(isascii(*p) && iscntrl(*p)) &&
- *p != '=')
- p++;
- }
-
- if (*p != '\0')
- *p++ = '\0';
-
- if (tTd(19, 1))
- sm_dprintf("MAIL: got arg %s=\"%s\"\n", kp,
- vp == NULL ? "" : vp);
-
- mail_esmtp_args(kp, vp, e, features);
- if (equal != NULL)
- *equal = '=';
- args[argno++] = kp;
- if (argno >= MAXSMTPARGS - 1)
- usrerr("501 5.5.4 Too many parameters");
- if (Errors > 0)
- sm_exc_raisenew_x(&EtypeQuickAbort, 1);
- }
- args[argno] = NULL;
+ parse_esmtp_args(e, NULL, p, delimptr, "MAIL", args,
+ mail_esmtp_args);
if (Errors > 0)
sm_exc_raisenew_x(&EtypeQuickAbort, 1);
@@ -2344,7 +2414,7 @@ smtp(nullserver, d_flags, e)
#endif /* _FFR_MAIL_MACRO */
if (rscheck("check_mail", addr,
NULL, e, RSF_RMCOMM|RSF_COUNT, 3,
- NULL, e->e_id) != EX_OK ||
+ NULL, e->e_id, NULL) != EX_OK ||
Errors > 0)
sm_exc_raisenew_x(&EtypeQuickAbort, 1);
macdefine(&e->e_macro, A_PERM,
@@ -2423,6 +2493,17 @@ smtp(nullserver, d_flags, e)
case CMDRCPT: /* rcpt -- designate recipient */
DELAY_CONN("RCPT");
+ macdefine(&e->e_macro, A_PERM,
+ macid("{rcpt_mailer}"), NULL);
+ macdefine(&e->e_macro, A_PERM,
+ macid("{rcpt_host}"), NULL);
+ macdefine(&e->e_macro, A_PERM,
+ macid("{rcpt_addr}"), NULL);
+#if MILTER
+ (void) memset(&addr_st, '\0', sizeof(addr_st));
+ a = NULL;
+ milter_rcpt_added = false;
+#endif
if (BadRcptThrottle > 0 &&
n_badrcpts >= BadRcptThrottle)
{
@@ -2476,16 +2557,16 @@ smtp(nullserver, d_flags, e)
#if MILTER
/*
- ** If the filter will be deleting recipients,
- ** don't expand them at RCPT time (in the call
+ ** Do not expand recipients at RCPT time (in the call
** to recipient()). If they are expanded, it
** is impossible for removefromlist() to figure
** out the expanded members of the original
** recipient and mark them as QS_DONTSEND.
*/
- if (milter_can_delrcpts())
- e->e_flags |= EF_VRFYONLY;
+ e->e_flags |= EF_VRFYONLY;
+ milter_cmd_done = false;
+ milter_cmd_safe = false;
#endif /* MILTER */
p = skipword(p, "to");
@@ -2533,63 +2614,34 @@ smtp(nullserver, d_flags, e)
/* now parse ESMTP arguments */
addr = p;
- argno = 0;
- args[argno++] = p;
- p = delimptr;
- while (p != NULL && *p != '\0')
- {
- char *kp;
- char *vp = NULL;
- char *equal = NULL;
-
- /* locate the beginning of the keyword */
- SKIP_SPACE(p);
- if (*p == '\0')
- break;
- kp = p;
-
- /* skip to the value portion */
- while ((isascii(*p) && isalnum(*p)) || *p == '-')
- p++;
- if (*p == '=')
- {
- equal = p;
- *p++ = '\0';
- vp = p;
-
- /* skip to the end of the value */
- while (*p != '\0' && *p != ' ' &&
- !(isascii(*p) && iscntrl(*p)) &&
- *p != '=')
- p++;
- }
-
- if (*p != '\0')
- *p++ = '\0';
-
- if (tTd(19, 1))
- sm_dprintf("RCPT: got arg %s=\"%s\"\n", kp,
- vp == NULL ? "" : vp);
-
- rcpt_esmtp_args(a, kp, vp, e, features);
- if (equal != NULL)
- *equal = '=';
- args[argno++] = kp;
- if (argno >= MAXSMTPARGS - 1)
- usrerr("501 5.5.4 Too many parameters");
- if (Errors > 0)
- break;
- }
- args[argno] = NULL;
+ parse_esmtp_args(e, a, p, delimptr, "RCPT", args,
+ rcpt_esmtp_args);
if (Errors > 0)
goto rcpt_done;
+#if MILTER
+ /*
+ ** rscheck() can trigger an "exception"
+ ** in which case the execution continues at
+ ** SM_EXCEPT(exc, "[!F]*")
+ ** This means milter_cmd_safe is not set
+ ** and hence milter is not invoked.
+ ** Would it be "safe" to change that, i.e., use
+ ** milter_cmd_safe = true;
+ ** here so a milter is informed (if requested)
+ ** about RCPTs that are rejected by check_rcpt?
+ */
+# if _FFR_MILTER_CHECK_REJECTIONS_TOO
+ milter_cmd_safe = true;
+# endif
+#endif
+
/* do config file checking of the recipient */
macdefine(&e->e_macro, A_PERM,
macid("{addr_type}"), "e r");
if (rscheck("check_rcpt", addr,
NULL, e, RSF_RMCOMM|RSF_COUNT, 3,
- NULL, e->e_id) != EX_OK ||
+ NULL, e->e_id, p_addr_st) != EX_OK ||
Errors > 0)
goto rcpt_done;
macdefine(&e->e_macro, A_PERM,
@@ -2598,38 +2650,74 @@ smtp(nullserver, d_flags, e)
/* If discarding, don't bother to verify user */
if (bitset(EF_DISCARD, e->e_flags))
a->q_state = QS_VERIFIED;
+#if MILTER
+ milter_cmd_safe = true;
+#endif
+
+ /* save in recipient list after ESMTP mods */
+ a = recipient(a, &e->e_sendqueue, 0, e);
+ /* may trigger exception... */
#if MILTER
+ milter_rcpt_added = true;
+#endif
+
+ if(!(Errors > 0) && QS_IS_BADADDR(a->q_state))
+ {
+ /* punt -- should keep message in ADDRESS.... */
+ usrerr("550 5.1.1 Addressee unknown");
+ }
+
+#if MILTER
+ rcpt_done:
if (smtp.sm_milterlist && smtp.sm_milterize &&
!bitset(EF_DISCARD, e->e_flags))
{
char state;
char *response;
- response = milter_envrcpt(args, e, &state);
+ /* how to get the error codes? */
+ if (Errors > 0)
+ {
+ macdefine(&e->e_macro, A_PERM,
+ macid("{rcpt_mailer}"),
+ "error");
+ if (a != NULL &&
+ a->q_status != NULL &&
+ a->q_rstatus != NULL)
+ {
+ macdefine(&e->e_macro, A_PERM,
+ macid("{rcpt_host}"),
+ a->q_status);
+ macdefine(&e->e_macro, A_PERM,
+ macid("{rcpt_addr}"),
+ a->q_rstatus);
+ }
+ else
+ {
+ if (addr_st.q_host != NULL)
+ macdefine(&e->e_macro,
+ A_PERM,
+ macid("{rcpt_host}"),
+ addr_st.q_host);
+ if (addr_st.q_user != NULL)
+ macdefine(&e->e_macro,
+ A_PERM,
+ macid("{rcpt_addr}"),
+ addr_st.q_user);
+ }
+ }
+
+ response = milter_envrcpt(args, e, &state,
+ Errors > 0);
+ milter_cmd_done = true;
MILTER_REPLY("to");
}
#endif /* MILTER */
- macdefine(&e->e_macro, A_PERM,
- macid("{rcpt_mailer}"), NULL);
- macdefine(&e->e_macro, A_PERM,
- macid("{rcpt_host}"), NULL);
- macdefine(&e->e_macro, A_PERM,
- macid("{rcpt_addr}"), NULL);
- macdefine(&e->e_macro, A_PERM,
- macid("{dsn_notify}"), NULL);
- if (Errors > 0)
- goto rcpt_done;
-
- /* save in recipient list after ESMTP mods */
- a = recipient(a, &e->e_sendqueue, 0, e);
- if (Errors > 0)
- goto rcpt_done;
-
/* no errors during parsing, but might be a duplicate */
e->e_to = a->q_paddr;
- if (!QS_IS_BADADDR(a->q_state))
+ if (!(Errors > 0) && !QS_IS_BADADDR(a->q_state))
{
if (smtp.sm_nrcpts == 0)
initsys(e);
@@ -2638,12 +2726,20 @@ smtp(nullserver, d_flags, e)
" (will queue)" : "");
smtp.sm_nrcpts++;
}
- else
- {
- /* punt -- should keep message in ADDRESS.... */
- usrerr("550 5.1.1 Addressee unknown");
- }
- rcpt_done:
+
+ /* Is this needed? */
+#if !MILTER
+ rcpt_done:
+#endif /* !MILTER */
+ macdefine(&e->e_macro, A_PERM,
+ macid("{rcpt_mailer}"), NULL);
+ macdefine(&e->e_macro, A_PERM,
+ macid("{rcpt_host}"), NULL);
+ macdefine(&e->e_macro, A_PERM,
+ macid("{rcpt_addr}"), NULL);
+ macdefine(&e->e_macro, A_PERM,
+ macid("{dsn_notify}"), NULL);
+
if (Errors > 0)
{
++n_badrcpts;
@@ -2656,6 +2752,55 @@ smtp(nullserver, d_flags, e)
e->e_flags &= ~(EF_FATALERRS|EF_PM_NOTIFY);
++n_badrcpts;
NBADRCPTS;
+#if MILTER
+ if (smtp.sm_milterlist && smtp.sm_milterize &&
+ !bitset(EF_DISCARD, e->e_flags) &&
+ !milter_cmd_done && milter_cmd_safe)
+ {
+ char state;
+ char *response;
+
+ macdefine(&e->e_macro, A_PERM,
+ macid("{rcpt_mailer}"), "error");
+
+ /* how to get the error codes? */
+ if (addr_st.q_host != NULL)
+ macdefine(&e->e_macro, A_PERM,
+ macid("{rcpt_host}"),
+ addr_st.q_host);
+ else if (a != NULL && a->q_status != NULL)
+ macdefine(&e->e_macro, A_PERM,
+ macid("{rcpt_host}"),
+ a->q_status);
+
+ if (addr_st.q_user != NULL)
+ macdefine(&e->e_macro, A_PERM,
+ macid("{rcpt_addr}"),
+ addr_st.q_user);
+ else if (a != NULL && a->q_rstatus != NULL)
+ macdefine(&e->e_macro, A_PERM,
+ macid("{rcpt_addr}"),
+ a->q_rstatus);
+
+ response = milter_envrcpt(args, e, &state,
+ true);
+ milter_cmd_done = true;
+ MILTER_REPLY("to");
+ macdefine(&e->e_macro, A_PERM,
+ macid("{rcpt_mailer}"), NULL);
+ macdefine(&e->e_macro, A_PERM,
+ macid("{rcpt_host}"), NULL);
+ macdefine(&e->e_macro, A_PERM,
+ macid("{rcpt_addr}"), NULL);
+ }
+ if (smtp.sm_milterlist && smtp.sm_milterize &&
+ milter_rcpt_added && milter_cmd_done &&
+ milter_cmd_fail)
+ {
+ (void) removefromlist(addr, &e->e_sendqueue, e);
+ milter_cmd_fail = false;
+ }
+#endif /* MILTER */
}
SM_END_TRY
break;
@@ -2738,7 +2883,7 @@ smtp(nullserver, d_flags, e)
/* do config file checking of the address */
if (rscheck(vrfy ? "check_vrfy" : "check_expn",
p, NULL, e, RSF_RMCOMM,
- 3, NULL, NOQID) != EX_OK ||
+ 3, NULL, NOQID, NULL) != EX_OK ||
Errors > 0)
sm_exc_raisenew_x(&EtypeQuickAbort, 1);
(void) sendtolist(p, NULLADDR, &vrfyqueue, 0, e);
@@ -2834,7 +2979,8 @@ smtp(nullserver, d_flags, e)
*/
if (rscheck("check_etrn", p, NULL, e,
- RSF_RMCOMM, 3, NULL, NOQID) != EX_OK ||
+ RSF_RMCOMM, 3, NULL, NOQID, NULL)
+ != EX_OK ||
Errors > 0)
break;
@@ -2997,7 +3143,7 @@ smtp(nullserver, d_flags, e)
break;
case CMDDBGDEBUG: /* set debug mode */
- tTsetup(tTdvect, sizeof tTdvect, "0-99.1");
+ tTsetup(tTdvect, sizeof(tTdvect), "0-99.1");
tTflag(p);
message("200 2.0.0 Debug set");
break;
@@ -3106,12 +3252,13 @@ smtp_data(smtp, e)
#endif /* MILTER */
bool aborting;
bool doublequeue;
+ bool rv = true;
ADDRESS *a;
ENVELOPE *ee;
char *id;
char *oldid;
+ unsigned int features;
char buf[32];
- bool rv = true;
SmtpPhase = "server DATA";
if (!smtp->sm_gotmail)
@@ -3124,10 +3271,10 @@ smtp_data(smtp, e)
usrerr("503 5.0.0 Need RCPT (recipient)");
return true;
}
- (void) sm_snprintf(buf, sizeof buf, "%u", smtp->sm_nrcpts);
+ (void) sm_snprintf(buf, sizeof(buf), "%u", smtp->sm_nrcpts);
if (rscheck("check_data", buf, NULL, e,
RSF_RMCOMM|RSF_UNSTRUCTURED|RSF_COUNT, 3, NULL,
- e->e_id) != EX_OK)
+ e->e_id, NULL) != EX_OK)
return true;
#if MILTER && SMFI_VERSION > 3
@@ -3233,14 +3380,12 @@ smtp_data(smtp, e)
collect(InChannel, true, NULL, e, true);
/* redefine message size */
- (void) sm_snprintf(buf, sizeof buf, "%ld", e->e_msgsize);
+ (void) sm_snprintf(buf, sizeof(buf), "%ld", e->e_msgsize);
macdefine(&e->e_macro, A_TEMP, macid("{msg_size}"), buf);
-#if _FFR_CHECK_EOM
/* rscheck() will set Errors or EF_DISCARD if it trips */
(void) rscheck("check_eom", buf, NULL, e, RSF_UNSTRUCTURED|RSF_COUNT,
- 3, NULL, e->e_id);
-#endif /* _FFR_CHECK_EOM */
+ 3, NULL, e->e_id, NULL);
#if MILTER
milteraccept = true;
@@ -3303,7 +3448,7 @@ smtp_data(smtp, e)
}
/* Milter may have changed message size */
- (void) sm_snprintf(buf, sizeof buf, "%ld", e->e_msgsize);
+ (void) sm_snprintf(buf, sizeof(buf), "%ld", e->e_msgsize);
macdefine(&e->e_macro, A_TEMP, macid("{msg_size}"), buf);
/* abort message filters that didn't get the body & log msg is OK */
@@ -3509,7 +3654,7 @@ smtp_data(smtp, e)
{
char msg[MAXLINE];
- expand(MessageAccept, msg, sizeof msg, e);
+ expand(MessageAccept, msg, sizeof(msg), e);
message("250 2.0.0 %s", msg);
}
else
@@ -3603,8 +3748,10 @@ smtp_data(smtp, e)
*/
CurEnv = e;
+ features = e->e_features;
newenvelope(e, e, sm_rpool_new_x(NULL));
e->e_flags = BlankEnvelope.e_flags;
+ e->e_features = features;
/* restore connection quarantining */
if (smtp->sm_quarmsg == NULL)
@@ -3855,24 +4002,68 @@ skipword(p, w)
}
/*
-** MAIL_ESMTP_ARGS -- process ESMTP arguments from MAIL line
+** RESET_MAIL_ESMTP_ARGS -- process ESMTP arguments from MAIL line
**
** Parameters:
-** kp -- the parameter key.
-** vp -- the value of that parameter.
** e -- the envelope.
-** features -- current server features
**
** Returns:
** none.
*/
-static void
-mail_esmtp_args(kp, vp, e, features)
+void
+reset_mail_esmtp_args(e)
+ ENVELOPE *e;
+{
+ /* "size": no reset */
+
+ /* "body" */
+ SevenBitInput = SevenBitInput_Saved;
+ e->e_bodytype = NULL;
+
+ /* "envid" */
+ e->e_envid = NULL;
+ macdefine(&e->e_macro, A_PERM, macid("{dsn_envid}"), NULL);
+
+ /* "ret" */
+ e->e_flags &= EF_RET_PARAM;
+ e->e_flags &= EF_NO_BODY_RETN;
+ macdefine(&e->e_macro, A_TEMP, macid("{dsn_ret}"), NULL);
+
+#if SASL
+ /* "auth" */
+ macdefine(&e->e_macro, A_TEMP, macid("{auth_author}"), NULL);
+ e->e_auth_param = "";
+# if _FFR_AUTH_PASSING
+ macdefine(&BlankEnvelope.e_macro, A_PERM,
+ macid("{auth_author}"), NULL);
+# endif /* _FFR_AUTH_PASSING */
+#endif /* SASL */
+
+ /* "by" */
+ e->e_deliver_by = 0;
+ e->e_dlvr_flag = 0;
+}
+
+/*
+** MAIL_ESMTP_ARGS -- process ESMTP arguments from MAIL line
+**
+** Parameters:
+** a -- address (unused, for compatibility with rcpt_esmtp_args)
+** kp -- the parameter key.
+** vp -- the value of that parameter.
+** e -- the envelope.
+**
+** Returns:
+** none.
+*/
+
+void
+mail_esmtp_args(a, kp, vp, e)
+ ADDRESS *a;
char *kp;
char *vp;
ENVELOPE *e;
- unsigned int features;
{
if (sm_strcasecmp(kp, "size") == 0)
{
@@ -3919,7 +4110,7 @@ mail_esmtp_args(kp, vp, e, features)
}
else if (sm_strcasecmp(kp, "envid") == 0)
{
- if (!bitset(SRV_OFFER_DSN, features))
+ if (!bitset(SRV_OFFER_DSN, e->e_features))
{
usrerr("504 5.7.0 Sorry, ENVID not supported, we do not allow DSN");
/* NOTREACHED */
@@ -3945,7 +4136,7 @@ mail_esmtp_args(kp, vp, e, features)
}
else if (sm_strcasecmp(kp, "ret") == 0)
{
- if (!bitset(SRV_OFFER_DSN, features))
+ if (!bitset(SRV_OFFER_DSN, e->e_features))
{
usrerr("504 5.7.0 Sorry, RET not supported, we do not allow DSN");
/* NOTREACHED */
@@ -4018,7 +4209,7 @@ mail_esmtp_args(kp, vp, e, features)
QuickAbort = false;
if (strcmp(auth_param, "<>") != 0 &&
(rscheck("trust_auth", auth_param, NULL, e, RSF_RMCOMM,
- 9, NULL, NOQID) != EX_OK || Errors > 0))
+ 9, NULL, NOQID, NULL) != EX_OK || Errors > 0))
{
if (tTd(95, 8))
{
@@ -4130,6 +4321,7 @@ mail_esmtp_args(kp, vp, e, features)
/* NOTREACHED */
}
}
+
/*
** RCPT_ESMTP_ARGS -- process ESMTP arguments from RCPT line
**
@@ -4138,25 +4330,23 @@ mail_esmtp_args(kp, vp, e, features)
** kp -- the parameter key.
** vp -- the value of that parameter.
** e -- the envelope.
-** features -- current server features
**
** Returns:
** none.
*/
-static void
-rcpt_esmtp_args(a, kp, vp, e, features)
+void
+rcpt_esmtp_args(a, kp, vp, e)
ADDRESS *a;
char *kp;
char *vp;
ENVELOPE *e;
- unsigned int features;
{
if (sm_strcasecmp(kp, "notify") == 0)
{
char *p;
- if (!bitset(SRV_OFFER_DSN, features))
+ if (!bitset(SRV_OFFER_DSN, e->e_features))
{
usrerr("504 5.7.0 Sorry, NOTIFY not supported, we do not allow DSN");
/* NOTREACHED */
@@ -4197,7 +4387,7 @@ rcpt_esmtp_args(a, kp, vp, e, features)
}
else if (sm_strcasecmp(kp, "orcpt") == 0)
{
- if (!bitset(SRV_OFFER_DSN, features))
+ if (!bitset(SRV_OFFER_DSN, e->e_features))
{
usrerr("504 5.7.0 Sorry, ORCPT not supported, we do not allow DSN");
/* NOTREACHED */
@@ -4251,11 +4441,11 @@ printvrfyaddr(a, last, vrfy)
if (vrfy && a->q_mailer != NULL &&
!bitnset(M_VRFY250, a->q_mailer->m_flags))
- (void) sm_strlcpy(fmtbuf, "252", sizeof fmtbuf);
+ (void) sm_strlcpy(fmtbuf, "252", sizeof(fmtbuf));
else
- (void) sm_strlcpy(fmtbuf, "250", sizeof fmtbuf);
+ (void) sm_strlcpy(fmtbuf, "250", sizeof(fmtbuf));
fmtbuf[3] = last ? ' ' : '-';
- (void) sm_strlcpy(&fmtbuf[4], "2.1.5 ", sizeof fmtbuf - 4);
+ (void) sm_strlcpy(&fmtbuf[4], "2.1.5 ", sizeof(fmtbuf) - 4);
if (a->q_fullname == NULL)
{
if ((a->q_mailer == NULL ||
@@ -4263,10 +4453,10 @@ printvrfyaddr(a, last, vrfy)
sm_strcasecmp(a->q_mailer->m_addrtype, "rfc822") == 0) &&
strchr(a->q_user, '@') == NULL)
(void) sm_strlcpy(&fmtbuf[OFFF], "<%s@%s>",
- sizeof fmtbuf - OFFF);
+ sizeof(fmtbuf) - OFFF);
else
(void) sm_strlcpy(&fmtbuf[OFFF], "<%s>",
- sizeof fmtbuf - OFFF);
+ sizeof(fmtbuf) - OFFF);
message(fmtbuf, a->q_user, MyHostName);
}
else
@@ -4276,10 +4466,10 @@ printvrfyaddr(a, last, vrfy)
sm_strcasecmp(a->q_mailer->m_addrtype, "rfc822") == 0) &&
strchr(a->q_user, '@') == NULL)
(void) sm_strlcpy(&fmtbuf[OFFF], "%s <%s@%s>",
- sizeof fmtbuf - OFFF);
+ sizeof(fmtbuf) - OFFF);
else
(void) sm_strlcpy(&fmtbuf[OFFF], "%s <%s>",
- sizeof fmtbuf - OFFF);
+ sizeof(fmtbuf) - OFFF);
message(fmtbuf, a->q_fullname, a->q_user, MyHostName);
}
}
@@ -4600,7 +4790,7 @@ help(topic, e)
len = strlen(topic);
- while (sm_io_fgets(hf, SM_TIME_DEFAULT, buf, sizeof buf) != NULL)
+ while (sm_io_fgets(hf, SM_TIME_DEFAULT, buf, sizeof(buf)) != NULL)
{
if (buf[0] == '#')
{
@@ -4633,8 +4823,13 @@ help(topic, e)
fixcrlf(p, true);
if (foundvers >= 2)
{
- translate_dollars(p);
- expand(p, inp, sizeof inp, e);
+ char *lbp;
+ int lbs = sizeof(buf) - (p - buf);
+
+ lbp = translate_dollars(p, p, &lbs);
+ expand(lbp, inp, sizeof(inp), e);
+ if (p != lbp)
+ sm_free(lbp);
p = inp;
}
message("214-2.0.0 %s", p);
diff --git a/contrib/sendmail/src/stab.c b/contrib/sendmail/src/stab.c
index 2a7151496e6e..6dacdfa4ee55 100644
--- a/contrib/sendmail/src/stab.c
+++ b/contrib/sendmail/src/stab.c
@@ -13,7 +13,7 @@
#include
-SM_RCSID("@(#)$Id: stab.c,v 8.88 2003/05/21 15:36:30 ca Exp $")
+SM_RCSID("@(#)$Id: stab.c,v 8.89 2006/08/15 23:24:58 ca Exp $")
/*
** STAB -- manage the symbol table
@@ -110,72 +110,72 @@ stab(name, type, op)
switch (type)
{
case ST_CLASS:
- len = sizeof s->s_class;
+ len = sizeof(s->s_class);
break;
case ST_ADDRESS:
- len = sizeof s->s_address;
+ len = sizeof(s->s_address);
break;
case ST_MAILER:
- len = sizeof s->s_mailer;
+ len = sizeof(s->s_mailer);
break;
case ST_ALIAS:
- len = sizeof s->s_alias;
+ len = sizeof(s->s_alias);
break;
case ST_MAPCLASS:
- len = sizeof s->s_mapclass;
+ len = sizeof(s->s_mapclass);
break;
case ST_MAP:
- len = sizeof s->s_map;
+ len = sizeof(s->s_map);
break;
case ST_HOSTSIG:
- len = sizeof s->s_hostsig;
+ len = sizeof(s->s_hostsig);
break;
case ST_NAMECANON:
- len = sizeof s->s_namecanon;
+ len = sizeof(s->s_namecanon);
break;
case ST_MACRO:
- len = sizeof s->s_macro;
+ len = sizeof(s->s_macro);
break;
case ST_RULESET:
- len = sizeof s->s_ruleset;
+ len = sizeof(s->s_ruleset);
break;
case ST_HEADER:
- len = sizeof s->s_header;
+ len = sizeof(s->s_header);
break;
case ST_SERVICE:
- len = sizeof s->s_service;
+ len = sizeof(s->s_service);
break;
#if LDAPMAP
case ST_LMAP:
- len = sizeof s->s_lmap;
+ len = sizeof(s->s_lmap);
break;
#endif /* LDAPMAP */
#if MILTER
case ST_MILTER:
- len = sizeof s->s_milter;
+ len = sizeof(s->s_milter);
break;
#endif /* MILTER */
case ST_QUEUE:
- len = sizeof s->s_quegrp;
+ len = sizeof(s->s_quegrp);
break;
#if SOCKETMAP
case ST_SOCKETMAP:
- len = sizeof s->s_socketmap;
+ len = sizeof(s->s_socketmap);
break;
#endif /* SOCKETMAP */
@@ -189,15 +189,15 @@ stab(name, type, op)
*/
if (type >= ST_MCI)
- len = sizeof s->s_mci;
+ len = sizeof(s->s_mci);
else
{
syserr("stab: unknown symbol type %d", type);
- len = sizeof s->s_value;
+ len = sizeof(s->s_value);
}
break;
}
- len += sizeof *s - sizeof s->s_value;
+ len += sizeof(*s) - sizeof(s->s_value);
if (tTd(36, 15))
sm_dprintf("size of stab entry: %d\n", len);
diff --git a/contrib/sendmail/src/stats.c b/contrib/sendmail/src/stats.c
index 5725219298bc..16a9c6d2a162 100644
--- a/contrib/sendmail/src/stats.c
+++ b/contrib/sendmail/src/stats.c
@@ -13,7 +13,7 @@
#include
-SM_RCSID("@(#)$Id: stats.c,v 8.56 2002/06/27 22:47:37 gshapiro Exp $")
+SM_RCSID("@(#)$Id: stats.c,v 8.57 2006/08/15 23:24:58 ca Exp $")
#include
@@ -112,7 +112,7 @@ void
clearstats()
{
/* clear the structure to avoid future disappointment */
- memset(&Stat, '\0', sizeof Stat);
+ memset(&Stat, '\0', sizeof(Stat));
GotStats = false;
}
/*
@@ -143,7 +143,7 @@ poststats(sfile)
entered = true;
(void) time(&Stat.stat_itime);
- Stat.stat_size = sizeof Stat;
+ Stat.stat_size = sizeof(Stat);
Stat.stat_magic = STAT_MAGIC;
Stat.stat_version = STAT_VERSION;
@@ -162,8 +162,8 @@ poststats(sfile)
entered = false;
return;
}
- if (read(fd, (char *) &stats, sizeof stats) == sizeof stats &&
- stats.stat_size == sizeof stats &&
+ if (read(fd, (char *) &stats, sizeof(stats)) == sizeof(stats) &&
+ stats.stat_size == sizeof(stats) &&
stats.stat_magic == Stat.stat_magic &&
stats.stat_version == Stat.stat_version)
{
@@ -185,11 +185,11 @@ poststats(sfile)
stats.stat_cf += Stat.stat_cf;
}
else
- memmove((char *) &stats, (char *) &Stat, sizeof stats);
+ memmove((char *) &stats, (char *) &Stat, sizeof(stats));
/* write out results */
(void) lseek(fd, (off_t) 0, 0);
- (void) write(fd, (char *) &stats, sizeof stats);
+ (void) write(fd, (char *) &stats, sizeof(stats));
(void) close(fd);
/* clear the structure to avoid future disappointment */
diff --git a/contrib/sendmail/src/timers.c b/contrib/sendmail/src/timers.c
index fdace0150029..43dc07d05b44 100644
--- a/contrib/sendmail/src/timers.c
+++ b/contrib/sendmail/src/timers.c
@@ -11,7 +11,7 @@
*/
#include
-SM_RCSID("@(#)$Id: timers.c,v 8.25 2005/06/14 23:07:23 ca Exp $")
+SM_RCSID("@(#)$Id: timers.c,v 8.26 2006/08/15 23:24:58 ca Exp $")
#if _FFR_TIMERS
# include
@@ -40,7 +40,7 @@ warntimer(msg, va_alist)
return;
# endif /* 0 */
SM_VA_START(ap, msg);
- (void) sm_vsnprintf(buf, sizeof buf, msg, ap);
+ (void) sm_vsnprintf(buf, sizeof(buf), msg, ap);
SM_VA_END(ap);
sm_syslog(LOG_NOTICE, CurEnv->e_id, "%s; e_timers=0x%lx",
buf, (unsigned long) &CurEnv->e_timers);
@@ -50,7 +50,7 @@ static void
zerotimer(ptimer)
TIMER *ptimer;
{
- memset(ptimer, '\0', sizeof *ptimer);
+ memset(ptimer, '\0', sizeof(*ptimer));
}
static void
@@ -130,7 +130,7 @@ getinctimer(ptimer)
if (BaseTimer.ti_wall_sec == 0)
{
/* first call */
- memset(ptimer, '\0', sizeof *ptimer);
+ memset(ptimer, '\0', sizeof(*ptimer));
}
else
{
@@ -223,7 +223,7 @@ strtimer(ptimer)
{
static char buf[40];
- (void) sm_snprintf(buf, sizeof buf, "%ld.%06ldr/%ld.%06ldc",
+ (void) sm_snprintf(buf, sizeof(buf), "%ld.%06ldr/%ld.%06ldc",
ptimer->ti_wall_sec, ptimer->ti_wall_usec,
ptimer->ti_cpu_sec, ptimer->ti_cpu_usec);
return buf;
diff --git a/contrib/sendmail/src/tls.c b/contrib/sendmail/src/tls.c
index 71fcdc396b42..1a213cab68ee 100644
--- a/contrib/sendmail/src/tls.c
+++ b/contrib/sendmail/src/tls.c
@@ -10,7 +10,7 @@
#include
-SM_RCSID("@(#)$Id: tls.c,v 8.105 2006/05/11 22:59:31 ca Exp $")
+SM_RCSID("@(#)$Id: tls.c,v 8.107 2006/10/12 21:35:11 ca Exp $")
#if STARTTLS
# include
@@ -213,7 +213,7 @@ tls_rand_init(randfile, logl)
DontBlameSendmail))
{
/* add this even if fstat() failed */
- RAND_seed((void *) &st, sizeof st);
+ RAND_seed((void *) &st, sizeof(st));
}
(void) close(fd);
}
@@ -251,7 +251,7 @@ tls_rand_init(randfile, logl)
r = get_random();
(void) memcpy(buf + i, (void *) &r, sizeof(long));
}
- RAND_seed(buf, sizeof buf);
+ RAND_seed(buf, sizeof(buf));
if (LogLevel > logl)
sm_syslog(LOG_WARNING, NOQID,
"STARTTLS: Warning: random number generator not properly seeded");
@@ -747,8 +747,10 @@ inittls(ctx, req, srv, certfile, keyfile, cacertpath, cacertfile, dhparam)
sm_syslog(LOG_WARNING, NOQID,
"STARTTLS=%s, error: BIO_new=failed", who);
}
+ else
+ store = NULL;
# if _FFR_CRLPATH
- if (CRLPath != NULL)
+ if (CRLPath != NULL && store != NULL)
{
X509_LOOKUP *lookup;
@@ -1175,9 +1177,9 @@ tls_get_info(ssl, srv, host, mac, certreq)
macdefine(mac, A_TEMP, macid("{cipher}"),
(char *) SSL_CIPHER_get_name(c));
b = SSL_CIPHER_get_bits(c, &r);
- (void) sm_snprintf(bitstr, sizeof bitstr, "%d", b);
+ (void) sm_snprintf(bitstr, sizeof(bitstr), "%d", b);
macdefine(mac, A_TEMP, macid("{cipher_bits}"), bitstr);
- (void) sm_snprintf(bitstr, sizeof bitstr, "%d", r);
+ (void) sm_snprintf(bitstr, sizeof(bitstr), "%d", r);
macdefine(mac, A_TEMP, macid("{alg_bits}"), bitstr);
s = SSL_CIPHER_get_version(c);
if (s == NULL)
@@ -1198,19 +1200,19 @@ tls_get_info(ssl, srv, host, mac, certreq)
char buf[MAXNAME];
X509_NAME_oneline(X509_get_subject_name(cert),
- buf, sizeof buf);
+ buf, sizeof(buf));
macdefine(mac, A_TEMP, macid("{cert_subject}"),
xtextify(buf, "<>\")"));
X509_NAME_oneline(X509_get_issuer_name(cert),
- buf, sizeof buf);
+ buf, sizeof(buf));
macdefine(mac, A_TEMP, macid("{cert_issuer}"),
xtextify(buf, "<>\")"));
X509_NAME_get_text_by_NID(X509_get_subject_name(cert),
- NID_commonName, buf, sizeof buf);
+ NID_commonName, buf, sizeof(buf));
macdefine(mac, A_TEMP, macid("{cn_subject}"),
xtextify(buf, "<>\")"));
X509_NAME_get_text_by_NID(X509_get_issuer_name(cert),
- NID_commonName, buf, sizeof buf);
+ NID_commonName, buf, sizeof(buf));
macdefine(mac, A_TEMP, macid("{cn_issuer}"),
xtextify(buf, "<>\")"));
n = 0;
@@ -1564,7 +1566,7 @@ tls_verify_log(ok, ctx, name)
return 0;
}
- X509_NAME_oneline(X509_get_subject_name(cert), buf, sizeof buf);
+ X509_NAME_oneline(X509_get_subject_name(cert), buf, sizeof(buf));
sm_syslog(LOG_INFO, NOQID,
"STARTTLS: %s cert verify: depth=%d %s, state=%d, reason=%s",
name, depth, buf, ok, X509_verify_cert_error_string(reason));
diff --git a/contrib/sendmail/src/udb.c b/contrib/sendmail/src/udb.c
index 83312300f467..29470e7c6902 100644
--- a/contrib/sendmail/src/udb.c
+++ b/contrib/sendmail/src/udb.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998-2003 Sendmail, Inc. and its suppliers.
+ * Copyright (c) 1998-2003, 2006 Sendmail, Inc. and its suppliers.
* All rights reserved.
* Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved.
* Copyright (c) 1988, 1993
@@ -12,15 +12,17 @@
*/
#include
+#include "map.h"
#if USERDB
-SM_RCSID("@(#)$Id: udb.c,v 8.161 2005/08/31 21:34:20 ca Exp $ (with USERDB)")
+SM_RCSID("@(#)$Id: udb.c,v 8.164 2006/12/19 19:49:51 ca Exp $ (with USERDB)")
#else /* USERDB */
-SM_RCSID("@(#)$Id: udb.c,v 8.161 2005/08/31 21:34:20 ca Exp $ (without USERDB)")
+SM_RCSID("@(#)$Id: udb.c,v 8.164 2006/12/19 19:49:51 ca Exp $ (without USERDB)")
#endif /* USERDB */
#if USERDB
+#include
# if NEWDB
# include "sm/bdb.h"
# else /* NEWDB */
@@ -139,8 +141,8 @@ udbexpand(a, sendq, aliaslevel, e)
char *user;
char keybuf[MAXUDBKEY];
- memset(&key, '\0', sizeof key);
- memset(&info, '\0', sizeof info);
+ memset(&key, '\0', sizeof(key));
+ memset(&info, '\0', sizeof(info));
if (tTd(28, 1))
sm_dprintf("udbexpand(%s)\n", a->q_paddr);
@@ -173,10 +175,10 @@ udbexpand(a, sendq, aliaslevel, e)
if (user[0] == ':')
return EX_OK;
- keylen = sm_strlcpyn(keybuf, sizeof keybuf, 2, user, ":maildrop");
+ keylen = sm_strlcpyn(keybuf, sizeof(keybuf), 2, user, ":maildrop");
/* if name is too long, assume it won't match */
- if (keylen >= sizeof keybuf)
+ if (keylen >= sizeof(keybuf))
return EX_OK;
/* build actual database key */
@@ -196,8 +198,8 @@ udbexpand(a, sendq, aliaslevel, e)
user = userbuf;
userbuf[0] = '\0';
- usersize = sizeof userbuf;
- userleft = sizeof userbuf - 1;
+ usersize = sizeof(userbuf);
+ userleft = sizeof(userbuf) - 1;
/*
** Select action based on entry type.
@@ -350,9 +352,9 @@ udbexpand(a, sendq, aliaslevel, e)
** it into the envelope.
*/
- memset(&key, '\0', sizeof key);
- memset(&info, '\0', sizeof info);
- (void) sm_strlcpyn(keybuf, sizeof keybuf, 2, a->q_user,
+ memset(&key, '\0', sizeof(key));
+ memset(&info, '\0', sizeof(info));
+ (void) sm_strlcpyn(keybuf, sizeof(keybuf), 2, a->q_user,
":mailsender");
keylen = strlen(keybuf);
key.data = keybuf;
@@ -426,7 +428,7 @@ udbexpand(a, sendq, aliaslevel, e)
break;
}
if (strlen(hp->po_name) + strlen(hp->po_host) >
- sizeof pobuf - 2)
+ sizeof(pobuf) - 2)
{
if (tTd(28, 2))
sm_dprintf("hes_getmailhost(%s): expansion too long: %.30s@%.30s\n",
@@ -436,7 +438,7 @@ udbexpand(a, sendq, aliaslevel, e)
break;
}
info.data = pobuf;
- (void) sm_snprintf(pobuf, sizeof pobuf,
+ (void) sm_snprintf(pobuf, sizeof(pobuf),
"%s@%s", hp->po_name, hp->po_host);
info.size = strlen(info.data);
# else /* HES_GETMAILHOST */
@@ -484,7 +486,7 @@ udbexpand(a, sendq, aliaslevel, e)
** it into the envelope.
*/
- (void) sm_strlcpyn(keybuf, sizeof keybuf, 2, a->q_user,
+ (void) sm_strlcpyn(keybuf, sizeof(keybuf), 2, a->q_user,
":mailsender");
keylen = strlen(keybuf);
key.data = keybuf;
@@ -618,9 +620,9 @@ udbmatch(user, field, rpool)
/* long names can never match and are a pain to deal with */
i = strlen(field);
- if (i < sizeof "maildrop")
- i = sizeof "maildrop";
- if ((strlen(user) + i) > sizeof keybuf - 4)
+ if (i < sizeof("maildrop"))
+ i = sizeof("maildrop");
+ if ((strlen(user) + i) > sizeof(keybuf) - 4)
return NULL;
/* names beginning with colons indicate metadata */
@@ -628,7 +630,7 @@ udbmatch(user, field, rpool)
return NULL;
/* build database key */
- (void) sm_strlcpyn(keybuf, sizeof keybuf, 3, user, ":", field);
+ (void) sm_strlcpyn(keybuf, sizeof(keybuf), 3, user, ":", field);
keylen = strlen(keybuf);
for (up = UdbEnts; up->udb_type != UDB_EOLIST; up++)
@@ -641,8 +643,8 @@ udbmatch(user, field, rpool)
{
# if NEWDB
case UDB_DBFETCH:
- memset(&key, '\0', sizeof key);
- memset(&info, '\0', sizeof info);
+ memset(&key, '\0', sizeof(key));
+ memset(&info, '\0', sizeof(info));
key.data = keybuf;
key.size = keylen;
# if DB_VERSION_MAJOR < 2
@@ -700,7 +702,7 @@ udbmatch(user, field, rpool)
*/
/* build database key */
- (void) sm_strlcpyn(keybuf, sizeof keybuf, 2, user, ":maildrop");
+ (void) sm_strlcpyn(keybuf, sizeof(keybuf), 2, user, ":maildrop");
keylen = strlen(keybuf);
for (up = UdbEnts; up->udb_type != UDB_EOLIST; up++)
@@ -712,8 +714,8 @@ udbmatch(user, field, rpool)
/* get the default case for this database */
if (up->udb_default == NULL)
{
- memset(&key, '\0', sizeof key);
- memset(&info, '\0', sizeof info);
+ memset(&key, '\0', sizeof(key));
+ memset(&info, '\0', sizeof(info));
key.data = ":default:mailname";
key.size = strlen(key.data);
# if DB_VERSION_MAJOR < 2
@@ -740,8 +742,8 @@ udbmatch(user, field, rpool)
continue;
/* we have a default case -- verify user:maildrop */
- memset(&key, '\0', sizeof key);
- memset(&info, '\0', sizeof info);
+ memset(&key, '\0', sizeof(key));
+ memset(&info, '\0', sizeof(info));
key.data = keybuf;
key.size = keylen;
# if DB_VERSION_MAJOR < 2
@@ -852,8 +854,8 @@ udb_map_lookup(map, name, av, statp)
{
int keysize = strlen(name);
- if (keysize > sizeof keybuf - 1)
- keysize = sizeof keybuf - 1;
+ if (keysize > sizeof(keybuf) - 1)
+ keysize = sizeof(keybuf) - 1;
memmove(keybuf, name, keysize);
keybuf[keysize] = '\0';
makelower(keybuf);
@@ -1234,7 +1236,7 @@ hes_udb_get(key, info)
char **hp;
char kbuf[MAXUDBKEY + 1];
- if (sm_strlcpy(kbuf, key->data, sizeof kbuf) >= sizeof kbuf)
+ if (sm_strlcpy(kbuf, key->data, sizeof(kbuf)) >= sizeof(kbuf))
return 0;
name = kbuf;
type = strrchr(name, ':');
diff --git a/contrib/sendmail/src/usersmtp.c b/contrib/sendmail/src/usersmtp.c
index 0c5195eb9fef..622bbb83199a 100644
--- a/contrib/sendmail/src/usersmtp.c
+++ b/contrib/sendmail/src/usersmtp.c
@@ -13,7 +13,7 @@
#include
-SM_RCSID("@(#)$Id: usersmtp.c,v 8.467 2006/03/19 06:07:56 ca Exp $")
+SM_RCSID("@(#)$Id: usersmtp.c,v 8.469 2006/12/13 20:11:15 ca Exp $")
#include
@@ -541,6 +541,10 @@ static sasl_callback_t callbacks[] =
**
** Side Effects:
** checks/sets sasl_clt_init.
+**
+** Note:
+** Callbacks are ignored if sasl_client_init() has
+** been called before (by a library such as libnss_ldap)
*/
static bool sasl_clt_init = false;
@@ -789,7 +793,7 @@ readauth(filename, safe, sai, rpool)
lc = 0;
while (lc <= SASL_MECHLIST &&
- sm_io_fgets(f, SM_TIME_DEFAULT, buf, sizeof buf) != NULL)
+ sm_io_fgets(f, SM_TIME_DEFAULT, buf, sizeof(buf)) != NULL)
{
if (buf[0] != '#')
{
@@ -1578,9 +1582,15 @@ attemptauth(m, mci, e, sai)
/* make a new client sasl connection */
# if SASL >= 20000
+ /*
+ ** We provide the callbacks again because global callbacks in
+ ** sasl_client_init() are ignored if SASL has been initialized
+ ** before, for example, by a library such as libnss-ldap.
+ */
+
saslresult = sasl_client_new(bitnset(M_LMTP, m->m_flags) ? "lmtp"
: "smtp",
- CurHostName, NULL, NULL, NULL, 0,
+ CurHostName, NULL, NULL, callbacks, 0,
&mci->mci_conn);
# else /* SASL >= 20000 */
saslresult = sasl_client_new(bitnset(M_LMTP, m->m_flags) ? "lmtp"
@@ -1591,7 +1601,7 @@ attemptauth(m, mci, e, sai)
return EX_TEMPFAIL;
/* set properties */
- (void) memset(&ssp, '\0', sizeof ssp);
+ (void) memset(&ssp, '\0', sizeof(ssp));
/* XXX should these be options settable via .cf ? */
{
@@ -1650,7 +1660,7 @@ attemptauth(m, mci, e, sai)
break;
}
if (iptostring(&CurHostAddr, addrsize,
- remoteip, sizeof remoteip))
+ remoteip, sizeof(remoteip)))
{
if (sasl_setprop(mci->mci_conn, SASL_IPREMOTEPORT,
remoteip) != SASL_OK)
@@ -1662,7 +1672,7 @@ attemptauth(m, mci, e, sai)
(struct sockaddr *) &saddr_l, &addrsize) == 0)
{
if (iptostring(&saddr_l, addrsize,
- localip, sizeof localip))
+ localip, sizeof(localip)))
{
if (sasl_setprop(mci->mci_conn,
SASL_IPLOCALPORT,
@@ -2011,7 +2021,7 @@ smtpmailfrom(m, mci, e)
/* set up appropriate options to include */
if (bitset(MCIF_SIZE, mci->mci_flags) && e->e_msgsize > 0)
{
- (void) sm_snprintf(optbuf, sizeof optbuf, " SIZE=%ld",
+ (void) sm_snprintf(optbuf, sizeof(optbuf), " SIZE=%ld",
e->e_msgsize);
bufp = &optbuf[strlen(optbuf)];
}
@@ -2138,7 +2148,7 @@ smtpmailfrom(m, mci, e)
!bitnset(M_NO_NULL_FROM, m->m_flags))
buf[0] = '\0';
else
- expand("\201g", buf, sizeof buf, e);
+ expand("\201g", buf, sizeof(buf), e);
if (buf[0] == '<')
{
/* strip off (put back on below) */
@@ -2296,7 +2306,7 @@ smtprcpt(to, m, mci, e, ctladdr, xstart)
/*
** Warning: in the following it is assumed that the free space
- ** in bufp is sizeof optbuf
+ ** in bufp is sizeof(optbuf)
*/
if (bitset(MCIF_DSN, mci->mci_flags))
@@ -2320,30 +2330,30 @@ smtprcpt(to, m, mci, e, ctladdr, xstart)
{
bool firstone = true;
- (void) sm_strlcat(bufp, " NOTIFY=", sizeof optbuf);
+ (void) sm_strlcat(bufp, " NOTIFY=", sizeof(optbuf));
if (bitset(QPINGONSUCCESS, to->q_flags))
{
- (void) sm_strlcat(bufp, "SUCCESS", sizeof optbuf);
+ (void) sm_strlcat(bufp, "SUCCESS", sizeof(optbuf));
firstone = false;
}
if (bitset(QPINGONFAILURE, to->q_flags))
{
if (!firstone)
(void) sm_strlcat(bufp, ",",
- sizeof optbuf);
- (void) sm_strlcat(bufp, "FAILURE", sizeof optbuf);
+ sizeof(optbuf));
+ (void) sm_strlcat(bufp, "FAILURE", sizeof(optbuf));
firstone = false;
}
if (bitset(QPINGONDELAY, to->q_flags))
{
if (!firstone)
(void) sm_strlcat(bufp, ",",
- sizeof optbuf);
- (void) sm_strlcat(bufp, "DELAY", sizeof optbuf);
+ sizeof(optbuf));
+ (void) sm_strlcat(bufp, "DELAY", sizeof(optbuf));
firstone = false;
}
if (firstone)
- (void) sm_strlcat(bufp, "NEVER", sizeof optbuf);
+ (void) sm_strlcat(bufp, "NEVER", sizeof(optbuf));
bufp += strlen(bufp);
}
@@ -3122,7 +3132,7 @@ reply(m, mci, e, timeout, pfunc, enhstat, rtype)
if (errno == 0)
{
(void) sm_snprintf(SmtpReplyBuffer,
- sizeof SmtpReplyBuffer,
+ sizeof(SmtpReplyBuffer),
"421 4.4.1 Connection reset by %s",
CURHOSTNAME);
#ifdef ECONNRESET
@@ -3242,7 +3252,7 @@ reply(m, mci, e, timeout, pfunc, enhstat, rtype)
/* save temporary failure messages for posterity */
if (SmtpReplyBuffer[0] == '4')
- (void) sm_strlcpy(SmtpError, SmtpReplyBuffer, sizeof SmtpError);
+ (void) sm_strlcpy(SmtpError, SmtpReplyBuffer, sizeof(SmtpError));
/* reply code 421 is "Service Shutting Down" */
if (r == SMTPCLOSING && mci->mci_state != MCIS_SSD &&
@@ -3285,7 +3295,7 @@ smtpmessage(f, m, mci, va_alist)
SM_VA_LOCAL_DECL
SM_VA_START(ap, mci);
- (void) sm_vsnprintf(SmtpMsgBuffer, sizeof SmtpMsgBuffer, f, ap);
+ (void) sm_vsnprintf(SmtpMsgBuffer, sizeof(SmtpMsgBuffer), f, ap);
SM_VA_END(ap);
if (tTd(18, 1) || Verbose)
diff --git a/contrib/sendmail/src/util.c b/contrib/sendmail/src/util.c
index c27cd906f2a6..af781ef3d9c0 100644
--- a/contrib/sendmail/src/util.c
+++ b/contrib/sendmail/src/util.c
@@ -13,8 +13,9 @@
#include
-SM_RCSID("@(#)$Id: util.c,v 8.394 2006/05/03 23:55:29 ca Exp $")
+SM_RCSID("@(#)$Id: util.c,v 8.410 2006/12/18 18:36:44 ca Exp $")
+#include
#include
#include
@@ -180,6 +181,7 @@ rfc822_string(s)
/* unbalanced '"' or '(' */
return !quoted && commentlev == 0;
}
+
/*
** SHORTEN_RFC822_STRING -- Truncate and rebalance an RFC822 string
**
@@ -288,6 +290,7 @@ shorten_rfc822_string(string, length)
}
return modified;
}
+
/*
** FIND_CHARACTER -- find an unquoted character in an RFC822 string
**
@@ -383,7 +386,6 @@ check_bodytype(bodytype)
return BODYTYPE_ILLEGAL;
}
-#if _FFR_BESTMX_BETTER_TRUNCATION || _FFR_DNSMAP_MULTI
/*
** TRUNCATE_AT_DELIM -- truncate string at a delimiter and append "..."
**
@@ -426,7 +428,7 @@ truncate_at_delim(str, len, delim)
else
str[0] = '\0';
}
-#endif /* _FFR_BESTMX_BETTER_TRUNCATION || _FFR_DNSMAP_MULTI */
+
/*
** XALLOC -- Allocate memory, raise an exception on error
**
@@ -472,6 +474,7 @@ xalloc(sz)
}
return p;
}
+
/*
** COPYPLIST -- copy list of pointers.
**
@@ -504,8 +507,8 @@ copyplist(list, copycont, rpool)
vp++;
- newvp = (char **) sm_rpool_malloc_x(rpool, (vp - list) * sizeof *vp);
- memmove((char *) newvp, (char *) list, (int) (vp - list) * sizeof *vp);
+ newvp = (char **) sm_rpool_malloc_x(rpool, (vp - list) * sizeof(*vp));
+ memmove((char *) newvp, (char *) list, (int) (vp - list) * sizeof(*vp));
if (copycont)
{
@@ -515,6 +518,7 @@ copyplist(list, copycont, rpool)
return newvp;
}
+
/*
** COPYQUEUE -- copy address queue.
**
@@ -543,7 +547,7 @@ copyqueue(addr, rpool)
if (!QS_IS_DEAD(addr->q_state))
{
newaddr = (ADDRESS *) sm_rpool_malloc_x(rpool,
- sizeof *newaddr);
+ sizeof(*newaddr));
STRUCTCOPY(*addr, *newaddr);
*tail = newaddr;
tail = &newaddr->q_next;
@@ -554,6 +558,7 @@ copyqueue(addr, rpool)
return ret;
}
+
/*
** LOG_SENDMAIL_PID -- record sendmail pid and command line.
**
@@ -582,7 +587,7 @@ log_sendmail_pid(e)
sff = SFF_NOLINK|SFF_ROOTOK|SFF_REGONLY|SFF_CREAT|SFF_NBLOCK;
if (TrustedUid != 0 && RealUid == TrustedUid)
sff |= SFF_OPENASROOT;
- expand(PidFile, pidpath, sizeof pidpath, e);
+ expand(PidFile, pidpath, sizeof(pidpath), e);
Pidf = safefopen(pidpath, O_WRONLY|O_TRUNC, FileMode, sff);
if (Pidf == NULL)
{
@@ -666,6 +671,7 @@ set_delivery_mode(mode, e)
buf[1] = '\0';
macdefine(&e->e_macro, A_TEMP, macid("{deliveryMode}"), buf);
}
+
/*
** SET_OP_MODE -- set and record the op mode
**
@@ -692,6 +698,7 @@ set_op_mode(mode)
buf[1] = '\0';
macdefine(&BlankEnvelope.e_macro, A_TEMP, MID_OPMODE, buf);
}
+
/*
** PRINTAV -- print argument vector.
**
@@ -709,7 +716,7 @@ set_op_mode(mode)
void
printav(fp, av)
SM_FILE_T *fp;
- register char **av;
+ char **av;
{
while (*av != NULL)
{
@@ -717,10 +724,14 @@ printav(fp, av)
sm_dprintf("\n\t%08lx=", (unsigned long) *av);
else
(void) sm_io_putc(fp, SM_TIME_DEFAULT, ' ');
- xputs(fp, *av++);
+ if (tTd(0, 99))
+ sm_dprintf("%s", str2prt(*av++));
+ else
+ xputs(fp, *av++);
}
(void) sm_io_putc(fp, SM_TIME_DEFAULT, '\n');
}
+
/*
** XPUTS -- put string doing control escapes.
**
@@ -738,10 +749,10 @@ printav(fp, av)
void
xputs(fp, s)
SM_FILE_T *fp;
- register const char *s;
+ const char *s;
{
- register int c;
- register struct metamac *mp;
+ int c;
+ struct metamac *mp;
bool shiftout = false;
extern struct metamac MetaMacros[];
static SM_DEBUG_T DebugANSI = SM_DEBUG_INITIALIZER("ANSI",
@@ -758,19 +769,19 @@ xputs(fp, s)
if (sm_debug_active(&DebugANSI, 1))
{
TermEscape.te_rv_on = "\033[7m";
- TermEscape.te_rv_off = "\033[0m";
+ TermEscape.te_normal = "\033[0m";
}
else
{
TermEscape.te_rv_on = "";
- TermEscape.te_rv_off = "";
+ TermEscape.te_normal = "";
}
}
if (s == NULL)
{
(void) sm_io_fprintf(fp, SM_TIME_DEFAULT, "%s%s",
- TermEscape.te_rv_on, TermEscape.te_rv_off);
+ TermEscape.te_rv_on, TermEscape.te_normal);
return;
}
while ((c = (*s++ & 0377)) != '\0')
@@ -778,10 +789,10 @@ xputs(fp, s)
if (shiftout)
{
(void) sm_io_fprintf(fp, SM_TIME_DEFAULT, "%s",
- TermEscape.te_rv_off);
+ TermEscape.te_normal);
shiftout = false;
}
- if (!isascii(c))
+ if (!isascii(c) && !tTd(84, 1))
{
if (c == MATCHREPL)
{
@@ -889,7 +900,11 @@ xputs(fp, s)
(void) sm_io_putc(fp, SM_TIME_DEFAULT, '\\');
(void) sm_io_putc(fp, SM_TIME_DEFAULT, c);
}
- else
+ else if (tTd(84, 2))
+ (void) sm_io_fprintf(fp, SM_TIME_DEFAULT, " %o ", c);
+ else if (tTd(84, 1))
+ (void) sm_io_fprintf(fp, SM_TIME_DEFAULT, " %#x ", c);
+ else if (!isascii(c) && !tTd(84, 1))
{
(void) sm_io_putc(fp, SM_TIME_DEFAULT, '^');
(void) sm_io_putc(fp, SM_TIME_DEFAULT, c ^ 0100);
@@ -897,9 +912,10 @@ xputs(fp, s)
}
if (shiftout)
(void) sm_io_fprintf(fp, SM_TIME_DEFAULT, "%s",
- TermEscape.te_rv_off);
+ TermEscape.te_normal);
(void) sm_io_flush(fp, SM_TIME_DEFAULT);
}
+
/*
** MAKELOWER -- Translate a line into lower case
**
@@ -926,6 +942,7 @@ makelower(p)
if (isascii(c) && isupper(c))
*p = tolower(c);
}
+
/*
** FIXCRLF -- fix in line.
**
@@ -961,6 +978,7 @@ fixcrlf(line, stripnl)
*p++ = '\n';
*p = '\0';
}
+
/*
** PUTLINE -- put a line like fputs obeying SMTP conventions
**
@@ -985,6 +1003,7 @@ putline(l, mci)
{
return putxline(l, strlen(l), mci, PXLF_MAPFROM);
}
+
/*
** PUTXLINE -- putline with flags bits.
**
@@ -1000,6 +1019,7 @@ putline(l, mci)
** PXLF_STRIP8BIT -- strip 8th bit.
** PXLF_HEADER -- map bare newline in header to newline space.
** PXLF_NOADDEOL -- don't add an EOL if one wasn't present.
+** PXLF_STRIPMQUOTE -- strip METAQUOTE bytes.
**
** Returns:
** true iff line was written successfully
@@ -1008,6 +1028,37 @@ putline(l, mci)
** output of l to mci->mci_out.
*/
+
+#define PUTX(limit) \
+ do \
+ { \
+ quotenext = false; \
+ while (l < limit) \
+ { \
+ unsigned char c = (unsigned char) *l++; \
+ \
+ if (bitset(PXLF_STRIPMQUOTE, pxflags) && \
+ !quotenext && c == METAQUOTE) \
+ { \
+ quotenext = true; \
+ continue; \
+ } \
+ quotenext = false; \
+ if (strip8bit) \
+ c &= 0177; \
+ if (sm_io_putc(mci->mci_out, SM_TIME_DEFAULT, \
+ c) == SM_IO_EOF) \
+ { \
+ dead = true; \
+ break; \
+ } \
+ if (TrafficLogFile != NULL) \
+ (void) sm_io_putc(TrafficLogFile, \
+ SM_TIME_DEFAULT, \
+ c); \
+ } \
+ } while (0)
+
bool
putxline(l, len, mci, pxflags)
register char *l;
@@ -1015,20 +1066,15 @@ putxline(l, len, mci, pxflags)
register MCI *mci;
int pxflags;
{
- bool dead = false;
register char *p, *end;
- int slop = 0;
+ int slop;
+ bool dead, quotenext, strip8bit;
/* strip out 0200 bits -- these can look like TELNET protocol */
- if (bitset(MCIF_7BIT, mci->mci_flags) ||
- bitset(PXLF_STRIP8BIT, pxflags))
- {
- register char svchar;
-
- for (p = l; (svchar = *p) != '\0'; ++p)
- if (bitset(0200, svchar))
- *p = svchar &~ 0200;
- }
+ strip8bit = bitset(MCIF_7BIT, mci->mci_flags) ||
+ bitset(PXLF_STRIP8BIT, pxflags);
+ dead = false;
+ slop = 0;
end = l + len;
do
@@ -1051,7 +1097,6 @@ putxline(l, len, mci, pxflags)
while (mci->mci_mailer->m_linelimit > 0 &&
(p - l + slop) > mci->mci_mailer->m_linelimit)
{
- char *l_base = l;
register char *q = &l[mci->mci_mailer->m_linelimit - slop - 1];
if (l[0] == '.' && slop == 0 &&
@@ -1080,35 +1125,22 @@ putxline(l, len, mci, pxflags)
if (dead)
break;
- while (l < q)
- {
- if (sm_io_putc(mci->mci_out, SM_TIME_DEFAULT,
- (unsigned char) *l++) == SM_IO_EOF)
- {
- dead = true;
- break;
- }
- }
+ PUTX(q);
if (dead)
break;
- if (sm_io_putc(mci->mci_out, SM_TIME_DEFAULT, '!') ==
- SM_IO_EOF ||
+ if (sm_io_putc(mci->mci_out, SM_TIME_DEFAULT,
+ '!') == SM_IO_EOF ||
sm_io_fputs(mci->mci_out, SM_TIME_DEFAULT,
- mci->mci_mailer->m_eol) ==
- SM_IO_EOF ||
- sm_io_putc(mci->mci_out, SM_TIME_DEFAULT, ' ') ==
- SM_IO_EOF)
+ mci->mci_mailer->m_eol) == SM_IO_EOF ||
+ sm_io_putc(mci->mci_out, SM_TIME_DEFAULT,
+ ' ') == SM_IO_EOF)
{
dead = true;
break;
}
if (TrafficLogFile != NULL)
{
- for (l = l_base; l < q; l++)
- (void) sm_io_putc(TrafficLogFile,
- SM_TIME_DEFAULT,
- (unsigned char)*l);
(void) sm_io_fprintf(TrafficLogFile,
SM_TIME_DEFAULT,
"!\n%05d >>> ",
@@ -1149,19 +1181,7 @@ putxline(l, len, mci, pxflags)
(void) sm_io_putc(TrafficLogFile,
SM_TIME_DEFAULT, '>');
}
- for ( ; l < p; ++l)
- {
- if (TrafficLogFile != NULL)
- (void) sm_io_putc(TrafficLogFile,
- SM_TIME_DEFAULT,
- (unsigned char)*l);
- if (sm_io_putc(mci->mci_out, SM_TIME_DEFAULT,
- (unsigned char) *l) == SM_IO_EOF)
- {
- dead = true;
- break;
- }
- }
+ PUTX(p);
if (dead)
break;
@@ -1230,6 +1250,7 @@ xunlink(f)
errno = save_errno;
return i;
}
+
/*
** SFGETS -- "safe" fgets -- times out and ignores random interrupts.
**
@@ -1338,12 +1359,15 @@ sfgets(buf, siz, fp, timeout, during)
}
return buf;
}
+
/*
** FGETFOLDED -- like fgets, but knows about folded lines.
**
** Parameters:
** buf -- place to put result.
-** n -- bytes available.
+** np -- pointer to bytes available; will be updated with
+** the actual buffer size (not number of bytes filled)
+** on return.
** f -- file to read from.
**
** Returns:
@@ -1358,15 +1382,18 @@ sfgets(buf, siz, fp, timeout, during)
*/
char *
-fgetfolded(buf, n, f)
+fgetfolded(buf, np, f)
char *buf;
- register int n;
+ int *np;
SM_FILE_T *f;
{
register char *p = buf;
char *bp = buf;
register int i;
+ int n;
+ SM_REQUIRE(np != NULL);
+ n = *np;
SM_REQUIRE(n > 0);
SM_REQUIRE(buf != NULL);
if (f == NULL)
@@ -1408,6 +1435,7 @@ fgetfolded(buf, n, f)
sm_free(bp);
bp = nbp;
n = nn - (p - bp);
+ *np = nn;
}
*p++ = i;
if (i == '\n')
@@ -1427,6 +1455,7 @@ fgetfolded(buf, n, f)
*p = '\0';
return bp;
}
+
/*
** CURTIME -- return current time.
**
@@ -1445,6 +1474,7 @@ curtime()
(void) time(&t);
return t;
}
+
/*
** ATOBOOL -- convert a string representation to boolean.
**
@@ -1466,6 +1496,7 @@ atobool(s)
return true;
return false;
}
+
/*
** ATOOCT -- convert a string representation to octal.
**
@@ -1487,6 +1518,7 @@ atooct(s)
i = (i << 3) | (*s++ - '0');
return i;
}
+
/*
** BITINTERSECT -- tell if two bitmaps intersect
**
@@ -1505,13 +1537,14 @@ bitintersect(a, b)
{
int i;
- for (i = BITMAPBYTES / sizeof (int); --i >= 0; )
+ for (i = BITMAPBYTES / sizeof(int); --i >= 0; )
{
if ((a[i] & b[i]) != 0)
return true;
}
return false;
}
+
/*
** BITZEROP -- tell if a bitmap is all zero
**
@@ -1529,13 +1562,14 @@ bitzerop(map)
{
int i;
- for (i = BITMAPBYTES / sizeof (int); --i >= 0; )
+ for (i = BITMAPBYTES / sizeof(int); --i >= 0; )
{
if (map[i] != 0)
return false;
}
return true;
}
+
/*
** STRCONTAINEDIN -- tell if one string is contained in another
**
@@ -1584,6 +1618,7 @@ strcontainedin(icase, a, b)
}
return false;
}
+
/*
** CHECKFD012 -- check low numbered file descriptors
**
@@ -1608,6 +1643,7 @@ checkfd012(where)
fill_fd(i, where);
#endif /* XDEBUG */
}
+
/*
** CHECKFDOPEN -- make sure file descriptor is open -- for extended debugging
**
@@ -1634,6 +1670,7 @@ checkfdopen(fd, where)
}
#endif /* XDEBUG */
}
+
/*
** CHECKFDS -- check for new or missing file descriptors
**
@@ -1694,6 +1731,7 @@ checkfds(where)
}
errno = save_errno;
}
+
/*
** PRINTOPENFDS -- print the open file descriptors (for debugging)
**
@@ -1719,6 +1757,7 @@ printopenfds(logit)
for (fd = 0; fd < DtableSize; fd++)
dumpfd(fd, false, logit);
}
+
/*
** DUMPFD -- dump a file descriptor
**
@@ -1795,8 +1834,8 @@ dumpfd(fd, printclosed, logit)
case S_IFSOCK:
(void) sm_snprintf(p, SPACELEFT(buf, p), "SOCK ");
p += strlen(p);
- memset(&sa, '\0', sizeof sa);
- slen = sizeof sa;
+ memset(&sa, '\0', sizeof(sa));
+ slen = sizeof(sa);
if (getsockname(fd, &sa.sa, &slen) < 0)
(void) sm_snprintf(p, SPACELEFT(buf, p), "(%s)",
sm_errstring(errno));
@@ -1825,7 +1864,7 @@ dumpfd(fd, printclosed, logit)
p += strlen(p);
(void) sm_snprintf(p, SPACELEFT(buf, p), "->");
p += strlen(p);
- slen = sizeof sa;
+ slen = sizeof(sa);
if (getpeername(fd, &sa.sa, &slen) < 0)
(void) sm_snprintf(p, SPACELEFT(buf, p), "(%s)",
sm_errstring(errno));
@@ -1908,6 +1947,7 @@ dumpfd(fd, printclosed, logit)
else
sm_dprintf("%s\n", buf);
}
+
/*
** SHORTEN_HOSTNAME -- strip local domain information off of hostname.
**
@@ -1955,6 +1995,7 @@ shorten_hostname(host)
}
return NULL;
}
+
/*
** PROG_OPEN -- open a program for reading
**
@@ -2057,7 +2098,7 @@ prog_open(argv, pfd, e)
/* chroot to the program mailer directory, if defined */
if (ProgMailer != NULL && ProgMailer->m_rootdir != NULL)
{
- expand(ProgMailer->m_rootdir, buf, sizeof buf, e);
+ expand(ProgMailer->m_rootdir, buf, sizeof(buf), e);
if (chroot(buf) < 0)
{
syserr("prog_open: cannot chroot(%s)", buf);
@@ -2097,7 +2138,7 @@ prog_open(argv, pfd, e)
q = strchr(p, ':');
if (q != NULL)
*q = '\0';
- expand(p, buf, sizeof buf, e);
+ expand(p, buf, sizeof(buf), e);
if (q != NULL)
*q++ = ':';
if (buf[0] != '\0' && chdir(buf) >= 0)
@@ -2138,6 +2179,7 @@ prog_open(argv, pfd, e)
_exit(EX_CONFIG);
return -1; /* avoid compiler warning on IRIX */
}
+
/*
** GET_COLUMN -- look up a Column in a line buffer
**
@@ -2168,7 +2210,7 @@ get_column(line, col, delim, buf, buflen)
char delimbuf[4];
if ((char) delim == '\0')
- (void) sm_strlcpy(delimbuf, "\n\t ", sizeof delimbuf);
+ (void) sm_strlcpy(delimbuf, "\n\t ", sizeof(delimbuf));
else
{
delimbuf[0] = (char) delim;
@@ -2211,6 +2253,7 @@ get_column(line, col, delim, buf, buflen)
(void) sm_strlcpy(buf, begin, i + 1);
return buf;
}
+
/*
** CLEANSTRCPY -- copy string keeping out bogus characters
**
@@ -2248,6 +2291,7 @@ cleanstrcpy(t, f, l)
}
*t = '\0';
}
+
/*
** DENLSTRING -- convert newlines in a string to spaces
**
@@ -2296,7 +2340,7 @@ denlstring(s, strict, logattacks)
if (logattacks)
{
- sm_syslog(LOG_NOTICE, CurEnv->e_id,
+ sm_syslog(LOG_NOTICE, CurEnv ? CurEnv->e_id : NULL,
"POSSIBLE ATTACK from %.100s: newline in string \"%s\"",
RealHostName == NULL ? "[UNKNOWN]" : RealHostName,
shortenstring(bp, MAXSHORTSTR));
@@ -2338,101 +2382,6 @@ strreplnonprt(s, c)
return ok;
}
-/*
-** STR2PRT -- convert "unprintable" characters in a string to \oct
-**
-** Parameters:
-** s -- string to convert
-**
-** Returns:
-** converted string.
-** This is a static local buffer, string must be copied
-** before this function is called again!
-*/
-
-char *
-str2prt(s)
- char *s;
-{
- int l;
- char c, *h;
- bool ok;
- static int len = 0;
- static char *buf = NULL;
-
- if (s == NULL)
- return NULL;
- ok = true;
- for (h = s, l = 1; *h != '\0'; h++, l++)
- {
- if (*h == '\\')
- {
- ++l;
- ok = false;
- }
- else if (!(isascii(*h) && isprint(*h)))
- {
- l += 3;
- ok = false;
- }
- }
- if (ok)
- return s;
- if (l > len)
- {
- char *nbuf = sm_pmalloc_x(l);
-
- if (buf != NULL)
- sm_free(buf);
- len = l;
- buf = nbuf;
- }
- for (h = buf; *s != '\0' && l > 0; s++, l--)
- {
- c = *s;
- if (isascii(c) && isprint(c) && c != '\\')
- {
- *h++ = c;
- }
- else
- {
- *h++ = '\\';
- --l;
- switch (c)
- {
- case '\\':
- *h++ = '\\';
- break;
- case '\t':
- *h++ = 't';
- break;
- case '\n':
- *h++ = 'n';
- break;
- case '\r':
- *h++ = 'r';
- break;
- default:
- SM_ASSERT(l >= 2);
- (void) sm_snprintf(h, l, "%03o",
- (unsigned int)((unsigned char) c));
-
- /*
- ** XXX since l is unsigned this may
- ** wrap around if the calculation is screwed
- ** up...
- */
-
- l -= 2;
- h += 3;
- break;
- }
- }
- }
- *h = '\0';
- buf[len - 1] = '\0';
- return buf;
-}
/*
** PATH_IS_DIR -- check to see if file exists and is a directory.
**
@@ -2482,6 +2431,7 @@ path_is_dir(pathname, createflag)
}
return true;
}
+
/*
** PROC_LIST_ADD -- add process id to list of our children
**
@@ -2545,15 +2495,19 @@ proc_list_add(pid, task, type, count, other, hostaddr)
if (i >= ProcListSize)
{
/* grow process list */
+ int chldwasblocked;
PROCS_T *npv;
SM_ASSERT(ProcListSize < INT_MAX - PROC_LIST_SEG);
- npv = (PROCS_T *) sm_pmalloc_x((sizeof *npv) *
+ npv = (PROCS_T *) sm_pmalloc_x((sizeof(*npv)) *
(ProcListSize + PROC_LIST_SEG));
+
+ /* Block SIGCHLD so reapchild() doesn't mess with us */
+ chldwasblocked = sm_blocksignal(SIGCHLD);
if (ProcListSize > 0)
{
memmove(npv, ProcListVec,
- ProcListSize * sizeof (PROCS_T));
+ ProcListSize * sizeof(PROCS_T));
sm_free(ProcListVec);
}
@@ -2567,6 +2521,8 @@ proc_list_add(pid, task, type, count, other, hostaddr)
i = ProcListSize;
ProcListSize += PROC_LIST_SEG;
ProcListVec = npv;
+ if (chldwasblocked == 0)
+ (void) sm_releasesignal(SIGCHLD);
}
ProcListVec[i].proc_pid = pid;
PSTRSET(ProcListVec[i].proc_task, task);
@@ -2586,6 +2542,7 @@ proc_list_add(pid, task, type, count, other, hostaddr)
CurChildren++;
}
}
+
/*
** PROC_LIST_SET -- set pid task in process list
**
@@ -2613,6 +2570,7 @@ proc_list_set(pid, task)
}
}
}
+
/*
** PROC_LIST_DROP -- drop pid from process list
**
@@ -2674,6 +2632,7 @@ proc_list_drop(pid, st, other)
else if (type == PROC_QUEUE)
CurRunners -= ProcListVec[i].proc_count;
}
+
/*
** PROC_LIST_CLEAR -- clear the process list
**
@@ -2697,6 +2656,7 @@ proc_list_clear()
ProcListVec[i].proc_pid = NO_PID;
CurChildren = 0;
}
+
/*
** PROC_LIST_PROBE -- probe processes in the list to see if they still exist
**
diff --git a/contrib/sendmail/src/version.c b/contrib/sendmail/src/version.c
index f5777280eb21..6bdfd1199c7a 100644
--- a/contrib/sendmail/src/version.c
+++ b/contrib/sendmail/src/version.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998-2006 Sendmail, Inc. and its suppliers.
+ * Copyright (c) 1998-2007 Sendmail, Inc. and its suppliers.
* All rights reserved.
* Copyright (c) 1983 Eric P. Allman. All rights reserved.
* Copyright (c) 1988, 1993
@@ -13,6 +13,6 @@
#include
-SM_RCSID("@(#)$Id: version.c,v 8.163.2.8 2006/07/26 17:24:02 ca Exp $")
+SM_RCSID("@(#)$Id: version.c,v 8.191 2007/04/03 21:21:18 ca Exp $")
-char Version[] = "8.13.8";
+char Version[] = "8.14.1";
diff --git a/contrib/sendmail/test/Makefile b/contrib/sendmail/test/Makefile
index 7ca1b40855ca..d0a88423bb54 100644
--- a/contrib/sendmail/test/Makefile
+++ b/contrib/sendmail/test/Makefile
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.1 2001/09/23 22:39:24 ca Exp $
+# $Id: Makefile,v 1.2 2006/05/30 18:50:26 ca Exp $
SHELL= /bin/sh
BUILD= ./Build
@@ -8,6 +8,8 @@ all: FRC
$(SHELL) $(BUILD) $(OPTIONS) $@
clean: FRC
$(SHELL) $(BUILD) $(OPTIONS) $@
+check: FRC
+ $(SHELL) $(BUILD) $(OPTIONS) $@
install: FRC
$(SHELL) $(BUILD) $(OPTIONS) $@
diff --git a/contrib/sendmail/vacation/Makefile.m4 b/contrib/sendmail/vacation/Makefile.m4
index ed4967ee5495..8979d5d3f437 100644
--- a/contrib/sendmail/vacation/Makefile.m4
+++ b/contrib/sendmail/vacation/Makefile.m4
@@ -1,7 +1,8 @@
-dnl $Id: Makefile.m4,v 8.25 2002/06/21 22:01:57 ca Exp $
+dnl $Id: Makefile.m4,v 8.26 2006/06/28 21:08:05 ca Exp $
include(confBUILDTOOLSDIR`/M4/switch.m4')
define(`confREQUIRE_LIBSM', `true')
+define(`confREQUIRE_SM_OS_H', `true')
# sendmail dir
SMSRCDIR= ifdef(`confSMSRCDIR', `confSMSRCDIR', `${SRCDIR}/sendmail')
PREPENDDEF(`confENVDEF', `confMAPDEF')
diff --git a/contrib/sendmail/vacation/vacation.c b/contrib/sendmail/vacation/vacation.c
index afccbf793917..4f31dddce91b 100644
--- a/contrib/sendmail/vacation/vacation.c
+++ b/contrib/sendmail/vacation/vacation.c
@@ -20,7 +20,7 @@ SM_IDSTR(copyright,
The Regents of the University of California. All rights reserved.\n\
Copyright (c) 1983 Eric P. Allman. All rights reserved.\n")
-SM_IDSTR(id, "@(#)$Id: vacation.c,v 8.142 2004/11/02 18:25:33 ca Exp $")
+SM_IDSTR(id, "@(#)$Id: vacation.c,v 8.143 2006/12/19 19:00:43 ca Exp $")
#include
@@ -53,6 +53,16 @@ bool DontInitGroups = false;
uid_t TrustedUid = 0;
BITMAP256 DontBlameSendmail;
+static int readheaders __P((bool));
+static bool junkmail __P((char *));
+static bool nsearch __P((char *, char *));
+static void usage __P((void));
+static void setinterval __P((time_t));
+static bool recent __P((void));
+static void setreply __P((char *, time_t));
+static void sendmessage __P((char *, char *, char *));
+static void xclude __P((SM_FILE_T *));
+
/*
** VACATION -- return a message to the sender when on vacation.
**
@@ -149,13 +159,6 @@ main(argc, argv)
static char rnamebuf[MAXNAME];
extern int optind, opterr;
extern char *optarg;
- extern void usage __P((void));
- extern void setinterval __P((time_t));
- extern int readheaders __P((bool));
- extern bool recent __P((void));
- extern void setreply __P((char *, time_t));
- extern void sendmessage __P((char *, char *, char *));
- extern void xclude __P((SM_FILE_T *));
/* Vars needed to link with smutil */
clrbitmap(DontBlameSendmail);
@@ -489,7 +492,7 @@ eatmsg()
**
*/
-int
+static int
readheaders(alwaysrespond)
bool alwaysrespond;
{
@@ -497,8 +500,6 @@ readheaders(alwaysrespond)
register char *p;
register ALIAS *cur;
char buf[MAXLINE];
- extern bool junkmail __P((char *));
- extern bool nsearch __P((char *, char *));
cont = false;
tome = alwaysrespond;
@@ -623,7 +624,7 @@ readheaders(alwaysrespond)
**
*/
-bool
+static bool
nsearch(name, str)
register char *name, *str;
{
@@ -677,7 +678,7 @@ typedef struct ignore IGNORE_T;
/* delimiters for the local part of an address */
#define isdelim(c) ((c) == '%' || (c) == '@' || (c) == '+')
-bool
+static bool
junkmail(from)
char *from;
{
@@ -815,7 +816,7 @@ junkmail(from)
**
*/
-bool
+static bool
recent()
{
SMDB_DBENT key, data;
@@ -877,7 +878,7 @@ recent()
** stores the reply interval in database.
*/
-void
+static void
setinterval(interval)
time_t interval;
{
@@ -908,7 +909,7 @@ setinterval(interval)
** stores user/time in database.
*/
-void
+static void
setreply(from, when)
char *from;
time_t when;
@@ -939,7 +940,7 @@ setreply(from, when)
** stores users in database.
*/
-void
+static void
xclude(f)
SM_FILE_T *f;
{
@@ -971,7 +972,7 @@ xclude(f)
** sends vacation reply.
*/
-void
+static void
sendmessage(myname, msgfn, sender)
char *myname;
char *msgfn;
@@ -1047,7 +1048,7 @@ sendmessage(myname, msgfn, sender)
}
}
-void
+static void
usage()
{
msglog(LOG_NOTICE,