diff --git a/include/wine/library.h b/include/wine/library.h index d22368f89b0..1f72a0fbaf0 100644 --- a/include/wine/library.h +++ b/include/wine/library.h @@ -32,6 +32,7 @@ extern const char *wine_get_config_dir(void); extern const char *wine_get_server_dir(void); extern const char *wine_get_user_name(void); +extern const char *wine_get_argv0_path(void); /* dll loading */ diff --git a/libs/wine/config.c b/libs/wine/config.c index a2e3c152f7f..e4ef9d54fdc 100644 --- a/libs/wine/config.c +++ b/libs/wine/config.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #ifdef HAVE_UNISTD_H # include @@ -40,6 +41,7 @@ static const char * const server_dir_prefix = "/server-"; /* prefix for ser static char *config_dir; static char *server_dir; static char *user_name; +static char *argv0_path; #ifdef __GNUC__ static void fatal_error( const char *err, ... ) __attribute__((noreturn,format(printf,1,2))); @@ -178,6 +180,43 @@ static void init_paths(void) sprintf( server_dir + strlen(server_dir), "%lx", (unsigned long)st.st_ino ); } +/* initialize the argv0 path */ +void init_argv0_path( const char *argv0 ) +{ + size_t size, len; + const char *p; + char *cwd; + + if (!(p = strrchr( argv0, '/' ))) + return; /* if argv0 doesn't contain a path, don't do anything */ + + len = p - argv0 + 1; + if (argv0[0] == '/') /* absolute path */ + { + argv0_path = xmalloc( len + 1 ); + memcpy( argv0_path, argv0, len ); + argv0_path[len] = 0; + return; + } + + /* relative path, make it absolute */ + for (size = 256 + len; ; size *= 2) + { + if (!(cwd = malloc( size ))) break; + if (getcwd( cwd, size - len )) + { + argv0_path = cwd; + cwd += strlen(cwd); + *cwd++ = '/'; + memcpy( cwd, argv0, len ); + cwd[len] = 0; + return; + } + free( cwd ); + if (errno != ERANGE) break; + } +} + /* return the configuration directory ($WINEPREFIX or $HOME/.wine) */ const char *wine_get_config_dir(void) { @@ -198,3 +237,9 @@ const char *wine_get_user_name(void) if (!user_name) init_paths(); return user_name; } + +/* return the path of argv[0], including a trailing slash */ +const char *wine_get_argv0_path(void) +{ + return argv0_path; +} diff --git a/libs/wine/loader.c b/libs/wine/loader.c index f2956532b78..ed2a8260cad 100644 --- a/libs/wine/loader.c +++ b/libs/wine/loader.c @@ -46,6 +46,8 @@ int __wine_main_argc = 0; char **__wine_main_argv = NULL; WCHAR **__wine_main_wargv = NULL; +extern void init_argv0_path( const char *argv0 ); /* config.c */ + #define MAX_DLLS 100 static struct @@ -63,7 +65,6 @@ static load_dll_callback_t load_dll_callback; static const char **dll_paths; static int nb_dll_paths; static int dll_path_maxlen; -static int init_done; /* build the dll load path from the WINEDLLPATH variable */ @@ -73,8 +74,6 @@ static void build_dll_path(void) int len, count = 0; char *p, *path = getenv( "WINEDLLPATH" ); - init_done = 1; - if (path) { /* count how many path elements we need */ @@ -132,8 +131,6 @@ static void *dlopen_dll( const char *name, char *error, int errorsize, char *buffer, *p; void *ret = NULL; - if (!init_done) build_dll_path(); - buffer = malloc( dll_path_maxlen + namelen + 5 ); /* store the name at the end of the buffer, followed by .so */ @@ -421,6 +418,8 @@ void wine_init( int argc, char *argv[], char *error, int error_size ) void *kernel; void (*init_func)(int, char **); + build_dll_path(); + init_argv0_path( argv[0] ); if (!dlopen_dll( "ntdll.dll", error, error_size, 0, &file_exists )) return; /* make sure kernel32 is loaded too */ if (!(kernel = dlopen_dll( "kernel32.dll", error, error_size, 0, &file_exists ))) return;