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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include "wine/port.h"
37 static const char * const server_config_dir
= "/.wine"; /* config dir relative to $HOME */
38 static const char * const server_root_prefix
= "/tmp/.wine-"; /* prefix for server root dir */
39 static const char * const server_dir_prefix
= "/server-"; /* prefix for server dir */
41 static char *config_dir
;
42 static char *server_dir
;
43 static char *user_name
;
44 static char *argv0_path
;
45 static char *argv0_name
;
48 static void fatal_error( const char *err
, ... ) __attribute__((noreturn
,format(printf
,1,2)));
49 static void fatal_perror( const char *err
, ... ) __attribute__((noreturn
,format(printf
,1,2)));
52 /* die on a fatal error */
53 static void fatal_error( const char *err
, ... )
57 va_start( args
, err
);
58 fprintf( stderr
, "wine: " );
59 vfprintf( stderr
, err
, args
);
64 /* die on a fatal error */
65 static void fatal_perror( const char *err
, ... )
69 va_start( args
, err
);
70 fprintf( stderr
, "wine: " );
71 vfprintf( stderr
, err
, args
);
78 static void *xmalloc( size_t size
)
83 if (!(res
= malloc( size
))) fatal_error( "virtual memory exhausted\n");
88 static char *xstrdup( const char *str
)
90 size_t len
= strlen(str
) + 1;
91 char *res
= xmalloc( len
);
92 memcpy( res
, str
, len
);
96 /* remove all trailing slashes from a path name */
97 inline static void remove_trailing_slashes( char *path
)
99 int len
= strlen( path
);
100 while (len
> 1 && path
[len
-1] == '/') path
[--len
] = 0;
103 /* initialize all the paths values */
104 static void init_paths(void)
109 const char *home
= getenv( "HOME" );
110 const char *user
= NULL
;
111 const char *prefix
= getenv( "WINEPREFIX" );
115 struct passwd
*pwd
= getpwuid( getuid() );
120 if (!home
) home
= pwd
->pw_dir
;
124 sprintf( uid_str
, "%d", getuid() );
127 #else /* HAVE_GETPWUID */
128 if (!(user
= getenv( "USER" )))
129 fatal_error( "cannot determine your user name, set the USER environment variable\n" );
130 #endif /* HAVE_GETPWUID */
131 user_name
= xstrdup( user
);
133 /* build config_dir */
137 if (!(config_dir
= strdup( prefix
))) fatal_error( "virtual memory exhausted\n");
138 remove_trailing_slashes( config_dir
);
139 if (config_dir
[0] != '/')
140 fatal_error( "invalid directory %s in WINEPREFIX: not an absolute path\n", prefix
);
141 if (stat( config_dir
, &st
) == -1)
142 fatal_perror( "cannot open %s as specified in WINEPREFIX", config_dir
);
146 if (!home
) fatal_error( "could not determine your home directory\n" );
147 if (home
[0] != '/') fatal_error( "your home directory %s is not an absolute path\n", home
);
148 config_dir
= xmalloc( strlen(home
) + strlen(server_config_dir
) + 1 );
149 strcpy( config_dir
, home
);
150 remove_trailing_slashes( config_dir
);
151 strcat( config_dir
, server_config_dir
);
152 if (stat( config_dir
, &st
) == -1)
153 fatal_perror( "cannot open %s", config_dir
);
155 if (!S_ISDIR(st
.st_mode
)) fatal_error( "%s is not a directory\n", config_dir
);
157 /* build server_dir */
159 server_dir
= xmalloc( strlen(server_root_prefix
) + strlen(user
) + strlen( server_dir_prefix
) +
160 2*sizeof(st
.st_dev
) + 2*sizeof(st
.st_ino
) + 2 );
161 strcpy( server_dir
, server_root_prefix
);
162 p
= server_dir
+ strlen(server_dir
);
166 if (*p
== '/') *p
= '!';
169 strcpy( p
, server_dir_prefix
);
171 if (sizeof(st
.st_dev
) > sizeof(unsigned long) && st
.st_dev
> ~0UL)
172 sprintf( server_dir
+ strlen(server_dir
), "%lx%08lx-",
173 (unsigned long)(st
.st_dev
>> 32), (unsigned long)st
.st_dev
);
175 sprintf( server_dir
+ strlen(server_dir
), "%lx-", (unsigned long)st
.st_dev
);
177 if (sizeof(st
.st_ino
) > sizeof(unsigned long) && st
.st_ino
> ~0UL)
178 sprintf( server_dir
+ strlen(server_dir
), "%lx%08lx",
179 (unsigned long)(st
.st_ino
>> 32), (unsigned long)st
.st_ino
);
181 sprintf( server_dir
+ strlen(server_dir
), "%lx", (unsigned long)st
.st_ino
);
184 /* initialize the argv0 path */
185 void wine_init_argv0_path( const char *argv0
)
191 if (!(p
= strrchr( argv0
, '/' )))
193 argv0_name
= xstrdup( argv0
);
194 return; /* if argv0 doesn't contain a path, don't store any path */
196 else argv0_name
= xstrdup( p
+ 1 );
199 if (argv0
[0] == '/') /* absolute path */
201 argv0_path
= xmalloc( len
+ 1 );
202 memcpy( argv0_path
, argv0
, len
);
207 /* relative path, make it absolute */
208 for (size
= 256 + len
; ; size
*= 2)
210 if (!(cwd
= malloc( size
))) break;
211 if (getcwd( cwd
, size
- len
))
216 memcpy( cwd
, argv0
, len
);
221 if (errno
!= ERANGE
) break;
225 /* return the configuration directory ($WINEPREFIX or $HOME/.wine) */
226 const char *wine_get_config_dir(void)
228 if (!config_dir
) init_paths();
232 /* return the full name of the server directory (the one containing the socket) */
233 const char *wine_get_server_dir(void)
235 if (!server_dir
) init_paths();
239 /* return the current user name */
240 const char *wine_get_user_name(void)
242 if (!user_name
) init_paths();
246 /* exec a wine internal binary (either the wine loader or the wine server) */
247 /* if name is null, default to the name of the current binary */
248 void wine_exec_wine_binary( const char *name
, char **argv
, char **envp
)
250 const char *path
, *pos
, *ptr
;
251 extern char **environ
;
253 if (!envp
) envp
= environ
;
254 if (!name
) name
= argv0_name
;
256 /* first, try bin directory */
257 argv
[0] = xmalloc( sizeof(BINDIR
"/") + strlen(name
) );
258 strcpy( argv
[0], BINDIR
"/" );
259 strcat( argv
[0], name
);
260 execve( argv
[0], argv
, envp
);
263 /* now try the path of argv0 of the current binary */
266 argv
[0] = xmalloc( strlen(argv0_path
) + strlen(name
) + 1 );
267 strcpy( argv
[0], argv0_path
);
268 strcat( argv
[0], name
);
269 execve( argv
[0], argv
, envp
);
273 /* now search in the Unix path */
274 if ((path
= getenv( "PATH" )))
276 argv
[0] = xmalloc( strlen(path
) + strlen(name
) + 2 );
280 while (*pos
== ':') pos
++;
282 if (!(ptr
= strchr( pos
, ':' ))) ptr
= pos
+ strlen(pos
);
283 memcpy( argv
[0], pos
, ptr
- pos
);
284 strcpy( argv
[0] + (ptr
- pos
), "/" );
285 strcat( argv
[0] + (ptr
- pos
), name
);
286 execve( argv
[0], argv
, envp
);