2 * Dolda Connect - Modular multiuser Direct Connect-style client
3 * Copyright (C) 2004 Fredrik Tolf <fredrik@dolda2000.com>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 #include <sys/types.h>
31 #include <arpa/inet.h>
41 static struct configmod *modules = NULL;
44 static void dumpconfig(void)
46 struct configmod *mod;
47 struct configvar *var;
49 for(mod = modules; mod != NULL; mod = mod->next)
51 printf("%s:\n", mod->name);
52 for(var = mod->vars; var->type != CONF_VAR_END; var++)
57 printf("\t%s: %s\n", var->name, var->val.num?"t":"f");
60 printf("\t%s: %i\n", var->name, var->val.num);
63 printf("\t%s: \"%ls\" (%i)\n", var->name, var->val.str, wcslen(var->val.str));
66 printf("\t%s: %s\n", var->name, inet_ntoa(var->val.ipv4));
74 struct configvar *confgetvar(char *modname, char *varname)
79 for(m = modules; m != NULL; m = m->next)
81 if(!strcmp(m->name, modname))
83 for(v = m->vars; v->type != CONF_VAR_END; v++)
85 if(!strcmp(v->name, varname))
94 void confregmod(struct configmod *mod)
96 struct configvar *var;
98 for(var = mod->vars; var->type != CONF_VAR_END; var++)
104 var->val.num = var->defaults.num;
106 case CONF_VAR_STRING:
107 if(var->defaults.str != NULL)
109 var->val.str = swcsdup(var->defaults.str);
115 var->val.ipv4.s_addr = var->defaults.ipv4.s_addr;
118 CBCHAININIT(var, conf_update);
124 int runconfcmd(int argc, wchar_t **argv)
126 struct configmod *module;
127 struct configvar *var;
128 struct configcmd *cmd;
131 char *cmdn, *buf, *buf2, *valbuf;
133 struct in_addr newipv4;
138 if((cmdn = icwcstombs(argv[0], "us-ascii")) == NULL)
140 flog(LOG_WARNING, "could not convert %ls to us-ascii", argv[0]);
145 if(!strcmp(cmdn, "set"))
149 if((p = wcschr(argv[1], L'.')) == NULL)
151 flog(LOG_WARNING, "illegal configuration variable format: %ls", argv[1]);
157 if((buf = icwcstombs(argv[1], "us-ascii")) == NULL)
159 flog(LOG_WARNING, "could not convert %ls to us-ascii", argv[1]);
163 if((buf2 = icwcstombs(p, "us-ascii")) == NULL)
166 flog(LOG_WARNING, "could not convert %ls to us-ascii", p);
170 for(module = modules; module != NULL; module = module->next)
172 if(!strcmp(module->name, buf) && (module->vars != NULL))
174 for(var = module->vars; var->type != CONF_VAR_END; var++)
176 if(!strcmp(var->name, buf2))
183 if(!wcscmp(argv[2], L"off") ||
184 !wcscmp(argv[2], L"false") ||
185 !wcscmp(argv[2], L"no") ||
186 !wcscmp(argv[2], L"0"))
191 } else if(!wcscmp(argv[2], L"on") ||
192 !wcscmp(argv[2], L"true") ||
193 !wcscmp(argv[2], L"yes") ||
194 !wcscmp(argv[2], L"1")) {
199 flog(LOG_WARNING, "unrecognized boolean: %ls", argv[2]);
203 num = wcstol(argv[2], &p, 0);
206 flog(LOG_WARNING, "%ls: not a number, ignoring", argv[2]);
210 flog(LOG_WARNING, "%ls: could not entirely parse as a number, ignoring trailing garbage", argv[2]);
211 if(num != var->val.num)
216 case CONF_VAR_STRING:
217 if(wcscmp(var->val.str, argv[2]))
220 var->val.str = swcsdup(argv[2]);
223 if((valbuf = icwcstombs(argv[2], "us-ascii")) == NULL)
225 flog(LOG_WARNING, "could not convert IPv4 address to as-ascii in var %s, ignoring", buf2);
227 if(!inet_aton(valbuf, &newipv4))
229 flog(LOG_WARNING, "could not parse IPv4 address (%s), ignoring", valbuf);
230 memcpy(&var->val.ipv4, &var->defaults.ipv4, sizeof(var->val.ipv4));
232 if(memcmp(&newipv4, &var->val.ipv4, sizeof(newipv4)))
234 memcpy(&var->val.ipv4, &newipv4, sizeof(newipv4));
241 CBCHAINDOCB(var, conf_update, var);
246 flog(LOG_WARNING, "variable %s not found, ignoring set command", buf2);
251 flog(LOG_WARNING, "module %s not found, ignoring set command", buf);
255 for(module = modules; !handled && (module != NULL); module = module->next)
257 if(module->cmds != NULL)
259 for(cmd = module->cmds; cmd->name != NULL; cmd++)
261 if(!strcmp(cmd->name, cmdn))
264 ret = cmd->handler(argc, argv);
271 flog(LOG_WARNING, "command not found: %s", cmdn);
276 void readconfig(FILE *stream)
281 wchar_t *buf, *p, *p2;
285 buf = smalloc(sizeof(wchar_t) * 1024);
297 while((c != WEOF) && (c != L'\n'));
308 if(runconfcmd(w, words))
309 flog(LOG_WARNING, "ignoring this command on line %i", line);
323 } else if(iswspace(c)) {
326 flog(LOG_WARNING, "too many words on config line %i, ignoring rest", line);
338 flog(LOG_WARNING, "too many characters on config line %i, ignoring rest", line);
353 flog(LOG_WARNING, "too many characters on config line %i, ignoring rest", line);
361 flog(LOG_WARNING, "error on configuration stream: %s", strerror(errno));
363 flog(LOG_WARNING, "unexpected end of file");
366 /* {store,fetch}var re-opens the database every time, just in case two
367 * doldacond processes would be running simultaneously. */
368 void storevar(char *key, void *val, size_t len)
374 dbname = findfile("dc-vardb", NULL, 1);
375 if((db = gdbm_open(dbname, 0, GDBM_WRCREAT, 0666, NULL)) == NULL)
377 flog(LOG_CRIT, "could not open var database for writing, cannot continue: %s", gdbm_strerror(gdbm_errno));
382 k.dsize = strlen(key);
385 gdbm_store(db, k, v, GDBM_REPLACE);
389 void *fetchvar(char *key, size_t *lenb)
395 if((dbname = findfile("dc-vardb", NULL, 0)) == NULL)
397 if((db = gdbm_open(dbname, 0, GDBM_READER, 0666, NULL)) == NULL)
401 k.dsize = strlen(key);
402 v = gdbm_fetch(db, k);