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