added: program reads its configuration from a config file

added: confparser directory and confparser.h and confparser.cpp
       class ConfParser used to parse a config file
       this is a generic parser, can be used by another project
added: config.h, config.cpp
       class Config used for assigning values from 
       a config file into the data object
added: function for signals: SIGINT, SIGHUP
       after receiving SIGHUP the program will read
       its config file again


git-svn-id: svn://ttmath.org/publicrep/cmslu/trunk@463 e52654a7-88a9-db11-a3e9-0013d4bc506e
This commit is contained in:
Tomasz Sowa 2008-12-11 02:46:16 +00:00
parent c53e985a92
commit 8aab988752
15 changed files with 449 additions and 219 deletions

View File

@ -1,5 +1,5 @@
CC = g++
o = templates.o log.o requestcontroller.o main.o misc.o db.o session.o request.o content.o sessionmanager.o httpsimpleparser.o data.o dir.o error.o done.o dircontainer.o ezc.o
o = dir.o data.o content.o log.o sessionmanager.o requestcontroller.o dircontainer.o session.o main.o done.o request.o misc.o templates.o httpsimpleparser.o db.o error.o config.o confparser.o ezc.o
CFLAGS = -Wall -pedantic -g -I/usr/local/include -L/usr/local/lib
name = cmslu.fcgi
@ -19,27 +19,29 @@ $(name): $(o)
templates.o: core/templates.cpp core/templates.h core/../../ezc/src/ezc.h core/data.h core/misc.h core/log.h core/item.h core/error.h core/dir.h core/db.h core/dircontainer.h core/request.h core/requesttypes.h core/session.h core/done.h core/getparser.h core/httpsimpleparser.h core/postparser.h core/cookieparser.h
log.o: core/log.cpp core/log.h
requestcontroller.o: core/requestcontroller.cpp core/requestcontroller.h core/data.h core/misc.h core/log.h core/item.h core/error.h core/dir.h core/db.h core/dircontainer.h core/request.h core/requesttypes.h core/session.h core/done.h core/getparser.h core/httpsimpleparser.h core/postparser.h core/cookieparser.h core/content.h core/templates.h core/../../ezc/src/ezc.h core/sessionmanager.h
main.o: core/main.cpp core/requestcontroller.h core/data.h core/misc.h core/log.h core/item.h core/error.h core/dir.h core/db.h core/dircontainer.h core/request.h core/requesttypes.h core/session.h core/done.h core/getparser.h core/httpsimpleparser.h core/postparser.h core/cookieparser.h core/content.h core/templates.h core/../../ezc/src/ezc.h core/sessionmanager.h
misc.o: core/misc.cpp core/misc.h core/log.h core/item.h
db.o: core/db.cpp core/db.h core/log.h core/item.h core/misc.h core/error.h core/dircontainer.h
session.o: core/session.cpp core/session.h core/requesttypes.h core/error.h core/log.h core/item.h core/done.h
request.o: core/request.cpp core/request.h core/requesttypes.h core/log.h core/session.h core/error.h core/item.h core/done.h core/getparser.h core/httpsimpleparser.h core/postparser.h core/cookieparser.h
content.o: core/content.cpp core/content.h core/templates.h core/../../ezc/src/ezc.h core/data.h core/misc.h core/log.h core/item.h core/error.h core/dir.h core/db.h core/dircontainer.h core/request.h core/requesttypes.h core/session.h core/done.h core/getparser.h core/httpsimpleparser.h core/postparser.h core/cookieparser.h
sessionmanager.o: core/sessionmanager.cpp core/sessionmanager.h core/request.h core/requesttypes.h core/log.h core/session.h core/error.h core/item.h core/done.h core/getparser.h core/httpsimpleparser.h core/postparser.h core/cookieparser.h core/data.h core/misc.h core/dir.h core/db.h core/dircontainer.h
httpsimpleparser.o: core/httpsimpleparser.cpp core/httpsimpleparser.h
data.o: core/data.cpp core/data.h core/misc.h core/log.h core/item.h core/error.h core/dir.h core/db.h core/dircontainer.h
dir.o: core/dir.cpp core/dir.h core/item.h core/error.h core/log.h core/db.h core/misc.h core/dircontainer.h
error.o: core/error.cpp core/error.h core/log.h
done.o: core/done.cpp core/done.h
data.o: core/data.cpp core/data.h core/misc.h core/log.h core/item.h core/error.h core/dir.h core/db.h core/dircontainer.h
content.o: core/content.cpp core/content.h core/templates.h core/../../ezc/src/ezc.h core/data.h core/misc.h core/log.h core/item.h core/error.h core/dir.h core/db.h core/dircontainer.h core/request.h core/requesttypes.h core/session.h core/done.h core/getparser.h core/httpsimpleparser.h core/postparser.h core/cookieparser.h
log.o: core/log.cpp core/log.h
sessionmanager.o: core/sessionmanager.cpp core/sessionmanager.h core/request.h core/requesttypes.h core/log.h core/session.h core/error.h core/item.h core/done.h core/getparser.h core/httpsimpleparser.h core/postparser.h core/cookieparser.h core/data.h core/misc.h core/dir.h core/db.h core/dircontainer.h
requestcontroller.o: core/requestcontroller.cpp core/requestcontroller.h core/data.h core/misc.h core/log.h core/item.h core/error.h core/dir.h core/db.h core/dircontainer.h core/request.h core/requesttypes.h core/session.h core/done.h core/getparser.h core/httpsimpleparser.h core/postparser.h core/cookieparser.h core/content.h core/templates.h core/../../ezc/src/ezc.h core/sessionmanager.h
dircontainer.o: core/dircontainer.cpp core/dircontainer.h core/item.h core/log.h
session.o: core/session.cpp core/session.h core/requesttypes.h core/error.h core/log.h core/item.h core/done.h
main.o: core/main.cpp core/requestcontroller.h core/data.h core/misc.h core/log.h core/item.h core/error.h core/dir.h core/db.h core/dircontainer.h core/request.h core/requesttypes.h core/session.h core/done.h core/getparser.h core/httpsimpleparser.h core/postparser.h core/cookieparser.h core/content.h core/templates.h core/../../ezc/src/ezc.h core/sessionmanager.h core/config.h core/../confparser/confparser.h
done.o: core/done.cpp core/done.h
request.o: core/request.cpp core/request.h core/requesttypes.h core/log.h core/session.h core/error.h core/item.h core/done.h core/getparser.h core/httpsimpleparser.h core/postparser.h core/cookieparser.h
misc.o: core/misc.cpp core/misc.h core/log.h core/item.h
templates.o: core/templates.cpp core/templates.h core/../../ezc/src/ezc.h core/data.h core/misc.h core/log.h core/item.h core/error.h core/dir.h core/db.h core/dircontainer.h core/request.h core/requesttypes.h core/session.h core/done.h core/getparser.h core/httpsimpleparser.h core/postparser.h core/cookieparser.h
httpsimpleparser.o: core/httpsimpleparser.cpp core/httpsimpleparser.h
db.o: core/db.cpp core/db.h core/log.h core/item.h core/misc.h core/error.h core/dircontainer.h
error.o: core/error.cpp core/error.h core/log.h
config.o: core/config.cpp core/config.h core/../confparser/confparser.h core/error.h core/log.h core/data.h core/misc.h core/item.h core/dir.h core/db.h core/dircontainer.h
confparser.o: confparser/confparser.cpp confparser/confparser.h
ezc.o: ../ezc/src/ezc.cpp ../ezc/src/ezc.h
clean:
rm -f *.o
rm -f $(name)

