xref: /titanic_41/usr/src/cmd/nscd/nscd_cfgfile.c (revision 18bdb8a7484e018149ac9a2766c97bdea9752c87)
1cb5caa98Sdjl /*
2cb5caa98Sdjl  * CDDL HEADER START
3cb5caa98Sdjl  *
4cb5caa98Sdjl  * The contents of this file are subject to the terms of the
5cb5caa98Sdjl  * Common Development and Distribution License (the "License").
6cb5caa98Sdjl  * You may not use this file except in compliance with the License.
7cb5caa98Sdjl  *
8cb5caa98Sdjl  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9cb5caa98Sdjl  * or http://www.opensolaris.org/os/licensing.
10cb5caa98Sdjl  * See the License for the specific language governing permissions
11cb5caa98Sdjl  * and limitations under the License.
12cb5caa98Sdjl  *
13cb5caa98Sdjl  * When distributing Covered Code, include this CDDL HEADER in each
14cb5caa98Sdjl  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15cb5caa98Sdjl  * If applicable, add the following below this CDDL HEADER, with the
16cb5caa98Sdjl  * fields enclosed by brackets "[]" replaced with your own identifying
17cb5caa98Sdjl  * information: Portions Copyright [yyyy] [name of copyright owner]
18cb5caa98Sdjl  *
19cb5caa98Sdjl  * CDDL HEADER END
20cb5caa98Sdjl  */
21cb5caa98Sdjl /*
22*18bdb8a7Smichen  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
23cb5caa98Sdjl  * Use is subject to license terms.
24cb5caa98Sdjl  */
25cb5caa98Sdjl 
26cb5caa98Sdjl #pragma ident	"%Z%%M%	%I%	%E% SMI"
27cb5caa98Sdjl 
28cb5caa98Sdjl /*
29cb5caa98Sdjl  *   routine to read configuration file
30cb5caa98Sdjl  *
31cb5caa98Sdjl  */
32cb5caa98Sdjl #include "nscd_config.h"
33cb5caa98Sdjl #include "nscd_log.h"
34cb5caa98Sdjl #include <locale.h>
35cb5caa98Sdjl #include <ctype.h>
36cb5caa98Sdjl #include <string.h>
37cb5caa98Sdjl #include <errno.h>
38cb5caa98Sdjl 
39cb5caa98Sdjl static int
strbreak(char * field[],int array_size,char * s,char * sep)40cb5caa98Sdjl strbreak(char *field[], int array_size, char *s, char *sep)
41cb5caa98Sdjl {
42cb5caa98Sdjl 	int	i;
43cb5caa98Sdjl 	char	*lasts, *qp;
44cb5caa98Sdjl 	int	inquote;
45cb5caa98Sdjl 
46cb5caa98Sdjl 	qp = strchr(s, '"');
47*18bdb8a7Smichen 	for (i = 0; i < array_size && (field[i] = strtok_r((i?(char *)NULL:s),
48*18bdb8a7Smichen 	    sep, &lasts)); i++) {
49*18bdb8a7Smichen 		/* empty */
50*18bdb8a7Smichen 	}
51cb5caa98Sdjl 
52cb5caa98Sdjl 	if (qp == NULL)
53cb5caa98Sdjl 		return (i);
54cb5caa98Sdjl 
55cb5caa98Sdjl 	inquote = 1;
56cb5caa98Sdjl 	while (++qp < lasts) {
57cb5caa98Sdjl 
58cb5caa98Sdjl 		switch (*qp) {
59cb5caa98Sdjl 
60cb5caa98Sdjl 		case '"':
61cb5caa98Sdjl 			inquote = (inquote == 0);
62cb5caa98Sdjl 			break;
63cb5caa98Sdjl 
64cb5caa98Sdjl 		case '\\':
65cb5caa98Sdjl 			/* escape " */
66cb5caa98Sdjl 			if (inquote == 1 && *(qp + 1) == '"')
67cb5caa98Sdjl 				qp++;
68cb5caa98Sdjl 			break;
69cb5caa98Sdjl 
70cb5caa98Sdjl 		case '\0':
71cb5caa98Sdjl 			if (inquote == 1) {
72cb5caa98Sdjl 				*qp = ' ';
73cb5caa98Sdjl 				i--;
74cb5caa98Sdjl 			}
75cb5caa98Sdjl 
76cb5caa98Sdjl 			break;
77cb5caa98Sdjl 		}
78cb5caa98Sdjl 	}
79cb5caa98Sdjl 
80cb5caa98Sdjl 	return (i);
81cb5caa98Sdjl }
82cb5caa98Sdjl 
83cb5caa98Sdjl 
84cb5caa98Sdjl nscd_rc_t
_nscd_cfg_read_file(char * filename,nscd_cfg_error_t ** errorp)85cb5caa98Sdjl _nscd_cfg_read_file(
86cb5caa98Sdjl 	char			*filename,
87cb5caa98Sdjl 	nscd_cfg_error_t	**errorp)
88cb5caa98Sdjl {
89cb5caa98Sdjl 	char			*me = "_nscd_cfg_read_file";
90cb5caa98Sdjl 	FILE			*in;
91cb5caa98Sdjl 	char			buffer[255];
92cb5caa98Sdjl 	char			*fields [128];
93cb5caa98Sdjl 	int			linecnt;
94cb5caa98Sdjl 	int			fieldcnt;
95cb5caa98Sdjl 	nscd_rc_t		rc = NSCD_SUCCESS;
96cb5caa98Sdjl 	nscd_cfg_handle_t	*h = NULL;
97cb5caa98Sdjl 	nscd_cfg_param_desc_t	*pdesc;
98cb5caa98Sdjl 	char			*dbname, *str;
99cb5caa98Sdjl 	void			*data_p;
100cb5caa98Sdjl 	int			i;
101cb5caa98Sdjl 	char			msg[NSCD_CFG_MAX_ERR_MSG_LEN];
102cb5caa98Sdjl 
103cb5caa98Sdjl 	union {
104cb5caa98Sdjl 		int	i;
105cb5caa98Sdjl 		char	data[256];
106cb5caa98Sdjl 	} u;
107cb5caa98Sdjl 
108cb5caa98Sdjl 	if ((in = fopen(filename, "r")) == NULL) {
109cb5caa98Sdjl 
110cb5caa98Sdjl 		(void) snprintf(msg, sizeof (msg),
111cb5caa98Sdjl 		    gettext("open of configuration file \"%s\" failed: %s"),
112cb5caa98Sdjl 		    filename, strerror(errno));
113cb5caa98Sdjl 		if (errorp != NULL)
114cb5caa98Sdjl 			*errorp = _nscd_cfg_make_error(
115cb5caa98Sdjl 			    NSCD_CFG_FILE_OPEN_ERROR, msg);
116cb5caa98Sdjl 
117cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
118cb5caa98Sdjl 		(me, "%s\n", msg);
119cb5caa98Sdjl 
120cb5caa98Sdjl 		return (NSCD_CFG_FILE_OPEN_ERROR);
121cb5caa98Sdjl 	}
122cb5caa98Sdjl 
123cb5caa98Sdjl 	linecnt = 0;
124cb5caa98Sdjl 	msg[0] = '\0';
125cb5caa98Sdjl 	while (fgets(buffer, sizeof (buffer), in) != NULL) {
126cb5caa98Sdjl 
127cb5caa98Sdjl 		linecnt++;
128cb5caa98Sdjl 		if ((fieldcnt = strbreak(fields, 128, buffer, " \t\n")) ==
129cb5caa98Sdjl 		    0 || *fields[0] == '#') {
130cb5caa98Sdjl 			/* skip blank or comment lines */
131cb5caa98Sdjl 			continue;
132cb5caa98Sdjl 		}
133cb5caa98Sdjl 
134cb5caa98Sdjl 		switch (fieldcnt) {
135cb5caa98Sdjl 
136cb5caa98Sdjl 		case 2:
137cb5caa98Sdjl 			dbname = NULL;
138cb5caa98Sdjl 			str = fields[1];
139cb5caa98Sdjl 			break;
140cb5caa98Sdjl 
141cb5caa98Sdjl 		case 3:
142cb5caa98Sdjl 			dbname = fields[1];
143cb5caa98Sdjl 			str = fields[2];
144cb5caa98Sdjl 			break;
145cb5caa98Sdjl 
146cb5caa98Sdjl 		default:
147cb5caa98Sdjl 
148cb5caa98Sdjl 			(void) strlcpy(u.data, fields[0], sizeof (u.data));
149cb5caa98Sdjl 			for (i = 1; i < fieldcnt; i++) {
150cb5caa98Sdjl 				(void) strlcat(u.data, " ",
151cb5caa98Sdjl 				    sizeof (u.data));
152cb5caa98Sdjl 				(void) strlcat(u.data, fields[i],
153cb5caa98Sdjl 				    sizeof (u.data));
154cb5caa98Sdjl 			}
155cb5caa98Sdjl 
156cb5caa98Sdjl 			(void) snprintf(msg, sizeof (msg),
157cb5caa98Sdjl 		gettext("Syntax error: line %d of configuration "
158cb5caa98Sdjl 			"file: %s : \"%s\""), linecnt, filename, u.data);
159cb5caa98Sdjl 			if (errorp != NULL)
160cb5caa98Sdjl 				*errorp = _nscd_cfg_make_error(
161cb5caa98Sdjl 				    NSCD_CFG_SYNTAX_ERROR, msg);
162cb5caa98Sdjl 
163cb5caa98Sdjl 			_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
164cb5caa98Sdjl 			(me, "%s\n", msg);
165cb5caa98Sdjl 
166cb5caa98Sdjl 			rc = NSCD_CFG_SYNTAX_ERROR;
167cb5caa98Sdjl 			break;
168cb5caa98Sdjl 		}
169cb5caa98Sdjl 
170cb5caa98Sdjl 		if (rc != NSCD_SUCCESS)
171cb5caa98Sdjl 			break;
172cb5caa98Sdjl 
173cb5caa98Sdjl 		rc = _nscd_cfg_get_handle(fields[0], dbname, &h, errorp);
174cb5caa98Sdjl 		if (rc != NSCD_SUCCESS)
175cb5caa98Sdjl 			break;
176cb5caa98Sdjl 
177cb5caa98Sdjl 		pdesc = _nscd_cfg_get_desc(h);
178cb5caa98Sdjl 
179cb5caa98Sdjl 		/* convert string to data */
180cb5caa98Sdjl 		rc = _nscd_cfg_str_to_data(pdesc, str, &u.data,
181cb5caa98Sdjl 		    &data_p, errorp);
182cb5caa98Sdjl 		if (rc != NSCD_SUCCESS)
183cb5caa98Sdjl 			break;
184cb5caa98Sdjl 
185cb5caa98Sdjl 		/* do preliminary check based on data type */
186cb5caa98Sdjl 		rc = _nscd_cfg_prelim_check(pdesc, data_p, errorp);
187cb5caa98Sdjl 		if (rc != NSCD_SUCCESS)
188cb5caa98Sdjl 			break;
189cb5caa98Sdjl 
190cb5caa98Sdjl 		rc = _nscd_cfg_set_linked(h, data_p, errorp);
191cb5caa98Sdjl 		_nscd_cfg_free_handle(h);
192cb5caa98Sdjl 		h = NULL;
193cb5caa98Sdjl 		if (rc != NSCD_CFG_READ_ONLY && rc != NSCD_SUCCESS)
194cb5caa98Sdjl 			break;
195cb5caa98Sdjl 		else {
196cb5caa98Sdjl 			_nscd_cfg_free_error(*errorp);
197cb5caa98Sdjl 			*errorp = NULL;
198cb5caa98Sdjl 		}
199cb5caa98Sdjl 	}
200cb5caa98Sdjl 	/* NSCD_CFG_READ_ONLY is not fatal */
201cb5caa98Sdjl 	if (rc == NSCD_CFG_READ_ONLY)
202cb5caa98Sdjl 		rc = NSCD_SUCCESS;
203cb5caa98Sdjl 
204cb5caa98Sdjl 	if (h != NULL)
205cb5caa98Sdjl 		_nscd_cfg_free_handle(h);
206cb5caa98Sdjl 
207cb5caa98Sdjl 	(void) fclose(in);
208cb5caa98Sdjl 
209cb5caa98Sdjl 	if (msg[0] == '\0' && rc != NSCD_SUCCESS) {
210cb5caa98Sdjl 		if (errorp != NULL)
211cb5caa98Sdjl 			_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
212cb5caa98Sdjl 			(me, "%s\n", NSCD_ERR2MSG(*errorp));
213cb5caa98Sdjl 	}
214cb5caa98Sdjl 
215cb5caa98Sdjl 	return (rc);
216cb5caa98Sdjl }
217cb5caa98Sdjl 
218cb5caa98Sdjl nscd_rc_t
_nscd_cfg_read_nsswitch_file(char * filename,nscd_cfg_error_t ** errorp)219cb5caa98Sdjl _nscd_cfg_read_nsswitch_file(
220cb5caa98Sdjl 	char			*filename,
221cb5caa98Sdjl 	nscd_cfg_error_t	**errorp)
222cb5caa98Sdjl {
223cb5caa98Sdjl 	char			*me = "_nscd_cfg_read_nsswitch_file";
224cb5caa98Sdjl 	char			*pname = "nsw-config-string";
225cb5caa98Sdjl 	FILE			*in;
226cb5caa98Sdjl 	char			buffer[255];
227cb5caa98Sdjl 	char			*cc, *ce, *ce1, *c1, *c2;
228cb5caa98Sdjl 	char			*db, *dbe;
229cb5caa98Sdjl 	char			*nsscfg;
230cb5caa98Sdjl 	int			syntax_err;
231cb5caa98Sdjl 	int			linecnt;
232cb5caa98Sdjl 	nscd_rc_t		rc = NSCD_SUCCESS;
233cb5caa98Sdjl 	nscd_cfg_handle_t	*h = NULL;
234cb5caa98Sdjl 	nscd_cfg_param_desc_t	*pdesc;
235cb5caa98Sdjl 	void			*data_p;
236cb5caa98Sdjl 	char			msg[NSCD_CFG_MAX_ERR_MSG_LEN];
237cb5caa98Sdjl 
238cb5caa98Sdjl 	union {
239cb5caa98Sdjl 		int	i;
240cb5caa98Sdjl 		char	data[256];
241cb5caa98Sdjl 	} u;
242cb5caa98Sdjl 
243cb5caa98Sdjl 	if ((in = fopen(filename, "r")) == NULL) {
244cb5caa98Sdjl 
245cb5caa98Sdjl 		(void) snprintf(msg, sizeof (msg),
246cb5caa98Sdjl 		    gettext("open of configuration file \"%s\" failed: %s"),
247cb5caa98Sdjl 		    filename, strerror(errno));
248cb5caa98Sdjl 		if (errorp != NULL)
249cb5caa98Sdjl 			*errorp = _nscd_cfg_make_error(
250cb5caa98Sdjl 			    NSCD_CFG_FILE_OPEN_ERROR, msg);
251cb5caa98Sdjl 
252cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
253cb5caa98Sdjl 		(me, "%s\n", msg);
254cb5caa98Sdjl 
255cb5caa98Sdjl 		return (NSCD_CFG_FILE_OPEN_ERROR);
256cb5caa98Sdjl 	}
257cb5caa98Sdjl 
258cb5caa98Sdjl 	linecnt = 0;
259cb5caa98Sdjl 	msg[0] = '\0';
260cb5caa98Sdjl 	while (fgets(buffer, sizeof (buffer), in) != NULL) {
261cb5caa98Sdjl 
262cb5caa98Sdjl 		linecnt++;
263cb5caa98Sdjl 		syntax_err = 0;
264cb5caa98Sdjl 		/* skip blank or comment lines */
265cb5caa98Sdjl 		if (buffer[0] == '#' || buffer[0] == '\n')
266cb5caa98Sdjl 			continue;
267cb5caa98Sdjl 		/* skip end of line comment */
268cb5caa98Sdjl 		if ((ce = strchr(buffer, '\n')) != NULL)
269cb5caa98Sdjl 			*ce = '\0';
270cb5caa98Sdjl 		else
271cb5caa98Sdjl 			ce = &buffer[255];
272cb5caa98Sdjl 		if ((ce1 = strchr(buffer, '#')) != NULL) {
273cb5caa98Sdjl 			ce = ce1;
274cb5caa98Sdjl 			*ce = '\0';
275cb5caa98Sdjl 		}
276cb5caa98Sdjl 		if ((cc = strchr(buffer, ':')) == NULL) {
277cb5caa98Sdjl 			c1 = buffer;
278cb5caa98Sdjl 			while (isalpha(*c1) && c1 < ce)
279cb5caa98Sdjl 				c1++;
280cb5caa98Sdjl 			if (c1 > ce)
281cb5caa98Sdjl 				syntax_err = 1;
282cb5caa98Sdjl 			else /* blank line */
283cb5caa98Sdjl 				continue;
284cb5caa98Sdjl 		} else {
285cb5caa98Sdjl 			/*
286cb5caa98Sdjl 			 * data name goes before ':',
287cb5caa98Sdjl 			 * skip spaces on both ends
288cb5caa98Sdjl 			 */
289cb5caa98Sdjl 			c2 = cc - 1;
290cb5caa98Sdjl 			while (buffer <= c2 && isspace(*c2))
291cb5caa98Sdjl 				c2--;
292cb5caa98Sdjl 			c1 = buffer;
293cb5caa98Sdjl 			while (c1 <= cc && isspace(*c1))
294cb5caa98Sdjl 				c1++;
295cb5caa98Sdjl 			if (c1 > c2)
296cb5caa98Sdjl 				syntax_err = 1;
297cb5caa98Sdjl 			else {
298cb5caa98Sdjl 				db = c1;
299cb5caa98Sdjl 				dbe = c2 + 1;
300cb5caa98Sdjl 
301cb5caa98Sdjl 				/*
302cb5caa98Sdjl 				 * nss config goes after ':',
303cb5caa98Sdjl 				 * skip spaces on both ends
304cb5caa98Sdjl 				 */
305cb5caa98Sdjl 				c1 = cc + 1;
306cb5caa98Sdjl 				while (c1 <= ce && isspace(*c1))
307cb5caa98Sdjl 					c1++;
308cb5caa98Sdjl 				c2 = ce - 1;
309cb5caa98Sdjl 				while (cc <= c2 && isspace(*c2))
310cb5caa98Sdjl 					c2--;
311*18bdb8a7Smichen 				if (c1 > c2) {
312*18bdb8a7Smichen 					/* no source specified, it's OK */
313*18bdb8a7Smichen 					continue;
314*18bdb8a7Smichen 				} else {
315cb5caa98Sdjl 					*dbe = '\0';
316cb5caa98Sdjl 					nsscfg = c1;
317cb5caa98Sdjl 					*(c2 + 1) = '\0';
318cb5caa98Sdjl 				}
319cb5caa98Sdjl 			}
320cb5caa98Sdjl 		}
321cb5caa98Sdjl 
322cb5caa98Sdjl 		if (syntax_err == 1) {
323cb5caa98Sdjl 
324cb5caa98Sdjl 			(void) snprintf(msg, sizeof (msg),
325cb5caa98Sdjl 		gettext("Syntax error: line %d of configuration "
326cb5caa98Sdjl 			"file: %s : \"%s\""), linecnt, filename, buffer);
327cb5caa98Sdjl 			if (errorp != NULL)
328cb5caa98Sdjl 				*errorp = _nscd_cfg_make_error(
329cb5caa98Sdjl 				    NSCD_CFG_SYNTAX_ERROR, msg);
330cb5caa98Sdjl 
331cb5caa98Sdjl 			_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
332cb5caa98Sdjl 			(me, "%s\n", msg);
333cb5caa98Sdjl 
334cb5caa98Sdjl 			rc = NSCD_CFG_SYNTAX_ERROR;
335cb5caa98Sdjl 			return (rc);
336cb5caa98Sdjl 		}
337cb5caa98Sdjl 
338cb5caa98Sdjl 		rc = _nscd_cfg_get_handle(pname, db, &h, errorp);
339cb5caa98Sdjl 		if (rc != NSCD_SUCCESS) {
340cb5caa98Sdjl 			/* ignore unsupported switch database */
341cb5caa98Sdjl 			if (rc == NSCD_CFG_UNSUPPORTED_SWITCH_DB) {
342cb5caa98Sdjl 				_nscd_cfg_free_error(*errorp);
343cb5caa98Sdjl 				*errorp = NULL;
344cb5caa98Sdjl 				rc = NSCD_SUCCESS;
345cb5caa98Sdjl 				continue;
346cb5caa98Sdjl 			}
347cb5caa98Sdjl 			break;
348cb5caa98Sdjl 		}
349cb5caa98Sdjl 
350cb5caa98Sdjl 		pdesc = _nscd_cfg_get_desc(h);
351cb5caa98Sdjl 
352cb5caa98Sdjl 		/* convert string to data */
353cb5caa98Sdjl 		rc = _nscd_cfg_str_to_data(pdesc, nsscfg, &u.data,
354cb5caa98Sdjl 		    &data_p, errorp);
355cb5caa98Sdjl 		if (rc != NSCD_SUCCESS)
356cb5caa98Sdjl 			break;
357cb5caa98Sdjl 
358cb5caa98Sdjl 		/* do preliminary check based on data type */
359cb5caa98Sdjl 		rc = _nscd_cfg_prelim_check(pdesc, data_p, errorp);
360cb5caa98Sdjl 		if (rc != NSCD_SUCCESS)
361cb5caa98Sdjl 			break;
362cb5caa98Sdjl 
363cb5caa98Sdjl 		rc = _nscd_cfg_set_linked(h, data_p, errorp);
364cb5caa98Sdjl 		_nscd_cfg_free_handle(h);
365cb5caa98Sdjl 		h = NULL;
366cb5caa98Sdjl 		if (rc != NSCD_CFG_READ_ONLY && rc != NSCD_SUCCESS)
367cb5caa98Sdjl 			break;
368cb5caa98Sdjl 		else {
369cb5caa98Sdjl 			_nscd_cfg_free_error(*errorp);
370cb5caa98Sdjl 			*errorp = NULL;
371cb5caa98Sdjl 		}
372cb5caa98Sdjl 	}
373cb5caa98Sdjl 	/* NSCD_CFG_READ_ONLY is not fatal */
374cb5caa98Sdjl 	if (rc == NSCD_CFG_READ_ONLY)
375cb5caa98Sdjl 		rc = NSCD_SUCCESS;
376cb5caa98Sdjl 
377cb5caa98Sdjl 	if (h != NULL)
378cb5caa98Sdjl 		_nscd_cfg_free_handle(h);
379cb5caa98Sdjl 
380cb5caa98Sdjl 	(void) fclose(in);
381cb5caa98Sdjl 
382cb5caa98Sdjl 	if (msg[0] == '\0' && rc != NSCD_SUCCESS) {
383cb5caa98Sdjl 		if (errorp != NULL)
384cb5caa98Sdjl 			_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
385cb5caa98Sdjl 			(me, "%s\n", NSCD_ERR2MSG(*errorp));
386cb5caa98Sdjl 	}
387cb5caa98Sdjl 
388cb5caa98Sdjl 	return (rc);
389cb5caa98Sdjl }
390