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