aboutsummaryrefslogtreecommitdiff
path: root/nx-X11/programs/Xserver/xkb/ddxLoad.c
diff options
context:
space:
mode:
Diffstat (limited to 'nx-X11/programs/Xserver/xkb/ddxLoad.c')
-rw-r--r--nx-X11/programs/Xserver/xkb/ddxLoad.c908
1 files changed, 908 insertions, 0 deletions
diff --git a/nx-X11/programs/Xserver/xkb/ddxLoad.c b/nx-X11/programs/Xserver/xkb/ddxLoad.c
new file mode 100644
index 000000000..5f24e9ccc
--- /dev/null
+++ b/nx-X11/programs/Xserver/xkb/ddxLoad.c
@@ -0,0 +1,908 @@
+/************************************************************
+Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc.
+
+Permission to use, copy, modify, and distribute this
+software and its documentation for any purpose and without
+fee is hereby granted, provided that the above copyright
+notice appear in all copies and that both that copyright
+notice and this permission notice appear in supporting
+documentation, and that the name of Silicon Graphics not be
+used in advertising or publicity pertaining to distribution
+of the software without specific prior written permission.
+Silicon Graphics makes no representation about the suitability
+of this software for any purpose. It is provided "as is"
+without any express or implied warranty.
+
+SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
+GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
+DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH
+THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+********************************************************/
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#ifdef HAVE_XKB_CONFIG_H
+#include <xkb-config.h>
+#endif
+
+#include <errno.h>
+#include <stdio.h>
+#include <ctype.h>
+
+/* stat() */
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include <nx-X11/X.h>
+#include <nx-X11/Xos.h>
+#include <nx-X11/Xproto.h>
+#include <nx-X11/keysym.h>
+#include <nx-X11/extensions/XKM.h>
+#include "inputstr.h"
+#include "scrnintstr.h"
+#include "windowstr.h"
+#include <xkbsrv.h>
+#include <nx-X11/extensions/XI.h>
+#include "xkb.h"
+
+#if defined(CSRG_BASED) || defined(linux) || defined(__GNU__)
+#include <paths.h>
+#endif
+
+#ifndef PATH_MAX
+#ifdef MAXPATHLEN
+#define PATH_MAX MAXPATHLEN
+#else
+#define PATH_MAX 1024
+#endif
+#endif
+
+ /*
+ * If XKM_OUTPUT_DIR specifies a path without a leading slash, it is
+ * relative to the top-level XKB configuration directory.
+ * Making the server write to a subdirectory of that directory
+ * requires some work in the general case (install procedure
+ * has to create links to /var or somesuch on many machines),
+ * so we just compile into /usr/tmp for now.
+ */
+#ifndef XKM_OUTPUT_DIR
+#define XKM_OUTPUT_DIR "compiled/"
+#endif
+
+#define PRE_ERROR_MSG "\"The XKEYBOARD keymap compiler (xkbcomp) reports:\""
+#define ERROR_PREFIX "\"> \""
+#define POST_ERROR_MSG1 "\"Errors from xkbcomp are not fatal to the X server\""
+#define POST_ERROR_MSG2 "\"End of messages from xkbcomp\""
+
+#if defined(WIN32)
+#define PATHSEPARATOR "\\"
+#else
+#define PATHSEPARATOR "/"
+#endif
+
+#ifdef WIN32
+
+#include <nx-X11/Xwindows.h>
+const char*
+Win32TempDir()
+{
+ static char buffer[PATH_MAX];
+ if (GetTempPath(sizeof(buffer), buffer))
+ {
+ int len;
+ buffer[sizeof(buffer)-1] = 0;
+ len = strlen(buffer);
+ if (len > 0)
+ if (buffer[len-1] == '\\')
+ buffer[len-1] = 0;
+ return buffer;
+ }
+ if (getenv("TEMP") != NULL)
+ return getenv("TEMP");
+ else if (getenv("TMP") != NULL)
+ return getenv("TEMP");
+ else
+ return "/tmp";
+}
+
+int
+Win32System(const char *cmdline)
+{
+ STARTUPINFO si;
+ PROCESS_INFORMATION pi;
+ DWORD dwExitCode;
+ char *cmd = xstrdup(cmdline);
+
+ ZeroMemory( &si, sizeof(si) );
+ si.cb = sizeof(si);
+ ZeroMemory( &pi, sizeof(pi) );
+
+ if (!CreateProcess(NULL, cmd, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi))
+ {
+ LPVOID buffer;
+ if (!FormatMessage(
+ FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL,
+ GetLastError(),
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ (LPTSTR) &buffer,
+ 0,
+ NULL ))
+ {
+ ErrorF("Starting '%s' failed!\n", cmdline);
+ }
+ else
+ {
+ ErrorF("Starting '%s' failed: %s", cmdline, (char *)buffer);
+ LocalFree(buffer);
+ }
+
+ free(cmd);
+ return -1;
+ }
+ /* Wait until child process exits. */
+ WaitForSingleObject( pi.hProcess, INFINITE );
+
+ GetExitCodeProcess( pi.hProcess, &dwExitCode);
+
+ /* Close process and thread handles. */
+ CloseHandle( pi.hProcess );
+ CloseHandle( pi.hThread );
+ free(cmd);
+
+ return dwExitCode;
+}
+#undef System
+#define System(x) Win32System(x)
+#endif
+
+#ifdef MAKE_XKM_OUTPUT_DIR
+/* Borrow trans_mkdir from Xtransutil.c to more safely make directories */
+# undef X11_t
+# define TRANS_SERVER
+# define PRMSG(lvl,x,a,b,c) \
+ if (lvl <= 1) { LogMessage(X_ERROR,x,a,b,c); } else ((void)0)
+# include <nx-X11/Xtrans/Xtransutil.c>
+# ifndef XKM_OUTPUT_DIR_MODE
+# define XKM_OUTPUT_DIR_MODE 0755
+# endif
+#endif
+
+#ifdef NXAGENT_SERVER
+
+#define NX_XKB_BASE_DIRECTORY "/usr/lib/X11/xkb"
+#define NX_XKB_ALTERNATE_BASE_DIRECTORY "/usr/share/X11/xkb"
+#define NX_XKB_RULES_BASE_FILE "rules/base"
+#define NX_ALT_XKBCOMP_PATH "/usr/bin"
+
+static char _NXXkbBasePath[PATH_MAX];
+static char _NXXkbCompPath[PATH_MAX];
+
+static int NXVerifyXkbBaseDirectory(const char *dirPath)
+{
+ int size;
+ char *rulesBaseFilePath;
+ struct stat rulesBaseFileStat;
+
+ /*
+ * If rules/base file
+ * is not present inside
+ * the Xkb Base Directory,
+ * we suppose that the
+ * path is not valid.
+ */
+
+ size = strlen(dirPath) + strlen("/") +
+ strlen(NX_XKB_RULES_BASE_FILE) + 1;
+
+ if ((rulesBaseFilePath = malloc((size + 1) * sizeof(char))) == NULL)
+ {
+ FatalError("NXVerifyXkbBaseDirectory: malloc failed.\n");
+ }
+
+ strcpy(rulesBaseFilePath, dirPath);
+ strcat(rulesBaseFilePath, "/");
+ strcat(rulesBaseFilePath, NX_XKB_RULES_BASE_FILE);
+
+ #ifdef TEST
+ fprintf(stderr, "NXVerifyXkbBaseDirectory: Looking for [%s] file.\n",
+ rulesBaseFilePath);
+ #endif
+
+ if (stat(rulesBaseFilePath, &rulesBaseFileStat) != 0)
+ {
+
+ #ifdef TEST
+ fprintf(stderr, "NXVerifyXkbBaseDirectory: Xkb Base Directory [%s] is not valid (can't find file [%s]).\n",
+ dirPath, rulesBaseFilePath);
+ #endif
+
+ free(rulesBaseFilePath);
+
+ return 0;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "NXVerifyXkbBaseDirectory: Xkb Base Directory [%s] is valid.\n",
+ dirPath);
+ #endif
+
+ free(rulesBaseFilePath);
+
+ return 1;
+}
+
+/*
+ * This function returns the directory
+ * containing the configuration files.
+ * This directory is referred by Xkb-
+ * BaseDirectory variable (generally
+ * it contains the hardcoded path at
+ * compile time). If the directory
+ * does not exist, the function will
+ * try a set of well known directories.
+ */
+
+char *_NXGetXkbBasePath(const char *path)
+{
+ /*
+ * Check the xkb base directory only once.
+ */
+
+ if (*_NXXkbBasePath != '\0')
+ {
+ return _NXXkbBasePath;
+ }
+
+ if (NXVerifyXkbBaseDirectory(XkbBaseDirectory) == 1)
+ {
+ if (strlen(XkbBaseDirectory) + 1 > PATH_MAX)
+ {
+ #ifdef TEST
+ fprintf(stderr, "_NXGetXkbBasePath: WARNING! Maximum length of xkb base path exceeded.\n");
+ #endif
+
+ goto _NXGetXkbBasePathError;
+ }
+
+ strcpy(_NXXkbBasePath, XkbBaseDirectory);
+
+ #ifdef TEST
+ fprintf(stderr, "_NXGetXkbBasePath: Using NX xkb base directory path [%s].\n",
+ _NXXkbBasePath);
+ #endif
+
+ return _NXXkbBasePath;
+ }
+
+ if (NXVerifyXkbBaseDirectory(NX_XKB_BASE_DIRECTORY) == 1)
+ {
+ if (strlen(NX_XKB_BASE_DIRECTORY) + 1 > PATH_MAX)
+ {
+ #ifdef TEST
+ fprintf(stderr, "_NXGetXkbBasePath: WARNING! Maximum length of xkb base path exceeded.\n");
+ #endif
+
+ goto _NXGetXkbBasePathError;
+ }
+
+ strcpy(_NXXkbBasePath, NX_XKB_BASE_DIRECTORY);
+
+ #ifdef TEST
+ fprintf(stderr, "_NXGetXkbBasePath: Using NX xkb base directory path [%s].\n",
+ _NXXkbBasePath);
+ #endif
+
+ return _NXXkbBasePath;
+ }
+
+ if (NXVerifyXkbBaseDirectory(NX_XKB_ALTERNATE_BASE_DIRECTORY) == 1)
+ {
+ if (strlen(NX_XKB_ALTERNATE_BASE_DIRECTORY) + 1 > PATH_MAX)
+ {
+ #ifdef TEST
+ fprintf(stderr, "_NXGetXkbBasePath: WARNING! Maximum length of xkb base path exceeded.\n");
+ #endif
+
+ goto _NXGetXkbBasePathError;
+ }
+
+ strcpy(_NXXkbBasePath, NX_XKB_ALTERNATE_BASE_DIRECTORY);
+
+ #ifdef TEST
+ fprintf(stderr, "_NXGetXkbBasePath: Using NX xkb base directory path [%s].\n",
+ _NXXkbBasePath);
+ #endif
+
+ return _NXXkbBasePath;
+ }
+
+_NXGetXkbBasePathError:
+
+ if (strlen(path) + 1 > PATH_MAX)
+ {
+ #ifdef TEST
+ fprintf(stderr, "_NXGetXkbBasePath: WARNING! Maximum length of xkb base path exceeded.\n");
+ #endif
+ }
+
+ strcpy(_NXXkbBasePath, path);
+
+ #ifdef TEST
+ fprintf(stderr, "_NXGetXkbBasePath: Using default xkb base path [%s].\n",
+ _NXXkbBasePath);
+ #endif
+
+ return _NXXkbBasePath;
+}
+
+static int NXVerifyXkbCompPath(char *path)
+{
+ char *xkbCompPath;
+ int xkbCompPathSize;
+ struct stat xkbCompPathStat;
+
+ if (path == NULL)
+ {
+ return 0;
+ }
+
+ xkbCompPathSize = strlen(path) + strlen("/") +
+ strlen("xkbcomp") + 1;
+
+ if ((xkbCompPath = malloc((xkbCompPathSize + 1) * sizeof(char))) == NULL)
+ {
+ FatalError("NXVerifyXkbCompPath: WARNING! malloc failed.\n");
+
+ return 0;
+ }
+
+ strcpy(xkbCompPath, path);
+ strcat(xkbCompPath, "/");
+ strcat(xkbCompPath, "xkbcomp");
+
+ if (stat(xkbCompPath, &xkbCompPathStat) != 0)
+ {
+ #ifdef NX_TRANS_TEST
+ fprintf(stderr, "NXVerifyXkbCompPath: WARNING! Failed to stat xkbcomp path [%s].\n",
+ xkbCompPath);
+ #endif
+
+ free(xkbCompPath);
+
+ return 0;
+ }
+
+ free(xkbCompPath);
+
+ return 1;
+}
+
+/*
+ * This function returns the directory
+ * containing the xkbcomp executable.
+ * The function will first try to locate
+ * the executable in the hardcoded path
+ * (the same path as the "base" xkb one)
+ * and, if the xkbcomp file couldn't be
+ * found, the function will not include
+ * an explicit path and will rely on the
+ * PATH environment to list the directory.
+ */
+
+char *_NXGetXkbCompPath(const char *path)
+{
+
+ char * xkbCompPath;
+
+ /*
+ * Check the xkbcomp executable
+ * directory only once.
+ */
+
+ if (*_NXXkbCompPath != '\0')
+ {
+ return _NXXkbCompPath;
+ }
+
+ xkbCompPath = _NXGetXkbBasePath(path);
+
+ if (NXVerifyXkbCompPath(xkbCompPath) == 1)
+ {
+ if (strlen(xkbCompPath) + 1 > PATH_MAX)
+ {
+ #ifdef TEST
+ fprintf(stderr, "_NXGetXkbCompPath: WARNING! Maximum length of xkbcomp path exceeded.\n");
+ #endif
+
+ goto _NXGetXkbCompPathError;
+ }
+
+ strcpy(_NXXkbCompPath, xkbCompPath);
+
+ #ifdef TEST
+ fprintf(stderr, "_NXGetXkbCompPath: Using xkbcomp path [%s].\n",
+ _NXXkbCompPath);
+ #endif
+
+ return _NXXkbCompPath;
+ }
+
+ xkbCompPath = NX_ALT_XKBCOMP_PATH;
+
+ if (NXVerifyXkbCompPath(xkbCompPath) == 1)
+ {
+ if (strlen(xkbCompPath) + 1 > PATH_MAX)
+ {
+ #ifdef TEST
+ fprintf(stderr, "_NXGetXkbCompPath: WARNING! Maximum length of xkbcomp path exceeded.\n");
+ #endif
+
+ goto _NXGetXkbCompPathError;
+ }
+
+ strcpy(_NXXkbCompPath, xkbCompPath);
+
+ #ifdef TEST
+ fprintf(stderr, "_NXGetXkbCompPath: Using NX xkbcomp path [%s].\n",
+ _NXXkbCompPath);
+ #endif
+
+ return _NXXkbCompPath;
+ }
+
+_NXGetXkbCompPathError:
+
+ if (strlen(path) + 1 > PATH_MAX)
+ {
+ #ifdef TEST
+ fprintf(stderr, "_NXGetXkbCompPath: WARNING! Maximum length of xkbcomp path exceeded.\n");
+ #endif
+ }
+
+ strcpy(_NXXkbCompPath, path);
+
+ #ifdef TEST
+ fprintf(stderr, "_NXGetXkbCompPath: Using default xkbcomp path [%s].\n",
+ _NXXkbCompPath);
+ #endif
+
+ return _NXXkbCompPath;
+}
+
+#endif
+
+static void
+OutputDirectory(
+ char* outdir,
+ size_t size)
+{
+#ifndef WIN32
+ if (getuid() == 0 && (strlen(XKM_OUTPUT_DIR) < size)
+#ifdef MAKE_XKM_OUTPUT_DIR
+ && (trans_mkdir(XKM_OUTPUT_DIR, XKM_OUTPUT_DIR_MODE) == 0)
+#endif
+ )
+ {
+ /* if server running as root it *may* be able to write */
+ /* FIXME: check whether directory is writable at all */
+ (void) strcpy (outdir, XKM_OUTPUT_DIR);
+ } else
+#endif
+#ifdef _PATH_VARTMP
+ if ((strlen(_PATH_VARTMP) + 1) < size)
+ {
+ (void) strcpy (outdir, _PATH_VARTMP);
+ if (outdir[strlen(outdir) - 1] != '/') /* Hi IBM, Digital */
+ (void) strcat (outdir, "/");
+ } else
+#endif
+#ifdef WIN32
+ if (strlen(Win32TempDir()) + 1 < size)
+ {
+ (void) strcpy(outdir, Win32TempDir());
+ (void) strcat(outdir, "\\");
+ } else
+#endif
+ if (strlen("/tmp/") < size)
+ {
+ (void) strcpy (outdir, "/tmp/");
+ }
+}
+
+Bool
+XkbDDXCompileNamedKeymap( XkbDescPtr xkb,
+ XkbComponentNamesPtr names,
+ char * nameRtrn,
+ int nameRtrnLen)
+{
+char *cmd = NULL,file[PATH_MAX],xkm_output_dir[PATH_MAX],*map,*outFile;
+
+ if (names->keymap==NULL)
+ return False;
+ strncpy(file,names->keymap,PATH_MAX); file[PATH_MAX-1]= '\0';
+ if ((map= strrchr(file,'('))!=NULL) {
+ char *tmp;
+ if ((tmp= strrchr(map,')'))!=NULL) {
+ *map++= '\0';
+ *tmp= '\0';
+ }
+ else {
+ map= NULL;
+ }
+ }
+ if ((outFile= strrchr(file,'/'))!=NULL)
+ outFile= Xstrdup(&outFile[1]);
+ else outFile= Xstrdup(file);
+ XkbEnsureSafeMapName(outFile);
+ OutputDirectory(xkm_output_dir, sizeof(xkm_output_dir));
+
+#ifdef NXAGENT_SERVER
+
+ if (_NXGetXkbCompPath(XkbBaseDirectory) != NULL)
+ {
+
+#else
+
+ if (XkbBaseDirectory!=NULL) {
+
+#endif
+
+#ifdef NXAGENT_SERVER
+ char *xkbbasedir = _NXGetXkbBasePath(XkbBaseDirectory);
+ char *xkbbindir = _NXGetXkbCompPath(XkbBinDirectory);
+#else
+ char *xkbbasedir = XkbBaseDirectory;
+ char *xkbbindir = XkbBinDirectory;
+#endif
+
+ cmd = Xprintf("\"%s" PATHSEPARATOR "xkbcomp\" -w %d \"-R%s\" -xkm %s%s -em1 %s -emp %s -eml %s keymap/%s \"%s%s.xkm\"",
+ xkbbindir,
+ ((xkbDebugFlags<2)?1:((xkbDebugFlags>10)?10:(int)xkbDebugFlags)),
+ xkbbasedir,(map?"-m ":""),(map?map:""),
+ PRE_ERROR_MSG,ERROR_PREFIX,POST_ERROR_MSG1,file,
+ xkm_output_dir,outFile);
+ }
+ else {
+ cmd = Xprintf("xkbcomp -w %d -xkm %s%s -em1 %s -emp %s -eml %s keymap/%s \"%s%s.xkm\"",
+ ((xkbDebugFlags<2)?1:((xkbDebugFlags>10)?10:(int)xkbDebugFlags)),
+ (map?"-m ":""),(map?map:""),
+ PRE_ERROR_MSG,ERROR_PREFIX,POST_ERROR_MSG1,file,
+ xkm_output_dir,outFile);
+ }
+#ifdef DEBUG
+ if (xkbDebugFlags) {
+ ErrorF("XkbDDXCompileNamedKeymap compiling keymap using:\n");
+ ErrorF(" \"cmd\"\n");
+ }
+#endif
+#ifdef DEBUG_CMD
+ ErrorF("xkb executes: %s\n",cmd);
+#endif
+ if (System(cmd)==0) {
+ if (nameRtrn) {
+ strncpy(nameRtrn,outFile,nameRtrnLen);
+ nameRtrn[nameRtrnLen-1]= '\0';
+ }
+ if (outFile!=NULL)
+ _XkbFree(outFile);
+ if (cmd!=NULL)
+ free(cmd);
+ return True;
+ }
+#ifdef DEBUG
+ ErrorF("Error compiling keymap (%s)\n",names->keymap);
+#endif
+ if (outFile!=NULL)
+ _XkbFree(outFile);
+ if (cmd!=NULL)
+ free(cmd);
+ return False;
+}
+
+Bool
+XkbDDXCompileKeymapByNames( XkbDescPtr xkb,
+ XkbComponentNamesPtr names,
+ unsigned want,
+ unsigned need,
+ char * nameRtrn,
+ int nameRtrnLen)
+{
+FILE * out;
+char *buf = NULL, keymap[PATH_MAX],xkm_output_dir[PATH_MAX];
+
+#ifdef WIN32
+char tmpname[PATH_MAX];
+#endif
+ if ((names->keymap==NULL)||(names->keymap[0]=='\0')) {
+ sprintf(keymap,"server-%s",display);
+ }
+ else {
+ if (strlen(names->keymap) > PATH_MAX - 1) {
+ ErrorF("name of keymap (%s) exceeds max length\n", names->keymap);
+ return False;
+ }
+ strcpy(keymap,names->keymap);
+ }
+
+ XkbEnsureSafeMapName(keymap);
+ OutputDirectory(xkm_output_dir, sizeof(xkm_output_dir));
+#ifdef WIN32
+ strcpy(tmpname, Win32TempDir());
+ strcat(tmpname, "\\xkb_XXXXXX");
+ (void) mktemp(tmpname);
+#endif
+
+#ifdef NXAGENT_SERVER
+ if (_NXGetXkbCompPath(XkbBaseDirectory)!=NULL) {
+#else
+ if (XkbBaseDirectory!=NULL) {
+#endif
+
+#ifndef WIN32
+ char *xkmfile = "-";
+#else
+ /* WIN32 has no popen. The input must be stored in a file which is used as input
+ for xkbcomp. xkbcomp does not read from stdin. */
+ char *xkmfile = tmpname;
+#endif
+#ifdef NXAGENT_SERVER
+ char *xkbbasedir = _NXGetXkbBasePath(XkbBaseDirectory);
+ char *xkbbindir = _NXGetXkbCompPath(XkbBinDirectory);
+#else
+ char *xkbbasedir = XkbBaseDirectory;
+ char *xkbbindir = XkbBinDirectory;
+#endif
+
+ buf = Xprintf(
+ "\"%s" PATHSEPARATOR "xkbcomp\" -w %d \"-R%s\" -xkm \"%s\" -em1 %s -emp %s -eml %s \"%s%s.xkm\"",
+ xkbbindir,
+ ((xkbDebugFlags<2)?1:((xkbDebugFlags>10)?10:(int)xkbDebugFlags)),
+ xkbbasedir, xkmfile,
+ PRE_ERROR_MSG,ERROR_PREFIX,POST_ERROR_MSG1,
+ xkm_output_dir,keymap);
+ }
+ else {
+#ifndef WIN32
+ char *xkmfile = "-";
+#else
+ char *xkmfile = tmpname;
+#endif
+ buf = Xprintf(
+ "xkbcomp -w %d -xkm \"%s\" -em1 %s -emp %s -eml %s \"%s%s.xkm\"",
+ ((xkbDebugFlags<2)?1:((xkbDebugFlags>10)?10:(int)xkbDebugFlags)),
+ xkmfile,
+ PRE_ERROR_MSG,ERROR_PREFIX,POST_ERROR_MSG1,
+ xkm_output_dir,keymap);
+ }
+
+ #ifdef TEST
+ if (buf != NULL)
+ fprintf(stderr, "XkbDDXCompileKeymapByNames: "
+ "Executing command [%s].\n", buf);
+ else
+ fprintf(stderr, "XkbDDXCompileKeymapByNames: "
+ "Callin Popen() with null command.\n");
+ #endif
+
+#ifndef WIN32
+ out= Popen(buf,"w");
+#else
+ out= fopen(tmpname, "w");
+#endif
+
+ if (out!=NULL) {
+#ifdef DEBUG
+ if (xkbDebugFlags) {
+ ErrorF("XkbDDXCompileKeymapByNames compiling keymap:\n");
+ XkbWriteXKBKeymapForNames(stderr,names,NULL,xkb,want,need);
+ }
+#endif
+ XkbWriteXKBKeymapForNames(out,names,NULL,xkb,want,need);
+#ifndef WIN32
+#ifdef __sun
+ if (Pclose(out) != 0)
+ {
+ ErrorF("Warning: Spurious failure reported in Pclose() runnning 'xkbcomp'.\n");
+ }
+ if (1)
+#else
+ if (Pclose(out)==0)
+#endif
+#else
+ if (fclose(out)==0 && System(buf) >= 0)
+#endif
+ {
+#ifdef DEBUG_CMD
+ ErrorF("xkb executes: %s\n",buf);
+ ErrorF("xkbcomp input:\n");
+ XkbWriteXKBKeymapForNames(stderr,names,NULL,xkb,want,need);
+ ErrorF("end xkbcomp input\n");
+#endif
+ if (nameRtrn) {
+ strncpy(nameRtrn,keymap,nameRtrnLen);
+ nameRtrn[nameRtrnLen-1]= '\0';
+ }
+ if (buf != NULL)
+ free (buf);
+ return True;
+ }
+#ifdef DEBUG
+ else
+ ErrorF("Error compiling keymap (%s)\n",keymap);
+#endif
+#ifdef WIN32
+ /* remove the temporary file */
+ unlink(tmpname);
+#endif
+ }
+#ifdef DEBUG
+ else {
+#ifndef WIN32
+ ErrorF("Could not invoke keymap compiler\n");
+#else
+ ErrorF("Could not open file %s\n", tmpname);
+#endif
+ }
+#endif
+ if (nameRtrn)
+ nameRtrn[0]= '\0';
+ if (buf != NULL)
+ free (buf);
+ return False;
+}
+
+FILE *
+XkbDDXOpenConfigFile(char *mapName,char *fileNameRtrn,int fileNameRtrnLen)
+{
+char buf[PATH_MAX],xkm_output_dir[PATH_MAX];
+FILE * file;
+
+ buf[0]= '\0';
+ if (mapName!=NULL) {
+ OutputDirectory(xkm_output_dir, sizeof(xkm_output_dir));
+ if ((XkbBaseDirectory!=NULL)&&(xkm_output_dir[0]!='/')
+#ifdef WIN32
+ &&(!isalpha(xkm_output_dir[0]) || xkm_output_dir[1]!=':')
+#endif
+ ) {
+ if (strlen(XkbBaseDirectory)+strlen(xkm_output_dir)
+ +strlen(mapName)+6 <= PATH_MAX)
+ {
+ sprintf(buf,"%s/%s%s.xkm",XkbBaseDirectory,
+ xkm_output_dir,mapName);
+ }
+ }
+ else if (strlen(xkm_output_dir)+strlen(mapName)+5 <= PATH_MAX)
+ sprintf(buf,"%s%s.xkm",xkm_output_dir,mapName);
+ if (buf[0] != '\0')
+ file= fopen(buf,"rb");
+ else file= NULL;
+ }
+ else file= NULL;
+ if ((fileNameRtrn!=NULL)&&(fileNameRtrnLen>0)) {
+ strncpy(fileNameRtrn,buf,fileNameRtrnLen);
+ buf[fileNameRtrnLen-1]= '\0';
+ }
+ return file;
+}
+
+unsigned
+XkbDDXLoadKeymapByNames( DeviceIntPtr keybd,
+ XkbComponentNamesPtr names,
+ unsigned want,
+ unsigned need,
+ XkbFileInfo * finfoRtrn,
+ char * nameRtrn,
+ int nameRtrnLen)
+{
+XkbDescPtr xkb;
+FILE * file;
+char fileName[PATH_MAX];
+unsigned missing;
+
+ bzero(finfoRtrn,sizeof(XkbFileInfo));
+ if ((keybd==NULL)||(keybd->key==NULL)||(keybd->key->xkbInfo==NULL))
+ xkb= NULL;
+ else xkb= keybd->key->xkbInfo->desc;
+ if ((names->keycodes==NULL)&&(names->types==NULL)&&
+ (names->compat==NULL)&&(names->symbols==NULL)&&
+ (names->geometry==NULL)) {
+ if (names->keymap==NULL) {
+ bzero(finfoRtrn,sizeof(XkbFileInfo));
+ if (xkb && XkbDetermineFileType(finfoRtrn,XkbXKMFile,NULL) &&
+ ((finfoRtrn->defined&need)==need) ) {
+ finfoRtrn->xkb= xkb;
+ nameRtrn[0]= '\0';
+ return finfoRtrn->defined;
+ }
+ return 0;
+ }
+ else if (!XkbDDXCompileNamedKeymap(xkb,names,nameRtrn,nameRtrnLen)) {
+#ifdef NOISY
+ ErrorF("Couldn't compile keymap file\n");
+#endif
+ return 0;
+ }
+ }
+ else if (!XkbDDXCompileKeymapByNames(xkb,names,want,need,
+ nameRtrn,nameRtrnLen)){
+#ifdef NOISY
+ ErrorF("Couldn't compile keymap file\n");
+#endif
+ return 0;
+ }
+ file= XkbDDXOpenConfigFile(nameRtrn,fileName,PATH_MAX);
+ if (file==NULL) {
+ LogMessage(X_ERROR, "Couldn't open compiled keymap file %s\n",fileName);
+ return 0;
+ }
+ missing= XkmReadFile(file,need,want,finfoRtrn);
+ if (finfoRtrn->xkb==NULL) {
+ LogMessage(X_ERROR, "Error loading keymap %s\n",fileName);
+ fclose(file);
+ (void) unlink (fileName);
+ return 0;
+ }
+#ifdef DEBUG
+ else if (xkbDebugFlags) {
+ ErrorF("Loaded %s, defined=0x%x\n",fileName,finfoRtrn->defined);
+ }
+#endif
+ fclose(file);
+ (void) unlink (fileName);
+ return (need|want)&(~missing);
+}
+
+Bool
+XkbDDXNamesFromRules( DeviceIntPtr keybd,
+ char * rules_name,
+ XkbRF_VarDefsPtr defs,
+ XkbComponentNamesPtr names)
+{
+char buf[PATH_MAX];
+FILE * file;
+Bool complete;
+XkbRF_RulesPtr rules;
+
+ if (!rules_name)
+ return False;
+ if (XkbBaseDirectory==NULL) {
+ if (strlen(rules_name)+7 > PATH_MAX)
+ return False;
+ sprintf(buf,"rules/%s",rules_name);
+ }
+ else {
+ if (strlen(XkbBaseDirectory)+strlen(rules_name)+8 > PATH_MAX)
+ return False;
+ sprintf(buf,"%s/rules/%s",XkbBaseDirectory,rules_name);
+ }
+ if ((file= fopen(buf,"r"))==NULL)
+ return False;
+ if ((rules= XkbRF_Create(0,0))==NULL) {
+ fclose(file);
+ return False;
+ }
+ if (!XkbRF_LoadRules(file,rules)) {
+ fclose(file);
+ XkbRF_Free(rules,True);
+ return False;
+ }
+ bzero((char *)names,sizeof(XkbComponentNamesRec));
+ complete= XkbRF_GetComponents(rules,defs,names);
+ fclose(file);
+ XkbRF_Free(rules,True);
+ return complete;
+}
+
+