/* # Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg # # This program is free software distributed under the GPL version 2. # See http://openslx.org/COPYING # # If you have any feedback please consult http://openslx.org/feedback and # send your suggestions, praise, or complaints to feedback@openslx.org # # General information about OpenSLX can be found at http://openslx.org/ # -------------------------------------------------------------------------- # pvsprivinputd.cpp: # - Handle privileged input events - daemon # -------------------------------------------------------------------------- */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "pvsPrivInputSocket.h" #include "pvsPrivInputHandler.h" using namespace std; #ifndef UNIX_PATH_MAX # define UNIX_PATH_MAX 108 /* according to unix(7) */ #endif QByteArray socketPath; int sigintFds[2]; static void unlinkSocket() { if(!socketPath.isNull()) { unlink(socketPath.constData()); } } static void onInterrupt(int) { char buf[] = { '!' }; char msg[] = "SIGINT caught. Quitting.\n"; write(sigintFds[0], buf, 1); write(1, msg, sizeof(msg)-1); } int main(int argc, char** argv) { QCoreApplication app(argc, argv); app.setApplicationName("pvsprivinputd"); app.setOrganizationName("openslx"); bool no_fork = app.arguments().contains("--no-fork", Qt::CaseInsensitive); if(!no_fork) { pid_t pid; pid_t sid; pid = fork(); if(pid < 0) { qCritical("Could not fork: %s", strerror(errno)); exit(EXIT_FAILURE); } if(pid > 0) { exit(EXIT_SUCCESS); } // We are now inside a child process. // Detach from parent: sid = setsid(); if(sid < 0) { qCritical("Could not detach from parent process: %s", strerror(errno)); exit(EXIT_FAILURE); } // Change to some benign directory: if(chdir("/") < 0) { qCritical("Could not change directory: %s", strerror(errno)); exit(EXIT_FAILURE); } } // Okay, we are running as a daemon. Defer reopening standard file descriptors // so we can report errors. // Set the file creation mask to allow all processes to connect to // the socket (access control is handled differently): umask(0); // Ignore SIGPIPE. Connection errors are handled internally. // According to signal(2), the only error is that the signal number // is invalid. This cannot happen. signal(SIGPIPE, SIG_IGN); // set up signal handling: if(socketpair(AF_UNIX, SOCK_STREAM, 0, sigintFds) < 0) { qCritical("Could not set up signal handling. Giving up."); exit(EXIT_FAILURE); } socketPath = pvsPrivInputGetSocketAddress().toLocal8Bit(); QSocketNotifier sigintWatcher(sigintFds[1], QSocketNotifier::Read); QObject::connect(&sigintWatcher, SIGNAL(activated(int)), &app, SLOT(quit())); signal(SIGINT, onInterrupt); // Create our socket: int sock = pvsPrivInputMakeServerSocket(); if(sock < 0) { exit(EXIT_FAILURE); } // Our setup is complete. if(!no_fork) { // Reopen standard file descriptors: freopen("/dev/null", "r", stdin); freopen("/dev/null", "w", stderr); freopen("/dev/null", "w", stdout); } // Install our main object PVSPrivInputHandler handler(sock); atexit(unlinkSocket); // and run the main loop. int ret = app.exec(); return ret; }