difsutils.c revision 8f34cbf9
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 180int 181strncmpnocase( 182 const char *first, 183 const char *second, 184 int n) 185{ 186 register const unsigned char *ap, 187 *bp; 188 189 for (ap = (const unsigned char *) first, 190 bp = (const unsigned char *) second; 191 /* SUPPRESS 112 */ 192 n > 0 && *ap && *bp; n--, ap++, bp++) { 193 register unsigned char a, 194 b; 195 196 /* SUPPRESS 112 */ 197 if ((a = *ap) != (b = *bp)) { 198 /* try lowercasing and try again */ 199 200 if ((a >= XK_A) && (a <= XK_Z)) 201 a += (XK_a - XK_A); 202 else if ((a >= XK_Agrave) && (a <= XK_Odiaeresis)) 203 a += (XK_agrave - XK_Agrave); 204 else if ((a >= XK_Ooblique) && (a <= XK_Thorn)) 205 a += (XK_oslash - XK_Ooblique); 206 207 if ((b >= XK_A) && (b <= XK_Z)) 208 b += (XK_a - XK_A); 209 else if ((b >= XK_Agrave) && (b <= XK_Odiaeresis)) 210 b += (XK_agrave - XK_Agrave); 211 else if ((b >= XK_Ooblique) && (b <= XK_Thorn)) 212 b += (XK_oslash - XK_Ooblique); 213 214 if (a != b) 215 break; 216 } 217 } 218 /* SUPPRESS 112 */ 219 return (n ? (((int) *ap) - ((int) *bp)) : 0); 220} 221 222void 223NoopDDA(void) 224{ 225} 226 227/* block & wakeup handlers */ 228 229typedef struct _BlockHandler { 230 BlockHandlerProcPtr BlockHandler; 231 DifsWakeupFunc WakeupHandler; 232 pointer blockData; 233 Bool deleted; 234} BlockHandlerRec, *BlockHandlerPtr; 235 236static BlockHandlerPtr handlers; 237static int numHandlers; 238static int sizeHandlers; 239static Bool inHandler; 240static Bool handlerDeleted; 241 242/* called from the OS layer */ 243void 244BlockHandler( 245 OSTimePtr pTimeout, /* DIX doesn't want to know how OS represents 246 * time */ 247 pointer pReadmask) /* nor how it represents the set of 248 * descriptors */ 249{ 250 register int i, 251 j; 252 253 ++inHandler; 254 for (i = 0; i < numHandlers; i++) 255 (*handlers[i].BlockHandler) (handlers[i].blockData, 256 pTimeout, pReadmask); 257 if (handlerDeleted) { 258 for (i = 0; i < numHandlers;) 259 if (handlers[i].deleted) { 260 for (j = i; j < numHandlers - 1; j++) 261 handlers[j] = handlers[j + 1]; 262 numHandlers--; 263 } else 264 i++; 265 } 266 --inHandler; 267} 268 269 270void 271WakeupHandler( 272 int result, /* result from the wait */ 273 unsigned long * pReadmask) /* the resulting descriptor mask */ 274{ 275 register int i, 276 j; 277 278 ++inHandler; 279 for (i = numHandlers - 1; i >= 0; i--) 280 (*handlers[i].WakeupHandler) (handlers[i].blockData, 281 result, pReadmask); 282 if (handlerDeleted) { 283 for (i = 0; i < numHandlers;) 284 if (handlers[i].deleted) { 285 for (j = i; j < numHandlers - 1; j++) 286 handlers[j] = handlers[j + 1]; 287 numHandlers--; 288 } else 289 i++; 290 } 291 --inHandler; 292} 293 294/* Reentrant with BlockHandler and WakeupHandler, except wakeup won't 295 * get called until next time 296 */ 297 298Bool 299RegisterBlockAndWakeupHandlers( 300 BlockHandlerProcPtr blockHandler, 301 DifsWakeupFunc wakeupHandler, 302 pointer blockData) 303{ 304 BlockHandlerPtr new; 305 306 if (numHandlers >= sizeHandlers) { 307 new = (BlockHandlerPtr) fsrealloc(handlers, (numHandlers + 1) * 308 sizeof(BlockHandlerRec)); 309 if (!new) 310 return FALSE; 311 handlers = new; 312 sizeHandlers = numHandlers + 1; 313 } 314 handlers[numHandlers].BlockHandler = blockHandler; 315 handlers[numHandlers].WakeupHandler = wakeupHandler; 316 handlers[numHandlers].blockData = blockData; 317 numHandlers = numHandlers + 1; 318 return TRUE; 319} 320 321void 322RemoveBlockAndWakeupHandlers( 323 BlockHandlerProcPtr blockHandler, 324 DifsWakeupFunc wakeupHandler, 325 pointer blockData) 326{ 327 int i; 328 329 for (i = 0; i < numHandlers; i++) 330 if (handlers[i].BlockHandler == blockHandler && 331 handlers[i].WakeupHandler == wakeupHandler && 332 handlers[i].blockData == blockData) { 333 if (inHandler) { 334 handlerDeleted = TRUE; 335 handlers[i].deleted = TRUE; 336 } else { 337 for (; i < numHandlers - 1; i++) 338 handlers[i] = handlers[i + 1]; 339 numHandlers--; 340 } 341 break; 342 } 343} 344 345void 346InitBlockAndWakeupHandlers(void) 347{ 348 fsfree(handlers); 349 handlers = (BlockHandlerPtr) 0; 350 numHandlers = 0; 351 sizeHandlers = 0; 352} 353 354/* 355 * A general work queue. Perform some task before the server 356 * sleeps for input. 357 */ 358 359WorkQueuePtr workQueue; 360static WorkQueuePtr *workQueueLast = &workQueue; 361 362/* ARGSUSED */ 363void 364ProcessWorkQueue(void) 365{ 366 WorkQueuePtr q, 367 n, 368 p; 369 370 p = NULL; 371 /* 372 * Scan the work queue once, calling each function. Those which return 373 * TRUE are removed from the queue, otherwise they will be called again. 374 * This must be reentrant with QueueWorkProc, hence the crufty usage of 375 * variables. 376 */ 377 for (q = workQueue; q; q = n) { 378 if ((*q->function) (q->client, q->closure)) { 379 /* remove q from the list */ 380 n = q->next; /* don't fetch until after func called */ 381 if (p) 382 p->next = n; 383 else 384 workQueue = n; 385 fsfree(q); 386 } else { 387 n = q->next; /* don't fetch until after func called */ 388 p = q; 389 } 390 } 391 if (p) 392 workQueueLast = &p->next; 393 else { 394 workQueueLast = &workQueue; 395 } 396} 397 398Bool 399QueueWorkProc( 400 Bool (*function) (ClientPtr, pointer), 401 ClientPtr client, 402 pointer data) 403{ 404 WorkQueuePtr q; 405 406 q = (WorkQueuePtr) fsalloc(sizeof *q); 407 if (!q) 408 return FALSE; 409 q->function = function; 410 q->client = client; 411 q->closure = data; 412 q->next = NULL; 413 *workQueueLast = q; 414 workQueueLast = &q->next; 415 return TRUE; 416} 417 418/* 419 * Manage a queue of sleeping clients, awakening them 420 * when requested, by using the OS functions IgnoreClient 421 * and AttendClient. Note that this *ignores* the troubles 422 * with request data interleaving itself with events, but 423 * we'll leave that until a later time. 424 */ 425 426typedef struct _SleepQueue { 427 struct _SleepQueue *next; 428 ClientPtr client; 429 Bool (*function) (ClientPtr, pointer); 430 pointer closure; 431} SleepQueueRec, *SleepQueuePtr; 432 433static SleepQueuePtr sleepQueue = NULL; 434 435Bool 436ClientSleep( 437 ClientPtr client, 438 Bool (*function) (ClientPtr, pointer), 439 pointer data) 440{ 441 SleepQueuePtr q; 442 443 q = (SleepQueuePtr) fsalloc(sizeof *q); 444 if (!q) 445 return FALSE; 446 447 IgnoreClient(client); 448 q->next = sleepQueue; 449 q->client = client; 450 q->function = function; 451 q->closure = data; 452 sleepQueue = q; 453 return TRUE; 454} 455 456Bool 457ClientSignal(ClientPtr client) 458{ 459 SleepQueuePtr q; 460 461 for (q = sleepQueue; q; q = q->next) 462 if (q->client == client) { 463 return QueueWorkProc(q->function, q->client, q->closure); 464 } 465 return FALSE; 466} 467 468void 469ClientWakeup(ClientPtr client) 470{ 471 SleepQueuePtr q, 472 *prev; 473 474 prev = &sleepQueue; 475 while ((q = *prev) != (SleepQueuePtr) 0) { 476 if (q->client == client) { 477 *prev = q->next; 478 fsfree(q); 479 if (client->clientGone == CLIENT_GONE) 480 CloseDownClient(client); 481 else 482 AttendClient(client); 483 break; 484 } 485 prev = &q->next; 486 } 487} 488 489Bool 490ClientIsAsleep(ClientPtr client) 491{ 492 SleepQueuePtr q; 493 494 for (q = sleepQueue; q; q = q->next) 495 if (q->client == client) 496 return TRUE; 497 return FALSE; 498} 499 500pointer 501Xalloc(unsigned long m) 502{ 503 return fsalloc(m); 504} 505 506pointer 507Xrealloc(pointer n, unsigned long m) 508{ 509 return fsrealloc(n, m); 510} 511 512void 513Xfree(unsigned long *n) 514{ 515 fsfree(n); 516} 517 518pointer 519Xcalloc(unsigned long n) 520{ 521 pointer ret; 522 523 ret = fsalloc(n); 524 if (ret && n) 525 bzero(ret, n); 526 return ret; 527} 528 529int 530set_font_authorizations(char **authorizations, int *authlen, ClientPtr client) 531{ 532#define AUTH1_NAME "hp-hostname-1" 533#define AUTH2_NAME "hp-printername-1" 534 static char result[1024]; 535 char *p; 536 AuthContextPtr acp = client->auth; 537 int len1, len2; 538 539 if (acp != NULL && acp->authname != NULL && acp->authdata != NULL && 540 (!strcmp(AUTH1_NAME, acp->authname) || 541 !strcmp(AUTH2_NAME, acp->authname)) && 542 (len1 = strlen(acp->authname) + 1) + 543 (len2 = strlen(acp->authdata) + 1) + 2 * sizeof(short) <= 1024) 544 { 545 p = result; 546 *p++ = len1 >> 8; 547 *p++ = len1 &0xff; 548 *p++ = len2 >> 8; 549 *p++ = len2 & 0xff; 550 memmove( p, acp->authname, len1); 551 p += len1; 552 memmove( p, acp->authdata, len2); 553 p += len2; 554 *authlen = p - result; 555 *authorizations = result; 556 return 1; 557 } 558 559 *authlen = 0; 560 return 0; 561} 562 563int 564client_auth_generation(ClientPtr client) 565{ 566 return client->auth_generation; 567} 568