208
confparser/confparser.cpp Executable file
View File

@ -0,0 +1,208 @@
/*
* This file is a part of CMSLU -- Content Management System like Unix
* and is not publicly distributed
*
* Copyright (c) 2008, Tomasz Sowa
* All rights reserved.
*
*/
#include "confparser.h"
ConfParser::ConfParser()
{
separator = '=';
commentary = '#';
}
ConfParser::Status ConfParser::Parse(const char * file_name)
{
file.open( file_name );
if( !file )
return cant_open_file;
line = 1;
table.clear();
ReadChar();
status = ParseFile();
file.close();
return status;
}
ConfParser::Status ConfParser::ParseFile()
{
while( lastc != -1 )
{
if( ReadVariable() )
{
if( lastc != separator )
return syntax_error;
ReadChar(); // skipping separator
if( !ReadValue() )
return syntax_error;
table.insert( std::make_pair(variable, value) );
}
if( lastc == commentary )
SkipLine();
if( lastc != -1 && lastc != '\n' )
return syntax_error;
ReadChar(); // skipping '\n' if was
}
return ok;
}
bool ConfParser::IsVariableChar(int c)
{
if( (c>='a' && c<='z') ||
(c>='A' && c<='Z') ||
(c>='0' && c<='9') ||
c=='.' || c==',' || c=='_' )
return true;
return false;
}
bool ConfParser::IsValueSimpleChar(int c)
{
if( c==-1 || c=='\n' || IsWhite(c) || c==commentary )
return false;
return true;
}
bool ConfParser::ReadVariable()
{
variable.clear();
SkipWhite();
while( IsVariableChar(lastc) )
{
variable += lastc;
ReadChar();
}
SkipWhite();
return !variable.empty();
}
bool ConfParser::ReadValue()
{
value.clear();
SkipWhite();
if( lastc == '"' )
// quoted value
return ReadValueQuoted();
else
return ReadValueSimple();
}
bool ConfParser::ReadValueQuoted()
{
ReadChar(); // skipping the first quote
while( lastc != '\n' && lastc != '"' && lastc != -1 )
{
if( lastc == '\\' )
ReadChar();
value += lastc;
ReadChar();
}
if( lastc != '"' )
return false;
ReadChar(); // skipping the last quote
SkipWhite();
return true;
}
bool ConfParser::ReadValueSimple()
{
while( IsValueSimpleChar(lastc) )
{
value += lastc;
ReadChar();
}
SkipWhite();
return true;
}
int ConfParser::ReadChar()
{
lastc = file.get();
if( lastc == '\n' )
++line;
return lastc;
}
bool ConfParser::IsWhite(int c)
{
if( c==' ' || c=='\t' || c==13 )
return true;
return false;
}
void ConfParser::SkipWhite()
{
while( IsWhite(lastc) )
ReadChar();
}
void ConfParser::SkipLine()
{
while( lastc != -1 && lastc != '\n' )
ReadChar();
}

