Protecting the world

from criminally bad code

gethostname

Synopsis

#include <unistd.h>

int gethostname(char* name,size_t namelen);

Description

The gethostname function copies the hostname of the local machine into a buffer supplied by the caller.

Pitfalls

Success may be reported even if the hostname was truncated

POSIX specifies that gethostname should return 0 if it was successful or -1 if not, but it does not define what is meant by success. There are at least two possible interpretations:

  • Success means copying the full hostname, so any truncation implies failure (or at least, does not imply success).
  • Success means behaving as specified by POSIX, which in the case of an insufficiently long buffer means truncating the hostname.

It can be strongly argued that the former behaviour is more useful, but at least one notable example of the latter is known (glibc on some platforms prior to version 2.2). For this reason it would be prudent to allow for either possibility.

A secondary method for detecting truncation is to inspect the content of the buffer on return from gethostname. If the buffer is filled to its limit, either with or without a terminator, then the assumption should be made that it was too small to hold the full hostname. (This assumption might not be correct, but it is safer to try again with a larger buffer than to press ahead with a possibly incomplete hostname.)

If the hostname is truncated then it will not necessarily be terminated

POSIX expressly leaves open the question of whether a truncated hostname should be terminated, therefore programs should be written to allow for either possibility. The simplest way to do this is to explicitly set the last byte of the buffer to null after calling gethostname:

char buffer[256];
int err=gethostname(buffer,sizeof(buffer));
buffer[sizeof(buffer)-1]=0;

The hostname may or may not be fully qualified

On modern systems the hostname is often a DNS domain name with multiple components. Such names can be expressed in three ways:

  • In fully-qualified form, where all of the components are listed.
  • In unqualified form, where only the first component is listed.
  • In partially-qualified form, where some but not all of the components are listed.

POSIX does not specify which of these forms should be returned by gethostbyname. Some implementations do, but they are split between use of the unqualified name and the fully-qualified name.

For this reason, programs should be written to allow for the possibility that the hostname may or may not be qualified. This is can be done by canonicalising the result using getaddrinfo, which will convert it to fully qualified form if that is possible.

HOST_NAME_MAX should not be used to set the buffer length

POSIX provides a variable named HOST_NAME_MAX which can be read using the sysconf function and which specifies the maximum length of the hostname allowed by the local system. Programs should not use this value when deciding how much memory to allocate for the hostname, for two reasons:

  • the limit could be very large, or
  • there might not be a limit (indicated by sysconf returning -1).

POSIX gives PATH_MAX as an example of a limit that is unsuitable for use as an array size. HOST_NAME_MAX differs in that there is little practical benefit in allowing very long hostnames, but nor is there any compelling reason why the length needs to be limited.

Alternatives

Using uname

The uname function returns the hostname, in the form of the nodename member of a utsname structure. It is somewhat easier to use than gethostname because the caller does not need to supply a buffer.

Unfortunately the buffer used to return the hostname is of fixed length, and POSIX warns that it may not be large enough to accommodate the hostname. There is nothing that the caller can do to lengthen the buffer. For this reason it is normally better to call gethostname if it is available.

Portability

  •  C90
  •  C99
  •  C++98
  •  C++11
  •  POSIX:1988
  •  POSIX:1990
  •  POSIX:2001
  •  POSIX:2008
  •  SVID1
  •  SVID2
  •  SVID3
  •  SVID4
  •  XPG3
  •  XPG4
  •  XPG4v2
  •  XPG5
  •  SUSv2
  •  SUSv3
  •  SUSv4

Further reading