xref: /dragonfly/games/hunt/huntd/conf.c (revision 0db87cb7)
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 }
318