1 /* $OpenBSD: conf.c,v 1.4 1999/12/12 15:08:14 d Exp $ */ 2 /* David Leonard <d@openbsd.org>, 1999. Public domain. */ 3 4 #include <stdio.h> 5 #include <string.h> 6 #include <dirent.h> 7 #include <stdlib.h> 8 #include <ctype.h> 9 #include <syslog.h> 10 #include <errno.h> 11 12 #include "hunt.h" 13 #include "server.h" 14 #include "conf.h" 15 16 /* Configuration option variables for the server: */ 17 18 int conf_random = 1; 19 int conf_reflect = 1; 20 int conf_monitor = 1; 21 int conf_ooze = 1; 22 int conf_fly = 1; 23 int conf_volcano = 1; 24 int conf_drone = 1; 25 int conf_boots = 1; 26 int conf_scan = 1; 27 int conf_cloak = 1; 28 int conf_logerr = 1; 29 int conf_syslog = 0; 30 31 int conf_scoredecay = 15; 32 int conf_maxremove = 40; 33 int conf_linger = 90; 34 35 int conf_flytime = 20; 36 int conf_flystep = 5; 37 int conf_volcano_max = 50; 38 int conf_ptrip_face = 2; 39 int conf_ptrip_back = 95; 40 int conf_ptrip_side = 50; 41 int conf_prandom = 1; 42 int conf_preflect = 1; 43 int conf_pshot_coll = 5; 44 int conf_pgren_coll = 10; 45 int conf_pgren_catch = 10; 46 int conf_pmiss = 5; 47 int conf_pdroneabsorb = 1; 48 int conf_fall_frac = 5; 49 50 int conf_bulspd = 5; 51 int conf_ishots = 15; 52 int conf_nshots = 5; 53 int conf_maxncshot = 2; 54 int conf_maxdam = 10; 55 int conf_mindam = 5; 56 int conf_stabdam = 2; 57 int conf_killgain = 2; 58 int conf_slimefactor = 3; 59 int conf_slimespeed = 5; 60 int conf_lavaspeed = 1; 61 int conf_cloaklen = 20; 62 int conf_scanlen = 20; 63 int conf_mindshot = 2; 64 int conf_simstep = 0; 65 66 67 struct kwvar { 68 char * kw; 69 void * var; 70 enum vartype { Vint, Vchar, Vstring, Vdouble } type; 71 }; 72 73 static struct kwvar keywords[] = { 74 { "random", &conf_random, Vint }, 75 { "reflect", &conf_reflect, Vint }, 76 { "monitor", &conf_monitor, Vint }, 77 { "ooze", &conf_ooze, Vint }, 78 { "fly", &conf_fly, Vint }, 79 { "volcano", &conf_volcano, Vint }, 80 { "drone", &conf_drone, Vint }, 81 { "boots", &conf_boots, Vint }, 82 { "scan", &conf_scan, Vint }, 83 { "cloak", &conf_cloak, Vint }, 84 { "logerr", &conf_logerr, Vint }, 85 { "syslog", &conf_syslog, Vint }, 86 { "scoredecay", &conf_scoredecay, Vint }, 87 { "maxremove", &conf_maxremove, Vint }, 88 { "linger", &conf_linger, Vint }, 89 90 { "flytime", &conf_flytime, Vint }, 91 { "flystep", &conf_flystep, Vint }, 92 { "volcano_max", &conf_volcano_max, Vint }, 93 { "ptrip_face", &conf_ptrip_face, Vint }, 94 { "ptrip_back", &conf_ptrip_back, Vint }, 95 { "ptrip_side", &conf_ptrip_side, Vint }, 96 { "prandom", &conf_prandom, Vint }, 97 { "preflect", &conf_preflect, Vint }, 98 { "pshot_coll", &conf_pshot_coll, Vint }, 99 { "pgren_coll", &conf_pgren_coll, Vint }, 100 { "pgren_catch", &conf_pgren_catch, Vint }, 101 { "pmiss", &conf_pmiss, Vint }, 102 { "pdroneabsorb", &conf_pdroneabsorb, Vint }, 103 { "fall_frac", &conf_fall_frac, Vint }, 104 105 { "bulspd", &conf_bulspd, Vint }, 106 { "ishots", &conf_ishots, Vint }, 107 { "nshots", &conf_nshots, Vint }, 108 { "maxncshot", &conf_maxncshot, Vint }, 109 { "maxdam", &conf_maxdam, Vint }, 110 { "mindam", &conf_mindam, Vint }, 111 { "stabdam", &conf_stabdam, Vint }, 112 { "killgain", &conf_killgain, Vint }, 113 { "slimefactor", &conf_slimefactor, Vint }, 114 { "slimespeed", &conf_slimespeed, Vint }, 115 { "lavaspeed", &conf_lavaspeed, Vint }, 116 { "cloaklen", &conf_cloaklen, Vint }, 117 { "scanlen", &conf_scanlen, Vint }, 118 { "mindshot", &conf_mindshot, Vint }, 119 { "simstep", &conf_simstep, Vint }, 120 121 { NULL } 122 }; 123 124 static char * 125 parse_int(p, kvp, fnm, linep) 126 char *p; 127 struct kwvar *kvp; 128 const char *fnm; 129 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 (*p && 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(p, kvp, fnm, linep) 160 char *p; 161 struct kwvar *kvp; 162 const char *fnm; 163 int *linep; 164 { 165 166 switch (kvp->type) { 167 case Vint: 168 return parse_int(p, kvp, fnm, linep); 169 case Vchar: 170 case Vstring: 171 case Vdouble: 172 /* tbd */ 173 default: 174 abort(); 175 } 176 } 177 178 static void 179 parse_line(buf, fnm, line) 180 char *buf; 181 char *fnm; 182 int *line; 183 { 184 char *p; 185 char *word; 186 char *endword; 187 struct kwvar *kvp; 188 char savec; 189 190 p = buf; 191 192 /* skip leading white */ 193 while (*p && isspace(*p)) 194 p++; 195 /* allow blank lines and comment lines */ 196 if (*p == '\0' || *p == '#') 197 return; 198 199 /* walk to the end of the word: */ 200 word = p; 201 if (*p && (isalpha(*p) || *p == '_')) { 202 p++; 203 while (*p && (isalpha(*p) || isdigit(*p) || *p == '_')) 204 p++; 205 } 206 endword = p; 207 208 if (endword == word) { 209 logx(LOG_ERR, "%s:%d: expected variable name", 210 fnm, *line); 211 return; 212 } 213 214 /* match the configuration variable name */ 215 savec = *endword; 216 *endword = '\0'; 217 for (kvp = keywords; kvp->kw; kvp++) 218 if (strcmp(kvp->kw, word) == 0) 219 break; 220 *endword = savec; 221 222 if (kvp->kw == NULL) { 223 logx(LOG_ERR, 224 "%s:%d: unrecognised variable \"%.*s\"", 225 fnm, *line, endword - word, word); 226 return; 227 } 228 229 /* skip whitespace */ 230 while (*p && isspace(*p)) 231 p++; 232 233 if (*p++ != '=') { 234 logx(LOG_ERR, "%s:%d: expected `=' after %s", fnm, *line, word); 235 return; 236 } 237 238 /* skip whitespace */ 239 while (*p && isspace(*p)) 240 p++; 241 242 /* parse the value */ 243 p = parse_value(p, kvp, fnm, line); 244 if (!p) 245 return; 246 247 /* skip trailing whitespace */ 248 while (*p && isspace(*p)) 249 p++; 250 251 if (*p && *p != '#') { 252 logx(LOG_WARNING, "%s:%d: trailing garbage ignored", 253 fnm, *line); 254 } 255 } 256 257 258 static void 259 load_config(f, fnm) 260 FILE * f; 261 char * fnm; 262 { 263 char buf[BUFSIZ]; 264 size_t len; 265 int line; 266 char *p; 267 268 line = 0; 269 while ((p = fgetln(f, &len)) != NULL) { 270 line++; 271 if (p[len-1] == '\n') 272 len--; 273 if (len >= sizeof(buf)) { 274 logx(LOG_ERR, "%s:%d: line too long", fnm, line); 275 continue; 276 } 277 (void)memcpy(buf, p, len); 278 buf[len] = '\0'; 279 parse_line(buf, fnm, &line); 280 } 281 } 282 283 /* 284 * load various config file, allowing later ones to 285 * overwrite earlier values 286 */ 287 void 288 config() 289 { 290 char *home; 291 char nm[MAXNAMLEN + 1]; 292 static char *fnms[] = { 293 "/etc/hunt.conf", 294 "%s/.hunt.conf", 295 ".hunt.conf", 296 NULL 297 }; 298 int fn; 299 FILE *f; 300 301 /* All the %s's get converted to $HOME */ 302 if ((home = getenv("HOME")) == NULL) 303 home = ""; 304 305 for (fn = 0; fnms[fn]; fn++) { 306 snprintf(nm, sizeof nm, fnms[fn], home); 307 if ((f = fopen(nm, "r")) != NULL) { 308 load_config(f, nm); 309 fclose(f); 310 } 311 else if (errno != ENOENT) 312 log(LOG_WARNING, "%s", nm); 313 } 314 } 315 316 /* 317 * Parse a single configuration argument given on the command line 318 */ 319 void 320 config_arg(arg) 321 char *arg; 322 { 323 int line = 0; 324 325 parse_line(arg, "*Initialisation*", &line); 326 } 327