1<html> 2<head> 3 <title>libsm : Debugging and Tracing</title> 4</head> 5<body> 6 7<a href="index.html">Back to libsm overview</a> 8 9<center> 10 <h1> libsm : Debugging and Tracing </h1> 11 <br> $Id: debug.html,v 1.9 2002/02/02 16:50:56 ca Exp $ 12</center> 13 14<h2> Introduction </h2> 15 16The debug and trace package provides abstractions for writing trace 17messages, and abstractions for enabling and disabling debug and 18trace code at run time. 19 20<p> 21Sendmail 8.11 and earlier has a <tt>-d</tt> option which 22lets you turn on debug and trace code. 23Debug categories are integers from 0 to 99, with the sole exception 24of "ANSI", which is a named debug category. 25 26<p> 27The libsm debug package supports named debug categories. 28Debug category names have the form of C identifiers. 29For example, <tt>sm_trace_heap</tt> controls the output of trace 30messages from the sm heap package, while <tt>sm_check_heap</tt> 31controls the argument validity checking and memory leak detection 32features of the sm heap package. 33 34<p> 35In sendmail 8.12, the <tt>-d</tt> flag is generalized 36to support both the original style numeric categories, for backwards 37compatibility, and the new style named categories implemented by libsm. 38With this change, 39"-dANSI" is implemented using a libsm named debug category. 40You will be able to set a collection of named debug categories to 41the same activation level by specifying a glob pattern. 42For example, 43<dl> 44<dt> 45 <tt> -dANSI </tt> 46<dd> 47 sets the named category "ANSI" to level 1, 48<dt> 49 <tt> -dfoo_*.3 </tt> 50<dd> 51 sets all named categories matching the glob pattern "foo_*" to level 3, 52<dt> 53 <tt> -d0-99.1 </tt> 54<dd> 55 sets the numeric categories 0 through 99 to level 1, and 56<dt> 57 <tt> -dANSI,foo_*.3,0-99.1 </tt> 58<dd> 59 does all of the above. 60</dl> 61 62<h2> Synopsis </h2> 63 64<pre> 65#include <sm/debug.h> 66 67/* 68** abstractions for printing trace messages 69*/ 70void sm_dprintf(char *fmt, ...) 71void sm_dflush() 72void sm_debug_setfile(SM_FILE_T *) 73 74/* 75** abstractions for setting and testing debug activation levels 76*/ 77void sm_debug_addsettings(char *settings) 78void sm_debug_addsetting(char *pattern, int level) 79 80typedef struct sm_debug SM_DEBUG_T; 81SM_DEBUG_T dbg = SM_DEBUG_INITIALIZER("name", "@(#)$Debug: name - description $"); 82 83bool sm_debug_active(SM_DEBUG_T *debug, int level) 84int sm_debug_level(SM_DEBUG_T *debug) 85bool sm_debug_unknown(SM_DEBUG_T *debug) 86</pre> 87 88<h2> Naming Conventions </h2> 89 90All debug categories defined by libsm have names of the form <tt>sm_*</tt>. 91Debug categories that turn on trace output have names of the form 92<tt>*_trace_*</tt>. 93Debug categories that turn on run time checks have names of the form 94<tt>*_check_*</tt>. 95Here are all of the libsm debug categories as of March 2000: 96 97<table> 98 <tr> 99 <td>Variable name</td> 100 <td>Category name</td> 101 <td>Meaning</td> 102 </tr> 103 <tr> 104 <td>SmExpensiveAssert</td> 105 <td>sm_check_assert</td> 106 <td>enable expensive SM_ASSERT checking</td> 107 </tr> 108 <tr> 109 <td>SmExpensiveRequire</td> 110 <td>sm_check_require</td> 111 <td>enable expensive SM_REQUIRE checking</td> 112 </tr> 113 <tr> 114 <td>SmExpensiveEnsure</td> 115 <td>sm_check_ensure</td> 116 <td>enable expensive SM_ENSURE checking</td> 117 </tr> 118 <tr> 119 <td>SmHeapTrace</td> 120 <td>sm_trace_heap</td> 121 <td>trace sm_{malloc,realloc,free} calls</td> 122 </tr> 123 <tr> 124 <td>SmHeapCheck</td> 125 <td>sm_check_heap</td> 126 <td>enable checking and memory leak detection in sm_{malloc,realloc,free}</td> 127 </tr> 128</table> 129 130<h2> Function Reference </h2> 131 132<dl> 133<dt> 134<tt> SM_DEBUG_INITIALIZER </tt> 135<dd> 136 To create a new debug category, use the SM_DEBUG_INITIALIZER macro 137 to initialize a static variable of type SM_DEBUG_T. For example, 138<blockquote><pre> 139SM_DEBUG_T ANSI_debug = SM_DEBUG_INITIALIZER("ANSI", 140 "@(#)$Debug: ANSI - enable reverse video in debug output $"); 141</pre></blockquote> 142 There is no centralized table of category names that needs to 143 be edited in order to add a new debug category. 144 The sole purpose of the second argument to SM_DEBUG_INITIALIZER 145 is to provide an easy way to find out what named debug categories 146 are present in a sendmail binary. You can use: 147<blockquote><pre> 148ident /usr/sbin/sendmail | grep Debug 149</pre></blockquote> 150 or: 151<blockquote><pre> 152what /usr/sbin/sendmail | grep Debug 153</pre></blockquote> 154 155 156<dt> 157<tt> void sm_debug_addsetting(char *pattern, int level) </tt> 158<dd> 159 All debug categories default to activation level 0, which means 160 no activity. 161 This function updates an internal database of debug settings, 162 setting all categories whose name matches the specified glob 163 pattern to the specified activation level. The level argument 164 must be >= 0. 165 <p> 166 167 168<dt> 169<tt> void sm_debug_addsettings(char *settings) </tt> 170<dd> 171 This function is used to process the <tt>-d</tt> command line 172 option of Sendmail 9.x, and of other programs that support the 173 setting of named debug categories. The settings argument is a 174 comma-separated list of settings; each setting is a glob pattern, 175 optionally followed by a '.' and a decimal numeral. 176 <p> 177 178 179<dt> 180<tt> bool sm_debug_active(SM_DEBUG_T *debug, int level) </tt> 181<dd> 182 This macro returns <tt>true</tt> if the activation level of 183 the statically initialized debug structure <tt>debug</tt> 184 is >= the specified level. 185 The test is performed very efficiently: in the most common case, 186 when the result is <tt>false</tt>, only a single comparison 187 operation is performed. 188 <p> 189 This macro performs a function call only if the debug structure has 190 an unknown activation level. All debug structures are in this state 191 at the beginning of program execution, and after a call to 192 <tt>sm_debug_addsetting</tt>. 193 <p> 194 195 196<dt> 197<tt> int sm_debug_level(SM_DEBUG_T *debug) </tt> 198<dd> 199 This macro returns the activation level of the specified debug structure. 200 The comparison 201<blockquote><pre> 202sm_debug_level(debug) >= level 203</pre></blockquote> 204 is slightly less efficient than, but otherwise semantically 205 equivalent to 206<blockquote><pre> 207sm_debug_active(debug, level) 208</pre></blockquote> 209 <p> 210 211 212<dt> 213<tt> bool sm_debug_unknown(SM_DEBUG_T *debug) </tt> 214<dd> 215 This macro returns true if the activation level of the specified 216 debug structure is unknown. 217 Here is an example of how the macro might be used: 218<blockquote><pre> 219if (sm_debug_unknown(&FooDebug)) 220{ 221 if (sm_debug_active(&FooDebug, 1)) 222 { 223 ... perform some expensive data structure initializations 224 ... in order to enable the "foo" debugging mechanism 225 } 226 else 227 { 228 ... disable the "foo" debugging mechanism 229 } 230} 231</pre></blockquote> 232 The purpose of using <tt>sm_debug_unknown</tt> in the above example 233 is to avoid performing the expensive initializations each time through 234 the code. So it's a performance hack. 235 A debug structure is in the "unknown" state at the beginning of 236 program execution, and after a call to <tt>sm_debug_addsetting</tt>. 237 A side effect of calling <tt>sm_debug_active</tt> is that the 238 activation level becomes known. 239 <p> 240 241 242<dt> 243<tt> void sm_dprintf(char *fmt, ...) </tt> 244<dd> 245 This function is used to print a debug message. 246 The standard idiom is 247<blockquote><pre> 248if (sm_debug_active(&BarDebug, 1)) 249 sm_dprintf("bar: about to test tensile strength of bar %d\n", i); 250</pre></blockquote> 251 <p> 252 253<dt> 254<tt> void sm_dflush() </tt> 255<dd> 256 Flush the debug output stream. 257 <p> 258 259<dt> 260<tt> void sm_debug_setfile(SM_FILE_T *file) </tt> 261<dd> 262 This function lets you specify where debug output is printed. 263 By default, debug output is written to standard output. 264 <p> 265 We want to allow you to direct debug output to syslog. 266 The current plan is to provide a standard interface for 267 creating an SM_FILE_T object that writes to syslog. 268 269</dl> 270 271</body> 272</html> 273