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