Commit | Line | Data |
---|---|---|
a09e091a JB |
1 | /************************************************************ |
2 | ||
3 | Author: Eamon Walsh <ewalsh@tycho.nsa.gov> | |
4 | ||
5 | Permission to use, copy, modify, distribute, and sell this software and its | |
6 | documentation for any purpose is hereby granted without fee, provided that | |
7 | this permission notice appear in supporting documentation. This permission | |
8 | notice shall be included in all copies or substantial portions of the | |
9 | Software. | |
10 | ||
11 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
12 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
13 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
14 | AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN | |
15 | AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | |
16 | CONNECTION 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 | ||
42 | static FILE *fh; | |
43 | ||
44 | static char ***requests, **events, **errors; | |
45 | static const char **resources; | |
46 | static unsigned nmajor, *nminor, nevent, nerror, nresource; | |
47 | ||
48 | /* | |
49 | * File parsing routines | |
50 | */ | |
51 | static int | |
52 | double_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 | ||
76 | static void | |
77 | RegisterRequestName(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 | ||
96 | static void | |
97 | RegisterEventName(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 | ||
109 | static void | |
110 | RegisterErrorName(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 | ||
122 | void | |
123 | RegisterExtensionNames(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 | ||
204 | void | |
205 | RegisterResourceName(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 | ||
222 | const char * | |
223 | LookupRequestName(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 | ||
233 | const char * | |
234 | LookupMajorName(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 | ||
254 | const char * | |
255 | LookupEventName(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 | ||
264 | const char * | |
265 | LookupErrorName(int error) | |
266 | { | |
267 | if (error >= nerror) | |
268 | return XREGISTRY_UNKNOWN; | |
269 | ||
270 | return errors[error] ? errors[error] : XREGISTRY_UNKNOWN; | |
271 | } | |
272 | ||
273 | const char * | |
274 | LookupResourceName(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 | ||
283 | void | |
284 | dixFreeRegistry(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 | */ | |
322 | void | |
323 | dixResetRegistry(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 */ |