]> git.tuebingen.mpg.de Git - paraslash.git/blobdiff - audiod_command.c
server: Remove command pointer from struct command_context.
[paraslash.git] / audiod_command.c
index 332ce85b6b199a44f076e38c4569b38692a020c8..0fe2e5f05edd39e18ed8aac3d0191daec9196026 100644 (file)
@@ -1,16 +1,22 @@
 /*
- * Copyright (C) 2005-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2005 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 "audiod.command_list.h"
 #include "list.h"
 #include "sched.h"
 #include "ggo.h"
 #include "string.h"
 #include "write.h"
 #include "fd.h"
-#include "audiod_command_list.h"
+#include "version.h"
 
 extern struct sched sched;
 extern char *stat_item_values[NUM_STAT_ITEMS];
 
+/* Defines one command of para_audiod. */
+struct audiod_command {
+       const char *name;
+       /* Pointer to the function that handles the command. */
+       int (*handler)(int, int, char **);
+       /* One-line description. */
+       const char *description;
+       /* Summary of the command line options. */
+       const char *usage;
+       /* The long help text. */
+       const char *help;
+};
 
 static struct audiod_command audiod_cmds[] = {DEFINE_AUDIOD_CMD_ARRAY};
 
@@ -109,6 +127,31 @@ static int stat_client_add(int fd, uint64_t mask, int parser_friendly)
        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.
  *
@@ -127,7 +170,7 @@ void stat_client_write_item(int item_num)
        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;
@@ -135,15 +178,11 @@ void stat_client_write_item(int item_num)
                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);
@@ -189,46 +228,6 @@ __malloc static char *audiod_status_string(void)
        return para_strdup(status);
 }
 
-static int get_play_time_slot_num(void)
-{
-       int i, oldest_slot = -1;
-       struct timeval oldest_wstime = {0, 0};
-
-       FOR_EACH_SLOT(i) {
-               struct slot_info *s = &slot[i];
-               struct timeval wstime;
-               if (!s->wns || !s->wns[0].btrn)
-                       continue;
-               btr_get_node_start(s->wns[0].btrn, &wstime);
-               if (oldest_slot >= 0 && tv_diff(&wstime, &oldest_wstime, NULL) > 0)
-                       continue;
-               oldest_wstime = wstime;
-               oldest_slot = i;
-       }
-       //PARA_CRIT_LOG("oldest slot: %d\n", oldest_slot);
-       return oldest_slot;
-}
-
-__malloc static char *decoder_flags(void)
-{
-       int i;
-       char flags[MAX_STREAM_SLOTS + 1];
-
-       FOR_EACH_SLOT(i) {
-               struct slot_info *s = &slot[i];
-               char flag = '0';
-               if (s->receiver_node)
-                       flag += 1;
-               if (s->fns)
-                       flag += 2;
-               if (s->wns)
-                       flag += 4;
-               flags[i] = flag;
-       }
-       flags[MAX_STREAM_SLOTS] = '\0';
-       return para_strdup(flags);
-}
-
 static int dump_commands(int fd)
 {
        char *buf = para_strdup(""), *tmp = NULL;
@@ -291,6 +290,7 @@ static int com_tasks(int fd, __a_unused int argc, __a_unused char **argv)
 {
        char *tl = get_task_list(&sched);
        int ret = 1;
+
        if (tl)
                ret = client_write(fd, tl);
        free(tl);
@@ -349,10 +349,10 @@ static int com_grab(int fd, int argc, char **argv)
        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)
@@ -393,14 +393,30 @@ static int com_cycle(int fd, int argc, char **argv)
        return 1;
 }
 
-static int check_perms(uid_t uid)
+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, uid_t *whitelist)
 {
        int i;
 
        if (!conf.user_allow_given)
                return 1;
        for (i = 0; i < conf.user_allow_given; i++)
-               if (uid == conf.user_allow_arg[i])
+               if (uid == whitelist[i])
                        return 1;
        return -E_UCRED_PERM;
 }
@@ -410,6 +426,7 @@ static int check_perms(uid_t uid)
  *
  * \param accept_fd The fd to accept connections on.
  * \param rfds If \a accept_fd is not set in \a rfds, do nothing.
+ * \param uid_whitelist Array of UIDs which are allowed to connect.
  *
  * This is called in each iteration of the select loop. If there is an incoming
  * connection on \a accept_fd, this function reads the command sent by the peer,
@@ -422,7 +439,7 @@ static int check_perms(uid_t uid)
  *
  * \sa para_accept(), recv_cred_buffer()
  * */
-int handle_connect(int accept_fd, fd_set *rfds)
+int handle_connect(int accept_fd, fd_set *rfds, uid_t *uid_whitelist)
 {
        int i, argc, ret, clifd;
        char buf[MAXLINE], **argv = NULL;
@@ -437,7 +454,7 @@ int handle_connect(int accept_fd, fd_set *rfds)
                goto out;
        uid = ret;
        PARA_INFO_LOG("connection from user %i, buf: %s\n",  ret, buf);
-       ret = check_perms(uid);
+       ret = check_perms(uid, uid_whitelist);
        if (ret < 0)
                goto out;
        ret = create_argv(buf, "\n", &argv);
@@ -465,16 +482,17 @@ out:
 
 /**
  * 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);
+       new = get_time_string();
        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);
@@ -482,9 +500,9 @@ void audiod_status_dump(void)
                        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);
@@ -493,7 +511,7 @@ void audiod_status_dump(void)
 
        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);
@@ -501,8 +519,8 @@ void audiod_status_dump(void)
                free(new);
 
        old = stat_item_values[SI_DECODER_FLAGS];
-       new = decoder_flags();
-       if (!old || strcmp(old, new)) {
+       new = audiod_get_decoder_flags();
+       if (force || !old || strcmp(old, new)) {
                free(old);
                stat_item_values[SI_DECODER_FLAGS] = new;
                stat_client_write_item(SI_DECODER_FLAGS);