2002-11-03 17:26:12 +01:00
|
|
|
/*
|
2005-01-12 05:24:53 +01:00
|
|
|
* 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.
|
2002-11-03 17:26:12 +01:00
|
|
|
*
|
2005-01-12 05:24:53 +01:00
|
|
|
* 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.
|
2002-11-03 17:26:12 +01:00
|
|
|
*
|
2005-01-12 05:24:53 +01:00
|
|
|
* The Original Code was created by Dmitry Yemanov
|
|
|
|
* for the Firebird Open Source RDBMS project.
|
|
|
|
*
|
|
|
|
* Copyright (c) 2002 Dmitry Yemanov <dimitr@users.sf.net>
|
|
|
|
* and all contributors signed below.
|
|
|
|
*
|
|
|
|
* All Rights Reserved.
|
|
|
|
* Contributor(s): ______________________________________.
|
2002-11-03 17:26:12 +01:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include "firebird.h"
|
|
|
|
|
2004-03-26 00:12:50 +01:00
|
|
|
#include "../../common/classes/alloc.h"
|
2004-03-14 14:14:58 +01:00
|
|
|
#include "../../common/classes/auto.h"
|
2002-11-03 17:26:12 +01:00
|
|
|
#include "../../common/config/config_file.h"
|
2003-04-19 18:46:24 +02:00
|
|
|
#include "../jrd/os/fbsyslog.h"
|
2004-04-29 00:00:03 +02:00
|
|
|
#include <stdio.h>
|
2002-11-03 17:26:12 +01:00
|
|
|
|
|
|
|
#ifdef HAVE_STDLIB_H
|
|
|
|
#include <stdlib.h>
|
|
|
|
#endif
|
|
|
|
|
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))
|
2004-08-30 20:11:08 +02:00
|
|
|
#define EXCEPTION_ON_NO_CONF
|
2003-05-22 08:39:54 +02:00
|
|
|
#else
|
2004-08-30 20:11:08 +02:00
|
|
|
#undef EXCEPTION_ON_NO_CONF
|
2003-05-22 08:39:54 +02:00
|
|
|
#endif
|
2003-04-19 18:46:24 +02:00
|
|
|
|
2004-02-08 18:08:34 +01:00
|
|
|
// config_file works with OS case-sensitivity
|
|
|
|
typedef Firebird::PathName string;
|
2002-11-03 17:26:12 +01:00
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
*
|
|
|
|
* Strip any comments
|
|
|
|
*/
|
|
|
|
|
2008-05-21 15:53:17 +02:00
|
|
|
bool ConfigFile::stripComments(string& s) const
|
2002-11-03 17:26:12 +01:00
|
|
|
{
|
2008-05-21 15:53:17 +02:00
|
|
|
if (!parsingAliases)
|
2002-11-03 17:26:12 +01:00
|
|
|
{
|
2008-05-21 15:53:17 +02:00
|
|
|
// 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;
|
2002-11-03 17:26:12 +01:00
|
|
|
}
|
2008-05-21 15:53:17 +02:00
|
|
|
|
|
|
|
// Paranoid, slow processing for aliases.conf
|
|
|
|
bool equalSeen = false, inString = false;
|
|
|
|
const char* iter = s.begin();
|
|
|
|
const char* end = s.end();
|
2008-05-22 23:45:22 +02:00
|
|
|
|
2008-05-21 15:53:17 +02:00
|
|
|
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
|
2009-01-05 09:22:58 +01:00
|
|
|
const string::size_type startPos = s.find_first_not_of(" \t\r", iter + 1 - s.begin());
|
2008-05-21 15:53:17 +02:00
|
|
|
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;
|
|
|
|
}
|
2008-05-22 23:45:22 +02:00
|
|
|
|
2008-05-21 15:53:17 +02:00
|
|
|
++iter;
|
|
|
|
}
|
2008-05-22 23:45:22 +02:00
|
|
|
|
2008-05-21 15:53:17 +02:00
|
|
|
return !inString; // If we are still inside a string, it's error
|
2002-11-03 17:26:12 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
*
|
|
|
|
* Check whether the given key exists or not
|
|
|
|
*/
|
|
|
|
|
|
|
|
bool ConfigFile::doesKeyExist(const string& key)
|
|
|
|
{
|
2008-05-21 15:53:17 +02:00
|
|
|
checkLoadConfig();
|
2002-11-03 17:26:12 +01:00
|
|
|
|
2008-05-21 15:53:17 +02:00
|
|
|
const string data = getString(key);
|
2002-11-03 17:26:12 +01:00
|
|
|
|
2008-05-21 15:53:17 +02:00
|
|
|
return !data.empty();
|
2002-11-03 17:26:12 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
*
|
|
|
|
* Return string value corresponding the given key
|
|
|
|
*/
|
|
|
|
|
|
|
|
string ConfigFile::getString(const string& key)
|
|
|
|
{
|
2008-05-21 15:53:17 +02:00
|
|
|
checkLoadConfig();
|
2002-11-03 17:26:12 +01:00
|
|
|
|
2008-05-21 15:53:17 +02:00
|
|
|
size_t pos;
|
|
|
|
return parameters.find(key, pos) ? parameters[pos].second : string();
|
2002-11-03 17:26:12 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
*
|
|
|
|
* Parse key
|
|
|
|
*/
|
|
|
|
|
|
|
|
string ConfigFile::parseKeyFrom(const string& inputLine, string::size_type& endPos)
|
|
|
|
{
|
2008-05-21 15:53:17 +02:00
|
|
|
endPos = inputLine.find_first_of("=");
|
|
|
|
if (endPos == string::npos)
|
|
|
|
{
|
|
|
|
return inputLine;
|
|
|
|
}
|
2002-11-03 17:26:12 +01:00
|
|
|
|
2008-05-21 15:53:17 +02:00
|
|
|
return inputLine.substr(0, endPos);
|
2002-11-03 17:26:12 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
*
|
|
|
|
* Parse value
|
|
|
|
*/
|
|
|
|
|
|
|
|
string ConfigFile::parseValueFrom(string inputLine, string::size_type initialPos)
|
|
|
|
{
|
2008-05-21 15:53:17 +02:00
|
|
|
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.
|
2008-12-31 06:06:08 +01:00
|
|
|
if (parsingAliases && inputLine.length() > startPos + 1 &&
|
|
|
|
inputLine[startPos] == '"' && inputLine.end()[-1] == '"')
|
2008-05-21 15:53:17 +02:00
|
|
|
{
|
|
|
|
return inputLine.substr(startPos + 1, inputLine.length() - startPos - 2);
|
|
|
|
}
|
2008-12-05 02:20:14 +01:00
|
|
|
|
2008-05-21 15:53:17 +02:00
|
|
|
return inputLine.substr(startPos);
|
2002-11-03 17:26:12 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
*
|
|
|
|
* Load file, if necessary
|
|
|
|
*/
|
|
|
|
|
|
|
|
void ConfigFile::checkLoadConfig()
|
|
|
|
{
|
|
|
|
if (!isLoadedFlg)
|
|
|
|
{
|
2008-05-21 15:53:17 +02:00
|
|
|
loadConfig();
|
2002-11-03 17:26:12 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
*
|
|
|
|
* Load file immediately
|
|
|
|
*/
|
|
|
|
|
|
|
|
void ConfigFile::loadConfig()
|
|
|
|
{
|
|
|
|
isLoadedFlg = true;
|
|
|
|
|
|
|
|
parameters.clear();
|
|
|
|
|
2009-04-09 18:44:45 +02:00
|
|
|
Firebird::AutoPtr<FILE, Firebird::FileClose> ifile(fopen(configFile.c_str(), "rt"));
|
2008-05-21 15:53:17 +02:00
|
|
|
|
2004-08-30 20:11:08 +02:00
|
|
|
#ifdef EXCEPTION_ON_NO_CONF
|
2003-04-19 18:46:24 +02:00
|
|
|
int BadLinesCount = 0;
|
|
|
|
#endif
|
2008-05-21 15:53:17 +02:00
|
|
|
if (!ifile)
|
|
|
|
{
|
|
|
|
// config file does not exist
|
2004-08-30 20:11:08 +02:00
|
|
|
#ifdef EXCEPTION_ON_NO_CONF
|
|
|
|
if (fExceptionOnError)
|
2004-04-11 16:47:04 +02:00
|
|
|
{
|
2009-01-06 18:46:08 +01:00
|
|
|
const Firebird::string msg =
|
2009-01-05 09:22:58 +01:00
|
|
|
"Missing configuration file: " + configFile.ToString() + ", exiting";
|
2009-01-06 18:46:08 +01:00
|
|
|
Firebird::Syslog::Record(Firebird::Syslog::Error, msg.c_str());
|
|
|
|
Firebird::fatal_exception::raise(msg.c_str());
|
2004-04-11 16:47:04 +02:00
|
|
|
}
|
2004-08-30 20:11:08 +02:00
|
|
|
#endif //EXCEPTION_ON_NO_CONF
|
2003-04-19 18:46:24 +02:00
|
|
|
return;
|
2008-05-21 15:53:17 +02:00
|
|
|
}
|
|
|
|
string inputLine;
|
2002-11-03 17:26:12 +01:00
|
|
|
|
2008-05-21 15:53:17 +02:00
|
|
|
while (!feof(ifile))
|
|
|
|
{
|
2004-02-08 18:08:34 +01:00
|
|
|
inputLine.LoadFromFile(ifile);
|
2002-11-03 17:26:12 +01:00
|
|
|
|
2008-05-21 15:53:17 +02:00
|
|
|
const bool goodLine = stripComments(inputLine);
|
2004-03-14 14:14:58 +01:00
|
|
|
inputLine.ltrim(" \t\r");
|
2008-05-21 15:53:17 +02:00
|
|
|
|
2002-11-03 17:26:12 +01:00
|
|
|
if (!inputLine.size())
|
|
|
|
{
|
|
|
|
continue; // comment-line or empty line
|
|
|
|
}
|
|
|
|
|
2008-05-21 15:53:17 +02:00
|
|
|
if (!goodLine || inputLine.find('=') == string::npos)
|
|
|
|
{
|
2009-01-06 18:46:08 +01:00
|
|
|
const Firebird::string msg =
|
2009-01-05 09:22:58 +01:00
|
|
|
(configFile + ": illegal line \"" + inputLine + "\"").ToString();
|
2008-05-21 15:53:17 +02:00
|
|
|
Firebird::Syslog::Record(fExceptionOnError ?
|
2009-01-05 09:22:58 +01:00
|
|
|
Firebird::Syslog::Error : Firebird::Syslog::Warning,
|
2009-01-06 18:46:08 +01:00
|
|
|
msg.c_str());
|
2004-08-30 20:11:08 +02:00
|
|
|
#ifdef EXCEPTION_ON_NO_CONF
|
2003-04-19 18:46:24 +02:00
|
|
|
BadLinesCount++;
|
|
|
|
#endif
|
2008-05-21 15:53:17 +02:00
|
|
|
continue;
|
|
|
|
}
|
2002-11-03 17:26:12 +01:00
|
|
|
|
2008-05-21 15:53:17 +02:00
|
|
|
string::size_type endPos;
|
2002-11-03 17:26:12 +01:00
|
|
|
|
2008-05-21 15:53:17 +02:00
|
|
|
string key = parseKeyFrom(inputLine, endPos);
|
2004-03-14 14:14:58 +01:00
|
|
|
key.rtrim(" \t\r");
|
2003-04-19 18:46:24 +02:00
|
|
|
// TODO: here we must check for correct parameter spelling !
|
2008-05-21 15:53:17 +02:00
|
|
|
const string value = parseValueFrom(inputLine, endPos);
|
2002-11-03 17:26:12 +01:00
|
|
|
|
2004-03-14 14:14:58 +01:00
|
|
|
parameters.add(Parameter(getPool(), key, value));
|
2008-05-21 15:53:17 +02:00
|
|
|
}
|
2004-08-30 20:11:08 +02:00
|
|
|
#ifdef EXCEPTION_ON_NO_CONF
|
2008-05-21 15:53:17 +02:00
|
|
|
if (BadLinesCount && fExceptionOnError)
|
2004-08-16 14:24:30 +02:00
|
|
|
{
|
|
|
|
Firebird::fatal_exception::raise("Bad lines in firebird.conf");
|
2003-04-19 18:46:24 +02:00
|
|
|
}
|
|
|
|
#endif
|
2002-11-03 17:26:12 +01:00
|
|
|
}
|
2005-01-12 09:30:24 +01:00
|
|
|
|
2008-05-21 15:53:17 +02:00
|
|
|
|