74
confparser/confparser.h Executable file
View File

@ -0,0 +1,74 @@
/*
* This file is a part of CMSLU -- Content Management System like Unix
* and is not publicly distributed
*
* Copyright (c) 2008, Tomasz Sowa
* All rights reserved.
*
*/
#ifndef headerfileconfparser
#define headerfileconfparser
#include <fstream>
#include <string>
#include <map>
class ConfParser
{
public:
enum Status { ok, cant_open_file, syntax_error };
ConfParser();
Status Parse(const char * file_name);
// last status
Status status;
// line in which there is a syntax_error
int line;
typedef std::map<std::string, std::string> Table;
Table table;
private:
// last read variable, value
std::string variable, value;
// separator between a variable and a value, usually '='
int separator;
// commentary char
int commentary;
// last read char
int lastc;
// current file
std::ifstream file;
Status ParseFile();
bool IsVariableChar(int c);
bool IsValueSimpleChar(int c);
bool ReadVariable();
bool ReadValue();
bool ReadValueQuoted();
bool ReadValueSimple();
int ReadChar();
bool IsWhite(int c);
void SkipWhite();
void SkipLine();
};
#endif

View File

@ -460,9 +460,9 @@ void Content::Make()
templates.Generate();
// request.PrintGetTable();
//request.PrintGetTable();
//request.PrintEnv();
// request.PrintIn();
//request.PrintIn();
}

View File

@ -13,34 +13,11 @@
Data::Data()
{
// all these data will be reading from a config file
signal_hup = false;
stdout_is_closed = false;
log_file = "cmslu.log";
fcgi_socket = "/var/cmslu/s1";
fcgi_socket_chmod = 0770;
fcgi_socket_user = "tomek";
fcgi_socket_group = "www";
log_level = 2;
log_stdout = true;
templates = "../httpd/templates"; // templates dir
default_index = "index.html";
http_session_id_name = "slimaczek_sid";
db_database = "tomek";
db_user = "tomek";
db_pass = "monitorekasd";
// !! add a method which will be adding a slash at the end of url-es
base_url = "http://s10.slimaczek.pl/"; // with a slash at the end
one_item_is_showed = true;
dir.root.default_item = 134;
// the rest will be read from a config file
}

