dispatch.c revision bbe1b32b
1bbe1b32bSmrg/* $Xorg: dispatch.c,v 1.6 2001/02/09 02:05:42 xorgcvs Exp $ */
2bbe1b32bSmrg/*
3bbe1b32bSmrg * protocol dispatcher
4bbe1b32bSmrg */
5bbe1b32bSmrg/*
6bbe1b32bSmrg
7bbe1b32bSmrgCopyright 1990, 1991, 1998  The Open Group
8bbe1b32bSmrg
9bbe1b32bSmrgPermission to use, copy, modify, distribute, and sell this software and its
10bbe1b32bSmrgdocumentation for any purpose is hereby granted without fee, provided that
11bbe1b32bSmrgthe above copyright notice appear in all copies and that both that
12bbe1b32bSmrgcopyright notice and this permission notice appear in supporting
13bbe1b32bSmrgdocumentation.
14bbe1b32bSmrg
15bbe1b32bSmrgThe above copyright notice and this permission notice shall be included in
16bbe1b32bSmrgall copies or substantial portions of the Software.
17bbe1b32bSmrg
18bbe1b32bSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19bbe1b32bSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20bbe1b32bSmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
21bbe1b32bSmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
22bbe1b32bSmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23bbe1b32bSmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24bbe1b32bSmrg
25bbe1b32bSmrgExcept as contained in this notice, the name of The Open Group shall not be
26bbe1b32bSmrgused in advertising or otherwise to promote the sale, use or other dealings
27bbe1b32bSmrgin this Software without prior written authorization from The Open Group.
28bbe1b32bSmrg
29bbe1b32bSmrg * Copyright 1990, 1991 Network Computing Devices;
30bbe1b32bSmrg * Portions Copyright 1987 by Digital Equipment Corporation
31bbe1b32bSmrg *
32bbe1b32bSmrg * Permission to use, copy, modify, distribute, and sell this software and
33bbe1b32bSmrg * its documentation for any purpose is hereby granted without fee, provided
34bbe1b32bSmrg * that the above copyright notice appear in all copies and that both that
35bbe1b32bSmrg * copyright notice and this permission notice appear in supporting
36bbe1b32bSmrg * documentation, and that the names of Network Computing Devices, or Digital
37bbe1b32bSmrg * not be used in advertising or publicity pertaining to distribution
38bbe1b32bSmrg * of the software without specific, written prior permission.
39bbe1b32bSmrg *
40bbe1b32bSmrg * NETWORK COMPUTING DEVICES, AND DIGITAL DISCLAIM ALL WARRANTIES WITH
41bbe1b32bSmrg * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
42bbe1b32bSmrg * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL NETWORK COMPUTING DEVICES,
43bbe1b32bSmrg * OR DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
44bbe1b32bSmrg * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
45bbe1b32bSmrg * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
46bbe1b32bSmrg * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
47bbe1b32bSmrg * THIS SOFTWARE.
48bbe1b32bSmrg */
49bbe1b32bSmrg/* $XFree86: xc/programs/xfs/difs/dispatch.c,v 3.12 2001/12/14 20:01:33 dawes Exp $ */
50bbe1b32bSmrg
51bbe1b32bSmrg#include	<stdlib.h>
52bbe1b32bSmrg#include	"dispatch.h"
53bbe1b32bSmrg#include	"swapreq.h"
54bbe1b32bSmrg#include	"swaprep.h"
55bbe1b32bSmrg
56bbe1b32bSmrg#include	<X11/fonts/FS.h>
57bbe1b32bSmrg#include	<X11/fonts/FSproto.h>
58bbe1b32bSmrg#include	"clientstr.h"
59bbe1b32bSmrg#include	"authstr.h"
60bbe1b32bSmrg#include	"osstruct.h"
61bbe1b32bSmrg#include	"extentst.h"
62bbe1b32bSmrg#include	"globals.h"
63bbe1b32bSmrg#include	"fsresource.h"
64bbe1b32bSmrg#include	"difsfnst.h"
65bbe1b32bSmrg#include	<X11/fonts/fontstruct.h>
66bbe1b32bSmrg#include	"site.h"
67bbe1b32bSmrg#include	"fsevents.h"
68bbe1b32bSmrg#include	"cache.h"
69bbe1b32bSmrg#include	"globals.h"
70bbe1b32bSmrg#include	"difs.h"
71bbe1b32bSmrg
72bbe1b32bSmrgstatic void kill_all_clients(void);
73bbe1b32bSmrg
74bbe1b32bSmrgvolatile char        dispatchException = 0;
75bbe1b32bSmrgvolatile char        isItTimeToYield;
76bbe1b32bSmrg
77bbe1b32bSmrgClientPtr   currentClient;
78bbe1b32bSmrg
79bbe1b32bSmrgstatic int  nClients = 0;
80bbe1b32bSmrgstatic int  nextFreeClientID;
81bbe1b32bSmrg
82bbe1b32bSmrgextern char *ConnectionInfo;
83bbe1b32bSmrgextern int  ConnInfoLen;
84bbe1b32bSmrg
85bbe1b32bSmrgextern char *configfilename;
86bbe1b32bSmrg
87bbe1b32bSmrgextern Bool drone_server;
88bbe1b32bSmrg
89bbe1b32bSmrg#define	MAJOROP	((fsReq *)client->requestBuffer)->reqType
90bbe1b32bSmrg
91bbe1b32bSmrg#define	ALL_FORMAT_BITS	(BitmapFormatByteOrderMask | \
92bbe1b32bSmrg			 BitmapFormatBitOrderMask | \
93bbe1b32bSmrg			 BitmapFormatScanlineUnitMask | \
94bbe1b32bSmrg			 BitmapFormatScanlinePadMask | \
95bbe1b32bSmrg			 BitmapFormatImageRectMask)
96bbe1b32bSmrg
97bbe1b32bSmrg#define	ALL_FORMAT_MASK_BITS	(BitmapFormatMaskByte | \
98bbe1b32bSmrg				 BitmapFormatMaskBit | \
99bbe1b32bSmrg				 BitmapFormatMaskImageRectangle | \
100bbe1b32bSmrg				 BitmapFormatMaskScanLinePad | \
101bbe1b32bSmrg				 BitmapFormatMaskScanLineUnit)
102bbe1b32bSmrg
103bbe1b32bSmrgvoid
104bbe1b32bSmrgDispatch(void)
105bbe1b32bSmrg{
106bbe1b32bSmrg    int         nready,
107bbe1b32bSmrg                result;
108bbe1b32bSmrg    int        *clientReady;
109bbe1b32bSmrg    ClientPtr   client;
110bbe1b32bSmrg    int		op;
111bbe1b32bSmrg
112bbe1b32bSmrg    nextFreeClientID = MINCLIENT;
113bbe1b32bSmrg    nClients = 0;
114bbe1b32bSmrg
115bbe1b32bSmrg    clientReady = (int *) ALLOCATE_LOCAL(sizeof(int) * MaxClients);
116bbe1b32bSmrg    if (!clientReady)
117bbe1b32bSmrg	return;
118bbe1b32bSmrg
119bbe1b32bSmrg    while (1) {
120bbe1b32bSmrg	/* wait for something */
121bbe1b32bSmrg	nready = WaitForSomething(clientReady);
122bbe1b32bSmrg
123bbe1b32bSmrg	while (!dispatchException && (--nready >= 0)) {
124bbe1b32bSmrg	    client = currentClient = clients[clientReady[nready]];
125bbe1b32bSmrg
126bbe1b32bSmrg	    /* Client can be NULL if CloseDownClient() is called during
127bbe1b32bSmrg	       this dispatchException loop. */
128bbe1b32bSmrg	    if (client == (ClientPtr)NULL) continue;
129bbe1b32bSmrg
130bbe1b32bSmrg	    isItTimeToYield = FALSE;
131bbe1b32bSmrg
132bbe1b32bSmrg	    while (!isItTimeToYield) {
133bbe1b32bSmrg		result = ReadRequest(client);
134bbe1b32bSmrg		if (result <= 0) {
135bbe1b32bSmrg		    if (result < 0)
136bbe1b32bSmrg			CloseDownClient(client);
137bbe1b32bSmrg		    break;
138bbe1b32bSmrg		}
139bbe1b32bSmrg		client->sequence++;
140bbe1b32bSmrg
141bbe1b32bSmrg		if (result > (MAX_REQUEST_SIZE << 2))
142bbe1b32bSmrg		    result = FSBadLength;
143bbe1b32bSmrg		else
144bbe1b32bSmrg		{
145bbe1b32bSmrg		    op = MAJOROP;
146bbe1b32bSmrg		    if (op >= NUM_PROC_VECTORS)
147bbe1b32bSmrg			result = ProcBadRequest (client);
148bbe1b32bSmrg		    else if (*client->requestVector[op] != NULL)
149bbe1b32bSmrg			result = (*client->requestVector[op]) (client);
150bbe1b32bSmrg		    else
151bbe1b32bSmrg			result = FSBadRequest;
152bbe1b32bSmrg		}
153bbe1b32bSmrg		if (result != FSSuccess) {
154bbe1b32bSmrg		    if (client->noClientException != FSSuccess)
155bbe1b32bSmrg			CloseDownClient(client);
156bbe1b32bSmrg		    break;
157bbe1b32bSmrg		}
158bbe1b32bSmrg	    }
159bbe1b32bSmrg	    FlushAllOutput ();
160bbe1b32bSmrg	}
161bbe1b32bSmrg	/* reset if server is a drone and has run out of clients */
162bbe1b32bSmrg	if (drone_server && nClients == 0) {
163bbe1b32bSmrg	    dispatchException |= DE_RESET;
164bbe1b32bSmrg	}
165bbe1b32bSmrg	if (dispatchException) {
166bbe1b32bSmrg	    /* re-read the config file */
167bbe1b32bSmrg	    if (dispatchException & DE_RECONFIG) {
168bbe1b32bSmrg		NoticeF("re-reading config file\n");
169bbe1b32bSmrg		if (ReadConfigFile(configfilename) != FSSuccess)
170bbe1b32bSmrg		    ErrorF("couldn't parse config file\n");
171bbe1b32bSmrg		SetConfigValues();
172bbe1b32bSmrg		dispatchException &= ~DE_RECONFIG;
173bbe1b32bSmrg	    }
174bbe1b32bSmrg	    /* flush all the caches */
175bbe1b32bSmrg	    if (dispatchException & DE_FLUSH) {
176bbe1b32bSmrg		NoticeF("flushing all caches\n");
177bbe1b32bSmrg		CacheReset();
178bbe1b32bSmrg		dispatchException &= ~DE_FLUSH;
179bbe1b32bSmrg	    }
180bbe1b32bSmrg	    /* reset */
181bbe1b32bSmrg	    if (dispatchException & DE_RESET) {
182bbe1b32bSmrg		NoticeF("resetting\n");
183bbe1b32bSmrg		break;
184bbe1b32bSmrg	    }
185bbe1b32bSmrg	    /* die *now* */
186bbe1b32bSmrg	    if (dispatchException & DE_TERMINATE) {
187bbe1b32bSmrg		NoticeF("terminating\n");
188bbe1b32bSmrg		kill_all_clients();
189bbe1b32bSmrg		CloseSockets();
190bbe1b32bSmrg		CloseErrors();
191bbe1b32bSmrg		exit(0);
192bbe1b32bSmrg		break;
193bbe1b32bSmrg	    }
194bbe1b32bSmrg	}
195bbe1b32bSmrg    }
196bbe1b32bSmrg    kill_all_clients();
197bbe1b32bSmrg    dispatchException = 0;
198bbe1b32bSmrg}
199bbe1b32bSmrg
200bbe1b32bSmrgint
201bbe1b32bSmrgProcInitialConnection(ClientPtr client)
202bbe1b32bSmrg{
203bbe1b32bSmrg    REQUEST(fsFakeReq);
204bbe1b32bSmrg    fsConnClientPrefix *prefix;
205bbe1b32bSmrg    int         whichbyte = 1;
206bbe1b32bSmrg
207bbe1b32bSmrg    nClients++;
208bbe1b32bSmrg    prefix = (fsConnClientPrefix *) stuff+1;
209bbe1b32bSmrg    if ((prefix->byteOrder != 'l') && (prefix->byteOrder != 'B'))
210bbe1b32bSmrg	return (client->noClientException = -2);
211bbe1b32bSmrg    if (((*(char *) &whichbyte) && (prefix->byteOrder == 'B')) ||
212bbe1b32bSmrg	    (!(*(char *) &whichbyte) && (prefix->byteOrder == 'l'))) {
213bbe1b32bSmrg	int status;
214bbe1b32bSmrg
215bbe1b32bSmrg	client->swapped = TRUE;
216bbe1b32bSmrg	status = SwapConnClientPrefix(client, prefix);
217bbe1b32bSmrg	if (status != FSSuccess)
218bbe1b32bSmrg	    return (status);
219bbe1b32bSmrg    }
220bbe1b32bSmrg    client->major_version = prefix->major_version;
221bbe1b32bSmrg    client->minor_version = prefix->minor_version;
222bbe1b32bSmrg    stuff->reqType = 2;
223bbe1b32bSmrg    stuff->length += prefix->auth_len;
224bbe1b32bSmrg    if (client->swapped) {
225bbe1b32bSmrg	stuff->length = lswaps(stuff->length);
226bbe1b32bSmrg    }
227bbe1b32bSmrg    ResetCurrentRequest(client);
228bbe1b32bSmrg    return client->noClientException;
229bbe1b32bSmrg}
230bbe1b32bSmrg
231bbe1b32bSmrgint
232bbe1b32bSmrgProcEstablishConnection(ClientPtr client)
233bbe1b32bSmrg{
234bbe1b32bSmrg    fsConnClientPrefix *prefix;
235bbe1b32bSmrg    fsConnSetup csp;
236bbe1b32bSmrg    int         ret;
237bbe1b32bSmrg    pointer     auth_data;
238bbe1b32bSmrg    char       *ad;
239bbe1b32bSmrg    char       *server_auth_data;
240bbe1b32bSmrg    AuthPtr     client_auth;
241bbe1b32bSmrg    int         i,
242bbe1b32bSmrg                num_alts,
243bbe1b32bSmrg                altlen,
244bbe1b32bSmrg                auth_accept,
245bbe1b32bSmrg                auth_index,
246bbe1b32bSmrg                auth_len;
247bbe1b32bSmrg    AlternateServerPtr altservers;
248bbe1b32bSmrg
249bbe1b32bSmrg    REQUEST(fsFakeReq);
250bbe1b32bSmrg
251bbe1b32bSmrg    prefix = (fsConnClientPrefix *) stuff+1;
252bbe1b32bSmrg    auth_data = prefix + sz_fsConnClientPrefix;
253bbe1b32bSmrg    client_auth = (AuthPtr) ALLOCATE_LOCAL(prefix->num_auths * sizeof(AuthRec));
254bbe1b32bSmrg    if (!client_auth) {
255bbe1b32bSmrg	SendErrToClient(client, FSBadAlloc, (pointer) 0);
256bbe1b32bSmrg	return FSBadAlloc;
257bbe1b32bSmrg    }
258bbe1b32bSmrg/* XXXX -- this needs work for multiple auth replies */
259bbe1b32bSmrg
260bbe1b32bSmrg    /* build up a list of the stuff */
261bbe1b32bSmrg    for (i = 0, ad = auth_data; i < (int)prefix->num_auths; i++) {
262bbe1b32bSmrg	if (ad - (char *)auth_data > (stuff->length << 2) - 4) {
263bbe1b32bSmrg	    int lengthword = stuff->length;
264bbe1b32bSmrg
265bbe1b32bSmrg	    SendErrToClient(client, FSBadLength, (pointer)&lengthword);
266bbe1b32bSmrg	    return (FSBadLength);
267bbe1b32bSmrg	}
268bbe1b32bSmrg	/* copy carefully in case wire data is not aligned */
269bbe1b32bSmrg	client_auth[i].namelen = (((unsigned char *)ad)[0] << 8) +
270bbe1b32bSmrg				 ((unsigned char *)ad)[1];
271bbe1b32bSmrg	ad += 2;
272bbe1b32bSmrg	client_auth[i].datalen = (((unsigned char *)ad)[0] << 8) +
273bbe1b32bSmrg				 ((unsigned char *)ad)[1];
274bbe1b32bSmrg	ad += 2;
275bbe1b32bSmrg	client_auth[i].name = (char *) ad;
276bbe1b32bSmrg	ad += client_auth[i].namelen;
277bbe1b32bSmrg	client_auth[i].data = (char *) ad;
278bbe1b32bSmrg	ad += client_auth[i].datalen;
279bbe1b32bSmrg    }
280bbe1b32bSmrg    if (!(int)prefix->num_auths)
281bbe1b32bSmrg	ad += 4;
282bbe1b32bSmrg    if (ad - (char *)auth_data > (stuff->length << 2)) {
283bbe1b32bSmrg	int lengthword = stuff->length;
284bbe1b32bSmrg
285bbe1b32bSmrg	SendErrToClient(client, FSBadLength, (pointer)&lengthword);
286bbe1b32bSmrg	return (FSBadLength);
287bbe1b32bSmrg    }
288bbe1b32bSmrg
289bbe1b32bSmrg    num_alts = ListAlternateServers(&altservers);
290bbe1b32bSmrg    for (i = 0, altlen = 0; i < num_alts; i++) {
291bbe1b32bSmrg	/* subset + len + namelen + pad */
292bbe1b32bSmrg	altlen += (2 + altservers[i].namelen + 3) >> 2;
293bbe1b32bSmrg    }
294bbe1b32bSmrg
295bbe1b32bSmrg    auth_index = prefix->num_auths;
296bbe1b32bSmrg    client->auth_generation = 0;
297bbe1b32bSmrg    ret = CheckClientAuthorization(client, client_auth,
298bbe1b32bSmrg		    &auth_accept, &auth_index, &auth_len, &server_auth_data);
299bbe1b32bSmrg    if (auth_index > 0)
300bbe1b32bSmrg    {
301bbe1b32bSmrg	AuthContextPtr authp;
302bbe1b32bSmrg	authp = (AuthContextPtr) fsalloc(sizeof(AuthContextRec));
303bbe1b32bSmrg	if (!authp) {
304bbe1b32bSmrg	    SendErrToClient(client, FSBadAlloc, (pointer) 0);
305bbe1b32bSmrg	    return FSBadAlloc;
306bbe1b32bSmrg	}
307bbe1b32bSmrg	authp->authname = 0;
308bbe1b32bSmrg	authp->authdata = 0;
309bbe1b32bSmrg	authp->authname =
310bbe1b32bSmrg	    (char *) fsalloc(client_auth[auth_index - 1].namelen + 1);
311bbe1b32bSmrg	authp->authdata =
312bbe1b32bSmrg	    (char *) fsalloc(client_auth[auth_index - 1].datalen + 1);
313bbe1b32bSmrg	if (!authp->authname || !authp->authdata) {
314bbe1b32bSmrg	    fsfree((char *) authp->authname);
315bbe1b32bSmrg	    fsfree((char *) authp->authdata);
316bbe1b32bSmrg	    fsfree((char *) authp);
317bbe1b32bSmrg	    SendErrToClient(client, FSBadAlloc, (pointer) 0);
318bbe1b32bSmrg	    return FSBadAlloc;
319bbe1b32bSmrg	}
320bbe1b32bSmrg	memmove( authp->authname, client_auth[auth_index - 1].name,
321bbe1b32bSmrg	      client_auth[auth_index - 1].namelen);
322bbe1b32bSmrg	memmove( authp->authdata, client_auth[auth_index - 1].data,
323bbe1b32bSmrg	      client_auth[auth_index - 1].datalen);
324bbe1b32bSmrg	/* Save it with a zero resource id...  subsequent
325bbe1b32bSmrg	   SetAuthorizations of None will find it.  And it will be freed
326bbe1b32bSmrg	   by FreeClientResources when the connection closes.  */
327bbe1b32bSmrg	if (!AddResource(client->index, 0, RT_AUTHCONT,(pointer) authp))
328bbe1b32bSmrg	{
329bbe1b32bSmrg	    fsfree((char *) authp->authname);
330bbe1b32bSmrg	    fsfree((char *) authp->authdata);
331bbe1b32bSmrg	    fsfree((char *) authp);
332bbe1b32bSmrg	    SendErrToClient(client, FSBadAlloc, (pointer) 0);
333bbe1b32bSmrg	    return FSBadAlloc;
334bbe1b32bSmrg	}
335bbe1b32bSmrg	client->auth = client->default_auth = authp;
336bbe1b32bSmrg    }
337bbe1b32bSmrg    else
338bbe1b32bSmrg	client->auth = client->default_auth = (AuthContextPtr)0;
339bbe1b32bSmrg
340bbe1b32bSmrg    DEALLOCATE_LOCAL(client_auth);
341bbe1b32bSmrg
342bbe1b32bSmrg    if (ret != FSSuccess) {
343bbe1b32bSmrg	SendErrToClient(client, FSBadAlloc, (pointer) 0);
344bbe1b32bSmrg	return FSBadAlloc;
345bbe1b32bSmrg    }
346bbe1b32bSmrg    csp.status = auth_accept;
347bbe1b32bSmrg    if (client->major_version == 1)
348bbe1b32bSmrg	/* we implement backwards compatibility for version 1.0 */
349bbe1b32bSmrg	csp.major_version = client->major_version;
350bbe1b32bSmrg    else
351bbe1b32bSmrg	csp.major_version = FS_PROTOCOL;
352bbe1b32bSmrg    csp.minor_version = FS_PROTOCOL_MINOR;
353bbe1b32bSmrg    csp.num_alternates = num_alts;
354bbe1b32bSmrg    csp.alternate_len = altlen;
355bbe1b32bSmrg    csp.auth_len = auth_len >> 2;
356bbe1b32bSmrg    csp.auth_index = auth_index;
357bbe1b32bSmrg    if (client->swapped) {
358bbe1b32bSmrg	WriteSConnSetup(client, &csp);
359bbe1b32bSmrg    } else {
360bbe1b32bSmrg	(void) WriteToClient(client, SIZEOF(fsConnSetup), (char *) &csp);
361bbe1b32bSmrg    }
362bbe1b32bSmrg
363bbe1b32bSmrg    /* send the alternates info */
364bbe1b32bSmrg    for (i = 0; i < num_alts; i++) {
365bbe1b32bSmrg	char        tmp[258];
366bbe1b32bSmrg
367bbe1b32bSmrg	/* WriteToClient pads, so we have to fake some things */
368bbe1b32bSmrg	tmp[0] = altservers[i].subset;
369bbe1b32bSmrg	tmp[1] = altservers[i].namelen;
370bbe1b32bSmrg	memmove( (char *) &tmp[2], altservers[i].name, altservers[i].namelen);
371bbe1b32bSmrg	(void) WriteToClient(client, altservers[i].namelen + 2, tmp);
372bbe1b32bSmrg    }
373bbe1b32bSmrg
374bbe1b32bSmrg    if (auth_len)
375bbe1b32bSmrg	(void) WriteToClient(client, auth_len, (char *) server_auth_data);
376bbe1b32bSmrg
377bbe1b32bSmrg    if (auth_accept != AuthSuccess) {
378bbe1b32bSmrg	nClients--;
379bbe1b32bSmrg	return (client->noClientException = -2);
380bbe1b32bSmrg    }
381bbe1b32bSmrg    client->requestVector = client->swapped ? SwappedProcVector : ProcVector;
382bbe1b32bSmrg    client->sequence = 0;
383bbe1b32bSmrg    if (client->swapped)
384bbe1b32bSmrg	(void) WriteSConnectionInfo(client, ConnInfoLen, ConnectionInfo);
385bbe1b32bSmrg    else
386bbe1b32bSmrg	(void) WriteToClient(client, ConnInfoLen, ConnectionInfo);
387bbe1b32bSmrg
388bbe1b32bSmrg#ifdef DEBUG
389bbe1b32bSmrg    fprintf(stderr, "Establishing new connection\n");
390bbe1b32bSmrg#endif
391bbe1b32bSmrg
392bbe1b32bSmrg    return client->noClientException;
393bbe1b32bSmrg}
394bbe1b32bSmrg
395bbe1b32bSmrg/*
396bbe1b32bSmrg * NOTE -- the incoming data may be mangled
397bbe1b32bSmrg */
398bbe1b32bSmrg
399bbe1b32bSmrgvoid
400bbe1b32bSmrgDoSendErrToClient(
401bbe1b32bSmrg    ClientPtr   client,
402bbe1b32bSmrg    int         error,
403bbe1b32bSmrg    pointer     data)		/* resource id, format, resolution, etc */
404bbe1b32bSmrg{
405bbe1b32bSmrg    fsError     rep;
406bbe1b32bSmrg    int         extralen = 0;
407bbe1b32bSmrg
408bbe1b32bSmrg    switch (error) {
409bbe1b32bSmrg    case FSBadFormat:
410bbe1b32bSmrg	extralen = SIZEOF(fsBitmapFormat);
411bbe1b32bSmrg	break;
412bbe1b32bSmrg    case FSBadFont:
413bbe1b32bSmrg    case FSBadAccessContext:
414bbe1b32bSmrg    case FSBadIDChoice:
415bbe1b32bSmrg    case FSBadEventMask:
416bbe1b32bSmrg	if (data) {
417bbe1b32bSmrg	    if (client->swapped)
418bbe1b32bSmrg	        SwapLongs((long *) data, 1);
419bbe1b32bSmrg	    extralen = 4;
420bbe1b32bSmrg	}
421bbe1b32bSmrg	break;
422bbe1b32bSmrg    case FSBadRange:
423bbe1b32bSmrg	extralen = SIZEOF(fsRange);
424bbe1b32bSmrg	break;
425bbe1b32bSmrg    case FSBadResolution:
426bbe1b32bSmrg	if (data) {
427bbe1b32bSmrg	    if (client->swapped)
428bbe1b32bSmrg	        SwapShorts((short *) data, 1);
429bbe1b32bSmrg	    /* note sneaky hack */
430bbe1b32bSmrg	    rep.pad = *(CARD16 *) data;
431bbe1b32bSmrg	    data = (char *)data + 2;
432bbe1b32bSmrg	    extralen = 4;
433bbe1b32bSmrg	}
434bbe1b32bSmrg	break;
435bbe1b32bSmrg    case FSBadLength:
436bbe1b32bSmrg	if (data) {
437bbe1b32bSmrg	    if (client->swapped)
438bbe1b32bSmrg	        SwapLongs((long *) data, 1);
439bbe1b32bSmrg	    extralen = 4;
440bbe1b32bSmrg	}
441bbe1b32bSmrg	break;
442bbe1b32bSmrg    default:
443bbe1b32bSmrg	/* nothing else to send */
444bbe1b32bSmrg	break;
445bbe1b32bSmrg    }
446bbe1b32bSmrg
447bbe1b32bSmrg    rep.type = FS_Error;
448bbe1b32bSmrg    rep.sequenceNumber = client->sequence;
449bbe1b32bSmrg    rep.request = error;
450bbe1b32bSmrg    rep.major_opcode = ((fsReq *) client->requestBuffer)->reqType;
451bbe1b32bSmrg    rep.minor_opcode = MinorOpcodeOfRequest(client),
452bbe1b32bSmrg	rep.timestamp = GetTimeInMillis();
453bbe1b32bSmrg    rep.length = (SIZEOF(fsError) + extralen) >> 2;
454bbe1b32bSmrg
455bbe1b32bSmrg    WriteErrorToClient(client, &rep);
456bbe1b32bSmrg
457bbe1b32bSmrg    if (extralen)
458bbe1b32bSmrg	WriteToClient(client, extralen, (char *) data);
459bbe1b32bSmrg}
460bbe1b32bSmrg
461bbe1b32bSmrg/* ARGSUSED */
462bbe1b32bSmrgint
463bbe1b32bSmrgProcBadRequest(ClientPtr client)
464bbe1b32bSmrg{
465bbe1b32bSmrg    SendErrToClient(client, FSBadRequest, NULL);
466bbe1b32bSmrg    return FSBadRequest;
467bbe1b32bSmrg}
468bbe1b32bSmrg
469bbe1b32bSmrgint
470bbe1b32bSmrgProcNoop(ClientPtr client)
471bbe1b32bSmrg{
472bbe1b32bSmrg    REQUEST(fsReq);
473bbe1b32bSmrg    REQUEST_AT_LEAST_SIZE(fsReq);
474bbe1b32bSmrg
475bbe1b32bSmrg    return client->noClientException;
476bbe1b32bSmrg}
477bbe1b32bSmrg
478bbe1b32bSmrgint
479bbe1b32bSmrgProcListCatalogues(ClientPtr client)
480bbe1b32bSmrg{
481bbe1b32bSmrg    int         len,
482bbe1b32bSmrg                num;
483bbe1b32bSmrg    char       *catalogues;
484bbe1b32bSmrg    fsListCataloguesReply rep;
485bbe1b32bSmrg
486bbe1b32bSmrg    REQUEST(fsListCataloguesReq);
487bbe1b32bSmrg    REQUEST_AT_LEAST_SIZE(fsListCataloguesReq);
488bbe1b32bSmrg
489bbe1b32bSmrg    num = ListCatalogues((char *)stuff + SIZEOF(fsListCataloguesReq),
490bbe1b32bSmrg			 stuff->nbytes, stuff->maxNames,
491bbe1b32bSmrg			 &catalogues, &len);
492bbe1b32bSmrg    rep.type = FS_Reply;
493bbe1b32bSmrg    rep.num_replies = 0;
494bbe1b32bSmrg    rep.num_catalogues = num;
495bbe1b32bSmrg    rep.sequenceNumber = client->sequence;
496bbe1b32bSmrg    rep.length = (SIZEOF(fsListCataloguesReply) + len + 3) >> 2;
497bbe1b32bSmrg
498bbe1b32bSmrg    WriteReplyToClient(client, SIZEOF(fsListCataloguesReply), &rep);
499bbe1b32bSmrg    (void) WriteToClient(client, len, (char *) catalogues);
500bbe1b32bSmrg    fsfree((char *) catalogues);
501bbe1b32bSmrg    return client->noClientException;
502bbe1b32bSmrg}
503bbe1b32bSmrg
504bbe1b32bSmrgint
505bbe1b32bSmrgProcSetCatalogues(ClientPtr client)
506bbe1b32bSmrg{
507bbe1b32bSmrg    char       *new_cat;
508bbe1b32bSmrg    int         err,
509bbe1b32bSmrg                len;
510bbe1b32bSmrg    int         num;
511bbe1b32bSmrg
512bbe1b32bSmrg    REQUEST(fsSetCataloguesReq);
513bbe1b32bSmrg    REQUEST_AT_LEAST_SIZE(fsSetCataloguesReq);
514bbe1b32bSmrg
515bbe1b32bSmrg    if (stuff->num_catalogues == 0) {
516bbe1b32bSmrg	/* use the default */
517bbe1b32bSmrg	num = ListCatalogues("*", 1, 10000, &new_cat, &len);
518bbe1b32bSmrg    } else {
519bbe1b32bSmrg	num = stuff->num_catalogues;
520bbe1b32bSmrg	err = ValidateCatalogues(&num, (char *)stuff + SIZEOF(fsSetCataloguesReq));
521bbe1b32bSmrg	if (err == FSSuccess) {
522bbe1b32bSmrg	    len = (stuff->length << 2) - SIZEOF(fsSetCataloguesReq);
523bbe1b32bSmrg	    new_cat = (char *) fsalloc(len);
524bbe1b32bSmrg	    if (!new_cat)
525bbe1b32bSmrg		return FSBadAlloc;
526bbe1b32bSmrg	    memmove( new_cat, (char *)stuff + SIZEOF(fsSetCataloguesReq), len);
527bbe1b32bSmrg	} else {
528bbe1b32bSmrg	    SendErrToClient(client, err, (pointer) &num);
529bbe1b32bSmrg	    return err;
530bbe1b32bSmrg	}
531bbe1b32bSmrg    }
532bbe1b32bSmrg    if (client->catalogues)
533bbe1b32bSmrg	fsfree((char *) client->catalogues);
534bbe1b32bSmrg    client->catalogues = new_cat;
535bbe1b32bSmrg    client->num_catalogues = num;
536bbe1b32bSmrg    return client->noClientException;
537bbe1b32bSmrg}
538bbe1b32bSmrg
539bbe1b32bSmrgint
540bbe1b32bSmrgProcGetCatalogues(ClientPtr client)
541bbe1b32bSmrg{
542bbe1b32bSmrg    int         len,
543bbe1b32bSmrg                i,
544bbe1b32bSmrg                size;
545bbe1b32bSmrg    char       *cp;
546bbe1b32bSmrg    fsGetCataloguesReply rep;
547bbe1b32bSmrg
548bbe1b32bSmrg    REQUEST(fsGetCataloguesReq);
549bbe1b32bSmrg    REQUEST_AT_LEAST_SIZE(fsGetCataloguesReq);
550bbe1b32bSmrg
551bbe1b32bSmrg    for (i = 0, len = 0, cp = client->catalogues;
552bbe1b32bSmrg	    i < client->num_catalogues; i++) {
553bbe1b32bSmrg	size = *cp++;
554bbe1b32bSmrg	len += size + 1;	/* str length + size byte */
555bbe1b32bSmrg	cp += size;
556bbe1b32bSmrg    }
557bbe1b32bSmrg
558bbe1b32bSmrg    rep.type = FS_Reply;
559bbe1b32bSmrg    rep.num_catalogues = client->num_catalogues;
560bbe1b32bSmrg    rep.sequenceNumber = client->sequence;
561bbe1b32bSmrg    rep.length = (SIZEOF(fsGetCataloguesReply) + len + 3) >> 2;
562bbe1b32bSmrg
563bbe1b32bSmrg    WriteReplyToClient(client, SIZEOF(fsGetCataloguesReply), &rep);
564bbe1b32bSmrg    (void) WriteToClient(client, len, client->catalogues);
565bbe1b32bSmrg
566bbe1b32bSmrg    return client->noClientException;
567bbe1b32bSmrg}
568bbe1b32bSmrg
569bbe1b32bSmrgint
570bbe1b32bSmrgProcCreateAC(ClientPtr client)
571bbe1b32bSmrg{
572bbe1b32bSmrg    fsCreateACReply rep;
573bbe1b32bSmrg    AuthPtr     acp;
574bbe1b32bSmrg    AuthContextPtr authp;
575bbe1b32bSmrg    int         accept,
576bbe1b32bSmrg                i,
577bbe1b32bSmrg                err,
578bbe1b32bSmrg                index,
579bbe1b32bSmrg                size;
580bbe1b32bSmrg    char       *ad;
581bbe1b32bSmrg    char       *auth_data;
582bbe1b32bSmrg
583bbe1b32bSmrg    REQUEST(fsCreateACReq);
584bbe1b32bSmrg    REQUEST_AT_LEAST_SIZE(fsCreateACReq);
585bbe1b32bSmrg
586bbe1b32bSmrg    authp = (AuthContextPtr) LookupIDByType(client->index, stuff->acid,
587bbe1b32bSmrg					    RT_AUTHCONT);
588bbe1b32bSmrg    if (authp) {
589bbe1b32bSmrg	int aligned_acid = stuff->acid;
590bbe1b32bSmrg	SendErrToClient(client, FSBadIDChoice, (pointer) &aligned_acid);
591bbe1b32bSmrg	return FSBadIDChoice;
592bbe1b32bSmrg    }
593bbe1b32bSmrg    acp = 0;
594bbe1b32bSmrg    if (stuff->num_auths)
595bbe1b32bSmrg    {
596bbe1b32bSmrg    	acp = (AuthPtr) ALLOCATE_LOCAL(stuff->num_auths * sizeof(AuthRec));
597bbe1b32bSmrg    	if (!acp) {
598bbe1b32bSmrg	    SendErrToClient(client, FSBadAlloc, (pointer) 0);
599bbe1b32bSmrg	    return FSBadAlloc;
600bbe1b32bSmrg    	}
601bbe1b32bSmrg    }
602bbe1b32bSmrg    /* build up a list of the stuff */
603bbe1b32bSmrg    for (i = 0, ad = (char *)stuff + SIZEOF(fsCreateACReq);
604bbe1b32bSmrg         i < (int)stuff->num_auths; i++) {
605bbe1b32bSmrg	if (ad - (char *)stuff + SIZEOF(fsCreateACReq) >
606bbe1b32bSmrg	    (stuff->length << 2) - 4) {
607bbe1b32bSmrg	    int lengthword = stuff->length;
608bbe1b32bSmrg
609bbe1b32bSmrg	    SendErrToClient(client, FSBadLength, (pointer)&lengthword);
610bbe1b32bSmrg	    return (FSBadLength);
611bbe1b32bSmrg	}
612bbe1b32bSmrg	/* copy carefully in case data is not aligned */
613bbe1b32bSmrg	acp[i].namelen = (((unsigned char *)ad)[0] << 8) +
614bbe1b32bSmrg			 ((unsigned char *)ad)[1];
615bbe1b32bSmrg	ad += 2;
616bbe1b32bSmrg	acp[i].datalen = (((unsigned char *)ad)[0] << 8) +
617bbe1b32bSmrg			 ((unsigned char *)ad)[1];
618bbe1b32bSmrg	ad += 2;
619bbe1b32bSmrg	acp[i].name = (char *) ad;
620bbe1b32bSmrg	ad += acp[i].namelen;
621bbe1b32bSmrg	acp[i].data = (char *) ad;
622bbe1b32bSmrg	ad += acp[i].datalen;
623bbe1b32bSmrg    }
624bbe1b32bSmrg    if (!(int)stuff->num_auths)
625bbe1b32bSmrg	ad += 4;
626bbe1b32bSmrg    if (ad - (char *)stuff > (stuff->length << 2)) {
627bbe1b32bSmrg	int lengthword = stuff->length;
628bbe1b32bSmrg
629bbe1b32bSmrg	SendErrToClient(client, FSBadLength, (pointer)&lengthword);
630bbe1b32bSmrg	return (FSBadLength);
631bbe1b32bSmrg    }
632bbe1b32bSmrg
633bbe1b32bSmrg/* XXX needs work for AuthContinue */
634bbe1b32bSmrg    index = stuff->num_auths;
635bbe1b32bSmrg    err = CheckClientAuthorization(client, acp, &accept, &index, &size,
636bbe1b32bSmrg				   &auth_data);
637bbe1b32bSmrg
638bbe1b32bSmrg    if (err != FSSuccess) {
639bbe1b32bSmrg	SendErrToClient(client, err, (pointer) 0);
640bbe1b32bSmrg	if (acp)
641bbe1b32bSmrg	    DEALLOCATE_LOCAL(acp);
642bbe1b32bSmrg	return err;
643bbe1b32bSmrg    }
644bbe1b32bSmrg    authp = (AuthContextPtr) fsalloc(sizeof(AuthContextRec));
645bbe1b32bSmrg    if (!authp) {
646bbe1b32bSmrg	goto alloc_failure;
647bbe1b32bSmrg    }
648bbe1b32bSmrg    authp->authname = 0;
649bbe1b32bSmrg    authp->authdata = 0;
650bbe1b32bSmrg    if (index > 0)
651bbe1b32bSmrg    {
652bbe1b32bSmrg	authp->authname = (char *) fsalloc(acp[index - 1].namelen + 1);
653bbe1b32bSmrg	authp->authdata = (char *) fsalloc(acp[index - 1].datalen + 1);
654bbe1b32bSmrg	if (!authp->authname || !authp->authdata) {
655bbe1b32bSmrg	    fsfree((char *) authp->authname);
656bbe1b32bSmrg	    fsfree((char *) authp->authdata);
657bbe1b32bSmrg	    fsfree((char *) authp);
658bbe1b32bSmrg	    goto alloc_failure;
659bbe1b32bSmrg	}
660bbe1b32bSmrg	memmove( authp->authname, acp[index - 1].name, acp[index - 1].namelen);
661bbe1b32bSmrg	memmove( authp->authdata, acp[index - 1].data, acp[index - 1].datalen);
662bbe1b32bSmrg    }
663bbe1b32bSmrg    else
664bbe1b32bSmrg	size = 0;
665bbe1b32bSmrg    authp->acid = stuff->acid;
666bbe1b32bSmrg    if (!AddResource(client->index, stuff->acid, RT_AUTHCONT,(pointer) authp))
667bbe1b32bSmrg    {
668bbe1b32bSmrgalloc_failure:
669bbe1b32bSmrg	SendErrToClient(client, FSBadAlloc, (pointer) 0);
670bbe1b32bSmrg	if (acp)
671bbe1b32bSmrg	    DEALLOCATE_LOCAL(acp);
672bbe1b32bSmrg	return FSBadAlloc;
673bbe1b32bSmrg    }
674bbe1b32bSmrg    DEALLOCATE_LOCAL(acp);
675bbe1b32bSmrg    rep.type = FS_Reply;
676bbe1b32bSmrg    rep.status = accept;
677bbe1b32bSmrg    rep.auth_index = index;
678bbe1b32bSmrg    rep.sequenceNumber = client->sequence;
679bbe1b32bSmrg    rep.length = (SIZEOF(fsCreateACReply) + size) >> 2;
680bbe1b32bSmrg
681bbe1b32bSmrg    WriteReplyToClient(client, SIZEOF(fsCreateACReply), &rep);
682bbe1b32bSmrg    if (size)
683bbe1b32bSmrg	(void) WriteToClient(client, size, auth_data);
684bbe1b32bSmrg
685bbe1b32bSmrg    return client->noClientException;
686bbe1b32bSmrg}
687bbe1b32bSmrg
688bbe1b32bSmrg/* ARGSUSED */
689bbe1b32bSmrgint
690bbe1b32bSmrgDeleteAuthCont (pointer value, FSID id)
691bbe1b32bSmrg{
692bbe1b32bSmrg    AuthContextPtr  authp = (AuthContextPtr) value;
693bbe1b32bSmrg
694bbe1b32bSmrg    if (authp->authname)
695bbe1b32bSmrg	fsfree (authp->authname);
696bbe1b32bSmrg    if (authp->authdata)
697bbe1b32bSmrg	fsfree (authp->authdata);
698bbe1b32bSmrg    fsfree (authp);
699bbe1b32bSmrg    return 1;
700bbe1b32bSmrg}
701bbe1b32bSmrg
702bbe1b32bSmrgint
703bbe1b32bSmrgProcFreeAC(ClientPtr client)
704bbe1b32bSmrg{
705bbe1b32bSmrg    AuthContextPtr authp;
706bbe1b32bSmrg
707bbe1b32bSmrg    REQUEST(fsFreeACReq);
708bbe1b32bSmrg    REQUEST_AT_LEAST_SIZE(fsFreeACReq);
709bbe1b32bSmrg    authp = (AuthContextPtr) LookupIDByType(client->index, stuff->id,
710bbe1b32bSmrg					  RT_AUTHCONT);
711bbe1b32bSmrg    if (!authp) {
712bbe1b32bSmrg	int aligned_id = stuff->id;
713bbe1b32bSmrg	SendErrToClient(client, FSBadIDChoice, (pointer) &aligned_id);
714bbe1b32bSmrg	return FSBadIDChoice;
715bbe1b32bSmrg    }
716bbe1b32bSmrg    if (client->auth == authp)
717bbe1b32bSmrg	client->auth = client->default_auth;
718bbe1b32bSmrg    FreeResource(client->index, stuff->id, RT_NONE);
719bbe1b32bSmrg    return client->noClientException;
720bbe1b32bSmrg}
721bbe1b32bSmrg
722bbe1b32bSmrgint
723bbe1b32bSmrgProcSetAuthorization(ClientPtr client)
724bbe1b32bSmrg{
725bbe1b32bSmrg    AuthContextPtr acp;
726bbe1b32bSmrg
727bbe1b32bSmrg    REQUEST(fsSetAuthorizationReq);
728bbe1b32bSmrg    REQUEST_AT_LEAST_SIZE(fsSetAuthorizationReq);
729bbe1b32bSmrg    acp = (AuthContextPtr) LookupIDByType(client->index, stuff->id,
730bbe1b32bSmrg					  RT_AUTHCONT);
731bbe1b32bSmrg    if (!acp) {
732bbe1b32bSmrg	int aligned_id = stuff->id;
733bbe1b32bSmrg	SendErrToClient(client, FSBadIDChoice, (pointer) &aligned_id);
734bbe1b32bSmrg	return FSBadIDChoice;
735bbe1b32bSmrg    }
736bbe1b32bSmrg    client->auth = acp;		/* XXX does this need a refcount? */
737bbe1b32bSmrg    return client->noClientException;
738bbe1b32bSmrg}
739bbe1b32bSmrg
740bbe1b32bSmrgint
741bbe1b32bSmrgProcSetResolution(ClientPtr client)
742bbe1b32bSmrg{
743bbe1b32bSmrg    fsResolution *new_res;
744bbe1b32bSmrg
745bbe1b32bSmrg    REQUEST(fsSetResolutionReq);
746bbe1b32bSmrg    REQUEST_AT_LEAST_SIZE(fsSetResolutionReq);
747bbe1b32bSmrg
748bbe1b32bSmrg    if ((stuff->length << 2) - SIZEOF(fsSetResolutionReq) <
749bbe1b32bSmrg        stuff->num_resolutions * SIZEOF(fsResolution)) {
750bbe1b32bSmrg	int lengthword = stuff->length;
751bbe1b32bSmrg
752bbe1b32bSmrg	SendErrToClient(client, FSBadLength, &lengthword);
753bbe1b32bSmrg	return FSBadLength;
754bbe1b32bSmrg    }
755bbe1b32bSmrg    new_res = (fsResolution *)
756bbe1b32bSmrg	fsalloc(SIZEOF(fsResolution) * stuff->num_resolutions);
757bbe1b32bSmrg    if (!new_res) {
758bbe1b32bSmrg	SendErrToClient(client, FSBadAlloc, NULL);
759bbe1b32bSmrg	return FSBadAlloc;
760bbe1b32bSmrg    }
761bbe1b32bSmrg    fsfree((char *) client->resolutions);
762bbe1b32bSmrg    memmove( (char *) new_res, (char *)stuff + SIZEOF(fsSetResolutionReq),
763bbe1b32bSmrg	  (stuff->num_resolutions * SIZEOF(fsResolution)));
764bbe1b32bSmrg    client->resolutions = new_res;
765bbe1b32bSmrg    client->num_resolutions = stuff->num_resolutions;
766bbe1b32bSmrg
767bbe1b32bSmrg    return client->noClientException;
768bbe1b32bSmrg}
769bbe1b32bSmrg
770bbe1b32bSmrgint
771bbe1b32bSmrgProcGetResolution(ClientPtr client)
772bbe1b32bSmrg{
773bbe1b32bSmrg    fsGetResolutionReply reply;
774bbe1b32bSmrg
775bbe1b32bSmrg    REQUEST(fsReq);
776bbe1b32bSmrg    REQUEST_AT_LEAST_SIZE(fsReq);
777bbe1b32bSmrg
778bbe1b32bSmrg    if ((stuff->length << 2) - SIZEOF(fsResolution) < client->num_resolutions *
779bbe1b32bSmrg	sizeof(fsResolution)) {
780bbe1b32bSmrg	int lengthword = stuff->length;
781bbe1b32bSmrg
782bbe1b32bSmrg	SendErrToClient(client, FSBadLength, &lengthword);
783bbe1b32bSmrg	return FSBadLength;
784bbe1b32bSmrg    }
785bbe1b32bSmrg    reply.type = FS_Reply;
786bbe1b32bSmrg    reply.num_resolutions = client->num_resolutions;
787bbe1b32bSmrg    reply.sequenceNumber = client->sequence;
788bbe1b32bSmrg    reply.length = (SIZEOF(fsGetResolutionReply) +
789bbe1b32bSmrg		    client->num_resolutions * SIZEOF(fsResolution)) >> 2;
790bbe1b32bSmrg
791bbe1b32bSmrg    WriteReplyToClient(client, SIZEOF(fsGetResolutionReply), &reply);
792bbe1b32bSmrg    if (client->swapped)
793bbe1b32bSmrg	client->pSwapReplyFunc = CopySwap16Write;
794bbe1b32bSmrg
795bbe1b32bSmrg    WriteSwappedDataToClient(client,
796bbe1b32bSmrg       (client->num_resolutions * SIZEOF(fsResolution)), (short *)client->resolutions);
797bbe1b32bSmrg
798bbe1b32bSmrg    return client->noClientException;
799bbe1b32bSmrg}
800bbe1b32bSmrg
801bbe1b32bSmrgint
802bbe1b32bSmrgProcListFonts(ClientPtr client)
803bbe1b32bSmrg{
804bbe1b32bSmrg    REQUEST(fsListFontsReq);
805bbe1b32bSmrg    REQUEST_FIXED_SIZE(fsListFontsReq, stuff->nbytes);
806bbe1b32bSmrg
807bbe1b32bSmrg    return ListFonts(client, stuff->nbytes,
808bbe1b32bSmrg		     (unsigned char *)stuff + SIZEOF(fsListFontsReq),
809bbe1b32bSmrg		     stuff->maxNames);
810bbe1b32bSmrg}
811bbe1b32bSmrg
812bbe1b32bSmrgint
813bbe1b32bSmrgProcListFontsWithXInfo(ClientPtr client)
814bbe1b32bSmrg{
815bbe1b32bSmrg    REQUEST(fsListFontsWithXInfoReq);
816bbe1b32bSmrg    REQUEST_FIXED_SIZE(fsListFontsWithXInfoReq, stuff->nbytes);
817bbe1b32bSmrg
818bbe1b32bSmrg    return StartListFontsWithInfo(client, stuff->nbytes,
819bbe1b32bSmrg				  (unsigned char *)stuff + SIZEOF(fsListFontsWithXInfoReq), stuff->maxNames);
820bbe1b32bSmrg}
821bbe1b32bSmrg
822bbe1b32bSmrgint
823bbe1b32bSmrgProcOpenBitmapFont(ClientPtr client)
824bbe1b32bSmrg{
825bbe1b32bSmrg    FontPtr     pfont;
826bbe1b32bSmrg    int         nbytes,
827bbe1b32bSmrg                err;
828bbe1b32bSmrg    unsigned char *fname;
829bbe1b32bSmrg
830bbe1b32bSmrg    REQUEST(fsOpenBitmapFontReq);
831bbe1b32bSmrg    fname = (unsigned char *)stuff + SIZEOF(fsOpenBitmapFontReq);
832bbe1b32bSmrg    nbytes = *fname++;
833bbe1b32bSmrg
834bbe1b32bSmrg    REQUEST_FIXED_SIZE(fsOpenBitmapFontReq, (nbytes + 1));
835bbe1b32bSmrg
836bbe1b32bSmrg    pfont = (FontPtr) LookupIDByType(client->index, stuff->fid, RT_FONT);
837bbe1b32bSmrg    if (pfont) {
838bbe1b32bSmrg	int aligned_fid = stuff->fid;
839bbe1b32bSmrg	SendErrToClient(client, FSBadIDChoice, (pointer) &aligned_fid);
840bbe1b32bSmrg	return FSBadIDChoice;
841bbe1b32bSmrg    }
842bbe1b32bSmrg    if (stuff->format_hint != 0 &&
843bbe1b32bSmrg	    stuff->format_hint & ~ALL_FORMAT_BITS) {
844bbe1b32bSmrg	int aligned_format_hint = stuff->format_hint;
845bbe1b32bSmrg	SendErrToClient(client, FSBadFormat, (pointer) &aligned_format_hint);
846bbe1b32bSmrg	return FSBadFormat;
847bbe1b32bSmrg    }
848bbe1b32bSmrg    if (stuff->format_mask & ~ALL_FORMAT_MASK_BITS) {
849bbe1b32bSmrg	int aligned_format_mask = stuff->format_mask;
850bbe1b32bSmrg	SendErrToClient(client, FSBadFormat, (pointer) &aligned_format_mask);
851bbe1b32bSmrg	return FSBadFormat;
852bbe1b32bSmrg    }
853bbe1b32bSmrg    err = OpenFont(client, stuff->fid, stuff->format_hint, stuff->format_mask,
854bbe1b32bSmrg		   nbytes, (char *) fname);
855bbe1b32bSmrg
856bbe1b32bSmrg    if (err == FSSuccess) {
857bbe1b32bSmrg	return client->noClientException;
858bbe1b32bSmrg    } else {
859bbe1b32bSmrg	return err;
860bbe1b32bSmrg    }
861bbe1b32bSmrg}
862bbe1b32bSmrg
863bbe1b32bSmrgint
864bbe1b32bSmrgProcQueryXInfo(ClientPtr client)
865bbe1b32bSmrg{
866bbe1b32bSmrg    ClientFontPtr cfp;
867bbe1b32bSmrg    int         err,
868bbe1b32bSmrg                lendata;
869bbe1b32bSmrg    fsQueryXInfoReply reply;
870bbe1b32bSmrg    fsPropInfo *prop_info;
871bbe1b32bSmrg
872bbe1b32bSmrg    REQUEST(fsQueryXInfoReq);
873bbe1b32bSmrg
874bbe1b32bSmrg    REQUEST_AT_LEAST_SIZE(fsQueryXInfoReq);
875bbe1b32bSmrg
876bbe1b32bSmrg    cfp = (ClientFontPtr) LookupIDByType(client->index, stuff->id, RT_FONT);
877bbe1b32bSmrg    if (!cfp) {
878bbe1b32bSmrg	int aligned_id = stuff->id;
879bbe1b32bSmrg	SendErrToClient(client, FSBadFont, (pointer) &aligned_id);
880bbe1b32bSmrg	return FSBadFont;
881bbe1b32bSmrg    }
882bbe1b32bSmrg    reply.type = FS_Reply;
883bbe1b32bSmrg    reply.sequenceNumber = client->sequence;
884bbe1b32bSmrg
885bbe1b32bSmrg    /* get the header */
886bbe1b32bSmrg    fsPack_XFontInfoHeader(&cfp->font->info, &reply, client->major_version);
887bbe1b32bSmrg    err = convert_props(&cfp->font->info, &prop_info);
888bbe1b32bSmrg
889bbe1b32bSmrg    switch (err)
890bbe1b32bSmrg    {
891bbe1b32bSmrg    case Successful:
892bbe1b32bSmrg	break;
893bbe1b32bSmrg    case AllocError:
894bbe1b32bSmrg	SendErrToClient(client, FSBadAlloc, (pointer) 0);
895bbe1b32bSmrg	return err;
896bbe1b32bSmrg    default:
897bbe1b32bSmrg	ErrorF("ProcQueryXInfo: unexpected return val %d from convert_props\n",
898bbe1b32bSmrg	       err);
899bbe1b32bSmrg	SendErrToClient(client, FSBadImplementation, (pointer) 0);
900bbe1b32bSmrg	return err;
901bbe1b32bSmrg    }
902bbe1b32bSmrg    lendata = SIZEOF(fsPropInfo) +
903bbe1b32bSmrg	prop_info->num_offsets * SIZEOF(fsPropOffset) +
904bbe1b32bSmrg	prop_info->data_len;
905bbe1b32bSmrg
906bbe1b32bSmrg    reply.length = (SIZEOF(fsQueryXInfoReply) + lendata + 3) >> 2;
907bbe1b32bSmrg    WriteReplyToClient(client, SIZEOF(fsQueryXInfoReply), &reply);
908bbe1b32bSmrg
909bbe1b32bSmrg    if (client->swapped)
910bbe1b32bSmrg	SwapPropInfo(prop_info);
911bbe1b32bSmrg    (void) WriteToClient(client, lendata, (char *) prop_info);
912bbe1b32bSmrg
913bbe1b32bSmrg    fsfree((char *) prop_info);
914bbe1b32bSmrg    return client->noClientException;
915bbe1b32bSmrg}
916bbe1b32bSmrg
917bbe1b32bSmrgint
918bbe1b32bSmrgProcQueryXExtents(ClientPtr client)
919bbe1b32bSmrg{
920bbe1b32bSmrg    ClientFontPtr cfp;
921bbe1b32bSmrg    int         err;
922bbe1b32bSmrg    int         item_size;
923bbe1b32bSmrg
924bbe1b32bSmrg    REQUEST(fsQueryXExtents8Req);
925bbe1b32bSmrg
926bbe1b32bSmrg    REQUEST_AT_LEAST_SIZE(fsQueryXExtents8Req);
927bbe1b32bSmrg
928bbe1b32bSmrg    cfp = (ClientFontPtr) LookupIDByType(client->index, stuff->fid, RT_FONT);
929bbe1b32bSmrg    if (!cfp) {
930bbe1b32bSmrg	int aligned_fid = stuff->fid;
931bbe1b32bSmrg	SendErrToClient(client, FSBadFont, (pointer) &aligned_fid);
932bbe1b32bSmrg	return FSBadFont;
933bbe1b32bSmrg    }
934bbe1b32bSmrg    item_size = (stuff->reqType == FS_QueryXExtents8) ? 1 : 2;
935bbe1b32bSmrg
936bbe1b32bSmrg    if (stuff->num_ranges >
937bbe1b32bSmrg	 ((stuff->length << 2) - SIZEOF(fsQueryXExtents8Req))/item_size) {
938bbe1b32bSmrg	int num_ranges = stuff->num_ranges;
939bbe1b32bSmrg	SendErrToClient(client, FSBadLength, (pointer)&num_ranges);
940bbe1b32bSmrg	return FSBadLength;
941bbe1b32bSmrg    }
942bbe1b32bSmrg
943bbe1b32bSmrg    /* get the extents */
944bbe1b32bSmrg    err = QueryExtents(client, cfp, item_size,
945bbe1b32bSmrg		       stuff->num_ranges, stuff->range,
946bbe1b32bSmrg		       (char *)stuff + SIZEOF(fsQueryXExtents8Req));
947bbe1b32bSmrg
948bbe1b32bSmrg    if (err != FSSuccess) {
949bbe1b32bSmrg	return err;
950bbe1b32bSmrg    } else
951bbe1b32bSmrg	return client->noClientException;
952bbe1b32bSmrg}
953bbe1b32bSmrg
954bbe1b32bSmrgint
955bbe1b32bSmrgProcQueryXBitmaps(ClientPtr client)
956bbe1b32bSmrg{
957bbe1b32bSmrg    ClientFontPtr cfp;
958bbe1b32bSmrg    int         err;
959bbe1b32bSmrg    int         item_size;
960bbe1b32bSmrg
961bbe1b32bSmrg    REQUEST(fsQueryXBitmaps8Req);
962bbe1b32bSmrg
963bbe1b32bSmrg    REQUEST_AT_LEAST_SIZE(fsQueryXBitmaps8Req);
964bbe1b32bSmrg
965bbe1b32bSmrg    cfp = (ClientFontPtr) LookupIDByType(client->index, stuff->fid, RT_FONT);
966bbe1b32bSmrg    if (!cfp) {
967bbe1b32bSmrg	int aligned_fid = stuff->fid;
968bbe1b32bSmrg	SendErrToClient(client, FSBadFont, (pointer) &aligned_fid);
969bbe1b32bSmrg	return FSBadFont;
970bbe1b32bSmrg    }
971bbe1b32bSmrg    if (stuff->format & ~ALL_FORMAT_BITS) {
972bbe1b32bSmrg	int aligned_format = stuff->format;
973bbe1b32bSmrg	SendErrToClient(client, FSBadFormat, (pointer) &aligned_format);
974bbe1b32bSmrg	return FSBadFormat;
975bbe1b32bSmrg    }
976bbe1b32bSmrg    assert((stuff->reqType == FS_QueryXBitmaps8) || (stuff->reqType == FS_QueryXBitmaps16));
977bbe1b32bSmrg    item_size = (stuff->reqType == FS_QueryXBitmaps8) ? 1 : 2;
978bbe1b32bSmrg
979bbe1b32bSmrg    if (stuff->num_ranges >
980bbe1b32bSmrg	((stuff->length << 2) - SIZEOF(fsQueryXBitmaps8Req))/item_size) {
981bbe1b32bSmrg	int num_ranges = stuff->num_ranges;
982bbe1b32bSmrg	SendErrToClient(client, FSBadLength, (pointer)&num_ranges);
983bbe1b32bSmrg	return FSBadLength;
984bbe1b32bSmrg    }
985bbe1b32bSmrg    /* get the glyphs */
986bbe1b32bSmrg    err = QueryBitmaps(client, cfp, item_size, stuff->format,
987bbe1b32bSmrg		       stuff->num_ranges, stuff->range,
988bbe1b32bSmrg		       (char *)stuff + SIZEOF(fsQueryXBitmaps8Req));
989bbe1b32bSmrg
990bbe1b32bSmrg    if (err != FSSuccess) {
991bbe1b32bSmrg	return err;
992bbe1b32bSmrg    } else {
993bbe1b32bSmrg	return client->noClientException;
994bbe1b32bSmrg    }
995bbe1b32bSmrg}
996bbe1b32bSmrg
997bbe1b32bSmrgint
998bbe1b32bSmrgProcCloseFont(ClientPtr client)
999bbe1b32bSmrg{
1000bbe1b32bSmrg    ClientFontPtr cfp;
1001bbe1b32bSmrg
1002bbe1b32bSmrg    REQUEST(fsResourceReq);
1003bbe1b32bSmrg
1004bbe1b32bSmrg    REQUEST_SIZE_MATCH(fsResourceReq);
1005bbe1b32bSmrg    cfp = (ClientFontPtr) LookupIDByType(client->index, stuff->id, RT_FONT);
1006bbe1b32bSmrg    if (cfp) {
1007bbe1b32bSmrg	FreeResource(client->index, stuff->id, RT_NONE);
1008bbe1b32bSmrg	return client->noClientException;
1009bbe1b32bSmrg    } else {
1010bbe1b32bSmrg	int aligned_id = stuff->id;
1011bbe1b32bSmrg	SendErrToClient(client, FSBadFont, (pointer) &aligned_id);
1012bbe1b32bSmrg	return FSBadFont;
1013bbe1b32bSmrg    }
1014bbe1b32bSmrg}
1015bbe1b32bSmrg
1016bbe1b32bSmrgvoid
1017bbe1b32bSmrgDoCloseDownClient(ClientPtr client)
1018bbe1b32bSmrg{
1019bbe1b32bSmrg    if (client->clientGone != CLIENT_GONE) {
1020bbe1b32bSmrg	DeleteClientFontStuff(client);
1021bbe1b32bSmrg	client->clientGone = CLIENT_GONE;
1022bbe1b32bSmrg	CloseDownConnection(client);
1023bbe1b32bSmrg	--nClients;
1024bbe1b32bSmrg    }
1025bbe1b32bSmrg
1026bbe1b32bSmrg    if (ClientIsAsleep(client))
1027bbe1b32bSmrg	ClientSignal((pointer)client);
1028bbe1b32bSmrg    else
1029bbe1b32bSmrg    {
1030bbe1b32bSmrg	FreeClientResources(client);
1031bbe1b32bSmrg	if (client->index < nextFreeClientID)
1032bbe1b32bSmrg	    nextFreeClientID = client->index;
1033bbe1b32bSmrg	clients[client->index] = NullClient;
1034bbe1b32bSmrg#ifdef DebugConnectionTranslation
1035bbe1b32bSmrg	CheckFileNumbers();
1036bbe1b32bSmrg#endif /* DebugConnectionTranslation */
1037bbe1b32bSmrg
1038bbe1b32bSmrg#ifdef NOTYET
1039bbe1b32bSmrg	/* reset server when last client goes away */
1040bbe1b32bSmrg	if (client->requestVector != InitialVector && nClients == 0)
1041bbe1b32bSmrg	    dispatchException |= DE_RESET;
1042bbe1b32bSmrg#endif
1043bbe1b32bSmrg
1044bbe1b32bSmrg	if (currentClient == client)
1045bbe1b32bSmrg	    currentClient = serverClient;
1046bbe1b32bSmrg	fsfree(client);
1047bbe1b32bSmrg
1048bbe1b32bSmrg#ifdef DEBUG
1049bbe1b32bSmrg	fprintf(stderr, "Shut down client\n");
1050bbe1b32bSmrg#endif
1051bbe1b32bSmrg
1052bbe1b32bSmrg	while (!clients[currentMaxClients - 1])
1053bbe1b32bSmrg	    currentMaxClients--;
1054bbe1b32bSmrg    }
1055bbe1b32bSmrg}
1056bbe1b32bSmrg
1057bbe1b32bSmrgstatic void
1058bbe1b32bSmrgkill_all_clients(void)
1059bbe1b32bSmrg{
1060bbe1b32bSmrg    int         i;
1061bbe1b32bSmrg
1062bbe1b32bSmrg    for (i = MINCLIENT; i < currentMaxClients; i++) {
1063bbe1b32bSmrg	if (clients[i])
1064bbe1b32bSmrg	    CloseDownClient(clients[i]);
1065bbe1b32bSmrg    }
1066bbe1b32bSmrg}
1067bbe1b32bSmrg
1068bbe1b32bSmrgvoid
1069bbe1b32bSmrgInitProcVectors(void)
1070bbe1b32bSmrg{
1071bbe1b32bSmrg    int         i;
1072bbe1b32bSmrg
1073bbe1b32bSmrg    for (i = 0; i < NUM_PROC_VECTORS; i++) {
1074bbe1b32bSmrg	if (!ProcVector[i]) {
1075bbe1b32bSmrg	    ProcVector[i] = SwappedProcVector[i] = ProcBadRequest;
1076bbe1b32bSmrg	    ReplySwapVector[i] = (ReplySwapFunc)NotImplemented;
1077bbe1b32bSmrg	}
1078bbe1b32bSmrg    }
1079bbe1b32bSmrg    for (i = FSLASTEvent; i < NUM_EVENT_VECTORS; i++) {
1080bbe1b32bSmrg	EventSwapVector[i] = (EventSwapFunc)NotImplemented;
1081bbe1b32bSmrg    }
1082bbe1b32bSmrg}
1083bbe1b32bSmrg
1084bbe1b32bSmrgvoid
1085bbe1b32bSmrgInitClient(
1086bbe1b32bSmrg    ClientPtr   client,
1087bbe1b32bSmrg    int         i,
1088bbe1b32bSmrg    pointer     ospriv)
1089bbe1b32bSmrg{
1090bbe1b32bSmrg    client->index = i;
1091bbe1b32bSmrg    client->sequence = 0;
1092bbe1b32bSmrg    client->last_request_time = GetTimeInMillis();
1093bbe1b32bSmrg    client->clientGone = CLIENT_ALIVE;
1094bbe1b32bSmrg    client->noClientException = FSSuccess;
1095bbe1b32bSmrg    client->requestVector = InitialVector;
1096bbe1b32bSmrg    client->osPrivate = ospriv;
1097bbe1b32bSmrg    client->swapped = FALSE;
1098bbe1b32bSmrg
1099bbe1b32bSmrg    client->auth = (AuthContextPtr) 0;
1100bbe1b32bSmrg    client->catalogues = NULL;
1101bbe1b32bSmrg    client->num_catalogues = 0;
1102bbe1b32bSmrg    client->num_resolutions = 0;
1103bbe1b32bSmrg    client->resolutions = (fsResolution *) 0;
1104bbe1b32bSmrg    client->eventmask = (Mask) 0;
1105bbe1b32bSmrg}
1106bbe1b32bSmrg
1107bbe1b32bSmrgClientPtr
1108bbe1b32bSmrgNextAvailableClient(pointer ospriv)
1109bbe1b32bSmrg{
1110bbe1b32bSmrg    int         i;
1111bbe1b32bSmrg    ClientPtr   client;
1112bbe1b32bSmrg    fsFakeReq   data;
1113bbe1b32bSmrg
1114bbe1b32bSmrg    i = nextFreeClientID;
1115bbe1b32bSmrg    if (i == MaxClients)
1116bbe1b32bSmrg	return NullClient;
1117bbe1b32bSmrg
1118bbe1b32bSmrg    clients[i] = client = (ClientPtr) fsalloc(sizeof(ClientRec));
1119bbe1b32bSmrg    if (!client)
1120bbe1b32bSmrg	return NullClient;
1121bbe1b32bSmrg
1122bbe1b32bSmrg    InitClient(client, i, ospriv);
1123bbe1b32bSmrg
1124bbe1b32bSmrg    if (!InitClientResources(client)) {
1125bbe1b32bSmrg	fsfree(client);
1126bbe1b32bSmrg	return NullClient;
1127bbe1b32bSmrg    }
1128bbe1b32bSmrg    data.reqType = 1;
1129bbe1b32bSmrg    data.length = (sizeof(fsFakeReq) + SIZEOF(fsConnClientPrefix)) >> 2;
1130bbe1b32bSmrg    if (!InsertFakeRequest(client, (char *) &data, sizeof(fsFakeReq))) {
1131bbe1b32bSmrg	FreeClientResources(client);
1132bbe1b32bSmrg	fsfree(client);
1133bbe1b32bSmrg	return NullClient;
1134bbe1b32bSmrg    }
1135bbe1b32bSmrg    if (i == currentMaxClients)
1136bbe1b32bSmrg	currentMaxClients++;
1137bbe1b32bSmrg    while ((nextFreeClientID < MAXCLIENTS) && clients[nextFreeClientID])
1138bbe1b32bSmrg	nextFreeClientID++;
1139bbe1b32bSmrg
1140bbe1b32bSmrg    /* if we've maxed out, try to clone */
1141bbe1b32bSmrg    if (nextFreeClientID == MaxClients) {
1142bbe1b32bSmrg	CloneMyself();
1143bbe1b32bSmrg    }
1144bbe1b32bSmrg    return client;
1145bbe1b32bSmrg}
1146bbe1b32bSmrg
1147bbe1b32bSmrgvoid
1148bbe1b32bSmrgMarkClientException(ClientPtr client)
1149bbe1b32bSmrg{
1150bbe1b32bSmrg    client->noClientException = -2;
1151bbe1b32bSmrg}
1152