diff options
author | Jon TURNEY <jon.turney@dronecode.org.uk> | 2012-03-05 22:16:33 +0000 |
---|---|---|
committer | Jon TURNEY <jon.turney@dronecode.org.uk> | 2015-07-25 16:24:54 +0100 |
commit | bc6a87cd082e902c955ae73dcd7c1710ce801756 (patch) | |
tree | b064d69f919cffebb388e628851873f2c248ef57 | |
parent | b666e936e777b96776efffc74fd54b1dd2b4ab9a (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.h | 4 | ||||
-rw-r--r-- | os/utils.c | 32 | ||||
-rw-r--r-- | xkb/ddxLoad.c | 15 |
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 |