summaryrefslogtreecommitdiffstats
path: root/cpukit/libnetworking/libc/gethostbyht.c
diff options
context:
space:
mode:
authorJoel Sherrill <joel.sherrill@OARcorp.com>2006-11-02 21:48:41 +0000
committerJoel Sherrill <joel.sherrill@OARcorp.com>2006-11-02 21:48:41 +0000
commit068c3ee1df9be23ee252428b87cfcf2c43cda3cf (patch)
treea874ea91a3d48ab47e2957c97c1e7ea1dbe6f3fe /cpukit/libnetworking/libc/gethostbyht.c
parent2006-11-01 Joel Sherrill <joel@OARcorp.com> (diff)
downloadrtems-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.c117
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