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