/*
- * Copyright (C) 2005-2012 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2005-2014 Andre Noll <maan@tuebingen.mpg.de>
*
* Licensed under the GPL v2. For licencing details see COPYING.
*/
/** \file audiod_command.c Commands for para_audiod. */
+#include <netinet/in.h>
+#include <sys/socket.h>
#include <regex.h>
#include <sys/types.h>
+#include <arpa/inet.h>
+#include <sys/un.h>
+#include <netdb.h>
#include "para.h"
#include "audiod.cmdline.h"
#include "string.h"
#include "write.h"
#include "fd.h"
-#include "audiod_command_list.h"
+#include "version.h"
+#include "audiod.command_list.h"
extern struct sched sched;
extern char *stat_item_values[NUM_STAT_ITEMS];
-struct audiod_command audiod_cmds[] = {DEFINE_AUDIOD_CMD_ARRAY};
+static struct audiod_command audiod_cmds[] = {DEFINE_AUDIOD_CMD_ARRAY};
/** Iterate over the array of all audiod commands. */
#define FOR_EACH_COMMAND(c) for (c = 0; audiod_cmds[c].name; c++)
num_clients++;
return 1;
}
+
+static void close_stat_client(struct stat_client *sc)
+{
+ PARA_INFO_LOG("closing client fd %d\n", sc->fd);
+ close(sc->fd);
+ list_del(&sc->node);
+ free(sc);
+ num_clients--;
+}
+
+/**
+ * Empty the status clients list.
+ *
+ * This iterates over the list of connected status clients, closes each client
+ * file descriptor and frees the resources.
+ */
+void close_stat_clients(void)
+{
+ struct stat_client *sc, *tmp;
+
+ list_for_each_entry_safe(sc, tmp, &client_list, node)
+ close_stat_client(sc);
+ assert(num_clients == 0);
+}
+
/**
* Write a message to all connected status clients.
*
struct para_buffer *b;
list_for_each_entry_safe(sc, tmp, &client_list, node) {
- int fd = sc->fd, ret;
+ int ret;
if (!((one << item_num) & sc->item_mask))
continue;
if (!b->buf)
(void)WRITE_STATUS_ITEM(b, item_num, "%s\n",
msg? msg : "");
- ret = write(fd, b->buf, b->offset);
+ ret = write(sc->fd, b->buf, b->offset);
if (ret == b->offset)
continue;
/* write error or short write */
- close(fd);
- num_clients--;
- PARA_INFO_LOG("deleting client on fd %d\n", fd);
- list_del(&sc->node);
- free(sc);
+ close_stat_client(sc);
dump_stat_client_list();
}
free(pb.buf);
if (!strncmp(arg, "-p", 2)) {
parser_friendly = 1;
b.flags = PBF_SIZE_PREFIX;
- continue;
}
}
if (i >= argc)
return grab_client_new(fd, argc, argv, &sched);
}
-__noreturn static int com_term(int fd, __a_unused int argc, __a_unused char **argv)
+static int com_term(int fd, __a_unused int argc, __a_unused char **argv)
{
close(fd);
- clean_exit(EXIT_SUCCESS, "terminating on user request");
+ return -E_AUDIOD_TERM;
}
static int com_on(int fd, __a_unused int argc, __a_unused char **argv)
return 1;
}
+static int com_version(int fd, int argc, char **argv)
+{
+ int ret;
+ char *msg;
+
+ if (argc > 1 && strcmp(argv[1], "-v") == 0)
+ msg = make_message("%s", version_text("audiod"));
+ else
+ msg = make_message("%s\n", version_single_line("audiod"));
+ ret = client_write(fd, msg);
+ free(msg);
+ if (ret >= 0)
+ close(fd);
+ return ret;
+}
+
static int check_perms(uid_t uid)
{
int i;
if (ret < 0)
goto out;
ret = create_argv(buf, "\n", &argv);
- if (ret < 0)
+ if (ret <= 0)
goto out;
argc = ret;
//PARA_INFO_LOG("argv[0]: %s, argc = %d\n", argv[0], argc);
/**
* Send the current audiod status to all connected stat clients.
+ *
+ * \param force Whether to write unchanged items.
*/
-void audiod_status_dump(void)
+void audiod_status_dump(bool force)
{
int slot_num = get_play_time_slot_num();
char *old, *new;
old = stat_item_values[SI_PLAY_TIME];
new = get_time_string(slot_num);
if (new) {
- if (!old || strcmp(old, new)) {
+ if (force || !old || strcmp(old, new)) {
free(old);
stat_item_values[SI_PLAY_TIME] = new;
stat_client_write_item(SI_PLAY_TIME);
free(new);
}
- new = get_server_uptime_str(now);
+ new = daemon_get_uptime_str(now);
old = stat_item_values[SI_AUDIOD_UPTIME];
- if (!old || strcmp(old, new)) {
+ if (force || !old || strcmp(old, new)) {
free(old);
stat_item_values[SI_AUDIOD_UPTIME] = new;
stat_client_write_item(SI_AUDIOD_UPTIME);
old = stat_item_values[SI_AUDIOD_STATUS];
new = audiod_status_string();
- if (!old || strcmp(old, new)) {
+ if (force || !old || strcmp(old, new)) {
free(old);
stat_item_values[SI_AUDIOD_STATUS] = new;
stat_client_write_item(SI_AUDIOD_STATUS);
old = stat_item_values[SI_DECODER_FLAGS];
new = decoder_flags();
- if (!old || strcmp(old, new)) {
+ if (force || !old || strcmp(old, new)) {
free(old);
stat_item_values[SI_DECODER_FLAGS] = new;
stat_client_write_item(SI_DECODER_FLAGS);