debug.html revision 90792
190792Sgshapiro<html>
290792Sgshapiro<head>
390792Sgshapiro    <title>libsm : Debugging and Tracing</title>
490792Sgshapiro</head>
590792Sgshapiro<body>
690792Sgshapiro
790792Sgshapiro<a href="index.html">Back to libsm overview</a>
890792Sgshapiro
990792Sgshapiro<center>
1090792Sgshapiro    <h1> libsm : Debugging and Tracing </h1>
1190792Sgshapiro    <br> $Id: debug.html,v 1.8 2000/12/08 21:41:41 ca Exp $
1290792Sgshapiro</center>
1390792Sgshapiro
1490792Sgshapiro<h2> Introduction </h2>
1590792Sgshapiro
1690792SgshapiroThe debug and trace package provides abstractions for writing trace
1790792Sgshapiromessages, and abstractions for enabling and disabling debug and
1890792Sgshapirotrace code at run time.
1990792Sgshapiro
2090792Sgshapiro<p>
2190792SgshapiroSendmail 8.11 and earlier has a <tt>-d</tt> option which 
2290792Sgshapirolets you turn on debug and trace code.
2390792SgshapiroDebug categories are integers from 0 to 99, with the sole exception
2490792Sgshapiroof "ANSI", which is a named debug category.
2590792Sgshapiro
2690792Sgshapiro<p>
2790792SgshapiroThe libsm debug package supports named debug categories.
2890792SgshapiroDebug category names have the form of C identifiers.
2990792SgshapiroFor example, <tt>sm_trace_heap</tt> controls the output of trace
3090792Sgshapiromessages from the sm heap package, while <tt>sm_check_heap</tt>
3190792Sgshapirocontrols the argument validity checking and memory leak detection
3290792Sgshapirofeatures of the sm heap package.
3390792Sgshapiro
3490792Sgshapiro<p>
3590792SgshapiroIn sendmail 8.12, the <tt>-d</tt> flag is generalized
3690792Sgshapiroto support both the original style numeric categories, for backwards
3790792Sgshapirocompatibility, and the new style named categories implemented by libsm.
3890792SgshapiroWith this change,
3990792Sgshapiro"-dANSI" is implemented using a libsm named debug category.
4090792SgshapiroYou will be able to set a collection of named debug categories to
4190792Sgshapirothe same activation level by specifying a glob pattern.
4290792SgshapiroFor example,
4390792Sgshapiro<dl>
4490792Sgshapiro<dt>
4590792Sgshapiro    <tt> -dANSI </tt>
4690792Sgshapiro<dd>
4790792Sgshapiro    sets the named category "ANSI" to level 1,
4890792Sgshapiro<dt>
4990792Sgshapiro    <tt> -dfoo_*.3 </tt>
5090792Sgshapiro<dd>
5190792Sgshapiro    sets all named categories matching the glob pattern "foo_*" to level 3,
5290792Sgshapiro<dt>
5390792Sgshapiro    <tt> -d0-99.1 </tt>
5490792Sgshapiro<dd>
5590792Sgshapiro    sets the numeric categories 0 through 99 to level 1, and
5690792Sgshapiro<dt>
5790792Sgshapiro    <tt> -dANSI,foo_*.3,0-99.1 </tt>
5890792Sgshapiro<dd>
5990792Sgshapiro    does all of the above.
6090792Sgshapiro</dl>
6190792Sgshapiro
6290792Sgshapiro<p>
6390792SgshapiroFor sendmail 9.x, I propose to drop support for numeric debug categories,
6490792Sgshapiroand just use named debug categories.
6590792Sgshapiro
6690792Sgshapiro<h2> Synopsis </h2>
6790792Sgshapiro
6890792Sgshapiro<pre>
6990792Sgshapiro#include &lt;sm/debug.h&gt;
7090792Sgshapiro
7190792Sgshapiro/*
7290792Sgshapiro**  abstractions for printing trace messages
7390792Sgshapiro*/
7490792Sgshapirovoid sm_dprintf(char *fmt, ...)
7590792Sgshapirovoid sm_dflush()
7690792Sgshapirovoid sm_debug_setfile(SM_FILE_T *)
7790792Sgshapiro
7890792Sgshapiro/*
7990792Sgshapiro**  abstractions for setting and testing debug activation levels
8090792Sgshapiro*/
8190792Sgshapirovoid sm_debug_addsettings(char *settings)
8290792Sgshapirovoid sm_debug_addsetting(char *pattern, int level)
8390792Sgshapiro
8490792Sgshapirotypedef struct sm_debug SM_DEBUG_T;
8590792SgshapiroSM_DEBUG_T dbg = SM_DEBUG_INITIALIZER("name", "@(#)$Debug: name - description $");
8690792Sgshapiro
8790792Sgshapirobool sm_debug_active(SM_DEBUG_T *debug, int level)
8890792Sgshapiroint  sm_debug_level(SM_DEBUG_T *debug)
8990792Sgshapirobool sm_debug_unknown(SM_DEBUG_T *debug)
9090792Sgshapiro</pre>
9190792Sgshapiro
9290792Sgshapiro<h2> Naming Conventions </h2>
9390792Sgshapiro
9490792SgshapiroAll debug categories defined by libsm have names of the form <tt>sm_*</tt>.
9590792SgshapiroDebug categories that turn on trace output have names of the form
9690792Sgshapiro<tt>*_trace_*</tt>.
9790792SgshapiroDebug categories that turn on run time checks have names of the form
9890792Sgshapiro<tt>*_check_*</tt>.
9990792SgshapiroHere are all of the libsm debug categories as of March 2000:
10090792Sgshapiro
10190792Sgshapiro<table>
10290792Sgshapiro  <tr>
10390792Sgshapiro    <td>Variable name</td>
10490792Sgshapiro    <td>Category name</td>
10590792Sgshapiro    <td>Meaning</td>
10690792Sgshapiro  </tr>
10790792Sgshapiro  <tr>
10890792Sgshapiro    <td>SmExpensiveAssert</td>
10990792Sgshapiro    <td>sm_check_assert</td>
11090792Sgshapiro    <td>enable expensive SM_ASSERT checking</td>
11190792Sgshapiro  </tr>
11290792Sgshapiro  <tr>
11390792Sgshapiro    <td>SmExpensiveRequire</td>
11490792Sgshapiro    <td>sm_check_require</td>
11590792Sgshapiro    <td>enable expensive SM_REQUIRE checking</td>
11690792Sgshapiro  </tr>
11790792Sgshapiro  <tr>
11890792Sgshapiro    <td>SmExpensiveEnsure</td>
11990792Sgshapiro    <td>sm_check_ensure</td>
12090792Sgshapiro    <td>enable expensive SM_ENSURE checking</td>
12190792Sgshapiro  </tr>
12290792Sgshapiro  <tr>
12390792Sgshapiro    <td>SmHeapTrace</td>
12490792Sgshapiro    <td>sm_trace_heap</td>
12590792Sgshapiro    <td>trace sm_{malloc,realloc,free} calls</td>
12690792Sgshapiro  </tr>
12790792Sgshapiro  <tr>
12890792Sgshapiro    <td>SmHeapCheck</td>
12990792Sgshapiro    <td>sm_check_heap</td>
13090792Sgshapiro    <td>enable checking and memory leak detection in sm_{malloc,realloc,free}</td>
13190792Sgshapiro  </tr>
13290792Sgshapiro</table>
13390792Sgshapiro
13490792Sgshapiro<h2> Function Reference </h2>
13590792Sgshapiro
13690792Sgshapiro<dl>
13790792Sgshapiro<dt>
13890792Sgshapiro<tt> SM_DEBUG_INITIALIZER </tt>
13990792Sgshapiro<dd>
14090792Sgshapiro    To create a new debug category, use the SM_DEBUG_INITIALIZER macro
14190792Sgshapiro    to initialize a static variable of type SM_DEBUG_T.  For example,
14290792Sgshapiro<blockquote><pre>
14390792SgshapiroSM_DEBUG_T ANSI_debug = SM_DEBUG_INITIALIZER("ANSI",
14490792Sgshapiro	    "@(#)$Debug: ANSI - enable reverse video in debug output $");
14590792Sgshapiro</pre></blockquote>
14690792Sgshapiro    There is no centralized table of category names that needs to
14790792Sgshapiro    be edited in order to add a new debug category.
14890792Sgshapiro    The sole purpose of the second argument to SM_DEBUG_INITIALIZER
14990792Sgshapiro    is to provide an easy way to find out what named debug categories
15090792Sgshapiro    are present in a sendmail binary.  You can use:
15190792Sgshapiro<blockquote><pre>
15290792Sgshapiroident /usr/sbin/sendmail | grep Debug
15390792Sgshapiro</pre></blockquote>
15490792Sgshapiro    or:
15590792Sgshapiro<blockquote><pre>
15690792Sgshapirowhat /usr/sbin/sendmail | grep Debug
15790792Sgshapiro</pre></blockquote>
15890792Sgshapiro
15990792Sgshapiro
16090792Sgshapiro<dt>
16190792Sgshapiro<tt> void sm_debug_addsetting(char *pattern, int level) </tt>
16290792Sgshapiro<dd>
16390792Sgshapiro    All debug categories default to activation level 0, which means
16490792Sgshapiro    no activity.
16590792Sgshapiro    This function updates an internal database of debug settings,
16690792Sgshapiro    setting all categories whose name matches the specified glob
16790792Sgshapiro    pattern to the specified activation level.  The level argument
16890792Sgshapiro    must be &gt;= 0.
16990792Sgshapiro    <p>
17090792Sgshapiro
17190792Sgshapiro
17290792Sgshapiro<dt>
17390792Sgshapiro<tt> void sm_debug_addsettings(char *settings) </tt>
17490792Sgshapiro<dd>
17590792Sgshapiro    This function is used to process the <tt>-d</tt> command line
17690792Sgshapiro    option of Sendmail 9.x, and of other programs that support the
17790792Sgshapiro    setting of named debug categories.  The settings argument is a
17890792Sgshapiro    comma-separated list of settings; each setting is a glob pattern,
17990792Sgshapiro    optionally followed by a '.' and a decimal numeral.
18090792Sgshapiro    <p>
18190792Sgshapiro
18290792Sgshapiro
18390792Sgshapiro<dt>
18490792Sgshapiro<tt> bool sm_debug_active(SM_DEBUG_T *debug, int level) </tt>
18590792Sgshapiro<dd>
18690792Sgshapiro    This macro returns <tt>true</tt> if the activation level of
18790792Sgshapiro    the statically initialized debug structure <tt>debug</tt>
18890792Sgshapiro    is &gt;= the specified level.
18990792Sgshapiro    The test is performed very efficiently: in the most common case,
19090792Sgshapiro    when the result is <tt>false</tt>, only a single comparison
19190792Sgshapiro    operation is performed.
19290792Sgshapiro    <p>
19390792Sgshapiro    This macro performs a function call only if the debug structure has
19490792Sgshapiro    an unknown activation level.  All debug structures are in this state
19590792Sgshapiro    at the beginning of program execution, and after a call to
19690792Sgshapiro    <tt>sm_debug_addsetting</tt>.
19790792Sgshapiro    <p>
19890792Sgshapiro
19990792Sgshapiro
20090792Sgshapiro<dt>
20190792Sgshapiro<tt> int sm_debug_level(SM_DEBUG_T *debug) </tt>
20290792Sgshapiro<dd>
20390792Sgshapiro    This macro returns the activation level of the specified debug structure.
20490792Sgshapiro    The comparison
20590792Sgshapiro<blockquote><pre>
20690792Sgshapirosm_debug_level(debug) &gt;= level
20790792Sgshapiro</pre></blockquote>
20890792Sgshapiro    is slightly less efficient than, but otherwise semantically
20990792Sgshapiro    equivalent to
21090792Sgshapiro<blockquote><pre>
21190792Sgshapirosm_debug_active(debug, level)
21290792Sgshapiro</pre></blockquote>
21390792Sgshapiro    <p>
21490792Sgshapiro
21590792Sgshapiro
21690792Sgshapiro<dt>
21790792Sgshapiro<tt> bool sm_debug_unknown(SM_DEBUG_T *debug) </tt>
21890792Sgshapiro<dd>
21990792Sgshapiro    This macro returns true if the activation level of the specified
22090792Sgshapiro    debug structure is unknown.
22190792Sgshapiro    Here is an example of how the macro might be used:
22290792Sgshapiro<blockquote><pre>
22390792Sgshapiroif (sm_debug_unknown(&FooDebug))
22490792Sgshapiro{
22590792Sgshapiro	if (sm_debug_active(&FooDebug, 1))
22690792Sgshapiro	{
22790792Sgshapiro		... perform some expensive data structure initializations
22890792Sgshapiro		... in order to enable the "foo" debugging mechanism
22990792Sgshapiro	}
23090792Sgshapiro	else
23190792Sgshapiro	{
23290792Sgshapiro		... disable the "foo" debugging mechanism
23390792Sgshapiro	}
23490792Sgshapiro}
23590792Sgshapiro</pre></blockquote>
23690792Sgshapiro    The purpose of using <tt>sm_debug_unknown</tt> in the above example
23790792Sgshapiro    is to avoid performing the expensive initializations each time through
23890792Sgshapiro    the code.  So it's a performance hack.
23990792Sgshapiro    A debug structure is in the "unknown" state at the beginning of
24090792Sgshapiro    program execution, and after a call to <tt>sm_debug_addsetting</tt>.
24190792Sgshapiro    A side effect of calling <tt>sm_debug_active</tt> is that the
24290792Sgshapiro    activation level becomes known.
24390792Sgshapiro    <p>
24490792Sgshapiro
24590792Sgshapiro
24690792Sgshapiro<dt>
24790792Sgshapiro<tt> void sm_dprintf(char *fmt, ...) </tt>
24890792Sgshapiro<dd>
24990792Sgshapiro    This function is used to print a debug message.
25090792Sgshapiro    The standard idiom is
25190792Sgshapiro<blockquote><pre>
25290792Sgshapiroif (sm_debug_active(&BarDebug, 1))
25390792Sgshapiro	sm_dprintf("bar: about to test tensile strength of bar %d\n", i);
25490792Sgshapiro</pre></blockquote>
25590792Sgshapiro    <p>
25690792Sgshapiro
25790792Sgshapiro<dt>
25890792Sgshapiro<tt> void sm_dflush() </tt>
25990792Sgshapiro<dd>
26090792Sgshapiro    Flush the debug output stream.
26190792Sgshapiro    <p>
26290792Sgshapiro
26390792Sgshapiro<dt>
26490792Sgshapiro<tt> void sm_debug_setfile(SM_FILE_T *file) </tt>
26590792Sgshapiro<dd>
26690792Sgshapiro    This function lets you specify where debug output is printed.
26790792Sgshapiro    By default, debug output is written to standard output.
26890792Sgshapiro    <p>
26990792Sgshapiro    We want to allow you to direct debug output to syslog.
27090792Sgshapiro    The current plan is to provide a standard interface for
27190792Sgshapiro    creating an SM_FILE_T object that writes to syslog.
27290792Sgshapiro
27390792Sgshapiro</dl>
27490792Sgshapiro
27590792Sgshapiro</body>
27690792Sgshapiro</html>
277