mirror of OpenBSD xenocara tree github.com/openbsd/xenocara
openbsd
at master 970 lines 26 kB view raw
1/* 2 * Copyright 1990 Network Computing Devices; 3 * Portions Copyright 1987 by Digital Equipment Corporation 4 * 5 * Permission to use, copy, modify, distribute, and sell this software 6 * and its documentation for any purpose is hereby granted without fee, 7 * provided that the above copyright notice appear in all copies and 8 * that both that copyright notice and this permission notice appear 9 * in supporting documentation, and that the names of Network Computing 10 * Devices or Digital not be used in advertising or publicity pertaining 11 * to distribution of the software without specific, written prior 12 * permission. Network Computing Devices or Digital make no representations 13 * about the suitability of this software for any purpose. It is provided 14 * "as is" without express or implied warranty. 15 * 16 * NETWORK COMPUTING DEVICES AND DIGITAL DISCLAIM ALL WARRANTIES WITH 17 * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF 18 * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL NETWORK COMPUTING DEVICES 19 * OR DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES 20 * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 21 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 22 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 23 * SOFTWARE. 24 */ 25 26/* 27 28Copyright 1987, 1994, 1998 The Open Group 29 30Permission to use, copy, modify, distribute, and sell this software and its 31documentation for any purpose is hereby granted without fee, provided that 32the above copyright notice appear in all copies and that both that 33copyright notice and this permission notice appear in supporting 34documentation. 35 36The above copyright notice and this permission notice shall be included in 37all copies or substantial portions of the Software. 38 39THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 40IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 41FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 42OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 43AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 44CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 45 46Except as contained in this notice, the name of The Open Group shall not be 47used in advertising or otherwise to promote the sale, use or other dealings 48in this Software without prior written authorization from The Open Group. 49 50*/ 51 52/* 53 * FSlibInt.c - Internal support routines for the C subroutine 54 * interface library (FSlib). 55 */ 56#ifdef HAVE_CONFIG_H 57#include <config.h> 58#endif 59#include <stdio.h> 60#include "FSlibint.h" 61#include <X11/Xtrans/Xtransint.h> 62#include <X11/Xos.h> 63 64static void _EatData32 ( FSServer *svr, unsigned long n ); 65static const char * _SysErrorMsg ( int n ); 66 67/* check for both EAGAIN and EWOULDBLOCK, because some supposedly POSIX 68 * systems are broken and return EWOULDBLOCK when they should return EAGAIN 69 * 70 * Solaris defines EWOULDBLOCK to be EAGAIN, so don't need to check twice 71 * for it. 72 */ 73#ifdef WIN32 74#define ETEST() (WSAGetLastError() == WSAEWOULDBLOCK) 75#else 76#if defined(EAGAIN) && defined(EWOULDBLOCK) && (EAGAIN != EWOULDBLOCK) 77#define ETEST() (errno == EAGAIN || errno == EWOULDBLOCK) 78#else 79#ifdef EAGAIN 80#define ETEST() (errno == EAGAIN) 81#else 82#define ETEST() (errno == EWOULDBLOCK) 83#endif 84#endif 85#endif 86#ifdef WIN32 87#define ECHECK(err) (WSAGetLastError() == err) 88#define ESET(val) WSASetLastError(val) 89#else 90#ifdef ISC 91#define ECHECK(err) ((errno == err) || ETEST()) 92#else 93#define ECHECK(err) (errno == err) 94#endif 95#define ESET(val) errno = val 96#endif 97 98/* 99 * The following routines are internal routines used by FSlib for protocol 100 * packet transmission and reception. 101 * 102 * FSIOError(FSServer *) will be called if any sort of system call error occurs. 103 * This is assumed to be a fatal condition, i.e., FSIOError should not return. 104 * 105 * FSError(FSServer *, FSErrorEvent *) will be called whenever an FS_Error event is 106 * received. This is not assumed to be a fatal condition, i.e., it is 107 * acceptable for this procedure to return. However, FSError should NOT 108 * perform any operations (directly or indirectly) on the DISPLAY. 109 * 110 * Routines declared with a return type of 'Status' return 0 on failure, 111 * and non 0 on success. Routines with no declared return type don't 112 * return anything. Whenever possible routines that create objects return 113 * the object they have created. 114 */ 115 116_FSQEvent *_FSqfree = NULL; /* NULL _FSQEvent. */ 117 118static int padlength[4] = {0, 3, 2, 1}; 119 120 /* 121 * lookup table for adding padding bytes to data that is read from or written 122 * to the FS socket. 123 */ 124 125static fsReq _dummy_request = { 126 0, 0, 0 127}; 128 129/* 130 * _FSFlush - Flush the FS request buffer. If the buffer is empty, no 131 * action is taken. This routine correctly handles incremental writes. 132 * This routine may have to be reworked if int < long. 133 */ 134void 135_FSFlush(register FSServer *svr) 136{ 137 register long size, 138 todo; 139 register int write_stat; 140 register char *bufindex; 141 142 size = todo = svr->bufptr - svr->buffer; 143 bufindex = svr->bufptr = svr->buffer; 144 /* 145 * While write has not written the entire buffer, keep looping until the 146 * entire buffer is written. bufindex will be incremented and size 147 * decremented as buffer is written out. 148 */ 149 while (size) { 150 ESET(0); 151 write_stat = _FSTransWrite(svr->trans_conn, bufindex, (int) todo); 152 if (write_stat >= 0) { 153 size -= write_stat; 154 todo = size; 155 bufindex += write_stat; 156 } else if (ETEST()) { 157 _FSWaitForWritable(svr); 158#ifdef SUNSYSV 159 } else if (ECHECK(0)) { 160 _FSWaitForWritable(svr); 161#endif 162 163#ifdef EMSGSIZE 164 } else if (ECHECK(EMSGSIZE)) { 165 if (todo > 1) 166 todo >>= 1; 167 else 168 _FSWaitForWritable(svr); 169#endif 170 } else { 171 /* Write failed! */ 172 /* errno set by write system call. */ 173 (*_FSIOErrorFunction) (svr); 174 } 175 } 176 svr->last_req = (char *) &_dummy_request; 177} 178 179/* _FSReadEvents - Flush the output queue, 180 * then read as many events as possible (but at least 1) and enqueue them 181 */ 182void 183_FSReadEvents(register FSServer *svr) 184{ 185 char buf[BUFSIZE]; 186 BytesReadable_t pend_not_register; /* because can't "&" a register 187 * variable */ 188 register BytesReadable_t pend; 189 register fsEvent *ev; 190 Bool not_yet_flushed = True; 191 192 do { 193 /* find out how much data can be read */ 194 if (_FSTransBytesReadable(svr->trans_conn, &pend_not_register) < 0) 195 (*_FSIOErrorFunction) (svr); 196 pend = pend_not_register; 197 198 /* 199 * must read at least one fsEvent; if none is pending, then we'll just 200 * flush and block waiting for it 201 */ 202 if (pend < SIZEOF(fsEvent)) { 203 pend = SIZEOF(fsEvent); 204 /* don't flush until we block the first time */ 205 if (not_yet_flushed) { 206 int qlen = svr->qlen; 207 208 _FSFlush(svr); 209 if (qlen != svr->qlen) 210 return; 211 not_yet_flushed = False; 212 } 213 } 214 /* but we won't read more than the max buffer size */ 215 if (pend > BUFSIZE) 216 pend = BUFSIZE; 217 218 /* round down to an integral number of XReps */ 219 pend = (pend / SIZEOF(fsEvent)) * SIZEOF(fsEvent); 220 221 _FSRead(svr, buf, (long)pend); 222 223 /* no space between comma and type or else macro will die */ 224 STARTITERATE(ev, fsEvent, buf, (pend > 0), 225 pend -= SIZEOF(fsEvent)) { 226 if (ev->type == FS_Error) 227 _FSError(svr, (fsError *) ev); 228 else /* it's an event packet; enqueue it */ 229 _FSEnq(svr, ev); 230 } 231 ENDITERATE 232 } while (svr->head == NULL); 233} 234 235/* 236 * _FSRead - Read bytes from the socket taking into account incomplete 237 * reads. This routine may have to be reworked if int < long. 238 */ 239void 240_FSRead( 241 register FSServer *svr, 242 register char *data, 243 register long size) 244{ 245 register long bytes_read; 246#if defined(SVR4) && defined(i386) 247 int num_failed_reads = 0; 248#endif 249 250 if (size == 0) 251 return; 252 ESET(0); 253 /* 254 * For SVR4 with a unix-domain connection, ETEST() after selecting 255 * readable means the server has died. To do this here, we look for 256 * two consecutive reads returning ETEST(). 257 */ 258 while ((bytes_read = _FSTransRead(svr->trans_conn, data, (int) size)) 259 != size) { 260 261 if (bytes_read > 0) { 262 size -= bytes_read; 263 data += bytes_read; 264#if defined(SVR4) && defined(i386) 265 num_failed_reads = 0; 266#endif 267 } 268 else if (ETEST()) { 269 _FSWaitForReadable(svr); 270#if defined(SVR4) && defined(i386) 271 num_failed_reads++; 272 if (num_failed_reads > 1) { 273 ESET(EPIPE); 274 (*_FSIOErrorFunction) (svr); 275 } 276#endif 277 ESET(0); 278 } 279#ifdef SUNSYSV 280 else if (ECHECK(0)) { 281 _FSWaitForReadable(svr); 282 } 283#endif 284 285 else if (bytes_read == 0) { 286 /* Read failed because of end of file! */ 287 ESET(EPIPE); 288 (*_FSIOErrorFunction) (svr); 289 } else { /* bytes_read is less than 0; presumably -1 */ 290 /* If it's a system call interrupt, it's not an error. */ 291 if (!ECHECK(EINTR)) 292 (*_FSIOErrorFunction) (svr); 293#if defined(SVR4) && defined(i386) 294 else 295 num_failed_reads = 0; 296#endif 297 } 298 } 299} 300 301 302/* 303 * _FSReadPad - Read bytes from the socket taking into account incomplete 304 * reads. If the number of bytes is not 0 mod 32, read additional pad 305 * bytes. This routine may have to be reworked if int < long. 306 */ 307void 308_FSReadPad( 309 register FSServer *svr, 310 register char *data, 311 register long size) 312{ 313 register long bytes_read; 314 struct iovec iov[2]; 315 char pad[3]; 316 317 if (size == 0) 318 return; 319 iov[0].iov_len = size; 320 iov[0].iov_base = data; 321 /* 322 * The following hack is used to provide 32 bit long-word aligned padding. 323 * The [1] vector is of length 0, 1, 2, or 3, whatever is needed. 324 */ 325 326 iov[1].iov_len = padlength[size & 3]; 327 iov[1].iov_base = pad; 328 size += iov[1].iov_len; 329 330 ESET(0); 331 while ((bytes_read = readv(svr->trans_conn->fd, iov, 2)) != size) { 332 333 if (bytes_read > 0) { 334 size -= bytes_read; 335 if (iov[0].iov_len < bytes_read) { 336 int pad_bytes_read = bytes_read - iov[0].iov_len; 337 iov[1].iov_len -= pad_bytes_read; 338 iov[1].iov_base = 339 (char *)iov[1].iov_base + pad_bytes_read; 340 iov[0].iov_len = 0; 341 } else { 342 iov[0].iov_len -= bytes_read; 343 iov[0].iov_base = (char *)iov[0].iov_base + bytes_read; 344 } 345 } 346 else if (ETEST()) { 347 _FSWaitForReadable(svr); 348 ESET(0); 349 } 350#ifdef SUNSYSV 351 else if (ECHECK(0)) { 352 _FSWaitForReadable(svr); 353 } 354#endif 355 356 else if (bytes_read == 0) { 357 /* Read failed because of end of file! */ 358 ESET(EPIPE); 359 (*_FSIOErrorFunction) (svr); 360 } else { /* bytes_read is less than 0; presumably -1 */ 361 /* If it's a system call interrupt, it's not an error. */ 362 if (!ECHECK(EINTR)) 363 (*_FSIOErrorFunction) (svr); 364 } 365 } 366} 367 368/* 369 * _FSSend - Flush the buffer and send the client data. 32 bit word aligned 370 * transmission is used, if size is not 0 mod 4, extra bytes are transmitted. 371 * This routine may have to be reworked if int < long; 372 */ 373void 374_FSSend( 375 register FSServer *svr, 376 const char *data, 377 register long size) 378{ 379 struct iovec iov[3]; 380 static char pad[3] = {0, 0, 0}; 381 382 long skip = 0; 383 long svrbufsize = (svr->bufptr - svr->buffer); 384 long padsize = padlength[size & 3]; 385 long total = svrbufsize + size + padsize; 386 long todo = total; 387 388 /* 389 * There are 3 pieces that may need to be written out: 390 * 391 * o whatever is in the display buffer o the data passed in by the user o 392 * any padding needed to 32bit align the whole mess 393 * 394 * This loop looks at all 3 pieces each time through. It uses skip to figure 395 * out whether or not a given piece is needed. 396 */ 397 while (total) { 398 long before = skip; /* amount of whole thing written */ 399 long remain = todo; /* amount to try this time, <= total */ 400 int i = 0; 401 long len; 402 403 /* 404 * You could be very general here and have "in" and "out" iovecs and 405 * write a loop without using a macro, but what the heck. This 406 * translates to: 407 * 408 * how much of this piece is new? if more new then we are trying this 409 * time, clamp if nothing new then bump down amount already written, 410 * for next piece else put new stuff in iovec, will need all of next 411 * piece 412 * 413 * Note that todo had better be at least 1 or else we'll end up writing 0 414 * iovecs. 415 */ 416#define InsertIOV(pointer, length) \ 417 len = (length) - before; \ 418 if (len > remain) \ 419 len = remain; \ 420 if (len <= 0) { \ 421 before = (-len); \ 422 } else { \ 423 iov[i].iov_len = len; \ 424 iov[i].iov_base = (pointer) + before; \ 425 i++; \ 426 remain -= len; \ 427 before = 0; \ 428 } 429 430 InsertIOV(svr->buffer, svrbufsize) 431 InsertIOV((char *)data, size) 432 InsertIOV(pad, padsize) 433 434 ESET(0); 435 if ((len = _FSTransWritev(svr->trans_conn, iov, i)) >= 0) { 436 skip += len; 437 total -= len; 438 todo = total; 439 } else if (ETEST()) { 440 _FSWaitForWritable(svr); 441#ifdef SUNSYSV 442 } else if (ECHECK(0)) { 443 _FSWaitForWritable(svr); 444#endif 445 446#ifdef EMSGSIZE 447 } else if (ECHECK(EMSGSIZE)) { 448 if (todo > 1) 449 todo >>= 1; 450 else 451 _FSWaitForWritable(svr); 452#endif 453 } else { 454 (*_FSIOErrorFunction) (svr); 455 } 456 } 457 458 svr->bufptr = svr->buffer; 459 svr->last_req = (char *) &_dummy_request; 460} 461 462#ifdef undef 463/* 464 * _FSAllocID - normal resource ID allocation routine. A client 465 * can roll their own and instantiate it if they want, but must 466 * follow the rules. 467 */ 468FSID 469_FSAllocID(register FSServer *svr) 470{ 471 return (svr->resource_base + (svr->resource_id++ << svr->resource_shift)); 472} 473 474#endif 475 476/* 477 * The hard part about this is that we only get 16 bits from a reply. Well, 478 * then, we have three values that will march along, with the following 479 * invariant: 480 * svr->last_request_read <= rep->sequenceNumber <= svr->request 481 * The right choice for rep->sequenceNumber is the largest that 482 * still meets these constraints. 483 */ 484 485unsigned long 486_FSSetLastRequestRead( 487 register FSServer *svr, 488 register fsGenericReply *rep) 489{ 490 register unsigned long newseq, 491 lastseq; 492 493 newseq = (svr->last_request_read & ~((unsigned long) 0xffff)) | 494 rep->sequenceNumber; 495 lastseq = svr->last_request_read; 496 while (newseq < lastseq) { 497 newseq += 0x10000; 498 if (newseq > svr->request) { 499 (void) fprintf(stderr, 500 "FSlib: sequence lost (0x%lx > 0x%lx) in reply type 0x%x!\n", 501 newseq, svr->request, 502 (unsigned int) rep->type); 503 newseq -= 0x10000; 504 break; 505 } 506 } 507 508 svr->last_request_read = newseq; 509 return (newseq); 510} 511 512/* 513 * _FSReply - Wait for a reply packet and copy its contents into the 514 * specified rep. Mean while we must handle error and event packets that 515 * we may encounter. 516 */ 517Status 518_FSReply( 519 register FSServer *svr, 520 register fsReply *rep, 521 int extra, /* number of 32-bit words expected after the 522 * reply */ 523 Bool discard)/* should I discard data following "extra" 524 * words? */ 525{ 526 /* 527 * Pull out the serial number now, so that (currently illegal) requests 528 * generated by an error handler don't confuse us. 529 */ 530 unsigned long cur_request = svr->request; 531 long rem_length; 532 533 _FSFlush(svr); 534 while (1) { 535 _FSRead(svr, (char *) rep, (long) SIZEOF(fsReply)); 536 switch ((int) rep->generic.type) { 537 538 case FS_Reply: 539 /* 540 * Reply received. Fast update for synchronous replies, but deal 541 * with multiple outstanding replies. 542 */ 543 if (rep->generic.sequenceNumber == (cur_request & 0xffff)) 544 svr->last_request_read = cur_request; 545 else 546 (void) _FSSetLastRequestRead(svr, &rep->generic); 547 rem_length = rep->generic.length - (SIZEOF(fsReply) >> 2); 548 if (rem_length < 0) rem_length = 0; 549 if (extra == 0) { 550 if (discard && rem_length) 551 /* unexpectedly long reply! */ 552 _EatData32(svr, rem_length); 553 return (1); 554 } 555 if (extra == rem_length) { 556 /* 557 * Read the extra data into storage immediately following the 558 * GenericReply structure. 559 */ 560 _FSRead(svr, (char *) NEXTPTR(rep, fsReply), ((long) extra) << 2); 561 return (1); 562 } 563 if (extra < rem_length) { 564 /* Actual reply is longer than "extra" */ 565 _FSRead(svr, (char *) NEXTPTR(rep, fsReply), ((long) extra) << 2); 566 if (discard) 567 _EatData32(svr, rem_length - extra); 568 return (1); 569 } 570 /* 571 * if we get here, then extra > rem_length -- meaning we 572 * read a reply that's shorter than we expected. This is an 573 * error, but we still need to figure out how to handle it... 574 */ 575 _FSRead(svr, (char *) NEXTPTR(rep, fsReply), rem_length << 2); 576 (*_FSIOErrorFunction) (svr); 577 return (0); 578 579 case FS_Error: 580 { 581 register _FSExtension *ext; 582 register Bool ret = False; 583 int ret_code; 584 fsError err; 585 unsigned long serial; 586 long err_data; 587 588 /* copy in the part we already read off the wire */ 589 memcpy(&err, rep, SIZEOF(fsReply)); 590 /* read the rest of the error */ 591 _FSRead(svr, (char *) &err + SIZEOF(fsReply), 592 (long) (SIZEOF(fsError) - SIZEOF(fsReply))); 593 serial = _FSSetLastRequestRead(svr, (fsGenericReply *) rep); 594 if (serial == cur_request) 595 /* do not die on certain failures */ 596 switch ((int) err.request) { 597 /* suck in any extra error info */ 598 case FSBadResolution: 599 case FSBadLength: 600 case FSBadIDChoice: 601 case FSBadRange: 602 case FSBadFont: 603 case FSBadFormat: 604 _FSRead(svr, (char *) &err_data, 4); 605 break; 606 case FSBadAccessContext: 607 _FSRead(svr, (char *) &err_data, 4); 608 return 0; 609 case FSBadAlloc: 610 return (0); 611 /* 612 * we better see if there is an extension who may want 613 * to suppress the error. 614 */ 615 default: 616 ext = svr->ext_procs; 617 while (ext) { 618 if (ext->error != NULL) 619 ret = (*ext->error) 620 (svr, &err, &ext->codes, &ret_code); 621 ext = ext->next; 622 } 623 if (ret) 624 return (ret_code); 625 break; 626 } 627 _FSError(svr, &err); 628 if (serial == cur_request) 629 return (0); 630 } 631 break; 632 default: 633 _FSEnq(svr, (fsEvent *) rep); 634 break; 635 } 636 } 637} 638 639 640/* Read and discard "n" 8-bit bytes of data */ 641 642void 643_FSEatData( 644 FSServer *svr, 645 register unsigned long n) 646{ 647#define SCRATCHSIZE 2048 648 char buf[SCRATCHSIZE]; 649 650 while (n > 0) { 651 register long bytes_read = (n > SCRATCHSIZE) ? SCRATCHSIZE : n; 652 653 _FSRead(svr, buf, bytes_read); 654 n -= bytes_read; 655 } 656#undef SCRATCHSIZE 657} 658 659 660/* Read and discard "n" 32-bit words. */ 661 662static void 663_EatData32( 664 FSServer *svr, 665 unsigned long n) 666{ 667 _FSEatData(svr, n << 2); 668} 669 670 671/* 672 * _FSEnq - Place event packets on the display's queue. 673 * note that no squishing of move events in V11, since there 674 * is pointer motion hints.... 675 */ 676void 677_FSEnq( 678 register FSServer *svr, 679 register fsEvent *event) 680{ 681 register _FSQEvent *qelt; 682 683/*NOSTRICT*/ 684 if ((qelt = _FSqfree) != NULL) { 685 /* If _FSqfree is non-NULL do this, else malloc a new one. */ 686 _FSqfree = qelt->next; 687 } else if ((qelt = FSmalloc(sizeof(_FSQEvent))) == NULL) { 688 /* Malloc call failed! */ 689 ESET(ENOMEM); 690 (*_FSIOErrorFunction) (svr); 691 } 692 qelt->next = NULL; 693 /* go call through display to find proper event reformatter */ 694 if ((*svr->event_vec[event->type & 0177]) (svr, &qelt->event, event)) { 695 if (svr->tail) 696 svr->tail->next = qelt; 697 else 698 svr->head = qelt; 699 700 svr->tail = qelt; 701 svr->qlen++; 702 } else { 703 /* ignored, or stashed away for many-to-one compression */ 704 qelt->next = _FSqfree; 705 _FSqfree = qelt; 706 } 707} 708 709/* 710 * EventToWire in separate file that is often not needed. 711 */ 712 713/*ARGSUSED*/ 714Bool 715_FSUnknownWireEvent( 716 register FSServer *svr, /* pointer to display structure */ 717 register FSEvent *re, /* pointer to where event should be 718 * reformatted */ 719 register fsEvent *event) /* wire protocol event */ 720{ 721 722#ifdef notdef 723 (void) fprintf(stderr, 724 "FSlib: unhandled wire event! event number = %d, display = %x\n.", 725 event->type, svr); 726#endif 727 728 return (False); 729} 730 731/*ARGSUSED*/ 732Status 733_FSUnknownNativeEvent( 734 register FSServer *svr, /* pointer to display structure */ 735 register FSEvent *re, /* pointer to where event should be 736 * reformatted */ 737 register fsEvent *event) /* wire protocol event */ 738{ 739 740#ifdef notdef 741 (void) fprintf(stderr, 742 "FSlib: unhandled native event! event number = %d, display = %x\n.", 743 re->type, svr); 744#endif 745 746 return (0); 747} 748 749static const char * 750_SysErrorMsg(int n) 751{ 752 char *s = strerror(n); 753 754 return (s ? s : "no such error"); 755} 756 757#ifdef __SUNPRO_C 758/* prevent "Function has no return statement" error for _FSDefaultIOError */ 759#pragma does_not_return(exit) 760#endif 761 762/* 763 * _FSDefaultIOError - Default fatal system error reporting routine. Called 764 * when an X internal system error is encountered. 765 */ 766int 767_FSDefaultIOError(FSServer *svr) 768{ 769 (void) fprintf(stderr, 770 "FSIO: fatal IO error %d (%s) on font server \"%s\"\r\n", 771#ifdef WIN32 772 WSAGetLastError(), strerror(WSAGetLastError()), 773#else 774 775 errno, _SysErrorMsg(errno), 776#endif 777 FSServerString(svr) ? FSServerString(svr) : ""); 778 (void) fprintf(stderr, 779 " after %lu requests (%lu known processed) with %d events remaining.\r\n", 780 FSNextRequest(svr) - 1, FSLastKnownRequestProcessed(svr), 781 FSQLength(svr)); 782 783 if (ECHECK(EPIPE)) { 784 (void) fprintf(stderr, 785 " The connection was probably broken by a server shutdown.\r\n"); 786 } 787 exit(1); 788 /* NOTREACHED */ 789} 790 791/* 792 * _FSError - Default non-fatal error reporting routine. Called when an 793 * FS_Error packet is encountered in the input stream. 794 */ 795int 796_FSError( 797 FSServer *svr, 798 fsError *rep) 799{ 800 FSErrorEvent event; 801 802 /* 803 * FS_Error packet encountered! We need to unpack the error before giving 804 * it to the user. 805 */ 806 807 event.server = svr; 808 event.type = FS_Error; 809 event.serial = _FSSetLastRequestRead(svr, (fsGenericReply *) rep); 810 event.error_code = rep->request; 811 event.request_code = rep->major_opcode; 812 event.minor_code = rep->minor_opcode; 813 if (_FSErrorFunction != NULL) { 814 return ((*_FSErrorFunction) (svr, &event)); 815 } 816 exit(1); 817 /* NOTREACHED */ 818} 819 820#ifdef __clang__ 821#pragma clang diagnostic push 822#pragma clang diagnostic ignored "-Wformat-nonliteral" // We know better 823#endif 824 825int 826_FSPrintDefaultError( 827 FSServer *svr, 828 FSErrorEvent *event, 829 FILE *fp) 830{ 831 char buffer[BUFSIZ]; 832 char mesg[BUFSIZ]; 833 char number[32]; 834 const char *mtype = "FSlibMessage"; 835 register _FSExtension *ext = (_FSExtension *) NULL; 836 837 (void) FSGetErrorText(svr, event->error_code, buffer, BUFSIZ); 838 (void) FSGetErrorDatabaseText(svr, mtype, "FSError", "FS Error", mesg, 839 BUFSIZ); 840 (void) fprintf(fp, "%s: %s\n ", mesg, buffer); 841 (void) FSGetErrorDatabaseText(svr, mtype, "MajorCode", 842 "Request Major code %d", mesg, BUFSIZ); 843 (void) fprintf(fp, mesg, event->request_code); 844 if (event->request_code < 128) { 845 snprintf(number, sizeof(number), "%d", event->request_code); 846 (void) FSGetErrorDatabaseText(svr, "FSRequest", number, "", buffer, 847 BUFSIZ); 848 } else { 849 for (ext = svr->ext_procs; 850 ext && (ext->codes.major_opcode != event->request_code); 851 ext = ext->next); 852 if (ext) 853#ifdef HAVE_STRLCPY 854 strlcpy(buffer, ext->name, sizeof(buffer)); 855#else 856 strcpy(buffer, ext->name); 857#endif 858 else 859 buffer[0] = '\0'; 860 } 861 (void) fprintf(fp, " (%s)\n ", buffer); 862 (void) FSGetErrorDatabaseText(svr, mtype, "MinorCode", 863 "Request Minor code %d", mesg, BUFSIZ); 864 (void) fprintf(fp, mesg, event->minor_code); 865 if (ext) { 866 snprintf(mesg, sizeof(mesg), "%s.%d", ext->name, event->minor_code); 867 (void) FSGetErrorDatabaseText(svr, "FSRequest", mesg, "", buffer, 868 BUFSIZ); 869 (void) fprintf(fp, " (%s)", buffer); 870 } 871 fputs("\n ", fp); 872 (void) FSGetErrorDatabaseText(svr, mtype, "ResourceID", "ResourceID 0x%x", 873 mesg, BUFSIZ); 874 (void) fprintf(fp, mesg, event->resourceid); 875 fputs("\n ", fp); 876 (void) FSGetErrorDatabaseText(svr, mtype, "ErrorSerial", "Error Serial #%d", 877 mesg, BUFSIZ); 878 (void) fprintf(fp, mesg, event->serial); 879 fputs("\n ", fp); 880 (void) FSGetErrorDatabaseText(svr, mtype, "CurrentSerial", 881 "Current Serial #%d", mesg, BUFSIZ); 882 (void) fprintf(fp, mesg, svr->request); 883 fputs("\n", fp); 884 return 1; 885} 886 887#ifdef __clang__ 888#pragma clang diagnostic pop 889#endif 890 891int 892_FSDefaultError( 893 FSServer *svr, 894 FSErrorEvent *event) 895{ 896 if (_FSPrintDefaultError(svr, event, stderr) == 0) 897 return 0; 898 exit(1); 899 /* NOTREACHED */ 900} 901 902 903FSIOErrorHandler _FSIOErrorFunction = _FSDefaultIOError; 904FSErrorHandler _FSErrorFunction = _FSDefaultError; 905 906int 907FSFree(char *data) 908{ 909 FSfree(data); 910 return 1; 911} 912 913unsigned char * 914FSMalloc(unsigned size) 915{ 916 return (unsigned char *) FSmalloc(size); 917} 918 919#ifdef DataRoutineIsProcedure 920void 921Data( 922 FSServer *svr, 923 char *data, 924 long len) 925{ 926 if (svr->bufptr + (len) <= svr->bufmax) { 927 memmove(svr->bufptr, data, len); 928 svr->bufptr += ((len) + 3) & ~3; 929 } else { 930 _FSSend(svr, data, len); 931 } 932} 933 934#endif /* DataRoutineIsProcedure */ 935 936 937/* 938 * _FSFreeQ - free the queue of events, called by XCloseServer when there are 939 * no more displays left on the display list 940 */ 941 942void 943_FSFreeQ(void) 944{ 945 register _FSQEvent *qelt = _FSqfree; 946 947 while (qelt) { 948 register _FSQEvent *qnext = qelt->next; 949 950 FSfree(qelt); 951 qelt = qnext; 952 } 953 _FSqfree = NULL; 954 return; 955} 956 957#ifndef _FSANYSET 958/* 959 * This is not always a macro. 960 */ 961_FSANYSET(long *src) 962{ 963 int i; 964 965 for (i=0; i<MSKCNT; i++) 966 if (src[ i ]) 967 return (1); 968 return (0); 969} 970#endif