#include #include #include #include #include #ifndef __APPLE__ /* prctl is Linux only */ #include #endif #include #include #include #include #include #include #include #include #include #include #include #include "HyperionConfig.h" #include #include #include #include #include <../../include/db/AuthTable.h> #ifdef ENABLE_X11 #include #endif #include "hyperiond.h" #include "systray.h" using namespace commandline; #define PERM0664 QFileDevice::ReadOwner | QFileDevice::ReadGroup | QFileDevice::ReadOther | QFileDevice::WriteOwner | QFileDevice::WriteGroup unsigned int getProcessIdsByProcessName(const char* processName, QStringList &listOfPids) { // Clear content of returned list of PIDS listOfPids.clear(); #if defined(WIN32) // Get the list of process identifiers. DWORD aProcesses[1024], cbNeeded, cProcesses; unsigned int i; if (!EnumProcesses(aProcesses, sizeof(aProcesses), &cbNeeded)) return 0; // Calculate how many process identifiers were returned. cProcesses = cbNeeded / sizeof(DWORD); // Search for a matching name for each process for (i = 0; i < cProcesses; i++) { if (aProcesses[i] != 0) { char szProcessName[MAX_PATH] = {0}; DWORD processID = aProcesses[i]; // Get a handle to the process. HANDLE hProcess = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processID); // Get the process name if (NULL != hProcess) { HMODULE hMod; DWORD cbNeeded; if (EnumProcessModules(hProcess, &hMod, sizeof(hMod), &cbNeeded)) GetModuleBaseNameA(hProcess, hMod, szProcessName, sizeof(szProcessName)/sizeof(char)); // Release the handle to the process. CloseHandle(hProcess); if (*szProcessName != 0 && strcmp(processName, szProcessName) == 0) listOfPids.append(QString::number(processID)); } } } return listOfPids.count(); #else // Run pgrep, which looks through the currently running processses and lists the process IDs // which match the selection criteria to stdout. QProcess process; process.start("pgrep", QStringList() << processName); process.waitForReadyRead(); QByteArray bytes = process.readAllStandardOutput(); process.terminate(); process.waitForFinished(); process.kill(); // Output is something like "2472\n2323" for multiple instances if (bytes.isEmpty()) return 0; listOfPids = QString(bytes).split("\n", QString::SkipEmptyParts); return listOfPids.count(); #endif } void signal_handler(const int signum) { // Hyperion Managment instance HyperionIManager* _hyperion = HyperionIManager::getInstance(); if(signum == SIGCHLD) { // only quit when a registered child process is gone // currently this feature is not active ... return; } else if (signum == SIGUSR1) { if (_hyperion != nullptr) { _hyperion->toggleStateAllInstances(false); } return; } else if (signum == SIGUSR2) { if (_hyperion != nullptr) { _hyperion->toggleStateAllInstances(true); } return; } QCoreApplication::quit(); // reset signal handler to default (in case this handler is not capable of stopping) signal(signum, SIG_DFL); } QCoreApplication* createApplication(int &argc, char *argv[]) { bool isGuiApp = false; bool forceNoGui = false; // command line for (int i = 1; i < argc; ++i) { if (qstrcmp(argv[i], "--desktop") == 0) { isGuiApp = true; } else if (qstrcmp(argv[i], "--service") == 0) { isGuiApp = false; forceNoGui = true; } } // on osx/windows gui always available #if defined(__APPLE__) || defined(__WIN32__) isGuiApp = true && ! forceNoGui; #else if (!forceNoGui) { // if x11, then test if xserver is available #ifdef ENABLE_X11 Display* dpy = XOpenDisplay(NULL); if (dpy != NULL) { XCloseDisplay(dpy); isGuiApp = true; } #endif } #endif if (isGuiApp) { QApplication* app = new QApplication(argc, argv); // add optional library path app->addLibraryPath(QApplication::applicationDirPath() + "/../lib"); app->setApplicationDisplayName("Hyperion"); app->setWindowIcon(QIcon(":/hyperion-icon-32px.png")); return app; } QCoreApplication* app = new QCoreApplication(argc, argv); app->setApplicationName("Hyperion"); app->setApplicationVersion(HYPERION_VERSION); // add optional library path app->addLibraryPath(QApplication::applicationDirPath() + "/../lib"); return app; } int main(int argc, char** argv) { setenv("AVAHI_COMPAT_NOWARN", "1", 1); // initialize main logger and set global log level Logger* log = Logger::getInstance("MAIN"); Logger::setLogLevel(Logger::WARNING); // check if we are running already an instance // TODO Do not use pgrep on linux, instead iter /proc // TODO Allow one session per user // http://www.qtcentre.org/threads/44489-Get-Process-ID-for-a-running-application QStringList listOfPids; if(getProcessIdsByProcessName("hyperiond", listOfPids) > 1) { Error(log, "The Hyperion Daemon is already running, abort start"); return 0; } // Initialising QCoreApplication QScopedPointer app(createApplication(argc, argv)); bool isGuiApp = (qobject_cast(app.data()) != 0 && QSystemTrayIcon::isSystemTrayAvailable()); signal(SIGINT, signal_handler); signal(SIGTERM, signal_handler); signal(SIGABRT, signal_handler); signal(SIGCHLD, signal_handler); signal(SIGPIPE, signal_handler); signal(SIGUSR1, signal_handler); signal(SIGUSR2, signal_handler); // force the locale setlocale(LC_ALL, "C"); QLocale::setDefault(QLocale::c()); Parser parser("Hyperion Daemon"); parser.addHelpOption(); BooleanOption & versionOption = parser.add (0x0, "version", "Show version information"); Option & userDataOption = parser.add