difsutils.c revision bbe1b32b
1/* $Xorg: difsutils.c,v 1.4 2001/02/09 02:05:42 xorgcvs Exp $ */
2/*
3 * misc utility routines
4 */
5/*
6
7Copyright 1990, 1991, 1998  The Open Group
8
9Permission to use, copy, modify, distribute, and sell this software and its
10documentation for any purpose is hereby granted without fee, provided that
11the above copyright notice appear in all copies and that both that
12copyright notice and this permission notice appear in supporting
13documentation.
14
15The above copyright notice and this permission notice shall be included in
16all copies or substantial portions of the Software.
17
18THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
21OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
22AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
25Except as contained in this notice, the name of The Open Group shall not be
26used in advertising or otherwise to promote the sale, use or other dealings
27in this Software without prior written authorization from The Open Group.
28
29 * Copyright 1990, 1991 Network Computing Devices;
30 * Portions Copyright 1987 by Digital Equipment Corporation
31 *
32 * Permission to use, copy, modify, distribute, and sell this software and
33 * its documentation for any purpose is hereby granted without fee, provided
34 * that the above copyright notice appear in all copies and that both that
35 * copyright notice and this permission notice appear in supporting
36 * documentation, and that the names of Network Computing Devices, or Digital
37 * not be used in advertising or publicity pertaining to distribution
38 * of the software without specific, written prior permission.
39 *
40 * NETWORK COMPUTING DEVICES, AND DIGITAL DISCLAIM ALL WARRANTIES WITH
41 * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
42 * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL NETWORK COMPUTING DEVICES,
43 * OR DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
44 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
45 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
46 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
47 * THIS SOFTWARE.
48 */
49/* $XFree86: xc/programs/xfs/difs/difsutils.c,v 1.6 2001/01/17 23:45:28 dawes Exp $ */
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	"accstr.h"
61#include	<X11/fonts/fontstruct.h>
62#include	<X11/keysymdef.h>
63
64#include	"authstr.h"
65#include	"auth.h"
66#include	"client.h"
67
68extern ClientPtr currentClient;
69static FontResolutionPtr default_resolutions;
70static int  num_resolutions;
71static int  default_point_size = 120;
72
73AuthContextPtr
74GetClientAuthorization(void)
75{
76    return currentClient->auth;
77}
78
79void
80SetDefaultPointSize(int ps)
81{
82    int         i;
83
84    default_point_size = ps;
85    for (i = 0; i < num_resolutions; i++)
86	default_resolutions[i].point_size = ps;
87}
88
89int
90SetDefaultResolutions(char *str)
91{
92    int         num,
93                numr = 0,
94                n;
95    char       *s;
96    FontResolutionPtr new,
97                nr;
98    int         state;
99
100    s = str;
101    while (*s) {		/* count commas */
102	if (*s == ',')
103	    numr++;
104	s++;
105    }
106
107    if ((numr % 2) != 1) {	/* must be multiple of 2 + 1 */
108	return FSBadResolution;
109    }
110    numr = (numr + 1) / 2;
111    nr = new = (FontResolutionPtr) fsalloc(sizeof(FontResolutionRec)
112					   * numr);
113    if (!new)
114	return FSBadAlloc;
115    s = str;
116    num = 0;
117    state = 0;
118    while (*s) {
119	if (*s == ',') {
120	    if (state == 0) {
121		nr->x_resolution = num;
122		state++;
123	    } else {
124		state = 0;
125		nr->y_resolution = num;
126		nr->point_size = default_point_size;
127		nr++;
128	    }
129	    num = 0;
130	    s++;
131	    continue;
132	}
133	if (!isdigit(*s)) {
134	    fsfree((char *) new);
135	    return FSBadResolution;
136	}
137	n = *s - '0';
138	num = num * 10 + n;
139	s++;
140    }
141
142    /* do the last one */
143    assert(state == 1);
144    nr->y_resolution = num;
145    nr->point_size = default_point_size;
146
147    if (default_resolutions) {
148	fsfree((char *) default_resolutions);
149    }
150    default_resolutions = new;
151    num_resolutions = numr;
152    return FSSuccess;
153}
154
155FontResolutionPtr
156GetClientResolutions(int *num)
157{
158    /* return the client's if it has them, otherwise the default values */
159    if (currentClient->num_resolutions) {
160	*num = currentClient->num_resolutions;
161	return (FontResolutionPtr) currentClient->resolutions;
162    } else {
163	*num = num_resolutions;
164	return default_resolutions;
165    }
166}
167
168int
169GetDefaultPointSize(void)
170{
171    FontResolutionPtr res;
172    int         num;
173
174    res = GetClientResolutions(&num);
175    if (res)
176	return res->point_size;
177    else
178	return default_point_size;
179}
180
181Bool
182XpClientIsBitmapClient(ClientPtr client)
183{
184    return TRUE;
185}
186
187Bool
188XpClientIsPrintClient(ClientPtr client, FontPathElementPtr fpe)
189{
190    return FALSE;
191}
192
193void
194CopyISOLatin1Lowered(unsigned char *dest, unsigned char *source, int length)
195{
196    register int i;
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    char       *first,
214    char       *second,
215    int         n)
216{
217    register unsigned char *ap,
218               *bp;
219
220    for (ap = (unsigned char *) first,
221	    bp = (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/* host list manipulation */
259int
260AddHost(
261    HostList   *list,
262    HostAddress *addr)
263{
264    HostAddress *new;
265
266    new = (HostAddress *) fsalloc(sizeof(HostAddress));
267    if (!new)
268	return FSBadAlloc;
269    new->address = (pointer) fsalloc(addr->addr_len);
270    if (!new->address) {
271	fsfree((char *) addr);
272	return FSBadAlloc;
273    }
274    new->type = addr->type;
275    new->addr_len = addr->addr_len;
276    memmove( (char *) new->address, (char *) addr->address, new->addr_len);
277
278    new->next = *list;
279    *list = new;
280    return FSSuccess;
281}
282
283int
284RemoveHost(
285    HostList   *list,
286    HostAddress *addr)
287{
288    HostAddress *t,
289               *last;
290
291    last = (HostAddress *) 0;
292    t = *list;
293    while (t) {
294	if (t->type == addr->type &&
295		t->addr_len == addr->addr_len &&
296		memcmp((char *) t->address, (char *) addr->address,
297		     min(t->addr_len, addr->addr_len)) == 0) {
298	    if (last) {
299		last->next = t->next;
300	    } else {
301		*list = t->next;
302	    }
303	    fsfree((char *) t->address);
304	    fsfree((char *) t);
305	    return FSSuccess;
306	}
307	last = t;
308	t = t->next;
309    }
310    return FSBadName;		/* bad host name */
311}
312
313Bool
314ValidHost(
315    HostList    list,
316    HostAddress *addr)
317{
318    HostAddress *t;
319
320    t = list;
321    while (t) {
322	if (t->type == addr->type &&
323		t->addr_len == addr->addr_len &&
324		memcmp((char *) t->address, (char *) addr->address,
325		     min(t->addr_len, addr->addr_len)) == 0) {
326	    return TRUE;
327	}
328    }
329    return FALSE;
330}
331
332/* block & wakeup handlers */
333
334typedef struct _BlockHandler {
335    BlockHandlerProcPtr	BlockHandler;
336    DifsWakeupFunc	WakeupHandler;
337    pointer     	blockData;
338    Bool        	deleted;
339}           BlockHandlerRec, *BlockHandlerPtr;
340
341static BlockHandlerPtr handlers;
342static int  numHandlers;
343static int  sizeHandlers;
344static Bool inHandler;
345static Bool handlerDeleted;
346
347/* called from the OS layer */
348void
349BlockHandler(
350    OSTimePtr   pTimeout,	/* DIX doesn't want to know how OS represents
351				 * time */
352    pointer     pReadmask)	/* nor how it represents the set of
353				 * descriptors */
354{
355    register int i,
356                j;
357
358    ++inHandler;
359    for (i = 0; i < numHandlers; i++)
360	(*handlers[i].BlockHandler) (handlers[i].blockData,
361				     pTimeout, pReadmask);
362    if (handlerDeleted) {
363	for (i = 0; i < numHandlers;)
364	    if (handlers[i].deleted) {
365		for (j = i; j < numHandlers - 1; j++)
366		    handlers[j] = handlers[j + 1];
367		numHandlers--;
368	    } else
369		i++;
370    }
371    --inHandler;
372}
373
374
375void
376WakeupHandler(
377    int		result,		/* result from the wait */
378    unsigned long * pReadmask)	/* the resulting descriptor mask */
379{
380    register int i,
381                j;
382
383    ++inHandler;
384    for (i = numHandlers - 1; i >= 0; i--)
385	(*handlers[i].WakeupHandler) (handlers[i].blockData,
386				      result, pReadmask);
387    if (handlerDeleted) {
388	for (i = 0; i < numHandlers;)
389	    if (handlers[i].deleted) {
390		for (j = i; j < numHandlers - 1; j++)
391		    handlers[j] = handlers[j + 1];
392		numHandlers--;
393	    } else
394		i++;
395    }
396    --inHandler;
397}
398
399/* Reentrant with BlockHandler and WakeupHandler, except wakeup won't
400 * get called until next time
401 */
402
403Bool
404RegisterBlockAndWakeupHandlers(
405    BlockHandlerProcPtr blockHandler,
406    DifsWakeupFunc wakeupHandler,
407    pointer     blockData)
408{
409    BlockHandlerPtr new;
410
411    if (numHandlers >= sizeHandlers) {
412	new = (BlockHandlerPtr) fsrealloc(handlers, (numHandlers + 1) *
413					  sizeof(BlockHandlerRec));
414	if (!new)
415	    return FALSE;
416	handlers = new;
417	sizeHandlers = numHandlers + 1;
418    }
419    handlers[numHandlers].BlockHandler = blockHandler;
420    handlers[numHandlers].WakeupHandler = wakeupHandler;
421    handlers[numHandlers].blockData = blockData;
422    numHandlers = numHandlers + 1;
423    return TRUE;
424}
425
426void
427RemoveBlockAndWakeupHandlers(
428    BlockHandlerProcPtr blockHandler,
429    DifsWakeupFunc wakeupHandler,
430    pointer     blockData)
431{
432    int         i;
433
434    for (i = 0; i < numHandlers; i++)
435	if (handlers[i].BlockHandler == blockHandler &&
436		handlers[i].WakeupHandler == wakeupHandler &&
437		handlers[i].blockData == blockData) {
438	    if (inHandler) {
439		handlerDeleted = TRUE;
440		handlers[i].deleted = TRUE;
441	    } else {
442		for (; i < numHandlers - 1; i++)
443		    handlers[i] = handlers[i + 1];
444		numHandlers--;
445	    }
446	    break;
447	}
448}
449
450void
451InitBlockAndWakeupHandlers(void)
452{
453    fsfree(handlers);
454    handlers = (BlockHandlerPtr) 0;
455    numHandlers = 0;
456    sizeHandlers = 0;
457}
458
459/*
460 * A general work queue.  Perform some task before the server
461 * sleeps for input.
462 */
463
464WorkQueuePtr workQueue;
465static WorkQueuePtr *workQueueLast = &workQueue;
466
467/* ARGSUSED */
468void
469ProcessWorkQueue(void)
470{
471    WorkQueuePtr q,
472                n,
473                p;
474
475    p = NULL;
476    /*
477     * Scan the work queue once, calling each function.  Those which return
478     * TRUE are removed from the queue, otherwise they will be called again.
479     * This must be reentrant with QueueWorkProc, hence the crufty usage of
480     * variables.
481     */
482    for (q = workQueue; q; q = n) {
483	if ((*q->function) (q->client, q->closure)) {
484	    /* remove q from the list */
485	    n = q->next;	/* don't fetch until after func called */
486	    if (p)
487		p->next = n;
488	    else
489		workQueue = n;
490	    fsfree(q);
491	} else {
492	    n = q->next;	/* don't fetch until after func called */
493	    p = q;
494	}
495    }
496    if (p)
497	workQueueLast = &p->next;
498    else {
499	workQueueLast = &workQueue;
500    }
501}
502
503Bool
504QueueWorkProc(
505    Bool        (*function) (ClientPtr, pointer),
506    ClientPtr   client,
507    pointer     data)
508{
509    WorkQueuePtr q;
510
511    q = (WorkQueuePtr) fsalloc(sizeof *q);
512    if (!q)
513	return FALSE;
514    q->function = function;
515    q->client = client;
516    q->closure = data;
517    q->next = NULL;
518    *workQueueLast = q;
519    workQueueLast = &q->next;
520    return TRUE;
521}
522
523/*
524 * Manage a queue of sleeping clients, awakening them
525 * when requested, by using the OS functions IgnoreClient
526 * and AttendClient.  Note that this *ignores* the troubles
527 * with request data interleaving itself with events, but
528 * we'll leave that until a later time.
529 */
530
531typedef struct _SleepQueue {
532    struct _SleepQueue *next;
533    ClientPtr   client;
534    Bool        (*function) (ClientPtr, pointer);
535    pointer     closure;
536}           SleepQueueRec, *SleepQueuePtr;
537
538static SleepQueuePtr sleepQueue = NULL;
539
540Bool
541ClientSleep(
542    ClientPtr   client,
543    Bool        (*function) (ClientPtr, pointer),
544    pointer     data)
545{
546    SleepQueuePtr q;
547
548    q = (SleepQueuePtr) fsalloc(sizeof *q);
549    if (!q)
550	return FALSE;
551
552    IgnoreClient(client);
553    q->next = sleepQueue;
554    q->client = client;
555    q->function = function;
556    q->closure = data;
557    sleepQueue = q;
558    return TRUE;
559}
560
561Bool
562ClientSignal(ClientPtr client)
563{
564    SleepQueuePtr q;
565
566    for (q = sleepQueue; q; q = q->next)
567	if (q->client == client) {
568	    return QueueWorkProc(q->function, q->client, q->closure);
569	}
570    return FALSE;
571}
572
573void
574ClientWakeup(ClientPtr client)
575{
576    SleepQueuePtr q,
577               *prev;
578
579    prev = &sleepQueue;
580    while ((q = *prev) != (SleepQueuePtr) 0) {
581	if (q->client == client) {
582	    *prev = q->next;
583	    fsfree(q);
584	    if (client->clientGone == CLIENT_GONE)
585		CloseDownClient(client);
586	    else
587		AttendClient(client);
588	    break;
589	}
590	prev = &q->next;
591    }
592}
593
594Bool
595ClientIsAsleep(ClientPtr client)
596{
597    SleepQueuePtr q;
598
599    for (q = sleepQueue; q; q = q->next)
600	if (q->client == client)
601	    return TRUE;
602    return FALSE;
603}
604
605pointer
606Xalloc(unsigned long m)
607{
608    return fsalloc(m);
609}
610
611pointer
612Xrealloc(pointer n, unsigned long m)
613{
614    return fsrealloc(n, m);
615}
616
617void
618Xfree(unsigned long *n)
619{
620    fsfree(n);
621}
622
623pointer
624Xcalloc(unsigned long n)
625{
626    pointer ret;
627
628    ret = fsalloc(n);
629    if (ret && n)
630	bzero(ret, n);
631    return ret;
632}
633
634int
635set_font_authorizations(char **authorizations, int *authlen, ClientPtr client)
636{
637#define AUTH1_NAME "hp-hostname-1"
638#define AUTH2_NAME "hp-printername-1"
639    static char result[1024];
640    char *p;
641    AuthContextPtr acp = client->auth;
642    int len1, len2;
643
644    if (acp != NULL && acp->authname != NULL && acp->authdata != NULL &&
645	(!strcmp(AUTH1_NAME, acp->authname) ||
646	 !strcmp(AUTH2_NAME, acp->authname)) &&
647	(len1 = strlen(acp->authname) + 1) +
648	(len2 = strlen(acp->authdata) + 1) + 2 * sizeof(short) <= 1024)
649    {
650	p = result;
651	*p++ = len1 >> 8;
652	*p++ = len1 &0xff;
653	*p++ = len2 >> 8;
654	*p++ = len2 & 0xff;
655	memmove( p, acp->authname, len1);
656	p += len1;
657	memmove( p, acp->authdata, len2);
658	p += len2;
659	*authlen = p - result;
660	*authorizations = result;
661	return 1;
662    }
663
664    *authlen = 0;
665    return 0;
666}
667
668int
669client_auth_generation(ClientPtr client)
670{
671    return client->auth_generation;
672}
673