1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21/*
22 * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
23 * Use is subject to license terms.
24 */
25
26#pragma ident	"%Z%%M%	%I%	%E% SMI"
27
28/*
29 * Provides accessors to configuration properties.
30 *
31 * slp_readConfig:	attempts to locate slp.conf, and reads in all
32 *				properties specified therein.
33 * slp_get_mtu:		returns the MTU
34 * slp_get_next_onlist:	parses a comma separated list of integers (in
35 *				string form), returning one at a time.
36 * slp_parse_static_das: parses the list of DAs given in the DAAddresses
37 *				property.
38 *
39 * Also see the config wrapper macros in slp-internal.h.
40 */
41
42#include <stdio.h>
43#include <syslog.h>
44#include <string.h>
45#include <stdlib.h>
46#include <ctype.h>
47#include <slp-internal.h>
48
49/*
50 * Reads from fp and dynamically reallocates the buffer if necessary.
51 * Returns 1 on success, 0 on read completion, and -1 on failure.
52 */
53static int super_fgets(char **buf, size_t *bufsize, FILE *fp) {
54	char *r, *p;
55	size_t real_bufsize, readlen = 0;
56
57	p = *buf;
58	real_bufsize = *bufsize;
59	for (;;) {
60		r = fgets(p, (int)real_bufsize, fp);
61		if (feof(fp) && !r)
62			return (0);
63		if (!r)
64			return (-1);
65		readlen += strlen(r);
66		if ((*buf)[readlen - 1] == '\n')
67			return (1);
68
69		/* else	buf is too small */
70		*bufsize *= 2;
71		if (!(*buf = realloc(*buf, *bufsize))) {
72			slp_err(LOG_CRIT, 0, "super_fgets", "out of memory");
73			return (-1);
74		}
75		p = *buf + readlen;
76		real_bufsize = *bufsize - readlen;
77	}
78}
79
80static void skip_space(char **p) {
81	while (*p && **p != '\n' && isspace(**p))
82		(*p)++;
83}
84
85static void null_space(char *p) {
86	for (; *p; p++)
87		if (isspace(*p))
88			*p = 0;
89}
90
91/*
92 * Reads into the local property store all properties defined in
93 * the config file.
94 */
95void slp_readConfig() {
96	char *cfile, *buf;
97	FILE *fp;
98	size_t buflen = 512;
99
100	/* check env for alternate config file */
101	fp = NULL;
102	if (cfile = getenv("SLP_CONF_FILE"))
103		fp = fopen(cfile, "rF");
104	if (!fp)
105		if (!(fp = fopen(SLP_DEFAULT_CONFIG_FILE, "rF"))) {
106			slp_err(LOG_INFO, 0, "readConfig",
107				"cannot open config file");
108			return;
109		}
110
111	if (!(buf = malloc(buflen))) {
112		slp_err(LOG_CRIT, 0, "readConfig", "out of memory");
113		(void) fclose(fp);
114		return;
115	}
116
117	while (!feof(fp)) {
118		char *val, *p;
119		int err;
120
121		/* read a line */
122		err = super_fgets(&buf, &buflen, fp);
123		if (err == 0) continue;
124		if (err == -1) {
125			slp_err(LOG_INFO, 0, "readConfig",
126				"error reading file: %d",
127				ferror(fp));
128			(void) fclose(fp);
129			free(buf);
130			return;
131		}
132
133		/* skip comments and newlines */
134		p = buf;
135		skip_space(&p);
136		if (*p == '#' || *p == ';' || *p == '\n')
137			continue;
138
139		/* get property and value */
140		if (val = strchr(p, '=')) {
141			*val++ = 0;
142			skip_space(&val);
143			/* remove the trailing newline */
144			val[strlen(val) - 1] = 0;
145		}
146		null_space(p);
147
148		SLPSetProperty(p, val ? val : "");
149	}
150
151	(void) fclose(fp);
152	free(buf);
153}
154
155/*
156 * Config convenience wrappers
157 */
158size_t slp_get_mtu() {
159	size_t size;
160	size = atoi(SLPGetProperty(SLP_CONFIG_MTU));
161	size = size ? size : SLP_DEFAULT_SENDMTU;
162
163	return (size);
164}
165
166/*
167 * On the first invocation, *state should == the value of the property
168 * to parse.
169 * If there are no more timeouts, returns -1, otherwise the timeout.
170 * If the value in the property is invalid, returns the default 2000.
171 */
172int slp_get_next_onlist(char **state) {
173	char *p, buf[33];
174	size_t l;
175	int answer;
176
177	if (!*state)
178		return (-1);
179
180	if (**state == ',') {
181		(*state)++;	/* skip the ',' */
182	}
183	p = *state;
184	*state = slp_utf_strchr(*state, ',');
185	if (!*state)
186		l = strlen(p);
187	else {
188		l = *state - p;
189		l = (l > 32 ? 32 : l);
190	}
191	(void) strncpy(buf, p, l);
192	buf[l] = 0;
193	answer = atoi(buf);
194
195	return (answer != 0 ? answer : 2000);
196}
197
198int slp_get_maxResults() {
199	int num = atoi(SLPGetProperty(SLP_CONFIG_MAXRESULTS));
200
201	return (num <= 0 ? -1 : num);
202}
203