Line data Source code
1 : /* mapstrings.c - Static string mapping
2 : * Copyright (C) 2014 Werner Koch
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 "stringhelp.h"
36 : #include "membuf.h"
37 :
38 :
39 : static struct {
40 : const char *name;
41 : const char *value;
42 : } macros[] = {
43 : #ifdef PACKAGE_BUGREPORT
44 : { "EMAIL", PACKAGE_BUGREPORT },
45 : #else
46 : { "EMAIL", "bug@example.org" },
47 : #endif
48 : { "GNUPG", GNUPG_NAME },
49 : { "GPG", GPG_NAME },
50 : { "GPGSM", GPGSM_NAME },
51 : { "GPG_AGENT", GPG_AGENT_NAME },
52 : { "SCDAEMON", SCDAEMON_NAME },
53 : { "DIRMNGR", DIRMNGR_NAME },
54 : { "G13", G13_NAME },
55 : { "GPGCONF", GPGCONF_NAME },
56 : { "GPGTAR", GPGTAR_NAME }
57 : };
58 :
59 :
60 :
61 : /* A list to remember already done mappings. */
62 : struct mapping_s
63 : {
64 : struct mapping_s *next;
65 : const char *key;
66 : const char *value;
67 : };
68 : static struct mapping_s *mappings;
69 :
70 :
71 : /* If STRING has already been mapped, return the mapped string. If
72 : not return NULL. */
73 : static const char *
74 248 : already_mapped (const char *string)
75 : {
76 : struct mapping_s *m;
77 :
78 511 : for (m=mappings; m; m = m->next)
79 271 : if (m->key == string && !strcmp (m->key, string))
80 8 : return m->value;
81 240 : return NULL;
82 : }
83 :
84 :
85 : /* Store NEWSTRING under key STRING and return NEWSTRING. */
86 : static const char *
87 32 : store_mapping (const char *string, char *newstring)
88 : {
89 : struct mapping_s *m;
90 :
91 32 : m = xmalloc (sizeof *m);
92 32 : m->key = string;
93 32 : m->value = newstring;
94 32 : m->next = mappings;
95 32 : mappings = m;
96 32 : return newstring;
97 : }
98 :
99 :
100 : /* Find the first macro in STRING. Return a pointer to the
101 : replacement value, set BEGPTR to the leading '@', and set ENDPTR to
102 : the terminating '@'. If no macro is found return NULL. */
103 : const char *
104 301 : find_macro (const char *string, const char **begptr,
105 : const char **endptr)
106 : {
107 : const char *s, *s2, *s3;
108 : int idx;
109 :
110 301 : s = string;
111 301 : if (!s)
112 0 : return NULL;
113 :
114 303 : for (; (s2 = strchr (s, '@')); s = s2)
115 : {
116 63 : s2++;
117 63 : if (*s2 >= 'A' && *s2 <= 'Z' && (s3 = (strchr (s2, '@'))))
118 : {
119 162 : for (idx=0; idx < DIM (macros); idx++)
120 162 : if (strlen (macros[idx].name) == (s3 - s2)
121 91 : && !memcmp (macros[idx].name, s2, (s3 - s2)))
122 : {
123 61 : *begptr = s2 - 1;
124 61 : *endptr = s3;
125 61 : return macros[idx].value;
126 : }
127 : }
128 : }
129 240 : return NULL;
130 : }
131 :
132 :
133 : /* If STRING includes known @FOO@ macros, replace these macros and
134 : return a new static string. Warning: STRING must have been
135 : allocated statically. Note that this function allocates memory
136 : which will not be released (similar to gettext). */
137 : const char *
138 248 : map_static_macro_string (const char *string)
139 : {
140 : const char *s, *s2, *s3, *value;
141 : membuf_t mb;
142 : char *p;
143 :
144 248 : if ((s = already_mapped (string)))
145 8 : return s;
146 240 : s = string;
147 240 : value = find_macro (s, &s2, &s3);
148 240 : if (!value)
149 208 : return string; /* No macros at all. */
150 :
151 32 : init_membuf (&mb, strlen (string) + 100);
152 : do
153 : {
154 61 : put_membuf (&mb, s, s2 - s);
155 61 : put_membuf_str (&mb, value);
156 61 : s = s3 + 1;
157 : }
158 61 : while ((value = find_macro (s, &s2, &s3)));
159 32 : put_membuf_str (&mb, s);
160 32 : put_membuf (&mb, "", 1);
161 :
162 32 : p = get_membuf_shrink (&mb, NULL);
163 32 : if (!p)
164 0 : log_fatal ("map_static_macro_string failed: %s\n", strerror (errno));
165 :
166 32 : return store_mapping (string, p);
167 : }
|