handle failure to clone the log filehandle when cloning the Imager context
[imager.git] / dynaload.c
1 #if defined(OS_hpux)
2 #include <dl.h>
3 typedef shl_t minthandle_t;
4 #elif defined(WIN32)
5 #define WIN32_LEAN_AND_MEAN
6 #include <windows.h>
7 typedef HMODULE minthandle_t;
8 #undef WIN32_LEAN_AND_MEAN
9 #else 
10 #include <dlfcn.h>
11 typedef void *minthandle_t; 
12 #endif 
13
14 #include "ext.h"
15
16 struct DSO_handle_tag {
17   minthandle_t handle;
18   char *filename;
19   func_ptr *function_list;
20 };
21
22 #include "imager.h"
23 #include "dynaload.h"
24 /* #include "XSUB.h"  so we can compile on threaded perls */
25 #include "imageri.h"
26
27 static im_context_t
28 do_get_context(void) {
29   return im_get_context();
30 }
31
32 static symbol_table_t symbol_table=
33   {
34     i_has_format,
35     ICL_set_internal,
36     ICL_info,
37     do_get_context,
38     im_img_empty_ch,
39     i_img_exorcise,
40     i_img_info,
41     i_img_setmask,
42     i_img_getmask,
43     i_box,
44     i_line,
45     i_arc,
46     i_copyto,
47     i_copyto_trans,
48     i_rubthru
49   };
50
51
52 /*
53   Dynamic loading works like this:
54   dynaload opens the shared object and
55   loads all the functions into an array of functions
56   it returns a string from the dynamic function that
57   can be supplied to the parser for evaling.
58 */
59
60 void
61 DSO_call(DSO_handle *handle,int func_index,HV* hv) {
62   mm_log((1,"DSO_call(handle %p, func_index %d, hv %p)\n",
63           handle, func_index, hv));
64   (handle->function_list[func_index].iptr)((void*)hv);
65 }
66
67 func_ptr *
68 DSO_funclist(DSO_handle *handle) {
69   return handle->function_list;
70 }
71
72
73 #if defined( OS_hpux )
74
75 void*
76 DSO_open(char* file,char** evalstring) {
77   shl_t tt_handle;
78   void *d_handle,**plugin_symtab,**plugin_utiltab;
79   int  rc,*iptr, (*fptr)(int);
80   func_ptr *function_list;
81   DSO_handle *dso_handle;
82   void (*f)(void *s,void *u); /* these will just have to be void for now */
83   int i;
84
85   *evalstring=NULL;
86
87   mm_log( (1,"DSO_open(file '%s' (0x%08X), evalstring 0x%08X)\n",file,file,evalstring) );
88
89   if ( (tt_handle = shl_load(file, BIND_DEFERRED,0L)) == NULL) return NULL; 
90   if ( (shl_findsym(&tt_handle, I_EVALSTR,TYPE_UNDEFINED,(void*)evalstring))) return NULL;
91
92   /*
93   if ( (shl_findsym(&tt_handle, "symbol_table",TYPE_UNDEFINED,(void*)&plugin_symtab))) return NULL;
94   if ( (shl_findsym(&tt_handle, "util_table",TYPE_UNDEFINED,&plugin_utiltab))) return NULL;
95   (*plugin_symtab)=&symbol_table;
96   (*plugin_utiltab)=&i_UTIL_table;
97   */
98
99   if ( (shl_findsym(&tt_handle, I_INSTALL_TABLES ,TYPE_UNDEFINED, &f ))) return NULL; 
100  
101   mm_log( (1,"Calling install_tables\n") );
102   f(&symbol_table,&i_UTIL_table);
103   mm_log( (1,"Call ok.\n") ); 
104  
105   if ( (shl_findsym(&tt_handle, I_FUNCTION_LIST ,TYPE_UNDEFINED,(func_ptr*)&function_list))) return NULL; 
106   if ( (dso_handle=(DSO_handle*)malloc(sizeof(DSO_handle))) == NULL) /* checked 17jul05 tonyc */
107     return NULL;
108
109   dso_handle->handle=tt_handle; /* needed to close again */
110   dso_handle->function_list=function_list;
111   if ( (dso_handle->filename=(char*)malloc(strlen(file)+1)) == NULL) { /* checked 17jul05 tonyc */
112     free(dso_handle); return NULL;
113   }
114   strcpy(dso_handle->filename,file);
115
116   mm_log((1,"DSO_open <- (0x%X)\n",dso_handle));
117   return (void*)dso_handle;
118 }
119
120 undef_int
121 DSO_close(void *ptr) {
122   DSO_handle *handle=(DSO_handle*) ptr;
123   mm_log((1,"DSO_close(ptr 0x%X)\n",ptr));
124   return !shl_unload((handle->handle));
125 }
126
127 #elif defined(WIN32)
128
129 void *
130 DSO_open(char *file, char **evalstring) {
131   HMODULE d_handle;
132   func_ptr *function_list;
133   DSO_handle *dso_handle;
134   
135   void (*f)(void *s,void *u); /* these will just have to be void for now */
136
137   mm_log( (1,"DSO_open(file '%s' (%p), evalstring %p)\n",file,file,evalstring) );
138
139   *evalstring = NULL;
140   if ((d_handle = LoadLibrary(file)) == NULL) {
141     mm_log((1, "DSO_open: LoadLibrary(%s) failed: %lu\n", file, GetLastError()));
142     return NULL;
143   }
144   if ( (*evalstring = (char *)GetProcAddress(d_handle, I_EVALSTR)) == NULL) {
145     mm_log((1,"DSO_open: GetProcAddress didn't fine '%s': %lu\n", I_EVALSTR, GetLastError()));
146     FreeLibrary(d_handle);
147     return NULL;
148   }
149   if ((f = (void (*)(void *, void*))GetProcAddress(d_handle, I_INSTALL_TABLES)) == NULL) {
150     mm_log((1, "DSO_open: GetProcAddress didn't find '%s': %lu\n", I_INSTALL_TABLES, GetLastError()));
151     FreeLibrary(d_handle);
152     return NULL;
153   }
154   mm_log((1, "Calling install tables\n"));
155   f(&symbol_table, &i_UTIL_table);
156   mm_log((1, "Call ok\n"));
157   
158   if ( (function_list = (func_ptr *)GetProcAddress(d_handle, I_FUNCTION_LIST)) == NULL) {
159     mm_log((1, "DSO_open: GetProcAddress didn't find '%s': %lu\n", I_FUNCTION_LIST, GetLastError()));
160     FreeLibrary(d_handle);
161     return NULL;
162   }
163   if ( (dso_handle = (DSO_handle*)malloc(sizeof(DSO_handle))) == NULL) { /* checked 17jul05 tonyc */
164     mm_log( (1, "DSO_Open: out of memory\n") );
165     FreeLibrary(d_handle);
166     return NULL;
167   }
168   dso_handle->handle=d_handle; /* needed to close again */
169   dso_handle->function_list=function_list;
170   if ( (dso_handle->filename=(char*)malloc(strlen(file)+1)) == NULL) { /* checked 17jul05 tonyc */
171     free(dso_handle);
172     FreeLibrary(d_handle); 
173     return NULL; 
174   }
175   strcpy(dso_handle->filename,file);
176
177   mm_log( (1,"DSO_open <- %p\n",dso_handle) );
178   return (void*)dso_handle;
179
180 }
181
182 undef_int
183 DSO_close(void *ptr) {
184   DSO_handle *handle = (DSO_handle *)ptr;
185   BOOL result = FreeLibrary(handle->handle);
186   free(handle->filename);
187   free(handle);
188
189   return result;
190 }
191
192 #else
193
194 /* OS/2 has no dlclose; Perl doesn't provide one. */
195 #ifdef __EMX__ /* OS/2 */
196 int
197 dlclose(minthandle_t h) {
198   return DosFreeModule(h) ? -1 : 0;
199 }
200 #endif /* __EMX__ */
201
202 void*
203 DSO_open(char* file,char** evalstring) {
204   void *d_handle;
205   func_ptr *function_list;
206   DSO_handle *dso_handle;
207
208   void (*f)(void *s,void *u); /* these will just have to be void for now */
209   
210   *evalstring=NULL;
211
212   mm_log( (1,"DSO_open(file '%s' (%p), evalstring %p)\n",
213            file, file, evalstring) );
214
215   if ( (d_handle = dlopen(file, RTLD_LAZY)) == NULL) {
216     mm_log( (1,"DSO_open: dlopen failed: %s.\n",dlerror()) );
217     return NULL;
218   }
219
220   if ( (*evalstring = (char *)dlsym(d_handle, I_EVALSTR)) == NULL) {
221     mm_log( (1,"DSO_open: dlsym didn't find '%s': %s.\n",I_EVALSTR,dlerror()) );
222     return NULL;
223   }
224
225   /*
226
227     I'll just leave this thing in here for now if I need it real soon
228
229    mm_log( (1,"DSO_open: going to dlsym '%s'\n", I_SYMBOL_TABLE ));
230    if ( (plugin_symtab = dlsym(d_handle, I_SYMBOL_TABLE)) == NULL) {
231      mm_log( (1,"DSO_open: dlsym didn't find '%s': %s.\n",I_SYMBOL_TABLE,dlerror()) );
232      return NULL;
233    }
234   
235    mm_log( (1,"DSO_open: going to dlsym '%s'\n", I_UTIL_TABLE ));
236     if ( (plugin_utiltab = dlsym(d_handle, I_UTIL_TABLE)) == NULL) {
237      mm_log( (1,"DSO_open: dlsym didn't find '%s': %s.\n",I_UTIL_TABLE,dlerror()) );
238      return NULL;
239    }
240
241   */
242
243   f = (void(*)(void *s,void *u))dlsym(d_handle, I_INSTALL_TABLES);
244   mm_log( (1,"DSO_open: going to dlsym '%s'\n", I_INSTALL_TABLES ));
245   if ( (f = (void(*)(void *s,void *u))dlsym(d_handle, I_INSTALL_TABLES)) == NULL) {
246     mm_log( (1,"DSO_open: dlsym didn't find '%s': %s.\n",I_INSTALL_TABLES,dlerror()) );
247     return NULL;
248   }
249
250   mm_log( (1,"Calling install_tables\n") );
251   f(&symbol_table,&i_UTIL_table);
252   mm_log( (1,"Call ok.\n") );
253
254   /* (*plugin_symtab)=&symbol_table;
255      (*plugin_utiltab)=&i_UTIL_table; */
256   
257   mm_log( (1,"DSO_open: going to dlsym '%s'\n", I_FUNCTION_LIST ));
258   if ( (function_list=(func_ptr *)dlsym(d_handle, I_FUNCTION_LIST)) == NULL) {
259     mm_log( (1,"DSO_open: dlsym didn't find '%s': %s.\n",I_FUNCTION_LIST,dlerror()) );
260     return NULL;
261   }
262   
263   if ( (dso_handle=(DSO_handle*)malloc(sizeof(DSO_handle))) == NULL) /* checked 17jul05 tonyc */
264     return NULL;
265   
266   dso_handle->handle=d_handle; /* needed to close again */
267   dso_handle->function_list=function_list;
268   if ( (dso_handle->filename=(char*)malloc(strlen(file)+1)) == NULL) { /* checked 17jul05 tonyc */
269     free(dso_handle); 
270     return NULL;
271   }
272   strcpy(dso_handle->filename,file);
273
274   mm_log( (1,"DSO_open <- %p\n",dso_handle) );
275   return (void*)dso_handle;
276 }
277
278 undef_int
279 DSO_close(void *ptr) {
280   DSO_handle *handle;
281   mm_log((1,"DSO_close(ptr %p)\n",ptr));
282   handle=(DSO_handle*) ptr;
283   return !dlclose(handle->handle);
284 }
285
286 #endif
287