mirror of
https://github.com/gnustep/libs-base.git
synced 2025-04-22 16:33:29 +00:00
Implement lazy evaluation of path to executable.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@22523 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
f6aad79d90
commit
1c89b5daed
2 changed files with 147 additions and 94 deletions
|
@ -2,6 +2,8 @@
|
|||
|
||||
* Source/NSFileManager.m: Ensure that NSBundle is initialised before
|
||||
changing the current directory.
|
||||
* Source/NSBundle.m: Restructure for lazy evaluation of path to
|
||||
executable ... lots of apps never need it.
|
||||
|
||||
2006-02-20 Richard Frith-Macdonald <rfm@gnu.org>
|
||||
|
||||
|
|
|
@ -70,8 +70,8 @@ typedef enum {
|
|||
static NSBundle *_mainBundle = nil;
|
||||
static NSMapTable *_bundles = NULL;
|
||||
|
||||
/* Keep the path to the executable file for finding the main bundle. */
|
||||
static NSString *_executable_path;
|
||||
/* Store the working directory at startup */
|
||||
static NSString *_launchDirectory = nil;
|
||||
|
||||
/*
|
||||
* An empty strings file table for use when localization files can't be found.
|
||||
|
@ -117,12 +117,147 @@ static NSString *library_combo =
|
|||
nil;
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Try to find the absolute path of an executable.
|
||||
* Search all the directoried in the PATH.
|
||||
* The atLaunch flag determines whether '.' is considered to be
|
||||
* the current working directory or the working directory at the
|
||||
* time when the program was launched (technically the directory
|
||||
* at the point when NSBundle was first used ... so programs must
|
||||
* use NSBundle *before* changing their working directories).
|
||||
*/
|
||||
static NSString*
|
||||
AbsolutePathOfExecutable(NSString *path, BOOL atLaunch)
|
||||
{
|
||||
NSFileManager *mgr;
|
||||
NSDictionary *env;
|
||||
NSString *pathlist;
|
||||
NSString *prefix;
|
||||
id patharr;
|
||||
|
||||
path = [path stringByStandardizingPath];
|
||||
if ([path isAbsolutePath])
|
||||
{
|
||||
return path;
|
||||
}
|
||||
|
||||
mgr = [NSFileManager defaultManager];
|
||||
env = [[NSProcessInfo processInfo] environment];
|
||||
pathlist = [env objectForKey:@"PATH"];
|
||||
|
||||
/* Windows 2000 and perhaps others have "Path" not "PATH" */
|
||||
if (pathlist == nil)
|
||||
{
|
||||
pathlist = [env objectForKey:@"Path"];
|
||||
}
|
||||
#if defined(__MINGW32__)
|
||||
patharr = [pathlist componentsSeparatedByString:@";"];
|
||||
#else
|
||||
patharr = [pathlist componentsSeparatedByString:@":"];
|
||||
#endif
|
||||
/* Add . if not already in path */
|
||||
if ([patharr indexOfObject: @"."] == NSNotFound)
|
||||
{
|
||||
patharr = AUTORELEASE([patharr mutableCopy]);
|
||||
[patharr addObject: @"."];
|
||||
}
|
||||
patharr = [patharr objectEnumerator];
|
||||
while ((prefix = [patharr nextObject]))
|
||||
{
|
||||
if ([prefix isEqual:@"."])
|
||||
{
|
||||
if (atLaunch == YES)
|
||||
{
|
||||
prefix = _launchDirectory;
|
||||
}
|
||||
else
|
||||
{
|
||||
prefix = [mgr currentDirectoryPath];
|
||||
}
|
||||
}
|
||||
prefix = [prefix stringByAppendingPathComponent: path];
|
||||
if ([mgr isExecutableFileAtPath: prefix])
|
||||
{
|
||||
return [prefix stringByStandardizingPath];
|
||||
}
|
||||
#if defined(__WIN32__)
|
||||
{
|
||||
NSString *ext = [path pathExtension];
|
||||
|
||||
/* Also add common executable extensions on windows */
|
||||
if (ext == nil || [ext length] == 0)
|
||||
{
|
||||
NSString *wpath;
|
||||
wpath = [prefix stringByAppendingPathExtension: @"exe"];
|
||||
if ([mgr isExecutableFileAtPath: wpath])
|
||||
return [wpath stringByStandardizingPath];
|
||||
wpath = [prefix stringByAppendingPathExtension: @"com"];
|
||||
if ([mgr isExecutableFileAtPath: wpath])
|
||||
return [wpath stringByStandardizingPath];
|
||||
wpath = [prefix stringByAppendingPathExtension: @"cmd"];
|
||||
if ([mgr isExecutableFileAtPath: wpath])
|
||||
return [wpath stringByStandardizingPath];
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the path to this executable.
|
||||
*/
|
||||
static NSString *ExecutablePath()
|
||||
{
|
||||
static NSString *executablePath = nil;
|
||||
static BOOL beenHere = NO;
|
||||
|
||||
if (beenHere == NO)
|
||||
{
|
||||
[load_lock lock];
|
||||
if (beenHere == NO)
|
||||
{
|
||||
#ifdef PROCFS_EXE_LINK
|
||||
executablePath = [[NSFileManager defaultManager]
|
||||
pathContentOfSymbolicLinkAtPath:
|
||||
[NSString stringWithCString: PROCFS_EXE_LINK]];
|
||||
|
||||
/*
|
||||
On some systems, the link is of the form "[device]:inode", which
|
||||
can be used to open the executable, but is useless if you want
|
||||
the path to it. Thus we check that the path is an actual absolute
|
||||
path. (Using '/' here is safe; it isn't the path separator
|
||||
everywhere, but it is on all systems that have PROCFS_EXE_LINK.)
|
||||
*/
|
||||
if ([executablePath length] > 0
|
||||
&& [executablePath characterAtIndex: 0] != '/')
|
||||
{
|
||||
executablePath = nil;
|
||||
}
|
||||
#endif
|
||||
if (executablePath == nil || [executablePath length] == 0)
|
||||
{
|
||||
executablePath
|
||||
= [[[NSProcessInfo processInfo] arguments] objectAtIndex: 0];
|
||||
executablePath = AbsolutePathOfExecutable(executablePath, YES);
|
||||
}
|
||||
|
||||
RETAIN(executablePath);
|
||||
beenHere = YES;
|
||||
}
|
||||
[load_lock unlock];
|
||||
NSCAssert(executablePath != nil, NSInternalInconsistencyException);
|
||||
}
|
||||
return executablePath;
|
||||
}
|
||||
|
||||
/* This function is provided for objc-load.c, although I'm not sure it
|
||||
really needs it (So far only needed if using GNU dld library) */
|
||||
const char *
|
||||
objc_executable_location (void)
|
||||
{
|
||||
return (const char*)[[_executable_path stringByDeletingLastPathComponent]
|
||||
return (const char*)[[ExecutablePath() stringByDeletingLastPathComponent]
|
||||
fileSystemRepresentation];
|
||||
}
|
||||
|
||||
|
@ -323,7 +458,7 @@ _find_framework(NSString *name)
|
|||
*/
|
||||
bundlePath = objc_get_symbol_path (frameworkClass, NULL);
|
||||
|
||||
if ([bundlePath isEqualToString: _executable_path])
|
||||
if ([bundlePath isEqualToString: ExecutablePath()])
|
||||
{
|
||||
/* Ops ... the NSFramework_xxx class is linked in the main
|
||||
* executable. Maybe the framework was statically linked
|
||||
|
@ -574,35 +709,9 @@ _bundle_load_callback(Class theClass, struct objc_category *theCategory)
|
|||
if ((paths != nil) && ([paths count] > 0))
|
||||
system = RETAIN([paths objectAtIndex: 0]);
|
||||
|
||||
_executable_path = nil;
|
||||
#ifdef PROCFS_EXE_LINK
|
||||
_executable_path = [[NSFileManager defaultManager]
|
||||
pathContentOfSymbolicLinkAtPath:
|
||||
[NSString stringWithCString: PROCFS_EXE_LINK]];
|
||||
_launchDirectory = RETAIN([[NSFileManager defaultManager]
|
||||
currentDirectoryPath]);
|
||||
|
||||
/*
|
||||
On some systems, the link is of the form "[device]:inode", which
|
||||
can be used to open the executable, but is useless if you want
|
||||
the path to it. Thus we check that the path is an actual absolute
|
||||
path. (Using '/' here is safe; it isn't the path separator
|
||||
everywhere, but it is on all systems that have PROCFS_EXE_LINK.)
|
||||
*/
|
||||
if ([_executable_path length] > 0
|
||||
&& [_executable_path characterAtIndex: 0] != '/')
|
||||
{
|
||||
_executable_path = nil;
|
||||
}
|
||||
#endif
|
||||
if (_executable_path == nil || [_executable_path length] == 0)
|
||||
{
|
||||
_executable_path =
|
||||
[[[NSProcessInfo processInfo] arguments] objectAtIndex: 0];
|
||||
_executable_path =
|
||||
[self _absolutePathOfExecutable: _executable_path];
|
||||
NSAssert(_executable_path, NSInternalInconsistencyException);
|
||||
}
|
||||
|
||||
RETAIN(_executable_path);
|
||||
_gnustep_bundle = RETAIN([self bundleWithPath: system]);
|
||||
|
||||
#if 0
|
||||
|
@ -773,13 +882,13 @@ _bundle_load_callback(Class theClass, struct objc_category *theCategory)
|
|||
know yet if it's a tool or an application, we always store
|
||||
the executable name here - just in case it turns out it's a
|
||||
tool. */
|
||||
NSString *toolName = [_executable_path lastPathComponent];
|
||||
NSString *toolName = [ExecutablePath() lastPathComponent];
|
||||
#if defined(__WIN32__)
|
||||
toolName = [toolName stringByDeletingPathExtension];
|
||||
#endif
|
||||
|
||||
/* Strip off the name of the program */
|
||||
path = [_executable_path stringByDeletingLastPathComponent];
|
||||
path = [ExecutablePath() stringByDeletingLastPathComponent];
|
||||
|
||||
/* We now need to chop off the extra subdirectories, the library
|
||||
combo and the target cpu/os if they exist. The executable
|
||||
|
@ -1603,7 +1712,7 @@ _bundle_load_callback(Class theClass, struct objc_category *theCategory)
|
|||
}
|
||||
if (self == _mainBundle)
|
||||
{
|
||||
return _executable_path;
|
||||
return ExecutablePath();
|
||||
}
|
||||
object = [[self infoDictionary] objectForKey: @"NSExecutable"];
|
||||
if (object == nil || [object length] == 0)
|
||||
|
@ -1776,65 +1885,7 @@ _bundle_load_callback(Class theClass, struct objc_category *theCategory)
|
|||
|
||||
+ (NSString *) _absolutePathOfExecutable: (NSString *)path
|
||||
{
|
||||
NSFileManager *mgr;
|
||||
NSDictionary *env;
|
||||
NSString *pathlist, *prefix;
|
||||
id patharr;
|
||||
|
||||
path = [path stringByStandardizingPath];
|
||||
if ([path isAbsolutePath])
|
||||
return path;
|
||||
|
||||
mgr = [NSFileManager defaultManager];
|
||||
env = [[NSProcessInfo processInfo] environment];
|
||||
pathlist = [env objectForKey:@"PATH"];
|
||||
|
||||
/* Windows 2000 and perhaps others have "Path" not "PATH" */
|
||||
if (pathlist == nil)
|
||||
{
|
||||
pathlist = [env objectForKey:@"Path"];
|
||||
}
|
||||
#if defined(__MINGW32__)
|
||||
patharr = [pathlist componentsSeparatedByString:@";"];
|
||||
#else
|
||||
patharr = [pathlist componentsSeparatedByString:@":"];
|
||||
#endif
|
||||
/* Add . if not already in path */
|
||||
if ([patharr indexOfObject: @"."] == NSNotFound)
|
||||
{
|
||||
patharr = AUTORELEASE([patharr mutableCopy]);
|
||||
[patharr addObject: @"."];
|
||||
}
|
||||
patharr = [patharr objectEnumerator];
|
||||
while ((prefix = [patharr nextObject]))
|
||||
{
|
||||
if ([prefix isEqual:@"."])
|
||||
prefix = [mgr currentDirectoryPath];
|
||||
prefix = [prefix stringByAppendingPathComponent: path];
|
||||
if ([mgr isExecutableFileAtPath: prefix])
|
||||
return [prefix stringByStandardizingPath];
|
||||
#if defined(__WIN32__)
|
||||
{
|
||||
NSString *ext = [path pathExtension];
|
||||
|
||||
/* Also add common executable extensions on windows */
|
||||
if (ext == nil || [ext length] == 0)
|
||||
{
|
||||
NSString *wpath;
|
||||
wpath = [prefix stringByAppendingPathExtension: @"exe"];
|
||||
if ([mgr isExecutableFileAtPath: wpath])
|
||||
return [wpath stringByStandardizingPath];
|
||||
wpath = [prefix stringByAppendingPathExtension: @"com"];
|
||||
if ([mgr isExecutableFileAtPath: wpath])
|
||||
return [wpath stringByStandardizingPath];
|
||||
wpath = [prefix stringByAppendingPathExtension: @"cmd"];
|
||||
if ([mgr isExecutableFileAtPath: wpath])
|
||||
return [wpath stringByStandardizingPath];
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return nil;
|
||||
return AbsolutePathOfExecutable(path, NO);
|
||||
}
|
||||
|
||||
+ (NSBundle *) gnustepBundle
|
||||
|
|
Loading…
Reference in a new issue