Imported Upstream version 1.15.1
[deb_xorg-server.git] / dix / registry.c
CommitLineData
a09e091a
JB
1/************************************************************
2
3Author: Eamon Walsh <ewalsh@tycho.nsa.gov>
4
5Permission to use, copy, modify, distribute, and sell this software and its
6documentation for any purpose is hereby granted without fee, provided that
7this permission notice appear in supporting documentation. This permission
8notice shall be included in all copies or substantial portions of the
9Software.
10
11THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
12IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
13FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
14AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
15AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
16CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
17
18********************************************************/
19
20#ifdef HAVE_DIX_CONFIG_H
21#include <dix-config.h>
22#endif
23
24#ifdef XREGISTRY
25
26#include <stdlib.h>
27#include <string.h>
28#include <X11/X.h>
29#include <X11/Xproto.h>
30#include "resource.h"
31#include "registry.h"
32
33#define BASE_SIZE 16
34#define CORE "X11"
35#define FILENAME SERVER_MISC_CONFIG_PATH "/protocol.txt"
36
37#define PROT_COMMENT '#'
38#define PROT_REQUEST 'R'
39#define PROT_EVENT 'V'
40#define PROT_ERROR 'E'
41
42static FILE *fh;
43
44static char ***requests, **events, **errors;
45static const char **resources;
46static unsigned nmajor, *nminor, nevent, nerror, nresource;
47
48/*
49 * File parsing routines
50 */
51static int
52double_size(void *p, unsigned n, unsigned size)
53{
54 char **ptr = (char **) p;
55 unsigned s, f;
56
57 if (n) {
58 s = n * size;
59 n *= 2 * size;
60 f = n;
61 }
62 else {
63 s = 0;
64 n = f = BASE_SIZE * size;
65 }
66
67 *ptr = realloc(*ptr, n);
68 if (!*ptr) {
69 dixResetRegistry();
70 return FALSE;
71 }
72 memset(*ptr + s, 0, f - s);
73 return TRUE;
74}
75
76static void
77RegisterRequestName(unsigned major, unsigned minor, char *name)
78{
79 while (major >= nmajor) {
80 if (!double_size(&requests, nmajor, sizeof(char **)))
81 return;
82 if (!double_size(&nminor, nmajor, sizeof(unsigned)))
83 return;
84 nmajor = nmajor ? nmajor * 2 : BASE_SIZE;
85 }
86 while (minor >= nminor[major]) {
87 if (!double_size(requests + major, nminor[major], sizeof(char *)))
88 return;
89 nminor[major] = nminor[major] ? nminor[major] * 2 : BASE_SIZE;
90 }
91
92 free(requests[major][minor]);
93 requests[major][minor] = name;
94}
95
96static void
97RegisterEventName(unsigned event, char *name)
98{
99 while (event >= nevent) {
100 if (!double_size(&events, nevent, sizeof(char *)))
101 return;
102 nevent = nevent ? nevent * 2 : BASE_SIZE;
103 }
104
105 free(events[event]);
106 events[event] = name;
107}
108
109static void
110RegisterErrorName(unsigned error, char *name)
111{
112 while (error >= nerror) {
113 if (!double_size(&errors, nerror, sizeof(char *)))
114 return;
115 nerror = nerror ? nerror * 2 : BASE_SIZE;
116 }
117
118 free(errors[error]);
119 errors[error] = name;
120}
121
122void
123RegisterExtensionNames(ExtensionEntry * extEntry)
124{
125 char buf[256], *lineobj, *ptr;
126 unsigned offset;
127
128 if (fh == NULL)
129 return;
130
131 rewind(fh);
132
133 while (fgets(buf, sizeof(buf), fh)) {
134 lineobj = NULL;
135 ptr = strchr(buf, '\n');
136 if (ptr)
137 *ptr = 0;
138
139 /* Check for comments or empty lines */
140 switch (buf[0]) {
141 case PROT_REQUEST:
142 case PROT_EVENT:
143 case PROT_ERROR:
144 break;
145 case PROT_COMMENT:
146 case '\0':
147 continue;
148 default:
149 goto invalid;
150 }
151
152 /* Check for space character in the fifth position */
153 ptr = strchr(buf, ' ');
154 if (!ptr || ptr != buf + 4)
155 goto invalid;
156
157 /* Duplicate the string after the space */
158 lineobj = strdup(ptr + 1);
159 if (!lineobj)
160 continue;
161
162 /* Check for a colon somewhere on the line */
163 ptr = strchr(buf, ':');
164 if (!ptr)
165 goto invalid;
166
167 /* Compare the part before colon with the target extension name */
168 *ptr = 0;
169 if (strcmp(buf + 5, extEntry->name))
170 goto skip;
171
172 /* Get the opcode for the request, event, or error */
173 offset = strtol(buf + 1, &ptr, 10);
174 if (offset == 0 && ptr == buf + 1)
175 goto invalid;
176
177 /* Save the strdup result in the registry */
178 switch (buf[0]) {
179 case PROT_REQUEST:
180 if (extEntry->base)
181 RegisterRequestName(extEntry->base, offset, lineobj);
182 else
183 RegisterRequestName(offset, 0, lineobj);
184 continue;
185 case PROT_EVENT:
186 RegisterEventName(extEntry->eventBase + offset, lineobj);
187 continue;
188 case PROT_ERROR:
189 RegisterErrorName(extEntry->errorBase + offset, lineobj);
190 continue;
191 }
192
193 invalid:
194 LogMessage(X_WARNING, "Invalid line in " FILENAME ", skipping\n");
195 skip:
196 free(lineobj);
197 }
198}
199
200/*
201 * Registration functions
202 */
203
204void
205RegisterResourceName(RESTYPE resource, const char *name)
206{
207 resource &= TypeMask;
208
209 while (resource >= nresource) {
210 if (!double_size(&resources, nresource, sizeof(char *)))
211 return;
212 nresource = nresource ? nresource * 2 : BASE_SIZE;
213 }
214
215 resources[resource] = name;
216}
217
218/*
219 * Lookup functions
220 */
221
222const char *
223LookupRequestName(int major, int minor)
224{
225 if (major >= nmajor)
226 return XREGISTRY_UNKNOWN;
227 if (minor >= nminor[major])
228 return XREGISTRY_UNKNOWN;
229
230 return requests[major][minor] ? requests[major][minor] : XREGISTRY_UNKNOWN;
231}
232
233const char *
234LookupMajorName(int major)
235{
236 if (major < 128) {
237 const char *retval;
238
239 if (major >= nmajor)
240 return XREGISTRY_UNKNOWN;
241 if (0 >= nminor[major])
242 return XREGISTRY_UNKNOWN;
243
244 retval = requests[major][0];
245 return retval ? retval + sizeof(CORE) : XREGISTRY_UNKNOWN;
246 }
247 else {
248 ExtensionEntry *extEntry = GetExtensionEntry(major);
249
250 return extEntry ? extEntry->name : XREGISTRY_UNKNOWN;
251 }
252}
253
254const char *
255LookupEventName(int event)
256{
257 event &= 127;
258 if (event >= nevent)
259 return XREGISTRY_UNKNOWN;
260
261 return events[event] ? events[event] : XREGISTRY_UNKNOWN;
262}
263
264const char *
265LookupErrorName(int error)
266{
267 if (error >= nerror)
268 return XREGISTRY_UNKNOWN;
269
270 return errors[error] ? errors[error] : XREGISTRY_UNKNOWN;
271}
272
273const char *
274LookupResourceName(RESTYPE resource)
275{
276 resource &= TypeMask;
277 if (resource >= nresource)
278 return XREGISTRY_UNKNOWN;
279
280 return resources[resource] ? resources[resource] : XREGISTRY_UNKNOWN;
281}
282
283void
284dixFreeRegistry(void)
285{
286 /* Free all memory */
287 while (nmajor--) {
288 while (nminor[nmajor])
289 free(requests[nmajor][--nminor[nmajor]]);
290 free(requests[nmajor]);
291 }
292 free(requests);
293 free(nminor);
294
295 while (nevent--)
296 free(events[nevent]);
297 free(events);
298
299 while (nerror--)
300 free(errors[nerror]);
301 free(errors);
302
303 free(resources);
304
305 requests = NULL;
306 nminor = NULL;
307 events = NULL;
308 errors = NULL;
309 resources = NULL;
310
311 nmajor = nevent = nerror = nresource = 0;
312
313 if (fh) {
314 fclose(fh);
315 fh = NULL;
316 }
317}
318
319/*
320 * Setup and teardown
321 */
322void
323dixResetRegistry(void)
324{
325 ExtensionEntry extEntry = { .name = CORE };
326
327 dixFreeRegistry();
328
329 /* Open the protocol file */
330 fh = fopen(FILENAME, "r");
331 if (!fh)
332 LogMessage(X_WARNING,
333 "Failed to open protocol names file " FILENAME "\n");
334
335 /* Add built-in resources */
336 RegisterResourceName(RT_NONE, "NONE");
337 RegisterResourceName(RT_WINDOW, "WINDOW");
338 RegisterResourceName(RT_PIXMAP, "PIXMAP");
339 RegisterResourceName(RT_GC, "GC");
340 RegisterResourceName(RT_FONT, "FONT");
341 RegisterResourceName(RT_CURSOR, "CURSOR");
342 RegisterResourceName(RT_COLORMAP, "COLORMAP");
343 RegisterResourceName(RT_CMAPENTRY, "COLORMAP ENTRY");
344 RegisterResourceName(RT_OTHERCLIENT, "OTHER CLIENT");
345 RegisterResourceName(RT_PASSIVEGRAB, "PASSIVE GRAB");
346
347 /* Add the core protocol */
348 RegisterExtensionNames(&extEntry);
349}
350
351#endif /* XREGISTRY */