SNode.C
Loading...
Searching...
No Matches
utils::Config Class Reference

#include <Config.h>

Collaboration diagram for utils::Config:

Public Member Functions

 Config ()=delete
 
 Config (const Config &)=delete
 
 ~Config ()=delete
 
Configoperator= (const Config &)=delete
 

Static Public Member Functions

static bool init (int argc, char *argv[])
 
static bool bootstrap ()
 
static void terminate ()
 
static CLI::App * addInstance (const std::string &name, const std::string &description, const std::string &group)
 
static CLI::App * getInstance (const std::string &name)
 
static bool removeInstance (CLI::App *instance)
 
static void required (CLI::App *instance, bool required=true)
 
static void disabled (CLI::App *instance, bool disabled=true)
 
static CLI::App * addStandardFlags (CLI::App *app)
 
static CLI::App * addSimpleHelp (CLI::App *app)
 
static CLI::App * addHelp (CLI::App *app)
 
static std::string getApplicationName ()
 
static int getLogLevel ()
 
static int getVerboseLevel ()
 
static CLI::Option * addStringOption (const std::string &name, const std::string &description, const std::string &typeName)
 
static CLI::Option * addStringOption (const std::string &name, const std::string &description, const std::string &typeName, bool configurable)
 
static CLI::Option * addStringOption (const std::string &name, const std::string &description, const std::string &typeName, const std::string &defaultValue)
 
static CLI::Option * addStringOption (const std::string &name, const std::string &description, const std::string &typeName, const std::string &defaultValue, bool configurable)
 
static CLI::Option * addStringOption (const std::string &name, const std::string &description, const std::string &typeName, const char *defaultValue)
 
static CLI::Option * addStringOption (const std::string &name, const std::string &description, const std::string &typeName, const char *defaultValue, bool configurable)
 
static std::string getStringOptionValue (const std::string &name)
 
static void addFlag (const std::string &name, bool &variable, const std::string &description, bool required, bool configurable=true, const std::string &groupName="Application Options")
 

Static Public Attributes

static std::shared_ptr< CLI::App > app = makeApp()
 
static int argc = 0
 
static char ** argv = nullptr
 
static CLI::App * helpTriggerApp = nullptr
 
static CLI::App * showConfigTriggerApp = nullptr
 

Static Private Member Functions

static bool parse1 ()
 
static bool parse2 ()
 

Static Private Attributes

static std::shared_ptr< CLI::Formatter > sectionFormatter = makeSectionFormatter()
 
static bool subParse
 
static std::string applicationName
 
static std::string configDirectory
 
static std::string logDirectory
 
static std::string pidDirectory
 
static CLI::Option * daemonizeOpt = nullptr
 
static CLI::Option * logFileOpt = nullptr
 
static CLI::Option * userNameOpt = nullptr
 
static CLI::Option * groupNameOpt = nullptr
 
static CLI::Option * enforceLogFileOpt = nullptr
 
static CLI::Option * logLevelOpt = nullptr
 
static CLI::Option * verboseLevelOpt = nullptr
 
static CLI::Option * quietOpt = nullptr
 
static std::map< std::string, std::string > aliases
 
static std::map< std::string, CLI::Option * > applicationOptions
 

Detailed Description

Definition at line 61 of file Config.h.

Constructor & Destructor Documentation

◆ Config() [1/2]

utils::Config::Config ( )
delete

◆ Config() [2/2]

utils::Config::Config ( const Config )
delete

◆ ~Config()

utils::Config::~Config ( )
delete

Member Function Documentation

◆ addFlag()

void utils::Config::addFlag ( const std::string &  name,
bool &  variable,
const std::string &  description,
bool  required,
bool  configurable = true,
const std::string &  groupName = "Application Options" 
)
static

Definition at line 972 of file Config.cpp.

977 {
978 app->add_flag(name, variable, description) //
979 ->required(required) //
980 ->configurable(configurable) //
981 ->group(groupName);
982 }
static std::shared_ptr< CLI::App > app
Definition Config.h:123
static void required(CLI::App *instance, bool required=true)
Definition Config.cpp:850

◆ addHelp()

CLI::App * utils::Config::addHelp ( CLI::App *  app)
static

Definition at line 824 of file Config.cpp.

824 {
825 app->set_help_flag(
826 "-h{exact},--help{exact}",
827 [app](std::size_t) {
829 },
830 "Print help message and exit")
831 ->group(app->get_formatter()->get_label("Nonpersistent Options"))
832 ->check(CLI::IsMember({"standard", "exact", "expanded"}));
833
834 return app;
835 }
static CLI::App * helpTriggerApp
Definition Config.h:153

◆ addInstance()

CLI::App * utils::Config::addInstance ( const std::string &  name,
const std::string &  description,
const std::string &  group 
)
static

