Files can be included as "include foo" in .crawlrc instead of using the Lua call: : crawl.read_options('foo'). include foo and the Lua crawl.read_options('foo') are not equivalent - Lua only runs after the start of a new game, which is too late for some option settings.
Crawl searches for included files in this sequence:
The data file search path now includes settings/ for when we move rc stuff to settings/
.gitignore: ignore saves and morgue dirs correctly.
git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@5256 c06c8d41-db1a-0410-9941-cceddc491573
C55G5JGGSVWMU7XVEJL6YZZLDXQZGRN7JQOAALS6WIKFPX3L2U6QC 6WG4FW67ZXR3BLWHCIGJGHWJO4AKVG3HT5JQL7FVSYFE76PLFVOQC SRQJVKQVUY7QGCEBA2VQTWEJ7ADIUSY7L46HJQSQNM5DXYRRH5KAC QEEJFAETO6B2J4IWDIDCJ5UNIFNNHHG22IWF2CUJRTJJBNE47CWQC AM7QPHDAWNXHLUEVUHVRHG2RO2DOIEFFU4GV3DCIROW6O5HW7H4AC GVDKSZGU5NDWQAADOPCIURSBQG2T7VMFDKAF75Z5T3KVVP6744VQC KI2WFER7ZCET4FVNEJ2UTK2AEYLTJ6R5OSRJG3Q3EHOEPLZC2BTQC K2CS6TCX2NDVL2ASEHGP4J4K4IJ6FP3ANNKTSIWVG43HPYSBX6ZQC RPOZZWKG5GLPHVZZ7ZKMKS64ZMV2LDCQSARBJFJ6FZOTOKCQO7FAC 4O3VTUJT5T7NBNF3Q45XO2WHS6TCJXVLH6CKX4K36WUBDRT5F6KAC VXSORUQOM2VZA4CAZDC6KPAY373NQIN3UT7CXQXTRCYXO2WM62DAC GQL5SIGBHLU3FMCE54XVGLRY5AZHRM6DUEB722REA2DPLGJSN6EQC SVY2PTCLXR3KNPQAWXVXTTGCC5DR334HOAKHYO3VDDRWM2BWMALAC SDLKLUNFGVKDS55DDJZCBAVIB7NL3RRYPTACAY65SCUQKV6APFSAC V4WGXVERZ34B7CEINV4D3ZYEKKT2TUIUYTOX5FSOX6B26U3DPVLQC QXQE7C5XDYNF4JSHGDAVMS7HYLOC6YEZFOVFJ3RD7RB6U4AJSFIQC O6ZMFKDI3XO2SWPNEYHIPYFDWJR4TVDP5BAATK6LVCVETQID6E7AC O3QBT2ISABMEWTNSYEJKAJG6LZMON7U6RQZDSLY2KQHSMILUYQFQC 547JREUJXTZNYVGHNNAET5F5O5JYYGNTDQB6ABZNT7YX5EY64OHAC T3V75V2CMAABSOXKSGCC6ZTI2WBKSVSGUEF2QAGM2BWLVRIL6SQQC LOAHVKQFG57THOYHK6ONP5YUUO2WATATFTW3IETBPJZ5NYO3KZ5AC Z3RI4XAN7J2GUABAQ5G6YIOQYMBOAEQFFGRBWHMUEB2A2QYXO5MQC GSQ72ULBSL6WBJZUB3GJKAPQDXZIQV7B2TDBA5OP2WVGHVJMCQFQC WLX2RQMMOMP2PYPAGJRM4VFD2WTLJTOAZZPPY3MV76FU2EGEJ54QC ASLW3Z5PAVZSWJEMMMVZT226P44EKSAD47QS72JIFJESAI3RPN3AC BWAQ3FHBBM6G3K3KYP75CRTR343RDQZJRYX5ZGYUEXYBAC3APDLAC 5UVDIVD4NSXA52U4QMQIVST3GSZJ2A2YZK3RUEXKPM43YVQ7LI5AC NCDWWDJQLAU5ORSAQGZKJJ5E22VTDGGPJMVVBWQFHQ2B3U3UFHDQC 3ZNI2YMHYXRVEONY5CGWXSRMFSLOATZMKU7H6HRY3CC2W6OZAM7QC HNXKX6ZDQJV33E7UKZOLBYWJMRZ4QLEMXVXJZNRCTOIG2KVRTIEAC 5B5DP5S6A6LQMKZYVLQAEMHQZWFWYDHPCKQGRNSCNNYIBQYZ6BIQC SH6NU4H5TG4O7CRXRHZ7MDHABZLWWXQ77NJDBHI7KCVHXHQYK46QC QYDFLJPRJ3GKULPAMHDSTR4JFASE5T45FPQYXJ25PWVN77KFKPGAC NXVPOFYKJFWQWKVPQUMWH2Y2KJEZX44BUOBFJ4JD4KFGPEGYHG4QC OB4OY6HAYGB5LZ2VQSD2S7EG5M3YDDXIIMXM4EGIZ4BVO5IICWWQC K2MLPJIAXXZRWEWZCNSGICCBNIU2WAAPT7SPIMOH7FLLTOB4QFRAC TP5EDQXPVPTKQYTAMN3VQYHM4WRT2RNIR4EDLWLDAV2OQGKSB6KAC CH7JECYYH35H4TRHRNRTRJCQTQLZ2WRH62TKV72SUIU2RTK5OH7AC 2VDLCWQOJPOXPJQ7XYGOWZG5P2AE44DGFHC76WI4GBOOK4B7FQTQC 72GIZBEMQLEF3TITOHABWHRLL5TE7KOUSVWOUEHFMO2OZQ4EIB7AC THEWZBBFONK266AMYIIFQ4SFGZMTMU62ZO2Y43UMCDD6DDBSDYKAC YL67KHG3TAZXJCWGRZPVASD6RS2SQ3V5KMIUK4E6PV43V2NBOLEAC EHSY6DVGUMI6C67WKET3GDJVLWJWGYBYQONNDK5JVT7BCTHBEZVAC D77K7ISUWRLGNSQGYH5P2KEJZCNYQHDZC5AMLSKTXVBIRNG6F5KQC 4VK7VHWRVRO66BRSGTBPSYJGGXLRF6AG6G74UDTPHTPXR7ZRNINQC msg += init_file_location;
if (init_found){#ifdef DGAMELAUNCH// For dgl installs, show only the last segment of the .crawlrc// file name so that we don't leak details of the directory// structure to (untrusted) users.msg += get_base_filename(Options.filename);#elsemsg += Options.filename;#endifmsg += ".)";}else{msg += init_file_error;msg += ", using defaults.";}
FILE* f = NULL;char name_buff[kPathLen];
// -rc option always wins.if (!SysEnv.crawl_rc.empty())return (SysEnv.crawl_rc);// If we have any rcdirs, look in them for files from the// rc_dir_names list.for (int i = 0, size = SysEnv.rcdirs.size(); i < size; ++i){for (unsigned n = 0; n < ARRAYSZ(rc_dir_filenames); ++n){const std::string rc(catpath(SysEnv.rcdirs[i], rc_dir_filenames[n]));if (file_exists(rc))return (rc);}}
snprintf( name_buff, sizeof name_buff, "%s%s",locations_data[i][0], locations_data[i][1] );f = fopen( name_buff, "r" );
const std::string rc =catpath(locations_data[i][0], locations_data[i][1]);if (file_exists(rc))return (rc);
}}bool game_options::include_file_directive(const std::string &line,bool runscript){const std::string prefix = "include ";if (line.find(prefix) == std::string::npos)return (false);std::string include_line = trimmed_string(line);if (include_line.find(prefix) == 0){include(trimmed_string(include_line.substr(prefix.length())),true, runscript);return (true);
// Checks an include file name for safety and resolves it to a readable path.// If safety check fails, throws a string with the reason for failure.// If file cannot be resolved, returns the empty string (this does not throw!)// If file can be resolved, returns the resolved path.std::string game_options::resolve_include(std::string parent_file,std::string included_file,const std::vector<std::string> *rcdirs)throw (std::string){// Before we start, make sure we convert forward slashes to the platform's// favoured file separator.parent_file = canonicalise_file_separator(parent_file);included_file = canonicalise_file_separator(included_file);// How we resolve include paths:// 1. If it's an absolute path, use it directly.// 2. Try the name relative to the parent filename, if supplied.// 3. Try the name relative to any of the provided rcdirs.// 4. Try locating the name as a regular data file (also checks for the// file name relative to the current directory).// 5. Fail, and return empty string.assert_read_safe_path(included_file);
// There's only so much you can do with an absolute path.// Note: absolute paths can only get here if we're not on a// multiuser system. On multiuser systems assert_read_safe_path()// will throw an exception if it sees absolute paths.if (is_absolute_path(included_file))return (file_exists(included_file)? included_file : "");if (!parent_file.empty()){const std::string candidate =get_path_relative_to(parent_file, included_file);if (file_exists(candidate))return (candidate);}if (rcdirs){const std::vector<std::string> &dirs(*rcdirs);for (int i = 0, size = dirs.size(); i < size; ++i){const std::string candidate( catpath(dirs[i], included_file) );if (file_exists(candidate))return (candidate);}}return datafile_path(included_file, false, true);}std::string game_options::resolve_include(const std::string &file,const char *type){try{const std::string resolved =resolve_include(this->filename, file, &SysEnv.rcdirs);if (resolved.empty())report_error(make_stringf("Cannot find %sfile \"%s\".",type, file.c_str()));return (resolved);}catch (const std::string &err){report_error(make_stringf("Cannot include %sfile: %s", type, err.c_str()));return "";}}bool game_options::was_included(const std::string &file) const{return (included.find(file) != included.end());}void game_options::include(const std::string &rawfilename,bool resolve,bool runscript){const std::string include_file =resolve ? resolve_include(rawfilename) : rawfilename;if (was_included(include_file)){// Report error with rawfilename, not the resolved file name - we// don't want to leak file paths in dgamelaunch installs.report_error(make_stringf("Skipping previously included file: \"%s\".",rawfilename.c_str()));return;}included.insert(include_file);// Change this->filename to the included filename while we're reading it.unwind_var<std::string> optfile(this->filename, include_file);FILE* f = fopen( include_file.c_str(), "r" );if (f){FileLineInput fl(f);read_options(fl, runscript);fclose(f);}}void game_options::report_error(const std::string &error){// If called before game starts, log a startup error,// otherwise spam the warning channel.if (crawl_state.need_save)mprf(MSGCH_WARN, "Warning: %s", error.c_str());elsecrawl_state.add_startup_error(error);}
static const char *cmd_ops[] = { "scores", "name", "race", "class","pizza", "plain", "dir", "rc", "tscores","vscores", "scorefile", "morgue","macro", "mapstat" };
static const char *cmd_ops[] = {"scores", "name", "race", "class", "pizza", "plain", "dir", "rc","rcdir", "tscores", "vscores", "scorefile", "morgue", "macro","mapstat"};
// system_environmentvoid system_environment::add_rcdir(const std::string &dir){std::string cdir = canonicalise_file_separator(dir);if (dir_exists(cdir))rcdirs.push_back(cdir);elseend(1, false, "Cannot find -rcdir \"%s\"", cdir.c_str());}///////////////////////////////////////////////////////////////////////
}bool is_absolute_path(const std::string &path){return (!path.empty()&& (path[0] == FILE_SEPARATOR#if defined(WIN32CONSOLE) || defined(WIN32TILES)|| path.find(':') != std::string::npos#endif));}// Concatenates two paths, separating them with FILE_SEPARATOR if necessary.// Assumes that the second path is not absolute.//// If the first path is empty, returns the second unchanged. The second path// may be absolute in this case.std::string catpath(const std::string &first, const std::string &second){if (first.empty())return (second);std::string directory = first;if (directory[directory.length() - 1] != FILE_SEPARATOR)directory += FILE_SEPARATOR;directory += second;return (directory);}// Given a relative path and a reference file name, returns the relative path// suffixed to the directory containing the reference file name. Assumes that// the second path is not absolute.std::string get_path_relative_to(const std::string &referencefile,const std::string &relativepath){return catpath(get_parent_directory(referencefile),relativepath);
}return (true);}// Checks whether the given path is safe to read from. A path is safe if:// 1. If Unix: It contains no shell metacharacters.// 2. If DATA_DIR_PATH is set: the path is not an absolute path.// 3. If DATA_DIR_PATH is set: the path contains no ".." sequence.void assert_read_safe_path(const std::string &path) throw (std::string){// Check for rank tomfoolery first:if (path.empty())throw "Empty file name.";#ifdef UNIXif (!shell_safe(path.c_str()))throw make_stringf("\"%s\" contains bad characters.",path.c_str());#endif#ifdef DATA_DIR_PATHif (is_absolute_path(path))throw make_stringf("\"%s\" is an absolute path.", path.c_str());if (path.find("..") != std::string::npos)throw make_stringf("\"%s\" contains \"..\" sequences.",path.c_str());#endif// Path is okay.}bool is_read_safe_path(const std::string &path){try{assert_read_safe_path(path);
void include(const std::string &file, bool resolve, bool runscript);void report_error(const std::string &error);std::string resolve_include(const std::string &file,const char *type = "");bool was_included(const std::string &file) const;static std::string resolve_include(std::string including_file,std::string included_file,const std::vector<std::string> *rcdirs = NULL)throw (std::string);
FILE* f = fopen( filename, "r" );if (f){FileLineInput fl(f);Options.read_options(fl, true);fclose(f);}else{mprf(MSGCH_WARN, "Warning: could not read options file '%s'", filename);}
Options.include(filename, true, true);
# You can use the travel_stop_message for making autotravel better behaved.# The following file contains a list of such options, with explanations.: crawl.read_options('docs/travel_stoppers.txt')
# You can use travel_stop_message to make autotravel stop for situations that# warrant your attention. This file (travel_stoppers.txt) contains a list of# travel_stop_message settings, with brief descriptions of what they do.include docs/travel_stoppers.txt