From 4f8b5e649a39ef8f298d7b0b7ba006ba9ef1f5a0 Mon Sep 17 00:00:00 2001 From: Tomasz Sowa Date: Sat, 16 Apr 2022 18:38:30 +0200 Subject: [PATCH] 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. --- winixd/core/config.cpp | 31 ++++------ winixd/core/config.h | 11 +--- winixd/main/main.cpp | 126 ++++++++++++++++++++++++++++++++++------- 3 files changed, 120 insertions(+), 48 deletions(-) diff --git a/winixd/core/config.cpp b/winixd/core/config.cpp index 3530278..523624c 100644 --- a/winixd/core/config.cpp +++ b/winixd/core/config.cpp @@ -45,7 +45,6 @@ namespace Winix 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 ) { case pt::SpaceParser::ok: - log << log2 << "Config: syntax ok" << logend; break; - + case pt::SpaceParser::cant_open_file: - if( errors_to_stdout ) - 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; + log << log1 << "Config: I cannot open a config file: " << config_file << logend; break; case pt::SpaceParser::syntax_error: - if( errors_to_stdout ) - 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; + log << log1 << "Config: syntax error in file: " << config_file << ", line: " << parser.get_last_parsed_line() << logend; 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() ) { log << log2 << "Config: name of the config file is empty" << logend; return false; } - log << log2 << "Config: reading a config file" << logend; - pt::SpaceParser::Status status = parser.parse_space_file(config_file, space); + log << log2 << "Config: reading a config file: " << config_file << logend; + pt::SpaceParser::Status status = parser.parse_space_file(config_file, space, false); if( status == pt::SpaceParser::ok ) { - AssignValues(stdout_is_closed); + AssignValues(); SetAdditionalVariables(); return true; } else { - ShowError(); + ShowError(config_file); 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"); demonize = Bool(L"demonize", true); diff --git a/winixd/core/config.h b/winixd/core/config.h index c92e023..c492186 100644 --- a/winixd/core/config.h +++ b/winixd/core/config.h @@ -53,10 +53,6 @@ class Config { public: - // name of the config file - // this is the parameter passed to winix programm - std::wstring config_file; - // server mode // you can assign any string to it such as "production" "dev" // this value is not used by winix itself @@ -857,7 +853,7 @@ public: 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: pt::SpaceParser parser; - bool errors_to_stdout; Log log; - void ShowError(); - void AssignValues(bool stdout_is_closed); + void ShowError(const std::wstring & config_file); + void AssignValues(); void SetAdditionalVariables(); void CheckPasswd(); diff --git a/winixd/main/main.cpp b/winixd/main/main.cpp index f86e949..a4f86db 100644 --- a/winixd/main/main.cpp +++ b/winixd/main/main.cpp @@ -5,7 +5,7 @@ */ /* - * Copyright (c) 2008-2018, Tomasz Sowa + * Copyright (c) 2008-2022, Tomasz Sowa * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -43,7 +43,7 @@ #include "core/app.h" #include "core/version.h" #include "utf8/utf8.h" - +#include "mainoptions/mainoptionsparser.h" @@ -59,11 +59,19 @@ App app; - void print_syntax() { - std::cout << "Syntax:" << std::endl; - std::cout << " winix config_file" << std::endl; + std::cout << "Winix version " << WINIX_VER_MAJOR << '.' << WINIX_VER_MINOR << '.' << WINIX_VER_REVISION << 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 -int main(int argv, char ** argc) + +int main(int argc, const char ** argv) { using Winix::app; 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(); - 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; } - if( !app.config.ReadConfig(true, false) ) /* errors to stdout, stdout in not closed */ - return 2; + if( options.has_key(L"h") || options.has_key(L"help") || options.has_key(L"?") ) + { + Winix::print_syntax(); + return 0; + } 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(); if( app.stdout_is_closed || app.config.demonize ) @@ -185,15 +266,22 @@ using Winix::app; Winix::CloseDescriptors(); if( app.config.demonize && !app.Demonize() ) + { + log << Winix::logsave; return 4; - - Winix::LogInfo(log, Winix::log3, "booting Winix", true, ""); + } if( !app.InitFCGI() ) + { + log << Winix::logsave; return 5; + } if( !app.DropPrivileges() ) + { + log << Winix::logsave; return 3; + } app.LogUserGroups(); Winix::SavePidFile(log);