aboutsummaryrefslogtreecommitdiff
path: root/nx-X11/lib/FS/FSlibInt.c
diff options
context:
space:
mode:
authorReinhard Tartler <siretart@tauware.de>2011-10-10 17:43:39 +0200
committerReinhard Tartler <siretart@tauware.de>2011-10-10 17:43:39 +0200
commitf4092abdf94af6a99aff944d6264bc1284e8bdd4 (patch)
tree2ac1c9cc16ceb93edb2c4382c088dac5aeafdf0f /nx-X11/lib/FS/FSlibInt.c
parenta840692edc9c6d19cd7c057f68e39c7d95eb767d (diff)
downloadnx-libs-f4092abdf94af6a99aff944d6264bc1284e8bdd4.tar.gz
nx-libs-f4092abdf94af6a99aff944d6264bc1284e8bdd4.tar.bz2
nx-libs-f4092abdf94af6a99aff944d6264bc1284e8bdd4.zip
Imported nx-X11-3.1.0-1.tar.gznx-X11/3.1.0-1
Summary: Imported nx-X11-3.1.0-1.tar.gz Keywords: Imported nx-X11-3.1.0-1.tar.gz into Git repository
Diffstat (limited to 'nx-X11/lib/FS/FSlibInt.c')
-rw-r--r--nx-X11/lib/FS/FSlibInt.c1360
1 files changed, 1360 insertions, 0 deletions
diff --git a/nx-X11/lib/FS/FSlibInt.c b/nx-X11/lib/FS/FSlibInt.c
new file mode 100644
index 000000000..3e1ac54d0
--- /dev/null
+++ b/nx-X11/lib/FS/FSlibInt.c
@@ -0,0 +1,1360 @@
+/* $Xorg: FSlibInt.c,v 1.5 2001/02/09 02:03:25 xorgcvs Exp $ */
+
+/*
+ * Copyright 1990 Network Computing Devices;
+ * Portions Copyright 1987 by Digital Equipment Corporation
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation, and that the names of Network Computing
+ * Devices or Digital not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. Network Computing Devices or Digital make no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as is" without express or implied warranty.
+ *
+ * NETWORK COMPUTING DEVICES AND DIGITAL DISCLAIM ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL NETWORK COMPUTING DEVICES
+ * OR DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+/*
+
+Copyright 1987, 1994, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+*/
+/* $XFree86: xc/lib/FS/FSlibInt.c,v 3.10tsi Exp $ */
+
+/*
+ * FSlibInt.c - Internal support routines for the C subroutine
+ * interface library (FSlib).
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <stdio.h>
+#include "FSlibint.h"
+#include <X11/Xos.h>
+
+static void _EatData32 ( FSServer *svr, unsigned long n );
+static char * _SysErrorMsg ( int n );
+
+/* check for both EAGAIN and EWOULDBLOCK, because some supposedly POSIX
+ * systems are broken and return EWOULDBLOCK when they should return EAGAIN
+ */
+#ifdef WIN32
+#define ETEST() (WSAGetLastError() == WSAEWOULDBLOCK)
+#else
+#if defined(EAGAIN) && defined(EWOULDBLOCK)
+#define ETEST() (errno == EAGAIN || errno == EWOULDBLOCK)
+#else
+#ifdef EAGAIN
+#define ETEST() (errno == EAGAIN)
+#else
+#define ETEST() (errno == EWOULDBLOCK)
+#endif
+#endif
+#endif
+#ifdef WIN32
+#define ECHECK(err) (WSAGetLastError() == err)
+#define ESET(val) WSASetLastError(val)
+#else
+#ifdef ISC
+#define ECHECK(err) ((errno == err) || ETEST())
+#else
+#define ECHECK(err) (errno == err)
+#endif
+#define ESET(val) errno = val
+#endif
+
+/*
+ * The following routines are internal routines used by FSlib for protocol
+ * packet transmission and reception.
+ *
+ * FSIOError(FSServer *) will be called if any sort of system call error occurs.
+ * This is assumed to be a fatal condition, i.e., FSIOError should not return.
+ *
+ * FSError(FSServer *, FSErrorEvent *) will be called whenever an FS_Error event is
+ * received. This is not assumed to be a fatal condition, i.e., it is
+ * acceptable for this procedure to return. However, FSError should NOT
+ * perform any operations (directly or indirectly) on the DISPLAY.
+ *
+ * Routines declared with a return type of 'Status' return 0 on failure,
+ * and non 0 on success. Routines with no declared return type don't
+ * return anything. Whenever possible routines that create objects return
+ * the object they have created.
+ */
+
+_FSQEvent *_FSqfree = NULL; /* NULL _FSQEvent. */
+
+static int padlength[4] = {0, 3, 2, 1};
+
+ /*
+ * lookup table for adding padding bytes to data that is read from or written
+ * to the FS socket.
+ */
+
+static fsReq _dummy_request = {
+ 0, 0, 0
+};
+
+/*
+ * _FSFlush - Flush the FS request buffer. If the buffer is empty, no
+ * action is taken. This routine correctly handles incremental writes.
+ * This routine may have to be reworked if int < long.
+ */
+void
+_FSFlush(svr)
+ register FSServer *svr;
+{
+ register long size,
+ todo;
+ register int write_stat;
+ register char *bufindex;
+
+ size = todo = svr->bufptr - svr->buffer;
+ bufindex = svr->bufptr = svr->buffer;
+ /*
+ * While write has not written the entire buffer, keep looping until the
+ * entire buffer is written. bufindex will be incremented and size
+ * decremented as buffer is written out.
+ */
+ while (size) {
+ ESET(0);
+ write_stat = _FSTransWrite(svr->trans_conn, bufindex, (int) todo);
+ if (write_stat >= 0) {
+ size -= write_stat;
+ todo = size;
+ bufindex += write_stat;
+ } else if (ETEST()) {
+ _FSWaitForWritable(svr);
+#ifdef SUNSYSV
+ } else if (ECHECK(0)) {
+ _FSWaitForWritable(svr);
+#endif
+
+#ifdef EMSGSIZE
+ } else if (ECHECK(EMSGSIZE)) {
+ if (todo > 1)
+ todo >>= 1;
+ else
+ _FSWaitForWritable(svr);
+#endif
+ } else {
+ /* Write failed! */
+ /* errno set by write system call. */
+ (*_FSIOErrorFunction) (svr);
+ }
+ }
+ svr->last_req = (char *) &_dummy_request;
+}
+
+int
+_FSEventsQueued(svr, mode)
+ register FSServer *svr;
+ int mode;
+{
+ register BytesReadable_t len;
+ BytesReadable_t pend;
+ char buf[BUFSIZE];
+ register fsReply *rep;
+
+ if (mode == QueuedAfterFlush) {
+ _FSFlush(svr);
+ if (svr->qlen)
+ return (svr->qlen);
+ }
+ if (_FSTransBytesReadable(svr->trans_conn, &pend) < 0)
+ (*_FSIOErrorFunction) (svr);
+ if ((len = pend) < SIZEOF(fsReply))
+ return (svr->qlen); /* _FSFlush can enqueue events */
+ else if (len > BUFSIZE)
+ len = BUFSIZE;
+ len /= SIZEOF(fsReply);
+ pend = len * SIZEOF(fsReply);
+ _FSRead(svr, buf, (long) pend);
+
+ /* no space between comma and type or else macro will die */
+ STARTITERATE(rep, fsReply, buf, (len > 0), len--) {
+ if (rep->generic.type == FS_Error)
+ _FSError(svr, (fsError *) rep);
+ else /* must be an event packet */
+ _FSEnq(svr, (fsEvent *) rep);
+ }
+ ENDITERATE
+ return (svr->qlen);
+}
+
+/* _FSReadEvents - Flush the output queue,
+ * then read as many events as possible (but at least 1) and enqueue them
+ */
+void
+_FSReadEvents(svr)
+ register FSServer *svr;
+{
+ char buf[BUFSIZE];
+ BytesReadable_t pend_not_register; /* because can't "&" a register
+ * variable */
+ register BytesReadable_t pend;
+ register fsEvent *ev;
+ Bool not_yet_flushed = True;
+
+ do {
+ /* find out how much data can be read */
+ if (_FSTransBytesReadable(svr->trans_conn, &pend_not_register) < 0)
+ (*_FSIOErrorFunction) (svr);
+ pend = pend_not_register;
+
+ /*
+ * must read at least one fsEvent; if none is pending, then we'll just
+ * flush and block waiting for it
+ */
+ if (pend < SIZEOF(fsEvent)) {
+ pend = SIZEOF(fsEvent);
+ /* don't flush until we block the first time */
+ if (not_yet_flushed) {
+ int qlen = svr->qlen;
+
+ _FSFlush(svr);
+ if (qlen != svr->qlen)
+ return;
+ not_yet_flushed = False;
+ }
+ }
+ /* but we won't read more than the max buffer size */
+ if (pend > BUFSIZE)
+ pend = BUFSIZE;
+
+ /* round down to an integral number of XReps */
+ pend = (pend / SIZEOF(fsEvent)) * SIZEOF(fsEvent);
+
+ _FSRead(svr, buf, (long)pend);
+
+ /* no space between comma and type or else macro will die */
+ STARTITERATE(ev, fsEvent, buf, (pend > 0),
+ pend -= SIZEOF(fsEvent)) {
+ if (ev->type == FS_Error)
+ _FSError(svr, (fsError *) ev);
+ else /* it's an event packet; enqueue it */
+ _FSEnq(svr, ev);
+ }
+ ENDITERATE
+ } while (svr->head == NULL);
+}
+
+/*
+ * _FSRead - Read bytes from the socket taking into account incomplete
+ * reads. This routine may have to be reworked if int < long.
+ */
+void
+_FSRead(svr, data, size)
+ register FSServer *svr;
+ register char *data;
+ register long size;
+{
+ register long bytes_read;
+#if defined(SVR4) && defined(i386)
+ int num_failed_reads = 0;
+#endif
+
+ if (size == 0)
+ return;
+ ESET(0);
+ /*
+ * For SVR4 with a unix-domain connection, ETEST() after selecting
+ * readable means the server has died. To do this here, we look for
+ * two consecutive reads returning ETEST().
+ */
+ while ((bytes_read = _FSTransRead(svr->trans_conn, data, (int) size))
+ != size) {
+
+ if (bytes_read > 0) {
+ size -= bytes_read;
+ data += bytes_read;
+#if defined(SVR4) && defined(i386)
+ num_failed_reads = 0;
+#endif
+ }
+ else if (ETEST()) {
+ _FSWaitForReadable(svr);
+#if defined(SVR4) && defined(i386)
+ num_failed_reads++;
+ if (num_failed_reads > 1) {
+ ESET(EPIPE);
+ (*_FSIOErrorFunction) (svr);
+ }
+#endif
+ ESET(0);
+ }
+#ifdef SUNSYSV
+ else if (ECHECK(0)) {
+ _FSWaitForReadable(svr);
+ }
+#endif
+
+ else if (bytes_read == 0) {
+ /* Read failed because of end of file! */
+ ESET(EPIPE);
+ (*_FSIOErrorFunction) (svr);
+ } else { /* bytes_read is less than 0; presumably -1 */
+ /* If it's a system call interrupt, it's not an error. */
+ if (!ECHECK(EINTR))
+ (*_FSIOErrorFunction) (svr);
+#if defined(SVR4) && defined(i386)
+ else
+ num_failed_reads = 0;
+#endif
+ }
+ }
+}
+
+#ifdef WORD64
+/*
+ * XXX This is a *really* stupid way of doing this....
+ */
+
+#define PACKBUFFERSIZE 4096
+
+
+/*
+ * _FSRead32 - Read bytes from the socket unpacking each 32 bits
+ * into a long (64 bits on a CRAY computer).
+ *
+ */
+static void
+_doFSRead32(svr, data, size, packbuffer)
+ register FSServer *svr;
+ register long *data;
+ register long size;
+ register char *packbuffer;
+{
+ long *lpack,
+ *lp;
+ long mask32 = 0x00000000ffffffff;
+ long maskw,
+ nwords,
+ i,
+ bits;
+
+ _FSReadPad(svr, packbuffer, size);
+
+ lp = data;
+ lpack = (long *) packbuffer;
+ nwords = size >> 2;
+ bits = 32;
+
+ for (i = 0; i < nwords; i++) {
+ maskw = mask32 << bits;
+ *lp++ = (*lpack & maskw) >> bits;
+ bits = bits ^ 32;
+ if (bits) {
+ lpack++;
+ }
+ }
+}
+
+void
+_FSRead32(svr, data, len)
+ FSServer *svr;
+ long *data;
+ long len;
+{
+ char packbuffer[PACKBUFFERSIZE];
+ unsigned nwords = (PACKBUFFERSIZE >> 2); /* bytes to CARD32 */
+
+ for (; len > nwords; len -= nwords, data += nwords) {
+ _doFSRead32(svr, data, nwords, packbuffer);
+ }
+ _doFSRead32(svr, data, len, packbuffer);
+}
+
+
+
+/*
+ * _FSRead16 - Read bytes from the socket unpacking each 16 bits
+ * into a long (64 bits on a CRAY computer).
+ *
+ */
+static void
+_doFSRead16(svr, data, size, packbuffer)
+ register FSServer *svr;
+ register short *data;
+ register long size;
+ char *packbuffer;
+{
+ long *lpack,
+ *lp;
+ long mask16 = 0x000000000000ffff;
+ long maskw,
+ nwords,
+ i,
+ bits;
+
+ _FSRead(svr, packbuffer, size); /* don't do a padded read... */
+
+ lp = (long *) data;
+ lpack = (long *) packbuffer;
+ nwords = size >> 1; /* number of 16 bit words to be unpacked */
+ bits = 48;
+ for (i = 0; i < nwords; i++) {
+ maskw = mask16 << bits;
+ *lp++ = (*lpack & maskw) >> bits;
+ bits -= 16;
+ if (bits < 0) {
+ lpack++;
+ bits = 48;
+ }
+ }
+}
+
+void
+_FSRead16(svr, data, len)
+ FSServer *svr;
+ short *data;
+ long len;
+{
+ char packbuffer[PACKBUFFERSIZE];
+ unsigned nwords = (PACKBUFFERSIZE >> 1); /* bytes to CARD16 */
+
+ for (; len > nwords; len -= nwords, data += nwords) {
+ _doFSRead16(svr, data, nwords, packbuffer);
+ }
+ _doFSRead16(svr, data, len, packbuffer);
+}
+
+void
+_FSRead16Pad(svr, data, size)
+ FSServer *svr;
+ short *data;
+ long size;
+{
+ int slop = (size & 3);
+ short slopbuf[3];
+
+ _FSRead16(svr, data, size);
+ if (slop > 0) {
+ _FSRead16(svr, slopbuf, 4 - slop);
+ }
+}
+
+#endif /* WORD64 */
+
+
+/*
+ * _FSReadPad - Read bytes from the socket taking into account incomplete
+ * reads. If the number of bytes is not 0 mod 32, read additional pad
+ * bytes. This routine may have to be reworked if int < long.
+ */
+void
+_FSReadPad(svr, data, size)
+ register FSServer *svr;
+ register char *data;
+ register long size;
+{
+ register long bytes_read;
+ struct iovec iov[2];
+ char pad[3];
+
+ if (size == 0)
+ return;
+ iov[0].iov_len = (int) size;
+ iov[0].iov_base = data;
+ /*
+ * The following hack is used to provide 32 bit long-word aligned padding.
+ * The [1] vector is of length 0, 1, 2, or 3, whatever is needed.
+ */
+
+ iov[1].iov_len = padlength[size & 3];
+ iov[1].iov_base = pad;
+ size += iov[1].iov_len;
+
+ ESET(0);
+ while ((bytes_read = _FSTransReadv(svr->trans_conn, iov, 2)) != size) {
+
+ if (bytes_read > 0) {
+ size -= bytes_read;
+ if (iov[0].iov_len < bytes_read) {
+ int pad_bytes_read = bytes_read - iov[0].iov_len;
+ iov[1].iov_len -= pad_bytes_read;
+ iov[1].iov_base =
+ (char *)iov[1].iov_base + pad_bytes_read;
+ iov[0].iov_len = 0;
+ } else {
+ iov[0].iov_len -= bytes_read;
+ iov[0].iov_base = (char *)iov[0].iov_base + bytes_read;
+ }
+ }
+ else if (ETEST()) {
+ _FSWaitForReadable(svr);
+ ESET(0);
+ }
+#ifdef SUNSYSV
+ else if (ECHECK(0)) {
+ _FSWaitForReadable(svr);
+ }
+#endif
+
+ else if (bytes_read == 0) {
+ /* Read failed because of end of file! */
+ ESET(EPIPE);
+ (*_FSIOErrorFunction) (svr);
+ } else { /* bytes_read is less than 0; presumably -1 */
+ /* If it's a system call interrupt, it's not an error. */
+ if (!ECHECK(EINTR))
+ (*_FSIOErrorFunction) (svr);
+ }
+ }
+}
+
+/*
+ * _FSSend - Flush the buffer and send the client data. 32 bit word aligned
+ * transmission is used, if size is not 0 mod 4, extra bytes are transmitted.
+ * This routine may have to be reworked if int < long;
+ */
+void
+_FSSend(svr, data, size)
+ register FSServer *svr;
+ char *data;
+ register long size;
+{
+ struct iovec iov[3];
+ static char pad[3] = {0, 0, 0};
+
+ long skip = 0;
+ long svrbufsize = (svr->bufptr - svr->buffer);
+ long padsize = padlength[size & 3];
+ long total = svrbufsize + size + padsize;
+ long todo = total;
+
+ /*
+ * There are 3 pieces that may need to be written out:
+ *
+ * o whatever is in the display buffer o the data passed in by the user o
+ * any padding needed to 32bit align the whole mess
+ *
+ * This loop looks at all 3 pieces each time through. It uses skip to figure
+ * out whether or not a given piece is needed.
+ */
+ while (total) {
+ long before = skip; /* amount of whole thing written */
+ long remain = todo; /* amount to try this time, <= total */
+ int i = 0;
+ long len;
+
+ /*
+ * You could be very general here and have "in" and "out" iovecs and
+ * write a loop without using a macro, but what the heck. This
+ * translates to:
+ *
+ * how much of this piece is new? if more new then we are trying this
+ * time, clamp if nothing new then bump down amount already written,
+ * for next piece else put new stuff in iovec, will need all of next
+ * piece
+ *
+ * Note that todo had better be at least 1 or else we'll end up writing 0
+ * iovecs.
+ */
+#define InsertIOV(pointer, length) \
+ len = (length) - before; \
+ if (len > remain) \
+ len = remain; \
+ if (len <= 0) { \
+ before = (-len); \
+ } else { \
+ iov[i].iov_len = len; \
+ iov[i].iov_base = (pointer) + before; \
+ i++; \
+ remain -= len; \
+ before = 0; \
+ }
+
+ InsertIOV(svr->buffer, svrbufsize)
+ InsertIOV(data, size)
+ InsertIOV(pad, padsize)
+
+ ESET(0);
+ if ((len = _FSTransWritev(svr->trans_conn, iov, i)) >= 0) {
+ skip += len;
+ total -= len;
+ todo = total;
+ } else if (ETEST()) {
+ _FSWaitForWritable(svr);
+#ifdef SUNSYSV
+ } else if (ECHECK(0)) {
+ _FSWaitForWritable(svr);
+#endif
+
+#ifdef EMSGSIZE
+ } else if (ECHECK(EMSGSIZE)) {
+ if (todo > 1)
+ todo >>= 1;
+ else
+ _FSWaitForWritable(svr);
+#endif
+ } else {
+ (*_FSIOErrorFunction) (svr);
+ }
+ }
+
+ svr->bufptr = svr->buffer;
+ svr->last_req = (char *) &_dummy_request;
+}
+
+#ifdef undef
+/*
+ * _FSAllocID - normal resource ID allocation routine. A client
+ * can roll his own and instatantiate it if he wants, but must
+ * follow the rules.
+ */
+FSID
+_FSAllocID(svr)
+ register FSServer *svr;
+{
+ return (svr->resource_base + (svr->resource_id++ << svr->resource_shift));
+}
+
+#endif
+
+/*
+ * The hard part about this is that we only get 16 bits from a reply. Well,
+ * then, we have three values that will march along, with the following
+ * invariant:
+ * svr->last_request_read <= rep->sequenceNumber <= svr->request
+ * The right choice for rep->sequenceNumber is the largest that
+ * still meets these constraints.
+ */
+
+unsigned long
+_FSSetLastRequestRead(svr, rep)
+ register FSServer *svr;
+ register fsGenericReply *rep;
+{
+ register unsigned long newseq,
+ lastseq;
+
+ newseq = (svr->last_request_read & ~((unsigned long) 0xffff)) |
+ rep->sequenceNumber;
+ lastseq = svr->last_request_read;
+ while (newseq < lastseq) {
+ newseq += 0x10000;
+ if (newseq > svr->request) {
+ (void) fprintf(stderr,
+ "FSlib: sequence lost (0x%lx > 0x%lx) in reply type 0x%x!\n",
+ newseq, svr->request,
+ (unsigned int) rep->type);
+ newseq -= 0x10000;
+ break;
+ }
+ }
+
+ svr->last_request_read = newseq;
+ return (newseq);
+}
+
+/*
+ * _FSReply - Wait for a reply packet and copy its contents into the
+ * specified rep. Mean while we must handle error and event packets that
+ * we may encounter.
+ */
+Status
+_FSReply(svr, rep, extra, discard)
+ register FSServer *svr;
+ register fsReply *rep;
+ int extra; /* number of 32-bit words expected after the
+ * reply */
+ Bool discard; /* should I discard data followind "extra"
+ * words? */
+{
+ /*
+ * Pull out the serial number now, so that (currently illegal) requests
+ * generated by an error handler don't confuse us.
+ */
+ unsigned long cur_request = svr->request;
+ long rem_length;
+
+ _FSFlush(svr);
+ while (1) {
+ _FSRead(svr, (char *) rep, (long) SIZEOF(fsReply));
+ switch ((int) rep->generic.type) {
+
+ case FS_Reply:
+ /*
+ * Reply received. Fast update for synchronous replies, but deal
+ * with multiple outstanding replies.
+ */
+ if (rep->generic.sequenceNumber == (cur_request & 0xffff))
+ svr->last_request_read = cur_request;
+ else
+ (void) _FSSetLastRequestRead(svr, &rep->generic);
+ rem_length = rep->generic.length - (SIZEOF(fsReply) >> 2);
+ if (rem_length < 0) rem_length = 0;
+ if (extra == 0) {
+ if (discard && rem_length)
+ /* unexpectedly long reply! */
+ _EatData32(svr, rem_length);
+ return (1);
+ }
+ if (extra == rem_length) {
+ /*
+ * Read the extra data into storage immediately following the
+ * GenericReply structure.
+ */
+ _FSRead(svr, (char *) NEXTPTR(rep, fsReply), ((long) extra) << 2);
+ return (1);
+ }
+ if (extra < rem_length) {
+ /* Actual reply is longer than "extra" */
+ _FSRead(svr, (char *) NEXTPTR(rep, fsReply), ((long) extra) << 2);
+ if (discard)
+ _EatData32(svr, rem_length - extra);
+ return (1);
+ }
+ /*
+ * if we get here, then extra > rem_length -- meaning we
+ * read a reply that's shorter than we expected. This is an
+ * error, but we still need to figure out how to handle it...
+ */
+ _FSRead(svr, (char *) NEXTPTR(rep, fsReply), rem_length << 2);
+ (*_FSIOErrorFunction) (svr);
+ return (0);
+
+ case FS_Error:
+ {
+ register _FSExtension *ext;
+ register Bool ret = False;
+ int ret_code;
+ fsError err;
+ unsigned long serial;
+ long err_data;
+
+ err = *(fsError *) rep;
+ /* read the rest of the error */
+ _FSRead(svr, (char *) &err + SIZEOF(fsReply),
+ (long) (SIZEOF(fsError) - SIZEOF(fsReply)));
+ serial = _FSSetLastRequestRead(svr, (fsGenericReply *) rep);
+ if (serial == cur_request)
+ /* do not die on certain failures */
+ switch ((int) err.request) {
+ /* suck in any extra error info */
+ case FSBadResolution:
+ case FSBadLength:
+ case FSBadIDChoice:
+ case FSBadRange:
+ case FSBadFont:
+ case FSBadFormat:
+ _FSRead(svr, (char *) &err_data, 4);
+ break;
+ case FSBadAccessContext:
+ _FSRead(svr, (char *) &err_data, 4);
+ return 0;
+ case FSBadAlloc:
+ return (0);
+ /*
+ * we better see if there is an extension who may want
+ * to suppress the error.
+ */
+ default:
+ ext = svr->ext_procs;
+ while (ext) {
+ if (ext->error != NULL)
+ ret = (*ext->error)
+ (svr, &err, &ext->codes, &ret_code);
+ ext = ext->next;
+ }
+ if (ret)
+ return (ret_code);
+ break;
+ }
+ _FSError(svr, &err);
+ if (serial == cur_request)
+ return (0);
+ }
+ break;
+ default:
+ _FSEnq(svr, (fsEvent *) rep);
+ break;
+ }
+ }
+}
+
+
+/* Read and discard "n" 8-bit bytes of data */
+
+void
+_FSEatData(svr, n)
+ FSServer *svr;
+ register unsigned long n;
+{
+#define SCRATCHSIZE 2048
+ char buf[SCRATCHSIZE];
+
+ while (n > 0) {
+ register long bytes_read = (n > SCRATCHSIZE) ? SCRATCHSIZE : n;
+
+ _FSRead(svr, buf, bytes_read);
+ n -= bytes_read;
+ }
+#undef SCRATCHSIZE
+}
+
+
+/* Read and discard "n" 32-bit words. */
+
+static void
+_EatData32(svr, n)
+ FSServer *svr;
+ unsigned long n;
+{
+ _FSEatData(svr, n << 2);
+}
+
+
+/*
+ * _FSEnq - Place event packets on the display's queue.
+ * note that no squishing of move events in V11, since there
+ * is pointer motion hints....
+ */
+void
+_FSEnq(svr, event)
+ register FSServer *svr;
+ register fsEvent *event;
+{
+ register _FSQEvent *qelt;
+
+/*NOSTRICT*/
+ if ((qelt = _FSqfree) != NULL) {
+ /* If _FSqfree is non-NULL do this, else malloc a new one. */
+ _FSqfree = qelt->next;
+ } else if ((qelt =
+ (_FSQEvent *) FSmalloc((unsigned) sizeof(_FSQEvent))) == NULL) {
+ /* Malloc call failed! */
+ ESET(ENOMEM);
+ (*_FSIOErrorFunction) (svr);
+ }
+ qelt->next = NULL;
+ /* go call through display to find proper event reformatter */
+ if ((*svr->event_vec[event->type & 0177]) (svr, &qelt->event, event)) {
+ if (svr->tail)
+ svr->tail->next = qelt;
+ else
+ svr->head = qelt;
+
+ svr->tail = qelt;
+ svr->qlen++;
+ } else {
+ /* ignored, or stashed away for many-to-one compression */
+ qelt->next = _FSqfree;
+ _FSqfree = qelt;
+ }
+}
+
+/*
+ * EventToWire in seperate file in that often not needed.
+ */
+
+/*ARGSUSED*/
+Bool
+_FSUnknownWireEvent(svr, re, event)
+ register FSServer *svr; /* pointer to display structure */
+ register FSEvent *re; /* pointer to where event should be
+ * reformatted */
+ register fsEvent *event; /* wire protocol event */
+{
+
+#ifdef notdef
+ (void) fprintf(stderr,
+ "FSlib: unhandled wire event! event number = %d, display = %x\n.",
+ event->type, svr);
+#endif
+
+ return (False);
+}
+
+/*ARGSUSED*/
+Status
+_FSUnknownNativeEvent(svr, re, event)
+ register FSServer *svr; /* pointer to display structure */
+ register FSEvent *re; /* pointer to where event should be
+ * reformatted */
+ register fsEvent *event; /* wire protocol event */
+{
+
+#ifdef notdef
+ (void) fprintf(stderr,
+ "FSlib: unhandled native event! event number = %d, display = %x\n.",
+ re->type, svr);
+#endif
+
+ return (0);
+}
+
+/*
+ * reformat a wire event into an FSEvent structure of the right type.
+ */
+Bool
+_FSWireToEvent(svr, re, event)
+ register FSServer *svr; /* pointer to display structure */
+ register FSEvent *re; /* pointer to where event should be
+ * reformatted */
+ register fsEvent *event; /* wire protocol event */
+{
+
+ re->type = event->type & 0x7f;
+ ((FSAnyEvent *) re)->serial = _FSSetLastRequestRead(svr,
+ (fsGenericReply *) event);
+ ((FSAnyEvent *) re)->send_event = ((event->type & 0x80) != 0);
+ ((FSAnyEvent *) re)->server = svr;
+
+ /*
+ * Ignore the leading bit of the event type since it is set when a client
+ * sends an event rather than the server.
+ */
+
+ switch (event->type & 0177) {
+ default:
+ return (_FSUnknownWireEvent(svr, re, event));
+ }
+}
+
+
+static char *
+_SysErrorMsg(n)
+ int n;
+{
+ char *s = strerror(n);
+
+ return (s ? s : "no such error");
+}
+
+/*
+ * _FSDefaultIOError - Default fatal system error reporting routine. Called
+ * when an X internal system error is encountered.
+ */
+int
+_FSDefaultIOError(svr)
+ FSServer *svr;
+{
+ (void) fprintf(stderr,
+ "FSIO: fatal IO error %d (%s) on font server \"%s\"\r\n",
+#ifdef WIN32
+ WSAGetLastError(), strerror(WSAGetLastError()),
+#else
+
+ errno, _SysErrorMsg(errno),
+#endif
+ FSServerString(svr));
+ (void) fprintf(stderr,
+ " after %lu requests (%lu known processed) with %d events remaining.\r\n",
+ FSNextRequest(svr) - 1, FSLastKnownRequestProcessed(svr),
+ FSQLength(svr));
+
+ if (ECHECK(EPIPE)) {
+ (void) fprintf(stderr,
+ " The connection was probably broken by a server shutdown.\r\n");
+ }
+ exit(1);
+ /* NOTREACHED */
+}
+
+/*
+ * _FSError - Default non-fatal error reporting routine. Called when an
+ * FS_Error packet is encountered in the input stream.
+ */
+int
+_FSError(svr, rep)
+ FSServer *svr;
+ fsError *rep;
+{
+ FSErrorEvent event;
+
+ /*
+ * FS_Error packet encountered! We need to unpack the error before giving
+ * it to the user.
+ */
+
+ event.server = svr;
+ event.type = FS_Error;
+ event.serial = _FSSetLastRequestRead(svr, (fsGenericReply *) rep);
+ event.error_code = rep->request;
+ event.request_code = rep->major_opcode;
+ event.minor_code = rep->minor_opcode;
+ if (_FSErrorFunction != NULL) {
+ return ((*_FSErrorFunction) (svr, &event));
+ }
+ exit(1);
+ /* NOTREACHED */
+}
+
+int
+_FSPrintDefaultError(svr, event, fp)
+ FSServer *svr;
+ FSErrorEvent *event;
+ FILE *fp;
+{
+ char buffer[BUFSIZ];
+ char mesg[BUFSIZ];
+ char number[32];
+ char *mtype = "FSlibMessage";
+ register _FSExtension *ext = (_FSExtension *) NULL;
+
+ (void) FSGetErrorText(svr, event->error_code, buffer, BUFSIZ);
+ (void) FSGetErrorDatabaseText(svr, mtype, "FSError", "FS Error", mesg,
+ BUFSIZ);
+ (void) fprintf(fp, "%s: %s\n ", mesg, buffer);
+ (void) FSGetErrorDatabaseText(svr, mtype, "MajorCode",
+ "Request Major code %d", mesg, BUFSIZ);
+ (void) fprintf(fp, mesg, event->request_code);
+ if (event->request_code < 128) {
+ sprintf(number, "%d", event->request_code);
+ (void) FSGetErrorDatabaseText(svr, "FSRequest", number, "", buffer,
+ BUFSIZ);
+ } else {
+ for (ext = svr->ext_procs;
+ ext && (ext->codes.major_opcode != event->request_code);
+ ext = ext->next);
+ if (ext)
+ strcpy(buffer, ext->name);
+ else
+ buffer[0] = '\0';
+ }
+ (void) fprintf(fp, " (%s)\n ", buffer);
+ (void) FSGetErrorDatabaseText(svr, mtype, "MinorCode",
+ "Request Minor code %d", mesg, BUFSIZ);
+ (void) fprintf(fp, mesg, event->minor_code);
+ if (ext) {
+ sprintf(mesg, "%s.%d", ext->name, event->minor_code);
+ (void) FSGetErrorDatabaseText(svr, "FSRequest", mesg, "", buffer,
+ BUFSIZ);
+ (void) fprintf(fp, " (%s)", buffer);
+ }
+ fputs("\n ", fp);
+ (void) FSGetErrorDatabaseText(svr, mtype, "ResourceID", "ResourceID 0x%x",
+ mesg, BUFSIZ);
+ (void) fprintf(fp, mesg, event->resourceid);
+ fputs("\n ", fp);
+ (void) FSGetErrorDatabaseText(svr, mtype, "ErrorSerial", "Error Serial #%d",
+ mesg, BUFSIZ);
+ (void) fprintf(fp, mesg, event->serial);
+ fputs("\n ", fp);
+ (void) FSGetErrorDatabaseText(svr, mtype, "CurrentSerial",
+ "Current Serial #%d", mesg, BUFSIZ);
+ (void) fprintf(fp, mesg, svr->request);
+ fputs("\n", fp);
+ return 1;
+}
+
+int
+_FSDefaultError(svr, event)
+ FSServer *svr;
+ FSErrorEvent *event;
+{
+ if (_FSPrintDefaultError(svr, event, stderr) == 0)
+ return 0;
+ exit(1);
+ /* NOTREACHED */
+}
+
+
+FSIOErrorHandler _FSIOErrorFunction = _FSDefaultIOError;
+FSErrorHandler _FSErrorFunction = _FSDefaultError;
+
+/*
+ * This routine can be used to (cheaply) get some memory within a single
+ * Xlib routine for scratch space. It is reallocated from the same place
+ * each time, unless the library needs a large scratch space.
+ */
+char *
+_FSAllocScratch(svr, nbytes)
+ register FSServer *svr;
+ unsigned long nbytes;
+{
+ if (nbytes > svr->scratch_length) {
+ if (svr->scratch_buffer != NULL)
+ FSfree(svr->scratch_buffer);
+ return (svr->scratch_length = nbytes,
+ svr->scratch_buffer = FSmalloc((unsigned) nbytes));
+ }
+ return (svr->scratch_buffer);
+}
+
+int
+FSFree(data)
+ char *data;
+{
+ FSfree(data);
+ return 1;
+}
+
+unsigned char *
+FSMalloc(size)
+ unsigned size;
+{
+ return (unsigned char *) FSmalloc(size);
+}
+
+#ifdef DataRoutineIsProcedure
+void
+Data(svr, data, len)
+ FSServer *svr;
+ char *data;
+ long len;
+{
+ if (svr->bufptr + (len) <= svr->bufmax) {
+ bcopy(data, svr->bufptr, (int) len);
+ svr->bufptr += ((len) + 3) & ~3;
+ } else {
+ _FSSend(svr, data, len);
+ }
+}
+
+#endif /* DataRoutineIsProcedure */
+
+
+#ifdef WORD64
+/*
+ * XXX This is a *really* stupid way of doing this. It should just use
+ * svr->bufptr directly, taking into account where in the word it is.
+ */
+
+/*
+ * Data16 - Place 16 bit data in the buffer.
+ *
+ * "svr" is a pointer to a FSServer.
+ * "data" is a pointer to the data.
+ * "len" is the length in bytes of the data.
+ */
+
+static void
+doData16(svr, data, len, packbuffer)
+ register FSServer *svr;
+ short *data;
+ unsigned len;
+ char *packbuffer;
+{
+ long *lp,
+ *lpack;
+ long i,
+ nwords,
+ bits;
+ long mask16 = 0x000000000000ffff;
+
+ lp = (long *) data;
+ lpack = (long *) packbuffer;
+ *lpack = 0;
+
+/* nwords is the number of 16 bit values to be packed,
+ * the low order 16 bits of each word will be packed
+ * into 64 bit words
+ */
+ nwords = len >> 1;
+ bits = 48;
+
+ for (i = 0; i < nwords; i++) {
+ *lpack ^= (*lp & mask16) << bits;
+ bits -= 16;
+ lp++;
+ if (bits < 0) {
+ lpack++;
+ *lpack = 0;
+ bits = 48;
+ }
+ }
+ Data(svr, packbuffer, len);
+}
+
+void
+Data16(svr, data, len)
+ FSServer *svr;
+ short *data;
+ unsigned len;
+{
+ char packbuffer[PACKBUFFERSIZE];
+ unsigned nwords = (PACKBUFFERSIZE >> 1); /* bytes to CARD16 */
+
+ for (; len > nwords; len -= nwords, data += nwords) {
+ doData16(svr, data, nwords, packbuffer);
+ }
+ doData16(svr, data, len, packbuffer);
+}
+
+/*
+ * Data32 - Place 32 bit data in the buffer.
+ *
+ * "svr" is a pointer to a FSServer.
+ * "data" is a pointer to the data.
+ * "len" is the length in bytes of the data.
+ */
+
+static
+doData32(svr, data, len, packbuffer)
+ register FSServer *svr;
+ long *data;
+ unsigned len;
+ char *packbuffer;
+{
+ long *lp,
+ *lpack;
+ long i,
+ bits,
+ nwords;
+ long mask32 = 0x00000000ffffffff;
+
+ lpack = (long *) packbuffer;
+ lp = data;
+
+ *lpack = 0;
+
+/* nwords is the number of 32 bit values to be packed
+ * the low order 32 bits of each word will be packed
+ * into 64 bit words
+ */
+ nwords = len >> 2;
+ bits = 32;
+
+ for (i = 0; i < nwords; i++) {
+ *lpack ^= (*lp & mask32) << bits;
+ bits = bits ^ 32;
+ lp++;
+ if (bits) {
+ lpack++;
+ *lpack = 0;
+ }
+ }
+ Data(svr, packbuffer, len);
+}
+
+void
+Data32(svr, data, len)
+ FSServer *svr;
+ short *data;
+ unsigned len;
+{
+ char packbuffer[PACKBUFFERSIZE];
+ unsigned nwords = (PACKBUFFERSIZE >> 2); /* bytes to CARD32 */
+
+ for (; len > nwords; len -= nwords, data += nwords) {
+ doData32(svr, data, nwords, packbuffer);
+ }
+ doData32(svr, data, len, packbuffer);
+}
+
+#endif /* WORD64 */
+
+
+
+/*
+ * _FSFreeQ - free the queue of events, called by XCloseServer when there are
+ * no more displays left on the display list
+ */
+
+void
+_FSFreeQ()
+{
+ register _FSQEvent *qelt = _FSqfree;
+
+ while (qelt) {
+ register _FSQEvent *qnext = qelt->next;
+
+ FSfree(qelt);
+ qelt = qnext;
+ }
+ _FSqfree = NULL;
+ return;
+}
+
+#ifdef _POSIX_SOURCE /* stupid makedepend [need if] */
+#ifndef __QNX__ /* QNX's uname nodename entry is not same as tcpip hostname */
+#define NEED_UTSNAME
+#endif
+#endif
+#ifdef hpux
+#define NEED_UTSNAME
+#endif
+#ifdef USG
+#define NEED_UTSNAME
+#endif
+#ifdef SVR4
+#ifndef _SEQUENT_
+#define NEED_UTSNAME
+#endif
+#endif
+
+#ifdef NEED_UTSNAME
+#include <sys/utsname.h>
+#endif
+
+
+/*
+ * _FSGetHostname - similar to gethostname but allows special processing.
+ */
+int
+_FSGetHostname(buf, maxlen)
+ char *buf;
+ int maxlen;
+{
+ int len;
+
+#ifdef NEED_UTSNAME
+ /*
+ * same host name crock as in server and xinit.
+ */
+ struct utsname name;
+
+ uname(&name);
+ len = strlen(name.nodename);
+ if (len >= maxlen)
+ len = maxlen - 1;
+ strncpy(buf, name.nodename, len);
+ buf[len] = '\0';
+#else
+ buf[0] = '\0';
+ (void) gethostname(buf, maxlen);
+ buf[maxlen - 1] = '\0';
+ len = strlen(buf);
+#endif /* NEED_UTSNAME */
+
+ return len;
+}
+
+#ifndef _FSANYSET
+/*
+ * This is not always a macro.
+ */
+_FSANYSET(src)
+ long *src;
+{
+ int i;
+
+ for (i=0; i<MSKCNT; i++)
+ if (src[ i ])
+ return (1);
+ return (0);
+}
+#endif