Merge branch 'develop' into feature/AddTimeServer_#20

pull/32/head
Geoffrey Merck 4 years ago
commit feb5a95b5c

@ -25,6 +25,10 @@
"description": "Définir la version désassemblage sur Intel", "description": "Définir la version désassemblage sur Intel",
"text": "-gdb-set disassembly-flavor intel", "text": "-gdb-set disassembly-flavor intel",
"ignoreFailures": true "ignoreFailures": true
},
{
"description": "Tell GDB to follow forks child",
"text": "-gdb-set follow-fork-mode child"
} }
] ]
}, },

@ -0,0 +1,206 @@
/*
* Copyright (c) 2022 by Geoffrey Merck F4FXL / KC3FRA
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
* Losely based on https://github.com/jirihnidek/daemon/blob/master/src/daemon.c
*/
#include <unistd.h>
#include <cstdlib>
#include <csignal>
#include <sys/stat.h>
#include <cstdio>
#include <cstring>
#include <sys/types.h>
#include <fcntl.h>
#include <pwd.h>
#include <sys/file.h>
#include "Daemon.h"
#include "Log.h"
int CDaemon::m_pid_fd = -1;
std::string CDaemon::m_pidFileName("");
DAEMONIZE_RESULT CDaemon::daemonise(const std::string& pidFile, const std::string& userName)
{
// get user
struct passwd* user = nullptr;
if(!userName.empty() && getuid() == 0) {
user = getpwnam(userName.c_str());
if(user == nullptr) {
CLog::logFatal("Failed to get %s user", userName.c_str());
return DR_FAILURE;
}
}
// Create PID file if needed
if (!pidFile.empty()) {
auto tempFd = tryGetLock(pidFile);
if (tempFd < 0) {
CLog::logFatal("Failed to acquire lock on pidfile %s : %s", pidFile.c_str(), strerror(errno));
return DR_PIDFILE_FAILED;
}
releaseLock(tempFd, "");
if(user != nullptr) {
int res = chown(pidFile.c_str(), user->pw_uid, user->pw_gid);
if(res != 0) {
CLog::logFatal("Failed to set ownership of pidfile to user %s : %s", userName.c_str(), strerror(errno));
return DR_FAILURE;
}
}
}
// change process ownership
if(user != nullptr) {
if(setgid(user->pw_gid) != 0) {
CLog::logFatal("Failed to set %s GID : %s", userName.c_str(), strerror(errno));
return DR_FAILURE;
}
if(setuid(user->pw_uid) != 0) {
CLog::logFatal("Failed to set %s UID : %s", userName.c_str(), strerror(errno));
return DR_FAILURE;
}
// Double check it worked (AKA Paranoia)
if (setuid(0) != -1){
CLog::logFatal("It's possible to regain root - something is wrong!, exiting");
return DR_FAILURE;
}
}
pid_t pid = 0;
/* Fork off the parent process */
pid = fork();
/* An error occurred */
if (pid < 0) {
CLog::logFatal("Forking failed, exiting");
return DR_FAILURE;
}
/* Success: Let the parent terminate */
if (pid > 0) {
return DR_PARENT;
}
// On success: The child process becomes session leader
if (setsid() < 0) {
CLog::logFatal("Failed to set session id, exiting");
return DR_FAILURE;
}
/* Ignore signal sent from child to parent process */
signal(SIGCHLD, SIG_IGN);
#ifdef DOUBLE_FORK
// Fork off for the second time. Some litterature says it is best to fork 2 times so that the process never can open a terminal.
// However it messes up systemd, event when unit is set as forking
pid = fork();
// An error occurred
if (pid < 0) {
CLog::logFatal("Second forking failed, exiting");
return DR_FAILURE;
}
// Success: Let the parent terminate
if (pid > 0) {
return DR_PARENT;
}
#endif
// Set new file permissions
umask(0);
/* Change the working directory to the root directory */
/* or another appropriated directory */
if(chdir("/") != 0) {
CLog::logFatal("Faild to cd, exiting");
return DR_FAILURE;
}
#ifdef CLOSE_FILE_DESC
// Close all open file descriptors
for (int fd = sysconf(_SC_OPEN_MAX); fd > 0; fd--) {
close(fd);
}
// Reopen stdin (fd = 0), stdout (fd = 1), stderr (fd = 2)
stdin = fopen("/dev/null", "r");
stdout = fopen("/dev/null", "w+");
stderr = fopen("/dev/null", "w+");
#endif
// Try to write PID of daemon to lockfile
if (!pidFile.empty())
{
m_pid_fd = tryGetLock(pidFile);
if (m_pid_fd < 0) {
/* Can't open lockfile */
return DR_PIDFILE_FAILED;
}
if (lockf(m_pid_fd, F_TLOCK, 0) < 0) {
/* Can't lock file */
return DR_PIDFILE_FAILED;
}
m_pidFileName.assign(pidFile);
/* Get current PID */
char str[256];
sprintf(str, "%d\n", getpid());
/* Write PID to lockfile */
write(m_pid_fd, str, strlen(str));
}
return DR_CHILD;
}
void CDaemon::finalise()
{
releaseLock(m_pid_fd, m_pidFileName);
if(!m_pidFileName.empty()) {
unlink(m_pidFileName.c_str());
}
}
int CDaemon::tryGetLock( const std::string& file )
{
mode_t m = umask( 0 );
int fd = open( file.c_str(), O_RDWR|O_CREAT, 0640 );
umask( m );
if( fd >= 0 && flock( fd, LOCK_EX | LOCK_NB ) < 0 ) {
close( fd );
fd = -1;
}
return fd;
}
void CDaemon::releaseLock(int fd, const std::string& file)
{
if( fd < 0 )
return;
remove(file.c_str());
close(fd);
}

