Index: configure.in
===================================================================
--- configure.in	(revision 5604)
+++ configure.in	(working copy)
@@ -162,7 +162,7 @@
 # Checks for header files.
 AC_HEADER_DIRENT
 AC_HEADER_STDC
-AC_CHECK_HEADERS([sys/types.h])
+AC_CHECK_HEADERS([sys/types.h sys/resource.h])
 
 # Checks for typedefs, structures, and compiler characteristics.
 AC_C_CONST
@@ -176,7 +176,11 @@
 AC_FUNC_MALLOC
 AC_TYPE_SIGNAL
 AC_FUNC_STRFTIME
-AC_CHECK_FUNCS([gethostname vasprintf mmap mlock mlockall usleep])
+AC_CHECK_FUNCS([gethostname vasprintf mmap mlock mlockall usleep setrlimit initgroups])
+AC_CHECK_DECL([RLIMIT_MEMLOCK],,,
+	[#ifdef HAVE_SYS_RESOURCE_H
+	 #include <sys/resource.h>
+	 #endif])
 
 AC_C_BIGENDIAN(AC_DEFINE([SWITCH_BYTE_ORDER],__BIG_ENDIAN,[Big Endian]),AC_DEFINE([SWITCH_BYTE_ORDER],__LITTLE_ENDIAN,[Little Endian]))
 
Index: src/switch.c
===================================================================
--- src/switch.c	(revision 5604)
+++ src/switch.c	(working copy)
@@ -61,7 +61,19 @@
 
 /* event to signal shutdown (for you unix people, this is like a pthread_cond) */
 static HANDLE shutdown_event;
+#else
+
+/* setuid, setgid */
+#include <unistd.h>
+
+/* getgrnam, getpwnam */
+#include <pwd.h>
+#include <grp.h>
+
+#ifdef HAVE_SYS_RESOURCE_H
+#include <sys/resource.h>
 #endif
+#endif
 
 /* signal handler for when freeswitch is running in background mode.
  * signal triggers the shutdown of freeswitch
@@ -204,6 +216,8 @@
 	const char *err = NULL;		/* error value for return from freeswitch initialization */
 #ifndef WIN32
 	int nf = 0;					/* TRUE if we are running in nofork mode */
+	gid_t runas_gid = 0;
+	struct passwd *runas_pw = NULL;
 #endif
 	int nc = 0;					/* TRUE if we are running in noconsole mode */
 	FILE *f;					/* file handle to the pid file */
@@ -213,6 +227,7 @@
 	char *usageDesc;
 	int alt_dirs = 0;
 	int known_opt;
+	int high_prio = 0;
 
 #ifdef WIN32
 	SERVICE_TABLE_ENTRY dispatchTable[] = {
@@ -227,7 +242,8 @@
 		"\t-stop            -- stop freeswitch\n"
 		"\t-nc              -- do not output to a console and background\n"
 		"\t-conf [confdir]  -- specify an alternate config dir\n"
-		"\t-log [logdir]    -- specify an alternate log dir\n" "\t-db [dbdir]      -- specify an alternate db dir\n";
+		"\t-log [logdir]    -- specify an alternate log dir\n"
+		"\t-db [dbdir]      -- specify an alternate db dir\n";
 #else
 	usageDesc = "these are the optional arguments you can pass to freeswitch\n"
 		"\t-help            -- this message\n"
@@ -236,7 +252,10 @@
 		"\t-stop            -- stop freeswitch\n"
 		"\t-nc              -- do not output to a console and background\n"
 		"\t-conf [confdir]  -- specify an alternate config dir\n"
-		"\t-log [logdir]    -- specify an alternate log dir\n" "\t-db [dbdir]      -- specify an alternate db dir\n";
+		"\t-log [logdir]    -- specify an alternate log dir\n"
+		"\t-db [dbdir]      -- specify an alternate db dir\n"
+		"\t-u [user]        -- specify user to switch to\n"
+		"\t-g [group]       -- specify group to switch to\n";
 
 #endif
 
@@ -281,13 +300,41 @@
 		}
 #else
 
+		if (argv[x] && !strcmp(argv[x], "-u")) {
+			x++;
+			if (argv[x] && strlen(argv[x])) {
+				runas_pw = getpwnam( argv[x] );
+				if (!runas_pw) {
+					fprintf(stderr, "Unknown user passed to -u option\n");
+					return 255;
+				}
+			}
+			known_opt++;
+		}
+
+		if (argv[x] && !strcmp(argv[x], "-g")) {
+			x++;
+			if (argv[x] && strlen(argv[x])) {
+				struct group *gr = NULL;
+
+				gr = getgrnam( argv[x] );
+				if (!gr) {
+					fprintf(stderr, "Unknown group passed to -g option\n");
+					return 255;
+				}
+				runas_gid = gr->gr_gid;
+				free(gr);
+			}
+			known_opt++;
+		}
+
 		if (argv[x] && !strcmp(argv[x], "-nf")) {
 			nf++;
 			known_opt++;
 		}
 #endif
 		if (argv[x] && !strcmp(argv[x], "-hp")) {
-			set_high_priority();
+			high_prio++;
 			known_opt++;
 		}
 
@@ -372,6 +419,47 @@
 #endif
 	}
 
+	if (high_prio) {
+#ifndef WIN32
+#if defined(HAVE_SETRLIMIT) && defined(HAVE_DECL_RLIMIT_MEMLOCK) && HAVE_DECL_RLIMIT_MEMLOCK
+		/* Need to reset limit for mlockall before calling setuid() */
+		if (runas_pw && runas_pw->pw_uid) {
+			struct rlimit lim = { RLIM_INFINITY, RLIM_INFINITY };
+
+			if (setrlimit(RLIMIT_MEMLOCK, &lim) < 0) {
+				fprintf(stderr, "Failed to set locked memory limit\n");
+				return 255;
+			}
+		}
+#endif
+#endif
+		set_high_priority();
+	}
+
+#ifndef WIN32
+	if (runas_gid) {
+		if (setgid(runas_gid) < 0) {
+			fprintf(stderr, "Failed to change gid!\n");
+			return 255;
+		}
+	}
+	if (runas_pw && runas_pw->pw_uid) {
+		if (setuid(runas_pw->pw_uid) < 0) {
+			fprintf(stderr, "Failed to change uid!\n");
+			return 255;
+		}
+#if defined(HAVE_INITGROUPS)
+		if (!runas_gid) {
+			if (initgroups(runas_pw->pw_name, runas_pw->pw_gid) < 0) {
+				fprintf(stderr, "Failed to set group access list for user\n");
+				return 255;
+			}
+		}
+#endif
+		free(runas_pw);
+	}
+#endif
+
 	if (switch_core_init_and_modload(nc ? lfile : NULL, &err) != SWITCH_STATUS_SUCCESS) {
 		fprintf(stderr, "Cannot Initilize [%s]\n", err);
 		return 255;
