chiark / gitweb /
Table-driven usage message for adnshost.
[adns.git] / client / adnshost.c
1 /*
2  * adnshost.c
3  * - useful general-purpose resolver client program
4  */
5 /*
6  *  This file is
7  *    Copyright (C) 1997-1999 Ian Jackson <ian@davenant.greenend.org.uk>
8  *
9  *  It is part of adns, which is
10  *    Copyright (C) 1997-1999 Ian Jackson <ian@davenant.greenend.org.uk>
11  *    Copyright (C) 1999 Tony Finch <dot@dotat.at>
12  *  
13  *  This program is free software; you can redistribute it and/or modify
14  *  it under the terms of the GNU General Public License as published by
15  *  the Free Software Foundation; either version 2, or (at your option)
16  *  any later version.
17  *  
18  *  This program is distributed in the hope that it will be useful,
19  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
20  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  *  GNU General Public License for more details.
22  *  
23  *  You should have received a copy of the GNU General Public License
24  *  along with this program; if not, write to the Free Software Foundation,
25  *  Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 
26  */
27
28 #include <stdio.h>
29 #include <string.h>
30 #include <errno.h>
31
32 #include "config.h"
33 #include "adns.h"
34
35 static void sysfail(const char *what, int errnoval) NONRETURNING;
36 static void sysfail(const char *what, int errnoval) {
37   fprintf(stderr,"adnshost failed: %s: %s\n",what,strerror(errnoval));
38   exit(10);
39 }
40
41 struct optinfo;
42 typedef void optfunc(const struct optinfo *oi, const char *arg);
43
44 struct optinfo {
45   enum oi_type {
46     ot_end, ot_desconly,
47     ot_flag, ot_value, ot_func, ot_funcarg
48   } type;
49   const char *desc;
50   const char *sopt, *lopt;
51   int *storep, value;
52   optfunc *func;
53   const char *argdesc;
54 };
55
56 static int ov_env=1, ov_pipe=0, ov_asynch=0;
57 static int ov_verbose= 0;
58 static int ov_search=0, ov_qc_query=0, ov_qc_anshost=0, ov_qc_cname=1;
59 static int ov_tcp=0, ov_show_owner=1, ov_show_type=1, ov_show_cname=1;
60 static int ov_cname=0;
61 enum ttlmode { tm_none, tm_rel, tm_abs };
62 static int ov_ttl= tm_none;
63
64 static optfunc of_help, of_type, of_asynch_id, of_cancel_id;
65
66 static const struct optinfo global_options[]= {
67   { ot_desconly, "global binary options:" },
68   { ot_flag,             "Do not look at environment variables at all",
69     "e", "env",            &ov_env, 0 },
70   { ot_flag,             "Read queries on stdin instead of using args",
71     "f", "pipe",           &ov_pipe, 1 },
72   { ot_flag,             "Allow answers to be reordered",
73     "a", "asynch",         &ov_asynch, 1 },
74                          
75   { ot_desconly, "global verbosity level:" },
76   { ot_value,            "Do not print anything to stderr",
77     "Vq", "quiet",         &ov_verbose, adns_if_noerrprint },
78   { ot_value,            "Report unexpected kinds of problem only  (default)",
79     "Vn", "no-quiet",      &ov_verbose, 0 },
80   { ot_value,            "Debugging mode",
81     "Vd", "debug",         &ov_verbose, adns_if_debug },
82                          
83   { ot_desconly, "other global options:" },
84   { ot_func,             "Print usage information",
85     0, "help",             0,0, of_help },
86
87   { ot_end }
88 };
89
90 static const struct optinfo perquery_options[]= {
91   { ot_desconly, "per-query options:" },
92   { ot_funcarg,          "Query type (see below)",
93     "t", "type",           0,0, &of_type, "type" },
94
95   { ot_desconly, "per-query binary options:" },
96   { ot_flag,             "Use the search list",
97     "s", "search",         &ov_search, 1 },
98   { ot_flag,             "Let query domains contain quote-requiring chars",
99     "Qq", "qc-query",      &ov_qc_query, 1 },
100   { ot_flag,             "Let hostnames in answers contain ...",
101     "Qa", "qc-anshost",    &ov_qc_anshost, 1 },
102   { ot_flag,             "Prevent CNAME target domains from containing ...",
103     "Qc", "qc-cname",      &ov_qc_cname, 0 },
104   { ot_flag,             "Force use of a virtual circuit",
105     "u", "tcp",            &ov_tcp, 1 },
106   { ot_flag,             "Do not display owner name in output",
107     "Do", "show-owner",   &ov_show_owner, 0 },
108   { ot_flag,             "Do not display RR type in output",
109     "Dt", "show-type",    &ov_show_type, 0 },
110   { ot_flag,             "Do not display CNAME target in output",
111     "Dc", "show-cname",    &ov_show_cname, 0 },
112   
113   { ot_desconly, "per-query TTL mode (NB TTL is minimum across all info in reply):" },
114   { ot_value,            "Show the TTL as a TTL",
115     "Tt", "ttl-ttl",       &ov_ttl, tm_rel },
116   { ot_value,            "Show the TTL as a time_t when the data might expire",
117     "Ta", "ttl-abs",       &ov_ttl, tm_abs },
118   { ot_value,            "Do not show the TTL (default)",
119     "Tn", "no-ttl",        &ov_ttl, tm_none },
120   
121   { ot_desconly, "per-query CNAME handling mode:" },
122   { ot_value,            "Call it an error if a CNAME is found",
123     "Cf", "cname-reject",  &ov_cname, adns_qf_cname_forbid },
124   { ot_value,            "Allow references to CNAMEs in other RRs",
125     "Cl", "cname-loose",   &ov_cname, adns_qf_cname_loose },
126   { ot_value,            "CNAME ok for query domain, but not in RRs (default)",
127     "Cs", "cname-ok",      &ov_cname, 0 },
128   
129   { ot_end }
130 };
131
132 static const struct optinfo asynch_options[]= {
133   { ot_desconly, "asynchronous mode `options':" },
134   { ot_funcarg,          "Set <id>, default is decimal sequence starting 0",
135     "i", "asynch-id",      0,0, &of_asynch_id, "id" },
136   { ot_funcarg,          "Cancel the query with id <id>",
137     0, "cancel-id",        0,0, &of_cancel_id, "id" },
138
139   { ot_end }
140 };
141
142 static void printusage(void) {
143   static const struct optinfo *const alloptions[]= {
144     global_options, perquery_options, asynch_options, 0
145   };
146
147   const struct optinfo *const *oiap, *oip=0;
148   int maxsopt, maxlopt, l;
149
150   maxsopt= maxlopt= 0;
151   
152   for (oiap=alloptions; *oiap; oiap++) {
153     for (oip=*oiap; oip->type != ot_end; oip++) {
154       if (oip->type == ot_funcarg) continue;
155       if (oip->sopt) { l= strlen(oip->sopt); if (l>maxsopt) maxsopt= l; }
156       if (oip->lopt) {
157         l= strlen(oip->lopt);
158         if (oip->type == ot_flag && !oip->value) l+= 3;
159         if (l>maxlopt) maxlopt= l;
160       }
161     }
162   }
163         
164   fputs("usage: adnshost [global-opts] [query-opts] query-domain\n"
165         "                             [[query-opts] query-domain ...]\n"
166         "       adnshost [global-opts] [query-opts] -f|--pipe\n",
167         stdout);
168
169   for (oiap=alloptions; *oiap; oiap++) {
170     putchar('\n');
171     for (oip=*oiap; oip->type != ot_end; oip++) {
172       switch (oip->type) {
173       case ot_flag:
174         if (!oip->value) {
175           if (oip->sopt) {
176             printf(" +%-*s --no-%-*s %s\n",
177                    maxsopt, oip->sopt,
178                    maxlopt-2, oip->lopt,
179                    oip->desc);
180           } else {
181             printf(" --no-%-*s %s\n",
182                    maxlopt+maxsopt+1, oip->lopt,
183                    oip->desc);
184           }
185           break;
186         }
187       case ot_value: case ot_func: /* fall through */
188         if (oip->sopt) {
189           printf(" -%-*s --%-*s %s\n",
190                  maxsopt, oip->sopt,
191                  maxlopt+1, oip->lopt,
192                  oip->desc);
193         } else {
194           printf(" --%-*s %s\n",
195                  maxlopt+maxsopt+3, oip->lopt,
196                  oip->desc);
197         }
198         break;
199       case ot_funcarg:
200         if (oip->sopt) {
201           l= (maxlopt + maxsopt - 9 -
202               (strlen(oip->sopt) + strlen(oip->lopt) + 2*strlen(oip->argdesc)));
203           printf(" -%s<%s> / --%s <%s>%*s%s\n",
204                  oip->sopt, oip->argdesc, oip->lopt, oip->argdesc,
205                  l>2 ? l : 2, "",
206                  oip->desc);
207         } else {
208           l= (maxlopt + maxsopt + 1 -
209               (strlen(oip->lopt) + strlen(oip->argdesc)));
210           printf(" --%s <%s>%*s%s\n",
211                  oip->lopt, oip->argdesc,
212                  l>2 ? l : 2, "",
213                  oip->desc);
214         }
215         break;
216       case ot_desconly:
217         printf("%s\n", oip->desc);
218         break;
219       default:
220         abort();
221       }
222     }
223   }
224
225   printf("\nEscaping domains which might start with `-':\n"
226          " - %-*s Next argument is a domain, but more options may follow\n",
227          maxlopt+maxsopt+3, "<domain>");
228   
229   fputs("\n"
230         "Query domains should always be quoted according to master file format.\n"
231         "\n"
232         "For binary options, --FOO and --no-FOO are opposites, as are\n"
233         "-X and +X.  In each case the default is the one not listed.\n"
234         "Per query options stay set a particular way until they are reset,\n"
235         "whether they appear on the command line or on stdin.\n"
236         "All global options must preceed the first query domain.\n"
237         "\n"
238         "With -f, the input should be lines with either an option, possibly\n"
239         "with a value argument (separated from the option by a space if it's a long\n"
240         "option), or a domain (possibly preceded by a hyphen and a space to\n"
241         "distinguish it from an option).\n"
242         "\n"
243         "Output format is master file format without class or TTL by default:\n"
244         "   [<owner>] [<ttl>] [<type>] <data>\n"
245         "or if the <owner> domain refers to a CNAME and --show-cname is on\n"
246         "   [<owner>] [<ttl>] CNAME <cname>\n"
247         "   [<cname>] [<ttl>] <type> <data>\n"
248         "When a query fails you get a line like:\n"
249  "   ; failed <statustype> [<owner>] [<ttl>] [<type>] <status> \"<status string>\"\n"
250         "\n"
251         "If you use --asynch each answer (success or failure) is preceded by a line\n"
252         "   <id> <statustype> <status> <nrrs> [<cname>] \"<status string>\"\n"
253         "where <nrrs> is the number of RRs that follow and <cname> will be `$' or\n"
254         "the CNAME target; the CNAME indirection and error formats above are not used.\n"
255         "\n"
256         "Exit status:\n"
257         " 0    all went well\n"
258         " 1-6  at least one query failed with statustype:\n"
259         "   1    localfail   )\n"
260         "   2    remotefail  ) temporary errors\n"
261         "   3    tempfail  __)_________________\n"
262         "   4    misconfig   )\n"
263         "   5    misquery    ) permanent errors\n"
264         "   6    permfail    )\n"
265         " 10   system trouble\n"
266         " 11   usage problems\n"
267         "\n"
268         "Query types (see adns.h; default is addr):\n"
269         "  ns  soa  ptr  mx  rp  addr       - enhanced versions\n"
270         "  cname  hinfo  txt                - types with only one version\n"
271         "  a  ns-  soa-  ptr-  mx-  rp-     - _raw versions\n",
272         stdout);
273   if (ferror(stdout)) sysfail("write usage message",errno);
274 }
275
276 static void of_help(const struct optinfo *oi, const char *arg) {
277   printusage();
278   if (fclose(stdout)) sysfail("finish writing output",errno);
279   exit(0);
280 }
281
282 static void of_type(const struct optinfo *oi, const char *arg) { abort(); }
283 static void of_asynch_id(const struct optinfo *oi, const char *arg) { abort(); }
284 static void of_cancel_id(const struct optinfo *oi, const char *arg) { abort(); }
285
286 int main(int argc, const char *const *argv) {
287   of_help(0,0);
288   abort();
289 }