Check-in Lasker-2.2.3 tar ball from samba.org
[capablanca.git] / lasker-2.2.3 / src / config.c
1 /*
2   global configuration option handler for lasker chess server
3
4    Copyright (C) Andrew Tridgell 2002
5    
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2 of the License, or
9    (at your option) any later version.
10    
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15    
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 #include "includes.h"
22
23 /* database for holding config info */
24 static TDB_CONTEXT *config_db;
25
26 static int config_set(const char *name, char *value);
27
28 /*
29   tdb logging function, just in case something goes wrong we log database errors to stderr
30  */
31 static void tdb_log_fn(TDB_CONTEXT *t, int level, const char *format, ...)
32 {
33         va_list ap;
34         
35         va_start(ap, format);
36         vfprintf(stderr, format, ap);
37         va_end(ap);
38 }
39
40
41 /* 
42    initialise the config database with some default values. This is only called once
43    on initial installation
44    returns 0 on success
45  */
46 static int config_init(void)
47 {
48         config_db = tdb_open_ex(CONFIG_DB, 0, 0, O_RDWR|O_CREAT, 0600, tdb_log_fn);
49         if (!config_db) {
50                 d_printf("Failed to create the config database!\n");
51                 return -1;
52         }
53
54         /* a few important defaults */
55         config_set("DEFAULT_PROMPT", "fics% ");
56         config_set("GUEST_LOGIN", "guest");
57
58         /* this allows an initial admin connection */
59         return config_set("HEAD_ADMIN", "admin");
60 }
61
62 /* close the config database */
63 void config_close(void)
64 {
65         if (!config_db) return;
66         tdb_close(config_db);
67         config_db = NULL;
68 }
69
70 /* 
71    open the config database
72    returns 0 on success
73  */
74 int config_open(void)
75 {
76         config_db = tdb_open_ex(CONFIG_DB, 0, 0, O_RDWR, 0600, tdb_log_fn);
77         if (!config_db && errno == ENOENT) {
78                 return config_init();
79         }
80         if (!config_db) {
81                 return -1;
82         }
83         return 0;
84 }
85
86 /* 
87    fetch a value from the config database - caller must free 
88 */
89 const char *config_get(const char *name)
90 {
91         TDB_DATA data;
92         TDB_DATA key;
93
94         key.dptr = name;
95         key.dsize = strlen(name)+1;
96
97         data = tdb_fetch(config_db, key);
98
99         /* this trick allows config variables to show up in 'aconfig' as
100            soon as they are used */
101         if (!data.dptr && config_set(name, "NOT_CONFIGURED") == 0) {
102                 data = tdb_fetch(config_db, key);
103         }
104
105         return data.dptr;
106 }
107
108
109 /* 
110    fetch an integer value from the config database, with a default value
111 */
112 int config_get_int(const char *name, int default_v)
113 {
114         TDB_DATA data;
115         TDB_DATA key;
116         int v;
117
118         key.dptr = name;
119         key.dsize = strlen(name)+1;
120
121         data = tdb_fetch(config_db, key);
122
123         /* this trick allows config variables to show up in 'aconfig' as
124            soon as they are used */
125         if (!data.dptr) {
126                 char *s = NULL;
127                 data.dsize = asprintf(&s, "%d", default_v) + 1;
128                 data.dptr = s;
129                 tdb_store(config_db, key, data, TDB_REPLACE);
130         }
131
132         v = atoi(data.dptr);
133         free(data.dptr);
134
135         return v;
136 }
137
138
139 /* 
140    set a configration variable. 
141    Returns 0 on success 
142 */
143 static int config_set(const char *name, char *value)
144 {
145         TDB_DATA data;
146         TDB_DATA key;
147         int ret;
148
149         key.dptr = name;
150         key.dsize = strlen(name)+1;
151         
152         if (strcmp(value, "-") == 0) {
153                 return tdb_delete(config_db, key);
154         }
155
156         data.dptr = value;
157         data.dsize = strlen(value)+1;
158   
159         ret = tdb_store(config_db, key, data, TDB_REPLACE);
160         return ret;
161 }
162
163 /* 
164    fetch a value from the config database - will be auto-freed on a future call
165    to config_get_tmp()
166 */
167 const char *config_get_tmp(const char *name)
168 {
169         static const char *ret[10];
170         static unsigned idx;
171         const char **p = &ret[idx];
172         idx = (idx+1) % 10;
173         if (*p) {
174                 free(*p);
175         }
176         *p = config_get(name);
177         return *p;
178 }
179
180
181 /*
182   dump the current config
183  */
184 static void config_dump(int p)
185 {
186         TDB_DATA data1, data2;
187   
188         /* looping using firstkey/nextkey is a pain ... */
189         for (data1 = tdb_firstkey(config_db); 
190              data1.dptr; 
191              data2 = data1, 
192                      data1 = tdb_nextkey(config_db, data2), 
193                      free(data2.dptr)) {
194                 pprintf(p, "%s = %s\n", data1.dptr, config_get_tmp(data1.dptr));
195         }
196 }
197
198 /*
199  * aconfig
200  *
201  * Usage: aconfig variable value
202  *
203  *   sets the config variable 'variable' to 'value'
204  */
205 int com_aconfig(int p, param_list param)
206 {
207         if (param[0].type == TYPE_NULL) {
208                 /* if no parameters are given then dump the current config */
209                 config_dump(p);
210                 return COM_OK;
211         }
212
213         if (config_set(param[0].val.word, param[1].val.string) != 0) {
214                 return COM_FAILED;
215         }
216   
217         return COM_OK;
218 }