+static void free_names() {
+ if(identname) {
+ free(identname);
+ }
+
+ if(netname) {
+ free(netname);
+ }
+
+ if(pidfilename) {
+ free(pidfilename);
+ }
+
+ if(logfilename) {
+ free(logfilename);
+ }
+
+ if(confbase) {
+ free(confbase);
+ }
+}
+
+static bool drop_privs() {
+#ifdef HAVE_MINGW
+
+ if(switchuser) {
+ logger(LOG_ERR, "%s not supported on this platform", "-U");
+ return false;
+ }
+
+ if(do_chroot) {
+ logger(LOG_ERR, "%s not supported on this platform", "-R");
+ return false;
+ }
+
+#else
+ uid_t uid = 0;
+
+ if(switchuser) {
+ struct passwd *pw = getpwnam(switchuser);
+
+ if(!pw) {
+ logger(LOG_ERR, "unknown user `%s'", switchuser);
+ return false;
+ }
+
+ uid = pw->pw_uid;
+
+ if(initgroups(switchuser, pw->pw_gid) != 0 ||
+ setgid(pw->pw_gid) != 0) {
+ logger(LOG_ERR, "System call `%s' failed: %s",
+ "initgroups", strerror(errno));
+ return false;
+ }
+
+#ifndef ANDROID
+// Not supported in android NDK
+ endgrent();
+ endpwent();
+#endif
+ }
+
+ if(do_chroot) {
+ tzset(); /* for proper timestamps in logs */
+
+ if(chroot(confbase) != 0 || chdir("/") != 0) {
+ logger(LOG_ERR, "System call `%s' failed: %s",
+ "chroot", strerror(errno));
+ return false;
+ }
+
+ free(confbase);
+ confbase = xstrdup("");
+ }
+
+ if(switchuser)
+ if(setuid(uid) != 0) {
+ logger(LOG_ERR, "System call `%s' failed: %s",
+ "setuid", strerror(errno));
+ return false;
+ }
+
+#endif
+ return true;
+}
+
+#ifdef HAVE_MINGW
+# define setpriority(level) !SetPriorityClass(GetCurrentProcess(), (level))
+#else
+# define NORMAL_PRIORITY_CLASS 0
+# define BELOW_NORMAL_PRIORITY_CLASS 10
+# define HIGH_PRIORITY_CLASS -10
+# define setpriority(level) (setpriority(PRIO_PROCESS, 0, (level)))
+#endif