Line data Source code
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
4 :
5 : This file is part of Assuan.
6 :
7 : Assuan 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.
11 :
12 : Assuan 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.
16 :
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. */
21 :
22 : #if HAVE_CONFIG_H
23 : #include <config.h>
24 : #endif
25 : #include <stdio.h>
26 : #include <stdlib.h>
27 : #include <string.h>
28 : #include <stdarg.h>
29 : #ifdef HAVE_UNISTD_H
30 : # include <unistd.h>
31 : #endif
32 : #include <ctype.h>
33 : #include <errno.h>
34 : #ifndef HAVE_DOSISH_SYSTEM
35 : # include <sys/types.h>
36 : # include <sys/stat.h>
37 : # include <fcntl.h>
38 : #endif
39 : #include <assert.h>
40 :
41 : #include "assuan-defs.h"
42 : #include "debug.h"
43 :
44 :
45 : /* Log the formatted string FORMAT at debug category CAT higher. */
46 : void
47 0 : _assuan_debug (assuan_context_t ctx, unsigned int cat, const char *format, ...)
48 : {
49 : va_list arg_ptr;
50 : int saved_errno;
51 : char *msg;
52 : int res;
53 :
54 : /* vasprintf is an expensive operation thus we first check whether
55 : the callback has enabled CAT for logging. */
56 0 : if (!ctx
57 0 : || !ctx->log_cb
58 0 : || !(*ctx->log_cb) (ctx, ctx->log_cb_data, cat, NULL))
59 0 : return;
60 :
61 0 : saved_errno = errno;
62 0 : va_start (arg_ptr, format);
63 0 : res = gpgrt_vasprintf (&msg, format, arg_ptr);
64 0 : va_end (arg_ptr);
65 0 : if (res < 0)
66 0 : return;
67 0 : ctx->log_cb (ctx, ctx->log_cb_data, cat, msg);
68 0 : free (msg);
69 0 : gpg_err_set_errno (saved_errno);
70 : }
71 :
72 :
73 : /* Start a new debug line in *LINE, logged at level LEVEL or higher,
74 : and starting with the formatted string FORMAT. */
75 : void
76 0 : _assuan_debug_begin (assuan_context_t ctx,
77 : void **line, unsigned int cat, const char *format, ...)
78 : {
79 : va_list arg_ptr;
80 : int res;
81 :
82 0 : *line = NULL;
83 : /* Probe if this wants to be logged based on category. */
84 0 : if (! ctx
85 0 : || ! ctx->log_cb
86 0 : || ! (*ctx->log_cb) (ctx, ctx->log_cb_data, cat, NULL))
87 0 : return;
88 :
89 0 : va_start (arg_ptr, format);
90 0 : res = gpgrt_vasprintf ((char **) line, format, arg_ptr);
91 0 : va_end (arg_ptr);
92 0 : if (res < 0)
93 0 : *line = NULL;
94 : }
95 :
96 :
97 : /* Add the formatted string FORMAT to the debug line *LINE. */
98 : void
99 0 : _assuan_debug_add (assuan_context_t ctx, void **line, const char *format, ...)
100 : {
101 : va_list arg_ptr;
102 : char *toadd;
103 : char *result;
104 : int res;
105 :
106 0 : if (!*line)
107 0 : return;
108 :
109 0 : va_start (arg_ptr, format);
110 0 : res = gpgrt_vasprintf (&toadd, format, arg_ptr);
111 0 : va_end (arg_ptr);
112 0 : if (res < 0)
113 : {
114 0 : free (*line);
115 0 : *line = NULL;
116 : }
117 0 : res = gpgrt_asprintf (&result, "%s%s", *(char **) line, toadd);
118 0 : free (toadd);
119 0 : free (*line);
120 0 : if (res < 0)
121 0 : *line = NULL;
122 : else
123 0 : *line = result;
124 : }
125 :
126 :
127 : /* Finish construction of *LINE and send it to the debug output
128 : stream. */
129 : void
130 0 : _assuan_debug_end (assuan_context_t ctx, void **line, unsigned int cat)
131 : {
132 0 : if (!*line)
133 0 : return;
134 :
135 : /* Force logging here by using category ~0. */
136 0 : _assuan_debug (ctx, ~0, "%s", *line);
137 0 : free (*line);
138 0 : *line = NULL;
139 : }
140 :
141 :
142 : #define TOHEX(val) (((val) < 10) ? ((val) + '0') : ((val) - 10 + 'a'))
143 :
144 : void
145 0 : _assuan_debug_buffer (assuan_context_t ctx, unsigned int cat,
146 : const char *const fmt, const char *const func,
147 : const char *const tagname, void *tag,
148 : const char *const buffer, size_t len)
149 : {
150 0 : int idx = 0;
151 : int j;
152 :
153 : /* Probe if this wants to be logged based on category. */
154 0 : if (!ctx
155 0 : || ! ctx->log_cb
156 0 : || ! (*ctx->log_cb) (ctx, ctx->log_cb_data, cat, NULL))
157 0 : return;
158 :
159 0 : while (idx < len)
160 : {
161 : char str[51];
162 0 : char *strp = str;
163 0 : char *strp2 = &str[34];
164 :
165 0 : for (j = 0; j < 16; j++)
166 : {
167 : unsigned char val;
168 0 : if (idx < len)
169 : {
170 0 : val = buffer[idx++];
171 0 : *(strp++) = TOHEX (val >> 4);
172 0 : *(strp++) = TOHEX (val % 16);
173 0 : *(strp2++) = isprint (val) ? val : '.';
174 : }
175 : else
176 : {
177 0 : *(strp++) = ' ';
178 0 : *(strp++) = ' ';
179 : }
180 0 : if (j == 7)
181 0 : *(strp++) = ' ';
182 : }
183 0 : *(strp++) = ' ';
184 0 : *(strp2++) = '\n';
185 0 : *(strp2) = '\0';
186 :
187 0 : _assuan_debug (ctx, cat, fmt, func, tagname, tag, str);
188 : }
189 : }
|