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