#include // FILE, #include // atoi #include // isdigit #include // always #include "conf_meta.h" // me #include "support_meta.h" // strmatch #include "osdep.h" // strtok, MConfig::MConfig(void) : list(NULL), filename(NULL), debuglevel(0), gamedll(NULL), plugins_file(NULL), exec_cfg(NULL) { } // Initialize default values from the stored options struct. Has to happen // _after_ constructor, so that all the fields are allocated (d'oh). void DLLINTERNAL MConfig::init(option_t *global_options) { option_t *optp; list=global_options; for(optp=list; optp->name; optp++) set(optp, optp->init); } option_t * DLLINTERNAL MConfig::find(const char *lookup) { option_t *optp; for(optp=list; optp->name && !strmatch(optp->name, lookup); optp++); if(optp->name) return(optp); else RETURN_ERRNO(NULL, ME_NOTFOUND); } mBOOL DLLINTERNAL MConfig::set(const char *key, const char *value) { option_t *optp; optp=find(key); if(optp) return(set(optp, value)); else RETURN_ERRNO(mFALSE, ME_NOTFOUND); } mBOOL DLLINTERNAL MConfig::set(option_t *setp, const char *setstr) { //char pathbuf[PATH_MAX]; int *optval = (int *) setp->dest; char **optstr = (char **) setp->dest; // cvar_t *optcvar = (cvar_t *) setp->dest; // SETOPT_FN optcmd = (SETOPT_FN) setp->dest; if(!setstr) return(mTRUE); switch(setp->type) { case CF_INT: if(!isdigit(setstr[0])) { META_WARNING("option '%s' invalid format '%s'", setp->name, setstr); RETURN_ERRNO(mFALSE, ME_FORMAT); } *optval=atoi(setstr); META_DEBUG(3, ("set config int: %s = %d", setp->name, *optval)); break; case CF_BOOL: if(strcasematch(setstr, "true") || strcasematch(setstr, "yes") || strmatch(setstr, "1")) { *optval=1; } else if(strcasematch(setstr, "false") || strcasematch(setstr, "no") || strmatch(setstr, "0")) { *optval=0; } else { META_WARNING("option '%s' invalid format '%s'", setp->name, setstr); RETURN_ERRNO(mFALSE, ME_FORMAT); } META_DEBUG(3, ("set config bool: %s = %s", setp->name, *optval ? "true" : "false")); break; case CF_STR: if(*optstr) free(*optstr); *optstr=strdup(setstr); META_DEBUG(3, ("set config string: %s = %s", setp->name, *optstr)); break; case CF_PATH: /* force load if(*optstr) free(*optstr); full_gamedir_path(setstr, pathbuf); *optstr=strdup(pathbuf); META_DEBUG(3, ("set config path: %s = %s", setp->name, *optstr)); */ break; #if 0 case CF_CVAR: CVAR_SET_STRING(optcvar->name, setstr); META_DEBUG(3, ("set config cvar: %s = %s", optcvar->name, setstr)); break; case CF_CMD: optcmd(setp->name, setstr); META_DEBUG(3, ("set config command: %s, %s", optcvar->name, setstr)); break; #endif default: META_WARNING("unrecognized config type '%d'", setp->type); RETURN_ERRNO(mFALSE, ME_ARGUMENT); } return(mTRUE); } mBOOL DLLINTERNAL MConfig::load(const char *fn) { FILE *fp; char loadfile[PATH_MAX]; char line[MAX_CONF_LEN]; char *optname, *optval; option_t *optp; int ln; // Make full pathname (from gamedir if relative, collapse "..", // backslashes, etc). full_gamedir_path(fn, loadfile); fp=fopen(loadfile, "r"); if(!fp) { META_WARNING("unable to open config file '%s': %s", loadfile, strerror(errno)); RETURN_ERRNO(mFALSE, ME_NOFILE); } META_DEBUG(2, ("Loading from config file: %s", loadfile)); for(ln=1; !feof(fp) && fgets(line, sizeof(line), fp); ln++) { if(line[0]=='#') continue; if(line[0]==';') continue; if(strnmatch(line, "//", 2)) continue; if(!(optname=strtok(line, " \t\r\n"))) { META_WARNING("'%s' line %d: bad config format: missing option", loadfile, ln); continue; } if(!(optval=strtok(NULL, "\r\n"))) { META_WARNING("'%s' line %d: bad config format: missing value", loadfile, ln); continue; } if(!(optp=find(optname))) { META_WARNING("'%s' line %d: unknown option name '%s'", loadfile, ln, optname); continue; } if(!set(optp, optval)) { META_WARNING("'%s' line %d: unable to set option '%s' value '%s'", loadfile, ln, optname, optval); continue; } } filename=strdup(loadfile); fclose(fp); return(mTRUE); } void DLLINTERNAL MConfig::show(void) { option_t *optp; if(filename) META_CONS("%s and %s:", "Config options from localinfo", filename); else META_CONS("%s:", "Config options from localinfo"); for(optp=list; optp->name; optp++) { int *optval = (int *) optp->dest; char **optstr = (char **) optp->dest; // cvar_t *optcvar = (cvar_t *) optp->dest; // SETOPT_FN optcmd = (SETOPT_FN) optp->dest; switch(optp->type) { case CF_INT: META_CONS(" %-20s\t%d\n", optp->name, *optval); break; case CF_BOOL: META_CONS(" %-20s\t%s\n", optp->name, *optval ? "true" : "false"); break; case CF_STR: case CF_PATH: META_CONS(" %-20s\t%s\n", optp->name, *optstr ? *optstr : ""); break; #if 0 case CF_CVAR: META_CONS(" %-20s\tstores in: %s\n", optp->name, optcvar->name); break; case CF_CMD: META_CONS(" %-20s\tparsed by: %d\n", optp->name, (int) optcmd); break; #endif case CF_NONE: break; } } }