// clang -lcares -I/opt/local/include -L/opt/local/lib -o domains domains.c #include <ares.h> #include <stdio.h> #include <stdlib.h> #include <sys/socket.h> #include <arpa/inet.h> #include <netinet/in.h> #include <netdb.h> #include <stdarg.h> #include <string.h> #include <ctype.h> #include <unistd.h> #include <sys/queue.h> #include <fcntl.h> static void callback(void *arg, int status, int timeouts, struct hostent *host) { if(!host || status != ARES_SUCCESS){ printf("Failed to lookup %s\n", ares_strerror(status)); return; } char ip[INET6_ADDRSTRLEN]; int i = 0; for (i = 0; host->h_addr_list[i]; ++i) { inet_ntop(host->h_addrtype, host->h_addr_list[i], ip, sizeof(ip)); printf("%s: %s\n", host->h_name, ip); } } static void wait_ares(ares_channel channel) { for(;;){ struct timeval *tvp, tv; fd_set read_fds, write_fds; int nfds; FD_ZERO(&read_fds); FD_ZERO(&write_fds); nfds = ares_fds(channel, &read_fds, &write_fds); if(nfds == 0){ break; } tvp = ares_timeout(channel, NULL, &tv); select(nfds, &read_fds, &write_fds, NULL, tvp); ares_process(channel, &read_fds, &write_fds); } } struct Request { ares_channel channel; char* domain; SLIST_ENTRY(Request) next; }; int main(const int argc, const char* argv[]) { SLIST_HEAD(Requests, Request) requests; SLIST_INIT(&requests); struct Request* last = NULL; int status; struct ares_options options; int optmask = 0; const char* path; optmask |= ARES_OPT_TIMEOUTMS; options.timeout = 1000; status = ares_library_init(ARES_LIB_INIT_ALL); if (status != ARES_SUCCESS){ printf("ares_library_init: %s\n", ares_strerror(status)); return 1; } for (int i = 1; (path = argv[i]) != NULL || i == 0; i++) { int fd = open(path, O_RDONLY); FILE* fp = fdopen(fd, "r"); char* buffer = NULL; size_t bufferSize = 0; int lineLength = 0; while ((lineLength = getline(&buffer, &bufferSize, fp)) > 0) { struct Request* request = malloc(sizeof(struct Request)); status = ares_init_options(&request->channel, &options, optmask); if(status != ARES_SUCCESS) { printf("ares_init_options: %s\n", ares_strerror(status)); continue; } buffer[lineLength - 1] = '\0'; request->domain = buffer; buffer = NULL; if (NULL == last) { SLIST_INSERT_HEAD(&requests, request, next); } else { SLIST_INSERT_AFTER(last, request, next); } last = request; ares_gethostbyname(request->channel, request->domain, AF_INET, callback, NULL); } } while (!SLIST_EMPTY(&requests)) { struct Request* request = SLIST_FIRST(&requests); wait_ares(request->channel); ares_destroy(request->channel); free(request->domain); SLIST_REMOVE_HEAD(&requests, next); free(request); } ares_library_cleanup(); return 0; }