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
24 #include <sys/types.h>
30 #include <arpa/inet.h>
40 static struct configmod *modules = NULL;
43 static void dumpconfig(void)
45 struct configmod *mod;
46 struct configvar *var;
48 for(mod = modules; mod != NULL; mod = mod->next)
50 printf("%s:\n", mod->name);
51 for(var = mod->vars; var->type != CONF_VAR_END; var++)
56 printf("\t%s: %s\n", var->name, var->val.num?"t":"f");
59 printf("\t%s: %i\n", var->name, var->val.num);
62 printf("\t%s: \"%ls\" (%i)\n", var->name, var->val.str, wcslen(var->val.str));
65 printf("\t%s: %s\n", var->name, inet_ntoa(var->val.ipv4));
73 struct configvar *confgetvar(char *modname, char *varname)
78 for(m = modules; m != NULL; m = m->next)
80 if(!strcmp(m->name, modname))
82 for(v = m->vars; v->type != CONF_VAR_END; v++)
84 if(!strcmp(v->name, varname))
93 void confregmod(struct configmod *mod)
95 struct configvar *var;
97 for(var = mod->vars; var->type != CONF_VAR_END; var++)
103 var->val.num = var->defaults.num;
105 case CONF_VAR_STRING:
106 if(var->defaults.str != NULL)
108 var->val.str = swcsdup(var->defaults.str);
114 var->val.ipv4.s_addr = var->defaults.ipv4.s_addr;
117 CBCHAININIT(var, conf_update);
123 int runconfcmd(int argc, wchar_t **argv)
125 struct configmod *module;
126 struct configvar *var;
127 struct configcmd *cmd;
130 char *cmdn, *buf, *buf2, *valbuf;
132 struct in_addr newipv4;
137 if((cmdn = icwcstombs(argv[0], "us-ascii")) == NULL)
139 flog(LOG_WARNING, "could not convert %ls to us-ascii", argv[0]);
144 if(!strcmp(cmdn, "set"))
148 if((p = wcschr(argv[1], L'.')) == NULL)
150 flog(LOG_WARNING, "illegal configuration variable format: %ls", argv[1]);
156 if((buf = icwcstombs(argv[1], "us-ascii")) == NULL)
158 flog(LOG_WARNING, "could not convert %ls to us-ascii", argv[1]);
162 if((buf2 = icwcstombs(p, "us-ascii")) == NULL)
165 flog(LOG_WARNING, "could not convert %ls to us-ascii", p);
169 for(module = modules; module != NULL; module = module->next)
171 if(!strcmp(module->name, buf) && (module->vars != NULL))
173 for(var = module->vars; var->type != CONF_VAR_END; var++)
175 if(!strcmp(var->name, buf2))
182 if(!wcscmp(argv[2], L"off") ||
183 !wcscmp(argv[2], L"false") ||
184 !wcscmp(argv[2], L"no") ||
185 !wcscmp(argv[2], L"0"))
190 } else if(!wcscmp(argv[2], L"on") ||
191 !wcscmp(argv[2], L"true") ||
192 !wcscmp(argv[2], L"yes") ||
193 !wcscmp(argv[2], L"1")) {
198 flog(LOG_WARNING, "unrecognized boolean: %ls", argv[2]);
202 num = wcstol(argv[2], &p, 0);
205 flog(LOG_WARNING, "%ls: not a number, ignoring", argv[2]);
209 flog(LOG_WARNING, "%ls: could not entirely parse as a number, ignoring trailing garbage", argv[2]);
210 if(num != var->val.num)
215 case CONF_VAR_STRING:
216 if(wcscmp(var->val.str, argv[2]))
219 var->val.str = swcsdup(argv[2]);
222 if((valbuf = icwcstombs(argv[2], "us-ascii")) == NULL)
224 flog(LOG_WARNING, "could not convert IPv4 address to as-ascii in var %s, ignoring", buf2);
226 if(!inet_aton(valbuf, &newipv4))
228 flog(LOG_WARNING, "could not parse IPv4 address (%s), ignoring", valbuf);
229 memcpy(&var->val.ipv4, &var->defaults.ipv4, sizeof(var->val.ipv4));
231 if(memcmp(&newipv4, &var->val.ipv4, sizeof(newipv4)))
233 memcpy(&var->val.ipv4, &newipv4, sizeof(newipv4));
240 CBCHAINDOCB(var, conf_update, var);
245 flog(LOG_WARNING, "variable %s not found, ignoring set command", buf2);
250 flog(LOG_WARNING, "module %s not found, ignoring set command", buf);
254 for(module = modules; !handled && (module != NULL); module = module->next)
256 if(module->cmds != NULL)
258 for(cmd = module->cmds; cmd->name != NULL; cmd++)
260 if(!strcmp(cmd->name, cmdn))
263 ret = cmd->handler(argc, argv);
270 flog(LOG_WARNING, "command not found: %s", cmdn);
275 void readconfig(FILE *stream)
280 wchar_t *buf, *p, *p2;
284 buf = smalloc(sizeof(wchar_t) * 1024);
296 while((c != WEOF) && (c != L'\n'));
307 if(runconfcmd(w, words))
308 flog(LOG_WARNING, "ignoring this command on line %i", line);
322 } else if(iswspace(c)) {
325 flog(LOG_WARNING, "too many words on config line %i, ignoring rest", line);
337 flog(LOG_WARNING, "too many characters on config line %i, ignoring rest", line);
352 flog(LOG_WARNING, "too many characters on config line %i, ignoring rest", line);
360 flog(LOG_WARNING, "error on configuration stream: %s", strerror(errno));
362 flog(LOG_WARNING, "unexpected end of file");
365 /* {store,fetch}var re-opens the database every time, just in case two
366 * doldacond processes would be running simultaneously. */
367 void storevar(char *key, void *val, size_t len)
373 dbname = findfile("dc-vardb", "dc-vardb", NULL, 1);
374 if((db = gdbm_open(dbname, 0, GDBM_WRCREAT, 0666, NULL)) == NULL)
376 flog(LOG_CRIT, "could not open var database for writing, cannot continue: %s", gdbm_strerror(gdbm_errno));
381 k.dsize = strlen(key);
384 gdbm_store(db, k, v, GDBM_REPLACE);
388 void *fetchvar(char *key, size_t *lenb)
394 if((dbname = findfile("dc-vardb", "dc-vardb", NULL, 0)) == NULL)
396 if((db = gdbm_open(dbname, 0, GDBM_READER, 0666, NULL)) == NULL)
400 k.dsize = strlen(key);
401 v = gdbm_fetch(db, k);