1 /* servparse.y -- Parser for dictd server configuration file
2  * Created: Fri Feb 28 08:31:38 1997 by faith@cs.unc.edu
3  * Copyright 1997 Rickard E. Faith (faith@cs.unc.edu)
4  * Copyright 2002-2008 Aleksey Cheusov (vle@gmx.net)
5  *
6  * This program is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU General Public License as published by the
8  * Free Software Foundation; either version 1, or (at your option) any
9  * later version.
10  *
11  * This program is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License along
17  * with this program; if not, write to the Free Software Foundation, Inc.,
18  * 675 Mass Ave, Cambridge, MA 02139, USA.
19  */
20 
21 %{
22 #include "dictd.h"
23 #include "strategy.h"
24 #include "index.h"
25 #include "data.h"
26 #include "maa.h"
27 
28 #define YYDEBUG 1
29 #define YYERROR_VERBOSE
30 
31 static dictDatabase *db;
32 
string2bool(const char * str)33 static int string2bool (const char *str)
34 {
35    if (
36       !strcasecmp ("1", str)
37       || !strcasecmp ("true", str)
38       || !strcasecmp ("yes", str))
39    {
40       return 1;
41    }else{
42       return 0;
43    }
44 }
45 
46 #define SET(field,s,t) do {                                   \
47    if (db->field)                                             \
48       src_parse_error( stderr, s.src, #field "already set" ); \
49    db->field = t.string;                                      \
50 } while(0);
51 %}
52 
53 %union {
54    dictToken     token;
55    dictDatabase  *db;
56    dictAccess    *access;
57    lst_List      list;
58    hsh_HashTable hash;
59 }
60 
61 				/* Terminals */
62 
63 %token <token.integer> TOKEN_NUMBER
64 %token <token> '{' '}' TOKEN_ACCESS TOKEN_ALLOW TOKEN_DENY
65 %token <token> TOKEN_GROUP TOKEN_DATABASE TOKEN_DATA
66 %token <token> TOKEN_INDEX TOKEN_INDEX_SUFFIX TOKEN_INDEX_WORD
67 %token <token> TOKEN_FILTER TOKEN_PREFILTER TOKEN_POSTFILTER TOKEN_NAME TOKEN_INFO
68 %token <token> TOKEN_USER TOKEN_AUTHONLY TOKEN_DATABASE_EXIT
69 
70 %token <token> TOKEN_SITE TOKEN_SITE_NO_BANNER TOKEN_SITE_NO_UPTIME
71 %token <token> TOKEN_SITE_NO_DBLIST
72 
73 %token <token> TOKEN_STRING
74 %token <token> TOKEN_INVISIBLE TOKEN_DISABLE_STRAT
75 %token <token> TOKEN_DATABASE_VIRTUAL TOKEN_DATABASE_LIST
76 %token <token> TOKEN_DATABASE_PLUGIN TOKEN_PLUGIN
77 %token <token> TOKEN_DATABASE_MIME
78 %token <token> TOKEN_DEFAULT_STRAT
79 %token <token> TOKEN_GLOBAL
80 %token <token> TOKEN_PORT
81 %token <token> TOKEN_DELAY
82 %token <token> TOKEN_DEPTH
83 
84 %token <token> TOKEN_TIMESTAMP
85 %token <token> TOKEN_LOG_OPTION
86 %token <token> TOKEN_DEBUG_OPTION
87 %token <token> TOKEN_LOCALE
88 %token <token> TOKEN_ADD_STRAT
89 %token <token> TOKEN_LISTEN_TO
90 %token <token> TOKEN_ADDRESS_FAMILY
91 %token <token> TOKEN_SYSLOG
92 %token <token> TOKEN_SYSLOG_FACILITY
93 %token <token> TOKEN_LOG_FILE
94 %token <token> TOKEN_PID_FILE
95 %token <token> TOKEN_FAST_START
96 %token <token> TOKEN_WITHOUT_MMAP
97 
98 %token <token> TOKEN_LIMIT_CHILDS
99 %token <token> TOKEN_LIMIT_MATCHES
100 %token <token> TOKEN_LIMIT_DEFS
101 %token <token> TOKEN_LIMIT_TIME
102 %token <token> TOKEN_LIMIT_QUERIES
103 
104 %token <token> TOKEN_MIME_DBNAME
105 %token <token> TOKEN_NOMIME_DBNAME
106 
107 %type  <token>  Site
108 %type  <access> AccessSpec
109 %type  <db>     Database
110 %type  <list>   DatabaseList Access AccessSpecList
111 %type  <hash>   UserList
112 %type  <token>  Global
113 
114 %%
115 
116 Program : Global DatabaseList
117           { DictConfig = xmalloc(sizeof(struct dictConfig));
118 	    memset( DictConfig, 0, sizeof(struct dictConfig) );
119 	    DictConfig->dbl = $2;
120 	  }
121         | Global Access DatabaseList
122           { DictConfig = xmalloc(sizeof(struct dictConfig));
123 	    memset( DictConfig, 0, sizeof(struct dictConfig) );
124 	    DictConfig->acl = $2;
125 	    DictConfig->dbl = $3;
126 	  }
127         | Global DatabaseList UserList
128           { DictConfig = xmalloc(sizeof(struct dictConfig));
129 	    memset( DictConfig, 0, sizeof(struct dictConfig) );
130 	    DictConfig->dbl = $2;
131 	    DictConfig->usl = $3;
132 	  }
133         | Global Access DatabaseList UserList
134           { DictConfig = xmalloc(sizeof(struct dictConfig));
135 	    memset( DictConfig, 0, sizeof(struct dictConfig) );
136 	    DictConfig->acl = $2;
137 	    DictConfig->dbl = $3;
138 	    DictConfig->usl = $4;
139 	  }
140         | Global Site DatabaseList
141           { DictConfig = xmalloc(sizeof(struct dictConfig));
142 	    memset( DictConfig, 0, sizeof(struct dictConfig) );
143 	    site_info        = $2.string;
144 	    DictConfig->dbl  = $3;
145 	  }
146         | Global Site Access DatabaseList
147           { DictConfig = xmalloc(sizeof(struct dictConfig));
148 	    memset( DictConfig, 0, sizeof(struct dictConfig) );
149 	    site_info        = $2.string;
150 	    DictConfig->acl  = $3;
151 	    DictConfig->dbl  = $4;
152 	  }
153         | Global Site DatabaseList UserList
154           { DictConfig = xmalloc(sizeof(struct dictConfig));
155 	    memset( DictConfig, 0, sizeof(struct dictConfig) );
156 	    site_info        = $2.string;
157 	    DictConfig->dbl  = $3;
158 	    DictConfig->usl  = $4;
159 	  }
160         | Global Site Access DatabaseList UserList
161           { DictConfig = xmalloc(sizeof(struct dictConfig));
162 	    memset( DictConfig, 0, sizeof(struct dictConfig) );
163 	    site_info        = $2.string;
164 	    DictConfig->acl  = $3;
165 	    DictConfig->dbl  = $4;
166 	    DictConfig->usl  = $5;
167 	  }
168         ;
169 
170 
171 Global : {}
172        | TOKEN_GLOBAL '{' GlobalSpecList '}' {}
173        ;
174 
175 GlobalSpecList :
176              | GlobalSpecList GlobalSpec
177              ;
178 
179 GlobalSpec : TOKEN_PORT             TOKEN_STRING
180      {
181 	if (!daemon_service_set)
182 	   daemon_service = str_copy($2.string);
183      }
184    | TOKEN_SITE             TOKEN_STRING
185      {
186 	if (site_info){
187 	   /* site is specified twice */
188 	   xfree ((void *) site_info);
189 	}
190 
191 	site_info = $2.string;
192      }
193    | TOKEN_SITE_NO_BANNER     TOKEN_STRING
194      {
195 	site_info_no_banner = string2bool ($2.string);
196 	fprintf (stderr, "site_info_no_banner=%d\n", site_info_no_banner);
197      }
198    | TOKEN_SITE_NO_UPTIME   TOKEN_STRING
199      {
200 	site_info_no_uptime = string2bool ($2.string);
201      }
202    | TOKEN_SITE_NO_DBLIST  TOKEN_STRING
203      {
204 	site_info_no_dblist = string2bool ($2.string);
205      }
206    | TOKEN_PORT             TOKEN_NUMBER
207      {
208 	if (!daemon_service_set){
209 	   char number [40] = "";
210 	   snprintf (number, sizeof (number), "%d", $2);
211 	   daemon_service = str_copy (number);
212 	}
213      }
214    | TOKEN_DELAY            TOKEN_NUMBER
215      {
216 	if (!client_delay_set)
217 	   client_delay = $2;
218 
219 	_dict_daemon_limit_time = 0;
220      }
221    | TOKEN_DEPTH            TOKEN_NUMBER
222      {
223 	if (!depth_set)
224 	   depth = $2;
225      }
226    | TOKEN_LIMIT_CHILDS     TOKEN_NUMBER
227      {
228 	if (!_dict_daemon_limit_childs_set)
229 	   _dict_daemon_limit_childs = $2;
230      }
231    | TOKEN_LIMIT_MATCHES    TOKEN_NUMBER
232      {
233 	_dict_daemon_limit_matches = $2;
234      }
235    | TOKEN_LIMIT_DEFS       TOKEN_NUMBER
236      {
237 	_dict_daemon_limit_defs = $2;
238      }
239    | TOKEN_LIMIT_TIME       TOKEN_NUMBER
240      {
241 	_dict_daemon_limit_time = $2;
242 	client_delay            = 0;
243      }
244    | TOKEN_LIMIT_QUERIES    TOKEN_NUMBER
245      {
246 	_dict_daemon_limit_queries = $2;
247      }
248    | TOKEN_TIMESTAMP        TOKEN_NUMBER
249      {
250 	if (!_dict_markTime_set)
251 	   _dict_markTime = 60*$2;
252      }
253    | TOKEN_LOG_OPTION       TOKEN_STRING
254      {
255 	 ++logOptions;
256 	 flg_set ($2.string);
257 	 if (flg_test (LOG_MIN))
258 	    set_minimal ();
259      }
260    | TOKEN_DEBUG_OPTION     TOKEN_STRING
261      {
262 	dbg_set ($2.string);
263      }
264    | TOKEN_LOCALE           TOKEN_STRING
265      {
266 	if (!locale_set)
267 	   locale = str_copy ($2.string);
268      }
269    | TOKEN_DEFAULT_STRAT        TOKEN_STRING
270      {
271 	if (!default_strategy_set)
272 	   default_strategy     = lookup_strategy_ex ($2.string);
273      }
274    | TOKEN_DISABLE_STRAT    TOKEN_STRING
275      {
276 	dict_disable_strategies ($2.string);
277      }
278    | TOKEN_ADD_STRAT        TOKEN_STRING TOKEN_STRING
279      {
280 	dict_add_strategy ($2.string, $3.string);
281      }
282    | TOKEN_LISTEN_TO        TOKEN_STRING
283      {
284 	if (!bind_to_set)
285 	   if ($2.string[0] != '*' || $2.string[1] != '\0')
286 	      bind_to = str_copy ($2.string);
287      }
288    | TOKEN_ADDRESS_FAMILY        TOKEN_NUMBER
289      {
290 	if (!dictd_address_family_set){
291 	   if ($2 == 4)
292 	      dictd_address_family = AF_INET;
293 	   else if ($2 == 6)
294 	      dictd_address_family = AF_INET6;
295 	   else {
296 	      log_error (NULL, ":E: Incorrect value '%d' for global option 'address_family'\n", $2);
297 	      exit(1);
298 	   }
299 	}
300      }
301    | TOKEN_SYSLOG
302      {
303 	++useSyslog;
304      }
305    | TOKEN_SYSLOG_FACILITY  TOKEN_STRING
306      {
307 	++useSyslog;
308 	if (!syslog_facility_set){
309 	   log_set_facility ($2.string);
310 	}
311      }
312    | TOKEN_LOG_FILE         TOKEN_STRING
313      {
314 	if (!logFile_set){
315 	   logFile     = str_copy ($2.string);
316 	}
317      }
318    | TOKEN_PID_FILE         TOKEN_STRING
319      {
320 	if (!pidFile_set){
321 	   pidFile     = str_copy ($2.string);
322 	}
323      }
324    | TOKEN_FAST_START
325      {
326 	optStart_mode = 0;
327      }
328    | TOKEN_WITHOUT_MMAP
329      {
330 	mmap_mode = 0;
331      }
332 ;
333 
334 Access : TOKEN_ACCESS '{' AccessSpecList '}' { $$ = $3; }
335        ;
336 
337 DatabaseList : Database { $$ = lst_create(); lst_append($$, $1); }
338              | DatabaseList Database { lst_append($1, $2); $$ = $1; }
339              ;
340 
341 AccessSpecList : AccessSpec { $$ = lst_create(); lst_append($$, $1); }
342                | AccessSpecList AccessSpec { lst_append($1, $2); $$ = $1; }
343                ;
344 
345 Site : TOKEN_SITE TOKEN_STRING
346        {
347 	  $$ = $2;
348 	  log_error (NULL, ":E: Move \"site\" directive to section \"global\" of the configuration file!\n");
349        }
350      ;
351 
352 UserList : TOKEN_USER TOKEN_STRING TOKEN_STRING
353            { $$ = hsh_create(NULL,NULL);
354 	     hsh_insert( $$, $2.string, $3.string );
355 	   }
356          | UserList TOKEN_USER TOKEN_STRING TOKEN_STRING
357            { hsh_insert( $1, $3.string, $4.string ); $$ = $1; }
358          ;
359 
360 AccessSpec : TOKEN_ALLOW TOKEN_STRING
361              {
362 		dictAccess *a = xmalloc(sizeof(struct dictAccess));
363 		a->type = DICT_ALLOW;
364 		a->spec = $2.string;
365 		$$ = a;
366 	     }
367            | TOKEN_DENY TOKEN_STRING
368              {
369 		dictAccess *a = xmalloc(sizeof(struct dictAccess));
370 		a->type = DICT_DENY;
371 		a->spec = $2.string;
372 		$$ = a;
373 	     }
374            | TOKEN_AUTHONLY TOKEN_STRING
375              {
376 		dictAccess *a = xmalloc(sizeof(struct dictAccess));
377 		a->type = DICT_AUTHONLY;
378 		a->spec = $2.string;
379 		$$ = a;
380 	     }
381            | TOKEN_USER TOKEN_STRING
382              {
383 		dictAccess *a = xmalloc(sizeof(struct dictAccess));
384 		a->type = DICT_USER;
385 		a->spec = $2.string;
386 		$$ = a;
387 	     }
388            ;
389 
390 Database : TOKEN_DATABASE TOKEN_STRING
391            {
392 	      db = xmalloc(sizeof(struct dictDatabase));
393 	      memset( db, 0, sizeof(struct dictDatabase));
394 	      db->databaseName = $2.string;
395 	      db->normal_db    = 1;
396 	   }
397            '{' SpecList '}' { $$ = db; }
398            |
399            TOKEN_DATABASE_VIRTUAL TOKEN_STRING
400            {
401 	      db = xmalloc(sizeof(struct dictDatabase));
402 	      memset( db, 0, sizeof(struct dictDatabase));
403 	      db->databaseName = $2.string;
404 	      db->virtual_db   = 1;
405 	   }
406            '{' SpecList_virtual '}' { $$ = db; }
407            |
408            TOKEN_DATABASE_PLUGIN TOKEN_STRING
409            {
410 	      db = xmalloc(sizeof(struct dictDatabase));
411 	      memset( db, 0, sizeof(struct dictDatabase));
412 	      db->databaseName = $2.string;
413 	      db->plugin_db    = 1;
414 	   }
415            '{' SpecList_plugin '}' { $$ = db; }
416            |
417            TOKEN_DATABASE_MIME TOKEN_STRING
418 	   {
419 	      db = xmalloc (sizeof (struct dictDatabase));
420 	      memset (db, 0, sizeof (struct dictDatabase));
421 	      db->databaseName = $2.string;
422 	      db->mime_db      = 1;
423 	   }
424            '{' SpecList_mime '}' { $$ = db; }
425            |
426 	   TOKEN_DATABASE_EXIT
427 	   {
428 	      db = xmalloc(sizeof(struct dictDatabase));
429 	      memset( db, 0, sizeof(struct dictDatabase));
430 	      db -> databaseName  = strdup("--exit--");
431 	      db -> databaseShort = strdup("Stop default search here.");
432 	      db -> exit_db       = 1;
433 	      $$ = db;
434 	   }
435          ;
436 
437 SpecList_virtual : Spec_virtual
438          | SpecList_virtual Spec_virtual
439          ;
440 
441 Spec_virtual : Spec__name
442      | Spec__info
443      | TOKEN_DATABASE_LIST TOKEN_STRING      { SET(database_list,$1,$2);}
444      | Spec__invisible
445      | Spec__disable_strat
446      | Spec__access
447      ;
448 
449 SpecList_plugin : Spec_plugin
450          | SpecList_plugin Spec_plugin
451          ;
452 
453 SpecList_mime : Spec_mime
454          | SpecList_mime Spec_mime
455          ;
456 
457 Spec_mime : Spec__name
458      | Spec__info
459      | Spec__dbname_mime
460      | Spec__dbname_nomime
461      | Spec__invisible
462      | Spec__disable_strat
463      | Spec__default_strat
464      | Spec__access
465      ;
466 
467 Spec_plugin : Spec__name
468      | Spec__info
469      | TOKEN_PLUGIN TOKEN_STRING      { SET(pluginFilename,$1,$2);}
470      | TOKEN_DATA TOKEN_STRING        { SET(plugin_data,$1,$2);}
471      | Spec__invisible
472      | Spec__disable_strat
473      | Spec__default_strat
474      | Spec__access
475      ;
476 
477 SpecList : Spec
478          | SpecList Spec
479          ;
480 
481 Spec : Spec__data
482      | Spec__index
483      | Spec__index_suffix
484      | Spec__index_word
485      | Spec__filter
486      | Spec__prefilter
487      | Spec__postfilter
488      | Spec__name
489      | Spec__info
490      | Spec__invisible
491      | Spec__disable_strat
492      | Spec__default_strat
493      | Spec__access
494      ;
495 
496 Spec__access : Access
497      {  db->acl = $1;  };
498 
499 Spec__data : TOKEN_DATA TOKEN_STRING
500      {	SET(dataFilename,$1,$2);  };
501 
502 Spec__index : TOKEN_INDEX TOKEN_STRING
503      {  SET(indexFilename,$1,$2);  };
504 
505 Spec__index_suffix : TOKEN_INDEX_SUFFIX TOKEN_STRING
506      {  SET(indexsuffixFilename,$1,$2); };
507 
508 Spec__index_word : TOKEN_INDEX_WORD TOKEN_STRING
509      {  SET(indexwordFilename,$1,$2);  };
510 
511 Spec__filter : TOKEN_FILTER TOKEN_STRING
512      {  SET(filter,$1,$2);  };
513 
514 Spec__prefilter : TOKEN_PREFILTER TOKEN_STRING
515      {  SET(prefilter,$1,$2);  };
516 
517 Spec__postfilter : TOKEN_POSTFILTER TOKEN_STRING
518      {  SET(postfilter,$1,$2);  };
519 
520 Spec__name : TOKEN_NAME TOKEN_STRING
521      {  SET(databaseShort,$1,$2);  };
522 
523 Spec__info : TOKEN_INFO TOKEN_STRING
524      {  SET(databaseInfo,$1,$2);  };
525 
526 Spec__invisible : TOKEN_INVISIBLE
527      {  db->invisible = 1;  };
528 
529 Spec__disable_strat : TOKEN_DISABLE_STRAT TOKEN_STRING
530      {  dict_disable_strat (db, $2.string);  };
531 
532 Spec__default_strat : TOKEN_DEFAULT_STRAT TOKEN_STRING
533      {  db -> default_strategy = lookup_strategy_ex ($2.string);  };
534 
535 Spec__dbname_mime : TOKEN_MIME_DBNAME TOKEN_STRING
536      {  SET(mime_mimeDbname,$1,$2);  };
537 
538 Spec__dbname_nomime : TOKEN_NOMIME_DBNAME TOKEN_STRING
539      {  SET(mime_nomimeDbname,$1,$2);  };
540