Configure with m4
The
process of building a sendmail configuration
file begins by creating a file of m4 statements.
Traditionally, the suffix for such files is .mc
.
The cf/cf directory contains examples of many
.mc
files. Of special interest are those that
begin with generic
, for these can serve as
boilerplates in developing your own .mc
files:
generic-bsd4.4.mc generic-mpeix.mc generic-sunos4.1.mc generic-hpux10.mc generic-nextstep3.3.mc generic-ultrix4.mc generic-hpux9.mc generic-osf1.mc generic-linux.mc generic-solaris.mc
All .mc
files require specific minimal statements.
For a SunOS 4.1.4 site on the Internet, for example, the following
are minimal:
OSTYPE(sunos4.1)dnl ← see Section 4.2.2.1 MAILER(local)dnl ← see Section 4.2.2.2 MAILER(smtp)dnl← see Section 4.2.2.2
To build a configuration file from these statements, you would place them into a file—say, localsun.mc—then run the following command:
% ./Build localsun.cf
Using M4=/usr/5bin/m4
rm -f localsun.cf
/usr/5bin/m4 ../m4/cf.m4 localsun.mc > localsun.cf || ( rm -f localsun.cf && exit 1 )
chmod 444 localsun.cf
Here, you run the Build[1] script found in the cf/cf directory. You pass it the name of your mc file with the “.mc” suffix changed to a “.cf” suffix. The Build script uses m4 to expand your mc file into a full-fledged configuration file.
Another way to build a configuration file is by running m4 by hand:
% m4 ../m4/cf.m4 localsun.mc > sendmail.cf
Here, the ../m4/cf.m4
tells
m4 where to look for its default configuration
file information.
If you are using an old version of m4, the following error message will be printed:
You need a newer version of M4, at least as new as System V or GNU m4: file not found: NoSuchFile
Just as the message says, you need a newer version of m4. (The third line is just a result of forcing m4 to fail and can be safely ignored.) Thus, we would need to rerun our second localsun.mc example (earlier) as:
% /usr/5bin/m4 ../m4/cf.m4 localsun.mc > sendmail.cf
↑ System V version of m4
Another cause of failure could be that the
../m4/cf.m4
file was not where you thought it was.
Various versions of m4 print this error in
different ways:
/usr/5bin/m4:-:1 can't open file ←SysV m4 m4: ../m4/cf.m4: No such file or directory ←GNU m4 m4: file not found: ../m4/cf.m4←BSD m4
One possible reason for this error might be that you are developing
your .mc
file somewhere other than in the
cf/cf directory.[2] The solution is to use a full pathname to
cf.m4 or to replace that expression on the
command line with a shell variable.
After you have successfully produced a “first draft” of your configuration file, you can edit localsun.mc and add features as you need them. Many possibilities are described in the rest of this chapter.
The _CF_DIR_ m4 Macro
It can be advantageous to maintain all the files that make up your local m4 configuration separately from the sendmail distribution. This prevents new releases of sendmail from clobbering your source files. It also allows you to maintain configuration information more conveniently (perhaps under rcs(1) control) and to use programs such as make(1) to simplify configuring and installation.
Most modern versions of m4 allow you to define m4 macros on the command line, and one such m4 macro is recognized internally by the m4 technique:
_CF_DIR_
This command-line m4 macro tells m4 where the m4/cf.m4 file described earlier is located. It needs to have its value set to be the cf directory under the sendmail source distribution, and it needs to end in a slash character. For example, GNU m4 version 1.2 allows this:
%setenv CFDIR /usr/local/src/mail/sendmail/cf/
%/usr/local/gnu/bin/m4 -D_CF_DIR_=${CFDIR} ${CFDIR}m4/cf.m4 localsun.mc \
> sendmail.cf
Notice that we store the value for _CF_DIR_
in an
environment variable. Note that GNU m4 can
figure out the _CF_DIR_
path itself from the path
of the cf.m4 file. We include
_CF_DIR_
here merely as an example. If your
version of m4 lacks this ability, you should
consider upgrading.
With the _CF_DIR_
m4 macro,
we can further simplify configuration and installation by using
make(1). To illustrate, consider the following
few lines from a Makefile on a SunOS system:
M4=/usr/local/gnu/bin/m4 CFDIR=/usr/local/src/mail/sendmail/cf/ localsun: localsun.mc $(M4) -D_CF_DIR_=$(CFDIR) $(CFDIR)/m4/cf.m4 localsun.mc > sendmail.cf
With this Makefile the two complex command lines shown earlier are reduced to a single, simple command line:
% make
The Minimal mc File
Every mc file requires minimal information. Table 4-1 shows which m4 items are required and lists two that are recommended. We show them in the order that they should be declared (OSTYPE first and MAILER last), then describe the mandatory and recommended information.
Item |
§ |
Description | |
OSTYPE( ) |
Required |
Support for your operating system | |
DOMAIN( ) |
Recommended |
Common domain-wide information | |
FEATURE( ) |
Recommended |
Solutions to special needs | |
MAILER( ) |
Required |
Necessary delivery agents |
Note that what is minimally required for a workstation differs from what is minimally required for a central mail server. We suggest that you use these recommendations as a jumping-off point and then investigate all the m4 macros and features that are available.
OSTYPE( ) m4 macro
Support for various operating systems is
supplied with the OSTYPE m4 command. Every
.mc
file must declare the
operating system with this command, and this command must be the
first in your mc file.[3] The available support is supplied by
files in the _CF_DIR_/ostype directory. A
listing of those files looks something like this:
a-ux.m4 bsdi2.0.m4 hpux9.m4 openbsd.m4 solaris2.ml.m4 aix3.m4 darwin.m4 irix4.m4 osf1.m4 solaris2.pre5.m4 aix4.m4 dgux.m4 irix5.m4 powerux.m4 solaris8.m4 aix5.m4 domainos.m4 irix6.m4 ptx2.m4 sunos3.5.m4 altos.m4 dynix3.2.m4 isc4.1.m4 qnx.m4 sunos4.1.m4 amdahl-uts.m4 freebsd4.m4 linux.m4 riscos4.5.m4 svr4.m4 bsd4.3.m4 freebsd5.m4 maxion.m4 sco-uw-2.1.m4 ultrix4.m4 bsd4.4.m4 gnu.m4 mklinux.m4 sco3.2.m4 unixware7.m4 bsdi.m4 hpux10.m4 mpeix.m4 sinix.m4 unknown.m4 bsdi1.0.m4 hpux11.m4 nextstep.m4 solaris2.m4 uxpds.m4
To include support, select the file that best describes your operating system, delete the .m4 suffix from its name, and include the resulting name in an OSTYPE declaration:
OSTYPE(`ultrix4')
Here, support for the DEC Ultrix operating system is defined. Note
that some of these are not entirely accurate. For example,
ultrix4.m4
includes support for Ultrix versions
4.2 and 4.3, and sunos4.1.m4
includes support for
SunOS versions 4.1.2, 4.1.3., and 4.1.4.
If you pick a name for which no file exists, or if you misspell the name of the file, an error similar to the following will print:
m4: Can't open ../ostype/ultrux4.1.m4: No such file or directory
If you omit the OSTYPE declaration entirely, you will get the following error:
*** ERROR: No system type defined (use OSTYPE macro)
MAILER( ) m4 macro
Delivery agents are not automatically declared. Instead, you must specify which ones you want to support and which ones you want to ignore. Support is included by using the MAILER definition:
MAILER(`local')
This causes support for both the local
and
prog
delivery agents to be included. This is the
minimal declaration (even if you don’t intend to
perform local or program delivery).
The MAILER definition must always be last in your
mc configuration file.[4] If you include
MAILER definitions for procmail
(1),
maildrop
(1), or uucp
, those
definitions must always follow the definition for
smtp
. Any modification of a MAILER definition (as,
for example, with LOCAL_MAILER_MAX) must precede that MAILER
definition:
define(`LOCAL_MAILER_MAX', `1000000') ←here MAILER(`local') define(`LOCAL_MAILER_MAX', `1000000')←not here
A minimal mc file for an average machine on the Internet would contain two MAILER definitions:
MAILER(`local') MAILER(`smtp')
The first you have already seen. The second includes support for sending email to other hosts on the Internet. If this minimal mc is all you think you’ll need, you can continue on to the rest of this chapter. If, on the other hand, you expect to support any variations on mail receipt and delivery beyond the basics, you should leap ahead to Chapter 20, study that chapter, then return here. (See Table 20-1 in Section 20.3 for a list of all the available delivery agents.)
All delivery agent equates, such as F=
and
M=
, can be modified with the
.m4
configuration technique. Table 20-18 (Section 20.5) lists all the
equates and shows where to find further information about each of
them. By investigating those sections, you can discover how to tune
particular equates with the m4 technique. For
example, the following mc lines define the
program used for local delivery to be
mail.local:
FEATURE(`local_lmtp') define(`LOCAL_MAILER_PATH', `/usr/local/bin/mail.local') MAILER(local)
Note that all modifications to equates must precede the corresponding MAILER( ) definition.
DOMAIN( ) m4 macro
For large sites it can be advantageous to gather into a single file all configuration decisions that are common to the entire domain. The directory to hold domain information files is called domain. The configuration information in those files is accessed by using the DOMAIN( ) m4 technique. For example:
DOMAIN(`uofa.edu')
This line in any of your mc files causes the file domain/uofa.edu.m4 to be included at that point. Examples that come with the distribution illustrate subdomains under Berkeley.EDU. One boilerplate file, named generic.m4, can be used as a starting point for your own domainwide file. For example, if all hosts at your site masquerade behind one email name, you might want to put MASQUERADE_AS (Section 4.4.2) in your domain file. Domain files also form a natural location for the definition of site-specific relays (Section 4.5).
If the domain that is specified does not exist or is misspelled, an error similar to the following will be printed:
m4: Can't open ../domain/generik.m4: No such file or directory
The use of DOMAIN( ) is not mandatory but is recommended. Note that problems can arise because the items inside your domain file will determine where the DOMAIN( ) declaration must go in the mc file. If, for example, the domain file contains MAILER( ) definitions, DOMAIN( ) should appear near the end of the mc file with the MAILER( ) definitions. If the domain file contains rules and rule sets, the DOMAIN( ) must be last in the mc file, but if the domain file contains OSTYPE( ), DOMAIN( ) must be first in the mc file. So, consider well what you place in your domain file. Avoid defining anything in your domain file that restricts where the DOMAIN( ) definition must go in your mc file.
In the event that your domain file contains many position-dependent commands, such as rule sets and an OSTYPE( ) command, you might need to split that file into pieces. You can split it something like this:
DOMAIN(`our.domain.sun') DOMAIN(`our.domain.rules')
Here, the first line causes the file our.domain.sun.m4 to be read. That file contains the OSTYPE( ) declaration for all your Sun workstations. This DOMAIN( ) entry would appear at the top of your mc file.
The second line causes the file our.domain.rules.m4 to be read. That file might contain antispam rule sets. This second DOMAIN( ) entry would appear near the end of your mc file, perhaps under LOCAL_RULESETS.
FEATURE( ) m4 macro
V8 sendmail offers a number of features that you might find very useful. To use a feature, include an m4 command such as one of the following in your mc file:
FEATURE(keyword) FEATURE(keyword, argument) FEATURE(keyword, argument, argument, ... etc. )
These declarations cause a file of the name
feature/keyword.m4
to
be read at that place in your mc file. The
available keyword files are summarized in Table 4-7 of Section 4.8, and each is
explained in the section at the end of this chapter. Note that some
keywords require additional arguments.
The Order of mc Lines
As you have seen, some mc lines must precede others. This is necessary partly because m4(1) is a one-pass program, and partly because the order of items in the final sendmail.cf file is also critical. The recommended order is:
VERSIONID( ) ← see Section 4.2.3.1 OSTYPE( ) ← see Section 4.2.2.1 DOMAIN( ) ← see Section 4.2.2.3 option definitions ← see Section 24.4 FEATURE( ) ← see Section 4.8 macro definitions ← see Section 21.7 MAILER( ) ← see Section 4.2.2.2ruleset definitions← see Section 19.1.7
If in doubt about where some particular item should go, look in the many example files in cf/cf. Some of them (especially the file knecht.mc) will also give you good ideas about how you can improve your own mc file.
VERSIONID m4 macro
The VERSIONID m4 macro is used to insert an identifier into each mc and m4 file that becomes a part of your final .cf file. Each file that is supplied with sendmail already has such an identifier. You should include a similar identifier in each of your mc files:
VERSIONID(`$Id$')
Here, the VERSIONID m4 macro is used to insert an RCS-style revision number. The $Id: ch04,v 1.53 2002/12/12 21:54:32 judyh Exp judyh $ becomes an actual version number when the file is checked in with ci(1). Arbitrary text can appear between the single quotes. You can use RCS, SCCS, or any other kind of revision identification system. The text cannot contain a newline because the text appears in the .cf file as a comment:
##### $Id: ch04.xml,v 1.8 2004/05/27 18:36:15 marti Exp $ #####
Use of VERSIONID and revision control in general is recommended.
HACK( ) m4 macro
Some things just can’t be called features. To make this clear, they go in the hack directory and are referenced using the HACK m4 macro. They tend to be site-dependent:
HACK(`cssubdomain')
This illustrates use of the Berkeley-dependent
cssubdomain
hack (that makes
sendmail accept local names in either
Berkeley.EDU or
CS.Berkeley.EDU).
Another way to think of a hack is as a transient feature. Create and use HACK as a temporary solution to a temporary problem. If a solution becomes permanent, move it to the FEATURE directory and reference it there.
[1] This is not the same Build script that is documented in Section 5.1. It is a small shell script that works only in the cf/cf directory, and that can be used only to build configuration files. You can use make in its place, but make will not automatically find the correct version of m4 for you.
[2] This is
actually a good idea. It prevents new sendmail
distributions from clobbering your .mc
files.
[3] We fudge for simplicity. Actually OSTYPE can legally be preceded by VERSION (Section 4.2.3.1) and m4 comments.
[4] Although it can and probably should be followed by rule set declarations, as for example, LOCAL_RULESET_0.
Get Sendmail, 3rd Edition now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.