|
|
|
|
@ -34,12 +34,19 @@
|
|
|
|
|
#include "media_player.h"
|
|
|
|
|
|
|
|
|
|
typedef struct cli_handler_t cli_handler_t;
|
|
|
|
|
typedef struct cli_command_t cli_command_t;
|
|
|
|
|
typedef void (*cli_handler_func)(str *, struct cli_writer *, const cli_handler_t *);
|
|
|
|
|
struct cli_handler_t {
|
|
|
|
|
|
|
|
|
|
struct cli_command_t {
|
|
|
|
|
const char *cmd;
|
|
|
|
|
cli_handler_func handler;
|
|
|
|
|
const cli_handler_t *next;
|
|
|
|
|
};
|
|
|
|
|
struct cli_handler_t {
|
|
|
|
|
unsigned int section;
|
|
|
|
|
const cli_command_t *commands;
|
|
|
|
|
unsigned int num_commands;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static void cli_generic_handler(str *instr, struct cli_writer *cw, const cli_handler_t *);
|
|
|
|
|
static void cli_incoming_terminate(str *instr, struct cli_writer *cw, const cli_handler_t *);
|
|
|
|
|
@ -135,10 +142,10 @@ static void cli_incoming_media_evict_players(str *instr, struct cli_writer *cw,
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define HANDLER_START(n) static const cli_handler_t n[] = {
|
|
|
|
|
#define HANDLER_CMD(c, f) { .cmd = c, .handler = f, },
|
|
|
|
|
#define HANDLER_GENERIC(c, h) { .cmd = c, .handler = cli_generic_handler, .next = h, },
|
|
|
|
|
#define HANDLER_END { NULL, } };
|
|
|
|
|
#define HANDLER_START(n) static const cli_handler_t n = { .section = CSH_SECTION, .commands = (const struct cli_command_t []) {
|
|
|
|
|
#define HANDLER_CMD(c, f) [CSH_LOOKUP(c)] = { .cmd = c, .handler = f },
|
|
|
|
|
#define HANDLER_GENERIC(c, h) [CSH_LOOKUP(c)] = { .cmd = c, .handler = cli_generic_handler, .next = &h },
|
|
|
|
|
#define HANDLER_END }, .num_commands = CSH_NUM_LOOKUPS };
|
|
|
|
|
|
|
|
|
|
HANDLER_START(cli_set_handlers)
|
|
|
|
|
HANDLER_CMD("maxopenfiles", cli_incoming_set_maxopenfiles)
|
|
|
|
|
@ -274,40 +281,29 @@ static void cli_list_tag_info(struct cli_writer *cw, struct call_monologue *ml);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void cli_handler_do(const cli_handler_t *handlers, str *instr,
|
|
|
|
|
static void cli_handler_do(const cli_handler_t *handler, str *instr,
|
|
|
|
|
struct cli_writer *cw)
|
|
|
|
|
{
|
|
|
|
|
const cli_handler_t *h;
|
|
|
|
|
|
|
|
|
|
if (!str_cmp(instr, "help")) {
|
|
|
|
|
cw->cw_printf(cw, "Available sub-commands at this level:\n");
|
|
|
|
|
for (h = handlers; h->cmd; h++)
|
|
|
|
|
cw->cw_printf(cw, "\t%s\n", h->cmd);
|
|
|
|
|
for (unsigned int i = 0; i < handler->num_commands; i++)
|
|
|
|
|
cw->cw_printf(cw, "\t%s\n", handler->commands[i].cmd);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (h = handlers; h->cmd; h++) {
|
|
|
|
|
if (str_shift_cmp(instr, h->cmd))
|
|
|
|
|
continue;
|
|
|
|
|
// check if followed by space or newline or end of line
|
|
|
|
|
if (instr->len) {
|
|
|
|
|
if (instr->s[0] == ' ') {
|
|
|
|
|
while (instr->len && instr->s[0] == ' ')
|
|
|
|
|
str_shift(instr, 1);
|
|
|
|
|
}
|
|
|
|
|
else if (instr->s[0] == '\n' || instr->s[0] == '\r')
|
|
|
|
|
instr->len = 0;
|
|
|
|
|
else {
|
|
|
|
|
// not a match. rewind and continue
|
|
|
|
|
str_unshift(instr, strlen(h->cmd));
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
h->handler(instr, cw, h);
|
|
|
|
|
str cmd;
|
|
|
|
|
if (!str_token_sep(&cmd, instr, ' ')) {
|
|
|
|
|
cw->cw_printf(cw, "Incomplete command: " STR_FORMAT "\n", STR_FMT(instr));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int val = __csh_lookup_section(handler->section, &cmd);
|
|
|
|
|
if (val < 0 || val >= handler->num_commands) {
|
|
|
|
|
cw->cw_printf(cw, "Unknown command: " STR_FORMAT "\n", STR_FMT(&cmd));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cw->cw_printf(cw, "Unknown or incomplete command: " STR_FORMAT "\n", STR_FMT(instr));
|
|
|
|
|
handler->commands[val].handler(instr, cw, handler->commands[val].next);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void destroy_own_foreign_calls(bool foreign_call, unsigned int uint_keyspace_db) {
|
|
|
|
|
@ -1045,7 +1041,7 @@ static void cli_generic_handler(str *instr, struct cli_writer *cw, const cli_han
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cli_handler_do(handler->next, instr, cw);
|
|
|
|
|
cli_handler_do(handler, instr, cw);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void cli_incoming_terminate(str *instr, struct cli_writer *cw, const cli_handler_t *handler) {
|
|
|
|
|
@ -1305,7 +1301,7 @@ static void cli_stream_readable(struct streambuf_stream *s) {
|
|
|
|
|
|
|
|
|
|
void cli_handle(str *instr, struct cli_writer *cw) {
|
|
|
|
|
ilogs(control, LOG_INFO, "Got CLI command: " STR_FORMAT_M, STR_FMT_M(instr));
|
|
|
|
|
cli_handler_do(cli_top_handlers, instr, cw);
|
|
|
|
|
cli_handler_do(&cli_top_handlers, instr, cw);
|
|
|
|
|
release_closed_sockets();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -1530,7 +1526,7 @@ static void cli_incoming_call(str *instr, struct cli_writer *cw, const cli_handl
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cli_handler_do(cli_call_handlers, instr, cw);
|
|
|
|
|
cli_handler_do(&cli_call_handlers, instr, cw);
|
|
|
|
|
|
|
|
|
|
if (cw->call) {
|
|
|
|
|
rwlock_unlock_w(&cw->call->master_lock);
|
|
|
|
|
@ -1590,7 +1586,7 @@ static void cli_incoming_call_tag(str *instr, struct cli_writer *cw, const cli_h
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cli_handler_do(cli_tag_handlers, instr, cw);
|
|
|
|
|
cli_handler_do(&cli_tag_handlers, instr, cw);
|
|
|
|
|
|
|
|
|
|
cw->ml = NULL;
|
|
|
|
|
}
|
|
|
|
|
|