Add better debug printing. Use reader threads for W32
[gpgme.git] / gpgme / debug.c
1 /* debug.c
2  *      Copyright (C) 2001 Werner Koch (dd9jn)
3  *
4  * This file is part of GPGME.
5  *
6  * GPGME is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * GPGME is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19  */
20
21 #include <config.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <stdarg.h>
26 #include <assert.h>
27
28 #include "util.h"
29 #include "sema.h"
30
31 DEFINE_STATIC_LOCK (debug_lock);
32
33 struct debug_control_s {
34     FILE *fp;
35     char fname[100];
36 };
37
38 static int debug_level = 0;
39
40 static void
41 debug_init (void)
42 {
43     static volatile int initialized = 0;
44        
45     if (initialized) 
46         return;
47     LOCK (debug_lock);
48     if (!initialized) {
49         const char *e = getenv ("GPGME_DEBUG");
50         
51         debug_level =  e? atoi (e): 0;
52         initialized = 1;
53         if (debug_level > 0)
54             fprintf (stderr,"gpgme_debug: level=%d\n", debug_level);
55     }
56     UNLOCK (debug_lock);
57 }
58
59
60 void
61 _gpgme_debug (int level, const char *format, ...)
62 {
63     va_list arg_ptr ;
64
65     debug_init ();
66     if ( debug_level < level )
67         return;
68     
69     va_start ( arg_ptr, format ) ;
70     LOCK (debug_lock);
71     vfprintf (stderr, format, arg_ptr) ;
72     va_end ( arg_ptr ) ;
73     if( format && *format && format[strlen(format)-1] != '\n' )
74         putc ('\n', stderr);
75     UNLOCK (debug_lock);
76     fflush (stderr);
77 }
78
79
80
81 void
82 _gpgme_debug_begin ( void **helper, int level, const char *text)
83 {
84     struct debug_control_s *ctl;
85
86     debug_init ();
87
88     *helper = NULL;
89     if ( debug_level < level )
90         return;
91     ctl = xtrycalloc (1, sizeof *ctl );
92     if (!ctl) {
93         _gpgme_debug (255, __FILE__ ":" STR2(__LINE__)": out of core");
94         return;
95     }
96
97     /* Oh what a pitty sthat we don't have a asprintf or snprintf under
98      * Windoze.  We definitely should write our own clib for W32! */
99     sprintf ( ctl->fname, "/tmp/gpgme_debug.%d.%p", getpid (), ctl );
100     ctl->fp = fopen (ctl->fname, "w+");
101     if (!ctl->fp) {
102         _gpgme_debug (255,__FILE__ ":" STR2(__LINE__)": failed to create `%s'",
103                       ctl->fname );
104         xfree (ctl);
105         return;
106     }
107     *helper = ctl;
108     _gpgme_debug_add (helper, "%s", text );
109 }
110
111 int
112 _gpgme_debug_enabled (void **helper)
113 {
114     return helper && *helper;
115 }
116
117
118 void
119 _gpgme_debug_add (void **helper, const char *format, ...)
120 {
121     struct debug_control_s *ctl = *helper;
122     va_list arg_ptr ;
123
124     if ( !*helper )
125         return;
126     
127     va_start ( arg_ptr, format ) ;
128     vfprintf (ctl->fp, format, arg_ptr) ;
129     va_end ( arg_ptr ) ;
130 }
131
132 void
133 _gpgme_debug_end (void **helper, const char *text)
134 {
135     struct debug_control_s *ctl = *helper;
136     int c, last_c=EOF;
137
138     if ( !*helper )
139         return;
140     
141     _gpgme_debug_add (helper, "%s", text );
142     rewind (ctl->fp);
143     LOCK (debug_lock);
144     while ( (c=getc (ctl->fp)) != EOF ) {
145         putc (c, stderr);
146         last_c = c;
147     }
148     if (last_c != '\n')
149         putc ('\n', stderr);
150     UNLOCK (debug_lock);
151     
152     remove (ctl->fname);
153     xfree (ctl);
154     *helper = NULL;
155 }
156