#include <getopt.h>
#include <string.h>
#include <signal.h>
+#include <errno.h>
+#include <string.h>
#include <libdaemon/dfork.h>
#include <libdaemon/dsignal.h>
int r = -1;
GKeyFile *f = NULL;
GError *err = NULL;
- gchar **groups = NULL, **g, **keys = NULL;
+ gchar **groups = NULL, **g, **keys = NULL, *v = NULL;
g_assert(config);
keys = g_key_file_get_keys(f, *g, NULL, NULL);
for (k = keys; *k; k++) {
+
+ v = g_key_file_get_value(f, *g, *k, NULL);
+
if (g_strcasecmp(*k, "host-name") == 0) {
g_free(config->server_config.host_name);
- config->server_config.host_name = g_strdup(g_key_file_get_string(f, *g, *k, NULL));
+ config->server_config.host_name = v;
+ v = NULL;
} else if (g_strcasecmp(*k, "domain-name") == 0) {
g_free(config->server_config.domain_name);
- config->server_config.domain_name = g_strdup(g_key_file_get_string(f, *g, *k, NULL));
+ config->server_config.domain_name = v;
+ v = NULL;
} else if (g_strcasecmp(*k, "use-ipv4") == 0)
- config->server_config.use_ipv4 = is_yes(g_key_file_get_string(f, *g, *k, NULL));
+ config->server_config.use_ipv4 = is_yes(v);
else if (g_strcasecmp(*k, "use-ipv6") == 0)
- config->server_config.use_ipv6 = is_yes(g_key_file_get_string(f, *g, *k, NULL));
+ config->server_config.use_ipv6 = is_yes(v);
else if (g_strcasecmp(*k, "check-response-ttl") == 0)
- config->server_config.check_response_ttl = is_yes(g_key_file_get_string(f, *g, *k, NULL));
+ config->server_config.check_response_ttl = is_yes(v);
else if (g_strcasecmp(*k, "use-iff-running") == 0)
- config->server_config.use_iff_running = is_yes(g_key_file_get_string(f, *g, *k, NULL));
+ config->server_config.use_iff_running = is_yes(v);
else if (g_strcasecmp(*k, "enable-dbus") == 0)
- config->enable_dbus = is_yes(g_key_file_get_string(f, *g, *k, NULL));
+ config->enable_dbus = is_yes(v);
else {
fprintf(stderr, "Invalid configuration key \"%s\" in group \"%s\"\n", *k, *g);
goto finish;
}
+
+ g_free(v);
+ v = NULL;
}
+
+ g_strfreev(keys);
+ keys = NULL;
} else if (g_strcasecmp(*g, "publish") == 0) {
gchar **k;
keys = g_key_file_get_keys(f, *g, NULL, NULL);
for (k = keys; *k; k++) {
+
+ v = g_key_file_get_string(f, *g, *k, NULL);
+
if (g_strcasecmp(*k, "publish-addresses") == 0)
- config->server_config.publish_addresses = is_yes(g_key_file_get_string(f, *g, *k, NULL));
+ config->server_config.publish_addresses = is_yes(v);
else if (g_strcasecmp(*k, "publish-hinfo") == 0)
- config->server_config.publish_hinfo = is_yes(g_key_file_get_string(f, *g, *k, NULL));
+ config->server_config.publish_hinfo = is_yes(v);
else if (g_strcasecmp(*k, "publish-workstation") == 0)
- config->server_config.publish_workstation = is_yes(g_key_file_get_string(f, *g, *k, NULL));
+ config->server_config.publish_workstation = is_yes(v);
else if (g_strcasecmp(*k, "publish-domain") == 0)
- config->server_config.publish_domain = is_yes(g_key_file_get_string(f, *g, *k, NULL));
+ config->server_config.publish_domain = is_yes(v);
else {
fprintf(stderr, "Invalid configuration key \"%s\" in group \"%s\"\n", *k, *g);
goto finish;
}
+
+ g_free(v);
+ v = NULL;
}
+ g_strfreev(keys);
+ keys = NULL;
+
} else if (g_strcasecmp(*g, "reflector") == 0) {
gchar **k;
keys = g_key_file_get_keys(f, *g, NULL, NULL);
for (k = keys; *k; k++) {
+
+ v = g_key_file_get_string(f, *g, *k, NULL);
+
if (g_strcasecmp(*k, "enable-reflector") == 0)
- config->server_config.enable_reflector = is_yes(g_key_file_get_string(f, *g, *k, NULL));
+ config->server_config.enable_reflector = is_yes(v);
else if (g_strcasecmp(*k, "reflect-ipv") == 0)
- config->server_config.reflect_ipv = is_yes(g_key_file_get_string(f, *g, *k, NULL));
+ config->server_config.reflect_ipv = is_yes(v);
else {
fprintf(stderr, "Invalid configuration key \"%s\" in group \"%s\"\n", *k, *g);
goto finish;
}
+
+ g_free(v);
+ v = NULL;
}
+ g_strfreev(keys);
+ keys = NULL;
+
} else {
fprintf(stderr, "Invalid configuration file group \"%s\".\n", *g);
goto finish;
g_strfreev(groups);
g_strfreev(keys);
+ g_free(v);
if (err)
g_error_free (err);
daemon_log(log_level_map[level], "%s", txt);
}
+static gboolean signal_callback(GIOChannel *source, GIOCondition condition, gpointer data) {
+ gint sig;
+ g_assert(source);
+
+ if ((sig = daemon_signal_next()) <= 0) {
+ avahi_log_error("daemon_signal_next() failed");
+ return FALSE;
+ }
+
+ switch (sig) {
+ case SIGINT:
+ case SIGQUIT:
+ case SIGTERM:
+ avahi_log_info(
+ "Got %s, quitting.",
+ sig == SIGINT ? "SIGINT" :
+ (sig == SIGQUIT ? "SIGQUIT" : "SIGTERM"));
+ g_main_loop_quit((GMainLoop*) data);
+ break;
+
+ case SIGHUP:
+ avahi_log_info("Got SIGHUP, reloading.");
+ static_service_load();
+ break;
+
+ default:
+ avahi_log_warn("Got spurious signal, ignoring.");
+ break;
+ }
+
+ return TRUE;
+}
+
static gint run_server(DaemonConfig *config) {
GMainLoop *loop = NULL;
gint r = -1;
+ GIOChannel *io = NULL;
+ guint watch_id = (guint) -1;
g_assert(config);
loop = g_main_loop_new(NULL, FALSE);
+
+ if (daemon_signal_init(SIGINT, SIGQUIT, SIGHUP, SIGTERM, 0) < 0) {
+ avahi_log_error("Could not register signal handlers (%s).", strerror(errno));
+ goto finish;
+ }
+
+ if (!(io = g_io_channel_unix_new(daemon_signal_fd()))) {
+ avahi_log_error( "Failed to create signal io channel.");
+ goto finish;
+ }
+
+ g_io_channel_set_close_on_unref(io, FALSE);
+ g_io_add_watch(io, G_IO_IN, signal_callback, loop);
if (simple_protocol_setup(NULL) < 0)
goto finish;
daemon_retval_send(0);
r = 0;
}
-
- g_main_loop_run(loop);
+ g_main_loop_run(loop);
finish:
if (avahi_server)
avahi_server_free(avahi_server);
+
+ daemon_signal_done();
+
+ if (watch_id != (guint) -1)
+ g_source_remove(watch_id);
+ if (io)
+ g_io_channel_unref(io);
+
+
if (loop)
g_main_loop_unref(loop);
if (r != 0 && config->daemonize)
- daemon_retval_send(0);
+ daemon_retval_send(1);
return r;
}
} else if (config.command == DAEMON_KILL) {
if (daemon_pid_file_kill_wait(SIGTERM, 5) < 0) {
- avahi_log_warn("Failed to kill daemon");
+ avahi_log_warn("Failed to kill daemon: %s", strerror(errno));
goto finish;
}
}
if (daemon_pid_file_create() < 0) {
- avahi_log_error("Failed to create PID file.");
- daemon_retval_send(1);
+ 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;
#include <glib.h>
#include <avahi-core/llist.h>
+#include <avahi-core/log.h>
#include "simple-protocol.h"
#include "main.h"
AVAHI_LLIST_HEAD(Client, clients);
guint n_clients;
+ gboolean bind_successful;
};
static Server *server = NULL;
if ((r = read(c->fd, c->inbuf + c->inbuf_length, sizeof(c->inbuf) - c->inbuf_length)) <= 0) {
if (r < 0)
- g_warning("read(): %s", strerror(errno));
+ avahi_log_warn("read(): %s", strerror(errno));
client_free(c);
return;
}
ssize_t r;
if ((r = write(c->fd, c->outbuf, c->outbuf_length)) < 0) {
- g_warning("write(): %s", strerror(errno));
+ avahi_log_warn("write(): %s", strerror(errno));
client_free(c);
return;
}
gint fd;
if ((fd = accept(s->fd, NULL, NULL)) < 0)
- g_warning("accept(): %s", strerror(errno));
+ avahi_log_warn("accept(): %s", strerror(errno));
else
client_new(s, fd);
} else if (s->poll_fd.revents)
g_assert(!server);
server = (Server*) g_source_new(&source_funcs, sizeof(Server));
+ server->bind_successful = FALSE;
server->fd = -1;
AVAHI_LLIST_HEAD_INIT(Client, server->clients);
- if (c)
- g_main_context_ref(server->context = c);
- else
- server->context = g_main_context_default();
+ g_main_context_ref(server->context = (c ? c : g_main_context_default()));
server->clients = NULL;
u = umask(0000);
if (mkdir(UNIX_SOCKET_PATH, 0755) < 0 && errno != EEXIST) {
- g_warning("mkdir(): %s", strerror(errno));
+ avahi_log_warn("mkdir(): %s", strerror(errno));
goto fail;
}
if ((server->fd = socket(PF_LOCAL, SOCK_STREAM, 0)) < 0) {
- g_warning("socket(PF_LOCAL, SOCK_STREAM, 0): %s", strerror(errno));
+ avahi_log_warn("socket(PF_LOCAL, SOCK_STREAM, 0): %s", strerror(errno));
goto fail;
}
strncpy(sa.sun_path, UNIX_SOCKET, sizeof(sa.sun_path)-1);
if (bind(server->fd, &sa, sizeof(sa)) < 0) {
- g_warning("bind(): %s", strerror(errno));
+ avahi_log_warn("bind(): %s", strerror(errno));
goto fail;
}
+
+ server->bind_successful = TRUE;
if (listen(server->fd, 2) < 0) {
- g_warning("listen(): %s", strerror(errno));
+ avahi_log_warn("listen(): %s", strerror(errno));
goto fail;
}
while (server->clients)
client_free(server->clients);
+
+ if (server->bind_successful)
+ unlink(UNIX_SOCKET);
- if (server->fd >= 0) {
- unlink(UNIX_SOCKET_PATH);
+ if (server->fd >= 0)
close(server->fd);
- }
g_main_context_unref(server->context);
+
g_source_destroy(&server->source);
g_source_unref(&server->source);