Assorted spelling fixes.
[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 /* remove all trailing slashes from a path name */
101 inline static void remove_trailing_slashes( char *path )
102 {
103     int len = strlen( path );
104     while (len > 1 && path[len-1] == '/') path[--len] = 0;
105 }
106
107 /* build a path from the specified dir and name */
108 static char *build_path( const char *dir, const char *name )
109 {
110     size_t len = strlen(dir);
111     char *ret = xmalloc( len + strlen(name) + 2 );
112
113     memcpy( ret, dir, len );
114     if (len && ret[len-1] != '/') ret[len++] = '/';
115     strcpy( ret + len, name );
116     return ret;
117 }
118
119 /* return the directory that contains the library at run-time */
120 static char *get_runtime_libdir(void)
121 {
122 #ifdef HAVE_DLADDR
123     Dl_info info;
124     char *libdir;
125
126     if (dladdr( get_runtime_libdir, &info ) && info.dli_fname[0] == '/')
127     {
128         const char *p = strrchr( info.dli_fname, '/' );
129         unsigned int len = p - info.dli_fname;
130         if (!len) len++;  /* include initial slash */
131         libdir = xmalloc( len + 1 );
132         memcpy( libdir, info.dli_fname, len );
133         libdir[len] = 0;
134         return libdir;
135     }
136 #endif /* HAVE_DLADDR */
137     return NULL;
138 }
139
140 /* initialize the server directory value */
141 static void init_server_dir( dev_t dev, ino_t ino )
142 {
143     char *p;
144 #ifdef HAVE_GETUID
145     const unsigned int uid = getuid();
146 #else
147     const unsigned int uid = 0;
148 #endif
149
150     server_dir = xmalloc( sizeof(server_root_prefix) + 32 + sizeof(server_dir_prefix) +
151                           2*sizeof(dev) + 2*sizeof(ino) );
152     sprintf( server_dir, "%s%u%s", server_root_prefix, uid, server_dir_prefix );
153     p = server_dir + strlen(server_dir);
154
155     if (sizeof(dev) > sizeof(unsigned long) && dev > ~0UL)
156         p += sprintf( p, "%lx%08lx-", (unsigned long)((unsigned long long)dev >> 32), (unsigned long)dev );
157     else
158         p += sprintf( p, "%lx-", (unsigned long)dev );
159
160     if (sizeof(ino) > sizeof(unsigned long) && ino > ~0UL)
161         sprintf( p, "%lx%08lx", (unsigned long)((unsigned long long)ino >> 32), (unsigned long)ino );
162     else
163         sprintf( p, "%lx", (unsigned long)ino );
164 }
165
166 /* retrieve the default dll dir */
167 const char *get_dlldir( const char **default_dlldir )
168 {
169     *default_dlldir = DLLDIR;
170     return dlldir;
171 }
172
173 /* initialize all the paths values */
174 static void init_paths(void)
175 {
176     struct stat st;
177
178     const char *home = getenv( "HOME" );
179     const char *user = NULL;
180     const char *prefix = getenv( "WINEPREFIX" );
181
182 #ifdef HAVE_GETPWUID
183     char uid_str[32];
184     struct passwd *pwd = getpwuid( getuid() );
185
186     if (pwd)
187     {
188         user = pwd->pw_name;
189         if (!home) home = pwd->pw_dir;
190     }
191     if (!user)
192     {
193         sprintf( uid_str, "%lu", (unsigned long)getuid() );
194         user = uid_str;
195     }
196 #else  /* HAVE_GETPWUID */
197     if (!(user = getenv( "USER" )))
198         fatal_error( "cannot determine your user name, set the USER environment variable\n" );
199 #endif  /* HAVE_GETPWUID */
200     user_name = xstrdup( user );
201
202     /* build config_dir */
203
204     if (prefix)
205     {
206         if (!(config_dir = strdup( prefix ))) fatal_error( "virtual memory exhausted\n");
207         remove_trailing_slashes( config_dir );
208         if (config_dir[0] != '/')
209             fatal_error( "invalid directory %s in WINEPREFIX: not an absolute path\n", prefix );
210         if (stat( config_dir, &st ) == -1)
211         {
212             if (errno != ENOENT)
213                 fatal_perror( "cannot open %s as specified in WINEPREFIX", config_dir );
214             fatal_error( "the '%s' directory specified in WINEPREFIX doesn't exist.\n"
215                          "You may want to create it by running 'wineprefixcreate'.\n", config_dir );
216         }
217     }
218     else
219     {
220         if (!home) fatal_error( "could not determine your home directory\n" );
221         if (home[0] != '/') fatal_error( "your home directory %s is not an absolute path\n", home );
222         config_dir = xmalloc( strlen(home) + sizeof(server_config_dir) );
223         strcpy( config_dir, home );
224         remove_trailing_slashes( config_dir );
225         strcat( config_dir, server_config_dir );
226         if (stat( config_dir, &st ) == -1)
227         {
228             if (errno == ENOENT) return;  /* will be created later on */
229             fatal_perror( "cannot open %s", config_dir );
230         }
231     }
232     if (!S_ISDIR(st.st_mode)) fatal_error( "%s is not a directory\n", config_dir );
233
234     init_server_dir( st.st_dev, st.st_ino );
235 }
236
237 /* check if basedir is a valid build dir by checking for wineserver and ntdll */
238 /* helper for running_from_build_dir */
239 static inline int is_valid_build_dir( char *basedir, int baselen )
240 {
241     struct stat st;
242
243     strcpy( basedir + baselen, "/server/wineserver" );
244     if (stat( basedir, &st ) == -1) return 0;  /* no wineserver found */
245     /* check for ntdll too to make sure */
246     strcpy( basedir + baselen, "/dlls/ntdll/ntdll.dll.so" );
247     if (stat( basedir, &st ) == -1) return 0;  /* no ntdll found */
248
249     basedir[baselen] = 0;
250     return 1;
251 }
252
253 /* check if we are running from the build directory */
254 static char *running_from_build_dir( const char *basedir, const char *bindir )
255 {
256     struct stat st;
257     const char *p;
258     char *path;
259     int res;
260
261     if (!(path = build_path( bindir, "wineserver" ))) return NULL;
262     res = stat( path, &st );
263     free( path );
264     if (res != -1) return NULL;  /* the real bindir is valid */
265
266     /* remove last component from basedir */
267     p = basedir + strlen(basedir) - 1;
268     while (p > basedir && *p == '/') p--;
269     while (p > basedir && *p != '/') p--;
270     if (p == basedir) return NULL;
271     path = xmalloc( p - basedir + sizeof("/dlls/ntdll/ntdll.dll.so") );
272     memcpy( path, basedir, p - basedir );
273
274     if (!is_valid_build_dir( path, p - basedir ))
275     {
276         /* remove another component */
277         while (p > basedir && *p == '/') p--;
278         while (p > basedir && *p != '/') p--;
279         if (p == basedir || !is_valid_build_dir( path, p - basedir ))
280         {
281             free( path );
282             return NULL;
283         }
284     }
285     return path;
286 }
287
288 /* initialize the argv0 path */
289 void wine_init_argv0_path( const char *argv0 )
290 {
291     size_t size, len;
292     const char *p, *basename;
293     char *cwd, *libdir;
294
295     if (!(p = strrchr( argv0, '/' )))
296         basename = argv0;
297     else
298         basename = p + 1;
299
300     argv0_name = xstrdup( basename );
301
302     if ((libdir = get_runtime_libdir()))
303     {
304         bindir = build_path( libdir, LIB_TO_BINDIR );
305         if ((build_dir = running_from_build_dir( libdir, bindir )))
306         {
307             free( libdir );
308             goto in_build_dir;
309         }
310         dlldir = build_path( libdir, LIB_TO_DLLDIR );
311         datadir = build_path( libdir, LIB_TO_DATADIR );
312         free( libdir );
313         return;
314     }
315
316     if (!p) return;  /* if argv0 doesn't contain a path, don't store anything */
317
318     len = p - argv0;
319     if (!len) len++;  /* include leading slash */
320
321     if (argv0[0] == '/')  /* absolute path */
322     {
323         bindir = xmalloc( len + 1 );
324         memcpy( bindir, argv0, len );
325         bindir[len] = 0;
326     }
327     else
328     {
329         /* relative path, make it absolute */
330         for (size = 256 + len; ; size *= 2)
331         {
332             if (!(cwd = malloc( size ))) return;
333             if (getcwd( cwd, size - len ))
334             {
335                 bindir = cwd;
336                 cwd += strlen(cwd);
337                 *cwd++ = '/';
338                 memcpy( cwd, argv0, len );
339                 cwd[len] = 0;
340                 break;
341             }
342             free( cwd );
343             if (errno != ERANGE) return;
344         }
345     }
346
347     if ((build_dir = running_from_build_dir( bindir, bindir ))) goto in_build_dir;
348
349     dlldir = build_path( bindir, BIN_TO_DLLDIR );
350     datadir = build_path( bindir, BIN_TO_DATADIR );
351     return;
352
353 in_build_dir:
354     free( bindir );
355     free( argv0_name );
356     bindir = NULL;
357     argv0_name = build_path( "loader/", basename );
358 }
359
360 /* return the configuration directory ($WINEPREFIX or $HOME/.wine) */
361 const char *wine_get_config_dir(void)
362 {
363     if (!config_dir) init_paths();
364     return config_dir;
365 }
366
367 /* retrieve the wine data dir */
368 const char *wine_get_data_dir(void)
369 {
370     return datadir;
371 }
372
373 /* retrieve the wine build dir (if we are running from there) */
374 const char *wine_get_build_dir(void)
375 {
376     return build_dir;
377 }
378
379 /* return the full name of the server directory (the one containing the socket) */
380 const char *wine_get_server_dir(void)
381 {
382     if (!server_dir)
383     {
384         if (!config_dir) init_paths();
385         else
386         {
387             struct stat st;
388
389             if (stat( config_dir, &st ) == -1)
390             {
391                 if (errno != ENOENT) fatal_error( "cannot stat %s\n", config_dir );
392                 return NULL;  /* will have to try again once config_dir has been created */
393             }
394             init_server_dir( st.st_dev, st.st_ino );
395         }
396     }
397     return server_dir;
398 }
399
400 /* return the current user name */
401 const char *wine_get_user_name(void)
402 {
403     if (!user_name) init_paths();
404     return user_name;
405 }
406
407 /* exec a binary using the preloader if requested; helper for wine_exec_wine_binary */
408 static void preloader_exec( char **argv, int use_preloader )
409 {
410 #ifdef linux
411     if (use_preloader)
412     {
413         static const char preloader[] = "wine-preloader";
414         char *p, *full_name;
415         char **last_arg = argv, **new_argv;
416
417         if (!(p = strrchr( argv[0], '/' ))) p = argv[0];
418         else p++;
419
420         full_name = xmalloc( p - argv[0] + sizeof(preloader) );
421         memcpy( full_name, argv[0], p - argv[0] );
422         memcpy( full_name + (p - argv[0]), preloader, sizeof(preloader) );
423
424         /* make a copy of argv */
425         while (*last_arg) last_arg++;
426         new_argv = xmalloc( (last_arg - argv + 2) * sizeof(*argv) );
427         memcpy( new_argv + 1, argv, (last_arg - argv + 1) * sizeof(*argv) );
428         new_argv[0] = full_name;
429         execv( full_name, new_argv );
430         free( new_argv );
431         free( full_name );
432         return;
433     }
434 #endif
435     execv( argv[0], argv );
436 }
437
438 /* exec a wine internal binary (either the wine loader or the wine server) */
439 void wine_exec_wine_binary( const char *name, char **argv, const char *env_var )
440 {
441     const char *path, *pos, *ptr;
442     int use_preloader = 0;
443
444     if (!name)  /* no name means default loader */
445     {
446         name = argv0_name;
447         use_preloader = 1;
448     }
449
450     if ((ptr = strrchr( name, '/' )))
451     {
452         /* if we are in build dir and name contains a path, try that */
453         if (build_dir)
454         {
455             argv[0] = build_path( build_dir, name );
456             preloader_exec( argv, use_preloader );
457             free( argv[0] );
458         }
459         name = ptr + 1;  /* get rid of path */
460     }
461
462     /* first, bin directory from the current libdir or argv0 */
463     if (bindir)
464     {
465         argv[0] = build_path( bindir, name );
466         preloader_exec( argv, use_preloader );
467         free( argv[0] );
468     }
469
470     /* then specified environment variable */
471     if (env_var)
472     {
473         argv[0] = (char *)env_var;
474         preloader_exec( argv, use_preloader );
475     }
476
477     /* now search in the Unix path */
478     if ((path = getenv( "PATH" )))
479     {
480         argv[0] = xmalloc( strlen(path) + strlen(name) + 2 );
481         pos = path;
482         for (;;)
483         {
484             while (*pos == ':') pos++;
485             if (!*pos) break;
486             if (!(ptr = strchr( pos, ':' ))) ptr = pos + strlen(pos);
487             memcpy( argv[0], pos, ptr - pos );
488             strcpy( argv[0] + (ptr - pos), "/" );
489             strcat( argv[0] + (ptr - pos), name );
490             preloader_exec( argv, use_preloader );
491             pos = ptr;
492         }
493         free( argv[0] );
494     }
495
496     /* and finally try BINDIR */
497     argv[0] = build_path( BINDIR, name );
498     preloader_exec( argv, use_preloader );
499     free( argv[0] );
500 }