diff options
author | Joel Sherrill <joel.sherrill@OARcorp.com> | 2006-11-02 21:48:41 +0000 |
---|---|---|
committer | Joel Sherrill <joel.sherrill@OARcorp.com> | 2006-11-02 21:48:41 +0000 |
commit | 068c3ee1df9be23ee252428b87cfcf2c43cda3cf (patch) | |
tree | a874ea91a3d48ab47e2957c97c1e7ea1dbe6f3fe /cpukit/libnetworking/libc/gethostbyht.c | |
parent | 2006-11-01 Joel Sherrill <joel@OARcorp.com> (diff) | |
download | rtems-068c3ee1df9be23ee252428b87cfcf2c43cda3cf.tar.bz2 |
2006-11-02 Steven Johnson <sjohnson@sakuraindustries.com>
* libnetworking/netdb.h, libnetworking/libc/gethostbyht.c,
libnetworking/libc/gethostnamadr.c: This patch adds a functional
gethostbyname_r to RTEMS. We were having problems with multiple
threads calling gethostbyname, so we decided the best way to deal
with it was to do it properly, rather than kludge up our code to make
gethostbyname safe. We have found several slightly different
parameter lists for this function, it does not seem to be standard.
The one we used has the linux interface. In RTEMS there was an
existing gethostbyname_r inside a #ifdef _THREAD_SAFE which was NOT
Threadsafe, as this just called gethostbyname. So we have placed all
of the additional code inside the #ifdef _THREAD_SAFE.
Diffstat (limited to 'cpukit/libnetworking/libc/gethostbyht.c')
-rw-r--r-- | cpukit/libnetworking/libc/gethostbyht.c | 117 |
1 files changed, 117 insertions, 0 deletions
diff --git a/cpukit/libnetworking/libc/gethostbyht.c b/cpukit/libnetworking/libc/gethostbyht.c index 29f2805367..df785cc351 100644 --- a/cpukit/libnetworking/libc/gethostbyht.c +++ b/cpukit/libnetworking/libc/gethostbyht.c @@ -67,6 +67,7 @@ static char rcsid[] = "$Id$"; #include <string.h> #include <arpa/nameser.h> /* XXX */ #include <resolv.h> /* XXX */ +#include <sys/fcntl.h> #define MAXALIASES 35 @@ -78,6 +79,10 @@ static u_char host_addr[16]; /* IPv4 or IPv6 */ static char *h_addr_ptrs[2]; static int stayopen = 0; +static char* hostmap = NULL; +static unsigned int hostlen = 0; +static char *cur; + void _sethosthtent(f) int f; @@ -200,3 +205,115 @@ _gethostbyhtaddr(addr, len, af) endhostent(); return (p); } + + +#ifdef _THREAD_SAFE + +static int isblank ( int ch ) +{ + return ch == ' ' || ch == '\t'; +} + +struct hostent* gethostent_r(char* buf, int len) +{ + char *dest; + struct hostent* pe=(struct hostent*)buf; + char* last; + char* max=buf+len; + int aliasidx; + int curlen; + + + if (hostf<0) return 0; + fseek(hostf,0,SEEK_END); + curlen=ftell(hostf); + fseek(hostf,0,SEEK_SET); + + if (curlen > hostlen) { + if (hostmap) { + hostmap = realloc(hostmap,curlen); + } + else { + hostmap = malloc(curlen); + } + } + hostlen = curlen; + + if (hostmap) { + if (fread(hostmap,hostlen,1,hostf) != hostlen) { + hostmap=0; goto error; + } + cur=hostmap; + } + last=hostmap+hostlen; +again: + if ((size_t)len<sizeof(struct hostent)+11*sizeof(char*)) goto nospace; + dest=buf+sizeof(struct hostent); + pe->h_name=0; + pe->h_aliases=(char**)dest; pe->h_aliases[0]=0; dest+=10*sizeof(char*); + pe->h_addr_list=(char**)dest; dest+=2*sizeof(char**); + if (cur>=last) return 0; + if (*cur=='#' || *cur=='\n') goto parseerror; + /* first, the ip number */ + pe->h_name=cur; + while (cur<last && !isspace(*cur)) cur++; + if (cur>=last) return 0; + if (*cur=='\n') goto parseerror; + { + char save=*cur; + *cur=0; + pe->h_addr_list[0]=dest; + pe->h_addr_list[1]=0; + if (max-dest<16) goto nospace; + if (inet_pton(AF_INET6,pe->h_name,dest)>0) { + pe->h_addrtype=AF_INET6; + pe->h_length=16; + dest+=16; + } else if (inet_pton(AF_INET,pe->h_name,dest)>0) { + pe->h_addrtype=AF_INET; + pe->h_length=4; + dest+=4; + } else { + *cur=save; + goto parseerror; + } + *cur=save; + } + ++cur; + /* now the aliases */ + for (aliasidx=0;aliasidx<9;++aliasidx) { + while (cur<last && isblank(*cur)) ++cur; + pe->h_aliases[aliasidx]=cur; + while (cur<last && !isspace(*cur)) ++cur; + { + char *from=pe->h_aliases[aliasidx]; + int len=cur-from; + if (max-dest<len+2) goto nospace; + pe->h_aliases[aliasidx]=dest; + memmove(dest,from,(size_t)(cur-from)); + dest+=len; + *dest=0; ++dest; + } + if (*cur=='\n') { ++cur; ++aliasidx; break; } + if (cur>=last || !isblank(*cur)) break; + cur++; + } + pe->h_aliases[aliasidx]=0; + pe->h_name=pe->h_aliases[0]; + pe->h_aliases++; + return pe; +parseerror: + while (cur<last && *cur!='\n') cur++; + cur++; + goto again; +nospace: + errno=ERANGE; + goto __error; +error: + errno=ENOMEM; +__error: + if (hostmap!=NULL) free(hostmap); + hostmap=NULL; + return 0; +} +#endif |