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