recognize startup parameters

Usage: winix [options]
  -c             : a path to the config file
  --config       : a path to the config file
  -h             : print usage information
  --help         : print usage information
  -?             : print usage information

While here:
- let it be possible to parse multiple configs,
- fix: some error messages were not printed at startup.
This commit is contained in:
Tomasz Sowa 2022-04-16 18:38:30 +02:00
parent e0d9989d74
commit 4f8b5e649a
3 changed files with 120 additions and 48 deletions

View File

@ -45,7 +45,6 @@ namespace Winix
Config::Config() Config::Config()
{ {
errors_to_stdout = true;
} }
@ -61,27 +60,19 @@ void Config::SetLogBuffer(pt::WTextStream * log_buffer)
} }
void Config::ShowError() void Config::ShowError(const std::wstring & config_file)
{ {
switch( parser.status ) switch( parser.status )
{ {
case pt::SpaceParser::ok: case pt::SpaceParser::ok:
log << log2 << "Config: syntax ok" << logend;
break; break;
case pt::SpaceParser::cant_open_file: case pt::SpaceParser::cant_open_file:
if( errors_to_stdout ) log << log1 << "Config: I cannot open a config file: " << config_file << logend;
std::wcout << L"Config: I cannot open a config file: " << config_file << std::endl;
log << log1 << "Config: cant open a config file: " << config_file << logend;
break; break;
case pt::SpaceParser::syntax_error: case pt::SpaceParser::syntax_error:
if( errors_to_stdout ) log << log1 << "Config: syntax error in file: " << config_file << ", line: " << parser.get_last_parsed_line() << logend;
std::wcout << "Config: syntax error, line: " << parser.get_last_parsed_line() << std::endl;
log << log1 << "Config: syntax error, line: " << parser.get_last_parsed_line() << logend;
break; break;
} }
} }
@ -91,28 +82,26 @@ void Config::ShowError()
bool Config::ReadConfig(bool errors_to_stdout_, bool stdout_is_closed) bool Config::ReadConfig(const std::wstring & config_file)
{ {
errors_to_stdout = errors_to_stdout_;
if( config_file.empty() ) if( config_file.empty() )
{ {
log << log2 << "Config: name of the config file is empty" << logend; log << log2 << "Config: name of the config file is empty" << logend;
return false; return false;
} }
log << log2 << "Config: reading a config file" << logend; log << log2 << "Config: reading a config file: " << config_file << logend;
pt::SpaceParser::Status status = parser.parse_space_file(config_file, space); pt::SpaceParser::Status status = parser.parse_space_file(config_file, space, false);
if( status == pt::SpaceParser::ok ) if( status == pt::SpaceParser::ok )
{ {
AssignValues(stdout_is_closed); AssignValues();
SetAdditionalVariables(); SetAdditionalVariables();
return true; return true;
} }
else else
{ {
ShowError(); ShowError(config_file);
return false; return false;
} }
} }
@ -120,7 +109,7 @@ bool Config::ReadConfig(bool errors_to_stdout_, bool stdout_is_closed)
void Config::AssignValues(bool stdout_is_closed) void Config::AssignValues()
{ {
server_mode = Text(L"server_mode"); server_mode = Text(L"server_mode");
demonize = Bool(L"demonize", true); demonize = Bool(L"demonize", true);

View File

@ -53,10 +53,6 @@ class Config
{ {
public: public:
// name of the config file
// this is the parameter passed to winix programm
std::wstring config_file;
// server mode // server mode
// you can assign any string to it such as "production" "dev" // you can assign any string to it such as "production" "dev"
// this value is not used by winix itself // this value is not used by winix itself
@ -857,7 +853,7 @@ public:
Config(); Config();
bool ReadConfig(bool errors_to_stdout_, bool stdout_is_closed = true); bool ReadConfig(const std::wstring & config_file);
/* /*
* *
@ -902,11 +898,10 @@ public:
private: private:
pt::SpaceParser parser; pt::SpaceParser parser;
bool errors_to_stdout;
Log log; Log log;
void ShowError(); void ShowError(const std::wstring & config_file);
void AssignValues(bool stdout_is_closed); void AssignValues();
void SetAdditionalVariables(); void SetAdditionalVariables();
void CheckPasswd(); void CheckPasswd();

View File

@ -5,7 +5,7 @@
*/ */
/* /*
* Copyright (c) 2008-2018, Tomasz Sowa * Copyright (c) 2008-2022, Tomasz Sowa
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -43,7 +43,7 @@
#include "core/app.h" #include "core/app.h"
#include "core/version.h" #include "core/version.h"
#include "utf8/utf8.h" #include "utf8/utf8.h"
#include "mainoptions/mainoptionsparser.h"
@ -59,11 +59,19 @@ App app;
void print_syntax() void print_syntax()
{ {
std::cout << "Syntax:" << std::endl; std::cout << "Winix version " << WINIX_VER_MAJOR << '.' << WINIX_VER_MINOR << '.' << WINIX_VER_REVISION << std::endl;
std::cout << " winix config_file" << std::endl; std::cout << "Copyright (c) 2008-2022, Tomasz Sowa" << std::endl;
std::cout << "Usage: winix [options]" << std::endl;
std::cout << " -c : a path to the config file" << std::endl;
std::cout << " --config : a path to the config file" << std::endl;
std::cout << " -h : print usage information" << std::endl;
std::cout << " --help : print usage information" << std::endl;
std::cout << " -? : print usage information" << std::endl;
std::cout << "At least one -c or --config parameter is required, use -c or --config option" << std::endl;
std::cout << "multiple times to load more than one config." << std::endl;
} }
@ -148,34 +156,107 @@ void RemovePidFile()
} }
bool ReadConfigs(const pt::Space::TableType & table, size_t & config_read)
{
bool status = true;
for(const pt::Space * config : table)
{
if( config->is_table() && config->table_size() == 1 )
{
std::wstring config_file = config->value.value_table[0]->to_wstr();
config_read += 1;
if( !app.config.ReadConfig(config_file) )
{
status = false;
break;
}
}
}
return status;
}
bool ReadConfigs(const pt::Space & options)
{
size_t config_read = 0;
bool status = true;
const pt::Space::TableType * table = options.get_table(L"c");
app.config.space.clear();
if( table )
{
status = status && ReadConfigs(*table, config_read);
}
table = options.get_table(L"config");
if( table )
{
status = status && ReadConfigs(*table, config_read);
}
if( config_read == 0 )
{
std::cout << "You have to provide a config file with c parameter" << std::endl;
Winix::print_syntax();
return false;
}
return status;
}
} // namespace Winix } // namespace Winix
int main(int argv, char ** argc)
int main(int argc, const char ** argv)
{ {
using Winix::app; using Winix::app;
std::srand(std::time(0)); std::srand(std::time(0));
app.system.system_start = time(0);
if( argv != 2 ) pt::Space options;
pt::Space arguments;
pt::MainOptionsParser options_parser;
arguments.add(L"c", 1);
arguments.add(L"config", 1);
pt::MainOptionsParser::Status status = options_parser.parse(argc, argv, options, arguments);
if( status != pt::MainOptionsParser::status_ok )
{ {
Winix::print_syntax(); Winix::print_syntax();
return 1;
}
app.system.system_start = time(0);
if( !pt::utf8_to_wide(argc[1], app.config.config_file) )
{
std::wcout << "An incorrect UTF-8 path of the config file" << std::endl;
return 6; return 6;
} }
if( !app.config.ReadConfig(true, false) ) /* errors to stdout, stdout in not closed */ if( options.has_key(L"h") || options.has_key(L"help") || options.has_key(L"?") )
return 2; {
Winix::print_syntax();
return 0;
}
Winix::Log & log = app.GetMainLog(); Winix::Log & log = app.GetMainLog();
Winix::LogInfo(log, Winix::log3, "UTC booting Winix", true, ""); // date will be printed as UTC because the time zones are not loaded yet
if( !Winix::ReadConfigs(options) )
{
// we need to print the buffer by hand because the logger
// is not fully initialized yet
pt::WTextStream * buffer = log.get_log_buffer();
if( buffer && !buffer->empty() )
{
pt::wide_stream_to_utf8(*buffer, std::cout);
}
return 2;
}
app.InitLoggers(); app.InitLoggers();
if( app.stdout_is_closed || app.config.demonize ) if( app.stdout_is_closed || app.config.demonize )
@ -185,15 +266,22 @@ using Winix::app;
Winix::CloseDescriptors(); Winix::CloseDescriptors();
if( app.config.demonize && !app.Demonize() ) if( app.config.demonize && !app.Demonize() )
{
log << Winix::logsave;
return 4; return 4;
}
Winix::LogInfo(log, Winix::log3, "booting Winix", true, "");
if( !app.InitFCGI() ) if( !app.InitFCGI() )
{
log << Winix::logsave;
return 5; return 5;
}
if( !app.DropPrivileges() ) if( !app.DropPrivileges() )
{
log << Winix::logsave;
return 3; return 3;
}
app.LogUserGroups(); app.LogUserGroups();
Winix::SavePidFile(log); Winix::SavePidFile(log);