summaryrefslogtreecommitdiff
path: root/games/hunt/huntd/conf.c
blob: 26dfa531598475b54ff7cd4b464c783356fe9213 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
/*	$OpenBSD: conf.c,v 1.10 2016/01/07 21:37:53 mestre Exp $	*/
/* David Leonard <d@openbsd.org>, 1999. Public domain. */

#include <ctype.h>
#include <dirent.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <syslog.h>

#include "hunt.h"
#include "server.h"

/* Configuration option variables for the server: */

int conf_random =	1;
int conf_reflect =	1;
int conf_monitor =	1;
int conf_ooze =		1;
int conf_fly =		1;
int conf_volcano =	1;
int conf_drone =	1;
int conf_boots =	1;
int conf_scan =		1;
int conf_cloak =	1;
int conf_logerr =	1;
int conf_syslog =	0;

int conf_scoredecay =	15;
int conf_maxremove =	40;
int conf_linger =	90;

int conf_flytime =	20;
int conf_flystep =	5;
int conf_volcano_max =	50;
int conf_ptrip_face =	2;
int conf_ptrip_back =	95;
int conf_ptrip_side =	50;
int conf_prandom =	1;
int conf_preflect =	1;
int conf_pshot_coll =	5;
int conf_pgren_coll =	10;
int conf_pgren_catch =	10;
int conf_pmiss =	5;
int conf_pdroneabsorb =	1;
int conf_fall_frac =	5;

int conf_bulspd =	5;
int conf_ishots =	15;
int conf_nshots =	5;
int conf_maxncshot =	2;
int conf_maxdam =	10;
int conf_mindam =	5;
int conf_stabdam =	2;
int conf_killgain =	2;
int conf_slimefactor =	3;
int conf_slimespeed =	5;
int conf_lavaspeed =	1;
int conf_cloaklen =	20;
int conf_scanlen =	20;
int conf_mindshot =	2;
int conf_simstep =	0;


struct kwvar {
	char *	kw;
	void *	var;
	enum vartype { Vint, Vchar, Vstring, Vdouble } type;
};

static struct kwvar keywords[] = {
	{ "random",		&conf_random,		Vint },
	{ "reflect",		&conf_reflect,		Vint },
	{ "monitor",		&conf_monitor,		Vint },
	{ "ooze",		&conf_ooze,		Vint },
	{ "fly",		&conf_fly,		Vint },
	{ "volcano",		&conf_volcano,		Vint },
	{ "drone",		&conf_drone,		Vint },
	{ "boots",		&conf_boots,		Vint },
	{ "scan",		&conf_scan,		Vint },
	{ "cloak",		&conf_cloak,		Vint },
	{ "logerr",		&conf_logerr,		Vint },
	{ "syslog",		&conf_syslog,		Vint },
	{ "scoredecay",		&conf_scoredecay,	Vint },
	{ "maxremove",		&conf_maxremove,	Vint },
	{ "linger",		&conf_linger,		Vint },

	{ "flytime",		&conf_flytime,		Vint },
	{ "flystep",		&conf_flystep,		Vint },
	{ "volcano_max",	&conf_volcano_max,	Vint },
	{ "ptrip_face",		&conf_ptrip_face,	Vint },
	{ "ptrip_back",		&conf_ptrip_back,	Vint },
	{ "ptrip_side",		&conf_ptrip_side,	Vint },
	{ "prandom",		&conf_prandom,		Vint },
	{ "preflect",		&conf_preflect,		Vint },
	{ "pshot_coll",		&conf_pshot_coll,	Vint },
	{ "pgren_coll",		&conf_pgren_coll,	Vint },
	{ "pgren_catch",	&conf_pgren_catch,	Vint },
	{ "pmiss",		&conf_pmiss,		Vint },
	{ "pdroneabsorb",	&conf_pdroneabsorb,	Vint },
	{ "fall_frac",		&conf_fall_frac,	Vint },

	{ "bulspd",		&conf_bulspd,		Vint },
	{ "ishots",		&conf_ishots,		Vint },
	{ "nshots",		&conf_nshots,		Vint },
	{ "maxncshot",		&conf_maxncshot,	Vint },
	{ "maxdam",		&conf_maxdam,		Vint },
	{ "mindam",		&conf_mindam,		Vint },
	{ "stabdam",		&conf_stabdam,		Vint },
	{ "killgain",		&conf_killgain,		Vint },
	{ "slimefactor",	&conf_slimefactor,	Vint },
	{ "slimespeed",		&conf_slimespeed,	Vint },
	{ "lavaspeed",		&conf_lavaspeed,	Vint },
	{ "cloaklen",		&conf_cloaklen,		Vint },
	{ "scanlen",		&conf_scanlen,		Vint },
	{ "mindshot",		&conf_mindshot,		Vint },
	{ "simstep",		&conf_simstep,		Vint },

