fsio.c revision a96d7823
1a96d7823Smrg/*
2a96d7823Smrg * Copyright 1990 Network Computing Devices
3a96d7823Smrg *
4a96d7823Smrg * Permission to use, copy, modify, distribute, and sell this software and its
5a96d7823Smrg * documentation for any purpose is hereby granted without fee, provided that
6a96d7823Smrg * the above copyright notice appear in all copies and that both that
7a96d7823Smrg * copyright notice and this permission notice appear in supporting
8a96d7823Smrg * documentation, and that the name of Network Computing Devices not be
9a96d7823Smrg * used in advertising or publicity pertaining to distribution of the
10a96d7823Smrg * software without specific, written prior permission.  Network Computing
11a96d7823Smrg * Devices makes no representations about the suitability of this software
12a96d7823Smrg * for any purpose.  It is provided "as is" without express or implied
13a96d7823Smrg * warranty.
14a96d7823Smrg *
15a96d7823Smrg * NETWORK COMPUTING DEVICES DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
16a96d7823Smrg * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
17a96d7823Smrg * IN NO EVENT SHALL NETWORK COMPUTING DEVICES BE LIABLE FOR ANY SPECIAL,
18a96d7823Smrg * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
19a96d7823Smrg * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
20a96d7823Smrg * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
21a96d7823Smrg * OR PERFORMANCE OF THIS SOFTWARE.
22a96d7823Smrg *
23a96d7823Smrg * Author:  	Dave Lemke, Network Computing Devices, Inc
24a96d7823Smrg */
25a96d7823Smrg/*
26a96d7823Smrg * font server i/o routines
27a96d7823Smrg */
28a96d7823Smrg
29a96d7823Smrg#ifdef HAVE_CONFIG_H
30a96d7823Smrg#include <config.h>
31a96d7823Smrg#endif
32a96d7823Smrg#include "libxfontint.h"
33a96d7823Smrg
34a96d7823Smrg#ifdef WIN32
35a96d7823Smrg#define _WILLWINSOCK_
36a96d7823Smrg#include	"X11/Xwindows.h"
37a96d7823Smrg#endif
38a96d7823Smrg
39a96d7823Smrg#define FONT_t
40a96d7823Smrg#define TRANS_CLIENT
41a96d7823Smrg#include 	"X11/Xtrans/Xtrans.h"
42a96d7823Smrg#include	"X11/Xpoll.h"
43a96d7823Smrg#include	<X11/fonts/FS.h>
44a96d7823Smrg#include	<X11/fonts/FSproto.h>
45a96d7823Smrg#include	<X11/fonts/fontmisc.h>
46a96d7823Smrg#include	<X11/fonts/fontstruct.h>
47a96d7823Smrg#include	"fservestr.h"
48a96d7823Smrg
49a96d7823Smrg#include	<stdio.h>
50a96d7823Smrg#include	<signal.h>
51a96d7823Smrg#include	<sys/types.h>
52a96d7823Smrg#if !defined(WIN32)
53a96d7823Smrg#ifndef Lynx
54a96d7823Smrg#include	<sys/socket.h>
55a96d7823Smrg#else
56a96d7823Smrg#include	<socket.h>
57a96d7823Smrg#endif
58a96d7823Smrg#endif
59a96d7823Smrg#include	<errno.h>
60a96d7823Smrg#ifdef WIN32
61a96d7823Smrg#define EWOULDBLOCK WSAEWOULDBLOCK
62a96d7823Smrg#undef EINTR
63a96d7823Smrg#define EINTR WSAEINTR
64a96d7823Smrg#endif
65a96d7823Smrg
66a96d7823Smrg
67a96d7823Smrg
68a96d7823Smrgstatic int  padlength[4] = {0, 3, 2, 1};
69a96d7823Smrg
70a96d7823Smrgstatic int
71a96d7823Smrg_fs_resize (FSBufPtr buf, long size);
72a96d7823Smrg
73a96d7823Smrgstatic void
74a96d7823Smrg_fs_downsize (FSBufPtr buf, long size);
75a96d7823Smrg
76a96d7823Smrgint
77a96d7823Smrg_fs_poll_connect (XtransConnInfo trans_conn, int timeout)
78a96d7823Smrg{
79a96d7823Smrg    fd_set	    w_mask;
80a96d7823Smrg    struct timeval  tv;
81a96d7823Smrg    int		    fs_fd = _FontTransGetConnectionNumber (trans_conn);
82a96d7823Smrg    int		    ret;
83a96d7823Smrg
84a96d7823Smrg    do
85a96d7823Smrg    {
86a96d7823Smrg	tv.tv_usec = 0;
87a96d7823Smrg	tv.tv_sec = timeout;
88a96d7823Smrg	FD_ZERO (&w_mask);
89a96d7823Smrg	FD_SET (fs_fd, &w_mask);
90a96d7823Smrg	ret = Select (fs_fd + 1, NULL, &w_mask, NULL, &tv);
91a96d7823Smrg    } while (ret < 0 && ECHECK(EINTR));
92a96d7823Smrg    if (ret == 0)
93a96d7823Smrg	return FSIO_BLOCK;
94a96d7823Smrg    if (ret < 0)
95a96d7823Smrg	return FSIO_ERROR;
96a96d7823Smrg    return FSIO_READY;
97a96d7823Smrg}
98a96d7823Smrg
99a96d7823SmrgXtransConnInfo
100a96d7823Smrg_fs_connect(char *servername, int *err)
101a96d7823Smrg{
102a96d7823Smrg    XtransConnInfo  trans_conn;		/* transport connection object */
103a96d7823Smrg    int		    ret;
104a96d7823Smrg    int		    i = 0;
105a96d7823Smrg    int		    retries = 5;
106a96d7823Smrg
107a96d7823Smrg    /*
108a96d7823Smrg     * Open the network connection.
109a96d7823Smrg     */
110a96d7823Smrg    if( (trans_conn=_FontTransOpenCOTSClient(servername)) == NULL )
111a96d7823Smrg    {
112a96d7823Smrg	*err = FSIO_ERROR;
113a96d7823Smrg	return 0;
114a96d7823Smrg    }
115a96d7823Smrg
116a96d7823Smrg    /*
117a96d7823Smrg     * Set the connection non-blocking since we use select() to block.
118a96d7823Smrg     */
119a96d7823Smrg
120a96d7823Smrg    _FontTransSetOption(trans_conn, TRANS_NONBLOCKING, 1);
121a96d7823Smrg
122a96d7823Smrg    do {
123a96d7823Smrg	i = _FontTransConnect(trans_conn,servername);
124a96d7823Smrg    } while ((i == TRANS_TRY_CONNECT_AGAIN) && (retries-- > 0));
125a96d7823Smrg
126a96d7823Smrg    if (i < 0)
127a96d7823Smrg    {
128a96d7823Smrg	if (i == TRANS_IN_PROGRESS)
129a96d7823Smrg	    ret = FSIO_BLOCK;
130a96d7823Smrg	else
131a96d7823Smrg	    ret = FSIO_ERROR;
132a96d7823Smrg    }
133a96d7823Smrg    else
134a96d7823Smrg	ret = FSIO_READY;
135a96d7823Smrg
136a96d7823Smrg    if (ret == FSIO_ERROR)
137a96d7823Smrg    {
138a96d7823Smrg	_FontTransClose(trans_conn);
139a96d7823Smrg	trans_conn = 0;
140a96d7823Smrg    }
141a96d7823Smrg
142a96d7823Smrg    *err = ret;
143a96d7823Smrg    return trans_conn;
144a96d7823Smrg}
145a96d7823Smrg
146a96d7823Smrgstatic int
147a96d7823Smrg_fs_fill (FSFpePtr conn)
148a96d7823Smrg{
149a96d7823Smrg    long    avail;
150a96d7823Smrg    long    bytes_read;
151a96d7823Smrg    Bool    waited = FALSE;
152a96d7823Smrg
153a96d7823Smrg    if (_fs_flush (conn) < 0)
154a96d7823Smrg	return FSIO_ERROR;
155a96d7823Smrg    /*
156a96d7823Smrg     * Don't go overboard here; stop reading when we've
157a96d7823Smrg     * got enough to satisfy the pending request
158a96d7823Smrg     */
159a96d7823Smrg    while ((conn->inNeed - (conn->inBuf.insert - conn->inBuf.remove)) > 0)
160a96d7823Smrg    {
161a96d7823Smrg	avail = conn->inBuf.size - conn->inBuf.insert;
162a96d7823Smrg	/*
163a96d7823Smrg	 * For SVR4 with a unix-domain connection, ETEST() after selecting
164a96d7823Smrg	 * readable means the server has died.  To do this here, we look for
165a96d7823Smrg	 * two consecutive reads returning ETEST().
166a96d7823Smrg	 */
167a96d7823Smrg	ESET (0);
168a96d7823Smrg	bytes_read =_FontTransRead(conn->trans_conn,
169a96d7823Smrg				   conn->inBuf.buf + conn->inBuf.insert,
170a96d7823Smrg				   avail);
171a96d7823Smrg	if (bytes_read > 0) {
172a96d7823Smrg	    conn->inBuf.insert += bytes_read;
173a96d7823Smrg	    waited = FALSE;
174a96d7823Smrg	}
175a96d7823Smrg	else
176a96d7823Smrg	{
177a96d7823Smrg	    if (bytes_read == 0 || ETEST ())
178a96d7823Smrg	    {
179a96d7823Smrg		if (!waited)
180a96d7823Smrg		{
181a96d7823Smrg		    waited = TRUE;
182a96d7823Smrg		    if (_fs_wait_for_readable (conn, 0) == FSIO_BLOCK)
183a96d7823Smrg			return FSIO_BLOCK;
184a96d7823Smrg		    continue;
185a96d7823Smrg		}
186a96d7823Smrg	    }
187a96d7823Smrg	    if (!ECHECK(EINTR))
188a96d7823Smrg	    {
189a96d7823Smrg	        _fs_connection_died (conn);
190a96d7823Smrg	        return FSIO_ERROR;
191a96d7823Smrg	    }
192a96d7823Smrg	}
193a96d7823Smrg    }
194a96d7823Smrg    return FSIO_READY;
195a96d7823Smrg}
196a96d7823Smrg
197a96d7823Smrg/*
198a96d7823Smrg * Make space and return whether data have already arrived
199a96d7823Smrg */
200a96d7823Smrg
201a96d7823Smrgint
202a96d7823Smrg_fs_start_read (FSFpePtr conn, long size, char **buf)
203a96d7823Smrg{
204a96d7823Smrg    int	    ret;
205a96d7823Smrg
206a96d7823Smrg    conn->inNeed = size;
207a96d7823Smrg    if (fs_inqueued(conn) < size)
208a96d7823Smrg    {
209a96d7823Smrg	if (_fs_resize (&conn->inBuf, size) != FSIO_READY)
210a96d7823Smrg	{
211a96d7823Smrg	    _fs_connection_died (conn);
212a96d7823Smrg	    return FSIO_ERROR;
213a96d7823Smrg	}
214a96d7823Smrg	ret = _fs_fill (conn);
215a96d7823Smrg	if (ret == FSIO_ERROR)
216a96d7823Smrg	    return ret;
217a96d7823Smrg	if (ret == FSIO_BLOCK || fs_inqueued(conn) < size)
218a96d7823Smrg	    return FSIO_BLOCK;
219a96d7823Smrg    }
220a96d7823Smrg    if (buf)
221a96d7823Smrg	*buf = conn->inBuf.buf + conn->inBuf.remove;
222a96d7823Smrg    return FSIO_READY;
223a96d7823Smrg}
224a96d7823Smrg
225a96d7823Smrgvoid
226a96d7823Smrg_fs_done_read (FSFpePtr conn, long size)
227a96d7823Smrg{
228a96d7823Smrg    if (conn->inBuf.insert - conn->inBuf.remove < size)
229a96d7823Smrg    {
230a96d7823Smrg#ifdef DEBUG
231a96d7823Smrg	fprintf (stderr, "_fs_done_read skipping to many bytes\n");
232a96d7823Smrg#endif
233a96d7823Smrg	return;
234a96d7823Smrg    }
235a96d7823Smrg    conn->inBuf.remove += size;
236a96d7823Smrg    conn->inNeed -= size;
237a96d7823Smrg    _fs_downsize (&conn->inBuf, FS_BUF_MAX);
238a96d7823Smrg}
239a96d7823Smrg
240a96d7823Smrglong
241a96d7823Smrg_fs_pad_length (long len)
242a96d7823Smrg{
243a96d7823Smrg    return len + padlength[len&3];
244a96d7823Smrg}
245a96d7823Smrg
246a96d7823Smrgint
247a96d7823Smrg_fs_flush (FSFpePtr conn)
248a96d7823Smrg{
249a96d7823Smrg    long    bytes_written;
250a96d7823Smrg    long    remain;
251a96d7823Smrg
252a96d7823Smrg    /* XXX - hack.  The right fix is to remember that the font server
253a96d7823Smrg       has gone away when we first discovered it. */
254a96d7823Smrg    if (conn->fs_fd < 0)
255a96d7823Smrg	return FSIO_ERROR;
256a96d7823Smrg
257a96d7823Smrg    while ((remain = conn->outBuf.insert - conn->outBuf.remove) > 0)
258a96d7823Smrg    {
259a96d7823Smrg	bytes_written = _FontTransWrite(conn->trans_conn,
260a96d7823Smrg					conn->outBuf.buf + conn->outBuf.remove,
261a96d7823Smrg					(int) remain);
262a96d7823Smrg	if (bytes_written > 0)
263a96d7823Smrg	{
264a96d7823Smrg	    conn->outBuf.remove += bytes_written;
265a96d7823Smrg	}
266a96d7823Smrg	else
267a96d7823Smrg	{
268a96d7823Smrg	    if (bytes_written == 0 || ETEST ())
269a96d7823Smrg	    {
270a96d7823Smrg		conn->brokenWriteTime = GetTimeInMillis () + FS_FLUSH_POLL;
271a96d7823Smrg		_fs_mark_block (conn, FS_BROKEN_WRITE);
272a96d7823Smrg		break;
273a96d7823Smrg	    }
274a96d7823Smrg	    if (!ECHECK (EINTR))
275a96d7823Smrg	    {
276a96d7823Smrg		_fs_connection_died (conn);
277a96d7823Smrg		return FSIO_ERROR;
278a96d7823Smrg	    }
279a96d7823Smrg	}
280a96d7823Smrg    }
281a96d7823Smrg    if (conn->outBuf.remove == conn->outBuf.insert)
282a96d7823Smrg    {
283a96d7823Smrg	_fs_unmark_block (conn, FS_BROKEN_WRITE|FS_PENDING_WRITE);
284a96d7823Smrg	if (conn->outBuf.size > FS_BUF_INC)
285a96d7823Smrg	    conn->outBuf.buf = realloc (conn->outBuf.buf, FS_BUF_INC);
286a96d7823Smrg	conn->outBuf.remove = conn->outBuf.insert = 0;
287a96d7823Smrg    }
288a96d7823Smrg    return FSIO_READY;
289a96d7823Smrg}
290a96d7823Smrg
291a96d7823Smrgstatic int
292a96d7823Smrg_fs_resize (FSBufPtr buf, long size)
293a96d7823Smrg{
294a96d7823Smrg    char    *new;
295a96d7823Smrg    long    new_size;
296a96d7823Smrg
297a96d7823Smrg    if (buf->remove)
298a96d7823Smrg    {
299a96d7823Smrg	if (buf->remove != buf->insert)
300a96d7823Smrg	{
301a96d7823Smrg	    memmove (buf->buf,
302a96d7823Smrg		     buf->buf + buf->remove,
303a96d7823Smrg		     buf->insert - buf->remove);
304a96d7823Smrg	}
305a96d7823Smrg	buf->insert -= buf->remove;
306a96d7823Smrg	buf->remove = 0;
307a96d7823Smrg    }
308a96d7823Smrg    if (buf->size - buf->remove < size)
309a96d7823Smrg    {
310a96d7823Smrg	new_size = ((buf->remove + size + FS_BUF_INC) / FS_BUF_INC) * FS_BUF_INC;
311a96d7823Smrg	new = realloc (buf->buf, new_size);
312a96d7823Smrg	if (!new)
313a96d7823Smrg	    return FSIO_ERROR;
314a96d7823Smrg	buf->buf = new;
315a96d7823Smrg	buf->size = new_size;
316a96d7823Smrg    }
317a96d7823Smrg    return FSIO_READY;
318a96d7823Smrg}
319a96d7823Smrg
320a96d7823Smrgstatic void
321a96d7823Smrg_fs_downsize (FSBufPtr buf, long size)
322a96d7823Smrg{
323a96d7823Smrg    if (buf->insert == buf->remove)
324a96d7823Smrg    {
325a96d7823Smrg	buf->insert = buf->remove = 0;
326a96d7823Smrg	if (buf->size > size)
327a96d7823Smrg	{
328a96d7823Smrg	    buf->buf = realloc (buf->buf, size);
329a96d7823Smrg	    buf->size = size;
330a96d7823Smrg	}
331a96d7823Smrg    }
332a96d7823Smrg}
333a96d7823Smrg
334a96d7823Smrgvoid
335a96d7823Smrg_fs_io_reinit (FSFpePtr conn)
336a96d7823Smrg{
337a96d7823Smrg    conn->outBuf.insert = conn->outBuf.remove = 0;
338a96d7823Smrg    _fs_downsize (&conn->outBuf, FS_BUF_INC);
339a96d7823Smrg    conn->inBuf.insert = conn->inBuf.remove = 0;
340a96d7823Smrg    _fs_downsize (&conn->inBuf, FS_BUF_MAX);
341a96d7823Smrg}
342a96d7823Smrg
343a96d7823SmrgBool
344a96d7823Smrg_fs_io_init (FSFpePtr conn)
345a96d7823Smrg{
346a96d7823Smrg    conn->outBuf.insert = conn->outBuf.remove = 0;
347a96d7823Smrg    conn->outBuf.buf = malloc (FS_BUF_INC);
348a96d7823Smrg    if (!conn->outBuf.buf)
349a96d7823Smrg	return FALSE;
350a96d7823Smrg    conn->outBuf.size = FS_BUF_INC;
351a96d7823Smrg
352a96d7823Smrg    conn->inBuf.insert = conn->inBuf.remove = 0;
353a96d7823Smrg    conn->inBuf.buf = malloc (FS_BUF_INC);
354a96d7823Smrg    if (!conn->inBuf.buf)
355a96d7823Smrg    {
356a96d7823Smrg	free (conn->outBuf.buf);
357a96d7823Smrg	conn->outBuf.buf = 0;
358a96d7823Smrg	return FALSE;
359a96d7823Smrg    }
360a96d7823Smrg    conn->inBuf.size = FS_BUF_INC;
361a96d7823Smrg
362a96d7823Smrg    return TRUE;
363a96d7823Smrg}
364a96d7823Smrg
365a96d7823Smrgvoid
366a96d7823Smrg_fs_io_fini (FSFpePtr conn)
367a96d7823Smrg{
368a96d7823Smrg    if (conn->outBuf.buf)
369a96d7823Smrg	free (conn->outBuf.buf);
370a96d7823Smrg    if (conn->inBuf.buf)
371a96d7823Smrg	free (conn->inBuf.buf);
372a96d7823Smrg}
373a96d7823Smrg
374a96d7823Smrgstatic int
375a96d7823Smrg_fs_do_write(FSFpePtr conn, const char *data, long len, long size)
376a96d7823Smrg{
377a96d7823Smrg    if (size == 0) {
378a96d7823Smrg#ifdef DEBUG
379a96d7823Smrg	fprintf(stderr, "tried to write 0 bytes \n");
380a96d7823Smrg#endif
381a96d7823Smrg	return FSIO_READY;
382a96d7823Smrg    }
383a96d7823Smrg
384a96d7823Smrg    if (conn->fs_fd == -1)
385a96d7823Smrg	return FSIO_ERROR;
386a96d7823Smrg
387a96d7823Smrg    while (conn->outBuf.insert + size > conn->outBuf.size)
388a96d7823Smrg    {
389a96d7823Smrg	if (_fs_flush (conn) < 0)
390a96d7823Smrg	    return FSIO_ERROR;
391a96d7823Smrg	if (_fs_resize (&conn->outBuf, size) < 0)
392a96d7823Smrg	{
393a96d7823Smrg	    _fs_connection_died (conn);
394a96d7823Smrg	    return FSIO_ERROR;
395a96d7823Smrg	}
396a96d7823Smrg    }
397a96d7823Smrg    memcpy (conn->outBuf.buf + conn->outBuf.insert, data, len);
398a96d7823Smrg    /* Clear pad data */
399a96d7823Smrg    memset (conn->outBuf.buf + conn->outBuf.insert + len, 0, size - len);
400a96d7823Smrg    conn->outBuf.insert += size;
401a96d7823Smrg    _fs_mark_block (conn, FS_PENDING_WRITE);
402a96d7823Smrg    return FSIO_READY;
403a96d7823Smrg}
404a96d7823Smrg
405a96d7823Smrg/*
406a96d7823Smrg * Write the indicated bytes
407a96d7823Smrg */
408a96d7823Smrgint
409a96d7823Smrg_fs_write (FSFpePtr conn, const char *data, long len)
410a96d7823Smrg{
411a96d7823Smrg    return _fs_do_write (conn, data, len, len);
412a96d7823Smrg}
413a96d7823Smrg
414a96d7823Smrg/*
415a96d7823Smrg * Write the indicated bytes adding any appropriate pad
416a96d7823Smrg */
417a96d7823Smrgint
418a96d7823Smrg_fs_write_pad(FSFpePtr conn, const char *data, long len)
419a96d7823Smrg{
420a96d7823Smrg    return _fs_do_write (conn, data, len, len + padlength[len & 3]);
421a96d7823Smrg}
422a96d7823Smrg
423a96d7823Smrgint
424a96d7823Smrg_fs_wait_for_readable(FSFpePtr conn, int ms)
425a96d7823Smrg{
426a96d7823Smrg    fd_set	r_mask;
427a96d7823Smrg    fd_set	e_mask;
428a96d7823Smrg    int         result;
429a96d7823Smrg    struct timeval  tv;
430a96d7823Smrg
431a96d7823Smrg    for (;;) {
432a96d7823Smrg	if (conn->fs_fd < 0)
433a96d7823Smrg	    return FSIO_ERROR;
434a96d7823Smrg	FD_ZERO(&r_mask);
435a96d7823Smrg	FD_ZERO(&e_mask);
436a96d7823Smrg	tv.tv_sec = ms / 1000;
437a96d7823Smrg	tv.tv_usec = (ms % 1000) * 1000;
438a96d7823Smrg	FD_SET(conn->fs_fd, &r_mask);
439a96d7823Smrg	FD_SET(conn->fs_fd, &e_mask);
440a96d7823Smrg	result = Select(conn->fs_fd + 1, &r_mask, NULL, &e_mask, &tv);
441a96d7823Smrg	if (result < 0)
442a96d7823Smrg	{
443a96d7823Smrg	    if (ECHECK(EINTR) || ECHECK(EAGAIN))
444a96d7823Smrg		continue;
445a96d7823Smrg	    else
446a96d7823Smrg		return FSIO_ERROR;
447a96d7823Smrg	}
448a96d7823Smrg	if (result == 0)
449a96d7823Smrg	    return FSIO_BLOCK;
450a96d7823Smrg	if (FD_ISSET(conn->fs_fd, &r_mask))
451a96d7823Smrg	    return FSIO_READY;
452a96d7823Smrg	return FSIO_ERROR;
453a96d7823Smrg    }
454a96d7823Smrg}
455