@@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -20,22 +20,29 @@ #import "OFDNSResolverSettings.h" #import "OFArray.h" #import "OFCharacterSet.h" #import "OFDate.h" #import "OFDictionary.h" -#import "OFFile.h" +#ifdef OF_HAVE_FILES +# import "OFFile.h" +# import "OFFileManager.h" +#endif #import "OFLocale.h" #import "OFSocket+Private.h" #import "OFString.h" #ifdef OF_WINDOWS # import "OFWindowsRegistryKey.h" #endif #import "OFInvalidFormatException.h" #import "OFOpenItemFailedException.h" +#ifdef OF_WINDOWS +# import "OFOpenWindowsRegistryKeyFailedException.h" +#endif #import "OFOutOfMemoryException.h" #import "OFOutOfRangeException.h" +#import "OFUndefinedKeyException.h" #ifdef OF_WINDOWS # define interface struct # include # undef interface @@ -46,24 +53,24 @@ # define id id_3ds # include <3ds.h> # undef id #endif +#if defined(OF_AMIGAOS_M68K) || defined(OF_AMIGAOS4) +# define Class IntuitionClass +# include +# undef Class +#endif #ifdef OF_MORPHOS # include # include # include #endif #if defined(OF_HAIKU) # define HOSTS_PATH @"/system/settings/network/hosts" # define RESOLV_CONF_PATH @"/system/settings/network/resolv.conf" -#elif defined(OF_AMIGAOS4) -# define HOSTS_PATH @"DEVS:Internet/hosts" -#elif defined(OF_AMIGAOS) -# define HOSTS_PATH @"AmiTCP:db/hosts" -# define RESOLV_CONF_PATH @"AmiTCP:db/resolv.conf" #else # define HOSTS_PATH @"/etc/hosts" # define RESOLV_CONF_PATH @"/etc/resolv.conf" #endif @@ -113,10 +120,21 @@ return [OFString stringWithCString: hostname encoding: [OFLocale encoding]]; } #endif + +#ifdef OF_AMIGAOS_M68K +static bool +assignExists(const char *assign) +{ + struct DosList *list = LockDosList(LDF_ASSIGNS | LDF_READ); + bool found = (FindDosEntry(list, assign, LDF_ASSIGNS) != NULL); + UnLockDosList(LDF_ASSIGNS | LDF_READ); + return found; +} +#endif #ifdef OF_MORPHOS static OFString * arexxCommand(const char *port, const char *command) { @@ -211,11 +229,11 @@ copy->_searchDomains = [_searchDomains copy]; copy->_timeout = _timeout; copy->_maxAttempts = _maxAttempts; copy->_minNumberOfDotsInAbsoluteName = _minNumberOfDotsInAbsoluteName; - copy->_usesTCP = _usesTCP; + copy->_forcesTCP = _forcesTCP; copy->_configReloadInterval = _configReloadInterval; copy->_lastConfigReload = [_lastConfigReload copy]; } @catch (id e) { [copy release]; @throw e; @@ -239,11 +257,11 @@ _searchDomains = nil; _timeout = 2; _maxAttempts = 3; _minNumberOfDotsInAbsoluteName = 1; - _usesTCP = false; + _forcesTCP = false; #ifndef OF_NINTENDO_3DS _configReloadInterval = 2; #else _configReloadInterval = 0; #endif @@ -253,10 +271,12 @@ - (void)parseHosts: (OFString *)path { void *pool = objc_autoreleasePoolPush(); OFCharacterSet *whitespaceCharacterSet = [OFCharacterSet whitespaceCharacterSet]; + OFCharacterSet *commentCharacters = + [OFCharacterSet characterSetWithCharactersInString: @"#;"]; OFMutableDictionary *staticHosts; OFFile *file; OFString *line; @try { @@ -272,11 +292,11 @@ [file readLineWithEncoding: [OFLocale encoding]]) != nil) { OFArray *components, *hosts; size_t pos; OFString *address; - pos = [line rangeOfString: @"#"].location; + pos = [line indexOfCharacterFromSet: commentCharacters]; if (pos != OFNotFound) line = [line substringToIndex: pos]; components = [line componentsSeparatedByCharactersInSet: whitespaceCharacterSet @@ -288,12 +308,14 @@ address = components.firstObject; hosts = [components objectsInRange: OFMakeRange(1, components.count - 1)]; for (OFString *host in hosts) { - OFMutableArray *addresses = - [staticHosts objectForKey: host]; + OFMutableArray *addresses; + + host = host.lowercaseString; + addresses = [staticHosts objectForKey: host]; if (addresses == nil) { addresses = [OFMutableArray array]; [staticHosts setObject: addresses forKey: host]; } @@ -308,11 +330,11 @@ _staticHosts = [staticHosts copy]; objc_autoreleasePoolPop(pool); } -# if !defined(OF_WINDOWS) && !defined(OF_AMIGAOS4) +# ifndef OF_WINDOWS - (void)parseResolvConfOption: (OFString *)option { @try { if ([option hasPrefix: @"ndots:"]) { unsigned long long number; @@ -341,11 +363,11 @@ } else if ([option hasPrefix: @"reload-period:"]) { option = [option substringFromIndex: 14]; _configReloadInterval = option.unsignedLongLongValue; } else if ([option isEqual: @"tcp"]) - _usesTCP = true; + _forcesTCP = true; } @catch (OFInvalidFormatException *e) { } } - (void)parseResolvConf: (OFString *)path @@ -387,11 +409,11 @@ if (components.count < 2) { objc_autoreleasePoolPop(pool2); continue; } - option = components.firstObject; + option = [components.firstObject lowercaseString]; arguments = [components objectsInRange: OFMakeRange(1, components.count - 1)]; if ([option isEqual: @"nameserver"]) { if (arguments.count != 1) { @@ -445,14 +467,19 @@ if (GetNetworkParams(fixedInfo, &length) != ERROR_SUCCESS) return; nameServers = [OFMutableArray array]; - for (iter = &fixedInfo->DnsServerList; iter != NULL; iter = iter->Next) - [nameServers addObject: + for (iter = &fixedInfo->DnsServerList; iter != NULL; + iter = iter->Next) { + OFString *nameServer = [OFString stringWithCString: iter->IpAddress.String - encoding: encoding]]; + encoding: encoding]; + + if (nameServer.length > 0) + [nameServers addObject: nameServer]; + } if (nameServers.count > 0) { [nameServers makeImmutable]; _nameServers = [nameServers copy]; } @@ -491,12 +518,14 @@ address = components.firstObject; hosts = [components objectsInRange: OFMakeRange(1, components.count - 1)]; for (OFString *host in hosts) { - OFMutableArray *addresses = - [staticHosts objectForKey: host]; + OFMutableArray *addresses; + + host = host.lowercaseString; + addresses = [staticHosts objectForKey: host]; if (addresses == nil) { addresses = [OFMutableArray array]; [staticHosts setObject: addresses forKey: host]; } @@ -512,17 +541,26 @@ objc_autoreleasePoolPop(pool); } #endif -#ifdef OF_AMIGAOS4 -- (void)obtainAmigaOS4SystemConfig +#if defined(OF_AMIGAOS_M68K) || defined(OF_AMIGAOS4) +- (bool)obtainRoadshowSystemConfig { - OFMutableArray *nameServers = [OFMutableArray array]; - OFStringEncoding encoding = [OFLocale encoding]; - struct List *nameServerList = ObtainDomainNameServerList(); + OFMutableArray *nameServers; + OFStringEncoding encoding; + struct List *nameServerList; char buffer[MAXHOSTNAMELEN]; + LONG hasDNSAPI; + + if (SocketBaseTags(SBTM_GETREF(SBTC_HAVE_DNS_API), (ULONG)&hasDNSAPI, + TAG_END) != 0 || !hasDNSAPI) + return false; + + nameServers = [OFMutableArray array]; + encoding = [OFLocale encoding]; + nameServerList = ObtainDomainNameServerList(); if (nameServerList == NULL) @throw [OFOutOfMemoryException exception]; @try { @@ -552,10 +590,12 @@ } if (GetDefaultDomainName(buffer, sizeof(buffer))) _localDomain = [[OFString alloc] initWithCString: buffer encoding: encoding]; + + return true; } #endif #ifdef OF_NINTENDO_3DS - (void)obtainNintendo3DSSytemConfig @@ -600,14 +640,17 @@ } #endif - (void)reload { - void *pool; #ifdef OF_WINDOWS - OFString *path; + OFString *path = nil; +#endif +#if (defined(OF_AMIGAOS_M68K) || defined(OF_AMIGAOS4)) && defined(OF_HAVE_FILES) + OFFileManager *fileManager = [OFFileManager defaultManager]; #endif + void *pool; /* * TODO: Rather than reparsing every time, check what actually changed * (mtime) and only reset those. */ @@ -620,29 +663,53 @@ [self setDefaults]; #if defined(OF_WINDOWS) # ifdef OF_HAVE_FILES - OFWindowsRegistryKey *key = [[OFWindowsRegistryKey localMachineKey] - openSubkeyAtPath: @"SYSTEM\\CurrentControlSet\\Services\\" - @"Tcpip\\Parameters" - accessRights: KEY_QUERY_VALUE - options: 0]; - path = [[[key stringForValueNamed: @"DataBasePath"] - stringByAppendingPathComponent: @"hosts"] - stringByExpandingWindowsEnvironmentStrings]; + @try { + OFWindowsRegistryKey *key; + + key = [[OFWindowsRegistryKey localMachineKey] + openSubkeyAtPath: @"SYSTEM\\CurrentControlSet\\Services\\" + @"Tcpip\\Parameters" + accessRights: KEY_QUERY_VALUE + options: 0]; + path = [[[key stringForValueNamed: @"DataBasePath"] + stringByAppendingPathComponent: @"hosts"] + stringByExpandingWindowsEnvironmentStrings]; + } @catch (OFOpenWindowsRegistryKeyFailedException *e) { + /* Ignore */ + } @catch (OFUndefinedKeyException *e) { + /* Ignore */ + } if (path != nil) [self parseHosts: path]; # endif [self obtainWindowsSystemConfig]; #elif defined(OF_MORPHOS) [self obtainMorphOSSystemConfig]; -#elif defined(OF_AMIGAOS4) - [self parseHosts: HOSTS_PATH]; - [self obtainAmigaOS4SystemConfig]; +#elif defined(OF_AMIGAOS_M68K) || defined(OF_AMIGAOS4) +# ifdef OF_HAVE_FILES + if (![self obtainRoadshowSystemConfig]) { + if (assignExists("AmiTCP")) + /* + * FIXME: The installer puts it there, but theoretically + * it could also be in AmiTCP:db/netdb or any of + * the files included there. + */ + [self parseResolvConf: @"AmiTCP:db/netdb-myhost"]; + } + + if ([fileManager fileExistsAtPath: @"DEVS:Internet/hosts"]) + [self parseHosts: @"DEVS:Internet/hosts"]; + else if (assignExists("AmiTCP")) + [self parseHosts: @"AmiTCP:db/hosts"]; +# else + [self obtainRoadshowSystemConfig]; +# endif #elif defined(OF_NINTENDO_3DS) [self obtainNintendo3DSSytemConfig]; #elif defined(OF_HAVE_FILES) [self parseHosts: HOSTS_PATH]; [self parseResolvConf: RESOLV_CONF_PATH];