Definition at line 730 of file Config.cpp.

730 {
731 CLI::App* instanceSc = app->add_subcommand(name, description) //
732 ->group(group)
733 ->fallthrough()
734 ->formatter(sectionFormatter)
735 ->configurable(false)
736 ->allow_extras(false)
737 ->disabled(name.empty());
738
739 instanceSc //
740 ->option_defaults()
741 ->configurable(!instanceSc->get_disabled());
742
743 if (!instanceSc->get_disabled()) {
744 if (aliases.contains(name)) {
745 instanceSc //
746 ->alias(aliases[name]);
747 }
748 }
749
751 utils::Config::addHelp(instanceSc);
752
753 return instanceSc;
754 }
static CLI::App * addStandardFlags(CLI::App *app)
Definition Config.cpp:760
static CLI::App * addHelp(CLI::App *app)
Definition Config.cpp:824
static std::shared_ptr< CLI::Formatter > sectionFormatter
Definition Config.h:129
static std::map< std::string, std::string > aliases
Definition Config.h:157

◆ addSimpleHelp()

CLI::App * utils::Config::addSimpleHelp ( CLI::App *  app)
static

Definition at line 837 of file Config.cpp.

837 {
838 app->set_help_flag(
839 "--help{exact},-h{exact}",
840 [app](std::size_t) {
842 },
843 "Print help message and exit")
844 ->group(app->get_formatter()->get_label("Nonpersistent Options"))
845 ->check(CLI::IsMember({"standard", "exact"}));
846
847 return app;
848 }

◆ addStandardFlags()

CLI::App * utils::Config::addStandardFlags ( CLI::App *  app)
static

Definition at line 760 of file Config.cpp.

760 {
761 app //
762 ->add_flag_function(
763 "-s,--show-config",
764 [app](std::size_t) {
766 },
767 "Show current configuration and exit") //
768 ->configurable(false)
769 ->disable_flag_override();
770
771 app //
772 ->add_flag(
773 "--command-line{standard}",
774 [app]([[maybe_unused]] std::int64_t count) {
775 const std::string& result = app->get_option("--command-line")->as<std::string>();
776 if (result == "standard") {
778 app,
779 "Below is a command line viewing all non-default and required options:\n"
780 "* Options show their configured value\n"
781 "* Required but not yet configured options show <REQUIRED> as value\n"
782 "* Options marked as <REQUIRED> need to be configured for a successful bootstrap",
784 }
785 if (result == "required") {
787 app,
788 "Below is a command line viewing required options only:\n"
789 "* Options show either their configured or default value\n"
790 "* Required but not yet configured options show <REQUIRED> as value\n"
791 "* Options marked as <REQUIRED> need to be configured for a successful bootstrap",
793 }
794 if (result == "full") {
796 app,
797 "Below is a command line viewing the full set of options with their default or configured values:\n"
798 "* Options show either their configured or default value\n"
799 "* Required but not yet configured options show <REQUIRED> as value\n"
800 "* Options marked as <REQUIRED> need to be configured for a successful bootstrap",
802 }
803 if (result == "default") {
805 app,
806 "Below is a command line viewing the full set of options with their default values\n"
807 "* Options show their default value\n"
808 "* Required but not yet configured options show <REQUIRED> as value\n"
809 "* Options marked as <REQUIRED> need to be configured for a successful bootstrap",
811 }
812 },
813 "Print a command line\n"
814 " standard (default): View all non-default and required options\n"
815 " required: View required options only\n"
816 " full: View the full set of options with their default or configured values\n"
817 " default: View the full set of options with their default values")
818 ->configurable(false)
819 ->check(CLI::IsMember({"standard", "required", "full", "default"}));
820
821 return app;
822 }
static CLI::App * showConfigTriggerApp
Definition Config.h:154

References CLI::CallForCommandline::CallForCommandline(), CLI::CallForCommandline::DEFAULT, CLI::CallForCommandline::FULL, CLI::CallForCommandline::REQUIRED, and CLI::CallForCommandline::STANDARD.

Here is the call graph for this function:

◆ addStringOption() [1/6]

CLI::Option * utils::Config::addStringOption ( const std::string &  name,
const std::string &  description,
const std::string &  typeName 
)
static

Definition at line 907 of file Config.cpp.

907 {
908 applicationOptions[name] = app //
909 ->add_option(name, description)
910 ->type_name(typeName)
911 ->configurable()
912 ->required()
913 ->group("Application Options");
914
915 app->needs(applicationOptions[name]);
916
917 return applicationOptions[name];
918 }
static std::map< std::string, CLI::Option * > applicationOptions
Definition Config.h:158

◆ addStringOption() [2/6]

