Sendmail 8.11 and earlier has a -d option which lets you turn on debug and trace code. Debug categories are integers from 0 to 99, with the sole exception of "ANSI", which is a named debug category.
The libsm debug package supports named debug categories. Debug category names have the form of C identifiers. For example, sm_trace_heap controls the output of trace messages from the sm heap package, while sm_check_heap controls the argument validity checking and memory leak detection features of the sm heap package.
In sendmail 8.12, the -d flag is generalized to support both the original style numeric categories, for backwards compatibility, and the new style named categories implemented by libsm. With this change, "-dANSI" is implemented using a libsm named debug category. You will be able to set a collection of named debug categories to the same activation level by specifying a glob pattern. For example,
For sendmail 9.x, I propose to drop support for numeric debug categories, and just use named debug categories.
#include <sm/debug.h> /* ** abstractions for printing trace messages */ void sm_dprintf(char *fmt, ...) void sm_dflush() void sm_debug_setfile(SM_FILE_T *) /* ** abstractions for setting and testing debug activation levels */ void sm_debug_addsettings(char *settings) void sm_debug_addsetting(char *pattern, int level) typedef struct sm_debug SM_DEBUG_T; SM_DEBUG_T dbg = SM_DEBUG_INITIALIZER("name", "@(#)$Debug: name - description $"); bool sm_debug_active(SM_DEBUG_T *debug, int level) int sm_debug_level(SM_DEBUG_T *debug) bool sm_debug_unknown(SM_DEBUG_T *debug)
Variable name | Category name | Meaning |
SmExpensiveAssert | sm_check_assert | enable expensive SM_ASSERT checking |
SmExpensiveRequire | sm_check_require | enable expensive SM_REQUIRE checking |
SmExpensiveEnsure | sm_check_ensure | enable expensive SM_ENSURE checking |
SmHeapTrace | sm_trace_heap | trace sm_{malloc,realloc,free} calls |
SmHeapCheck | sm_check_heap | enable checking and memory leak detection in sm_{malloc,realloc,free} |
There is no centralized table of category names that needs to be edited in order to add a new debug category. The sole purpose of the second argument to SM_DEBUG_INITIALIZER is to provide an easy way to find out what named debug categories are present in a sendmail binary. You can use:SM_DEBUG_T ANSI_debug = SM_DEBUG_INITIALIZER("ANSI", "@(#)$Debug: ANSI - enable reverse video in debug output $");
or:ident /usr/sbin/sendmail | grep Debug
what /usr/sbin/sendmail | grep Debug
This macro performs a function call only if the debug structure has an unknown activation level. All debug structures are in this state at the beginning of program execution, and after a call to sm_debug_addsetting.
is slightly less efficient than, but otherwise semantically equivalent tosm_debug_level(debug) >= level
sm_debug_active(debug, level)
The purpose of using sm_debug_unknown in the above example is to avoid performing the expensive initializations each time through the code. So it's a performance hack. A debug structure is in the "unknown" state at the beginning of program execution, and after a call to sm_debug_addsetting. A side effect of calling sm_debug_active is that the activation level becomes known.if (sm_debug_unknown(&FooDebug)) { if (sm_debug_active(&FooDebug, 1)) { ... perform some expensive data structure initializations ... in order to enable the "foo" debugging mechanism } else { ... disable the "foo" debugging mechanism } }
if (sm_debug_active(&BarDebug, 1)) sm_dprintf("bar: about to test tensile strength of bar %d\n", i);
We want to allow you to direct debug output to syslog. The current plan is to provide a standard interface for creating an SM_FILE_T object that writes to syslog.