agent: Print a warning for obsolete options.
[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  * This file is free software; you can redistribute it and/or modify
7  * it under the terms of either
8  *
9  *   - the GNU Lesser General Public License as published by the Free
10  *     Software Foundation; either version 3 of the License, or (at
11  *     your option) any later version.
12  *
13  * or
14  *
15  *   - the GNU General Public License as published by the Free
16  *     Software Foundation; either version 2 of the License, or (at
17  *     your option) any later version.
18  *
19  * or both in parallel, as here.
20  *
21  * This file is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24  * GNU General Public License for more details.
25  *
26  * You should have received a copy of the GNU General Public License
27  * along with this program; if not, see <http://www.gnu.org/licenses/>.
28  */
29
30 #include <config.h>
31 #include <stdlib.h>
32 #include <errno.h>
33
34 #include "util.h"
35 #include "iobuf.h"
36 #include "i18n.h"
37
38 /* Used by libgcrypt for logging.  */
39 static void
40 my_gcry_logger (void *dummy, int level, const char *fmt, va_list arg_ptr)
41 {
42   (void)dummy;
43
44   /* Map the log levels.  */
45   switch (level)
46     {
47     case GCRY_LOG_CONT: level = GPGRT_LOG_CONT; break;
48     case GCRY_LOG_INFO: level = GPGRT_LOG_INFO; break;
49     case GCRY_LOG_WARN: level = GPGRT_LOG_WARN; break;
50     case GCRY_LOG_ERROR:level = GPGRT_LOG_ERROR; break;
51     case GCRY_LOG_FATAL:level = GPGRT_LOG_FATAL; break;
52     case GCRY_LOG_BUG:  level = GPGRT_LOG_BUG; break;
53     case GCRY_LOG_DEBUG:level = GPGRT_LOG_DEBUG; break;
54     default:            level = GPGRT_LOG_ERROR; break;
55     }
56   log_logv (level, fmt, arg_ptr);
57 }
58
59
60 /* This function is called by libgcrypt on a fatal error.  */
61 static void
62 my_gcry_fatalerror_handler (void *opaque, int rc, const char *text)
63 {
64   (void)opaque;
65
66   log_fatal ("libgcrypt problem: %s\n", text ? text : gpg_strerror (rc));
67   abort ();
68 }
69
70
71 /* This function is called by libgcrypt if it ran out of core and
72    there is no way to return that error to the caller.  We do our own
73    function here to make use of our logging functions. */
74 static int
75 my_gcry_outofcore_handler (void *opaque, size_t req_n, unsigned int flags)
76 {
77   static int been_here;  /* Used to protect against recursive calls. */
78
79   (void)opaque;
80
81   if (!been_here)
82     {
83       been_here = 1;
84       if ( (flags & 1) )
85         log_fatal (_("out of core in secure memory "
86                      "while allocating %lu bytes"), (unsigned long)req_n);
87       else
88         log_fatal (_("out of core while allocating %lu bytes"),
89                    (unsigned long)req_n);
90     }
91   return 0; /* Let libgcrypt call its own fatal error handler.
92                Actually this will turn out to be
93                my_gcry_fatalerror_handler. */
94 }
95
96
97 /* Setup libgcrypt to use our own logging functions.  Should be used
98    early at startup. */
99 void
100 setup_libgcrypt_logging (void)
101 {
102   gcry_set_log_handler (my_gcry_logger, NULL);
103   gcry_set_fatalerror_handler (my_gcry_fatalerror_handler, NULL);
104   gcry_set_outofcore_handler (my_gcry_outofcore_handler, NULL);
105 }
106
107
108 /* A wrapper around gcry_cipher_algo_name to return the string
109    "AES-128" instead of "AES".  Given that we have an alias in
110    libgcrypt for it, it does not harm to too much to return this other
111    string.  Some users complained that we print "AES" but "AES192"
112    and "AES256".  We can't fix that in libgcrypt but it is pretty
113    safe to do it in an application. */
114 const char *
115 gnupg_cipher_algo_name (int algo)
116 {
117   const char *s;
118
119   s = gcry_cipher_algo_name (algo);
120   if (!strcmp (s, "AES"))
121     s = "AES128";
122   return s;
123 }
124
125
126 void
127 obsolete_option (const char *configname, unsigned int configlineno,
128                  const char *name)
129 {
130   if (configname)
131     log_info (_("%s:%u: obsolete option \"%s\" - it has no effect\n"),
132               configname, configlineno, name);
133   else
134     log_info (_("WARNING: \"%s%s\" is an obsolete option - it has no effect\n"),
135               "--", name);
136 }
137
138
139 /* Decide whether the filename is stdout or a real filename and return
140  * an appropriate string.  */
141 const char *
142 print_fname_stdout (const char *s)
143 {
144     if( !s || (*s == '-' && !s[1]) )
145         return "[stdout]";
146     return s;
147 }
148
149
150 /* Decide whether the filename is stdin or a real filename and return
151  * an appropriate string.  */
152 const char *
153 print_fname_stdin (const char *s)
154 {
155     if( !s || (*s == '-' && !s[1]) )
156         return "[stdin]";
157     return s;
158 }
159
160
161 static int
162 do_print_utf8_buffer (estream_t stream,
163                       const void *buffer, size_t length,
164                       const char *delimiters, size_t *bytes_written)
165 {
166   const char *p = buffer;
167   size_t i;
168
169   /* We can handle plain ascii simpler, so check for it first. */
170   for (i=0; i < length; i++ )
171     {
172       if ( (p[i] & 0x80) )
173         break;
174     }
175   if (i < length)
176     {
177       int delim = delimiters? *delimiters : 0;
178       char *buf;
179       int ret;
180
181       /*(utf8 conversion already does the control character quoting). */
182       buf = utf8_to_native (p, length, delim);
183       if (bytes_written)
184         *bytes_written = strlen (buf);
185       ret = es_fputs (buf, stream);
186       xfree (buf);
187       return ret == EOF? ret : (int)i;
188     }
189   else
190     return es_write_sanitized (stream, p, length, delimiters, bytes_written);
191 }
192
193
194 void
195 print_utf8_buffer3 (estream_t stream, const void *p, size_t n,
196                     const char *delim)
197 {
198   do_print_utf8_buffer (stream, p, n, delim, NULL);
199 }
200
201
202 void
203 print_utf8_buffer2 (estream_t stream, const void *p, size_t n, int delim)
204 {
205   char tmp[2];
206
207   tmp[0] = delim;
208   tmp[1] = 0;
209   do_print_utf8_buffer (stream, p, n, tmp, NULL);
210 }
211
212
213 void
214 print_utf8_buffer (estream_t stream, const void *p, size_t n)
215 {
216   do_print_utf8_buffer (stream, p, n, NULL, NULL);
217 }
218
219 /* Write LENGTH bytes of BUFFER to FP as a hex encoded string.
220    RESERVED must be 0. */
221 void
222 print_hexstring (FILE *fp, const void *buffer, size_t length, int reserved)
223 {
224 #define tohex(n) ((n) < 10 ? ((n) + '0') : (((n) - 10) + 'A'))
225   const unsigned char *s;
226
227   (void)reserved;
228
229   for (s = buffer; length; s++, length--)
230     {
231       putc ( tohex ((*s>>4)&15), fp);
232       putc ( tohex (*s&15), fp);
233     }
234 #undef tohex
235 }
236
237 char *
238 make_printable_string (const void *p, size_t n, int delim )
239 {
240   return sanitize_buffer (p, n, delim);
241 }
242
243
244
245 /*
246  * Check if the file is compressed.
247  */
248 int
249 is_file_compressed (const char *s, int *ret_rc)
250 {
251     iobuf_t a;
252     byte buf[4];
253     int i, rc = 0;
254     int overflow;
255
256     struct magic_compress_s {
257         size_t len;
258         byte magic[4];
259     } magic[] = {
260         { 3, { 0x42, 0x5a, 0x68, 0x00 } }, /* bzip2 */
261         { 3, { 0x1f, 0x8b, 0x08, 0x00 } }, /* gzip */
262         { 4, { 0x50, 0x4b, 0x03, 0x04 } }, /* (pk)zip */
263     };
264
265     if ( iobuf_is_pipe_filename (s) || !ret_rc )
266         return 0; /* We can't check stdin or no file was given */
267
268     a = iobuf_open( s );
269     if ( a == NULL ) {
270         *ret_rc = gpg_error_from_syserror ();
271         return 0;
272     }
273
274     if ( iobuf_get_filelength( a, &overflow ) < 4 && !overflow) {
275         *ret_rc = 0;
276         goto leave;
277     }
278
279     if ( iobuf_read( a, buf, 4 ) == -1 ) {
280         *ret_rc = a->error;
281         goto leave;
282     }
283
284     for ( i = 0; i < DIM( magic ); i++ ) {
285         if ( !memcmp( buf, magic[i].magic, magic[i].len ) ) {
286             *ret_rc = 0;
287             rc = 1;
288             break;
289         }
290     }
291
292 leave:
293     iobuf_close( a );
294     return rc;
295 }
296
297
298 /* Try match against each substring of multistr, delimited by | */
299 int
300 match_multistr (const char *multistr,const char *match)
301 {
302   do
303     {
304       size_t seglen = strcspn (multistr,"|");
305       if (!seglen)
306         break;
307       /* Using the localized strncasecmp! */
308       if (strncasecmp(multistr,match,seglen)==0)
309         return 1;
310       multistr += seglen;
311       if (*multistr == '|')
312         multistr++;
313     }
314   while (*multistr);
315
316   return 0;
317 }
318
319
320 \f
321 /* Parse the first portion of the version number S and store it at
322    NUMBER.  On success, the function returns a pointer into S starting
323    with the first character, which is not part of the initial number
324    portion; on failure, NULL is returned.  */
325 static const char*
326 parse_version_number (const char *s, int *number)
327 {
328   int val = 0;
329
330   if (*s == '0' && digitp (s+1))
331     return NULL; /* Leading zeros are not allowed.  */
332   for (; digitp (s); s++ )
333     {
334       val *= 10;
335       val += *s - '0';
336     }
337   *number = val;
338   return val < 0? NULL : s;
339 }
340
341 /* Break up the complete string representation of the version number S,
342    which is expected to have this format:
343
344       <major number>.<minor number>.<micro number><patch level>.
345
346    The major, minor and micro number components will be stored at
347    MAJOR, MINOR and MICRO. On success, a pointer to the last
348    component, the patch level, will be returned; on failure, NULL will
349    be returned.  */
350 static const char *
351 parse_version_string (const char *s, int *major, int *minor, int *micro)
352 {
353   s = parse_version_number (s, major);
354   if (!s || *s != '.')
355     return NULL;
356   s++;
357   s = parse_version_number (s, minor);
358   if (!s || *s != '.')
359     return NULL;
360   s++;
361   s = parse_version_number (s, micro);
362   if (!s)
363     return NULL;
364   return s; /* Patchlevel.  */
365 }
366
367 /* Return true if version string is at least version B. */
368 int
369 gnupg_compare_version (const char *a, const char *b)
370 {
371   int a_major, a_minor, a_micro;
372   int b_major, b_minor, b_micro;
373   const char *a_plvl, *b_plvl;
374
375   if (!a || !b)
376     return 0;
377
378   /* Parse version A.  */
379   a_plvl = parse_version_string (a, &a_major, &a_minor, &a_micro);
380   if (!a_plvl )
381     return 0; /* Invalid version number.  */
382
383   /* Parse version B.  */
384   b_plvl = parse_version_string (b, &b_major, &b_minor, &b_micro);
385   if (!b_plvl )
386     return 0; /* Invalid version number.  */
387
388   /* Compare version numbers.  */
389   return (a_major > b_major
390           || (a_major == b_major && a_minor > b_minor)
391           || (a_major == b_major && a_minor == b_minor
392               && a_micro > b_micro)
393           || (a_major == b_major && a_minor == b_minor
394               && a_micro == b_micro
395               && strcmp (a_plvl, b_plvl) >= 0));
396 }