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