<keyword>C++</keyword>
<keyword>Code</keyword>
</keywords>
+ <projectname>libi2ncommon</projectname>
</general>
<kdevautoproject>
<general>
<codeCompletionDelay>250</codeCompletionDelay>
<argumentsHintDelay>400</argumentsHintDelay>
<headerCompletionDelay>250</headerCompletionDelay>
+ <showOnlyAccessibleItems>false</showOnlyAccessibleItems>
+ <completionBoxItemOrder>0</completionBoxItemOrder>
+ <howEvaluationContextMenu>true</howEvaluationContextMenu>
+ <showCommentWithArgumentHint>true</showCommentWithArgumentHint>
+ <statusBarTypeEvaluation>false</statusBarTypeEvaluation>
+ <namespaceAliases>std=_GLIBCXX_STD;__gnu_cxx=std</namespaceAliases>
+ <processPrimaryTypes>true</processPrimaryTypes>
+ <processFunctionArguments>false</processFunctionArguments>
+ <preProcessAllHeaders>false</preProcessAllHeaders>
+ <parseMissingHeadersExperimental>false</parseMissingHeadersExperimental>
+ <resolveIncludePathsUsingMakeExperimental>false</resolveIncludePathsUsingMakeExperimental>
+ <alwaysParseInBackground>true</alwaysParseInBackground>
+ <usePermanentCaching>true</usePermanentCaching>
+ <alwaysIncludeNamespaces>false</alwaysIncludeNamespaces>
+ <includePaths>.;</includePaths>
</codecompletion>
+ <qt>
+ <used>false</used>
+ <version>3</version>
+ <includestyle>3</includestyle>
+ <root>/usr/lib/qt-3.3</root>
+ <designerintegration>EmbeddedKDevDesigner</designerintegration>
+ <qmake>/usr/lib/qt-3.3/bin/qmake</qmake>
+ <designer>/usr/lib/qt-3.3/bin/designer</designer>
+ <designerpluginpaths/>
+ </qt>
</kdevcppsupport>
</kdevelop>
# the library search path.
lib_LTLIBRARIES = libi2ncommon.la
-include_HEADERS = pidfile.hxx logread.hxx insocketstream.hxx oftmpstream.hxx pipestream.hxx filefunc.hxx stringfunc.hxx timefunc.hxx ipfunc.hxx ip_type.hxx
-libi2ncommon_la_SOURCES = pidfile.cpp logread.cpp oftmpstream.cpp ipfunc.cpp timefunc.cpp filefunc.cpp stringfunc.cpp
+include_HEADERS = daemonfunc.hxx pidfile.hxx logread.hxx insocketstream.hxx oftmpstream.hxx pipestream.hxx filefunc.hxx stringfunc.hxx timefunc.hxx ipfunc.hxx ip_type.hxx
+libi2ncommon_la_SOURCES = daemonfunc.cpp pidfile.cpp logread.cpp oftmpstream.cpp ipfunc.cpp timefunc.cpp filefunc.cpp stringfunc.cpp
# Note: If you specify a:b:c as the version in the next line,
# the library that is made has version (a-c).c.b. In this
--- /dev/null
+/***************************************************************************
+ * Copyright (C) 2008 by Intra2net AG - Thomas Jarosch *
+ * thomas.jarosch@intra2net.com *
+ * http://www.intra2net.com *
+ ***************************************************************************/
+#include <sys/types.h>
+#include <unistd.h>
+#include <pwd.h>
+#include <grp.h>
+
+#include <string>
+#include <stdexcept>
+#include "daemonfunc.hxx"
+
+using namespace std;
+
+/**
+ * Fork into the background.
+ */
+void daemon::daemonize()
+{
+ int pid=fork();
+
+ if (pid < 0)
+ {
+ throw runtime_error("fork() failed");
+ }
+ if (pid > 0)
+ {
+ // parent process
+ exit (0);
+ }
+ // pid==0 -> child process: continue
+}
+
+/**
+ * Lookup uid for given username
+ * @param username username to convert
+ * @return uid of the user
+ */
+uid_t daemon::lookup_uid(const std::string &username)
+{
+ struct passwd *user = getpwnam(username.c_str());
+ if (user == NULL) {
+ throw runtime_error("user " + username + " not found");
+ }
+
+ return user->pw_uid;
+}
+
+/**
+ * Lookup gid for given group
+ * @param group group to convert
+ * @return gid of the group
+ */
+gid_t daemon::lookup_gid(const std::string &group)
+{
+ struct group *my_group = getgrnam(group.c_str());
+ if (my_group == NULL) {
+ throw runtime_error("group " + group + " not found");
+ }
+
+ return my_group->gr_gid;
+}
+
+/**
+ * Drop root priviledges
+ * @param username User to become. Don't change user if empty
+ * @param group Group to become. Don't change group if empty
+ */
+void daemon::drop_root_priviledges(const std::string &username,
+ const std::string &group)
+{
+ if (!group.empty()) {
+ if (setgid(daemon::lookup_gid(group))) {
+ throw runtime_error("Can't change to group " + group);
+ }
+ }
+
+ if (!username.empty()) {
+ if (setuid(daemon::lookup_uid(username))) {
+ throw runtime_error("Can't change to user " + username);
+ }
+ }
+}
--- /dev/null
+/***************************************************************************
+ * Copyright (C) 2008 by Intra2net AG - Thomas Jarosch *
+ * thomas.jarosch@intra2net.com *
+ * http://www.intra2net.com *
+ ***************************************************************************/
+#ifndef DAEMONFUNC_H
+#define DAEMONFUNC_H
+
+#include <sys/types.h>
+#include <string>
+
+/// Collection of functions for daemons
+class daemon
+{
+public:
+ static void daemonize();
+
+ static uid_t lookup_uid(const std::string &username);
+ static gid_t lookup_gid(const std::string &group);
+
+ static void drop_root_priviledges(const std::string &username,
+ const std::string &group);
+};
+
+#endif
***************************************************************************/
#include <string>
+#include <sstream>
#include <iostream>
+#include <stdexcept>
#include <sys/types.h>
#include <sys/stat.h>
+#include <dirent.h>
#include <pwd.h>
#include <grp.h>
#include <unistd.h>
+#include <errno.h>
#include <filefunc.hxx>
bool file_exists (const string &name)
{
struct stat statbuff;
-
+
if (stat(name.c_str(), &statbuff) < 0)
return false;
else
long fsize (const string &name)
{
long iReturn = -1;
-
+
struct stat statbuff;
-
+
if (lstat(name.c_str(), &statbuff) < 0)
return -1;
if (!S_ISREG(statbuff.st_mode))
return -1;
-
+
iReturn=statbuff.st_size;
return iReturn;
return false;
}
+/**
+ * Recursive delete of files and directories
+ * @param path File or directory to delete
+ * @param error Will contain the error if the return value is false
+ * @return true on success, false otherwise
+ */
+bool recursive_delete(const std::string &path, std::string *error)
+{
+ bool rtn = true;
+
+ try {
+ struct stat my_stat;
+ if (stat(path.c_str(), &my_stat) != 0) {
+ throw runtime_error("can't stat " + path);
+ }
+
+ if (S_ISDIR(my_stat.st_mode)) {
+ DIR *dir = opendir(path.c_str());
+ if (!dir) {
+ throw runtime_error("can't open directory " + path);
+ }
+
+ struct dirent *entry;
+ while ((entry = readdir(dir))) {
+ string filename = entry->d_name;
+ if (filename == "." || filename == "..") {
+ continue;
+ }
+
+ // Delete subdir or file.
+ rtn = recursive_delete(path + "/" + filename, error);
+ if (rtn == false) {
+ break;
+ }
+ }
+
+ closedir(dir);
+ if (rmdir(path.c_str()) != 0) {
+ throw runtime_error("can't remove directory " + path);
+ }
+ } else {
+ if (unlink(path.c_str()) != 0) {
+ throw runtime_error("can't unlink " + path);
+ }
+ }
+ } catch (exception &e) {
+ if (error) {
+ ostringstream out;
+ out << e.what() << " (" << strerror(errno) << ")";
+ *error = out.str();
+ }
+ rtn = false;
+ } catch (...) {
+ if (error) {
+ ostringstream out;
+ out << "unknown error (" << strerror(errno) << ")";
+ *error = out.str();
+ }
+ rtn = false;
+ }
+ return rtn;
+}
bool chown(const char* file,const char* owner, const char* group);
+bool recursive_delete(const std::string &path, std::string *error=NULL);
+
#endif