diff -uprN PtokaX.orig/makefile PtokaX/makefile
--- PtokaX.orig/makefile	2010-01-09 21:34:47.000000000 +0300
+++ PtokaX/makefile	2011-03-22 00:07:27.000000000 +0300
@@ -39,7 +39,7 @@ PtokaX: $(CURDIR)/obj/ClientTagManager.o
   $(CURDIR)/obj/LuaRegManLib.o $(CURDIR)/obj/LuaScript.o $(CURDIR)/obj/LuaScriptManager.o $(CURDIR)/obj/LuaScriptManLib.o $(CURDIR)/obj/LuaSetManLib.o $(CURDIR)/obj/LuaTmrManLib.o $(CURDIR)/obj/LuaUDPDbgLib.o $(CURDIR)/obj/ProfileManager.o \
   $(CURDIR)/obj/PtokaX.o $(CURDIR)/obj/pxstring.o $(CURDIR)/obj/RegThread.o $(CURDIR)/obj/ResNickManager.o $(CURDIR)/obj/ServerManager.o $(CURDIR)/obj/ServerThread.o $(CURDIR)/obj/serviceLoop.o $(CURDIR)/obj/SettingManager.o \
   $(CURDIR)/obj/TextFileManager.o $(CURDIR)/obj/UdpDebug.o $(CURDIR)/obj/UDPThread.o $(CURDIR)/obj/User.o $(CURDIR)/obj/utility.o $(CURDIR)/obj/ZlibUtility.o
-	$(CXX) -lpthread -lz -llua5.1 -lrt -o PtokaX \
+	$(CXX) -lpthread -lz -llua5.1 -lrt -lcap -o PtokaX \
         $(CURDIR)/obj/ClientTagManager.o $(CURDIR)/obj/colUsers.o $(CURDIR)/obj/DcCommands.o $(CURDIR)/obj/DeFlood.o $(CURDIR)/obj/eventqueue.o $(CURDIR)/obj/globalQueue.o $(CURDIR)/obj/hashBanManager.o $(CURDIR)/obj/hashUsrManager.o \
         $(CURDIR)/obj/hashRegManager.o $(CURDIR)/obj/HubCommands.o $(CURDIR)/obj/IP2Country.o $(CURDIR)/obj/LanguageManager.o $(CURDIR)/obj/LuaBanManLib.o $(CURDIR)/obj/LuaCoreLib.o $(CURDIR)/obj/LuaIP2CountryLib.o \
         $(CURDIR)/obj/LuaProfManLib.o $(CURDIR)/obj/LuaRegManLib.o $(CURDIR)/obj/LuaScript.o $(CURDIR)/obj/LuaScriptManager.o $(CURDIR)/obj/LuaScriptManLib.o $(CURDIR)/obj/LuaSetManLib.o $(CURDIR)/obj/LuaTmrManLib.o \
diff -uprN PtokaX.orig/src/PtokaX-nix.cpp PtokaX/src/PtokaX-nix.cpp
--- PtokaX.orig/src/PtokaX-nix.cpp	2010-01-09 20:27:20.000000000 +0300
+++ PtokaX/src/PtokaX-nix.cpp	2011-03-22 00:08:45.000000000 +0300
@@ -19,6 +19,11 @@
 
 //---------------------------------------------------------------------------
 #include "stdinc.h"
+#include <grp.h>
+#include <pwd.h>
+#include <stdarg.h>
+#include <sys/capability.h>
+#include <sys/prctl.h>
 //---------------------------------------------------------------------------
 #include "LanguageManager.h"
 #include "ServerManager.h"
@@ -66,7 +71,30 @@ static void SigHandler(int sig) {
 }
 //---------------------------------------------------------------------------
 
