instance.c: Defaulting to /proc/curproc/file when locating module on FreeBSD
[sdk] / ecere / src / com / instance.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <stdarg.h>
4 #include <ctype.h>
5 #include <string.h>
6
7 #if defined(__GNUC__) || defined(__WATCOMC__) || defined(__WIN32__)
8 #include <time.h>
9 #include <sys/types.h>
10 #include <sys/stat.h>
11 #include <fcntl.h>
12 #endif
13
14 #if defined(__unix__) || defined(__APPLE__)
15 #define bool _bool
16 #include <utime.h>
17 #include <dlfcn.h>
18 #undef bool
19 #endif
20
21 #if defined(__WIN32__)
22 #define WIN32_LEAN_AND_MEAN
23 #define UNICODE
24 #include <windows.h>
25 #include <io.h>
26
27 #else
28 #include <unistd.h>
29 #endif
30
31 typedef int bool;
32 typedef unsigned char byte;
33 typedef unsigned short uint16;
34 typedef unsigned int uint;
35 typedef unsigned int FileSize;
36 typedef unsigned long long uint64;
37
38 #define false 0
39 #define true 1
40
41 #define null ((void *)0)
42
43 #define MAX_LOCATION 797
44 #define MAX_FILENAME 274
45 #define MAX_EXTENSION 17
46
47 FILE *eC_stdin(void)  { return stdin; }
48 FILE *eC_stdout(void) { return stdout; }
49 FILE *eC_stderr(void) { return stderr; }
50
51 void __ecereNameSpace__ecere__com__eSystem_Delete(void * memory);
52 void * __ecereNameSpace__ecere__com__eSystem_New0(unsigned int size);
53 void * __ecereNameSpace__ecere__com__eSystem_Renew(void * memory, unsigned int size);
54 void * __ecereNameSpace__ecere__com__eSystem_Renew0(void * memory, unsigned int size);
55 unsigned short * __ecereNameSpace__ecere__sys__UTF8toUTF16(char * source, int * wordCount);
56 unsigned short * __ecereNameSpace__ecere__sys__UTF8toUTF16Buffer(char * source, uint16 * dest, int max);
57 char * __ecereNameSpace__ecere__sys__UTF16toUTF8(uint16 * source);
58 char * __ecereNameSpace__ecere__sys__UTF16toUTF8Buffer(uint16 * source, byte * dest, int max);
59
60 #define eSystem_Delete     __ecereNameSpace__ecere__com__eSystem_Delete
61 #define eSystem_New0       __ecereNameSpace__ecere__com__eSystem_New0
62 #define eSystem_Renew      __ecereNameSpace__ecere__com__eSystem_Renew
63 #define eSystem_Renew0     __ecereNameSpace__ecere__com__eSystem_Renew0
64 #define UTF8toUTF16        __ecereNameSpace__ecere__sys__UTF8toUTF16
65 #define UTF8toUTF16Buffer  __ecereNameSpace__ecere__sys__UTF8toUTF16Buffer
66 #define UTF16toUTF8        __ecereNameSpace__ecere__sys__UTF16toUTF8
67 #define UTF16toUTF8Buffer  __ecereNameSpace__ecere__sys__UTF16toUTF8Buffer
68
69 #if defined(__unix__)
70 static char exeLocation[MAX_LOCATION];
71 #endif
72
73 int __ecereNameSpace__ecere__sys__Tokenize(char * string, int maxTokens, char* tokens[], bool escapeBackSlashes);
74 char * __ecereNameSpace__ecere__sys__RSearchString(char * buffer, char * subStr, int maxLen, bool matchCase, bool matchWord);
75 char * __ecereNameSpace__ecere__sys__GetLastDirectory(char * string, char * output);
76 char * __ecereNameSpace__ecere__sys__PathCat(char * string, char * addedPath);
77 char * __ecereNameSpace__ecere__sys__GetExtension(char * string, char * output);
78
79 #define Tokenize           __ecereNameSpace__ecere__sys__Tokenize
80 #define RSearchString      __ecereNameSpace__ecere__sys__RSearchString
81 #define GetLastDirectory   __ecereNameSpace__ecere__sys__GetLastDirectory
82 #define PathCat            __ecereNameSpace__ecere__sys__PathCat
83 #define GetExtension       __ecereNameSpace__ecere__sys__GetExtension
84
85 extern struct __ecereNameSpace__ecere__com__Instance * __thisModule;
86
87 typedef enum { unknown, win32, tux, apple } Platform;
88
89 #if defined(__WIN32__)
90 Platform runtimePlatform = win32;
91 #elif defined(__APPLE__)
92 Platform runtimePlatform = apple;
93 #elif defined(__linux__)
94 Platform runtimePlatform = tux;
95 #else
96 Platform runtimePlatform = unknown;
97 #endif
98
99 bool Instance_LocateModule(char * name, char * fileName)
100 {
101 #if defined(__WIN32__)
102    HMODULE hModule = null;
103    if(name && name[0])
104    {
105       uint16 _wmoduleName[MAX_LOCATION];
106       UTF8toUTF16Buffer(name, _wmoduleName, MAX_LOCATION);
107       hModule = GetModuleHandle(_wmoduleName);
108       if(!hModule)
109       {
110          wcscat(_wmoduleName, L".exe");
111          hModule = GetModuleHandle(_wmoduleName);
112       }
113       if(hModule)
114       {
115          uint16 _wfileName[MAX_LOCATION];
116          GetModuleFileNameW(hModule, _wfileName, MAX_LOCATION);
117          UTF16toUTF8Buffer(_wfileName, (byte *)fileName, MAX_LOCATION);
118          return true;
119       }
120    }
121    else
122    {
123       uint16 _wfileName[MAX_LOCATION];
124       GetModuleFileNameW(null, _wfileName, MAX_LOCATION);
125       UTF16toUTF8Buffer(_wfileName, (byte *)fileName, MAX_LOCATION);
126       return true;
127    }
128 #elif defined(__APPLE__)
129    if(name && name[0])
130    {
131       int imageCount = _dyld_image_count();
132       int c;
133       int nameLen = strlen(name);
134       for(c = 0; c<imageCount; c++)
135       {
136          struct mach_header * header = _dyld_get_image_header(c);
137          char * path = _dyld_get_image_name(c);
138          int pathLen = strlen(path);
139          char * subStr = RSearchString(path, name, pathLen, false, false);
140          if(subStr)
141          {
142             if(( *(subStr-1) == '/' || !strncmp(subStr - 4, "/lib", 4)) &&
143                (!subStr[nameLen] || !strncmp(subStr + nameLen, ".dylib", 6)))
144             {
145                strcpy(fileName, path);
146                return true;
147             }
148          }
149       }
150    }
151    else
152    {
153       int size = MAX_LOCATION;
154       _NSGetExecutablePath(fileName, &size);
155       return true;
156    }
157 #elif defined(__unix__)
158    //File f = FileOpen("/proc/self/maps", read);
159    FILE * f;
160    char exeName[MAX_FILENAME];
161    exeName[0] = 0;
162 #if defined(__linux__)
163    f = fopen("/proc/self/status", "r");
164 #else
165    f = fopen("/proc/curproc/status", "r");
166 #endif
167    if(f)
168    {
169       char line[1025];
170       while(fgets(line, sizeof(line), f))
171       {
172          char * name = strstr(line, "Name:\t");
173          if(name)
174          {
175             int nameLen;
176             name += 6;
177             nameLen = strlen(name);
178             name[--nameLen] = 0;
179             strcpy(exeName, name);
180             break;
181          }
182       }
183       fclose(f);
184   }
185 #if defined(__linux__)
186    f = fopen("/proc/self/maps", "r");
187 #else
188    f = fopen("/proc/curproc/map", "r");
189 #endif
190    if(f)
191    {
192       char line[1025];
193       //while(f.GetLine(line, sizeof(line)))
194       while(fgets(line, sizeof(line), f))
195       {
196          char * path = strstr(line, "/");
197          if(path)
198          {
199             int pathLen = strlen(path);
200             path[--pathLen] = 0;
201             if(name && name[0])
202             {
203                int nameLen = strlen(name);
204                char * subStr;
205                subStr = RSearchString(path, name, pathLen, false, false);
206                if(subStr)
207                {
208                   if(( *(subStr-1) == '/' || !strncmp(subStr - 4, "/lib", 4)) &&
209                      (!subStr[nameLen] || !strncmp(subStr + nameLen, ".so", 3)))
210                   {
211                      char * space = strchr(path, ' ');
212                      if(space) *space = 0;
213                      strcpy(fileName, path);
214                      fclose(f);
215                      return true;
216                   }
217                }
218             }
219             else
220             {
221                char name[MAX_FILENAME];
222                GetLastDirectory(path, name);
223                if(!exeName[0] || !strcmp(name, exeName))
224                {
225                   char * space = strchr(path, ' ');
226                   if(space) *space = 0;
227                   strcpy(fileName, path);
228                   fclose(f);
229                   return true;
230                }
231             }
232          }
233       }
234       fclose(f);
235    }
236    if(!name || !name[0])
237    {
238 #if !defined(__linux__)
239       if(!access("/proc/curproc/file", F_OK))
240          strcpy(fileName, "/proc/curproc/file");
241       else
242 #endif
243          strcpy(fileName, exeLocation);
244       return true;
245    }
246 #endif
247    return false;
248 }
249
250 void Instance_COM_Initialize(int argc, char ** argv, char ** parsedCommand, int * argcPtr, char *** argvPtr)
251 {
252 #if !defined(__WIN32__) && !defined(ECERE_BOOTSTRAP)
253    // Disable stdout buffering on Unix
254    setvbuf(stdout, null, _IONBF, 0);
255 #endif
256 #if defined(__WIN32__)
257    *parsedCommand = UTF16toUTF8(GetCommandLineW());
258    *argvPtr = eSystem_New0(sizeof(char *) * 512);
259    *argcPtr = Tokenize(*parsedCommand, 512,(void*)(char **)(*argvPtr), false);
260 #else
261    *argcPtr = argc;
262    *argvPtr = argv;
263 #endif
264 #if defined(__unix__)
265    if(!__thisModule && argv)
266    {
267       getcwd(exeLocation, MAX_LOCATION);
268       PathCat(exeLocation, argv[0]);
269    }
270 #endif
271 }
272
273 void * Instance_Module_Load(const char * libLocation, const char * name, void ** Load, void ** Unload)
274 {
275    char fileName[MAX_LOCATION];
276    char extension[MAX_EXTENSION];
277    void * library = null;
278 #if defined(__unix__) || defined(__APPLE__)
279    int attempts = 0;
280    char * paths[] = { null, "/usr/lib/ec/lib", "/usr/lib32/ec/lib" };
281 #endif
282
283    *Load = null;
284    *Unload = null;
285
286 #if defined(__WIN32__)
287    strcpy(fileName, name);
288    GetExtension(fileName, extension);
289    if(!extension[0])
290       strcat(fileName, ".dll");
291
292    {
293       uint16 _wfileName[MAX_LOCATION];
294       UTF8toUTF16Buffer(fileName, _wfileName, MAX_LOCATION);
295       library = LoadLibraryW(_wfileName);
296    }
297    if(library)
298    {
299 #ifdef _WIN64
300       *Load = (void *)GetProcAddress(library, "__ecereDll_Load");
301       *Unload = (void *)GetProcAddress(library, "__ecereDll_Unload");
302 #else
303       *Load = (void *)GetProcAddress(library, "__ecereDll_Load@4");
304       *Unload = (void *)GetProcAddress(library, "__ecereDll_Unload@4");
305 #endif
306       if(!*Load)
307          FreeLibrary(library);
308    }
309 #elif defined(__unix__) || defined(__APPLE__)
310    if(libLocation)
311       strcpy(fileName, libLocation);
312    else
313       strcpy(fileName, "lib");
314    strcat(fileName, name);
315    GetExtension(fileName, extension);
316    if(!extension[0])
317 #if defined(__APPLE__)
318       strcat(fileName, ".dylib");
319 #else
320       strcat(fileName, ".so");
321 #endif
322
323    library = dlopen(fileName, RTLD_LAZY);
324    while(!library && attempts < sizeof(paths)/sizeof(paths[0]))
325    {
326       if(paths[attempts])
327          strcpy(fileName, paths[attempts++]);
328       else
329       {
330          attempts++;
331 #ifdef DEB_HOST_MULTIARCH
332          strcpy(fileName, DEB_HOST_MULTIARCH);
333          strcat(fileName, "/ec/lib");
334 #else
335          continue;
336 #endif
337       }
338       strcat(fileName, name);
339       GetExtension(fileName, extension);
340       if(!extension[0])
341 #if defined(__APPLE__)
342          strcat(fileName, ".dylib");
343 #else
344          strcat(fileName, ".so");
345 #endif
346       library = dlopen(fileName, RTLD_LAZY);
347    }
348
349    if(library)
350    {
351       *Load = dlsym(library, "__ecereDll_Load");
352       *Unload = dlsym(library, "__ecereDll_Unload");
353       if(!*Load)
354          dlclose(library);
355    }
356 #elif defined(__APPLE__)
357    strcpy(fileName, "lib");
358    strcat(fileName, name);
359    GetExtension(fileName, extension);
360    if(!extension[0])
361       strcat(fileName, ".dylib");
362    {
363       NSObjectFileImage *fileImage;
364       NSObjectFileImageReturnCode returnCode = NSCreateObjectFileImageFromFile(fileName, &fileImage);
365
366       if(returnCode == NSObjectFileImageSuccess)
367       {
368          printf("NSObjectFileImageSuccess!\n");
369          library = NSLinkModule(fileImage,fileName, 
370               NSLINKMODULE_OPTION_RETURN_ON_ERROR
371             | NSLINKMODULE_OPTION_PRIVATE);
372          // NSDestroyObjectFileImage(fileImage);
373          if(library)
374          {
375             *Load = NSAddressOfSymbol(NSLookupSymbolInModule(library, "__ecereDll_Load")); 
376             *Unload = NSAddressOfSymbol(NSLookupSymbolInModule(library, "__ecereDll_Unload"));
377             if(!*Load)
378             {
379                NSUnLinkModule(library, 0);
380             }
381             else
382                printf("Found Load!\n");
383          }
384       }
385       else
386          printf("No Success :(\n");
387    }
388 #endif
389    return library;
390 }
391
392 void Instance_Module_Free(void * library)
393 {
394 #if defined(__WIN32__)
395    if(library)
396       FreeLibrary(library);
397 #elif defined(__unix__) || defined(__APPLE__)
398    if(library)
399       dlclose(library);
400 #endif
401 }
402
403 #if defined(_DEBUG)
404    void InternalModuleLoadBreakpoint()
405    {
406    }
407 #endif