]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
- include: directive in config file accepts wildcards. Patch from
authorWouter Wijngaards <wouter@nlnetlabs.nl>
Thu, 27 Sep 2012 08:52:37 +0000 (08:52 +0000)
committerWouter Wijngaards <wouter@nlnetlabs.nl>
Thu, 27 Sep 2012 08:52:37 +0000 (08:52 +0000)
  Paul Wouters.  Suggested use: include: "/etc/unbound.d/conf.d/*"

git-svn-id: file:///svn/unbound/trunk@2765 be551aaa-1e26-0410-a405-d3ace91eadb9

doc/Changelog
doc/unbound.conf.5.in
util/config_file.c
util/configlexer.c
util/configlexer.lex

index 68b57f07b248eb368d975af056c49fe2177ca3e9..6317da9e051bc6f94e123cd2f15eb3b61410d24a 100644 (file)
@@ -1,3 +1,7 @@
+27 September 2012: Wouter
+       - include: directive in config file accepts wildcards.  Patch from
+         Paul Wouters.  Suggested use: include: "/etc/unbound.d/conf.d/*"
+
 21 September 2012: Wouter
        - chdir to / after chroot call (suggested by Camiel Dobbelaar).
 
index 627a848b1a0e21fde04c678f24049dbb470f5ac1..b9ce9170cf47328a367eb868179c06bd0d3cd8a4 100644 (file)
@@ -71,7 +71,7 @@ is followed by its containing attributes, or a value.
 .P
 Files can be included using the
 .B include:
-directive. It can appear anywhere, and takes a single filename as an argument.
+directive. It can appear anywhere, and accepts wildcards as an argument. 
 Processing continues as if the text from the included file was copied into
 the config file at that point.  If also using chroot, using full path names
 for the included files works, relative pathnames for the included names work
index 2f5e988cb7a4f537a5f2c5ab5b055620bde79468..dffbce6b935041c62dfdd763b8dc925e6ded4d0b 100644 (file)
 #include "util/regional.h"
 #include "util/fptr_wlist.h"
 #include "util/data/dname.h"
+#ifdef HAVE_GLOB_H
+# include <glob.h>
+#endif
+
 /** global config during parsing */
 struct config_parser_state* cfg_parser = 0;
 /** lex in file */
