1 /* $XConsortium: fsio.c,v 1.37 95/04/05 19:58:13 kaleb Exp $ */
2 /* $XFree86: xc/lib/font/fc/fsio.c,v 3.5.2.1 1998/02/15 16:08:40 hohndel Exp $ */
4 * Copyright 1990 Network Computing Devices
6 * Permission to use, copy, modify, distribute, and sell this software and its
7 * documentation for any purpose is hereby granted without fee, provided that
8 * the above copyright notice appear in all copies and that both that
9 * copyright notice and this permission notice appear in supporting
10 * documentation, and that the name of Network Computing Devices not be
11 * used in advertising or publicity pertaining to distribution of the
12 * software without specific, written prior permission. Network Computing
13 * Devices makes no representations about the suitability of this software
14 * for any purpose. It is provided "as is" without express or implied
17 * NETWORK COMPUTING DEVICES DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
18 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
19 * IN NO EVENT SHALL NETWORK COMPUTING DEVICES BE LIABLE FOR ANY SPECIAL,
20 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
21 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
22 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
23 * OR PERFORMANCE OF THIS SOFTWARE.
25 * Author: Dave Lemke, Network Computing Devices, Inc
28 * font server i/o routines
38 #include "X11/Xtrans.h"
39 #include "X11/Xpoll.h"
45 #include <sys/types.h>
46 #if !defined(WIN32) && !defined(AMOEBA) && !defined(_MINIX)
48 #include <sys/socket.h>
58 #define EWOULDBLOCK WSAEWOULDBLOCK
60 #define EINTR WSAEINTR
65 #define select(n,r,w,x,t) nbio_select(n,r,w,x,t)
69 #define select(n,r,w,x,t) os2PseudoSelect(n,r,w,x,t)
72 /* check for both EAGAIN and EWOULDBLOCK, because some supposedly POSIX
73 * systems are broken and return EWOULDBLOCK when they should return EAGAIN
76 #define ETEST() (WSAGetLastError() == WSAEWOULDBLOCK)
78 #if defined(EAGAIN) && defined(EWOULDBLOCK)
79 #define ETEST() (errno == EAGAIN || errno == EWOULDBLOCK)
82 #define ETEST() (errno == EAGAIN)
84 #define ETEST() (errno == EWOULDBLOCK)
89 #define ECHECK(err) (WSAGetLastError() == err)
90 #define ESET(val) WSASetLastError(val)
93 #define ECHECK(err) ((errno == err) || ETEST())
95 #define ECHECK(err) (errno == err)
97 #define ESET(val) errno = val
100 static int padlength[4] = {0, 3, 2, 1};
103 int _fs_wait_for_readable();
105 #ifdef SIGNALRETURNSINT
108 #define SIGNAL_T void
119 static XtransConnInfo
120 _fs_connect(servername, timeout)
124 XtransConnInfo trans_conn; /* transport connection object */
129 SIGNAL_T(*oldAlarm) ();
133 * Open the network connection.
135 if( (trans_conn=_FontTransOpenCOTSClient(servername)) == NULL )
141 oldTime = alarm((unsigned) 0);
142 oldAlarm = signal(SIGALRM, _fs_alarm);
143 alarm((unsigned) timeout);
146 ret = _FontTransConnect(trans_conn,servername);
150 signal(SIGALRM, oldAlarm);
156 _FontTransClose(trans_conn);
161 * Set the connection non-blocking since we use select() to block.
164 _FontTransSetOption(trans_conn, TRANS_NONBLOCKING, 1);
169 static int generationCount;
173 _fs_setup_connection(conn, servername, timeout, copy_name_p)
179 fsConnClientPrefix prefix;
182 fsConnSetupAccept conn_accept;
186 char *auth_data = NULL,
187 *vendor_string = NULL,
193 if ((conn->trans_conn = _fs_connect(servername, 5)) == NULL)
196 conn->fs_fd = _FontTransGetConnectionNumber (conn->trans_conn);
198 conn->generation = ++generationCount;
200 /* send setup prefix */
202 if (*(char *) &endian)
203 prefix.byteOrder = 'l';
205 prefix.byteOrder = 'B';
207 prefix.major_version = FS_PROTOCOL;
208 prefix.minor_version = FS_PROTOCOL_MINOR;
210 /* XXX add some auth info here */
211 prefix.num_auths = 0;
214 if (_fs_write(conn, (char *) &prefix, SIZEOF(fsConnClientPrefix)) == -1)
217 /* read setup info */
218 if (_fs_read(conn, (char *) &rep, SIZEOF(fsConnSetup)) == -1)
221 conn->fsMajorVersion = rep.major_version;
222 if (rep.major_version > FS_PROTOCOL)
226 /* parse alternate list */
227 if (nalts = rep.num_alternates) {
228 setuplength = rep.alternate_len << 2;
229 alts = (FSFpeAltPtr) xalloc(nalts * sizeof(FSFpeAltRec) +
232 _FontTransClose(conn->trans_conn);
236 alt_data = (char *) (alts + nalts);
237 if (_fs_read(conn, (char *) alt_data, setuplength) == -1) {
242 for (i = 0; i < nalts; i++) {
243 alts[i].subset = alt_data[0];
244 alt_len = alt_data[1];
245 alts[i].name = alt_dst;
246 memmove(alt_dst, alt_data + 2, alt_len);
247 alt_dst[alt_len] = '\0';
248 alt_dst += (alt_len + 1);
249 alt_data += (2 + alt_len + padlength[(2 + alt_len) & 3]);
255 conn->numAlts = nalts;
257 setuplength = rep.auth_len << 2;
259 !(auth_data = (char *) xalloc((unsigned int) setuplength))) {
260 _FontTransClose(conn->trans_conn);
264 if (_fs_read(conn, (char *) auth_data, setuplength) == -1) {
268 if (rep.status != AuthSuccess) {
270 _FontTransClose(conn->trans_conn);
275 if (_fs_read(conn, (char *) &conn_accept, (long) SIZEOF(fsConnSetupAccept)) == -1) {
279 if ((vendor_string = (char *)
280 xalloc((unsigned) conn_accept.vendor_len + 1)) == NULL) {
282 _FontTransClose(conn->trans_conn);
286 if (_fs_read_pad(conn, (char *) vendor_string, conn_accept.vendor_len) == -1) {
287 xfree(vendor_string);
292 xfree(vendor_string);
296 conn->servername = (char *) xalloc(strlen(servername) + 1);
297 if (conn->servername == NULL)
299 strcpy(conn->servername, servername);
302 conn->servername = servername;
308 _fs_try_alternates(conn, timeout)
314 for (i = 0; i < conn->numAlts; i++)
315 if (_fs_setup_connection(conn, conn->alts[i].name, timeout, TRUE))
320 #define FS_OPEN_TIMEOUT 30
321 #define FS_REOPEN_TIMEOUT 10
324 _fs_open_server(servername)
329 conn = (FSFpePtr) xalloc(sizeof(FSFpeRec));
332 return (FSFpePtr) NULL;
334 bzero((char *) conn, sizeof(FSFpeRec));
335 if (!_fs_setup_connection(conn, servername, FS_OPEN_TIMEOUT, TRUE)) {
336 if (!_fs_try_alternates(conn, FS_OPEN_TIMEOUT)) {
339 return (FSFpePtr) NULL;
346 _fs_reopen_server(conn)
349 if (_fs_setup_connection(conn, conn->servername, FS_REOPEN_TIMEOUT, FALSE))
351 if (_fs_try_alternates(conn, FS_REOPEN_TIMEOUT))
357 * expects everything to be here. *not* to be called when reading huge
358 * numbers of replies, but rather to get each chunk
360 _fs_read(conn, data, size)
366 #if defined(SVR4) && defined(i386)
367 int num_failed_reads = 0;
373 fprintf(stderr, "tried to read 0 bytes \n");
380 * For SVR4 with a unix-domain connection, ETEST() after selecting
381 * readable means the server has died. To do this here, we look for
382 * two consecutive reads returning ETEST().
384 while ((bytes_read = _FontTransRead(conn->trans_conn,
385 data, (int) size)) != size) {
386 if (bytes_read > 0) {
389 #if defined(SVR4) && defined(i386)
390 num_failed_reads = 0;
392 } else if (ETEST()) {
393 /* in a perfect world, this shouldn't happen */
394 /* ... but then, its less than perfect... */
395 if (_fs_wait_for_readable(conn) == -1) { /* check for error */
396 _fs_connection_died(conn);
400 #if defined(SVR4) && defined(i386)
402 if (num_failed_reads > 1) {
403 _fs_connection_died(conn);
409 } else if (ECHECK(EINTR)) {
410 #if defined(SVR4) && defined(i386)
411 num_failed_reads = 0;
414 } else { /* something bad happened */
416 _fs_connection_died(conn);
424 _fs_write(conn, data, size)
434 fprintf(stderr, "tried to write 0 bytes \n");
440 /* XXX - hack. The right fix is to remember that the font server
441 has gone away when we first discovered it. */
442 if (!conn->trans_conn)
446 while ((bytes_written = _FontTransWrite(conn->trans_conn,
447 data, (int) size)) != size) {
448 if (bytes_written > 0) {
449 size -= bytes_written;
450 data += bytes_written;
451 } else if (ETEST()) {
452 /* XXX -- we assume this can't happen */
455 fprintf(stderr, "fs_write blocking\n");
457 } else if (ECHECK(EINTR)) {
459 } else { /* something bad happened */
460 _fs_connection_died(conn);
468 _fs_read_pad(conn, data, len)
475 if (_fs_read(conn, data, len) == -1)
479 if (padlength[len & 3]) {
480 return _fs_read(conn, pad, padlength[len & 3]);
485 _fs_write_pad(conn, data, len)
492 if (_fs_write(conn, data, len) == -1)
496 if (padlength[len & 3]) {
497 return _fs_write(conn, pad, padlength[len & 3]);
503 * returns the amount of data waiting to be read
509 BytesReadable_t readable;
511 if (_FontTransBytesReadable(conn->trans_conn, &readable) < 0)
517 _fs_wait_for_readable(conn)
526 fprintf(stderr, "read would block\n");
534 FD_SET(conn->fs_fd, &r_mask);
535 FD_SET(conn->fs_fd, &e_mask);
536 result = Select(conn->fs_fd + 1, &r_mask, NULL, &e_mask, NULL);
538 if (ECHECK(EINTR) || ECHECK(EAGAIN))
543 if (result && FD_ISSET(conn->fs_fd, &e_mask))
545 } while (result <= 0);
549 printf("fs_wait_for_readable(): fail\n");
555 _fs_set_bit(mask, fd)
564 _fs_is_bit_set(mask, fd)
568 return FD_ISSET(fd, mask);
572 _fs_bit_clear(mask, fd)
580 _fs_any_bit_set(mask)
587 _fs_or_bits(dst, m1, m2)
595 for (i = m1->fd_count; --i >= 0; ) {
596 if (!FD_ISSET(m1->fd_array[i], dst))
597 FD_SET(m1->fd_array[i], dst);
601 for (i = m2->fd_count; --i >= 0; ) {
602 if (!FD_ISSET(m2->fd_array[i], dst))
603 FD_SET(m2->fd_array[i], dst);
607 XFD_ORSET(dst, m1, m2);
611 _fs_drain_bytes(conn, len)
618 fprintf(stderr, "draining wire\n");
622 if (_fs_read(conn, buf, (len < 128) ? len : 128) < 0)
629 _fs_drain_bytes_pad(conn, len)
633 _fs_drain_bytes(conn, len);
636 if (padlength[len & 3]) {
637 _fs_drain_bytes(conn, padlength[len & 3]);
641 _fs_eat_rest_of_error(conn, err)
645 int len = (err->length - (SIZEOF(fsGenericReply) >> 2)) << 2;
648 fprintf(stderr, "clearing error\n");
651 _fs_drain_bytes(conn, len);