MEDIUM: cli: Add payload support
In order to use arbitrary data in the CLI (multiple lines or group of words that must be considered as a whole, for example), it is now possible to add a payload to the commands. To do so, the first line needs to end with a special pattern: <<\n. Everything that follows will be left untouched by the CLI parser and will be passed to the commands parsers. Per-command support will need to be added to take advantage of this feature. Signed-off-by: Aurlien Nephtali <aurelien.nephtali@corp.ovh.com>
This commit is contained in:
parent
799f51801a
commit
abbf607105
@ -1298,6 +1298,18 @@ delimiter to mark an end of output for each command, and takes care of ensuring
|
||||
that no command can emit an empty line on output. A script can thus easily
|
||||
parse the output even when multiple commands were pipelined on a single line.
|
||||
|
||||
Some commands may take an optional payload. To add one to a command, the first
|
||||
line needs to end with the "<<\n" pattern. The next lines will be treated as
|
||||
the payload and can contain as many lines as needed. To validate a command with
|
||||
a payload, it needs to end with an empty line.
|
||||
|
||||
Limitations do exist: the length of the whole buffer passed to the CLI must
|
||||
not be greater than tune.bfsize and the pattern "<<" must not be glued to the
|
||||
last word of the line.
|
||||
|
||||
When entering a paylod while in interactive mode, the prompt will change from
|
||||
"> " to "+ ".
|
||||
|
||||
It is important to understand that when multiple haproxy processes are started
|
||||
on the same sockets, any process may pick up the request and will output its
|
||||
own stats.
|
||||
|
@ -43,11 +43,13 @@ static int inline appctx_res_wakeup(struct appctx *appctx);
|
||||
|
||||
/* Initializes all required fields for a new appctx. Note that it does the
|
||||
* minimum acceptable initialization for an appctx. This means only the
|
||||
* 3 integer states st0, st1, st2 are zeroed.
|
||||
* 3 integer states st0, st1, st2 and the chunk used to gather unfinished
|
||||
* commands are zeroed
|
||||
*/
|
||||
static inline void appctx_init(struct appctx *appctx, unsigned long thread_mask)
|
||||
{
|
||||
appctx->st0 = appctx->st1 = appctx->st2 = 0;
|
||||
appctx->chunk = NULL;
|
||||
appctx->io_release = NULL;
|
||||
appctx->thread_mask = thread_mask;
|
||||
appctx->state = APPLET_SLEEPING;
|
||||
|
@ -24,7 +24,6 @@
|
||||
#define _PROTO_CLI_H
|
||||
|
||||
|
||||
struct cli_kw* cli_find_kw(char **args);
|
||||
void cli_register_kw(struct cli_kw_list *kw_list);
|
||||
|
||||
int cli_has_level(struct appctx *appctx, int level);
|
||||
|
@ -50,6 +50,9 @@ struct applet {
|
||||
#define APPLET_WOKEN_UP 0x02 /* applet was running and requested to woken up again */
|
||||
#define APPLET_WANT_DIE 0x04 /* applet was running and requested to die */
|
||||
|
||||
#define APPCTX_CLI_ST1_PROMPT (1 << 0)
|
||||
#define APPCTX_CLI_ST1_PAYLOAD (1 << 1)
|
||||
|
||||
/* Context of a running applet. */
|
||||
struct appctx {
|
||||
struct list runq; /* chaining in the applet run queue */
|
||||
@ -57,7 +60,8 @@ struct appctx {
|
||||
/* 3 unused bytes here */
|
||||
unsigned short state; /* Internal appctx state */
|
||||
unsigned int st0; /* CLI state for stats, session state for peers */
|
||||
unsigned int st1; /* prompt for stats, session error for peers */
|
||||
unsigned int st1; /* prompt/payload (bitwise OR of APPCTX_CLI_ST1_*) for stats, session error for peers */
|
||||
struct chunk *chunk; /* used to store unfinished commands */
|
||||
unsigned int st2; /* output state for stats, unused by peers */
|
||||
struct applet *applet; /* applet this context refers to */
|
||||
void *owner; /* pointer to upper layer's entity (eg: stream interface) */
|
||||
|
@ -27,7 +27,7 @@ struct cli_kw {
|
||||
const char *str_kw[5]; /* keywords ended by NULL, limited to 5
|
||||
separated keywords combination */
|
||||
const char *usage; /* usage message */
|
||||
int (*parse)(char **args, struct appctx *appctx, void *private);
|
||||
int (*parse)(char **args, char *payload, struct appctx *appctx, void *private);
|
||||
int (*io_handler)(struct appctx *appctx);
|
||||
void (*io_release)(struct appctx *appctx);
|
||||
void *private;
|
||||
|
@ -952,7 +952,7 @@ struct flt_ops cache_ops = {
|
||||
|
||||
};
|
||||
|
||||
static int cli_parse_show_cache(char **args, struct appctx *appctx, void *private)
|
||||
static int cli_parse_show_cache(char **args, char *payload, struct appctx *appctx, void *private)
|
||||
{
|
||||
if (!cli_has_level(appctx, ACCESS_LVL_ADMIN))
|
||||
return 1;
|
||||
|
301
src/cli.c
301
src/cli.c
@ -67,6 +67,8 @@
|
||||
#include <proto/task.h>
|
||||
#include <proto/proto_udp.h>
|
||||
|
||||
#define PAYLOAD_PATTERN "<<"
|
||||
|
||||
static struct applet cli_applet;
|
||||
|
||||
static const char stats_sock_usage_msg[] =
|
||||
@ -90,7 +92,7 @@ static struct cli_kw_list cli_keywords = {
|
||||
|
||||
extern const char *stat_status_codes[];
|
||||
|
||||
char *cli_gen_usage_msg()
|
||||
static char *cli_gen_usage_msg(struct appctx *appctx)
|
||||
{
|
||||
struct cli_kw_list *kw_list;
|
||||
struct cli_kw *kw;
|
||||
@ -101,7 +103,7 @@ char *cli_gen_usage_msg()
|
||||
dynamic_usage_msg = NULL;
|
||||
|
||||
if (LIST_ISEMPTY(&cli_keywords.list))
|
||||
return NULL;
|
||||
goto end;
|
||||
|
||||
chunk_reset(tmp);
|
||||
chunk_strcat(tmp, stats_sock_usage_msg);
|
||||
@ -115,6 +117,18 @@ char *cli_gen_usage_msg()
|
||||
chunk_init(&out, NULL, 0);
|
||||
chunk_dup(&out, tmp);
|
||||
dynamic_usage_msg = out.str;
|
||||
|
||||
end:
|
||||
if (dynamic_usage_msg) {
|
||||
appctx->ctx.cli.severity = LOG_INFO;
|
||||
appctx->ctx.cli.msg = dynamic_usage_msg;
|
||||
}
|
||||
else {
|
||||
appctx->ctx.cli.severity = LOG_INFO;
|
||||
appctx->ctx.cli.msg = stats_sock_usage_msg;
|
||||
}
|
||||
appctx->st0 = CLI_ST_PRINT;
|
||||
|
||||
return dynamic_usage_msg;
|
||||
}
|
||||
|
||||
@ -379,62 +393,70 @@ static int cli_get_severity_output(struct appctx *appctx)
|
||||
* If a keyword parser is NULL and an I/O handler is declared, the I/O handler
|
||||
* will automatically be used.
|
||||
*/
|
||||
static int cli_parse_request(struct appctx *appctx, char *line)
|
||||
static int cli_parse_request(struct appctx *appctx)
|
||||
{
|
||||
char *args[MAX_STATS_ARGS + 1];
|
||||
char *args[MAX_STATS_ARGS + 1], *p, *end, *payload = NULL;
|
||||
int i = 0;
|
||||
struct cli_kw *kw;
|
||||
int arg;
|
||||
int i, j;
|
||||
|
||||
while (isspace((unsigned char)*line))
|
||||
line++;
|
||||
|
||||
arg = 0;
|
||||
args[arg] = line;
|
||||
|
||||
while (*line && arg < MAX_STATS_ARGS) {
|
||||
if (*line == '\\') {
|
||||
line++;
|
||||
if (*line == '\0')
|
||||
break;
|
||||
}
|
||||
else if (isspace((unsigned char)*line)) {
|
||||
*line++ = '\0';
|
||||
|
||||
while (isspace((unsigned char)*line))
|
||||
line++;
|
||||
|
||||
args[++arg] = line;
|
||||
continue;
|
||||
}
|
||||
|
||||
line++;
|
||||
}
|
||||
|
||||
while (++arg <= MAX_STATS_ARGS)
|
||||
args[arg] = line;
|
||||
|
||||
/* unescape '\' */
|
||||
arg = 0;
|
||||
while (arg <= MAX_STATS_ARGS && *args[arg] != '\0') {
|
||||
j = 0;
|
||||
for (i=0; args[arg][i] != '\0'; i++) {
|
||||
if (args[arg][i] == '\\') {
|
||||
if (args[arg][i+1] == '\\')
|
||||
i++;
|
||||
else
|
||||
continue;
|
||||
}
|
||||
args[arg][j] = args[arg][i];
|
||||
j++;
|
||||
}
|
||||
args[arg][j] = '\0';
|
||||
arg++;
|
||||
}
|
||||
|
||||
appctx->st2 = 0;
|
||||
memset(&appctx->ctx.cli, 0, sizeof(appctx->ctx.cli));
|
||||
|
||||
p = appctx->chunk->str;
|
||||
end = p + appctx->chunk->len;
|
||||
|
||||
/*
|
||||
* Get the payload start if there is one.
|
||||
* For the sake of simplicity, the payload pattern is looked up
|
||||
* everywhere from the start of the input but it can only be found
|
||||
* at the end of the first line if APPCTX_CLI_ST1_PAYLOAD is set.
|
||||
*
|
||||
* The input string was zero terminated so it is safe to use
|
||||
* the str*() functions throughout the parsing
|
||||
*/
|
||||
if (appctx->st1 & APPCTX_CLI_ST1_PAYLOAD) {
|
||||
payload = strstr(p, PAYLOAD_PATTERN);
|
||||
end = payload;
|
||||
/* skip the pattern */
|
||||
payload += strlen(PAYLOAD_PATTERN);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get pointers on words.
|
||||
* One extra slot is reserved to store a pointer on a null byte.
|
||||
*/
|
||||
while (i < MAX_STATS_ARGS && p < end) {
|
||||
int j, k;
|
||||
|
||||
/* skip leading spaces/tabs */
|
||||
p += strspn(p, " \t");
|
||||
if (!*p)
|
||||
break;
|
||||
|
||||
args[i] = p;
|
||||
p += strcspn(p, " \t");
|
||||
*p++ = 0;
|
||||
|
||||
/* unescape backslashes (\) */
|
||||
for (j = 0, k = 0; args[i][k]; k++) {
|
||||
if (args[i][k] == '\\') {
|
||||
if (args[i][k + 1] == '\\')
|
||||
k++;
|
||||
else
|
||||
continue;
|
||||
}
|
||||
args[i][j] = args[i][k];
|
||||
j++;
|
||||
}
|
||||
args[i][j] = 0;
|
||||
|
||||
i++;
|
||||
}
|
||||
/* fill unused slots */
|
||||
p = appctx->chunk->str + appctx->chunk->len;
|
||||
for (; i < MAX_STATS_ARGS + 1; i++)
|
||||
args[i] = p;
|
||||
|
||||
kw = cli_find_kw(args);
|
||||
if (!kw)
|
||||
return 0;
|
||||
@ -442,7 +464,7 @@ static int cli_parse_request(struct appctx *appctx, char *line)
|
||||
appctx->io_handler = kw->io_handler;
|
||||
appctx->io_release = kw->io_release;
|
||||
/* kw->parse could set its own io_handler or ip_release handler */
|
||||
if ((!kw->parse || kw->parse(args, appctx, kw->private) == 0) && appctx->io_handler) {
|
||||
if ((!kw->parse || kw->parse(args, payload, appctx, kw->private) == 0) && appctx->io_handler) {
|
||||
appctx->st0 = CLI_ST_CALLBACK;
|
||||
}
|
||||
return 1;
|
||||
@ -519,9 +541,23 @@ static void cli_io_handler(struct appctx *appctx)
|
||||
* side, the conditions below will complete if needed.
|
||||
*/
|
||||
si_shutw(si);
|
||||
free_trash_chunk(appctx->chunk);
|
||||
break;
|
||||
}
|
||||
else if (appctx->st0 == CLI_ST_GETREQ) {
|
||||
char *str;
|
||||
|
||||
/* use a trash chunk to store received data */
|
||||
if (!appctx->chunk) {
|
||||
appctx->chunk = alloc_trash_chunk();
|
||||
if (!appctx->chunk) {
|
||||
appctx->st0 = CLI_ST_END;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
str = appctx->chunk->str + appctx->chunk->len;
|
||||
|
||||
/* ensure we have some output room left in the event we
|
||||
* would want to return some info right after parsing.
|
||||
*/
|
||||
@ -530,7 +566,8 @@ static void cli_io_handler(struct appctx *appctx)
|
||||
break;
|
||||
}
|
||||
|
||||
reql = co_getline(si_oc(si), trash.str, trash.size);
|
||||
/* '- 1' is to ensure a null byte can always be inserted at the end */
|
||||
reql = co_getline(si_oc(si), str, appctx->chunk->size - appctx->chunk->len - 1);
|
||||
if (reql <= 0) { /* closed or EOL not found */
|
||||
if (reql == 0)
|
||||
break;
|
||||
@ -538,18 +575,20 @@ static void cli_io_handler(struct appctx *appctx)
|
||||
continue;
|
||||
}
|
||||
|
||||
/* seek for a possible unescaped semi-colon. If we find
|
||||
* one, we replace it with an LF and skip only this part.
|
||||
*/
|
||||
for (len = 0; len < reql; len++) {
|
||||
if (trash.str[len] == '\\') {
|
||||
len++;
|
||||
continue;
|
||||
}
|
||||
if (trash.str[len] == ';') {
|
||||
trash.str[len] = '\n';
|
||||
reql = len + 1;
|
||||
break;
|
||||
if (!(appctx->st1 & APPCTX_CLI_ST1_PAYLOAD)) {
|
||||
/* seek for a possible unescaped semi-colon. If we find
|
||||
* one, we replace it with an LF and skip only this part.
|
||||
*/
|
||||
for (len = 0; len < reql; len++) {
|
||||
if (str[len] == '\\') {
|
||||
len++;
|
||||
continue;
|
||||
}
|
||||
if (str[len] == ';') {
|
||||
str[len] = '\n';
|
||||
reql = len + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -558,56 +597,58 @@ static void cli_io_handler(struct appctx *appctx)
|
||||
* line.
|
||||
*/
|
||||
len = reql - 1;
|
||||
if (trash.str[len] != '\n') {
|
||||
if (str[len] != '\n') {
|
||||
appctx->st0 = CLI_ST_END;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (len && trash.str[len-1] == '\r')
|
||||
if (len && str[len-1] == '\r')
|
||||
len--;
|
||||
|
||||
trash.str[len] = '\0';
|
||||
str[len] = '\0';
|
||||
appctx->chunk->len += len;
|
||||
|
||||
if (appctx->st1 & APPCTX_CLI_ST1_PAYLOAD) {
|
||||
appctx->chunk->str[appctx->chunk->len] = '\n';
|
||||
appctx->chunk->str[appctx->chunk->len + 1] = 0;
|
||||
appctx->chunk->len++;
|
||||
}
|
||||
|
||||
appctx->st0 = CLI_ST_PROMPT;
|
||||
if (len) {
|
||||
if (strcmp(trash.str, "quit") == 0) {
|
||||
appctx->st0 = CLI_ST_END;
|
||||
continue;
|
||||
|
||||
if (appctx->st1 & APPCTX_CLI_ST1_PAYLOAD) {
|
||||
/* empty line */
|
||||
if (!len) {
|
||||
/* remove the last two \n */
|
||||
appctx->chunk->len -= 2;
|
||||
appctx->chunk->str[appctx->chunk->len] = 0;
|
||||
|
||||
if (!cli_parse_request(appctx))
|
||||
cli_gen_usage_msg(appctx);
|
||||
|
||||
chunk_reset(appctx->chunk);
|
||||
/* NB: cli_sock_parse_request() may have put
|
||||
* another CLI_ST_O_* into appctx->st0.
|
||||
*/
|
||||
|
||||
appctx->st1 &= ~APPCTX_CLI_ST1_PAYLOAD;
|
||||
}
|
||||
else if (strcmp(trash.str, "prompt") == 0)
|
||||
appctx->st1 = !appctx->st1;
|
||||
else if (strcmp(trash.str, "help") == 0 ||
|
||||
!cli_parse_request(appctx, trash.str)) {
|
||||
cli_gen_usage_msg();
|
||||
if (dynamic_usage_msg) {
|
||||
appctx->ctx.cli.severity = LOG_INFO;
|
||||
appctx->ctx.cli.msg = dynamic_usage_msg;
|
||||
}
|
||||
else {
|
||||
appctx->ctx.cli.severity = LOG_INFO;
|
||||
appctx->ctx.cli.msg = stats_sock_usage_msg;
|
||||
}
|
||||
appctx->st0 = CLI_ST_PRINT;
|
||||
}
|
||||
/* NB: stats_sock_parse_request() may have put
|
||||
* another CLI_ST_O_* into appctx->st0.
|
||||
*/
|
||||
}
|
||||
else if (!appctx->st1) {
|
||||
/* if prompt is disabled, print help on empty lines,
|
||||
* so that the user at least knows how to enable
|
||||
* prompt and find help.
|
||||
else {
|
||||
/*
|
||||
* Look for the "payload start" pattern at the end of a line
|
||||
* Its location is not remembered here, this is just to switch
|
||||
* to a gathering mode.
|
||||
*/
|
||||
cli_gen_usage_msg();
|
||||
if (dynamic_usage_msg) {
|
||||
appctx->ctx.cli.severity = LOG_INFO;
|
||||
appctx->ctx.cli.msg = dynamic_usage_msg;
|
||||
}
|
||||
if (!strcmp(appctx->chunk->str + appctx->chunk->len - strlen(PAYLOAD_PATTERN), PAYLOAD_PATTERN))
|
||||
appctx->st1 |= APPCTX_CLI_ST1_PAYLOAD;
|
||||
else {
|
||||
appctx->ctx.cli.severity = LOG_INFO;
|
||||
appctx->ctx.cli.msg = stats_sock_usage_msg;
|
||||
/* no payload, the command is complete: parse the request */
|
||||
if (!cli_parse_request(appctx))
|
||||
cli_gen_usage_msg(appctx);
|
||||
|
||||
chunk_reset(appctx->chunk);
|
||||
}
|
||||
appctx->st0 = CLI_ST_PRINT;
|
||||
}
|
||||
|
||||
/* re-adjust req buffer */
|
||||
@ -656,7 +697,24 @@ static void cli_io_handler(struct appctx *appctx)
|
||||
|
||||
/* The post-command prompt is either LF alone or LF + '> ' in interactive mode */
|
||||
if (appctx->st0 == CLI_ST_PROMPT) {
|
||||
if (ci_putstr(si_ic(si), appctx->st1 ? "\n> " : "\n") != -1)
|
||||
const char *prompt = "";
|
||||
|
||||
if (appctx->st1 & APPCTX_CLI_ST1_PROMPT) {
|
||||
/*
|
||||
* when entering a payload with interactive mode, change the prompt
|
||||
* to emphasize that more data can still be sent
|
||||
*/
|
||||
if (appctx->chunk->len && appctx->st1 & APPCTX_CLI_ST1_PAYLOAD)
|
||||
prompt = "+ ";
|
||||
else
|
||||
prompt = "\n> ";
|
||||
}
|
||||
else {
|
||||
if (!(appctx->st1 & APPCTX_CLI_ST1_PAYLOAD))
|
||||
prompt = "\n";
|
||||
}
|
||||
|
||||
if (ci_putstr(si_ic(si), prompt) != -1)
|
||||
appctx->st0 = CLI_ST_GETREQ;
|
||||
else
|
||||
si_applet_cant_put(si);
|
||||
@ -671,7 +729,7 @@ static void cli_io_handler(struct appctx *appctx)
|
||||
* buffer is empty. This still allows pipelined requests
|
||||
* to be sent in non-interactive mode.
|
||||
*/
|
||||
if ((res->flags & (CF_SHUTW|CF_SHUTW_NOW)) || (!appctx->st1 && !req->buf->o)) {
|
||||
if ((res->flags & (CF_SHUTW|CF_SHUTW_NOW)) || (!(appctx->st1 & APPCTX_CLI_ST1_PROMPT) && !req->buf->o)) {
|
||||
appctx->st0 = CLI_ST_END;
|
||||
continue;
|
||||
}
|
||||
@ -1020,7 +1078,7 @@ static int cli_io_handler_show_cli_sock(struct appctx *appctx)
|
||||
* wants to stop here. It puts the variable to be dumped into cli.p0 if a single
|
||||
* variable is requested otherwise puts environ there.
|
||||
*/
|
||||
static int cli_parse_show_env(char **args, struct appctx *appctx, void *private)
|
||||
static int cli_parse_show_env(char **args, char *payload, struct appctx *appctx, void *private)
|
||||
{
|
||||
extern char **environ;
|
||||
char **var;
|
||||
@ -1054,7 +1112,7 @@ static int cli_parse_show_env(char **args, struct appctx *appctx, void *private)
|
||||
* wants to stop here. It puts the FD number into cli.i0 if a specific FD is
|
||||
* requested and sets st2 to STAT_ST_END, otherwise leaves 0 in i0.
|
||||
*/
|
||||
static int cli_parse_show_fd(char **args, struct appctx *appctx, void *private)
|
||||
static int cli_parse_show_fd(char **args, char *payload, struct appctx *appctx, void *private)
|
||||
{
|
||||
if (!cli_has_level(appctx, ACCESS_LVL_OPER))
|
||||
return 1;
|
||||
@ -1069,7 +1127,7 @@ static int cli_parse_show_fd(char **args, struct appctx *appctx, void *private)
|
||||
}
|
||||
|
||||
/* parse a "set timeout" CLI request. It always returns 1. */
|
||||
static int cli_parse_set_timeout(char **args, struct appctx *appctx, void *private)
|
||||
static int cli_parse_set_timeout(char **args, char *payload, struct appctx *appctx, void *private)
|
||||
{
|
||||
struct stream_interface *si = appctx->owner;
|
||||
struct stream *s = si_strm(si);
|
||||
@ -1106,7 +1164,7 @@ static int cli_parse_set_timeout(char **args, struct appctx *appctx, void *priva
|
||||
}
|
||||
|
||||
/* parse a "set maxconn global" command. It always returns 1. */
|
||||
static int cli_parse_set_maxconn_global(char **args, struct appctx *appctx, void *private)
|
||||
static int cli_parse_set_maxconn_global(char **args, char *payload, struct appctx *appctx, void *private)
|
||||
{
|
||||
int v;
|
||||
|
||||
@ -1159,7 +1217,7 @@ static int set_severity_output(int *target, char *argument)
|
||||
}
|
||||
|
||||
/* parse a "set severity-output" command. */
|
||||
static int cli_parse_set_severity_output(char **args, struct appctx *appctx, void *private)
|
||||
static int cli_parse_set_severity_output(char **args, char *payload, struct appctx *appctx, void *private)
|
||||
{
|
||||
if (*args[2] && set_severity_output(&appctx->cli_severity_output, args[2]))
|
||||
return 0;
|
||||
@ -1170,13 +1228,13 @@ static int cli_parse_set_severity_output(char **args, struct appctx *appctx, voi
|
||||
return 1;
|
||||
}
|
||||
|
||||
int cli_parse_default(char **args, struct appctx *appctx, void *private)
|
||||
int cli_parse_default(char **args, char *payload, struct appctx *appctx, void *private)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* parse a "set rate-limit" command. It always returns 1. */
|
||||
static int cli_parse_set_ratelimit(char **args, struct appctx *appctx, void *private)
|
||||
static int cli_parse_set_ratelimit(char **args, char *payload, struct appctx *appctx, void *private)
|
||||
{
|
||||
int v;
|
||||
int *res;
|
||||
@ -1296,7 +1354,7 @@ static int bind_parse_severity_output(char **args, int cur_arg, struct proxy *px
|
||||
}
|
||||
|
||||
/* Send all the bound sockets, always returns 1 */
|
||||
static int _getsocks(char **args, struct appctx *appctx, void *private)
|
||||
static int _getsocks(char **args, char *payload, struct appctx *appctx, void *private)
|
||||
{
|
||||
char *cmsgbuf = NULL;
|
||||
unsigned char *tmpbuf = NULL;
|
||||
@ -1474,6 +1532,20 @@ out:
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int cli_parse_simple(char **args, char *payload, struct appctx *appctx, void *private)
|
||||
{
|
||||
if (*args[0] == 'h')
|
||||
/* help */
|
||||
cli_gen_usage_msg(appctx);
|
||||
else if (*args[0] == 'p')
|
||||
/* prompt */
|
||||
appctx->st1 ^= APPCTX_CLI_ST1_PROMPT;
|
||||
else if (*args[0] == 'q')
|
||||
/* quit */
|
||||
appctx->st0 = CLI_ST_END;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static struct applet cli_applet = {
|
||||
@ -1485,6 +1557,9 @@ static struct applet cli_applet = {
|
||||
|
||||
/* register cli keywords */
|
||||
static struct cli_kw_list cli_kws = {{ },{
|
||||
{ { "help", NULL }, NULL, cli_parse_simple, NULL },
|
||||
{ { "prompt", NULL }, NULL, cli_parse_simple, NULL },
|
||||
{ { "quit", NULL }, NULL, cli_parse_simple, NULL },
|
||||
{ { "set", "maxconn", "global", NULL }, "set maxconn global : change the per-process maxconn setting", cli_parse_set_maxconn_global, NULL },
|
||||
{ { "set", "rate-limit", NULL }, "set rate-limit : change a rate limiting value", cli_parse_set_ratelimit, NULL },
|
||||
{ { "set", "severity-output", NULL }, "set severity-output [none|number|string] : set presence of severity level in feedback information", cli_parse_set_severity_output, NULL, NULL },
|
||||
|
@ -1948,7 +1948,7 @@ static int dns_finalize_config(void)
|
||||
}
|
||||
|
||||
/* if an arg is found, it sets the resolvers section pointer into cli.p0 */
|
||||
static int cli_parse_stat_resolvers(char **args, struct appctx *appctx, void *private)
|
||||
static int cli_parse_stat_resolvers(char **args, char *payload, struct appctx *appctx, void *private)
|
||||
{
|
||||
struct dns_resolvers *presolvers;
|
||||
|
||||
|
@ -6926,7 +6926,7 @@ __LJMP static int hlua_register_service(lua_State *L)
|
||||
/* This function initialises Lua cli handler. It copies the
|
||||
* arguments in the Lua stack and create channel IO objects.
|
||||
*/
|
||||
static int hlua_cli_parse_fct(char **args, struct appctx *appctx, void *private)
|
||||
static int hlua_cli_parse_fct(char **args, char *payload, struct appctx *appctx, void *private)
|
||||
{
|
||||
struct hlua *hlua;
|
||||
struct hlua_function *fcn;
|
||||
|
12
src/map.c
12
src/map.c
@ -565,7 +565,7 @@ static void cli_release_mlook(struct appctx *appctx)
|
||||
}
|
||||
|
||||
|
||||
static int cli_parse_get_map(char **args, struct appctx *appctx, void *private)
|
||||
static int cli_parse_get_map(char **args, char *payload, struct appctx *appctx, void *private)
|
||||
{
|
||||
if (strcmp(args[1], "map") == 0 || strcmp(args[1], "acl") == 0) {
|
||||
/* Set flags. */
|
||||
@ -632,7 +632,7 @@ static void cli_release_show_map(struct appctx *appctx)
|
||||
}
|
||||
}
|
||||
|
||||
static int cli_parse_show_map(char **args, struct appctx *appctx, void *private)
|
||||
static int cli_parse_show_map(char **args, char *payload, struct appctx *appctx, void *private)
|
||||
{
|
||||
if (strcmp(args[1], "map") == 0 ||
|
||||
strcmp(args[1], "acl") == 0) {
|
||||
@ -672,7 +672,7 @@ static int cli_parse_show_map(char **args, struct appctx *appctx, void *private)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cli_parse_set_map(char **args, struct appctx *appctx, void *private)
|
||||
static int cli_parse_set_map(char **args, char *payload, struct appctx *appctx, void *private)
|
||||
{
|
||||
if (strcmp(args[1], "map") == 0) {
|
||||
char *err;
|
||||
@ -772,7 +772,7 @@ static int cli_parse_set_map(char **args, struct appctx *appctx, void *private)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int cli_parse_add_map(char **args, struct appctx *appctx, void *private)
|
||||
static int cli_parse_add_map(char **args, char *payload, struct appctx *appctx, void *private)
|
||||
{
|
||||
if (strcmp(args[1], "map") == 0 ||
|
||||
strcmp(args[1], "acl") == 0) {
|
||||
@ -862,7 +862,7 @@ static int cli_parse_add_map(char **args, struct appctx *appctx, void *private)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cli_parse_del_map(char **args, struct appctx *appctx, void *private)
|
||||
static int cli_parse_del_map(char **args, char *payload, struct appctx *appctx, void *private)
|
||||
{
|
||||
if (args[1][0] == 'm')
|
||||
appctx->ctx.map.display_flags = PAT_REF_MAP;
|
||||
@ -958,7 +958,7 @@ static int cli_parse_del_map(char **args, struct appctx *appctx, void *private)
|
||||
}
|
||||
|
||||
|
||||
static int cli_parse_clear_map(char **args, struct appctx *appctx, void *private)
|
||||
static int cli_parse_clear_map(char **args, char *payload, struct appctx *appctx, void *private)
|
||||
{
|
||||
if (strcmp(args[1], "map") == 0 || strcmp(args[1], "acl") == 0) {
|
||||
/* Set ACL or MAP flags. */
|
||||
|
@ -12489,7 +12489,7 @@ struct action_kw *action_http_res_custom(const char *kw)
|
||||
/* "show errors" handler for the CLI. Returns 0 if wants to continue, 1 to stop
|
||||
* now.
|
||||
*/
|
||||
static int cli_parse_show_errors(char **args, struct appctx *appctx, void *private)
|
||||
static int cli_parse_show_errors(char **args, char *payload, struct appctx *appctx, void *private)
|
||||
{
|
||||
if (!cli_has_level(appctx, ACCESS_LVL_OPER))
|
||||
return 1;
|
||||
|
16
src/proxy.c
16
src/proxy.c
@ -1393,7 +1393,7 @@ struct proxy *cli_find_backend(struct appctx *appctx, const char *arg)
|
||||
* 1 if it stops immediately. If an argument is specified, it will set the proxy
|
||||
* pointer into cli.p0 and its ID into cli.i0.
|
||||
*/
|
||||
static int cli_parse_show_servers(char **args, struct appctx *appctx, void *private)
|
||||
static int cli_parse_show_servers(char **args, char *payload, struct appctx *appctx, void *private)
|
||||
{
|
||||
struct proxy *px;
|
||||
|
||||
@ -1558,7 +1558,7 @@ static int cli_io_handler_show_backend(struct appctx *appctx)
|
||||
}
|
||||
|
||||
/* Parses the "enable dynamic-cookies backend" directive, it always returns 1 */
|
||||
static int cli_parse_enable_dyncookie_backend(char **args, struct appctx *appctx, void *private)
|
||||
static int cli_parse_enable_dyncookie_backend(char **args, char *payload, struct appctx *appctx, void *private)
|
||||
{
|
||||
struct proxy *px;
|
||||
struct server *s;
|
||||
@ -1579,7 +1579,7 @@ static int cli_parse_enable_dyncookie_backend(char **args, struct appctx *appctx
|
||||
}
|
||||
|
||||
/* Parses the "disable dynamic-cookies backend" directive, it always returns 1 */
|
||||
static int cli_parse_disable_dyncookie_backend(char **args, struct appctx *appctx, void *private)
|
||||
static int cli_parse_disable_dyncookie_backend(char **args, char *payload, struct appctx *appctx, void *private)
|
||||
{
|
||||
struct proxy *px;
|
||||
struct server *s;
|
||||
@ -1604,7 +1604,7 @@ static int cli_parse_disable_dyncookie_backend(char **args, struct appctx *appct
|
||||
}
|
||||
|
||||
/* Parses the "set dynamic-cookie-key backend" directive, it always returns 1 */
|
||||
static int cli_parse_set_dyncookie_key_backend(char **args, struct appctx *appctx, void *private)
|
||||
static int cli_parse_set_dyncookie_key_backend(char **args, char *payload, struct appctx *appctx, void *private)
|
||||
{
|
||||
struct proxy *px;
|
||||
struct server *s;
|
||||
@ -1641,7 +1641,7 @@ static int cli_parse_set_dyncookie_key_backend(char **args, struct appctx *appct
|
||||
}
|
||||
|
||||
/* Parses the "set maxconn frontend" directive, it always returns 1 */
|
||||
static int cli_parse_set_maxconn_frontend(char **args, struct appctx *appctx, void *private)
|
||||
static int cli_parse_set_maxconn_frontend(char **args, char *payload, struct appctx *appctx, void *private)
|
||||
{
|
||||
struct proxy *px;
|
||||
struct listener *l;
|
||||
@ -1686,7 +1686,7 @@ static int cli_parse_set_maxconn_frontend(char **args, struct appctx *appctx, vo
|
||||
}
|
||||
|
||||
/* Parses the "shutdown frontend" directive, it always returns 1 */
|
||||
static int cli_parse_shutdown_frontend(char **args, struct appctx *appctx, void *private)
|
||||
static int cli_parse_shutdown_frontend(char **args, char *payload, struct appctx *appctx, void *private)
|
||||
{
|
||||
struct proxy *px;
|
||||
|
||||
@ -1713,7 +1713,7 @@ static int cli_parse_shutdown_frontend(char **args, struct appctx *appctx, void
|
||||
}
|
||||
|
||||
/* Parses the "disable frontend" directive, it always returns 1 */
|
||||
static int cli_parse_disable_frontend(char **args, struct appctx *appctx, void *private)
|
||||
static int cli_parse_disable_frontend(char **args, char *payload, struct appctx *appctx, void *private)
|
||||
{
|
||||
struct proxy *px;
|
||||
|
||||
@ -1748,7 +1748,7 @@ static int cli_parse_disable_frontend(char **args, struct appctx *appctx, void *
|
||||
}
|
||||
|
||||
/* Parses the "enable frontend" directive, it always returns 1 */
|
||||
static int cli_parse_enable_frontend(char **args, struct appctx *appctx, void *private)
|
||||
static int cli_parse_enable_frontend(char **args, char *payload, struct appctx *appctx, void *private)
|
||||
{
|
||||
struct proxy *px;
|
||||
|
||||
|
20
src/server.c
20
src/server.c
@ -4088,7 +4088,7 @@ struct server *cli_find_server(struct appctx *appctx, char *arg)
|
||||
}
|
||||
|
||||
|
||||
static int cli_parse_set_server(char **args, struct appctx *appctx, void *private)
|
||||
static int cli_parse_set_server(char **args, char *payload, struct appctx *appctx, void *private)
|
||||
{
|
||||
struct server *sv;
|
||||
const char *warning;
|
||||
@ -4271,7 +4271,7 @@ static int cli_parse_set_server(char **args, struct appctx *appctx, void *privat
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int cli_parse_get_weight(char **args, struct appctx *appctx, void *private)
|
||||
static int cli_parse_get_weight(char **args, char *payload, struct appctx *appctx, void *private)
|
||||
{
|
||||
struct stream_interface *si = appctx->owner;
|
||||
struct proxy *px;
|
||||
@ -4309,7 +4309,7 @@ static int cli_parse_get_weight(char **args, struct appctx *appctx, void *privat
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int cli_parse_set_weight(char **args, struct appctx *appctx, void *private)
|
||||
static int cli_parse_set_weight(char **args, char *payload, struct appctx *appctx, void *private)
|
||||
{
|
||||
struct server *sv;
|
||||
const char *warning;
|
||||
@ -4331,7 +4331,7 @@ static int cli_parse_set_weight(char **args, struct appctx *appctx, void *privat
|
||||
}
|
||||
|
||||
/* parse a "set maxconn server" command. It always returns 1. */
|
||||
static int cli_parse_set_maxconn_server(char **args, struct appctx *appctx, void *private)
|
||||
static int cli_parse_set_maxconn_server(char **args, char *payload, struct appctx *appctx, void *private)
|
||||
{
|
||||
struct server *sv;
|
||||
const char *warning;
|
||||
@ -4353,7 +4353,7 @@ static int cli_parse_set_maxconn_server(char **args, struct appctx *appctx, void
|
||||
}
|
||||
|
||||
/* parse a "disable agent" command. It always returns 1. */
|
||||
static int cli_parse_disable_agent(char **args, struct appctx *appctx, void *private)
|
||||
static int cli_parse_disable_agent(char **args, char *payload, struct appctx *appctx, void *private)
|
||||
{
|
||||
struct server *sv;
|
||||
|
||||
@ -4369,7 +4369,7 @@ static int cli_parse_disable_agent(char **args, struct appctx *appctx, void *pri
|
||||
}
|
||||
|
||||
/* parse a "disable health" command. It always returns 1. */
|
||||
static int cli_parse_disable_health(char **args, struct appctx *appctx, void *private)
|
||||
static int cli_parse_disable_health(char **args, char *payload, struct appctx *appctx, void *private)
|
||||
{
|
||||
struct server *sv;
|
||||
|
||||
@ -4385,7 +4385,7 @@ static int cli_parse_disable_health(char **args, struct appctx *appctx, void *pr
|
||||
}
|
||||
|
||||
/* parse a "disable server" command. It always returns 1. */
|
||||
static int cli_parse_disable_server(char **args, struct appctx *appctx, void *private)
|
||||
static int cli_parse_disable_server(char **args, char *payload, struct appctx *appctx, void *private)
|
||||
{
|
||||
struct server *sv;
|
||||
|
||||
@ -4401,7 +4401,7 @@ static int cli_parse_disable_server(char **args, struct appctx *appctx, void *pr
|
||||
}
|
||||
|
||||
/* parse a "enable agent" command. It always returns 1. */
|
||||
static int cli_parse_enable_agent(char **args, struct appctx *appctx, void *private)
|
||||
static int cli_parse_enable_agent(char **args, char *payload, struct appctx *appctx, void *private)
|
||||
{
|
||||
struct server *sv;
|
||||
|
||||
@ -4424,7 +4424,7 @@ static int cli_parse_enable_agent(char **args, struct appctx *appctx, void *priv
|
||||
}
|
||||
|
||||
/* parse a "enable health" command. It always returns 1. */
|
||||
static int cli_parse_enable_health(char **args, struct appctx *appctx, void *private)
|
||||
static int cli_parse_enable_health(char **args, char *payload, struct appctx *appctx, void *private)
|
||||
{
|
||||
struct server *sv;
|
||||
|
||||
@ -4440,7 +4440,7 @@ static int cli_parse_enable_health(char **args, struct appctx *appctx, void *pri
|
||||
}
|
||||
|
||||
/* parse a "enable server" command. It always returns 1. */
|
||||
static int cli_parse_enable_server(char **args, struct appctx *appctx, void *private)
|
||||
static int cli_parse_enable_server(char **args, char *payload, struct appctx *appctx, void *private)
|
||||
{
|
||||
struct server *sv;
|
||||
|
||||
|
@ -8500,7 +8500,7 @@ static int cli_io_handler_tlskeys_files(struct appctx *appctx) {
|
||||
}
|
||||
|
||||
/* sets cli.i0 to non-zero if only file lists should be dumped */
|
||||
static int cli_parse_show_tlskeys(char **args, struct appctx *appctx, void *private)
|
||||
static int cli_parse_show_tlskeys(char **args, char *payload, struct appctx *appctx, void *private)
|
||||
{
|
||||
/* no parameter, shows only file list */
|
||||
if (!*args[2]) {
|
||||
@ -8525,7 +8525,7 @@ static int cli_parse_show_tlskeys(char **args, struct appctx *appctx, void *priv
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cli_parse_set_tlskeys(char **args, struct appctx *appctx, void *private)
|
||||
static int cli_parse_set_tlskeys(char **args, char *payload, struct appctx *appctx, void *private)
|
||||
{
|
||||
struct tls_keys_ref *ref;
|
||||
|
||||
@ -8561,7 +8561,7 @@ static int cli_parse_set_tlskeys(char **args, struct appctx *appctx, void *priva
|
||||
}
|
||||
#endif
|
||||
|
||||
static int cli_parse_set_ocspresponse(char **args, struct appctx *appctx, void *private)
|
||||
static int cli_parse_set_ocspresponse(char **args, char *payload, struct appctx *appctx, void *private)
|
||||
{
|
||||
#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
|
||||
char *err = NULL;
|
||||
|
@ -3524,7 +3524,7 @@ static int stats_dump_json_schema_to_buffer(struct stream_interface *si)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int cli_parse_clear_counters(char **args, struct appctx *appctx, void *private)
|
||||
static int cli_parse_clear_counters(char **args, char *payload, struct appctx *appctx, void *private)
|
||||
{
|
||||
struct proxy *px;
|
||||
struct server *sv;
|
||||
@ -3586,7 +3586,7 @@ static int cli_parse_clear_counters(char **args, struct appctx *appctx, void *pr
|
||||
}
|
||||
|
||||
|
||||
static int cli_parse_show_info(char **args, struct appctx *appctx, void *private)
|
||||
static int cli_parse_show_info(char **args, char *payload, struct appctx *appctx, void *private)
|
||||
{
|
||||
appctx->ctx.stats.scope_str = 0;
|
||||
appctx->ctx.stats.scope_len = 0;
|
||||
@ -3600,7 +3600,7 @@ static int cli_parse_show_info(char **args, struct appctx *appctx, void *private
|
||||
}
|
||||
|
||||
|
||||
static int cli_parse_show_stat(char **args, struct appctx *appctx, void *private)
|
||||
static int cli_parse_show_stat(char **args, char *payload, struct appctx *appctx, void *private)
|
||||
{
|
||||
appctx->ctx.stats.scope_str = 0;
|
||||
appctx->ctx.stats.scope_len = 0;
|
||||
|
@ -3375,7 +3375,7 @@ static int table_prepare_data_request(struct appctx *appctx, char **args)
|
||||
}
|
||||
|
||||
/* returns 0 if wants to be called, 1 if has ended processing */
|
||||
static int cli_parse_table_req(char **args, struct appctx *appctx, void *private)
|
||||
static int cli_parse_table_req(char **args, char *payload, struct appctx *appctx, void *private)
|
||||
{
|
||||
appctx->ctx.table.data_type = -1;
|
||||
appctx->ctx.table.target = NULL;
|
||||
|
@ -3025,7 +3025,7 @@ static int stats_dump_full_strm_to_buffer(struct stream_interface *si, struct st
|
||||
}
|
||||
|
||||
|
||||
static int cli_parse_show_sess(char **args, struct appctx *appctx, void *private)
|
||||
static int cli_parse_show_sess(char **args, char *payload, struct appctx *appctx, void *private)
|
||||
{
|
||||
if (!cli_has_level(appctx, ACCESS_LVL_OPER))
|
||||
return 1;
|
||||
@ -3280,7 +3280,7 @@ static void cli_release_show_sess(struct appctx *appctx)
|
||||
}
|
||||
|
||||
/* Parses the "shutdown session" directive, it always returns 1 */
|
||||
static int cli_parse_shutdown_session(char **args, struct appctx *appctx, void *private)
|
||||
static int cli_parse_shutdown_session(char **args, char *payload, struct appctx *appctx, void *private)
|
||||
{
|
||||
struct stream *strm, *ptr;
|
||||
|
||||
@ -3315,7 +3315,7 @@ static int cli_parse_shutdown_session(char **args, struct appctx *appctx, void *
|
||||
}
|
||||
|
||||
/* Parses the "shutdown session server" directive, it always returns 1 */
|
||||
static int cli_parse_shutdown_sessions_server(char **args, struct appctx *appctx, void *private)
|
||||
static int cli_parse_shutdown_sessions_server(char **args, char *payload, struct appctx *appctx, void *private)
|
||||
{
|
||||
struct server *sv;
|
||||
struct stream *strm, *strm_bck;
|
||||
|
Loading…
x
Reference in New Issue
Block a user