19ec1a45d44ad2528b870a359f9b1012432f3123
[dragonfly.git] / games / hunt / huntd / conf.c
1 /*-
2  * David Leonard <d@openbsd.org>, 1999. Public domain.
3  *
4  * $OpenBSD: conf.c,v 1.7 2007/03/20 03:43:50 tedu Exp $
5  * $DragonFly: src/games/hunt/huntd/conf.c,v 1.3 2008/11/10 15:28:13 swildner Exp $
6  */
7 #include <sys/param.h>
8 #include <sys/types.h>
9 #include <stdio.h>
10 #include <string.h>
11 #include <dirent.h>
12 #include <stdlib.h>
13 #include <ctype.h>
14 #include <syslog.h>
15 #include <errno.h>
16
17 #include "hunt.h"
18 #include "server.h"
19 #include "conf.h"
20
21 /* Configuration option variables for the server: */
22
23 int conf_random =       1;
24 int conf_reflect =      1;
25 int conf_monitor =      1;
26 int conf_ooze =         1;
27 int conf_fly =          1;
28 int conf_volcano =      1;
29 int conf_drone =        1;
30 int conf_boots =        1;
31 int conf_scan =         1;
32 int conf_cloak =        1;
33 int conf_logerr =       1;
34 int conf_syslog =       0;
35
36 int conf_scoredecay =   15;
37 int conf_maxremove =    40;
38 int conf_linger =       90;
39
40 int conf_flytime =      20;
41 int conf_flystep =      5;
42 int conf_volcano_max =  50;
43 int conf_ptrip_face =   2;
44 int conf_ptrip_back =   95;
45 int conf_ptrip_side =   50;
46 int conf_prandom =      1;
47 int conf_preflect =     1;
48 int conf_pshot_coll =   5;
49 int conf_pgren_coll =   10;
50 int conf_pgren_catch =  10;
51 int conf_pmiss =        5;
52 int conf_pdroneabsorb = 1;
53 int conf_fall_frac =    5;
54
55 int conf_bulspd =       5;
56 int conf_ishots =       15;
57 int conf_nshots =       5;
58 int conf_maxncshot =    2;
59 int conf_maxdam =       10;
60 int conf_mindam =       5;
61 int conf_stabdam =      2;
62 int conf_killgain =     2;
63 int conf_slimefactor =  3;
64 int conf_slimespeed =   5;
65 int conf_lavaspeed =    1;
66 int conf_cloaklen =     20;
67 int conf_scanlen =      20;
68 int conf_mindshot =     2;
69 int conf_simstep =      0;
70
71
72 struct kwvar {
73         const char *    kw;
74         void *  var;
75         enum vartype { Vint, Vchar, Vstring, Vdouble } type;
76 };
77
78 static struct kwvar keywords[] = {
79         { "random",             &conf_random,           Vint },
80         { "reflect",            &conf_reflect,          Vint },
81         { "monitor",            &conf_monitor,          Vint },
82         { "ooze",               &conf_ooze,             Vint },
83         { "fly",                &conf_fly,              Vint },
84         { "volcano",            &conf_volcano,          Vint },
85         { "drone",              &conf_drone,            Vint },
86         { "boots",              &conf_boots,            Vint },
87         { "scan",               &conf_scan,             Vint },
88         { "cloak",              &conf_cloak,            Vint },
89         { "logerr",             &conf_logerr,           Vint },
90         { "syslog",             &conf_syslog,           Vint },
91         { "scoredecay",         &conf_scoredecay,       Vint },
92         { "maxremove",          &conf_maxremove,        Vint },
93         { "linger",             &conf_linger,           Vint },
94
95         { "flytime",            &conf_flytime,          Vint },
96         { "flystep",            &conf_flystep,          Vint },
97         { "volcano_max",        &conf_volcano_max,      Vint },
98         { "ptrip_face",         &conf_ptrip_face,       Vint },
99         { "ptrip_back",         &conf_ptrip_back,       Vint },
100         { "ptrip_side",         &conf_ptrip_side,       Vint },
101         { "prandom",            &conf_prandom,          Vint },
102         { "preflect",           &conf_preflect,         Vint },
103         { "pshot_coll",         &conf_pshot_coll,       Vint },
104         { "pgren_coll",         &conf_pgren_coll,       Vint },
105         { "pgren_catch",        &conf_pgren_catch,      Vint },
106         { "pmiss",              &conf_pmiss,            Vint },
107         { "pdroneabsorb",       &conf_pdroneabsorb,     Vint },
108         { "fall_frac",          &conf_fall_frac,        Vint },
109
110         { "bulspd",             &conf_bulspd,           Vint },
111         { "ishots",             &conf_ishots,           Vint },
112         { "nshots",             &conf_nshots,           Vint },
113         { "maxncshot",          &conf_maxncshot,        Vint },
114         { "maxdam",             &conf_maxdam,           Vint },
115         { "mindam",             &conf_mindam,           Vint },
116         { "stabdam",            &conf_stabdam,          Vint },
117         { "killgain",           &conf_killgain,         Vint },
118         { "slimefactor",        &conf_slimefactor,      Vint },
119         { "slimespeed",         &conf_slimespeed,       Vint },
120         { "lavaspeed",          &conf_lavaspeed,        Vint },
121         { "cloaklen",           &conf_cloaklen,         Vint },
122         { "scanlen",            &conf_scanlen,          Vint },
123         { "mindshot",           &conf_mindshot,         Vint },
124         { "simstep",            &conf_simstep,          Vint },
125
126         { NULL, NULL, Vint }
127 };
128
129 static char *
130 parse_int(char *p, struct kwvar *kvp, const char *fnm, int *linep)
131 {
132         char *valuestart, *digitstart;
133         char savec;
134         int newval;
135
136         /* expect a number */
137         valuestart = p;
138         if (*p == '-')
139                 p++;
140         digitstart = p;
141         while (isdigit(*p))
142                 p++;
143         if ((*p == '\0' || isspace(*p) || *p == '#') && digitstart != p) {
144                 savec = *p;
145                 *p = '\0';
146                 newval = atoi(valuestart);
147                 *p = savec;
148                 logx(LOG_INFO, "%s:%d: %s: %d -> %d",
149                         fnm, *linep, kvp->kw, *(int *)kvp->var, newval);
150                 *(int *)kvp->var = newval;
151                 return p;
152         } else {
153                 logx(LOG_ERR, "%s:%d: invalid integer value \"%s\"",
154                     fnm, *linep, valuestart);
155                 return NULL;
156         }
157 }
158
159 static char *
160 parse_value(char *p, struct kwvar *kvp, const char *fnm, int *linep)
161 {
162
163         switch (kvp->type) {
164         case Vint:
165                 return parse_int(p, kvp, fnm, linep);
166         case Vchar:
167         case Vstring:
168         case Vdouble:
169                 /* tbd */
170         default:
171                 abort();
172         }
173 }
174
175 static void
176 parse_line(char *buf, const char *fnm, int *line)
177 {
178         char *p;
179         char *word;
180         char *endword;
181         struct kwvar *kvp;
182         char savec;
183
184         p = buf;
185
186         /* skip leading white */
187         while (isspace(*p))
188                 p++;
189         /* allow blank lines and comment lines */
190         if (*p == '\0' || *p == '#')
191                 return;
192
193         /* walk to the end of the word: */
194         word = p;
195         if (isalpha(*p) || *p == '_') {
196                 p++;
197                 while (isalpha(*p) || isdigit(*p) || *p == '_')
198                         p++;
199         }
200         endword = p;
201
202         if (endword == word) {
203                 logx(LOG_ERR, "%s:%d: expected variable name",
204                         fnm, *line);
205                 return;
206         }
207
208         /* match the configuration variable name */
209         savec = *endword;
210         *endword = '\0';
211         for (kvp = keywords; kvp->kw; kvp++)
212                 if (strcmp(kvp->kw, word) == 0)
213                         break;
214         *endword = savec;
215
216         if (kvp->kw == NULL) {
217                 logx(LOG_ERR,
218                     "%s:%d: unrecognised variable \"%.*s\"",
219                     fnm, *line, (int)(endword - word), word);
220                 return;
221         }
222
223         /* skip whitespace */
224         while (isspace(*p))
225                 p++;
226
227         if (*p++ != '=') {
228                 logx(LOG_ERR, "%s:%d: expected `=' after %s", fnm, *line, word);
229                 return;
230         }
231
232         /* skip whitespace */
233         while (isspace(*p))
234                 p++;
235
236         /* parse the value */
237         p = parse_value(p, kvp, fnm, line);
238         if (!p)
239                 return;
240
241         /* skip trailing whitespace */
242         while (isspace(*p))
243                 p++;
244
245         if (*p && *p != '#') {
246                 logx(LOG_WARNING, "%s:%d: trailing garbage ignored",
247                         fnm, *line);
248         }
249 }
250
251
252 static void
253 load_config(FILE *f, char *fnm)
254 {
255         char buf[BUFSIZ];
256         size_t len;
257         int line;
258         char *p;
259
260         line = 0;
261         while ((p = fgetln(f, &len)) != NULL) {
262                 line++;
263                 if (p[len-1] == '\n')
264                         len--;
265                 if (len >= sizeof(buf)) {
266                         logx(LOG_ERR, "%s:%d: line too long", fnm, line);
267                         continue;
268                 }
269                 (void)memcpy(buf, p, len);
270                 buf[len] = '\0';
271                 parse_line(buf, fnm, &line);
272         }
273 }
274
275 /*
276  * load various config file, allowing later ones to
277  * overwrite earlier values
278  */
279 void
280 config(void)
281 {
282         const char *home;
283         char nm[MAXPATHLEN + 1];
284         static const char *fnms[] = {
285                 "/etc/hunt.conf",
286                 "%s/.hunt.conf",
287                 ".hunt.conf",
288                 NULL
289         };
290         int fn;
291         FILE *f;
292
293         /* All the %s's get converted to $HOME */
294         if ((home = getenv("HOME")) == NULL)
295                 home = "";
296
297         for (fn = 0; fnms[fn]; fn++) {
298                 snprintf(nm, sizeof nm, fnms[fn], home);
299                 if ((f = fopen(nm, "r")) != NULL) {
300                         load_config(f, nm);
301                         fclose(f);
302                 }
303                 else if (errno != ENOENT)
304                         logit(LOG_WARNING, "%s", nm);
305         }
306 }
307
308 /*
309  * Parse a single configuration argument given on the command line
310  */
311 void
312 config_arg(char *arg)
313 {
314         int line = 0;
315
316         parse_line(arg, "*Initialisation*", &line);
317 }