Line data Source code
1 : /* gpg-error.c - Determining gpg-error error codes.
2 : Copyright (C) 2004 g10 Code GmbH
3 :
4 : This file is part of libgpg-error.
5 :
6 : libgpg-error is free software; you can redistribute it and/or
7 : modify it under the terms of the GNU Lesser General Public License
8 : as published by the Free Software Foundation; either version 2.1 of
9 : the License, or (at your option) any later version.
10 :
11 : libgpg-error is distributed in the hope that it will be useful, but
12 : WITHOUT ANY WARRANTY; without even the implied warranty of
13 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 : Lesser General Public License for more details.
15 :
16 : You should have received a copy of the GNU Lesser General Public
17 : License along with libgpg-error; if not, write to the Free
18 : Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19 : 02111-1307, USA. */
20 :
21 : #if HAVE_CONFIG_H
22 : #include <config.h>
23 : #endif
24 :
25 : #include <stddef.h>
26 : #include <stdlib.h>
27 : #include <string.h>
28 : #include <errno.h>
29 : #include <limits.h>
30 : #include <stdio.h>
31 :
32 : #ifdef HAVE_LOCALE_H
33 : # include <locale.h>
34 : #endif
35 : #ifdef ENABLE_NLS
36 : #ifdef HAVE_W32_SYSTEM
37 : # include "gettext.h"
38 : #else
39 : # include <libintl.h>
40 : #endif
41 : # define _(a) gettext (a)
42 : # ifdef gettext_noop
43 : # define N_(a) gettext_noop (a)
44 : # else
45 : # define N_(a) (a)
46 : # endif
47 : #else
48 : # define _(a) (a)
49 : # define N_(a) (a)
50 : #endif
51 :
52 : #include <gpg-error.h>
53 :
54 :
55 : #if HAVE_W32_SYSTEM
56 : /* The implementation follows below. */
57 : static char *get_locale_dir (void);
58 : static void drop_locale_dir (char *locale_dir);
59 : #else
60 : #define get_locale_dir() LOCALEDIR
61 : #define drop_locale_dir(dir)
62 : #endif
63 :
64 : static void
65 0 : i18n_init (void)
66 : {
67 : #ifdef ENABLE_NLS
68 : char *locale_dir;
69 :
70 : #ifdef HAVE_LC_MESSAGES
71 : setlocale (LC_TIME, "");
72 : setlocale (LC_MESSAGES, "");
73 : #else
74 : # ifndef HAVE_W32_SYSTEM
75 0 : setlocale (LC_ALL, "" );
76 : # endif
77 : #endif
78 :
79 : /* Note that for this program we would only need the textdomain call
80 : because libgpg-error already initializes itself to its locale dir
81 : (via gpg_err_init or a constructor). However this is only done
82 : for the static standard locale and thus if the above setlocale
83 : calls select a different locale the bindtext below will do
84 : something else. */
85 :
86 : locale_dir = get_locale_dir ();
87 : if (locale_dir)
88 : {
89 0 : bindtextdomain (PACKAGE, locale_dir);
90 : drop_locale_dir (locale_dir);
91 : }
92 0 : textdomain (PACKAGE);
93 : #endif
94 0 : }
95 :
96 :
97 : #ifdef HAVE_W32_SYSTEM
98 :
99 : #include <windows.h>
100 :
101 :
102 : static char *
103 : get_locale_dir (void)
104 : {
105 : static wchar_t moddir[MAX_PATH+5];
106 : char *result, *p;
107 : int nbytes;
108 :
109 : if (!GetModuleFileNameW (NULL, moddir, MAX_PATH))
110 : *moddir = 0;
111 :
112 : #define SLDIR "\\share\\locale"
113 : if (*moddir)
114 : {
115 : nbytes = WideCharToMultiByte (CP_UTF8, 0, moddir, -1, NULL, 0, NULL, NULL);
116 : if (nbytes < 0)
117 : return NULL;
118 :
119 : result = malloc (nbytes + strlen (SLDIR) + 1);
120 : if (result)
121 : {
122 : nbytes = WideCharToMultiByte (CP_UTF8, 0, moddir, -1,
123 : result, nbytes, NULL, NULL);
124 : if (nbytes < 0)
125 : {
126 : free (result);
127 : result = NULL;
128 : }
129 : else
130 : {
131 : p = strrchr (result, '\\');
132 : if (p)
133 : *p = 0;
134 : /* If we are installed below "bin" strip that part and
135 : use the top directory instead. */
136 : p = strrchr (result, '\\');
137 : if (p && !strcmp (p+1, "bin"))
138 : *p = 0;
139 : /* Append the static part. */
140 : strcat (result, SLDIR);
141 : }
142 : }
143 : }
144 : else /* Use the old default value. */
145 : {
146 : result = malloc (10 + strlen (SLDIR) + 1);
147 : if (result)
148 : {
149 : strcpy (result, "c:\\gnupg");
150 : strcat (result, SLDIR);
151 : }
152 : }
153 : #undef SLDIR
154 : return result;
155 : }
156 :
157 :
158 : static void
159 : drop_locale_dir (char *locale_dir)
160 : {
161 : free (locale_dir);
162 : }
163 :
164 : #endif /* HAVE_W32_SYSTEM */
165 :
166 :
167 : const char *gpg_strerror_sym (gpg_error_t err);
168 : const char *gpg_strsource_sym (gpg_error_t err);
169 :
170 :
171 : static int
172 0 : get_err_from_number (char *str, gpg_error_t *err)
173 : {
174 : unsigned long nr;
175 : char *tail;
176 :
177 0 : gpg_err_set_errno (0);
178 0 : nr = strtoul (str, &tail, 0);
179 0 : if (errno)
180 : return 0;
181 :
182 0 : if (nr > UINT_MAX)
183 : return 0;
184 :
185 0 : if (*tail)
186 : {
187 0 : unsigned long cnr = strtoul (tail + 1, &tail, 0);
188 0 : if (errno || *tail)
189 : return 0;
190 :
191 0 : if (nr >= GPG_ERR_SOURCE_DIM || cnr >= GPG_ERR_CODE_DIM)
192 : return 0;
193 :
194 0 : nr = gpg_err_make (nr, cnr);
195 : }
196 :
197 0 : *err = (unsigned int) nr;
198 0 : return 1;
199 : }
200 :
201 :
202 : static int
203 0 : get_err_from_symbol_one (char *str, gpg_error_t *err,
204 : int *have_source, int *have_code)
205 : {
206 : static const char src_prefix[] = "GPG_ERR_SOURCE_";
207 : static const char code_prefix[] = "GPG_ERR_";
208 :
209 0 : if (!strncasecmp (src_prefix, str, sizeof (src_prefix) - 1))
210 : {
211 : gpg_err_source_t src;
212 :
213 0 : if (*have_source)
214 : return 0;
215 0 : *have_source = 1;
216 0 : str += sizeof (src_prefix) - 1;
217 :
218 0 : for (src = 0; src < GPG_ERR_SOURCE_DIM; src++)
219 : {
220 : const char *src_sym;
221 :
222 0 : src_sym = gpg_strsource_sym (src << GPG_ERR_SOURCE_SHIFT);
223 0 : if (src_sym && !strcasecmp (str, src_sym + sizeof (src_prefix) - 1))
224 : {
225 0 : *err |= src << GPG_ERR_SOURCE_SHIFT;
226 0 : return 1;
227 : }
228 : }
229 : }
230 0 : else if (!strncasecmp (code_prefix, str, sizeof (code_prefix) - 1))
231 : {
232 : gpg_err_code_t code;
233 :
234 0 : if (*have_code)
235 : return 0;
236 0 : *have_code = 1;
237 0 : str += sizeof (code_prefix) - 1;
238 :
239 0 : for (code = 0; code < GPG_ERR_CODE_DIM; code++)
240 : {
241 0 : const char *code_sym = gpg_strerror_sym (code);
242 0 : if (code_sym
243 0 : && !strcasecmp (str, code_sym + sizeof (code_prefix) - 1))
244 : {
245 0 : *err |= code;
246 0 : return 1;
247 : }
248 : }
249 : }
250 : return 0;
251 : }
252 :
253 :
254 : static int
255 0 : get_err_from_symbol (char *str, gpg_error_t *err)
256 : {
257 : char *str2 = str;
258 0 : int have_source = 0;
259 0 : int have_code = 0;
260 : int ret;
261 : char *saved_pos = NULL;
262 : char saved_char;
263 :
264 0 : *err = 0;
265 0 : while (*str2 && ((*str2 >= 'A' && *str2 <= 'Z')
266 0 : || (*str2 >= '0' && *str2 <= '9')
267 0 : || *str2 == '_'))
268 0 : str2++;
269 0 : if (*str2)
270 : {
271 0 : saved_pos = str2;
272 0 : saved_char = *str2;
273 0 : *str2 = '\0';
274 0 : str2++;
275 : }
276 : else
277 : str2 = NULL;
278 :
279 0 : ret = get_err_from_symbol_one (str, err, &have_source, &have_code);
280 0 : if (ret && str2)
281 0 : ret = get_err_from_symbol_one (str2, err, &have_source, &have_code);
282 :
283 0 : if (saved_pos)
284 0 : *saved_pos = saved_char;
285 0 : return ret;
286 : }
287 :
288 :
289 : static int
290 0 : get_err_from_str_one (char *str, gpg_error_t *err,
291 : int *have_source, int *have_code)
292 : {
293 : gpg_err_source_t src;
294 : gpg_err_code_t code;
295 :
296 0 : for (src = 0; src < GPG_ERR_SOURCE_DIM; src++)
297 : {
298 0 : const char *src_str = gpg_strsource (src << GPG_ERR_SOURCE_SHIFT);
299 0 : if (src_str && !strcasecmp (str, src_str))
300 : {
301 0 : if (*have_source)
302 : return 0;
303 :
304 0 : *have_source = 1;
305 0 : *err |= src << GPG_ERR_SOURCE_SHIFT;
306 0 : return 1;
307 : }
308 : }
309 :
310 0 : for (code = 0; code < GPG_ERR_CODE_DIM; code++)
311 : {
312 0 : const char *code_str = gpg_strerror (code);
313 0 : if (code_str && !strcasecmp (str, code_str))
314 : {
315 0 : if (*have_code)
316 : return 0;
317 :
318 0 : *have_code = 1;
319 0 : *err |= code;
320 0 : return 1;
321 : }
322 : }
323 :
324 : return 0;
325 : }
326 :
327 :
328 : static int
329 0 : get_err_from_str (char *str, gpg_error_t *err)
330 : {
331 : char *str2 = str;
332 0 : int have_source = 0;
333 0 : int have_code = 0;
334 : int ret;
335 : char *saved_pos = NULL;
336 : char saved_char = 0; /* (avoid warning) */
337 :
338 0 : *err = 0;
339 0 : ret = get_err_from_str_one (str, err, &have_source, &have_code);
340 0 : if (ret)
341 : return ret;
342 :
343 0 : while (*str2 && ((*str2 >= 'A' && *str2 <= 'Z')
344 0 : || (*str2 >= 'a' && *str2 <= 'z')
345 0 : || (*str2 >= '0' && *str2 <= '9')
346 0 : || *str2 == '_'))
347 0 : str2++;
348 0 : if (*str2)
349 : {
350 0 : saved_pos = str2;
351 0 : saved_char = *str2;
352 0 : *((char *) str2) = '\0';
353 0 : str2++;
354 0 : while (*str2 && !((*str2 >= 'A' && *str2 <= 'Z')
355 0 : || (*str2 >= 'a' && *str2 <= 'z')
356 0 : || (*str2 >= '0' && *str2 <= '9')
357 : || *str2 == '_'))
358 0 : str2++;
359 : }
360 : else
361 : str2 = NULL;
362 :
363 0 : ret = get_err_from_str_one (str, err, &have_source, &have_code);
364 0 : if (ret && str2)
365 0 : ret = get_err_from_str_one (str2, err, &have_source, &have_code);
366 :
367 0 : if (saved_pos)
368 0 : *saved_pos = saved_char;
369 0 : return ret;
370 : }
371 :
372 :
373 :
374 : int
375 0 : main (int argc, char *argv[])
376 : {
377 : int i = 1;
378 : int listmode = 0;
379 : const char *source_sym;
380 : const char *error_sym;
381 : gpg_error_t err;
382 :
383 0 : gpgrt_init ();
384 0 : i18n_init ();
385 :
386 0 : if (argc == 1)
387 : {
388 0 : fprintf (stderr, _("Usage: %s GPG-ERROR [...]\n"),
389 0 : strrchr (argv[0],'/')? (strrchr (argv[0], '/')+1): argv[0]);
390 0 : exit (1);
391 : }
392 0 : else if (argc == 2 && !strcmp (argv[1], "--version"))
393 : {
394 0 : fputs ("gpg-error (" PACKAGE_NAME ") " PACKAGE_VERSION "\n", stdout);
395 0 : exit (0);
396 : }
397 0 : else if (argc == 2 && !strcmp (argv[1], "--help"))
398 : {
399 0 : fputs ("gpg-error (" PACKAGE_NAME ") " PACKAGE_VERSION "\n", stdout);
400 0 : fputs ("Options:\n"
401 : " --version Print version\n"
402 : " --lib-version Print library version\n"
403 : " --help Print this help\n"
404 : " --list Print all error codes\n"
405 : " --defines Print all error codes as #define lines\n"
406 : , stdout);
407 0 : exit (0);
408 : }
409 0 : else if (argc == 2 && !strcmp (argv[1], "--lib-version"))
410 : {
411 0 : printf ("Version from header: %s (0x%06x)\n",
412 : GPG_ERROR_VERSION, GPG_ERROR_VERSION_NUMBER);
413 0 : printf ("Version from binary: %s\n", gpg_error_check_version (NULL));
414 0 : printf ("Copyright blurb ...:%s\n", gpg_error_check_version ("\x01\x01"));
415 0 : exit (0);
416 : }
417 0 : else if (argc == 2 && !strcmp (argv[1], "--list"))
418 : {
419 : listmode = 1;
420 : }
421 0 : else if (argc == 2 && !strcmp (argv[1], "--defines"))
422 : {
423 : listmode = 2;
424 : }
425 :
426 :
427 0 : if (listmode == 1)
428 : {
429 0 : for (i=0; i < GPG_ERR_SOURCE_DIM; i++)
430 : {
431 : /* We use error code 1 because gpg_err_make requires a
432 : non-zero error code. */
433 0 : err = gpg_err_make (i, 1);
434 0 : err -= 1;
435 0 : source_sym = gpg_strsource_sym (err);
436 0 : if (source_sym)
437 0 : printf ("%u = (%u, -) = (%s, -) = (%s, -)\n",
438 : err, gpg_err_source (err),
439 : source_sym, gpg_strsource (err));
440 : }
441 0 : for (i=0; i < GPG_ERR_CODE_DIM; i++)
442 : {
443 0 : err = gpg_err_make (GPG_ERR_SOURCE_UNKNOWN, i);
444 0 : error_sym = gpg_strerror_sym (err);
445 0 : if (error_sym)
446 0 : printf ("%u = (-, %u) = (-, %s) = (-, %s)\n",
447 : err, gpg_err_code (err),
448 : error_sym, gpg_strerror (err));
449 : }
450 : }
451 0 : else if (listmode == 2)
452 : {
453 : int n, nmax;
454 :
455 0 : for (i=0, nmax=0; i < GPG_ERR_SOURCE_DIM; i++)
456 : {
457 0 : err = gpg_err_make (i, 1);
458 0 : source_sym = gpg_strsource_sym (err);
459 0 : if (source_sym)
460 : {
461 0 : n = strlen (source_sym);
462 0 : if (n > nmax)
463 : nmax = n;
464 : }
465 : }
466 0 : for (i=0; i < GPG_ERR_SOURCE_DIM; i++)
467 : {
468 0 : err = gpg_err_make (i, 1);
469 0 : source_sym = gpg_strsource_sym (err);
470 0 : if (source_sym)
471 0 : printf ("#define %-*s %3u\n", nmax,source_sym,gpg_err_source (err));
472 : }
473 :
474 :
475 0 : for (i=0, nmax = 0; i < GPG_ERR_CODE_DIM; i++)
476 : {
477 0 : err = gpg_err_make (GPG_ERR_SOURCE_UNKNOWN, i);
478 0 : error_sym = gpg_strerror_sym (err);
479 0 : if (error_sym)
480 : {
481 0 : n = strlen (error_sym);
482 0 : if (n > nmax)
483 : nmax = n;
484 : }
485 : }
486 0 : for (i=0; i < GPG_ERR_CODE_DIM; i++)
487 : {
488 0 : err = gpg_err_make (GPG_ERR_SOURCE_UNKNOWN, i);
489 0 : error_sym = gpg_strerror_sym (err);
490 0 : if (error_sym)
491 0 : printf ("#define %-*s %5u\n", nmax, error_sym, gpg_err_code (err));
492 : }
493 : }
494 : else /* Standard mode. */
495 : {
496 0 : while (i < argc)
497 : {
498 0 : if (get_err_from_number (argv[i], &err)
499 0 : || get_err_from_symbol (argv[i], &err)
500 0 : || get_err_from_str (argv[i], &err))
501 : {
502 0 : source_sym = gpg_strsource_sym (err);
503 0 : error_sym = gpg_strerror_sym (err);
504 :
505 0 : printf ("%u = (%u, %u) = (%s, %s) = (%s, %s)\n",
506 : err, gpg_err_source (err), gpg_err_code (err),
507 : source_sym ? source_sym : "-", error_sym ? error_sym:"-",
508 : gpg_strsource (err), gpg_strerror (err));
509 : }
510 : else
511 0 : fprintf (stderr, _("%s: warning: could not recognize %s\n"),
512 : argv[0], argv[i]);
513 0 : i++;
514 : }
515 : }
516 :
517 0 : exit (0);
518 : }
|