1 /***********************************************************
3 Copyright 1987, 1998 The Open Group
5 Permission to use, copy, modify, distribute, and sell this software and its
6 documentation for any purpose is hereby granted without fee, provided that
7 the above copyright notice appear in all copies and that both that
8 copyright notice and this permission notice appear in supporting
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 Except as contained in this notice, the name of The Open Group shall not be
22 used in advertising or otherwise to promote the sale, use or other dealings
23 in this Software without prior written authorization from The Open Group.
26 Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
30 Permission to use, copy, modify, and distribute this software and its
31 documentation for any purpose and without fee is hereby granted,
32 provided that the above copyright notice appear in all copies and that
33 both that copyright notice and this permission notice appear in
34 supporting documentation, and that the name of Digital not be
35 used in advertising or publicity pertaining to distribution of the
36 software without specific, written prior permission.
38 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
39 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
40 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
41 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
42 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
43 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
46 ******************************************************************/
48 #ifdef HAVE_DIX_CONFIG_H
49 #include <dix-config.h>
53 #include <X11/Xproto.h>
55 #include "dixstruct.h"
56 #include "extnsionst.h"
58 #include "scrnintstr.h"
64 #define LAST_EVENT 128
65 #define LAST_ERROR 255
67 static ExtensionEntry **extensions = (ExtensionEntry **)NULL;
69 int lastEvent = EXTENSION_EVENT_BASE;
70 static int lastError = FirstExtensionError;
71 static unsigned int NumExtensions = 0;
74 AddExtension(char *name, int NumEvents, int NumErrors,
75 int (*MainProc)(ClientPtr c1),
76 int (*SwappedMainProc)(ClientPtr c2),
77 void (*CloseDownProc)(ExtensionEntry *e),
78 unsigned short (*MinorOpcodeProc)(ClientPtr c3))
81 ExtensionEntry *ext, **newexts;
83 if (!MainProc || !SwappedMainProc || !MinorOpcodeProc)
84 return((ExtensionEntry *) NULL);
85 if ((lastEvent + NumEvents > LAST_EVENT) ||
86 (unsigned)(lastError + NumErrors > LAST_ERROR)) {
87 LogMessage(X_ERROR, "Not enabling extension %s: maximum number of "
88 "events or errors exceeded.\n", name);
89 return((ExtensionEntry *) NULL);
92 ext = calloc(sizeof (ExtensionEntry), 1);
95 if (!dixAllocatePrivates(&ext->devPrivates, PRIVATE_EXTENSION)) {
99 ext->name = malloc(strlen(name) + 1);
100 ext->num_aliases = 0;
101 ext->aliases = (char **)NULL;
104 dixFreePrivates(ext->devPrivates, PRIVATE_EXTENSION);
106 return((ExtensionEntry *) NULL);
108 strcpy(ext->name, name);
110 newexts = (ExtensionEntry **) realloc(extensions,
111 (i + 1) * sizeof(ExtensionEntry *));
115 dixFreePrivates(ext->devPrivates, PRIVATE_EXTENSION);
117 return((ExtensionEntry *) NULL);
120 extensions = newexts;
123 ext->base = i + EXTENSION_BASE;
124 ext->CloseDown = CloseDownProc;
125 ext->MinorOpcode = MinorOpcodeProc;
126 ProcVector[i + EXTENSION_BASE] = MainProc;
127 SwappedProcVector[i + EXTENSION_BASE] = SwappedMainProc;
130 ext->eventBase = lastEvent;
131 ext->eventLast = lastEvent + NumEvents;
132 lastEvent += NumEvents;
141 ext->errorBase = lastError;
142 ext->errorLast = lastError + NumErrors;
143 lastError += NumErrors;
151 RegisterExtensionNames(ext);
155 Bool AddExtensionAlias(char *alias, ExtensionEntry *ext)
162 aliases = (char **)realloc(ext->aliases,
163 (ext->num_aliases + 1) * sizeof(char *));
166 ext->aliases = aliases;
167 name = malloc(strlen(alias) + 1);
171 ext->aliases[ext->num_aliases] = name;
177 FindExtension(char *extname, int len)
181 for (i=0; i<NumExtensions; i++)
183 if ((strlen(extensions[i]->name) == len) &&
184 !strncmp(extname, extensions[i]->name, len))
186 for (j = extensions[i]->num_aliases; --j >= 0;)
188 if ((strlen(extensions[i]->aliases[j]) == len) &&
189 !strncmp(extname, extensions[i]->aliases[j], len))
194 return ((i == NumExtensions) ? -1 : i);
198 * CheckExtension returns the extensions[] entry for the requested
199 * extension name. Maybe this could just return a Bool instead?
202 CheckExtension(const char *extname)
206 n = FindExtension((char*)extname, strlen(extname));
208 return extensions[n];
214 * Added as part of Xace.
217 GetExtensionEntry(int major)
219 if (major < EXTENSION_BASE)
221 major -= EXTENSION_BASE;
222 if (major >= NumExtensions)
224 return extensions[major];
228 StandardMinorOpcode(ClientPtr client)
230 return ((xReq *)client->requestBuffer)->data;
234 MinorOpcodeOfRequest(ClientPtr client)
238 major = ((xReq *)client->requestBuffer)->reqType;
239 if (major < EXTENSION_BASE)
241 major -= EXTENSION_BASE;
242 if (major >= NumExtensions)
244 return (*extensions[major]->MinorOpcode)(client);
248 CloseDownExtensions(void)
252 for (i = NumExtensions - 1; i >= 0; i--)
254 if (extensions[i]->CloseDown)
255 extensions[i]->CloseDown(extensions[i]);
257 free(extensions[i]->name);
258 for (j = extensions[i]->num_aliases; --j >= 0;)
259 free(extensions[i]->aliases[j]);
260 free(extensions[i]->aliases);
261 dixFreePrivates(extensions[i]->devPrivates, PRIVATE_EXTENSION);
265 extensions = (ExtensionEntry **)NULL;
266 lastEvent = EXTENSION_EVENT_BASE;
267 lastError = FirstExtensionError;
271 ProcQueryExtension(ClientPtr client)
273 xQueryExtensionReply reply;
275 REQUEST(xQueryExtensionReq);
277 REQUEST_FIXED_SIZE(xQueryExtensionReq, stuff->nbytes);
279 memset(&reply, 0, sizeof(xQueryExtensionReply));
280 reply.type = X_Reply;
282 reply.major_opcode = 0;
283 reply.sequenceNumber = client->sequence;
285 if ( ! NumExtensions )
286 reply.present = xFalse;
289 i = FindExtension((char *)&stuff[1], stuff->nbytes);
290 if (i < 0 || XaceHook(XACE_EXT_ACCESS, client, extensions[i]))
291 reply.present = xFalse;
294 reply.present = xTrue;
295 reply.major_opcode = extensions[i]->base;
296 reply.first_event = extensions[i]->eventBase;
297 reply.first_error = extensions[i]->errorBase;
300 WriteReplyToClient(client, sizeof(xQueryExtensionReply), &reply);
305 ProcListExtensions(ClientPtr client)
307 xListExtensionsReply reply;
308 char *bufptr, *buffer;
309 int total_length = 0;
311 REQUEST_SIZE_MATCH(xReq);
313 memset(&reply, 0, sizeof(xListExtensionsReply));
314 reply.type = X_Reply;
315 reply.nExtensions = 0;
317 reply.sequenceNumber = client->sequence;
324 for (i=0; i<NumExtensions; i++)
326 /* call callbacks to find out whether to show extension */
327 if (XaceHook(XACE_EXT_ACCESS, client, extensions[i]) != Success)
330 total_length += strlen(extensions[i]->name) + 1;
331 reply.nExtensions += 1 + extensions[i]->num_aliases;
332 for (j = extensions[i]->num_aliases; --j >= 0;)
333 total_length += strlen(extensions[i]->aliases[j]) + 1;
335 reply.length = bytes_to_int32(total_length);
336 buffer = bufptr = malloc(total_length);
339 for (i=0; i<NumExtensions; i++)
342 if (XaceHook(XACE_EXT_ACCESS, client, extensions[i]) != Success)
345 *bufptr++ = len = strlen(extensions[i]->name);
346 memmove(bufptr, extensions[i]->name, len);
348 for (j = extensions[i]->num_aliases; --j >= 0;)
350 *bufptr++ = len = strlen(extensions[i]->aliases[j]);
351 memmove(bufptr, extensions[i]->aliases[j], len);
356 WriteReplyToClient(client, sizeof(xListExtensionsReply), &reply);
359 WriteToClient(client, total_length, buffer);