Chapter 15. Debug sendmail with -d

The sendmail program offers the -d command-line switch, which allows you to observe sendmail’s inner workings in detail. Understanding this switch can help you solve complex email problems.

In earlier editions of this book, we attempted to document all the debugging switches available, and provided a table showing which were useful. For this edition, however, we will limit our detailed description to V8.14 sendmail and only to those debugging switches considered useful. This was done because debugging switches show the inner workings of sendmail, and, thus, those that are other than “useful” can change dramatically from release to release and are impossible to accurately represent in a static book.

The Syntax of -d

The form for the -d command-line switch is:

-dcategory.level,category.level,....
-dANSI                                         ← V8.8 and above
-dexpression.level,expression.level,....V8.12 and above

The -d can appear alone, or it can be followed by one or more category.level pairs separated by commas or, beginning with V8.8, by the word ANSI. We cover the category.level pairs first, then ANSI, and finally the expression form.

The category limits debugging to an aspect of sendmail (such as queuing or aliasing). The level limits the verbosity of sendmail (with low levels producing the least output).

The category is either a positive integer or a range of integer values specified as:

first-last

When category is a range, first is a positive integer that specifies the first category in the range. It is followed by a hyphen character (-) and then last, a positive integer that specifies the last category in the range. The value of first must be less than the value of last, or the range will be ignored.

The level is a positive integer. A level of 0 causes sendmail to produce no output for the category.

When the -d is specified with neither category nor level, an internal sendmail default is used:

0-99.1

This default causes sendmail to set all the categories, from zero through 99 inclusive, to a level of 1.

When category is included but level is omitted, the value for level defaults to 1. When a dot (.) and level are included, but category is omitted, the value for category defaults to 0.

The maximum value that can be specified for a single category is 99. The maximum value for level is that of an unsigned char (255 decimal). Any value specified above the maximum is reduced to the maximum. Nondigits for the category or range evaluate to zero. Nondigits for the level evaluate to 1.

The level specifies the maximum amount of verbose output to produce. All levels below the level specified also produce output.

The expression that produces the maximum debugging output is:

-d0-99.127

But beware that debugging levels of 100 or greater can cause sendmail to modify its behavior. (For example, one category at such a high level prevents sendmail from removing its temporary files.) For this reason, -d0-99.99 is the maximum level recommended.

Debugging can be turned on from the command line and from within -bt rule-testing mode (Add Debugging for Detail on page 318).

Beginning with V8.8 sendmail, a special debugging word can be specified at the command line to cause debugging output to become clearer:

-dANSI        ← V8.8 and above

ANSI is case-sensitive and must be the only argument following the -d. If you wish to combine it with other debugging switches, you must specify them separately:

-dANSI -d0.4

ANSI causes defined macros, class macros, and operators to be displayed in reverse video, as shown in Figure 15-1.

Reverse video display using ANSI
Figure 15-1. Reverse video display using ANSI

This is truly a “hack.” The escape code to highlight characters is hardcoded into sendmail. Your display must support ANSI-standard escape sequences for this to work. There is no plan to use standard termcap(5) library support for this “aid to rule-set hackers.”

Beginning with V8.12, sendmail has begun transitioning to more easily remembered alphanumeric debugging categories. For the V8 series, this is being accomplished by adding alphanumeric categories rather than replacing the existing numeric categories entirely.

The forms for this new way of specifying a debug category look like this:

-dprogram_check_process.level
-dprogram_trace_process.level

Here, the -d is literal. The program_ specifies the program for which the debugging flag applies. Currently, the only program_ available is “sm_” for sendmail.

The check lets you know that a particular category is intended for checks on limits, states, or the rationality of values. The trace lets you know that a particular category is intended to trace the behavior of a section of code, or of behavior common to many sections of code.

The _process specifies just what aspect of the code will be checked or traced. Table 15-1, we list the handful of new categories that currently use this new form.

Table 15-1. New alphanumeric debug categories

Category

Does what

sm_check_assert

Enable expensive SM_ASSERT checking.

sm_check_require

Enable expensive SM_REQUIRE checking.

sm_check_ensure

Enable expensive SM_ENSURE checking.

sm_trace_heap

Trace sm_{malloc,realloc,free} calls.

sm_check_heap

Enable memory leak detection.

All of these new categories are intended to be used by sendmail developers and are not generally useful to mail administrators. If you suspect you might need to use one of these categories, examine the sendmail code first to determine the effect of each, and then apply them in one window while examining the source in another.

The Behavior of -d

When sendmail is given the -d debugging switch, it internally performs three distinct actions. First, if the category.level is omitted, sendmail presets all categories, 0–99 inclusively, to a level of 1. It then sets the categories in the command line (if any) to the corresponding levels specified (or to 1 if no level is specified). Finally, it calls setbuf(3) to place the standard output in unbuffered mode.

Setting categories 0–99 to a level of 1 has two side effects:

  • Usually, certain errors are not reported because they are tolerable, but a level of 1 generally causes those otherwise missing error messages to be printed. For example, if the aliases file is missing, sendmail does not perform aliasing but is silent about it. A category 27 level of 1, on the other hand, causes sendmail to print the reason it could not open the aliases file.

  • Because sendmail is usually silent about what it is doing, any debugging at all causes it to print a great deal of information about what it is trying to do and what it has done.

Note, however, that debugging should generally not be used in combination with any -bd, -bD, or -bs command-line switch. Debugging output can interfere with normal SMTP transactions, and thus can corrupt the transmission or receipt of SMTP email. Use these debugging switches only when you are absolutely certain that no actual mail will be impacted (as might be the case on a machine that normally does not receive mail).

Interpret the Output

Some debugging output references C-language structures that are internal to sendmail. For those, it will help if you have access to sendmail source. One subroutine, called printaddr( ), is used to dump complete details about all the recipients for a given mail message. This subroutine is used by many categories of debugging output, but rather than describe it repeatedly, we describe it once, here, and reference this description as needed.

The sendmail program’s internal printaddr( ) subroutine prints details about addresses. The sendmail program views an address as more than just an expression such as gw@wash.dc.gov. Internally, it represents every address with a C-language structure. The printaddr( ) routine prints the values stored in most of the items of that structure. Its output looks like this:

subroutine: ra= addr:
        mailer mnum (mname), host `hname'
        user `uname', ruser `rname'
        state=state, next=link, alias aname, uid user-id, gid group-id
        flags=fhex<names here>
        owner=owner, home="home", fullname="fname"
        orcpt="oparam", statmta=mta, status=status
        finalrcpt="finalrcpt"
        rstatus="rstatus"
        statdate=statdate

First, sendmail prints the address in memory, ra, of the C-language struct that contains the information necessary to deliver a mail message. It then prints the information in that structure:

addr

The mail address as text--e.g., you@uofa.edu.

mnum

Number of the delivery agent to be used (an index into the array of delivery agents).

mname

