diff --git a/client/Makefile b/client/Makefile index 4ab75393..29d7d00a 100644 --- a/client/Makefile +++ b/client/Makefile @@ -3,7 +3,7 @@ CC = /usr/bin/g++ CFLAGS = -std=gnu++0x -Wall -Wno-unused-function -O3 -D_REENTRANT -DVERSION=\"$(VERSION)\" -I.. LDFLAGS = -lrt -lpthread -lportaudio -lboost_system -lboost_program_options -OBJ = snapClient.o stream.o ../common/chunk.o +OBJ = snapClient.o stream.o ../common/chunk.o ../common/log.o BIN = snapclient all: client diff --git a/client/snapClient.cpp b/client/snapClient.cpp index bac801d7..8beafd64 100644 --- a/client/snapClient.cpp +++ b/client/snapClient.cpp @@ -20,6 +20,7 @@ #include "common/chunk.h" #include "common/utils.h" +#include "common/log.h" #include "stream.h" using boost::asio::ip::tcp; @@ -183,13 +184,15 @@ int main (int argc, char *argv[]) string ip; int bufferMs; size_t port; + bool runAsDaemon; po::options_description desc("Allowed options"); desc.add_options() ("help,h", "produce help message") ("port,p", po::value(&port)->default_value(98765), "port where the server listens on") ("ip,i", po::value(&ip)->default_value("192.168.0.2"), "server IP") - ("device,d", po::value(&deviceIdx)->default_value(-1), "index of the soundcard") + ("soundcard,s", po::value(&deviceIdx)->default_value(-1), "index of the soundcard") ("buffer,b", po::value(&bufferMs)->default_value(300), "buffer size [ms]") + ("daemon,d", po::bool_switch(&runAsDaemon)->default_value(false), "daemonize") ; po::variables_map vm; @@ -202,6 +205,13 @@ int main (int argc, char *argv[]) return 1; } + if (runAsDaemon) + { + daemonize(); + std::clog.rdbuf(new Log("snapserver", LOG_DAEMON)); + std::clog << kLogNotice << "daemon started" << std::endl; + } + stream = new Stream(); stream->setBufferLen(bufferMs); PaError paError; diff --git a/common/log.cpp b/common/log.cpp new file mode 100644 index 00000000..9682ac89 --- /dev/null +++ b/common/log.cpp @@ -0,0 +1,35 @@ +#include "log.h" + +Log::Log(std::string ident, int facility) { + facility_ = facility; + priority_ = LOG_DEBUG; + strncpy(ident_, ident.c_str(), sizeof(ident_)); + ident_[sizeof(ident_)-1] = '\0'; + + openlog(ident_, LOG_PID, facility_); +} + +int Log::sync() { + if (buffer_.length()) { + syslog(priority_, buffer_.c_str()); + buffer_.erase(); + priority_ = LOG_DEBUG; // default to debug for each message + } + return 0; +} + +int Log::overflow(int c) { + if (c != EOF) { + buffer_ += static_cast(c); + } else { + sync(); + } + return c; +} + +std::ostream& operator<< (std::ostream& os, const LogPriority& log_priority) { + static_cast(os.rdbuf())->priority_ = (int)log_priority; + return os; +} + + diff --git a/common/log.h b/common/log.h new file mode 100644 index 00000000..1e93f6a9 --- /dev/null +++ b/common/log.h @@ -0,0 +1,41 @@ +#ifndef LOG_H +#define LOG_H + +#include +#include +#include + + +enum LogPriority { + kLogEmerg = LOG_EMERG, // system is unusable + kLogAlert = LOG_ALERT, // action must be taken immediately + kLogCrit = LOG_CRIT, // critical conditions + kLogErr = LOG_ERR, // error conditions + kLogWarning = LOG_WARNING, // warning conditions + kLogNotice = LOG_NOTICE, // normal, but significant, condition + kLogInfo = LOG_INFO, // informational message + kLogDebug = LOG_DEBUG // debug-level message +}; + +std::ostream& operator<< (std::ostream& os, const LogPriority& log_priority); + +class Log : public std::basic_streambuf > { +public: + explicit Log(std::string ident, int facility); + +protected: + int sync(); + int overflow(int c); + +private: + friend std::ostream& operator<< (std::ostream& os, const LogPriority& log_priority); + std::string buffer_; + int facility_; + int priority_; + char ident_[50]; +}; + + +#endif + + diff --git a/common/log.o b/common/log.o new file mode 100644 index 00000000..df8a3e89 Binary files /dev/null and b/common/log.o differ diff --git a/common/utils.h b/common/utils.h index a45e1966..de5a3f40 100644 --- a/common/utils.h +++ b/common/utils.h @@ -47,6 +47,48 @@ std::vector split(const std::string& str) } +static void daemonize() +{ + /* Our process ID and Session ID */ + pid_t pid, sid; + + /* Fork off the parent process */ + pid = fork(); + if (pid < 0) + exit(EXIT_FAILURE); + + /* If we got a good PID, then + we can exit the parent process. */ + if (pid > 0) + exit(EXIT_SUCCESS); + + /* Change the file mode mask */ + umask(0); + + /* Open any logs here */ + + /* Create a new SID for the child process */ + sid = setsid(); + if (sid < 0) + { + /* Log the failure */ + exit(EXIT_FAILURE); + } + + /* Change the current working directory */ + if ((chdir("/")) < 0) + { + /* Log the failure */ + exit(EXIT_FAILURE); + } + + /* Close out the standard file descriptors */ + close(STDIN_FILENO); + close(STDOUT_FILENO); + close(STDERR_FILENO); +} + + #endif diff --git a/server/snapServer.cpp b/server/snapServer.cpp index 7fff049f..a645c854 100644 --- a/server/snapServer.cpp +++ b/server/snapServer.cpp @@ -165,47 +165,6 @@ private: }; -void daemonize() -{ - /* Our process ID and Session ID */ - pid_t pid, sid; - - /* Fork off the parent process */ - pid = fork(); - if (pid < 0) - exit(EXIT_FAILURE); - - /* If we got a good PID, then - we can exit the parent process. */ - if (pid > 0) - exit(EXIT_SUCCESS); - - /* Change the file mode mask */ - umask(0); - - /* Open any logs here */ - - /* Create a new SID for the child process */ - sid = setsid(); - if (sid < 0) - { - /* Log the failure */ - exit(EXIT_FAILURE); - } - - /* Change the current working directory */ - if ((chdir("/")) < 0) - { - /* Log the failure */ - exit(EXIT_FAILURE); - } - - /* Close out the standard file descriptors */ - close(STDIN_FILENO); - close(STDOUT_FILENO); - close(STDERR_FILENO); -} - int main(int argc, char* argv[]) {