source: trunk/third/sendmail/libsm/debug.c @ 19204

Revision 19204, 7.0 KB checked in by zacheiss, 22 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r19203, which included commits to RCS files with non-trunk default branches.
Line 
1/*
2 * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers.
3 *      All rights reserved.
4 *
5 * By using this file, you agree to the terms and conditions set
6 * forth in the LICENSE file which can be found at the top level of
7 * the sendmail distribution.
8 */
9
10#include <sm/gen.h>
11SM_RCSID("@(#)$Id: debug.c,v 1.1.1.1 2003-04-08 15:06:18 zacheiss Exp $")
12
13/*
14**  libsm debugging and tracing
15**  For documentation, see debug.html.
16*/
17
18#include <ctype.h>
19#include <stdlib.h>
20#include <setjmp.h>
21#include <sm/io.h>
22#include <sm/assert.h>
23#include <sm/conf.h>
24#include <sm/debug.h>
25#include <sm/string.h>
26#include <sm/varargs.h>
27#include <sm/heap.h>
28
29/*
30**  Abstractions for printing trace messages.
31*/
32
33/*
34**  The output file to which trace output is directed.
35**  There is a controversy over whether this variable
36**  should be process global or thread local.
37**  To make the interface more abstract, we've hidden the
38**  variable behind access functions.
39*/
40
41static SM_FILE_T *SmDebugOutput = smioout;
42
43/*
44**  SM_DEBUG_FILE -- Returns current debug file pointer.
45**
46**      Parameters:
47**              none.
48**
49**      Returns:
50**              current debug file pointer.
51*/
52
53SM_FILE_T *
54sm_debug_file()
55{
56        return SmDebugOutput;
57}
58
59/*
60**  SM_DEBUG_SETFILE -- Sets debug file pointer.
61**
62**      Parameters:
63**              fp -- new debug file pointer.
64**
65**      Returns:
66**              none.
67**
68**      Side Effects:
69**              Sets SmDebugOutput.
70*/
71
72void
73sm_debug_setfile(fp)
74        SM_FILE_T *fp;
75{
76        SmDebugOutput = fp;
77}
78
79/*
80**  SM_DPRINTF -- printf() for debug output.
81**
82**      Parameters:
83**              fmt -- format for printf()
84**
85**      Returns:
86**              none.
87*/
88
89void
90#if SM_VA_STD
91sm_dprintf(char *fmt, ...)
92#else /* SM_VA_STD */
93sm_dprintf(fmt, va_alist)
94        char *fmt;
95        va_dcl
96#endif /* SM_VA_STD */
97{
98        SM_VA_LOCAL_DECL
99
100        if (SmDebugOutput == NULL)
101                return;
102        SM_VA_START(ap, fmt);
103        sm_io_vfprintf(SmDebugOutput, SmDebugOutput->f_timeout, fmt, ap);
104        SM_VA_END(ap);
105}
106
107/*
108**  SM_DFLUSH -- Flush debug output.
109**
110**      Parameters:
111**              none.
112**
113**      Returns:
114**              none.
115*/
116
117void
118sm_dflush()
119{
120        sm_io_flush(SmDebugOutput, SM_TIME_DEFAULT);
121}
122
123/*
124**  This is the internal database of debug settings.
125**  The semantics of looking up a setting in the settings database
126**  are that the *last* setting specified in a -d option on the sendmail
127**  command line that matches a given SM_DEBUG structure is the one that is
128**  used.  That is necessary to conform to the existing semantics of
129**  the sendmail -d option.  We store the settings as a linked list in
130**  reverse order, so when we do a lookup, we take the *first* entry
131**  that matches.
132*/
133
134typedef struct sm_debug_setting SM_DEBUG_SETTING_T;
135struct sm_debug_setting
136{
137        const char              *ds_pattern;
138        unsigned int            ds_level;
139        SM_DEBUG_SETTING_T      *ds_next;
140};
141SM_DEBUG_SETTING_T *SmDebugSettings = NULL;
142
143/*
144**  We keep a linked list of SM_DEBUG structures that have been initialized,
145**  for use by sm_debug_reset.
146*/
147
148SM_DEBUG_T *SmDebugInitialized = NULL;
149
150const char SmDebugMagic[] = "sm_debug";
151
152/*
153**  SM_DEBUG_RESET -- Reset SM_DEBUG structures.
154**
155**      Reset all SM_DEBUG structures back to the uninitialized state.
156**      This is used by sm_debug_addsetting to ensure that references to
157**      SM_DEBUG structures that occur before sendmail processes its -d flags
158**      do not cause those structures to be permanently forced to level 0.
159**
160**      Parameters:
161**              none.
162**
163**      Returns:
164**              none.
165*/
166
167void
168sm_debug_reset()
169{
170        SM_DEBUG_T *debug;
171
172        for (debug = SmDebugInitialized;
173             debug != NULL;
174             debug = debug->debug_next)
175        {
176                debug->debug_level = SM_DEBUG_UNKNOWN;
177        }
178        SmDebugInitialized = NULL;
179}
180
181/*
182**  SM_DEBUG_ADDSETTING_X -- add an entry to the database of debug settings
183**
184**      Parameters:
185**              pattern -- a shell-style glob pattern (see sm_match).
186**                      WARNING: the storage for 'pattern' will be owned by
187**                      the debug package, so it should either be a string
188**                      literal or the result of a call to sm_strdup_x.
189**              level -- a non-negative integer.
190**
191**      Returns:
192**              none.
193**
194**      Exceptions:
195**              F:sm_heap -- out of memory
196*/
197
198void
199sm_debug_addsetting_x(pattern, level)
200        const char *pattern;
201        int level;
202{
203        SM_DEBUG_SETTING_T *s;
204
205        SM_REQUIRE(pattern != NULL);
206        SM_REQUIRE(level >= 0);
207        s = sm_malloc_x(sizeof(SM_DEBUG_SETTING_T));
208        s->ds_pattern = pattern;
209        s->ds_level = (unsigned int) level;
210        s->ds_next = SmDebugSettings;
211        SmDebugSettings = s;
212        sm_debug_reset();
213}
214
215/*
216**  PARSE_NAMED_SETTING_X -- process a symbolic debug setting
217**
218**      Parameters:
219**              s -- Points to a non-empty \0 or , terminated string,
220**                   of which the initial character is not a digit.
221**
222**      Returns:
223**              pointer to terminating \0 or , character.
224**
225**      Exceptions:
226**              F:sm.heap -- out of memory.
227**
228**      Side Effects:
229**              adds the setting to the database.
230*/
231
232static const char *
233parse_named_setting_x(s)
234        register const char *s;
235{
236        const char *pat, *endpat;
237        int level;
238
239        pat = s;
240        while (*s != '\0' && *s != ',' && *s != '.')
241                ++s;
242        endpat = s;
243        if (*s == '.')
244        {
245                ++s;
246                level = 0;
247                while (isascii(*s) && isdigit(*s))
248                {
249                        level = level * 10 + (*s - '0');
250                        ++s;
251                }
252                if (level < 0)
253                        level = 0;
254        }
255        else
256                level = 1;
257
258        sm_debug_addsetting_x(sm_strndup_x(pat, endpat - pat), level);
259
260        /* skip trailing junk */
261        while (*s != '\0' && *s != ',')
262                ++s;
263
264        return s;
265}
266
267/*
268**  SM_DEBUG_ADDSETTINGS_X -- process a list of debug options
269**
270**      Parameters:
271**              s -- a list of debug settings, eg the argument to the
272**                   sendmail -d option.
273**
274**              The syntax of the string s is as follows:
275**
276**              <settings> ::= <setting> | <settings> "," <setting>
277**              <setting> ::= <categories> | <categories> "." <level>
278**              <categories> ::= [a-zA-Z_*?][a-zA-Z0-9_*?]*
279**
280**              However, note that we skip over anything we don't
281**              understand, rather than report an error.
282**
283**      Returns:
284**              none.
285**
286**      Exceptions:
287**              F:sm.heap -- out of memory
288**
289**      Side Effects:
290**              updates the database of debug settings.
291*/
292
293void
294sm_debug_addsettings_x(s)
295        register const char *s;
296{
297        for (;;)
298        {
299                if (*s == '\0')
300                        return;
301                if (*s == ',')
302                {
303                        ++s;
304                        continue;
305                }
306                s = parse_named_setting_x(s);
307        }
308}
309
310/*
311**  SM_DEBUG_LOADLEVEL -- Get activation level of the specified debug object.
312**
313**      Parameters:
314**              debug -- debug object.
315**
316**      Returns:
317**              Activation level of the specified debug object.
318**
319**      Side Effects:
320**              Ensures that the debug object is initialized.
321*/
322
323int
324sm_debug_loadlevel(debug)
325        SM_DEBUG_T *debug;
326{
327        if (debug->debug_level == SM_DEBUG_UNKNOWN)
328        {
329                SM_DEBUG_SETTING_T *s;
330
331                for (s = SmDebugSettings; s != NULL; s = s->ds_next)
332                {
333                        if (sm_match(debug->debug_name, s->ds_pattern))
334                        {
335                                debug->debug_level = s->ds_level;
336                                goto initialized;
337                        }
338                }
339                debug->debug_level = 0;
340        initialized:
341                debug->debug_next = SmDebugInitialized;
342                SmDebugInitialized = debug;
343        }
344        return (int) debug->debug_level;
345}
346
347/*
348**  SM_DEBUG_LOADACTIVE -- Activation level reached?
349**
350**      Parameters:
351**              debug -- debug object.
352**              level -- level to check.
353**
354**      Returns:
355**              true iff the activation level of the specified debug
356**                      object >= level.
357**
358**      Side Effects:
359**              Ensures that the debug object is initialized.
360*/
361
362bool
363sm_debug_loadactive(debug, level)
364        SM_DEBUG_T *debug;
365        int level;
366{
367        return sm_debug_loadlevel(debug) >= level;
368}
Note: See TracBrowser for help on using the repository browser.