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