Index: src/OFDNSResolverSettings.m ================================================================== --- src/OFDNSResolverSettings.m +++ src/OFDNSResolverSettings.m @@ -46,19 +46,22 @@ /* Newer versions of libctru started using id as a parameter name. */ # define id id_3ds # include <3ds.h> # undef id #endif + +#ifdef OF_MORPHOS +# include +# include +# include +#endif #import "socket_helpers.h" #if defined(OF_HAIKU) # define HOSTS_PATH @"/system/settings/network/hosts" # define RESOLV_CONF_PATH @"/system/settings/network/resolv.conf" -#elif defined(OF_MORPHOS) -# define HOSTS_PATH @"ENV:sys/net/hosts" -# define RESOLV_CONF_PATH @"ENV:sys/net/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" @@ -65,42 +68,118 @@ #else # define HOSTS_PATH @"/etc/hosts" # define RESOLV_CONF_PATH @"/etc/resolv.conf" #endif -#ifndef OF_WII static OFString * -domainFromHostname(void) +domainFromHostname(OFString *hostname) { - char hostname[256]; - OFString *domain, *ret; - - if (gethostname(hostname, 256) != 0) + if (hostname == nil) return nil; - domain = [OFString stringWithCString: hostname - encoding: [OFLocale encoding]]; - @try { - of_socket_address_parse_ip(domain, 0); + of_socket_address_parse_ip(hostname, 0); /* * If we are still here, the host name is a valid IP address. * We can't use that as local domain. */ return nil; } @catch (OFInvalidFormatException *e) { /* Not an IP address -> we can use it if it contains a dot. */ - size_t pos = [domain rangeOfString: @"."].location; + size_t pos = [hostname rangeOfString: @"."].location; if (pos == OF_NOT_FOUND) return nil; - ret = [domain substringFromIndex: pos + 1]; + return [hostname substringFromIndex: pos + 1]; + } +} + +#if !defined(OF_WII) && !defined(OF_MORPHOS) +static OFString * +hostname(void) +{ + char hostname[256]; + + if (gethostname(hostname, 256) != 0) + return nil; + + return [OFString stringWithCString: hostname + encoding: [OFLocale encoding]]; +} +#endif + +#ifdef OF_MORPHOS +static OFString * +arexxCommand(const char *port, const char *command) +{ + struct Library *RexxSysBase; + struct MsgPort *replyPort = NULL; + struct RexxMsg *msg = NULL; + + if ((RexxSysBase = OpenLibrary("rexxsyslib.library", 36)) == NULL) + return nil; + + @try { + struct MsgPort *rexxPort; + + if ((replyPort = CreateMsgPort()) == NULL) + return nil; + + if ((msg = CreateRexxMsg(replyPort, NULL, port)) == NULL) + return nil; + + msg->rm_Action = RXCOMM | RXFF_RESULT; + + if ((msg->rm_Args[0] = (char *)CreateArgstring( + command, strlen(command))) == NULL) + return nil; + + Forbid(); + + if ((rexxPort = FindPort(port)) == NULL) { + Permit(); + return nil; + } + + PutMsg(rexxPort, &msg->rm_Node); + Permit(); + WaitPort(replyPort); + GetMsg(replyPort); + + if (msg->rm_Result1 != RC_OK || msg->rm_Result2 == 0) + return nil; + + return [OFString stringWithCString: (char *)msg->rm_Result2 + encoding: [OFLocale encoding]]; + } @finally { + if (msg != NULL) { + if (msg->rm_Args[0] != NULL) + DeleteArgstring(msg->rm_Args[0]); + if (msg->rm_Result2 != 0) + DeleteArgstring((char *)msg->rm_Result2); + + DeleteRexxMsg(msg); + } + + if (replyPort != NULL) + DeleteMsgPort(replyPort); + + CloseLibrary(RexxSysBase); } +} - return ret; +static OFArray OF_GENERIC(OFString *) * +parseNetStackArray(OFString *string) +{ + if (![string hasPrefix: @"["] || ![string hasSuffix: @"]"]) + return nil; + + string = [string substringWithRange: of_range(1, string.length - 2)]; + + return [string componentsSeparatedByString: @"|"]; } #endif @implementation OFDNSResolverSettings - (void)dealloc @@ -161,21 +240,19 @@ #else _configReloadInterval = 0; #endif } -#if defined(OF_HAVE_FILES) && !defined(OF_NINTENDO_3DS) +#if defined(OF_HAVE_FILES) && !defined(OF_MORPHOS) && !defined(OF_NINTENDO_3DS) - (void)parseHosts: (OFString *)path { void *pool = objc_autoreleasePoolPush(); OFCharacterSet *whitespaceCharacterSet = [OFCharacterSet whitespaceCharacterSet]; OFMutableDictionary *staticHosts; OFFile *file; OFString *line; - OFEnumerator *enumerator; - OFMutableArray *addresses; @try { file = [OFFile fileWithPath: path mode: @"r"]; } @catch (OFOpenItemFailedException *e) { @@ -184,11 +261,10 @@ } staticHosts = [OFMutableDictionary dictionary]; while ((line = [file readLine]) != nil) { - void *pool2 = objc_autoreleasePoolPush(); OFArray *components, *hosts; size_t pos; OFString *address; pos = [line rangeOfString: @"#"].location; @@ -197,41 +273,34 @@ components = [line componentsSeparatedByCharactersInSet: whitespaceCharacterSet options: OF_STRING_SKIP_EMPTY]; - if (components.count < 2) { - objc_autoreleasePoolPop(pool2); + if (components.count < 2) continue; - } address = components.firstObject; hosts = [components objectsInRange: of_range(1, components.count - 1)]; for (OFString *host in hosts) { - addresses = [staticHosts objectForKey: host]; + OFMutableArray *addresses = + [staticHosts objectForKey: host]; if (addresses == nil) { addresses = [OFMutableArray array]; [staticHosts setObject: addresses forKey: host]; } [addresses addObject: address]; } - - objc_autoreleasePoolPop(pool2); } - - enumerator = [staticHosts objectEnumerator]; - while ((addresses = [enumerator nextObject]) != nil) + for (OFMutableArray *addresses in [staticHosts objectEnumerator]) [addresses makeImmutable]; [staticHosts makeImmutable]; - - [_staticHosts release]; _staticHosts = [staticHosts copy]; objc_autoreleasePoolPop(pool); } @@ -386,10 +455,61 @@ _localDomain = [[OFString alloc] initWithCString: fixedInfo->DomainName encoding: encoding]; } #endif + +#ifdef OF_MORPHOS +- (void)obtainMorphOSSystemConfig +{ + void *pool = objc_autoreleasePoolPush(); + OFMutableDictionary *staticHosts; + + _nameServers = [parseNetStackArray(arexxCommand("NETSTACK", + "QUERY NAMESERVERS")) copy]; + _localDomain = [domainFromHostname(arexxCommand("NETSTACK", + "QUERY HOSTNAME")) copy]; + _searchDomains = [parseNetStackArray(arexxCommand("NETSTACK", + "QUERY DOMAINS")) copy]; + + staticHosts = [OFMutableDictionary dictionary]; + + for (OFString *entry in parseNetStackArray(arexxCommand("NETSTACK", + "QUERY HOSTS"))) { + OFArray *components = [entry componentsSeparatedByString: @" "]; + OFString *address; + OFArray *hosts; + + if (components.count < 2) + continue; + + address = components.firstObject; + hosts = [components objectsInRange: + of_range(1, components.count - 1)]; + + for (OFString *host in hosts) { + OFMutableArray *addresses = + [staticHosts objectForKey: host]; + + if (addresses == nil) { + addresses = [OFMutableArray array]; + [staticHosts setObject: addresses + forKey: host]; + } + + [addresses addObject: address]; + } + } + for (OFMutableArray *addresses in [staticHosts objectEnumerator]) + [addresses makeImmutable]; + + [staticHosts makeImmutable]; + _staticHosts = [staticHosts copy]; + + objc_autoreleasePoolPop(pool); +} +#endif #ifdef OF_AMIGAOS4 - (void)obtainAmigaOS4SystemConfig { OFMutableArray *nameServers = [OFMutableArray array]; @@ -508,10 +628,12 @@ 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_NINTENDO_3DS) [self obtainNintendo3DSSytemConfig]; @@ -539,13 +661,13 @@ initWithObjects: @"127.0.0.1", @"::1", nil]; #else _nameServers = [[OFArray alloc] initWithObject: @"127.0.0.1"]; #endif -#ifndef OF_WII +#if !defined(OF_WII) && !defined(OF_MORPHOS) if (_localDomain == nil) - _localDomain = [domainFromHostname() copy]; + _localDomain = [domainFromHostname(hostname()) copy]; #endif if (_searchDomains == nil) { if (_localDomain != nil) _searchDomains = [[OFArray alloc]