]> jfr.im git - irc/thales.git/blame - src/conf.c
keep track of max number of servers
[irc/thales.git] / src / conf.c
CommitLineData
18038256 1/* GNU Thales - IRC to Relational Database Gateway
2ace9480 2 * Copyright (C) 2002 Lucas Nussbaum <lucas@lucas-nussbaum.net>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 */
18
19/* Configuration file handling. */
20
21#include "conf.h"
22#include "misc.h"
23#include "compat.h"
24
25extern int debug;
26
27
28/* configuration variables: */
29char *RemoteServer;
30int RemotePort;
31char *RemotePassword;
32char *LocalHost;
33int LocalPort;
34
35char *ServerName;
36char *ServerDesc;
37char *PIDFilename;
38char *LogFilename;
39
40char *MysqlServer;
41char *MysqlDatabase;
42char *MysqlUser;
43char *MysqlPassword;
44
45int UserCacheTime;
46int UserCleanFreq;
47
48int ServerCacheTime;
49int ServerCleanFreq;
50
51int HidePasswords;
52
53Directive directives[] = {
54 {"RemoteServer", {{PARAM_STRING, 0, &RemoteServer},
55 {PARAM_PORT, 0, &RemotePort},
56 {PARAM_STRING, 0, &RemotePassword}}},
57 {"LocalAddress", {{PARAM_STRING, 0, &LocalHost},
58 {PARAM_PORT, PARAM_OPTIONAL, &LocalPort}}},
59 {"ServerDesc", {{PARAM_STRING, 0, &ServerDesc}}},
60 {"ServerName", {{PARAM_STRING, 0, &ServerName}}},
61 {"MysqlServer", {{PARAM_STRING, 0, &MysqlServer}}},
62 {"MysqlDatabase", {{PARAM_STRING, 0, &MysqlDatabase}}},
63 {"MysqlUser", {{PARAM_STRING, 0, &MysqlUser}}},
64 {"MysqlPassword", {{PARAM_STRING, 0, &MysqlPassword}}},
65 {"PIDFile", {{PARAM_STRING, 0, &PIDFilename}}},
66 {"LogFile", {{PARAM_STRING, 0, &LogFilename}}},
67 {"UserCacheTime", {{PARAM_POSINT, 0, &UserCacheTime}}},
68 {"ServerCacheTime", {{PARAM_POSINT, 0, &ServerCacheTime}}},
69 {"UserCleanFreq", {{PARAM_POSINT, 0, &UserCleanFreq}}},
70 {"ServerCleanFreq", {{PARAM_POSINT, 0, &ServerCleanFreq}}},
71 {"HidePasswords", {{PARAM_SET, 0, &HidePasswords}}},
72};
73
74/*************************************************************************/
75
76/* Print an error message to the log (and the console, if open). */
77
78void error(int linenum, char *message, ...)
79{
80 char buf[4096];
81 va_list args;
82
83 va_start(args, message);
84 vsnprintf(buf, sizeof(buf), message, args);
85 if (linenum)
18038256 86 mylog("%s:%d: %s", THALES_CONF, linenum, buf);
2ace9480 87 else
18038256 88 mylog("%s: %s", THALES_CONF, buf);
2ace9480 89 if (!debug && isatty(2))
90 {
91 if (linenum)
92 fprintf(stderr, "%s:%d: %s\n", THALES_CONF, linenum, buf);
93 else
94 fprintf(stderr, "%s: %s\n", THALES_CONF, buf);
95 }
96}
97
98/*************************************************************************/
99
100/* Parse a configuration line. Return 1 on success; otherwise, print an
101 * appropriate error message and return 0. Destroys the buffer by side
102 * effect.
103 */
104
105int parse(char *buf, int linenum, int reload)
106{
107 char *s, *t, *dir;
108 int i, n, optind, val;
109 int retval = 1;
110 int ac = 0;
111 char *av[MAXPARAMS];
112
113 dir = strtok(buf, " \t\r\n");
114 s = strtok(NULL, "");
115 if (s)
116 {
117 while (isspace(*s))
118 s++;
119 while (*s)
120 {
121 if (ac >= MAXPARAMS)
122 {
123 error(linenum, "Warning: too many parameters (%d max)",
124 MAXPARAMS);
125 break;
126 }
127 t = s;
128 if (*s == '"')
129 {
130 t++;
131 s++;
132 while (*s && *s != '"')
133 {
134 if (*s == '\\' && s[1] != 0)
135 s++;
136 s++;
137 }
138 if (!*s)
139 error(linenum,
140 "Warning: unterminated double-quoted string");
141 else
142 *s++ = 0;
143 }
144 else
145 {
146 s += strcspn(s, " \t\r\n");
147 if (*s)
148 *s++ = 0;
149 }
150 av[ac++] = t;
151 while (isspace(*s))
152 s++;
153 }
154 }
155
156 if (!dir)
157 return 1;
158
159 for (n = 0; n < lenof(directives); n++)
160 {
161 Directive *d = &directives[n];
162 if (stricmp(dir, d->name) != 0)
163 continue;
164 optind = 0;
165 for (i = 0; i < MAXPARAMS && d->params[i].type != PARAM_NONE; i++)
166 {
167 if (reload && !(d->params[i].flags & PARAM_RELOAD))
168 continue;
169
170 if (d->params[i].type == PARAM_SET)
171 {
172 *(int *) d->params[i].ptr = 1;
173 continue;
174 }
175#ifdef STREAMLINED
176 if (d->params[i].flags & PARAM_FULLONLY)
177 {
178 error(linenum,
179 "Directive `%s' not available in STREAMLINED mode",
180 d->name);
181 break;
182 }
183#endif
184
185 if (d->params[i].type == PARAM_DEPRECATED)
186 {
187 void (*func) (void);
188 error(linenum, "Deprecated directive `%s' used", d->name);
189 func = (void (*)(void)) (d->params[i].ptr);
190 func(); /* For clarity */
191 continue;
192 }
193 if (optind >= ac)
194 {
195 if (!(d->params[i].flags & PARAM_OPTIONAL))
196 {
197 error(linenum, "Not enough parameters for `%s'", d->name);
198 retval = 0;
199 }
200 break;
201 }
202 switch (d->params[i].type)
203 {
204 case PARAM_INT:
205 val = strtol(av[optind++], &s, 0);
206 if (*s)
207 {
208 error(linenum, "%s: Expected an integer for parameter %d",
209 d->name, optind);
210 retval = 0;
211 break;
212 }
213 *(int *) d->params[i].ptr = val;
214 break;
215 case PARAM_POSINT:
216 val = strtol(av[optind++], &s, 0);
217 if (*s || val < 0)
218 {
219 error(linenum,
220 "%s: Expected a positive integer for parameter %d",
221 d->name, optind);
222 retval = 0;
223 break;
224 }
225 *(int *) d->params[i].ptr = val;
226 break;
227 case PARAM_PORT:
228 val = strtol(av[optind++], &s, 0);
229 if (*s)
230 {
231 error(linenum,
232 "%s: Expected a port number for parameter %d",
233 d->name, optind);
234 retval = 0;
235 break;
236 }
237 if (val < 1 || val > 65535)
238 {
239 error(linenum,
240 "Port numbers must be in the range 1..65535");
241 retval = 0;
242 break;
243 }
244 *(int *) d->params[i].ptr = val;
245 break;
246 case PARAM_STRING:
247/* if (reload && *(char **)d->params[i].ptr)
248 free(*(char **)d->params[i].ptr); */
249 *(char **) d->params[i].ptr = strdup(av[optind++]);
250 if (!d->params[i].ptr)
251 {
252 error(linenum, "%s: Out of memory", d->name);
253 return 0;
254 }
255 break;
256 case PARAM_TIME:
257 val = dotime(av[optind++]);
258 if (val < 0)
259 {
260 error(linenum,
261 "%s: Expected a time value for parameter %d",
262 d->name, optind);
263 retval = 0;
264 break;
265 }
266 *(int *) d->params[i].ptr = val;
267 break;
268 default:
269 error(linenum, "%s: Unknown type %d for param %d",
270 d->name, d->params[i].type, i + 1);
271 return 0; /* don't bother continuing--something's bizarre */
272 }
273 }
274 break; /* because we found a match */
275 }
276
277 if (n == lenof(directives))
278 {
279 error(linenum, "Unknown directive `%s'", dir);
280 return 1; /* don't cause abort */
281 }
282
283 return retval;
284}
285
286/*************************************************************************/
287
288#define CHECK(v) do { \
289 if (!v) { \
290 error(0, #v " missing"); \
291 retval = 0; \
292 } \
293} while (0)
294
295#define CHEK2(v,n) do { \
296 if (!v) { \
297 error(0, #n " missing"); \
298 retval = 0; \
299 } \
300} while (0)
301
302/* Read the entire configuration file. If an error occurs while reading
303 * the file or a required directive is not found, print and log an
304 * appropriate error message and return 0; otherwise, return 1.
305 *
306 * If reload is 1, will reload the configuration file.
307 * --lara
308 *
309 */
310
311int read_config(void)
312{
313 FILE *config;
314 int linenum = 0, retval = 1;
315 char buf[1024];
316 config = fopen(THALES_CONF, "r");
317 if (!config)
318 {
18038256 319 mylog_perror("Can't open " THALES_CONF);
2ace9480 320 if (!debug && isatty(2))
321 perror("Can't open " THALES_CONF);
322 else
18038256 323 mylog("Can't open %s", THALES_CONF);
2ace9480 324 return 0;
325 }
326 while (fgets(buf, sizeof(buf), config))
327 {
328 linenum++;
329 if (*buf == '#' || *buf == '\r' || *buf == '\n')
330 continue;
331 if (!parse(buf, linenum, 0))
332 retval = 0;
333 }
334 fclose(config);
335
336 CHECK(RemoteServer);
337 CHECK(ServerName);
338 CHECK(ServerDesc);
339 CHEK2(PIDFilename, PIDFile);
340 return retval;
341}