xref: /openbsd/games/hunt/huntd/conf.c (revision f3c23159)
1 /*	$OpenBSD: conf.c,v 1.14 2022/08/08 17:57:05 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, stdin)) != -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