Import sendmail 8.13.4 into a new contrib directory as the first step
[dragonfly.git] / contrib / sendmail-8.13.4 / libsm / debug.c
blobf9281fd5e710996f024cde6f62eb696f2bbb2f95
1 /*
2 * Copyright (c) 2000, 2001, 2003, 2004 Sendmail, Inc. and its suppliers.
3 * All rights reserved.
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 */
10 #include <sm/gen.h>
11 SM_RCSID("@(#)$Id: debug.c,v 1.30 2004/08/03 20:10:26 ca Exp $")
14 ** libsm debugging and tracing
15 ** For documentation, see debug.html.
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>
29 static void sm_debug_reset __P((void));
30 static const char *parse_named_setting_x __P((const char *));
33 ** Abstractions for printing trace messages.
37 ** The output file to which trace output is directed.
38 ** There is a controversy over whether this variable
39 ** should be process global or thread local.
40 ** To make the interface more abstract, we've hidden the
41 ** variable behind access functions.
44 static SM_FILE_T *SmDebugOutput = smioout;
47 ** SM_DEBUG_FILE -- Returns current debug file pointer.
49 ** Parameters:
50 ** none.
52 ** Returns:
53 ** current debug file pointer.
56 SM_FILE_T *
57 sm_debug_file()
59 return SmDebugOutput;
63 ** SM_DEBUG_SETFILE -- Sets debug file pointer.
65 ** Parameters:
66 ** fp -- new debug file pointer.
68 ** Returns:
69 ** none.
71 ** Side Effects:
72 ** Sets SmDebugOutput.
75 void
76 sm_debug_setfile(fp)
77 SM_FILE_T *fp;
79 SmDebugOutput = fp;
83 ** SM_DEBUG_CLOSE -- Close debug file pointer.
85 ** Parameters:
86 ** none.
88 ** Returns:
89 ** none.
91 ** Side Effects:
92 ** Closes SmDebugOutput.
95 void
96 sm_debug_close()
98 if (SmDebugOutput != NULL && SmDebugOutput != smioout)
100 sm_io_close(SmDebugOutput, SM_TIME_DEFAULT);
101 SmDebugOutput = NULL;
106 ** SM_DPRINTF -- printf() for debug output.
108 ** Parameters:
109 ** fmt -- format for printf()
111 ** Returns:
112 ** none.
115 void
116 #if SM_VA_STD
117 sm_dprintf(char *fmt, ...)
118 #else /* SM_VA_STD */
119 sm_dprintf(fmt, va_alist)
120 char *fmt;
121 va_dcl
122 #endif /* SM_VA_STD */
124 SM_VA_LOCAL_DECL
126 if (SmDebugOutput == NULL)
127 return;
128 SM_VA_START(ap, fmt);
129 sm_io_vfprintf(SmDebugOutput, SmDebugOutput->f_timeout, fmt, ap);
130 SM_VA_END(ap);
134 ** SM_DFLUSH -- Flush debug output.
136 ** Parameters:
137 ** none.
139 ** Returns:
140 ** none.
143 void
144 sm_dflush()
146 sm_io_flush(SmDebugOutput, SM_TIME_DEFAULT);
150 ** This is the internal database of debug settings.
151 ** The semantics of looking up a setting in the settings database
152 ** are that the *last* setting specified in a -d option on the sendmail
153 ** command line that matches a given SM_DEBUG structure is the one that is
154 ** used. That is necessary to conform to the existing semantics of
155 ** the sendmail -d option. We store the settings as a linked list in
156 ** reverse order, so when we do a lookup, we take the *first* entry
157 ** that matches.
160 typedef struct sm_debug_setting SM_DEBUG_SETTING_T;
161 struct sm_debug_setting
163 const char *ds_pattern;
164 unsigned int ds_level;
165 SM_DEBUG_SETTING_T *ds_next;
167 SM_DEBUG_SETTING_T *SmDebugSettings = NULL;
170 ** We keep a linked list of SM_DEBUG structures that have been initialized,
171 ** for use by sm_debug_reset.
174 SM_DEBUG_T *SmDebugInitialized = NULL;
176 const char SmDebugMagic[] = "sm_debug";
179 ** SM_DEBUG_RESET -- Reset SM_DEBUG structures.
181 ** Reset all SM_DEBUG structures back to the uninitialized state.
182 ** This is used by sm_debug_addsetting to ensure that references to
183 ** SM_DEBUG structures that occur before sendmail processes its -d flags
184 ** do not cause those structures to be permanently forced to level 0.
186 ** Parameters:
187 ** none.
189 ** Returns:
190 ** none.
193 static void
194 sm_debug_reset()
196 SM_DEBUG_T *debug;
198 for (debug = SmDebugInitialized;
199 debug != NULL;
200 debug = debug->debug_next)
202 debug->debug_level = SM_DEBUG_UNKNOWN;
204 SmDebugInitialized = NULL;
208 ** SM_DEBUG_ADDSETTING_X -- add an entry to the database of debug settings
210 ** Parameters:
211 ** pattern -- a shell-style glob pattern (see sm_match).
212 ** WARNING: the storage for 'pattern' will be owned by
213 ** the debug package, so it should either be a string
214 ** literal or the result of a call to sm_strdup_x.
215 ** level -- a non-negative integer.
217 ** Returns:
218 ** none.
220 ** Exceptions:
221 ** F:sm_heap -- out of memory
224 void
225 sm_debug_addsetting_x(pattern, level)
226 const char *pattern;
227 int level;
229 SM_DEBUG_SETTING_T *s;
231 SM_REQUIRE(pattern != NULL);
232 SM_REQUIRE(level >= 0);
233 s = sm_malloc_x(sizeof(SM_DEBUG_SETTING_T));
234 s->ds_pattern = pattern;
235 s->ds_level = (unsigned int) level;
236 s->ds_next = SmDebugSettings;
237 SmDebugSettings = s;
238 sm_debug_reset();
242 ** PARSE_NAMED_SETTING_X -- process a symbolic debug setting
244 ** Parameters:
245 ** s -- Points to a non-empty \0 or , terminated string,
246 ** of which the initial character is not a digit.
248 ** Returns:
249 ** pointer to terminating \0 or , character.
251 ** Exceptions:
252 ** F:sm.heap -- out of memory.
254 ** Side Effects:
255 ** adds the setting to the database.
258 static const char *
259 parse_named_setting_x(s)
260 const char *s;
262 const char *pat, *endpat;
263 int level;
265 pat = s;
266 while (*s != '\0' && *s != ',' && *s != '.')
267 ++s;
268 endpat = s;
269 if (*s == '.')
271 ++s;
272 level = 0;
273 while (isascii(*s) && isdigit(*s))
275 level = level * 10 + (*s - '0');
276 ++s;
278 if (level < 0)
279 level = 0;
281 else
282 level = 1;
284 sm_debug_addsetting_x(sm_strndup_x(pat, endpat - pat), level);
286 /* skip trailing junk */
287 while (*s != '\0' && *s != ',')
288 ++s;
290 return s;
294 ** SM_DEBUG_ADDSETTINGS_X -- process a list of debug options
296 ** Parameters:
297 ** s -- a list of debug settings, eg the argument to the
298 ** sendmail -d option.
300 ** The syntax of the string s is as follows:
302 ** <settings> ::= <setting> | <settings> "," <setting>
303 ** <setting> ::= <categories> | <categories> "." <level>
304 ** <categories> ::= [a-zA-Z_*?][a-zA-Z0-9_*?]*
306 ** However, note that we skip over anything we don't
307 ** understand, rather than report an error.
309 ** Returns:
310 ** none.
312 ** Exceptions:
313 ** F:sm.heap -- out of memory
315 ** Side Effects:
316 ** updates the database of debug settings.
319 void
320 sm_debug_addsettings_x(s)
321 const char *s;
323 for (;;)
325 if (*s == '\0')
326 return;
327 if (*s == ',')
329 ++s;
330 continue;
332 s = parse_named_setting_x(s);
337 ** SM_DEBUG_LOADLEVEL -- Get activation level of the specified debug object.
339 ** Parameters:
340 ** debug -- debug object.
342 ** Returns:
343 ** Activation level of the specified debug object.
345 ** Side Effects:
346 ** Ensures that the debug object is initialized.
350 sm_debug_loadlevel(debug)
351 SM_DEBUG_T *debug;
353 if (debug->debug_level == SM_DEBUG_UNKNOWN)
355 SM_DEBUG_SETTING_T *s;
357 for (s = SmDebugSettings; s != NULL; s = s->ds_next)
359 if (sm_match(debug->debug_name, s->ds_pattern))
361 debug->debug_level = s->ds_level;
362 goto initialized;
365 debug->debug_level = 0;
366 initialized:
367 debug->debug_next = SmDebugInitialized;
368 SmDebugInitialized = debug;
370 return (int) debug->debug_level;
374 ** SM_DEBUG_LOADACTIVE -- Activation level reached?
376 ** Parameters:
377 ** debug -- debug object.
378 ** level -- level to check.
380 ** Returns:
381 ** true iff the activation level of the specified debug
382 ** object >= level.
384 ** Side Effects:
385 ** Ensures that the debug object is initialized.
388 bool
389 sm_debug_loadactive(debug, level)
390 SM_DEBUG_T *debug;
391 int level;
393 return sm_debug_loadlevel(debug) >= level;