diff --git a/CHANGES b/CHANGES index c40093a1e5..bfa947a160 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,7 @@ +3244. [func] Added readline support to nslookup and nsupdate. + Also simplified nsupdate syntax to make "update" + and "prereq" optional. [RT #24659] + 3243. [port] freebsd,netbsd,bsdi: the thread defaults were not being properly set. diff --git a/bin/dig/nslookup.c b/bin/dig/nslookup.c index b45272b0da..2f56b8522a 100644 --- a/bin/dig/nslookup.c +++ b/bin/dig/nslookup.c @@ -15,11 +15,12 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: nslookup.c,v 1.129 2011/02/21 23:47:44 tbox Exp $ */ +/* $Id: nslookup.c,v 1.130 2011/12/16 23:01:16 each Exp $ */ #include #include +#include #include #include @@ -45,6 +46,11 @@ #include +#if defined(HAVE_READLINE) +#include +#include +#endif + static isc_boolean_t short_form = ISC_TRUE, tcpmode = ISC_FALSE, identify = ISC_FALSE, stats = ISC_TRUE, @@ -53,6 +59,8 @@ static isc_boolean_t short_form = ISC_TRUE, section_additional = ISC_TRUE, recurse = ISC_TRUE, aaonly = ISC_FALSE, nofail = ISC_TRUE; +static isc_boolean_t interactive; + static isc_boolean_t in_use = ISC_FALSE; static char defclass[MXRD] = "IN"; static char deftype[MXRD] = "A"; @@ -708,28 +716,12 @@ addlookup(char *opt) { } static void -get_next_command(void) { - char *buf; +do_next_command(char *input) { char *ptr, *arg; - char *input; - fflush(stdout); - buf = isc_mem_allocate(mctx, COMMSIZE); - if (buf == NULL) - fatal("memory allocation failure"); - fputs("> ", stderr); - fflush(stderr); - isc_app_block(); - ptr = fgets(buf, COMMSIZE, stdin); - isc_app_unblock(); - if (ptr == NULL) { - in_use = ISC_FALSE; - goto cleanup; - } - input = buf; ptr = next_token(&input, " \t\r\n"); if (ptr == NULL) - goto cleanup; + return; arg = next_token(&input, " \t\r\n"); if ((strcasecmp(ptr, "set") == 0) && (arg != NULL)) @@ -743,20 +735,48 @@ get_next_command(void) { show_settings(ISC_TRUE, ISC_TRUE); } else if (strcasecmp(ptr, "exit") == 0) { in_use = ISC_FALSE; - goto cleanup; } else if (strcasecmp(ptr, "help") == 0 || strcasecmp(ptr, "?") == 0) { printf("The '%s' command is not yet implemented.\n", ptr); - goto cleanup; } else if (strcasecmp(ptr, "finger") == 0 || strcasecmp(ptr, "root") == 0 || strcasecmp(ptr, "ls") == 0 || strcasecmp(ptr, "view") == 0) { printf("The '%s' command is not implemented.\n", ptr); - goto cleanup; } else addlookup(ptr); - cleanup: +} + +static void +get_next_command(void) { + char *buf; + char *ptr; + + fflush(stdout); + buf = isc_mem_allocate(mctx, COMMSIZE); + if (buf == NULL) + fatal("memory allocation failure"); + isc_app_block(); + if (interactive) { +#ifdef HAVE_READLINE + ptr = readline("> "); + add_history(ptr); +#else + fputs("> ", stderr); + fflush(stderr); + ptr = fgets(buf, COMMSIZE, stdin); +#endif + } else + ptr = fgets(buf, COMMSIZE, stdin); + isc_app_unblock(); + if (ptr == NULL) { + in_use = ISC_FALSE; + } else + do_next_command(ptr); +#ifdef HAVE_READLINE + if (interactive) + free(ptr); +#endif isc_mem_free(mctx, buf); } @@ -852,6 +872,8 @@ int main(int argc, char **argv) { isc_result_t result; + interactive = ISC_TF(isatty(0)); + ISC_LIST_INIT(lookup_list); ISC_LIST_INIT(server_list); ISC_LIST_INIT(search_list); diff --git a/bin/nsupdate/nsupdate.c b/bin/nsupdate/nsupdate.c index ba02366159..e0d1af0105 100644 --- a/bin/nsupdate/nsupdate.c +++ b/bin/nsupdate/nsupdate.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: nsupdate.c,v 1.197 2011/11/03 04:29:28 each Exp $ */ +/* $Id: nsupdate.c,v 1.198 2011/12/16 23:01:16 each Exp $ */ /*! \file */ @@ -85,6 +85,10 @@ #endif #include +#if defined(HAVE_READLINE) +#include +#include +#endif #ifdef HAVE_ADDRINFO #ifdef HAVE_GETADDRINFO @@ -1154,6 +1158,11 @@ parse_rdata(char **cmdlinep, dns_rdataclass_t rdataclass, dns_rdatacallbacks_t callbacks; isc_result_t result; + if (cmdline == NULL) { + rdata->flags = DNS_RDATA_UPDATE; + return (STATUS_MORE); + } + while (*cmdline != 0 && isspace((unsigned char)*cmdline)) cmdline++; @@ -1800,6 +1809,8 @@ evaluate_update(char *cmdline) { } if (strcasecmp(word, "delete") == 0) isdelete = ISC_TRUE; + else if (strcasecmp(word, "del") == 0) + isdelete = ISC_TRUE; else if (strcasecmp(word, "add") == 0) isdelete = ISC_FALSE; else { @@ -1878,27 +1889,13 @@ show_message(FILE *stream, dns_message_t *msg, const char *description) { isc_buffer_free(&buf); } - static isc_uint16_t -get_next_command(void) { - char cmdlinebuf[MAXCMD]; - char *cmdline; +do_next_command(char *cmdline) { char *word; - ddebug("get_next_command()"); - if (interactive) { - fprintf(stdout, "> "); - fflush(stdout); - } - isc_app_block(); - cmdline = fgets(cmdlinebuf, MAXCMD, input); - isc_app_unblock(); - if (cmdline == NULL) - return (STATUS_QUIT); + ddebug("do_next_command()"); word = nsu_strsep(&cmdline, " \t\r\n"); - if (feof(input)) - return (STATUS_QUIT); if (*word == 0) return (STATUS_SEND); if (word[0] == ';') @@ -1907,8 +1904,22 @@ get_next_command(void) { return (STATUS_QUIT); if (strcasecmp(word, "prereq") == 0) return (evaluate_prereq(cmdline)); + if (strcasecmp(word, "nxdomain") == 0) + return (make_prereq(cmdline, ISC_FALSE, ISC_FALSE)); + if (strcasecmp(word, "yxdomain") == 0) + return (make_prereq(cmdline, ISC_TRUE, ISC_FALSE)); + if (strcasecmp(word, "nxrrset") == 0) + return (make_prereq(cmdline, ISC_FALSE, ISC_TRUE)); + if (strcasecmp(word, "yxrrset") == 0) + return (make_prereq(cmdline, ISC_TRUE, ISC_TRUE)); if (strcasecmp(word, "update") == 0) return (evaluate_update(cmdline)); + if (strcasecmp(word, "delete") == 0) + return (update_addordelete(cmdline, ISC_TRUE)); + if (strcasecmp(word, "del") == 0) + return (update_addordelete(cmdline, ISC_TRUE)); + if (strcasecmp(word, "add") == 0) + return (update_addordelete(cmdline, ISC_FALSE)); if (strcasecmp(word, "server") == 0) return (evaluate_server(cmdline)); if (strcasecmp(word, "local") == 0) @@ -1975,18 +1986,46 @@ get_next_command(void) { "oldgsstsig (use Microsoft's GSS_TSIG to sign the request)\n" "zone name (set the zone to be updated)\n" "class CLASS (set the zone's DNS class, e.g. IN (default), CH)\n" -"prereq nxdomain name (does this name not exist)\n" -"prereq yxdomain name (does this name exist)\n" -"prereq nxrrset .... (does this RRset exist)\n" -"prereq yxrrset .... (does this RRset not exist)\n" -"update add .... (add the given record to the zone)\n" -"update delete .... (remove the given record(s) from the zone)\n"); +"[prereq] nxdomain name (does this name not exist)\n" +"[prereq] yxdomain name (does this name exist)\n" +"[prereq] nxrrset .... (does this RRset exist)\n" +"[prereq] yxrrset .... (does this RRset not exist)\n" +"[update] add .... (add the given record to the zone)\n" +"[update] del[ete] .... (remove the given record(s) from the zone)\n"); return (STATUS_MORE); } fprintf(stderr, "incorrect section name: %s\n", word); return (STATUS_SYNTAX); } +static isc_uint16_t +get_next_command(void) { + isc_uint16_t result = STATUS_QUIT; + char cmdlinebuf[MAXCMD]; + char *cmdline; + + isc_app_block(); + if (interactive) { +#ifdef HAVE_READLINE + cmdline = readline("> "); + add_history(cmdline); +#else + fprintf(stdout, "> "); + fflush(stdout); + cmdline = fgets(cmdlinebuf, MAXCMD, input); +#endif + } else + cmdline = fgets(cmdlinebuf, MAXCMD, input); + isc_app_unblock(); + if (cmdline != NULL) + result = do_next_command(cmdline); +#ifdef HAVE_READLINE + if (interactive) + free(cmdline); +#endif + return (result); +} + static isc_boolean_t user_interaction(void) { isc_uint16_t result = STATUS_MORE; diff --git a/bin/nsupdate/nsupdate.docbook b/bin/nsupdate/nsupdate.docbook index 6378df7a7f..9ea461a029 100644 --- a/bin/nsupdate/nsupdate.docbook +++ b/bin/nsupdate/nsupdate.docbook @@ -18,7 +18,7 @@ - PERFORMANCE OF THIS SOFTWARE. --> - + Aug 25, 2009 @@ -424,7 +424,7 @@ - prereq nxdomain + prereq nxdomain domain-name @@ -438,7 +438,7 @@ - prereq yxdomain + prereq yxdomain domain-name @@ -452,7 +452,7 @@ - prereq nxrrset + prereq nxrrset domain-name class type @@ -474,7 +474,7 @@ - prereq yxrrset + prereq yxrrset domain-name class type @@ -496,7 +496,7 @@ - prereq yxrrset + prereq yxrrset domain-name class type @@ -530,7 +530,7 @@ - update delete + update delete domain-name ttl class @@ -556,7 +556,7 @@ - update add + update add domain-name ttl class diff --git a/bin/tests/system/nsupdate/tests.sh b/bin/tests/system/nsupdate/tests.sh index 136af2318f..2374b61874 100644 --- a/bin/tests/system/nsupdate/tests.sh +++ b/bin/tests/system/nsupdate/tests.sh @@ -15,7 +15,7 @@ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -# $Id: tests.sh,v 1.41 2011/07/01 02:25:47 marka Exp $ +# $Id: tests.sh,v 1.42 2011/12/16 23:01:17 each Exp $ SYSTEMTESTTOP=.. . $SYSTEMTESTTOP/conf.sh @@ -58,8 +58,8 @@ echo "I:updating zone" $NSUPDATE -k ns1/ddns.key < /dev/null || status=1 server 10.53.0.1 5300 update add updated.example.nil. 600 A 10.10.10.1 -update add updated.example.nil. 600 TXT Foo -update delete t.example.nil. +add updated.example.nil. 600 TXT Foo +delete t.example.nil. END echo "I:sleeping 5 seconds for server to incorporate changes" @@ -303,7 +303,7 @@ $NSUPDATE -k ns1/ddns.key < /dev/null || status=1 server 10.53.0.1 5300 update add updated3.example.nil. 600 A 10.10.10.3 update add updated3.example.nil. 600 TXT Zap -update delete d.example.nil. +del d.example.nil. send END diff --git a/config.h.in b/config.h.in index 5d252c31f0..740b02dab3 100644 --- a/config.h.in +++ b/config.h.in @@ -16,7 +16,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: config.h.in,v 1.150 2011/12/16 00:10:04 marka Exp $ */ +/* $Id: config.h.in,v 1.151 2011/12/16 23:01:16 each Exp $ */ /*! \file */ @@ -280,6 +280,9 @@ int sigwait(const unsigned int *set, int *sig); /* Define if your OpenSSL version supports GOST. */ #undef HAVE_OPENSSL_GOST +/* Define to 1 if you have the `readline' function. */ +#undef HAVE_READLINE + /* Define to 1 if you have the header file. */ #undef HAVE_REGEX_H diff --git a/configure.in b/configure.in index 12a3b88a68..8582291d87 100644 --- a/configure.in +++ b/configure.in @@ -18,7 +18,7 @@ AC_DIVERT_PUSH(1)dnl esyscmd([sed "s/^/# /" COPYRIGHT])dnl AC_DIVERT_POP()dnl -AC_REVISION($Revision: 1.531 $) +AC_REVISION($Revision: 1.532 $) AC_INIT(lib/dns/name.c) AC_PREREQ(2.59) @@ -2202,6 +2202,28 @@ AC_CHECK_FUNC(strlcat, [ISC_PLATFORM_NEEDSTRLCAT="#define ISC_PLATFORM_NEEDSTRLCAT 1"]) AC_SUBST(ISC_PLATFORM_NEEDSTRLCAT) + +AC_ARG_WITH(readline, + [ --with-readline[=LIBSPEC] specify readline library [default -lreadline]], + readline="$withval", readline="-lreadline") +case "$readline" in +no) ;; +*) + if test "x$readline" = "xyes" + then + readline=-lreadline + fi + saved_LIBS="$LIBS" + LIBS="$LIBS $readline" + AC_CHECK_FUNCS(readline) + if test "$ac_cv_func_readline" = "no" + then + LIBS="$saved_LIBS" + fi + ;; +esac + + ISC_PRINT_OBJS= ISC_PRINT_SRCS= AC_MSG_CHECKING(sprintf)