home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / X / mit / fonts / lib / fs / FSlibInt.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-07-22  |  32.5 KB  |  1,355 lines

  1. /* $XConsortium: FSlibInt.c,v 1.9 91/07/22 11:29:28 rws Exp $ */
  2.  
  3. /* @(#)FSlibInt.c    3.3    91/05/02
  4.  * Copyright 1990 Network Computing Devices;
  5.  * Portions Copyright 1987 by Digital Equipment Corporation and the
  6.  * Massachusetts Institute of Technology
  7.  *
  8.  * Permission to use, copy, modify, and distribute this protoype software
  9.  * and its documentation to Members and Affiliates of the MIT X Consortium
  10.  * any purpose and without fee is hereby granted, provided
  11.  * that the above copyright notice appear in all copies and that both that
  12.  * copyright notice and this permission notice appear in supporting
  13.  * documentation, and that the names of Network Computing Devices, Digital or
  14.  * MIT not be used in advertising or publicity pertaining to distribution of
  15.  * the software without specific, written prior permission.
  16.  *
  17.  * NETWORK COMPUTING DEVICES, DIGITAL AND MIT DISCLAIM ALL WARRANTIES WITH
  18.  * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  19.  * AND FITNESS, IN NO EVENT SHALL NETWORK COMPUTING DEVICES, DIGITAL OR MIT BE
  20.  * LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  21.  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
  22.  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  23.  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  24.  */
  25.  
  26. /*
  27.  *    FSlibInt.c - Internal support routines for the C subroutine
  28.  *    interface library (FSlib).
  29.  */
  30. #include <stdio.h>
  31. #include "FSlibint.h"
  32.  
  33. static void _EatData32();
  34.  
  35. /* check for both EAGAIN and EWOULDBLOCK, because some supposedly POSIX
  36.  * systems are broken and return EWOULDBLOCK when they should return EAGAIN
  37.  */
  38. #if defined(EAGAIN) && defined(EWOULDBLOCK)
  39. #define ETEST(err) (err == EAGAIN || err == EWOULDBLOCK)
  40. #else
  41. #ifdef EAGAIN
  42. #define ETEST(err) (err == EAGAIN)
  43. #else
  44. #define ETEST(err) (err == EWOULDBLOCK)
  45. #endif
  46. #endif
  47.  
  48. #ifdef CRAY
  49. /*
  50.  * Cray UniCOS does not have readv and writev so we emulate
  51.  */
  52. #include <sys/socket.h>
  53.  
  54. int
  55. _FSReadV(fd, iov, iovcnt)
  56.     int         fd;
  57.     struct iovec *iov;
  58.     int         iovcnt;
  59. {
  60.     struct msghdr hdr;
  61.  
  62.     hdr.msg_iov = iov;
  63.     hdr.msg_iovlen = iovcnt;
  64.     hdr.msg_accrights = 0;
  65.     hdr.msg_accrightslen = 0;
  66.     hdr.msg_name = 0;
  67.     hdr.msg_namelen = 0;
  68.  
  69.     return (recvmsg(fd, &hdr, 0));
  70. }
  71.  
  72. int
  73. _FSWriteV(fd, iov, iovcnt)
  74.     int         fd;
  75.     struct iovec *iov;
  76.     int         iovcnt;
  77. {
  78.     struct msghdr hdr;
  79.  
  80.     hdr.msg_iov = iov;
  81.     hdr.msg_iovlen = iovcnt;
  82.     hdr.msg_accrights = 0;
  83.     hdr.msg_accrightslen = 0;
  84.     hdr.msg_name = 0;
  85.     hdr.msg_namelen = 0;
  86.  
  87.     return (sendmsg(fd, &hdr, 0));
  88. }
  89.  
  90. #endif                /* CRAY */
  91.  
  92. #if defined(SYSV) && defined(SYSV386) && !defined(STREAMSCONN)
  93. /*
  94.  * SYSV/386 does not have readv so we emulate
  95.  */
  96. #include <sys/uio.h>
  97.  
  98. int _FSReadV(fd, iov, iovcnt)
  99. int fd;
  100. struct iovec *iov;
  101. int iovcnt;
  102. {
  103.     int i, len, total;
  104.     char *base;
  105.  
  106.     errno = 0;
  107.     for (i=0, total=0;  i<iovcnt;  i++, iov++) {
  108.     len = iov->iov_len;
  109.     base = iov->iov_base;
  110.     while (len > 0) {
  111.         register int nbytes;
  112.         nbytes = read(fd, base, len);
  113.         if (nbytes < 0 && total == 0)  return -1;
  114.         if (nbytes <= 0)  return total;
  115.         errno = 0;
  116.         len   -= nbytes;
  117.         total += nbytes;
  118.         base  += nbytes;
  119.     }
  120.     }
  121.     return total;
  122. }
  123.  
  124. #endif /* SYSV && SYSV386 && !STREAMSCONN */
  125.  
  126. /*
  127.  * The following routines are internal routines used by FSlib for protocol
  128.  * packet transmission and reception.
  129.  *
  130.  * FSIOError(FSServer *) will be called if any sort of system call error occurs.
  131.  * This is assumed to be a fatal condition, i.e., FSIOError should not return.
  132.  *
  133.  * FSError(FSServer *, FSErrorEvent *) will be called whenever an FS_Error event is
  134.  * received.  This is not assumed to be a fatal condition, i.e., it is
  135.  * acceptable for this procedure to return.  However, FSError should NOT
  136.  * perform any operations (directly or indirectly) on the DISPLAY.
  137.  *
  138.  * Routines declared with a return type of 'Status' return 0 on failure,
  139.  * and non 0 on success.  Routines with no declared return type don't
  140.  * return anything.  Whenever possible routines that create objects return
  141.  * the object they have created.
  142.  */
  143.  
  144. _FSQEvent  *_FSqfree = NULL;    /* NULL _FSQEvent. */
  145.  
  146. static int  padlength[4] = {0, 3, 2, 1};
  147.  
  148.  /*
  149.   * lookup table for adding padding bytes to data that is read from or written
  150.   * to the FS socket.
  151.   */
  152.  
  153. static fsReq _dummy_request = {
  154.     0, 0, 0
  155. };
  156.  
  157. /*
  158.  * _FSFlush - Flush the FS request buffer.  If the buffer is empty, no
  159.  * action is taken.  This routine correctly handles incremental writes.
  160.  * This routine may have to be reworked if int < long.
  161.  */
  162. _FSFlush(svr)
  163.     register FSServer *svr;
  164. {
  165.     register long size,
  166.                 todo;
  167.     register int write_stat;
  168.     register char *bufindex;
  169.  
  170.     size = todo = svr->bufptr - svr->buffer;
  171.     bufindex = svr->bufptr = svr->buffer;
  172.     /*
  173.      * While write has not written the entire buffer, keep looping until the
  174.      * entire buffer is written.  bufindex will be incremented and size
  175.      * decremented as buffer is written out.
  176.      */
  177.     while (size) {
  178.     errno = 0;
  179.     write_stat = WriteToServer(svr->fd, bufindex, (int) todo);
  180.     if (write_stat >= 0) {
  181.         size -= write_stat;
  182.         todo = size;
  183.         bufindex += write_stat;
  184.     } else if (ETEST(errno)) {
  185.         _FSWaitForWritable(svr);
  186. #ifdef SUNSYSV
  187.     } else if (errno == 0) {
  188.         _FSWaitForWritable(svr);
  189. #endif
  190.  
  191. #ifdef EMSGSIZE
  192.     } else if (errno == EMSGSIZE) {
  193.         if (todo > 1)
  194.         todo >>= 1;
  195.         else
  196.         _FSWaitForWritable(svr);
  197. #endif
  198.     } else {
  199.         /* Write failed! */
  200.         /* errno set by write system call. */
  201.         (*_FSIOErrorFunction) (svr);
  202.     }
  203.     }
  204.     svr->last_req = (char *) &_dummy_request;
  205. }
  206.  
  207. int
  208. _FSEventsQueued(svr, mode)
  209.     register FSServer *svr;
  210.     int         mode;
  211. {
  212.     register int len;
  213.     int         pend;
  214.     char        buf[BUFSIZE];
  215.     register fsReply *rep;
  216.  
  217.     if (mode == QueuedAfterFlush) {
  218.     _FSFlush(svr);
  219.     if (svr->qlen)
  220.         return (svr->qlen);
  221.     }
  222.     if (BytesReadable(svr->fd, (char *) &pend) < 0)
  223.     (*_FSIOErrorFunction) (svr);
  224.     if ((len = pend) < SIZEOF(fsReply))
  225.     return (svr->qlen);    /* _FSFlush can enqueue events */
  226.     else if (len > BUFSIZE)
  227.     len = BUFSIZE;
  228.     len /= SIZEOF(fsReply);
  229.     pend = len * SIZEOF(fsReply);
  230.     _FSRead(svr, buf, (long) pend);
  231.  
  232.     /* no space between comma and type or else macro will die */
  233.     STARTITERATE(rep, fsReply, buf, (len > 0), len--) {
  234.     if (rep->generic.type == FS_Error)
  235.         _FSError(svr, (fsError *) rep);
  236.     else            /* must be an event packet */
  237.         _FSEnq(svr, (fsEvent *) rep);
  238.     }
  239.     ENDITERATE
  240.     return (svr->qlen);
  241. }
  242.  
  243. /* _FSReadEvents - Flush the output queue,
  244.  * then read as many events as possible (but at least 1) and enqueue them
  245.  */
  246. _FSReadEvents(svr)
  247.     register FSServer *svr;
  248. {
  249.     char        buf[BUFSIZE];
  250.     long        pend_not_register;    /* because can't "&" a register
  251.                      * variable */
  252.     register long pend;
  253.     register fsEvent *ev;
  254.     Bool        not_yet_flushed = True;
  255.  
  256.     do {
  257.     /* find out how much data can be read */
  258.     if (BytesReadable(svr->fd, (char *) &pend_not_register) < 0)
  259.         (*_FSIOErrorFunction) (svr);
  260.     pend = pend_not_register;
  261.  
  262.     /*
  263.      * must read at least one fsEvent; if none is pending, then we'll just
  264.      * flush and block waiting for it
  265.      */
  266.     if (pend < SIZEOF(fsEvent)) {
  267.         pend = SIZEOF(fsEvent);
  268.         /* don't flush until we block the first time */
  269.         if (not_yet_flushed) {
  270.         int         qlen = svr->qlen;
  271.  
  272.         _FSFlush(svr);
  273.         if (qlen != svr->qlen)
  274.             return;
  275.         not_yet_flushed = False;
  276.         }
  277.     }
  278.     /* but we won't read more than the max buffer size */
  279.     if (pend > BUFSIZE)
  280.         pend = BUFSIZE;
  281.  
  282.     /* round down to an integral number of XReps */
  283.     pend = (pend / SIZEOF(fsEvent)) * SIZEOF(fsEvent);
  284.  
  285.     _FSRead(svr, buf, pend);
  286.  
  287.     /* no space between comma and type or else macro will die */
  288.     STARTITERATE(ev, fsEvent, buf, (pend > 0),
  289.              pend -= SIZEOF(fsEvent)) {
  290.         if (ev->type == FS_Error)
  291.         _FSError(svr, (fsError *) ev);
  292.         else        /* it's an event packet; enqueue it */
  293.         _FSEnq(svr, ev);
  294.     }
  295.     ENDITERATE
  296.     } while (svr->head == NULL);
  297. }
  298.  
  299. /*
  300.  * _FSRead - Read bytes from the socket taking into account incomplete
  301.  * reads.  This routine may have to be reworked if int < long.
  302.  */
  303. _FSRead(svr, data, size)
  304.     register FSServer *svr;
  305.     register char *data;
  306.     register long size;
  307. {
  308.     register long bytes_read;
  309.  
  310.     if (size == 0)
  311.     return;
  312.     errno = 0;
  313.     while ((bytes_read = ReadFromServer(svr->fd, data, (int) size))
  314.         != size) {
  315.  
  316.     if (bytes_read > 0) {
  317.         size -= bytes_read;
  318.         data += bytes_read;
  319.     }
  320.     else if (ETEST(errno)) {
  321.         _FSWaitForReadable(svr);
  322.         errno = 0;
  323.     }
  324. #ifdef SUNSYSV
  325.     else if (errno == 0) {
  326.         _FSWaitForReadable(svr);
  327.     }
  328. #endif
  329.  
  330.     else if (bytes_read == 0) {
  331.         /* Read failed because of end of file! */
  332.         errno = EPIPE;
  333.         (*_FSIOErrorFunction) (svr);
  334.     } else {        /* bytes_read is less than 0; presumably -1 */
  335.         /* If it's a system call interrupt, it's not an error. */
  336.         if (errno != EINTR)
  337.         (*_FSIOErrorFunction) (svr);
  338.     }
  339.     }
  340. }
  341.  
  342. #ifdef WORD64
  343. /*
  344.  * XXX This is a *really* stupid way of doing this....
  345.  */
  346.  
  347. #define PACKBUFFERSIZE 4096
  348.  
  349.  
  350. /*
  351.  * _FSRead32 - Read bytes from the socket unpacking each 32 bits
  352.  *            into a long (64 bits on a CRAY computer).
  353.  *
  354.  */
  355. static
  356. _doFSRead32(svr, data, size, packbuffer)
  357.     register FSServer *svr;
  358.     register long *data;
  359.     register long size;
  360.     register char *packbuffer;
  361. {
  362.     long       *lpack,
  363.                *lp;
  364.     long        mask32 = 0x00000000ffffffff;
  365.     long        maskw,
  366.                 nwords,
  367.                 i,
  368.                 bits;
  369.  
  370.     _FSReadPad(svr, packbuffer, size);
  371.  
  372.     lp = data;
  373.     lpack = (long *) packbuffer;
  374.     nwords = size >> 2;
  375.     bits = 32;
  376.  
  377.     for (i = 0; i < nwords; i++) {
  378.     maskw = mask32 << bits;
  379.     *lp++ = (*lpack & maskw) >> bits;
  380.     bits = bits ^ 32;
  381.     if (bits) {
  382.         lpack++;
  383.     }
  384.     }
  385. }
  386.  
  387. _FSRead32(svr, data, len)
  388.     FSServer   *svr;
  389.     long       *data;
  390.     long        len;
  391. {
  392.     char        packbuffer[PACKBUFFERSIZE];
  393.     unsigned    nwords = (PACKBUFFERSIZE >> 2);    /* bytes to CARD32 */
  394.  
  395.     for (; len > nwords; len -= nwords, data += nwords) {
  396.     _doFSRead32(svr, data, nwords, packbuffer);
  397.     }
  398.     _doFSRead32(svr, data, len, packbuffer);
  399. }
  400.  
  401.  
  402.  
  403. /*
  404.  * _FSRead16 - Read bytes from the socket unpacking each 16 bits
  405.  *            into a long (64 bits on a CRAY computer).
  406.  *
  407.  */
  408. static
  409. _doFSRead16(svr, data, size, packbuffer)
  410.     register FSServer *svr;
  411.     register short *data;
  412.     register long size;
  413.     char       *packbuffer;
  414. {
  415.     long       *lpack,
  416.                *lp;
  417.     long        mask16 = 0x000000000000ffff;
  418.     long        maskw,
  419.                 nwords,
  420.                 i,
  421.                 bits;
  422.  
  423.     _FSRead(svr, packbuffer, size);    /* don't do a padded read... */
  424.  
  425.     lp = (long *) data;
  426.     lpack = (long *) packbuffer;
  427.     nwords = size >> 1;        /* number of 16 bit words to be unpacked */
  428.     bits = 48;
  429.     for (i = 0; i < nwords; i++) {
  430.     maskw = mask16 << bits;
  431.     *lp++ = (*lpack & maskw) >> bits;
  432.     bits -= 16;
  433.     if (bits < 0) {
  434.         lpack++;
  435.         bits = 48;
  436.     }
  437.     }
  438. }
  439.  
  440. _FSRead16(svr, data, len)
  441.     FSServer   *svr;
  442.     short      *data;
  443.     long        len;
  444. {
  445.     char        packbuffer[PACKBUFFERSIZE];
  446.     unsigned    nwords = (PACKBUFFERSIZE >> 1);    /* bytes to CARD16 */
  447.  
  448.     for (; len > nwords; len -= nwords, data += nwords) {
  449.     _doFSRead16(svr, data, nwords, packbuffer);
  450.     }
  451.     _doFSRead16(svr, data, len, packbuffer);
  452. }
  453.  
  454. _FSRead16Pad(svr, data, size)
  455.     FSServer   *svr;
  456.     short      *data;
  457.     long        size;
  458. {
  459.     int         slop = (size & 3);
  460.     short       slopbuf[3];
  461.  
  462.     _FSRead16(svr, data, size);
  463.     if (slop > 0) {
  464.     _FSRead16(svr, slopbuf, 4 - slop);
  465.     }
  466. }
  467.  
  468. #endif                /* WORD64 */
  469.  
  470.  
  471. /*
  472.  * _FSReadPad - Read bytes from the socket taking into account incomplete
  473.  * reads.  If the number of bytes is not 0 mod 32, read additional pad
  474.  * bytes. This routine may have to be reworked if int < long.
  475.  */
  476. _FSReadPad(svr, data, size)
  477.     register FSServer *svr;
  478.     register char *data;
  479.     register long size;
  480. {
  481.     register long bytes_read;
  482.     struct iovec iov[2];
  483.     char        pad[3];
  484.  
  485.     if (size == 0)
  486.     return;
  487.     iov[0].iov_len = (int) size;
  488.     iov[0].iov_base = data;
  489.     /*
  490.      * The following hack is used to provide 32 bit long-word aligned padding.
  491.      * The [1] vector is of length 0, 1, 2, or 3, whatever is needed.
  492.      */
  493.  
  494.     iov[1].iov_len = padlength[size & 3];
  495.     iov[1].iov_base = pad;
  496.     size += iov[1].iov_len;
  497.  
  498.     errno = 0;
  499.     while ((bytes_read = ReadvFromServer(svr->fd, iov, 2)) != size) {
  500.  
  501.     if (bytes_read > 0) {
  502.         size -= bytes_read;
  503.         if ((iov[0].iov_len -= bytes_read) < 0) {
  504.         iov[1].iov_len += iov[0].iov_len;
  505.         iov[1].iov_base -= iov[0].iov_len;
  506.         iov[0].iov_len = 0;
  507.         } else
  508.         iov[0].iov_base += bytes_read;
  509.     }
  510.     else if (ETEST(errno)) {
  511.         _FSWaitForReadable(svr);
  512.         errno = 0;
  513.     }
  514. #ifdef SUNSYSV
  515.     else if (errno == 0) {
  516.         _FSWaitForReadable(svr);
  517.     }
  518. #endif
  519.  
  520.     else if (bytes_read == 0) {
  521.         /* Read failed because of end of file! */
  522.         errno = EPIPE;
  523.         (*_FSIOErrorFunction) (svr);
  524.     } else {        /* bytes_read is less than 0; presumably -1 */
  525.         /* If it's a system call interrupt, it's not an error. */
  526.         if (errno != EINTR)
  527.         (*_FSIOErrorFunction) (svr);
  528.     }
  529.     }
  530. }
  531.  
  532. /*
  533.  * _FSSend - Flush the buffer and send the client data. 32 bit word aligned
  534.  * transmission is used, if size is not 0 mod 4, extra bytes are transmitted.
  535.  * This routine may have to be reworked if int < long;
  536.  */
  537. _FSSend(svr, data, size)
  538.     register FSServer *svr;
  539.     char       *data;
  540.     register long size;
  541. {
  542.     struct iovec iov[3];
  543.     static char pad[3] = {0, 0, 0};
  544.  
  545.     long        skip = 0;
  546.     long        svrbufsize = (svr->bufptr - svr->buffer);
  547.     long        padsize = padlength[size & 3];
  548.     long        total = svrbufsize + size + padsize;
  549.     long        todo = total;
  550.  
  551.     /*
  552.      * There are 3 pieces that may need to be written out:
  553.      * 
  554.      * o  whatever is in the display buffer o  the data passed in by the user o
  555.      * any padding needed to 32bit align the whole mess
  556.      * 
  557.      * This loop looks at all 3 pieces each time through.  It uses skip to figure
  558.      * out whether or not a given piece is needed.
  559.      */
  560.     while (total) {
  561.     long        before = skip;    /* amount of whole thing written */
  562.     long        remain = todo;    /* amount to try this time, <= total */
  563.     int         i = 0;
  564.     long        len;
  565.  
  566.     /*
  567.      * You could be very general here and have "in" and "out" iovecs and
  568.      * write a loop without using a macro, but what the heck.  This
  569.      * translates to:
  570.      * 
  571.      * how much of this piece is new? if more new then we are trying this
  572.      * time, clamp if nothing new then bump down amount already written,
  573.      * for next piece else put new stuff in iovec, will need all of next
  574.      * piece
  575.      * 
  576.      * Note that todo had better be at least 1 or else we'll end up writing 0
  577.      * iovecs.
  578.      */
  579. #define InsertIOV(pointer, length) \
  580.         len = (length) - before; \
  581.         if (len > remain) \
  582.         len = remain; \
  583.         if (len <= 0) { \
  584.         before = (-len); \
  585.         } else { \
  586.         iov[i].iov_len = len; \
  587.         iov[i].iov_base = (pointer) + before; \
  588.         i++; \
  589.         remain -= len; \
  590.         before = 0; \
  591.         }
  592.  
  593.     InsertIOV(svr->buffer, svrbufsize)
  594.     InsertIOV(data, size)
  595.     InsertIOV(pad, padsize)
  596.  
  597.     errno = 0;
  598.     if ((len = WritevToServer(svr->fd, iov, i)) >= 0) {
  599.         skip += len;
  600.         total -= len;
  601.         todo = total;
  602.     } else if (ETEST(errno)) {
  603.         _FSWaitForWritable(svr);
  604. #ifdef SUNSYSV
  605.     } else if (errno == 0) {
  606.         _FSWaitForWritable(svr);
  607. #endif
  608.  
  609. #ifdef EMSGSIZE
  610.     } else if (errno == EMSGSIZE) {
  611.         if (todo > 1)
  612.         todo >>= 1;
  613.         else
  614.         _FSWaitForWritable(svr);
  615. #endif
  616.     } else {
  617.         (*_FSIOErrorFunction) (svr);
  618.     }
  619.     }
  620.  
  621.     svr->bufptr = svr->buffer;
  622.     svr->last_req = (char *) &_dummy_request;
  623. }
  624.  
  625. #ifdef undef
  626. /*
  627.  * _FSAllocID - normal resource ID allocation routine.  A client
  628.  * can roll his own and instatantiate it if he wants, but must
  629.  * follow the rules.
  630.  */
  631. FSID
  632. _FSAllocID(svr)
  633.     register FSServer *svr;
  634. {
  635.     return (svr->resource_base + (svr->resource_id++ << svr->resource_shift));
  636. }
  637.  
  638. #endif
  639.  
  640. /*
  641.  * The hard part about this is that we only get 16 bits from a reply.  Well,
  642.  * then, we have three values that will march along, with the following
  643.  * invariant:
  644.  *    svr->last_request_read <= rep->sequenceNumber <= svr->request
  645.  * The right choice for rep->sequenceNumber is the largest that
  646.  * still meets these constraints.
  647.  */
  648.  
  649. unsigned long
  650. _FSSetLastRequestRead(svr, rep)
  651.     register FSServer *svr;
  652.     register fsGenericReply *rep;
  653. {
  654.     register unsigned long newseq,
  655.                 lastseq;
  656.  
  657.     newseq = (svr->last_request_read & ~((unsigned long) 0xffff)) |
  658.     rep->sequenceNumber;
  659.     lastseq = svr->last_request_read;
  660.     while (newseq < lastseq) {
  661.     newseq += 0x10000;
  662.     if (newseq > svr->request) {
  663.         (void) fprintf(stderr,
  664.            "FSlib:  sequence lost (0x%lx > 0x%lx) in reply type 0x%x!\n",
  665.                newseq, svr->request,
  666.                (unsigned int) rep->type);
  667.         newseq -= 0x10000;
  668.         break;
  669.     }
  670.     }
  671.  
  672.     svr->last_request_read = newseq;
  673.     return (newseq);
  674. }
  675.  
  676. /*
  677.  * _FSReply - Wait for a reply packet and copy its contents into the
  678.  * specified rep.  Mean while we must handle error and event packets that
  679.  * we may encounter.
  680.  */
  681. Status
  682. _FSReply(svr, rep, extra, discard)
  683.     register FSServer *svr;
  684.     register fsReply *rep;
  685.     int         extra;        /* number of 32-bit words expected after the
  686.                  * reply */
  687.     Bool        discard;    /* should I discard data followind "extra"
  688.                  * words? */
  689. {
  690.     /*
  691.      * Pull out the serial number now, so that (currently illegal) requests
  692.      * generated by an error handler don't confuse us.
  693.      */
  694.     unsigned long cur_request = svr->request;
  695.     long rem_length;
  696.  
  697.     _FSFlush(svr);
  698.     while (1) {
  699.     _FSRead(svr, (char *) rep, (long) SIZEOF(fsReply));
  700.     switch ((int) rep->generic.type) {
  701.  
  702.     case FS_Reply:
  703.         /*
  704.          * Reply received.  Fast update for synchronous replies, but deal
  705.          * with multiple outstanding replies.
  706.          */
  707.         if (rep->generic.sequenceNumber == (cur_request & 0xffff))
  708.         svr->last_request_read = cur_request;
  709.         else
  710.         (void) _FSSetLastRequestRead(svr, &rep->generic);
  711.         rem_length = rep->generic.length - (SIZEOF(fsReply) >> 2);
  712.         if (rem_length < 0) rem_length = 0;
  713.         if (extra == 0) {
  714.         if (discard && rem_length)
  715.             /* unexpectedly long reply! */
  716.             _EatData32(svr, rem_length);
  717.         return (1);
  718.         }
  719.         if (extra == rem_length) {
  720.         /*
  721.          * Read the extra data into storage immediately following the
  722.          * GenericReply structure.
  723.          */
  724.         _FSRead(svr, (char *) NEXTPTR(rep, fsReply), ((long) extra) << 2);
  725.         return (1);
  726.         }
  727.         if (extra < rem_length) {
  728.         /* Actual reply is longer than "extra" */
  729.         _FSRead(svr, (char *) NEXTPTR(rep, fsReply), ((long) extra) << 2);
  730.         if (discard)
  731.             _EatData32(svr, rem_length - extra);
  732.         return (1);
  733.         }
  734.         /*
  735.          * if we get here, then extra > rem_length -- meaning we
  736.          * read a reply that's shorter than we expected.  This is an
  737.          * error,  but we still need to figure out how to handle it...
  738.          */
  739.         _FSRead(svr, (char *) NEXTPTR(rep, fsReply), rem_length << 2);
  740.         (*_FSIOErrorFunction) (svr);
  741.         return (0);
  742.  
  743.     case FS_Error:
  744.         {
  745.         register _FSExtension *ext;
  746.         register Bool ret = False;
  747.         int         ret_code;
  748.         fsError     err;
  749.         unsigned long serial;
  750.         long        err_data;
  751.  
  752.         err = *(fsError *) rep;
  753.         /* read the rest of the error */
  754.         _FSRead(svr, (char *) &err + sizeof(fsReply),
  755.             (long) (sizeof(fsError) - SIZEOF(fsReply)));
  756.         serial = _FSSetLastRequestRead(svr, (fsGenericReply *) rep);
  757.         if (serial == cur_request)
  758.             /* do not die on certain failures */
  759.             switch ((int) err.request) {
  760.             /* suck in any extra error info */
  761.             case FSBadResolution:
  762.             case FSBadLength:
  763.             case FSBadIDChoice:
  764.             case FSBadRange:
  765.             case FSBadFont:
  766.             case FSBadFormat:
  767.             _FSRead(svr, (char *) &err_data, 4);
  768.             break;
  769.             case FSBadAccessContext:
  770.             _FSRead(svr, (char *) &err_data, 4);
  771.             return 0;
  772.             case FSBadAlloc:
  773.             return (0);
  774.             /*
  775.              * we better see if there is an extension who may want
  776.              * to suppress the error.
  777.              */
  778.             default:
  779.             ext = svr->ext_procs;
  780.             while (ext) {
  781.                 if (ext->error != NULL)
  782.                 ret = (*ext->error)
  783.                     (svr, &err, &ext->codes, &ret_code);
  784.                 ext = ext->next;
  785.             }
  786.             if (ret)
  787.                 return (ret_code);
  788.             break;
  789.             }
  790.         _FSError(svr, &err);
  791.         if (serial == cur_request)
  792.             return (0);
  793.         }
  794.         break;
  795.     default:
  796.         _FSEnq(svr, (fsEvent *) rep);
  797.         break;
  798.     }
  799.     }
  800. }
  801.  
  802.  
  803. /* Read and discard "n" 8-bit bytes of data */
  804.  
  805. void
  806. _FSEatData(svr, n)
  807.     FSServer   *svr;
  808.     register unsigned long n;
  809. {
  810. #define SCRATCHSIZE 2048
  811.     char        buf[SCRATCHSIZE];
  812.  
  813.     while (n > 0) {
  814.     register long bytes_read = (n > SCRATCHSIZE) ? SCRATCHSIZE : n;
  815.  
  816.     _FSRead(svr, buf, bytes_read);
  817.     n -= bytes_read;
  818.     }
  819. #undef SCRATCHSIZE
  820. }
  821.  
  822.  
  823. /* Read and discard "n" 32-bit words. */
  824.  
  825. static void
  826. _EatData32(svr, n)
  827.     FSServer   *svr;
  828.     unsigned long n;
  829. {
  830.     _FSEatData(svr, n << 2);
  831. }
  832.  
  833.  
  834. /*
  835.  * _FSEnq - Place event packets on the display's queue.
  836.  * note that no squishing of move events in V11, since there
  837.  * is pointer motion hints....
  838.  */
  839. _FSEnq(svr, event)
  840.     register FSServer *svr;
  841.     register fsEvent *event;
  842. {
  843.     register _FSQEvent *qelt;
  844.  
  845. /*NOSTRICT*/
  846.     if (qelt = _FSqfree) {
  847.     /* If _FSqfree is non-NULL do this, else malloc a new one. */
  848.     _FSqfree = qelt->next;
  849.     } else if ((qelt =
  850.          (_FSQEvent *) FSmalloc((unsigned) sizeof(_FSQEvent))) == NULL) {
  851.     /* Malloc call failed! */
  852.     errno = ENOMEM;
  853.     (*_FSIOErrorFunction) (svr);
  854.     }
  855.     qelt->next = NULL;
  856.     /* go call through display to find proper event reformatter */
  857.     if ((*svr->event_vec[event->type & 0177]) (svr, &qelt->event, event)) {
  858.     if (svr->tail)
  859.         svr->tail->next = qelt;
  860.     else
  861.         svr->head = qelt;
  862.  
  863.     svr->tail = qelt;
  864.     svr->qlen++;
  865.     } else {
  866.     /* ignored, or stashed away for many-to-one compression */
  867.     qelt->next = _FSqfree;
  868.     _FSqfree = qelt;
  869.     }
  870. }
  871.  
  872. /*
  873.  * EventToWire in seperate file in that often not needed.
  874.  */
  875.  
  876. /*ARGSUSED*/
  877. Bool
  878. _FSUnknownWireEvent(svr, re, event)
  879.     register FSServer *svr;    /* pointer to display structure */
  880.     register FSEvent *re;    /* pointer to where event should be
  881.                  * reformatted */
  882.     register fsEvent *event;    /* wire protocol event */
  883. {
  884.  
  885. #ifdef notdef
  886.     (void) fprintf(stderr,
  887.        "FSlib: unhandled wire event! event number = %d, display = %x\n.",
  888.            event->type, svr);
  889. #endif
  890.  
  891.     return (False);
  892. }
  893.  
  894. /*ARGSUSED*/
  895. Status
  896. _FSUnknownNativeEvent(svr, re, event)
  897.     register FSServer *svr;    /* pointer to display structure */
  898.     register FSEvent *re;    /* pointer to where event should be
  899.                  * reformatted */
  900.     register fsEvent *event;    /* wire protocol event */
  901. {
  902.  
  903. #ifdef notdef
  904.     (void) fprintf(stderr,
  905.      "FSlib: unhandled native event! event number = %d, display = %x\n.",
  906.            re->type, svr);
  907. #endif
  908.  
  909.     return (0);
  910. }
  911.  
  912. /*
  913.  * reformat a wire event into an FSEvent structure of the right type.
  914.  */
  915. Bool
  916. _FSWireToEvent(svr, re, event)
  917.     register FSServer *svr;    /* pointer to display structure */
  918.     register FSEvent *re;    /* pointer to where event should be
  919.                  * reformatted */
  920.     register fsEvent *event;    /* wire protocol event */
  921. {
  922.  
  923.     re->type = event->type & 0x7f;
  924.     ((FSAnyEvent *) re)->serial = _FSSetLastRequestRead(svr,
  925.                            (fsGenericReply *) event);
  926.     ((FSAnyEvent *) re)->send_event = ((event->type & 0x80) != 0);
  927.     ((FSAnyEvent *) re)->server = svr;
  928.  
  929.     /*
  930.      * Ignore the leading bit of the event type since it is set when a client
  931.      * sends an event rather than the server.
  932.      */
  933.  
  934.     switch (event->type & 0177) {
  935.     default:
  936.     return (_FSUnknownWireEvent(svr, re, event));
  937.     }
  938. }
  939.  
  940.  
  941. static char *
  942. _SysErrorMsg(n)
  943.     int         n;
  944. {
  945.     extern char *sys_errlist[];
  946.     extern int  sys_nerr;
  947.     char       *s = ((n >= 0 && n < sys_nerr) ? sys_errlist[n] : "unknown error");
  948.  
  949.     return (s ? s : "no such error");
  950. }
  951.  
  952. /*
  953.  * _FSIOError - Default fatal system error reporting routine.  Called when
  954.  * an X internal system error is encountered.
  955.  */
  956. _FSIOError(svr)
  957.     FSServer   *svr;
  958. {
  959.     (void) fprintf(stderr,
  960.            "FSIO:  fatal IO error %d (%s) on font server \"%s\"\r\n",
  961.            errno, _SysErrorMsg(errno), FSServerString(svr));
  962.     (void) fprintf(stderr,
  963.            "      after %lu requests (%lu known processed) with %d events remaining.\r\n",
  964.            NextRequest(svr) - 1, LastKnownRequestProcessed(svr),
  965.            QLength(svr));
  966.  
  967.     if (errno == EPIPE) {
  968.     (void) fprintf(stderr,
  969.     "      The connection was probably broken by a server shutdown.\r\n");
  970.     }
  971.     exit(1);
  972. }
  973.  
  974. /*
  975.  * _FSError - Default non-fatal error reporting routine.  Called when an
  976.  * FS_Error packet is encountered in the input stream.
  977.  */
  978. int
  979. _FSError(svr, rep)
  980.     FSServer   *svr;
  981.     fsError    *rep;
  982. {
  983.     FSErrorEvent event;
  984.  
  985.     /*
  986.      * FS_Error packet encountered!  We need to unpack the error before giving
  987.      * it to the user.
  988.      */
  989.  
  990.     event.server = svr;
  991.     event.type = FS_Error;
  992.     event.serial = _FSSetLastRequestRead(svr, (fsGenericReply *) rep);
  993.     event.error_code = rep->request;
  994.     event.request_code = rep->major_opcode;
  995.     event.minor_code = rep->minor_opcode;
  996.     if (_FSErrorFunction != NULL) {
  997.     return ((*_FSErrorFunction) (svr, &event));
  998.     }
  999.     exit(1);
  1000.     /* NOTREACHED */
  1001. }
  1002.  
  1003. int
  1004. _FSDefaultIOError(svr)
  1005.     FSServer   *svr;
  1006. {
  1007.     (void) fprintf(stderr,
  1008.            "FSIO:  fatal IO error %d (%s) on Font server \"%s\"\r\n",
  1009.            errno, _SysErrorMsg(errno), FSServerString(svr));
  1010.     (void) fprintf(stderr,
  1011.            "    after %lu requests (%lu known processed) with %d events remaining.\r\n",
  1012.            NextRequest(svr) - 1, LastKnownRequestProcessed(svr),
  1013.            QLength(svr));
  1014.     if (errno == EPIPE) {
  1015.     (void) fprintf(stderr,
  1016.                "    The connection was probably broken by a server shutdown.\n\r");
  1017.     }
  1018.     exit(1);
  1019. }
  1020.  
  1021. int
  1022. _FSPrintDefaultError(svr, event, fp)
  1023.     FSServer   *svr;
  1024.     FSErrorEvent *event;
  1025.     FILE       *fp;
  1026. {
  1027.     char        buffer[BUFSIZ];
  1028.     char        mesg[BUFSIZ];
  1029.     char        number[32];
  1030.     char       *mtype = "FSlibMessage";
  1031.     register _FSExtension *ext = (_FSExtension *) NULL;
  1032.  
  1033.     FSGetErrorText(svr, event->error_code, buffer, BUFSIZ);
  1034.     FSGetErrorDatabaseText(svr, mtype, "FSError", "FS Error", mesg, BUFSIZ);
  1035.     (void) fprintf(fp, "%s:  %s\n  ", mesg, buffer);
  1036.     FSGetErrorDatabaseText(svr, mtype, "MajorCode", "Request Major code %d",
  1037.                mesg, BUFSIZ);
  1038.     (void) fprintf(fp, mesg, event->request_code);
  1039.     if (event->request_code < 128) {
  1040.     sprintf(number, "%d", event->request_code);
  1041.     FSGetErrorDatabaseText(svr, "FSRequest", number, "", buffer, BUFSIZ);
  1042.     } else {
  1043.     for (ext = svr->ext_procs;
  1044.         ext && (ext->codes.major_opcode != event->request_code);
  1045.         ext = ext->next);
  1046.     if (ext)
  1047.         strcpy(buffer, ext->name);
  1048.     else
  1049.         buffer[0] = '\0';
  1050.     }
  1051.     (void) fprintf(fp, " (%s)\n  ", buffer);
  1052.     FSGetErrorDatabaseText(svr, mtype, "MinorCode", "Request Minor code %d",
  1053.                mesg, BUFSIZ);
  1054.     (void) fprintf(fp, mesg, event->minor_code);
  1055.     if (ext) {
  1056.     sprintf(mesg, "%s.%d", ext->name, event->minor_code);
  1057.     FSGetErrorDatabaseText(svr, "FSRequest", mesg, "", buffer, BUFSIZ);
  1058.     (void) fprintf(fp, " (%s)", buffer);
  1059.     }
  1060.     fputs("\n  ", fp);
  1061.     FSGetErrorDatabaseText(svr, mtype, "ResourceID", "ResourceID 0x%x",
  1062.                mesg, BUFSIZ);
  1063.     (void) fprintf(fp, mesg, event->resourceid);
  1064.     fputs("\n  ", fp);
  1065.     FSGetErrorDatabaseText(svr, mtype, "ErrorSerial", "Error Serial #%d",
  1066.                mesg, BUFSIZ);
  1067.     (void) fprintf(fp, mesg, event->serial);
  1068.     fputs("\n  ", fp);
  1069.     FSGetErrorDatabaseText(svr, mtype, "CurrentSerial", "Current Serial #%d",
  1070.                mesg, BUFSIZ);
  1071.     (void) fprintf(fp, mesg, svr->request);
  1072.     fputs("\n", fp);
  1073.     return 1;
  1074. }
  1075.  
  1076. int
  1077. _FSDefaultError(svr, event)
  1078.     FSServer   *svr;
  1079.     FSErrorEvent *event;
  1080. {
  1081.     if (_FSPrintDefaultError(svr, event, stderr) == 0)
  1082.     return 0;
  1083.     exit(1);
  1084.     /* NOTREACHED */
  1085. }
  1086.  
  1087. int         (*_FSIOErrorFunction) () = _FSIOError;
  1088. int         (*_FSErrorFunction) () = _FSDefaultError;
  1089.  
  1090. /*
  1091.  * This routine can be used to (cheaply) get some memory within a single
  1092.  * Xlib routine for scratch space.  It is reallocated from the same place
  1093.  * each time, unless the library needs a large scratch space.
  1094.  */
  1095. char       *
  1096. _FSAllocScratch(svr, nbytes)
  1097.     register FSServer *svr;
  1098.     unsigned long nbytes;
  1099. {
  1100.     if (nbytes > svr->scratch_length) {
  1101.     if (svr->scratch_buffer != NULL)
  1102.         FSfree(svr->scratch_buffer);
  1103.     return (svr->scratch_length = nbytes,
  1104.         svr->scratch_buffer = FSmalloc((unsigned) nbytes));
  1105.     }
  1106.     return (svr->scratch_buffer);
  1107. }
  1108.  
  1109. FSFree(data)
  1110.     char       *data;
  1111. {
  1112.     FSfree(data);
  1113. }
  1114.  
  1115. unsigned char *
  1116. FSMalloc(size)
  1117.     unsigned    size;
  1118. {
  1119.     return (unsigned char *) FSmalloc(size);
  1120. }
  1121.  
  1122. #ifdef DataRoutineIsProcedure
  1123. void
  1124. Data(svr, data, len)
  1125.     FSServer   *svr;
  1126.     char       *data;
  1127.     long        len;
  1128. {
  1129.     if (svr->bufptr + (len) <= svr->bufmax) {
  1130.     bcopy(data, svr->bufptr, (int) len);
  1131.     svr->bufptr += ((len) + 3) & ~3;
  1132.     } else {
  1133.     _FSSend(svr, data, len);
  1134.     }
  1135. }
  1136.  
  1137. #endif                /* DataRoutineIsProcedure */
  1138.  
  1139.  
  1140. #ifdef WORD64
  1141. /*
  1142.  * XXX This is a *really* stupid way of doing this.  It should just use
  1143.  * svr->bufptr directly, taking into account where in the word it is.
  1144.  */
  1145.  
  1146. /*
  1147.  * Data16 - Place 16 bit data in the buffer.
  1148.  *
  1149.  * "svr" is a pointer to a FSServer.
  1150.  * "data" is a pointer to the data.
  1151.  * "len" is the length in bytes of the data.
  1152.  */
  1153.  
  1154. static
  1155. doData16(svr, data, len, packbuffer)
  1156.     register FSServer *svr;
  1157.     short      *data;
  1158.     unsigned    len;
  1159.     char       *packbuffer;
  1160. {
  1161.     long       *lp,
  1162.                *lpack;
  1163.     long        i,
  1164.                 nwords,
  1165.                 bits;
  1166.     long        mask16 = 0x000000000000ffff;
  1167.  
  1168.     lp = (long *) data;
  1169.     lpack = (long *) packbuffer;
  1170.     *lpack = 0;
  1171.  
  1172. /*  nwords is the number of 16 bit values to be packed,
  1173.  *  the low order 16 bits of each word will be packed
  1174.  *  into 64 bit words
  1175.  */
  1176.     nwords = len >> 1;
  1177.     bits = 48;
  1178.  
  1179.     for (i = 0; i < nwords; i++) {
  1180.     *lpack ^= (*lp & mask16) << bits;
  1181.     bits -= 16;
  1182.     lp++;
  1183.     if (bits < 0) {
  1184.         lpack++;
  1185.         *lpack = 0;
  1186.         bits = 48;
  1187.     }
  1188.     }
  1189.     Data(svr, packbuffer, len);
  1190. }
  1191.  
  1192. Data16(svr, data, len)
  1193.     FSServer   *svr;
  1194.     short      *data;
  1195.     unsigned    len;
  1196. {
  1197.     char        packbuffer[PACKBUFFERSIZE];
  1198.     unsigned    nwords = (PACKBUFFERSIZE >> 1);    /* bytes to CARD16 */
  1199.  
  1200.     for (; len > nwords; len -= nwords, data += nwords) {
  1201.     doData16(svr, data, nwords, packbuffer);
  1202.     }
  1203.     doData16(svr, data, len, packbuffer);
  1204. }
  1205.  
  1206. /*
  1207.  * Data32 - Place 32 bit data in the buffer.
  1208.  *
  1209.  * "svr" is a pointer to a FSServer.
  1210.  * "data" is a pointer to the data.
  1211.  * "len" is the length in bytes of the data.
  1212.  */
  1213.  
  1214. static
  1215. doData32(svr, data, len, packbuffer)
  1216.     register FSServer *svr;
  1217.     long       *data;
  1218.     unsigned    len;
  1219.     char       *packbuffer;
  1220. {
  1221.     long       *lp,
  1222.                *lpack;
  1223.     long        i,
  1224.                 bits,
  1225.                 nwords;
  1226.     long        mask32 = 0x00000000ffffffff;
  1227.  
  1228.     lpack = (long *) packbuffer;
  1229.     lp = data;
  1230.  
  1231.     *lpack = 0;
  1232.  
  1233. /*  nwords is the number of 32 bit values to be packed
  1234.  *  the low order 32 bits of each word will be packed
  1235.  *  into 64 bit words
  1236.  */
  1237.     nwords = len >> 2;
  1238.     bits = 32;
  1239.  
  1240.     for (i = 0; i < nwords; i++) {
  1241.     *lpack ^= (*lp & mask32) << bits;
  1242.     bits = bits ^ 32;
  1243.     lp++;
  1244.     if (bits) {
  1245.         lpack++;
  1246.         *lpack = 0;
  1247.     }
  1248.     }
  1249.     Data(svr, packbuffer, len);
  1250. }
  1251.  
  1252. Data32(svr, data, len)
  1253.     FSServer   *svr;
  1254.     short      *data;
  1255.     unsigned    len;
  1256. {
  1257.     char        packbuffer[PACKBUFFERSIZE];
  1258.     unsigned    nwords = (PACKBUFFERSIZE >> 2);    /* bytes to CARD32 */
  1259.  
  1260.     for (; len > nwords; len -= nwords, data += nwords) {
  1261.     doData32(svr, data, nwords, packbuffer);
  1262.     }
  1263.     doData32(svr, data, len, packbuffer);
  1264. }
  1265.  
  1266. #endif                /* WORD64 */
  1267.  
  1268.  
  1269.  
  1270. /*
  1271.  * _FSFreeQ - free the queue of events, called by XCloseServer when there are
  1272.  * no more displays left on the display list
  1273.  */
  1274.  
  1275. void
  1276. _FSFreeQ()
  1277. {
  1278.     register _FSQEvent *qelt = _FSqfree;
  1279.  
  1280.     while (qelt) {
  1281.     register _FSQEvent *qnext = qelt->next;
  1282.  
  1283.     FSfree(qelt);
  1284.     qelt = qnext;
  1285.     }
  1286.     _FSqfree = NULL;
  1287.     return;
  1288. }
  1289.  
  1290. #ifdef _POSIX_SOURCE                     /* stupid makedepend [need if] */
  1291. #define NEED_UTSNAME
  1292. #endif
  1293. #ifdef hpux
  1294. #define NEED_UTSNAME
  1295. #endif
  1296. #ifdef USG
  1297. #define NEED_UTSNAME
  1298. #endif
  1299. #ifdef SVR4
  1300. #define NEED_UTSNAME
  1301. #endif
  1302.  
  1303. #ifdef NEED_UTSNAME
  1304. #include <sys/utsname.h>
  1305. #endif
  1306.  
  1307.  
  1308. /*
  1309.  * _FSGetHostname - similar to gethostname but allows special processing.
  1310.  */
  1311. int
  1312. _FSGetHostname(buf, maxlen)
  1313.     char       *buf;
  1314.     int         maxlen;
  1315. {
  1316.     int         len;
  1317.  
  1318. #ifdef NEED_UTSNAME
  1319.     /*
  1320.      * same host name crock as in server and xinit.
  1321.      */
  1322.     struct utsname name;
  1323.  
  1324.     uname(&name);
  1325.     len = strlen(name.nodename);
  1326.     if (len >= maxlen)
  1327.     len = maxlen - 1;
  1328.     strncpy(buf, name.nodename, len);
  1329.     buf[len] = '\0';
  1330. #else
  1331.     buf[0] = '\0';
  1332.     (void) gethostname(buf, maxlen);
  1333.     buf[maxlen - 1] = '\0';
  1334.     len = strlen(buf);
  1335. #endif                /* NEED_UTSNAME */
  1336.  
  1337.     return len;
  1338. }
  1339.  
  1340. #ifndef _FSANYSET
  1341. /*
  1342.  * This is not always a macro.
  1343.  */
  1344. _FSANYSET(src)
  1345.     long    *src;
  1346. {
  1347.     int i;
  1348.  
  1349.     for (i=0; i<MSKCNT; i++)
  1350.     if (src[ i ])
  1351.         return (1);
  1352.     return (0);
  1353. }
  1354. #endif
  1355.