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