2005-03-15 04:24:26 +00:00
|
|
|
/* Implementation of filesystem & path-related functions for GNUstep
|
|
|
|
Copyright (C) 1996-2004 Free Software Foundation, Inc.
|
2005-03-15 06:36:21 +00:00
|
|
|
|
2005-03-15 04:24:26 +00:00
|
|
|
Written by: Andrew Kachites McCallum <address@hidden>
|
2005-03-03 16:04:22 +00:00
|
|
|
Created: May 1996
|
2005-03-15 04:24:26 +00:00
|
|
|
Rewrite by: Sheldon Gill
|
|
|
|
Date: Jan 2004
|
2005-10-13 10:11:56 +00:00
|
|
|
Rewrites by: Richard Frith-Macdonald
|
|
|
|
Date: 2004-2005
|
2005-03-15 06:36:21 +00:00
|
|
|
|
2005-03-03 16:04:22 +00:00
|
|
|
This file is part of the GNUstep Base Library.
|
|
|
|
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
|
|
modify it under the terms of the GNU Library General Public
|
|
|
|
License as published by the Free Software Foundation; either
|
|
|
|
version 2 of the License, or (at your option) any later version.
|
2005-03-15 06:36:21 +00:00
|
|
|
|
2005-03-03 16:04:22 +00:00
|
|
|
This library is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
Library General Public License for more details.
|
2005-03-15 06:36:21 +00:00
|
|
|
|
2005-03-03 16:04:22 +00:00
|
|
|
You should have received a copy of the GNU Library General Public
|
|
|
|
License along with this library; if not, write to the Free
|
2005-05-22 03:32:16 +00:00
|
|
|
Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111 USA.
|
2005-03-03 16:04:22 +00:00
|
|
|
|
2005-03-15 04:24:26 +00:00
|
|
|
<title>NSPathUtilities function reference</title>
|
2005-03-03 16:04:22 +00:00
|
|
|
$Date$ $Revision$
|
|
|
|
*/
|
|
|
|
|
2005-03-15 04:24:26 +00:00
|
|
|
/**
|
|
|
|
<unit>
|
|
|
|
<heading>Path Utility Functions</heading>
|
|
|
|
<p>
|
|
|
|
Path utilities provides functions to dynamically discover paths
|
|
|
|
for the platform the application is running on.
|
|
|
|
This avoids the need for hard coding paths, making porting easier
|
|
|
|
and also allowing for places to change without breaking
|
|
|
|
applications.
|
|
|
|
(why do this? Well imagine we're running GNUstep 1 and the new
|
|
|
|
wonderful GNUstep 2 becomes available but we're not sure of it
|
|
|
|
yet. You could install /GNUstep/System2/ and have applications
|
|
|
|
use which ever System you wanted at the time...)
|
|
|
|
</p>
|
|
|
|
<p>
|
|
|
|
On unix systems, the paths are initialised by reading a configuration
|
|
|
|
file. Something like "/etc/GNUstep/GNUstep.conf". This provides the basic
|
|
|
|
information required by the library to establish all locations required.
|
|
|
|
</p>
|
|
|
|
<p>
|
2005-10-13 10:11:56 +00:00
|
|
|
On windows, the paths may also (as a fallback) be initialised by
|
|
|
|
reading information from the windows registry.
|
2005-03-15 04:24:26 +00:00
|
|
|
HKEY_LOCAL_MACHINE\Software\GNU\GNUstep contains the machine wide
|
|
|
|
definititions for system paths.
|
|
|
|
</p>
|
|
|
|
<p>
|
|
|
|
See <REF "filesystem.pdf">GNUstep File System Heirarchy</REF> document
|
|
|
|
for more information and detailed descriptions.</p>
|
|
|
|
</unit>
|
|
|
|
*/
|
|
|
|
|
2005-03-03 16:04:22 +00:00
|
|
|
#include "config.h"
|
|
|
|
#include "GNUstepBase/preface.h"
|
|
|
|
#include "Foundation/NSObjCRuntime.h"
|
|
|
|
#include "Foundation/NSString.h"
|
|
|
|
#include "Foundation/NSPathUtilities.h"
|
|
|
|
#include "Foundation/NSException.h"
|
|
|
|
#include "Foundation/NSArray.h"
|
2005-03-15 04:24:26 +00:00
|
|
|
#include "Foundation/NSDebug.h"
|
2005-03-03 16:04:22 +00:00
|
|
|
#include "Foundation/NSDictionary.h"
|
|
|
|
#include "Foundation/NSFileManager.h"
|
|
|
|
#include "Foundation/NSProcessInfo.h"
|
|
|
|
#include "Foundation/NSString.h"
|
|
|
|
#include "Foundation/NSValue.h"
|
|
|
|
#include "Foundation/NSLock.h"
|
|
|
|
#include "Foundation/NSUserDefaults.h"
|
|
|
|
#include "GNUstepBase/GSCategories.h"
|
2005-03-15 04:24:26 +00:00
|
|
|
#if defined(__WIN32__)
|
|
|
|
#include "GNUstepBase/Win32_Utilities.h"
|
|
|
|
#endif
|
2005-03-03 16:04:22 +00:00
|
|
|
|
|
|
|
#include "GSPrivate.h"
|
2005-03-15 04:24:26 +00:00
|
|
|
#include "GNUstepBase/Win32Support.h"
|
2005-03-03 16:04:22 +00:00
|
|
|
|
|
|
|
#ifdef HAVE_UNISTD_H
|
2005-03-15 04:24:26 +00:00
|
|
|
#include <unistd.h> // for getuid()
|
2005-03-03 16:04:22 +00:00
|
|
|
#endif
|
|
|
|
#ifdef HAVE_PWD_H
|
|
|
|
#include <pwd.h> // for getpwnam()
|
|
|
|
#endif
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
|
2005-03-15 04:24:26 +00:00
|
|
|
/* Defines used to highlight design decisions. It's possible these could
|
|
|
|
be made compile time or even user configurable.
|
|
|
|
*/
|
|
|
|
#define OPTION_PLATFORM_SUPPORT // To find platform specific things
|
|
|
|
|
2005-03-03 16:04:22 +00:00
|
|
|
#define lowlevelstringify(X) #X
|
|
|
|
#define stringify(X) lowlevelstringify(X)
|
|
|
|
|
2005-03-15 04:24:26 +00:00
|
|
|
/* The global configuration file. The real value is read from config.h */
|
2005-10-15 07:19:11 +00:00
|
|
|
#ifndef GNUSTEP_CONFIG_FILE
|
|
|
|
# define GNUSTEP_CONFIG_FILE /etc/GNUstep/GNUstep.conf
|
2005-03-15 04:24:26 +00:00
|
|
|
#endif
|
2005-03-17 14:48:32 +00:00
|
|
|
|
2005-07-31 08:18:19 +00:00
|
|
|
static NSString *gnustep_target_cpu =
|
|
|
|
#ifdef GNUSTEP_TARGET_CPU
|
|
|
|
@GNUSTEP_TARGET_CPU;
|
|
|
|
#else
|
|
|
|
nil;
|
|
|
|
#endif
|
|
|
|
static NSString *gnustep_target_os =
|
|
|
|
#ifdef GNUSTEP_TARGET_OS
|
|
|
|
@GNUSTEP_TARGET_OS;
|
|
|
|
#else
|
|
|
|
nil;
|
|
|
|
#endif
|
|
|
|
static NSString *library_combo =
|
|
|
|
#ifdef LIBRARY_COMBO
|
|
|
|
@LIBRARY_COMBO;
|
|
|
|
#else
|
|
|
|
nil;
|
|
|
|
#endif
|
|
|
|
static NSString *gnustep_flattened =
|
|
|
|
#ifdef GNUSTEP_FLATTENED
|
|
|
|
@GNUSTEP_FLATTENED;
|
|
|
|
#else
|
|
|
|
nil;
|
|
|
|
#endif
|
|
|
|
|
2005-03-17 14:48:32 +00:00
|
|
|
#define MGR() [NSFileManager defaultManager]
|
|
|
|
|
2005-03-18 09:42:54 +00:00
|
|
|
/*
|
|
|
|
* NB. use fprintf() rather than NSLog() to avoid possibility of recursion
|
|
|
|
* when features of NSLog() cause patrh utilities to be used.
|
|
|
|
*/
|
|
|
|
#define PrintOnce(format, args...) \
|
|
|
|
do { static BOOL beenHere = NO; if (beenHere == NO) {\
|
|
|
|
beenHere = YES; \
|
|
|
|
fprintf(stderr, format, ## args); }} while (0)
|
|
|
|
|
2005-03-15 04:24:26 +00:00
|
|
|
/* ------------------ */
|
|
|
|
/* Internal variables */
|
|
|
|
/* ------------------ */
|
2005-03-17 14:48:32 +00:00
|
|
|
|
2005-10-16 11:48:54 +00:00
|
|
|
static NSString *gnustepConfigPath = nil;
|
2005-03-15 04:24:26 +00:00
|
|
|
|
|
|
|
/* We read these four paths only once */
|
2005-03-17 14:48:32 +00:00
|
|
|
static NSString *gnustepUserRoot = nil; /* GNUSTEP_USER_ROOT path */
|
|
|
|
static NSString *gnustepLocalRoot = nil; /* GNUSTEP_LOCAL_ROOT path */
|
|
|
|
static NSString *gnustepNetworkRoot = nil; /* GNUSTEP_NETWORK_ROOT path */
|
|
|
|
static NSString *gnustepSystemRoot = nil; /* GNUSTEP_SYSTEM_ROOT path */
|
2005-03-15 04:24:26 +00:00
|
|
|
|
2005-10-15 07:19:11 +00:00
|
|
|
static NSString *gnustepUserDir = nil;
|
|
|
|
static NSString *gnustepUserHome = nil;
|
|
|
|
static NSString *gnustepUserConfigFile = nil;
|
|
|
|
static NSString *gnustepUserDefaultsDir = nil;
|
2005-03-15 04:24:26 +00:00
|
|
|
|
|
|
|
static NSString *theUserName = nil; /* The user's login name */
|
|
|
|
static NSString *tempDir = nil; /* user's temporary directory */
|
|
|
|
|
|
|
|
#ifdef OPTION_PLATFORM_SUPPORT
|
2005-03-17 14:48:32 +00:00
|
|
|
static NSString *osSysPrefs = nil;
|
|
|
|
static NSString *osSysApps = nil;
|
|
|
|
static NSString *osSysLibs = nil;
|
|
|
|
static NSString *osSysAdmin = nil;
|
2005-03-15 04:24:26 +00:00
|
|
|
|
2005-03-17 14:48:32 +00:00
|
|
|
static NSString *platformResources = nil;
|
|
|
|
static NSString *platformApps = nil;
|
|
|
|
static NSString *platformLibs = nil;
|
|
|
|
static NSString *platformAdmin = nil;
|
2005-03-15 04:24:26 +00:00
|
|
|
|
2005-03-17 14:48:32 +00:00
|
|
|
static NSString *localResources = nil;
|
|
|
|
static NSString *localApps = nil;
|
|
|
|
static NSString *localLibs = nil;
|
2005-03-15 04:24:26 +00:00
|
|
|
|
|
|
|
/* Keys for Platform support in conf-file. */
|
|
|
|
#define SYS_APPS @"SYS_APPS"
|
|
|
|
#define SYS_LIBS @"SYS_LIBS"
|
|
|
|
#define SYS_PREFS @"SYS_PREFS"
|
|
|
|
#define SYS_ADMIN @"SYS_ADMIN"
|
|
|
|
#define SYS_RESOURCES @"SYS_RESOURCES"
|
|
|
|
|
|
|
|
#define PLATFORM_APPS @"PLATFORM_APPS"
|
|
|
|
#define PLATFORM_LIBS @"PLATFORM_LIBS"
|
|
|
|
#define PLATFORM_ADMIN @"PLATFORM_ADMIN"
|
|
|
|
#define PLATFORM_RESOURCES @"PLATFORM_RESOURCES"
|
|
|
|
|
|
|
|
#define PLATFORM_LOCAL_APPS @"PLATFORM_LOCAL_APPS"
|
|
|
|
#define PLATFORM_LOCAL_LIBS @"PLATFORM_LOCAL_LIBS"
|
|
|
|
#define PLATFORM_LOCAL_ADMIN @"PLATFORM_LOCAL_ADMIN"
|
|
|
|
#define PLATFORM_LOCAL_RESOURCES @"PLATFORM_LOCAL_RESOURCES"
|
|
|
|
#endif /* OPTION_PLATFORM_SUPPORT */
|
|
|
|
|
|
|
|
/* ============================= */
|
|
|
|
/* Internal function prototypes. */
|
|
|
|
/* ============================= */
|
|
|
|
|
2005-10-15 07:19:11 +00:00
|
|
|
static NSDictionary* GNUstepConfig(void);
|
2005-03-15 04:24:26 +00:00
|
|
|
|
2005-10-15 07:19:11 +00:00
|
|
|
static BOOL ParseConfigurationFile(NSString *name, NSMutableDictionary *dict);
|
2005-03-15 04:24:26 +00:00
|
|
|
|
2005-03-17 15:27:52 +00:00
|
|
|
static void InitialisePathUtilities(void);
|
|
|
|
static void ShutdownPathUtilities(void);
|
2005-03-15 04:24:26 +00:00
|
|
|
|
2005-10-14 10:51:50 +00:00
|
|
|
/* Conditionally assign an object from a dictionary to var
|
|
|
|
* We don't need to retain val before releasing var, because we
|
|
|
|
* can be sure that if var is val it is retained by the dictionary
|
|
|
|
* as well as being retained when it was first placed in var.
|
|
|
|
*/
|
2005-10-13 10:11:56 +00:00
|
|
|
#define ASSIGN_IF_SET(var, dictionary, key) ({\
|
2005-10-14 10:51:50 +00:00
|
|
|
id val = [dictionary objectForKey: key];\
|
|
|
|
if (val != nil)\
|
|
|
|
{\
|
|
|
|
RELEASE(var);\
|
|
|
|
var = RETAIN(val);\
|
|
|
|
}\
|
|
|
|
})
|
|
|
|
|
2005-10-16 11:48:54 +00:00
|
|
|
#define ASSIGN_PATH(var, dictionary, key) ({\
|
|
|
|
id val = getPathConfig(dictionary, key);\
|
|
|
|
if (val != nil)\
|
|
|
|
{\
|
|
|
|
RELEASE(var);\
|
|
|
|
var = RETAIN(val);\
|
|
|
|
}\
|
|
|
|
})
|
|
|
|
|
2005-10-14 10:51:50 +00:00
|
|
|
/* Conditionally assign lval to var only if var is nil */
|
|
|
|
#define TEST_ASSIGN(var, lval) ({\
|
|
|
|
if ((var == nil)&&(lval != nil))\
|
|
|
|
{\
|
|
|
|
var = RETAIN(lval);\
|
|
|
|
}\
|
|
|
|
})
|
2005-03-03 16:04:22 +00:00
|
|
|
|
2005-10-16 11:48:54 +00:00
|
|
|
/* Get a full path string */
|
2005-03-15 04:24:26 +00:00
|
|
|
static inline NSString *
|
2005-10-16 11:48:54 +00:00
|
|
|
getPath(NSString *path)
|
2005-03-03 16:04:22 +00:00
|
|
|
{
|
2005-10-16 11:48:54 +00:00
|
|
|
if ([path hasPrefix: @"./"] == YES)
|
|
|
|
{
|
|
|
|
path = [gnustepConfigPath stringByAppendingPathComponent:
|
|
|
|
[path substringFromIndex: 2]];
|
|
|
|
}
|
|
|
|
return path;
|
|
|
|
}
|
2005-03-15 04:24:26 +00:00
|
|
|
|
2005-10-16 11:48:54 +00:00
|
|
|
/* Get a full path string from a dictionary */
|
|
|
|
static inline NSString *
|
|
|
|
getPathConfig(NSDictionary *dict, NSString *key)
|
|
|
|
{
|
|
|
|
NSString *path;
|
2005-03-03 16:04:22 +00:00
|
|
|
|
2005-03-15 04:24:26 +00:00
|
|
|
path = [dict objectForKey: key];
|
2005-10-16 11:48:54 +00:00
|
|
|
path = getPath(path);
|
2005-03-15 04:24:26 +00:00
|
|
|
return path;
|
|
|
|
}
|
|
|
|
|
2005-10-15 07:19:11 +00:00
|
|
|
static void ExtractValuesFromConfig(NSDictionary *config)
|
2005-03-15 04:24:26 +00:00
|
|
|
{
|
2005-10-16 11:48:54 +00:00
|
|
|
ASSIGN_PATH(gnustepSystemRoot, config, @"GNUSTEP_SYSTEM_ROOT");
|
|
|
|
ASSIGN_PATH(gnustepNetworkRoot, config, @"GNUSTEP_NETWORK_ROOT");
|
|
|
|
ASSIGN_PATH(gnustepLocalRoot, config, @"GNUSTEP_LOCAL_ROOT");
|
2005-10-15 07:19:11 +00:00
|
|
|
|
2005-10-16 11:48:54 +00:00
|
|
|
ASSIGN_PATH(gnustepUserHome, config, @"GNUSTEP_USER_HOME");
|
2005-10-15 07:19:11 +00:00
|
|
|
ASSIGN_IF_SET(gnustepUserDir, config, @"GNUSTEP_USER_DIR");
|
|
|
|
ASSIGN_IF_SET(gnustepUserDefaultsDir, config, @"GNUSTEP_USER_DEFAULTS_DIR");
|
|
|
|
|
|
|
|
#ifdef OPTION_PLATFORM_SUPPORT
|
2005-10-16 11:48:54 +00:00
|
|
|
ASSIGN_PATH(osSysPrefs, config, SYS_PREFS);
|
|
|
|
ASSIGN_PATH(osSysApps, config, SYS_APPS);
|
|
|
|
ASSIGN_PATH(osSysLibs, config, SYS_LIBS);
|
|
|
|
ASSIGN_PATH(osSysAdmin, config, SYS_ADMIN);
|
|
|
|
|
|
|
|
ASSIGN_PATH(platformResources, config, PLATFORM_RESOURCES);
|
|
|
|
ASSIGN_PATH(platformApps, config, PLATFORM_APPS);
|
|
|
|
ASSIGN_PATH(platformLibs, config, PLATFORM_LIBS);
|
|
|
|
ASSIGN_PATH(platformAdmin, config, PLATFORM_ADMIN);
|
|
|
|
|
|
|
|
ASSIGN_PATH(localResources, config, PLATFORM_LOCAL_RESOURCES);
|
|
|
|
ASSIGN_PATH(localApps, config, PLATFORM_LOCAL_APPS);
|
|
|
|
ASSIGN_PATH(localLibs, config, PLATFORM_LOCAL_LIBS);
|
2005-10-15 07:19:11 +00:00
|
|
|
#endif /* OPTION_PLATFORM SUPPORT */
|
|
|
|
|
|
|
|
/*
|
2005-10-16 11:48:54 +00:00
|
|
|
* Set default locations for user files if necessary.
|
2005-10-15 07:19:11 +00:00
|
|
|
*/
|
|
|
|
if (gnustepUserDir == nil)
|
2005-03-15 04:24:26 +00:00
|
|
|
{
|
2005-10-15 07:19:11 +00:00
|
|
|
ASSIGN(gnustepUserDir, @"GNUstep");
|
2005-03-15 04:24:26 +00:00
|
|
|
}
|
2005-10-16 04:08:12 +00:00
|
|
|
if (gnustepUserDefaultsDir == nil)
|
|
|
|
{
|
|
|
|
ASSIGN(gnustepUserDefaultsDir, @"GNUstep/Defaults");
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
* Set the user root from the user home and the user dir
|
|
|
|
*/
|
2005-10-15 07:19:11 +00:00
|
|
|
ASSIGN(gnustepUserRoot,
|
|
|
|
[gnustepUserHome stringByAppendingPathComponent: gnustepUserDir]);
|
2005-03-15 04:24:26 +00:00
|
|
|
|
2005-10-16 04:08:12 +00:00
|
|
|
/*
|
2005-10-16 11:48:54 +00:00
|
|
|
* Finally set default locations for the essential paths if required.
|
2005-10-16 04:08:12 +00:00
|
|
|
*/
|
2005-10-15 07:19:11 +00:00
|
|
|
if (gnustepSystemRoot == nil)
|
2005-03-15 04:24:26 +00:00
|
|
|
{
|
2005-10-15 07:19:11 +00:00
|
|
|
gnustepSystemRoot = [NSString stringWithCString:\
|
|
|
|
STRINGIFY(GNUSTEP_INSTALL_PREFIX)];
|
2005-10-16 11:48:54 +00:00
|
|
|
gnustepSystemRoot = RETAIN(getPath(gnustepSystemRoot));
|
2005-10-15 07:19:11 +00:00
|
|
|
}
|
|
|
|
if (gnustepNetworkRoot == nil)
|
|
|
|
{
|
|
|
|
gnustepNetworkRoot = [NSString stringWithCString:\
|
2005-10-16 11:48:54 +00:00
|
|
|
STRINGIFY(GNUSTEP_INSTALL_PREFIX)];
|
|
|
|
gnustepNetworkRoot = RETAIN(getPath(gnustepNetworkRoot));
|
2005-10-15 07:19:11 +00:00
|
|
|
}
|
|
|
|
if (gnustepLocalRoot == nil)
|
|
|
|
{
|
|
|
|
gnustepLocalRoot = [NSString stringWithCString:\
|
2005-10-16 11:48:54 +00:00
|
|
|
STRINGIFY(GNUSTEP_INSTALL_PREFIX)];
|
|
|
|
gnustepLocalRoot = RETAIN(getPath(gnustepLocalRoot));
|
2005-10-15 07:19:11 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Function to return the system-wide configuration
|
|
|
|
*/
|
|
|
|
static NSDictionary*
|
|
|
|
GNUstepConfig(void)
|
|
|
|
{
|
|
|
|
static NSDictionary *config = nil;
|
2005-03-17 14:48:32 +00:00
|
|
|
|
2005-10-15 07:19:11 +00:00
|
|
|
if (config == nil)
|
|
|
|
{
|
|
|
|
[gnustep_global_lock lock];
|
|
|
|
if (config == nil)
|
2005-03-17 14:48:32 +00:00
|
|
|
{
|
2005-10-15 07:19:11 +00:00
|
|
|
NSMutableDictionary *conf = nil;
|
|
|
|
|
|
|
|
NS_DURING
|
2005-03-17 14:48:32 +00:00
|
|
|
{
|
2005-10-16 11:48:54 +00:00
|
|
|
NSString *file;
|
|
|
|
|
2005-10-15 07:19:11 +00:00
|
|
|
conf = [[NSMutableDictionary alloc] initWithCapacity: 32];
|
|
|
|
|
|
|
|
/* Now we source the configuration file if it exists */
|
|
|
|
#ifndef OPTION_NO_ENVIRONMENT
|
2005-10-16 11:48:54 +00:00
|
|
|
file = [[[NSProcessInfo processInfo] environment]
|
2005-10-15 07:19:11 +00:00
|
|
|
objectForKey: @"GNUSTEP_CONFIG_FILE"];
|
|
|
|
#endif
|
2005-10-16 11:48:54 +00:00
|
|
|
if (file == nil)
|
2005-10-12 06:15:15 +00:00
|
|
|
{
|
2005-10-16 11:48:54 +00:00
|
|
|
file = [NSString stringWithCString:
|
2005-10-15 07:19:11 +00:00
|
|
|
stringify(GNUSTEP_CONFIG_FILE)];
|
2005-10-12 06:15:15 +00:00
|
|
|
}
|
2005-10-16 11:48:54 +00:00
|
|
|
file = [file stringByStandardizingPath];
|
|
|
|
gnustepConfigPath = [file stringByDeletingLastPathComponent];
|
|
|
|
RETAIN(gnustepConfigPath);
|
|
|
|
ParseConfigurationFile(file, conf);
|
2005-10-15 07:19:11 +00:00
|
|
|
|
|
|
|
/* System admins may force the user and defaults paths by
|
|
|
|
* setting GNUSTEP_USER_CONFIG_FILE to be an empty string.
|
|
|
|
* If they simply don't define it at all, we assign a default.
|
2005-10-12 06:15:15 +00:00
|
|
|
*/
|
2005-10-15 07:19:11 +00:00
|
|
|
if ([conf objectForKey: @"GNUSTEP_USER_CONFIG_FILE"] == nil)
|
2005-10-12 06:15:15 +00:00
|
|
|
{
|
2005-10-15 07:19:11 +00:00
|
|
|
[conf setObject: @".GNUstep.conf"
|
|
|
|
forKey: @"GNUSTEP_USER_CONFIG_FILE"];
|
2005-10-12 06:15:15 +00:00
|
|
|
}
|
2005-10-15 07:19:11 +00:00
|
|
|
config = [conf copy];
|
|
|
|
DESTROY(conf);
|
|
|
|
gnustepUserConfigFile
|
|
|
|
= [config objectForKey: @"GNUSTEP_USER_CONFIG_FILE"];
|
|
|
|
}
|
|
|
|
NS_HANDLER
|
|
|
|
{
|
|
|
|
[gnustep_global_lock unlock];
|
|
|
|
config = nil;
|
|
|
|
DESTROY(conf);
|
|
|
|
[localException raise];
|
2005-03-17 14:48:32 +00:00
|
|
|
}
|
2005-10-15 07:19:11 +00:00
|
|
|
NS_ENDHANDLER
|
2005-03-17 14:48:32 +00:00
|
|
|
}
|
2005-10-15 07:19:11 +00:00
|
|
|
[gnustep_global_lock unlock];
|
2005-03-15 04:24:26 +00:00
|
|
|
}
|
2005-10-15 07:19:11 +00:00
|
|
|
return config;
|
|
|
|
}
|
2005-03-15 04:24:26 +00:00
|
|
|
|
2005-10-15 07:19:11 +00:00
|
|
|
/*
|
|
|
|
* Function to return the configuration for the named user
|
|
|
|
*/
|
|
|
|
static NSDictionary*
|
|
|
|
GNUstepUserConfig(NSString *name)
|
|
|
|
{
|
|
|
|
NSMutableDictionary *conf;
|
|
|
|
NSString *file;
|
|
|
|
NSString *home;
|
|
|
|
|
|
|
|
conf = [GNUstepConfig() mutableCopy];
|
|
|
|
file = gnustepUserConfigFile;
|
|
|
|
home = NSHomeDirectoryForUser(name);
|
|
|
|
ParseConfigurationFile([home stringByAppendingPathComponent: file], conf);
|
|
|
|
/*
|
|
|
|
* We don't let the user config file override the home directory for
|
|
|
|
* the user ... that would be inconsistent as we have already used
|
|
|
|
* that directory. Similarly, we don't permit overriding of the
|
|
|
|
* users config file name ... we make sure it's the one we just used.
|
|
|
|
*/
|
|
|
|
[conf setObject: home
|
|
|
|
forKey: [@"GNUSTEP_USER_HOME_" stringByAppendingString: name]];
|
|
|
|
[conf setObject: home forKey: @"GNUSTEP_USER_HOME"];
|
|
|
|
[conf setObject: gnustepUserConfigFile forKey: @"GNUSTEP_USER_CONFIG_FILE"];
|
|
|
|
return AUTORELEASE(conf);
|
2005-03-15 04:24:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Initialise all things required by this module */
|
2005-03-17 15:27:52 +00:00
|
|
|
static void InitialisePathUtilities(void)
|
2005-03-15 04:24:26 +00:00
|
|
|
{
|
2005-10-15 07:19:11 +00:00
|
|
|
NSMutableDictionary *userConfig = nil;
|
|
|
|
|
2005-10-12 08:40:48 +00:00
|
|
|
if (gnustepSystemRoot != nil)
|
2005-03-15 04:24:26 +00:00
|
|
|
{
|
2005-10-12 08:40:48 +00:00
|
|
|
return; // Protect from multiple calls
|
|
|
|
}
|
2005-10-12 07:03:18 +00:00
|
|
|
|
2005-10-15 07:19:11 +00:00
|
|
|
[gnustep_global_lock lock];
|
|
|
|
|
2005-10-12 08:40:48 +00:00
|
|
|
/* Set up our root paths */
|
|
|
|
NS_DURING
|
|
|
|
{
|
2005-10-15 09:18:02 +00:00
|
|
|
BOOL shouldLoadUserConfig = YES;
|
|
|
|
|
2005-10-15 07:19:11 +00:00
|
|
|
userConfig = [GNUstepConfig() mutableCopy];
|
|
|
|
ASSIGNCOPY(gnustepUserHome, NSHomeDirectoryForUser(NSUserName()));
|
2005-10-15 09:18:02 +00:00
|
|
|
#ifdef HAVE_GETEUID
|
|
|
|
/*
|
|
|
|
* A program which is running setuid cannot be trusted
|
|
|
|
* to pick up user specific config.
|
|
|
|
*/
|
|
|
|
if (getuid() != geteuid())
|
|
|
|
{
|
|
|
|
shouldLoadUserConfig = NO;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
if (shouldLoadUserConfig == YES)
|
|
|
|
{
|
|
|
|
NSString *file;
|
|
|
|
|
|
|
|
file = [gnustepUserHome stringByAppendingPathComponent:
|
|
|
|
gnustepUserConfigFile];
|
|
|
|
ParseConfigurationFile(file, userConfig);
|
|
|
|
}
|
2005-10-15 07:19:11 +00:00
|
|
|
ExtractValuesFromConfig(userConfig);
|
|
|
|
DESTROY(userConfig);
|
2005-10-12 17:40:40 +00:00
|
|
|
|
2005-03-15 04:24:26 +00:00
|
|
|
#if defined(__WIN32__)
|
2005-10-15 07:19:11 +00:00
|
|
|
{
|
|
|
|
HKEY regkey;
|
|
|
|
/* Initialise Win32 things if on that platform */
|
|
|
|
Win32Initialise(); // should be called by DLL_PROCESS_ATTACH
|
|
|
|
|
|
|
|
regkey = Win32OpenRegistry(HKEY_LOCAL_MACHINE,
|
2005-10-12 08:40:48 +00:00
|
|
|
"\\Software\\GNU\\GNUstep");
|
2005-10-15 07:19:11 +00:00
|
|
|
if (regkey != (HKEY)NULL)
|
|
|
|
{
|
|
|
|
TEST_ASSIGN(gnustepSystemRoot,
|
|
|
|
Win32NSStringFromRegistry(regkey, @"GNUSTEP_SYSTEM_ROOT"));
|
|
|
|
TEST_ASSIGN(gnustepNetworkRoot,
|
|
|
|
Win32NSStringFromRegistry(regkey, @"GNUSTEP_NETWORK_ROOT"));
|
|
|
|
TEST_ASSIGN(gnustepLocalRoot,
|
|
|
|
Win32NSStringFromRegistry(regkey, @"GNUSTEP_LOCAL_ROOT"));
|
|
|
|
RegCloseKey(regkey);
|
|
|
|
}
|
2005-03-15 04:24:26 +00:00
|
|
|
#if 0
|
2005-10-15 07:19:11 +00:00
|
|
|
// Not implemented yet
|
|
|
|
platformApps = Win32FindDirectory(CLSID_APPS);
|
|
|
|
platformLibs = Win32FindDirectory(CLSID_LIBS);
|
2005-03-15 04:24:26 +00:00
|
|
|
#endif
|
2005-10-15 07:19:11 +00:00
|
|
|
}
|
2005-03-17 15:27:52 +00:00
|
|
|
#endif
|
2005-03-15 04:24:26 +00:00
|
|
|
|
2005-10-12 08:40:48 +00:00
|
|
|
[gnustep_global_lock unlock];
|
2005-03-15 04:24:26 +00:00
|
|
|
}
|
2005-10-12 08:40:48 +00:00
|
|
|
NS_HANDLER
|
|
|
|
{
|
|
|
|
/* unlock then re-raise the exception */
|
|
|
|
[gnustep_global_lock unlock];
|
2005-10-15 07:19:11 +00:00
|
|
|
DESTROY(userConfig);
|
2005-10-12 08:40:48 +00:00
|
|
|
[localException raise];
|
|
|
|
}
|
|
|
|
NS_ENDHANDLER
|
2005-03-15 04:24:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Close down and release all things allocated.
|
|
|
|
*/
|
2005-03-17 15:27:52 +00:00
|
|
|
static void ShutdownPathUtilities(void)
|
2005-03-15 04:24:26 +00:00
|
|
|
{
|
2005-10-12 07:03:18 +00:00
|
|
|
DESTROY(gnustepSystemRoot);
|
|
|
|
DESTROY(gnustepNetworkRoot);
|
|
|
|
DESTROY(gnustepLocalRoot);
|
|
|
|
DESTROY(gnustepUserRoot);
|
2005-03-15 04:24:26 +00:00
|
|
|
|
2005-10-15 07:19:11 +00:00
|
|
|
DESTROY(gnustepUserHome);
|
|
|
|
DESTROY(gnustepUserConfigFile);
|
|
|
|
DESTROY(gnustepUserDefaultsDir);
|
2005-03-15 04:24:26 +00:00
|
|
|
|
|
|
|
#ifdef OPTION_PLATFORM_SUPPORT
|
2005-10-12 07:03:18 +00:00
|
|
|
DESTROY(osSysPrefs);
|
|
|
|
DESTROY(osSysApps);
|
|
|
|
DESTROY(osSysLibs);
|
|
|
|
DESTROY(osSysAdmin);
|
|
|
|
|
|
|
|
DESTROY(platformResources);
|
|
|
|
DESTROY(platformApps);
|
|
|
|
DESTROY(platformLibs);
|
|
|
|
DESTROY(platformAdmin);
|
|
|
|
|
|
|
|
DESTROY(localResources);
|
|
|
|
DESTROY(localApps);
|
|
|
|
DESTROY(localLibs);
|
2005-03-15 04:24:26 +00:00
|
|
|
#endif /* OPTION_PLATFORM SUPPORT */
|
|
|
|
|
2005-10-12 07:03:18 +00:00
|
|
|
DESTROY(tempDir);
|
2005-03-15 04:24:26 +00:00
|
|
|
|
|
|
|
/* Shutdown Win32 support */
|
|
|
|
Win32Finalise();
|
2005-03-03 16:04:22 +00:00
|
|
|
}
|
|
|
|
|
2005-03-15 04:24:26 +00:00
|
|
|
|
2005-03-03 16:04:22 +00:00
|
|
|
/**
|
2005-03-15 04:24:26 +00:00
|
|
|
* Reads a file and expects it to be in basic unix "conf" style format with
|
2005-10-13 10:11:56 +00:00
|
|
|
* one key = value per line (the format a unix shell can 'source' in order
|
|
|
|
* to define shell variables).<br />
|
2005-10-14 10:51:50 +00:00
|
|
|
* Attempts to mimic the escape sequence and quoting conventions of standard
|
|
|
|
* shells, so that a config file sourced by the make package will produce
|
|
|
|
* the same results as one parsed by this function.<br />
|
|
|
|
* The value may be any quoted string (or an unquoted string containing no
|
|
|
|
* white space).<br />
|
2005-03-15 04:24:26 +00:00
|
|
|
* Lines beginning with a hash '#' are deemed comment lines and ignored.<br/ >
|
2005-10-13 10:11:56 +00:00
|
|
|
* The backslash character may be used as an escape character anywhere
|
|
|
|
* in the file except within a singly quoted string
|
2005-10-14 10:51:50 +00:00
|
|
|
* (where it is taken literally).<<br />
|
|
|
|
* A backslash followed immediately by a newline (except in a singly
|
|
|
|
* quoted string) is removed completely along with the newline ... it
|
|
|
|
* thus serves to join lines so that they are treated as a single line.<br />
|
2005-10-13 10:11:56 +00:00
|
|
|
* NB. Since windows uses backslash characters in paths, it is a good
|
|
|
|
* idea to specify path values in the config file as singly quoted
|
|
|
|
* strings to avoid having to double all occurrances of the backslash.<br />
|
2005-10-14 10:51:50 +00:00
|
|
|
* Returns a dictionary of the (key,value) pairs.<br/ >
|
2005-03-03 16:04:22 +00:00
|
|
|
*/
|
2005-10-15 07:19:11 +00:00
|
|
|
static BOOL
|
|
|
|
ParseConfigurationFile(NSString *fileName, NSMutableDictionary *dict)
|
2005-03-03 16:04:22 +00:00
|
|
|
{
|
2005-03-17 14:48:32 +00:00
|
|
|
NSDictionary *attributes;
|
2005-03-15 04:24:26 +00:00
|
|
|
NSString *file;
|
2005-10-14 10:51:50 +00:00
|
|
|
unsigned l;
|
|
|
|
unichar *src;
|
|
|
|
unichar *dst;
|
|
|
|
unichar *end;
|
|
|
|
unichar *spos;
|
|
|
|
unichar *dpos;
|
|
|
|
BOOL newLine = YES;
|
2005-10-14 14:03:13 +00:00
|
|
|
BOOL wantKey = YES;
|
|
|
|
BOOL wantVal = NO;
|
2005-10-14 10:51:50 +00:00
|
|
|
NSString *key = nil;
|
2005-03-15 04:24:26 +00:00
|
|
|
|
2005-03-17 14:48:32 +00:00
|
|
|
if ([MGR() isReadableFileAtPath: fileName] == NO)
|
|
|
|
{
|
2005-10-15 07:19:11 +00:00
|
|
|
return NO;
|
2005-03-17 14:48:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
attributes = [MGR() fileAttributesAtPath: fileName traverseLink: YES];
|
|
|
|
if (([attributes filePosixPermissions] & 022) != 0)
|
|
|
|
{
|
2005-10-09 10:41:53 +00:00
|
|
|
#if defined(__WIN32__)
|
|
|
|
fprintf(stderr, "The file '%S' is writable by someone other than"
|
|
|
|
" its owner.\nIgnoring it.\n",
|
|
|
|
(const unichar*)[fileName fileSystemRepresentation]);
|
|
|
|
#else
|
2005-03-17 14:48:32 +00:00
|
|
|
fprintf(stderr, "The file '%s' is writable by someone other than"
|
|
|
|
" its owner.\nIgnoring it.\n", [fileName fileSystemRepresentation]);
|
2005-10-09 10:41:53 +00:00
|
|
|
#endif
|
2005-10-15 07:19:11 +00:00
|
|
|
return NO;
|
2005-03-17 14:48:32 +00:00
|
|
|
}
|
|
|
|
|
2005-03-15 04:24:26 +00:00
|
|
|
if (dict == nil)
|
|
|
|
{
|
2005-10-15 07:19:11 +00:00
|
|
|
[NSException raise: NSInvalidArgumentException
|
|
|
|
format: @"No destination dictionary supplied"];
|
2005-03-15 04:24:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
file = [NSString stringWithContentsOfFile: fileName];
|
2005-10-14 10:51:50 +00:00
|
|
|
l = [file length];
|
|
|
|
src = (unichar*)NSZoneMalloc(NSDefaultMallocZone(), sizeof(unichar) * l);
|
|
|
|
spos = src;
|
|
|
|
end = src + l;
|
|
|
|
dst = (unichar*)NSZoneMalloc(NSDefaultMallocZone(), sizeof(unichar) * l);
|
|
|
|
dpos = dst;
|
|
|
|
[file getCharacters: src];
|
|
|
|
|
|
|
|
while (spos < end)
|
2005-03-03 16:04:22 +00:00
|
|
|
{
|
2005-10-14 10:51:50 +00:00
|
|
|
/*
|
|
|
|
* Step past any whitespace ... including blank lines
|
|
|
|
*/
|
|
|
|
while (spos < end)
|
2005-03-17 14:48:32 +00:00
|
|
|
{
|
2005-10-14 10:51:50 +00:00
|
|
|
if (*spos == '\\')
|
2005-03-17 14:48:32 +00:00
|
|
|
{
|
2005-10-14 10:51:50 +00:00
|
|
|
spos++;
|
|
|
|
if (spos >= end)
|
|
|
|
{
|
|
|
|
break; // At end of file ... odd but not fatal
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (*spos > ' ')
|
|
|
|
{
|
|
|
|
break; // OK ... found a non space character.
|
|
|
|
}
|
|
|
|
if (*spos == '\r' || *spos == '\n')
|
|
|
|
{
|
|
|
|
newLine = YES;
|
|
|
|
}
|
|
|
|
spos++;
|
|
|
|
}
|
2005-03-17 14:48:32 +00:00
|
|
|
|
2005-10-14 10:51:50 +00:00
|
|
|
/*
|
|
|
|
* Handle any comments .. hash on a new line.
|
|
|
|
*/
|
|
|
|
if (newLine == YES)
|
|
|
|
{
|
2005-10-14 14:03:13 +00:00
|
|
|
if (wantVal == YES)
|
2005-10-14 10:51:50 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* On a newline ...so the last key had no value set.
|
2005-10-14 14:03:13 +00:00
|
|
|
* Put an empty value in the dictionary.
|
2005-10-14 10:51:50 +00:00
|
|
|
*/
|
|
|
|
[dict setObject: @"" forKey: key];
|
|
|
|
DESTROY(key);
|
2005-10-14 14:03:13 +00:00
|
|
|
wantVal = NO;
|
2005-10-14 10:51:50 +00:00
|
|
|
}
|
|
|
|
if (spos < end && *spos == '#')
|
|
|
|
{
|
|
|
|
// Got a comment ... ignore remainder of line.
|
|
|
|
while (spos < end && *spos != '\n' && *spos != '\r')
|
|
|
|
{
|
|
|
|
spos++;
|
|
|
|
}
|
|
|
|
continue; // restart loop ... skip space at start of line
|
|
|
|
}
|
|
|
|
newLine = NO;
|
2005-10-14 14:03:13 +00:00
|
|
|
wantKey = YES;
|
2005-10-14 10:51:50 +00:00
|
|
|
}
|
2005-03-17 14:48:32 +00:00
|
|
|
|
2005-10-14 10:51:50 +00:00
|
|
|
if (*spos == '=')
|
|
|
|
{
|
2005-10-14 14:03:13 +00:00
|
|
|
if (wantKey == NO)
|
2005-10-14 10:51:50 +00:00
|
|
|
{
|
2005-10-14 14:03:13 +00:00
|
|
|
wantVal = YES;
|
2005-10-14 10:51:50 +00:00
|
|
|
}
|
|
|
|
spos++;
|
|
|
|
}
|
|
|
|
else if (*spos == '\'')
|
|
|
|
{
|
|
|
|
spos++;
|
|
|
|
while (spos < end)
|
|
|
|
{
|
|
|
|
if (*spos == '\'')
|
2005-10-13 10:11:56 +00:00
|
|
|
{
|
2005-10-14 10:51:50 +00:00
|
|
|
spos++;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
*dpos++ = *spos++;
|
|
|
|
}
|
2005-10-14 14:03:13 +00:00
|
|
|
if (wantVal == YES)
|
2005-10-14 10:51:50 +00:00
|
|
|
{
|
2005-10-14 14:03:13 +00:00
|
|
|
NSString *val = [NSString alloc];
|
|
|
|
|
|
|
|
val = [val initWithCharacters: dst length: dpos - dst];
|
|
|
|
[dict setObject: val forKey: key];
|
2005-10-14 10:51:50 +00:00
|
|
|
DESTROY(key);
|
2005-10-14 14:03:13 +00:00
|
|
|
DESTROY(val);
|
|
|
|
wantVal = NO;
|
2005-10-14 10:51:50 +00:00
|
|
|
}
|
|
|
|
dpos = dst; // reset output buffer
|
|
|
|
}
|
|
|
|
else if (*spos == '"')
|
|
|
|
{
|
|
|
|
spos++;
|
|
|
|
while (spos < end)
|
|
|
|
{
|
|
|
|
BOOL escaped = NO;
|
2005-10-13 10:11:56 +00:00
|
|
|
|
2005-10-14 10:51:50 +00:00
|
|
|
if (*spos == '\\')
|
|
|
|
{
|
|
|
|
spos++;
|
|
|
|
if (spos >= end)
|
2005-10-13 10:11:56 +00:00
|
|
|
{
|
2005-10-14 10:51:50 +00:00
|
|
|
break; // Unexpected end of file
|
|
|
|
}
|
|
|
|
if (*spos == '\n')
|
|
|
|
{
|
|
|
|
spos++;
|
|
|
|
continue; // escaped newline is removed.
|
|
|
|
}
|
|
|
|
if (*spos == '\r')
|
|
|
|
{
|
|
|
|
spos++;
|
|
|
|
if (spos < end && *spos == '\n')
|
2005-10-13 10:11:56 +00:00
|
|
|
{
|
2005-10-14 10:51:50 +00:00
|
|
|
spos++;
|
2005-10-13 10:11:56 +00:00
|
|
|
}
|
2005-10-14 10:51:50 +00:00
|
|
|
continue; // escaped newline is removed.
|
2005-10-13 10:11:56 +00:00
|
|
|
}
|
2005-10-14 10:51:50 +00:00
|
|
|
escaped = YES;
|
|
|
|
}
|
|
|
|
if (*spos == '"' && escaped == NO)
|
|
|
|
{
|
|
|
|
spos++;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
*dpos++ = *spos++;
|
|
|
|
}
|
2005-10-14 14:03:13 +00:00
|
|
|
if (wantVal == YES)
|
2005-10-14 10:51:50 +00:00
|
|
|
{
|
2005-10-14 14:03:13 +00:00
|
|
|
NSString *val = [NSString alloc];
|
|
|
|
|
|
|
|
val = [val initWithCharacters: dst length: dpos - dst];
|
|
|
|
[dict setObject: val forKey: key];
|
2005-10-14 10:51:50 +00:00
|
|
|
DESTROY(key);
|
2005-10-14 14:03:13 +00:00
|
|
|
DESTROY(val);
|
|
|
|
wantVal = NO;
|
2005-10-14 10:51:50 +00:00
|
|
|
}
|
|
|
|
dpos = dst; // reset output buffer
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
while (spos < end)
|
|
|
|
{
|
|
|
|
if (*spos == '\\')
|
|
|
|
{
|
|
|
|
spos++;
|
|
|
|
if (spos >= end)
|
|
|
|
{
|
|
|
|
break; // Unexpected end of file
|
|
|
|
}
|
|
|
|
if (*spos == '\n')
|
|
|
|
{
|
|
|
|
spos++;
|
|
|
|
continue; // escaped newline is removed.
|
|
|
|
}
|
|
|
|
if (*spos == '\r')
|
2005-10-13 10:11:56 +00:00
|
|
|
{
|
2005-10-14 10:51:50 +00:00
|
|
|
spos++;
|
|
|
|
if (spos < end && *spos == '\n')
|
2005-10-13 10:11:56 +00:00
|
|
|
{
|
2005-10-14 10:51:50 +00:00
|
|
|
spos++;
|
2005-10-13 10:11:56 +00:00
|
|
|
}
|
2005-10-14 10:51:50 +00:00
|
|
|
continue; // escaped newline is removed.
|
2005-10-13 10:11:56 +00:00
|
|
|
}
|
|
|
|
}
|
2005-10-14 10:51:50 +00:00
|
|
|
if (*spos <= ' ' || *spos == '=')
|
2005-10-12 08:40:48 +00:00
|
|
|
{
|
2005-10-14 10:51:50 +00:00
|
|
|
break;
|
2005-10-12 08:40:48 +00:00
|
|
|
}
|
2005-10-14 10:51:50 +00:00
|
|
|
*dpos++ = *spos++;
|
2005-03-17 14:48:32 +00:00
|
|
|
}
|
2005-10-14 10:51:50 +00:00
|
|
|
|
2005-10-14 14:03:13 +00:00
|
|
|
if (wantKey == YES)
|
2005-03-17 14:48:32 +00:00
|
|
|
{
|
2005-10-14 14:03:13 +00:00
|
|
|
key = [NSString alloc];
|
|
|
|
key = [key initWithCharacters: dst length: dpos - dst];
|
|
|
|
wantKey = NO;
|
|
|
|
}
|
|
|
|
else if (wantVal == YES)
|
|
|
|
{
|
|
|
|
NSString *val = [NSString alloc];
|
|
|
|
|
|
|
|
val = [val initWithCharacters: dst length: dpos - dst];
|
|
|
|
[dict setObject: val forKey: key];
|
2005-10-14 10:51:50 +00:00
|
|
|
DESTROY(key);
|
2005-10-14 14:03:13 +00:00
|
|
|
DESTROY(val);
|
|
|
|
wantVal = NO;
|
2005-03-17 14:48:32 +00:00
|
|
|
}
|
2005-10-14 10:51:50 +00:00
|
|
|
dpos = dst; // reset output buffer
|
2005-03-17 14:48:32 +00:00
|
|
|
}
|
2005-03-03 16:04:22 +00:00
|
|
|
}
|
2005-10-14 14:03:13 +00:00
|
|
|
if (wantVal == YES)
|
2005-10-14 10:51:50 +00:00
|
|
|
{
|
|
|
|
[dict setObject: @"" forKey: key];
|
|
|
|
DESTROY(key);
|
|
|
|
}
|
|
|
|
NSZoneFree(NSDefaultMallocZone(), src);
|
|
|
|
NSZoneFree(NSDefaultMallocZone(), dst);
|
|
|
|
|
2005-10-15 07:19:11 +00:00
|
|
|
return YES;
|
2005-03-15 04:24:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* See NSPathUtilities.h for description */
|
|
|
|
void
|
|
|
|
GSSetUserName(NSString *aName)
|
|
|
|
{
|
|
|
|
NSCParameterAssert([aName length] > 0);
|
|
|
|
|
2005-03-03 16:04:22 +00:00
|
|
|
/*
|
2005-03-15 04:24:26 +00:00
|
|
|
* Do nothing if it's not a different user.
|
2005-03-03 16:04:22 +00:00
|
|
|
*/
|
2005-03-15 04:24:26 +00:00
|
|
|
if ([theUserName isEqualToString: aName])
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Release the memory
|
2005-03-15 06:36:21 +00:00
|
|
|
*/
|
2005-03-15 04:24:26 +00:00
|
|
|
[gnustep_global_lock lock];
|
|
|
|
ShutdownPathUtilities();
|
2005-03-15 06:36:21 +00:00
|
|
|
|
2005-03-03 16:04:22 +00:00
|
|
|
/*
|
2005-03-15 04:24:26 +00:00
|
|
|
* Reset things as new user
|
2005-03-03 16:04:22 +00:00
|
|
|
*/
|
2005-03-15 04:24:26 +00:00
|
|
|
ASSIGN(theUserName, aName);
|
|
|
|
InitialisePathUtilities();
|
2005-03-03 16:04:22 +00:00
|
|
|
[NSUserDefaults resetStandardUserDefaults];
|
2005-03-15 04:24:26 +00:00
|
|
|
|
|
|
|
[gnustep_global_lock unlock];
|
2005-03-03 16:04:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2005-03-15 04:24:26 +00:00
|
|
|
* Return the caller's login name as an NSString object.<br/ >
|
2005-03-03 16:04:22 +00:00
|
|
|
* Under unix-like systems, the name associated with the current
|
2005-03-15 04:24:26 +00:00
|
|
|
* effective user ID is used.<br/ >
|
|
|
|
* Under ms-windows, the 'LOGNAME' environemnt is used, or if that fails, the
|
|
|
|
* GetUserName() call is used to find the user name.
|
2005-03-03 16:04:22 +00:00
|
|
|
*/
|
|
|
|
/* NOTE FOR DEVELOPERS.
|
|
|
|
* If you change the behavior of this method you must also change
|
|
|
|
* user_home.c in the makefiles package to match.
|
|
|
|
*/
|
|
|
|
NSString *
|
|
|
|
NSUserName(void)
|
|
|
|
{
|
|
|
|
#if defined(__WIN32__)
|
|
|
|
if (theUserName == nil)
|
|
|
|
{
|
|
|
|
const char *loginName = 0;
|
|
|
|
/* The GetUserName function returns the current user name */
|
|
|
|
char buf[1024];
|
|
|
|
DWORD n = 1024;
|
|
|
|
|
|
|
|
if (GetEnvironmentVariable("LOGNAME", buf, 1024) != 0 && buf[0] != '\0')
|
|
|
|
loginName = buf;
|
|
|
|
else if (GetUserName(buf, &n) != 0 && buf[0] != '\0')
|
|
|
|
loginName = buf;
|
|
|
|
if (loginName)
|
|
|
|
theUserName = [[NSString alloc] initWithCString: loginName];
|
|
|
|
else
|
|
|
|
[NSException raise: NSInternalInconsistencyException
|
|
|
|
format: @"Unable to determine current user name"];
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
/* Set olduid to some invalid uid that we could never start off running
|
|
|
|
as. */
|
|
|
|
static int olduid = -1;
|
|
|
|
#ifdef HAVE_GETEUID
|
|
|
|
int uid = geteuid();
|
|
|
|
#else
|
|
|
|
int uid = getuid();
|
|
|
|
#endif /* HAVE_GETEUID */
|
|
|
|
|
|
|
|
if (theUserName == nil || uid != olduid)
|
|
|
|
{
|
|
|
|
const char *loginName = 0;
|
|
|
|
#ifdef HAVE_GETPWUID
|
|
|
|
struct passwd *pwent = getpwuid (uid);
|
|
|
|
loginName = pwent->pw_name;
|
|
|
|
#endif /* HAVE_GETPWUID */
|
|
|
|
olduid = uid;
|
|
|
|
if (loginName)
|
|
|
|
theUserName = [[NSString alloc] initWithCString: loginName];
|
|
|
|
else
|
|
|
|
[NSException raise: NSInternalInconsistencyException
|
|
|
|
format: @"Unable to determine current user name"];
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
return theUserName;
|
|
|
|
}
|
|
|
|
|
2005-03-15 04:24:26 +00:00
|
|
|
|
2005-03-03 16:04:22 +00:00
|
|
|
/**
|
|
|
|
* Return the caller's home directory as an NSString object.
|
|
|
|
* Calls NSHomeDirectoryForUser() to do this.
|
|
|
|
*/
|
|
|
|
NSString *
|
|
|
|
NSHomeDirectory(void)
|
|
|
|
{
|
|
|
|
return NSHomeDirectoryForUser (NSUserName ());
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns loginName's home directory as an NSString object.
|
|
|
|
*/
|
|
|
|
/* NOTE FOR DEVELOPERS.
|
|
|
|
* If you change the behavior of this method you must also change
|
|
|
|
* user_home.c in the makefiles package to match.
|
|
|
|
*/
|
|
|
|
NSString *
|
|
|
|
NSHomeDirectoryForUser(NSString *loginName)
|
|
|
|
{
|
2005-10-15 07:19:11 +00:00
|
|
|
NSDictionary *config = GNUstepConfig();
|
2005-03-03 16:04:22 +00:00
|
|
|
NSString *s = nil;
|
|
|
|
|
2005-10-15 07:19:11 +00:00
|
|
|
s = [@"GNUSTEP_USER_ROOT_" stringByAppendingString: loginName];
|
|
|
|
s = [config objectForKey: s];
|
|
|
|
if (s == nil)
|
2005-03-03 16:04:22 +00:00
|
|
|
{
|
2005-10-15 07:19:11 +00:00
|
|
|
s = [config objectForKey: @"GNUSTEP_USER_ROOT"];
|
2005-03-03 16:04:22 +00:00
|
|
|
}
|
2005-10-15 07:19:11 +00:00
|
|
|
if ([s length] == 0)
|
|
|
|
{
|
|
|
|
#if !defined(__MINGW32__)
|
|
|
|
struct passwd *pw;
|
|
|
|
|
|
|
|
[gnustep_global_lock lock];
|
|
|
|
pw = getpwnam ([loginName cString]);
|
|
|
|
if (pw != 0 && pw->pw_dir != NULL)
|
|
|
|
{
|
|
|
|
s = [NSString stringWithCString: pw->pw_dir];
|
|
|
|
}
|
|
|
|
[gnustep_global_lock unlock];
|
2005-03-03 16:04:22 +00:00
|
|
|
#else
|
2005-10-15 07:19:11 +00:00
|
|
|
s = Win32GetUserProfileDirectory(loginName);
|
2005-03-03 16:04:22 +00:00
|
|
|
#endif
|
2005-10-15 07:19:11 +00:00
|
|
|
}
|
2005-03-03 16:04:22 +00:00
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the full username of the current user.
|
|
|
|
* If unable to determine this, returns the standard user name.
|
|
|
|
*/
|
|
|
|
NSString *
|
|
|
|
NSFullUserName(void)
|
|
|
|
{
|
2005-03-15 04:24:26 +00:00
|
|
|
#if defined(__WIN32__)
|
|
|
|
/* FIXME: Win32 way to get full user name via Net API */
|
|
|
|
return NSUserName();
|
|
|
|
#else
|
|
|
|
#ifdef HAVE_PWD_H
|
2005-03-03 16:04:22 +00:00
|
|
|
struct passwd *pw;
|
|
|
|
|
|
|
|
pw = getpwnam([NSUserName() cString]);
|
|
|
|
return [NSString stringWithCString: pw->pw_gecos];
|
|
|
|
#else
|
|
|
|
NSLog(@"Warning: NSFullUserName not implemented\n");
|
|
|
|
return NSUserName();
|
2005-03-15 04:24:26 +00:00
|
|
|
#endif /* HAVE_PWD_H */
|
|
|
|
#endif /* defined(__Win32__) else */
|
2005-03-03 16:04:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2005-03-15 04:24:26 +00:00
|
|
|
* Return the path of the defaults directory for userName.<br />
|
2005-03-03 16:04:22 +00:00
|
|
|
* This examines the .GNUsteprc file in the home directory of the
|
|
|
|
* user for the GNUSTEP_DEFAULTS_ROOT or the GNUSTEP_USER_ROOT
|
2005-03-15 04:24:26 +00:00
|
|
|
* directory definitions, over-riding those in GNUstep.conf.
|
2005-03-03 16:04:22 +00:00
|
|
|
*/
|
2005-03-15 04:24:26 +00:00
|
|
|
NSString *
|
2005-03-03 16:04:22 +00:00
|
|
|
GSDefaultsRootForUser(NSString *userName)
|
|
|
|
{
|
2005-03-15 04:24:26 +00:00
|
|
|
NSString *home;
|
2005-10-15 07:19:11 +00:00
|
|
|
NSString *defaultsDir = nil;
|
2005-03-03 16:04:22 +00:00
|
|
|
|
2005-03-17 15:27:52 +00:00
|
|
|
if ([userName length] == 0)
|
|
|
|
{
|
|
|
|
userName = NSUserName();
|
|
|
|
}
|
2005-10-12 07:03:18 +00:00
|
|
|
InitialisePathUtilities();
|
2005-03-15 04:24:26 +00:00
|
|
|
if ([userName isEqual: NSUserName()])
|
2005-03-03 16:04:22 +00:00
|
|
|
{
|
2005-10-15 07:19:11 +00:00
|
|
|
home = gnustepUserHome;
|
|
|
|
defaultsDir = gnustepUserDefaultsDir;
|
2005-03-03 16:04:22 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2005-10-15 07:19:11 +00:00
|
|
|
NSDictionary *config;
|
2005-03-03 16:04:22 +00:00
|
|
|
|
2005-10-15 07:19:11 +00:00
|
|
|
config = GNUstepUserConfig(userName);
|
|
|
|
home = [config objectForKey: @"GNUSTEP_USER_HOME"];
|
|
|
|
defaultsDir = [config objectForKey: @"GNUSTEP_USER_DEFAULTS_DIR"];
|
2005-03-15 04:24:26 +00:00
|
|
|
}
|
2005-10-15 07:19:11 +00:00
|
|
|
home = [home stringByAppendingPathComponent: defaultsDir];
|
2005-03-15 06:36:21 +00:00
|
|
|
|
2005-10-13 10:11:56 +00:00
|
|
|
return home;
|
2005-03-03 16:04:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the standard paths in which applications are stored and
|
2005-03-15 04:24:26 +00:00
|
|
|
* should be searched for. Calls NSSearchPathForDirectoriesInDomains()<br/ >
|
|
|
|
* Refer to the GNUstep File System Heirarchy documentation for more info.
|
2005-03-03 16:04:22 +00:00
|
|
|
*/
|
|
|
|
NSArray *
|
|
|
|
NSStandardApplicationPaths(void)
|
|
|
|
{
|
|
|
|
return NSSearchPathForDirectoriesInDomains(NSAllApplicationsDirectory,
|
|
|
|
NSAllDomainsMask, YES);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2005-03-15 04:24:26 +00:00
|
|
|
* Returns the standard paths in which resources are stored and
|
|
|
|
* should be searched for. Calls NSSearchPathForDirectoriesInDomains()<br/ >
|
|
|
|
* Refer to the GNUstep File System Heirarchy documentation for more info.
|
2005-03-03 16:04:22 +00:00
|
|
|
*/
|
|
|
|
NSArray *
|
|
|
|
NSStandardLibraryPaths(void)
|
|
|
|
{
|
|
|
|
return NSSearchPathForDirectoriesInDomains(NSAllLibrariesDirectory,
|
|
|
|
NSAllDomainsMask, YES);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the name of a directory in which temporary files can be stored.
|
|
|
|
* Under GNUstep this is a location which is not readable by other users.
|
|
|
|
* <br />
|
|
|
|
* If a suitable directory can't be found or created, this function raises an
|
|
|
|
* NSGenericException.
|
|
|
|
*/
|
|
|
|
NSString *
|
|
|
|
NSTemporaryDirectory(void)
|
|
|
|
{
|
|
|
|
NSFileManager *manager;
|
|
|
|
NSString *tempDirName;
|
|
|
|
NSString *baseTempDirName = nil;
|
|
|
|
NSDictionary *attr;
|
|
|
|
int perm;
|
|
|
|
int owner;
|
|
|
|
BOOL flag;
|
|
|
|
#if !defined(__WIN32__)
|
|
|
|
int uid;
|
|
|
|
#else
|
|
|
|
char buffer[1024];
|
|
|
|
|
|
|
|
if (GetTempPath(1024, buffer))
|
|
|
|
{
|
2005-10-13 10:11:56 +00:00
|
|
|
baseTempDirName = [NSString stringWithCString: buffer];
|
2005-03-03 16:04:22 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If the user has supplied a directory name in the TEMP or TMP
|
|
|
|
* environment variable, attempt to use that unless we already
|
2005-04-12 17:01:30 +00:00
|
|
|
* have a temporary directory specified.
|
2005-03-03 16:04:22 +00:00
|
|
|
*/
|
|
|
|
if (baseTempDirName == nil)
|
|
|
|
{
|
|
|
|
NSDictionary *env = [[NSProcessInfo processInfo] environment];
|
|
|
|
|
|
|
|
baseTempDirName = [env objectForKey: @"TEMP"];
|
|
|
|
if (baseTempDirName == nil)
|
|
|
|
{
|
|
|
|
baseTempDirName = [env objectForKey: @"TMP"];
|
|
|
|
if (baseTempDirName == nil)
|
|
|
|
{
|
2005-10-11 19:09:26 +00:00
|
|
|
#if defined(__MINGW32__)
|
2005-03-03 16:04:22 +00:00
|
|
|
#ifdef __CYGWIN__
|
|
|
|
baseTempDirName = @"/cygdrive/c/";
|
|
|
|
#else
|
|
|
|
baseTempDirName = @"/c/";
|
|
|
|
#endif
|
|
|
|
#else
|
|
|
|
baseTempDirName = @"/tmp";
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Check that the base directory exists ... if it doesn't we can't
|
|
|
|
* go any further.
|
|
|
|
*/
|
|
|
|
tempDirName = baseTempDirName;
|
|
|
|
manager = [NSFileManager defaultManager];
|
|
|
|
if ([manager fileExistsAtPath: tempDirName isDirectory: &flag] == NO
|
|
|
|
|| flag == NO)
|
|
|
|
{
|
|
|
|
[NSException raise: NSGenericException
|
|
|
|
format: @"Temporary directory (%@) does not exist",
|
|
|
|
tempDirName];
|
|
|
|
return nil; /* Not reached. */
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Check that we are the directory owner, and that we, and nobody else,
|
|
|
|
* have access to it. If other people have access, try to create a secure
|
|
|
|
* subdirectory.
|
|
|
|
*/
|
|
|
|
attr = [manager fileAttributesAtPath: tempDirName traverseLink: YES];
|
|
|
|
owner = [[attr objectForKey: NSFileOwnerAccountID] intValue];
|
|
|
|
perm = [[attr objectForKey: NSFilePosixPermissions] intValue];
|
|
|
|
perm = perm & 0777;
|
|
|
|
|
|
|
|
// Mateu Batle: secure temporary directories don't work in MinGW
|
2005-10-11 19:09:26 +00:00
|
|
|
#ifndef __MINGW32__
|
2005-03-03 16:04:22 +00:00
|
|
|
|
2005-10-11 19:09:26 +00:00
|
|
|
#if defined(__MINGW32__)
|
2005-03-03 16:04:22 +00:00
|
|
|
uid = owner;
|
|
|
|
#else
|
|
|
|
#ifdef HAVE_GETEUID
|
|
|
|
uid = geteuid();
|
|
|
|
#else
|
|
|
|
uid = getuid();
|
|
|
|
#endif /* HAVE_GETEUID */
|
|
|
|
#endif
|
|
|
|
if ((perm != 0700 && perm != 0600) || owner != uid)
|
|
|
|
{
|
2005-04-12 17:01:30 +00:00
|
|
|
NSString *secure;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The name of the secure subdirectory reflects the user ID rather
|
|
|
|
* than the user name, since it is possible to have an account with
|
|
|
|
* lots of names on a unix system (ie multiple entries in the password
|
|
|
|
* file but a single userid). The private directory is secure within
|
|
|
|
* the account, not to a particular user name.
|
|
|
|
*/
|
|
|
|
secure = [NSString stringWithFormat: @"GNUstepSecure%d", uid];
|
|
|
|
tempDirName
|
|
|
|
= [baseTempDirName stringByAppendingPathComponent: secure];
|
2005-03-03 16:04:22 +00:00
|
|
|
/*
|
|
|
|
NSLog(@"Temporary directory (%@) may be insecure ... attempting to "
|
|
|
|
@"add secure subdirectory", tempDirName);
|
|
|
|
*/
|
|
|
|
if ([manager fileExistsAtPath: tempDirName] == NO)
|
|
|
|
{
|
|
|
|
NSNumber *p = [NSNumber numberWithInt: 0700];
|
|
|
|
|
|
|
|
attr = [NSDictionary dictionaryWithObject: p
|
|
|
|
forKey: NSFilePosixPermissions];
|
|
|
|
if ([manager createDirectoryAtPath: tempDirName
|
|
|
|
attributes: attr] == NO)
|
|
|
|
{
|
|
|
|
[NSException raise: NSGenericException
|
2005-04-12 17:01:30 +00:00
|
|
|
format:
|
|
|
|
@"Attempt to create a secure temporary directory (%@) failed.",
|
2005-03-03 16:04:22 +00:00
|
|
|
tempDirName];
|
|
|
|
return nil; /* Not reached. */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Check that the new directory is really secure.
|
|
|
|
*/
|
|
|
|
attr = [manager fileAttributesAtPath: tempDirName traverseLink: YES];
|
|
|
|
owner = [[attr objectForKey: NSFileOwnerAccountID] intValue];
|
|
|
|
perm = [[attr objectForKey: NSFilePosixPermissions] intValue];
|
|
|
|
perm = perm & 0777;
|
|
|
|
if ((perm != 0700 && perm != 0600) || owner != uid)
|
|
|
|
{
|
|
|
|
[NSException raise: NSGenericException
|
2005-04-12 17:01:30 +00:00
|
|
|
format:
|
|
|
|
@"Attempt to create a secure temporary directory (%@) failed.",
|
2005-03-03 16:04:22 +00:00
|
|
|
tempDirName];
|
|
|
|
return nil; /* Not reached. */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if ([manager isWritableFileAtPath: tempDirName] == NO)
|
|
|
|
{
|
|
|
|
[NSException raise: NSGenericException
|
|
|
|
format: @"Temporary directory (%@) is not writable",
|
|
|
|
tempDirName];
|
|
|
|
return nil; /* Not reached. */
|
|
|
|
}
|
|
|
|
return tempDirName;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2005-03-15 04:24:26 +00:00
|
|
|
* Deprecated function. Returns the location of the <em>root</em>
|
2005-03-15 06:36:21 +00:00
|
|
|
* directory of the GNUstep file heirarchy. Don't assume that /System,
|
2005-03-15 04:24:26 +00:00
|
|
|
* /Network etc exist in this path! Use other path utility functions for that.
|
|
|
|
* Refer to the GNUstep File System Heirarchy documentation for more info.
|
2005-03-03 16:04:22 +00:00
|
|
|
*/
|
|
|
|
NSString *
|
|
|
|
NSOpenStepRootDirectory(void)
|
|
|
|
{
|
|
|
|
NSString *root;
|
|
|
|
|
|
|
|
root = [[[NSProcessInfo processInfo] environment]
|
|
|
|
objectForKey: @"GNUSTEP_ROOT"];
|
|
|
|
if (root == nil)
|
|
|
|
{
|
2005-10-11 19:09:26 +00:00
|
|
|
#if defined(__MINGW32__)
|
2005-03-03 16:04:22 +00:00
|
|
|
#ifdef __CYGWIN__
|
|
|
|
root = @"/cygdrive/c/";
|
|
|
|
#else
|
|
|
|
root = @"~c/";
|
|
|
|
#endif
|
|
|
|
#else
|
|
|
|
root = @"/";
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
return root;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2005-03-15 04:24:26 +00:00
|
|
|
* Returns an array of search paths to look at for resources.<br/ >
|
2005-07-25 05:18:19 +00:00
|
|
|
* The paths are returned in domain order: USER, LOCAL, NETWORK then SYSTEM.
|
2005-03-03 16:04:22 +00:00
|
|
|
*/
|
|
|
|
NSArray *
|
2005-03-15 06:36:21 +00:00
|
|
|
NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory directoryKey,
|
2005-03-03 16:04:22 +00:00
|
|
|
NSSearchPathDomainMask domainMask, BOOL expandTilde)
|
|
|
|
{
|
2005-03-15 04:24:26 +00:00
|
|
|
static NSString *adminDir = @"Administrator";
|
|
|
|
static NSString *appsDir = @"Applications";
|
|
|
|
static NSString *devDir = @"Developer";
|
|
|
|
static NSString *demosDir = @"Demos";
|
|
|
|
static NSString *libraryDir = @"Library";
|
|
|
|
static NSString *supportDir = @"ApplicationSupport";
|
2005-03-15 06:36:21 +00:00
|
|
|
static NSString *docDir = @"Documentation";
|
2005-03-15 04:24:26 +00:00
|
|
|
static NSString *fontsDir = @"Fonts";
|
|
|
|
static NSString *frameworkDir = @"Frameworks";
|
|
|
|
static NSString *libsDir = @"Libraries";
|
|
|
|
static NSString *toolsDir = @"Tools";
|
|
|
|
NSMutableArray *paths = [NSMutableArray new];
|
|
|
|
NSString *path;
|
|
|
|
unsigned i;
|
|
|
|
unsigned count;
|
2005-03-03 16:04:22 +00:00
|
|
|
|
2005-10-12 07:03:18 +00:00
|
|
|
InitialisePathUtilities();
|
|
|
|
|
2005-03-17 14:48:32 +00:00
|
|
|
NSCAssert(gnustepSystemRoot!=nil,@"Path utilities without initialisation!");
|
2005-03-15 06:36:21 +00:00
|
|
|
|
2005-03-03 16:04:22 +00:00
|
|
|
/*
|
|
|
|
* The order in which we return paths is important - user must come
|
|
|
|
* first, followed by local, followed by network, followed by system.
|
|
|
|
* The calling code can then loop on the returned paths, and stop as
|
|
|
|
* soon as it finds something. So things in user automatically
|
|
|
|
* override things in system etc.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#define ADD_PATH(mask, base_dir, add_dir) \
|
|
|
|
if (domainMask & mask) \
|
|
|
|
{ \
|
|
|
|
path = [base_dir stringByAppendingPathComponent: add_dir]; \
|
2005-07-25 05:18:19 +00:00
|
|
|
if (path != nil && [paths containsObject: path] == NO) \
|
2005-03-03 16:04:22 +00:00
|
|
|
[paths addObject: path]; \
|
|
|
|
}
|
2005-03-15 04:24:26 +00:00
|
|
|
#ifdef OPTION_PLATFORM_SUPPORT
|
|
|
|
#define ADD_PLATFORM_PATH(mask, add_dir) \
|
|
|
|
if (domainMask & mask) \
|
|
|
|
{ \
|
2005-07-25 05:18:19 +00:00
|
|
|
if (add_dir != nil && [paths containsObject: add_dir] == NO) \
|
2005-03-15 04:24:26 +00:00
|
|
|
[paths addObject: add_dir]; \
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
#define ADD_PLATFORM_PATH(mask, add_dir)
|
|
|
|
#endif /* OPTION_PLATFORM_SUPPORT */
|
2005-03-03 16:04:22 +00:00
|
|
|
|
2005-07-25 05:18:19 +00:00
|
|
|
switch (directoryKey)
|
2005-03-03 16:04:22 +00:00
|
|
|
{
|
2005-07-25 05:18:19 +00:00
|
|
|
case NSAllApplicationsDirectory:
|
|
|
|
{
|
|
|
|
NSString *devDemosDir;
|
|
|
|
NSString *devAppsDir;
|
|
|
|
NSString *devAdminDir;
|
2005-03-03 16:04:22 +00:00
|
|
|
|
2005-07-25 05:18:19 +00:00
|
|
|
devDemosDir = [devDir stringByAppendingPathComponent: demosDir];
|
|
|
|
devAppsDir = [devDir stringByAppendingPathComponent: appsDir];
|
|
|
|
devAdminDir = [devDir stringByAppendingPathComponent: adminDir];
|
2005-03-03 16:04:22 +00:00
|
|
|
|
2005-07-25 05:18:19 +00:00
|
|
|
ADD_PATH(NSUserDomainMask, gnustepUserRoot, appsDir);
|
|
|
|
ADD_PATH(NSUserDomainMask, gnustepUserRoot, devAppsDir);
|
2005-03-15 06:36:21 +00:00
|
|
|
|
2005-07-25 05:18:19 +00:00
|
|
|
ADD_PATH(NSLocalDomainMask, gnustepLocalRoot, appsDir);
|
|
|
|
ADD_PATH(NSLocalDomainMask, gnustepLocalRoot, devAppsDir);
|
|
|
|
ADD_PATH(NSLocalDomainMask, gnustepLocalRoot, devAdminDir);
|
2005-03-15 04:24:26 +00:00
|
|
|
|
2005-07-25 05:18:19 +00:00
|
|
|
ADD_PATH(NSNetworkDomainMask, gnustepNetworkRoot, appsDir);
|
|
|
|
ADD_PATH(NSNetworkDomainMask, gnustepNetworkRoot, devAppsDir);
|
|
|
|
ADD_PATH(NSNetworkDomainMask, gnustepNetworkRoot, devAdminDir);
|
2005-03-15 06:36:21 +00:00
|
|
|
|
2005-07-25 05:18:19 +00:00
|
|
|
ADD_PATH(NSSystemDomainMask, gnustepSystemRoot, appsDir);
|
|
|
|
ADD_PATH(NSSystemDomainMask, gnustepSystemRoot, devAppsDir);
|
|
|
|
ADD_PATH(NSSystemDomainMask, gnustepSystemRoot, devAdminDir);
|
2005-03-15 06:36:21 +00:00
|
|
|
|
2005-07-25 05:18:19 +00:00
|
|
|
ADD_PATH(NSSystemDomainMask, gnustepSystemRoot, devDemosDir);
|
2005-03-15 06:36:21 +00:00
|
|
|
|
2005-07-25 05:18:19 +00:00
|
|
|
ADD_PLATFORM_PATH(NSLocalDomainMask, localApps);
|
|
|
|
ADD_PLATFORM_PATH(NSSystemDomainMask, platformApps);
|
|
|
|
ADD_PLATFORM_PATH(NSSystemDomainMask, osSysApps);
|
|
|
|
ADD_PLATFORM_PATH(NSSystemDomainMask, osSysAdmin);
|
|
|
|
ADD_PLATFORM_PATH(NSSystemDomainMask, platformAdmin);
|
|
|
|
}
|
|
|
|
break;
|
2005-03-15 04:24:26 +00:00
|
|
|
|
2005-07-25 05:18:19 +00:00
|
|
|
case NSApplicationDirectory:
|
|
|
|
{
|
|
|
|
ADD_PATH(NSUserDomainMask, gnustepUserRoot, appsDir);
|
|
|
|
ADD_PATH(NSLocalDomainMask, gnustepLocalRoot, appsDir);
|
|
|
|
ADD_PATH(NSNetworkDomainMask, gnustepNetworkRoot, appsDir);
|
|
|
|
ADD_PATH(NSSystemDomainMask, gnustepSystemRoot, appsDir);
|
|
|
|
|
|
|
|
ADD_PLATFORM_PATH(NSLocalDomainMask, localApps);
|
|
|
|
ADD_PLATFORM_PATH(NSSystemDomainMask, platformApps);
|
|
|
|
ADD_PLATFORM_PATH(NSSystemDomainMask, osSysApps);
|
|
|
|
}
|
|
|
|
break;
|
2005-03-15 04:24:26 +00:00
|
|
|
|
2005-07-25 05:18:19 +00:00
|
|
|
case NSDemoApplicationDirectory:
|
|
|
|
{
|
|
|
|
NSString *devDemosDir;
|
2005-03-17 14:48:32 +00:00
|
|
|
|
2005-07-25 05:18:19 +00:00
|
|
|
devDemosDir = [devDir stringByAppendingPathComponent: demosDir];
|
|
|
|
ADD_PATH(NSSystemDomainMask, gnustepSystemRoot, devDemosDir);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NSDeveloperApplicationDirectory:
|
|
|
|
{
|
|
|
|
NSString *devAppsDir;
|
|
|
|
|
|
|
|
devAppsDir = [devDir stringByAppendingPathComponent: appsDir];
|
|
|
|
ADD_PATH(NSUserDomainMask, gnustepUserRoot, devAppsDir);
|
|
|
|
ADD_PATH(NSLocalDomainMask, gnustepLocalRoot, devAppsDir);
|
|
|
|
ADD_PATH(NSNetworkDomainMask, gnustepNetworkRoot, devAppsDir);
|
|
|
|
ADD_PATH(NSSystemDomainMask, gnustepSystemRoot, devAppsDir);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NSAdminApplicationDirectory:
|
|
|
|
{
|
|
|
|
NSString *devAdminDir;
|
|
|
|
|
|
|
|
devAdminDir = [devDir stringByAppendingPathComponent: adminDir];
|
|
|
|
/* NSUserDomainMask - users have no Administrator directory */
|
|
|
|
ADD_PATH(NSLocalDomainMask, gnustepLocalRoot, devAdminDir);
|
|
|
|
ADD_PATH(NSNetworkDomainMask, gnustepNetworkRoot, devAdminDir);
|
|
|
|
ADD_PATH(NSSystemDomainMask, gnustepSystemRoot, devAdminDir);
|
|
|
|
|
|
|
|
ADD_PLATFORM_PATH(NSSystemDomainMask, osSysAdmin);
|
|
|
|
ADD_PLATFORM_PATH(NSSystemDomainMask, platformAdmin);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NSAllLibrariesDirectory:
|
|
|
|
{
|
|
|
|
ADD_PATH(NSUserDomainMask, gnustepUserRoot, libraryDir);
|
|
|
|
ADD_PATH(NSLocalDomainMask, gnustepLocalRoot, libraryDir);
|
|
|
|
ADD_PATH(NSNetworkDomainMask, gnustepNetworkRoot, libraryDir);
|
|
|
|
ADD_PATH(NSSystemDomainMask, gnustepSystemRoot, libraryDir);
|
|
|
|
|
|
|
|
ADD_PLATFORM_PATH(NSLocalDomainMask, localResources);
|
|
|
|
ADD_PLATFORM_PATH(NSSystemDomainMask, platformResources);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NSLibraryDirectory:
|
|
|
|
{
|
|
|
|
ADD_PATH(NSUserDomainMask, gnustepUserRoot, libraryDir);
|
|
|
|
ADD_PATH(NSLocalDomainMask, gnustepLocalRoot, libraryDir);
|
|
|
|
ADD_PATH(NSNetworkDomainMask, gnustepNetworkRoot, libraryDir);
|
|
|
|
ADD_PATH(NSSystemDomainMask, gnustepSystemRoot, libraryDir);
|
|
|
|
|
|
|
|
ADD_PLATFORM_PATH(NSLocalDomainMask, localResources);
|
|
|
|
ADD_PLATFORM_PATH(NSSystemDomainMask, platformResources);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NSDeveloperDirectory:
|
|
|
|
{
|
|
|
|
ADD_PATH(NSUserDomainMask, gnustepUserRoot, devDir);
|
|
|
|
ADD_PATH(NSLocalDomainMask, gnustepLocalRoot, devDir);
|
|
|
|
ADD_PATH(NSNetworkDomainMask, gnustepNetworkRoot, devDir);
|
|
|
|
ADD_PATH(NSSystemDomainMask, gnustepSystemRoot, devDir);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NSUserDirectory:
|
|
|
|
{
|
|
|
|
if (domainMask & NSUserDomainMask)
|
|
|
|
{
|
|
|
|
[paths addObject: gnustepUserRoot];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NSDocumentationDirectory:
|
|
|
|
{
|
|
|
|
NSString *gsdocDir;
|
|
|
|
|
|
|
|
gsdocDir = [libraryDir stringByAppendingPathComponent: docDir];
|
|
|
|
ADD_PATH(NSUserDomainMask, gnustepUserRoot, gsdocDir);
|
|
|
|
ADD_PATH(NSLocalDomainMask, gnustepLocalRoot, gsdocDir);
|
|
|
|
ADD_PATH(NSNetworkDomainMask, gnustepNetworkRoot, gsdocDir);
|
|
|
|
ADD_PATH(NSSystemDomainMask, gnustepSystemRoot, gsdocDir);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
/* Now the GNUstep additions */
|
|
|
|
case GSApplicationSupportDirectory:
|
|
|
|
{
|
|
|
|
NSString *appSupDir;
|
|
|
|
|
|
|
|
appSupDir = [libraryDir stringByAppendingPathComponent: supportDir];
|
|
|
|
ADD_PATH(NSUserDomainMask, gnustepUserRoot, appSupDir);
|
|
|
|
ADD_PATH(NSLocalDomainMask, gnustepLocalRoot, appSupDir);
|
|
|
|
ADD_PATH(NSNetworkDomainMask, gnustepNetworkRoot, appSupDir);
|
|
|
|
ADD_PATH(NSSystemDomainMask, gnustepSystemRoot, appSupDir);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case GSFrameworksDirectory:
|
|
|
|
{
|
|
|
|
NSString *frameDir;
|
|
|
|
|
|
|
|
frameDir = [libraryDir stringByAppendingPathComponent: frameworkDir];
|
|
|
|
ADD_PATH(NSUserDomainMask, gnustepUserRoot, frameDir);
|
|
|
|
ADD_PATH(NSLocalDomainMask, gnustepLocalRoot, frameDir);
|
|
|
|
ADD_PATH(NSNetworkDomainMask, gnustepNetworkRoot, frameDir);
|
|
|
|
ADD_PATH(NSSystemDomainMask, gnustepSystemRoot, frameDir);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case GSFontsDirectory:
|
|
|
|
{
|
|
|
|
NSString *fontDir;
|
|
|
|
|
|
|
|
fontDir = [libraryDir stringByAppendingPathComponent: fontsDir];
|
|
|
|
ADD_PATH(NSUserDomainMask, gnustepUserRoot, fontDir);
|
|
|
|
ADD_PATH(NSLocalDomainMask, gnustepLocalRoot, fontDir);
|
|
|
|
ADD_PATH(NSNetworkDomainMask, gnustepNetworkRoot, fontDir);
|
|
|
|
ADD_PATH(NSSystemDomainMask, gnustepSystemRoot, fontDir);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case GSLibrariesDirectory:
|
|
|
|
{
|
|
|
|
NSString *gslibsDir;
|
2005-07-31 08:18:19 +00:00
|
|
|
NSString *full = nil;
|
|
|
|
NSString *part = nil;
|
2005-07-25 05:18:19 +00:00
|
|
|
|
|
|
|
gslibsDir = [libraryDir stringByAppendingPathComponent: libsDir];
|
2005-07-31 08:18:19 +00:00
|
|
|
if ([gnustep_flattened boolValue] == NO
|
|
|
|
&& gnustep_target_cpu != nil && gnustep_target_os != nil)
|
|
|
|
{
|
|
|
|
part = [gnustep_target_cpu stringByAppendingPathComponent:
|
|
|
|
gnustep_target_os];
|
|
|
|
if (library_combo != nil)
|
|
|
|
{
|
|
|
|
full = [part stringByAppendingPathComponent: library_combo];
|
|
|
|
full = [gslibsDir stringByAppendingPathComponent: full];
|
|
|
|
}
|
|
|
|
part = [gslibsDir stringByAppendingPathComponent: part];
|
|
|
|
}
|
|
|
|
|
2005-07-25 05:18:19 +00:00
|
|
|
ADD_PATH(NSUserDomainMask, gnustepUserRoot, gslibsDir);
|
2005-07-31 08:18:19 +00:00
|
|
|
if (full) ADD_PATH(NSUserDomainMask, gnustepUserRoot, full);
|
|
|
|
if (part) ADD_PATH(NSUserDomainMask, gnustepUserRoot, part);
|
2005-07-25 05:18:19 +00:00
|
|
|
ADD_PATH(NSLocalDomainMask, gnustepLocalRoot, gslibsDir);
|
2005-07-31 08:18:19 +00:00
|
|
|
if (full) ADD_PATH(NSLocalDomainMask, gnustepLocalRoot, full);
|
|
|
|
if (part) ADD_PATH(NSLocalDomainMask, gnustepLocalRoot, part);
|
2005-07-25 05:18:19 +00:00
|
|
|
ADD_PATH(NSNetworkDomainMask, gnustepNetworkRoot, gslibsDir);
|
2005-07-31 08:18:19 +00:00
|
|
|
if (full) ADD_PATH(NSNetworkDomainMask, gnustepNetworkRoot, full);
|
|
|
|
if (part) ADD_PATH(NSNetworkDomainMask, gnustepNetworkRoot, part);
|
2005-07-25 05:18:19 +00:00
|
|
|
ADD_PATH(NSSystemDomainMask, gnustepSystemRoot, gslibsDir);
|
2005-07-31 08:18:19 +00:00
|
|
|
if (full) ADD_PATH(NSSystemDomainMask, gnustepSystemRoot, full);
|
|
|
|
if (part) ADD_PATH(NSSystemDomainMask, gnustepSystemRoot, part);
|
2005-07-25 05:18:19 +00:00
|
|
|
|
|
|
|
ADD_PLATFORM_PATH(NSLocalDomainMask, localLibs);
|
|
|
|
ADD_PLATFORM_PATH(NSSystemDomainMask, platformLibs);
|
|
|
|
ADD_PLATFORM_PATH(NSSystemDomainMask, osSysLibs);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case GSToolsDirectory:
|
|
|
|
{
|
2005-07-31 08:18:19 +00:00
|
|
|
NSString *full = nil;
|
|
|
|
NSString *part = nil;
|
|
|
|
|
|
|
|
if ([gnustep_flattened boolValue] == NO
|
|
|
|
&& gnustep_target_cpu != nil && gnustep_target_os != nil)
|
|
|
|
{
|
|
|
|
part = [gnustep_target_cpu stringByAppendingPathComponent:
|
|
|
|
gnustep_target_os];
|
|
|
|
if (library_combo != nil)
|
|
|
|
{
|
|
|
|
full = [part stringByAppendingPathComponent: library_combo];
|
|
|
|
full = [toolsDir stringByAppendingPathComponent: full];
|
|
|
|
}
|
|
|
|
part = [toolsDir stringByAppendingPathComponent: part];
|
|
|
|
}
|
|
|
|
|
2005-07-25 05:18:19 +00:00
|
|
|
ADD_PATH(NSUserDomainMask, gnustepUserRoot, toolsDir);
|
2005-07-31 08:18:19 +00:00
|
|
|
if (full) ADD_PATH(NSUserDomainMask, gnustepUserRoot, full);
|
|
|
|
if (part) ADD_PATH(NSUserDomainMask, gnustepUserRoot, part);
|
2005-07-25 05:18:19 +00:00
|
|
|
ADD_PATH(NSLocalDomainMask, gnustepLocalRoot, toolsDir);
|
2005-07-31 08:18:19 +00:00
|
|
|
if (full) ADD_PATH(NSLocalDomainMask, gnustepLocalRoot, full);
|
|
|
|
if (part) ADD_PATH(NSLocalDomainMask, gnustepLocalRoot, part);
|
2005-07-25 05:18:19 +00:00
|
|
|
ADD_PATH(NSNetworkDomainMask, gnustepNetworkRoot, toolsDir);
|
2005-07-31 08:18:19 +00:00
|
|
|
if (full) ADD_PATH(NSNetworkDomainMask, gnustepNetworkRoot, full);
|
|
|
|
if (part) ADD_PATH(NSNetworkDomainMask, gnustepNetworkRoot, part);
|
2005-07-25 05:18:19 +00:00
|
|
|
ADD_PATH(NSSystemDomainMask, gnustepSystemRoot, toolsDir);
|
2005-07-31 08:18:19 +00:00
|
|
|
if (full) ADD_PATH(NSSystemDomainMask, gnustepSystemRoot, full);
|
|
|
|
if (part) ADD_PATH(NSSystemDomainMask, gnustepSystemRoot, part);
|
2005-07-25 05:18:19 +00:00
|
|
|
|
|
|
|
ADD_PLATFORM_PATH(NSLocalDomainMask, localApps);
|
|
|
|
ADD_PLATFORM_PATH(NSSystemDomainMask, platformApps);
|
|
|
|
ADD_PLATFORM_PATH(NSSystemDomainMask, osSysApps);
|
|
|
|
ADD_PLATFORM_PATH(NSSystemDomainMask, platformAdmin);
|
|
|
|
ADD_PLATFORM_PATH(NSSystemDomainMask, osSysAdmin);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case GSPreferencesDirectory:
|
|
|
|
{
|
|
|
|
// Not used
|
|
|
|
}
|
|
|
|
break;
|
2005-03-03 16:04:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#undef ADD_PATH
|
2005-03-15 04:24:26 +00:00
|
|
|
#undef ADD_PLATFORM_PATH
|
2005-03-03 16:04:22 +00:00
|
|
|
|
|
|
|
count = [paths count];
|
|
|
|
for (i = 0; i < count; i++)
|
|
|
|
{
|
|
|
|
path = [paths objectAtIndex: i];
|
2005-03-15 04:24:26 +00:00
|
|
|
|
|
|
|
/* remove paths which don't exist on this system */
|
2005-03-17 14:48:32 +00:00
|
|
|
if ([MGR() fileExistsAtPath: path] == NO)
|
2005-03-03 16:04:22 +00:00
|
|
|
{
|
|
|
|
[paths removeObjectAtIndex: i];
|
2005-03-15 04:24:26 +00:00
|
|
|
i--;
|
|
|
|
count--;
|
2005-03-03 16:04:22 +00:00
|
|
|
}
|
|
|
|
/*
|
|
|
|
* this may look like a performance hit at first glance, but if these
|
|
|
|
* string methods don't alter the string, they return the receiver
|
|
|
|
*/
|
|
|
|
else if (expandTilde == YES)
|
2005-03-15 04:24:26 +00:00
|
|
|
{
|
|
|
|
[paths replaceObjectAtIndex: i
|
|
|
|
withObject: [path stringByExpandingTildeInPath]];
|
|
|
|
}
|
2005-03-03 16:04:22 +00:00
|
|
|
else
|
2005-03-15 04:24:26 +00:00
|
|
|
{
|
|
|
|
[paths replaceObjectAtIndex: i
|
|
|
|
withObject: [path stringByAbbreviatingWithTildeInPath]];
|
|
|
|
}
|
2005-03-03 16:04:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
AUTORELEASE (paths);
|
|
|
|
return paths;
|
|
|
|
}
|