chiark / gitweb /
adnshost improvements - now runs for at least one query.
[adns.git] / client / adh-main.c
1 /*
2  * adh-main.c
3  * - useful general-purpose resolver client program
4  *   main program and useful subroutines
5  */
6 /*
7  *  This file is
8  *    Copyright (C) 1997-1999 Ian Jackson <ian@davenant.greenend.org.uk>
9  *
10  *  It is part of adns, which is
11  *    Copyright (C) 1997-1999 Ian Jackson <ian@davenant.greenend.org.uk>
12  *    Copyright (C) 1999 Tony Finch <dot@dotat.at>
13  *  
14  *  This program is free software; you can redistribute it and/or modify
15  *  it under the terms of the GNU General Public License as published by
16  *  the Free Software Foundation; either version 2, or (at your option)
17  *  any later version.
18  *  
19  *  This program is distributed in the hope that it will be useful,
20  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
21  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  *  GNU General Public License for more details.
23  *  
24  *  You should have received a copy of the GNU General Public License
25  *  along with this program; if not, write to the Free Software Foundation,
26  *  Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 
27  */
28
29 #include "adnshost.h"
30
31 void sysfail(const char *what, int errnoval) {
32   fprintf(stderr,"adnshost failed: %s: %s\n",what,strerror(errnoval));
33   exit(10);
34 }
35
36 void usageerr(const char *fmt, ...) {
37   va_list al;
38   fputs("adnshost usage error: ",stderr);
39   va_start(al,fmt);
40   vfprintf(stderr,fmt,al);
41   va_end(al);
42   putc('\n',stderr);
43   exit(11);
44 }
45
46 void outerr(void) {
47   sysfail("write to stdout",errno);
48 }
49
50 static void domain_do_arg(const char *domain) {
51   if (ov_pipe) usageerr("-f/--pipe not consistent with domains on command line");
52   ensure_adns_init();
53   query_do(domain);
54 }
55
56 void *xmalloc(size_t sz) {
57   void *p;
58
59   p= malloc(sz); if (!p) sysfail("malloc",sz);
60   return p;
61 }
62
63 char *xstrsave(const char *str) {
64   char *p;
65   
66   p= xmalloc(strlen(str)+1);
67   strcpy(p,str);
68   return p;
69 }
70
71 void of_type(const struct optioninfo *oi, const char *arg) { abort(); }
72
73 int rcode;
74
75 void setnonblock(int fd, int nonblock) { }
76
77 static void read_query(void) { abort(); }
78
79 int main(int argc, const char *const *argv) {
80   const char *arg;
81   const struct optioninfo *oip;
82   struct timeval *tv, tvbuf;
83   adns_query qu;
84   void *qun_v;
85   adns_answer *answer;
86   int r, maxfd;
87   fd_set readfds, writefds, exceptfds;
88   
89   while ((arg= *++argv)) {
90     if (arg[0] == '-') {
91       if (arg[1] == '-') {
92         oip= opt_findl(arg+2);
93         if (oip->type == ot_funcarg) {
94           arg= *++argv;
95           if (!arg) usageerr("option --%s requires a value argument",oip->lopt);
96         } else {
97           arg= 0;
98         }
99         opt_do(oip,arg);
100       } else if (arg[1] == 0) {
101         arg= *++argv;
102         if (!arg) usageerr("option `-' must be followed by a domain");
103         domain_do_arg(arg);
104       } else { /* arg[1] != '-', != '\0' */
105         ++arg;
106         while (*arg) {
107           oip= opt_finds(&arg);
108           if (oip->type == ot_funcarg) {
109             if (!*arg) {
110               arg= *++argv;
111               if (!arg) usageerr("option -%s requires a value argument",oip->sopt);
112             }
113             arg= "";
114           } else {
115             arg= 0;
116           }
117           opt_do(oip,arg);
118         }
119       }
120     } else { /* arg[0] != '-' */
121       domain_do_arg(arg);
122     }
123   }
124
125   if (!ov_pipe && !ads) usageerr("no domains given, and -f/--pipe not used; try --help");
126
127   for (;;) {
128     for (;;) {
129       qu= ov_asynch ? 0 : outstanding.head ? outstanding.head->qu : 0;
130       r= adns_check(ads,&qu,&answer,&qun_v);
131       if (r == EAGAIN) break;
132       if (r == ESRCH) { if (!ov_pipe) goto x_quit; else break; }
133       assert(!r);
134       query_done(qun_v,answer);
135     }
136     maxfd= 0;
137     FD_ZERO(&readfds);
138     FD_ZERO(&writefds);
139     FD_ZERO(&exceptfds);
140     if (ov_pipe) {
141       maxfd= 1;
142       FD_SET(0,&readfds);
143     }
144     tv= 0;
145     adns_beforeselect(ads, &maxfd, &readfds,&writefds,&exceptfds, &tv,&tvbuf,0);
146     r= select(maxfd, &readfds,&writefds,&exceptfds, tv);
147     if (r == -1) {
148       if (errno == EINTR) continue;
149       sysfail("select",errno);
150     }
151     adns_afterselect(ads, maxfd, &readfds,&writefds,&exceptfds, 0);
152     if (ov_pipe && FD_ISSET(0,&readfds)) read_query();
153   }
154 x_quit:
155   if (fclose(stdout)) outerr();
156   exit(rcode);
157 }