xserver

xserver with xephyr scale patch
git clone https://git.neptards.moe/u3shit/xserver.git
Log | Files | Refs | README | LICENSE

xf86bigfont.c (23161B)


      1 /*
      2  * BIGFONT extension for sharing font metrics between clients (if possible)
      3  * and for transmitting font metrics to clients in a compressed form.
      4  *
      5  * Copyright (c) 1999-2000  Bruno Haible
      6  * Copyright (c) 1999-2000  The XFree86 Project, Inc.
      7  */
      8 
      9 /* THIS IS NOT AN X CONSORTIUM STANDARD */
     10 
     11 /*
     12  * Big fonts suffer from the following: All clients that have opened a
     13  * font can access the complete glyph metrics array (the XFontStruct member
     14  * `per_char') directly, without going through a macro. Moreover these
     15  * glyph metrics are ink metrics, i.e. are not redundant even for a
     16  * fixed-width font. For a Unicode font, the size of this array is 768 KB.
     17  *
     18  * Problems: 1. It eats a lot of memory in each client. 2. All this glyph
     19  * metrics data is piped through the socket when the font is opened.
     20  *
     21  * This extension addresses these two problems for local clients, by using
     22  * shared memory. It also addresses the second problem for non-local clients,
     23  * by compressing the data before transmit by a factor of nearly 6.
     24  *
     25  * If you use this extension, your OS ought to nicely support shared memory.
     26  * This means: Shared memory should be swappable to the swap, and the limits
     27  * should be high enough (SHMMNI at least 64, SHMMAX at least 768 KB,
     28  * SHMALL at least 48 MB). It is a plus if your OS allows shmat() calls
     29  * on segments that have already been marked "removed", because it permits
     30  * these segments to be cleaned up by the OS if the X server is killed with
     31  * signal SIGKILL.
     32  *
     33  * This extension is transparently exploited by Xlib (functions XQueryFont,
     34  * XLoadQueryFont).
     35  */
     36 
     37 #ifdef HAVE_DIX_CONFIG_H
     38 #include <dix-config.h>
     39 #endif
     40 
     41 #include <sys/types.h>
     42 #ifdef HAS_SHM
     43 #ifdef SVR4
     44 #include <sys/sysmacros.h>
     45 #endif
     46 #if defined(__CYGWIN__)
     47 #include <sys/param.h>
     48 #include <sys/sysmacros.h>
     49 #endif
     50 #include <sys/ipc.h>
     51 #include <sys/shm.h>
     52 #include <sys/stat.h>
     53 #include <stdlib.h>
     54 #include <unistd.h>
     55 #include <time.h>
     56 #include <errno.h>
     57 #endif
     58 
     59 #include <X11/X.h>
     60 #include <X11/Xproto.h>
     61 #include "misc.h"
     62 #include "os.h"
     63 #include "dixstruct.h"
     64 #include "gcstruct.h"
     65 #include "dixfontstr.h"
     66 #include "extnsionst.h"
     67 #include "extinit.h"
     68 #include "protocol-versions.h"
     69 
     70 #include <X11/extensions/xf86bigfproto.h>
     71 #include "xf86bigfontsrv.h"
     72 
     73 static void XF86BigfontResetProc(ExtensionEntry *       /* extEntry */
     74     );
     75 
     76 #ifdef HAS_SHM
     77 
     78 /* A random signature, transmitted to the clients so they can verify that the
     79    shared memory segment they are attaching to was really established by the
     80    X server they are talking to. */
     81 static CARD32 signature;
     82 
     83 /* Index for additional information stored in a FontRec's devPrivates array. */
     84 static int FontShmdescIndex;
     85 
     86 static unsigned int pagesize;
     87 
     88 static Bool badSysCall = FALSE;
     89 
     90 #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__CYGWIN__) || defined(__DragonFly__)
     91 
     92 static void
     93 SigSysHandler(int signo)
     94 {
     95     badSysCall = TRUE;
     96 }
     97 
     98 static Bool
     99 CheckForShmSyscall(void)
    100 {
    101     void (*oldHandler) (int);
    102     int shmid = -1;
    103 
    104     /* If no SHM support in the kernel, the bad syscall will generate SIGSYS */
    105     oldHandler = OsSignal(SIGSYS, SigSysHandler);
    106 
    107     badSysCall = FALSE;
    108     shmid = shmget(IPC_PRIVATE, 4096, IPC_CREAT);
    109     if (shmid != -1) {
    110         /* Successful allocation - clean up */
    111         shmctl(shmid, IPC_RMID, NULL);
    112     }
    113     else {
    114         /* Allocation failed */
    115         badSysCall = TRUE;
    116     }
    117     OsSignal(SIGSYS, oldHandler);
    118     return !badSysCall;
    119 }
    120 
    121 #define MUST_CHECK_FOR_SHM_SYSCALL
    122 
    123 #endif
    124 
    125 #endif
    126 
    127 /* ========== Management of shared memory segments ========== */
    128 
    129 #ifdef HAS_SHM
    130 
    131 #ifdef __linux__
    132 /* On Linux, shared memory marked as "removed" can still be attached.
    133    Nice feature, because the kernel will automatically free the associated
    134    storage when the server and all clients are gone. */
    135 #define EARLY_REMOVE
    136 #endif
    137 
    138 typedef struct _ShmDesc {
    139     struct _ShmDesc *next;
    140     struct _ShmDesc **prev;
    141     int shmid;
    142     char *attach_addr;
    143 } ShmDescRec, *ShmDescPtr;
    144 
    145 static ShmDescPtr ShmList = (ShmDescPtr) NULL;
    146 
    147 static ShmDescPtr
    148 shmalloc(unsigned int size)
    149 {
    150     ShmDescPtr pDesc;
    151     int shmid;
    152     char *addr;
    153 
    154 #ifdef MUST_CHECK_FOR_SHM_SYSCALL
    155     if (pagesize == 0)
    156         return (ShmDescPtr) NULL;
    157 #endif
    158 
    159     /* On some older Linux systems, the number of shared memory segments
    160        system-wide is 127. In Linux 2.4, it is 4095.
    161        Therefore there is a tradeoff to be made between allocating a
    162        shared memory segment on one hand, and allocating memory and piping
    163        the glyph metrics on the other hand. If the glyph metrics size is
    164        small, we prefer the traditional way. */
    165     if (size < 3500)
    166         return (ShmDescPtr) NULL;
    167 
    168     pDesc = malloc(sizeof(ShmDescRec));
    169     if (!pDesc)
    170         return (ShmDescPtr) NULL;
    171 
    172     size = (size + pagesize - 1) & -pagesize;
    173     shmid = shmget(IPC_PRIVATE, size, S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH);
    174     if (shmid == -1) {
    175         ErrorF(XF86BIGFONTNAME " extension: shmget() failed, size = %u, %s\n",
    176                size, strerror(errno));
    177         free(pDesc);
    178         return (ShmDescPtr) NULL;
    179     }
    180 
    181     if ((addr = shmat(shmid, 0, 0)) == (char *) -1) {
    182         ErrorF(XF86BIGFONTNAME " extension: shmat() failed, size = %u, %s\n",
    183                size, strerror(errno));
    184         shmctl(shmid, IPC_RMID, (void *) 0);
    185         free(pDesc);
    186         return (ShmDescPtr) NULL;
    187     }
    188 
    189 #ifdef EARLY_REMOVE
    190     shmctl(shmid, IPC_RMID, (void *) 0);
    191 #endif
    192 
    193     pDesc->shmid = shmid;
    194     pDesc->attach_addr = addr;
    195     if (ShmList)
    196         ShmList->prev = &pDesc->next;
    197     pDesc->next = ShmList;
    198     pDesc->prev = &ShmList;
    199     ShmList = pDesc;
    200 
    201     return pDesc;
    202 }
    203 
    204 static void
    205 shmdealloc(ShmDescPtr pDesc)
    206 {
    207 #ifndef EARLY_REMOVE
    208     shmctl(pDesc->shmid, IPC_RMID, (void *) 0);
    209 #endif
    210     shmdt(pDesc->attach_addr);
    211 
    212     if (pDesc->next)
    213         pDesc->next->prev = pDesc->prev;
    214     *pDesc->prev = pDesc->next;
    215     free(pDesc);
    216 }
    217 
    218 #endif
    219 
    220 /* Called when a font is closed. */
    221 void
    222 XF86BigfontFreeFontShm(FontPtr pFont)
    223 {
    224 #ifdef HAS_SHM
    225     ShmDescPtr pDesc;
    226 
    227     /* If during shutdown of the server, XF86BigfontCleanup() has already
    228      * called shmdealloc() for all segments, we don't need to do it here.
    229      */
    230     if (!ShmList)
    231         return;
    232 
    233     pDesc = (ShmDescPtr) FontGetPrivate(pFont, FontShmdescIndex);
    234     if (pDesc)
    235         shmdealloc(pDesc);
    236 #endif
    237 }
    238 
    239 /* Called upon fatal signal. */
    240 void
    241 XF86BigfontCleanup(void)
    242 {
    243 #ifdef HAS_SHM
    244     while (ShmList)
    245         shmdealloc(ShmList);
    246 #endif
    247 }
    248 
    249 /* Called when a server generation dies. */
    250 static void
    251 XF86BigfontResetProc(ExtensionEntry * extEntry)
    252 {
    253     /* This function is normally called from CloseDownExtensions(), called
    254      * from main(). It will be followed by a call to FreeAllResources(),
    255      * which will call XF86BigfontFreeFontShm() for each font. Thus it
    256      * appears that we do not need to do anything in this function. --
    257      * But I prefer to write robust code, and not keep shared memory lying
    258      * around when it's not needed any more. (Someone might close down the
    259      * extension without calling FreeAllResources()...)
    260      */
    261     XF86BigfontCleanup();
    262 }
    263 
    264 /* ========== Handling of extension specific requests ========== */
    265 
    266 static int
    267 ProcXF86BigfontQueryVersion(ClientPtr client)
    268 {
    269     xXF86BigfontQueryVersionReply reply;
    270 
    271     REQUEST_SIZE_MATCH(xXF86BigfontQueryVersionReq);
    272     reply = (xXF86BigfontQueryVersionReply) {
    273         .type = X_Reply,
    274         .sequenceNumber = client->sequence,
    275         .length = 0,
    276         .majorVersion = SERVER_XF86BIGFONT_MAJOR_VERSION,
    277         .minorVersion = SERVER_XF86BIGFONT_MINOR_VERSION,
    278         .uid = geteuid(),
    279         .gid = getegid(),
    280 #ifdef HAS_SHM
    281         .signature = signature,
    282         .capabilities = (client->local && !client->swapped)
    283                          ? XF86Bigfont_CAP_LocalShm : 0
    284 #else
    285         .signature = 0,
    286         .capabilities = 0
    287 #endif
    288     };
    289     if (client->swapped) {
    290         swaps(&reply.sequenceNumber);
    291         swapl(&reply.length);
    292         swaps(&reply.majorVersion);
    293         swaps(&reply.minorVersion);
    294         swapl(&reply.uid);
    295         swapl(&reply.gid);
    296         swapl(&reply.signature);
    297     }
    298     WriteToClient(client, sizeof(xXF86BigfontQueryVersionReply), &reply);
    299     return Success;
    300 }
    301 
    302 static void
    303 swapCharInfo(xCharInfo * pCI)
    304 {
    305     swaps(&pCI->leftSideBearing);
    306     swaps(&pCI->rightSideBearing);
    307     swaps(&pCI->characterWidth);
    308     swaps(&pCI->ascent);
    309     swaps(&pCI->descent);
    310     swaps(&pCI->attributes);
    311 }
    312 
    313 /* static CARD32 hashCI (xCharInfo *p); */
    314 #define hashCI(p) \
    315 	(CARD32)(((p->leftSideBearing << 27) + (p->leftSideBearing >> 5) + \
    316 	          (p->rightSideBearing << 23) + (p->rightSideBearing >> 9) + \
    317 	          (p->characterWidth << 16) + \
    318 	          (p->ascent << 11) + (p->descent << 6)) ^ p->attributes)
    319 
    320 static int
    321 ProcXF86BigfontQueryFont(ClientPtr client)
    322 {
    323     FontPtr pFont;
    324 
    325     REQUEST(xXF86BigfontQueryFontReq);
    326     CARD32 stuff_flags;
    327     xCharInfo *pmax;
    328     xCharInfo *pmin;
    329     int nCharInfos;
    330     int shmid;
    331 
    332 #ifdef HAS_SHM
    333     ShmDescPtr pDesc = NULL;
    334 #else
    335 #define pDesc 0
    336 #endif
    337     xCharInfo *pCI;
    338     CARD16 *pIndex2UniqIndex;
    339     CARD16 *pUniqIndex2Index;
    340     CARD32 nUniqCharInfos;
    341 
    342 #if 0
    343     REQUEST_SIZE_MATCH(xXF86BigfontQueryFontReq);
    344 #else
    345     switch (client->req_len) {
    346     case 2:                    /* client with version 1.0 libX11 */
    347         stuff_flags = (client->local &&
    348                        !client->swapped ? XF86Bigfont_FLAGS_Shm : 0);
    349         break;
    350     case 3:                    /* client with version 1.1 libX11 */
    351         stuff_flags = stuff->flags;
    352         break;
    353     default:
    354         return BadLength;
    355     }
    356 #endif
    357     if (dixLookupFontable(&pFont, stuff->id, client, DixGetAttrAccess) !=
    358         Success)
    359         return BadFont;         /* procotol spec says only error is BadFont */
    360 
    361     pmax = FONTINKMAX(pFont);
    362     pmin = FONTINKMIN(pFont);
    363     nCharInfos =
    364         (pmax->rightSideBearing == pmin->rightSideBearing
    365          && pmax->leftSideBearing == pmin->leftSideBearing
    366          && pmax->descent == pmin->descent
    367          && pmax->ascent == pmin->ascent
    368          && pmax->characterWidth == pmin->characterWidth)
    369         ? 0 : N2dChars(pFont);
    370     shmid = -1;
    371     pCI = NULL;
    372     pIndex2UniqIndex = NULL;
    373     pUniqIndex2Index = NULL;
    374     nUniqCharInfos = 0;
    375 
    376     if (nCharInfos > 0) {
    377 #ifdef HAS_SHM
    378         if (!badSysCall)
    379             pDesc = (ShmDescPtr) FontGetPrivate(pFont, FontShmdescIndex);
    380         if (pDesc) {
    381             pCI = (xCharInfo *) pDesc->attach_addr;
    382             if (stuff_flags & XF86Bigfont_FLAGS_Shm)
    383                 shmid = pDesc->shmid;
    384         }
    385         else {
    386             if (stuff_flags & XF86Bigfont_FLAGS_Shm && !badSysCall)
    387                 pDesc = shmalloc(nCharInfos * sizeof(xCharInfo)
    388                                  + sizeof(CARD32));
    389             if (pDesc) {
    390                 pCI = (xCharInfo *) pDesc->attach_addr;
    391                 shmid = pDesc->shmid;
    392             }
    393             else {
    394 #endif
    395                 pCI = xallocarray(nCharInfos, sizeof(xCharInfo));
    396                 if (!pCI)
    397                     return BadAlloc;
    398 #ifdef HAS_SHM
    399             }
    400 #endif
    401             /* Fill nCharInfos starting at pCI. */
    402             {
    403                 xCharInfo *prCI = pCI;
    404                 int ninfos = 0;
    405                 int ncols = pFont->info.lastCol - pFont->info.firstCol + 1;
    406                 int row;
    407 
    408                 for (row = pFont->info.firstRow;
    409                      row <= pFont->info.lastRow && ninfos < nCharInfos; row++) {
    410                     unsigned char chars[512];
    411                     xCharInfo *tmpCharInfos[256];
    412                     unsigned long count;
    413                     int col;
    414                     unsigned long i;
    415 
    416                     i = 0;
    417                     for (col = pFont->info.firstCol;
    418                          col <= pFont->info.lastCol; col++) {
    419                         chars[i++] = row;
    420                         chars[i++] = col;
    421                     }
    422                     (*pFont->get_metrics) (pFont, ncols, chars, TwoD16Bit,
    423                                            &count, tmpCharInfos);
    424                     for (i = 0; i < count && ninfos < nCharInfos; i++) {
    425                         *prCI++ = *tmpCharInfos[i];
    426                         ninfos++;
    427                     }
    428                 }
    429             }
    430 #ifdef HAS_SHM
    431             if (pDesc && !badSysCall) {
    432                 *(CARD32 *) (pCI + nCharInfos) = signature;
    433                 if (!xfont2_font_set_private(pFont, FontShmdescIndex, pDesc)) {
    434                     shmdealloc(pDesc);
    435                     return BadAlloc;
    436                 }
    437             }
    438         }
    439 #endif
    440         if (shmid == -1) {
    441             /* Cannot use shared memory, so remove-duplicates the xCharInfos
    442                using a temporary hash table. */
    443             /* Note that CARD16 is suitable as index type, because
    444                nCharInfos <= 0x10000. */
    445             CARD32 hashModulus;
    446             CARD16 *pHash2UniqIndex;
    447             CARD16 *pUniqIndex2NextUniqIndex;
    448             CARD32 NextIndex;
    449             CARD32 NextUniqIndex;
    450             CARD16 *tmp;
    451             CARD32 i, j;
    452 
    453             hashModulus = 67;
    454             if (hashModulus > nCharInfos + 1)
    455                 hashModulus = nCharInfos + 1;
    456 
    457             tmp = xallocarray(4 * nCharInfos + 1, sizeof(CARD16));
    458             if (!tmp) {
    459                 if (!pDesc)
    460                     free(pCI);
    461                 return BadAlloc;
    462             }
    463             pIndex2UniqIndex = tmp;
    464             /* nCharInfos elements */
    465             pUniqIndex2Index = tmp + nCharInfos;
    466             /* max. nCharInfos elements */
    467             pUniqIndex2NextUniqIndex = tmp + 2 * nCharInfos;
    468             /* max. nCharInfos elements */
    469             pHash2UniqIndex = tmp + 3 * nCharInfos;
    470             /* hashModulus (<= nCharInfos+1) elements */
    471 
    472             /* Note that we can use 0xffff as end-of-list indicator, because
    473                even if nCharInfos = 0x10000, 0xffff can not occur as valid
    474                entry before the last element has been inserted. And once the
    475                last element has been inserted, we don't need the hash table
    476                any more. */
    477             for (j = 0; j < hashModulus; j++)
    478                 pHash2UniqIndex[j] = (CARD16) (-1);
    479 
    480             NextUniqIndex = 0;
    481             for (NextIndex = 0; NextIndex < nCharInfos; NextIndex++) {
    482                 xCharInfo *p = &pCI[NextIndex];
    483                 CARD32 hashCode = hashCI(p) % hashModulus;
    484 
    485                 for (i = pHash2UniqIndex[hashCode];
    486                      i != (CARD16) (-1); i = pUniqIndex2NextUniqIndex[i]) {
    487                     j = pUniqIndex2Index[i];
    488                     if (pCI[j].leftSideBearing == p->leftSideBearing
    489                         && pCI[j].rightSideBearing == p->rightSideBearing
    490                         && pCI[j].characterWidth == p->characterWidth
    491                         && pCI[j].ascent == p->ascent
    492                         && pCI[j].descent == p->descent
    493                         && pCI[j].attributes == p->attributes)
    494                         break;
    495                 }
    496                 if (i != (CARD16) (-1)) {
    497                     /* Found *p at Index j, UniqIndex i */
    498                     pIndex2UniqIndex[NextIndex] = i;
    499                 }
    500                 else {
    501                     /* Allocate a new entry in the Uniq table */
    502                     if (hashModulus <= 2 * NextUniqIndex
    503                         && hashModulus < nCharInfos + 1) {
    504                         /* Time to increate hash table size */
    505                         hashModulus = 2 * hashModulus + 1;
    506                         if (hashModulus > nCharInfos + 1)
    507                             hashModulus = nCharInfos + 1;
    508                         for (j = 0; j < hashModulus; j++)
    509                             pHash2UniqIndex[j] = (CARD16) (-1);
    510                         for (i = 0; i < NextUniqIndex; i++)
    511                             pUniqIndex2NextUniqIndex[i] = (CARD16) (-1);
    512                         for (i = 0; i < NextUniqIndex; i++) {
    513                             j = pUniqIndex2Index[i];
    514                             p = &pCI[j];
    515                             hashCode = hashCI(p) % hashModulus;
    516                             pUniqIndex2NextUniqIndex[i] =
    517                                 pHash2UniqIndex[hashCode];
    518                             pHash2UniqIndex[hashCode] = i;
    519                         }
    520                         p = &pCI[NextIndex];
    521                         hashCode = hashCI(p) % hashModulus;
    522                     }
    523                     i = NextUniqIndex++;
    524                     pUniqIndex2NextUniqIndex[i] = pHash2UniqIndex[hashCode];
    525                     pHash2UniqIndex[hashCode] = i;
    526                     pUniqIndex2Index[i] = NextIndex;
    527                     pIndex2UniqIndex[NextIndex] = i;
    528                 }
    529             }
    530             nUniqCharInfos = NextUniqIndex;
    531             /* fprintf(stderr, "font metrics: nCharInfos = %d, nUniqCharInfos = %d, hashModulus = %d\n", nCharInfos, nUniqCharInfos, hashModulus); */
    532         }
    533     }
    534 
    535     {
    536         int nfontprops = pFont->info.nprops;
    537         int rlength = sizeof(xXF86BigfontQueryFontReply)
    538             + nfontprops * sizeof(xFontProp)
    539             + (nCharInfos > 0 && shmid == -1
    540                ? nUniqCharInfos * sizeof(xCharInfo)
    541                + (nCharInfos + 1) / 2 * 2 * sizeof(CARD16)
    542                : 0);
    543         xXF86BigfontQueryFontReply *reply = calloc(1, rlength);
    544         char *p;
    545 
    546         if (!reply) {
    547             if (nCharInfos > 0) {
    548                 if (shmid == -1)
    549                     free(pIndex2UniqIndex);
    550                 if (!pDesc)
    551                     free(pCI);
    552             }
    553             return BadAlloc;
    554         }
    555         reply->type = X_Reply;
    556         reply->length = bytes_to_int32(rlength - sizeof(xGenericReply));
    557         reply->sequenceNumber = client->sequence;
    558         reply->minBounds = pFont->info.ink_minbounds;
    559         reply->maxBounds = pFont->info.ink_maxbounds;
    560         reply->minCharOrByte2 = pFont->info.firstCol;
    561         reply->maxCharOrByte2 = pFont->info.lastCol;
    562         reply->defaultChar = pFont->info.defaultCh;
    563         reply->nFontProps = pFont->info.nprops;
    564         reply->drawDirection = pFont->info.drawDirection;
    565         reply->minByte1 = pFont->info.firstRow;
    566         reply->maxByte1 = pFont->info.lastRow;
    567         reply->allCharsExist = pFont->info.allExist;
    568         reply->fontAscent = pFont->info.fontAscent;
    569         reply->fontDescent = pFont->info.fontDescent;
    570         reply->nCharInfos = nCharInfos;
    571         reply->nUniqCharInfos = nUniqCharInfos;
    572         reply->shmid = shmid;
    573         reply->shmsegoffset = 0;
    574         if (client->swapped) {
    575             swaps(&reply->sequenceNumber);
    576             swapl(&reply->length);
    577             swapCharInfo(&reply->minBounds);
    578             swapCharInfo(&reply->maxBounds);
    579             swaps(&reply->minCharOrByte2);
    580             swaps(&reply->maxCharOrByte2);
    581             swaps(&reply->defaultChar);
    582             swaps(&reply->nFontProps);
    583             swaps(&reply->fontAscent);
    584             swaps(&reply->fontDescent);
    585             swapl(&reply->nCharInfos);
    586             swapl(&reply->nUniqCharInfos);
    587             swapl(&reply->shmid);
    588             swapl(&reply->shmsegoffset);
    589         }
    590         p = (char *) &reply[1];
    591         {
    592             FontPropPtr pFP;
    593             xFontProp *prFP;
    594             int i;
    595 
    596             for (i = 0, pFP = pFont->info.props, prFP = (xFontProp *) p;
    597                  i < nfontprops; i++, pFP++, prFP++) {
    598                 prFP->name = pFP->name;
    599                 prFP->value = pFP->value;
    600                 if (client->swapped) {
    601                     swapl(&prFP->name);
    602                     swapl(&prFP->value);
    603                 }
    604             }
    605             p = (char *) prFP;
    606         }
    607         if (nCharInfos > 0 && shmid == -1) {
    608             xCharInfo *pci;
    609             CARD16 *ps;
    610             int i, j;
    611 
    612             pci = (xCharInfo *) p;
    613             for (i = 0; i < nUniqCharInfos; i++, pci++) {
    614                 *pci = pCI[pUniqIndex2Index[i]];
    615                 if (client->swapped)
    616                     swapCharInfo(pci);
    617             }
    618             ps = (CARD16 *) pci;
    619             for (j = 0; j < nCharInfos; j++, ps++) {
    620                 *ps = pIndex2UniqIndex[j];
    621                 if (client->swapped) {
    622                     swaps(ps);
    623                 }
    624             }
    625         }
    626         WriteToClient(client, rlength, reply);
    627         free(reply);
    628         if (nCharInfos > 0) {
    629             if (shmid == -1)
    630                 free(pIndex2UniqIndex);
    631             if (!pDesc)
    632                 free(pCI);
    633         }
    634         return Success;
    635     }
    636 }
    637 
    638 static int
    639 ProcXF86BigfontDispatch(ClientPtr client)
    640 {
    641     REQUEST(xReq);
    642 
    643     switch (stuff->data) {
    644     case X_XF86BigfontQueryVersion:
    645         return ProcXF86BigfontQueryVersion(client);
    646     case X_XF86BigfontQueryFont:
    647         return ProcXF86BigfontQueryFont(client);
    648     default:
    649         return BadRequest;
    650     }
    651 }
    652 
    653 static int _X_COLD
    654 SProcXF86BigfontQueryVersion(ClientPtr client)
    655 {
    656     REQUEST(xXF86BigfontQueryVersionReq);
    657 
    658     swaps(&stuff->length);
    659     return ProcXF86BigfontQueryVersion(client);
    660 }
    661 
    662 static int _X_COLD
    663 SProcXF86BigfontQueryFont(ClientPtr client)
    664 {
    665     REQUEST(xXF86BigfontQueryFontReq);
    666 
    667     swaps(&stuff->length);
    668     REQUEST_SIZE_MATCH(xXF86BigfontQueryFontReq);
    669     swapl(&stuff->id);
    670     return ProcXF86BigfontQueryFont(client);
    671 }
    672 
    673 static int _X_COLD
    674 SProcXF86BigfontDispatch(ClientPtr client)
    675 {
    676     REQUEST(xReq);
    677 
    678     switch (stuff->data) {
    679     case X_XF86BigfontQueryVersion:
    680         return SProcXF86BigfontQueryVersion(client);
    681     case X_XF86BigfontQueryFont:
    682         return SProcXF86BigfontQueryFont(client);
    683     default:
    684         return BadRequest;
    685     }
    686 }
    687 
    688 void
    689 XFree86BigfontExtensionInit(void)
    690 {
    691     if (AddExtension(XF86BIGFONTNAME,
    692                      XF86BigfontNumberEvents,
    693                      XF86BigfontNumberErrors,
    694                      ProcXF86BigfontDispatch,
    695                      SProcXF86BigfontDispatch,
    696                      XF86BigfontResetProc, StandardMinorOpcode)) {
    697 #ifdef HAS_SHM
    698 #ifdef MUST_CHECK_FOR_SHM_SYSCALL
    699         /*
    700          * Note: Local-clients will not be optimized without shared memory
    701          * support. Remote-client optimization does not depend on shared
    702          * memory support.  Thus, the extension is still registered even
    703          * when shared memory support is not functional.
    704          */
    705         if (!CheckForShmSyscall()) {
    706             ErrorF(XF86BIGFONTNAME
    707                    " extension local-client optimization disabled due to lack of shared memory support in the kernel\n");
    708             return;
    709         }
    710 #endif
    711 
    712         srand((unsigned int) time(NULL));
    713         signature = ((unsigned int) (65536.0 / (RAND_MAX + 1.0) * rand()) << 16)
    714             + (unsigned int) (65536.0 / (RAND_MAX + 1.0) * rand());
    715         /* fprintf(stderr, "signature = 0x%08X\n", signature); */
    716 
    717         FontShmdescIndex = xfont2_allocate_font_private_index();
    718 
    719 #if !defined(CSRG_BASED) && !defined(__CYGWIN__)
    720         pagesize = SHMLBA;
    721 #else
    722 #ifdef _SC_PAGESIZE
    723         pagesize = sysconf(_SC_PAGESIZE);
    724 #else
    725         pagesize = getpagesize();
    726 #endif
    727 #endif
    728 #endif
    729     }
    730 }