2002-11-03 17:26:12 +01:00
|
|
|
/*
|
2003-09-26 16:13:15 +02:00
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
|
|
* You may obtain a copy of the Licence at
|
|
|
|
* http://www.gnu.org/licences/lgpl.html
|
|
|
|
*
|
|
|
|
* As a special exception this file can also be included in modules
|
|
|
|
* with other source code as long as that source code has been
|
|
|
|
* released under an Open Source Initiative certificed licence.
|
|
|
|
* More information about OSI certification can be found at:
|
|
|
|
* http://www.opensource.org
|
|
|
|
*
|
|
|
|
* This module is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU Lesser General Public Licence for more details.
|
|
|
|
*
|
|
|
|
* This module was created by members of the firebird development
|
|
|
|
* team. All individual contributions remain the Copyright (C) of
|
|
|
|
* those individuals and all rights are reserved. Contributors to
|
|
|
|
* this file are either listed below or can be obtained from a CVS
|
|
|
|
* history command.
|
2002-11-03 17:26:12 +01:00
|
|
|
*
|
2003-09-26 16:13:15 +02:00
|
|
|
* Created by: Mark O'Donohue <skywalker@users.sourceforge.net>
|
2002-11-03 17:26:12 +01:00
|
|
|
*
|
2003-09-26 16:13:15 +02:00
|
|
|
* Contributor(s):
|
2002-11-03 17:26:12 +01:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include "firebird.h"
|
|
|
|
|
|
|
|
#include "../../common/config/config_file.h"
|
2003-04-19 18:46:24 +02:00
|
|
|
#include "../jrd/os/fbsyslog.h"
|
2002-11-03 17:26:12 +01:00
|
|
|
|
|
|
|
#ifdef HAVE_STDLIB_H
|
|
|
|
#include <stdlib.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <fstream>
|
|
|
|
#include <iostream>
|
|
|
|
|
2003-04-19 18:46:24 +02:00
|
|
|
// 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.
|
2003-05-22 08:39:54 +02:00
|
|
|
#if (! defined(BOOT_BUILD)) && (! defined(EMBEDDED)) && (! defined(SUPERCLIENT))
|
2003-04-19 18:46:24 +02:00
|
|
|
#define EXIT_ON_NO_CONF
|
2003-05-22 08:39:54 +02:00
|
|
|
#define INFORM_ON_NO_CONF
|
|
|
|
#else
|
2003-07-08 13:49:02 +02:00
|
|
|
#undef EXIT_ON_NO_CONF
|
2003-05-22 08:39:54 +02:00
|
|
|
#undef INFORM_ON_NO_CONF
|
|
|
|
#endif
|
2003-04-19 18:46:24 +02:00
|
|
|
|
2002-11-03 17:26:12 +01:00
|
|
|
typedef Firebird::string string;
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
*
|
|
|
|
* Allow case-insensitive comparison
|
|
|
|
*/
|
|
|
|
|
|
|
|
bool ConfigFile::key_compare::operator()(const string& x, const string& y) const
|
|
|
|
{
|
2003-05-30 14:17:47 +02:00
|
|
|
return Firebird::PathName(x) < Firebird::PathName(y);
|
2002-11-03 17:26:12 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
*
|
|
|
|
* Strip leading spaces
|
|
|
|
*/
|
|
|
|
|
|
|
|
void ConfigFile::stripLeadingWhiteSpace(string& s)
|
|
|
|
{
|
|
|
|
if (!s.size())
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2003-12-13 11:59:59 +01:00
|
|
|
const string::size_type startPos = s.find_first_not_of(" \t\r");
|
2002-11-03 17:26:12 +01:00
|
|
|
if (startPos == string::npos)
|
|
|
|
{
|
|
|
|
s.erase(); // nothing but air
|
|
|
|
}
|
|
|
|
else if (startPos)
|
|
|
|
{
|
|
|
|
s = s.substr(startPos);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
*
|
|
|
|
* Strip trailing spaces
|
|
|
|
*/
|
|
|
|
|
|
|
|
void ConfigFile::stripTrailingWhiteSpace(string& s)
|
|
|
|
{
|
|
|
|
if (!s.size())
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2003-12-13 11:59:59 +01:00
|
|
|
string::size_type endPos = s.find_last_not_of(" \t\r");
|
2002-11-03 17:26:12 +01:00
|
|
|
if (endPos != string::npos)
|
|
|
|
{
|
|
|
|
// Note that endPos is the index to the last non-ws char
|
|
|
|
// why we have to inc. it
|
|
|
|
++endPos;
|
|
|
|
s = s.substr(0, endPos);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
*
|
|
|
|
* Strip any comments
|
|
|
|
*/
|
|
|
|
|
|
|
|
void ConfigFile::stripComments(string& s)
|
|
|
|
{
|
|
|
|
// 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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
*
|
|
|
|
* Check whether the given key exists or not
|
|
|
|
*/
|
|
|
|
|
|
|
|
bool ConfigFile::doesKeyExist(const string& key)
|
|
|
|
{
|
|
|
|
checkLoadConfig();
|
|
|
|
|
|
|
|
string data = getString(key);
|
|
|
|
|
|
|
|
return !data.empty();
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
*
|
|
|
|
* Return string value corresponding the given key
|
|
|
|
*/
|
|
|
|
|
|
|
|
string ConfigFile::getString(const string& key)
|
|
|
|
{
|
|
|
|
checkLoadConfig();
|
|
|
|
|
|
|
|
mymap_t::iterator lookup;
|
|
|
|
|
|
|
|
lookup = parameters.find(key);
|
|
|
|
|
|
|
|
if (lookup != parameters.end())
|
|
|
|
{
|
|
|
|
return lookup->second;
|
|
|
|
}
|
|
|
|
|
|
|
|
return string();
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
*
|
|
|
|
* Parse key
|
|
|
|
*/
|
|
|
|
|
|
|
|
string ConfigFile::parseKeyFrom(const string& inputLine, string::size_type& endPos)
|
|
|
|
{
|
2002-11-22 10:02:47 +01:00
|
|
|
endPos = inputLine.find_first_of("=\t");
|
2002-11-03 17:26:12 +01:00
|
|
|
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
|
|
|
|
unsigned int startPos = inputLine.find_first_not_of("= \t", initialPos);
|
|
|
|
if (startPos == string::npos)
|
|
|
|
{
|
|
|
|
return string();
|
|
|
|
}
|
|
|
|
|
|
|
|
stripTrailingWhiteSpace(inputLine);
|
|
|
|
return inputLine.substr(startPos);
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
*
|
|
|
|
* Load file, if necessary
|
|
|
|
*/
|
|
|
|
|
|
|
|
void ConfigFile::checkLoadConfig()
|
|
|
|
{
|
|
|
|
if (!isLoadedFlg)
|
|
|
|
{
|
|
|
|
loadConfig();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
*
|
|
|
|
* Load file immediately
|
|
|
|
*/
|
|
|
|
|
|
|
|
void ConfigFile::loadConfig()
|
|
|
|
{
|
|
|
|
isLoadedFlg = true;
|
|
|
|
|
|
|
|
parameters.clear();
|
|
|
|
|
2002-11-16 11:56:49 +01:00
|
|
|
std::ifstream configFileStream(configFile.c_str());
|
2003-04-19 18:46:24 +02:00
|
|
|
|
|
|
|
#ifdef EXIT_ON_NO_CONF
|
|
|
|
int BadLinesCount = 0;
|
|
|
|
#endif
|
2002-11-16 11:56:49 +01:00
|
|
|
if (!configFileStream)
|
2002-11-03 17:26:12 +01:00
|
|
|
{
|
2003-04-19 18:46:24 +02:00
|
|
|
// config file does not exist
|
2003-05-22 08:39:54 +02:00
|
|
|
#ifdef INFORM_ON_NO_CONF
|
2003-04-19 18:46:24 +02:00
|
|
|
string Msg = "Missing configuration file: " + configFile;
|
|
|
|
#ifdef EXIT_ON_NO_CONF
|
|
|
|
if (fExitOnError)
|
|
|
|
Msg += ", exiting";
|
|
|
|
#endif
|
|
|
|
Firebird::Syslog::Record(fExitOnError ?
|
|
|
|
Firebird::Syslog::Error :
|
|
|
|
Firebird::Syslog::Warning, Msg);
|
|
|
|
#ifdef EXIT_ON_NO_CONF
|
|
|
|
if (fExitOnError)
|
|
|
|
exit(1);
|
|
|
|
#endif
|
2003-05-22 08:39:54 +02:00
|
|
|
#endif //INFORM_ON_NO_CONF
|
2003-04-19 18:46:24 +02:00
|
|
|
return;
|
2002-11-03 17:26:12 +01:00
|
|
|
}
|
|
|
|
string inputLine;
|
|
|
|
|
2002-11-16 11:56:49 +01:00
|
|
|
while (!configFileStream.eof())
|
2002-11-03 17:26:12 +01:00
|
|
|
{
|
2002-11-16 11:56:49 +01:00
|
|
|
std::getline(configFileStream, inputLine);
|
2002-11-03 17:26:12 +01:00
|
|
|
|
|
|
|
stripComments(inputLine);
|
|
|
|
stripLeadingWhiteSpace(inputLine);
|
|
|
|
|
|
|
|
if (!inputLine.size())
|
|
|
|
{
|
|
|
|
continue; // comment-line or empty line
|
|
|
|
}
|
|
|
|
|
|
|
|
if (inputLine.find('=') == string::npos)
|
|
|
|
{
|
2003-04-19 18:46:24 +02:00
|
|
|
string Msg = configFile + ": illegal line \"" +
|
|
|
|
inputLine + "\"";
|
|
|
|
Firebird::Syslog::Record(fExitOnError ?
|
|
|
|
Firebird::Syslog::Error :
|
|
|
|
Firebird::Syslog::Warning, Msg);
|
|
|
|
#ifdef EXIT_ON_NO_CONF
|
|
|
|
BadLinesCount++;
|
|
|
|
#endif
|
2002-11-03 17:26:12 +01:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
string::size_type endPos;
|
|
|
|
|
|
|
|
string key = parseKeyFrom(inputLine, endPos);
|
2002-11-22 10:02:47 +01:00
|
|
|
stripTrailingWhiteSpace(key);
|
2003-04-19 18:46:24 +02:00
|
|
|
// TODO: here we must check for correct parameter spelling !
|
2002-11-03 17:26:12 +01:00
|
|
|
string value = parseValueFrom(inputLine, endPos);
|
|
|
|
|
|
|
|
// parameters.insert(pair<string, string>(key, value));
|
|
|
|
// Just to display yet another template function
|
|
|
|
parameters.insert(std::make_pair(key, value));
|
|
|
|
}
|
2003-04-19 18:46:24 +02:00
|
|
|
#ifdef EXIT_ON_NO_CONF
|
|
|
|
if (BadLinesCount && fExitOnError) {
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
#endif
|
2002-11-03 17:26:12 +01:00
|
|
|
}
|