2 * Copyright (c) 2005 Michael Bushkov <bushman@rsu.ru>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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
26 * $FreeBSD: src/usr.sbin/nscd/parser.c,v 1.2 2007/09/27 12:30:11 bushman Exp $
37 static void enable_cache(struct configuration
*,const char *, int);
38 static struct configuration_entry
*find_create_entry(struct configuration
*,
40 static int get_number(const char *, int, int);
41 static enum cache_policy_t
get_policy(const char *);
42 static int get_yesno(const char *);
43 static int check_cachename(const char *);
44 static void check_files(struct configuration
*, const char *, int);
45 static void set_keep_hot_count(struct configuration
*, const char *, int);
46 static void set_negative_policy(struct configuration
*, const char *,
48 static void set_negative_time_to_live(struct configuration
*,
50 static void set_positive_policy(struct configuration
*, const char *,
52 static void set_perform_actual_lookups(struct configuration
*, const char *,
54 static void set_positive_time_to_live(struct configuration
*,
56 static void set_suggested_size(struct configuration
*, const char *,
58 static void set_threads_num(struct configuration
*, int);
59 static int strbreak(char *, char **, int);
62 strbreak(char *str
, char **fields
, int fields_size
)
71 strsep(i
< fields_size
? &c
: NULL
, "\n\t ")) != NULL
);
73 if ((*(*fields
)) != '\0') {
83 * Tries to find the configuration entry with the specified name. If search
84 * fails, the new entry with the default parameters will be created.
86 static struct configuration_entry
*
87 find_create_entry(struct configuration
*config
,
88 const char *entry_name
)
90 struct configuration_entry
*entry
= NULL
;
93 TRACE_IN(find_create_entry
);
94 entry
= configuration_find_entry(config
, entry_name
);
96 entry
= create_def_configuration_entry(entry_name
);
97 assert( entry
!= NULL
);
98 res
= add_configuration_entry(config
, entry
);
102 TRACE_OUT(find_create_entry
);
107 * The vast majority of the functions below corresponds to the particular
108 * keywords in the configuration file.
111 enable_cache(struct configuration
*config
, const char *entry_name
, int flag
)
113 struct configuration_entry
*entry
;
115 TRACE_IN(enable_cache
);
116 entry
= find_create_entry(config
, entry_name
);
117 entry
->enabled
= flag
;
118 TRACE_OUT(enable_cache
);
122 set_positive_time_to_live(struct configuration
*config
,
123 const char *entry_name
, int ttl
)
125 struct configuration_entry
*entry
;
126 struct timeval lifetime
;
128 TRACE_IN(set_positive_time_to_live
);
130 assert(entry_name
!= NULL
);
131 memset(&lifetime
, 0, sizeof(struct timeval
));
132 lifetime
.tv_sec
= ttl
;
134 entry
= find_create_entry(config
, entry_name
);
135 memcpy(&entry
->positive_cache_params
.max_lifetime
,
136 &lifetime
, sizeof(struct timeval
));
137 memcpy(&entry
->mp_cache_params
.max_lifetime
,
138 &lifetime
, sizeof(struct timeval
));
140 TRACE_OUT(set_positive_time_to_live
);
144 set_negative_time_to_live(struct configuration
*config
,
145 const char *entry_name
, int nttl
)
147 struct configuration_entry
*entry
;
148 struct timeval lifetime
;
150 TRACE_IN(set_negative_time_to_live
);
152 assert(entry_name
!= NULL
);
153 memset(&lifetime
, 0, sizeof(struct timeval
));
154 lifetime
.tv_sec
= nttl
;
156 entry
= find_create_entry(config
, entry_name
);
157 assert(entry
!= NULL
);
158 memcpy(&entry
->negative_cache_params
.max_lifetime
,
159 &lifetime
, sizeof(struct timeval
));
161 TRACE_OUT(set_negative_time_to_live
);
165 * Hot count is actually the elements size limit.
168 set_keep_hot_count(struct configuration
*config
,
169 const char *entry_name
, int count
)
171 struct configuration_entry
*entry
;
173 TRACE_IN(set_keep_hot_count
);
175 assert(entry_name
!= NULL
);
177 entry
= find_create_entry(config
, entry_name
);
178 assert(entry
!= NULL
);
179 entry
->positive_cache_params
.max_elemsize
= count
;
181 entry
= find_create_entry(config
, entry_name
);
182 assert(entry
!= NULL
);
183 entry
->negative_cache_params
.max_elemsize
= count
;
185 TRACE_OUT(set_keep_hot_count
);
189 set_positive_policy(struct configuration
*config
,
190 const char *entry_name
, enum cache_policy_t policy
)
192 struct configuration_entry
*entry
;
194 TRACE_IN(set_positive_policy
);
195 assert(entry_name
!= NULL
);
197 entry
= find_create_entry(config
, entry_name
);
198 assert(entry
!= NULL
);
199 entry
->positive_cache_params
.policy
= policy
;
201 TRACE_OUT(set_positive_policy
);
205 set_negative_policy(struct configuration
*config
,
206 const char *entry_name
, enum cache_policy_t policy
)
208 struct configuration_entry
*entry
;
210 TRACE_IN(set_negative_policy
);
211 assert(entry_name
!= NULL
);
213 entry
= find_create_entry(config
, entry_name
);
214 assert(entry
!= NULL
);
215 entry
->negative_cache_params
.policy
= policy
;
217 TRACE_OUT(set_negative_policy
);
221 set_perform_actual_lookups(struct configuration
*config
,
222 const char *entry_name
, int flag
)
224 struct configuration_entry
*entry
;
226 TRACE_IN(set_perform_actual_lookups
);
227 assert(entry_name
!= NULL
);
229 entry
= find_create_entry(config
, entry_name
);
230 assert(entry
!= NULL
);
231 entry
->perform_actual_lookups
= flag
;
233 TRACE_OUT(set_perform_actual_lookups
);
237 set_suggested_size(struct configuration
*config
,
238 const char *entry_name
, int size
)
240 struct configuration_entry
*entry
;
242 TRACE_IN(set_suggested_size
);
243 assert(config
!= NULL
);
244 assert(entry_name
!= NULL
);
247 entry
= find_create_entry(config
, entry_name
);
248 assert(entry
!= NULL
);
249 entry
->positive_cache_params
.cache_entries_size
= size
;
250 entry
->negative_cache_params
.cache_entries_size
= size
;
252 TRACE_OUT(set_suggested_size
);
256 check_files(struct configuration
*config
, const char *entry_name
, int flag
)
259 TRACE_IN(check_files
);
260 assert(entry_name
!= NULL
);
261 TRACE_OUT(check_files
);
265 get_yesno(const char *str
)
268 if (strcmp(str
, "yes") == 0)
270 else if (strcmp(str
, "no") == 0)
277 get_number(const char *str
, int low
, int max
)
286 res
= strtol(str
, &end
, 10);
290 if (((res
>= low
) || (low
== -1)) &&
291 ((res
<= max
) || (max
== -1)))
297 static enum cache_policy_t
298 get_policy(const char *str
)
301 if (strcmp(str
, "fifo") == 0)
303 else if (strcmp(str
, "lru") == 0)
305 else if (strcmp(str
, "lfu") == 0)
312 check_cachename(const char *str
)
316 return ((strlen(str
) > 0) ? 0 : -1);
320 set_threads_num(struct configuration
*config
, int value
)
323 assert(config
!= NULL
);
324 config
->threads_num
= value
;
328 * The main configuration routine. Its implementation is hugely inspired by the
329 * the same routine implementation in Solaris NSCD.
332 parse_config_file(struct configuration
*config
,
333 const char *fname
, char const **error_str
, int *error_line
)
338 int field_count
, line_num
, value
;
341 TRACE_IN(parse_config_file
);
342 assert(config
!= NULL
);
343 assert(fname
!= NULL
);
345 fin
= fopen(fname
, "r");
347 TRACE_OUT(parse_config_file
);
353 memset(buffer
, 0, sizeof(buffer
));
354 while ((res
== 0) && (fgets(buffer
, sizeof(buffer
) - 1, fin
) != NULL
)) {
355 field_count
= strbreak(buffer
, fields
, sizeof(fields
));
358 if (field_count
== 0)
361 switch (fields
[0][0]) {
366 if ((field_count
== 3) &&
367 (strcmp(fields
[0], "enable-cache") == 0) &&
368 (check_cachename(fields
[1]) == 0) &&
369 ((value
= get_yesno(fields
[2])) != -1)) {
370 enable_cache(config
, fields
[1], value
);
375 if ((field_count
== 2) &&
376 (strcmp(fields
[0], "debug-level") == 0) &&
377 ((value
= get_number(fields
[1], 0, 10)) != -1)) {
382 if ((field_count
== 3) &&
383 (strcmp(fields
[0], "positive-time-to-live") == 0) &&
384 (check_cachename(fields
[1]) == 0) &&
385 ((value
= get_number(fields
[2], 0, -1)) != -1)) {
386 set_positive_time_to_live(config
,
389 } else if ((field_count
== 3) &&
390 (strcmp(fields
[0], "positive-policy") == 0) &&
391 (check_cachename(fields
[1]) == 0) &&
392 ((value
= get_policy(fields
[2])) != -1)) {
393 set_positive_policy(config
, fields
[1], value
);
395 } else if ((field_count
== 3) &&
396 (strcmp(fields
[0], "perform-actual-lookups") == 0) &&
397 (check_cachename(fields
[1]) == 0) &&
398 ((value
= get_yesno(fields
[2])) != -1)) {
399 set_perform_actual_lookups(config
, fields
[1],
405 if ((field_count
== 3) &&
406 (strcmp(fields
[0], "negative-time-to-live") == 0) &&
407 (check_cachename(fields
[1]) == 0) &&
408 ((value
= get_number(fields
[2], 0, -1)) != -1)) {
409 set_negative_time_to_live(config
,
412 } else if ((field_count
== 3) &&
413 (strcmp(fields
[0], "negative-policy") == 0) &&
414 (check_cachename(fields
[1]) == 0) &&
415 ((value
= get_policy(fields
[2])) != -1)) {
416 set_negative_policy(config
,
422 if ((field_count
== 3) &&
423 (strcmp(fields
[0], "suggested-size") == 0) &&
424 (check_cachename(fields
[1]) == 0) &&
425 ((value
= get_number(fields
[2], 1, -1)) != -1)) {
426 set_suggested_size(config
, fields
[1], value
);
431 if ((field_count
== 2) &&
432 (strcmp(fields
[0], "threads") == 0) &&
433 ((value
= get_number(fields
[1], 1, -1)) != -1)) {
434 set_threads_num(config
, value
);
439 if ((field_count
== 3) &&
440 (strcmp(fields
[0], "keep-hot-count") == 0) &&
441 (check_cachename(fields
[1]) == 0) &&
442 ((value
= get_number(fields
[2], 0, -1)) != -1)) {
443 set_keep_hot_count(config
,
449 if ((field_count
== 3) &&
450 (strcmp(fields
[0], "check-files") == 0) &&
451 (check_cachename(fields
[1]) == 0) &&
452 ((value
= get_yesno(fields
[2])) != -1)) {
462 LOG_ERR_2("config file parser", "error in file "
463 "%s on line %d", fname
, line_num
);
464 *error_str
= "syntax error";
465 *error_line
= line_num
;
470 TRACE_OUT(parse_config_file
);