main函数
/**********************************************************************
* main
*/
int main( int argc, char *argv[] )
{
char error[1024];
int i;
判断是否有这个环境,是否在运行
if (!getenv( "WINELOADERNOEXEC" )) /* first time around */
{
static char noexec[] = "WINELOADERNOEXEC=1";
如果没有就可以运行wine,设置成1.
putenv( noexec );
确认命令格式,对--help和--version做出解释
check_command_line( argc, argv );
确认运行前的进程,资源情况
if (pre_exec())
{
初始化运行所需要的环境,库环境,数据的环境
wine_init_argv0_path( argv[0] );
确认相关文件是否正确,是否存在,载入文件运行
wine_exec_wine_binary( NULL, argv, getenv( "WINELOADER" ));
如果能载入程序,并正常退出。程序不会到这里
fprintf( stderr, "wine: could not exec the wine loader\n" );
强制退出
exit(1);
}
}
#ifndef __APPLE__
if (wine_main_preload_info)
#endif
{
for (i = 0; wine_main_preload_info[i].size; i++)
reserve_area( wine_main_preload_info[i].addr, wine_main_preload_info[i].size );
}
wine_init( argc, argv, error, sizeof(error) );
fprintf( stderr, "wine: failed to initialize: %s\n", error );
exit(1);
}
main函数中的check_command_line
[main() >check_command_line()]
static void check_command_line( int argc, char *argv[] )
{
提示的相关信息
static const char usage[] =
"Usage: wine PROGRAM [ARGUMENTS...] Run the specified program\n"
" wine --help Display this help and exit\n"
" wine --version Output version information and exit";
参数不够
if (argc <= 1)
{
fprintf( stderr, "%s\n", usage );
exit(1);
}
如果是--help
if (!strcmp( argv[1], "--help" ))
{
printf( "%s\n", usage );
exit(0);
}
如果是--version
if (!strcmp( argv[1], "--version" ))
{
printf( "%s\n", wine_get_build_id() );
exit(0);
}
}
check_command_line函数手中的wine_get_build_id
[main() >check_command_line()>wine_get_build_id()]
const char *wine_get_build_id(void)
{
这里wine_build = “1.7.21”...
extern const char wine_build[];
return wine_build;
}
main中的pre_exec
[main() >pre_exec()]
static int pre_exec(void)
{
int temp;
确认不使用pthread
check_threading();
要求小于2G
check_vmsplit( &temp );
设置最大使用资源
set_max_limit( RLIMIT_AS );
return 1;
}
main中的wine_init_argv0_path
[main() >wine_init_argv0_path()]
/* initialize the argv0 path */初始化argv0路径
void wine_init_argv0_path( const char *argv0 )
{
const char *basename;
char *libdir;
basename是从路径中提取wine
if (!(basename = strrchr( argv0, '/' ))) basename = argv0;
else basename++;
bindir是wine所在的路径
bindir = get_runtime_exedir();
判断wine路径是否存在和相同路径下wineserver是否存在
if (bindir && !is_valid_bindir( bindir ))
{
如果wine路径下没有wineserver,说明还在源文件下。于是到server目录下找到wineserver,到dlls目录下找到ntdll.dll.so。此时build_dir是源文件目录,如"/home/chen/下载/wine-1.7.21"
build_dir = running_from_build_dir( bindir );
清空bindir
free( bindir );
bindir = NULL;
}
这里找lib文件的目录,如"/home/chen/下载/wine-1.7.21/loader/../libs/wine"
libdir = get_runtime_libdir();
if (libdir && !bindir && !build_dir)
{
build_dir = running_from_build_dir( libdir );
if (!build_dir) bindir = build_path( libdir, LIB_TO_BINDIR );
}
if (!libdir && !bindir && !build_dir)
{
bindir = get_runtime_argvdir( argv0 );
if (bindir && !is_valid_bindir( bindir ))
{
build_dir = running_from_build_dir( bindir );
free( bindir );
bindir = NULL;
}
}
这里argv0_name为”loader/wine”
if (build_dir)
{
argv0_name = build_path( "loader/", basename );
}
else
{
if (libdir) dlldir = build_path( libdir, LIB_TO_DLLDIR );
else if (bindir) dlldir = build_path( bindir, BIN_TO_DLLDIR );
if (bindir) datadir = build_path( bindir, BIN_TO_DATADIR );
argv0_name = xstrdup( basename );
}
free( libdir );
函数结束后只有build_dir还存放着wine的路径,如"/home/chen/下载/wine-1.7.21"
}
main中的wine_exec_wine_binary
[main() >wine_exec_wine_binary()]
void wine_exec_wine_binary( const char *name, char **argv, const char *env_var )
{
const char *path, *pos, *ptr;
int use_preloader;
name为”loader/wine”
if (!name) name = argv0_name; /* no name means default loader */
#ifdef linux
use_preloader = !strendswith( name, "wineserver" );
#else
use_preloader = 0;
#endif
linux下use_preloader = 1,这个use_preloader在preloader_exec用来判断
if ((ptr = strrchr( name, '/' )))
{
/* if we are in build dir and name contains a path, try that */
这里ptr有值,build_dir也有值,判断后进入。其他的判断应该也差不多,都是为了进preloader_exec函数。
if (build_dir)
{
argv[0] = build_path( build_dir, name );
preloader_exec( argv, use_preloader );
free( argv[0] );
}
name = ptr + 1; /* get rid of path */
}
/* first, bin directory from the current libdir or argv0 */
if (bindir)
{
argv[0] = build_path( bindir, name );
preloader_exec( argv, use_preloader );
free( argv[0] );
}
/* then specified environment variable */
if (env_var)
{
argv[0] = (char *)env_var;
preloader_exec( argv, use_preloader );
}
/* now search in the Unix path */
if ((path = getenv( "PATH" )))
{
argv[0] = xmalloc( strlen(path) + strlen(name) + 2 );
pos = path;
for (;;)
{
while (*pos == ':') pos++;
if (!*pos) break;
if (!(ptr = strchr( pos, ':' ))) ptr = pos + strlen(pos);
memcpy( argv[0], pos, ptr - pos );
strcpy( argv[0] + (ptr - pos), "/" );
strcat( argv[0] + (ptr - pos), name );
preloader_exec( argv, use_preloader );
pos = ptr;
}
free( argv[0] );
}
/* and finally try BINDIR */
argv[0] = build_path( BINDIR, name );
preloader_exec( argv, use_preloader );
free( argv[0] );
}
wine_exec_wine_binary中的preloader_exec
/* exec a binary using the preloader if requested; helper for wine_exec_wine_binary */
static void preloader_exec( char **argv, int use_preloader )
{
if (use_preloader)
{
static const char preloader[] = "wine-preloader";
static const char preloader64[] = "wine64-preloader";
char *p, *full_name;
char **last_arg = argv, **new_argv;
这里p和之前basename一样,是”wine”
if (!(p = strrchr( argv[0], '/' ))) p = argv[0];
else p++;
full_name = xmalloc( p - argv[0] + sizeof(preloader64) );
memcpy( full_name, argv[0], p - argv[0] );
if (strendswith( p, "64" ))
memcpy( full_name + (p - argv[0]), preloader64, sizeof(preloader64) );
else
memcpy( full_name + (p - argv[0]), preloader, sizeof(preloader) );
到这里full_name是wine(或64)-preloader的路径了
/* make a copy of argv */
last_arg存放着argv,现在又扩展了.last_arg是在argv后面的部分,last_arg[-2]是argv[0]
while (*last_arg) last_arg++;
last_arg-argv=2,又加了2,分配了×argv的空间,new_argv有4个×argv的空间
new_argv = xmalloc( (last_arg - argv + 2) * sizeof(*argv) );
从new_argv[1]开始把argv内容复制进去大小为3个×argv,
memcpy( new_argv + 1, argv, (last_arg - argv + 1) * sizeof(*argv) );
这里new_argv[0]是full_name的路径,new_argv就依次有full_name,argv的内容了
new_argv[0] = full_name;
execv中运行的是wine-preloader,new_argv中又三个参数:wine-preloader(带路径),wine(带路径),notepad.exe。没有kthread了
execv( full_name, new_argv );
free( new_argv );
free( full_name );
}
use_preloader=0就直接运行
execv( argv[0], argv );
}
阅读(1080) | 评论(0) | 转发(0) |