VirtualBox

source: vbox/trunk/src/VBox/Additions/WINNT/Graphics/Wine/libWine/config.c@ 33085

Last change on this file since 33085 was 23571, checked in by vboxsync, 15 years ago

crOpenGL: update to wine 1.1.30

  • Property svn:eol-style set to native
File size: 15.3 KB
Line 
1/*
2 * Configuration parameters shared between Wine server and clients
3 *
4 * Copyright 2002 Alexandre Julliard
5 *
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.
10 *
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.
15 *
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
19 */
20
21/*
22 * Sun LGPL Disclaimer: For the avoidance of doubt, except that if any license choice
23 * other than GPL or LGPL is available it will apply instead, Sun elects to use only
24 * the Lesser General Public License version 2.1 (LGPLv2) at this time for any software where
25 * a choice of LGPL license versions is made available with the language indicating
26 * that LGPLv2 or any later version may be used, or where a choice of which version
27 * of the LGPL is applied is otherwise unspecified.
28 */
29
30#include "config.h"
31#include "wine/port.h"
32
33#include <stdio.h>
34#include <stdarg.h>
35#include <stdlib.h>
36#include <string.h>
37#include <errno.h>
38#include <sys/stat.h>
39#ifdef HAVE_UNISTD_H
40# include <unistd.h>
41#endif
42#ifdef HAVE_PWD_H
43#include <pwd.h>
44#endif
45#include "wine/library.h"
46
47static const char server_config_dir[] = "/.wine"; /* config dir relative to $HOME */
48static const char server_root_prefix[] = "/tmp/.wine-"; /* prefix for server root dir */
49static const char server_dir_prefix[] = "/server-"; /* prefix for server dir */
50
51static char *bindir;
52static char *dlldir;
53static char *datadir;
54static char *config_dir;
55static char *server_dir;
56static char *build_dir;
57static char *user_name;
58static char *argv0_name;
59
60#ifdef __GNUC__
61static void fatal_error( const char *err, ... ) __attribute__((noreturn,format(printf,1,2)));
62static void fatal_perror( const char *err, ... ) __attribute__((noreturn,format(printf,1,2)));
63#endif
64
65/* die on a fatal error */
66static void fatal_error( const char *err, ... )
67{
68 va_list args;
69
70 va_start( args, err );
71 fprintf( stderr, "wine: " );
72 vfprintf( stderr, err, args );
73 va_end( args );
74 exit(1);
75}
76
77/* die on a fatal error */
78static void fatal_perror( const char *err, ... )
79{
80 va_list args;
81
82 va_start( args, err );
83 fprintf( stderr, "wine: " );
84 vfprintf( stderr, err, args );
85 perror( " " );
86 va_end( args );
87 exit(1);
88}
89
90/* malloc wrapper */
91static void *xmalloc( size_t size )
92{
93 void *res;
94
95 if (!size) size = 1;
96 if (!(res = malloc( size ))) fatal_error( "virtual memory exhausted\n");
97 return res;
98}
99
100/* strdup wrapper */
101static char *xstrdup( const char *str )
102{
103 size_t len = strlen(str) + 1;
104 char *res = xmalloc( len );
105 memcpy( res, str, len );
106 return res;
107}
108
109/* remove all trailing slashes from a path name */
110static inline void remove_trailing_slashes( char *path )
111{
112 int len = strlen( path );
113 while (len > 1 && path[len-1] == '/') path[--len] = 0;
114}
115
116/* build a path from the specified dir and name */
117static char *build_path( const char *dir, const char *name )
118{
119 size_t len = strlen(dir);
120 char *ret = xmalloc( len + strlen(name) + 2 );
121
122 memcpy( ret, dir, len );
123 if (len && ret[len-1] != '/') ret[len++] = '/';
124 strcpy( ret + len, name );
125 return ret;
126}
127
128/* return the directory that contains the library at run-time */
129static char *get_runtime_libdir(void)
130{
131#ifdef HAVE_DLADDR
132 Dl_info info;
133 char *libdir;
134
135 if (dladdr( get_runtime_libdir, &info ) && info.dli_fname[0] == '/')
136 {
137 const char *p = strrchr( info.dli_fname, '/' );
138 unsigned int len = p - info.dli_fname;
139 if (!len) len++; /* include initial slash */
140 libdir = xmalloc( len + 1 );
141 memcpy( libdir, info.dli_fname, len );
142 libdir[len] = 0;
143 return libdir;
144 }
145#endif /* HAVE_DLADDR */
146 return NULL;
147}
148
149/* return the directory that contains the main exe at run-time */
150static char *get_runtime_bindir( const char *argv0 )
151{
152 char *p, *bindir, *cwd;
153 size_t len, size;
154
155#ifdef linux
156 for (size = 256; ; size *= 2)
157 {
158 int ret;
159 if (!(bindir = malloc( size ))) break;
160 if ((ret = readlink( "/proc/self/exe", bindir, size )) == -1) break;
161 if (ret != size)
162 {
163 if (!(p = memrchr( bindir, '/', ret ))) break;
164 if (p == bindir) p++;
165 *p = 0;
166 return bindir;
167 }
168 free( bindir );
169 }
170 free( bindir );
171#endif
172
173 if (!(p = strrchr( argv0, '/' ))) return NULL;
174
175 len = p - argv0;
176 if (!len) len++; /* include leading slash */
177
178 if (argv0[0] == '/') /* absolute path */
179 {
180 bindir = xmalloc( len + 1 );
181 memcpy( bindir, argv0, len );
182 bindir[len] = 0;
183 }
184 else
185 {
186 /* relative path, make it absolute */
187 for (size = 256 + len; ; size *= 2)
188 {
189 if (!(cwd = malloc( size ))) return NULL;
190 if (getcwd( cwd, size - len ))
191 {
192 bindir = cwd;
193 cwd += strlen(cwd);
194 *cwd++ = '/';
195 memcpy( cwd, argv0, len );
196 cwd[len] = 0;
197 break;
198 }
199 free( cwd );
200 if (errno != ERANGE) return NULL;
201 }
202 }
203 return bindir;
204}
205
206/* initialize the server directory value */
207static void init_server_dir( dev_t dev, ino_t ino )
208{
209 char *p;
210#ifdef HAVE_GETUID
211 const unsigned int uid = getuid();
212#else
213 const unsigned int uid = 0;
214#endif
215
216 server_dir = xmalloc( sizeof(server_root_prefix) + 32 + sizeof(server_dir_prefix) +
217 2*sizeof(dev) + 2*sizeof(ino) );
218 sprintf( server_dir, "%s%u%s", server_root_prefix, uid, server_dir_prefix );
219 p = server_dir + strlen(server_dir);
220
221 if (sizeof(dev) > sizeof(unsigned long) && dev > ~0UL)
222 p += sprintf( p, "%lx%08lx-", (unsigned long)((unsigned long long)dev >> 32), (unsigned long)dev );
223 else
224 p += sprintf( p, "%lx-", (unsigned long)dev );
225
226 if (sizeof(ino) > sizeof(unsigned long) && ino > ~0UL)
227 sprintf( p, "%lx%08lx", (unsigned long)((unsigned long long)ino >> 32), (unsigned long)ino );
228 else
229 sprintf( p, "%lx", (unsigned long)ino );
230}
231
232/* retrieve the default dll dir */
233const char *get_dlldir( const char **default_dlldir )
234{
235 *default_dlldir = DLLDIR;
236 return dlldir;
237}
238
239/* initialize all the paths values */
240static void init_paths(void)
241{
242 struct stat st;
243
244 const char *home = getenv( "HOME" );
245 const char *user = NULL;
246 const char *prefix = getenv( "WINEPREFIX" );
247
248#ifdef HAVE_GETPWUID
249 char uid_str[32];
250 struct passwd *pwd = getpwuid( getuid() );
251
252 if (pwd)
253 {
254 user = pwd->pw_name;
255 if (!home) home = pwd->pw_dir;
256 }
257 if (!user)
258 {
259 sprintf( uid_str, "%lu", (unsigned long)getuid() );
260 user = uid_str;
261 }
262#else /* HAVE_GETPWUID */
263 if (!(user = getenv( "USER" )))
264 fatal_error( "cannot determine your user name, set the USER environment variable\n" );
265#endif /* HAVE_GETPWUID */
266 user_name = xstrdup( user );
267
268 /* build config_dir */
269
270 if (prefix)
271 {
272 config_dir = xstrdup( prefix );
273 remove_trailing_slashes( config_dir );
274 if (config_dir[0] != '/')
275 fatal_error( "invalid directory %s in WINEPREFIX: not an absolute path\n", prefix );
276 if (stat( config_dir, &st ) == -1)
277 {
278 if (errno == ENOENT) return; /* will be created later on */
279 fatal_perror( "cannot open %s as specified in WINEPREFIX", config_dir );
280 }
281 }
282 else
283 {
284 if (!home) fatal_error( "could not determine your home directory\n" );
285 if (home[0] != '/') fatal_error( "your home directory %s is not an absolute path\n", home );
286 config_dir = xmalloc( strlen(home) + sizeof(server_config_dir) );
287 strcpy( config_dir, home );
288 remove_trailing_slashes( config_dir );
289 strcat( config_dir, server_config_dir );
290 if (stat( config_dir, &st ) == -1)
291 {
292 if (errno == ENOENT) return; /* will be created later on */
293 fatal_perror( "cannot open %s", config_dir );
294 }
295 }
296 if (!S_ISDIR(st.st_mode)) fatal_error( "%s is not a directory\n", config_dir );
297#ifdef HAVE_GETUID
298 if (st.st_uid != getuid()) fatal_error( "%s is not owned by you\n", config_dir );
299#endif
300
301 init_server_dir( st.st_dev, st.st_ino );
302}
303
304/* check if bindir is valid by checking for wineserver */
305static int is_valid_bindir( const char *bindir )
306{
307 struct stat st;
308 char *path = build_path( bindir, "wineserver" );
309 int ret = (stat( path, &st ) != -1);
310 free( path );
311 return ret;
312}
313
314/* check if basedir is a valid build dir by checking for wineserver and ntdll */
315/* helper for running_from_build_dir */
316static inline int is_valid_build_dir( char *basedir, int baselen )
317{
318 struct stat st;
319
320 strcpy( basedir + baselen, "/server/wineserver" );
321 if (stat( basedir, &st ) == -1) return 0; /* no wineserver found */
322 /* check for ntdll too to make sure */
323 strcpy( basedir + baselen, "/dlls/ntdll/ntdll.dll.so" );
324 if (stat( basedir, &st ) == -1) return 0; /* no ntdll found */
325
326 basedir[baselen] = 0;
327 return 1;
328}
329
330/* check if we are running from the build directory */
331static char *running_from_build_dir( const char *basedir )
332{
333 const char *p;
334 char *path;
335
336 /* remove last component from basedir */
337 p = basedir + strlen(basedir) - 1;
338 while (p > basedir && *p == '/') p--;
339 while (p > basedir && *p != '/') p--;
340 if (p == basedir) return NULL;
341 path = xmalloc( p - basedir + sizeof("/dlls/ntdll/ntdll.dll.so") );
342 memcpy( path, basedir, p - basedir );
343
344 if (!is_valid_build_dir( path, p - basedir ))
345 {
346 /* remove another component */
347 while (p > basedir && *p == '/') p--;
348 while (p > basedir && *p != '/') p--;
349 if (p == basedir || !is_valid_build_dir( path, p - basedir ))
350 {
351 free( path );
352 return NULL;
353 }
354 }
355 return path;
356}
357
358/* initialize the argv0 path */
359void wine_init_argv0_path( const char *argv0 )
360{
361 const char *basename;
362 char *libdir;
363
364 if (!(basename = strrchr( argv0, '/' ))) basename = argv0;
365 else basename++;
366
367 bindir = get_runtime_bindir( argv0 );
368 libdir = get_runtime_libdir();
369
370 if (bindir && !is_valid_bindir( bindir ))
371 {
372 build_dir = running_from_build_dir( bindir );
373 free( bindir );
374 bindir = NULL;
375 }
376 if (libdir && !bindir && !build_dir)
377 {
378 build_dir = running_from_build_dir( libdir );
379 if (!build_dir) bindir = build_path( libdir, LIB_TO_BINDIR );
380 }
381
382 if (build_dir)
383 {
384 argv0_name = build_path( "loader/", basename );
385 }
386 else
387 {
388 if (libdir) dlldir = build_path( libdir, LIB_TO_DLLDIR );
389 else if (bindir) dlldir = build_path( bindir, BIN_TO_DLLDIR );
390
391 if (bindir) datadir = build_path( bindir, BIN_TO_DATADIR );
392 argv0_name = xstrdup( basename );
393 }
394 free( libdir );
395}
396
397/* return the configuration directory ($WINEPREFIX or $HOME/.wine) */
398const char *wine_get_config_dir(void)
399{
400 if (!config_dir) init_paths();
401 return config_dir;
402}
403
404/* retrieve the wine data dir */
405const char *wine_get_data_dir(void)
406{
407 return datadir;
408}
409
410/* retrieve the wine build dir (if we are running from there) */
411const char *wine_get_build_dir(void)
412{
413 return build_dir;
414}
415
416/* return the full name of the server directory (the one containing the socket) */
417const char *wine_get_server_dir(void)
418{
419 if (!server_dir)
420 {
421 if (!config_dir) init_paths();
422 else
423 {
424 struct stat st;
425
426 if (stat( config_dir, &st ) == -1)
427 {
428 if (errno != ENOENT) fatal_error( "cannot stat %s\n", config_dir );
429 return NULL; /* will have to try again once config_dir has been created */
430 }
431 init_server_dir( st.st_dev, st.st_ino );
432 }
433 }
434 return server_dir;
435}
436
437/* return the current user name */
438const char *wine_get_user_name(void)
439{
440 if (!user_name) init_paths();
441 return user_name;
442}
443
444/* return the standard version string */
445const char *wine_get_version(void)
446{
447 return PACKAGE_VERSION;
448}
449
450/* return the build id string */
451const char *wine_get_build_id(void)
452{
453 extern const char wine_build[];
454 return wine_build;
455}
456
457/* exec a binary using the preloader if requested; helper for wine_exec_wine_binary */
458static void preloader_exec( char **argv, int use_preloader )
459{
460#if defined(linux) && defined(__i386__)
461 if (use_preloader)
462 {
463 static const char preloader[] = "wine-preloader";
464 char *p, *full_name;
465 char **last_arg = argv, **new_argv;
466
467 if (!(p = strrchr( argv[0], '/' ))) p = argv[0];
468 else p++;
469
470 full_name = xmalloc( p - argv[0] + sizeof(preloader) );
471 memcpy( full_name, argv[0], p - argv[0] );
472 memcpy( full_name + (p - argv[0]), preloader, sizeof(preloader) );
473
474 /* make a copy of argv */
475 while (*last_arg) last_arg++;
476 new_argv = xmalloc( (last_arg - argv + 2) * sizeof(*argv) );
477 memcpy( new_argv + 1, argv, (last_arg - argv + 1) * sizeof(*argv) );
478 new_argv[0] = full_name;
479 execv( full_name, new_argv );
480 free( new_argv );
481 free( full_name );
482 return;
483 }
484#endif
485 execv( argv[0], argv );
486}
487
488/* exec a wine internal binary (either the wine loader or the wine server) */
489void wine_exec_wine_binary( const char *name, char **argv, const char *env_var )
490{
491 const char *path, *pos, *ptr;
492 int use_preloader = 0;
493
494 if (!name) /* no name means default loader */
495 {
496 name = argv0_name;
497 use_preloader = 1;
498 }
499
500 if ((ptr = strrchr( name, '/' )))
501 {
502 /* if we are in build dir and name contains a path, try that */
503 if (build_dir)
504 {
505 argv[0] = build_path( build_dir, name );
506 preloader_exec( argv, use_preloader );
507 free( argv[0] );
508 }
509 name = ptr + 1; /* get rid of path */
510 }
511
512 /* first, bin directory from the current libdir or argv0 */
513 if (bindir)
514 {
515 argv[0] = build_path( bindir, name );
516 preloader_exec( argv, use_preloader );
517 free( argv[0] );
518 }
519
520 /* then specified environment variable */
521 if (env_var)
522 {
523 argv[0] = (char *)env_var;
524 preloader_exec( argv, use_preloader );
525 }
526
527 /* now search in the Unix path */
528 if ((path = getenv( "PATH" )))
529 {
530 argv[0] = xmalloc( strlen(path) + strlen(name) + 2 );
531 pos = path;
532 for (;;)
533 {
534 while (*pos == ':') pos++;
535 if (!*pos) break;
536 if (!(ptr = strchr( pos, ':' ))) ptr = pos + strlen(pos);
537 memcpy( argv[0], pos, ptr - pos );
538 strcpy( argv[0] + (ptr - pos), "/" );
539 strcat( argv[0] + (ptr - pos), name );
540 preloader_exec( argv, use_preloader );
541 pos = ptr;
542 }
543 free( argv[0] );
544 }
545
546 /* and finally try BINDIR */
547 argv[0] = build_path( BINDIR, name );
548 preloader_exec( argv, use_preloader );
549 free( argv[0] );
550}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette