This was 4 out of 5 and thus should decrease the size of executables for non-Linux
systems a bit as we don't use -fdata-sections -ffunction-sections and -Wl,--gc-sections
there.
Is also allows to remove some entries from para.h.
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++)
#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 struct list_head client_list;
+static int client_list_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 (!client_list_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.
+ */
+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;
+ }
+ if (!client_list_initialized) {
+ INIT_LIST_HEAD(&client_list);
+ 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 (!client_list_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.
+ */
+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;
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 \
#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"), \
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*, ...);
*/
#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' */