1 #include <sys/stat.h>
2 /****************************************************************
3 Copyright (C) 1998, 1999, 2000 Lucent Technologies
4 All Rights Reserved
5
6 Permission to use, copy, modify, and distribute this software and
7 its documentation for any purpose and without fee is hereby
8 granted, provided that the above copyright notice appear in all
9 copies and that both that the copyright notice and this
10 permission notice and warranty disclaimer appear in supporting
11 documentation, and that the name of Lucent or any of its entities
12 not be used in advertising or publicity pertaining to
13 distribution of the software without specific, written prior
14 permission.
15
16 LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
17 INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
18 IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
19 SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
20 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
21 IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
22 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
23 THIS SOFTWARE.
24 ****************************************************************/
25
26 #ifdef NO_FUNCADD
27 #include "funcadd.h"
28
29 const char *ix_details_ASL[] = {0};
30
31 void
funcadd(AmplExports * ae)32 funcadd(AmplExports *ae)
33 { ae = ae; /* shut up non-use warning */ }
34
35 #else
36
37 #ifdef _WIN32
38 #undef WIN32
39 #define WIN32
40 #endif
41
42 #ifdef WIN32
43 #include "windows.h"
44 #undef void
45 #endif
46
47 #define _POSIX_SOURCE /* for HP-UX */
48
49 #include "stdlib.h" /* for free() */
50 #include "string.h"
51 #include "funcadd.h"
52 #include "arith.h" /* for X64_bit_pointers */
53 #include <sys/types.h>
54 #include <sys/stat.h>
55 #ifndef S_IFREG /*{*/
56 #ifdef __S_IFREG
57 #define S_IFREG __S_IFREG
58 #define S_IFDIR __S_IFDIR
59 #elif defined(_S_IFREG)
60 #define S_IFREG _S_IFREG
61 #define S_IFDIR _S_IFDIR
62 #endif
63 #endif /*}*/
64 #ifdef X64_bit_pointers
65 static char Bits[] = "64", BitsAlt[] = "32";
66 #else
67 static char Bits[] = "32", BitsAlt[] = "64";
68 #endif
69
70 #ifdef Old_APPLE /* formerly __APPLE__, for earlier versions of Mac OS X */
71 #define FUNCADD "_funcadd_ASL"
72 #endif
73 #ifndef FUNCADD
74 #define FUNCADD "funcadd_ASL"
75 #endif
76
77 #ifdef __cplusplus
78 extern "C" {
79 extern int libload_ASL(AmplExports *ae, const char *s, int ns, int warn);
80 #endif
81
82 typedef void Funcadd ANSI((AmplExports*));
83
84 extern void *mymalloc_ASL ANSI((size_t));
85 #undef mymalloc
86 #define mymalloc(x) mymalloc_ASL((size_t)(x))
87
88 const char *ix_details_ASL[] = {
89 "? {show -i options}",
90 "- {do not import functions: do not access amplfunc.dll}",
91 "dir {look for amplfunc.dll in directory dir}",
92 "file {import functions from file rather than amplfunc.dll}",
93 "",
94 "When the x of -ix is suitably quoted, multiple files may appear on",
95 "separate lines or may appear on the same line if each is enclosed",
96 "by single or double quotes.",
97 "",
98 "If no -i option appears but $ampl_funclibs is set, assume",
99 "-i $ampl_funclibs. Otherwise, if $AMPLFUNC is set, assume",
100 "-i $AMPLFUNC. Otherwise look for amplfunc.dll in the",
101 "directory that is current when execution begins.",
102 "",
103 "-ix and -i x are treated alike.",
104 0 };
105 #define afdll afdll_ASL
106 extern int aflibname_ASL ANSI((AmplExports*, const char*, const char*, int, Funcadd*, int, void(*)(void*), void*));
107 extern const char *i_option_ASL;
108
109 #ifdef __cplusplus
110 }
111 #endif
112
113 static int first = 1;
114
115 static int
file_kind(const char * name)116 file_kind(const char *name) /* 1 == regular file, 2 ==> directory; else 0 */
117 {
118 struct stat sb;
119
120 if (stat(name,&sb))
121 return 0;
122 if (sb.st_mode & S_IFDIR)
123 return 2;
124 if (sb.st_mode & S_IFREG)
125 return 1;
126 return 0;
127 }
128
129 #ifdef WIN32 /*{{*/
130
131 #define SLASH '\\'
132 char afdll[] = "\\amplfunc.dll";
133 typedef HINSTANCE shl_t;
134 #define dlopen(x,y) LoadLibrary(x)
135 #define find_dlsym(a,b,c) (a = (Funcadd*)GetProcAddress(b,c))
136 #define dlclose(x) FreeLibrary((HMODULE)x)
137 #define NO_DLERROR
138
139 static int
Abspath(const char * s)140 Abspath(const char *s)
141 {
142 int c = *s;
143 if ((c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z')
144 && s[1] == ':'
145 && (c = s[2]) == '\\' || c == '/')
146 return 1;
147 return 0;
148 }
149
150 #else /*}{ !WIN32 */
151
152 #define SLASH '/'
153
154 char afdll[] = "/amplfunc.dll";
155
156 #define Abspath(s) (*(s) == '/')
157
158 #include "unistd.h" /* for getcwd */
159 #define GetCurrentDirectory(a,b) getcwd(b,(int)(a))
160
161 #ifdef __hpux /*{{*/
162 #include "dl.h"
163 #define dlopen(x,y) shl_load(x, BIND_IMMEDIATE, 0)
164 #define find_dlsym(a,b,c) !shl_findsym(&b, c, TYPE_PROCEDURE, &a)
165 #define dlclose(x) shl_unload((shl_t)x)
166 #define NO_DLERROR
167 #else /*}{*/
168 #ifdef Old_APPLE /*{{*/
169 #include <mach-o/dyld.h>
170 typedef struct {
171 NSObjectFileImage ofi;
172 NSModule m;
173 char *name;
174 } NS_pair;
175 typedef NS_pair *shl_t;
176
177 static void*
find_sym_addr(NS_pair * p,const char * name)178 find_sym_addr(NS_pair *p, const char *name)
179 {
180 NSSymbol nss;
181
182 if (nss = NSLookupSymbolInModule(p->m, name))
183 return NSAddressOfSymbol(nss);
184 return 0;
185 }
186
187 #define find_dlsym(a,b,c) (a = find_sym_addr(b,c))
188
189 static void
dlclose(NS_pair * p)190 dlclose(NS_pair *p)
191 {
192 if (NSUnLinkModule(p->m, NSUNLINKMODULE_OPTION_NONE))
193 NSDestroyObjectFileImage(p->ofi);
194 free(p);
195 }
196 #define NO_DLERROR
197 #else /*}{*/
198 #ifdef __sun__
199 #define __EXTENSIONS__
200 #endif
201 #include "dlfcn.h"
202 typedef void *shl_t;
203 #define find_dlsym(a,b,c) (a = (Funcadd*)dlsym(b,c))
204 #ifdef sun /*{*/
205 #ifndef RTLD_NOW
206 #define RTLD_NOW RTLD_LAZY
207 #endif
208 #endif /* sun }*/
209 #endif /*}} Old_APPLE */
210 #endif /*}} __hpux */
211 #endif /*}} WIN32 */
212
213 #ifdef __cplusplus
214 extern "C" {
215 #endif
216
217 #ifdef WIN32
218 static int
wrong_bits(AmplExports * ae,char * name)219 wrong_bits(AmplExports *ae, char *name)
220 {
221 FILE *f;
222 IMAGE_DOS_HEADER dh;
223 int rc;
224 union { WORD w[2]; DWORD dw; } u;
225 struct {
226 IMAGE_FILE_HEADER ifh;
227 IMAGE_OPTIONAL_HEADER ioh;
228 } h;
229 #ifdef X64_bit_pointers
230 #define Bits_MAGIC 0x20b
231 #else
232 #define Bits_MAGIC 0x10b
233 #endif
234 if (!(f = fopen(name, "rb")))
235 return 1;
236 rc = 0;
237 if (fread(&dh, sizeof(IMAGE_DOS_HEADER), 1, f) != 1
238 || dh.e_magic != IMAGE_DOS_SIGNATURE
239 || fseek(f, dh.e_lfanew, SEEK_SET)
240 || fread(&u, sizeof(u), 1, f) != 1
241 || u.dw != IMAGE_NT_SIGNATURE
242 || fread(&h, sizeof(h), 1, f) != 1
243 || h.ioh.Magic != Bits_MAGIC)
244 rc = 1;
245 fclose(f);
246 return rc;
247 }
248 #undef Bits_MAGIC
249 #endif
250
251 static shl_t
dl_open(AmplExports * ae,char * name,int * warned,int * pns)252 dl_open(AmplExports *ae, char *name, int *warned, int *pns)
253 {
254 FILE *f;
255 char *d, *d0, *dz, *s;
256 const char *cs;
257 int ns;
258 shl_t h;
259 #ifdef Old_APPLE
260 NS_pair p;
261 #endif
262 d = d0 = dz = 0;
263 for(s = name; *s; ++s)
264 switch(*s) {
265 case '.':
266 d = s;
267 break;
268 case '/':
269 #ifdef WIN32
270 case '\\':
271 #endif
272 d = 0;
273 }
274 ns = s - name;
275 if (d
276 && d - name > 3
277 && d[-3] == '_') {
278 if (d[-2] == BitsAlt[0]
279 && d[-1] == BitsAlt[1]) {
280 d[-2] = Bits[0];
281 d[-1] = Bits[1];
282 dz = d;
283 d = 0;
284 }
285 else if (d[-2] == Bits[0]
286 && d[-1] == Bits[1]) {
287 dz = d;
288 d = 0;
289 }
290 }
291 tryagain:
292 #ifdef Old_APPLE
293 NSObjectFileImageReturnCode irc;
294 irc = NSCreateObjectFileImageFromFile(name,&p.ofi);
295 h = 0;
296 if (irc == NSObjectFileImageSuccess) {
297 p.m = NSLinkModule(p.ofi, name,
298 NSLINKMODULE_OPTION_BINDNOW
299 | NSLINKMODULE_OPTION_PRIVATE
300 | NSLINKMODULE_OPTION_RETURN_ON_ERROR);
301 if (!p.m)
302 fprintf(stderr, "NSLinkModule(\"%s\") failed.\n", name);
303 else {
304 h = (NS_pair*)mymalloc(sizeof(NS_pair) + strlen(name) + 1);
305 strcpy(p.name = (char*)(h+1), name);
306 memcpy(h, &p, sizeof(NS_pair));
307 }
308 }
309 else if (irc != NSObjectFileImageAccess)
310 fprintf(stderr,
311 "return %d from NSCreateObjectFileImageFromFile(\"%s\")\n",
312 irc, name);
313 #else
314 #ifdef WIN32 /*{*/ /* make sure name is for the right number of bits */
315 if (wrong_bits(ae, name))
316 h = 0;
317 else
318 #endif /*}*/
319 h = dlopen(name, RTLD_NOW);
320 #endif
321 if (!h) {
322 if (d) {
323 do s[3] = s[0]; while(--s >= d);
324 d[0] = '_';
325 d[1] = Bits[0];
326 d[2] = Bits[1];
327 d0 = d;
328 d = 0;
329 ns += 3;
330 goto tryagain;
331 }
332 if (dz) {
333 for(d = dz-3; (*d = *dz); ++d, ++dz);
334 d = dz = 0;
335 goto tryagain;
336 }
337 if (d0)
338 for(s = d0; (s[0] = s[3]); ++s);
339 if (!*warned && (f = fopen(name,"rb"))) {
340 fclose(f);
341 if (file_kind(name) == 1) {
342 #ifdef NO_DLERROR
343 *warned = 1;
344 fprintf(Stderr, "Cannot load library \"%s\".\n", name);
345 #else
346 /* get dlerror() for original name */
347 if (!d0 || !(h = dlopen(name, RTLD_NOW))) {
348 *warned = 1;
349 fprintf(Stderr, "Cannot load library \"%s\"", name);
350 cs = dlerror();
351 fprintf(Stderr, cs ? ":\n%s\n" : ".\n", cs);
352 }
353 #endif
354 }
355 }
356 }
357 *pns = ns;
358 return h;
359 }
360
361 static void
dl_close(void * h)362 dl_close(void *h)
363 {
364 #ifdef CLOSE_AT_RESET
365 first = 1;
366 #endif
367 if (h)
368 dlclose(h);
369 }
370
371 int
libload_ASL(AmplExports * ae,const char * s,int ns,int warn)372 libload_ASL(AmplExports *ae, const char *s, int ns, int warn)
373 {
374 Funcadd *fa;
375 char buf0[2048], *buf;
376 int ns1, rc, rcnf, warned;
377 shl_t h;
378 size_t n, nx;
379
380 nx = 0;
381 buf = buf0;
382 if (!Abspath(s)) {
383 if (!GetCurrentDirectory(sizeof(buf0),buf0))
384 return 2;
385 nx = strlen(buf0);
386 }
387 n = ns + sizeof(afdll) + nx + 3; /* +3 for inserting _32 or _64 */
388 if (n > sizeof(buf0)) {
389 buf = (char*)mymalloc(n);
390 if (nx)
391 memcpy(buf, buf0, nx);
392 }
393 if (nx)
394 buf[nx++] = SLASH;
395 strncpy(buf+nx, s, ns);
396 buf[nx+ns] = 0;
397 rc = warned = 0;
398 rcnf = warn >> 1;
399 warn &= 1;
400 if ((h = dl_open(ae, buf, &warned, &ns1))) {
401 found:
402 if (find_dlsym(fa, h, FUNCADD)
403 || find_dlsym(fa, h, "funcadd")) {
404 #ifdef CLOSE_AT_RESET
405 aflibname_ASL(ae,buf,buf+nx,ns1-nx,fa,0,dl_close,h);
406 /* -DCLOSE_AT_RESET is for use in shared */
407 /* libraries, such as MATLAB mex functions, */
408 /* that may be loaded and unloaded several */
409 /* times during execution of the program. */
410 #else
411 aflibname_ASL(ae,buf,buf+nx,ns1-nx,fa,1,dl_close,h);
412 #endif
413 }
414 else {
415 fprintf(stderr, "Could not find funcadd in %s\n", buf);
416 dl_close(h);
417 rc = 3;
418 }
419 }
420 else if (warn) {
421 if (!warned) {
422 strcpy(buf+nx+ns, afdll);
423 if ((h = dl_open(ae, buf, &warned, &ns1)))
424 goto found;
425 }
426 if (warned)
427 rc = 2;
428 else
429 goto notfound;
430 }
431 else {
432 notfound:
433 rc = rcnf;
434 if (warn) {
435 buf[nx+ns] = 0;
436 if (file_kind(buf) == 2) {
437 buf[nx+ns] = SLASH;
438 fprintf(Stderr, "Cannot find library \"%s\".\n", buf);
439 }
440 else
441 fprintf(Stderr, "Cannot find library \"%.*s\".\n", ns, s);
442 }
443 }
444 if (buf != buf0)
445 free(buf);
446 return rc;
447 }
448
449 static int
libloop(AmplExports * ae,const char * s)450 libloop(AmplExports *ae, const char *s)
451 {
452 const char *s1, *s2;
453 int c, ns, rc;
454
455 for(rc = 0;; s = s1) {
456 while(*s <= ' ')
457 if (!*s++)
458 goto ret;
459 if (*s == '"' || *s == '\'') {
460 c = *s++;
461 for(s1 = s; *s1 != c; ++s1)
462 if (!*s1)
463 goto ret;
464 if (s1 == s)
465 goto ret;
466 s2 = s1++;
467 }
468 else {
469 for(s1 = s; *++s1 >= ' '; );
470 for(s2 = s1; s2[-1] == ' '; --s2);
471 }
472 ns = s2 - s;
473 if (libload_ASL(ae, s, ns, 1))
474 ++rc;
475 }
476 ret:
477 return rc;
478 }
479
480 int n_badlibs_ASL;
481
482 void
funcadd(AmplExports * ae)483 funcadd(AmplExports *ae)
484 {
485 const char *s;
486 int nb = 0;
487
488 if (first) {
489 first = 0;
490 if ((s = i_option_ASL)) {
491 if (!*s || (*s == '-' && !s[1]))
492 return;
493 nb += libloop(ae, s);
494 }
495 else
496 nb = libload_ASL(ae, afdll+1, (int)sizeof(afdll)-2, 0);
497 }
498 n_badlibs_ASL = nb;
499 }
500
501 #ifdef __cplusplus
502 }
503 #endif
504
505 #endif /* NO_FUNCADD */
506