In comp.unix.admin Roland Mainz <roland.ma...@informatik.med.uni-giessen.de> wrote:
: How to get the FQDN(=Full Qualified Domain Name) of a
: (Solaris/Linux/AIX/etc.) machine from a ksh script or from a C program
: in a platform-independent manner (...what about POSIX ??) ?
/*
* 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 <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <ctype.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <pwd.h>
/* ---------------------------------------------------------------------- */
#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);
}
/* ---------------------------------------------------------------------- */
--
PGP and other useless info at \ La ciencia-ficcion es
http://www.cps.unizar.es/~spd/ \ ese futuro en el que
finger://daphne.cps.unizar.es/spd \ lo seguro es que ya
ftp://ivo.cps.unizar.es/pub/ \ (F. Alfaro) no seremos jovenes