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