Annotation of 43BSDReno/contrib/isode-beta/others/X/server/io.c, revision 1.1

1.1     ! root        1: /***********************************************************
        !             2: Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts,
        !             3: and the Massachusetts Institute of Technology, Cambridge, Massachusetts.
        !             4: 
        !             5:                         All Rights Reserved
        !             6: 
        !             7: Permission to use, copy, modify, and distribute this software and its 
        !             8: documentation for any purpose and without fee is hereby granted, 
        !             9: provided that the above copyright notice appear in all copies and that
        !            10: both that copyright notice and this permission notice appear in 
        !            11: supporting documentation, and that the names of Digital or MIT not be
        !            12: used in advertising or publicity pertaining to distribution of the
        !            13: software without specific, written prior permission.  
        !            14: 
        !            15: DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
        !            16: ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
        !            17: DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
        !            18: ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
        !            19: WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
        !            20: ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
        !            21: SOFTWARE.
        !            22: 
        !            23: ******************************************************************/
        !            24: /* $XConsortium: io.c,v 1.49 88/09/06 15:50:44 jim Exp $ */
        !            25: /*****************************************************************
        !            26:  * i/o functions
        !            27:  *
        !            28:  *   WriteToClient, ReadRequestFromClient
        !            29:  *
        !            30:  *****************************************************************/
        !            31: 
        !            32: #include <stdio.h>
        !            33: #include "Xos.h"
        !            34: #include "Xmd.h"
        !            35: #include <errno.h>
        !            36: #include <sys/param.h>
        !            37: #include <sys/types.h>
        !            38: #include <sys/uio.h>
        !            39: #include "X.h"
        !            40: #include "Xproto.h"
        !            41: #include "os.h"
        !            42: #include "osdep.h"
        !            43: #include "opaque.h"
        !            44: #include "dixstruct.h"
        !            45: #include "misc.h"
        !            46: 
        !            47: #ifdef ISOCONN
        !            48: #include <isode/tsap.h>
        !            49: #endif /* ISOCONN */
        !            50: 
        !            51: extern long ClientsWithInput[];
        !            52: extern long ClientsWriteBlocked[];
        !            53: extern long OutputPending[];
        !            54: extern long OutputBufferSize;
        !            55: extern ClientPtr ConnectionTranslation[];
        !            56: extern Bool NewOutputPending;
        !            57: extern Bool AnyClientsWriteBlocked;
        !            58: static Bool CriticalOutputPending;
        !            59: static int timesThisConnection = 0;
        !            60: 
        !            61: extern int errno;
        !            62: 
        !            63: #define request_length(req, cli) ((cli->swapped ? \
        !            64:        lswaps((req)->length) : (req)->length) << 2)
        !            65: #define MAX_TIMES_PER         10
        !            66: 
        !            67: #ifdef ISOCONN
        !            68: /*
        !            69:  * Convenience Routines
        !            70:  */
        !            71: TWriteToClient(sd, buf, len)
        !            72: int sd, len;
        !            73: char *buf;
        !            74: {
        !            75:     struct TSAPdisconnect tds;
        !            76:     struct TSAPdisconnect *td = &tds;
        !            77: 
        !            78:     if (TDataRequest(sd, buf, len, td) == NOTOK){      
        !            79:        if (errno != EWOULDBLOCK)
        !            80:                fprintf(stderr, "TWriteToClient: %s\n", td->td_reason);
        !            81:     }
        !            82: }
        !            83: /*
        !            84:  * sd = transport descriptor
        !            85:  * iov is iovec of iovcnt buffers
        !            86:  */
        !            87: TWritevToClient(sd, iov, iovcnt)
        !            88: int sd, iovcnt;
        !            89: struct iovec *iov;
        !            90: {
        !            91:     int i, ret, tot = 0;
        !            92:     struct udvec uv[64], *uvp = uv;
        !            93:     struct TSAPdisconnect tds;
        !            94:     struct TSAPdisconnect *td = &tds;
        !            95: 
        !            96: /*
        !            97:  * Grotty hack
        !            98:  */
        !            99:     if (iovcnt >= 64) {
        !           100:        fprintf(stderr, "Oh Spaghettio\n");
        !           101:        return -1;
        !           102:     }
        !           103:     for(i=0; i<iovcnt; i++, uvp++, iov++) {
        !           104:        uvp->uv_base = iov->iov_base;
        !           105:        uvp->uv_len = iov->iov_len;
        !           106:        tot += iov->iov_len;
        !           107:     }
        !           108:     uvp->uv_base = NULL;
        !           109:     uvp->uv_len = 0;
        !           110:        
        !           111:     ret = TWriteRequest (sd, uv, td);
        !           112:     if (ret == NOTOK) {
        !           113: #ifdef ISODEBUG
        !           114:        if (errno != EWOULDBLOCK) 
        !           115:                if (isodexbug)
        !           116:                        fprintf(stderr, "TWritevToCl: %s\n", TErrString(td->td_reason));
        !           117: #endif /* ISODEBUG */
        !           118:        return ret;
        !           119:     } else {
        !           120: #ifdef ISODEBUG
        !           121:        if  (isodexbug)
        !           122:                fprintf(stderr, "TWritevToCl to %d: %d\n", sd, tot);
        !           123: #endif /* ISODEBUG */
        !           124:        return tot;
        !           125:     }
        !           126: }
        !           127: 
        !           128: TAcceptFromClient(fd, vecp, vec)
        !           129: int fd;
        !           130: int vecp;
        !           131: char **vec;
        !           132: {
        !           133:        struct TSAPdisconnect tds;
        !           134:        struct TSAPdisconnect *td = &tds;
        !           135:        struct TSAPstart tsts;
        !           136:        struct TSAPstart *tst = &tsts;
        !           137: 
        !           138:        if (TInit(vecp, vec, tst,  td) == NOTOK) {
        !           139:                 Error(TErrString(td->td_reason));
        !           140:                 Error("TInit");
        !           141:                return -1;
        !           142:        }
        !           143: 
        !           144:        if (TConnResponse(tst->ts_sd, NULLTA, tst->ts_expedited, NULL, 0,
        !           145:                         &(tst->ts_qos), td) == NOTOK) {
        !           146:                 Error(TErrString(td->td_reason));
        !           147:                 Error("TConnResponse");
        !           148:                return -1;
        !           149:        }
        !           150:        return tst->ts_sd;
        !           151: }
        !           152: 
        !           153: TDiscFromClient(fd)
        !           154: int fd;
        !           155: {
        !           156:        struct TSAPdisconnect tds;
        !           157: 
        !           158:        if (TDiscRequest(fd, NULLCP, 0, &tds)==NOTOK)
        !           159:                     fprintf(stderr, "TDisc Failed %s\n",
        !           160:                         TErrString(tds.td_reason));
        !           161: }
        !           162: #endif /* ISOCONN */
        !           163: 
        !           164: /*****************************************************************
        !           165:  * ReadRequestFromClient
        !           166:  *    Returns one request from client.  If the client misbehaves,
        !           167:  *    returns NULL.  The dispatcher closes down all misbehaving clients.  
        !           168:  *
        !           169:  *        client:  index into bit array returned from WaitForSomething() 
        !           170:  *
        !           171:  *        status: status is set to
        !           172:  *            > 0 the number of bytes in the request if the read is sucessful 
        !           173:  *            = 0 if action would block (entire request not ready)
        !           174:  *            < 0 indicates an error (probably client died)
        !           175:  *
        !           176:  *        oldbuf:
        !           177:  *            To facilitate buffer management (e.g. on multi-processor
        !           178:  *            systems), the diX layer must tell the OS layer when it is 
        !           179:  *            done with a request, so the parameter oldbuf is a pointer 
        !           180:  *            to a request that diX is finished with.  In the 
        !           181:  *            sample implementation, which is single threaded,
        !           182:  *            oldbuf is ignored.  We assume that when diX calls
        !           183:  *            ReadRequestFromClient(), the previous buffer is finished with.
        !           184:  *
        !           185:  *    The returned string returned must be contiguous so that it can be
        !           186:  *    cast in the dispatcher to the correct request type.  Because requests
        !           187:  *    are variable length, ReadRequestFromClient() must look at the first 4
        !           188:  *    bytes of a request to determine the length (the request length is
        !           189:  *    always the 3rd byte in the request).  
        !           190:  *
        !           191:  *    Note: in order to make the server scheduler (WaitForSomething())
        !           192:  *    "fair", the ClientsWithInput mask is used.  This mask tells which
        !           193:  *    clients have FULL requests left in their buffers.  Clients with
        !           194:  *    partial requests require a read.  Basically, client buffers
        !           195:  *    are drained before select() is called again.  But, we can't keep
        !           196:  *    reading from a client that is sending buckets of data (or has
        !           197:  *    a partial request) because others clients need to be scheduled.
        !           198:  *****************************************************************/
        !           199: 
        !           200: ConnectionInput inputBuffers[MAXSOCKS];    /* buffers for clients */
        !           201: 
        !           202: /*ARGSUSED*/
        !           203: char *
        !           204: ReadRequestFromClient(who, status, oldbuf)
        !           205:     ClientPtr who;
        !           206:     int *status;          /* read at least n from client */
        !           207:     char *oldbuf;
        !           208: {
        !           209: #define YieldControl()                         \
        !           210:         { isItTimeToYield = TRUE;              \
        !           211:          timesThisConnection = 0; }
        !           212: #define YieldControlNoInput()                  \
        !           213:         { YieldControl();                      \
        !           214:          BITCLEAR(ClientsWithInput, client); }
        !           215: #define YieldControlAndReturnNull()            \
        !           216:         { YieldControlNoInput();               \
        !           217:          return((char *) NULL ); }
        !           218: 
        !           219:     OsCommPtr oc = (OsCommPtr)who->osPrivate;
        !           220:     int client = oc->fd;
        !           221:     int result, gotnow, needed;
        !           222:     register ConnectionInput *pBuff;
        !           223:     register xReq *request;
        !           224: 
        !           225:         /* ignore oldbuf, just assume we're done with prev. buffer */
        !           226: 
        !           227:     if (client == -1) 
        !           228:     {
        !           229:        ErrorF( "OH NO, %d translates to -1\n", who);
        !           230:        return((char *)NULL);
        !           231:     }
        !           232: 
        !           233:     pBuff = &inputBuffers[client];
        !           234:     pBuff->bufptr += pBuff->lenLastReq;
        !           235:     pBuff->lenLastReq = 0;
        !           236: 
        !           237:             /* handle buffer empty or full case first */
        !           238: 
        !           239:     if ((pBuff->bufptr - pBuff->buffer) >= pBuff->bufcnt)
        !           240:     {
        !           241: #ifdef ISOCONN
        !           242:        result = SRead(client, pBuff->buffer, pBuff->size, OK);
        !           243: #else /* ISOCONN */
        !           244:         result = read(client, pBuff->buffer, pBuff->size);
        !           245: #endif /* ISOCONN */
        !           246:        if (result < 0) 
        !           247:        {
        !           248:            if (errno == EWOULDBLOCK)
        !           249:                *status = 0;
        !           250:            else
        !           251:                *status = -1;
        !           252:            YieldControlAndReturnNull();
        !           253:        }
        !           254:        else if (result == 0)
        !           255:         {
        !           256:            *status = -1;
        !           257:            YieldControlAndReturnNull();
        !           258:        }
        !           259:        else 
        !           260:        {
        !           261:            pBuff->bufcnt = result; 
        !           262:            /* free up some space after huge requests */
        !           263:            if ((pBuff->size > BUFWATERMARK) && (result < BUFSIZE))
        !           264:            {
        !           265:                pBuff->size = BUFSIZE;
        !           266:                pBuff->buffer = (char *)xrealloc(pBuff->buffer, pBuff->size);
        !           267:            }
        !           268:            pBuff->bufptr = pBuff->buffer;
        !           269:        }
        !           270:     }
        !           271:               /* now look if there is enough in the buffer */
        !           272: 
        !           273:     request = (xReq *)pBuff->bufptr;
        !           274:     gotnow = pBuff->bufcnt + pBuff->buffer - pBuff->bufptr;
        !           275: 
        !           276:     if (gotnow < sizeof(xReq))
        !           277:        needed = sizeof(xReq) - gotnow;
        !           278:     else
        !           279:     {
        !           280:         needed = request_length(request, who);
        !           281:         if (needed > MAXBUFSIZE)
        !           282:         {
        !           283:            *status = -1;
        !           284:            YieldControlAndReturnNull();
        !           285:         }
        !           286:        if (needed <= 0)
        !           287:             needed = sizeof(xReq);
        !           288:     }
        !           289:         /* if the needed amount won't fit in what's remaining,
        !           290:           move everything to the front of the buffer.  If the
        !           291:           entire header isn't available, move what's there too */
        !           292:     if ((pBuff->bufptr + needed - pBuff->buffer > pBuff->size) ||
        !           293:                (gotnow < sizeof(xReq)))
        !           294:     {
        !           295:         bcopy(pBuff->bufptr, pBuff->buffer, gotnow);
        !           296:        pBuff->bufcnt = gotnow;
        !           297:         if (needed > pBuff->size)
        !           298:         {
        !           299:            pBuff->size = needed;
        !           300:            pBuff->buffer = (char *)xrealloc(pBuff->buffer, needed);
        !           301:         }
        !           302:         pBuff->bufptr = pBuff->buffer;
        !           303:     }
        !           304:                /* don't have a full header */
        !           305:     if (gotnow < sizeof(xReq))
        !           306:     {
        !           307:         while (pBuff->bufcnt + pBuff->buffer - pBuff->bufptr < sizeof(xReq))
        !           308:        {
        !           309: #ifdef ISOCONN
        !           310:            result = SRead(client, 
        !           311:                        pBuff->buffer + pBuff->bufcnt, 
        !           312:                        pBuff->size - pBuff->bufcnt, 
        !           313:                        OK);
        !           314: #else /* ISOCONN */
        !           315:            result = read(client, pBuff->buffer + pBuff->bufcnt, 
        !           316:                      pBuff->size - pBuff->bufcnt); 
        !           317: #endif /* ISOCONN */
        !           318:            if (result < 0)
        !           319:            {
        !           320:                if (errno == EWOULDBLOCK)
        !           321:                    *status = 0;
        !           322:                else
        !           323:                    *status = -1;
        !           324:                YieldControlAndReturnNull();
        !           325:            }
        !           326:            if (result == 0)
        !           327:            {
        !           328:                *status = -1;
        !           329:                YieldControlAndReturnNull();
        !           330:            }
        !           331:             pBuff->bufcnt += result;        
        !           332:        }
        !           333:         request = (xReq *)pBuff->bufptr;
        !           334:         gotnow = pBuff->bufcnt + pBuff->buffer - pBuff->bufptr;
        !           335:         needed = request_length(request, who);
        !           336:        if (needed <= 0)
        !           337:             needed = sizeof(xReq);
        !           338:         if (needed > pBuff->size)
        !           339:         {
        !           340:            pBuff->size = needed;
        !           341:            pBuff->buffer = (char *)xrealloc(pBuff->buffer, needed);
        !           342:         }
        !           343:         pBuff->bufptr = pBuff->buffer;
        !           344:     }  
        !           345: 
        !           346:     if (gotnow < needed )   
        !           347:     {
        !           348:        int i, wanted;
        !           349: 
        !           350:        wanted = needed - gotnow;
        !           351:        i = 0;
        !           352:        while (i < wanted) 
        !           353:        {
        !           354: #ifdef ISOCONN
        !           355:            result = SRead(client, 
        !           356:                            pBuff->buffer + pBuff->bufcnt, 
        !           357:                            pBuff->size - pBuff->bufcnt,
        !           358:                            OK); 
        !           359: #else /* ISOCONN */
        !           360:            result = read(client, pBuff->buffer + pBuff->bufcnt, 
        !           361:                          pBuff->size - pBuff->bufcnt); 
        !           362: #endif /* ISOCONN */
        !           363:            if (result < 0) 
        !           364:            {
        !           365:                if (errno == EWOULDBLOCK)
        !           366:                    *status = 0;
        !           367:                else
        !           368:                    *status = -1;
        !           369:                YieldControlAndReturnNull();
        !           370:            }
        !           371:            else if (result == 0)
        !           372:            {
        !           373:                *status = -1;
        !           374:                YieldControlAndReturnNull();
        !           375:            }
        !           376:            i += result;
        !           377:            pBuff->bufcnt += result;
        !           378:        }
        !           379:     }
        !           380:     *status = needed;
        !           381:     pBuff->lenLastReq = needed;
        !           382: 
        !           383:     /*
        !           384:      *  Check to see if client has at least one whole request in the
        !           385:      *  buffer.  If there is only a partial request, treat like buffer
        !           386:      *  is empty so that select() will be called again and other clients
        !           387:      *  can get into the queue.   
        !           388:      */
        !           389: 
        !           390:     timesThisConnection++;
        !           391:     if (pBuff->bufcnt + pBuff->buffer >= pBuff->bufptr + needed + sizeof(xReq)) 
        !           392:     {
        !           393:        request = (xReq *)(pBuff->bufptr + needed);
        !           394:         if ((pBuff->bufcnt + pBuff->buffer) >= 
        !           395:             ((char *)request + request_length(request, who)))
        !           396:            BITSET(ClientsWithInput, client);
        !           397:         else
        !           398:            YieldControlNoInput();
        !           399:     }
        !           400:     else
        !           401:        YieldControlNoInput();
        !           402:     if (timesThisConnection == MAX_TIMES_PER)
        !           403:        YieldControl();
        !           404: 
        !           405:     return((char *)pBuff->bufptr);
        !           406: 
        !           407: #undef YieldControlAndReturnNull
        !           408: #undef YieldControlNoInput
        !           409: #undef YieldControl
        !           410: }
        !           411: 
        !           412: 
        !           413:     /* lookup table for adding padding bytes to data that is read from
        !           414:        or written to the X socket.  */
        !           415: static int padlength[4] = {0, 3, 2, 1};
        !           416: 
        !           417:  /********************
        !           418:  * FlushClient()
        !           419:  *    If the client isn't keeping up with us, then we try to continue
        !           420:  *    buffering the data and set the apropriate bit in ClientsWritable
        !           421:  *    (which is used by WaitFor in the select).  If the connection yields
        !           422:  *    a permanent error, or we can't allocate any more space, we then
        !           423:  *    close the connection.
        !           424:  *
        !           425:  **********************/
        !           426: 
        !           427: static int
        !           428: FlushClient(who, oc, extraBuf, extraCount)
        !           429:     ClientPtr who;
        !           430:     OsCommPtr oc;
        !           431:     char *extraBuf;
        !           432:     int extraCount; /* do not modify... returned below */
        !           433: {
        !           434:     int connection = oc->fd,
        !           435:        total, n, i, notWritten, written,
        !           436:        iovCnt = 0;
        !           437:     struct iovec iov[3];
        !           438:     char padBuffer[3];
        !           439: #ifdef ISOCONN
        !           440:     struct TSAPdisconnect tds;
        !           441: #endif /* ISOCONN */
        !           442: 
        !           443:     total = 0;
        !           444:     if (oc->count)
        !           445:     {
        !           446:        total += iov[iovCnt].iov_len = oc->count;
        !           447:        iov[iovCnt++].iov_base = (caddr_t)oc->buf;
        !           448:         /* Notice that padding isn't needed for oc->buf since
        !           449:            it is alreay padded by WriteToClient */
        !           450:     }
        !           451:     if (extraCount)
        !           452:     {
        !           453:        total += iov[iovCnt].iov_len = extraCount;
        !           454:        iov[iovCnt++].iov_base = extraBuf;
        !           455:        if (extraCount & 3)
        !           456:        {
        !           457:            total += iov[iovCnt].iov_len = padlength[extraCount & 3];
        !           458:            iov[iovCnt++].iov_base = padBuffer;
        !           459:        }
        !           460:     }
        !           461: 
        !           462:     notWritten = total;
        !           463:        
        !           464: #ifdef ISOCONN
        !           465:     while ((n = SWritev (connection, iov, iovCnt)) != notWritten)
        !           466: #else /* ISOCONN */
        !           467:     while ((n = writev (connection, iov, iovCnt)) != notWritten)
        !           468: #endif /* ISOCONN */
        !           469:     {
        !           470: #ifdef hpux
        !           471:        if (n == -1 && errno == EMSGSIZE)
        !           472:            n = swWritev (connection, iov, 2);
        !           473: #endif
        !           474:         if (n > 0) 
        !           475:         {
        !           476:            notWritten -= n;
        !           477:            for (i = 0; i < iovCnt; i++)
        !           478:             {
        !           479:                if (n > iov[i].iov_len)
        !           480:                {
        !           481:                    n -= iov[i].iov_len;
        !           482:                    iov[i].iov_len = 0;
        !           483:                }
        !           484:                else
        !           485:                {
        !           486:                    iov[i].iov_len -= n;
        !           487:                    iov[i].iov_base += n;
        !           488:                    break;
        !           489:                }
        !           490:            }
        !           491:            continue;
        !           492:        }
        !           493:        else if (errno != EWOULDBLOCK)
        !           494:         {
        !           495: #ifdef notdef  
        !           496:            if (errno != EBADF)
        !           497:                ErrorF("Closing connection %d because write failed\n",
        !           498:                        connection);
        !           499:                /* this close will cause the select in WaitForSomething
        !           500:                   to return that the connection is dead, so we can actually
        !           501:                   clean up after the client.  We can't clean up here,
        !           502:                   because the we're in the middle of doing something
        !           503:                   and will probably screw up some data strucutres */
        !           504: #endif
        !           505: #ifdef ISOCONN
        !           506:            SClose(connection);
        !           507: #else /* ISOCONN */
        !           508:            close(connection);
        !           509: #endif /* ISOCONN */
        !           510:             MarkClientException(who);
        !           511:            return(-1);
        !           512:        }
        !           513: 
        !           514:        /* If we've arrived here, then the client is stuffed to the gills
        !           515:           and not ready to accept more.  Make a note of it and buffer
        !           516:           the rest. */
        !           517:        BITSET(ClientsWriteBlocked, connection);
        !           518:        AnyClientsWriteBlocked = TRUE;
        !           519: 
        !           520:        written = total - notWritten;
        !           521:        if (written < oc->count)
        !           522:        {
        !           523:            if (written > 0)
        !           524:            {
        !           525:                oc->count -= written;
        !           526:                bcopy((char *)oc->buf + written, (char *)oc->buf, oc->count);
        !           527:                written = 0;
        !           528:            }
        !           529:        }
        !           530:        else
        !           531:        {
        !           532:            written -= oc->count;
        !           533:            oc->count = 0;
        !           534:        }
        !           535: 
        !           536:        if (notWritten > oc->bufsize)
        !           537:        {
        !           538:            /* allocate at least enough to contain it plus one
        !           539:               OutputBufferSize */
        !           540:            oc->bufsize = notWritten + OutputBufferSize;
        !           541:            oc->buf = (unsigned char *)xrealloc(oc->buf, oc->bufsize);
        !           542:            if (oc->buf == NULL)
        !           543:            {
        !           544:        outOfMem:
        !           545: #ifdef notdef
        !           546:                ErrorF("Closing connection %d because out of memory\n",
        !           547:                        connection);
        !           548:                /* this close will cause the select in WaitForSomething
        !           549:                   to return that the connection is dead, so we can actually
        !           550:                   clean up after the client.  We can't clean up here,
        !           551:                   because the we're in the middle of doing something
        !           552:                   and will probably screw up some data strucutres */
        !           553: #endif
        !           554: #ifdef ISOCONN
        !           555: #ifdef ISODEBUG
        !           556:                fprintf(stderr, "out of mem: closing connection %d\n", 
        !           557:                        connection);
        !           558: #endif /* ISODEBUG */
        !           559:                SClose(connection);
        !           560: #else /* ISOCONN */
        !           561:                close(connection);
        !           562: #endif /* ISOCONN */
        !           563:                MarkClientException(who);
        !           564:                oc->count = 0;
        !           565:                oc->bufsize = 0;
        !           566:                return(-1);
        !           567:            }
        !           568:        }
        !           569: 
        !           570:        /* If the amount written extended into the padBuffer, then the
        !           571:           difference "extraCount - written" may be less than 0 */
        !           572:        if ((n = extraCount - written) > 0)
        !           573:            bcopy (extraBuf + written, (char *)oc->buf + oc->count, n);
        !           574: 
        !           575:        oc->count = notWritten; /* this will include the pad */
        !           576: 
        !           577:        return extraCount; /* return only the amount explicitly requested */
        !           578:     }
        !           579: 
        !           580:     /* everything was flushed out */
        !           581:     oc->count = 0;
        !           582:     if (oc->bufsize > OutputBufferSize)
        !           583:     {
        !           584:        oc->bufsize = OutputBufferSize;
        !           585:        oc->buf = (unsigned char *)xrealloc(oc->buf, OutputBufferSize);
        !           586:        if (oc->buf == NULL) /* nearly impossible */
        !           587:            goto outOfMem;
        !           588:     }
        !           589:     return extraCount; /* return only the amount explicitly requested */
        !           590: }
        !           591: 
        !           592:  /********************
        !           593:  * FlushAllOutput()
        !           594:  *    Flush all clients with output.  However, if some client still
        !           595:  *    has input in the queue (more requests), then don't flush.  This
        !           596:  *    will prevent the output queue from being flushed every time around
        !           597:  *    the round robin queue.  Now, some say that it SHOULD be flushed
        !           598:  *    every time around, but...
        !           599:  *
        !           600:  **********************/
        !           601: 
        !           602: void
        !           603: FlushAllOutput()
        !           604: {
        !           605:     register int index, base, mask;
        !           606:     OsCommPtr oc;
        !           607:     register ClientPtr client;
        !           608: 
        !           609:     if (! NewOutputPending)
        !           610:        return;
        !           611: 
        !           612:     /*
        !           613:      * It may be that some client still has critical output pending,
        !           614:      * but he is not yet ready to receive it anyway, so we will
        !           615:      * simply wait for the select to tell us when he's ready to receive.
        !           616:      */
        !           617:     CriticalOutputPending = FALSE;
        !           618:     NewOutputPending = FALSE;
        !           619: 
        !           620:     for (base = 0; base < mskcnt; base++)
        !           621:     {
        !           622:        mask = OutputPending[ base ];
        !           623:        OutputPending[ base ] = 0;
        !           624:        while (mask)
        !           625:        {
        !           626:            index = ffs(mask) - 1;
        !           627:            mask &= ~lowbit(mask);
        !           628:            if ((client = ConnectionTranslation[(32 * base) + index ]) == NULL)
        !           629:                continue;
        !           630:            if (client->clientGone)
        !           631:                continue;
        !           632:            oc = (OsCommPtr)client->osPrivate;
        !           633:            if (GETBIT(ClientsWithInput, client->index))
        !           634:            {
        !           635:                BITSET(OutputPending, oc->fd); /* set the bit again */
        !           636:                NewOutputPending = TRUE;
        !           637:            }
        !           638:            else
        !           639:                FlushClient(client, oc, (char *)NULL, 0);
        !           640:        }
        !           641:     }
        !           642: 
        !           643: }
        !           644: 
        !           645: void
        !           646: FlushIfCriticalOutputPending()
        !           647: {
        !           648:     if (CriticalOutputPending)
        !           649:        FlushAllOutput();
        !           650: }
        !           651: 
        !           652: void
        !           653: SetCriticalOutputPending()
        !           654: {
        !           655:     CriticalOutputPending = TRUE;
        !           656: }
        !           657: 
        !           658: /*****************
        !           659:  * WriteToClient
        !           660:  *    Copies buf into ClientPtr.buf if it fits (with padding), else
        !           661:  *    flushes ClientPtr.buf and buf to client.  As of this writing,
        !           662:  *    every use of WriteToClient is cast to void, and the result
        !           663:  *    is ignored.  Potentially, this could be used by requests
        !           664:  *    that are sending several chunks of data and want to break
        !           665:  *    out of a loop on error.  Thus, we will leave the type of
        !           666:  *    this routine as int.
        !           667:  *****************/
        !           668: 
        !           669: int
        !           670: WriteToClient (who, count, buf)
        !           671:     ClientPtr who;
        !           672:     char *buf;
        !           673:     int count;
        !           674: {
        !           675:     OsCommPtr oc = (OsCommPtr)who->osPrivate;
        !           676:     int padBytes;
        !           677: 
        !           678:     if (oc->fd == -1) 
        !           679:     {
        !           680:        ErrorF( "OH NO, %d translates to -1\n", oc->fd);
        !           681:        return(-1);
        !           682:     }
        !           683: 
        !           684:     if (oc->fd == -2) 
        !           685:     {
        !           686: #ifdef notdef
        !           687:        ErrorF( "CONNECTION %d ON ITS WAY OUT\n", oc->fd);
        !           688: #endif
        !           689:        return(-1);
        !           690:     }
        !           691: 
        !           692:     padBytes =  padlength[count & 3];
        !           693: 
        !           694:     if (oc->count + count + padBytes > oc->bufsize)
        !           695:     {
        !           696:        BITCLEAR(OutputPending, oc->fd);
        !           697:        CriticalOutputPending = FALSE;
        !           698:        NewOutputPending = FALSE;
        !           699:        return FlushClient(who, oc, buf, count);
        !           700:     }
        !           701: 
        !           702:     NewOutputPending = TRUE;
        !           703:     BITSET(OutputPending, oc->fd);
        !           704:     bcopy(buf, (char *)oc->buf + oc->count, count);
        !           705:     oc->count += count + padBytes;
        !           706:     
        !           707:     return(count);
        !           708: }
        !           709: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.