Table-driven usage message for adnshost.
[adns] / 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 }