From: ian Date: Sun, 10 Oct 1999 15:04:47 +0000 (+0000) Subject: Table-driven usage message for adnshost. X-Git-Tag: privaterel-1999-10-12-fanf-dustman~15 X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=adns.git;a=commitdiff_plain;h=c8bea377e6e198caeef903e5e895718755210274 Table-driven usage message for adnshost. --- diff --git a/client/adnshost.c b/client/adnshost.c index 95831b7..b35af29 100644 --- a/client/adnshost.c +++ b/client/adnshost.c @@ -30,6 +30,7 @@ #include #include "config.h" +#include "adns.h" static void sysfail(const char *what, int errnoval) NONRETURNING; static void sysfail(const char *what, int errnoval) { @@ -37,94 +38,252 @@ static void sysfail(const char *what, int errnoval) { exit(10); } +struct optinfo; +typedef void optfunc(const struct optinfo *oi, const char *arg); + +struct optinfo { + enum oi_type { + ot_end, ot_desconly, + ot_flag, ot_value, ot_func, ot_funcarg + } type; + const char *desc; + const char *sopt, *lopt; + int *storep, value; + optfunc *func; + const char *argdesc; +}; + +static int ov_env=1, ov_pipe=0, ov_asynch=0; +static int ov_verbose= 0; +static int ov_search=0, ov_qc_query=0, ov_qc_anshost=0, ov_qc_cname=1; +static int ov_tcp=0, ov_show_owner=1, ov_show_type=1, ov_show_cname=1; +static int ov_cname=0; +enum ttlmode { tm_none, tm_rel, tm_abs }; +static int ov_ttl= tm_none; + +static optfunc of_help, of_type, of_asynch_id, of_cancel_id; + +static const struct optinfo global_options[]= { + { ot_desconly, "global binary options:" }, + { ot_flag, "Do not look at environment variables at all", + "e", "env", &ov_env, 0 }, + { ot_flag, "Read queries on stdin instead of using args", + "f", "pipe", &ov_pipe, 1 }, + { ot_flag, "Allow answers to be reordered", + "a", "asynch", &ov_asynch, 1 }, + + { ot_desconly, "global verbosity level:" }, + { ot_value, "Do not print anything to stderr", + "Vq", "quiet", &ov_verbose, adns_if_noerrprint }, + { ot_value, "Report unexpected kinds of problem only (default)", + "Vn", "no-quiet", &ov_verbose, 0 }, + { ot_value, "Debugging mode", + "Vd", "debug", &ov_verbose, adns_if_debug }, + + { ot_desconly, "other global options:" }, + { ot_func, "Print usage information", + 0, "help", 0,0, of_help }, + + { ot_end } +}; + +static const struct optinfo perquery_options[]= { + { ot_desconly, "per-query options:" }, + { ot_funcarg, "Query type (see below)", + "t", "type", 0,0, &of_type, "type" }, + + { ot_desconly, "per-query binary options:" }, + { ot_flag, "Use the search list", + "s", "search", &ov_search, 1 }, + { ot_flag, "Let query domains contain quote-requiring chars", + "Qq", "qc-query", &ov_qc_query, 1 }, + { ot_flag, "Let hostnames in answers contain ...", + "Qa", "qc-anshost", &ov_qc_anshost, 1 }, + { ot_flag, "Prevent CNAME target domains from containing ...", + "Qc", "qc-cname", &ov_qc_cname, 0 }, + { ot_flag, "Force use of a virtual circuit", + "u", "tcp", &ov_tcp, 1 }, + { ot_flag, "Do not display owner name in output", + "Do", "show-owner", &ov_show_owner, 0 }, + { ot_flag, "Do not display RR type in output", + "Dt", "show-type", &ov_show_type, 0 }, + { ot_flag, "Do not display CNAME target in output", + "Dc", "show-cname", &ov_show_cname, 0 }, + + { ot_desconly, "per-query TTL mode (NB TTL is minimum across all info in reply):" }, + { ot_value, "Show the TTL as a TTL", + "Tt", "ttl-ttl", &ov_ttl, tm_rel }, + { ot_value, "Show the TTL as a time_t when the data might expire", + "Ta", "ttl-abs", &ov_ttl, tm_abs }, + { ot_value, "Do not show the TTL (default)", + "Tn", "no-ttl", &ov_ttl, tm_none }, + + { ot_desconly, "per-query CNAME handling mode:" }, + { ot_value, "Call it an error if a CNAME is found", + "Cf", "cname-reject", &ov_cname, adns_qf_cname_forbid }, + { ot_value, "Allow references to CNAMEs in other RRs", + "Cl", "cname-loose", &ov_cname, adns_qf_cname_loose }, + { ot_value, "CNAME ok for query domain, but not in RRs (default)", + "Cs", "cname-ok", &ov_cname, 0 }, + + { ot_end } +}; + +static const struct optinfo asynch_options[]= { + { ot_desconly, "asynchronous mode `options':" }, + { ot_funcarg, "Set , default is decimal sequence starting 0", + "i", "asynch-id", 0,0, &of_asynch_id, "id" }, + { ot_funcarg, "Cancel the query with id ", + 0, "cancel-id", 0,0, &of_cancel_id, "id" }, + + { ot_end } +}; static void printusage(void) { - if (fputs -("usage: adnshost [global-opts] [query-opts] query-domain\n" - " [[query-opts] query-domain ...]\n" - " adnshost [global-opts] [query-opts] -f|--pipe\n" - "\n" - "global binary options:\n" - " +e --no-env Do not look at environment variables at all.\n" - " -f --pipe Read queries on stdin instead of using args.\n" - " -a --asynch Allow answers to be reordered.\n" - " -0 --null stdin items are delimited by nulls.\n" - "global verbosity level:\n" - " -Vq --quiet Do not print anything to stderr.\n" - " -Vn --no-quiet Report unexpected kinds of problem only. (default)\n" - " -Vd --debug Debugging mode.\n" - "other global options:\n" - " --help, --version Print usage or version information.\n" - "\n" - "per-query binary options:\n" - " -s --search Use the search list.\n" - " -Qq --qc-query Let query domains contain quote-requiring chars.\n" - " -Qa --qc-anshost Let hostnames in answers contain ...\n" - " +Qc --no-qc-cname Prevent CNAME target domains from containing ...\n" - " -u --tcp Force use of a virtual circuit.\n" - " +Do --no-owner Do not display owner name in output.\n" - " +Dt --no-type Do not display RR type in output.\n" - " +Dc --no-show-cname Do not display CNAME target in output.\n" - "per-query TTL mode (NB TTL is minimum across whole query reply):\n" - " -Tt --ttl-ttl Show the TTL as a TTL.\n" - " -Ta --ttl-abs Show the TTL as a time_t when the data might expire.\n" - " -Tn --no-ttl Do not show the TTL (default).\n" - "per-query cname handling mode:\n" - " -Cf --cname-reject Call it an error if a CNAME is found.\n" - " -Cl --cname-loose Allow references to CNAMEs in other RRs.\n" - " -Cs --cname-ok CNAME ok for query domain, but not in RRs (default).\n" - "query type:\n" - " -t } Set the query type (see below).\n" - " --type } Default is addr. Not case-sensitive.\n" - "other per-query options:\n" - " -i } Set the to print in the output with --async;\n" - " --asynch-id } default is a sequence number in decimal starting at 0.\n" - " --cancel-id Cancel the query with id .\n" - " - Next argument is a domain, but more options may follow.\n" - "\n" - "For binary options, --FOO and --no-FOO are opposites, as are\n" - "-X and +X. In each case the default is the one not listed.\n" - "Per query options stay set a particular way until they are reset,\n" - "whether they appear on the command line or on stdin.\n" - "All global options must preceed the first query domain.\n" - "\n" - "Output format is master file format without class or TTL by default:\n" - " [] [] [] \n" - "or if the domain refers to a CNAME and --show-cname is on\n" - " [] [] CNAME \n" - " [] [] \n" - "When a query fails you get a line like:\n" - " ; failed [] [] [] \"\"\n" - "If you use --asynch, you don't get that. Instead, each answer (success or\n" - "failure) is preceded by a line:\n" - " [] \"\"\n" - "where is the number of RRs that follow and will be `$' or\n" - "the canonical name.\n" - "\n" - "With -f, the input should be a list of arguments one per line (ie separated\n" - "by newlines), or separated by null characters if -0 or --null was used\n" - "\n" - "Exit status:\n" - " 0 all went well\n" - " 1-6 at least one query failed with statustype:\n" - " 1 localfail )\n" - " 2 remotefail ) temporary errors\n" - " 3 tempfail __)_________________\n" - " 4 misconfig )\n" - " 5 misquery ) permanent errors\n" - " 6 permfail )\n" - " 10 system trouble\n" - " 11 usage problems\n" - "\n" - "Query types (see adns.h):\n" - " ns soa ptr mx rp addr - enhanced versions\n" - " cname hinfo txt - types with only one version\n" - " a ns- soa- ptr- mx- rp- - _raw versions\n", - stdout) == EOF) sysfail("write usage message",errno); + static const struct optinfo *const alloptions[]= { + global_options, perquery_options, asynch_options, 0 + }; + + const struct optinfo *const *oiap, *oip=0; + int maxsopt, maxlopt, l; + + maxsopt= maxlopt= 0; + + for (oiap=alloptions; *oiap; oiap++) { + for (oip=*oiap; oip->type != ot_end; oip++) { + if (oip->type == ot_funcarg) continue; + if (oip->sopt) { l= strlen(oip->sopt); if (l>maxsopt) maxsopt= l; } + if (oip->lopt) { + l= strlen(oip->lopt); + if (oip->type == ot_flag && !oip->value) l+= 3; + if (l>maxlopt) maxlopt= l; + } + } + } + + fputs("usage: adnshost [global-opts] [query-opts] query-domain\n" + " [[query-opts] query-domain ...]\n" + " adnshost [global-opts] [query-opts] -f|--pipe\n", + stdout); + + for (oiap=alloptions; *oiap; oiap++) { + putchar('\n'); + for (oip=*oiap; oip->type != ot_end; oip++) { + switch (oip->type) { + case ot_flag: + if (!oip->value) { + if (oip->sopt) { + printf(" +%-*s --no-%-*s %s\n", + maxsopt, oip->sopt, + maxlopt-2, oip->lopt, + oip->desc); + } else { + printf(" --no-%-*s %s\n", + maxlopt+maxsopt+1, oip->lopt, + oip->desc); + } + break; + } + case ot_value: case ot_func: /* fall through */ + if (oip->sopt) { + printf(" -%-*s --%-*s %s\n", + maxsopt, oip->sopt, + maxlopt+1, oip->lopt, + oip->desc); + } else { + printf(" --%-*s %s\n", + maxlopt+maxsopt+3, oip->lopt, + oip->desc); + } + break; + case ot_funcarg: + if (oip->sopt) { + l= (maxlopt + maxsopt - 9 - + (strlen(oip->sopt) + strlen(oip->lopt) + 2*strlen(oip->argdesc))); + printf(" -%s<%s> / --%s <%s>%*s%s\n", + oip->sopt, oip->argdesc, oip->lopt, oip->argdesc, + l>2 ? l : 2, "", + oip->desc); + } else { + l= (maxlopt + maxsopt + 1 - + (strlen(oip->lopt) + strlen(oip->argdesc))); + printf(" --%s <%s>%*s%s\n", + oip->lopt, oip->argdesc, + l>2 ? l : 2, "", + oip->desc); + } + break; + case ot_desconly: + printf("%s\n", oip->desc); + break; + default: + abort(); + } + } + } + + printf("\nEscaping domains which might start with `-':\n" + " - %-*s Next argument is a domain, but more options may follow\n", + maxlopt+maxsopt+3, ""); + + fputs("\n" + "Query domains should always be quoted according to master file format.\n" + "\n" + "For binary options, --FOO and --no-FOO are opposites, as are\n" + "-X and +X. In each case the default is the one not listed.\n" + "Per query options stay set a particular way until they are reset,\n" + "whether they appear on the command line or on stdin.\n" + "All global options must preceed the first query domain.\n" + "\n" + "With -f, the input should be lines with either an option, possibly\n" + "with a value argument (separated from the option by a space if it's a long\n" + "option), or a domain (possibly preceded by a hyphen and a space to\n" + "distinguish it from an option).\n" + "\n" + "Output format is master file format without class or TTL by default:\n" + " [] [] [] \n" + "or if the domain refers to a CNAME and --show-cname is on\n" + " [] [] CNAME \n" + " [] [] \n" + "When a query fails you get a line like:\n" + " ; failed [] [] [] \"\"\n" + "\n" + "If you use --asynch each answer (success or failure) is preceded by a line\n" + " [] \"\"\n" + "where is the number of RRs that follow and will be `$' or\n" + "the CNAME target; the CNAME indirection and error formats above are not used.\n" + "\n" + "Exit status:\n" + " 0 all went well\n" + " 1-6 at least one query failed with statustype:\n" + " 1 localfail )\n" + " 2 remotefail ) temporary errors\n" + " 3 tempfail __)_________________\n" + " 4 misconfig )\n" + " 5 misquery ) permanent errors\n" + " 6 permfail )\n" + " 10 system trouble\n" + " 11 usage problems\n" + "\n" + "Query types (see adns.h; default is addr):\n" + " ns soa ptr mx rp addr - enhanced versions\n" + " cname hinfo txt - types with only one version\n" + " a ns- soa- ptr- mx- rp- - _raw versions\n", + stdout); + if (ferror(stdout)) sysfail("write usage message",errno); } -int main(int argc, const char *const *argv) { +static void of_help(const struct optinfo *oi, const char *arg) { printusage(); if (fclose(stdout)) sysfail("finish writing output",errno); exit(0); } + +static void of_type(const struct optinfo *oi, const char *arg) { abort(); } +static void of_asynch_id(const struct optinfo *oi, const char *arg) { abort(); } +static void of_cancel_id(const struct optinfo *oi, const char *arg) { abort(); } + +int main(int argc, const char *const *argv) { + of_help(0,0); + abort(); +}