libi2ncommon: (tomj) added daemon handling and recursive_delete()
authorThomas Jarosch <thomas.jarosch@intra2net.com>
Fri, 4 Apr 2008 12:29:50 +0000 (12:29 +0000)
committerThomas Jarosch <thomas.jarosch@intra2net.com>
Fri, 4 Apr 2008 12:29:50 +0000 (12:29 +0000)
libi2ncommon.kdevelop
src/Makefile.am
src/daemonfunc.cpp [new file with mode: 0644]
src/daemonfunc.hxx [new file with mode: 0644]
src/filefunc.cpp
src/filefunc.hxx

index 01beb7f..f8f531f 100644 (file)
@@ -10,6 +10,7 @@
       <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>
index f26b4cd..421cca4 100644 (file)
@@ -4,8 +4,8 @@ INCLUDES = -I$(top_srcdir)/src @LIBGETTEXT_CFLAGS@ @LIBICONV_CFLAGS@ $(all_inclu
 
 # 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
diff --git a/src/daemonfunc.cpp b/src/daemonfunc.cpp
new file mode 100644 (file)
index 0000000..cc570e9
--- /dev/null
@@ -0,0 +1,85 @@
+/***************************************************************************
+ *   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);
+        }
+    }
+}
diff --git a/src/daemonfunc.hxx b/src/daemonfunc.hxx
new file mode 100644 (file)
index 0000000..4e14560
--- /dev/null
@@ -0,0 +1,25 @@
+/***************************************************************************
+ *   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
index 6804af7..f65db18 100644 (file)
@@ -7,13 +7,17 @@
  ***************************************************************************/
 
 #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>
 
@@ -22,7 +26,7 @@ using namespace std;
 bool file_exists (const string &name)
 {
     struct stat statbuff;
-    
+
     if (stat(name.c_str(), &statbuff) < 0)
         return false;
     else
@@ -32,15 +36,15 @@ bool file_exists (const string &name)
 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;
@@ -95,4 +99,66 @@ bool chown(const char* file,const char* owner, const char* group)
         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;
+}
index a4af02c..14c9ddb 100644 (file)
@@ -15,4 +15,6 @@ std::string load_file (const std::string &name);
 
 bool chown(const char* file,const char* owner, const char* group);
 
+bool recursive_delete(const std::string &path, std::string *error=NULL);
+
 #endif