xref: /dragonfly/games/hunt/huntd/conf.c (revision a4da4a90)
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 *
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 *
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
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
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
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
311 config_arg(char *arg)
312 {
313 	int line = 0;
314 
315 	parse_line(arg, "*Initialisation*", &line);
316 }
317