2002-11-03 17:26:12 +01:00
|
|
|
/*
|
|
|
|
* PROGRAM: Client/Server Common Code
|
|
|
|
* MODULE: config_file.cpp
|
|
|
|
* DESCRIPTION: Configuration manager (file handling)
|
|
|
|
*
|
|
|
|
* The contents of this file are subject to the Interbase 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.Inprise.com/IPL.html
|
|
|
|
*
|
|
|
|
* Software distributed under the License is distributed on an
|
|
|
|
* "AS IS" basis, 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 Inprise Corporation
|
|
|
|
* and its predecessors. Portions created by Inprise Corporation are
|
|
|
|
* Copyright (C) Inprise Corporation.
|
|
|
|
*
|
|
|
|
* Created by: Mark O'Donohue <mark.odonohue@ludwig.edu.au>
|
|
|
|
*
|
|
|
|
* All Rights Reserved.
|
|
|
|
* Contributor(s): ______________________________________.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#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
|
|
|
|
#else
|
|
|
|
#undef EXIT_ON_NO_CONF
|
|
|
|
#endif
|
2003-05-22 08:39:54 +02:00
|
|
|
#if (! defined(BOOT_BUILD)) && (! defined(SUPERCLIENT))
|
|
|
|
#define INFORM_ON_NO_CONF
|
|
|
|
#else
|
|
|
|
#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
|
|
|
|
*/
|
|
|
|
|
|
|
|
void ConfigFile::key_compare::uppercase(string& x) const
|
|
|
|
{
|
|
|
|
for (size_t pos = 0; pos < x.length(); pos++)
|
|
|
|
{
|
|
|
|
x[pos] = toupper(x[pos]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ConfigFile::key_compare::operator()(const string& x, const string& y) const
|
|
|
|
{
|
|
|
|
string s1 = x, s2 = y;
|
|
|
|
|
|
|
|
if (!isCaseSensitive)
|
|
|
|
{
|
|
|
|
uppercase(s1), uppercase(s2);
|
|
|
|
}
|
|
|
|
|
|
|
|
return (s1 < s2);
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
*
|
|
|
|
* Strip leading spaces
|
|
|
|
*/
|
|
|
|
|
|
|
|
void ConfigFile::stripLeadingWhiteSpace(string& s)
|
|
|
|
{
|
|
|
|
if (!s.size())
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
const string::size_type startPos = s.find_first_not_of(" \t");
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
string::size_type endPos = s.find_last_not_of(" \t");
|
|
|
|
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
|
|
|
}
|