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