/* * gethostybname -- * * The following code was contributed by Casper H.S. Dik * to address the following problem: * * gethostbyname() always returns null in h->aliases. * Now, gethostbyX can be replaced its __switch_gethostbyX * equivalents. However, these are missing from Solaris 2.3. * * The _r functions are reentrant. They have a different * calling sequence. (The __switch_getXXXbyYYY are called * like getXXXbyYYY, the _switch_getXXXbyYYY_r are called * like getXXXbyYYY_r) * * With this bit of knowledge I constructed the code that * follows this message. Just plug it in every program * that requires gethostbyname to work. (Gethostbyaddr() * is added for symmetry). * * You'll need to link with -lnsl -ldl. * * It works for Solaris 2.2 and 2.3. (Compiled on 2.3 or * 2.2 it will run 2.2 and 2.3) * * Note that as with __switch* _switch*_r is undocumented * and can be changed in the next release. * */ /* * Proper gethostbyXX function for Solaris 2.0-2.3 * (and later ?) * * Fixed in 2.4? * * You'll need -ldl added to the link command line. * * Casper Dik (casper@fwi.uva.nl) * */ #include #include #define HBUFSIZE 4096 static void *dlhandle; /* The gethostbyXXX function variables. Named after * then .so files they appear in. nsw*.so in SunOS 5.2 * and earlier, nss_*.so in 5.3 */ static struct hostent *(*nswghba)(const char *, int, int), *(*nswghbn)(const char *), *(*nss_ghba)(const char *, int, int, struct hostent *, char *, int, int *), *(*nss_ghbn)(const char *, struct hostent *, char *, int, int *); static int dlinit(void) { static int dlstatus = 0; /* 0 = uninited, 1 = inited & ok, -1 = error */ if (dlstatus) return dlstatus; dlstatus = -1; dlhandle = dlopen(0, RTLD_LAZY); if (dlhandle == 0) return dlstatus; /* SunOS 5.0 - 5.2 */ nswghba = (struct hostent *(*)(const char *, int, int)) dlsym(dlhandle, "__switch_gethostbyaddr"); nswghbn = (struct hostent *(*)(const char *)) dlsym(dlhandle, "__switch_gethostbyname"); /* either both should exist or both should not exist */ if ((nswghbn == 0) != (nswghba == 0)) return dlstatus; if (nswghbn) return dlstatus = 1; /* SunOS 5.3 - ? */ nss_ghba = (struct hostent *(*) (const char *, int, int, struct hostent *, char *, int , int *)) dlsym(dlhandle, "_switch_gethostbyaddr_r"); nss_ghbn = (struct hostent *(*) (const char *, struct hostent *, char *, int , int *)) dlsym(dlhandle, "_switch_gethostbyname_r"); /* these two must exist when we get here */ if (nss_ghbn != 0 && nss_ghba != 0) dlstatus = 1; return dlstatus; } struct hostent * gethostbyname(const char *name) { static struct hostent hp; static char buf[HBUFSIZE]; if (dlinit() == -1) return 0; if (nswghbn) return nswghbn(name); else return nss_ghbn(name, &hp, buf, sizeof(buf), &h_errno); } struct hostent * gethostbyaddr(const char *addr, int len, int type) { static struct hostent hp; static char buf[HBUFSIZE]; if (dlinit() == -1) return 0; if (nswghba) return nswghba(addr, len, type); else return nss_ghba(addr, len, type, &hp, buf, sizeof(buf), &h_errno); }