2 Copyright 2004-2021 Chris Tallon
4 This file is part of VOMP.
6 VOMP is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 VOMP is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with VOMP. If not, see <https://www.gnu.org/licenses/>.
26 #include <sys/types.h>
40 #ifdef HANDLE_VT_SWITCHING
41 #include <sys/ioctl.h>
50 #ifdef VOMP_PLATTFORM_NMT
52 #include "osddirectfb.h"
58 #ifndef WIN32 // FIXME do we need any if WIN32 stuff in here? windows has own winmain file
59 void threadSignalReceiverFunction();
62 [[ noreturn ]] void shutdown(int code);
68 #ifdef HANDLE_VT_SWITCHING
70 struct vt_mode old_vtmode;
73 static const char* TAG = "Main";
75 // Linux main function and sighandler
77 int main(int argc, char** argv)
81 config = new Config();
82 if (!config->loadFile())
84 printf("Parse error in config.json\n");
89 while ((c = getopt(argc, argv, "clf:ns:")) != -1)
97 config->set("log", "enabled", true);
100 config->set("log", "filename", optarg);
103 config->set("main", "daemonize", false);
106 config->set("server", "address", optarg);
109 printf("Vompclient\n\n");
111 printf(" -l Enable logging\n");
112 printf(" -f F Log to file F instead of stdout\n");
113 printf(" -n Disable daemonize\n");
114 printf(" -s S Connect to server S\n");
117 printf("Option error\n");
122 // Start Log --------------------------------------------------------------------------------------------------
124 loggerNT = new LogNT();
127 printf("Failed to create LogNT object\n");
131 std::string logFileName;
132 config->getString("log", "filename", logFileName);
134 config->getBool("log", "enabled", logEnabled);
136 config->getBool("main", "daemonize", daemonize);
138 if (logEnabled && daemonize && !logFileName.compare("stdout"))
140 printf("Cannot daemonize and log to stdout\n");
144 if (!loggerNT->init(logFileName, logEnabled))
146 printf("Could not initialise log object. Aborting.\n");
150 loggerNT->info(TAG, "Starting up...");
152 // Daemonize --------------------------------------------------------------------------------------------------
154 // Would read config for daemonize here, but actually it's just above in the log section
155 // to detect attempts to log to stdout while daemonized
159 pid_t forkTest = fork();
161 { printf("Cannot fork (1).\n"); exit(1); }
162 if (forkTest != 0) _exit(0); // PID returned, I am the parent
163 // otherwise, I am the child
167 { printf("Cannot fork (2).\n"); exit(1); }
168 if (forkTest != 0) _exit(0); // PID returned, I am the parent
169 // otherwise, I am the child
175 // Set up signal handling ------------------------------------------------------------------------------------------
180 int sigBlockResult = pthread_sigmask(SIG_SETMASK, &set, NULL);
183 //logger->log("Main", Log::EMERG, "Could not block signals: %i", sigBlockResult);
184 loggerNT->crit(TAG, "Could not block signals: {}", sigBlockResult);
188 // Start signal receiver thread
189 std::thread threadSignalReceiver(threadSignalReceiverFunction);
190 threadSignalReceiver.detach();
192 loggerNT->info(TAG, "Signal handlers set up successfully");
194 // VT Switching -----------------------------------------------------------------------------------------------
196 #ifdef HANDLE_VT_SWITCHING
200 (fdtty = open("/dev/tty", O_WRONLY),0) == -1 // FIXME. Why the ,0 ? Surely this kills the log line below
205 loggerNT->warn(TAG, "Could not open /dev/tty. Please change permissions");
210 if (ioctl(fdtty, VT_OPENQRY, &free_vt) == -1 || free_vt == -1)
212 loggerNT->crit(TAG, "Could not retrieve free virtual console, please change permissions");
216 ioctl(fdtty, VT_ACTIVATE, free_vt);
217 ioctl(fdtty, VT_WAITACTIVE, free_vt);
218 ioctl(fdtty, VT_LOCKSWITCH, 1);
223 // Test area ------------------------------------------------------------------------------------------------------
227 // Run control ----------------------------------------------------------------------------------------------------
229 control = new Control();
232 loggerNT->crit(TAG, "Control module failed to create");
236 if (!control->init(crashed))
238 loggerNT->crit(TAG, "Control module failed to initialise");
250 // -------------------------------------------------------------------------------------------------------------------
252 void threadSignalReceiverFunction()
259 if(sigwait(&set, &sig))
261 loggerNT->crit(TAG, "Sigwait returned fail - signal handler exiting");
265 loggerNT->info(TAG, "Signal received: {}", sig);
267 if ((sig == SIGINT) || (sig == SIGTERM)) control->stop();
273 // -------------------------------------------------------------------------------------------------------------------
275 [[ noreturn ]] void shutdown(int code)
277 // FIXME, send a del all to boxstack first, then get rid of it after control?
278 if (control) // shut down control here in case views have posted messages
282 loggerNT->info(TAG, "Control module shut down");
285 #ifdef HANDLE_VT_SWITCHING
286 ioctl(fdtty, VT_UNLOCKSWITCH, 1);
292 loggerNT->info(TAG, "Log module shutting down... bye!\n\n");
293 #warning loggerNT has no shutdown
294 //loggerNT->shutdown();
306 // -------------------------------------------------------------------------------------------------------------------
308 long long getTimeMS()
311 clock_gettime(VOMP_LINUX_CLOCK, &ts);
312 return ts.tv_sec * 1000 + ts.tv_nsec / 1000000LL;
315 int getClockRealTime(struct timespec *tp) // FIXME - del if all goes chrono
317 return clock_gettime(CLOCK_REALTIME, tp);