24 #include <baseapp/daemonize.h> 25 #include <baseapp/main_thread.h> 26 #include <baseapp/run.h> 27 #include <baseapp/thread_manager.h> 28 #include <core/threading/thread.h> 30 #ifdef HAVE_BLACKBOARD 31 # include <blackboard/local.h> 33 #include <config/sqlite.h> 34 #include <config/yaml.h> 35 #ifdef HAVE_CONFIG_NETWORK_HANDLER 36 # include <config/net_handler.h> 38 #include <logging/console.h> 39 #include <logging/factory.h> 40 #include <logging/liblogger.h> 41 #include <logging/multi.h> 42 #include <utils/ipc/shm.h> 43 #include <utils/system/argparser.h> 44 #ifdef HAVE_NETWORK_LOGGER 45 # include <network_logger/network_logger.h> 47 #ifdef HAVE_LOGGING_FD_REDIRECT 48 # include <logging/fd_redirect.h> 50 #include <utils/time/clock.h> 51 #include <utils/time/time.h> 52 #ifdef HAVE_NETWORK_MANAGER 53 # include <netcomm/fawkes/network_manager.h> 55 #include <plugin/manager.h> 56 #ifdef HAVE_PLUGIN_NETWORK_HANDLER 57 # include <plugin/net/handler.h> 59 #include <aspect/manager.h> 60 #include <syncpoint/syncpoint_manager.h> 62 # include <tf/transform_listener.h> 63 # include <tf/transformer.h> 67 #include <sys/types.h> 81 class FawkesNetworkManager;
85 ArgumentParser * argument_parser = NULL;
86 FawkesMainThread * main_thread = NULL;
87 MultiLogger * logger = NULL;
88 NetworkLogger * network_logger = NULL;
89 BlackBoard * blackboard = NULL;
90 Configuration * config = NULL;
91 PluginManager * plugin_manager = NULL;
92 AspectManager * aspect_manager = NULL;
93 ThreadManager * thread_manager = NULL;
94 FawkesNetworkManager * network_manager = NULL;
95 ConfigNetworkHandler * nethandler_config = NULL;
96 PluginNetworkHandler * nethandler_plugin = NULL;
98 SharedMemoryRegistry * shm_registry;
99 InitOptions * init_options = NULL;
100 tf::Transformer * tf_transformer = NULL;
101 tf::TransformListener *tf_listener = NULL;
102 Time * start_time = NULL;
103 SyncPointManager * syncpoint_manager = NULL;
104 #ifdef HAVE_LOGGING_FD_REDIRECT 105 LogFileDescriptorToLog *log_fd_redirect_stderr_ = NULL;
106 LogFileDescriptorToLog *log_fd_redirect_stdout_ = NULL;
110 FawkesMainThread::Runner *runner = NULL;
113 init(
int argc,
char **argv,
int &retval)
115 return init(InitOptions(argc, argv), retval);
119 init(
const InitOptions &options,
int &retval)
121 init_options =
new InitOptions(options);
126 if (options.daemonize()) {
127 fawkes::daemon::init(options.daemon_pid_file(), options.basename());
128 if (options.daemonize_kill()) {
129 fawkes::daemon::kill();
132 }
else if (options.daemonize_status()) {
133 retval = fawkes::daemon::running() ? 0 : 1;
136 if (fawkes::daemon::start()) {
144 const char *user = NULL;
145 const char *group = NULL;
146 if (options.has_username()) {
147 user = options.username();
149 if (options.has_groupname()) {
150 group = options.groupname();
155 if (!(pw = getpwnam(user))) {
156 printf(
"Failed to find user %s, check -u argument.\n", user);
161 r = setreuid(pw->pw_uid, pw->pw_uid);
163 perror(
"Failed to drop privileges (user)");
169 if (!(gr = getgrnam(group))) {
170 printf(
"Failed to find group %s, check -g argument.\n", user);
175 r = setregid(gr->gr_gid, gr->gr_gid);
177 perror(
"Failed to drop privileges (group)");
185 struct passwd *uid_pw = getpwuid(getuid());
186 if (uid_pw == NULL) {
187 shm_registry =
new SharedMemoryRegistry();
190 if (asprintf(®istry_name, USER_SHM_NAME, uid_pw->pw_name) == -1) {
191 shm_registry =
new SharedMemoryRegistry();
193 shm_registry =
new SharedMemoryRegistry(registry_name);
199 throw Exception(
"Failed to create shared memory registry");
203 if (options.has_loggers()) {
206 }
catch (Exception &e) {
207 e.append(
"Initializing multi logger failed");
211 logger =
new MultiLogger(
new ConsoleLogger());
218 const char *homedir = getenv(
"HOME");
221 if (asprintf(&userdir,
"%s/%s", homedir, USERDIR) != -1) {
222 if (access(userdir, W_OK) != 0) {
223 if (mkdir(userdir, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) == -1) {
224 logger->
log_warn(
"FawkesMainThread",
225 "Failed to create .fawkes " 226 "directory %s, trying without",
236 SQLiteConfiguration *sqconfig = NULL;
238 if (options.config_file() && fnmatch(
"*.sql", options.config_file(), FNM_PATHNAME) == 0) {
239 sqconfig =
new SQLiteConfiguration(CONFDIR);
242 config =
new YamlConfiguration(CONFDIR);
245 config->
load(options.config_file());
249 SQLiteConfiguration::SQLiteValueIterator *i = sqconfig->modified_iterator();
251 std::string modtype = i->get_modtype();
252 if (modtype ==
"changed") {
253 logger->
log_warn(
"FawkesMainThread",
254 "Default config value CHANGED: %s" 257 i->get_oldvalue().c_str(),
258 i->get_as_string().c_str());
259 }
else if (modtype ==
"erased") {
260 logger->
log_warn(
"FawkesMainThread",
"Default config value ERASED: %s", i->path());
263 "Default config value ADDED: %s " 266 i->get_as_string().c_str());
270 }
catch (Exception &e) {
271 logger->
log_warn(
"FawkesMainThread",
272 "Failed to read modified default " 273 "config values, no dump?");
277 if (!options.has_loggers()) {
279 if (config->
exists(
"/fawkes/mainapp/loggers")) {
281 std::string loggers = config->
get_string(
"/fawkes/mainapp/loggers");
282 MultiLogger *new_logger =
287 }
catch (Exception &e) {
288 logger->
log_warn(
"FawkesMainThread",
289 "Loggers set in config file, " 290 "but failed to read, exception follows.");
291 logger->
log_warn(
"FawkesMainThread", e);
296 if (config->
exists(
"/fawkes/mainapp/log_stderr_as_warn")) {
298 bool log_stderr_as_warn = config->
get_bool(
"/fawkes/mainapp/log_stderr_as_warn");
299 if (log_stderr_as_warn) {
300 #ifdef HAVE_LOGGING_FD_REDIRECT 301 log_fd_redirect_stderr_ =
302 new LogFileDescriptorToLog(STDERR_FILENO, logger,
"stderr",
Logger::LL_WARN);
304 logger->
log_warn(
"FawkesMainThread",
305 "stderr log redirection enabled but not available at compile time");
308 }
catch (Exception &e) {
313 bool enable_ipv4 =
true;
314 bool enable_ipv6 =
true;
315 std::string listen_ipv4;
316 std::string listen_ipv6;
317 unsigned int net_tcp_port = 1910;
318 std::string net_service_name =
"Fawkes on %h";
319 if (options.has_net_tcp_port()) {
320 net_tcp_port = options.net_tcp_port();
323 net_tcp_port = config->
get_uint(
"/network/fawkes/tcp_port");
324 }
catch (Exception &e) {
328 if (options.has_net_service_name()) {
329 net_service_name = options.net_service_name();
332 net_service_name = config->
get_string(
"/network/fawkes/service_name");
333 }
catch (Exception &e) {
337 if (net_tcp_port > 65535) {
338 logger->
log_warn(
"FawkesMainThread",
"Invalid port '%u', using 1910", net_tcp_port);
343 enable_ipv4 = config->
get_bool(
"/network/ipv4/enable");
344 }
catch (Exception &e) {
347 enable_ipv6 = config->
get_bool(
"/network/ipv6/enable");
348 }
catch (Exception &e) {
352 listen_ipv4 = config->
get_string(
"/network/ipv4/listen");
353 }
catch (Exception &e) {
356 listen_ipv6 = config->
get_string(
"/network/ipv6/listen");
357 }
catch (Exception &e) {
361 logger->
log_warn(
"FawkesMainThread",
"Disabling IPv4 support");
364 logger->
log_warn(
"FawkesMainThread",
"Disabling IPv6 support");
366 if (!listen_ipv4.empty()) {
367 logger->
log_info(
"FawkesMainThread",
"Listening on IPv4 address %s", listen_ipv4.c_str());
369 if (!listen_ipv6.empty()) {
370 logger->
log_info(
"FawkesMainThread",
"Listening on IPv6 address %s", listen_ipv4.c_str());
373 #ifdef HAVE_BLACKBOARD 375 std::string bb_magic_token =
"";
376 unsigned int bb_size = 2097152;
378 bb_magic_token = config->
get_string(
"/fawkes/mainapp/blackboard_magic_token");
380 "BlackBoard magic token defined. " 381 "Using shared memory BlackBoard.");
382 }
catch (Exception &e) {
386 bb_size = config->
get_uint(
"/fawkes/mainapp/blackboard_size");
387 }
catch (Exception &e) {
389 "BlackBoard size not defined. " 390 "Will use %u, saving to default DB",
396 if (options.bb_cleanup()) {
402 LocalBlackBoard *lbb = NULL;
403 if (bb_magic_token ==
"") {
404 lbb =
new LocalBlackBoard(bb_size);
406 lbb =
new LocalBlackBoard(bb_size, bb_magic_token.c_str());
412 tf_transformer =
new tf::Transformer();
413 tf_listener =
new tf::TransformListener(blackboard, tf_transformer);
416 aspect_manager =
new AspectManager();
417 thread_manager =
new ThreadManager(aspect_manager, aspect_manager);
419 syncpoint_manager =
new SyncPointManager(logger);
421 plugin_manager =
new PluginManager(thread_manager,
423 "/fawkes/meta_plugins/",
424 options.plugin_module_flags(),
425 options.init_plugin_cache());
426 #ifdef HAVE_NETWORK_MANAGER 427 network_manager =
new FawkesNetworkManager(thread_manager,
433 net_service_name.c_str());
434 # ifdef HAVE_CONFIG_NETWORK_HANDLER 435 nethandler_config =
new ConfigNetworkHandler(config, network_manager->
hub());
437 # ifdef HAVE_PLUGIN_NETWORK_HANDLER 438 nethandler_plugin =
new PluginNetworkHandler(plugin_manager, network_manager->
hub());
439 nethandler_plugin->
start();
441 # ifdef HAVE_NETWORK_LOGGER 442 network_logger =
new NetworkLogger(network_manager->
hub(), logger->
loglevel());
448 start_time =
new Time(clock);
450 #if defined(HAVE_NETWORK_MANAGER) && defined(HAVE_BLACKBOARD) 451 lbb->start_nethandler(network_manager->
hub());
460 options.load_plugin_list(),
461 options.default_plugin());
468 #ifdef HAVE_NETWORK_MANAGER 469 network_manager->
hub(),
476 #ifdef HAVE_NETWORK_MANAGER 497 fawkes::daemon::cleanup();
500 #ifdef HAVE_PLUGIN_NETWORK_HANDLER 501 if (nethandler_plugin) {
502 nethandler_plugin->
cancel();
503 nethandler_plugin->
join();
507 #ifdef HAVE_NETWORK_LOGGER 512 delete network_logger;
516 #ifdef HAVE_CONFIG_NETWORK_HANDLER 517 delete nethandler_config;
519 #ifdef HAVE_PLUGIN_NETWORK_HANDLER 520 delete nethandler_plugin;
522 delete plugin_manager;
526 delete tf_transformer;
528 #ifdef HAVE_BLACKBOARD 532 delete argument_parser;
534 #ifdef HAVE_NETWORK_MANAGER 535 delete network_manager;
537 delete thread_manager;
538 delete aspect_manager;
540 #ifdef HAVE_LOGGING_FD_REDIRECT 541 delete log_fd_redirect_stderr_;
542 delete log_fd_redirect_stdout_;
546 argument_parser = NULL;
548 nethandler_config = NULL;
549 nethandler_plugin = NULL;
550 plugin_manager = NULL;
551 network_manager = NULL;
553 thread_manager = NULL;
554 aspect_manager = NULL;
557 #ifdef HAVE_LOGGING_FD_REDIRECT 558 log_fd_redirect_stderr_ = NULL;
559 log_fd_redirect_stdout_ = NULL;
573 }
catch (Exception &e) {
586 print_usage(init_options->
basename());
591 runner =
new FawkesMainThread::Runner(main_thread, defsigs);
595 }
catch (Exception &e) {
596 printf(
"Running Fawkes failed\n");
612 kill(getpid(), SIGINT);
616 print_usage(
const char *progname)
618 printf(
"Fawkes Main Application - Usage Instructions\n" 619 "================================================" 620 "===============================\n" 621 "Usage: %s [options] [plugins]\n" 623 " [plugins] is a space-separated list of plugins to load on startup in given order\n" 624 " [options] is one or more of:\n" 625 " -h These help instructions\n" 626 " -C Cleanup old BB and shared memory segments\n" 627 " -c config file Configuration file to load.\n" 628 " Examples: default.sql or config.yaml\n" 629 " -d Enable debug output\n" 630 " -q[qqq] Quiet mode, -q omits debug, -qq debug and" 632 "-qqq omit debug, info and warn, -qqqq no output\n" 633 " -l level Set log level directly mutually exclusive" 635 "level is one of debug, info, warn, error, or none\n" 636 " -L loggers Define loggers. By default this setting is" 638 "config (console logger if unset). Format is:\n" 639 " logger:args[;logger2:args2[!...]]\n" 640 " Currently supported:\n" 641 " console, file:file.log, network logger always added\n" 642 " -p plugins List of plugins to load on startup in given order\n" 643 " -P port TCP port to listen on for Fawkes network connections.\n" 644 " --net-service-name=name mDNS service name to use.\n" 645 " -u user Drop privileges and run as given user.\n" 646 " -g group Drop privileges and run as given group.\n" 647 #ifdef HAVE_LIBDAEMON
648 " -D[pid file] Run daemonized in the background, pid file " 650 "default is /var/run/fawkes.pid, must be absolute path.\n" 651 " -D[pid file] -k Kill a daemonized Fawkes running in the" 653 " -D[pid file] -s Check status of daemon.\n" 669 return now - start_time;
static void finalize()
Delete internal logger.
NetworkNameResolver * nnresolver()
Get network name resolver.
virtual void load(const char *file_path)=0
Load configuration.
static Clock * instance()
Clock initializer.
static void cleanup(const char *magic_token, bool use_lister=false)
Cleanup orphaned BlackBoard segments.
Fawkes library namespace.
virtual bool get_bool(const char *path)=0
Get value from configuration which is of type bool.
void register_default_inifins(BlackBoard *blackboard, ThreadCollector *collector, Configuration *config, Logger *logger, Clock *clock, FawkesNetworkHub *fnethub, MainLoopEmployer *mloop_employer, LoggerEmployer *logger_employer, BlockedTimingExecutor *btexec, NetworkNameResolver *nnresolver, ServicePublisher *service_publisher, ServiceBrowser *service_browser, PluginManager *pmanager, tf::Transformer *tf_listener, SyncPointManager *syncpoint_manager)
Register default aspect initializer/finalizer.
warning, should be investigated but software still functions, an example is that something was reques...
A class for handling time.
static void init_main()
Initialize Thread wrapper instance for main thread.
FawkesNetworkHub * hub()
Get Fawkes network hub.
static MultiLogger * multilogger_instance(const char *as, Logger::LogLevel default_ll=Logger::LL_DEBUG)
Create MultiLogger instance.
InitOptions & default_signal_handlers(bool enable)
Set default signal handlers.
virtual void set_loglevel(LogLevel level)
Sets the log level.
virtual void set_default_uint(const char *path, unsigned int uint)=0
Set new default value in configuration of type unsigned int.
static void destroy_main()
Destroy main thread wrapper instance.
virtual void log_warn(const char *component, const char *format,...)
Log warning message.
InitOptions & show_help(bool show_help)
Set to show help.
void add_logger(Logger *logger)
Add a logger.
ServicePublisher * service_publisher()
Get service publisher.
static void finalize()
Finalize.
virtual void log_info(const char *component, const char *format,...)
Log informational message.
void cancel()
Cancel a thread.
static void init(MultiLogger *multi_logger=NULL)
Initialize logger.
void run()
Run main thread.
ServiceBrowser * service_browser()
Get service browser.
void join()
Join the thread.
virtual bool exists(const char *path)=0
Check if a given value exists.
virtual unsigned int get_uint(const char *path)=0
Get value from configuration which is of type unsigned int.
const char * basename() const
Get program basename.
virtual LogLevel loglevel()
Get log level.
Fawkes default main thread.
ThreadCollector * aspect_collector() const
Get a thread collector to be used for an aspect initializer.
virtual void log_debug(const char *component, const char *format,...)
Log debug message.
void remove_logger(Logger *logger)
Remove logger.
virtual std::string get_string(const char *path)=0
Get value from configuration which is of type string.
void start(bool wait=true)
Call this method to start the thread.
InitOptions & daemonize(bool daemonize, bool kill=false, bool status=false, const char *pid_file=0)
Set daemonization options.
static void cleanup(const char *name=0)
Cleanup existing shared memory segments.