How about a few lines of C?
// clang -lcares -I/opt/local/include -L/opt/local/lib -o domains domains.c
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
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;
}