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