]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
cfg_parse_ functions internally handle the parser
authorColin Vidal <colin@isc.org>
Wed, 22 Oct 2025 09:49:09 +0000 (11:49 +0200)
committerEvan Hunt <each@isc.org>
Thu, 23 Oct 2025 20:01:08 +0000 (13:01 -0700)
Instead of (1) allocating a parser, (2) parsing a file/buffer then (3)
freeing the parser, the parser is now internally created/destroyed from
within the `cfg_parse_*` functions. This simplifies a lot the use cases,
especially around the error cases where the parser needs to be freed in
a cleanup goto.

The only trick was the parser callback mechanism, which would previously
have been set up between steps 1 and 2.  Since it's never been used for
any purpose other than the "directory" option, the chdir call has now
been moved inside the parser and the generic callback mechanism has been
removed, replacing CFG_CLAUSEFLAG_CALLBACK with CFG_CLAUSEFLAG_CHDIR.

25 files changed:
bin/check/named-checkconf.c
bin/delv/delv.c
bin/dig/dighost.c
bin/dnssec/dnssec-keygen.c
bin/dnssec/dnssec-ksr.c
bin/named/config.c
bin/named/controlconf.c
bin/named/include/named/config.h
bin/named/server.c
bin/nsupdate/nsupdate.c
bin/plugins/filter-a.c
bin/plugins/filter-aaaa.c
bin/plugins/synthrecord.c
bin/rndc/rndc.c
bin/tests/system/checkconf/tests.sh
bin/tests/system/hooks/driver/test-syncplugin.c
doc/misc/cfg_test.c
lib/isccfg/include/isccfg/cfg.h
lib/isccfg/include/isccfg/grammar.h
lib/isccfg/namedconf.c
lib/isccfg/parser.c
tests/isccfg/duration_test.c
tests/isccfg/grammar_test.c
tests/isccfg/meson.build
tests/isccfg/parser_test.c

index 0c217efd924441b43538d8ddaa4ee1f26f785ab0..169fd66ef75ca1db0dca3fbc1ad954979bf89153 100644 (file)
@@ -63,32 +63,6 @@ usage(void) {
        exit(EXIT_SUCCESS);
 }
 
