Exemple #1
0
static void
OutputDirectory(char *outdir, size_t size)
{
#ifndef WIN32
    /* Can we write an xkm and then open it too? */
    if (access(XKM_OUTPUT_DIR, W_OK | X_OK) == 0 &&
        (strlen(XKM_OUTPUT_DIR) < size)) {
        (void) strcpy(outdir, XKM_OUTPUT_DIR);
    }
    else
#else
    if (strlen(Win32TempDir()) + 1 < size) {
        (void) strcpy(outdir, Win32TempDir());
        (void) strcat(outdir, "\\");
    }
    else
#endif
    if (strlen("/tmp/") < size) {
        (void) strcpy(outdir, "/tmp/");
    }
}
Exemple #2
0
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/");
    }
}
static void
OutputDirectory(
    char* outdir,
    size_t size)
{
#ifndef WIN32
    if (getuid() == 0 && (strlen(XKM_OUTPUT_DIR) < size))
    {
	/* 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
#else
    if (strlen(Win32TempDir()) + 1 < size)
    {
	(void) strcpy(outdir, Win32TempDir());
	(void) strcat(outdir, "\\");
    } else 
#endif
    if (strlen("/tmp/") < size)
    {
	(void) strcpy (outdir, "/tmp/");
    }
}
Exemple #4
0
static 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];

    const char	*emptystring = "";
    char *xkbbasedirflag = NULL;
    const char	*xkbbindir = emptystring;
    const char	*xkbbindirsep = emptystring;

#ifdef WIN32
    /* 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];
    const char *xkmfile = tmpname;
#else
    const char *xkmfile = "-";
#endif

    snprintf(keymap, sizeof(keymap), "server-%s", display);

    OutputDirectory(xkm_output_dir, sizeof(xkm_output_dir));

#ifdef WIN32
    strcpy(tmpname, Win32TempDir());
    strcat(tmpname, "\\xkb_XXXXXX");
    (void) mktemp(tmpname);
#endif

    if (XkbBaseDirectory != NULL) {
	xkbbasedirflag = Xprintf("\"-R%s\"", XkbBaseDirectory);
    }

    if (XkbBinDirectory != NULL) {
	int ld = strlen(XkbBinDirectory);
	int lps = strlen(PATHSEPARATOR);

	xkbbindir = XkbBinDirectory;

	if ((ld >= lps) &&
	    (strcmp(xkbbindir + ld - lps, PATHSEPARATOR) != 0)) {
	    xkbbindirsep = PATHSEPARATOR;
	}
    }

    buf = Xprintf("\"%s%sxkbcomp\" -w %d %s -xkm \"%s\" "
		  "-em1 %s -emp %s -eml %s \"%s%s.xkm\"",
		  xkbbindir, xkbbindirsep,
		  ( (xkbDebugFlags < 2) ? 1 :
		    ((xkbDebugFlags > 10) ? 10 : (int)xkbDebugFlags) ),
		  xkbbasedirflag ? xkbbasedirflag : "", xkmfile,
		  PRE_ERROR_MSG, ERROR_PREFIX, POST_ERROR_MSG1,
		  xkm_output_dir, keymap);

    free(xkbbasedirflag);

    if (!buf) {
        LogMessage(X_ERROR, "XKB: Could not invoke xkbcomp: not enough memory\n");
        return FALSE;
    }
    
#ifndef WIN32
    out= Popen(buf,"w");
#else
    out= fopen(tmpname, "w");
#endif
    
    if (out!=NULL) {
#ifdef DEBUG
    if (xkbDebugFlags) {
       ErrorF("[xkb] XkbDDXCompileKeymapByNames compiling keymap:\n");
       XkbWriteXKBKeymapForNames(stderr,names,xkb,want,need);
    }
#endif
	XkbWriteXKBKeymapForNames(out,names,xkb,want,need);
#ifndef WIN32
	if (Pclose(out)==0)
#else
	if (fclose(out)==0 && System(buf) >= 0)
#endif
	{
            if (xkbDebugFlags)
                DebugF("[xkb] xkb executes: %s\n",buf);
	    if (nameRtrn) {
		strncpy(nameRtrn,keymap,nameRtrnLen);
		nameRtrn[nameRtrnLen-1]= '\0';
	    }
            if (buf != NULL)
                free(buf);
	    return TRUE;
	}
	else
	    LogMessage(X_ERROR, "Error compiling keymap (%s)\n", keymap);
#ifdef WIN32
        /* remove the temporary file */
        unlink(tmpname);
#endif
    }
    else {
#ifndef WIN32
	LogMessage(X_ERROR, "XKB: Could not invoke xkbcomp\n");
#else
	LogMessage(X_ERROR, "Could not open file %s\n", tmpname);
#endif
    }
    if (nameRtrn)
	nameRtrn[0]= '\0';
    if (buf != NULL)
        free(buf);
    return FALSE;
}
/***====================================================================***/
static Status
XkbDDXListComponent(	DeviceIntPtr 		dev,
			int			what,
			XkbSrvListInfoPtr	list,
			ClientPtr		client)
{
char 	*file,*map,*tmp,*buf=NULL;
FILE 	*in;
Status	status;
int	rval;
Bool	haveDir;
#ifdef WIN32
char	tmpname[PATH_MAX];
#endif

    if ((list->pattern[what]==NULL)||(list->pattern[what][0]=='\0'))
	return Success;
    file= list->pattern[what];
    map= strrchr(file,'(');
    if (map!=NULL) {
	char *tmp;
	map++;
	tmp= strrchr(map,')');
	if ((tmp==NULL)||(tmp[1]!='\0')) {
	    /* illegal pattern.  No error, but no match */
	    return Success;
	}
    }

    in= NULL;
    haveDir= TRUE;
#ifdef WIN32
    strcpy(tmpname, Win32TempDir());
    strcat(tmpname, "\\xkb_XXXXXX");
    (void) mktemp(tmpname);
#endif
    if (XkbBaseDirectory!=NULL) {
	if ((list->pattern[what][0]=='*')&&(list->pattern[what][1]=='\0')) {
	    if (asprintf(&buf, "%s/%s.dir", XkbBaseDirectory,
			 componentDirs[what]) == -1)
		buf = NULL;
	    else
		in = fopen(buf,"r");
	}
	if (!in) {
	    haveDir= FALSE;
	    free(buf);
	    if (asprintf
		(&buf,
		 "'%s/xkbcomp' '-R%s/%s' -w %ld -l -vlfhpR '%s'" W32_tmparg,
		 XkbBinDirectory, XkbBaseDirectory, componentDirs[what],
		 (long) ((xkbDebugFlags < 2) ? 1 :
			 ((xkbDebugFlags > 10) ? 10 : xkbDebugFlags)),
		 file W32_tmpfile
		    ) == -1)
		buf = NULL;
	}
    }
    else {
	if ((list->pattern[what][0]=='*')&&(list->pattern[what][1]=='\0')) {
	    if (asprintf(&buf, "%s.dir", componentDirs[what]) == -1)
		buf = NULL;
	    else
		in = fopen(buf,"r");
	}
	if (!in) {
	    haveDir= FALSE;
	    free(buf);
	    if (asprintf
		(&buf,
		 "xkbcomp -R%s -w %ld -l -vlfhpR '%s'" W32_tmparg,
		 componentDirs[what],
		 (long)	((xkbDebugFlags < 2) ? 1 :
			 ((xkbDebugFlags > 10) ? 10 : xkbDebugFlags)),
		 file W32_tmpfile
		    ) == -1)
		buf = NULL;
	}
    }
    status= Success;
    if (!haveDir)
    {  
#ifndef WIN32
	in= Popen(buf,"r");
#else
        if (xkbDebugFlags)
            DebugF("[xkb] xkbList executes: %s\n",buf);
	if (System(buf) < 0)
	    ErrorF("[xkb] Could not invoke keymap compiler\n");
	else
	    in= fopen(tmpname, "r");
#endif
    }
    if (!in)
    {
	free(buf);
#ifdef WIN32
	unlink(tmpname);
#endif
	return BadImplementation;
    }
    list->nFound[what]= 0;
    free(buf);
    buf = malloc(PATH_MAX * sizeof(char));
    if (!buf)
        return BadAlloc;
    while ((status==Success)&&((tmp=fgets(buf,PATH_MAX,in))!=NULL)) {
	unsigned flags;
	register unsigned int i;
	if (*tmp=='#') /* comment, skip it */
	    continue;
	if (!strncmp(tmp, "Warning:", 8) || !strncmp(tmp, "        ", 8))
	    /* skip warnings too */
	    continue;
	flags= 0;
	/* each line in the listing is supposed to start with two */
	/* groups of eight characters, which specify the general  */
	/* flags and the flags that are specific to the component */
	/* if they're missing, fail with BadImplementation	  */
	for (i=0;(i<8)&&(status==Success);i++) { /* read the general flags */
	   if (isalpha(*tmp))	flags|= (1L<<i);
	   else if (*tmp!='-')	status= BadImplementation;
	   tmp++;
	}
	if (status != Success)  break;
	if (!isspace(*tmp)) {
	     status= BadImplementation;
	     break;
	}
	else tmp++;
	for (i=0;(i<8)&&(status==Success);i++) { /* read the component flags */
	   if (isalpha(*tmp))	flags|= (1L<<(i+8));
	   else if (*tmp!='-')	status= BadImplementation;
	   tmp++;
	}
	if (status != Success)  break;
	if (isspace(*tmp)) {
	    while (isspace(*tmp)) {
		tmp++;
	    }
	}
	else {
	    status= BadImplementation;
	    break;
	}
	status= _AddListComponent(list,what,flags,tmp,client);
    }
#ifndef WIN32
    if (haveDir)
	fclose(in);
    else if ((rval=Pclose(in))!=0) {
	if (xkbDebugFlags)
	    ErrorF("[xkb] xkbcomp returned exit code %d\n",rval);
    }
#else
    fclose(in);
    unlink(tmpname);
#endif
    free(buf);
    return status;
}
Exemple #6
0
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 = _NXGetXkbBasePath(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(_NXGetXkbBasePath(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 = _NXGetXkbBasePath(XkbBaseDirectory);
        char *xkbbindir = _NXGetXkbCompPath(XkbBinDirectory);
#else
        char *xkbbasedir = XkbBaseDirectory;
        char *xkbbindir = XkbBinDirectory;
#endif
#else
        int i;
#ifdef NXAGENT_SERVER
        char *xkbbasedir = (char*)__XOS2RedirRoot(_NXGetXkbBasePath(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
    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 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;
}
Exemple #7
0
/**
 * Start xkbcomp, let the callback write into xkbcomp's stdin. When done,
 * return a strdup'd copy of the file name we've written to.
 */
static char *
RunXkbComp(xkbcomp_buffer_callback callback, void *userdata)
{
    FILE *out;
    char *buf = NULL, keymap[PATH_MAX], xkm_output_dir[PATH_MAX];

    const char *emptystring = "";
    char *xkbbasedirflag = NULL;
    const char *xkbbindir = emptystring;
    const char *xkbbindirsep = emptystring;

#ifdef WIN32
    /* 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];
    const char *xkmfile = tmpname;
#else
    const char *xkmfile = "-";
#endif

    snprintf(keymap, sizeof(keymap), "server-%s", display);

    OutputDirectory(xkm_output_dir, sizeof(xkm_output_dir));

#ifdef WIN32
    strcpy(tmpname, Win32TempDir());
    strcat(tmpname, "\\xkb_XXXXXX");
    (void) mktemp(tmpname);
#endif

    if (XkbBaseDirectory != NULL) {
        if (asprintf(&xkbbasedirflag, "\"-R%s\"", XkbBaseDirectory) == -1)
            xkbbasedirflag = NULL;
    }

    if (XkbBinDirectory != NULL) {
        int ld = strlen(XkbBinDirectory);
        int lps = strlen(PATHSEPARATOR);

        xkbbindir = XkbBinDirectory;

        if ((ld >= lps) && (strcmp(xkbbindir + ld - lps, PATHSEPARATOR) != 0)) {
            xkbbindirsep = PATHSEPARATOR;
        }
    }

    if (asprintf(&buf,
                 "\"%s%sxkbcomp\" -w %d %s -xkm \"%s\" "
                 "-em1 %s -emp %s -eml %s \"%s%s.xkm\"",
                 xkbbindir, xkbbindirsep,
                 ((xkbDebugFlags < 2) ? 1 :
                  ((xkbDebugFlags > 10) ? 10 : (int) xkbDebugFlags)),
                 xkbbasedirflag ? xkbbasedirflag : "", xkmfile,
                 PRE_ERROR_MSG, ERROR_PREFIX, POST_ERROR_MSG1,
                 xkm_output_dir, keymap) == -1)
        buf = NULL;

    free(xkbbasedirflag);

    if (!buf) {
        LogMessage(X_ERROR,
                   "XKB: Could not invoke xkbcomp: not enough memory\n");
        return NULL;
    }

#ifndef WIN32
    out = Popen(buf, "w");
#else
    out = fopen(tmpname, "w");
#endif

    if (out != NULL) {
        /* Now write to xkbcomp */
        (*callback)(out, userdata);

#ifndef WIN32
        if (Pclose(out) == 0)
#else
        if (fclose(out) == 0 && System(buf) >= 0)
#endif
        {
            if (xkbDebugFlags)
                DebugF("[xkb] xkb executes: %s\n", buf);
            free(buf);
#ifdef WIN32
            unlink(tmpname);
#endif
            return xnfstrdup(keymap);
        }
        else {
            LogMessage(X_ERROR, "Error compiling keymap (%s) executing '%s'\n",
                       keymap, buf);
        }
#ifdef WIN32
        /* remove the temporary file */
        unlink(tmpname);
#endif
    }
    else {
#ifndef WIN32
        LogMessage(X_ERROR, "XKB: Could not invoke xkbcomp\n");
#else
        LogMessage(X_ERROR, "Could not open file %s\n", tmpname);
#endif
    }
    free(buf);
    return NULL;
}
static 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
    if (XkbBaseDirectory!=NULL) {
#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
        char *xkbbasedir = XkbBaseDirectory;
        char *xkbbindir = XkbBinDirectory;
        
	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);
    }
    
#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,xkb,want,need);
    }
#endif
	XkbWriteXKBKeymapForNames(out,names,xkb,want,need);
#ifndef WIN32
	if (Pclose(out)==0)
#else
	if (fclose(out)==0 && System(buf) >= 0)
#endif
	{
            if (xkbDebugFlags)
                DebugF("xkb executes: %s\n",buf);
	    if (nameRtrn) {
		strncpy(nameRtrn,keymap,nameRtrnLen);
		nameRtrn[nameRtrnLen-1]= '\0';
	    }
            if (buf != NULL)
                xfree (buf);
	    return True;
	}
	else
	    LogMessage(X_ERROR, "Error compiling keymap (%s)\n", keymap);
#ifdef WIN32
        /* remove the temporary file */
        unlink(tmpname);
#endif
    }
    else {
#ifndef WIN32
	LogMessage(X_ERROR, "XKB: Could not invoke xkbcomp\n");
#else
	LogMessage(X_ERROR, "Could not open file %s\n", tmpname);
#endif
    }
    if (nameRtrn)
	nameRtrn[0]= '\0';
    if (buf != NULL)
        xfree (buf);
    return False;
}