adds a couple print_vmcb()s for the write CR0 -> shutdown bug
[freebsd-src/fkvm-freebsd.git] / usr.sbin / nscd / parser.c
blobb877efa6cf44767c078a5c53ec17911db064060a
1 /*-
2 * Copyright (c) 2005 Michael Bushkov <bushman@rsu.ru>
3 * All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
28 #include <sys/cdefs.h>
29 __FBSDID("$FreeBSD$");
31 #include <assert.h>
32 #include <stdio.h>
33 #include <string.h>
34 #include "config.h"
35 #include "debug.h"
36 #include "log.h"
37 #include "parser.h"
39 static void enable_cache(struct configuration *,const char *, int);
40 static struct configuration_entry *find_create_entry(struct configuration *,
41 const char *);
42 static int get_number(const char *, int, int);
43 static enum cache_policy_t get_policy(const char *);
44 static int get_yesno(const char *);
45 static int check_cachename(const char *);
46 static void check_files(struct configuration *, const char *, int);
47 static void set_keep_hot_count(struct configuration *, const char *, int);
48 static void set_negative_policy(struct configuration *, const char *,
49 enum cache_policy_t);
50 static void set_negative_time_to_live(struct configuration *,
51 const char *, int);
52 static void set_positive_policy(struct configuration *, const char *,
53 enum cache_policy_t);
54 static void set_perform_actual_lookups(struct configuration *, const char *,
55 int);
56 static void set_positive_time_to_live(struct configuration *,
57 const char *, int);
58 static void set_suggested_size(struct configuration *, const char *,
59 int size);
60 static void set_threads_num(struct configuration *, int);
61 static int strbreak(char *, char **, int);
63 static int
64 strbreak(char *str, char **fields, int fields_size)
66 char *c = str;
67 int i, num;
69 TRACE_IN(strbreak);
70 num = 0;
71 for (i = 0;
72 ((*fields =
73 strsep(i < fields_size ? &c : NULL, "\n\t ")) != NULL);
74 ++i)
75 if ((*(*fields)) != '\0') {
76 ++fields;
77 ++num;
80 TRACE_OUT(strbreak);
81 return (num);
85 * Tries to find the configuration entry with the specified name. If search
86 * fails, the new entry with the default parameters will be created.
88 static struct configuration_entry *
89 find_create_entry(struct configuration *config,
90 const char *entry_name)
92 struct configuration_entry *entry = NULL;
93 int res;
95 TRACE_IN(find_create_entry);
96 entry = configuration_find_entry(config, entry_name);
97 if (entry == NULL) {
98 entry = create_def_configuration_entry(entry_name);
99 assert( entry != NULL);
100 res = add_configuration_entry(config, entry);
101 assert(res == 0);
104 TRACE_OUT(find_create_entry);
105 return (entry);
109 * The vast majority of the functions below corresponds to the particular
110 * keywords in the configuration file.
112 static void
113 enable_cache(struct configuration *config, const char *entry_name, int flag)
115 struct configuration_entry *entry;
117 TRACE_IN(enable_cache);
118 entry = find_create_entry(config, entry_name);
119 entry->enabled = flag;
120 TRACE_OUT(enable_cache);
123 static void
124 set_positive_time_to_live(struct configuration *config,
125 const char *entry_name, int ttl)
127 struct configuration_entry *entry;
128 struct timeval lifetime;
130 TRACE_IN(set_positive_time_to_live);
131 assert(ttl >= 0);
132 assert(entry_name != NULL);
133 memset(&lifetime, 0, sizeof(struct timeval));
134 lifetime.tv_sec = ttl;
136 entry = find_create_entry(config, entry_name);
137 memcpy(&entry->positive_cache_params.max_lifetime,
138 &lifetime, sizeof(struct timeval));
139 memcpy(&entry->mp_cache_params.max_lifetime,
140 &lifetime, sizeof(struct timeval));
142 TRACE_OUT(set_positive_time_to_live);
145 static void
146 set_negative_time_to_live(struct configuration *config,
147 const char *entry_name, int nttl)
149 struct configuration_entry *entry;
150 struct timeval lifetime;
152 TRACE_IN(set_negative_time_to_live);
153 assert(nttl > 0);
154 assert(entry_name != NULL);
155 memset(&lifetime, 0, sizeof(struct timeval));
156 lifetime.tv_sec = nttl;
158 entry = find_create_entry(config, entry_name);
159 assert(entry != NULL);
160 memcpy(&entry->negative_cache_params.max_lifetime,
161 &lifetime, sizeof(struct timeval));
163 TRACE_OUT(set_negative_time_to_live);
167 * Hot count is actually the elements size limit.
169 static void
170 set_keep_hot_count(struct configuration *config,
171 const char *entry_name, int count)
173 struct configuration_entry *entry;
175 TRACE_IN(set_keep_hot_count);
176 assert(count >= 0);
177 assert(entry_name != NULL);
179 entry = find_create_entry(config, entry_name);
180 assert(entry != NULL);
181 entry->positive_cache_params.max_elemsize = count;
183 entry = find_create_entry(config, entry_name);
184 assert(entry != NULL);
185 entry->negative_cache_params.max_elemsize = count;
187 TRACE_OUT(set_keep_hot_count);
190 static void
191 set_positive_policy(struct configuration *config,
192 const char *entry_name, enum cache_policy_t policy)
194 struct configuration_entry *entry;
196 TRACE_IN(set_positive_policy);
197 assert(entry_name != NULL);
199 entry = find_create_entry(config, entry_name);
200 assert(entry != NULL);
201 entry->positive_cache_params.policy = policy;
203 TRACE_OUT(set_positive_policy);
206 static void
207 set_negative_policy(struct configuration *config,
208 const char *entry_name, enum cache_policy_t policy)
210 struct configuration_entry *entry;
212 TRACE_IN(set_negative_policy);
213 assert(entry_name != NULL);
215 entry = find_create_entry(config, entry_name);
216 assert(entry != NULL);
217 entry->negative_cache_params.policy = policy;
219 TRACE_OUT(set_negative_policy);
222 static void
223 set_perform_actual_lookups(struct configuration *config,
224 const char *entry_name, int flag)
226 struct configuration_entry *entry;
228 TRACE_IN(set_perform_actual_lookups);
229 assert(entry_name != NULL);
231 entry = find_create_entry(config, entry_name);
232 assert(entry != NULL);
233 entry->perform_actual_lookups = flag;
235 TRACE_OUT(set_perform_actual_lookups);
238 static void
239 set_suggested_size(struct configuration *config,
240 const char *entry_name, int size)
242 struct configuration_entry *entry;
244 TRACE_IN(set_suggested_size);
245 assert(config != NULL);
246 assert(entry_name != NULL);
247 assert(size > 0);
249 entry = find_create_entry(config, entry_name);
250 assert(entry != NULL);
251 entry->positive_cache_params.cache_entries_size = size;
252 entry->negative_cache_params.cache_entries_size = size;
254 TRACE_OUT(set_suggested_size);
257 static void
258 check_files(struct configuration *config, const char *entry_name, int flag)
261 TRACE_IN(check_files);
262 assert(entry_name != NULL);
263 TRACE_OUT(check_files);
266 static int
267 get_yesno(const char *str)
270 if (strcmp(str, "yes") == 0)
271 return (1);
272 else if (strcmp(str, "no") == 0)
273 return (0);
274 else
275 return (-1);
278 static int
279 get_number(const char *str, int low, int max)
282 char *end = NULL;
283 int res = 0;
285 if (str[0] == '\0')
286 return (-1);
288 res = strtol(str, &end, 10);
289 if (*end != '\0')
290 return (-1);
291 else
292 if (((res >= low) || (low == -1)) &&
293 ((res <= max) || (max == -1)))
294 return (res);
295 else
296 return (-2);
299 static enum cache_policy_t
300 get_policy(const char *str)
303 if (strcmp(str, "fifo") == 0)
304 return (CPT_FIFO);
305 else if (strcmp(str, "lru") == 0)
306 return (CPT_LRU);
307 else if (strcmp(str, "lfu") == 0)
308 return (CPT_LFU);
310 return (-1);
313 static int
314 check_cachename(const char *str)
317 assert(str != NULL);
318 return ((strlen(str) > 0) ? 0 : -1);
321 static void
322 set_threads_num(struct configuration *config, int value)
325 assert(config != NULL);
326 config->threads_num = value;
330 * The main configuration routine. Its implementation is hugely inspired by the
331 * the same routine implementation in Solaris NSCD.
334 parse_config_file(struct configuration *config,
335 const char *fname, char const **error_str, int *error_line)
337 FILE *fin;
338 char buffer[255];
339 char *fields[128];
340 int field_count, line_num, value;
341 int res;
343 TRACE_IN(parse_config_file);
344 assert(config != NULL);
345 assert(fname != NULL);
347 fin = fopen(fname, "r");
348 if (fin == NULL) {
349 TRACE_OUT(parse_config_file);
350 return (-1);
353 res = 0;
354 line_num = 0;
355 memset(buffer, 0, sizeof(buffer));
356 while ((res == 0) && (fgets(buffer, sizeof(buffer) - 1, fin) != NULL)) {
357 field_count = strbreak(buffer, fields, sizeof(fields));
358 ++line_num;
360 if (field_count == 0)
361 continue;
363 switch (fields[0][0]) {
364 case '#':
365 case '\0':
366 continue;
367 case 'e':
368 if ((field_count == 3) &&
369 (strcmp(fields[0], "enable-cache") == 0) &&
370 (check_cachename(fields[1]) == 0) &&
371 ((value = get_yesno(fields[2])) != -1)) {
372 enable_cache(config, fields[1], value);
373 continue;
375 break;
376 case 'd':
377 if ((field_count == 2) &&
378 (strcmp(fields[0], "debug-level") == 0) &&
379 ((value = get_number(fields[1], 0, 10)) != -1)) {
380 continue;
382 break;
383 case 'p':
384 if ((field_count == 3) &&
385 (strcmp(fields[0], "positive-time-to-live") == 0) &&
386 (check_cachename(fields[1]) == 0) &&
387 ((value = get_number(fields[2], 0, -1)) != -1)) {
388 set_positive_time_to_live(config,
389 fields[1], value);
390 continue;
391 } else if ((field_count == 3) &&
392 (strcmp(fields[0], "positive-policy") == 0) &&
393 (check_cachename(fields[1]) == 0) &&
394 ((value = get_policy(fields[2])) != -1)) {
395 set_positive_policy(config, fields[1], value);
396 continue;
397 } else if ((field_count == 3) &&
398 (strcmp(fields[0], "perform-actual-lookups") == 0) &&
399 (check_cachename(fields[1]) == 0) &&
400 ((value = get_yesno(fields[2])) != -1)) {
401 set_perform_actual_lookups(config, fields[1],
402 value);
403 continue;
405 break;
406 case 'n':
407 if ((field_count == 3) &&
408 (strcmp(fields[0], "negative-time-to-live") == 0) &&
409 (check_cachename(fields[1]) == 0) &&
410 ((value = get_number(fields[2], 0, -1)) != -1)) {
411 set_negative_time_to_live(config,
412 fields[1], value);
413 continue;
414 } else if ((field_count == 3) &&
415 (strcmp(fields[0], "negative-policy") == 0) &&
416 (check_cachename(fields[1]) == 0) &&
417 ((value = get_policy(fields[2])) != -1)) {
418 set_negative_policy(config,
419 fields[1], value);
420 continue;
422 break;
423 case 's':
424 if ((field_count == 3) &&
425 (strcmp(fields[0], "suggested-size") == 0) &&
426 (check_cachename(fields[1]) == 0) &&
427 ((value = get_number(fields[2], 1, -1)) != -1)) {
428 set_suggested_size(config, fields[1], value);
429 continue;
431 break;
432 case 't':
433 if ((field_count == 2) &&
434 (strcmp(fields[0], "threads") == 0) &&
435 ((value = get_number(fields[1], 1, -1)) != -1)) {
436 set_threads_num(config, value);
437 continue;
439 break;
440 case 'k':
441 if ((field_count == 3) &&
442 (strcmp(fields[0], "keep-hot-count") == 0) &&
443 (check_cachename(fields[1]) == 0) &&
444 ((value = get_number(fields[2], 0, -1)) != -1)) {
445 set_keep_hot_count(config,
446 fields[1], value);
447 continue;
449 break;
450 case 'c':
451 if ((field_count == 3) &&
452 (strcmp(fields[0], "check-files") == 0) &&
453 (check_cachename(fields[1]) == 0) &&
454 ((value = get_yesno(fields[2])) != -1)) {
455 check_files(config,
456 fields[1], value);
457 continue;
459 break;
460 default:
461 break;
464 LOG_ERR_2("config file parser", "error in file "
465 "%s on line %d", fname, line_num);
466 *error_str = "syntax error";
467 *error_line = line_num;
468 res = -1;
470 fclose(fin);
472 TRACE_OUT(parse_config_file);
473 return (res);