@ -0,0 +1,41 @@
/*
* Copyright (c) 2022 by Geoffrey Merck F4FXL / KC3FRA
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <string>
enum DAEMONIZE_RESULT
{
DR_PARENT,
DR_CHILD,
DR_FAILURE,
DR_PIDFILE_FAILED
};
class CDaemon
{
public:
static DAEMONIZE_RESULT daemonise(const std::string& pidFile, const std::string& user);
static void finalise();
private:
static int tryGetLock(const std::string& file);
static void releaseLock(int fd, const std::string& file);
static int m_pid_fd;
static std::string m_pidFileName;
};

@ -30,4 +30,5 @@ CLogTarget(logLevel)
void CLogConsoleTarget::printLogInt(const std::string& msg) void CLogConsoleTarget::printLogInt(const std::string& msg)
{ {
std::cout << msg; std::cout << msg;
std::cout.flush();
} }

@ -226,13 +226,13 @@ bool CAPRSHandler::isConnected() const
void CAPRSHandler::close() void CAPRSHandler::close()
{ {
m_thread->stop();
if(m_idFrameProvider != nullptr) { if(m_idFrameProvider != nullptr) {
m_idFrameProvider->close(); m_idFrameProvider->close();
delete m_idFrameProvider; delete m_idFrameProvider;
m_idFrameProvider = nullptr; m_idFrameProvider = nullptr;
} }
m_thread->stop();
} }
void CAPRSHandler::addReadAPRSCallback(IReadAPRSFrameCallback* cb) void CAPRSHandler::addReadAPRSCallback(IReadAPRSFrameCallback* cb)

@ -438,11 +438,6 @@ void CRepeaterHandler::finalise()
m_repeaters[i] = NULL; m_repeaters[i] = NULL;
} }
if (m_aprsWriter != NULL) {
m_aprsWriter->close();
delete m_aprsWriter;
}
delete[] m_repeaters; delete[] m_repeaters;
} }

@ -25,6 +25,8 @@
#include <vector> #include <vector>
#include <signal.h> #include <signal.h>
#include <exception> #include <exception>
#include <cassert>
#include <unistd.h>
#ifdef DEBUG_DSTARGW #ifdef DEBUG_DSTARGW
#include <boost/stacktrace.hpp> #include <boost/stacktrace.hpp>
#endif #endif
@ -45,8 +47,12 @@
#include "LogConsoleTarget.h" #include "LogConsoleTarget.h"
#include "APRSGPSDIdFrameProvider.h" #include "APRSGPSDIdFrameProvider.h"
#include "APRSFixedIdFrameProvider.h" #include "APRSFixedIdFrameProvider.h"
#include "Daemon.h"
CDStarGatewayApp * CDStarGatewayApp::g_app = nullptr; CDStarGatewayApp * CDStarGatewayApp::g_app = nullptr;
const std::string BANNER_1 = CStringUtils::string_format("%s Copyright (C) %s\n", FULL_PRODUCT_NAME.c_str(), VENDOR_NAME.c_str());
const std::string BANNER_2 = "DStarGateway comes with ABSOLUTELY NO WARRANTY; see the LICENSE for details.\n";
const std::string BANNER_3 = "This is free software, and you are welcome to distribute it under certain conditions that are discussed in the LICENSE file.\n\n";
#ifdef UNIT_TESTS #ifdef UNIT_TESTS
int fakemain(int argc, char *argv[]) int fakemain(int argc, char *argv[])
@ -70,16 +76,56 @@ int main(int argc, char *argv[])
return 1; return 1;
} }
std::cout << std::endl << BANNER_1 << BANNER_2 << BANNER_3;
if ('-' == argv[1][0]) { if ('-' == argv[1][0]) {
printf("\n%s Copyright (C) %s\n", FULL_PRODUCT_NAME.c_str(), VENDOR_NAME.c_str());
printf("DStarGateway comes with ABSOLUTELY NO WARRANTY; see the LICENSE for details.\n");
printf("This is free software, and you are welcome to distribute it\nunder certain conditions that are discussed in the LICENSE file.\n\n");
return 0; return 0;
} }
std::string cfgFile(argv[1]); CDStarGatewayConfig * config = new CDStarGatewayConfig(std::string((argv[1])));
if(!config->load()) {
CLog::logFatal("Invalid configuration, aborting");
return false;
}
TDaemon daemon;
config->getDaemon(daemon);
if (daemon.daemon) {
CLog::logInfo("Configured as a daemon, detaching ...");
auto res = CDaemon::daemonise(daemon.pidFile, daemon.user);
switch (res)
{
case DR_PARENT:
return 0;
case DR_CHILD:
break;
case DR_PIDFILE_FAILED:
case DR_FAILURE:
default:
CLog::logFatal("Failed to run as daemon");
delete config;
CLog::finalise();
return 1;
}
}
// Setup Log
TLog logConf;
config->getLog(logConf);
CLog::finalise();
if(logConf.m_displayLevel != LOG_NONE && !daemon.daemon) CLog::addTarget(new CLogConsoleTarget(logConf.m_displayLevel));
if(logConf.m_fileLevel != LOG_NONE) CLog::addTarget(new CLogFileTarget(logConf.m_fileLevel, logConf.logDir, logConf.m_fileRotate));
//write banner in log file if we are dameon
if(daemon.daemon) {
CLog::logInfo(BANNER_1);
CLog::logInfo(BANNER_2);
CLog::logInfo(BANNER_3);
}
CDStarGatewayApp gateway(cfgFile); CDStarGatewayApp gateway(config);
if (!gateway.init()) { if (!gateway.init()) {
return 1; return 1;
@ -87,11 +133,18 @@ int main(int argc, char *argv[])
gateway.run(); gateway.run();
if(daemon.daemon) {
CDaemon::finalise();
}
return 0; return 0;
} }
CDStarGatewayApp::CDStarGatewayApp(const std::string &configFile) : m_configFile(configFile), m_thread(NULL) CDStarGatewayApp::CDStarGatewayApp(CDStarGatewayConfig * config) :
m_config(config),
m_thread(NULL)
{ {
assert(config != nullptr);
g_app = this; g_app = this;
} }
@ -102,7 +155,6 @@ CDStarGatewayApp::~CDStarGatewayApp()
bool CDStarGatewayApp::init() bool CDStarGatewayApp::init()
{ {
return createThread(); return createThread();
//2021-12-31 F4FXL This is ugly, if we failed to create the thread we do not clean up ... :(
} }
void CDStarGatewayApp::run() void CDStarGatewayApp::run()
@ -115,30 +167,18 @@ void CDStarGatewayApp::run()
bool CDStarGatewayApp::createThread() bool CDStarGatewayApp::createThread()
{ {
printf("\n%s Copyright (C) %s\n", FULL_PRODUCT_NAME.c_str(), VENDOR_NAME.c_str()); // Log
printf("DStarGateway comes with ABSOLUTELY NO WARRANTY; see the LICENSE for details.\n");
printf("This is free software, and you are welcome to distribute it\nunder certain conditions that are discussed in the LICENSE file.\n\n");
CDStarGatewayConfig config(m_configFile);
if(!config.load()) {
CLog::logFatal("Invalid configuration, aborting");
return false;
}
// Setup Log
TLog log; TLog log;
config.getLog(log); m_config->getLog(log);
CLog::finalise();
if(log.m_displayLevel != LOG_NONE) CLog::addTarget(new CLogConsoleTarget(log.m_displayLevel));
if(log.m_fileLevel != LOG_NONE) CLog::addTarget(new CLogFileTarget(log.m_fileLevel, log.logDir, log.m_fileRotate));
// Paths
Tpaths paths; Tpaths paths;
config.getPaths(paths); m_config->getPaths(paths);
m_thread = new CDStarGatewayThread(log.logDir, paths.dataDir, ""); m_thread = new CDStarGatewayThread(log.logDir, paths.dataDir, "");
// Setup the gateway // Setup the gateway
TGateway gatewayConfig; TGateway gatewayConfig;
config.getGateway(gatewayConfig); m_config->getGateway(gatewayConfig);
m_thread->setGateway(gatewayConfig.type, gatewayConfig.callsign, gatewayConfig.address); m_thread->setGateway(gatewayConfig.type, gatewayConfig.callsign, gatewayConfig.address);
m_thread->setLanguage(gatewayConfig.language); m_thread->setLanguage(gatewayConfig.language);
m_thread->setLocation(gatewayConfig.latitude, gatewayConfig.longitude); m_thread->setLocation(gatewayConfig.latitude, gatewayConfig.longitude);
@ -146,12 +186,12 @@ bool CDStarGatewayApp::createThread()
#ifdef USE_GPSD #ifdef USE_GPSD
// Setup GPSD // Setup GPSD
TGPSD gpsdConfig; TGPSD gpsdConfig;
config.getGPSD(gpsdConfig); m_config->getGPSD(gpsdConfig);
#endif #endif
// Setup APRS // Setup APRS
TAPRS aprsConfig; TAPRS aprsConfig;
config.getAPRS(aprsConfig); m_config->getAPRS(aprsConfig);
CAPRSHandler * aprsWriter = NULL; CAPRSHandler * aprsWriter = NULL;
if(aprsConfig.enabled && !aprsConfig.password.empty()) { if(aprsConfig.enabled && !aprsConfig.password.empty()) {
aprsWriter = new CAPRSHandler(aprsConfig.hostname, aprsConfig.port, gatewayConfig.callsign, aprsConfig.password, gatewayConfig.address); aprsWriter = new CAPRSHandler(aprsConfig.hostname, aprsConfig.port, gatewayConfig.callsign, aprsConfig.password, gatewayConfig.address);
@ -176,9 +216,9 @@ bool CDStarGatewayApp::createThread()
bool ddEnabled = false; bool ddEnabled = false;
bool atLeastOneRepeater = false; bool atLeastOneRepeater = false;
CRepeaterProtocolHandlerFactory repeaterProtocolFactory; CRepeaterProtocolHandlerFactory repeaterProtocolFactory;
for(unsigned int i = 0U; i < config.getRepeaterCount(); i++) { for(unsigned int i = 0U; i < m_config->getRepeaterCount(); i++) {
TRepeater rptrConfig; TRepeater rptrConfig;
config.getRepeater(i, rptrConfig); m_config->getRepeater(i, rptrConfig);
auto repeaterProtocolHandler = repeaterProtocolFactory.getRepeaterProtocolHandler(rptrConfig.hwType, gatewayConfig, rptrConfig.address, rptrConfig.port); auto repeaterProtocolHandler = repeaterProtocolFactory.getRepeaterProtocolHandler(rptrConfig.hwType, gatewayConfig, rptrConfig.address, rptrConfig.port);
if(repeaterProtocolHandler == nullptr) if(repeaterProtocolHandler == nullptr)
continue; continue;
@ -221,9 +261,9 @@ bool CDStarGatewayApp::createThread()
// Setup ircddb // Setup ircddb
auto ircddbVersionInfo = "linux_" + PRODUCT_NAME + "-" + VERSION; auto ircddbVersionInfo = "linux_" + PRODUCT_NAME + "-" + VERSION;
std::vector<CIRCDDB *> clients; std::vector<CIRCDDB *> clients;
for(unsigned int i=0; i < config.getIrcDDBCount(); i++) { for(unsigned int i=0; i < m_config->getIrcDDBCount(); i++) {
TircDDB ircDDBConfig; TircDDB ircDDBConfig;
config.getIrcDDB(i, ircDDBConfig); m_config->getIrcDDB(i, ircDDBConfig);
CLog::logInfo("ircDDB Network %d set to %s user: %s, Quadnet %d", i + 1,ircDDBConfig.hostname.c_str(), ircDDBConfig.username.c_str(), ircDDBConfig.isQuadNet); CLog::logInfo("ircDDB Network %d set to %s user: %s, Quadnet %d", i + 1,ircDDBConfig.hostname.c_str(), ircDDBConfig.username.c_str(), ircDDBConfig.isQuadNet);
CIRCDDB * ircDDB = new CIRCDDBClient(ircDDBConfig.hostname, 9007U, ircDDBConfig.username, ircDDBConfig.password, ircddbVersionInfo, gatewayConfig.address, ircDDBConfig.isQuadNet); CIRCDDB * ircDDB = new CIRCDDBClient(ircDDBConfig.hostname, 9007U, ircDDBConfig.username, ircDDBConfig.password, ircddbVersionInfo, gatewayConfig.address, ircDDBConfig.isQuadNet);
clients.push_back(ircDDB); clients.push_back(ircDDB);
@ -240,31 +280,31 @@ bool CDStarGatewayApp::createThread()
// Setup Dextra // Setup Dextra
TDextra dextraConfig; TDextra dextraConfig;
config.getDExtra(dextraConfig); m_config->getDExtra(dextraConfig);
CLog::logInfo("DExtra enabled: %d, max. dongles: %u", int(dextraConfig.enabled), dextraConfig.maxDongles); CLog::logInfo("DExtra enabled: %d, max. dongles: %u", int(dextraConfig.enabled), dextraConfig.maxDongles);
m_thread->setDExtra(dextraConfig.enabled, dextraConfig.maxDongles); m_thread->setDExtra(dextraConfig.enabled, dextraConfig.maxDongles);
// Setup DCS // Setup DCS
TDCS dcsConfig; TDCS dcsConfig;
config.getDCS(dcsConfig); m_config->getDCS(dcsConfig);
CLog::logInfo("DCS enabled: %d", int(dcsConfig.enabled)); CLog::logInfo("DCS enabled: %d", int(dcsConfig.enabled));
m_thread->setDCS(dcsConfig.enabled); m_thread->setDCS(dcsConfig.enabled);
// Setup DPlus // Setup DPlus
TDplus dplusConfig; TDplus dplusConfig;
config.getDPlus(dplusConfig); m_config->getDPlus(dplusConfig);
CLog::logInfo("D-Plus enabled: %d, max. dongles: %u, login: %s", int(dplusConfig.enabled), dplusConfig.maxDongles, dplusConfig.login.c_str()); CLog::logInfo("D-Plus enabled: %d, max. dongles: %u, login: %s", int(dplusConfig.enabled), dplusConfig.maxDongles, dplusConfig.login.c_str());
m_thread->setDPlus(dplusConfig.enabled, dplusConfig.maxDongles, dplusConfig.login); m_thread->setDPlus(dplusConfig.enabled, dplusConfig.maxDongles, dplusConfig.login);
// Setup XLX // Setup XLX
TXLX xlxConfig; TXLX xlxConfig;
config.getXLX(xlxConfig); m_config->getXLX(xlxConfig);
CLog::logInfo("XLX enabled: %d, Hosts file url: %s", int(xlxConfig.enabled), xlxConfig.url.c_str()); CLog::logInfo("XLX enabled: %d, Hosts file url: %s", int(xlxConfig.enabled), xlxConfig.url.c_str());
m_thread->setXLX(xlxConfig.enabled, xlxConfig.enabled ? CXLXHostsFileDownloader::download(xlxConfig.url) : ""); m_thread->setXLX(xlxConfig.enabled, xlxConfig.enabled ? CXLXHostsFileDownloader::download(xlxConfig.url) : "");
// Setup Remote // Setup Remote
TRemote remoteConfig; TRemote remoteConfig;
config.getRemote(remoteConfig); m_config->getRemote(remoteConfig);
CLog::logInfo("Remote enabled: %d, port %u", int(remoteConfig.enabled), remoteConfig.port); CLog::logInfo("Remote enabled: %d, port %u", int(remoteConfig.enabled), remoteConfig.port);
m_thread->setRemote(remoteConfig.enabled, remoteConfig.password, remoteConfig.port); m_thread->setRemote(remoteConfig.enabled, remoteConfig.password, remoteConfig.port);
@ -292,12 +332,14 @@ void CDStarGatewayApp::sigHandler(int sig)
void CDStarGatewayApp::sigHandlerFatal(int sig) void CDStarGatewayApp::sigHandlerFatal(int sig)
{ {
CLog::logFatal("Caught signal : %s", strsignal(sig)); CLog::logFatal("Caught signal : %s", strsignal(sig));
fprintf(stderr, "Caught signal : %s\n", strsignal(sig));
#ifdef DEBUG_DSTARGW #ifdef DEBUG_DSTARGW
std::stringstream stackTrace; std::stringstream stackTrace;
stackTrace << boost::stacktrace::stacktrace(); stackTrace << boost::stacktrace::stacktrace();
CLog::logFatal("Stack Trace : \n%s", stackTrace.str().c_str()); CLog::logFatal("Stack Trace : \n%s", stackTrace.str().c_str());
fprintf(stderr, "Stack Trace : \n%s\n", stackTrace.str().c_str());
#endif #endif
exit(1); exit(3);
} }
void CDStarGatewayApp::terminateHandler() void CDStarGatewayApp::terminateHandler()
@ -316,13 +358,15 @@ void CDStarGatewayApp::terminateHandler()
} }
else { else {
CLog::logFatal("Unhandled unknown exception occured"); CLog::logFatal("Unhandled unknown exception occured");
fprintf(stderr, "Unknown ex\n");
} }
} catch(const std::exception& e) { } catch(const std::exception& e) {
CLog::logFatal("Unhandled exception occured %s", e.what()); CLog::logFatal("Unhandled exception occured %s", e.what());
fprintf(stderr, "Unhandled ex %s\n", e.what());
} }
#ifdef DEBUG_DSTARGW #ifdef DEBUG_DSTARGW
CLog::logFatal("Stack Trace : \n%s", stackTrace.str().c_str()); CLog::logFatal("Stack Trace : \n%s", stackTrace.str().c_str());
#endif #endif
exit(1); exit(2);
} }

@ -20,18 +20,18 @@
#pragma once #pragma once
#include "DStarGatewayThread.h" #include "DStarGatewayThread.h"
#include "DStarGatewayConfig.h"
class CDStarGatewayApp class CDStarGatewayApp
{ {
private: private:
std::string m_configFile; CDStarGatewayConfig * m_config;
CDStarGatewayThread * m_thread; CDStarGatewayThread * m_thread;
bool createThread(); bool createThread();
static CDStarGatewayApp * g_app; static CDStarGatewayApp * g_app;
public: public:
CDStarGatewayApp(const std::string &configFile); CDStarGatewayApp(CDStarGatewayConfig * config);
~CDStarGatewayApp(); ~CDStarGatewayApp();
bool init(); bool init();

@ -55,6 +55,7 @@ bool CDStarGatewayConfig::load()
#ifdef USE_GPSD #ifdef USE_GPSD
ret = loadGPSD(cfg) && ret; ret = loadGPSD(cfg) && ret;
#endif #endif
ret = loadDaemon(cfg) && ret;
} }
if(ret) { if(ret) {
@ -69,6 +70,14 @@ bool CDStarGatewayConfig::load()
return ret; return ret;
} }
bool CDStarGatewayConfig::loadDaemon(const CConfig & cfg)
{
bool ret = cfg.getValue("daemon", "daemon", m_daemon.daemon, false);
ret = cfg.getValue("daemon", "pidfile", m_daemon.pidFile, 0, 1024, "") && ret;
ret = cfg.getValue("daemon", "user", m_daemon.user, 0, 1024, "") && ret;
return ret;
}
bool CDStarGatewayConfig::loadXLX(const CConfig & cfg) bool CDStarGatewayConfig::loadXLX(const CConfig & cfg)
{ {
bool ret = cfg.getValue("xlx", "enabled", m_xlx.enabled, true); bool ret = cfg.getValue("xlx", "enabled", m_xlx.enabled, true);
@ -438,3 +447,8 @@ void CDStarGatewayConfig::getGPSD(TGPSD & gpsd) const
gpsd = m_gpsd; gpsd = m_gpsd;
} }
#endif #endif
void CDStarGatewayConfig::getDaemon(TDaemon & gen) const
{
gen = m_daemon;
}

@ -25,6 +25,12 @@
#include "Config.h" #include "Config.h"
#include "LogSeverity.h" #include "LogSeverity.h"
typedef struct {
bool daemon;
std::string pidFile;
std::string user;
} TDaemon;
typedef struct { typedef struct {
GATEWAY_TYPE type; GATEWAY_TYPE type;
std::string callsign; std::string callsign;
@ -150,6 +156,7 @@ public:
#ifdef USE_GPSD #ifdef USE_GPSD
void getGPSD(TGPSD & gpsd) const; void getGPSD(TGPSD & gpsd) const;
#endif #endif
void getDaemon(TDaemon & gen) const;
private: private:
bool open(CConfig & cfg); bool open(CConfig & cfg);
@ -167,6 +174,7 @@ private:
#ifdef USE_GPSD #ifdef USE_GPSD
bool loadGPSD(const CConfig & cfg); bool loadGPSD(const CConfig & cfg);
#endif #endif
bool loadDaemon(const CConfig & cfg);
std::string m_fileName; std::string m_fileName;
TGateway m_gateway; TGateway m_gateway;
@ -181,6 +189,8 @@ private:
#ifdef USE_GPSD #ifdef USE_GPSD
TGPSD m_gpsd; TGPSD m_gpsd;
#endif #endif
TDaemon m_daemon;
std::vector<TRepeater *> m_repeaters; std::vector<TRepeater *> m_repeaters;
std::vector<TircDDB *> m_ircDDB; std::vector<TircDDB *> m_ircDDB;
}; };

@ -21,7 +21,7 @@
#include <string> #include <string>
const std::string APPLICATION_NAME("ircDDB Gateway"); const std::string APPLICATION_NAME("dstargateway");
const std::string CONFIG_FILE_NAME("dstargateway"); const std::string CONFIG_FILE_NAME("dstargateway");

@ -131,19 +131,7 @@ m_restrictList(NULL)
CDStarGatewayThread::~CDStarGatewayThread() CDStarGatewayThread::~CDStarGatewayThread()
{ {
CHeaderData::finalise();
CG2Handler::finalise();
CDExtraHandler::finalise();
CDPlusHandler::finalise();
CDCSHandler::finalise();
CRepeaterHandler::finalise();
#ifdef USE_STARNET
CStarNetHandler::finalise();
#endif
#ifdef USE_CCS
CCCSHandler::finalise();
#endif
CAudioUnit::finalise();
} }
void* CDStarGatewayThread::Entry() void* CDStarGatewayThread::Entry()
@ -491,7 +479,19 @@ void* CDStarGatewayThread::Entry()
delete headerLogger; delete headerLogger;
} }
CHeaderData::finalise();
CG2Handler::finalise();
CDExtraHandler::finalise();
CDPlusHandler::finalise(); CDPlusHandler::finalise();
CDCSHandler::finalise();
CRepeaterHandler::finalise();
#ifdef USE_STARNET
CStarNetHandler::finalise();
#endif
#ifdef USE_CCS
CCCSHandler::finalise();
#endif
CAudioUnit::finalise();
return NULL; return NULL;
} }

@ -2,7 +2,6 @@
# The order of the sections or key/values pairs inside the sections does not matter nor does casing. # The order of the sections or key/values pairs inside the sections does not matter nor does casing.
# Boolean values can be set using true, false, 1 or 0 # Boolean values can be set using true, false, 1 or 0
# Floating point values must use . (point) as decimal separator # Floating point values must use . (point) as decimal separator
[Gateway] [Gateway]
type= # repeater, hotspot, dongle. Defaults to repeater type= # repeater, hotspot, dongle. Defaults to repeater
callsign= callsign=
@ -22,7 +21,7 @@ language= # valid values: english_uk, deutsch, dansk, francais, ita
[ircddb_1] [ircddb_1]
enabled=true enabled=true
hostname=ircv4.openquad.net hostname=ircv4.openquad.net
username= # The ircDDB username default to the value defined for gateway callsign. username= # The ircDDB username defaults to the value defined for gateway callsign.
password= password=
[ircddb_2] [ircddb_2]
@ -178,3 +177,10 @@ enabled=false
port=4242 port=4242
password=CHANGE_ME # If password is left blank, remote will be disabled regardless of the enabled field password=CHANGE_ME # If password is left blank, remote will be disabled regardless of the enabled field
# Provided install routines install the program as a systemd unit. SystemD does not recommand "old-school" forking daemons nor does systemd
# require a pid file. Moreover system handles the user under which the program is started. This is provided as convenience for people who might
# run the program using sysv or any other old school init system.
[Daemon]
daemon=false
pidfile=/var/run/dstargateway/dstargateway.pid # pid file is in our case useless when running as a daemon using systemd as systemd takes care of the service not being started twice
user=dstar # user account the daemon will run under, ideally a user with low privileges. Switching to this user will only happen when the program is started as root

@ -14,5 +14,3 @@ StartLimitBurst=0
[Install] [Install]
WantedBy=multi-user.target WantedBy=multi-user.target

Loading…
Cancel
Save

Powered by TurnKey Linux.