1 /*
2  * Copyright (c) 2000, 2001, 2003 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  *	$Id: debug.h,v 1.16 2003/01/10 00:26:06 ca Exp $
10  */
11 
12 #pragma ident	"%Z%%M%	%I%	%E% SMI"
13 
14 /*
15 **  libsm debugging and tracing
16 **  See libsm/debug.html for documentation.
17 */
18 
19 #ifndef SM_DEBUG_H
20 # define SM_DEBUG_H
21 
22 # include <sm/gen.h>
23 # include <sm/io.h>
24 
25 /*
26 **  abstractions for printing trace messages
27 */
28 
29 extern SM_FILE_T *
30 sm_debug_file __P((void));
31 
32 extern void
33 sm_debug_setfile __P(( SM_FILE_T *));
34 
35 extern void PRINTFLIKE(1, 2)
36 sm_dprintf __P((char *_fmt, ...));
37 
38 extern void
39 sm_dflush __P((void));
40 
41 extern void
42 sm_debug_close __P((void));
43 
44 /*
45 **  abstractions for setting and testing debug activation levels
46 */
47 
48 extern void
49 sm_debug_addsettings_x __P((const char *));
50 
51 extern void
52 sm_debug_addsetting_x __P((const char *, int));
53 
54 # define SM_DEBUG_UNKNOWN	((SM_ATOMIC_UINT_T)(-1))
55 
56 extern const char SmDebugMagic[];
57 
58 typedef struct sm_debug SM_DEBUG_T;
59 struct sm_debug
60 {
61 	const char *sm_magic;	/* points to SmDebugMagic */
62 
63 	/*
64 	**  debug_level is the activation level of this debug
65 	**  object.  Level 0 means no debug activity.
66 	**  It is initialized to SM_DEBUG_UNKNOWN, which indicates
67 	**  that the true value is unknown.  If debug_level ==
68 	**  SM_DEBUG_UNKNOWN, then the access functions will look up
69 	**  its true value in the internal table of debug settings.
70 	*/
71 
72 	SM_ATOMIC_UINT_T debug_level;
73 
74 	/*
75 	**  debug_name is the name used to reference this SM_DEBUG
76 	**  structure via the sendmail -d option.
77 	*/
78 
79 	char *debug_name;
80 
81 	/*
82 	**  debug_desc is a literal character string of the form
83 	**  "@(#)$Debug: <name> - <short description> $"
84 	*/
85 
86 	char *debug_desc;
87 
88 	/*
89 	**  We keep a linked list of initialized SM_DEBUG structures
90 	**  so that when sm_debug_addsetting is called, we can reset
91 	**  them all back to the uninitialized state.
92 	*/
93 
94 	SM_DEBUG_T *debug_next;
95 };
96 
97 # ifndef SM_DEBUG_CHECK
98 #  define SM_DEBUG_CHECK 1
99 # endif /* ! SM_DEBUG_CHECK */
100 
101 # if SM_DEBUG_CHECK
102 /*
103 **  This macro is cleverly designed so that if the debug object is below
104 **  the specified level, then the only overhead is a single comparison
105 **  (except for the first time this macro is invoked).
106 */
107 
108 #  define sm_debug_active(debug, level) \
109 	    ((debug)->debug_level >= (level) && \
110 	     ((debug)->debug_level != SM_DEBUG_UNKNOWN || \
111 	      sm_debug_loadactive(debug, level)))
112 
113 #  define sm_debug_level(debug) \
114 	    ((debug)->debug_level == SM_DEBUG_UNKNOWN \
115 	     ? sm_debug_loadlevel(debug) : (debug)->debug_level)
116 
117 #  define sm_debug_unknown(debug) ((debug)->debug_level == SM_DEBUG_UNKNOWN)
118 # else /* SM_DEBUG_CHECK */
119 #  define sm_debug_active(debug, level)	0
120 #  define sm_debug_level(debug)		0
121 #  define sm_debug_unknown(debug)	0
122 # endif /* SM_DEBUG_CHECK */
123 
124 extern bool
125 sm_debug_loadactive __P((SM_DEBUG_T *, int));
126 
127 extern int
128 sm_debug_loadlevel __P((SM_DEBUG_T *));
129 
130 # define SM_DEBUG_INITIALIZER(name, desc) { \
131 		SmDebugMagic, \
132 		SM_DEBUG_UNKNOWN, \
133 		name, \
134 		desc, \
135 		NULL}
136 
137 #endif /* ! SM_DEBUG_H */
138