Table-driven usage message for adnshost.
[adns] / client / adnshost.c
CommitLineData
b0f83da6 1/*
2 * adnshost.c
3 * - useful general-purpose resolver client program
4 */
5/*
d942707d 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>
b0f83da6 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"
c8bea377 33#include "adns.h"
b0f83da6 34
35static void sysfail(const char *what, int errnoval) NONRETURNING;
36static void sysfail(const char *what, int errnoval) {
37 fprintf(stderr,"adnshost failed: %s: %s\n",what,strerror(errnoval));
38 exit(10);
39}
40
c8bea377 41struct optinfo;
42typedef void optfunc(const struct optinfo *oi, const char *arg);
43
44struct 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
56static int ov_env=1, ov_pipe=0, ov_asynch=0;
57static int ov_verbose= 0;
58static int ov_search=0, ov_qc_query=0, ov_qc_anshost=0, ov_qc_cname=1;
59static int ov_tcp=0, ov_show_owner=1, ov_show_type=1, ov_show_cname=1;
60static int ov_cname=0;
61enum ttlmode { tm_none, tm_rel, tm_abs };
62static int ov_ttl= tm_none;
63
64static optfunc of_help, of_type, of_asynch_id, of_cancel_id;
65
66static 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
90static 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
132static 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};
b0f83da6 141
142static void printusage(void) {
c8bea377 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);
b0f83da6 274}
275
c8bea377 276static void of_help(const struct optinfo *oi, const char *arg) {
b0f83da6 277 printusage();
278 if (fclose(stdout)) sysfail("finish writing output",errno);
279 exit(0);
280}
c8bea377 281
282static void of_type(const struct optinfo *oi, const char *arg) { abort(); }
283static void of_asynch_id(const struct optinfo *oi, const char *arg) { abort(); }
284static void of_cancel_id(const struct optinfo *oi, const char *arg) { abort(); }
285
286int main(int argc, const char *const *argv) {
287 of_help(0,0);
288 abort();
289}