main.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. /*
  2. * Emulator initialisation code
  3. *
  4. * Copyright 2000 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. #include "config.h"
  21. #include "wine/port.h"
  22. #include <pthread.h>
  23. #include <stdio.h>
  24. #include <stdlib.h>
  25. #include "main.h"
  26. extern char **environ;
  27. /* the preloader will set this variable */
  28. const struct wine_preload_info *wine_main_preload_info = NULL;
  29. /* canonicalize path and return its directory name */
  30. static char *realpath_dirname( const char *name )
  31. {
  32. char *p, *fullpath = realpath( name, NULL );
  33. if (fullpath)
  34. {
  35. p = strrchr( fullpath, '/' );
  36. if (p == fullpath) p++;
  37. if (p) *p = 0;
  38. }
  39. return fullpath;
  40. }
  41. /* if string ends with tail, remove it */
  42. static char *remove_tail( const char *str, const char *tail )
  43. {
  44. size_t len = strlen( str );
  45. size_t tail_len = strlen( tail );
  46. char *ret;
  47. if (len < tail_len) return NULL;
  48. if (strcmp( str + len - tail_len, tail )) return NULL;
  49. ret = malloc( len - tail_len + 1 );
  50. memcpy( ret, str, len - tail_len );
  51. ret[len - tail_len] = 0;
  52. return ret;
  53. }
  54. /* build a path from the specified dir and name */
  55. static char *build_path( const char *dir, const char *name )
  56. {
  57. size_t len = strlen( dir );
  58. char *ret = malloc( len + strlen( name ) + 2 );
  59. memcpy( ret, dir, len );
  60. if (len && ret[len - 1] != '/') ret[len++] = '/';
  61. strcpy( ret + len, name );
  62. return ret;
  63. }
  64. static const char *get_self_exe( char *argv0 )
  65. {
  66. #if defined(__linux__) || defined(__FreeBSD_kernel__) || defined(__NetBSD__)
  67. return "/proc/self/exe";
  68. #elif defined (__FreeBSD__) || defined(__DragonFly__)
  69. return "/proc/curproc/file";
  70. #else
  71. if (!strchr( argv0, '/' )) /* search in PATH */
  72. {
  73. char *p, *path = getenv( "PATH" );
  74. if (!path || !(path = strdup(path))) return NULL;
  75. for (p = strtok( path, ":" ); p; p = strtok( NULL, ":" ))
  76. {
  77. char *name = build_path( p, argv0 );
  78. if (!access( name, X_OK ))
  79. {
  80. free( path );
  81. return name;
  82. }
  83. free( name );
  84. }
  85. free( path );
  86. return NULL;
  87. }
  88. return argv0;
  89. #endif
  90. }
  91. static void *try_dlopen( const char *dir, const char *name )
  92. {
  93. char *path = build_path( dir, name );
  94. void *handle = dlopen( path, RTLD_NOW );
  95. free( path );
  96. return handle;
  97. }
  98. static void *load_ntdll( char *argv0 )
  99. {
  100. const char *self = get_self_exe( argv0 );
  101. char *path, *p;
  102. void *handle = NULL;
  103. if (self && ((path = realpath_dirname( self ))))
  104. {
  105. if ((p = remove_tail( path, "/loader" )))
  106. {
  107. handle = try_dlopen( p, "dlls/ntdll/ntdll.so" );
  108. free( p );
  109. }
  110. else handle = try_dlopen( path, BIN_TO_DLLDIR "/ntdll.so" );
  111. free( path );
  112. }
  113. if (!handle && (path = getenv( "WINEDLLPATH" )))
  114. {
  115. path = strdup( path );
  116. for (p = strtok( path, ":" ); p; p = strtok( NULL, ":" ))
  117. {
  118. handle = try_dlopen( p, "ntdll.so" );
  119. if (handle) break;
  120. }
  121. free( path );
  122. }
  123. if (!handle && !self) handle = try_dlopen( DLLDIR, "ntdll.so" );
  124. return handle;
  125. }
  126. /**********************************************************************
  127. * main
  128. */
  129. int main( int argc, char *argv[] )
  130. {
  131. void *handle;
  132. if ((handle = load_ntdll( argv[0] )))
  133. {
  134. void (*init_func)(int, char **, char **) = dlsym( handle, "__wine_main" );
  135. if (init_func) init_func( argc, argv, environ );
  136. fprintf( stderr, "wine: __wine_main function not found in ntdll.so\n" );
  137. exit(1);
  138. }
  139. fprintf( stderr, "wine: could not load ntdll.so: %s\n", dlerror() );
  140. pthread_detach( pthread_self() ); /* force importing libpthread for OpenGL */
  141. exit(1);
  142. }