📄 fsio.c
字号:
/* $XConsortium: fsio.c,v 1.37 95/04/05 19:58:13 kaleb Exp $ *//* $XFree86: xc/lib/font/fc/fsio.c,v 3.5.2.1 1998/02/15 16:08:40 hohndel Exp $ *//* * Copyright 1990 Network Computing Devices * * 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 name of Network Computing Devices not be * used in advertising or publicity pertaining to distribution of the * software without specific, written prior permission. Network Computing * Devices makes no representations about the suitability of this software * for any purpose. It is provided "as is" without express or implied * warranty. * * NETWORK COMPUTING DEVICES DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, * IN NO EVENT SHALL NETWORK COMPUTING DEVICES 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. * * Author: Dave Lemke, Network Computing Devices, Inc *//* * font server i/o routines */#ifdef WIN32#define _WILLWINSOCK_#endif#include "FS.h"#include "FSproto.h"#include "X11/Xtrans.h"#include "X11/Xpoll.h"#include "fontmisc.h"#include "fsio.h"#include <stdio.h>#include <signal.h>#include <sys/types.h>#if !defined(WIN32) && !defined(AMOEBA) && !defined(_MINIX)#ifndef Lynx#include <sys/socket.h>#else#include <socket.h>#endif#endif#include <errno.h>#ifdef X_NOT_STDC_ENVextern int errno;#endif #ifdef WIN32#define EWOULDBLOCK WSAEWOULDBLOCK#undef EINTR#define EINTR WSAEINTR#endif#ifdef MINIX#include <sys/nbio.h>#define select(n,r,w,x,t) nbio_select(n,r,w,x,t)#endif#ifdef __EMX__#define select(n,r,w,x,t) os2PseudoSelect(n,r,w,x,t)#endif/* 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#endifstatic int padlength[4] = {0, 3, 2, 1};fd_set _fs_fd_mask;int _fs_wait_for_readable();#ifdef SIGNALRETURNSINT#define SIGNAL_T int#else#define SIGNAL_T void#endif/* ARGSUSED */static SIGNAL_T_fs_alarm(foo) int foo;{ return;}static XtransConnInfo_fs_connect(servername, timeout) char *servername; int timeout;{ XtransConnInfo trans_conn; /* transport connection object */ int ret = -1;#ifdef SIGALRM unsigned oldTime; SIGNAL_T(*oldAlarm) ();#endif /* * Open the network connection. */ if( (trans_conn=_FontTransOpenCOTSClient(servername)) == NULL ) { return (NULL); }#ifdef SIGALRM oldTime = alarm((unsigned) 0); oldAlarm = signal(SIGALRM, _fs_alarm); alarm((unsigned) timeout);#endif ret = _FontTransConnect(trans_conn,servername);#ifdef SIGALRM alarm((unsigned) 0); signal(SIGALRM, oldAlarm); alarm(oldTime);#endif if (ret < 0) { _FontTransClose(trans_conn); return (NULL); } /* * Set the connection non-blocking since we use select() to block. */ _FontTransSetOption(trans_conn, TRANS_NONBLOCKING, 1); return trans_conn;}static int generationCount;/* ARGSUSED */static Bool_fs_setup_connection(conn, servername, timeout, copy_name_p) FSFpePtr conn; char *servername; int timeout; Bool copy_name_p;{ fsConnClientPrefix prefix; fsConnSetup rep; int setuplength; fsConnSetupAccept conn_accept; int endian; int i; int alt_len; char *auth_data = NULL, *vendor_string = NULL, *alt_data = NULL, *alt_dst; FSFpeAltPtr alts; int nalts; if ((conn->trans_conn = _fs_connect(servername, 5)) == NULL) return FALSE; conn->fs_fd = _FontTransGetConnectionNumber (conn->trans_conn); conn->generation = ++generationCount; /* send setup prefix */ endian = 1; if (*(char *) &endian) prefix.byteOrder = 'l'; else prefix.byteOrder = 'B'; prefix.major_version = FS_PROTOCOL; prefix.minor_version = FS_PROTOCOL_MINOR;/* XXX add some auth info here */ prefix.num_auths = 0; prefix.auth_len = 0; if (_fs_write(conn, (char *) &prefix, SIZEOF(fsConnClientPrefix)) == -1) return FALSE; /* read setup info */ if (_fs_read(conn, (char *) &rep, SIZEOF(fsConnSetup)) == -1) return FALSE; conn->fsMajorVersion = rep.major_version; if (rep.major_version > FS_PROTOCOL) return FALSE; alts = 0; /* parse alternate list */ if (nalts = rep.num_alternates) { setuplength = rep.alternate_len << 2; alts = (FSFpeAltPtr) xalloc(nalts * sizeof(FSFpeAltRec) + setuplength); if (!alts) { _FontTransClose(conn->trans_conn); errno = ENOMEM; return FALSE; } alt_data = (char *) (alts + nalts); if (_fs_read(conn, (char *) alt_data, setuplength) == -1) { xfree(alts); return FALSE; } alt_dst = alt_data; for (i = 0; i < nalts; i++) { alts[i].subset = alt_data[0]; alt_len = alt_data[1]; alts[i].name = alt_dst; memmove(alt_dst, alt_data + 2, alt_len); alt_dst[alt_len] = '\0'; alt_dst += (alt_len + 1); alt_data += (2 + alt_len + padlength[(2 + alt_len) & 3]); } } if (conn->alts) xfree(conn->alts); conn->alts = alts; conn->numAlts = nalts; setuplength = rep.auth_len << 2; if (setuplength && !(auth_data = (char *) xalloc((unsigned int) setuplength))) { _FontTransClose(conn->trans_conn); errno = ENOMEM; return FALSE; } if (_fs_read(conn, (char *) auth_data, setuplength) == -1) { xfree(auth_data); return FALSE; } if (rep.status != AuthSuccess) { xfree(auth_data); _FontTransClose(conn->trans_conn); errno = EPERM; return FALSE; } /* get rest */ if (_fs_read(conn, (char *) &conn_accept, (long) SIZEOF(fsConnSetupAccept)) == -1) { xfree(auth_data); return FALSE; } if ((vendor_string = (char *) xalloc((unsigned) conn_accept.vendor_len + 1)) == NULL) { xfree(auth_data); _FontTransClose(conn->trans_conn); errno = ENOMEM; return FALSE; } if (_fs_read_pad(conn, (char *) vendor_string, conn_accept.vendor_len) == -1) { xfree(vendor_string); xfree(auth_data); return FALSE; } xfree(auth_data); xfree(vendor_string); if (copy_name_p) { conn->servername = (char *) xalloc(strlen(servername) + 1); if (conn->servername == NULL) return FALSE; strcpy(conn->servername, servername); } else conn->servername = servername; return TRUE;}static Bool_fs_try_alternates(conn, timeout) FSFpePtr conn; int timeout;{ int i; for (i = 0; i < conn->numAlts; i++) if (_fs_setup_connection(conn, conn->alts[i].name, timeout, TRUE)) return TRUE; return FALSE;}#define FS_OPEN_TIMEOUT 30#define FS_REOPEN_TIMEOUT 10FSFpePtr_fs_open_server(servername) char *servername;{ FSFpePtr conn; conn = (FSFpePtr) xalloc(sizeof(FSFpeRec)); if (!conn) { errno = ENOMEM; return (FSFpePtr) NULL; } bzero((char *) conn, sizeof(FSFpeRec)); if (!_fs_setup_connection(conn, servername, FS_OPEN_TIMEOUT, TRUE)) { if (!_fs_try_alternates(conn, FS_OPEN_TIMEOUT)) { xfree(conn->alts); xfree(conn); return (FSFpePtr) NULL; } } return conn;}Bool_fs_reopen_server(conn) FSFpePtr conn;{ if (_fs_setup_connection(conn, conn->servername, FS_REOPEN_TIMEOUT, FALSE)) return TRUE; if (_fs_try_alternates(conn, FS_REOPEN_TIMEOUT)) return TRUE; return FALSE;}/* * expects everything to be here. *not* to be called when reading huge * numbers of replies, but rather to get each chunk */_fs_read(conn, data, size) FSFpePtr conn; char *data; unsigned long size;{ long bytes_read;#if defined(SVR4) && defined(i386) int num_failed_reads = 0;#endif if (size == 0) {#ifdef DEBUG fprintf(stderr, "tried to read 0 bytes \n");#endif return 0; } 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 = _FontTransRead(conn->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()) { /* in a perfect world, this shouldn't happen */ /* ... but then, its less than perfect... */ if (_fs_wait_for_readable(conn) == -1) { /* check for error */ _fs_connection_died(conn); ESET(EPIPE); return -1; }#if defined(SVR4) && defined(i386) num_failed_reads++; if (num_failed_reads > 1) { _fs_connection_died(conn); ESET(EPIPE); return -1; }#endif ESET(0); } else if (ECHECK(EINTR)) {#if defined(SVR4) && defined(i386) num_failed_reads = 0;#endif continue; } else { /* something bad happened */ if (conn->fs_fd > 0) _fs_connection_died(conn); ESET(EPIPE); return -1; } } return 0;}_fs_write(conn, data, size) FSFpePtr conn; char *data; unsigned long size;{ long bytes_written; if (size == 0) {#ifdef DEBUG fprintf(stderr, "tried to write 0 bytes \n");#endif return 0; } /* XXX - hack. The right fix is to remember that the font server has gone away when we first discovered it. */ if (!conn->trans_conn) return -1; ESET(0); while ((bytes_written = _FontTransWrite(conn->trans_conn, data, (int) size)) != size) { if (bytes_written > 0) { size -= bytes_written; data += bytes_written; } else if (ETEST()) { /* XXX -- we assume this can't happen */#ifdef DEBUG fprintf(stderr, "fs_write blocking\n");#endif } else if (ECHECK(EINTR)) { continue; } else { /* something bad happened */ _fs_connection_died(conn); ESET(EPIPE); return -1; } } return 0;}_fs_read_pad(conn, data, len) FSFpePtr conn; char *data; int len;{ char pad[3]; if (_fs_read(conn, data, len) == -1) return -1; /* read the junk */ if (padlength[len & 3]) { return _fs_read(conn, pad, padlength[len & 3]); } return 0;}_fs_write_pad(conn, data, len) FSFpePtr conn; char *data; int len;{ static char pad[3]; if (_fs_write(conn, data, len) == -1) return -1; /* write the pad */ if (padlength[len & 3]) { return _fs_write(conn, pad, padlength[len & 3]); } return 0;}/* * returns the amount of data waiting to be read */int_fs_data_ready(conn) FSFpePtr conn;{ BytesReadable_t readable; if (_FontTransBytesReadable(conn->trans_conn, &readable) < 0) return -1; return readable;}int_fs_wait_for_readable(conn) FSFpePtr conn;{#ifndef AMOEBA fd_set r_mask; fd_set e_mask; int result;#ifdef DEBUG fprintf(stderr, "read would block\n");#endif do { FD_ZERO(&r_mask);#ifndef MINIX FD_ZERO(&e_mask);#endif FD_SET(conn->fs_fd, &r_mask); FD_SET(conn->fs_fd, &e_mask); result = Select(conn->fs_fd + 1, &r_mask, NULL, &e_mask, NULL); if (result == -1) { if (ECHECK(EINTR) || ECHECK(EAGAIN)) continue; else return -1; } if (result && FD_ISSET(conn->fs_fd, &e_mask)) return -1; } while (result <= 0); return 0;#else printf("fs_wait_for_readable(): fail\n"); return -1;#endif}int_fs_set_bit(mask, fd) fd_set* mask; int fd;{ FD_SET(fd, mask); return fd;}int_fs_is_bit_set(mask, fd) fd_set* mask; int fd;{ return FD_ISSET(fd, mask);}void_fs_bit_clear(mask, fd) fd_set* mask; int fd;{ FD_CLR(fd, mask);}int_fs_any_bit_set(mask) fd_set* mask;{ return XFD_ANYSET(mask);}int_fs_or_bits(dst, m1, m2) fd_set* dst; fd_set* m1; fd_set* m2;{#ifdef WIN32 int i; if (dst != m1) { for (i = m1->fd_count; --i >= 0; ) { if (!FD_ISSET(m1->fd_array[i], dst)) FD_SET(m1->fd_array[i], dst); } } if (dst != m2) { for (i = m2->fd_count; --i >= 0; ) { if (!FD_ISSET(m2->fd_array[i], dst)) FD_SET(m2->fd_array[i], dst); } }#else XFD_ORSET(dst, m1, m2);#endif return 0;}_fs_drain_bytes(conn, len) FSFpePtr conn; int len;{ char buf[128];#ifdef DEBUG fprintf(stderr, "draining wire\n");#endif while (len > 0) { if (_fs_read(conn, buf, (len < 128) ? len : 128) < 0) return -1; len -= 128; } return 0;}_fs_drain_bytes_pad(conn, len) FSFpePtr conn; int len;{ _fs_drain_bytes(conn, len); /* read the junk */ if (padlength[len & 3]) { _fs_drain_bytes(conn, padlength[len & 3]); }}_fs_eat_rest_of_error(conn, err) FSFpePtr conn; fsError *err;{ int len = (err->length - (SIZEOF(fsGenericReply) >> 2)) << 2;#ifdef DEBUG fprintf(stderr, "clearing error\n");#endif _fs_drain_bytes(conn, len);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -