+static void make_names(void) {
+#ifdef HAVE_MINGW
+ HKEY key;
+ char installdir[1024] = "";
+ DWORD len = sizeof(installdir);
+#endif
+
+ if(netname) {
+ xasprintf(&identname, "tinc.%s", netname);
+ } else {
+ identname = xstrdup("tinc");
+ }
+
+#ifdef HAVE_MINGW
+
+ if(!RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\tinc", 0, KEY_READ, &key)) {
+ if(!RegQueryValueEx(key, NULL, 0, 0, (LPBYTE)installdir, &len)) {
+ if(!confbase) {
+ if(netname) {
+ xasprintf(&confbase, "%s/%s", installdir, netname);
+ } else {
+ xasprintf(&confbase, "%s", installdir);
+ }
+ }
+
+ if(!logfilename) {
+ xasprintf(&logfilename, "%s/tinc.log", confbase);
+ }
+ }
+
+ RegCloseKey(key);
+
+ if(*installdir) {
+ return;
+ }
+ }
+
+#endif
+
+ if(!pidfilename) {
+ xasprintf(&pidfilename, RUNSTATEDIR "/%s.pid", identname);
+ }
+
+ if(!logfilename) {
+ xasprintf(&logfilename, LOCALSTATEDIR "/log/%s.log", identname);
+ }
+
+ if(netname) {
+ if(!confbase) {
+ xasprintf(&confbase, CONFDIR "/tinc/%s", netname);
+ } else {
+ logger(LOG_INFO, "Both netname and configuration directory given, using the latter...");
+ }
+ } else {
+ if(!confbase) {
+ xasprintf(&confbase, CONFDIR "/tinc");
+ }
+ }
+}
+
+static void free_names() {
+ free(identname);
+ free(netname);
+ free(pidfilename);
+ free(logfilename);
+ 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
+
+int main(int argc, char **argv) {
+ program_name = argv[0];
+
+ if(!parse_options(argc, argv)) {
+ return 1;
+ }
+
+ if(show_version) {
+ printf("%s version %s\n", PACKAGE, VERSION);
+ printf("Copyright (C) 1998-2018 Ivo Timmermans, Guus Sliepen and others.\n"
+ "See the AUTHORS file for a complete list.\n\n"
+ "tinc comes with ABSOLUTELY NO WARRANTY. This is free software,\n"
+ "and you are welcome to redistribute it under certain conditions;\n"
+ "see the file COPYING for details.\n");
+
+ return 0;
+ }
+
+ if(show_help) {
+ usage(false);
+ return 0;
+ }
+
+ make_names();
+
+ if(kill_tincd) {
+ return !kill_other(kill_tincd);
+ }
+
+ openlogger("tinc", use_logfile ? LOGMODE_FILE : LOGMODE_STDERR);
+
+ g_argv = argv;
+
+ if(getenv("LISTEN_PID") && atoi(getenv("LISTEN_PID")) == getpid()) {
+ do_detach = false;
+ }
+
+#ifdef HAVE_UNSETENV
+ unsetenv("LISTEN_PID");
+#endif
+
+ init_configuration(&config_tree);
+
+ ENGINE_load_builtin_engines();
+ ENGINE_register_all_complete();
+
+ OpenSSL_add_all_algorithms();
+
+ if(generate_keys) {
+ read_server_config();
+ return !keygen(generate_keys);
+ }
+
+ if(!read_server_config()) {
+ return 1;
+ }
+
+#ifdef HAVE_LZO
+
+ if(lzo_init() != LZO_E_OK) {
+ logger(LOG_ERR, "Error initializing LZO compressor!");
+ return 1;
+ }
+
+#endif
+
+#ifdef HAVE_MINGW
+
+ if(WSAStartup(MAKEWORD(2, 2), &wsa_state)) {
+ logger(LOG_ERR, "System call `%s' failed: %s", "WSAStartup", winerror(GetLastError()));
+ return 1;
+ }
+
+ if(!do_detach || !init_service()) {
+ return main2(argc, argv);
+ } else {
+ return 1;
+ }