Add files to new directory.
[libgcrypt.git] / jnlib / logging.c
1 /* logging.c -  useful logging functions
2  *      Copyright (C) 1998, 1999 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 GnuPG.
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
35 #include "libjnlib-config.h"
36 #include "logging.h"
37
38 enum my_log_levels {
39     MY_LOG_BEGIN,  /* only print the timestamp if configured */
40     MY_LOG_CONT,
41     MY_LOG_INFO,
42     MY_LOG_WARN,
43     MY_LOG_ERROR,
44     MY_LOG_FATAL,
45     MY_LOG_BUG,
46     MY_LOG_DEBUG
47 };
48
49 static FILE *logstream;
50 static int use_time;
51 static int missing_lf;
52
53 #if 0
54 static void
55 write2stderr( const char *s )
56 {
57     write( 2, s, strlen(s) );
58 }
59
60
61 static void
62 do_die(int rc, const char *text )
63 {
64     write2stderr("\nFatal error: ");
65     write2stderr(text);
66     write2stderr("\n");
67     abort();
68 }
69 #endif
70
71 void
72 log_set_file( const char *name )
73 {
74     FILE *fp = (name && strcmp(name,"-"))? fopen(name, "a") : stderr;
75     if( !fp ) {
76         fprintf(stderr, "failed to open log file `%s': %s\n",
77                                                 name, strerror(errno));
78         return;
79     }
80     setvbuf( fp, NULL, _IOLBF, 0 );
81
82     if( logstream && logstream != stderr )
83         fclose( logstream );
84     logstream = fp;
85     use_time = fp != stderr;
86     missing_lf = 0;
87 }
88
89
90 int
91 log_get_fd()
92 {
93     return fileno(logstream?logstream:stderr);
94 }
95
96 static void
97 do_logv( int level, const char *fmt, va_list arg_ptr )
98 {
99     if( !logstream )
100         logstream = stderr;
101
102     if( missing_lf && level != MY_LOG_CONT )
103         putc('\n', logstream );
104     missing_lf = 0;
105
106     if( use_time && level != MY_LOG_CONT ) {
107         /* Note this does not work for multiple line logging as we would
108          * need to print to a buffer first */
109         struct tm *tp;
110         time_t atime = time(NULL);
111
112         tp = localtime( &atime );
113         fprintf( logstream, "%04d-%02d-%02d %02d:%02d:%02d ",
114                     1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday,
115                          tp->tm_hour, tp->tm_min, tp->tm_sec );
116     }
117
118     switch ( level ) {
119       case MY_LOG_BEGIN: break;
120       case MY_LOG_CONT: break;
121       case MY_LOG_INFO: break;
122       case MY_LOG_WARN: break;
123       case MY_LOG_ERROR: break;
124       case MY_LOG_FATAL: fputs("Fatal: ",logstream ); break;
125       case MY_LOG_BUG: fputs("Ohhhh jeeee: ", logstream); break;
126       case MY_LOG_DEBUG: fputs("DBG: ", logstream ); break;
127       default: fprintf(logstream,"[Unknown log level %d]: ", level ); break;
128     }
129
130     if( fmt ) {
131         vfprintf(logstream,fmt,arg_ptr) ;
132         if( *fmt && fmt[strlen(fmt)-1] != '\n' )
133             missing_lf = 1;
134     }
135
136     if( level == MY_LOG_FATAL )
137         exit(2);
138     if( level == MY_LOG_BUG )
139         abort();
140 }
141
142 static void
143 do_log( int level, const char *fmt, ... )
144 {
145     va_list arg_ptr ;
146
147     va_start( arg_ptr, fmt ) ;
148     do_logv( level, fmt, arg_ptr );
149     va_end(arg_ptr);
150 }
151
152
153
154 void
155 log_info( const char *fmt, ... )
156 {
157     va_list arg_ptr ;
158
159     va_start( arg_ptr, fmt ) ;
160     do_logv( MY_LOG_INFO, fmt, arg_ptr );
161     va_end(arg_ptr);
162 }
163
164 void
165 log_error( const char *fmt, ... )
166 {
167     va_list arg_ptr ;
168
169     va_start( arg_ptr, fmt ) ;
170     do_logv( MY_LOG_ERROR, fmt, arg_ptr );
171     va_end(arg_ptr);
172 }
173
174
175 void
176 log_fatal( const char *fmt, ... )
177 {
178     va_list arg_ptr ;
179
180     va_start( arg_ptr, fmt ) ;
181     do_logv( MY_LOG_FATAL, fmt, arg_ptr );
182     va_end(arg_ptr);
183     abort(); /* never called, bugs it makes the compiler happy */
184 }
185
186 void
187 log_bug( const char *fmt, ... )
188 {
189     va_list arg_ptr ;
190
191     va_start( arg_ptr, fmt ) ;
192     do_logv( MY_LOG_BUG, fmt, arg_ptr );
193     va_end(arg_ptr);
194     abort(); /* never called, but it makes the compiler happy */
195 }
196
197 void
198 log_debug( const char *fmt, ... )
199 {
200     va_list arg_ptr ;
201
202     va_start( arg_ptr, fmt ) ;
203     do_logv( MY_LOG_DEBUG, fmt, arg_ptr );
204     va_end(arg_ptr);
205 }
206
207
208 void
209 log_printf( const char *fmt, ... )
210 {
211     va_list arg_ptr ;
212
213     if( !fmt ) {
214         do_logv( MY_LOG_BEGIN, NULL, NULL );
215     }
216     else {
217         va_start( arg_ptr, fmt ) ;
218         do_logv( MY_LOG_CONT, fmt, arg_ptr );
219         va_end(arg_ptr);
220     }
221 }
222
223
224 #if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 5 )
225 void
226 bug_at( const char *file, int line, const char *func )
227 {
228     do_log( MY_LOG_BUG,
229              ("... this is a bug (%s:%d:%s)\n"), file, line, func );
230     abort(); /* never called, but it makes the compiler happy */
231 }
232 #else
233 void
234 bug_at( const char *file, int line )
235 {
236     do_log( MY_LOG_BUG,
237              _("you found a bug ... (%s:%d)\n"), file, line);
238     abort(); /* never called, but it makes the compiler happy */
239 }
240 #endif
241