Commit dec38ffb authored by Alexandre Julliard's avatar Alexandre Julliard

ntdll: Move the wineserver exec support to the Unix library.

parent 67bc4a6d
...@@ -99,7 +99,6 @@ extern void heap_set_debug_flags( HANDLE handle ) DECLSPEC_HIDDEN; ...@@ -99,7 +99,6 @@ extern void heap_set_debug_flags( HANDLE handle ) DECLSPEC_HIDDEN;
extern void init_unix_codepage(void) DECLSPEC_HIDDEN; extern void init_unix_codepage(void) DECLSPEC_HIDDEN;
extern void init_locale( HMODULE module ) DECLSPEC_HIDDEN; extern void init_locale( HMODULE module ) DECLSPEC_HIDDEN;
extern void init_user_process_params( SIZE_T data_size ) DECLSPEC_HIDDEN; extern void init_user_process_params( SIZE_T data_size ) DECLSPEC_HIDDEN;
extern void init_paths(void) DECLSPEC_HIDDEN;
extern char **build_envp( const WCHAR *envW ) DECLSPEC_HIDDEN; extern char **build_envp( const WCHAR *envW ) DECLSPEC_HIDDEN;
extern NTSTATUS restart_process( RTL_USER_PROCESS_PARAMETERS *params, NTSTATUS status ) DECLSPEC_HIDDEN; extern NTSTATUS restart_process( RTL_USER_PROCESS_PARAMETERS *params, NTSTATUS status ) DECLSPEC_HIDDEN;
......
...@@ -127,8 +127,6 @@ const char *build_dir = NULL; ...@@ -127,8 +127,6 @@ const char *build_dir = NULL;
const char *data_dir = NULL; const char *data_dir = NULL;
const char *config_dir = NULL; const char *config_dir = NULL;
static const char *server_dir; static const char *server_dir;
static const char *bin_dir;
static const char *argv0;
unsigned int server_cpus = 0; unsigned int server_cpus = 0;
BOOL is_wow64 = FALSE; BOOL is_wow64 = FALSE;
...@@ -191,47 +189,6 @@ static void fatal_perror( const char *err, ... ) ...@@ -191,47 +189,6 @@ static void fatal_perror( const char *err, ... )
exit(1); exit(1);
} }
/* canonicalize path and return its directory name */
static char *realpath_dirname( const char *name )
{
char *p, *fullpath = realpath( name, NULL );
if (fullpath)
{
p = strrchr( fullpath, '/' );
if (p == fullpath) p++;
if (p) *p = 0;
}
return fullpath;
}
/* if string ends with tail, remove it */
static char *remove_tail( const char *str, const char *tail )
{
size_t len = strlen( str );
size_t tail_len = strlen( tail );
char *ret;
if (len < tail_len) return NULL;
if (strcmp( str + len - tail_len, tail )) return NULL;
ret = malloc( len - tail_len + 1 );
memcpy( ret, str, len - tail_len );
ret[len - tail_len] = 0;
return ret;
}
/* build a path from the specified dir and name */
static char *build_path( const char *dir, const char *name )
{
size_t len = strlen( dir );
char *ret = malloc( len + strlen( name ) + 2 );
memcpy( ret, dir, len );
if (len && ret[len - 1] != '/') ret[len++] = '/';
strcpy( ret + len, name );
return ret;
}
/*********************************************************************** /***********************************************************************
* server_protocol_error * server_protocol_error
*/ */
...@@ -1224,83 +1181,6 @@ int server_pipe( int fd[2] ) ...@@ -1224,83 +1181,6 @@ int server_pipe( int fd[2] )
/*********************************************************************** /***********************************************************************
* exec_wineserver
*
* Exec a new wine server.
*/
static void exec_wineserver( char **argv )
{
char *path;
if (build_dir)
{
if (!is_win64) /* look for 64-bit server */
{
char *loader = realpath_dirname( build_path( build_dir, "loader/wine64" ));
if (loader)
{
argv[0] = build_path( loader, "../server/wineserver" );
execv( argv[0], argv );
}
}
argv[0] = build_path( build_dir, "server/wineserver" );
execv( argv[0], argv );
return;
}
argv[0] = build_path( bin_dir, "wineserver" );
execv( argv[0], argv );
argv[0] = getenv( "WINESERVER" );
if (argv[0]) execv( argv[0], argv );
if ((path = getenv( "PATH" )))
{
for (path = strtok( strdup( path ), ":" ); path; path = strtok( NULL, ":" ))
{
argv[0] = build_path( path, "wineserver" );
execvp( argv[0], argv );
}
}
argv[0] = build_path( BINDIR, "wineserver" );
execv( argv[0], argv );
}
/***********************************************************************
* start_server
*
* Start a new wine server.
*/
static void start_server(void)
{
static BOOL started; /* we only try once */
char *argv[3];
static char debug[] = "-d";
if (!started)
{
int status;
int pid = fork();
if (pid == -1) fatal_perror( "fork" );
if (!pid)
{
argv[1] = TRACE_ON(server) ? debug : NULL;
argv[2] = NULL;
exec_wineserver( argv );
fatal_error( "could not exec wineserver\n" );
}
waitpid( pid, &status, 0 );
status = WIFEXITED(status) ? WEXITSTATUS(status) : 1;
if (status == 2) return; /* server lock held by someone else, will retry later */
if (status) exit(status); /* server failed */
started = TRUE;
}
}
/***********************************************************************
* init_server_dir * init_server_dir
*/ */
static const char *init_server_dir( dev_t dev, ino_t ino ) static const char *init_server_dir( dev_t dev, ino_t ino )
...@@ -1333,43 +1213,6 @@ static const char *init_server_dir( dev_t dev, ino_t ino ) ...@@ -1333,43 +1213,6 @@ static const char *init_server_dir( dev_t dev, ino_t ino )
/*********************************************************************** /***********************************************************************
* init_paths
*/
void init_paths(void)
{
const char *dll_dir = NULL;
#ifdef HAVE_DLADDR
Dl_info info;
if (dladdr( init_paths, &info ) && info.dli_fname[0] == '/')
dll_dir = realpath_dirname( info.dli_fname );
#endif
argv0 = strdup( __wine_main_argv[0] );
#if defined(__linux__) || defined(__FreeBSD_kernel__) || defined(__NetBSD__)
bin_dir = realpath_dirname( "/proc/self/exe" );
#elif defined (__FreeBSD__) || defined(__DragonFly__)
bin_dir = realpath_dirname( "/proc/curproc/file" );
#else
bin_dir = realpath_dirname( argv0 );
#endif
if (dll_dir) build_dir = remove_tail( dll_dir, "/dlls/ntdll" );
else if (bin_dir) build_dir = remove_tail( bin_dir, "/loader" );
if (!build_dir)
{
if (!bin_dir) bin_dir = dll_dir ? build_path( dll_dir, DLL_TO_BINDIR ) : BINDIR;
else if (!dll_dir) dll_dir = build_path( bin_dir, BIN_TO_DLLDIR );
}
unix_funcs->get_paths( &build_dir, &data_dir, &config_dir );
}
/***********************************************************************
* setup_config_dir * setup_config_dir
* *
* Setup the wine configuration dir. * Setup the wine configuration dir.
...@@ -1467,7 +1310,7 @@ static int server_connect(void) ...@@ -1467,7 +1310,7 @@ static int server_connect(void)
if (chdir( server_dir ) == -1) if (chdir( server_dir ) == -1)
{ {
if (errno != ENOENT) fatal_perror( "chdir to %s", server_dir ); if (errno != ENOENT) fatal_perror( "chdir to %s", server_dir );
start_server(); unix_funcs->start_server( TRACE_ON(server) );
if (chdir( server_dir ) == -1) fatal_perror( "chdir to %s", server_dir ); if (chdir( server_dir ) == -1) fatal_perror( "chdir to %s", server_dir );
} }
...@@ -1482,13 +1325,13 @@ static int server_connect(void) ...@@ -1482,13 +1325,13 @@ static int server_connect(void)
if (retry) if (retry)
{ {
usleep( 100000 * retry * retry ); usleep( 100000 * retry * retry );
start_server(); unix_funcs->start_server( TRACE_ON(server) );
if (lstat( SOCKETNAME, &st ) == -1) continue; /* still no socket, wait a bit more */ if (lstat( SOCKETNAME, &st ) == -1) continue; /* still no socket, wait a bit more */
} }
else if (lstat( SOCKETNAME, &st ) == -1) /* check for an already existing socket */ else if (lstat( SOCKETNAME, &st ) == -1) /* check for an already existing socket */
{ {
if (errno != ENOENT) fatal_perror( "lstat %s/%s", server_dir, SOCKETNAME ); if (errno != ENOENT) fatal_perror( "lstat %s/%s", server_dir, SOCKETNAME );
start_server(); unix_funcs->start_server( TRACE_ON(server) );
if (lstat( SOCKETNAME, &st ) == -1) continue; /* still no socket, wait a bit more */ if (lstat( SOCKETNAME, &st ) == -1) continue; /* still no socket, wait a bit more */
} }
......
...@@ -381,7 +381,7 @@ TEB *thread_init(void) ...@@ -381,7 +381,7 @@ TEB *thread_init(void)
thread_data->wait_fd[1] = -1; thread_data->wait_fd[1] = -1;
unix_funcs->dbg_init(); unix_funcs->dbg_init();
init_paths(); unix_funcs->get_paths( &build_dir, &data_dir, &config_dir );
set_process_name( __wine_main_argc, __wine_main_argv ); set_process_name( __wine_main_argc, __wine_main_argv );
/* initialize time values in user_shared_data */ /* initialize time values in user_shared_data */
......
...@@ -42,6 +42,9 @@ ...@@ -42,6 +42,9 @@
#ifdef HAVE_SYS_UTSNAME_H #ifdef HAVE_SYS_UTSNAME_H
#include <sys/utsname.h> #include <sys/utsname.h>
#endif #endif
#ifdef HAVE_SYS_WAIT_H
#include <sys/wait.h>
#endif
#ifdef __APPLE__ #ifdef __APPLE__
# include <CoreFoundation/CoreFoundation.h> # include <CoreFoundation/CoreFoundation.h>
# define LoadResource MacLoadResource # define LoadResource MacLoadResource
...@@ -484,6 +487,83 @@ static NTSTATUS CDECL exec_wineloader( char **argv, int socketfd, int is_child_6 ...@@ -484,6 +487,83 @@ static NTSTATUS CDECL exec_wineloader( char **argv, int socketfd, int is_child_6
} }
/***********************************************************************
* exec_wineserver
*
* Exec a new wine server.
*/
static void exec_wineserver( char **argv )
{
char *path;
if (build_dir)
{
if (!is_win64) /* look for 64-bit server */
{
char *loader = realpath_dirname( build_path( build_dir, "loader/wine64" ));
if (loader)
{
argv[0] = build_path( loader, "../server/wineserver" );
execv( argv[0], argv );
}
}
argv[0] = build_path( build_dir, "server/wineserver" );
execv( argv[0], argv );
return;
}
argv[0] = build_path( bin_dir, "wineserver" );
execv( argv[0], argv );
argv[0] = getenv( "WINESERVER" );
if (argv[0]) execv( argv[0], argv );
if ((path = getenv( "PATH" )))
{
for (path = strtok( strdup( path ), ":" ); path; path = strtok( NULL, ":" ))
{
argv[0] = build_path( path, "wineserver" );
execvp( argv[0], argv );
}
}
argv[0] = build_path( BINDIR, "wineserver" );
execv( argv[0], argv );
}
/***********************************************************************
* start_server
*
* Start a new wine server.
*/
static void CDECL start_server( BOOL debug )
{
static BOOL started; /* we only try once */
char *argv[3];
static char debug_flag[] = "-d";
if (!started)
{
int status;
int pid = fork();
if (pid == -1) fatal_error( "fork: %s", strerror(errno) );
if (!pid)
{
argv[1] = debug ? debug_flag : NULL;
argv[2] = NULL;
exec_wineserver( argv );
fatal_error( "could not exec wineserver\n" );
}
waitpid( pid, &status, 0 );
status = WIFEXITED(status) ? WEXITSTATUS(status) : 1;
if (status == 2) return; /* server lock held by someone else, will retry later */
if (status) exit(status); /* server failed */
started = TRUE;
}
}
/************************************************************************* /*************************************************************************
* map_so_dll * map_so_dll
* *
...@@ -760,6 +840,7 @@ static struct unix_funcs unix_funcs = ...@@ -760,6 +840,7 @@ static struct unix_funcs unix_funcs =
get_build_id, get_build_id,
get_host_version, get_host_version,
exec_wineloader, exec_wineloader,
start_server,
map_so_dll, map_so_dll,
mmap_add_reserved_area, mmap_add_reserved_area,
mmap_remove_reserved_area, mmap_remove_reserved_area,
......
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
#include "wine/debug.h" #include "wine/debug.h"
/* increment this when you change the function table */ /* increment this when you change the function table */
#define NTDLL_UNIXLIB_VERSION 5 #define NTDLL_UNIXLIB_VERSION 6
struct unix_funcs struct unix_funcs
{ {
...@@ -39,6 +39,7 @@ struct unix_funcs ...@@ -39,6 +39,7 @@ struct unix_funcs
/* loader functions */ /* loader functions */
NTSTATUS (CDECL *exec_wineloader)( char **argv, int socketfd, int is_child_64bit, NTSTATUS (CDECL *exec_wineloader)( char **argv, int socketfd, int is_child_64bit,
ULONGLONG res_start, ULONGLONG res_end ); ULONGLONG res_start, ULONGLONG res_end );
void (CDECL *start_server)( BOOL debug );
/* virtual memory functions */ /* virtual memory functions */
NTSTATUS (CDECL *map_so_dll)( const IMAGE_NT_HEADERS *nt_descr, HMODULE module ); NTSTATUS (CDECL *map_so_dll)( const IMAGE_NT_HEADERS *nt_descr, HMODULE module );
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment