registry.c revision 4642e01f
14642e01fSmrg/************************************************************
24642e01fSmrg
34642e01fSmrgAuthor: Eamon Walsh <ewalsh@epoch.ncsc.mil>
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
644642e01fSmrg    *ptr = xrealloc(*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]]);
2884642e01fSmrg	xfree(requests[nmajor]);
2894642e01fSmrg    }
2904642e01fSmrg    xfree(requests);
2914642e01fSmrg    xfree(nminor);
2924642e01fSmrg
2934642e01fSmrg    while (nevent--)
2944642e01fSmrg	free(events[nevent]);
2954642e01fSmrg    xfree(events);
2964642e01fSmrg
2974642e01fSmrg    while (nerror--)
2984642e01fSmrg	free(errors[nerror]);
2994642e01fSmrg    xfree(errors);
3004642e01fSmrg
3014642e01fSmrg    xfree(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)
3164642e01fSmrg	LogMessage(X_WARNING, "Failed to open protocol names file " FILENAME);
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