Back to home page

Wine source

 
 

    


File indexing completed on 2023-11-10 23:34:04

a0b2b1d0f Alex*0001 /*
                0002  * Emulator initialisation code
                0003  *
0799c1a78 Alex*0004  * Copyright 2000 Alexandre Julliard
                0005  *
                0006  * This library is free software; you can redistribute it and/or
                0007  * modify it under the terms of the GNU Lesser General Public
                0008  * License as published by the Free Software Foundation; either
                0009  * version 2.1 of the License, or (at your option) any later version.
                0010  *
                0011  * This library is distributed in the hope that it will be useful,
                0012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
                0013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
                0014  * Lesser General Public License for more details.
                0015  *
                0016  * You should have received a copy of the GNU Lesser General Public
                0017  * License along with this library; if not, write to the Free Software
360a3f914 Jona*0018  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
a0b2b1d0f Alex*0019  */
                0020 
181cf8b63 Alex*0021 #include "config.h"
                0022 
28d7d5ba9 Alex*0023 #include <fcntl.h>
4826900a3 Alex*0024 #include <pthread.h>
fedc41174 Alex*0025 #include <stdio.h>
2989895f7 Alex*0026 #include <stdlib.h>
28d7d5ba9 Alex*0027 #include <string.h>
                0028 #include <sys/types.h>
                0029 #include <sys/stat.h>
                0030 #include <unistd.h>
                0031 #include <dlfcn.h>
f5e51cfc5 Damj*0032 #include <limits.h>
                0033 #ifdef HAVE_SYS_SYSCTL_H
                0034 # include <sys/sysctl.h>
                0035 #endif
181cf8b63 Alex*0036 
b1abca8a5 Alex*0037 #include "main.h"
                0038 
526522caa Alex*0039 extern char **environ;
                0040 
b1abca8a5 Alex*0041 /* the preloader will set this variable */
4502eb56b Alex*0042 const __attribute((visibility("default"))) struct wine_preload_info *wine_main_preload_info = NULL;
181cf8b63 Alex*0043 
526522caa Alex*0044 /* canonicalize path and return its directory name */
                0045 static char *realpath_dirname( const char *name )
                0046 {
                0047     char *p, *fullpath = realpath( name, NULL );
                0048 
                0049     if (fullpath)
                0050     {
                0051         p = strrchr( fullpath, '/' );
                0052         if (p == fullpath) p++;
                0053         if (p) *p = 0;
                0054     }
                0055     return fullpath;
                0056 }
                0057 
                0058 /* if string ends with tail, remove it */
                0059 static char *remove_tail( const char *str, const char *tail )
                0060 {
                0061     size_t len = strlen( str );
                0062     size_t tail_len = strlen( tail );
                0063     char *ret;
                0064 
                0065     if (len < tail_len) return NULL;
                0066     if (strcmp( str + len - tail_len, tail )) return NULL;
                0067     ret = malloc( len - tail_len + 1 );
                0068     memcpy( ret, str, len - tail_len );
                0069     ret[len - tail_len] = 0;
                0070     return ret;
                0071 }
                0072 
                0073 /* build a path from the specified dir and name */
                0074 static char *build_path( const char *dir, const char *name )
                0075 {
                0076     size_t len = strlen( dir );
                0077     char *ret = malloc( len + strlen( name ) + 2 );
                0078 
                0079     memcpy( ret, dir, len );
                0080     if (len && ret[len - 1] != '/') ret[len++] = '/';
                0081     strcpy( ret + len, name );
                0082     return ret;
                0083 }
                0084 
                0085 static const char *get_self_exe( char *argv0 )
                0086 {
                0087 #if defined(__linux__) || defined(__FreeBSD_kernel__) || defined(__NetBSD__)
                0088     return "/proc/self/exe";
                0089 #elif defined (__FreeBSD__) || defined(__DragonFly__)
f5e51cfc5 Damj*0090     static int pathname[] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 };
                0091     size_t path_size = PATH_MAX;
                0092     char *path = malloc( path_size );
