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
SigSysHandler(int signo)93 SigSysHandler(int signo)
94 {
95     badSysCall = TRUE;
96 }
97 
98 static Bool
CheckForShmSyscall(void)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
shmalloc(unsigned int size)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
shmdealloc(ShmDescPtr pDesc)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
XF86BigfontFreeFontShm(FontPtr pFont)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
XF86BigfontCleanup(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
XF86BigfontResetProc(ExtensionEntry * extEntry)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
ProcXF86BigfontQueryVersion(ClientPtr client)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
swapCharInfo(xCharInfo * pCI)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
ProcXF86BigfontQueryFont(ClientPtr client)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
ProcXF86BigfontDispatch(ClientPtr client)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
SProcXF86BigfontQueryVersion(ClientPtr client)654 SProcXF86BigfontQueryVersion(ClientPtr client)
655 {
656     REQUEST(xXF86BigfontQueryVersionReq);
657 
658     swaps(&stuff->length);
659     return ProcXF86BigfontQueryVersion(client);
660 }
661 
662 static int _X_COLD
SProcXF86BigfontQueryFont(ClientPtr client)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
SProcXF86BigfontDispatch(ClientPtr client)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
XFree86BigfontExtensionInit(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 }
731