1 /* This is a _simple_ program to lookup a hostname via. gethostbyname().
2 *
3 * This shows how easy it is to use custom format specifiers, to make your code
4 * easier to write and maintain.
5 *
6 * This file is more commented than normal code, so as to make it easy to follow
7 * while knowning almost nothing about Vstr or Linux IO programming.
8 */
9 #define EX_UTILS_NO_USE_INPUT 1
10 #define EX_UTILS_NO_USE_OPEN 1
11
12 #include "ex_utils.h"
13
14 #include <sys/socket.h>
15 #include <netdb.h>
16
17
main(int argc,char * argv[])18 int main(int argc, char *argv[])
19 {
20 Vstr_base *s1 = ex_init(NULL); /* init the library, and create a string */
21 struct hostent *hp = NULL; /* data from the resolver library */
22
23 /* setup the pre-written custom format specifier for IPv4 addresses,
24 */
25 vstr_cntl_conf(s1->conf, VSTR_CNTL_CONF_SET_FMT_CHAR_ESC, '$');
26 vstr_sc_fmt_add_ipv4_ptr(s1->conf, "{IPv4:%p}");
27
28
29 if (argc != 2) /* if a hostname isn't given output an message to stderr */
30 {
31 size_t pos = 0;
32 size_t len = 0;
33
34 /* add another format specifier for printing Vstr strings */
35 vstr_sc_fmt_add_vstr(s1->conf, "{Vstr:%p%zu%zu%u}");
36
37 /* find the program name ...
38 * putting it at the begining of the Vstr string */
39 vstr_add_cstr_ptr(s1, 0, argc ? argv[0] : "lookup_ip");
40 vstr_sc_basename(s1, 1, s1->len, &pos, &len);
41
42 /* add a format line to the Vstr string, including the program name
43 * which is at the begining of this Vstr string itself */
44 len = vstr_add_fmt(s1, s1->len, " %s ${Vstr:%p%zu%zu%u} %s\n",
45 "Format:",
46 s1, pos, len, 0,
47 "<hostname>");
48
49 vstr_del(s1, 1, s1->len - len); /* delete the original program name */
50
51 io_put_all(s1, STDERR_FILENO);
52
53 exit (EXIT_FAILURE);
54 }
55
56
57 sethostent(1);
58 /* call libc to lookup the hostname */
59 hp = gethostbyname(argv[1]);
60
61
62 /* just print the relevant data.... Note that nothing complicated needs to
63 * be done to print the IPv4 address, the custom formatter takes care of
64 * it */
65 if (!hp)
66 vstr_add_fmt(s1, 0, " Error retrieving hostname '%s': %s.\n",
67 argv[1], hstrerror(h_errno));
68 else if (hp->h_addrtype == AF_INET)
69 vstr_add_fmt(s1, 0, " The hostname '%s' has an "
70 "IPv4 address of \"${IPv4:%p}\".\n", hp->h_name,
71 hp->h_addr_list[0]);
72 else
73 vstr_add_fmt(s1, 0, " The hostname '%s' has an address type that "
74 "isn't an IPv4 address.\n",
75 hp->h_name);
76
77
78 /* Cleanup... */
79 io_put_all(s1, STDOUT_FILENO);
80
81 exit (ex_exit(s1, NULL));
82 }
83