699067ae1 Gera*0093     if (path && !sysctl( pathname, sizeof(pathname)/sizeof(pathname[0]), path, &path_size, NULL, 0 ))
f5e51cfc5 Damj*0094         return path;
                0095     free( path );
                0096 #endif
                0097 
526522caa Alex*0098     if (!strchr( argv0, '/' )) /* search in PATH */
                0099     {
                0100         char *p, *path = getenv( "PATH" );
                0101 
                0102         if (!path || !(path = strdup(path))) return NULL;
                0103         for (p = strtok( path, ":" ); p; p = strtok( NULL, ":" ))
                0104         {
                0105             char *name = build_path( p, argv0 );
a75596c94 Mart*0106             if (!access( name, X_OK ))
                0107             {
                0108                 free( path );
                0109                 return name;
                0110             }
526522caa Alex*0111             free( name );
                0112         }
                0113         free( path );
a75596c94 Mart*0114         return NULL;
526522caa Alex*0115     }
                0116     return argv0;
                0117 }
                0118 
                0119 static void *try_dlopen( const char *dir, const char *name )
                0120 {
                0121     char *path = build_path( dir, name );
                0122     void *handle = dlopen( path, RTLD_NOW );
                0123     free( path );
                0124     return handle;
                0125 }
                0126 
                0127 static void *load_ntdll( char *argv0 )
                0128 {
2801d6341 Alex*0129 #ifdef __i386__
                0130 #define SO_DIR "i386-unix/"
                0131 #elif defined(__x86_64__)
                0132 #define SO_DIR "x86_64-unix/"
                0133 #elif defined(__arm__)
                0134 #define SO_DIR "arm-unix/"
                0135 #elif defined(__aarch64__)
                0136 #define SO_DIR "aarch64-unix/"
                0137 #else
                0138 #define SO_DIR ""
                0139 #endif
526522caa Alex*0140     const char *self = get_self_exe( argv0 );
                0141     char *path, *p;
                0142     void *handle = NULL;
                0143 
                0144     if (self && ((path = realpath_dirname( self ))))
                0145     {
                0146         if ((p = remove_tail( path, "/loader" )))
                0147         {
                0148             handle = try_dlopen( p, "dlls/ntdll/ntdll.so" );
                0149             free( p );
                0150         }
2801d6341 Alex*0151         else handle = try_dlopen( path, BIN_TO_DLLDIR "/" SO_DIR "ntdll.so" );
526522caa Alex*0152         free( path );
                0153     }
                0154 
                0155     if (!handle && (path = getenv( "WINEDLLPATH" )))
                0156     {
                0157         path = strdup( path );
                0158         for (p = strtok( path, ":" ); p; p = strtok( NULL, ":" ))
                0159         {
2801d6341 Alex*0160             handle = try_dlopen( p, SO_DIR "ntdll.so" );
                0161             if (!handle) handle = try_dlopen( p, "ntdll.so" );
526522caa Alex*0162             if (handle) break;
                0163         }
                0164         free( path );
                0165     }
                0166 
2801d6341 Alex*0167     if (!handle && !self) handle = try_dlopen( DLLDIR, SO_DIR "ntdll.so" );
526522caa Alex*0168 
                0169     return handle;
                0170 }
                0171 
                0172 
a0b2b1d0f Alex*0173 /**********************************************************************
                0174  *           main
                0175  */
                0176 int main( int argc, char *argv[] )
                0177 {
526522caa Alex*0178     void *handle;
b1abca8a5 Alex*0179 
50134cce8 Alex*0180     if ((handle = load_ntdll( argv[0] )))
                0181     {
                0182         void (*init_func)(int, char **, char **) = dlsym( handle, "__wine_main" );
                0183         if (init_func) init_func( argc, argv, environ );
                0184         fprintf( stderr, "wine: __wine_main function not found in ntdll.so\n" );
                0185         exit(1);
                0186     }
                0187 
4826900a3 Alex*0188     fprintf( stderr, "wine: could not load ntdll.so: %s\n", dlerror() );
                0189     pthread_detach( pthread_self() );  /* force importing libpthread for OpenGL */
fedc41174 Alex*0190     exit(1);
a0b2b1d0f Alex*0191 }