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> 1198121Sgshapiro <br> $Id: debug.html,v 1.9 2002/02/02 16:50:56 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<h2> Synopsis </h2> 6390792Sgshapiro 6490792Sgshapiro<pre> 6590792Sgshapiro#include <sm/debug.h> 6690792Sgshapiro 6790792Sgshapiro/* 6890792Sgshapiro** abstractions for printing trace messages 6990792Sgshapiro*/ 7090792Sgshapirovoid sm_dprintf(char *fmt, ...) 7190792Sgshapirovoid sm_dflush() 7290792Sgshapirovoid sm_debug_setfile(SM_FILE_T *) 7390792Sgshapiro 7490792Sgshapiro/* 7590792Sgshapiro** abstractions for setting and testing debug activation levels 7690792Sgshapiro*/ 7790792Sgshapirovoid sm_debug_addsettings(char *settings) 7890792Sgshapirovoid sm_debug_addsetting(char *pattern, int level) 7990792Sgshapiro 8090792Sgshapirotypedef struct sm_debug SM_DEBUG_T; 8190792SgshapiroSM_DEBUG_T dbg = SM_DEBUG_INITIALIZER("name", "@(#)$Debug: name - description $"); 8290792Sgshapiro 8390792Sgshapirobool sm_debug_active(SM_DEBUG_T *debug, int level) 8490792Sgshapiroint sm_debug_level(SM_DEBUG_T *debug) 8590792Sgshapirobool sm_debug_unknown(SM_DEBUG_T *debug) 8690792Sgshapiro</pre> 8790792Sgshapiro 8890792Sgshapiro<h2> Naming Conventions </h2> 8990792Sgshapiro 9090792SgshapiroAll debug categories defined by libsm have names of the form <tt>sm_*</tt>. 9190792SgshapiroDebug categories that turn on trace output have names of the form 9290792Sgshapiro<tt>*_trace_*</tt>. 9390792SgshapiroDebug categories that turn on run time checks have names of the form 9490792Sgshapiro<tt>*_check_*</tt>. 9590792SgshapiroHere are all of the libsm debug categories as of March 2000: 9690792Sgshapiro 9790792Sgshapiro<table> 9890792Sgshapiro <tr> 9990792Sgshapiro <td>Variable name</td> 10090792Sgshapiro <td>Category name</td> 10190792Sgshapiro <td>Meaning</td> 10290792Sgshapiro </tr> 10390792Sgshapiro <tr> 10490792Sgshapiro <td>SmExpensiveAssert</td> 10590792Sgshapiro <td>sm_check_assert</td> 10690792Sgshapiro <td>enable expensive SM_ASSERT checking</td> 10790792Sgshapiro </tr> 10890792Sgshapiro <tr> 10990792Sgshapiro <td>SmExpensiveRequire</td> 11090792Sgshapiro <td>sm_check_require</td> 11190792Sgshapiro <td>enable expensive SM_REQUIRE checking</td> 11290792Sgshapiro </tr> 11390792Sgshapiro <tr> 11490792Sgshapiro <td>SmExpensiveEnsure</td> 11590792Sgshapiro <td>sm_check_ensure</td> 11690792Sgshapiro <td>enable expensive SM_ENSURE checking</td> 11790792Sgshapiro </tr> 11890792Sgshapiro <tr> 11990792Sgshapiro <td>SmHeapTrace</td> 12090792Sgshapiro <td>sm_trace_heap</td> 12190792Sgshapiro <td>trace sm_{malloc,realloc,free} calls</td> 12290792Sgshapiro </tr> 12390792Sgshapiro <tr> 12490792Sgshapiro <td>SmHeapCheck</td> 12590792Sgshapiro <td>sm_check_heap</td> 12690792Sgshapiro <td>enable checking and memory leak detection in sm_{malloc,realloc,free}</td> 12790792Sgshapiro </tr> 12890792Sgshapiro</table> 12990792Sgshapiro 13090792Sgshapiro<h2> Function Reference </h2> 13190792Sgshapiro 13290792Sgshapiro<dl> 13390792Sgshapiro<dt> 13490792Sgshapiro<tt> SM_DEBUG_INITIALIZER </tt> 13590792Sgshapiro<dd> 13690792Sgshapiro To create a new debug category, use the SM_DEBUG_INITIALIZER macro 13790792Sgshapiro to initialize a static variable of type SM_DEBUG_T. For example, 13890792Sgshapiro<blockquote><pre> 13990792SgshapiroSM_DEBUG_T ANSI_debug = SM_DEBUG_INITIALIZER("ANSI", 14090792Sgshapiro "@(#)$Debug: ANSI - enable reverse video in debug output $"); 14190792Sgshapiro</pre></blockquote> 14290792Sgshapiro There is no centralized table of category names that needs to 14390792Sgshapiro be edited in order to add a new debug category. 14490792Sgshapiro The sole purpose of the second argument to SM_DEBUG_INITIALIZER 14590792Sgshapiro is to provide an easy way to find out what named debug categories 14690792Sgshapiro are present in a sendmail binary. You can use: 14790792Sgshapiro<blockquote><pre> 14890792Sgshapiroident /usr/sbin/sendmail | grep Debug 14990792Sgshapiro</pre></blockquote> 15090792Sgshapiro or: 15190792Sgshapiro<blockquote><pre> 15290792Sgshapirowhat /usr/sbin/sendmail | grep Debug 15390792Sgshapiro</pre></blockquote> 15490792Sgshapiro 15590792Sgshapiro 15690792Sgshapiro<dt> 15790792Sgshapiro<tt> void sm_debug_addsetting(char *pattern, int level) </tt> 15890792Sgshapiro<dd> 15990792Sgshapiro All debug categories default to activation level 0, which means 16090792Sgshapiro no activity. 16190792Sgshapiro This function updates an internal database of debug settings, 16290792Sgshapiro setting all categories whose name matches the specified glob 16390792Sgshapiro pattern to the specified activation level. The level argument 16490792Sgshapiro must be >= 0. 16590792Sgshapiro <p> 16690792Sgshapiro 16790792Sgshapiro 16890792Sgshapiro<dt> 16990792Sgshapiro<tt> void sm_debug_addsettings(char *settings) </tt> 17090792Sgshapiro<dd> 17190792Sgshapiro This function is used to process the <tt>-d</tt> command line 17290792Sgshapiro option of Sendmail 9.x, and of other programs that support the 17390792Sgshapiro setting of named debug categories. The settings argument is a 17490792Sgshapiro comma-separated list of settings; each setting is a glob pattern, 17590792Sgshapiro optionally followed by a '.' and a decimal numeral. 17690792Sgshapiro <p> 17790792Sgshapiro 17890792Sgshapiro 17990792Sgshapiro<dt> 18090792Sgshapiro<tt> bool sm_debug_active(SM_DEBUG_T *debug, int level) </tt> 18190792Sgshapiro<dd> 18290792Sgshapiro This macro returns <tt>true</tt> if the activation level of 18390792Sgshapiro the statically initialized debug structure <tt>debug</tt> 18490792Sgshapiro is >= the specified level. 18590792Sgshapiro The test is performed very efficiently: in the most common case, 18690792Sgshapiro when the result is <tt>false</tt>, only a single comparison 18790792Sgshapiro operation is performed. 18890792Sgshapiro <p> 18990792Sgshapiro This macro performs a function call only if the debug structure has 19090792Sgshapiro an unknown activation level. All debug structures are in this state 19190792Sgshapiro at the beginning of program execution, and after a call to 19290792Sgshapiro <tt>sm_debug_addsetting</tt>. 19390792Sgshapiro <p> 19490792Sgshapiro 19590792Sgshapiro 19690792Sgshapiro<dt> 19790792Sgshapiro<tt> int sm_debug_level(SM_DEBUG_T *debug) </tt> 19890792Sgshapiro<dd> 19990792Sgshapiro This macro returns the activation level of the specified debug structure. 20090792Sgshapiro The comparison 20190792Sgshapiro<blockquote><pre> 20290792Sgshapirosm_debug_level(debug) >= level 20390792Sgshapiro</pre></blockquote> 20490792Sgshapiro is slightly less efficient than, but otherwise semantically 20590792Sgshapiro equivalent to 20690792Sgshapiro<blockquote><pre> 20790792Sgshapirosm_debug_active(debug, level) 20890792Sgshapiro</pre></blockquote> 20990792Sgshapiro <p> 21090792Sgshapiro 21190792Sgshapiro 21290792Sgshapiro<dt> 21390792Sgshapiro<tt> bool sm_debug_unknown(SM_DEBUG_T *debug) </tt> 21490792Sgshapiro<dd> 21590792Sgshapiro This macro returns true if the activation level of the specified 21690792Sgshapiro debug structure is unknown. 21790792Sgshapiro Here is an example of how the macro might be used: 21890792Sgshapiro<blockquote><pre> 21990792Sgshapiroif (sm_debug_unknown(&FooDebug)) 22090792Sgshapiro{ 22190792Sgshapiro if (sm_debug_active(&FooDebug, 1)) 22290792Sgshapiro { 22390792Sgshapiro ... perform some expensive data structure initializations 22490792Sgshapiro ... in order to enable the "foo" debugging mechanism 22590792Sgshapiro } 22690792Sgshapiro else 22790792Sgshapiro { 22890792Sgshapiro ... disable the "foo" debugging mechanism 22990792Sgshapiro } 23090792Sgshapiro} 23190792Sgshapiro</pre></blockquote> 23290792Sgshapiro The purpose of using <tt>sm_debug_unknown</tt> in the above example 23390792Sgshapiro is to avoid performing the expensive initializations each time through 23490792Sgshapiro the code. So it's a performance hack. 23590792Sgshapiro A debug structure is in the "unknown" state at the beginning of 23690792Sgshapiro program execution, and after a call to <tt>sm_debug_addsetting</tt>. 23790792Sgshapiro A side effect of calling <tt>sm_debug_active</tt> is that the 23890792Sgshapiro activation level becomes known. 23990792Sgshapiro <p> 24090792Sgshapiro 24190792Sgshapiro 24290792Sgshapiro<dt> 24390792Sgshapiro<tt> void sm_dprintf(char *fmt, ...) </tt> 24490792Sgshapiro<dd> 24590792Sgshapiro This function is used to print a debug message. 24690792Sgshapiro The standard idiom is 24790792Sgshapiro<blockquote><pre> 24890792Sgshapiroif (sm_debug_active(&BarDebug, 1)) 24990792Sgshapiro sm_dprintf("bar: about to test tensile strength of bar %d\n", i); 25090792Sgshapiro</pre></blockquote> 25190792Sgshapiro <p> 25290792Sgshapiro 25390792Sgshapiro<dt> 25490792Sgshapiro<tt> void sm_dflush() </tt> 25590792Sgshapiro<dd> 25690792Sgshapiro Flush the debug output stream. 25790792Sgshapiro <p> 25890792Sgshapiro 25990792Sgshapiro<dt> 26090792Sgshapiro<tt> void sm_debug_setfile(SM_FILE_T *file) </tt> 26190792Sgshapiro<dd> 26290792Sgshapiro This function lets you specify where debug output is printed. 26390792Sgshapiro By default, debug output is written to standard output. 26490792Sgshapiro <p> 26590792Sgshapiro We want to allow you to direct debug output to syslog. 26690792Sgshapiro The current plan is to provide a standard interface for 26790792Sgshapiro creating an SM_FILE_T object that writes to syslog. 26890792Sgshapiro 26990792Sgshapiro</dl> 27090792Sgshapiro 27190792Sgshapiro</body> 27290792Sgshapiro</html> 273