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