CLI::Option * utils::Config::addStringOption ( const std::string &  name,
const std::string &  description,
const std::string &  typeName,
bool  configurable 
)
static

Definition at line 921 of file Config.cpp.

921 {
922 addStringOption(name, description, typeName);
923 return applicationOptions[name] //
924 ->configurable(configurable);
925 }
static CLI::Option * addStringOption(const std::string &name, const std::string &description, const std::string &typeName)
Definition Config.cpp:907

◆ addStringOption() [3/6]

CLI::Option * utils::Config::addStringOption ( const std::string &  name,
const std::string &  description,
const std::string &  typeName,
const char *  defaultValue 
)
static

Definition at line 952 of file Config.cpp.

955 {
956 return addStringOption(name, description, typeName, std::string(defaultValue));
957 }

◆ addStringOption() [4/6]

CLI::Option * utils::Config::addStringOption ( const std::string &  name,
const std::string &  description,
const std::string &  typeName,
const char *  defaultValue,
bool  configurable 
)
static

Definition at line 959 of file Config.cpp.

960 {
961 return addStringOption(name, description, typeName, std::string(defaultValue), configurable);
962 }

◆ addStringOption() [5/6]

CLI::Option * utils::Config::addStringOption ( const std::string &  name,
const std::string &  description,
const std::string &  typeName,
const std::string &  defaultValue 
)
static

Definition at line 927 of file Config.cpp.

930 {
931 addStringOption(name, description, typeName);
932
933 applicationOptions[name] //
934 ->required(false)
935 ->default_str(defaultValue);
936
937 app->remove_needs(applicationOptions[name]);
938
939 return applicationOptions[name];
940 }

◆ addStringOption() [6/6]

CLI::Option * utils::Config::addStringOption ( const std::string &  name,
const std::string &  description,
const std::string &  typeName,
const std::string &  defaultValue,
bool  configurable 
)
static

Definition at line 942 of file Config.cpp.

946 {
947 addStringOption(name, description, typeName, defaultValue);
948 return applicationOptions[name] //
949 ->configurable(configurable);
950 }

◆ bootstrap()

bool utils::Config::bootstrap ( )
static

Definition at line 362 of file Config.cpp.

362 {
363 aliases.clear();
364
365 app->final_callback([]() {
366 if (daemonizeOpt->as<bool>() && helpTriggerApp == nullptr && showConfigTriggerApp == nullptr &&
367 (*app)["--write-config"]->count() == 0 && (*app)["--command-line"]->count() == 0) {
368 std::cout << "Running as daemon (double fork)" << std::endl;
369
370 utils::Daemon::startDaemon(
371 pidDirectory + "/" + applicationName + ".pid", userNameOpt->as<std::string>(), groupNameOpt->as<std::string>());
372
373 logger::Logger::setQuiet();
374
375 const std::string logFile = logFileOpt->as<std::string>();
376 if (!logFile.empty()) {
377 logger::Logger::logToFile(logFile);
378 }
379 } else if ((*app)["--enforce-log-file"]->as<bool>()) {
380 const std::string logFile = logFileOpt->as<std::string>();
381 if (!logFile.empty()) {
382 std::cout << "Writing logs to file " << logFile << std::endl;
383
385 }
386 }
387 });
388
389 return parse2();
390 }
static void logToFile(const std::string &logFile)
Definition Logger.cpp:127
static bool parse2()
Definition Config.cpp:577
static CLI::Option * logFileOpt
Definition Config.h:144
static CLI::Option * daemonizeOpt
Definition Config.h:143

References logger::Logger::logToFile(), logger::Logger::setQuiet(), and utils::Daemon::startDaemon().

Here is the call graph for this function:

◆ disabled()

void utils::Config::disabled ( CLI::App *  instance,
bool  disabled = true 
)
static

Definition at line 873 of file Config.cpp.

873 {
874 if (disabled) {
875 if (instance->get_ignore_case()) {
876 app->remove_needs(instance);
877 }
878
879 for (const auto& sub : instance->get_subcommands({})) {
880 if (sub->get_ignore_case()) {
881 instance->remove_needs(sub);
882 sub->required(false); // ### must be stored in ConfigInstance
883 }
884 }
885 } else {
886 if (instance->get_ignore_case()) {
887 app->needs(instance);
888 }
889
890 for (const auto& sub : instance->get_subcommands({})) {
891 if (sub->get_ignore_case()) { // ### must be recalled from ConfigInstance
892 instance->needs(sub);
893 sub->required();
894 }
895 }
896 }
897
898 instance->required(disabled ? false : instance->get_ignore_case());
899 }
static void disabled(CLI::App *instance, bool disabled=true)
Definition Config.cpp:873

◆ getApplicationName()

std::string utils::Config::getApplicationName ( )
static

