dmcompos/tests: Build without -DWINE_NO_LONG_TYPES.
[wine.git] / libs / wine / config.c
blob23c76fda1282063b2e4f05a6d45cdadca0be2cea
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/asm.h"
24 #ifdef __ASM_OBSOLETE
26 #include <stdio.h>
27 #include <stdarg.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <errno.h>
31 #include <limits.h>
32 #include <sys/types.h>
33 #include <sys/stat.h>
34 #ifdef HAVE_SYS_SYSCTL_H
35 # include <sys/sysctl.h>
36 #endif
37 #include <unistd.h>
38 #include <dlfcn.h>
39 #ifdef HAVE_PWD_H
40 #include <pwd.h>
41 #endif
42 #ifdef __APPLE__
43 #include <crt_externs.h>
44 #include <spawn.h>
45 #ifndef _POSIX_SPAWN_DISABLE_ASLR
46 #define _POSIX_SPAWN_DISABLE_ASLR 0x0100
47 #endif
48 #endif
50 static char *bindir;
51 static char *dlldir;
52 static char *datadir;
53 const char *build_dir;
54 static char *argv0_name;
55 static char *wineserver64;
57 #ifdef __GNUC__
58 static void fatal_error( const char *err, ... ) __attribute__((noreturn,format(printf,1,2)));
59 #endif
61 #if defined(__linux__) || defined(__FreeBSD_kernel__) || defined(__NetBSD__)
62 static const char exe_link[] = "/proc/self/exe";
63 #else
64 static const char exe_link[] = "";
65 #endif
67 /* die on a fatal error */
68 static void fatal_error( const char *err, ... )
70 va_list args;
72 va_start( args, err );
73 fprintf( stderr, "wine: " );
74 vfprintf( stderr, err, args );
75 va_end( args );
76 exit(1);
79 /* malloc wrapper */
80 static void *xmalloc( size_t size )
82 void *res;
84 if (!size) size = 1;
85 if (!(res = malloc( size ))) fatal_error( "virtual memory exhausted\n");
86 return res;
89 /* strdup wrapper */
90 static char *xstrdup( const char *str )
92 size_t len = strlen(str) + 1;
93 char *res = xmalloc( len );
94 memcpy( res, str, len );
95 return res;
98 /* build a path from the specified dir and name */
99 static char *build_path( const char *dir, const char *name )
101 size_t len = strlen(dir);
102 char *ret = xmalloc( len + strlen(name) + 2 );
104 memcpy( ret, dir, len );
105 if (len && ret[len-1] != '/') ret[len++] = '/';
106 strcpy( ret + len, name );
107 return ret;
110 /* return the directory that contains the library at run-time */
111 static char *get_runtime_libdir(void)
113 Dl_info info;
114 char *libdir;
116 if (dladdr( get_runtime_libdir, &info ) && info.dli_fname[0] == '/')
118 const char *p = strrchr( info.dli_fname, '/' );
119 unsigned int len = p - info.dli_fname;
120 if (!len) len++; /* include initial slash */
121 libdir = xmalloc( len + 1 );
122 memcpy( libdir, info.dli_fname, len );
123 libdir[len] = 0;
124 return libdir;
126 return NULL;
129 /* read a symlink and return its directory */
130 static char *symlink_dirname( const char *name )
132 char *p, *fullpath = realpath( name, NULL );
134 if (fullpath)
136 p = strrchr( fullpath, '/' );
137 if (p == fullpath) p++;
138 if (p) *p = 0;
140 return fullpath;
143 /* return the directory that contains the main exe at run-time */
144 static char *get_runtime_exedir(void)
146 #if defined(__FreeBSD__) || defined(__DragonFly__)
147 static int pathname[] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 };
148 size_t dir_size = PATH_MAX;
149 char *dir = malloc( dir_size );
150 if (dir && !sysctl( pathname, sizeof(pathname)/sizeof(pathname[0]), dir, &dir_size, NULL, 0 ))
151 return dir;
152 free( dir );
153 return NULL;
154 #else
155 if (exe_link[0]) return symlink_dirname( exe_link );
156 return NULL;
157 #endif
160 /* return the base directory from argv0 */
161 static char *get_runtime_argvdir( const char *argv0 )
163 char *p, *bindir, *cwd;
164 int len, size;
166 if (!(p = strrchr( argv0, '/' ))) return NULL;
168 len = p - argv0;
169 if (!len) len++; /* include leading slash */
171 if (argv0[0] == '/') /* absolute path */
173 bindir = xmalloc( len + 1 );
174 memcpy( bindir, argv0, len );
175 bindir[len] = 0;
177 else
179 /* relative path, make it absolute */
180 for (size = 256 + len; ; size *= 2)
182 if (!(cwd = malloc( size ))) return NULL;
183 if (getcwd( cwd, size - len ))
185 bindir = cwd;
186 cwd += strlen(cwd);
187 *cwd++ = '/';
188 memcpy( cwd, argv0, len );
189 cwd[len] = 0;
190 break;
192 free( cwd );
193 if (errno != ERANGE) return NULL;
196 return bindir;
199 /* retrieve the default dll dir */
200 const char *get_dlldir( const char **default_dlldir )
202 *default_dlldir = DLLDIR;
203 return dlldir;
206 /* check if bindir is valid by checking for wineserver */
207 static int is_valid_bindir( const char *bindir )
209 struct stat st;
210 char *path = build_path( bindir, "wineserver" );
211 int ret = (stat( path, &st ) != -1);
212 free( path );
213 return ret;
216 /* check if dlldir is valid by checking for ntdll */
217 static int is_valid_dlldir( const char *dlldir )
219 struct stat st;
220 char *path = build_path( dlldir, "ntdll.dll.so" );
221 int ret = (stat( path, &st ) != -1);
222 free( path );
223 return ret;
226 /* check if basedir is a valid build dir by checking for wineserver and ntdll */
227 /* helper for running_from_build_dir */
228 static inline int is_valid_build_dir( char *basedir, int baselen )
230 struct stat st;
232 strcpy( basedir + baselen, "/server/wineserver" );
233 if (stat( basedir, &st ) == -1) return 0; /* no wineserver found */
234 /* check for ntdll too to make sure */
235 strcpy( basedir + baselen, "/dlls/ntdll/ntdll.dll.so" );
236 if (stat( basedir, &st ) == -1) return 0; /* no ntdll found */
238 basedir[baselen] = 0;
239 return 1;
242 /* check if we are running from the build directory */
243 static char *running_from_build_dir( const char *basedir )
245 const char *p;
246 char *path;
248 /* remove last component from basedir */
249 p = basedir + strlen(basedir) - 1;
250 while (p > basedir && *p == '/') p--;
251 while (p > basedir && *p != '/') p--;
252 if (p == basedir) return NULL;
253 path = xmalloc( p - basedir + sizeof("/dlls/ntdll/ntdll.dll.so") );
254 memcpy( path, basedir, p - basedir );
256 if (!is_valid_build_dir( path, p - basedir ))
258 /* remove another component */
259 while (p > basedir && *p == '/') p--;
260 while (p > basedir && *p != '/') p--;
261 if (p == basedir || !is_valid_build_dir( path, p - basedir ))
263 free( path );
264 return NULL;
267 return path;
270 /* try to set the specified directory as bindir, or set build_dir if it's inside the build directory */
271 static int set_bindir( char *dir )
273 if (!dir) return 0;
274 if (is_valid_bindir( dir ))
276 bindir = dir;
277 dlldir = build_path( bindir, BIN_TO_DLLDIR );
279 else
281 build_dir = running_from_build_dir( dir );
282 free( dir );
284 return bindir || build_dir;
287 /* try to set the specified directory as dlldir, or set build_dir if it's inside the build directory */
288 static int set_dlldir( char *libdir )
290 char *path;
292 if (!libdir) return 0;
294 path = build_path( libdir, LIB_TO_DLLDIR );
295 if (is_valid_dlldir( path ))
297 dlldir = path;
298 bindir = build_path( libdir, LIB_TO_BINDIR );
300 else
302 build_dir = running_from_build_dir( libdir );
303 free( path );
305 free( libdir );
306 return dlldir || build_dir;
309 /* initialize the argv0 path */
310 void wine_init_argv0_path_obsolete( const char *argv0 )
312 const char *basename, *wineloader;
314 if (!(basename = strrchr( argv0, '/' ))) basename = argv0;
315 else basename++;
317 if (set_bindir( get_runtime_exedir() )) goto done;
318 if (set_dlldir( get_runtime_libdir() )) goto done;
319 if (set_bindir( get_runtime_argvdir( argv0 ))) goto done;
320 if ((wineloader = getenv( "WINELOADER" ))) set_bindir( get_runtime_argvdir( wineloader ));
322 done:
323 if (build_dir)
325 argv0_name = build_path( "loader/", basename );
326 if (sizeof(int) == sizeof(void *))
328 char *loader, *linkname = build_path( build_dir, "loader/wine64" );
329 if ((loader = symlink_dirname( linkname )))
331 wineserver64 = build_path( loader, "../server/wineserver" );
332 free( loader );
334 free( linkname );
337 else
339 if (bindir) datadir = build_path( bindir, BIN_TO_DATADIR );
340 argv0_name = xstrdup( basename );
344 static const char server_config_dir[] = "/.wine"; /* config dir relative to $HOME */
345 static const char server_root_prefix[] = "/tmp/.wine"; /* prefix for server root dir */
346 static const char server_dir_prefix[] = "/server-"; /* prefix for server dir */
348 static char *config_dir;
349 static char *server_dir;
350 static char *user_name;
352 /* check if a string ends in a given substring */
353 static inline int strendswith( const char* str, const char* end )
355 size_t len = strlen( str );
356 size_t tail = strlen( end );
357 return len >= tail && !strcmp( str + len - tail, end );
360 /* remove all trailing slashes from a path name */
361 static inline void remove_trailing_slashes( char *path )
363 int len = strlen( path );
364 while (len > 1 && path[len-1] == '/') path[--len] = 0;
367 /* die on a fatal error */
368 static void fatal_perror( const char *err, ... )
370 va_list args;
372 va_start( args, err );
373 fprintf( stderr, "wine: " );
374 vfprintf( stderr, err, args );
375 perror( " " );
376 va_end( args );
377 exit(1);
380 /* initialize the server directory value */
381 static void init_server_dir( dev_t dev, ino_t ino )
383 char *p, *root;
385 #ifdef __ANDROID__ /* there's no /tmp dir on Android */
386 root = build_path( config_dir, ".wineserver" );
387 #else
388 root = xmalloc( sizeof(server_root_prefix) + 12 );
389 sprintf( root, "%s-%u", server_root_prefix, getuid() );
390 #endif
392 server_dir = xmalloc( strlen(root) + sizeof(server_dir_prefix) + 2*sizeof(dev) + 2*sizeof(ino) + 2 );
393 strcpy( server_dir, root );
394 strcat( server_dir, server_dir_prefix );
395 p = server_dir + strlen(server_dir);
397 if (dev != (unsigned long)dev)
398 p += sprintf( p, "%lx%08lx-", (unsigned long)((unsigned long long)dev >> 32), (unsigned long)dev );
399 else
400 p += sprintf( p, "%lx-", (unsigned long)dev );
402 if (ino != (unsigned long)ino)
403 sprintf( p, "%lx%08lx", (unsigned long)((unsigned long long)ino >> 32), (unsigned long)ino );
404 else
405 sprintf( p, "%lx", (unsigned long)ino );
406 free( root );
409 /* initialize all the paths values */
410 static void init_paths(void)
412 struct stat st;
414 const char *home = getenv( "HOME" );
415 const char *user = NULL;
416 const char *prefix = getenv( "WINEPREFIX" );
417 char uid_str[32];
418 struct passwd *pwd = getpwuid( getuid() );
420 if (pwd)
422 user = pwd->pw_name;
423 if (!home) home = pwd->pw_dir;
425 if (!user)
427 sprintf( uid_str, "%lu", (unsigned long)getuid() );
428 user = uid_str;
430 user_name = xstrdup( user );
432 /* build config_dir */
434 if (prefix)
436 config_dir = xstrdup( prefix );
437 remove_trailing_slashes( config_dir );
438 if (config_dir[0] != '/')
439 fatal_error( "invalid directory %s in WINEPREFIX: not an absolute path\n", prefix );
440 if (stat( config_dir, &st ) == -1)
442 if (errno == ENOENT) return; /* will be created later on */
443 fatal_perror( "cannot open %s as specified in WINEPREFIX", config_dir );
446 else
448 if (!home) fatal_error( "could not determine your home directory\n" );
449 if (home[0] != '/') fatal_error( "your home directory %s is not an absolute path\n", home );
450 config_dir = xmalloc( strlen(home) + sizeof(server_config_dir) );
451 strcpy( config_dir, home );
452 remove_trailing_slashes( config_dir );
453 strcat( config_dir, server_config_dir );
454 if (stat( config_dir, &st ) == -1)
456 if (errno == ENOENT) return; /* will be created later on */
457 fatal_perror( "cannot open %s", config_dir );
460 if (!S_ISDIR(st.st_mode)) fatal_error( "%s is not a directory\n", config_dir );
461 if (st.st_uid != getuid()) fatal_error( "%s is not owned by you\n", config_dir );
462 init_server_dir( st.st_dev, st.st_ino );
465 /* return the configuration directory ($WINEPREFIX or $HOME/.wine) */
466 const char *wine_get_config_dir_obsolete(void)
468 if (!config_dir) init_paths();
469 return config_dir;
472 /* retrieve the wine data dir */
473 const char *wine_get_data_dir_obsolete(void)
475 return datadir;
478 /* retrieve the wine build dir (if we are running from there) */
479 const char *wine_get_build_dir_obsolete(void)
481 return build_dir;
484 /* return the full name of the server directory (the one containing the socket) */
485 const char *wine_get_server_dir_obsolete(void)
487 if (!server_dir)
489 if (!config_dir) init_paths();
490 else
492 struct stat st;
494 if (stat( config_dir, &st ) == -1)
496 if (errno != ENOENT) fatal_error( "cannot stat %s\n", config_dir );
497 return NULL; /* will have to try again once config_dir has been created */
499 init_server_dir( st.st_dev, st.st_ino );
502 return server_dir;
505 /* return the current user name */
506 const char *wine_get_user_name_obsolete(void)
508 if (!user_name) init_paths();
509 return user_name;
512 /* return the standard version string */
513 const char *wine_get_version_obsolete(void)
515 return PACKAGE_VERSION;
518 /* return the build id string */
519 const char *wine_get_build_id_obsolete(void)
521 return PACKAGE_VERSION;
524 /* exec a binary using the preloader if requested; helper for wine_exec_wine_binary */
525 static void preloader_exec( char **argv, int use_preloader )
527 if (use_preloader)
529 static const char preloader[] = "wine-preloader";
530 static const char preloader64[] = "wine64-preloader";
531 char *p, *full_name;
532 char **last_arg = argv, **new_argv;
534 if (!(p = strrchr( argv[0], '/' ))) p = argv[0];
535 else p++;
537 full_name = xmalloc( p - argv[0] + sizeof(preloader64) );
538 memcpy( full_name, argv[0], p - argv[0] );
539 if (strendswith( p, "64" ))
540 memcpy( full_name + (p - argv[0]), preloader64, sizeof(preloader64) );
541 else
542 memcpy( full_name + (p - argv[0]), preloader, sizeof(preloader) );
544 /* make a copy of argv */
545 while (*last_arg) last_arg++;
546 new_argv = xmalloc( (last_arg - argv + 2) * sizeof(*argv) );
547 memcpy( new_argv + 1, argv, (last_arg - argv + 1) * sizeof(*argv) );
548 new_argv[0] = full_name;
549 #ifdef __APPLE__
551 posix_spawnattr_t attr;
552 posix_spawnattr_init( &attr );
553 posix_spawnattr_setflags( &attr, POSIX_SPAWN_SETEXEC | _POSIX_SPAWN_DISABLE_ASLR );
554 posix_spawn( NULL, full_name, NULL, &attr, new_argv, *_NSGetEnviron() );
555 posix_spawnattr_destroy( &attr );
557 #endif
558 execv( full_name, new_argv );
559 free( new_argv );
560 free( full_name );
562 execv( argv[0], argv );
565 /* exec a wine internal binary (either the wine loader or the wine server) */
566 void wine_exec_wine_binary_obsolete( const char *name, char **argv, const char *env_var )
568 const char *path, *pos, *ptr;
569 int use_preloader;
571 if (!name) name = argv0_name; /* no name means default loader */
573 #if defined(linux) || defined(__APPLE__)
574 use_preloader = !strendswith( name, "wineserver" );
575 #else
576 use_preloader = 0;
577 #endif
579 if ((ptr = strrchr( name, '/' )))
581 /* if we are in build dir and name contains a path, try that */
582 if (build_dir)
584 if (wineserver64 && !strcmp( name, "server/wineserver" ))
585 argv[0] = xstrdup( wineserver64 );
586 else
587 argv[0] = build_path( build_dir, name );
588 preloader_exec( argv, use_preloader );
589 free( argv[0] );
591 name = ptr + 1; /* get rid of path */
594 /* first, bin directory from the current libdir or argv0 */
595 if (bindir)
597 argv[0] = build_path( bindir, name );
598 preloader_exec( argv, use_preloader );
599 free( argv[0] );
602 /* then specified environment variable */
603 if (env_var)
605 argv[0] = (char *)env_var;
606 preloader_exec( argv, use_preloader );
609 /* now search in the Unix path */
610 if ((path = getenv( "PATH" )))
612 argv[0] = xmalloc( strlen(path) + strlen(name) + 2 );
613 pos = path;
614 for (;;)
616 while (*pos == ':') pos++;
617 if (!*pos) break;
618 if (!(ptr = strchr( pos, ':' ))) ptr = pos + strlen(pos);
619 memcpy( argv[0], pos, ptr - pos );
620 strcpy( argv[0] + (ptr - pos), "/" );
621 strcat( argv[0] + (ptr - pos), name );
622 preloader_exec( argv, use_preloader );
623 pos = ptr;
625 free( argv[0] );
628 /* and finally try BINDIR */
629 argv[0] = build_path( BINDIR, name );
630 preloader_exec( argv, use_preloader );
631 free( argv[0] );
634 __ASM_OBSOLETE(wine_init_argv0_path);
635 __ASM_OBSOLETE(wine_get_build_dir);
636 __ASM_OBSOLETE(wine_get_build_id);
637 __ASM_OBSOLETE(wine_get_config_dir);
638 __ASM_OBSOLETE(wine_get_data_dir);
639 __ASM_OBSOLETE(wine_get_server_dir);
640 __ASM_OBSOLETE(wine_get_user_name);
641 __ASM_OBSOLETE(wine_get_version);
642 __ASM_OBSOLETE(wine_exec_wine_binary);
644 #endif /* __ASM_OBSOLETE */