]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
snapshot-20000507
authorWietse Venema <wietse@porcupine.org>
Sun, 7 May 2000 00:00:00 +0000 (00:00 +0000)
committerWietse Venema <wietse@porcupine.org>
Thu, 17 Jan 2013 23:10:48 +0000 (18:10 -0500)
43 files changed:
postfix/HISTORY
postfix/INSTALL
postfix/LDAP_README
postfix/LMTP_README
postfix/Makefile.in
postfix/RELEASE_NOTES
postfix/SASL_README
postfix/cleanup/cleanup_message.c
postfix/conf/master.cf
postfix/conf/sample-auth.cf
postfix/conf/sample-smtp.cf
postfix/global/mail_conf.c
postfix/global/mail_conf.h
postfix/global/mail_copy.c
postfix/global/mail_params.h
postfix/global/mail_version.h
postfix/global/smtp_stream.h
postfix/html/faq.html
postfix/html/pipe.8.html
postfix/html/smtp.8.html
postfix/lmtp/Makefile.in
postfix/lmtp/README.local [deleted file]
postfix/lmtp/fixnames [deleted file]
postfix/lmtp/lmtp.c
postfix/man/man8/pipe.8
postfix/man/man8/smtp.8
postfix/master/multi_server.c
postfix/master/single_server.c
postfix/master/trigger_server.c
postfix/pipe/pipe.c
postfix/smtp/smtp.c
postfix/smtp/smtp_connect.c
postfix/smtp/smtp_sasl_glue.c
postfix/smtpd/smtpd.c
postfix/smtpd/smtpd_chat.c
postfix/smtpd/smtpd_sasl_glue.c
postfix/smtpd/smtpd_sasl_proto.c
postfix/util/dict_ldap.c
postfix/util/sys_defs.h
postfix/util/unescape.c
postfix/util/vstream.c
postfix/util/vstring.c
postfix/util/vstring.h

index 0df70aa11ea5f888ad996481d6c7261d3aa7bdfa..33ba6aebdf2aa5e0298ecd506bb8011496ae22d6 100644 (file)
@@ -3618,7 +3618,7 @@ Apologies for any names omitted.
        field by the recipient localpart when a destination matches
        $mydestination/$inet_interfaces. The price is the introduction
        of a new parameter local_destination_recipient_limit which
-       defaults to 1 i order to maintain backwards compatibility.
+       defaults to 1 in order to maintain backwards compatibility.
        Files: qmgr/qmgr.c, qmgr/qmgr_message.c.
 
 20000129
@@ -3843,13 +3843,6 @@ Apologies for any names omitted.
        record delimiter (for example, eol=\r\n). This is necessary
        for transports that require CRLF instead of UNIX-style LF.
 
-20000428
-
-       New code: added support to the vstring module for fixed-size
-       buffers. This may help to avoid clumsy code that would have
-       to prevent memory leaks.  The buffers cause a fatal error
-       when they turn out too small.  File: util/vstring.[hc].
-
 20000502
 
        In order to support timeouts more conveniently, VSTREAMs
@@ -3881,13 +3874,45 @@ Apologies for any names omitted.
 
 20000505
 
-       Bugfix: the SMTP server now flushes output in-between tarpit
-       delays, to avoid protocol timeouts when a client causes lots
-       of errors. Found by Lamont Jones, HP. File:  smtpd/smtpd_chat.c.
+       Bugfix: the SMTP server now flushes unwritten output before
+       tarpit delays, to avoid protocol timeouts in pipelined
+       sessions when a client causes lots of errors. Found by
+       Lamont Jones, HP. File:  smtpd/smtpd_chat.c.
+
+       Finished the LMTP client, which is based on a modified
+       version of the SMTP client by Philippe Prindeville, Mirapoint,
+       Inc., later modified by Amos Gouaux, UTDallas, and then
+       Wietse ripped it all up again. Currently this talks LMTP
+       over TCP only.
+
+       Feature: override main.cf parameters in master.cf. Specify
+       "-o parameter=value" after the program name. This allows
+       you to selectively override myhostname etc. See also the
+       new smtp_bind_address parameter below.
 
 20000506
 
        Convenience: the LMTP and SMTP clients now append the local
        domain to unqualified nexthop destinations. This makes it
-       more convenient to set up transport maps. Files: 
+       more convenient to set up transport maps. Files:
        lmtp/lmtp_addr.c, smtp/smtp_addr.c.
+
+       Sendmail compatibility: the Postfix SMTP client now skips
+       servers that greet the client with a 4xx or 5xx status
+       code.  To disable, set both smtp_skip_4xx_greeting and
+       smtp_skip_5xx_greeting to "no".
+
+20000507
+
+       Portability: NetBSD has migrated to /etc/mail/aliases. We
+       can expect to see this happen more often when systems start
+       shipping Sendmail 8.10. File: util/sys_defs.h
+
+       Updated LDAP code by John Hensley, with support for
+       dereferencing of LDAP aliases, which have nothing to do
+       with Postfix aliases.
+
+       Feature: "smtp_bind_address=x.x.x.x" specifies the source
+       IP address for SMTP client connections. Specify in master.cf
+       as "smtp -o smtp_bind_address=x.x.x.x" in order to give
+       different delivery agents different source addresses.
index 2a1620e625ef6bd0f8938aaf250fa815c51b701f..b383ed8977b2684badb12c45a5fb696d5428b947 100644 (file)
@@ -92,10 +92,8 @@ development are in /usr/ccs/bin, so you MUST have /usr/ccs/bin in
 your command search path.
 
 If you need to build Postfix for multiple architectures, use the
-makelinks shell script to build a shadow tree with symbolic links
-to the source files.
-
-    % sh makelinks `pwd` /some/where/else
+lndir command to build a shadow tree with symbolic links to the
+source files. lndir is part of X11R6.
 
 If at any time in the build process you get messages like: "make:
 don't know how to ..." you should be able to recover by running
index 76d26eb0550b45c11a29d19aca239e53ebb985d6..50b020ed1a7ce0522539af2b12171aeeaae1bcc9 100644 (file)
@@ -1,3 +1,15 @@
+LDAP SUPPORT IN POSTFIX
+=======================
+
+Postfix can use an LDAP directory as a source for any of its lookups:
+aliases, virtual, canonical, etc. This allows you to keep information
+for your mail service in a replicated network database with fine-grained
+access controls. By not storing it locally on the mail server, the
+administrators can maintain it from anywhere, and the users can control
+whatever bits of it you think appropriate. You can have multiple mail
+servers using the same information, without the hassle and delay of
+having to copy it to each.
+
 BUILDING WITH LDAP SUPPORT
 ==========================
 
