]> git.tuebingen.mpg.de Git - paraslash.git/commitdiff
Merge commit 'meins/next' into next
authorAndre Noll <maan@systemlinux.org>
Mon, 20 Jul 2009 09:31:32 +0000 (11:31 +0200)
committerAndre Noll <maan@systemlinux.org>
Mon, 20 Jul 2009 09:31:32 +0000 (11:31 +0200)
26 files changed:
NEWS
README.afs
aac_afh.c
alsa_write.c
amp_filter.c
audiod.c
audiod.h
audiod_command.c
client.h
client_common.c
compress_filter.c
dccp_recv.c
error.h
file_write.c
filter.c
gcc-compat.h
ggo/udp_recv.ggo
http_recv.c
list.h
mm.c
mp3_afh.c
ogg_afh.c
oss_write.c
para.h
stat.c
udp_recv.c

diff --git a/NEWS b/NEWS
index 793e323408075ad857e2d17f0b56320b9c05be7f..68c3f406ece95d109e2b74283144d8d047763e1e 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -18,6 +18,7 @@ provided for conversion of the 0.3 database to the new 0.4 format.
        - mandatory rc4 encryption
        - major audio format handler cleanups
        - improved tag handling
+       - lots of new mood methods
 
 -------------------------------------------------
 0.3.5 (to be announced) "symplectic separability"
@@ -31,6 +32,7 @@ provided for conversion of the 0.3 database to the new 0.4 format.
        - --log_color actually works
        - new ls option: -d (print dates as seconds after the epoch)
        - update to gengetopt 2.22.2
+       - support for RSA keys of size > 512 bits
 
 -----------------------------------------
 0.3.4 (2009-05-07) "elliptic inheritance"
index edd2d17be98591391a7d3ceab0a820cf12b77763..46e30c4542f3ba619e8b5109ac3ddab98214623b 100644 (file)
@@ -178,18 +178,19 @@ is not set, the empty string is matched against the pattern.
        bitrate ~ <num>
        frequency ~ <num>
        channels ~ <num>
+       num_played ~ <num>
 
 Takes a comparator ~ of the set {<, =, <=, >, >=, !=} and a number
 <num>. Matches an audio file iff the condition <val> ~ <num> is
 satisfied where val is the corresponding value of the audio file
-(bitrate in kbit/s, frequency in Hz, channel count, value of the
-year tag).
+(value of the year tag, bitrate in kbit/s, frequency in Hz, channel
+count, play count).
 
 The year tag is special as its value is undefined if the audio file
 has no year tag or the content of the year tag is not a number. Such
 audio files never match. Another difference is the special treatment
 if the year tag is a two-digit number. In this case either 1900 or
-2000 are added to the tag value, depending on whether the number is
+2000 are added to the tag value depending on whether the number is
 greater than 2000 plus the current year.
 
 
index 7de737068863df6d4a6233aa52628cbf53738921..d12dfa19ca8eb59f7a47951665941d63fd8ba1a6 100644 (file)
--- a/aac_afh.c
+++ b/aac_afh.c
@@ -11,7 +11,6 @@
 /** \file aac_afh.c para_server's aac audio format handler */
 
 #include <regex.h>
-#include <osl.h>
 
 #include "para.h"
 #include "error.h"
index 3c7c03b467cb9e40a13e1d348a93600c0fdd51b3..ae8bed6d339724563e86eb899d9aa96a46f6f8e7 100644 (file)
@@ -264,4 +264,5 @@ void alsa_write_init(struct writer *w)
                .short_help = alsa_write_args_info_help,
                .detailed_help = alsa_write_args_info_detailed_help
        };
+       alsa_cmdline_parser_free(&dummy);
 }
