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