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