chiark / gitweb /
121c195ded555e14153d7d10e2a0c5056b5a4343
[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, invert;
87   fd_set readfds, writefds, exceptfds;
88   
89   while ((arg= *++argv)) {
90     if (arg[0] == '-' || arg[0] == '+') {
91       if (arg[0] == '-' && arg[1] == '-') {
92         if (!strncmp(arg,"--no-",5)) {
93           invert= 1;
94           oip= opt_findl(arg+5);
95         } else {
96           invert= 0;
97           oip= opt_findl(arg+2);
98         }
99         if (oip->type == ot_funcarg) {
100           arg= *++argv;
101           if (!arg) usageerr("option --%s requires a value argument",oip->lopt);
102         } else {
103           arg= 0;
104         }
105         opt_do(oip,arg,invert);
106       } else if (arg[0] == '-' && arg[1] == 0) {
107         arg= *++argv;
108         if (!arg) usageerr("option `-' must be followed by a domain");
109         domain_do_arg(arg);
110       } else { /* arg[1] != '-', != '\0' */
111         invert= (arg[0] == '+');
112         ++arg;
113         while (*arg) {
114           oip= opt_finds(&arg);
115           if (oip->type == ot_funcarg) {
116             if (!*arg) {
117               arg= *++argv;
118               if (!arg) usageerr("option -%s requires a value argument",oip->sopt);
119             }
120             opt_do(oip,arg,invert);
121             arg= "";
122           } else {
123             opt_do(oip,0,invert);
124           }
125         }
126       }
127     } else { /* arg[0] != '-' */
128       domain_do_arg(arg);
129     }
130   }
131
132   if (!ov_pipe && !ads) usageerr("no domains given, and -f/--pipe not used; try --help");
133
134   for (;;) {
135     for (;;) {
136       qu= ov_asynch ? 0 : outstanding.head ? outstanding.head->qu : 0;
137       r= adns_check(ads,&qu,&answer,&qun_v);
138       if (r == EAGAIN) break;
139       if (r == ESRCH) { if (!ov_pipe) goto x_quit; else break; }
140       assert(!r);
141       query_done(qun_v,answer);
142     }
143     maxfd= 0;
144     FD_ZERO(&readfds);
145     FD_ZERO(&writefds);
146     FD_ZERO(&exceptfds);
147     if (ov_pipe) {
148       maxfd= 1;
149       FD_SET(0,&readfds);
150     }
151     tv= 0;
152     adns_beforeselect(ads, &maxfd, &readfds,&writefds,&exceptfds, &tv,&tvbuf,0);
153     r= select(maxfd, &readfds,&writefds,&exceptfds, tv);
154     if (r == -1) {
155       if (errno == EINTR) continue;
156       sysfail("select",errno);
157     }
158     adns_afterselect(ads, maxfd, &readfds,&writefds,&exceptfds, 0);
159     if (ov_pipe && FD_ISSET(0,&readfds)) read_query();
160   }
161 x_quit:
162   if (fclose(stdout)) outerr();
163   exit(rcode);
164 }