mirror of
https://github.com/gnustep/libs-ec.git
synced 2025-02-15 08:01:42 +00:00
347 lines
8.7 KiB
Objective-C
347 lines
8.7 KiB
Objective-C
|
|
/** Enterprise Control Configuration and Logging
|
|
|
|
Copyright (C) 2012 Free Software Foundation, Inc.
|
|
|
|
Written by: Richard Frith-Macdonald <rfm@gnu.org>
|
|
Date: Febrary 2010
|
|
Originally developed from 1996 to 2012 by Brainstorm, and donated to
|
|
the FSF.
|
|
|
|
This file is part of the GNUstep project.
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU Lesser General Public
|
|
License as published by the Free Software Foundation; either
|
|
version 3 of the License, or (at your option) any later version.
|
|
|
|
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.
|
|
|
|
You should have received a copy of the GNU Lesser General Public
|
|
License along with this library; if not, write to the Free
|
|
Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
Boston, MA 02111 USA.
|
|
|
|
*/
|
|
|
|
#import <Foundation/NSArray.h>
|
|
#import <Foundation/NSDictionary.h>
|
|
#import <Foundation/NSEnumerator.h>
|
|
#import <Foundation/NSLock.h>
|
|
#import <Foundation/NSObjCRuntime.h>
|
|
#import <Foundation/NSRunLoop.h>
|
|
#import <Foundation/NSString.h>
|
|
#import <Foundation/NSThread.h>
|
|
|
|
#import "EcUserDefaults.h"
|
|
#import "EcHost.h"
|
|
|
|
static NSRecursiveLock *lock = nil;
|
|
static NSMutableDictionary *fromWellKnown = nil;
|
|
static NSMutableDictionary *toWellKnown = nil;
|
|
static NSString *controlName = nil;
|
|
|
|
@implementation NSHost (EcHost)
|
|
|
|
typedef NSHost *(*hwnType)(Class c, SEL s, NSString *n);
|
|
static IMP hwnImp; // Original +hostWithName: implementation
|
|
|
|
/* This method is used to replace +[NSHost hostWithName:]
|
|
* First it checks to see if the supplied name is a well known name aliasing
|
|
* another. Then it performs the host lookup using the original method.
|
|
*/
|
|
+ (NSHost*) _hostWithName: (NSString*)aName
|
|
{
|
|
NSHost *found = nil;
|
|
|
|
if (YES == [aName isKindOfClass: [NSString class]])
|
|
{
|
|
NSString *rep;
|
|
|
|
[lock lock];
|
|
if (nil != (rep = [fromWellKnown objectForKey: aName]))
|
|
{
|
|
aName = [[rep retain] autorelease];
|
|
}
|
|
[lock unlock];
|
|
found = ((hwnType)hwnImp)(self, @selector(hostWithName:), aName);
|
|
}
|
|
return found;
|
|
}
|
|
|
|
+ (void) _EcHostSetup
|
|
{
|
|
if (nil == lock)
|
|
{
|
|
if (YES == [NSThread isMainThread])
|
|
{
|
|
NSUserDefaults *defs;
|
|
NSString *name;
|
|
NSHost *host;
|
|
NSRecursiveLock *l;
|
|
|
|
/* Create the lock locked ... until it is unlocked all other
|
|
* threads are waiting for this method to complete, and we
|
|
* can do what we like.
|
|
*/
|
|
l = [NSRecursiveLock new];
|
|
[l lock];
|
|
lock = l;
|
|
fromWellKnown = [NSMutableDictionary alloc];
|
|
toWellKnown = [NSMutableDictionary alloc];
|
|
|
|
/* We need to override the class method of NSHost so that it
|
|
* knows about well known host names.
|
|
*/
|
|
Method m;
|
|
IMP r;
|
|
|
|
m = class_getClassMethod(self, @selector(_hostWithName:));
|
|
r = method_getImplementation(m);
|
|
m = class_getClassMethod([NSHost class], @selector(hostWithName:));
|
|
hwnImp = method_setImplementation(m, r);
|
|
|
|
/* Perform initial setup of control host and current host
|
|
* from user defaults system.
|
|
*/
|
|
defs = [NSUserDefaults prefixedDefaults];
|
|
if (nil == defs)
|
|
{
|
|
defs = [NSUserDefaults userDefaultsWithPrefix: nil];
|
|
}
|
|
name = [defs stringForKey: @"ControlHost"];
|
|
if (nil != name)
|
|
{
|
|
controlName = [name copy];
|
|
|
|
/* Use mapping from domain name to well known name.
|
|
*/
|
|
name = [defs stringForKey: @"ControlDomain"];
|
|
}
|
|
else if (nil != (name = [defs stringForKey: @"ControlDomain"]))
|
|
{
|
|
/* Use domain name as the known name.
|
|
*/
|
|
controlName = [name copy];
|
|
}
|
|
if (nil != name)
|
|
{
|
|
host = ((hwnType)hwnImp)(self, @selector(hostWithName:), name);
|
|
if (nil == host)
|
|
{
|
|
/* No such host ... set up name mapping in case
|
|
* the host becomes available later.
|
|
*/
|
|
[toWellKnown setObject: controlName forKey: name];
|
|
[fromWellKnown setObject: name forKey: controlName];
|
|
}
|
|
else
|
|
{
|
|
[host setWellKnownName: controlName];
|
|
}
|
|
}
|
|
host = [self currentHost];
|
|
name = [defs stringForKey: @"CurrentHost"];
|
|
if (nil == name)
|
|
{
|
|
/* If the current host is the control host, we may have the
|
|
* well known name set already, but if we don't this method
|
|
* will select an arbitrary name that we can use.
|
|
*/
|
|
name = [host wellKnownName];
|
|
}
|
|
[host setWellKnownName: name];
|
|
|
|
[lock unlock];
|
|
}
|
|
else
|
|
{
|
|
NSArray *modes;
|
|
|
|
modes = [NSArray arrayWithObject: NSDefaultRunLoopMode];
|
|
[self performSelectorOnMainThread: _cmd
|
|
withObject: nil
|
|
waitUntilDone: YES
|
|
modes: modes];
|
|
}
|
|
}
|
|
}
|
|
|
|
+ (NSString*) controlWellKnownName
|
|
{
|
|
if (nil == lock) [self _EcHostSetup];
|
|
return controlName;
|
|
}
|
|
|
|
+ (NSHost*) hostWithWellKnownName: (NSString*)aName
|
|
{
|
|
NSHost *found = nil;
|
|
|
|
if (nil == lock) [self _EcHostSetup];
|
|
if (YES == [aName isKindOfClass: [NSString class]])
|
|
{
|
|
[lock lock];
|
|
aName = [[[fromWellKnown objectForKey: aName] retain] autorelease];
|
|
[lock unlock];
|
|
if (nil != aName)
|
|
{
|
|
found = ((hwnType)hwnImp)(self, @selector(hostWithName:), aName);
|
|
}
|
|
}
|
|
return found;
|
|
}
|
|
|
|
+ (void) setWellKnownNames: (NSDictionary*)map
|
|
{
|
|
if (nil == lock) [self _EcHostSetup];
|
|
if ([map isKindOfClass: [NSDictionary class]])
|
|
{
|
|
NSEnumerator *e;
|
|
NSString *k;
|
|
|
|
e = [map keyEnumerator];
|
|
while (nil != (k = [e nextObject]))
|
|
{
|
|
NSString *v = [map objectForKey: k];
|
|
|
|
if ([k isKindOfClass: [NSString class]]
|
|
&& [v isKindOfClass: [NSString class]])
|
|
{
|
|
NSHost *h;
|
|
|
|
h = ((hwnType)hwnImp)(self, @selector(hostWithName:), k);
|
|
if (nil == h)
|
|
{
|
|
NSEnumerator *e;
|
|
NSString *name;
|
|
|
|
/* No such host ... set up name mapping in case
|
|
* the host becomes available later.
|
|
*/
|
|
|
|
[lock lock];
|
|
/* Remove any existing names which map to this new
|
|
* well known name.
|
|
*/
|
|
e = [[toWellKnown allKeys] objectEnumerator];
|
|
while (nil != (name = [e nextObject]))
|
|
{
|
|
NSString *wellKnown;
|
|
|
|
wellKnown = [toWellKnown objectForKey: name];
|
|
if ([wellKnown isEqualToString: v])
|
|
{
|
|
[toWellKnown removeObjectForKey: name];
|
|
}
|
|
}
|
|
/* Set up the specified mappings to and from the new
|
|
* well known name and its normal host name.
|
|
*/
|
|
[toWellKnown setObject: v forKey: k];
|
|
[fromWellKnown setObject: k forKey: v];
|
|
[lock unlock];
|
|
}
|
|
else
|
|
{
|
|
/* We have found a host with the specified names ...
|
|
* so set the well known name for it.
|
|
*/
|
|
[h setWellKnownName: v];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
- (void) setWellKnownName: (NSString*)aName
|
|
{
|
|
if (nil == lock) [[self class] _EcHostSetup];
|
|
if ([aName isKindOfClass: [NSString class]])
|
|
{
|
|
NSEnumerator *e;
|
|
NSString *name;
|
|
|
|
[lock lock];
|
|
|
|
/* Set a mapping to this host from the well known name.
|
|
*/
|
|
name = [self name];
|
|
if (nil == name)
|
|
{
|
|
name = [self address];
|
|
}
|
|
[fromWellKnown setObject: name forKey: aName];
|
|
|
|
/* Remove any old mappings to this well known name.
|
|
*/
|
|
e = [[toWellKnown allKeys] objectEnumerator];
|
|
while (nil != (name = [e nextObject]))
|
|
{
|
|
if ([[toWellKnown objectForKey: name] isEqualToString: aName])
|
|
{
|
|
[toWellKnown removeObjectForKey: name];
|
|
}
|
|
}
|
|
|
|
/* Add mappings to the well known name from any of our names.
|
|
*/
|
|
e = [[self names] objectEnumerator];
|
|
while (nil != (name = [e nextObject]))
|
|
{
|
|
[toWellKnown setObject: aName forKey: name];
|
|
}
|
|
|
|
/* Add mappings to the well known name from any of our addresses.
|
|
*/
|
|
e = [[self addresses] objectEnumerator];
|
|
while (nil != (name = [e nextObject]))
|
|
{
|
|
[toWellKnown setObject: aName forKey: name];
|
|
}
|
|
|
|
[lock unlock];
|
|
}
|
|
}
|
|
|
|
- (NSString*) wellKnownName
|
|
{
|
|
NSString *found;
|
|
|
|
if (nil == lock) [[self class] _EcHostSetup];
|
|
[lock lock];
|
|
found = [[[toWellKnown objectForKey: [self name]] retain] autorelease];
|
|
if (nil == found)
|
|
{
|
|
NSEnumerator *e;
|
|
NSString *name;
|
|
|
|
e = [[self names] objectEnumerator];
|
|
while (nil == found && nil != (name = [e nextObject]))
|
|
{
|
|
found = [[[toWellKnown objectForKey: name] retain] autorelease];
|
|
}
|
|
if (nil == found)
|
|
{
|
|
e = [[self addresses] objectEnumerator];
|
|
while (nil == found && nil != (name = [e nextObject]))
|
|
{
|
|
found = [[[toWellKnown objectForKey: name] retain] autorelease];
|
|
}
|
|
}
|
|
}
|
|
[lock unlock];
|
|
if (nil == found)
|
|
{
|
|
found = [self name];
|
|
if (nil == found)
|
|
{
|
|
found = [self address];
|
|
}
|
|
}
|
|
return found;
|
|
}
|
|
@end
|
|
|