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