+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;
+}