Annotation of 43BSDReno/contrib/isode-beta/others/X/server/connection.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: connection.c,v 1.88 88/10/22 22:06:31 keith Exp $ */
        !            25: /*****************************************************************
        !            26:  *  Stuff to create connections --- OS dependent
        !            27:  *
        !            28:  *      EstablishNewConnections, CreateWellKnownSockets, ResetWellKnownSockets,
        !            29:  *      CloseDownConnection, CheckConnections, AddEnabledDevice,
        !            30:  *     RemoveEnabledDevice, OnlyListToOneClient,
        !            31:  *      ListenToAllClients,
        !            32:  *
        !            33:  *      (WaitForSomething is in its own file)
        !            34:  *
        !            35:  *      In this implementation, a client socket table is not kept.
        !            36:  *      Instead, what would be the index into the table is just the
        !            37:  *      file descriptor of the socket.  This won't work for if the
        !            38:  *      socket ids aren't small nums (0 - 2^8)
        !            39:  *
        !            40:  *****************************************************************/
        !            41: 
        !            42: #ifdef ISOCONN
        !            43: #include <math.h>
        !            44: #endif /* ISOCONN */
        !            45: 
        !            46: #include <dbm.h>
        !            47: #undef NULL
        !            48: #include "X.h"
        !            49: #include "Xproto.h"
        !            50: #include <sys/param.h>
        !            51: #include <errno.h>
        !            52: #include "Xos.h"                       /* for strings, file, time */
        !            53: #include <sys/socket.h>
        !            54: 
        !            55: #include <signal.h>
        !            56: #include <fcntl.h>
        !            57: #include <setjmp.h>
        !            58: 
        !            59: #ifdef hpux
        !            60: #include <sys/ioctl.h>
        !            61: #endif
        !            62: 
        !            63: #ifdef TCPCONN
        !            64: #include <netinet/in.h>
        !            65: #ifndef hpux
        !            66: #include <netinet/tcp.h>
        !            67: #endif
        !            68: #endif
        !            69: 
        !            70: #ifdef UNIXCONN
        !            71: /*
        !            72:  * sites should be careful to have separate /tmp directories for diskless nodes
        !            73:  */
        !            74: #include <sys/un.h>
        !            75: #include <sys/stat.h>
        !            76: static int unixDomainConnection = -1;
        !            77: #endif
        !            78: 
        !            79: #include <stdio.h>
        !            80: #include <sys/uio.h>
        !            81: #include "osstruct.h"
        !            82: #include "osdep.h"
        !            83: #include "opaque.h"
        !            84: #include "dixstruct.h"
        !            85: 
        !            86: #ifdef DNETCONN
        !            87: #include <netdnet/dn.h>
        !            88: #endif /* DNETCONN */
        !            89: 
        !            90: #ifdef ISOCONN
        !            91: #include <isode/psap.h>
        !            92: #include <isode/tsap.h>
        !            93: #include <isode/isoservent.h>
        !            94: 
        !            95: extern char *isodetcpath; 
        !            96: 
        !            97: #ifdef ISODEBUG
        !            98: /*
        !            99:  * Set to true for loads of TSAP messages...
        !           100:  */
        !           101: int isodexbug = FALSE;
        !           102: #endif /* ISODEBUG */
        !           103: 
        !           104: /*
        !           105:  * array of fd 2 family map so we can lookup right function below...
        !           106:  * Its initialised at connection setup...
        !           107:  */
        !           108: int fd2family[MAXSOCKS];
        !           109: /*
        !           110:  * Globals for storing functions appropos each fd/socket type
        !           111:  * UNIX_IO (0) map to sys calls
        !           112:  * ISODE_IO (1) maps to my fns...
        !           113:  */
        !           114: 
        !           115: extern int accept(), TAcceptFromClient();
        !           116: int (*acceptfn[])() =
        !           117: {
        !           118:        accept, TAcceptFromClient
        !           119: };
        !           120: extern getpeername(), getISOpeername();
        !           121: int (*getpeerfn[])() =
        !           122: {
        !           123:        getpeername, getISOpeername
        !           124: };
        !           125: /*
        !           126:  * Note yuckiness here XXX
        !           127:  * TReadFromClient takes one more param than read - must fix...
        !           128:  */
        !           129: extern int read(), TReadFromClient();
        !           130: int (*readfn[])() = 
        !           131: {
        !           132:        read, TReadFromClient
        !           133: };
        !           134: extern int write(), TWriteToClient();
        !           135: int (*writefn[])() =
        !           136: {
        !           137:        write, TWriteToClient
        !           138: };
        !           139: extern writev(), TWritevToClient();
        !           140: int (*writevfn[])() =
        !           141: {
        !           142:        writev, TWritevToClient
        !           143: };
        !           144: extern int close(), TDiscFromClient();
        !           145: int (*closefn[])() =
        !           146: {
        !           147:        close, TDiscFromClient
        !           148: };
        !           149: 
        !           150: #endif /* ISOCONN */
        !           151: 
        !           152: typedef long CCID;      /* mask of indices into client socket table */
        !           153: 
        !           154: #ifndef X_UNIX_PATH
        !           155: #define X_UNIX_DIR     "/tmp/.X11-unix"
        !           156: #define X_UNIX_PATH    "/tmp/.X11-unix/X"
        !           157: #endif
        !           158: 
        !           159: #ifdef ISOCONN
        !           160: char *display = NULLCP;                        /* The display number */
        !           161: #else /* ISOCONN */
        !           162: char *display;                 /* The display number */
        !           163: #endif /* ISOCONN */
        !           164: int lastfdesc;                 /* maximum file descriptor */
        !           165: 
        !           166: long WellKnownConnections;     /* Listener mask */
        !           167: long EnabledDevices;           /* mask for input devices that are on */
        !           168: long AllSockets[mskcnt];       /* select on this */
        !           169: long AllClients[mskcnt];       /* available clients */
        !           170: long LastSelectMask[mskcnt];   /* mask returned from last select call */
        !           171: long ClientsWithInput[mskcnt]; /* clients with FULL requests in buffer */
        !           172: long ClientsWriteBlocked[mskcnt];/* clients who cannot receive output */
        !           173: long OutputPending[mskcnt];    /* clients with reply/event data ready to go */
        !           174: long MaxClients = MAXSOCKS ;
        !           175: long OutputBufferSize = BUFSIZ; /* output buffer size (must be > 0) */
        !           176: long NConnBitArrays = mskcnt;
        !           177: long FirstClient;
        !           178: Bool NewOutputPending;         /* not yet attempted to write some new output */
        !           179: Bool AnyClientsWriteBlocked;   /* true if some client blocked on write */
        !           180: 
        !           181: static Bool debug_conns = FALSE;
        !           182: 
        !           183: static char whichByteIsFirst;
        !           184: 
        !           185: static int SavedAllClients[mskcnt];
        !           186: static int SavedAllSockets[mskcnt];
        !           187: static int SavedClientsWithInput[mskcnt];
        !           188: static Bool GrabDone = FALSE;
        !           189: 
        !           190: ClientPtr ConnectionTranslation[MAXSOCKS];
        !           191: extern ClientPtr NextAvailableClient();
        !           192: 
        !           193: extern ConnectionInput inputBuffers[];
        !           194: 
        !           195: int swappedClients[MAXSOCKS];
        !           196: 
        !           197: extern int AutoResetServer();
        !           198: extern int GiveUp();
        !           199: 
        !           200: #ifdef UNIXCONN
        !           201: 
        !           202: static struct sockaddr_un unsock;
        !           203: 
        !           204: static int open_unix_socket ()
        !           205: {
        !           206:     int oldUmask;
        !           207:     int request;
        !           208: 
        !           209:     unsock.sun_family = AF_UNIX;
        !           210:     oldUmask = umask (0);
        !           211: #ifdef X_UNIX_DIR
        !           212:     mkdir (X_UNIX_DIR, 0777);
        !           213: #endif
        !           214:     strcpy (unsock.sun_path, X_UNIX_PATH);
        !           215:     strcat (unsock.sun_path, display);
        !           216:     unlink (unsock.sun_path);
        !           217:     if ((request = socket (AF_UNIX, SOCK_STREAM, 0)) < 0) 
        !           218:     {
        !           219:        Notice ("Creating Unix socket");
        !           220:     } 
        !           221:     else 
        !           222:     {
        !           223:        if(bind(request,(struct sockaddr *)&unsock, strlen(unsock.sun_path)+2))
        !           224:            Error ("Binding Unix socket");
        !           225:        if (listen (request, 5)) Error ("Unix Listening");
        !           226:     }
        !           227:     (void)umask(oldUmask);
        !           228:     return request;
        !           229: }
        !           230: #endif /*UNIXCONN */
        !           231: 
        !           232: /*****************
        !           233:  * CreateWellKnownSockets
        !           234:  *    At initialization, create the sockets to listen on for new clients.
        !           235:  *    There are potentially 4: DECnet, UNIX Domain, TCP-IP with MSB first, 
        !           236:  *    with TCP-IP with LSB first.
        !           237:  *****************/
        !           238: 
        !           239: void
        !           240: CreateWellKnownSockets()
        !           241: {
        !           242:     int                request, i;
        !           243:     int                whichbyte;          /* used to figure out whether this is
        !           244:                                         LSB or MSB */
        !           245: #ifdef TCPCONN
        !           246:     struct sockaddr_in insock;
        !           247:     int                tcpportReg;         /* port with same byte order as server */
        !           248: 
        !           249: #ifdef SO_LINGER
        !           250:     static int linger[2] = { 0, 0 };
        !           251: #endif /* SO_LINGER */
        !           252: 
        !           253: #endif /* TCPCONN */
        !           254: 
        !           255: #ifdef DNETCONN
        !           256:     struct sockaddr_dn dnsock;
        !           257: #endif /* DNETCONN */
        !           258: 
        !           259: #ifdef ISOCONN
        !           260:     struct TSAPdisconnect tds;
        !           261:     struct TSAPdisconnect *td = &tds;
        !           262:     struct TSAPaddr tas;
        !           263:     struct TSAPaddr *ta = &tas;
        !           264:     struct PSAPaddr *pa;
        !           265:     AEI   aei;
        !           266: #endif /* ISOCONN */
        !           267:     int retry;
        !           268: 
        !           269: #ifdef ISOCONN
        !           270: #ifdef ISODEBUG
        !           271:     isodetcpath = ISODEPATH;
        !           272: #endif
        !           273: #endif /* ISOCONN */
        !           274: 
        !           275:     CLEARBITS(AllSockets);
        !           276:     CLEARBITS(AllClients);
        !           277:     CLEARBITS(LastSelectMask);
        !           278:     CLEARBITS(ClientsWithInput);
        !           279: 
        !           280:     for (i=0; i<MAXSOCKS; i++) ConnectionTranslation[i] = (ClientPtr)NULL;
        !           281:     
        !           282: #ifdef hpux
        !           283:        lastfdesc = _NFILE - 1;
        !           284: #else
        !           285:        lastfdesc = getdtablesize() - 1;
        !           286: #endif /* hpux */
        !           287: 
        !           288:     if (lastfdesc > MAXSOCKS)
        !           289:     {
        !           290:        lastfdesc = MAXSOCKS;
        !           291:        if (debug_conns)
        !           292:            ErrorF( "GOT TO END OF SOCKETS %d\n", MAXSOCKS);
        !           293:     }
        !           294: 
        !           295:     WellKnownConnections = 0;
        !           296:     whichbyte = 1;
        !           297:     
        !           298:     if (*(char *) &whichbyte)
        !           299:         whichByteIsFirst = 'l';
        !           300:     else
        !           301:         whichByteIsFirst = 'B';
        !           302: 
        !           303: 
        !           304: #ifdef TCPCONN
        !           305: 
        !           306:     tcpportReg = atoi (display); 
        !           307:     tcpportReg += X_TCP_PORT;
        !           308: 
        !           309:     if ((request = socket (AF_INET, SOCK_STREAM, 0)) < 0) 
        !           310:     {
        !           311:        Notice ("Creating TCP socket");
        !           312:     } 
        !           313:     else 
        !           314:     {
        !           315:        bzero ((char *)&insock, sizeof (insock));
        !           316:        insock.sin_family = AF_INET;
        !           317:        insock.sin_port = htons (tcpportReg);
        !           318:        insock.sin_addr.s_addr = htonl(INADDR_ANY);
        !           319:        retry = 20;
        !           320:        while (i = bind(request, (struct sockaddr *) &insock, sizeof (insock))) 
        !           321:        {
        !           322: #ifdef hpux
        !           323:            /* Necesary to restart the server without a reboot */
        !           324:            if (errno == EADDRINUSE)
        !           325:                set_socket_option (request, SO_REUSEADDR);
        !           326:            if (--retry == 0)
        !           327:                Error ("Binding TCP socket");
        !           328:            sleep (1);
        !           329: #else
        !           330:            if (--retry == 0)
        !           331:                Error ("Binding MSB TCP socket");
        !           332:            sleep (10);
        !           333: #endif /* hpux */
        !           334:        }
        !           335: #ifdef hpux
        !           336:        /* return the socket option to the original */
        !           337:        if (errno)
        !           338:            unset_socket_option (request, SO_REUSEADDR);
        !           339: #endif /* hpux */
        !           340: #ifdef SO_LINGER
        !           341:        if(setsockopt (request, SOL_SOCKET, SO_LINGER,
        !           342:                       (char *)linger, sizeof(linger)))
        !           343:            Notice ("Setting TCP SO_LINGER\n");
        !           344: #endif /* SO_LINGER */
        !           345:        if (listen (request, 5))
        !           346:            Error ("Reg TCP Listening");
        !           347:        WellKnownConnections |= (1 << request);
        !           348:        DefineSelf (request);
        !           349: #ifdef ISOCONN
        !           350:        fd2family[request] = UNIX_IO;
        !           351: #endif /* ISOCONN */
        !           352:     }
        !           353: 
        !           354: #endif /* TCPCONN */
        !           355: 
        !           356: #ifdef UNIXCONN
        !           357:     if ((request = open_unix_socket ()) != -1) {
        !           358:        WellKnownConnections |= (1L << request);
        !           359:        unixDomainConnection = request;
        !           360: #ifdef ISOCONN
        !           361:     fd2family[request] = UNIX_IO;
        !           362: #endif /* ISOCONN */
        !           363:     }
        !           364: #endif /*UNIXCONN */
        !           365: 
        !           366: #ifdef DNETCONN
        !           367:     if ((request = socket (AF_DECnet, SOCK_STREAM, 0)) < 0) 
        !           368:     {
        !           369:        Notice ("Creating DECnet socket");
        !           370:     } 
        !           371:     else 
        !           372:     {
        !           373:        bzero ((char *)&dnsock, sizeof (dnsock));
        !           374:        dnsock.sdn_family = AF_DECnet;
        !           375:        sprintf(dnsock.sdn_objname, "X$X%d", atoi (display));
        !           376:        dnsock.sdn_objnamel = strlen(dnsock.sdn_objname);
        !           377:        if (bind (request, (struct sockaddr *) &dnsock, sizeof (dnsock)))
        !           378:                Error ("Binding DECnet socket");
        !           379:        if (listen (request, 5)) Error ("DECnet Listening");
        !           380:        WellKnownConnections |= (1 << request);
        !           381:        DefineSelf (request);
        !           382: #ifdef ISOCONN
        !           383:     fd2family[request] = UNIX_IO;
        !           384: #endif /* ISOCONN */
        !           385:     }
        !           386: #endif /* DNETCONN */
        !           387: #ifdef ISOCONN
        !           388: /*
        !           389:  * If display is set, its the string after the Colon:
        !           390:  * i.e. X0 or X1 or T0 or T1...
        !           391:  */
        !           392:     if ((display == NULLCP) || (atoi(display) == 0))
        !           393:        aei = str2aei(TLocalHostName(), DEFAULTTSERVICE);
        !           394:     else
        !           395:        aei = str2aei(TLocalHostName(), display);
        !           396: 
        !           397:     if (aei == NULLAEI) {
        !           398:        ErrorF("No AEI for me:");
        !           399:        FatalError(TLocalHostName());
        !           400:     }
        !           401: 
        !           402: /*
        !           403:  * This hack only works if the PSAPaddr and SSAP addrsd are null!!
        !           404:  */
        !           405:      if ((pa = aei2addr (aei)) == NULLPA) 
        !           406:        FatalError("address translation failed");
        !           407: 
        !           408:     ta = (struct TSAPaddr *)&(pa->pa_addr.sa_addr);
        !           409: 
        !           410: /*
        !           411:  * Just put out a listen for now
        !           412:  */
        !           413:     if ((request = TNetListen(ta, td)) != OK) {
        !           414:        Error(TErrString(td->td_reason));
        !           415:        FatalError("TNetListen");
        !           416:     }
        !           417: 
        !           418:     WellKnownConnections |= (1 << request);
        !           419:     DefineSelf (request);
        !           420:     fd2family[request] = ISODE_IO;
        !           421: #endif /*  ISOCONN */
        !           422:     if (WellKnownConnections == 0)
        !           423:         Error ("No Listeners, nothing to do");
        !           424:     signal (SIGPIPE, SIG_IGN);
        !           425:     signal (SIGHUP, AutoResetServer);
        !           426:     signal (SIGINT, GiveUp);
        !           427:     signal (SIGTERM, GiveUp);
        !           428:     FirstClient = request + 1;
        !           429:     AllSockets[0] = WellKnownConnections;
        !           430:     ResetHosts(display);
        !           431: 
        !           432:     for (i=0; i<MaxClients; i++)
        !           433:     {
        !           434:        inputBuffers[i].buffer = (char *) NULL;
        !           435:        inputBuffers[i].bufptr = (char *) NULL;
        !           436:        inputBuffers[i].bufcnt = 0;
        !           437:        inputBuffers[i].lenLastReq = 0;
        !           438:        inputBuffers[i].size = 0;
        !           439:     }
        !           440: }
        !           441: 
        !           442: void
        !           443: ResetWellKnownSockets ()
        !           444: {
        !           445: #ifdef UNIXCONN
        !           446:     if (unixDomainConnection != -1)
        !           447:     {
        !           448:        /*
        !           449:         * see if the unix domain socket has disappeared
        !           450:         */
        !           451:        struct stat     statb;
        !           452: 
        !           453:        if (stat (unsock.sun_path, &statb) == -1 ||
        !           454:            (statb.st_mode & S_IFMT) != S_IFSOCK)
        !           455:        {
        !           456:            ErrorF ("Unix domain socket %s trashed, recreating\n",
        !           457:                unsock.sun_path);
        !           458:            (void) unlink (unsock.sun_path);
        !           459:            (void) close (unixDomainConnection);
        !           460:            WellKnownConnections &= ~(1L << unixDomainConnection);
        !           461:            unixDomainConnection = open_unix_socket ();
        !           462:            if (unixDomainConnection != -1)
        !           463:                WellKnownConnections |= (1L << unixDomainConnection);
        !           464:        }
        !           465:     }
        !           466: #endif /* UNIXCONN */
        !           467: }
        !           468: 
        !           469: #ifdef ISOCONN
        !           470: /*
        !           471:  * Convenience routine...
        !           472:  * client = transport descriptor
        !           473:  * data, size = buffer
        !           474:  * nonblock = NOTOK, blocks, OK, non blocks
        !           475:  */
        !           476: TReadFromClient(client, data, size, nonblock)
        !           477: int client, size, nonblock;
        !           478: char *data;
        !           479: {
        !           480:        struct TSAPdisconnect tds;
        !           481:        struct TSAPdisconnect *td = &tds;
        !           482:        int ret;
        !           483: static struct TSAPdata txs;
        !           484: static struct TSAPdata *tx = &txs;
        !           485:        char *aptr; 
        !           486: static struct qbuf *qb;
        !           487: static char *qptr;
        !           488: static int ingot, qcpy, result = 0;
        !           489:        int q2data;
        !           490: 
        !           491: #ifdef ISODEBUG
        !           492:        if (isodexbug) {
        !           493:                fprintf(stderr, "TReadFromClient %d want %d (%d buffered)\n", 
        !           494:                        client, size, result);
        !           495:        }
        !           496: #endif /* ISODEBUG */
        !           497:        if (result == 0) {
        !           498:                if ((ret = TReadRequest(client, tx, nonblock, td)) == NOTOK) {
        !           499: #ifdef ISODEBUG
        !           500:                    if(errno == EWOULDBLOCK ) {
        !           501:                        fprintf(stderr, "Server TReadReq: would block %s\n",
        !           502:                                TErrString(td->td_reason));
        !           503:                        if (!DR_FATAL(td->td_reason))
        !           504:                                errno = EWOULDBLOCK;
        !           505:                        else
        !           506:                                errno = EBADF;
        !           507:                        return ret;
        !           508:                    } 
        !           509:                    if (isodexbug)
        !           510:                            fprintf(stderr, "Server TReadReq: %s\n", 
        !           511:                                TErrString(td->td_reason));
        !           512: #endif /* ISODEBUG */
        !           513: /*
        !           514:  * map problems here - eg TimeOut...
        !           515:  */
        !           516:                    if (td->td_reason == DR_TIMER)
        !           517:                        errno = EWOULDBLOCK;
        !           518:                    return ret;
        !           519:                }
        !           520:                result = tx->tx_cc;
        !           521:                qb = &(tx->tx_qbuf);
        !           522:                qptr = qb->qb_data;
        !           523: #ifdef ISODEBUG
        !           524:                if (isodexbug)
        !           525:                        fprintf(stderr, "TReadRequest want %d got %d\n", 
        !           526:                                size, result);
        !           527: #endif
        !           528:        } 
        !           529: #ifdef ISODEBUG
        !           530:        else {
        !           531:                if (isodexbug)
        !           532:                        fprintf(stderr, "TReadFromClient want %d buffered %d\n",
        !           533:                                 size, result);
        !           534:        }
        !           535: #endif
        !           536: /*
        !           537:  * Buffer it
        !           538:  */
        !           539:         ingot = 0;
        !           540:         aptr = data;
        !           541:        for(ingot = 0, aptr = data, q2data = min(size, result); 
        !           542:                ingot<q2data;
        !           543:                aptr += qcpy, ingot+= qcpy) {
        !           544:            int aleft = q2data - ingot;
        !           545:            if (qb->qb_len > aleft) {
        !           546:                    qcpy = aleft;
        !           547:                    bcopy(qptr, aptr, qcpy);
        !           548:                    qptr += aleft;
        !           549:            } else {
        !           550:                    qcpy = qb->qb_len;
        !           551:                    bcopy(qb->qb_data, aptr, qcpy);
        !           552:                    if ((qb = qb->qb_forw) == NULL)
        !           553:                        break;
        !           554:                    qptr = qb->qb_data;
        !           555:            }
        !           556:         }
        !           557:        if ((result -= ingot) <= 0) {
        !           558:                result = 0;
        !           559:                TXFREE(tx);
        !           560:        }
        !           561:        return ingot;
        !           562: }
        !           563: 
        !           564: #endif /* ISOCONN */
        !           565: 
        !           566: /* We want to read the connection information.  If the client doesn't
        !           567:  * send us enough data, however, we want to time out eventually.
        !           568:  * The scheme is to clear a flag, set an alarm, and keep doing non-blocking
        !           569:  * reads until we get all the data we want. If the alarm goes
        !           570:  * off, the handler will clear the flag.  If we see that the flag is
        !           571:  * cleared, we know we've timed out and return with an error.
        !           572:  *
        !           573:  * there remains one problem with this code:
        !           574:  * there is a window of vulnerability in which we might get an alarm
        !           575:  * even though all the data has come in properly.  This is because I
        !           576:  * can't atomically clear the alarm.
        !           577:  * 
        !           578:  * Anyone who sees how to fix this problem should do so and
        !           579:  * submit a fix.
        !           580:  */
        !           581: 
        !           582: jmp_buf        env;
        !           583: void TimeOut()
        !           584: {
        !           585:     longjmp(env, 1);
        !           586: }
        !           587: static Bool 
        !           588: ReadBuffer(conn, buffer, charsWanted)
        !           589:     long conn;
        !           590:     char *buffer;
        !           591:     int charsWanted;
        !           592: {
        !           593:     char *bptr = buffer;
        !           594:     int got, fTimeOut;
        !           595:     struct itimerval   itv;
        !           596: 
        !           597:     signal(SIGALRM, TimeOut);
        !           598:     fTimeOut = FALSE;
        !           599:     /* only 1 alarm, please, not 1 per minute */
        !           600:     timerclear(&itv.it_interval);
        !           601:     itv.it_value.tv_sec = TimeOutValue;
        !           602:     itv.it_value.tv_usec = 0;
        !           603:     setitimer(ITIMER_REAL, &itv, (struct itimerval *)NULL);
        !           604:     /* It better not take a full minute to get to the read call */
        !           605: 
        !           606:     while (charsWanted && (fTimeOut = setjmp(env)) == FALSE)
        !           607:     {
        !           608: #ifdef ISOCONN
        !           609:        got = SRead(conn, bptr, charsWanted, NOTOK);
        !           610: #else /* ISOCONN */
        !           611:        got = read(conn, bptr, charsWanted);    
        !           612: #endif /* ISOCONN */
        !           613:        if (got <= 0)
        !           614:            return FALSE;
        !           615:        if(got > 0)
        !           616:        {
        !           617:            charsWanted -= got;
        !           618:            bptr += got;
        !           619:            /* Ok, we got something, reset the timer */
        !           620:            itv.it_value.tv_sec = TimeOutValue;
        !           621:             itv.it_value.tv_usec = 0;
        !           622:            setitimer(ITIMER_REAL, &itv, (struct itimerval *)NULL);
        !           623:        }
        !           624:     }
        !           625:     /* disable the timer */
        !           626:     timerclear(&itv.it_value);
        !           627:     setitimer(ITIMER_REAL, &itv, (struct itimerval *)NULL);
        !           628:     /* If we got here and we didn't time out, then return TRUE, because
        !           629:      * we must have read what we wanted. If we timed out, return FALSE */
        !           630:     if(fTimeOut && debug_conns)
        !           631:        ErrorF("Timed out on connection %d\n", conn);
        !           632:     return (!fTimeOut);
        !           633: }
        !           634: 
        !           635: #ifdef ISOCONN
        !           636: /*
        !           637:  * Who's calling us?
        !           638:  */
        !           639: getISOpeername (conn, from, alen) 
        !           640: int conn;
        !           641: struct TSAPaddr *from;
        !           642: int *alen;
        !           643: {
        !           644:        struct TSAPdisconnect td;
        !           645:        if (TGetAddresses (conn, from, NULLTA, &td) == NOTOK) {
        !           646:                Error(TErrString(td.td_reason));
        !           647:                return TRUE;
        !           648:        };
        !           649:        *alen = sizeof(struct TSAPaddr);
        !           650:        return FALSE;
        !           651: }
        !           652: #endif /* ISOCONN */
        !           653: /*****************************************************************
        !           654:  * ClientAuthorized
        !           655:  *
        !           656:  *    Sent by the client at connection setup:
        !           657:  *                typedef struct _xConnClientPrefix {
        !           658:  *                   CARD8     byteOrder;
        !           659:  *                   BYTE      pad;
        !           660:  *                   CARD16    majorVersion, minorVersion;
        !           661:  *                   CARD16    nbytesAuthProto;    
        !           662:  *                   CARD16    nbytesAuthString;   
        !           663:  *                 } xConnClientPrefix;
        !           664:  *
        !           665:  *             It is hoped that eventually one protocol will be agreed upon.  In the
        !           666:  *        mean time, a server that implements a different protocol than the
        !           667:  *        client expects, or a server that only implements the host-based
        !           668:  *        mechanism, will simply ignore this information.
        !           669:  *
        !           670:  *****************************************************************/
        !           671: 
        !           672: int 
        !           673: ClientAuthorized(conn, pswapped, reason)
        !           674:     long conn;
        !           675:     int  *pswapped;
        !           676:     char **reason;   /* if authorization fails, put reason in here */
        !           677: {
        !           678:     short slen;
        !           679:     union {
        !           680:        struct sockaddr sa;
        !           681: #ifdef UNIXCONN
        !           682:        struct sockaddr_un un;
        !           683: #endif /* UNIXCONN */
        !           684: #ifdef TCPCONN
        !           685:        struct sockaddr_in in;
        !           686: #endif /* TCPCONN */
        !           687: #ifdef DNETCONN
        !           688:        struct sockaddr_dn dn;
        !           689: #endif /* DNETCONN */
        !           690: #ifdef ISOCONN
        !           691:        struct TSAPaddr ts;
        !           692: #endif /* ISOCONN */
        !           693:     } from;
        !           694:     int        fromlen;
        !           695:     xConnClientPrefix xccp;
        !           696:     char auth_proto[100];
        !           697:     char auth_string[100];
        !           698: 
        !           699: #ifdef ISOCONN
        !           700: /*
        !           701:  * For now we always auth an ISO client!!
        !           702:  * should use directory etc etc
        !           703:  */
        !           704:     *reason = 0;
        !           705: #endif /* ISOCONN */
        !           706:     if (!ReadBuffer(conn, (char *)&xccp, sizeof(xConnClientPrefix)))
        !           707:     {
        !           708:        /* If they can't even give us this much, just blow them off
        !           709:         * without an error message */
        !           710:        *reason = 0;
        !           711:         return 0;
        !           712:     }
        !           713:     if (xccp.byteOrder != whichByteIsFirst)
        !           714:     {        
        !           715:        SwapConnClientPrefix(&xccp);
        !           716:        *pswapped = TRUE;
        !           717:     }
        !           718:     else
        !           719:         *pswapped = FALSE;
        !           720:     if ((xccp.majorVersion != X_PROTOCOL) ||
        !           721:        (xccp.minorVersion != X_PROTOCOL_REVISION))
        !           722:     {        
        !           723: #define STR "Protocol version mismatch"
        !           724:         *reason = (char *)xalloc(sizeof(STR));
        !           725:         strcpy(*reason, STR);
        !           726:        if (debug_conns)
        !           727:            ErrorF("%s\n", STR);
        !           728: #undef STR
        !           729:         return 0;
        !           730:     }
        !           731:     fromlen = sizeof (from);
        !           732: #ifdef ISOCONN
        !           733:     if (SGetPeerName (conn, &(from.ts), &fromlen) ||
        !           734:         InvalidHost (&(from.ts), fromlen)) 
        !           735: #else /* ISOCONN */
        !           736:     if (getpeername (conn, &from.sa, &fromlen) ||
        !           737:         InvalidHost (&from.sa, fromlen)) 
        !           738: #endif /* ISOCONN */
        !           739:     {
        !           740: #define STR "Server is not authorized to connect to host"      
        !           741:         *reason = (char *)xalloc(sizeof(STR));
        !           742:         strcpy(*reason, STR);
        !           743: #undef STR
        !           744:         return 0;
        !           745:     }
        !           746:     
        !           747:    slen = (xccp.nbytesAuthProto + 3) & ~3;  
        !           748:     if ( slen )
        !           749:         if (!ReadBuffer(conn, auth_proto, slen))
        !           750:         {
        !           751: #define STR "Length error in xConnClientPrefix for protocol authorization "
        !           752:             *reason = (char *)xalloc(sizeof(STR));
        !           753:             strcpy(*reason, STR);
        !           754:             return 0;
        !           755: #undef STR
        !           756:        }
        !           757:     auth_proto[slen] = '\0';
        !           758: 
        !           759:     slen = (xccp.nbytesAuthString + 3) & ~3;   
        !           760:     if ( slen)
        !           761:         if (!ReadBuffer(conn, auth_string, slen))
        !           762:         {
        !           763: #define STR "Length error in xConnClientPrefix for protocol string"
        !           764:             *reason = (char *)xalloc(sizeof(STR));
        !           765:             strcpy(*reason, STR);
        !           766:             return 0;
        !           767: #undef STR
        !           768:        }
        !           769:     auth_string[slen] = '\0';
        !           770: 
        !           771:     /* At this point, if the client is authorized to change the access control
        !           772:      * list, we should getpeername() information, and add the client to
        !           773:      * the selfhosts list.  It's not really the host machine, but the
        !           774:      * true purpose of the selfhosts list is to see who may change the
        !           775:      * access control list.
        !           776:      */
        !           777:     return(1);
        !           778: }    
        !           779: 
        !           780: static int padlength[4] = {0, 3, 2, 1};
        !           781: 
        !           782: /*****************
        !           783:  * EstablishNewConnections
        !           784:  *    If anyone is waiting on listened sockets, accept them.
        !           785:  *    Returns a mask with indices of new clients.  Updates AllClients
        !           786:  *    and AllSockets.
        !           787:  *****************/
        !           788: 
        !           789: void
        !           790: #ifdef ISOCONN
        !           791: EstablishNewConnections(newclients, nnew, vecp, vec)
        !           792:     ClientPtr          *newclients;
        !           793:     int                *nnew;
        !           794:     int                        vecp;
        !           795:     char               **vec;
        !           796: #else /* ISOCONN */
        !           797: EstablishNewConnections(newclients, nnew)
        !           798:     ClientPtr          *newclients;
        !           799:     int                *nnew;
        !           800: #endif /* ISOCONN */
        !           801: {
        !           802:     long readyconnections;     /* mask of listeners that are ready */
        !           803:     long curconn;                  /* fd of listener that's ready */
        !           804:     long newconn;                  /* fd of new client */
        !           805:     int         swapped;               /* set by ClientAuthorized if connection is
        !           806:                                 * swapped */
        !           807:     char *reason;
        !           808:     struct iovec iov[2];
        !           809: #ifdef ISOCONN
        !           810:     struct udvec uv[3];
        !           811:     struct TSAPdisconnect tds;
        !           812:     struct TSAPdisconnect *td = &tds;
        !           813:     struct TSAPstart tsts;
        !           814:     struct TSAPstart *tst = &tsts;
        !           815: #endif /* ISOCONN */
        !           816:     char p[3];
        !           817: 
        !           818: #ifdef TCP_NODELAY
        !           819:     union {
        !           820:        struct sockaddr sa;
        !           821: #ifdef UNIXCONN
        !           822:        struct sockaddr_un un;
        !           823: #endif /* UNIXCONN */
        !           824: #ifdef TCPCONN
        !           825:        struct sockaddr_in in;
        !           826: #endif /* TCPCONN */
        !           827: #ifdef DNETCONN
        !           828:        struct sockaddr_dn dn;
        !           829: #endif /* DNETCONN */
        !           830:     } from;
        !           831:     int        fromlen;
        !           832: #endif TCP_NODELAY
        !           833: 
        !           834:     *nnew = 0;
        !           835:     if (readyconnections = (LastSelectMask[0] & WellKnownConnections)) 
        !           836:     {
        !           837:        while (readyconnections) 
        !           838:        {
        !           839:            curconn = ffs (readyconnections) - 1;
        !           840: #ifdef ISOCONN 
        !           841: /*
        !           842:  * At this point, a TAccept has finished with a vec > 0
        !           843:  * so we need to init them...
        !           844:  */
        !           845:            if ((newconn = SAccept(curconn, vecp, vec)) >= 0)
        !           846:            {
        !           847:                fd2family[newconn] = ISODE_IO;
        !           848: #else /* ISOCONN */
        !           849:            if ((newconn = accept (curconn,
        !           850:                                  (struct sockaddr *) NULL, 
        !           851:                                  (int *)NULL)) >= 0) 
        !           852:            {
        !           853:                fd2family[newconn] = UNIX_IO;
        !           854: #endif /* ISOCONN */
        !           855:                if (newconn >= lastfdesc)
        !           856:                {
        !           857:                    if (debug_conns)
        !           858: ErrorF("Didn't make connection: Out of file descriptors for connections\n");
        !           859: #ifdef ISOCONN
        !           860:                    SClose(newconn);
        !           861: #else /* ISOCONN */
        !           862:                    close (newconn);
        !           863: #endif /* ISOCONN */
        !           864:                } 
        !           865:                else 
        !           866:                {
        !           867:                    ClientPtr next = (ClientPtr)NULL;
        !           868: 
        !           869: #ifdef TCP_NODELAY
        !           870: #ifdef ISOCONN
        !           871:                    if (fd2family(newconn) == UNIX_IO) 
        !           872:                    {
        !           873: #endif /* ISOCONN */
        !           874:                    fromlen = sizeof (from);
        !           875:                     if (!getpeername (newconn, &from.sa, &fromlen))
        !           876:                    {
        !           877:                        if (fromlen && (from.sa.sa_family == AF_INET)) 
        !           878:                        {
        !           879:                            int mi = 1;
        !           880:                            setsockopt (newconn, IPPROTO_TCP, TCP_NODELAY,
        !           881:                                       (char *)&mi, sizeof (int));
        !           882:                        }
        !           883:                    }
        !           884: #ifdef ISOCONN
        !           885:                    }
        !           886: #endif /* ISOCONN */
        !           887: #endif /* TCP_NODELAY */
        !           888:                    if (ClientAuthorized(newconn, &swapped, &reason))
        !           889:                    {
        !           890: #ifdef hpux
        !           891:                        /*
        !           892:                         * HPUX does not have  FNDELAY
        !           893:                         */
        !           894:                        {
        !           895:                            int arg;
        !           896:                            arg = 1;
        !           897:                            ioctl(newconn, FIOSNBIO, &arg);
        !           898:                        }
        !           899: #else
        !           900:                        fcntl (newconn, F_SETFL, FNDELAY);
        !           901: #endif /* hpux */
        !           902:                        inputBuffers[newconn].used = 1; 
        !           903:                         if (! inputBuffers[newconn].size) 
        !           904:                        {
        !           905:                            inputBuffers[newconn].buffer = 
        !           906:                                        (char *)xalloc(BUFSIZE);
        !           907:                            inputBuffers[newconn].size = BUFSIZE;
        !           908:                            inputBuffers[newconn].bufptr =      
        !           909:                                        inputBuffers[newconn].buffer;
        !           910:                        }
        !           911:                        if (GrabDone)
        !           912:                        {
        !           913:                            BITSET(SavedAllClients, newconn);
        !           914:                            BITSET(SavedAllSockets, newconn);
        !           915:                        }
        !           916:                        else
        !           917:                        {
        !           918:                            BITSET(AllClients, newconn);
        !           919:                            BITSET(AllSockets, newconn);
        !           920:                        }
        !           921:                        next = NextAvailableClient();
        !           922:                        if (next != (ClientPtr)NULL)
        !           923:                        {
        !           924:                           OsCommPtr priv;
        !           925: 
        !           926:                           newclients[(*nnew)++] = next;
        !           927:                           next->swapped = swapped;
        !           928:                           ConnectionTranslation[newconn] = next;
        !           929:                           priv =  (OsCommPtr)xalloc(sizeof(OsCommRec));
        !           930:                           priv->fd = newconn;
        !           931:                           priv->buf = (unsigned char *)
        !           932:                                        xalloc(OutputBufferSize);
        !           933:                           priv->bufsize = OutputBufferSize;
        !           934:                           priv->count = 0;
        !           935:                           next->osPrivate = (pointer)priv;
        !           936:                        }
        !           937:                        else
        !           938:                        {
        !           939: #define STR "Maximum number of clients exceeded"
        !           940:                           reason = (char *)xalloc(sizeof(STR));
        !           941:                           strcpy(reason, STR);
        !           942: #undef STR
        !           943:                        }
        !           944:                    }
        !           945:                    if (next == (ClientPtr)NULL)
        !           946:                    {
        !           947:                        xConnSetupPrefix c;
        !           948: 
        !           949:                        if(reason)
        !           950:                        {
        !           951:                            c.success = xFalse;
        !           952:                            c.lengthReason = strlen(reason);
        !           953:                            c.length = (c.lengthReason + 3) >> 2;
        !           954:                            c.majorVersion = X_PROTOCOL;
        !           955:                            c.minorVersion = X_PROTOCOL_REVISION;
        !           956:                            if(swapped)
        !           957:                            {
        !           958:                                int     n;
        !           959: 
        !           960:                                swaps(&c.majorVersion, n);
        !           961:                                swaps(&c.minorVersion, n);
        !           962:                                swaps(&c.length, n);
        !           963:                            }
        !           964: 
        !           965: #ifdef ISOCONN
        !           966:                            (void)SWrite(newconn, (char *)&c, sizeof(xConnSetupPrefix)); 
        !           967: #else /* ISOCONN */
        !           968:                            write(newconn, (char *)&c, sizeof(xConnSetupPrefix)); 
        !           969: #endif /* ISOCONN */
        !           970:                            iov[0].iov_len = c.lengthReason;
        !           971:                            iov[0].iov_base = reason;
        !           972:                            iov[1].iov_len = padlength[c.lengthReason & 3];
        !           973:                            iov[1].iov_base = p;
        !           974: #ifdef ISOCONN
        !           975:                            SWritev(newconn, iov, 2);
        !           976: #else /* ISOCONN */
        !           977:                            writev(newconn, iov, 2);
        !           978: #endif /* ISOCONN */
        !           979:                            if (debug_conns)
        !           980:                                ErrorF("Didn't make connection:%s\n", reason);
        !           981:                        }
        !           982: #ifdef ISOCONN
        !           983:                        SClose(newconn);
        !           984: #else /* ISOCONN */
        !           985:                        close(newconn);
        !           986: #endif /* ISOCONN */
        !           987:                        xfree(reason);
        !           988:                    }
        !           989: 
        !           990:                }
        !           991:            }
        !           992:            readyconnections &= ~(1 << curconn);
        !           993:        }
        !           994:     }
        !           995: }
        !           996: 
        !           997: /************
        !           998:  *   CloseDownFileDescriptor:
        !           999:  *     Remove this file descriptor and it's inputbuffers, etc.
        !          1000:  ************/
        !          1001: 
        !          1002: void
        !          1003: CloseDownFileDescriptor(connection)
        !          1004:     int connection;
        !          1005: {
        !          1006: #ifdef ISOCONN
        !          1007:     struct TSAPdisconnect tds;
        !          1008: #ifdef ISODEBUG
        !          1009:        if (isodexbug)
        !          1010:                fprintf(stderr, "server: TDiscReq\n");
        !          1011: #endif /* ISODEBUG */
        !          1012:     SClose(connection);
        !          1013: #else /* ISOCONN */
        !          1014:     close(connection);
        !          1015: #endif /* ISOCONN */
        !          1016: 
        !          1017:     if (inputBuffers[connection].size)
        !          1018:     {
        !          1019:        xfree(inputBuffers[connection].buffer);
        !          1020:        inputBuffers[connection].buffer = (char *) NULL;
        !          1021:        inputBuffers[connection].bufptr = (char *) NULL;
        !          1022:        inputBuffers[connection].size = 0;
        !          1023:     }
        !          1024:     inputBuffers[connection].bufcnt = 0;
        !          1025:     inputBuffers[connection].lenLastReq = 0;
        !          1026:     inputBuffers[connection].used = 0;
        !          1027: 
        !          1028:     BITCLEAR(AllSockets, connection);
        !          1029:     BITCLEAR(AllClients, connection);
        !          1030:     BITCLEAR(ClientsWithInput, connection);
        !          1031:     BITCLEAR(ClientsWriteBlocked, connection);
        !          1032:     if (!ANYSET(ClientsWriteBlocked))
        !          1033:        AnyClientsWriteBlocked = FALSE;
        !          1034: }
        !          1035: 
        !          1036: /*****************
        !          1037:  * CheckConections
        !          1038:  *    Some connection has died, go find which one and shut it down 
        !          1039:  *    The file descriptor has been closed, but is still in AllClients.
        !          1040:  *    If would truly be wonderful if select() would put the bogus
        !          1041:  *    file descriptors in the exception mask, but nooooo.  So we have
        !          1042:  *    to check each and every socket individually.
        !          1043:  *****************/
        !          1044: 
        !          1045: void
        !          1046: CheckConnections()
        !          1047: {
        !          1048:     long               mask[mskcnt];
        !          1049:     long               tmask[mskcnt]; 
        !          1050:     register int       curclient;
        !          1051:     int                        i;
        !          1052:     struct timeval     notime;
        !          1053:     ClientPtr           bad;
        !          1054:     int r;
        !          1055: #ifdef ISOCONN
        !          1056:     struct TSAPdisconnect tds;
        !          1057:     struct TSAPdisconnect *td = &tds;
        !          1058:     char *vec[4];
        !          1059:     int vecp;
        !          1060: #endif /* ISOCONN */
        !          1061: 
        !          1062:     notime.tv_sec = 0;
        !          1063:     notime.tv_usec = 0;
        !          1064: 
        !          1065:     COPYBITS(AllClients, mask);
        !          1066:     for (i=0; i<mskcnt; i++)
        !          1067:     {
        !          1068:         while (mask[i])
        !          1069:        {
        !          1070:            curclient = ffs (mask[i]) - 1 + (i << 5);
        !          1071:             CLEARBITS(tmask);
        !          1072:             BITSET(tmask, curclient);
        !          1073: #ifdef ISOCONN
        !          1074:             r = TNetAccept (&vecp, vec,
        !          1075:                        curclient + 1, tmask, (int *)NULL, (int *)NULL, 
        !          1076:                        OK, td);
        !          1077:             if (r == NOTOK)
        !          1078:             {
        !          1079:                Error(TErrString(td->td_reason));
        !          1080:                Error("TNetAccept");
        !          1081: #else /* ISOCONN */
        !          1082:             r = select (curclient + 1, tmask, (int *)NULL, (int *)NULL, 
        !          1083:                        &notime);
        !          1084:             if (r < 0)
        !          1085:             {
        !          1086: #endif /* ISOCONN */
        !          1087:                if (bad = ConnectionTranslation[curclient])
        !          1088:                    CloseDownClient(bad);
        !          1089:                 else
        !          1090:                     CloseDownFileDescriptor(curclient);
        !          1091:             }
        !          1092:            BITCLEAR(mask, curclient);
        !          1093:        }
        !          1094:     }  
        !          1095: }
        !          1096: 
        !          1097: 
        !          1098: /*****************
        !          1099:  * CloseDownConnection
        !          1100:  *    Delete client from AllClients and free resources 
        !          1101:  *****************/
        !          1102: 
        !          1103: CloseDownConnection(client)
        !          1104:     ClientPtr client;
        !          1105: {
        !          1106:     OsCommPtr oc = (OsCommPtr)client->osPrivate;
        !          1107: 
        !          1108:     ConnectionTranslation[oc->fd] = (ClientPtr)NULL;
        !          1109:     CloseDownFileDescriptor(oc->fd);
        !          1110:     if (oc->buf != NULL) /* an Xrealloc may have returned NULL */
        !          1111:        xfree(oc->buf);
        !          1112:     xfree(client->osPrivate);
        !          1113: }
        !          1114: 
        !          1115: 
        !          1116: AddEnabledDevice(fd)
        !          1117:     int fd;
        !          1118: {
        !          1119:     EnabledDevices |= (1<<fd);
        !          1120:     BITSET(AllSockets, fd);
        !          1121: }
        !          1122: 
        !          1123: 
        !          1124: RemoveEnabledDevice(fd)
        !          1125:     int fd;
        !          1126: {
        !          1127:     EnabledDevices &= ~(1<<fd);
        !          1128:     BITCLEAR(AllSockets, fd);
        !          1129: }
        !          1130: 
        !          1131: /*****************
        !          1132:  * OnlyListenToOneClient:
        !          1133:  *    Only accept requests from  one client.  Continue to handle new
        !          1134:  *    connections, but don't take any protocol requests from the new
        !          1135:  *    ones.  Note that if GrabDone is set, EstablishNewConnections
        !          1136:  *    needs to put new clients into SavedAllSockets and SavedAllClients.
        !          1137:  *    Note also that there is no timeout for this in the protocol.
        !          1138:  *    This routine is "undone" by ListenToAllClients()
        !          1139:  *****************/
        !          1140: 
        !          1141: OnlyListenToOneClient(client)
        !          1142:     ClientPtr client;
        !          1143: {
        !          1144:     OsCommPtr oc = (OsCommPtr)client->osPrivate;
        !          1145:     int connection = oc->fd;
        !          1146: 
        !          1147:     if (! GrabDone)
        !          1148:     {
        !          1149:        COPYBITS (ClientsWithInput, SavedClientsWithInput);
        !          1150:         BITCLEAR (SavedClientsWithInput, connection);
        !          1151:        if (GETBIT(ClientsWithInput, connection))
        !          1152:        {
        !          1153:            CLEARBITS(ClientsWithInput);            
        !          1154:            BITSET(ClientsWithInput, connection);
        !          1155:        }
        !          1156:        else
        !          1157:         {
        !          1158:            CLEARBITS(ClientsWithInput);            
        !          1159:        }
        !          1160:        COPYBITS(AllSockets, SavedAllSockets);
        !          1161:        COPYBITS(AllClients, SavedAllClients);
        !          1162: 
        !          1163:        UNSETBITS(AllSockets, AllClients);
        !          1164:        BITSET(AllSockets, connection);
        !          1165:        CLEARBITS(AllClients);
        !          1166:        BITSET(AllClients, connection);
        !          1167:        GrabDone = TRUE;
        !          1168:     }
        !          1169: }
        !          1170: 
        !          1171: /****************
        !          1172:  * ListenToAllClients:
        !          1173:  *    Undoes OnlyListentToOneClient()
        !          1174:  ****************/
        !          1175: 
        !          1176: ListenToAllClients()
        !          1177: {
        !          1178:     if (GrabDone)
        !          1179:     {
        !          1180:        ORBITS(AllSockets, AllSockets, SavedAllSockets);
        !          1181:        ORBITS(AllClients, AllClients, SavedAllClients);
        !          1182:        ORBITS(ClientsWithInput, ClientsWithInput, SavedClientsWithInput);
        !          1183:        GrabDone = FALSE;
        !          1184:     }  
        !          1185: }
        !          1186: 
        !          1187: 

unix.superglobalmegacorp.com

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