xref: /freebsd/usr.sbin/nscd/parser.c (revision a397989d4ec948c5fe138e83bc997a4f37098fce)
106a99fe3SHajimu UMEMOTO /*-
206a99fe3SHajimu UMEMOTO  * Copyright (c) 2005 Michael Bushkov <bushman@rsu.ru>
306a99fe3SHajimu UMEMOTO  * All rights reserved.
406a99fe3SHajimu UMEMOTO  *
506a99fe3SHajimu UMEMOTO  * Redistribution and use in source and binary forms, with or without
606a99fe3SHajimu UMEMOTO  * modification, are permitted provided that the following conditions
706a99fe3SHajimu UMEMOTO  * are met:
806a99fe3SHajimu UMEMOTO  * 1. Redistributions of source code must retain the above copyright
906a99fe3SHajimu UMEMOTO  *    notice, this list of conditions and the following disclaimer.
1006a99fe3SHajimu UMEMOTO  * 2. Redistributions in binary form must reproduce the above copyright
1106a99fe3SHajimu UMEMOTO  *    notice, this list of conditions and the following disclaimer in the
1206a99fe3SHajimu UMEMOTO  *    documentation and/or other materials provided with the distribution.
1306a99fe3SHajimu UMEMOTO  *
1406a99fe3SHajimu UMEMOTO  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1506a99fe3SHajimu UMEMOTO  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1606a99fe3SHajimu UMEMOTO  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1706a99fe3SHajimu UMEMOTO  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1806a99fe3SHajimu UMEMOTO  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1906a99fe3SHajimu UMEMOTO  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2006a99fe3SHajimu UMEMOTO  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2106a99fe3SHajimu UMEMOTO  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2206a99fe3SHajimu UMEMOTO  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2306a99fe3SHajimu UMEMOTO  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2406a99fe3SHajimu UMEMOTO  * SUCH DAMAGE.
2506a99fe3SHajimu UMEMOTO  *
2606a99fe3SHajimu UMEMOTO  */
2706a99fe3SHajimu UMEMOTO 
2806a99fe3SHajimu UMEMOTO #include <sys/cdefs.h>
2906a99fe3SHajimu UMEMOTO __FBSDID("$FreeBSD$");
3006a99fe3SHajimu UMEMOTO 
3128f805ceSDag-Erling Smørgrav #include <sys/time.h>
3228f805ceSDag-Erling Smørgrav 
3306a99fe3SHajimu UMEMOTO #include <assert.h>
3406a99fe3SHajimu UMEMOTO #include <stdio.h>
3528f805ceSDag-Erling Smørgrav #include <stdlib.h>
3606a99fe3SHajimu UMEMOTO #include <string.h>
3728f805ceSDag-Erling Smørgrav 
3806a99fe3SHajimu UMEMOTO #include "config.h"
3906a99fe3SHajimu UMEMOTO #include "debug.h"
4006a99fe3SHajimu UMEMOTO #include "log.h"
4106a99fe3SHajimu UMEMOTO #include "parser.h"
4206a99fe3SHajimu UMEMOTO 
4306a99fe3SHajimu UMEMOTO static void enable_cache(struct configuration *,const char *, int);
4406a99fe3SHajimu UMEMOTO static struct configuration_entry *find_create_entry(struct configuration *,
4506a99fe3SHajimu UMEMOTO 	const char *);
4606a99fe3SHajimu UMEMOTO static int get_number(const char *, int, int);
4706a99fe3SHajimu UMEMOTO static enum cache_policy_t get_policy(const char *);
4806a99fe3SHajimu UMEMOTO static int get_yesno(const char *);
4906a99fe3SHajimu UMEMOTO static int check_cachename(const char *);
5006a99fe3SHajimu UMEMOTO static void check_files(struct configuration *, const char *, int);
5106a99fe3SHajimu UMEMOTO static void set_keep_hot_count(struct configuration *, const char *, int);
5206a99fe3SHajimu UMEMOTO static void set_negative_policy(struct configuration *, const char *,
5306a99fe3SHajimu UMEMOTO 	enum cache_policy_t);
5406a99fe3SHajimu UMEMOTO static void set_negative_time_to_live(struct configuration *,
5506a99fe3SHajimu UMEMOTO 	const char *, int);
5606a99fe3SHajimu UMEMOTO static void set_positive_policy(struct configuration *, const char *,
5706a99fe3SHajimu UMEMOTO 	enum cache_policy_t);
5806a99fe3SHajimu UMEMOTO static void set_perform_actual_lookups(struct configuration *, const char *,
5906a99fe3SHajimu UMEMOTO 	int);
6006a99fe3SHajimu UMEMOTO static void set_positive_time_to_live(struct configuration *,
6106a99fe3SHajimu UMEMOTO 	const char *, int);
6206a99fe3SHajimu UMEMOTO static void set_suggested_size(struct configuration *, const char *,
6306a99fe3SHajimu UMEMOTO 	int size);
6406a99fe3SHajimu UMEMOTO static void set_threads_num(struct configuration *, int);
6506a99fe3SHajimu UMEMOTO static int strbreak(char *, char **, int);
6606a99fe3SHajimu UMEMOTO 
6706a99fe3SHajimu UMEMOTO static int
6806a99fe3SHajimu UMEMOTO strbreak(char *str, char **fields, int fields_size)
6906a99fe3SHajimu UMEMOTO {
7006a99fe3SHajimu UMEMOTO 	char	*c = str;
7106a99fe3SHajimu UMEMOTO 	int	i, num;
7206a99fe3SHajimu UMEMOTO 
7306a99fe3SHajimu UMEMOTO 	TRACE_IN(strbreak);
7406a99fe3SHajimu UMEMOTO 	num = 0;
7506a99fe3SHajimu UMEMOTO 	for (i = 0;
7606a99fe3SHajimu UMEMOTO 	     ((*fields =
7706a99fe3SHajimu UMEMOTO 	     	strsep(i < fields_size ? &c : NULL, "\n\t ")) != NULL);
7806a99fe3SHajimu UMEMOTO 	     ++i)
7906a99fe3SHajimu UMEMOTO 		if ((*(*fields)) != '\0') {
8006a99fe3SHajimu UMEMOTO 			++fields;
8106a99fe3SHajimu UMEMOTO 			++num;
8206a99fe3SHajimu UMEMOTO 		}
8306a99fe3SHajimu UMEMOTO 
8406a99fe3SHajimu UMEMOTO 	TRACE_OUT(strbreak);
8506a99fe3SHajimu UMEMOTO 	return (num);
8606a99fe3SHajimu UMEMOTO }
8706a99fe3SHajimu UMEMOTO 
8806a99fe3SHajimu UMEMOTO /*
8906a99fe3SHajimu UMEMOTO  * Tries to find the configuration entry with the specified name. If search
9006a99fe3SHajimu UMEMOTO  * fails, the new entry with the default parameters will be created.
9106a99fe3SHajimu UMEMOTO  */
9206a99fe3SHajimu UMEMOTO static struct configuration_entry *
9306a99fe3SHajimu UMEMOTO find_create_entry(struct configuration *config,
9406a99fe3SHajimu UMEMOTO 	const char *entry_name)
9506a99fe3SHajimu UMEMOTO {
9606a99fe3SHajimu UMEMOTO 	struct configuration_entry *entry = NULL;
9706a99fe3SHajimu UMEMOTO 	int res;
9806a99fe3SHajimu UMEMOTO 
9906a99fe3SHajimu UMEMOTO 	TRACE_IN(find_create_entry);
10006a99fe3SHajimu UMEMOTO 	entry = configuration_find_entry(config, entry_name);
10106a99fe3SHajimu UMEMOTO 	if (entry == NULL) {
10206a99fe3SHajimu UMEMOTO 		entry = create_def_configuration_entry(entry_name);
10306a99fe3SHajimu UMEMOTO 		assert( entry != NULL);
10406a99fe3SHajimu UMEMOTO 		res = add_configuration_entry(config, entry);
10506a99fe3SHajimu UMEMOTO 		assert(res == 0);
10606a99fe3SHajimu UMEMOTO 	}
10706a99fe3SHajimu UMEMOTO 
10806a99fe3SHajimu UMEMOTO 	TRACE_OUT(find_create_entry);
10906a99fe3SHajimu UMEMOTO 	return (entry);
11006a99fe3SHajimu UMEMOTO }
11106a99fe3SHajimu UMEMOTO 
11206a99fe3SHajimu UMEMOTO /*
11306a99fe3SHajimu UMEMOTO  * The vast majority of the functions below corresponds to the particular
11406a99fe3SHajimu UMEMOTO  * keywords in the configuration file.
11506a99fe3SHajimu UMEMOTO  */
11606a99fe3SHajimu UMEMOTO static void
11706a99fe3SHajimu UMEMOTO enable_cache(struct configuration *config, const char *entry_name, int flag)
11806a99fe3SHajimu UMEMOTO {
11906a99fe3SHajimu UMEMOTO 	struct configuration_entry	*entry;
12006a99fe3SHajimu UMEMOTO 
12106a99fe3SHajimu UMEMOTO 	TRACE_IN(enable_cache);
12206a99fe3SHajimu UMEMOTO 	entry = find_create_entry(config, entry_name);
12306a99fe3SHajimu UMEMOTO 	entry->enabled = flag;
12406a99fe3SHajimu UMEMOTO 	TRACE_OUT(enable_cache);
12506a99fe3SHajimu UMEMOTO }
12606a99fe3SHajimu UMEMOTO 
12706a99fe3SHajimu UMEMOTO static void
12806a99fe3SHajimu UMEMOTO set_positive_time_to_live(struct configuration *config,
12906a99fe3SHajimu UMEMOTO 	const char *entry_name, int ttl)
13006a99fe3SHajimu UMEMOTO {
13106a99fe3SHajimu UMEMOTO 	struct configuration_entry *entry;
13206a99fe3SHajimu UMEMOTO 	struct timeval lifetime;
13306a99fe3SHajimu UMEMOTO 
13406a99fe3SHajimu UMEMOTO 	TRACE_IN(set_positive_time_to_live);
13506a99fe3SHajimu UMEMOTO 	assert(ttl >= 0);
13606a99fe3SHajimu UMEMOTO 	assert(entry_name != NULL);
13706a99fe3SHajimu UMEMOTO 	memset(&lifetime, 0, sizeof(struct timeval));
13806a99fe3SHajimu UMEMOTO 	lifetime.tv_sec = ttl;
13906a99fe3SHajimu UMEMOTO 
14006a99fe3SHajimu UMEMOTO 	entry = find_create_entry(config, entry_name);
14106a99fe3SHajimu UMEMOTO 	memcpy(&entry->positive_cache_params.max_lifetime,
14206a99fe3SHajimu UMEMOTO 		&lifetime, sizeof(struct timeval));
14306a99fe3SHajimu UMEMOTO 	memcpy(&entry->mp_cache_params.max_lifetime,
14406a99fe3SHajimu UMEMOTO 		&lifetime, sizeof(struct timeval));
14506a99fe3SHajimu UMEMOTO 
14606a99fe3SHajimu UMEMOTO 	TRACE_OUT(set_positive_time_to_live);
14706a99fe3SHajimu UMEMOTO }
14806a99fe3SHajimu UMEMOTO 
14906a99fe3SHajimu UMEMOTO static void
15006a99fe3SHajimu UMEMOTO set_negative_time_to_live(struct configuration *config,
15106a99fe3SHajimu UMEMOTO 	const char *entry_name, int nttl)
15206a99fe3SHajimu UMEMOTO {
15306a99fe3SHajimu UMEMOTO 	struct configuration_entry *entry;
15406a99fe3SHajimu UMEMOTO 	struct timeval lifetime;
15506a99fe3SHajimu UMEMOTO 
15606a99fe3SHajimu UMEMOTO 	TRACE_IN(set_negative_time_to_live);
15706a99fe3SHajimu UMEMOTO 	assert(nttl > 0);
15806a99fe3SHajimu UMEMOTO 	assert(entry_name != NULL);
15906a99fe3SHajimu UMEMOTO 	memset(&lifetime, 0, sizeof(struct timeval));
16006a99fe3SHajimu UMEMOTO 	lifetime.tv_sec = nttl;
16106a99fe3SHajimu UMEMOTO 
16206a99fe3SHajimu UMEMOTO 	entry = find_create_entry(config, entry_name);
16306a99fe3SHajimu UMEMOTO 	assert(entry != NULL);
16406a99fe3SHajimu UMEMOTO 	memcpy(&entry->negative_cache_params.max_lifetime,
16506a99fe3SHajimu UMEMOTO 		&lifetime, sizeof(struct timeval));
16606a99fe3SHajimu UMEMOTO 
16706a99fe3SHajimu UMEMOTO 	TRACE_OUT(set_negative_time_to_live);
16806a99fe3SHajimu UMEMOTO }
16906a99fe3SHajimu UMEMOTO 
170*a397989dSStefan Eßer static void
171*a397989dSStefan Eßer set_positive_confidence_threshold(struct configuration *config,
172*a397989dSStefan Eßer 	const char *entry_name, int conf_thresh)
173*a397989dSStefan Eßer {
174*a397989dSStefan Eßer 	struct configuration_entry *entry;
175*a397989dSStefan Eßer 
176*a397989dSStefan Eßer 	TRACE_IN(set_positive_conf_thresh);
177*a397989dSStefan Eßer 	assert(conf_thresh > 0);
178*a397989dSStefan Eßer 	assert(entry_name != NULL);
179*a397989dSStefan Eßer 
180*a397989dSStefan Eßer 	entry = find_create_entry(config, entry_name);
181*a397989dSStefan Eßer 	assert(entry != NULL);
182*a397989dSStefan Eßer 	entry->positive_cache_params.confidence_threshold = conf_thresh;
183*a397989dSStefan Eßer 
184*a397989dSStefan Eßer 	TRACE_OUT(set_positive_conf_thresh);
185*a397989dSStefan Eßer }
186*a397989dSStefan Eßer 
187*a397989dSStefan Eßer static void
188*a397989dSStefan Eßer set_negative_confidence_threshold(struct configuration *config,
189*a397989dSStefan Eßer 	const char *entry_name, int conf_thresh)
190*a397989dSStefan Eßer {
191*a397989dSStefan Eßer 	struct configuration_entry *entry;
192*a397989dSStefan Eßer 
193*a397989dSStefan Eßer 	TRACE_IN(set_negative_conf_thresh);
194*a397989dSStefan Eßer 	assert(conf_thresh > 0);
195*a397989dSStefan Eßer 	assert(entry_name != NULL);
196*a397989dSStefan Eßer 	entry = find_create_entry(config, entry_name);
197*a397989dSStefan Eßer 	assert(entry != NULL);
198*a397989dSStefan Eßer 	entry->negative_cache_params.confidence_threshold = conf_thresh;
199*a397989dSStefan Eßer 	TRACE_OUT(set_negative_conf_thresh);
200*a397989dSStefan Eßer }
201*a397989dSStefan Eßer 
20206a99fe3SHajimu UMEMOTO /*
20306a99fe3SHajimu UMEMOTO  * Hot count is actually the elements size limit.
20406a99fe3SHajimu UMEMOTO  */
20506a99fe3SHajimu UMEMOTO static void
20606a99fe3SHajimu UMEMOTO set_keep_hot_count(struct configuration *config,
20706a99fe3SHajimu UMEMOTO 	const char *entry_name, int count)
20806a99fe3SHajimu UMEMOTO {
20906a99fe3SHajimu UMEMOTO 	struct configuration_entry *entry;
21006a99fe3SHajimu UMEMOTO 
21106a99fe3SHajimu UMEMOTO 	TRACE_IN(set_keep_hot_count);
21206a99fe3SHajimu UMEMOTO 	assert(count >= 0);
21306a99fe3SHajimu UMEMOTO 	assert(entry_name != NULL);
21406a99fe3SHajimu UMEMOTO 
21506a99fe3SHajimu UMEMOTO 	entry = find_create_entry(config, entry_name);
21606a99fe3SHajimu UMEMOTO 	assert(entry != NULL);
21706a99fe3SHajimu UMEMOTO 	entry->positive_cache_params.max_elemsize = count;
21806a99fe3SHajimu UMEMOTO 
21906a99fe3SHajimu UMEMOTO 	entry = find_create_entry(config, entry_name);
22006a99fe3SHajimu UMEMOTO 	assert(entry != NULL);
22106a99fe3SHajimu UMEMOTO 	entry->negative_cache_params.max_elemsize = count;
22206a99fe3SHajimu UMEMOTO 
22306a99fe3SHajimu UMEMOTO 	TRACE_OUT(set_keep_hot_count);
22406a99fe3SHajimu UMEMOTO }
22506a99fe3SHajimu UMEMOTO 
22606a99fe3SHajimu UMEMOTO static void
22706a99fe3SHajimu UMEMOTO set_positive_policy(struct configuration *config,
22806a99fe3SHajimu UMEMOTO 	const char *entry_name, enum cache_policy_t policy)
22906a99fe3SHajimu UMEMOTO {
23006a99fe3SHajimu UMEMOTO 	struct configuration_entry *entry;
23106a99fe3SHajimu UMEMOTO 
23206a99fe3SHajimu UMEMOTO 	TRACE_IN(set_positive_policy);
23306a99fe3SHajimu UMEMOTO 	assert(entry_name != NULL);
23406a99fe3SHajimu UMEMOTO 
23506a99fe3SHajimu UMEMOTO 	entry = find_create_entry(config, entry_name);
23606a99fe3SHajimu UMEMOTO 	assert(entry != NULL);
23706a99fe3SHajimu UMEMOTO 	entry->positive_cache_params.policy = policy;
23806a99fe3SHajimu UMEMOTO 
23906a99fe3SHajimu UMEMOTO 	TRACE_OUT(set_positive_policy);
24006a99fe3SHajimu UMEMOTO }
24106a99fe3SHajimu UMEMOTO 
24206a99fe3SHajimu UMEMOTO static void
24306a99fe3SHajimu UMEMOTO set_negative_policy(struct configuration *config,
24406a99fe3SHajimu UMEMOTO 	const char *entry_name, enum cache_policy_t policy)
24506a99fe3SHajimu UMEMOTO {
24606a99fe3SHajimu UMEMOTO 	struct configuration_entry *entry;
24706a99fe3SHajimu UMEMOTO 
24806a99fe3SHajimu UMEMOTO 	TRACE_IN(set_negative_policy);
24906a99fe3SHajimu UMEMOTO 	assert(entry_name != NULL);
25006a99fe3SHajimu UMEMOTO 
25106a99fe3SHajimu UMEMOTO 	entry = find_create_entry(config, entry_name);
25206a99fe3SHajimu UMEMOTO 	assert(entry != NULL);
25306a99fe3SHajimu UMEMOTO 	entry->negative_cache_params.policy = policy;
25406a99fe3SHajimu UMEMOTO 
25506a99fe3SHajimu UMEMOTO 	TRACE_OUT(set_negative_policy);
25606a99fe3SHajimu UMEMOTO }
25706a99fe3SHajimu UMEMOTO 
25806a99fe3SHajimu UMEMOTO static void
25906a99fe3SHajimu UMEMOTO set_perform_actual_lookups(struct configuration *config,
26006a99fe3SHajimu UMEMOTO 	const char *entry_name, int flag)
26106a99fe3SHajimu UMEMOTO {
26206a99fe3SHajimu UMEMOTO 	struct configuration_entry *entry;
26306a99fe3SHajimu UMEMOTO 
26406a99fe3SHajimu UMEMOTO 	TRACE_IN(set_perform_actual_lookups);
26506a99fe3SHajimu UMEMOTO 	assert(entry_name != NULL);
26606a99fe3SHajimu UMEMOTO 
26706a99fe3SHajimu UMEMOTO 	entry = find_create_entry(config, entry_name);
26806a99fe3SHajimu UMEMOTO 	assert(entry != NULL);
26906a99fe3SHajimu UMEMOTO 	entry->perform_actual_lookups = flag;
27006a99fe3SHajimu UMEMOTO 
27106a99fe3SHajimu UMEMOTO 	TRACE_OUT(set_perform_actual_lookups);
27206a99fe3SHajimu UMEMOTO }
27306a99fe3SHajimu UMEMOTO 
27406a99fe3SHajimu UMEMOTO static void
27506a99fe3SHajimu UMEMOTO set_suggested_size(struct configuration *config,
27606a99fe3SHajimu UMEMOTO 	const char *entry_name, int size)
27706a99fe3SHajimu UMEMOTO {
27806a99fe3SHajimu UMEMOTO 	struct configuration_entry	*entry;
27906a99fe3SHajimu UMEMOTO 
28006a99fe3SHajimu UMEMOTO 	TRACE_IN(set_suggested_size);
28106a99fe3SHajimu UMEMOTO 	assert(config != NULL);
28206a99fe3SHajimu UMEMOTO 	assert(entry_name != NULL);
28306a99fe3SHajimu UMEMOTO 	assert(size > 0);
28406a99fe3SHajimu UMEMOTO 
28506a99fe3SHajimu UMEMOTO 	entry = find_create_entry(config, entry_name);
28606a99fe3SHajimu UMEMOTO 	assert(entry != NULL);
28706a99fe3SHajimu UMEMOTO 	entry->positive_cache_params.cache_entries_size = size;
28806a99fe3SHajimu UMEMOTO 	entry->negative_cache_params.cache_entries_size = size;
28906a99fe3SHajimu UMEMOTO 
29006a99fe3SHajimu UMEMOTO 	TRACE_OUT(set_suggested_size);
29106a99fe3SHajimu UMEMOTO }
29206a99fe3SHajimu UMEMOTO 
29306a99fe3SHajimu UMEMOTO static void
29406a99fe3SHajimu UMEMOTO check_files(struct configuration *config, const char *entry_name, int flag)
29506a99fe3SHajimu UMEMOTO {
29606a99fe3SHajimu UMEMOTO 
29706a99fe3SHajimu UMEMOTO 	TRACE_IN(check_files);
29806a99fe3SHajimu UMEMOTO 	assert(entry_name != NULL);
29906a99fe3SHajimu UMEMOTO 	TRACE_OUT(check_files);
30006a99fe3SHajimu UMEMOTO }
30106a99fe3SHajimu UMEMOTO 
30206a99fe3SHajimu UMEMOTO static int
30306a99fe3SHajimu UMEMOTO get_yesno(const char *str)
30406a99fe3SHajimu UMEMOTO {
30506a99fe3SHajimu UMEMOTO 
30606a99fe3SHajimu UMEMOTO 	if (strcmp(str, "yes") == 0)
30706a99fe3SHajimu UMEMOTO 		return (1);
30806a99fe3SHajimu UMEMOTO 	else if (strcmp(str, "no") == 0)
30906a99fe3SHajimu UMEMOTO 		return (0);
31006a99fe3SHajimu UMEMOTO 	else
31106a99fe3SHajimu UMEMOTO 		return (-1);
31206a99fe3SHajimu UMEMOTO }
31306a99fe3SHajimu UMEMOTO 
31406a99fe3SHajimu UMEMOTO static int
31506a99fe3SHajimu UMEMOTO get_number(const char *str, int low, int max)
31606a99fe3SHajimu UMEMOTO {
31706a99fe3SHajimu UMEMOTO 
31806a99fe3SHajimu UMEMOTO 	char *end = NULL;
31906a99fe3SHajimu UMEMOTO 	int res = 0;
32006a99fe3SHajimu UMEMOTO 
32106a99fe3SHajimu UMEMOTO 	if (str[0] == '\0')
32206a99fe3SHajimu UMEMOTO 		return (-1);
32306a99fe3SHajimu UMEMOTO 
32406a99fe3SHajimu UMEMOTO 	res = strtol(str, &end, 10);
32506a99fe3SHajimu UMEMOTO 	if (*end != '\0')
32606a99fe3SHajimu UMEMOTO 		return (-1);
32706a99fe3SHajimu UMEMOTO 	else
32806a99fe3SHajimu UMEMOTO 		if (((res >= low) || (low == -1)) &&
32906a99fe3SHajimu UMEMOTO 			((res <= max) || (max == -1)))
33006a99fe3SHajimu UMEMOTO 			return (res);
33106a99fe3SHajimu UMEMOTO 		else
33206a99fe3SHajimu UMEMOTO 			return (-2);
33306a99fe3SHajimu UMEMOTO }
33406a99fe3SHajimu UMEMOTO 
33506a99fe3SHajimu UMEMOTO static enum cache_policy_t
33606a99fe3SHajimu UMEMOTO get_policy(const char *str)
33706a99fe3SHajimu UMEMOTO {
33806a99fe3SHajimu UMEMOTO 
33906a99fe3SHajimu UMEMOTO 	if (strcmp(str, "fifo") == 0)
34006a99fe3SHajimu UMEMOTO 		return (CPT_FIFO);
34106a99fe3SHajimu UMEMOTO 	else if (strcmp(str, "lru") == 0)
34206a99fe3SHajimu UMEMOTO 		return (CPT_LRU);
34306a99fe3SHajimu UMEMOTO 	else if (strcmp(str, "lfu") == 0)
34406a99fe3SHajimu UMEMOTO 		return (CPT_LFU);
34506a99fe3SHajimu UMEMOTO 
34606a99fe3SHajimu UMEMOTO 	return (-1);
34706a99fe3SHajimu UMEMOTO }
34806a99fe3SHajimu UMEMOTO 
34906a99fe3SHajimu UMEMOTO static int
35006a99fe3SHajimu UMEMOTO check_cachename(const char *str)
35106a99fe3SHajimu UMEMOTO {
35206a99fe3SHajimu UMEMOTO 
35306a99fe3SHajimu UMEMOTO 	assert(str != NULL);
35406a99fe3SHajimu UMEMOTO 	return ((strlen(str) > 0) ? 0 : -1);
35506a99fe3SHajimu UMEMOTO }
35606a99fe3SHajimu UMEMOTO 
35706a99fe3SHajimu UMEMOTO static void
35806a99fe3SHajimu UMEMOTO set_threads_num(struct configuration *config, int value)
35906a99fe3SHajimu UMEMOTO {
36006a99fe3SHajimu UMEMOTO 
36106a99fe3SHajimu UMEMOTO 	assert(config != NULL);
36206a99fe3SHajimu UMEMOTO 	config->threads_num = value;
36306a99fe3SHajimu UMEMOTO }
36406a99fe3SHajimu UMEMOTO 
36506a99fe3SHajimu UMEMOTO /*
36606a99fe3SHajimu UMEMOTO  * The main configuration routine. Its implementation is hugely inspired by the
36706a99fe3SHajimu UMEMOTO  * the same routine implementation in Solaris NSCD.
36806a99fe3SHajimu UMEMOTO  */
36906a99fe3SHajimu UMEMOTO int
37006a99fe3SHajimu UMEMOTO parse_config_file(struct configuration *config,
37106a99fe3SHajimu UMEMOTO 	const char *fname, char const **error_str, int *error_line)
37206a99fe3SHajimu UMEMOTO {
37306a99fe3SHajimu UMEMOTO 	FILE	*fin;
37406a99fe3SHajimu UMEMOTO 	char	buffer[255];
37506a99fe3SHajimu UMEMOTO 	char	*fields[128];
37606a99fe3SHajimu UMEMOTO 	int	field_count, line_num, value;
37706a99fe3SHajimu UMEMOTO 	int	res;
37806a99fe3SHajimu UMEMOTO 
37906a99fe3SHajimu UMEMOTO 	TRACE_IN(parse_config_file);
38006a99fe3SHajimu UMEMOTO 	assert(config != NULL);
38106a99fe3SHajimu UMEMOTO 	assert(fname != NULL);
38206a99fe3SHajimu UMEMOTO 
38306a99fe3SHajimu UMEMOTO 	fin = fopen(fname, "r");
38406a99fe3SHajimu UMEMOTO 	if (fin == NULL) {
38506a99fe3SHajimu UMEMOTO 		TRACE_OUT(parse_config_file);
38606a99fe3SHajimu UMEMOTO 		return (-1);
38706a99fe3SHajimu UMEMOTO 	}
38806a99fe3SHajimu UMEMOTO 
38906a99fe3SHajimu UMEMOTO 	res = 0;
39006a99fe3SHajimu UMEMOTO 	line_num = 0;
39106a99fe3SHajimu UMEMOTO 	memset(buffer, 0, sizeof(buffer));
39206a99fe3SHajimu UMEMOTO 	while ((res == 0) && (fgets(buffer, sizeof(buffer) - 1, fin) != NULL)) {
39306a99fe3SHajimu UMEMOTO 		field_count = strbreak(buffer, fields, sizeof(fields));
39406a99fe3SHajimu UMEMOTO 		++line_num;
39506a99fe3SHajimu UMEMOTO 
39606a99fe3SHajimu UMEMOTO 		if (field_count == 0)
39706a99fe3SHajimu UMEMOTO 			continue;
39806a99fe3SHajimu UMEMOTO 
39906a99fe3SHajimu UMEMOTO 		switch (fields[0][0]) {
40006a99fe3SHajimu UMEMOTO 		case '#':
40106a99fe3SHajimu UMEMOTO 		case '\0':
40206a99fe3SHajimu UMEMOTO 			continue;
40306a99fe3SHajimu UMEMOTO 		case 'e':
40406a99fe3SHajimu UMEMOTO 			if ((field_count == 3) &&
40506a99fe3SHajimu UMEMOTO 			(strcmp(fields[0], "enable-cache") == 0) &&
40606a99fe3SHajimu UMEMOTO 			(check_cachename(fields[1]) == 0) &&
40706a99fe3SHajimu UMEMOTO 			((value = get_yesno(fields[2])) != -1)) {
40806a99fe3SHajimu UMEMOTO 				enable_cache(config, fields[1], value);
40906a99fe3SHajimu UMEMOTO 				continue;
41006a99fe3SHajimu UMEMOTO 			}
41106a99fe3SHajimu UMEMOTO 			break;
41206a99fe3SHajimu UMEMOTO 		case 'd':
41306a99fe3SHajimu UMEMOTO 			if ((field_count == 2) &&
41406a99fe3SHajimu UMEMOTO 			(strcmp(fields[0], "debug-level") == 0) &&
41506a99fe3SHajimu UMEMOTO 			((value = get_number(fields[1], 0, 10)) != -1)) {
41606a99fe3SHajimu UMEMOTO 				continue;
41706a99fe3SHajimu UMEMOTO 			}
41806a99fe3SHajimu UMEMOTO 			break;
41906a99fe3SHajimu UMEMOTO 		case 'p':
42006a99fe3SHajimu UMEMOTO 			if ((field_count == 3) &&
42106a99fe3SHajimu UMEMOTO 			(strcmp(fields[0], "positive-time-to-live") == 0) &&
42206a99fe3SHajimu UMEMOTO 			(check_cachename(fields[1]) == 0) &&
42306a99fe3SHajimu UMEMOTO 			((value = get_number(fields[2], 0, -1)) != -1)) {
42406a99fe3SHajimu UMEMOTO 				set_positive_time_to_live(config,
42506a99fe3SHajimu UMEMOTO 					fields[1], value);
42606a99fe3SHajimu UMEMOTO 				continue;
42706a99fe3SHajimu UMEMOTO 			} else if ((field_count == 3) &&
428*a397989dSStefan Eßer 			(strcmp(fields[0], "positive-confidence-threshold") == 0) &&
429*a397989dSStefan Eßer 			((value = get_number(fields[2], 1, -1)) != -1)) {
430*a397989dSStefan Eßer 				set_positive_confidence_threshold(config,
431*a397989dSStefan Eßer 					fields[1], value);
432*a397989dSStefan Eßer 				continue;
433*a397989dSStefan Eßer 			} else if ((field_count == 3) &&
43406a99fe3SHajimu UMEMOTO 			(strcmp(fields[0], "positive-policy") == 0) &&
43506a99fe3SHajimu UMEMOTO 			(check_cachename(fields[1]) == 0) &&
43606a99fe3SHajimu UMEMOTO 			((value = get_policy(fields[2])) != -1)) {
43706a99fe3SHajimu UMEMOTO 				set_positive_policy(config, fields[1], value);
43806a99fe3SHajimu UMEMOTO 				continue;
43906a99fe3SHajimu UMEMOTO 			} else if ((field_count == 3) &&
44006a99fe3SHajimu UMEMOTO 			(strcmp(fields[0], "perform-actual-lookups") == 0) &&
44106a99fe3SHajimu UMEMOTO 			(check_cachename(fields[1]) == 0) &&
44206a99fe3SHajimu UMEMOTO 			((value = get_yesno(fields[2])) != -1)) {
44306a99fe3SHajimu UMEMOTO 				set_perform_actual_lookups(config, fields[1],
44406a99fe3SHajimu UMEMOTO 					value);
44506a99fe3SHajimu UMEMOTO 				continue;
44606a99fe3SHajimu UMEMOTO 			}
44706a99fe3SHajimu UMEMOTO 			break;
44806a99fe3SHajimu UMEMOTO 		case 'n':
44906a99fe3SHajimu UMEMOTO 			if ((field_count == 3) &&
45006a99fe3SHajimu UMEMOTO 			(strcmp(fields[0], "negative-time-to-live") == 0) &&
45106a99fe3SHajimu UMEMOTO 			(check_cachename(fields[1]) == 0) &&
45206a99fe3SHajimu UMEMOTO 			((value = get_number(fields[2], 0, -1)) != -1)) {
45306a99fe3SHajimu UMEMOTO 				set_negative_time_to_live(config,
45406a99fe3SHajimu UMEMOTO 					fields[1], value);
45506a99fe3SHajimu UMEMOTO 				continue;
45606a99fe3SHajimu UMEMOTO 			} else if ((field_count == 3) &&
457*a397989dSStefan Eßer 			(strcmp(fields[0], "negative-confidence-threshold") == 0) &&
458*a397989dSStefan Eßer 			((value = get_number(fields[2], 1, -1)) != -1)) {
459*a397989dSStefan Eßer 				set_negative_confidence_threshold(config,
460*a397989dSStefan Eßer 					fields[1], value);
461*a397989dSStefan Eßer 				continue;
462*a397989dSStefan Eßer 			} else if ((field_count == 3) &&
46306a99fe3SHajimu UMEMOTO 			(strcmp(fields[0], "negative-policy") == 0) &&
46406a99fe3SHajimu UMEMOTO 			(check_cachename(fields[1]) == 0) &&
46506a99fe3SHajimu UMEMOTO 			((value = get_policy(fields[2])) != -1)) {
46606a99fe3SHajimu UMEMOTO 				set_negative_policy(config,
46706a99fe3SHajimu UMEMOTO 					fields[1], value);
46806a99fe3SHajimu UMEMOTO 				continue;
46906a99fe3SHajimu UMEMOTO 			}
47006a99fe3SHajimu UMEMOTO 			break;
47106a99fe3SHajimu UMEMOTO 		case 's':
47206a99fe3SHajimu UMEMOTO 			if ((field_count == 3) &&
47306a99fe3SHajimu UMEMOTO 			(strcmp(fields[0], "suggested-size") == 0) &&
47406a99fe3SHajimu UMEMOTO 			(check_cachename(fields[1]) == 0) &&
47506a99fe3SHajimu UMEMOTO 			((value = get_number(fields[2], 1, -1)) != -1)) {
47606a99fe3SHajimu UMEMOTO 				set_suggested_size(config, fields[1], value);
47706a99fe3SHajimu UMEMOTO 				continue;
47806a99fe3SHajimu UMEMOTO 			}
47906a99fe3SHajimu UMEMOTO 			break;
48006a99fe3SHajimu UMEMOTO 		case 't':
48106a99fe3SHajimu UMEMOTO 			if ((field_count == 2) &&
48206a99fe3SHajimu UMEMOTO 			(strcmp(fields[0], "threads") == 0) &&
48306a99fe3SHajimu UMEMOTO 			((value = get_number(fields[1], 1, -1)) != -1)) {
48406a99fe3SHajimu UMEMOTO 				set_threads_num(config, value);
48506a99fe3SHajimu UMEMOTO 				continue;
48606a99fe3SHajimu UMEMOTO 			}
48706a99fe3SHajimu UMEMOTO 			break;
48806a99fe3SHajimu UMEMOTO 		case 'k':
48906a99fe3SHajimu UMEMOTO 			if ((field_count == 3) &&
49006a99fe3SHajimu UMEMOTO 			(strcmp(fields[0], "keep-hot-count") == 0) &&
49106a99fe3SHajimu UMEMOTO 			(check_cachename(fields[1]) == 0) &&
49206a99fe3SHajimu UMEMOTO 			((value = get_number(fields[2], 0, -1)) != -1)) {
49306a99fe3SHajimu UMEMOTO 				set_keep_hot_count(config,
49406a99fe3SHajimu UMEMOTO 					fields[1], value);
49506a99fe3SHajimu UMEMOTO 				continue;
49606a99fe3SHajimu UMEMOTO 			}
49706a99fe3SHajimu UMEMOTO 			break;
49806a99fe3SHajimu UMEMOTO 		case 'c':
49906a99fe3SHajimu UMEMOTO 			if ((field_count == 3) &&
50006a99fe3SHajimu UMEMOTO 			(strcmp(fields[0], "check-files") == 0) &&
50106a99fe3SHajimu UMEMOTO 			(check_cachename(fields[1]) == 0) &&
50206a99fe3SHajimu UMEMOTO 			((value = get_yesno(fields[2])) != -1)) {
50306a99fe3SHajimu UMEMOTO 				check_files(config,
50406a99fe3SHajimu UMEMOTO 					fields[1], value);
50506a99fe3SHajimu UMEMOTO 				continue;
50606a99fe3SHajimu UMEMOTO 			}
50706a99fe3SHajimu UMEMOTO 			break;
50806a99fe3SHajimu UMEMOTO 		default:
50906a99fe3SHajimu UMEMOTO 			break;
51006a99fe3SHajimu UMEMOTO 		}
51106a99fe3SHajimu UMEMOTO 
51206a99fe3SHajimu UMEMOTO 		LOG_ERR_2("config file parser", "error in file "
51306a99fe3SHajimu UMEMOTO 			"%s on line %d", fname, line_num);
51406a99fe3SHajimu UMEMOTO 		*error_str = "syntax error";
51506a99fe3SHajimu UMEMOTO 		*error_line = line_num;
51606a99fe3SHajimu UMEMOTO 		res = -1;
51706a99fe3SHajimu UMEMOTO 	}
51806a99fe3SHajimu UMEMOTO 	fclose(fin);
51906a99fe3SHajimu UMEMOTO 
52006a99fe3SHajimu UMEMOTO 	TRACE_OUT(parse_config_file);
52106a99fe3SHajimu UMEMOTO 	return (res);
52206a99fe3SHajimu UMEMOTO }
523