+ if (r != 0 && c->daemonize)
+ daemon_retval_send(1);
+
+ return r;
+}
+
+static gint drop_root(void) {
+ struct passwd *pw;
+ struct group * gr;
+ gint r;
+
+ if (!(pw = getpwnam(AVAHI_USER))) {
+ avahi_log_error( "Failed to find user '"AVAHI_USER"'.");
+ return -1;
+ }
+
+ if (!(gr = getgrnam(AVAHI_GROUP))) {
+ avahi_log_error( "Failed to find group '"AVAHI_GROUP"'.");
+ return -1;
+ }
+
+ avahi_log_info("Found user '"AVAHI_USER"' (UID %lu) and group '"AVAHI_GROUP"' (GID %lu).", (unsigned long) pw->pw_uid, (unsigned long) gr->gr_gid);
+
+ if (initgroups(AVAHI_USER, gr->gr_gid) != 0) {
+ avahi_log_error("Failed to change group list: %s", strerror(errno));
+ return -1;
+ }
+
+#if defined(HAVE_SETRESGID)
+ r = setresgid(gr->gr_gid, gr->gr_gid, gr->gr_gid);
+#elif defined(HAVE_SETREGID)
+ r = setregid(gr->gr_gid, gr->gr_gid);
+#else
+ if ((r = setgid(gr->gr_gid)) >= 0)
+ r = setegid(gr->gr_gid);
+#endif
+
+ if (r < 0) {
+ avahi_log_error("Failed to change GID: %s", strerror(errno));
+ return -1;
+ }
+
+#if defined(HAVE_SETRESUID)
+ r = setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid);
+#elif defined(HAVE_SETREUID)
+ r = setreuid(pw->pw_uid, pw->pw_uid);
+#else
+ if ((r = setuid(pw->pw_uid)) >= 0)
+ r = seteuid(pw->pw_uid);
+#endif
+
+ if (r < 0) {
+ avahi_log_error("Failed to change UID: %s", strerror(errno));
+ return -1;
+ }
+
+ g_setenv("USER", pw->pw_name, 1);
+ g_setenv("LOGNAME", pw->pw_name, 1);
+ g_setenv("HOME", pw->pw_dir, 1);
+
+ avahi_log_info("Successfully dropped root privileges.");
+
+ return 0;
+}
+
+static const char* pid_file_proc(void) {
+ return AVAHI_DAEMON_RUNTIME_DIR"/pid";
+}
+
+static gint make_runtime_dir(void) {
+ gint r = -1;
+ mode_t u;
+ gboolean reset_umask = FALSE;
+ struct passwd *pw;
+ struct group * gr;
+ struct stat st;
+
+ if (!(pw = getpwnam(AVAHI_USER))) {
+ avahi_log_error( "Failed to find user '"AVAHI_USER"'.");
+ goto fail;
+ }
+
+ if (!(gr = getgrnam(AVAHI_GROUP))) {
+ avahi_log_error( "Failed to find group '"AVAHI_GROUP"'.");
+ goto fail;
+ }
+
+ u = umask(0000);
+ reset_umask = TRUE;
+
+ if (mkdir(AVAHI_DAEMON_RUNTIME_DIR, 0755) < 0 && errno != EEXIST) {
+ avahi_log_error("mkdir(\""AVAHI_DAEMON_RUNTIME_DIR"\"): %s", strerror(errno));
+ goto fail;
+ }
+
+ chown(AVAHI_DAEMON_RUNTIME_DIR, pw->pw_uid, gr->gr_gid);
+
+ if (stat(AVAHI_DAEMON_RUNTIME_DIR, &st) < 0) {
+ avahi_log_error("stat(): %s\n", strerror(errno));
+ goto fail;
+ }
+
+ if (!S_ISDIR(st.st_mode) || st.st_uid != pw->pw_uid || st.st_gid != gr->gr_gid) {
+ avahi_log_error("Failed to create runtime directory "AVAHI_DAEMON_RUNTIME_DIR".");
+ goto fail;
+ }
+
+ r = 0;
+
+fail:
+ if (reset_umask)
+ umask(u);
+ return r;
+
+}
+
+int main(int argc, char *argv[]) {
+ gint r = 255;
+ const gchar *argv0;
+ gboolean wrote_pid_file = FALSE;
+
+ avahi_set_log_function(log_function);
+
+ avahi_server_config_init(&config.server_config);
+ config.command = DAEMON_RUN;
+ config.daemonize = FALSE;
+ config.config_file = NULL;
+ config.enable_dbus = TRUE;
+ config.drop_root = TRUE;
+ config.publish_dns_servers = NULL;
+ config.publish_resolv_conf = FALSE;
+
+ if ((argv0 = strrchr(argv[0], '/')))
+ argv0++;
+ else
+ argv0 = argv[0];
+
+ daemon_pid_file_ident = (const char *) argv0;
+ daemon_log_ident = (char*) argv0;
+ daemon_pid_file_proc = pid_file_proc;
+
+ if (parse_command_line(&config, argc, argv) < 0)
+ goto finish;
+
+ if (config.command == DAEMON_HELP) {
+ help(stdout, argv0);
+ r = 0;
+ } else if (config.command == DAEMON_VERSION) {
+ printf("%s "PACKAGE_VERSION"\n", argv0);
+ r = 0;
+ } else if (config.command == DAEMON_KILL) {
+ if (daemon_pid_file_kill_wait(SIGTERM, 5) < 0) {
+ avahi_log_warn("Failed to kill daemon: %s", strerror(errno));
+ goto finish;
+ }
+
+ r = 0;
+
+ } else if (config.command == DAEMON_RELOAD) {
+ if (daemon_pid_file_kill(SIGHUP) < 0) {
+ avahi_log_warn("Failed to kill daemon: %s", strerror(errno));
+ goto finish;
+ }
+
+ r = 0;
+
+ } else if (config.command == DAEMON_CHECK)
+ r = (daemon_pid_file_is_running() >= 0) ? 0 : 1;
+ else if (config.command == DAEMON_RUN) {
+ pid_t pid;
+
+ if (getuid() != 0) {
+ avahi_log_error("This program is intended to be run as root.");
+ goto finish;
+ }
+
+ if ((pid = daemon_pid_file_is_running()) >= 0) {
+ avahi_log_error("Daemon already running on PID %u", pid);
+ goto finish;
+ }
+
+ if (load_config_file(&config) < 0)
+ goto finish;
+
+ if (config.daemonize) {
+ daemon_retval_init();
+
+ if ((pid = daemon_fork()) < 0)
+ goto finish;
+ else if (pid != 0) {
+ int ret;
+ /** Parent **/
+
+ if ((ret = daemon_retval_wait(20)) < 0) {
+ avahi_log_error("Could not recieve return value from daemon process.");
+ goto finish;
+ }
+
+ r = ret;
+ goto finish;
+ }
+
+ /* Child */
+ }
+
+
+ printf("%s "PACKAGE_VERSION" starting up.\n", argv0);
+
+ chdir("/");
+
+ if (make_runtime_dir() < 0)
+ goto finish;
+
+ if (config.drop_root) {
+ if (drop_root() < 0)
+ goto finish;
+ }
+
+ if (daemon_pid_file_create() < 0) {
+ avahi_log_error("Failed to create PID file: %s", strerror(errno));
+
+ if (config.daemonize)
+ daemon_retval_send(1);
+ goto finish;
+ } else
+ wrote_pid_file = TRUE;
+
+ if (run_server(&config) == 0)
+ r = 0;
+ }
+
+finish:
+
+ if (config.daemonize)
+ daemon_retval_done();
+
+ avahi_server_config_free(&config.server_config);
+ g_free(config.config_file);
+ g_strfreev(config.publish_dns_servers);
+ g_strfreev(resolv_conf);
+
+ if (wrote_pid_file)
+ daemon_pid_file_remove();
+