37

In a C project (POSIX), how do I get the fully qualified name for the current system?

For example, I can get just the hostname of my machine by doing gethostname() from unistd.h. This might give me machine3 in return, but I'm actually looking for machine3.somedomain.com for example.

How do I go about getting this information? I do not want to use a call to system() to do this, if possible.

Zxaos
  • 7,791
  • 12
  • 47
  • 61

5 Answers5

64

To get a fully qualified name for a machine, we must first get the local hostname, and then lookup the canonical name.

The easiest way to do this is by first getting the local hostname using uname() or gethostname() and then performing a lookup with gethostbyname() and looking at the h_name member of the struct it returns. If you are using ANSI c, you must use uname() instead of gethostname().

Example:

char hostname[1024];
hostname[1023] = '\0';
gethostname(hostname, 1023);
printf("Hostname: %s\n", hostname);
struct hostent* h;
h = gethostbyname(hostname);
printf("h_name: %s\n", h->h_name);

Unfortunately, gethostbyname() is deprecated in the current POSIX specification, as it doesn't play well with IPv6. A more modern version of this code would use getaddrinfo().

Example:

struct addrinfo hints, *info, *p;
int gai_result;

char hostname[1024];
hostname[1023] = '\0';
gethostname(hostname, 1023);

memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC; /*either IPV4 or IPV6*/
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_CANONNAME;

if ((gai_result = getaddrinfo(hostname, "http", &hints, &info)) != 0) {
    fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(gai_result));
    exit(1);
}

for(p = info; p != NULL; p = p->ai_next) {
    printf("hostname: %s\n", p->ai_canonname);
}

freeaddrinfo(info);

Of course, this will only work if the machine has a FQDN to give - if not, the result of the getaddrinfo() ends up being the same as the unqualified hostname.

vdm
  • 3
  • 3
Zxaos
  • 7,791
  • 12
  • 47
  • 61
  • 2
    I believe you skipped your call to freeaddrinfo() when getaddrinfo() succeeds! – Miquella Apr 27 '12 at 18:05
  • 1
    By the way here http://pubs.opengroup.org/onlinepubs/7908799/xns/gethostname.html is said that `Host names are limited to 255 bytes.`. You use 1024. –  Dec 11 '12 at 12:35
  • 1
    @skwllsp: 255 was the limit in SUSv2 (1997); since 2001, the limit is technically HOST_NAME_MAX / sysconf(_SC_HOST_NAME_MAX), which might exceed 255 (the absolute minimum value for _POSIX_HOST_NAME_MAX, #defined in ), and in fact might exceed 1023 as well; of course this is just theory; but in practice, 1023 is just as correct as 255 here :^) – AntoineL Apr 26 '14 at 17:27
  • On an IX'ish box the "hostname" does not need to correlated at all to the result of a DNS query for any of its interfaces' network addresses! The command `hostname` might return `box1` where as the the ip assigned to `eth0` would resolve to return `box2.test2.net` and the one on `eth1` would resolve to return `box3.test3.net`. – alk May 05 '15 at 11:29
  • 2
    This solution won't work if hostname is set to not map to any FDQN for any interfaces' address. – alk May 05 '15 at 11:41
12

My solution:

#ifdef WIN32
    #include <Windows.h>
    #include <tchar.h>
#else
    #include <unistd.h>
#endif

void GetMachineName(char machineName[150])
{
    char Name[150];
    int i=0;

    #ifdef WIN32
        TCHAR infoBuf[150];
        DWORD bufCharCount = 150;
        memset(Name, 0, 150);
        if( GetComputerName( infoBuf, &bufCharCount ) )
        {
            for(i=0; i<150; i++)
            {
                Name[i] = infoBuf[i];
            }
        }
        else
        {
            strcpy(Name, "Unknown_Host_Name");
        }
    #else
        memset(Name, 0, 150);
        gethostname(Name, 150);
    #endif
    strncpy(machineName,Name, 150);
}
MSalters
  • 173,980
  • 10
  • 155
  • 350
Bipul
  • 121
  • 1
  • 2
3

gethostname() is POSIX way to get local host name. Check out man.

BSD function getdomainname() can give you domain name so you can build fully qualified hostname. There is no POSIX way to get a domain I'm afraid.

qrdl
  • 34,062
  • 14
  • 56
  • 86
  • 2
    gethostname only returns the local hostname. I'm looking for the fully qualified name. – Zxaos Feb 02 '09 at 21:26
  • `getdomainname` returns the NIS domain name, which may not necessarily match the DNS domain name, or even be set at all – kbolino Apr 13 '21 at 20:16
0

I believe you are looking for:

gethostbyaddress

Just pass it the localhost IP.

There is also a gethostbyname function, that is also usefull.

Alex
  • 6,843
  • 10
  • 52
  • 71
  • if you give it 127.0.0.1 as IP address you are likely to get localhost or localhost.localdomain as answer. It is not common to assign the machines full hostname to a loopback interface. – Wichert Akkerman Sep 23 '11 at 12:24
-1

The easy way, try uname()

If that does not work, use gethostname() then gethostbyname() and finally gethostbyaddr()

The h_name of hostent{} should be your FQDN

Jack L.
  • 151
  • 1
  • 4
  • 11