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