io.c revision 30f8ce46
1bbe1b32bSmrg/* 2bbe1b32bSmrg * i/o functions 3bbe1b32bSmrg */ 4bbe1b32bSmrg/* 5bbe1b32bSmrg 6bbe1b32bSmrgCopyright 1990, 1991, 1998 The Open Group 7bbe1b32bSmrg 8bbe1b32bSmrgPermission to use, copy, modify, distribute, and sell this software and its 9bbe1b32bSmrgdocumentation for any purpose is hereby granted without fee, provided that 10bbe1b32bSmrgthe above copyright notice appear in all copies and that both that 11bbe1b32bSmrgcopyright notice and this permission notice appear in supporting 12bbe1b32bSmrgdocumentation. 13bbe1b32bSmrg 14bbe1b32bSmrgThe above copyright notice and this permission notice shall be included in 15bbe1b32bSmrgall copies or substantial portions of the Software. 16bbe1b32bSmrg 17bbe1b32bSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18bbe1b32bSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19bbe1b32bSmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20bbe1b32bSmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 21bbe1b32bSmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22bbe1b32bSmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23bbe1b32bSmrg 24bbe1b32bSmrgExcept as contained in this notice, the name of The Open Group shall not be 25bbe1b32bSmrgused in advertising or otherwise to promote the sale, use or other dealings 26bbe1b32bSmrgin this Software without prior written authorization from The Open Group. 27bbe1b32bSmrg 28bbe1b32bSmrg * Copyright 1990, 1991 Network Computing Devices; 29bbe1b32bSmrg * Portions Copyright 1987 by Digital Equipment Corporation 30bbe1b32bSmrg * 31bbe1b32bSmrg * Permission to use, copy, modify, distribute, and sell this software and 32bbe1b32bSmrg * its documentation for any purpose is hereby granted without fee, provided 33bbe1b32bSmrg * that the above copyright notice appear in all copies and that both that 34bbe1b32bSmrg * copyright notice and this permission notice appear in supporting 35bbe1b32bSmrg * documentation, and that the names of Network Computing Devices, or Digital 36bbe1b32bSmrg * not be used in advertising or publicity pertaining to distribution 37bbe1b32bSmrg * of the software without specific, written prior permission. 38bbe1b32bSmrg * 39bbe1b32bSmrg * NETWORK COMPUTING DEVICES, AND DIGITAL DISCLAIM ALL WARRANTIES WITH 40bbe1b32bSmrg * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF 41bbe1b32bSmrg * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL NETWORK COMPUTING DEVICES, 42bbe1b32bSmrg * OR DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL 43bbe1b32bSmrg * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 44bbe1b32bSmrg * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS 45bbe1b32bSmrg * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF 46bbe1b32bSmrg * THIS SOFTWARE. 47bbe1b32bSmrg */ 48ce6676dbSmrg 49ce6676dbSmrg#include "xfs-config.h" 50bbe1b32bSmrg 51bbe1b32bSmrg#include <X11/Xtrans/Xtrans.h> 52bbe1b32bSmrg#include <stdio.h> 53bbe1b32bSmrg#include <errno.h> 54bbe1b32bSmrg#include <sys/types.h> 55bbe1b32bSmrg#include <sys/param.h> 56bbe1b32bSmrg#ifndef __UNIXOS2__ 57bbe1b32bSmrg#include <sys/uio.h> 58bbe1b32bSmrg#endif 59bbe1b32bSmrg 60bbe1b32bSmrg#include <X11/fonts/FSproto.h> 61bbe1b32bSmrg#include "clientstr.h" 62bbe1b32bSmrg#include "X11/Xpoll.h" 63bbe1b32bSmrg#include "osdep.h" 64bbe1b32bSmrg#include "globals.h" 65bbe1b32bSmrg#include "dispatch.h" 66bbe1b32bSmrg 67bbe1b32bSmrg 68bbe1b32bSmrg/* check for both EAGAIN and EWOULDBLOCK, because some supposedly POSIX 69bbe1b32bSmrg * systems are broken and return EWOULDBLOCK when they should return EAGAIN 70bbe1b32bSmrg */ 71bbe1b32bSmrg 72bbe1b32bSmrg#if defined(EAGAIN) && defined(EWOULDBLOCK) 73bbe1b32bSmrg#define ETEST(err) (err == EAGAIN || err == EWOULDBLOCK) 74bbe1b32bSmrg#else 75bbe1b32bSmrg 76bbe1b32bSmrg#ifdef EAGAIN 77bbe1b32bSmrg#define ETEST(err) (err == EAGAIN) 78bbe1b32bSmrg#else 79bbe1b32bSmrg#define ETEST(err) (err == EWOULDBLOCK) 80bbe1b32bSmrg#endif 81bbe1b32bSmrg 82bbe1b32bSmrg#endif 83bbe1b32bSmrg 84bbe1b32bSmrgstatic int timesThisConnection = 0; 85bbe1b32bSmrgstatic ConnectionInputPtr FreeInputs = (ConnectionInputPtr) NULL; 86bbe1b32bSmrgstatic ConnectionOutputPtr FreeOutputs = (ConnectionOutputPtr) NULL; 87bbe1b32bSmrgstatic OsCommPtr AvailableInput = (OsCommPtr) NULL; 88bbe1b32bSmrg 8930f8ce46Smrgextern int xfd_ffs(fd_mask); 90bbe1b32bSmrgstatic ConnectionInputPtr AllocateInputBuffer(void); 91bbe1b32bSmrgstatic ConnectionOutputPtr AllocateOutputBuffer(void); 92bbe1b32bSmrg 93bbe1b32bSmrg 94bbe1b32bSmrg#define MAX_TIMES_PER 10 95bbe1b32bSmrg 96bbe1b32bSmrg#define yield_control() \ 97bbe1b32bSmrg { isItTimeToYield = TRUE; \ 98bbe1b32bSmrg timesThisConnection = 0; } 99bbe1b32bSmrg 100bbe1b32bSmrg#define yield_control_no_input() \ 101bbe1b32bSmrg { yield_control(); \ 102bbe1b32bSmrg FD_CLR(fd, &ClientsWithInput); } 103bbe1b32bSmrg 104bbe1b32bSmrg#define yield_control_death() \ 105bbe1b32bSmrg { timesThisConnection = 0; } 106bbe1b32bSmrg 107bbe1b32bSmrg#define request_length(req, client) \ 108bbe1b32bSmrg ((int)((client)->swapped ? lswaps((req)->length) : (req)->length) << 2) 109bbe1b32bSmrg 110bbe1b32bSmrgint 111bbe1b32bSmrgReadRequest(ClientPtr client) 112bbe1b32bSmrg{ 113bbe1b32bSmrg OsCommPtr oc; 114bbe1b32bSmrg ConnectionInputPtr oci; 115bbe1b32bSmrg fsReq *request; 116bbe1b32bSmrg int fd, 117bbe1b32bSmrg result, 118bbe1b32bSmrg gotnow, 119bbe1b32bSmrg needed = 0; 120bbe1b32bSmrg 121bbe1b32bSmrg if (client == NULL) 122bbe1b32bSmrg return -1; 123bbe1b32bSmrg oc = (OsCommPtr) client->osPrivate; 124bbe1b32bSmrg if (oc == NULL) 125bbe1b32bSmrg return -1; 126bbe1b32bSmrg oci = oc->input; 127bbe1b32bSmrg fd = oc->fd; 128bbe1b32bSmrg if (oci != NULL && fd < 0) 129bbe1b32bSmrg return -1; 130bbe1b32bSmrg 131bbe1b32bSmrg if (AvailableInput) { 132bbe1b32bSmrg if (AvailableInput != oc) { 133bbe1b32bSmrg ConnectionInputPtr aci = AvailableInput->input; 134bbe1b32bSmrg 135bbe1b32bSmrg if (aci->size > BUFWATERMARK) { 136bbe1b32bSmrg fsfree(aci->buffer); 137bbe1b32bSmrg fsfree(aci); 138bbe1b32bSmrg } else { 139bbe1b32bSmrg aci->next = FreeInputs; 140bbe1b32bSmrg FreeInputs = aci; 141bbe1b32bSmrg } 142bbe1b32bSmrg AvailableInput->input = (ConnectionInputPtr) NULL; 143bbe1b32bSmrg } 144bbe1b32bSmrg AvailableInput = (OsCommPtr) NULL; 145bbe1b32bSmrg } 146bbe1b32bSmrg if (!oci) { 147bbe1b32bSmrg if ((oci = FreeInputs ) != (ConnectionInputPtr) 0) { 148bbe1b32bSmrg FreeInputs = oci->next; 149bbe1b32bSmrg } else if (!(oci = AllocateInputBuffer())) { 150bbe1b32bSmrg yield_control_death(); 151bbe1b32bSmrg return -1; 152bbe1b32bSmrg } 153bbe1b32bSmrg oc->input = oci; 154bbe1b32bSmrg } 155bbe1b32bSmrg oci->bufptr += oci->lenLastReq; 156bbe1b32bSmrg 157bbe1b32bSmrg gotnow = oci->bufcnt + oci->buffer - oci->bufptr; 158bbe1b32bSmrg 159bbe1b32bSmrg#ifdef WORD64 160bbe1b32bSmrg /* need 8-byte alignment */ 161bbe1b32bSmrg if ((oci->bufptr - oci->buffer) & 7 && gotnow > 0) 162bbe1b32bSmrg { 163bbe1b32bSmrg memmove( oci->buffer, oci->bufptr, gotnow); 164bbe1b32bSmrg oci->bufptr = oci->buffer; 165bbe1b32bSmrg oci->bufcnt = gotnow; 166bbe1b32bSmrg } 167bbe1b32bSmrg#endif 168bbe1b32bSmrg 169bbe1b32bSmrg request = (fsReq *) oci->bufptr; 170bbe1b32bSmrg 171bbe1b32bSmrg /* not enough for a request */ 172bbe1b32bSmrg if ((gotnow < SIZEOF(fsReq)) || 173bbe1b32bSmrg (gotnow < (needed = request_length(request, client)))) { 174bbe1b32bSmrg oci->lenLastReq = 0; 175bbe1b32bSmrg if ((gotnow < SIZEOF(fsReq)) || needed == 0) 176bbe1b32bSmrg needed = SIZEOF(fsReq); 177bbe1b32bSmrg else if (needed > MAXBUFSIZE) { 178bbe1b32bSmrg yield_control_death(); 179bbe1b32bSmrg return -1; 180bbe1b32bSmrg } 181bbe1b32bSmrg /* see if we need to shift up a partial request so the rest can fit */ 182bbe1b32bSmrg if ((gotnow == 0) || 183bbe1b32bSmrg ((oci->bufptr - oci->buffer + needed) > oci->size)) 184bbe1b32bSmrg { 185bbe1b32bSmrg if ((gotnow > 0) && (oci->bufptr != oci->buffer)) 186bbe1b32bSmrg memmove( oci->buffer, oci->bufptr, gotnow); 187bbe1b32bSmrg /* grow buffer if necessary */ 188bbe1b32bSmrg if (needed > oci->size) { 189bbe1b32bSmrg char *ibuf; 190bbe1b32bSmrg 191bbe1b32bSmrg ibuf = (char *) fsrealloc(oci->buffer, needed); 192bbe1b32bSmrg if (!ibuf) { 193bbe1b32bSmrg yield_control_death(); 194bbe1b32bSmrg return -1; 195bbe1b32bSmrg } 196bbe1b32bSmrg oci->size = needed; 197bbe1b32bSmrg oci->buffer = ibuf; 198bbe1b32bSmrg } 199bbe1b32bSmrg oci->bufptr = oci->buffer; 200bbe1b32bSmrg oci->bufcnt = gotnow; 201bbe1b32bSmrg } 202bbe1b32bSmrg /* fill 'er up */ 203bbe1b32bSmrg if (oc->trans_conn == NULL) { 204bbe1b32bSmrg yield_control_death(); 205bbe1b32bSmrg return -1; 206bbe1b32bSmrg } 207bbe1b32bSmrg result = _FontTransRead(oc->trans_conn, oci->buffer + oci->bufcnt, 208bbe1b32bSmrg oci->size - oci->bufcnt); 209bbe1b32bSmrg if (result <= 0) { 210bbe1b32bSmrg#if !(defined(SVR4) && defined(i386) && !defined(sun)) 211bbe1b32bSmrg if ((result < 0) && ETEST(errno)) { 212bbe1b32bSmrg yield_control_no_input(); 213bbe1b32bSmrg return 0; 214bbe1b32bSmrg } else 215bbe1b32bSmrg#endif 216bbe1b32bSmrg { 217bbe1b32bSmrg 218bbe1b32bSmrg yield_control_death(); 219bbe1b32bSmrg return -1; 220bbe1b32bSmrg } 221bbe1b32bSmrg } 222bbe1b32bSmrg oci->bufcnt += result; 223bbe1b32bSmrg gotnow += result; 224bbe1b32bSmrg 225bbe1b32bSmrg /* free up space after huge requests */ 226bbe1b32bSmrg if ((oci->size > BUFWATERMARK) && 227bbe1b32bSmrg (oci->bufcnt < BUFSIZE) && (needed < BUFSIZE)) { 228bbe1b32bSmrg char *ibuf; 229bbe1b32bSmrg 230bbe1b32bSmrg ibuf = (char *) fsrealloc(oci->buffer, BUFSIZE); 231bbe1b32bSmrg if (ibuf) { 232bbe1b32bSmrg oci->size = BUFSIZE; 233bbe1b32bSmrg oci->buffer = ibuf; 234bbe1b32bSmrg oci->bufptr = ibuf + oci->bufcnt - gotnow; 235bbe1b32bSmrg } 236bbe1b32bSmrg } 237bbe1b32bSmrg request = (fsReq *) oci->bufptr; 238bbe1b32bSmrg if ((gotnow < SIZEOF(fsReq)) || 239bbe1b32bSmrg (gotnow < (needed = request_length(request, client)))) { 240bbe1b32bSmrg yield_control_no_input(); 241bbe1b32bSmrg return 0; 242bbe1b32bSmrg } 243bbe1b32bSmrg } 244bbe1b32bSmrg if (needed == 0) 245bbe1b32bSmrg needed = SIZEOF(fsReq); 246bbe1b32bSmrg oci->lenLastReq = needed; 247bbe1b32bSmrg /* 248bbe1b32bSmrg * Check to see if client has at least one whole request in the buffer. If 249bbe1b32bSmrg * there is only a partial request, treat like buffer is empty so that 250bbe1b32bSmrg * select() will be called again and other clients can get into the queue. 251bbe1b32bSmrg */ 252bbe1b32bSmrg 253bbe1b32bSmrg if (gotnow >= needed + SIZEOF(fsReq)) { 254bbe1b32bSmrg request = (fsReq *) (oci->bufptr + needed); 255bbe1b32bSmrg if (gotnow >= needed + request_length(request, client)) 256bbe1b32bSmrg FD_SET(fd, &ClientsWithInput); 257bbe1b32bSmrg else 258bbe1b32bSmrg yield_control_no_input(); 259bbe1b32bSmrg } else { 260bbe1b32bSmrg if (gotnow == needed) 261bbe1b32bSmrg AvailableInput = oc; 262bbe1b32bSmrg yield_control_no_input(); 263bbe1b32bSmrg } 264bbe1b32bSmrg 265bbe1b32bSmrg if (++timesThisConnection >= MAX_TIMES_PER) 266bbe1b32bSmrg yield_control(); 267bbe1b32bSmrg 268bbe1b32bSmrg client->requestBuffer = (pointer) oci->bufptr; 269bbe1b32bSmrg return needed; 270bbe1b32bSmrg} 271bbe1b32bSmrg 272bbe1b32bSmrgBool 273bbe1b32bSmrgInsertFakeRequest(ClientPtr client, char *data, int count) 274bbe1b32bSmrg{ 275bbe1b32bSmrg OsCommPtr oc = (OsCommPtr) client->osPrivate; 276bbe1b32bSmrg ConnectionInputPtr oci = oc->input; 277bbe1b32bSmrg int fd = oc->fd; 278bbe1b32bSmrg fsReq *request; 279bbe1b32bSmrg int gotnow, 280bbe1b32bSmrg moveup; 281bbe1b32bSmrg 282bbe1b32bSmrg if (AvailableInput) { 283bbe1b32bSmrg if (AvailableInput != oc) { 284bbe1b32bSmrg register ConnectionInputPtr aci = AvailableInput->input; 285bbe1b32bSmrg 286bbe1b32bSmrg if (aci->size > BUFWATERMARK) { 287bbe1b32bSmrg fsfree(aci->buffer); 288bbe1b32bSmrg fsfree(aci); 289bbe1b32bSmrg } else { 290bbe1b32bSmrg aci->next = FreeInputs; 291bbe1b32bSmrg FreeInputs = aci; 292bbe1b32bSmrg } 293bbe1b32bSmrg AvailableInput->input = (ConnectionInputPtr) NULL; 294bbe1b32bSmrg } 295bbe1b32bSmrg AvailableInput = (OsCommPtr) NULL; 296bbe1b32bSmrg } 297bbe1b32bSmrg if (!oci) { 298bbe1b32bSmrg if ((oci = FreeInputs) != (ConnectionInputPtr) 0) 299bbe1b32bSmrg FreeInputs = oci->next; 300bbe1b32bSmrg else if (!(oci = AllocateInputBuffer())) 301bbe1b32bSmrg return FALSE; 302bbe1b32bSmrg oc->input = oci; 303bbe1b32bSmrg 304bbe1b32bSmrg } 305bbe1b32bSmrg oci->bufptr += oci->lenLastReq; 306bbe1b32bSmrg oci->lenLastReq = 0; 307bbe1b32bSmrg gotnow = oci->bufcnt + oci->buffer - oci->bufptr; 308bbe1b32bSmrg if ((gotnow + count) > oci->size) { 309bbe1b32bSmrg char *ibuf; 310bbe1b32bSmrg 311bbe1b32bSmrg ibuf = (char *) fsrealloc(oci->buffer, gotnow + count); 312bbe1b32bSmrg if (!ibuf) 313bbe1b32bSmrg return FALSE; 314bbe1b32bSmrg oci->size = gotnow + count; 315bbe1b32bSmrg oci->buffer = ibuf; 316bbe1b32bSmrg oci->bufptr = ibuf + oci->bufcnt - gotnow; 317bbe1b32bSmrg } 318bbe1b32bSmrg moveup = count - (oci->bufptr - oci->buffer); 319bbe1b32bSmrg if (moveup > 0) { 320bbe1b32bSmrg if (gotnow > 0) 321bbe1b32bSmrg memmove( oci->bufptr + moveup, oci->bufptr, gotnow); 322bbe1b32bSmrg oci->bufptr += moveup; 323bbe1b32bSmrg oci->bufcnt += moveup; 324bbe1b32bSmrg } 325bbe1b32bSmrg memmove( oci->bufptr - count, data, count); 326bbe1b32bSmrg oci->bufptr -= count; 327bbe1b32bSmrg request = (fsReq *) oci->bufptr; 328bbe1b32bSmrg gotnow += count; 329bbe1b32bSmrg if ((gotnow >= SIZEOF(fsReq)) && 330bbe1b32bSmrg (gotnow >= request_length(request, client))) 331bbe1b32bSmrg FD_SET(fd, &ClientsWithInput); 332bbe1b32bSmrg else 333bbe1b32bSmrg yield_control_no_input(); 334bbe1b32bSmrg return TRUE; 335bbe1b32bSmrg} 336bbe1b32bSmrg 337bbe1b32bSmrgvoid 338bbe1b32bSmrgResetCurrentRequest(ClientPtr client) 339bbe1b32bSmrg{ 340bbe1b32bSmrg OsCommPtr oc = (OsCommPtr) client->osPrivate; 341bbe1b32bSmrg ConnectionInputPtr oci = oc->input; 342bbe1b32bSmrg int fd = oc->fd; 343bbe1b32bSmrg fsReq *request; 344bbe1b32bSmrg int gotnow; 345bbe1b32bSmrg 346bbe1b32bSmrg if (AvailableInput == oc) 347bbe1b32bSmrg AvailableInput = (OsCommPtr) NULL; 348bbe1b32bSmrg oci->lenLastReq = 0; 349bbe1b32bSmrg request = (fsReq *) oci->bufptr; 350bbe1b32bSmrg gotnow = oci->bufcnt + oci->buffer - oci->bufptr; 351bbe1b32bSmrg if ((gotnow >= SIZEOF(fsReq)) && 352bbe1b32bSmrg (gotnow >= request_length(request, client))) { 353bbe1b32bSmrg FD_SET(fd, &ClientsWithInput); 354bbe1b32bSmrg yield_control(); 355bbe1b32bSmrg } else { 356bbe1b32bSmrg yield_control_no_input(); 357bbe1b32bSmrg } 358bbe1b32bSmrg} 359bbe1b32bSmrg 360bbe1b32bSmrgint 361bbe1b32bSmrgFlushClient( 362bbe1b32bSmrg ClientPtr client, 363bbe1b32bSmrg OsCommPtr oc, 364bbe1b32bSmrg char *extraBuf, 365bbe1b32bSmrg int extraCount, 366bbe1b32bSmrg int padsize) 367bbe1b32bSmrg{ 368bbe1b32bSmrg ConnectionOutputPtr oco = oc->output; 369bbe1b32bSmrg int fd = oc->fd; 370bbe1b32bSmrg struct iovec iov[3]; 371bbe1b32bSmrg char padBuffer[3]; 372bbe1b32bSmrg long written; 373bbe1b32bSmrg long notWritten; 374bbe1b32bSmrg long todo; 375bbe1b32bSmrg 376bbe1b32bSmrg if (!oco) 377bbe1b32bSmrg return 0; 378bbe1b32bSmrg written = 0; 379bbe1b32bSmrg notWritten = oco->count + extraCount + padsize; 380bbe1b32bSmrg todo = notWritten; 381bbe1b32bSmrg while (notWritten) { 382bbe1b32bSmrg long before = written; 383bbe1b32bSmrg long remain = todo; 384bbe1b32bSmrg int i = 0; 385bbe1b32bSmrg long len; 386bbe1b32bSmrg 387bbe1b32bSmrg /*- 388bbe1b32bSmrg * You could be very general here and have "in" and "out" iovecs and 389bbe1b32bSmrg * write a loop without using a macro, but what the heck. This 390bbe1b32bSmrg * translates to: 391bbe1b32bSmrg * 392bbe1b32bSmrg * how much of this piece is new? 393bbe1b32bSmrg * if more new then we are trying this time, clamp 394bbe1b32bSmrg * if nothing new 395bbe1b32bSmrg * then bump down amount already written, for next piece 396bbe1b32bSmrg * else put new stuff in iovec, will need all of next piece 397bbe1b32bSmrg * 398bbe1b32bSmrg * Note that todo had better be at least 1 or else we'll end up 399bbe1b32bSmrg * writing 0 iovecs. 400bbe1b32bSmrg */ 401bbe1b32bSmrg 402bbe1b32bSmrg#define InsertIOV(pointer, length) \ 403bbe1b32bSmrg len = (length) - before; \ 404bbe1b32bSmrg if (len > remain) \ 405bbe1b32bSmrg len = remain; \ 406bbe1b32bSmrg if (len <= 0) { \ 407bbe1b32bSmrg before = (-len); \ 408bbe1b32bSmrg } else { \ 409bbe1b32bSmrg iov[i].iov_len = len; \ 410bbe1b32bSmrg iov[i].iov_base = (pointer) + before; \ 411bbe1b32bSmrg i++; \ 412bbe1b32bSmrg remain -= len; \ 413bbe1b32bSmrg before = 0; \ 414bbe1b32bSmrg } 415bbe1b32bSmrg 416bbe1b32bSmrg InsertIOV((char *) oco->buf, oco->count); 417bbe1b32bSmrg InsertIOV(extraBuf, extraCount); 418bbe1b32bSmrg InsertIOV(padBuffer, padsize); 419bbe1b32bSmrg 420bbe1b32bSmrg errno = 0; 421bbe1b32bSmrg if (oc->trans_conn && (len = _FontTransWritev(oc->trans_conn, iov, i)) >= 0) { 422bbe1b32bSmrg written += len; 423bbe1b32bSmrg notWritten -= len; 424bbe1b32bSmrg todo = notWritten; 425bbe1b32bSmrg } else if (ETEST(errno) 426bbe1b32bSmrg#ifdef SUNSYSV /* check for another brain-damaged OS bug */ 427bbe1b32bSmrg || (errno == 0) 428bbe1b32bSmrg#endif 429bbe1b32bSmrg#ifdef EMSGSIZE /* check for another brain-damaged OS bug */ 430bbe1b32bSmrg || ((errno == EMSGSIZE) && (todo == 1)) 431bbe1b32bSmrg#endif 432bbe1b32bSmrg ) 433bbe1b32bSmrg { 434bbe1b32bSmrg FD_SET(fd, &ClientsWriteBlocked); 435bbe1b32bSmrg AnyClientsWriteBlocked = TRUE; 436bbe1b32bSmrg 437bbe1b32bSmrg if (written < oco->count) { 438bbe1b32bSmrg if (written > 0) { 439bbe1b32bSmrg oco->count -= written; 440bbe1b32bSmrg memmove( (char *) oco->buf, (char *) oco->buf + written, 441bbe1b32bSmrg oco->count); 442bbe1b32bSmrg written = 0; 443bbe1b32bSmrg } 444bbe1b32bSmrg } else { 445bbe1b32bSmrg written -= oco->count; 446bbe1b32bSmrg oco->count = 0; 447bbe1b32bSmrg } 448bbe1b32bSmrg 449bbe1b32bSmrg /* grow buffer if necessary */ 450bbe1b32bSmrg if (notWritten > oco->size) { 451bbe1b32bSmrg unsigned char *obuf; 452bbe1b32bSmrg 453bbe1b32bSmrg obuf = (unsigned char *) fsrealloc(oco->buf, 454bbe1b32bSmrg notWritten + OutputBufferSize); 455bbe1b32bSmrg if (!obuf) { 456bbe1b32bSmrg if (oc->trans_conn) 457bbe1b32bSmrg _FontTransClose(oc->trans_conn); 458bbe1b32bSmrg oc->trans_conn = NULL; 459bbe1b32bSmrg MarkClientException(client); 460bbe1b32bSmrg oco->count = 0; 461bbe1b32bSmrg return -1; 462bbe1b32bSmrg } 463bbe1b32bSmrg oco->size = notWritten + OutputBufferSize; 464bbe1b32bSmrg oco->buf = obuf; 465bbe1b32bSmrg } 466bbe1b32bSmrg if ((len = extraCount - written) > 0) { 467bbe1b32bSmrg memmove( (char *) oco->buf + oco->count, 468bbe1b32bSmrg extraBuf + written, len); 469bbe1b32bSmrg } 470bbe1b32bSmrg oco->count = notWritten; 471bbe1b32bSmrg return extraCount; 472bbe1b32bSmrg } 473bbe1b32bSmrg#ifdef EMSGSIZE /* check for another brain-damaged OS bug */ 474bbe1b32bSmrg else if (errno == EMSGSIZE) 475bbe1b32bSmrg { 476bbe1b32bSmrg todo >>= 1; 477bbe1b32bSmrg } 478bbe1b32bSmrg#endif 479bbe1b32bSmrg else 480bbe1b32bSmrg { 481bbe1b32bSmrg if (oc->trans_conn) 482bbe1b32bSmrg _FontTransClose(oc->trans_conn); 483bbe1b32bSmrg oc->trans_conn = NULL; 484bbe1b32bSmrg MarkClientException(client); 485bbe1b32bSmrg oco->count = 0; 486bbe1b32bSmrg return -1; 487bbe1b32bSmrg } 488bbe1b32bSmrg } 489bbe1b32bSmrg 490bbe1b32bSmrg /* everything was flushed */ 491bbe1b32bSmrg oco->count = 0; 492bbe1b32bSmrg 493bbe1b32bSmrg /* clear the write block if it was set */ 494bbe1b32bSmrg if (AnyClientsWriteBlocked) { 495bbe1b32bSmrg FD_CLR(fd, &ClientsWriteBlocked); 496bbe1b32bSmrg if (!XFD_ANYSET(&ClientsWriteBlocked)) 497bbe1b32bSmrg AnyClientsWriteBlocked = FALSE; 498bbe1b32bSmrg } 499bbe1b32bSmrg if (oco->size > BUFWATERMARK) { 500bbe1b32bSmrg fsfree(oco->buf); 501bbe1b32bSmrg fsfree(oco); 502bbe1b32bSmrg } else { 503bbe1b32bSmrg oco->next = FreeOutputs; 504bbe1b32bSmrg FreeOutputs = oco; 505bbe1b32bSmrg } 506bbe1b32bSmrg oc->output = (ConnectionOutputPtr) NULL; 507bbe1b32bSmrg 508bbe1b32bSmrg return extraCount; 509bbe1b32bSmrg} 510bbe1b32bSmrg 511bbe1b32bSmrgvoid 512bbe1b32bSmrgFlushAllOutput(void) 513bbe1b32bSmrg{ 514bbe1b32bSmrg int index, base; 515bbe1b32bSmrg fd_mask mask; 516bbe1b32bSmrg OsCommPtr oc; 517bbe1b32bSmrg ClientPtr client; 518bbe1b32bSmrg 519bbe1b32bSmrg if (!NewOutputPending) 520bbe1b32bSmrg return; 521bbe1b32bSmrg 522bbe1b32bSmrg NewOutputPending = FALSE; 523bbe1b32bSmrg 524bbe1b32bSmrg for (base = 0; base < howmany(XFD_SETSIZE, NFDBITS); base++) { 525bbe1b32bSmrg mask = OutputPending.fds_bits[base]; 526bbe1b32bSmrg OutputPending.fds_bits[base] = 0; 527bbe1b32bSmrg while (mask) { 52830f8ce46Smrg index = xfd_ffs(mask) - 1; 529bbe1b32bSmrg mask &= ~lowbit(mask); 53030f8ce46Smrg if ((index = ConnectionTranslation[(base * (sizeof(fd_mask) * 8)) + index]) == 0) 531bbe1b32bSmrg continue; 532bbe1b32bSmrg client = clients[index]; 533bbe1b32bSmrg if (client->clientGone == CLIENT_GONE) 534bbe1b32bSmrg continue; 535bbe1b32bSmrg oc = (OsCommPtr) client->osPrivate; 536bbe1b32bSmrg if (FD_ISSET(oc->fd, &ClientsWithInput)) { 537bbe1b32bSmrg FD_SET(oc->fd, &OutputPending); 538bbe1b32bSmrg NewOutputPending = TRUE; 539bbe1b32bSmrg } else { 540bbe1b32bSmrg (void) FlushClient(client, oc, (char *) NULL, 0, 0); 541bbe1b32bSmrg } 542bbe1b32bSmrg } 543bbe1b32bSmrg } 544bbe1b32bSmrg} 545bbe1b32bSmrg 546bbe1b32bSmrg/* 547bbe1b32bSmrg * returns number of bytes written 548bbe1b32bSmrg */ 549bbe1b32bSmrgstatic int 550bbe1b32bSmrgwrite_to_client_internal(ClientPtr client, int count, char *buf, int padBytes) 551bbe1b32bSmrg{ 552bbe1b32bSmrg OsCommPtr oc = (OsCommPtr) client->osPrivate; 553bbe1b32bSmrg ConnectionOutputPtr oco = oc->output; 554bbe1b32bSmrg 555bbe1b32bSmrg if (!count) 556bbe1b32bSmrg return 0; 557bbe1b32bSmrg 558bbe1b32bSmrg if (!oco) { 559bbe1b32bSmrg if ((oco = FreeOutputs) != (ConnectionOutputPtr) 0) { 560bbe1b32bSmrg FreeOutputs = oco->next; 561bbe1b32bSmrg } else if (!(oco = AllocateOutputBuffer())) { 562bbe1b32bSmrg _FontTransClose(oc->trans_conn); 563bbe1b32bSmrg oc->trans_conn = NULL; 564bbe1b32bSmrg MarkClientException(client); 565bbe1b32bSmrg return -1; 566bbe1b32bSmrg } 567bbe1b32bSmrg oc->output = oco; 568bbe1b32bSmrg } 569bbe1b32bSmrg if (oco->count + count + padBytes > oco->size) { 570bbe1b32bSmrg FD_CLR(oc->fd, &OutputPending); 571bbe1b32bSmrg NewOutputPending = FALSE; 572bbe1b32bSmrg return FlushClient(client, oc, buf, count, padBytes); 573bbe1b32bSmrg } 574bbe1b32bSmrg NewOutputPending = TRUE; 575bbe1b32bSmrg FD_SET(oc->fd, &OutputPending); 576bbe1b32bSmrg memmove( (char *) oco->buf + oco->count, buf, count); 577bbe1b32bSmrg oco->count += count + padBytes; 578bbe1b32bSmrg 579bbe1b32bSmrg return count; 580bbe1b32bSmrg} 581bbe1b32bSmrg 582bbe1b32bSmrgvoid 583bbe1b32bSmrgWriteToClientUnpadded(ClientPtr client, int count, char *buf) 584bbe1b32bSmrg{ 585bbe1b32bSmrg write_to_client_internal(client, count, buf, 0); 586bbe1b32bSmrg} 587bbe1b32bSmrg 588bbe1b32bSmrgstatic int padlength[4] = {0, 3, 2, 1}; 589bbe1b32bSmrg 590bbe1b32bSmrgvoid 591bbe1b32bSmrgWriteToClient(ClientPtr client, int count, char *buf) 592bbe1b32bSmrg{ 593bbe1b32bSmrg int flag = 0; 594bbe1b32bSmrg if (NULL == buf) { 595bbe1b32bSmrg flag = -1; 596bbe1b32bSmrg buf = (char *)fsalloc(count); memset(buf, 0, count); 597bbe1b32bSmrg } 598bbe1b32bSmrg write_to_client_internal(client, count, buf, padlength[count & 3]); 599bbe1b32bSmrg if (flag) 600bbe1b32bSmrg fsfree(buf); 601bbe1b32bSmrg} 602bbe1b32bSmrg 603bbe1b32bSmrgstatic ConnectionInputPtr 604bbe1b32bSmrgAllocateInputBuffer(void) 605bbe1b32bSmrg{ 606bbe1b32bSmrg register ConnectionInputPtr oci; 607bbe1b32bSmrg 608bbe1b32bSmrg oci = (ConnectionInputPtr) fsalloc(sizeof(ConnectionInput)); 609bbe1b32bSmrg if (!oci) 610bbe1b32bSmrg return (ConnectionInputPtr) NULL; 611bbe1b32bSmrg oci->buffer = (char *) fsalloc(BUFSIZE); 612bbe1b32bSmrg if (!oci->buffer) { 613bbe1b32bSmrg fsfree(oci); 614bbe1b32bSmrg return (ConnectionInputPtr) NULL; 615bbe1b32bSmrg } 616ce6676dbSmrg oci->next = NULL; 617bbe1b32bSmrg oci->size = BUFSIZE; 618bbe1b32bSmrg oci->bufptr = oci->buffer; 619bbe1b32bSmrg oci->bufcnt = 0; 620bbe1b32bSmrg oci->lenLastReq = 0; 621bbe1b32bSmrg return oci; 622bbe1b32bSmrg} 623bbe1b32bSmrg 624bbe1b32bSmrgstatic ConnectionOutputPtr 625bbe1b32bSmrgAllocateOutputBuffer(void) 626bbe1b32bSmrg{ 627bbe1b32bSmrg register ConnectionOutputPtr oco; 628bbe1b32bSmrg 629bbe1b32bSmrg oco = (ConnectionOutputPtr) fsalloc(sizeof(ConnectionOutput)); 630bbe1b32bSmrg if (!oco) 631bbe1b32bSmrg return (ConnectionOutputPtr) NULL; 632bbe1b32bSmrg oco->buf = (unsigned char *) fsalloc(BUFSIZE); 633bbe1b32bSmrg if (!oco->buf) { 634bbe1b32bSmrg fsfree(oco); 635bbe1b32bSmrg return (ConnectionOutputPtr) NULL; 636bbe1b32bSmrg } 637bbe1b32bSmrg oco->size = BUFSIZE; 638bbe1b32bSmrg oco->count = 0; 639bbe1b32bSmrg return oco; 640bbe1b32bSmrg} 641bbe1b32bSmrg 642bbe1b32bSmrg 643bbe1b32bSmrgvoid 644bbe1b32bSmrgFreeOsBuffers(OsCommPtr oc) 645bbe1b32bSmrg{ 646bbe1b32bSmrg register ConnectionInputPtr oci; 647bbe1b32bSmrg register ConnectionOutputPtr oco; 648bbe1b32bSmrg 649bbe1b32bSmrg if (AvailableInput == oc) 650bbe1b32bSmrg AvailableInput = (OsCommPtr) NULL; 651bbe1b32bSmrg if ((oci = oc->input) != (ConnectionInputPtr) 0) { 652bbe1b32bSmrg if (FreeInputs) { 653bbe1b32bSmrg fsfree(oci->buffer); 654bbe1b32bSmrg fsfree(oci); 655bbe1b32bSmrg } else { 656bbe1b32bSmrg FreeInputs = oci; 657bbe1b32bSmrg oci->next = (ConnectionInputPtr) NULL; 658bbe1b32bSmrg oci->bufptr = oci->buffer; 659bbe1b32bSmrg oci->bufcnt = 0; 660bbe1b32bSmrg oci->lenLastReq = 0; 661bbe1b32bSmrg } 662bbe1b32bSmrg } 663bbe1b32bSmrg if ((oco = oc->output) != (ConnectionOutputPtr) 0) { 664bbe1b32bSmrg if (FreeOutputs) { 665bbe1b32bSmrg fsfree(oco->buf); 666bbe1b32bSmrg fsfree(oco); 667bbe1b32bSmrg } else { 668bbe1b32bSmrg FreeOutputs = oco; 669bbe1b32bSmrg oco->next = (ConnectionOutputPtr) NULL; 670bbe1b32bSmrg oco->count = 0; 671bbe1b32bSmrg } 672bbe1b32bSmrg } 673bbe1b32bSmrg} 674bbe1b32bSmrg 675bbe1b32bSmrgvoid 676bbe1b32bSmrgResetOsBuffers(void) 677bbe1b32bSmrg{ 678bbe1b32bSmrg register ConnectionInputPtr oci; 679bbe1b32bSmrg register ConnectionOutputPtr oco; 680bbe1b32bSmrg 681bbe1b32bSmrg while ((oci = FreeInputs) != (ConnectionInputPtr) 0) { 682bbe1b32bSmrg FreeInputs = oci->next; 683bbe1b32bSmrg fsfree(oci->buffer); 684bbe1b32bSmrg fsfree(oci); 685bbe1b32bSmrg } 686bbe1b32bSmrg while ((oco = FreeOutputs) != (ConnectionOutputPtr) 0) { 687bbe1b32bSmrg FreeOutputs = oco->next; 688bbe1b32bSmrg fsfree(oco->buf); 689bbe1b32bSmrg fsfree(oco); 690bbe1b32bSmrg } 691bbe1b32bSmrg} 692