+//
+// Output error message to stdout or syslog and exit with a non-zero error code
+// Uses printf()-like format string
+//
+static void fatal_error(bool use_syslog, const char *format, ...) {
+    va_list args;
+
+    va_start(args, format);
+    if(use_syslog) {
+        vsyslog(LOG_USER | LOG_ERR, format, args);
+    } else {
+        vprintf(format, args);
+    }
+    va_end(args);
+
+    exit(EXIT_FAILURE);
+}
+//---------------------------------------------------------------------------
+
 int main(int argc, char* argv[]) {
+    cap_t caps;
+    cap_flag_value_t nbs_flag;
+    struct passwd *user = 0;
+
 	sTitle = "PtokaX DC Hub " + string(PtokaXVersionString);
 	
 #ifdef _DEBUG
@@ -93,25 +121,24 @@ int main(int argc, char* argv[]) {
 			} else {
 	            PATH = string(argv[i], iLen);
 	        }
-	
-	        if(DirExist(PATH.c_str()) == false) {
-	        	if(mkdir(PATH.c_str(), S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP) == -1) {
-	                if(bDaemon == true) {
-	                    syslog(LOG_USER | LOG_ERR, "Config directory not exist and can't be created!\n");
-	                } else {
-	                    printf("Config directory not exist and can't be created!");
-	                }
-	            }
-            }
 	    } else if(strcasecmp(argv[i], "-v") == 0) {
 	        printf((sTitle+" built on "+__DATE__+" "+__TIME__+"\n").c_str());
 	        return EXIT_SUCCESS;
 	    } else if(strcasecmp(argv[i], "-h") == 0) {
-	        printf("PtokaX [-d] [-c <configdir>] [-v]\n");
+	        printf("PtokaX [-d] [-c <configdir>] [-v] [-u <username>]\n");
 	        return EXIT_SUCCESS;
 	    } else if(strcasecmp(argv[i], "/nokeycheck") == 0) {
 	        bCmdNoKeyCheck = true;
-	    }
+        } else if(strcasecmp(argv[i], "-u") == 0) {
+            if(++i == argc) {
+                fatal_error(false, "Missing username!\n");
+            }
+
+            user = getpwnam(argv[i]);
+            if(!user) {
+                fatal_error(false, "Cannot find user '%s'!\n", argv[i]);
+            }
+        }
 	}
 	
 	if(PATH.size() == 0) {
@@ -119,12 +146,6 @@ int main(int argc, char* argv[]) {
 	    char curdir[PATH_MAX];
 	    if(bDaemon == true && (home = getenv("HOME")) != NULL) {
 	        PATH = string(home) + "/.PtokaX";
-	            
-	        if(DirExist(PATH.c_str()) == false) {
-	            if(mkdir(PATH.c_str(), S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP) == -1) {
-	                syslog(LOG_USER | LOG_ERR, "Config directory not exist and can't be created!\n");
-	            }
-	        }
 	    } else if(getcwd(curdir, PATH_MAX) != NULL) {
 	        PATH = curdir;
 	    } else {
@@ -132,6 +153,8 @@ int main(int argc, char* argv[]) {
 	    }
 	}
 	
+    umask(027);
+
 	if(bDaemon == true) {
 	    printf(("Starting "+sTitle+" as daemon using "+PATH+" as config directory.\n").c_str());
 	
@@ -162,8 +185,6 @@ int main(int argc, char* argv[]) {
 	    close(STDOUT_FILENO);
 	    close(STDERR_FILENO);
 	
-	    umask(117);
-	
 	    if(open("/dev/null", O_RDWR) == -1) {
 	        syslog(LOG_USER | LOG_ERR, "Failed to open /dev/null!\n");
 	        return EXIT_FAILURE;
@@ -173,6 +194,57 @@ int main(int argc, char* argv[]) {
 	    dup(0);
 	}
 	
+    if(user) {
+        // Keep capabilities across UID change
+        if(prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) != 0) {
+            fatal_error(bDaemon, "prctl(PR_SET_KEEPCAPS) failed!\n");
+        }
+
+        // Change supplementary groups
+        if(initgroups(user->pw_name, user->pw_gid) != 0) {
+            fatal_error(bDaemon, "initgroups() for user '%s' failed!\n", user->pw_name);
+        }
+
+        // Change GID
+        if(setgid(user->pw_gid) != 0) {
+            fatal_error(bDaemon, "Cannot set GID to %d!\n", user->pw_gid);
+        }
+
+        // Change UID
+        if(setuid(user->pw_uid) != 0) {
+            fatal_error(bDaemon, "Cannot set UID to %d!\n", user->pw_uid);
+        }
+    }
+
+    // Check capability to bind privileged ports
+    caps = cap_get_proc();
+    if(!caps) {
+        fatal_error(bDaemon, "cap_get_proc() failed to get capabilities!\n");
+    }
+    if(cap_get_flag(caps, CAP_NET_BIND_SERVICE, CAP_PERMITTED, &nbs_flag) != 0) {
+        cap_free(caps);
+        fatal_error(bDaemon, "cap_get_flag() failed to get CAP_NET_BIND_SERVICE state!\n");
+    }
+    cap_free(caps);
+
+    // Drop all capabilities except privileged ports binding
+    caps = cap_from_text(nbs_flag == CAP_SET ? "cap_net_bind_service=ep" : "=");
+    if(!caps) {
+        fatal_error(bDaemon, "cap_from_text() failed to parse capabilities string!\n");
+    }
+    if(cap_set_proc(caps) != 0) {
+        cap_free(caps);
+        fatal_error(bDaemon, "cap_set_proc() failed to set capabilities!\n");
+    }
+    cap_free(caps);
+
+    // Create config directory if it does not exist
+    if(!DirExist(PATH.c_str())) {
+        if(mkdir(PATH.c_str(), S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP) == -1) {
+            fatal_error(bDaemon, "Config directory '%s' not exist and can't be created!\n", PATH.c_str());
+        }
+    }
+
 	sigset_t sst;
 	sigemptyset(&sst);
 	sigaddset(&sst, SIGPIPE);
