dispatch.c revision 8f34cbf9
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);
256bbe1b32bSmrg	    return (FSBadLength);
257bbe1b32bSmrg	}
258bbe1b32bSmrg	/* copy carefully in case wire data is not aligned */
259bbe1b32bSmrg	client_auth[i].namelen = (((unsigned char *)ad)[0] << 8) +
260bbe1b32bSmrg				 ((unsigned char *)ad)[1];
261bbe1b32bSmrg	ad += 2;
262bbe1b32bSmrg	client_auth[i].datalen = (((unsigned char *)ad)[0] << 8) +
263bbe1b32bSmrg				 ((unsigned char *)ad)[1];
264bbe1b32bSmrg	ad += 2;
265bbe1b32bSmrg	client_auth[i].name = (char *) ad;
266bbe1b32bSmrg	ad += client_auth[i].namelen;
267bbe1b32bSmrg	client_auth[i].data = (char *) ad;
268bbe1b32bSmrg	ad += client_auth[i].datalen;
269bbe1b32bSmrg    }
270bbe1b32bSmrg    if (!(int)prefix->num_auths)
271bbe1b32bSmrg	ad += 4;
272bbe1b32bSmrg    if (ad - (char *)auth_data > (stuff->length << 2)) {
273bbe1b32bSmrg	int lengthword = stuff->length;
274bbe1b32bSmrg
275bbe1b32bSmrg	SendErrToClient(client, FSBadLength, (pointer)&lengthword);
276bbe1b32bSmrg	return (FSBadLength);
277bbe1b32bSmrg    }
278bbe1b32bSmrg
279bbe1b32bSmrg    num_alts = ListAlternateServers(&altservers);
280bbe1b32bSmrg    for (i = 0, altlen = 0; i < num_alts; i++) {
281bbe1b32bSmrg	/* subset + len + namelen + pad */
282bbe1b32bSmrg	altlen += (2 + altservers[i].namelen + 3) >> 2;
283bbe1b32bSmrg    }
284bbe1b32bSmrg
285bbe1b32bSmrg    auth_index = prefix->num_auths;
286bbe1b32bSmrg    client->auth_generation = 0;
287bbe1b32bSmrg    ret = CheckClientAuthorization(client, client_auth,
288bbe1b32bSmrg		    &auth_accept, &auth_index, &auth_len, &server_auth_data);
289bbe1b32bSmrg    if (auth_index > 0)
290bbe1b32bSmrg    {
291bbe1b32bSmrg	AuthContextPtr authp;
292bbe1b32bSmrg	authp = (AuthContextPtr) fsalloc(sizeof(AuthContextRec));
293bbe1b32bSmrg	if (!authp) {
294bbe1b32bSmrg	    SendErrToClient(client, FSBadAlloc, (pointer) 0);
295bbe1b32bSmrg	    return FSBadAlloc;
296bbe1b32bSmrg	}
297bbe1b32bSmrg	authp->authname =
298bbe1b32bSmrg	    (char *) fsalloc(client_auth[auth_index - 1].namelen + 1);
299bbe1b32bSmrg	authp->authdata =
300bbe1b32bSmrg	    (char *) fsalloc(client_auth[auth_index - 1].datalen + 1);
301bbe1b32bSmrg	if (!authp->authname || !authp->authdata) {
302bbe1b32bSmrg	    fsfree((char *) authp->authname);
303bbe1b32bSmrg	    fsfree((char *) authp->authdata);
304bbe1b32bSmrg	    fsfree((char *) authp);
305bbe1b32bSmrg	    SendErrToClient(client, FSBadAlloc, (pointer) 0);
306bbe1b32bSmrg	    return FSBadAlloc;
307bbe1b32bSmrg	}
308bbe1b32bSmrg	memmove( authp->authname, client_auth[auth_index - 1].name,
309bbe1b32bSmrg	      client_auth[auth_index - 1].namelen);
310bbe1b32bSmrg	memmove( authp->authdata, client_auth[auth_index - 1].data,
311bbe1b32bSmrg	      client_auth[auth_index - 1].datalen);
312bbe1b32bSmrg	/* Save it with a zero resource id...  subsequent
313bbe1b32bSmrg	   SetAuthorizations of None will find it.  And it will be freed
314bbe1b32bSmrg	   by FreeClientResources when the connection closes.  */
315bbe1b32bSmrg	if (!AddResource(client->index, 0, RT_AUTHCONT,(pointer) authp))
316bbe1b32bSmrg	{
317bbe1b32bSmrg	    fsfree((char *) authp->authname);
318bbe1b32bSmrg	    fsfree((char *) authp->authdata);
319bbe1b32bSmrg	    fsfree((char *) authp);
320bbe1b32bSmrg	    SendErrToClient(client, FSBadAlloc, (pointer) 0);
321bbe1b32bSmrg	    return FSBadAlloc;
322bbe1b32bSmrg	}
323bbe1b32bSmrg	client->auth = client->default_auth = authp;
324bbe1b32bSmrg    }
325bbe1b32bSmrg    else
326bbe1b32bSmrg	client->auth = client->default_auth = (AuthContextPtr)0;
327bbe1b32bSmrg
328bbe1b32bSmrg    DEALLOCATE_LOCAL(client_auth);
329bbe1b32bSmrg
330bbe1b32bSmrg    if (ret != FSSuccess) {
331bbe1b32bSmrg	SendErrToClient(client, FSBadAlloc, (pointer) 0);
332bbe1b32bSmrg	return FSBadAlloc;
333bbe1b32bSmrg    }
33434f90d55Smrg    else {
33534f90d55Smrg	fsConnSetup csp = {
33634f90d55Smrg	    .status = auth_accept,
33734f90d55Smrg	    /* we implement backwards compatibility for version 1.0 */
33834f90d55Smrg	    .major_version = (client->major_version == 1) ?
33934f90d55Smrg	        client->major_version : FS_PROTOCOL,
34034f90d55Smrg	    .minor_version = FS_PROTOCOL_MINOR,
34134f90d55Smrg	    .num_alternates = num_alts,
34234f90d55Smrg	    .alternate_len = altlen,
34334f90d55Smrg	    .auth_len = auth_len >> 2,
34434f90d55Smrg	    .auth_index = auth_index
34534f90d55Smrg	};
34634f90d55Smrg	if (client->swapped) {
34734f90d55Smrg	    WriteSConnSetup(client, &csp);
34834f90d55Smrg	} else {
34934f90d55Smrg	    (void) WriteToClient(client, SIZEOF(fsConnSetup), (char *) &csp);
35034f90d55Smrg	}
351bbe1b32bSmrg    }
352bbe1b32bSmrg
353bbe1b32bSmrg    /* send the alternates info */
354bbe1b32bSmrg    for (i = 0; i < num_alts; i++) {
355bbe1b32bSmrg	char        tmp[258];
356bbe1b32bSmrg
357bbe1b32bSmrg	/* WriteToClient pads, so we have to fake some things */
358bbe1b32bSmrg	tmp[0] = altservers[i].subset;
359bbe1b32bSmrg	tmp[1] = altservers[i].namelen;
360bbe1b32bSmrg	memmove( (char *) &tmp[2], altservers[i].name, altservers[i].namelen);
361bbe1b32bSmrg	(void) WriteToClient(client, altservers[i].namelen + 2, tmp);
362bbe1b32bSmrg    }
363bbe1b32bSmrg
364bbe1b32bSmrg    if (auth_len)
365bbe1b32bSmrg	(void) WriteToClient(client, auth_len, (char *) server_auth_data);
366bbe1b32bSmrg
367bbe1b32bSmrg    if (auth_accept != AuthSuccess) {
368bbe1b32bSmrg	nClients--;
369bbe1b32bSmrg	return (client->noClientException = -2);
370bbe1b32bSmrg    }
371bbe1b32bSmrg    client->requestVector = client->swapped ? SwappedProcVector : ProcVector;
372bbe1b32bSmrg    client->sequence = 0;
373bbe1b32bSmrg    if (client->swapped)
374bbe1b32bSmrg	(void) WriteSConnectionInfo(client, ConnInfoLen, ConnectionInfo);
375bbe1b32bSmrg    else
376bbe1b32bSmrg	(void) WriteToClient(client, ConnInfoLen, ConnectionInfo);
377bbe1b32bSmrg
378bbe1b32bSmrg#ifdef DEBUG
379bbe1b32bSmrg    fprintf(stderr, "Establishing new connection\n");
380bbe1b32bSmrg#endif
381bbe1b32bSmrg
382bbe1b32bSmrg    return client->noClientException;
383bbe1b32bSmrg}
384bbe1b32bSmrg
385bbe1b32bSmrg/*
386bbe1b32bSmrg * NOTE -- the incoming data may be mangled
387bbe1b32bSmrg */
388bbe1b32bSmrg
389bbe1b32bSmrgvoid
390bbe1b32bSmrgDoSendErrToClient(
391bbe1b32bSmrg    ClientPtr   client,
392bbe1b32bSmrg    int         error,
393bbe1b32bSmrg    pointer     data)		/* resource id, format, resolution, etc */
394bbe1b32bSmrg{
39534f90d55Smrg    fsError     rep = {
39634f90d55Smrg	.type = FS_Error,
39734f90d55Smrg	.request = error,
39834f90d55Smrg	.sequenceNumber = client->sequence,
39934f90d55Smrg	.timestamp = GetTimeInMillis(),
40034f90d55Smrg	.major_opcode = ((fsReq *) client->requestBuffer)->reqType,
4018f34cbf9Ssnj	.minor_opcode = 0
40234f90d55Smrg    };
403bbe1b32bSmrg    int         extralen = 0;
404bbe1b32bSmrg
405bbe1b32bSmrg    switch (error) {
406bbe1b32bSmrg    case FSBadFormat:
407bbe1b32bSmrg	extralen = SIZEOF(fsBitmapFormat);
408bbe1b32bSmrg	break;
409bbe1b32bSmrg    case FSBadFont:
410bbe1b32bSmrg    case FSBadAccessContext:
411bbe1b32bSmrg    case FSBadIDChoice:
412bbe1b32bSmrg    case FSBadEventMask:
413bbe1b32bSmrg	if (data) {
414bbe1b32bSmrg	    if (client->swapped)
415bbe1b32bSmrg	        SwapLongs((long *) data, 1);
416bbe1b32bSmrg	    extralen = 4;
417bbe1b32bSmrg	}
418bbe1b32bSmrg	break;
419bbe1b32bSmrg    case FSBadRange:
420bbe1b32bSmrg	extralen = SIZEOF(fsRange);
421bbe1b32bSmrg	break;
422bbe1b32bSmrg    case FSBadResolution:
423bbe1b32bSmrg	if (data) {
424bbe1b32bSmrg	    if (client->swapped)
425bbe1b32bSmrg	        SwapShorts((short *) data, 1);
426bbe1b32bSmrg	    /* note sneaky hack */
427bbe1b32bSmrg	    rep.pad = *(CARD16 *) data;
428bbe1b32bSmrg	    data = (char *)data + 2;
429bbe1b32bSmrg	    extralen = 4;
430bbe1b32bSmrg	}
431bbe1b32bSmrg	break;
432bbe1b32bSmrg    case FSBadLength:
433bbe1b32bSmrg	if (data) {
434bbe1b32bSmrg	    if (client->swapped)
435bbe1b32bSmrg	        SwapLongs((long *) data, 1);
436bbe1b32bSmrg	    extralen = 4;
437bbe1b32bSmrg	}
438bbe1b32bSmrg	break;
439bbe1b32bSmrg    default:
440bbe1b32bSmrg	/* nothing else to send */
441bbe1b32bSmrg	break;
442bbe1b32bSmrg    }
443bbe1b32bSmrg
444bbe1b32bSmrg    rep.length = (SIZEOF(fsError) + extralen) >> 2;
445bbe1b32bSmrg
446bbe1b32bSmrg    WriteErrorToClient(client, &rep);
447bbe1b32bSmrg
448bbe1b32bSmrg    if (extralen)
449bbe1b32bSmrg	WriteToClient(client, extralen, (char *) data);
450bbe1b32bSmrg}
451bbe1b32bSmrg
452bbe1b32bSmrg/* ARGSUSED */
453bbe1b32bSmrgint
454bbe1b32bSmrgProcBadRequest(ClientPtr client)
455bbe1b32bSmrg{
456bbe1b32bSmrg    SendErrToClient(client, FSBadRequest, NULL);
457bbe1b32bSmrg    return FSBadRequest;
458bbe1b32bSmrg}
459bbe1b32bSmrg
460bbe1b32bSmrgint
461bbe1b32bSmrgProcNoop(ClientPtr client)
462bbe1b32bSmrg{
463bbe1b32bSmrg    REQUEST(fsReq);
464bbe1b32bSmrg    REQUEST_AT_LEAST_SIZE(fsReq);
465bbe1b32bSmrg
466bbe1b32bSmrg    return client->noClientException;
467bbe1b32bSmrg}
468bbe1b32bSmrg
469bbe1b32bSmrgint
470bbe1b32bSmrgProcListCatalogues(ClientPtr client)
471bbe1b32bSmrg{
472bbe1b32bSmrg    int         len,
473bbe1b32bSmrg                num;
474bbe1b32bSmrg    char       *catalogues;
47534f90d55Smrg    fsListCataloguesReply rep = {
47634f90d55Smrg	.type = FS_Reply,
47734f90d55Smrg	.sequenceNumber = client->sequence,
47834f90d55Smrg	.num_replies = 0
47934f90d55Smrg    };
480bbe1b32bSmrg
481bbe1b32bSmrg    REQUEST(fsListCataloguesReq);
482bbe1b32bSmrg    REQUEST_AT_LEAST_SIZE(fsListCataloguesReq);
483bbe1b32bSmrg
484bbe1b32bSmrg    num = ListCatalogues((char *)stuff + SIZEOF(fsListCataloguesReq),
485bbe1b32bSmrg			 stuff->nbytes, stuff->maxNames,
486bbe1b32bSmrg			 &catalogues, &len);
487bbe1b32bSmrg    rep.num_catalogues = num;
488bbe1b32bSmrg    rep.length = (SIZEOF(fsListCataloguesReply) + len + 3) >> 2;
489bbe1b32bSmrg
490bbe1b32bSmrg    WriteReplyToClient(client, SIZEOF(fsListCataloguesReply), &rep);
491bbe1b32bSmrg    (void) WriteToClient(client, len, (char *) catalogues);
492bbe1b32bSmrg    fsfree((char *) catalogues);
493bbe1b32bSmrg    return client->noClientException;
494bbe1b32bSmrg}
495bbe1b32bSmrg
496bbe1b32bSmrgint
497bbe1b32bSmrgProcSetCatalogues(ClientPtr client)
498bbe1b32bSmrg{
499bbe1b32bSmrg    char       *new_cat;
500bbe1b32bSmrg    int         err,
501bbe1b32bSmrg                len;
502bbe1b32bSmrg    int         num;
503bbe1b32bSmrg
504bbe1b32bSmrg    REQUEST(fsSetCataloguesReq);
505bbe1b32bSmrg    REQUEST_AT_LEAST_SIZE(fsSetCataloguesReq);
506bbe1b32bSmrg
507bbe1b32bSmrg    if (stuff->num_catalogues == 0) {
508bbe1b32bSmrg	/* use the default */
509bbe1b32bSmrg	num = ListCatalogues("*", 1, 10000, &new_cat, &len);
510bbe1b32bSmrg    } else {
511bbe1b32bSmrg	num = stuff->num_catalogues;
512bbe1b32bSmrg	err = ValidateCatalogues(&num, (char *)stuff + SIZEOF(fsSetCataloguesReq));
513bbe1b32bSmrg	if (err == FSSuccess) {
514bbe1b32bSmrg	    len = (stuff->length << 2) - SIZEOF(fsSetCataloguesReq);
515bbe1b32bSmrg	    new_cat = (char *) fsalloc(len);
516bbe1b32bSmrg	    if (!new_cat)
517bbe1b32bSmrg		return FSBadAlloc;
518bbe1b32bSmrg	    memmove( new_cat, (char *)stuff + SIZEOF(fsSetCataloguesReq), len);
519bbe1b32bSmrg	} else {
520bbe1b32bSmrg	    SendErrToClient(client, err, (pointer) &num);
521bbe1b32bSmrg	    return err;
522bbe1b32bSmrg	}
523bbe1b32bSmrg    }
524bbe1b32bSmrg    if (client->catalogues)
525bbe1b32bSmrg	fsfree((char *) client->catalogues);
526bbe1b32bSmrg    client->catalogues = new_cat;
527bbe1b32bSmrg    client->num_catalogues = num;
528bbe1b32bSmrg    return client->noClientException;
529bbe1b32bSmrg}
530bbe1b32bSmrg
531bbe1b32bSmrgint
532bbe1b32bSmrgProcGetCatalogues(ClientPtr client)
533bbe1b32bSmrg{
534bbe1b32bSmrg    int         len,
535bbe1b32bSmrg                i,
536bbe1b32bSmrg                size;
537bbe1b32bSmrg    char       *cp;
538bbe1b32bSmrg
539bbe1b32bSmrg    REQUEST(fsGetCataloguesReq);
540bbe1b32bSmrg    REQUEST_AT_LEAST_SIZE(fsGetCataloguesReq);
541bbe1b32bSmrg
542bbe1b32bSmrg    for (i = 0, len = 0, cp = client->catalogues;
543bbe1b32bSmrg	    i < client->num_catalogues; i++) {
544bbe1b32bSmrg	size = *cp++;
545bbe1b32bSmrg	len += size + 1;	/* str length + size byte */
546bbe1b32bSmrg	cp += size;
547bbe1b32bSmrg    }
548bbe1b32bSmrg
54934f90d55Smrg    {
55034f90d55Smrg        fsGetCataloguesReply rep = {
55134f90d55Smrg	    .type = FS_Reply,
55234f90d55Smrg	    .num_catalogues = client->num_catalogues,
55334f90d55Smrg	    .sequenceNumber = client->sequence,
55434f90d55Smrg	    .length = (SIZEOF(fsGetCataloguesReply) + len + 3) >> 2
55534f90d55Smrg	};
556bbe1b32bSmrg
55734f90d55Smrg	WriteReplyToClient(client, SIZEOF(fsGetCataloguesReply), &rep);
55834f90d55Smrg    }
559bbe1b32bSmrg    (void) WriteToClient(client, len, client->catalogues);
560bbe1b32bSmrg
561bbe1b32bSmrg    return client->noClientException;
562bbe1b32bSmrg}
563bbe1b32bSmrg
564bbe1b32bSmrgint
565bbe1b32bSmrgProcCreateAC(ClientPtr client)
566bbe1b32bSmrg{
567bbe1b32bSmrg    AuthPtr     acp;
568bbe1b32bSmrg    AuthContextPtr authp;
569bbe1b32bSmrg    int         accept,
570bbe1b32bSmrg                i,
571bbe1b32bSmrg                err,
572bbe1b32bSmrg                index,
573bbe1b32bSmrg                size;
574bbe1b32bSmrg    char       *ad;
575bbe1b32bSmrg    char       *auth_data;
576bbe1b32bSmrg
577bbe1b32bSmrg    REQUEST(fsCreateACReq);
578bbe1b32bSmrg    REQUEST_AT_LEAST_SIZE(fsCreateACReq);
579bbe1b32bSmrg
580bbe1b32bSmrg    authp = (AuthContextPtr) LookupIDByType(client->index, stuff->acid,
581bbe1b32bSmrg					    RT_AUTHCONT);
582bbe1b32bSmrg    if (authp) {
583bbe1b32bSmrg	int aligned_acid = stuff->acid;
584bbe1b32bSmrg	SendErrToClient(client, FSBadIDChoice, (pointer) &aligned_acid);
585bbe1b32bSmrg	return FSBadIDChoice;
586bbe1b32bSmrg    }
587ce6676dbSmrg    acp = NULL;
588bbe1b32bSmrg    if (stuff->num_auths)
589bbe1b32bSmrg    {
590bbe1b32bSmrg    	acp = (AuthPtr) ALLOCATE_LOCAL(stuff->num_auths * sizeof(AuthRec));
591bbe1b32bSmrg    	if (!acp) {
592ce6676dbSmrg	    SendErrToClient(client, FSBadAlloc, (pointer) NULL);
593bbe1b32bSmrg	    return FSBadAlloc;
594bbe1b32bSmrg    	}
595bbe1b32bSmrg    }
596bbe1b32bSmrg    /* build up a list of the stuff */
597bbe1b32bSmrg    for (i = 0, ad = (char *)stuff + SIZEOF(fsCreateACReq);
598bbe1b32bSmrg         i < (int)stuff->num_auths; i++) {
599bbe1b32bSmrg	if (ad - (char *)stuff + SIZEOF(fsCreateACReq) >
600bbe1b32bSmrg	    (stuff->length << 2) - 4) {
601bbe1b32bSmrg	    int lengthword = stuff->length;
602bbe1b32bSmrg
603bbe1b32bSmrg	    SendErrToClient(client, FSBadLength, (pointer)&lengthword);
604bbe1b32bSmrg	    return (FSBadLength);
605bbe1b32bSmrg	}
606bbe1b32bSmrg	/* copy carefully in case data is not aligned */
607bbe1b32bSmrg	acp[i].namelen = (((unsigned char *)ad)[0] << 8) +
608bbe1b32bSmrg			 ((unsigned char *)ad)[1];
609bbe1b32bSmrg	ad += 2;
610bbe1b32bSmrg	acp[i].datalen = (((unsigned char *)ad)[0] << 8) +
611bbe1b32bSmrg			 ((unsigned char *)ad)[1];
612bbe1b32bSmrg	ad += 2;
613bbe1b32bSmrg	acp[i].name = (char *) ad;
614bbe1b32bSmrg	ad += acp[i].namelen;
615bbe1b32bSmrg	acp[i].data = (char *) ad;
616bbe1b32bSmrg	ad += acp[i].datalen;
617bbe1b32bSmrg    }
618bbe1b32bSmrg    if (ad - (char *)stuff > (stuff->length << 2)) {
619bbe1b32bSmrg	int lengthword = stuff->length;
620bbe1b32bSmrg
621bbe1b32bSmrg	SendErrToClient(client, FSBadLength, (pointer)&lengthword);
622bbe1b32bSmrg	return (FSBadLength);
623bbe1b32bSmrg    }
624bbe1b32bSmrg
625bbe1b32bSmrg/* XXX needs work for AuthContinue */
626bbe1b32bSmrg    index = stuff->num_auths;
627bbe1b32bSmrg    err = CheckClientAuthorization(client, acp, &accept, &index, &size,
628bbe1b32bSmrg				   &auth_data);
629bbe1b32bSmrg
630bbe1b32bSmrg    if (err != FSSuccess) {
631bbe1b32bSmrg	SendErrToClient(client, err, (pointer) 0);
632bbe1b32bSmrg	if (acp)
633bbe1b32bSmrg	    DEALLOCATE_LOCAL(acp);
634bbe1b32bSmrg	return err;
635bbe1b32bSmrg    }
636bbe1b32bSmrg    authp = (AuthContextPtr) fsalloc(sizeof(AuthContextRec));
637bbe1b32bSmrg    if (!authp) {
638bbe1b32bSmrg	goto alloc_failure;
639bbe1b32bSmrg    }
640ce6676dbSmrg    authp->authname = NULL;
641ce6676dbSmrg    authp->authdata = NULL;
642bbe1b32bSmrg    if (index > 0)
643bbe1b32bSmrg    {
644bbe1b32bSmrg	authp->authname = (char *) fsalloc(acp[index - 1].namelen + 1);
645bbe1b32bSmrg	authp->authdata = (char *) fsalloc(acp[index - 1].datalen + 1);
646bbe1b32bSmrg	if (!authp->authname || !authp->authdata) {
647bbe1b32bSmrg	    fsfree((char *) authp->authname);
648bbe1b32bSmrg	    fsfree((char *) authp->authdata);
649bbe1b32bSmrg	    fsfree((char *) authp);
650bbe1b32bSmrg	    goto alloc_failure;
651bbe1b32bSmrg	}
652bbe1b32bSmrg	memmove( authp->authname, acp[index - 1].name, acp[index - 1].namelen);
653bbe1b32bSmrg	memmove( authp->authdata, acp[index - 1].data, acp[index - 1].datalen);
654bbe1b32bSmrg    }
655bbe1b32bSmrg    else
656bbe1b32bSmrg	size = 0;
657bbe1b32bSmrg    authp->acid = stuff->acid;
658bbe1b32bSmrg    if (!AddResource(client->index, stuff->acid, RT_AUTHCONT,(pointer) authp))
659bbe1b32bSmrg    {
660bbe1b32bSmrgalloc_failure:
661bbe1b32bSmrg	SendErrToClient(client, FSBadAlloc, (pointer) 0);
662bbe1b32bSmrg	if (acp)
663bbe1b32bSmrg	    DEALLOCATE_LOCAL(acp);
664bbe1b32bSmrg	return FSBadAlloc;
665bbe1b32bSmrg    }
666bbe1b32bSmrg    DEALLOCATE_LOCAL(acp);
66734f90d55Smrg    {
66834f90d55Smrg        fsCreateACReply rep = {
66934f90d55Smrg	    .type = FS_Reply,
67034f90d55Smrg	    .auth_index = index,
67134f90d55Smrg	    .sequenceNumber = client->sequence,
67234f90d55Smrg	    .status = accept,
67334f90d55Smrg	    .length = (SIZEOF(fsCreateACReply) + size) >> 2
67434f90d55Smrg	};
675bbe1b32bSmrg
67634f90d55Smrg	WriteReplyToClient(client, SIZEOF(fsCreateACReply), &rep);
67734f90d55Smrg    }
678bbe1b32bSmrg    if (size)
679bbe1b32bSmrg	(void) WriteToClient(client, size, auth_data);
680bbe1b32bSmrg
681bbe1b32bSmrg    return client->noClientException;
682bbe1b32bSmrg}
683bbe1b32bSmrg
684bbe1b32bSmrg/* ARGSUSED */
685bbe1b32bSmrgint
686bbe1b32bSmrgDeleteAuthCont (pointer value, FSID id)
687bbe1b32bSmrg{
688bbe1b32bSmrg    AuthContextPtr  authp = (AuthContextPtr) value;
689bbe1b32bSmrg
690bbe1b32bSmrg    if (authp->authname)
691bbe1b32bSmrg	fsfree (authp->authname);
692bbe1b32bSmrg    if (authp->authdata)
693bbe1b32bSmrg	fsfree (authp->authdata);
694bbe1b32bSmrg    fsfree (authp);
695bbe1b32bSmrg    return 1;
696bbe1b32bSmrg}
697bbe1b32bSmrg
698bbe1b32bSmrgint
699bbe1b32bSmrgProcFreeAC(ClientPtr client)
700bbe1b32bSmrg{
701bbe1b32bSmrg    AuthContextPtr authp;
702bbe1b32bSmrg
703bbe1b32bSmrg    REQUEST(fsFreeACReq);
704bbe1b32bSmrg    REQUEST_AT_LEAST_SIZE(fsFreeACReq);
705bbe1b32bSmrg    authp = (AuthContextPtr) LookupIDByType(client->index, stuff->id,
706bbe1b32bSmrg					  RT_AUTHCONT);
707bbe1b32bSmrg    if (!authp) {
708bbe1b32bSmrg	int aligned_id = stuff->id;
709bbe1b32bSmrg	SendErrToClient(client, FSBadIDChoice, (pointer) &aligned_id);
710bbe1b32bSmrg	return FSBadIDChoice;
711bbe1b32bSmrg    }
712bbe1b32bSmrg    if (client->auth == authp)
713bbe1b32bSmrg	client->auth = client->default_auth;
714bbe1b32bSmrg    FreeResource(client->index, stuff->id, RT_NONE);
715bbe1b32bSmrg    return client->noClientException;
716bbe1b32bSmrg}
717bbe1b32bSmrg
718bbe1b32bSmrgint
719bbe1b32bSmrgProcSetAuthorization(ClientPtr client)
720bbe1b32bSmrg{
721bbe1b32bSmrg    AuthContextPtr acp;
722bbe1b32bSmrg
723bbe1b32bSmrg    REQUEST(fsSetAuthorizationReq);
724bbe1b32bSmrg    REQUEST_AT_LEAST_SIZE(fsSetAuthorizationReq);
725bbe1b32bSmrg    acp = (AuthContextPtr) LookupIDByType(client->index, stuff->id,
726bbe1b32bSmrg					  RT_AUTHCONT);
727bbe1b32bSmrg    if (!acp) {
728bbe1b32bSmrg	int aligned_id = stuff->id;
729bbe1b32bSmrg	SendErrToClient(client, FSBadIDChoice, (pointer) &aligned_id);
730bbe1b32bSmrg	return FSBadIDChoice;
731bbe1b32bSmrg    }
732bbe1b32bSmrg    client->auth = acp;		/* XXX does this need a refcount? */
733bbe1b32bSmrg    return client->noClientException;
734bbe1b32bSmrg}
735bbe1b32bSmrg
736bbe1b32bSmrgint
737bbe1b32bSmrgProcSetResolution(ClientPtr client)
738bbe1b32bSmrg{
739bbe1b32bSmrg    fsResolution *new_res;
740bbe1b32bSmrg
741bbe1b32bSmrg    REQUEST(fsSetResolutionReq);
742bbe1b32bSmrg    REQUEST_AT_LEAST_SIZE(fsSetResolutionReq);
743bbe1b32bSmrg
744bbe1b32bSmrg    if ((stuff->length << 2) - SIZEOF(fsSetResolutionReq) <
745bbe1b32bSmrg        stuff->num_resolutions * SIZEOF(fsResolution)) {
746bbe1b32bSmrg	int lengthword = stuff->length;
747bbe1b32bSmrg
748bbe1b32bSmrg	SendErrToClient(client, FSBadLength, &lengthword);
749bbe1b32bSmrg	return FSBadLength;
750bbe1b32bSmrg    }
751bbe1b32bSmrg    new_res = (fsResolution *)
752bbe1b32bSmrg	fsalloc(SIZEOF(fsResolution) * stuff->num_resolutions);
753bbe1b32bSmrg    if (!new_res) {
754bbe1b32bSmrg	SendErrToClient(client, FSBadAlloc, NULL);
755bbe1b32bSmrg	return FSBadAlloc;
756bbe1b32bSmrg    }
757bbe1b32bSmrg    fsfree((char *) client->resolutions);
758bbe1b32bSmrg    memmove( (char *) new_res, (char *)stuff + SIZEOF(fsSetResolutionReq),
759bbe1b32bSmrg	  (stuff->num_resolutions * SIZEOF(fsResolution)));
760bbe1b32bSmrg    client->resolutions = new_res;
761bbe1b32bSmrg    client->num_resolutions = stuff->num_resolutions;
762bbe1b32bSmrg
763bbe1b32bSmrg    return client->noClientException;
764bbe1b32bSmrg}
765bbe1b32bSmrg
766bbe1b32bSmrgint
767bbe1b32bSmrgProcGetResolution(ClientPtr client)
768bbe1b32bSmrg{
769bbe1b32bSmrg    REQUEST(fsReq);
770bbe1b32bSmrg    REQUEST_AT_LEAST_SIZE(fsReq);
771bbe1b32bSmrg
772bbe1b32bSmrg    if ((stuff->length << 2) - SIZEOF(fsResolution) < client->num_resolutions *
773bbe1b32bSmrg	sizeof(fsResolution)) {
774bbe1b32bSmrg	int lengthword = stuff->length;
775bbe1b32bSmrg
776bbe1b32bSmrg	SendErrToClient(client, FSBadLength, &lengthword);
777bbe1b32bSmrg	return FSBadLength;
778bbe1b32bSmrg    }
77934f90d55Smrg    else {
78034f90d55Smrg	fsGetResolutionReply reply = {
78134f90d55Smrg	    .type = FS_Reply,
78234f90d55Smrg	    .num_resolutions = client->num_resolutions,
78334f90d55Smrg	    .sequenceNumber = client->sequence,
78434f90d55Smrg	    .length = (SIZEOF(fsGetResolutionReply) +
78534f90d55Smrg		       client->num_resolutions * SIZEOF(fsResolution)) >> 2
78634f90d55Smrg	};
787bbe1b32bSmrg
78834f90d55Smrg	WriteReplyToClient(client, SIZEOF(fsGetResolutionReply), &reply);
78934f90d55Smrg    }
790bbe1b32bSmrg    if (client->swapped)
791bbe1b32bSmrg	client->pSwapReplyFunc = CopySwap16Write;
792bbe1b32bSmrg
793bbe1b32bSmrg    WriteSwappedDataToClient(client,
794bbe1b32bSmrg       (client->num_resolutions * SIZEOF(fsResolution)), (short *)client->resolutions);
795bbe1b32bSmrg
796bbe1b32bSmrg    return client->noClientException;
797bbe1b32bSmrg}
798bbe1b32bSmrg
799bbe1b32bSmrgint
800bbe1b32bSmrgProcListFonts(ClientPtr client)
801bbe1b32bSmrg{
802bbe1b32bSmrg    REQUEST(fsListFontsReq);
803bbe1b32bSmrg    REQUEST_FIXED_SIZE(fsListFontsReq, stuff->nbytes);
804bbe1b32bSmrg
805bbe1b32bSmrg    return ListFonts(client, stuff->nbytes,
806bbe1b32bSmrg		     (unsigned char *)stuff + SIZEOF(fsListFontsReq),
807bbe1b32bSmrg		     stuff->maxNames);
808bbe1b32bSmrg}
809bbe1b32bSmrg
810bbe1b32bSmrgint
811bbe1b32bSmrgProcListFontsWithXInfo(ClientPtr client)
812bbe1b32bSmrg{
813bbe1b32bSmrg    REQUEST(fsListFontsWithXInfoReq);
814bbe1b32bSmrg    REQUEST_FIXED_SIZE(fsListFontsWithXInfoReq, stuff->nbytes);
815bbe1b32bSmrg
816bbe1b32bSmrg    return StartListFontsWithInfo(client, stuff->nbytes,
817bbe1b32bSmrg				  (unsigned char *)stuff + SIZEOF(fsListFontsWithXInfoReq), stuff->maxNames);
818bbe1b32bSmrg}
819bbe1b32bSmrg
820bbe1b32bSmrgint
821bbe1b32bSmrgProcOpenBitmapFont(ClientPtr client)
822bbe1b32bSmrg{
823bbe1b32bSmrg    FontPtr     pfont;
824bbe1b32bSmrg    int         nbytes,
825bbe1b32bSmrg                err;
826bbe1b32bSmrg    unsigned char *fname;
827bbe1b32bSmrg
828bbe1b32bSmrg    REQUEST(fsOpenBitmapFontReq);
829bbe1b32bSmrg    fname = (unsigned char *)stuff + SIZEOF(fsOpenBitmapFontReq);
830bbe1b32bSmrg    nbytes = *fname++;
831bbe1b32bSmrg
832bbe1b32bSmrg    REQUEST_FIXED_SIZE(fsOpenBitmapFontReq, (nbytes + 1));
833bbe1b32bSmrg
834bbe1b32bSmrg    pfont = (FontPtr) LookupIDByType(client->index, stuff->fid, RT_FONT);
835bbe1b32bSmrg    if (pfont) {
836bbe1b32bSmrg	int aligned_fid = stuff->fid;
837bbe1b32bSmrg	SendErrToClient(client, FSBadIDChoice, (pointer) &aligned_fid);
838bbe1b32bSmrg	return FSBadIDChoice;
839bbe1b32bSmrg    }
840bbe1b32bSmrg    if (stuff->format_hint != 0 &&
841bbe1b32bSmrg	    stuff->format_hint & ~ALL_FORMAT_BITS) {
842bbe1b32bSmrg	int aligned_format_hint = stuff->format_hint;
843bbe1b32bSmrg	SendErrToClient(client, FSBadFormat, (pointer) &aligned_format_hint);
844bbe1b32bSmrg	return FSBadFormat;
845bbe1b32bSmrg    }
846bbe1b32bSmrg    if (stuff->format_mask & ~ALL_FORMAT_MASK_BITS) {
847bbe1b32bSmrg	int aligned_format_mask = stuff->format_mask;
848bbe1b32bSmrg	SendErrToClient(client, FSBadFormat, (pointer) &aligned_format_mask);
849bbe1b32bSmrg	return FSBadFormat;
850bbe1b32bSmrg    }
851bbe1b32bSmrg    err = OpenFont(client, stuff->fid, stuff->format_hint, stuff->format_mask,
852bbe1b32bSmrg		   nbytes, (char *) fname);
853bbe1b32bSmrg
854bbe1b32bSmrg    if (err == FSSuccess) {
855bbe1b32bSmrg	return client->noClientException;
856bbe1b32bSmrg    } else {
857bbe1b32bSmrg	return err;
858bbe1b32bSmrg    }
859bbe1b32bSmrg}
860bbe1b32bSmrg
861bbe1b32bSmrgint
862bbe1b32bSmrgProcQueryXInfo(ClientPtr client)
863bbe1b32bSmrg{
864bbe1b32bSmrg    ClientFontPtr cfp;
865bbe1b32bSmrg    int         err,
866bbe1b32bSmrg                lendata;
86734f90d55Smrg    fsQueryXInfoReply reply = {
86834f90d55Smrg	.type = FS_Reply,
86934f90d55Smrg	.sequenceNumber = client->sequence
87034f90d55Smrg    };
871bbe1b32bSmrg    fsPropInfo *prop_info;
872bbe1b32bSmrg
873bbe1b32bSmrg    REQUEST(fsQueryXInfoReq);
874bbe1b32bSmrg
875bbe1b32bSmrg    REQUEST_AT_LEAST_SIZE(fsQueryXInfoReq);
876bbe1b32bSmrg
877bbe1b32bSmrg    cfp = (ClientFontPtr) LookupIDByType(client->index, stuff->id, RT_FONT);
878bbe1b32bSmrg    if (!cfp) {
879bbe1b32bSmrg	int aligned_id = stuff->id;
880bbe1b32bSmrg	SendErrToClient(client, FSBadFont, (pointer) &aligned_id);
881bbe1b32bSmrg	return FSBadFont;
882bbe1b32bSmrg    }
883bbe1b32bSmrg
884bbe1b32bSmrg    /* get the header */
885bbe1b32bSmrg    fsPack_XFontInfoHeader(&cfp->font->info, &reply, client->major_version);
886bbe1b32bSmrg    err = convert_props(&cfp->font->info, &prop_info);
887bbe1b32bSmrg
888bbe1b32bSmrg    switch (err)
889bbe1b32bSmrg    {
890bbe1b32bSmrg    case Successful:
891bbe1b32bSmrg	break;
892bbe1b32bSmrg    case AllocError:
893bbe1b32bSmrg	SendErrToClient(client, FSBadAlloc, (pointer) 0);
894bbe1b32bSmrg	return err;
895bbe1b32bSmrg    default:
896bbe1b32bSmrg	ErrorF("ProcQueryXInfo: unexpected return val %d from convert_props\n",
897bbe1b32bSmrg	       err);
898bbe1b32bSmrg	SendErrToClient(client, FSBadImplementation, (pointer) 0);
899bbe1b32bSmrg	return err;
900bbe1b32bSmrg    }
901bbe1b32bSmrg    lendata = SIZEOF(fsPropInfo) +
902bbe1b32bSmrg	prop_info->num_offsets * SIZEOF(fsPropOffset) +
903bbe1b32bSmrg	prop_info->data_len;
904bbe1b32bSmrg
905bbe1b32bSmrg    reply.length = (SIZEOF(fsQueryXInfoReply) + lendata + 3) >> 2;
906bbe1b32bSmrg    WriteReplyToClient(client, SIZEOF(fsQueryXInfoReply), &reply);
907bbe1b32bSmrg
908bbe1b32bSmrg    if (client->swapped)
909bbe1b32bSmrg	SwapPropInfo(prop_info);
910bbe1b32bSmrg    (void) WriteToClient(client, lendata, (char *) prop_info);
911bbe1b32bSmrg
912bbe1b32bSmrg    fsfree((char *) prop_info);
913bbe1b32bSmrg    return client->noClientException;
914bbe1b32bSmrg}
915bbe1b32bSmrg
916bbe1b32bSmrgint
917bbe1b32bSmrgProcQueryXExtents(ClientPtr client)
918bbe1b32bSmrg{
919bbe1b32bSmrg    ClientFontPtr cfp;
920bbe1b32bSmrg    int         err;
921bbe1b32bSmrg    int         item_size;
922bbe1b32bSmrg
923bbe1b32bSmrg    REQUEST(fsQueryXExtents8Req);
924bbe1b32bSmrg
925bbe1b32bSmrg    REQUEST_AT_LEAST_SIZE(fsQueryXExtents8Req);
926bbe1b32bSmrg
927bbe1b32bSmrg    cfp = (ClientFontPtr) LookupIDByType(client->index, stuff->fid, RT_FONT);
928bbe1b32bSmrg    if (!cfp) {
929bbe1b32bSmrg	int aligned_fid = stuff->fid;
930bbe1b32bSmrg	SendErrToClient(client, FSBadFont, (pointer) &aligned_fid);
931bbe1b32bSmrg	return FSBadFont;
932bbe1b32bSmrg    }
933bbe1b32bSmrg    item_size = (stuff->reqType == FS_QueryXExtents8) ? 1 : 2;
934bbe1b32bSmrg
935bbe1b32bSmrg    if (stuff->num_ranges >
936bbe1b32bSmrg	 ((stuff->length << 2) - SIZEOF(fsQueryXExtents8Req))/item_size) {
937bbe1b32bSmrg	int num_ranges = stuff->num_ranges;
938bbe1b32bSmrg	SendErrToClient(client, FSBadLength, (pointer)&num_ranges);
939bbe1b32bSmrg	return FSBadLength;
940bbe1b32bSmrg    }
941bbe1b32bSmrg
942bbe1b32bSmrg    /* get the extents */
943bbe1b32bSmrg    err = QueryExtents(client, cfp, item_size,
944bbe1b32bSmrg		       stuff->num_ranges, stuff->range,
945bbe1b32bSmrg		       (char *)stuff + SIZEOF(fsQueryXExtents8Req));
946bbe1b32bSmrg
947bbe1b32bSmrg    if (err != FSSuccess) {
948bbe1b32bSmrg	return err;
949bbe1b32bSmrg    } else
950bbe1b32bSmrg	return client->noClientException;
951bbe1b32bSmrg}
952bbe1b32bSmrg
953bbe1b32bSmrgint
954bbe1b32bSmrgProcQueryXBitmaps(ClientPtr client)
955bbe1b32bSmrg{
956bbe1b32bSmrg    ClientFontPtr cfp;
957bbe1b32bSmrg    int         err;
958bbe1b32bSmrg    int         item_size;
959bbe1b32bSmrg
960bbe1b32bSmrg    REQUEST(fsQueryXBitmaps8Req);
961bbe1b32bSmrg
962bbe1b32bSmrg    REQUEST_AT_LEAST_SIZE(fsQueryXBitmaps8Req);
963bbe1b32bSmrg
964bbe1b32bSmrg    cfp = (ClientFontPtr) LookupIDByType(client->index, stuff->fid, RT_FONT);
965bbe1b32bSmrg    if (!cfp) {
966bbe1b32bSmrg	int aligned_fid = stuff->fid;
967bbe1b32bSmrg	SendErrToClient(client, FSBadFont, (pointer) &aligned_fid);
968bbe1b32bSmrg	return FSBadFont;
969bbe1b32bSmrg    }
970bbe1b32bSmrg    if (stuff->format & ~ALL_FORMAT_BITS) {
971bbe1b32bSmrg	int aligned_format = stuff->format;
972bbe1b32bSmrg	SendErrToClient(client, FSBadFormat, (pointer) &aligned_format);
973bbe1b32bSmrg	return FSBadFormat;
974bbe1b32bSmrg    }
975bbe1b32bSmrg    assert((stuff->reqType == FS_QueryXBitmaps8) || (stuff->reqType == FS_QueryXBitmaps16));
976bbe1b32bSmrg    item_size = (stuff->reqType == FS_QueryXBitmaps8) ? 1 : 2;
977bbe1b32bSmrg
978bbe1b32bSmrg    if (stuff->num_ranges >
979bbe1b32bSmrg	((stuff->length << 2) - SIZEOF(fsQueryXBitmaps8Req))/item_size) {
980bbe1b32bSmrg	int num_ranges = stuff->num_ranges;
981bbe1b32bSmrg	SendErrToClient(client, FSBadLength, (pointer)&num_ranges);
982bbe1b32bSmrg	return FSBadLength;
983bbe1b32bSmrg    }
984bbe1b32bSmrg    /* get the glyphs */
985bbe1b32bSmrg    err = QueryBitmaps(client, cfp, item_size, stuff->format,
986bbe1b32bSmrg		       stuff->num_ranges, stuff->range,
987bbe1b32bSmrg		       (char *)stuff + SIZEOF(fsQueryXBitmaps8Req));
988bbe1b32bSmrg
989bbe1b32bSmrg    if (err != FSSuccess) {
990bbe1b32bSmrg	return err;
991bbe1b32bSmrg    } else {
992bbe1b32bSmrg	return client->noClientException;
993bbe1b32bSmrg    }
994bbe1b32bSmrg}
995bbe1b32bSmrg
996bbe1b32bSmrgint
997bbe1b32bSmrgProcCloseFont(ClientPtr client)
998bbe1b32bSmrg{
999bbe1b32bSmrg    ClientFontPtr cfp;
1000bbe1b32bSmrg
1001bbe1b32bSmrg    REQUEST(fsResourceReq);
1002bbe1b32bSmrg
1003bbe1b32bSmrg    REQUEST_SIZE_MATCH(fsResourceReq);
1004bbe1b32bSmrg    cfp = (ClientFontPtr) LookupIDByType(client->index, stuff->id, RT_FONT);
1005bbe1b32bSmrg    if (cfp) {
1006bbe1b32bSmrg	FreeResource(client->index, stuff->id, RT_NONE);
1007bbe1b32bSmrg	return client->noClientException;
1008bbe1b32bSmrg    } else {
1009bbe1b32bSmrg	int aligned_id = stuff->id;
1010bbe1b32bSmrg	SendErrToClient(client, FSBadFont, (pointer) &aligned_id);
1011bbe1b32bSmrg	return FSBadFont;
1012bbe1b32bSmrg    }
1013bbe1b32bSmrg}
1014bbe1b32bSmrg
1015bbe1b32bSmrgvoid
1016bbe1b32bSmrgDoCloseDownClient(ClientPtr client)
1017bbe1b32bSmrg{
1018bbe1b32bSmrg    if (client->clientGone != CLIENT_GONE) {
1019bbe1b32bSmrg	DeleteClientFontStuff(client);
1020bbe1b32bSmrg	client->clientGone = CLIENT_GONE;
1021bbe1b32bSmrg	CloseDownConnection(client);
1022bbe1b32bSmrg	--nClients;
1023bbe1b32bSmrg    }
1024bbe1b32bSmrg
1025bbe1b32bSmrg    if (ClientIsAsleep(client))
1026bbe1b32bSmrg	ClientSignal((pointer)client);
1027bbe1b32bSmrg    else
1028bbe1b32bSmrg    {
1029bbe1b32bSmrg	FreeClientResources(client);
1030bbe1b32bSmrg	if (client->index < nextFreeClientID)
1031bbe1b32bSmrg	    nextFreeClientID = client->index;
1032bbe1b32bSmrg	clients[client->index] = NullClient;
1033bbe1b32bSmrg#ifdef DebugConnectionTranslation
1034bbe1b32bSmrg	CheckFileNumbers();
1035bbe1b32bSmrg#endif /* DebugConnectionTranslation */
1036bbe1b32bSmrg
1037bbe1b32bSmrg
1038bbe1b32bSmrg	if (currentClient == client)
1039bbe1b32bSmrg	    currentClient = serverClient;
1040bbe1b32bSmrg	fsfree(client);
1041bbe1b32bSmrg
1042bbe1b32bSmrg#ifdef DEBUG
1043bbe1b32bSmrg	fprintf(stderr, "Shut down client\n");
1044bbe1b32bSmrg#endif
1045bbe1b32bSmrg
1046bbe1b32bSmrg	while (!clients[currentMaxClients - 1])
1047bbe1b32bSmrg	    currentMaxClients--;
1048bbe1b32bSmrg    }
1049bbe1b32bSmrg}
1050bbe1b32bSmrg
1051bbe1b32bSmrgstatic void
1052bbe1b32bSmrgkill_all_clients(void)
1053bbe1b32bSmrg{
1054bbe1b32bSmrg    int         i;
1055bbe1b32bSmrg
1056bbe1b32bSmrg    for (i = MINCLIENT; i < currentMaxClients; i++) {
1057bbe1b32bSmrg	if (clients[i])
1058bbe1b32bSmrg	    CloseDownClient(clients[i]);
1059bbe1b32bSmrg    }
1060bbe1b32bSmrg}
1061bbe1b32bSmrg
1062bbe1b32bSmrgvoid
1063bbe1b32bSmrgInitProcVectors(void)
1064bbe1b32bSmrg{
1065bbe1b32bSmrg    int         i;
1066bbe1b32bSmrg
1067bbe1b32bSmrg    for (i = 0; i < NUM_PROC_VECTORS; i++) {
1068bbe1b32bSmrg	if (!ProcVector[i]) {
1069bbe1b32bSmrg	    ProcVector[i] = SwappedProcVector[i] = ProcBadRequest;
1070bbe1b32bSmrg	    ReplySwapVector[i] = (ReplySwapFunc)NotImplemented;
1071bbe1b32bSmrg	}
1072bbe1b32bSmrg    }
1073bbe1b32bSmrg    for (i = FSLASTEvent; i < NUM_EVENT_VECTORS; i++) {
1074bbe1b32bSmrg	EventSwapVector[i] = (EventSwapFunc)NotImplemented;
1075bbe1b32bSmrg    }
1076bbe1b32bSmrg}
1077bbe1b32bSmrg
1078bbe1b32bSmrgvoid
1079bbe1b32bSmrgInitClient(
1080bbe1b32bSmrg    ClientPtr   client,
1081bbe1b32bSmrg    int         i,
1082bbe1b32bSmrg    pointer     ospriv)
1083bbe1b32bSmrg{
1084ce6676dbSmrg    if (i != SERVER_CLIENT) {
1085ce6676dbSmrg	nClients++;
1086ce6676dbSmrg    }
1087bbe1b32bSmrg    client->index = i;
1088bbe1b32bSmrg    client->sequence = 0;
1089bbe1b32bSmrg    client->last_request_time = GetTimeInMillis();
1090bbe1b32bSmrg    client->clientGone = CLIENT_ALIVE;
1091bbe1b32bSmrg    client->noClientException = FSSuccess;
1092bbe1b32bSmrg    client->requestVector = InitialVector;
1093bbe1b32bSmrg    client->osPrivate = ospriv;
1094bbe1b32bSmrg    client->swapped = FALSE;
1095bbe1b32bSmrg
1096bbe1b32bSmrg    client->auth = (AuthContextPtr) 0;
1097bbe1b32bSmrg    client->catalogues = NULL;
1098bbe1b32bSmrg    client->num_catalogues = 0;
1099bbe1b32bSmrg    client->num_resolutions = 0;
1100bbe1b32bSmrg    client->resolutions = (fsResolution *) 0;
1101bbe1b32bSmrg    client->eventmask = (Mask) 0;
1102bbe1b32bSmrg}
1103bbe1b32bSmrg
1104bbe1b32bSmrgClientPtr
1105bbe1b32bSmrgNextAvailableClient(pointer ospriv)
1106bbe1b32bSmrg{
1107bbe1b32bSmrg    int         i;
1108bbe1b32bSmrg    ClientPtr   client;
1109bbe1b32bSmrg    fsFakeReq   data;
1110bbe1b32bSmrg
1111bbe1b32bSmrg    i = nextFreeClientID;
1112bbe1b32bSmrg    if (i == MaxClients)
1113bbe1b32bSmrg	return NullClient;
1114bbe1b32bSmrg
1115bbe1b32bSmrg    clients[i] = client = (ClientPtr) fsalloc(sizeof(ClientRec));
1116bbe1b32bSmrg    if (!client)
1117bbe1b32bSmrg	return NullClient;
1118bbe1b32bSmrg
1119bbe1b32bSmrg    InitClient(client, i, ospriv);
1120bbe1b32bSmrg
1121bbe1b32bSmrg    if (!InitClientResources(client)) {
1122bbe1b32bSmrg	fsfree(client);
1123bbe1b32bSmrg	return NullClient;
1124bbe1b32bSmrg    }
1125bbe1b32bSmrg    data.reqType = 1;
1126bbe1b32bSmrg    data.length = (sizeof(fsFakeReq) + SIZEOF(fsConnClientPrefix)) >> 2;
1127bbe1b32bSmrg    if (!InsertFakeRequest(client, (char *) &data, sizeof(fsFakeReq))) {
1128bbe1b32bSmrg	FreeClientResources(client);
1129bbe1b32bSmrg	fsfree(client);
1130bbe1b32bSmrg	return NullClient;
1131bbe1b32bSmrg    }
1132bbe1b32bSmrg    if (i == currentMaxClients)
1133bbe1b32bSmrg	currentMaxClients++;
1134bbe1b32bSmrg    while ((nextFreeClientID < MAXCLIENTS) && clients[nextFreeClientID])
1135bbe1b32bSmrg	nextFreeClientID++;
1136bbe1b32bSmrg
1137bbe1b32bSmrg    /* if we've maxed out, try to clone */
1138bbe1b32bSmrg    if (nextFreeClientID == MaxClients) {
1139bbe1b32bSmrg	CloneMyself();
1140bbe1b32bSmrg    }
1141bbe1b32bSmrg    return client;
1142bbe1b32bSmrg}
1143bbe1b32bSmrg
1144bbe1b32bSmrgvoid
1145bbe1b32bSmrgMarkClientException(ClientPtr client)
1146bbe1b32bSmrg{
1147bbe1b32bSmrg    client->noClientException = -2;
1148bbe1b32bSmrg}
1149