aboutsummaryrefslogtreecommitdiff
path: root/nx-X11/programs/Xserver/xkb/ddxLoad.c
diff options
context:
space:
mode:
authorReinhard Tartler <siretart@tauware.de>2011-10-10 17:43:39 +0200
committerReinhard Tartler <siretart@tauware.de>2011-10-10 17:43:39 +0200
commitf4092abdf94af6a99aff944d6264bc1284e8bdd4 (patch)
tree2ac1c9cc16ceb93edb2c4382c088dac5aeafdf0f /nx-X11/programs/Xserver/xkb/ddxLoad.c
parenta840692edc9c6d19cd7c057f68e39c7d95eb767d (diff)
downloadnx-libs-f4092abdf94af6a99aff944d6264bc1284e8bdd4.tar.gz
nx-libs-f4092abdf94af6a99aff944d6264bc1284e8bdd4.tar.bz2
nx-libs-f4092abdf94af6a99aff944d6264bc1284e8bdd4.zip
Imported nx-X11-3.1.0-1.tar.gznx-X11/3.1.0-1
Summary: Imported nx-X11-3.1.0-1.tar.gz Keywords: Imported nx-X11-3.1.0-1.tar.gz into Git repository
Diffstat (limited to 'nx-X11/programs/Xserver/xkb/ddxLoad.c')
-rw-r--r--nx-X11/programs/Xserver/xkb/ddxLoad.c965
1 files changed, 965 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..8def401e8
--- /dev/null
+++ b/nx-X11/programs/Xserver/xkb/ddxLoad.c
@@ -0,0 +1,965 @@
+/* $Xorg: ddxLoad.c,v 1.3 2000/08/17 19:53:46 cpqbld Exp $ */
+/************************************************************
+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.
+
+********************************************************/
+/* $XFree86: xc/programs/Xserver/xkb/ddxLoad.c,v 3.35 2003/10/02 13:30:12 eich Exp $ */
+
+#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>
+#define NEED_EVENTS 1
+#include <X11/X.h>
+#include <X11/Xos.h>
+#include <X11/Xproto.h>
+#include <X11/keysym.h>
+#include <X11/extensions/XKM.h>
+#include "inputstr.h"
+#include "scrnintstr.h"
+#include "windowstr.h"
+#define XKBSRV_NEED_FILE_FUNCS
+#include <X11/extensions/XKBsrv.h>
+#include <X11/extensions/XI.h>
+#include "xkb.h"
+
+#if defined(CSRG_BASED) || defined(linux) || defined(__sgi) || defined(AIXV3) || defined(__osf__) || 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(__UNIXOS2__) || defined(WIN32)
+#define PATHSEPARATOR "\\"
+#else
+#define PATHSEPARATOR "/"
+#endif
+
+#ifdef WIN32
+
+#include <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);
+ }
+
+ xfree(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 );
+ xfree(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 <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_KEYMAP_DIR_FILE "keymap.dir"
+#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 *keymapDirFilePath;
+ struct stat keymapDirFileStat;
+
+ /*
+ * If keymap.dir file
+ * is not present into
+ * Xkb Base Directory,
+ * we suppose that the
+ * path is not valid.
+ */
+
+ size = strlen(dirPath) + strlen("/") +
+ strlen(NX_KEYMAP_DIR_FILE) + 1;
+
+ if ((keymapDirFilePath = malloc((size + 1) * sizeof(char))) == NULL)
+ {
+ FatalError("NXVerifyXkbBaseDirectory: malloc failed.\n");
+ }
+
+ strcpy(keymapDirFilePath, dirPath);
+ strcat(keymapDirFilePath, "/");
+ strcat(keymapDirFilePath, NX_KEYMAP_DIR_FILE);
+
+ #ifdef TEST
+ fprintf(stderr, "NXVerifyXkbBaseDirectory: Looking for [%s] file.\n",
+ keymapDirFilePath);
+ #endif
+
+ if (stat(keymapDirFilePath, &keymapDirFileStat) != 0)
+ {
+
+ #ifdef TEST
+ fprintf(stderr, "NXVerifyXkbBaseDirectory: Can't find the keymap.dir file [%s].\n",
+ keymapDirFilePath);
+ #endif
+
+ free(keymapDirFilePath);
+
+ return 0;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "NXVerifyXkbBaseDirectory: Xkb Base Directory [%s] is valid.\n",
+ dirPath);
+ #endif
+
+ free(keymapDirFilePath);
+
+ 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= _XkbDupString(&outFile[1]);
+ else outFile= _XkbDupString(file);
+ XkbEnsureSafeMapName(outFile);
+ OutputDirectory(xkm_output_dir, sizeof(xkm_output_dir));
+
+#ifdef NXAGENT_SERVER
+
+ if (_NXGetXkbCompPath(XkbBaseDirectory) != NULL)
+ {
+
+#else
+
+ if (XkbBaseDirectory!=NULL) {
+
+#endif
+
+#ifndef __UNIXOS2__
+
+#ifdef NXAGENT_SERVER
+ char *xkbbasedir = _NXGetXkbCompPath(XkbBaseDirectory);
+ char *xkbbindir = _NXGetXkbCompPath(XkbBinDirectory);
+#else
+ char *xkbbasedir = XkbBaseDirectory;
+ char *xkbbindir = XkbBinDirectory;
+#endif
+
+#else
+ /* relocate the basedir and replace the slashes with backslashes */
+#ifdef NXAGENT_SERVER
+ char *xkbbasedir = (char*)__XOS2RedirRoot(_NXGetXkbCompPath(XkbBaseDirectory));
+ char *xkbbindir = (char*)__XOS2RedirRoot(_NXGetXkbCompPath(XkbBinDirectory));
+#else
+ char *xkbbasedir = (char*)__XOS2RedirRoot(XkbBaseDirectory);
+ char *xkbbindir = (char*)__XOS2RedirRoot(XkbBinDirectory);
+#endif
+ int i;
+
+ for (i=0; i<strlen(xkbbasedir); i++)
+ if (xkbbasedir[i]=='/') xkbbasedir[i]='\\';
+ for (i=0; i<strlen(xkbbindir); i++)
+ if (xkbbindir[i]=='/') xkbbindir[i]='\\';
+#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)
+ xfree(cmd);
+ return True;
+ }
+#ifdef DEBUG
+ ErrorF("Error compiling keymap (%s)\n",names->keymap);
+#endif
+ if (outFile!=NULL)
+ _XkbFree(outFile);
+ if (cmd!=NULL)
+ xfree(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
+#ifndef __UNIXOS2__
+#ifdef NXAGENT_SERVER
+ char *xkbbasedir = _NXGetXkbCompPath(XkbBaseDirectory);
+ char *xkbbindir = _NXGetXkbCompPath(XkbBinDirectory);
+#else
+ char *xkbbasedir = XkbBaseDirectory;
+ char *xkbbindir = XkbBinDirectory;
+#endif
+#else
+ int i;
+#ifdef NXAGENT_SERVER
+ char *xkbbasedir = (char*)__XOS2RedirRoot(_NXGetXkbCompPath(XkbBaseDirectory));
+ char *xkbbindir = (char*)__XOS2RedirRoot(_NXGetXkbCompPath(XkbBinDirectory));
+#else
+ char *xkbbasedir = (char*)__XOS2RedirRoot(XkbBaseDirectory);
+ char *xkbbindir = (char*)__XOS2RedirRoot(XkbBinDirectory);
+#endif
+ for (i=0; i<strlen(xkbbasedir); i++)
+ if (xkbbasedir[i]=='/') xkbbasedir[i]='\\';
+ for (i=0; i<strlen(xkbbindir); i++)
+ if (xkbbindir[i]=='/') xkbbindir[i]='\\';
+#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
+ fprintf(stderr, "XkbDDXCompileKeymapByNames: Executing command [%s].\n", buf);
+ #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 defined(Lynx) && defined(__i386__) && defined(NEED_POPEN_WORKAROUND)
+ /* somehow popen/pclose is broken on LynxOS AT 2.3.0/2.4.0!
+ * the problem usually shows up with XF86Setup
+ * this hack waits at max 5 seconds after pclose() returns
+ * for the output of the xkbcomp output file.
+ * I didn't manage to get a patch in time for the 3.2 release
+ */
+ {
+ int i;
+ char name[PATH_MAX];
+#ifdef NXAGENT_SERVER
+ if (_NXGetXkbCompPath(XkbBaseDirectory)!=NULL)
+ sprintf(name,"%s/%s%s.xkm", _NXGetXkbCompPath(XkbBaseDirectory)
+ ,xkm_output_dir, keymap);
+#else
+ if (XkbBaseDirectory!=NULL)
+ sprintf(name,"%s/%s%s.xkm", XkbBaseDirectory
+ ,xkm_output_dir, keymap);
+#endif
+ else
+ sprintf(name,"%s%s.xkm", xkm_output_dir, keymap);
+ for (i = 0; i < 10; i++) {
+ if (access(name, 0) == 0) break;
+ usleep(500000);
+ }
+#ifdef DEBUG
+ if (i) ErrorF(">>>> Waited %d times for %s\n", i, name);
+#endif
+ }
+#endif
+ if (buf != NULL)
+ xfree (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)
+ xfree (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;
+}
+
+