-->

Previous | Table of Contents | Next

Page 119

The values of macros and classes are matched in the lhs with the operators shown in Table 7.3.

Table 7.3. lhs macro and class-matching operators.


Operator Description
$X Matches the value of macro X
$=C Matches any word in class C
$~C Matches if token is not in class C

The pattern-matching operators and macro- and class-matching operators are necessary because most rules must match many different input addresses. For example, a rule might need to match all addresses that end with gonzo.gov and begin with one or more of anything.

The Right-Hand Side (rhs) of Rules

The rhs of a rewriting rule tells sendmail how to rewrite an address that matches the lhs. The rhs can include text, macros, and positional references to matches in the lhs. When a pattern-matching operator from Table 7.2 matches the input, sendmail assigns it to a numeric macro $n, corresponding to the position it matches in the lhs. For example, suppose the address joe@pc1.gonzo.gov is passed to the following rule:


R$+ @ $+       $: $1 < @ $2 >           focus on domain

In this example, joe matches $+ (one or more of anything), so sendmail assigns the string joe to $1. The @ in the address matches the @ in the lhs, but constant strings are not assigned to positional macros. The tokens in the string pc1.gonzo.gov match the second $+ and are assigned to $2. The address is rewritten as $1<@$2>, or joe<@pc1.gonzo.gov>.

$: and $@—Altering a Ruleset's Evaluation

Consider the following rule:


R$*  $: $1 < @ $j > add local domain

After rewriting an address in the rhs, sendmail tries to match the rewritten address with the lhs of the current rule. Because $* matches zero or more of anything, what prevents sendmail from going into an infinite loop on this rule? After all, no matter how the rhs rewrites the address, it will always match $*.

The $: preface to the rhs comes to the rescue; it tells sendmail to evaluate the rule only once.

Sometimes you might want a ruleset to terminate immediately and return the address to the calling ruleset or the next ruleset in sendmail's built-in sequence. Prefacing a rule's rhs with $@ causes sendmail to exit the ruleset immediately after rewriting the address in the rhs.

Page 120

$>—Calling Another Ruleset

A ruleset can pass an address to another ruleset by using the $> preface to the rhs. Consider the following rule:


R$*       $: $>66 $1          call ruleset 66

The lhs $* matches zero or more of anything, so sendmail always does the rhs. As you learned in the preceding section, the $: prevents the rule from being evaluated more than once. $>66 $1 calls ruleset 66 with $1 as its input address. Because $1 matches whatever was in the lhs, this rule simply passes the entirety of the current input address to ruleset 66. Whatever ruleset 66 returns is passed to the next rule in the ruleset.

Testing Rules and Rulesets—The -bt, -d, and -C Options

Debugging sendmail.cf can be a tricky business. Fortunately, sendmail provides several ways to test rulesets before you install them.

NOTE
The examples in this section assume that you have a working sendmail. If your system does not, try running these examples again after you have installed V8 sendmail.

The -bt option tells sendmail to enter its rule-testing mode:


$ sendmail -bt

ADDRESS TEST MODE (ruleset 3 NOT automatically invoked)

Enter <ruleset> <address>

>




NOTE
Notice the warning ruleset 3 NOT automatically invoked. Older versions of sendmail ran ruleset 3 automatically when in address test mode, which made sense because sendmail sends all addresses through ruleset 3 anyway. V8 sendmail does not, but invoking ruleset 3 manually is a good idea because later rulesets expect the address to be in canonical form.

The > prompt means sendmail is waiting for you to enter one or more ruleset numbers, separated by commas, and an address. Try your login name with rulesets 3 and 0. The result should look something like this:


> 3,0 joe

rewrite: ruleset  3   input: joe

rewrite: ruleset  3 returns: joe

rewrite: ruleset  0   input: joe

Page 121


rewrite: ruleset  3   input: joe

rewrite: ruleset  3 returns: joe

rewrite: ruleset  6   input: joe

rewrite: ruleset  6 returns: joe

rewrite: ruleset  0 returns: $# local $: joe

>

The output shows how sendmail processes the input address joe in each ruleset. Each line of output is identified with the number of the ruleset processing it, the input address, and the address that the ruleset returns. The > is a second prompt indicating that sendmail is waiting for another line of input. When you're done testing, just press Ctrl+D.

Indentation and blank lines better show the flow of processing in this example:


rewrite: ruleset  3   input: joe

rewrite: ruleset  3 returns: joe



rewrite: ruleset  0   input: joe



     rewrite: ruleset  3   input: joe

     rewrite: ruleset  3 returns: joe



     rewrite: ruleset  6   input: joe

     rewrite: ruleset  6 returns: joe



rewrite: ruleset  0 returns: $# local $: joe

The rulesets called were 3 and 0, in that order. Ruleset 3 was processed and returned the value joe, and then sendmail called ruleset 0. Ruleset 0 called ruleset 3 again and then ruleset 6, an example of how a ruleset can call another one by using $>. Neither ruleset 3 nor ruleset 6 rewrote the input address. Finally, ruleset 0 resolved to a mailer, as it must.

Often you need more detail than -bt provides—usually just before you tear out a large handful of hair because you don't understand why an address doesn't match the lhs of a rule. You can remain hirsute because sendmail has verbose debugging built in to most of its code.

You use the -d option to turn on sendmail's verbose debugging. This option is followed by a numeric code that tells which section of debugging code to turn on and at what level. The following example shows how to run sendmail in one of its debugging modes and the output it produces:


$ sendmail -bt -d21.12

ADDRESS TEST MODE (ruleset 3 NOT automatically invoked)

Enter <ruleset> <address>

> 3,0 joe

rewrite: ruleset  3   input: joe

--trying rule: $* < > $*

-- rule fails

--trying rule: $* < $* < $* < $+ > $* > $* > $*

-- rule fails

[etc.]

Previous | Table of Contents | Next