Definition at line 984 of file Config.cpp.

984 {
985 return applicationName;
986 }
static std::string applicationName
Definition Config.h:137

◆ getInstance()

CLI::App * utils::Config::getInstance ( const std::string &  name)
static

Definition at line 756 of file Config.cpp.

756 {
757 return app->get_subcommand(name);
758 }

◆ getLogLevel()

int utils::Config::getLogLevel ( )
static

Definition at line 988 of file Config.cpp.

988 {
989 return logLevelOpt->as<int>();
990 }
static CLI::Option * logLevelOpt
Definition Config.h:148

◆ getStringOptionValue()

std::string utils::Config::getStringOptionValue ( const std::string &  name)
static

Definition at line 964 of file Config.cpp.

964 {
965 if (app->get_option(name) == nullptr) {
966 throw CLI::OptionNotFound(name);
967 }
968
969 return (*app)[name]->as<std::string>();
970 }

◆ getVerboseLevel()

int utils::Config::getVerboseLevel ( )
static

Definition at line 992 of file Config.cpp.

992 {
993 return verboseLevelOpt->as<int>();
994 }
static CLI::Option * verboseLevelOpt
Definition Config.h:149

◆ init()

bool utils::Config::init ( int  argc,
char *  argv[] 
)
static

Definition at line 130 of file Config.cpp.

