Contents:
Class Configuration Commands
Access Class in Rules
Class with m4
Pitfalls
Alphabetized Reference
A class is like an array of string values. In the LHS of rules it is sometimes advantageous to compare individual tokens to multiple strings when determining a match. The configuration class command provides this ability. The class command is similar to the macro definition command, except that instead of assigning a single value to a macro, it assigns many values to a class. Classes differs from macros in that they can be used only in the LHS of rules, whereas macros can be used in either the RHS or the LHS.
Two different configuration commands can be used to assign values to
a class.
The C
configuration command is used to
assign values from within the configuration file.
The F
configuration command is used in two ways:
to assign values by reading them from a disk file or
to assign values by running a program and reading the output.
These commands may be
intermixed to create a single class or used separately to
create multiple classes.
You may wish to review the tutorial in Chapter 12, Class, to see a few typical applications of class.
The three forms for the class configuration command are the following:
CX list
values from configuration file FX file
values from a disk file FX
|program
values via another program
The class configuration command starts with either the letter
C
or F
, which must begin a line. The C
says
values will be assigned as a part of the configuration command.
The F
says values will be assigned from an external
file or program.
The C
or F
is immediately followed
(with no intervening whitespace) by the name of the class
(the X
above). A class name is any single ASCII character or,
beginning with V8.7 sendmail a multicharacter name enclosed
in curly braces:
CX list
all versions C{LongName} list
beginning with V8.7
See Section 31.4.2, "Multicharacter Names" for a full discussion of how to use multicharacter names.
Note that classes are separate from macros, so they may both use the same letter or name with no conflict.
The sendmail program reserves the lowercase letters for its own use as internally defined class names (although currently only a few are actually used). All uppercase letters and all names that begin with uppercase letters are available for use.
The C
form of the class command causes values to
be assigned from within the configuration file.
In general, the class command looks like this:
CX list
values from configuration file C{XX} list
values from configuration file
Here, a list
is a list
of string elements (delimited by whitespace) that follows
on the same line as the C
command. Each word in
list
is appended to the array of values in the class
X
in the first case and to the class {XX}
in
the second.
[1]
[1] Note that when a class name is a single character, it may be referenced with or without enclosing curly braces, with no change in meaning. That is,
CX
andC{X}
are equivalent.
Multiple declarations of the same named class may coexist in the configuration file. Each declaration after the first appends its string elements to the preceding list. That is,
CX string1 string2 CX string3 string4
produces the same class as does
CX string1 string2 string3 string4
Both create a class with four strings as elements.
When an array of values is built, whitespace is used to
separate one value from another. Whitespace is defined by
the C language isspace(3) routine and usually includes
the space, tab, newline, carriage-return, and form-feed characters.
Each line of text assigned to a class is broken up by sendmail
into whitespace delimited words.
When a line
is indented with a space or a tab, that line is joined by sendmail
to the preceding line. Thus the following three declarations
also append four words to the class X
:
CX string1 CX string2 CX string3 string4 tab
Words that are added to a class cannot be removed after sendmail has read them. Instead, they must be edited out of whatever file or program produced them, and the sendmail daemon must be killed and restarted.
The list of words in a class declaration can include macros. For example
the following assigns the same values to class X
as did
the above example:
D{LIST} string1 string2 string3 string4 CX ${LIST}
Macros used in class declarations are expanded when the configuration file
is read. Deferred macros (those with the $&
prefix) may not be used
in class declarations. But conditionals may:
CX ourhost$?{Domain}.${Domain}$.
The F
form of the class configuration command allows values
to be appended to a class from outside the configuration file.
In general, the file command looks like either of the following:
FX file
values from a disk file FX
|program
values via another program (V8.7 and above, or IDA)
The F
is immediately followed by the name of the class. This can be either a
single-character name, as shown, or a multicharacter name.
The name is followed by optional whitespace and then the name of
a file or program.
If the file or program begins with the pipe
character (|
), it is taken to be the name of
a program to run.
[2]
Otherwise, it is taken to be the name of a file
to read.
[2] This was removed from V8.1 sendmail because it presented a security risk. It was restored to V8.7 because sendmail now checks permissions more carefully and exec(2)'s the program itself instead of using the old, buggy popen(3) approach of yore.
If SCANF was defined when sendmail was compiled
(see Section 18.8.39, SCANF),
each line that is read from a file or program
is parsed by the C language scanf(3) library routine.
The formatting pattern given to scanf(3) is %s
,
which tells scanf(3) to read only the first whitespace-delimited word from each line of text.
The file is opened for reading
or the program is executed when the configuration file is processed.
If either cannot be opened (for reading or execution), sendmail
syslog(3)'s the following error and ignores that configuration command:
cannot open what:why
file cannot exec what:why
program
Here, the what is the exact text that was given in the configuration
file, and why
is the text of a system error.
For the file form only,
if the file may optionally not exist, you can prefix its name
with a -o
switch:
FX -o file
okay for file to not exist
This tells sendmail to remain silent if the file does not exit.
The -o
switch is useful when a configuration file is
shared by several machines, only some of which need the external class
macro file.
The C
and F
forms of the configuration command may be
intermixed for any given class name. For example, consider a file
named /etc/local/names with the following contents:
string3 string4
The following two configuration commands add the same
four strings to the class X
as did the C
command alone
in the previous section:
CX string1 string2 FX /etc/local/names
This creates a class with four strings as array elements. Whitespace
delimits one string from the others in the C
line declaration,
and they are stored in the order in which they are listed.
The file /etc/local/names is then opened and read,
and each of the two words in that file is appended to the two words
that are already in the class.
The file form of the class configuration command
allows different formatting patterns to be used with scanf(3).
[3]
But the program form does not
allow any variation,
and so its scanf(3) pattern is always %s
,
which tells scanf(3) to read only the first whitespace-delimited
word from each line of text:
[3] The version of sendmail that you are using must have been compiled with SCANF defined (see Section 18.8.39) for scanf(3) to be usable from within the configuration file.
FX file pat
with scanf(3) pattern FX
|program
always ``%s''
If the optional pat
argument to the file form is missing, the pattern
given to scanf(3) is %s
.
The pat
argument is separated from the file
argument by one or more spaces or tabs. It should not be quoted, and it consists
of everything from its first character to the end of the line.
Internally, scanf(3) is called with:
sscanf(result, pat, input)
Here, result
is the string array element to be added
to the class definition. The pat
is the scanf(3) pattern,
and input
is the line of text read from the file.
[4]
[4] Avoid using a bare
%s
as the pattern. Doing so risks overflowing internal sendmail buffers. Instead specify a limited string length with something like%.40s
.
After each line of text is read from the file and filtered with the scanf(3) pattern, it is further subdivided by sendmail into individual words. That subdividing uses whitespace (as defined by the C language isspace(3) routine) to separate words. Each separate word is then appended as an individual element to the class array.
Consider the contents of the following file named /etc/local/myhosts:
server1 server2 # my two nets uuhost # my uucp alias #mailhost # mail server alias (retired 06,23,91)
This file contains three hostname aliases to be added
to a class, say H
. The following configuration command
does just that:
FH /etc/local/myhosts %[^\#]
The pattern %[^#]
causes scanf(3) to read all characters
in each line up to, but not including, the first #
character.
The first line includes two white-space delimited words
that are appended to the class H
. The second line
contains one word, and the third contains none. The \
character prevents sendmail from treating the #
as a
comment character.