diff --git a/Makefile.in b/Makefile.in index b53f79b8..7cb63b7a 100644 --- a/Makefile.in +++ b/Makefile.in @@ -94,6 +94,9 @@ example: test: cd src && $(MAKE) $@ +getdns_query: + cd src && $(MAKE) $@ + clean: cd src && $(MAKE) $@ cd doc && $(MAKE) $@ diff --git a/src/Makefile.in b/src/Makefile.in index 172231fc..b14c5163 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -149,6 +149,9 @@ libgetdns.la: $(GETDNS_OBJ) context.lo libmini_event.lo $(GLDNS_OBJ) $(COMPAT_OB test: FORCE cd test && $(MAKE) $@ +getdns_query: FORCE + cd test && $(MAKE) $@ + clean: cd test && $(MAKE) $@ rm -f *.o *.lo extension/*.lo extension/*.o $(PROGRAMS) libgetdns.la libgetdns_ext_*.la diff --git a/src/dict.c b/src/dict.c index 439ec0e6..76b07939 100644 --- a/src/dict.c +++ b/src/dict.c @@ -46,6 +46,7 @@ #include "rr-dict.h" #include "const-info.h" #include "gldns/gbuffer.h" +#include "gldns/wire2str.h" /*---------------------------------------- getdns_dict_find */ /** @@ -520,14 +521,13 @@ priv_getdns_bindata_is_dname(struct getdns_bindata *bindata) */ static int getdns_pp_bindata(gldns_buffer *buf, size_t indent, - getdns_bindata *bindata, int rdata_raw) + getdns_bindata *bindata, int rdata_raw, int json) { size_t i, p = gldns_buffer_position(buf); uint8_t *dptr; - char *dname; - char truncfmt[100]; + char spc[1024]; - if (gldns_buffer_printf(buf, " size > 0 && i == bindata->size) { /* all printable? */ - (void) snprintf(truncfmt, 100, - "of \"%%.%ds\"%%s>", (int)(i > 32 ? 32 : i)); - if (gldns_buffer_printf(buf, truncfmt, bindata->data, - i > 32 ? "... " : "") < 0) + if (json) + (void)snprintf(spc, sizeof(spc), "\"%%.%ds\"", (int)i); + else + (void)snprintf(spc, sizeof(spc), "of \"%%.%ds\"%s>", + (int)(i > 32 ? 32 : i), (i > 32 ? "..." : "")); + if (gldns_buffer_printf(buf, spc, bindata->data) < 0) return -1; } else if (bindata->size > 1 && /* null terminated printable */ i == bindata->size - 1 && bindata->data[i] == 0) { - if (gldns_buffer_printf(buf, "of \"%s\">", bindata->data) < 0) + if (gldns_buffer_printf( + buf, (json ? "\"%s\"" : "of \"%s\">"), bindata->data) < 0) return -1; } else if (bindata->size == 1 && *bindata->data == 0) { - if (gldns_buffer_printf(buf, "for .>") < 0) + if (gldns_buffer_printf(buf, json ? "\".\"" : "for .>") < 0) return -1; } else if (priv_getdns_bindata_is_dname(bindata)) { - if (GETDNS_RETURN_GOOD == - getdns_convert_dns_name_to_fqdn(bindata, &dname) && - gldns_buffer_printf(buf, "for %s>", dname) < 0) { - free(dname); + (void)gldns_wire2str_dname_buf( + bindata->data, bindata->size, spc, sizeof(spc)); + if (gldns_buffer_printf( + buf, (json ? "\"%s\"" : "of \"%s\">"), spc) < 0) return -1; + } else if (json) { + if (gldns_buffer_printf(buf, "[") < 0) + return -1; + for (dptr = bindata->data; + dptr < bindata->data + bindata->size; dptr++) { + if (dptr > bindata->data) { + if (gldns_buffer_printf(buf, ",") < 0) + return -1; + } + if (gldns_buffer_printf(buf, "%d", (int)*dptr) < 0) + return -1; } - free(dname); - + if (gldns_buffer_printf(buf, "]") < 0) + return -1; } else { if (gldns_buffer_printf(buf, "of 0x") < 0) return -1; @@ -584,7 +598,9 @@ getdns_pp_bindata(gldns_buffer *buf, size_t indent, static int getdns_pp_dict(gldns_buffer * buf, size_t indent, - const struct getdns_dict *dict); + const getdns_dict *dict, int json); + +static const char *unknown_str_l[] = {" ", " null", "null"}; /*---------------------------------------- getdns_pp_list */ /** @@ -599,7 +615,7 @@ getdns_pp_dict(gldns_buffer * buf, size_t indent, */ static int getdns_pp_list(gldns_buffer *buf, size_t indent, const getdns_list *list, - int for_namespaces) + int for_namespaces, int json) { size_t i, length, p = gldns_buffer_position(buf); getdns_data_type dtype; @@ -620,12 +636,14 @@ getdns_pp_list(gldns_buffer *buf, size_t indent, const getdns_list *list, indent += 2; for (i = 0; i < length; i++) { - if (gldns_buffer_printf(buf, "%s\n%s", (i ? "," : ""), - getdns_indent(indent)) < 0) + if (i && gldns_buffer_printf(buf, ",") < 0) + return -1; + if (json < 2 && gldns_buffer_printf(buf, "\n%s", + getdns_indent(indent)) < 0) return -1; - if (getdns_list_get_data_type(list, i, - &dtype) != GETDNS_RETURN_GOOD) + if (getdns_list_get_data_type(list, i, &dtype) != + GETDNS_RETURN_GOOD) return -1; switch (dtype) { @@ -633,7 +651,7 @@ getdns_pp_list(gldns_buffer *buf, size_t indent, const getdns_list *list, if (getdns_list_get_int(list, i, &int_item)) return -1; - if (for_namespaces && + if (!json && for_namespaces && (strval = priv_getdns_get_const_info(int_item)->name)) { if (gldns_buffer_printf(buf, "%s", strval) < 0) @@ -645,17 +663,19 @@ getdns_pp_list(gldns_buffer *buf, size_t indent, const getdns_list *list, case t_bindata: if (getdns_list_get_bindata(list, i, &bindata_item) != - GETDNS_RETURN_GOOD) + GETDNS_RETURN_GOOD) return -1; - if (getdns_pp_bindata(buf, indent, bindata_item, 0) < 0) + if (getdns_pp_bindata( + buf, indent, bindata_item, 0, json) < 0) return -1; break; case t_list: if (getdns_list_get_list(list, i, &list_item) != - GETDNS_RETURN_GOOD) + GETDNS_RETURN_GOOD) return -1; - if (getdns_pp_list(buf, indent, list_item, 0) < 0) + if (getdns_pp_list( + buf, indent, list_item, 0, json) < 0) return -1; break; @@ -663,18 +683,21 @@ getdns_pp_list(gldns_buffer *buf, size_t indent, const getdns_list *list, if (getdns_list_get_dict(list, i, &dict_item) != GETDNS_RETURN_GOOD) return -1; - if (getdns_pp_dict(buf, indent, dict_item) < 0) + if (getdns_pp_dict(buf, indent, dict_item, json) < 0) return -1; break; default: - if (gldns_buffer_printf(buf, " ") < 0) + if (gldns_buffer_printf( + buf, "%s", unknown_str_l[json]) < 0) return -1; } } indent -= 2; - if (gldns_buffer_printf(buf, i ? "\n%s]" : "]", - getdns_indent(indent)) < 0) + if (json < 2 && i && gldns_buffer_printf( + buf, "\n%s", getdns_indent(indent)) < 0) + return -1; + if (gldns_buffer_printf(buf, "]") < 0) return -1; return gldns_buffer_position(buf) - p; @@ -761,7 +784,7 @@ priv_getdns_print_rcode(gldns_buffer *buf, uint32_t rcode) */ static int getdns_pp_dict(gldns_buffer * buf, size_t indent, - const struct getdns_dict *dict) + const getdns_dict *dict, int json) { size_t i, length, p = gldns_buffer_position(buf); struct getdns_dict_item *item; @@ -779,14 +802,20 @@ getdns_pp_dict(gldns_buffer * buf, size_t indent, indent += 2; RBTREE_FOR(item, struct getdns_dict_item *, (getdns_rbtree_t *)&(dict->root)) { - if (gldns_buffer_printf(buf, "%s\n%s\"%s\":", (i ? "," : "") - , getdns_indent(indent) - , (const char *)item->node.key) < 0) + + if (i && gldns_buffer_printf(buf, ",") < 0) + return -1; + if (json < 2 && gldns_buffer_printf( + buf, "\n%s", getdns_indent(indent)) < 0) + return -1; + if (gldns_buffer_printf( + buf, "\"%s\":",(const char *)item->node.key) < 0) return -1; switch (item->dtype) { case t_int: - if ((strcmp(item->node.key, "type") == 0 || + if (!json && + (strcmp(item->node.key, "type") == 0 || strcmp(item->node.key, "type_covered") == 0 || strcmp(item->node.key, "qtype") == 0) && (strval = priv_getdns_rr_type_name(item->data.n))) { @@ -795,7 +824,8 @@ getdns_pp_dict(gldns_buffer * buf, size_t indent, return -1; break; } - if ((strcmp(item->node.key, "answer_type") == 0 || + if (!json && + (strcmp(item->node.key, "answer_type") == 0 || strcmp(item->node.key, "dnssec_status") == 0 || strcmp(item->node.key, "status") == 0 || strcmp(item->node.key, "append_name") == 0 || @@ -808,17 +838,19 @@ getdns_pp_dict(gldns_buffer * buf, size_t indent, return -1; break; } - if ((strcmp(item->node.key, "class") == 0 || - strcmp(item->node.key, "qclass") == 0) && - priv_getdns_print_class(buf, item->data.n)) + if (!json && + (strcmp(item->node.key, "class") == 0 || + strcmp(item->node.key, "qclass") == 0) && + priv_getdns_print_class(buf, item->data.n)) break; - if (strcmp(item->node.key, "opcode") == 0 && - priv_getdns_print_opcode(buf, item->data.n)) + if (!json && strcmp(item->node.key, "opcode") == 0 && + priv_getdns_print_opcode(buf, item->data.n)) break; - if (strcmp(item->node.key, "rcode") == 0 && - priv_getdns_print_rcode(buf, item->data.n)) + if (!json && strcmp(item->node.key, "rcode") == 0 && + priv_getdns_print_rcode(buf, item->data.n)) break; - if (gldns_buffer_printf(buf, " %d", item->data.n) < 0) + if (gldns_buffer_printf( + buf,(json < 2 ? " %d" : "%d"), item->data.n) < 0) return -1; break; @@ -829,56 +861,64 @@ getdns_pp_dict(gldns_buffer * buf, size_t indent, (item->data.bindata->size == 4 || item->data.bindata->size == 16 )) { - if (gldns_buffer_printf(buf, " ", + if (gldns_buffer_printf(buf, + (json ? "\"%s\"" : " "), inet_ntop(( item->data.bindata->size == 4 ? AF_INET : AF_INET6) - , item->data.bindata->data - , abuf - , 40 - )) < 0) + , item->data.bindata->data + , abuf + , 40 + )) < 0) return -1; - } else if (getdns_pp_bindata(buf, indent, - item->data.bindata, - (strcmp(item->node.key, "rdata_raw") == 0)) < 0) + } else if (getdns_pp_bindata( + buf, indent, item->data.bindata, + (strcmp(item->node.key, "rdata_raw") == 0), + json) < 0) return -1; break; case t_list: /* Don't put empty lists on a new line */ - if (getdns_list_get_length(item->data.list, - &length) != GETDNS_RETURN_GOOD) + if (getdns_list_get_length(item->data.list, &length) != + GETDNS_RETURN_GOOD) return -1; if (length == 0) { - if (gldns_buffer_printf(buf, " []") < 0) + if (gldns_buffer_printf( + buf, (json < 2 ? " []" : "[]")) < 0) return -1; break; } - if (gldns_buffer_printf(buf, "\n%s", - getdns_indent(indent)) < 0) + if (json < 2 && gldns_buffer_printf(buf, "\n%s", + getdns_indent(indent)) < 0) return -1; if (getdns_pp_list(buf, indent, item->data.list, - (strcmp(item->node.key, "namespaces") == 0)) < 0) + (strcmp(item->node.key, "namespaces") == 0), + json) < 0) return -1; break; case t_dict: - if (gldns_buffer_printf(buf, "\n%s", - getdns_indent(indent)) < 0) + if (json < 2 && gldns_buffer_printf(buf, "\n%s", + getdns_indent(indent)) < 0) return -1; - if (getdns_pp_dict(buf, indent, item->data.dict) < 0) + if (getdns_pp_dict( + buf, indent, item->data.dict, json) < 0) return -1; break; default: - if (gldns_buffer_printf(buf, " ") < 0) + if (gldns_buffer_printf( + buf, "%s", unknown_str_l[json]) < 0) return -1; } i++; } indent -= 2; - if (gldns_buffer_printf(buf, i ? "\n%s}" : "}", - getdns_indent(indent)) < 0) + if (json < 2 && i && gldns_buffer_printf( + buf, "\n%s", getdns_indent(indent)) < 0) + return -1; + if (gldns_buffer_printf(buf, "}") < 0) return -1; return gldns_buffer_position(buf) - p; @@ -905,7 +945,7 @@ getdns_pretty_print_dict(const struct getdns_dict *dict) if (!buf) return NULL; - if (getdns_pp_dict(buf, 0, dict) < 0) { + if (getdns_pp_dict(buf, 0, dict, 0) < 0) { gldns_buffer_free(buf); return NULL; } @@ -914,6 +954,18 @@ getdns_pretty_print_dict(const struct getdns_dict *dict) return ret; } /* getdns_pretty_print_dict */ +int +getdns_pretty_snprint_dict(char *str, size_t size, const getdns_dict *dict) +{ + gldns_buffer buf; + + if (!dict) return -1; + + gldns_buffer_init_frm_data(&buf, str, size); + return getdns_pp_dict(&buf, 0, dict, 0) < 0 + ? -1 : gldns_buffer_position(&buf); +} + char * getdns_pretty_print_list(const getdns_list *list) { @@ -927,7 +979,7 @@ getdns_pretty_print_list(const getdns_list *list) if (!buf) return NULL; - if (getdns_pp_list(buf, 0, list, 0) < 0) { + if (getdns_pp_list(buf, 0, list, 0, 0) < 0) { gldns_buffer_free(buf); return NULL; } @@ -936,6 +988,88 @@ getdns_pretty_print_list(const getdns_list *list) return ret; } +int +getdns_pretty_snprint_list(char *str, size_t size, const getdns_list *list) +{ + gldns_buffer buf; + + if (!list) return -1; + + gldns_buffer_init_frm_data(&buf, str, size); + return getdns_pp_list(&buf, 0, list, 0, 0) < 0 + ? -1 : gldns_buffer_position(&buf); +} + +char * +getdns_print_json_dict(const getdns_dict *dict, int pretty) +{ + gldns_buffer *buf; + char *ret; + + if (!dict) + return NULL; + + buf = gldns_buffer_new(8192); + if (!buf) + return NULL; + + if (getdns_pp_dict(buf, 0, dict, pretty ? 1 : 2) < 0) { + gldns_buffer_free(buf); + return NULL; + } + ret = (char *) gldns_buffer_export(buf); + gldns_buffer_free(buf); + return ret; +} /* getdns_print_json_dict */ + +int +getdns_snprint_json_dict( + char *str, size_t size, const getdns_dict *dict, int pretty) +{ + gldns_buffer buf; + + if (!dict) return -1; + + gldns_buffer_init_frm_data(&buf, str, size); + return getdns_pp_dict(&buf, 0, dict, pretty ? 1 : 2) < 0 + ? -1 : gldns_buffer_position(&buf); +} + +char * +getdns_print_json_list(const getdns_list *list, int pretty) +{ + gldns_buffer *buf; + char *ret; + + if (!list) + return NULL; + + buf = gldns_buffer_new(4096); + if (!buf) + return NULL; + + if (getdns_pp_list(buf, 0, list, 0, pretty ? 1 : 2) < 0) { + gldns_buffer_free(buf); + return NULL; + } + ret = (char *) gldns_buffer_export(buf); + gldns_buffer_free(buf); + return ret; +} + +int +getdns_snprint_json_list( + char *str, size_t size, const getdns_list *list, int pretty) +{ + gldns_buffer buf; + + if (!list) return -1; + + gldns_buffer_init_frm_data(&buf, str, size); + return getdns_pp_list(&buf, 0, list, 0, pretty ? 1 : 2) < 0 + ? -1 : gldns_buffer_position(&buf); +} + getdns_return_t getdns_dict_remove_name(struct getdns_dict *this_dict, const char *name) { diff --git a/src/getdns/getdns_extra.h b/src/getdns/getdns_extra.h index 874ef64d..6ea3fb93 100644 --- a/src/getdns/getdns_extra.h +++ b/src/getdns/getdns_extra.h @@ -187,7 +187,29 @@ getdns_context_get_edns_version(getdns_context *context, uint8_t* value); getdns_return_t getdns_context_get_edns_do_bit(getdns_context *context, uint8_t* value); -char *getdns_pretty_print_list(const getdns_list *some_list); +int +getdns_pretty_snprint_dict(char *str, size_t size, const getdns_dict *dict); + +char * +getdns_pretty_print_list(const getdns_list *some_list); + +int +getdns_pretty_snprint_list(char *str, size_t size, const getdns_list *list); + +char * +getdns_print_json_dict(const getdns_dict *some_dict, int pretty); + +int +getdns_snprint_json_dict( + char *str, size_t size, const getdns_dict *dict, int pretty); + +char * +getdns_print_json_list(const getdns_list *some_list, int pretty); + +int +getdns_snprint_json_list( + char *str, size_t size, const getdns_list *list, int pretty); + #ifdef __cplusplus } diff --git a/src/gldns/gbuffer.c b/src/gldns/gbuffer.c index 26d092e5..a73281c5 100644 --- a/src/gldns/gbuffer.c +++ b/src/gldns/gbuffer.c @@ -74,7 +74,7 @@ gldns_buffer_set_capacity(gldns_buffer *buffer, size_t capacity) void *data; gldns_buffer_invariant(buffer); - assert(buffer->_position <= capacity); + assert(buffer->_position <= capacity && !buffer->_fixed); data = (uint8_t *) realloc(buffer->_data, capacity); if (!data) { @@ -126,7 +126,7 @@ gldns_buffer_printf(gldns_buffer *buffer, const char *format, ...) if (written == -1) { buffer->_status_err = 1; return -1; - } else if ((size_t) written >= remaining) { + } else if (!buffer->_fixed && (size_t) written >= remaining) { if (!gldns_buffer_reserve(buffer, (size_t) written + 1)) { buffer->_status_err = 1; return -1; diff --git a/src/gldns/gbuffer.h b/src/gldns/gbuffer.h index 70ef08b2..56e19c78 100644 --- a/src/gldns/gbuffer.h +++ b/src/gldns/gbuffer.h @@ -134,7 +134,7 @@ INLINE void gldns_buffer_invariant(gldns_buffer *buffer) { assert(buffer != NULL); - assert(buffer->_position <= buffer->_limit); + assert(buffer->_position <= buffer->_limit || buffer->_fixed); assert(buffer->_limit <= buffer->_capacity); assert(buffer->_data != NULL); } @@ -231,7 +231,7 @@ gldns_buffer_position(gldns_buffer *buffer) INLINE void gldns_buffer_set_position(gldns_buffer *buffer, size_t mark) { - assert(mark <= buffer->_limit); + assert(mark <= buffer->_limit || buffer->_fixed); buffer->_position = mark; } @@ -245,7 +245,7 @@ gldns_buffer_set_position(gldns_buffer *buffer, size_t mark) INLINE void gldns_buffer_skip(gldns_buffer *buffer, ssize_t count) { - assert(buffer->_position + count <= buffer->_limit); + assert(buffer->_position + count <= buffer->_limit || buffer->_fixed); buffer->_position += count; } @@ -317,7 +317,7 @@ int gldns_buffer_reserve(gldns_buffer *buffer, size_t amount); INLINE uint8_t * gldns_buffer_at(const gldns_buffer *buffer, size_t at) { - assert(at <= buffer->_limit); + assert(at <= buffer->_limit || buffer->_fixed); return buffer->_data + at; } @@ -353,6 +353,7 @@ gldns_buffer_end(gldns_buffer *buffer) INLINE uint8_t * gldns_buffer_current(gldns_buffer *buffer) { + assert(buffer->_position <= buffer->_limit || buffer->_fixed); return gldns_buffer_at(buffer, buffer->_position); } @@ -367,8 +368,7 @@ INLINE size_t gldns_buffer_remaining_at(gldns_buffer *buffer, size_t at) { gldns_buffer_invariant(buffer); - assert(at <= buffer->_limit); - return buffer->_limit - at; + return at < buffer->_limit ? buffer->_limit - at : 0; } /** @@ -420,7 +420,15 @@ gldns_buffer_available(gldns_buffer *buffer, size_t count) INLINE void gldns_buffer_write_at(gldns_buffer *buffer, size_t at, const void *data, size_t count) { - assert(gldns_buffer_available_at(buffer, at, count)); + if (!buffer->_fixed) + assert(gldns_buffer_available_at(buffer, at, count)); + else if (gldns_buffer_remaining_at(buffer, at) == 0) + return; + else if (count > gldns_buffer_remaining_at(buffer, at)) { + memcpy(buffer->_data + at, data, + gldns_buffer_remaining_at(buffer, at)); + return; + } memcpy(buffer->_data + at, data, count); } @@ -469,6 +477,7 @@ gldns_buffer_write_string(gldns_buffer *buffer, const char *str) INLINE void gldns_buffer_write_u8_at(gldns_buffer *buffer, size_t at, uint8_t data) { + if (buffer->_fixed && at + sizeof(data) > buffer->_limit) return; assert(gldns_buffer_available_at(buffer, at, sizeof(data))); buffer->_data[at] = data; } @@ -494,6 +503,7 @@ gldns_buffer_write_u8(gldns_buffer *buffer, uint8_t data) INLINE void gldns_buffer_write_u16_at(gldns_buffer *buffer, size_t at, uint16_t data) { + if (buffer->_fixed && at + sizeof(data) > buffer->_limit) return; assert(gldns_buffer_available_at(buffer, at, sizeof(data))); gldns_write_uint16(buffer->_data + at, data); } @@ -519,6 +529,7 @@ gldns_buffer_write_u16(gldns_buffer *buffer, uint16_t data) INLINE void gldns_buffer_write_u32_at(gldns_buffer *buffer, size_t at, uint32_t data) { + if (buffer->_fixed && at + sizeof(data) > buffer->_limit) return; assert(gldns_buffer_available_at(buffer, at, sizeof(data))); gldns_write_uint32(buffer->_data + at, data); } diff --git a/src/libgetdns.symbols b/src/libgetdns.symbols index d8740b15..3a5a2eb4 100644 --- a/src/libgetdns.symbols +++ b/src/libgetdns.symbols @@ -97,8 +97,6 @@ getdns_context_process_async getdns_context_set_eventloop getdns_context_detach_eventloop getdns_context_run -plain_mem_funcs_user_arg -priv_getdns_context_mf getdns_context_get_resolution_type getdns_context_get_namespaces getdns_context_get_dns_transport @@ -115,3 +113,12 @@ getdns_context_get_edns_maximum_udp_payload_size getdns_context_get_edns_extended_rcode getdns_context_get_edns_version getdns_context_get_edns_do_bit +getdns_pretty_snprint_dict +getdns_pretty_print_list +getdns_pretty_snprint_list +getdns_print_json_dict +getdns_snprint_json_dict +getdns_print_json_list +getdns_snprint_json_list +plain_mem_funcs_user_arg +priv_getdns_context_mf diff --git a/src/test/getdns_query.c b/src/test/getdns_query.c index ecf67749..c7d2eba4 100644 --- a/src/test/getdns_query.c +++ b/src/test/getdns_query.c @@ -95,6 +95,9 @@ print_usage(FILE *out, const char *progname) fprintf(out, "\t-h\tPrint this help\n"); fprintf(out, "\t-i\tPrint api information\n"); fprintf(out, "\t-I\tInteractive mode (> 1 queries on same context)\n"); + fprintf(out, "\t-j\tOutput json response dict\n"); + fprintf(out, "\t-J\tPretty print json response dict\n"); + fprintf(out, "\t-p\tPretty print response dict\n"); fprintf(out, "\t-r\tSet recursing resolution type\n"); fprintf(out, "\t-s\tSet stub resolution type (default = recursing)\n"); fprintf(out, "\t-S\tservice lookup ( is ignored)\n"); @@ -123,6 +126,7 @@ static uint16_t request_type = GETDNS_RRTYPE_NS; static int timeout, edns0_size; static int async = 0, interactive = 0; static enum { GENERAL, ADDRESS, HOSTNAME, SERVICE } calltype = GENERAL; +static int json = 0; #define CONTINUE ((getdns_return_t)-2) @@ -271,6 +275,15 @@ getdns_return_t parse_args(int argc, char **argv) case 'I': interactive = 1; break; + case 'j': + json = 2; + break; + case 'J': + json = 1; + break; + case 'p': + json = 0; + break; case 'r': getdns_context_set_resolution_type( context, @@ -445,7 +458,13 @@ main(int argc, char **argv) if (r) goto done_destroy_extensions; } - if ((response_str = getdns_pretty_print_dict(response))) { + if (json) + response_str = getdns_print_json_dict( + response, json == 1); + else + response_str = getdns_pretty_print_dict(response); + + if (response_str) { fprintf(stdout, "%s\n", response_str); free(response_str); } else {