21.6 Macro Conditionals: $?, $|, and $.
Occasionally, it is necessary to test a
sendmail macro to see whether a value has been
assigned to it. To perform such a test, a special prefix and two
operators are used. The general form is:
if else endif
$?x text1 $| text2 $.
if x is defined if x is not defined
This expression yields one of two possible values:
text1 if the macro named x has
a value, text2 if it doesn't. The
entire expression, starting with the $? and ending
with the $., yields a single value, which can
contain multiple tokens.
The following, for example, includes the configuration-file version
in the SMTP greeting message but does so only if that version (in
$Z; see $Z) is defined:
O SmtpGreetingMessage=$j Sendmail ($v/$?Z$Z$|generic$. ) ready at $b
note
Here, the parenthetical version information is expressed one way if
$Z has a value (such as 1.4):
($v/$Z)
but is expressed differently if $Z lacks a value:
($v/generic)
The else part ($|) of this
conditional expression is optional. If it is omitted, the result is
the same as if the text2 were omitted:
$?xtext1$|$.
$?xtext1$.
Both of the preceding yield the same result. If x
has a value, text1 becomes the value of the entire
expression. If x lacks a value, the entire
expression lacks a value (produces no tokens).
Note that it is not advisable to use the
$? conditional expression in rules. Such a use can
have other than the intended effect because macro conditionals are
expanded when the configuration file is read.
21.6.1 Conditionals Can Nest
V8
sendmail allows conditionals to nest. To
illustrate, consider the following expression:
$?x $?y both $| xonly $. $| $?y yonly $| none $. $.
This is just like the example in the previous section:
$?x text1 $| text2 $.
except that text1 and text2 are
both conditionals:
text1 = $?y both $| xonly $.
text2 = $?y yonly $| none $.
The grouping when conditionals nest is from the outside in. In the
following example, parentheses have been inserted to show the
groupings (they are not a part of either expression):
($?x (text1) $| (text2) $. )
($?x ($?y both $| xonly $. ) $| ($?y yonly $| none $. ) $. )
Interpretation is from left to right. The logic of the second line is
therefore this: if both $x and
$y have values, the result is
both. If $x has a value but
$y lacks one, the result is
xonly. If $x lacks a value but
$y has one, the result is
yonly. And if both lack values, the result is
none.
The sendmail program does not enforce or check
for balance in nested conditionals. Each $? should
have a corresponding $. to balance it. If they do
not balance, sendmail will not detect the
problem. Instead, it might interpret the expression in a way that you
did not intend.
The depth to which conditionals can be nested is limited only by our
ability to easily comprehend the result. More than two deep is not
recommended, and more than three deep is vigorously discouraged.
21.6.2 Macro Translations
Some macros are assigned values from text that is supplied by outside
connecting hosts. Such text cannot necessarily be trusted in rule
sets, or as keys in database-map lookups.
To protect itself, sendmail modifies such text
by translating whitespace characters (spaces and tabs), nonprinting
characters (such as newlines and control characters), and the
following list of special characters:
< > ( ) " +
Translation is the replacement of each special character with its
corresponding hexadecimal value (based on U.S. ASCII), where each new
hexadecimal value is prefixed with a plus character. For example:
(some text) becomes +28some+20text+29
Only four macros are subject to this encoding at this time. They are
listed in Table 21-4.
Table 21-4. Macros subject to xtext encoding
${cert_issuer}
|
${cert_issuer}
|
Distinguished name of certificate signer
|
${cert_subject}
|
${cert_subject}
|
Distinguished name of certificate (owner)
|
${cn_issuer}
|
${cn_issuer}
|
Common name of certificate signer
|
${cn_subject}
|
${cn_subject}
|
Common name of certificate
|
|