mirror of
https://github.com/gnustep/libs-base.git
synced 2025-04-22 16:33:29 +00:00
improve handling of user domain paths
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@30998 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
3b00aacbfe
commit
8b1d3e61ba
3 changed files with 240 additions and 83 deletions
12
ChangeLog
12
ChangeLog
|
@ -1,3 +1,15 @@
|
|||
2010-07-19 Richard Frith-Macdonald <rfm@gnu.org>
|
||||
|
||||
* Source/NSPathUtilities.m: User domain handling improvements.
|
||||
Match gnustep-make in allowing absolute paths to be specified for the
|
||||
user domain directories rather than always treating user domain paths
|
||||
as being within the user's home directory.
|
||||
Also, add support for simple field substitution into the path:
|
||||
'%u' --> user name
|
||||
'%i' --> user id
|
||||
'%%' --> '%'
|
||||
* Documentation/Base.gsdoc: Document the new behavior.
|
||||
|
||||
2010-07-19 Niels Grewe <niels.grewe@halbordnung.de>
|
||||
|
||||
* Headers/Additions/GNUstepBase/GSConfig.h: Define GS_USE_ICU when
|
||||
|
|
|
@ -517,39 +517,90 @@ notice and this notice are preserved.
|
|||
of no name.<br />
|
||||
System paths are defined by the following:
|
||||
</p>
|
||||
<deflist>
|
||||
<term>GNUSTEP_SYSTEM_ROOT</term>
|
||||
<desc>
|
||||
Obsolete.
|
||||
Used to specify the GNUstep system root directory ... all
|
||||
system libraries, tools, applications, headers, resources
|
||||
in general are located relative to this.
|
||||
</desc>
|
||||
<term>GNUSTEP_NETWORK_ROOT</term>
|
||||
<desc>
|
||||
Obsolete. Used to specify the GNUstep root directory for local
|
||||
(non-system) resources that are intended to be shared
|
||||
across a local network. Typically this is an NFS exported
|
||||
directory shared by many machines. It provides an
|
||||
alternative to GNUSTEP_LOCAL_ROOT but is usually defined
|
||||
to the same value.
|
||||
</desc>
|
||||
<term>GNUSTEP_LOCAL_ROOT</term>
|
||||
<desc>
|
||||
Obsolete. Used to specify the GNUstep root directory for local
|
||||
(non-system) resources. Typically all locally produced
|
||||
or contributed software is installed relative to this.
|
||||
</desc>
|
||||
</deflist>
|
||||
<deflist>
|
||||
<term>GNUSTEP_SYSTEM_APPS</term>
|
||||
<desc>This is where System GUI Applications get installed.<br />
|
||||
Traditionally it is /usr/GNUstep/System/Applications.
|
||||
</desc>
|
||||
<term>GNUSTEP_SYSTEM_ADMIN_APPS</term>
|
||||
<desc>This is where System GUI Applications that only the
|
||||
Administrator can use get installed.<br />
|
||||
Traditionally it is /usr/GNUstep/System/Applications/Admin.
|
||||
</desc>
|
||||
<term>GNUSTEP_SYSTEM_WEB_APPS</term>
|
||||
<desc>This is where System Web Applications (GSWeb, SOPE) get
|
||||
installed.<br />
|
||||
Traditionally it is /usr/GNUstep/System/Library/WebApplications.
|
||||
</desc>
|
||||
<term>GNUSTEP_SYSTEM_TOOLS</term>
|
||||
<desc>This is where System Command-Line Tools get installed.<br />
|
||||
Traditionally it is /usr/GNUstep/System/Tools.
|
||||
</desc>
|
||||
<term>GNUSTEP_SYSTEM_ADMIN_TOOLS</term>
|
||||
<desc>This is where System Command-Line Tools that only the
|
||||
Administrator can use get installed. Important: this
|
||||
should not be in the PATH of normal users.<br />
|
||||
Traditionally it is /usr/GNUstep/System/Tools/Admin.
|
||||
</desc>
|
||||
<term>GNUSTEP_SYSTEM_LIBRARY</term>
|
||||
<desc>This is where System resources get installed.
|
||||
This directory will contain a lot of executable code
|
||||
since *step traditionally likes to
|
||||
bundle executables and resources together.<br />
|
||||
Traditionally it is /usr/GNUstep/System/Library.
|
||||
</desc>
|
||||
<term>GNUSTEP_SYSTEM_HEADERS</term>
|
||||
<desc>This is where System headers get installed. They are the
|
||||
library .h headers.<br />
|
||||
Traditionally it is /usr/GNUstep/System/Library/Headers.
|
||||
</desc>
|
||||
<term>GNUSTEP_SYSTEM_LIBRARIES</term>
|
||||
<desc>This is where System libraries get installed.
|
||||
By libraries we mean the shared/static object files that
|
||||
you can link into programs.<br />
|
||||
Traditionally it is /usr/GNUstep/System/Library/Libraries.
|
||||
</desc>
|
||||
<term>GNUSTEP_SYSTEM_DOC</term>
|
||||
<desc>This is where System documentation get installed.
|
||||
This is known not to contain any executable, so we keep
|
||||
it separate.<br />
|
||||
Traditionally it is /usr/GNUstep/System/Library/Documentation.
|
||||
</desc>
|
||||
<term>GNUSTEP_SYSTEM_DOC_MAN</term>
|
||||
<desc>This is where System man pages get installed.<br />
|
||||
Traditionally it is
|
||||
/usr/GNUstep/System/Library/Documentation/man.
|
||||
</desc>
|
||||
<term>GNUSTEP_SYSTEM_DOC_INFO</term>
|
||||
<desc>This is where System info pages get installed.<br />
|
||||
Traditionally it is
|
||||
/usr/GNUstep/System/Library/Documentation/info.
|
||||
</desc>
|
||||
</deflist>
|
||||
<p>
|
||||
Paths for each user are defined by the following:
|
||||
In addition to the above SYSTEM domain paths, there are
|
||||
corresponding LOCAL, NETWORK, and USER domain paths (with the
|
||||
same names except for replacing 'SYSTEM' with 'LOCAL', 'NETWORK',
|
||||
or 'USER'.<br />
|
||||
All these paths must be absolute, except for the USER domain
|
||||
paths which, if not absolute, are considered to be with the
|
||||
user's home directory.<br />
|
||||
NB. as a special case a path may begin with './' or '../' when
|
||||
it is to be resolved to an absolute path relative to the
|
||||
location of the GNUstep configuration file.
|
||||
So while such paths appear to be relative, they actually produce
|
||||
absolute locations at runtime since the location of the
|
||||
configuration file is known.<br />
|
||||
Finally, for paths in the USER domain only, a limited substitution
|
||||
into the path is performed at runtime as follows:<br />
|
||||
'%u' is replaced by the user name<br />
|
||||
'%i' is replaced by the user ID<br />
|
||||
'%%' is replaced by a single '%'<br />
|
||||
</p>
|
||||
<p>
|
||||
Other paths for each user are defined by the following:
|
||||
</p>
|
||||
<deflist>
|
||||
<term>GNUSTEP_USER_DIR</term>
|
||||
<desc>Obsolete.
|
||||
Path for user specific GNUstep resources (eg. 'GNUstep').
|
||||
Relative to the user's home directory.
|
||||
</desc>
|
||||
<term>GNUSTEP_USER_CONFIG_FILE</term>
|
||||
<desc>Name of user configuration file (eg. '.GNUstep.conf')
|
||||
relative to the user's home directory.<br />
|
||||
|
@ -558,7 +609,7 @@ notice and this notice are preserved.
|
|||
</desc>
|
||||
<term>GNUSTEP_USER_DEFAULTS_DIR</term>
|
||||
<desc>Name of directory for user defaults files.
|
||||
Relative to the user's home directory.<br />
|
||||
Always relative to the user's home directory except:<br />
|
||||
On mswindows this may be set to be ':REGISTRY:' to have defaults
|
||||
stored in the windows registry rather than in the standard file
|
||||
format.<br />
|
||||
|
|
|
@ -138,6 +138,8 @@ static NSString *gnustep_is_flattened =
|
|||
static NSString *gnustepConfigPath = nil;
|
||||
|
||||
static NSString *gnustepUserHome = nil;
|
||||
static NSString *gnustepUserID = nil;
|
||||
static NSString *gnustepUserName = nil;
|
||||
static NSString *gnustepUserDefaultsDir = nil;
|
||||
|
||||
static NSString *theUserName = nil; /* The user's login name */
|
||||
|
@ -236,6 +238,10 @@ static void ShutdownPathUtilities(void);
|
|||
}\
|
||||
})
|
||||
|
||||
/* Grab a path from the config file, making it relative to the config
|
||||
* file location if it begins with './' or '../', and checking that the
|
||||
* result is an absolute path.
|
||||
*/
|
||||
#define ASSIGN_PATH(var, dictionary, key) ({\
|
||||
id val = getPathConfig(dictionary, key);\
|
||||
if (val != nil)\
|
||||
|
@ -246,6 +252,23 @@ static void ShutdownPathUtilities(void);
|
|||
}\
|
||||
})
|
||||
|
||||
/* Like ASSIGN_PATH(), but permits the result to be a relative path as that
|
||||
* is what we normally use (the path is within the user's home directory).
|
||||
*/
|
||||
#define ASSIGN_USER(var, dictionary, key) ({\
|
||||
id val = [dictionary objectForKey: key];\
|
||||
if (val != nil)\
|
||||
{\
|
||||
val = getPath(val);\
|
||||
}\
|
||||
if (val != nil)\
|
||||
{\
|
||||
RELEASE(var);\
|
||||
var = RETAIN(val);\
|
||||
[dictionary removeObjectForKey: key];\
|
||||
}\
|
||||
})
|
||||
|
||||
/* Conditionally assign lval to var only if var is nil */
|
||||
#define TEST_ASSIGN(var, lval) ({\
|
||||
if ((var == nil)&&(lval != nil))\
|
||||
|
@ -262,6 +285,77 @@ static void ShutdownPathUtilities(void);
|
|||
}\
|
||||
})
|
||||
|
||||
/* The user domain paths are normally located within the user's home directory,
|
||||
* but if they are specified as absolute paths they can be anywhere you like.
|
||||
*
|
||||
*/
|
||||
#define ASSIGN_USER_PATH(var, val) ({\
|
||||
if (nil == var) \
|
||||
{\
|
||||
ASSIGN(var, ([val isAbsolutePath] ? substUser(val) : \
|
||||
[gnustepUserHome stringByAppendingPathComponent: substUser(val)]));\
|
||||
}\
|
||||
})
|
||||
|
||||
/* For user domain paths, we allow '%u' as the username, '%i' as the userid,
|
||||
* and '%%' as a '%' in cases where it would otherwise be treated as a
|
||||
* username or userid.
|
||||
*/
|
||||
static NSString*
|
||||
substUser(NSString *str)
|
||||
{
|
||||
if (str != nil && [str rangeOfString: @"%"].length > 0)
|
||||
{
|
||||
NSMutableString *m = [[str mutableCopy] autorelease];
|
||||
int l = [m length];
|
||||
int i = 0;
|
||||
BOOL percent = NO;
|
||||
|
||||
while (i < l)
|
||||
{
|
||||
unichar c = [m characterAtIndex: i];
|
||||
|
||||
if (YES == percent)
|
||||
{
|
||||
NSString *s;
|
||||
|
||||
if (c == '%')
|
||||
{
|
||||
s = @"%"; // Escaped percent
|
||||
}
|
||||
else if (c == 'i')
|
||||
{
|
||||
s = gnustepUserID; // User ID
|
||||
}
|
||||
else if (c == 'u')
|
||||
{
|
||||
s = gnustepUserName; // User name
|
||||
}
|
||||
else
|
||||
{
|
||||
s = nil; // No substitution
|
||||
}
|
||||
if (s != nil)
|
||||
{
|
||||
int diff = [s length] - 2;
|
||||
|
||||
[m replaceCharactersInRange: NSMakeRange(i-1, 2)
|
||||
withString: s];
|
||||
l += diff;
|
||||
i += diff;
|
||||
}
|
||||
percent = NO;
|
||||
}
|
||||
else if (c == '%')
|
||||
{
|
||||
percent = YES;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
str = m;
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
/* Get a full path string */
|
||||
static inline NSString *
|
||||
|
@ -302,8 +396,8 @@ getPathConfig(NSDictionary *dict, NSString *key)
|
|||
unichar buf[3];
|
||||
|
||||
[path getCharacters: buf range: NSMakeRange(0, 3)];
|
||||
if ((buf[0] == '/' || bug[0] == '\\') && isalpha(buf[1])
|
||||
&& (buf[2] == '/' || bug[2] == '\\'))
|
||||
if ((buf[0] == '/' || buf[0] == '\\') && isalpha(buf[1])
|
||||
&& (buf[2] == '/' || buf[2] == '\\'))
|
||||
{
|
||||
path = [NSString stringWithFormat: @"%c:%@", (char)buf[1],
|
||||
[path substringFromindex: 2]];
|
||||
|
@ -370,27 +464,27 @@ static void ExtractValuesFromConfig(NSDictionary *config)
|
|||
ASSIGN_PATH(gnustepLocalDocumentationMan, c, @"GNUSTEP_LOCAL_DOC_MAN");
|
||||
ASSIGN_PATH(gnustepLocalDocumentationInfo, c, @"GNUSTEP_LOCAL_DOC_INFO");
|
||||
|
||||
ASSIGN_IF_SET(gnustepUserDirApps, c, @"GNUSTEP_USER_DIR_APPS");
|
||||
ASSIGN_USER(gnustepUserDirApps, c, @"GNUSTEP_USER_DIR_APPS");
|
||||
TEST_ASSIGN(gnustepUserDirApps, @GNUSTEP_TARGET_USER_DIR_APPS);
|
||||
ASSIGN_IF_SET(gnustepUserDirAdminApps, c, @"GNUSTEP_USER_DIR_ADMIN_APPS");
|
||||
ASSIGN_USER(gnustepUserDirAdminApps, c, @"GNUSTEP_USER_DIR_ADMIN_APPS");
|
||||
TEST_ASSIGN(gnustepUserDirAdminApps, @GNUSTEP_TARGET_USER_DIR_ADMIN_APPS);
|
||||
ASSIGN_IF_SET(gnustepUserDirWebApps, c, @"GNUSTEP_USER_DIR_WEB_APPS");
|
||||
ASSIGN_USER(gnustepUserDirWebApps, c, @"GNUSTEP_USER_DIR_WEB_APPS");
|
||||
TEST_ASSIGN(gnustepUserDirWebApps, @GNUSTEP_TARGET_USER_DIR_WEB_APPS);
|
||||
ASSIGN_IF_SET(gnustepUserDirTools, c, @"GNUSTEP_USER_DIR_TOOLS");
|
||||
ASSIGN_USER(gnustepUserDirTools, c, @"GNUSTEP_USER_DIR_TOOLS");
|
||||
TEST_ASSIGN(gnustepUserDirTools, @GNUSTEP_TARGET_USER_DIR_TOOLS);
|
||||
ASSIGN_IF_SET(gnustepUserDirAdminTools, c, @"GNUSTEP_USER_DIR_ADMIN_TOOLS");
|
||||
ASSIGN_USER(gnustepUserDirAdminTools, c, @"GNUSTEP_USER_DIR_ADMIN_TOOLS");
|
||||
TEST_ASSIGN(gnustepUserDirAdminTools, @GNUSTEP_TARGET_USER_DIR_ADMIN_TOOLS);
|
||||
ASSIGN_IF_SET(gnustepUserDirLibrary, c, @"GNUSTEP_USER_DIR_LIBRARY");
|
||||
ASSIGN_USER(gnustepUserDirLibrary, c, @"GNUSTEP_USER_DIR_LIBRARY");
|
||||
TEST_ASSIGN(gnustepUserDirLibrary, @GNUSTEP_TARGET_USER_DIR_LIBRARY);
|
||||
ASSIGN_IF_SET(gnustepUserDirLibraries, c, @"GNUSTEP_USER_DIR_LIBRARIES");
|
||||
ASSIGN_USER(gnustepUserDirLibraries, c, @"GNUSTEP_USER_DIR_LIBRARIES");
|
||||
TEST_ASSIGN(gnustepUserDirLibraries, @GNUSTEP_TARGET_USER_DIR_LIBRARIES);
|
||||
ASSIGN_IF_SET(gnustepUserDirHeaders, c, @"GNUSTEP_USER_DIR_HEADERS");
|
||||
ASSIGN_USER(gnustepUserDirHeaders, c, @"GNUSTEP_USER_DIR_HEADERS");
|
||||
TEST_ASSIGN(gnustepUserDirHeaders, @GNUSTEP_TARGET_USER_DIR_HEADERS);
|
||||
ASSIGN_IF_SET(gnustepUserDirDocumentation, c, @"GNUSTEP_USER_DIR_DOC");
|
||||
ASSIGN_USER(gnustepUserDirDocumentation, c, @"GNUSTEP_USER_DIR_DOC");
|
||||
TEST_ASSIGN(gnustepUserDirDocumentation, @GNUSTEP_TARGET_USER_DIR_DOC);
|
||||
ASSIGN_IF_SET(gnustepUserDirDocumentationMan, c, @"GNUSTEP_USER_DIR_DOC_MAN");
|
||||
ASSIGN_USER(gnustepUserDirDocumentationMan, c, @"GNUSTEP_USER_DIR_DOC_MAN");
|
||||
TEST_ASSIGN(gnustepUserDirDocumentationMan, @GNUSTEP_TARGET_USER_DIR_DOC_MAN);
|
||||
ASSIGN_IF_SET(gnustepUserDirDocumentationInfo, c, @"GNUSTEP_USER_DIR_DOC_INFO");
|
||||
ASSIGN_USER(gnustepUserDirDocumentationInfo, c, @"GNUSTEP_USER_DIR_DOC_INFO");
|
||||
TEST_ASSIGN(gnustepUserDirDocumentationInfo, @GNUSTEP_TARGET_USER_DIR_DOC_INFO);
|
||||
|
||||
/*
|
||||
|
@ -486,41 +580,17 @@ static void ExtractValuesFromConfig(NSDictionary *config)
|
|||
* Set the GNUSTEP_USER_xxx variables from the user home and the
|
||||
* GNUSTEP_USER_DIR_xxx variables.
|
||||
*/
|
||||
ASSIGN(gnustepUserApps,
|
||||
[gnustepUserHome stringByAppendingPathComponent: gnustepUserDirApps]);
|
||||
|
||||
ASSIGN(gnustepUserAdminApps,
|
||||
[gnustepUserHome stringByAppendingPathComponent: gnustepUserDirAdminApps]);
|
||||
|
||||
ASSIGN(gnustepUserWebApps,
|
||||
[gnustepUserHome stringByAppendingPathComponent: gnustepUserDirWebApps]);
|
||||
|
||||
ASSIGN(gnustepUserTools,
|
||||
[gnustepUserHome stringByAppendingPathComponent: gnustepUserDirTools]);
|
||||
|
||||
ASSIGN(gnustepUserAdminTools,
|
||||
[gnustepUserHome stringByAppendingPathComponent: gnustepUserDirAdminTools]);
|
||||
|
||||
ASSIGN(gnustepUserLibrary,
|
||||
[gnustepUserHome stringByAppendingPathComponent: gnustepUserDirLibrary]);
|
||||
|
||||
ASSIGN(gnustepUserLibraries,
|
||||
[gnustepUserHome stringByAppendingPathComponent: gnustepUserDirLibraries]);
|
||||
|
||||
ASSIGN(gnustepUserHeaders,
|
||||
[gnustepUserHome stringByAppendingPathComponent: gnustepUserDirHeaders]);
|
||||
|
||||
ASSIGN(gnustepUserDocumentation,
|
||||
[gnustepUserHome stringByAppendingPathComponent:
|
||||
gnustepUserDocumentation]);
|
||||
|
||||
ASSIGN(gnustepUserDocumentationMan,
|
||||
[gnustepUserHome stringByAppendingPathComponent:
|
||||
gnustepUserDocumentationMan]);
|
||||
|
||||
ASSIGN(gnustepUserDocumentationInfo,
|
||||
[gnustepUserHome stringByAppendingPathComponent:
|
||||
gnustepUserDocumentationInfo]);
|
||||
ASSIGN_USER_PATH(gnustepUserApps, gnustepUserDirApps);
|
||||
ASSIGN_USER_PATH(gnustepUserAdminApps, gnustepUserDirAdminApps);
|
||||
ASSIGN_USER_PATH(gnustepUserWebApps, gnustepUserDirWebApps);
|
||||
ASSIGN_USER_PATH(gnustepUserTools, gnustepUserDirTools);
|
||||
ASSIGN_USER_PATH(gnustepUserAdminTools, gnustepUserDirAdminTools);
|
||||
ASSIGN_USER_PATH(gnustepUserLibrary, gnustepUserDirLibrary);
|
||||
ASSIGN_USER_PATH(gnustepUserLibraries, gnustepUserDirLibraries);
|
||||
ASSIGN_USER_PATH(gnustepUserHeaders, gnustepUserDirHeaders);
|
||||
ASSIGN_USER_PATH(gnustepUserDocumentation, gnustepUserDocumentation);
|
||||
ASSIGN_USER_PATH(gnustepUserDocumentationMan, gnustepUserDocumentationMan);
|
||||
ASSIGN_USER_PATH(gnustepUserDocumentationInfo, gnustepUserDocumentationInfo);
|
||||
|
||||
/*
|
||||
* Try to ensure that essential user directories exist.
|
||||
|
@ -867,14 +937,36 @@ static void InitialisePathUtilities(void)
|
|||
/* Set up our root paths */
|
||||
NS_DURING
|
||||
{
|
||||
NSString *userName;
|
||||
NSMutableDictionary *config;
|
||||
|
||||
[gnustep_global_lock lock];
|
||||
userName = NSUserName();
|
||||
gnustepUserName = [NSUserName() copy];
|
||||
#if defined(__MINGW__)
|
||||
{
|
||||
unichar buf[1024];
|
||||
SID_NAME_USE use;
|
||||
SID sid;
|
||||
DWORD n = 1024;
|
||||
|
||||
if (GetUserNameW(buf, &n) == 0 || buf[0] == '\0')
|
||||
{
|
||||
[NSException raise: NSInternalInconsistencyException
|
||||
format: @"Unable to determine current user name"];
|
||||
}
|
||||
n = sizeof(SID);
|
||||
if (LookupAccountName(0, buf, &sid, &n, NULL, 0, &use) == 0)
|
||||
{
|
||||
[NSException raise: NSInternalInconsistencyException
|
||||
format: @"Unable to determine current account"];
|
||||
}
|
||||
gnustepUserID = [[NSString alloc] initWithFormat: @"%ld", (long)sid];
|
||||
}
|
||||
#else
|
||||
gnustepUserID = [[NSString alloc] initWithFormat: @"%ld", (long)getuid()];
|
||||
#endif
|
||||
config = GNUstepConfig(nil);
|
||||
GNUstepUserConfig(config, userName);
|
||||
ASSIGNCOPY(gnustepUserHome, NSHomeDirectoryForUser(userName));
|
||||
GNUstepUserConfig(config, gnustepUserName);
|
||||
gnustepUserHome = [NSHomeDirectoryForUser(gnustepUserName) copy];
|
||||
ExtractValuesFromConfig(config);
|
||||
|
||||
[gnustep_global_lock unlock];
|
||||
|
@ -894,6 +986,8 @@ static void InitialisePathUtilities(void)
|
|||
static void ShutdownPathUtilities(void)
|
||||
{
|
||||
DESTROY(gnustepUserHome);
|
||||
DESTROY(gnustepUserID);
|
||||
DESTROY(gnustepUserName);
|
||||
DESTROY(gnustepUserDefaultsDir);
|
||||
|
||||
DESTROY(gnustepMakefiles);
|
||||
|
|
Loading…
Reference in a new issue