From 8aab9887528d1bcc2650df5f0e6adfc896ad0e7c Mon Sep 17 00:00:00 2001 From: Tomasz Sowa Date: Thu, 11 Dec 2008 02:46:16 +0000 Subject: [PATCH] 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 --- Makefile | 34 +++--- confparser/confparser.cpp | 208 +++++++++++++++++++++++++++++++++++++ confparser/confparser.h | 74 +++++++++++++ core/content.cpp | 4 +- core/data.cpp | 29 +----- core/data.h | 31 ++++-- core/db.cpp | 2 + core/error.h | 1 + core/log.cpp | 60 +++++------ core/log.h | 8 +- core/main.cpp | 76 +++++++++++--- core/request.cpp | 104 +------------------ core/request.h | 2 + core/requestcontroller.cpp | 30 ++++-- core/requestcontroller.h | 5 +- 15 files changed, 449 insertions(+), 219 deletions(-) create mode 100755 confparser/confparser.cpp create mode 100755 confparser/confparser.h diff --git a/Makefile b/Makefile index c19f4fc..e9bc04a 100755 --- a/Makefile +++ b/Makefile @@ -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) diff --git a/confparser/confparser.cpp b/confparser/confparser.cpp new file mode 100755 index 0000000..c5def8b --- /dev/null +++ b/confparser/confparser.cpp @@ -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(); +} + + + + + + + diff --git a/confparser/confparser.h b/confparser/confparser.h new file mode 100755 index 0000000..5413e3f --- /dev/null +++ b/confparser/confparser.h @@ -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 +#include +#include + + +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 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 diff --git a/core/content.cpp b/core/content.cpp index 0a76360..e38fd6d 100755 --- a/core/content.cpp +++ b/core/content.cpp @@ -460,9 +460,9 @@ void Content::Make() templates.Generate(); - // request.PrintGetTable(); + //request.PrintGetTable(); //request.PrintEnv(); - // request.PrintIn(); + //request.PrintIn(); } diff --git a/core/data.cpp b/core/data.cpp index c93ddec..787a59c 100755 --- a/core/data.cpp +++ b/core/data.cpp @@ -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 } - - - diff --git a/core/data.h b/core/data.h index fad1ffa..8eee011 100755 --- a/core/data.h +++ b/core/data.h @@ -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(); - }; diff --git a/core/db.cpp b/core/db.cpp index ec4c0e8..07ec1e0 100755 --- a/core/db.cpp +++ b/core/db.cpp @@ -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; diff --git a/core/error.h b/core/error.h index f44235e..80ff0a8 100755 --- a/core/error.h +++ b/core/error.h @@ -33,6 +33,7 @@ public: db_incorrect_login, db_more_than_one_login, db_err_currval, + incorrect_dir, diff --git a/core/log.cpp b/core/log.cpp index 5e4d30a..c6dd4ad 100755 --- a/core/log.cpp +++ b/core/log.cpp @@ -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 diff --git a/core/log.h b/core/log.h index 4994472..92d82ad 100755 --- a/core/log.h +++ b/core/log.h @@ -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(); - - }; diff --git a/core/main.cpp b/core/main.cpp index edd5feb..2d32d26 100755 --- a/core/main.cpp +++ b/core/main.cpp @@ -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; } diff --git a/core/request.cpp b/core/request.cpp index 7101a28..70a3612 100755 --- a/core/request.cpp +++ b/core/request.cpp @@ -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> 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='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; -} - - - - - -*/ - - - - diff --git a/core/request.h b/core/request.h index 8c967ac..decbe01 100755 --- a/core/request.h +++ b/core/request.h @@ -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() diff --git a/core/requestcontroller.cpp b/core/requestcontroller.cpp index 448cd12..2c67bde 100755 --- a/core/requestcontroller.cpp +++ b/core/requestcontroller.cpp @@ -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; + } } } diff --git a/core/requestcontroller.h b/core/requestcontroller.h index d195412..9cb570b 100755 --- a/core/requestcontroller.h +++ b/core/requestcontroller.h @@ -32,11 +32,14 @@ class RequestController Content content; SessionManager session_manager; + public: RequestController(); - + ~RequestController(); + bool Init(); + void Close(); void Loop(); };