/* * attempt to construct a fully-qualified hostname * * not likely to work on multi-homed or multi-addressed machines * * David Laur, Rainsound, 9/96 * * (converted from the C++ in my app) */ #include #include #include #include #include #include #include #include #include #include /* ---------------------------------------------------------------------- */ #ifdef sun extern int gethostname( char *name, int namelen ); #endif #ifndef __sgi static char* hstrerror ( int errnum ) { switch (errnum) { case HOST_NOT_FOUND: return "can't resolve name"; case TRY_AGAIN: return "name lookup timeout, try again"; case NO_RECOVERY: return "name server failure"; case NO_DATA: return "no data/address associated with name"; default: break; } return "unknown gethostbyname failure"; } #endif /* ---------------------------------------------------------------------- */ static int countDots ( char *name ) { int n; for (n=0; *name; ++name) if (*name=='.') ++n; return(n); } /* ---------------------------------------------------------------------- */ char* gethostnameFullyQualified ( void ) { /* a fully qualified name is one that an arbitrary * internet host could use to find this host (assuming * that the various DNS pieces are working properly) * for example: spanky.hipsters.com * * some sites maintain local subdomains, so a full name * might be: niles.CS.Rudeboy.EDU * * under some conditions the 'gethostname' routine returns * either the fully qualified name, or just the first word. * (i.e. for IRIX, depends on the definition of /etc/sys_id) * * note that the old routine getdomainname only returns the * current NIS "domain" name, which is just a database grouping, * it is often set to the same string as the internet domain, * but not always. Also it's documented as 'backward compatible only' * under IRIX, and not at all on the Sun. * * also, at some sites one of the gethostbyname h_aliases is the * fully qualified name rather than the h_name "official" name * * the only solution that really deals with situations like * multi-homed hosts or multi-network gateway hosts is to have * some sysadmin specify the FQ-hostname in a file, much as * sendmail requires. * * note that the return value is new[] memory and should be * freed by the caller * * the criteria used by this heuristic: the more dots in a name the * better, i.e. longer names are likely to be more resolvable from * external sites. */ char host[774]; struct hostent *hp; char *fqname=NULL; char *result; int nd; host[0] = 0; if (-1 == gethostname(host, sizeof(host))) { perror("warning - getting local hostname"); /* not a general solution, but for the 95% case of (my app) * talking to itself on the same host, "localhost" will do */ strcpy(host,"localhost"); } fqname = host; nd = countDots(fqname); hp = gethostbyname(host); if (!hp) { fprintf(stderr, "warning - can't gethostbyname(%s): %s\n", host, hstrerror(h_errno)); } else { char **nm; if (nd <= countDots(hp->h_name)) { fqname = hp->h_name; nd = countDots(fqname); } for (nm = hp->h_aliases; *nm; ++nm) { int d = countDots(*nm); if (d > nd) {fqname = *nm; nd=d;} } } if (2 > nd) { /* still need to find a domain, look through the usual suspects: * LOCALDOMAIN env variable * domain defn from /etc/resolv.conf * /etc/defaultdomain (sun only?) */ FILE *fp = NULL; char domain[1024]; char *e = getenv("LOCALDOMAIN"); if (e) strcpy(domain, e); else domain[0] = 0; if( !domain[0] && NULL != (fp=fopen("/etc/resplv.conf","r")) ) { nd = 0; while( fgets(domain, sizeof(domain), fp) ) { if( 0==strncmp("domain ",domain,7) ) { nd = strlen(domain) - 7; memmove(domain, domain+7, nd); } } domain[nd] = 0; /* nul terminate (or reset empty) */ fclose(fp); } if( !domain[0] && NULL != (fp=fopen("/etc/defaultdomain","r")) ) { fgets(domain, sizeof(domain), fp); fclose(fp); } if( domain[0] ) { /* trim blanks */ int first = 0; nd = strlen(domain) - 1; while (first <= nd && isspace(domain[first])) ++first; while (nd > first && isspace(domain[nd])) domain[nd--] = 0; if (domain[first]) { if (fqname != host) strcpy(host,fqname); if ('.'!=domain[first]) strcat(host,"."); strcat(host,domain+first); fqname = host; } } } result = malloc(1+strlen(fqname)); strcpy(result,fqname); return(result); } /* ---------------------------------------------------------------------- */ main () { int uid = getuid(); struct passwd *pwd = getpwuid( uid ); char *fqname = gethostnameFullyQualified(); if ( NULL == ( pwd = getpwuid ( uid ))) { printf( "%d@%s\n" , uid , fqname); } else { printf( "%s@%s\n", pwd->pw_name, fqname); } free(fqname); return(0); } /* ---------------------------------------------------------------------- */