Hello, I found out that there are several places inside wine's C code that use the BINDIR macro. This is not good and leads to strange behavior when I try to run wine before properly installing it in /usr/local (yes, I set up PATH and LD_LIBRARY_PATH to prefer my temporary directories first). BINDIR is used in: scheduler/client.c: execl( BINDIR "/wineserver", "wineserver", NULL ); scheduler/process.c: argv[0] = BINDIR "/wine" windows/x11drv/clipboard.c: execl( BINDIR "/wineclipsrv", "wineclipsrv", Instead, I suggest detecting the BINDIR during the initialization of wine. Using argv[0] of wine's main it is possible to figure out where wine executable came from. I have written a short code that detects the directory of an executable, based on its argv[0] value. Since I am not an expert in wine, I thought it was not a good idea to integrate into wine myself. Michael
#include <sys/stat.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <assert.h> /* Find full path to the given executable. * Assuming that input executable name does not contain a '/' and assuming * that $PATH is to be used for its search. * * exe_name: the name of the executable read from argv[0] * return: heap-allocated full path. */ static char *get_fullpath_from_path(const char*exe_name) { const char *path= getenv("PATH"); const char *begin, *end; unsigned size; char *fullpath; struct stat stat_buf; assert(path != NULL); /* $PATH *should*i be defined here */ /* allocate enough memory */ fullpath= malloc( strlen(path) + 1 + strlen(exe_name) + 1 ); assert(fullpath != NULL); /* I don't like strtok, so instead it is all done by hand */ for (begin= path ; begin ; begin= end) { end= strchr(begin, ':'); /* find the last '\0' character instead of NULL */ if (end == NULL) { size= strlen(begin); } else { size= end-begin; end++; } memcpy(fullpath, begin, size); fullpath[size]='/'; strcpy(fullpath + size + 1, exe_name); /* Here, fullpath contains a potential full path to the executable: * Test it. */ if (stat(fullpath,&stat_buf) == 0 && S_ISREG(stat_buf.st_mode) ) { /* FIXME: This check may give executables that we have no * permissions to execute. */ if ( (stat_buf.st_mode & S_IXUSR) == S_IXUSR) return fullpath; } } abort(); /* The executable must be somewhere */ } /* Find the full path where the given executable is in. * Assuming that $PATH is not to be used for its search. * * exe_name: the name of the executable read from argv[0] * return: heap-allocated full path. */ static char *get_fullpath_from_name(const char*exe_name) { char *fullpath= NULL; char *cwd; int size; if (exe_name[0] == '/') { fullpath= strdup(exe_name); } else { /* Get rid of the annoying ./ prefix */ if (exe_name[0] == '.' && exe_name[1] == '/') exe_name += 2; /* get the current directory - without relying on PATH_MAX */ size= 1024; cwd= malloc(size); assert(cwd!=NULL); while(getcwd(cwd, size-1) == NULL) { size *=2; cwd= realloc(cwd, size); assert(cwd!=NULL); } /* construct the full path to the executable using cwd */ fullpath = malloc( strlen(cwd) + 1 + strlen(exe_name) + 1); assert(fullpath != NULL); sprintf(fullpath, "%s/%s", cwd, exe_name); free(cwd); } return fullpath; } /* Find the full path to the directory where the given executable is in. * The executable is given in the the same format as used by argv[0] * * exe_name: the name of the executable read from argv[0] * return: heap-allocated full path to a '/' terminated directory. */ char *get_bindir(const char* exe_name) { char *bindir; char *tmp; if (strrchr(exe_name, '/' ) == NULL) { tmp= get_fullpath_from_path(exe_name); bindir= get_fullpath_from_name(tmp); free(tmp); } else { bindir= get_fullpath_from_name(exe_name); } /* strip the name of the executable from the full path */ tmp= strrchr(bindir, '/'); ++tmp; *tmp= '\0'; return bindir; } int main(int argc, char* argv[]) { char *bindir=get_bindir(argv[0]); printf("bindir=%s\n", bindir); free(bindir); return 0; }