View File

@ -23,11 +23,13 @@
class Data
{
public:
// -----------------------------------------------------------------
// members read from a config file
// name of the config file (full path can be)
std::string config_file;
// log file name
std::string log_file;
@ -62,21 +64,30 @@ public:
std::string base_url;
std::string http_session_id_name;
Dir dir;
// if there is one item in a directory
// it will be showed
// (instead of showing directory contents)
bool one_item_is_showed;
// end config members
// -----------------------------------------------------------------
// false at the beginning
bool stdout_is_closed;
// true if there was the SIGHUP signal
volatile bool signal_hup;
Dir dir;
Data();
};

View File

@ -35,6 +35,8 @@ void Db::Init(const std::string & d, const std::string & u, const std::string &
void Db::Connect()
{
Close();
std::ostringstream buf;
buf << "dbname=" << db_database << " user=" << db_user << " password=" << db_pass;

View File

@ -33,6 +33,7 @@ public:
db_incorrect_login,
db_more_than_one_login,
db_err_currval,
incorrect_dir,

View File

@ -13,10 +13,8 @@
Log::Log()
{
log_level = 1;
current_level = 2;
log_file = "cmslu.log";
log_stdout = true;
log_level = 3;
current_level = 4; // nothing to log (call Init() first)
}
@ -27,8 +25,7 @@ void Log::Init(int log_l, const std::string & log_f, bool log_std)
log_stdout = log_std;
}
// zrobic templeta z tych metod
// i dla const char * zrobic specjalizacje
Log & Log::operator<<(const char * s)
{
@ -64,14 +61,7 @@ Log & Log::operator<<(long s)
return *this;
}
/*
Log & Log::operator<<(void * s)
{
buffer << s;
return *this;
}
*/
Log & Log::operator<<(char s)
@ -92,28 +82,27 @@ Log & Log::operator<<(size_t s)
Log & Log::operator<<(Manipulators m)
{
switch(m)
{
case logend:
SaveLog();
buffer.str( "" );
break;
switch(m)
{
case logend:
SaveLog();
buffer.str( "" );
break;
case log1:
current_level = 1;
break;
case log2:
current_level = 2;
break;
case log3:
current_level = 3;
break;
}
case log1:
current_level = 1;
break;
case log2:
current_level = 2;
break;
case log3:
current_level = 3;
break;
}
return *this;
return *this;
}
@ -129,6 +118,9 @@ int attempt = 2;
std::cout << buffer.str() << std::endl;
if( log_file.empty() )
return;
std::ofstream file;
do

View File

@ -28,27 +28,21 @@ std::string log_file;
bool log_stdout;
public:
Log();
void Init(int log_l, const std::string & log_f, bool log_std);
Log & operator<<(const char * s);
Log & operator<<(const std::string & s);
Log & operator<<(int s);
Log & operator<<(long s);
//Log & operator<<(void * s); // ??
Log & operator<<(char s);
Log & operator<<(size_t s);
Log & operator<<(Manipulators m);
void SaveLog();
};

View File

@ -16,6 +16,8 @@
#include "log.h"
#include "request.h"
#include "db.h"
#include "config.h"
// singletons
@ -24,50 +26,92 @@ Data data;
Log log;
Request request;
Db db;
Config config;
void signal_term(int)
{
log << log1 << "system aborted" << logend;
log << log1 << "cmslu stopped" << logend;
exit(0);
}
int main()
void signal_hup(int)
{
std::srand(std::time(0));
log << log3 << "SIGHUP received" << logend;
data.signal_hup = true;
config.ReadConfig(false); /* errors not to stdout */
}
log.Init(data.log_level, data.log_file, data.log_stdout);
void print_syntax()
{
std::cout << "Syntax:" << std::endl;
std::cout << " cmslu.fcgi config_file" << std::endl;
}
int main(int argv, char ** argc)
{
RequestController req_controller;
//data.read_from_file();
std::srand(std::time(0));
db.Init(data.db_database, data.db_user, data.db_pass);
if( !req_controller.Init() )
if( argv != 2 )
{
print_syntax();
return 1;
}
data.config_file = argc[1];
if( !config.ReadConfig(true) ) /* errors to stdout */
return 2;
// closing descriptors only at the beginning
close(2);
if( !data.log_stdout )
{
close(1);
data.stdout_is_closed = true;
}
log << log1 << "system started" << logend;
signal(SIGTERM, signal_term);
signal(SIGINT, signal_term);
signal(SIGHUP, signal_hup);
log << log1 << "checking for table consistency...";
db.CheckAllUrlSubject();
log << log1 << "done" << logend;
while( true )
{
log.Init(data.log_level, data.log_file, data.log_stdout);
db.Init(data.db_database, data.db_user, data.db_pass);
if( !req_controller.Init() )
return 1;
req_controller.Loop();
log << log2 << "checking for table consistency:" << logend;
db.CheckAllUrlSubject();
log << log1 << "cmslu started" << logend;
log << log1 << "system stopped" << logend;
req_controller.Loop();
if( data.signal_hup )
data.signal_hup = false;
}
return 0;
}

