Bug Summary

File:fc/fserve.c
Location:line 2632, column 26
Description:Access to field 'length' results in a dereference of a null pointer (loaded from variable 'rep')

Annotated Source Code

1/*
2
3Copyright 1990, 1998 The Open Group
4
5Permission to use, copy, modify, distribute, and sell this software and its
6documentation for any purpose is hereby granted without fee, provided that
7the above copyright notice appear in all copies and that both that
8copyright notice and this permission notice appear in supporting
9documentation.
10
11The above copyright notice and this permission notice shall be included in
12all copies or substantial portions of the Software.
13
14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
21Except as contained in this notice, the name of The Open Group shall not be
22used in advertising or otherwise to promote the sale, use or other dealings
23in this Software without prior written authorization from The Open Group.
24
25*/
26
27/*
28 * Copyright 1990 Network Computing Devices
29 *
30 * Permission to use, copy, modify, distribute, and sell this software and
31 * its documentation for any purpose is hereby granted without fee, provided
32 * that the above copyright notice appear in all copies and that both that
33 * copyright notice and this permission notice appear in supporting
34 * documentation, and that the names of Network Computing Devices, or Digital
35 * not be used in advertising or publicity pertaining to distribution
36 * of the software without specific, written prior permission.
37 *
38 * NETWORK COMPUTING DEVICES, AND DIGITAL AND DISCLAIM ALL WARRANTIES WITH
39 * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
40 * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL NETWORK COMPUTING DEVICES,
41 * OR DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
42 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
43 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
44 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
45 * THIS SOFTWARE.
46 *
47 * Author: Dave Lemke, Network Computing Devices, Inc
48 */
49/*
50 * font server specific font access
51 */
52
53#ifdef HAVE_CONFIG_H1
54#include <config.h>
55#endif
56#include "libxfontint.h"
57
58#ifdef WIN32
59#define _WILLWINSOCK_
60#endif
61#define FONT_t
62#define TRANS_CLIENT
63#include "X11/Xtrans/Xtrans.h"
64#include "X11/Xpoll.h"
65#include <X11/fonts/FS.h>
66#include <X11/fonts/FSproto.h>
67#include <X11/X.h>
68#include <X11/Xos.h>
69#include <X11/fonts/fontmisc.h>
70#include <X11/fonts/fontstruct.h>
71#include "fservestr.h"
72#include <X11/fonts/fontutil.h>
73#include <errno(*__error()).h>
74#include <limits.h>
75
76#include <time.h>
77#define Time_ttime_t time_t
78
79#ifdef NCD
80#include <ncd/nvram.h>
81#endif
82
83#include <stddef.h>
84
85#ifndef MIN
86#define MIN(a,b)(((a)<(b))?(a):(b)) ((a)<(b)?(a):(b))
87#endif
88#define TimeCmp(a,c,b)((int) ((a) - (b)) c 0) ((int) ((a) - (b)) c 0)
89
90#define NONZEROMETRICS(pci)((pci)->leftSideBearing || (pci)->rightSideBearing || (
pci)->ascent || (pci)->descent || (pci)->characterWidth
)
((pci)->leftSideBearing || \
91 (pci)->rightSideBearing || \
92 (pci)->ascent || \
93 (pci)->descent || \
94 (pci)->characterWidth)
95
96/*
97 * SIZEOF(r) is in bytes, length fields in the protocol are in 32-bit words,
98 * so this converts for doing size comparisons.
99 */
100#define LENGTHOF(r)(sz_r >> 2) (SIZEOF(r)sz_r >> 2)
101
102/* Somewhat arbitrary limit on maximum reply size we'll try to read. */
103#define MAX_REPLY_LENGTH((64 * 1024 * 1024) >> 2) ((64 * 1024 * 1024) >> 2)
104
105static int fs_read_glyphs ( FontPathElementPtr fpe, FSBlockDataPtr blockrec );
106static int fs_read_list ( FontPathElementPtr fpe, FSBlockDataPtr blockrec );
107static int fs_read_list_info ( FontPathElementPtr fpe,
108 FSBlockDataPtr blockrec );
109
110static void fs_block_handler ( void *wt );
111
112static int fs_wakeup ( FontPathElementPtr fpe );
113
114/*
115 * List of all FPEs
116 */
117static FSFpePtr fs_fpes;
118/*
119 * Union of all FPE blockStates
120 */
121static CARD32 fs_blockState;
122
123static int _fs_restart_connection ( FSFpePtr conn );
124static void fs_send_query_bitmaps ( FontPathElementPtr fpe,
125 FSBlockDataPtr blockrec );
126static int fs_send_close_font ( FontPathElementPtr fpe, Font id );
127static void fs_client_died ( pointer client, FontPathElementPtr fpe );
128static void _fs_client_access ( FSFpePtr conn, pointer client, Bool sync );
129static void _fs_client_resolution ( FSFpePtr conn );
130static fsGenericReply *fs_get_reply (FSFpePtr conn, int *error);
131static int fs_await_reply (FSFpePtr conn);
132static void _fs_do_blocked (FSFpePtr conn);
133static void fs_cleanup_bfont (FSBlockedFontPtr bfont);
134
135char _fs_glyph_undefined;
136char _fs_glyph_requested;
137static char _fs_glyph_zero_length;
138
139static int generationCount;
140
141static int FontServerRequestTimeout = 30 * 1000;
142
143static void
144_fs_close_server (FSFpePtr conn);
145
146static FSFpePtr
147_fs_init_conn (const char *servername, FontPathElementPtr fpe);
148
149static int
150_fs_wait_connect (FSFpePtr conn);
151
152static int
153_fs_send_init_packets (FSFpePtr conn);
154
155static void
156_fs_check_reconnect (FSFpePtr conn);
157
158static void
159_fs_start_reconnect (FSFpePtr conn);
160
161static void
162_fs_free_conn (FSFpePtr conn);
163
164static int
165fs_free_fpe(FontPathElementPtr fpe);
166
167static void
168fs_fd_handler(int fd, void *data);
169
170/*
171 * Font server access
172 *
173 * the basic idea for the non-blocking access is to have the function
174 * called multiple times until the actual data is returned, instead
175 * of ClientBlocked.
176 *
177 * the first call to the function will cause the request to be sent to
178 * the font server, and a block record to be stored in the fpe's list
179 * of outstanding requests. the FS block handler also sticks the
180 * proper set of fd's into the select mask. when data is ready to be
181 * read in, the FS wakup handler will be hit. this will read the
182 * data off the wire into the proper block record, and then signal the
183 * client that caused the block so that it can restart. it will then
184 * call the access function again, which will realize that the data has
185 * arrived and return it.
186 */
187
188
189#ifdef DEBUG
190static void
191_fs_add_req_log(FSFpePtr conn, int opcode)((FSFpePtr conn)->current_seq++)
192{
193 conn->current_seq++;
194 fprintf (stderr__stderrp, "\t\tRequest: %5d Opcode: %2d\n",
195 conn->current_seq, opcode);
196 conn->reqbuffer[conn->reqindex].opcode = opcode;
197 conn->reqbuffer[conn->reqindex].sequence = conn->current_seq;
198 conn->reqindex++;
199 if (conn->reqindex == REQUEST_LOG_SIZE)
200 conn->reqindex = 0;
201}
202
203static void
204_fs_add_rep_log (FSFpePtr conn, fsGenericReply *rep)
205{
206 int i;
207
208 for (i = 0; i < REQUEST_LOG_SIZE; i++)
209 if (conn->reqbuffer[i].sequence == rep->sequenceNumber)
210 break;
211 if (i == REQUEST_LOG_SIZE)
212 fprintf (stderr__stderrp, "\t\t\t\t\tReply: %5d Opcode: unknown\n",
213 rep->sequenceNumber);
214 else
215 fprintf (stderr__stderrp, "\t\t\t\t\tReply: %5d Opcode: %d\n",
216 rep->sequenceNumber,
217 conn->reqbuffer[i].opcode);
218}
219
220#define _fs_reply_failed(rep, name, op) do { \
221 if (rep) { \
222 if (rep->type == FS_Error1) \
223 fprintf (stderr__stderrp, "Error: %d Request: %s\n", \
224 ((fsError *)rep)->request, #name); \
225 else \
226 fprintf (stderr__stderrp, "Bad Length for %s Reply: %d %s %d\n", \
227 #name, rep->length, op, LENGTHOF(name)(sz_name >> 2)); \
228 } \
229} while (0)
230
231#else
232#define _fs_add_req_log(conn,op)((conn)->current_seq++) ((conn)->current_seq++)
233#define _fs_add_rep_log(conn,rep)
234#define _fs_reply_failed(rep,name,op)
235#endif
236
237static Bool
238fs_name_check(const char *name)
239{
240 /* Just make sure there is a protocol/ prefix */
241 return (name && *name != '/' && strchr(name, '/'));
242}
243
244static void
245_fs_client_resolution(FSFpePtr conn)
246{
247 fsSetResolutionReq srreq;
248 int num_res;
249 FontResolutionPtr res;
250
251 res = GetClientResolutions__libxfont__GetClientResolutions(&num_res);
252
253 if (num_res) {
254 srreq.reqType = FS_SetResolution11;
255 srreq.num_resolutions = num_res;
256 srreq.length = (SIZEOF(fsSetResolutionReq)4 +
257 (num_res * SIZEOF(fsResolution)6) + 3) >> 2;
258
259 _fs_add_req_log(conn, FS_SetResolution)((conn)->current_seq++);
260 if (_fs_write(conn, (char *) &srreq, SIZEOF(fsSetResolutionReq)4) != -1)
261 (void)_fs_write_pad(conn, (char *) res,
262 (num_res * SIZEOF(fsResolution)6));
263 }
264}
265
266/*
267 * close font server and remove any state associated with
268 * this connection - this includes any client records.
269 */
270
271static void
272fs_close_conn(FSFpePtr conn)
273{
274 FSClientPtr client, nclient;
275
276 _fs_close_server (conn);
277
278 for (client = conn->clients; client; client = nclient)
279 {
280 nclient = client->next;
281 free (client);
282 }
283 conn->clients = NULL((void*)0);
284}
285
286/*
287 * the wakeup handlers have to be set when the FPE is open, and not
288 * removed until it is freed, in order to handle unexpected data, like
289 * events
290 */
291/* ARGSUSED */
292static int
293fs_init_fpe(FontPathElementPtr fpe)
294{
295 FSFpePtr conn;
296 const char *name;
297 int err;
298 int ret;
299
300 /* open font server */
301 /* create FS specific fpe info */
302 name = fpe->name;
303
304 /* hack for old style names */
305 if (*name == ':')
306 name++; /* skip ':' */
307
308 conn = _fs_init_conn (name, fpe);
309 if (!conn)
310 err = AllocError80;
311 else
312 {
313 err = init_fs_handlers2 (fpe, fs_block_handler);
314 if (err != Successful85)
315 {
316 _fs_free_conn (conn);
317 err = AllocError80;
318 }
319 else
320 {
321 fpe->private = conn;
322 conn->next = fs_fpes;
323 fs_fpes = conn;
324 ret = _fs_wait_connect (conn);
325 if (ret != FSIO_READY1)
326 {
327 fs_free_fpe (fpe);
328 err = BadFontPath86;
329 }
330 else
331 err = Successful85;
332 }
333 }
334
335 if (err == Successful85)
336 {
337#ifdef NCD
338 if (configData.ExtendedFontDiags)
339 printf("Connected to font server \"%s\"\n", name);
340#endif
341#ifdef DEBUG
342 fprintf (stderr__stderrp, "connected to FS \"%s\"\n", name);
343#endif
344 }
345 else
346 {
347#ifdef DEBUG
348 fprintf(stderr__stderrp, "failed to connect to FS \"%s\" %d\n", name, err);
349#endif
350#ifdef NCD
351 if (configData.ExtendedFontDiags)
352 printf("Failed to connect to font server \"%s\"\n", name);
353#endif
354 ;
355 }
356 return err;
357}
358
359static int
360fs_reset_fpe(FontPathElementPtr fpe)
361{
362 (void) _fs_send_init_packets((FSFpePtr) fpe->private);
363 return Successful85;
364}
365
366/*
367 * this shouldn't be called till all refs to the FPE are gone
368 */
369
370static int
371fs_free_fpe(FontPathElementPtr fpe)
372{
373 FSFpePtr conn = (FSFpePtr) fpe->private, *prev;
374
375 /* unhook from chain of all font servers */
376 for (prev = &fs_fpes; *prev; prev = &(*prev)->next)
377 {
378 if (*prev == conn)
379 {
380 *prev = conn->next;
381 break;
382 }
383 }
384 _fs_unmark_block (conn, conn->blockState);
385 fs_close_conn(conn);
386 remove_fs_handlers2(fpe, fs_block_handler, fs_fpes == 0);
387 _fs_free_conn (conn);
388 fpe->private = (pointer) 0;
389
390#ifdef NCD
391 if (configData.ExtendedFontDiags)
392 printf("Disconnected from font server \"%s\"\n", fpe->name);
393#endif
394#ifdef DEBUG
395 fprintf (stderr__stderrp, "disconnect from FS \"%s\"\n", fpe->name);
396#endif
397
398 return Successful85;
399}
400
401static FSBlockDataPtr
402fs_new_block_rec(FontPathElementPtr fpe, pointer client, int type)
403{
404 FSBlockDataPtr blockrec,
405 *prev;
406 FSFpePtr conn = (FSFpePtr) fpe->private;
407 int size;
408
409 switch (type) {
410 case FS_OPEN_FONT1:
411 size = sizeof(FSBlockedFontRec);
412 break;
413 case FS_LOAD_GLYPHS2:
414 size = sizeof(FSBlockedGlyphRec);
415 break;
416 case FS_LIST_FONTS3:
417 size = sizeof(FSBlockedListRec);
418 break;
419 case FS_LIST_WITH_INFO4:
420 size = sizeof(FSBlockedListInfoRec);
421 break;
422 default:
423 size = 0;
424 break;
425 }
426 blockrec = malloc(sizeof(FSBlockDataRec) + size);
427 if (!blockrec)
428 return (FSBlockDataPtr) 0;
429 blockrec->data = (pointer) (blockrec + 1);
430 blockrec->client = client;
431 blockrec->sequenceNumber = -1;
432 blockrec->errcode = StillWorking81;
433 blockrec->type = type;
434 blockrec->depending = 0;
435 blockrec->next = (FSBlockDataPtr) 0;
436
437 /* stick it on the end of the list (since its expected last) */
438 for (prev = &conn->blockedRequests; *prev; prev = &(*prev)->next)
439 ;
440 *prev = blockrec;
441
442 return blockrec;
443}
444
445static void
446_fs_set_pending_reply (FSFpePtr conn)
447{
448 FSBlockDataPtr blockrec;
449
450 for (blockrec = conn->blockedRequests; blockrec; blockrec = blockrec->next)
451 if (blockrec->errcode == StillWorking81)
452 break;
453 if (blockrec)
454 {
455 conn->blockedReplyTime = GetTimeInMillis__libxfont__GetTimeInMillis () + FontServerRequestTimeout;
456 _fs_mark_block (conn, FS_PENDING_REPLY0x08);
457 }
458 else
459 _fs_unmark_block (conn, FS_PENDING_REPLY0x08);
460}
461
462static void
463_fs_remove_block_rec(FSFpePtr conn, FSBlockDataPtr blockrec)
464{
465 FSBlockDataPtr *prev;
466
467 for (prev = &conn->blockedRequests; *prev; prev = &(*prev)->next)
468 if (*prev == blockrec)
469 {
470 *prev = blockrec->next;
471 break;
472 }
473 if (blockrec->type == FS_LOAD_GLYPHS2)
474 {
475 FSBlockedGlyphPtr bglyph = (FSBlockedGlyphPtr)blockrec->data;
476 if (bglyph->num_expected_ranges)
477 free(bglyph->expected_ranges);
478 }
479 free(blockrec);
480 _fs_set_pending_reply (conn);
481}
482
483static void
484_fs_signal_clients_depending(FSClientsDependingPtr *clients_depending)
485{
486 FSClientsDependingPtr p;
487
488 while ((p = *clients_depending))
489 {
490 *clients_depending = p->next;
491 ClientSignal__libxfont__ClientSignal(p->client);
492 free(p);
493 }
494}
495
496static int
497_fs_add_clients_depending(FSClientsDependingPtr *clients_depending, pointer client)
498{
499 FSClientsDependingPtr new, cd;
500
501 for (; (cd = *clients_depending);
502 clients_depending = &(*clients_depending)->next)
503 {
504 if (cd->client == client)
505 return Suspended84;
506 }
507
508 new = malloc (sizeof (FSClientsDependingRec));
509 if (!new)
510 return BadAlloc11;
511
512 new->client = client;
513 new->next = 0;
514 *clients_depending = new;
515 return Suspended84;
516}
517
518static void
519conn_start_listening(FSFpePtr conn)
520{
521 if (!conn->fs_listening) {
522 add_fs_fd__libxfont_add_fs_fd(conn->fs_fd, fs_fd_handler, conn->fpe);
523 conn->fs_listening = TRUE1;
524 }
525}
526
527static void
528conn_stop_listening(FSFpePtr conn)
529{
530 if (conn->fs_listening) {
531 remove_fs_fd__libxfont_remove_fs_fd(conn->fs_fd);
532 conn->fs_listening = FALSE0;
533 }
534}
535
536/*
537 * When a request is aborted due to a font server failure,
538 * signal any depending clients to restart their dependant
539 * requests
540 */
541static void
542_fs_clean_aborted_blockrec(FSFpePtr conn, FSBlockDataPtr blockrec)
543{
544 switch(blockrec->type) {
545 case FS_OPEN_FONT1: {
546 FSBlockedFontPtr bfont = (FSBlockedFontPtr)blockrec->data;
547
548 fs_cleanup_bfont (bfont);
549 _fs_signal_clients_depending(&bfont->clients_depending);
550 break;
551 }
552 case FS_LOAD_GLYPHS2: {
553 FSBlockedGlyphPtr bglyph = (FSBlockedGlyphPtr)blockrec->data;
554
555 _fs_clean_aborted_loadglyphs(bglyph->pfont,
556 bglyph->num_expected_ranges,
557 bglyph->expected_ranges);
558 _fs_signal_clients_depending(&bglyph->clients_depending);
559 break;
560 }
561 case FS_LIST_FONTS3:
562 break;
563 case FS_LIST_WITH_INFO4: {
564 FSBlockedListInfoPtr binfo;
565 binfo = (FSBlockedListInfoPtr) blockrec->data;
566 if (binfo->status == FS_LFWI_REPLY1)
567 conn_start_listening(conn);
568 _fs_free_props (&binfo->info);
569 }
570 default:
571 break;
572 }
573}
574
575static void
576fs_abort_blockrec(FSFpePtr conn, FSBlockDataPtr blockrec)
577{
578 _fs_clean_aborted_blockrec (conn, blockrec);
579 _fs_remove_block_rec (conn, blockrec);
580}
581
582/*
583 * Tell the font server we've failed to complete an open and
584 * then unload the partially created font
585 */
586static void
587fs_cleanup_bfont (FSBlockedFontPtr bfont)
588{
589 FSFontDataRec *fsd;
590
591 if (bfont->pfont)
592 {
593 fsd = (FSFontDataRec *) bfont->pfont->fpePrivate;
594
595 /* make sure the FS knows we choked on it */
596 fs_send_close_font(bfont->pfont->fpe, bfont->fontid);
597
598 /*
599 * Either unload the font if it's being opened for
600 * the first time, or smash the generation field to
601 * mark this font as an orphan
602 */
603 if (!(bfont->flags & FontReopen0x0020))
604 {
605 if (bfont->freeFont)
606 (*bfont->pfont->unload_font) (bfont->pfont);
607#ifdef DEBUG
608 else
609 fprintf (stderr__stderrp, "Not freeing other font in cleanup_bfont\n");
610#endif
611 bfont->pfont = 0;
612 }
613 else
614 fsd->generation = -1;
615 }
616}
617
618/*
619 * Check to see if a complete reply is waiting
620 */
621static fsGenericReply *
622fs_get_reply (FSFpePtr conn, int *error)
623{
624 char *buf;
625 fsGenericReply *rep;
626 int ret;
627
628 /* block if the connection is down or paused in lfwi */
629 if (conn->fs_fd == -1 || !conn->fs_listening)
38
Taking false branch
630 {
631 *error = FSIO_BLOCK0;
632 return 0;
633 }
634
635 ret = _fs_start_read (conn, sizeof (fsGenericReply), &buf);
636 if (ret != FSIO_READY1)
39
Assuming 'ret' is equal to 1
40
Taking false branch
637 {
638 *error = FSIO_BLOCK0;
639 return 0;
640 }
641
642 rep = (fsGenericReply *) buf;
643
644 /*
645 * Refuse to accept replies longer than a maximum reasonable length,
646 * before we pass to _fs_start_read, since it will try to resize the
647 * incoming connection buffer to this size. Also avoids integer overflow
648 * on 32-bit systems.
649 */
650 if (rep->length > MAX_REPLY_LENGTH((64 * 1024 * 1024) >> 2))
41
Taking false branch
651 {
652 ErrorF__libxfont__ErrorF("fserve: reply length %ld > MAX_REPLY_LENGTH, disconnecting"
653 " from font server\n", (long)rep->length);
654 _fs_connection_died (conn);
655 *error = FSIO_ERROR-1;
656 return 0;
657 }
658
659 ret = _fs_start_read (conn, rep->length << 2, &buf);
660 if (ret != FSIO_READY1)
42
Assuming 'ret' is equal to 1
43
Taking false branch
661 {
662 *error = FSIO_BLOCK0;
663 return 0;
664 }
665
666 *error = FSIO_READY1;
667
668 return (fsGenericReply *) buf;
669}
670
671static Bool
672fs_reply_ready (FSFpePtr conn)
673{
674 fsGenericReply *rep;
675
676 if (conn->fs_fd == -1 || !conn->fs_listening)
677 return FALSE0;
678 if (fs_data_read (conn)((conn)->inBuf.insert - (conn)->inBuf.remove) < sizeof (fsGenericReply))
679 return FALSE0;
680 rep = (fsGenericReply *) (conn->inBuf.buf + conn->inBuf.remove);
681 if (fs_data_read (conn)((conn)->inBuf.insert - (conn)->inBuf.remove) < rep->length << 2)
682 return FALSE0;
683 return TRUE1;
684}
685
686static void
687_fs_pending_reply (FSFpePtr conn)
688{
689 if (!(conn->blockState & FS_PENDING_REPLY0x08))
690 {
691 _fs_mark_block (conn, FS_PENDING_REPLY0x08);
692 conn->blockedReplyTime = GetTimeInMillis__libxfont__GetTimeInMillis () + FontServerRequestTimeout;
693 }
694}
695
696static void
697_fs_prepare_for_reply (FSFpePtr conn)
698{
699 _fs_pending_reply (conn);
700 _fs_flush (conn);
701}
702
703/*
704 * Block (for a while) awaiting a complete reply
705 */
706static int
707fs_await_reply (FSFpePtr conn)
708{
709 int ret;
710
711 if (conn->blockState & FS_COMPLETE_REPLY0x20)
712 return FSIO_READY1;
713
714 while (!fs_get_reply (conn, &ret))
715 {
716 if (ret != FSIO_BLOCK0)
717 return ret;
718 if (_fs_wait_for_readable (conn, FontServerRequestTimeout) != FSIO_READY1)
719 {
720 _fs_connection_died (conn);
721 return FSIO_ERROR-1;
722 }
723 }
724 return FSIO_READY1;
725}
726
727/*
728 * Process the reply to an OpenBitmapFont request
729 */
730static int
731fs_read_open_font(FontPathElementPtr fpe, FSBlockDataPtr blockrec)
732{
733 FSFpePtr conn = (FSFpePtr) fpe->private;
734 FSBlockedFontPtr bfont = (FSBlockedFontPtr) blockrec->data;
735 fsOpenBitmapFontReply *rep;
736 FSBlockDataPtr blockOrig;
737 FSBlockedFontPtr origBfont;
738 int ret;
739
740 rep = (fsOpenBitmapFontReply *) fs_get_reply (conn, &ret);
741 if (!rep || rep->type == FS_Error1 ||
742 (rep->length != LENGTHOF(fsOpenBitmapFontReply)(16 >> 2)))
743 {
744 if (ret == FSIO_BLOCK0)
745 return StillWorking81;
746 if (rep)
747 _fs_done_read (conn, rep->length << 2);
748 fs_cleanup_bfont (bfont);
749 _fs_reply_failed (rep, fsOpenBitmapFontReply, "!=");
750 return BadFontName83;
751 }
752
753 /* If we're not reopening a font and FS detected a duplicate font
754 open request, replace our reference to the new font with a
755 reference to an existing font (possibly one not finished
756 opening). If this is a reopen, keep the new font reference...
757 it's got the metrics and extents we read when the font was opened
758 before. This also gives us the freedom to easily close the font
759 if we we decide (in fs_read_query_info()) that we don't like what
760 we got. */
761
762 if (rep->otherid && !(bfont->flags & FontReopen0x0020))
763 {
764 fs_cleanup_bfont (bfont);
765
766 /* Find old font if we're completely done getting it from server. */
767 bfont->pfont = find_old_font__libxfont__find_old_font(rep->otherid);
768 bfont->freeFont = FALSE0;
769 bfont->fontid = rep->otherid;
770 bfont->state = FS_DONE_REPLY4;
771 /*
772 * look for a blocked request to open the same font
773 */
774 for (blockOrig = conn->blockedRequests;
775 blockOrig;
776 blockOrig = blockOrig->next)
777 {
778 if (blockOrig != blockrec && blockOrig->type == FS_OPEN_FONT1)
779 {
780 origBfont = (FSBlockedFontPtr) blockOrig->data;
781 if (origBfont->fontid == rep->otherid)
782 {
783 blockrec->depending = blockOrig->depending;
784 blockOrig->depending = blockrec;
785 bfont->state = FS_DEPENDING5;
786 bfont->pfont = origBfont->pfont;
787 break;
788 }
789 }
790 }
791 if (bfont->pfont == NULL((void*)0))
792 {
793 /* XXX - something nasty happened */
794 ret = BadFontName83;
795 }
796 else
797 ret = AccessDone0x400;
798 }
799 else
800 {
801 bfont->pfont->info.cachable = rep->cachable != 0;
802 bfont->state = FS_INFO_REPLY1;
803 /*
804 * Reset the blockrec for the next reply
805 */
806 blockrec->sequenceNumber = bfont->queryInfoSequence;
807 conn->blockedReplyTime = GetTimeInMillis__libxfont__GetTimeInMillis () + FontServerRequestTimeout;
808 ret = StillWorking81;
809 }
810 _fs_done_read (conn, rep->length << 2);
811 return ret;
812}
813
814static Bool
815fs_fonts_match (FontInfoPtr pInfo1, FontInfoPtr pInfo2)
816{
817 int i;
818
819 if (pInfo1->firstCol != pInfo2->firstCol ||
820 pInfo1->lastCol != pInfo2->lastCol ||
821 pInfo1->firstRow != pInfo2->firstRow ||
822 pInfo1->lastRow != pInfo2->lastRow ||
823 pInfo1->defaultCh != pInfo2->defaultCh ||
824 pInfo1->noOverlap != pInfo2->noOverlap ||
825 pInfo1->terminalFont != pInfo2->terminalFont ||
826 pInfo1->constantMetrics != pInfo2->constantMetrics ||
827 pInfo1->constantWidth != pInfo2->constantWidth ||
828 pInfo1->inkInside != pInfo2->inkInside ||
829 pInfo1->inkMetrics != pInfo2->inkMetrics ||
830 pInfo1->allExist != pInfo2->allExist ||
831 pInfo1->drawDirection != pInfo2->drawDirection ||
832 pInfo1->cachable != pInfo2->cachable ||
833 pInfo1->anamorphic != pInfo2->anamorphic ||
834 pInfo1->maxOverlap != pInfo2->maxOverlap ||
835 pInfo1->fontAscent != pInfo2->fontAscent ||
836 pInfo1->fontDescent != pInfo2->fontDescent ||
837 pInfo1->nprops != pInfo2->nprops)
838 return FALSE0;
839
840#define MATCH(xci1, xci2) \
841 (((xci1).leftSideBearing == (xci2).leftSideBearing) && \
842 ((xci1).rightSideBearing == (xci2).rightSideBearing) && \
843 ((xci1).characterWidth == (xci2).characterWidth) && \
844 ((xci1).ascent == (xci2).ascent) && \
845 ((xci1).descent == (xci2).descent) && \
846 ((xci1).attributes == (xci2).attributes))
847
848 if (!MATCH(pInfo1->maxbounds, pInfo2->maxbounds) ||
849 !MATCH(pInfo1->minbounds, pInfo2->minbounds) ||
850 !MATCH(pInfo1->ink_maxbounds, pInfo2->ink_maxbounds) ||
851 !MATCH(pInfo1->ink_minbounds, pInfo2->ink_minbounds))
852 return FALSE0;
853
854#undef MATCH
855
856 for (i = 0; i < pInfo1->nprops; i++)
857 if (pInfo1->isStringProp[i] !=
858 pInfo2->isStringProp[i] ||
859 pInfo1->props[i].name !=
860 pInfo2->props[i].name ||
861 pInfo1->props[i].value !=
862 pInfo2->props[i].value)
863 {
864 return FALSE0;
865 }
866 return TRUE1;
867}
868
869static int
870fs_read_query_info(FontPathElementPtr fpe, FSBlockDataPtr blockrec)
871{
872 FSBlockedFontPtr bfont = (FSBlockedFontPtr) blockrec->data;
873 FSFpePtr conn = (FSFpePtr) fpe->private;
874 fsQueryXInfoReply *rep;
875 char *buf;
876 long bufleft; /* length of reply left to use */
877 fsPropInfo *pi;
878 fsPropOffset *po;
879 pointer pd;
880 FontInfoPtr pInfo;
881 FontInfoRec tempInfo;
882 int err;
883 int ret;
884
885 rep = (fsQueryXInfoReply *) fs_get_reply (conn, &ret);
886 if (!rep || rep->type == FS_Error1 ||
887 (rep->length < LENGTHOF(fsQueryXInfoReply)((8 + 40) >> 2)))
888 {
889 if (ret == FSIO_BLOCK0)
890 return StillWorking81;
891 if (rep)
892 _fs_done_read (conn, rep->length << 2);
893 fs_cleanup_bfont (bfont);
894 _fs_reply_failed (rep, fsQueryXInfoReply, "<");
895 return BadFontName83;
896 }
897
898 /* If this is a reopen, accumulate the query info into a dummy
899 font and compare to our original data. */
900 if (bfont->flags & FontReopen0x0020)
901 pInfo = &tempInfo;
902 else
903 pInfo = &bfont->pfont->info;
904
905 buf = (char *) rep;
906 buf += SIZEOF(fsQueryXInfoReply)(8 + 40);
907
908 bufleft = rep->length << 2;
909 bufleft -= SIZEOF(fsQueryXInfoReply)(8 + 40);
910
911 /* move the data over */
912 fsUnpack_XFontInfoHeader(rep, pInfo)(pInfo)->allExist = ((rep)->font_header_flags & (1L
<< 0)) != 0; (pInfo)->drawDirection = ((rep)->font_header_draw_direction
== 0) ? 0 : 1; (pInfo)->inkInside = ((rep)->font_header_flags
& (1L << 1)) != 0; (pInfo)->firstRow = (rep)->
font_hdr_char_range_min_char_high; (pInfo)->firstCol = (rep
)->font_hdr_char_range_min_char_low; (pInfo)->lastRow =
(rep)->font_hdr_char_range_max_char_high; (pInfo)->lastCol
= (rep)->font_hdr_char_range_max_char_low; (pInfo)->defaultCh
= (rep)->font_header_default_char_low + ((rep)->font_header_default_char_high
<< 8); (pInfo)->fontDescent = (rep)->font_header_font_descent
; (pInfo)->fontAscent = (rep)->font_header_font_ascent;
(&(pInfo)->minbounds)->leftSideBearing = (rep)->
font_header_min_bounds_left; (&(pInfo)->minbounds)->
rightSideBearing = (rep)->font_header_min_bounds_right; (&
(pInfo)->minbounds)->characterWidth = (rep)->font_header_min_bounds_width
; (&(pInfo)->minbounds)->ascent = (rep)->font_header_min_bounds_ascent
; (&(pInfo)->minbounds)->descent = (rep)->font_header_min_bounds_descent
; (&(pInfo)->minbounds)->attributes = (rep)->font_header_min_bounds_attributes
; (&(pInfo)->ink_minbounds)->leftSideBearing = (rep
)->font_header_min_bounds_left; (&(pInfo)->ink_minbounds
)->rightSideBearing = (rep)->font_header_min_bounds_right
; (&(pInfo)->ink_minbounds)->characterWidth = (rep)
->font_header_min_bounds_width; (&(pInfo)->ink_minbounds
)->ascent = (rep)->font_header_min_bounds_ascent; (&
(pInfo)->ink_minbounds)->descent = (rep)->font_header_min_bounds_descent
; (&(pInfo)->ink_minbounds)->attributes = (rep)->
font_header_min_bounds_attributes; (&(pInfo)->maxbounds
)->leftSideBearing = (rep)->font_header_max_bounds_left
; (&(pInfo)->maxbounds)->rightSideBearing = (rep)->
font_header_max_bounds_right; (&(pInfo)->maxbounds)->
characterWidth = (rep)->font_header_max_bounds_width; (&
(pInfo)->maxbounds)->ascent = (rep)->font_header_max_bounds_ascent
; (&(pInfo)->maxbounds)->descent = (rep)->font_header_max_bounds_descent
; (&(pInfo)->maxbounds)->attributes = (rep)->font_header_max_bounds_attributes
; (&(pInfo)->ink_maxbounds)->leftSideBearing = (rep
)->font_header_max_bounds_left; (&(pInfo)->ink_maxbounds
)->rightSideBearing = (rep)->font_header_max_bounds_right
; (&(pInfo)->ink_maxbounds)->characterWidth = (rep)
->font_header_max_bounds_width; (&(pInfo)->ink_maxbounds
)->ascent = (rep)->font_header_max_bounds_ascent; (&
(pInfo)->ink_maxbounds)->descent = (rep)->font_header_max_bounds_descent
; (&(pInfo)->ink_maxbounds)->attributes = (rep)->
font_header_max_bounds_attributes
;
913
914 /* compute accelerators */
915 _fs_init_fontinfo(conn, pInfo);
916
917 /* Compute offsets into the reply */
918 if (bufleft < SIZEOF(fsPropInfo)8)
919 {
920 ret = -1;
921#ifdef DEBUG
922 fprintf(stderr__stderrp, "fsQueryXInfo: bufleft (%ld) < SIZEOF(fsPropInfo)\n",
923 bufleft);
924#endif
925 goto bail;
926 }
927 pi = (fsPropInfo *) buf;
928 buf += SIZEOF (fsPropInfo)8;
929 bufleft -= SIZEOF(fsPropInfo)8;
930
931 if ((bufleft / SIZEOF(fsPropOffset)20) < pi->num_offsets)
932 {
933 ret = -1;
934#ifdef DEBUG
935 fprintf(stderr__stderrp,
936 "fsQueryXInfo: bufleft (%ld) / SIZEOF(fsPropOffset) < %d\n",
937 bufleft, pi->num_offsets);
938#endif
939 goto bail;
940 }
941 po = (fsPropOffset *) buf;
942 buf += pi->num_offsets * SIZEOF(fsPropOffset)20;
943 bufleft -= pi->num_offsets * SIZEOF(fsPropOffset)20;
944
945 if (bufleft < pi->data_len)
946 {
947 ret = -1;
948#ifdef DEBUG
949 fprintf(stderr__stderrp,
950 "fsQueryXInfo: bufleft (%ld) < data_len (%d)\n",
951 bufleft, pi->data_len);
952#endif
953 goto bail;
954 }
955 pd = (pointer) buf;
956 buf += pi->data_len;
957 bufleft -= pi->data_len;
958
959 /* convert the properties and step over the reply */
960 ret = _fs_convert_props(pi, po, pd, pInfo);
961 bail:
962 _fs_done_read (conn, rep->length << 2);
963
964 if (ret == -1)
965 {
966 fs_cleanup_bfont (bfont);
967 return AllocError80;
968 }
969
970 if (bfont->flags & FontReopen0x0020)
971 {
972 /* We're reopening a font that we lost because of a downed
973 connection. In the interest of avoiding corruption from
974 opening a different font than the old one (we already have
975 its metrics, extents, and probably some of its glyphs),
976 verify that the metrics and properties all match. */
977
978 if (fs_fonts_match (pInfo, &bfont->pfont->info))
979 {
980 err = Successful85;
981 bfont->state = FS_DONE_REPLY4;
982 }
983 else
984 {
985 fs_cleanup_bfont (bfont);
986 err = BadFontName83;
987 }
988 _fs_free_props (pInfo);
989
990 return err;
991 }
992
993 /*
994 * Ask for terminal format fonts if possible
995 */
996 if (bfont->pfont->info.terminalFont)
997 bfont->format = ((bfont->format & ~ (BitmapFormatImageRectMask(3L << 2))) |
998 BitmapFormatImageRectMax(2L << 2));
999
1000 /*
1001 * Figure out if the whole font should get loaded right now.
1002 */
1003 if (glyphCachingMode == CACHING_OFF0 ||
1004 (glyphCachingMode == CACHE_16_BIT_GLYPHS1
1005 && !bfont->pfont->info.lastRow))
1006 {
1007 bfont->flags |= FontLoadAll0x000f;
1008 }
1009
1010 /*
1011 * Ready to send the query bitmaps; the terminal font bit has
1012 * been computed and glyphCaching has been considered
1013 */
1014 if (bfont->flags & FontLoadBitmaps0x0008)
1015 {
1016 fs_send_query_bitmaps (fpe, blockrec);
1017 _fs_flush (conn);
1018 }
1019
1020 bfont->state = FS_EXTENT_REPLY2;
1021
1022 /*
1023 * Reset the blockrec for the next reply
1024 */
1025 blockrec->sequenceNumber = bfont->queryExtentsSequence;
1026 conn->blockedReplyTime = GetTimeInMillis__libxfont__GetTimeInMillis () + FontServerRequestTimeout;
1027
1028 return StillWorking81;
1029}
1030
1031static int
1032fs_read_extent_info(FontPathElementPtr fpe, FSBlockDataPtr blockrec)
1033{
1034 FSFpePtr conn = (FSFpePtr) fpe->private;
1035 FSBlockedFontPtr bfont = (FSBlockedFontPtr) blockrec->data;
1036 FSFontDataPtr fsd = (FSFontDataPtr) bfont->pfont->fpePrivate;
1037 FSFontPtr fsfont = (FSFontPtr) bfont->pfont->fontPrivate;
1038 fsQueryXExtents16Reply *rep;
1039 char *buf;
1040 int i;
1041 int numExtents;
1042 int numInfos;
1043 int ret;
1044 Bool haveInk = FALSE0; /* need separate ink metrics? */
1045 CharInfoPtr ci, pCI;
1046 char *fsci;
1047 fsXCharInfo fscilocal;
1048 FontInfoRec *fi = &bfont->pfont->info;
1049
1050 rep = (fsQueryXExtents16Reply *) fs_get_reply (conn, &ret);
1051 if (!rep || rep->type == FS_Error1 ||
1052 (rep->length < LENGTHOF(fsQueryXExtents16Reply)(12 >> 2)))
1053 {
1054 if (ret == FSIO_BLOCK0)
1055 return StillWorking81;
1056 if (rep)
1057 _fs_done_read (conn, rep->length << 2);
1058 fs_cleanup_bfont (bfont);
1059 _fs_reply_failed (rep, fsQueryXExtents16Reply, "<");
1060 return BadFontName83;
1061 }
1062
1063 /* move the data over */
1064 /* need separate inkMetrics for fixed font server protocol version */
1065 numExtents = rep->num_extents;
1066 numInfos = numExtents;
1067 if (bfont->pfont->info.terminalFont && conn->fsMajorVersion > 1)
1068 {
1069 numInfos *= 2;
1070 haveInk = TRUE1;
1071 }
1072 if (numInfos >= (INT_MAX2147483647 / sizeof(CharInfoRec))) {
1073#ifdef DEBUG
1074 fprintf(stderr__stderrp,
1075 "fsQueryXExtents16: numInfos (%d) >= %ld\n",
1076 numInfos, (INT_MAX2147483647 / sizeof(CharInfoRec)));
1077#endif
1078 pCI = NULL((void*)0);
1079 }
1080 else if (numExtents > ((rep->length - LENGTHOF(fsQueryXExtents16Reply)(12 >> 2))
1081 / LENGTHOF(fsXCharInfo)(12 >> 2))) {
1082#ifdef DEBUG
1083 fprintf(stderr__stderrp,
1084 "fsQueryXExtents16: numExtents (%d) > (%d - %d) / %d\n",
1085 numExtents, rep->length,
1086 LENGTHOF(fsQueryXExtents16Reply)(12 >> 2), LENGTHOF(fsXCharInfo)(12 >> 2));
1087#endif
1088 pCI = NULL((void*)0);
1089 }
1090 else
1091 pCI = malloc(sizeof(CharInfoRec) * numInfos);
1092
1093 if (!pCI)
1094 {
1095 _fs_done_read (conn, rep->length << 2);
1096 fs_cleanup_bfont(bfont);
1097 return AllocError80;
1098 }
1099 fsfont->encoding = pCI;
1100 if (haveInk)
1101 fsfont->inkMetrics = pCI + numExtents;
1102 else
1103 fsfont->inkMetrics = pCI;
1104
1105 buf = (char *) rep;
1106 buf += SIZEOF (fsQueryXExtents16Reply)12;
1107 fsci = buf;
1108
1109 fsd->glyphs_to_get = 0;
1110 ci = fsfont->inkMetrics;
1111 for (i = 0; i < numExtents; i++)
1112 {
1113 memcpy(&fscilocal, fsci, SIZEOF(fsXCharInfo))__builtin___memcpy_chk (&fscilocal, fsci, 12, __builtin_object_size
(&fscilocal, 0))
; /* align it */
1114 _fs_convert_char_info(&fscilocal, &ci->metrics);
1115 /* Bounds check. */
1116 if (ci->metrics.ascent > fi->maxbounds.ascent)
1117 {
1118 ErrorF__libxfont__ErrorF("fserve: warning: %s %s ascent (%d) > maxascent (%d)\n",
1119 fpe->name, fsd->name,
1120 ci->metrics.ascent, fi->maxbounds.ascent);
1121 ci->metrics.ascent = fi->maxbounds.ascent;
1122 }
1123 if (ci->metrics.descent > fi->maxbounds.descent)
1124 {
1125 ErrorF__libxfont__ErrorF("fserve: warning: %s %s descent (%d) > maxdescent (%d)\n",
1126 fpe->name, fsd->name,
1127 ci->metrics.descent, fi->maxbounds.descent);
1128 ci->metrics.descent = fi->maxbounds.descent;
1129 }
1130 fsci = fsci + SIZEOF(fsXCharInfo)12;
1131 /* Initialize the bits field for later glyph-caching use */
1132 if (NONZEROMETRICS(&ci->metrics)((&ci->metrics)->leftSideBearing || (&ci->metrics
)->rightSideBearing || (&ci->metrics)->ascent ||
(&ci->metrics)->descent || (&ci->metrics)->
characterWidth)
)
1133 {
1134 if (!haveInk &&
1135 (ci->metrics.leftSideBearing == ci->metrics.rightSideBearing ||
1136 ci->metrics.ascent == -ci->metrics.descent))
1137 pCI[i].bits = &_fs_glyph_zero_length;
1138 else
1139 {
1140 pCI[i].bits = &_fs_glyph_undefined;
1141 fsd->glyphs_to_get++;
1142 }
1143 }
1144 else
1145 pCI[i].bits = (char *)0;
1146 ci++;
1147 }
1148
1149 /* Done with reply */
1150 _fs_done_read (conn, rep->length << 2);
1151
1152 /* build bitmap metrics, ImageRectMax style */
1153 if (haveInk)
1154 {
1155 CharInfoPtr ii;
1156
1157 ci = fsfont->encoding;
1158 ii = fsfont->inkMetrics;
1159 for (i = 0; i < numExtents; i++, ci++, ii++)
1160 {
1161 if (NONZEROMETRICS(&ii->metrics)((&ii->metrics)->leftSideBearing || (&ii->metrics
)->rightSideBearing || (&ii->metrics)->ascent ||
(&ii->metrics)->descent || (&ii->metrics)->
characterWidth)
)
1162 {
1163 ci->metrics.leftSideBearing = FONT_MIN_LEFT(fi)((fi)->ink_minbounds.leftSideBearing < 0 ? (fi)->ink_minbounds
.leftSideBearing : 0)
;
1164 ci->metrics.rightSideBearing = FONT_MAX_RIGHT(fi)((fi)->ink_maxbounds.rightSideBearing > (fi)->ink_maxbounds
.characterWidth ? (fi)->ink_maxbounds.rightSideBearing : (
fi)->ink_maxbounds.characterWidth)
;
1165 ci->metrics.ascent = FONT_MAX_ASCENT(fi)((fi)->fontAscent > (fi)->ink_maxbounds.ascent ? (fi
)->fontAscent : (fi)->ink_maxbounds.ascent)
;
1166 ci->metrics.descent = FONT_MAX_DESCENT(fi)((fi)->fontDescent > (fi)->ink_maxbounds.descent ? (
fi)->fontDescent : (fi)->ink_maxbounds.descent)
;
1167 ci->metrics.characterWidth = FONT_MAX_WIDTH(fi)(((fi)->ink_maxbounds.rightSideBearing > (fi)->ink_maxbounds
.characterWidth ? (fi)->ink_maxbounds.rightSideBearing : (
fi)->ink_maxbounds.characterWidth) - ((fi)->ink_minbounds
.leftSideBearing < 0 ? (fi)->ink_minbounds.leftSideBearing
: 0))
;
1168 ci->metrics.attributes = ii->metrics.attributes;
1169 }
1170 else
1171 {
1172 ci->metrics = ii->metrics;
1173 }
1174 /* Bounds check. */
1175 if (ci->metrics.ascent > fi->maxbounds.ascent)
1176 {
1177 ErrorF__libxfont__ErrorF("fserve: warning: %s %s ascent (%d) "
1178 "> maxascent (%d)\n",
1179 fpe->name, fsd->name,
1180 ci->metrics.ascent, fi->maxbounds.ascent);
1181 ci->metrics.ascent = fi->maxbounds.ascent;
1182 }
1183 if (ci->metrics.descent > fi->maxbounds.descent)
1184 {
1185 ErrorF__libxfont__ErrorF("fserve: warning: %s %s descent (%d) "
1186 "> maxdescent (%d)\n",
1187 fpe->name, fsd->name,
1188 ci->metrics.descent, fi->maxbounds.descent);
1189 ci->metrics.descent = fi->maxbounds.descent;
1190 }
1191 }
1192 }
1193 {
1194 unsigned int r, c, numCols, firstCol;
1195
1196 firstCol = bfont->pfont->info.firstCol;
1197 numCols = bfont->pfont->info.lastCol - firstCol + 1;
1198 c = bfont->pfont->info.defaultCh;
1199 fsfont->pDefault = 0;
1200 if (bfont->pfont->info.lastRow)
1201 {
1202 r = c >> 8;
1203 r -= bfont->pfont->info.firstRow;
1204 c &= 0xff;
1205 c -= firstCol;
1206 if (r < bfont->pfont->info.lastRow-bfont->pfont->info.firstRow+1 &&
1207 c < numCols)
1208 fsfont->pDefault = &pCI[r * numCols + c];
1209 }
1210 else
1211 {
1212 c -= firstCol;
1213 if (c < numCols)
1214 fsfont->pDefault = &pCI[c];
1215 }
1216 }
1217 bfont->state = FS_GLYPHS_REPLY3;
1218
1219 if (bfont->flags & FontLoadBitmaps0x0008)
1220 {
1221 /*
1222 * Reset the blockrec for the next reply
1223 */
1224 blockrec->sequenceNumber = bfont->queryBitmapsSequence;
1225 conn->blockedReplyTime = GetTimeInMillis__libxfont__GetTimeInMillis () + FontServerRequestTimeout;
1226 return StillWorking81;
1227 }
1228 return Successful85;
1229}
1230
1231#ifdef DEBUG
1232static const char *fs_open_states[] = {
1233 "OPEN_REPLY ",
1234 "INFO_REPLY ",
1235 "EXTENT_REPLY",
1236 "GLYPHS_REPLY",
1237 "DONE_REPLY ",
1238 "DEPENDING ",
1239};
1240#endif
1241
1242static int
1243fs_do_open_font(FontPathElementPtr fpe, FSBlockDataPtr blockrec)
1244{
1245 FSBlockedFontPtr bfont = (FSBlockedFontPtr) blockrec->data;
1246 int err;
1247
1248#ifdef DEBUG
1249 fprintf (stderr__stderrp, "fs_do_open_font state %s %s\n",
1250 fs_open_states[bfont->state],
1251 ((FSFontDataPtr) (bfont->pfont->fpePrivate))->name);
1252#endif
1253 err = BadFontName83;
1254 switch (bfont->state) {
1255 case FS_OPEN_REPLY0:
1256 err = fs_read_open_font(fpe, blockrec);
1257 if (err != StillWorking81) { /* already loaded, or error */
1258 /* if font's already loaded, massage error code */
1259 switch (bfont->state) {
1260 case FS_DONE_REPLY4:
1261 err = Successful85;
1262 break;
1263 case FS_DEPENDING5:
1264 err = StillWorking81;
1265 break;
1266 }
1267 }
1268 break;
1269 case FS_INFO_REPLY1:
1270 err = fs_read_query_info(fpe, blockrec);
1271 break;
1272 case FS_EXTENT_REPLY2:
1273 err = fs_read_extent_info(fpe, blockrec);
1274 break;
1275 case FS_GLYPHS_REPLY3:
1276 if (bfont->flags & FontLoadBitmaps0x0008)
1277 err = fs_read_glyphs(fpe, blockrec);
1278 break;
1279 case FS_DEPENDING5: /* can't happen */
1280 default:
1281 break;
1282 }
1283#ifdef DEBUG
1284 fprintf (stderr__stderrp, "fs_do_open_font err %d\n", err);
1285#endif
1286 if (err != StillWorking81)
1287 {
1288 bfont->state = FS_DONE_REPLY4; /* for _fs_load_glyphs() */
1289 while ((blockrec = blockrec->depending))
1290 {
1291 bfont = (FSBlockedFontPtr) blockrec->data;
1292 bfont->state = FS_DONE_REPLY4; /* for _fs_load_glyphs() */
1293 }
1294 }
1295 return err;
1296}
1297
1298void
1299_fs_mark_block (FSFpePtr conn, CARD32 mask)
1300{
1301 conn->blockState |= mask;
1302 fs_blockState |= mask;
1303}
1304
1305void
1306_fs_unmark_block (FSFpePtr conn, CARD32 mask)
1307{
1308 FSFpePtr c;
1309
1310 if (conn->blockState & mask)
1311 {
1312 conn->blockState &= ~mask;
1313 fs_blockState = 0;
1314 for (c = fs_fpes; c; c = c->next)
1315 fs_blockState |= c->blockState;
1316 }
1317}
1318
1319/* ARGSUSED */
1320static void
1321fs_block_handler(void *wt)
1322{
1323 CARD32 now, earliest, wakeup;
1324 int soonest;
1325 FSFpePtr conn;
1326
1327 /*
1328 * Flush all pending output
1329 */
1330 if (fs_blockState & FS_PENDING_WRITE0x01)
1331 for (conn = fs_fpes; conn; conn = conn->next)
1332 if (conn->blockState & FS_PENDING_WRITE0x01)
1333 _fs_flush (conn);
1334 /*
1335 * Check for any fpe with a complete reply, set sleep time to zero
1336 */
1337 if (fs_blockState & FS_COMPLETE_REPLY0x20)
1338 adjust_fs_wait_for_delay__libxfont_adjust_fs_wait_for_delay(wt, 0);
1339 /*
1340 * Walk through fpe list computing sleep time
1341 */
1342 else if (fs_blockState & (FS_BROKEN_WRITE0x02|
1343 FS_BROKEN_CONNECTION0x04|
1344 FS_PENDING_REPLY0x08|
1345 FS_RECONNECTING0x40))
1346 {
1347 now = GetTimeInMillis__libxfont__GetTimeInMillis ();
1348 earliest = now + 10000000;
1349 for (conn = fs_fpes; conn; conn = conn->next)
1350 {
1351 if (conn->blockState & FS_RECONNECTING0x40)
1352 {
1353 wakeup = conn->blockedConnectTime;
1354 if (TimeCmp (wakeup, <, earliest)((int) ((wakeup) - (earliest)) < 0))
1355 earliest = wakeup;
1356 }
1357 if (conn->blockState & FS_BROKEN_CONNECTION0x04)
1358 {
1359 wakeup = conn->brokenConnectionTime;
1360 if (TimeCmp (wakeup, <, earliest)((int) ((wakeup) - (earliest)) < 0))
1361 earliest = wakeup;
1362 }
1363 if (conn->blockState & FS_BROKEN_WRITE0x02)
1364 {
1365 wakeup = conn->brokenWriteTime;
1366 if (TimeCmp (wakeup, <, earliest)((int) ((wakeup) - (earliest)) < 0))
1367 earliest = wakeup;
1368 }
1369 if (conn->blockState & FS_PENDING_REPLY0x08)
1370 {
1371 wakeup = conn->blockedReplyTime;
1372 if (TimeCmp (wakeup, <, earliest)((int) ((wakeup) - (earliest)) < 0))
1373 earliest = wakeup;
1374 }
1375 }
1376 soonest = earliest - now;
1377 if (soonest < 0)
1378 soonest = 0;
1379 adjust_fs_wait_for_delay__libxfont_adjust_fs_wait_for_delay(wt, soonest);
1380 }
1381}
1382
1383static void
1384fs_handle_unexpected(FSFpePtr conn, fsGenericReply *rep)
1385{
1386 if (rep->type == FS_Event2 && rep->data1 == KeepAlive0)
1387 {
1388 fsNoopReq req;
1389
1390 /* ping it back */
1391 req.reqType = FS_Noop0;
1392 req.length = SIZEOF(fsNoopReq)4 >> 2;
1393 _fs_add_req_log(conn, FS_Noop)((conn)->current_seq++);
1394 _fs_write(conn, (char *) &req, SIZEOF(fsNoopReq)4);
1395 }
1396 /* this should suck up unexpected replies and events */
1397 _fs_done_read (conn, rep->length << 2);
1398}
1399
1400static void
1401fs_read_reply (FontPathElementPtr fpe, pointer client)
1402{
1403 FSFpePtr conn = (FSFpePtr) fpe->private;
1404 FSBlockDataPtr blockrec;
1405 int ret;
1406 int err;
1407 fsGenericReply *rep;
1408
1409 if ((rep = fs_get_reply (conn, &ret)))
23
Assuming 'rep' is not null
24
Taking true branch
1410 {
1411 _fs_add_rep_log (conn, rep);
1412 for (blockrec = conn->blockedRequests;
25
Loop condition is true. Entering loop body
27
Loop condition is true. Entering loop body
29
Loop condition is true. Entering loop body
31
Loop condition is true. Entering loop body
1413 blockrec;
1414 blockrec = blockrec->next)
1415 {
1416 if (blockrec->sequenceNumber == rep->sequenceNumber)
26
Taking false branch
28
Taking false branch
30
Taking false branch
32
Taking true branch
1417 break;
33
Execution continues on line 1419
1418 }
1419 err = Successful85;
1420 if (!blockrec)
34
Taking false branch
1421 {
1422 fs_handle_unexpected(conn, rep);
1423 }
1424 else
1425 {
1426 /*
1427 * go read it, and if we're done,
1428 * wake up the appropriate client
1429 */
1430 switch (blockrec->type) {
35
Control jumps to 'case 4:' at line 1440
1431 case FS_OPEN_FONT1:
1432 blockrec->errcode = fs_do_open_font(fpe, blockrec);
1433 break;
1434 case FS_LOAD_GLYPHS2:
1435 blockrec->errcode = fs_read_glyphs(fpe, blockrec);
1436 break;
1437 case FS_LIST_FONTS3:
1438 blockrec->errcode = fs_read_list(fpe, blockrec);
1439 break;
1440 case FS_LIST_WITH_INFO4:
1441 blockrec->errcode = fs_read_list_info(fpe, blockrec);
36
Calling 'fs_read_list_info'
1442 break;
1443 default:
1444 break;
1445 }
1446 err = blockrec->errcode;
1447 if (err != StillWorking81)
1448 {
1449 while (blockrec)
1450 {
1451 blockrec->errcode = err;
1452 if (client != blockrec->client)
1453 ClientSignal__libxfont__ClientSignal(blockrec->client);
1454 blockrec = blockrec->depending;
1455 }
1456 _fs_unmark_block (conn, FS_PENDING_REPLY0x08);
1457 }
1458 }
1459 if (fs_reply_ready (conn))
1460 _fs_mark_block (conn, FS_COMPLETE_REPLY0x20);
1461 else
1462 _fs_unmark_block (conn, FS_COMPLETE_REPLY0x20);
1463 }
1464}
1465
1466static void
1467fs_fd_handler(int fd, void *data)
1468{
1469 FontPathElementPtr fpe = data;
1470 FSFpePtr conn = (FSFpePtr) fpe->private;
1471
1472 /*
1473 * Don't continue if the fd is -1 (which will be true when the
1474 * font server terminates
1475 */
1476 if ((conn->blockState & FS_RECONNECTING0x40))
1477 _fs_check_reconnect (conn);
1478 else if ((conn->fs_fd != -1))
1479 fs_read_reply (fpe, 0);
1480}
1481
1482static int
1483fs_wakeup(FontPathElementPtr fpe)
1484{
1485 FSFpePtr conn = (FSFpePtr) fpe->private;
1486
1487 if (conn->blockState & (FS_PENDING_REPLY0x08|FS_BROKEN_CONNECTION0x04|FS_BROKEN_WRITE0x02))
1488 _fs_do_blocked (conn);
1489 if (conn->blockState & FS_COMPLETE_REPLY0x20)
1490 fs_read_reply (fpe, 0);
1491#ifdef DEBUG
1492 {
1493 FSBlockDataPtr blockrec;
1494 FSBlockedFontPtr bfont;
1495 static CARD32 lastState;
1496 static FSBlockDataPtr lastBlock;
1497
1498 if (conn->blockState || conn->blockedRequests || lastState || lastBlock)
1499 {
1500 fprintf (stderr__stderrp, " Block State 0x%x\n", (int) conn->blockState);
1501 lastState = conn->blockState;
1502 lastBlock = conn->blockedRequests;
1503 }
1504 for (blockrec = conn->blockedRequests; blockrec; blockrec = blockrec->next)
1505 {
1506 switch (blockrec->type) {
1507 case FS_OPEN_FONT1:
1508 bfont = (FSBlockedFontPtr) blockrec->data;
1509 fprintf (stderr__stderrp, " Blocked font errcode %d sequence %d state %s %s\n",
1510 blockrec->errcode,
1511 blockrec->sequenceNumber,
1512 fs_open_states[bfont->state],
1513 bfont->pfont ?
1514 ((FSFontDataPtr) (bfont->pfont->fpePrivate))->name :
1515 "<freed>");
1516 break;
1517 case FS_LIST_FONTS3:
1518 fprintf (stderr__stderrp, " Blocked list errcode %d sequence %d\n",
1519 blockrec->errcode, blockrec->sequenceNumber);
1520 break;
1521 default:
1522 fprintf (stderr__stderrp, " Blocked type %d errcode %d sequence %d\n",
1523 blockrec->type,
1524 blockrec->errcode,
1525 blockrec->sequenceNumber);
1526 break;
1527 }
1528 }
1529 }
1530#endif
1531 return FALSE0;
1532}
1533
1534/*
1535 * Notice a dead connection and prepare for reconnect
1536 */
1537
1538void
1539_fs_connection_died(FSFpePtr conn)
1540{
1541 if (conn->blockState & FS_BROKEN_CONNECTION0x04)
1542 return;
1543 fs_close_conn(conn);
1544 conn->brokenConnectionTime = GetTimeInMillis__libxfont__GetTimeInMillis ();
1545 _fs_mark_block (conn, FS_BROKEN_CONNECTION0x04);
1546 _fs_unmark_block (conn, FS_BROKEN_WRITE0x02|FS_PENDING_WRITE0x01|FS_RECONNECTING0x40);
1547}
1548
1549/*
1550 * Signal clients that the connection has come back up
1551 */
1552static int
1553_fs_restart_connection(FSFpePtr conn)
1554{
1555 FSBlockDataPtr block;
1556
1557 _fs_unmark_block (conn, FS_GIVE_UP0x10);
1558 while ((block = (FSBlockDataPtr) conn->blockedRequests))
1559 {
1560 if (block->errcode == StillWorking81)
1561 {
1562 ClientSignal__libxfont__ClientSignal(block->client);
1563 fs_abort_blockrec(conn, block);
1564 }
1565 }
1566 return TRUE1;
1567}
1568
1569/*
1570 * Declare this font server connection useless
1571 */
1572static void
1573_fs_giveup (FSFpePtr conn)
1574{
1575 FSBlockDataPtr block;
1576
1577 if (conn->blockState & FS_GIVE_UP0x10)
1578 return;
1579#ifdef DEBUG
1580 fprintf (stderr__stderrp, "give up on FS \"%s\"\n", conn->servername);
1581#endif
1582 _fs_mark_block (conn, FS_GIVE_UP0x10);
1583 while ((block = (FSBlockDataPtr) conn->blockedRequests))
1584 {
1585 if (block->errcode == StillWorking81)
1586 {
1587 ClientSignal__libxfont__ClientSignal (block->client);
1588 fs_abort_blockrec (conn, block);
1589 }
1590 }
1591 if (conn->fs_fd >= 0)
1592 _fs_connection_died (conn);
1593}
1594
1595static void
1596_fs_do_blocked (FSFpePtr conn)
1597{
1598 CARD32 now;
1599
1600 now = GetTimeInMillis__libxfont__GetTimeInMillis ();
1601 if ((conn->blockState & FS_PENDING_REPLY0x08) &&
1602 TimeCmp (conn->blockedReplyTime, <=, now)((int) ((conn->blockedReplyTime) - (now)) <= 0))
1603 {
1604 _fs_giveup (conn);
1605 }
1606 else
1607 {
1608 if (conn->blockState & FS_BROKEN_CONNECTION0x04)
1609 {
1610 /* Try to reconnect broken connections */
1611 if (TimeCmp (conn->brokenConnectionTime, <=, now)((int) ((conn->brokenConnectionTime) - (now)) <= 0))
1612 _fs_start_reconnect (conn);
1613 }
1614 else if (conn->blockState & FS_BROKEN_WRITE0x02)
1615 {
1616 /* Try to flush blocked connections */
1617 if (TimeCmp (conn->brokenWriteTime, <=, now)((int) ((conn->brokenWriteTime) - (now)) <= 0))
1618 _fs_flush (conn);
1619 }
1620 }
1621}
1622
1623/*
1624 * sends the actual request out
1625 */
1626/* ARGSUSED */
1627static int
1628fs_send_open_font(pointer client, FontPathElementPtr fpe, Mask flags,
1629 const char *name, int namelen,
1630 fsBitmapFormat format, fsBitmapFormatMask fmask,
1631 XID id, FontPtr *ppfont)
1632{
1633 FSFpePtr conn = (FSFpePtr) fpe->private;
1634 FontPtr font;
1635 FSBlockDataPtr blockrec = NULL((void*)0);
1636 FSBlockedFontPtr bfont;
1637 FSFontDataPtr fsd;
1638 fsOpenBitmapFontReq openreq;
1639 fsQueryXInfoReq inforeq;
1640 fsQueryXExtents16Req extreq;
1641 int err;
1642 unsigned char buf[1024];
1643
1644 if (conn->blockState & FS_GIVE_UP0x10)
3
Taking false branch
1645 return BadFontName83;
1646
1647 if (namelen < 0 || namelen > sizeof (buf) - 1)
4
Assuming 'namelen' is >= 0
5
Taking false branch
1648 return BadFontName83;
1649
1650 /*
1651 * Get the font structure put together, either by reusing
1652 * the existing one or creating a new one
1653 */
1654 if (flags & FontReopen0x0020)
6
Taking false branch
1655 {
1656 Atom nameatom, fn = None0L;
1657 int i;
1658
1659 font = *ppfont;
1660 fsd = (FSFontDataPtr)font->fpePrivate;
1661 /* This is an attempt to reopen a font. Did the font have a
1662 NAME property? */
1663 if ((nameatom = MakeAtom__libxfont__MakeAtom("FONT", 4, 0)) != None0L)
1664 {
1665 for (i = 0; i < font->info.nprops; i++)
1666 if (font->info.props[i].name == nameatom &&
1667 font->info.isStringProp[i])
1668 {
1669 fn = font->info.props[i].value;
1670 break;
1671 }
1672 }
1673 if (fn == None0L || !(name = NameForAtom__libxfont__NameForAtom(fn)))
1674 {
1675 name = fsd->name;
1676 namelen = fsd->namelen;
1677 }
1678 else
1679 namelen = strlen(name);
1680 }
1681 else
1682 {
1683 font = fs_create_font (fpe, name, namelen, format, fmask);
1684 if (!font)
7
Assuming 'font' is non-null
8
Taking false branch
1685 return AllocError80;
1686
1687 fsd = (FSFontDataPtr)font->fpePrivate;
1688 }
1689
1690 /* make a new block record, and add it to the end of the list */
1691 blockrec = fs_new_block_rec(font->fpe, client, FS_OPEN_FONT1);
1692 if (!blockrec)
9
Assuming 'blockrec' is non-null
10
Taking false branch
1693 {
1694 if (!(flags & FontReopen0x0020))
1695 (*font->unload_font) (font);
1696 return AllocError80;
1697 }
1698
1699 /*
1700 * Must check this before generating any protocol, otherwise we'll
1701 * mess up a reconnect in progress
1702 */
1703 if (conn->blockState & (FS_BROKEN_CONNECTION0x04 | FS_RECONNECTING0x40))
11
Taking false branch
1704 {
1705 _fs_pending_reply (conn);
1706 return Suspended84;
1707 }
1708
1709 fsd->generation = conn->generation;
1710
1711 bfont = (FSBlockedFontPtr) blockrec->data;
1712 bfont->fontid = fsd->fontid;
1713 bfont->pfont = font;
1714 bfont->state = FS_OPEN_REPLY0;
1715 bfont->flags = flags;
1716 bfont->format = fsd->format;
1717 bfont->clients_depending = (FSClientsDependingPtr)0;
1718 bfont->freeFont = (flags & FontReopen0x0020) == 0;
1719
1720 _fs_client_access (conn, client, (flags & FontOpenSync0x0010) != 0);
1721 _fs_client_resolution(conn);
1722
1723 /* do an FS_OpenFont, FS_QueryXInfo and FS_QueryXExtents */
1724 buf[0] = (unsigned char) namelen;
1725 memcpy(&buf[1], name, namelen)__builtin___memcpy_chk (&buf[1], name, namelen, __builtin_object_size
(&buf[1], 0))
;
1726 openreq.reqType = FS_OpenBitmapFont15;
1727 openreq.pad = 0;
1728 openreq.fid = fsd->fontid;
1729 openreq.format_hint = fsd->format;
1730 openreq.format_mask = fsd->fmask;
1731 openreq.length = (SIZEOF(fsOpenBitmapFontReq)16 + namelen + 4) >> 2;
1732
1733 _fs_add_req_log(conn, FS_OpenBitmapFont)((conn)->current_seq++);
1734 _fs_write(conn, (char *) &openreq, SIZEOF(fsOpenBitmapFontReq)16);
1735 _fs_write_pad(conn, (char *) buf, namelen + 1);
1736
1737 blockrec->sequenceNumber = conn->current_seq;
1738
1739 inforeq.reqType = FS_QueryXInfo16;
1740 inforeq.pad = 0;
1741 inforeq.id = fsd->fontid;
1742 inforeq.length = SIZEOF(fsQueryXInfoReq)8 >> 2;
1743
1744 bfont->queryInfoSequence = conn->current_seq + 1;
1745
1746 _fs_add_req_log(conn, FS_QueryXInfo)((conn)->current_seq++);
1747 _fs_write(conn, (char *) &inforeq, SIZEOF(fsQueryXInfoReq)8);
1748
1749 if (!(bfont->flags & FontReopen0x0020))
12
Taking false branch
1750 {
1751 extreq.reqType = FS_QueryXExtents1618;
1752 extreq.range = fsTrue1;
1753 extreq.fid = fsd->fontid;
1754 extreq.num_ranges = 0;
1755 extreq.length = SIZEOF(fsQueryXExtents16Req)12 >> 2;
1756
1757 bfont->queryExtentsSequence = conn->current_seq + 1;
1758
1759 _fs_add_req_log(conn, FS_QueryXExtents16)((conn)->current_seq++);
1760 _fs_write(conn, (char *) &extreq, SIZEOF(fsQueryXExtents16Req)12);
1761 }
1762
1763#ifdef NCD
1764 if (configData.ExtendedFontDiags)
1765 {
1766 memcpy(buf, name, MIN(256, namelen))__builtin___memcpy_chk (buf, name, (((256)<(namelen))?(256
):(namelen)), __builtin_object_size (buf, 0))
;
1767 buf[MIN(256, namelen)(((256)<(namelen))?(256):(namelen))] = '\0';
1768 printf("Requesting font \"%s\" from font server \"%s\"\n",
1769 buf, font->fpe->name);
1770 }
1771#endif
1772 _fs_prepare_for_reply (conn);
1773
1774 err = blockrec->errcode;
1775 if (bfont->flags & FontOpenSync0x0010)
13
Taking true branch
1776 {
1777 while (blockrec->errcode == StillWorking81)
14
Loop condition is true. Entering loop body
16
Loop condition is true. Entering loop body
18
Loop condition is true. Entering loop body
20
Loop condition is true. Entering loop body
1778 {
1779 if (fs_await_reply (conn) != FSIO_READY1)
15
Taking false branch
17
Taking false branch
19
Taking false branch
21
Taking false branch
1780 {
1781 blockrec->errcode = BadFontName83;
1782 break;
1783 }
1784 fs_read_reply (font->fpe, client);
22
Calling 'fs_read_reply'
1785 }
1786 err = blockrec->errcode;
1787 if (err == Successful85)
1788 *ppfont = bfont->pfont;
1789 else
1790 fs_cleanup_bfont (bfont);
1791 bfont->freeFont = FALSE0;
1792 _fs_remove_block_rec (conn, blockrec);
1793 }
1794 return err == StillWorking81 ? Suspended84 : err;
1795}
1796
1797static void
1798fs_send_query_bitmaps(FontPathElementPtr fpe, FSBlockDataPtr blockrec)
1799{
1800 FSFpePtr conn = (FSFpePtr) fpe->private;
1801 FSBlockedFontPtr bfont = (FSBlockedFontPtr) blockrec->data;
1802 fsQueryXBitmaps16Req bitreq;
1803
1804 /* send the request */
1805 bitreq.reqType = FS_QueryXBitmaps1620;
1806 bitreq.fid = bfont->fontid;
1807 bitreq.format = bfont->format;
1808 bitreq.range = TRUE1;
1809 bitreq.length = SIZEOF(fsQueryXBitmaps16Req)16 >> 2;
1810 bitreq.num_ranges = 0;
1811
1812 bfont->queryBitmapsSequence = conn->current_seq + 1;
1813
1814 _fs_add_req_log(conn, FS_QueryXBitmaps16)((conn)->current_seq++);
1815 _fs_write(conn, (char *) &bitreq, SIZEOF(fsQueryXBitmaps16Req)16);
1816}
1817
1818/* ARGSUSED */
1819static int
1820fs_open_font(pointer client, FontPathElementPtr fpe, Mask flags,
1821 const char *name, int namelen,
1822 fsBitmapFormat format, fsBitmapFormatMask fmask,
1823 XID id, FontPtr *ppfont,
1824 char **alias, FontPtr non_cachable_font)
1825{
1826 FSFpePtr conn = (FSFpePtr) fpe->private;
1827 FSBlockDataPtr blockrec;
1828 FSBlockedFontPtr bfont;
1829 int err;
1830
1831 /* libfont interface expects ImageRectMin glyphs */
1832 format = (format & ~BitmapFormatImageRectMask(3L << 2)) | BitmapFormatImageRectMin(0L << 2);
1833
1834 *alias = (char *) 0;
1835 for (blockrec = conn->blockedRequests; blockrec; blockrec = blockrec->next)
1
Loop condition is false. Execution continues on line 1852
1836 {
1837 if (blockrec->type == FS_OPEN_FONT1 && blockrec->client == client)
1838 {
1839 err = blockrec->errcode;
1840 if (err == StillWorking81)
1841 return Suspended84;
1842
1843 bfont = (FSBlockedFontPtr) blockrec->data;
1844 if (err == Successful85)
1845 *ppfont = bfont->pfont;
1846 else
1847 fs_cleanup_bfont (bfont);
1848 _fs_remove_block_rec (conn, blockrec);
1849 return err;
1850 }
1851 }
1852 return fs_send_open_font(client, fpe, flags, name, namelen, format, fmask,
2
Calling 'fs_send_open_font'
1853 id, ppfont);
1854}
1855
1856/* ARGSUSED */
1857static int
1858fs_send_close_font(FontPathElementPtr fpe, Font id)
1859{
1860 FSFpePtr conn = (FSFpePtr) fpe->private;
1861 fsCloseReq req;
1862
1863 if (conn->blockState & FS_GIVE_UP0x10)
1864 return Successful85;
1865 /* tell the font server to close the font */
1866 req.reqType = FS_CloseFont21;
1867 req.pad = 0;
1868 req.length = SIZEOF(fsCloseReq)8 >> 2;
1869 req.id = id;
1870 _fs_add_req_log(conn, FS_CloseFont)((conn)->current_seq++);
1871 _fs_write(conn, (char *) &req, SIZEOF(fsCloseReq)8);
1872
1873 return Successful85;
1874}
1875
1876/* ARGSUSED */
1877static void
1878fs_close_font(FontPathElementPtr fpe, FontPtr pfont)
1879{
1880 FSFontDataPtr fsd = (FSFontDataPtr) pfont->fpePrivate;
1881 FSFpePtr conn = (FSFpePtr) fpe->private;
1882
1883 if (conn->generation == fsd->generation)
1884 fs_send_close_font(fpe, fsd->fontid);
1885
1886#ifdef DEBUG
1887 {
1888 FSBlockDataPtr blockrec;
1889 FSBlockedFontPtr bfont;
1890
1891 for (blockrec = conn->blockedRequests; blockrec; blockrec = blockrec->next)
1892 {
1893 if (blockrec->type == FS_OPEN_FONT1)
1894 {
1895 bfont = (FSBlockedFontPtr) blockrec->data;
1896 if (bfont->pfont == pfont)
1897 fprintf (stderr__stderrp, "closing font which hasn't been opened\n");
1898 }
1899 }
1900 }
1901#endif
1902 (*pfont->unload_font) (pfont);
1903}
1904
1905static int
1906fs_read_glyphs(FontPathElementPtr fpe, FSBlockDataPtr blockrec)
1907{
1908 FSBlockedGlyphPtr bglyph = (FSBlockedGlyphPtr) blockrec->data;
1909 FSBlockedFontPtr bfont = (FSBlockedFontPtr) blockrec->data;
1910 FSFpePtr conn = (FSFpePtr) fpe->private;
1911 FontPtr pfont = bglyph->pfont;
1912 /* works for either blocked font
1913 or glyph rec... pfont is at
1914 the very beginning of both
1915 blockrec->data structures */
1916 FSFontDataPtr fsd = (FSFontDataPtr) (pfont->fpePrivate);
1917 FSFontPtr fsdata = (FSFontPtr) pfont->fontPrivate;
1918 FontInfoPtr pfi = &pfont->info;
1919 fsQueryXBitmaps16Reply *rep;
1920 char *buf;
1921 long bufleft; /* length of reply left to use */
1922 fsOffset32 *ppbits;
1923 fsOffset32 local_off;
1924 char *off_adr;
1925 pointer pbitmaps;
1926 char *bits, *allbits;
1927#ifdef DEBUG
1928 char *origallbits;
1929#endif
1930 int i,
1931 err;
1932 int nranges = 0;
1933 int ret;
1934 fsRange *nextrange = 0;
1935 unsigned long minchar, maxchar;
1936
1937 rep = (fsQueryXBitmaps16Reply *) fs_get_reply (conn, &ret);
1938 if (!rep || rep->type == FS_Error1 ||
1939 (rep->length < LENGTHOF(fsQueryXBitmaps16Reply)(20 >> 2)))
1940 {
1941 if (ret == FSIO_BLOCK0)
1942 return StillWorking81;
1943 if (rep)
1944 _fs_done_read (conn, rep->length << 2);
1945 err = AllocError80;
1946 _fs_reply_failed (rep, fsQueryXBitmaps16Reply, "<");
1947 goto bail;
1948 }
1949
1950 buf = (char *) rep;
1951 buf += SIZEOF (fsQueryXBitmaps16Reply)20;
1952
1953 bufleft = rep->length << 2;
1954 bufleft -= SIZEOF (fsQueryXBitmaps16Reply)20;
1955
1956 if ((bufleft / SIZEOF (fsOffset32)8) < rep->num_chars)
1957 {
1958#ifdef DEBUG
1959 fprintf(stderr__stderrp,
1960 "fsQueryXBitmaps16: num_chars (%d) > bufleft (%ld) / %d\n",
1961 rep->num_chars, bufleft, SIZEOF (fsOffset32)8);
1962#endif
1963 err = AllocError80;
1964 goto bail;
1965 }
1966 ppbits = (fsOffset32 *) buf;
1967 buf += SIZEOF (fsOffset32)8 * (rep->num_chars);
1968 bufleft -= SIZEOF (fsOffset32)8 * (rep->num_chars);
1969
1970 if (bufleft < rep->nbytes)
1971 {
1972#ifdef DEBUG
1973 fprintf(stderr__stderrp,
1974 "fsQueryXBitmaps16: nbytes (%d) > bufleft (%ld)\n",
1975 rep->nbytes, bufleft);
1976#endif
1977 err = AllocError80;
1978 goto bail;
1979 }
1980 pbitmaps = (pointer ) buf;
1981
1982 if (blockrec->type == FS_LOAD_GLYPHS2)
1983 {
1984 nranges = bglyph->num_expected_ranges;
1985 nextrange = bglyph->expected_ranges;
1986 }
1987
1988 /* place the incoming glyphs */
1989 if (nranges)
1990 {
1991 /* We're operating under the assumption that the ranges
1992 requested in the LoadGlyphs call were all legal for this
1993 font, and that individual ranges do not cover multiple
1994 rows... fs_build_range() is designed to ensure this. */
1995 minchar = (nextrange->min_char_high - pfi->firstRow) *
1996 (pfi->lastCol - pfi->firstCol + 1) +
1997 nextrange->min_char_low - pfi->firstCol;
1998 maxchar = (nextrange->max_char_high - pfi->firstRow) *
1999 (pfi->lastCol - pfi->firstCol + 1) +
2000 nextrange->max_char_low - pfi->firstCol;
2001 nextrange++;
2002 }
2003 else
2004 {
2005 minchar = 0;
2006 maxchar = rep->num_chars;
2007 }
2008
2009 off_adr = (char *)ppbits;
2010
2011 allbits = fs_alloc_glyphs (pfont, rep->nbytes);
2012
2013 if (!allbits)
2014 {
2015 err = AllocError80;
2016 goto bail;
2017 }
2018
2019#ifdef DEBUG
2020 origallbits = allbits;
2021 fprintf (stderr__stderrp, "Reading %d glyphs in %d bytes for %s\n",
2022 (int) rep->num_chars, (int) rep->nbytes, fsd->name);
2023#endif
2024
2025 for (i = 0; i < rep->num_chars; i++)
2026 {
2027 memcpy(&local_off, off_adr, SIZEOF(fsOffset32))__builtin___memcpy_chk (&local_off, off_adr, 8, __builtin_object_size
(&local_off, 0))
; /* align it */
2028 if (blockrec->type == FS_OPEN_FONT1 ||
2029 fsdata->encoding[minchar].bits == &_fs_glyph_requested)
2030 {
2031 /*
2032 * Broken X font server returns bits for missing characters
2033 * when font is padded
2034 */
2035 if (NONZEROMETRICS(&fsdata->encoding[minchar].metrics)((&fsdata->encoding[minchar].metrics)->leftSideBearing
|| (&fsdata->encoding[minchar].metrics)->rightSideBearing
|| (&fsdata->encoding[minchar].metrics)->ascent ||
(&fsdata->encoding[minchar].metrics)->descent || (
&fsdata->encoding[minchar].metrics)->characterWidth
)
)
2036 {
2037 if (local_off.length &&
2038 (local_off.position < rep->nbytes) &&
2039 (local_off.length <= (rep->nbytes - local_off.position)))
2040 {
2041 bits = allbits;
2042 allbits += local_off.length;
2043 memcpy(bits, (char *)pbitmaps + local_off.position,__builtin___memcpy_chk (bits, (char *)pbitmaps + local_off.position
, local_off.length, __builtin_object_size (bits, 0))
2044 local_off.length)__builtin___memcpy_chk (bits, (char *)pbitmaps + local_off.position
, local_off.length, __builtin_object_size (bits, 0))
;
2045 }
2046 else
2047 bits = &_fs_glyph_zero_length;
2048 }
2049 else
2050 bits = 0;
2051 if (fsdata->encoding[minchar].bits == &_fs_glyph_requested)
2052 fsd->glyphs_to_get--;
2053 fsdata->encoding[minchar].bits = bits;
2054 }
2055 if (minchar++ == maxchar)
2056 {
2057 if (!--nranges) break;
2058 minchar = (nextrange->min_char_high - pfi->firstRow) *
2059 (pfi->lastCol - pfi->firstCol + 1) +
2060 nextrange->min_char_low - pfi->firstCol;
2061 maxchar = (nextrange->max_char_high - pfi->firstRow) *
2062 (pfi->lastCol - pfi->firstCol + 1) +
2063 nextrange->max_char_low - pfi->firstCol;
2064 nextrange++;
2065 }
2066 off_adr += SIZEOF(fsOffset32)8;
2067 }
2068#ifdef DEBUG
2069 fprintf (stderr__stderrp, "Used %d bytes instead of %d\n",
2070 (int) (allbits - origallbits), (int) rep->nbytes);
2071#endif
2072
2073 if (blockrec->type == FS_OPEN_FONT1)
2074 {
2075 fsd->glyphs_to_get = 0;
2076 bfont->state = FS_DONE_REPLY4;
2077 }
2078 err = Successful85;
2079
2080bail:
2081 _fs_done_read (conn, rep->length << 2);
2082 return err;
2083}
2084
2085static int
2086fs_send_load_glyphs(pointer client, FontPtr pfont,
2087 int nranges, fsRange *ranges)
2088{
2089 FontPathElementPtr fpe = pfont->fpe;
2090 FSFpePtr conn = (FSFpePtr) fpe->private;
2091 FSBlockedGlyphPtr blockedglyph;
2092 fsQueryXBitmaps16Req req;
2093 FSBlockDataPtr blockrec;
2094
2095 if (conn->blockState & FS_GIVE_UP0x10)
2096 return BadCharRange87;
2097
2098 /* make a new block record, and add it to the end of the list */
2099 blockrec = fs_new_block_rec(fpe, client, FS_LOAD_GLYPHS2);
2100 if (!blockrec)
2101 return AllocError80;
2102 blockedglyph = (FSBlockedGlyphPtr) blockrec->data;
2103 blockedglyph->pfont = pfont;
2104 blockedglyph->num_expected_ranges = nranges;
2105 /* Assumption: it's our job to free ranges */
2106 blockedglyph->expected_ranges = ranges;
2107 blockedglyph->clients_depending = (FSClientsDependingPtr)0;
2108
2109 if (conn->blockState & (FS_BROKEN_CONNECTION0x04|FS_RECONNECTING0x40))
2110 {
2111 _fs_pending_reply (conn);
2112 return Suspended84;
2113 }
2114
2115 /* send the request */
2116 req.reqType = FS_QueryXBitmaps1620;
2117 req.fid = ((FSFontDataPtr) pfont->fpePrivate)->fontid;
2118 req.format = pfont->format;
2119 if (pfont->info.terminalFont)
2120 req.format = (req.format & ~(BitmapFormatImageRectMask(3L << 2))) |
2121 BitmapFormatImageRectMax(2L << 2);
2122 req.range = TRUE1;
2123 /* each range takes up 4 bytes */
2124 req.length = (SIZEOF(fsQueryXBitmaps16Req)16 >> 2) + nranges;
2125 req.num_ranges = nranges * 2; /* protocol wants count of fsChar2bs */
2126 _fs_add_req_log(conn, FS_QueryXBitmaps16)((conn)->current_seq++);
2127 _fs_write(conn, (char *) &req, SIZEOF(fsQueryXBitmaps16Req)16);
2128
2129 blockrec->sequenceNumber = conn->current_seq;
2130
2131 /* Send ranges to the server... pack into a char array by hand
2132 to avoid structure-packing portability problems and to
2133 handle swapping for version1 protocol */
2134 if (nranges)
2135 {
2136#define RANGE_BUFFER_SIZE64 64
2137#define RANGE_BUFFER_SIZE_MASK63 63
2138 int i;
2139 char range_buffer[RANGE_BUFFER_SIZE64 * 4];
2140 char *range_buffer_p;
2141
2142 range_buffer_p = range_buffer;
2143 for (i = 0; i < nranges;)
2144 {
2145 if (conn->fsMajorVersion > 1)
2146 {
2147 *range_buffer_p++ = ranges[i].min_char_high;
2148 *range_buffer_p++ = ranges[i].min_char_low;
2149 *range_buffer_p++ = ranges[i].max_char_high;
2150 *range_buffer_p++ = ranges[i].max_char_low;
2151 }
2152 else
2153 {
2154 *range_buffer_p++ = ranges[i].min_char_low;
2155 *range_buffer_p++ = ranges[i].min_char_high;
2156 *range_buffer_p++ = ranges[i].max_char_low;
2157 *range_buffer_p++ = ranges[i].max_char_high;
2158 }
2159
2160 if (!(++i & RANGE_BUFFER_SIZE_MASK63))
2161 {
2162 _fs_write(conn, range_buffer, RANGE_BUFFER_SIZE64 * 4);
2163 range_buffer_p = range_buffer;
2164 }
2165 }
2166 if (i &= RANGE_BUFFER_SIZE_MASK63)
2167 _fs_write(conn, range_buffer, i * 4);
2168 }
2169
2170 _fs_prepare_for_reply (conn);
2171 return Suspended84;
2172}
2173
2174static int
2175_fs_load_glyphs(pointer client, FontPtr pfont, Bool range_flag,
2176 unsigned int nchars, int item_size, unsigned char *data)
2177{
2178 FSFpePtr conn = (FSFpePtr) pfont->fpe->private;
2179 int nranges = 0;
2180 fsRange *ranges = NULL((void*)0);
2181 int res;
2182 FSBlockDataPtr blockrec;
2183 FSBlockedGlyphPtr blockedglyph;
2184 FSClientsDependingPtr *clients_depending = NULL((void*)0);
2185 int err;
2186
2187 /* see if the result is already there */
2188 for (blockrec = conn->blockedRequests; blockrec; blockrec = blockrec->next)
2189 {
2190 if (blockrec->type == FS_LOAD_GLYPHS2)
2191 {
2192 blockedglyph = (FSBlockedGlyphPtr) blockrec->data;
2193 if (blockedglyph->pfont == pfont)
2194 {
2195 /* Look for this request */
2196 if (blockrec->client == client)
2197 {
2198 err = blockrec->errcode;
2199 if (err == StillWorking81)
2200 return Suspended84;
2201 _fs_signal_clients_depending(&blockedglyph->clients_depending);
2202 _fs_remove_block_rec(conn, blockrec);
2203 return err;
2204 }
2205 /* We've found an existing LoadGlyphs blockrec for this
2206 font but for another client. Rather than build a
2207 blockrec for it now (which entails some complex
2208 maintenance), we'll add it to a queue of clients to
2209 be signalled when the existing LoadGlyphs is
2210 completed. */
2211 clients_depending = &blockedglyph->clients_depending;
2212 break;
2213 }
2214 }
2215 else if (blockrec->type == FS_OPEN_FONT1)
2216 {
2217 FSBlockedFontPtr bfont;
2218 bfont = (FSBlockedFontPtr) blockrec->data;
2219 if (bfont->pfont == pfont)
2220 {
2221 /*
2222 * An OpenFont is pending for this font, this must
2223 * be from a reopen attempt, so finish the open
2224 * attempt and retry the LoadGlyphs
2225 */
2226 if (blockrec->client == client)
2227 {
2228 err = blockrec->errcode;
2229 if (err == StillWorking81)
2230 return Suspended84;
2231
2232 _fs_signal_clients_depending(&bfont->clients_depending);
2233 _fs_remove_block_rec(conn, blockrec);
2234 if (err != Successful85)
2235 return err;
2236 break;
2237 }
2238 /* We've found an existing OpenFont blockrec for this
2239 font but for another client. Rather than build a
2240 blockrec for it now (which entails some complex
2241 maintenance), we'll add it to a queue of clients to
2242 be signalled when the existing OpenFont is
2243 completed. */
2244 if (blockrec->errcode == StillWorking81)
2245 {
2246 clients_depending = &bfont->clients_depending;
2247 break;
2248 }
2249 }
2250 }
2251 }
2252
2253 /*
2254 * see if the desired glyphs already exist, and return Successful if they
2255 * do, otherwise build up character range/character string
2256 */
2257 res = fs_build_range(pfont, range_flag, nchars, item_size, data,
2258 &nranges, &ranges);
2259
2260 switch (res)
2261 {
2262 case AccessDone0x400:
2263 return Successful85;
2264
2265 case Successful85:
2266 break;
2267
2268 default:
2269 return res;
2270 }
2271
2272 /*
2273 * If clients_depending is not null, this request must wait for
2274 * some prior request(s) to complete.
2275 */
2276 if (clients_depending)
2277 {
2278 /* Since we're not ready to send the load_glyphs request yet,
2279 clean up the damage (if any) caused by the fs_build_range()
2280 call. */
2281 if (nranges)
2282 {
2283 _fs_clean_aborted_loadglyphs(pfont, nranges, ranges);
2284 free(ranges);
2285 }
2286 return _fs_add_clients_depending(clients_depending, client);
2287 }
2288
2289 /*
2290 * If fsd->generation != conn->generation, the font has been closed
2291 * due to a lost connection. We will reopen it, which will result
2292 * in one of three things happening:
2293 * 1) The open will succeed and obtain the same font. Life
2294 * is wonderful.
2295 * 2) The open will fail. There is code above to recognize this
2296 * and flunk the LoadGlyphs request. The client might not be
2297 * thrilled.
2298 * 3) Worst case: the open will succeed but the font we open will
2299 * be different. The fs_read_query_info() procedure attempts
2300 * to detect this by comparing the existing metrics and
2301 * properties against those of the reopened font... if they
2302 * don't match, we flunk the reopen, which eventually results
2303 * in flunking the LoadGlyphs request. We could go a step
2304 * further and compare the extents, but this should be
2305 * sufficient.
2306 */
2307 if (((FSFontDataPtr)pfont->fpePrivate)->generation != conn->generation)
2308 {
2309 /* Since we're not ready to send the load_glyphs request yet,
2310 clean up the damage caused by the fs_build_range() call. */
2311 _fs_clean_aborted_loadglyphs(pfont, nranges, ranges);
2312 free(ranges);
2313
2314 /* Now try to reopen the font. */
2315 return fs_send_open_font(client, pfont->fpe,
2316 (Mask)FontReopen0x0020, (char *)0, 0,
2317 (fsBitmapFormat)0, (fsBitmapFormatMask)0,
2318 (XID)0, &pfont);
2319 }
2320
2321 return fs_send_load_glyphs(client, pfont, nranges, ranges);
2322}
2323
2324int
2325fs_load_all_glyphs(FontPtr pfont)
2326{
2327 int err;
2328 FSFpePtr conn = (FSFpePtr) pfont->fpe->private;
2329
2330 /*
2331 * The purpose of this procedure is to load all glyphs in the event
2332 * that we're dealing with someone who doesn't understand the finer
2333 * points of glyph caching... it is called from _fs_get_glyphs() if
2334 * the latter is called to get glyphs that have not yet been loaded.
2335 * We assume that the caller will not know how to handle a return
2336 * value of Suspended (usually the case for a GetGlyphs() caller),
2337 * so this procedure hangs around, freezing the server, for the
2338 * request to complete. This is an unpleasant kluge called to
2339 * perform an unpleasant job that, we hope, will never be required.
2340 */
2341
2342 while ((err = _fs_load_glyphs(__GetServerClient__libxfont____GetServerClient(), pfont, TRUE1, 0, 0, NULL((void*)0))) ==
2343 Suspended84)
2344 {
2345 if (fs_await_reply (conn) != FSIO_READY1)
2346 {
2347 /* Get rid of blockrec */
2348 fs_client_died(__GetServerClient__libxfont____GetServerClient(), pfont->fpe);
2349 err = BadCharRange87;
2350 break;
2351 }
2352 fs_read_reply (pfont->fpe, __GetServerClient__libxfont____GetServerClient());
2353 }
2354 return err;
2355}
2356
2357static int
2358fs_read_list(FontPathElementPtr fpe, FSBlockDataPtr blockrec)
2359{
2360 FSFpePtr conn = (FSFpePtr) fpe->private;
2361 FSBlockedListPtr blist = (FSBlockedListPtr) blockrec->data;
2362 fsListFontsReply *rep;
2363 char *data;
2364 long dataleft; /* length of reply left to use */
2365 int length,
2366 i,
2367 ret;
2368 int err;
2369
2370 rep = (fsListFontsReply *) fs_get_reply (conn, &ret);
2371 if (!rep || rep->type == FS_Error1 ||
2372 (rep->length < LENGTHOF(fsListFontsReply)(16 >> 2)))
2373 {
2374 if (ret == FSIO_BLOCK0)
2375 return StillWorking81;
2376 if (rep)
2377 _fs_done_read (conn, rep->length << 2);
2378 _fs_reply_failed (rep, fsListFontsReply, "<");
2379 return AllocError80;
2380 }
2381 data = (char *) rep + SIZEOF (fsListFontsReply)16;
2382 dataleft = (rep->length << 2) - SIZEOF (fsListFontsReply)16;
2383
2384 err = Successful85;
2385 /* copy data into FontPathRecord */
2386 for (i = 0; i < rep->nFonts; i++)
2387 {
2388 if (dataleft < 1)
2389 break;
2390 length = *(unsigned char *)data++;
2391 dataleft--; /* used length byte */
2392 if (length > dataleft) {
2393#ifdef DEBUG
2394 fprintf(stderr__stderrp,
2395 "fsListFonts: name length (%d) > dataleft (%ld)\n",
2396 length, dataleft);
2397#endif
2398 err = BadFontName83;
2399 break;
2400 }
2401 err = xfont2_add_font_names_name(blist->names, data, length);
2402 if (err != Successful85)
2403 break;
2404 data += length;
2405 dataleft -= length;
2406 }
2407 _fs_done_read (conn, rep->length << 2);
2408 return err;
2409}
2410
2411static int
2412fs_send_list_fonts(pointer client, FontPathElementPtr fpe, const char *pattern,
2413 int patlen, int maxnames, FontNamesPtr newnames)
2414{
2415 FSFpePtr conn = (FSFpePtr) fpe->private;
2416 FSBlockDataPtr blockrec;
2417 FSBlockedListPtr blockedlist;
2418 fsListFontsReq req;
2419
2420 if (conn->blockState & FS_GIVE_UP0x10)
2421 return BadFontName83;
2422
2423 /* make a new block record, and add it to the end of the list */
2424 blockrec = fs_new_block_rec(fpe, client, FS_LIST_FONTS3);
2425 if (!blockrec)
2426 return AllocError80;
2427 blockedlist = (FSBlockedListPtr) blockrec->data;
2428 blockedlist->names = newnames;
2429
2430 if (conn->blockState & (FS_BROKEN_CONNECTION0x04 | FS_RECONNECTING0x40))
2431 {
2432 _fs_pending_reply (conn);
2433 return Suspended84;
2434 }
2435
2436 _fs_client_access (conn, client, FALSE0);
2437 _fs_client_resolution(conn);
2438
2439 /* send the request */
2440 req.reqType = FS_ListFonts13;
2441 req.pad = 0;
2442 req.maxNames = maxnames;
2443 req.nbytes = patlen;
2444 req.length = (SIZEOF(fsListFontsReq)12 + patlen + 3) >> 2;
2445 _fs_add_req_log(conn, FS_ListFonts)((conn)->current_seq++);
2446 _fs_write(conn, (char *) &req, SIZEOF(fsListFontsReq)12);
2447 _fs_write_pad(conn, (char *) pattern, patlen);
2448
2449 blockrec->sequenceNumber = conn->current_seq;
2450
2451#ifdef NCD
2452 if (configData.ExtendedFontDiags) {
2453 char buf[256];
2454
2455 memcpy(buf, pattern, MIN(256, patlen))__builtin___memcpy_chk (buf, pattern, (((256)<(patlen))?(256
):(patlen)), __builtin_object_size (buf, 0))
;
2456 buf[MIN(256, patlen)(((256)<(patlen))?(256):(patlen))] = '\0';
2457 printf("Listing fonts on pattern \"%s\" from font server \"%s\"\n",
2458 buf, fpe->name);
2459 }
2460#endif
2461
2462 _fs_prepare_for_reply (conn);
2463 return Suspended84;
2464}
2465
2466static int
2467fs_list_fonts(pointer client, FontPathElementPtr fpe,
2468 const char *pattern, int patlen, int maxnames, FontNamesPtr newnames)
2469{
2470 FSFpePtr conn = (FSFpePtr) fpe->private;
2471 FSBlockDataPtr blockrec;
2472 int err;
2473
2474 /* see if the result is already there */
2475 for (blockrec = conn->blockedRequests; blockrec; blockrec = blockrec->next)
2476 {
2477 if (blockrec->type == FS_LIST_FONTS3 && blockrec->client == client)
2478 {
2479 err = blockrec->errcode;
2480 if (err == StillWorking81)
2481 return Suspended84;
2482 _fs_remove_block_rec(conn, blockrec);
2483 return err;
2484 }
2485 }
2486
2487 /* didn't find waiting record, so send a new one */
2488 return fs_send_list_fonts(client, fpe, pattern, patlen, maxnames, newnames);
2489}
2490
2491/*
2492 * Read a single list info reply and restart for the next reply
2493 */
2494static int
2495fs_read_list_info(FontPathElementPtr fpe, FSBlockDataPtr blockrec)
2496{
2497 FSBlockedListInfoPtr binfo = (FSBlockedListInfoPtr) blockrec->data;
2498 fsListFontsWithXInfoReply *rep;
2499 char *buf;
2500 long bufleft;
2501 FSFpePtr conn = (FSFpePtr) fpe->private;
2502 fsPropInfo *pi;
2503 fsPropOffset *po;
2504 pointer pd;
2505 int ret;
2506 int err;
2507
2508 /* clean up anything from the last trip */
2509 _fs_free_props (&binfo->info);
2510
2511 rep = (fsListFontsWithXInfoReply *) fs_get_reply (conn, &ret);
37
Calling 'fs_get_reply'
44
Returning from 'fs_get_reply'
45
Value assigned to 'rep'
2512 if (!rep || rep->type == FS_Error1 ||
46
Assuming 'rep' is null
2513 ((rep->nameLength != 0) &&
2514 (rep->length < LENGTHOF(fsListFontsWithXInfoReply)((12 + 40) >> 2))))
2515 {
2516 if (ret == FSIO_BLOCK0)
47
Taking false branch
2517 return StillWorking81;
2518 binfo->status = FS_LFWI_FINISHED2;
2519 err = AllocError80;
2520 _fs_reply_failed (rep, fsListFontsWithXInfoReply, "<");
2521 goto done;
48
Control jumps to line 2632
2522 }
2523 /*
2524 * Normal termination -- the list ends with a name of length 0
2525 */
2526 if (rep->nameLength == 0)
2527 {
2528#ifdef DEBUG
2529 fprintf (stderr__stderrp, "fs_read_list_info done\n");
2530#endif
2531 binfo->status = FS_LFWI_FINISHED2;
2532 err = BadFontName83;
2533 goto done;
2534 }
2535
2536 buf = (char *) rep + SIZEOF (fsListFontsWithXInfoReply)(12 + 40);
2537 bufleft = (rep->length << 2) - SIZEOF (fsListFontsWithXInfoReply)(12 + 40);
2538
2539 /*
2540 * The original FS implementation didn't match
2541 * the spec, version 1 was respecified to match the FS.
2542 * Version 2 matches the original intent
2543 */
2544 if (conn->fsMajorVersion <= 1)
2545 {
2546 if (rep->nameLength > bufleft) {
2547#ifdef DEBUG
2548 fprintf(stderr__stderrp,
2549 "fsListFontsWithXInfo: name length (%d) > bufleft (%ld)\n",
2550 (int) rep->nameLength, bufleft);
2551#endif
2552 err = AllocError80;
2553 goto done;
2554 }
2555 /* binfo->name is a 256 char array, rep->nameLength is a CARD8 */
2556 memcpy (binfo->name, buf, rep->nameLength)__builtin___memcpy_chk (binfo->name, buf, rep->nameLength
, __builtin_object_size (binfo->name, 0))
;
2557 buf += _fs_pad_length (rep->nameLength);
2558 bufleft -= _fs_pad_length (rep->nameLength);
2559 }
2560 pi = (fsPropInfo *) buf;
2561 if (SIZEOF (fsPropInfo)8 > bufleft) {
2562#ifdef DEBUG
2563 fprintf(stderr__stderrp,
2564 "fsListFontsWithXInfo: PropInfo length (%d) > bufleft (%ld)\n",
2565 (int) SIZEOF (fsPropInfo)8, bufleft);
2566#endif
2567 err = AllocError80;
2568 goto done;
2569 }
2570 bufleft -= SIZEOF (fsPropInfo)8;
2571 buf += SIZEOF (fsPropInfo)8;
2572 po = (fsPropOffset *) buf;
2573 if (pi->num_offsets > (bufleft / SIZEOF (fsPropOffset)20)) {
2574#ifdef DEBUG
2575 fprintf(stderr__stderrp,
2576 "fsListFontsWithXInfo: offset length (%d * %d) > bufleft (%ld)\n",
2577 pi->num_offsets, (int) SIZEOF (fsPropOffset)20, bufleft);
2578#endif
2579 err = AllocError80;
2580 goto done;
2581 }
2582 bufleft -= pi->num_offsets * SIZEOF (fsPropOffset)20;
2583 buf += pi->num_offsets * SIZEOF (fsPropOffset)20;
2584 pd = (pointer) buf;
2585 if (pi->data_len > bufleft) {
2586#ifdef DEBUG
2587 fprintf(stderr__stderrp,
2588 "fsListFontsWithXInfo: data length (%d) > bufleft (%ld)\n",
2589 pi->data_len, bufleft);
2590#endif
2591 err = AllocError80;
2592 goto done;
2593 }
2594 bufleft -= pi->data_len;
2595 buf += pi->data_len;
2596 if (conn->fsMajorVersion > 1)
2597 {
2598 if (rep->nameLength > bufleft) {
2599#ifdef DEBUG
2600 fprintf(stderr__stderrp,
2601 "fsListFontsWithXInfo: name length (%d) > bufleft (%ld)\n",
2602 (int) rep->nameLength, bufleft);
2603#endif
2604 err = AllocError80;
2605 goto done;
2606 }
2607 /* binfo->name is a 256 char array, rep->nameLength is a CARD8 */
2608 memcpy (binfo->name, buf, rep->nameLength)__builtin___memcpy_chk (binfo->name, buf, rep->nameLength
, __builtin_object_size (binfo->name, 0))
;
2609 buf += _fs_pad_length (rep->nameLength);
2610 bufleft -= _fs_pad_length (rep->nameLength);
2611 }
2612
2613#ifdef DEBUG
2614 binfo->name[rep->nameLength] = '\0';
2615 fprintf (stderr__stderrp, "fs_read_list_info %s\n", binfo->name);
2616#endif
2617 err = _fs_convert_lfwi_reply(conn, &binfo->info, rep, pi, po, pd);
2618 if (err != Successful85)
2619 {
2620 binfo->status = FS_LFWI_FINISHED2;
2621 goto done;
2622 }
2623 binfo->namelen = rep->nameLength;
2624 binfo->remaining = rep->nReplies;
2625
2626 binfo->status = FS_LFWI_REPLY1;
2627
2628 /* disable this font server until we've processed this response */
2629 _fs_unmark_block (conn, FS_COMPLETE_REPLY0x20);
2630 conn_stop_listening(conn);
2631done:
2632 _fs_done_read (conn, rep->length << 2);
49
Access to field 'length' results in a dereference of a null pointer (loaded from variable 'rep')
2633 return err;
2634}
2635
2636/* ARGSUSED */
2637static int
2638fs_start_list_with_info(pointer client, FontPathElementPtr fpe,
2639 const char *pattern, int len, int maxnames, pointer *pdata)
2640{
2641 FSFpePtr conn = (FSFpePtr) fpe->private;
2642 FSBlockDataPtr blockrec;
2643 FSBlockedListInfoPtr binfo;
2644 fsListFontsWithXInfoReq req;
2645
2646 if (conn->blockState & FS_GIVE_UP0x10)
2647 return BadFontName83;
2648
2649 /* make a new block record, and add it to the end of the list */
2650 blockrec = fs_new_block_rec(fpe, client, FS_LIST_WITH_INFO4);
2651 if (!blockrec)
2652 return AllocError80;
2653
2654 binfo = (FSBlockedListInfoPtr) blockrec->data;
2655 bzero((char *) binfo, sizeof(FSBlockedListInfoRec))__builtin___memset_chk ((char *) binfo, 0, sizeof(FSBlockedListInfoRec
), __builtin_object_size ((char *) binfo, 0))
;
2656 binfo->status = FS_LFWI_WAITING0;
2657
2658 if (conn->blockState & (FS_BROKEN_CONNECTION0x04 | FS_RECONNECTING0x40))
2659 {
2660 _fs_pending_reply (conn);
2661 return Suspended84;
2662 }
2663
2664 _fs_client_access (conn, client, FALSE0);
2665 _fs_client_resolution(conn);
2666
2667 /* send the request */
2668 req.reqType = FS_ListFontsWithXInfo14;
2669 req.pad = 0;
2670 req.maxNames = maxnames;
2671 req.nbytes = len;
2672 req.length = (SIZEOF(fsListFontsWithXInfoReq)12 + len + 3) >> 2;
2673 _fs_add_req_log(conn, FS_ListFontsWithXInfo)((conn)->current_seq++);
2674 (void) _fs_write(conn, (char *) &req, SIZEOF(fsListFontsWithXInfoReq)12);
2675 (void) _fs_write_pad(conn, pattern, len);
2676
2677 blockrec->sequenceNumber = conn->current_seq;
2678
2679#ifdef NCD
2680 if (configData.ExtendedFontDiags) {
2681 char buf[256];
2682
2683 memcpy(buf, pattern, MIN(256, len))__builtin___memcpy_chk (buf, pattern, (((256)<(len))?(256)
:(len)), __builtin_object_size (buf, 0))
;
2684 buf[MIN(256, len)(((256)<(len))?(256):(len))] = '\0';
2685 printf("Listing fonts with info on pattern \"%s\" from font server \"%s\"\n",
2686 buf, fpe->name);
2687 }
2688#endif
2689
2690 _fs_prepare_for_reply (conn);
2691 return Successful85;
2692}
2693
2694/* ARGSUSED */
2695static int
2696fs_next_list_with_info(pointer client, FontPathElementPtr fpe,
2697 char **namep, int *namelenp,
2698 FontInfoPtr *pFontInfo, int *numFonts,
2699 pointer private)
2700{
2701 FSFpePtr conn = (FSFpePtr) fpe->private;
2702 FSBlockDataPtr blockrec;
2703 FSBlockedListInfoPtr binfo;
2704 int err;
2705
2706 /* see if the result is already there */
2707 for (blockrec = conn->blockedRequests; blockrec; blockrec = blockrec->next)
2708 if (blockrec->type == FS_LIST_WITH_INFO4 && blockrec->client == client)
2709 break;
2710
2711 if (!blockrec)
2712 {
2713 /* The only good reason for not finding a blockrec would be if
2714 disconnect/reconnect to the font server wiped it out and the
2715 code that called us didn't do the right thing to create
2716 another one. Under those circumstances, we need to return an
2717 error to prevent that code from attempting to interpret the
2718 information we don't return. */
2719 return BadFontName83;
2720 }
2721
2722 binfo = (FSBlockedListInfoPtr) blockrec->data;
2723
2724 if (binfo->status == FS_LFWI_WAITING0)
2725 return Suspended84;
2726
2727 *namep = binfo->name;
2728 *namelenp = binfo->namelen;
2729 *pFontInfo = &binfo->info;
2730 *numFonts = binfo->remaining;
2731
2732 /* Restart reply processing from this font server */
2733 conn_start_listening(conn);
2734 if (fs_reply_ready (conn))
2735 _fs_mark_block (conn, FS_COMPLETE_REPLY0x20);
2736
2737 err = blockrec->errcode;
2738 switch (binfo->status) {
2739 case FS_LFWI_FINISHED2:
2740 _fs_remove_block_rec(conn, blockrec);
2741 break;
2742 case FS_LFWI_REPLY1:
2743 binfo->status = FS_LFWI_WAITING0;
2744 blockrec->errcode = StillWorking81;
2745 conn->blockedReplyTime = GetTimeInMillis__libxfont__GetTimeInMillis () + FontServerRequestTimeout;
2746 _fs_mark_block (conn, FS_PENDING_REPLY0x08);
2747 break;
2748 }
2749
2750 return err;
2751}
2752
2753/*
2754 * Called when client exits
2755 */
2756
2757static void
2758fs_client_died(pointer client, FontPathElementPtr fpe)
2759{
2760 FSFpePtr conn = (FSFpePtr) fpe->private;
2761 FSBlockDataPtr blockrec,
2762 depending;
2763 FSClientPtr *prev, cur;
2764 fsFreeACReq freeac;
2765
2766 for (prev = &conn->clients; (cur = *prev); prev = &cur->next)
2767 {
2768 if (cur->client == client) {
2769 freeac.reqType = FS_FreeAC9;
2770 freeac.pad = 0;
2771 freeac.id = cur->acid;
2772 freeac.length = sizeof (fsFreeACReq) >> 2;
2773 _fs_add_req_log(conn, FS_FreeAC)((conn)->current_seq++);
2774 _fs_write (conn, (char *) &freeac, sizeof (fsFreeACReq));
2775 *prev = cur->next;
2776 free (cur);
2777 break;
2778 }
2779 }
2780 /* find a pending requests */
2781 for (blockrec = conn->blockedRequests; blockrec; blockrec = blockrec->next)
2782 if (blockrec->client == client)
2783 break;
2784
2785 if (!blockrec)
2786 return;
2787
2788 /* replace the client pointers in this block rec with the chained one */
2789 if ((depending = blockrec->depending))
2790 {
2791 blockrec->client = depending->client;
2792 blockrec->depending = depending->depending;
2793 blockrec = depending;
2794 }
2795 fs_abort_blockrec(conn, blockrec);
2796}
2797
2798static void
2799_fs_client_access (FSFpePtr conn, pointer client, Bool sync)
2800{
2801 FSClientPtr *prev, cur;
2802 fsCreateACReq crac;
2803 fsSetAuthorizationReq setac;
2804 char *authorizations;
2805 int authlen;
2806 Bool new_cur = FALSE0;
2807 char padding[4] = { 0, 0, 0, 0 };
2808
2809#ifdef DEBUG
2810 if (conn->blockState & (FS_RECONNECTING0x40|FS_BROKEN_CONNECTION0x04))
2811 {
2812 fprintf (stderr__stderrp, "Sending requests without a connection\n");
2813 }
2814#endif
2815 for (prev = &conn->clients; (cur = *prev); prev = &cur->next)
2816 {
2817 if (cur->client == client)
2818 {
2819 if (prev != &conn->clients)
2820 {
2821 *prev = cur->next;
2822 cur->next = conn->clients;
2823 conn->clients = cur;
2824 }
2825 break;
2826 }
2827 }
2828 if (!cur)
2829 {
2830 cur = malloc (sizeof (FSClientRec));
2831 if (!cur)
2832 return;
2833 cur->client = client;
2834 cur->next = conn->clients;
2835 conn->clients = cur;
2836 cur->acid = GetNewFontClientID__libxfont__GetNewFontClientID ();
2837 new_cur = TRUE1;
2838 }
2839 if (new_cur || cur->auth_generation != client_auth_generation__libxfont__client_auth_generation(client))
2840 {
2841 if (!new_cur)
2842 {
2843 fsFreeACReq freeac;
2844 freeac.reqType = FS_FreeAC9;
2845 freeac.pad = 0;
2846 freeac.id = cur->acid;
2847 freeac.length = sizeof (fsFreeACReq) >> 2;
2848 _fs_add_req_log(conn, FS_FreeAC)((conn)->current_seq++);
2849 _fs_write (conn, (char *) &freeac, sizeof (fsFreeACReq));
2850 }
2851 crac.reqType = FS_CreateAC8;
2852 crac.num_auths = set_font_authorizations__libxfont__set_font_authorizations(&authorizations, &authlen,
2853 client);
2854 /* Work around bug in xfs versions up through modular release 1.0.8
2855 which rejects CreateAC packets with num_auths = 0 & authlen < 4 */
2856 if (crac.num_auths == 0) {
2857 authorizations = padding;
2858 authlen = 4;
2859 }
2860 crac.length = (sizeof (fsCreateACReq) + authlen) >> 2;
2861 crac.acid = cur->acid;
2862 _fs_add_req_log(conn, FS_CreateAC)((conn)->current_seq++);
2863 _fs_write(conn, (char *) &crac, sizeof (fsCreateACReq));
2864 _fs_write_pad(conn, authorizations, authlen);
2865 /* ignore reply; we don't even care about it */
2866 conn->curacid = 0;
2867 cur->auth_generation = client_auth_generation__libxfont__client_auth_generation(client);
2868 }
2869 if (conn->curacid != cur->acid)
2870 {
2871 setac.reqType = FS_SetAuthorization10;
2872 setac.pad = 0;
2873 setac.length = sizeof (fsSetAuthorizationReq) >> 2;
2874 setac.id = cur->acid;
2875 _fs_add_req_log(conn, FS_SetAuthorization)((conn)->current_seq++);
2876 _fs_write(conn, (char *) &setac, sizeof (fsSetAuthorizationReq));
2877 conn->curacid = cur->acid;
2878 }
2879}
2880
2881/*
2882 * Poll a pending connect
2883 */
2884
2885static int
2886_fs_check_connect (FSFpePtr conn)
2887{
2888 int ret;
2889
2890 ret = _fs_poll_connect (conn->trans_conn, 0);
2891 switch (ret) {
2892 case FSIO_READY1:
2893 conn->fs_fd = _FontTransGetConnectionNumber (conn->trans_conn);
2894 conn_start_listening(conn);
2895 break;
2896 case FSIO_BLOCK0:
2897 break;
2898 }
2899 return ret;
2900}
2901
2902/*
2903 * Return an FSIO status while waiting for the completed connection
2904 * reply to arrive
2905 */
2906
2907static fsConnSetup *
2908_fs_get_conn_setup (FSFpePtr conn, int *error, int *setup_len)
2909{
2910 int ret;
2911 char *data;
2912 int headlen;
2913 int len;
2914 fsConnSetup *setup;
2915 fsConnSetupAccept *accept;
2916
2917 ret = _fs_start_read (conn, SIZEOF (fsConnSetup)12, &data);
2918 if (ret != FSIO_READY1)
2919 {
2920 *error = ret;
2921 return 0;
2922 }
2923
2924 setup = (fsConnSetup *) data;
2925 if (setup->major_version > FS_PROTOCOL2)
2926 {
2927 *error = FSIO_ERROR-1;
2928 return 0;
2929 }
2930
2931 headlen = (SIZEOF (fsConnSetup)12 +
2932 (setup->alternate_len << 2) +
2933 (setup->auth_len << 2));
2934 /* On anything but Success, no extra data is sent */
2935 if (setup->status != AuthSuccess0)
2936 {
2937 len = headlen;
2938 }
2939 else
2940 {
2941 ret = _fs_start_read (conn, headlen + SIZEOF (fsConnSetupAccept)12, &data);
2942 if (ret != FSIO_READY1)
2943 {
2944 *error = ret;
2945 return 0;
2946 }
2947 setup = (fsConnSetup *) data;
2948 accept = (fsConnSetupAccept *) (data + headlen);
2949 len = headlen + (accept->length << 2);
2950 }
2951 ret = _fs_start_read (conn, len, &data);
2952 if (ret != FSIO_READY1)
2953 {
2954 *error = ret;
2955 return 0;
2956 }
2957 *setup_len = len;
2958 return (fsConnSetup *) data;
2959}
2960
2961static int
2962_fs_send_conn_client_prefix (FSFpePtr conn)
2963{
2964 fsConnClientPrefix req;
2965 int endian;
2966 int ret;
2967
2968 /* send setup prefix */
2969 endian = 1;
2970 if (*(char *) &endian)
2971 req.byteOrder = 'l';
2972 else
2973 req.byteOrder = 'B';
2974
2975 req.major_version = FS_PROTOCOL2;
2976 req.minor_version = FS_PROTOCOL_MINOR0;
2977
2978/* XXX add some auth info here */
2979 req.num_auths = 0;
2980 req.auth_len = 0;
2981 ret = _fs_write (conn, (char *) &req, SIZEOF (fsConnClientPrefix)8);
2982 if (ret != FSIO_READY1)
2983 return FSIO_ERROR-1;
2984 conn->blockedConnectTime = GetTimeInMillis__libxfont__GetTimeInMillis () + FontServerRequestTimeout;
2985 return ret;
2986}
2987
2988static int
2989_fs_recv_conn_setup (FSFpePtr conn)
2990{
2991 int ret = FSIO_ERROR-1;
2992 fsConnSetup *setup;
2993 FSFpeAltPtr alts;
2994 unsigned int i, alt_len;
2995 int setup_len;
2996 char *alt_save, *alt_names;
2997
2998 setup = _fs_get_conn_setup (conn, &ret, &setup_len);
2999 if (!setup)
3000 return ret;
3001 conn->current_seq = 0;
3002 conn->fsMajorVersion = setup->major_version;
3003 /*
3004 * Create an alternate list from the initial server, but
3005 * don't chain looking for alternates.
3006 */
3007 if (conn->alternate == 0)
3008 {
3009 /*
3010 * free any existing alternates list, allowing the list to
3011 * be updated
3012 */
3013 if (conn->alts)
3014 {
3015 free (conn->alts);
3016 conn->alts = 0;
3017 conn->numAlts = 0;
3018 }
3019 if (setup->num_alternates)
3020 {
3021 size_t alt_name_len = setup->alternate_len << 2;
3022 alts = malloc (setup->num_alternates * sizeof (FSFpeAltRec) +
3023 alt_name_len);
3024 if (alts)
3025 {
3026 alt_names = (char *) (setup + 1);
3027 alt_save = (char *) (alts + setup->num_alternates);
3028 for (i = 0; i < setup->num_alternates; i++)
3029 {
3030 alts[i].subset = alt_names[0];
3031 alt_len = alt_names[1];
3032 if (alt_len >= alt_name_len) {
3033 /*
3034 * Length is longer than setup->alternate_len
3035 * told us to allocate room for, assume entire
3036 * alternate list is corrupted.
3037 */
3038#ifdef DEBUG
3039 fprintf (stderr__stderrp,
3040 "invalid alt list (length %lx >= %lx)\n",
3041 (long) alt_len, (long) alt_name_len);
3042#endif
3043 free(alts);
3044 return FSIO_ERROR-1;
3045 }
3046 alts[i].name = alt_save;
3047 memcpy (alt_save, alt_names + 2, alt_len)__builtin___memcpy_chk (alt_save, alt_names + 2, alt_len, __builtin_object_size
(alt_save, 0))
;
3048 alt_save[alt_len] = '\0';
3049 alt_save += alt_len + 1;
3050 alt_name_len -= alt_len + 1;
3051 alt_names += _fs_pad_length (alt_len + 2);
3052 }
3053 conn->numAlts = setup->num_alternates;
3054 conn->alts = alts;
3055 }
3056 }
3057 }
3058 _fs_done_read (conn, setup_len);
3059 if (setup->status != AuthSuccess0)
3060 return FSIO_ERROR-1;
3061 return FSIO_READY1;
3062}
3063
3064static int
3065_fs_open_server (FSFpePtr conn)
3066{
3067 int ret;
3068 char *servername;
3069
3070 if (conn->alternate == 0)
3071 servername = conn->servername;
3072 else
3073 servername = conn->alts[conn->alternate-1].name;
3074 conn->trans_conn = _fs_connect (servername, &ret);
3075 conn->blockedConnectTime = GetTimeInMillis__libxfont__GetTimeInMillis () + FS_RECONNECT_WAIT5000;
3076 return ret;
3077}
3078
3079static char *
3080_fs_catalog_name (char *servername)
3081{
3082 char *sp;
3083
3084 sp = strchr (servername, '/');
3085 if (!sp)
3086 return 0;
3087 return strrchr (sp + 1, '/');
3088}
3089
3090static int
3091_fs_send_init_packets (FSFpePtr conn)
3092{
3093 fsSetResolutionReq srreq;
3094 fsSetCataloguesReq screq;
3095 int num_cats,
3096 clen;
3097 char *catalogues;
3098 char *cat;
3099 char len;
3100 char *end;
3101 int num_res;
3102 FontResolutionPtr res;
3103
3104#define CATALOGUE_SEP'+' '+'
3105
3106 res = GetClientResolutions__libxfont__GetClientResolutions(&num_res);
3107 if (num_res)
3108 {
3109 srreq.reqType = FS_SetResolution11;
3110 srreq.num_resolutions = num_res;
3111 srreq.length = (SIZEOF(fsSetResolutionReq)4 +
3112 (num_res * SIZEOF(fsResolution)6) + 3) >> 2;
3113
3114 _fs_add_req_log(conn, FS_SetResolution)((conn)->current_seq++);
3115 if (_fs_write(conn, (char *) &srreq, SIZEOF(fsSetResolutionReq)4) != FSIO_READY1)
3116 return FSIO_ERROR-1;
3117 if (_fs_write_pad(conn, (char *) res, (num_res * SIZEOF(fsResolution)6)) != FSIO_READY1)
3118 return FSIO_ERROR-1;
3119 }
3120
3121 catalogues = 0;
3122 if (conn->alternate != 0)
3123 catalogues = _fs_catalog_name (conn->alts[conn->alternate-1].name);
3124 if (!catalogues)
3125 catalogues = _fs_catalog_name (conn->servername);
3126
3127 if (!catalogues)
3128 {
3129 conn->has_catalogues = FALSE0;
3130 return FSIO_READY1;
3131 }
3132 conn->has_catalogues = TRUE1;
3133
3134 /* turn cats into counted list */
3135 catalogues++;
3136
3137 cat = catalogues;
3138 num_cats = 0;
3139 clen = 0;
3140 while (*cat)
3141 {
3142 num_cats++;
3143 end = strchr(cat, CATALOGUE_SEP'+');
3144 if (!end)
3145 end = cat + strlen (cat);
3146 clen += (end - cat) + 1; /* length byte + string */
3147 cat = end;
3148 }
3149
3150 screq.reqType = FS_SetCatalogues4;
3151 screq.num_catalogues = num_cats;
3152 screq.length = (SIZEOF(fsSetCataloguesReq)4 + clen + 3) >> 2;
3153
3154 _fs_add_req_log(conn, FS_SetCatalogues)((conn)->current_seq++);
3155 if (_fs_write(conn, (char *) &screq, SIZEOF(fsSetCataloguesReq)4) != FSIO_READY1)
3156 return FSIO_ERROR-1;
3157
3158 while (*cat)
3159 {
3160 num_cats++;
3161 end = strchr(cat, CATALOGUE_SEP'+');
3162 if (!end)
3163 end = cat + strlen (cat);
3164 len = end - cat;
3165 if (_fs_write (conn, &len, 1) != FSIO_READY1)
3166 return FSIO_ERROR-1;
3167 if (_fs_write (conn, cat, (int) len) != FSIO_READY1)
3168 return FSIO_ERROR-1;
3169 cat = end;
3170 }
3171
3172 if (_fs_write (conn, "....", _fs_pad_length (clen) - clen) != FSIO_READY1)
3173 return FSIO_ERROR-1;
3174
3175 return FSIO_READY1;
3176}
3177
3178static int
3179_fs_send_cat_sync (FSFpePtr conn)
3180{
3181 fsListCataloguesReq lcreq;
3182
3183 /*
3184 * now sync up with the font server, to see if an error was generated
3185 * by a bogus catalogue
3186 */
3187 lcreq.reqType = FS_ListCatalogues3;
3188 lcreq.data = 0;
3189 lcreq.length = (SIZEOF(fsListCataloguesReq)12) >> 2;
3190 lcreq.maxNames = 0;
3191 lcreq.nbytes = 0;
3192 lcreq.pad2 = 0;
3193 _fs_add_req_log(conn, FS_SetCatalogues)((conn)->current_seq++);
3194 if (_fs_write(conn, (char *) &lcreq, SIZEOF(fsListCataloguesReq)12) != FSIO_READY1)
3195 return FSIO_ERROR-1;
3196 conn->blockedConnectTime = GetTimeInMillis__libxfont__GetTimeInMillis () + FontServerRequestTimeout;
3197 return FSIO_READY1;
3198}
3199
3200static int
3201_fs_recv_cat_sync (FSFpePtr conn)
3202{
3203 fsGenericReply *reply;
3204 fsError *error;
3205 int err;
3206 int ret;
3207
3208 reply = fs_get_reply (conn, &err);
3209 if (!reply)
3210 return err;
3211
3212 ret = FSIO_READY1;
3213 if (reply->type == FS_Error1)
3214 {
3215 error = (fsError *) reply;
3216 if (error->major_opcode == FS_SetCatalogues4)
3217 ret = FSIO_ERROR-1;
3218 }
3219 _fs_done_read (conn, reply->length << 2);
3220 return ret;
3221}
3222
3223static void
3224_fs_close_server (FSFpePtr conn)
3225{
3226 _fs_unmark_block (conn, FS_PENDING_WRITE0x01|FS_BROKEN_WRITE0x02|FS_COMPLETE_REPLY0x20|FS_BROKEN_CONNECTION0x04);
3227 if (conn->trans_conn)
3228 {
3229 _FontTransClose (conn->trans_conn);
3230 conn->trans_conn = 0;
3231 _fs_io_reinit (conn);
3232 }
3233 if (conn->fs_fd >= 0)
3234 {
3235 conn_stop_listening(conn);
3236 conn->fs_fd = -1;
3237 }
3238 conn->fs_conn_state = FS_CONN_UNCONNECTED0;
3239}
3240
3241static int
3242_fs_do_setup_connection (FSFpePtr conn)
3243{
3244 int ret;
3245
3246 do
3247 {
3248#ifdef DEBUG
3249 fprintf (stderr__stderrp, "fs_do_setup_connection state %d\n", conn->fs_conn_state);
3250#endif
3251 switch (conn->fs_conn_state) {
3252 case FS_CONN_UNCONNECTED0:
3253 ret = _fs_open_server (conn);
3254 if (ret == FSIO_BLOCK0)
3255 conn->fs_conn_state = FS_CONN_CONNECTING1;
3256 break;
3257 case FS_CONN_CONNECTING1:
3258 ret = _fs_check_connect (conn);
3259 break;
3260 case FS_CONN_CONNECTED2:
3261 ret = _fs_send_conn_client_prefix (conn);
3262 break;
3263 case FS_CONN_SENT_PREFIX3:
3264 ret = _fs_recv_conn_setup (conn);
3265 break;
3266 case FS_CONN_RECV_INIT4:
3267 ret = _fs_send_init_packets (conn);
3268 if (conn->has_catalogues)
3269 ret = _fs_send_cat_sync (conn);
3270 break;
3271 case FS_CONN_SENT_CAT5:
3272 if (conn->has_catalogues)
3273 ret = _fs_recv_cat_sync (conn);
3274 else
3275 ret = FSIO_READY1;
3276 break;
3277 default:
3278 ret = FSIO_READY1;
3279 break;
3280 }
3281 switch (ret) {
3282 case FSIO_READY1:
3283 if (conn->fs_conn_state < FS_CONN_RUNNING6)
3284 conn->fs_conn_state++;
3285 break;
3286 case FSIO_BLOCK0:
3287 if (TimeCmp (GetTimeInMillis (), <, conn->blockedConnectTime)((int) ((__libxfont__GetTimeInMillis ()) - (conn->blockedConnectTime
)) < 0)
)
3288 break;
3289 ret = FSIO_ERROR-1;
3290 /* fall through... */
3291 case FSIO_ERROR-1:
3292 _fs_close_server (conn);
3293 /*
3294 * Try the next alternate
3295 */
3296 if (conn->alternate < conn->numAlts)
3297 {
3298 conn->alternate++;
3299 ret = FSIO_READY1;
3300 }
3301 else
3302 conn->alternate = 0;
3303 break;
3304 }
3305 } while (conn->fs_conn_state != FS_CONN_RUNNING6 && ret == FSIO_READY1);
3306 if (ret == FSIO_READY1)
3307 conn->generation = ++generationCount;
3308 return ret;
3309}
3310
3311static int
3312_fs_wait_connect (FSFpePtr conn)
3313{
3314 int ret;
3315
3316 for (;;)
3317 {
3318 ret = _fs_do_setup_connection (conn);
3319 if (ret != FSIO_BLOCK0)
3320 break;
3321 if (conn->fs_conn_state <= FS_CONN_CONNECTING1)
3322 ret = _fs_poll_connect (conn->trans_conn, 1000);
3323 else
3324 ret = _fs_wait_for_readable (conn, 1000);
3325 if (ret == FSIO_ERROR-1)
3326 break;
3327 }
3328 return ret;
3329}
3330
3331/*
3332 * Poll a connection in the process of reconnecting
3333 */
3334static void
3335_fs_check_reconnect (FSFpePtr conn)
3336{
3337 int ret;
3338
3339 ret = _fs_do_setup_connection (conn);
3340 switch (ret) {
3341 case FSIO_READY1:
3342 _fs_unmark_block (conn, FS_RECONNECTING0x40|FS_GIVE_UP0x10);
3343 _fs_restart_connection (conn);
3344 break;
3345 case FSIO_BLOCK0:
3346 break;
3347 case FSIO_ERROR-1:
3348 conn->brokenConnectionTime = GetTimeInMillis__libxfont__GetTimeInMillis () + FS_RECONNECT_POLL1000;
3349 break;
3350 }
3351}
3352
3353/*
3354 * Start the reconnection process
3355 */
3356static void
3357_fs_start_reconnect (FSFpePtr conn)
3358{
3359 if (conn->blockState & FS_RECONNECTING0x40)
3360 return;
3361 conn->alternate = 0;
3362 _fs_mark_block (conn, FS_RECONNECTING0x40);
3363 _fs_unmark_block (conn, FS_BROKEN_CONNECTION0x04);
3364 _fs_check_reconnect (conn);
3365}
3366
3367
3368static FSFpePtr
3369_fs_init_conn (const char *servername, FontPathElementPtr fpe)
3370{
3371 FSFpePtr conn;
3372
3373 conn = calloc (1, sizeof (FSFpeRec) + strlen (servername) + 1);
3374 if (!conn)
3375 return 0;
3376 if (!_fs_io_init (conn))
3377 {
3378 free (conn);
3379 return 0;
3380 }
3381 conn->servername = (char *) (conn + 1);
3382 conn->fs_conn_state = FS_CONN_UNCONNECTED0;
3383 conn->fs_fd = -1;
3384 conn->fpe = fpe;
3385 strcpy (conn->servername, servername)__builtin___strcpy_chk (conn->servername, servername, __builtin_object_size
(conn->servername, 2 > 1 ? 1 : 0))
;
3386 return conn;
3387}
3388
3389static void
3390_fs_free_conn (FSFpePtr conn)
3391{
3392 _fs_close_server (conn);
3393 _fs_io_fini (conn);
3394 if (conn->alts)
3395 free (conn->alts);
3396 free (conn);
3397}
3398
3399/*
3400 * called at server init time
3401 */
3402
3403static const xfont2_fpe_funcs_rec fs_fpe_funcs = {
3404 .version = XFONT2_FPE_FUNCS_VERSION1,
3405 .name_check = fs_name_check,
3406 .init_fpe = fs_init_fpe,
3407 .free_fpe = fs_free_fpe,
3408 .reset_fpe = fs_reset_fpe,
3409 .open_font = fs_open_font,
3410 .close_font = fs_close_font,
3411 .list_fonts = fs_list_fonts,
3412 .start_list_fonts_with_info = fs_start_list_with_info,
3413 .list_next_font_with_info = fs_next_list_with_info,
3414 .wakeup_fpe = fs_wakeup,
3415 .client_died = fs_client_died,
3416 .load_glyphs = _fs_load_glyphs,
3417 .start_list_fonts_and_aliases = (StartLaFunc) 0,
3418 .list_next_font_or_alias = (NextLaFunc) 0,
3419 .set_path_hook = (SetPathFunc) 0
3420};
3421
3422void
3423fs_register_fpe_functions(void)
3424{
3425 register_fpe_funcs(&fs_fpe_funcs);
3426}