2
// Created by John M McIntosh on 09-11-27.
3
// This file orginally comes from the sqUnixExternalPrims.c written by Ian Piumarta
4
// With additional work for the 3.x and 4.x series of macintosh carbon vms
5
// To preserve the behavior, bugs, etc I decided to copy the code versus a new re-write
7
/* sqUnixExternalPrims.c -- Unix named primitives and loadable modules
9
* Copyright (C) 1996-2009 by Ian Piumarta
10
* All rights reserved.
12
* This file is part of Unix Squeak.
14
* Permission is hereby granted, free of charge, to any person obtaining a copy
15
* of this software and associated documentation files (the "Software"), to deal
16
* in the Software without restriction, including without limitation the rights
17
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
18
* copies of the Software, and to permit persons to whom the Software is
19
* furnished to do so, subject to the following conditions:
21
* The above copyright notice and this permission notice shall be included in
22
* all copies or substantial portions of the Software.
24
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
27
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
29
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
33
/* Author: Ian.Piumarta@INRIA.Fr
35
* Last edited: 2005-04-06 06:09:36 by piumarta on pauillac.hpl.hp.com
37
* Altered by John M McIntosh johnmci@smalltalkconsulting.com Feb 24th, 2006 for os-x carbon support
38
3.8.11b2 load from resource location first, avoid plugins external directory because of intel migration effort issues.
39
3.8.17b1 April 25, 2007, JMM rework for 10.2.8 backwards support using Ian's dl* logic.
40
5.0.0b6 Nov 27, 2009, JMM rework for the 32/64bit 5.0 VM
43
#import "sqSqueakOSXInfoPlistInterface.h"
44
#import "SqueakOSXAppDelegate.h"
47
extern SqueakOSXAppDelegate *gDelegateApp;
49
# define dprintf(ARGS) if (((sqSqueakOSXInfoPlistInterface*) gDelegateApp.squeakApplication.infoPlistInterfaceLogic).SqueakDebug) fprintf ARGS
51
#if defined(HAVE_LIBDL) /* non-starter without this! */
54
#include <sys/param.h>
57
/* get a value for RTLD_NOW, with increasing levels of desperation... */
59
#if !defined(RTLD_NOW)
61
# define RTLD_NOW DL_NOW
62
# elif defined(RTLD_LAZY)
63
# define RTLD_NOW RTLD_LAZY
64
# elif defined(DL_LAZY)
65
# define RTLD_NOW DL_LAZY
67
# warning: defining RTLD_NOW as 1
72
#if !defined(RTLD_GLOBAL)
73
# define RTLD_GLOBAL 0
79
/*** local functions ***/
80
void *ioLoadModuleRaw(char *pluginName);
82
/* Attempt to load the shared library named by the concatenation of prefix,
83
* moduleName and suffix. Answer the new module entry, or 0 if the shared
84
* library could not be loaded.
86
static void *tryLoadingInternals(NSString *libNameString) {
90
const char* libName = [libNameString fileSystemRepresentation];
92
if ((!(err= stat(libName, &buf))) && S_ISDIR(buf.st_mode)) {
93
dprintf((stderr, "ignoring directory: %s\n", libName));
95
dprintf((stderr, "tryLoading %s\n", libName));
96
handle= dlopen(libName, RTLD_NOW | RTLD_GLOBAL);
98
const char* why = dlerror();
99
if ((!err) && (((sqSqueakOSXInfoPlistInterface*) gDelegateApp.squeakApplication.infoPlistInterfaceLogic).SqueakDebug))
100
fprintf(stderr, "ioLoadModule(%s):\n %s\n", libName, why);
108
static void *tryLoading(NSString *dirNameString, char *moduleName)
113
libName = [dirNameString stringByAppendingPathComponent: [NSString stringWithUTF8String: moduleName]];
114
libName = [libName stringByAppendingPathExtension: @"bundle/Contents/MacOS/"];
115
libName = [libName stringByAppendingPathComponent: [NSString stringWithUTF8String: moduleName]];
116
handle = tryLoadingInternals(libName);
120
libName = [dirNameString stringByAppendingPathComponent: [NSString stringWithUTF8String: moduleName]];
121
handle = tryLoadingInternals(libName);
125
if (((sqSqueakOSXInfoPlistInterface*) gDelegateApp.squeakApplication.infoPlistInterfaceLogic).SqueakPluginsBuiltInOrLocalOnly)
128
static char *prefixes[]= { "", "lib", 0 };
129
static char *suffixes[]= { "", "so", "dylib",0 };
130
char **prefix= NULL, **suffix= NULL;
132
for (prefix= prefixes; *prefix; ++prefix)
133
for (suffix= suffixes; *suffix; ++suffix) {
134
libName = [dirNameString stringByAppendingPathComponent: [NSString stringWithUTF8String: *prefix]];
135
libName = [libName stringByAppendingString: [NSString stringWithUTF8String: moduleName]];
136
libName = [libName stringByAppendingPathExtension: [NSString stringWithUTF8String: *suffix]];
138
handle = tryLoadingInternals(libName);
146
/* Find and load the named module. Answer 0 if not found (do NOT fail
149
void *ioLoadModule(char *pluginName) {
150
NSAutoreleasePool * pool = [NSAutoreleasePool new];
151
void* result = ioLoadModuleRaw(pluginName);
156
void *ioLoadModuleRaw(char *pluginName)
160
if ((pluginName == null) || (pluginName[0] == 0x00)) {
161
handle = dlopen(0, RTLD_NOW | RTLD_GLOBAL);
162
if (handle == null) {
163
char * why = dlerror();
164
dprintf((stderr, "ioLoadModule(<intrinsic>): %s\n", why));
166
dprintf((stderr, "loaded: <intrinsic>\n"));
171
/* first, look in the "<Squeak VM directory>Plugins" directory for the library */
172
NSString *pluginDirPath = [[gDelegateApp.squeakApplication.vmPathStringURL path] stringByAppendingPathComponent: @"Plugins/"];
173
NSString *vmDirPath = [[NSBundle mainBundle] resourcePath];
175
if (((sqSqueakOSXInfoPlistInterface*) gDelegateApp.squeakApplication.infoPlistInterfaceLogic).SqueakPluginsBuiltInOrLocalOnly) {
176
if ( (handle= tryLoading( vmDirPath, pluginName)) || (handle= tryLoading( pluginDirPath, pluginName)))
179
if (( handle= tryLoading( pluginDirPath, pluginName))
180
|| (handle= tryLoading( @"./", pluginName))
181
|| (handle= tryLoading( vmDirPath, pluginName))
182
|| (handle= tryLoading( @"", pluginName))
187
// the following is needed so that, for example, the FFI can pick up
188
// things like <cdecl: 'xyz' module: 'CoreServices'>
190
static char *frameworks[]=
193
"/CoreServices.framework/Frameworks",
194
"/ApplicationServices.framework/Frameworks",
195
"/Carbon.framework/Frameworks",
199
static NSString *systemFolder = NULL;
200
char **framework= NULL;
201
char workingData[PATH_MAX+1];
202
size_t pluginNameLength;
203
NSString *path,*path2;
206
struct FSRef frameworksFolderRef;
207
OSErr err = FSFindFolder(kSystemDomain, kFrameworksFolderType, false, &frameworksFolderRef);
209
NSURL *myURLRef = (NSURL *) CFURLCreateFromFSRef(kCFAllocatorDefault, &frameworksFolderRef);
210
systemFolder = [[myURLRef path] retain];
214
pluginNameLength = strlen(pluginName);
215
if (pluginNameLength > 10) {
216
strncpy(workingData,pluginName+pluginNameLength-10,10);
217
workingData[10] = 0x00;
218
if (strcmp(workingData,".framework") == 0) {
219
strncpy(workingData,pluginName,pluginNameLength-10);
220
workingData[pluginNameLength-10] = 0x00;
221
path = [vmDirPath stringByAppendingPathComponent: [NSString stringWithUTF8String: pluginName]];
222
if (((sqSqueakOSXInfoPlistInterface*) gDelegateApp.squeakApplication.infoPlistInterfaceLogic).SqueakPluginsBuiltInOrLocalOnly) {
223
path2 = [path stringByAppendingPathComponent: [NSString stringWithUTF8String: workingData]];
224
if ((handle = tryLoadingInternals(path2)))
227
if ((handle= tryLoading(path, workingData)))
230
path = [pluginDirPath stringByAppendingPathComponent: [NSString stringWithUTF8String: pluginName]];
232
if (((sqSqueakOSXInfoPlistInterface*) gDelegateApp.squeakApplication.infoPlistInterfaceLogic).SqueakPluginsBuiltInOrLocalOnly) {
233
path2 = [path stringByAppendingPathComponent: [NSString stringWithUTF8String: workingData]];
234
if ((handle = tryLoadingInternals(path2)))
237
if ((handle= tryLoading(path, workingData)))
241
path = [systemFolder stringByAppendingPathComponent: [NSString stringWithUTF8String: pluginName]];
242
if (((sqSqueakOSXInfoPlistInterface*) gDelegateApp.squeakApplication.infoPlistInterfaceLogic).SqueakPluginsBuiltInOrLocalOnly) {
243
path2 = [path stringByAppendingPathComponent: [NSString stringWithUTF8String: workingData]];
244
if ((handle = tryLoadingInternals(path2)))
247
if ((handle= tryLoading(path, workingData)))
253
if (((sqSqueakOSXInfoPlistInterface*) gDelegateApp.squeakApplication.infoPlistInterfaceLogic).SqueakPluginsBuiltInOrLocalOnly)
256
for (framework= frameworks; *framework; ++framework) {
257
path = [[systemFolder stringByAppendingPathComponent: [NSString stringWithUTF8String: *framework]]
258
stringByAppendingPathComponent: [NSString stringWithUTF8String: pluginName]];
259
if ((handle= tryLoading(path, pluginName)))
262
path = [systemFolder stringByAppendingPathComponent: [NSString stringWithUTF8String: *framework]];
263
path = [path stringByAppendingPathComponent: [NSString stringWithUTF8String: pluginName]];
264
path = [path stringByAppendingPathExtension: @"framework"];
266
if ((handle= tryLoading(path, pluginName)))
275
/* Find a function in a loaded module. Answer 0 if not found (do NOT
276
* fail the primitive!).
278
void *ioFindExternalFunctionIn(char *lookupName, void *moduleHandle)
280
char buf[NAME_MAX+1];
282
snprintf(buf, sizeof(buf), "%s", lookupName);
283
void *fn = dlsym(moduleHandle, buf);
285
dprintf((stderr, "ioFindExternalFunctionIn(%s, %ld)\n",lookupName, (long) moduleHandle));
287
if ((fn == NULL) && (((sqSqueakOSXInfoPlistInterface*) gDelegateApp.squeakApplication.infoPlistInterfaceLogic).SqueakDebug)
288
&& strcmp(lookupName, "initialiseModule")
289
&& strcmp(lookupName, "shutdownModule")
290
&& strcmp(lookupName, "setInterpreter")
291
&& strcmp(lookupName, "getModuleName")) {
292
char *why = dlerror();
293
fprintf(stderr, "ioFindExternalFunctionIn(%s, %p):\n %s\n",lookupName, moduleHandle, why);
299
/* Free the module with the associated handle. Answer 0 on error (do
300
* NOT fail the primitive!).
302
sqInt ioFreeModule(void *moduleHandle)
304
int results = dlclose(moduleHandle);
307
char* why = dlerror();
308
dprintf((stderr, "ioFreeModule(%ld): %s\n", (long) moduleHandle, why));
b'\\ No newline at end of file'