View File

@ -184,6 +184,9 @@ void Request::ReadEnvVariables()
env_request_method = FCGX_GetParam("REQUEST_METHOD", env);
env_request_uri = FCGX_GetParam("REQUEST_URI", env);
env_http_cookie = FCGX_GetParam("HTTP_COOKIE", env);
env_remote_addr = FCGX_GetParam("REMOTE_ADDR", env);
log << log1 << "IP: " << env_remote_addr << logend;
}
@ -271,104 +274,3 @@ void Request::SendAll()
// ----------------
/*
unsigned char Request::tohex(unsigned char polowa)
{
// polowa z zakresu 0-15
polowa = polowa & 0xf;
if(polowa<10)
polowa += '0';
else
polowa = polowa - 10 + 'A';
return polowa;
}
// cala wartosc zapisywana jest w postaci hex
string Request::ToHex(const string & dane)
{
string wynik;
unsigned int i;
for(i=0 ; i<dane.length() ; ++i)
{
wynik += tohex(dane[i] >> 4);
wynik += tohex(dane[i] & 0xf);
}
return wynik;
}
string Request::HexToString(const string & dane)
{
string wynik;
unsigned int i;
unsigned char znak,znak1,znak2;
if(dane.length()==0)
return wynik;
for(i=0 ; i<dane.length()-1 ; i+=2)
{
znak1 = parsujhex(dane[i]);
znak2 = parsujhex(dane[i+1]);
znak = (znak1 << 4) + znak2;
wynik += znak;
}
return wynik;
}
string Request::ToUrl(const string & dane)
{
string wynik;
unsigned int i;
for(i=0 ; i<dane.length() ; ++i)
{
if( (dane[i]>='a' && dane[i]<='z') ||
(dane[i]>='A' && dane[i]<='Z') ||
(dane[i]>='0' && dane[i]<='9') ||
dane[i]=='_' )
{
wynik += dane[i];
}
else
{
wynik += '%';
wynik += tohex(dane[i] >> 4);
wynik += tohex(dane[i] & 0xf);
}
}
return wynik;
}
*/

View File

@ -41,9 +41,11 @@ struct Request
PostTable post_table;
CookieTable cookie_table;
// environment variables (can be null)
const char * env_request_method;
const char * env_request_uri;
const char * env_http_cookie;
const char * env_remote_addr;
// current session
// is set after calling session_manager.SetSession()

View File

@ -16,6 +16,22 @@ RequestController::RequestController()
}
RequestController::~RequestController()
{
Close();
}
void RequestController::Close()
{
// don't call close(0)
// it will be closed next time during dup(s,0)
// if you closed the descriptor here
// then the database would have that descriptor (during connecting)
// and there'll be a problem in the next loop (after SIGHUP)
}
bool RequestController::Init()
@ -77,12 +93,6 @@ bool RequestController::Init()
dup2(s, 0);
if( !data.log_stdout )
close(1);
close(2);
//
@ -133,5 +143,13 @@ void RequestController::Loop()
log << log2 << "end request" << logend;
log << log2 << "---------------------------------------------------------------------------------" << logend;
// !! this should be immediately after FCGX_Accept() but signals don't want to break FCGX_Accept
if( data.signal_hup )
{
FCGX_Finish();
return;
}
}
}

View File

@ -32,11 +32,14 @@ class RequestController
Content content;
SessionManager session_manager;
public:
RequestController();
~RequestController();
bool Init();
void Close();
void Loop();
};