	{ NULL, NULL, Vint }
};

static char *
parse_int(char *p, struct kwvar *kvp, const char *fnm, int *linep)
{
	char *valuestart, *digitstart;
	char savec;
	int newval;

	/* expect a number */
	valuestart = p;
	if (*p == '-') 
		p++;
	digitstart = p;
	while (isdigit((unsigned char)*p))
		p++;
	if ((*p == '\0' || isspace((unsigned char)*p) || *p == '#') &&
	    digitstart != p) {
		savec = *p;
		*p = '\0';
		newval = atoi(valuestart);
		*p = savec;
		logx(LOG_INFO, "%s:%d: %s: %d -> %d", 
			fnm, *linep, kvp->kw, *(int *)kvp->var, newval);
		*(int *)kvp->var = newval;
		return p;
	} else {
		logx(LOG_ERR, "%s:%d: invalid integer value \"%s\"", 
		    fnm, *linep, valuestart);
		return NULL;
	}
}

static char *
parse_value(char *p, struct kwvar *kvp, const char *fnm, int *linep)
{

	switch (kvp->type) {
	case Vint:
		return parse_int(p, kvp, fnm, linep);
	case Vchar:
	case Vstring:
	case Vdouble:
		/* tbd */
	default:
		abort();
	}
}

static void
parse_line(char *buf, char *fnm, int *line)
{
	char *p;
	char *word;
	char *endword;
	struct kwvar *kvp;
	char savec;

	p = buf;

	/* skip leading white */
	while (isspace((unsigned char)*p))
		p++;
	/* allow blank lines and comment lines */
	if (*p == '\0' || *p == '#')
		return;

	/* walk to the end of the word: */
	word = p;
	if (isalpha((unsigned char)*p) || *p == '_') {
		p++;
		while (isalpha((unsigned char)*p) || isdigit((unsigned char)*p) || *p == '_')
			p++;
	}
	endword = p;

	if (endword == word) {
		logx(LOG_ERR, "%s:%d: expected variable name",
			fnm, *line);
		return;
	}

	/* match the configuration variable name */
	savec = *endword;
	*endword = '\0';
	for (kvp = keywords; kvp->kw; kvp++) 
		if (strcmp(kvp->kw, word) == 0)
			break;
	*endword = savec;

	if (kvp->kw == NULL) {
		logx(LOG_ERR, 
		    "%s:%d: unrecognised variable \"%.*s\"", 
		    fnm, *line, endword - word, word);
		return;
	}

	/* skip whitespace */
	while (isspace((unsigned char)*p))
		p++;

	if (*p++ != '=') {
		logx(LOG_ERR, "%s:%d: expected `=' after %s", fnm, *line, word);
		return;
	}

	/* skip whitespace */
	while (isspace((unsigned char)*p))
		p++;

	/* parse the value */
	p = parse_value(p, kvp, fnm, line);
	if (!p) 
		return;

	/* skip trailing whitespace */
	while (isspace((unsigned char)*p))
		p++;

	if (*p && *p != '#') {
		logx(LOG_WARNING, "%s:%d: trailing garbage ignored",
			fnm, *line);
	}
}


static void
load_config(FILE *f, char *fnm)
{
	char buf[BUFSIZ];
	size_t len;
	int line;
	char *p;

	line = 0;
	while ((p = fgetln(f, &len)) != NULL) {
		line++;
		if (p[len-1] == '\n')
			len--;
		if (len >= sizeof(buf)) {
			logx(LOG_ERR, "%s:%d: line too long", fnm, line);
			continue;
		}
		(void)memcpy(buf, p, len);
		buf[len] = '\0';
		parse_line(buf, fnm, &line);
	}
}

/*
 * load various config file, allowing later ones to 
 * overwrite earlier values
 */
void
config(void)
{
	char *home;
	char nm[MAXNAMLEN + 1];
	static char *fnms[] = { 
		"/etc/hunt.conf",
		"%s/.hunt.conf", 
		".hunt.conf", 
		NULL
	};
	int fn;
	FILE *f;

	/* All the %s's get converted to $HOME */
	if ((home = getenv("HOME")) == NULL)
		home = "";

	for (fn = 0; fnms[fn]; fn++) {
		snprintf(nm, sizeof nm, fnms[fn], home);
		if ((f = fopen(nm, "r")) != NULL) {
			load_config(f, nm);
			fclose(f);
		} 
		else if (errno != ENOENT)
			logit(LOG_WARNING, "%s", nm);
	}
}

/*
 * Parse a single configuration argument given on the command line
 */
void
config_arg( char *arg)
{
	int line = 0;

	parse_line(arg, "*Initialisation*", &line);
}