MINOR: cli: add private pointer and release function

This pointer will be used for storing private context. With this,
the same executed function can handle more than one keyword. This
will be very useful for creation Lua cli bindings.

The release function is called when the command is terminated (give
back the hand to the prompt) or when the session is broken (timeout
or client closed).
diff --git a/include/proto/applet.h b/include/proto/applet.h
index b256816..81c20e1 100644
--- a/include/proto/applet.h
+++ b/include/proto/applet.h
@@ -40,6 +40,7 @@
 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
diff --git a/include/proto/dumpstats.h b/include/proto/dumpstats.h
index db60bab..12f972c 100644
--- a/include/proto/dumpstats.h
+++ b/include/proto/dumpstats.h
@@ -413,8 +413,10 @@
 	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 {
diff --git a/include/types/applet.h b/include/types/applet.h
index 1f094e6..e60b08a 100644
--- a/include/types/applet.h
+++ b/include/types/applet.h
@@ -55,6 +55,8 @@
 	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 {
diff --git a/src/dumpstats.c b/src/dumpstats.c
index 491b0fe..5cc09aa 100644
--- a/src/dumpstats.c
+++ b/src/dumpstats.c
@@ -1306,9 +1306,10 @@
 	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) {
@@ -2844,8 +2845,13 @@
 				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;
@@ -6752,6 +6758,10 @@
  */
 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);