130 {
131 bool proceed = true;
132
135
136 applicationName = std::filesystem::path(argv[0]).filename();
137
138 uid_t euid = 0;
139 struct passwd* pw = nullptr;
140 struct group* gr = nullptr;
141
142 if ((pw = getpwuid(getuid())) == nullptr) {
143 proceed = false;
144 } else if ((gr = getgrgid(pw->pw_gid)) == nullptr) {
145 proceed = false;
146 } else if ((euid = geteuid()) == 0) {
147 configDirectory = "/etc/snode.c";
148 logDirectory = "/var/log/snode.c";
149 pidDirectory = "/var/run/snode.c";
150 } else {
151 const char* homedir = nullptr;
152 if ((homedir = std::getenv("XDG_CONFIG_HOME")) == nullptr) {
153 if ((homedir = std::getenv("HOME")) == nullptr) {
154 homedir = pw->pw_dir;
155 }
156 }
157
158 if (homedir != nullptr) {
159 configDirectory = std::string(homedir) + "/.config/snode.c";
160 logDirectory = std::string(homedir) + "/.local/log/snode.c";
161 pidDirectory = std::string(homedir) + "/.local/run/snode.c";
162 } else {
163 proceed = false;
164 }
165 }
166
167 if (proceed && !std::filesystem::exists(configDirectory)) {
168 if (std::filesystem::create_directories(configDirectory)) {
169 std::filesystem::permissions(
171 (std::filesystem::perms::owner_all | std::filesystem::perms::group_read | std::filesystem::perms::group_exec) &
172 ~std::filesystem::perms::others_all);
173 if (geteuid() == 0) {
174 struct group* gr = nullptr;
175 if ((gr = getgrnam(XSTR(GROUP_NAME))) != nullptr) {
176 if (chown(configDirectory.c_str(), euid, gr->gr_gid) < 0) {
177 std::cout << "Warning: Can not set group ownership of '" << configDirectory
178 << "' to 'snodec':" << strerror(errno) << std::endl;
179 }
180 } else {
181 std::cout << "Error: Can not find group 'snodec'. Add it using groupadd or addgroup" << std::endl;
182 std::cout << " and add the current user to this group." << std::endl;
183 std::filesystem::remove(configDirectory);
184 proceed = false;
185 }
186 }
187 } else {
188 std::cout << "Error: Can not create directory '" << configDirectory << "'" << std::endl;
189 proceed = false;
190 }
191 }
192
193 if (proceed && !std::filesystem::exists(logDirectory)) {
194 if (std::filesystem::create_directories(logDirectory)) {
195 std::filesystem::permissions(logDirectory,
196 (std::filesystem::perms::owner_all | std::filesystem::perms::group_all) &
197 ~std::filesystem::perms::others_all);
198 if (geteuid() == 0) {
199 struct group* gr = nullptr;
200 if ((gr = getgrnam(XSTR(GROUP_NAME))) != nullptr) {
201 if (chown(logDirectory.c_str(), euid, gr->gr_gid) < 0) {
202 std::cout << "Warning: Can not set group ownership of '" << logDirectory << "' to 'snodec':" << strerror(errno)
203 << std::endl;
204 }
205 } else {
206 std::cout << "Error: Can not find group 'snodec'. Add it using groupadd or addgroup" << std::endl;
207 std::cout << " and add the current user to this group." << std::endl;
208 std::filesystem::remove(configDirectory);
209 proceed = false;
210 }
211 }
212 } else {
213 std::cout << "Error: Can not create directory '" << logDirectory << "'" << std::endl;
214 proceed = false;
215 }
216 }
217
218 if (proceed && !std::filesystem::exists(pidDirectory)) {
219 if (std::filesystem::create_directories(pidDirectory)) {
220 std::filesystem::permissions(pidDirectory,
221 (std::filesystem::perms::owner_all | std::filesystem::perms::group_all) &
222 ~std::filesystem::perms::others_all);
223 if (geteuid() == 0) {
224 struct group* gr = nullptr;
225 if ((gr = getgrnam(XSTR(GROUP_NAME))) != nullptr) {
226 if (chown(pidDirectory.c_str(), euid, gr->gr_gid) < 0) {
227 std::cout << "Warning: Can not set group ownership of '" << pidDirectory << "' to 'snodec':" << strerror(errno)
228 << std::endl;
229 }
230 } else {
231 std::cout << "Error: Can not find group 'snodec'. Add it using groupadd or addgroup." << std::endl;
232 std::cout << " and add the current user to this group." << std::endl;
233 std::filesystem::remove(configDirectory);
234 proceed = false;
235 }
236 }
237 } else {
238 std::cout << "Error: Can not create directory '" << pidDirectory << "'" << std::endl;
239 proceed = false;
240 }
241 }
242
243 if (proceed) {
244 app->description("Configuration for Application '" + applicationName + "'");
245
246 app->footer("Application '" + applicationName +
247 "' powered by SNode.C\n"
248 "(C) 2020-2025 Volker Christian <me@vchrist.at>\n"
249 "https://github.com/SNodeC/snode.c");
250
251 app->set_config( //
252 "-c,--config-file",
253 configDirectory + "/" + applicationName + ".conf",
254 "Read a config file",
255 false) //
256 ->take_all()
257 ->type_name("configfile")
258 ->check(!CLI::ExistingDirectory);
259
260 app->add_option("-w,--write-config", "Write config file and exit")
261 ->configurable(false)
262 ->default_val(configDirectory + "/" + applicationName + ".conf")
263 ->type_name("[configfile]")
264 ->check(!CLI::ExistingDirectory)
265 ->expected(0, 1);
266
267 app->add_flag( //
268 "-k,--kill",
269 "Kill running daemon") //
270 ->configurable(false)
271 ->disable_flag_override();
272
273 app->add_option( //
274 "-i,--instance-alias",
275 "Make an instance also known as an alias in configuration files")
276 ->configurable(false)
277 ->type_name("instance=instance_alias [instance=instance_alias [...]]")
278 ->each([](const std::string& item) {
279 const auto it = item.find('=');
280 if (it != std::string::npos) {
281 aliases[item.substr(0, it)] = item.substr(it + 1);
282 } else {
283 throw CLI::ConversionError("Can not convert '" + item + "' to a 'instance=instance_alias' pair");
284 }
285 });
286
287 addStandardFlags(app.get());
288
289 logLevelOpt = app->add_option( //
290 "-l,--log-level",
291 "Log level") //
292 ->default_val(4)
293 ->type_name("level")
294 ->check(CLI::Range(0, 6))
295 ->group(app->get_formatter()->get_label("Persistent Options"));
296
297 verboseLevelOpt = app->add_option( //
298 "-v,--verbose-level",
299 "Verbose level") //
300 ->default_val(2)
301 ->type_name("level")
302 ->check(CLI::Range(0, 10))
303 ->group(app->get_formatter()->get_label("Persistent Options"));
304
305 quietOpt = app->add_flag( //
306 "-q{true},!-u,--quiet{true}",
307 "Quiet mode") //
308 ->default_val("false")
309 ->type_name("bool")
310 ->check(CLI::IsMember({"true", "false"}))
311 ->group(app->get_formatter()->get_label("Persistent Options"));
312
313 logFileOpt = app->add_option( //
314 "--log-file",
315 "Log file path") //
316 ->default_val(logDirectory + "/" + applicationName + ".log")
317 ->type_name("logfile")
318 ->check(!CLI::ExistingDirectory)
319 ->group(app->get_formatter()->get_label("Persistent Options"));
320
321 enforceLogFileOpt = app->add_flag( //
322 "-e{true},!-n,--enforce-log-file{true}",
323 "Enforce writing of logs to file for foreground applications") //
324 ->default_val("false")
325 ->type_name("bool")
326 ->check(CLI::IsMember({"true", "false"}))
327 ->group(app->get_formatter()->get_label("Persistent Options"));
328
329 daemonizeOpt = app->add_flag( //
330 "-d{true},!-f,--daemonize{true}",
331 "Start application as daemon") //
332 ->default_val("false")
333 ->type_name("bool")
334 ->check(CLI::IsMember({"true", "false"}))
335 ->group(app->get_formatter()->get_label("Persistent Options"));
336
337 userNameOpt = app->add_option( //
338 "--user-name",
339 "Run daemon under specific user permissions") //
340 ->default_val(pw->pw_name)
341 ->type_name("username")
342 ->needs(daemonizeOpt)
343 ->group(app->get_formatter()->get_label("Persistent Options"));
344
345 groupNameOpt = app->add_option( //
346 "--group-name",
347 "Run daemon under specific group permissions")
348 ->default_val(gr->gr_name)
349 ->type_name("groupname")
350 ->needs(daemonizeOpt)
351 ->group(app->get_formatter()->get_label("Persistent Options"));
352
353 proceed = parse1(); // for stopDaemon and pre init application options
354
355 app->set_version_flag("--version", "1.0-rc1", "Framework version");
356 addHelp(app.get());
357 }
358
359 return proceed;
360 }
#define XSTR(s)
static bool parse1()
Definition Config.cpp:392
static char ** argv
Definition Config.h:133
static std::string configDirectory
Definition Config.h:139
static CLI::Option * groupNameOpt
Definition Config.h:146
static CLI::Option * quietOpt
Definition Config.h:150
static int argc
Definition Config.h:132
static std::string pidDirectory
Definition Config.h:141
static CLI::Option * enforceLogFileOpt
Definition Config.h:147
static std::string logDirectory
Definition Config.h:140
static CLI::Option * userNameOpt
Definition Config.h:145

