Commit 74eb2f5c authored by Evan Hunt's avatar Evan Hunt

[master] rndc showzone / rndc delzone of non-added zones

4030.	[func]		"rndc delzone" is now applicable to zones that were
			configured in named.conf, as well as zones that
			were added via "rndc addzone". (Note, however, that
			if named.conf is not also modified, the deleted zone
			will return when named is reloaded.) [RT #37887]

4029.	[func]		"rndc showzone" displays the current configuration
			of a specified zone. [RT #37887]
parent 651c5a50
4030. [func] "rndc delzone" is now applicable to zones that were
configured in named.conf, as well as zones that
were added via "rndc addzone". (Note, however, that
if named.conf is not also modified, the deleted zone
will return when named is reloaded.) [RT #37887]
4029. [func] "rndc showzone" displays the current configuration
of a specified zone. [RT #37887]
4028. [bug] $GENERATE with a zero step was not being caught as a
error. A $GENERATE with a / but no step was not being
caught as a error. [RT #38262]
......
......@@ -206,9 +206,11 @@ ns_control_docommand(isccc_sexpr_t *message, isc_buffer_t **text) {
command_compare(command, NS_COMMAND_LOADKEYS)) {
result = ns_server_rekey(ns_g_server, command, text);
} else if (command_compare(command, NS_COMMAND_ADDZONE)) {
result = ns_server_add_zone(ns_g_server, command, text);
result = ns_server_addzone(ns_g_server, command, text);
} else if (command_compare(command, NS_COMMAND_DELZONE)) {
result = ns_server_del_zone(ns_g_server, command, text);
result = ns_server_delzone(ns_g_server, command, text);
} else if (command_compare(command, NS_COMMAND_SHOWZONE)) {
result = ns_server_showzone(ns_g_server, command, text);
} else if (command_compare(command, NS_COMMAND_SIGNING)) {
result = ns_server_signing(ns_g_server, command, text);
} else if (command_compare(command, NS_COMMAND_ZONESTATUS)) {
......
......@@ -63,6 +63,7 @@
#define NS_COMMAND_SIGN "sign"
#define NS_COMMAND_LOADKEYS "loadkeys"
#define NS_COMMAND_ADDZONE "addzone"
#define NS_COMMAND_SHOWZONE "showzone"
#define NS_COMMAND_DELZONE "delzone"
#define NS_COMMAND_SYNC "sync"
#define NS_COMMAND_SIGNING "signing"
......
......@@ -67,6 +67,7 @@ EXTERN unsigned int ns_g_cpus_detected INIT(1);
EXTERN isc_timermgr_t * ns_g_timermgr INIT(NULL);
EXTERN isc_socketmgr_t * ns_g_socketmgr INIT(NULL);
EXTERN cfg_parser_t * ns_g_parser INIT(NULL);
EXTERN cfg_parser_t * ns_g_addparser INIT(NULL);
EXTERN const char * ns_g_version INIT(VERSION);
EXTERN const char * ns_g_product INIT(PRODUCT);
EXTERN const char * ns_g_description INIT(DESCRIPTION);
......
......@@ -373,13 +373,19 @@ ns_server_validation(ns_server_t *server, char *args, isc_buffer_t **text);
* Add a zone to a running process
*/
isc_result_t
ns_server_add_zone(ns_server_t *server, char *args, isc_buffer_t **text);
ns_server_addzone(ns_server_t *server, char *args, isc_buffer_t **text);
/*%
* Deletes a zone from a running process
*/
isc_result_t
ns_server_del_zone(ns_server_t *server, char *args, isc_buffer_t **text);
ns_server_delzone(ns_server_t *server, char *args, isc_buffer_t **text);
/*%
* Show current configuration for a given zone
*/
isc_result_t
ns_server_showzone(ns_server_t *server, char *args, isc_buffer_t **text);
/*%
* Lists the status of the signing records for a given zone.
......
This diff is collapsed.
......@@ -730,9 +730,6 @@
<listitem>
<para>
Delete a zone while the server is running.
Only zones that were originally added via
<command>rndc addzone</command> can be deleted
in this manner.
</para>
<para>
If the <option>-clean</option> is specified,
......@@ -744,6 +741,25 @@
be cleaned up will be reported in the output
of the <command>rndc delzone</command> command.)
</para>
<para>
If the zone was originally added via
<command>rndc addzone</command>, then it will be
removed permanently. However, if it was originally
configured in <filename>named.conf</filename>, then
that original configuration is still in place; when
the server is restarted or reconfigured, the zone will
come back. To remove it permanently, it must also be
removed from <filename>named.conf</filename>
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><userinput>showzone <replaceable>zone</replaceable> <optional><replaceable>class</replaceable> <optional><replaceable>view</replaceable></optional></optional> </userinput></term>
<listitem>
<para>
Print the configuration of a running zone.
</para>
</listitem>
</varlistentry>
......
......@@ -92,6 +92,15 @@ n=`expr $n + 1`
if [ $ret != 0 ]; then echo "I:failed"; fi
status=`expr $status + $ret`
echo "I:checking rndc showzone with previously added zone ($n)"
ret=0
$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 showzone previous.example > rndc.out.ns2.$n
expected='zone "previous.example" { type master; file "previous.db"; };'
[ "`cat rndc.out.ns2.$n`" = "$expected" ] || ret=1
n=`expr $n + 1`
if [ $ret != 0 ]; then echo "I:failed"; fi
status=`expr $status + $ret`
echo "I:deleting previously added zone ($n)"
ret=0
$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 delzone previous.example 2>&1 | sed 's/^/I:ns2 /'
......@@ -130,13 +139,20 @@ n=`expr $n + 1`
if [ $ret != 0 ]; then echo "I:failed"; fi
status=`expr $status + $ret`
echo "I:attempt to delete a normally-loaded zone ($n)"
echo "I:checking rndc showzone with a normally-loaded zone ($n)"
ret=0
$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 showzone normal.example > rndc.out.ns2.$n
expected='zone "normal.example" { type master; file "normal.db"; };'
[ "`cat rndc.out.ns2.$n`" = "$expected" ] || ret=1
n=`expr $n + 1`
if [ $ret != 0 ]; then echo "I:failed"; fi
status=`expr $status + $ret`
echo "I:delete a normally-loaded zone ($n)"
ret=0
$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 delzone normal.example 2> rndc.out.ns2.$n
grep "permission denied" rndc.out.ns2.$n > /dev/null || ret=1
$DIG $DIGOPTS @10.53.0.2 a.normal.example a > dig.out.ns2.$n
grep 'status: NOERROR' dig.out.ns2.$n > /dev/null || ret=1
grep '^a.normal.example' dig.out.ns2.$n > /dev/null || ret=1
grep 'status: REFUSED' dig.out.ns2.$n > /dev/null || ret=1
n=`expr $n + 1`
if [ $ret != 0 ]; then echo "I:failed"; fi
status=`expr $status + $ret`
......@@ -267,6 +283,14 @@ n=`expr $n + 1`
if [ $ret != 0 ]; then echo "I:failed"; fi
status=`expr $status + $ret`
echo "I:checking rndc showzone with newly added zone ($n)"
ret=0
$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 showzone added.example in external > rndc.out.ns2.$n
expected='zone "added.example" in external { type master; file "added.db"; };'
[ "`cat rndc.out.ns2.$n`" = "$expected" ] || ret=1
n=`expr $n + 1`
if [ $ret != 0 ]; then echo "I:failed"; fi
status=`expr $status + $ret`
echo "I:deleting newly added zone ($n)"
ret=0
......
......@@ -5894,8 +5894,7 @@ options {
<listitem>
<para>
If <userinput>yes</userinput>, then zones can be
added at runtime via <command>rndc addzone</command>
or deleted via <command>rndc delzone</command>.
added at runtime via <command>rndc addzone</command>.
The default is <userinput>no</userinput>.
</para>
</listitem>
......
......@@ -251,6 +251,23 @@
line option.
</para>
</listitem>
<listitem>
<para>
<command>rndc delzone</command> can now be applied to zones
which were configured in <filename>named.conf</filename>;
it is no longer restricted to zones which were added by
<command>rndc addzone</command>. (Note, however, that
this does not edit <filename>named.conf</filename>; the zone
must be removed from the configuration or it will return
when <command>named</command> is restarted or reloaded.)
</para>
</listitem>
<listitem>
<para>
<command>rndc showzone</command> displays the current
configuration for a specified zone.
</para>
</listitem>
</itemizedlist>
</sect2>
<sect2 id="relnotes_changes">
......
......@@ -39,7 +39,6 @@
#include <isc/types.h>
#include <isc/list.h>
/***
*** Types
***/
......@@ -144,6 +143,26 @@ cfg_parse_buffer(cfg_parser_t *pctx, isc_buffer_t *buffer,
*\li others - file contains errors
*/
isc_result_t
cfg_parser_mapadd(cfg_parser_t *pctx, cfg_obj_t *mapobj,
cfg_obj_t *obj, const char *clause);
/*%<
* Add the object 'obj' to the specified clause in mapbody 'mapobj'.
* Used for adding new zones.
*
* Require:
* \li 'obj' is a valid cfg_obj_t.
* \li 'mapobj' is a valid cfg_obj_t of type map.
* \li 'pctx' is a valid cfg_parser_t.
*/
void
cfg_parser_reset(cfg_parser_t *pctx);
/*%<
* Reset an existing parser so it can be re-used for a new file or
* buffer.
*/
void
cfg_parser_destroy(cfg_parser_t **pctxp);
/*%<
......@@ -412,6 +431,7 @@ cfg_printx(const cfg_obj_t *obj, unsigned int flags,
void *closure);
#define CFG_PRINTER_XKEY 0x1 /* '?' out shared keys. */
#define CFG_PRINTER_ONELINE 0x2 /* print config as a single line */
/*%<
* Print the configuration object 'obj' by repeatedly calling the
......@@ -475,7 +495,6 @@ cfg_obj_line(const cfg_obj_t *obj);
* Return the line in file where this object was defined.
*/
ISC_LANG_ENDDECLS
#endif /* ISCCFG_CFG_H */
......@@ -304,9 +304,9 @@ parse_matchname(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
static void
doc_matchname(cfg_printer_t *pctx, const cfg_type_t *type) {
cfg_print_chars(pctx, "[ ", 2);
cfg_print_cstr(pctx, "[ ");
cfg_doc_obj(pctx, type->of);
cfg_print_chars(pctx, " ]", 2);
cfg_print_cstr(pctx, " ]");
}
static const char *matchtype_enums[] = {
......@@ -739,11 +739,11 @@ parse_boolorauto(cfg_parser_t *pctx, const cfg_type_t *type,
static void
print_boolorauto(cfg_printer_t *pctx, const cfg_obj_t *obj) {
if (obj->type->rep == &cfg_rep_void)
cfg_print_chars(pctx, "auto", 4);
cfg_print_cstr(pctx, "auto");
else if (obj->value.boolean)
cfg_print_chars(pctx, "yes", 3);
cfg_print_cstr(pctx, "yes");
else
cfg_print_chars(pctx, "no", 2);
cfg_print_cstr(pctx, "no");
}
static void
......@@ -1117,18 +1117,18 @@ doc_rpz_policy(cfg_printer_t *pctx, const cfg_type_t *type) {
/*
* This is cfg_doc_enum() without the trailing " )".
*/
cfg_print_chars(pctx, "( ", 2);
cfg_print_cstr(pctx, "( ");
for (p = type->of; *p != NULL; p++) {
cfg_print_cstr(pctx, *p);
if (p[1] != NULL)
cfg_print_chars(pctx, " | ", 3);
cfg_print_cstr(pctx, " | ");
}
}
static void
doc_rpz_cname(cfg_printer_t *pctx, const cfg_type_t *type) {
cfg_doc_terminal(pctx, type);
cfg_print_chars(pctx, " )", 2);
cfg_print_cstr(pctx, " )");
}
/*
......@@ -1232,9 +1232,9 @@ cfg_print_kv_tuple(cfg_printer_t *pctx, const cfg_obj_t *obj) {
if (fieldobj->type->print == cfg_print_void)
continue;
if (i != 0) {
cfg_print_chars(pctx, " ", 1);
cfg_print_cstr(pctx, " ");
cfg_print_cstr(pctx, f->name);
cfg_print_chars(pctx, " ", 1);
cfg_print_cstr(pctx, " ");
}
cfg_print_obj(pctx, fieldobj);
}
......@@ -1247,14 +1247,14 @@ cfg_doc_kv_tuple(cfg_printer_t *pctx, const cfg_type_t *type) {
fields = type->of;
for (f = fields; f->name != NULL; f++) {
if (f != fields) {
cfg_print_chars(pctx, " [ ", 3);
cfg_print_cstr(pctx, " [ ");
cfg_print_cstr(pctx, f->name);
if (f->type->doc != cfg_doc_void)
cfg_print_chars(pctx, " ", 1);
cfg_print_cstr(pctx, " ");
}
cfg_doc_obj(pctx, f->type);
if (f != fields)
cfg_print_chars(pctx, " ]", 2);
cfg_print_cstr(pctx, " ]");
}
}
......@@ -1931,11 +1931,11 @@ static cfg_tuplefielddef_t addzone_fields[] = {
{ NULL, NULL, 0 }
};
static cfg_type_t cfg_type_addzone = {
"addzone", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple, &cfg_rep_tuple, addzone_fields };
"zone", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple, &cfg_rep_tuple, addzone_fields };
static cfg_clausedef_t
addzoneconf_clauses[] = {
{ "addzone", &cfg_type_addzone, 0 },
{ "zone", &cfg_type_addzone, CFG_CLAUSEFLAG_MULTI },
{ NULL, NULL, 0 }
};
......@@ -2119,7 +2119,7 @@ static void
print_keyvalue(cfg_printer_t *pctx, const cfg_obj_t *obj) {
const keyword_type_t *kw = obj->type->of;
cfg_print_cstr(pctx, kw->name);
cfg_print_chars(pctx, " ", 1);
cfg_print_cstr(pctx, " ");
kw->type->print(pctx, obj);
}
......@@ -2127,18 +2127,18 @@ static void
doc_keyvalue(cfg_printer_t *pctx, const cfg_type_t *type) {
const keyword_type_t *kw = type->of;
cfg_print_cstr(pctx, kw->name);
cfg_print_chars(pctx, " ", 1);
cfg_print_cstr(pctx, " ");
cfg_doc_obj(pctx, kw->type);
}
static void
doc_optional_keyvalue(cfg_printer_t *pctx, const cfg_type_t *type) {
const keyword_type_t *kw = type->of;
cfg_print_chars(pctx, "[ ", 2);
cfg_print_cstr(pctx, "[ ");
cfg_print_cstr(pctx, kw->name);
cfg_print_chars(pctx, " ", 1);
cfg_print_cstr(pctx, " ");
cfg_doc_obj(pctx, kw->type);
cfg_print_chars(pctx, " ]", 2);
cfg_print_cstr(pctx, " ]");
}
static const char *dialup_enums[] = {
......@@ -2283,9 +2283,9 @@ doc_geoip(cfg_printer_t *pctx, const cfg_type_t *type) {
cfg_print_cstr(pctx, "[ db ");
cfg_doc_enum(pctx, &cfg_type_geoipdb);
cfg_print_cstr(pctx, " ]");
cfg_print_chars(pctx, " ", 1);
cfg_print_cstr(pctx, " ");
cfg_doc_enum(pctx, &cfg_type_geoiptype);
cfg_print_chars(pctx, " ", 1);
cfg_print_cstr(pctx, " ");
cfg_print_cstr(pctx, "<quoted_string>");
}
#endif /* HAVE_GEOIP */
......@@ -2399,11 +2399,11 @@ static cfg_type_t cfg_type_controls = {
static void
doc_optional_bracketed_list(cfg_printer_t *pctx, const cfg_type_t *type) {
const keyword_type_t *kw = type->of;
cfg_print_chars(pctx, "[ ", 2);
cfg_print_cstr(pctx, "[ ");
cfg_print_cstr(pctx, kw->name);
cfg_print_chars(pctx, " ", 1);
cfg_print_cstr(pctx, " ");
cfg_doc_obj(pctx, kw->type);
cfg_print_chars(pctx, " ]", 2);
cfg_print_cstr(pctx, " ]");
}
static cfg_type_t cfg_type_optional_allow = {
......@@ -2646,7 +2646,7 @@ static cfg_tuplefielddef_t negated_fields[] = {
static void
print_negated(cfg_printer_t *pctx, const cfg_obj_t *obj) {
cfg_print_chars(pctx, "!", 1);
cfg_print_cstr(pctx, "!");
cfg_print_tuple(pctx, obj);
}
......@@ -2881,9 +2881,9 @@ static void
doc_logfile(cfg_printer_t *pctx, const cfg_type_t *type) {
UNUSED(type);
cfg_print_cstr(pctx, "<quoted_string>");
cfg_print_chars(pctx, " ", 1);
cfg_print_cstr(pctx, " ");
cfg_print_cstr(pctx, "[ versions ( \"unlimited\" | <integer> ) ]");
cfg_print_chars(pctx, " ", 1);
cfg_print_cstr(pctx, " ");
cfg_print_cstr(pctx, "[ size <size> ]");
}
......@@ -3049,25 +3049,25 @@ static cfg_type_t cfg_type_nameport = {
static void
doc_sockaddrnameport(cfg_printer_t *pctx, const cfg_type_t *type) {
UNUSED(type);
cfg_print_chars(pctx, "( ", 2);
cfg_print_cstr(pctx, "( ");
cfg_print_cstr(pctx, "<quoted_string>");
cfg_print_chars(pctx, " ", 1);
cfg_print_cstr(pctx, " ");
cfg_print_cstr(pctx, "[ port <integer> ]");
cfg_print_chars(pctx, " ", 1);
cfg_print_cstr(pctx, " ");
cfg_print_cstr(pctx, "[ dscp <integer> ]");
cfg_print_chars(pctx, " | ", 3);
cfg_print_cstr(pctx, " | ");
cfg_print_cstr(pctx, "<ipv4_address>");
cfg_print_chars(pctx, " ", 1);
cfg_print_cstr(pctx, " ");
cfg_print_cstr(pctx, "[ port <integer> ]");
cfg_print_chars(pctx, " ", 1);
cfg_print_cstr(pctx, " ");
cfg_print_cstr(pctx, "[ dscp <integer> ]");
cfg_print_chars(pctx, " | ", 3);
cfg_print_cstr(pctx, " | ");
cfg_print_cstr(pctx, "<ipv6_address>");
cfg_print_chars(pctx, " ", 1);
cfg_print_cstr(pctx, " ");
cfg_print_cstr(pctx, "[ port <integer> ]");
cfg_print_chars(pctx, " ", 1);
cfg_print_cstr(pctx, " ");
cfg_print_cstr(pctx, "[ dscp <integer> ]");
cfg_print_chars(pctx, " )", 2);
cfg_print_cstr(pctx, " )");
}
static isc_result_t
......@@ -3141,17 +3141,17 @@ static cfg_type_t cfg_type_nameportiplist = {
static void
doc_masterselement(cfg_printer_t *pctx, const cfg_type_t *type) {
UNUSED(type);
cfg_print_chars(pctx, "( ", 2);
cfg_print_cstr(pctx, "( ");
cfg_print_cstr(pctx, "<masters>");
cfg_print_chars(pctx, " | ", 3);
cfg_print_cstr(pctx, " | ");
cfg_print_cstr(pctx, "<ipv4_address>");
cfg_print_chars(pctx, " ", 1);
cfg_print_cstr(pctx, " ");
cfg_print_cstr(pctx, "[ port <integer> ]");
cfg_print_chars(pctx, " | ", 3);
cfg_print_cstr(pctx, " | ");
cfg_print_cstr(pctx, "<ipv6_address>");
cfg_print_chars(pctx, " ", 1);
cfg_print_cstr(pctx, " ");
cfg_print_cstr(pctx, "[ port <integer> ]");
cfg_print_chars(pctx, " )", 2);
cfg_print_cstr(pctx, " )");
}
static isc_result_t
......
......@@ -147,24 +147,34 @@ cfg_print_chars(cfg_printer_t *pctx, const char *text, int len) {
static void
print_open(cfg_printer_t *pctx) {
cfg_print_chars(pctx, "{\n", 2);
pctx->indent++;
if ((pctx->flags & CFG_PRINTER_ONELINE) != 0)
cfg_print_cstr(pctx, "{ ");
else {
cfg_print_cstr(pctx, "{\n");
pctx->indent++;
}
}
static void
print_indent(cfg_printer_t *pctx) {
int indent = pctx->indent;
if ((pctx->flags & CFG_PRINTER_ONELINE) != 0) {
cfg_print_cstr(pctx, " ");
return;
}
while (indent > 0) {
cfg_print_chars(pctx, "\t", 1);
cfg_print_cstr(pctx, "\t");
indent--;
}
}
static void
print_close(cfg_printer_t *pctx) {
pctx->indent--;
print_indent(pctx);
cfg_print_chars(pctx, "}", 1);
if ((pctx->flags & CFG_PRINTER_ONELINE) == 0) {
pctx->indent--;
print_indent(pctx);
}
cfg_print_cstr(pctx, "}");
}
isc_result_t
......@@ -262,7 +272,7 @@ cfg_print_tuple(cfg_printer_t *pctx, const cfg_obj_t *obj) {
for (f = fields, i = 0; f->name != NULL; f++, i++) {
const cfg_obj_t *fieldobj = obj->value.tuple[i];
if (need_space)
cfg_print_chars(pctx, " ", 1);
cfg_print_cstr(pctx, " ");
cfg_print_obj(pctx, fieldobj);
need_space = ISC_TF(fieldobj->type->print != cfg_print_void);
}
......@@ -276,7 +286,7 @@ cfg_doc_tuple(cfg_printer_t *pctx, const cfg_type_t *type) {
for (f = fields; f->name != NULL; f++) {
if (need_space)
cfg_print_chars(pctx, " ", 1);
cfg_print_cstr(pctx, " ");
cfg_doc_obj(pctx, f->type);
need_space = ISC_TF(f->type->print != cfg_print_void);
}
......@@ -481,6 +491,20 @@ cfg_parser_setcallback(cfg_parser_t *pctx,
pctx->callbackarg = arg;
}
void
cfg_parser_reset(cfg_parser_t *pctx) {
REQUIRE(pctx != NULL);
if (pctx->lexer != NULL)
isc_lex_close(pctx->lexer);
pctx->seen_eof = ISC_FALSE;
pctx->ungotten = ISC_FALSE;
pctx->errors = 0;
pctx->warnings = 0;
pctx->line = 0;
}
/*
* Parse a configuration using a pctx where a lexer has already
* been set up with a source.
......@@ -535,9 +559,12 @@ cfg_parse_buffer(cfg_parser_t *pctx, isc_buffer_t *buffer,
const cfg_type_t *type, cfg_obj_t **ret)
{
isc_result_t result;
REQUIRE(buffer != NULL);
CHECK(isc_lex_openbuffer(pctx->lexer, buffer));
CHECK(parse2(pctx, type, ret));
cleanup:
return (result);
}
......@@ -821,13 +848,13 @@ cfg_parse_enum(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
void
cfg_doc_enum(cfg_printer_t *pctx, const cfg_type_t *type) {
const char * const *p;
cfg_print_chars(pctx, "( ", 2);
cfg_print_cstr(pctx, "( ");
for (p = type->of; *p != NULL; p++) {
cfg_print_cstr(pctx, *p);
if (p[1] != NULL)
cfg_print_chars(pctx, " | ", 3);
cfg_print_cstr(pctx, " | ");
}
cfg_print_chars(pctx, " )", 2);
cfg_print_cstr(pctx, " )");
}
void
......@@ -837,21 +864,21 @@ cfg_print_ustring(cfg_printer_t *pctx, const cfg_obj_t *obj) {
static void
print_qstring(cfg_printer_t *pctx, const cfg_obj_t *obj) {
cfg_print_chars(pctx, "\"", 1);
cfg_print_cstr(pctx, "\"");
cfg_print_ustring(pctx, obj);
cfg_print_chars(pctx, "\"", 1);
cfg_print_cstr(pctx, "\"");
}
static void
print_sstring(cfg_printer_t *pctx, const cfg_obj_t *obj) {
cfg_print_chars(pctx, "\"", 1);
cfg_print_cstr(pctx, "\"");
if ((pctx->flags & CFG_PRINTER_XKEY) != 0) {
unsigned int len = obj->value.string.length;
while (len-- > 0)
cfg_print_chars(pctx, "?", 1);
cfg_print_cstr(pctx, "?");
} else
cfg_print_ustring(pctx, obj);
cfg_print_chars(pctx, "\"", 1);
cfg_print_cstr(pctx, "\"");
}
static void
......@@ -958,9 +985,9 @@ cfg_parse_boolean(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret)
void
cfg_print_boolean(cfg_printer_t *pctx, const cfg_obj_t *obj) {
if (obj->value.boolean)
cfg_print_chars(pctx, "yes", 3);
cfg_print_cstr(pctx, "yes");
else
cfg_print_chars(pctx, "no", 2);
cfg_print_cstr(pctx, "no");
}
cfg_type_t cfg_type_boolean = {
......@@ -994,8 +1021,9 @@ create_listelt(cfg_parser_t *pctx, cfg_listelt_t **eltp) {
}
static void
free_list_elt(cfg_parser_t *pctx, cfg_listelt_t *elt) {
cfg_obj_destroy(pctx, &elt->obj);
free_listelt(cfg_parser_t *pctx, cfg_listelt_t *elt) {
if (elt->obj != NULL)
cfg_obj_destroy(pctx, &elt->obj);
isc_mem_put(pctx->mctx, elt, sizeof(*elt));
}