16693db17SSascha Wildner /*-
282a5c12eSMatthew Dillon * David Leonard <d@openbsd.org>, 1999. Public domain.
382a5c12eSMatthew Dillon *
482a5c12eSMatthew Dillon * $OpenBSD: conf.c,v 1.7 2007/03/20 03:43:50 tedu Exp $
582a5c12eSMatthew Dillon */
682a5c12eSMatthew Dillon #include <sys/param.h>
782a5c12eSMatthew Dillon #include <sys/types.h>
882a5c12eSMatthew Dillon #include <stdio.h>
982a5c12eSMatthew Dillon #include <string.h>
1082a5c12eSMatthew Dillon #include <dirent.h>
1182a5c12eSMatthew Dillon #include <stdlib.h>
1282a5c12eSMatthew Dillon #include <ctype.h>
1382a5c12eSMatthew Dillon #include <syslog.h>
1482a5c12eSMatthew Dillon #include <errno.h>
1582a5c12eSMatthew Dillon
1682a5c12eSMatthew Dillon #include "hunt.h"
1782a5c12eSMatthew Dillon #include "server.h"
1882a5c12eSMatthew Dillon #include "conf.h"
1982a5c12eSMatthew Dillon
2082a5c12eSMatthew Dillon /* Configuration option variables for the server: */
2182a5c12eSMatthew Dillon
2282a5c12eSMatthew Dillon int conf_random = 1;
2382a5c12eSMatthew Dillon int conf_reflect = 1;
2482a5c12eSMatthew Dillon int conf_monitor = 1;
2582a5c12eSMatthew Dillon int conf_ooze = 1;
2682a5c12eSMatthew Dillon int conf_fly = 1;
2782a5c12eSMatthew Dillon int conf_volcano = 1;
2882a5c12eSMatthew Dillon int conf_drone = 1;
2982a5c12eSMatthew Dillon int conf_boots = 1;
3082a5c12eSMatthew Dillon int conf_scan = 1;
3182a5c12eSMatthew Dillon int conf_cloak = 1;
3282a5c12eSMatthew Dillon int conf_logerr = 1;
3382a5c12eSMatthew Dillon int conf_syslog = 0;
3482a5c12eSMatthew Dillon
3582a5c12eSMatthew Dillon int conf_scoredecay = 15;
3682a5c12eSMatthew Dillon int conf_maxremove = 40;
3782a5c12eSMatthew Dillon int conf_linger = 90;
3882a5c12eSMatthew Dillon
3982a5c12eSMatthew Dillon int conf_flytime = 20;
4082a5c12eSMatthew Dillon int conf_flystep = 5;
4182a5c12eSMatthew Dillon int conf_volcano_max = 50;
4282a5c12eSMatthew Dillon int conf_ptrip_face = 2;
4382a5c12eSMatthew Dillon int conf_ptrip_back = 95;
4482a5c12eSMatthew Dillon int conf_ptrip_side = 50;
4582a5c12eSMatthew Dillon int conf_prandom = 1;
4682a5c12eSMatthew Dillon int conf_preflect = 1;
4782a5c12eSMatthew Dillon int conf_pshot_coll = 5;
4882a5c12eSMatthew Dillon int conf_pgren_coll = 10;
4982a5c12eSMatthew Dillon int conf_pgren_catch = 10;
5082a5c12eSMatthew Dillon int conf_pmiss = 5;
5182a5c12eSMatthew Dillon int conf_pdroneabsorb = 1;
5282a5c12eSMatthew Dillon int conf_fall_frac = 5;
5382a5c12eSMatthew Dillon
5482a5c12eSMatthew Dillon int conf_bulspd = 5;
5582a5c12eSMatthew Dillon int conf_ishots = 15;
5682a5c12eSMatthew Dillon int conf_nshots = 5;
5782a5c12eSMatthew Dillon int conf_maxncshot = 2;
5882a5c12eSMatthew Dillon int conf_maxdam = 10;
5982a5c12eSMatthew Dillon int conf_mindam = 5;
6082a5c12eSMatthew Dillon int conf_stabdam = 2;
6182a5c12eSMatthew Dillon int conf_killgain = 2;
6282a5c12eSMatthew Dillon int conf_slimefactor = 3;
6382a5c12eSMatthew Dillon int conf_slimespeed = 5;
6482a5c12eSMatthew Dillon int conf_lavaspeed = 1;
6582a5c12eSMatthew Dillon int conf_cloaklen = 20;
6682a5c12eSMatthew Dillon int conf_scanlen = 20;
6782a5c12eSMatthew Dillon int conf_mindshot = 2;
6882a5c12eSMatthew Dillon int conf_simstep = 0;
6982a5c12eSMatthew Dillon
7082a5c12eSMatthew Dillon
7182a5c12eSMatthew Dillon struct kwvar {
7282a5c12eSMatthew Dillon const char * kw;
7382a5c12eSMatthew Dillon void * var;
7482a5c12eSMatthew Dillon enum vartype { Vint, Vchar, Vstring, Vdouble } type;
7582a5c12eSMatthew Dillon };
7682a5c12eSMatthew Dillon
7782a5c12eSMatthew Dillon static struct kwvar keywords[] = {
7882a5c12eSMatthew Dillon { "random", &conf_random, Vint },
7982a5c12eSMatthew Dillon { "reflect", &conf_reflect, Vint },
8082a5c12eSMatthew Dillon { "monitor", &conf_monitor, Vint },
8182a5c12eSMatthew Dillon { "ooze", &conf_ooze, Vint },
8282a5c12eSMatthew Dillon { "fly", &conf_fly, Vint },
8382a5c12eSMatthew Dillon { "volcano", &conf_volcano, Vint },
8482a5c12eSMatthew Dillon { "drone", &conf_drone, Vint },
8582a5c12eSMatthew Dillon { "boots", &conf_boots, Vint },
8682a5c12eSMatthew Dillon { "scan", &conf_scan, Vint },
8782a5c12eSMatthew Dillon { "cloak", &conf_cloak, Vint },
8882a5c12eSMatthew Dillon { "logerr", &conf_logerr, Vint },
8982a5c12eSMatthew Dillon { "syslog", &conf_syslog, Vint },
9082a5c12eSMatthew Dillon { "scoredecay", &conf_scoredecay, Vint },
9182a5c12eSMatthew Dillon { "maxremove", &conf_maxremove, Vint },
9282a5c12eSMatthew Dillon { "linger", &conf_linger, Vint },
9382a5c12eSMatthew Dillon
9482a5c12eSMatthew Dillon { "flytime", &conf_flytime, Vint },
9582a5c12eSMatthew Dillon { "flystep", &conf_flystep, Vint },
9682a5c12eSMatthew Dillon { "volcano_max", &conf_volcano_max, Vint },
9782a5c12eSMatthew Dillon { "ptrip_face", &conf_ptrip_face, Vint },
9882a5c12eSMatthew Dillon { "ptrip_back", &conf_ptrip_back, Vint },
9982a5c12eSMatthew Dillon { "ptrip_side", &conf_ptrip_side, Vint },
10082a5c12eSMatthew Dillon { "prandom", &conf_prandom, Vint },
10182a5c12eSMatthew Dillon { "preflect", &conf_preflect, Vint },
10282a5c12eSMatthew Dillon { "pshot_coll", &conf_pshot_coll, Vint },
10382a5c12eSMatthew Dillon { "pgren_coll", &conf_pgren_coll, Vint },
10482a5c12eSMatthew Dillon { "pgren_catch", &conf_pgren_catch, Vint },
10582a5c12eSMatthew Dillon { "pmiss", &conf_pmiss, Vint },
10682a5c12eSMatthew Dillon { "pdroneabsorb", &conf_pdroneabsorb, Vint },
10782a5c12eSMatthew Dillon { "fall_frac", &conf_fall_frac, Vint },
10882a5c12eSMatthew Dillon
10982a5c12eSMatthew Dillon { "bulspd", &conf_bulspd, Vint },
11082a5c12eSMatthew Dillon { "ishots", &conf_ishots, Vint },
11182a5c12eSMatthew Dillon { "nshots", &conf_nshots, Vint },
11282a5c12eSMatthew Dillon { "maxncshot", &conf_maxncshot, Vint },
11382a5c12eSMatthew Dillon { "maxdam", &conf_maxdam, Vint },
11482a5c12eSMatthew Dillon { "mindam", &conf_mindam, Vint },
11582a5c12eSMatthew Dillon { "stabdam", &conf_stabdam, Vint },
11682a5c12eSMatthew Dillon { "killgain", &conf_killgain, Vint },
11782a5c12eSMatthew Dillon { "slimefactor", &conf_slimefactor, Vint },
11882a5c12eSMatthew Dillon { "slimespeed", &conf_slimespeed, Vint },
11982a5c12eSMatthew Dillon { "lavaspeed", &conf_lavaspeed, Vint },
12082a5c12eSMatthew Dillon { "cloaklen", &conf_cloaklen, Vint },
12182a5c12eSMatthew Dillon { "scanlen", &conf_scanlen, Vint },
12282a5c12eSMatthew Dillon { "mindshot", &conf_mindshot, Vint },
12382a5c12eSMatthew Dillon { "simstep", &conf_simstep, Vint },
12482a5c12eSMatthew Dillon
12582a5c12eSMatthew Dillon { NULL, NULL, Vint }
12682a5c12eSMatthew Dillon };
12782a5c12eSMatthew Dillon
12882a5c12eSMatthew Dillon static char *
parse_int(char * p,struct kwvar * kvp,const char * fnm,int * linep)12982a5c12eSMatthew Dillon parse_int(char *p, struct kwvar *kvp, const char *fnm, int *linep)
13082a5c12eSMatthew Dillon {
13182a5c12eSMatthew Dillon char *valuestart, *digitstart;
13282a5c12eSMatthew Dillon char savec;
13382a5c12eSMatthew Dillon int newval;
13482a5c12eSMatthew Dillon
13582a5c12eSMatthew Dillon /* expect a number */
13682a5c12eSMatthew Dillon valuestart = p;
13782a5c12eSMatthew Dillon if (*p == '-')
13882a5c12eSMatthew Dillon p++;
13982a5c12eSMatthew Dillon digitstart = p;
14082a5c12eSMatthew Dillon while (isdigit(*p))
14182a5c12eSMatthew Dillon p++;
14282a5c12eSMatthew Dillon if ((*p == '\0' || isspace(*p) || *p == '#') && digitstart != p) {
14382a5c12eSMatthew Dillon savec = *p;
14482a5c12eSMatthew Dillon *p = '\0';
14582a5c12eSMatthew Dillon newval = atoi(valuestart);
14682a5c12eSMatthew Dillon *p = savec;
14782a5c12eSMatthew Dillon logx(LOG_INFO, "%s:%d: %s: %d -> %d",
14882a5c12eSMatthew Dillon fnm, *linep, kvp->kw, *(int *)kvp->var, newval);
14982a5c12eSMatthew Dillon *(int *)kvp->var = newval;
15082a5c12eSMatthew Dillon return p;
15182a5c12eSMatthew Dillon } else {
15282a5c12eSMatthew Dillon logx(LOG_ERR, "%s:%d: invalid integer value \"%s\"",
15382a5c12eSMatthew Dillon fnm, *linep, valuestart);
15482a5c12eSMatthew Dillon return NULL;
15582a5c12eSMatthew Dillon }
15682a5c12eSMatthew Dillon }
15782a5c12eSMatthew Dillon
15882a5c12eSMatthew Dillon static char *
parse_value(char * p,struct kwvar * kvp,const char * fnm,int * linep)15982a5c12eSMatthew Dillon parse_value(char *p, struct kwvar *kvp, const char *fnm, int *linep)
16082a5c12eSMatthew Dillon {
16182a5c12eSMatthew Dillon
16282a5c12eSMatthew Dillon switch (kvp->type) {
16382a5c12eSMatthew Dillon case Vint:
16482a5c12eSMatthew Dillon return parse_int(p, kvp, fnm, linep);
16582a5c12eSMatthew Dillon case Vchar:
16682a5c12eSMatthew Dillon case Vstring:
16782a5c12eSMatthew Dillon case Vdouble:
16882a5c12eSMatthew Dillon /* tbd */
16982a5c12eSMatthew Dillon default:
17082a5c12eSMatthew Dillon abort();
17182a5c12eSMatthew Dillon }
17282a5c12eSMatthew Dillon }
17382a5c12eSMatthew Dillon
17482a5c12eSMatthew Dillon static void
parse_line(char * buf,const char * fnm,int * line)17582a5c12eSMatthew Dillon parse_line(char *buf, const char *fnm, int *line)
17682a5c12eSMatthew Dillon {
17782a5c12eSMatthew Dillon char *p;
17882a5c12eSMatthew Dillon char *word;
17982a5c12eSMatthew Dillon char *endword;
18082a5c12eSMatthew Dillon struct kwvar *kvp;
18182a5c12eSMatthew Dillon char savec;
18282a5c12eSMatthew Dillon
18382a5c12eSMatthew Dillon p = buf;
18482a5c12eSMatthew Dillon
18582a5c12eSMatthew Dillon /* skip leading white */
18682a5c12eSMatthew Dillon while (isspace(*p))
18782a5c12eSMatthew Dillon p++;
18882a5c12eSMatthew Dillon /* allow blank lines and comment lines */
18982a5c12eSMatthew Dillon if (*p == '\0' || *p == '#')
19082a5c12eSMatthew Dillon return;
19182a5c12eSMatthew Dillon
19282a5c12eSMatthew Dillon /* walk to the end of the word: */
19382a5c12eSMatthew Dillon word = p;
19482a5c12eSMatthew Dillon if (isalpha(*p) || *p == '_') {
19582a5c12eSMatthew Dillon p++;
19682a5c12eSMatthew Dillon while (isalpha(*p) || isdigit(*p) || *p == '_')
19782a5c12eSMatthew Dillon p++;
19882a5c12eSMatthew Dillon }
19982a5c12eSMatthew Dillon endword = p;
20082a5c12eSMatthew Dillon
20182a5c12eSMatthew Dillon if (endword == word) {
20282a5c12eSMatthew Dillon logx(LOG_ERR, "%s:%d: expected variable name",
20382a5c12eSMatthew Dillon fnm, *line);
20482a5c12eSMatthew Dillon return;
20582a5c12eSMatthew Dillon }
20682a5c12eSMatthew Dillon
20782a5c12eSMatthew Dillon /* match the configuration variable name */
20882a5c12eSMatthew Dillon savec = *endword;
20982a5c12eSMatthew Dillon *endword = '\0';
21082a5c12eSMatthew Dillon for (kvp = keywords; kvp->kw; kvp++)
21182a5c12eSMatthew Dillon if (strcmp(kvp->kw, word) == 0)
21282a5c12eSMatthew Dillon break;
21382a5c12eSMatthew Dillon *endword = savec;
21482a5c12eSMatthew Dillon
21582a5c12eSMatthew Dillon if (kvp->kw == NULL) {
21682a5c12eSMatthew Dillon logx(LOG_ERR,
21782a5c12eSMatthew Dillon "%s:%d: unrecognised variable \"%.*s\"",
2187383c38bSSascha Wildner fnm, *line, (int)(endword - word), word);
21982a5c12eSMatthew Dillon return;
22082a5c12eSMatthew Dillon }
22182a5c12eSMatthew Dillon
22282a5c12eSMatthew Dillon /* skip whitespace */
22382a5c12eSMatthew Dillon while (isspace(*p))
22482a5c12eSMatthew Dillon p++;
22582a5c12eSMatthew Dillon
22682a5c12eSMatthew Dillon if (*p++ != '=') {
22782a5c12eSMatthew Dillon logx(LOG_ERR, "%s:%d: expected `=' after %s", fnm, *line, word);
22882a5c12eSMatthew Dillon return;
22982a5c12eSMatthew Dillon }
23082a5c12eSMatthew Dillon
23182a5c12eSMatthew Dillon /* skip whitespace */
23282a5c12eSMatthew Dillon while (isspace(*p))
23382a5c12eSMatthew Dillon p++;
23482a5c12eSMatthew Dillon
23582a5c12eSMatthew Dillon /* parse the value */
23682a5c12eSMatthew Dillon p = parse_value(p, kvp, fnm, line);
23782a5c12eSMatthew Dillon if (!p)
23882a5c12eSMatthew Dillon return;
23982a5c12eSMatthew Dillon
24082a5c12eSMatthew Dillon /* skip trailing whitespace */
24182a5c12eSMatthew Dillon while (isspace(*p))
24282a5c12eSMatthew Dillon p++;
24382a5c12eSMatthew Dillon
24482a5c12eSMatthew Dillon if (*p && *p != '#') {
24582a5c12eSMatthew Dillon logx(LOG_WARNING, "%s:%d: trailing garbage ignored",
24682a5c12eSMatthew Dillon fnm, *line);
24782a5c12eSMatthew Dillon }
24882a5c12eSMatthew Dillon }
24982a5c12eSMatthew Dillon
25082a5c12eSMatthew Dillon
25182a5c12eSMatthew Dillon static void
load_config(FILE * f,char * fnm)25282a5c12eSMatthew Dillon load_config(FILE *f, char *fnm)
25382a5c12eSMatthew Dillon {
25482a5c12eSMatthew Dillon char buf[BUFSIZ];
25582a5c12eSMatthew Dillon size_t len;
25682a5c12eSMatthew Dillon int line;
25782a5c12eSMatthew Dillon char *p;
25882a5c12eSMatthew Dillon
25982a5c12eSMatthew Dillon line = 0;
26082a5c12eSMatthew Dillon while ((p = fgetln(f, &len)) != NULL) {
26182a5c12eSMatthew Dillon line++;
26282a5c12eSMatthew Dillon if (p[len-1] == '\n')
26382a5c12eSMatthew Dillon len--;
26482a5c12eSMatthew Dillon if (len >= sizeof(buf)) {
26582a5c12eSMatthew Dillon logx(LOG_ERR, "%s:%d: line too long", fnm, line);
26682a5c12eSMatthew Dillon continue;
26782a5c12eSMatthew Dillon }
268*d9f85b33Szrj memcpy(buf, p, len);
26982a5c12eSMatthew Dillon buf[len] = '\0';
27082a5c12eSMatthew Dillon parse_line(buf, fnm, &line);
27182a5c12eSMatthew Dillon }
27282a5c12eSMatthew Dillon }
27382a5c12eSMatthew Dillon
27482a5c12eSMatthew Dillon /*
27582a5c12eSMatthew Dillon * load various config file, allowing later ones to
27682a5c12eSMatthew Dillon * overwrite earlier values
27782a5c12eSMatthew Dillon */
27882a5c12eSMatthew Dillon void
config(void)2796beb426bSSascha Wildner config(void)
28082a5c12eSMatthew Dillon {
28182a5c12eSMatthew Dillon const char *home;
28282a5c12eSMatthew Dillon char nm[MAXPATHLEN + 1];
28382a5c12eSMatthew Dillon static const char *fnms[] = {
28482a5c12eSMatthew Dillon "/etc/hunt.conf",
28582a5c12eSMatthew Dillon "%s/.hunt.conf",
28682a5c12eSMatthew Dillon ".hunt.conf",
28782a5c12eSMatthew Dillon NULL
28882a5c12eSMatthew Dillon };
28982a5c12eSMatthew Dillon int fn;
29082a5c12eSMatthew Dillon FILE *f;
29182a5c12eSMatthew Dillon
29282a5c12eSMatthew Dillon /* All the %s's get converted to $HOME */
29382a5c12eSMatthew Dillon if ((home = getenv("HOME")) == NULL)
29482a5c12eSMatthew Dillon home = "";
29582a5c12eSMatthew Dillon
29682a5c12eSMatthew Dillon for (fn = 0; fnms[fn]; fn++) {
29782a5c12eSMatthew Dillon snprintf(nm, sizeof nm, fnms[fn], home);
29882a5c12eSMatthew Dillon if ((f = fopen(nm, "r")) != NULL) {
29982a5c12eSMatthew Dillon load_config(f, nm);
30082a5c12eSMatthew Dillon fclose(f);
30182a5c12eSMatthew Dillon }
30282a5c12eSMatthew Dillon else if (errno != ENOENT)
30382a5c12eSMatthew Dillon logit(LOG_WARNING, "%s", nm);
30482a5c12eSMatthew Dillon }
30582a5c12eSMatthew Dillon }
30682a5c12eSMatthew Dillon
30782a5c12eSMatthew Dillon /*
30882a5c12eSMatthew Dillon * Parse a single configuration argument given on the command line
30982a5c12eSMatthew Dillon */
31082a5c12eSMatthew Dillon void
config_arg(char * arg)3116beb426bSSascha Wildner config_arg(char *arg)
31282a5c12eSMatthew Dillon {
31382a5c12eSMatthew Dillon int line = 0;
31482a5c12eSMatthew Dillon
31582a5c12eSMatthew Dillon parse_line(arg, "*Initialisation*", &line);
31682a5c12eSMatthew Dillon }
317