X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=adns.git;a=blobdiff_plain;f=client%2Fadh-opts.c;h=08310e089d19939c7672d6bd7156f73b57ec700e;hp=7c2c42bfc2572bdf117eef03a738fcce2a7374a6;hb=75884a1571b83afd1bf1ba0e9546521594280254;hpb=d1cff511d87e902d96bcd39544635f81728de1ae diff --git a/client/adh-opts.c b/client/adh-opts.c index 7c2c42b..08310e0 100644 --- a/client/adh-opts.c +++ b/client/adh-opts.c @@ -4,12 +4,11 @@ * option handling tables etc. */ /* - * This file is - * Copyright (C) 1997-1999 Ian Jackson - * - * It is part of adns, which is - * Copyright (C) 1997-1999 Ian Jackson - * Copyright (C) 1999 Tony Finch + * This file is part of adns, which is + * Copyright (C) 1997-2000,2003,2006 Ian Jackson + * Copyright (C) 1999-2000,2003,2006 Tony Finch + * Copyright (C) 1991 Massachusetts Institute of Technology + * (See the file INSTALL for full details.) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -26,13 +25,17 @@ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#include "adnshost.h" + int ov_env=1, ov_pipe=0, ov_asynch=0; int ov_verbose= 0; +adns_rrtype ov_type= adns_r_none; int ov_search=0, ov_qc_query=0, ov_qc_anshost=0, ov_qc_cname=1; +int ov_tcp=0, ov_cname=0, ov_format=fmt_default; +char *ov_id= 0; struct perqueryflags_remember ov_pqfr = { 1,1,1, tm_none }; -int ov_tcp=0, ov_cname=0; -static const struct optinfo global_options[]= { +static const struct optioninfo global_options[]= { { ot_desconly, "global binary options:" }, { ot_flag, "Do not look at environment variables at all", "e", "env", &ov_env, 0 }, @@ -40,6 +43,14 @@ static const struct optinfo global_options[]= { "f", "pipe", &ov_pipe, 1 }, { ot_flag, "Allow answers to be reordered", "a", "asynch", &ov_asynch, 1 }, + + { ot_desconly, "answer/error output format and destination (see below):" }, + { ot_value, "Answers to stdout, errors as messages to stderr (default)", + "Fs", "fmt-simple", &ov_format, fmt_simple }, + { ot_value, "Answers and errors both to stdout in parseable format", + "Fi", "fmt-inline", &ov_format, fmt_inline }, + { ot_value, "Fully-parseable output format (default for --asynch)", + "Fa", "fmt-asynch", &ov_format, fmt_asynch }, { ot_desconly, "global verbosity level:" }, { ot_value, "Do not print anything to stderr", @@ -50,16 +61,24 @@ static const struct optinfo global_options[]= { "Vd", "debug", &ov_verbose, adns_if_debug }, { ot_desconly, "other global options:" }, + { ot_funcarg, "Configuration to use instead of /etc/resolv.conf", + 0, "config", 0,0, of_config, "" }, + { ot_func, "Print version number", + 0, "version", 0,0, of_version }, { ot_func, "Print usage information", 0, "help", 0,0, of_help }, { ot_end } }; -static const struct optinfo perquery_options[]= { +static const struct optioninfo perquery_options[]= { { ot_desconly, "per-query options:" }, { ot_funcarg, "Query type (see below)", "t", "type", 0,0, &of_type, "type" }, + { ot_funcarg, "Do reverse query (address -> name lookup)", + "i", "ptr", 0,0, &of_ptr, "addr" }, + { ot_funcarg2, "Lookup in in-addr-like `zone' (eg MAPS RBL)", + 0, "reverse", 0,0, &of_reverse, "addr","zone" }, { ot_desconly, "per-query binary options:" }, { ot_flag, "Use the search list", @@ -97,24 +116,24 @@ static const struct optinfo perquery_options[]= { { ot_desconly, "asynchronous/pipe 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, "asynch-id", 0,0, &of_asynch_id, "id" }, + { ot_funcarg, "Cancel the query with id (no error if not found)", 0, "cancel-id", 0,0, &of_cancel_id, "id" }, { ot_end } }; static void printusage(void) { - static const struct optinfo *const all_optiontables[]= { + static const struct optioninfo *const all_optiontables[]= { global_options, perquery_options, 0 }; - const struct optinfo *const *oiap, *oip=0; + const struct optioninfo *const *oiap, *oip=0; int maxsopt, maxlopt, l; maxsopt= maxlopt= 0; - for (oiap=alloptions; *oiap; oiap++) { + for (oiap=all_optiontables; *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; } @@ -131,7 +150,7 @@ static void printusage(void) { " adnshost [global-opts] [query-opts] -f|--pipe\n", stdout); - for (oiap=alloptions; *oiap; oiap++) { + for (oiap=all_optiontables; *oiap; oiap++) { putchar('\n'); for (oip=*oiap; oip->type != ot_end; oip++) { switch (oip->type) { @@ -178,6 +197,15 @@ static void printusage(void) { oip->desc); } break; + case ot_funcarg2: + assert(!oip->sopt); + l= (maxlopt + maxsopt - 2 - + (strlen(oip->lopt) + strlen(oip->argdesc) + strlen(oip->argdesc2))); + printf(" --%s <%s> <%s>%*s%s\n", + oip->lopt, oip->argdesc, oip->argdesc2, + l>2 ? l : 2, "", + oip->desc); + break; case ot_desconly: printf("%s\n", oip->desc); break; @@ -210,11 +238,14 @@ static void printusage(void) { "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" + "When a query fails you get an error message to stderr (with --fmt-simple).\n" + "Specify --fmt-inline for lines like this (broken here for readability):\n" + " ; failed \\\n" + " [] [] [] \"\"\n" + "If you use --fmt-asynch, which is the default for --asynch,\n" + "each answer (success or failure) is preceded by a line\n" + " \\\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" @@ -231,16 +262,96 @@ static void printusage(void) { " 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", + " ns soa ptr mx rp srv addr - enhanced versions\n" + " cname hinfo txt - types with only one version\n" + " a ns- soa- ptr- mx- rp- srv- - _raw versions\n" + " type - `unknown' type, RFC3597\n" + "Default is addr, or ptr for -i/--ptr queries\n", stdout); if (ferror(stdout)) sysfail("write usage message",errno); } -static void of_help(const struct optinfo *oi, const char *arg) { +void of_version(const struct optioninfo *oi, const char *arg, const char *arg2) { + VERSION_PRINT_QUIT("adnshost"); +} + +void of_help(const struct optioninfo *oi, const char *arg, const char *arg2) { printusage(); if (fclose(stdout)) sysfail("finish writing output",errno); - exit(0); + quitnow(0); +} + +typedef int comparer_type(const char **optp, const struct optioninfo *entry); + +static int oc_long(const char **optp, const struct optioninfo *entry) { + return entry->lopt && !strcmp(*optp,entry->lopt); } +static int oc_short(const char **optp, const struct optioninfo *entry) { + const char *sopt; + int l; + + sopt= entry->sopt; + if (!sopt) return 0; + l= strlen(sopt); + if (memcmp(*optp,sopt,l)) return 0; + (*optp) += l; + return 1; +} + +static const struct optioninfo *find1(const char **optp, + const struct optioninfo *table, + comparer_type *comparer) { + for (;;) { + if (table->type == ot_end) return 0; + if (comparer(optp,table)) return table; + table++; + } +} + +static const struct optioninfo *find(const char **optp, + const char *prefix, + comparer_type *comparer) { + const struct optioninfo *oip; + const char *opt; + + opt= *optp; + oip= find1(optp,perquery_options,comparer); + if (oip) return oip; + oip= find1(optp,global_options,comparer); + if (!oip) usageerr("unknown option %s%s",prefix,opt); + if (ads) usageerr("global option %s%s specified after query domain(s)",prefix,opt); + return oip; +} + +const struct optioninfo *opt_findl(const char *opt) { return find(&opt,"--",oc_long); } +const struct optioninfo *opt_finds(const char **optp) { return find(optp,"-",oc_short); } + +static void noninvert(const struct optioninfo *oip) NONRETURNING; +static void noninvert(const struct optioninfo *oip) { + usageerr("option %s%s%s%s%s may not be inverted", + oip->sopt ? "-" : "", oip->sopt ? oip->sopt : "", + oip->lopt && oip->sopt ? " / " : "", + oip->lopt ? "--" : "", oip->lopt ? oip->lopt : ""); +} + +void opt_do(const struct optioninfo *oip, int invert, + const char *arg, const char *arg2) { + switch (oip->type) { + case ot_flag: + assert(!arg); + *oip->storep= !invert; + return; + case ot_value: + assert(!arg); + if (invert) noninvert(oip); + *oip->storep= oip->value; + return; + case ot_func: case ot_funcarg: case ot_funcarg2: + if (invert) noninvert(oip); + oip->func(oip,arg,arg2); + return; + default: + abort(); + } +}