-/*% directory callback */
-static isc_result_t
-directory_callback(const char *clausename, const cfg_obj_t *obj, void *arg) {
-       isc_result_t result;
-       const char *directory;
-
-       REQUIRE(strcasecmp("directory", clausename) == 0);
-
-       UNUSED(arg);
-       UNUSED(clausename);
-
-       /*
-        * Change directory.
-        */
-       directory = cfg_obj_asstring(obj);
-       result = isc_dir_chdir(directory);
-       if (result != ISC_R_SUCCESS) {
-               cfg_obj_log(obj, ISC_LOG_ERROR,
-                           "change directory to '%s' failed: %s\n", directory,
-                           isc_result_totext(result));
-               return result;
-       }
-
-       return ISC_R_SUCCESS;
-}
-
 static bool
 get_maps(const cfg_obj_t **maps, const char *name, const cfg_obj_t **obj) {
        int i;
@@ -574,16 +548,14 @@ output(void *closure, const char *text, int textlen) {
 int
 main(int argc, char **argv) {
        int c;
-       cfg_parser_t *parser = NULL;
        cfg_obj_t *config = NULL;
        const char *conffile = NULL;
        isc_result_t result = ISC_R_SUCCESS;
        bool load_zones = false;
        bool list_zones = false;
        bool print = false;
-       bool nodeprecate = false;
-       bool allconfigs = false;
        unsigned int flags = 0;
+       unsigned int parserflags = 0;
        unsigned int checkflags = BIND_CHECK_PLUGINS | BIND_CHECK_ALGORITHMS;
 
        isc_commandline_init(argc, argv);
@@ -631,7 +603,7 @@ main(int argc, char **argv) {
                        break;
 
                case 'i':
-                       nodeprecate = true;
+                       parserflags |= CFG_PCTX_NODEPRECATED;
                        break;
 
                case 'j':
@@ -650,7 +622,7 @@ main(int argc, char **argv) {
                        break;
 
                case 'n':
-                       allconfigs = true;
+                       parserflags |= CFG_PCTX_ALLCONFIGS;
                        break;
 
                case 't':
@@ -722,18 +694,8 @@ main(int argc, char **argv) {
        }
 
        CHECK(setup_logging(stdout));
-
-       CHECK(cfg_parser_create(isc_g_mctx, &parser));
-
-       if (nodeprecate) {
-               cfg_parser_setflags(parser, CFG_PCTX_NODEPRECATED, true);
-       }
-       if (allconfigs) {
-               cfg_parser_setflags(parser, CFG_PCTX_ALLCONFIGS, true);
-       }
-       cfg_parser_setcallback(parser, directory_callback, NULL);
-
-       CHECK(cfg_parse_file(parser, conffile, &cfg_type_namedconf, &config));
+       CHECK(cfg_parse_file(isc_g_mctx, conffile, &cfg_type_namedconf,
+                            parserflags, &config));
        CHECK(isccfg_check_namedconf(config, checkflags, isc_g_mctx));
        if (load_zones || list_zones) {
                CHECK(load_zones_fromconfig(config, list_zones));
@@ -748,9 +710,5 @@ cleanup:
                cfg_obj_detach(&config);
        }
 
-       if (parser != NULL) {
-               cfg_parser_destroy(&parser);
-       }
-
        return result == ISC_R_SUCCESS ? 0 : 1;
 }
index dd53c825fa36c98af70383c437b04c1150881a03..b05e05f2d22f3c715b6b1746fdf656020bb67a0a 100644 (file)
@@ -808,7 +808,6 @@ cleanup:
 static isc_result_t
 setup_dnsseckeys(dns_client_t *client, dns_view_t *toview) {
        isc_result_t result;
-       cfg_parser_t *parser = NULL;
        const cfg_obj_t *trust_anchors = NULL;
        cfg_obj_t *bindkeys = NULL;
 
@@ -824,15 +823,13 @@ setup_dnsseckeys(dns_client_t *client, dns_view_t *toview) {
                CHECK(convert_name(&afn, &anchor_name, trust_anchor));
        }
 
-       CHECK(cfg_parser_create(isc_g_mctx, &parser));
-
        if (anchorfile != NULL) {
                if (access(anchorfile, R_OK) != 0) {
                        fatal("Unable to read key file '%s'", anchorfile);
                }
 
-               result = cfg_parse_file(parser, anchorfile, &cfg_type_bindkeys,
-                                       &bindkeys);
+               result = cfg_parse_file(isc_g_mctx, anchorfile,
+                                       &cfg_type_bindkeys, 0, &bindkeys);
                if (result != ISC_R_SUCCESS) {
                        fatal("Unable to load keys from '%s'", anchorfile);
                }
@@ -841,8 +838,7 @@ setup_dnsseckeys(dns_client_t *client, dns_view_t *toview) {
 
                isc_buffer_init(&b, anchortext, sizeof(anchortext) - 1);
                isc_buffer_add(&b, sizeof(anchortext) - 1);
-               cfg_parser_reset(parser);
-               result = cfg_parse_buffer(parser, &b, NULL, 0,
+               result = cfg_parse_buffer(isc_g_mctx, &b, NULL, 0,
                                          &cfg_type_bindkeys, 0, &bindkeys);
                if (result != ISC_R_SUCCESS) {
                        fatal("Unable to parse built-in keys");
@@ -864,9 +860,6 @@ cleanup:
        if (bindkeys != NULL) {
                cfg_obj_detach(&bindkeys);
        }
-       if (parser != NULL) {
-               cfg_parser_destroy(&parser);
-       }
        if (result != ISC_R_SUCCESS) {
                delv_log(ISC_LOG_ERROR, "setup_dnsseckeys: %s",
                         isc_result_totext(result));
index 51949c2cc9fdffbffd9718681773d255b3f0436e..5928c265bd8a8c3f270269df663f61c3f85574f7 100644 (file)
@@ -1072,7 +1072,6 @@ parse_hmac(const char *algname) {
  */
 static isc_result_t
 read_confkey(void) {
-       cfg_parser_t *pctx = NULL;
        cfg_obj_t *file = NULL;
        const cfg_obj_t *keyobj = NULL;
        const cfg_obj_t *secretobj = NULL;
@@ -1086,12 +1085,8 @@ read_confkey(void) {
                return ISC_R_FILENOTFOUND;
        }
 
-       result = cfg_parser_create(isc_g_mctx, &pctx);
-       if (result != ISC_R_SUCCESS) {
-               goto cleanup;
-       }
-
-       result = cfg_parse_file(pctx, keyfile, &cfg_type_sessionkey, &file);
+       result = cfg_parse_file(isc_g_mctx, keyfile, &cfg_type_sessionkey, 0,
+                               &file);
        if (result != ISC_R_SUCCESS) {
                goto cleanup;
        }
@@ -1117,11 +1112,8 @@ read_confkey(void) {
        setup_text_key();
 
 cleanup:
-       if (pctx != NULL) {
-               if (file != NULL) {
-                       cfg_obj_detach(&file);
-               }
-               cfg_parser_destroy(&pctx);
+       if (file != NULL) {
+               cfg_obj_detach(&file);
        }
 
        return result;
index ab53148b44950ce4c9e01aa59649a4021f0a9f94..6c6e82f097d96f250c920c252cdbfe8e29577a81 100644 (file)
@@ -1147,14 +1147,11 @@ main(int argc, char **argv) {
 
                        keygen(&ctx, argc, argv);
                } else {
-                       cfg_parser_t *parser = NULL;
                        cfg_obj_t *config = NULL;
                        dns_kasp_t *kasp = NULL;
 
-                       RUNTIME_CHECK(cfg_parser_create(isc_g_mctx, &parser) ==
-                                     ISC_R_SUCCESS);
-                       if (cfg_parse_file(parser, ctx.configfile,
-                                          &cfg_type_namedconf,
+                       if (cfg_parse_file(isc_g_mctx, ctx.configfile,
+                                          &cfg_type_namedconf, 0,
                                           &config) != ISC_R_SUCCESS)
                        {
                                fatal("unable to load dnssec-policy '%s' from "
@@ -1200,7 +1197,6 @@ main(int argc, char **argv) {
 
                        dns_kasp_detach(&kasp);
                        cfg_obj_detach(&config);
-                       cfg_parser_destroy(&parser);
                }
        } else {
                keygen(&ctx, argc, argv);
index 0a43fd889acc708c8c786baed4f37d80b0376e97..a4ef81b82ec4e4fedebaf0f62cdc762b230e08d9 100644 (file)
@@ -170,11 +170,9 @@ checkparams(ksr_ctx_t *ksr, const char *command) {
 
 static void
 getkasp(ksr_ctx_t *ksr, dns_kasp_t **kasp) {
-       cfg_parser_t *parser = NULL;
        cfg_obj_t *config = NULL;
 
-       RUNTIME_CHECK(cfg_parser_create(isc_g_mctx, &parser) == ISC_R_SUCCESS);
-       if (cfg_parse_file(parser, ksr->configfile, &cfg_type_namedconf,
+       if (cfg_parse_file(isc_g_mctx, ksr->configfile, &cfg_type_namedconf, 0,
                           &config) != ISC_R_SUCCESS)
        {
                fatal("unable to load dnssec-policy '%s' from '%s'",
@@ -188,7 +186,6 @@ getkasp(ksr_ctx_t *ksr, dns_kasp_t **kasp) {
                fatal("dnssec-policy '%s' has no keys configured", ksr->policy);
        }
        cfg_obj_detach(&config);
-       cfg_parser_destroy(&parser);
 }
 
 static int
index d7022be01bacecd9afc73b490d803e6fb3d9fe56..00006a8522f97a70d0e532719490b316fab20490 100644 (file)
@@ -363,89 +363,28 @@ remote-servers " DEFAULT_IANA_ROOT_ZONE_PRIMARIES " {\n\
 isc_result_t
 named_config_parsedefaults(cfg_obj_t **conf) {
        isc_buffer_t b;
-       cfg_parser_t *parser = NULL;
-       isc_result_t result;
-
-       result = cfg_parser_create(isc_g_mctx, &parser);
-       if (result != ISC_R_SUCCESS) {
-               return result;
-       }
 
        isc_buffer_init(&b, defaultconf, sizeof(defaultconf) - 1);
        isc_buffer_add(&b, sizeof(defaultconf) - 1);
-       result = cfg_parse_buffer(parser, &b, __FILE__, 0, &cfg_type_namedconf,
-                                 CFG_PCTX_NODEPRECATED | CFG_PCTX_NOOBSOLETE |
-                                         CFG_PCTX_NOEXPERIMENTAL,
-                                 conf);
-
-       cfg_parser_destroy(&parser);
-       return result;
-}
-
-/*
- * This function is called as soon as the 'directory' statement has been
- * parsed.  This can be extended to support other options if necessary.
- */
-static isc_result_t
-directory_callback(const char *clausename, const cfg_obj_t *obj, void *arg) {
-       isc_result_t result;
-       const char *directory;
-
-       REQUIRE(strcasecmp("directory", clausename) == 0);
-
-       UNUSED(arg);
-       UNUSED(clausename);
-
-       /*
-        * Change directory.
-        */
-       directory = cfg_obj_asstring(obj);
-
-       if (!isc_file_ischdiridempotent(directory)) {
-               cfg_obj_log(obj, ISC_LOG_WARNING,
-                           "option 'directory' contains relative path '%s'",
-                           directory);
-       }
-
-       if (!isc_file_isdirwritable(directory)) {
-               isc_log_write(NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_SERVER,
-                             ISC_LOG_ERROR, "directory '%s' is not writable",
-                             directory);
-               return ISC_R_NOPERM;
-       }
-
-       result = isc_dir_chdir(directory);
-       if (result != ISC_R_SUCCESS) {
-               cfg_obj_log(obj, ISC_LOG_ERROR,
-                           "change directory to '%s' failed: %s", directory,
-                           isc_result_totext(result));
-               return result;
-       }
-
-       char cwd[PATH_MAX];
-       if (getcwd(cwd, sizeof(cwd)) == cwd) {
-               isc_log_write(NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_SERVER,
-                             ISC_LOG_INFO, "the working directory is now '%s'",
-                             cwd);
-       }
-
-       return ISC_R_SUCCESS;
+       return cfg_parse_buffer(isc_g_mctx, &b, __FILE__, 0,
+                               &cfg_type_namedconf,
+                               CFG_PCTX_NODEPRECATED | CFG_PCTX_NOOBSOLETE |
+                                       CFG_PCTX_NOEXPERIMENTAL,
+                               conf);
 }
 
 isc_result_t
-named_config_parsefile(cfg_parser_t *parser, cfg_obj_t **conf) {
+named_config_parsefile(cfg_obj_t **conf) {
        isc_result_t result;
 
-       REQUIRE(parser);
        REQUIRE(conf && *conf == NULL);
 
        isc_log_write(NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_SERVER,
                      ISC_LOG_INFO, "parsing user configuration from '%s'",
                      named_g_conffile);
 
-       cfg_parser_setcallback(parser, directory_callback, NULL);
-       result = cfg_parse_file(parser, named_g_conffile, &cfg_type_namedconf,
-                               conf);
+       result = cfg_parse_file(isc_g_mctx, named_g_conffile,
+                               &cfg_type_namedconf, 0, conf);
        if (result != ISC_R_SUCCESS) {
                goto cleanup;
        }
index 0ae02c8891ed33f340a663da43cd2c19854475fc..0376d2b77094a876a49044e6c7474262ece8c57e 100644 (file)
@@ -787,7 +787,6 @@ register_keys(const cfg_obj_t *control, const cfg_obj_t *keylist,
 static isc_result_t
 get_rndckey(isc_mem_t *mctx, controlkeylist_t *keyids) {
        isc_result_t result;
-       cfg_parser_t *pctx = NULL;
        cfg_obj_t *config = NULL;
        const cfg_obj_t *key = NULL;
        const cfg_obj_t *algobj = NULL;
@@ -806,8 +805,7 @@ get_rndckey(isc_mem_t *mctx, controlkeylist_t *keyids) {
                return ISC_R_FILENOTFOUND;
        }
 
-       CHECK(cfg_parser_create(mctx, &pctx));
-       CHECK(cfg_parse_file(pctx, named_g_keyfile, &cfg_type_rndckey,
+       CHECK(cfg_parse_file(mctx, named_g_keyfile, &cfg_type_rndckey, 0,
                             &config));
        CHECK(cfg_map_get(config, "key", &key));
 
@@ -863,9 +861,6 @@ cleanup:
        if (config != NULL) {
                cfg_obj_detach(&config);
        }
-       if (pctx != NULL) {
-               cfg_parser_destroy(&pctx);
-       }
        return result;
 }
 
index 6b275727d4b976fa1fffe75a7060b81bdaf0c13f..3de19d73f8429126ba61aac5330ff05858e528b7 100644 (file)
@@ -28,7 +28,7 @@ isc_result_t
 named_config_parsedefaults(cfg_obj_t **conf);
 
 isc_result_t
-named_config_parsefile(cfg_parser_t *parser, cfg_obj_t **conf);
+named_config_parsefile(cfg_obj_t **conf);
 
 const char *
 named_config_getdefault(void);
index 5fdfedd08298c520a82e02a090299cfc70435381..989bcee49c11d5119a9f930320969f16f901ed39 100644 (file)
@@ -2349,7 +2349,6 @@ catz_addmodzone_cb(void *arg) {
        cfg_obj_t *zoneobj = NULL;
        ns_cfgctx_t *cfg = NULL;
        dns_zone_t *zone = NULL;
-       cfg_parser_t *parser = NULL;
 
        if (isc_loop_shuttingdown(isc_loop_get(isc_tid()))) {
                goto cleanup;
@@ -2464,10 +2463,8 @@ catz_addmodzone_cb(void *arg) {
        confbuf = NULL;
        result = dns_catz_generate_zonecfg(cz->origin, cz->entry, &confbuf);
        if (result == ISC_R_SUCCESS) {
-               CHECK(cfg_parser_create(cfg->mctx, &parser));
-               result = cfg_parse_buffer(parser, confbuf, "catz", 0,
+               result = cfg_parse_buffer(cfg->mctx, confbuf, "catz", 0,
                                          &cfg_type_addzoneconf, 0, &zoneconf);
-               cfg_parser_destroy(&parser);
                isc_buffer_free(&confbuf);
        }
        /*
@@ -2721,7 +2718,6 @@ catz_reconfigure(dns_catz_entry_t *entry, void *arg1, void *arg2) {
        ns_cfgctx_t *cfg = NULL;
        dns_zone_t *zone = NULL;
        isc_result_t result;
-       cfg_parser_t *parser = NULL;
 
        isc_buffer_init(&namebuf, nameb, DNS_NAME_FORMATSIZE);
        dns_name_totext(dns_catz_entry_getname(entry), DNS_NAME_OMITFINALDOT,
@@ -2745,10 +2741,8 @@ catz_reconfigure(dns_catz_entry_t *entry, void *arg1, void *arg2) {
 
        result = dns_catz_generate_zonecfg(data->catz, entry, &confbuf);
        if (result == ISC_R_SUCCESS) {
-               CHECK(cfg_parser_create(cfg->mctx, &parser));
-               result = cfg_parse_buffer(parser, confbuf, "catz", 0,
+               result = cfg_parse_buffer(cfg->mctx, confbuf, "catz", 0,
                                          &cfg_type_addzoneconf, 0, &zoneconf);
-               cfg_parser_destroy(&parser);
                isc_buffer_free(&confbuf);
        }
        /*
@@ -7558,7 +7552,6 @@ data_to_cfg(dns_view_t *view, MDB_val *key, MDB_val *data, isc_buffer_t **text,
        size_t zone_config_len;
        cfg_obj_t *zoneconf = NULL;
        char bufname[DNS_NAME_FORMATSIZE];
-       cfg_parser_t *parser = NULL;
 
        REQUIRE(view != NULL);
        REQUIRE(key != NULL);
@@ -7596,10 +7589,8 @@ data_to_cfg(dns_view_t *view, MDB_val *key, MDB_val *data, isc_buffer_t **text,
        snprintf(bufname, sizeof(bufname), "%.*s", (int)zone_name_len,
                 zone_name);
 
-       CHECK(cfg_parser_create(view->mctx, &parser));
-       result = cfg_parse_buffer(parser, *text, bufname, 0,
+       result = cfg_parse_buffer(view->mctx, *text, bufname, 0,
                                  &cfg_type_addzoneconf, 0, &zoneconf);
-       cfg_parser_destroy(&parser);
        if (result != ISC_R_SUCCESS) {
                isc_log_write(NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_SERVER,
                              ISC_LOG_ERROR,
@@ -9232,14 +9223,12 @@ cleanup_aclctx:
 static isc_result_t
 load_configuration(named_server_t *server, bool first_time) {
        isc_result_t result;
-       cfg_parser_t *parser = NULL;
        cfg_obj_t *config = NULL, *bindkeys = NULL;
 
        isc_log_write(NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_SERVER,
                      ISC_LOG_DEBUG(1), "load_configuration");
 
-       CHECK(cfg_parser_create(isc_g_mctx, &parser));
-       CHECK(named_config_parsefile(parser, &config));
+       CHECK(named_config_parsefile(&config));
 
        if (named_g_bindkeysfile != NULL) {
                /*
@@ -9255,9 +9244,9 @@ load_configuration(named_server_t *server, bool first_time) {
                                      "keys instead",
                                      named_g_bindkeysfile);
                } else {
-                       cfg_parser_reset(parser);
-                       result = cfg_parse_file(parser, named_g_bindkeysfile,
-                                               &cfg_type_bindkeys, &bindkeys);
+                       result = cfg_parse_file(
+                               isc_g_mctx, named_g_bindkeysfile,
+                               &cfg_type_bindkeys, 0, &bindkeys);
                        if (result != ISC_R_SUCCESS) {
                                isc_log_write(NAMED_LOGCATEGORY_GENERAL,
                                              NAMED_LOGMODULE_SERVER,
@@ -9274,9 +9263,6 @@ load_configuration(named_server_t *server, bool first_time) {
        result = apply_configuration(config, bindkeys, server, first_time);
 
 cleanup:
-       if (parser != NULL) {
-               cfg_parser_destroy(&parser);
-       }
        if (bindkeys != NULL) {
                cfg_obj_detach(&bindkeys);
        }
@@ -12466,9 +12452,8 @@ load_nzf(dns_view_t *view, ns_cfgctx_t *nzcfg) {
         * Parse the configuration in the NZF file.  This may be called in
         * multiple views, so we reset the parser each time.
         */
-       cfg_parser_reset(named_g_addparser);
-       result = cfg_parse_file(named_g_addparser, view->new_zone_file,
-                               &cfg_type_addzoneconf, &nzcfg->nzf_config);
+       result = cfg_parse_file(nzcfg->mctx, view->new_zone_file,
+                               &cfg_type_addzoneconf, 0, &nzcfg->nzf_config);
        if (result != ISC_R_SUCCESS) {
                isc_log_write(NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_SERVER,
                              ISC_LOG_ERROR, "Error parsing NZF file '%s': %s",
@@ -12816,7 +12801,6 @@ load_nzf(dns_view_t *view, ns_cfgctx_t *nzcfg) {
        MDB_dbi dbi;
        MDB_val key, data;
        ns_dzarg_t dzarg;
-       cfg_parser_t *parser = NULL;
 
        UNUSED(nzcfg);
 
@@ -12840,10 +12824,8 @@ load_nzf(dns_view_t *view, ns_cfgctx_t *nzcfg) {
         * config type, giving us a guarantee that valid configuration
         * will be written to DB.
         */
-       CHECK(cfg_parser_create(nzcfg->mctx, &parser));
-       result = cfg_parse_file(parser, view->new_zone_file,
-                               &cfg_type_addzoneconf, &nzf_config);
-       cfg_parser_destroy(&parser);
+       result = cfg_parse_file(nzcfg->mctx, view->new_zone_file,
+                               &cfg_type_addzoneconf, 0, &nzf_config);
        if (result != ISC_R_SUCCESS) {
                isc_log_write(NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_SERVER,
                              ISC_LOG_ERROR, "Error parsing NZF file '%s': %s",
@@ -12973,7 +12955,6 @@ newzone_parse(named_server_t *server, char *command, dns_view_t **viewp,
        dns_rdataclass_t rdclass;
        dns_view_t *view = NULL;
        const char *bn = NULL;
-       cfg_parser_t *parser = NULL;
 
        REQUIRE(viewp != NULL && *viewp == NULL);
        REQUIRE(zoneobjp != NULL && *zoneobjp == NULL);
@@ -12998,10 +12979,8 @@ newzone_parse(named_server_t *server, char *command, dns_view_t **viewp,
         */
        isc_buffer_forward(&argbuf, 3);
 
-       CHECK(cfg_parser_create(server->mctx, &parser));
-       CHECK(cfg_parse_buffer(parser, &argbuf, bn, 0, &cfg_type_addzoneconf, 0,
-                              &zoneconf));
-       cfg_parser_destroy(&parser);
+       CHECK(cfg_parse_buffer(server->mctx, &argbuf, bn, 0,
+                              &cfg_type_addzoneconf, 0, &zoneconf));
 
        CHECK(cfg_map_get(zoneconf, "zone", &zlist));
        if (!cfg_obj_islist(zlist)) {
@@ -13076,10 +13055,6 @@ newzone_parse(named_server_t *server, char *command, dns_view_t **viewp,
        return ISC_R_SUCCESS;
 
 cleanup:
-       if (parser != NULL) {
-               cfg_parser_destroy(&parser);
-       }
-
        if (zoneconf != NULL) {
                cfg_obj_detach(&zoneconf);
        }
@@ -13091,13 +13066,12 @@ cleanup:
 }
 
 static isc_result_t
-delete_zoneconf(dns_view_t *view, cfg_parser_t *pctx, const cfg_obj_t *config,
+delete_zoneconf(dns_view_t *view, const cfg_obj_t *config,
                const dns_name_t *zname, nzfwriter_t nzfwriter) {
        isc_result_t result = ISC_R_NOTFOUND;
        const cfg_obj_t *zl = NULL;
 
        REQUIRE(view != NULL);
-       REQUIRE(pctx != NULL);
        REQUIRE(config != NULL);
        REQUIRE(zname != NULL);
 
@@ -13126,7 +13100,6 @@ delete_zoneconf(dns_view_t *view, cfg_parser_t *pctx, const cfg_obj_t *config,
                e = UNCONST(elt);
                ISC_LIST_UNLINK(*list, e, link);
                cfg_obj_detach(&e->obj);
-               isc_mem_put(pctx->mctx, e, sizeof(*e));
                result = ISC_R_SUCCESS;
                break;
        }
@@ -13263,8 +13236,7 @@ do_addzone(named_server_t *server, ns_cfgctx_t *cfg, dns_view_t *view,
                cfg_obj_attach(zoneconf, &cfg->nzf_config);
        } else {
                cfg_obj_t *z = UNCONST(zoneobj);
-               CHECK(cfg_parser_mapadd(cfg->add_parser, cfg->nzf_config, z,
-                                       "zone"));
+               CHECK(cfg_parser_mapadd(cfg->nzf_config, z, "zone"));
        }
        cleanup_config = true;
 #endif /* HAVE_LMDB */
@@ -13313,8 +13285,7 @@ cleanup:
                (void)isc_stdio_close(fp);
        }
        if (result != ISC_R_SUCCESS && cleanup_config) {
-               tresult = delete_zoneconf(view, cfg->add_parser,
-                                         cfg->nzf_config, name, NULL);
+               tresult = delete_zoneconf(view, cfg->nzf_config, name, NULL);
                RUNTIME_CHECK(tresult == ISC_R_SUCCESS);
        }
 #else  /* HAVE_LMDB */
@@ -13341,7 +13312,6 @@ do_modzone(named_server_t *server, ns_cfgctx_t *cfg, dns_view_t *view,
        dns_zone_t *zone = NULL;
        const cfg_obj_t *voptions = NULL;
        bool added;
-       cfg_parser_t *parser = NULL;
 #ifndef HAVE_LMDB
        FILE *fp = NULL;
        cfg_obj_t *z;
@@ -13448,7 +13418,7 @@ do_modzone(named_server_t *server, ns_cfgctx_t *cfg, dns_view_t *view,
 #ifndef HAVE_LMDB
        /* Remove old zone from configuration (and NZF file if applicable) */
        if (added) {
-               result = delete_zoneconf(view, cfg->add_parser, cfg->nzf_config,
+               result = delete_zoneconf(view, cfg->nzf_config,
                                         dns_zone_getorigin(zone),
                                         nzf_writeconf);
                if (result != ISC_R_SUCCESS) {
@@ -13461,18 +13431,15 @@ do_modzone(named_server_t *server, ns_cfgctx_t *cfg, dns_view_t *view,
 #endif /* HAVE_LMDB */
 
        if (!added) {
-               TCHECK(cfg_parser_create(cfg->mctx, &parser));
                if (cfg->vconfig == NULL) {
-                       result = delete_zoneconf(view, parser, cfg->config,
+                       result = delete_zoneconf(view, cfg->config,
                                                 dns_zone_getorigin(zone),
                                                 NULL);
                } else {
                        voptions = cfg_tuple_get(cfg->vconfig, "options");
-                       result = delete_zoneconf(view, parser, voptions,
-                                                dns_zone_getorigin(zone),
-                                                NULL);
+                       result = delete_zoneconf(
+                               view, voptions, dns_zone_getorigin(zone), NULL);
                }
-               cfg_parser_destroy(&parser);
 
                if (result != ISC_R_SUCCESS) {
                        TCHECK(putstr(text, "former zone configuration "
@@ -13520,7 +13487,7 @@ do_modzone(named_server_t *server, ns_cfgctx_t *cfg, dns_view_t *view,
 #ifndef HAVE_LMDB
        /* Store the new zone configuration; also in NZF if applicable */
        z = UNCONST(zoneobj);
-       CHECK(cfg_parser_mapadd(cfg->add_parser, cfg->nzf_config, z, "zone"));
+       CHECK(cfg_parser_mapadd(cfg->nzf_config, z, "zone"));
 #endif /* HAVE_LMDB */
 
        if (added) {
@@ -13695,7 +13662,6 @@ rmzone(void *arg) {
        dns_db_t *dbp = NULL;
        bool added;
        isc_result_t result;
-       cfg_parser_t *parser = NULL;
 #ifdef HAVE_LMDB
        MDB_txn *txn = NULL;
        MDB_dbi dbi;
@@ -13746,7 +13712,7 @@ rmzone(void *arg) {
                }
                UNLOCK(&view->new_zone_lock);
 #else  /* ifdef HAVE_LMDB */
-               result = delete_zoneconf(view, cfg->add_parser, cfg->nzf_config,
+               result = delete_zoneconf(view, cfg->nzf_config,
                                         dns_zone_getorigin(zone),
                                         nzf_writeconf);
                if (result != ISC_R_SUCCESS) {
@@ -13759,24 +13725,17 @@ rmzone(void *arg) {
        }
 
        if (!added && cfg != NULL) {
-               result = cfg_parser_create(cfg->mctx, &parser);
-               INSIST(result == ISC_R_SUCCESS); /* colin: this is just a
-                                                   shortcut until the
-                                                   initialization function of
-                                                   the parser can't fails */
-
                if (cfg->vconfig != NULL) {
                        const cfg_obj_t *voptions = cfg_tuple_get(cfg->vconfig,
                                                                  "options");
-                       result = delete_zoneconf(view, parser, voptions,
-                                                dns_zone_getorigin(zone),
-                                                NULL);
+                       result = delete_zoneconf(
+                               view, voptions, dns_zone_getorigin(zone), NULL);
                } else {
-                       result = delete_zoneconf(view, parser, cfg->config,
+                       result = delete_zoneconf(view, cfg->config,
                                                 dns_zone_getorigin(zone),
                                                 NULL);
                }
-               cfg_parser_destroy(&parser);
+
                if (result != ISC_R_SUCCESS) {
                        isc_log_write(NAMED_LOGCATEGORY_GENERAL,
                                      NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
index 585dc80b91dd5363e9ad85827517b07c95662e1f..4ceff5646617fa7db4646101a84dcc0cb092d8c9 100644 (file)
@@ -555,7 +555,6 @@ failure:
  */
 static isc_result_t
 read_sessionkey(isc_mem_t *mctx) {
-       cfg_parser_t *pctx = NULL;
        cfg_obj_t *sessionkey = NULL;
        const cfg_obj_t *key = NULL;
        const cfg_obj_t *secretobj = NULL;
@@ -570,12 +569,7 @@ read_sessionkey(isc_mem_t *mctx) {
                return ISC_R_FILENOTFOUND;
        }
 
-       result = cfg_parser_create(mctx, &pctx);
-       if (result != ISC_R_SUCCESS) {
-               goto cleanup;
-       }
-
-       result = cfg_parse_file(pctx, keyfile, &cfg_type_sessionkey,
+       result = cfg_parse_file(mctx, keyfile, &cfg_type_sessionkey, 0,
                                &sessionkey);
        if (result != ISC_R_SUCCESS) {
                goto cleanup;
@@ -602,11 +596,8 @@ read_sessionkey(isc_mem_t *mctx) {
        setup_keystr();
 
 cleanup:
-       if (pctx != NULL) {
-               if (sessionkey != NULL) {
-                       cfg_obj_detach(&sessionkey);
-               }
-               cfg_parser_destroy(&pctx);
+       if (sessionkey != NULL) {
+               cfg_obj_detach(&sessionkey);
        }
 
        if (keystr != NULL) {
index 5d1cf06e524c6d102e37bc1baa90d71de690dc32..2d98b706921bbdd9914b3229adce57bb32204d9f 100644 (file)
@@ -274,16 +274,13 @@ parse_parameters(filter_instance_t *inst, const char *parameters,
                 const void *cfg, const char *cfg_file, unsigned long cfg_line,
                 isc_mem_t *mctx, void *aclctx) {
        isc_result_t result = ISC_R_SUCCESS;
-       cfg_parser_t *parser = NULL;
        cfg_obj_t *param_obj = NULL;
        const cfg_obj_t *obj = NULL;
        isc_buffer_t b;
 
-       CHECK(cfg_parser_create(mctx, &parser));
-
        isc_buffer_constinit(&b, parameters, strlen(parameters));
        isc_buffer_add(&b, strlen(parameters));
-       CHECK(cfg_parse_buffer(parser, &b, cfg_file, cfg_line,
+       CHECK(cfg_parse_buffer(mctx, &b, cfg_file, cfg_line,
                               &cfg_type_parameters, 0, &param_obj));
 
        CHECK(parse_filter_a_on(param_obj, "filter-a-on-v6", &inst->v6_a));
@@ -302,9 +299,6 @@ cleanup:
        if (param_obj != NULL) {
                cfg_obj_detach(&param_obj);
        }
-       if (parser != NULL) {
-               cfg_parser_destroy(&parser);
-       }
        return result;
 }
 
@@ -368,15 +362,12 @@ plugin_check(const char *parameters, const void *cfg, const char *cfg_file,
             unsigned long cfg_line, isc_mem_t *mctx, void *aclctx,
             const ns_pluginctx_t *ctx ISC_ATTR_UNUSED) {
        isc_result_t result = ISC_R_SUCCESS;
-       cfg_parser_t *parser = NULL;
        cfg_obj_t *param_obj = NULL;
        isc_buffer_t b;
 
-       CHECK(cfg_parser_create(mctx, &parser));
-
        isc_buffer_constinit(&b, parameters, strlen(parameters));
        isc_buffer_add(&b, strlen(parameters));
-       CHECK(cfg_parse_buffer(parser, &b, cfg_file, cfg_line,
+       CHECK(cfg_parse_buffer(mctx, &b, cfg_file, cfg_line,
                               &cfg_type_parameters, 0, &param_obj));
 
        CHECK(check_syntax(param_obj, cfg, mctx, aclctx));
@@ -385,9 +376,6 @@ cleanup:
        if (param_obj != NULL) {
                cfg_obj_detach(&param_obj);
        }
-       if (parser != NULL) {
-               cfg_parser_destroy(&parser);
-       }
        return result;
 }
 
index ad2ef52f3ac9e7c947e6c40f62aa0fa62bbab90f..dad917464cd4143c2ebb8afb53f465a14d651720 100644 (file)
@@ -275,16 +275,13 @@ parse_parameters(filter_instance_t *inst, const char *parameters,
                 const void *cfg, const char *cfg_file, unsigned long cfg_line,
                 isc_mem_t *mctx, void *aclctx) {
        isc_result_t result = ISC_R_SUCCESS;
-       cfg_parser_t *parser = NULL;
        cfg_obj_t *param_obj = NULL;
        const cfg_obj_t *obj = NULL;
        isc_buffer_t b;
 
-       CHECK(cfg_parser_create(mctx, &parser));
-
        isc_buffer_constinit(&b, parameters, strlen(parameters));
        isc_buffer_add(&b, strlen(parameters));
-       CHECK(cfg_parse_buffer(parser, &b, cfg_file, cfg_line,
+       CHECK(cfg_parse_buffer(mctx, &b, cfg_file, cfg_line,
                               &cfg_type_parameters, 0, &param_obj));
 
        CHECK(parse_filter_aaaa_on(param_obj, "filter-aaaa-on-v4",
@@ -305,9 +302,6 @@ cleanup:
        if (param_obj != NULL) {
                cfg_obj_detach(&param_obj);
        }
-       if (parser != NULL) {
-               cfg_parser_destroy(&parser);
-       }
        return result;
 }
 
@@ -372,15 +366,12 @@ plugin_check(const char *parameters, const void *cfg, const char *cfg_file,
             unsigned long cfg_line, isc_mem_t *mctx, void *aclctx,
             const ns_pluginctx_t *ctx ISC_ATTR_UNUSED) {
        isc_result_t result = ISC_R_SUCCESS;
-       cfg_parser_t *parser = NULL;
        cfg_obj_t *param_obj = NULL;
        isc_buffer_t b;
 
-       CHECK(cfg_parser_create(mctx, &parser));
-
        isc_buffer_constinit(&b, parameters, strlen(parameters));
        isc_buffer_add(&b, strlen(parameters));
-       CHECK(cfg_parse_buffer(parser, &b, cfg_file, cfg_line,
+       CHECK(cfg_parse_buffer(mctx, &b, cfg_file, cfg_line,
                               &cfg_type_parameters, 0, &param_obj));
 
        CHECK(check_syntax(param_obj, cfg, mctx, aclctx));
@@ -389,9 +380,6 @@ cleanup:
        if (param_obj != NULL) {
                cfg_obj_detach(&param_obj);
        }
-       if (parser != NULL) {
-               cfg_parser_destroy(&parser);
-       }
        return result;
 }
 
index 5c5f34bf8925419a4ad9be2768c0507c5e5df76b..1fab2a3a374486783045489a61965bd658071993 100644 (file)
@@ -573,16 +573,13 @@ synthrecord_parseconfig(synthrecord_t *inst, const char *parameters,
                        const dns_name_t *zname) {
        isc_result_t result;
        isc_mem_t *mctx = inst->mctx;
-       cfg_parser_t *parser = NULL;
        cfg_obj_t *synthrecordcfg = NULL;
        isc_buffer_t b;
 
-       CHECK(cfg_parser_create(mctx, &parser));
-
        isc_buffer_constinit(&b, parameters, strlen(parameters));
        isc_buffer_add(&b, strlen(parameters));
 
-       CHECK(cfg_parse_buffer(parser, &b, cfgfile, cfgline,
+       CHECK(cfg_parse_buffer(mctx, &b, cfgfile, cfgline,
                               &synthrecord_cfgparams, 0, &synthrecordcfg));
 
        synthrecord_setconfigmode(inst, zname);
@@ -596,10 +593,6 @@ cleanup:
                cfg_obj_detach(&synthrecordcfg);
        }
 
-       if (parser != NULL) {
-               cfg_parser_destroy(&parser);
-       }
-
        return result;
 }
 
index 3204e30a6367fb414f272816740987bb6de77842..46d0aa0c97cadd16588e0a7f242c9566dadab9f5 100644 (file)
@@ -535,8 +535,7 @@ rndc_start(void *arg) {
 }
 
 static void
-parse_config(isc_mem_t *mctx, const char *keyname, cfg_parser_t **pctxp,
-            cfg_obj_t **configp) {
+parse_config(isc_mem_t *mctx, const char *keyname, cfg_obj_t **configp) {
        isc_result_t result;
        const char *conffile = admin_conffile;
        const cfg_obj_t *addresses = NULL;
@@ -577,12 +576,10 @@ parse_config(isc_mem_t *mctx, const char *keyname, cfg_parser_t **pctxp,
                        admin_keyfile, admin_conffile);
        }
 
-       DO("create parser", cfg_parser_create(mctx, pctxp));
-
        /*
         * The parser will output its own errors, so DO() is not used.
         */
-       result = cfg_parse_file(*pctxp, conffile, conftype, &config);
+       result = cfg_parse_file(mctx, conffile, conftype, 0, &config);
        if (result != ISC_R_SUCCESS) {
                fatal("could not load rndc configuration");
        }
@@ -809,7 +806,6 @@ int
 main(int argc, char **argv) {
        bool show_final_mem = false;
        isc_logconfig_t *logconfig = NULL;
-       cfg_parser_t *pctx = NULL;
        cfg_obj_t *config = NULL;
        const char *keyname = NULL;
        struct in_addr in;
@@ -963,7 +959,7 @@ main(int argc, char **argv) {
                ISC_LOG_PRINTTAG | ISC_LOG_PRINTLEVEL, ISC_LOGCATEGORY_DEFAULT,
                ISC_LOGMODULE_DEFAULT);
 
-       parse_config(isc_g_mctx, keyname, &pctx, &config);
+       parse_config(isc_g_mctx, keyname, &config);
 
        isc_buffer_allocate(isc_g_mctx, &databuf, 2048);
 
@@ -1000,7 +996,6 @@ main(int argc, char **argv) {
        isccc_ccmsg_invalidate(&rndc_ccmsg);
 
        cfg_obj_detach(&config);
-       cfg_parser_destroy(&pctx);
 
        isc_mem_put(isc_g_mctx, args, argslen);
 
index efb781188b8862c962533d157022a20cd974b02a..aec7b136396b158b4eb06937d7bbc7c4d31b6967 100644 (file)
@@ -522,6 +522,7 @@ n=$((n + 1))
 echo_i "check that named-checkconf -l prints out the zone list ($n)"
 ret=0
 $CHECKCONF -l good.conf \
+  | grep -v "working directory is" \
   | grep -v "is deprecated" \
   | grep -v "is not implemented" \
   | grep -v "is not recommended" \
index 09856fd2ccf02d029d379311ba559c26a846ba0b..620829c8cc4c1404990119d44042c57518ce551a 100644 (file)
@@ -116,7 +116,6 @@ plugin_register(const char *parameters, const void *cfg, const char *cfgfile,
                ns_hooktable_t *hooktable, const ns_pluginctx_t *ctx,
                void **instp) {
        isc_result_t result;
-       cfg_parser_t *parser = NULL;
        cfg_obj_t *syncplugincfg = NULL;
        const cfg_obj_t *obj = NULL;
        isc_buffer_t b;
@@ -135,12 +134,10 @@ plugin_register(const char *parameters, const void *cfg, const char *cfgfile,
        *inst = (syncplugin_t){ .mctx = mctx };
        *instp = inst;
 
-       CHECK(cfg_parser_create(mctx, &parser));
-
        isc_buffer_constinit(&b, parameters, strlen(parameters));
        isc_buffer_add(&b, strlen(parameters));
 
-       CHECK(cfg_parse_buffer(parser, &b, cfgfile, cfgline,
+       CHECK(cfg_parse_buffer(mctx, &b, cfgfile, cfgline,
                               &syncplugin__cfgparams, 0, &syncplugincfg));
 
        CHECK(syncplugin__parse_rcode(syncplugincfg, &inst->rcode));
@@ -220,10 +217,6 @@ cleanup:
                cfg_obj_detach(&syncplugincfg);
        }
 
-       if (parser != NULL) {
-               cfg_parser_destroy(&parser);
-       }
-
        return result;
 }
 
index 60b28bc159342bc08a9f72dd3713ea38031ff586..f29600c2aa7f7ddeb2a54d424e68acddd3bcbdf0 100644 (file)
@@ -52,7 +52,6 @@ int
 main(int argc, char **argv) {
        isc_result_t result;
        isc_mem_t *mctx = NULL;
-       cfg_parser_t *pctx = NULL;
        cfg_obj_t *cfg = NULL;
        cfg_type_t *type = NULL;
        bool grammar = false;
@@ -134,9 +133,7 @@ main(int argc, char **argv) {
                if (type == NULL || filename == NULL) {
                        usage();
                }
-               RUNTIME_CHECK(cfg_parser_create(mctx, &pctx) == ISC_R_SUCCESS);
-
-               result = cfg_parse_file(pctx, filename, type, &cfg);
+               result = cfg_parse_file(mctx, filename, type, 0, &cfg);
 
                fprintf(stderr, "read config: %s\n", isc_result_totext(result));
 
@@ -147,8 +144,6 @@ main(int argc, char **argv) {
                cfg_print(cfg, output, NULL);
 
                cfg_obj_detach(&cfg);
-
-               cfg_parser_destroy(&pctx);
        }
 
        if (memstats) {
index 8e861655a50330d35809df40b7358407c16e2be6..b403fa7b28a9362f1ef678f9e235e5a0cf06f0cc 100644 (file)
@@ -113,25 +113,12 @@ cfg_parser_setflags(cfg_parser_t *pctx, unsigned int flags, bool turn_on);
  *\li  "pctx" is not NULL.
  */
 
-void
-cfg_parser_setcallback(cfg_parser_t *pctx, cfg_parsecallback_t callback,
-                      void *arg);
-/*%<
- * Make the parser call 'callback' whenever it encounters
- * a configuration clause with the callback attribute,
- * passing it the clause name, the clause value,
- * and 'arg' as arguments.
- *
- * To restore the default of not invoking callbacks, pass
- * callback==NULL and arg==NULL.
- */
-
 isc_result_t
-cfg_parse_file(cfg_parser_t *pctx, const char *file, const cfg_type_t *type,
-              cfg_obj_t **ret);
+cfg_parse_file(isc_mem_t *mctx, const char *file, const cfg_type_t *type,
+              unsigned int flags, cfg_obj_t **ret);
 
 isc_result_t
-cfg_parse_buffer(cfg_parser_t *pctx, isc_buffer_t *buffer, const char *file,
+cfg_parse_buffer(isc_mem_t *mctx, isc_buffer_t *buffer, const char *file,
                 unsigned int line, const cfg_type_t *type, unsigned int flags,
                 cfg_obj_t **ret);
 /*%<
@@ -152,8 +139,9 @@ cfg_parse_buffer(cfg_parser_t *pctx, isc_buffer_t *buffer, const char *file,
  * Returns an error if the file or buffer does not parse correctly.
  *
  * Requires:
- *\li  "filename" is valid.
- *\li  "mem" is valid.
+ *\li  "file" is valid.
+ *\li   "buffer" is valid.
+ *\li  "mctx" is valid.
  *\li  "type" is valid.
  *\li  "cfg" is non-NULL and "*cfg" is NULL.
  *\li   "flags" be one or more of CFG_PCTX_NODEPRECATED or zero.
@@ -165,8 +153,7 @@ cfg_parse_buffer(cfg_parser_t *pctx, isc_buffer_t *buffer, const char *file,
  */
 
 isc_result_t
-cfg_parser_mapadd(cfg_parser_t *pctx, cfg_obj_t *mapobj, cfg_obj_t *obj,
-                 const char *clause);
+cfg_parser_mapadd(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.
@@ -174,7 +161,6 @@ cfg_parser_mapadd(cfg_parser_t *pctx, cfg_obj_t *mapobj, cfg_obj_t *obj,
  * 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
index c06fedefb296884e3a070fabec42c8798f94f50d..8e84e31a37df37c49b8ebbea621cfe2f49e6a829 100644 (file)
@@ -47,11 +47,8 @@ enum {
        /*% Clause is obsolete (logs a warning, but is not a fatal error) */
        CFG_CLAUSEFLAG_OBSOLETE = 1 << 3,
 
-       /*%
-        * Clause needs to be interpreted during parsing by calling a
-        * callback function, like the "directory" option.
-        */
-       CFG_CLAUSEFLAG_CALLBACK = 1 << 4,
+       /*% Clause indicates it must change the current directory */
+       CFG_CLAUSEFLAG_CHDIR = 1 << 4,
 
        /*% Clause that is only used in testing. */
        CFG_CLAUSEFLAG_TESTONLY = 1 << 5,
@@ -266,9 +263,6 @@ struct cfg_parser {
 
        /*%< Reference counter */
        isc_refcount_t references;
-
-       cfg_parsecallback_t callback;
-       void               *callbackarg;
 };
 
 /* Parser context flags */
@@ -438,7 +432,8 @@ void
 cfg_doc_tuple(cfg_printer_t *pctx, const cfg_type_t *type);
 
 isc_result_t
-cfg_create_list(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **objp);
+cfg_create_list(isc_mem_t *mctx, cfg_obj_t *file, size_t line,
+               const cfg_type_t *type, cfg_obj_t **objp);
 
 isc_result_t
 cfg_parse_listelt(cfg_parser_t *pctx, const cfg_type_t *elttype,
index ce30d4b948cf6f8070c4bfba1689b0fea8b3bcc2..d13fd830f862ecd227fc1a541f4dbd9025b25ef4 100644 (file)
@@ -1232,7 +1232,7 @@ static cfg_clausedef_t options_clauses[] = {
        { "coresize", NULL, CFG_CLAUSEFLAG_ANCIENT },
        { "datasize", NULL, CFG_CLAUSEFLAG_ANCIENT },
        { "deallocate-on-exit", NULL, CFG_CLAUSEFLAG_ANCIENT },
-       { "directory", &cfg_type_qstring, CFG_CLAUSEFLAG_CALLBACK },
+       { "directory", &cfg_type_qstring, CFG_CLAUSEFLAG_CHDIR },
        { "dnsrps-library", &cfg_type_qstring, CFG_CLAUSEFLAG_OBSOLETE },
 #ifdef HAVE_DNSTAP
        { "dnstap-output", &cfg_type_dnstapoutput, CFG_CLAUSEFLAG_OPTIONAL },
index 822ccc83a20610e555400c0684cb949a3318147f..b2667a2629c1006006f43a4be576888cf7996855 100644 (file)
@@ -50,6 +50,7 @@
 #include <isc/buffer.h>
 #include <isc/dir.h>
 #include <isc/errno.h>
+#include <isc/file.h>
 #include <isc/formatcheck.h>
 #include <isc/lex.h>
 #include <isc/log.h>
@@ -114,7 +115,7 @@ static void
 free_list(cfg_obj_t *obj);
 
 static isc_result_t
-create_listelt(cfg_parser_t *pctx, cfg_listelt_t **eltp);
+create_listelt(isc_mem_t *mctx, cfg_listelt_t **eltp);
 
 static isc_result_t
 create_string(cfg_parser_t *pctx, const char *contents, const cfg_type_t *type,
@@ -542,8 +543,6 @@ cfg_parser_create(isc_mem_t *mctx, cfg_parser_t **ret) {
        pctx->open_files = NULL;
        pctx->closed_files = NULL;
        pctx->line = 0;
-       pctx->callback = NULL;
-       pctx->callbackarg = NULL;
        pctx->token.type = isc_tokentype_unknown;
        pctx->flags = 0;
        pctx->buf_name = NULL;
@@ -563,8 +562,12 @@ cfg_parser_create(isc_mem_t *mctx, cfg_parser_t **ret) {
                                                 ISC_LEXCOMMENT_CPLUSPLUS |
                                                 ISC_LEXCOMMENT_SHELL);
 
-       CHECK(cfg_create_list(pctx, &cfg_type_filelist, &pctx->open_files));
-       CHECK(cfg_create_list(pctx, &cfg_type_filelist, &pctx->closed_files));
+       CHECK(cfg_create_list(pctx->mctx, cfg_parser_currentfile(pctx),
+                             pctx->line, &cfg_type_filelist,
+                             &pctx->open_files));
+       CHECK(cfg_create_list(pctx->mctx, cfg_parser_currentfile(pctx),
+                             pctx->line, &cfg_type_filelist,
+                             &pctx->closed_files));
 
        *ret = pctx;
        return ISC_R_SUCCESS;
@@ -604,7 +607,7 @@ parser_openfile(cfg_parser_t *pctx, const char *filename) {
        }
 
        CHECK(create_string(pctx, filename, &cfg_type_qstring, &stringobj));
-       CHECK(create_listelt(pctx, &elt));
+       CHECK(create_listelt(pctx->mctx, &elt));
        elt->obj = stringobj;
        ISC_LIST_APPEND(pctx->open_files->value.list, elt, link);
 
@@ -614,15 +617,6 @@ cleanup:
        return result;
 }
 
-void
-cfg_parser_setcallback(cfg_parser_t *pctx, cfg_parsecallback_t callback,
-                      void *arg) {
-       REQUIRE(pctx != NULL);
-
-       pctx->callback = callback;
-       pctx->callbackarg = arg;
-}
-
 void
 cfg_parser_reset(cfg_parser_t *pctx) {
        REQUIRE(pctx != NULL);
@@ -674,16 +668,25 @@ cleanup:
        return result;
 }
 
+#define REQUIRE_PCTX_FLAGS(flags)                                        \
+       REQUIRE((flags & ~(CFG_PCTX_NODEPRECATED | CFG_PCTX_NOOBSOLETE | \
+                          CFG_PCTX_NOEXPERIMENTAL)) == 0)
+
 isc_result_t
-cfg_parse_file(cfg_parser_t *pctx, const char *filename, const cfg_type_t *type,
-              cfg_obj_t **ret) {
+cfg_parse_file(isc_mem_t *mctx, const char *filename, const cfg_type_t *type,
+              unsigned int flags, cfg_obj_t **ret) {
        isc_result_t result;
        cfg_listelt_t *elt;
+       cfg_parser_t *pctx = NULL;
 
-       REQUIRE(pctx != NULL);
+       REQUIRE(mctx != NULL);
        REQUIRE(filename != NULL);
        REQUIRE(type != NULL);
        REQUIRE(ret != NULL && *ret == NULL);
+       REQUIRE_PCTX_FLAGS(flags);
+
+       CHECK(cfg_parser_create(mctx, &pctx));
+       pctx->flags = flags;
 
        CHECK(parser_openfile(pctx, filename));
 
@@ -696,22 +699,27 @@ cfg_parse_file(cfg_parser_t *pctx, const char *filename, const cfg_type_t *type,
        ISC_LIST_APPEND(pctx->closed_files->value.list, elt, link);
 
 cleanup:
+       if (pctx != NULL) {
+               cfg_parser_destroy(&pctx);
+       }
+
        return result;
 }
 
 isc_result_t
-cfg_parse_buffer(cfg_parser_t *pctx, isc_buffer_t *buffer, const char *file,
+cfg_parse_buffer(isc_mem_t *mctx, isc_buffer_t *buffer, const char *file,
                 unsigned int line, const cfg_type_t *type, unsigned int flags,
                 cfg_obj_t **ret) {
        isc_result_t result;
+       cfg_parser_t *pctx = NULL;
 
-       REQUIRE(pctx != NULL);
+       REQUIRE(mctx != NULL);
        REQUIRE(type != NULL);
        REQUIRE(buffer != NULL);
        REQUIRE(ret != NULL && *ret == NULL);
-       REQUIRE((flags & ~(CFG_PCTX_NODEPRECATED | CFG_PCTX_NOOBSOLETE |
-                          CFG_PCTX_NOEXPERIMENTAL)) == 0);
+       REQUIRE_PCTX_FLAGS(flags);
 
+       CHECK(cfg_parser_create(mctx, &pctx));
        CHECK(isc_lex_openbuffer(pctx->lexer, buffer));
 
        pctx->buf_name = file;
@@ -725,6 +733,10 @@ cfg_parse_buffer(cfg_parser_t *pctx, isc_buffer_t *buffer, const char *file,
        pctx->buf_name = NULL;
 
 cleanup:
+       if (pctx != NULL) {
+               cfg_parser_destroy(&pctx);
+       }
+
        return result;
 }
 
@@ -1945,25 +1957,25 @@ cfg_type_t cfg_type_boolean = { "boolean",         cfg_parse_boolean,
  */
 
 isc_result_t
-cfg_create_list(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **obj) {
+cfg_create_list(isc_mem_t *mctx, cfg_obj_t *file, size_t line,
+               const cfg_type_t *type, cfg_obj_t **obj) {
        isc_result_t result;
 
-       REQUIRE(pctx != NULL);
+       REQUIRE(mctx != NULL);
        REQUIRE(type != NULL);
        REQUIRE(obj != NULL && *obj == NULL);
 
-       CHECK(cfg_create_obj(pctx->mctx, cfg_parser_currentfile(pctx),
-                            pctx->line, type, obj));
+       CHECK(cfg_create_obj(mctx, file, line, type, obj));
        ISC_LIST_INIT((*obj)->value.list);
 cleanup:
        return result;
 }
 
 static isc_result_t
-create_listelt(cfg_parser_t *pctx, cfg_listelt_t **eltp) {
+create_listelt(isc_mem_t *mctx, cfg_listelt_t **eltp) {
        cfg_listelt_t *elt;
 
-       elt = isc_mem_get(pctx->mctx, sizeof(*elt));
+       elt = isc_mem_get(mctx, sizeof(*elt));
        elt->obj = NULL;
        ISC_LINK_INIT(elt, link);
        *eltp = elt;
@@ -1996,7 +2008,7 @@ cfg_parse_listelt(cfg_parser_t *pctx, const cfg_type_t *elttype,
        REQUIRE(elttype != NULL);
        REQUIRE(ret != NULL && *ret == NULL);
 
-       CHECK(create_listelt(pctx, &elt));
+       CHECK(create_listelt(pctx->mctx, &elt));
 
        result = cfg_parse_obj(pctx, elttype, &value);
        if (result != ISC_R_SUCCESS) {
@@ -2024,7 +2036,8 @@ parse_list(cfg_parser_t *pctx, const cfg_type_t *listtype, cfg_obj_t **ret) {
        isc_result_t result;
        cfg_listelt_t *elt = NULL;
 
-       CHECK(cfg_create_list(pctx, listtype, &listobj));
+       CHECK(cfg_create_list(pctx->mctx, cfg_parser_currentfile(pctx),
+                             pctx->line, listtype, &listobj));
 
        for (;;) {
                CHECK(cfg_peektoken(pctx, 0));
@@ -2119,7 +2132,8 @@ cfg_parse_spacelist(cfg_parser_t *pctx, const cfg_type_t *listtype,
 
        listof = listtype->of;
 
-       CHECK(cfg_create_list(pctx, listtype, &listobj));
+       CHECK(cfg_create_list(pctx->mctx, cfg_parser_currentfile(pctx),
+                             pctx->line, listtype, &listobj));
 
        for (;;) {
                cfg_listelt_t *elt = NULL;
@@ -2386,8 +2400,9 @@ cfg_parse_mapbody(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
                        /* Multivalued clause */
                        cfg_obj_t *listobj = NULL;
 
-                       CHECK(cfg_create_list(pctx, &cfg_type_implicitlist,
-                                             &listobj));
+                       CHECK(cfg_create_list(
+                               pctx->mctx, cfg_parser_currentfile(pctx),
+                               pctx->line, &cfg_type_implicitlist, &listobj));
                        symval.as_pointer = listobj;
                        result = isc_symtab_define_and_return(
                                obj->value.map.symtab, clause->name,
@@ -2406,12 +2421,12 @@ cfg_parse_mapbody(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
                        ISC_LIST_APPEND(listobj->value.list, elt, link);
                } else {
                        /* Single-valued clause */
-                       bool callback = ((clause->flags &
-                                         CFG_CLAUSEFLAG_CALLBACK) != 0);
+                       bool chdir = ((clause->flags & CFG_CLAUSEFLAG_CHDIR) !=
+                                     0);
 
-                       result = parse_symtab_elt(
-                               pctx, clause->name, clause->type,
-                               obj->value.map.symtab, callback);
+                       result = parse_symtab_elt(pctx, clause->name,
+                                                 clause->type,
+                                                 obj->value.map.symtab, chdir);
                        if (result == ISC_R_EXISTS) {
                                cfg_parser_error(pctx, CFG_LOG_NEAR,
                                                 "'%s' redefined",
@@ -2437,17 +2452,60 @@ cleanup:
        return result;
 }
 
+static isc_result_t
+change_directory(const char *clausename, const cfg_obj_t *obj) {
+       isc_result_t result;
+       const char *directory;
+
+       REQUIRE(strcasecmp("directory", clausename) == 0);
+
+       UNUSED(clausename);
+
+       /*
+        * Change directory.
+        */
+       directory = cfg_obj_asstring(obj);
+
+       if (!isc_file_ischdiridempotent(directory)) {
+               cfg_obj_log(obj, ISC_LOG_WARNING,
+                           "option 'directory' contains relative path '%s'",
+                           directory);
+       }
+
+       if (!isc_file_isdirwritable(directory)) {
+               cfg_obj_log(obj, ISC_LOG_ERROR,
+                           "directory '%s' is not writable", directory);
+               return ISC_R_NOPERM;
+       }
+
+       result = isc_dir_chdir(directory);
+       if (result != ISC_R_SUCCESS) {
+               cfg_obj_log(obj, ISC_LOG_ERROR,
+                           "change directory to '%s' failed: %s", directory,
+                           isc_result_totext(result));
+               return result;
+       }
+
+       char cwd[PATH_MAX];
+       if (getcwd(cwd, sizeof(cwd)) == cwd) {
+               cfg_obj_log(obj, ISC_LOG_INFO,
+                           "the working directory is now '%s'", cwd);
+       }
+
+       return ISC_R_SUCCESS;
+}
+
 static isc_result_t
 parse_symtab_elt(cfg_parser_t *pctx, const char *name, cfg_type_t *elttype,
-                isc_symtab_t *symtab, bool callback) {
+                isc_symtab_t *symtab, bool chdir) {
        isc_result_t result;
        cfg_obj_t *obj = NULL;
        isc_symvalue_t symval;
 
        CHECK(cfg_parse_obj(pctx, elttype, &obj));
 
-       if (callback && pctx->callback != NULL) {
-               CHECK(pctx->callback(name, obj, pctx->callbackarg));
+       if (chdir) {
+               CHECK(change_directory(name, obj));
        }
 
        symval.as_pointer = obj;
@@ -2857,7 +2915,8 @@ parse_unsupported(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
        isc_result_t result;
        int braces = 0;
 
-       CHECK(cfg_create_list(pctx, type, &listobj));
+       CHECK(cfg_create_list(pctx->mctx, cfg_parser_currentfile(pctx),
+                             pctx->line, type, &listobj));
 
        for (;;) {
                cfg_listelt_t *elt = NULL;
@@ -3868,17 +3927,15 @@ cfg_print_grammar(const cfg_type_t *type, unsigned int flags,
 }
 
 isc_result_t
-cfg_parser_mapadd(cfg_parser_t *pctx, cfg_obj_t *mapobj, cfg_obj_t *obj,
-                 const char *clausename) {
+cfg_parser_mapadd(cfg_obj_t *mapobj, cfg_obj_t *obj, const char *clausename) {
        isc_result_t result = ISC_R_SUCCESS;
-       const cfg_map_t *map;
+       const cfg_map_t *map = NULL;
        isc_symvalue_t symval;
        cfg_obj_t *destobj = NULL;
        cfg_listelt_t *elt = NULL;
-       const cfg_clausedef_t *const *clauseset;
-       const cfg_clausedef_t *clause;
+       const cfg_clausedef_t *const *clauseset = NULL;
+       const cfg_clausedef_t *clause = NULL;
 
-       REQUIRE(pctx != NULL);
        REQUIRE(mapobj != NULL && mapobj->type->rep == &cfg_rep_map);
        REQUIRE(obj != NULL);
        REQUIRE(clausename != NULL);
@@ -3903,9 +3960,10 @@ breakout:
                                   &symval);
        if (result == ISC_R_NOTFOUND) {
                if ((clause->flags & CFG_CLAUSEFLAG_MULTI) != 0) {
-                       CHECK(cfg_create_list(pctx, &cfg_type_implicitlist,
+                       CHECK(cfg_create_list(mapobj->mctx, obj->file,
+                                             obj->line, &cfg_type_implicitlist,
                                              &destobj));
-                       CHECK(create_listelt(pctx, &elt));
+                       CHECK(create_listelt(mapobj->mctx, &elt));
                        cfg_obj_attach(obj, &elt->obj);
                        ISC_LIST_APPEND(destobj->value.list, elt, link);
                        symval.as_pointer = destobj;
@@ -3923,7 +3981,7 @@ breakout:
                INSIST(result == ISC_R_SUCCESS);
 
                if (destobj2->type == &cfg_type_implicitlist) {
-                       CHECK(create_listelt(pctx, &elt));
+                       CHECK(create_listelt(mapobj->mctx, &elt));
                        cfg_obj_attach(obj, &elt->obj);
                        ISC_LIST_APPEND(destobj2->value.list, elt, link);
                } else {
@@ -3936,7 +3994,7 @@ breakout:
 
 cleanup:
        if (elt != NULL) {
-               free_listelt(pctx->mctx, elt);
+               free_listelt(mapobj->mctx, elt);
        }
        CLEANUP_OBJ(destobj);
 
index 4454933a1cd06696371d41c875b458ad259d0f5e..a9cb1fd021d53833e36204463da2c0395a03c62b 100644 (file)
@@ -120,7 +120,6 @@ ISC_RUN_TEST_IMPL(duration) {
                            "T99999999999H99999999999M99999999999S" },
        };
        isc_buffer_t buf1;
-       cfg_parser_t *p1 = NULL;
        cfg_obj_t *c1 = NULL;
        bool must_fail = false;
 
@@ -144,14 +143,10 @@ ISC_RUN_TEST_IMPL(duration) {
                isc_buffer_add(&buf1, strlen(conf) - 1);
 
                /* Parse with default line numbering */
-               result = cfg_parser_create(isc_g_mctx, &p1);
-               assert_int_equal(result, ISC_R_SUCCESS);
-
-               result = cfg_parse_buffer(p1, &buf1, "text1", 0,
+               result = cfg_parse_buffer(isc_g_mctx, &buf1, "text1", 0,
                                          &cfg_type_namedconf, 0, &c1);
                if (must_fail) {
                        assert_int_equal(result, DNS_R_BADTTL);
-                       cfg_parser_destroy(&p1);
                        continue;
                }
                assert_int_equal(result, ISC_R_SUCCESS);
@@ -193,7 +188,6 @@ ISC_RUN_TEST_IMPL(duration) {
                }
 
                cfg_obj_detach(&c1);
-               cfg_parser_destroy(&p1);
        }
 }
 
index ac06a7e49aff0aba7cf8ab11e2c71af1e2dd2b70..88e4f00160e97cdcd5b601046ce506f337b5a34b 100644 (file)
@@ -124,16 +124,12 @@ static void
 test__query_source_print(const char *config, const char *expected) {
        isc_result_t result;
        isc_buffer_t buffer;
-       cfg_parser_t *parser = NULL;
        cfg_obj_t *output_conf = NULL;
 
-       result = cfg_parser_create(mctx, &parser);
-       assert_int_equal(result, ISC_R_SUCCESS);
-
        isc_buffer_constinit(&buffer, config, strlen(config));
        isc_buffer_add(&buffer, strlen(config));
 
-       result = cfg_parse_buffer(parser, &buffer, "text1", 0,
+       result = cfg_parse_buffer(isc_g_mctx, &buffer, "text1", 0,
                                  &cfg_type_namedconf, 0, &output_conf);
        assert_int_equal(result, ISC_R_SUCCESS);
        assert_non_null(output_conf);
@@ -144,9 +140,7 @@ test__query_source_print(const char *config, const char *expected) {
        output_conf->type->print(&pctx, output_conf);
        assert_text(expected);
 
-       cfg_obj_detach(parser, &output_conf);
-       cfg_parser_reset(parser);
-       cfg_parser_destroy(&parser);
+       cfg_obj_detach(&output_conf);
 }
 
 ISC_RUN_TEST_IMPL(query_source_print_none) {
index 16ca023f8613c9af7a25fd275ea1be73f24e54df..419986f595bc4ccb48aed5fe3d0df3fdcb5fe0dd 100644 (file)
@@ -11,6 +11,7 @@
 
 foreach unit : [
     'duration',
+    'grammar',
     'parser',
 ]
     test_bin = executable(
index 8ace4ea4f4071b6b8229bab6dc5d4423f18a6d4a..a08bf2abe666714a6d551687cfc52d5ac4af52c2 100644 (file)
@@ -60,7 +60,6 @@ append(void *arg, const char *str, int len) {
 ISC_RUN_TEST_IMPL(addzoneconf) {
        isc_result_t result;
        isc_buffer_t b;
-       cfg_parser_t *p = NULL;
        const char *tests[] = {
                "zone \"test4.baz\" { type primary; file \"e.db\"; };",
                "zone \"test/.baz\" { type primary; file \"e.db\"; };",
@@ -73,9 +72,6 @@ ISC_RUN_TEST_IMPL(addzoneconf) {
        char buf[1024];
 
        /* Parse with default line numbering */
-       result = cfg_parser_create(isc_g_mctx, &p);
-       assert_int_equal(result, ISC_R_SUCCESS);
-
        for (size_t i = 0; i < ARRAY_SIZE(tests); i++) {
                cfg_obj_t *conf = NULL;
                const cfg_obj_t *obj = NULL, *zlist = NULL;
@@ -83,7 +79,7 @@ ISC_RUN_TEST_IMPL(addzoneconf) {
                isc_buffer_constinit(&b, tests[i], strlen(tests[i]));
                isc_buffer_add(&b, strlen(tests[i]));
 
-               result = cfg_parse_buffer(p, &b, "text1", 0,
+               result = cfg_parse_buffer(isc_g_mctx, &b, "text1", 0,
                                          &cfg_type_namedconf, 0, &conf);
                assert_int_equal(result, ISC_R_SUCCESS);
 
@@ -103,49 +99,77 @@ ISC_RUN_TEST_IMPL(addzoneconf) {
                assert_string_equal(tests[i], buf);
 
                cfg_obj_detach(&conf);
-               cfg_parser_reset(p);
        }
-
-       cfg_parser_destroy(&p);
 }
 
 /* test cfg_parse_buffer() */
 ISC_RUN_TEST_IMPL(parse_buffer) {
        isc_result_t result;
-       unsigned char text[] = "options\n{\nrecursion yes;\n};\n";
-       isc_buffer_t buf1, buf2;
-       cfg_parser_t *p1 = NULL, *p2 = NULL;
-       cfg_obj_t *c1 = NULL, *c2 = NULL;
-
-       isc_buffer_init(&buf1, &text[0], sizeof(text) - 1);
-       isc_buffer_add(&buf1, sizeof(text) - 1);
-
-       /* Parse with default line numbering */
-       result = cfg_parser_create(isc_g_mctx, &p1);
-       assert_int_equal(result, ISC_R_SUCCESS);
-
-       result = cfg_parse_buffer(p1, &buf1, "text1", 0, &cfg_type_namedconf, 0,
-                                 &c1);
-       assert_int_equal(result, ISC_R_SUCCESS);
-       assert_int_equal(p1->line, 5);
-
-       isc_buffer_init(&buf2, &text[0], sizeof(text) - 1);
-       isc_buffer_add(&buf2, sizeof(text) - 1);
-
-       /* Parse with changed line number */
-       result = cfg_parser_create(isc_g_mctx, &p2);
-       assert_int_equal(result, ISC_R_SUCCESS);
-
-       result = cfg_parse_buffer(p2, &buf2, "text2", 100, &cfg_type_namedconf,
-                                 0, &c2);
-       assert_int_equal(result, ISC_R_SUCCESS);
-       assert_int_equal(p2->line, 104);
-
-       cfg_obj_detach(&c1);
-       cfg_obj_detach(&c2);
-
-       cfg_parser_destroy(&p1);
-       cfg_parser_destroy(&p2);
+       int fresult;
+       unsigned char text[] = "options\n{\nidonotexists yes;\n};\n";
+       char logfilebuf[512];
+       size_t logfilelen;
+       isc_buffer_t buf;
+       cfg_obj_t *c = NULL;
+
+       /*
+        * Redirect parser errors into a specific file for checking the output
+        * later.
+        */
+       constexpr char logfilename[] = "./cfglog.out";
+       FILE *logfile = fopen(logfilename, "w+");
+       assert_non_null(logfile);
+
+       isc_logdestination_t *logdest = ISC_LOGDESTINATION_FILE(logfile);
+       isc_logconfig_t *logconfig = isc_logconfig_get();
+       isc_log_createandusechannel(logconfig, "default_stderr",
+                                   ISC_LOG_TOFILEDESC, ISC_LOG_DYNAMIC,
+                                   logdest, 0, ISC_LOGCATEGORY_DEFAULT,
+                                   ISC_LOGMODULE_DEFAULT);
+
+       /* Parse with default line numbering. */
+       isc_buffer_init(&buf, &text[0], sizeof(text) - 1);
+       isc_buffer_add(&buf, sizeof(text) - 1);
+       result = cfg_parse_buffer(isc_g_mctx, &buf, "text1", 0,
+                                 &cfg_type_namedconf, 0, &c);
+       assert_int_equal(result, ISC_R_FAILURE);
+       assert_null(c);
+
+       /* Parse with changed line number. */
+       isc_buffer_first(&buf);
+       result = cfg_parse_buffer(isc_g_mctx, &buf, "text2", 100,
+                                 &cfg_type_namedconf, 0, &c);
+       assert_int_equal(result, ISC_R_FAILURE);
+       assert_null(c);
+
+       /* Parse with changed line number and no name. */
+       isc_buffer_first(&buf);
+       result = cfg_parse_buffer(isc_g_mctx, &buf, NULL, 100,
+                                 &cfg_type_namedconf, 0, &c);
+       assert_int_equal(result, ISC_R_FAILURE);
+       assert_null(c);
+
+       /* Check log values (and, specifically, line numbers). */
+       logfilelen = ftell(logfile);
+       assert_in_range(logfilelen, 0, sizeof(logfilebuf));
+
+       fresult = fseek(logfile, 0, SEEK_SET);
+       assert_int_equal(fresult, 0);
+
+       fresult = fread(logfilebuf, 1, logfilelen, logfile);
+       assert_int_equal(fresult, logfilelen);
+
+       logfilebuf[logfilelen] = 0;
+
+       assert_non_null(
+               strstr(logfilebuf, "text1:3: unknown option 'idonotexists'"));
+       assert_non_null(
+               strstr(logfilebuf, "text2:102: unknown option 'idonotexists'"));
+       assert_non_null(
+               strstr(logfilebuf, "none:102: unknown option 'idonotexists'"));
+
+       fclose(logfile);
+       remove(logfilename);
 }
 
 /* test cfg_map_firstclause() */