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