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