Use a custom log handler for libassuan.
[gnupg.git] / common / miscellaneous.c
1 /* miscellaneous.c - Stuff not fitting elsewhere
2  *      Copyright (C) 2003, 2006 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 3 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, see <http://www.gnu.org/licenses/>.
18  */
19
20 #include <config.h>
21 #include <stdlib.h>
22 #include <errno.h>
23
24 #define JNLIB_NEED_LOG_LOGV
25 #include "util.h"
26 #include "iobuf.h"
27 #include "i18n.h"
28
29 /* Used by libgcrypt for logging.  */
30 static void
31 my_gcry_logger (void *dummy, int level, const char *fmt, va_list arg_ptr)
32 {
33   (void)dummy;
34   
35   /* Map the log levels.  */
36   switch (level)
37     {
38     case GCRY_LOG_CONT: level = JNLIB_LOG_CONT; break;
39     case GCRY_LOG_INFO: level = JNLIB_LOG_INFO; break;
40     case GCRY_LOG_WARN: level = JNLIB_LOG_WARN; break;
41     case GCRY_LOG_ERROR:level = JNLIB_LOG_ERROR; break;
42     case GCRY_LOG_FATAL:level = JNLIB_LOG_FATAL; break;
43     case GCRY_LOG_BUG:  level = JNLIB_LOG_BUG; break;
44     case GCRY_LOG_DEBUG:level = JNLIB_LOG_DEBUG; break;
45     default:            level = JNLIB_LOG_ERROR; break;  
46     }
47   log_logv (level, fmt, arg_ptr);
48 }
49
50
51 /* This function is called by libgcrypt on a fatal error.  */
52 static void
53 my_gcry_fatalerror_handler (void *opaque, int rc, const char *text)
54 {
55   (void)opaque;
56
57   log_fatal ("libgcrypt problem: %s\n", text ? text : gpg_strerror (rc));
58   abort ();
59 }
60
61
62 /* This function is called by libgcrypt if it ran out of core and
63    there is no way to return that error to the caller.  We do our own
64    function here to make use of our logging functions. */
65 static int
66 my_gcry_outofcore_handler (void *opaque, size_t req_n, unsigned int flags)
67 {
68   static int been_here;  /* Used to protect against recursive calls. */
69
70   (void)opaque;
71
72   if (!been_here)
73     {
74       been_here = 1;
75       if ( (flags & 1) )
76         log_fatal (_("out of core in secure memory "
77                      "while allocating %lu bytes"), (unsigned long)req_n);
78       else
79         log_fatal (_("out of core while allocating %lu bytes"),
80                    (unsigned long)req_n);
81     }
82   return 0; /* Let libgcrypt call its own fatal error handler.
83                Actually this will turn out to be
84                my_gcry_fatalerror_handler. */
85 }
86
87
88 /* Setup libgcrypt to use our own logging functions.  Should be used
89    early at startup. */
90 void
91 setup_libgcrypt_logging (void)
92 {
93   gcry_set_log_handler (my_gcry_logger, NULL);
94   gcry_set_fatalerror_handler (my_gcry_fatalerror_handler, NULL);
95   gcry_set_outofcore_handler (my_gcry_outofcore_handler, NULL);
96 }
97
98
99 /* Decide whether the filename is stdout or a real filename and return
100  * an appropriate string.  */
101 const char *
102 print_fname_stdout (const char *s)
103 {
104     if( !s || (*s == '-' && !s[1]) )
105         return "[stdout]";
106     return s;
107 }
108
109
110 /* Decide whether the filename is stdin or a real filename and return
111  * an appropriate string.  */
112 const char *
113 print_fname_stdin (const char *s)
114 {
115     if( !s || (*s == '-' && !s[1]) )
116         return "[stdin]";
117     return s;
118 }
119
120 /* fixme: Globally replace it by print_sanitized_buffer. */
121 void
122 print_string( FILE *fp, const byte *p, size_t n, int delim )
123 {
124   print_sanitized_buffer (fp, p, n, delim);
125 }
126
127 void
128 print_utf8_string2 ( FILE *fp, const byte *p, size_t n, int delim )
129 {
130   print_sanitized_utf8_buffer (fp, p, n, delim);
131 }
132
133 void
134 print_utf8_string( FILE *fp, const byte *p, size_t n )
135 {
136     print_utf8_string2 (fp, p, n, 0);
137 }
138
139 /* Write LENGTH bytes of BUFFER to FP as a hex encoded string.
140    RESERVED must be 0. */
141 void
142 print_hexstring (FILE *fp, const void *buffer, size_t length, int reserved)
143 {
144 #define tohex(n) ((n) < 10 ? ((n) + '0') : (((n) - 10) + 'A'))
145   const unsigned char *s;
146
147   (void)reserved;
148
149   for (s = buffer; length; s++, length--)
150     {
151       putc ( tohex ((*s>>4)&15), fp);
152       putc ( tohex (*s&15), fp);
153     }
154 #undef tohex
155 }
156
157 char *
158 make_printable_string (const void *p, size_t n, int delim )
159 {
160   return sanitize_buffer (p, n, delim);
161 }
162
163
164
165 /*
166  * Check if the file is compressed.
167  */
168 int
169 is_file_compressed (const char *s, int *ret_rc)
170 {
171     iobuf_t a;
172     byte buf[4];
173     int i, rc = 0;
174     int overflow;
175
176     struct magic_compress_s {
177         size_t len;
178         byte magic[4];
179     } magic[] = {
180         { 3, { 0x42, 0x5a, 0x68, 0x00 } }, /* bzip2 */
181         { 3, { 0x1f, 0x8b, 0x08, 0x00 } }, /* gzip */
182         { 4, { 0x50, 0x4b, 0x03, 0x04 } }, /* (pk)zip */
183     };
184     
185     if ( iobuf_is_pipe_filename (s) || !ret_rc )
186         return 0; /* We can't check stdin or no file was given */
187
188     a = iobuf_open( s );
189     if ( a == NULL ) {
190         *ret_rc = gpg_error_from_syserror ();
191         return 0;
192     }
193
194     if ( iobuf_get_filelength( a, &overflow ) < 4 && !overflow) {
195         *ret_rc = 0;
196         goto leave;
197     }
198
199     if ( iobuf_read( a, buf, 4 ) == -1 ) {
200         *ret_rc = a->error;
201         goto leave;
202     }
203
204     for ( i = 0; i < DIM( magic ); i++ ) {
205         if ( !memcmp( buf, magic[i].magic, magic[i].len ) ) {
206             *ret_rc = 0;
207             rc = 1;
208             break;
209         }
210     }
211
212 leave:    
213     iobuf_close( a );
214     return rc;
215 }
216
217
218 /* Try match against each substring of multistr, delimited by | */
219 int
220 match_multistr (const char *multistr,const char *match)
221 {
222   do
223     {
224       size_t seglen = strcspn (multistr,"|");
225       if (!seglen)
226         break;
227       /* Using the localized strncasecmp! */
228       if (strncasecmp(multistr,match,seglen)==0)
229         return 1;
230       multistr += seglen;
231       if (*multistr == '|')
232         multistr++;
233     }
234   while (*multistr);
235
236   return 0;
237 }
238
239