Multiple signatures can now be verified.
[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 <unistd.h>
27 #include <assert.h>
28
29 #include "util.h"
30 #include "sema.h"
31
32 DEFINE_STATIC_LOCK (debug_lock);
33
34 struct debug_control_s {
35     FILE *fp;
36     char fname[100];
37 };
38
39 static int debug_level = 0;
40
41 static void
42 debug_init (void)
43 {
44     static volatile int initialized = 0;
45        
46     if (initialized) 
47         return;
48     LOCK (debug_lock);
49     if (!initialized) {
50         const char *e = getenv ("GPGME_DEBUG");
51         
52         debug_level =  e? atoi (e): 0;
53         initialized = 1;
54         if (debug_level > 0)
55             fprintf (stderr,"gpgme_debug: level=%d\n", debug_level);
56     }
57     UNLOCK (debug_lock);
58 }
59
60
61 void
62 _gpgme_debug (int level, const char *format, ...)
63 {
64     va_list arg_ptr ;
65
66     debug_init ();
67     if ( debug_level < level )
68         return;
69     
70     va_start ( arg_ptr, format ) ;
71     LOCK (debug_lock);
72     vfprintf (stderr, format, arg_ptr) ;
73     va_end ( arg_ptr ) ;
74     if( format && *format && format[strlen(format)-1] != '\n' )
75         putc ('\n', stderr);
76     UNLOCK (debug_lock);
77     fflush (stderr);
78 }
79
80
81
82 void
83 _gpgme_debug_begin ( void **helper, int level, const char *text)
84 {
85     struct debug_control_s *ctl;
86
87     debug_init ();
88
89     *helper = NULL;
90     if ( debug_level < level )
91         return;
92     ctl = xtrycalloc (1, sizeof *ctl );
93     if (!ctl) {
94         _gpgme_debug (255, __FILE__ ":" STR2(__LINE__)": out of core");
95         return;
96     }
97
98     /* Oh what a pitty that we don't have a asprintf or snprintf under
99      * Windoze.  We definitely should write our own clib for W32! */
100     sprintf ( ctl->fname, "/tmp/gpgme_debug.%d.%p", getpid (), ctl );
101     ctl->fp = fopen (ctl->fname, "w+");
102     if (!ctl->fp) {
103         _gpgme_debug (255,__FILE__ ":" STR2(__LINE__)": failed to create `%s'",
104                       ctl->fname );
105         xfree (ctl);
106         return;
107     }
108     *helper = ctl;
109     _gpgme_debug_add (helper, "%s", text );
110 }
111
112 int
113 _gpgme_debug_enabled (void **helper)
114 {
115     return helper && *helper;
116 }
117
118
119 void
120 _gpgme_debug_add (void **helper, const char *format, ...)
121 {
122     struct debug_control_s *ctl = *helper;
123     va_list arg_ptr ;
124
125     if ( !*helper )
126         return;
127     
128     va_start ( arg_ptr, format ) ;
129     vfprintf (ctl->fp, format, arg_ptr) ;
130     va_end ( arg_ptr ) ;
131 }
132
133 void
134 _gpgme_debug_end (void **helper, const char *text)
135 {
136     struct debug_control_s *ctl = *helper;
137     int c, last_c=EOF;
138
139     if ( !*helper )
140         return;
141     
142     _gpgme_debug_add (helper, "%s", text );
143     fflush (ctl->fp); /* we need this for the buggy Windoze libc */
144     rewind (ctl->fp);
145     LOCK (debug_lock);
146     while ( (c=getc (ctl->fp)) != EOF ) {
147         putc (c, stderr);
148         last_c = c;
149     }
150     if (last_c != '\n')
151         putc ('\n', stderr);
152     UNLOCK (debug_lock);
153     
154     fclose (ctl->fp);
155     remove (ctl->fname);
156     xfree (ctl);
157     *helper = NULL;
158 }
159