/* * The contents of this file are subject to the Initial * Developer's Public License Version 1.0 (the "License"); * you may not use this file except in compliance with the * License. You may obtain a copy of the License at * http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl. * * Software distributed under the License is distributed AS IS, * WITHOUT WARRANTY OF ANY KIND, either express or implied. * See the License for the specific language governing rights * and limitations under the License. * * The Original Code was created by Dmitry Yemanov * for the Firebird Open Source RDBMS project. * * Copyright (c) 2002 Dmitry Yemanov * and all contributors signed below. * * All Rights Reserved. * Contributor(s): ______________________________________. */ #include "firebird.h" #include "../../common/classes/alloc.h" #include "../../common/classes/auto.h" #include "../../common/config/config_file.h" #include "../jrd/os/fbsyslog.h" #include #ifdef HAVE_STDLIB_H #include #endif // Invalid or missing CONF_FILE may lead to severe errors // in applications. That's why for regular SERVER builds // it's better to exit with appropriate diags rather continue // with missing / wrong configuration. #if (! defined(BOOT_BUILD)) && (! defined(EMBEDDED)) && (! defined(SUPERCLIENT)) #define EXCEPTION_ON_NO_CONF #else #undef EXCEPTION_ON_NO_CONF #endif // config_file works with OS case-sensitivity typedef Firebird::PathName string; /****************************************************************************** * * Strip any comments */ bool ConfigFile::stripComments(string& s) const { if (!parsingAliases) { // Simple, fast processing for firebird.conf // Note that this is only a hack. It won't work in case inputLine // contains hash-marks embedded in quotes! Not that I know if we // should care about that case. const string::size_type commentPos = s.find('#'); if (commentPos != string::npos) { s = s.substr(0, commentPos); } return true; } // Paranoid, slow processing for aliases.conf bool equalSeen = false, inString = false; const char* iter = s.begin(); const char* end = s.end(); while (iter < end) { switch (*iter) { case '"': if (!equalSeen) // quoted string to the left of = doesn't make sense return false; inString = !inString; // We don't support embedded quotes if (!inString) // we finished a quoted string { // We don't want trash after closing the quoted string, except comments const string::size_type startPos = s.find_first_not_of(" \t\r", iter + 1 - s.begin()); if (startPos == string::npos || s[startPos] == '#') { s = s.substr(0, iter + 1 - s.begin()); return true; } return false; } break; case '=': equalSeen = true; break; case '#': if (!inString) { s = s.substr(0, iter - s.begin()); return true; } break; } ++iter; } return !inString; // If we are still inside a string, it's error } /****************************************************************************** * * Check whether the given key exists or not */ bool ConfigFile::doesKeyExist(const string& key) { checkLoadConfig(); const string data = getString(key); return !data.empty(); } /****************************************************************************** * * Return string value corresponding the given key */ string ConfigFile::getString(const string& key) { checkLoadConfig(); size_t pos; return parameters.find(key, pos) ? parameters[pos].second : string(); } /****************************************************************************** * * Parse key */ string ConfigFile::parseKeyFrom(const string& inputLine, string::size_type& endPos) { endPos = inputLine.find_first_of("="); if (endPos == string::npos) { return inputLine; } return inputLine.substr(0, endPos); } /****************************************************************************** * * Parse value */ string ConfigFile::parseValueFrom(string inputLine, string::size_type initialPos) { if (initialPos == string::npos) { return string(); } // skip leading white spaces const string::size_type startPos = inputLine.find_first_not_of("= \t", initialPos); if (startPos == string::npos) { return string(); } inputLine.rtrim(" \t\r"); // stringComments demands paired quotes but trimming \r may render startPos invalid. if (parsingAliases && inputLine.length() > startPos + 1 && inputLine[startPos] == '"' && inputLine.end()[-1] == '"') { return inputLine.substr(startPos + 1, inputLine.length() - startPos - 2); } return inputLine.substr(startPos); } /****************************************************************************** * * Load file, if necessary */ void ConfigFile::checkLoadConfig() { if (!isLoadedFlg) { loadConfig(); } } /****************************************************************************** * * Load file immediately */ void ConfigFile::loadConfig() { isLoadedFlg = true; parameters.clear(); Firebird::AutoPtr ifile(fopen(configFile.c_str(), "rt")); #ifdef EXCEPTION_ON_NO_CONF int BadLinesCount = 0; #endif if (!ifile) { // config file does not exist #ifdef EXCEPTION_ON_NO_CONF if (fExceptionOnError) { const Firebird::string msg = "Missing configuration file: " + configFile.ToString() + ", exiting"; Firebird::Syslog::Record(Firebird::Syslog::Error, msg.c_str()); Firebird::fatal_exception::raise(msg.c_str()); } #endif //EXCEPTION_ON_NO_CONF return; } string inputLine; while (!feof(ifile)) { inputLine.LoadFromFile(ifile); const bool goodLine = stripComments(inputLine); inputLine.ltrim(" \t\r"); if (!inputLine.size()) { continue; // comment-line or empty line } if (!goodLine || inputLine.find('=') == string::npos) { const Firebird::string msg = (configFile + ": illegal line \"" + inputLine + "\"").ToString(); Firebird::Syslog::Record(fExceptionOnError ? Firebird::Syslog::Error : Firebird::Syslog::Warning, msg.c_str()); #ifdef EXCEPTION_ON_NO_CONF BadLinesCount++; #endif continue; } string::size_type endPos; string key = parseKeyFrom(inputLine, endPos); key.rtrim(" \t\r"); // TODO: here we must check for correct parameter spelling ! const string value = parseValueFrom(inputLine, endPos); parameters.add(Parameter(getPool(), key, value)); } #ifdef EXCEPTION_ON_NO_CONF if (BadLinesCount && fExceptionOnError) { Firebird::fatal_exception::raise("Bad lines in firebird.conf"); } #endif }