summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJon TURNEY <jon.turney@dronecode.org.uk>2012-03-05 22:16:33 +0000
committerJon TURNEY <jon.turney@dronecode.org.uk>2015-07-25 16:24:54 +0100
commitbc6a87cd082e902c955ae73dcd7c1710ce801756 (patch)
treeb064d69f919cffebb388e628851873f2c248ef57
parentb666e936e777b96776efffc74fd54b1dd2b4ab9a (diff)
Use spawnl() rather than pipe() & fork() to invoke xkbcomp
Implement System() specially on Cygwin not to use fork() and exec(), but spawnl() Use System() and a temp file rather than pipe() & fork() to invoke xkbcomp on cygwin, just as done on mingw Somewhat the counsel of despair, but sometimes Windows is being such a little bitch that the cygwin DLL just can't emulate fork() successfully, so just using spawnl() here is more robust and means I don't have to deal with end-users reporting this as a problem with the xserver Popen is not used, but must be built as it is referenced by sdksyms v2: Update to include fix to Win32TempDir() when TMP is set but TEMP isn't XXX: Really this should check TMPDIR first, as that's the canonical UNIX way to set the temporary directory? v3: Fix implicit-function-declaration of Win32TempDir() in XkbDDXCompileKeymapByNames() Add a prototype for Win32TempDir() Signed-off-by: Jon TURNEY <jon.turney@dronecode.org.uk>
-rw-r--r--include/os.h4
-rw-r--r--os/utils.c32
-rw-r--r--xkb/ddxLoad.c15
3 files changed, 44 insertions, 7 deletions
diff --git a/include/os.h b/include/os.h
index b2b96c863..3f6e389e4 100644
--- a/include/os.h
+++ b/include/os.h
@@ -350,6 +350,10 @@ extern _X_EXPORT void *
Fopen(const char *, const char *);
extern _X_EXPORT int
Fclose(void *);
+#if defined(__CYGWIN__)
+extern const char *
+Win32TempDir(void);
+#endif
#else
extern const char *
diff --git a/os/utils.c b/os/utils.c
index d09ca79fd..d2be119dd 100644
--- a/os/utils.c
+++ b/os/utils.c
@@ -1374,6 +1374,26 @@ OsAbort(void)
* as well. As it is now, xkbcomp messages don't end up in the log file.
*/
+#ifdef __CYGWIN__
+#include <process.h>
+int
+System(const char *command)
+{
+ int status;
+
+ if (!command)
+ return 1;
+
+ DebugF("System: `%s'\n", command);
+
+ /*
+ Use spawnl() rather than execl() to implement System() on cygwin to
+ avoid fork emulation overhead and brittleness
+ */
+ status = spawnl(_P_WAIT, "/bin/sh", "sh", "-c", command, (char *) NULL);
+ return status;
+}
+#else
int
System(const char *command)
{
@@ -1416,6 +1436,7 @@ System(const char *command)
return p == -1 ? -1 : status;
}
+#endif
static struct pid {
struct pid *next;
@@ -1727,6 +1748,17 @@ System(const char *cmdline)
return dwExitCode;
}
+#elif defined(__CYGWIN__)
+const char*
+Win32TempDir(void)
+{
+ if (getenv("TEMP") != NULL)
+ return getenv("TEMP");
+ else if (getenv("TMP") != NULL)
+ return getenv("TMP");
+ else
+ return "/tmp";
+}
#endif
/*
diff --git a/xkb/ddxLoad.c b/xkb/ddxLoad.c
index f71815aa8..8955d913a 100644
--- a/xkb/ddxLoad.c
+++ b/xkb/ddxLoad.c
@@ -44,6 +44,7 @@ THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include <xkbsrv.h>
#include <X11/extensions/XI.h>
#include "xkb.h"
+#include "os.h"
/*
* If XKM_OUTPUT_DIR specifies a path without a leading slash, it is
@@ -113,7 +114,7 @@ RunXkbComp(xkbcomp_buffer_callback callback, void *userdata)
const char *xkbbindir = emptystring;
const char *xkbbindirsep = emptystring;
-#ifdef WIN32
+#if defined(WIN32) || defined(__CYGWIN__)
/* 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 tmpname[PATH_MAX];
@@ -126,9 +127,9 @@ RunXkbComp(xkbcomp_buffer_callback callback, void *userdata)
OutputDirectory(xkm_output_dir, sizeof(xkm_output_dir));
-#ifdef WIN32
+#if defined(WIN32) || defined(__CYGWIN__)
strcpy(tmpname, Win32TempDir());
- strcat(tmpname, "\\xkb_XXXXXX");
+ strcat(tmpname, PATHSEPARATOR "xkb_XXXXXX");
(void) mktemp(tmpname);
#endif
@@ -167,7 +168,7 @@ RunXkbComp(xkbcomp_buffer_callback callback, void *userdata)
return NULL;
}
-#ifndef WIN32
+#if !defined(WIN32) && !defined(__CYGWIN__)
out = Popen(buf, "w");
#else
out = fopen(tmpname, "w");
@@ -177,7 +178,7 @@ RunXkbComp(xkbcomp_buffer_callback callback, void *userdata)
/* Now write to xkbcomp */
(*callback)(out, userdata);
-#ifndef WIN32
+#if !defined(WIN32) && !defined(__CYGWIN__)
if (Pclose(out) == 0)
#else
if (fclose(out) == 0 && System(buf) >= 0)
@@ -186,14 +187,14 @@ RunXkbComp(xkbcomp_buffer_callback callback, void *userdata)
if (xkbDebugFlags)
DebugF("[xkb] xkb executes: %s\n", buf);
free(buf);
-#ifdef WIN32
+#if defined(WIN32) || defined(__CYGWIN__)
unlink(tmpname);
#endif
return xnfstrdup(keymap);
}
else
LogMessage(X_ERROR, "Error compiling keymap (%s)\n", keymap);
-#ifdef WIN32
+#if defined(WIN32) || defined(__CYGWIN__)
/* remove the temporary file */
unlink(tmpname);
#endif