> I can get the machine name by gethostname(2), but I still can't get the
> internet address.
> I got the machine name like 'idefix'
> But I can't get the internet address such as
> 'idefix@ee.mcgill.ca' even though I try to use gethostbyname(2)...
Yell to your sysadmin: it means that the machine name in /etc/hosts
is not the full qualified hostname. However, since it might take ages
before that gets changed to the RightThing(tm), you may want to use
a more bulletproof method.
To understand how it works, you need to remember the following:
(a) An IP address is a 32 bit number, represented as by the following struct
defined in <netinet/in.h>
struct in_addr {u_long s_addr;};
An "u_long" is the same as an "unsigned long" of C, but it's language
independent.
(b) The name service (gethostbyname(2), gethostbyaddr(2), etc.) represents
addresses as character strings that *still* encode 32 bit integers in
their characters bytes. More precisely, gethostbyname(2) returns a
pointer to a struct defined in <netdb.h>
struct hostent {
char *h_name; /* official name of host */
char **h_aliases; /* alias list */
int h_addrtype; /* host address type */
int h_length; /* length of address */
char **h_addr_list; /* list of addresses from name server */
};
#define h_addr h_addr_list[0]
and each member of h_addr_list is a pointer to a string of h_length bytes
encoding an address. Do *not* assume that these are '\0' terminated
strings, since 0 is a valid byte inside an IP address, hence do not even
think of processing these strings with the <string.h> functions (strcpy,
strlen, etc.).
(c) The h_name field of an hostent, however, is a nice "regular",
human-readable, 0-terminated string representing the "official" inet host
name. Same for the aliases.
(d) Both the alias and the address lists are terminated by a (char*)NULL.
They must be, since the struct does not contain the numner of their
elements.
(e) We humans like to write IP addresses in the so-called "dotted quad"
notation, i.e. with strings like "132.206.8.5", where each number
represents one byte of the 4-byte long inet address. A nice library
function, called inet_ntoa(3) can be used to convert an in_addr into a
dotted quad string. See also inet(3) for other useful library functions
that manipulate addresses.
(f) Last but not least, the gethostname(2) routine can be used to get the name
of the local host. However, as your colleague noticed, this may not be the
full qualified inet name, so you have to pass it through gethostbyname to
fix it.
The following program is as an example of the above techniques. It gets
the local host name via gethostname(2), then address and full qualified name
via gethostbyname, and eventually translates the address in a dotted quad.
Ciao
Franco
#include <sys/param.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
int
main(int argc, char *argv[]) {
char hname[MAXHOSTNAMELEN];
char *quad;
struct hostent *hent;
struct in_addr adr;
if (-1==gethostname(hname, MAXHOSTNAMELEN)) {
perror("gethostname");
exit(1);
}
printf("gethostname: %s\n",hname);
if (NULL==(hent=gethostbyname(hname))) {
perror("gethostent");
exit(1);
} else if (AF_INET!=hent->h_addrtype) {
fprintf(stderr,"gethostbyname: not an AF_INET address\n");
exit(1);
}
printf("gethostbyname: %s\n", hent->h_name);
/*
// inet_ntoa(2) needs an in_addr, which we get from the hostent
*/
bcopy(hent->h_addr, &adr.s_addr, hent->h_length);
quad=inet_ntoa(adr);
printf("hostaddr %s\n", quad);
return 0;
}