@@ -7,13 +19,14 @@ accordingly.
 
 If you're using the libraries from the UM distribution
 (http://www.umich.edu/~dirsvcs/ldap/ldap.html) or OpenLDAP
-(http://www.openldap.org), something like this should work:
+(http://www.openldap.org), something like this in the top level of your
+Postfix source tree should work:
 
     % make tidy
     % make makefiles CCARGS="-I/some/where/include -DHAS_LDAP" \
-           AUXLIBS="/some/where/libldap.a /some/where/liblber.a"
+           AUXLIBS="/some/where/lib/libldap.a /some/where/lib/liblber.a"
 
-The `make tidy' command is needed only if you have previously built
+The 'make tidy' command is needed only if you have previously built
 Postfix without LDAP support.
 
 If your LDAP libraries were built with Kerberos support, you'll also
@@ -21,16 +34,16 @@ need to include your Kerberos libraries in this line. Note that the KTH
 Kerberos IV libraries might conflict with Postfix's lib/libdns.a, which
 defines dns_lookup. If that happens, you'll probably want to link with
 LDAP libraries that lack Kerberos support just to build Postfix, as it
-doesn't yet support Kerberos binds to the LDAP server anyway. Sorry
-about the bother.
+doesn't support Kerberos binds to the LDAP server anyway. Sorry about
+the bother.
 
 If you're using one of the Netscape LDAP SDKs, you'll need to change the
 AUXLIBS line to point to libldap10.so or libldapssl30.so or whatever you
-have, and you may need to use the -R option so the executables can find
-it at runtime.
+have, and you may need to use the appropriate linker option (e.g. '-R')
+so the executables can find it at runtime.
 
-USING LDAP LOOKUPS
-==================
+CONFIGURING LDAP LOOKUPS
+========================
 
 In order to use LDAP lookups, define at least one LDAP source as a table
 lookup in main.cf, for example:
@@ -39,22 +52,24 @@ lookup in main.cf, for example:
 
 Each LDAP source can have the following parameters, which should be
 prefixed in main.cf with the name you've given the source in its
-definition. To continue the example, the first parameter below,
-"server_host", would be defined in main.cf as "ldapsource_server_host". 
-Defaults are given in parentheses:
+definition and an underscore. To continue the example, the first
+parameter below, "server_host", would be defined in main.cf as
+"ldapsource_server_host". Defaults are given in parentheses:
 
     server_host (localhost)
        The name of the host running the LDAP server, e.g.
                ldapsource_server_host = ldap.your.com
        It should be possible with all the libraries mentioned above to 
        specify multiple servers separated by spaces, with the libraries
-       trying them in order should the first one fail.
+       trying them in order should the first one fail. It should also
+       be possible to give each server in the list a different port, by
+       naming them like "ldap.your.com:1444".
 
     server_port (389) 
        The port the LDAP server listens on, e.g.
                ldapsource_server_port = 778
 
-    search_base (no default)
+    search_base (No default; you must configure this.)
        The base at which to conduct the search, e.g. 
                ldapsource_search_base = dc=your, dc=com
 
@@ -72,12 +87,23 @@ Defaults are given in parentheses:
        returned by the lookup, to be resolved to an email address.
                ldapsource_result_attribute = mailbox
 
+    scope (sub)
+        The LDAP search scope: sub, base, or one. These translate into
+       LDAP_SCOPE_SUBTREE, LDAP_SCOPE_BASE, and LDAP_SCOPE_ONELEVEL.
+
     bind (yes)
        Whether or not to bind to the LDAP server. Newer LDAP
        implementations don't require clients to bind, which saves
        time. Example:
                ldapsource_bind = no
 
+       If you do need to bind, you might consider configuring Postfix
+       to connect to the local machine on a port that's an SSL tunnel
+       to your LDAP server. If your LDAP server doesn't natively
+       support SSL, put a tunnel (wrapper, proxy, whatever you want to
+       call it) on that system too. This should prevent the password
+       from traversing the network in the clear.
+
     bind_dn ("")
        If you do have to bind, do it with this distinguished name.
        Example:
@@ -85,18 +111,44 @@ Defaults are given in parentheses:
 
     bind_pw ("")
        The password for the distinguished name above. If you have to
-       have this, you probably want to make main.cf readable only by
+       use this, you probably want to make main.cf readable only by
        the Postfix user. Example:
                ldapsource_bind_pw = postfixpw
 
+    cache (no)
+        Whether to use a client-side cache for the LDAP connection. See
+       ldap_enable_cache(3). It's off by default.
+
+    cache_expiry (30 seconds)
+        If the client-side cache is enabled, cached results will expire
+       after this many seconds.
+
+    cache_size (32768 bytes)
+        If the client-side cache is enabled, this is its size in bytes.
+
+    dereference (0)
+       When to dereference LDAP aliases. (Note that this has nothing
+       do with Postfix aliases.) The permitted values are those 
+       legal for the OpenLDAP/UM LDAP implementations:
+
+               0       never
+               1       when searching
+               2       when locating the base object for the search
+               3       always
+
+       See ldap.h or the ldap_open(3) or ldapsearch(1) man pages for
+       more information. And if you're using an LDAP package that has
+       other possible values, please bring it to the attention of the
+       postfix-users@postfix.org mailing list.
+
 Don't use quotes in these variables; at least, not until the Postfix
 configuration routines understand how to deal with quoted strings.
 
-EXAMPLE
-=======
+EXAMPLES
+========
 
-Here's a basic example. In main.cf, you have these configuration
-parameters defined:
+Here's a basic example for using LDAP to look up aliases. In main.cf,
+you have these configuration parameters defined:
 
 alias_maps = hash:/etc/aliases, ldap:ldapsource
 ldapsource_server_host = ldap.my.com
@@ -110,6 +162,45 @@ read the "maildrop" attributes of those found, and build a list of their
 maildrops, which will be treated as RFC822 addresses to which the
 message will be delivered.
 
+If you want to keep information for virtual lookups in your directory,
+it's only a little more complicated. You'll want to make sure all of
+your virtual mailacceptinggeneralid attributes are fully qualified with
+their virtual domains. If you want to designate a directory entry as the
+default user for a virtual domain, just give it an additional
+mailacceptinggeneralid (or the equivalent in your directory) of
+"@virtual.dom". That's right, no user part.
+
+If you want to get information for relay_domains out of your directory,
+the simplest way to get it is to add the domain name (without even the
+'@') as a mailacceptinggeneralid to some recipient in each domain, then
+add "$virtual_maps" to your relay_domains line. Then you can use the
+same map you use to find virtual recipients to determine if a domain is
+a valid virtual domain and should be allowed to relay.
+
+For example, the catchall user for a virtual domain might look like
+this:
+
+   dn: cn=defaultrecipient, dc=fake, dc=dom
+   objectclass: top
+   objectclass: rfc822mailgroup
+   cn: defaultrecipient
+   owner: uid=root, dc=someserver, dc=isp, dc=dom
+   mailacceptinggeneralid: fake.dom
+   mailacceptinggeneralid: @fake.dom
+   maildrop: realuser@real.dom         
+
+If you don't necessarily have a catchall user for the domain (i.e. you
+want mail to unknown users in the domain to bounce), and don't want to
+tag an arbitrary user in the virtual domain, you might define another
+LDAP map that finds your virtual domain's domain object entry, and add
+that map to relay_domains instead of "$virtual_maps". All that's
+necessary is that a search for the domain name return something.
+
+Other common uses for LDAP lookups include rewriting senders and
+recipients with Postfix' canonical lookups, for example in order to make
+mail leaving your site appear to be coming from "First.Last@site.dom"
+instead of "userid@site.dom".
+
 NOTES AND THINGS TO THINK ABOUT
 ===============================
 
@@ -117,10 +208,11 @@ NOTES AND THINGS TO THINK ABOUT
   unique, and that not just anyone can specify theirs as postmaster or
   root, say.
 
-- An entry can have an arbitrary number of maildrops. Maildrops can also
-  be comma-separated lists of addresses. For example, you could define
-  an entry intended for use as a mailing list that looks like this
-  (Warning! Schema made up just for this example):
+- An entry can have an arbitrary number of mailacceptinggeneralids or
+  maildrops. Maildrops can also be comma-separated lists of addresses.
+  They will all be found and returned by the lookups. For example, you
+  could define an entry intended for use as a mailing list that looks
+  like this (Warning! Schema made up just for this example):
 
   dn: cn=Accounting Staff List, dc=my, dc=com
   cn: Accounting Staff List
@@ -135,61 +227,41 @@ NOTES AND THINGS TO THINK ABOUT
 
 - If you use an LDAP map for lookups other than aliases, you may have to
   make sure the lookup makes sense. In the case of virtual lookups,
-  maildrops like "|/some/program" are pretty useless. Your query_filter
-  should probably look something like this:
+  maildrops other than mail addresses are pretty useless, because
+  Postfix can't know how to set the ownership for program or file
+  delivery. Your query_filter should probably look something like this:
 
-  virtual_query_filter = 
-       (&(mailacceptinggeneralid=%s)(!(|(maildrop="*|*")(maildrop="*:*"))))
+  virtual_query_filter = (&(mailacceptinggeneralid=%s)(!(|(maildrop="*|*")(maildrop="*:*")(maildrop="*/*"))))
 
-- And for that matter, you may not want users able to specify their
-  maildrops as programs, particularly if they'd be executed on the
-  server. A safer local query_filter could look something like:
+- And for that matter, even for aliases, you may not want users able to
+  specify their maildrops as programs, includes, etc. This might be
+  particularly pertinent on a "sealed" server where they don't have
+  local UNIX accounts, but exist only in LDAP and Cyrus. You might allow
+  the fun stuff only for directory entries owned by an administrative
+  account:
 
-  local_query_filter = (&(mailacceptinggeneralid=%s)(|(!(maildrop="*|*"))(owner=cn=root, dc=your, dc=com)))
+  local_query_filter = (&(mailacceptinggeneralid=%s)(|(!(maildrop="*|*")(maildrop="*:*")(maildrop="*/*"))(owner=cn=root, dc=your, dc=com)))
 
   So that if the object had a program as its maildrop and weren't owned
   by "cn=root" it wouldn't be returned as a valid local user. This will
-  probably require some thought on your part to implement safely,
-  considering the ramifications of includes and programs. You may decide
-  it's not worth the bother to allow any of that nonsense in LDAP
-  lookups, ban it in the query_filter, and keep things like majordomo
-  lists in local alias databases.
-
-- It's not yet known how all this scales, but LDAP lookups are much more
-  expensive than checking a DB file. If you anticipate a lot of lookups,
-  it may pay to plan your directory to reduce the number of lookups. For
-  instance, rather than having a bunch of objects that serve as aliases
-  to just one object, you could simply add their mailacceptinggeneralids
-  to the target object. This:
-
-       dn: uid=firstlast, dc=your, dc=com
-       maildrop: firstlast@mailbox.your.com
-       mailacceptinggeneralid: firstlast
-       mailacceptinggeneralid: First.Last
-       mailacceptinggeneralid: F.Last
-
-  Not this:
-  
-       dn: uid=firstlast, dc=your, dc=com
-       maildrop: firstlast@mailbox.your.com
-       mailacceptinggeneralid: firstlast
-
-       dn: cn=First.Last, dc=your, dc=com
-       maildrop: firstlast
-       mailacceptinggeneralid: First.Last
-
-       dn: cn=F.Last, dc=your, dc=com
-       maildrop: firstlast
-       mailacceptinggeneralid: F.Last
-
-  Any performance reports will be much appreciated on the postfix-users
-  list.
-
-  UPDATE: At Merit, I've seen over 150000 deliveries per day with no
-  noticeable delay from our OpenLDAP server. I'd now recommend not
-  resorting to the above unless you anticipate much more traffic than
-  that. It makes management of your directory less intuitive, which is
-  probably not worth the reduction in lookups.
+  require some thought on your part to implement safely, considering the
+  ramifications of this type of delivery. You may decide it's not worth
+  the bother to allow any of that nonsense in LDAP lookups, ban it in
+  the query_filter, and keep things like majordomo lists in local alias
+  databases.
+
+- LDAP lookups are slower than local DB or DBM lookups. For most sites
+  they won't be a bottleneck, but it's a good idea to know how to tune
+  your directory service.
+
+FEEDBACK
+========
+
+If you have questions, send them to postfix-users@postfix.org. Please
+include relevant information about your Postfix setup: LDAP-related
+output from postconf, which LDAP libraries you built with, and which
+directory server you're using. If your question involves your directory
+contents, please include the applicable bits of some directory entries.
 
 CREDITS
 =======
@@ -198,6 +270,13 @@ Support for LDAP was initially written by Prabhat K Singh of VSNL,
 Bombay, India, and then hideously bloated by John Hensley to support
 multiple sources and more configurable attributes. The caching bits were
 initially worked out by Prabhat, then munged to support the multiple
-sources. Other contributions have been submitted to move toward better
-support of Netscape/LDAPv3 libraries, and any other improvements are of
-course welcome.
+sources. 
+
+Other contributors, of code or direction or dope slaps, include:
+
+Manuel Guesdon
+Carsten Hoeger
+Keith Stevenson
+Samuel Tardieu
+
+And of course Wietse.
index 2e39a785a3b980eb35aa0c9d477a168d4f747a54..f21f7cbb9dea142a95d4fe9bcea33e984e849d39 100644 (file)
@@ -1,10 +1,11 @@
 Postfix LMTP support
 ====================
 
-Postfix LMTP support was initially implemented by Philip A.
-Prindeville of Mirapoint, Inc., USA, and was modified further by
-Amos Gouaux of University of Texas at Dallas, Richardson, USA.
-Wietse then beat the code into its present shape.
+Postfix LMTP support is based on a modified version of the Postfix
+SMTP client. The initial version was by Philip A.  Prindeville of
+Mirapoint, Inc., USA. This code was modified further by Amos Gouaux
+of University of Texas at Dallas, Richardson, USA.  Wietse Venema
+reduced the code to its present shape.
 
 Postfix can be configured to talk to a local or remote LMTP server.
 Most people will run the LMTP server on the same machine that runs
@@ -27,10 +28,15 @@ Next, put the following in /etc/inetd.conf:
 
     lmtp    stream  tcp     nowait  cyrus   /usr/sbin/tcpd  /usr/local/cyrus/bin/deliver -e -l
 
-/usr/sbin/tcpd is from the tcp_wrappers package.  You want this
-to make sure only your mail relay(s) can talk to the LMTP server.
-Postfix by default enables connection cacheing for delivery via
-LMTP, so do not worry about the load of wrapping the LMTP port.
+/usr/sbin/tcpd is from the tcp_wrappers package.  You want this to
+make sure only your mail relay(s) can talk to the LMTP server.
+Postfix by default does multiple deliveries per LMTP session
+(connection cacheing), so do not worry about the overhead of
+tcp_wrapping the LMTP port.
+
+On some systems, tcpd is built into inetd, so you do not have to
+specify tcpd in the inetd.conf file. Instead of tcpd/inetd, xinetd
+can do a similar job of logging and access control.
 
 Configuring Postfix
 ===================
@@ -43,39 +49,45 @@ You may have to add the following entry to /etc/postfix/master.cf:
 
     lmtp      unix  -       -       n       -       -       lmtp
 
-NOTES:  Root privs are not necessary!
+NOTE:  Root privileges are not necessary!
 
-We put this in /etc/postfix/transport:
+Put this in /etc/postfix/transport:
 
     inbox.domain.org     lmtp:inbox.domain.org
 
-Naturally, this means we also have to have in 
-/etc/postfix/main.cf:
+Naturally, this means we also need in /etc/postfix/main.cf:
 
     transport_maps      = hash:/etc/postfix/transport
 
-Use the map type of your choice. Use "postconf -m" to find out
-what map types are supported.
+Instead of "hash", use the map type of your choice. Some systems
+use "dbm" instead. Use "postconf -m" to find out what map types
+are supported.
 
-Connection cacheing performance
-===============================
+Improving connection cacheing performance
+=========================================
 
 After delivering a message via LMTP, Postfix will keep the connection
 open for a while, so that it can be reused for a subsequent delivery.
 This reduces overhead of LMTP servers that create one process per
 connection.  
 
-The Postfix LMTP client makes only one connection at a time. For
-connection cacheing to work well, the Postfix LMTP client has to
-avoid switching destination hosts. If you have multiple LMTP servers,
-configure separate master.cf entries for each LMTP server, and
-configure transport entries that distribute mail domains to the
-right LMTP servers.
+For LMTP connection cacheing to work, the Postfix LMTP client should
+not switch destination hosts.  This is no problem when you run only
+one LMTP server. However, if you run multiple LMTP servers, this
+can be an issue.
 
-    /etc/postfix/transport:
-        foo.com lmtp1:lmtp1host
-        bar.com lmtp2:lmtp2host
+You can prevent the LMTP client from switching between servers by
+configuring a separate mail delivery transport for each LMTP server:
 
     /etc/postfix/master.cf:
         lmtp1      unix  -       -       n       -       -       lmtp
         lmtp2      unix  -       -       n       -       -       lmtp
+          .         .    .       .       .       .       .        .
+
+Configure transport table entries such that the lmtp1 mail delivery
+transport is used for all deliveries to the LMTP server #1, the
+mail lmtp2 transport for the LMTP server #2, and so on.
+
+    /etc/postfix/transport:
+        foo.com lmtp1:lmtp1host
+        bar.com lmtp2:lmtp2host
index af831c7678288ddff1875b6baabe604881c5fe56..ce59fd1d1d76c61a43147e52480af97d33ce6707 100644 (file)
@@ -4,7 +4,7 @@ OPTS    = "CC=$(CC)"
 DIRS   = util global dns master postfix smtpstone sendmail error \
        pickup cleanup smtpd local lmtp trivial-rewrite qmgr smtp bounce pipe \
        showq postalias postcat postconf postdrop postkick postlock postlog \
-       postmap postsuper spawn # base64 proto man html
+       postmap postsuper # spawn base64 proto man html
 
 default: update
 
index aba10614af06f9af54ec9fbb55cbaadadcf496c1..c1fce4090953506b8da9426e236562e8a3477cc5 100644 (file)
@@ -1,37 +1,64 @@
-Incompatible changes with snapshot-20000506
+Incompatible changes with snapshot-20000507
 ===========================================
 
-None.
+As required by RFC 822, Postfix now inserts a generic destination
+message header when no destination header is present.  The text is
+specified via the undisclosed_recipients_header configuration
+parameter (default:  "To: undisclosed-recipients:;").
+
+The Postfix sendmail command treats a line with only `.' as
+the end of input, for the sake of sendmail compatibility. To disable
+this feature, specify the sendmail-compatible `-i' or `-oi' flags
+on the sendmail command line.
+
+For the sake of Sendmail compatibility, the Postfix SMTP client
+skips over SMTP servers that greet with a 4XX or 5XX reply code,
+treating them as unreachable servers.  To obtain prior behavior
+(4XX=retry, 5XX=bounce), specify "smtp_skip_4xx_greeting = no" and
+"smtp_skip_5xx_greeting = no".
+
+The read/write interface underneath VSTREAMs has been extended with
+parameters that specify a read/write timeout and application context.
+This should make it easier to plug in encryption modules such as TLS.
 
-Major changes with snapshot-20000506
+Major changes with snapshot-20000507
 ====================================
 
-Preliminary LMTP client support with connection cacheing, currently
-only over TCP sockets.  Support for LMTP over UNIX-domain support
-will be added later. See the LMTP_README file for more details.
+Better documentation of Postfix lookup tables, including descriptions
+of how to use regular expressions in Postfix lookup tables.
+
+Updated mysql and LDAP client code with fixes and improvements.
+
+In master.cf you can selectively override main.cf configuration
+parameters, for example: "smtpd -o myhostname=foo.com".
+
+In main.cf, specify "smtp_bind_address=x.x.x.x" to bind SMTP
+connections to a specific local interface. Or override the default
+setting in master.cf with "smtp -o smtp_bind_address=x.x.x.x".
+For now, you must specify a numeric IP address.
+
+Preliminary LMTP client support over TCP with connection cacheing.
+Support for LMTP over UNIX-domain sockets will be added later as
+an enhancement to the transport table syntax. See the LMTP_README
+file for more details.
+
+By the way, LMTP client-side connection cacheing is a good example
+for how to do the same in the SMTP client.
 
 Preliminary support for SASL authentication, both in the SMTP server
 and in the SMTP client. See the SASL_README file for more details.
 
-The pipe mailer now has a configurable end-of-line attribute.
-Specify, for example, "pipe ... eol=\r\n" for delivery mechanisms
-that require CRLF record delimiters.
-
-The manual pages in sample configuration files now show plain text
-without TROFF escape sequences.
+The pipe delivery agent has a configurable end-of-line attribute.
+Specify "pipe ... eol=\r\n" for delivery mechanisms that require
+CRLF record delimiters. The eol attribute understands the following
+C-style escape sequences:  \a \b \f \n \r \t \v \nnn \\.
 
 Incompatible changes with snapshot-20000309
 ===========================================
 
-As required by RFC 822, Postfix now inserts a generic destination 
-message header when no destination header is present.  The text is  
-specified via the undisclosed_recipients_header configuration 
-parameter (default:  "To: undisclosed-recipients:;").
-
-The Postfix sendmail command now treats a line with only `.' as
-the end of input, for the sake of sendmail compatibility. To disable
-this feature, specify the sendmail-compatible `-i' or `-oi' flags
-on the sendmail command line.
+This release is mainly to have a reference point after reorganizing
+the cleanup daemon, and before adding some major contributions from
+other people.
 
 Major changes with snapshot-20000309
 ====================================
@@ -50,7 +77,6 @@ read keys from stdin).
 The manual pages in Postfix configuration files no longer contain
 troff formatting codes.  The text is now generated from prototype
 files in a new "proto" subdirectory.
-        
 
 Incompatible changes with postfix-19991231:
 ===========================================
index dc1034c7ac55600f4f5d7e298c8b69ce469cc07a..13ebf317d61f7b47193b2dfa81b7c595323ab288 100644 (file)
@@ -3,8 +3,8 @@ WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
 
 Do not use this code.  The Postfix SASL support is based on the
 Cyrus SASL library, which has not enough documentation about how
-the software is supposed to work, and it is not clear if the code
-is safe enough for security-critical applications.
+the software is supposed to work. It is not clear if the code is
+safe enough for security-critical applications.
 
 Postfix+SASL 1.5.5 appears to work on RedHat 6.1 (pwcheck_method
 set to shadow or sasldb), Solaris 2.7 (pwcheck_method set to shadow
@@ -53,19 +53,19 @@ and that the Cyrus SASL libraries are in /usr/local/lib.
 
 On some systems this generates the necessary Makefile definitions:
 
-    % make tidy # if you have left-over files from a previus build
+    % make tidy # if you have left-over files from a previous build
     % make makefiles CCARGS=-DUSE_SASL_AUTH" -I/usr/local/include" \
        AUXLIBS="-L/usr/local/lib -lsasl"
 
 On Solaris 2.x you need to specify run-time link information,
 otherwise ld.so will not find the SASL shared library:
 
-    % make tidy # if you have left-over files from a previus build
+    % make tidy # if you have left-over files from a previous build
     % make makefiles CCARGS=-DUSE_SASL_AUTH" -I/usr/local/include" \
        AUXLIBS="-L/usr/local/lib -R/usr/local/lib -lsasl"
 
-Enabling SASL authentication in the SMTP server
-===============================================
+Enabling SASL authentication in the Postfix SMTP server
+=======================================================
 
 If you installed the Cyrus SASL libraries as per the default, you
 will have to symlink /usr/lib/sasl -> /usr/local/lib/sasl.
@@ -83,18 +83,34 @@ In order to allow mail relaying by authenticated clients:
        smtpd_recipient_restrictions = 
            permit_mynetworks permit_sasl_authenticated ...
 
-In /usr/local/lib/sasl/smtpd.conf you need to specify what authentication
-mechanism the server will support, for example:
+In /usr/local/lib/sasl/smtpd.conf you need to specify how the server
+should validate client passwords. For example:
 
-    pwcheck_method:  sasldb
+    /usr/local/lib/sasl/smtpd.conf:
+       pwcheck_method:  sasldb
 
 This will use the SASL password file (default: /etc/sasldb), which
-is maintained with the saslpasswd command. On some systems the
-saslpasswd command needs to be run multiple times before it stops
-complaining.  The Postfix SMTP server needs read access to the
-sasldb file - you have to play games with group access permissions.
+is maintained with the saslpasswd command (part of the Cyrus SASL
+software). On some poorly-supported systems the saslpasswd command
+needs to be run multiple times before it stops complaining.  The
+Postfix SMTP server needs read access to the sasldb file - you may
+have to play games with group access permissions. On RedHat 6.1,
+SASL 1.5.5 insists on write access to /etc/sasldb.
 
-To run chrooted with SASL support is an interesting exercise.
+Instead of the SASL-specific password file you can configure the
+Postfix SMTP server to validate client passwords against the UNIX
+shadow password file:
+
+    /usr/local/lib/sasl/smtpd.conf:
+       pwcheck_method:  shadow
+
+However this requires that Postfix has read access to the UNIX shadow
+password file, which is normally readable only by root.  Shadow
+password support has been found to work for Solaris 2.7 and RedHat
+6. 1 but not with freeBSD 3.4.
+
+To run software chrooted with SASL support is an interesting exercise.
+This is one of the many problems with the present SASL support.
 
 To test the whole mess, connect to the SMTP server, and you should
 be able to have a conversation like this:
@@ -114,8 +130,8 @@ Instead of dGVzdAB0ZXN0AHRlc3RwYXNz, specify the base64 encoded
 form of username\0username\0password (the \0 is a null byte). The
 example above is for a user named `test' with password `testpass'.
 
-Enabling SASL authentication in the SMTP client
-===============================================
+Enabling SASL authentication in the Postfix SMTP client
+=======================================================
 
 Turn on client-side SASL authentication, and specify a table with
 per-host username and password information.
@@ -128,6 +144,6 @@ per-host username and password information.
        foo.com         username:password
        bar.com         username
 
-The SASL password file is opened before the SMTP server enters the
-optional chroot jail, so there is no need to copy the sasl_passwd
-DB or DBM file into /var/spool/postfix/etc/postfix.
+The SASL client password file is opened before the SMTP server
+enters the optional chroot jail, so you can keep the file in
+/etc/postfix.
index c29808f003f2f4fed9311139e0066655bf42e53d..1e5e5117da9b66522c443b88b5e5bbdfbe207d26 100644 (file)
@@ -358,11 +358,11 @@ static void cleanup_missing_headers(CLEANUP_STATE *state)
        vstring_sprintf(state->temp2, "%sFrom: %s",
                        state->resent, vstring_str(state->temp1));
        if (state->fullname && *state->fullname) {
-           vstring_strcat(state->temp2, " (");
-           token = tok822_alloc(TOK822_COMMENT_TEXT, state->fullname);
+           vstring_sprintf(state->temp1, "(%s)", state->fullname);
+           token = tok822_parse(vstring_str(state->temp1));
+           vstring_strcat(state->temp2, " ");
            tok822_externalize(state->temp2, token, TOK822_STR_NONE);
-           tok822_free(token);
-           vstring_strcat(state->temp2, ")");
+           tok822_free_tree(token);
        }
        CLEANUP_OUT_BUF(state, REC_TYPE_NORM, state->temp2);
     } else if ((state->headers_seen & (1 << (state->resent[0] ?
index 34e222855f6da1a130d02ef18f112f79b95b68f9..e3c05a1be756e722c5fed6b5421b41c797b96dc0 100644 (file)
@@ -70,7 +70,7 @@ smtp    unix  -       -       n       -       -       smtp
 showq     unix n       -       n       -       -       showq
 error     unix -       -       n       -       -       error
 local    unix  -       n       n       -       -       local
-lmtp     unix  -       -       n       -       -       lmtp server=localhost
+lmtp     unix  -       -       n       -       -       lmtp
 cyrus    unix  -       n       n       -       -       pipe
     flags=R user=cyrus argv=/cyrus/bin/deliver -e -m ${extension} ${user}
 uucp     unix  -       n       n       -       -       pipe
index eaf66feec6a345c8acacc4365c177b3112a61dc0..e4e30d4efeaf6aa12f132f37520bcd4b6379fa28 100644 (file)
@@ -2,15 +2,24 @@
 # HERE JUST SERVES AS AN EXAMPLE.
 #
 # This file contains example settings of Postfix configuration 
-# parameters that control SASL authentication.
+# parameters that control SASL authentication for the Postfix
+# SMTP server and client programs.
 
 # SMTP SERVER CONTROLS
 
-# The smtpd_sasl_auth_enable parameter controls whether authentication
-# is enabled in the Postfix SMTP server.
+# The smtpd_sasl_auth_enable parameter controls whether SMTP client
+# authentication is enabled in the Postfix SMTP server. By default,
+# the Postfix SMTP server does not use authentication.
 #
-# If a client is authenticated, then the permit_sasl_authenticated
-# can be used to permit relay access.
+# If an SMTP client is authenticated, then the permit_sasl_authenticated
+# access restriction can be used to permit relay access, like this:
+#
+#      smtpd_recipient_restrictions = permit_sasl_authenticated, ...
+#
+# To reject all SMTP connections from unauthenticated clients,
+# specify smtpd_delay_reject=yes (which is the default) and use:
+#
+#      smtpd_client_restrictions = permit_sasl_authenticated
 #
 # In order to enable server-side authentication, build Postfix with
 # SASL support, and install a configuration file /usr/lib/sasl/smtpd.conf
 #      pwcheck_method:  sasldb
 #
 # or whatever method is suitable for your environment: PAM, shadow,
-# whatever.  If you use sasldb, you can add users with the "saslpasswd"
-# command that is part of the SASL library. If you use PAM, The PAM
-# service name for SASL authentication is "smtp", and adding users
-# depends entirely on how PAM is set up.
+# etc.  If you use sasldb, you can add users with the "saslpasswd"
+# command that comes with the SASL library. If you configure Postfix
+# to use PAM, the PAM service name for SASL authentication is "smtp",
+# and adding users depends entirely on how PAM is set up.
 #
 # If you run your SMTP server chrooted, then you need to copy PAM
 # and/or SASL support libraries and data files into the chroot jail.
+# That's a lot of files, and it seems not very practical to do so.
 #
-smtpd_sasl_auth_enable = yes
+#smtpd_sasl_auth_enable = yes
+smtpd_sasl_auth_enable = no
 
 # The smtpd_sasl_security_options parameter controls what authentication
 # mechanisms the Postfix SMTP server will offer to the client.  The
@@ -43,10 +54,10 @@ smtpd_sasl_auth_enable = yes
 # By default, the Postfix SMTP server accepts plaintext passwords but
 # not anonymous logins. 
 #
-# Horror! It appears that clients try authentication methods in the
-# order as advertised by the server (PLAIN ANONYMOUS CRAM-MD5
-# ...) which means that if you disable plaintext passwords, clients
-# will log in anonymously even when they would be able to use CRAM-MD5.
+# HORROR! It appears that clients try authentication methods in the
+# order as advertised by the server (e.g., PLAIN ANONYMOUS CRAM-MD5)
+# which means that if you disable plaintext passwords, clients will
+# log in anonymously, even when they should be able to use CRAM-MD5.
 # So, if you disable plaintext logins, disable anonymous logins too.
 # Postfix treats anonymous login as no authentication.
 #
@@ -56,9 +67,11 @@ smtpd_sasl_security_options = noanonymous
 # SMTP CLIENT CONTROLS
 
 # The smtp_sasl_auth_enable parameter controls whether authentication
-# is enabled in the Postfix SMTP client.
+# is enabled in the Postfix SMTP client. By default, the Postfix SMTP
+# client uses no authentication.
 #
-smtp_sasl_auth_enable = yes
+#smtp_sasl_auth_enable = yes
+smtp_sasl_auth_enable = no
 
 # The smtp_sasl_password_maps parameter specifies the names of lookup
 # tables with one username:password entry per remote hostname.  If a
@@ -66,7 +79,7 @@ smtp_sasl_auth_enable = yes
 # client will not attempt to authenticate to the remote host.
 #
 # The Postfix SMTP client opens the lookup table before going to
-# chroot jail, so you can keep the password file in /etc/postfix.
+# chroot jail, so you can leave the password file in /etc/postfix.
 #
 smtp_auth_passwd_map = hash:/etc/postfix/saslpass
 
index 084c0ad6d183a802d0392c956ad106839ce8e386..c0fea6563c0f280c819ad5722377277a07d095bf 100644 (file)
@@ -33,6 +33,15 @@ fallback_relay =
 #
 ignore_mx_lookup_error = no
 
+# The smtp_bind_address parameter specifies a numerical network
+# address that the client should bind to when making a connection.
+# This can be used in the main.cf file, or in the master.cf file,
+# for example:
+# 
+#      smtp ... smtp -o smtp_bind_address=111.222.333.444
+# 
+#smtp_bind_address=111.222.333.444
+
 # The smtp_skip_4xx_greeting parameter controls what happens when
 # an SMTP server greets us with a 4XX status code. By default, Postfix
 # backs off. Specify "smtp_skip_4xx_greeting = yes" to move on the
index bb491892cc4576aacefb1ce08e729d9ea8cbb4c1..2af13f29c55ebad309c52f60ccf68871f4cfe01e 100644 (file)
@@ -8,6 +8,8 @@
 /*
 /*     void    mail_conf_read()
 /*
+/*     void    mail_conf_suck()
+/*
 /*     void    mail_conf_update(name, value)
 /*     const char *name;
 /*     const char *value;
 /*     const char *mail_conf_lookup_eval(name)
 /*     const char *name;
 /* DESCRIPTION
-/*     mail_conf_read() reads the global Postfix configuration file, and
+/*     mail_conf_suck() reads the global Postfix configuration file, and
 /*     stores its values into a global configuration dictionary.
 /*
+/*     mail_conf_read() invokes mail_conf_suck() and assigns the values
+/*     to global variables by calling mail_params_init().
+/*
 /*     The following routines are wrappers around the generic dictionary
 /*     access routines.
 /*
 /* mail_conf_read - read global configuration file */
 
 void    mail_conf_read(void)
+{
+    mail_conf_suck();
+    mail_params_init();
+}
+
+/* mail_conf_suck - suck in the global configuration file */
+
+void    mail_conf_suck(void)
 {
     char   *config_dir;
     char   *path;
@@ -107,7 +120,6 @@ void    mail_conf_read(void)
     path = concatenate(var_config_dir, "/", "main.cf", (char *) 0);
     dict_load_file(CONFIG_DICT, path);
     myfree(path);
-    mail_params_init();
 }
 
 /* mail_conf_eval - expand macros in string */
index 6443ff78d1f8a50036db264018c8051b070c007e..1d77f145cbc1f3472bd4708d68035899ecfca8a5 100644 (file)
@@ -33,6 +33,7 @@
   * Basic configuration management.
   */
 extern void mail_conf_read(void);
+extern void mail_conf_suck(void);
 
 extern void mail_conf_update(const char *, const char *);
 extern const char *mail_conf_lookup(const char *);
index a2e26aa86e01e0fda7d0d69d465e782336dfaf07..912f1a7eef42dd69bf2dcb1647b719e34ba29a00 100644 (file)
@@ -136,10 +136,9 @@ int     mail_copy(const char *sender, const char *delivered,
        quote_822_local(buf, sender);
        if (flags & MAIL_COPY_FROM) {
            time(&now);
-           vstream_fprintf(dst, "From %s  %s", *sender == 0 ?
-                           MAIL_ADDR_MAIL_DAEMON :
-                           vstring_str(buf),
-                           asctime(localtime(&now)));
+           vstream_fprintf(dst, "From %s  %.24s%s", *sender == 0 ?
+                           MAIL_ADDR_MAIL_DAEMON : vstring_str(buf),
+                           asctime(localtime(&now)), eol);
        }
        if (flags & MAIL_COPY_RETURN_PATH) {
            vstream_fprintf(dst, "Return-Path: <%s>%s",
index 29bd2d258437839ee8c7cbb3fdc390e4e14cb5f7..16eb7b5ef66a8b32b1cc924fc0e10e1bb6dd63c4 100644 (file)
@@ -609,6 +609,10 @@ extern bool var_skip_quit_resp;
 #define DEF_SMTP_ALWAYS_EHLO   0
 extern bool var_smtp_always_ehlo;
 
+#define VAR_SMTP_BIND_ADDR     "smtp_bind_address"
+#define DEF_SMTP_BIND_ADDR     ""
+extern char *var_smtp_bind_addr;
+
  /*
   * SMTP server. The soft error limit determines how many errors an SMTP
   * client may make before we start to slow down; the hard error limit
index 81e972d267259882a2ef51936cd9580003e07559..df72da36d3ec066889c61b03268eccbb15c03db5 100644 (file)
@@ -15,7 +15,7 @@
   * Version of this program.
   */
 #define VAR_MAIL_VERSION       "mail_version"
-#define DEF_MAIL_VERSION       "Snapshot-20000506"
+#define DEF_MAIL_VERSION       "Snapshot-20000507"
 extern char *var_mail_version;
 
 /* LICENSE
index 296eae28af6ca35f634c29025af1efb0d502af14..f1f087b49a535d9c81ba1508b8e10346c2c4b60e 100644 (file)
@@ -29,7 +29,6 @@
 #define SMTP_ERR_EOF   1               /* unexpected client disconnect */
 #define SMTP_ERR_TIME  2               /* time out */
 
-extern void smtp_jump_setup(VSTREAM *, jmp_buf *);
 extern void smtp_timeout_setup(VSTREAM *, int);
 extern void smtp_printf(VSTREAM *, const char *,...);
 extern int smtp_get(VSTRING *, VSTREAM *, int);
index acad8c3aff986e789b7e67b3980276786f434f89..c8c95e19beba10107fd73b0aa560aa5499d93111 100644 (file)
@@ -99,7 +99,7 @@ distribution list</a>
 
 <ul>
 
-<li><a href="#delay">Postfix responds slowly to SMTP connections</a>
+<li><a href="#delay">Postfix responds slowly to incoming SMTP connections</a>
 
 <li><a href="#numerical_log">Postfix logs SMTP clients as IP
 addresses</a>
@@ -779,7 +779,7 @@ delivery agent deals with undeliverable mail.
 
 <hr>
 
-<a name="delay"><h3>Postfix responds slowly to SMTP connections</h3></a>
+<a name="delay"><h3>Postfix responds slowly to incoming SMTP connections</h3></a>
 
 <dl>
 
index f18c24f49fbc700953167739e9c83bf7cfe2110e..eeed535672022db6a771fcb2b35746194a8b2cf3 100644 (file)
@@ -73,36 +73,37 @@ PIPE(8)                                                   PIPE(8)
 
        <b>eol=string</b> (default: <b>\n</b>)
               The output record delimiter.  Typically  one  would
-              use either <b>\r\n</b> or <b>\n</b>. You can specify the usual C-
-              style backslash escape sequences.
+              use  either <b>\r\n</b> or <b>\n</b>. The usual C-style backslash
+              escape sequences are recognized: <b>\a</b> <b>\b</b> <b>\f</b> <b>\n</b> <b>\r</b>  <b>\t</b>
+              <b>\v</b> <b>\</b><i>octal</i> and <b>\\</b>.
 
        <b>argv</b>=<i>command</i>... (required)
-              The command to be executed. This must be  specified
+              The  command to be executed. This must be specified
               as the last command attribute.  The command is exe-
               cuted  directly,  i.e.  without  interpretation  of
-              shell  meta  characters  by  a shell command inter-
+              shell meta characters by  a  shell  command  inter-
               preter.
 
               In  the  command  argument  vector,  the  following
               macros are recognized and replaced with correspond-
-              ing information  from  the  Postfix  queue  manager
+              ing  information  from  the  Postfix  queue manager
               delivery request:
 
               <b>${extension</b>}
-                     This  macro expands to the extension part of
-                     a recipient address.  For example,  with  an
+                     This macro expands to the extension part  of
+                     a  recipient  address.  For example, with an
                      address  <i>user+foo@domain</i>  the  extension  is
-                     <i>foo</i>.  A command-line argument that  contains
-                     <b>${extension</b>}  expands  into as many command-
+                     <i>foo</i>.   A command-line argument that contains
+                     <b>${extension</b>} expands into as  many  command-
                      line arguments as there are recipients.
 
               <b>${mailbox</b>}
-                     This macro expands  to  the  complete  local
-                     part  of  a recipient address.  For example,
-                     with an address <i>user+foo@domain</i> the  mailbox
-                     is  <i>user+foo</i>.   A command-line argument that
-                     contains <b>${mailbox</b>}  expands  into  as  many
-                     command-line  arguments as there are recipi-
+                     This  macro  expands  to  the complete local
+                     part of a recipient address.   For  example,
+                     with  an address <i>user+foo@domain</i> the mailbox
+                     is <i>user+foo</i>.  A command-line  argument  that
+                     contains  <b>${mailbox</b>}  expands  into  as many
+                     command-line arguments as there are  recipi-
                      ents.
 
               <b>${nexthop</b>}
@@ -110,21 +111,20 @@ PIPE(8)                                                   PIPE(8)
 
               <b>${recipient</b>}
                      This macro expands to the complete recipient
-                     address.  A command-line argument that  con-
+                     address.   A command-line argument that con-
                      tains <b>${recipient</b>} expands into as many com-
                      mand-line arguments as there are recipients.
 
               <b>${sender</b>}
-                     This  macro  expands  to the envelope sender
+                     This macro expands to  the  envelope  sender
                      address.
 
               <b>${user</b>}
                      This macro expands to the username part of a
-                     recipient  address.   For  example,  with an
+                     recipient address.   For  example,  with  an
                      address <i>user+foo@domain</i> the username part is
                      <i>user</i>.  A command-line argument that contains
-                     <b>${user</b>} expands into  as  many  command-line
-                     arguments as there are recipients.
+                     <b>${user</b>}  expands  into  as many command-line
 
 
 
@@ -137,60 +137,60 @@ PIPE(8)                                                   PIPE(8)
 PIPE(8)                                                   PIPE(8)
 
 
-       In  addition  to  the  form  ${<i>name</i>},  the forms $<i>name</i> and
-       $(<i>name</i>) are also recognized.  Specify <b>$$</b> where a single  <b>$</b>
+                     arguments as there are recipients.
+
+       In addition to the  form  ${<i>name</i>},  the  forms  $<i>name</i>  and
+       $(<i>name</i>)  are also recognized.  Specify <b>$$</b> where a single <b>$</b>
        is wanted.
 
 <b>DIAGNOSTICS</b>
-       Command  exit status codes are expected to follow the con-
+       Command exit status codes are expected to follow the  con-
        ventions defined in &lt;<b>sysexits.h</b>&gt;.
 
-       Problems and transactions are logged to <b>syslogd</b>(8).   Cor-
-       rupted  message files are marked so that the queue manager
+       Problems  and transactions are logged to <b>syslogd</b>(8).  Cor-
+       rupted message files are marked so that the queue  manager
        can move them to the <b>corrupt</b> queue for further inspection.
 
 <b>SECURITY</b>
-       This  program  needs  a  dual personality 1) to access the
-       private Postfix queue and IPC mechanisms, and 2)  to  exe-
+       This program needs a dual personality  1)  to  access  the
+       private  Postfix  queue and IPC mechanisms, and 2) to exe-
        cute external commands as the specified user. It is there-
        fore security sensitive.
 
 <b>CONFIGURATION</b> <b>PARAMETERS</b>
-       The following <b>main.cf</b> parameters are  especially  relevant
-       to  this  program. See the Postfix <b>main.cf</b> file for syntax
-       details and for default values.  Use  the  <b>postfix</b>  <b>reload</b>
+       The  following  <b>main.cf</b> parameters are especially relevant
+       to this program. See the Postfix <b>main.cf</b> file  for  syntax
+       details  and  for  default  values. Use the <b>postfix</b> <b>reload</b>
        command after a configuration change.
 
 <b>Miscellaneous</b>
        <b>mail</b><i>_</i><b>owner</b>
-              The  process  privileges  used while not running an
+              The process privileges used while  not  running  an
               external command.
 
 <b>Resource</b> <b>controls</b>
-       In the text below, <i>transport</i> is the first field in a  <b>mas-</b>
+       In  the text below, <i>transport</i> is the first field in a <b>mas-</b>
        <b>ter.cf</b> entry.
 
        <i>transport_</i><b>destination</b><i>_</i><b>concurrency</b><i>_</i><b>limit</b>
               Limit the number of parallel deliveries to the same
-              destination, for delivery via the named  <i>transport</i>.
-              The  default limit is taken from the <b>default</b><i>_</i><b>desti-</b>
-              <b>nation</b><i>_</i><b>concurrency</b><i>_</i><b>limit</b> parameter.  The  limit  is
+              destination,  for delivery via the named <i>transport</i>.
+              The default limit is taken from the  <b>default</b><i>_</i><b>desti-</b>
+              <b>nation</b><i>_</i><b>concurrency</b><i>_</i><b>limit</b>  parameter.   The limit is
               enforced by the Postfix queue manager.
 
        <i>transport_</i><b>destination</b><i>_</i><b>recipient</b><i>_</i><b>limit</b>
-              Limit  the  number of recipients per message deliv-
-              ery, for delivery  via  the  named  <i>transport</i>.  The
-              default  limit  is  taken from the <b>default</b><i>_</i><b>destina-</b>
-              <b>tion</b><i>_</i><b>recipient</b><i>_</i><b>limit</b>  parameter.   The   limit   is
+              Limit the number of recipients per  message  deliv-
+              ery,  for  delivery  via  the  named <i>transport</i>. The
+              default limit is taken  from  the  <b>default</b><i>_</i><b>destina-</b>
+              <b>tion</b><i>_</i><b>recipient</b><i>_</i><b>limit</b>   parameter.    The  limit  is
               enforced by the Postfix queue manager.
 
        <i>transport_</i><b>time</b><i>_</i><b>limit</b>
-              Limit  the  time  for delivery to external command,
-              for delivery via the named <b>transport</b>.  The  default
-              limit  is taken from the <b>command</b><i>_</i><b>time</b><i>_</i><b>limit</b> parame-
-              ter.  The limit is enforced by  the  Postfix  queue
-              manager.
-
+              Limit the time for delivery  to  external  command,
+              for  delivery  via the named <b>transport</b>. The default
+              limit is taken from the <b>command</b><i>_</i><b>time</b><i>_</i><b>limit</b>  parame-
+              ter.   The  limit  is enforced by the Postfix queue
 
 
 
@@ -203,6 +203,8 @@ PIPE(8)                                                   PIPE(8)
 PIPE(8)                                                   PIPE(8)
 
 
+              manager.
+
 <b>SEE</b> <b>ALSO</b>
        <a href="bounce.8.html">bounce(8)</a> non-delivery status reports
        <a href="master.8.html">master(8)</a> process manager
@@ -210,7 +212,7 @@ PIPE(8)                                                   PIPE(8)
        syslogd(8) system logging
 
 <b>LICENSE</b>
-       The  Secure  Mailer  license must be distributed with this
+       The Secure Mailer license must be  distributed  with  this
        software.
 
 <b>AUTHOR(S)</b>
@@ -255,8 +257,6 @@ PIPE(8)                                                   PIPE(8)
 
 
 
-
-
 
 
 
index 46c25fe2389c601ab0edf58183b3db13dd98954d..83c3aef76408280dabc1e51d028e31b026680788 100644 (file)
@@ -144,15 +144,19 @@ SMTP(8)                                                   SMTP(8)
               Do  not  wait for the server response after sending
               QUIT.
 
+       <b>smtp</b><i>_</i><b>bind</b><i>_</i><b>address</b>
+              Numerical network address to bind to when making  a
+              connection.
+
 <b>Authentication</b> <b>controls</b>
        <b>smtp</b><i>_</i><b>enable</b><i>_</i><b>sasl</b><i>_</i><b>auth</b>
-              Enable per-session authentication as per  <a href="http://www.faqs.org/rfcs/rfc2554.html">RFC  2554</a>
-              (SASL).   By default, Postfix is built without SASL
+              Enable  per-session  authentication as per <a href="http://www.faqs.org/rfcs/rfc2554.html">RFC 2554</a>
+              (SASL).  By default, Postfix is built without  SASL
               support.
 
        <b>smtp</b><i>_</i><b>sasl</b><i>_</i><b>password</b><i>_</i><b>maps</b>
-              Lookup tables with per-host <i>name</i>:<i>password</i>  entries.
-              No  entry  for a host means no attempt to authenti-
+              Lookup  tables with per-host <i>name</i>:<i>password</i> entries.
+              No entry for a host means no attempt  to  authenti-
               cate.
 
        <b>smtp</b><i>_</i><b>sasl</b><i>_</i><b>security</b><i>_</i><b>options</b>
@@ -176,21 +180,17 @@ SMTP(8)                                                   SMTP(8)
 <b>Resource</b> <b>controls</b>
        <b>smtp</b><i>_</i><b>destination</b><i>_</i><b>concurrency</b><i>_</i><b>limit</b>
               Limit the number of parallel deliveries to the same
-              destination.   The  default limit is taken from the
+              destination.  The default limit is taken  from  the
               <b>default</b><i>_</i><b>destination</b><i>_</i><b>concurrency</b><i>_</i><b>limit</b> parameter.
 
        <b>smtp</b><i>_</i><b>destination</b><i>_</i><b>recipient</b><i>_</i><b>limit</b>
-              Limit the number of recipients per  message  deliv-
-              ery.    The   default   limit  is  taken  from  the
+              Limit  the  number of recipients per message deliv-
+              ery.   The  default  limit  is   taken   from   the
               <b>default</b><i>_</i><b>destination</b><i>_</i><b>recipient</b><i>_</i><b>limit</b> parameter.
 
 <b>Timeout</b> <b>controls</b>
        <b>smtp</b><i>_</i><b>connect</b><i>_</i><b>timeout</b>
               Timeout in seconds for completing a TCP connection.
-              When no connection can be made within the deadline,
-              the SMTP client tries the next address on the  mail
-              exchanger list.
-
 
 
 
@@ -203,20 +203,24 @@ SMTP(8)                                                   SMTP(8)
 SMTP(8)                                                   SMTP(8)
 
 
+              When no connection can be made within the deadline,
+              the  SMTP client tries the next address on the mail
+              exchanger list.
+
        <b>smtp</b><i>_</i><b>helo</b><i>_</i><b>timeout</b>
-              Timeout  in seconds for receiving the SMTP greeting
+              Timeout in seconds for receiving the SMTP  greeting
               banner.  When the server drops the connection with-
-              out  sending a greeting banner, or when it sends no
+              out sending a greeting banner, or when it sends  no
               greeting  banner  within  the  deadline,  the  SMTP
               client tries the next address on the mail exchanger
               list.
 
        <b>smtp</b><i>_</i><b>helo</b><i>_</i><b>timeout</b>
-              Timeout in seconds for sending  the  <b>HELO</b>  command,
+              Timeout  in  seconds  for sending the <b>HELO</b> command,
               and for receiving the server response.
 
        <b>smtp</b><i>_</i><b>mail</b><i>_</i><b>timeout</b>
-              Timeout  in  seconds for sending the <b>MAIL</b> <b>FROM</b> com-
+              Timeout in seconds for sending the <b>MAIL</b>  <b>FROM</b>  com-
               mand, and for receiving the server response.
 
        <b>smtp</b><i>_</i><b>rcpt</b><i>_</i><b>timeout</b>
@@ -224,7 +228,7 @@ SMTP(8)                                                   SMTP(8)
               and for receiving the server response.
 
        <b>smtp</b><i>_</i><b>data</b><i>_</i><b>init</b><i>_</i><b>timeout</b>
-              Timeout  in  seconds  for sending the <b>DATA</b> command,
+              Timeout in seconds for sending  the  <b>DATA</b>  command,
               and for receiving the server response.
 
        <b>smtp</b><i>_</i><b>data</b><i>_</i><b>xfer</b><i>_</i><b>timeout</b>
@@ -233,11 +237,11 @@ SMTP(8)                                                   SMTP(8)
        <b>smtp</b><i>_</i><b>data</b><i>_</i><b>done</b><i>_</i><b>timeout</b>
               Timeout in seconds for sending the "<b>.</b>" command, and
               for receiving the server response. When no response
-              is  received, a warning is logged that the mail may
+              is received, a warning is logged that the mail  may
               be delivered multiple times.
 
        <b>smtp</b><i>_</i><b>quit</b><i>_</i><b>timeout</b>
-              Timeout in seconds for sending  the  <b>QUIT</b>  command,
+              Timeout  in  seconds  for sending the <b>QUIT</b> command,
               and for receiving the server response.
 
 <b>SEE</b> <b>ALSO</b>
@@ -247,12 +251,24 @@ SMTP(8)                                                   SMTP(8)
        syslogd(8) system logging
 
 <b>LICENSE</b>
-       The  Secure  Mailer  license must be distributed with this
+       The Secure Mailer license must be  distributed  with  this
        software.
 
 <b>AUTHOR(S)</b>
        Wietse Venema
        IBM T.J. Watson Research
+
+
+
+                                                                4
+
+
+
+
+
+SMTP(8)                                                   SMTP(8)
+
+
        P.O. Box 704
        Yorktown Heights, NY 10598, USA
 
@@ -260,7 +276,57 @@ SMTP(8)                                                   SMTP(8)
 
 
 
-                                                                4
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+                                                                5
 
 
 </pre> </body> </html>
index ca9e128774a94e8065e7a6b82662b688a22cf5ac..7f2884018a9095ef8d5cc541aa7c1e40656beece 100644 (file)
@@ -56,7 +56,7 @@ depend: $(MAKES)
            $(CC) -E $(DEFS) $(INCL) $$i | sed -n -e '/^# *1 *"\([^"]*\)".*/{' \
            -e 's//'`echo $$i|sed 's/c$$/o/'`': \1/' -e 'p' -e '}'; \
        done) | grep -v '[.][o][:][ ][/]' >$$$$ && mv $$$$ Makefile.in
-       @make -f Makefile.in Makefile
+       @$(EXPORT) make -f Makefile.in Makefile 1>&2
 
 # do not edit below this line - it is generated by 'make depend'
 lmtp.o: lmtp.c
diff --git a/postfix/lmtp/README.local b/postfix/lmtp/README.local
deleted file mode 100644 (file)
index a6286ec..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-README.local
-
-This file describes how to use the lmtp service for local delivery.
-You'll need postfix-19991231-pl04 or later for this to work because
-it relies on the "spawn" service.
-
-Configure your Postfix as follows:
-
-/etc/postfix/master.cf:
-
-#local    unix  -       n       n       -       -       local
-local     unix  -       -       n       -       -       lmtp
-    serv=unix:private/lmtpd
-lmtpd     unix  -       n       n       -       -       spawn
-    user=cyrus:cyrus argv=/usr/local/cyrus/bin/deliver -e -l
-
-
-First, we comment out the original "local" service and define
-a new one based on the "lmtp" client.  The "serv=" argument says
-what LMTP server we're to talk to, in this case the "lmtpd"
-service.
-
-The `-l' option to deliver tells it to go into LMTP mode, and the
-`-e' tells it to use the duplicate delivery database, which is
-required in order to use the vacation features of Sieve, the
-filtering language in Cyrus 1.6.X.
-
-A note about spawn, this is a new experimental service.  The
-makefile-patch included with this bundle will add spawn to the
-compile targets.  However, you may need to check that it actually
-gets installed.
-
-A note about local delivery and the number of recipients.  Starting
-with postfix-19991231-pl04, it is now possible to specify the
-maximum number of recipients per message for local delivery.  By 
-default, this is set to 1 as follows:
-
-   local_destination_recipient_limit = 1
-
-You can set it to zero (means no limit) or, safer, set it to some
-reasonable number so that your machine doesn't risk running out of
-resources on a message with an inordinate number of recipients.
-
-Why is this of interest?  Well, if a message contains multiple
-recipients, and all these recipients happen to be on the same Cyrus
-partition, then recent (1.6.X) releases of deliver will hard link
-the message to each recipient instead of each recipient getting a
-copy.  So you'll probably want to set the above mail.cf value to
-something reasonable to take advantage of this feature in Cyrus.
-
diff --git a/postfix/lmtp/fixnames b/postfix/lmtp/fixnames
deleted file mode 100644 (file)
index c5e121a..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-# script to compare common code between smtp and lmtp
-
-sed '
-       s/SMTP/LMTP/g
-       s/smtp/lmtp/g
-' $*
index b8a1475591a27ed54053628014ed12987540ea19..485c976dd96154116e8d51275d506127874cb6ca 100644 (file)
@@ -381,6 +381,12 @@ static void lmtp_service(VSTREAM *client_stream, char *unused_service, char **ar
     DELIVER_REQUEST *request;
     int     status;
 
+    /*
+     * Sanity check. This service takes no command-line arguments.
+     */
+    if (argv[0])
+       msg_fatal("unexpected command-line argument: %s", argv[0]);
+
     /*
      * This routine runs whenever a client connects to the UNIX-domain socket
      * dedicated to remote LMTP delivery service. What we see below is a
index f9f77422d99afc4acd86c387ea393ccea07a4fbf..9676e8210fbb669fb0928c66d1cadab788615842 100644 (file)
@@ -59,8 +59,9 @@ corresponding group ID is used instead of the group ID of
 \fIusername\fR.
 .IP "\fBeol=string\fR (default: \fB\en\fR)"
 The output record delimiter. Typically one would use either
-\fB\er\en\fR or \fB\en\fR. You can specify the usual C-style
-backslash escape sequences.
+\fB\er\en\fR or \fB\en\fR. The usual C-style backslash escape
+sequences are recognized: \fB\ea \eb \ef \en \er \et \ev
+\e\fIoctal\fR and \fB\e\e\fR.
 .IP "\fBargv\fR=\fIcommand\fR... (required)"
 The command to be executed. This must be specified as the
 last command attribute.
index b69e90b5c494708d4fc8f4555ff31c799641caf7..c1177d3bb71e2d16f76ea55fbfa9bf4734bb4a28 100644 (file)
@@ -110,6 +110,8 @@ Skip servers that greet us with a 4xx status code.
 Skip servers that greet us with a 5xx status code.
 .IP \fBsmtp_skip_quit_response\fR
 Do not wait for the server response after sending QUIT.
+.IP \fBsmtp_bind_address\fR
+Numerical network address to bind to when making a connection.
 .SH "Authentication controls"
 .IP \fBsmtp_enable_sasl_auth\fR
 Enable per-session authentication as per RFC 2554 (SASL).
index 7f12ae301a7086d31a6a0813677b5b7e1f5eee85..3f19860248678dbeea65deed8a63bc85562cb60d 100644 (file)
@@ -395,42 +395,7 @@ NORETURN multi_server_main(int argc, char **argv, MULTI_SERVER_FN service,...)
      * Initialize from the configuration file. Allow command-line options to
      * override compiled-in defaults or configured parameter values.
      */
-    mail_conf_read();
-    va_start(ap, service);
-    while ((key = va_arg(ap, int)) != 0) {
-       switch (key) {
-       case MAIL_SERVER_INT_TABLE:
-           get_mail_conf_int_table(va_arg(ap, CONFIG_INT_TABLE *));
-           break;
-       case MAIL_SERVER_STR_TABLE:
-           get_mail_conf_str_table(va_arg(ap, CONFIG_STR_TABLE *));
-           break;
-       case MAIL_SERVER_BOOL_TABLE:
-           get_mail_conf_bool_table(va_arg(ap, CONFIG_BOOL_TABLE *));
-           break;
-       case MAIL_SERVER_RAW_TABLE:
-           get_mail_conf_raw_table(va_arg(ap, CONFIG_STR_TABLE *));
-           break;
-       case MAIL_SERVER_PRE_INIT:
-           pre_init = va_arg(ap, MAIL_SERVER_INIT_FN);
-           break;
-       case MAIL_SERVER_POST_INIT:
-           post_init = va_arg(ap, MAIL_SERVER_INIT_FN);
-           break;
-       case MAIL_SERVER_LOOP:
-           loop = va_arg(ap, MAIL_SERVER_LOOP_FN);
-           break;
-       case MAIL_SERVER_EXIT:
-           multi_server_onexit = va_arg(ap, MAIL_SERVER_EXIT_FN);
-           break;
-       case MAIL_SERVER_PRE_ACCEPT:
-           multi_server_pre_accept = va_arg(ap, MAIL_SERVER_ACCEPT_FN);
-           break;
-       default:
-           msg_panic("%s: unknown argument type: %d", myname, key);
-       }
-    }
-    va_end(ap);
+    mail_conf_suck();
 
     /*
      * Pick up policy settings from master process. Shut up error messages to
@@ -440,29 +405,27 @@ NORETURN multi_server_main(int argc, char **argv, MULTI_SERVER_FN service,...)
     while ((c = GETOPT(argc, argv, "cDi:lm:n:o:s:St:uv")) > 0) {
        switch (c) {
        case 'c':
-           root_dir = var_queue_dir;
+           root_dir = "setme";
            break;
        case 'D':
            debug_me = 1;
            break;
        case 'i':
-           if ((var_idle_limit = atoi(optarg)) <= 0)
-               msg_fatal("invalid max_idle time: %s", optarg);
+           mail_conf_update(VAR_MAX_IDLE, optarg);
            break;
        case 'l':
            alone = 1;
            break;
        case 'm':
-           if ((var_use_limit = atoi(optarg)) <= 0)
-               msg_fatal("invalid max_use: %s", optarg);
+           mail_conf_update(VAR_MAX_USE, optarg);
            break;
        case 'n':
            service_name = optarg;
            break;
        case 'o':
-           mail_conf_update(optarg,
-                            (oval = split_at(optarg, '=')) ? oval : "");
-           mail_params_init();                 /* XXX */
+           if ((oval = split_at(optarg, '=')) == 0)
+               oval = "";
+           mail_conf_update(optarg, oval);
            break;
        case 's':
            if ((socket_count = atoi(optarg)) <= 0)
@@ -472,7 +435,7 @@ NORETURN multi_server_main(int argc, char **argv, MULTI_SERVER_FN service,...)
            stream = VSTREAM_IN;
            break;
        case 'u':
-           user_name = var_mail_owner;
+           user_name = "setme";
            break;
        case 't':
            transport = optarg;
@@ -486,6 +449,55 @@ NORETURN multi_server_main(int argc, char **argv, MULTI_SERVER_FN service,...)
        }
     }
 
+    /*
+     * Initialize generic parameters.
+     */
+    mail_params_init();
+
+    /*
+     * Application-specific initialization.
+     */
+    va_start(ap, service);
+    while ((key = va_arg(ap, int)) != 0) {
+       switch (key) {
+       case MAIL_SERVER_INT_TABLE:
+           get_mail_conf_int_table(va_arg(ap, CONFIG_INT_TABLE *));
+           break;
+       case MAIL_SERVER_STR_TABLE:
+           get_mail_conf_str_table(va_arg(ap, CONFIG_STR_TABLE *));
+           break;
+       case MAIL_SERVER_BOOL_TABLE:
+           get_mail_conf_bool_table(va_arg(ap, CONFIG_BOOL_TABLE *));
+           break;
+       case MAIL_SERVER_RAW_TABLE:
+           get_mail_conf_raw_table(va_arg(ap, CONFIG_STR_TABLE *));
+           break;
+       case MAIL_SERVER_PRE_INIT:
+           pre_init = va_arg(ap, MAIL_SERVER_INIT_FN);
+           break;
+       case MAIL_SERVER_POST_INIT:
+           post_init = va_arg(ap, MAIL_SERVER_INIT_FN);
+           break;
+       case MAIL_SERVER_LOOP:
+           loop = va_arg(ap, MAIL_SERVER_LOOP_FN);
+           break;
+       case MAIL_SERVER_EXIT:
+           multi_server_onexit = va_arg(ap, MAIL_SERVER_EXIT_FN);
+           break;
+       case MAIL_SERVER_PRE_ACCEPT:
+           multi_server_pre_accept = va_arg(ap, MAIL_SERVER_ACCEPT_FN);
+           break;
+       default:
+           msg_panic("%s: unknown argument type: %d", myname, key);
+       }
+    }
+    va_end(ap);
+
+    if (root_dir)
+       root_dir = var_queue_dir;
+    if (user_name)
+       user_name = var_mail_owner;
+
     /*
      * If not connected to stdin, stdin must not be a terminal.
      */
index fc39204a9cb9bf578470cc5e3f7ecea003dcf8f5..ca927a605d079abaabd5027e5476bb2f6adf6cbc 100644 (file)
@@ -367,42 +367,7 @@ NORETURN single_server_main(int argc, char **argv, SINGLE_SERVER_FN service,...)
      * Initialize from the configuration file. Allow command-line options to
      * override compiled-in defaults or configured parameter values.
      */
-    mail_conf_read();
-    va_start(ap, service);
-    while ((key = va_arg(ap, int)) != 0) {
-       switch (key) {
-       case MAIL_SERVER_INT_TABLE:
-           get_mail_conf_int_table(va_arg(ap, CONFIG_INT_TABLE *));
-           break;
-       case MAIL_SERVER_STR_TABLE:
-           get_mail_conf_str_table(va_arg(ap, CONFIG_STR_TABLE *));
-           break;
-       case MAIL_SERVER_BOOL_TABLE:
-           get_mail_conf_bool_table(va_arg(ap, CONFIG_BOOL_TABLE *));
-           break;
-       case MAIL_SERVER_RAW_TABLE:
-           get_mail_conf_raw_table(va_arg(ap, CONFIG_STR_TABLE *));
-           break;
-       case MAIL_SERVER_PRE_INIT:
-           pre_init = va_arg(ap, MAIL_SERVER_INIT_FN);
-           break;
-       case MAIL_SERVER_POST_INIT:
-           post_init = va_arg(ap, MAIL_SERVER_INIT_FN);
-           break;
-       case MAIL_SERVER_LOOP:
-           loop = va_arg(ap, MAIL_SERVER_LOOP_FN);
-           break;
-       case MAIL_SERVER_EXIT:
-           single_server_onexit = va_arg(ap, MAIL_SERVER_EXIT_FN);
-           break;
-       case MAIL_SERVER_PRE_ACCEPT:
-           single_server_pre_accept = va_arg(ap, MAIL_SERVER_ACCEPT_FN);
-           break;
-       default:
-           msg_panic("%s: unknown argument type: %d", myname, key);
-       }
-    }
-    va_end(ap);
+    mail_conf_suck();
 
     /*
      * Pick up policy settings from master process. Shut up error messages to
@@ -412,29 +377,27 @@ NORETURN single_server_main(int argc, char **argv, SINGLE_SERVER_FN service,...)
     while ((c = GETOPT(argc, argv, "cDi:lm:n:o:s:St:uv")) > 0) {
        switch (c) {
        case 'c':
-           root_dir = var_queue_dir;
+           root_dir = "setme";
            break;
        case 'D':
            debug_me = 1;
            break;
        case 'i':
-           if ((var_idle_limit = atoi(optarg)) <= 0)
-               msg_fatal("invalid max_idle time: %s", optarg);
+           mail_conf_update(VAR_MAX_IDLE, optarg);
            break;
        case 'l':
            alone = 1;
            break;
        case 'm':
-           if ((var_use_limit = atoi(optarg)) <= 0)
-               msg_fatal("invalid max_use: %s", optarg);
+           mail_conf_update(VAR_MAX_USE, optarg);
            break;
        case 'n':
            service_name = optarg;
            break;
        case 'o':
-           mail_conf_update(optarg,
-                            (oval = split_at(optarg, '=')) ? oval : "");
-           mail_params_init();                 /* XXX */
+           if ((oval = split_at(optarg, '=')) == 0)
+               oval = "";
+           mail_conf_update(optarg, oval);
            break;
        case 's':
            if ((socket_count = atoi(optarg)) <= 0)
@@ -444,7 +407,7 @@ NORETURN single_server_main(int argc, char **argv, SINGLE_SERVER_FN service,...)
            stream = VSTREAM_IN;
            break;
        case 'u':
-           user_name = var_mail_owner;
+           user_name = "setme";
            break;
        case 't':
            transport = optarg;
@@ -458,6 +421,55 @@ NORETURN single_server_main(int argc, char **argv, SINGLE_SERVER_FN service,...)
        }
     }
 
+    /*
+     * Initialize generic parameters.
+     */
+    mail_params_init();
+
+    /*
+     * Application-specific initialization.
+     */
+    va_start(ap, service);
+    while ((key = va_arg(ap, int)) != 0) {
+       switch (key) {
+       case MAIL_SERVER_INT_TABLE:
+           get_mail_conf_int_table(va_arg(ap, CONFIG_INT_TABLE *));
+           break;
+       case MAIL_SERVER_STR_TABLE:
+           get_mail_conf_str_table(va_arg(ap, CONFIG_STR_TABLE *));
+           break;
+       case MAIL_SERVER_BOOL_TABLE:
+           get_mail_conf_bool_table(va_arg(ap, CONFIG_BOOL_TABLE *));
+           break;
+       case MAIL_SERVER_RAW_TABLE:
+           get_mail_conf_raw_table(va_arg(ap, CONFIG_STR_TABLE *));
+           break;
+       case MAIL_SERVER_PRE_INIT:
+           pre_init = va_arg(ap, MAIL_SERVER_INIT_FN);
+           break;
+       case MAIL_SERVER_POST_INIT:
+           post_init = va_arg(ap, MAIL_SERVER_INIT_FN);
+           break;
+       case MAIL_SERVER_LOOP:
+           loop = va_arg(ap, MAIL_SERVER_LOOP_FN);
+           break;
+       case MAIL_SERVER_EXIT:
+           single_server_onexit = va_arg(ap, MAIL_SERVER_EXIT_FN);
+           break;
+       case MAIL_SERVER_PRE_ACCEPT:
+           single_server_pre_accept = va_arg(ap, MAIL_SERVER_ACCEPT_FN);
+           break;
+       default:
+           msg_panic("%s: unknown argument type: %d", myname, key);
+       }
+    }
+    va_end(ap);
+
+    if (root_dir)
+       root_dir = var_queue_dir;
+    if (user_name)
+       user_name = var_mail_owner;
+
     /*
      * If not connected to stdin, stdin must not be a terminal.
      */
index 3a1b9d89b0fec819dd0f52a74aacde1d61eb81e7..98603d18cfccb8f7ef9f99a17b4bef2139c815c1 100644 (file)
@@ -267,7 +267,6 @@ static void trigger_server_accept_local(int unused_event, char *context)
     int     time_left = 0;
     int     fd;
 
-
     if (msg_verbose)
        msg_info("%s: trigger arrived", myname);
 
@@ -368,42 +367,7 @@ NORETURN trigger_server_main(int argc, char **argv, TRIGGER_SERVER_FN service,..
      * Initialize from the configuration file. Allow command-line options to
      * override compiled-in defaults or configured parameter values.
      */
-    mail_conf_read();
-    va_start(ap, service);
-    while ((key = va_arg(ap, int)) != 0) {
-       switch (key) {
-       case MAIL_SERVER_INT_TABLE:
-           get_mail_conf_int_table(va_arg(ap, CONFIG_INT_TABLE *));
-           break;
-       case MAIL_SERVER_STR_TABLE:
-           get_mail_conf_str_table(va_arg(ap, CONFIG_STR_TABLE *));
-           break;
-       case MAIL_SERVER_BOOL_TABLE:
-           get_mail_conf_bool_table(va_arg(ap, CONFIG_BOOL_TABLE *));
-           break;
-       case MAIL_SERVER_RAW_TABLE:
-           get_mail_conf_raw_table(va_arg(ap, CONFIG_STR_TABLE *));
-           break;
-       case MAIL_SERVER_PRE_INIT:
-           pre_init = va_arg(ap, MAIL_SERVER_INIT_FN);
-           break;
-       case MAIL_SERVER_POST_INIT:
-           post_init = va_arg(ap, MAIL_SERVER_INIT_FN);
-           break;
-       case MAIL_SERVER_LOOP:
-           loop = va_arg(ap, MAIL_SERVER_LOOP_FN);
-           break;
-       case MAIL_SERVER_EXIT:
-           trigger_server_onexit = va_arg(ap, MAIL_SERVER_EXIT_FN);
-           break;
-       case MAIL_SERVER_PRE_ACCEPT:
-           trigger_server_pre_accept = va_arg(ap, MAIL_SERVER_ACCEPT_FN);
-           break;
-       default:
-           msg_panic("%s: unknown argument type: %d", myname, key);
-       }
-    }
-    va_end(ap);
+    mail_conf_suck();
 
     /*
      * Pick up policy settings from master process. Shut up error messages to
@@ -413,29 +377,27 @@ NORETURN trigger_server_main(int argc, char **argv, TRIGGER_SERVER_FN service,..
     while ((c = GETOPT(argc, argv, "cDi:lm:n:o:s:St:uv")) > 0) {
        switch (c) {
        case 'c':
-           root_dir = var_queue_dir;
+           root_dir = "setme";
            break;
        case 'D':
            debug_me = 1;
            break;
        case 'i':
-           if ((var_idle_limit = atoi(optarg)) <= 0)
-               msg_fatal("invalid max_idle time: %s", optarg);
+           mail_conf_update(VAR_MAX_IDLE, optarg);
            break;
        case 'l':
            alone = 1;
            break;
        case 'm':
-           if ((var_use_limit = atoi(optarg)) <= 0)
-               msg_fatal("invalid max_use: %s", optarg);
+           mail_conf_update(VAR_MAX_USE, optarg);
            break;
        case 'n':
            service_name = optarg;
            break;
        case 'o':
-           mail_conf_update(optarg,
-                            (oval = split_at(optarg, '=')) ? oval : "");
-           mail_params_init();                 /* XXX */
+           if ((oval = split_at(optarg, '=')) == 0)
+               oval = "";
+           mail_conf_update(optarg, oval);
            break;
        case 's':
            if ((socket_count = atoi(optarg)) <= 0)
@@ -448,7 +410,7 @@ NORETURN trigger_server_main(int argc, char **argv, TRIGGER_SERVER_FN service,..
            transport = optarg;
            break;
        case 'u':
-           user_name = var_mail_owner;
+           user_name = "setme";
            break;
        case 'v':
            msg_verbose++;
@@ -459,6 +421,55 @@ NORETURN trigger_server_main(int argc, char **argv, TRIGGER_SERVER_FN service,..
        }
     }
 
+    /*
+     * Initialize generic parameters.
+     */
+    mail_params_init();
+
+    /*
+     * Application-specific initialization.
+     */
+    va_start(ap, service);
+    while ((key = va_arg(ap, int)) != 0) {
+       switch (key) {
+       case MAIL_SERVER_INT_TABLE:
+           get_mail_conf_int_table(va_arg(ap, CONFIG_INT_TABLE *));
+           break;
+       case MAIL_SERVER_STR_TABLE:
+           get_mail_conf_str_table(va_arg(ap, CONFIG_STR_TABLE *));
+           break;
+       case MAIL_SERVER_BOOL_TABLE:
+           get_mail_conf_bool_table(va_arg(ap, CONFIG_BOOL_TABLE *));
+           break;
+       case MAIL_SERVER_RAW_TABLE:
+           get_mail_conf_raw_table(va_arg(ap, CONFIG_STR_TABLE *));
+           break;
+       case MAIL_SERVER_PRE_INIT:
+           pre_init = va_arg(ap, MAIL_SERVER_INIT_FN);
+           break;
+       case MAIL_SERVER_POST_INIT:
+           post_init = va_arg(ap, MAIL_SERVER_INIT_FN);
+           break;
+       case MAIL_SERVER_LOOP:
+           loop = va_arg(ap, MAIL_SERVER_LOOP_FN);
+           break;
+       case MAIL_SERVER_EXIT:
+           trigger_server_onexit = va_arg(ap, MAIL_SERVER_EXIT_FN);
+           break;
+       case MAIL_SERVER_PRE_ACCEPT:
+           trigger_server_pre_accept = va_arg(ap, MAIL_SERVER_ACCEPT_FN);
+           break;
+       default:
+           msg_panic("%s: unknown argument type: %d", myname, key);
+       }
+    }
+    va_end(ap);
+
+    if (root_dir)
+       root_dir = var_queue_dir;
+    if (user_name)
+       user_name = var_mail_owner;
+
     /*
      * If not connected to stdin, stdin must not be a terminal.
      */
index a1127d36eb60075c4a5189afdd19a6f64279d587..9102d4275b269e96a29a129986dc43e939e403eb 100644 (file)
@@ -51,8 +51,9 @@
 /*     \fIusername\fR.
 /* .IP "\fBeol=string\fR (default: \fB\en\fR)"
 /*     The output record delimiter. Typically one would use either
-/*     \fB\er\en\fR or \fB\en\fR. You can specify the usual C-style
-/*     backslash escape sequences.
+/*     \fB\er\en\fR or \fB\en\fR. The usual C-style backslash escape
+/*     sequences are recognized: \fB\ea \eb \ef \en \er \et \ev
+/*     \e\fIoctal\fR and \fB\e\e\fR.
 /* .IP "\fBargv\fR=\fIcommand\fR... (required)"
 /*     The command to be executed. This must be specified as the
 /*     last command attribute.
@@ -479,7 +480,7 @@ static void get_service_attr(PIPE_ATTR *attr, char **argv)
         * eol=string
         */
        else if (strncasecmp("eol=", *argv, sizeof("eol=") - 1) == 0) {
-           unescape(attr->eol, *argv + sizeof("eol=") -1);
+           unescape(attr->eol, *argv + sizeof("eol=") - 1);
        }
 
        /*
index ac674188a31489cec84779d5c217da7f333524f9..e7cfbb3164cfb520e0ee703b40f7b4abee7e666b 100644 (file)
@@ -94,6 +94,8 @@
 /*     Skip servers that greet us with a 5xx status code.
 /* .IP \fBsmtp_skip_quit_response\fR
 /*     Do not wait for the server response after sending QUIT.
+/* .IP \fBsmtp_bind_address\fR
+/*     Numerical network address to bind to when making a connection.
 /* .SH "Authentication controls"
 /* .IP \fBsmtp_enable_sasl_auth\fR
 /*     Enable per-session authentication as per RFC 2554 (SASL).
@@ -236,6 +238,7 @@ int     var_smtp_always_ehlo;
 char   *var_smtp_sasl_opts;
 char   *var_smtp_sasl_passwd;
 bool    var_smtp_sasl_enable;
+char   *var_smtp_bind_addr;
 
  /*
   * Global variables. smtp_errno is set by the address lookup routines and by
@@ -383,6 +386,7 @@ int     main(int argc, char **argv)
        VAR_ERROR_RCPT, DEF_ERROR_RCPT, &var_error_rcpt, 1, 0,
        VAR_SMTP_SASL_PASSWD, DEF_SMTP_SASL_PASSWD, &var_smtp_sasl_passwd, 0, 0,
        VAR_SMTP_SASL_OPTS, DEF_SMTP_SASL_OPTS, &var_smtp_sasl_opts, 0, 0,
+       VAR_SMTP_BIND_ADDR, DEF_SMTP_BIND_ADDR, &var_smtp_bind_addr, 0, 0,
        0,
     };
     static CONFIG_INT_TABLE int_table[] = {
index c3a22762294e0e1185bad8b2b5429d167c8b9217..6d73cb4bab0d2974e7b93df88eee7f151725fe3b 100644 (file)
 #include <strings.h>
 #endif
 
+#ifndef INADDR_NONE
+#define INADDR_NONE 0xffffff
+#endif
+
 /* Utility library. */
 
 #include <msg.h>
@@ -149,13 +153,26 @@ static SMTP_SESSION *smtp_connect_addr(DNS_RR *addr, unsigned port,
     if ((sock = socket(sin.sin_family, SOCK_STREAM, 0)) < 0)
        msg_fatal("%s: socket: %m", myname);
 
+    /*
+     * Allow the sysadmin to specify the source address, for example, as "-o
+     * smtp_bind_address=x.x.x.x" in the master.cf file.
+     */
+    if (*var_smtp_bind_addr) {
+       sin.sin_addr.s_addr = inet_addr(var_smtp_bind_addr);
+       if (sin.sin_addr.s_addr == INADDR_NONE)
+           msg_fatal("%s: bad %s parameter: %s",
+                     myname, VAR_SMTP_BIND_ADDR, var_smtp_bind_addr);
+       if (bind(sock, (struct sockaddr *) & sin, sizeof(sin)) < 0)
+           msg_warn("%s: bind %s: %m", myname, inet_ntoa(sin.sin_addr));
+       if (msg_verbose)
+           msg_info("%s: bind %s", myname, inet_ntoa(sin.sin_addr));
+    }
+
     /*
      * When running as a virtual host, bind to the virtual interface so that
      * the mail appears to come from the "right" machine address.
      */
-    addr_list = own_inet_addr_list();
-    if (addr_list->used == 1) {
-       sin.sin_port = 0;
+    else if ((addr_list = own_inet_addr_list())->used == 1) {
        memcpy((char *) &sin.sin_addr, addr_list->addrs, sizeof(sin.sin_addr));
        inaddr = ntohl(sin.sin_addr.s_addr);
        if (!IN_CLASSA(inaddr)
index f5841096563480711c2e804c03b59bee9a7fafc5..de1bfaff30345c170b3cd2bd678749f060ab12a4 100644 (file)
@@ -201,7 +201,7 @@ static int smtp_sasl_get_passwd(sasl_conn_t *conn, void *context,
     if ((*psecret = (sasl_secret_t *) malloc(sizeof(sasl_secret_t) + len)) == 0)
        return (SASL_NOMEM);
     (*psecret)->len = len;
-    strcpy((*psecret)->data, state->sasl_passwd);
+    memcpy((*psecret)->data, state->sasl_passwd, len + 1);
 
     return (SASL_OK);
 }
index cea1ab58fd95148bcc205dd20d0a6e9cf7378cb4..9d58c62caa7e9aac545fd3636a36566708e499fd 100644 (file)
@@ -423,7 +423,7 @@ static int ehlo_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
        smtpd_chat_reply(state, "250-SIZE");
     smtpd_chat_reply(state, "250-ETRN");
 #ifdef USE_SASL_AUTH
-    if (var_smtpd_sasl_enable)
+    if (SMTPD_STAND_ALONE(state) == 0 && var_smtpd_sasl_enable)
        smtpd_chat_reply(state, "250-AUTH %s", state->sasl_mechanism_list);
 #endif
     smtpd_chat_reply(state, "250 8BITMIME");
@@ -535,7 +535,8 @@ static char *extract_addr(SMTPD_STATE *state, SMTPD_TOKEN *arg,
     }
 
     /*
-     * Report trouble. Log a warning only if we are going to sleep+reject.
+     * Report trouble. Log a warning only if we are going to sleep+reject so
+     * that attackers can't flood our logfiles.
      */
     if ((naddr < 1 && !allow_empty_addr)
        || naddr > 1
@@ -615,7 +616,9 @@ static int mail_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
            if ((state->msg_size = off_cvt_string(arg + 5)) < 0)
                state->msg_size = 0;
 #ifdef USE_SASL_AUTH
-       } else if (var_smtpd_sasl_enable && strncasecmp(arg, "AUTH=", 5) == 0) {
+       } else if (SMTPD_STAND_ALONE(state) == 0
+                  && var_smtpd_sasl_enable
+                  && strncasecmp(arg, "AUTH=", 5) == 0) {
            if ((err = smtpd_sasl_mail_opt(state, arg + 5)) != 0) {
                smtpd_chat_reply(state, "%s", err);
                return (-1);
@@ -1089,7 +1092,9 @@ static int quit_cmd(SMTPD_STATE *state, int unused_argc, SMTPD_TOKEN *unused_arg
 }
 
  /*
-  * The table of all SMTP commands that we know.
+  * The table of all SMTP commands that we know. Set the junk limit flag on
+  * any command that can be repeated an arbitrary number of times without
+  * triggering a tarpit delay of some sort.
   */
 typedef struct SMTPD_CMD {
     char   *name;
@@ -1100,8 +1105,8 @@ typedef struct SMTPD_CMD {
 #define SMTPD_CMD_FLAG_LIMIT    (1<<0) /* limit usage */
 
 static SMTPD_CMD smtpd_cmd_table[] = {
-    "HELO", helo_cmd, 0,
-    "EHLO", ehlo_cmd, 0,
+    "HELO", helo_cmd, SMTPD_CMD_FLAG_LIMIT,
+    "EHLO", ehlo_cmd, SMTPD_CMD_FLAG_LIMIT,
 
 #ifdef USE_SASL_AUTH
     "AUTH", smtpd_sasl_auth_cmd, 0,
index cd1009b2533cda3809bec056fb858adfd4947477..8c6d437f776d6da4749a37dce0d59e103c5298be 100644 (file)
@@ -147,11 +147,14 @@ void    smtpd_chat_reply(SMTPD_STATE *state, char *format,...)
      * that abort the connection and go into a connect-error-disconnect loop;
      * sleep-on-anything slows down clients that make an excessive number of
      * errors within a session.
+     * 
+     * Flush unsent output before sleeping. Pipelined error responses could
+     * result in client-side timeouts.
      */
     if (state->error_count > var_smtpd_soft_erlim)
-       sleep(state->error_count), vstream_fflush(state->client);
+       vstream_fflush(state->client), sleep(state->error_count);
     else if (STR(state->buffer)[0] == '4' || STR(state->buffer)[0] == '5')
-       sleep(var_smtpd_err_sleep), vstream_fflush(state->client);
+       vstream_fflush(state->client), sleep(var_smtpd_err_sleep);
 
     smtp_fputs(STR(state->buffer), LEN(state->buffer), state->client);
 }
index 46771e3a155fa6eba99a4d366c57888ea5738aa8..6423a51089ea3c0615b9685dbc2d3ef974b46310 100644 (file)
@@ -173,7 +173,7 @@ void    smtpd_sasl_initialize(void)
 
 void    smtpd_sasl_connect(SMTPD_STATE *state)
 {
-    int     sasl_mechanism_count;
+    unsigned sasl_mechanism_count;
     sasl_security_properties_t sec_props;
 
     /*
index 5f80e3ca815200947d7ec972a385aed2f684865b..02ee490a3927fdfbd66ba027b19ded9f7d021307 100644 (file)
@@ -123,7 +123,7 @@ int     smtpd_sasl_auth_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
        smtpd_chat_reply(state, "503 Error: send HELO/EHLO first");
        return (-1);
     }
-    if (!var_smtpd_sasl_enable) {
+    if (SMTPD_STAND_ALONE(state) || !var_smtpd_sasl_enable) {
        state->error_mask |= MAIL_ERROR_PROTOCOL;
        smtpd_chat_reply(state, "503 Error: authentication not enabled");
        return (-1);
index f644f0e18c722496c1574f8c019c40962ffeeca6..e0cf2440cd14770d12d4ba6d49cdc5326aea3a71 100644 (file)
@@ -1,3 +1,4 @@
+
 /*++
 /* NAME
 /*     dict_ldap 3
@@ -39,6 +40,8 @@
 /* .IP \fIldapsource_\fRresult_attribute
 /*     The attribute returned by the search, in which to find
 /*     RFC822 addresses, for example \fImaildrop\fR.
+/* .IP \fIldapsource_\fRscope
+/*     LDAP search scope: sub, base, or one.
 /* .IP \fIldapsource_\fRbind
 /*     Whether or not to bind to the server -- LDAP v3 implementations don't
 /*     require it, which saves some overhead.
 /*     If you must bind to the server, do it with this distinguished name ...
 /* .IP \fIldapsource_\fRbind_pw
 /*     \&... and this password.
-/* BUGS
-/*     Thrice a year, needed or not.
+/* .IP \fIldapsource_\fRcache
+/*     Whether or not to turn on client-side caching.
+/* .IP \fIldapsource_\fRcache_expiry
+/*     If you do cache results, expire them after this many seconds.
+/* .IP \fIldapsource_\fRcache_size
+/*     The cache size in bytes. Does nothing if the cache is off, of course.
+/* .IP \fIldapsource_\fRdereference
+/*     How to handle LDAP aliases. See ldap.h or ldap_open(3) man page.
 /* SEE ALSO
 /*     dict(3) generic dictionary manager
-/* DIAGNOSTICS
-/*     Warnings: unable to connect to server, unable to bind to server.
 /* AUTHOR(S)
 /*     Prabhat K Singh
 /*     VSNL, Bombay, India.
@@ -63,7 +70,7 @@
 /*     Yorktown Heights, NY 10532, USA
 /*
 /*     John Hensley
-/*     stormroll@yahoo.com
+/*     roll@ic.net
 /*
 /*--*/
 
@@ -75,8 +82,6 @@
 
 #include <sys/time.h>
 #include <stdio.h>
-#include <unistd.h>
-#include <string.h>
 #include <signal.h>
 #include <setjmp.h>
 #include <stdlib.h>
 #include "dict.h"
 #include "dict_ldap.h"
 
-/* Global library. */
-
-#include "../global/mail_conf.h"       /* XXX Fixme. */
-
 /*
- * structure containing all the configuration parameters for a given
- * LDAP source, plus its connection handle
+ * Structure containing all the configuration parameters for a given
+ * LDAP source, plus its connection handle.
  */
 typedef struct {
     DICT    dict;                      /* generic member */
     char   *ldapsource;
     char   *server_host;
     int     server_port;
+    int     scope;
     char   *search_base;
     char   *query_filter;
     char   *result_attribute;
@@ -111,12 +113,16 @@ typedef struct {
     char   *bind_dn;
     char   *bind_pw;
     int     timeout;
+    int     cache;
+    long    cache_expiry;
+    long    cache_size;
+    int     dereference;
     LDAP   *ld;
 } DICT_LDAP;
 
- /*
 * LDAP connection timeout support.
 */
+/*
+ * LDAP connection timeout support.
+ */
 static jmp_buf env;
 
 static void dict_ldap_timeout(int unused_sig)
@@ -124,6 +130,103 @@ static void dict_ldap_timeout(int unused_sig)
     longjmp(env, 1);
 }
 
+/* Establish a connection to the LDAP server. */
+static int dict_ldap_connect(DICT_LDAP *dict_ldap)
+{
+    char   *myname = "dict_ldap_connect";
+    void    (*saved_alarm) (int);
+    int     rc = 0;
+
+    dict_errno = 0;
+
+    if (msg_verbose)
+       msg_info("%s: Connecting to server %s", myname,
+                dict_ldap->server_host);
+
+    if ((saved_alarm = signal(SIGALRM, dict_ldap_timeout)) == SIG_ERR) {
+       msg_warn("%s: Error setting signal handler for open timeout: %m",
+                myname);
+       dict_errno = DICT_ERR_RETRY;
+       return (-1);
+    }
+    alarm(dict_ldap->timeout);
+    if (setjmp(env) == 0)
+       dict_ldap->ld = ldap_open(dict_ldap->server_host,
+                                 (int) dict_ldap->server_port);
+    alarm(0);
+
+    if (signal(SIGALRM, saved_alarm) == SIG_ERR) {
+       msg_warn("%s: Error resetting signal handler after open: %m",
+                myname);
+       dict_errno = DICT_ERR_RETRY;
+       return (-1);
+    }
+    if (dict_ldap->ld == NULL) {
+       msg_warn("%s: Unable to connect to LDAP server %s",
+                myname, dict_ldap->server_host);
+       dict_errno = DICT_ERR_RETRY;
+       return (-1);
+    }
+
+    /*
+     * Configure alias dereferencing for this connection. Thanks to Mike
+     * Mattice for this.
+     */
+    dict_ldap->ld->ld_deref = dict_ldap->dereference;
+
+    /*
+     * If this server requires a bind, do so. Thanks to Sam Tardieu for
+     * noticing that the original bind call was broken.
+     */
+    if (dict_ldap->bind) {
+       if (msg_verbose)
+           msg_info("%s: Binding to server %s as dn %s",
+                    myname, dict_ldap->server_host, dict_ldap->bind_dn);
+
+       rc = ldap_bind_s(dict_ldap->ld, dict_ldap->bind_dn,
+                        dict_ldap->bind_pw, LDAP_AUTH_SIMPLE);
+
+       if (rc != LDAP_SUCCESS) {
+           msg_warn("%s: Unable to bind to server %s as %s: %d (%s)",
+                    myname, dict_ldap->server_host, dict_ldap->bind_dn,
+                    rc, ldap_err2string(rc));
+           dict_errno = DICT_ERR_RETRY;
+           return (-1);
+       }
+       if (msg_verbose)
+           msg_info("%s: Successful bind to server %s as %s ",
+                    myname, dict_ldap->server_host, dict_ldap->bind_dn);
+    }
+
+    /*
+     * Set up client-side caching if it's configured.
+     */
+    if (dict_ldap->cache) {
+       if (msg_verbose)
+           msg_info
+               ("%s: Enabling %ld-byte cache for %s with %ld-second expiry",
+                myname, dict_ldap->cache_size, dict_ldap->ldapsource,
+                dict_ldap->cache_expiry);
+
+       rc = ldap_enable_cache(dict_ldap->ld, dict_ldap->cache_expiry,
+                              dict_ldap->cache_size);
+       if (rc != LDAP_SUCCESS) {
+           msg_warn
+               ("%s: Unable to configure cache for %s: %d (%s) -- continuing",
+                myname, dict_ldap->ldapsource, rc, ldap_err2string(rc));
+       } else {
+           if (msg_verbose)
+               msg_info("%s: Caching enabled for %s",
+                        myname, dict_ldap->ldapsource);
+       }
+    }
+    if (msg_verbose)
+       msg_info("%s: Cached connection handle for LDAP source %s",
+                myname, dict_ldap->ldapsource);
+
+    return (0);
+}
+
 /* dict_ldap_lookup - find database entry */
 
 static const char *dict_ldap_lookup(DICT *dict, const char *name)
@@ -136,85 +239,45 @@ static const char *dict_ldap_lookup(DICT *dict, const char *name)
     struct timeval tv;
     VSTRING *escaped_name = 0,
            *filter_buf = 0;
-    char  **attr_values;
+    char   *result_attributes[1],
+          **attr_values;
     long    i = 0;
     int     rc = 0;
-    void    (*saved_alarm) (int);
     char   *sub,
            *end;
 
     dict_errno = 0;
 
     /*
-     * Initialize.
+     * Initialize the result holder.
      */
     if (result == 0)
        result = vstring_alloc(2);
-
     vstring_strcpy(result, "");
 
     if (msg_verbose)
        msg_info("%s: In dict_ldap_lookup", myname);
 
+    /*
+     * Connect to the LDAP server, if necessary.
+     */
     if (dict_ldap->ld == NULL) {
        if (msg_verbose)
-           msg_info("%s: no existing connection for ldapsource %s, reopening",
-                    myname, dict_ldap->ldapsource);
+           msg_info
+               ("%s: No existing connection for ldapsource %s, reopening",
+                myname, dict_ldap->ldapsource);
 
-       if ((saved_alarm = signal(SIGALRM, dict_ldap_timeout)) == SIG_ERR) {
-           msg_warn("%s: error setting signal handler for open timeout: %m", myname);
-           dict_errno = DICT_ERR_RETRY;
-           return (0);
-       }
-       if (msg_verbose)
-           msg_info("%s: connecting to server %s", myname,
-                    dict_ldap->server_host);
+       dict_ldap_connect(dict_ldap);
 
-       alarm(dict_ldap->timeout);
-       if (setjmp(env) == 0)
-           dict_ldap->ld = ldap_open(dict_ldap->server_host,
-                                     (int) dict_ldap->server_port);
-       alarm(0);
-
-       if (signal(SIGALRM, saved_alarm) == SIG_ERR) {
-           msg_warn("%s: error resetting signal handler after open: %m", myname);
-           dict_errno = DICT_ERR_RETRY;
+       /*
+        * if dict_ldap_connect() set dict_errno, abort.
+        */
+       if (dict_errno)
            return (0);
-       }
-       if (msg_verbose)
-           msg_info("%s: after ldap_open", myname);
+    } else if (msg_verbose)
+       msg_info("%s: Using existing connection for ldapsource %s",
+                myname, dict_ldap->ldapsource);
 
-       if (dict_ldap->ld == NULL) {
-           msg_warn("%s: Unable to contact LDAP server %s",
-                    myname, dict_ldap->server_host);
-           dict_errno = DICT_ERR_RETRY;
-           return (0);
-       } else {
-
-           /*
-            * If this server requires a bind, do so.
-            */
-           if (dict_ldap->bind) {
-               if (msg_verbose)
-                   msg_info("%s: about to bind to server %s as dn %s", myname,
-                            dict_ldap->server_host, dict_ldap->bind_dn);
-
-               rc = ldap_bind_s(dict_ldap->ld, dict_ldap->bind_dn,
-                                dict_ldap->bind_pw, LDAP_AUTH_SIMPLE);
-               if (rc != LDAP_SUCCESS) {
-                   msg_warn("%s: Unable to bind to server %s as %s (%d -- %s): ", myname, dict_ldap->server_host, dict_ldap->bind_dn, rc, ldap_err2string(rc));
-                   dict_errno = DICT_ERR_RETRY;
-                   return (0);
-               } else {
-                   if (msg_verbose)
-                       msg_info("%s: Successful bind to server %s as %s (%d -- %s): ", myname, dict_ldap->server_host, dict_ldap->bind_dn, rc, ldap_err2string(rc));
-               }
-           }
-           if (msg_verbose)
-               msg_info("%s: cached connection handle for LDAP source %s",
-                        myname, dict_ldap->ldapsource);
-       }
-    }
 
     /*
      * Prepare the query.
@@ -226,14 +289,17 @@ static const char *dict_ldap_lookup(DICT *dict, const char *name)
 
     /*
      * If any characters in the supplied address should be escaped per RFC
-     * 2254, do so.
+     * 2254, do so. Thanks to Keith Stevenson and Wietse. And thanks to
+     * Samuel Tardieu for spotting that wildcard searches were being done in
+     * the first place, which prompted the ill-conceived lookup_wildcards
+     * parameter and then this more comprehensive mechanism.
      */
-
     end = (char *) name + strlen((char *) name);
     sub = (char *) strpbrk((char *) name, "*()\\\0");
     if (sub && sub != end) {
        if (msg_verbose)
-           msg_info("%s: found character(s) in %s that must be escaped", myname, name);
+           msg_info("%s: Found character(s) in %s that must be escaped",
+                    myname, name);
        for (sub = (char *) name; sub != end; sub++) {
            switch (*sub) {
            case '*':
@@ -256,19 +322,27 @@ static const char *dict_ldap_lookup(DICT *dict, const char *name)
            }
        }
        if (msg_verbose)
-           msg_info("%s: after escaping, it's %s", myname, vstring_str(escaped_name));
+           msg_info("%s: After escaping, it's %s", myname,
+                    vstring_str(escaped_name));
     } else
        vstring_strcpy(escaped_name, (char *) name);
 
-    /* Does the supplied query_filter even include a substitution? */
-    if (strstr(dict_ldap->query_filter, "%s") == NULL) {
-       /* No, log the fact and continue. */
-       msg_warn("%s: fixed query_filter %s is probably useless", myname,
+    /*
+     * Does the supplied query_filter even include a substitution?
+     */
+    if ((char *) strstr(dict_ldap->query_filter, "%s") == NULL) {
+
+       /*
+        * No, log the fact and continue.
+        */
+       msg_warn("%s: Fixed query_filter %s is probably useless", myname,
                 dict_ldap->query_filter);
        vstring_strcpy(filter_buf, dict_ldap->query_filter);
     } else {
 
-       /* Yes, replace all instances of %s with the address to look up. */
+       /*
+        * Yes, replace all instances of %s with the address to look up.
+        */
        sub = dict_ldap->query_filter;
        end = sub + strlen(dict_ldap->query_filter);
        while (sub < end) {
@@ -279,7 +353,9 @@ static const char *dict_ldap_lookup(DICT *dict, const char *name)
             */
            if (*(sub) == '%') {
                if ((sub + 1) != end && *(sub + 1) != 's')
-                   msg_warn("%s: invalid lookup substitution format '%%%c'!", myname, *(sub + 1));
+                   msg_warn
+                       ("%s: Invalid lookup substitution format '%%%c'!",
+                        myname, *(sub + 1));
                vstring_strcat(filter_buf, vstring_str(escaped_name));
                sub++;
            } else
@@ -288,31 +364,46 @@ static const char *dict_ldap_lookup(DICT *dict, const char *name)
        }
     }
 
-    /* On to the search. */
+    /*
+     * On to the search.
+     */
     if (msg_verbose)
-       msg_info("%s: searching with filter %s", myname,
+       msg_info("%s: Searching with filter %s", myname,
                 vstring_str(filter_buf));
 
+    /*
+     * Put result_attribute in an array, so the search can return only that
+     * attribute and not the entire entry.
+     */
+    result_attributes[0] = dict_ldap->result_attribute;
+
     if ((rc = ldap_search_st(dict_ldap->ld, dict_ldap->search_base,
-                            LDAP_SCOPE_SUBTREE,
+                            dict_ldap->scope,
                             vstring_str(filter_buf),
-                            0, 0, &tv, &res)) == LDAP_SUCCESS) {
+                            result_attributes,
+                            0, &tv, &res)) == LDAP_SUCCESS) {
 
        /*
         * Search worked; extract the requested result_attribute.
         */
        if (msg_verbose)
-           msg_info("%s: search found %d matches", myname,
+           msg_info("%s: Search found %d match(es)", myname,
                     ldap_count_entries(dict_ldap->ld, res));
 
-       /* There could have been lots of hits. */
-       for (entry = ldap_first_entry(dict_ldap->ld, res); entry != NULL; entry = ldap_next_entry(dict_ldap->ld, entry)) {
+       /*
+        * There could have been lots of hits.
+        */
+       for (entry = ldap_first_entry(dict_ldap->ld, res); entry != NULL;
+            entry = ldap_next_entry(dict_ldap->ld, entry)) {
 
-           /* And each entry could have multiple attributes. */
+           /*
+            * And each entry could have multiple attributes.
+            */
            attr_values = ldap_get_values(dict_ldap->ld, entry,
                                          dict_ldap->result_attribute);
            if (attr_values == NULL) {
-               msg_warn("%s: entry doesn't have any values for %s", myname, dict_ldap->result_attribute);
+               msg_warn("%s: Entry doesn't have any values for %s",
+                        myname, dict_ldap->result_attribute);
                continue;
            }
 
@@ -326,11 +417,20 @@ static const char *dict_ldap_lookup(DICT *dict, const char *name)
            }
            ldap_value_free(attr_values);
        }
+       if (dict_ldap->ld->ld_errno != LDAP_SUCCESS)
+           msg_warn
+               ("%s: Had some trouble with entries returned by search: %s",
+                myname, ldap_err2string(dict_ldap->ld->ld_errno));
        if (msg_verbose)
-           msg_info("%s: search returned: %s", myname, vstring_str(result));
+           msg_info("%s: Search returned %s", myname,
+                    VSTRING_LEN(result) >
+                    0 ? vstring_str(result) : "nothing");
     } else {
-       /* Rats. That didn't work. */
-       msg_warn("%s: search error %d: %s ", myname, rc,
+
+       /*
+        * Rats. The search didn't work.
+        */
+       msg_warn("%s: Search error %d: %s ", myname, rc,
                 ldap_err2string(rc));
 
        /*
@@ -340,11 +440,15 @@ static const char *dict_ldap_lookup(DICT *dict, const char *name)
        ldap_unbind(dict_ldap->ld);
        dict_ldap->ld = NULL;
 
-       /* And tell the caller to try again later. */
+       /*
+        * And tell the caller to try again later.
+        */
        dict_errno = DICT_ERR_RETRY;
     }
 
-    /* Cleanup. */
+    /*
+     * Cleanup.
+     */
     if (res != 0)
        ldap_msgfree(res);
     if (filter_buf != 0)
@@ -358,7 +462,7 @@ static const char *dict_ldap_lookup(DICT *dict, const char *name)
 static void dict_ldap_update(DICT *dict, const char *unused_name,
                                     const char *unused_value)
 {
-    msg_fatal("dict_ldap_update: operation not implemented");
+    msg_fatal("dict_ldap_update: Operation not implemented");
 }
 
 /* dict_ldap_close - disassociate from data base */
@@ -389,7 +493,7 @@ DICT   *dict_ldap_open(const char *ldapsource, int dummy, int dict_flags)
     DICT_LDAP *dict_ldap;
     VSTRING *config_param;
     int     rc = 0;
-    void    (*saved_alarm) (int);
+    char   *scope;
 
     dict_ldap = (DICT_LDAP *) mymalloc(sizeof(*dict_ldap));
     dict_ldap->dict.lookup = dict_ldap_lookup;
@@ -399,7 +503,7 @@ DICT   *dict_ldap_open(const char *ldapsource, int dummy, int dict_flags)
     dict_ldap->dict.flags = dict_flags | DICT_FLAG_FIXED;
 
     if (msg_verbose)
-       msg_info("%s: using LDAP source %s", myname, ldapsource);
+       msg_info("%s: Using LDAP source %s", myname, ldapsource);
 
     dict_ldap->ldapsource = mystrdup(ldapsource);
 
@@ -424,16 +528,53 @@ DICT   *dict_ldap_open(const char *ldapsource, int dummy, int dict_flags)
        msg_info("%s: %s is %d", myname, vstring_str(config_param),
                 dict_ldap->server_port);
 
+    /*
+     * Scope handling thanks to Carsten Hoeger of SuSE.
+     */
+    vstring_sprintf(config_param, "%s_scope", ldapsource);
+    scope =
+       (char *) get_mail_conf_str(vstring_str(config_param), "sub", 0, 0);
+
+    if (strcasecmp(scope, "one") == 0) {
+       dict_ldap->scope = LDAP_SCOPE_ONELEVEL;
+       if (msg_verbose)
+           msg_info("%s: %s is LDAP_SCOPE_ONELEVEL", myname,
+                    vstring_str(config_param));
+
+    } else if (strcasecmp(scope, "base") == 0) {
+       dict_ldap->scope = LDAP_SCOPE_BASE;
+       if (msg_verbose)
+           msg_info("%s: %s is LDAP_SCOPE_BASE", myname,
+                    vstring_str(config_param));
+
+    } else {
+       dict_ldap->scope = LDAP_SCOPE_SUBTREE;
+       if (msg_verbose)
+           msg_info("%s: %s is LDAP_SCOPE_SUBTREE", myname,
+                    vstring_str(config_param));
+
+    }
+
+    myfree(scope);
+
     vstring_sprintf(config_param, "%s_search_base", ldapsource);
-    dict_ldap->search_base =
-       mystrdup((char *) get_mail_conf_str(vstring_str(config_param), "", 0, 0));
+    dict_ldap->search_base = mystrdup((char *)
+                                     get_mail_conf_str(vstring_str
+                                                       (config_param), "",
+                                                       0, 0));
     if (msg_verbose)
        msg_info("%s: %s is %s", myname, vstring_str(config_param),
                 dict_ldap->search_base);
 
-    /* get configured value of "ldapsource_timeout"; default to 10 */
+    /*
+     * get configured value of "ldapsource_timeout"; default to 10 seconds
+     * 
+     * Thanks to Manuel Guesdon for spotting that this wasn't really getting
+     * set.
+     */
     vstring_sprintf(config_param, "%s_timeout", ldapsource);
-    dict_ldap->timeout = get_mail_conf_int(vstring_str(config_param), 10, 0, 0);
+    dict_ldap->timeout =
+       get_mail_conf_int(vstring_str(config_param), 10, 0, 0);
     if (msg_verbose)
        msg_info("%s: %s is %d", myname, vstring_str(config_param),
                 dict_ldap->timeout);
@@ -441,7 +582,8 @@ DICT   *dict_ldap_open(const char *ldapsource, int dummy, int dict_flags)
     vstring_sprintf(config_param, "%s_query_filter", ldapsource);
     dict_ldap->query_filter =
        mystrdup((char *) get_mail_conf_str(vstring_str(config_param),
-                                     "(mailacceptinggeneralid=%s)", 0, 0));
+                                           "(mailacceptinggeneralid=%s)",
+                                           0, 0));
     if (msg_verbose)
        msg_info("%s: %s is %s", myname, vstring_str(config_param),
                 dict_ldap->query_filter);
@@ -454,87 +596,104 @@ DICT   *dict_ldap_open(const char *ldapsource, int dummy, int dict_flags)
        msg_info("%s: %s is %s", myname, vstring_str(config_param),
                 dict_ldap->result_attribute);
 
-    /* get configured value of "ldapsource_bind"; default to true */
+    /*
+     * get configured value of "ldapsource_bind"; default to true
+     */
     vstring_sprintf(config_param, "%s_bind", ldapsource);
     dict_ldap->bind = get_mail_conf_bool(vstring_str(config_param), 1);
     if (msg_verbose)
        msg_info("%s: %s is %d", myname, vstring_str(config_param),
                 dict_ldap->bind);
 
-    /* get configured value of "ldapsource_bind_dn"; default to "" */
+    /*
+     * get configured value of "ldapsource_bind_dn"; default to ""
+     */
     vstring_sprintf(config_param, "%s_bind_dn", ldapsource);
-    dict_ldap->bind_dn =
-       mystrdup((char *) get_mail_conf_str(vstring_str(config_param), "", 0, 0));
+    dict_ldap->bind_dn = mystrdup((char *)
+                                 get_mail_conf_str(vstring_str
+                                                   (config_param), "", 0,
+                                                   0));
     if (msg_verbose)
        msg_info("%s: %s is %s", myname, vstring_str(config_param),
                 dict_ldap->bind_dn);
 
-    /* get configured value of "ldapsource_bind_pw"; default to "" */
+    /*
+     * get configured value of "ldapsource_bind_pw"; default to ""
+     */
     vstring_sprintf(config_param, "%s_bind_pw", ldapsource);
-    dict_ldap->bind_pw =
-       mystrdup((char *) get_mail_conf_str(vstring_str(config_param), "", 0, 0));
+    dict_ldap->bind_pw = mystrdup((char *)
+                                 get_mail_conf_str(vstring_str
+                                                   (config_param), "", 0,
+                                                   0));
     if (msg_verbose)
        msg_info("%s: %s is %s", myname, vstring_str(config_param),
                 dict_ldap->bind_pw);
 
     /*
-     * establish the connection to the LDAP server
+     * get configured value of "ldapsource_cache"; default to false
      */
+    vstring_sprintf(config_param, "%s_cache", ldapsource);
+    dict_ldap->cache = get_mail_conf_bool(vstring_str(config_param), 0);
+    if (msg_verbose)
+       msg_info("%s: %s is %d", myname, vstring_str(config_param),
+                dict_ldap->cache);
 
+    /*
+     * get configured value of "ldapsource_cache_expiry"; default to 30
+     * seconds
+     */
+    vstring_sprintf(config_param, "%s_cache_expiry", ldapsource);
+    dict_ldap->cache_expiry = get_mail_conf_int(vstring_str(config_param),
+                                               30, 0, 0);
     if (msg_verbose)
-       msg_info("%s: connecting to server %s", myname,
-                dict_ldap->server_host);
+       msg_info("%s: %s is %d", myname, vstring_str(config_param),
+                dict_ldap->cache_expiry);
 
-    if ((saved_alarm = signal(SIGALRM, dict_ldap_timeout)) == SIG_ERR) {
-       msg_warn("%s: error setting signal handler for open timeout: %m", myname);
-       dict_errno = DICT_ERR_RETRY;
-       return (0);
-    }
-    alarm(dict_ldap->timeout);
-    if (setjmp(env) == 0)
-       dict_ldap->ld = ldap_open(dict_ldap->server_host,
-                                 (int) dict_ldap->server_port);
-    alarm(0);
+    /*
+     * get configured value of "ldapsource_cache_size"; default to 32k
+     */
+    vstring_sprintf(config_param, "%s_cache_size", ldapsource);
+    dict_ldap->cache_size = get_mail_conf_int(vstring_str(config_param),
+                                             32768, 0, 0);
+    if (msg_verbose)
+       msg_info("%s: %s is %d", myname, vstring_str(config_param),
+                dict_ldap->cache_size);
 
-    if (signal(SIGALRM, saved_alarm) == SIG_ERR) {
-       msg_warn("%s: error resetting signal handler after open: %m", myname);
-       dict_errno = DICT_ERR_RETRY;
-       return (0);
+    /*
+     * Alias dereferencing suggested by Mike Mattice.
+     */
+    vstring_sprintf(config_param, "%s_dereference", ldapsource);
+    dict_ldap->dereference = get_mail_conf_int(vstring_str(config_param), 0, 0,
+                                              0);
+
+    /*
+     * Make sure only valid options for alias dereferencing are used.
+     */
+    if (dict_ldap->dereference < 0 || dict_ldap->dereference > 3) {
+       msg_warn("%s: Unrecognized value %d specified for %s; using 0",
+                myname, dict_ldap->dereference, vstring_str(config_param));
+       dict_ldap->dereference = 0;
     }
-    if (dict_ldap->ld == NULL) {
-       msg_warn("%s: Unable to contact LDAP server %s",
-                myname, dict_ldap->server_host);
-       dict_errno = DICT_ERR_RETRY;
-       return (0);
-    } else {
+    if (msg_verbose)
+       msg_info("%s: %s is %d", myname, vstring_str(config_param),
+                dict_ldap->dereference);
 
-       if (msg_verbose)
-           msg_info("%s: after ldap_open", myname);
+    dict_ldap_connect(dict_ldap);
 
-       /*
-        * If this server requires a bind, do so.
-        */
-       if (dict_ldap->bind) {
-           if (msg_verbose)
-               msg_info("%s: about to bind to server %s as dn %s", myname,
-                        dict_ldap->server_host, dict_ldap->bind_dn);
-
-           rc = ldap_bind_s(dict_ldap->ld, dict_ldap->bind_dn,
-                            dict_ldap->bind_pw, LDAP_AUTH_SIMPLE);
-           if (rc != LDAP_SUCCESS) {
-               msg_warn("%s: Unable to bind to server %s as %s (%d -- %s): ", myname, dict_ldap->server_host, dict_ldap->bind_dn, rc, ldap_err2string(rc));
-               dict_errno = DICT_ERR_RETRY;
-               return (0);
-           } else {
-               if (msg_verbose)
-                   msg_info("%s: Successful bind to server %s as %s (%d -- %s): ", myname, dict_ldap->server_host, dict_ldap->bind_dn, rc, ldap_err2string(rc));
-           }
-       }
-       if (msg_verbose)
-           msg_info("%s: cached connection handle for LDAP source %s",
-                    myname, dict_ldap->ldapsource);
+    /*
+     * if dict_ldap_connect() set dict_errno, free dict_ldap and abort.
+     */
+    if (dict_errno) {
+       if (dict_ldap->ld)
+           ldap_unbind(dict_ldap->ld);
+
+       myfree((char *) dict_ldap);
+       return (0);
     }
 
+    /*
+     * Otherwise, we're all set. Return the new dict_ldap structure.
+     */
     return (&dict_ldap->dict);
 }
 
index e468bdb7021961111c069f782809836b086100a3..85c56e3117877f0d4fc5ac3500cc5dd8dec3d108 100644 (file)
   * directory. Adding support for a new system type means updating the
   * makedefs script, and adding a section below for the new system.
   */
+#if (defined(__NetBSD_Version__) && __NetBSD_Version__ >= 104250000)
+#define ALIAS_DB_MAP   "hash:/etc/mail/aliases"        /* sendmail 8.10 */
+#endif
+
 #if defined(FREEBSD2) || defined(FREEBSD3) || defined(FREEBSD4) \
     || defined(FREEBSD5) \
     || defined(BSDI2) || defined(BSDI3) || defined(BSDI4) \
@@ -32,7 +36,9 @@
 #define HAS_DB
 #define HAS_SA_LEN
 #define DEF_DB_TYPE    "hash"
+#ifndef ALIAS_DB_MAP
 #define ALIAS_DB_MAP   "hash:/etc/aliases"
+#endif
 #define GETTIMEOFDAY(t)        gettimeofday(t,(struct timezone *) 0)
 #define ROOT_PATH      "/bin:/usr/bin:/sbin:/usr/sbin"
 #define USE_STATFS
index 66d2e2e4f5161fe30fb490e19a0af04581b22648..7229fb504f9f8329603f54736e4bacd4cb8db93b 100644 (file)
 /*     Vertical tab character.
 /* .IP \e\e
 /*     Backslash character.
-/* .IP \enum
+/* .IP \e\fInum\fR
 /*     8-bit character whose ASCII value is the 1..3 digit
 /*     octal number \fInum\fR.
+/* .IP \e\fIother\fR
+/*     The backslash character is discarded.
 /* LICENSE
 /* .ad
 /* .fi
index 9c845a613ed27b0ec8f1325312bc74c270f3795e..96e94c07c51162278619fe2890cec324635e60bb 100644 (file)
@@ -94,9 +94,8 @@
 /*     int     vstream_peek(stream)
 /*     VSTREAM *stream;
 /*
-/*     int     vstream_setjmp(stream, buffer)
+/*     int     vstream_setjmp(stream)
 /*     VSTREAM *stream;
-/*     jmp_buf *buffer;
 /*
 /*     void    longjmp(stream, val)
 /*     VSTREAM *stream;
index a6f5feb9123e750876ae20c1e0be0a21bc8a64fa..65aca4fe1ad3dc548f2ee21fe6f2c802afedfbe1 100644 (file)
@@ -1,4 +1,4 @@
-/*++
+/*
 /* NAME
 /*     vstring 3
 /* SUMMARY
@@ -9,11 +9,6 @@
 /*     VSTRING *vstring_alloc(len)
 /*     int     len;
 /*
-/*     VSTRING *vstring_init(vp, buf, len)
-/*     VSTRING *vp;
-/*     char    *buf;
-/*     int     len;
-/*
 /*     vstring_ctl(vp, type, value, ..., VSTRING_CTL_END)
 /*     VSTRING *vp;
 /*     int     type;
 /*     of at least "len" bytes. The minimal length is 1. The result
 /*     is a null-terminated string of length zero.
 /*
-/*     vstring_init() initializes a fixed-size buffer. Attempts to
-/*     allocate space beyond the buffer end cause the process to
-/*     terminate with a fatal run-time error.
-/*
 /*     vstring_ctl() gives control over memory management policy.
 /*     The function takes a VSTRING pointer and a list of zero
 /*     or more (name,value) pairs. The expected valye type of the
 
 #include <sys_defs.h>
 #include <stddef.h>
-#include <stdlib.h>                    /* 44BSD stdarg.h uses abort() */
+#include <stdlib.h>            /* 44BSD stdarg.h uses abort() */
 #include <stdarg.h>
 #include <string.h>
 
@@ -306,49 +297,6 @@ VSTRING *vstring_alloc(int len)
     return (vp);
 }
 
-/* vstring_fixed_get_ready - vbuf callback for read buffer empty condition */
-
-static int vstring_fixed_get_ready(VBUF *unused_buf)
-{
-    msg_panic("vstring_fixed_get: write-only buffer");
-}
-
-/* vstring_fixed_put_ready - vbuf callback for write buffer full condition */
-
-static int vstring_fixed_put_ready(VBUF *unused_bp)
-{
-    msg_fatal("fixed-size string buffer full");
-}
-
-/* vstring_fixed_space - vbuf callback to reserve space */
-
-static int vstring_fixed_space(VBUF *bp, int len)
-{
-    if (len < 0)
-       msg_panic("vstring_fixed_space: bad length %d", len);
-    if (len - bp->cnt > 0)
-       msg_fatal("fixed-size string buffer full");
-    return (0);
-}
-
-/* vstring_init - initialize fixed-length buffer */
-
-VSTRING *vstring_init(VSTRING *vp, char *buf, int len)
-{
-    if (len < 1)
-       msg_panic("vstring_init: bad length %d", len);
-    vp->vbuf.flags = 0;
-    vp->vbuf.data = (unsigned char *) buf;
-    vp->vbuf.len = len;
-    VSTRING_RESET(vp);
-    vp->vbuf.data[0] = 0;
-    vp->vbuf.get_ready = vstring_fixed_get_ready;
-    vp->vbuf.put_ready = vstring_fixed_put_ready;
-    vp->vbuf.space = vstring_fixed_space;
-    vp->maxlen = 0;
-    return (vp);
-}
-
 /* vstring_free - destroy variable-length string */
 
 VSTRING *vstring_free(VSTRING *vp)
index 4231559a2dcf9746f077c5a5a86d184e578cd21c..c1c9eb966ebdaf68bbe3e06fef9f464daeed2a07 100644 (file)
@@ -31,7 +31,6 @@ typedef struct VSTRING {
 } VSTRING;
 
 extern VSTRING *vstring_alloc(int);
-extern VSTRING *vstring_init(VSTRING *, char *, int);
 extern void vstring_ctl(VSTRING *,...);
 extern VSTRING *vstring_truncate(VSTRING *, int);
 extern VSTRING *vstring_free(VSTRING *);