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 <https://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 786 : already_mapped (const char *string)
75 : {
76 : struct mapping_s *m;
77 :
78 971 : for (m=mappings; m; m = m->next)
79 197 : if (m->key == string && !strcmp (m->key, string))
80 12 : return m->value;
81 774 : return NULL;
82 : }
83 :
84 :
85 : /* Store NEWSTRING under key STRING and return NEWSTRING. */
86 : static const char *
87 67 : store_mapping (const char *string, char *newstring)
88 : {
89 : struct mapping_s *m;
90 :
91 67 : m = xmalloc (sizeof *m);
92 67 : m->key = string;
93 67 : m->value = newstring;
94 67 : m->next = mappings;
95 67 : mappings = m;
96 67 : 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 901 : find_macro (const char *string, const char **begptr,
105 : const char **endptr)
106 : {
107 : const char *s, *s2, *s3;
108 : int idx;
109 :
110 901 : s = string;
111 901 : if (!s)
112 0 : return NULL;
113 :
114 939 : for (; (s2 = strchr (s, '@')); s = s2)
115 : {
116 165 : s2++;
117 165 : if (*s2 >= 'A' && *s2 <= 'Z' && (s3 = (strchr (s2, '@'))))
118 : {
119 447 : for (idx=0; idx < DIM (macros); idx++)
120 447 : if (strlen (macros[idx].name) == (s3 - s2)
121 188 : && !memcmp (macros[idx].name, s2, (s3 - s2)))
122 : {
123 127 : *begptr = s2 - 1;
124 127 : *endptr = s3;
125 127 : return macros[idx].value;
126 : }
127 : }
128 : }
129 774 : 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 786 : map_static_macro_string (const char *string)
139 : {
140 : const char *s, *s2, *s3, *value;
141 : membuf_t mb;
142 : char *p;
143 :
144 786 : if ((s = already_mapped (string)))
145 12 : return s;
146 774 : s = string;
147 774 : value = find_macro (s, &s2, &s3);
148 774 : if (!value)
149 707 : return string; /* No macros at all. */
150 :
151 67 : init_membuf (&mb, strlen (string) + 100);
152 : do
153 : {
154 127 : put_membuf (&mb, s, s2 - s);
155 127 : put_membuf_str (&mb, value);
156 127 : s = s3 + 1;
157 : }
158 127 : while ((value = find_macro (s, &s2, &s3)));
159 67 : put_membuf_str (&mb, s);
160 67 : put_membuf (&mb, "", 1);
161 :
162 67 : p = get_membuf_shrink (&mb, NULL);
163 67 : if (!p)
164 0 : log_fatal ("map_static_macro_string failed: %s\n", strerror (errno));
165 :
166 67 : return store_mapping (string, p);
167 : }
|