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 2006 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 /* 29 * routine to read configuration file 30 * 31 */ 32 #include "nscd_config.h" 33 #include "nscd_log.h" 34 #include <locale.h> 35 #include <ctype.h> 36 #include <string.h> 37 #include <errno.h> 38 39 static int 40 strbreak(char *field[], int array_size, char *s, char *sep) 41 { 42 int i; 43 char *lasts, *qp; 44 int inquote; 45 46 qp = strchr(s, '"'); 47 for (i = 0; i < array_size && (field[i] = 48 strtok_r((i?(char *)NULL:s), sep, &lasts)); i++); 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 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 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 syntax_err = 1; 311 else { 312 *dbe = '\0'; 313 nsscfg = c1; 314 *(c2 + 1) = '\0'; 315 } 316 } 317 } 318 319 if (syntax_err == 1) { 320 321 (void) snprintf(msg, sizeof (msg), 322 gettext("Syntax error: line %d of configuration " 323 "file: %s : \"%s\""), linecnt, filename, buffer); 324 if (errorp != NULL) 325 *errorp = _nscd_cfg_make_error( 326 NSCD_CFG_SYNTAX_ERROR, msg); 327 328 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 329 (me, "%s\n", msg); 330 331 rc = NSCD_CFG_SYNTAX_ERROR; 332 return (rc); 333 } 334 335 rc = _nscd_cfg_get_handle(pname, db, &h, errorp); 336 if (rc != NSCD_SUCCESS) { 337 /* ignore unsupported switch database */ 338 if (rc == NSCD_CFG_UNSUPPORTED_SWITCH_DB) { 339 _nscd_cfg_free_error(*errorp); 340 *errorp = NULL; 341 rc = NSCD_SUCCESS; 342 continue; 343 } 344 break; 345 } 346 347 pdesc = _nscd_cfg_get_desc(h); 348 349 /* convert string to data */ 350 rc = _nscd_cfg_str_to_data(pdesc, nsscfg, &u.data, 351 &data_p, errorp); 352 if (rc != NSCD_SUCCESS) 353 break; 354 355 /* do preliminary check based on data type */ 356 rc = _nscd_cfg_prelim_check(pdesc, data_p, errorp); 357 if (rc != NSCD_SUCCESS) 358 break; 359 360 rc = _nscd_cfg_set_linked(h, data_p, errorp); 361 _nscd_cfg_free_handle(h); 362 h = NULL; 363 if (rc != NSCD_CFG_READ_ONLY && rc != NSCD_SUCCESS) 364 break; 365 else { 366 _nscd_cfg_free_error(*errorp); 367 *errorp = NULL; 368 } 369 } 370 /* NSCD_CFG_READ_ONLY is not fatal */ 371 if (rc == NSCD_CFG_READ_ONLY) 372 rc = NSCD_SUCCESS; 373 374 if (h != NULL) 375 _nscd_cfg_free_handle(h); 376 377 (void) fclose(in); 378 379 if (msg[0] == '\0' && rc != NSCD_SUCCESS) { 380 if (errorp != NULL) 381 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 382 (me, "%s\n", NSCD_ERR2MSG(*errorp)); 383 } 384 385 return (rc); 386 } 387