|
|
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: /* $Header: connection.c,v 1.62 87/09/07 17:12:18 rws Exp $ */ ! 25: /***************************************************************** ! 26: * Stuff to create connections --- OS dependent ! 27: * ! 28: * EstablishNewConnections, CreateWellKnownSockets, ! 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: #include <dbm.h> ! 43: #undef NULL ! 44: #include "X.h" ! 45: #include "Xproto.h" ! 46: #include <sys/param.h> ! 47: #include <errno.h> ! 48: #include <sys/types.h> ! 49: #include <sys/socket.h> ! 50: #include <sys/time.h> ! 51: #include <signal.h> ! 52: #include <fcntl.h> ! 53: #include <setjmp.h> ! 54: #ifdef TCPCONN ! 55: #include <netinet/in.h> ! 56: #endif ! 57: #ifdef UNIXCONN ! 58: #include <sys/un.h> ! 59: #endif ! 60: #include <stdio.h> ! 61: #include <sys/uio.h> ! 62: #include <strings.h> ! 63: #include "osstruct.h" ! 64: #include "osdep.h" ! 65: #include "opaque.h" ! 66: ! 67: #include "dixstruct.h" ! 68: ! 69: #ifdef DNETCONN ! 70: #include <netdnet/dn.h> ! 71: #endif /* DNETCONN */ ! 72: ! 73: typedef long CCID; /* mask of indices into client socket table */ ! 74: ! 75: #define X_UNIX_PATH "/tmp/.X11-unix" ! 76: ! 77: char *display; /* The display number */ ! 78: int lastfdesc; /* maximum file descriptor */ ! 79: ! 80: long WellKnownConnections; /* Listener mask */ ! 81: long EnabledDevices; /* mask for input devices that are on */ ! 82: long AllSockets[mskcnt]; /* select on this */ ! 83: long AllClients[mskcnt]; /* available clients */ ! 84: long LastSelectMask[mskcnt]; /* mask returned from last select call */ ! 85: long ClientsWithInput[mskcnt]; ! 86: long MaxClients = MAXSOCKS ; ! 87: long NConnBitArrays = mskcnt; ! 88: long FirstClient; ! 89: ! 90: static Bool debug_conns = FALSE; ! 91: ! 92: static char whichByteIsFirst; ! 93: ! 94: static int SavedAllClients[mskcnt]; ! 95: static int SavedAllSockets[mskcnt]; ! 96: static int SavedClientsWithInput[mskcnt]; ! 97: static Bool GrabDone = FALSE; ! 98: ! 99: ClientPtr ConnectionTranslation[MAXSOCKS]; ! 100: extern ClientPtr NextAvailableClient(); ! 101: ! 102: extern ConnectionInput inputBuffers[]; ! 103: ! 104: int swappedClients[MAXSOCKS]; ! 105: ! 106: extern int AutoResetServer(); ! 107: extern int GiveUp(); ! 108: ! 109: /***************** ! 110: * CreateWellKnownSockets ! 111: * At initialization, create the sockets to listen on for new clients. ! 112: * There are potentially 4: DECnet, UNIX Domain, TCP-IP with MSB first, ! 113: * with TCP-IP with LSB first. ! 114: *****************/ ! 115: ! 116: void ! 117: CreateWellKnownSockets() ! 118: { ! 119: char fname[32]; ! 120: int request, i; ! 121: int whichbyte; /* used to figure out whether this is ! 122: LSB or MSB */ ! 123: #ifdef TCPCONN ! 124: struct sockaddr_in insock; ! 125: int tcpportReg; /* port with same byte order as server */ ! 126: ! 127: #ifdef SO_LINGER ! 128: static int linger[2] = { 0, 0 }; ! 129: #endif /* SO_LINGER */ ! 130: ! 131: #endif /* TCPCONN */ ! 132: ! 133: #ifdef UNIXCONN ! 134: struct sockaddr_un unsock; ! 135: int oldUmask; ! 136: #endif /* UNIXCONN */ ! 137: ! 138: #ifdef DNETCONN ! 139: struct sockaddr_dn dnsock; ! 140: #endif /* DNETCONN */ ! 141: int retry; ! 142: ! 143: CLEARBITS(AllSockets); ! 144: CLEARBITS(AllClients); ! 145: CLEARBITS(LastSelectMask); ! 146: CLEARBITS(ClientsWithInput); ! 147: ! 148: for (i=0; i<MAXSOCKS; i++) ConnectionTranslation[i] = (ClientPtr)NULL; ! 149: ! 150: lastfdesc = getdtablesize() - 1; ! 151: if (lastfdesc > MAXSOCKS) ! 152: { ! 153: lastfdesc = MAXSOCKS; ! 154: ErrorF( "GOT TO END OF SOCKETS %d\n", MAXSOCKS); ! 155: } ! 156: ! 157: /* hack test to decide where to log errors */ ! 158: ! 159: if (write (2, fname, 0)) ! 160: { ! 161: long t; ! 162: ! 163: char *ctime(); ! 164: close(stdin); ! 165: close(stdout); ! 166: strcpy (fname, "/usr/adm/X"); ! 167: strcat (fname, display); ! 168: strcat (fname, "msgs"); ! 169: freopen (fname, "a+", stderr); ! 170: setlinebuf(stderr); ! 171: time (&t); ! 172: fprintf (stderr, "start %s", ctime(&t)); ! 173: } ! 174: if (getpgrp (0) == 0) ! 175: setpgrp (0, getpid ()); ! 176: ! 177: WellKnownConnections = 0; ! 178: whichbyte = 1; ! 179: ! 180: if (*(char *) &whichbyte) ! 181: whichByteIsFirst = 'l'; ! 182: else ! 183: whichByteIsFirst = 'B'; ! 184: ! 185: ! 186: #ifdef TCPCONN ! 187: ! 188: tcpportReg = atoi (display); ! 189: tcpportReg += X_TCP_PORT; ! 190: ! 191: if ((request = socket (AF_INET, SOCK_STREAM, 0)) < 0) ! 192: { ! 193: Notice ("Creating TCP socket"); ! 194: } ! 195: else ! 196: { ! 197: bzero ((char *)&insock, sizeof (insock)); ! 198: insock.sin_family = AF_INET; ! 199: insock.sin_port = htons (tcpportReg); ! 200: insock.sin_addr.s_addr = htonl(INADDR_ANY); ! 201: retry = 20; ! 202: while (i = bind(request, (struct sockaddr *) &insock, sizeof (insock))) ! 203: { ! 204: if (--retry == 0) ! 205: Error ("Binding MSB TCP socket"); ! 206: sleep (10); ! 207: } ! 208: #ifdef SO_LINGER ! 209: if(setsockopt (request, SOL_SOCKET, SO_LINGER, linger, sizeof(linger))) ! 210: Notice ("Setting TCP SO_LINGER\n"); ! 211: #endif /* SO_LINGER */ ! 212: if (listen (request, 5)) ! 213: Error ("Reg TCP Listening"); ! 214: WellKnownConnections |= (1 << request); ! 215: DefineSelf (request); ! 216: } ! 217: ! 218: #endif /* TCPCONN */ ! 219: ! 220: #ifdef UNIXCONN ! 221: unsock.sun_family = AF_UNIX; ! 222: oldUmask = umask (0); ! 223: mkdir (X_UNIX_PATH, 0777); ! 224: (void)umask(oldUmask); ! 225: strcpy (unsock.sun_path, X_UNIX_PATH); ! 226: strcat (unsock.sun_path, "/X"); ! 227: strcat (unsock.sun_path, display); ! 228: unlink (unsock.sun_path); ! 229: if ((request = socket (AF_UNIX, SOCK_STREAM, 0)) < 0) ! 230: { ! 231: Notice ("Creating Unix socket"); ! 232: } ! 233: else ! 234: { ! 235: if(bind(request,(struct sockaddr *)&unsock, strlen(unsock.sun_path)+2)) ! 236: Error ("Binding Unix socket"); ! 237: if (listen (request, 5)) Error ("Unix Listening"); ! 238: WellKnownConnections |= (1 << request); ! 239: } ! 240: #endif /*UNIXCONN */ ! 241: ! 242: #ifdef DNETCONN ! 243: if ((request = socket (AF_DECnet, SOCK_STREAM, 0)) < 0) ! 244: { ! 245: Notice ("Creating DECnet socket"); ! 246: } ! 247: else ! 248: { ! 249: bzero ((char *)&dnsock, sizeof (dnsock)); ! 250: dnsock.sdn_family = AF_DECnet; ! 251: sprintf(dnsock.sdn_objname, "X%d", atoi (display)); ! 252: dnsock.sdn_objnamel = strlen(dnsock.sdn_objname); ! 253: if (bind (request, (struct sockaddr *) &dnsock, sizeof (dnsock))) ! 254: Error ("Binding DECnet socket"); ! 255: if (listen (request, 5)) Error ("DECnet Listening"); ! 256: WellKnownConnections |= (1 << request); ! 257: DefineSelf (request); ! 258: } ! 259: #endif /* DNETCONN */ ! 260: if (WellKnownConnections == 0) ! 261: Error ("No Listeners, nothing to do"); ! 262: signal (SIGPIPE, SIG_IGN); ! 263: signal (SIGHUP, AutoResetServer); ! 264: signal (SIGINT, GiveUp); ! 265: signal (SIGTERM, GiveUp); ! 266: FirstClient = request + 1; ! 267: AllSockets[0] = WellKnownConnections; ! 268: ResetHosts(display); ! 269: ! 270: for (i=0; i<MaxClients; i++) ! 271: { ! 272: inputBuffers[i].buffer = (char *) NULL; ! 273: inputBuffers[i].bufptr = (char *) NULL; ! 274: inputBuffers[i].bufcnt = 0; ! 275: inputBuffers[i].lenLastReq = 0; ! 276: inputBuffers[i].size = 0; ! 277: } ! 278: } ! 279: ! 280: /* We want to read the connection information. If the client doesn't ! 281: * send us enough data, however, we want to time out eventually. ! 282: * The scheme is to clear a flag, set an alarm, and keep doing non-blocking ! 283: * reads until we get all the data we want. If the alarm goes ! 284: * off, the handler will clear the flag. If we see that the flag is ! 285: * cleared, we know we've timed out and return with an error. ! 286: * ! 287: * there remains one problem with this code: ! 288: * there is a window of vulnerability in which we might get an alarm ! 289: * even though all the data has come in properly. This is because I ! 290: * can't atomically clear the alarm. ! 291: * ! 292: * Anyone who sees how to fix this problem should do so and ! 293: * submit a fix. ! 294: */ ! 295: ! 296: jmp_buf env; ! 297: void TimeOut() ! 298: { ! 299: longjmp(env, 1); ! 300: } ! 301: static Bool ! 302: ReadBuffer(conn, buffer, charsWanted) ! 303: long conn; ! 304: char *buffer; ! 305: int charsWanted; ! 306: { ! 307: char *bptr = buffer; ! 308: int got, fTimeOut; ! 309: struct itimerval itv; ! 310: ! 311: signal(SIGALRM, TimeOut); ! 312: fTimeOut = FALSE; ! 313: /* only 1 alarm, please, not 1 per minute */ ! 314: timerclear(&itv.it_interval); ! 315: itv.it_value.tv_sec = TimeOutValue; ! 316: itv.it_value.tv_usec = 0; ! 317: setitimer(ITIMER_REAL, &itv, NULL); ! 318: /* It better not take a full minute to get to the read call */ ! 319: ! 320: while (charsWanted && (fTimeOut = setjmp(env)) == FALSE) ! 321: { ! 322: got = read(conn, bptr, charsWanted); ! 323: if (got <= 0) ! 324: return FALSE; ! 325: if(got > 0) ! 326: { ! 327: charsWanted -= got; ! 328: bptr += got; ! 329: /* Ok, we got something, reset the timer */ ! 330: itv.it_value.tv_sec = TimeOutValue; ! 331: itv.it_value.tv_usec = 0; ! 332: setitimer(ITIMER_REAL, &itv, NULL); ! 333: } ! 334: } ! 335: /* disable the timer */ ! 336: timerclear(&itv.it_value); ! 337: setitimer(ITIMER_REAL, &itv, NULL); ! 338: /* If we got here and we didn't time out, then return TRUE, because ! 339: * we must have read what we wanted. If we timed out, return FALSE */ ! 340: if(fTimeOut && debug_conns) ! 341: ErrorF("Timed out on connection %d\n", conn); ! 342: return (!fTimeOut); ! 343: } ! 344: ! 345: /***************************************************************** ! 346: * ClientAuthorized ! 347: * ! 348: * Sent by the client at connection setup: ! 349: * typedef struct _xConnClientPrefix { ! 350: * CARD8 byteOrder; ! 351: * BYTE pad; ! 352: * CARD16 majorVersion, minorVersion; ! 353: * CARD16 nbytesAuthProto; ! 354: * CARD16 nbytesAuthString; ! 355: * } xConnClientPrefix; ! 356: * ! 357: * It is hoped that eventually one protocol will be agreed upon. In the ! 358: * mean time, a server that implements a different protocol than the ! 359: * client expects, or a server that only implements the host-based ! 360: * mechanism, will simply ignore this information. ! 361: * ! 362: *****************************************************************/ ! 363: ! 364: int ! 365: ClientAuthorized(conn, pswapped, reason) ! 366: long conn; ! 367: int *pswapped; ! 368: char **reason; /* if authorization fails, put reason in here */ ! 369: { ! 370: short slen; ! 371: union { ! 372: struct sockaddr sa; ! 373: #ifdef UNIXCONN ! 374: struct sockaddr_un un; ! 375: #endif /* UNIXCONN */ ! 376: #ifdef TCPCONN ! 377: struct sockaddr_in in; ! 378: #endif /* TCPCONN */ ! 379: #ifdef DNETCONN ! 380: struct sockaddr_dn dn; ! 381: #endif /* DNETCONN */ ! 382: } from; ! 383: int fromlen; ! 384: xConnClientPrefix xccp; ! 385: char auth_proto[100]; ! 386: char auth_string[100]; ! 387: ! 388: if (!ReadBuffer(conn, &xccp, sizeof(xConnClientPrefix))) ! 389: { ! 390: /* If they can't even give us this much, just blow them off ! 391: * without an error message */ ! 392: *reason = 0; ! 393: return 0; ! 394: } ! 395: if (xccp.byteOrder != whichByteIsFirst) ! 396: { ! 397: SwapConnClientPrefix(&xccp); ! 398: *pswapped = TRUE; ! 399: } ! 400: else ! 401: *pswapped = FALSE; ! 402: if ((xccp.majorVersion != X_PROTOCOL) || ! 403: (xccp.minorVersion != X_PROTOCOL_REVISION)) ! 404: { ! 405: #define STR "Protocol version mismatch" ! 406: *reason = (char *)Xalloc(strlen(STR) + 1); ! 407: strcpy(*reason, STR); ! 408: if (debug_conns) ! 409: ErrorF("%s\n", STR); ! 410: #undef STR ! 411: return 0; ! 412: } ! 413: fromlen = sizeof (from); ! 414: if (getpeername (conn, &from.sa, &fromlen) || ! 415: InvalidHost (&from.sa, fromlen)) ! 416: { ! 417: #define STR "Server is not authorized to connect to host" ! 418: *reason = (char *)Xalloc(strlen(STR)); ! 419: strcpy(*reason, STR); ! 420: #undef STR ! 421: return 0; ! 422: } ! 423: ! 424: slen = (xccp.nbytesAuthProto + 3) & ~3; ! 425: if ( slen ) ! 426: if (!ReadBuffer(conn, auth_proto, slen)) ! 427: { ! 428: #define STR "Length error in xConnClientPrefix for protocol authorization " ! 429: *reason = (char *)Xalloc(strlen(STR)); ! 430: strcpy(*reason, STR); ! 431: return 0; ! 432: #undef STR ! 433: } ! 434: auth_proto[slen] = '\0'; ! 435: ! 436: slen = (xccp.nbytesAuthString + 3) & ~3; ! 437: if ( slen) ! 438: if (!ReadBuffer(conn, auth_string, slen)) ! 439: { ! 440: #define STR "Length error in xConnClientPrefix for protocol string" ! 441: *reason = (char *)Xalloc(strlen(STR)); ! 442: strcpy(*reason, STR); ! 443: return 0; ! 444: #undef STR ! 445: } ! 446: auth_string[slen] = '\0'; ! 447: ! 448: /* At this point, if the client is authorized to change the access control ! 449: * list, we should getpeername() information, and add the client to ! 450: * the selfhosts list. It's not really the host machine, but the ! 451: * true purpose of the selfhosts list is to see who may change the ! 452: * access control list. ! 453: */ ! 454: return(1); ! 455: } ! 456: ! 457: static int padlength[4] = {0, 3, 2, 1}; ! 458: ! 459: /***************** ! 460: * EstablishNewConnections ! 461: * If anyone is waiting on listened sockets, accept them. ! 462: * Returns a mask with indices of new clients. Updates AllClients ! 463: * and AllSockets. ! 464: *****************/ ! 465: ! 466: void ! 467: EstablishNewConnections(newclients, nnew) ! 468: ClientPtr *newclients; ! 469: int *nnew; ! 470: { ! 471: long readyconnections; /* mask of listeners that are ready */ ! 472: long curconn; /* fd of listener that's ready */ ! 473: long newconn; /* fd of new client */ ! 474: int swapped; /* set by ClientAuthorized if connection is ! 475: * swapped */ ! 476: char *reason; ! 477: struct iovec iov[2]; ! 478: char p[3]; ! 479: ! 480: #ifdef TCP_NODELAY ! 481: union { ! 482: struct sockaddr sa; ! 483: #ifdef UNIXCONN ! 484: struct sockaddr_un un; ! 485: #endif /* UNIXCONN */ ! 486: #ifdef TCPCONN ! 487: struct sockaddr_in in; ! 488: #endif /* TCPCONN */ ! 489: #ifdef DNETCONN ! 490: struct sockaddr_dn dn; ! 491: #endif /* DNETCONN */ ! 492: } from; ! 493: int fromlen; ! 494: #endif TCP_NODELAY ! 495: ! 496: *nnew = 0; ! 497: if (readyconnections = (LastSelectMask[0] & WellKnownConnections)) ! 498: { ! 499: while (readyconnections) ! 500: { ! 501: curconn = ffs (readyconnections) - 1; ! 502: if ((newconn = accept (curconn, ! 503: (struct sockaddr *) NULL, ! 504: (int *)NULL)) >= 0) ! 505: { ! 506: if (newconn >= lastfdesc) ! 507: { ! 508: if (debug_conns) ! 509: ErrorF("Didn't make connection: Out of file descriptors for connections\n"); ! 510: close (newconn); ! 511: } ! 512: else ! 513: { ! 514: #ifdef TCP_NODELAY ! 515: fromlen = sizeof (from); ! 516: if (!getpeername (newconn, &from.sa, &fromlen)) ! 517: { ! 518: if (fromlen && (from.sa.sa_family == AF_INET)) ! 519: { ! 520: mi = 1; ! 521: setsockopt (newconn, IPPROTO_TCP, TCP_NODELAY, ! 522: &mi, sizeof (int)); ! 523: } ! 524: } ! 525: #endif /* TCP_NODELAY */ ! 526: if (ClientAuthorized(newconn, &swapped, &reason)) ! 527: { ! 528: ClientPtr next; ! 529: ! 530: fcntl (newconn, F_SETFL, FNDELAY); ! 531: inputBuffers[newconn].used = 1; ! 532: if (! inputBuffers[newconn].size) ! 533: { ! 534: inputBuffers[newconn].buffer = ! 535: (char *)Xalloc(BUFSIZE); ! 536: inputBuffers[newconn].size = BUFSIZE; ! 537: inputBuffers[newconn].bufptr = ! 538: inputBuffers[newconn].buffer; ! 539: } ! 540: if (GrabDone) ! 541: { ! 542: BITSET(SavedAllClients, newconn); ! 543: BITSET(SavedAllSockets, newconn); ! 544: } ! 545: else ! 546: { ! 547: BITSET(AllClients, newconn); ! 548: BITSET(AllSockets, newconn); ! 549: } ! 550: next = NextAvailableClient(); ! 551: if (next != (ClientPtr)NULL) ! 552: { ! 553: osPrivPtr priv; ! 554: ! 555: newclients[(*nnew)++] = next; ! 556: next->swapped = swapped; ! 557: ConnectionTranslation[newconn] = next; ! 558: priv = (osPrivPtr)Xalloc(sizeof(osPrivRec)); ! 559: priv->fd = newconn; ! 560: next->osPrivate = (pointer)priv; ! 561: } ! 562: } ! 563: else ! 564: { ! 565: xConnSetupPrefix c; ! 566: ! 567: if(reason) ! 568: { ! 569: c.success = xFalse; ! 570: c.lengthReason = strlen(reason); ! 571: c.length = (c.lengthReason + 3) >> 2; ! 572: c.majorVersion = X_PROTOCOL; ! 573: c.minorVersion = X_PROTOCOL_REVISION; ! 574: if(swapped) ! 575: { ! 576: int n; ! 577: ! 578: swaps(&c.majorVersion, n); ! 579: swaps(&c.minorVersion, n); ! 580: swaps(&c.length, n); ! 581: } ! 582: ! 583: write(newconn, &c, sizeof(xConnSetupPrefix)); ! 584: iov[0].iov_len = c.lengthReason; ! 585: iov[0].iov_base = reason; ! 586: iov[1].iov_len = padlength[c.lengthReason & 3]; ! 587: iov[1].iov_base = p; ! 588: writev(newconn, iov, 2); ! 589: if (debug_conns) ! 590: ErrorF("Didn't make connection:%s\n", reason); ! 591: } ! 592: close(newconn); ! 593: Xfree(reason); ! 594: } ! 595: ! 596: } ! 597: } ! 598: readyconnections &= ~(1 << curconn); ! 599: } ! 600: } ! 601: } ! 602: ! 603: /************ ! 604: * CloseDwonFileDescriptor: ! 605: * Remove this file descriptor and it's inputbuffers, etc. ! 606: ************/ ! 607: ! 608: void ! 609: CloseDownFileDescriptor(connection) ! 610: long connection; ! 611: { ! 612: close(connection); ! 613: ! 614: inputBuffers[connection].bufptr = inputBuffers[connection].buffer; ! 615: inputBuffers[connection].bufcnt = 0; ! 616: inputBuffers[connection].lenLastReq = 0; ! 617: inputBuffers[connection].used = 0; ! 618: ! 619: BITCLEAR(AllSockets, connection); ! 620: BITCLEAR(AllClients, connection); ! 621: BITCLEAR(ClientsWithInput, connection); ! 622: ! 623: } ! 624: ! 625: /***************** ! 626: * CheckConections ! 627: * Some connection has died, go find which one and shut it down ! 628: * The file descriptor has been closed, but is still in AllClients. ! 629: * If would truly be wonderful if select() would put the bogus ! 630: * file descriptors in the exception mask, but nooooo. So we have ! 631: * to check each and every socket individually. ! 632: *****************/ ! 633: ! 634: void ! 635: CheckConnections() ! 636: { ! 637: long mask[mskcnt]; ! 638: long tmask[mskcnt]; ! 639: register int curclient; ! 640: int i; ! 641: struct timeval notime; ! 642: ClientPtr bad; ! 643: int r; ! 644: ! 645: notime.tv_sec = 0; ! 646: notime.tv_usec = 0; ! 647: ! 648: COPYBITS(AllClients, mask); ! 649: for (i=0; i<mskcnt; i++) ! 650: { ! 651: while (mask[i]) ! 652: { ! 653: curclient = ffs (mask[i]) - 1 + (i << 5); ! 654: CLEARBITS(tmask); ! 655: BITSET(tmask, curclient); ! 656: r = select (curclient + 1, tmask, (int *)NULL, (int *)NULL, ! 657: ¬ime); ! 658: if (r < 0) ! 659: { ! 660: if (bad = ConnectionTranslation[curclient]) ! 661: CloseDownClient(bad); ! 662: else ! 663: CloseDownFileDescriptor(curclient); ! 664: } ! 665: BITCLEAR(mask, curclient); ! 666: } ! 667: } ! 668: } ! 669: ! 670: ! 671: /***************** ! 672: * CloseDownConnection ! 673: * Delete client from AllClients and free resources ! 674: *****************/ ! 675: ! 676: CloseDownConnection(client) ! 677: ClientPtr client; ! 678: { ! 679: int connection = ((osPrivPtr)client->osPrivate)->fd; ! 680: ! 681: ConnectionTranslation[connection] = (ClientPtr)NULL; ! 682: CloseDownFileDescriptor(connection); ! 683: Xfree(client->osPrivate); ! 684: } ! 685: ! 686: ! 687: AddEnabledDevice(fd) ! 688: int fd; ! 689: { ! 690: EnabledDevices |= (1<<fd); ! 691: BITSET(AllSockets, fd); ! 692: } ! 693: ! 694: ! 695: RemoveEnabledDevice(fd) ! 696: int fd; ! 697: { ! 698: EnabledDevices &= ~(1<<fd); ! 699: BITCLEAR(AllSockets, fd); ! 700: } ! 701: ! 702: /***************** ! 703: * OnlyListenToOneClient: ! 704: * Only accept requests from one client. Continue to handle new ! 705: * connections, but don't take any protocol requests from the new ! 706: * ones. Note that if GrabDone is set, EstablishNewConnections ! 707: * needs to put new clients into SavedAllSockets and SavedAllClients. ! 708: * Note also that there is no timeout for this in the protocol. ! 709: * This routine is "undone" by ListenToAllClients() ! 710: *****************/ ! 711: ! 712: OnlyListenToOneClient(client) ! 713: ClientPtr client; ! 714: { ! 715: int connection = ((osPrivPtr)client->osPrivate)->fd; ! 716: ! 717: if (! GrabDone) ! 718: { ! 719: COPYBITS (ClientsWithInput, SavedClientsWithInput); ! 720: BITCLEAR (SavedClientsWithInput, connection); ! 721: if (GETBIT(ClientsWithInput, connection)) ! 722: { ! 723: CLEARBITS(ClientsWithInput); ! 724: BITSET(ClientsWithInput, connection); ! 725: } ! 726: else ! 727: { ! 728: CLEARBITS(ClientsWithInput); ! 729: } ! 730: COPYBITS(AllSockets, SavedAllSockets); ! 731: COPYBITS(AllClients, SavedAllClients); ! 732: ! 733: UNSETBITS(AllSockets, AllClients); ! 734: BITSET(AllSockets, connection); ! 735: CLEARBITS(AllClients); ! 736: BITSET(AllClients, connection); ! 737: GrabDone = TRUE; ! 738: } ! 739: } ! 740: ! 741: /**************** ! 742: * ListenToAllClients: ! 743: * Undoes OnlyListentToOneClient() ! 744: ****************/ ! 745: ! 746: ListenToAllClients() ! 747: { ! 748: if (GrabDone) ! 749: { ! 750: ORBITS(AllSockets, AllSockets, SavedAllSockets); ! 751: ORBITS(AllClients, AllClients, SavedAllClients); ! 752: ORBITS(ClientsWithInput, ClientsWithInput, SavedClientsWithInput); ! 753: GrabDone = FALSE; ! 754: } ! 755: } ! 756: ! 757:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.