* global.c (gcry_set_progress_handler): Register a random progress
[libgcrypt.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 )
93         fclose( logstream );
94     logstream = fp;
95     missing_lf = 0;
96 }
97
98
99 void
100 log_set_prefix (const char *text, unsigned int flags)
101 {
102   if (text)
103     {
104       strncpy (prefix_buffer, text, sizeof (prefix_buffer)-1);
105       prefix_buffer[sizeof (prefix_buffer)-1] = 0;
106     }
107   
108   with_prefix = (flags & 1);
109   with_time = (flags & 2);
110   with_pid  = (flags & 4);
111 }
112
113 int
114 log_get_fd()
115 {
116     return fileno(logstream?logstream:stderr);
117 }
118
119 FILE *
120 log_get_stream ()
121 {
122     return logstream?logstream:stderr;
123 }
124
125
126 static void
127 do_logv( int level, const char *fmt, va_list arg_ptr )
128 {
129   if (!logstream)
130     logstream = stderr;
131
132   if (missing_lf && level != JNLIB_LOG_CONT)
133     putc('\n', logstream );
134   missing_lf = 0;
135
136   if (level != JNLIB_LOG_CONT)
137     { /* Note this does not work for multiple line logging as we would
138        * need to print to a buffer first */
139       if (with_time)
140         {
141           struct tm *tp;
142           time_t atime = time (NULL);
143           
144           tp = localtime (&atime);
145           fprintf (logstream, "%04d-%02d-%02d %02d:%02d:%02d ",
146                    1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday,
147                    tp->tm_hour, tp->tm_min, tp->tm_sec );
148         }
149       if (with_prefix)
150         fputs (prefix_buffer, logstream);
151       if (with_pid)
152         fprintf (logstream, "[%u]", (unsigned int)getpid ());
153       if (!with_time)
154         putc (':', logstream);
155       putc (' ', logstream);
156     }
157
158   switch (level)
159     {
160     case JNLIB_LOG_BEGIN: break;
161     case JNLIB_LOG_CONT: break;
162     case JNLIB_LOG_INFO: break;
163     case JNLIB_LOG_WARN: break;
164     case JNLIB_LOG_ERROR: break;
165     case JNLIB_LOG_FATAL: fputs("Fatal: ",logstream ); break;
166     case JNLIB_LOG_BUG: fputs("Ohhhh jeeee: ", logstream); break;
167     case JNLIB_LOG_DEBUG: fputs("DBG: ", logstream ); break;
168     default: fprintf(logstream,"[Unknown log level %d]: ", level ); break;
169     }
170
171   if (fmt)
172     {
173       vfprintf(logstream,fmt,arg_ptr) ;
174       if (*fmt && fmt[strlen(fmt)-1] != '\n')
175         missing_lf = 1;
176     }
177
178   if (level == JNLIB_LOG_FATAL)
179     exit(2);
180   if (level == JNLIB_LOG_BUG)
181     abort();
182 }
183
184 static void
185 do_log( int level, const char *fmt, ... )
186 {
187     va_list arg_ptr ;
188
189     va_start( arg_ptr, fmt ) ;
190     do_logv( level, fmt, arg_ptr );
191     va_end(arg_ptr);
192 }
193
194
195 void
196 log_logv (int level, const char *fmt, va_list arg_ptr)
197 {
198   do_logv (level, fmt, arg_ptr);
199 }
200
201 void
202 log_info( const char *fmt, ... )
203 {
204     va_list arg_ptr ;
205
206     va_start( arg_ptr, fmt ) ;
207     do_logv( JNLIB_LOG_INFO, fmt, arg_ptr );
208     va_end(arg_ptr);
209 }
210
211 void
212 log_error( const char *fmt, ... )
213 {
214     va_list arg_ptr ;
215
216     va_start( arg_ptr, fmt ) ;
217     do_logv( JNLIB_LOG_ERROR, fmt, arg_ptr );
218     va_end(arg_ptr);
219     /* protect against counter overflow */
220     if( errorcount < 30000 )
221         errorcount++;
222 }
223
224
225 void
226 log_fatal( const char *fmt, ... )
227 {
228     va_list arg_ptr ;
229
230     va_start( arg_ptr, fmt ) ;
231     do_logv( JNLIB_LOG_FATAL, fmt, arg_ptr );
232     va_end(arg_ptr);
233     abort(); /* never called, bugs it makes the compiler happy */
234 }
235
236 void
237 log_bug( const char *fmt, ... )
238 {
239     va_list arg_ptr ;
240
241     va_start( arg_ptr, fmt ) ;
242     do_logv( JNLIB_LOG_BUG, fmt, arg_ptr );
243     va_end(arg_ptr);
244     abort(); /* never called, but it makes the compiler happy */
245 }
246
247 void
248 log_debug( const char *fmt, ... )
249 {
250     va_list arg_ptr ;
251
252     va_start( arg_ptr, fmt ) ;
253     do_logv( JNLIB_LOG_DEBUG, fmt, arg_ptr );
254     va_end(arg_ptr);
255 }
256
257
258 void
259 log_printf (const char *fmt, ...)
260 {
261   va_list arg_ptr;
262
263   va_start (arg_ptr, fmt);
264   do_logv (fmt ? JNLIB_LOG_CONT : JNLIB_LOG_BEGIN, fmt, arg_ptr);
265   va_end (arg_ptr);
266 }
267
268 /* Print a hexdump of BUFFER.  With TEXT of NULL print just the raw
269    dump, with TEXT just an empty string, print a trailing linefeed,
270    otherwise print an entire debug line. */
271 void
272 log_printhex (const char *text, const void *buffer, size_t length)
273 {
274   if (text && *text)
275     log_debug ("%s ", text);
276   if (length)
277     {
278       const unsigned char *p = buffer;
279       log_printf ("%02X", *p);
280       for (length--, p++; length--; p++)
281         log_printf (" %02X", *p);
282     }
283   if (text)
284     log_printf ("\n");
285 }
286
287
288 #if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 5 )
289 void
290 bug_at( const char *file, int line, const char *func )
291 {
292     do_log( JNLIB_LOG_BUG,
293              ("... this is a bug (%s:%d:%s)\n"), file, line, func );
294     abort(); /* never called, but it makes the compiler happy */
295 }
296 #else
297 void
298 bug_at( const char *file, int line )
299 {
300     do_log( JNLIB_LOG_BUG,
301              _("you found a bug ... (%s:%d)\n"), file, line);
302     abort(); /* never called, but it makes the compiler happy */
303 }
304 #endif
305