Edit

IABSD.fr/xenocara/xserver/Xext/xf86bigfont.c

Branch :

  • Show log

    Commit

  • Author : matthieu
    Date : 2026-05-08 11:12:08
    Hash : f0e0a48c
    Message : Update to xserver 21.1.22. The security fixes were already committed.

  • xserver/Xext/xf86bigfont.c
  • /*
     * BIGFONT extension for sharing font metrics between clients (if possible)
     * and for transmitting font metrics to clients in a compressed form.
     *
     * Copyright (c) 1999-2000  Bruno Haible
     * Copyright (c) 1999-2000  The XFree86 Project, Inc.
     */
    
    /* THIS IS NOT AN X CONSORTIUM STANDARD */
    
    /*
     * Big fonts suffer from the following: All clients that have opened a
     * font can access the complete glyph metrics array (the XFontStruct member
     * `per_char') directly, without going through a macro. Moreover these
     * glyph metrics are ink metrics, i.e. are not redundant even for a
     * fixed-width font. For a Unicode font, the size of this array is 768 KB.
     *
     * Problems: 1. It eats a lot of memory in each client. 2. All this glyph
     * metrics data is piped through the socket when the font is opened.
     *
     * This extension addresses these two problems for local clients, by using
     * shared memory. It also addresses the second problem for non-local clients,
     * by compressing the data before transmit by a factor of nearly 6.
     *
     * If you use this extension, your OS ought to nicely support shared memory.
     * This means: Shared memory should be swappable to the swap, and the limits
     * should be high enough (SHMMNI at least 64, SHMMAX at least 768 KB,
     * SHMALL at least 48 MB). It is a plus if your OS allows shmat() calls
     * on segments that have already been marked "removed", because it permits
     * these segments to be cleaned up by the OS if the X server is killed with
     * signal SIGKILL.
     *
     * This extension is transparently exploited by Xlib (functions XQueryFont,
     * XLoadQueryFont).
     */
    
    #ifdef HAVE_DIX_CONFIG_H
    #include <dix-config.h>
    #endif
    
    #include <sys/types.h>
    #ifdef HAS_SHM
    #ifdef SVR4
    #include <sys/sysmacros.h>
    #endif
    #if defined(__CYGWIN__)
    #include <sys/param.h>
    #include <sys/sysmacros.h>
    #endif
    #include <sys/ipc.h>
    #include <sys/shm.h>
    #include <sys/stat.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <time.h>
    #include <errno.h>
    #endif
    
    #include <X11/X.h>
    #include <X11/Xproto.h>
    #include <X11/fonts/fontstruct.h>
    #include <X11/fonts/libxfont2.h>
    
    #include "misc.h"
    #include "os.h"
    #include "dixstruct.h"
    #include "gcstruct.h"
    #include "dixfontstr.h"
    #include "extnsionst.h"
    #include "extinit.h"
    #include "protocol-versions.h"
    
    #include <X11/extensions/xf86bigfproto.h>
    #include "xf86bigfontsrv.h"
    
    static void XF86BigfontResetProc(ExtensionEntry *       /* extEntry */
        );
    
    #ifdef HAS_SHM
    
    /* A random signature, transmitted to the clients so they can verify that the
       shared memory segment they are attaching to was really established by the
       X server they are talking to. */
    static CARD32 signature;
    
    /* Index for additional information stored in a FontRec's devPrivates array. */
    static int FontShmdescIndex;
    
    static unsigned int pagesize;
    
    static Bool badSysCall = FALSE;
    
    #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__CYGWIN__) || defined(__DragonFly__)
    
    static void
    SigSysHandler(int signo)
    {
        badSysCall = TRUE;
    }
    
    static Bool
    CheckForShmSyscall(void)
    {
        void (*oldHandler) (int);
        int shmid = -1;
    
        /* If no SHM support in the kernel, the bad syscall will generate SIGSYS */
        oldHandler = OsSignal(SIGSYS, SigSysHandler);
    
        badSysCall = FALSE;
        shmid = shmget(IPC_PRIVATE, 4096, IPC_CREAT);
        if (shmid != -1) {
            /* Successful allocation - clean up */
            shmctl(shmid, IPC_RMID, NULL);
        }
        else {
            /* Allocation failed */
            badSysCall = TRUE;
        }
        OsSignal(SIGSYS, oldHandler);
        return !badSysCall;
    }
    
    #define MUST_CHECK_FOR_SHM_SYSCALL
    
    #endif
    
    #endif
    
    /* ========== Management of shared memory segments ========== */
    
    #ifdef HAS_SHM
    
    #ifdef __linux__
    /* On Linux, shared memory marked as "removed" can still be attached.
       Nice feature, because the kernel will automatically free the associated
       storage when the server and all clients are gone. */
    #define EARLY_REMOVE
    #endif
    
    typedef struct _ShmDesc {
        struct _ShmDesc *next;
        struct _ShmDesc **prev;
        int shmid;
        char *attach_addr;
    } ShmDescRec, *ShmDescPtr;
    
    static ShmDescPtr ShmList = (ShmDescPtr) NULL;
    
    static ShmDescPtr
    shmalloc(unsigned int size)
    {
        ShmDescPtr pDesc;
        int shmid;
        char *addr;
    
    #ifdef MUST_CHECK_FOR_SHM_SYSCALL
        if (pagesize == 0)
            return (ShmDescPtr) NULL;
    #endif
    
        /* On some older Linux systems, the number of shared memory segments
           system-wide is 127. In Linux 2.4, it is 4095.
           Therefore there is a tradeoff to be made between allocating a
           shared memory segment on one hand, and allocating memory and piping
           the glyph metrics on the other hand. If the glyph metrics size is
           small, we prefer the traditional way. */
        if (size < 3500)
            return (ShmDescPtr) NULL;
    
        pDesc = malloc(sizeof(ShmDescRec));
        if (!pDesc)
            return (ShmDescPtr) NULL;
    
        size = (size + pagesize - 1) & -pagesize;
        shmid = shmget(IPC_PRIVATE, size, S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH);
        if (shmid == -1) {
            ErrorF(XF86BIGFONTNAME " extension: shmget() failed, size = %u, %s\n",
                   size, strerror(errno));
            free(pDesc);
            return (ShmDescPtr) NULL;
        }
    
        if ((addr = shmat(shmid, 0, 0)) == (char *) -1) {
            ErrorF(XF86BIGFONTNAME " extension: shmat() failed, size = %u, %s\n",
                   size, strerror(errno));
            shmctl(shmid, IPC_RMID, (void *) 0);
            free(pDesc);
            return (ShmDescPtr) NULL;
        }
    
    #ifdef EARLY_REMOVE
        shmctl(shmid, IPC_RMID, (void *) 0);
    #endif
    
        pDesc->shmid = shmid;
        pDesc->attach_addr = addr;
        if (ShmList)
            ShmList->prev = &pDesc->next;
        pDesc->next = ShmList;
        pDesc->prev = &ShmList;
        ShmList = pDesc;
    
        return pDesc;
    }
    
    static void
    shmdealloc(ShmDescPtr pDesc)
    {
    #ifndef EARLY_REMOVE
        shmctl(pDesc->shmid, IPC_RMID, (void *) 0);
    #endif
        shmdt(pDesc->attach_addr);
    
        if (pDesc->next)
            pDesc->next->prev = pDesc->prev;
        *pDesc->prev = pDesc->next;
        free(pDesc);
    }
    
    #endif
    
    /* Called when a font is closed. */
    void
    XF86BigfontFreeFontShm(FontPtr pFont)
    {
    #ifdef HAS_SHM
        ShmDescPtr pDesc;
    
        /* If during shutdown of the server, XF86BigfontCleanup() has already
         * called shmdealloc() for all segments, we don't need to do it here.
         */
        if (!ShmList)
            return;
    
        pDesc = (ShmDescPtr) FontGetPrivate(pFont, FontShmdescIndex);
        if (pDesc)
            shmdealloc(pDesc);
    #endif
    }
    
    /* Called upon fatal signal. */
    void
    XF86BigfontCleanup(void)
    {
    #ifdef HAS_SHM
        while (ShmList)
            shmdealloc(ShmList);
    #endif
    }
    
    /* Called when a server generation dies. */
    static void
    XF86BigfontResetProc(ExtensionEntry * extEntry)
    {
        /* This function is normally called from CloseDownExtensions(), called
         * from main(). It will be followed by a call to FreeAllResources(),
         * which will call XF86BigfontFreeFontShm() for each font. Thus it
         * appears that we do not need to do anything in this function. --
         * But I prefer to write robust code, and not keep shared memory lying
         * around when it's not needed any more. (Someone might close down the
         * extension without calling FreeAllResources()...)
         */
        XF86BigfontCleanup();
    }
    
    /* ========== Handling of extension specific requests ========== */
    
    static int
    ProcXF86BigfontQueryVersion(ClientPtr client)
    {
        xXF86BigfontQueryVersionReply reply;
    
        REQUEST_SIZE_MATCH(xXF86BigfontQueryVersionReq);
        reply = (xXF86BigfontQueryVersionReply) {
            .type = X_Reply,
            .sequenceNumber = client->sequence,
            .length = 0,
            .majorVersion = SERVER_XF86BIGFONT_MAJOR_VERSION,
            .minorVersion = SERVER_XF86BIGFONT_MINOR_VERSION,
            .uid = geteuid(),
            .gid = getegid(),
    #ifdef HAS_SHM
            .signature = signature,
            .capabilities = (client->local && !client->swapped)
                             ? XF86Bigfont_CAP_LocalShm : 0
    #else
            .signature = 0,
            .capabilities = 0
    #endif
        };
        if (client->swapped) {
            swaps(&reply.sequenceNumber);
            swapl(&reply.length);
            swaps(&reply.majorVersion);
            swaps(&reply.minorVersion);
            swapl(&reply.uid);
            swapl(&reply.gid);
            swapl(&reply.signature);
        }
        WriteToClient(client, sizeof(xXF86BigfontQueryVersionReply), &reply);
        return Success;
    }
    
    static void
    swapCharInfo(xCharInfo * pCI)
    {
        swaps(&pCI->leftSideBearing);
        swaps(&pCI->rightSideBearing);
        swaps(&pCI->characterWidth);
        swaps(&pCI->ascent);
        swaps(&pCI->descent);
        swaps(&pCI->attributes);
    }
    
    /* static CARD32 hashCI (xCharInfo *p); */
    #define hashCI(p) \
    	(CARD32)(((p->leftSideBearing << 27) + (p->leftSideBearing >> 5) + \
    	          (p->rightSideBearing << 23) + (p->rightSideBearing >> 9) + \
    	          (p->characterWidth << 16) + \
    	          (p->ascent << 11) + (p->descent << 6)) ^ p->attributes)
    
    static int
    ProcXF86BigfontQueryFont(ClientPtr client)
    {
        FontPtr pFont;
    
        REQUEST(xXF86BigfontQueryFontReq);
        CARD32 stuff_flags;
        xCharInfo *pmax;
        xCharInfo *pmin;
        int nCharInfos;
        int shmid;
    
    #ifdef HAS_SHM
        ShmDescPtr pDesc = NULL;
    #else
    #define pDesc 0
    #endif
        xCharInfo *pCI;
        CARD16 *pIndex2UniqIndex;
        CARD16 *pUniqIndex2Index;
        CARD32 nUniqCharInfos;
    
    #if 0
        REQUEST_SIZE_MATCH(xXF86BigfontQueryFontReq);
    #else
        switch (client->req_len) {
        case 2:                    /* client with version 1.0 libX11 */
            stuff_flags = (client->local &&
                           !client->swapped ? XF86Bigfont_FLAGS_Shm : 0);
            break;
        case 3:                    /* client with version 1.1 libX11 */
            stuff_flags = stuff->flags;
            break;
        default:
            return BadLength;
        }
    #endif
        if (dixLookupFontable(&pFont, stuff->id, client, DixGetAttrAccess) !=
            Success)
            return BadFont;         /* procotol spec says only error is BadFont */
    
        pmax = FONTINKMAX(pFont);
        pmin = FONTINKMIN(pFont);
        nCharInfos =
            (pmax->rightSideBearing == pmin->rightSideBearing
             && pmax->leftSideBearing == pmin->leftSideBearing
             && pmax->descent == pmin->descent
             && pmax->ascent == pmin->ascent
             && pmax->characterWidth == pmin->characterWidth)
            ? 0 : N2dChars(pFont);
        shmid = -1;
        pCI = NULL;
        pIndex2UniqIndex = NULL;
        pUniqIndex2Index = NULL;
        nUniqCharInfos = 0;
    
        if (nCharInfos > 0) {
    #ifdef HAS_SHM
            if (!badSysCall)
                pDesc = (ShmDescPtr) FontGetPrivate(pFont, FontShmdescIndex);
            if (pDesc) {
                pCI = (xCharInfo *) pDesc->attach_addr;
                if (stuff_flags & XF86Bigfont_FLAGS_Shm)
                    shmid = pDesc->shmid;
            }
            else {
                if (stuff_flags & XF86Bigfont_FLAGS_Shm && !badSysCall)
                    pDesc = shmalloc(nCharInfos * sizeof(xCharInfo)
                                     + sizeof(CARD32));
                if (pDesc) {
                    pCI = (xCharInfo *) pDesc->attach_addr;
                    shmid = pDesc->shmid;
                }
                else {
    #endif
                    pCI = xallocarray(nCharInfos, sizeof(xCharInfo));
                    if (!pCI)
                        return BadAlloc;
    #ifdef HAS_SHM
                }
    #endif
                /* Fill nCharInfos starting at pCI. */
                {
                    xCharInfo *prCI = pCI;
                    int ninfos = 0;
                    int ncols = pFont->info.lastCol - pFont->info.firstCol + 1;
                    int row;
    
                    for (row = pFont->info.firstRow;
                         row <= pFont->info.lastRow && ninfos < nCharInfos; row++) {
                        unsigned char chars[512];
                        xCharInfo *tmpCharInfos[256];
                        unsigned long count;
                        int col;
                        unsigned long i;
    
                        i = 0;
                        for (col = pFont->info.firstCol;
                             col <= pFont->info.lastCol; col++) {
                            chars[i++] = row;
                            chars[i++] = col;
                        }
                        (*pFont->get_metrics) (pFont, ncols, chars, TwoD16Bit,
                                               &count, tmpCharInfos);
                        for (i = 0; i < count && ninfos < nCharInfos; i++) {
                            *prCI++ = *tmpCharInfos[i];
                            ninfos++;
                        }
                    }
                }
    #ifdef HAS_SHM
                if (pDesc && !badSysCall) {
                    *(CARD32 *) (pCI + nCharInfos) = signature;
                    if (!xfont2_font_set_private(pFont, FontShmdescIndex, pDesc)) {
                        shmdealloc(pDesc);
                        return BadAlloc;
                    }
                }
            }
    #endif
            if (shmid == -1) {
                /* Cannot use shared memory, so remove-duplicates the xCharInfos
                   using a temporary hash table. */
                /* Note that CARD16 is suitable as index type, because
                   nCharInfos <= 0x10000. */
                CARD32 hashModulus;
                CARD16 *pHash2UniqIndex;
                CARD16 *pUniqIndex2NextUniqIndex;
                CARD32 NextIndex;
                CARD32 NextUniqIndex;
                CARD16 *tmp;
                CARD32 i, j;
    
                hashModulus = 67;
                if (hashModulus > nCharInfos + 1)
                    hashModulus = nCharInfos + 1;
    
                tmp = xallocarray(4 * nCharInfos + 1, sizeof(CARD16));
                if (!tmp) {
                    if (!pDesc)
                        free(pCI);
                    return BadAlloc;
                }
                pIndex2UniqIndex = tmp;
                /* nCharInfos elements */
                pUniqIndex2Index = tmp + nCharInfos;
                /* max. nCharInfos elements */
                pUniqIndex2NextUniqIndex = tmp + 2 * nCharInfos;
                /* max. nCharInfos elements */
                pHash2UniqIndex = tmp + 3 * nCharInfos;
                /* hashModulus (<= nCharInfos+1) elements */
    
                /* Note that we can use 0xffff as end-of-list indicator, because
                   even if nCharInfos = 0x10000, 0xffff can not occur as valid
                   entry before the last element has been inserted. And once the
                   last element has been inserted, we don't need the hash table
                   any more. */
                for (j = 0; j < hashModulus; j++)
                    pHash2UniqIndex[j] = (CARD16) (-1);
    
                NextUniqIndex = 0;
                for (NextIndex = 0; NextIndex < nCharInfos; NextIndex++) {
                    xCharInfo *p = &pCI[NextIndex];
                    CARD32 hashCode = hashCI(p) % hashModulus;
    
                    for (i = pHash2UniqIndex[hashCode];
                         i != (CARD16) (-1); i = pUniqIndex2NextUniqIndex[i]) {
                        j = pUniqIndex2Index[i];
                        if (pCI[j].leftSideBearing == p->leftSideBearing
                            && pCI[j].rightSideBearing == p->rightSideBearing
                            && pCI[j].characterWidth == p->characterWidth
                            && pCI[j].ascent == p->ascent
                            && pCI[j].descent == p->descent
                            && pCI[j].attributes == p->attributes)
                            break;
                    }
                    if (i != (CARD16) (-1)) {
                        /* Found *p at Index j, UniqIndex i */
                        pIndex2UniqIndex[NextIndex] = i;
                    }
                    else {
                        /* Allocate a new entry in the Uniq table */
                        if (hashModulus <= 2 * NextUniqIndex
                            && hashModulus < nCharInfos + 1) {
                            /* Time to increate hash table size */
                            hashModulus = 2 * hashModulus + 1;
                            if (hashModulus > nCharInfos + 1)
                                hashModulus = nCharInfos + 1;
                            for (j = 0; j < hashModulus; j++)
                                pHash2UniqIndex[j] = (CARD16) (-1);
                            for (i = 0; i < NextUniqIndex; i++)
                                pUniqIndex2NextUniqIndex[i] = (CARD16) (-1);
                            for (i = 0; i < NextUniqIndex; i++) {
                                j = pUniqIndex2Index[i];
                                p = &pCI[j];
                                hashCode = hashCI(p) % hashModulus;
                                pUniqIndex2NextUniqIndex[i] =
                                    pHash2UniqIndex[hashCode];
                                pHash2UniqIndex[hashCode] = i;
                            }
                            p = &pCI[NextIndex];
                            hashCode = hashCI(p) % hashModulus;
                        }
                        i = NextUniqIndex++;
                        pUniqIndex2NextUniqIndex[i] = pHash2UniqIndex[hashCode];
                        pHash2UniqIndex[hashCode] = i;
                        pUniqIndex2Index[i] = NextIndex;
                        pIndex2UniqIndex[NextIndex] = i;
                    }
                }
                nUniqCharInfos = NextUniqIndex;
                /* fprintf(stderr, "font metrics: nCharInfos = %d, nUniqCharInfos = %d, hashModulus = %d\n", nCharInfos, nUniqCharInfos, hashModulus); */
            }
        }
    
        {
            int nfontprops = pFont->info.nprops;
            int rlength = sizeof(xXF86BigfontQueryFontReply)
                + nfontprops * sizeof(xFontProp)
                + (nCharInfos > 0 && shmid == -1
                   ? nUniqCharInfos * sizeof(xCharInfo)
                   + (nCharInfos + 1) / 2 * 2 * sizeof(CARD16)
                   : 0);
            xXF86BigfontQueryFontReply *reply = calloc(1, rlength);
            char *p;
    
            if (!reply) {
                if (nCharInfos > 0) {
                    if (shmid == -1)
                        free(pIndex2UniqIndex);
                    if (!pDesc)
                        free(pCI);
                }
                return BadAlloc;
            }
            reply->type = X_Reply;
            reply->length = bytes_to_int32(rlength - sizeof(xGenericReply));
            reply->sequenceNumber = client->sequence;
            reply->minBounds = pFont->info.ink_minbounds;
            reply->maxBounds = pFont->info.ink_maxbounds;
            reply->minCharOrByte2 = pFont->info.firstCol;
            reply->maxCharOrByte2 = pFont->info.lastCol;
            reply->defaultChar = pFont->info.defaultCh;
            reply->nFontProps = pFont->info.nprops;
            reply->drawDirection = pFont->info.drawDirection;
            reply->minByte1 = pFont->info.firstRow;
            reply->maxByte1 = pFont->info.lastRow;
            reply->allCharsExist = pFont->info.allExist;
            reply->fontAscent = pFont->info.fontAscent;
            reply->fontDescent = pFont->info.fontDescent;
            reply->nCharInfos = nCharInfos;
            reply->nUniqCharInfos = nUniqCharInfos;
            reply->shmid = shmid;
            reply->shmsegoffset = 0;
            if (client->swapped) {
                swaps(&reply->sequenceNumber);
                swapl(&reply->length);
                swapCharInfo(&reply->minBounds);
                swapCharInfo(&reply->maxBounds);
                swaps(&reply->minCharOrByte2);
                swaps(&reply->maxCharOrByte2);
                swaps(&reply->defaultChar);
                swaps(&reply->nFontProps);
                swaps(&reply->fontAscent);
                swaps(&reply->fontDescent);
                swapl(&reply->nCharInfos);
                swapl(&reply->nUniqCharInfos);
                swapl(&reply->shmid);
                swapl(&reply->shmsegoffset);
            }
            p = (char *) &reply[1];
            {
                FontPropPtr pFP;
                xFontProp *prFP;
                int i;
    
                for (i = 0, pFP = pFont->info.props, prFP = (xFontProp *) p;
                     i < nfontprops; i++, pFP++, prFP++) {
                    prFP->name = pFP->name;
                    prFP->value = pFP->value;
                    if (client->swapped) {
                        swapl(&prFP->name);
                        swapl(&prFP->value);
                    }
                }
                p = (char *) prFP;
            }
            if (nCharInfos > 0 && shmid == -1) {
                xCharInfo *pci;
                CARD16 *ps;
                int i, j;
    
                pci = (xCharInfo *) p;
                for (i = 0; i < nUniqCharInfos; i++, pci++) {
                    *pci = pCI[pUniqIndex2Index[i]];
                    if (client->swapped)
                        swapCharInfo(pci);
                }
                ps = (CARD16 *) pci;
                for (j = 0; j < nCharInfos; j++, ps++) {
                    *ps = pIndex2UniqIndex[j];
                    if (client->swapped) {
                        swaps(ps);
                    }
                }
            }
            WriteToClient(client, rlength, reply);
            free(reply);
            if (nCharInfos > 0) {
                if (shmid == -1)
                    free(pIndex2UniqIndex);
                if (!pDesc)
                    free(pCI);
            }
            return Success;
        }
    }
    
    static int
    ProcXF86BigfontDispatch(ClientPtr client)
    {
        REQUEST(xReq);
    
        switch (stuff->data) {
        case X_XF86BigfontQueryVersion:
            return ProcXF86BigfontQueryVersion(client);
        case X_XF86BigfontQueryFont:
            return ProcXF86BigfontQueryFont(client);
        default:
            return BadRequest;
        }
    }
    
    static int _X_COLD
    SProcXF86BigfontQueryVersion(ClientPtr client)
    {
        REQUEST(xXF86BigfontQueryVersionReq);
    
        swaps(&stuff->length);
        return ProcXF86BigfontQueryVersion(client);
    }
    
    static int _X_COLD
    SProcXF86BigfontQueryFont(ClientPtr client)
    {
        REQUEST(xXF86BigfontQueryFontReq);
    
        swaps(&stuff->length);
        REQUEST_SIZE_MATCH(xXF86BigfontQueryFontReq);
        swapl(&stuff->id);
        return ProcXF86BigfontQueryFont(client);
    }
    
    static int _X_COLD
    SProcXF86BigfontDispatch(ClientPtr client)
    {
        REQUEST(xReq);
    
        switch (stuff->data) {
        case X_XF86BigfontQueryVersion:
            return SProcXF86BigfontQueryVersion(client);
        case X_XF86BigfontQueryFont:
            return SProcXF86BigfontQueryFont(client);
        default:
            return BadRequest;
        }
    }
    
    void
    XFree86BigfontExtensionInit(void)
    {
        if (AddExtension(XF86BIGFONTNAME,
                         XF86BigfontNumberEvents,
                         XF86BigfontNumberErrors,
                         ProcXF86BigfontDispatch,
                         SProcXF86BigfontDispatch,
                         XF86BigfontResetProc, StandardMinorOpcode)) {
    #ifdef HAS_SHM
    #ifdef MUST_CHECK_FOR_SHM_SYSCALL
            /*
             * Note: Local-clients will not be optimized without shared memory
             * support. Remote-client optimization does not depend on shared
             * memory support.  Thus, the extension is still registered even
             * when shared memory support is not functional.
             */
            if (!CheckForShmSyscall()) {
                ErrorF(XF86BIGFONTNAME
                       " extension local-client optimization disabled due to lack of shared memory support in the kernel\n");
                return;
            }
    #endif
    
            srand((unsigned int) time(NULL));
            signature = ((unsigned int) (65536.0 / (RAND_MAX + 1.0) * rand()) << 16)
                + (unsigned int) (65536.0 / (RAND_MAX + 1.0) * rand());
            /* fprintf(stderr, "signature = 0x%08X\n", signature); */
    
            FontShmdescIndex = xfont2_allocate_font_private_index();
    
    #if !defined(CSRG_BASED) && !defined(__CYGWIN__)
            pagesize = SHMLBA;
    #else
    #ifdef _SC_PAGESIZE
            pagesize = sysconf(_SC_PAGESIZE);
    #else
            pagesize = getpagesize();
    #endif
    #endif
    #endif
        }
    }