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