registry.c revision 6747b715
14642e01fSmrg/************************************************************ 24642e01fSmrg 36747b715SmrgAuthor: Eamon Walsh <ewalsh@tycho.nsa.gov> 44642e01fSmrg 54642e01fSmrgPermission to use, copy, modify, distribute, and sell this software and its 64642e01fSmrgdocumentation for any purpose is hereby granted without fee, provided that 74642e01fSmrgthis permission notice appear in supporting documentation. This permission 84642e01fSmrgnotice shall be included in all copies or substantial portions of the 94642e01fSmrgSoftware. 104642e01fSmrg 114642e01fSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 124642e01fSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 134642e01fSmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 144642e01fSmrgAUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 154642e01fSmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 164642e01fSmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 174642e01fSmrg 184642e01fSmrg********************************************************/ 194642e01fSmrg 204642e01fSmrg#ifdef HAVE_DIX_CONFIG_H 214642e01fSmrg#include <dix-config.h> 224642e01fSmrg#endif 234642e01fSmrg 244642e01fSmrg#ifdef XREGISTRY 254642e01fSmrg 264642e01fSmrg#include <stdlib.h> 274642e01fSmrg#include <string.h> 284642e01fSmrg#include <X11/X.h> 294642e01fSmrg#include <X11/Xproto.h> 304642e01fSmrg#include "resource.h" 314642e01fSmrg#include "registry.h" 324642e01fSmrg 334642e01fSmrg#define BASE_SIZE 16 344642e01fSmrg#define CORE "X11" 354642e01fSmrg#define FILENAME SERVER_MISC_CONFIG_PATH "/protocol.txt" 364642e01fSmrg 374642e01fSmrg#define PROT_COMMENT '#' 384642e01fSmrg#define PROT_REQUEST 'R' 394642e01fSmrg#define PROT_EVENT 'V' 404642e01fSmrg#define PROT_ERROR 'E' 414642e01fSmrg 424642e01fSmrgstatic FILE *fh; 434642e01fSmrg 444642e01fSmrgstatic char ***requests, **events, **errors, **resources; 454642e01fSmrgstatic unsigned nmajor, *nminor, nevent, nerror, nresource; 464642e01fSmrg 474642e01fSmrg/* 484642e01fSmrg * File parsing routines 494642e01fSmrg */ 504642e01fSmrgstatic int double_size(void *p, unsigned n, unsigned size) 514642e01fSmrg{ 524642e01fSmrg char **ptr = (char **)p; 534642e01fSmrg unsigned s, f; 544642e01fSmrg 554642e01fSmrg if (n) { 564642e01fSmrg s = n * size; 574642e01fSmrg n *= 2 * size; 584642e01fSmrg f = n; 594642e01fSmrg } else { 604642e01fSmrg s = 0; 614642e01fSmrg n = f = BASE_SIZE * size; 624642e01fSmrg } 634642e01fSmrg 646747b715Smrg *ptr = realloc(*ptr, n); 654642e01fSmrg if (!*ptr) { 664642e01fSmrg dixResetRegistry(); 674642e01fSmrg return FALSE; 684642e01fSmrg } 694642e01fSmrg memset(*ptr + s, 0, f - s); 704642e01fSmrg return TRUE; 714642e01fSmrg} 724642e01fSmrg 734642e01fSmrgstatic void 744642e01fSmrgRegisterRequestName(unsigned major, unsigned minor, char *name) 754642e01fSmrg{ 764642e01fSmrg while (major >= nmajor) { 774642e01fSmrg if (!double_size(&requests, nmajor, sizeof(char **))) 784642e01fSmrg return; 794642e01fSmrg if (!double_size(&nminor, nmajor, sizeof(unsigned))) 804642e01fSmrg return; 814642e01fSmrg nmajor = nmajor ? nmajor * 2 : BASE_SIZE; 824642e01fSmrg } 834642e01fSmrg while (minor >= nminor[major]) { 844642e01fSmrg if (!double_size(requests+major, nminor[major], sizeof(char *))) 854642e01fSmrg return; 864642e01fSmrg nminor[major] = nminor[major] ? nminor[major] * 2 : BASE_SIZE; 874642e01fSmrg } 884642e01fSmrg 894642e01fSmrg free(requests[major][minor]); 904642e01fSmrg requests[major][minor] = name; 914642e01fSmrg} 924642e01fSmrg 934642e01fSmrgstatic void 944642e01fSmrgRegisterEventName(unsigned event, char *name) { 954642e01fSmrg while (event >= nevent) { 964642e01fSmrg if (!double_size(&events, nevent, sizeof(char *))) 974642e01fSmrg return; 984642e01fSmrg nevent = nevent ? nevent * 2 : BASE_SIZE; 994642e01fSmrg } 1004642e01fSmrg 1014642e01fSmrg free(events[event]); 1024642e01fSmrg events[event] = name; 1034642e01fSmrg} 1044642e01fSmrg 1054642e01fSmrgstatic void 1064642e01fSmrgRegisterErrorName(unsigned error, char *name) { 1074642e01fSmrg while (error >= nerror) { 1084642e01fSmrg if (!double_size(&errors, nerror, sizeof(char *))) 1094642e01fSmrg return; 1104642e01fSmrg nerror = nerror ? nerror * 2 : BASE_SIZE; 1114642e01fSmrg } 1124642e01fSmrg 1134642e01fSmrg free(errors[error]); 1144642e01fSmrg errors[error] = name; 1154642e01fSmrg} 1164642e01fSmrg 1174642e01fSmrgvoid 1184642e01fSmrgRegisterExtensionNames(ExtensionEntry *extEntry) 1194642e01fSmrg{ 1204642e01fSmrg char buf[256], *lineobj, *ptr; 1214642e01fSmrg unsigned offset; 1224642e01fSmrg 1234642e01fSmrg if (fh == NULL) 1244642e01fSmrg return; 1254642e01fSmrg 1264642e01fSmrg rewind(fh); 1274642e01fSmrg 1284642e01fSmrg while (fgets(buf, sizeof(buf), fh)) { 1294642e01fSmrg lineobj = NULL; 1304642e01fSmrg ptr = strchr(buf, '\n'); 1314642e01fSmrg if (ptr) 1324642e01fSmrg *ptr = 0; 1334642e01fSmrg 1344642e01fSmrg /* Check for comments or empty lines */ 1354642e01fSmrg switch (buf[0]) { 1364642e01fSmrg case PROT_REQUEST: 1374642e01fSmrg case PROT_EVENT: 1384642e01fSmrg case PROT_ERROR: 1394642e01fSmrg break; 1404642e01fSmrg case PROT_COMMENT: 1414642e01fSmrg case '\0': 1424642e01fSmrg continue; 1434642e01fSmrg default: 1444642e01fSmrg goto invalid; 1454642e01fSmrg } 1464642e01fSmrg 1474642e01fSmrg /* Check for space character in the fifth position */ 1484642e01fSmrg ptr = strchr(buf, ' '); 1494642e01fSmrg if (!ptr || ptr != buf + 4) 1504642e01fSmrg goto invalid; 1514642e01fSmrg 1524642e01fSmrg /* Duplicate the string after the space */ 1534642e01fSmrg lineobj = strdup(ptr + 1); 1544642e01fSmrg if (!lineobj) 1554642e01fSmrg continue; 1564642e01fSmrg 1574642e01fSmrg /* Check for a colon somewhere on the line */ 1584642e01fSmrg ptr = strchr(buf, ':'); 1594642e01fSmrg if (!ptr) 1604642e01fSmrg goto invalid; 1614642e01fSmrg 1624642e01fSmrg /* Compare the part before colon with the target extension name */ 1634642e01fSmrg *ptr = 0; 1644642e01fSmrg if (strcmp(buf + 5, extEntry->name)) 1654642e01fSmrg goto skip; 1664642e01fSmrg 1674642e01fSmrg /* Get the opcode for the request, event, or error */ 1684642e01fSmrg offset = strtol(buf + 1, &ptr, 10); 1694642e01fSmrg if (offset == 0 && ptr == buf + 1) 1704642e01fSmrg goto invalid; 1714642e01fSmrg 1724642e01fSmrg /* Save the strdup result in the registry */ 1734642e01fSmrg switch(buf[0]) { 1744642e01fSmrg case PROT_REQUEST: 1754642e01fSmrg if (extEntry->base) 1764642e01fSmrg RegisterRequestName(extEntry->base, offset, lineobj); 1774642e01fSmrg else 1784642e01fSmrg RegisterRequestName(offset, 0, lineobj); 1794642e01fSmrg continue; 1804642e01fSmrg case PROT_EVENT: 1814642e01fSmrg RegisterEventName(extEntry->eventBase + offset, lineobj); 1824642e01fSmrg continue; 1834642e01fSmrg case PROT_ERROR: 1844642e01fSmrg RegisterErrorName(extEntry->errorBase + offset, lineobj); 1854642e01fSmrg continue; 1864642e01fSmrg } 1874642e01fSmrg 1884642e01fSmrg invalid: 1894642e01fSmrg LogMessage(X_WARNING, "Invalid line in " FILENAME ", skipping\n"); 1904642e01fSmrg skip: 1914642e01fSmrg free(lineobj); 1924642e01fSmrg } 1934642e01fSmrg} 1944642e01fSmrg 1954642e01fSmrg/* 1964642e01fSmrg * Registration functions 1974642e01fSmrg */ 1984642e01fSmrg 1994642e01fSmrgvoid 2004642e01fSmrgRegisterResourceName(RESTYPE resource, char *name) 2014642e01fSmrg{ 2024642e01fSmrg resource &= TypeMask; 2034642e01fSmrg 2044642e01fSmrg while (resource >= nresource) { 2054642e01fSmrg if (!double_size(&resources, nresource, sizeof(char *))) 2064642e01fSmrg return; 2074642e01fSmrg nresource = nresource ? nresource * 2 : BASE_SIZE; 2084642e01fSmrg } 2094642e01fSmrg 2104642e01fSmrg resources[resource] = name; 2114642e01fSmrg} 2124642e01fSmrg 2134642e01fSmrg/* 2144642e01fSmrg * Lookup functions 2154642e01fSmrg */ 2164642e01fSmrg 2174642e01fSmrgconst char * 2184642e01fSmrgLookupRequestName(int major, int minor) 2194642e01fSmrg{ 2204642e01fSmrg if (major >= nmajor) 2214642e01fSmrg return XREGISTRY_UNKNOWN; 2224642e01fSmrg if (minor >= nminor[major]) 2234642e01fSmrg return XREGISTRY_UNKNOWN; 2244642e01fSmrg 2254642e01fSmrg return requests[major][minor] ? requests[major][minor] : XREGISTRY_UNKNOWN; 2264642e01fSmrg} 2274642e01fSmrg 2284642e01fSmrgconst char * 2294642e01fSmrgLookupMajorName(int major) 2304642e01fSmrg{ 2314642e01fSmrg if (major < 128) { 2324642e01fSmrg const char *retval; 2334642e01fSmrg 2344642e01fSmrg if (major >= nmajor) 2354642e01fSmrg return XREGISTRY_UNKNOWN; 2364642e01fSmrg if (0 >= nminor[major]) 2374642e01fSmrg return XREGISTRY_UNKNOWN; 2384642e01fSmrg 2394642e01fSmrg retval = requests[major][0]; 2404642e01fSmrg return retval ? retval + sizeof(CORE) : XREGISTRY_UNKNOWN; 2414642e01fSmrg } else { 2424642e01fSmrg ExtensionEntry *extEntry = GetExtensionEntry(major); 2434642e01fSmrg return extEntry ? extEntry->name : XREGISTRY_UNKNOWN; 2444642e01fSmrg } 2454642e01fSmrg} 2464642e01fSmrg 2474642e01fSmrgconst char * 2484642e01fSmrgLookupEventName(int event) 2494642e01fSmrg{ 2504642e01fSmrg event &= 127; 2514642e01fSmrg if (event >= nevent) 2524642e01fSmrg return XREGISTRY_UNKNOWN; 2534642e01fSmrg 2544642e01fSmrg return events[event] ? events[event] : XREGISTRY_UNKNOWN; 2554642e01fSmrg} 2564642e01fSmrg 2574642e01fSmrgconst char * 2584642e01fSmrgLookupErrorName(int error) 2594642e01fSmrg{ 2604642e01fSmrg if (error >= nerror) 2614642e01fSmrg return XREGISTRY_UNKNOWN; 2624642e01fSmrg 2634642e01fSmrg return errors[error] ? errors[error] : XREGISTRY_UNKNOWN; 2644642e01fSmrg} 2654642e01fSmrg 2664642e01fSmrgconst char * 2674642e01fSmrgLookupResourceName(RESTYPE resource) 2684642e01fSmrg{ 2694642e01fSmrg resource &= TypeMask; 2704642e01fSmrg if (resource >= nresource) 2714642e01fSmrg return XREGISTRY_UNKNOWN; 2724642e01fSmrg 2734642e01fSmrg return resources[resource] ? resources[resource] : XREGISTRY_UNKNOWN; 2744642e01fSmrg} 2754642e01fSmrg 2764642e01fSmrg/* 2774642e01fSmrg * Setup and teardown 2784642e01fSmrg */ 2794642e01fSmrgvoid 2804642e01fSmrgdixResetRegistry(void) 2814642e01fSmrg{ 2824642e01fSmrg ExtensionEntry extEntry; 2834642e01fSmrg 2844642e01fSmrg /* Free all memory */ 2854642e01fSmrg while (nmajor--) { 2864642e01fSmrg while (nminor[nmajor]) 2874642e01fSmrg free(requests[nmajor][--nminor[nmajor]]); 2886747b715Smrg free(requests[nmajor]); 2894642e01fSmrg } 2906747b715Smrg free(requests); 2916747b715Smrg free(nminor); 2924642e01fSmrg 2934642e01fSmrg while (nevent--) 2944642e01fSmrg free(events[nevent]); 2956747b715Smrg free(events); 2964642e01fSmrg 2974642e01fSmrg while (nerror--) 2984642e01fSmrg free(errors[nerror]); 2996747b715Smrg free(errors); 3004642e01fSmrg 3016747b715Smrg free(resources); 3024642e01fSmrg 3034642e01fSmrg requests = NULL; 3044642e01fSmrg nminor = NULL; 3054642e01fSmrg events = NULL; 3064642e01fSmrg errors = NULL; 3074642e01fSmrg resources = NULL; 3084642e01fSmrg 3094642e01fSmrg nmajor = nevent = nerror = nresource = 0; 3104642e01fSmrg 3114642e01fSmrg /* Open the protocol file */ 3124642e01fSmrg if (fh) 3134642e01fSmrg fclose(fh); 3144642e01fSmrg fh = fopen(FILENAME, "r"); 3154642e01fSmrg if (!fh) 3166747b715Smrg LogMessage(X_WARNING, "Failed to open protocol names file " FILENAME "\n"); 3174642e01fSmrg 3184642e01fSmrg /* Add built-in resources */ 3194642e01fSmrg RegisterResourceName(RT_NONE, "NONE"); 3204642e01fSmrg RegisterResourceName(RT_WINDOW, "WINDOW"); 3214642e01fSmrg RegisterResourceName(RT_PIXMAP, "PIXMAP"); 3224642e01fSmrg RegisterResourceName(RT_GC, "GC"); 3234642e01fSmrg RegisterResourceName(RT_FONT, "FONT"); 3244642e01fSmrg RegisterResourceName(RT_CURSOR, "CURSOR"); 3254642e01fSmrg RegisterResourceName(RT_COLORMAP, "COLORMAP"); 3264642e01fSmrg RegisterResourceName(RT_CMAPENTRY, "COLORMAP ENTRY"); 3274642e01fSmrg RegisterResourceName(RT_OTHERCLIENT, "OTHER CLIENT"); 3284642e01fSmrg RegisterResourceName(RT_PASSIVEGRAB, "PASSIVE GRAB"); 3294642e01fSmrg 3304642e01fSmrg /* Add the core protocol */ 3314642e01fSmrg memset(&extEntry, 0, sizeof(extEntry)); 3324642e01fSmrg extEntry.name = CORE; 3334642e01fSmrg RegisterExtensionNames(&extEntry); 3344642e01fSmrg} 3354642e01fSmrg 3364642e01fSmrg#endif /* XREGISTRY */ 337