Annotation of 43BSDReno/contrib/isode-beta/others/X/server/io.c, revision 1.1.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.