Symbolic name of that delivery agent (from rule set parse 0, $#).

hname

Name of the recipient’s host machine (from rule set parse 0, $@).

uname

Recipient’s mail name (from rule set parse 0, $:).

rname

Recipient’s login name, if known; otherwise, it is <null>.

state

The current state of the message in text form. See Table 15-2 for a list of the text names that can be printed, and their meanings.

Table 15-2. State names

State name

Description

OK

The message is initially in an untried, OK state.

DONTSEND

The message must not be sent to this address.

BADADDR

The address is bad.

QUEUEUP

The message should be queued for this address.

RETRY

Proceed to the next MX server and try again.

SENT

The message was successfully delivered or relayed to this address.

VERIFIED

The address has been verified, but not alias-expanded.

EXPANDED

The address has been alias-expanded.

SENDER

This address is that of the sender.

CLONED

This address was cloned as part of envelope splitting.

DISCARDED

This recipient address must be discarded.

REPLACED

This address was replaced by the User Database or the localaddr rule set 5.

REMOVED

This address has been removed from the recipient list.

DUPLICATE

This is a duplicate address that has been suppressed.

INCLUDED

This address resulted in an :include: expansion.

link

Address in memory of the next C-language structure of information about the next recipient in the list of recipients.

aname

Address in memory of the next C-language structure of information about the alias that led to this address (if there was one).

user-id and group-id

The user-id and group-id assigned to this delivery agent. These values are derived from the ownership permissions of an :include: file or a ~/.forward file (Delivery to Files on page 466) or the user-id and group-id of a local user or the DefaultUser’s identity (DefaultUser on page 1000).

fhex

A hexadecimal representation of the possible envelope flags. This is immediately followed by a list of the names of flags inside the angle brackets. We don’t describe those names here.

owner

The owner- that corresponds to the aname, if there is one.

home

Home directory of the recipient (for local mail only).

fname

Full name of the recipient, if it is known.

oparam

The ORCPT parameter to the SMTP RCPT command, if there was one.

mta

The name of the MTA host (such as “other.dc.gov”) that generated the Delivery Status Notification (DSN) message shown in rstatus.

finalrcpt

The DSN FinalRecipient: value—for example, “RFC822; gw@wash.dc.gov.”

status

The DSN number as text.

rstatus

The DSN message from the remote receiving host’s MTA.

statdate

The date and time the status of this address changed.

The -D Debug File Switch

The -D command-line switch is used to redirect sendmail’s debugging output into a file for later examination. It is used like this, where file is the name of an existing or new file:

-D file

The -D command-line switch (if used) must precede the -d switch on the same command line; otherwise, the following error will print and all debugging output will be printed to the standard output (possibly causing you to miss seeing the error):

-D file must be before -d

The file specified with -D must live in a directory that is writable by the user running sendmail. If the file does not exist, it will be created. If the file already exists, it will be silently appended to.

Extra care must be exercised when using the -D command-line switch as root because the target file will be appended to, even if it is a symbolic link to an important file. For example, when /tmp/foo is a non-root-owned symbolic link that points to /etc/passwd, the following command line, when run by root, will silently append debugging information to the /etc/passwd file:

# /usr/sbin/sendmail -D /tmp/foo -d0.1 -bt < /dev/null

Table of All -d Categories

Because debugging is so closely tied to the internals of sendmail, we no longer cover all debugging switches in detail. In the reference section at the end of this chapter, we cover in detail only those debugging switches that are useful to the administrator. In Table 15-3, we list all the debugging switches by category, regardless of their usefulness, and give a brief description of each. If you need more detail about those we do not document, we suggest you use sendmail/TRACEFLAGS as a guide to the appropriate source code files.

Table 15-3. Debugging switches by category

Category

Description

-d0

Display system configuration information.

-d1

Show sender information.

-d2

Trace sendmail’s exit information.

-d3

Print the load average.

-d4

Trace disk-space calculations.

-d5

Trace timed events.

-d6

Show failed mail.

-d7

Trace the queue filename.

-d8

Trace hostname canonicalization.

-d9

Trace identd exchanges.

-d10

Trace recipient delivery.

-d11

Trace delivery generally.

-d12

Trace mapping of relative host.

-d13

Trace the envelope and envelope splitting.

-d14

Show header field commas.

-d15

Trace incoming connections.

-d16

Trace outgoing connections.

-d17

Trace MX record lookups.

-d18

Trace SMTP replies.

-d19

Show ESMTP MAIL and RCPT parameters.

-d20

Show delivery agent selection.

-d21

Trace rules and rule sets.

-d22

Show address tokenization.

-d23

Unused.

-d24

Trace assembly of address tokens.

-d25

Trace the send-to list.

-d26

Trace recipient queueing.

-d27

Trace aliasing, ~/.forward file handling, and controlling user.

-d28

Trace the User Database.

-d29

Trace localaddr rule set rewrite of local recipient.

-d30

Trace header processing.

-d31

Trace header validation.

-d32

Show collected headers.

-d33

Watch crackaddr( ).

-d34

Trace header generation and skipping.

-d35

Trace macro definition and expansion.

-d36

Trace the internal symbol table.

-d37

Trace setting of options and classes.

-d38

Trace database processing.

-d39

Display digit database mapping.

-d40

Trace processing of the queue.

-d41

Trace queue ordering.

-d42

Trace connection caching.

-d43

Trace MIME conversions.

-d44

Trace safefile( ).

-d45

Trace envelope sender.

-d46

Show xf file’s descriptors.

-d47

Trace effective/real user/group IDs.

-d48

Trace calls to the check_ rule sets.

-d49

Trace checkcompat( ).

-d50

Trace envelope dropping.

-d51

Trace unlocking and prevent unlink of xf file.

-d52

Trace controlling TTY.

-d53

Trace xclose( ).

-d54

Show error return and output message.

-d55

Trace file locking.

-d56

Trace persistent host status.

-d57

Monitor vsnprintf( ) overflows.

-d58

Trace buffered filesystem I/O.

-d59

Trace XLA from contrib.

-d60

Trace database map lookups inside rewrite( ).

-d61

Trace gethostbyname( ).

-d62

Log file descriptors before and after all deliveries.

-d63

Trace queue processing forks.

-d64

Trace Milter interactions.

-d65

Trace nonallowed user actions.

-d66

Unused.

-d67

Unused.

-d68

Unused.

-d69

Queue scheduling.

-d70

Queue quarantining.

-d71

Milter quarantine on errors.

-d72

Unused.

-d73

Queue shared memory updates.

-d74

Unused.

-d75

Unused.

-d76

Unused.

-d77

Unused.

-d78

Unused.

-d79

Unused.

-d80

Trace Content-Length: header (Sun version).

-d81

Trace > option for remote mode (Sun version).

-d82

Unused.

-d83

Collection timeout.

-d84

Delivery timeout.

-d85

The internal dprintf database map.

-d86

Unused.

-d87

Unused.

-d88

Unused.

-d89

Unused.

-d90

Unused.

-d91

Log caching and uncaching connections.

-d92

Unused.

-d93

Unused.

-d94

Force RSET failure.

-d95

Trace AUTH= authentication.

-d96

Allow SSL_CTX_set_info_callback( ) call.

-d97

Trace setting of auto mode for I/O.

-d98

Trace timers (commented out in the code).

-d99

Prevent backgrounding the daemon.

Pitfalls

  • It is best to debug sendmail in a window environment, within script(1), with emacs(1), or something similar. Debugging output can run to many screens.

  • Sometimes debugging output seems not to be printed:

    % /usr/sbin/sendmail -d11.1 you < /dev/null
    %

    When this happens, add the -v command-line switch to keep the output attached to your screen:

    % /usr/sbin/sendmail -v -d11.1 you < /dev/nullmany lines of output here
    %
  • There must be no space between the -d and its numeric arguments. If you put space there, the numeric arguments might be interpreted as recipient addresses.

  • There is no way to isolate a single category and level. Each level includes the output of all lower levels within a specified category.

  • The concept of debugging, versus other uses of -d, is muddled in sendmail. Tracing, for example, can be valuable for tuning a configuration file, yet such an activity is not really debugging. We hope to make the distinction clear by documenting only the “useful” debugging switches, and omitting the true code-level debugging switches from this chapter.

  • Because the -d command-line switch shows details of the internals of sendmail, the developers of sendmail consider that output to be unpublished material. As a consequence, the details of debugging output documented here might differ from what you see when running versions above or below V8.14. You are strongly encouraged to avoid writing a program to parse debugging output because such a program might become obsolete with a future release of sendmail.

  • Beginning with V8.13 sendmail, the -d switch may no longer be combined with the -q switch. This prevents direct tracing of the queueing process:

    WARNING: Cannot use -d with -q.  Disabling debugging.

Reference for -d in Numerical Order

The sendmail debugging switches vary from vendor to vendor and from version to version. This section is specific to V8.14 sendmail. These switches are perhaps best used with a copy of the sendmail source by your side. Be further advised that many of the internal details shown here will change as sendmail continues to evolve and improve.

In Table 15-4, we provide a detailed description of categories that we consider useful for the system administrator who is trying to solve an email problem. Categories that are of interest only to sendmail developers are omitted. If you need to use a category not listed here, you must examine the source and find a category that will solve your unusual problem.

Table 15-4. Debugging switches by category

Category

§

Description

-d0.1

-d0.1 on page 542

Print version, compilation, and interface information.

-d0.4

-d0.4 on page 542

Our name and aliases

-d0.10

-d0.10 on page 543

Operating system defines

-d0.12

-d0.12 on page 544

Print library (libsm) defines.

-d0.13

-d0.13 on page 544

Print _FFR defines.

-d0.15

-d0.15 on page 544

Dump delivery agents.

-d0.20

-d0.20 on page 544

Print network address of each interface.

-d2.1

-d2.1 on page 544

End with finis( ).

-d2.9

-d2.9 on page 546

Show file descriptors with dumpfd( ).

-d4.80

-d4.80 on page 547

Trace enoughspace( ).

-d6.1

-d6.1 on page 547

Show failed mail.

-d8.1

-d8.1 on page 548

DNS name resolution.

-d8.2

-d8.2 on page 548

Call to getcanonname(3).

-d8.3

-d8.3 on page 549

Trace dropped local hostnames.

-d8.5

-d8.5 on page 549

Hostname being tried in getcanonname(3).

-d8.7

-d8.7 on page 549

Yes/no response to -d8.5.

-d8.8

-d8.8 on page 549

Resolver debugging.

-d11.1

-d11.1 on page 550

Trace delivery.

-d11.2

-d11.2 on page 552

Show the user-id running as during delivery.

-d12.1

-d12.1 on page 552

Show mapping of relative host.

-d13.1

-d13.1 on page 553

Show delivery.

-d20.1

-d20.1 on page 553

Show resolving delivery agent: parseaddr( ).

-d21.1

-d21.1 on page 554

Trace rewriting rules.

-d21.2

-d21.2 on page 554

Trace $& macros.

-d22.1

-d22.1 on page 554

Trace tokenizing an address: prescan( ).

-d22.11

-d22.11 on page 555

Show address before prescan.

-d22.12

-d22.12 on page 555

Show address after prescan.

-d25.1

-d25.1 on page 555

Trace “sendtolist”.

-d26.1

-d26.1 on page 555

Trace recipient queueing.

-d27.1

-d27.1 on page 556

Trace aliasing.

-d27.2

-d27.2 on page 557

Include file, self-reference, error on home.

-d27.3

-d27.3 on page 558

Forwarding path and alias wait.

-d27.4

-d27.4 on page 558

Print not safe.

-d27.5

-d27.5 on page 559

Trace aliasing with printaddr( ).

-d27.8

-d27.8 on page 559

Show setting up an alias map.

-d27.9

-d27.9 on page 559

Show user-id/group-id changes with :include: reads.

-d28.1

-d28.1 on page 560

Trace user database transactions.

-d29.1

-d29.1 on page 560

Special rewrite of local recipient.

-d29.4

-d29.4 on page 561

Trace fuzzy matching.

-d31.2

-d31.2 on page 561

Trace processing of headers.

-d34.1

-d34.1 on page 562

Watch header assembly for output.

-d34.11

-d34.11 on page 562

Trace header generation and skipping.

-d35.9

-d35.9 on page 563

Macro values defined.

-d37.1

-d37.1 on page 563

Trace setting of options.

-d37.8

-d37.8 on page 564

Trace adding of words to a class.

-d38.2

-d38.2 on page 564

Show database map opens and failures.

-d38.3

-d38.3 on page 565

Show passes.

-d38.4

-d38.4 on page 565

Show result of database map open.

-d38.9

-d38.9 on page 566

Trace database map closings and appends.

-d38.10

-d38.10 on page 567

Trace NIS search for @:@.

-d38.12

-d38.12 on page 568

Trace database map stores.

-d38.19

-d38.19 on page 568

Trace switched map finds.

-d38.20

-d38.20 on page 568

Trace database map lookups.

-d44.4

-d44.4 on page 569

Trace safefile( ).

-d44.5

-d44.5 on page 571

Trace writable( ).

-d48.2

-d48.2 on page 572

Trace calls to the check_ rule sets.

-d49.1

-d49.1 on page 572

Trace checkcompat( ).

-d52.1

-d52.1 on page 572

Show disconnect from controlling TTY.

-d52.100

-d52.100 on page 573

Prevent disconnect from controlling TTY.

-d60.1

-d60.1 on page 573

Trace database map lookups inside rewrite( ).

-d99.100

-d99.100 on page 574

Prevent backgrounding the daemon.

-d0.1

Print version, compilation, and interface information Debug command-line switch

The -d0.1 (a.k.a. -d0) debugging switch previously prevented sendmail from forking and detaching itself, but that function has been moved to the -d99.100 debugging switch. The -d0.1 debugging switch now just tells sendmail to print information about its version:

Version 8.14.1
Compiled with:   LOG MATCHGECOS NAMED_BIND NDBM NEWDB NETINET NETUNIX
                 NIS
=  ==  ==  ==  ==  ==  = SYSTEM IDENTITY (after readcf) =  ==  ==  ==  ==  ==  =
            (short domain name) $w = here
        (canonical domain name) $j = here.US.EDU
               (subdomain name) $m = US.EDU
                    (node name) $k = here
=  ==  ==  ==  ==  ==  ==  ==  ==  ==  ==  ==  ==  ==  ==  ==  ==  ==  ==  ==  ==  ==
 ==  ==  ==  ==  ==  ==  =

The Version is the current version of sendmail. Note that for Sun, the number can look like SMI-8.7.5 or 8.14.1+Sun.

The Compiled with: lists the compile-time definitions that were specified when sendmail was compiled. All the available definitions are listed in Table 3-2 on page 105.

The SYSTEM IDENTITY shows the value assigned to four important macros. The meaning of each macro is shown in Table 21-7 on page 798.

-d0.4

Our name and aliases Debug command-line switch

The -d0.4 debugging switch tells sendmail to print several lines of information in addition to those printed by -d0.1:

Version 8.14.1
Compiled with:   LOG MATCHGECOS NAMED_BIND NDBM NEWDB NETINET NETUNIX
                 NIS
canonical name: here.US.EDUadditional
UUCP nodename: hereadditional
        a.k.a.: [123.45.67.89]additional
=  ==  ==  ==  ==  ==  = SYSTEM IDENTITY (after readcf) =  ==  ==  ==  ==  ==  =
            (short domain name) $w = here
        (canonical domain name) $j = here.US.EDU
               (subdomain name) $m = US.EDU
                    (node name) $k = here
=  ==  ==  ==  ==  ==  ==  ==  ==  ==  ==  ==  ==  ==  ==  ==  ==  ==  ==  ==  ==  ==
 ==  ==  ==  ==  ==  ==  =

To find the canonical name of the local host, sendmail calls gethostname( ). If that call fails, the name localhost is used. The hostname is then looked up with the internal routine sm_gethostbyname( ), which gathers additional information (such as other names and addresses for the machine) and fixes several bugs in some operating system versions of the gethostby... routines. Next the canonical name for the local host is looked up. For operating systems that normally support switched services, the name is looked up as specified. For systems that specify switched services in the configuration file’s ServiceSwitchFile option (ServiceSwitchFile on page 1088), switched services are not used because the configuration file has not been read yet. (This canonicalization process can be traced with the -d61.10 debugging switch.) If the canonical name is found and that name contains a dot, sendmail saves the part of the name to the right of the leftmost dot as the domain name in the $m sendmail macro ($m on page 833). It also appends the part of the name to the left of the leftmost dot to the class w ($=w on page 876). If the canonical name doesn’t contain a dot, the $m macro is undefined, and the whole name is appended to the class $=w.

In addition, sendmail also sets the $k sendmail macro ($k on page 831) to be the correct UUCP name for the machine. It uses uname(3), if available, to find that name. Otherwise, it uses the same strategy as for class $=w.

Then sendmail lists any other name, or address (in square brackets), that it found. If it finds any, it prints the found item prefixed by an a.k.a.: and adds each found item to the class $=w. The aliases listed are only those found using gethostbyname(3). To see each entry as it is added to the class $=w, use the -d37.8 debugging switch.

Finally, sendmail scans the network hardware to find any other names associated with interfaces. If the ioctl(2) call to get that information fails, the -d0.4 debugging switch causes sendmail to print that failure:

SIOGIFCONF failed: ← reason here

If any are found, each is printed with an a.k.a.: prefix and added to the class $=w.

-d0.10

Operating system defines Debug command-line switch

The -d0.10 debugging switch causes sendmail to print all the operating system-specific definitions that were used to compile your specific version of sendmail. This output prints after the “Compiled with:” information described earlier:

OS Defines: HASFCHOWN HASFCHMOD HASFLOCK HASGETUSERSHELL
            HASINITGROUPS HASLSTAT HASNICE HASRANDOM HASRRESVPORT
            HASSETREUID HASSETSID HASSETVBUF HASUNAME HASWAITPID IDENTPROTO
            IP_SRCROUTE SAFENFSPATHCONF USE_DOUBLE_FORK
 Conf file: /etc/mail/submit.cf (default for MSP)
 Conf file: /etc/mail/sendmail.cf (default for MTA)
  Pid file: /var/run/sendmail.pid (default)

The OS Defines are described in Table 3-2 on page 105. Most are automatically determined during compilation; others are specified in Makefile.

A Kernel symbols: line can also print on your machine. If so, it will show the name of the file (such as /dev/ksyms) that is accessed to determine the load average. It is automatically defined correctly when conf.c is compiled.

The location of the configuration files and the process identifier file is defined in the Makefile and conf.h in the sendmail source (_PATH... on page 131).

-d0.12

Print library (libsm) defines Debug command-line switch

The -d0.12 debugging switch, in addition to the information displayed by the -d0.10 debugging switch, causes the list of the sendmail library (libsm) macros that were defined at compile time to be displayed:

libsm Defines: SM_CONF_BROKEN_STRTOD SM_CONF_GETOPT SM_CONF_SETITIMER
               SM_CONF_SHM SM_CONF_STDDEF_H SM_CONF_UID_GID SM_HEAP_CHECK

-d0.13

Print _FFR defines Debug command-line switch

The -d0.13 debugging switch, in addition to the information displayed by the -d0.12 debugging switch, causes the list of _FFR additions that were defined at compile time to be displayed:

FFR Defines: _FFR_NO_PIPE

Unless you define such additions yourself, chances are slim that any will be printed with this debugging switch.

-d0.15

Dump delivery agents Debug command-line switch

The -d0.15 debugging switch causes sendmail to display how it interpreted its delivery agent definitions. The clarity and completeness of the delivery agent information vary with the version of sendmail. See the =M rule-testing command (Show Delivery Agents with =M on page 307) for an example of this output.

-d0.20

Print network address of each interface Debug command-line switch

When sendmail scans the network hardware to find other names for the local host, it uses only those names that are new. Each new name was printed by the -d0.4 debugging switch described earlier. To see every name that sendmail finds, new and old alike, use the -d0.20 debugging switch:

128.32.201.55already found
127.0.0.1found new
        a.k.a.: [127.0.0.1]

-d2.1

End with finis( ) Debug command-line switch

Ordinarily, sendmail exits silently when it is done (unless an error causes an error message to be printed). The -d2.1 (a.k.a. -d2) debugging switch causes sendmail to print three useful values when it exits. The message it prints looks like this:

=  ==  =finis: stat number e_id=qid e_flags=flags

The number is the final value of the sendmail program’s global ExitStat variable. It is usually updated to contain the latest error value as defined in <sysexits.h >. See sendmail’s exit( ) Status on page 228 for a detailed description of the possible exit values.

The qid is either the queue identifier (such as g7PI04TK027759), or NOQUEUE if the message was never assigned an identifier (if it was never queued, for instance).

The flags is a hexadecimal representation of the possible envelope flags followed by a text representation of those flags in angle brackets with the leading EF_ removed. For example:

201003<OLDSTYLE,INQUEUE,GLOBALERRS,HAS_DF>

These are the envelope flags that were in effect with the current envelope when sendmail exited. The possible values are shown in Table 15-5.

Table 15-5. Hexadecimal envelope flags

Text

Hex

Description

EF_OLDSTYLE

0x00000001

Use spaces (not commas) in headers.

EF_INQUEUE

0x00000002

This message is fully queued.

EF_NO_BODY_RETN

0x00000004

Omit message body on error.

EF_CLRQUEUE

0x00000008

Disk copy is no longer needed.

EF_SENDRECEIPT

0x00000010

Send a return receipt.

EF_FATALERRS

0x00000020

Fatal errors occurred.

EF_DELETE_BCC

0x00000040

Delete Bcc: headers entirely.

EF_RESPONSE

0x00000080

This is an error or return receipt.

EF_RESENT

0x00000100

This message is being forwarded.

EF_VRFYONLY

0x00000200

Verify only (don’t expand aliases).

EF_WARNING

0x00000400

Warning message has been sent.

EF_QUEUERUN

0x00000800

This envelope is from the queue.

EF_GLOBALERRS

0x00001000

Treat errors as global.

EF_PM_NOTIFY

0x00002000

Send return mail to postmaster.

EF_METOO

0x00004000

Send to me too.

EF_LOGSENDER

0x00008000

Need to log the sender.

EF_NORECEIPT

0x00010000

Suppress all return receipts.

EF_HAS8BIT

0x00020000

Has at least one 8-bit character in body.

EF_NL_NOT_EOL

0x00040000

Don’t accept raw newline as end-of-line.

EF_CRLF_NOT_EOL

0x00080000

Don’t accept carriage-return/line-feed as end-of-line.

EF_RET_PARAM

0x00100000

SMTP RCPT command had RET argument.

EF_HAS_DF

0x00200000

Set when the df file is instantiated.

EF_IS_MIME

0x00400000

This is really a MIME message.

EF_DONT_MIME

0x00800000

This message is not MIME-able.

EF_DISCARD

0x01000000

Discard this message.

EF_TOOBIG

0x02000000

This message’s body is too big.

EF_SPLIT

0x04000000

This envelope has been split.

EF_UNSAFE

0x08000000

Message read from an untrusted source.

For example, if the message were fully queued and required a DSN return receipt, the flags would print as:

e_flags=12<INQUEUE,SENDRECEIPT>

Note that this line of output is also produced by the -d13.1, -d40.3, and -d50.1 debugging switches but under different circumstances.

-d2.9

Show file descriptors with dumpfd( ) Debug command-line switch

The -d2.9 debugging switch tells sendmail to display the properties of each open file descriptor. That output is produced by the dumpfd( ) routine, and each line of output is for a single file descriptor:

number: fl=flags mode=mode type stats

Here, the number is the count of the open file descriptor. Note that descriptors 0, 1, and 2 are usually tied to the standard input, output, and error output, respectively.

The flags is a hexadecimal representation of the state flags associated with a file descriptor. F_GETFL is used with ioctl(2) to fetch each, and all are described in <sys/fcntl.h> on most systems.

The mode is printed in octal and is the st_mode associated with an fstat(2) of the file descriptor.

The type examines the file type portion of the st_mode and prints SOCK for a socket, CHR: for a character special device, BLK: for a block special device, FIFO: for a named pipe, DIR: for a directory, LNK: for a symbolic link, and nothing otherwise (e.g., nothing if it is a file).

The stats are printed for all but the socket. They look like this:

dev=major/minor ino=inum nlink=nlink u/gid=user-id/group-id size=bytes

Here the dev= shows the major and minor device numbers for the device that the file descriptor is associated with. The inum is the inode number on the disk (if there is one) and nlink is the number of hard links to the file on disk. The u/gid shows the user and group ownership associated with the file descriptor. The bytes is the number of bytes in a file, and zero for almost everything else.

For a socket, the stats part of each line looks like this:

[addr]/port-> host

Here, addr is the IP address (surrounded in square braces) of the local end of the socket. If the connection is of type AF_INET or AF_INET6, the port number of the connection is also shown as /port. The host is the hostname, as returned by getpeername(3), of the connecting host. If any of these cannot be found, the error string associated with errno is printed parenthetically in its place.

The -d7.9, -d40.9, and -d46.9 debugging switches also print a line such as this for specific file descriptors. Also, if sendmail is run with the -d10.100 switch, or if sendmail fails to open a tf queue file (The Temporary qf Rewrite Image: tf on page 400) or if sendmail exited because of too many open files, it will syslog all its open file descriptors within this format.

-d4.80

Trace enoughspace( ) Debug command-line switch

The MinFreeBlocks option (MinFreeBlocks on page 1057) defines the minimum number of disk blocks that must be reserved on the queue disk. If an incoming SMTP message will fill the disk beyond this minimum, the message is rejected.

The -d4.80 debugging switch[225] traces the enoughspace( ) routine in conf.c. That routine examines the disk space and prints the following if the MinFreeBlocks option (MinFreeBlocks on page 1057) was less than or equal to zero, or if the message’s size is less than or equal to zero:

enoughdiskspace: no threshold

-d6.1

Show failed mail Debug command-line switch

Mail can fail for a wide variety of reasons. The way that sendmail handles errors is determined by the setting of the ErrorMode option (ErrorMode on page 1028) in the configuration file. The -d6.1 (a.k.a. -d6) debugging switch causes sendmail to print the error-handling mode that is in effect at the time it first begins to handle failed mail:

savemail, errorMode = char, id = qid, ExitStat = errornum
e_from= ← output of printaddr(  ) here (§15.3 on page 533)

Here, char is either p for print errors; m for mail-back errors; w for write-back errors; e for special Berknet processing; or q for “don’t print anything” (all of which are described under the ErrorMode option in ErrorMode on page 1028). The qid is the queue identifier (such as g7PEf0Bv027517). The errornum is the number of the error that caused the message to fail (as defined in <sysexits.h>). And e_from= uses printaddr( ) to print details about the sender’s address.

If the error-processing mode is m (for mail back) and the -d6.1 debugging switch is in effect, sendmail prints details about how the message is being returned to the sender:

***Return To Sender: msg=reason, depth=number, e=addr, returnq=
 ← output of printaddr(  ) here (§15.3 on page 533)

Here, reason is a quoted string of text that explains why the mail failed. This can be an SMTP reply string. The number is zero for normal delivery and one for error delivery. The addr is the location in memory of the information about the current envelope. Finally, sendmail calls printaddr( ) to print the details of the queue of recipients (returnq=) for the current message.

-d8.1

DNS name resolution Debug command-line switch

Name resolution is the process of determining a machine’s IP address based on its fully qualified domain name. This is done by using the Domain Name System (DNS). The process that sendmail uses to resolve a name is described in How sendmail Uses DNS on page 325.

When sendmail finds that a hostname is really an MX record, it attempts to look up the address (which can be an A or AAAA record) for the host that handles mail receipt. That request can fail for a variety of reasons. If the -d8.1 (a.k.a. -d8) debugging switch is specified, sendmail produces the following message:

getmxrr: res_search(host) failed (errno=errornum, h_errno=herrornum
)

Here, host is the hostname that was looked up, errornum is the system error number (if any) from <errno.h>, and herrornum is the resolver-specific error number from <netdb.h>, as shown in Table 15-6.

Table 15-6. Resolver errors from <netdb.h>

Value

Mnemonic

Description

−1

NETDB_INTERNAL

Error in the lookup code, see errno=

0

NETDB_SUCCESS

Success

1

HOST_NOT_FOUND

Host not found

2

TRY_AGAIN

Temporary DNS server failure

3

NO_RECOVERY

Nonrecoverable errors and refusals

4

NO_DATA

Valid name but no record of requested type

-d8.2

Call to getcanonname(3) Debug command-line switch

The routine dns_getcanonname( ) in domain.c of the sendmail source converts a hostname to a fully qualified domain name. This routine is called only if DNS is used to look up hostnames, as determined by the ResolverOptions option (ResolverOptions on page 1080) and the ServiceSwitchFile option (ServiceSwitchFile on page 1088). If it is, dns_getcanonname( ) can be called from three places: during startup to get the values for $w, $j, and $m (-d0.4 on page 542); when a host is looked up via the $[ and $] canonify operators (Canonicalize Hostname: $[ and $] on page 668); or when a host is looked up using the host database map (host on page 910).

The -d8.2 debugging switch shows the hostname before it is fully qualified with this call:

dns_getcanonname(host, flag)

If the flag is nonzero, calls to the getmxrr( ) routine (which looks up MX records) are also traced. On entry to that routine, sendmail will print:

getmxrr(host, droplocalhost=bool)

The host is the hostname whose MX records are being looked up. The bool, if nonzero, means that all MX records that are less preferred than the local host (as determined by $=w) will be discarded. If zero, they will be retained.

The -d8.2 debugging switch also causes sendmail to show the result of processing the ResolverOptions option’s settings (ResolverOptions on page 1080) while reading the configuration file:

_res.options = hex, HasWildcardMX = 1 or 0

The hex is a hexadecimal representation of the state structure’s options variable as described in <resolv.h>. The value of HasWildcardMX is determined by its prefix (+ or ) when listed with the ResolverOptions option.

-d8.3

Trace dropped local hostnames Debug command-line switch

If a hostname is dropped because bool (above) is nonzero, the -d8.3 switch causes sendmail to print the following:

found localhost (host) in MX list, pref=pref

The host is the hostname that is being dropped. The pref is the numerical preference associated with the MX record.

-d8.5

Hostname being tried in getcanonname(3) Debug command-line switch

The -d8.5 debugging switch causes the getcanonname(3) routine to print the host name it is trying to fully qualify. It shows the name with the local domain appended, without the local domain appended, and at each step in between. Each try is printed as:

dns_getcanonname: trying host.domain (type)

Here, the type is the type of lookup and is either A, AAAA, or MX. (Prior to V8.12, the type could also include ANY.)

-d8.7

Yes/no response to -d8.5 Debug command-line switch

The -d8.7 debugging switch causes sendmail to print a yes or no response to each of the “trying” lines printed by −8.5. “Yes” means that the host could successfully be fully canonicalized. A yes answer prints just this:

YES

If the host could not be canonicalized, a more complex answer is printed:

NO: errno=errornum, h_errno=herrornum

The errornum is the system error number (if any) from <errno.h>, and herrornum is the resolver-specific error from <netdb.h>, as shown in Table 15-6.

-d8.8

Resolver debugging Debug command-line switch

The -d8.8 debugging switch causes the resolver library to be put into debugging mode (if that mode was included when that library was compiled). The ResolverOptions option (ResolverOptions on page 1080) +DEBUG also turns on this debugging mode. But be aware that turning on +DEBUG will cause a large number of screens full of output to be produced by the resolver library for every DNS lookup.

If the name server returns an answer to an MX lookup, and if the answer is not an MX record or an error, sendmail will skip that host. The -d8.8 debugging switch (or the resolver library being in debug mode) then causes sendmail to print the following:

unexpected answer type wrongtype, size bytes

The wrongtype is an integer that can be found in <arpa/nameser.h >.

-d11.1

Trace delivery Debug command-line switch

The -d11.1 (a.k.a. -d11) debugging switch is used to trace message delivery. It must be run with the -v command-line switch, or no output will be produced.

First, for each delivery agent the following is printed:

openmailer: argv

Here, argv is the A= array for the delivery agent, with macros expanded and printed.

Second, the status of remote hosts is cached internally. Before connecting to a remote host, sendmail checks its cache to see whether that host is down. If it is, it skips connecting to that host. If the -d11.1 debugging switch is also specified, the status of the down host is printed as:

openmailer: output of mci_dump(  ) here

The output of mci_dump( ) looks like this:

MCI@memaddr: flags=mci_flags<flag,flag,...>,
errno=mci_errno, herrno=mci_herrno, exitstat=mci_exitstat, state=mci_state,
     pid=mci_pid,
maxsize=mci_maxsize, phase=mci_phase, mailer=mci_mailer,
status=mci_status, rstatus=mci+rstatus,
host=mci_host, lastuse=mci_lastuse

The meaning of each mci_ item in this output is described in Table 15-7.

Table 15-7. The meaning of the MCI structure items

Name

What prints

memaddr

The address in memory of this C-language structure

mci_flags

The flag bits in hexadecimal (see Table 15-8)

mci_errno

The error number of the last connection

mci_herrno

The DNS h_errno of the last lookup

mci_exitstat

The <sysexits.h> exit status of the last connection

mci_state

The current SMTP state

mci_maxsize

The maximum size message the host will accept

mci_pid

The PID of the child process

mci_phase

SMTP phase (string) such as “client greeting” (or NULL)

mci_mailer

The (text) name of the delivery agent (or NULL)

mci_status

The DSN status to be added to the address (or NULL)

mci_rstatus

The SMTP status to be added to the address (or NULL)

mci_host

The host’s name (or NULL)

mci_lastuse

Last usage time in ctime(3) format

Table 15-8 shows what the individual flag bits in mci_flags mean, and the human-readable flags text that corresponds to each bit. Those text items are shown with the leading source MCIF_ prefix removed.

Table 15-8. The meaning of mci_flags hexadecimal values

Name printed

Hex value

Meaning

VALID

0x00000001

This entry is valid.

TEMP

0x00000002

Don’t cache this connection (prior to V8.12).

CACHED

0x00000004

This connection is currently in open cache.

ESMTP

0x00000008

This host speaks ESMTP.

EXPN

0x00000010

EXPN command supported.

SIZE

0x00000020

SIZE option supported.

8BITMIME

0x00000040

BODY=8BITMIME supported.

7BIT

0x00000080

Strip this message to 7 bits.

MULTSTAT

0x00000100

MAIL11V3: handles MULT status (prior to V8.12).

INHEADER

0x00000200

Currently outputting header.

CVT8TO7

0x00000400

Convert from 8 to 7 bits.

DSN

0x00000800

DSN extension supported.

8BITOK

0x00001000

OK to send 8-bit characters.

CVT7TO8

0x00002000

Convert from 7 to 8 bits.

INMIME

0x00004000

Currently reading MIME header.

AUTH

0x00008000

ESMTP AUTH= is supported (V8.10 and above).

AUTHACT

0x00010000

SASL (AUTH) is active (V8.10 and above).

ENHSTAT

0x00020000

ENHANCEDSTATUSCODES SMTP extension supported (V8.10 and above).

PIPELINED

0x00040000

PIPELINING SMTP extension supported (V8.12 and above).

TLS

0x00100000

STARTTLS SMTP extension supported (V8.12 and above).

TLSACT

0x00200000

STARTTLS is active (V8.12 and above).

DLVR_BY

0x00400000

DELIVERBY SMTP extension supported (V8.12 and above).

HELO

0x00800000

Sending sendmail used HELO, so ignore extensions (V8.12 and above).

ONLY_EHLO

0x10000000

Use only EHLO when establishing a connection (V8.12 and above).

After checking to see whether the host is down, sendmail attempts to connect to it for network SMTP mail. If that connect fails, the -d11.1 debugging switch causes the following to be printed:

openmailer: makeconnection => stat=exitstatus, errno=errno

Here, exitstatus is a numerical representation of the reason for the failure, as documented in <sysexits.h>, and errno is the system-level reason for the error, as documented in <errno.h>.

Other errors, such as failure to establish a pipe(2), or failure to fork(2), cause the following to be printed:

openmailer: NULL

This message (although it contains no information) signals that a more descriptive error message was logged with syslog(3) (Log with syslog on page 513).

-d11.2

Show the user-id running as during delivery Debug command-line switch

To perform delivery, sendmail often has to set its uid to something other than root’s. The logic behind that process is described in Delivery to Files on page 466. The -d11.2 debugging switch tells sendmail to print the real and effective user-ids that it is running under during delivery:

openmailer: running as r/euid=real-user-id/effective-user-id

Also, the -d11.2 debugging switch causes sendmail to print any error response that might be produced by a delivery agent:

giveresponse: stat=status, e->e_message=what

Here, status is the number of the error that caused delivery to fail (or succeed if it is 0) as defined in <sysexits.h>. The what is either the error message produced by the delivery agent, or <NULL> if the delivery agent was silent.

-d12.1

Show mapping of relative host Debug command-line switch

In the SMTP RCPT command, sendmail is required to express the recipient’s address relative to the local host. For domain addresses, this simply means that the address should be RFC2821-compliant.

The -d12.1 (a.k.a. -d12) debugging switch causes sendmail to print the address as it appeared before it was made relative:

remotename(addr)

If the addr is for the sender or recipient and is being processed from a queue file, nothing more is printed, and the addr is processed by canonify rule set 3. If the delivery agent for the recipient has the F=C flag set (F=C on page 768) and the recipient address lacks a domain part, the domain of the sender is appended, and the result is processed by the canonify rule set 3 again. Sender/recipient-specific rule sets are then applied (1 and S= for the sender, or 2 and R= for the recipient). Next, the final rule set 4 is applied, and any sendmail macros in the result are expanded. Finally, the fully qualified and relative address is printed as:

remotename => `addr'

-d13.1

Show delivery Debug command-line switch

The -d13.1 (a.k.a. -d13) debugging switch causes sendmail to display information about the recipients of each mail message as it is being delivered. The -d13.1 debugging switch tells sendmail to print the mode of delivery and then the recipient information:

SENDALL: mode dmode, id=qid, e_from output of printaddr(  ) here (§15.3 on page
533)
        e_flags = envelope flags here
        sendqueue:
output of printaddr(  ) here (§15.3 on page 533)

Here, dmode is one of the delivery modes shown in Table 15-9. The qid is the queue message identifier (such as g7PI04TK027759). The address of the sender (e_from) is dumped by using the printaddr( ) routine. Then the envelope flags (e_flags) are dumped as described in Table 15-5 on page 545. Next, information about all the recipients (sendqueue:) is printed by using the printaddr( ) routine.

Table 15-9. Delivery modes used by sendall( )

Mode

Description

b

Deliver in background

d

Defer, queue without DNS lookups

i

Interactive delivery

q

Queue, don’t deliver

v

Verify only (used internally)

Finally, the -d13.1 debugging switch causes sendmail to print a message every time it splits an envelope in two:

sendall: split orig into new

Here, orig is the original queue message identifier for the original envelope (such as g7PKuBWE027877) and new is the identifier for the new envelope, the near identical clone of the first. Envelopes need to split if they have different owners.

-d20.1

Show resolving delivery agent: parseaddr( ) Debug command-line switch

The -d20.1 (a.k.a. -d20) debugging switch causes sendmail to print each recipient address before it is rewritten by the canonify rule set 3 and the parse rule set 0:

--parseaddr(addr)

Here, addr is the recipient address before it is rewritten and before any aliasing has been performed on it.

The -d20.1 debugging switch also causes sendmail to print information about problems that might exist in recipient addresses. If an address contains any control or whitespace character that is not an isspace(3) character, sendmail prints the following message and skips that address:

parseaddr-->bad address

If an address is empty (that is, if it is composed entirely of an RFC2822-style comment), sendmail prints the following and skips that address:

parseaddr-->NULL

After the recipient address has been rewritten by the canonify rule set 3 and the parse rule set 0, and if a delivery agent was successfully selected, sendmail prints the result using the printaddr( ) routine.

-d21.1

Trace rewriting rules Debug command-line switch

The -d21.1 (a.k.a. -d21) debugging switch causes sendmail to print each step that it takes in rewriting addresses with rules. The -d21.1 debugging switch causes output to be produced that is identical to the output produced by the -bt command-line switch (Overview on page 299):

rewrite: rule set name or number      input: address
rewrite: rule set name or number    returns: address

First, the address (workspace) is displayed for the rule set whose name or number is shown before rewriting, and second, the address is shown after rewriting.

Because rules are recursive by nature, they can sometimes cause infinite loops (Rewrite Once Prefix: $: on page 662). When a rule loops more than 100 times, the following error is issued:

Infinite loop in rule set name or number, rule rule number

If the -d21.1 debugging switch was also invoked, the preceding error is followed by:

workspace: state of rewritten address, so far, is shown here

-d21.2

Trace $& macros Debug command-line switch

The -d21.2 debugging switch tells sendmail to show the current value of any deferred-expansion macro (one that was declared with the $& prefix). Each such macro that is encountered in processing a rule prints as:

rewrite: LHS $&char => "value"
rewrite: RHS $&char => "value"
rewrite: LHS $&name => "value"   ← V8.7 and above
rewrite: RHS $&name => "value"   ← V8.7 and above

The char is the single-character name of the macro, the name is either a multicharacter macro name or a single-character name, and the value is its current value. If that particular macro lacks a value, it will print as (NULL). The LHS refers to the lefthand side of the rule, and the RHS corresponds to the righthand side. Deferred-expansion macros are described in Use Value As Is with $& on page 793.

-d22.1

Trace tokenizing an address: prescan( ) Debug command-line switch

Processing of rules requires that all addresses be divided into tokens. The -d22.1 (a.k.a. -d22) debugging switch causes sendmail to print the various steps it takes in tokenizing an address.

In addition to tokenizing, the prescan( ) routine also normalizes addresses. That is, it removes RFC2822-style comments and recognizes quoted strings. Be aware that rules are also viewed as addresses and processed by prescan( ) when the configuration file is being read.

The -d22.1 debugging switch tells sendmail to complain if the first token in the address it is parsing turns out to be nothing:

prescan: null leading token

This can happen if an address (or rule) contains only RFC2822-style comments in parentheses.

-d22.11

Show address before prescan Debug command-line switch

The -d22.11 debugging switch causes the address to be printed as it appears before any tokenizing or normalization:

prescan: address

-d22.12

Show address after prescan Debug command-line switch

The -d22.12 debugging switch causes the address to be printed as it appears after all tokenizing and normalization:

prescan=  => address

-d25.1

Trace “sendtolist” Debug command-line switch

Each recipient address for a mail message is added one by one to an internal list of recipients. The -d25.1 (a.k.a. -d25) debugging switch causes sendmail to print each address as it is added to this list:

sendto: list
   ctladdr= output of printaddr( ) here (§15.3 on page 533)

After each is added, those that have selected a delivery agent with the F=A (F=A on page 767) and F=w (F=w on page 781) flags set are further processed by aliasing and by reading the user’s ~/.forward file. Each new address that results from this processing is added to the list, and any duplicates are discarded.

-d26.1

Trace recipient queueing Debug command-line switch

The -d26.1 (a.k.a. -d26) debugging switch causes sendmail to print the addresses of recipients as they are added to the send queue, which is an internal list of addresses that sendmail uses to sort and remove duplicates from the recipient addresses for a mail message.

On entry to the recipient( ) routine, the -d26.1 debugging switch causes sendmail to print the raw address (as it appears before adding it to the send queue):

recipient (level): output of printaddr(  ) here  (§15.3 on page 533)

An address can be the result of alias expansion. Because the process of aliasing (including :include: and .forward files) can be recursive, it is possible to get too many alias expansions. The level shows the number of alias expansions so far. If that number exceeds the value set by the MaxAliasRecursion option (MaxAliasRecursion on page 1044), sendmail issues this warning:

aliasing/forwarding loop broken (level aliases deep; maximum max)

Next, sendmail compares the new address to others that are already in the send queue. If it finds a duplicate, it prints the following message and skips the new address:

addr in sendq: output of printaddr(  ) here (§15.3 on page 533)

Here, addr is the duplicate address. Information about that address is produced with the printaddr( ) routine.

-d27.1

Trace aliasing Debug command-line switch

The -d27.1 (a.k.a. -d27) debugging switch causes sendmail to print each step it takes when processing local addresses through aliasing. First, sendmail prints the addresses being aliased:

alias(addr)

Here, addr is the address (usually a local username) that is about to be aliased. Note that it can already be the result of previous aliasing. If the addr can be aliased, its transformation is printed as:

addr (host, user) aliased to newaddr

Here, addr is the address before aliasing, and the newaddr is the new address that resulted from successful aliasing. The host and user are the hostname and username from the recipient part of the envelope. If the addr cannot be aliased, nothing is printed.

During initialization, if the aliases database cannot be opened, the -d27.1 debugging switch causes sendmail to print:

Can't open aliasfile

Here, aliasfile is the full pathname of the aliases(5) file, as declared by the AliasFile option (AliasFile on page 970) or implied with the service-switch file set by the ServiceSwitchFile option (ServiceSwitchFile on page 1088).

If the failure was due to a faulty map declaration, sendmail logs the following error:

setalias: unknown alias class dbtype

If the map is not allowed to provide alias services, sendmail logs this error:

setalias: map class dbtype can't handle aliases

If sendmail is trying to create a database file and it can’t (usually when it is run with the -bi command-line switch or run as newaliases), the -d27.1 debugging switch causes the following error to be printed:

Can't create database for filename: reason here

A self-destructive alias can cause a dangerous loop to occur. For example, the following two aliases can lead to a loop on the host mailhost:

jake:           Jake_Bair
Jake_Bair:      jake@mailhost

The -d27.1 debugging switch causes the following message to be printed when sendmail tests an address to see whether it loops:

self_reference(addr)
        ... no self ref                     ← if it didn't loop
        ... cannot break loop for "addr"if it's unbreakable

An alias loop is unbreakable if no local username can be found in the list of aliases.

The -d27.1 debugging switch also causes sendmail to print a warning if it cannot open an alias file for rebuilding (the AutoRebuildAliases option, AutoRebuildAliases on page 978):

Can't open file:  reason here
newaliases: cannot open file:  reason here

Here, the error might be caused by the file simply not existing (as would be the case if it was NFS-mounted on a down host) or an I/O error (as would be the case if it was a bad disk):

warning: cannot lock file:  reason here

Failure to lock can be caused by system errors or by the file being read-only. Note that maintaining an aliases file under revision control can cause a read-only copy to exist, resulting in the following error:

Can't create database for file:  reason here
Cannot create database for alias file file

This error indicates that the output file (the dbm(3) or db(3) file) could not be created or written.

The -d27.1 debugging switch also causes sendmail to print the following message when it is attempting to read the user’s ~/.forward file:

forward(user)

If the user has no home directory listed in the passwd(5) file, sendmail issues the following message with a syslog(3) level of LOG_CRIT:

forward: no home

-d27.2

Include file, self reference, error on home Debug command-line switch

The -d27.2 debugging switch causes each :include: and ~/.forward file name to be printed before each is opened for reading:

include(file)

The -d27.2 debugging switch also causes additional information to be printed for the alias loop check described earlier:

self_reference(addr)
        ... getpwnam(user)...found      ← if in passwd file
        ... getpwnam(user)...failed     ← otherwise

The -d27.2 debugging switch also causes sendmail to print a message every time it sleeps while waiting for the aliases database to be rebuilt:

aliaswait: sleeping for secs seconds

Also, when processing the ~/.forward file, sendmail might experience a temporary inability to read it (such as when an NFS server is down). In that case the -d27.2 debugging switch causes the following message to be printed:

forward: transient error on home

Here the message will be queued and tried again later.

-d27.3

Forwarding path and alias wait Debug command-line switch

The -d27.3 debugging switch causes each path for a possible ~/.forward file to be printed before it is tried:

forward: trying file

Here, file is each file in the path of files declared by the ForwardPath option (ForwardPath on page 1034).

The -d27.3 debugging switch also causes sendmail to trace its wait for another alias rebuild to complete (Rebuild the Alias Database on page 478). First sendmail prints the database type (such as hash) and filename for which it will wait:

aliaswait(dbtype:file)

If the database is not rebuildable (as would be the case with a network database type, such as nis, nis+, or hesiod), the -d27.3 debugging switch causes the following to be printed:

aliaswait: not rebuildable

If the file specified doesn’t exist, the -d27.3 debugging switch prints:

aliaswait: no source file

The -d27.3 debugging switch also causes sendmail to print an error message if there was a read error while processing an :include: or ~/.forward file:

include: read error: reason here

-d27.4

Print not safe Debug command-line switch

A ~/.forward file must be owned by the user or by root. If it is not, it is considered unsafe, and sendmail ignores it. The -d27.4 debugging switch causes sendmail to print a message describing any such file it finds unsafe:

include: not safe (uid=user-id)

Note that a file is considered unsafe if, among other things, it lacks all read permissions.

The -d27.4 debugging switch also causes sendmail to print information about an :include: file beyond that printed with -d27.2:

include(file)                                ← printed with -d27.2
   ruid=real-user-id euid=effective-user-idprinted with -d27.4

This shows the real user-id (the ruid=) and effective user-id (the euid=) of the currently running sendmail.

The -d27.4 debugging switch causes sendmail to print an error if an :include: or ~/.forward file cannot be opened for reading:

include: open: reason here

-d27.5

Trace aliasing with printaddr( ) Debug command-line switch

The -d27.5 debugging switch tells sendmail to print several addresses with printaddr( ) (Interpret the Output on page 533) as each one is handled.

When an address is aliased to another, the original needs to be marked as one that shouldn’t be delivered. The QS_DONTSEND here means just that:

alias: QS_DONTSEND output of printaddr(  ) here (§15.3 on page 533)

If there was a self-reference, the retained address is printed like this:

sendtolist: QS_SELFREF output of printaddr(  ) here (§15.3 on page 533)

If the original (before the test for a self-reference) is not the same as the retained address, the original must be marked for nondelivery:

sendtolist: QS_DONTSEND output of printaddr(  ) here (§15.3 on page 533)

If an address resulted from an :include: or ~/.forward file, it will have a controlling user associated with it. That controlling user’s address needs to be marked for nondelivery:

include: QS_DONTSEND output of printaddr(  ) here (§15.3 on page 533)

-d27.8

Show setting up an alias map Debug command-line switch

The -d27.8 debugging switch tells sendmail to print the string passed to its internal setalias( ) routine:

setalias(what)

Here, what is one of the items listed with the AliasFile option (AliasFile on page 970) such as /etc/mail/aliases, or implied with the service-switch file and the ServiceSwitchFile option (ServiceSwitchFile on page 1088).

-d27.9

Show user-id/group-id changes with :include: reads Debug command-line switch

The -d27.9 debugging switch causes sendmail to trace the setting and resetting of its user-id and group-id identities when processing :include: and ~/.forward files. First, an additional line is printed below the output of the -d27.2 and -d27.4 debugging switches:

include(file)                             ← printed with -d27.2
   ruid=real-user-id euid=effective-user-idprinted with -d27.4
include: old uid = real-user-id/effective-user-id

The second and third lines contain the same information. After the new line is printed, sendmail might or might not change its identity depending on the nature of a :include: or ~/.forward file and that file’s controlling user. Regardless of whether it changed, sendmail prints:

include: new uid = real-user-id/effective-user-id

After sendmail has finished processing an :include: or ~/.forward file, it resets its user-id and group-id back to their original values and displays the result:

include: reset uid = real-user-id/effective-user-id

-d28.1

Trace user database transactions Debug command-line switch

The sendmail program can be compiled to use the user database (userdb on page 942) by defining USERDB in the Makefile (USERDB on page 150). If an address is selected by the parse rule set 0 for delivery by a delivery agent with the F=l flag set, and if it remains un-aliased even if the F=A flag is set and if the F=5 (F=5 on page 764) delivery agent flag is set, it is looked up in the user database. The -d28.1 (a.k.a. -d28) debugging switch is used to watch the interaction between sendmail and the user database:

udbexpand(addr)

Here, addr is the address being looked up.

The sender is looked up in a similar fashion. The intent in this case is to correct information such as the return address:

udbmatch(login, what)

Here, login is the login name of the sender and what is the mailname for sender lookups. If the lookup is via hesiod, sendmail will print the same information, like this:

hes_udb_get(login, what)

If the sender is found in the database, sendmail prints:

udbmatch =  => login@defaulthost

Here, login can be a new login name. The defaulthost is either the sitewide host for all reply mail as defined in the user database, or the default destination host for a particular user.

In the event that a db(3)-style user database fails to open, the -d28.1 debugging switch displays the following error message:

dbopen(database): reason for failure here

-d29.1

Special rewrite of local recipient Debug command-line switch

With a level 2 or greater configuration file (see the V configuration command in The V Configuration Command on page 580), V8 sendmail passes the user part ($u) of local recipient addresses through the localaddr rule set 5 as a hook to select a new delivery agent. If the F=5 flag (F=5 on page 764) is set for the delivery agent, the localaddr rule set 5 is called after all aliasing (including the ~/.forward file). The -d29.1 (a.k.a. -d29) debugging switch causes the address to be printed as it appears before the localaddr rule set 5 rewrite:

maplocaluser: output of printaddr(  ) here (§15.3 on page 533)

Information about the address is printed with the printaddr( ) routine. The output of maplocaluser( ) becomes the input to recipient( ), so the result of rewriting can be seen by using the -d26.1 debugging switch (-d26.1 on page 555) in combination with this one.

-d29.4

Trace fuzzy matching Debug command-line switch

Fuzzy matching is the attempt to match a local recipient name to one of the names in the GECOS field of the passwd(5) file (or NIS map). The -d29.4 debugging switch causes the process of fuzzy matching to be traced:

finduser(name)

Here, name is an address in the form of a local user address, without the host part. The name is first looked up in the passwd(5) file on the assumption that it is a login name. If it is found, sendmail prints:

found (non-fuzzy)

If sendmail was compiled with hesiod support, all numeric login names will not work properly, resulting in the following:

failed (numeric input)

If the name is looked up and not found, the entire passwd(5) is searched to see whether name appears in any of the GECOS fields. This search is done only if MATCHGECOS (MATCHGECOS on page 120) was defined when sendmail was compiled and if the MatchGECOS option (MatchGECOS on page 1043) is true. If MATCHGECOS was undefined, the search ends and the not-found name causes the mail to bounce. If the MatchGECOS option is false, sendmail bounces the message and prints the following:

not found (fuzzy disabled)

If the MatchGECOS option is true, the GECOS fields are searched. But before the search starts, any underscore characters (and the character defined by the BlankSub option, BlankSub on page 980) that appear in name are converted to spaces. Then, in turn, each GECOS field has the full name extracted (everything following the first comma, semicolon, or percent is truncated off, including that character), and any "&" (ampersand) characters found are converted to the login name. The two are then compared in a case-insensitive fashion. If they are identical, sendmail prints:

fuzzy matches found GECOS field here

If all GECOS fields are compared and no match is found, sendmail bounces the message and prints the following:

no fuzzy match found

There is no debugging flag to watch each comparison.

-d31.2

Trace processing of headers Debug command-line switch

Header lines (Overview on page 1120) from the configuration file and from mail messages are processed by the chompheader( ) routine before they are included in any mail message. That routine parses each header line to save critical information, to check for validity, and to replace default values with new values.

The -d31.2 debugging switch[226] shows that sendmail is about to check whether it should replace a From: or Resent-From: header with the one defined by the H configuration command. If the header line is not read from the configuration file and if sendmail is not processing the queue, the following test is made:

comparing header from (header) against default (address or name)

The value of the From: or Resent-From: header is compared to the sender’s address and to the sender’s name. If it is the same as either one, the address is replaced.

-d34.1

Watch header assembly for output Debug command-line switch

When sendmail bounces a mail message, it needs to create headers that probably didn’t exist before. It uses the putheader( ) routine to create them. The -d34.1 (a.k.a. -d34) debugging switch causes sendmail to print the following on entry to that routine:

--- putheader, mailer = agent  ---

Here, agent is the symbolic name of the delivery agent that will deliver the bounced message.

-d34.11

Trace header generation and skipping Debug command-line switch

Each header line created for the bounced message is displayed with two leading spaces. For example:

--- putheader, mailer = *file* ---
  Return-Path: you

Then certain headers are excluded from the bounced mail message header. Those with the H_CTE flag set (H_CTE Header Flag (V8.7 and Later) on page 1140) and either the MCIF_CVT8TO7 or MCIF_INMIME mci flag set will have the text:

(skipped (content-transfer-encoding))

appended and that header will be skipped (excluded).

Any header that has both the H_CHECK and H_ACHECK flags set and doesn’t have identical delivery agent flags set for itself and its cached connection information will also be skipped:

(skipped)

All re-sent headers (those marked with H_RESENT) are also skipped:

(skipped (resent))

Return-receipt headers are also skipped:

(skipped (receipt))

If a Bcc: header (Bcc: on page 1152) is being skipped, this is printed:

(skipped -- bcc)

Finally, valueless headers are also skipped with this message:

(skipped -- null value)

Any headers that survive this skipping process are included in the eventually delivered bounced message. Note that MIME headers are not generated or displayed here.

-d35.9

Macro values defined Debug command-line switch

The -d35.9 debugging switch[227] causes sendmail to print each macro as it is defined. The output looks like this:

define(name as "value")

Here, the name is the macro’s name, and the value is the value (text) assigned to the macro. If the macro already has a value assigned to it, sendmail prints:

redefine(name as "value")

-d37.1

Trace setting of options Debug command-line switch

Options can be set on the command line or in the configuration file. The -d37.1 (a.k.a. -d37) debugging switch allows you to watch each option being defined. As each is processed, this message is first printed, without a trailing newline:

setoption: name (char).sub =val

Here, name is the option’s multicharacter name, char is its single-character equivalent (or a hexadecimal value if it is non-ASCII), and sub is the subvalue for that option if there was one. Finally, val is the value being given to that option. If the option has already been set from the command line and is thus prohibited from being set in the configuration file, sendmail prints:

(ignored)

A newline is then printed, and the job is done. If defining the option is permitted, sendmail next checks to see whether it is safe (Options That Are Safe on page 951). If it is not, sendmail prints:

(unsafe)

If it is unsafe, sendmail checks to see whether it should relinquish its current privileges. If so, it prints:

(Resetting uid)

A newline is then printed, and the option has been defined.

The -d37.1 debugging switch also shows the modifier flags set for each DaemonPortOptions option. For example, consider the following:

setoption DaemonPortOptions (O)=Name=MTA
Daemon MTA flags:
setoption DaemonPortOptions (O)=Port=587, Name=MSA, M=E
Daemon MSA flags: NOETRN

The first setting of the DaemonPortOptions option sets no modifier flags, so the line following it shows no flags. The second setting of the DaemonPortOptions option sets the M=E modifier flag. The line following it shows that flag means to disallow ETRN. See DaemonPortOptions on page 993 for the meaning of the various possible modifier flags.

-d37.8

Trace adding of words to a class Debug command-line switch

The adding of words to a class (C or F configuration commands) can be traced with the -d37.8 debugging switch. Each word is printed like this:

setclass(name, text)

The text is added to the class whose symbolic name is name. Class names can be single-character or multicharacter (Class Configuration Commands on page 854).

-d38.2

Show database map opens and failures Debug command-line switch

Most database maps are declared directly with the K configuration command (The K Configuration Command on page 882). Others are declared internally by sendmail, such as the host and alias maps. The -d38.2 debugging switch (there is no -d38.1 information) first shows database maps being initialized:

map_init(dbtype:name, file, pass)

Here, dbtype is one of the internal database types allowed by sendmail, such as host, and dequote (The K Configuration Command on page 882, the K configuration command). The name is either the name you gave to the database map with the K configuration command, or one assigned internally by sendmail (such as aliases.files). The file is either a literal NULL, or the name of the database file (such as /etc/mail/aliases). And pass is a flag that tells sendmail whether it should open the database, rebuild the database, or do neither.

Next, the -d38.2 debugging switch causes sendmail to show each database map as it is about to be opened. The output that is produced will look like one of the following lines:

bt_map_open(name, file, mode)
hash_map_open(name, file, mode)
hes_map_open(name, file, mode)
impl_map_open(name, file, mode)
ldap_map_open(name, mode)
ndbm_map_open(name, file, mode)
ni_map_open(name, file, mode)
nis_map_open(name, file, mode)
nisplus_map_open(name, file, mode)
stab_map_open(name, file, mode)
switch_map_open(name, file, mode)
text_map_open(name, file, mode)
user_map_open(name, mode)

In all of the previous lines, the mode is a decimal representation of the file permissions that are used during the open. The name prefixing each line corresponds to the database type. For example, impl corresponds to the implicit database type.

The -d38.2 debugging switch also causes sendmail to display the NIS domain that was used if one was specified for the nisplus database type:

nisplus_map_open(file): using domain ypdomain

The -d38.2 debugging switch also allows other silent errors to be printed about some open failures. Under NIS+, lookups are performed by named columns (as in the case of the password database, the columns are named passwd, shell, and so on):

nisplus_map_open(name): cannot find key column colname
nisplus_map_open(name): cannot find column colname

Text files that are used as maps must be declared with a filename that is an absolute path (begins with a / character, thus forming a fully qualified pathname), that exists, and that is a regular file. If there is a problem, one of the following is logged (even if -d38.2 is not specified):

text_map_open: filename required
text_map_open(file): filename must be fully qualified
text_map_open(name): cannot stat file
text_map_open(name): file is not a file

Text files should be syntactically correct. The delimiting character, char, will print either as a single character or as the phrase (whitespace). Note that the third line in the following example will be reported only when the -d38.2 debugging switch is used:

text_map_open(file): -k should specify a number, not badtext
text_map_open(file): -v should specify a number, not badtext
text_map_open(file): delimiter = char

-d38.3

Show passes Debug command-line switch

The sendmail program initializes maps in passes so that it can open a map for reading or rebuild. That is, pass 0 opens it for reading only, and passes 1 and 2 open it for updating. This gives sendmail the opportunity to detect optional maps. The -d38.3 debugging switch causes sendmail to print wrong pass every time it skips rebuilding because the pass is inappropriate:

map_init(dbtype:name, file, pass)from -d38.2
wrong pass

The -d38.3 debugging switch also causes sendmail to print a failure message if an implicit database type does not exist:

impl_map_open(name, file, mode)   ← from -d38.2
no map file

-d38.4

Show result of database map open Debug command-line switch

When rebuilding the aliases files, each database file is rebuilt even if its source file has not changed. The -d38.4 debugging switch shows the success or failure of each open:

map_init(dbtype:name, file, pass)  ← from -d38.2
     dbtype:name file  valid or  invalid

The status is valid if the open succeeded; otherwise, it is invalid.

The -d38.4 debugging switch also shows each map being looked up in a switch database type (switch on page 938):

switch_map_open(name, file, mode)  ← from -d38.2
        map_stack[index] = dbtype:name

If the name was not declared in a K configuration command, the following error is printed:

Switch map dbtype: unknown member map name

-d38.9

Trace database map closings and appends Debug command-line switch

The -d38.9 debugging switch traces map closures for maps that can be closed:

ndbm_map_close(name, file, flags)
db_map_close(name, file, flags)
impl_map_close(name, file, flags)
ph_map_close(name): pmap-ph_fastclose=num
prog_map_lookup(name) failed (errno) -- closing
seq_map_close(name)

Here, the name is either the name you gave to the map with the K configuration command, or one assigned internally by sendmail (such as aliases.files). The file is the filename on disk that contains the database. The flags describe the specific features of a map. They are printed in hexadecimal, and the meanings of the values printed are listed in Table 15-10.

Table 15-10. Flags describing properties of database maps

Hex

Text

Description

MF_VALID

0x00000001

This entry is valid.

MF_INCLNULL

0x00000002

Include null byte in key.

MF_OPTIONAL

0x00000004

Don’t complain if map is not found.

MF_NOFOLDCASE

0x00000008

Don’t fold case in keys.

MF_MATCHONLY

0x00000010

Only check for existence of the key.

MF_OPEN

0x00000020

This database is open.

MF_WRITABLE

0x00000040

Open for writing.

MF_ALIAS

0x00000080

This is an alias file.

MF_TRY0NULL

0x00000100

Try with no null byte.

MF_TRY1NULL

0x00000200

Try with the null byte.

MF_LOCKED

0x00000400

This map is currently locked.

MF_ALIASWAIT

0x00000800

Alias map in aliaswait state.

MF_IMPL_HASH

0x00001000

Implicit: underlying hash database.

MF_IMPL_NDBM

0x00002000

Implicit: underlying ndbm database.

MF_UNSAFEDB

0x00004000

This map is world-writable (prior to V8.12.1).

MF_APPEND

0x00008000

Append new entry on rebuild.

MF_KEEPQUOTES

0x00010000

Don’t dequote key before lookup.

MF_NODEFER

0x00020000

Don’t defer if map lookup fails (V8.8 and above).

MF_REGEX_NOT

0x00040000

Regular expression negation (V8.9 and above).

MF_DEFER

0x00080000

Don’t look up map in defer mode (V8.10 and above).

MF_SINGLEMATCH

0x00100000

Successful only if matches one key (V8.10 and above).

MF_FILECLASS

0x00400000

This is a file database type (V8.12 and above).

MF_OPENBOGUS

0x00800000

Open failed, don’t call map_close (V8.12 and above).

MF_CLOSING

0x01000000

This map is being closed (V8.12 and above).

In addition to tracing map closures, the -d38.9 debugging switch traces map appends allowed by the MF_APPEND flag (-A on page 886) as specified when the database is declared by the K configuration command:

ndbm_map_store append=new
db_map_store append=new

Here, new is the new value appended to the old. Because this property is used for alias files, the new and old values have a comma inserted between them.

-d38.10

Trace NIS search for @:@ Debug command-line switch

The NIS alias map needs to contain an @:@ entry to indicate that it is fully updated and ready for reading. But because HP-UX omits the @:@, it is useful only as a check to see whether the NIS map exists. The -d38.10 debugging switch causes the result of this check to be printed as:

nis_map_open: yp_match(@, domain, nisdb)

Here, domain is the NIS domain, and nisdb is usually mail.aliases (but it can be redefined in your configuration file; see AliasFile on page 970). If the database map is not marked as optional (-o on page 889), the following error will be printed:

Cannot bind to map nisdb in domain domain:  reason  here

The -d38.10 debugging switch also traces the NIS+ open’s check for a valid table:

nisplus_map_open: nisplusdb.domain is not a table

Essentially, this says that the NIS+ database map nisplusdb (in the domain shown) does not exist. The error is printed even if the -o (optional) database switch (-o on page 889) is present.

-d38.12

Trace database map stores Debug command-line switch

The -d38.12 debugging switch shows values being stored in maps that support updates:

db_map_store(name, key, value)
ndbm_map_store(name, key, value)
seq_map_store(name, key, value)

Here, the name is either the name you gave to the database map with the K configuration command, or a name assigned internally by sendmail (such as aliases.files). The key is the key for the new value that is being stored, and the value is the value being assigned to that key.

-d38.19

Trace switched map finds Debug command-line switch

A switched map is one that, either as the result of a service-switch file or because of sendmail’s internal logic, causes lookups to follow a select path. For example, Sun’s Solaris 2 nsswitch.conf might specify that aliases be looked up in the order files, then nis:

switch_map_open(name, file, mode)  ← from -d38.2
switch_map_find => nummaps
                dbtype
                ...

First the number of database maps found is printed with nummaps, and then the database type for each map found in the list is printed, such as files, or nis.

-d38.20

Trace database map lookups Debug command-line switch

The -d38.20 debugging switch traces many different map lookups. The getcanonname( ) routine looks up a hostname and tries to canonify it:

getcanonname(host), trying dbtype
getcanonname(host), found
getcanonname(host), failed, stat=error

Here, host is the hostname that is being looked up, and dbtype is one of files, nis, nisplus, dns, or netinfo. If the canonical name is not found, the error shows one of the errors listed in <sysexits.h>. The process of canonifying the name is handled by calling special subroutines based on the dbtype:

text_getcanonname(host)                 ← dbtype is files
nis_getcanonname(host)                  ← dbtype is nis
nisplus_getcanonname(host), qbuf=querydbtype is nisplus
dns_getcanonname(host, flag)              ← dbtype is dns, printed with -d8.2
ni_getcanonname(host)                   ← dbtype is netinfo

The nisplus_getcanonname( ) routine is far more verbose than the other. In addition to the preceding information, the -d38.20 switch also prints:

nisplus_getcanonname(host), got count entries, all but first ignored
nisplus_getcanonname(host), found in directory "nisdir"
nisplus_getcanonname(host), found result
nisplus_getcanonname(host), failed, status=nsistatus, nsw_stat=errno

The -d38.20 debugging switch also traces general lookups in various kinds of databases. Again note that nisplus is more verbose than the others:

ndbm_map_lookup(name, key)
db_map_lookup(name, key)
nis_map_lookup(name, key)
nisplus_map_lookup(name, key)
qbuf=query
nisplus_map_lookup(key), got count entries, additional entries ignored
nisplus_map_lookup(key), found value
nisplus_map_lookup(key), failed
hes_map_lookup(name, key)
ni_map_lookup(name, key)
stab_lookup(name, key)
impl_map_lookup(name, key)
user_map_lookup(name, key)
prog_map_lookup(name, key)
prog_map_lookup(name): empty answer
seq_map_lookup(name, key)

Here, the name is either the name you gave to the database map with the K configuration command, or one assigned internally by sendmail (such as aliases.files). The key is the item being looked up. The file is the pathname of the file that contains the database.

-d44.4

Trace safefile( ) Debug command-line switch

The V8 sendmail program tries to be extra careful about file permissions, and the key to checking them is the internal safefile( ) function. The -d44.4 debugging switch[228] prints the parameters passed to the safefile( ) function:

safefile(fname, uid=uid, gid=gid, flags=sff_flags, mode=wantmode)

Here, the file named fname is being checked to determine whether the user identified by the uid, with the group gid, is allowed to find or use the file. The range of checking is determined by the hexadecimal sff_flags, described in Table 15-11. Where a file’s permissions are required, the mode printed in wantmode will be used.

Table 15-11. safefile( ) access flags

Mnemonic

Hex flag

Description

SFF_ANYFILE

0x00000000

No special restrictions

SFF_MUSTOWN

0x00000001

User must own this file

SFF_NOSLINK

0x00000002

File cannot be a symbolic link

SFF_ROOTOK

0x00000004

OK for root to own this file

SFF_RUNASREALUID

0x00000008

If no controlling user, run as real user-id

SFF_NOPATHCHECK

0x00000010

Don’t bother checking directory path

SFF_SETUIDOK

0x00000020

Set-user-id files are OK.

SFF_CREAT

0x00000040

OK to create file if necessary

SFF_REGONLY

0x00000080

Regular files only

SFF_SAFEDIRPATH

0x00000100

No writable directories (also check owner)

SFF_NOHLINK

0x00000200

File cannot have hard links

SFF_NOWLINK

0x00000400

Links only in nonwritable directories

SFF_NOGWFILES

0x00000800

Disallow group-writable files

SFF_NOWWFILES

0x00001000

Disallow world-writable files

SFF_OPENASROOT

0x00002000

Open as root instead of real user

SFF_NOLOCK

0x00004000

Don’t lock the file

SFF_NOGRFILES

0x00008000

Disallow group-readable files

SFF_NOWRFILES

0x00010000

Disallow world-readable files

SFF_NOTEXCL

0x00020000

Creates don’t need to be exclusive

SFF_EXECOK

0x00040000

Executable files are OK

If both the SFF_NOPATHCHECK flag and the SFF_SAFEDIRPATH flags are clear (are 0), sendmail examines each component of the path leading to the file. If any component of the path is rejected, the -d44.4 debugging switch causes sendmail to print:

[dir fname]  reason for the rejection here

A path component can fail because stat(2) failed. If the user-id is 0 for root, a warning is logged if a component is found to be group- or world-writable. For example:

hash map "Alias0": unsafe map file /etc/mail/aliases.db: World-writable directory

For each component in the path, safefile( ) checks to verify that this user has permission to search the directory. If the SFF_ROOTOK flag is not set (is clear), root (user-id 0) access is special-cased in that all directory components must be world-searchable.

Otherwise, the path component is accepted if it is owned by the user-id and has the user search bit set, or if its group is the same as group-id and has the group search bit set. If NO_GROUP_SET is undefined when sendmail is compiled (NO_GROUP_SET on page 130) and the DontInitGroups option (DontInitGroups on page 1023) is not set, each group to which user-id belongs is also checked. Otherwise, the directory must be world-searchable.

If the fname could not be checked with stat(2), the -d44.4 debugging switch causes the reason to be printed:

reason for failure here

If the file does not exist, it might need to be created. If so, sendmail checks to be sure that the user-id has write permission. The result is printed with the -d44.4 debugging switch like this:

[final dir fname uid user-id mode wantmode ]  error  here

If the file exists and if symbolic links are supported, the file is rejected if it is a symbolic link and if the SFF_NOSLINK flag is set. If the -d44.4 debugging switch is specified, this error is printed:

[slink mode mode]    EPERM

If the SFF_REGONLY flag is set, the file must be a regular file. If it is not, it is rejected, and -d44.4 causes the following to be printed:

[non-reg mode mode]    EPERM

If wantmode has the write bits set, and the existing file has any execute bits set, the file is rejected and -d44.4 causes the following to be printed:

[exec bits mode]    EPERM

If the file has more than one link, the file is rejected and -d44.4 causes the following to be printed:

[link count nlinks]    EPERM

If the SFF_SETUIDOK flag is specified, if SUID_ROOT_FILES_OK (SUID_ROOT_FILES_OK on page 146) was defined when sendmail was compiled,[229] if the file exists, if it has the set-user-id bit set in the mode but no execute bits set in the mode, and if it is not owned by root, sendmail performs subsequent checks under the set-user-id and set-group-id identities of the existing file. A similar process occurs with the set-group-id bit. Sendmail then prints:

[uid new_uid, stat filemode, mode wantmode ]

If access is finally allowed, sendmail concludes with:

OK

Otherwise, it concludes with:

EACCES

-d44.5

Trace writable( ) Debug command-line switch

The -d44.5 debugging switch displays the values passed to sendmail’s internal writable( ) routine. This routine nearly duplicates the function of the access(3) call[230] but does it much more safely and allows checks to be made under the identity of the controlling user:

writable(fname, sff_flags)

Here, the fname is the full pathname of the file being checked. The sff_flags are documented in Table 15-11 earlier. Success or failure is described under -d44.4.

-d48.2

Trace calls to the check_ rule sets Debug command-line switch

Beginning with V8.8, sendmail calls rule sets whose names begin with check_ (The Local_check_ Rule Sets on page 252) to filter incoming and outgoing mail, to accept or reject connections, and to decide on actions, such as allowing STARTTSL. The -d48.2 debugging switch[231] can be used to display the workspace being passed to each such rule set:

rscheck(ruleset, left, right)

The ruleset is the name of the named rule set being called. If right is missing, it prints as NULL, and the workspace passed to the rule set is:

left

If right is present, the workspace is:

left $| right

Here, the $| in the workspace is the $| operator.

-d49.1

Trace checkcompat( ) Debug command-line switch

The checkcompat( ) routine inside conf.c can be tuned to solve many problems (see Appendix C on page 1248). The default -d49.1 (a.k.a. 49) debugging switch inside it prints the arguments that were passed to it:

checkcompat(to=recipient, from=sender)

When designing your own checkcompat( ), you should only use the -d49 category to trace it.

-d52.1

Show disconnect from controlling TTY Debug command-line switch

When sendmail runs as a daemon, it must disconnect itself from the terminal device that is used to run it. This prevents keyboard signals from killing it and prevents it from hanging (on a dial-in line waiting for carrier detect, for example).

The -d52.1 (a.k.a. -d52) debugging switch shows sendmail disconnecting from the controlling terminal device:

disconnect: In fd Out fd, e=addr

For both its input and output connections, the fd is a decimal representation of the file descriptor number. The addr is a hexadecimal representation of the address that contains the envelope information. If the LogLevel option (LogLevel on page 1040) is greater than 71, sendmail syslog(3)s the following message to show that it has disconnected:

in background, pid=pid

Here, pid is the process identification number of the child process (the daemon).

-d52.100

Prevent disconnect from controlling TTY Debug command-line switch

The -d52.100 debugging switch prevents sendmail from disconnecting from its controlling terminal device. To show that it is skipping the disconnect, it prints:

don't

This debugging switch is useful for debugging the daemon. Note that this -d52.100 prevents the detach but allows the daemon to fork(2). This differs from the behavior of the -d99.100 debugging switch (-d99.100 on page 574).

-d60.1

Trace database map lookups inside rewrite( ) Debug command-line switch

Rules defined by the R configuration command are rewritten by sendmail’s internal rewrite( ) subroutine. The $[ and $( lookup operators cause sendmail to look up keys in database maps.

If sendmail is running in deferred mode (DeliveryMode on page 1004), it might skip some database map lookups because they might take time to complete (as with DNS, NIS, etc.). The -d60.1 (a.k.a. -d60) debugging switch causes sendmail to print that it is skipping the lookup:

map_lookup(dbtype, key) => DEFERRED

Here, dbtype is the database map type, such as dequote or host. The key is the information being looked up.

If running in something other than deferred mode, sendmail performs the lookup. If the lookup fails (if key is not found), sendmail prints:

map_lookup(dbtype, key) => NOT FOUND (stat)

Here, stat is the number of the error that caused the failure. If it is 0, the lookup failed merely because the key was not found. Otherwise, it corresponds to the error numbers in <sysexits.h>. Then, if stat is the special value 75 (for EX_TEMPFAIL), sendmail also prints:

map_lookup(dbtype, key) tempfail: errno=err

Here, err is the error number that corresponds to the errors listed in <errno.h>.

If the key is successfully found, sendmail prints:

map_lookup(dbtype, key) => replacement  value here (stat)

Note that the replacement value will be whatever value was defined by the -a database switch (-a on page 887) when the K configuration command defined the database map.

-d99.100

Prevent backgrounding the daemon Debug command-line switch

The -d99.100 debugging switch[232] prevents the sendmail daemon from forking and putting itself into the background. This leaves the running daemon connected to your terminal so that you can see other debugging output. For example:

# /usr/sbin/sendmail -bd -d99.100 -d9.30

This allows you to watch the daemon perform RFC1413 identification queries when SMTP connections are made. See also -d52.100, which prevents sendmail from disconnecting from its controlling terminal device, or the -bD command-line switch (-bD on page 233), which does both.



[225] * No -d4.1 (a.k.a. -d4) information is available yet.

[226] * There is no -d31.1 information.

[227] * There is no -d35.1 information.

[228] * There is no -d44.1 debugging information.

[229] * Note that set-user-id root files are permitted if sendmail was compiled with SUID_ROOT_FILES_OK defined, but we highly recommend against that definition.

[230] It is more restrictive for root-owned files and can allow the set-user-id semantics needed for delivery to files.

[231] * There is no -d48.1 information.

[232] * There is no -d99.1 information available.