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
29extern SM_FILE_T *
30sm_debug_file __P((void));
31
32extern void
33sm_debug_setfile __P(( SM_FILE_T *));
34
35extern void PRINTFLIKE(1, 2)
36sm_dprintf __P((char *_fmt, ...));
37
38extern void
39sm_dflush __P((void));
40
41extern void
42sm_debug_close __P((void));
43
44/*
45**  abstractions for setting and testing debug activation levels
46*/
47
48extern void
49sm_debug_addsettings_x __P((const char *));
50
51extern void
52sm_debug_addsetting_x __P((const char *, int));
53
54# define SM_DEBUG_UNKNOWN	((SM_ATOMIC_UINT_T)(-1))
55
56extern const char SmDebugMagic[];
57
58typedef struct sm_debug SM_DEBUG_T;
59struct 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
124extern bool
125sm_debug_loadactive __P((SM_DEBUG_T *, int));
126
127extern int
128sm_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