1/* misc.c
2 * Copyright (C) 1999, 2001, 2002, 2003, 2007,
3 *               2008 Free Software Foundation, Inc.
4 *
5 * This file is part of Libgcrypt.
6 *
7 * Libgcrypt is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU Lesser General Public License as
9 * published by the Free Software Foundation; either version 2.1 of
10 * the License, or (at your option) any later version.
11 *
12 * Libgcrypt is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this program; if not, see <http://www.gnu.org/licenses/>.
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
28#include "g10lib.h"
29#include "secmem.h"
30
31static int verbosity_level = 0;
32
33static void (*fatal_error_handler)(void*,int, const char*) = NULL;
34static void *fatal_error_handler_value = 0;
35static void (*log_handler)(void*,int, const char*, va_list) = NULL;
36static void *log_handler_value = 0;
37
38static const char *(*user_gettext_handler)( const char * ) = NULL;
39
40void
41gcry_set_gettext_handler( const char *(*f)(const char*) )
42{
43    user_gettext_handler = f;
44}
45
46
47const char *
48_gcry_gettext( const char *key )
49{
50    if( user_gettext_handler )
51	return user_gettext_handler( key );
52    /* FIXME: switch the domain to gnupg and restore later */
53    return key;
54}
55
56void
57gcry_set_fatalerror_handler( void (*fnc)(void*,int, const char*), void *value)
58{
59    fatal_error_handler_value = value;
60    fatal_error_handler = fnc;
61}
62
63static void
64write2stderr( const char *s )
65{
66  /* Dummy variable to silence gcc warning.  */
67  int res = write( 2, s, strlen(s) );
68  (void) res;
69}
70
71/*
72 * This function is called for fatal errors.  A caller might want to
73 * set his own handler because this function simply calls abort().
74 */
75void
76_gcry_fatal_error (int rc, const char *text)
77{
78  if ( !text ) /* get a default text */
79    text = gpg_strerror (rc);
80
81  if (fatal_error_handler && !fips_mode () )
82    fatal_error_handler (fatal_error_handler_value, rc, text);
83
84  fips_signal_fatal_error (text);
85  write2stderr("\nFatal error: ");
86  write2stderr(text);
87  write2stderr("\n");
88  _gcry_secmem_term ();
89  abort ();
90}
91
92void
93gcry_set_log_handler( void (*f)(void*,int, const char*, va_list ),
94							    void *opaque )
95{
96    log_handler = f;
97    log_handler_value = opaque;
98}
99
100void
101_gcry_set_log_verbosity( int level )
102{
103    verbosity_level = level;
104}
105
106int
107_gcry_log_verbosity( int level )
108{
109    return verbosity_level >= level;
110}
111
112/****************
113 * This is our log function which prints all log messages to stderr or
114 * using the function defined with gcry_set_log_handler().
115 */
116static void
117_gcry_logv( int level, const char *fmt, va_list arg_ptr )
118{
119  if (log_handler)
120    log_handler (log_handler_value, level, fmt, arg_ptr);
121  else
122    {
123      switch (level)
124        {
125        case GCRY_LOG_CONT:  break;
126        case GCRY_LOG_INFO:  break;
127        case GCRY_LOG_WARN:  break;
128        case GCRY_LOG_ERROR: break;
129        case GCRY_LOG_FATAL: fputs("Fatal: ",stderr ); break;
130        case GCRY_LOG_BUG:   fputs("Ohhhh jeeee: ", stderr); break;
131        case GCRY_LOG_DEBUG: fputs("DBG: ", stderr ); break;
132        default: fprintf(stderr,"[Unknown log level %d]: ", level ); break;
133	}
134      vfprintf(stderr,fmt,arg_ptr) ;
135    }
136
137  if ( level == GCRY_LOG_FATAL || level == GCRY_LOG_BUG )
138    {
139      fips_signal_fatal_error ("internal error (fatal or bug)");
140      _gcry_secmem_term ();
141      abort ();
142    }
143}
144
145
146void
147_gcry_log( int level, const char *fmt, ... )
148{
149    va_list arg_ptr ;
150
151    va_start( arg_ptr, fmt ) ;
152    _gcry_logv( level, fmt, arg_ptr );
153    va_end(arg_ptr);
154}
155
156
157#if defined(JNLIB_GCC_M_FUNCTION) || __STDC_VERSION__ >= 199901L
158void
159_gcry_bug( const char *file, int line, const char *func )
160{
161    _gcry_log( GCRY_LOG_BUG,
162	     ("... this is a bug (%s:%d:%s)\n"), file, line, func );
163    abort(); /* never called, but it makes the compiler happy */
164}
165void
166_gcry_assert_failed (const char *expr, const char *file, int line,
167                     const char *func)
168{
169  _gcry_log (GCRY_LOG_BUG,
170             ("Assertion `%s' failed (%s:%d:%s)\n"), expr, file, line, func );
171  abort(); /* Never called, but it makes the compiler happy. */
172}
173#else
174void
175_gcry_bug( const char *file, int line )
176{
177    _gcry_log( GCRY_LOG_BUG,
178	     _("you found a bug ... (%s:%d)\n"), file, line);
179    abort(); /* never called, but it makes the compiler happy */
180}
181void
182_gcry_assert_failed (const char *expr, const char *file, int line)
183{
184  _gcry_log (GCRY_LOG_BUG,
185             ("Assertion `%s' failed (%s:%d)\n"), expr, file, line);
186  abort(); /* Never called, but it makes the compiler happy. */
187}
188#endif
189
190void
191_gcry_log_info( const char *fmt, ... )
192{
193    va_list arg_ptr ;
194
195    va_start( arg_ptr, fmt ) ;
196    _gcry_logv( GCRY_LOG_INFO, fmt, arg_ptr );
197    va_end(arg_ptr);
198}
199
200int
201_gcry_log_info_with_dummy_fp (FILE *fp, const char *fmt, ... )
202{
203    va_list arg_ptr;
204
205    (void)fp;
206    va_start( arg_ptr, fmt ) ;
207    _gcry_logv( GCRY_LOG_INFO, fmt, arg_ptr );
208    va_end(arg_ptr);
209    return 0;
210}
211
212void
213_gcry_log_error( const char *fmt, ... )
214{
215    va_list arg_ptr ;
216
217    va_start( arg_ptr, fmt ) ;
218    _gcry_logv( GCRY_LOG_ERROR, fmt, arg_ptr );
219    va_end(arg_ptr);
220}
221
222
223void
224_gcry_log_fatal( const char *fmt, ... )
225{
226    va_list arg_ptr ;
227
228    va_start( arg_ptr, fmt ) ;
229    _gcry_logv( GCRY_LOG_FATAL, fmt, arg_ptr );
230    va_end(arg_ptr);
231    abort(); /* never called, but it makes the compiler happy */
232}
233
234void
235_gcry_log_bug( const char *fmt, ... )
236{
237    va_list arg_ptr ;
238
239    va_start( arg_ptr, fmt ) ;
240    _gcry_logv( GCRY_LOG_BUG, fmt, arg_ptr );
241    va_end(arg_ptr);
242    abort(); /* never called, but it makes the compiler happy */
243}
244
245void
246_gcry_log_debug( const char *fmt, ... )
247{
248    va_list arg_ptr ;
249
250    va_start( arg_ptr, fmt ) ;
251    _gcry_logv( GCRY_LOG_DEBUG, fmt, arg_ptr );
252    va_end(arg_ptr);
253}
254
255
256void
257_gcry_log_printf (const char *fmt, ...)
258{
259  va_list arg_ptr;
260
261  if (fmt)
262    {
263      va_start( arg_ptr, fmt ) ;
264      _gcry_logv (GCRY_LOG_CONT, fmt, arg_ptr);
265      va_end(arg_ptr);
266    }
267}
268
269/* Print a hexdump of BUFFER.  With TEXT of NULL print just the raw
270   dump, with TEXT an empty string, print a trailing linefeed,
271   otherwise print an entire debug line. */
272void
273_gcry_log_printhex (const char *text, const void *buffer, size_t length)
274{
275  if (text && *text)
276    log_debug ("%s ", text);
277  if (length)
278    {
279      const unsigned char *p = buffer;
280      log_printf ("%02X", *p);
281      for (length--, p++; length--; p++)
282        log_printf (" %02X", *p);
283    }
284  if (text)
285    log_printf ("\n");
286}
287
288
289void
290_gcry_burn_stack (int bytes)
291{
292    char buf[64];
293
294    wipememory (buf, sizeof buf);
295    bytes -= sizeof buf;
296    if (bytes > 0)
297        _gcry_burn_stack (bytes);
298}
299