dispatch.c revision bbe1b32b
1/* $Xorg: dispatch.c,v 1.6 2001/02/09 02:05:42 xorgcvs Exp $ */ 2/* 3 * protocol dispatcher 4 */ 5/* 6 7Copyright 1990, 1991, 1998 The Open Group 8 9Permission to use, copy, modify, distribute, and sell this software and its 10documentation for any purpose is hereby granted without fee, provided that 11the above copyright notice appear in all copies and that both that 12copyright notice and this permission notice appear in supporting 13documentation. 14 15The above copyright notice and this permission notice shall be included in 16all copies or substantial portions of the Software. 17 18THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 22AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 23CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 25Except as contained in this notice, the name of The Open Group shall not be 26used in advertising or otherwise to promote the sale, use or other dealings 27in this Software without prior written authorization from The Open Group. 28 29 * Copyright 1990, 1991 Network Computing Devices; 30 * Portions Copyright 1987 by Digital Equipment Corporation 31 * 32 * Permission to use, copy, modify, distribute, and sell this software and 33 * its documentation for any purpose is hereby granted without fee, provided 34 * that the above copyright notice appear in all copies and that both that 35 * copyright notice and this permission notice appear in supporting 36 * documentation, and that the names of Network Computing Devices, or Digital 37 * not be used in advertising or publicity pertaining to distribution 38 * of the software without specific, written prior permission. 39 * 40 * NETWORK COMPUTING DEVICES, AND DIGITAL DISCLAIM ALL WARRANTIES WITH 41 * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF 42 * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL NETWORK COMPUTING DEVICES, 43 * OR DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL 44 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 45 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS 46 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF 47 * THIS SOFTWARE. 48 */ 49/* $XFree86: xc/programs/xfs/difs/dispatch.c,v 3.12 2001/12/14 20:01:33 dawes Exp $ */ 50 51#include <stdlib.h> 52#include "dispatch.h" 53#include "swapreq.h" 54#include "swaprep.h" 55 56#include <X11/fonts/FS.h> 57#include <X11/fonts/FSproto.h> 58#include "clientstr.h" 59#include "authstr.h" 60#include "osstruct.h" 61#include "extentst.h" 62#include "globals.h" 63#include "fsresource.h" 64#include "difsfnst.h" 65#include <X11/fonts/fontstruct.h> 66#include "site.h" 67#include "fsevents.h" 68#include "cache.h" 69#include "globals.h" 70#include "difs.h" 71 72static void kill_all_clients(void); 73 74volatile char dispatchException = 0; 75volatile char isItTimeToYield; 76 77ClientPtr currentClient; 78 79static int nClients = 0; 80static int nextFreeClientID; 81 82extern char *ConnectionInfo; 83extern int ConnInfoLen; 84 85extern char *configfilename; 86 87extern Bool drone_server; 88 89#define MAJOROP ((fsReq *)client->requestBuffer)->reqType 90 91#define ALL_FORMAT_BITS (BitmapFormatByteOrderMask | \ 92 BitmapFormatBitOrderMask | \ 93 BitmapFormatScanlineUnitMask | \ 94 BitmapFormatScanlinePadMask | \ 95 BitmapFormatImageRectMask) 96 97#define ALL_FORMAT_MASK_BITS (BitmapFormatMaskByte | \ 98 BitmapFormatMaskBit | \ 99 BitmapFormatMaskImageRectangle | \ 100 BitmapFormatMaskScanLinePad | \ 101 BitmapFormatMaskScanLineUnit) 102 103void 104Dispatch(void) 105{ 106 int nready, 107 result; 108 int *clientReady; 109 ClientPtr client; 110 int op; 111 112 nextFreeClientID = MINCLIENT; 113 nClients = 0; 114 115 clientReady = (int *) ALLOCATE_LOCAL(sizeof(int) * MaxClients); 116 if (!clientReady) 117 return; 118 119 while (1) { 120 /* wait for something */ 121 nready = WaitForSomething(clientReady); 122 123 while (!dispatchException && (--nready >= 0)) { 124 client = currentClient = clients[clientReady[nready]]; 125 126 /* Client can be NULL if CloseDownClient() is called during 127 this dispatchException loop. */ 128 if (client == (ClientPtr)NULL) continue; 129 130 isItTimeToYield = FALSE; 131 132 while (!isItTimeToYield) { 133 result = ReadRequest(client); 134 if (result <= 0) { 135 if (result < 0) 136 CloseDownClient(client); 137 break; 138 } 139 client->sequence++; 140 141 if (result > (MAX_REQUEST_SIZE << 2)) 142 result = FSBadLength; 143 else 144 { 145 op = MAJOROP; 146 if (op >= NUM_PROC_VECTORS) 147 result = ProcBadRequest (client); 148 else if (*client->requestVector[op] != NULL) 149 result = (*client->requestVector[op]) (client); 150 else 151 result = FSBadRequest; 152 } 153 if (result != FSSuccess) { 154 if (client->noClientException != FSSuccess) 155 CloseDownClient(client); 156 break; 157 } 158 } 159 FlushAllOutput (); 160 } 161 /* reset if server is a drone and has run out of clients */ 162 if (drone_server && nClients == 0) { 163 dispatchException |= DE_RESET; 164 } 165 if (dispatchException) { 166 /* re-read the config file */ 167 if (dispatchException & DE_RECONFIG) { 168 NoticeF("re-reading config file\n"); 169 if (ReadConfigFile(configfilename) != FSSuccess) 170 ErrorF("couldn't parse config file\n"); 171 SetConfigValues(); 172 dispatchException &= ~DE_RECONFIG; 173 } 174 /* flush all the caches */ 175 if (dispatchException & DE_FLUSH) { 176 NoticeF("flushing all caches\n"); 177 CacheReset(); 178 dispatchException &= ~DE_FLUSH; 179 } 180 /* reset */ 181 if (dispatchException & DE_RESET) { 182 NoticeF("resetting\n"); 183 break; 184 } 185 /* die *now* */ 186 if (dispatchException & DE_TERMINATE) { 187 NoticeF("terminating\n"); 188 kill_all_clients(); 189 CloseSockets(); 190 CloseErrors(); 191 exit(0); 192 break; 193 } 194 } 195 } 196 kill_all_clients(); 197 dispatchException = 0; 198} 199 200int 201ProcInitialConnection(ClientPtr client) 202{ 203 REQUEST(fsFakeReq); 204 fsConnClientPrefix *prefix; 205 int whichbyte = 1; 206 207 nClients++; 208 prefix = (fsConnClientPrefix *) stuff+1; 209 if ((prefix->byteOrder != 'l') && (prefix->byteOrder != 'B')) 210 return (client->noClientException = -2); 211 if (((*(char *) &whichbyte) && (prefix->byteOrder == 'B')) || 212 (!(*(char *) &whichbyte) && (prefix->byteOrder == 'l'))) { 213 int status; 214 215 client->swapped = TRUE; 216 status = SwapConnClientPrefix(client, prefix); 217 if (status != FSSuccess) 218 return (status); 219 } 220 client->major_version = prefix->major_version; 221 client->minor_version = prefix->minor_version; 222 stuff->reqType = 2; 223 stuff->length += prefix->auth_len; 224 if (client->swapped) { 225 stuff->length = lswaps(stuff->length); 226 } 227 ResetCurrentRequest(client); 228 return client->noClientException; 229} 230 231int 232ProcEstablishConnection(ClientPtr client) 233{ 234 fsConnClientPrefix *prefix; 235 fsConnSetup csp; 236 int ret; 237 pointer auth_data; 238 char *ad; 239 char *server_auth_data; 240 AuthPtr client_auth; 241 int i, 242 num_alts, 243 altlen, 244 auth_accept, 245 auth_index, 246 auth_len; 247 AlternateServerPtr altservers; 248 249 REQUEST(fsFakeReq); 250 251 prefix = (fsConnClientPrefix *) stuff+1; 252 auth_data = prefix + sz_fsConnClientPrefix; 253 client_auth = (AuthPtr) ALLOCATE_LOCAL(prefix->num_auths * sizeof(AuthRec)); 254 if (!client_auth) { 255 SendErrToClient(client, FSBadAlloc, (pointer) 0); 256 return FSBadAlloc; 257 } 258/* XXXX -- this needs work for multiple auth replies */ 259 260 /* build up a list of the stuff */ 261 for (i = 0, ad = auth_data; i < (int)prefix->num_auths; i++) { 262 if (ad - (char *)auth_data > (stuff->length << 2) - 4) { 263 int lengthword = stuff->length; 264 265 SendErrToClient(client, FSBadLength, (pointer)&lengthword); 266 return (FSBadLength); 267 } 268 /* copy carefully in case wire data is not aligned */ 269 client_auth[i].namelen = (((unsigned char *)ad)[0] << 8) + 270 ((unsigned char *)ad)[1]; 271 ad += 2; 272 client_auth[i].datalen = (((unsigned char *)ad)[0] << 8) + 273 ((unsigned char *)ad)[1]; 274 ad += 2; 275 client_auth[i].name = (char *) ad; 276 ad += client_auth[i].namelen; 277 client_auth[i].data = (char *) ad; 278 ad += client_auth[i].datalen; 279 } 280 if (!(int)prefix->num_auths) 281 ad += 4; 282 if (ad - (char *)auth_data > (stuff->length << 2)) { 283 int lengthword = stuff->length; 284 285 SendErrToClient(client, FSBadLength, (pointer)&lengthword); 286 return (FSBadLength); 287 } 288 289 num_alts = ListAlternateServers(&altservers); 290 for (i = 0, altlen = 0; i < num_alts; i++) { 291 /* subset + len + namelen + pad */ 292 altlen += (2 + altservers[i].namelen + 3) >> 2; 293 } 294 295 auth_index = prefix->num_auths; 296 client->auth_generation = 0; 297 ret = CheckClientAuthorization(client, client_auth, 298 &auth_accept, &auth_index, &auth_len, &server_auth_data); 299 if (auth_index > 0) 300 { 301 AuthContextPtr authp; 302 authp = (AuthContextPtr) fsalloc(sizeof(AuthContextRec)); 303 if (!authp) { 304 SendErrToClient(client, FSBadAlloc, (pointer) 0); 305 return FSBadAlloc; 306 } 307 authp->authname = 0; 308 authp->authdata = 0; 309 authp->authname = 310 (char *) fsalloc(client_auth[auth_index - 1].namelen + 1); 311 authp->authdata = 312 (char *) fsalloc(client_auth[auth_index - 1].datalen + 1); 313 if (!authp->authname || !authp->authdata) { 314 fsfree((char *) authp->authname); 315 fsfree((char *) authp->authdata); 316 fsfree((char *) authp); 317 SendErrToClient(client, FSBadAlloc, (pointer) 0); 318 return FSBadAlloc; 319 } 320 memmove( authp->authname, client_auth[auth_index - 1].name, 321 client_auth[auth_index - 1].namelen); 322 memmove( authp->authdata, client_auth[auth_index - 1].data, 323 client_auth[auth_index - 1].datalen); 324 /* Save it with a zero resource id... subsequent 325 SetAuthorizations of None will find it. And it will be freed 326 by FreeClientResources when the connection closes. */ 327 if (!AddResource(client->index, 0, RT_AUTHCONT,(pointer) authp)) 328 { 329 fsfree((char *) authp->authname); 330 fsfree((char *) authp->authdata); 331 fsfree((char *) authp); 332 SendErrToClient(client, FSBadAlloc, (pointer) 0); 333 return FSBadAlloc; 334 } 335 client->auth = client->default_auth = authp; 336 } 337 else 338 client->auth = client->default_auth = (AuthContextPtr)0; 339 340 DEALLOCATE_LOCAL(client_auth); 341 342 if (ret != FSSuccess) { 343 SendErrToClient(client, FSBadAlloc, (pointer) 0); 344 return FSBadAlloc; 345 } 346 csp.status = auth_accept; 347 if (client->major_version == 1) 348 /* we implement backwards compatibility for version 1.0 */ 349 csp.major_version = client->major_version; 350 else 351 csp.major_version = FS_PROTOCOL; 352 csp.minor_version = FS_PROTOCOL_MINOR; 353 csp.num_alternates = num_alts; 354 csp.alternate_len = altlen; 355 csp.auth_len = auth_len >> 2; 356 csp.auth_index = auth_index; 357 if (client->swapped) { 358 WriteSConnSetup(client, &csp); 359 } else { 360 (void) WriteToClient(client, SIZEOF(fsConnSetup), (char *) &csp); 361 } 362 363 /* send the alternates info */ 364 for (i = 0; i < num_alts; i++) { 365 char tmp[258]; 366 367 /* WriteToClient pads, so we have to fake some things */ 368 tmp[0] = altservers[i].subset; 369 tmp[1] = altservers[i].namelen; 370 memmove( (char *) &tmp[2], altservers[i].name, altservers[i].namelen); 371 (void) WriteToClient(client, altservers[i].namelen + 2, tmp); 372 } 373 374 if (auth_len) 375 (void) WriteToClient(client, auth_len, (char *) server_auth_data); 376 377 if (auth_accept != AuthSuccess) { 378 nClients--; 379 return (client->noClientException = -2); 380 } 381 client->requestVector = client->swapped ? SwappedProcVector : ProcVector; 382 client->sequence = 0; 383 if (client->swapped) 384 (void) WriteSConnectionInfo(client, ConnInfoLen, ConnectionInfo); 385 else 386 (void) WriteToClient(client, ConnInfoLen, ConnectionInfo); 387 388#ifdef DEBUG 389 fprintf(stderr, "Establishing new connection\n"); 390#endif 391 392 return client->noClientException; 393} 394 395/* 396 * NOTE -- the incoming data may be mangled 397 */ 398 399void 400DoSendErrToClient( 401 ClientPtr client, 402 int error, 403 pointer data) /* resource id, format, resolution, etc */ 404{ 405 fsError rep; 406 int extralen = 0; 407 408 switch (error) { 409 case FSBadFormat: 410 extralen = SIZEOF(fsBitmapFormat); 411 break; 412 case FSBadFont: 413 case FSBadAccessContext: 414 case FSBadIDChoice: 415 case FSBadEventMask: 416 if (data) { 417 if (client->swapped) 418 SwapLongs((long *) data, 1); 419 extralen = 4; 420 } 421 break; 422 case FSBadRange: 423 extralen = SIZEOF(fsRange); 424 break; 425 case FSBadResolution: 426 if (data) { 427 if (client->swapped) 428 SwapShorts((short *) data, 1); 429 /* note sneaky hack */ 430 rep.pad = *(CARD16 *) data; 431 data = (char *)data + 2; 432 extralen = 4; 433 } 434 break; 435 case FSBadLength: 436 if (data) { 437 if (client->swapped) 438 SwapLongs((long *) data, 1); 439 extralen = 4; 440 } 441 break; 442 default: 443 /* nothing else to send */ 444 break; 445 } 446 447 rep.type = FS_Error; 448 rep.sequenceNumber = client->sequence; 449 rep.request = error; 450 rep.major_opcode = ((fsReq *) client->requestBuffer)->reqType; 451 rep.minor_opcode = MinorOpcodeOfRequest(client), 452 rep.timestamp = GetTimeInMillis(); 453 rep.length = (SIZEOF(fsError) + extralen) >> 2; 454 455 WriteErrorToClient(client, &rep); 456 457 if (extralen) 458 WriteToClient(client, extralen, (char *) data); 459} 460 461/* ARGSUSED */ 462int 463ProcBadRequest(ClientPtr client) 464{ 465 SendErrToClient(client, FSBadRequest, NULL); 466 return FSBadRequest; 467} 468 469int 470ProcNoop(ClientPtr client) 471{ 472 REQUEST(fsReq); 473 REQUEST_AT_LEAST_SIZE(fsReq); 474 475 return client->noClientException; 476} 477 478int 479ProcListCatalogues(ClientPtr client) 480{ 481 int len, 482 num; 483 char *catalogues; 484 fsListCataloguesReply rep; 485 486 REQUEST(fsListCataloguesReq); 487 REQUEST_AT_LEAST_SIZE(fsListCataloguesReq); 488 489 num = ListCatalogues((char *)stuff + SIZEOF(fsListCataloguesReq), 490 stuff->nbytes, stuff->maxNames, 491 &catalogues, &len); 492 rep.type = FS_Reply; 493 rep.num_replies = 0; 494 rep.num_catalogues = num; 495 rep.sequenceNumber = client->sequence; 496 rep.length = (SIZEOF(fsListCataloguesReply) + len + 3) >> 2; 497 498 WriteReplyToClient(client, SIZEOF(fsListCataloguesReply), &rep); 499 (void) WriteToClient(client, len, (char *) catalogues); 500 fsfree((char *) catalogues); 501 return client->noClientException; 502} 503 504int 505ProcSetCatalogues(ClientPtr client) 506{ 507 char *new_cat; 508 int err, 509 len; 510 int num; 511 512 REQUEST(fsSetCataloguesReq); 513 REQUEST_AT_LEAST_SIZE(fsSetCataloguesReq); 514 515 if (stuff->num_catalogues == 0) { 516 /* use the default */ 517 num = ListCatalogues("*", 1, 10000, &new_cat, &len); 518 } else { 519 num = stuff->num_catalogues; 520 err = ValidateCatalogues(&num, (char *)stuff + SIZEOF(fsSetCataloguesReq)); 521 if (err == FSSuccess) { 522 len = (stuff->length << 2) - SIZEOF(fsSetCataloguesReq); 523 new_cat = (char *) fsalloc(len); 524 if (!new_cat) 525 return FSBadAlloc; 526 memmove( new_cat, (char *)stuff + SIZEOF(fsSetCataloguesReq), len); 527 } else { 528 SendErrToClient(client, err, (pointer) &num); 529 return err; 530 } 531 } 532 if (client->catalogues) 533 fsfree((char *) client->catalogues); 534 client->catalogues = new_cat; 535 client->num_catalogues = num; 536 return client->noClientException; 537} 538 539int 540ProcGetCatalogues(ClientPtr client) 541{ 542 int len, 543 i, 544 size; 545 char *cp; 546 fsGetCataloguesReply rep; 547 548 REQUEST(fsGetCataloguesReq); 549 REQUEST_AT_LEAST_SIZE(fsGetCataloguesReq); 550 551 for (i = 0, len = 0, cp = client->catalogues; 552 i < client->num_catalogues; i++) { 553 size = *cp++; 554 len += size + 1; /* str length + size byte */ 555 cp += size; 556 } 557 558 rep.type = FS_Reply; 559 rep.num_catalogues = client->num_catalogues; 560 rep.sequenceNumber = client->sequence; 561 rep.length = (SIZEOF(fsGetCataloguesReply) + len + 3) >> 2; 562 563 WriteReplyToClient(client, SIZEOF(fsGetCataloguesReply), &rep); 564 (void) WriteToClient(client, len, client->catalogues); 565 566 return client->noClientException; 567} 568 569int 570ProcCreateAC(ClientPtr client) 571{ 572 fsCreateACReply rep; 573 AuthPtr acp; 574 AuthContextPtr authp; 575 int accept, 576 i, 577 err, 578 index, 579 size; 580 char *ad; 581 char *auth_data; 582 583 REQUEST(fsCreateACReq); 584 REQUEST_AT_LEAST_SIZE(fsCreateACReq); 585 586 authp = (AuthContextPtr) LookupIDByType(client->index, stuff->acid, 587 RT_AUTHCONT); 588 if (authp) { 589 int aligned_acid = stuff->acid; 590 SendErrToClient(client, FSBadIDChoice, (pointer) &aligned_acid); 591 return FSBadIDChoice; 592 } 593 acp = 0; 594 if (stuff->num_auths) 595 { 596 acp = (AuthPtr) ALLOCATE_LOCAL(stuff->num_auths * sizeof(AuthRec)); 597 if (!acp) { 598 SendErrToClient(client, FSBadAlloc, (pointer) 0); 599 return FSBadAlloc; 600 } 601 } 602 /* build up a list of the stuff */ 603 for (i = 0, ad = (char *)stuff + SIZEOF(fsCreateACReq); 604 i < (int)stuff->num_auths; i++) { 605 if (ad - (char *)stuff + SIZEOF(fsCreateACReq) > 606 (stuff->length << 2) - 4) { 607 int lengthword = stuff->length; 608 609 SendErrToClient(client, FSBadLength, (pointer)&lengthword); 610 return (FSBadLength); 611 } 612 /* copy carefully in case data is not aligned */ 613 acp[i].namelen = (((unsigned char *)ad)[0] << 8) + 614 ((unsigned char *)ad)[1]; 615 ad += 2; 616 acp[i].datalen = (((unsigned char *)ad)[0] << 8) + 617 ((unsigned char *)ad)[1]; 618 ad += 2; 619 acp[i].name = (char *) ad; 620 ad += acp[i].namelen; 621 acp[i].data = (char *) ad; 622 ad += acp[i].datalen; 623 } 624 if (!(int)stuff->num_auths) 625 ad += 4; 626 if (ad - (char *)stuff > (stuff->length << 2)) { 627 int lengthword = stuff->length; 628 629 SendErrToClient(client, FSBadLength, (pointer)&lengthword); 630 return (FSBadLength); 631 } 632 633/* XXX needs work for AuthContinue */ 634 index = stuff->num_auths; 635 err = CheckClientAuthorization(client, acp, &accept, &index, &size, 636 &auth_data); 637 638 if (err != FSSuccess) { 639 SendErrToClient(client, err, (pointer) 0); 640 if (acp) 641 DEALLOCATE_LOCAL(acp); 642 return err; 643 } 644 authp = (AuthContextPtr) fsalloc(sizeof(AuthContextRec)); 645 if (!authp) { 646 goto alloc_failure; 647 } 648 authp->authname = 0; 649 authp->authdata = 0; 650 if (index > 0) 651 { 652 authp->authname = (char *) fsalloc(acp[index - 1].namelen + 1); 653 authp->authdata = (char *) fsalloc(acp[index - 1].datalen + 1); 654 if (!authp->authname || !authp->authdata) { 655 fsfree((char *) authp->authname); 656 fsfree((char *) authp->authdata); 657 fsfree((char *) authp); 658 goto alloc_failure; 659 } 660 memmove( authp->authname, acp[index - 1].name, acp[index - 1].namelen); 661 memmove( authp->authdata, acp[index - 1].data, acp[index - 1].datalen); 662 } 663 else 664 size = 0; 665 authp->acid = stuff->acid; 666 if (!AddResource(client->index, stuff->acid, RT_AUTHCONT,(pointer) authp)) 667 { 668alloc_failure: 669 SendErrToClient(client, FSBadAlloc, (pointer) 0); 670 if (acp) 671 DEALLOCATE_LOCAL(acp); 672 return FSBadAlloc; 673 } 674 DEALLOCATE_LOCAL(acp); 675 rep.type = FS_Reply; 676 rep.status = accept; 677 rep.auth_index = index; 678 rep.sequenceNumber = client->sequence; 679 rep.length = (SIZEOF(fsCreateACReply) + size) >> 2; 680 681 WriteReplyToClient(client, SIZEOF(fsCreateACReply), &rep); 682 if (size) 683 (void) WriteToClient(client, size, auth_data); 684 685 return client->noClientException; 686} 687 688/* ARGSUSED */ 689int 690DeleteAuthCont (pointer value, FSID id) 691{ 692 AuthContextPtr authp = (AuthContextPtr) value; 693 694 if (authp->authname) 695 fsfree (authp->authname); 696 if (authp->authdata) 697 fsfree (authp->authdata); 698 fsfree (authp); 699 return 1; 700} 701 702int 703ProcFreeAC(ClientPtr client) 704{ 705 AuthContextPtr authp; 706 707 REQUEST(fsFreeACReq); 708 REQUEST_AT_LEAST_SIZE(fsFreeACReq); 709 authp = (AuthContextPtr) LookupIDByType(client->index, stuff->id, 710 RT_AUTHCONT); 711 if (!authp) { 712 int aligned_id = stuff->id; 713 SendErrToClient(client, FSBadIDChoice, (pointer) &aligned_id); 714 return FSBadIDChoice; 715 } 716 if (client->auth == authp) 717 client->auth = client->default_auth; 718 FreeResource(client->index, stuff->id, RT_NONE); 719 return client->noClientException; 720} 721 722int 723ProcSetAuthorization(ClientPtr client) 724{ 725 AuthContextPtr acp; 726 727 REQUEST(fsSetAuthorizationReq); 728 REQUEST_AT_LEAST_SIZE(fsSetAuthorizationReq); 729 acp = (AuthContextPtr) LookupIDByType(client->index, stuff->id, 730 RT_AUTHCONT); 731 if (!acp) { 732 int aligned_id = stuff->id; 733 SendErrToClient(client, FSBadIDChoice, (pointer) &aligned_id); 734 return FSBadIDChoice; 735 } 736 client->auth = acp; /* XXX does this need a refcount? */ 737 return client->noClientException; 738} 739 740int 741ProcSetResolution(ClientPtr client) 742{ 743 fsResolution *new_res; 744 745 REQUEST(fsSetResolutionReq); 746 REQUEST_AT_LEAST_SIZE(fsSetResolutionReq); 747 748 if ((stuff->length << 2) - SIZEOF(fsSetResolutionReq) < 749 stuff->num_resolutions * SIZEOF(fsResolution)) { 750 int lengthword = stuff->length; 751 752 SendErrToClient(client, FSBadLength, &lengthword); 753 return FSBadLength; 754 } 755 new_res = (fsResolution *) 756 fsalloc(SIZEOF(fsResolution) * stuff->num_resolutions); 757 if (!new_res) { 758 SendErrToClient(client, FSBadAlloc, NULL); 759 return FSBadAlloc; 760 } 761 fsfree((char *) client->resolutions); 762 memmove( (char *) new_res, (char *)stuff + SIZEOF(fsSetResolutionReq), 763 (stuff->num_resolutions * SIZEOF(fsResolution))); 764 client->resolutions = new_res; 765 client->num_resolutions = stuff->num_resolutions; 766 767 return client->noClientException; 768} 769 770int 771ProcGetResolution(ClientPtr client) 772{ 773 fsGetResolutionReply reply; 774 775 REQUEST(fsReq); 776 REQUEST_AT_LEAST_SIZE(fsReq); 777 778 if ((stuff->length << 2) - SIZEOF(fsResolution) < client->num_resolutions * 779 sizeof(fsResolution)) { 780 int lengthword = stuff->length; 781 782 SendErrToClient(client, FSBadLength, &lengthword); 783 return FSBadLength; 784 } 785 reply.type = FS_Reply; 786 reply.num_resolutions = client->num_resolutions; 787 reply.sequenceNumber = client->sequence; 788 reply.length = (SIZEOF(fsGetResolutionReply) + 789 client->num_resolutions * SIZEOF(fsResolution)) >> 2; 790 791 WriteReplyToClient(client, SIZEOF(fsGetResolutionReply), &reply); 792 if (client->swapped) 793 client->pSwapReplyFunc = CopySwap16Write; 794 795 WriteSwappedDataToClient(client, 796 (client->num_resolutions * SIZEOF(fsResolution)), (short *)client->resolutions); 797 798 return client->noClientException; 799} 800 801int 802ProcListFonts(ClientPtr client) 803{ 804 REQUEST(fsListFontsReq); 805 REQUEST_FIXED_SIZE(fsListFontsReq, stuff->nbytes); 806 807 return ListFonts(client, stuff->nbytes, 808 (unsigned char *)stuff + SIZEOF(fsListFontsReq), 809 stuff->maxNames); 810} 811 812int 813ProcListFontsWithXInfo(ClientPtr client) 814{ 815 REQUEST(fsListFontsWithXInfoReq); 816 REQUEST_FIXED_SIZE(fsListFontsWithXInfoReq, stuff->nbytes); 817 818 return StartListFontsWithInfo(client, stuff->nbytes, 819 (unsigned char *)stuff + SIZEOF(fsListFontsWithXInfoReq), stuff->maxNames); 820} 821 822int 823ProcOpenBitmapFont(ClientPtr client) 824{ 825 FontPtr pfont; 826 int nbytes, 827 err; 828 unsigned char *fname; 829 830 REQUEST(fsOpenBitmapFontReq); 831 fname = (unsigned char *)stuff + SIZEOF(fsOpenBitmapFontReq); 832 nbytes = *fname++; 833 834 REQUEST_FIXED_SIZE(fsOpenBitmapFontReq, (nbytes + 1)); 835 836 pfont = (FontPtr) LookupIDByType(client->index, stuff->fid, RT_FONT); 837 if (pfont) { 838 int aligned_fid = stuff->fid; 839 SendErrToClient(client, FSBadIDChoice, (pointer) &aligned_fid); 840 return FSBadIDChoice; 841 } 842 if (stuff->format_hint != 0 && 843 stuff->format_hint & ~ALL_FORMAT_BITS) { 844 int aligned_format_hint = stuff->format_hint; 845 SendErrToClient(client, FSBadFormat, (pointer) &aligned_format_hint); 846 return FSBadFormat; 847 } 848 if (stuff->format_mask & ~ALL_FORMAT_MASK_BITS) { 849 int aligned_format_mask = stuff->format_mask; 850 SendErrToClient(client, FSBadFormat, (pointer) &aligned_format_mask); 851 return FSBadFormat; 852 } 853 err = OpenFont(client, stuff->fid, stuff->format_hint, stuff->format_mask, 854 nbytes, (char *) fname); 855 856 if (err == FSSuccess) { 857 return client->noClientException; 858 } else { 859 return err; 860 } 861} 862 863int 864ProcQueryXInfo(ClientPtr client) 865{ 866 ClientFontPtr cfp; 867 int err, 868 lendata; 869 fsQueryXInfoReply reply; 870 fsPropInfo *prop_info; 871 872 REQUEST(fsQueryXInfoReq); 873 874 REQUEST_AT_LEAST_SIZE(fsQueryXInfoReq); 875 876 cfp = (ClientFontPtr) LookupIDByType(client->index, stuff->id, RT_FONT); 877 if (!cfp) { 878 int aligned_id = stuff->id; 879 SendErrToClient(client, FSBadFont, (pointer) &aligned_id); 880 return FSBadFont; 881 } 882 reply.type = FS_Reply; 883 reply.sequenceNumber = client->sequence; 884 885 /* get the header */ 886 fsPack_XFontInfoHeader(&cfp->font->info, &reply, client->major_version); 887 err = convert_props(&cfp->font->info, &prop_info); 888 889 switch (err) 890 { 891 case Successful: 892 break; 893 case AllocError: 894 SendErrToClient(client, FSBadAlloc, (pointer) 0); 895 return err; 896 default: 897 ErrorF("ProcQueryXInfo: unexpected return val %d from convert_props\n", 898 err); 899 SendErrToClient(client, FSBadImplementation, (pointer) 0); 900 return err; 901 } 902 lendata = SIZEOF(fsPropInfo) + 903 prop_info->num_offsets * SIZEOF(fsPropOffset) + 904 prop_info->data_len; 905 906 reply.length = (SIZEOF(fsQueryXInfoReply) + lendata + 3) >> 2; 907 WriteReplyToClient(client, SIZEOF(fsQueryXInfoReply), &reply); 908 909 if (client->swapped) 910 SwapPropInfo(prop_info); 911 (void) WriteToClient(client, lendata, (char *) prop_info); 912 913 fsfree((char *) prop_info); 914 return client->noClientException; 915} 916 917int 918ProcQueryXExtents(ClientPtr client) 919{ 920 ClientFontPtr cfp; 921 int err; 922 int item_size; 923 924 REQUEST(fsQueryXExtents8Req); 925 926 REQUEST_AT_LEAST_SIZE(fsQueryXExtents8Req); 927 928 cfp = (ClientFontPtr) LookupIDByType(client->index, stuff->fid, RT_FONT); 929 if (!cfp) { 930 int aligned_fid = stuff->fid; 931 SendErrToClient(client, FSBadFont, (pointer) &aligned_fid); 932 return FSBadFont; 933 } 934 item_size = (stuff->reqType == FS_QueryXExtents8) ? 1 : 2; 935 936 if (stuff->num_ranges > 937 ((stuff->length << 2) - SIZEOF(fsQueryXExtents8Req))/item_size) { 938 int num_ranges = stuff->num_ranges; 939 SendErrToClient(client, FSBadLength, (pointer)&num_ranges); 940 return FSBadLength; 941 } 942 943 /* get the extents */ 944 err = QueryExtents(client, cfp, item_size, 945 stuff->num_ranges, stuff->range, 946 (char *)stuff + SIZEOF(fsQueryXExtents8Req)); 947 948 if (err != FSSuccess) { 949 return err; 950 } else 951 return client->noClientException; 952} 953 954int 955ProcQueryXBitmaps(ClientPtr client) 956{ 957 ClientFontPtr cfp; 958 int err; 959 int item_size; 960 961 REQUEST(fsQueryXBitmaps8Req); 962 963 REQUEST_AT_LEAST_SIZE(fsQueryXBitmaps8Req); 964 965 cfp = (ClientFontPtr) LookupIDByType(client->index, stuff->fid, RT_FONT); 966 if (!cfp) { 967 int aligned_fid = stuff->fid; 968 SendErrToClient(client, FSBadFont, (pointer) &aligned_fid); 969 return FSBadFont; 970 } 971 if (stuff->format & ~ALL_FORMAT_BITS) { 972 int aligned_format = stuff->format; 973 SendErrToClient(client, FSBadFormat, (pointer) &aligned_format); 974 return FSBadFormat; 975 } 976 assert((stuff->reqType == FS_QueryXBitmaps8) || (stuff->reqType == FS_QueryXBitmaps16)); 977 item_size = (stuff->reqType == FS_QueryXBitmaps8) ? 1 : 2; 978 979 if (stuff->num_ranges > 980 ((stuff->length << 2) - SIZEOF(fsQueryXBitmaps8Req))/item_size) { 981 int num_ranges = stuff->num_ranges; 982 SendErrToClient(client, FSBadLength, (pointer)&num_ranges); 983 return FSBadLength; 984 } 985 /* get the glyphs */ 986 err = QueryBitmaps(client, cfp, item_size, stuff->format, 987 stuff->num_ranges, stuff->range, 988 (char *)stuff + SIZEOF(fsQueryXBitmaps8Req)); 989 990 if (err != FSSuccess) { 991 return err; 992 } else { 993 return client->noClientException; 994 } 995} 996 997int 998ProcCloseFont(ClientPtr client) 999{ 1000 ClientFontPtr cfp; 1001 1002 REQUEST(fsResourceReq); 1003 1004 REQUEST_SIZE_MATCH(fsResourceReq); 1005 cfp = (ClientFontPtr) LookupIDByType(client->index, stuff->id, RT_FONT); 1006 if (cfp) { 1007 FreeResource(client->index, stuff->id, RT_NONE); 1008 return client->noClientException; 1009 } else { 1010 int aligned_id = stuff->id; 1011 SendErrToClient(client, FSBadFont, (pointer) &aligned_id); 1012 return FSBadFont; 1013 } 1014} 1015 1016void 1017DoCloseDownClient(ClientPtr client) 1018{ 1019 if (client->clientGone != CLIENT_GONE) { 1020 DeleteClientFontStuff(client); 1021 client->clientGone = CLIENT_GONE; 1022 CloseDownConnection(client); 1023 --nClients; 1024 } 1025 1026 if (ClientIsAsleep(client)) 1027 ClientSignal((pointer)client); 1028 else 1029 { 1030 FreeClientResources(client); 1031 if (client->index < nextFreeClientID) 1032 nextFreeClientID = client->index; 1033 clients[client->index] = NullClient; 1034#ifdef DebugConnectionTranslation 1035 CheckFileNumbers(); 1036#endif /* DebugConnectionTranslation */ 1037 1038#ifdef NOTYET 1039 /* reset server when last client goes away */ 1040 if (client->requestVector != InitialVector && nClients == 0) 1041 dispatchException |= DE_RESET; 1042#endif 1043 1044 if (currentClient == client) 1045 currentClient = serverClient; 1046 fsfree(client); 1047 1048#ifdef DEBUG 1049 fprintf(stderr, "Shut down client\n"); 1050#endif 1051 1052 while (!clients[currentMaxClients - 1]) 1053 currentMaxClients--; 1054 } 1055} 1056 1057static void 1058kill_all_clients(void) 1059{ 1060 int i; 1061 1062 for (i = MINCLIENT; i < currentMaxClients; i++) { 1063 if (clients[i]) 1064 CloseDownClient(clients[i]); 1065 } 1066} 1067 1068void 1069InitProcVectors(void) 1070{ 1071 int i; 1072 1073 for (i = 0; i < NUM_PROC_VECTORS; i++) { 1074 if (!ProcVector[i]) { 1075 ProcVector[i] = SwappedProcVector[i] = ProcBadRequest; 1076 ReplySwapVector[i] = (ReplySwapFunc)NotImplemented; 1077 } 1078 } 1079 for (i = FSLASTEvent; i < NUM_EVENT_VECTORS; i++) { 1080 EventSwapVector[i] = (EventSwapFunc)NotImplemented; 1081 } 1082} 1083 1084void 1085InitClient( 1086 ClientPtr client, 1087 int i, 1088 pointer ospriv) 1089{ 1090 client->index = i; 1091 client->sequence = 0; 1092 client->last_request_time = GetTimeInMillis(); 1093 client->clientGone = CLIENT_ALIVE; 1094 client->noClientException = FSSuccess; 1095 client->requestVector = InitialVector; 1096 client->osPrivate = ospriv; 1097 client->swapped = FALSE; 1098 1099 client->auth = (AuthContextPtr) 0; 1100 client->catalogues = NULL; 1101 client->num_catalogues = 0; 1102 client->num_resolutions = 0; 1103 client->resolutions = (fsResolution *) 0; 1104 client->eventmask = (Mask) 0; 1105} 1106 1107ClientPtr 1108NextAvailableClient(pointer ospriv) 1109{ 1110 int i; 1111 ClientPtr client; 1112 fsFakeReq data; 1113 1114 i = nextFreeClientID; 1115 if (i == MaxClients) 1116 return NullClient; 1117 1118 clients[i] = client = (ClientPtr) fsalloc(sizeof(ClientRec)); 1119 if (!client) 1120 return NullClient; 1121 1122 InitClient(client, i, ospriv); 1123 1124 if (!InitClientResources(client)) { 1125 fsfree(client); 1126 return NullClient; 1127 } 1128 data.reqType = 1; 1129 data.length = (sizeof(fsFakeReq) + SIZEOF(fsConnClientPrefix)) >> 2; 1130 if (!InsertFakeRequest(client, (char *) &data, sizeof(fsFakeReq))) { 1131 FreeClientResources(client); 1132 fsfree(client); 1133 return NullClient; 1134 } 1135 if (i == currentMaxClients) 1136 currentMaxClients++; 1137 while ((nextFreeClientID < MAXCLIENTS) && clients[nextFreeClientID]) 1138 nextFreeClientID++; 1139 1140 /* if we've maxed out, try to clone */ 1141 if (nextFreeClientID == MaxClients) { 1142 CloneMyself(); 1143 } 1144 return client; 1145} 1146 1147void 1148MarkClientException(ClientPtr client) 1149{ 1150 client->noClientException = -2; 1151} 1152