difsutils.c revision 34f90d55
1/* 2 * misc utility routines 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#define XK_LATIN1 52 53#include <difsutils.h> 54 55#include <stdio.h> 56#include <ctype.h> 57#include "misc.h" 58#include "globals.h" 59#include "clientstr.h" 60#include <X11/fonts/fontstruct.h> 61#include <X11/keysymdef.h> 62 63#include "authstr.h" 64#include "auth.h" 65#include "client.h" 66#include "dispatch.h" 67 68static FontResolutionPtr default_resolutions; 69static int num_resolutions; 70static int default_point_size = 120; 71 72AuthContextPtr 73GetClientAuthorization(void) 74{ 75 return currentClient->auth; 76} 77 78void 79SetDefaultPointSize(int ps) 80{ 81 int i; 82 83 default_point_size = ps; 84 for (i = 0; i < num_resolutions; i++) 85 default_resolutions[i].point_size = ps; 86} 87 88int 89SetDefaultResolutions(char *str) 90{ 91 int num, 92 numr = 0, 93 n; 94 char *s; 95 FontResolutionPtr new, 96 nr; 97 int state; 98 99 s = str; 100 while (*s) { /* count commas */ 101 if (*s == ',') 102 numr++; 103 s++; 104 } 105 106 if ((numr % 2) != 1) { /* must be multiple of 2 + 1 */ 107 return FSBadResolution; 108 } 109 numr = (numr + 1) / 2; 110 nr = new = (FontResolutionPtr) fsalloc(sizeof(FontResolutionRec) 111 * numr); 112 if (!new) 113 return FSBadAlloc; 114 s = str; 115 num = 0; 116 state = 0; 117 while (*s) { 118 if (*s == ',') { 119 if (state == 0) { 120 nr->x_resolution = num; 121 state++; 122 } else { 123 state = 0; 124 nr->y_resolution = num; 125 nr->point_size = default_point_size; 126 nr++; 127 } 128 num = 0; 129 s++; 130 continue; 131 } 132 if (!isdigit(*s)) { 133 fsfree((char *) new); 134 return FSBadResolution; 135 } 136 n = *s - '0'; 137 num = num * 10 + n; 138 s++; 139 } 140 141 /* do the last one */ 142 assert(state == 1); 143 nr->y_resolution = num; 144 nr->point_size = default_point_size; 145 146 if (default_resolutions) { 147 fsfree((char *) default_resolutions); 148 } 149 default_resolutions = new; 150 num_resolutions = numr; 151 return FSSuccess; 152} 153 154FontResolutionPtr 155GetClientResolutions(int *num) 156{ 157 /* return the client's if it has them, otherwise the default values */ 158 if (currentClient->num_resolutions) { 159 *num = currentClient->num_resolutions; 160 return (FontResolutionPtr) currentClient->resolutions; 161 } else { 162 *num = num_resolutions; 163 return default_resolutions; 164 } 165} 166 167int 168GetDefaultPointSize(void) 169{ 170 FontResolutionPtr res; 171 int num; 172 173 res = GetClientResolutions(&num); 174 if (res) 175 return res->point_size; 176 else 177 return default_point_size; 178} 179 180Bool 181XpClientIsBitmapClient(ClientPtr client) 182{ 183 return TRUE; 184} 185 186Bool 187XpClientIsPrintClient(ClientPtr client, FontPathElementPtr fpe) 188{ 189 return FALSE; 190} 191 192void 193CopyISOLatin1Lowered(char *d, char *s, int length) 194{ 195 register int i; 196 unsigned char *dest = (unsigned char *)d, *source = (unsigned char *)s; 197 198 for (i = 0; i < length; i++, source++, dest++) { 199 if ((*source >= XK_A) && (*source <= XK_Z)) 200 *dest = *source + (XK_a - XK_A); 201 else if ((*source >= XK_Agrave) && (*source <= XK_Odiaeresis)) 202 *dest = *source + (XK_agrave - XK_Agrave); 203 else if ((*source >= XK_Ooblique) && (*source <= XK_Thorn)) 204 *dest = *source + (XK_oslash - XK_Ooblique); 205 else 206 *dest = *source; 207 } 208 *dest = '\0'; 209} 210 211int 212strncmpnocase( 213 const char *first, 214 const char *second, 215 int n) 216{ 217 register const unsigned char *ap, 218 *bp; 219 220 for (ap = (const unsigned char *) first, 221 bp = (const unsigned char *) second; 222 /* SUPPRESS 112 */ 223 n > 0 && *ap && *bp; n--, ap++, bp++) { 224 register unsigned char a, 225 b; 226 227 /* SUPPRESS 112 */ 228 if ((a = *ap) != (b = *bp)) { 229 /* try lowercasing and try again */ 230 231 if ((a >= XK_A) && (a <= XK_Z)) 232 a += (XK_a - XK_A); 233 else if ((a >= XK_Agrave) && (a <= XK_Odiaeresis)) 234 a += (XK_agrave - XK_Agrave); 235 else if ((a >= XK_Ooblique) && (a <= XK_Thorn)) 236 a += (XK_oslash - XK_Ooblique); 237 238 if ((b >= XK_A) && (b <= XK_Z)) 239 b += (XK_a - XK_A); 240 else if ((b >= XK_Agrave) && (b <= XK_Odiaeresis)) 241 b += (XK_agrave - XK_Agrave); 242 else if ((b >= XK_Ooblique) && (b <= XK_Thorn)) 243 b += (XK_oslash - XK_Ooblique); 244 245 if (a != b) 246 break; 247 } 248 } 249 /* SUPPRESS 112 */ 250 return (n ? (((int) *ap) - ((int) *bp)) : 0); 251} 252 253void 254NoopDDA(void) 255{ 256} 257 258/* block & wakeup handlers */ 259 260typedef struct _BlockHandler { 261 BlockHandlerProcPtr BlockHandler; 262 DifsWakeupFunc WakeupHandler; 263 pointer blockData; 264 Bool deleted; 265} BlockHandlerRec, *BlockHandlerPtr; 266 267static BlockHandlerPtr handlers; 268static int numHandlers; 269static int sizeHandlers; 270static Bool inHandler; 271static Bool handlerDeleted; 272 273/* called from the OS layer */ 274void 275BlockHandler( 276 OSTimePtr pTimeout, /* DIX doesn't want to know how OS represents 277 * time */ 278 pointer pReadmask) /* nor how it represents the set of 279 * descriptors */ 280{ 281 register int i, 282 j; 283 284 ++inHandler; 285 for (i = 0; i < numHandlers; i++) 286 (*handlers[i].BlockHandler) (handlers[i].blockData, 287 pTimeout, pReadmask); 288 if (handlerDeleted) { 289 for (i = 0; i < numHandlers;) 290 if (handlers[i].deleted) { 291 for (j = i; j < numHandlers - 1; j++) 292 handlers[j] = handlers[j + 1]; 293 numHandlers--; 294 } else 295 i++; 296 } 297 --inHandler; 298} 299 300 301void 302WakeupHandler( 303 int result, /* result from the wait */ 304 unsigned long * pReadmask) /* the resulting descriptor mask */ 305{ 306 register int i, 307 j; 308 309 ++inHandler; 310 for (i = numHandlers - 1; i >= 0; i--) 311 (*handlers[i].WakeupHandler) (handlers[i].blockData, 312 result, pReadmask); 313 if (handlerDeleted) { 314 for (i = 0; i < numHandlers;) 315 if (handlers[i].deleted) { 316 for (j = i; j < numHandlers - 1; j++) 317 handlers[j] = handlers[j + 1]; 318 numHandlers--; 319 } else 320 i++; 321 } 322 --inHandler; 323} 324 325/* Reentrant with BlockHandler and WakeupHandler, except wakeup won't 326 * get called until next time 327 */ 328 329Bool 330RegisterBlockAndWakeupHandlers( 331 BlockHandlerProcPtr blockHandler, 332 DifsWakeupFunc wakeupHandler, 333 pointer blockData) 334{ 335 BlockHandlerPtr new; 336 337 if (numHandlers >= sizeHandlers) { 338 new = (BlockHandlerPtr) fsrealloc(handlers, (numHandlers + 1) * 339 sizeof(BlockHandlerRec)); 340 if (!new) 341 return FALSE; 342 handlers = new; 343 sizeHandlers = numHandlers + 1; 344 } 345 handlers[numHandlers].BlockHandler = blockHandler; 346 handlers[numHandlers].WakeupHandler = wakeupHandler; 347 handlers[numHandlers].blockData = blockData; 348 numHandlers = numHandlers + 1; 349 return TRUE; 350} 351 352void 353RemoveBlockAndWakeupHandlers( 354 BlockHandlerProcPtr blockHandler, 355 DifsWakeupFunc wakeupHandler, 356 pointer blockData) 357{ 358 int i; 359 360 for (i = 0; i < numHandlers; i++) 361 if (handlers[i].BlockHandler == blockHandler && 362 handlers[i].WakeupHandler == wakeupHandler && 363 handlers[i].blockData == blockData) { 364 if (inHandler) { 365 handlerDeleted = TRUE; 366 handlers[i].deleted = TRUE; 367 } else { 368 for (; i < numHandlers - 1; i++) 369 handlers[i] = handlers[i + 1]; 370 numHandlers--; 371 } 372 break; 373 } 374} 375 376void 377InitBlockAndWakeupHandlers(void) 378{ 379 fsfree(handlers); 380 handlers = (BlockHandlerPtr) 0; 381 numHandlers = 0; 382 sizeHandlers = 0; 383} 384 385/* 386 * A general work queue. Perform some task before the server 387 * sleeps for input. 388 */ 389 390WorkQueuePtr workQueue; 391static WorkQueuePtr *workQueueLast = &workQueue; 392 393/* ARGSUSED */ 394void 395ProcessWorkQueue(void) 396{ 397 WorkQueuePtr q, 398 n, 399 p; 400 401 p = NULL; 402 /* 403 * Scan the work queue once, calling each function. Those which return 404 * TRUE are removed from the queue, otherwise they will be called again. 405 * This must be reentrant with QueueWorkProc, hence the crufty usage of 406 * variables. 407 */ 408 for (q = workQueue; q; q = n) { 409 if ((*q->function) (q->client, q->closure)) { 410 /* remove q from the list */ 411 n = q->next; /* don't fetch until after func called */ 412 if (p) 413 p->next = n; 414 else 415 workQueue = n; 416 fsfree(q); 417 } else { 418 n = q->next; /* don't fetch until after func called */ 419 p = q; 420 } 421 } 422 if (p) 423 workQueueLast = &p->next; 424 else { 425 workQueueLast = &workQueue; 426 } 427} 428 429Bool 430QueueWorkProc( 431 Bool (*function) (ClientPtr, pointer), 432 ClientPtr client, 433 pointer data) 434{ 435 WorkQueuePtr q; 436 437 q = (WorkQueuePtr) fsalloc(sizeof *q); 438 if (!q) 439 return FALSE; 440 q->function = function; 441 q->client = client; 442 q->closure = data; 443 q->next = NULL; 444 *workQueueLast = q; 445 workQueueLast = &q->next; 446 return TRUE; 447} 448 449/* 450 * Manage a queue of sleeping clients, awakening them 451 * when requested, by using the OS functions IgnoreClient 452 * and AttendClient. Note that this *ignores* the troubles 453 * with request data interleaving itself with events, but 454 * we'll leave that until a later time. 455 */ 456 457typedef struct _SleepQueue { 458 struct _SleepQueue *next; 459 ClientPtr client; 460 Bool (*function) (ClientPtr, pointer); 461 pointer closure; 462} SleepQueueRec, *SleepQueuePtr; 463 464static SleepQueuePtr sleepQueue = NULL; 465 466Bool 467ClientSleep( 468 ClientPtr client, 469 Bool (*function) (ClientPtr, pointer), 470 pointer data) 471{ 472 SleepQueuePtr q; 473 474 q = (SleepQueuePtr) fsalloc(sizeof *q); 475 if (!q) 476 return FALSE; 477 478 IgnoreClient(client); 479 q->next = sleepQueue; 480 q->client = client; 481 q->function = function; 482 q->closure = data; 483 sleepQueue = q; 484 return TRUE; 485} 486 487Bool 488ClientSignal(ClientPtr client) 489{ 490 SleepQueuePtr q; 491 492 for (q = sleepQueue; q; q = q->next) 493 if (q->client == client) { 494 return QueueWorkProc(q->function, q->client, q->closure); 495 } 496 return FALSE; 497} 498 499void 500ClientWakeup(ClientPtr client) 501{ 502 SleepQueuePtr q, 503 *prev; 504 505 prev = &sleepQueue; 506 while ((q = *prev) != (SleepQueuePtr) 0) { 507 if (q->client == client) { 508 *prev = q->next; 509 fsfree(q); 510 if (client->clientGone == CLIENT_GONE) 511 CloseDownClient(client); 512 else 513 AttendClient(client); 514 break; 515 } 516 prev = &q->next; 517 } 518} 519 520Bool 521ClientIsAsleep(ClientPtr client) 522{ 523 SleepQueuePtr q; 524 525 for (q = sleepQueue; q; q = q->next) 526 if (q->client == client) 527 return TRUE; 528 return FALSE; 529} 530 531pointer 532Xalloc(unsigned long m) 533{ 534 return fsalloc(m); 535} 536 537pointer 538Xrealloc(pointer n, unsigned long m) 539{ 540 return fsrealloc(n, m); 541} 542 543void 544Xfree(unsigned long *n) 545{ 546 fsfree(n); 547} 548 549pointer 550Xcalloc(unsigned long n) 551{ 552 pointer ret; 553 554 ret = fsalloc(n); 555 if (ret && n) 556 bzero(ret, n); 557 return ret; 558} 559 560int 561set_font_authorizations(char **authorizations, int *authlen, ClientPtr client) 562{ 563#define AUTH1_NAME "hp-hostname-1" 564#define AUTH2_NAME "hp-printername-1" 565 static char result[1024]; 566 char *p; 567 AuthContextPtr acp = client->auth; 568 int len1, len2; 569 570 if (acp != NULL && acp->authname != NULL && acp->authdata != NULL && 571 (!strcmp(AUTH1_NAME, acp->authname) || 572 !strcmp(AUTH2_NAME, acp->authname)) && 573 (len1 = strlen(acp->authname) + 1) + 574 (len2 = strlen(acp->authdata) + 1) + 2 * sizeof(short) <= 1024) 575 { 576 p = result; 577 *p++ = len1 >> 8; 578 *p++ = len1 &0xff; 579 *p++ = len2 >> 8; 580 *p++ = len2 & 0xff; 581 memmove( p, acp->authname, len1); 582 p += len1; 583 memmove( p, acp->authdata, len2); 584 p += len2; 585 *authlen = p - result; 586 *authorizations = result; 587 return 1; 588 } 589 590 *authlen = 0; 591 return 0; 592} 593 594int 595client_auth_generation(ClientPtr client) 596{ 597 return client->auth_generation; 598} 599