1/* SASL Config file API
2 * Rob Siemborski
3 * Tim Martin (originally in Cyrus distribution)
4 * $Id: config.c,v 1.3 2004/07/07 22:48:35 snsimon Exp $
5 */
6/*
7 * Copyright (c) 1998-2009 Carnegie Mellon University.  All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 *
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 *
16 * 2. Redistributions in binary form must reproduce the above copyright
17 *    notice, this list of conditions and the following disclaimer in
18 *    the documentation and/or other materials provided with the
19 *    distribution.
20 *
21 * 3. The name "Carnegie Mellon University" must not be used to
22 *    endorse or promote products derived from this software without
23 *    prior written permission. For permission or any other legal
24 *    details, please contact
25 *      Office of Technology Transfer
26 *      Carnegie Mellon University
27 *      5000 Forbes Avenue
28 *      Pittsburgh, PA  15213-3890
29 *      (412) 268-4387, fax: (412) 268-7395
30 *      tech-transfer@andrew.cmu.edu
31 *
32 * 4. Redistributions of any form whatsoever must retain the following
33 *    acknowledgment:
34 *    "This product includes software developed by Computing Services
35 *     at Carnegie Mellon University (http://www.cmu.edu/computing/)."
36 *
37 * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
38 * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
39 * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
40 * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
41 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
42 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
43 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
44 */
45
46#include <stdio.h>
47#include <stdlib.h>
48#include <ctype.h>
49
50#include "sasl.h"
51#include "saslint.h"
52
53struct configlist {
54    char *key;
55    char *value;
56};
57
58static struct configlist *configlist = NULL;
59static int nconfiglist = 0;
60
61#define CONFIGLISTGROWSIZE 100
62
63int sasl_config_init(const char *filename)
64{
65    FILE *infile;
66    int lineno = 0;
67    int alloced = 0;
68    char buf[4096];
69    char *p, *key;
70    char *tail;
71    int result;
72
73    nconfiglist=0;
74
75    infile = fopen(filename, "r");
76    if (!infile) {
77        return SASL_CONTINUE;
78    }
79
80    while (fgets(buf, sizeof(buf), infile)) {
81	lineno++;
82
83	if (buf[strlen(buf)-1] == '\n') buf[strlen(buf)-1] = '\0';
84	for (p = buf; *p && isspace((int) *p); p++);
85	if (!*p || *p == '#') continue;
86
87	key = p;
88	while (*p && (isalnum((int) *p) || *p == '-' || *p == '_')) {
89	    if (isupper((int) *p)) *p = (char) tolower(*p);
90	    p++;
91	}
92	if (*p != ':') {
93	    fclose(infile);
94	    return SASL_FAIL;
95	}
96	*p++ = '\0';
97
98	while (*p && isspace((int) *p)) p++;
99
100	if (!*p) {
101	    fclose(infile);
102	    return SASL_FAIL;
103	}
104
105	/* Now strip trailing spaces, if any */
106	tail = p + strlen(p) - 1;
107	while (tail > p && isspace((int) *tail)) {
108	    *tail = '\0';
109	    tail--;
110	}
111
112	if (nconfiglist == alloced) {
113	    alloced += CONFIGLISTGROWSIZE;
114	    configlist=sasl_REALLOC((char *)configlist,
115				    alloced * sizeof(struct configlist));
116	    if (configlist == NULL) {
117		fclose(infile);
118		return SASL_NOMEM;
119	    }
120	}
121
122	result = _sasl_strdup(key,
123			      &(configlist[nconfiglist].key),
124			      NULL);
125	if (result != SASL_OK) {
126	    fclose(infile);
127	    return result;
128	}
129	result = _sasl_strdup(p,
130			      &(configlist[nconfiglist].value),
131			      NULL);
132	if (result != SASL_OK) {
133	    fclose(infile);
134	    return result;
135	}
136
137	nconfiglist++;
138    }
139    fclose(infile);
140
141    return SASL_OK;
142}
143
144const char *sasl_config_getstring(const char *key,const char *def)
145{
146    int opt;
147
148    for (opt = 0; opt < nconfiglist; opt++) {
149	if (*key == configlist[opt].key[0] &&
150	    !strcmp(key, configlist[opt].key))
151	  return configlist[opt].value;
152    }
153    return def;
154}
155
156void sasl_config_done(void)
157{
158    int opt;
159
160    for (opt = 0; opt < nconfiglist; opt++) {
161	if (configlist[opt].key) sasl_FREE(configlist[opt].key);
162	if (configlist[opt].value) sasl_FREE(configlist[opt].value);
163    }
164
165    sasl_FREE(configlist);
166    configlist = NULL;
167    nconfiglist = 0;
168}
169