diff --git a/AUTHORS b/AUTHORS index 361e3770e..d3fad9a49 100644 --- a/AUTHORS +++ b/AUTHORS @@ -37,7 +37,6 @@ OrderedCollection.m Port.m Proxy.m Queue.m -Random.m RawCStream.m RBTree.m RBTreeNode.m @@ -198,6 +197,7 @@ NSPipe.m NSPort.m NSProxy.m NSTask.m +NSUndoManager.m Stevo Crvenkovski: diff --git a/ChangeLog b/ChangeLog index 6206e0a20..0268f4ca7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,8 +1,45 @@ +Fri May 29 10:16:09 1998 Adam Fedor + + * doc/news.tmpl.texi: Fixed typo. + * doc/readme.tmpl.texi: Likewise. (patch from doko@cs.tu-berlin.de + (Matthias Klose)). + * src/ostream.m (ostream_save_buffer): Retain stream. + * src/include/MemoryStream.h: Remove outdated methods. + * src/include/NSException.h (NS_VALUERETURN): New macro. + +Thu May 28 10:45:00 1998 Richard Frith-Macdonald + + * Tools/gdomap.c: Added code to cope with systems where we can't + determine what network interfaces are active. + + * checks/heap.m: Portability fix for svr4 systems. + + * configure.in: Improved portability to svr4 systems. + + * src/NSMethodSignature.m: Changed order of includes to fix + compilation on svr4 systems. + + * src/NSPage.m: Altered to use 'sysconf(_SC_PAGESIZE)' to get page + size on svr4 systems. + + * src/NSTask.m: Altered to use 'kill()' rather than 'killpg()' on + svr4 + + * src/NSThread.m: Altered to use 'sleep()' rather than 'usleep()' + on svr4 + + * src/include/config.h.in: Added a couple of configuration + constants for portability - HAVE_KILLPG and HAVE_USLEEP + Thu May 21 09:38:14 1998 Adam Fedor * src/NSUser.m (NSUserName): Use getpwuid for BSD machines (patch provided by Stefanos Kiakas ). + * src/GetDefEncoding.c (GetDefEncoding): Change binary AND to + logical AND. (GetEncoding): Likewise (patch provided by + David Fritzsche ). + Wed May 20 15:26:50 1998 Richard Frith-Macdonald * src/GNUmakefile: Added NSUndoManager.[hm] diff --git a/Documentation/gnustep-base.tmpl.texi b/Documentation/gnustep-base.tmpl.texi index bac8ca80b..22a220202 100644 --- a/Documentation/gnustep-base.tmpl.texi +++ b/Documentation/gnustep-base.tmpl.texi @@ -52,10 +52,10 @@ into another language, under the above conditions for modified versions. @finalout @titlepage @title The GNUstep BASE Library -@subtitle DRAFT Edition for GNUstep BASE Library @value{GNUSTEP-BASE-VERSION} -@subtitle Last revision Jan 1998 +@c @subtitle DRAFT Edition for GNUstep BASE Library @value{GNUSTEP-BASE-VERSION} +@c @subtitle Last revision Jan 1998 @c @subtitle For GCC Version @value{GNUSTEP-BASE-GCC} -@author Andrew McCallum +@c @author Andrew McCallum @page @vskip 0pt plus 1filll diff --git a/Documentation/news.tmpl.texi b/Documentation/news.tmpl.texi index 9426a7b01..cc36413e8 100644 --- a/Documentation/news.tmpl.texi +++ b/Documentation/news.tmpl.texi @@ -14,7 +14,7 @@ The currently released version of the library is @item Additional runtime functions for interaction with Guile and ObjC-Guile library. -#end itemize +@end itemize @section Noteworthy changes in version @samp{0.5.0} diff --git a/Documentation/readme.tmpl.texi b/Documentation/readme.tmpl.texi index 54f2a836c..ee7e19ef6 100644 --- a/Documentation/readme.tmpl.texi +++ b/Documentation/readme.tmpl.texi @@ -100,6 +100,8 @@ separately. This version of the distributed objects only works with sockets. A Mach port back-end should be on the way. +@end itemize + @section Test Programs Some of the programs I've used to test the library are in diff --git a/Documentation/todo.tmpl.texi b/Documentation/todo.tmpl.texi index db57c3a12..7928b6156 100644 --- a/Documentation/todo.tmpl.texi +++ b/Documentation/todo.tmpl.texi @@ -4,16 +4,22 @@ @chapter Todo -This TODO list is out of date. - @section Projects Looking for Volunteers If you think you can do one of these projects, please let me know. Your help is greatly appreciated. Send email to -@samp{mccallum@@gnu.org}. +@samp{fedor@@gnu.org}. @itemize @bullet +@item Fix NSLog so it conforms to specs. Need to check that write to +stderr went ok, and if not write to syslog. Also need to serealize +output (with threads). + +@item Simplify NSException and NSAssertionHandler and make sure they +don't cause race conditions (if an exception is raised while processing +an exception. + @item Fix all the places marked FIXME or xxx. @item Need to improve the testsuite and actually run it on gstep-base. @@ -86,13 +92,6 @@ RunLoop properly. @item Make the NSTimer's work and interoperate with the RunLoop properly. -@item Fix many memory allocation inconsistencies. Methods that return -malloc'ed buffers should autorelease those buffers, (like readFormat:). -(I think all these are fixed now.) - -@item Many code fixes and cleanups, indicated with @samp{xxx} in the -source. - @item Add Coding methods to all the collection classes. @item Finish Collection heirarchy clean ups. We need non-mutable @@ -101,12 +100,6 @@ version for many of the classes. @item Possibly change implementation of @code{-(int)compare:anObject} for Collection. How should non-Indexed collections be ordered? -@item -Fix all the subclassResponsibility comments in objects/*.h - -@item -I will finish gnustep-base documentation. - @end itemize @c ================================================================== @@ -134,11 +127,6 @@ must be initialized to some consistent state. -allocCopy would never even get called. <> -@item -If you don't like the organization of the documentation and you have -suggestions for changes, please say so now, not after it's all been -written. - @item Does anyone really need the ability to set the collection element comparison function independent of the -compare: method? @@ -153,17 +141,6 @@ Something like this needed? - elementDidChange: (elt*)elementPtr; Currently you have to remove, change, add, for some classes. -@c ------------------------------------------------------------------- -@c @section Questions leftover from last release - -@item -I've been told that GNU filenames should be 14 chars or less. I -don't want to abbreviate my classnames, but I think using .h -@@interface files with names different than the class name is even -worse. ** I want to keep my unabbreviated filenames!! ** What to do, -what to do... I can't believe that *all* GNU classnames will be -limited to 12 characters forever and ever---disgusting. - @end itemize diff --git a/Headers/gnustep/base/Foundation.h b/Headers/gnustep/base/Foundation.h index 39b35f804..a36ece882 100644 --- a/Headers/gnustep/base/Foundation.h +++ b/Headers/gnustep/base/Foundation.h @@ -30,19 +30,20 @@ #include #include #include -#include #include +#include +#include #include #include #include -#include -#include -#include +#include #include -#include +#include #include #include #include +#include +#include #include #endif /* __Foundation_h_GNUSTEP_BASE_INCLUDE */ diff --git a/Headers/gnustep/base/MemoryStream.h b/Headers/gnustep/base/MemoryStream.h index 34693c78d..1f32ea815 100644 --- a/Headers/gnustep/base/MemoryStream.h +++ b/Headers/gnustep/base/MemoryStream.h @@ -65,7 +65,9 @@ prefix: (unsigned)prefix; - initWithData: (id)anObject; +#if 0 - initWithSize: (unsigned)s; /* For backwards compatibility, depricated */ +#endif - (id) data; - (id) mutableData; diff --git a/Headers/gnustep/base/NSException.h b/Headers/gnustep/base/NSException.h index 3fe8a2543..55f5b0a6a 100644 --- a/Headers/gnustep/base/NSException.h +++ b/Headers/gnustep/base/NSException.h @@ -117,6 +117,7 @@ extern void _NSRemoveHandler( NSHandler *handler ); #define NS_VALRETURN(val) do { typeof(val) temp = (val); \ _NSRemoveHandler(&NSLocalHandler); \ return(temp); } while (0) +#define NS_VALUERETURN NS_VALRETURN #define NS_VOIDRETURN do { _NSRemoveHandler(&NSLocalHandler); \ return; } while (0) diff --git a/Headers/gnustep/base/config.h.in b/Headers/gnustep/base/config.h.in index 84f2ef059..70f2896db 100644 --- a/Headers/gnustep/base/config.h.in +++ b/Headers/gnustep/base/config.h.in @@ -30,6 +30,9 @@ /* Define if you have the inet_aton function. */ #undef HAVE_INET_ATON +/* Define if you have the killpg function. */ +#undef HAVE_KILLPG + /* Define if you have the mmap function. */ #undef HAVE_MMAP @@ -48,6 +51,9 @@ /* Define if you have the times function. */ #undef HAVE_TIMES +/* Define if you have the usleep function. */ +#undef HAVE_USLEEP + /* Define if you have the valloc function. */ #undef HAVE_VALLOC diff --git a/NEWS b/NEWS index e4cd9a7cd..73d2a5281 100644 --- a/NEWS +++ b/NEWS @@ -3,6 +3,12 @@ News The currently released version of the library is `0.5.0'. +Noteworthy changes in version `0.5.1' +===================================== + + * Additional runtime functions for interaction with Guile and + ObjC-Guile library. + Noteworthy changes in version `0.5.0' ===================================== diff --git a/README b/README index 4f0063f55..a337b38a3 100644 --- a/README +++ b/README @@ -107,7 +107,7 @@ protocols by their name: they all end with "ing". Test Programs ============= - Some of the programs I've used to test the library are in + Some of the programs I've used to test the library are in `./checks'. Many of them are pretty messy, (desperately trying to tickle that late night bug), but at least they show some code that works when the library compiles correctly. I'm looking for a volunteer to @@ -116,20 +116,20 @@ write some nicely organized test cases using `dejagnu'. Any takers? How can you help? ================= - * Read the projects and questions in the `TODO' file. If you - can volunteer for any of the projects, or if you have any - useful comments send me email! + * Read the projects and questions in the `TODO' file. If you can + volunteer for any of the projects, or if you have any useful + comments send me email! - * Give me feedback! Tell me what you like; tell me what you - think could be better. Send me bug reports. + * Give me feedback! Tell me what you like; tell me what you think + could be better. Send me bug reports. - * Donate classes. If you write classes that fit in the - libgnustep-base framework, I'd be happy to include them. + * Donate classes. If you write classes that fit in the + libgnustep-base framework, I'd be happy to include them. - Happy hacking! - Andrew McCallum - mccallum@gnu.org - - Adam Fedor - fedor@gnu.org + Happy hacking! + Andrew McCallum + mccallum@gnu.org + + Adam Fedor + fedor@gnu.org diff --git a/STATUS b/STATUS index 40579a139..078b98f12 100644 --- a/STATUS +++ b/STATUS @@ -36,6 +36,7 @@ Classes *NSArray:: [9]* *NSAssertionHandler:: [9]* +*NSAttributedString:: [8]* *NSAutoreleasePool:: [9]* But not exception- safe @@ -71,12 +72,18 @@ Classes *NSDeserializer:: [7]* *NSDictionary:: [8]* *NSDistantObject:: [7]* +*NSDistributedLock:: [7]* *NSEnumerator:: [9]* -*NSException:: [9]* +*NSException:: [9]* But this needs integration with new, better +*NSFileHandle:: [9]* +*NSFileManager:: [9]* +*NSHashTable:: [8]* +*NSHost:: [8]* *NSInvocation:: [3]* *NSLock:: [8]* +*NSMapTable:: [8]* *NSMethodSignature:: [4]* *NSMutableArray:: [8]* *NSMutableCharacterSet:: [7]* @@ -104,6 +111,7 @@ Classes Careful, relationship with GNU String is tricky; this could also use fixing. +*NSTask:: [8]* *NSThread:: [8]* *NSTimeZone:: [8]* *NSTimeZoneDetail:: [8]* diff --git a/Source/GetDefEncoding.m b/Source/GetDefEncoding.m index 587051545..2687a876f 100644 --- a/Source/GetDefEncoding.m +++ b/Source/GetDefEncoding.m @@ -65,7 +65,7 @@ NSStringEncoding GetDefEncoding() if (encoding) { count = 0; - while ((count < str_encoding_table_size) & + while ((count < str_encoding_table_size) && strcmp(str_encoding_table[count].ename,encoding)) { count++; @@ -125,7 +125,7 @@ GetEncodingName(NSStringEncoding encoding) { char* ret; unsigned int count=0; - while ((count < str_encoding_table_size) & + while ((count < str_encoding_table_size) && !(str_encoding_table[count].enc == encoding)) { count++; diff --git a/Source/MemoryStream.m b/Source/MemoryStream.m index eda2e772f..19ee530c9 100644 --- a/Source/MemoryStream.m +++ b/Source/MemoryStream.m @@ -125,6 +125,7 @@ static BOOL debug_memory_stream = NO; } /* xxx This method will disappear. */ +#if 0 - initWithSize: (unsigned)s prefix: (unsigned)p position: (unsigned)i @@ -136,18 +137,27 @@ static BOOL debug_memory_stream = NO; prefix: p position: i]; } +#endif - initWithCapacity: (unsigned)capacity prefix: (unsigned)p { - return [self initWithSize: capacity + return [self _initOnMallocBuffer: 0 + freeWhenDone: YES + size: capacity + eofPosition: 0 prefix: p - position: 0]; + position: i]; } - initWithCapacity: (unsigned)capacity { - return [self initWithSize:capacity prefix:0 position:0]; + return [self _initOnMallocBuffer: 0 + freeWhenDone: YES + size: capacity + eofPosition: 0 + prefix: 0 + position: i]; } - initWithData: (id)anObject @@ -173,10 +183,12 @@ static BOOL debug_memory_stream = NO; return self; } +#if 0 - initWithSize: (unsigned)s { return [self initWithCapacity:s]; } +#endif - init { diff --git a/Source/NSMethodSignature.m b/Source/NSMethodSignature.m index 25b8d1531..423243173 100644 --- a/Source/NSMethodSignature.m +++ b/Source/NSMethodSignature.m @@ -21,6 +21,9 @@ Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include +#include + /* Deal with memchr: */ #if STDC_HEADERS || HAVE_STRING_H #include @@ -37,8 +40,6 @@ /* memory.h and strings.h conflict on some systems. */ #endif /* not STDC_HEADERS and not HAVE_STRING_H */ -#include -#include #include #include #include diff --git a/Source/NSPage.m b/Source/NSPage.m index f93fcb36a..bd463412c 100644 --- a/Source/NSPage.m +++ b/Source/NSPage.m @@ -45,6 +45,10 @@ #define getpagesize() sysconf(_SC_PAGESIZE) #endif +#ifdef __svr4__ +#define getpagesize() sysconf(_SC_PAGESIZE) +#endif + #if __mach__ #define getpagesize vm_page_size #endif diff --git a/Source/NSProcessInfo.m b/Source/NSProcessInfo.m index 36632cfbb..3fbb312b3 100644 --- a/Source/NSProcessInfo.m +++ b/Source/NSProcessInfo.m @@ -325,8 +325,13 @@ int main(int argc, char *argv[], char *env[]) + (NSProcessInfo *)processInfo { // Check if the main() function was successfully called - NSAssert(_gnu_processName && _gnu_arguments && _gnu_environment, - _GNU_MISSING_MAIN_FUNCTION_CALL); + // We can't use NSAssert, which calls NSLog, which calls NSProcessInfo... + if (!(_gnu_processName && _gnu_arguments && _gnu_environment)) + { + _NSLog_printf_handler(_GNU_MISSING_MAIN_FUNCTION_CALL); + [NSException raise: NSInternalInconsistencyException + format: _GNU_MISSING_MAIN_FUNCTION_CALL]; + } if (!_gnu_sharedProcessInfoObject) _gnu_sharedProcessInfoObject = [[_NSConcreteProcessInfo alloc] init]; diff --git a/Source/NSTask.m b/Source/NSTask.m index db8471ace..126e93c61 100644 --- a/Source/NSTask.m +++ b/Source/NSTask.m @@ -335,7 +335,11 @@ NSString *NSTaskDidTerminateNotification = @"NSTaskDidTerminateNotification"; } hasTerminated = YES; +#ifdef HAVE_KILLPG killpg(taskId, SIGTERM); +#else + kill(-taskId, SIGTERM); +#endif if (hasNotified == NO) { [self _sendNotification]; diff --git a/Source/NSThread.m b/Source/NSThread.m index 01c989632..62b24e3bb 100644 --- a/Source/NSThread.m +++ b/Source/NSThread.m @@ -45,6 +45,20 @@ static o_map_t thread_id_2_nsthread; /* Flag indicating whether the objc runtime ever went multi-threaded. */ static BOOL entered_multi_threaded_state; +void gnustep_base_thread_callback() +{ + /* Post a notification if this is the first new thread to be created. + Won't work properly if threads are not all created by this class. + */ + if (!entered_multi_threaded_state) + { + entered_multi_threaded_state = YES; + [NotificationDispatcher + postNotificationName: NSBecomingMultiThreaded + object: nil]; + } +} + @implementation NSThread @@ -59,6 +73,7 @@ static BOOL entered_multi_threaded_state; autorelease]; #endif entered_multi_threaded_state = NO; + objc_set_thread_callback(gnustep_base_thread_callback()); } } @@ -123,20 +138,12 @@ static BOOL entered_multi_threaded_state; toTarget:(id)aTarget withObject:(id)anArgument { - /* Post a notification if this is the first new thread to be created. - Won't work properly if threads are not all created by this class. - xxx Should the notification be done before the new thread starts, - or after? */ - if (!entered_multi_threaded_state) - { - entered_multi_threaded_state = YES; - [NotificationDispatcher - postNotificationName: NSBecomingMultiThreaded - object: nil]; - } - // Have the runtime detach the thread - objc_thread_detach (aSelector, aTarget, anArgument); + if (objc_thread_detach (aSelector, aTarget, anArgument) == NULL) + { + /* This should probably be an exception */ + NSLog(@"Unable to detach thread (unknown error)"); + } /* NOTE we can't create the new NSThread object for this thread here because there would be a race condition. The newly created @@ -177,14 +184,22 @@ static BOOL entered_multi_threaded_state; while (delay > 30.0*60.0) { // sleep 30 minutes +#ifdef HAVE_USLEEP usleep (30*60*1000000); +#else + sleep (30*60); +#endif delay = [date timeIntervalSinceNow]; } // usleep may return early because of signals while (delay > 0) { - usleep (delay*1000000.0); +#ifdef HAVE_USLEEP + usleep (delay*1000000); +#else + sleep (delay); +#endif delay = [date timeIntervalSinceNow]; } } diff --git a/Source/ostream.m b/Source/ostream.m index 523eec04b..b8732ddac 100644 --- a/Source/ostream.m +++ b/Source/ostream.m @@ -346,8 +346,9 @@ ostream_close_memory (ostream *s, int option) { if (s->flags & OSTREAM_ISBUFFER) { + /* Dumb way to save buffer, but what else? */ if (option == OSTREAM_SAVEBUFFER) - [(MemoryStream*)s->stream_obj setFreeWhenDone: NO]; + [(MemoryStream*)s->stream_obj retain]; } ostream_close(s); } diff --git a/TODO b/TODO index 4c2736c0e..31cb3c0e6 100644 --- a/TODO +++ b/TODO @@ -1,13 +1,21 @@ Todo **** -This TODO list is out of date. - Projects Looking for Volunteers =============================== - If you think you can do one of these projects, please let me know. -Your help is greatly appreciated. Send email to `mccallum@gnu.org'. +If you think you can do one of these projects, please let me know. Your +help is greatly appreciated. Send email to `fedor@gnu.org'. + + * Fix NSLog so it conforms to specs. Need to check that write to + stderr went ok, and if not write to syslog. Also need to serealize + output (with threads). + + * Simplify NSException and NSAssertionHandler and make sure they + don't cause race conditions (if an exception is raised while + processing an exception. + + * Fix all the places marked FIXME or xxx. * Need to improve the testsuite and actually run it on gstep-base. @@ -62,12 +70,6 @@ McCallum's To Do's * Make the NSTimer's work and interoperate with the RunLoop properly. - * Fix many memory allocation inconsistencies. Methods that return - malloc'ed buffers should autorelease those buffers, (like - readFormat:). (I think all these are fixed now.) - - * Many code fixes and cleanups, indicated with `xxx' in the source. - * Add Coding methods to all the collection classes. * Finish Collection heirarchy clean ups. We need non-mutable @@ -76,10 +78,6 @@ McCallum's To Do's * Possibly change implementation of `-(int)compare:anObject' for Collection. How should non-Indexed collections be ordered? - * Fix all the subclassResponsibility comments in objects/*.h - - * I will finish gnustep-base documentation. - Questions ========= @@ -102,10 +100,6 @@ Please email your thoughts to mccallum@gnu.ai.mit.edu. a less well-expressed version of what we've just been discussing in email.>> - * If you don't like the organization of the documentation and you - have suggestions for changes, please say so now, not after it's - all been written. - * Does anyone really need the ability to set the collection element comparison function independent of the -compare: method? @@ -116,13 +110,6 @@ Please email your thoughts to mccallum@gnu.ai.mit.edu. * Something like this needed? - elementDidChange: (elt*)elementPtr; Currently you have to remove, change, add, for some classes. - * I've been told that GNU filenames should be 14 chars or less. I - don't want to abbreviate my classnames, but I think using .h - @interface files with names different than the class name is even - worse. ** I want to keep my unabbreviated filenames!! ** What to - do, what to do... I can't believe that *all* GNU classnames will be - limited to 12 characters forever and ever--disgusting. - Albin's To Do List diff --git a/Testing/heap.m b/Testing/heap.m index 94cce5c7c..643fcb685 100644 --- a/Testing/heap.m +++ b/Testing/heap.m @@ -6,7 +6,7 @@ #define N 20 -#if (sun && __svr4__) || defined(__hpux) || defined(_SEQUENT_) +#if defined(__svr4__) || defined(__hpux) || defined(_SEQUENT_) long lrand48(); #define random lrand48 #else diff --git a/Tools/gdomap.c b/Tools/gdomap.c index 5214e262a..1f002fb2f 100644 --- a/Tools/gdomap.c +++ b/Tools/gdomap.c @@ -59,6 +59,9 @@ #endif #endif +#if defined(__svr4__) +#include +#endif #endif /* !__WIN32__ */ #include "gdomap.h" @@ -123,6 +126,7 @@ static void handle_request(int); static void handle_send(); static void handle_write(int); static void init_iface(); +static void load_iface(const char* from); static void init_ports(); static void init_probe(); static void queue_msg(struct sockaddr_in* a, unsigned char* d, int l); @@ -602,71 +606,65 @@ dump_stats() /* * Name - init_iface() - * Purpose - Establish our well-known port (my_port) and build up - * an array of the IP addresses supported on the network - * interfaces of this machine. - * The first non-loopback interface is presumed to be - * our primary interface and it's address is stored in - * the global variable 'my_addr'. + * Purpose - Build up an array of the IP addresses supported on + * the network interfaces of this machine. */ static void init_iface() { - struct servent *sp; +#ifdef SIOCGIFCONF struct ifconf ifc; struct ifreq ifreq; struct ifreq *ifr; struct ifreq *final; char buf[MAX_IFACE * sizeof(struct ifreq)]; - int set_my_addr = 0; int desc; int num_iface; - /* - * First we determine the port for the 'gdomap' service - ideally - * this should be the default port, since we should have registered - * this with the appropriate authority and have it reserved for us. - */ -#ifdef GDOMAP_PORT_OVERRIDE - my_port = htons(GDOMAP_PORT_OVERRIDE); -#else - my_port = htons(GDOMAP_PORT); - if ((sp = getservbyname("gdomap", "tcp")) == 0) { - fprintf(stderr, "Warning - unable to find service 'gdomap'\n"); - } - else { - unsigned short tcp_port = sp->s_port; - - if ((sp = getservbyname("gdomap", "udp")) == 0) { - fprintf(stderr, "Warning - unable to find service 'gdomap'\n"); - } - else if (sp->s_port != tcp_port) { - fprintf(stderr, "Warning - UDP and TCP service entries differ\n"); - fprintf(stderr, "Warning - I will use the TCP entry for both!\n"); - } - if (tcp_port != my_port) { - fprintf(stderr, "Warning - gdomap not running on normal port\n"); - } - my_port = tcp_port; - } -#endif - if ((desc = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { - perror("socketf for init_iface"); + perror("socket for init_iface"); exit(1); } +#if defined(__svr4__) + { + struct strioctl ioc; + + ioc.ic_cmd = SIOCGIFCONF; + ioc.ic_timout = 0; + ioc.ic_len = sizeof(buf); + ioc.ic_dp = buf; + if (ioctl(desc, I_STR, (char*)&ioc) < 0) { + ioc.ic_len = 0; + } + ifc.ifc_len = ioc.ic_len; + ifc.ifc_buf = ioc.ic_dp; + } +#else ifc.ifc_len = sizeof(buf); ifc.ifc_buf = buf; if (ioctl(desc, SIOCGIFCONF, (char*)&ifc) < 0) { - perror("SIOCGIFCONF for init_iface"); - close(desc); - exit(1); + ifc.ifc_len = 0; } +#endif /* * Find the IP address of each active network interface. */ num_iface = ifc.ifc_len / sizeof(struct ifreq); + if (num_iface == 0) { + int res = errno; + + perror("SIOCGIFCONF for init_iface found no active interfaces"); + if (res == EINVAL) { + fprintf(stderr, +"Either you have too many network interfaces on your machine (in which case\n" +"you need to change the 'MAX_IFACE' constant in gdomap.c and rebuild it), or\n" +"your system is buggy, and you need to use the '-a' command line flag for\n" +"gdomap to manually set the interface addresses and masks to be used.\n"); + } + close(desc); + exit(1); + } addr = (struct in_addr*)malloc(num_iface*IASIZE); mask = (struct in_addr*)malloc(num_iface*IASIZE); @@ -708,6 +706,172 @@ init_iface() } } close(desc); +#else + fprintf(stderr, "I can't find the SIOCGIFCONF ioctl on this platform -\r\nuse the '-a' flag to load interface details from a file instead.\r\n"); + exit(1); +#endif +} + +/* + * Name - load_iface() + * Purpose - Read addresses and netmasks for interfaces on this + * machine from a file. + */ +static void +load_iface(const char* from) +{ + FILE *fptr = fopen(from, "r"); + char buf[128]; + int num_iface = 0; + + if (fptr == 0) { + fprintf(stderr, "Unable to open address config - '%s'\n", from); + exit(1); + } + + while (fgets(buf, sizeof(buf), fptr) != 0) { + char *ptr = buf; + + /* + * Strip leading white space. + */ + while (isspace(*ptr)) { + ptr++; + } + if (ptr != buf) { + strcpy(buf, ptr); + } + /* + * Strip comments. + */ + ptr = strchr(buf, '#'); + if (ptr) { + *ptr = '\0'; + } + /* + * Strip trailing white space. + */ + ptr = buf; + while (*ptr) { + ptr++; + } + while (ptr > buf && isspace(ptr[-1])) { + ptr--; + } + *ptr = '\0'; + /* + * Ignore blank lines. + */ + if (*buf == '\0') { + continue; + } + num_iface++; + } + fseek(fptr, 0, 0); + + if (num_iface == 0) { + fprintf(stderr, "No address mask pairs found in file.\n"); + exit(1); + } + addr = (struct in_addr*)malloc(num_iface*IASIZE); + mask = (struct in_addr*)malloc(num_iface*IASIZE); + + while (fgets(buf, sizeof(buf), fptr) != 0) { + char *ptr = buf; + + /* + * Strip leading white space. + */ + while (isspace(*ptr)) { + ptr++; + } + if (ptr != buf) { + strcpy(buf, ptr); + } + /* + * Strip comments. + */ + ptr = strchr(buf, '#'); + if (ptr) { + *ptr = '\0'; + } + /* + * Strip trailing white space. + */ + ptr = buf; + while (*ptr) { + ptr++; + } + while (ptr > buf && isspace(ptr[-1])) { + ptr--; + } + *ptr = '\0'; + /* + * Ignore blank lines. + */ + if (*buf == '\0') { + continue; + } + + ptr = buf; + while (*ptr && (isdigit(*ptr) || (*ptr == '.'))) { + ptr++; + } + while (isspace(*ptr)) { + *ptr++ = '\0'; + } + addr[interfaces].s_addr = inet_addr(buf); + mask[interfaces].s_addr = inet_addr(ptr); + if (addr[interfaces].s_addr == -1) { + fprintf(stderr, "'%s' is not as valid address\n", buf); + } + else if (mask[interfaces].s_addr == -1) { + fprintf(stderr, "'%s' is not as valid netmask\n", ptr); + } + else { + interfaces++; + } + } + fclose(fptr); +} + +/* + * Name - init_my_port() + * Purpose - Establish our well-known port (my_port). + */ +static void +init_my_port() +{ + struct servent *sp; + + /* + * First we determine the port for the 'gdomap' service - ideally + * this should be the default port, since we should have registered + * this with the appropriate authority and have it reserved for us. + */ +#ifdef GDOMAP_PORT_OVERRIDE + my_port = htons(GDOMAP_PORT_OVERRIDE); +#else + my_port = htons(GDOMAP_PORT); + if ((sp = getservbyname("gdomap", "tcp")) == 0) { + fprintf(stderr, "Warning - unable to find service 'gdomap'\n"); + } + else { + unsigned short tcp_port = sp->s_port; + + if ((sp = getservbyname("gdomap", "udp")) == 0) { + fprintf(stderr, "Warning - unable to find service 'gdomap'\n"); + } + else if (sp->s_port != tcp_port) { + fprintf(stderr, "Warning - UDP and TCP service entries differ\n"); + fprintf(stderr, "Warning - I will use the TCP entry for both!\n"); + } + if (tcp_port != my_port) { + fprintf(stderr, "Warning - gdomap not running on normal port\n"); + } + my_port = tcp_port; + } +#endif } /* @@ -1767,7 +1931,7 @@ int main(int argc, char** argv) { extern char *optarg; - char *options = "CHc:dfi:p"; + char *options = "CHa:c:dfi:p"; int c; /* @@ -1788,6 +1952,7 @@ main(int argc, char** argv) printf("GNU Distributed Objects name server\n"); printf("-C help about configuration\n"); printf("-H general help\n"); + printf("-a file use config file for interface list.\n"); printf("-c file use config file for probe.\n"); printf("-d extra debug logging.\n"); printf("-f avoid fork() to make debugging easy\n"); @@ -1823,9 +1988,26 @@ main(int argc, char** argv) "Empty lines are permitted in the configuration file.\n" "Anything on a line after a hash ('#') is ignored.\n" "You tell gdomap about the config file with the '-c' command line option.\n"); + printf("\n"); + printf("\n"); +printf( +"gdomap uses the SIOCGIFCONF ioctl to build a list of IP addresses and\n" +"netmasks for the network interface cards on your machine. On some operating\n" +"systems, this facility is not available (or is broken), so you must tell\n" +"gdomap the addresses and masks of the interfaces using the '-a' command line\n" +"option. The file named with '-a' should contain a series of lines with\n" +"space separated pairs of addresses and masks in 'dot' notation.\n" +"You must NOT include loopback interfaces in this list.\n" +"If your operating system has some other method of giving you a list of\n" +"network interfaces and masks, please send me example code so that I can\n" +"implement it in gdomap.\n"); printf("\n"); exit(0); + case 'a': + load_iface(optarg); + break; + case 'c': { FILE *fptr = fopen(optarg, "r"); @@ -1979,7 +2161,10 @@ main(int argc, char** argv) (void)open("/dev/null", O_WRONLY); /* Stdout. */ (void)open("/dev/tty", O_WRONLY); /* Stderr. */ - init_iface(); /* Build up list of network interfaces. */ + init_my_port(); /* Determine port to listen on. */ + if (interfaces == 0) { + init_iface(); /* Build up list of network interfaces. */ + } init_ports(); /* Create ports to handle requests. */ init_probe(); /* Probe other name servers on net. */ diff --git a/configure b/configure index 174a2dd28..785883b59 100755 --- a/configure +++ b/configure @@ -2940,9 +2940,9 @@ done #-------------------------------------------------------------------- -# This function needed by NSDebug.m +# This function needed by NSTask.m #-------------------------------------------------------------------- -for ac_func in strerror +for ac_func in killpg do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 echo "configure:2949: checking for $ac_func" >&5 @@ -2999,9 +2999,9 @@ done #-------------------------------------------------------------------- -# This function needed by NSString for handling of %@ printf directive. +# This function needed by NSThread.m #-------------------------------------------------------------------- -for ac_func in register_printf_function +for ac_func in usleep do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 echo "configure:3008: checking for $ac_func" >&5 @@ -3057,6 +3057,124 @@ fi done +#-------------------------------------------------------------------- +# This function needed by NSDebug.m +#-------------------------------------------------------------------- +for ac_func in strerror +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +echo "configure:3067: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:3095: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <&6 +fi +done + + +#-------------------------------------------------------------------- +# This function needed by NSString for handling of %@ printf directive. +#-------------------------------------------------------------------- +for ac_func in register_printf_function +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +echo "configure:3126: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:3154: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <&6 +fi +done + + #-------------------------------------------------------------------- # Tools for making a DLL. #-------------------------------------------------------------------- diff --git a/configure.in b/configure.in index 441052bed..4bdcf14fe 100644 --- a/configure.in +++ b/configure.in @@ -281,6 +281,16 @@ AC_CHECK_FUNCS(mmap) #-------------------------------------------------------------------- AC_CHECK_FUNCS(inet_aton) +#-------------------------------------------------------------------- +# This function needed by NSTask.m +#-------------------------------------------------------------------- +AC_CHECK_FUNCS(killpg) + +#-------------------------------------------------------------------- +# This function needed by NSThread.m +#-------------------------------------------------------------------- +AC_CHECK_FUNCS(usleep) + #-------------------------------------------------------------------- # This function needed by NSDebug.m #--------------------------------------------------------------------