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