added SUPPORTDLL define and checks, if any platforms lack support for
[divverent/darkplaces.git] / sys_shared.c
1 #include "quakedef.h"
2
3 #define SUPPORTDLL
4
5 # include <time.h>
6 #ifndef WIN32
7 # include <unistd.h>
8 # include <fcntl.h>
9 #ifdef SUPPORTDLL
10 # include <dlfcn.h>
11 #endif
12 #endif
13
14 static char sys_timestring[128];
15 char *Sys_TimeString(const char *timeformat)
16 {
17         time_t mytime = time(NULL);
18 #if _MSC_VER >= 1400
19         struct tm mytm;
20         localtime_s(&mytm, &mytime);
21         strftime(sys_timestring, sizeof(sys_timestring), timeformat, &mytm);
22 #else
23         strftime(sys_timestring, sizeof(sys_timestring), timeformat, localtime(&mytime));
24 #endif
25         return sys_timestring;
26 }
27
28
29 extern qboolean host_shuttingdown;
30 void Sys_Quit (int returnvalue)
31 {
32         if (COM_CheckParm("-profilegameonly"))
33                 Sys_AllowProfiling(false);
34         host_shuttingdown = true;
35         Host_Shutdown();
36         exit(returnvalue);
37 }
38
39 #if defined(__linux__) || defined(__FreeBSD__)
40 #ifdef __cplusplus
41 extern "C"
42 #endif
43 int moncontrol(int);
44 #endif
45
46 void Sys_AllowProfiling(qboolean enable)
47 {
48 #if defined(__linux__) || defined(__FreeBSD__)
49         moncontrol(enable);
50 #endif
51 }
52
53
54 /*
55 ===============================================================================
56
57 DLL MANAGEMENT
58
59 ===============================================================================
60 */
61
62 qboolean Sys_LoadLibrary (const char** dllnames, dllhandle_t* handle, const dllfunction_t *fcts)
63 {
64 #ifdef SUPPORTDLL
65         const dllfunction_t *func;
66         dllhandle_t dllhandle = 0;
67         unsigned int i;
68
69         if (handle == NULL)
70                 return false;
71
72 #ifndef WIN32
73 #ifdef PREFER_PRELOAD
74         dllhandle = dlopen(NULL, RTLD_LAZY | RTLD_GLOBAL);
75         if(dllhandle)
76         {
77                 for (func = fcts; func && func->name != NULL; func++)
78                         if (!(*func->funcvariable = (void *) Sys_GetProcAddress (dllhandle, func->name)))
79                         {
80                                 dlclose(dllhandle);
81                                 goto notfound;
82                         }
83                 Con_Printf ("All of %s's functions were already linked in! Not loading dynamically...\n", dllnames[0]);
84                 *handle = dllhandle;
85                 return true;
86         }
87 notfound:
88 #endif
89 #endif
90
91         // Initializations
92         for (func = fcts; func && func->name != NULL; func++)
93                 *func->funcvariable = NULL;
94
95         // Try every possible name
96         Con_Printf ("Trying to load library...");
97         for (i = 0; dllnames[i] != NULL; i++)
98         {
99                 Con_Printf (" \"%s\"", dllnames[i]);
100 #ifdef WIN32
101                 dllhandle = LoadLibrary (dllnames[i]);
102 #else
103                 dllhandle = dlopen (dllnames[i], RTLD_LAZY | RTLD_GLOBAL);
104 #endif
105                 if (dllhandle)
106                         break;
107         }
108
109         // see if the names can be loaded relative to the executable path
110         // (this is for Mac OSX which does not check next to the executable)
111         if (!dllhandle && strrchr(com_argv[0], '/'))
112         {
113                 char path[MAX_OSPATH];
114                 strlcpy(path, com_argv[0], sizeof(path));
115                 strrchr(path, '/')[1] = 0;
116                 for (i = 0; dllnames[i] != NULL; i++)
117                 {
118                         char temp[MAX_OSPATH];
119                         strlcpy(temp, path, sizeof(temp));
120                         strlcat(temp, dllnames[i], sizeof(temp));
121                         Con_Printf (" \"%s\"", temp);
122 #ifdef WIN32
123                         dllhandle = LoadLibrary (temp);
124 #else
125                         dllhandle = dlopen (temp, RTLD_LAZY | RTLD_GLOBAL);
126 #endif
127                         if (dllhandle)
128                                 break;
129                 }
130         }
131
132         // No DLL found
133         if (! dllhandle)
134         {
135                 Con_Printf(" - failed.\n");
136                 return false;
137         }
138
139         Con_Printf(" - loaded.\n");
140
141         // Get the function adresses
142         for (func = fcts; func && func->name != NULL; func++)
143                 if (!(*func->funcvariable = (void *) Sys_GetProcAddress (dllhandle, func->name)))
144                 {
145                         Con_Printf ("Missing function \"%s\" - broken library!\n", func->name);
146                         Sys_UnloadLibrary (&dllhandle);
147                         return false;
148                 }
149
150         *handle = dllhandle;
151         return true;
152 #else
153         return false;
154 #endif
155 }
156
157 void Sys_UnloadLibrary (dllhandle_t* handle)
158 {
159 #ifdef SUPPORTDLL
160         if (handle == NULL || *handle == NULL)
161                 return;
162
163 #ifdef WIN32
164         FreeLibrary (*handle);
165 #else
166         dlclose (*handle);
167 #endif
168
169         *handle = NULL;
170 #endif
171 }
172
173 void* Sys_GetProcAddress (dllhandle_t handle, const char* name)
174 {
175 #ifdef SUPPORTDLL
176 #ifdef WIN32
177         return (void *)GetProcAddress (handle, name);
178 #else
179         return (void *)dlsym (handle, name);
180 #endif
181 #else
182         return NULL;
183 #endif
184 }
185