647e757c6c1958d4248fefa925b3d34fb8d5341f
[gpgme.git] / jnlib / logging.c
1 /* logging.c -  useful logging functions
2  *      Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
3  *
4  * This file is part of GnuPG.
5  *
6  * GnuPG 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  * GnuPG 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
22 /* This file should replace logger.c in the future - for now it is not
23  * used by GnuPG but by GPA.
24  * It is a quite simple implemenation but sufficient for most purposes.
25  */
26
27 #include <config.h>
28 #include <stdlib.h>
29 #include <stdio.h>
30 #include <string.h>
31 #include <stdarg.h>
32 #include <errno.h>
33 #include <time.h>
34 #include <sys/types.h>
35 #include <unistd.h>
36 #ifdef __MINGW32__
37   #include <io.h>
38 #endif
39
40 #define JNLIB_NEED_LOG_LOGV 1
41 #include "libjnlib-config.h"
42 #include "logging.h"
43
44
45 static FILE *logstream;
46 static char prefix_buffer[80];
47 static int with_time;
48 static int with_prefix;
49 static int with_pid;
50
51 static int missing_lf;
52 static int errorcount;
53
54 #if 0
55 static void
56 write2stderr( const char *s )
57 {
58     write( 2, s, strlen(s) );
59 }
60
61
62 static void
63 do_die(int rc, const char *text )
64 {
65     write2stderr("\nFatal error: ");
66     write2stderr(text);
67     write2stderr("\n");
68     abort();
69 }
70 #endif
71
72 int
73 log_get_errorcount (int clear)
74 {
75     int n = errorcount;
76     if( clear )
77         errorcount = 0;
78     return n;
79 }
80
81 void
82 log_set_file( const char *name )
83 {
84     FILE *fp = (name && strcmp(name,"-"))? fopen(name, "a") : stderr;
85     if( !fp ) {
86         fprintf(stderr, "failed to open log file `%s': %s\n",
87                                                 name, strerror(errno));
88         return;
89     }
90     setvbuf( fp, NULL, _IOLBF, 0 );
91
92     if (logstream && logstream != stderr && logstream != stdout)
93       fclose( logstream );
94     logstream = fp;
95     missing_lf = 0;
96 }
97
98 void
99 log_set_fd (int fd)
100 {
101   FILE *fp;
102   
103   if (fd == 1)
104     fp = stdout;
105   else if (fd == 2)
106     fp = stderr;
107   else
108     fp = fdopen (fd, "a");
109   if (!fp)
110     {
111       fprintf (stderr, "failed to fdopen log fd %d: %s\n",
112                fd, strerror(errno));
113       return;
114     }
115   setvbuf (fp, NULL, _IOLBF, 0);
116   
117   if (logstream && logstream != stderr && logstream != stdout)
118     fclose( logstream);
119   logstream = fp;
120   missing_lf = 0;
121 }
122
123
124 void
125 log_set_prefix (const char *text, unsigned int flags)
126 {
127   if (text)
128     {
129       strncpy (prefix_buffer, text, sizeof (prefix_buffer)-1);
130       prefix_buffer[sizeof (prefix_buffer)-1] = 0;
131     }
132   
133   with_prefix = (flags & 1);
134   with_time = (flags & 2);
135   with_pid  = (flags & 4);
136 }
137
138
139 const char *
140 log_get_prefix (unsigned int *flags)
141 {
142   if (flags)
143     {
144       *flags = 0;
145       if (with_prefix)
146         *flags |= 1;
147       if (with_time)
148         *flags |= 2;
149       if (with_pid)
150         *flags |=4;
151     }
152   return prefix_buffer;
153 }
154
155 int
156 log_get_fd()
157 {
158     return fileno(logstream?logstream:stderr);
159 }
160
161 FILE *
162 log_get_stream ()
163 {
164     return logstream?logstream:stderr;
165 }
166
167
168 static void
169 do_logv( int level, const char *fmt, va_list arg_ptr )
170 {
171   if (!logstream)
172     logstream = stderr;
173
174   if (missing_lf && level != JNLIB_LOG_CONT)
175     putc('\n', logstream );
176   missing_lf = 0;
177
178   if (level != JNLIB_LOG_CONT)
179     { /* Note this does not work for multiple line logging as we would
180        * need to print to a buffer first */
181       if (with_time)
182         {
183           struct tm *tp;
184           time_t atime = time (NULL);
185           
186           tp = localtime (&atime);
187           fprintf (logstream, "%04d-%02d-%02d %02d:%02d:%02d ",
188                    1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday,
189                    tp->tm_hour, tp->tm_min, tp->tm_sec );
190         }
191       if (with_prefix)
192         fputs (prefix_buffer, logstream);
193       if (with_pid)
194         fprintf (logstream, "[%u]", (unsigned int)getpid ());
195       if (!with_time)
196         putc (':', logstream);
197       putc (' ', logstream);
198     }
199
200   switch (level)
201     {
202     case JNLIB_LOG_BEGIN: break;
203     case JNLIB_LOG_CONT: break;
204     case JNLIB_LOG_INFO: break;
205     case JNLIB_LOG_WARN: break;
206     case JNLIB_LOG_ERROR: break;
207     case JNLIB_LOG_FATAL: fputs("Fatal: ",logstream ); break;
208     case JNLIB_LOG_BUG: fputs("Ohhhh jeeee: ", logstream); break;
209     case JNLIB_LOG_DEBUG: fputs("DBG: ", logstream ); break;
210     default: fprintf(logstream,"[Unknown log level %d]: ", level ); break;
211     }
212
213   if (fmt)
214     {
215       vfprintf(logstream,fmt,arg_ptr) ;
216       if (*fmt && fmt[strlen(fmt)-1] != '\n')
217         missing_lf = 1;
218     }
219
220   if (level == JNLIB_LOG_FATAL)
221     exit(2);
222   if (level == JNLIB_LOG_BUG)
223     abort();
224 }
225
226 static void
227 do_log( int level, const char *fmt, ... )
228 {
229     va_list arg_ptr ;
230
231     va_start( arg_ptr, fmt ) ;
232     do_logv( level, fmt, arg_ptr );
233     va_end(arg_ptr);
234 }
235
236
237 void
238 log_logv (int level, const char *fmt, va_list arg_ptr)
239 {
240   do_logv (level, fmt, arg_ptr);
241 }
242
243 void
244 log_info( const char *fmt, ... )
245 {
246     va_list arg_ptr ;
247
248     va_start( arg_ptr, fmt ) ;
249     do_logv( JNLIB_LOG_INFO, fmt, arg_ptr );
250     va_end(arg_ptr);
251 }
252
253 void
254 log_error( const char *fmt, ... )
255 {
256     va_list arg_ptr ;
257
258     va_start( arg_ptr, fmt ) ;
259     do_logv( JNLIB_LOG_ERROR, fmt, arg_ptr );
260     va_end(arg_ptr);
261     /* protect against counter overflow */
262     if( errorcount < 30000 )
263         errorcount++;
264 }
265
266
267 void
268 log_fatal( const char *fmt, ... )
269 {
270     va_list arg_ptr ;
271
272     va_start( arg_ptr, fmt ) ;
273     do_logv( JNLIB_LOG_FATAL, fmt, arg_ptr );
274     va_end(arg_ptr);
275     abort(); /* never called, bugs it makes the compiler happy */
276 }
277
278 void
279 log_bug( const char *fmt, ... )
280 {
281     va_list arg_ptr ;
282
283     va_start( arg_ptr, fmt ) ;
284     do_logv( JNLIB_LOG_BUG, fmt, arg_ptr );
285     va_end(arg_ptr);
286     abort(); /* never called, but it makes the compiler happy */
287 }
288
289 void
290 log_debug( const char *fmt, ... )
291 {
292     va_list arg_ptr ;
293
294     va_start( arg_ptr, fmt ) ;
295     do_logv( JNLIB_LOG_DEBUG, fmt, arg_ptr );
296     va_end(arg_ptr);
297 }
298
299
300 void
301 log_printf (const char *fmt, ...)
302 {
303   va_list arg_ptr;
304
305   va_start (arg_ptr, fmt);
306   do_logv (fmt ? JNLIB_LOG_CONT : JNLIB_LOG_BEGIN, fmt, arg_ptr);
307   va_end (arg_ptr);
308 }
309
310 /* Print a hexdump of BUFFER.  With TEXT of NULL print just the raw
311    dump, with TEXT just an empty string, print a trailing linefeed,
312    otherwise print an entire debug line. */
313 void
314 log_printhex (const char *text, const void *buffer, size_t length)
315 {
316   if (text && *text)
317     log_debug ("%s ", text);
318   if (length)
319     {
320       const unsigned char *p = buffer;
321       log_printf ("%02X", *p);
322       for (length--, p++; length--; p++)
323         log_printf (" %02X", *p);
324     }
325   if (text)
326     log_printf ("\n");
327 }
328
329
330 #if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 5 )
331 void
332 bug_at( const char *file, int line, const char *func )
333 {
334     do_log( JNLIB_LOG_BUG,
335              ("... this is a bug (%s:%d:%s)\n"), file, line, func );
336     abort(); /* never called, but it makes the compiler happy */
337 }
338 #else
339 void
340 bug_at( const char *file, int line )
341 {
342     do_log( JNLIB_LOG_BUG,
343              _("you found a bug ... (%s:%d)\n"), file, line);
344     abort(); /* never called, but it makes the compiler happy */
345 }
346 #endif
347