libwine: Add a helper function to read a symlink.
[wine.git] / libs / wine / config.c
blob8ebe970fafe226dbfd51b61c335c1ddcda02fea9
1 /*
2 * Configuration parameters shared between Wine server and clients
4 * Copyright 2002 Alexandre Julliard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include "config.h"
22 #include "wine/port.h"
24 #include <stdio.h>
25 #include <stdarg.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <errno.h>
29 #include <sys/stat.h>
30 #ifdef HAVE_UNISTD_H
31 # include <unistd.h>
32 #endif
33 #ifdef HAVE_PWD_H
34 #include <pwd.h>
35 #endif
36 #include "wine/library.h"
38 static const char server_config_dir[] = "/.wine"; /* config dir relative to $HOME */
39 static const char server_root_prefix[] = "/tmp/.wine"; /* prefix for server root dir */
40 static const char server_dir_prefix[] = "/server-"; /* prefix for server dir */
42 static char *bindir;
43 static char *dlldir;
44 static char *datadir;
45 static char *config_dir;
46 static char *server_dir;
47 static char *build_dir;
48 static char *user_name;
49 static char *argv0_name;
51 #ifdef __GNUC__
52 static void fatal_error( const char *err, ... ) __attribute__((noreturn,format(printf,1,2)));
53 static void fatal_perror( const char *err, ... ) __attribute__((noreturn,format(printf,1,2)));
54 #endif
56 #if defined(__linux__) || defined(__FreeBSD_kernel__ )
57 static const char exe_link[] = "/proc/self/exe";
58 #elif defined (__FreeBSD__) || defined(__DragonFly__)
59 static const char exe_link[] = "/proc/curproc/file";
60 #else
61 static const char exe_link[] = "";
62 #endif
64 /* die on a fatal error */
65 static void fatal_error( const char *err, ... )
67 va_list args;
69 va_start( args, err );
70 fprintf( stderr, "wine: " );
71 vfprintf( stderr, err, args );
72 va_end( args );
73 exit(1);
76 /* die on a fatal error */
77 static void fatal_perror( const char *err, ... )
79 va_list args;
81 va_start( args, err );
82 fprintf( stderr, "wine: " );
83 vfprintf( stderr, err, args );
84 perror( " " );
85 va_end( args );
86 exit(1);
89 /* malloc wrapper */
90 static void *xmalloc( size_t size )
92 void *res;
94 if (!size) size = 1;
95 if (!(res = malloc( size ))) fatal_error( "virtual memory exhausted\n");
96 return res;
99 /* strdup wrapper */
100 static char *xstrdup( const char *str )
102 size_t len = strlen(str) + 1;
103 char *res = xmalloc( len );
104 memcpy( res, str, len );
105 return res;
108 /* check if a string ends in a given substring */
109 static inline int strendswith( const char* str, const char* end )
111 size_t len = strlen( str );
112 size_t tail = strlen( end );
113 return len >= tail && !strcmp( str + len - tail, end );
116 /* remove all trailing slashes from a path name */
117 static inline void remove_trailing_slashes( char *path )
119 int len = strlen( path );
120 while (len > 1 && path[len-1] == '/') path[--len] = 0;
123 /* build a path from the specified dir and name */
124 static char *build_path( const char *dir, const char *name )
126 size_t len = strlen(dir);
127 char *ret = xmalloc( len + strlen(name) + 2 );
129 memcpy( ret, dir, len );
130 if (len && ret[len-1] != '/') ret[len++] = '/';
131 strcpy( ret + len, name );
132 return ret;
135 /* return the directory that contains the library at run-time */
136 static char *get_runtime_libdir(void)
138 #ifdef HAVE_DLADDR
139 Dl_info info;
140 char *libdir;
142 if (dladdr( get_runtime_libdir, &info ) && info.dli_fname[0] == '/')
144 const char *p = strrchr( info.dli_fname, '/' );
145 unsigned int len = p - info.dli_fname;
146 if (!len) len++; /* include initial slash */
147 libdir = xmalloc( len + 1 );
148 memcpy( libdir, info.dli_fname, len );
149 libdir[len] = 0;
150 return libdir;
152 #endif /* HAVE_DLADDR */
153 return NULL;
156 /* read a symlink and return its directory */
157 static char *symlink_dirname( const char *name )
159 char *p, *buffer;
160 int ret, size;
162 for (size = 256; ; size *= 2)
164 if (!(buffer = malloc( size ))) return NULL;
165 if ((ret = readlink( name, buffer, size )) == -1) break;
166 if (ret != size)
168 buffer[ret] = 0;
169 if (!(p = strrchr( buffer, '/' ))) break;
170 if (p == buffer) p++;
171 *p = 0;
172 return buffer;
174 free( buffer );
176 free( buffer );
177 return NULL;
180 /* return the directory that contains the main exe at run-time */
181 static char *get_runtime_exedir(void)
183 if (exe_link[0]) return symlink_dirname( exe_link );
184 return NULL;
187 /* return the base directory from argv0 */
188 static char *get_runtime_argvdir( const char *argv0 )
190 char *p, *bindir, *cwd;
191 int len, size;
193 if (!(p = strrchr( argv0, '/' ))) return NULL;
195 len = p - argv0;
196 if (!len) len++; /* include leading slash */
198 if (argv0[0] == '/') /* absolute path */
200 bindir = xmalloc( len + 1 );
201 memcpy( bindir, argv0, len );
202 bindir[len] = 0;
204 else
206 /* relative path, make it absolute */
207 for (size = 256 + len; ; size *= 2)
209 if (!(cwd = malloc( size ))) return NULL;
210 if (getcwd( cwd, size - len ))
212 bindir = cwd;
213 cwd += strlen(cwd);
214 *cwd++ = '/';
215 memcpy( cwd, argv0, len );
216 cwd[len] = 0;
217 break;
219 free( cwd );
220 if (errno != ERANGE) return NULL;
223 return bindir;
226 /* initialize the server directory value */
227 static void init_server_dir( dev_t dev, ino_t ino )
229 char *p, *root;
231 #ifdef __ANDROID__ /* there's no /tmp dir on Android */
232 root = build_path( config_dir, ".wineserver" );
233 #elif defined(HAVE_GETUID)
234 root = xmalloc( sizeof(server_root_prefix) + 12 );
235 sprintf( root, "%s-%u", server_root_prefix, getuid() );
236 #else
237 root = xstrdup( server_root_prefix );
238 #endif
240 server_dir = xmalloc( strlen(root) + sizeof(server_dir_prefix) + 2*sizeof(dev) + 2*sizeof(ino) + 2 );
241 strcpy( server_dir, root );
242 strcat( server_dir, server_dir_prefix );
243 p = server_dir + strlen(server_dir);
245 if (dev != (unsigned long)dev)
246 p += sprintf( p, "%lx%08lx-", (unsigned long)((unsigned long long)dev >> 32), (unsigned long)dev );
247 else
248 p += sprintf( p, "%lx-", (unsigned long)dev );
250 if (ino != (unsigned long)ino)
251 sprintf( p, "%lx%08lx", (unsigned long)((unsigned long long)ino >> 32), (unsigned long)ino );
252 else
253 sprintf( p, "%lx", (unsigned long)ino );
254 free( root );
257 /* retrieve the default dll dir */
258 const char *get_dlldir( const char **default_dlldir )
260 *default_dlldir = DLLDIR;
261 return dlldir;
264 /* initialize all the paths values */
265 static void init_paths(void)
267 struct stat st;
269 const char *home = getenv( "HOME" );
270 const char *user = NULL;
271 const char *prefix = getenv( "WINEPREFIX" );
273 #ifdef HAVE_GETPWUID
274 char uid_str[32];
275 struct passwd *pwd = getpwuid( getuid() );
277 if (pwd)
279 user = pwd->pw_name;
280 if (!home) home = pwd->pw_dir;
282 if (!user)
284 sprintf( uid_str, "%lu", (unsigned long)getuid() );
285 user = uid_str;
287 #else /* HAVE_GETPWUID */
288 if (!(user = getenv( "USER" )))
289 fatal_error( "cannot determine your user name, set the USER environment variable\n" );
290 #endif /* HAVE_GETPWUID */
291 user_name = xstrdup( user );
293 /* build config_dir */
295 if (prefix)
297 config_dir = xstrdup( prefix );
298 remove_trailing_slashes( config_dir );
299 if (config_dir[0] != '/')
300 fatal_error( "invalid directory %s in WINEPREFIX: not an absolute path\n", prefix );
301 if (stat( config_dir, &st ) == -1)
303 if (errno == ENOENT) return; /* will be created later on */
304 fatal_perror( "cannot open %s as specified in WINEPREFIX", config_dir );
307 else
309 if (!home) fatal_error( "could not determine your home directory\n" );
310 if (home[0] != '/') fatal_error( "your home directory %s is not an absolute path\n", home );
311 config_dir = xmalloc( strlen(home) + sizeof(server_config_dir) );
312 strcpy( config_dir, home );
313 remove_trailing_slashes( config_dir );
314 strcat( config_dir, server_config_dir );
315 if (stat( config_dir, &st ) == -1)
317 if (errno == ENOENT) return; /* will be created later on */
318 fatal_perror( "cannot open %s", config_dir );
321 if (!S_ISDIR(st.st_mode)) fatal_error( "%s is not a directory\n", config_dir );
322 #ifdef HAVE_GETUID
323 if (st.st_uid != getuid()) fatal_error( "%s is not owned by you\n", config_dir );
324 #endif
326 init_server_dir( st.st_dev, st.st_ino );
329 /* check if bindir is valid by checking for wineserver */
330 static int is_valid_bindir( const char *bindir )
332 struct stat st;
333 char *path = build_path( bindir, "wineserver" );
334 int ret = (stat( path, &st ) != -1);
335 free( path );
336 return ret;
339 /* check if dlldir is valid by checking for ntdll */
340 static int is_valid_dlldir( const char *dlldir )
342 struct stat st;
343 char *path = build_path( dlldir, "ntdll.dll.so" );
344 int ret = (stat( path, &st ) != -1);
345 free( path );
346 return ret;
349 /* check if basedir is a valid build dir by checking for wineserver and ntdll */
350 /* helper for running_from_build_dir */
351 static inline int is_valid_build_dir( char *basedir, int baselen )
353 struct stat st;
355 strcpy( basedir + baselen, "/server/wineserver" );
356 if (stat( basedir, &st ) == -1) return 0; /* no wineserver found */
357 /* check for ntdll too to make sure */
358 strcpy( basedir + baselen, "/dlls/ntdll/ntdll.dll.so" );
359 if (stat( basedir, &st ) == -1) return 0; /* no ntdll found */
361 basedir[baselen] = 0;
362 return 1;
365 /* check if we are running from the build directory */
366 static char *running_from_build_dir( const char *basedir )
368 const char *p;
369 char *path;
371 /* remove last component from basedir */
372 p = basedir + strlen(basedir) - 1;
373 while (p > basedir && *p == '/') p--;
374 while (p > basedir && *p != '/') p--;
375 if (p == basedir) return NULL;
376 path = xmalloc( p - basedir + sizeof("/dlls/ntdll/ntdll.dll.so") );
377 memcpy( path, basedir, p - basedir );
379 if (!is_valid_build_dir( path, p - basedir ))
381 /* remove another component */
382 while (p > basedir && *p == '/') p--;
383 while (p > basedir && *p != '/') p--;
384 if (p == basedir || !is_valid_build_dir( path, p - basedir ))
386 free( path );
387 return NULL;
390 return path;
393 /* try to set the specified directory as bindir, or set build_dir if it's inside the build directory */
394 static int set_bindir( char *dir )
396 if (!dir) return 0;
397 if (is_valid_bindir( dir ))
399 bindir = dir;
400 dlldir = build_path( bindir, BIN_TO_DLLDIR );
402 else
404 build_dir = running_from_build_dir( dir );
405 free( dir );
407 return bindir || build_dir;
410 /* try to set the specified directory as dlldir, or set build_dir if it's inside the build directory */
411 static int set_dlldir( char *libdir )
413 char *path;
415 if (!libdir) return 0;
417 path = build_path( libdir, LIB_TO_DLLDIR );
418 if (is_valid_dlldir( path ))
420 dlldir = path;
421 bindir = build_path( libdir, LIB_TO_BINDIR );
423 else
425 build_dir = running_from_build_dir( libdir );
426 free( path );
428 free( libdir );
429 return dlldir || build_dir;
432 /* initialize the argv0 path */
433 void wine_init_argv0_path( const char *argv0 )
435 const char *basename, *wineloader;
437 if (!(basename = strrchr( argv0, '/' ))) basename = argv0;
438 else basename++;
440 if (set_bindir( get_runtime_exedir() )) goto done;
441 if (set_dlldir( get_runtime_libdir() )) goto done;
442 if (set_bindir( get_runtime_argvdir( argv0 ))) goto done;
443 if ((wineloader = getenv( "WINELOADER" ))) set_bindir( get_runtime_argvdir( wineloader ));
445 done:
446 if (build_dir)
448 argv0_name = build_path( "loader/", basename );
450 else
452 if (bindir) datadir = build_path( bindir, BIN_TO_DATADIR );
453 argv0_name = xstrdup( basename );
457 /* return the configuration directory ($WINEPREFIX or $HOME/.wine) */
458 const char *wine_get_config_dir(void)
460 if (!config_dir) init_paths();
461 return config_dir;
464 /* retrieve the wine data dir */
465 const char *wine_get_data_dir(void)
467 return datadir;
470 /* retrieve the wine build dir (if we are running from there) */
471 const char *wine_get_build_dir(void)
473 return build_dir;
476 /* return the full name of the server directory (the one containing the socket) */
477 const char *wine_get_server_dir(void)
479 if (!server_dir)
481 if (!config_dir) init_paths();
482 else
484 struct stat st;
486 if (stat( config_dir, &st ) == -1)
488 if (errno != ENOENT) fatal_error( "cannot stat %s\n", config_dir );
489 return NULL; /* will have to try again once config_dir has been created */
491 init_server_dir( st.st_dev, st.st_ino );
494 return server_dir;
497 /* return the current user name */
498 const char *wine_get_user_name(void)
500 if (!user_name) init_paths();
501 return user_name;
504 /* return the standard version string */
505 const char *wine_get_version(void)
507 return PACKAGE_VERSION;
510 /* return the build id string */
511 const char *wine_get_build_id(void)
513 extern const char wine_build[];
514 return wine_build;
517 /* exec a binary using the preloader if requested; helper for wine_exec_wine_binary */
518 static void preloader_exec( char **argv, int use_preloader )
520 if (use_preloader)
522 static const char preloader[] = "wine-preloader";
523 static const char preloader64[] = "wine64-preloader";
524 char *p, *full_name;
525 char **last_arg = argv, **new_argv;
527 if (!(p = strrchr( argv[0], '/' ))) p = argv[0];
528 else p++;
530 full_name = xmalloc( p - argv[0] + sizeof(preloader64) );
531 memcpy( full_name, argv[0], p - argv[0] );
532 if (strendswith( p, "64" ))
533 memcpy( full_name + (p - argv[0]), preloader64, sizeof(preloader64) );
534 else
535 memcpy( full_name + (p - argv[0]), preloader, sizeof(preloader) );
537 /* make a copy of argv */
538 while (*last_arg) last_arg++;
539 new_argv = xmalloc( (last_arg - argv + 2) * sizeof(*argv) );
540 memcpy( new_argv + 1, argv, (last_arg - argv + 1) * sizeof(*argv) );
541 new_argv[0] = full_name;
542 execv( full_name, new_argv );
543 free( new_argv );
544 free( full_name );
546 execv( argv[0], argv );
549 /* exec a wine internal binary (either the wine loader or the wine server) */
550 void wine_exec_wine_binary( const char *name, char **argv, const char *env_var )
552 const char *path, *pos, *ptr;
553 int use_preloader;
555 if (!name) name = argv0_name; /* no name means default loader */
557 #ifdef linux
558 use_preloader = !strendswith( name, "wineserver" );
559 #else
560 use_preloader = 0;
561 #endif
563 if ((ptr = strrchr( name, '/' )))
565 /* if we are in build dir and name contains a path, try that */
566 if (build_dir)
568 argv[0] = build_path( build_dir, name );
569 preloader_exec( argv, use_preloader );
570 free( argv[0] );
572 name = ptr + 1; /* get rid of path */
575 /* first, bin directory from the current libdir or argv0 */
576 if (bindir)
578 argv[0] = build_path( bindir, name );
579 preloader_exec( argv, use_preloader );
580 free( argv[0] );
583 /* then specified environment variable */
584 if (env_var)
586 argv[0] = (char *)env_var;
587 preloader_exec( argv, use_preloader );
590 /* now search in the Unix path */
591 if ((path = getenv( "PATH" )))
593 argv[0] = xmalloc( strlen(path) + strlen(name) + 2 );
594 pos = path;
595 for (;;)
597 while (*pos == ':') pos++;
598 if (!*pos) break;
599 if (!(ptr = strchr( pos, ':' ))) ptr = pos + strlen(pos);
600 memcpy( argv[0], pos, ptr - pos );
601 strcpy( argv[0] + (ptr - pos), "/" );
602 strcat( argv[0] + (ptr - pos), name );
603 preloader_exec( argv, use_preloader );
604 pos = ptr;
606 free( argv[0] );
609 /* and finally try BINDIR */
610 argv[0] = build_path( BINDIR, name );
611 preloader_exec( argv, use_preloader );
612 free( argv[0] );