registry.c revision 6747b715
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, **resources; 45static unsigned nmajor, *nminor, nevent, nerror, nresource; 46 47/* 48 * File parsing routines 49 */ 50static int double_size(void *p, unsigned n, unsigned size) 51{ 52 char **ptr = (char **)p; 53 unsigned s, f; 54 55 if (n) { 56 s = n * size; 57 n *= 2 * size; 58 f = n; 59 } else { 60 s = 0; 61 n = f = BASE_SIZE * size; 62 } 63 64 *ptr = realloc(*ptr, n); 65 if (!*ptr) { 66 dixResetRegistry(); 67 return FALSE; 68 } 69 memset(*ptr + s, 0, f - s); 70 return TRUE; 71} 72 73static void 74RegisterRequestName(unsigned major, unsigned minor, char *name) 75{ 76 while (major >= nmajor) { 77 if (!double_size(&requests, nmajor, sizeof(char **))) 78 return; 79 if (!double_size(&nminor, nmajor, sizeof(unsigned))) 80 return; 81 nmajor = nmajor ? nmajor * 2 : BASE_SIZE; 82 } 83 while (minor >= nminor[major]) { 84 if (!double_size(requests+major, nminor[major], sizeof(char *))) 85 return; 86 nminor[major] = nminor[major] ? nminor[major] * 2 : BASE_SIZE; 87 } 88 89 free(requests[major][minor]); 90 requests[major][minor] = name; 91} 92 93static void 94RegisterEventName(unsigned event, char *name) { 95 while (event >= nevent) { 96 if (!double_size(&events, nevent, sizeof(char *))) 97 return; 98 nevent = nevent ? nevent * 2 : BASE_SIZE; 99 } 100 101 free(events[event]); 102 events[event] = name; 103} 104 105static void 106RegisterErrorName(unsigned error, char *name) { 107 while (error >= nerror) { 108 if (!double_size(&errors, nerror, sizeof(char *))) 109 return; 110 nerror = nerror ? nerror * 2 : BASE_SIZE; 111 } 112 113 free(errors[error]); 114 errors[error] = name; 115} 116 117void 118RegisterExtensionNames(ExtensionEntry *extEntry) 119{ 120 char buf[256], *lineobj, *ptr; 121 unsigned offset; 122 123 if (fh == NULL) 124 return; 125 126 rewind(fh); 127 128 while (fgets(buf, sizeof(buf), fh)) { 129 lineobj = NULL; 130 ptr = strchr(buf, '\n'); 131 if (ptr) 132 *ptr = 0; 133 134 /* Check for comments or empty lines */ 135 switch (buf[0]) { 136 case PROT_REQUEST: 137 case PROT_EVENT: 138 case PROT_ERROR: 139 break; 140 case PROT_COMMENT: 141 case '\0': 142 continue; 143 default: 144 goto invalid; 145 } 146 147 /* Check for space character in the fifth position */ 148 ptr = strchr(buf, ' '); 149 if (!ptr || ptr != buf + 4) 150 goto invalid; 151 152 /* Duplicate the string after the space */ 153 lineobj = strdup(ptr + 1); 154 if (!lineobj) 155 continue; 156 157 /* Check for a colon somewhere on the line */ 158 ptr = strchr(buf, ':'); 159 if (!ptr) 160 goto invalid; 161 162 /* Compare the part before colon with the target extension name */ 163 *ptr = 0; 164 if (strcmp(buf + 5, extEntry->name)) 165 goto skip; 166 167 /* Get the opcode for the request, event, or error */ 168 offset = strtol(buf + 1, &ptr, 10); 169 if (offset == 0 && ptr == buf + 1) 170 goto invalid; 171 172 /* Save the strdup result in the registry */ 173 switch(buf[0]) { 174 case PROT_REQUEST: 175 if (extEntry->base) 176 RegisterRequestName(extEntry->base, offset, lineobj); 177 else 178 RegisterRequestName(offset, 0, lineobj); 179 continue; 180 case PROT_EVENT: 181 RegisterEventName(extEntry->eventBase + offset, lineobj); 182 continue; 183 case PROT_ERROR: 184 RegisterErrorName(extEntry->errorBase + offset, lineobj); 185 continue; 186 } 187 188 invalid: 189 LogMessage(X_WARNING, "Invalid line in " FILENAME ", skipping\n"); 190 skip: 191 free(lineobj); 192 } 193} 194 195/* 196 * Registration functions 197 */ 198 199void 200RegisterResourceName(RESTYPE resource, char *name) 201{ 202 resource &= TypeMask; 203 204 while (resource >= nresource) { 205 if (!double_size(&resources, nresource, sizeof(char *))) 206 return; 207 nresource = nresource ? nresource * 2 : BASE_SIZE; 208 } 209 210 resources[resource] = name; 211} 212 213/* 214 * Lookup functions 215 */ 216 217const char * 218LookupRequestName(int major, int minor) 219{ 220 if (major >= nmajor) 221 return XREGISTRY_UNKNOWN; 222 if (minor >= nminor[major]) 223 return XREGISTRY_UNKNOWN; 224 225 return requests[major][minor] ? requests[major][minor] : XREGISTRY_UNKNOWN; 226} 227 228const char * 229LookupMajorName(int major) 230{ 231 if (major < 128) { 232 const char *retval; 233 234 if (major >= nmajor) 235 return XREGISTRY_UNKNOWN; 236 if (0 >= nminor[major]) 237 return XREGISTRY_UNKNOWN; 238 239 retval = requests[major][0]; 240 return retval ? retval + sizeof(CORE) : XREGISTRY_UNKNOWN; 241 } else { 242 ExtensionEntry *extEntry = GetExtensionEntry(major); 243 return extEntry ? extEntry->name : XREGISTRY_UNKNOWN; 244 } 245} 246 247const char * 248LookupEventName(int event) 249{ 250 event &= 127; 251 if (event >= nevent) 252 return XREGISTRY_UNKNOWN; 253 254 return events[event] ? events[event] : XREGISTRY_UNKNOWN; 255} 256 257const char * 258LookupErrorName(int error) 259{ 260 if (error >= nerror) 261 return XREGISTRY_UNKNOWN; 262 263 return errors[error] ? errors[error] : XREGISTRY_UNKNOWN; 264} 265 266const char * 267LookupResourceName(RESTYPE resource) 268{ 269 resource &= TypeMask; 270 if (resource >= nresource) 271 return XREGISTRY_UNKNOWN; 272 273 return resources[resource] ? resources[resource] : XREGISTRY_UNKNOWN; 274} 275 276/* 277 * Setup and teardown 278 */ 279void 280dixResetRegistry(void) 281{ 282 ExtensionEntry extEntry; 283 284 /* Free all memory */ 285 while (nmajor--) { 286 while (nminor[nmajor]) 287 free(requests[nmajor][--nminor[nmajor]]); 288 free(requests[nmajor]); 289 } 290 free(requests); 291 free(nminor); 292 293 while (nevent--) 294 free(events[nevent]); 295 free(events); 296 297 while (nerror--) 298 free(errors[nerror]); 299 free(errors); 300 301 free(resources); 302 303 requests = NULL; 304 nminor = NULL; 305 events = NULL; 306 errors = NULL; 307 resources = NULL; 308 309 nmajor = nevent = nerror = nresource = 0; 310 311 /* Open the protocol file */ 312 if (fh) 313 fclose(fh); 314 fh = fopen(FILENAME, "r"); 315 if (!fh) 316 LogMessage(X_WARNING, "Failed to open protocol names file " FILENAME "\n"); 317 318 /* Add built-in resources */ 319 RegisterResourceName(RT_NONE, "NONE"); 320 RegisterResourceName(RT_WINDOW, "WINDOW"); 321 RegisterResourceName(RT_PIXMAP, "PIXMAP"); 322 RegisterResourceName(RT_GC, "GC"); 323 RegisterResourceName(RT_FONT, "FONT"); 324 RegisterResourceName(RT_CURSOR, "CURSOR"); 325 RegisterResourceName(RT_COLORMAP, "COLORMAP"); 326 RegisterResourceName(RT_CMAPENTRY, "COLORMAP ENTRY"); 327 RegisterResourceName(RT_OTHERCLIENT, "OTHER CLIENT"); 328 RegisterResourceName(RT_PASSIVEGRAB, "PASSIVE GRAB"); 329 330 /* Add the core protocol */ 331 memset(&extEntry, 0, sizeof(extEntry)); 332 extEntry.name = CORE; 333 RegisterExtensionNames(&extEntry); 334} 335 336#endif /* XREGISTRY */ 337