1 /* debug.h - interface to debugging functions
2    Copyright (C) 2002, 2004, 2005, 2007 g10 Code GmbH
3 
4    This file is part of GPGME.
5 
6    GPGME is free software; you can redistribute it and/or modify it
7    under the terms of the GNU Lesser General Public License as
8    published by the Free Software Foundation; either version 2.1 of
9    the License, or (at your option) any later version.
10 
11    GPGME is distributed in the hope that it will be useful, but
12    WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    Lesser General Public License for more details.
15 
16    You should have received a copy of the GNU Lesser General Public
17    License along with this program; if not, write to the Free Software
18    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19    02111-1307, USA.  */
20 
21 #ifndef DEBUG_H
22 #define DEBUG_H
23 
24 #include <string.h>
25 #ifdef HAVE_STDINT_H
26 #include <stdint.h>
27 #endif
28 #include <errno.h>
29 
30 #include "gpgme.h"  /* Required for gpgme_error stuff.  */
31 
32 
33 /* Indirect stringification, requires __STDC__ to work.  */
34 #define STRINGIFY(v) #v
35 #define XSTRINGIFY(v) STRINGIFY(v)
36 
37 
38 /*
39  * The debug levels.
40  *
41  * Note that TRACE_LOGBUFX uses the current debug level + 1.
42  */
43 
44 #define DEBUG_INIT	1
45 #define DEBUG_GLOBAL    2
46 #define DEBUG_CTX	3
47 #define DEBUG_ENGINE	4
48 #define DEBUG_DATA	5
49 #define DEBUG_ASSUAN	6
50 #define DEBUG_SYSIO	7
51 
52 
53 /* Remove path components from filenames (i.e. __FILE__) for cleaner
54    logs. */
55 static inline const char *_gpgme_debug_srcname (const char *file)
56                                                 GPGME_GCC_A_PURE;
57 
58 static inline const char *
_gpgme_debug_srcname(const char * file)59 _gpgme_debug_srcname (const char *file)
60 {
61   const char *s = strrchr (file, '/');
62   return s? s+1:file;
63 }
64 
65 /* Initialization helper function; see debug.c.  */
66 int _gpgme_debug_set_debug_envvar (const char *value);
67 
68 /* Called early to initialize the logging.  */
69 void _gpgme_debug_subsystem_init (void);
70 
71 /* Log the formatted string FORMAT at debug level LEVEL or higher.  */
72 int  _gpgme_debug (void **line, int level, int mode,
73                    const char *func, const char *tagname, const char *tagvalue,
74                    const char *format, ...) GPGRT_ATTR_PRINTF(7,8);
75 
76 
77 /* Add the formatted string FORMAT to the debug line *LINE.  */
78 void _gpgme_debug_add (void **helper, const char *format, ...);
79 
80 /* Finish construction of *LINE and send it to the debug output
81    stream.  */
82 void _gpgme_debug_end (void **helper);
83 
84 void _gpgme_debug_buffer (int lvl, const char *const fmt,
85 			  const char *const func, const char *const buffer,
86 			  size_t len);
87 
88 void _gpgme_debug_frame_begin (void);
89 int  _gpgme_debug_frame_end (void);
90 
91 static inline gpgme_error_t
_gpgme_trace_gpgme_error(gpgme_error_t err,const char * file,int line)92 _gpgme_trace_gpgme_error (gpgme_error_t err, const char *file, int line)
93 {
94   _gpgme_debug (NULL, DEBUG_ENGINE, -1, NULL, NULL, NULL,
95                 "%s:%d: returning error: %s\n",
96                 _gpgme_debug_srcname (file), line, gpgme_strerror (err));
97   return err;
98 }
99 
100 
101 /* Trace support.  */
102 
103 /* FIXME: For now.  */
104 #define _gpgme_debug_trace() 1
105 
106 #define _TRACE(lvl, name, tag)					\
107   int _gpgme_trace_level = lvl;					\
108   const char *const _gpgme_trace_func = name;			\
109   const char *const _gpgme_trace_tagname = STRINGIFY (tag);	\
110   void *_gpgme_trace_tag = (void *) (uintptr_t) tag; \
111   _gpgme_debug_frame_begin ()
112 
113 /* Note: We can't protect this with a do-while block.  */
114 #define TRACE_BEG(lvl, name, tag, ...)                                  \
115   _TRACE (lvl, name, tag);						\
116   _gpgme_debug (NULL, _gpgme_trace_level, 1,                             \
117                 _gpgme_trace_func, _gpgme_trace_tagname, _gpgme_trace_tag, \
118                 __VA_ARGS__)
119 
120 #define TRACE(lvl, name, tag, ...) do {                                 \
121     _gpgme_debug_frame_begin ();					\
122     _gpgme_debug (NULL, lvl, 0, name, STRINGIFY (tag), (void *)(uintptr_t)tag, \
123                   __VA_ARGS__);                                         \
124     _gpgme_debug_frame_end ();                                          \
125   } while (0)
126 
127 
128 /* Trace a gpg-error and return it.  */
129 #define TRACE_ERR(err) \
130     _trace_err ((err), _gpgme_trace_level, _gpgme_trace_func, __LINE__)
131 static inline gpg_error_t
_trace_err(gpg_error_t err,int lvl,const char * func,int line)132 _trace_err (gpg_error_t err, int lvl, const char *func, int line)
133 {
134   if (!err)
135     _gpgme_debug (NULL, lvl, 3, func, NULL, NULL, "");
136   else
137     _gpgme_debug (NULL, lvl, -1, NULL, NULL, NULL,
138                   "%s:%d: error: %s <%s>\n",
139                   func, line,  gpgme_strerror (err), gpgme_strsource (err));
140   _gpgme_debug_frame_end ();
141   return err;
142 }
143 
144 /* Trace a system call result and return it.  */
145 #define TRACE_SYSRES(res) \
146     _trace_sysres ((res), _gpgme_trace_level, _gpgme_trace_func, __LINE__)
147 static inline int
_trace_sysres(int res,int lvl,const char * func,int line)148 _trace_sysres (int res, int lvl, const char *func, int line)
149 {
150   if (res >= 0)
151     _gpgme_debug (NULL, lvl, 3, func, NULL, NULL, "result=%d", res);
152   else
153     _gpgme_debug (NULL, lvl, -1, NULL, NULL, NULL,
154                   "%s:%d: error: %s (%d)\n",
155                   func, line,  strerror (errno), errno);
156   _gpgme_debug_frame_end ();
157   return res;
158 }
159 
160 /* Trace a system call error and return it.  */
161 #define TRACE_SYSERR(rc) \
162     _trace_syserr ((rc), _gpgme_trace_level, _gpgme_trace_func, __LINE__)
163 static inline int
_trace_syserr(int rc,int lvl,const char * func,int line)164 _trace_syserr (int rc, int lvl, const char *func, int line)
165 {
166   if (!rc)
167     _gpgme_debug (NULL, lvl, 3, func, NULL, NULL, "result=0");
168   else
169     _gpgme_debug (NULL, lvl, -1, NULL, NULL, NULL,
170                   "%s:%d: error: %s (%d)\n",
171                   func, line, strerror (rc), rc);
172   _gpgme_debug_frame_end ();
173   return rc;
174 }
175 
176 #define TRACE_SUC(...) do {                                             \
177     _gpgme_debug (NULL, _gpgme_trace_level, 3, _gpgme_trace_func, NULL, NULL, \
178                   __VA_ARGS__);                                         \
179     _gpgme_debug_frame_end ();                                          \
180   } while (0)
181 
182 #define TRACE_LOG(...) do {                                             \
183     _gpgme_debug (NULL, _gpgme_trace_level, 2,                           \
184                   _gpgme_trace_func, _gpgme_trace_tagname, _gpgme_trace_tag, \
185                   __VA_ARGS__);                                         \
186   } while (0)
187 
188 #define TRACE_LOGBUF(buf, len) do {                             \
189     _gpgme_debug_buffer (_gpgme_trace_level, "%s: check: %s",	\
190                          _gpgme_trace_func, buf, len);          \
191   } while (0)
192 
193 #define TRACE_LOGBUFX(buf, len) do {                                    \
194     _gpgme_debug_buffer (_gpgme_trace_level+1, "%s: check: %s",         \
195                          _gpgme_trace_func, buf, len); \
196   } while (0)
197 
198 #define TRACE_SEQ(hlp,...) do {						      \
199     _gpgme_debug (&(hlp), _gpgme_trace_level, 2, _gpgme_trace_func,            \
200                          _gpgme_trace_tagname, _gpgme_trace_tag, __VA_ARGS__); \
201   } while (0)
202 
203 #define TRACE_ADD0(hlp,fmt) \
204   _gpgme_debug_add (&(hlp), fmt)
205 #define TRACE_ADD1(hlp,fmt,a) \
206   _gpgme_debug_add (&(hlp), fmt, (a))
207 #define TRACE_ADD2(hlp,fmt,a,b) \
208   _gpgme_debug_add (&(hlp), fmt, (a), (b))
209 #define TRACE_ADD3(hlp,fmt,a,b,c) \
210   _gpgme_debug_add (&(hlp), fmt, (a), (b), (c))
211 #define TRACE_END(hlp,fmt) \
212   _gpgme_debug_add (&(hlp), fmt); \
213   _gpgme_debug_end (&(hlp))
214 
215 #define TRACE_ENABLED(hlp) (!!(hlp))
216 
217 /* And finally a simple macro to trace the location of an error code.
218    This macro is independent of the other trace macros and may be used
219    without any preconditions.  */
220 #define trace_gpg_error(e) \
221   _gpgme_trace_gpgme_error (gpg_error (e), __FILE__, __LINE__)
222 
223 
224 #endif	/* DEBUG_H */
225