registry.c revision 35c4bbdf
11.9Sandvar/************************************************************ 21.1Snonaka 31.1SnonakaAuthor: Eamon Walsh <ewalsh@tycho.nsa.gov> 41.4Snonaka 51.4SnonakaPermission to use, copy, modify, distribute, and sell this software and its 61.1Snonakadocumentation for any purpose is hereby granted without fee, provided that 71.1Snonakathis permission notice appear in supporting documentation. This permission 81.1Snonakanotice shall be included in all copies or substantial portions of the 91.1SnonakaSoftware. 101.1Snonaka 111.1SnonakaTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 121.1SnonakaIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 131.1SnonakaFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 141.1SnonakaAUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 151.1SnonakaAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 161.1SnonakaCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 171.1Snonaka 181.1Snonaka********************************************************/ 191.1Snonaka 201.1Snonaka#ifdef HAVE_DIX_CONFIG_H 211.1Snonaka#include <dix-config.h> 221.1Snonaka#endif 231.1Snonaka 241.1Snonaka#include <stdlib.h> 251.1Snonaka#include <string.h> 261.1Snonaka#include <X11/X.h> 271.1Snonaka#include <X11/Xproto.h> 281.1Snonaka#include "resource.h" 291.1Snonaka#include "registry.h" 301.1Snonaka 311.1Snonaka#define BASE_SIZE 16 321.1Snonaka 331.9Sandvar#ifdef X_REGISTRY_REQUEST 341.1Snonaka#define CORE "X11" 351.5Snonaka#define FILENAME SERVER_MISC_CONFIG_PATH "/protocol.txt" 361.1Snonaka 371.1Snonaka#define PROT_COMMENT '#' 381.1Snonaka#define PROT_REQUEST 'R' 391.1Snonaka#define PROT_EVENT 'V' 401.1Snonaka#define PROT_ERROR 'E' 411.1Snonaka 421.1Snonakastatic FILE *fh; 431.1Snonaka 441.1Snonakastatic char ***requests, **events, **errors; 451.1Snonakastatic unsigned nmajor, *nminor, nevent, nerror; 461.1Snonaka#endif 471.1Snonaka 481.1Snonaka#ifdef X_REGISTRY_RESOURCE 491.1Snonakastatic const char **resources; 501.1Snonakastatic unsigned nresource; 511.1Snonaka#endif 521.1Snonaka 531.1Snonaka#if defined(X_REGISTRY_RESOURCE) || defined(X_REGISTRY_REQUEST) 541.1Snonaka/* 551.1Snonaka * File parsing routines 561.1Snonaka */ 571.1Snonakastatic int 581.1Snonakadouble_size(void *p, unsigned n, unsigned size) 591.1Snonaka{ 601.1Snonaka char **ptr = (char **) p; 611.1Snonaka unsigned s, f; 621.1Snonaka 631.1Snonaka if (n) { 641.1Snonaka s = n * size; 651.1Snonaka n *= 2 * size; 661.1Snonaka f = n; 671.1Snonaka } 681.1Snonaka else { 691.1Snonaka s = 0; 701.1Snonaka n = f = BASE_SIZE * size; 711.1Snonaka } 721.1Snonaka 731.1Snonaka *ptr = realloc(*ptr, n); 741.1Snonaka if (!*ptr) { 751.1Snonaka dixResetRegistry(); 761.1Snonaka return FALSE; 771.4Snonaka } 781.1Snonaka memset(*ptr + s, 0, f - s); 791.1Snonaka return TRUE; 801.1Snonaka} 811.1Snonaka#endif 821.1Snonaka 831.1Snonaka#ifdef X_REGISTRY_REQUEST 841.1Snonaka/* 851.1Snonaka * Request/event/error registry functions 861.1Snonaka */ 871.1Snonakastatic void 881.1SnonakaRegisterRequestName(unsigned major, unsigned minor, char *name) 891.1Snonaka{ 901.1Snonaka while (major >= nmajor) { 911.9Sandvar if (!double_size(&requests, nmajor, sizeof(char **))) 921.4Snonaka return; 931.4Snonaka if (!double_size(&nminor, nmajor, sizeof(unsigned))) 941.1Snonaka return; 951.1Snonaka nmajor = nmajor ? nmajor * 2 : BASE_SIZE; 961.1Snonaka } 971.1Snonaka while (minor >= nminor[major]) { 981.1Snonaka if (!double_size(requests + major, nminor[major], sizeof(char *))) 991.1Snonaka return; 1001.1Snonaka nminor[major] = nminor[major] ? nminor[major] * 2 : BASE_SIZE; 1011.1Snonaka } 1021.1Snonaka 1031.1Snonaka free(requests[major][minor]); 1041.1Snonaka requests[major][minor] = name; 1051.1Snonaka} 1061.1Snonaka 1071.1Snonakastatic void 1081.1SnonakaRegisterEventName(unsigned event, char *name) 1091.1Snonaka{ 1101.1Snonaka while (event >= nevent) { 1111.1Snonaka if (!double_size(&events, nevent, sizeof(char *))) 1121.1Snonaka return; 1131.1Snonaka nevent = nevent ? nevent * 2 : BASE_SIZE; 1141.1Snonaka } 1151.1Snonaka 1161.1Snonaka free(events[event]); 1171.1Snonaka events[event] = name; 1181.1Snonaka} 1191.1Snonaka 1201.1Snonakastatic void 1211.1SnonakaRegisterErrorName(unsigned error, char *name) 1221.1Snonaka{ 1231.1Snonaka while (error >= nerror) { 1241.1Snonaka if (!double_size(&errors, nerror, sizeof(char *))) 1251.1Snonaka return; 1261.1Snonaka nerror = nerror ? nerror * 2 : BASE_SIZE; 1271.1Snonaka } 1281.1Snonaka 1291.1Snonaka free(errors[error]); 1301.1Snonaka errors[error] = name; 1311.1Snonaka} 1321.1Snonaka 1331.1Snonakavoid 1341.1SnonakaRegisterExtensionNames(ExtensionEntry * extEntry) 1351.1Snonaka{ 1361.1Snonaka char buf[256], *lineobj, *ptr; 1371.1Snonaka unsigned offset; 1381.1Snonaka 1391.6Sjdolecek if (fh == NULL) 1401.1Snonaka return; 1411.1Snonaka 1421.1Snonaka rewind(fh); 1431.1Snonaka 1441.1Snonaka while (fgets(buf, sizeof(buf), fh)) { 1451.1Snonaka lineobj = NULL; 1461.1Snonaka ptr = strchr(buf, '\n'); 1471.1Snonaka if (ptr) 1481.7Sjdolecek *ptr = 0; 1491.7Sjdolecek 1501.7Sjdolecek /* Check for comments or empty lines */ 1511.4Snonaka switch (buf[0]) { 1521.4Snonaka case PROT_REQUEST: 1531.4Snonaka case PROT_EVENT: 1541.4Snonaka case PROT_ERROR: 1551.4Snonaka break; 1561.4Snonaka case PROT_COMMENT: 1571.4Snonaka case '\0': 1581.4Snonaka continue; 1591.4Snonaka default: 1601.4Snonaka goto invalid; 1611.1Snonaka } 1621.1Snonaka 1631.1Snonaka /* Check for space character in the fifth position */ 1641.1Snonaka ptr = strchr(buf, ' '); 1651.1Snonaka if (!ptr || ptr != buf + 4) 1661.1Snonaka goto invalid; 1671.1Snonaka 1681.1Snonaka /* Duplicate the string after the space */ 1691.1Snonaka lineobj = strdup(ptr + 1); 1701.1Snonaka if (!lineobj) 1711.1Snonaka continue; 1721.1Snonaka 1731.1Snonaka /* Check for a colon somewhere on the line */ 1741.1Snonaka ptr = strchr(buf, ':'); 1751.1Snonaka if (!ptr) 1761.1Snonaka goto invalid; 1771.1Snonaka 1781.1Snonaka /* Compare the part before colon with the target extension name */ 1791.1Snonaka *ptr = 0; 1801.1Snonaka if (strcmp(buf + 5, extEntry->name)) 1811.1Snonaka goto skip; 1821.1Snonaka 1831.1Snonaka /* Get the opcode for the request, event, or error */ 1841.1Snonaka offset = strtol(buf + 1, &ptr, 10); 1851.1Snonaka if (offset == 0 && ptr == buf + 1) 1861.1Snonaka goto invalid; 1871.1Snonaka 1881.2Sjoerg /* Save the strdup result in the registry */ 1891.1Snonaka switch (buf[0]) { 1901.1Snonaka case PROT_REQUEST: 1911.1Snonaka if (extEntry->base) 1921.3Sjdolecek RegisterRequestName(extEntry->base, offset, lineobj); 1931.1Snonaka else 1941.1Snonaka RegisterRequestName(offset, 0, lineobj); 1951.1Snonaka continue; 1961.2Sjoerg case PROT_EVENT: 1971.1Snonaka RegisterEventName(extEntry->eventBase + offset, lineobj); 1981.1Snonaka continue; 1991.1Snonaka case PROT_ERROR: 2001.1Snonaka RegisterErrorName(extEntry->errorBase + offset, lineobj); 2011.1Snonaka continue; 2021.1Snonaka } 2031.1Snonaka 2041.1Snonaka invalid: 2051.1Snonaka LogMessage(X_WARNING, "Invalid line in " FILENAME ", skipping\n"); 2061.1Snonaka skip: 2071.1Snonaka free(lineobj); 2081.1Snonaka } 2091.1Snonaka} 2101.1Snonaka 2111.1Snonakaconst char * 2121.1SnonakaLookupRequestName(int major, int minor) 2131.1Snonaka{ 2141.1Snonaka if (major >= nmajor) 2151.1Snonaka return XREGISTRY_UNKNOWN; 2161.1Snonaka if (minor >= nminor[major]) 2171.1Snonaka return XREGISTRY_UNKNOWN; 2181.1Snonaka 2191.1Snonaka return requests[major][minor] ? requests[major][minor] : XREGISTRY_UNKNOWN; 2201.1Snonaka} 2211.1Snonaka 2221.1Snonakaconst char * 2231.1SnonakaLookupMajorName(int major) 2241.1Snonaka{ 2251.1Snonaka if (major < 128) { 2261.1Snonaka const char *retval; 2271.1Snonaka 2281.1Snonaka if (major >= nmajor) 2291.1Snonaka return XREGISTRY_UNKNOWN; 2301.1Snonaka if (0 >= nminor[major]) 2311.1Snonaka return XREGISTRY_UNKNOWN; 2321.1Snonaka 2331.1Snonaka retval = requests[major][0]; 2341.1Snonaka return retval ? retval + sizeof(CORE) : XREGISTRY_UNKNOWN; 2351.1Snonaka } 2361.1Snonaka else { 2371.1Snonaka ExtensionEntry *extEntry = GetExtensionEntry(major); 2381.1Snonaka 2391.1Snonaka return extEntry ? extEntry->name : XREGISTRY_UNKNOWN; 2401.1Snonaka } 2411.1Snonaka} 2421.1Snonaka 2431.2Sjoergconst char * 2441.1SnonakaLookupEventName(int event) 2451.1Snonaka{ 2461.1Snonaka event &= 127; 2471.1Snonaka if (event >= nevent) 2481.1Snonaka return XREGISTRY_UNKNOWN; 2491.1Snonaka 2501.1Snonaka return events[event] ? events[event] : XREGISTRY_UNKNOWN; 2511.1Snonaka} 2521.1Snonaka 2531.1Snonakaconst char * 2541.1SnonakaLookupErrorName(int error) 2551.1Snonaka{ 2561.1Snonaka if (error >= nerror) 2571.1Snonaka return XREGISTRY_UNKNOWN; 2581.1Snonaka 2591.1Snonaka return errors[error] ? errors[error] : XREGISTRY_UNKNOWN; 2601.1Snonaka} 2611.1Snonaka#endif /* X_REGISTRY_REQUEST */ 2621.1Snonaka 2631.1Snonaka#ifdef X_REGISTRY_RESOURCE 2641.1Snonaka/* 2651.1Snonaka * Resource registry functions 2661.1Snonaka */ 2671.1Snonaka 2681.1Snonakavoid 2691.1SnonakaRegisterResourceName(RESTYPE resource, const char *name) 2701.1Snonaka{ 2711.1Snonaka resource &= TypeMask; 2721.1Snonaka 2731.1Snonaka while (resource >= nresource) { 2741.1Snonaka if (!double_size(&resources, nresource, sizeof(char *))) 2751.1Snonaka return; 2761.1Snonaka nresource = nresource ? nresource * 2 : BASE_SIZE; 2771.1Snonaka } 2781.1Snonaka 2791.1Snonaka resources[resource] = name; 2801.1Snonaka} 2811.1Snonaka 2821.1Snonakaconst char * 2831.1SnonakaLookupResourceName(RESTYPE resource) 2841.1Snonaka{ 2851.1Snonaka resource &= TypeMask; 2861.1Snonaka if (resource >= nresource) 2871.1Snonaka return XREGISTRY_UNKNOWN; 2881.1Snonaka 2891.1Snonaka return resources[resource] ? resources[resource] : XREGISTRY_UNKNOWN; 2901.1Snonaka} 2911.1Snonaka#endif /* X_REGISTRY_RESOURCE */ 2921.1Snonaka 2931.1Snonakavoid 2941.1SnonakadixFreeRegistry(void) 2951.1Snonaka{ 2961.1Snonaka#ifdef X_REGISTRY_REQUEST 2971.1Snonaka /* Free all memory */ 2981.1Snonaka while (nmajor--) { 2991.1Snonaka while (nminor[nmajor]) 3001.1Snonaka free(requests[nmajor][--nminor[nmajor]]); 3011.1Snonaka free(requests[nmajor]); 3021.1Snonaka } 3031.1Snonaka free(requests); 3041.1Snonaka free(nminor); 3051.1Snonaka 3061.1Snonaka while (nevent--) 3071.1Snonaka free(events[nevent]); 3081.1Snonaka free(events); 3091.1Snonaka 3101.1Snonaka while (nerror--) 3111.1Snonaka free(errors[nerror]); 3121.1Snonaka free(errors); 3131.1Snonaka requests = NULL; 3141.1Snonaka nminor = NULL; 3151.1Snonaka events = NULL; 3161.1Snonaka errors = NULL; 3171.1Snonaka nmajor = nevent = nerror = 0; 3181.1Snonaka#endif 3191.1Snonaka 3201.1Snonaka#ifdef X_REGISTRY_RESOURCE 3211.1Snonaka free(resources); 3221.1Snonaka 3231.1Snonaka resources = NULL; 3241.1Snonaka nresource = 0; 3251.1Snonaka#endif 3261.1Snonaka} 3271.1Snonaka 3281.1Snonakavoid 3291.1SnonakadixCloseRegistry(void) 3301.1Snonaka{ 3311.1Snonaka#ifdef X_REGISTRY_REQUEST 3321.1Snonaka if (fh) { 3331.1Snonaka fclose(fh); 334 fh = NULL; 335 } 336#endif 337} 338 339/* 340 * Setup and teardown 341 */ 342void 343dixResetRegistry(void) 344{ 345#ifdef X_REGISTRY_REQUEST 346 ExtensionEntry extEntry = { .name = CORE }; 347#endif 348 349 dixFreeRegistry(); 350 351#ifdef X_REGISTRY_REQUEST 352 /* Open the protocol file */ 353 fh = fopen(FILENAME, "r"); 354 if (!fh) 355 LogMessage(X_WARNING, 356 "Failed to open protocol names file " FILENAME "\n"); 357 358 /* Add the core protocol */ 359 RegisterExtensionNames(&extEntry); 360#endif 361 362#ifdef X_REGISTRY_RESOURCE 363 /* Add built-in resources */ 364 RegisterResourceName(RT_NONE, "NONE"); 365 RegisterResourceName(RT_WINDOW, "WINDOW"); 366 RegisterResourceName(RT_PIXMAP, "PIXMAP"); 367 RegisterResourceName(RT_GC, "GC"); 368 RegisterResourceName(RT_FONT, "FONT"); 369 RegisterResourceName(RT_CURSOR, "CURSOR"); 370 RegisterResourceName(RT_COLORMAP, "COLORMAP"); 371 RegisterResourceName(RT_CMAPENTRY, "COLORMAP ENTRY"); 372 RegisterResourceName(RT_OTHERCLIENT, "OTHER CLIENT"); 373 RegisterResourceName(RT_PASSIVEGRAB, "PASSIVE GRAB"); 374#endif 375} 376