◆ operator=()

Config & utils::Config::operator= ( const Config )
delete

◆ parse1()

bool utils::Config::parse1 ( )
staticprivate

Definition at line 392 of file Config.cpp.

392 {
393 bool proceed = true;
394
395 try {
396 app->parse(argc, argv);
397 } catch (const CLI::ParseError&) {
398 // Do not process ParseError here but on second parse pass
399 }
400
401 if ((*app)["--kill"]->count() > 0) {
402 try {
403 const pid_t daemonPid = utils::Daemon::stopDaemon(pidDirectory + "/" + applicationName + ".pid");
404 std::cout << "Daemon terminated: Pid = " << daemonPid << std::endl;
405 } catch (const DaemonError& e) {
406 std::cout << "DaemonError: " << e.what() << std::endl;
407 } catch (const DaemonFailure& e) {
408 std::cout << "DaemonFailure: " << e.what() << std::endl;
409 }
410
411 proceed = false;
412 } else {
413 app->allow_extras((*app)["--show-config"]->count() != 0);
414
415 if (!quietOpt->as<bool>()) {
418 }
419
421 }
422
423 return proceed;
424 }
static void setVerboseLevel(int level)
Definition Logger.cpp:121
static void setLogLevel(int level)
Definition Logger.cpp:84
static void setQuiet(bool quiet=true)
Definition Logger.cpp:136
static pid_t stopDaemon(const std::string &pidFileName)
Definition Daemon.cpp:158

References logger::Logger::setLogLevel(), logger::Logger::setQuiet(), logger::Logger::setVerboseLevel(), and utils::Daemon::stopDaemon().

Here is the call graph for this function:

◆ parse2()

bool utils::Config::parse2 ( )
staticprivate

Definition at line 577 of file Config.cpp.

