From c0edbf834bf93640d59640218b43e6def672aecb Mon Sep 17 00:00:00 2001 From: Adam Fedor Date: Wed, 26 Nov 1997 21:15:12 +0000 Subject: [PATCH] DO patch from Frith-Macdonald. Makefile changes. git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@2659 72102866-910b-0410-8b05-ffd578937521 --- ChangeLog | 58 +++++++- Examples/GNUmakefile | 2 +- Headers/gnustep/base/DistributedObjects.h | 7 +- Headers/gnustep/base/NSPortCoder.h | 2 - Headers/gnustep/base/NSUserDefaults.h | 4 + Source/Makefile.postamble | 3 + Source/NSConnection.m | 165 ++++++++++++++++++---- Source/NSDistantObject.m | 32 ++++- Source/NSUserDefaults.m | 45 +++--- Source/ostream.m | 4 +- Testing/GNUmakefile | 2 +- Tools/GNUmakefile | 2 +- Tools/dwrite.m | 2 +- 13 files changed, 268 insertions(+), 60 deletions(-) diff --git a/ChangeLog b/ChangeLog index e27cad1b2..2805e925d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,7 +1,61 @@ +Wed Nov 26 16:08:20 1997 Adam Fedor + + * Tools/GNUmakefile (OBJC-PROGRAM_NAME): Change from underscore. + * checks/GNUmakefile: include new test-tool.make. + * examples/GNUmakefile: Likewise. + * src/Makefile.postamble (FORCE): New target. + + * src/ostream.m (_ostream_new_stream_struct): Use "r+" for append + or read/write mode. + +Wed Nov 26 11:30:00 1997 Richard Frith-Macdonald + + * Tools/dwrite.m: Fix problem with uninitialised variable. + + * src/NSConnection.m: Added [+connectionByOutPort:] and + [+connectionByInPort:OutPort:] methods to lookup connections for + use by other barts of the DO system. + Added [-_service_retain:] and [-retainTraget:] methods to handle + special case of retaining of proxies. + + * src/NSDistantObject.m: ([+newWithCoder:]) modified to fix two + problems to do with proxies passed in a triangle - + 1. if passed a proxy to an object in a third server, use any + existing connection to that third server if possible rather + than creating a new connection. + 2. if passed a proxy to an object in a third server, tell the + third server to retain it's local object for us. + + * src/NSUserDefaults.m: various modifications to fix for getting + the defaults for a user other than the logged in user - eg when a + server process runs setuid to a particular user ID and wants to + read the defaults for that user rather than the user who actually + launched it. Also - added code to break the lock on the defaults + database if it is more than five minutes old. + + * src/include/DistributedObjects.h: modifications for retaining + objects. + + * src/include/NSPortCoder.h: removed unneccessary include. + + * src/include/NSUserDefaults.h: minor changes for coping with + tasks runnning setuid to a user other than the person who launched + them. + +Fri Nov 21 13:14:31 1997 Adam Fedor + + * src/NSAttributedString.m (-initWIthString:attributes:): Make + designated initializer. + * src/NSGAttributedString.m: (_initWithString): Save value of + textChars. + * src/include/NSAttributedString.h: Update comments, Remove + attribute strings. + Fixes submitted by . + Tue Nov 18 14:13:13 1997 Adam Fedor - * src/NSNotification.h: Correct placeholder size (bug submitted by - Ville-Pertti Keinonen . + * src/include/NSNotification.h: Correct placeholder size (bug + submitted by Ville-Pertti Keinonen . Wed Nov 12 10:10:33 1997 Adam Fedor diff --git a/Examples/GNUmakefile b/Examples/GNUmakefile index b00b2c91b..50bd77bf6 100644 --- a/Examples/GNUmakefile +++ b/Examples/GNUmakefile @@ -61,6 +61,6 @@ custom-zone.m -include Makefile.preamble -include $(GNUSTEP_SYSTEM_ROOT)/Makefiles/test.make +include $(GNUSTEP_SYSTEM_ROOT)/Makefiles/test-tool.make -include Makefile.postamble diff --git a/Headers/gnustep/base/DistributedObjects.h b/Headers/gnustep/base/DistributedObjects.h index c1123a927..65b5384b0 100644 --- a/Headers/gnustep/base/DistributedObjects.h +++ b/Headers/gnustep/base/DistributedObjects.h @@ -60,7 +60,8 @@ enum { CONNECTION_SHUTDOWN, METHODTYPE_REQUEST, /* these two only needed with NeXT runtime */ METHODTYPE_REPLY, /* these two only needed with NeXT runtime */ - PROXY_RELEASE + PROXY_RELEASE, + PROXY_RETAIN }; @@ -70,8 +71,12 @@ enum { * by NSDistantObject et al for implementation of Distributed objects. */ @interface NSConnection (Internal) ++ (NSConnection*) connectionByInPort: (NSPort*)ip + outPort: (NSPort*)op; ++ (NSConnection*) connectionByOutPort: (NSPort*)op; - (NSDistantObject*) localForTarget: (void*)target; - (NSDistantObject*) proxyForTarget: (void*)target; +- (void) retainTarget: (unsigned)target; - (void) setNotOwned; @end diff --git a/Headers/gnustep/base/NSPortCoder.h b/Headers/gnustep/base/NSPortCoder.h index 6129a44bd..ac4c72c06 100644 --- a/Headers/gnustep/base/NSPortCoder.h +++ b/Headers/gnustep/base/NSPortCoder.h @@ -28,8 +28,6 @@ #include #include -#include - @class NSConnection; @interface NSPortCoder : NSCoder diff --git a/Headers/gnustep/base/NSUserDefaults.h b/Headers/gnustep/base/NSUserDefaults.h index baf6fa662..503c69c45 100644 --- a/Headers/gnustep/base/NSUserDefaults.h +++ b/Headers/gnustep/base/NSUserDefaults.h @@ -27,6 +27,7 @@ #include #include +#include @class NSArray; @class NSMutableArray; @@ -119,6 +120,9 @@ extern NSString *NSHomeDirectoryForUser(NSString * userName); NSMutableDictionary *tempDomains; // Contains volatile defaults info; NSMutableArray *changedDomains; /* ..after first time that persistent user defaults are changed */ + NSMutableString *defaultsDatabase; + NSMutableString *defaultsDatabaseLockName; + NSDistributedLock *defaultsDatabaseLock; BOOL tickingTimer; // for synchronization } diff --git a/Source/Makefile.postamble b/Source/Makefile.postamble index 74b21f1d7..65de299d5 100644 --- a/Source/Makefile.postamble +++ b/Source/Makefile.postamble @@ -223,3 +223,6 @@ copy-dist: $(DIST_FILES) ln $$file ../snap/src/include/`basename $$file` ; \ done ln AUTHORS ../snap + +FORCE: + diff --git a/Source/NSConnection.m b/Source/NSConnection.m index e6d9dcce8..fed6b4fa6 100644 --- a/Source/NSConnection.m +++ b/Source/NSConnection.m @@ -359,6 +359,18 @@ static int messages_received_count; return newConn; } +/* xxx This method is an anomaly, just until we get a proper name + server for port objects. Richard Frith-MacDonald is working on a + name server. */ +- (BOOL) registerName: (NSString*)name +{ + id old_receive_port = receive_port; + receive_port = [default_receive_port_class newForReceivingFromRegisteredName: name]; + [old_receive_port release]; + return YES; +} + + /* * Keep track of connections created by DO system but not necessarily * ever retained by users code. These must be retained now for later @@ -737,18 +749,6 @@ static int messages_received_count; return newRemote; } -/* xxx This method is an anomaly, just until we get a proper name - server for port objects. Richard Frith-MacDonald is working on a - name server. */ -- (BOOL) registerName: (NSString*)name -{ - id old_receive_port = receive_port; - receive_port = [default_receive_port_class newForReceivingFromRegisteredName: name]; - [old_receive_port release]; - return YES; -} - - /* This is the designated initializer for NSConnection */ @@ -756,28 +756,15 @@ static int messages_received_count; ancestorConnection: ancestor { NSConnection *newConn; - int i, count; - id newConnInPort, newConnOutPort; NSParameterAssert (ip); - [connection_array_gate lock]; - /* Find previously existing connection if there */ - /* xxx Clean this up */ - count = [connection_array count]; - for (i = 0; i < count; i++) - { - newConn = [connection_array objectAtIndex: i]; - newConnInPort = [newConn receivePort]; - newConnOutPort = [newConn sendPort]; - if ([newConnInPort isEqual: ip] - && [newConnOutPort isEqual: op]) - { - [connection_array_gate unlock]; - return [newConn retain]; - } - } + newConn = [[self connectionByInPort: ip outPort: op] retain]; + if (newConn) + return newConn; + + [connection_array_gate lock]; newConn = [[NSConnection alloc] _superInit]; if (debug_connection) @@ -920,6 +907,62 @@ static int messages_received_count; return newConn; } ++ (NSConnection*) connectionByInPort: (NSPort*)ip + outPort: (NSPort*)op +{ + int count; + int i; + + NSParameterAssert (ip); + + [connection_array_gate lock]; + count = [connection_array count]; + for (i = 0; i < count; i++) + { + id newConnInPort; + id newConnOutPort; + NSConnection *newConn; + + newConn = [connection_array objectAtIndex: i]; + newConnInPort = [newConn receivePort]; + newConnOutPort = [newConn sendPort]; + if ([newConnInPort isEqual: ip] + && [newConnOutPort isEqual: op]) + { + [connection_array_gate unlock]; + return newConn; + } + } + [connection_array_gate unlock]; + return nil; +} + ++ (NSConnection*) connectionByOutPort: (NSPort*)op +{ + int i, count; + + NSParameterAssert (op); + + [connection_array_gate lock]; + + count = [connection_array count]; + for (i = 0; i < count; i++) + { + id newConnOutPort; + NSConnection *newConn; + + newConn = [connection_array objectAtIndex: i]; + newConnOutPort = [newConn sendPort]; + if ([newConnOutPort isEqual: op]) + { + [connection_array_gate unlock]; + return newConn; + } + } + [connection_array_gate unlock]; + return nil; +} + - _superInit { [super init]; @@ -1245,6 +1288,30 @@ static int messages_received_count; [rmc dismiss]; } +- (void) _service_retain: rmc forConnection: receiving_connection +{ + unsigned int target; + + NSParameterAssert (is_valid); + + if ([rmc connection] != self) { + [NSException raise: @"ProxyDecodedBadTarget" + format: @"request to retain object on bad connection"]; + } + + [rmc decodeValueOfCType: @encode(typeof(target)) + at: &target + withName: NULL]; + + if ([self includesLocalObject:(void*)target] == NO) { + if ([[self class] includesLocalObject:(void*)target] == YES) { + [NSDistantObject proxyWithLocal: (id)target connection: self]; + } + } + + [rmc dismiss]; +} + - (void) shutdown { id op; @@ -1416,6 +1483,11 @@ static int messages_received_count; [conn _service_release: rmc forConnection: self]; break; } + case PROXY_RETAIN: + { + [conn _service_retain: rmc forConnection: self]; + break; + } default: [conn release]; [NSException raise: NSGenericException @@ -1641,6 +1713,39 @@ static int messages_received_count; NS_ENDHANDLER } +- (void) retainTarget: (unsigned int)target +{ + NS_DURING + { + /* + * Tell the remote app that it must retain the local object + * for the target on this connection. + */ + if (receive_port && is_valid) { + id op; + unsigned int i; + + op = [[self encodingClass] + newForWritingWithConnection: self + sequenceNumber: [self _newMsgNumber] + identifier: PROXY_RETAIN]; + + [op encodeValueOfCType: @encode(typeof(target)) + at: &target + withName: NULL]; + + [op dismiss]; + } + } + NS_HANDLER + { + if (debug_connection) + fprintf (stderr, "failed to retain target - %s\n", + [[localException name] cStringNoCopy]); + } + NS_ENDHANDLER +} + - (void) removeProxy: (NSDistantObject*)aProxy { unsigned target = (unsigned)[aProxy targetForProxy]; diff --git a/Source/NSDistantObject.m b/Source/NSDistantObject.m index 5d5894a9e..2c377e93e 100644 --- a/Source/NSDistantObject.m +++ b/Source/NSDistantObject.m @@ -415,6 +415,7 @@ format: @"NSDistantObject objects only decode with PortDecoder class"]; * inPort/outPort pair, or create a new connection if necessary. */ { + NSDistantObject *result; NSConnection *proxy_connection; NSPort* proxy_connection_out_port = nil; @@ -426,7 +427,27 @@ format: @"NSDistantObject objects only decode with PortDecoder class"]; withName: NULL]; assert (proxy_connection_out_port); + /* xxx - if there already exists a connection for talking to the + * out port, we use that one rather than creating a new one from + * our listening port. + * + * First we try for a connection from our receive port, + * Then we try any connection to the send port + * Finally we resort to creating a new connection - we don't + * release the newly created connection - it will get released + * automatically when no proxies are left on it. + */ proxy_connection = [[decoder_connection class] + connectionByInPort: + [decoder_connection receivePort] + outPort: + proxy_connection_out_port]; + if (proxy_connection == nil) + proxy_connection = [[decoder_connection class] + connectionByOutPort: + proxy_connection_out_port]; + if (proxy_connection == nil) + proxy_connection = [[decoder_connection class] newForInPort: [decoder_connection receivePort] outPort: proxy_connection_out_port ancestorConnection: decoder_connection]; @@ -438,8 +459,17 @@ format: @"NSDistantObject objects only decode with PortDecoder class"]; assert (proxy_connection != decoder_connection); assert ([proxy_connection isValid]); - return [[NSDistantObject proxyWithTarget: (id)target + /* + * If we don't already have a proxy for the object on the + * remote system, we must tell the other end to retain its + * local object for our use. + */ + if ([proxy_connection includesProxyForTarget: target] == NO) + [proxy_connection retainTarget: target]; + + result = [[NSDistantObject proxyWithTarget: (id)target connection: proxy_connection] retain]; + return result; } default: diff --git a/Source/NSUserDefaults.m b/Source/NSUserDefaults.m index 919fa7d11..fbe2e2e50 100644 --- a/Source/NSUserDefaults.m +++ b/Source/NSUserDefaults.m @@ -71,9 +71,6 @@ static NSString* GNU_UserDefaultsDatabaseLock = @"GNUstep/.GNUstepUDLock"; *** Class variables *************************************************************************/ static NSUserDefaults *sharedDefaults = nil; -static NSMutableString *defaultsDatabase = nil; -static NSMutableString *defaultsDatabaseLockName = nil; -static NSDistributedLock *defaultsDatabaseLock = nil; static NSMutableString *processName = nil; /************************************************************************* @@ -165,10 +162,11 @@ static NSMutableString *processName = nil; // Either userName is empty or it's wrong if (!userHome) { - [self release]; /* xxx really? -mccallum. */ + [self dealloc]; return nil; } - filename = [userHome stringByAppendingString: GNU_UserDefaultsDatabase]; + filename = [NSString stringWithFormat: @"%@/%@", + userHome, GNU_UserDefaultsDatabase]; return [self initWithContentsOfFile: filename]; } @@ -181,21 +179,31 @@ static NSMutableString *processName = nil; // Find the user's home folder and build the paths (executed only once) if (!defaultsDatabase) { - defaultsDatabase = + if (path != nil && [path isEqual: @""] == NO) + defaultsDatabase = [path copy]; + else + defaultsDatabase = [[NSMutableString stringWithFormat:@"%@/%@", NSHomeDirectoryForUser(NSUserName()), GNU_UserDefaultsDatabase] retain]; - defaultsDatabaseLockName = - [[NSMutableString stringWithFormat:@"%@/%@", + + if ([[defaultsDatabase lastPathComponent] isEqual: + [GNU_UserDefaultsDatabase lastPathComponent]] == YES) + defaultsDatabaseLockName = + [[NSMutableString stringWithFormat:@"%@/%@", + [defaultsDatabase stringByDeletingLastPathComponent], + [GNU_UserDefaultsDatabaseLock lastPathComponent]] + retain]; + else + defaultsDatabaseLockName = + [[NSMutableString stringWithFormat:@"%@/%@", NSHomeDirectoryForUser(NSUserName()), GNU_UserDefaultsDatabaseLock] retain]; defaultsDatabaseLock = [[NSDistributedLock lockWithPath: defaultsDatabaseLockName] retain]; - processName = [[[NSProcessInfo processInfo] processName] retain]; -#if 0 - processName = [[NSMutableString stringWithFormat:@"TestApp"] retain]; -#endif } + if (processName == nil) + processName = [[[NSProcessInfo processInfo] processName] retain]; // Create an empty search list searchList = [[NSMutableArray arrayWithCapacity:10] retain]; @@ -468,12 +476,13 @@ static NSMutableString *processName = nil; tickingTimer = NO; - // Get file lock + // Get file lock - break any lock that is more than five minute old. if ([defaultsDatabaseLock tryLock] == NO) + if ([[defaultsDatabaseLock lockDate] timeIntervalSinceNow] < 300.0) { - NSLog(@"unable to access defaults database - locked on (%@) since %@\n", - defaultsDatabaseLockName, [defaultsDatabaseLock lockDate]); - return NO; + [defaultsDatabaseLock breakLock]; + if ([defaultsDatabaseLock tryLock] == NO) + return NO; } // Read the persistent data from the stored database @@ -484,7 +493,7 @@ static NSMutableString *processName = nil; initWithCapacity:1]; if (changedDomains) - { // Synchronize bpth dictionaries + { // Synchronize both dictionaries NSEnumerator *enumerator = [changedDomains objectEnumerator]; id obj, dict; @@ -501,7 +510,7 @@ static NSMutableString *processName = nil; // Save the changes if (![persDomains writeToFile:defaultsDatabase atomically:YES]) { - NSLog(@"failed to write defaults to '%@'\n", defaultsDatabase); +// NSLog(@"failed to write defaults to '%@'\n", defaultsDatabase); [defaultsDatabaseLock unlock]; return NO; } diff --git a/Source/ostream.m b/Source/ostream.m index 04a7b3096..99ed4360b 100644 --- a/Source/ostream.m +++ b/Source/ostream.m @@ -212,12 +212,12 @@ _ostream_new_stream_struct (int mode, char** cmode) stream->flags |= OSTREAM_WRITEFLAG; break; case OSTREAM_READWRITE: - fmode = "w+"; + fmode = "r+"; stream->flags |= OSTREAM_READFLAG; stream->flags |= OSTREAM_WRITEFLAG; break; case OSTREAM_APPEND: - fmode = "w"; + fmode = "r+"; stream->flags |= OSTREAM_WRITEFLAG; break; default: diff --git a/Testing/GNUmakefile b/Testing/GNUmakefile index d7f62e950..77583dfae 100644 --- a/Testing/GNUmakefile +++ b/Testing/GNUmakefile @@ -156,6 +156,6 @@ DIST_FILES = $(SRCS) $(HDRS) $(DYNAMIC_MFILES) $(DYNAMIC_HFILES) \ -include Makefile.preamble -include $(GNUSTEP_SYSTEM_ROOT)/Makefiles/test.make +include $(GNUSTEP_SYSTEM_ROOT)/Makefiles/test-tool.make -include Makefile.postamble diff --git a/Tools/GNUmakefile b/Tools/GNUmakefile index 9198262e7..cd2cd664e 100644 --- a/Tools/GNUmakefile +++ b/Tools/GNUmakefile @@ -27,7 +27,7 @@ include $(GNUSTEP_SYSTEM_ROOT)/Makefiles/common.make # The application to be compiled TOOL_NAME = dread dwrite dremove -OBJC_PROGRAM_NAME = gdomap +OBJC-PROGRAM_NAME = gdomap # The source files to be compiled gdomap_C_FILES = gdomap.c diff --git a/Tools/dwrite.m b/Tools/dwrite.m index 036a83e1a..c36bf5c67 100644 --- a/Tools/dwrite.m +++ b/Tools/dwrite.m @@ -39,7 +39,7 @@ main(int argc, char** argv) NSString *name; NSString *value; const char *text; - id obj; + id obj = nil; int i; [NSObject enableDoubleReleaseCheck: YES];