1 /* debug.c - helpful output in desperate situations
2 Copyright (C) 2000 Werner Koch (dd9jn)
3 Copyright (C) 2001, 2002, 2003, 2004, 2005, 2007, 2009 g10 Code GmbH
5 This file is part of GPGME.
7 GPGME is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as
9 published by the Free Software Foundation; either version 2.1 of
10 the License, or (at your option) any later version.
12 GPGME is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public
18 License along with this program; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
20 MA 02110-1301, USA. */
35 #ifndef HAVE_DOSISH_SYSTEM
36 # include <sys/types.h>
37 # include <sys/stat.h>
48 /* Lock to serialize initialization of the debug output subsystem and
49 output of actual debug messages. */
50 DEFINE_STATIC_LOCK (debug_lock);
52 /* The amount of detail requested by the user, per environment
53 variable GPGME_DEBUG. */
54 static int debug_level;
56 /* The output stream for the debug messages. */
62 static __thread int frame_nr = 0;
66 _gpgme_debug_frame_begin (void)
73 void _gpgme_debug_frame_end (void)
82 /* Remove leading and trailing white spaces. */
84 trim_spaces (char *str)
86 char *string, *p, *mark;
89 /* Find first non space character. */
90 for (p = string; *p && isspace (*(unsigned char *) p); p++)
92 /* Move characters. */
93 for (mark = NULL; (*string = *p); string++, p++)
94 if (isspace (*(unsigned char *) p))
102 *mark = '\0'; /* Remove trailing spaces. */
111 static int initialized;
118 const char *s1, *s2;;
120 #ifdef HAVE_W32CE_SYSTEM
121 e = _gpgme_w32ce_get_debug_envvar ();
122 #else /*!HAVE_W32CE_SYSTEM*/
123 err = _gpgme_getenv ("GPGME_DEBUG", &e);
129 #endif /*!HAVE_W32CE_SYSTEM*/
135 debug_level = atoi (e);
136 s1 = strchr (e, PATHSEP_C);
139 #ifndef HAVE_DOSISH_SYSTEM
140 if (getuid () == geteuid ()
141 #if defined(HAVE_GETGID) && defined(HAVE_GETEGID)
142 && getgid () == getegid ()
151 if (!(s2 = strchr (s1, PATHSEP_C)))
152 s2 = s1 + strlen (s1);
153 p = malloc (s2 - s1 + 1);
156 memcpy (p, s1, s2 - s1);
162 setvbuf (fp, NULL, _IOLBF, 0);
167 #ifndef HAVE_DOSISH_SYSTEM
177 _gpgme_debug (DEBUG_INIT, "gpgme_debug: level=%d\n", debug_level);
182 /* This should be called as soon as the locks are intialized. It is
183 required so that the assuan logging gets conncted to the gpgme log
184 stream as early as possible. */
186 _gpgme_debug_subsystem_init (void)
194 /* Log the formatted string FORMAT at debug level LEVEL or higher. */
196 _gpgme_debug (int level, const char *format, ...)
202 if (debug_level < level)
205 va_start (arg_ptr, format);
209 time_t atime = time (NULL);
211 tp = localtime (&atime);
212 fprintf (errfp, "GPGME %04d-%02d-%02d %02d:%02d:%02d <0x%04llx> ",
213 1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday,
214 tp->tm_hour, tp->tm_min, tp->tm_sec,
215 (unsigned long long) ath_self ());
220 int nr_spaces = sizeof (spaces) - 1;
223 nr_columns = 2 * (frame_nr - 1);
224 if (nr_columns > nr_spaces)
225 nr_columns = nr_spaces;
228 spaces[nr_columns] = '\0';
229 fprintf (errfp, "%s", spaces);
233 vfprintf (errfp, format, arg_ptr);
235 if(format && *format && format[strlen (format) - 1] != '\n')
240 gpg_err_set_errno (saved_errno);
244 /* Start a new debug line in *LINE, logged at level LEVEL or higher,
245 and starting with the formatted string FORMAT. */
247 _gpgme_debug_begin (void **line, int level, const char *format, ...)
252 if (debug_level < level)
254 /* Disable logging of this line. */
259 va_start (arg_ptr, format);
260 res = vasprintf ((char **) line, format, arg_ptr);
267 /* Add the formatted string FORMAT to the debug line *LINE. */
269 _gpgme_debug_add (void **line, const char *format, ...)
279 va_start (arg_ptr, format);
280 res = vasprintf (&toadd, format, arg_ptr);
287 res = asprintf (&result, "%s%s", *(char **) line, toadd);
297 /* Finish construction of *LINE and send it to the debug output
300 _gpgme_debug_end (void **line)
305 /* The smallest possible level is 1, so force logging here by
307 _gpgme_debug (1, "%s", *line);
313 #define TOHEX(val) (((val) < 10) ? ((val) + '0') : ((val) - 10 + 'a'))
316 _gpgme_debug_buffer (int lvl, const char *const fmt,
317 const char *const func, const char *const buffer,
323 if (!_gpgme_debug_trace ())
330 char *strp2 = &str[34];
332 for (j = 0; j < 16; j++)
338 *(strp++) = TOHEX (val >> 4);
339 *(strp++) = TOHEX (val % 16);
340 *(strp2++) = isprint (val) ? val : '.';
353 _gpgme_debug (lvl, fmt, func, str);