index 63b1b9a618bcb561e9d73f2baf215dcea2e75221..e180db437c6a26fe8c978fefccdd51841cd97fd0 100644 (file)
@@ -32,19 +32,29 @@ struct private_amp_data {
 
 static ssize_t amp_convert(char *inbuf, size_t inbuf_len, struct filter_node *fn)
 {
-       size_t i, length = PARA_MIN((inbuf_len / 2) * 2,
-               (fn->bufsize - fn->loaded) / 2 * 2);
+       size_t i, length = PARA_MIN((inbuf_len / 2),
+               (fn->bufsize - fn->loaded) / 2);
        struct private_amp_data *pad = fn->private_data;
        int16_t *ip = (int16_t *)inbuf, *op = (int16_t *)(fn->buf + fn->loaded);
+       int factor = 64 + pad->amp;
 
        if (!length)
                return 0;
-       for (i = 0; i < length / 2; i++) {
-               int x = (PARA_ABS(*ip) * (64 + pad->amp)) >> 6;
-               *op++ = *ip++ > 0? PARA_MIN(x, 32767) : PARA_MAX(-x, -32768);
+
+       if (pad->amp == 0) {
+               memcpy(op, ip, length * 2);
+               goto out;
+       }
+       for (i = 0; i < length; i++) {
+               int x = (ip[i] * factor) >> 6;
+
+               op[i] = x;
+               if (op[i] != x)
+                       op[i] = (x >= 32768)? 32767 : -32768;
        }
-       fn->loaded += length;
-       return length;
+out:
+       fn->loaded += length * 2;
+       return length * 2;
 }
 
 static void amp_close(struct filter_node *fn)
index 32c839411b138406ab4bb760f8b8b9b873c1305d..27c153d791ee95983591e89176cf5917545e41df 100644 (file)
--- a/audiod.c
+++ b/audiod.c
@@ -902,8 +902,15 @@ static void command_post_select(struct sched *s, struct task *t)
 {
        int ret;
        struct command_task *ct = container_of(t, struct command_task, task);
+       static struct timeval last_status_dump;
+       struct timeval tmp;
+
+       tv_add(&last_status_dump, &(struct timeval){0, 500 * 1000}, &tmp);
+       if (tv_diff(&tmp, now, NULL) < 0) {
+               audiod_status_dump();
+               last_status_dump = *now;
+       }
 
-       audiod_status_dump();
        if (!FD_ISSET(ct->fd, &s->rfds))
                return;
        ret = handle_connect(ct->fd);
@@ -1227,7 +1234,7 @@ int main(int argc, char *argv[])
        register_task(&cmd_task->task);
        register_task(&stat_task->task);
        s.default_timeout.tv_sec = 0;
-       s.default_timeout.tv_usec = 99 * 1000;
+       s.default_timeout.tv_usec = 999 * 1000;
        ret = schedule(&s);
 
        PARA_EMERG_LOG("%s\n", para_strerror(-ret));
index 18bf48ed4ec178dcd81d4d84154ab97188f175e6..2d8fec1a24b9827ac8bd2e2ab0616639025ae14b 100644 (file)
--- a/audiod.h
+++ b/audiod.h
@@ -78,5 +78,8 @@ int handle_connect(int accept_fd);
 void audiod_status_dump(void);
 char *get_time_string(int slot_num);
 
+void stat_client_write_item(int item_num);
+void clear_and_dump_items(void);
+
 /** iterate over all slots */
 #define FOR_EACH_SLOT(_slot) for (_slot = 0; _slot < MAX_STREAM_SLOTS; _slot++)
index b3312940412a93511c4c730485e3db30a80bc9c9..2eaf26b9ca0809c28b4b0c8d2d4c20e54fb9907d 100644 (file)
@@ -13,7 +13,6 @@
 #include "para.h"
 #include "audiod.cmdline.h"
 #include "list.h"
-#include "close_on_fork.h"
 #include "sched.h"
 #include "ggo.h"
 #include "filter.h"
 
 extern char *stat_item_values[NUM_STAT_ITEMS];
 
-
-/** iterate over the array of all audiod commands */
+/** Iterate over the array of all audiod commands. */
 #define FOR_EACH_COMMAND(c) for (c = 0; audiod_cmds[c].name; c++)
 
+/** The maximal number of simultaneous connections. */
+#define MAX_STAT_CLIENTS 50
+
+/** Flags used for the stat command of para_audiod. */
+enum stat_client_flags {
+       /** Enable parser-friendly output. */
+       SCF_PARSER_FRIENDLY = 1,
+};
+
+/**
+ * Describes a status client of para_audiod.
+ *
+ * There's one such structure per audiod client that sent the 'stat' command.
+ *
+ * A status client is identified by its file descriptor.  para_audiod
+ * keeps a list of connected status clients.
+ */
+struct stat_client {
+       /** The stat client's file descriptor. */
+       int fd;
+       /** Bitmask of those status items the client is interested in. */
+       uint64_t item_mask;
+       /** See \ref stat_client flags. s*/
+       unsigned flags;
+       /** Its entry in the list of stat clients. */
+       struct list_head node;
+};
+
+static LIST_HEAD(client_list);
+static int num_clients;
+
+/** The list of all status items used by para_{server,audiod,gui}. */
+const char *status_item_list[] = {STATUS_ITEM_ARRAY};
+
+static void dump_stat_client_list(void)
+{
+       struct stat_client *sc;
+
+       list_for_each_entry(sc, &client_list, node)
+               PARA_INFO_LOG("stat client on fd %d\n", sc->fd);
+}
+/**
+ * Add a status client to the list.
+ *
+ * \param fd The file descriptor of the client.
+ * \param mask Bitfield of status items for this client.
+ * \param parser_friendly Enable parser-friendly output mode.
+ *
+ * Only those status items having the bit set in \a mask will be
+ * sent to the client.
+ *
+ * \return Positive value on success, or -E_TOO_MANY_CLIENTS if
+ * the number of connected clients exceeds #MAX_STAT_CLIENTS.
+ */
+static int stat_client_add(int fd, uint64_t mask, int parser_friendly)
+{
+       struct stat_client *new_client;
+
+       if (num_clients >= MAX_STAT_CLIENTS) {
+               PARA_ERROR_LOG("maximal number of stat clients (%d) exceeded\n",
+                       MAX_STAT_CLIENTS);
+               return -E_TOO_MANY_CLIENTS;
+       }
+       PARA_INFO_LOG("adding client on fd %d\n", fd);
+       new_client = para_calloc(sizeof(struct stat_client));
+       new_client->fd = fd;
+       new_client->item_mask = mask;
+       if (parser_friendly)
+               new_client->flags = SCF_PARSER_FRIENDLY;
+       para_list_add(&new_client->node, &client_list);
+       dump_stat_client_list();
+       num_clients++;
+       return 1;
+}
+/**
+ * Write a message to all connected status clients.
+ *
+ * \param item_num The number of the status item of \a msg.
+ *
+ * On write errors, remove the status client from the client list and close its
+ * file descriptor.
+ */
+void stat_client_write_item(int item_num)
+{
+       struct stat_client *sc, *tmp;
+       struct para_buffer pb = {.flags = 0};
+       struct para_buffer pfpb = {.flags = PBF_SIZE_PREFIX};
+       const uint64_t one = 1;
+
+       list_for_each_entry_safe(sc, tmp, &client_list, node) {
+               int fd = sc->fd, ret;
+
+               if (!((one << item_num) & sc->item_mask))
+                       continue;
+               if (write_ok(fd) > 0) {
+                       struct para_buffer *b =
+                               (sc->flags & SCF_PARSER_FRIENDLY)? &pfpb : &pb;
+                       char *msg = stat_item_values[item_num];
+                       if (!b->buf)
+                               WRITE_STATUS_ITEM(b, item_num, "%s\n",
+                                       msg? msg : "");
+                       ret = write(fd, b->buf, b->offset);
+                       if (ret == b->offset)
+                               continue;
+               }
+               /* write error or fd not ready for writing */
+               close(fd);
+               num_clients--;
+               PARA_INFO_LOG("deleting client on fd %d\n", fd);
+               list_del(&sc->node);
+               free(sc);
+               dump_stat_client_list();
+       }
+       free(pb.buf);
+       free(pfpb.buf);
+//     if (num_clients)
+//             PARA_DEBUG_LOG("%d client(s)\n", num_clients);
+}
+
+/**
+ * Check if string is a known status item.
+ *
+ * \param item Buffer containing the text to check.
+ *
+ * \return If \a item is a valid status item, the number of that status item is
+ * returned. Otherwise, this function returns \p -E_UNKNOWN_STAT_ITEM.
+ */
+static int stat_item_valid(const char *item)
+{
+       int i;
+       if (!item || !*item) {
+               PARA_ERROR_LOG("%s\n", "no item");
+               return -E_UNKNOWN_STAT_ITEM;
+       }
+       FOR_EACH_STATUS_ITEM(i)
+               if (!strcmp(status_item_list[i], item))
+                       return i;
+       PARA_ERROR_LOG("invalid stat item: %s\n", item);
+       return -E_UNKNOWN_STAT_ITEM;
+}
+
 static int client_write(int fd, const char *buf)
 {
        size_t len;
index fa965c354997ff9fef38ebba8b8220412ffeab84..5fc336827f4ba187d7b6171a4daeb057806d865d 100644 (file)
--- a/client.h
+++ b/client.h
@@ -61,8 +61,6 @@ struct client_task {
        int check_r;
        /** non-zero if the pre_select hook added \p fd to the write fd set */
        int check_w;
-       /** the decrypted challenge */
-       long unsigned challenge_nr;
        /** pointer to the data to be sent to para_server */
        char *inbuf;
        /** number of bytes loaded in \p inbuf */
index eb053581b8975de8360cf72aa47d7c4bfefcb9a5..108867bdec594444cf8eaf80629f981c35bcc461 100644 (file)
@@ -141,7 +141,6 @@ static ssize_t client_recv_buffer(struct client_task *ct)
 static void client_post_select(struct sched *s, struct task *t)
 {
        struct client_task *ct = container_of(t, struct client_task, task);
-       unsigned char crypt_buf[1024];
 
        t->error = 0;
        if (ct->rc4c.fd < 0)
@@ -172,23 +171,26 @@ static void client_post_select(struct sched *s, struct task *t)
                t->error = client_recv_buffer(ct);
                if (t->error < 0)
                        goto err;
-               PARA_INFO_LOG("<-- [challenge] (%d bytes)\n", t->error);
-               /* decrypt challenge/rc4 buffer  */
+               ct->loaded = t->error;
+               PARA_INFO_LOG("<-- [challenge] (%d bytes)\n", ct->loaded);
+               ct->status = CL_RECEIVED_CHALLENGE;
+               return;
+       case CL_RECEIVED_CHALLENGE:
+               {
+               /* decrypted challenge/rc4 buffer */
+               unsigned char crypt_buf[1024];
+               /* the SHA1 of the decrypted challenge */
+               unsigned char challenge_sha1[HASH_SIZE];
+
                t->error = para_decrypt_buffer(ct->key_file, crypt_buf,
-                       (unsigned char *)ct->buf, t->error);
+                       (unsigned char *)ct->buf, ct->loaded);
                if (t->error < 0)
                        goto err;
-               ct->status = CL_RECEIVED_CHALLENGE;
+               sha1_hash((char *)crypt_buf, CHALLENGE_SIZE, challenge_sha1);
                RC4_set_key(&ct->rc4c.send_key, RC4_KEY_LEN,
                        crypt_buf + CHALLENGE_SIZE);
                RC4_set_key(&ct->rc4c.recv_key, RC4_KEY_LEN,
                        crypt_buf + CHALLENGE_SIZE + RC4_KEY_LEN);
-               return;
-       case CL_RECEIVED_CHALLENGE:
-               {
-               unsigned char challenge_sha1[HASH_SIZE];
-               /* send sha1 of decrypted challenge */
-               sha1_hash((char *)crypt_buf, CHALLENGE_SIZE, challenge_sha1);
                hash_to_asc(challenge_sha1, ct->buf);
                PARA_INFO_LOG("--> %s\n", ct->buf);
                t->error = send_bin_buffer(ct->rc4c.fd, (char *)challenge_sha1,
index 2e263e87b0c6af2da12bd6226affe9f1b733e944..7bad4c25debac02e16f2df75a6f98530fd666e3b 100644 (file)
@@ -53,7 +53,7 @@ static ssize_t compress(char *inbuf, size_t inbuf_len, struct filter_node *fn)
                /* be careful in that heat, my dear */
                int sample = *ip++, adjusted_sample = (PARA_ABS(sample) *
                        pcd->current_gain) >> gain_shift;
-               if (unlikely(adjusted_sample > 32767)) { /* clip */
+               if (adjusted_sample > 32767) { /* clip */
                        PARA_NOTICE_LOG("clip: sample: %d, adjusted sample: %d\n",
                                sample, adjusted_sample);
                        adjusted_sample = 32767;
@@ -63,7 +63,7 @@ static ssize_t compress(char *inbuf, size_t inbuf_len, struct filter_node *fn)
                } else
                        pcd->peak = PARA_MAX(pcd->peak, adjusted_sample);
                *op++ = sample >= 0? adjusted_sample : -adjusted_sample;
-               if (likely(++pcd->num_samples & mask))
+               if (++pcd->num_samples & mask)
                        continue;
 //             PARA_DEBUG_LOG("gain: %u, peak: %u\n", pcd->current_gain,
 //                     pcd->peak);
index 4d4ac86db31cb28f1d2d1d9f081f13dc8a139dcc..58c969a255335461d0481e8864ec79fb41269dac 100644 (file)
@@ -158,4 +158,5 @@ void dccp_recv_init(struct receiver *r)
                .short_help = dccp_recv_args_info_help,
                .detailed_help = dccp_recv_args_info_detailed_help
        };
+       dccp_recv_cmdline_parser_free(&dummy);
 }
diff --git a/error.h b/error.h
index c9031f8201695f49fa95dd9b9047228196d581a8..d9133aa1317647c4bbf70f8052a8dff213f7f665 100644 (file)
--- a/error.h
+++ b/error.h
@@ -229,6 +229,8 @@ extern const char **para_errlist[];
        PARA_ERROR(AUDIOD_SYNTAX, "syntax error"), \
        PARA_ERROR(UCRED_PERM, "permission denied"), \
        PARA_ERROR(INVALID_AUDIOD_CMD, "invalid command"), \
+       PARA_ERROR(TOO_MANY_CLIENTS, "maximal number of stat clients exceeded"), \
+       PARA_ERROR(UNKNOWN_STAT_ITEM, "status item not recognized"), \
 
 
 #define FILTER_COMMON_ERRORS \
@@ -238,8 +240,6 @@ extern const char **para_errlist[];
 
 
 #define STAT_ERRORS \
-       PARA_ERROR(TOO_MANY_CLIENTS, "maximal number of stat clients exceeded"), \
-       PARA_ERROR(UNKNOWN_STAT_ITEM, "status item not recognized"), \
        PARA_ERROR(STAT_ITEM_PARSE, "failed to parse status item"), \
 
 
index 3286ea87a089363036cabe518a98ef16151e12ca..9a4f0707f6f213f1fc88346b0aa2c039bebfa003 100644 (file)
@@ -142,4 +142,5 @@ void file_write_init(struct writer *w)
                .short_help = file_write_args_info_help,
                .detailed_help = file_write_args_info_detailed_help
        };
+       file_cmdline_parser_free(&dummy);
 }
index 99b12217b8cc1e701c428928478a03a00ccd0c74..e6c75556b91e5ecc0c3ca1f005f5471056bdfb7a 100644 (file)
--- a/filter.c
+++ b/filter.c
@@ -62,6 +62,15 @@ static void open_filters(void)
        }
 }
 
+static void free_filter_confs(void)
+{
+       int i;
+       struct filter_node *fn;
+
+       FOR_EACH_FILTER_NODE(fn, fc, i)
+               free(fn->conf);
+}
+
 static int init_filter_chain(void)
 {
        int i, ret;
@@ -70,7 +79,7 @@ static int init_filter_chain(void)
        if (!conf.filter_given)
                return -E_NO_FILTERS;
        fc->num_filters = conf.filter_given;
-       fc->filter_nodes = para_malloc(fc->num_filters * sizeof(struct filter_node));
+       fc->filter_nodes = para_calloc(fc->num_filters * sizeof(struct filter_node));
        fc->inbufp = &sit->buf;
        fc->in_loaded = &sit->loaded;
        fc->input_error = &sit->task.error;
@@ -93,6 +102,7 @@ static int init_filter_chain(void)
        open_filters();
        return 1;
 err:
+       free_filter_confs();
        free(fc->filter_nodes);
        return ret;
 }
@@ -181,6 +191,7 @@ int main(int argc, char *argv[])
        s.default_timeout.tv_sec = 1;
        s.default_timeout.tv_usec = 0;
        ret = schedule(&s);
+       free_filter_confs();
        close_filters(fc);
 out:
        free(sit->buf);
index 61c3c88d1c4551a965aaa22c626ddf8fabec31ba..1cd30af2fc7219cb132aa9d0631518e4c6efa942 100644 (file)
@@ -2,11 +2,9 @@
 # define __noreturn    __attribute__ ((noreturn))
 # define __malloc      __attribute__ ((malloc))
 # define __a_unused    __attribute__ ((unused))
-# define likely(x)     __builtin_expect (!!(x), 1)
-# define unlikely(x)   __builtin_expect (!!(x), 0)
-/* 
- * p is the number of the "format string" parameter, and q is 
- * the number of the first variadic parameter 
+/*
+ * p is the number of the "format string" parameter, and q is
+ * the number of the first variadic parameter.
  */
 # define __printf(p,q) __attribute__ ((format (printf, p, q)))
 /*
index f19d319440192bad3a7af5e1ce34212f2b92438a..4c37eace5affa02a9cdb90e1aecbe65a12e9e184 100644 (file)
@@ -3,7 +3,7 @@ option "host" i
 string default="224.0.1.38"
 optional
 details="
-       The default address resoves to DANTZ.MCAST.NET and activates
+       The default address resolves to DANTZ.MCAST.NET and activates
        multicast.
 "
 
index f644233ba1ed1adb63fe9f21cf675ff319b5531d..13e9ede23d4d3cda0dcea71fbeef9dc0602dbd6f 100644 (file)
@@ -204,4 +204,5 @@ void http_recv_init(struct receiver *r)
                .short_help = http_recv_args_info_help,
                .detailed_help = http_recv_args_info_detailed_help
        };
+       http_recv_cmdline_parser_free(&dummy);
 }
diff --git a/list.h b/list.h
index de04ab9eed1184451f5338b06a7a2be9106aac5d..db2e84908130676e22f346eedea116254786146d 100644 (file)
--- a/list.h
+++ b/list.h
@@ -33,6 +33,10 @@ struct list_head {
        struct list_head *prev;
 };
 
+/** Define an initialized list head. */
+#define LIST_HEAD(name) struct list_head name = { &(name), &(name) }
+
+
 /** must be called before using any other list functions */
 #define INIT_LIST_HEAD(ptr) do { \
        (ptr)->next = (ptr); (ptr)->prev = (ptr); \
diff --git a/mm.c b/mm.c
index 4f76d40f306f1de0706617c04e27dd3281e7ff40..885b6307d80bfc86664f1933daef52988260574b 100644 (file)
--- a/mm.c
+++ b/mm.c
@@ -187,6 +187,14 @@ static int mm_channels_score_function(__a_unused const char *path,
        return mm_compare_num_score_function(afhi->channels, private);
 }
 
+static int mm_num_played_score_function(__a_unused const char *path,
+               const struct afs_info *afsi,
+               __a_unused const struct afh_info *afhi,
+               const void *private)
+{
+       return mm_compare_num_score_function(afsi->num_played, private);
+}
+
 struct mm_year_data {
        /** Comparator and year given at the mood line. */
        struct mm_compare_num_data *cnd;
@@ -343,5 +351,6 @@ const struct mood_method mood_methods[] = {
        {DEFINE_COMPARE_NUM_MOOD_METHOD(bitrate)},
        {DEFINE_COMPARE_NUM_MOOD_METHOD(frequency)},
        {DEFINE_COMPARE_NUM_MOOD_METHOD(channels)},
+       {DEFINE_COMPARE_NUM_MOOD_METHOD(num_played)},
        {.parser = NULL}
 };
index 5eacf63bea0d35b32966fdfcdd2577c1784f01d1..d0be0ad95459390e37879870b349e88783618509 100644 (file)
--- a/mp3_afh.c
+++ b/mp3_afh.c
@@ -17,7 +17,6 @@
  */
 
 #include <regex.h>
-#include <osl.h>
 
 #include "para.h"
 #include "error.h"
index 65573cfccf08c4e853231ade26509d8c3ee5c278..4e64f062e5e5f6a09d9629c491e1fab4b0a91ecb 100644 (file)
--- a/ogg_afh.c
+++ b/ogg_afh.c
@@ -10,7 +10,6 @@
 #include <ogg/ogg.h>
 #include <vorbis/codec.h>
 #include <vorbis/vorbisfile.h>
-#include <osl.h>
 
 #include "para.h"
 #include "error.h"
index 103b14ea5fa16c68feeb10302454e41570673dc7..9ec85560d29ebef00f269a95ca2fda49e9c427d1 100644 (file)
@@ -217,4 +217,5 @@ void oss_write_init(struct writer *w)
                .short_help = oss_write_args_info_help,
                .detailed_help = oss_write_args_info_detailed_help
        };
+       oss_cmdline_parser_free(&dummy);
 }
diff --git a/para.h b/para.h
index 66cf9e48d2fa7fb5e5df56ece15ef30df89427a2..c4c73a3f37661565037fc72ffbf03dc9bef8f20b 100644 (file)
--- a/para.h
+++ b/para.h
@@ -181,12 +181,8 @@ enum status_items {STATUS_ITEM_ENUM NUM_STAT_ITEMS};
 extern const char *status_item_list[];
 /** Loop over each status item. */
 #define FOR_EACH_STATUS_ITEM(i) for (i = 0; i < NUM_STAT_ITEMS; i++)
-int stat_item_valid(const char *item);
-void stat_client_write_item(int item_num);
-int stat_client_add(int fd, uint64_t mask, int parser_friendly);
 int for_each_stat_item(char *item_buf, size_t num_bytes,
        int (*item_handler)(int, char *));
-void clear_and_dump_items(void);
 
 __printf_2_3 void para_log(int, const char*, ...);
 
diff --git a/stat.c b/stat.c
index 03d00d771d622a8fb67ad07a99584ee150550b1f..27ffab5e04160343be9781a328a6d760865008d8 100644 (file)
--- a/stat.c
+++ b/stat.c
  */
 
 #include <regex.h>
-#include <sys/types.h>
-#include <dirent.h>
 
 #include "para.h"
-#include "close_on_fork.h"
-#include "list.h"
 #include "error.h"
 #include "string.h"
-#include "fd.h"
 
-/** The maximal number of simultaneous connections. */
-#define MAX_STAT_CLIENTS 50
-
-extern char *stat_item_values[NUM_STAT_ITEMS];
-
-/** Flags used for the stat command of para_audiod. */
-enum stat_client_flags {
-       /** Enable parser-friendly output. */
-       SCF_PARSER_FRIENDLY = 1,
-};
-
-/**
- * Describes a status client of para_audiod.
- *
- * There's one such structure per audiod client that sent the 'stat' command.
- *
- * A status client is identified by its file descriptor.  para_audiod
- * keeps a list of connected status clients.
- */
-struct stat_client {
-       /** The stat client's file descriptor. */
-       int fd;
-       /** Bitmask of those status items the client is interested in. */
-       uint64_t item_mask;
-       /** See \ref stat_client flags. s*/
-       unsigned flags;
-       /** Its entry in the list of stat clients. */
-       struct list_head node;
-};
-
-static struct list_head client_list;
-static int initialized;
-static int num_clients;
-
-/** The list of all status items used by para_{server,audiod,gui}. */
-const char *status_item_list[] = {STATUS_ITEM_ARRAY};
-
-static void dump_stat_client_list(void)
-{
-       struct stat_client *sc;
-
-       if (!initialized)
-               return;
-       list_for_each_entry(sc, &client_list, node)
-               PARA_INFO_LOG("stat client on fd %d\n", sc->fd);
-}
-/**
- * Add a status client to the list.
- *
- * \param fd The file descriptor of the client.
- * \param mask Bitfield of status items for this client.
- * \param parser_friendly Enable parser-friendly output mode.
- *
- * Only those status items having the bit set in \a mask will be
- * sent to the client.
- *
- * \return Positive value on success, or -E_TOO_MANY_CLIENTS if
- * the number of connected clients exceeds #MAX_STAT_CLIENTS.
- */
-int stat_client_add(int fd, uint64_t mask, int parser_friendly)
-{
-       struct stat_client *new_client;
-
-       if (num_clients >= MAX_STAT_CLIENTS) {
-               PARA_ERROR_LOG("maximal number of stat clients (%d) exceeded\n",
-                       MAX_STAT_CLIENTS);
-               return -E_TOO_MANY_CLIENTS;
-       }
-       if (!initialized) {
-               INIT_LIST_HEAD(&client_list);
-               initialized = 1;
-       }
-       PARA_INFO_LOG("adding client on fd %d\n", fd);
-       new_client = para_calloc(sizeof(struct stat_client));
-       new_client->fd = fd;
-       new_client->item_mask = mask;
-       if (parser_friendly)
-               new_client->flags = SCF_PARSER_FRIENDLY;
-       para_list_add(&new_client->node, &client_list);
-       dump_stat_client_list();
-       num_clients++;
-       return 1;
-}
-/**
- * Write a message to all connected status clients.
- *
- * \param item_num The number of the status item of \a msg.
- *
- * On write errors, remove the status client from the client list and close its
- * file descriptor.
- */
-void stat_client_write_item(int item_num)
-{
-       struct stat_client *sc, *tmp;
-       struct para_buffer pb = {.flags = 0};
-       struct para_buffer pfpb = {.flags = PBF_SIZE_PREFIX};
-       const uint64_t one = 1;
-
-       if (!initialized)
-               return;
-       list_for_each_entry_safe(sc, tmp, &client_list, node) {
-               int fd = sc->fd, ret;
-
-               if (!((one << item_num) & sc->item_mask))
-                       continue;
-               if (write_ok(fd) > 0) {
-                       struct para_buffer *b =
-                               (sc->flags & SCF_PARSER_FRIENDLY)? &pfpb : &pb;
-                       char *msg = stat_item_values[item_num];
-                       if (!b->buf)
-                               WRITE_STATUS_ITEM(b, item_num, "%s\n",
-                                       msg? msg : "");
-                       ret = write(fd, b->buf, b->offset);
-                       if (ret == b->offset)
-                               continue;
-               }
-               /* write error or fd not ready for writing */
-               close(fd);
-               num_clients--;
-               PARA_INFO_LOG("deleting client on fd %d\n", fd);
-               list_del(&sc->node);
-               free(sc);
-               dump_stat_client_list();
-       }
-       free(pb.buf);
-       free(pfpb.buf);
-//     if (num_clients)
-//             PARA_DEBUG_LOG("%d client(s)\n", num_clients);
-}
-
-/**
- * Check if string is a known status item.
- *
- * \param item Buffer containing the text to check.
- *
- * \return If \a item is a valid status item, the number of that status item is
- * returned. Otherwise, this function returns \p -E_UNKNOWN_STAT_ITEM.
- */
-int stat_item_valid(const char *item)
-{
-       int i;
-       if (!item || !*item) {
-               PARA_ERROR_LOG("%s\n", "no item");
-               return -E_UNKNOWN_STAT_ITEM;
-       }
-       FOR_EACH_STATUS_ITEM(i)
-               if (!strcmp(status_item_list[i], item))
-                       return i;
-       PARA_ERROR_LOG("invalid stat item: %s\n", item);
-       return -E_UNKNOWN_STAT_ITEM;
-}
 
 /** The minimal length of a status item buffer. */
 #define MIN_STAT_ITEM_LEN 9 /* 5 + 2 + 2, e.g. '0005 00:\n' */
index 7bbd4b0c575a351055170bab1df3f186769c6783..f9782985d113d390c70300d099546066203f188d 100644 (file)
@@ -239,4 +239,5 @@ void udp_recv_init(struct receiver *r)
                .short_help = udp_recv_args_info_help,
                .detailed_help = udp_recv_args_info_detailed_help
        };
+       udp_recv_cmdline_parser_free(&dummy);
 }