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>2012-03-10 13:26:17 +0000
commit2457daa7959ce02c9600d545e119ec3ed7330589 (patch)
tree2a813d7e0abf8d4ae5f14d59fed3753c62e6c9e0
parentc97a74e0cef8a64ba8d3dda6147311673282d1fa (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 Signed-off-by: Jon TURNEY <jon.turney@dronecode.org.uk>
-rw-r--r--os/utils.c22
-rw-r--r--xkb/ddxList.c24
-rw-r--r--xkb/ddxLoad.c25
3 files changed, 57 insertions, 14 deletions
diff --git a/os/utils.c b/os/utils.c
index 945094c03..74b1199ca 100644
--- a/os/utils.c
+++ b/os/utils.c
@@ -1262,6 +1262,25 @@ 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)
{
@@ -1303,6 +1322,7 @@ System(const char *command)
return p == -1 ? -1 : status;
}
+#endif
static struct pid {
struct pid *next;
@@ -1312,6 +1332,7 @@ static struct pid {
OsSigHandlerPtr old_alarm = NULL; /* XXX horrible awful hack */
+#if !defined(__CYGWIN__)
pointer
Popen(const char *command, const char *type)
{
@@ -1396,6 +1417,7 @@ Popen(const char *command, const char *type)
return iop;
}
+#endif
/* fopen that drops privileges */
pointer
diff --git a/xkb/ddxList.c b/xkb/ddxList.c
index db34c8df5..0164e2159 100644
--- a/xkb/ddxList.c
+++ b/xkb/ddxList.c
@@ -58,6 +58,16 @@ extern int Win32System(const char *cmdline);
#define W32_tmplen 0
#endif
+#ifdef __CYGWIN__
+extern const char* Win32TempDir(void);
+#endif
+
+#if defined(WIN32)
+#define PATHSEPARATOR "\\"
+#else
+#define PATHSEPARATOR "/"
+#endif
+
/***====================================================================***/
static const char *componentDirs[_XkbListNumComponents] = {
@@ -127,7 +137,7 @@ char *file,*map,*tmp,*buf=NULL;
FILE *in;
Status status;
Bool haveDir;
-#ifdef WIN32
+#if defined(WIN32) || defined(__CYGWIN__)
char tmpname[PATH_MAX];
#else
int rval;
@@ -149,9 +159,9 @@ int rval;
in= NULL;
haveDir= TRUE;
-#ifdef WIN32
+#if defined(WIN32) || defined(__CYGWIN__)
strcpy(tmpname, Win32TempDir());
- strcat(tmpname, "\\xkb_XXXXXX");
+ strcat(tmpname, PATHSEPARATOR "xkb_XXXXXX");
(void) mktemp(tmpname);
#endif
if (XkbBaseDirectory!=NULL) {
@@ -200,7 +210,7 @@ int rval;
status= Success;
if (!haveDir)
{
-#ifndef WIN32
+#if !defined(WIN32) && !defined(__CYGWIN__)
in= Popen(buf,"r");
#else
if (xkbDebugFlags)
@@ -214,7 +224,7 @@ int rval;
if (!in)
{
free(buf);
-#ifdef WIN32
+#if defined(WIN32) || defined(__CYGWIN__)
unlink(tmpname);
#endif
return BadImplementation;
@@ -224,7 +234,7 @@ int rval;
buf = malloc(PATH_MAX * sizeof(char));
if (!buf) {
fclose(in);
-#ifdef WIN32
+#if defined(WIN32) || defined(__CYGWIN__)
unlink(tmpname);
#endif
return BadAlloc;
@@ -270,7 +280,7 @@ int rval;
}
status= _AddListComponent(list,what,flags,tmp,client);
}
-#ifndef WIN32
+#if !defined(WIN32) && !defined(__CYGWIN__)
if (haveDir)
fclose(in);
else if ((rval=Pclose(in))!=0) {
diff --git a/xkb/ddxLoad.c b/xkb/ddxLoad.c
index 196142318..0d88b7f34 100644
--- a/xkb/ddxLoad.c
+++ b/xkb/ddxLoad.c
@@ -144,6 +144,17 @@ Win32System(const char *cmdline)
}
#undef System
#define System(x) Win32System(x)
+#elif defined(__CYGWIN__)
+const char*
+Win32TempDir(void)
+{
+ if (getenv("TEMP") != NULL)
+ return getenv("TEMP");
+ else if (getenv("TMP") != NULL)
+ return getenv("TEMP");
+ else
+ return "/tmp";
+}
#endif
static void
@@ -186,7 +197,7 @@ XkbDDXCompileKeymapByNames( XkbDescPtr xkb,
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];
@@ -199,9 +210,9 @@ XkbDDXCompileKeymapByNames( XkbDescPtr xkb,
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
@@ -240,7 +251,7 @@ XkbDDXCompileKeymapByNames( XkbDescPtr xkb,
return FALSE;
}
-#ifndef WIN32
+#if !defined(WIN32) && !defined(__CYGWIN__)
out= Popen(buf,"w");
#else
out= fopen(tmpname, "w");
@@ -254,7 +265,7 @@ XkbDDXCompileKeymapByNames( XkbDescPtr xkb,
}
#endif
XkbWriteXKBKeymapForNames(out,names,xkb,want,need);
-#ifndef WIN32
+#if !defined(WIN32) && !defined(__CYGWIN__)
if (Pclose(out)==0)
#else
if (fclose(out)==0 && System(buf) >= 0)
@@ -266,14 +277,14 @@ XkbDDXCompileKeymapByNames( XkbDescPtr xkb,
strlcpy(nameRtrn,keymap,nameRtrnLen);
}
free(buf);
-#ifdef WIN32
+#if defined(WIN32) || defined(__CYGWIN__)
unlink(tmpname);
#endif
return TRUE;
}
else
LogMessage(X_ERROR, "Error compiling keymap (%s)\n", keymap);
-#ifdef WIN32
+#if defined(WIN32) || defined(__CYGWIN__)
/* remove the temporary file */
unlink(tmpname);
#endif