577 {
578 bool success = false;
579
580 try {
581 try {
582 try {
583 app->parse(argc, argv);
584 success = true;
585 } catch (const CLI::ParseError&) {
586 if (helpTriggerApp == nullptr) {
587 if (showConfigTriggerApp != nullptr) {
588 success = false;
590 }
591 if ((*app)["--write-config"]->count() > 0) {
592 success = false;
593 throw CLI::CallForWriteConfig((*app)["--write-config"]->as<std::string>());
594 }
595 }
596
597 throw;
598 }
599 if (helpTriggerApp == nullptr) {
600 if (showConfigTriggerApp != nullptr) {
601 success = false;
603 }
604 if ((*app)["--write-config"]->count() > 0) {
605 success = false;
606 throw CLI::CallForWriteConfig((*app)["--write-config"]->as<std::string>());
607 }
608 }
609 } catch (const DaemonError& e) {
610 std::cout << "[" << Color::Code::FG_RED << "Error" << Color::Code::FG_DEFAULT << "] Daemonize: " << e.what()
611 << " ... exiting" << std::endl;
612 } catch (const DaemonFailure& e) {
613 std::cout << "[" << Color::Code::FG_RED << "Failure" << Color::Code::FG_DEFAULT << "] Daemonize: " << e.what()
614 << " ... exiting" << std::endl;
615 } catch (const DaemonSignaled& e) {
616 std::cout << "Pid: " << getpid() << ", child pid: " << e.getPid() << ": " << e.what() << std::endl;
617 } catch (const CLI::CallForHelp&) {
618 const std::string helpMode = helpTriggerApp->get_option("--help")->as<std::string>();
619 const CLI::App* helpApp = nullptr;
620 CLI::AppFormatMode mode = CLI::AppFormatMode::Normal;
621 if (helpMode == "exact") {
623 } else if (helpMode == "expanded") {
625 mode = CLI::AppFormatMode::All;
626 }
627 std::cout << app->help(helpApp, "", mode) << std::endl;
628 } catch (const CLI::CallForVersion&) {
629 std::cout << app->version() << std::endl << std::endl;
630 } catch (const CLI::CallForCommandline& e) {
631 std::cout << e.what() << std::endl;
632 std::cout << std::endl
633 << Color::Code::FG_GREEN << "command@line" << Color::Code::FG_DEFAULT << ":" << Color::Code::FG_BLUE << "~/> "
635 << std::endl;
636 } catch (const CLI::CallForShowConfig& e) {
637 try {
638 std::cout << e.getApp()->config_to_str(true, true);
639 } catch (const CLI::ParseError& e1) {
640 std::cout << "[" << Color::Code::FG_RED << "Error" << Color::Code::FG_DEFAULT << "] Showing config file: " << e.getApp()
641 << " " << e1.get_name() << " " << e1.what() << std::endl;
642 throw;
643 }
644 } catch (const CLI::CallForWriteConfig& e) {
645 std::cout << e.what() << std::endl;
646 std::ofstream confFile(e.getConfigFile());
647 if (confFile.is_open()) {
648 try {
649 confFile << app->config_to_str(true, true);
650 confFile.close();
651 } catch (const CLI::ParseError& e1) {
652 confFile.close();
653 std::cout << "Error writing config file: " << e1.get_name() << " " << e1.what() << std::endl;
654 throw;
655 }
656 } else {
657 std::cout << "[" << Color::Code::FG_RED << "Error" << Color::Code::FG_DEFAULT
658 << "] Writing config file: " << std::strerror(errno) << std::endl;
659 }
660 } catch (const CLI::ConversionError& e) {
661 std::cout << "[" << Color::Code::FG_RED << e.get_name() << Color::Code::FG_DEFAULT << "] " << e.what() << std::endl;
662 throw;
663 } catch (const CLI::ArgumentMismatch& e) {
664 std::cout << "[" << Color::Code::FG_RED << e.get_name() << Color::Code::FG_DEFAULT << "] " << e.what() << std::endl;
665 throw;
666 } catch (const CLI::ConfigError& e) {
667 std::cout << "[" << Color::Code::FG_RED << e.get_name() << Color::Code::FG_DEFAULT << "] " << e.what() << std::endl;
668 std::cout << " Adding '-w' on the command line may solve this problem" << std::endl;
669 throw;
670 } catch (const CLI::ParseError& e) {
671 const std::string what = e.what();
672 if (what.find("[Option Group: ") != std::string::npos) { // If CLI11 throws that error it means for us there are
673 // unconfigured anonymous instances
674 std::cout << Color::Code::FG_RED << e.get_name() << Color::Code::FG_DEFAULT
675 << " Anonymous instance(s) not configured in source code " << std::endl;
676 } else {
677 std::cout << "[" << Color::Code::FG_RED << e.get_name() << Color::Code::FG_DEFAULT << "] " << what << std::endl;
678 }
679 throw;
680 }
681 } catch ([[maybe_unused]] const CLI::ParseError& e) {
682 std::cout << std::endl << "Append -h or --help to your command line for more information." << std::endl;
683 } catch (const CLI::Error& e) {
684 std::cout << "[" << Color::Code::FG_RED << e.get_name() << Color::Code::FG_DEFAULT << "] " << e.what() << std::endl;
685
686 std::cout << std::endl << "Append -h or --help to your command line for more information." << std::endl;
687 }
688
689 return success;
690 }
CLI::App * getApp() const
CLI::App * getApp() const
std::string getConfigFile() const
static void createCommandLineTemplate(std::stringstream &out, CLI::App *app, CLI::CallForCommandline::Mode mode)
Definition Config.cpp:542

References CLI::CallForShowConfig::CallForShowConfig(), CLI::CallForWriteConfig::CallForWriteConfig(), utils::createCommandLineTemplate(), Color::FG_BLUE, Color::FG_DEFAULT, Color::FG_GREEN, Color::FG_RED, CLI::CallForCommandline::getApp(), CLI::CallForShowConfig::getApp(), CLI::CallForWriteConfig::getConfigFile(), CLI::CallForCommandline::getMode(), and utils::DaemonSignaled::getPid().

Here is the call graph for this function:

