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