aboutsummaryrefslogtreecommitdiff
path: root/contrib/sendmail/libsm/debug.html
blob: b7f1b9c73a15230997d896d3155dad6699f581d1 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
<html>
<head>
    <title>libsm : Debugging and Tracing</title>
</head>
<body>

<a href="index.html">Back to libsm overview</a>

<center>
    <h1> libsm : Debugging and Tracing </h1>
    <br> $Id: debug.html,v 1.1.1.2 2002/04/10 03:04:55 gshapiro Exp $
</center>

<h2> Introduction </h2>

The debug and trace package provides abstractions for writing trace
messages, and abstractions for enabling and disabling debug and
trace code at run time.

<p>
Sendmail 8.11 and earlier has a <tt>-d</tt> 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.

<p>
The libsm debug package supports named debug categories.
Debug category names have the form of C identifiers.
For example, <tt>sm_trace_heap</tt> controls the output of trace
messages from the sm heap package, while <tt>sm_check_heap</tt>
controls the argument validity checking and memory leak detection
features of the sm heap package.

<p>
In sendmail 8.12, the <tt>-d</tt> 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,
<dl>
<dt>
    <tt> -dANSI </tt>
<dd>
    sets the named category "ANSI" to level 1,
<dt>
    <tt> -dfoo_*.3 </tt>
<dd>
    sets all named categories matching the glob pattern "foo_*" to level 3,
<dt>
    <tt> -d0-99.1 </tt>
<dd>
    sets the numeric categories 0 through 99 to level 1, and
<dt>
    <tt> -dANSI,foo_*.3,0-99.1 </tt>
<dd>
    does all of the above.
</dl>

<h2> Synopsis </h2>

<pre>
#include &lt;sm/debug.h&gt;

/*
**  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)
</pre>

<h2> Naming Conventions </h2>

All debug categories defined by libsm have names of the form <tt>sm_*</tt>.
Debug categories that turn on trace output have names of the form
<tt>*_trace_*</tt>.
Debug categories that turn on run time checks have names of the form
<tt>*_check_*</tt>.
Here are all of the libsm debug categories as of March 2000:

<table>
  <tr>
    <td>Variable name</td>
    <td>Category name</td>
    <td>Meaning</td>
  </tr>
  <tr>
    <td>SmExpensiveAssert</td>
    <td>sm_check_assert</td>
    <td>enable expensive SM_ASSERT checking</td>
  </tr>
  <tr>
    <td>SmExpensiveRequire</td>
    <td>sm_check_require</td>
    <td>enable expensive SM_REQUIRE checking</td>
  </tr>
  <tr>
    <td>SmExpensiveEnsure</td>
    <td>sm_check_ensure</td>
    <td>enable expensive SM_ENSURE checking</td>
  </tr>
  <tr>
    <td>SmHeapTrace</td>
    <td>sm_trace_heap</td>
    <td>trace sm_{malloc,realloc,free} calls</td>
  </tr>
  <tr>
    <td>SmHeapCheck</td>
    <td>sm_check_heap</td>
    <td>enable checking and memory leak detection in sm_{malloc,realloc,free}</td>
  </tr>
</table>

<h2> Function Reference </h2>

<dl>
<dt>
<tt> SM_DEBUG_INITIALIZER </tt>
<dd>
    To create a new debug category, use the SM_DEBUG_INITIALIZER macro
    to initialize a static variable of type SM_DEBUG_T.  For example,
<blockquote><pre>
SM_DEBUG_T ANSI_debug = SM_DEBUG_INITIALIZER("ANSI",
	    "@(#)$Debug: ANSI - enable reverse video in debug output $");
</pre></blockquote>
    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:
<blockquote><pre>
ident /usr/sbin/sendmail | grep Debug
</pre></blockquote>
    or:
<blockquote><pre>
what /usr/sbin/sendmail | grep Debug
</pre></blockquote>


<dt>
<tt> void sm_debug_addsetting(char *pattern, int level) </tt>
<dd>
    All debug categories default to activation level 0, which means
    no activity.
    This function updates an internal database of debug settings,
    setting all categories whose name matches the specified glob
    pattern to the specified activation level.  The level argument
    must be &gt;= 0.
    <p>


<dt>
<tt> void sm_debug_addsettings(char *settings) </tt>
<dd>
    This function is used to process the <tt>-d</tt> command line
    option of Sendmail 9.x, and of other programs that support the
    setting of named debug categories.  The settings argument is a
    comma-separated list of settings; each setting is a glob pattern,
    optionally followed by a '.' and a decimal numeral.
    <p>


<dt>
<tt> bool sm_debug_active(SM_DEBUG_T *debug, int level) </tt>
<dd>
    This macro returns <tt>true</tt> if the activation level of
    the statically initialized debug structure <tt>debug</tt>
    is &gt;= the specified level.
    The test is performed very efficiently: in the most common case,
    when the result is <tt>false</tt>, only a single comparison
    operation is performed.
    <p>
    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
    <tt>sm_debug_addsetting</tt>.
    <p>


<dt>
<tt> int sm_debug_level(SM_DEBUG_T *debug) </tt>
<dd>
    This macro returns the activation level of the specified debug structure.
    The comparison
<blockquote><pre>
sm_debug_level(debug) &gt;= level
</pre></blockquote>
    is slightly less efficient than, but otherwise semantically
    equivalent to
<blockquote><pre>
sm_debug_active(debug, level)
</pre></blockquote>
    <p>


<dt>
<tt> bool sm_debug_unknown(SM_DEBUG_T *debug) </tt>
<dd>
    This macro returns true if the activation level of the specified
    debug structure is unknown.
    Here is an example of how the macro might be used:
<blockquote><pre>
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
	}
}
</pre></blockquote>
    The purpose of using <tt>sm_debug_unknown</tt> 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 <tt>sm_debug_addsetting</tt>.
    A side effect of calling <tt>sm_debug_active</tt> is that the
    activation level becomes known.
    <p>


<dt>
<tt> void sm_dprintf(char *fmt, ...) </tt>
<dd>
    This function is used to print a debug message.
    The standard idiom is
<blockquote><pre>
if (sm_debug_active(&BarDebug, 1))
	sm_dprintf("bar: about to test tensile strength of bar %d\n", i);
</pre></blockquote>
    <p>

<dt>
<tt> void sm_dflush() </tt>
<dd>
    Flush the debug output stream.
    <p>

<dt>
<tt> void sm_debug_setfile(SM_FILE_T *file) </tt>
<dd>
    This function lets you specify where debug output is printed.
    By default, debug output is written to standard output.
    <p>
    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.

</dl>

</body>
</html>