248 lines
5.0 KiB
C++
248 lines
5.0 KiB
C++
/*
|
|
* Copyright (C) 2006-2016 Jacek Sieka, arnetheduck on gmail point com
|
|
*
|
|
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
*/
|
|
|
|
#include <adchpp/adchpp.h>
|
|
#include <adchpp/common.h>
|
|
|
|
#include <adchpp/Util.h>
|
|
#include <adchpp/version.h>
|
|
#include <adchpp/File.h>
|
|
#include <adchpp/Core.h>
|
|
#include <adchpp/shared_ptr.h>
|
|
|
|
#include <signal.h>
|
|
#include <limits.h>
|
|
#include <locale.h>
|
|
|
|
#include "adchppd.h"
|
|
|
|
using namespace std;
|
|
using namespace adchpp;
|
|
|
|
static FILE* pidFile;
|
|
static string pidFileName;
|
|
static bool asdaemon = false;
|
|
static shared_ptr<Core> core;
|
|
|
|
static void installHandler();
|
|
|
|
void breakHandler(int) {
|
|
if(core) {
|
|
core->shutdown();
|
|
}
|
|
|
|
installHandler();
|
|
}
|
|
|
|
static void init() {
|
|
// Ignore SIGPIPE...
|
|
struct sigaction sa = { 0 };
|
|
|
|
sa.sa_handler = SIG_IGN;
|
|
|
|
sigaction(SIGPIPE, &sa, NULL);
|
|
sigaction(SIGHUP, &sa, NULL);
|
|
|
|
sigset_t mask;
|
|
|
|
sigfillset(&mask); /* Mask all allowed signals, the other threads should inherit
|
|
this... */
|
|
sigdelset(&mask, SIGCONT);
|
|
sigdelset(&mask, SIGFPE);
|
|
sigdelset(&mask, SIGILL);
|
|
sigdelset(&mask, SIGSEGV);
|
|
sigdelset(&mask, SIGBUS);
|
|
sigdelset(&mask, SIGINT);
|
|
sigdelset(&mask, SIGTRAP);
|
|
pthread_sigmask(SIG_SETMASK, &mask, NULL);
|
|
|
|
installHandler();
|
|
|
|
if(pidFile != NULL) {
|
|
fprintf(pidFile, "%d", (int)getpid());
|
|
fflush(pidFile);
|
|
}
|
|
|
|
loadXML(*core, File::makeAbsolutePath(core->getConfigPath(), "adchpp.xml"));
|
|
}
|
|
|
|
static void installHandler() {
|
|
struct sigaction sa = { 0 };
|
|
|
|
sa.sa_handler = breakHandler;
|
|
|
|
sigaction(SIGINT, &sa, NULL);
|
|
}
|
|
|
|
static void uninit() {
|
|
if(!asdaemon)
|
|
printf("Shut down");
|
|
|
|
if(pidFile != NULL)
|
|
fclose(pidFile);
|
|
pidFile = NULL;
|
|
|
|
if(!pidFileName.empty())
|
|
unlink(pidFileName.c_str());
|
|
}
|
|
|
|
#include <fcntl.h>
|
|
|
|
static void daemonize() {
|
|
switch(fork()) {
|
|
case -1:
|
|
fprintf(stderr, "First fork failed: %s\n", strerror(errno));
|
|
exit(5);
|
|
case 0: break;
|
|
default: _exit(0);
|
|
}
|
|
|
|
if(setsid() < 0) {
|
|
fprintf(stderr, "setsid failed: %s\n", strerror(errno));
|
|
exit(6);
|
|
}
|
|
|
|
switch(fork()) {
|
|
case -1:
|
|
fprintf(stderr, "Second fork failed: %s\n", strerror(errno));
|
|
exit(7);
|
|
case 0: break;
|
|
default: exit(0);
|
|
}
|
|
|
|
chdir("/");
|
|
close(0);
|
|
close(1);
|
|
close(2);
|
|
open("/dev/null", O_RDWR);
|
|
dup(0); dup(0);
|
|
}
|
|
|
|
#include <sys/wait.h>
|
|
|
|
static void runDaemon(const string& configPath) {
|
|
daemonize();
|
|
|
|
try {
|
|
core = Core::create(configPath);
|
|
|
|
init();
|
|
|
|
core->run();
|
|
|
|
core.reset();
|
|
} catch(const adchpp::Exception& e) {
|
|
fprintf(stderr, "Failed to start: %s\n", e.what());
|
|
}
|
|
|
|
uninit();
|
|
}
|
|
|
|
static void runConsole(const string& configPath) {
|
|
printf("Starting."); fflush(stdout);
|
|
|
|
try {
|
|
core = Core::create(configPath);
|
|
|
|
printf("."); fflush(stdout);
|
|
init();
|
|
|
|
printf(".\n%s running, press ctrl-c to exit...\n", versionString.c_str());
|
|
core->run();
|
|
|
|
core.reset();
|
|
} catch(const Exception& e) {
|
|
fprintf(stderr, "\nFATAL: Can't start ADCH++: %s\n", e.what());
|
|
}
|
|
|
|
uninit();
|
|
}
|
|
|
|
static void printUsage() {
|
|
printf("Usage: adchpp [[-c <configdir>] [-d]] | [-v] | [-h]\n");
|
|
}
|
|
|
|
int main(int argc, char* argv[]) {
|
|
setlocale(LC_ALL, "");
|
|
|
|
char buf[PATH_MAX + 1] = { 0 };
|
|
char* path = buf;
|
|
if (readlink("/proc/self/exe", buf, sizeof (buf)) == -1) {
|
|
path = getenv("_");
|
|
}
|
|
|
|
Util::setApp(path == NULL ? argv[0] : path);
|
|
string configPath = "/etc/adchpp/";
|
|
|
|
for(int i = 1; i < argc; i++) {
|
|
if(strcmp(argv[i], "-d") == 0) {
|
|
asdaemon = true;
|
|
} else if(strcmp(argv[i], "-v") == 0) {
|
|
printf("%s\n", versionString.c_str());
|
|
return 0;
|
|
} else if(strcmp(argv[i], "-c") == 0) {
|
|
if((i + 1) == argc) {
|
|
fprintf(stderr, "-c <directory>\n");
|
|
return 1;
|
|
}
|
|
|
|
i++;
|
|
string cfg = argv[i];
|
|
if(cfg[0] != '/') {
|
|
fprintf(stderr, "Config dir must be an absolute path\n");
|
|
return 2;
|
|
}
|
|
|
|
if(cfg[cfg.length() - 1] != '/') {
|
|
cfg+='/';
|
|
}
|
|
|
|
configPath = cfg;
|
|
} else if(strcmp(argv[i], "-p") == 0) {
|
|
if((i+1) == argc) {
|
|
fprintf(stderr, "-p <pid-file>\n");
|
|
return 1;
|
|
}
|
|
|
|
i++;
|
|
pidFileName = argv[i];
|
|
} else if(strcmp(argv[i], "-h") == 0) {
|
|
printUsage();
|
|
return 0;
|
|
} else {
|
|
fprintf(stderr, "Unknown parameter: %s\n", argv[i]);
|
|
return 4;
|
|
}
|
|
}
|
|
|
|
if(!pidFileName.empty()) {
|
|
pidFileName = File::makeAbsolutePath(configPath, pidFileName);
|
|
pidFile = fopen(pidFileName.c_str(), "w");
|
|
if(pidFile == NULL) {
|
|
fprintf(stderr, "Can't open %s for writing\n", pidFileName.c_str());
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
if(asdaemon) {
|
|
runDaemon(configPath);
|
|
} else {
|
|
runConsole(configPath);
|
|
}
|
|
}
|