@@ -286,7 +290,7 @@ struct config_file* config_create_forlib(void)
        { return cfg_strlist_insert(&cfg->var, strdup(val)); }
 
 int config_set_option(struct config_file* cfg, const char* opt,
-        const char* val)
+       const char* val)
 {
        S_NUMBER_OR_ZERO("verbosity:", verbosity)
        else if(strcmp(opt, "statistics-interval:") == 0) {
@@ -458,7 +462,7 @@ void config_collate_func(char* line, void* arg)
 }
 
 int config_get_option_list(struct config_file* cfg, const char* opt,
-        struct config_strlist** list)
+       struct config_strlist** list)
 {
        struct config_collate_arg m;
        memset(&m, 0, sizeof(m));
@@ -687,8 +691,69 @@ config_read(struct config_file* cfg, const char* filename, const char* chroot)
 {
        FILE *in;
        char *fname = (char*)filename;
+#ifdef HAVE_GLOB
+       glob_t g;
+       size_t i;
+       int r, flags;
+#endif
        if(!fname)
                return 1;
+
+       /* check for wildcards */
+#ifdef HAVE_GLOB
+       if(!(!strchr(fname, '*') && !strchr(fname, '?') && !strchr(fname, '[') &&
+               !strchr(fname, '{') && !strchr(fname, '~'))) {
+               verbose(VERB_QUERY, "wildcard found, processing %s", fname);
+               flags = 0
+#ifdef GLOB_ERR
+                       | GLOB_ERR
+#endif
+#ifdef GLOB_NOSORT
+                       | GLOB_NOSORT
+#endif
+#ifdef GLOB_BRACE
+                       | GLOB_BRACE
+#endif
+#ifdef GLOB_TILDE
+                       | GLOB_TILDE
+#endif
+               ;
+               memset(&g, 0, sizeof(g));
+               r = glob(fname, flags, NULL, &g);
+               if(r) {
+                       /* some error */
+                       globfree(&g);
+                       if(r == GLOB_NOMATCH) {
+                               verbose(VERB_QUERY, "include: "
+                               "no matches for %s", fname);
+                               return 1; 
+                       } else if(r == GLOB_NOSPACE) {
+                               log_err("include: %s: "
+                                       "fnametern out of memory", fname);
+                       } else if(r == GLOB_ABORTED) {
+                               log_err("wildcard include: %s: expansion "
+                                       "aborted (%s)", fname, strerror(errno));
+                       } else {
+                               log_err("wildcard include: %s: expansion "
+                                       "failed (%s)", fname, strerror(errno));
+                       }
+                       /* ignore globs that yield no files */
+                       return 1;
+               }
+               /* process files found, if any */
+               for(i=0; i<(size_t)g.gl_pathc; i++) {
+                       if(!config_read(cfg, g.gl_pathv[i], chroot)) {
+                               log_err("error reading wildcard "
+                                       "include: %s", g.gl_pathv[i]);
+                               globfree(&g);
+                               return 0;
+                       }
+               }
+               globfree(&g);
+               return 1;
+       }
+#endif /* HAVE_GLOB */
+
        in = fopen(fname, "r");
        if(!in) {
                log_err("Could not open %s: %s", fname, strerror(errno));
@@ -1003,26 +1068,26 @@ cfg_convert_timeval(const char* str)
 int 
 cfg_count_numbers(const char* s)
 {
-        /* format ::= (sp num)+ sp      */
-        /* num ::= [-](0-9)+            */
-        /* sp ::= (space|tab)*          */
-        int num = 0;
-        while(*s) {
-                while(*s && isspace((int)*s))
-                        s++;
-                if(!*s) /* end of string */
-                        break;
-                if(*s == '-')
-                        s++;
-                if(!*s) /* only - not allowed */
-                        return 0;
-                if(!isdigit((int)*s)) /* bad character */
-                        return 0;
-                while(*s && isdigit((int)*s))
-                        s++;
-                num++;
-        }
-        return num;
+       /* format ::= (sp num)+ sp      */
+       /* num ::= [-](0-9)+        */
+       /* sp ::= (space|tab)*    */
+       int num = 0;
+       while(*s) {
+               while(*s && isspace((int)*s))
+                       s++;
+               if(!*s) /* end of string */
+                       break;
+               if(*s == '-')
+                       s++;
+               if(!*s) /* only - not allowed */
+                       return 0;
+               if(!isdigit((int)*s)) /* bad character */
+                       return 0;
+               while(*s && isdigit((int)*s))
+                       s++;
+               num++;
+       }
+       return num;
 }
 
 /** all digit number */
index 32eb81ec0afa4958c1ddadbc0914d82d8c992bd6..146ceb7e3dadd21f20d0283da183d40091ae0926 100644 (file)
@@ -1507,6 +1507,9 @@ char *yytext;
 #include <ctype.h>
 #include <string.h>
 #include <strings.h>
+#ifdef HAVE_GLOB_H
+# include <glob.h>
+#endif
 
 #include "util/config_file.h"
 #include "util/configparser.h"
@@ -1539,6 +1542,7 @@ static int config_include_stack_ptr = 0;
 static int inc_prev = 0;
 static int num_args = 0;
 
+
 static void config_start_include(const char* filename)
 {
        FILE *input;
@@ -1570,6 +1574,50 @@ static void config_start_include(const char* filename)
        ++config_include_stack_ptr;
 }
 
+static void config_start_include_glob(const char* filename)
+{
+
+       /* check for wildcards */
+#ifdef HAVE_GLOB
+       glob_t g;
+       size_t i;
+       int r, flags;
+       if(!(!strchr(filename, '*') && !strchr(filename, '?') && !strchr(filename, '[') &&
+               !strchr(filename, '{') && !strchr(filename, '~'))) {
+               flags = 0
+#ifdef GLOB_ERR
+                       | GLOB_ERR
+#endif
+#ifdef GLOB_NOSORT
+                       | GLOB_NOSORT
+#endif
+#ifdef GLOB_BRACE
+                       | GLOB_BRACE
+#endif
+#ifdef GLOB_TILDE
+                       | GLOB_TILDE
+#endif
+               ;
+               memset(&g, 0, sizeof(g));
+               r = glob(filename, flags, NULL, &g);
+               if(r) {
+                       /* some error */
+                       globfree(&g);
+                       config_start_include(filename); /* let original deal with it */
+                       return;
+               }
+               /* process files found, if any */
+               for(i=0; i<(size_t)g.gl_pathc; i++) {
+                       config_start_include(g.gl_pathv[i]);
+               }
+               globfree(&g);
+               return;
+       }
+#endif /* HAVE_GLOB */
+
+       config_start_include(filename);
+}
+
 static void config_end_include(void)
 {
        --config_include_stack_ptr;
@@ -1590,7 +1638,7 @@ static void config_end_include(void)
 #endif
 
 #define YY_NO_INPUT 1
-#line 100 "./util/configlexer.lex"
+#line 148 "./util/configlexer.lex"
 #ifndef YY_NO_UNPUT
 #define YY_NO_UNPUT 1
 #endif
@@ -1598,7 +1646,7 @@ static void config_end_include(void)
 #define YY_NO_INPUT 1
 #endif
 
-#line 1600 "<stdout>"
+#line 1648 "<stdout>"
 
 #define INITIAL 0
 #define quotedstring 1
@@ -1783,9 +1831,9 @@ YY_DECL
        register char *yy_cp, *yy_bp;
        register int yy_act;
     
-#line 120 "./util/configlexer.lex"
+#line 168 "./util/configlexer.lex"
 
-#line 1787 "<stdout>"
+#line 1835 "<stdout>"
 
        if ( !(yy_init) )
                {
@@ -1876,627 +1924,627 @@ do_action:    /* This label is used only to access EOF actions. */
 
 case 1:
 YY_RULE_SETUP
-#line 121 "./util/configlexer.lex"
+#line 169 "./util/configlexer.lex"
 { 
        LEXOUT(("SP ")); /* ignore */ }
        YY_BREAK
 case 2:
 YY_RULE_SETUP
-#line 123 "./util/configlexer.lex"
+#line 171 "./util/configlexer.lex"
 { 
        /* note that flex makes the longest match and '.' is any but not nl */
        LEXOUT(("comment(%s) ", yytext)); /* ignore */ }
        YY_BREAK
 case 3:
 YY_RULE_SETUP
-#line 126 "./util/configlexer.lex"
+#line 174 "./util/configlexer.lex"
 { YDVAR(0, VAR_SERVER) }
        YY_BREAK
 case 4:
 YY_RULE_SETUP
-#line 127 "./util/configlexer.lex"
+#line 175 "./util/configlexer.lex"
 { YDVAR(1, VAR_NUM_THREADS) }
        YY_BREAK
 case 5:
 YY_RULE_SETUP
-#line 128 "./util/configlexer.lex"
+#line 176 "./util/configlexer.lex"
 { YDVAR(1, VAR_VERBOSITY) }
        YY_BREAK
 case 6:
 YY_RULE_SETUP
-#line 129 "./util/configlexer.lex"
+#line 177 "./util/configlexer.lex"
 { YDVAR(1, VAR_PORT) }
        YY_BREAK
 case 7:
 YY_RULE_SETUP
-#line 130 "./util/configlexer.lex"
+#line 178 "./util/configlexer.lex"
 { YDVAR(1, VAR_OUTGOING_RANGE) }
        YY_BREAK
 case 8:
 YY_RULE_SETUP
-#line 131 "./util/configlexer.lex"
+#line 179 "./util/configlexer.lex"
 { YDVAR(1, VAR_OUTGOING_PORT_PERMIT) }
        YY_BREAK
 case 9:
 YY_RULE_SETUP
-#line 132 "./util/configlexer.lex"
+#line 180 "./util/configlexer.lex"
 { YDVAR(1, VAR_OUTGOING_PORT_AVOID) }
        YY_BREAK
 case 10:
 YY_RULE_SETUP
-#line 133 "./util/configlexer.lex"
+#line 181 "./util/configlexer.lex"
 { YDVAR(1, VAR_OUTGOING_NUM_TCP) }
        YY_BREAK
 case 11:
 YY_RULE_SETUP
-#line 134 "./util/configlexer.lex"
+#line 182 "./util/configlexer.lex"
 { YDVAR(1, VAR_INCOMING_NUM_TCP) }
        YY_BREAK
 case 12:
 YY_RULE_SETUP
-#line 135 "./util/configlexer.lex"
+#line 183 "./util/configlexer.lex"
 { YDVAR(1, VAR_DO_IP4) }
        YY_BREAK
 case 13:
 YY_RULE_SETUP
-#line 136 "./util/configlexer.lex"
+#line 184 "./util/configlexer.lex"
 { YDVAR(1, VAR_DO_IP6) }
        YY_BREAK
 case 14:
 YY_RULE_SETUP
-#line 137 "./util/configlexer.lex"
+#line 185 "./util/configlexer.lex"
 { YDVAR(1, VAR_DO_UDP) }
        YY_BREAK
 case 15:
 YY_RULE_SETUP
-#line 138 "./util/configlexer.lex"
+#line 186 "./util/configlexer.lex"
 { YDVAR(1, VAR_DO_TCP) }
        YY_BREAK
 case 16:
 YY_RULE_SETUP
-#line 139 "./util/configlexer.lex"
+#line 187 "./util/configlexer.lex"
 { YDVAR(1, VAR_TCP_UPSTREAM) }
        YY_BREAK
 case 17:
 YY_RULE_SETUP
-#line 140 "./util/configlexer.lex"
+#line 188 "./util/configlexer.lex"
 { YDVAR(1, VAR_SSL_UPSTREAM) }
        YY_BREAK
 case 18:
 YY_RULE_SETUP
-#line 141 "./util/configlexer.lex"
+#line 189 "./util/configlexer.lex"
 { YDVAR(1, VAR_SSL_SERVICE_KEY) }
        YY_BREAK
 case 19:
 YY_RULE_SETUP
-#line 142 "./util/configlexer.lex"
+#line 190 "./util/configlexer.lex"
 { YDVAR(1, VAR_SSL_SERVICE_PEM) }
        YY_BREAK
 case 20:
 YY_RULE_SETUP
-#line 143 "./util/configlexer.lex"
+#line 191 "./util/configlexer.lex"
 { YDVAR(1, VAR_SSL_PORT) }
        YY_BREAK
 case 21:
 YY_RULE_SETUP
-#line 144 "./util/configlexer.lex"
+#line 192 "./util/configlexer.lex"
 { YDVAR(1, VAR_DO_DAEMONIZE) }
        YY_BREAK
 case 22:
 YY_RULE_SETUP
-#line 145 "./util/configlexer.lex"
+#line 193 "./util/configlexer.lex"
 { YDVAR(1, VAR_INTERFACE) }
        YY_BREAK
 case 23:
 YY_RULE_SETUP
-#line 146 "./util/configlexer.lex"
+#line 194 "./util/configlexer.lex"
 { YDVAR(1, VAR_OUTGOING_INTERFACE) }
        YY_BREAK
 case 24:
 YY_RULE_SETUP
-#line 147 "./util/configlexer.lex"
+#line 195 "./util/configlexer.lex"
 { YDVAR(1, VAR_INTERFACE_AUTOMATIC) }
        YY_BREAK
 case 25:
 YY_RULE_SETUP
-#line 148 "./util/configlexer.lex"
+#line 196 "./util/configlexer.lex"
 { YDVAR(1, VAR_SO_RCVBUF) }
        YY_BREAK
 case 26:
 YY_RULE_SETUP
-#line 149 "./util/configlexer.lex"
+#line 197 "./util/configlexer.lex"
 { YDVAR(1, VAR_SO_SNDBUF) }
        YY_BREAK
 case 27:
 YY_RULE_SETUP
-#line 150 "./util/configlexer.lex"
+#line 198 "./util/configlexer.lex"
 { YDVAR(1, VAR_CHROOT) }
        YY_BREAK
 case 28:
 YY_RULE_SETUP
-#line 151 "./util/configlexer.lex"
+#line 199 "./util/configlexer.lex"
 { YDVAR(1, VAR_USERNAME) }
        YY_BREAK
 case 29:
 YY_RULE_SETUP
-#line 152 "./util/configlexer.lex"
+#line 200 "./util/configlexer.lex"
 { YDVAR(1, VAR_DIRECTORY) }
        YY_BREAK
 case 30:
 YY_RULE_SETUP
-#line 153 "./util/configlexer.lex"
+#line 201 "./util/configlexer.lex"
 { YDVAR(1, VAR_LOGFILE) }
        YY_BREAK
 case 31:
 YY_RULE_SETUP
-#line 154 "./util/configlexer.lex"
+#line 202 "./util/configlexer.lex"
 { YDVAR(1, VAR_PIDFILE) }
        YY_BREAK
 case 32:
 YY_RULE_SETUP
-#line 155 "./util/configlexer.lex"
+#line 203 "./util/configlexer.lex"
 { YDVAR(1, VAR_ROOT_HINTS) }
        YY_BREAK
 case 33:
 YY_RULE_SETUP
-#line 156 "./util/configlexer.lex"
+#line 204 "./util/configlexer.lex"
 { YDVAR(1, VAR_EDNS_BUFFER_SIZE) }
        YY_BREAK
 case 34:
 YY_RULE_SETUP
-#line 157 "./util/configlexer.lex"
+#line 205 "./util/configlexer.lex"
 { YDVAR(1, VAR_MSG_BUFFER_SIZE) }
        YY_BREAK
 case 35:
 YY_RULE_SETUP
-#line 158 "./util/configlexer.lex"
+#line 206 "./util/configlexer.lex"
 { YDVAR(1, VAR_MSG_CACHE_SIZE) }
        YY_BREAK
 case 36:
 YY_RULE_SETUP
-#line 159 "./util/configlexer.lex"
+#line 207 "./util/configlexer.lex"
 { YDVAR(1, VAR_MSG_CACHE_SLABS) }
        YY_BREAK
 case 37:
 YY_RULE_SETUP
-#line 160 "./util/configlexer.lex"
+#line 208 "./util/configlexer.lex"
 { YDVAR(1, VAR_RRSET_CACHE_SIZE) }
        YY_BREAK
 case 38:
 YY_RULE_SETUP
-#line 161 "./util/configlexer.lex"
+#line 209 "./util/configlexer.lex"
 { YDVAR(1, VAR_RRSET_CACHE_SLABS) }
        YY_BREAK
 case 39:
 YY_RULE_SETUP
-#line 162 "./util/configlexer.lex"
+#line 210 "./util/configlexer.lex"
 { YDVAR(1, VAR_CACHE_MAX_TTL) }
        YY_BREAK
 case 40:
 YY_RULE_SETUP
-#line 163 "./util/configlexer.lex"
+#line 211 "./util/configlexer.lex"
 { YDVAR(1, VAR_CACHE_MIN_TTL) }
        YY_BREAK
 case 41:
 YY_RULE_SETUP
-#line 164 "./util/configlexer.lex"
+#line 212 "./util/configlexer.lex"
 { YDVAR(1, VAR_INFRA_HOST_TTL) }
        YY_BREAK
 case 42:
 YY_RULE_SETUP
-#line 165 "./util/configlexer.lex"
+#line 213 "./util/configlexer.lex"
 { YDVAR(1, VAR_INFRA_LAME_TTL) }
        YY_BREAK
 case 43:
 YY_RULE_SETUP
-#line 166 "./util/configlexer.lex"
+#line 214 "./util/configlexer.lex"
 { YDVAR(1, VAR_INFRA_CACHE_SLABS) }
        YY_BREAK
 case 44:
 YY_RULE_SETUP
-#line 167 "./util/configlexer.lex"
+#line 215 "./util/configlexer.lex"
 { YDVAR(1, VAR_INFRA_CACHE_NUMHOSTS) }
        YY_BREAK
 case 45:
 YY_RULE_SETUP
-#line 168 "./util/configlexer.lex"
+#line 216 "./util/configlexer.lex"
 { YDVAR(1, VAR_INFRA_CACHE_LAME_SIZE) }
        YY_BREAK
 case 46:
 YY_RULE_SETUP
-#line 169 "./util/configlexer.lex"
+#line 217 "./util/configlexer.lex"
 { YDVAR(1, VAR_NUM_QUERIES_PER_THREAD) }
        YY_BREAK
 case 47:
 YY_RULE_SETUP
-#line 170 "./util/configlexer.lex"
+#line 218 "./util/configlexer.lex"
 { YDVAR(1, VAR_JOSTLE_TIMEOUT) }
        YY_BREAK
 case 48:
 YY_RULE_SETUP
-#line 171 "./util/configlexer.lex"
+#line 219 "./util/configlexer.lex"
 { YDVAR(1, VAR_TARGET_FETCH_POLICY) }
        YY_BREAK
 case 49:
 YY_RULE_SETUP
-#line 172 "./util/configlexer.lex"
+#line 220 "./util/configlexer.lex"
 { YDVAR(1, VAR_HARDEN_SHORT_BUFSIZE) }
        YY_BREAK
 case 50:
 YY_RULE_SETUP
-#line 173 "./util/configlexer.lex"
+#line 221 "./util/configlexer.lex"
 { YDVAR(1, VAR_HARDEN_LARGE_QUERIES) }
        YY_BREAK
 case 51:
 YY_RULE_SETUP
-#line 174 "./util/configlexer.lex"
+#line 222 "./util/configlexer.lex"
 { YDVAR(1, VAR_HARDEN_GLUE) }
        YY_BREAK
 case 52:
 YY_RULE_SETUP
-#line 175 "./util/configlexer.lex"
+#line 223 "./util/configlexer.lex"
 { YDVAR(1, VAR_HARDEN_DNSSEC_STRIPPED) }
        YY_BREAK
 case 53:
 YY_RULE_SETUP
-#line 176 "./util/configlexer.lex"
+#line 224 "./util/configlexer.lex"
 { YDVAR(1, VAR_HARDEN_BELOW_NXDOMAIN) }
        YY_BREAK
 case 54:
 YY_RULE_SETUP
-#line 177 "./util/configlexer.lex"
+#line 225 "./util/configlexer.lex"
 { YDVAR(1, VAR_HARDEN_REFERRAL_PATH) }
        YY_BREAK
 case 55:
 YY_RULE_SETUP
-#line 178 "./util/configlexer.lex"
+#line 226 "./util/configlexer.lex"
 { YDVAR(1, VAR_USE_CAPS_FOR_ID) }
        YY_BREAK
 case 56:
 YY_RULE_SETUP
-#line 179 "./util/configlexer.lex"
+#line 227 "./util/configlexer.lex"
 { YDVAR(1, VAR_UNWANTED_REPLY_THRESHOLD) }
        YY_BREAK
 case 57:
 YY_RULE_SETUP
-#line 180 "./util/configlexer.lex"
+#line 228 "./util/configlexer.lex"
 { YDVAR(1, VAR_PRIVATE_ADDRESS) }
        YY_BREAK
 case 58:
 YY_RULE_SETUP
-#line 181 "./util/configlexer.lex"
+#line 229 "./util/configlexer.lex"
 { YDVAR(1, VAR_PRIVATE_DOMAIN) }
        YY_BREAK
 case 59:
 YY_RULE_SETUP
-#line 182 "./util/configlexer.lex"
+#line 230 "./util/configlexer.lex"
 { YDVAR(1, VAR_PREFETCH_KEY) }
        YY_BREAK
 case 60:
 YY_RULE_SETUP
-#line 183 "./util/configlexer.lex"
+#line 231 "./util/configlexer.lex"
 { YDVAR(1, VAR_PREFETCH) }
        YY_BREAK
 case 61:
 YY_RULE_SETUP
-#line 184 "./util/configlexer.lex"
+#line 232 "./util/configlexer.lex"
 { YDVAR(0, VAR_STUB_ZONE) }
        YY_BREAK
 case 62:
 YY_RULE_SETUP
-#line 185 "./util/configlexer.lex"
+#line 233 "./util/configlexer.lex"
 { YDVAR(1, VAR_NAME) }
        YY_BREAK
 case 63:
 YY_RULE_SETUP
-#line 186 "./util/configlexer.lex"
+#line 234 "./util/configlexer.lex"
 { YDVAR(1, VAR_STUB_ADDR) }
        YY_BREAK
 case 64:
 YY_RULE_SETUP
-#line 187 "./util/configlexer.lex"
+#line 235 "./util/configlexer.lex"
 { YDVAR(1, VAR_STUB_HOST) }
        YY_BREAK
 case 65:
 YY_RULE_SETUP
-#line 188 "./util/configlexer.lex"
+#line 236 "./util/configlexer.lex"
 { YDVAR(1, VAR_STUB_PRIME) }
        YY_BREAK
 case 66:
 YY_RULE_SETUP
-#line 189 "./util/configlexer.lex"
+#line 237 "./util/configlexer.lex"
 { YDVAR(1, VAR_STUB_FIRST) }
        YY_BREAK
 case 67:
 YY_RULE_SETUP
-#line 190 "./util/configlexer.lex"
+#line 238 "./util/configlexer.lex"
 { YDVAR(0, VAR_FORWARD_ZONE) }
        YY_BREAK
 case 68:
 YY_RULE_SETUP
-#line 191 "./util/configlexer.lex"
+#line 239 "./util/configlexer.lex"
 { YDVAR(1, VAR_FORWARD_ADDR) }
        YY_BREAK
 case 69:
 YY_RULE_SETUP
-#line 192 "./util/configlexer.lex"
+#line 240 "./util/configlexer.lex"
 { YDVAR(1, VAR_FORWARD_HOST) }
        YY_BREAK
 case 70:
 YY_RULE_SETUP
-#line 193 "./util/configlexer.lex"
+#line 241 "./util/configlexer.lex"
 { YDVAR(1, VAR_FORWARD_FIRST) }
        YY_BREAK
 case 71:
 YY_RULE_SETUP
-#line 194 "./util/configlexer.lex"
+#line 242 "./util/configlexer.lex"
 { YDVAR(1, VAR_DO_NOT_QUERY_ADDRESS) }
        YY_BREAK
 case 72:
 YY_RULE_SETUP
-#line 195 "./util/configlexer.lex"
+#line 243 "./util/configlexer.lex"
 { YDVAR(1, VAR_DO_NOT_QUERY_LOCALHOST) }
        YY_BREAK
 case 73:
 YY_RULE_SETUP
-#line 196 "./util/configlexer.lex"
+#line 244 "./util/configlexer.lex"
 { YDVAR(2, VAR_ACCESS_CONTROL) }
        YY_BREAK
 case 74:
 YY_RULE_SETUP
-#line 197 "./util/configlexer.lex"
+#line 245 "./util/configlexer.lex"
 { YDVAR(1, VAR_HIDE_IDENTITY) }
        YY_BREAK
 case 75:
 YY_RULE_SETUP
-#line 198 "./util/configlexer.lex"
+#line 246 "./util/configlexer.lex"
 { YDVAR(1, VAR_HIDE_VERSION) }
        YY_BREAK
 case 76:
 YY_RULE_SETUP
-#line 199 "./util/configlexer.lex"
+#line 247 "./util/configlexer.lex"
 { YDVAR(1, VAR_IDENTITY) }
        YY_BREAK
 case 77:
 YY_RULE_SETUP
-#line 200 "./util/configlexer.lex"
+#line 248 "./util/configlexer.lex"
 { YDVAR(1, VAR_VERSION) }
        YY_BREAK
 case 78:
 YY_RULE_SETUP
-#line 201 "./util/configlexer.lex"
+#line 249 "./util/configlexer.lex"
 { YDVAR(1, VAR_MODULE_CONF) }
        YY_BREAK
 case 79:
 YY_RULE_SETUP
-#line 202 "./util/configlexer.lex"
+#line 250 "./util/configlexer.lex"
 { YDVAR(1, VAR_DLV_ANCHOR) }
        YY_BREAK
 case 80:
 YY_RULE_SETUP
-#line 203 "./util/configlexer.lex"
+#line 251 "./util/configlexer.lex"
 { YDVAR(1, VAR_DLV_ANCHOR_FILE) }
        YY_BREAK
 case 81:
 YY_RULE_SETUP
-#line 204 "./util/configlexer.lex"
+#line 252 "./util/configlexer.lex"
 { YDVAR(1, VAR_TRUST_ANCHOR_FILE) }
        YY_BREAK
 case 82:
 YY_RULE_SETUP
-#line 205 "./util/configlexer.lex"
+#line 253 "./util/configlexer.lex"
 { YDVAR(1, VAR_AUTO_TRUST_ANCHOR_FILE) }
        YY_BREAK
 case 83:
 YY_RULE_SETUP
-#line 206 "./util/configlexer.lex"
+#line 254 "./util/configlexer.lex"
 { YDVAR(1, VAR_TRUSTED_KEYS_FILE) }
        YY_BREAK
 case 84:
 YY_RULE_SETUP
-#line 207 "./util/configlexer.lex"
+#line 255 "./util/configlexer.lex"
 { YDVAR(1, VAR_TRUST_ANCHOR) }
        YY_BREAK
 case 85:
 YY_RULE_SETUP
-#line 208 "./util/configlexer.lex"
+#line 256 "./util/configlexer.lex"
 { YDVAR(1, VAR_VAL_OVERRIDE_DATE) }
        YY_BREAK
 case 86:
 YY_RULE_SETUP
-#line 209 "./util/configlexer.lex"
+#line 257 "./util/configlexer.lex"
 { YDVAR(1, VAR_VAL_SIG_SKEW_MIN) }
        YY_BREAK
 case 87:
 YY_RULE_SETUP
-#line 210 "./util/configlexer.lex"
+#line 258 "./util/configlexer.lex"
 { YDVAR(1, VAR_VAL_SIG_SKEW_MAX) }
        YY_BREAK
 case 88:
 YY_RULE_SETUP
-#line 211 "./util/configlexer.lex"
+#line 259 "./util/configlexer.lex"
 { YDVAR(1, VAR_BOGUS_TTL) }
        YY_BREAK
 case 89:
 YY_RULE_SETUP
-#line 212 "./util/configlexer.lex"
+#line 260 "./util/configlexer.lex"
 { YDVAR(1, VAR_VAL_CLEAN_ADDITIONAL) }
        YY_BREAK
 case 90:
 YY_RULE_SETUP
-#line 213 "./util/configlexer.lex"
+#line 261 "./util/configlexer.lex"
 { YDVAR(1, VAR_VAL_PERMISSIVE_MODE) }
        YY_BREAK
 case 91:
 YY_RULE_SETUP
-#line 214 "./util/configlexer.lex"
+#line 262 "./util/configlexer.lex"
 { YDVAR(1, VAR_IGNORE_CD_FLAG) }
        YY_BREAK
 case 92:
 YY_RULE_SETUP
-#line 215 "./util/configlexer.lex"
+#line 263 "./util/configlexer.lex"
 { YDVAR(1, VAR_VAL_LOG_LEVEL) }
        YY_BREAK
 case 93:
 YY_RULE_SETUP
-#line 216 "./util/configlexer.lex"
+#line 264 "./util/configlexer.lex"
 { YDVAR(1, VAR_KEY_CACHE_SIZE) }
        YY_BREAK
 case 94:
 YY_RULE_SETUP
-#line 217 "./util/configlexer.lex"
+#line 265 "./util/configlexer.lex"
 { YDVAR(1, VAR_KEY_CACHE_SLABS) }
        YY_BREAK
 case 95:
 YY_RULE_SETUP
-#line 218 "./util/configlexer.lex"
+#line 266 "./util/configlexer.lex"
 { YDVAR(1, VAR_NEG_CACHE_SIZE) }
        YY_BREAK
 case 96:
 YY_RULE_SETUP
-#line 219 "./util/configlexer.lex"
+#line 267 "./util/configlexer.lex"
 { 
                                  YDVAR(1, VAR_VAL_NSEC3_KEYSIZE_ITERATIONS) }
        YY_BREAK
 case 97:
 YY_RULE_SETUP
-#line 221 "./util/configlexer.lex"
+#line 269 "./util/configlexer.lex"
 { YDVAR(1, VAR_ADD_HOLDDOWN) }
        YY_BREAK
 case 98:
 YY_RULE_SETUP
-#line 222 "./util/configlexer.lex"
+#line 270 "./util/configlexer.lex"
 { YDVAR(1, VAR_DEL_HOLDDOWN) }
        YY_BREAK
 case 99:
 YY_RULE_SETUP
-#line 223 "./util/configlexer.lex"
+#line 271 "./util/configlexer.lex"
 { YDVAR(1, VAR_KEEP_MISSING) }
        YY_BREAK
 case 100:
 YY_RULE_SETUP
-#line 224 "./util/configlexer.lex"
+#line 272 "./util/configlexer.lex"
 { YDVAR(1, VAR_USE_SYSLOG) }
        YY_BREAK
 case 101:
 YY_RULE_SETUP
-#line 225 "./util/configlexer.lex"
+#line 273 "./util/configlexer.lex"
 { YDVAR(1, VAR_LOG_TIME_ASCII) }
        YY_BREAK
 case 102:
 YY_RULE_SETUP
-#line 226 "./util/configlexer.lex"
+#line 274 "./util/configlexer.lex"
 { YDVAR(1, VAR_LOG_QUERIES) }
        YY_BREAK
 case 103:
 YY_RULE_SETUP
-#line 227 "./util/configlexer.lex"
+#line 275 "./util/configlexer.lex"
 { YDVAR(2, VAR_LOCAL_ZONE) }
        YY_BREAK
 case 104:
 YY_RULE_SETUP
-#line 228 "./util/configlexer.lex"
+#line 276 "./util/configlexer.lex"
 { YDVAR(1, VAR_LOCAL_DATA) }
        YY_BREAK
 case 105:
 YY_RULE_SETUP
-#line 229 "./util/configlexer.lex"
+#line 277 "./util/configlexer.lex"
 { YDVAR(1, VAR_LOCAL_DATA_PTR) }
        YY_BREAK
 case 106:
 YY_RULE_SETUP
-#line 230 "./util/configlexer.lex"
+#line 278 "./util/configlexer.lex"
 { YDVAR(1, VAR_STATISTICS_INTERVAL) }
        YY_BREAK
 case 107:
 YY_RULE_SETUP
-#line 231 "./util/configlexer.lex"
+#line 279 "./util/configlexer.lex"
 { YDVAR(1, VAR_STATISTICS_CUMULATIVE) }
        YY_BREAK
 case 108:
 YY_RULE_SETUP
-#line 232 "./util/configlexer.lex"
+#line 280 "./util/configlexer.lex"
 { YDVAR(1, VAR_EXTENDED_STATISTICS) }
        YY_BREAK
 case 109:
 YY_RULE_SETUP
-#line 233 "./util/configlexer.lex"
+#line 281 "./util/configlexer.lex"
 { YDVAR(0, VAR_REMOTE_CONTROL) }
        YY_BREAK
 case 110:
 YY_RULE_SETUP
-#line 234 "./util/configlexer.lex"
+#line 282 "./util/configlexer.lex"
 { YDVAR(1, VAR_CONTROL_ENABLE) }
        YY_BREAK
 case 111:
 YY_RULE_SETUP
-#line 235 "./util/configlexer.lex"
+#line 283 "./util/configlexer.lex"
 { YDVAR(1, VAR_CONTROL_INTERFACE) }
        YY_BREAK
 case 112:
 YY_RULE_SETUP
-#line 236 "./util/configlexer.lex"
+#line 284 "./util/configlexer.lex"
 { YDVAR(1, VAR_CONTROL_PORT) }
        YY_BREAK
 case 113:
 YY_RULE_SETUP
-#line 237 "./util/configlexer.lex"
+#line 285 "./util/configlexer.lex"
 { YDVAR(1, VAR_SERVER_KEY_FILE) }
        YY_BREAK
 case 114:
 YY_RULE_SETUP
-#line 238 "./util/configlexer.lex"
+#line 286 "./util/configlexer.lex"
 { YDVAR(1, VAR_SERVER_CERT_FILE) }
        YY_BREAK
 case 115:
 YY_RULE_SETUP
-#line 239 "./util/configlexer.lex"
+#line 287 "./util/configlexer.lex"
 { YDVAR(1, VAR_CONTROL_KEY_FILE) }
        YY_BREAK
 case 116:
 YY_RULE_SETUP
-#line 240 "./util/configlexer.lex"
+#line 288 "./util/configlexer.lex"
 { YDVAR(1, VAR_CONTROL_CERT_FILE) }
        YY_BREAK
 case 117:
 YY_RULE_SETUP
-#line 241 "./util/configlexer.lex"
+#line 289 "./util/configlexer.lex"
 { YDVAR(1, VAR_PYTHON_SCRIPT) }
        YY_BREAK
 case 118:
 YY_RULE_SETUP
-#line 242 "./util/configlexer.lex"
+#line 290 "./util/configlexer.lex"
 { YDVAR(0, VAR_PYTHON) }
        YY_BREAK
 case 119:
 YY_RULE_SETUP
-#line 243 "./util/configlexer.lex"
+#line 291 "./util/configlexer.lex"
 { YDVAR(1, VAR_DOMAIN_INSECURE) }
        YY_BREAK
 case 120:
 YY_RULE_SETUP
-#line 244 "./util/configlexer.lex"
+#line 292 "./util/configlexer.lex"
 { YDVAR(1, VAR_MINIMAL_RESPONSES) }
        YY_BREAK
 case 121:
 YY_RULE_SETUP
-#line 245 "./util/configlexer.lex"
+#line 293 "./util/configlexer.lex"
 { YDVAR(1, VAR_RRSET_ROUNDROBIN) }
        YY_BREAK
 case 122:
 /* rule 122 can match eol */
 YY_RULE_SETUP
-#line 246 "./util/configlexer.lex"
+#line 294 "./util/configlexer.lex"
 { LEXOUT(("NL\n")); cfg_parser->line++; }
        YY_BREAK
 /* Quoted strings. Strip leading and ending quotes */
 case 123:
 YY_RULE_SETUP
-#line 249 "./util/configlexer.lex"
+#line 297 "./util/configlexer.lex"
 { BEGIN(quotedstring); LEXOUT(("QS ")); }
        YY_BREAK
 case YY_STATE_EOF(quotedstring):
-#line 250 "./util/configlexer.lex"
+#line 298 "./util/configlexer.lex"
 {
         yyerror("EOF inside quoted string");
        if(--num_args == 0) { BEGIN(INITIAL); }
@@ -2505,19 +2553,19 @@ case YY_STATE_EOF(quotedstring):
        YY_BREAK
 case 124:
 YY_RULE_SETUP
-#line 255 "./util/configlexer.lex"
+#line 303 "./util/configlexer.lex"
 { LEXOUT(("STR(%s) ", yytext)); yymore(); }
        YY_BREAK
 case 125:
 /* rule 125 can match eol */
 YY_RULE_SETUP
-#line 256 "./util/configlexer.lex"
+#line 304 "./util/configlexer.lex"
 { yyerror("newline inside quoted string, no end \""); 
                          cfg_parser->line++; BEGIN(INITIAL); }
        YY_BREAK
 case 126:
 YY_RULE_SETUP
-#line 258 "./util/configlexer.lex"
+#line 306 "./util/configlexer.lex"
 {
         LEXOUT(("QE "));
        if(--num_args == 0) { BEGIN(INITIAL); }
@@ -2532,11 +2580,11 @@ YY_RULE_SETUP
 /* Single Quoted strings. Strip leading and ending quotes */
 case 127:
 YY_RULE_SETUP
-#line 270 "./util/configlexer.lex"
+#line 318 "./util/configlexer.lex"
 { BEGIN(singlequotedstr); LEXOUT(("SQS ")); }
        YY_BREAK
 case YY_STATE_EOF(singlequotedstr):
-#line 271 "./util/configlexer.lex"
+#line 319 "./util/configlexer.lex"
 {
         yyerror("EOF inside quoted string");
        if(--num_args == 0) { BEGIN(INITIAL); }
@@ -2545,19 +2593,19 @@ case YY_STATE_EOF(singlequotedstr):
        YY_BREAK
 case 128:
 YY_RULE_SETUP
-#line 276 "./util/configlexer.lex"
+#line 324 "./util/configlexer.lex"
 { LEXOUT(("STR(%s) ", yytext)); yymore(); }
        YY_BREAK
 case 129:
 /* rule 129 can match eol */
 YY_RULE_SETUP
-#line 277 "./util/configlexer.lex"
+#line 325 "./util/configlexer.lex"
 { yyerror("newline inside quoted string, no end '"); 
                             cfg_parser->line++; BEGIN(INITIAL); }
        YY_BREAK
 case 130:
 YY_RULE_SETUP
-#line 279 "./util/configlexer.lex"
+#line 327 "./util/configlexer.lex"
 {
         LEXOUT(("SQE "));
        if(--num_args == 0) { BEGIN(INITIAL); }
@@ -2572,12 +2620,12 @@ YY_RULE_SETUP
 /* include: directive */
 case 131:
 YY_RULE_SETUP
-#line 291 "./util/configlexer.lex"
+#line 339 "./util/configlexer.lex"
 { 
        LEXOUT(("v(%s) ", yytext)); inc_prev = YYSTATE; BEGIN(include); }
        YY_BREAK
 case YY_STATE_EOF(include):
-#line 293 "./util/configlexer.lex"
+#line 341 "./util/configlexer.lex"
 {
         yyerror("EOF inside include directive");
         BEGIN(inc_prev);
@@ -2585,31 +2633,31 @@ case YY_STATE_EOF(include):
        YY_BREAK
 case 132:
 YY_RULE_SETUP
-#line 297 "./util/configlexer.lex"
+#line 345 "./util/configlexer.lex"
 { LEXOUT(("ISP ")); /* ignore */ }
        YY_BREAK
 case 133:
 /* rule 133 can match eol */
 YY_RULE_SETUP
-#line 298 "./util/configlexer.lex"
+#line 346 "./util/configlexer.lex"
 { LEXOUT(("NL\n")); cfg_parser->line++;}
        YY_BREAK
 case 134:
 YY_RULE_SETUP
-#line 299 "./util/configlexer.lex"
+#line 347 "./util/configlexer.lex"
 { LEXOUT(("IQS ")); BEGIN(include_quoted); }
        YY_BREAK
 case 135:
 YY_RULE_SETUP
-#line 300 "./util/configlexer.lex"
+#line 348 "./util/configlexer.lex"
 {
        LEXOUT(("Iunquotedstr(%s) ", yytext));
-       config_start_include(yytext);
+       config_start_include_glob(yytext);
        BEGIN(inc_prev);
 }
        YY_BREAK
 case YY_STATE_EOF(include_quoted):
-#line 305 "./util/configlexer.lex"
+#line 353 "./util/configlexer.lex"
 {
         yyerror("EOF inside quoted string");
         BEGIN(inc_prev);
@@ -2617,29 +2665,29 @@ case YY_STATE_EOF(include_quoted):
        YY_BREAK
 case 136:
 YY_RULE_SETUP
-#line 309 "./util/configlexer.lex"
+#line 357 "./util/configlexer.lex"
 { LEXOUT(("ISTR(%s) ", yytext)); yymore(); }
        YY_BREAK
 case 137:
 /* rule 137 can match eol */
 YY_RULE_SETUP
-#line 310 "./util/configlexer.lex"
+#line 358 "./util/configlexer.lex"
 { yyerror("newline before \" in include name"); 
                                  cfg_parser->line++; BEGIN(inc_prev); }
        YY_BREAK
 case 138:
 YY_RULE_SETUP
-#line 312 "./util/configlexer.lex"
+#line 360 "./util/configlexer.lex"
 {
        LEXOUT(("IQE "));
        yytext[yyleng - 1] = '\0';
-       config_start_include(yytext);
+       config_start_include_glob(yytext);
        BEGIN(inc_prev);
 }
        YY_BREAK
 case YY_STATE_EOF(INITIAL):
 case YY_STATE_EOF(val):
-#line 318 "./util/configlexer.lex"
+#line 366 "./util/configlexer.lex"
 {
        yy_set_bol(1); /* Set beginning of line, so "^" rules match.  */
        if (config_include_stack_ptr == 0) {
@@ -2652,31 +2700,31 @@ case YY_STATE_EOF(val):
        YY_BREAK
 case 139:
 YY_RULE_SETUP
-#line 328 "./util/configlexer.lex"
+#line 376 "./util/configlexer.lex"
 { LEXOUT(("unquotedstr(%s) ", yytext)); 
                        if(--num_args == 0) { BEGIN(INITIAL); }
                        yylval.str = strdup(yytext); return STRING_ARG; }
        YY_BREAK
 case 140:
 YY_RULE_SETUP
-#line 332 "./util/configlexer.lex"
+#line 380 "./util/configlexer.lex"
 {
        ub_c_error_msg("unknown keyword '%s'", yytext);
        }
        YY_BREAK
 case 141:
 YY_RULE_SETUP
-#line 336 "./util/configlexer.lex"
+#line 384 "./util/configlexer.lex"
 {
        ub_c_error_msg("stray '%s'", yytext);
        }
        YY_BREAK
 case 142:
 YY_RULE_SETUP
-#line 340 "./util/configlexer.lex"
+#line 388 "./util/configlexer.lex"
 ECHO;
        YY_BREAK
-#line 2678 "<stdout>"
+#line 2726 "<stdout>"
 
        case YY_END_OF_BUFFER:
                {
@@ -3635,7 +3683,7 @@ void yyfree (void * ptr )
 
 #define YYTABLES_NAME "yytables"
 
-#line 340 "./util/configlexer.lex"
+#line 388 "./util/configlexer.lex"
 
 
 
index ed808aafc3931bcb3cc4f6e39b10370d725bd7a5..4694cdd821e7e6cd4c67b96b08a9900065a6498c 100644 (file)
@@ -11,6 +11,9 @@
 #include <ctype.h>
 #include <string.h>
 #include <strings.h>
+#ifdef HAVE_GLOB_H
+# include <glob.h>
+#endif
 
 #include "util/config_file.h"
 #include "util/configparser.h"
@@ -43,6 +46,7 @@ static int config_include_stack_ptr = 0;
 static int inc_prev = 0;
 static int num_args = 0;
 
+
 static void config_start_include(const char* filename)
 {
        FILE *input;
@@ -74,6 +78,50 @@ static void config_start_include(const char* filename)
        ++config_include_stack_ptr;
 }
 
+static void config_start_include_glob(const char* filename)
+{
+
+       /* check for wildcards */
+#ifdef HAVE_GLOB
+       glob_t g;
+       size_t i;
+       int r, flags;
+       if(!(!strchr(filename, '*') && !strchr(filename, '?') && !strchr(filename, '[') &&
+               !strchr(filename, '{') && !strchr(filename, '~'))) {
+               flags = 0
+#ifdef GLOB_ERR
+                       | GLOB_ERR
+#endif
+#ifdef GLOB_NOSORT
+                       | GLOB_NOSORT
+#endif
+#ifdef GLOB_BRACE
+                       | GLOB_BRACE
+#endif
+#ifdef GLOB_TILDE
+                       | GLOB_TILDE
+#endif
+               ;
+               memset(&g, 0, sizeof(g));
+               r = glob(filename, flags, NULL, &g);
+               if(r) {
+                       /* some error */
+                       globfree(&g);
+                       config_start_include(filename); /* let original deal with it */
+                       return;
+               }
+               /* process files found, if any */
+               for(i=0; i<(size_t)g.gl_pathc; i++) {
+                       config_start_include(g.gl_pathv[i]);
+               }
+               globfree(&g);
+               return;
+       }
+#endif /* HAVE_GLOB */
+
+       config_start_include(filename);
+}
+
 static void config_end_include(void)
 {
        --config_include_stack_ptr;
@@ -299,7 +347,7 @@ rrset-roundrobin{COLON}             { YDVAR(1, VAR_RRSET_ROUNDROBIN) }
 <include>\"            { LEXOUT(("IQS ")); BEGIN(include_quoted); }
 <include>{UNQUOTEDLETTER}*     {
        LEXOUT(("Iunquotedstr(%s) ", yytext));
-       config_start_include(yytext);
+       config_start_include_glob(yytext);
        BEGIN(inc_prev);
 }
 <include_quoted><<EOF>>        {
@@ -312,7 +360,7 @@ rrset-roundrobin{COLON}             { YDVAR(1, VAR_RRSET_ROUNDROBIN) }
 <include_quoted>\"     {
        LEXOUT(("IQE "));
        yytext[yyleng - 1] = '\0';
-       config_start_include(yytext);
+       config_start_include_glob(yytext);
        BEGIN(inc_prev);
 }
 <INITIAL,val><<EOF>>   {