1
/* $XFree86: xc/programs/Xserver/dix/extension.c,v 3.11 2001/12/14 19:59:31 dawes Exp $ */
2
/***********************************************************
4
Copyright 1987, 1998 The Open Group
6
Permission to use, copy, modify, distribute, and sell this software and its
7
documentation for any purpose is hereby granted without fee, provided that
8
the above copyright notice appear in all copies and that both that
9
copyright notice and this permission notice appear in supporting
12
The above copyright notice and this permission notice shall be included in
13
all copies or substantial portions of the Software.
15
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
19
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
Except as contained in this notice, the name of The Open Group shall not be
23
used in advertising or otherwise to promote the sale, use or other dealings
24
in this Software without prior written authorization from The Open Group.
27
Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
31
Permission to use, copy, modify, and distribute this software and its
32
documentation for any purpose and without fee is hereby granted,
33
provided that the above copyright notice appear in all copies and that
34
both that copyright notice and this permission notice appear in
35
supporting documentation, and that the name of Digital not be
36
used in advertising or publicity pertaining to distribution of the
37
software without specific, written prior permission.
39
DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
40
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
41
DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
42
ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
43
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
44
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
47
******************************************************************/
48
/* $Xorg: extension.c,v 1.4 2001/02/09 02:04:40 xorgcvs Exp $ */
50
#ifdef HAVE_DIX_CONFIG_H
51
#include <dix-config.h>
57
#include <X11/Xproto.h>
59
#include "dixstruct.h"
60
#include "extnsionst.h"
62
#include "scrnintstr.h"
65
#define _SECURITY_SERVER
66
#include <X11/extensions/security.h>
72
#define EXTENSION_BASE 128
73
#define EXTENSION_EVENT_BASE 64
74
#define LAST_EVENT 128
75
#define LAST_ERROR 255
77
ScreenProcEntry AuxillaryScreenProcs[MAXSCREENS];
79
static ExtensionEntry **extensions = (ExtensionEntry **)NULL;
81
int lastEvent = EXTENSION_EVENT_BASE;
82
static int lastError = FirstExtensionError;
83
static unsigned int NumExtensions = 0;
86
AddExtension(char *name, int NumEvents, int NumErrors,
87
int (*MainProc)(ClientPtr c1),
88
int (*SwappedMainProc)(ClientPtr c2),
89
void (*CloseDownProc)(ExtensionEntry *e),
90
unsigned short (*MinorOpcodeProc)(ClientPtr c3))
93
register ExtensionEntry *ext, **newexts;
95
if (!MainProc || !SwappedMainProc || !CloseDownProc || !MinorOpcodeProc)
96
return((ExtensionEntry *) NULL);
97
if ((lastEvent + NumEvents > LAST_EVENT) ||
98
(unsigned)(lastError + NumErrors > LAST_ERROR))
99
return((ExtensionEntry *) NULL);
101
ext = (ExtensionEntry *) xalloc(sizeof(ExtensionEntry));
103
return((ExtensionEntry *) NULL);
104
ext->name = (char *)xalloc(strlen(name) + 1);
105
ext->num_aliases = 0;
106
ext->aliases = (char **)NULL;
110
return((ExtensionEntry *) NULL);
112
strcpy(ext->name, name);
114
newexts = (ExtensionEntry **) xrealloc(extensions,
115
(i + 1) * sizeof(ExtensionEntry *));
120
return((ExtensionEntry *) NULL);
123
extensions = newexts;
126
ext->base = i + EXTENSION_BASE;
127
ext->CloseDown = CloseDownProc;
128
ext->MinorOpcode = MinorOpcodeProc;
129
ProcVector[i + EXTENSION_BASE] = MainProc;
130
SwappedProcVector[i + EXTENSION_BASE] = SwappedMainProc;
133
ext->eventBase = lastEvent;
134
ext->eventLast = lastEvent + NumEvents;
135
lastEvent += NumEvents;
144
ext->errorBase = lastError;
145
ext->errorLast = lastError + NumErrors;
146
lastError += NumErrors;
158
(void) LbxAddExtension(name, ext->base, ext->eventBase, ext->errorBase);
163
Bool AddExtensionAlias(char *alias, ExtensionEntry *ext)
168
aliases = (char **)xrealloc(ext->aliases,
169
(ext->num_aliases + 1) * sizeof(char *));
172
ext->aliases = aliases;
173
name = (char *)xalloc(strlen(alias) + 1);
177
ext->aliases[ext->num_aliases] = name;
180
return LbxAddExtensionAlias(ext->index, alias);
187
FindExtension(char *extname, int len)
191
for (i=0; i<NumExtensions; i++)
193
if ((strlen(extensions[i]->name) == len) &&
194
!strncmp(extname, extensions[i]->name, len))
196
for (j = extensions[i]->num_aliases; --j >= 0;)
198
if ((strlen(extensions[i]->aliases[j]) == len) &&
199
!strncmp(extname, extensions[i]->aliases[j], len))
204
return ((i == NumExtensions) ? -1 : i);
208
* CheckExtension returns the extensions[] entry for the requested
209
* extension name. Maybe this could just return a Bool instead?
212
CheckExtension(const char *extname)
216
n = FindExtension((char*)extname, strlen(extname));
218
return extensions[n];
224
DeclareExtensionSecurity(char *extname, Bool secure)
227
int i = FindExtension(extname, strlen(extname));
230
int majorop = extensions[i]->base;
231
extensions[i]->secure = secure;
234
UntrustedProcVector[majorop] = ProcVector[majorop];
235
SwappedUntrustedProcVector[majorop] = SwappedProcVector[majorop];
239
UntrustedProcVector[majorop] = ProcBadRequest;
240
SwappedUntrustedProcVector[majorop] = ProcBadRequest;
245
LbxDeclareExtensionSecurity(extname, secure);
250
StandardMinorOpcode(ClientPtr client)
252
return ((xReq *)client->requestBuffer)->data;
256
MinorOpcodeOfRequest(ClientPtr client)
260
major = ((xReq *)client->requestBuffer)->reqType;
261
if (major < EXTENSION_BASE)
263
major -= EXTENSION_BASE;
264
if (major >= NumExtensions)
266
return (*extensions[major]->MinorOpcode)(client);
270
CloseDownExtensions()
275
LbxCloseDownExtensions();
278
for (i = NumExtensions - 1; i >= 0; i--)
280
(* extensions[i]->CloseDown)(extensions[i]);
282
xfree(extensions[i]->name);
283
for (j = extensions[i]->num_aliases; --j >= 0;)
284
xfree(extensions[i]->aliases[j]);
285
xfree(extensions[i]->aliases);
286
xfree(extensions[i]);
289
extensions = (ExtensionEntry **)NULL;
290
lastEvent = EXTENSION_EVENT_BASE;
291
lastError = FirstExtensionError;
292
for (i=0; i<MAXSCREENS; i++)
294
register ScreenProcEntry *spentry = &AuxillaryScreenProcs[i];
299
xfree(spentry->procList[spentry->num].name);
301
xfree(spentry->procList);
302
spentry->procList = (ProcEntryPtr)NULL;
308
ProcQueryExtension(ClientPtr client)
310
xQueryExtensionReply reply;
312
REQUEST(xQueryExtensionReq);
314
REQUEST_FIXED_SIZE(xQueryExtensionReq, stuff->nbytes);
316
reply.type = X_Reply;
318
reply.major_opcode = 0;
319
reply.sequenceNumber = client->sequence;
321
if ( ! NumExtensions )
322
reply.present = xFalse;
325
i = FindExtension((char *)&stuff[1], stuff->nbytes);
328
/* don't show insecure extensions to untrusted clients */
329
|| (client->trustLevel == XSecurityClientUntrusted &&
330
!extensions[i]->secure)
333
reply.present = xFalse;
336
reply.present = xTrue;
337
reply.major_opcode = extensions[i]->base;
338
reply.first_event = extensions[i]->eventBase;
339
reply.first_error = extensions[i]->errorBase;
342
WriteReplyToClient(client, sizeof(xQueryExtensionReply), &reply);
343
return(client->noClientException);
347
ProcListExtensions(ClientPtr client)
349
xListExtensionsReply reply;
350
char *bufptr, *buffer;
351
int total_length = 0;
353
REQUEST_SIZE_MATCH(xReq);
355
reply.type = X_Reply;
356
reply.nExtensions = 0;
358
reply.sequenceNumber = client->sequence;
365
for (i=0; i<NumExtensions; i++)
368
/* don't show insecure extensions to untrusted clients */
369
if (client->trustLevel == XSecurityClientUntrusted &&
370
!extensions[i]->secure)
373
total_length += strlen(extensions[i]->name) + 1;
374
reply.nExtensions += 1 + extensions[i]->num_aliases;
375
for (j = extensions[i]->num_aliases; --j >= 0;)
376
total_length += strlen(extensions[i]->aliases[j]) + 1;
378
reply.length = (total_length + 3) >> 2;
379
buffer = bufptr = (char *)ALLOCATE_LOCAL(total_length);
382
for (i=0; i<NumExtensions; i++)
386
if (client->trustLevel == XSecurityClientUntrusted &&
387
!extensions[i]->secure)
390
*bufptr++ = len = strlen(extensions[i]->name);
391
memmove(bufptr, extensions[i]->name, len);
393
for (j = extensions[i]->num_aliases; --j >= 0;)
395
*bufptr++ = len = strlen(extensions[i]->aliases[j]);
396
memmove(bufptr, extensions[i]->aliases[j], len);
401
WriteReplyToClient(client, sizeof(xListExtensionsReply), &reply);
404
WriteToClient(client, total_length, buffer);
405
DEALLOCATE_LOCAL(buffer);
407
return(client->noClientException);
412
LookupProc(char *name, GCPtr pGC)
415
register ScreenProcEntry *spentry;
416
spentry = &AuxillaryScreenProcs[pGC->pScreen->myNum];
419
for (i = 0; i < spentry->num; i++)
420
if (strcmp(name, spentry->procList[i].name) == 0)
421
return(spentry->procList[i].proc);
423
return (ExtensionLookupProc)NULL;
427
RegisterProc(char *name, GC *pGC, ExtensionLookupProc proc)
429
return RegisterScreenProc(name, pGC->pScreen, proc);
433
RegisterScreenProc(char *name, ScreenPtr pScreen, ExtensionLookupProc proc)
435
register ScreenProcEntry *spentry;
436
register ProcEntryPtr procEntry = (ProcEntryPtr)NULL;
440
spentry = &AuxillaryScreenProcs[pScreen->myNum];
441
/* first replace duplicates */
444
for (i = 0; i < spentry->num; i++)
445
if (strcmp(name, spentry->procList[i].name) == 0)
447
procEntry = &spentry->procList[i];
452
procEntry->proc = proc;
455
newname = (char *)xalloc(strlen(name)+1);
458
procEntry = (ProcEntryPtr)
459
xrealloc(spentry->procList,
460
sizeof(ProcEntryRec) * (spentry->num+1));
466
spentry->procList = procEntry;
467
procEntry += spentry->num;
468
procEntry->name = newname;
469
strcpy(newname, name);
470
procEntry->proc = proc;