static inline void appctx_init(struct appctx *appctx)
{
appctx->st0 = appctx->st1 = appctx->st2 = 0;
+ appctx->io_release = NULL;
}
/* Tries to allocate a new appctx and initialize its main fields. The appctx
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);
+ int (*parse)(char **args, struct appctx *appctx, void *private);
int (*io_handler)(struct appctx *appctx);
+ void (*io_release)(struct appctx *appctx);
+ void *private;
};
struct cli_kw_list {
void *owner; /* pointer to upper layer's entity (eg: stream interface) */
struct act_rule *rule; /* rule associated with the applet. */
int (*io_handler)(struct appctx *appctx); /* used within the cli_io_handler when st0 = STAT_CLI_O_CUSTOM */
+ void (*io_release)(struct appctx *appctx); /* used within the cli_io_handler when st0 = STAT_CLI_O_CUSTOM,
+ if the command is terminated or the session released */
void *private;
union {
appctx->ctx.stats.flags = 0;
if ((kw = cli_find_kw(args))) {
if (kw->parse) {
- if (kw->parse(args, appctx) == 0 && kw->io_handler) {
+ if (kw->parse(args, appctx, kw->private) == 0 && kw->io_handler) {
appctx->st0 = STAT_CLI_O_CUSTOM;
appctx->io_handler = kw->io_handler;
+ appctx->io_release = kw->io_release;
}
}
} else if (strcmp(args[0], "show") == 0) {
break;
case STAT_CLI_O_CUSTOM: /* use custom pointer */
if (appctx->io_handler)
- if (appctx->io_handler(appctx))
+ if (appctx->io_handler(appctx)) {
appctx->st0 = STAT_CLI_PROMPT;
+ if (appctx->io_release) {
+ appctx->io_release(appctx);
+ appctx->io_release = NULL;
+ }
+ }
break;
default: /* abnormal state */
si->flags |= SI_FL_ERR;
*/
static void cli_release_handler(struct appctx *appctx)
{
+ if (appctx->io_release) {
+ appctx->io_release(appctx);
+ appctx->io_release = NULL;
+ }
if (appctx->st0 == STAT_CLI_O_SESS && appctx->st2 == STAT_ST_LIST) {
if (!LIST_ISEMPTY(&appctx->ctx.sess.bref.users))
LIST_DEL(&appctx->ctx.sess.bref.users);