24 #include <baseapp/run.h>
25 #include <baseapp/daemonize.h>
26 #include <baseapp/main_thread.h>
27 #include <baseapp/thread_manager.h>
29 #include <core/threading/thread.h>
31 #include <blackboard/local.h>
32 #include <config/sqlite.h>
33 #include <config/net_handler.h>
34 #include <utils/ipc/shm.h>
35 #include <utils/system/argparser.h>
36 #include <logging/multi.h>
37 #include <logging/console.h>
38 #include <logging/liblogger.h>
39 #include <logging/factory.h>
40 #include <logging/network.h>
41 #include <utils/time/clock.h>
42 #include <netcomm/fawkes/network_manager.h>
43 #include <plugin/manager.h>
44 #include <plugin/net/handler.h>
45 #include <aspect/manager.h>
48 #include <sys/types.h>
65 ArgumentParser * argument_parser = NULL;
66 FawkesMainThread * main_thread = NULL;
67 MultiLogger * logger = NULL;
68 NetworkLogger * network_logger = NULL;
69 BlackBoard * blackboard = NULL;
70 SQLiteConfiguration * config = NULL;
71 PluginManager * plugin_manager = NULL;
72 AspectManager * aspect_manager = NULL;
73 ThreadManager * thread_manager = NULL;
74 FawkesNetworkManager * network_manager = NULL;
75 ConfigNetworkHandler * nethandler_config = NULL;
76 PluginNetworkHandler * nethandler_plugin = NULL;
78 SharedMemoryRegistry * shm_registry;
79 InitOptions * init_options = NULL;
82 FawkesMainThread::Runner * runner = NULL;
85 init(
int argc,
char **argv)
87 return init(InitOptions(argc, argv));
92 init(InitOptions options)
94 init_options =
new InitOptions(options);
98 if ( options.daemonize() ) {
99 fawkes::daemon::init(options.daemon_pid_file(), options.basename());
100 if (options.daemonize_kill()) {
101 fawkes::daemon::kill();
102 }
else if (options.daemonize_status()) {
103 return fawkes::daemon::running() ? 0 : 1;
105 fawkes::daemon::start();
110 const char *user = NULL;
111 const char *group = NULL;
112 if (options.has_username()) {
113 user = options.username();
115 if (options.has_groupname()) {
116 group = options.groupname();
121 if (! (pw = getpwnam(user))) {
122 printf(
"Failed to find user %s, check -u argument.\n", user);
126 r = setreuid(pw->pw_uid, pw->pw_uid);
128 perror(
"Failed to drop privileges (user)");
134 if (! (gr = getgrnam(group))) {
135 printf(
"Failed to find group %s, check -g argument.\n", user);
139 r = setregid(gr->gr_gid, gr->gr_gid);
141 perror(
"Failed to drop privileges (group)");
147 shm_registry =
new SharedMemoryRegistry(
true);
150 if (options.has_loggers()) {
152 logger = LoggerFactory::multilogger_instance(options.loggers());
153 }
catch (Exception &e) {
154 e.append(
"Initializing multi logger failed");
158 logger =
new MultiLogger(
new ConsoleLogger());
162 LibLogger::init(logger);
165 const char *homedir = getenv(
"HOME");
168 if (asprintf(&userdir,
"%s/%s", homedir, USERDIR) != -1) {
169 if (access(userdir, W_OK) != 0) {
170 if (mkdir(userdir, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) == -1) {
171 logger->
log_warn(
"FawkesMainThread",
"Failed to create .fawkes "
172 "directory %s, trying without", userdir);
180 config =
new SQLiteConfiguration(CONFDIR);
182 config->
load(options.host_config(), options.default_config());
188 if (modtype ==
"changed") {
189 logger->
log_warn(
"FawkesMainThread",
"Default config value CHANGED: %s"
190 "(was: %s now: %s)", i->path(),
191 i->get_oldvalue().c_str(), i->get_as_string().c_str());
192 }
else if (modtype ==
"erased") {
193 logger->
log_warn(
"FawkesMainThread",
"Default config value ERASED: %s",
196 logger->
log_debug(
"FawkesMainThread",
"Default config value ADDED: %s "
197 "(value: %s)", i->path(), i->get_as_string().c_str());
201 }
catch (Exception &e) {
202 logger->
log_warn(
"FawkesMainThread",
"Failed to read modified default "
203 "config values, no dump?");
208 unsigned int net_tcp_port = 1910;
209 std::string net_service_name =
"Fawkes on %h";
210 if (options.has_net_tcp_port()) {
211 net_tcp_port = options.net_tcp_port();
214 net_tcp_port = config->
get_uint(
"/fawkes/mainapp/net/tcp_port");
215 }
catch (Exception &e) {}
218 if (options.has_net_service_name()) {
219 net_service_name = options.net_service_name();
222 net_service_name = config->
get_string(
"/fawkes/mainapp/net/service_name");
223 }
catch (Exception &e) {}
226 if (net_tcp_port > 65535) {
227 logger->
log_warn(
"FawkesMainThread",
"Invalid port '%u', using 1910",
233 std::string bb_magic_token =
"";
234 unsigned int bb_size = 2097152;
236 bb_magic_token = config->
get_string(
"/fawkes/mainapp/blackboard_magic_token");
237 logger->
log_info(
"FawkesMainApp",
"BlackBoard magic token defined. "
238 "Using shared memory BlackBoard.");
239 }
catch (Exception &e) {
243 bb_size = config->
get_uint(
"/fawkes/mainapp/blackboard_size");
244 }
catch (Exception &e) {
245 logger->
log_warn(
"FawkesMainApp",
"BlackBoard size not defined. "
246 "Will use %u, saving to default DB", bb_size);
251 if ( options.bb_cleanup()) {
252 LocalBlackBoard::cleanup(bb_magic_token.c_str(),
254 SharedMemoryRegistry::cleanup();
257 LocalBlackBoard *lbb = NULL;
258 if ( bb_magic_token ==
"") {
259 lbb =
new LocalBlackBoard(bb_size);
261 lbb =
new LocalBlackBoard(bb_size, bb_magic_token.c_str());
265 aspect_manager =
new AspectManager();
266 thread_manager =
new ThreadManager(aspect_manager, aspect_manager);
268 plugin_manager =
new PluginManager(thread_manager, config,
269 "/fawkes/meta_plugins/",
270 options.plugin_module_flags(),
271 options.init_plugin_cache());
272 network_manager =
new FawkesNetworkManager(thread_manager,
274 net_service_name.c_str());
275 nethandler_config =
new ConfigNetworkHandler(config,
276 network_manager->hub());
278 nethandler_plugin =
new PluginNetworkHandler(plugin_manager,
279 network_manager->hub());
280 nethandler_plugin->
start();
282 network_logger =
new NetworkLogger(network_manager->hub(),
286 clock = Clock::instance();
288 lbb->start_nethandler(network_manager->hub());
295 options.load_plugin_list(),
296 options.default_plugin());
300 config, logger, clock,
301 network_manager->hub(),
304 network_manager->nnresolver(),
305 network_manager->service_publisher(),
306 network_manager->service_browser(),
318 fawkes::daemon::cleanup();
321 if (nethandler_plugin) {
322 nethandler_plugin->cancel();
323 nethandler_plugin->join();
329 logger->remove_logger(network_logger);
330 delete network_logger;
334 delete argument_parser;
336 delete nethandler_config;
337 delete nethandler_plugin;
338 delete plugin_manager;
339 delete network_manager;
341 delete thread_manager;
342 delete aspect_manager;
346 argument_parser = NULL;
348 nethandler_config = NULL;
349 nethandler_plugin = NULL;
350 plugin_manager = NULL;
351 network_manager = NULL;
353 thread_manager = NULL;
354 aspect_manager = NULL;
358 LibLogger::finalize();
365 Thread::destroy_main();
366 }
catch (Exception &e) {}
378 print_usage(init_options->
basename());
383 runner =
new FawkesMainThread::Runner(main_thread, defsigs);
387 }
catch (Exception &e) {
388 printf(
"Running Fawkes failed\n");
405 kill(getpid(), SIGINT);
409 print_usage(
const char *progname)
411 printf(
"Fawkes Main Application - Usage Instructions\n"
412 "================================================"
413 "===============================\n"
414 "Usage: %s [options]\n"
415 "where [options] is one or more of:\n"
416 " -h These help instructions\n"
417 " -C Cleanup old BB and shared memory segments\n"
418 " -c db-file Mutable configuration file, created if it "
420 "exist, if it does must contain valid SQLite database\n"
421 " -d sql-file Default configuration SQL dump file.\n"
422 " -q[qqq] Quiet mode, -q omits debug, -qq debug and"
424 "-qqq omit debug, info and warn, -qqqq no output\n"
425 " -l level Set log level directly mutually exclusive"
427 "level is one of debug, info, warn, error, or none\n"
428 " -L loggers Define loggers. By default this setting is"
430 "config (console logger if unset). Format is:\n"
431 " logger:args[;logger2:args2[!...]]\n"
432 " Currently supported:\n"
433 " console, file:file.log, network logger always added\n"
434 " -p plugins List of plugins to load on startup in given order\n"
435 " -P port TCP port to listen on for Fawkes network connections.\n"
436 " --net-service-name=name mDNS service name to use.\n"
437 " -u user Drop privileges and run as given user.\n"
438 " -g group Drop privileges and run as given group.\n"
439 #ifdef HAVE_LIBDAEMON
440 " -D[pid file] Run daemonized in the background, pid file "
442 "default is /var/run/fawkes.pid, must be absolute path.\n"
443 " -D[pid file] -k Kill a daemonized Fawkes running in the"
445 " -D[pid file] -s Check status of daemon.\n"