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