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#include <stdlib.h> 254642e01fSmrg#include <string.h> 264642e01fSmrg#include <X11/X.h> 274642e01fSmrg#include <X11/Xproto.h> 284642e01fSmrg#include "resource.h" 294642e01fSmrg#include "registry.h" 304642e01fSmrg 314642e01fSmrg#define BASE_SIZE 16 3235c4bbdfSmrg 3335c4bbdfSmrg#ifdef X_REGISTRY_REQUEST 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 4435c4bbdfSmrgstatic char ***requests, **events, **errors; 4535c4bbdfSmrgstatic unsigned nmajor, *nminor, nevent, nerror; 4635c4bbdfSmrg#endif 4735c4bbdfSmrg 4835c4bbdfSmrg#ifdef X_REGISTRY_RESOURCE 4935c4bbdfSmrgstatic const char **resources; 5035c4bbdfSmrgstatic unsigned nresource; 5135c4bbdfSmrg#endif 524642e01fSmrg 5335c4bbdfSmrg#if defined(X_REGISTRY_RESOURCE) || defined(X_REGISTRY_REQUEST) 544642e01fSmrg/* 554642e01fSmrg * File parsing routines 564642e01fSmrg */ 5735c4bbdfSmrgstatic int 5835c4bbdfSmrgdouble_size(void *p, unsigned n, unsigned size) 594642e01fSmrg{ 6035c4bbdfSmrg char **ptr = (char **) p; 614642e01fSmrg unsigned s, f; 624642e01fSmrg 634642e01fSmrg if (n) { 6435c4bbdfSmrg s = n * size; 6535c4bbdfSmrg n *= 2 * size; 6635c4bbdfSmrg f = n; 6735c4bbdfSmrg } 6835c4bbdfSmrg else { 6935c4bbdfSmrg s = 0; 7035c4bbdfSmrg n = f = BASE_SIZE * size; 714642e01fSmrg } 724642e01fSmrg 736747b715Smrg *ptr = realloc(*ptr, n); 744642e01fSmrg if (!*ptr) { 7535c4bbdfSmrg dixResetRegistry(); 7635c4bbdfSmrg return FALSE; 774642e01fSmrg } 784642e01fSmrg memset(*ptr + s, 0, f - s); 794642e01fSmrg return TRUE; 8035c4bbdfSmrg} 8135c4bbdfSmrg#endif 824642e01fSmrg 8335c4bbdfSmrg#ifdef X_REGISTRY_REQUEST 8435c4bbdfSmrg/* 8535c4bbdfSmrg * Request/event/error registry functions 8635c4bbdfSmrg */ 874642e01fSmrgstatic void 884642e01fSmrgRegisterRequestName(unsigned major, unsigned minor, char *name) 894642e01fSmrg{ 904642e01fSmrg while (major >= nmajor) { 9135c4bbdfSmrg if (!double_size(&requests, nmajor, sizeof(char **))) 9235c4bbdfSmrg return; 9335c4bbdfSmrg if (!double_size(&nminor, nmajor, sizeof(unsigned))) 9435c4bbdfSmrg return; 9535c4bbdfSmrg nmajor = nmajor ? nmajor * 2 : BASE_SIZE; 964642e01fSmrg } 974642e01fSmrg while (minor >= nminor[major]) { 9835c4bbdfSmrg if (!double_size(requests + major, nminor[major], sizeof(char *))) 9935c4bbdfSmrg return; 10035c4bbdfSmrg nminor[major] = nminor[major] ? nminor[major] * 2 : BASE_SIZE; 1014642e01fSmrg } 1024642e01fSmrg 1034642e01fSmrg free(requests[major][minor]); 1044642e01fSmrg requests[major][minor] = name; 1054642e01fSmrg} 1064642e01fSmrg 1074642e01fSmrgstatic void 10835c4bbdfSmrgRegisterEventName(unsigned event, char *name) 10935c4bbdfSmrg{ 1104642e01fSmrg while (event >= nevent) { 11135c4bbdfSmrg if (!double_size(&events, nevent, sizeof(char *))) 11235c4bbdfSmrg return; 11335c4bbdfSmrg nevent = nevent ? nevent * 2 : BASE_SIZE; 1144642e01fSmrg } 1154642e01fSmrg 1164642e01fSmrg free(events[event]); 1174642e01fSmrg events[event] = name; 1184642e01fSmrg} 1194642e01fSmrg 1204642e01fSmrgstatic void 12135c4bbdfSmrgRegisterErrorName(unsigned error, char *name) 12235c4bbdfSmrg{ 1234642e01fSmrg while (error >= nerror) { 12435c4bbdfSmrg if (!double_size(&errors, nerror, sizeof(char *))) 12535c4bbdfSmrg return; 12635c4bbdfSmrg nerror = nerror ? nerror * 2 : BASE_SIZE; 1274642e01fSmrg } 1284642e01fSmrg 1294642e01fSmrg free(errors[error]); 1304642e01fSmrg errors[error] = name; 1314642e01fSmrg} 1324642e01fSmrg 1334642e01fSmrgvoid 13435c4bbdfSmrgRegisterExtensionNames(ExtensionEntry * extEntry) 1354642e01fSmrg{ 1364642e01fSmrg char buf[256], *lineobj, *ptr; 1374642e01fSmrg unsigned offset; 1384642e01fSmrg 1394642e01fSmrg if (fh == NULL) 14035c4bbdfSmrg return; 1414642e01fSmrg 1424642e01fSmrg rewind(fh); 1434642e01fSmrg 1444642e01fSmrg while (fgets(buf, sizeof(buf), fh)) { 14535c4bbdfSmrg lineobj = NULL; 14635c4bbdfSmrg ptr = strchr(buf, '\n'); 14735c4bbdfSmrg if (ptr) 14835c4bbdfSmrg *ptr = 0; 14935c4bbdfSmrg 15035c4bbdfSmrg /* Check for comments or empty lines */ 15135c4bbdfSmrg switch (buf[0]) { 15235c4bbdfSmrg case PROT_REQUEST: 15335c4bbdfSmrg case PROT_EVENT: 15435c4bbdfSmrg case PROT_ERROR: 15535c4bbdfSmrg break; 15635c4bbdfSmrg case PROT_COMMENT: 15735c4bbdfSmrg case '\0': 15835c4bbdfSmrg continue; 15935c4bbdfSmrg default: 16035c4bbdfSmrg goto invalid; 16135c4bbdfSmrg } 16235c4bbdfSmrg 16335c4bbdfSmrg /* Check for space character in the fifth position */ 16435c4bbdfSmrg ptr = strchr(buf, ' '); 16535c4bbdfSmrg if (!ptr || ptr != buf + 4) 16635c4bbdfSmrg goto invalid; 16735c4bbdfSmrg 16835c4bbdfSmrg /* Duplicate the string after the space */ 16935c4bbdfSmrg lineobj = strdup(ptr + 1); 17035c4bbdfSmrg if (!lineobj) 17135c4bbdfSmrg continue; 17235c4bbdfSmrg 17335c4bbdfSmrg /* Check for a colon somewhere on the line */ 17435c4bbdfSmrg ptr = strchr(buf, ':'); 17535c4bbdfSmrg if (!ptr) 17635c4bbdfSmrg goto invalid; 17735c4bbdfSmrg 17835c4bbdfSmrg /* Compare the part before colon with the target extension name */ 17935c4bbdfSmrg *ptr = 0; 18035c4bbdfSmrg if (strcmp(buf + 5, extEntry->name)) 18135c4bbdfSmrg goto skip; 18235c4bbdfSmrg 18335c4bbdfSmrg /* Get the opcode for the request, event, or error */ 18435c4bbdfSmrg offset = strtol(buf + 1, &ptr, 10); 18535c4bbdfSmrg if (offset == 0 && ptr == buf + 1) 18635c4bbdfSmrg goto invalid; 18735c4bbdfSmrg 18835c4bbdfSmrg /* Save the strdup result in the registry */ 18935c4bbdfSmrg switch (buf[0]) { 19035c4bbdfSmrg case PROT_REQUEST: 19135c4bbdfSmrg if (extEntry->base) 19235c4bbdfSmrg RegisterRequestName(extEntry->base, offset, lineobj); 19335c4bbdfSmrg else 19435c4bbdfSmrg RegisterRequestName(offset, 0, lineobj); 19535c4bbdfSmrg continue; 19635c4bbdfSmrg case PROT_EVENT: 19735c4bbdfSmrg RegisterEventName(extEntry->eventBase + offset, lineobj); 19835c4bbdfSmrg continue; 19935c4bbdfSmrg case PROT_ERROR: 20035c4bbdfSmrg RegisterErrorName(extEntry->errorBase + offset, lineobj); 20135c4bbdfSmrg continue; 20235c4bbdfSmrg } 20335c4bbdfSmrg 20435c4bbdfSmrg invalid: 20535c4bbdfSmrg LogMessage(X_WARNING, "Invalid line in " FILENAME ", skipping\n"); 20635c4bbdfSmrg skip: 20735c4bbdfSmrg free(lineobj); 2084642e01fSmrg } 2094642e01fSmrg} 2104642e01fSmrg 2114642e01fSmrgconst char * 2124642e01fSmrgLookupRequestName(int major, int minor) 2134642e01fSmrg{ 2144642e01fSmrg if (major >= nmajor) 21535c4bbdfSmrg return XREGISTRY_UNKNOWN; 2164642e01fSmrg if (minor >= nminor[major]) 21735c4bbdfSmrg return XREGISTRY_UNKNOWN; 2184642e01fSmrg 2194642e01fSmrg return requests[major][minor] ? requests[major][minor] : XREGISTRY_UNKNOWN; 2204642e01fSmrg} 2214642e01fSmrg 2224642e01fSmrgconst char * 2234642e01fSmrgLookupMajorName(int major) 2244642e01fSmrg{ 2254642e01fSmrg if (major < 128) { 22635c4bbdfSmrg const char *retval; 22735c4bbdfSmrg 22835c4bbdfSmrg if (major >= nmajor) 22935c4bbdfSmrg return XREGISTRY_UNKNOWN; 23035c4bbdfSmrg if (0 >= nminor[major]) 23135c4bbdfSmrg return XREGISTRY_UNKNOWN; 23235c4bbdfSmrg 23335c4bbdfSmrg retval = requests[major][0]; 23435c4bbdfSmrg return retval ? retval + sizeof(CORE) : XREGISTRY_UNKNOWN; 23535c4bbdfSmrg } 23635c4bbdfSmrg else { 23735c4bbdfSmrg ExtensionEntry *extEntry = GetExtensionEntry(major); 23835c4bbdfSmrg 23935c4bbdfSmrg return extEntry ? extEntry->name : XREGISTRY_UNKNOWN; 2404642e01fSmrg } 2414642e01fSmrg} 2424642e01fSmrg 2434642e01fSmrgconst char * 2444642e01fSmrgLookupEventName(int event) 2454642e01fSmrg{ 2464642e01fSmrg event &= 127; 2474642e01fSmrg if (event >= nevent) 24835c4bbdfSmrg return XREGISTRY_UNKNOWN; 2494642e01fSmrg 2504642e01fSmrg return events[event] ? events[event] : XREGISTRY_UNKNOWN; 2514642e01fSmrg} 2524642e01fSmrg 2534642e01fSmrgconst char * 2544642e01fSmrgLookupErrorName(int error) 2554642e01fSmrg{ 2564642e01fSmrg if (error >= nerror) 25735c4bbdfSmrg return XREGISTRY_UNKNOWN; 2584642e01fSmrg 2594642e01fSmrg return errors[error] ? errors[error] : XREGISTRY_UNKNOWN; 2604642e01fSmrg} 26135c4bbdfSmrg#endif /* X_REGISTRY_REQUEST */ 26235c4bbdfSmrg 26335c4bbdfSmrg#ifdef X_REGISTRY_RESOURCE 26435c4bbdfSmrg/* 26535c4bbdfSmrg * Resource registry functions 26635c4bbdfSmrg */ 26735c4bbdfSmrg 26835c4bbdfSmrgvoid 26935c4bbdfSmrgRegisterResourceName(RESTYPE resource, const char *name) 27035c4bbdfSmrg{ 27135c4bbdfSmrg resource &= TypeMask; 27235c4bbdfSmrg 27335c4bbdfSmrg while (resource >= nresource) { 27435c4bbdfSmrg if (!double_size(&resources, nresource, sizeof(char *))) 27535c4bbdfSmrg return; 27635c4bbdfSmrg nresource = nresource ? nresource * 2 : BASE_SIZE; 27735c4bbdfSmrg } 27835c4bbdfSmrg 27935c4bbdfSmrg resources[resource] = name; 28035c4bbdfSmrg} 2814642e01fSmrg 2824642e01fSmrgconst char * 2834642e01fSmrgLookupResourceName(RESTYPE resource) 2844642e01fSmrg{ 2854642e01fSmrg resource &= TypeMask; 2864642e01fSmrg if (resource >= nresource) 28735c4bbdfSmrg return XREGISTRY_UNKNOWN; 2884642e01fSmrg 2894642e01fSmrg return resources[resource] ? resources[resource] : XREGISTRY_UNKNOWN; 2904642e01fSmrg} 29135c4bbdfSmrg#endif /* X_REGISTRY_RESOURCE */ 2924642e01fSmrg 2934642e01fSmrgvoid 29435c4bbdfSmrgdixFreeRegistry(void) 2954642e01fSmrg{ 29635c4bbdfSmrg#ifdef X_REGISTRY_REQUEST 2974642e01fSmrg /* Free all memory */ 2984642e01fSmrg while (nmajor--) { 29935c4bbdfSmrg while (nminor[nmajor]) 30035c4bbdfSmrg free(requests[nmajor][--nminor[nmajor]]); 30135c4bbdfSmrg free(requests[nmajor]); 3024642e01fSmrg } 3036747b715Smrg free(requests); 3046747b715Smrg free(nminor); 3054642e01fSmrg 3064642e01fSmrg while (nevent--) 30735c4bbdfSmrg free(events[nevent]); 3086747b715Smrg free(events); 3094642e01fSmrg 3104642e01fSmrg while (nerror--) 31135c4bbdfSmrg free(errors[nerror]); 3126747b715Smrg free(errors); 3134642e01fSmrg requests = NULL; 3144642e01fSmrg nminor = NULL; 3154642e01fSmrg events = NULL; 3164642e01fSmrg errors = NULL; 31735c4bbdfSmrg nmajor = nevent = nerror = 0; 31835c4bbdfSmrg#endif 31935c4bbdfSmrg 32035c4bbdfSmrg#ifdef X_REGISTRY_RESOURCE 32135c4bbdfSmrg free(resources); 32235c4bbdfSmrg 3234642e01fSmrg resources = NULL; 32435c4bbdfSmrg nresource = 0; 32535c4bbdfSmrg#endif 32635c4bbdfSmrg} 32735c4bbdfSmrg 32835c4bbdfSmrgvoid 32935c4bbdfSmrgdixCloseRegistry(void) 33035c4bbdfSmrg{ 33135c4bbdfSmrg#ifdef X_REGISTRY_REQUEST 33235c4bbdfSmrg if (fh) { 33335c4bbdfSmrg fclose(fh); 33435c4bbdfSmrg fh = NULL; 33535c4bbdfSmrg } 33635c4bbdfSmrg#endif 33735c4bbdfSmrg} 33835c4bbdfSmrg 33935c4bbdfSmrg/* 34035c4bbdfSmrg * Setup and teardown 34135c4bbdfSmrg */ 34235c4bbdfSmrgvoid 34335c4bbdfSmrgdixResetRegistry(void) 34435c4bbdfSmrg{ 34535c4bbdfSmrg#ifdef X_REGISTRY_REQUEST 34635c4bbdfSmrg ExtensionEntry extEntry = { .name = CORE }; 34735c4bbdfSmrg#endif 3484642e01fSmrg 34935c4bbdfSmrg dixFreeRegistry(); 3504642e01fSmrg 35135c4bbdfSmrg#ifdef X_REGISTRY_REQUEST 3524642e01fSmrg /* Open the protocol file */ 3534642e01fSmrg fh = fopen(FILENAME, "r"); 3544642e01fSmrg if (!fh) 35535c4bbdfSmrg LogMessage(X_WARNING, 35635c4bbdfSmrg "Failed to open protocol names file " FILENAME "\n"); 35735c4bbdfSmrg 35835c4bbdfSmrg /* Add the core protocol */ 35935c4bbdfSmrg RegisterExtensionNames(&extEntry); 36035c4bbdfSmrg#endif 3614642e01fSmrg 36235c4bbdfSmrg#ifdef X_REGISTRY_RESOURCE 3634642e01fSmrg /* Add built-in resources */ 3644642e01fSmrg RegisterResourceName(RT_NONE, "NONE"); 3654642e01fSmrg RegisterResourceName(RT_WINDOW, "WINDOW"); 3664642e01fSmrg RegisterResourceName(RT_PIXMAP, "PIXMAP"); 3674642e01fSmrg RegisterResourceName(RT_GC, "GC"); 3684642e01fSmrg RegisterResourceName(RT_FONT, "FONT"); 3694642e01fSmrg RegisterResourceName(RT_CURSOR, "CURSOR"); 3704642e01fSmrg RegisterResourceName(RT_COLORMAP, "COLORMAP"); 3714642e01fSmrg RegisterResourceName(RT_CMAPENTRY, "COLORMAP ENTRY"); 3724642e01fSmrg RegisterResourceName(RT_OTHERCLIENT, "OTHER CLIENT"); 3734642e01fSmrg RegisterResourceName(RT_PASSIVEGRAB, "PASSIVE GRAB"); 37435c4bbdfSmrg#endif 3754642e01fSmrg} 376