◆ removeInstance()

bool utils::Config::removeInstance ( CLI::App *  instance)
static

Definition at line 901 of file Config.cpp.

901 {
902 Config::required(instance, false);
903
904 return app->remove_subcommand(instance);
905 }

◆ required()

void utils::Config::required ( CLI::App *  instance,
bool  required = true 
)
static

Definition at line 850 of file Config.cpp.

850 {
851 if (required) {
852 app->needs(instance);
853
854 for (const auto& sub : instance->get_subcommands([](const CLI::App* sc) -> bool {
855 return sc->get_required();
856 })) {
857 instance->needs(sub);
858 }
859 } else {
860 app->remove_needs(instance);
861
862 for (const auto& sub : instance->get_subcommands([](const CLI::App* sc) -> bool {
863 return sc->get_required();
864 })) {
865 instance->remove_needs(sub);
866 }
867 }
868
869 instance->required(required);
870 instance->ignore_case(required);
871 }

◆ terminate()

void utils::Config::terminate ( )
static

Definition at line 692 of file Config.cpp.

692 {
693 if ((*app)["--daemonize"]->as<bool>()) {
694 std::ifstream pidFile(pidDirectory + "/" + applicationName + ".pid", std::ifstream::in);
695
696 if (pidFile.good()) {
697 pid_t pid = 0;
698 pidFile >> pid;
699
700 if (getpid() == pid) {
702 }
703 }
704 } else if (fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK) >= 0) {
705 char buf[1024];
706 while (read(STDIN_FILENO, buf, 1024) > 0) {
707 }
708 }
709 }
static void erasePidFile(const std::string &pidFileName)
Definition Daemon.cpp:200
ssize_t read(int fd, void *buf, std::size_t count)
Definition unistd.cpp:57

References utils::Daemon::erasePidFile().

Here is the call graph for this function:

Member Data Documentation

◆ aliases

std::map< std::string, std::string > utils::Config::aliases
staticprivate

Definition at line 157 of file Config.h.

◆ app

std::shared_ptr< CLI::App > utils::Config::app = makeApp()
static

Definition at line 123 of file Config.h.

◆ applicationName

std::string utils::Config::applicationName
staticprivate

Definition at line 137 of file Config.h.

◆ applicationOptions

std::map< std::string, CLI::Option * > utils::Config::applicationOptions
staticprivate

Definition at line 158 of file Config.h.

◆ argc

int utils::Config::argc = 0
static

Definition at line 132 of file Config.h.

◆ argv

char ** utils::Config::argv = nullptr
static

Definition at line 133 of file Config.h.

◆ configDirectory

std::string utils::Config::configDirectory
staticprivate

Definition at line 139 of file Config.h.

◆ daemonizeOpt

CLI::Option * utils::Config::daemonizeOpt = nullptr
staticprivate

Definition at line 143 of file Config.h.

◆ enforceLogFileOpt

CLI::Option * utils::Config::enforceLogFileOpt = nullptr
staticprivate

Definition at line 147 of file Config.h.

◆ groupNameOpt

CLI::Option * utils::Config::groupNameOpt = nullptr
staticprivate

Definition at line 146 of file Config.h.

◆ helpTriggerApp

CLI::App * utils::Config::helpTriggerApp = nullptr
static

Definition at line 153 of file Config.h.

◆ logDirectory

std::string utils::Config::logDirectory
staticprivate

Definition at line 140 of file Config.h.

◆ logFileOpt

CLI::Option * utils::Config::logFileOpt = nullptr
staticprivate

Definition at line 144 of file Config.h.

◆ logLevelOpt

CLI::Option * utils::Config::logLevelOpt = nullptr
staticprivate

Definition at line 148 of file Config.h.

◆ pidDirectory

std::string utils::Config::pidDirectory
staticprivate

Definition at line 141 of file Config.h.

◆ quietOpt

CLI::Option * utils::Config::quietOpt = nullptr
staticprivate

Definition at line 150 of file Config.h.

◆ sectionFormatter

std::shared_ptr< CLI::Formatter > utils::Config::sectionFormatter = makeSectionFormatter()
staticprivate

Definition at line 129 of file Config.h.

◆ showConfigTriggerApp

CLI::App * utils::Config::showConfigTriggerApp = nullptr
static

Definition at line 154 of file Config.h.

◆ subParse

bool utils::Config::subParse
staticprivate

Definition at line 136 of file Config.h.

◆ userNameOpt

CLI::Option * utils::Config::userNameOpt = nullptr
staticprivate

Definition at line 145 of file Config.h.

◆ verboseLevelOpt

CLI::Option * utils::Config::verboseLevelOpt = nullptr
staticprivate

Definition at line 149 of file Config.h.


The documentation for this class was generated from the following files: