dispatch.c revision 34f90d55
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 return (FSBadLength); 257 } 258 /* copy carefully in case wire data is not aligned */ 259 client_auth[i].namelen = (((unsigned char *)ad)[0] << 8) + 260 ((unsigned char *)ad)[1]; 261 ad += 2; 262 client_auth[i].datalen = (((unsigned char *)ad)[0] << 8) + 263 ((unsigned char *)ad)[1]; 264 ad += 2; 265 client_auth[i].name = (char *) ad; 266 ad += client_auth[i].namelen; 267 client_auth[i].data = (char *) ad; 268 ad += client_auth[i].datalen; 269 } 270 if (!(int)prefix->num_auths) 271 ad += 4; 272 if (ad - (char *)auth_data > (stuff->length << 2)) { 273 int lengthword = stuff->length; 274 275 SendErrToClient(client, FSBadLength, (pointer)&lengthword); 276 return (FSBadLength); 277 } 278 279 num_alts = ListAlternateServers(&altservers); 280 for (i = 0, altlen = 0; i < num_alts; i++) { 281 /* subset + len + namelen + pad */ 282 altlen += (2 + altservers[i].namelen + 3) >> 2; 283 } 284 285 auth_index = prefix->num_auths; 286 client->auth_generation = 0; 287 ret = CheckClientAuthorization(client, client_auth, 288 &auth_accept, &auth_index, &auth_len, &server_auth_data); 289 if (auth_index > 0) 290 { 291 AuthContextPtr authp; 292 authp = (AuthContextPtr) fsalloc(sizeof(AuthContextRec)); 293 if (!authp) { 294 SendErrToClient(client, FSBadAlloc, (pointer) 0); 295 return FSBadAlloc; 296 } 297 authp->authname = 298 (char *) fsalloc(client_auth[auth_index - 1].namelen + 1); 299 authp->authdata = 300 (char *) fsalloc(client_auth[auth_index - 1].datalen + 1); 301 if (!authp->authname || !authp->authdata) { 302 fsfree((char *) authp->authname); 303 fsfree((char *) authp->authdata); 304 fsfree((char *) authp); 305 SendErrToClient(client, FSBadAlloc, (pointer) 0); 306 return FSBadAlloc; 307 } 308 memmove( authp->authname, client_auth[auth_index - 1].name, 309 client_auth[auth_index - 1].namelen); 310 memmove( authp->authdata, client_auth[auth_index - 1].data, 311 client_auth[auth_index - 1].datalen); 312 /* Save it with a zero resource id... subsequent 313 SetAuthorizations of None will find it. And it will be freed 314 by FreeClientResources when the connection closes. */ 315 if (!AddResource(client->index, 0, RT_AUTHCONT,(pointer) authp)) 316 { 317 fsfree((char *) authp->authname); 318 fsfree((char *) authp->authdata); 319 fsfree((char *) authp); 320 SendErrToClient(client, FSBadAlloc, (pointer) 0); 321 return FSBadAlloc; 322 } 323 client->auth = client->default_auth = authp; 324 } 325 else 326 client->auth = client->default_auth = (AuthContextPtr)0; 327 328 DEALLOCATE_LOCAL(client_auth); 329 330 if (ret != FSSuccess) { 331 SendErrToClient(client, FSBadAlloc, (pointer) 0); 332 return FSBadAlloc; 333 } 334 else { 335 fsConnSetup csp = { 336 .status = auth_accept, 337 /* we implement backwards compatibility for version 1.0 */ 338 .major_version = (client->major_version == 1) ? 339 client->major_version : FS_PROTOCOL, 340 .minor_version = FS_PROTOCOL_MINOR, 341 .num_alternates = num_alts, 342 .alternate_len = altlen, 343 .auth_len = auth_len >> 2, 344 .auth_index = auth_index 345 }; 346 if (client->swapped) { 347 WriteSConnSetup(client, &csp); 348 } else { 349 (void) WriteToClient(client, SIZEOF(fsConnSetup), (char *) &csp); 350 } 351 } 352 353 /* send the alternates info */ 354 for (i = 0; i < num_alts; i++) { 355 char tmp[258]; 356 357 /* WriteToClient pads, so we have to fake some things */ 358 tmp[0] = altservers[i].subset; 359 tmp[1] = altservers[i].namelen; 360 memmove( (char *) &tmp[2], altservers[i].name, altservers[i].namelen); 361 (void) WriteToClient(client, altservers[i].namelen + 2, tmp); 362 } 363 364 if (auth_len) 365 (void) WriteToClient(client, auth_len, (char *) server_auth_data); 366 367 if (auth_accept != AuthSuccess) { 368 nClients--; 369 return (client->noClientException = -2); 370 } 371 client->requestVector = client->swapped ? SwappedProcVector : ProcVector; 372 client->sequence = 0; 373 if (client->swapped) 374 (void) WriteSConnectionInfo(client, ConnInfoLen, ConnectionInfo); 375 else 376 (void) WriteToClient(client, ConnInfoLen, ConnectionInfo); 377 378#ifdef DEBUG 379 fprintf(stderr, "Establishing new connection\n"); 380#endif 381 382 return client->noClientException; 383} 384 385/* 386 * NOTE -- the incoming data may be mangled 387 */ 388 389void 390DoSendErrToClient( 391 ClientPtr client, 392 int error, 393 pointer data) /* resource id, format, resolution, etc */ 394{ 395 fsError rep = { 396 .type = FS_Error, 397 .request = error, 398 .sequenceNumber = client->sequence, 399 .timestamp = GetTimeInMillis(), 400 .major_opcode = ((fsReq *) client->requestBuffer)->reqType, 401 .minor_opcode = MinorOpcodeOfRequest(client) 402 }; 403 int extralen = 0; 404 405 switch (error) { 406 case FSBadFormat: 407 extralen = SIZEOF(fsBitmapFormat); 408 break; 409 case FSBadFont: 410 case FSBadAccessContext: 411 case FSBadIDChoice: 412 case FSBadEventMask: 413 if (data) { 414 if (client->swapped) 415 SwapLongs((long *) data, 1); 416 extralen = 4; 417 } 418 break; 419 case FSBadRange: 420 extralen = SIZEOF(fsRange); 421 break; 422 case FSBadResolution: 423 if (data) { 424 if (client->swapped) 425 SwapShorts((short *) data, 1); 426 /* note sneaky hack */ 427 rep.pad = *(CARD16 *) data; 428 data = (char *)data + 2; 429 extralen = 4; 430 } 431 break; 432 case FSBadLength: 433 if (data) { 434 if (client->swapped) 435 SwapLongs((long *) data, 1); 436 extralen = 4; 437 } 438 break; 439 default: 440 /* nothing else to send */ 441 break; 442 } 443 444 rep.length = (SIZEOF(fsError) + extralen) >> 2; 445 446 WriteErrorToClient(client, &rep); 447 448 if (extralen) 449 WriteToClient(client, extralen, (char *) data); 450} 451 452/* ARGSUSED */ 453int 454ProcBadRequest(ClientPtr client) 455{ 456 SendErrToClient(client, FSBadRequest, NULL); 457 return FSBadRequest; 458} 459 460int 461ProcNoop(ClientPtr client) 462{ 463 REQUEST(fsReq); 464 REQUEST_AT_LEAST_SIZE(fsReq); 465 466 return client->noClientException; 467} 468 469int 470ProcListCatalogues(ClientPtr client) 471{ 472 int len, 473 num; 474 char *catalogues; 475 fsListCataloguesReply rep = { 476 .type = FS_Reply, 477 .sequenceNumber = client->sequence, 478 .num_replies = 0 479 }; 480 481 REQUEST(fsListCataloguesReq); 482 REQUEST_AT_LEAST_SIZE(fsListCataloguesReq); 483 484 num = ListCatalogues((char *)stuff + SIZEOF(fsListCataloguesReq), 485 stuff->nbytes, stuff->maxNames, 486 &catalogues, &len); 487 rep.num_catalogues = num; 488 rep.length = (SIZEOF(fsListCataloguesReply) + len + 3) >> 2; 489 490 WriteReplyToClient(client, SIZEOF(fsListCataloguesReply), &rep); 491 (void) WriteToClient(client, len, (char *) catalogues); 492 fsfree((char *) catalogues); 493 return client->noClientException; 494} 495 496int 497ProcSetCatalogues(ClientPtr client) 498{ 499 char *new_cat; 500 int err, 501 len; 502 int num; 503 504 REQUEST(fsSetCataloguesReq); 505 REQUEST_AT_LEAST_SIZE(fsSetCataloguesReq); 506 507 if (stuff->num_catalogues == 0) { 508 /* use the default */ 509 num = ListCatalogues("*", 1, 10000, &new_cat, &len); 510 } else { 511 num = stuff->num_catalogues; 512 err = ValidateCatalogues(&num, (char *)stuff + SIZEOF(fsSetCataloguesReq)); 513 if (err == FSSuccess) { 514 len = (stuff->length << 2) - SIZEOF(fsSetCataloguesReq); 515 new_cat = (char *) fsalloc(len); 516 if (!new_cat) 517 return FSBadAlloc; 518 memmove( new_cat, (char *)stuff + SIZEOF(fsSetCataloguesReq), len); 519 } else { 520 SendErrToClient(client, err, (pointer) &num); 521 return err; 522 } 523 } 524 if (client->catalogues) 525 fsfree((char *) client->catalogues); 526 client->catalogues = new_cat; 527 client->num_catalogues = num; 528 return client->noClientException; 529} 530 531int 532ProcGetCatalogues(ClientPtr client) 533{ 534 int len, 535 i, 536 size; 537 char *cp; 538 539 REQUEST(fsGetCataloguesReq); 540 REQUEST_AT_LEAST_SIZE(fsGetCataloguesReq); 541 542 for (i = 0, len = 0, cp = client->catalogues; 543 i < client->num_catalogues; i++) { 544 size = *cp++; 545 len += size + 1; /* str length + size byte */ 546 cp += size; 547 } 548 549 { 550 fsGetCataloguesReply rep = { 551 .type = FS_Reply, 552 .num_catalogues = client->num_catalogues, 553 .sequenceNumber = client->sequence, 554 .length = (SIZEOF(fsGetCataloguesReply) + len + 3) >> 2 555 }; 556 557 WriteReplyToClient(client, SIZEOF(fsGetCataloguesReply), &rep); 558 } 559 (void) WriteToClient(client, len, client->catalogues); 560 561 return client->noClientException; 562} 563 564int 565ProcCreateAC(ClientPtr client) 566{ 567 AuthPtr acp; 568 AuthContextPtr authp; 569 int accept, 570 i, 571 err, 572 index, 573 size; 574 char *ad; 575 char *auth_data; 576 577 REQUEST(fsCreateACReq); 578 REQUEST_AT_LEAST_SIZE(fsCreateACReq); 579 580 authp = (AuthContextPtr) LookupIDByType(client->index, stuff->acid, 581 RT_AUTHCONT); 582 if (authp) { 583 int aligned_acid = stuff->acid; 584 SendErrToClient(client, FSBadIDChoice, (pointer) &aligned_acid); 585 return FSBadIDChoice; 586 } 587 acp = NULL; 588 if (stuff->num_auths) 589 { 590 acp = (AuthPtr) ALLOCATE_LOCAL(stuff->num_auths * sizeof(AuthRec)); 591 if (!acp) { 592 SendErrToClient(client, FSBadAlloc, (pointer) NULL); 593 return FSBadAlloc; 594 } 595 } 596 /* build up a list of the stuff */ 597 for (i = 0, ad = (char *)stuff + SIZEOF(fsCreateACReq); 598 i < (int)stuff->num_auths; i++) { 599 if (ad - (char *)stuff + SIZEOF(fsCreateACReq) > 600 (stuff->length << 2) - 4) { 601 int lengthword = stuff->length; 602 603 SendErrToClient(client, FSBadLength, (pointer)&lengthword); 604 return (FSBadLength); 605 } 606 /* copy carefully in case data is not aligned */ 607 acp[i].namelen = (((unsigned char *)ad)[0] << 8) + 608 ((unsigned char *)ad)[1]; 609 ad += 2; 610 acp[i].datalen = (((unsigned char *)ad)[0] << 8) + 611 ((unsigned char *)ad)[1]; 612 ad += 2; 613 acp[i].name = (char *) ad; 614 ad += acp[i].namelen; 615 acp[i].data = (char *) ad; 616 ad += acp[i].datalen; 617 } 618 if (ad - (char *)stuff > (stuff->length << 2)) { 619 int lengthword = stuff->length; 620 621 SendErrToClient(client, FSBadLength, (pointer)&lengthword); 622 return (FSBadLength); 623 } 624 625/* XXX needs work for AuthContinue */ 626 index = stuff->num_auths; 627 err = CheckClientAuthorization(client, acp, &accept, &index, &size, 628 &auth_data); 629 630 if (err != FSSuccess) { 631 SendErrToClient(client, err, (pointer) 0); 632 if (acp) 633 DEALLOCATE_LOCAL(acp); 634 return err; 635 } 636 authp = (AuthContextPtr) fsalloc(sizeof(AuthContextRec)); 637 if (!authp) { 638 goto alloc_failure; 639 } 640 authp->authname = NULL; 641 authp->authdata = NULL; 642 if (index > 0) 643 { 644 authp->authname = (char *) fsalloc(acp[index - 1].namelen + 1); 645 authp->authdata = (char *) fsalloc(acp[index - 1].datalen + 1); 646 if (!authp->authname || !authp->authdata) { 647 fsfree((char *) authp->authname); 648 fsfree((char *) authp->authdata); 649 fsfree((char *) authp); 650 goto alloc_failure; 651 } 652 memmove( authp->authname, acp[index - 1].name, acp[index - 1].namelen); 653 memmove( authp->authdata, acp[index - 1].data, acp[index - 1].datalen); 654 } 655 else 656 size = 0; 657 authp->acid = stuff->acid; 658 if (!AddResource(client->index, stuff->acid, RT_AUTHCONT,(pointer) authp)) 659 { 660alloc_failure: 661 SendErrToClient(client, FSBadAlloc, (pointer) 0); 662 if (acp) 663 DEALLOCATE_LOCAL(acp); 664 return FSBadAlloc; 665 } 666 DEALLOCATE_LOCAL(acp); 667 { 668 fsCreateACReply rep = { 669 .type = FS_Reply, 670 .auth_index = index, 671 .sequenceNumber = client->sequence, 672 .status = accept, 673 .length = (SIZEOF(fsCreateACReply) + size) >> 2 674 }; 675 676 WriteReplyToClient(client, SIZEOF(fsCreateACReply), &rep); 677 } 678 if (size) 679 (void) WriteToClient(client, size, auth_data); 680 681 return client->noClientException; 682} 683 684/* ARGSUSED */ 685int 686DeleteAuthCont (pointer value, FSID id) 687{ 688 AuthContextPtr authp = (AuthContextPtr) value; 689 690 if (authp->authname) 691 fsfree (authp->authname); 692 if (authp->authdata) 693 fsfree (authp->authdata); 694 fsfree (authp); 695 return 1; 696} 697 698int 699ProcFreeAC(ClientPtr client) 700{ 701 AuthContextPtr authp; 702 703 REQUEST(fsFreeACReq); 704 REQUEST_AT_LEAST_SIZE(fsFreeACReq); 705 authp = (AuthContextPtr) LookupIDByType(client->index, stuff->id, 706 RT_AUTHCONT); 707 if (!authp) { 708 int aligned_id = stuff->id; 709 SendErrToClient(client, FSBadIDChoice, (pointer) &aligned_id); 710 return FSBadIDChoice; 711 } 712 if (client->auth == authp) 713 client->auth = client->default_auth; 714 FreeResource(client->index, stuff->id, RT_NONE); 715 return client->noClientException; 716} 717 718int 719ProcSetAuthorization(ClientPtr client) 720{ 721 AuthContextPtr acp; 722 723 REQUEST(fsSetAuthorizationReq); 724 REQUEST_AT_LEAST_SIZE(fsSetAuthorizationReq); 725 acp = (AuthContextPtr) LookupIDByType(client->index, stuff->id, 726 RT_AUTHCONT); 727 if (!acp) { 728 int aligned_id = stuff->id; 729 SendErrToClient(client, FSBadIDChoice, (pointer) &aligned_id); 730 return FSBadIDChoice; 731 } 732 client->auth = acp; /* XXX does this need a refcount? */ 733 return client->noClientException; 734} 735 736int 737ProcSetResolution(ClientPtr client) 738{ 739 fsResolution *new_res; 740 741 REQUEST(fsSetResolutionReq); 742 REQUEST_AT_LEAST_SIZE(fsSetResolutionReq); 743 744 if ((stuff->length << 2) - SIZEOF(fsSetResolutionReq) < 745 stuff->num_resolutions * SIZEOF(fsResolution)) { 746 int lengthword = stuff->length; 747 748 SendErrToClient(client, FSBadLength, &lengthword); 749 return FSBadLength; 750 } 751 new_res = (fsResolution *) 752 fsalloc(SIZEOF(fsResolution) * stuff->num_resolutions); 753 if (!new_res) { 754 SendErrToClient(client, FSBadAlloc, NULL); 755 return FSBadAlloc; 756 } 757 fsfree((char *) client->resolutions); 758 memmove( (char *) new_res, (char *)stuff + SIZEOF(fsSetResolutionReq), 759 (stuff->num_resolutions * SIZEOF(fsResolution))); 760 client->resolutions = new_res; 761 client->num_resolutions = stuff->num_resolutions; 762 763 return client->noClientException; 764} 765 766int 767ProcGetResolution(ClientPtr client) 768{ 769 REQUEST(fsReq); 770 REQUEST_AT_LEAST_SIZE(fsReq); 771 772 if ((stuff->length << 2) - SIZEOF(fsResolution) < client->num_resolutions * 773 sizeof(fsResolution)) { 774 int lengthword = stuff->length; 775 776 SendErrToClient(client, FSBadLength, &lengthword); 777 return FSBadLength; 778 } 779 else { 780 fsGetResolutionReply reply = { 781 .type = FS_Reply, 782 .num_resolutions = client->num_resolutions, 783 .sequenceNumber = client->sequence, 784 .length = (SIZEOF(fsGetResolutionReply) + 785 client->num_resolutions * SIZEOF(fsResolution)) >> 2 786 }; 787 788 WriteReplyToClient(client, SIZEOF(fsGetResolutionReply), &reply); 789 } 790 if (client->swapped) 791 client->pSwapReplyFunc = CopySwap16Write; 792 793 WriteSwappedDataToClient(client, 794 (client->num_resolutions * SIZEOF(fsResolution)), (short *)client->resolutions); 795 796 return client->noClientException; 797} 798 799int 800ProcListFonts(ClientPtr client) 801{ 802 REQUEST(fsListFontsReq); 803 REQUEST_FIXED_SIZE(fsListFontsReq, stuff->nbytes); 804 805 return ListFonts(client, stuff->nbytes, 806 (unsigned char *)stuff + SIZEOF(fsListFontsReq), 807 stuff->maxNames); 808} 809 810int 811ProcListFontsWithXInfo(ClientPtr client) 812{ 813 REQUEST(fsListFontsWithXInfoReq); 814 REQUEST_FIXED_SIZE(fsListFontsWithXInfoReq, stuff->nbytes); 815 816 return StartListFontsWithInfo(client, stuff->nbytes, 817 (unsigned char *)stuff + SIZEOF(fsListFontsWithXInfoReq), stuff->maxNames); 818} 819 820int 821ProcOpenBitmapFont(ClientPtr client) 822{ 823 FontPtr pfont; 824 int nbytes, 825 err; 826 unsigned char *fname; 827 828 REQUEST(fsOpenBitmapFontReq); 829 fname = (unsigned char *)stuff + SIZEOF(fsOpenBitmapFontReq); 830 nbytes = *fname++; 831 832 REQUEST_FIXED_SIZE(fsOpenBitmapFontReq, (nbytes + 1)); 833 834 pfont = (FontPtr) LookupIDByType(client->index, stuff->fid, RT_FONT); 835 if (pfont) { 836 int aligned_fid = stuff->fid; 837 SendErrToClient(client, FSBadIDChoice, (pointer) &aligned_fid); 838 return FSBadIDChoice; 839 } 840 if (stuff->format_hint != 0 && 841 stuff->format_hint & ~ALL_FORMAT_BITS) { 842 int aligned_format_hint = stuff->format_hint; 843 SendErrToClient(client, FSBadFormat, (pointer) &aligned_format_hint); 844 return FSBadFormat; 845 } 846 if (stuff->format_mask & ~ALL_FORMAT_MASK_BITS) { 847 int aligned_format_mask = stuff->format_mask; 848 SendErrToClient(client, FSBadFormat, (pointer) &aligned_format_mask); 849 return FSBadFormat; 850 } 851 err = OpenFont(client, stuff->fid, stuff->format_hint, stuff->format_mask, 852 nbytes, (char *) fname); 853 854 if (err == FSSuccess) { 855 return client->noClientException; 856 } else { 857 return err; 858 } 859} 860 861int 862ProcQueryXInfo(ClientPtr client) 863{ 864 ClientFontPtr cfp; 865 int err, 866 lendata; 867 fsQueryXInfoReply reply = { 868 .type = FS_Reply, 869 .sequenceNumber = client->sequence 870 }; 871 fsPropInfo *prop_info; 872 873 REQUEST(fsQueryXInfoReq); 874 875 REQUEST_AT_LEAST_SIZE(fsQueryXInfoReq); 876 877 cfp = (ClientFontPtr) LookupIDByType(client->index, stuff->id, RT_FONT); 878 if (!cfp) { 879 int aligned_id = stuff->id; 880 SendErrToClient(client, FSBadFont, (pointer) &aligned_id); 881 return FSBadFont; 882 } 883 884 /* get the header */ 885 fsPack_XFontInfoHeader(&cfp->font->info, &reply, client->major_version); 886 err = convert_props(&cfp->font->info, &prop_info); 887 888 switch (err) 889 { 890 case Successful: 891 break; 892 case AllocError: 893 SendErrToClient(client, FSBadAlloc, (pointer) 0); 894 return err; 895 default: 896 ErrorF("ProcQueryXInfo: unexpected return val %d from convert_props\n", 897 err); 898 SendErrToClient(client, FSBadImplementation, (pointer) 0); 899 return err; 900 } 901 lendata = SIZEOF(fsPropInfo) + 902 prop_info->num_offsets * SIZEOF(fsPropOffset) + 903 prop_info->data_len; 904 905 reply.length = (SIZEOF(fsQueryXInfoReply) + lendata + 3) >> 2; 906 WriteReplyToClient(client, SIZEOF(fsQueryXInfoReply), &reply); 907 908 if (client->swapped) 909 SwapPropInfo(prop_info); 910 (void) WriteToClient(client, lendata, (char *) prop_info); 911 912 fsfree((char *) prop_info); 913 return client->noClientException; 914} 915 916int 917ProcQueryXExtents(ClientPtr client) 918{ 919 ClientFontPtr cfp; 920 int err; 921 int item_size; 922 923 REQUEST(fsQueryXExtents8Req); 924 925 REQUEST_AT_LEAST_SIZE(fsQueryXExtents8Req); 926 927 cfp = (ClientFontPtr) LookupIDByType(client->index, stuff->fid, RT_FONT); 928 if (!cfp) { 929 int aligned_fid = stuff->fid; 930 SendErrToClient(client, FSBadFont, (pointer) &aligned_fid); 931 return FSBadFont; 932 } 933 item_size = (stuff->reqType == FS_QueryXExtents8) ? 1 : 2; 934 935 if (stuff->num_ranges > 936 ((stuff->length << 2) - SIZEOF(fsQueryXExtents8Req))/item_size) { 937 int num_ranges = stuff->num_ranges; 938 SendErrToClient(client, FSBadLength, (pointer)&num_ranges); 939 return FSBadLength; 940 } 941 942 /* get the extents */ 943 err = QueryExtents(client, cfp, item_size, 944 stuff->num_ranges, stuff->range, 945 (char *)stuff + SIZEOF(fsQueryXExtents8Req)); 946 947 if (err != FSSuccess) { 948 return err; 949 } else 950 return client->noClientException; 951} 952 953int 954ProcQueryXBitmaps(ClientPtr client) 955{ 956 ClientFontPtr cfp; 957 int err; 958 int item_size; 959 960 REQUEST(fsQueryXBitmaps8Req); 961 962 REQUEST_AT_LEAST_SIZE(fsQueryXBitmaps8Req); 963 964 cfp = (ClientFontPtr) LookupIDByType(client->index, stuff->fid, RT_FONT); 965 if (!cfp) { 966 int aligned_fid = stuff->fid; 967 SendErrToClient(client, FSBadFont, (pointer) &aligned_fid); 968 return FSBadFont; 969 } 970 if (stuff->format & ~ALL_FORMAT_BITS) { 971 int aligned_format = stuff->format; 972 SendErrToClient(client, FSBadFormat, (pointer) &aligned_format); 973 return FSBadFormat; 974 } 975 assert((stuff->reqType == FS_QueryXBitmaps8) || (stuff->reqType == FS_QueryXBitmaps16)); 976 item_size = (stuff->reqType == FS_QueryXBitmaps8) ? 1 : 2; 977 978 if (stuff->num_ranges > 979 ((stuff->length << 2) - SIZEOF(fsQueryXBitmaps8Req))/item_size) { 980 int num_ranges = stuff->num_ranges; 981 SendErrToClient(client, FSBadLength, (pointer)&num_ranges); 982 return FSBadLength; 983 } 984 /* get the glyphs */ 985 err = QueryBitmaps(client, cfp, item_size, stuff->format, 986 stuff->num_ranges, stuff->range, 987 (char *)stuff + SIZEOF(fsQueryXBitmaps8Req)); 988 989 if (err != FSSuccess) { 990 return err; 991 } else { 992 return client->noClientException; 993 } 994} 995 996int 997ProcCloseFont(ClientPtr client) 998{ 999 ClientFontPtr cfp; 1000 1001 REQUEST(fsResourceReq); 1002 1003 REQUEST_SIZE_MATCH(fsResourceReq); 1004 cfp = (ClientFontPtr) LookupIDByType(client->index, stuff->id, RT_FONT); 1005 if (cfp) { 1006 FreeResource(client->index, stuff->id, RT_NONE); 1007 return client->noClientException; 1008 } else { 1009 int aligned_id = stuff->id; 1010 SendErrToClient(client, FSBadFont, (pointer) &aligned_id); 1011 return FSBadFont; 1012 } 1013} 1014 1015void 1016DoCloseDownClient(ClientPtr client) 1017{ 1018 if (client->clientGone != CLIENT_GONE) { 1019 DeleteClientFontStuff(client); 1020 client->clientGone = CLIENT_GONE; 1021 CloseDownConnection(client); 1022 --nClients; 1023 } 1024 1025 if (ClientIsAsleep(client)) 1026 ClientSignal((pointer)client); 1027 else 1028 { 1029 FreeClientResources(client); 1030 if (client->index < nextFreeClientID) 1031 nextFreeClientID = client->index; 1032 clients[client->index] = NullClient; 1033#ifdef DebugConnectionTranslation 1034 CheckFileNumbers(); 1035#endif /* DebugConnectionTranslation */ 1036 1037#ifdef NOTYET 1038 /* reset server when last client goes away */ 1039 if (client->requestVector != InitialVector && nClients == 0) 1040 dispatchException |= DE_RESET; 1041#endif 1042 1043 if (currentClient == client) 1044 currentClient = serverClient; 1045 fsfree(client); 1046 1047#ifdef DEBUG 1048 fprintf(stderr, "Shut down client\n"); 1049#endif 1050 1051 while (!clients[currentMaxClients - 1]) 1052 currentMaxClients--; 1053 } 1054} 1055 1056static void 1057kill_all_clients(void) 1058{ 1059 int i; 1060 1061 for (i = MINCLIENT; i < currentMaxClients; i++) { 1062 if (clients[i]) 1063 CloseDownClient(clients[i]); 1064 } 1065} 1066 1067void 1068InitProcVectors(void) 1069{ 1070 int i; 1071 1072 for (i = 0; i < NUM_PROC_VECTORS; i++) { 1073 if (!ProcVector[i]) { 1074 ProcVector[i] = SwappedProcVector[i] = ProcBadRequest; 1075 ReplySwapVector[i] = (ReplySwapFunc)NotImplemented; 1076 } 1077 } 1078 for (i = FSLASTEvent; i < NUM_EVENT_VECTORS; i++) { 1079 EventSwapVector[i] = (EventSwapFunc)NotImplemented; 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