diff --git a/apps/app_mixmonitor.c b/apps/app_mixmonitor.c
index 614adcba1215625fce8b3f00a6a6844d949644d2..ca775f163c5c458f36981a988dc687d75679a1bc 100644
--- a/apps/app_mixmonitor.c
+++ b/apps/app_mixmonitor.c
@@ -362,46 +362,44 @@ static int stop_mixmonitor_exec(struct ast_channel *chan, void *data)
 	return 0;
 }
 
-static int mixmonitor_cli(int fd, int argc, char **argv) 
+static char *handle_cli_mixmonitor(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
 	struct ast_channel *chan;
 
-	if (argc < 3)
-		return RESULT_SHOWUSAGE;
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "mixmonitor [start|stop]";
+		e->usage =
+			"Usage: mixmonitor <start|stop> <chan_name> [args]\n"
+			"       The optional arguments are passed to the MixMonitor\n"
+			"       application when the 'start' command is used.\n";
+		return NULL;
+	case CLI_GENERATE:
+		return ast_complete_channels(a->line, a->word, a->pos, a->n, 2);
+	}
+
+	if (a->argc < 3)
+		return CLI_SHOWUSAGE;
 
-	if (!(chan = ast_get_channel_by_name_prefix_locked(argv[2], strlen(argv[2])))) {
-		ast_cli(fd, "No channel matching '%s' found.\n", argv[2]);
-		return RESULT_SUCCESS;
+	if (!(chan = ast_get_channel_by_name_prefix_locked(a->argv[2], strlen(a->argv[2])))) {
+		ast_cli(a->fd, "No channel matching '%s' found.\n", a->argv[2]);
+		/* Technically this is a failure, but we don't want 2 errors printing out */
+		return CLI_SUCCESS;
 	}
 
-	if (!strcasecmp(argv[1], "start")) {
-		mixmonitor_exec(chan, argv[3]);
+	if (!strcasecmp(a->argv[1], "start")) {
+		mixmonitor_exec(chan, a->argv[3]);
 		ast_channel_unlock(chan);
 	} else {
 		ast_channel_unlock(chan);
 		ast_audiohook_detach_source(chan, mixmonitor_spy_type);
 	}
 
-	return RESULT_SUCCESS;
-}
-
-static char *complete_mixmonitor_cli(const char *line, const char *word, int pos, int state)
-{
-	char *options[] = {"start", "stop", NULL};
-
-	if (pos == 1)
-		return ast_cli_complete (word, options, state);
-
-	return ast_complete_channels(line, word, pos, state, 2);
+	return CLI_SUCCESS;
 }
 
 static struct ast_cli_entry cli_mixmonitor[] = {
-	{ { "mixmonitor", NULL, NULL },
-	mixmonitor_cli, "Execute a MixMonitor command.",
-	"mixmonitor <start|stop> <chan_name> [args]\n\n"
-	"The optional arguments are passed to the\n"
-	"MixMonitor application when the 'start' command is used.\n",
-	complete_mixmonitor_cli },
+	NEW_CLI(handle_cli_mixmonitor, "Execute a MixMonitor command")
 };
 
 static int unload_module(void)
diff --git a/apps/app_osplookup.c b/apps/app_osplookup.c
index 25b3fb5188ca690095128c8005534a8bfcab2bd4..5c4e2402bbefcca8eade57909408acc791280fe4 100644
--- a/apps/app_osplookup.c
+++ b/apps/app_osplookup.c
@@ -1861,10 +1861,7 @@ static int osp_unload(void)
 	return 0;
 }
 
-static int osp_show(
-	int fd,
-	int argc,
-	char* argv[])
+static char *handle_cli_osp_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
 	int i;
 	int found = 0;
@@ -1872,12 +1869,21 @@ static int osp_show(
 	const char* provider = NULL;
 	const char* tokenalgo;
 
-	if ((argc < 2) || (argc > 3)) {
-		return RESULT_SHOWUSAGE;
-	}
-	if (argc > 2) {
-		provider = argv[2];
-	}
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "osp show";
+		e->usage =
+			"Usage: osp show\n"
+			"       Displays information on Open Settlement Protocol support\n";
+		return NULL;
+	case CLI_GENERATE:
+		return NULL;
+	}
+
+	if ((a->argc < 2) || (a->argc > 3))
+		return CLI_SHOWUSAGE;
+	if (a->argc > 2) 
+		provider = a->argv[2];
 	if (!provider) {
 		switch (osp_tokenformat) {
 			case TOKEN_ALGO_BOTH:
@@ -1891,7 +1897,7 @@ static int osp_show(
 				tokenalgo = "Signed";
 				break;
 		}
-		ast_cli(fd, "OSP: %s %s %s\n",
+		ast_cli(a->fd, "OSP: %s %s %s\n",
 			osp_initialized ? "Initialized" : "Uninitialized", osp_hardware ? "Accelerated" : "Normal", tokenalgo);
 	}
 
@@ -1900,25 +1906,25 @@ static int osp_show(
 	while(p) {
 		if (!provider || !strcasecmp(p->name, provider)) {
 			if (found) {
-				ast_cli(fd, "\n");
+				ast_cli(a->fd, "\n");
 			}
-			ast_cli(fd, " == OSP Provider '%s' == \n", p->name);
-			ast_cli(fd, "Local Private Key: %s\n", p->privatekey);
-			ast_cli(fd, "Local Certificate: %s\n", p->localcert);
+			ast_cli(a->fd, " == OSP Provider '%s' == \n", p->name);
+			ast_cli(a->fd, "Local Private Key: %s\n", p->privatekey);
+			ast_cli(a->fd, "Local Certificate: %s\n", p->localcert);
 			for (i = 0; i < p->cacount; i++) {
-				ast_cli(fd, "CA Certificate %d:  %s\n", i + 1, p->cacerts[i]);
+				ast_cli(a->fd, "CA Certificate %d:  %s\n", i + 1, p->cacerts[i]);
 			}
 			for (i = 0; i < p->spcount; i++) {
-				ast_cli(fd, "Service Point %d:   %s\n", i + 1, p->srvpoints[i]);
+				ast_cli(a->fd, "Service Point %d:   %s\n", i + 1, p->srvpoints[i]);
 			}
-			ast_cli(fd, "Max Connections:   %d\n", p->maxconnections);
-			ast_cli(fd, "Retry Delay:       %d seconds\n", p->retrydelay);
-			ast_cli(fd, "Retry Limit:       %d\n", p->retrylimit);
-			ast_cli(fd, "Timeout:           %d milliseconds\n", p->timeout);
-			ast_cli(fd, "Source:            %s\n", strlen(p->source) ? p->source : "<unspecified>");
-			ast_cli(fd, "Auth Policy        %d\n", p->authpolicy);
-			ast_cli(fd, "Default protocol   %s\n", p->defaultprotocol);
-			ast_cli(fd, "OSP Handle:        %d\n", p->handle);
+			ast_cli(a->fd, "Max Connections:   %d\n", p->maxconnections);
+			ast_cli(a->fd, "Retry Delay:       %d seconds\n", p->retrydelay);
+			ast_cli(a->fd, "Retry Limit:       %d\n", p->retrylimit);
+			ast_cli(a->fd, "Timeout:           %d milliseconds\n", p->timeout);
+			ast_cli(a->fd, "Source:            %s\n", strlen(p->source) ? p->source : "<unspecified>");
+			ast_cli(a->fd, "Auth Policy        %d\n", p->authpolicy);
+			ast_cli(a->fd, "Default protocol   %s\n", p->defaultprotocol);
+			ast_cli(a->fd, "OSP Handle:        %d\n", p->handle);
 			found++;
 		}
 		p = p->next;
@@ -1927,12 +1933,12 @@ static int osp_show(
 
 	if (!found) {
 		if (provider) {
-			ast_cli(fd, "Unable to find OSP provider '%s'\n", provider);
+			ast_cli(a->fd, "Unable to find OSP provider '%s'\n", provider);
 		} else {
-			ast_cli(fd, "No OSP providers configured\n");
-		}
+			ast_cli(a->fd, "No OSP providers configured\n");
+		}	
 	}
-	return RESULT_SUCCESS;
+	return CLI_SUCCESS;
 }
 
 static const char* app1= "OSPAuth";
@@ -1993,14 +1999,8 @@ static const char* descrip4 =
 "	OSPFINISHSTATUS The status of the OSP Finish attempt as a text string, one of\n"
 "		SUCCESS | FAILED | ERROR \n";
 
-static const char osp_usage[] =
-"Usage: osp show\n"
-"       Displays information on Open Settlement Protocol support\n";
-
 static struct ast_cli_entry cli_osp[] = {
-	{ {"osp", "show", NULL},
-	osp_show, "Displays OSP information",
-	osp_usage },
+	NEW_CLI(handle_cli_osp_show, "Displays OSF information")
 };
 
 static int load_module(void)
diff --git a/apps/app_rpt.c b/apps/app_rpt.c
index 77e4ee4efbb801bd0250867406fbd1a3846a11cb..1f77cee3a5529f602b7418edcedd9e231033c33e 100644
--- a/apps/app_rpt.c
+++ b/apps/app_rpt.c
@@ -300,7 +300,6 @@ static char *remote_rig_rbi = "rbi";
 STANDARD_LOCAL_USER;
 #endif
 
-
 #define	MSWAIT 200
 #define	HANGTIME 5000
 #define	TOTIME 180000
@@ -699,60 +698,20 @@ static void _rpt_mutex_unlock(ast_mutex_t *lockp, struct rpt *myrpt, int line)
 */
 
 /* Debug mode */
-static int rpt_do_debug(int fd, int argc, char *argv[]);
-static int rpt_do_dump(int fd, int argc, char *argv[]);
-static int rpt_do_stats(int fd, int argc, char *argv[]);
-static int rpt_do_lstats(int fd, int argc, char *argv[]);
-static int rpt_do_reload(int fd, int argc, char *argv[]);
-static int rpt_do_restart(int fd, int argc, char *argv[]);
-
-static char debug_usage[] =
-"Usage: rpt debug level {0-7}\n"
-"       Enables debug messages in app_rpt\n";
-
-static char dump_usage[] =
-"Usage: rpt dump <nodename>\n"
-"       Dumps struct debug info to log\n";
-
-static char dump_stats[] =
-"Usage: rpt stats <nodename>\n"
-"       Dumps node statistics to console\n";
-
-static char dump_lstats[] =
-"Usage: rpt lstats <nodename>\n"
-"       Dumps link statistics to console\n";
-
-static char reload_usage[] =
-"Usage: rpt reload\n"
-"       Reloads app_rpt running config parameters\n";
-
-static char restart_usage[] =
-"Usage: rpt restart\n"
-"       Restarts app_rpt\n";
+static char *handle_cli_rpt_debug_level(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
+static char *handle_cli_rpt_dump(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
+static char *handle_cli_rpt_stats(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
+static char *handle_cli_rpt_lstats(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
+static char *handle_cli_rpt_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
+static char *handle_cli_rpt_restart(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
 
 static struct ast_cli_entry cli_rpt[] = {
-	{ { "rpt", "debug", "level" },
-		rpt_do_debug, "Enable app_rpt debugging",
-		debug_usage },
-
-	{ { "rpt", "dump" },
-		rpt_do_dump, "Dump app_rpt structs for debugging",
-		dump_usage },
-
-	{ { "rpt", "stats" },
-		rpt_do_stats, "Dump node statistics",
-		dump_stats },
-	{ { "rpt", "lstats" },
-		rpt_do_lstats, "Dump link statistics",
-		dump_lstats },
-
-	{ { "rpt", "reload" },
-		rpt_do_reload, "Reload app_rpt config",
-		reload_usage },
-
-	{ { "rpt", "restart" },
-		rpt_do_restart, "Restart app_rpt",
-		restart_usage },
+	NEW_CLI(handle_cli_rpt_debug_level, "Enable app_rpt debuggin"),
+	NEW_CLI(handle_cli_rpt_dump,        "Dump app_rpt structs for debugging"),
+	NEW_CLI(handle_cli_rpt_stats,       "Dump node statistics"),
+	NEW_CLI(handle_cli_rpt_lstats,      "Dump link statistics"),
+	NEW_CLI(handle_cli_rpt_reload,      "Reload app_rpt config"),
+	NEW_CLI(handle_cli_rpt_restart,     "Restart app_rpt")
 };
 
 /*
@@ -1130,48 +1089,70 @@ static void load_rpt_vars(int n, int init)
 /*
 * Enable or disable debug output at a given level at the console
 */
-static int rpt_do_debug(int fd, int argc, char *argv[])
+static char *handle_cli_rpt_debug_level(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
 	int newlevel;
 
-	if (argc != 4)
-		return RESULT_SHOWUSAGE;
-	newlevel = myatoi(argv[3]);
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "rpt debug level";
+		e->usage =
+			"Usage: rpt debug level {0-7}\n"
+			"       Enables debug messages in app_rpt\n";
+		return NULL;
+	case CLI_GENERATE:
+		return NULL;
+	}
+	if (a->argc != 4)
+		return CLI_SHOWUSAGE;
+	newlevel = myatoi(a->argv[3]);
 	if ((newlevel < 0) || (newlevel > 7))
-		return RESULT_SHOWUSAGE;
+		return CLI_SHOWUSAGE;
 	if (newlevel)
-		ast_cli(fd, "app_rpt Debugging enabled, previous level: %d, new level: %d\n", debug, newlevel);
+		ast_cli(a->fd, "app_rpt Debugging enabled, previous level: %d, new level: %d\n", debug, newlevel);
 	else
-		ast_cli(fd, "app_rpt Debugging disabled\n");
+		ast_cli(a->fd, "app_rpt Debugging disabled\n");
+
+	debug = newlevel;
 
-	debug = newlevel;                                                                                                                          
-	return RESULT_SUCCESS;
+	return CLI_SUCCESS;
 }
 
 /*
 * Dump rpt struct debugging onto console
 */
-static int rpt_do_dump(int fd, int argc, char *argv[])
+static char *handle_cli_rpt_dump(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
 	int i;
 
-	if (argc != 3)
-		return RESULT_SHOWUSAGE;
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "rpt dump";
+		e->usage =
+			"Usage: rpt dump <nodename>\n"
+			"       Dumps struct debug info to log\n";
+		return NULL;
+	case CLI_GENERATE:
+		return NULL;
+	}
+
+	if (a->argc != 3)
+		return CLI_SHOWUSAGE;
 
 	for (i = 0; i < nrpts; i++) {
-		if (!strcmp(argv[2], rpt_vars[i].name)) {
+		if (!strcmp(a->argv[2], rpt_vars[i].name)) {
 			rpt_vars[i].disgorgetime = time(NULL) + 10; /* Do it 10 seconds later */
-			ast_cli(fd, "app_rpt struct dump requested for node %s\n", argv[2]);
-			return RESULT_SUCCESS;
+			ast_cli(a->fd, "app_rpt struct dump requested for node %s\n", a->argv[2]);
+			return CLI_SUCCESS;
 		}
 	}
-	return RESULT_FAILURE;
+	return CLI_FAILURE;
 }
 
 /*
 * Dump statistics onto console
 */
-static int rpt_do_stats(int fd, int argc, char *argv[])
+static char *handle_cli_rpt_stats(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
 	int i, j;
 	int dailytxtime, dailykerchunks;
@@ -1187,8 +1168,19 @@ static int rpt_do_stats(int fd, int argc, char *argv[])
 
 	static char *not_applicable = "N/A";
 
-	if (argc != 3)
-		return RESULT_SHOWUSAGE;
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "rpt stats";
+		e->usage =
+			"Usage: rpt stats <nodename>\n"
+			"       Dumps node statistics to console\n";
+		return NULL;
+	case CLI_GENERATE:
+		return NULL;
+	}
+
+	if (a->argc != 3)
+		return CLI_SHOWUSAGE;
 
 	for (i = 0 ; i <= MAX_STAT_LINKS; i++)
 		listoflinks[i] = NULL;
@@ -1199,7 +1191,7 @@ static int rpt_do_stats(int fd, int argc, char *argv[])
 	lastdtmfcommand = not_applicable;
 
 	for (i = 0; i < nrpts; i++) {
-		if (!strcmp(argv[2], rpt_vars[i].name)) {
+		if (!strcmp(a->argv[2], rpt_vars[i].name)) {
 			/* Make a copy of all stat variables while locked */
 			myrpt = &rpt_vars[i];
 			rpt_mutex_lock(&myrpt->lock); /* LOCK */
@@ -1283,19 +1275,19 @@ static int rpt_do_stats(int fd, int argc, char *argv[])
 
 			rpt_mutex_unlock(&myrpt->lock); /* UNLOCK */
 
-			ast_cli(fd, "************************ NODE %s STATISTICS *************************\n\n", myrpt->name);
-			ast_cli(fd, "Signal on input..................................: %s\n", input_signal);
-			ast_cli(fd, "Transmitter enabled..............................: %s\n", enable_state);
-			ast_cli(fd, "Time out timer state.............................: %s\n", tot_state);
-			ast_cli(fd, "Time outs since system initialization............: %d\n", timeouts);
-			ast_cli(fd, "Identifier state.................................: %s\n", ider_state);
-			ast_cli(fd, "Kerchunks today..................................: %d\n", dailykerchunks);
-			ast_cli(fd, "Kerchunks since system initialization............: %d\n", totalkerchunks);
-			ast_cli(fd, "Keyups today.....................................: %d\n", dailykeyups);
-			ast_cli(fd, "Keyups since system initialization...............: %d\n", totalkeyups);
-			ast_cli(fd, "DTMF commands today..............................: %d\n", dailyexecdcommands);
-			ast_cli(fd, "DTMF commands since system initialization........: %d\n", totalexecdcommands);
-			ast_cli(fd, "Last DTMF command executed.......................: %s\n", lastdtmfcommand);
+			ast_cli(a->fd, "************************ NODE %s STATISTICS *************************\n\n", myrpt->name);
+			ast_cli(a->fd, "Signal on input..................................: %s\n", input_signal);
+			ast_cli(a->fd, "Transmitter enabled..............................: %s\n", enable_state);
+			ast_cli(a->fd, "Time out timer state.............................: %s\n", tot_state);
+			ast_cli(a->fd, "Time outs since system initialization............: %d\n", timeouts);
+			ast_cli(a->fd, "Identifier state.................................: %s\n", ider_state);
+			ast_cli(a->fd, "Kerchunks today..................................: %d\n", dailykerchunks);
+			ast_cli(a->fd, "Kerchunks since system initialization............: %d\n", totalkerchunks);
+			ast_cli(a->fd, "Keyups today.....................................: %d\n", dailykeyups);
+			ast_cli(a->fd, "Keyups since system initialization...............: %d\n", totalkeyups);
+			ast_cli(a->fd, "DTMF commands today..............................: %d\n", dailyexecdcommands);
+			ast_cli(a->fd, "DTMF commands since system initialization........: %d\n", totalexecdcommands);
+			ast_cli(a->fd, "Last DTMF command executed.......................: %s\n", lastdtmfcommand);
 
 			hours = dailytxtime / 3600000;
 			dailytxtime %= 3600000;
@@ -1304,7 +1296,7 @@ static int rpt_do_stats(int fd, int argc, char *argv[])
 			seconds = dailytxtime / 1000;
 			dailytxtime %= 1000;
 
-			ast_cli(fd, "TX time today ...................................: %02d:%02d:%02d.%d\n",
+			ast_cli(a->fd, "TX time today ...................................: %02d:%02d:%02d.%d\n",
 				hours, minutes, seconds, dailytxtime);
 
 			hours = (int) totaltxtime / 3600000;
@@ -1314,57 +1306,69 @@ static int rpt_do_stats(int fd, int argc, char *argv[])
 			seconds = (int)  totaltxtime / 1000;
 			totaltxtime %= 1000;
 
-			ast_cli(fd, "TX time since system initialization..............: %02d:%02d:%02d.%d\n",
+			ast_cli(a->fd, "TX time since system initialization..............: %02d:%02d:%02d.%d\n",
 				 hours, minutes, seconds, (int) totaltxtime);
-			ast_cli(fd, "Nodes currently connected to us..................: ");
+			ast_cli(a->fd, "Nodes currently connected to us..................: ");
 			for (j = 0;; j++) {
 				if (!listoflinks[j]) {
 					if (!j) {
-						ast_cli(fd, "<NONE>");
+						ast_cli(a->fd, "<NONE>");
 					}
 					break;
 				}
-				ast_cli(fd, "%s", listoflinks[j]);
+				ast_cli(a->fd, "%s", listoflinks[j]);
 				if (j % 4 == 3) {
-					ast_cli(fd, "\n");
-					ast_cli(fd, "                                                 : ");
+					ast_cli(a->fd, "\n");
+					ast_cli(a->fd, "                                                 : ");
 				} else {
 					if (listoflinks[j + 1])
-						ast_cli(fd, ", ");
+						ast_cli(a->fd, ", ");
 				}
 			}
-			ast_cli(fd, "\n");
+			ast_cli(a->fd, "\n");
 
-			ast_cli(fd, "Last node which transmitted to us................: %s\n", lastnodewhichkeyedusup);
-			ast_cli(fd, "Autopatch state..................................: %s\n", patch_state);
-			ast_cli(fd, "Autopatch called number..........................: %s\n", called_number);
-			ast_cli(fd, "Reverse patch/IAXRPT connected...................: %s\n\n", reverse_patch_state);
+			ast_cli(a->fd, "Last node which transmitted to us................: %s\n", lastnodewhichkeyedusup);
+			ast_cli(a->fd, "Autopatch state..................................: %s\n", patch_state);
+			ast_cli(a->fd, "Autopatch called number..........................: %s\n", called_number);
+			ast_cli(a->fd, "Reverse patch/IAXRPT connected...................: %s\n\n", reverse_patch_state);
 
-			return RESULT_SUCCESS;
+			return CLI_SUCCESS;
 		}
 	}
-	return RESULT_FAILURE;
+	return CLI_FAILURE;
 }
 
 /*
 * Link stats function
 */
-static int rpt_do_lstats(int fd, int argc, char *argv[])
+static char *handle_cli_rpt_lstats(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
 	int i, j;
 	struct rpt *myrpt;
 	struct rpt_link *l;
 	struct rpt_lstat *s, *t;
 	struct rpt_lstat s_head;
-	if (argc != 3)
-		return RESULT_SHOWUSAGE;
+
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "rpt lstats";
+		e->usage =
+			"Usage: rpt lstats <nodename>\n"
+			"       Dumps link statistics to console\n";
+		return NULL;
+	case CLI_GENERATE:
+		return NULL;
+	}
+
+	if (a->argc != 3)
+		return CLI_SHOWUSAGE;
 
 	s = NULL;
 	s_head.next = &s_head;
 	s_head.prev = &s_head;
 
 	for (i = 0; i < nrpts; i++) {
-		if (!strcmp(argv[2], rpt_vars[i].name)) {
+		if (!strcmp(a->argv[2], rpt_vars[i].name)) {
 			/* Make a copy of all stat variables while locked */
 			myrpt = &rpt_vars[i];
 			rpt_mutex_lock(&myrpt->lock); /* LOCK */
@@ -1379,7 +1383,7 @@ static int rpt_do_lstats(int fd, int argc, char *argv[])
 				if ((s = ast_calloc(1, sizeof(*s))) == NULL) {
 					ast_log(LOG_ERROR, "Malloc failed in rpt_do_lstats\n");
 					rpt_mutex_unlock(&myrpt->lock); /* UNLOCK */
-					return RESULT_FAILURE;
+					return CLI_FAILURE;
 				}
 				ast_copy_string(s->name, l->name, MAXREMSTR);
 				pbx_substitute_variables_helper(l->chan, "${IAXPEER(CURRENTCHANNEL)}", s->peer, MAXPEERSTR - 1);
@@ -1391,8 +1395,8 @@ static int rpt_do_lstats(int fd, int argc, char *argv[])
 				l = l->next;
 			}
 			rpt_mutex_unlock(&myrpt->lock); /* UNLOCK */
-			ast_cli(fd, "NODE      PEER                RECONNECTS  DIRECTION  CONNECT TIME\n");
-			ast_cli(fd, "----      ----                ----------  ---------  ------------\n");
+			ast_cli(a->fd, "NODE      PEER                RECONNECTS  DIRECTION  CONNECT TIME\n");
+			ast_cli(a->fd, "----      ----                ----------  ---------  ------------\n");
 
 			for (s = s_head.next; s != &s_head; s = s->next) {
 				int hours, minutes, seconds;
@@ -1406,7 +1410,7 @@ static int rpt_do_lstats(int fd, int argc, char *argv[])
 				connecttime %= 1000;
 				snprintf(conntime, sizeof(conntime), "%02d:%02d:%02d.%d",
 					hours, minutes, seconds, (int) connecttime);
-				ast_cli(fd, "%-10s%-20s%-12d%-11s%-30s\n",
+				ast_cli(a->fd, "%-10s%-20s%-12d%-11s%-30s\n",
 					s->name, s->peer, s->reconnects, (s->outbound)? "OUT":"IN", conntime);
 			}	
 			/* destroy our local link queue */
@@ -1417,42 +1421,65 @@ static int rpt_do_lstats(int fd, int argc, char *argv[])
 				remque((struct qelem *)t);
 				ast_free(t);
 			}			
-			return RESULT_SUCCESS;
+			return CLI_SUCCESS;
 		}
 	}
-	return RESULT_FAILURE;
+
+	return CLI_FAILURE;
 }
 
 /*
 * reload vars 
 */
-static int rpt_do_reload(int fd, int argc, char *argv[])
+static char *handle_cli_rpt_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
 	int	n;
 
-	if (argc > 2)
-		return RESULT_SHOWUSAGE;
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "rpt reload";
+		e->usage =
+			"Usage: rpt reload\n"
+			"       Reloads app_rpt running config parameters\n";
+		return NULL;
+	case CLI_GENERATE:
+		return NULL;
+	}
+
+	if (a->argc > 2)
+		return CLI_SHOWUSAGE;
 
 	for (n = 0; n < nrpts; n++)
 		rpt_vars[n].reload = 1;
 
-	return RESULT_FAILURE;
+	return CLI_SUCCESS;
 }
 
 /*
 * restart app_rpt
 */
-static int rpt_do_restart(int fd, int argc, char *argv[])
+static char *handle_cli_rpt_restart(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
 	int	i;
 
-	if (argc > 2)
-		return RESULT_SHOWUSAGE;
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "rpt restart";
+		e->usage =
+			"Usage: rpt restart\n"
+			"       Restarts app_rpt\n";
+		return NULL;
+	case CLI_GENERATE:
+		return NULL;
+	}
+
+	if (a->argc > 2)
+		return CLI_SHOWUSAGE;
 	for (i = 0; i < nrpts; i++) {
 		if (rpt_vars[i].rxchannel)
 			ast_softhangup(rpt_vars[i].rxchannel, AST_SOFTHANGUP_DEV);
 	}
-	return RESULT_FAILURE;
+	return CLI_SUCCESS;
 }
 
 static int play_tone_pair(struct ast_channel *chan, int f1, int f2, int duration, int amplitude)
@@ -4627,7 +4654,7 @@ static int function_remote(struct rpt *myrpt, char *param, char *digitbuf, int c
 	char multimode = 0;
 	char oc;
 	char tmp[20], freq[20] = "", savestr[20] = "";
-	int mhz, decimals;
+	int mhz = 0, decimals = 0;
 	struct ast_channel *mychannel;
 	AST_DECLARE_APP_ARGS(args1,
 		AST_APP_ARG(freq);
@@ -6800,7 +6827,7 @@ static int rpt_exec(struct ast_channel *chan, void *data)
 {
 	int res = -1, i, rem_totx, n, phone_mode = 0;
 	char *tmp, keyed = 0;
-	char *options, *tele, c;
+	char *options = NULL, *tele, c;
 	struct rpt *myrpt;
 	struct ast_frame *f;
 	struct ast_channel *who;
diff --git a/channels/chan_gtalk.c b/channels/chan_gtalk.c
index a67df2c8aeab5f20effc461bd23b4d23603e71c0..be3a346c57dbe5f61e7d5668518b5725802ec672 100644
--- a/channels/chan_gtalk.c
+++ b/channels/chan_gtalk.c
@@ -191,8 +191,8 @@ static int gtalk_indicate(struct ast_channel *ast, int condition, const void *da
 static int gtalk_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
 static int gtalk_sendhtml(struct ast_channel *ast, int subclass, const char *data, int datalen);
 static struct gtalk_pvt *gtalk_alloc(struct gtalk *client, const char *us, const char *them, const char *sid);
-static int gtalk_do_reload(int fd, int argc, char **argv);
-static int gtalk_show_channels(int fd, int argc, char **argv);
+static char *gtalk_do_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
+static char *gtalk_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
 /*----- RTP interface functions */
 static int gtalk_set_rtp_peer(struct ast_channel *chan, struct ast_rtp *rtp,
 							   struct ast_rtp *vrtp, struct ast_rtp *trtp, int codecs, int nat_active);
@@ -226,7 +226,6 @@ static struct sched_context *sched;	/*!< The scheduling context */
 static struct io_context *io;	/*!< The IO context */
 static struct in_addr __ourip;
 
-
 /*! \brief RTP driver interface */
 static struct ast_rtp_protocol gtalk_rtp = {
 	type: "Gtalk",
@@ -235,21 +234,10 @@ static struct ast_rtp_protocol gtalk_rtp = {
 	get_codec: gtalk_get_codec,
 };
 
-static const char debug_usage[] = 
-"Usage: gtalk show channels\n" 
-"       Shows current state of the Gtalk channels.\n";
-
-static const char reload_usage[] = 
-"Usage: gtalk reload\n" 
-"       Reload gtalk channel driver.\n";
-
-
 static struct ast_cli_entry gtalk_cli[] = {
-	{{ "gtalk", "reload", NULL}, gtalk_do_reload, "Enable Jabber debugging", reload_usage },
-	{{ "gtalk", "show", "channels", NULL}, gtalk_show_channels, "Show GoogleTalk Channels", debug_usage },
- };
-
-
+	NEW_CLI(gtalk_do_reload, "Enable Jabber debugging"),
+	NEW_CLI(gtalk_show_channels, "Show GoogleTalk Channels"),
+};
 
 static char externip[16];
 
@@ -265,7 +253,7 @@ static struct gtalk *find_gtalk(char *name, char *connection)
 	struct gtalk *gtalk = NULL;
 	char *domain = NULL , *s = NULL;
 
-	if(strchr(connection, '@')) {
+	if (strchr(connection, '@')) {
 		s = ast_strdupa(connection);
 		domain = strsep(&s, "@");
 		ast_verbose("OOOOH domain = %s\n", domain);
@@ -1581,7 +1569,7 @@ static struct ast_channel *gtalk_request(const char *type, int format, void *dat
 }
 
 /*! \brief CLI command "gtalk show channels" */
-static int gtalk_show_channels(int fd, int argc, char **argv)
+static char *gtalk_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
 #define FORMAT  "%-30.30s  %-30.30s  %-15.15s  %-5.5s %-5.5s \n"
 	struct gtalk_pvt *p;
@@ -1591,11 +1579,22 @@ static int gtalk_show_channels(int fd, int argc, char **argv)
 	char *jid = NULL;
 	char *resource = NULL;
 
-	if (argc != 3)
-		return RESULT_SHOWUSAGE;
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "gtalk show channels";
+		e->usage =
+			"Usage: gtalk show channels\n"
+			"       Shows current state of the Gtalk channels.\n";
+		return NULL;
+	case CLI_GENERATE:
+		return NULL;
+	}
+
+	if (a->argc != 3)
+		return CLI_SHOWUSAGE;
 
 	ast_mutex_lock(&gtalklock);
-	ast_cli(fd, FORMAT, "Channel", "Jabber ID", "Resource", "Read", "Write");
+	ast_cli(a->fd, FORMAT, "Channel", "Jabber ID", "Resource", "Read", "Write");
 	ASTOBJ_CONTAINER_TRAVERSE(&gtalk_list, 1, {
 		ASTOBJ_WRLOCK(iterator);
 		p = iterator->p;
@@ -1611,7 +1610,7 @@ static int gtalk_show_channels(int fd, int argc, char **argv)
 				resource ++;
 			}
 			if (chan)
-				ast_cli(fd, FORMAT, 
+				ast_cli(a->fd, FORMAT, 
 					chan->name,
 					jid,
 					resource,
@@ -1628,16 +1627,27 @@ static int gtalk_show_channels(int fd, int argc, char **argv)
 
 	ast_mutex_unlock(&gtalklock);
 
-	ast_cli(fd, "%d active gtalk channel%s\n", numchans, (numchans != 1) ? "s" : "");
-	return RESULT_SUCCESS;
+	ast_cli(a->fd, "%d active gtalk channel%s\n", numchans, (numchans != 1) ? "s" : "");
+	return CLI_SUCCESS;
 #undef FORMAT
 }
 
-/*! \brief CLI command "gtalk show channels" */
-static int gtalk_do_reload(int fd, int argc, char **argv)
+/*! \brief CLI command "gtalk reload" */
+static char *gtalk_do_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "gtalk reload";
+		e->usage =
+			"Usage: gtalk reload\n"
+			"       Reload gtalk channel driver.\n";
+		return NULL;
+	case CLI_GENERATE:
+		return NULL;
+	}	
+	
 	ast_verbose("IT DOES WORK!\n");
-	return RESULT_SUCCESS;
+	return CLI_SUCCESS;
 }
 
 static int gtalk_parser(void *data, ikspak *pak)
diff --git a/channels/chan_mgcp.c b/channels/chan_mgcp.c
index 7693397c766ad40757671921a575f1253024740a..a509dea7d08fc6608167a1c8f24cf0d214ee5658 100644
--- a/channels/chan_mgcp.c
+++ b/channels/chan_mgcp.c
@@ -422,7 +422,7 @@ static void start_rtp(struct mgcp_subchannel *sub);
 static void handle_response(struct mgcp_endpoint *p, struct mgcp_subchannel *sub,  
                             int result, unsigned int ident, struct mgcp_request *resp);
 static void dump_cmd_queues(struct mgcp_endpoint *p, struct mgcp_subchannel *sub);
-static int mgcp_reload(int fd, int argc, char *argv[]);
+static char *mgcp_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
 static int reload_config(int reload);
 
 static struct ast_channel *mgcp_request(const char *type, int format, void *data, int *cause);
@@ -1041,71 +1041,72 @@ static int mgcp_hangup(struct ast_channel *ast)
 	return 0;
 }
 
-static int mgcp_show_endpoints(int fd, int argc, char *argv[])
+static char *handle_mgcp_show_endpoints(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
-	struct mgcp_gateway  *g;
-	struct mgcp_endpoint *e;
+	struct mgcp_gateway  *mg;
+	struct mgcp_endpoint *me;
 	int hasendpoints = 0;
 
-	if (argc != 3) 
-		return RESULT_SHOWUSAGE;
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "mgcp show endpoints";
+		e->usage =
+			"Usage: mgcp show endpoints\n"
+			"       Lists all endpoints known to the MGCP (Media Gateway Control Protocol) subsystem.\n";
+		return NULL;
+	case CLI_GENERATE:
+		return NULL;
+	}
+
+	if (a->argc != 3) 
+		return CLI_SHOWUSAGE;
 	ast_mutex_lock(&gatelock);
-	g = gateways;
-	while(g) {
-		e = g->endpoints;
-		ast_cli(fd, "Gateway '%s' at %s (%s)\n", g->name, g->addr.sin_addr.s_addr ? ast_inet_ntoa(g->addr.sin_addr) : ast_inet_ntoa(g->defaddr.sin_addr), g->dynamic ? "Dynamic" : "Static");
-		while(e) {
+	mg = gateways;
+	while(mg) {
+		me = mg->endpoints;
+		ast_cli(a->fd, "Gateway '%s' at %s (%s)\n", mg->name, mg->addr.sin_addr.s_addr ? ast_inet_ntoa(mg->addr.sin_addr) : ast_inet_ntoa(mg->defaddr.sin_addr), mg->dynamic ? "Dynamic" : "Static");
+		while(me) {
 			/* Don't show wilcard endpoint */
-			if (strcmp(e->name, g->wcardep) !=0)
-				ast_cli(fd, "   -- '%s@%s in '%s' is %s\n", e->name, g->name, e->context, e->sub->owner ? "active" : "idle");
+			if (strcmp(me->name, mg->wcardep) != 0)
+				ast_cli(a->fd, "   -- '%s@%s in '%s' is %s\n", me->name, mg->name, me->context, me->sub->owner ? "active" : "idle");
 			hasendpoints = 1;
-			e = e->next;
+			me = me->next;
 		}
 		if (!hasendpoints) {
-			ast_cli(fd, "   << No Endpoints Defined >>     ");
+			ast_cli(a->fd, "   << No Endpoints Defined >>     ");
 		}
-		g = g->next;
+		mg = mg->next;
 	}
 	ast_mutex_unlock(&gatelock);
-	return RESULT_SUCCESS;
+	return CLI_SUCCESS;
 }
 
-static const char show_endpoints_usage[] = 
-"Usage: mgcp show endpoints\n"
-"       Lists all endpoints known to the MGCP (Media Gateway Control Protocol) subsystem.\n";
-
-static const char audit_endpoint_usage[] = 
-"Usage: mgcp audit endpoint <endpointid>\n"
-"       Lists the capabilities of an endpoint in the MGCP (Media Gateway Control Protocol) subsystem.\n"
-"       mgcp debug MUST be on to see the results of this command.\n";
-
-static const char debug_usage[] = 
-"Usage: mgcp set debug\n"
-"       Enables dumping of MGCP packets for debugging purposes\n";
-
-static const char no_debug_usage[] = 
-"Usage: mgcp set debug off\n"
-"       Disables dumping of MGCP packets for debugging purposes\n";
-
-static const char mgcp_reload_usage[] =
-"Usage: mgcp reload\n"
-"       Reloads MGCP configuration from mgcp.conf\n"
-"       Deprecated:  please use 'reload chan_mgcp.so' instead.\n";
-
-static int mgcp_audit_endpoint(int fd, int argc, char *argv[])
+static char *handle_mgcp_audit_endpoint(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
-	struct mgcp_gateway  *g;
-	struct mgcp_endpoint *e;
+	struct mgcp_gateway  *mg;
+	struct mgcp_endpoint *me;
 	int found = 0;
 	char *ename,*gname, *c;
 
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "mgcp audit endpoint";
+		e->usage =
+			"Usage: mgcp audit endpoint <endpointid>\n"
+			"       Lists the capabilities of an endpoint in the MGCP (Media Gateway Control Protocol) subsystem.\n"
+			"       mgcp debug MUST be on to see the results of this command.\n";
+		return NULL;
+	case CLI_GENERATE:
+		return NULL;
+	}
+
 	if (!mgcpdebug) {
-		return RESULT_SHOWUSAGE;
+		return CLI_SHOWUSAGE;
 	}
-	if (argc != 4) 
-		return RESULT_SHOWUSAGE;
+	if (a->argc != 4)
+		return CLI_SHOWUSAGE;
 	/* split the name into parts by null */
-	ename = argv[3];
+	ename = a->argv[3];
 	gname = ename;
 	while (*gname) {
 		if (*gname == '@') {
@@ -1120,69 +1121,77 @@ static int mgcp_audit_endpoint(int fd, int argc, char *argv[])
 	if ((c = strrchr(gname, ']')))
 		*c = '\0';
 	ast_mutex_lock(&gatelock);
-	g = gateways;
-	while(g) {
-		if (!strcasecmp(g->name, gname)) {
-			e = g->endpoints;
-			while(e) {
-				if (!strcasecmp(e->name, ename)) {
+	mg = gateways;
+	while(mg) {
+		if (!strcasecmp(mg->name, gname)) {
+			me = mg->endpoints;
+			while(me) {
+				if (!strcasecmp(me->name, ename)) {
 					found = 1;
-					transmit_audit_endpoint(e);
+					transmit_audit_endpoint(me);
 					break;
 				}
-				e = e->next;
+				me = me->next;
 			}
 			if (found) {
 				break;
 			}
 		}
-		g = g->next;
+		mg = mg->next;
 	}
 	if (!found) {
-		ast_cli(fd, "   << Could not find endpoint >>     ");
+		ast_cli(a->fd, "   << Could not find endpoint >>     ");
 	}
 	ast_mutex_unlock(&gatelock);
-	return RESULT_SUCCESS;
+	return CLI_SUCCESS;
 }
 
-static int mgcp_do_debug(int fd, int argc, char *argv[])
+static char *handle_mgcp_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
-	if (argc != 3)
-		return RESULT_SHOWUSAGE;
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "mgcp set debug";
+		e->usage =
+			"Usage: mgcp set debug\n"
+			"       Enables dumping of MGCP packets for debugging purposes\n";	
+		return NULL;
+	case CLI_GENERATE:
+		return NULL;
+	}
+
+	if (a->argc != 3)
+		return CLI_SHOWUSAGE;
 	mgcpdebug = 1;
-	ast_cli(fd, "MGCP Debugging Enabled\n");
-	return RESULT_SUCCESS;
+	ast_cli(a->fd, "MGCP Debugging Enabled\n");
+	return CLI_SUCCESS;
 }
 
-static int mgcp_no_debug(int fd, int argc, char *argv[])
+static char *handle_mgcp_set_debug_off(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
-	if (argc != 4)
-		return RESULT_SHOWUSAGE;
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "mgcp set debug off";
+		e->usage =
+			"Usage: mgcp set debug off\n"
+			"       Disables dumping of MGCP packets for debugging purposes\n";
+		return NULL;
+	case CLI_GENERATE:
+		return NULL;
+	}
+
+	if (a->argc != 4)
+		return CLI_SHOWUSAGE;
 	mgcpdebug = 0;
-	ast_cli(fd, "MGCP Debugging Disabled\n");
-	return RESULT_SUCCESS;
+	ast_cli(a->fd, "MGCP Debugging Disabled\n");
+	return CLI_SUCCESS;
 }
 
 static struct ast_cli_entry cli_mgcp[] = {
-	{ { "mgcp", "audit", "endpoint", NULL },
-	mgcp_audit_endpoint, "Audit specified MGCP endpoint",
-	audit_endpoint_usage },
-
-	{ { "mgcp", "show", "endpoints", NULL },
-	mgcp_show_endpoints, "List defined MGCP endpoints",
-	show_endpoints_usage },
-
-	{ { "mgcp", "set", "debug", NULL },
-	mgcp_do_debug, "Enable MGCP debugging",
-	debug_usage },
-
-	{ { "mgcp", "set", "debug", "off", NULL },
-	mgcp_no_debug, "Disable MGCP debugging",
-	no_debug_usage },
-
-	{ { "mgcp", "reload", NULL },
-	mgcp_reload, "Reload MGCP configuration",
-	mgcp_reload_usage },
+	NEW_CLI(handle_mgcp_audit_endpoint, "Audit specified MGCP endpoint"),
+	NEW_CLI(handle_mgcp_show_endpoints, "List defined MGCP endpoints"),
+	NEW_CLI(handle_mgcp_set_debug, "Enable MGCP debugging"),
+	NEW_CLI(handle_mgcp_set_debug_off, "Disable MGCP debugging"),
+	NEW_CLI(mgcp_reload, "Reload MGCP configuration"),
 };
 
 static int mgcp_answer(struct ast_channel *ast)
@@ -4242,10 +4251,24 @@ static int load_module(void)
 	return AST_MODULE_LOAD_SUCCESS;
 }
 
-static int mgcp_reload(int fd, int argc, char *argv[])
+static char *mgcp_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
 	static int deprecated = 0;
-	if (!deprecated && argc > 0) {
+
+	if (e) {
+		switch (cmd) {
+		case CLI_INIT:
+			e->command = "mgcp reload";
+			e->usage =
+				"Usage: mgcp reload\n"
+				"       'mgcp reload' is deprecated.  Please use 'reload chan_mgcp.so' instead.\n";
+			return NULL;
+		case CLI_GENERATE:
+			return NULL;
+		}
+	}
+
+	if (!deprecated && a && a->argc > 0) {
 		ast_log(LOG_WARNING, "'mgcp reload' is deprecated.  Please use 'reload chan_mgcp.so' instead.\n");
 		deprecated = 1;
 	}
@@ -4257,12 +4280,12 @@ static int mgcp_reload(int fd, int argc, char *argv[])
 		mgcp_reloading = 1;
 	ast_mutex_unlock(&mgcp_reload_lock);
 	restart_monitor();
-	return 0;
+	return CLI_SUCCESS;
 }
 
 static int reload(void)
 {
-	mgcp_reload(0, 0, NULL);
+	mgcp_reload(NULL, 0, NULL);
 	return 0;
 }
 
@@ -4297,7 +4320,7 @@ static int unload_module(void)
 		/* We always want to leave this in a consistent state */
 		ast_channel_register(&mgcp_tech);
 		mgcp_reloading = 0;
-		mgcp_reload(0, 0, NULL);
+		mgcp_reload(NULL, 0, NULL);
 		return -1;
 	}
 
@@ -4317,7 +4340,7 @@ static int unload_module(void)
 		/* Allow the monitor to restart */
 		monitor_thread = AST_PTHREADT_NULL;
 		mgcp_reloading = 0;
-		mgcp_reload(0, 0, NULL);
+		mgcp_reload(NULL, 0, NULL);
 		return -1;
 	}
 
diff --git a/channels/chan_oss.c b/channels/chan_oss.c
index 42e05460936512e0d608dab0ebbb908e9ff813eb..cea7984dcd50ad191631af08af07b92f8c19c851 100644
--- a/channels/chan_oss.c
+++ b/channels/chan_oss.c
@@ -1333,69 +1333,83 @@ static char *console_mute(struct ast_cli_entry *e, int cmd, struct ast_cli_args
 	return CLI_SUCCESS;
 }
 
-static int console_transfer(int fd, int argc, char *argv[])
+static char *console_transfer(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
 	struct chan_oss_pvt *o = find_desc(oss_active);
 	struct ast_channel *b = NULL;
 	char *tmp, *ext, *ctx;
 
-	if (argc != 3)
-		return RESULT_SHOWUSAGE;
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "console transfer";
+		e->usage =
+			"Usage: console transfer <extension>[@context]\n"
+			"       Transfers the currently connected call to the given extension (and\n"
+			"       context if specified)\n";
+		return NULL;
+	case CLI_GENERATE:
+		return NULL;
+	}
+
+	if (a->argc != 3)
+		return CLI_SHOWUSAGE;
 	if (o == NULL)
-		return RESULT_FAILURE;
+		return CLI_FAILURE;
 	if (o->owner == NULL || (b = ast_bridged_channel(o->owner)) == NULL) {
-		ast_cli(fd, "There is no call to transfer\n");
-		return RESULT_SUCCESS;
+		ast_cli(a->fd, "There is no call to transfer\n");
+		return CLI_SUCCESS;
 	}
 
-	tmp = ast_ext_ctx(argv[2], &ext, &ctx);
+	tmp = ast_ext_ctx(a->argv[2], &ext, &ctx);
 	if (ctx == NULL)			/* supply default context if needed */
 		ctx = o->owner->context;
 	if (!ast_exists_extension(b, ctx, ext, 1, b->cid.cid_num))
-		ast_cli(fd, "No such extension exists\n");
+		ast_cli(a->fd, "No such extension exists\n");
 	else {
-		ast_cli(fd, "Whee, transferring %s to %s@%s.\n", b->name, ext, ctx);
+		ast_cli(a->fd, "Whee, transferring %s to %s@%s.\n", b->name, ext, ctx);
 		if (ast_async_goto(b, ctx, ext, 1))
-			ast_cli(fd, "Failed to transfer :(\n");
+			ast_cli(a->fd, "Failed to transfer :(\n");
 	}
 	if (tmp)
 		ast_free(tmp);
-	return RESULT_SUCCESS;
+	return CLI_SUCCESS;
 }
 
-static const char transfer_usage[] =
-	"Usage: console transfer <extension>[@context]\n"
-	"       Transfers the currently connected call to the given extension (and\n"
-	"context if specified)\n";
-
-static int console_active(int fd, int argc, char *argv[])
+static char *console_active(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
-	if (argc == 2)
-		ast_cli(fd, "active console is [%s]\n", oss_active);
-	else if (argc != 3)
-		return RESULT_SHOWUSAGE;
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "console active";
+		e->usage =
+			"Usage: console active [device]\n"
+			"       If used without a parameter, displays which device is the current\n"
+			"       console.  If a device is specified, the console sound device is changed to\n"
+			"       the device specified.\n";
+		return NULL;
+	case CLI_GENERATE:
+		return NULL;
+	}
+
+	if (a->argc == 2)
+		ast_cli(a->fd, "active console is [%s]\n", oss_active);
+	else if (a->argc != 3)
+		return CLI_SHOWUSAGE;
 	else {
 		struct chan_oss_pvt *o;
-		if (strcmp(argv[2], "show") == 0) {
+		if (strcmp(a->argv[2], "show") == 0) {
 			for (o = oss_default.next; o; o = o->next)
-				ast_cli(fd, "device [%s] exists\n", o->name);
-			return RESULT_SUCCESS;
+				ast_cli(a->fd, "device [%s] exists\n", o->name);
+			return CLI_SUCCESS;
 		}
-		o = find_desc(argv[2]);
+		o = find_desc(a->argv[2]);
 		if (o == NULL)
-			ast_cli(fd, "No device [%s] exists\n", argv[2]);
+			ast_cli(a->fd, "No device [%s] exists\n", a->argv[2]);
 		else
 			oss_active = o->name;
 	}
-	return RESULT_SUCCESS;
+	return CLI_SUCCESS;
 }
 
-static const char active_usage[] =
-	"Usage: console active [device]\n"
-	"       If used without a parameter, displays which device is the current\n"
-	"console.  If a device is specified, the console sound device is changed to\n"
-	"the device specified.\n";
-
 /*!
  * \brief store the boost factor
  */
@@ -1418,15 +1432,26 @@ static void store_boost(struct chan_oss_pvt *o, char *s)
 	ast_log(LOG_WARNING, "setting boost %s to %d\n", s, o->boost);
 }
 
-static int do_boost(int fd, int argc, char *argv[])
+static char *console_boost(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
 	struct chan_oss_pvt *o = find_desc(oss_active);
 
-	if (argc == 2)
-		ast_cli(fd, "boost currently %5.1f\n", 20 * log10(((double) o->boost / (double) BOOST_SCALE)));
-	else if (argc == 3)
-		store_boost(o, argv[2]);
-	return RESULT_SUCCESS;
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "console boost";
+		e->usage =
+			"Usage: console boost [boost in dB]\n"
+			"       Sets or display mic boost in dB\n";
+		return NULL;
+	case CLI_GENERATE:
+		return NULL;
+	}
+
+	if (a->argc == 2)
+		ast_cli(a->fd, "boost currently %5.1f\n", 20 * log10(((double) o->boost / (double) BOOST_SCALE)));
+	else if (a->argc == 3)
+		store_boost(o, a->argv[2]);
+	return CLI_SUCCESS;
 }
 
 static struct ast_cli_entry cli_oss[] = {
@@ -1435,20 +1460,11 @@ static struct ast_cli_entry cli_oss[] = {
 	NEW_CLI(console_flash, "Flash a call on the console"),
 	NEW_CLI(console_dial, "Dial an extension on the console"),
 	NEW_CLI(console_mute, "Disable/Enable mic input"),
-	{ { "console", "transfer", NULL },
-	console_transfer, "Transfer a call to a different extension",
-	transfer_usage },
-
+	NEW_CLI(console_transfer, "Transfer a call to a different extension"),	
 	NEW_CLI(console_sendtext, "Send text to the remote device"),
 	NEW_CLI(console_autoanswer, "Sets/displays autoanswer"),
-
-	{ { "console", "boost", NULL },
-	do_boost, "Sets/displays mic boost in dB",
-	NULL },
-
-	{ { "console", "active", NULL },
-	console_active, "Sets/displays active console",
-	active_usage },
+	NEW_CLI(console_boost, "Sets/displays mic boost in dB"),
+	NEW_CLI(console_active, "Sets/displays active console"),
 };
 
 /*!
diff --git a/channels/chan_skinny.c b/channels/chan_skinny.c
index b1a83abbea73f886a6b5130580f5c761e81924d0..0e58689824ff29b6df5e13d83d405b3f0256ce40 100644
--- a/channels/chan_skinny.c
+++ b/channels/chan_skinny.c
@@ -2262,24 +2262,46 @@ static struct ast_rtp_protocol skinny_rtp = {
 	.set_rtp_peer = skinny_set_rtp_peer,
 };
 
-static int skinny_do_debug(int fd, int argc, char *argv[])
+static char *handle_skinny_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
-	if (argc != 3)
-		return RESULT_SHOWUSAGE;
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "skinny set debug";
+		e->usage =
+			"Usage: skinny set debug\n"
+			"       Enables dumping of Skinny packets for debugging purposes\n";
+		return NULL;
+	case CLI_GENERATE:
+		return NULL;
+	}
+	
+	if (a->argc != 3)
+		return CLI_SHOWUSAGE;
 
 	skinnydebug = 1;
-	ast_cli(fd, "Skinny Debugging Enabled\n");
-	return RESULT_SUCCESS;
+	ast_cli(a->fd, "Skinny Debugging Enabled\n");
+	return CLI_SUCCESS;
 }
 
-static int skinny_no_debug(int fd, int argc, char *argv[])
+static char *handle_skinny_set_debug_off(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
-	if (argc != 4)
-		return RESULT_SHOWUSAGE;
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "skinny set debug off";
+		e->usage =
+			"Usage: skinny set debug off\n"
+			"       Disables dumping of Skinny packets for debugging purposes\n";
+		return NULL;
+	case CLI_GENERATE:
+		return NULL;
+	}
+
+	if (a->argc != 4)
+		return CLI_SHOWUSAGE;
 
 	skinnydebug = 0;
-	ast_cli(fd, "Skinny Debugging Disabled\n");
-	return RESULT_SUCCESS;
+	ast_cli(a->fd, "Skinny Debugging Disabled\n");
+	return CLI_SUCCESS;
 }
 
 static char *complete_skinny_devices(const char *word, int state)
@@ -2306,7 +2328,7 @@ static char *complete_skinny_reset(const char *line, const char *word, int pos,
 	return (pos == 2 ? ast_strdup(complete_skinny_devices(word, state)) : NULL);
 }
 
-static char *complete_skinny_show_lines(const char *line, const char *word, int pos, int state)
+static char *complete_skinny_show_line(const char *line, const char *word, int pos, int state)
 {
 	struct skinny_device *d;
 	struct skinny_line *l;
@@ -2326,26 +2348,37 @@ static char *complete_skinny_show_lines(const char *line, const char *word, int
 	return result;
 }
 
-static int skinny_reset_device(int fd, int argc, char *argv[])
+static char *handle_skinny_reset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
 	struct skinny_device *d;
 	struct skinny_req *req;
 
-	if (argc < 3 || argc > 4)
-		return RESULT_SHOWUSAGE;
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "skinny reset";
+		e->usage =
+			"Usage: skinny reset <DeviceId|DeviceName|all> [restart]\n"
+			"       Causes a Skinny device to reset itself, optionally with a full restart\n";
+		return NULL;
+	case CLI_GENERATE:
+		return complete_skinny_reset(a->line, a->word, a->pos, a->n);
+	}
+
+	if (a->argc < 3 || a->argc > 4)
+		return CLI_SHOWUSAGE;
 
 	ast_mutex_lock(&devicelock);
 
 	for (d = devices; d; d = d->next) {
 		int fullrestart = 0;
-		if (!strcasecmp(argv[2], d->id) || !strcasecmp(argv[2], d->name) || !strcasecmp(argv[2], "all")) {
+		if (!strcasecmp(a->argv[2], d->id) || !strcasecmp(a->argv[2], d->name) || !strcasecmp(a->argv[2], "all")) {
 			if (!(d->session))
 				continue;
 
 			if (!(req = req_alloc(sizeof(struct reset_message), RESET_MESSAGE)))
 				continue;
 
-			if (argc == 4 && !strcasecmp(argv[3], "restart"))
+			if (a->argc == 4 && !strcasecmp(a->argv[3], "restart"))
 				fullrestart = 1;
 
 			if (fullrestart)
@@ -2358,7 +2391,7 @@ static int skinny_reset_device(int fd, int argc, char *argv[])
 		}
 	}
 	ast_mutex_unlock(&devicelock);
-	return RESULT_SUCCESS;
+	return CLI_SUCCESS;
 }
 
 static char *device2str(int type)
@@ -2450,18 +2483,29 @@ static void print_codec_to_cli(int fd, struct ast_codec_pref *pref)
 		ast_cli(fd, "none");
 }
 
-static int skinny_show_devices(int fd, int argc, char *argv[])
+static char *handle_skinny_show_devices(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
 	struct skinny_device *d;
 	struct skinny_line *l;
 
-	if (argc != 3)
-		return RESULT_SHOWUSAGE;
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "skinny show devices";
+		e->usage =
+			"Usage: skinny show devices\n"
+			"       Lists all devices known to the Skinny subsystem.\n";
+		return NULL;
+	case CLI_GENERATE:
+		return NULL;
+	}
+
+	if (a->argc != 3)
+		return CLI_SHOWUSAGE;
 
 	ast_mutex_lock(&devicelock);
 
-	ast_cli(fd, "Name                 DeviceId         IP              Type            R NL\n");
-	ast_cli(fd, "-------------------- ---------------- --------------- --------------- - --\n");
+	ast_cli(a->fd, "Name                 DeviceId         IP              Type            R NL\n");
+	ast_cli(a->fd, "-------------------- ---------------- --------------- --------------- - --\n");
 
 	for (d = devices; d; d = d->next) {
 		int numlines = 0;
@@ -2469,7 +2513,7 @@ static int skinny_show_devices(int fd, int argc, char *argv[])
 		for (l = d->lines; l; l = l->next)
 			numlines++;
 		
-		ast_cli(fd, "%-20s %-16s %-15s %-15s %c %2d\n",
+		ast_cli(a->fd, "%-20s %-16s %-15s %-15s %c %2d\n",
 			d->name,
 			d->id,
 			d->session?ast_inet_ntoa(d->session->sin.sin_addr):"",
@@ -2480,69 +2524,91 @@ static int skinny_show_devices(int fd, int argc, char *argv[])
 
 	ast_mutex_unlock(&devicelock);
 
-	return RESULT_SUCCESS;
+	return CLI_SUCCESS;
 }
 
 /*! \brief Show device information */
-static int skinny_show_device(int fd, int argc, char *argv[])
+static char *handle_skinny_show_device(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
 	struct skinny_device *d;
 	struct skinny_line *l;
 	struct skinny_speeddial *sd;
-	struct skinny_addon *a;
+	struct skinny_addon *sa;
+
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "skinny show device";
+		e->usage =
+			"Usage: skinny show device <DeviceId|DeviceName>\n"
+			"       Lists all deviceinformation of a specific device known to the Skinny subsystem.\n";
+		return NULL;
+	case CLI_GENERATE:
+		return complete_skinny_show_device(a->line, a->word, a->pos, a->n);
+	}
 
-	if (argc < 4)
-		return RESULT_SHOWUSAGE;
+	if (a->argc < 4)
+		return CLI_SHOWUSAGE;
 
 	ast_mutex_lock(&devicelock);
 	for (d = devices; d; d = d->next) {
-		if (!strcasecmp(argv[3], d->id) || !strcasecmp(argv[3], d->name)) {
+		if (!strcasecmp(a->argv[3], d->id) || !strcasecmp(a->argv[3], d->name)) {
 			int numlines = 0, numaddons = 0, numspeeddials = 0;
 
 			for (l = d->lines; l; l = l->next)
 				numlines++;
 
-			ast_cli(fd, "Name:        %s\n", d->name);
-			ast_cli(fd, "Id:          %s\n", d->id);
-			ast_cli(fd, "version:     %s\n", S_OR(d->version_id, "Unknown"));
-			ast_cli(fd, "Ip address:  %s\n", (d->session ? ast_inet_ntoa(d->session->sin.sin_addr) : "Unknown"));
-			ast_cli(fd, "Port:        %d\n", (d->session ? ntohs(d->session->sin.sin_port) : 0));
-			ast_cli(fd, "Device Type: %s\n", device2str(d->type));
-			ast_cli(fd, "Registered:  %s\n", (d->registered ? "Yes" : "No"));
-			ast_cli(fd, "Lines:       %d\n", numlines);
+			ast_cli(a->fd, "Name:        %s\n", d->name);
+			ast_cli(a->fd, "Id:          %s\n", d->id);
+			ast_cli(a->fd, "version:     %s\n", S_OR(d->version_id, "Unknown"));
+			ast_cli(a->fd, "Ip address:  %s\n", (d->session ? ast_inet_ntoa(d->session->sin.sin_addr) : "Unknown"));
+			ast_cli(a->fd, "Port:        %d\n", (d->session ? ntohs(d->session->sin.sin_port) : 0));
+			ast_cli(a->fd, "Device Type: %s\n", device2str(d->type));
+			ast_cli(a->fd, "Registered:  %s\n", (d->registered ? "Yes" : "No"));
+			ast_cli(a->fd, "Lines:       %d\n", numlines);
 			for (l = d->lines; l; l = l->next)
-				ast_cli(fd, "  %s (%s)\n", l->name, l->label);
-			for (a = d->addons; a; a = a->next)
+				ast_cli(a->fd, "  %s (%s)\n", l->name, l->label);
+			for (sa = d->addons; sa; sa = sa->next)
 				numaddons++;
-			ast_cli(fd, "Addons:      %d\n", numaddons);
-			for (a = d->addons; a; a = a->next)
-				ast_cli(fd, "  %s\n", a->type);
+			ast_cli(a->fd, "Addons:      %d\n", numaddons);
+			for (sa = d->addons; sa; sa = sa->next)
+				ast_cli(a->fd, "  %s\n", sa->type);
 			for (sd = d->speeddials; sd; sd = sd->next)
 				numspeeddials++;
-			ast_cli(fd, "Speeddials:  %d\n", numspeeddials);
+			ast_cli(a->fd, "Speeddials:  %d\n", numspeeddials);
 			for (sd = d->speeddials; sd; sd = sd->next)
-				ast_cli(fd, "  %s (%s) ishint: %d\n", sd->exten, sd->label, sd->isHint);
+				ast_cli(a->fd, "  %s (%s) ishint: %d\n", sd->exten, sd->label, sd->isHint);
 		}
 	}
 	ast_mutex_unlock(&devicelock);
-	return RESULT_SUCCESS;
+	return CLI_SUCCESS;
 }
 
-static int skinny_show_lines(int fd, int argc, char *argv[])
+static char *handle_skinny_show_lines(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
 	struct skinny_device *d;
 	struct skinny_line *l;
 
-	if (argc != 3)
-		return RESULT_SHOWUSAGE;
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "skinny show lines";
+		e->usage =
+			"Usage: skinny show lines\n"
+			"       Lists all lines known to the Skinny subsystem.\n";
+		return NULL;
+	case CLI_GENERATE:
+		return NULL;
+	}
+
+	if (a->argc != 3)
+		return CLI_SHOWUSAGE;
 	
 	ast_mutex_lock(&devicelock);
 	
-	ast_cli(fd, "Device Name          Instance Name                 Label               \n");
-	ast_cli(fd, "-------------------- -------- -------------------- --------------------\n");
+	ast_cli(a->fd, "Device Name          Instance Name                 Label               \n");
+	ast_cli(a->fd, "-------------------- -------- -------------------- --------------------\n");
 	for (d = devices; d; d = d->next) {
 		for (l = d->lines; l; l = l->next) {
-			ast_cli(fd, "%-20s %8d %-20s %-20s\n",
+			ast_cli(a->fd, "%-20s %8d %-20s %-20s\n",
 				d->name,
 				l->instance,
 				l->name,
@@ -2551,162 +2617,128 @@ static int skinny_show_lines(int fd, int argc, char *argv[])
 	}
 	
 	ast_mutex_unlock(&devicelock);
-	return RESULT_SUCCESS;
+	return CLI_SUCCESS;
 }
 
 /*! \brief List line information. */
-static int skinny_show_line(int fd, int argc, char *argv[])
+static char *handle_skinny_show_line(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
 	struct skinny_device *d;
 	struct skinny_line *l;
-
 	char codec_buf[512];
 	char group_buf[256];
 
-	if (argc < 4)
-		return RESULT_SHOWUSAGE;
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "skinny show line";
+		e->usage =
+			"Usage: skinny show line <Line> [ on <DeviceID|DeviceName> ]\n"
+			"       List all lineinformation of a specific line known to the Skinny subsystem.\n";
+		return NULL;
+	case CLI_GENERATE:
+		return complete_skinny_show_line(a->line, a->word, a->pos, a->n);
+	}
+
+	if (a->argc < 4)
+		return CLI_SHOWUSAGE;
 	
 	ast_mutex_lock(&devicelock);
 
 	/* Show all lines matching the one supplied */
 	for (d = devices; d; d = d->next) {
-		if (argc == 6 && (strcasecmp(argv[5], d->id) && strcasecmp(argv[5], d->name)))
+		if (a->argc == 6 && (strcasecmp(a->argv[5], d->id) && strcasecmp(a->argv[5], d->name)))
 			continue;
 		for (l = d->lines; l; l = l->next) {
-			if (strcasecmp(argv[3], l->name))
+			if (strcasecmp(a->argv[3], l->name))
 				continue;
-			ast_cli(fd, "Line:             %s\n", l->name);
-			ast_cli(fd, "On Device:        %s\n", d->name);
-			ast_cli(fd, "Line Label:       %s\n", l->label);
-			ast_cli(fd, "Extension:        %s\n", S_OR(l->exten, "<not set>"));
-			ast_cli(fd, "Context:          %s\n", l->context);
-			ast_cli(fd, "CallGroup:        %s\n", ast_print_group(group_buf, sizeof(group_buf), l->callgroup));
-			ast_cli(fd, "PickupGroup:      %s\n", ast_print_group(group_buf, sizeof(group_buf), l->pickupgroup));
-			ast_cli(fd, "Language:         %s\n", S_OR(l->language, "<not set>"));
-			ast_cli(fd, "Accountcode:      %s\n", S_OR(l->accountcode, "<not set>"));
-			ast_cli(fd, "AmaFlag:          %s\n", ast_cdr_flags2str(l->amaflags));
-			ast_cli(fd, "CallerId Number:  %s\n", S_OR(l->cid_num, "<not set>"));
-			ast_cli(fd, "CallerId Name:    %s\n", S_OR(l->cid_name, "<not set>"));
-			ast_cli(fd, "Hide CallerId:    %s\n", (l->hidecallerid ? "Yes" : "No"));
-			ast_cli(fd, "CallForward:      %s\n", S_OR(l->call_forward, "<not set>"));
-			ast_cli(fd, "VoicemailBox:     %s\n", S_OR(l->mailbox, "<not set>"));
-			ast_cli(fd, "VoicemailNumber:  %s\n", S_OR(l->vmexten, "<not set>"));
-			ast_cli(fd, "MWIblink:         %d\n", l->mwiblink);
-			ast_cli(fd, "Regextension:     %s\n", S_OR(l->regexten, "<not set>"));
-			ast_cli(fd, "Regcontext:       %s\n", S_OR(l->regcontext, "<not set>"));
-			ast_cli(fd, "MoHInterpret:     %s\n", S_OR(l->mohinterpret, "<not set>"));
-			ast_cli(fd, "MoHSuggest:       %s\n", S_OR(l->mohsuggest, "<not set>"));
-			ast_cli(fd, "Last dialed nr:   %s\n", S_OR(l->lastnumberdialed, "<no calls made yet>"));
-			ast_cli(fd, "Last CallerID:    %s\n", S_OR(l->lastcallerid, "<not set>"));
-			ast_cli(fd, "Transfer enabled: %s\n", (l->transfer ? "Yes" : "No"));
-			ast_cli(fd, "Callwaiting:      %s\n", (l->callwaiting ? "Yes" : "No"));
-			ast_cli(fd, "3Way Calling:     %s\n", (l->threewaycalling ? "Yes" : "No"));
-			ast_cli(fd, "Can forward:      %s\n", (l->cancallforward ? "Yes" : "No"));
-			ast_cli(fd, "Do Not Disturb:   %s\n", (l->dnd ? "Yes" : "No"));
-			ast_cli(fd, "NAT:              %s\n", (l->nat ? "Yes" : "No"));
-			ast_cli(fd, "immediate:        %s\n", (l->immediate ? "Yes" : "No"));
-			ast_cli(fd, "Group:            %d\n", l->group);
-			ast_cli(fd, "Codecs:           ");
-			ast_getformatname_multiple(codec_buf, sizeof(codec_buf) -1, l->capability);
-			ast_cli(fd, "%s\n", codec_buf);
-			ast_cli(fd, "Codec Order:      (");
-			print_codec_to_cli(fd, &l->prefs);
-			ast_cli(fd, ")\n");
-			ast_cli(fd, "\n");
+			ast_cli(a->fd, "Line:             %s\n", l->name);
+			ast_cli(a->fd, "On Device:        %s\n", d->name);
+			ast_cli(a->fd, "Line Label:       %s\n", l->label);
+			ast_cli(a->fd, "Extension:        %s\n", S_OR(l->exten, "<not set>"));
+			ast_cli(a->fd, "Context:          %s\n", l->context);
+			ast_cli(a->fd, "CallGroup:        %s\n", ast_print_group(group_buf, sizeof(group_buf), l->callgroup));
+			ast_cli(a->fd, "PickupGroup:      %s\n", ast_print_group(group_buf, sizeof(group_buf), l->pickupgroup));
+			ast_cli(a->fd, "Language:         %s\n", S_OR(l->language, "<not set>"));
+			ast_cli(a->fd, "Accountcode:      %s\n", S_OR(l->accountcode, "<not set>"));
+			ast_cli(a->fd, "AmaFlag:          %s\n", ast_cdr_flags2str(l->amaflags));
+			ast_cli(a->fd, "CallerId Number:  %s\n", S_OR(l->cid_num, "<not set>"));
+			ast_cli(a->fd, "CallerId Name:    %s\n", S_OR(l->cid_name, "<not set>"));
+			ast_cli(a->fd, "Hide CallerId:    %s\n", (l->hidecallerid ? "Yes" : "No"));
+			ast_cli(a->fd, "CallForward:      %s\n", S_OR(l->call_forward, "<not set>"));
+			ast_cli(a->fd, "VoicemailBox:     %s\n", S_OR(l->mailbox, "<not set>"));
+			ast_cli(a->fd, "VoicemailNumber:  %s\n", S_OR(l->vmexten, "<not set>"));
+			ast_cli(a->fd, "MWIblink:         %d\n", l->mwiblink);
+			ast_cli(a->fd, "Regextension:     %s\n", S_OR(l->regexten, "<not set>"));
+			ast_cli(a->fd, "Regcontext:       %s\n", S_OR(l->regcontext, "<not set>"));
+			ast_cli(a->fd, "MoHInterpret:     %s\n", S_OR(l->mohinterpret, "<not set>"));
+			ast_cli(a->fd, "MoHSuggest:       %s\n", S_OR(l->mohsuggest, "<not set>"));
+			ast_cli(a->fd, "Last dialed nr:   %s\n", S_OR(l->lastnumberdialed, "<no calls made yet>"));
+			ast_cli(a->fd, "Last CallerID:    %s\n", S_OR(l->lastcallerid, "<not set>"));
+			ast_cli(a->fd, "Transfer enabled: %s\n", (l->transfer ? "Yes" : "No"));
+			ast_cli(a->fd, "Callwaiting:      %s\n", (l->callwaiting ? "Yes" : "No"));
+			ast_cli(a->fd, "3Way Calling:     %s\n", (l->threewaycalling ? "Yes" : "No"));
+			ast_cli(a->fd, "Can forward:      %s\n", (l->cancallforward ? "Yes" : "No"));
+			ast_cli(a->fd, "Do Not Disturb:   %s\n", (l->dnd ? "Yes" : "No"));
+			ast_cli(a->fd, "NAT:              %s\n", (l->nat ? "Yes" : "No"));
+			ast_cli(a->fd, "immediate:        %s\n", (l->immediate ? "Yes" : "No"));
+			ast_cli(a->fd, "Group:            %d\n", l->group);
+			ast_cli(a->fd, "Codecs:           ");
+			ast_getformatname_multiple(codec_buf, sizeof(codec_buf) - 1, l->capability);
+			ast_cli(a->fd, "%s\n", codec_buf);
+			ast_cli(a->fd, "Codec Order:      (");
+			print_codec_to_cli(a->fd, &l->prefs);
+			ast_cli(a->fd, ")\n");
+			ast_cli(a->fd, "\n");
 		}
 	}
 	
 	ast_mutex_unlock(&devicelock);
-	return RESULT_SUCCESS;
+	return CLI_SUCCESS;
 }
 
 /*! \brief List global settings for the Skinny subsystem. */
-static int skinny_show_settings(int fd, int argc, char *argv[])
+static char *handle_skinny_show_settings(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
-	if (argc != 3)
-		return RESULT_SHOWUSAGE;
-
-	ast_cli(fd, "\nGlobal Settings:\n");
-	ast_cli(fd, "  Skinny Port:            %d\n", ntohs(bindaddr.sin_port));
-	ast_cli(fd, "  Bindaddress:            %s\n", ast_inet_ntoa(bindaddr.sin_addr));
-	ast_cli(fd, "  KeepAlive:              %d\n", keep_alive);
-	ast_cli(fd, "  Date Format:            %s\n", date_format);
-	ast_cli(fd, "  Voice Mail Extension:   %s\n", S_OR(vmexten, "(not set)"));
-	ast_cli(fd, "  Reg. context:           %s\n", S_OR(regcontext, "(not set)"));
-	ast_cli(fd, "  Jitterbuffer enabled:   %s\n", (ast_test_flag(&global_jbconf, AST_JB_ENABLED) ? "Yes" : "No"));
-	ast_cli(fd, "  Jitterbuffer forced:    %s\n", (ast_test_flag(&global_jbconf, AST_JB_FORCED) ? "Yes" : "No"));
-	ast_cli(fd, "  Jitterbuffer max size:  %ld\n", global_jbconf.max_size);
-	ast_cli(fd, "  Jitterbuffer resync:    %ld\n", global_jbconf.resync_threshold);
-	ast_cli(fd, "  Jitterbuffer impl:      %s\n", global_jbconf.impl);
-	ast_cli(fd, "  Jitterbuffer log:       %s\n", (ast_test_flag(&global_jbconf, AST_JB_LOG) ? "Yes" : "No"));
-
-	return RESULT_SUCCESS;
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "skinny show settings";
+		e->usage =
+			"Usage: skinny show settings\n"
+			"       Lists all global configuration settings of the Skinny subsystem.\n";
+		return NULL;
+	case CLI_GENERATE:
+		return NULL;
+	}	
+
+	if (a->argc != 3)
+		return CLI_SHOWUSAGE;
+
+	ast_cli(a->fd, "\nGlobal Settings:\n");
+	ast_cli(a->fd, "  Skinny Port:            %d\n", ntohs(bindaddr.sin_port));
+	ast_cli(a->fd, "  Bindaddress:            %s\n", ast_inet_ntoa(bindaddr.sin_addr));
+	ast_cli(a->fd, "  KeepAlive:              %d\n", keep_alive);
+	ast_cli(a->fd, "  Date Format:            %s\n", date_format);
+	ast_cli(a->fd, "  Voice Mail Extension:   %s\n", S_OR(vmexten, "(not set)"));
+	ast_cli(a->fd, "  Reg. context:           %s\n", S_OR(regcontext, "(not set)"));
+	ast_cli(a->fd, "  Jitterbuffer enabled:   %s\n", (ast_test_flag(&global_jbconf, AST_JB_ENABLED) ? "Yes" : "No"));
+	ast_cli(a->fd, "  Jitterbuffer forced:    %s\n", (ast_test_flag(&global_jbconf, AST_JB_FORCED) ? "Yes" : "No"));
+	ast_cli(a->fd, "  Jitterbuffer max size:  %ld\n", global_jbconf.max_size);
+	ast_cli(a->fd, "  Jitterbuffer resync:    %ld\n", global_jbconf.resync_threshold);
+	ast_cli(a->fd, "  Jitterbuffer impl:      %s\n", global_jbconf.impl);
+	ast_cli(a->fd, "  Jitterbuffer log:       %s\n", (ast_test_flag(&global_jbconf, AST_JB_LOG) ? "Yes" : "No"));
+
+	return CLI_SUCCESS;
 }
 
-static const char show_devices_usage[] =
-"Usage: skinny show devices\n"
-"       Lists all devices known to the Skinny subsystem.\n";
-
-static const char show_device_usage[] =
-"Usage: skinny show device <DeviceId|DeviceName>\n"
-"       Lists all deviceinformation of a specific device known to the Skinny subsystem.\n";
-
-static const char show_lines_usage[] =
-"Usage: skinny show lines\n"
-"       Lists all lines known to the Skinny subsystem.\n";
-
-static const char show_line_usage[] =
-"Usage: skinny show line <Line> [ on <DeviceID|DeviceName> ]\n"
-"       List all lineinformation of a specific line known to the Skinny subsystem.\n";
-
-static const char show_settings_usage[] =
-"Usage: skinny show settings\n"
-"       Lists all global configuration settings of the Skinny subsystem.\n";
-
-static const char debug_usage[] =
-"Usage: skinny set debug\n"
-"       Enables dumping of Skinny packets for debugging purposes\n";
-
-static const char no_debug_usage[] =
-"Usage: skinny set debug off\n"
-"       Disables dumping of Skinny packets for debugging purposes\n";
-
-static const char reset_usage[] =
-"Usage: skinny reset <DeviceId|DeviceName|all> [restart]\n"
-"       Causes a Skinny device to reset itself, optionally with a full restart\n";
-
 static struct ast_cli_entry cli_skinny[] = {
-	{ { "skinny", "show", "devices", NULL },
-	skinny_show_devices, "List defined Skinny devices",
-	show_devices_usage },
-
-	{ { "skinny", "show", "device", NULL },
-	skinny_show_device, "List Skinny device information",
-	show_device_usage, complete_skinny_show_device },
-
-	{ { "skinny", "show", "lines", NULL },
-	skinny_show_lines, "List defined Skinny lines per device",
-	show_lines_usage },
-
-	{ { "skinny", "show", "line", NULL },
-	skinny_show_line, "List Skinny line information",
-	show_line_usage, complete_skinny_show_lines },
-
-	{ { "skinny", "show", "settings", NULL },
-	skinny_show_settings, "List global Skinny settings",
-	show_settings_usage },
-
-	{ { "skinny", "set", "debug", NULL },
-	skinny_do_debug, "Enable Skinny debugging",
-	debug_usage },
-
-	{ { "skinny", "set", "debug", "off", NULL },
-	skinny_no_debug, "Disable Skinny debugging",
-	no_debug_usage },
-
-	{ { "skinny", "reset", NULL },
-	skinny_reset_device, "Reset Skinny device(s)",
-	reset_usage, complete_skinny_reset },
+	NEW_CLI(handle_skinny_show_devices, "List defined Skinny devices"),
+	NEW_CLI(handle_skinny_show_device, "List Skinny device information"),
+	NEW_CLI(handle_skinny_show_lines, "List defined Skinny lines per device"),	
+	NEW_CLI(handle_skinny_show_line, "List Skinny line information"),
+	NEW_CLI(handle_skinny_show_settings, "List global Skinny settings"),
+	NEW_CLI(handle_skinny_set_debug, "Enable Skinny debugging"),
+	NEW_CLI(handle_skinny_set_debug_off, "Disable Skinny debugging"),
+	NEW_CLI(handle_skinny_reset, "Reset Skinny device(s)"),
 };
 
 #if 0
diff --git a/channels/iax2-provision.c b/channels/iax2-provision.c
index 031897fc7020a8da87cd92139dc5f00a08e55e40..782a4097e11d5f4f137e52cad2a74debd19950c8 100644
--- a/channels/iax2-provision.c
+++ b/channels/iax2-provision.c
@@ -166,15 +166,16 @@ char *iax_prov_complete_template(const char *line, const char *word, int pos, in
 	char *ret = NULL;
 	int wordlen = strlen(word);
 
-	ast_mutex_lock(&provlock);
-	for (c = templates; c; c = c->next) {
-		if (!strncasecmp(word, c->name, wordlen) && ++which > state) {
-			ret = ast_strdup(c->name);
-			break;
+	if (pos == 3) {
+		ast_mutex_lock(&provlock);
+		for (c = templates; c; c = c->next) {
+			if (!strncasecmp(word, c->name, wordlen) && ++which > state) {
+				ret = ast_strdup(c->name);
+				break;
+			}
 		}
+		ast_mutex_unlock(&provlock);
 	}
-	ast_mutex_unlock(&provlock);
-	
 	return ret;
 }
 
@@ -398,11 +399,6 @@ static int iax_process_template(struct ast_config *cfg, char *s, char *def)
 	return 0;
 }
 
-static const char show_provisioning_usage[] = 
-"Usage: iax list provisioning [template]\n"
-"       Lists all known IAX provisioning templates or a\n"
-"       specific one if specified.\n";
-
 static const char *ifthere(const char *s)
 {
 	if (strlen(s))
@@ -424,51 +420,62 @@ static const char *iax_server(unsigned int addr)
 }
 
 
-static int iax_show_provisioning(int fd, int argc, char *argv[])
+static char *iax_show_provisioning(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
 	struct iax_template *cur;
 	char server[INET_ADDRSTRLEN];
 	char alternate[INET_ADDRSTRLEN];
 	char flags[80];	/* Has to be big enough for 'flags' too */
 	int found = 0;
-	if ((argc != 3) && (argc != 4))
-		return RESULT_SHOWUSAGE;
+
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "iax2 show provisioning";
+		e->usage =
+			"Usage: iax2 show provisioning [template]\n"
+			"       Lists all known IAX provisioning templates or a\n"
+			"       specific one if specified.\n";
+		return NULL;
+	case CLI_GENERATE:
+		return iax_prov_complete_template(a->line, a->word, a->pos, a->n);
+	}
+
+	if ((a->argc != 3) && (a->argc != 4))
+		return CLI_SHOWUSAGE;
 	ast_mutex_lock(&provlock);
 	for (cur = templates;cur;cur = cur->next) {
-		if ((argc == 3) || (!strcasecmp(argv[3], cur->name)))  {
+		if ((a->argc == 3) || (!strcasecmp(a->argv[3], cur->name)))  {
 			if (found) 
-				ast_cli(fd, "\n");
+				ast_cli(a->fd, "\n");
 			ast_copy_string(server, iax_server(cur->server), sizeof(server));
 			ast_copy_string(alternate, iax_server(cur->altserver), sizeof(alternate));
-			ast_cli(fd, "== %s ==\n", cur->name);
-			ast_cli(fd, "Base Templ:   %s\n", strlen(cur->src) ? cur->src : "<none>");
-			ast_cli(fd, "Username:     %s\n", ifthere(cur->user));
-			ast_cli(fd, "Secret:       %s\n", ifthere(cur->pass));
-			ast_cli(fd, "Language:     %s\n", ifthere(cur->lang));
-			ast_cli(fd, "Bind Port:    %d\n", cur->port);
-			ast_cli(fd, "Server:       %s\n", server);
-			ast_cli(fd, "Server Port:  %d\n", cur->serverport);
-			ast_cli(fd, "Alternate:    %s\n", alternate);
-			ast_cli(fd, "Flags:        %s\n", iax_provflags2str(flags, sizeof(flags), cur->flags));
-			ast_cli(fd, "Format:       %s\n", ast_getformatname(cur->format));
-			ast_cli(fd, "TOS:          0x%x\n", cur->tos);
+			ast_cli(a->fd, "== %s ==\n", cur->name);
+			ast_cli(a->fd, "Base Templ:   %s\n", strlen(cur->src) ? cur->src : "<none>");
+			ast_cli(a->fd, "Username:     %s\n", ifthere(cur->user));
+			ast_cli(a->fd, "Secret:       %s\n", ifthere(cur->pass));
+			ast_cli(a->fd, "Language:     %s\n", ifthere(cur->lang));
+			ast_cli(a->fd, "Bind Port:    %d\n", cur->port);
+			ast_cli(a->fd, "Server:       %s\n", server);
+			ast_cli(a->fd, "Server Port:  %d\n", cur->serverport);
+			ast_cli(a->fd, "Alternate:    %s\n", alternate);
+			ast_cli(a->fd, "Flags:        %s\n", iax_provflags2str(flags, sizeof(flags), cur->flags));
+			ast_cli(a->fd, "Format:       %s\n", ast_getformatname(cur->format));
+			ast_cli(a->fd, "TOS:          0x%x\n", cur->tos);
 			found++;
 		}
 	}
 	ast_mutex_unlock(&provlock);
 	if (!found) {
-		if (argc == 3)
-			ast_cli(fd, "No provisioning templates found\n");
+		if (a->argc == 3)
+			ast_cli(a->fd, "No provisioning templates found\n");
 		else
-			ast_cli(fd, "No provisioning template matching '%s' found\n", argv[3]);
+			ast_cli(a->fd, "No provisioning template matching '%s' found\n", a->argv[3]);
 	}
-	return RESULT_SUCCESS;
+	return CLI_SUCCESS;
 }
 
 static struct ast_cli_entry cli_iax2_provision[] = {
-	{ { "iax2", "show", "provisioning", NULL },
-	iax_show_provisioning, "Display iax provisioning",
-	show_provisioning_usage, iax_prov_complete_template, },
+	NEW_CLI(iax_show_provisioning, "Display iax provisioning"),
 };
 
 static int iax_provision_init(void)
diff --git a/main/asterisk.c b/main/asterisk.c
index 59b97e59e3882a55bf961ae3f9e4e341c858a4f8..6e9ccb7d4a225e8c831a38f6bcdcd666dc56e4c7 100644
--- a/main/asterisk.c
+++ b/main/asterisk.c
@@ -305,10 +305,6 @@ struct thread_list_t {
 
 static AST_RWLIST_HEAD_STATIC(thread_list, thread_list_t);
 
-static const char show_threads_help[] =
-"Usage: core show threads\n"
-"       List threads currently active in the system.\n";
-
 void ast_register_thread(char *name)
 { 
 	struct thread_list_t *new = ast_calloc(1, sizeof(*new));
@@ -342,105 +338,130 @@ void ast_unregister_thread(void *id)
 }
 
 /*! \brief Give an overview of core settings */
-static int handle_show_settings(int fd, int argc, char *argv[])
+static char *handle_show_settings(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
 	char buf[BUFSIZ];
 	struct ast_tm tm;
 
-	ast_cli(fd, "\nPBX Core settings\n");
-	ast_cli(fd, "-----------------\n");
-	ast_cli(fd, "  Version:                     %s\n", "" ASTERISK_VERSION "" );
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "core show settings";
+		e->usage = "Usage: core show settings\n"
+			   "       Show core misc settings";
+		return NULL;
+	case CLI_GENERATE:
+		return NULL;
+	}
+
+	ast_cli(a->fd, "\nPBX Core settings\n");
+	ast_cli(a->fd, "-----------------\n");
+	ast_cli(a->fd, "  Version:                     %s\n", "" ASTERISK_VERSION "" );
 	if (option_maxcalls)
-		ast_cli(fd, "  Max. calls:                  %d (Current %d)\n", option_maxcalls, ast_active_channels());
+		ast_cli(a->fd, "  Max. calls:                  %d (Current %d)\n", option_maxcalls, ast_active_channels());
 	else
-		ast_cli(fd, "  Max. calls:                  Not set\n");
+		ast_cli(a->fd, "  Max. calls:                  Not set\n");
 	if (option_maxfiles)
-		ast_cli(fd, "  Max. open file handles:      %d\n", option_maxfiles); 
+		ast_cli(a->fd, "  Max. open file handles:      %d\n", option_maxfiles); 
 	else
-		ast_cli(fd, "  Max. open file handles:      Not set\n");
-	ast_cli(fd, "  Verbosity:                   %d\n", option_verbose);
-	ast_cli(fd, "  Debug level:                 %d\n", option_debug);
-	ast_cli(fd, "  Max load avg:                %lf\n", option_maxload);
+		ast_cli(a->fd, "  Max. open file handles:      Not set\n");
+	ast_cli(a->fd, "  Verbosity:                   %d\n", option_verbose);
+	ast_cli(a->fd, "  Debug level:                 %d\n", option_debug);
+	ast_cli(a->fd, "  Max load avg:                %lf\n", option_maxload);
 #if defined(HAVE_SYSINFO)
-	ast_cli(fd, "  Min Free Memory:             %ld MB\n", option_minmemfree);
+	ast_cli(a->fd, "  Min Free Memory:             %ld MB\n", option_minmemfree);
 #endif
 	if (ast_localtime(&ast_startuptime, &tm, NULL)) {
 		ast_strftime(buf, sizeof(buf), "%H:%M:%S", &tm);
-		ast_cli(fd, "  Startup time:                %s\n", buf);
+		ast_cli(a->fd, "  Startup time:                %s\n", buf);
 	}
 	if (ast_localtime(&ast_lastreloadtime, &tm, NULL)) {
 		ast_strftime(buf, sizeof(buf), "%H:%M:%S", &tm);
-		ast_cli(fd, "  Last reload time:            %s\n", buf);
-	}
-	ast_cli(fd, "  System:                      %s/%s built by %s on %s %s\n", ast_build_os, ast_build_kernel, ast_build_user, ast_build_machine, ast_build_date);
-	ast_cli(fd, "  System name:                 %s\n", ast_config_AST_SYSTEM_NAME);
-	ast_cli(fd, "  Default language:            %s\n", defaultlanguage);
-	ast_cli(fd, "  Language prefix:             %s\n", ast_language_is_prefix ? "Enabled" : "Disabled");
-	ast_cli(fd, "  User name and group:         %s/%s\n", ast_config_AST_RUN_USER, ast_config_AST_RUN_GROUP);
-	ast_cli(fd, "  Executable includes:         %s\n", ast_test_flag(&ast_options, AST_OPT_FLAG_EXEC_INCLUDES) ? "Enabled" : "Disabled");
-	ast_cli(fd, "  Transcode via SLIN:          %s\n", ast_test_flag(&ast_options, AST_OPT_FLAG_TRANSCODE_VIA_SLIN) ? "Enabled" : "Disabled");
-	ast_cli(fd, "  Internal timing:             %s\n", ast_test_flag(&ast_options, AST_OPT_FLAG_INTERNAL_TIMING) ? "Enabled" : "Disabled");
-	ast_cli(fd, "  Transmit silence during rec: %s\n", ast_test_flag(&ast_options, AST_OPT_FLAG_INTERNAL_TIMING) ? "Enabled" : "Disabled");
-
-	ast_cli(fd, "\n* Subsystems\n");
-	ast_cli(fd, "  -------------\n");
-	ast_cli(fd, "  Manager (AMI):               %s\n", check_manager_enabled() ? "Enabled" : "Disabled");
-	ast_cli(fd, "  Web Manager (AMI/HTTP):      %s\n", check_webmanager_enabled() ? "Enabled" : "Disabled");
-	ast_cli(fd, "  Call data records:           %s\n", check_cdr_enabled() ? "Enabled" : "Disabled");
-	ast_cli(fd, "  Realtime Architecture (ARA): %s\n", ast_realtime_enabled() ? "Enabled" : "Disabled");
+		ast_cli(a->fd, "  Last reload time:            %s\n", buf);
+	}
+	ast_cli(a->fd, "  System:                      %s/%s built by %s on %s %s\n", ast_build_os, ast_build_kernel, ast_build_user, ast_build_machine, ast_build_date);
+	ast_cli(a->fd, "  System name:                 %s\n", ast_config_AST_SYSTEM_NAME);
+	ast_cli(a->fd, "  Default language:            %s\n", defaultlanguage);
+	ast_cli(a->fd, "  Language prefix:             %s\n", ast_language_is_prefix ? "Enabled" : "Disabled");
+	ast_cli(a->fd, "  User name and group:         %s/%s\n", ast_config_AST_RUN_USER, ast_config_AST_RUN_GROUP);
+	ast_cli(a->fd, "  Executable includes:         %s\n", ast_test_flag(&ast_options, AST_OPT_FLAG_EXEC_INCLUDES) ? "Enabled" : "Disabled");
+	ast_cli(a->fd, "  Transcode via SLIN:          %s\n", ast_test_flag(&ast_options, AST_OPT_FLAG_TRANSCODE_VIA_SLIN) ? "Enabled" : "Disabled");
+	ast_cli(a->fd, "  Internal timing:             %s\n", ast_test_flag(&ast_options, AST_OPT_FLAG_INTERNAL_TIMING) ? "Enabled" : "Disabled");
+	ast_cli(a->fd, "  Transmit silence during rec: %s\n", ast_test_flag(&ast_options, AST_OPT_FLAG_INTERNAL_TIMING) ? "Enabled" : "Disabled");
+
+	ast_cli(a->fd, "\n* Subsystems\n");
+	ast_cli(a->fd, "  -------------\n");
+	ast_cli(a->fd, "  Manager (AMI):               %s\n", check_manager_enabled() ? "Enabled" : "Disabled");
+	ast_cli(a->fd, "  Web Manager (AMI/HTTP):      %s\n", check_webmanager_enabled() ? "Enabled" : "Disabled");
+	ast_cli(a->fd, "  Call data records:           %s\n", check_cdr_enabled() ? "Enabled" : "Disabled");
+	ast_cli(a->fd, "  Realtime Architecture (ARA): %s\n", ast_realtime_enabled() ? "Enabled" : "Disabled");
 
 	/*! \todo we could check musiconhold, voicemail, smdi, adsi, queues  */
 
-	ast_cli(fd, "\n* Directories\n");
-	ast_cli(fd, "  -------------\n");
-	ast_cli(fd, "  Configuration file:          %s\n", ast_config_AST_CONFIG_FILE);
-	ast_cli(fd, "  Configuration directory:     %s\n", ast_config_AST_CONFIG_DIR);
-	ast_cli(fd, "  Module directory:            %s\n", ast_config_AST_MODULE_DIR);
-	ast_cli(fd, "  Spool directory:             %s\n", ast_config_AST_SPOOL_DIR);
-	ast_cli(fd, "  Log directory:               %s\n", ast_config_AST_LOG_DIR);
-	ast_cli(fd, "\n\n");
-	return 0;
+	ast_cli(a->fd, "\n* Directories\n");
+	ast_cli(a->fd, "  -------------\n");
+	ast_cli(a->fd, "  Configuration file:          %s\n", ast_config_AST_CONFIG_FILE);
+	ast_cli(a->fd, "  Configuration directory:     %s\n", ast_config_AST_CONFIG_DIR);
+	ast_cli(a->fd, "  Module directory:            %s\n", ast_config_AST_MODULE_DIR);
+	ast_cli(a->fd, "  Spool directory:             %s\n", ast_config_AST_SPOOL_DIR);
+	ast_cli(a->fd, "  Log directory:               %s\n", ast_config_AST_LOG_DIR);
+	ast_cli(a->fd, "\n\n");
+	return CLI_SUCCESS;
 }
 
-static int handle_show_threads(int fd, int argc, char *argv[])
+static char *handle_show_threads(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
 	int count = 0;
 	struct thread_list_t *cur;
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "core show threads";
+		e->usage = 
+			"Usage: core show threads\n"
+			"       List threads currently active in the system.\n";
+		return NULL;
+	case CLI_GENERATE:
+		return NULL;
+	}
 
 	AST_RWLIST_RDLOCK(&thread_list);
 	AST_RWLIST_TRAVERSE(&thread_list, cur, list) {
-		ast_cli(fd, "%p %s\n", (void *)cur->id, cur->name);
+		ast_cli(a->fd, "%p %s\n", (void *)cur->id, cur->name);
 		count++;
 	}
         AST_RWLIST_UNLOCK(&thread_list);
-	ast_cli(fd, "%d threads listed.\n", count);
-	return 0;
+	ast_cli(a->fd, "%d threads listed.\n", count);
+	return CLI_SUCCESS;
 }
 
 #if defined(HAVE_SYSINFO)
-static const char show_sysinfo_help[] =
-"Usage: core show sysinfo\n"
-"       List current system information.\n";
-
 /*! \brief Give an overview of system statistics */
-static int handle_show_sysinfo(int fd, int argc, char *argv[])
+static char *handle_show_sysinfo(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
 	struct sysinfo sys_info;
-
-	if (sysinfo(&sys_info)) {
-		ast_cli(fd, "FAILED to retrieve system information\n\n");
-		return 0;
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "core show sysinfo";
+		e->usage =
+			"Usage: core show sysinfo\n"
+			"       List current system information.\n";
+		return NULL;
+	case CLI_GENERATE:
+		return NULL;
 	}
-	ast_cli(fd, "\nSystem Statistics\n");
-	ast_cli(fd, "-----------------\n");
-	ast_cli(fd, "  System Uptime:             %ld hours\n", sys_info.uptime/3600);
-	ast_cli(fd, "  Total RAM:                 %ld KiB\n", (sys_info.totalram / sys_info.mem_unit)/1024);
-	ast_cli(fd, "  Free RAM:                  %ld KiB\n", (sys_info.freeram / sys_info.mem_unit)/1024);
-	ast_cli(fd, "  Buffer RAM:                %ld KiB\n", (sys_info.bufferram / sys_info.mem_unit)/1024);
-	ast_cli(fd, "  Total Swap Space:          %ld KiB\n", (sys_info.totalswap / sys_info.mem_unit)/1024);
-	ast_cli(fd, "  Free Swap Space:           %ld KiB\n\n", (sys_info.freeswap / sys_info.mem_unit)/1024);
-	ast_cli(fd, "  Number of Processes:       %d \n\n", sys_info.procs);
-	return 0;
+	if (sysinfo(&sys_info)) {
+		ast_cli(a->fd, "FAILED to retrieve system information\n\n");
+		return CLI_FAILURE;
+	}
+	ast_cli(a->fd, "\nSystem Statistics\n");
+	ast_cli(a->fd, "-----------------\n");
+	ast_cli(a->fd, "  System Uptime:             %ld hours\n", sys_info.uptime/3600);
+	ast_cli(a->fd, "  Total RAM:                 %ld KiB\n", (sys_info.totalram / sys_info.mem_unit)/1024);
+	ast_cli(a->fd, "  Free RAM:                  %ld KiB\n", (sys_info.freeram / sys_info.mem_unit)/1024);
+	ast_cli(a->fd, "  Buffer RAM:                %ld KiB\n", (sys_info.bufferram / sys_info.mem_unit)/1024);
+	ast_cli(a->fd, "  Total Swap Space:          %ld KiB\n", (sys_info.totalswap / sys_info.mem_unit)/1024);
+	ast_cli(a->fd, "  Free Swap Space:           %ld KiB\n\n", (sys_info.freeswap / sys_info.mem_unit)/1024);
+	ast_cli(a->fd, "  Number of Processes:       %d \n\n", sys_info.procs);
+	return CLI_SUCCESS;
 }
 #endif
 
@@ -541,59 +562,84 @@ int64_t ast_mark(int i, int startstop)
 	return prof_data->e[i].mark;
 }
 
-static int handle_show_profile(int fd, int argc, char *argv[])
+#define DEFINE_PROFILE_MIN_MAX_VALUES min = 0; \
+	max = prof_data->entries;\
+	if  (a->argc > 3) { /* specific entries */ \
+		if (isdigit(a->argv[3][0])) { \
+			min = atoi(a->argv[3]); \
+			if (a->argc == 5 && strcmp(a->argv[4], "-")) \
+				max = atoi(a->argv[4]); \
+		} else \
+			search = a->argv[3]; \
+	} \
+	if (max > prof_data->entries) \
+		max = prof_data->entries;
+
+static char *handle_show_profile(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
 	int i, min, max;
 	char *search = NULL;
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "core show profile";
+		e->usage = "Usage: core show profile\n"
+			   "       show profile information";
+		return NULL;
+	case CLI_GENERATE:
+		return NULL;
+	}
 
 	if (prof_data == NULL)
 		return 0;
 
-	min = 0;
-	max = prof_data->entries;
-	if  (argc > 3) { /* specific entries */
-		if (isdigit(argv[3][0])) {
-			min = atoi(argv[3]);
-			if (argc == 5 && strcmp(argv[4], "-"))
-				max = atoi(argv[4]);
-		} else
-			search = argv[3];
-	}
-	if (max > prof_data->entries)
-		max = prof_data->entries;
-	if (!strcmp(argv[1], "clear")) {
-		for (i= min; i < max; i++) {
-			if (!search || strstr(prof_data->e[i].name, search)) {
-				prof_data->e[i].value = 0;
-				prof_data->e[i].events = 0;
-			}
-		}
-		return 0;
-	}
-	ast_cli(fd, "profile values (%d, allocated %d)\n-------------------\n",
+	DEFINE_PROFILE_MIN_MAX_VALUES;
+	ast_cli(a->fd, "profile values (%d, allocated %d)\n-------------------\n",
 		prof_data->entries, prof_data->max_size);
-	ast_cli(fd, "%6s   %8s  %10s %12s %12s  %s\n", "ID", "Scale", "Events",
+	ast_cli(a->fd, "%6s   %8s  %10s %12s %12s  %s\n", "ID", "Scale", "Events",
 			"Value", "Average", "Name");
 	for (i = min; i < max; i++) {
 		struct profile_entry *e = &prof_data->e[i];
 		if (!search || strstr(prof_data->e[i].name, search))
-		    ast_cli(fd, "%6d: [%8ld] %10ld %12lld %12lld  %s\n",
+		    ast_cli(a->fd, "%6d: [%8ld] %10ld %12lld %12lld  %s\n",
 			i,
 			(long)e->scale,
 			(long)e->events, (long long)e->value,
 			(long long)(e->events ? e->value / e->events : e->value),
 			e->name);
 	}
-	return 0;
+	return CLI_SUCCESS;
 }
 
-static const char show_version_files_help[] = 
-"Usage: core show file version [like <pattern>]\n"
-"       Lists the revision numbers of the files used to build this copy of Asterisk.\n"
-"       Optional regular expression pattern is used to filter the file list.\n";
+static char *handle_clear_profile(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+{
+	int i, min, max;
+	char *search = NULL;
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "core clear profile";
+		e->usage = "Usage: core clear profile\n"
+			   "       clear profile information";
+		return NULL;
+	case CLI_GENERATE:
+		return NULL;
+	}
+
+	if (prof_data == NULL)
+		return 0;
+
+	DEFINE_PROFILE_MIN_MAX_VALUES;
+	for (i= min; i < max; i++) {
+		if (!search || strstr(prof_data->e[i].name, search)) {
+			prof_data->e[i].value = 0;
+			prof_data->e[i].events = 0;
+		}
+	}
+	return CLI_SUCCESS;
+}
+#undef DEFINE_PROFILE_MIN_MAX_VALUES
 
 /*! \brief CLI command to list module versions */
-static int handle_show_version_files(int fd, int argc, char *argv[])
+static char *handle_show_version_files(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
 #define FORMAT "%-25.25s %-40.40s\n"
 	struct file_version *iterator;
@@ -601,15 +647,42 @@ static int handle_show_version_files(int fd, int argc, char *argv[])
 	int havepattern = 0;
 	int havename = 0;
 	int count_files = 0;
+	char *ret = NULL;
+	int matchlen, which = 0;
+	struct file_version *find;
+
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "core show file version [like]";
+		e->usage = 
+			"Usage: core show file version [like <pattern>]\n"
+			"       Lists the revision numbers of the files used to build this copy of Asterisk.\n"
+			"       Optional regular expression pattern is used to filter the file list.\n";
+		return NULL;
+	case CLI_GENERATE:
+		matchlen = strlen(a->word);
+		if (a->pos != 3)
+			return NULL;
+		AST_RWLIST_RDLOCK(&file_versions);
+		AST_RWLIST_TRAVERSE(&file_versions, find, list) {
+			if (!strncasecmp(a->word, find->file, matchlen) && ++which > a->n) {
+				ret = ast_strdup(find->file);
+				break;
+			}
+		}
+		AST_RWLIST_UNLOCK(&file_versions);
+		return ret;
+	}
 
-	switch (argc) {
+
+	switch (a->argc) {
 	case 6:
-		if (!strcasecmp(argv[4], "like")) {
-			if (regcomp(&regexbuf, argv[5], REG_EXTENDED | REG_NOSUB))
-				return RESULT_SHOWUSAGE;
+		if (!strcasecmp(a->argv[4], "like")) {
+			if (regcomp(&regexbuf, a->argv[5], REG_EXTENDED | REG_NOSUB))
+				return CLI_SHOWUSAGE;
 			havepattern = 1;
 		} else
-			return RESULT_SHOWUSAGE;
+			return CLI_SHOWUSAGE;
 		break;
 	case 5:
 		havename = 1;
@@ -617,57 +690,36 @@ static int handle_show_version_files(int fd, int argc, char *argv[])
 	case 4:
 		break;
 	default:
-		return RESULT_SHOWUSAGE;
+		return CLI_SHOWUSAGE;
 	}
 
-	ast_cli(fd, FORMAT, "File", "Revision");
-	ast_cli(fd, FORMAT, "----", "--------");
+	ast_cli(a->fd, FORMAT, "File", "Revision");
+	ast_cli(a->fd, FORMAT, "----", "--------");
 	AST_RWLIST_RDLOCK(&file_versions);
 	AST_RWLIST_TRAVERSE(&file_versions, iterator, list) {
-		if (havename && strcasecmp(iterator->file, argv[4]))
+		if (havename && strcasecmp(iterator->file, a->argv[4]))
 			continue;
 
 		if (havepattern && regexec(&regexbuf, iterator->file, 0, NULL, 0))
 			continue;
 
-		ast_cli(fd, FORMAT, iterator->file, iterator->version);
+		ast_cli(a->fd, FORMAT, iterator->file, iterator->version);
 		count_files++;
 		if (havename)
 			break;
 	}
 	AST_RWLIST_UNLOCK(&file_versions);
 	if (!havename) {
-		ast_cli(fd, "%d files listed.\n", count_files);
+		ast_cli(a->fd, "%d files listed.\n", count_files);
 	}
 
 	if (havepattern)
 		regfree(&regexbuf);
 
-	return RESULT_SUCCESS;
+	return CLI_SUCCESS;
 #undef FORMAT
 }
 
-static char *complete_show_version_files(const char *line, const char *word, int pos, int state)
-{
-	struct file_version *find;
-	int which = 0;
-	char *ret = NULL;
-	int matchlen = strlen(word);
-
-	if (pos != 3)
-		return NULL;
-
-	AST_RWLIST_RDLOCK(&file_versions);
-	AST_RWLIST_TRAVERSE(&file_versions, find, list) {
-		if (!strncasecmp(word, find->file, matchlen) && ++which > state) {
-			ret = ast_strdup(find->file);
-			break;
-		}
-	}
-	AST_RWLIST_UNLOCK(&file_versions);
-
-	return ret;
-}
 #endif /* ! LOW_MEMORY */
 
 int ast_register_atexit(void (*func)(void))
@@ -1409,62 +1461,25 @@ static int remoteconsolehandler(char *s)
 	return ret;
 }
 
-static const char abort_halt_help[] = 
-"Usage: abort shutdown\n"
-"       Causes Asterisk to abort an executing shutdown or restart, and resume normal\n"
-"       call operations.\n";
-
-static const char shutdown_now_help[] = 
-"Usage: stop now\n"
-"       Shuts down a running Asterisk immediately, hanging up all active calls .\n";
-
-static const char shutdown_gracefully_help[] = 
-"Usage: stop gracefully\n"
-"       Causes Asterisk to not accept new calls, and exit when all\n"
-"       active calls have terminated normally.\n";
-
-static const char shutdown_when_convenient_help[] = 
-"Usage: stop when convenient\n"
-"       Causes Asterisk to perform a shutdown when all active calls have ended.\n";
-
-static const char restart_now_help[] = 
-"Usage: restart now\n"
-"       Causes Asterisk to hangup all calls and exec() itself performing a cold\n"
-"       restart.\n";
-
-static const char restart_gracefully_help[] = 
-"Usage: restart gracefully\n"
-"       Causes Asterisk to stop accepting new calls and exec() itself performing a cold\n"
-"       restart when all active calls have ended.\n";
-
-static const char restart_when_convenient_help[] = 
-"Usage: restart when convenient\n"
-"       Causes Asterisk to perform a cold restart when all active calls have ended.\n";
-
-static const char bang_help[] =
-"Usage: !<command>\n"
-"       Executes a given shell command\n";
-
-static const char show_warranty_help[] =
-"Usage: core show warranty\n"
-"       Shows the warranty (if any) for this copy of Asterisk.\n";
-
-static const char show_license_help[] =
-"Usage: core show license\n"
-"       Shows the license(s) for this copy of Asterisk.\n";
-
-static const char version_help[] =
-"Usage: core show version\n"
-"       Shows Asterisk version information.\n";
-
-static int handle_version(int fd, int argc, char *argv[])
+static char *handle_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
-	if (argc != 3)
-		return RESULT_SHOWUSAGE;
-	ast_cli(fd, "Asterisk %s built by %s @ %s on a %s running %s on %s\n",
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "core show version";
+		e->usage = 
+			"Usage: core show version\n"
+			"       Shows Asterisk version information.\n";
+		return NULL;
+	case CLI_GENERATE:
+		return NULL;
+	}
+
+	if (a->argc != 3)
+		return CLI_SHOWUSAGE;
+	ast_cli(a->fd, "Asterisk %s built by %s @ %s on a %s running %s on %s\n",
 		ASTERISK_VERSION, ast_build_user, ast_build_hostname,
 		ast_build_machine, ast_build_os, ast_build_date);
-	return RESULT_SUCCESS;
+	return CLI_SUCCESS;
 }
 
 #if 0
@@ -1477,68 +1492,160 @@ static int handle_quit(int fd, int argc, char *argv[])
 }
 #endif
 
-static int handle_shutdown_now(int fd, int argc, char *argv[])
+static char *handle_stop_now(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
-	if (argc != 2)
-		return RESULT_SHOWUSAGE;
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "stop now";
+		e->usage = 
+			"Usage: stop now\n"
+			"       Shuts down a running Asterisk immediately, hanging up all active calls .\n";
+		return NULL;
+	case CLI_GENERATE:
+		return NULL;
+	}
+
+	if (a->argc != 2)
+		return CLI_SHOWUSAGE;
 	quit_handler(0, 0 /* Not nice */, 1 /* safely */, 0 /* not restart */);
-	return RESULT_SUCCESS;
+	return CLI_SUCCESS;
 }
 
-static int handle_shutdown_gracefully(int fd, int argc, char *argv[])
+static char *handle_stop_gracefully(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
-	if (argc != 2)
-		return RESULT_SHOWUSAGE;
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "stop gracefully";
+		e->usage = 
+			"Usage: stop gracefully\n"
+			"       Causes Asterisk to not accept new calls, and exit when all\n"
+			"       active calls have terminated normally.\n";
+		return NULL;
+	case CLI_GENERATE:
+		return NULL;
+	}
+
+	if (a->argc != 2)
+		return CLI_SHOWUSAGE;
 	quit_handler(0, 1 /* nicely */, 1 /* safely */, 0 /* no restart */);
-	return RESULT_SUCCESS;
+	return CLI_SUCCESS;
 }
 
-static int handle_shutdown_when_convenient(int fd, int argc, char *argv[])
+static char *handle_stop_when_convenient(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
-	if (argc != 3)
-		return RESULT_SHOWUSAGE;
-	ast_cli(fd, "Waiting for inactivity to perform halt\n");
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "stop when convenient";
+		e->usage = 
+			"Usage: stop when convenient\n"
+			"       Causes Asterisk to perform a shutdown when all active calls have ended.\n";
+		return NULL;
+	case CLI_GENERATE:
+		return NULL;
+	}
+
+	if (a->argc != 3)
+		return CLI_SHOWUSAGE;
+	ast_cli(a->fd, "Waiting for inactivity to perform halt\n");
 	quit_handler(0, 2 /* really nicely */, 1 /* safely */, 0 /* don't restart */);
-	return RESULT_SUCCESS;
+	return CLI_SUCCESS;
 }
 
-static int handle_restart_now(int fd, int argc, char *argv[])
+static char *handle_restart_now(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
-	if (argc != 2)
-		return RESULT_SHOWUSAGE;
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "restart now";
+		e->usage = 
+			"Usage: restart now\n"
+			"       Causes Asterisk to hangup all calls and exec() itself performing a cold\n"
+			"       restart.\n";
+		return NULL;
+	case CLI_GENERATE:
+		return NULL;
+	}
+
+	if (a->argc != 2)
+		return CLI_SHOWUSAGE;
 	quit_handler(0, 0 /* not nicely */, 1 /* safely */, 1 /* restart */);
-	return RESULT_SUCCESS;
+	return CLI_SUCCESS;
 }
 
-static int handle_restart_gracefully(int fd, int argc, char *argv[])
+static char *handle_restart_gracefully(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
-	if (argc != 2)
-		return RESULT_SHOWUSAGE;
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "restart gracefully";
+		e->usage = 
+			"Usage: restart gracefully\n"
+			"       Causes Asterisk to stop accepting new calls and exec() itself performing a cold\n"
+			"       restart when all active calls have ended.\n";
+		return NULL;
+	case CLI_GENERATE:
+		return NULL;
+	}
+
+	if (a->argc != 2)
+		return CLI_SHOWUSAGE;
 	quit_handler(0, 1 /* nicely */, 1 /* safely */, 1 /* restart */);
-	return RESULT_SUCCESS;
+	return CLI_SUCCESS;
 }
 
-static int handle_restart_when_convenient(int fd, int argc, char *argv[])
+static char *handle_restart_when_convenient(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
-	if (argc != 3)
-		return RESULT_SHOWUSAGE;
-	ast_cli(fd, "Waiting for inactivity to perform restart\n");
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "restart when convenient";
+		e->usage = 
+			"Usage: restart when convenient\n"
+			"       Causes Asterisk to perform a cold restart when all active calls have ended.\n";
+		return NULL;
+	case CLI_GENERATE:
+		return NULL;
+	}
+
+	if (a->argc != 3)
+		return CLI_SHOWUSAGE;
+	ast_cli(a->fd, "Waiting for inactivity to perform restart\n");
 	quit_handler(0, 2 /* really nicely */, 1 /* safely */, 1 /* restart */);
-	return RESULT_SUCCESS;
+	return CLI_SUCCESS;
 }
 
-static int handle_abort_halt(int fd, int argc, char *argv[])
+static char *handle_abort_shutdown(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
-	if (argc != 2)
-		return RESULT_SHOWUSAGE;
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "abort shutdown";
+		e->usage = 
+			"Usage: abort shutdown\n"
+			"       Causes Asterisk to abort an executing shutdown or restart, and resume normal\n"
+			"       call operations.\n";
+		return NULL;
+	case CLI_GENERATE:
+		return NULL;
+	}
+
+	if (a->argc != 2)
+		return CLI_SHOWUSAGE;
 	ast_cancel_shutdown();
 	shuttingdown = 0;
-	return RESULT_SUCCESS;
+	return CLI_SUCCESS;
 }
 
-static int handle_bang(int fd, int argc, char *argv[])
+static char *handle_bang(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
-	return RESULT_SUCCESS;
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "!";
+		e->usage = 
+			"Usage: !<command>\n"
+			"       Executes a given shell command\n";
+		return NULL;
+	case CLI_GENERATE:
+		return NULL;
+	}
+
+	return CLI_SUCCESS;
 }
 static const char warranty_lines[] = {
 	"\n"
@@ -1565,11 +1672,22 @@ static const char warranty_lines[] = {
 	"POSSIBILITY OF SUCH DAMAGES.\n"
 };
 
-static int show_warranty(int fd, int argc, char *argv[])
+static char *show_warranty(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
-	ast_cli(fd, warranty_lines);
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "core show warranty";
+		e->usage = 
+			"Usage: core show warranty\n"
+			"       Shows the warranty (if any) for this copy of Asterisk.\n";
+		return NULL;
+	case CLI_GENERATE:
+		return NULL;
+	}
 
-	return RESULT_SUCCESS;
+	ast_cli(a->fd, warranty_lines);
+
+	return CLI_SUCCESS;
 }
 
 static const char license_lines[] = {
@@ -1591,11 +1709,22 @@ static const char license_lines[] = {
 	"Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n"
 };
 
-static int show_license(int fd, int argc, char *argv[])
+static char *show_license(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
-	ast_cli(fd, license_lines);
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "core show license";
+		e->usage = 
+			"Usage: core show license\n"
+			"       Shows the license(s) for this copy of Asterisk.\n";
+		return NULL;
+	case CLI_GENERATE:
+		return NULL;
+	}
 
-	return RESULT_SUCCESS;
+	ast_cli(a->fd, license_lines);
+
+	return CLI_SUCCESS;
 }
 
 #define ASTERISK_PROMPT "*CLI> "
@@ -1603,75 +1732,26 @@ static int show_license(int fd, int argc, char *argv[])
 #define ASTERISK_PROMPT2 "%s*CLI> "
 
 static struct ast_cli_entry cli_asterisk[] = {
-	{ { "abort", "halt", NULL },
-	handle_abort_halt, "Cancel a running halt",
-	abort_halt_help },
-
-	{ { "stop", "now", NULL },
-	handle_shutdown_now, "Shut down Asterisk immediately",
-	shutdown_now_help },
-
-	{ { "stop", "gracefully", NULL },
-	handle_shutdown_gracefully, "Gracefully shut down Asterisk",
-	shutdown_gracefully_help },
-
-	{ { "stop", "when", "convenient", NULL },
-	handle_shutdown_when_convenient, "Shut down Asterisk at empty call volume",
-	shutdown_when_convenient_help },
-
-	{ { "restart", "now", NULL },
-	handle_restart_now, "Restart Asterisk immediately", restart_now_help },
-
-	{ { "restart", "gracefully", NULL },
-	handle_restart_gracefully, "Restart Asterisk gracefully",
-	restart_gracefully_help },
-
-	{ { "restart", "when", "convenient", NULL },
-	handle_restart_when_convenient, "Restart Asterisk at empty call volume",
-	restart_when_convenient_help },
-
-	{ { "core", "show", "warranty", NULL },
-	show_warranty, "Show the warranty (if any) for this copy of Asterisk",
-	show_warranty_help },
-
-	{ { "core", "show", "license", NULL },
-	show_license, "Show the license(s) for this copy of Asterisk",
-	show_license_help },
-
-	{ { "core", "show", "version", NULL },
-	handle_version, "Display version info",
-	version_help },
-
-	{ { "!", NULL },
-	handle_bang, "Execute a shell command",
-	bang_help },
-
+	NEW_CLI(handle_abort_shutdown, "Cancel a running shutdown"),
+	NEW_CLI(handle_stop_now, "Shut down Asterisk immediately"),
+	NEW_CLI(handle_stop_gracefully, "Gracefully shut down Asterisk"),
+	NEW_CLI(handle_stop_when_convenient, "Shut down Asterisk at empty call volume"),
+	NEW_CLI(handle_restart_now, "Restart Asterisk immediately"), 
+	NEW_CLI(handle_restart_gracefully, "Restart Asterisk gracefully"),
+	NEW_CLI(handle_restart_when_convenient, "Restart Asterisk at empty call volume"),
+	NEW_CLI(show_warranty, "Show the warranty (if any) for this copy of Asterisk"),
+	NEW_CLI(show_license, "Show the license(s) for this copy of Asterisk"),
+	NEW_CLI(handle_version, "Display version info"),
+	NEW_CLI(handle_bang, "Execute a shell command"),
 #if !defined(LOW_MEMORY)
-	{ { "core", "show", "file", "version", NULL },
-	handle_show_version_files, "List versions of files used to build Asterisk",
-	show_version_files_help, complete_show_version_files },
-
-	{ { "core", "show", "threads", NULL },
-	handle_show_threads, "Show running threads",
-	show_threads_help },
-
+	NEW_CLI(handle_show_version_files, "List versions of files used to build Asterisk"),
+	NEW_CLI(handle_show_threads, "Show running threads"),
 #if defined(HAVE_SYSINFO)
-	{ { "core", "show", "sysinfo", NULL },
-	handle_show_sysinfo, "Show System Information",
-	show_sysinfo_help },
+	NEW_CLI(handle_show_sysinfo, "Show System Information"),
 #endif
-
-	{ { "core", "show", "profile", NULL },
-	handle_show_profile, "Display profiling info",
-	NULL },
-
-	{ { "core", "show", "settings", NULL },
-	handle_show_settings, "Show some core settings",
-	NULL },
-
-	{ { "core", "clear", "profile", NULL },
-	handle_show_profile, "Clear profiling info",
-	NULL },
+	NEW_CLI(handle_show_profile, "Display profiling info"),
+	NEW_CLI(handle_show_settings, "Show some core settings"),
+	NEW_CLI(handle_clear_profile, "Clear profiling info"),
 #endif /* ! LOW_MEMORY */
 };
 
diff --git a/main/astobj2.c b/main/astobj2.c
index f7fde9a29388f4fa316ed62c1109a5312df9bb25..7e1bdb0217909bb64338bd4757a269843641fc32 100644
--- a/main/astobj2.c
+++ b/main/astobj2.c
@@ -607,40 +607,65 @@ static int print_cb(void *obj, void *arg, int flag)
 /*
  * Print stats
  */
-static int handle_astobj2_stats(int fd, int argc, char *argv[])
+static char *handle_astobj2_stats(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
-	ast_cli(fd, "Objects    : %d\n", ao2.total_objects);
-	ast_cli(fd, "Containers : %d\n", ao2.total_containers);
-	ast_cli(fd, "Memory     : %d\n", ao2.total_mem);
-	ast_cli(fd, "Locked     : %d\n", ao2.total_locked);
-	ast_cli(fd, "Refs       : %d\n", ao2.total_refs);
-	return 0;
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "astobj2 stats";
+		e->usage = "Usage: astobj2 stats\n"
+			   "       Show astobj2 stats\n";
+		return NULL;
+	case CLI_GENERATE:
+		return NULL;
+	}
+	ast_cli(a->fd, "Objects    : %d\n", ao2.total_objects);
+	ast_cli(a->fd, "Containers : %d\n", ao2.total_containers);
+	ast_cli(a->fd, "Memory     : %d\n", ao2.total_mem);
+	ast_cli(a->fd, "Locked     : %d\n", ao2.total_locked);
+	ast_cli(a->fd, "Refs       : %d\n", ao2.total_refs);
+	return CLI_SUCCESS;
 }
 
 /*
  * This is testing code for astobj
  */
-static int handle_astobj2_test(int fd, int argc, char *argv[])
+static char *handle_astobj2_test(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
 	struct ao2_container *c1;
 	int i, lim;
 	char *obj;
 	static int prof_id = -1;
+	struct ast_cli_args fake_args = { a->fd, 0, NULL };
+
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "astobj2 test";
+		e->usage = "Usage: astobj2 test <num>\n"
+			   "       Runs astobj2 test. Creates 'num' objects,\n"
+			   "       and test iterators, callbacks and may be other stuff\n";
+		return NULL;
+	case CLI_GENERATE:
+		return NULL;
+	}
+
+	if (a->argc != 3) {
+		return CLI_SHOWUSAGE;
+	}
 
 	if (prof_id == -1)
 		prof_id = ast_add_profile("ao2_alloc", 0);
 
-	ast_cli(fd, "argc %d argv %s %s %s\n", argc, argv[0], argv[1], argv[2]);
-	lim = atoi(argv[2]);
-	ast_cli(fd, "called astobj_test\n");
+	ast_cli(a->fd, "argc %d argv %s %s %s\n", a->argc, a->argv[0], a->argv[1], a->argv[2]);
+	lim = atoi(a->argv[2]);
+	ast_cli(a->fd, "called astobj_test\n");
 
-	handle_astobj2_stats(fd, 0, NULL);
+	handle_astobj2_stats(e, CLI_HANDLER, &fake_args);
 	/*
 	 * allocate a container with no default callback, and no hash function.
 	 * No hash means everything goes in the same bucket.
 	 */
 	c1 = ao2_container_alloc(100, NULL /* no callback */, NULL /* no hash */);
-	ast_cli(fd, "container allocated as %p\n", c1);
+	ast_cli(a->fd, "container allocated as %p\n", c1);
 
 	/*
 	 * fill the container with objects.
@@ -651,48 +676,47 @@ static int handle_astobj2_test(int fd, int argc, char *argv[])
 		ast_mark(prof_id, 1 /* start */);
 		obj = ao2_alloc(80, NULL);
 		ast_mark(prof_id, 0 /* stop */);
-		ast_cli(fd, "object %d allocated as %p\n", i, obj);
+		ast_cli(a->fd, "object %d allocated as %p\n", i, obj);
 		sprintf(obj, "-- this is obj %d --", i);
 		ao2_link(c1, obj);
 	}
-	ast_cli(fd, "testing callbacks\n");
-	ao2_callback(c1, 0, print_cb, &fd);
+	ast_cli(a->fd, "testing callbacks\n");
+	ao2_callback(c1, 0, print_cb, &a->fd);
 
-	ast_cli(fd, "testing iterators, remove every second object\n");
+	ast_cli(a->fd, "testing iterators, remove every second object\n");
 	{
 		struct ao2_iterator ai;
 		int x = 0;
 
 		ai = ao2_iterator_init(c1, 0);
 		while ( (obj = ao2_iterator_next(&ai)) ) {
-			ast_cli(fd, "iterator on <%s>\n", obj);
+			ast_cli(a->fd, "iterator on <%s>\n", obj);
 			if (x++ & 1)
 				ao2_unlink(c1, obj);
 			ao2_ref(obj, -1);
 		}
-		ast_cli(fd, "testing iterators again\n");
+		ast_cli(a->fd, "testing iterators again\n");
 		ai = ao2_iterator_init(c1, 0);
 		while ( (obj = ao2_iterator_next(&ai)) ) {
-			ast_cli(fd, "iterator on <%s>\n", obj);
+			ast_cli(a->fd, "iterator on <%s>\n", obj);
 			ao2_ref(obj, -1);
 		}
 	}
-	ast_cli(fd, "testing callbacks again\n");
-	ao2_callback(c1, 0, print_cb, &fd);
+	ast_cli(a->fd, "testing callbacks again\n");
+	ao2_callback(c1, 0, print_cb, &a->fd);
 
 	ast_verbose("now you should see an error message:\n");
 	ao2_ref(&i, -1);	/* i is not a valid object so we print an error here */
 
-	ast_cli(fd, "destroy container\n");
+	ast_cli(a->fd, "destroy container\n");
 	ao2_ref(c1, -1);	/* destroy container */
-	handle_astobj2_stats(fd, 0, NULL);
-	return 0;
+	handle_astobj2_stats(e, CLI_HANDLER, &fake_args);
+	return CLI_SUCCESS;
 }
 
 static struct ast_cli_entry cli_astobj2[] = {
-	{ { "astobj2", "stats", NULL },
-	handle_astobj2_stats, "Print astobj2 statistics", },
-	{ { "astobj2", "test", NULL } , handle_astobj2_test, "Test astobj2", },
+	NEW_CLI(handle_astobj2_stats, "Print astobj2 statistics"),
+	NEW_CLI(handle_astobj2_test, "Test astobj2"),
 };
 #endif /* AO2_DEBUG */
 
diff --git a/main/cdr.c b/main/cdr.c
index 12d1e37fd5358b1ff05dcdfdd5b98cecc27fd6cc..3c28b1cbdc955c811b403b95d86a52eda2af63ea 100644
--- a/main/cdr.c
+++ b/main/cdr.c
@@ -1225,64 +1225,74 @@ static void *do_cdr(void *data)
 	return NULL;
 }
 
-static int handle_cli_status(int fd, int argc, char *argv[])
+static char *handle_cli_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
 	struct ast_cdr_beitem *beitem=NULL;
 	int cnt=0;
 	long nextbatchtime=0;
 
-	if (argc > 2)
-		return RESULT_SHOWUSAGE;
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "cdr status";
+		e->usage = 
+			"Usage: cdr status\n"
+			"	Displays the Call Detail Record engine system status.\n";
+		return NULL;
+	case CLI_GENERATE:
+		return NULL;
+	}
 
-	ast_cli(fd, "CDR logging: %s\n", enabled ? "enabled" : "disabled");
-	ast_cli(fd, "CDR mode: %s\n", batchmode ? "batch" : "simple");
+	if (a->argc > 2)
+		return CLI_SHOWUSAGE;
+
+	ast_cli(a->fd, "CDR logging: %s\n", enabled ? "enabled" : "disabled");
+	ast_cli(a->fd, "CDR mode: %s\n", batchmode ? "batch" : "simple");
 	if (enabled) {
 		if (batchmode) {
 			if (batch)
 				cnt = batch->size;
 			if (cdr_sched > -1)
 				nextbatchtime = ast_sched_when(sched, cdr_sched);
-			ast_cli(fd, "CDR safe shut down: %s\n", batchsafeshutdown ? "enabled" : "disabled");
-			ast_cli(fd, "CDR batch threading model: %s\n", batchscheduleronly ? "scheduler only" : "scheduler plus separate threads");
-			ast_cli(fd, "CDR current batch size: %d record%s\n", cnt, ESS(cnt));
-			ast_cli(fd, "CDR maximum batch size: %d record%s\n", batchsize, ESS(batchsize));
-			ast_cli(fd, "CDR maximum batch time: %d second%s\n", batchtime, ESS(batchtime));
-			ast_cli(fd, "CDR next scheduled batch processing time: %ld second%s\n", nextbatchtime, ESS(nextbatchtime));
+			ast_cli(a->fd, "CDR safe shut down: %s\n", batchsafeshutdown ? "enabled" : "disabled");
+			ast_cli(a->fd, "CDR batch threading model: %s\n", batchscheduleronly ? "scheduler only" : "scheduler plus separate threads");
+			ast_cli(a->fd, "CDR current batch size: %d record%s\n", cnt, ESS(cnt));
+			ast_cli(a->fd, "CDR maximum batch size: %d record%s\n", batchsize, ESS(batchsize));
+			ast_cli(a->fd, "CDR maximum batch time: %d second%s\n", batchtime, ESS(batchtime));
+			ast_cli(a->fd, "CDR next scheduled batch processing time: %ld second%s\n", nextbatchtime, ESS(nextbatchtime));
 		}
 		AST_RWLIST_RDLOCK(&be_list);
 		AST_RWLIST_TRAVERSE(&be_list, beitem, list) {
-			ast_cli(fd, "CDR registered backend: %s\n", beitem->name);
+			ast_cli(a->fd, "CDR registered backend: %s\n", beitem->name);
 		}
 		AST_RWLIST_UNLOCK(&be_list);
 	}
 
-	return 0;
+	return CLI_SUCCESS;
 }
 
-static int handle_cli_submit(int fd, int argc, char *argv[])
+static char *handle_cli_submit(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
-	if (argc > 2)
-		return RESULT_SHOWUSAGE;
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "cdr submit";
+		e->usage = 
+			"Usage: cdr submit\n"
+			"       Posts all pending batched CDR data to the configured CDR backend engine modules.\n";
+		return NULL;
+	case CLI_GENERATE:
+		return NULL;
+	}
+	if (a->argc > 2)
+		return CLI_SHOWUSAGE;
 
 	submit_unscheduled_batch();
-	ast_cli(fd, "Submitted CDRs to backend engines for processing.  This may take a while.\n");
+	ast_cli(a->fd, "Submitted CDRs to backend engines for processing.  This may take a while.\n");
 
-	return 0;
+	return CLI_SUCCESS;
 }
 
-static struct ast_cli_entry cli_submit = {
-	{ "cdr", "submit", NULL },
-	handle_cli_submit, "Posts all pending batched CDR data",
-	"Usage: cdr submit\n"
-	"       Posts all pending batched CDR data to the configured CDR backend engine modules.\n"
-};
-
-static struct ast_cli_entry cli_status = {
-	{ "cdr", "status", NULL },
-	handle_cli_status, "Display the CDR status",
-	"Usage: cdr status\n"
-	"	Displays the Call Detail Record engine system status.\n"
-};
+static struct ast_cli_entry cli_submit = NEW_CLI(handle_cli_submit, "Posts all pending batched CDR data");
+static struct ast_cli_entry cli_status = NEW_CLI(handle_cli_status, "Display the CDR status");
 
 static int do_reload(int reload)
 {
diff --git a/main/channel.c b/main/channel.c
index 9cdf0521dc5b3c483079e9b99efaf104838fa15b..9e209714c9912ba2c94c8e56ce752a47c7bae3e5 100644
--- a/main/channel.c
+++ b/main/channel.c
@@ -188,60 +188,106 @@ struct ast_variable *ast_channeltype_list(void)
 }
 
 /*! \brief Show channel types - CLI command */
-static int show_channeltypes(int fd, int argc, char *argv[])
+static char *handle_cli_core_show_channeltypes(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
 #define FORMAT  "%-10.10s  %-40.40s %-12.12s %-12.12s %-12.12s\n"
 	struct chanlist *cl;
 	int count_chan = 0;
 
-	ast_cli(fd, FORMAT, "Type", "Description",       "Devicestate", "Indications", "Transfer");
-	ast_cli(fd, FORMAT, "----------", "-----------", "-----------", "-----------", "--------");
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "core show channeltypes";
+		e->usage =
+			"Usage: core show channeltypes\n"
+			"       Lists available channel types registered in your\n"
+			"       Asterisk server.\n";
+		return NULL;
+	case CLI_GENERATE:
+		return NULL;
+	}
+
+	if (a->argc != 3)
+		return CLI_SHOWUSAGE;
+
+	ast_cli(a->fd, FORMAT, "Type", "Description",       "Devicestate", "Indications", "Transfer");
+	ast_cli(a->fd, FORMAT, "----------", "-----------", "-----------", "-----------", "--------");
 	if (AST_RWLIST_RDLOCK(&channels)) {
 		ast_log(LOG_WARNING, "Unable to lock channel list\n");
-		return -1;
+		return CLI_FAILURE;
 	}
 	AST_LIST_TRAVERSE(&backends, cl, list) {
-		ast_cli(fd, FORMAT, cl->tech->type, cl->tech->description,
+		ast_cli(a->fd, FORMAT, cl->tech->type, cl->tech->description,
 			(cl->tech->devicestate) ? "yes" : "no",
 			(cl->tech->indicate) ? "yes" : "no",
 			(cl->tech->transfer) ? "yes" : "no");
 		count_chan++;
 	}
 	AST_RWLIST_UNLOCK(&channels);
-	ast_cli(fd, "----------\n%d channel drivers registered.\n", count_chan);
-	return RESULT_SUCCESS;
+	ast_cli(a->fd, "----------\n%d channel drivers registered.\n", count_chan);
+	return CLI_SUCCESS;
 
 #undef FORMAT
+}
+
+static char *complete_channeltypes(struct ast_cli_args *a)
+{
+	struct chanlist *cl;
+	int which = 0;
+	int wordlen;
+	char *ret = NULL;
+
+	if (a->pos != 3)
+		return NULL;
 
+	wordlen = strlen(a->word);
+
+	AST_LIST_TRAVERSE(&backends, cl, list) {
+		if (!strncasecmp(a->word, cl->tech->type, wordlen) && ++which > a->n) {
+			ret = ast_strdup(cl->tech->type);
+			break;
+		}
+	}
+	
+	return ret;
 }
 
 /*! \brief Show details about a channel driver - CLI command */
-static int show_channeltype(int fd, int argc, char *argv[])
+static char *handle_cli_core_show_channeltype(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
 	struct chanlist *cl = NULL;
 
-	if (argc != 4)
-		return RESULT_SHOWUSAGE;
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "core show channeltype";
+		e->usage =
+			"Usage: core show channeltype <name>\n"
+			"	Show details about the specified channel type, <name>.\n";
+		return NULL;
+	case CLI_GENERATE:
+		return complete_channeltypes(a);
+	}
+
+	if (a->argc != 4)
+		return CLI_SHOWUSAGE;
 	
 	if (AST_RWLIST_RDLOCK(&channels)) {
 		ast_log(LOG_WARNING, "Unable to lock channel list\n");
-		return RESULT_FAILURE;
+		return CLI_FAILURE;
 	}
 
 	AST_LIST_TRAVERSE(&backends, cl, list) {
-		if (!strncasecmp(cl->tech->type, argv[3], strlen(cl->tech->type))) {
+		if (!strncasecmp(cl->tech->type, a->argv[3], strlen(cl->tech->type)))
 			break;
-		}
 	}
 
 
 	if (!cl) {
-		ast_cli(fd, "\n%s is not a registered channel driver.\n", argv[3]);
+		ast_cli(a->fd, "\n%s is not a registered channel driver.\n", a->argv[3]);
 		AST_RWLIST_UNLOCK(&channels);
-		return RESULT_FAILURE;
+		return CLI_FAILURE;
 	}
 
-	ast_cli(fd,
+	ast_cli(a->fd,
 		"-- Info about channel driver: %s --\n"
 		"  Device State: %s\n"
 		"    Indication: %s\n"
@@ -266,47 +312,12 @@ static int show_channeltype(int fd, int argc, char *argv[])
 	);
 
 	AST_RWLIST_UNLOCK(&channels);
-	return RESULT_SUCCESS;
-}
-
-static char *complete_channeltypes(const char *line, const char *word, int pos, int state)
-{
-	struct chanlist *cl;
-	int which = 0;
-	int wordlen;
-	char *ret = NULL;
-
-	if (pos != 3)
-		return NULL;
-
-	wordlen = strlen(word);
-
-	AST_LIST_TRAVERSE(&backends, cl, list) {
-		if (!strncasecmp(word, cl->tech->type, wordlen) && ++which > state) {
-			ret = ast_strdup(cl->tech->type);
-			break;
-		}
-	}
-	
-	return ret;
+	return CLI_SUCCESS;
 }
 
-static const char show_channeltypes_usage[] =
-"Usage: core show channeltypes\n"
-"       Lists available channel types registered in your Asterisk server.\n";
-
-static const char show_channeltype_usage[] =
-"Usage: core show channeltype <name>\n"
-"	Show details about the specified channel type, <name>.\n";
-
 static struct ast_cli_entry cli_channel[] = {
-	{ { "core", "show", "channeltypes", NULL },
-	show_channeltypes, "List available channel types",
-	show_channeltypes_usage },
-
-	{ { "core", "show", "channeltype", NULL },
-	show_channeltype, "Give more details on that channel type",
-	show_channeltype_usage, complete_channeltypes },
+	NEW_CLI(handle_cli_core_show_channeltypes, "List available channel types"),
+	NEW_CLI(handle_cli_core_show_channeltype,  "Give more details on that channel type")
 };
 
 /*! \brief Checks to see if a channel is needing hang up */
diff --git a/main/cli.c b/main/cli.c
index 7e7514aba1f8a4fe3bc3d45388b9709e8f857873..da4c25fe3530881719e92330cfadd6d0cf919145 100644
--- a/main/cli.c
+++ b/main/cli.c
@@ -123,22 +123,6 @@ unsigned int ast_verbose_get_by_file(const char *file)
 
 static AST_RWLIST_HEAD_STATIC(helpers, ast_cli_entry);
 
-static const char logger_mute_help[] = 
-"Usage: logger mute\n"
-"       Disables logging output to the current console, making it possible to\n"
-"       gather information without being disturbed by scrolling lines.\n";
-
-static const char softhangup_help[] =
-"Usage: soft hangup <channel>\n"
-"       Request that a channel be hung up. The hangup takes effect\n"
-"       the next time the driver reads or writes from the channel\n";
-
-static const char group_show_channels_help[] = 
-"Usage: group show channels [pattern]\n"
-"       Lists all currently active channels with channel group(s) specified.\n"
-"       Optional regular expression pattern is matched to group names for each\n"
-"       channel.\n";
-
 static char *complete_fn(const char *word, int state)
 {
 	char *c;
@@ -373,12 +357,24 @@ done:
 	return CLI_SUCCESS;
 }
 
-static int handle_logger_mute(int fd, int argc, char *argv[])
+static char *handle_logger_mute(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
-	if (argc != 2)
-		return RESULT_SHOWUSAGE;
-	ast_console_toggle_mute(fd);
-	return RESULT_SUCCESS;
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "logger mute";
+		e->usage = 
+			"Usage: logger mute\n"
+			"       Disables logging output to the current console, making it possible to\n"
+			"       gather information without being disturbed by scrolling lines.\n";
+		return NULL;
+	case CLI_GENERATE:
+		return NULL;
+	}
+
+	if (a->argc != 2)
+		return CLI_SHOWUSAGE;
+	ast_console_toggle_mute(a->fd);
+	return CLI_SUCCESS;
 }
 
 static char *handle_unload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
@@ -690,56 +686,61 @@ static char *handle_chanlist(struct ast_cli_entry *e, int cmd, struct ast_cli_ar
 #undef VERBOSE_FORMAT_STRING2
 }
 
-static const char showchan_help[] = 
-"Usage: core show channel <channel>\n"
-"       Shows lots of information about the specified channel.\n";
-
-static const char commandcomplete_help[] = 
-"Usage: _command complete \"<line>\" text state\n"
-"       This function is used internally to help with command completion and should.\n"
-"       never be called by the user directly.\n";
-
-static const char commandnummatches_help[] = 
-"Usage: _command nummatches \"<line>\" text \n"
-"       This function is used internally to help with command completion and should.\n"
-"       never be called by the user directly.\n";
-
-static const char commandmatchesarray_help[] = 
-"Usage: _command matchesarray \"<line>\" text \n"
-"       This function is used internally to help with command completion and should.\n"
-"       never be called by the user directly.\n";
-
-static int handle_softhangup(int fd, int argc, char *argv[])
+static char *handle_softhangup(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
 	struct ast_channel *c=NULL;
-	if (argc != 3)
-		return RESULT_SHOWUSAGE;
-	c = ast_get_channel_by_name_locked(argv[2]);
+
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "soft hangup";
+		e->usage =
+			"Usage: soft hangup <channel>\n"
+			"       Request that a channel be hung up. The hangup takes effect\n"
+			"       the next time the driver reads or writes from the channel\n";
+		return NULL;
+	case CLI_GENERATE:
+		return ast_complete_channels(a->line, a->word, a->pos, a->n, 2);
+	}
+	if (a->argc != 3)
+		return CLI_SHOWUSAGE;
+	c = ast_get_channel_by_name_locked(a->argv[2]);
 	if (c) {
-		ast_cli(fd, "Requested Hangup on channel '%s'\n", c->name);
+		ast_cli(a->fd, "Requested Hangup on channel '%s'\n", c->name);
 		ast_softhangup(c, AST_SOFTHANGUP_EXPLICIT);
 		ast_channel_unlock(c);
 	} else
-		ast_cli(fd, "%s is not a known channel\n", argv[2]);
-	return RESULT_SUCCESS;
+		ast_cli(a->fd, "%s is not a known channel\n", a->argv[2]);
+	return CLI_SUCCESS;
 }
 
 static char *__ast_cli_generator(const char *text, const char *word, int state, int lock);
 
-static int handle_commandmatchesarray(int fd, int argc, char *argv[])
+static char *handle_commandmatchesarray(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
 	char *buf, *obuf;
 	int buflen = 2048;
 	int len = 0;
 	char **matches;
 	int x, matchlen;
+	
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "_command matchesarray";
+		e->usage = 
+			"Usage: _command matchesarray \"<line>\" text \n"
+			"       This function is used internally to help with command completion and should.\n"
+			"       never be called by the user directly.\n";
+		return NULL;
+	case CLI_GENERATE:
+		return NULL;
+	}
 
-	if (argc != 4)
-		return RESULT_SHOWUSAGE;
+	if (a->argc != 4)
+		return CLI_SHOWUSAGE;
 	if (!(buf = ast_malloc(buflen)))
-		return RESULT_FAILURE;
+		return CLI_FAILURE;
 	buf[len] = '\0';
-	matches = ast_cli_completion_matches(argv[2], argv[3]);
+	matches = ast_cli_completion_matches(a->argv[2], a->argv[3]);
 	if (matches) {
 		for (x=0; matches[x]; x++) {
 			matchlen = strlen(matches[x]) + 1;
@@ -759,43 +760,65 @@ static int handle_commandmatchesarray(int fd, int argc, char *argv[])
 	}
 
 	if (buf) {
-		ast_cli(fd, "%s%s",buf, AST_CLI_COMPLETE_EOF);
+		ast_cli(a->fd, "%s%s",buf, AST_CLI_COMPLETE_EOF);
 		ast_free(buf);
 	} else
-		ast_cli(fd, "NULL\n");
+		ast_cli(a->fd, "NULL\n");
 
-	return RESULT_SUCCESS;
+	return CLI_SUCCESS;
 }
 
 
 
-static int handle_commandnummatches(int fd, int argc, char *argv[])
+static char *handle_commandnummatches(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
 	int matches = 0;
 
-	if (argc != 4)
-		return RESULT_SHOWUSAGE;
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "_command nummatches";
+		e->usage = 
+			"Usage: _command nummatches \"<line>\" text \n"
+			"       This function is used internally to help with command completion and should.\n"
+			"       never be called by the user directly.\n";
+		return NULL;
+	case CLI_GENERATE:
+		return NULL;
+	}
+
+	if (a->argc != 4)
+		return CLI_SHOWUSAGE;
 
-	matches = ast_cli_generatornummatches(argv[2], argv[3]);
+	matches = ast_cli_generatornummatches(a->argv[2], a->argv[3]);
 
-	ast_cli(fd, "%d", matches);
+	ast_cli(a->fd, "%d", matches);
 
-	return RESULT_SUCCESS;
+	return CLI_SUCCESS;
 }
 
-static int handle_commandcomplete(int fd, int argc, char *argv[])
+static char *handle_commandcomplete(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
 	char *buf;
-
-	if (argc != 5)
-		return RESULT_SHOWUSAGE;
-	buf = __ast_cli_generator(argv[2], argv[3], atoi(argv[4]), 0);
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "_command complete";
+		e->usage = 
+			"Usage: _command complete \"<line>\" text state\n"
+			"       This function is used internally to help with command completion and should.\n"
+			"       never be called by the user directly.\n";
+		return NULL;
+	case CLI_GENERATE:
+		return NULL;
+	}
+	if (a->argc != 5)
+		return CLI_SHOWUSAGE;
+	buf = __ast_cli_generator(a->argv[2], a->argv[3], atoi(a->argv[4]), 0);
 	if (buf) {
-		ast_cli(fd, buf);
+		ast_cli(a->fd, buf);
 		ast_free(buf);
 	} else
-		ast_cli(fd, "NULL\n");
-	return RESULT_SUCCESS;
+		ast_cli(a->fd, "NULL\n");
+	return CLI_SUCCESS;
 }
 
 static char *handle_core_set_debug_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
@@ -891,7 +914,7 @@ static char *handle_nodebugchan_deprecated(struct ast_cli_entry *e, int cmd, str
 	return res;
 }
 		
-static int handle_showchan(int fd, int argc, char *argv[])
+static char *handle_showchan(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
 	struct ast_channel *c=NULL;
 	struct timeval now;
@@ -900,14 +923,25 @@ static int handle_showchan(int fd, int argc, char *argv[])
 	char nf[256], wf[256], rf[256];
 	long elapsed_seconds=0;
 	int hour=0, min=0, sec=0;
+
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "core show channel";
+		e->usage = 
+			"Usage: core show channel <channel>\n"
+			"       Shows lots of information about the specified channel.\n";
+		return NULL;
+	case CLI_GENERATE:
+		return ast_complete_channels(a->line, a->word, a->pos, a->n, 3);
+	}
 	
-	if (argc != 4)
-		return RESULT_SHOWUSAGE;
+	if (a->argc != 4)
+		return CLI_SHOWUSAGE;
 	now = ast_tvnow();
-	c = ast_get_channel_by_name_locked(argv[3]);
+	c = ast_get_channel_by_name_locked(a->argv[3]);
 	if (!c) {
-		ast_cli(fd, "%s is not a known channel\n", argv[3]);
-		return RESULT_SUCCESS;
+		ast_cli(a->fd, "%s is not a known channel\n", a->argv[3]);
+		return CLI_SUCCESS;
 	}
 	if (c->cdr) {
 		elapsed_seconds = now.tv_sec - c->cdr->start.tv_sec;
@@ -917,7 +951,7 @@ static int handle_showchan(int fd, int argc, char *argv[])
 		snprintf(cdrtime, sizeof(cdrtime), "%dh%dm%ds", hour, min, sec);
 	} else
 		strcpy(cdrtime, "N/A");
-	ast_cli(fd, 
+	ast_cli(a->fd, 
 		" -- General --\n"
 		"           Name: %s\n"
 		"           Type: %s\n"
@@ -970,12 +1004,12 @@ static int handle_showchan(int fd, int argc, char *argv[])
 		(ast_test_flag(c, AST_FLAG_BLOCKING) ? c->blockproc : "(Not Blocking)"));
 	
 	if (pbx_builtin_serialize_variables(c, &out))
-		ast_cli(fd,"      Variables:\n%s\n", out->str);
+		ast_cli(a->fd,"      Variables:\n%s\n", out->str);
 	if (c->cdr && ast_cdr_serialize_variables(c->cdr, &out, '=', '\n', 1))
-		ast_cli(fd,"  CDR Variables:\n%s\n", out->str);
+		ast_cli(a->fd,"  CDR Variables:\n%s\n", out->str);
 	
 	ast_channel_unlock(c);
-	return RESULT_SUCCESS;
+	return CLI_SUCCESS;
 }
 
 /*
@@ -1015,17 +1049,7 @@ char *ast_complete_channels(const char *line, const char *word, int pos, int sta
 	return ret == &notfound ? NULL : ret;
 }
 
-static char *complete_ch_3(const char *line, const char *word, int pos, int state)
-{
-	return ast_complete_channels(line, word, pos, state, 2);
-}
-
-static char *complete_ch_4(const char *line, const char *word, int pos, int state)
-{
-	return ast_complete_channels(line, word, pos, state, 3);
-}
-
-static int group_show_channels(int fd, int argc, char *argv[])
+static char *group_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
 #define FORMAT_STRING  "%-25s  %-20s  %-20s\n"
 
@@ -1034,23 +1058,36 @@ static int group_show_channels(int fd, int argc, char *argv[])
 	regex_t regexbuf;
 	int havepattern = 0;
 
-	if (argc < 3 || argc > 4)
-		return RESULT_SHOWUSAGE;
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "group show channels";
+		e->usage = 
+			"Usage: group show channels [pattern]\n"
+			"       Lists all currently active channels with channel group(s) specified.\n"
+			"       Optional regular expression pattern is matched to group names for each\n"
+			"       channel.\n";
+		return NULL;
+	case CLI_GENERATE:
+		return NULL;
+	}
+
+	if (a->argc < 3 || a->argc > 4)
+		return CLI_SHOWUSAGE;
 	
-	if (argc == 4) {
-		if (regcomp(&regexbuf, argv[3], REG_EXTENDED | REG_NOSUB))
-			return RESULT_SHOWUSAGE;
+	if (a->argc == 4) {
+		if (regcomp(&regexbuf, a->argv[3], REG_EXTENDED | REG_NOSUB))
+			return CLI_SHOWUSAGE;
 		havepattern = 1;
 	}
 
-	ast_cli(fd, FORMAT_STRING, "Channel", "Group", "Category");
+	ast_cli(a->fd, FORMAT_STRING, "Channel", "Group", "Category");
 
 	ast_app_group_list_rdlock();
 	
 	gi = ast_app_group_list_head();
 	while (gi) {
 		if (!havepattern || !regexec(&regexbuf, gi->group, 0, NULL, 0)) {
-			ast_cli(fd, FORMAT_STRING, gi->chan->name, gi->group, (ast_strlen_zero(gi->category) ? "(default)" : gi->category));
+			ast_cli(a->fd, FORMAT_STRING, gi->chan->name, gi->group, (ast_strlen_zero(gi->category) ? "(default)" : gi->category));
 			numchans++;
 		}
 		gi = AST_LIST_NEXT(gi, list);
@@ -1061,8 +1098,8 @@ static int group_show_channels(int fd, int argc, char *argv[])
 	if (havepattern)
 		regfree(&regexbuf);
 
-	ast_cli(fd, "%d active channel%s\n", numchans, ESS(numchans));
-	return RESULT_SUCCESS;
+	ast_cli(a->fd, "%d active channel%s\n", numchans, ESS(numchans));
+	return CLI_SUCCESS;
 #undef FORMAT_STRING
 }
 
@@ -1072,18 +1109,9 @@ static int group_show_channels(int fd, int argc, char *argv[])
  */
 static struct ast_cli_entry builtins[] = {
 	/* Keep alphabetized, with longer matches first (example: abcd before abc) */
-	{ { "_command", "complete", NULL },
-	handle_commandcomplete, "Command complete",
-	commandcomplete_help },
-
-	{ { "_command", "nummatches", NULL },
-	handle_commandnummatches, "Returns number of command matches",
-	commandnummatches_help },
-
-	{ { "_command", "matchesarray", NULL },
-	handle_commandmatchesarray, "Returns command matches array",
-	commandmatchesarray_help },
-
+	NEW_CLI(handle_commandcomplete, "Command complete"),
+	NEW_CLI(handle_commandnummatches, "Returns number of command matches"),
+	NEW_CLI(handle_commandmatchesarray, "Returns command matches array"),
 	{ { NULL }, NULL, NULL, NULL }
 };
 
@@ -1100,24 +1128,18 @@ static struct ast_cli_entry cli_cli[] = {
 
 	NEW_CLI(handle_chanlist, "Display information on channels"),
 
-	{ { "core", "show", "channel", NULL },
-	handle_showchan, "Display information on a specific channel",
-	showchan_help, complete_ch_4 },
+	NEW_CLI(handle_showchan, "Display information on a specific channel"),
 
 	NEW_CLI(handle_core_set_debug_channel, "Enable/disable debugging on a channel",
 		.deprecate_cmd = &cli_debug_channel_deprecated),
 
 	NEW_CLI(handle_verbose, "Set level of debug/verbose chattiness"),
 
-	{ { "group", "show", "channels", NULL },
-	group_show_channels, "Display active channels with group(s)",
-	group_show_channels_help },
+	NEW_CLI(group_show_channels, "Display active channels with group(s)"),
 
 	NEW_CLI(handle_help, "Display help list, or specific help on a command"),
 
-	{ { "logger", "mute", NULL },
-	handle_logger_mute, "Toggle logging output to a console",
-	logger_mute_help },
+	NEW_CLI(handle_logger_mute, "Toggle logging output to a console"),
 
 	NEW_CLI(handle_modlist, "List modules and info"),
 
@@ -1129,9 +1151,7 @@ static struct ast_cli_entry cli_cli[] = {
 
 	NEW_CLI(handle_showuptime, "Show uptime information"),
 
-	{ { "soft", "hangup", NULL },
-	handle_softhangup, "Request a hangup on a given channel",
-	softhangup_help, complete_ch_3 },
+	NEW_CLI(handle_softhangup, "Request a hangup on a given channel"),
 };
 
 /*!
diff --git a/main/db.c b/main/db.c
index c38d8c8cc5e7824253b6ae3691b1f1ad8d43b42e..58245c255ba9675a1101a70f3fb4b216681e4acc 100644
--- a/main/db.c
+++ b/main/db.c
@@ -240,68 +240,120 @@ int ast_db_del(const char *family, const char *keys)
 	return res;
 }
 
-static int database_put(int fd, int argc, char *argv[])
+static char *handle_cli_database_put(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
 	int res;
-	if (argc != 5)
-		return RESULT_SHOWUSAGE;
-	res = ast_db_put(argv[2], argv[3], argv[4]);
+
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "database put";
+		e->usage =
+			"Usage: database put <family> <key> <value>\n"
+			"       Adds or updates an entry in the Asterisk database for\n"
+			"       a given family, key, and value.\n";
+		return NULL;
+	case CLI_GENERATE:
+		return NULL;
+	}
+
+	if (a->argc != 5)
+		return CLI_SHOWUSAGE;
+	res = ast_db_put(a->argv[2], a->argv[3], a->argv[4]);
 	if (res)  {
-		ast_cli(fd, "Failed to update entry\n");
+		ast_cli(a->fd, "Failed to update entry\n");
 	} else {
-		ast_cli(fd, "Updated database successfully\n");
+		ast_cli(a->fd, "Updated database successfully\n");
 	}
-	return RESULT_SUCCESS;
+	return CLI_SUCCESS;
 }
 
-static int database_get(int fd, int argc, char *argv[])
+static char *handle_cli_database_get(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
 	int res;
 	char tmp[256];
-	if (argc != 4)
-		return RESULT_SHOWUSAGE;
-	res = ast_db_get(argv[2], argv[3], tmp, sizeof(tmp));
+
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "database get";
+		e->usage =
+			"Usage: database get <family> <key>\n"
+			"       Retrieves an entry in the Asterisk database for a given\n"
+			"       family and key.\n";
+		return NULL;
+	case CLI_GENERATE:
+		return NULL;
+	}
+
+	if (a->argc != 4)
+		return CLI_SHOWUSAGE;
+	res = ast_db_get(a->argv[2], a->argv[3], tmp, sizeof(tmp));
 	if (res) {
-		ast_cli(fd, "Database entry not found.\n");
+		ast_cli(a->fd, "Database entry not found.\n");
 	} else {
-		ast_cli(fd, "Value: %s\n", tmp);
+		ast_cli(a->fd, "Value: %s\n", tmp);
 	}
-	return RESULT_SUCCESS;
+	return CLI_SUCCESS;
 }
 
-static int database_del(int fd, int argc, char *argv[])
+static char *handle_cli_database_del(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
 	int res;
-	if (argc != 4)
-		return RESULT_SHOWUSAGE;
-	res = ast_db_del(argv[2], argv[3]);
+
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "database del";
+		e->usage =
+			"Usage: database del <family> <key>\n"
+			"       Deletes an entry in the Asterisk database for a given\n"
+			"       family and key.\n";
+		return NULL;
+	case CLI_GENERATE:
+		return NULL;
+	}
+
+	if (a->argc != 4)
+		return CLI_SHOWUSAGE;
+	res = ast_db_del(a->argv[2], a->argv[3]);
 	if (res) {
-		ast_cli(fd, "Database entry does not exist.\n");
+		ast_cli(a->fd, "Database entry does not exist.\n");
 	} else {
-		ast_cli(fd, "Database entry removed.\n");
+		ast_cli(a->fd, "Database entry removed.\n");
 	}
-	return RESULT_SUCCESS;
+	return CLI_SUCCESS;
 }
 
-static int database_deltree(int fd, int argc, char *argv[])
+static char *handle_cli_database_deltree(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
 	int res;
-	if ((argc < 3) || (argc > 4))
-		return RESULT_SHOWUSAGE;
-	if (argc == 4) {
-		res = ast_db_deltree(argv[2], argv[3]);
+
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "database deltree";
+		e->usage =
+			"Usage: database deltree <family> [keytree]\n"
+			"       Deletes a family or specific keytree within a family\n"
+			"       in the Asterisk database.\n";
+		return NULL;
+	case CLI_GENERATE:
+		return NULL;
+	}
+
+	if ((a->argc < 3) || (a->argc > 4))
+		return CLI_SHOWUSAGE;
+	if (a->argc == 4) {
+		res = ast_db_deltree(a->argv[2], a->argv[3]);
 	} else {
-		res = ast_db_deltree(argv[2], NULL);
+		res = ast_db_deltree(a->argv[2], NULL);
 	}
 	if (res < 0) {
-		ast_cli(fd, "Database entries do not exist.\n");
+		ast_cli(a->fd, "Database entries do not exist.\n");
 	} else {
-		ast_cli(fd, "%d database entries removed.\n",res);
+		ast_cli(a->fd, "%d database entries removed.\n",res);
 	}
-	return RESULT_SUCCESS;
+	return CLI_SUCCESS;
 }
 
-static int database_show(int fd, int argc, char *argv[])
+static char *handle_cli_database_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
 	char prefix[256];
 	DBT key, data;
@@ -310,23 +362,35 @@ static int database_show(int fd, int argc, char *argv[])
 	int pass;
 	int counter = 0;
 
-	if (argc == 4) {
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "database show";
+		e->usage =
+			"Usage: database show [family [keytree]]\n"
+			"       Shows Asterisk database contents, optionally restricted\n"
+			"       to a given family, or family and keytree.\n";
+		return NULL;
+	case CLI_GENERATE:
+		return NULL;
+	}
+
+	if (a->argc == 4) {
 		/* Family and key tree */
-		snprintf(prefix, sizeof(prefix), "/%s/%s", argv[2], argv[3]);
-	} else if (argc == 3) {
+		snprintf(prefix, sizeof(prefix), "/%s/%s", a->argv[2], a->argv[3]);
+	} else if (a->argc == 3) {
 		/* Family only */
-		snprintf(prefix, sizeof(prefix), "/%s", argv[2]);
-	} else if (argc == 2) {
+		snprintf(prefix, sizeof(prefix), "/%s", a->argv[2]);
+	} else if (a->argc == 2) {
 		/* Neither */
 		prefix[0] = '\0';
 	} else {
-		return RESULT_SHOWUSAGE;
+		return CLI_SHOWUSAGE;
 	}
 	ast_mutex_lock(&dblock);
 	if (dbinit()) {
 		ast_mutex_unlock(&dblock);
-		ast_cli(fd, "Database unavailable\n");
-		return RESULT_SUCCESS;	
+		ast_cli(a->fd, "Database unavailable\n");
+		return CLI_SUCCESS;	
 	}
 	memset(&key, 0, sizeof(key));
 	memset(&data, 0, sizeof(data));
@@ -345,16 +409,16 @@ static int database_show(int fd, int argc, char *argv[])
 			values = "<bad value>";
 		}
 		if (keymatch(keys, prefix)) {
-			ast_cli(fd, "%-50s: %-25s\n", keys, values);
+			ast_cli(a->fd, "%-50s: %-25s\n", keys, values);
 			counter++;
 		}
 	}
 	ast_mutex_unlock(&dblock);
-	ast_cli(fd, "%d results found.\n", counter);
-	return RESULT_SUCCESS;	
+	ast_cli(a->fd, "%d results found.\n", counter);
+	return CLI_SUCCESS;	
 }
 
-static int database_showkey(int fd, int argc, char *argv[])
+static char *handle_cli_database_showkey(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
 	char suffix[256];
 	DBT key, data;
@@ -363,17 +427,28 @@ static int database_showkey(int fd, int argc, char *argv[])
 	int pass;
 	int counter = 0;
 
-	if (argc == 3) {
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "database show";
+		e->usage =
+			"Usage: database showkey <keytree>\n"
+			"       Shows Asterisk database contents, restricted to a given key.\n";
+		return NULL;
+	case CLI_GENERATE:
+		return NULL;
+	}
+
+	if (a->argc == 3) {
 		/* Key only */
-		snprintf(suffix, sizeof(suffix), "/%s", argv[2]);
+		snprintf(suffix, sizeof(suffix), "/%s", a->argv[2]);
 	} else {
-		return RESULT_SHOWUSAGE;
+		return CLI_SHOWUSAGE;
 	}
 	ast_mutex_lock(&dblock);
 	if (dbinit()) {
 		ast_mutex_unlock(&dblock);
-		ast_cli(fd, "Database unavailable\n");
-		return RESULT_SUCCESS;	
+		ast_cli(a->fd, "Database unavailable\n");
+		return CLI_SUCCESS;	
 	}
 	memset(&key, 0, sizeof(key));
 	memset(&data, 0, sizeof(data));
@@ -392,13 +467,13 @@ static int database_showkey(int fd, int argc, char *argv[])
 			values = "<bad value>";
 		}
 		if (subkeymatch(keys, suffix)) {
-			ast_cli(fd, "%-50s: %-25s\n", keys, values);
+			ast_cli(a->fd, "%-50s: %-25s\n", keys, values);
 			counter++;
 		}
 	}
 	ast_mutex_unlock(&dblock);
-	ast_cli(fd, "%d results found.\n", counter);
-	return RESULT_SUCCESS;	
+	ast_cli(a->fd, "%d results found.\n", counter);
+	return CLI_SUCCESS;	
 }
 
 struct ast_db_entry *ast_db_gettree(const char *family, const char *keytree)
@@ -473,59 +548,13 @@ void ast_db_freetree(struct ast_db_entry *dbe)
 	}
 }
 
-static const char database_show_usage[] =
-"Usage: database show [family [keytree]]\n"
-"       Shows Asterisk database contents, optionally restricted\n"
-"to a given family, or family and keytree.\n";
-
-static const char database_showkey_usage[] =
-"Usage: database showkey <keytree>\n"
-"       Shows Asterisk database contents, restricted to a given key.\n";
-
-static const char database_put_usage[] =
-"Usage: database put <family> <key> <value>\n"
-"       Adds or updates an entry in the Asterisk database for\n"
-"a given family, key, and value.\n";
-
-static const char database_get_usage[] =
-"Usage: database get <family> <key>\n"
-"       Retrieves an entry in the Asterisk database for a given\n"
-"family and key.\n";
-
-static const char database_del_usage[] =
-"Usage: database del <family> <key>\n"
-"       Deletes an entry in the Asterisk database for a given\n"
-"family and key.\n";
-
-static const char database_deltree_usage[] =
-"Usage: database deltree <family> [keytree]\n"
-"       Deletes a family or specific keytree within a family\n"
-"in the Asterisk database.\n";
-
 struct ast_cli_entry cli_database[] = {
-	{ { "database", "show", NULL },
-	database_show, "Shows database contents",
-	database_show_usage },
-
-	{ { "database", "showkey", NULL },
-	database_showkey, "Shows database contents",
-	database_showkey_usage },
-
-	{ { "database", "get", NULL },
-	database_get, "Gets database value",
-	database_get_usage },
-
-	{ { "database", "put", NULL },
-	database_put, "Adds/updates database value",
-	database_put_usage },
-
-	{ { "database", "del", NULL },
-	database_del, "Removes database key/value",
-	database_del_usage },
-
-	{ { "database", "deltree", NULL },
-	database_deltree, "Removes database keytree/values",
-	database_deltree_usage },
+	NEW_CLI(handle_cli_database_show,    "Shows database contents"),
+	NEW_CLI(handle_cli_database_showkey, "Shows database contents"),
+	NEW_CLI(handle_cli_database_get,     "Gets database value"),
+	NEW_CLI(handle_cli_database_put,     "Adds/updates database value"),
+	NEW_CLI(handle_cli_database_del,     "Removes database key/value"),
+	NEW_CLI(handle_cli_database_deltree, "Removes database keytree/values")
 };
 
 static int manager_dbput(struct mansession *s, const struct message *m)
diff --git a/main/file.c b/main/file.c
index 19f50bf81e74490568153905656b0e2a6c32a787..93763c87263945f434e193f6dbb562b90537d32c 100644
--- a/main/file.c
+++ b/main/file.c
@@ -1202,37 +1202,44 @@ int ast_stream_and_wait(struct ast_channel *chan, const char *file, const char *
         return res;
 } 
 
-static int show_file_formats(int fd, int argc, char *argv[])
+static char *handle_cli_core_show_file_formats(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
 #define FORMAT "%-10s %-10s %-20s\n"
 #define FORMAT2 "%-10s %-10s %-20s\n"
 	struct ast_format *f;
 	int count_fmt = 0;
 
-	if (argc != 4)
-		return RESULT_SHOWUSAGE;
-	ast_cli(fd, FORMAT, "Format", "Name", "Extensions");
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "core show file formats";
+		e->usage =
+			"Usage: core show file formats\n"
+			"       Displays currently registered file formats (if any).\n";
+		return NULL;
+	case CLI_GENERATE:
+		return NULL;
+	}
+
+	if (a->argc != 4)
+		return CLI_SHOWUSAGE;
+
+	ast_cli(a->fd, FORMAT, "Format", "Name", "Extensions");
+	ast_cli(a->fd, FORMAT, "------", "----", "----------");
 
 	AST_RWLIST_RDLOCK(&formats);
 	AST_RWLIST_TRAVERSE(&formats, f, list) {
-		ast_cli(fd, FORMAT2, ast_getformatname(f->format), f->name, f->exts);
+		ast_cli(a->fd, FORMAT2, ast_getformatname(f->format), f->name, f->exts);
 		count_fmt++;
 	}
 	AST_RWLIST_UNLOCK(&formats);
-	ast_cli(fd, "%d file formats registered.\n", count_fmt);
-	return RESULT_SUCCESS;
+	ast_cli(a->fd, "%d file formats registered.\n", count_fmt);
+	return CLI_SUCCESS;
 #undef FORMAT
 #undef FORMAT2
 }
 
-static const char show_file_formats_usage[] = 
-"Usage: core show file formats\n"
-"       Displays currently registered file formats (if any)\n";
-
 struct ast_cli_entry cli_file[] = {
-	{ { "core", "show", "file", "formats" },
-	show_file_formats, "Displays file formats",
-	show_file_formats_usage },
+	NEW_CLI(handle_cli_core_show_file_formats, "Displays file formats")
 };
 
 int ast_file_init(void)
diff --git a/main/image.c b/main/image.c
index 718d463a98fb6d5892251f888dd2d03508bc8794..0530ec5a4291b37af4a9afc89e609d11e8c1c65f 100644
--- a/main/image.c
+++ b/main/image.c
@@ -179,27 +179,39 @@ int ast_send_image(struct ast_channel *chan, char *filename)
 	return res;
 }
 
-static int show_image_formats(int fd, int argc, char *argv[])
+static char *handle_core_show_image_formats(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
 #define FORMAT "%10s %10s %50s %10s\n"
 #define FORMAT2 "%10s %10s %50s %10s\n"
 	struct ast_imager *i;
-	if (argc != 4)
-		return RESULT_SHOWUSAGE;
-	ast_cli(fd, FORMAT, "Name", "Extensions", "Description", "Format");
+	int count_fmt = 0;
+
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "core show image formats";
+		e->usage =
+			"Usage: core show image formats\n"
+			"       Displays currently registered image formats (if any).\n";
+		return NULL;
+	case CLI_GENERATE:
+		return NULL;
+	}
+	if (a->argc != 4)
+		return CLI_SHOWUSAGE;
+	ast_cli(a->fd, FORMAT, "Name", "Extensions", "Description", "Format");
+	ast_cli(a->fd, FORMAT, "----", "----------", "-----------", "------");
 	AST_RWLIST_RDLOCK(&imagers);
 	AST_RWLIST_TRAVERSE(&imagers, i, list) {
-		ast_cli(fd, FORMAT2, i->name, i->exts, i->desc, ast_getformatname(i->format));
+		ast_cli(a->fd, FORMAT2, i->name, i->exts, i->desc, ast_getformatname(i->format));
+		count_fmt++;
 	}
 	AST_RWLIST_UNLOCK(&imagers);
-	return RESULT_SUCCESS;
+	ast_cli(a->fd, "\n%d image format%s registered.\n", count_fmt, count_fmt == 1 ? "" : "s");
+	return CLI_SUCCESS;
 }
 
 struct ast_cli_entry cli_image[] = {
-	{ { "core", "show", "image", "formats" },
-	show_image_formats, "Displays image formats",
-	"Usage: core show image formats\n"
-	"       displays currently registered image formats (if any)\n" },
+	NEW_CLI(handle_core_show_image_formats, "Displays image formats")
 };
 
 int ast_image_init(void)
diff --git a/main/threadstorage.c b/main/threadstorage.c
index 26f3e1c192a8ca13278c46b60e4a5ef20cb332f0..de3e9e0df32a591d85977a6f4b38d5fa4cf473b0 100644
--- a/main/threadstorage.c
+++ b/main/threadstorage.c
@@ -104,15 +104,30 @@ void __ast_threadstorage_object_replace(void *key_old, void *key_new, size_t len
 	AST_RWLIST_UNLOCK(&tls_objects);
 }
 
-static int handle_show_allocations(int fd, int argc, char *argv[])
+static char *handle_cli_threadstorage_show_allocations(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
 	char *fn = NULL;
 	size_t len = 0;
 	unsigned int count = 0;
 	struct tls_object *to;
 
-	if (argc > 3)
-		fn = argv[3];
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "threadstorage show allocations";
+		e->usage =
+			"Usage: threadstorage show allocations [<file>]\n"
+			"       Dumps a list of all thread-specific memory allocations,\n"
+			"       optionally limited to those from a specific file\n";
+		return NULL;
+	case CLI_GENERATE:
+		return NULL;
+	}
+
+	if (a->argc > 4)
+		return CLI_SHOWUSAGE;
+
+	if (a->argc > 3)
+		fn = a->argv[3];
 
 	AST_RWLIST_RDLOCK(&tls_objects);
 
@@ -120,7 +135,7 @@ static int handle_show_allocations(int fd, int argc, char *argv[])
 		if (fn && strcasecmp(to->file, fn))
 			continue;
 
-		ast_cli(fd, "%10d bytes allocated in %20s at line %5d of %25s (thread %p)\n",
+		ast_cli(a->fd, "%10d bytes allocated in %20s at line %5d of %25s (thread %p)\n",
 			(int) to->size, to->function, to->line, to->file, (void *) to->thread);
 		len += to->size;
 		count++;
@@ -128,12 +143,12 @@ static int handle_show_allocations(int fd, int argc, char *argv[])
 
 	AST_RWLIST_UNLOCK(&tls_objects);
 
-	ast_cli(fd, "%10d bytes allocated in %d allocation%s\n", (int) len, count, count > 1 ? "s" : "");
+	ast_cli(a->fd, "%10d bytes allocated in %d allocation%s\n", (int) len, count, count > 1 ? "s" : "");
 	
-	return RESULT_SUCCESS;
+	return CLI_SUCCESS;
 }
 
-static int handle_show_summary(int fd, int argc, char *argv[])
+static char *handle_cli_threadstorage_show_summary(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
 	char *fn = NULL;
 	size_t len = 0;
@@ -145,10 +160,26 @@ static int handle_show_summary(int fd, int argc, char *argv[])
 		unsigned int count;
 		AST_LIST_ENTRY(file) entry;
 	} *file;
+
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "threadstorage show summary";
+		e->usage =
+			"Usage: threadstorage show summary [<file>]\n"
+			"       Summarizes thread-specific memory allocations by file, or optionally\n"
+			"       by function, if a file is specified\n";
+		return NULL;
+	case CLI_GENERATE:
+		return NULL;
+	}
+
+	if (a->argc > 4)
+		return CLI_SHOWUSAGE;
+
 	AST_LIST_HEAD_NOLOCK_STATIC(file_summary, file);
 
-	if (argc > 3)
-		fn = argv[3];
+	if (a->argc > 3)
+		fn = a->argv[3];
 
 	AST_RWLIST_RDLOCK(&tls_objects);
 
@@ -178,38 +209,22 @@ static int handle_show_summary(int fd, int argc, char *argv[])
 		len += file->len;
 		count += file->count;
 		if (fn) {
-			ast_cli(fd, "%10d bytes in %d allocation%ss in function %s\n",
+			ast_cli(a->fd, "%10d bytes in %d allocation%ss in function %s\n",
 				(int) file->len, file->count, file->count > 1 ? "s" : "", file->name);
 		} else {
-			ast_cli(fd, "%10d bytes in %d allocation%s in file %s\n",
+			ast_cli(a->fd, "%10d bytes in %d allocation%s in file %s\n",
 				(int) file->len, file->count, file->count > 1 ? "s" : "", file->name);
 		}
 	}
 
-	ast_cli(fd, "%10d bytes allocated in %d allocation%s\n", (int) len, count, count > 1 ? "s" : "");
-	
-	return RESULT_SUCCESS;
+	ast_cli(a->fd, "%10d bytes allocated in %d allocation%s\n", (int) len, count, count > 1 ? "s" : "");
+
+	return CLI_SUCCESS;
 }
 
 static struct ast_cli_entry cli[] = {
-	{
-		.cmda = { "threadstorage", "show", "allocations", NULL },
-		.handler = handle_show_allocations,
-		.summary = "Display outstanding thread local storage allocations",
-		.usage =
-		"Usage: threadstorage show allocations [<file>]\n"
-		"       Dumps a list of all thread-specific memory allocations,\n"
-		"optionally limited to those from a specific file\n",
-	},
-	{
-		.cmda = { "threadstorage", "show", "summary", NULL },
-		.handler = handle_show_summary,
-		.summary = "Summarize outstanding memory allocations",
-		.usage =
-		"Usage: threadstorage show summary [<file>]\n"
-		"       Summarizes thread-specific memory allocations by file, or optionally\n"
-		"by function, if a file is specified\n",
-	},
+	NEW_CLI(handle_cli_threadstorage_show_allocations, "Display outstanding thread local storage allocations"),
+	NEW_CLI(handle_cli_threadstorage_show_summary,     "Summarize outstanding memory allocations")
 };
 
 void threadstorage_init(void)
diff --git a/main/translate.c b/main/translate.c
index b22a3386ddfb4e8c77613532c9e0624a685c2e77..88811ddc8e42498e33287e22cf260e4dde0ddae7 100644
--- a/main/translate.c
+++ b/main/translate.c
@@ -491,28 +491,42 @@ static void rebuild_matrix(int samples)
 	}
 }
 
-static int show_translation(int fd, int argc, char *argv[])
+static char *handle_cli_core_show_translation(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
 #define SHOW_TRANS 13
 	int x, y, z;
 	int curlen = 0, longest = 0;
 
-	if (argc > 5)
-		return RESULT_SHOWUSAGE;
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "core show translation [recalc]";
+		e->usage =
+			"Usage: core show translation [recalc] [<recalc seconds>]\n"
+			"       Displays known codec translators and the cost associated\n"
+			"       with each conversion.  If the argument 'recalc' is supplied along\n"
+			"       with optional number of seconds to test a new test will be performed\n"
+			"       as the chart is being displayed.\n";
+		return NULL;
+	case CLI_GENERATE:
+		return NULL;
+	}
+
+	if (a->argc > 5)
+		return CLI_SHOWUSAGE;
 	
-	if (argv[3] && !strcasecmp(argv[3], "recalc")) {
-		z = argv[4] ? atoi(argv[4]) : 1;
+	if (a->argv[3] && !strcasecmp(a->argv[3], "recalc")) {
+		z = a->argv[4] ? atoi(a->argv[4]) : 1;
 
 		if (z <= 0) {
-			ast_cli(fd, "         C'mon let's be serious here... defaulting to 1.\n");
+			ast_cli(a->fd, "         Recalc must be greater than 0.  Defaulting to 1.\n");
 			z = 1;
 		}
 
 		if (z > MAX_RECALC) {
-			ast_cli(fd, "         Maximum limit of recalc exceeded by %d, truncating value to %d\n", z - MAX_RECALC, MAX_RECALC);
+			ast_cli(a->fd, "         Maximum limit of recalc exceeded by %d, truncating value to %d\n", z - MAX_RECALC, MAX_RECALC);
 			z = MAX_RECALC;
 		}
-		ast_cli(fd, "         Recalculating Codec Translation (number of sample seconds: %d)\n\n", z);
+		ast_cli(a->fd, "         Recalculating Codec Translation (number of sample seconds: %d)\n\n", z);
 		AST_RWLIST_WRLOCK(&translators);
 		rebuild_matrix(z);
 		AST_RWLIST_UNLOCK(&translators);
@@ -520,8 +534,8 @@ static int show_translation(int fd, int argc, char *argv[])
 
 	AST_RWLIST_RDLOCK(&translators);
 
-	ast_cli(fd, "         Translation times between formats (in microseconds) for one second of data\n");
-	ast_cli(fd, "          Source Format (Rows) Destination Format (Columns)\n\n");
+	ast_cli(a->fd, "         Translation times between formats (in microseconds) for one second of data\n");
+	ast_cli(a->fd, "          Source Format (Rows) Destination Format (Columns)\n\n");
 	/* Get the length of the longest (usable?) codec name, so we know how wide the left side should be */
 	for (x = 0; x < SHOW_TRANS; x++) {
 		curlen = strlen(ast_getformatname(1 << (x + 1)));
@@ -554,23 +568,14 @@ static int show_translation(int fd, int argc, char *argv[])
 			}
 		}
 		ast_str_append(&out, -1, "\n");
-		ast_cli(fd, out->str);			
+		ast_cli(a->fd, out->str);			
 	}
 	AST_RWLIST_UNLOCK(&translators);
-	return RESULT_SUCCESS;
+	return CLI_SUCCESS;
 }
 
-static const char show_trans_usage[] =
-"Usage: core show translation [recalc] [<recalc seconds>]\n"
-"       Displays known codec translators and the cost associated\n"
-"with each conversion.  If the argument 'recalc' is supplied along\n"
-"with optional number of seconds to test a new test will be performed\n"
-"as the chart is being displayed.\n";
-
 static struct ast_cli_entry cli_translate[] = {
-	{ { "core", "show", "translation", NULL },
-	show_translation, "Display translation matrix",
-	show_trans_usage, NULL, NULL },
+	NEW_CLI(handle_cli_core_show_translation, "Display translation matrix")
 };
 
 /*! \brief register codec translator */
diff --git a/main/udptl.c b/main/udptl.c
index d3c6163e7bf8dfc46d9d5f347dbd9184a191be50..a140cc4fe5363d9d6ffa5510f4f11ea5e821cffb 100644
--- a/main/udptl.c
+++ b/main/udptl.c
@@ -1107,7 +1107,7 @@ int ast_udptl_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags,
 	return -1;
 }
 
-static int udptl_do_debug_ip(int fd, int argc, char *argv[])
+static char *handle_cli_udptl_debug_ip(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
 	struct hostent *hp;
 	struct ast_hostent ahp;
@@ -1115,10 +1115,22 @@ static int udptl_do_debug_ip(int fd, int argc, char *argv[])
 	char *p;
 	char *arg;
 
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "udptl debug ip";
+		e->usage =
+			"Usage: udptl debug [ip host[:port]]\n"
+			"       Enable dumping of all UDPTL packets to and from host.\n";
+		return NULL;
+	case CLI_GENERATE:
+		return NULL;
+	}
+
 	port = 0;
-	if (argc != 4)
-		return RESULT_SHOWUSAGE;
-	arg = argv[3];
+
+	if (a->argc != 4)
+		return CLI_SHOWUSAGE;
+	arg = a->argv[3];
 	p = strstr(arg, ":");
 	if (p) {
 		*p = '\0';
@@ -1127,60 +1139,67 @@ static int udptl_do_debug_ip(int fd, int argc, char *argv[])
 	}
 	hp = ast_gethostbyname(arg, &ahp);
 	if (hp == NULL)
-		return RESULT_SHOWUSAGE;
+		return CLI_SHOWUSAGE;
 	udptldebugaddr.sin_family = AF_INET;
 	memcpy(&udptldebugaddr.sin_addr, hp->h_addr, sizeof(udptldebugaddr.sin_addr));
 	udptldebugaddr.sin_port = htons(port);
 	if (port == 0)
-		ast_cli(fd, "UDPTL Debugging Enabled for IP: %s\n", ast_inet_ntoa(udptldebugaddr.sin_addr));
+		ast_cli(a->fd, "UDPTL Debugging Enabled for IP: %s\n", ast_inet_ntoa(udptldebugaddr.sin_addr));
 	else
-		ast_cli(fd, "UDPTL Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(udptldebugaddr.sin_addr), port);
+		ast_cli(a->fd, "UDPTL Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(udptldebugaddr.sin_addr), port);
 	udptldebug = 1;
-	return RESULT_SUCCESS;
+	return CLI_SUCCESS;
 }
 
-static int udptl_do_debug(int fd, int argc, char *argv[])
+static char *handle_cli_udptl_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
-	if (argc != 2) {
-		if (argc != 4)
-			return RESULT_SHOWUSAGE;
-		return udptl_do_debug_ip(fd, argc, argv);
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "udptl debug";
+		e->usage =
+			"Usage: udptl debug\n"
+			"       Enable dumping of all UDPTL packets.\n";
+		return NULL;
+	case CLI_GENERATE:
+		return NULL;
 	}
+
+	if (a->argc != 2)
+		return CLI_SHOWUSAGE;
+
 	udptldebug = 1;
-	memset(&udptldebugaddr,0,sizeof(udptldebugaddr));
-	ast_cli(fd, "UDPTL Debugging Enabled\n");
-	return RESULT_SUCCESS;
-}
+	memset(&udptldebugaddr, 0, sizeof(udptldebugaddr));
 
-static int udptl_nodebug(int fd, int argc, char *argv[])
-{
-	if (argc != 3)
-		return RESULT_SHOWUSAGE;
-	udptldebug = 0;
-	ast_cli(fd,"UDPTL Debugging Disabled\n");
-	return RESULT_SUCCESS;
+	ast_cli(a->fd, "UDPTL Debugging Enabled\n");
+	return CLI_SUCCESS;
 }
 
-static const char debug_usage[] =
-  "Usage: udptl debug [ip host[:port]]\n"
-  "       Enable dumping of all UDPTL packets to and from host.\n";
+static char *handle_cli_udptl_debug_off(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+{
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "udptl debug off";
+		e->usage =
+			"Usage: udptl debug off\n"
+			"       Disable dumping of all UDPTL packets.\n";
+		return NULL;
+	case CLI_GENERATE:
+		return NULL;
+	}
 
-static const char nodebug_usage[] =
-  "Usage: udptl debug off\n"
-  "       Disable all UDPTL debugging\n";
+	if (a->argc != 3)
+		return CLI_SHOWUSAGE;
 
-static struct ast_cli_entry cli_udptl[] = {
-	{ { "udptl", "debug", NULL },
-	udptl_do_debug, "Enable UDPTL debugging",
-	debug_usage },
+	udptldebug = 0;
 
-	{ { "udptl", "debug", "ip", NULL },
-	udptl_do_debug, "Enable UDPTL debugging on IP",
-	debug_usage },
+	ast_cli(a->fd, "UDPTL Debugging Disabled\n");
+	return CLI_SUCCESS;
+}
 
-	{ { "udptl", "debug", "off", NULL },
-	udptl_nodebug, "Disable UDPTL debugging",
-	nodebug_usage },
+static struct ast_cli_entry cli_udptl[] = {
+	NEW_CLI(handle_cli_udptl_debug,     "Enable UDPTL debugging"),
+	NEW_CLI(handle_cli_udptl_debug_ip,  "Enable UDPTL debugging on IP"),
+	NEW_CLI(handle_cli_udptl_debug_off, "Disable UDPTL debugging")
 };
 
 static void __ast_udptl_reload(int reload)
diff --git a/pbx/pbx_ael.c b/pbx/pbx_ael.c
index 68902a0731b0a686788889809c884ed861e6674d..f5a54f0bf0787ca9d79a9899274544de54d41ea2 100644
--- a/pbx/pbx_ael.c
+++ b/pbx/pbx_ael.c
@@ -948,65 +948,62 @@ static int pbx_load_module(void)
 }
 
 /* CLI interface */
-static int ael2_debug_read(int fd, int argc, char *argv[])
+static char *handle_cli_ael_debug_multiple(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
-	aeldebug |= DEBUG_READ;
-	return 0;
-}
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "ael debug [read|tokens|macros|contexts|off]";
+		e->usage =
+			"Usage: ael debug [read|tokens|macros|contexts|off]\n"
+			"       Enable AEL read, token, macro, or context debugging,\n"
+			"       or disable all AEL debugging messages.  Note: this\n"
+			"       currently does nothing.\n";
+		return NULL;
+	case CLI_GENERATE:
+		return NULL;
+	}
 
-static int ael2_debug_tokens(int fd, int argc, char *argv[])
-{
-	aeldebug |= DEBUG_TOKENS;
-	return 0;
-}
+	if (a->argc != 3)
+		return CLI_SHOWUSAGE;
+
+	if (!strcasecmp(a->argv[2], "read"))
+		aeldebug |= DEBUG_READ;
+	else if (!strcasecmp(a->argv[2], "tokens"))
+		aeldebug |= DEBUG_TOKENS;
+	else if (!strcasecmp(a->argv[2], "macros"))
+		aeldebug |= DEBUG_MACROS;
+	else if (!strcasecmp(a->argv[2], "contexts"))
+		aeldebug |= DEBUG_CONTEXTS;
+	else if (!strcasecmp(a->argv[2], "off"))
+		aeldebug = 0;
+	else
+		return CLI_SHOWUSAGE;
 
-static int ael2_debug_macros(int fd, int argc, char *argv[])
-{
-	aeldebug |= DEBUG_MACROS;
-	return 0;
+	return CLI_SUCCESS;
 }
 
-static int ael2_debug_contexts(int fd, int argc, char *argv[])
+static char *handle_cli_ael_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
-	aeldebug |= DEBUG_CONTEXTS;
-	return 0;
-}
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "ael reload";
+		e->usage =
+			"Usage: ael reload\n"
+			"       Reloads AEL configuration.\n";
+		return NULL;
+	case CLI_GENERATE:
+		return NULL;
+	}
 
-static int ael2_no_debug(int fd, int argc, char *argv[])
-{
-	aeldebug = 0;
-	return 0;
-}
+	if (a->argc != 2)
+		return CLI_SHOWUSAGE;
 
-static int ael2_reload(int fd, int argc, char *argv[])
-{
-	return (pbx_load_module());
+	return (pbx_load_module() ? CLI_FAILURE : CLI_SUCCESS);
 }
 
-static struct ast_cli_entry cli_ael_no_debug = {
-	{ "ael", "no", "debug", NULL },
-	ael2_no_debug, NULL,
-	NULL };
-
 static struct ast_cli_entry cli_ael[] = {
-	{ { "ael", "reload", NULL },
-	ael2_reload, "Reload AEL configuration" },
-
-	{ { "ael", "debug", "read", NULL },
-	ael2_debug_read, "Enable AEL read debug (does nothing)" },
-
-	{ { "ael", "debug", "tokens", NULL },
-	ael2_debug_tokens, "Enable AEL tokens debug (does nothing)" },
-
-	{ { "ael", "debug", "macros", NULL },
-	ael2_debug_macros, "Enable AEL macros debug (does nothing)" },
-
-	{ { "ael", "debug", "contexts", NULL },
-	ael2_debug_contexts, "Enable AEL contexts debug (does nothing)" },
-
-	{ { "ael", "nodebug", NULL },
-	ael2_no_debug, "Disable AEL debug messages",
-	NULL, NULL, &cli_ael_no_debug },
+	NEW_CLI(handle_cli_ael_reload,         "Reload AEL configuration"),
+	NEW_CLI(handle_cli_ael_debug_multiple, "Enable AEL debugging flags")
 };
 
 static int unload_module(void)
diff --git a/pbx/pbx_config.c b/pbx/pbx_config.c
index 449bf3583c4609a183781b9888d3449632c609bd..4c7c42ae2ac96e53cc614006a834ca2ede989fcd 100644
--- a/pbx/pbx_config.c
+++ b/pbx/pbx_config.c
@@ -56,56 +56,14 @@ AST_MUTEX_DEFINE_STATIC(save_dialplan_lock);
 static struct ast_context *local_contexts = NULL;
 
 /*
- * Help for commands provided by this module ...
+ * Prototypes for our completion functions
  */
-static char context_add_extension_help[] =
-"Usage: dialplan add extension <exten>,<priority>,<app>,<app-data>\n"
-"       into <context> [replace]\n\n"
-"       This command will add new extension into <context>. If there is an\n"
-"       existence of extension with the same priority and last 'replace'\n"
-"       arguments is given here we simply replace this extension.\n"
-"\n"
-"Example: dialplan add extension 6123,1,Dial,IAX/216.207.245.56/6123 into local\n"
-"         Now, you can dial 6123 and talk to Markster :)\n";
-
-static char context_remove_extension_help[] =
-"Usage: dialplan remove extension exten@context [priority]\n"
-"       Remove an extension from a given context. If a priority\n"
-"       is given, only that specific priority from the given extension\n"
-"       will be removed.\n";
-
-static char context_add_ignorepat_help[] =
-"Usage: dialplan add ignorepat <pattern> into <context>\n"
-"       This command adds a new ignore pattern into context <context>\n"
-"\n"
-"Example: dialplan add ignorepat _3XX into local\n";
-
-static char context_remove_ignorepat_help[] =
-"Usage: dialplan remove ignorepat <pattern> from <context>\n"
-"       This command removes an ignore pattern from context <context>\n"
-"\n"
-"Example: dialplan remove ignorepat _3XX from local\n";
-
-static char context_add_include_help[] =
-"Usage: dialplan add include <context> into <context>\n"
-"       Include a context in another context.\n";
-
-static char context_remove_include_help[] =
-"Usage: dialplan remove include <context> from <context>\n"
-"       Remove an included context from another context.\n";
-
-static char save_dialplan_help[] =
-"Usage: dialplan save [/path/to/extension/file]\n"
-"       Save dialplan created by pbx_config module.\n"
-"\n"
-"Example: dialplan save                 (/etc/asterisk/extensions.conf)\n"
-"         dialplan save /home/markster  (/home/markster/extensions.conf)\n";
-
-static char reload_extensions_help[] =
-"Usage: dialplan reload\n"
-"       reload extensions.conf without reloading any other modules\n"
-"       This command does not delete global variables unless\n"
-"       clearglobalvars is set to yes in extensions.conf\n";
+static char *complete_dialplan_remove_include(struct ast_cli_args *);
+static char *complete_dialplan_add_include(struct ast_cli_args *);
+static char *complete_dialplan_remove_ignorepat(struct ast_cli_args *);
+static char *complete_dialplan_add_ignorepat(struct ast_cli_args *);
+static char *complete_dialplan_remove_extension(struct ast_cli_args *);
+static char *complete_dialplan_add_extension(struct ast_cli_args *);
 
 /*
  * Implementation of functions provided by this module
@@ -114,23 +72,31 @@ static char reload_extensions_help[] =
 /*!
  * REMOVE INCLUDE command stuff
  */
-static int handle_context_remove_include(int fd, int argc, char *argv[])
+static char *handle_cli_dialplan_remove_include(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
-	if (argc != 6)
-		return RESULT_SHOWUSAGE;
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "dialplan remove include";
+		e->usage =
+			"Usage: dialplan remove include <context> from <context>\n"
+			"       Remove an included context from another context.\n";
+		return NULL;
+	case CLI_GENERATE:
+		return complete_dialplan_remove_include(a);
+	}
 
-	if (strcmp(argv[4], "into"))
-		return RESULT_SHOWUSAGE;
+	if (strcmp(a->argv[4], "from"))
+		return CLI_SHOWUSAGE;
 
-	if (!ast_context_remove_include(argv[5], argv[3], registrar)) {
-		ast_cli(fd, "We are not including '%s' into '%s' now\n",
-			argv[3], argv[5]);
-		return RESULT_SUCCESS;
+	if (!ast_context_remove_include(a->argv[5], a->argv[3], registrar)) {
+		ast_cli(a->fd, "We are not including '%s' into '%s' now\n",
+			a->argv[3], a->argv[5]);
+		return CLI_SUCCESS;
 	}
 
-	ast_cli(fd, "Failed to remove '%s' include from '%s' context\n",
-		argv[3], argv[5]);
-	return RESULT_FAILURE;
+	ast_cli(a->fd, "Failed to remove '%s' include from '%s' context\n",
+		a->argv[3], a->argv[5]);
+	return CLI_FAILURE;
 }
 
 /*! \brief return true if 'name' is included by context c */
@@ -208,15 +174,14 @@ static int split_ec(const char *src, char **ext, char ** const ctx)
 }
 
 /* _X_ is the string we need to complete */
-static char *complete_context_remove_include(const char *line, const char *word,
-	int pos, int state)
+static char *complete_dialplan_remove_include(struct ast_cli_args *a)
 {
 	int which = 0;
 	char *res = NULL;
-	int len = strlen(word); /* how many bytes to match */
+	int len = strlen(a->word); /* how many bytes to match */
 	struct ast_context *c = NULL;
 
-	if (pos == 3) {		/* "dialplan remove include _X_" */
+	if (a->pos == 3) {		/* "dialplan remove include _X_" */
 		if (ast_wrlock_contexts()) {
 			ast_log(LOG_ERROR, "Failed to lock context list\n");
 			return NULL;
@@ -233,7 +198,7 @@ static char *complete_context_remove_include(const char *line, const char *word,
 				struct ast_context *nc = NULL;
 				int already_served = 0;
 
-				if (!partial_match(i_name, word, len))
+				if (!partial_match(i_name, a->word, len))
 					continue;	/* not matched */
 
 				/* check if this include is already served or not */
@@ -244,7 +209,7 @@ static char *complete_context_remove_include(const char *line, const char *word,
 				while ( (nc = ast_walk_contexts(nc)) && nc != c && !already_served)
 					already_served = lookup_ci(nc, i_name);
 
-				if (!already_served && ++which > state)
+				if (!already_served && ++which > a->n)
 					res = strdup(i_name);
 			}
 			ast_unlock_context(c);
@@ -252,15 +217,15 @@ static char *complete_context_remove_include(const char *line, const char *word,
 
 		ast_unlock_contexts();
 		return res;
-	} else if (pos == 4) { /* "dialplan remove include CTX _X_" */
+	} else if (a->pos == 4) { /* "dialplan remove include CTX _X_" */
 		/*
 		 * complete as 'from', but only if previous context is really
 		 * included somewhere
 		 */
 		char *context, *dupline;
-		const char *s = skip_words(line, 3); /* skip 'dialplan' 'remove' 'include' */
+		const char *s = skip_words(a->line, 3); /* skip 'dialplan' 'remove' 'include' */
 
-		if (state > 0)
+		if (a->n > 0)
 			return NULL;
 		context = dupline = strdup(s);
 		if (!dupline) {
@@ -284,12 +249,12 @@ static char *complete_context_remove_include(const char *line, const char *word,
 			ast_log(LOG_WARNING, "%s not included anywhere\n", context);
 		free(context);
 		return res;
-	} else if (pos == 5) { /* "dialplan remove include CTX from _X_" */
+	} else if (a->pos == 5) { /* "dialplan remove include CTX from _X_" */
 		/*
 		 * Context from which we removing include ... 
 		 */
 		char *context, *dupline, *from;
-		const char *s = skip_words(line, 3); /* skip 'dialplan' 'remove' 'include' */
+		const char *s = skip_words(a->line, 3); /* skip 'dialplan' 'remove' 'include' */
 		context = dupline = strdup(s);
 		if (!dupline) {
 			ast_log(LOG_ERROR, "Out of free memory\n");
@@ -315,10 +280,10 @@ static char *complete_context_remove_include(const char *line, const char *word,
 		c = NULL;
 		while ( !res && (c = ast_walk_contexts(c))) {
 			const char *c_name = ast_get_context_name(c);
-			if (!partial_match(c_name, word, len))	/* not a good target */
+			if (!partial_match(c_name, a->word, len))	/* not a good target */
 				continue;
 			/* walk through all includes and check if it is our context */	
-			if (lookup_ci(c, context) && ++which > state)
+			if (lookup_ci(c, context) && ++which > a->n)
 				res = strdup(c_name);
 		}
 		ast_unlock_contexts();
@@ -332,19 +297,33 @@ static char *complete_context_remove_include(const char *line, const char *word,
 /*!
  * REMOVE EXTENSION command stuff
  */
-static int handle_context_remove_extension(int fd, int argc, char *argv[])
+static char *handle_cli_dialplan_remove_extension(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
 	int removing_priority = 0;
 	char *exten, *context;
-	int ret = RESULT_FAILURE;
+	char *ret = CLI_FAILURE;
+
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "dialplan remove extension";
+		e->usage =
+			"Usage: dialplan remove extension exten@context [priority]\n"
+			"       Remove an extension from a given context. If a priority\n"
+			"       is given, only that specific priority from the given extension\n"
+			"       will be removed.\n";
+		return NULL;
+	case CLI_GENERATE:
+		return complete_dialplan_remove_extension(a);
+	}
 
-	if (argc != 5 && argc != 4) return RESULT_SHOWUSAGE;
+	if (a->argc != 5 && a->argc != 4)
+		return CLI_SHOWUSAGE;
 
 	/*
 	 * Priority input checking ...
 	 */
-	if (argc == 5) {
-		char *c = argv[4];
+	if (a->argc == 5) {
+		char *c = a->argv[4];
 
 		/* check for digits in whole parameter for right priority ...
 		 * why? because atoi (strtol) returns 0 if any characters in
@@ -356,16 +335,16 @@ static int handle_context_remove_extension(int fd, int argc, char *argv[])
 			while (*c && isdigit(*c))
 				c++;
 			if (*c) { /* non-digit in string */
-				ast_cli(fd, "Invalid priority '%s'\n", argv[4]);
-				return RESULT_FAILURE;
+				ast_cli(a->fd, "Invalid priority '%s'\n", a->argv[4]);
+				return CLI_FAILURE;
 			}
-			removing_priority = atoi(argv[4]);
+			removing_priority = atoi(a->argv[4]);
 		}
 
 		if (removing_priority == 0) {
-			ast_cli(fd, "If you want to remove whole extension, please " \
+			ast_cli(a->fd, "If you want to remove whole extension, please " \
 				"omit priority argument\n");
-			return RESULT_FAILURE;
+			return CLI_FAILURE;
 		}
 	}
 
@@ -373,27 +352,27 @@ static int handle_context_remove_extension(int fd, int argc, char *argv[])
 	/*
 	 * Format exten@context checking ...
 	 */
-	if (split_ec(argv[3], &exten, &context))
-		return RESULT_FAILURE; /* XXX malloc failure */
+	if (split_ec(a->argv[3], &exten, &context))
+		return CLI_FAILURE; /* XXX malloc failure */
 	if ((!strlen(exten)) || (!(strlen(context)))) {
-		ast_cli(fd, "Missing extension or context name in third argument '%s'\n",
-			argv[3]);
+		ast_cli(a->fd, "Missing extension or context name in third argument '%s'\n",
+			a->argv[3]);
 		free(exten);
-		return RESULT_FAILURE;
+		return CLI_FAILURE;
 	}
 
 	if (!ast_context_remove_extension(context, exten, removing_priority, registrar)) {
 		if (!removing_priority)
-			ast_cli(fd, "Whole extension %s@%s removed\n",
+			ast_cli(a->fd, "Whole extension %s@%s removed\n",
 				exten, context);
 		else
-			ast_cli(fd, "Extension %s@%s with priority %d removed\n",
+			ast_cli(a->fd, "Extension %s@%s with priority %d removed\n",
 				exten, context, removing_priority);
 			
-		ret = RESULT_SUCCESS;
+		ret = CLI_SUCCESS;
 	} else {
-		ast_cli(fd, "Failed to remove extension %s@%s\n", exten, context);
-		ret = RESULT_FAILURE;
+		ast_cli(a->fd, "Failed to remove extension %s@%s\n", exten, context);
+		ret = CLI_FAILURE;
 	}
 	free(exten);
 	return ret;
@@ -446,8 +425,7 @@ static int fix_complete_args(const char *line, char **word, int *pos)
 }
 #endif /* BROKEN_READLINE */
 
-static char *complete_context_remove_extension(const char *line, const char *word, int pos,
-	int state)
+static char *complete_dialplan_remove_extension(struct ast_cli_args *a)
 {
 	char *ret = NULL;
 	int which = 0;
@@ -458,20 +436,20 @@ static char *complete_context_remove_extension(const char *line, const char *wor
 	 * Fix arguments, *word is a new allocated structure, REMEMBER to
 	 * free *word when you want to return from this function ...
 	 */
-	if (fix_complete_args(line, &word2, &pos)) {
+	if (fix_complete_args(a->line, &word2, &a->pos)) {
 		ast_log(LOG_ERROR, "Out of free memory\n");
 		return NULL;
 	}
-	word = word2;
+	a->word = word2;
 #endif
 
-	if (pos == 3) { /* 'dialplan remove extension _X_' (exten@context ... */
+	if (a->pos == 3) { /* 'dialplan remove extension _X_' (exten@context ... */
 		struct ast_context *c = NULL;
 		char *context = NULL, *exten = NULL;
 		int le = 0;	/* length of extension */
 		int lc = 0;	/* length of context */
 
-		lc = split_ec(word, &exten, &context);
+		lc = split_ec(a->word, &exten, &context);
 #ifdef BROKEN_READLINE
 		free(word2);
 #endif
@@ -492,7 +470,7 @@ static char *complete_context_remove_extension(const char *line, const char *wor
 			if (!partial_match(ast_get_context_name(c), context, lc))
 				continue;	/* context not matched */
 			while ( (e = ast_walk_context_extensions(c, e)) ) { /* try to complete extensions ... */
-				if ( partial_match(ast_get_extension_name(e), exten, le) && ++which > state) { /* n-th match */
+				if ( partial_match(ast_get_extension_name(e), exten, le) && ++which > a->n) { /* n-th match */
 					/* If there is an extension then return exten@context. XXX otherwise ? */
 					if (exten)
 						asprintf(&ret, "%s@%s", ast_get_extension_name(e), ast_get_context_name(c));
@@ -507,11 +485,11 @@ static char *complete_context_remove_extension(const char *line, const char *wor
 	error2:
 		if (exten)
 			free(exten);
-	} else if (pos == 4) { /* 'dialplan remove extension EXT _X_' (priority) */
+	} else if (a->pos == 4) { /* 'dialplan remove extension EXT _X_' (priority) */
 		char *exten = NULL, *context, *p;
 		struct ast_context *c;
 		int le, lc, len;
-		const char *s = skip_words(line, 3); /* skip 'dialplan' 'remove' 'extension' */
+		const char *s = skip_words(a->line, 3); /* skip 'dialplan' 'remove' 'extension' */
 		int i = split_ec(s, &exten, &context);	/* parse ext@context */
 
 		if (i)	/* error */
@@ -522,7 +500,7 @@ static char *complete_context_remove_extension(const char *line, const char *wor
 			*p = '\0';
 		le = strlen(exten);
 		lc = strlen(context);
-		len = strlen(word);
+		len = strlen(a->word);
 		if (le == 0 || lc == 0)
 			goto error3;
 
@@ -550,7 +528,7 @@ static char *complete_context_remove_extension(const char *line, const char *wor
 				priority = NULL;
 				while ( !ret && (priority = ast_walk_extension_priorities(e, priority)) ) {
 					snprintf(buffer, sizeof(buffer), "%u", ast_get_extension_priority(priority));
-					if (partial_match(buffer, word, len) && ++which > state) /* n-th match */
+					if (partial_match(buffer, a->word, len) && ++which > a->n) /* n-th match */
 						ret = strdup(buffer);
 				}
 				break;
@@ -571,76 +549,86 @@ static char *complete_context_remove_extension(const char *line, const char *wor
 /*!
  * Include context ...
  */
-static int handle_context_add_include(int fd, int argc, char *argv[])
+static char *handle_cli_dialplan_add_include(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
-	if (argc != 6) /* dialplan add include CTX in CTX */
-		return RESULT_SHOWUSAGE;
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "dialplan add include";
+		e->usage =
+			"Usage: dialplan add include <context> into <context>\n"
+			"       Include a context in another context.\n";
+		return NULL;
+	case CLI_GENERATE:
+		return complete_dialplan_add_include(a);
+	}
+
+	if (a->argc != 6) /* dialplan add include CTX in CTX */
+		return CLI_SHOWUSAGE;
 
 	/* fifth arg must be 'into' ... */
-	if (strcmp(argv[4], "into"))
-		return RESULT_SHOWUSAGE;
+	if (strcmp(a->argv[4], "into"))
+		return CLI_SHOWUSAGE;
 
-	if (ast_context_add_include(argv[5], argv[3], registrar)) {
+	if (ast_context_add_include(a->argv[5], a->argv[3], registrar)) {
 		switch (errno) {
 		case ENOMEM:
-			ast_cli(fd, "Out of memory for context addition\n");
+			ast_cli(a->fd, "Out of memory for context addition\n");
 			break;
 
 		case EBUSY:
-			ast_cli(fd, "Failed to lock context(s) list, please try again later\n");
+			ast_cli(a->fd, "Failed to lock context(s) list, please try again later\n");
 			break;
 
 		case EEXIST:
-			ast_cli(fd, "Context '%s' already included in '%s' context\n",
-				argv[3], argv[5]);
+			ast_cli(a->fd, "Context '%s' already included in '%s' context\n",
+				a->argv[3], a->argv[5]);
 			break;
 
 		case ENOENT:
 		case EINVAL:
-			ast_cli(fd, "There is no existence of context '%s'\n",
-				errno == ENOENT ? argv[5] : argv[3]);
+			ast_cli(a->fd, "There is no existence of context '%s'\n",
+				errno == ENOENT ? a->argv[5] : a->argv[3]);
 			break;
 
 		default:
-			ast_cli(fd, "Failed to include '%s' in '%s' context\n",
-				argv[3], argv[5]);
+			ast_cli(a->fd, "Failed to include '%s' in '%s' context\n",
+				a->argv[3], a->argv[5]);
 			break;
 		}
-		return RESULT_FAILURE;
+		return CLI_FAILURE;
 	}
 
 	/* show some info ... */
-	ast_cli(fd, "Context '%s' included in '%s' context\n",
-		argv[3], argv[5]);
+	ast_cli(a->fd, "Context '%s' included in '%s' context\n",
+		a->argv[3], a->argv[5]);
 
-	return RESULT_SUCCESS;
+	return CLI_SUCCESS;
 }
 
-static char *complete_context_add_include(const char *line, const char *word, int pos,
-    int state)
+static char *complete_dialplan_add_include(struct ast_cli_args *a)
 {
 	struct ast_context *c;
 	int which = 0;
 	char *ret = NULL;
-	int len = strlen(word);
+	int len = strlen(a->word);
 
-	if (pos == 3) {		/* 'dialplan add include _X_' (context) ... */
+	if (a->pos == 3) {		/* 'dialplan add include _X_' (context) ... */
 		if (ast_rdlock_contexts()) {
 			ast_log(LOG_ERROR, "Failed to lock context list\n");
 			return NULL;
 		}
 		for (c = NULL; !ret && (c = ast_walk_contexts(c)); )
-			if (partial_match(ast_get_context_name(c), word, len) && ++which > state)
+			if (partial_match(ast_get_context_name(c), a->word, len) && ++which > a->n)
 				ret = strdup(ast_get_context_name(c));
 		ast_unlock_contexts();
 		return ret;
-	} else if (pos == 4) { /* dialplan add include CTX _X_ */
+	} else if (a->pos == 4) { /* dialplan add include CTX _X_ */
 		/* complete  as 'into' if context exists or we are unable to check */
 		char *context, *dupline;
 		struct ast_context *c;
-		const char *s = skip_words(line, 3); /* should not fail */
+		const char *s = skip_words(a->line, 3); /* should not fail */
 
-		if (state != 0)	/* only once */
+		if (a->n != 0)	/* only once */
 			return NULL;
 
 		/* parse context from line ... */
@@ -664,9 +652,9 @@ static char *complete_context_add_include(const char *line, const char *word, in
 		}
 		free(context);
 		return ret;
-	} else if (pos == 5) { /* 'dialplan add include CTX into _X_' (dst context) */
+	} else if (a->pos == 5) { /* 'dialplan add include CTX into _X_' (dst context) */
 		char *context, *dupline, *into;
-		const char *s = skip_words(line, 3); /* should not fail */
+		const char *s = skip_words(a->line, 3); /* should not fail */
 		context = dupline = strdup(s);
 		if (!dupline) {
 			ast_log(LOG_ERROR, "Out of free memory\n");
@@ -694,9 +682,9 @@ static char *complete_context_add_include(const char *line, const char *word, in
 			for (c = NULL; !ret && (c = ast_walk_contexts(c)); ) {
 				if (!strcmp(context, ast_get_context_name(c)))
 					continue; /* skip ourselves */
-				if (partial_match(ast_get_context_name(c), word, len) &&
+				if (partial_match(ast_get_context_name(c), a->word, len) &&
 						!lookup_ci(c, context) /* not included yet */ &&
-						++which > state)
+						++which > a->n)
 					ret = strdup(ast_get_context_name(c));
 			}
 		} else {
@@ -714,7 +702,7 @@ static char *complete_context_add_include(const char *line, const char *word, in
 /*!
  * \brief 'save dialplan' CLI command implementation functions ...
  */
-static int handle_save_dialplan(int fd, int argc, char *argv[])
+static char *handle_cli_dialplan_save(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
 	char filename[256];
 	struct ast_context *c;
@@ -723,32 +711,45 @@ static int handle_save_dialplan(int fd, int argc, char *argv[])
 	int incomplete = 0; /* incomplete config write? */
 	FILE *output;
 	struct ast_flags config_flags = { 0 };
-
 	const char *base, *slash, *file;
 
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "dialplan save";
+		e->usage =
+			"Usage: dialplan save [/path/to/extension/file]\n"
+			"       Save dialplan created by pbx_config module.\n"
+			"\n"
+			"Example: dialplan save                 (/etc/asterisk/extensions.conf)\n"
+			"         dialplan save /home/markster  (/home/markster/extensions.conf)\n";
+		return NULL;
+	case CLI_GENERATE:
+		return NULL;
+	}
+
 	if (! (static_config && !write_protect_config)) {
-		ast_cli(fd,
+		ast_cli(a->fd,
 			"I can't save dialplan now, see '%s' example file.\n",
 			config);
-		return RESULT_FAILURE;
+		return CLI_FAILURE;
 	}
 
-	if (argc != 2 && argc != 3)
-		return RESULT_SHOWUSAGE;
+	if (a->argc != 2 && a->argc != 3)
+		return CLI_SHOWUSAGE;
 
 	if (ast_mutex_lock(&save_dialplan_lock)) {
-		ast_cli(fd,
+		ast_cli(a->fd,
 			"Failed to lock dialplan saving (another proccess saving?)\n");
-		return RESULT_FAILURE;
+		return CLI_FAILURE;
 	}
 	/* XXX the code here is quite loose, a pathname with .conf in it
 	 * is assumed to be a complete pathname
 	 */
-	if (argc == 3) {	/* have config path. Look for *.conf */
-		base = argv[2];
-		if (!strstr(argv[2], ".conf")) { /*no, this is assumed to be a pathname */
+	if (a->argc == 3) {	/* have config path. Look for *.conf */
+		base = a->argv[2];
+		if (!strstr(a->argv[2], ".conf")) { /*no, this is assumed to be a pathname */
 			/* if filename ends with '/', do not add one */
-			slash = (*(argv[2] + strlen(argv[2]) -1) == '/') ? "/" : "";
+			slash = (*(a->argv[2] + strlen(a->argv[2]) -1) == '/') ? "/" : "";
 			file = config;	/* default: 'extensions.conf' */
 		} else {	/* yes, complete file name */
 			slash = "";
@@ -766,20 +767,20 @@ static int handle_save_dialplan(int fd, int argc, char *argv[])
 
 	/* try to lock contexts list */
 	if (ast_rdlock_contexts()) {
-		ast_cli(fd, "Failed to lock contexts list\n");
+		ast_cli(a->fd, "Failed to lock contexts list\n");
 		ast_mutex_unlock(&save_dialplan_lock);
 		ast_config_destroy(cfg);
-		return RESULT_FAILURE;
+		return CLI_FAILURE;
 	}
 
 	/* create new file ... */
 	if (!(output = fopen(filename, "wt"))) {
-		ast_cli(fd, "Failed to create file '%s'\n",
+		ast_cli(a->fd, "Failed to create file '%s'\n",
 			filename);
 		ast_unlock_contexts();
 		ast_mutex_unlock(&save_dialplan_lock);
 		ast_config_destroy(cfg);
-		return RESULT_FAILURE;
+		return CLI_FAILURE;
 	}
 
 	/* fireout general info */
@@ -845,7 +846,7 @@ static int handle_save_dialplan(int fd, int argc, char *argv[])
 			
 				PUT_CTX_HDR;
 
-				if (ast_get_extension_priority(p)==PRIORITY_HINT) { /* easy */
+				if (ast_get_extension_priority(p) == PRIORITY_HINT) { /* easy */
 					fprintf(output, "exten => %s,hint,%s\n",
 						    ast_get_extension_name(p),
 						    ast_get_extension_app(p));
@@ -914,19 +915,19 @@ static int handle_save_dialplan(int fd, int argc, char *argv[])
 	fclose(output);
 
 	if (incomplete) {
-		ast_cli(fd, "Saved dialplan is incomplete\n");
-		return RESULT_FAILURE;
+		ast_cli(a->fd, "Saved dialplan is incomplete\n");
+		return CLI_FAILURE;
 	}
 
-	ast_cli(fd, "Dialplan successfully saved into '%s'\n",
+	ast_cli(a->fd, "Dialplan successfully saved into '%s'\n",
 		filename);
-	return RESULT_SUCCESS;
+	return CLI_SUCCESS;
 }
 
 /*!
  * \brief ADD EXTENSION command stuff
  */
-static int handle_context_add_extension(int fd, int argc, char *argv[])
+static char *handle_cli_dialplan_add_extension(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
 	char *whole_exten;
 	char *exten, *prior;
@@ -934,16 +935,35 @@ static int handle_context_add_extension(int fd, int argc, char *argv[])
 	char *cidmatch, *app, *app_data;
 	char *start, *end;
 
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "dialplan add extension";
+		e->usage =
+			"Usage: dialplan add extension <exten>,<priority>,<app>,<app-data>\n"
+			"       into <context> [replace]\n\n"
+			"       This command will add new extension into <context>. If there is an\n"
+			"       existence of extension with the same priority and last 'replace'\n"
+			"       arguments is given here we simply replace this extension.\n"
+			"\n"
+			"Example: dialplan add extension 6123,1,Dial,IAX/216.207.245.56/6123 into local\n"
+			"         Now, you can dial 6123 and talk to Markster :)\n";
+		return NULL;
+	case CLI_GENERATE:
+		return complete_dialplan_add_extension(a);
+	}
+
 	/* check for arguments at first */
-	if (argc != 6 && argc != 7)
-		return RESULT_SHOWUSAGE;
-	if (strcmp(argv[4], "into"))
-		return RESULT_SHOWUSAGE;
-	if (argc == 7) if (strcmp(argv[6], "replace")) return RESULT_SHOWUSAGE;
+	if (a->argc != 6 && a->argc != 7)
+		return CLI_SHOWUSAGE;
+	if (strcmp(a->argv[4], "into"))
+		return CLI_SHOWUSAGE;
+	if (a->argc == 7)
+		if (strcmp(a->argv[6], "replace"))
+			return CLI_SHOWUSAGE;
 
 	/* XXX overwrite argv[3] */
-	whole_exten = argv[3];
-	exten 	= strsep(&whole_exten,",");
+	whole_exten = a->argv[3];
+	exten = strsep(&whole_exten,",");
 	if (strchr(exten, '/')) {
 		cidmatch = exten;
 		strsep(&cidmatch,"/");
@@ -956,7 +976,7 @@ static int handle_context_add_extension(int fd, int argc, char *argv[])
 			iprior = PRIORITY_HINT;
 		} else {
 			if (sscanf(prior, "%d", &iprior) != 1) {
-				ast_cli(fd, "'%s' is not a valid priority\n", prior);
+				ast_cli(a->fd, "'%s' is not a valid priority\n", prior);
 				prior = NULL;
 			}
 		}
@@ -977,58 +997,58 @@ static int handle_context_add_extension(int fd, int argc, char *argv[])
 	}
 
 	if (!exten || !prior || !app || (!app_data && iprior != PRIORITY_HINT))
-		return RESULT_SHOWUSAGE;
+		return CLI_SHOWUSAGE;
 
 	if (!app_data)
 		app_data="";
-	if (ast_add_extension(argv[5], argc == 7 ? 1 : 0, exten, iprior, NULL, cidmatch, app,
+	if (ast_add_extension(a->argv[5], a->argc == 7 ? 1 : 0, exten, iprior, NULL, cidmatch, app,
 		(void *)strdup(app_data), free, registrar)) {
 		switch (errno) {
 		case ENOMEM:
-			ast_cli(fd, "Out of free memory\n");
+			ast_cli(a->fd, "Out of free memory\n");
 			break;
 
 		case EBUSY:
-			ast_cli(fd, "Failed to lock context(s) list, please try again later\n");
+			ast_cli(a->fd, "Failed to lock context(s) list, please try again later\n");
 			break;
 
 		case ENOENT:
-			ast_cli(fd, "No existence of '%s' context\n", argv[5]);
+			ast_cli(a->fd, "No existence of '%s' context\n", a->argv[5]);
 			break;
 
 		case EEXIST:
-			ast_cli(fd, "Extension %s@%s with priority %s already exists\n",
-				exten, argv[5], prior);
+			ast_cli(a->fd, "Extension %s@%s with priority %s already exists\n",
+				exten, a->argv[5], prior);
 			break;
 
 		default:
-			ast_cli(fd, "Failed to add '%s,%s,%s,%s' extension into '%s' context\n",
-					exten, prior, app, app_data, argv[5]);
+			ast_cli(a->fd, "Failed to add '%s,%s,%s,%s' extension into '%s' context\n",
+					exten, prior, app, app_data, a->argv[5]);
 			break;
 		}
-		return RESULT_FAILURE;
+		return CLI_FAILURE;
 	}
 
-	if (argc == 7)
-		ast_cli(fd, "Extension %s@%s (%s) replace by '%s,%s,%s,%s'\n",
-			exten, argv[5], prior, exten, prior, app, app_data);
+	if (a->argc == 7)
+		ast_cli(a->fd, "Extension %s@%s (%s) replace by '%s,%s,%s,%s'\n",
+			exten, a->argv[5], prior, exten, prior, app, app_data);
 	else
-		ast_cli(fd, "Extension '%s,%s,%s,%s' added into '%s' context\n",
-			exten, prior, app, app_data, argv[5]);
+		ast_cli(a->fd, "Extension '%s,%s,%s,%s' added into '%s' context\n",
+			exten, prior, app, app_data, a->argv[5]);
 
-	return RESULT_SUCCESS;
+	return CLI_SUCCESS;
 }
 
 /*! dialplan add extension 6123,1,Dial,IAX/212.71.138.13/6123 into local */
-static char *complete_context_add_extension(const char *line, const char *word, int pos, int state)
+static char *complete_dialplan_add_extension(struct ast_cli_args *a)
 {
 	int which = 0;
 
-	if (pos == 4) {		/* complete 'into' word ... */
-		return (state == 0) ? strdup("into") : NULL;
-	} else if (pos == 5) { /* complete context */
+	if (a->pos == 4) {		/* complete 'into' word ... */
+		return (a->n == 0) ? strdup("into") : NULL;
+	} else if (a->pos == 5) { /* complete context */
 		struct ast_context *c = NULL;
-		int len = strlen(word);
+		int len = strlen(a->word);
 		char *res = NULL;
 
 		/* try to lock contexts list ... */
@@ -1039,12 +1059,12 @@ static char *complete_context_add_extension(const char *line, const char *word,
 
 		/* walk through all contexts */
 		while ( !res && (c = ast_walk_contexts(c)) )
-			if (partial_match(ast_get_context_name(c), word, len) && ++which > state)
+			if (partial_match(ast_get_context_name(c), a->word, len) && ++which > a->n)
 				res = strdup(ast_get_context_name(c));
 		ast_unlock_contexts();
 		return res;
-	} else if (pos == 6) {
-		return state == 0 ? strdup("replace") : NULL;
+	} else if (a->pos == 6) {
+		return a->n == 0 ? strdup("replace") : NULL;
 	}
 	return NULL;
 }
@@ -1052,60 +1072,74 @@ static char *complete_context_add_extension(const char *line, const char *word,
 /*!
  * IGNOREPAT CLI stuff
  */
-static int handle_context_add_ignorepat(int fd, int argc, char *argv[])
+static char *handle_cli_dialplan_add_ignorepat(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
-	if (argc != 6)
-		return RESULT_SHOWUSAGE;
-	if (strcmp(argv[4], "into"))
-		return RESULT_SHOWUSAGE;
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "dialplan add ignorepat";
+		e->usage =
+			"Usage: dialplan add ignorepat <pattern> into <context>\n"
+			"       This command adds a new ignore pattern into context <context>\n"
+			"\n"
+			"Example: dialplan add ignorepat _3XX into local\n";
+		return NULL;
+	case CLI_GENERATE:
+		return complete_dialplan_add_ignorepat(a);
+	}
+
+	if (a->argc != 6)
+		return CLI_SHOWUSAGE;
+
+	if (strcmp(a->argv[4], "into"))
+		return CLI_SHOWUSAGE;
 
-	if (ast_context_add_ignorepat(argv[5], argv[3], registrar)) {
+	if (ast_context_add_ignorepat(a->argv[5], a->argv[3], registrar)) {
 		switch (errno) {
 		case ENOMEM:
-			ast_cli(fd, "Out of free memory\n");
+			ast_cli(a->fd, "Out of free memory\n");
 			break;
 
 		case ENOENT:
-			ast_cli(fd, "There is no existence of '%s' context\n", argv[5]);
+			ast_cli(a->fd, "There is no existence of '%s' context\n", a->argv[5]);
 			break;
 
 		case EEXIST:
-			ast_cli(fd, "Ignore pattern '%s' already included in '%s' context\n",
-				argv[3], argv[5]);
+			ast_cli(a->fd, "Ignore pattern '%s' already included in '%s' context\n",
+				a->argv[3], a->argv[5]);
 			break;
 
 		case EBUSY:
-			ast_cli(fd, "Failed to lock context(s) list, please, try again later\n");
+			ast_cli(a->fd, "Failed to lock context(s) list, please, try again later\n");
 			break;
 
 		default:
-			ast_cli(fd, "Failed to add ingore pattern '%s' into '%s' context\n",
-				argv[3], argv[5]);
+			ast_cli(a->fd, "Failed to add ingore pattern '%s' into '%s' context\n",
+				a->argv[3], a->argv[5]);
 			break;
 		}
-		return RESULT_FAILURE;
+		return CLI_FAILURE;
 	}
 
-	ast_cli(fd, "Ignore pattern '%s' added into '%s' context\n",
-		argv[3], argv[5]);
-	return RESULT_SUCCESS;
+	ast_cli(a->fd, "Ignore pattern '%s' added into '%s' context\n",
+		a->argv[3], a->argv[5]);
+
+	return CLI_SUCCESS;
 }
 
-static char *complete_context_add_ignorepat(const char *line, const char *word,
-	int pos, int state)
+static char *complete_dialplan_add_ignorepat(struct ast_cli_args *a)
 {
-	if (pos == 4)
-		return state == 0 ? strdup("into") : NULL;
-	else if (pos == 5) {
+	if (a->pos == 4)
+		return a->n == 0 ? strdup("into") : NULL;
+	else if (a->pos == 5) {
 		struct ast_context *c;
 		int which = 0;
 		char *dupline, *ignorepat = NULL;
 		const char *s;
 		char *ret = NULL;
-		int len = strlen(word);
+		int len = strlen(a->word);
 
 		/* XXX skip first three words 'dialplan' 'add' 'ignorepat' */
-		s = skip_words(line, 3);
+		s = skip_words(a->line, 3);
 		if (s == NULL)
 			return NULL;
 		dupline = strdup(s);
@@ -1123,11 +1157,11 @@ static char *complete_context_add_ignorepat(const char *line, const char *word,
 		for (c = NULL; !ret && (c = ast_walk_contexts(c));) {
 			int found = 0;
 
-			if (!partial_match(ast_get_context_name(c), word, len))
+			if (!partial_match(ast_get_context_name(c), a->word, len))
 				continue; /* not mine */
 			if (ignorepat) /* there must be one, right ? */
 				found = lookup_c_ip(c, ignorepat);
-			if (!found && ++which > state)
+			if (!found && ++which > a->n)
 				ret = strdup(ast_get_context_name(c));
 		}
 
@@ -1140,49 +1174,63 @@ static char *complete_context_add_ignorepat(const char *line, const char *word,
 	return NULL;
 }
 
-static int handle_context_remove_ignorepat(int fd, int argc, char *argv[])
+static char *handle_cli_dialplan_remove_ignorepat(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
-	if (argc != 6)
-		return RESULT_SHOWUSAGE;
-	if (strcmp(argv[4], "from"))
-		return RESULT_SHOWUSAGE;
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "dialplan remove ignorepat";
+		e->usage =
+			"Usage: dialplan remove ignorepat <pattern> from <context>\n"
+			"       This command removes an ignore pattern from context <context>\n"
+			"\n"
+			"Example: dialplan remove ignorepat _3XX from local\n";
+		return NULL;
+	case CLI_GENERATE:
+		return complete_dialplan_remove_ignorepat(a);
+	}
+
+	if (a->argc != 6)
+		return CLI_SHOWUSAGE;
+
+	if (strcmp(a->argv[4], "from"))
+		return CLI_SHOWUSAGE;
 
-	if (ast_context_remove_ignorepat(argv[5], argv[3], registrar)) {
+	if (ast_context_remove_ignorepat(a->argv[5], a->argv[3], registrar)) {
 		switch (errno) {
 		case EBUSY:
-			ast_cli(fd, "Failed to lock context(s) list, please try again later\n");
+			ast_cli(a->fd, "Failed to lock context(s) list, please try again later\n");
 			break;
 
 		case ENOENT:
-			ast_cli(fd, "There is no existence of '%s' context\n", argv[5]);
+			ast_cli(a->fd, "There is no existence of '%s' context\n", a->argv[5]);
 			break;
 
 		case EINVAL:
-			ast_cli(fd, "There is no existence of '%s' ignore pattern in '%s' context\n",
-					argv[3], argv[5]);
+			ast_cli(a->fd, "There is no existence of '%s' ignore pattern in '%s' context\n",
+					a->argv[3], a->argv[5]);
 			break;
 
 		default:
-			ast_cli(fd, "Failed to remove ignore pattern '%s' from '%s' context\n", argv[3], argv[5]);
+			ast_cli(a->fd, "Failed to remove ignore pattern '%s' from '%s' context\n",
+					a->argv[3], a->argv[5]);
 			break;
 		}
-		return RESULT_FAILURE;
+		return CLI_FAILURE;
 	}
 
-	ast_cli(fd, "Ignore pattern '%s' removed from '%s' context\n",
-		argv[3], argv[5]);
-	return RESULT_SUCCESS;
+	ast_cli(a->fd, "Ignore pattern '%s' removed from '%s' context\n",
+		a->argv[3], a->argv[5]);
+	return CLI_SUCCESS;
 }
 
-static char *complete_context_remove_ignorepat(const char *line, const char *word,
-	int pos, int state)
+static char *complete_dialplan_remove_ignorepat(struct ast_cli_args *a)
 {
 	struct ast_context *c;
 	int which = 0;
 	char *ret = NULL;
 
-	if (pos == 3) {
-		int len = strlen(word);
+	if (a->pos == 3) {
+		int len = strlen(a->word);
 		if (ast_rdlock_contexts()) {
 			ast_log(LOG_WARNING, "Failed to lock contexts list\n");
 			return NULL;
@@ -1195,7 +1243,7 @@ static char *complete_context_remove_ignorepat(const char *line, const char *wor
 				continue;
 			
 			for (ip = NULL; !ret && (ip = ast_walk_context_ignorepats(c, ip));) {
-				if (partial_match(ast_get_ignorepat_name(ip), word, len) && ++which > state) {
+				if (partial_match(ast_get_ignorepat_name(ip), a->word, len) && ++which > a->n) {
 					/* n-th match */
 					struct ast_context *cw = NULL;
 					int found = 0;
@@ -1211,13 +1259,13 @@ static char *complete_context_remove_ignorepat(const char *line, const char *wor
 		}
 		ast_unlock_contexts();
 		return ret;
-	} else if (pos == 4) {
-		 return state == 0 ? strdup("from") : NULL;
-	} else if (pos == 5) { /* XXX check this */
+	} else if (a->pos == 4) {
+		 return a->n == 0 ? strdup("from") : NULL;
+	} else if (a->pos == 5) { /* XXX check this */
 		char *dupline, *duplinet, *ignorepat;
-		int len = strlen(word);
+		int len = strlen(a->word);
 
-		dupline = strdup(line);
+		dupline = strdup(a->line);
 		if (!dupline) {
 			ast_log(LOG_WARNING, "Out of free memory\n");
 			return NULL;
@@ -1242,9 +1290,9 @@ static char *complete_context_remove_ignorepat(const char *line, const char *wor
 		for (c = NULL; !ret && (c = ast_walk_contexts(c)); ) {
 			if (ast_rdlock_context(c))	/* fail, skip it */
 				continue;
-			if (!partial_match(ast_get_context_name(c), word, len))
+			if (!partial_match(ast_get_context_name(c), a->word, len))
 				continue;
-			if (lookup_c_ip(c, ignorepat) && ++which > state)
+			if (lookup_c_ip(c, ignorepat) && ++which > a->n)
 				ret = strdup(ast_get_context_name(c));
 			ast_unlock_context(c);
 		}
@@ -1258,54 +1306,47 @@ static char *complete_context_remove_ignorepat(const char *line, const char *wor
 
 static int pbx_load_module(void);
 
-static int handle_reload_extensions(int fd, int argc, char *argv[])
+static char *handle_cli_dialplan_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
-	if (argc != 2)
-		return RESULT_SHOWUSAGE;
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "dialplan reload";
+		e->usage =
+			"Usage: dialplan reload\n"
+			"       Reload extensions.conf without reloading any other\n"
+			"       modules.  This command does not delete global variables\n"
+			"       unless clearglobalvars is set to yes in extensions.conf\n";
+		return NULL;
+	case CLI_GENERATE:
+		return NULL;
+	}
+
+	if (a->argc != 2)
+		return CLI_SHOWUSAGE;
+
 	if (clearglobalvars_config)
 		pbx_builtin_clear_globals();
+
 	pbx_load_module();
-	return RESULT_SUCCESS;
+
+	return CLI_SUCCESS;
 }
 
 /*!
  * CLI entries for commands provided by this module
  */
 static struct ast_cli_entry cli_pbx_config[] = {
-	{ { "dialplan", "add", "extension", NULL },
-	handle_context_add_extension, "Add new extension into context",
-	context_add_extension_help, complete_context_add_extension },
-
-	{ { "dialplan", "remove", "extension", NULL },
-	handle_context_remove_extension, "Remove a specified extension",
-	context_remove_extension_help, complete_context_remove_extension },
-
-	{ { "dialplan", "add", "ignorepat", NULL },
-	handle_context_add_ignorepat, "Add new ignore pattern",
-	context_add_ignorepat_help, complete_context_add_ignorepat },
-
-	{ { "dialplan", "remove", "ignorepat", NULL },
-	handle_context_remove_ignorepat, "Remove ignore pattern from context",
-	context_remove_ignorepat_help, complete_context_remove_ignorepat },
-
-	{ { "dialplan", "add", "include", NULL },
-	handle_context_add_include, "Include context in other context",
-	context_add_include_help, complete_context_add_include },
-
-	{ { "dialplan", "remove", "include", NULL },
-	handle_context_remove_include, "Remove a specified include from context",
-	context_remove_include_help, complete_context_remove_include },
-
-	{ { "dialplan", "reload", NULL },
-	handle_reload_extensions, "Reload extensions and *only* extensions",
-	reload_extensions_help },
+	NEW_CLI(handle_cli_dialplan_add_extension,    "Add new extension into context"),
+	NEW_CLI(handle_cli_dialplan_remove_extension, "Remove a specified extension"),
+	NEW_CLI(handle_cli_dialplan_add_ignorepat,    "Add new ignore pattern"),
+	NEW_CLI(handle_cli_dialplan_remove_ignorepat, "Remove ignore pattern from context"),
+	NEW_CLI(handle_cli_dialplan_add_include,      "Include context in other context"),
+	NEW_CLI(handle_cli_dialplan_remove_include,   "Remove a specified include from context"),
+	NEW_CLI(handle_cli_dialplan_reload,           "Reload extensions and *only* extensions")
 };
 
-
-static struct ast_cli_entry cli_dialplan_save = {
-	{ "dialplan", "save", NULL },
-	handle_save_dialplan, "Save dialplan",
-	save_dialplan_help };
+static struct ast_cli_entry cli_dialplan_save =
+	NEW_CLI(handle_cli_dialplan_save, "Save dialplan");
 
 /*!
  * Standard module functions ...
diff --git a/pbx/pbx_dundi.c b/pbx/pbx_dundi.c
index d33e7c757b8aad569af528101e35962297b925b9..c2851eef235c5a3bc9bb57b4ce20b76903cc6366 100644
--- a/pbx/pbx_dundi.c
+++ b/pbx/pbx_dundi.c
@@ -2227,34 +2227,67 @@ static int start_network_thread(void)
 	return 0;
 }
 
-static int dundi_do_debug(int fd, int argc, char *argv[])
+static char *dundi_do_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
-	if (argc != 2)
-		return RESULT_SHOWUSAGE;
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "dundi debug";
+		e->usage = 
+			"Usage: dundi debug\n"
+			"       Enables dumping of DUNDi packets for debugging purposes\n";
+		return NULL;
+	case CLI_GENERATE:
+		return NULL;
+	}
+	if (a->argc != 2)
+		return CLI_SHOWUSAGE;
 	dundidebug = 1;
-	ast_cli(fd, "DUNDi Debugging Enabled\n");
-	return RESULT_SUCCESS;
+	ast_cli(a->fd, "DUNDi Debugging Enabled\n");
+	return CLI_SUCCESS;
 }
 
-static int dundi_do_store_history(int fd, int argc, char *argv[])
+static char *dundi_do_store_history(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
-	if (argc != 3)
-		return RESULT_SHOWUSAGE;
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "dundi store history";
+		e->usage = 
+			"Usage: dundi store history\n"
+			"       Enables storing of DUNDi requests and times for debugging\n"
+			"purposes\n";
+		return NULL;
+	case CLI_GENERATE:
+		return NULL;
+	}
+	if (a->argc != 3)
+		return CLI_SHOWUSAGE;
 	global_storehistory = 1;
-	ast_cli(fd, "DUNDi History Storage Enabled\n");
-	return RESULT_SUCCESS;
+	ast_cli(a->fd, "DUNDi History Storage Enabled\n");
+	return CLI_SUCCESS;
 }
 
-static int dundi_flush(int fd, int argc, char *argv[])
+static char *dundi_flush(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
 	int stats = 0;
-	if ((argc < 2) || (argc > 3))
-		return RESULT_SHOWUSAGE;
-	if (argc > 2) {
-		if (!strcasecmp(argv[2], "stats"))
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "dundi flush [stats]";
+		e->usage = 
+			"Usage: dundi flush [stats]\n"
+			"       Flushes DUNDi answer cache, used primarily for debug.  If\n"
+			"'stats' is present, clears timer statistics instead of normal\n"
+			"operation.\n";
+		return NULL;
+	case CLI_GENERATE:
+		return NULL;
+	}
+	if ((a->argc < 2) || (a->argc > 3))
+		return CLI_SHOWUSAGE;
+	if (a->argc > 2) {
+		if (!strcasecmp(a->argv[2], "stats"))
 			stats = 1;
 		else
-			return RESULT_SHOWUSAGE;
+			return CLI_SHOWUSAGE;
 	}
 	if (stats) {
 		/* Flush statistics */
@@ -2273,27 +2306,48 @@ static int dundi_flush(int fd, int argc, char *argv[])
 		AST_LIST_UNLOCK(&peers);
 	} else {
 		ast_db_deltree("dundi/cache", NULL);
-		ast_cli(fd, "DUNDi Cache Flushed\n");
+		ast_cli(a->fd, "DUNDi Cache Flushed\n");
 	}
-	return RESULT_SUCCESS;
+	return CLI_SUCCESS;
 }
 
-static int dundi_no_debug(int fd, int argc, char *argv[])
+static char *dundi_no_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
-	if (argc != 3)
-		return RESULT_SHOWUSAGE;
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "dundi no debug";
+		e->usage = 
+			"Usage: dundi no debug\n"
+			"       Disables dumping of DUNDi packets for debugging purposes\n";
+		return NULL;
+	case CLI_GENERATE:
+		return NULL;
+	}
+	if (a->argc != 3)
+		return CLI_SHOWUSAGE;
 	dundidebug = 0;
-	ast_cli(fd, "DUNDi Debugging Disabled\n");
-	return RESULT_SUCCESS;
+	ast_cli(a->fd, "DUNDi Debugging Disabled\n");
+	return CLI_SUCCESS;
 }
 
-static int dundi_no_store_history(int fd, int argc, char *argv[])
+static char *dundi_no_store_history(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
-	if (argc != 4)
-		return RESULT_SHOWUSAGE;
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "dundi no store history";
+		e->usage =
+			"Usage: dundi no store history\n"
+			"       Disables storing of DUNDi requests and times for debugging\n"
+			"purposes\n";
+		return NULL;
+	case CLI_GENERATE:
+		return NULL;
+	}
+	if (a->argc != 4)
+		return CLI_SHOWUSAGE;
 	global_storehistory = 0;
-	ast_cli(fd, "DUNDi History Storage Disabled\n");
-	return RESULT_SUCCESS;
+	ast_cli(a->fd, "DUNDi History Storage Disabled\n");
+	return CLI_SUCCESS;
 }
 
 static char *model2str(int model)
@@ -2330,11 +2384,6 @@ static char *complete_peer_helper(const char *line, const char *word, int pos, i
 	return ret;
 }
 
-static char *complete_peer_4(const char *line, const char *word, int pos, int state)
-{
-	return complete_peer_helper(line, word, pos, state, 3);
-}
-
 static int rescomp(const void *a, const void *b)
 {
 	const struct dundi_result *resa, *resb;
@@ -2352,7 +2401,7 @@ static void sort_results(struct dundi_result *results, int count)
 	qsort(results, count, sizeof(results[0]), rescomp);
 }
 
-static int dundi_do_lookup(int fd, int argc, char *argv[])
+static char *dundi_do_lookup(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
 	int res;
 	char tmp[256];
@@ -2362,15 +2411,28 @@ static int dundi_do_lookup(int fd, int argc, char *argv[])
 	int bypass = 0;
 	struct dundi_result dr[MAX_RESULTS];
 	struct timeval start;
-	if ((argc < 3) || (argc > 4))
-		return RESULT_SHOWUSAGE;
-	if (argc > 3) {
-		if (!strcasecmp(argv[3], "bypass"))
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "dundi lookup";
+		e->usage =
+			"Usage: dundi lookup <number>[@context] [bypass]\n"
+			"       Lookup the given number within the given DUNDi context\n"
+			"(or e164 if none is specified).  Bypasses cache if 'bypass'\n"
+			"keyword is specified.\n";
+		return NULL;
+	case CLI_GENERATE:
+		return NULL;
+	}
+
+	if ((a->argc < 3) || (a->argc > 4))
+		return CLI_SHOWUSAGE;
+	if (a->argc > 3) {
+		if (!strcasecmp(a->argv[3], "bypass"))
 			bypass=1;
 		else
-			return RESULT_SHOWUSAGE;
+			return CLI_SHOWUSAGE;
 	}
-	ast_copy_string(tmp, argv[2], sizeof(tmp));
+	ast_copy_string(tmp, a->argv[2], sizeof(tmp));
 	context = strchr(tmp, '@');
 	if (context) {
 		*context = '\0';
@@ -2380,28 +2442,40 @@ static int dundi_do_lookup(int fd, int argc, char *argv[])
 	res = dundi_lookup(dr, MAX_RESULTS, NULL, context, tmp, bypass);
 	
 	if (res < 0) 
-		ast_cli(fd, "DUNDi lookup returned error.\n");
+		ast_cli(a->fd, "DUNDi lookup returned error.\n");
 	else if (!res) 
-		ast_cli(fd, "DUNDi lookup returned no results.\n");
+		ast_cli(a->fd, "DUNDi lookup returned no results.\n");
 	else
 		sort_results(dr, res);
 	for (x=0;x<res;x++) {
-		ast_cli(fd, "%3d. %5d %s/%s (%s)\n", x + 1, dr[x].weight, dr[x].tech, dr[x].dest, dundi_flags2str(fs, sizeof(fs), dr[x].flags));
-		ast_cli(fd, "     from %s, expires in %d s\n", dr[x].eid_str, dr[x].expiration);
+		ast_cli(a->fd, "%3d. %5d %s/%s (%s)\n", x + 1, dr[x].weight, dr[x].tech, dr[x].dest, dundi_flags2str(fs, sizeof(fs), dr[x].flags));
+		ast_cli(a->fd, "     from %s, expires in %d s\n", dr[x].eid_str, dr[x].expiration);
 	}
-	ast_cli(fd, "DUNDi lookup completed in %d ms\n", ast_tvdiff_ms(ast_tvnow(), start));
-	return RESULT_SUCCESS;
+	ast_cli(a->fd, "DUNDi lookup completed in %d ms\n", ast_tvdiff_ms(ast_tvnow(), start));
+	return CLI_SUCCESS;
 }
 
-static int dundi_do_precache(int fd, int argc, char *argv[])
+static char *dundi_do_precache(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
 	int res;
 	char tmp[256];
 	char *context;
 	struct timeval start;
-	if ((argc < 3) || (argc > 3))
-		return RESULT_SHOWUSAGE;
-	ast_copy_string(tmp, argv[2], sizeof(tmp));
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "dundi precache";
+		e->usage = 
+			"Usage: dundi precache <number>[@context]\n"
+			"       Lookup the given number within the given DUNDi context\n"
+			"(or e164 if none is specified) and precaches the results to any\n"
+			"upstream DUNDi push servers.\n";
+		return NULL;
+	case CLI_GENERATE:
+		return NULL;
+	}
+	if ((a->argc < 3) || (a->argc > 3))
+		return CLI_SHOWUSAGE;
+	ast_copy_string(tmp, a->argv[2], sizeof(tmp));
 	context = strchr(tmp, '@');
 	if (context) {
 		*context = '\0';
@@ -2411,27 +2485,39 @@ static int dundi_do_precache(int fd, int argc, char *argv[])
 	res = dundi_precache(context, tmp);
 	
 	if (res < 0) 
-		ast_cli(fd, "DUNDi precache returned error.\n");
+		ast_cli(a->fd, "DUNDi precache returned error.\n");
 	else if (!res) 
-		ast_cli(fd, "DUNDi precache returned no error.\n");
-	ast_cli(fd, "DUNDi lookup completed in %d ms\n", ast_tvdiff_ms(ast_tvnow(), start));
-	return RESULT_SUCCESS;
+		ast_cli(a->fd, "DUNDi precache returned no error.\n");
+	ast_cli(a->fd, "DUNDi lookup completed in %d ms\n", ast_tvdiff_ms(ast_tvnow(), start));
+	return CLI_SUCCESS;
 }
 
-static int dundi_do_query(int fd, int argc, char *argv[])
+static char *dundi_do_query(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
 	int res;
 	char tmp[256];
 	char *context;
 	dundi_eid eid;
 	struct dundi_entity_info dei;
-	if ((argc < 3) || (argc > 3))
-		return RESULT_SHOWUSAGE;
-	if (dundi_str_to_eid(&eid, argv[2])) {
-		ast_cli(fd, "'%s' is not a valid EID!\n", argv[2]);
-		return RESULT_SHOWUSAGE;
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "dundi query";
+		e->usage = 
+			"Usage: dundi query <entity>[@context]\n"
+			"       Attempts to retrieve contact information for a specific\n"
+			"DUNDi entity identifier (EID) within a given DUNDi context (or\n"
+			"e164 if none is specified).\n";
+		return NULL;
+	case CLI_GENERATE:
+		return NULL;
 	}
-	ast_copy_string(tmp, argv[2], sizeof(tmp));
+	if ((a->argc < 3) || (a->argc > 3))
+		return CLI_SHOWUSAGE;
+	if (dundi_str_to_eid(&eid, a->argv[2])) {
+		ast_cli(a->fd, "'%s' is not a valid EID!\n", a->argv[2]);
+		return CLI_SHOWUSAGE;
+	}
+	ast_copy_string(tmp, a->argv[2], sizeof(tmp));
 	context = strchr(tmp, '@');
 	if (context) {
 		*context = '\0';
@@ -2439,36 +2525,45 @@ static int dundi_do_query(int fd, int argc, char *argv[])
 	}
 	res = dundi_query_eid(&dei, context, eid);
 	if (res < 0) 
-		ast_cli(fd, "DUNDi Query EID returned error.\n");
+		ast_cli(a->fd, "DUNDi Query EID returned error.\n");
 	else if (!res) 
-		ast_cli(fd, "DUNDi Query EID returned no results.\n");
+		ast_cli(a->fd, "DUNDi Query EID returned no results.\n");
 	else {
-		ast_cli(fd, "DUNDi Query EID succeeded:\n");
-		ast_cli(fd, "Department:      %s\n", dei.orgunit);
-		ast_cli(fd, "Organization:    %s\n", dei.org);
-		ast_cli(fd, "City/Locality:   %s\n", dei.locality);
-		ast_cli(fd, "State/Province:  %s\n", dei.stateprov);
-		ast_cli(fd, "Country:         %s\n", dei.country);
-		ast_cli(fd, "E-mail:          %s\n", dei.email);
-		ast_cli(fd, "Phone:           %s\n", dei.phone);
-		ast_cli(fd, "IP Address:      %s\n", dei.ipaddr);
-	}
-	return RESULT_SUCCESS;
+		ast_cli(a->fd, "DUNDi Query EID succeeded:\n");
+		ast_cli(a->fd, "Department:      %s\n", dei.orgunit);
+		ast_cli(a->fd, "Organization:    %s\n", dei.org);
+		ast_cli(a->fd, "City/Locality:   %s\n", dei.locality);
+		ast_cli(a->fd, "State/Province:  %s\n", dei.stateprov);
+		ast_cli(a->fd, "Country:         %s\n", dei.country);
+		ast_cli(a->fd, "E-mail:          %s\n", dei.email);
+		ast_cli(a->fd, "Phone:           %s\n", dei.phone);
+		ast_cli(a->fd, "IP Address:      %s\n", dei.ipaddr);
+	}
+	return CLI_SUCCESS;
 }
 
-static int dundi_show_peer(int fd, int argc, char *argv[])
+static char *dundi_show_peer(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
 	struct dundi_peer *peer;
 	struct permission *p;
 	char *order;
 	char eid_str[20];
 	int x, cnt;
-	
-	if (argc != 4)
-		return RESULT_SHOWUSAGE;
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "dundi show peer";
+		e->usage =
+			"Usage: dundi show peer [peer]\n"
+			"       Provide a detailed description of a specifid DUNDi peer.\n";
+		return NULL;
+	case CLI_GENERATE:
+		return complete_peer_helper(a->line, a->word, a->pos, a->n, 3);
+	}
+	if (a->argc != 4)
+		return CLI_SHOWUSAGE;
 	AST_LIST_LOCK(&peers);
 	AST_LIST_TRAVERSE(&peers, peer, list) {
-		if (!strcasecmp(dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid), argv[3]))
+		if (!strcasecmp(dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid), a->argv[3]))
 			break;
 	}
 	if (peer) {
@@ -2488,39 +2583,39 @@ static int dundi_show_peer(int fd, int argc, char *argv[])
 		default:
 			order = "Unknown";
 		}
-		ast_cli(fd, "Peer:    %s\n", dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
-		ast_cli(fd, "Model:   %s\n", model2str(peer->model));
-		ast_cli(fd, "Host:    %s\n", peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "<Unspecified>");
-		ast_cli(fd, "Dynamic: %s\n", peer->dynamic ? "yes" : "no");
-		ast_cli(fd, "Reg:     %s\n", peer->registerid < 0 ? "No" : "Yes");
-		ast_cli(fd, "In Key:  %s\n", ast_strlen_zero(peer->inkey) ? "<None>" : peer->inkey);
-		ast_cli(fd, "Out Key: %s\n", ast_strlen_zero(peer->outkey) ? "<None>" : peer->outkey);
+		ast_cli(a->fd, "Peer:    %s\n", dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
+		ast_cli(a->fd, "Model:   %s\n", model2str(peer->model));
+		ast_cli(a->fd, "Host:    %s\n", peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "<Unspecified>");
+		ast_cli(a->fd, "Dynamic: %s\n", peer->dynamic ? "yes" : "no");
+		ast_cli(a->fd, "Reg:     %s\n", peer->registerid < 0 ? "No" : "Yes");
+		ast_cli(a->fd, "In Key:  %s\n", ast_strlen_zero(peer->inkey) ? "<None>" : peer->inkey);
+		ast_cli(a->fd, "Out Key: %s\n", ast_strlen_zero(peer->outkey) ? "<None>" : peer->outkey);
 		if (!AST_LIST_EMPTY(&peer->include))
-			ast_cli(fd, "Include logic%s:\n", peer->model & DUNDI_MODEL_OUTBOUND ? "" : " (IGNORED)");
+			ast_cli(a->fd, "Include logic%s:\n", peer->model & DUNDI_MODEL_OUTBOUND ? "" : " (IGNORED)");
 		AST_LIST_TRAVERSE(&peer->include, p, list)
-			ast_cli(fd, "-- %s %s\n", p->allow ? "include" : "do not include", p->name);
+			ast_cli(a->fd, "-- %s %s\n", p->allow ? "include" : "do not include", p->name);
 		if (!AST_LIST_EMPTY(&peer->permit))
-			ast_cli(fd, "Query logic%s:\n", peer->model & DUNDI_MODEL_INBOUND ? "" : " (IGNORED)");
+			ast_cli(a->fd, "Query logic%s:\n", peer->model & DUNDI_MODEL_INBOUND ? "" : " (IGNORED)");
 		AST_LIST_TRAVERSE(&peer->permit, p, list)
-			ast_cli(fd, "-- %s %s\n", p->allow ? "permit" : "deny", p->name);
+			ast_cli(a->fd, "-- %s %s\n", p->allow ? "permit" : "deny", p->name);
 		cnt = 0;
 		for (x = 0;x < DUNDI_TIMING_HISTORY; x++) {
 			if (peer->lookups[x]) {
 				if (!cnt)
-					ast_cli(fd, "Last few query times:\n");
-				ast_cli(fd, "-- %d. %s (%d ms)\n", x + 1, peer->lookups[x], peer->lookuptimes[x]);
+					ast_cli(a->fd, "Last few query times:\n");
+				ast_cli(a->fd, "-- %d. %s (%d ms)\n", x + 1, peer->lookups[x], peer->lookuptimes[x]);
 				cnt++;
 			}
 		}
 		if (cnt)
-			ast_cli(fd, "Average query time: %d ms\n", peer->avgms);
+			ast_cli(a->fd, "Average query time: %d ms\n", peer->avgms);
 	} else
-		ast_cli(fd, "No such peer '%s'\n", argv[3]);
+		ast_cli(a->fd, "No such peer '%s'\n", a->argv[3]);
 	AST_LIST_UNLOCK(&peers);
-	return RESULT_SUCCESS;
+	return CLI_SUCCESS;
 }
 
-static int dundi_show_peers(int fd, int argc, char *argv[])
+static char *dundi_show_peers(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
 #define FORMAT2 "%-20.20s %-15.15s     %-10.10s %-8.8s %-15.15s\n"
 #define FORMAT "%-20.20s %-15.15s %s %-10.10s %-8.8s %-15.15s\n"
@@ -2532,17 +2627,28 @@ static int dundi_show_peers(int fd, int argc, char *argv[])
 	int offline_peers = 0;
 	int unmonitored_peers = 0;
 	int total_peers = 0;
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "dundi show peers [registered|include|exclude|begin]";
+		e->usage = 
+			"Usage: dundi show peers [registered|include|exclude|begin]\n"
+			"       Lists all known DUNDi peers.\n"
+			"       If 'registered' is present, only registered peers are shown.\n";
+		return NULL;
+	case CLI_GENERATE:
+		return NULL;
+	}
 
-	if ((argc != 3) && (argc != 4) && (argc != 5))
-		return RESULT_SHOWUSAGE;
-	if ((argc == 4)) {
- 		if (!strcasecmp(argv[3], "registered")) {
+	if ((a->argc != 3) && (a->argc != 4) && (a->argc != 5))
+		return CLI_SHOWUSAGE;
+	if ((a->argc == 4)) {
+ 		if (!strcasecmp(a->argv[3], "registered")) {
 			registeredonly = 1;
 		} else
-			return RESULT_SHOWUSAGE;
+			return CLI_SHOWUSAGE;
  	}
 	AST_LIST_LOCK(&peers);
-	ast_cli(fd, FORMAT2, "EID", "Host", "Model", "AvgTime", "Status");
+	ast_cli(a->fd, FORMAT2, "EID", "Host", "Model", "AvgTime", "Status");
 	AST_LIST_TRAVERSE(&peers, peer, list) {
 		char status[20];
 		int print_line = -1;
@@ -2579,12 +2685,12 @@ static int dundi_show_peers(int fd, int argc, char *argv[])
 					peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "(Unspecified)",
 					peer->dynamic ? "(D)" : "(S)", model2str(peer->model), avgms, status);
 
-                if (argc == 5) {
-                  if (!strcasecmp(argv[3],"include") && strstr(srch,argv[4])) {
+                if (a->argc == 5) {
+                  if (!strcasecmp(a->argv[3],"include") && strstr(srch,a->argv[4])) {
                         print_line = -1;
-                   } else if (!strcasecmp(argv[3],"exclude") && !strstr(srch,argv[4])) {
+                   } else if (!strcasecmp(a->argv[3],"exclude") && !strstr(srch,a->argv[4])) {
                         print_line = 1;
-                   } else if (!strcasecmp(argv[3],"begin") && !strncasecmp(srch,argv[4],strlen(argv[4]))) {
+                   } else if (!strcasecmp(a->argv[3],"begin") && !strncasecmp(srch,a->argv[4],strlen(a->argv[4]))) {
                         print_line = -1;
                    } else {
                         print_line = 0;
@@ -2592,106 +2698,155 @@ static int dundi_show_peers(int fd, int argc, char *argv[])
                 }
 		
         if (print_line) {
-			ast_cli(fd, FORMAT, dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid), 
+			ast_cli(a->fd, FORMAT, dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid), 
 					peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "(Unspecified)",
 					peer->dynamic ? "(D)" : "(S)", model2str(peer->model), avgms, status);
 		}
 	}
-	ast_cli(fd, "%d dundi peers [%d online, %d offline, %d unmonitored]\n", total_peers, online_peers, offline_peers, unmonitored_peers);
+	ast_cli(a->fd, "%d dundi peers [%d online, %d offline, %d unmonitored]\n", total_peers, online_peers, offline_peers, unmonitored_peers);
 	AST_LIST_UNLOCK(&peers);
-	return RESULT_SUCCESS;
+	return CLI_SUCCESS;
 #undef FORMAT
 #undef FORMAT2
 }
 
-static int dundi_show_trans(int fd, int argc, char *argv[])
+static char *dundi_show_trans(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
 #define FORMAT2 "%-22.22s %-5.5s %-5.5s %-3.3s %-3.3s %-3.3s\n"
 #define FORMAT "%-16.16s:%5d %-5.5d %-5.5d %-3.3d %-3.3d %-3.3d\n"
 	struct dundi_transaction *trans;
-	if (argc != 3)
-		return RESULT_SHOWUSAGE;
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "dundi show trans";
+		e->usage = 
+			"Usage: dundi show trans\n"
+			"       Lists all known DUNDi transactions.\n";
+		return NULL;
+	case CLI_GENERATE:
+		return NULL;
+	}
+	if (a->argc != 3)
+		return CLI_SHOWUSAGE;
 	AST_LIST_LOCK(&peers);
-	ast_cli(fd, FORMAT2, "Remote", "Src", "Dst", "Tx", "Rx", "Ack");
+	ast_cli(a->fd, FORMAT2, "Remote", "Src", "Dst", "Tx", "Rx", "Ack");
 	AST_LIST_TRAVERSE(&alltrans, trans, all) {
-		ast_cli(fd, FORMAT, ast_inet_ntoa(trans->addr.sin_addr), 
+		ast_cli(a->fd, FORMAT, ast_inet_ntoa(trans->addr.sin_addr), 
 			ntohs(trans->addr.sin_port), trans->strans, trans->dtrans, trans->oseqno, trans->iseqno, trans->aseqno);
 	}
 	AST_LIST_UNLOCK(&peers);
-	return RESULT_SUCCESS;
+	return CLI_SUCCESS;
 #undef FORMAT
 #undef FORMAT2
 }
 
-static int dundi_show_entityid(int fd, int argc, char *argv[])
+static char *dundi_show_entityid(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
 	char eid_str[20];
-	if (argc != 3)
-		return RESULT_SHOWUSAGE;
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "dundi show entityid";
+		e->usage =
+			"Usage: dundi show entityid\n"
+			"       Displays the global entityid for this host.\n";
+		return NULL;
+	case CLI_GENERATE:
+		return NULL;
+	}
+	if (a->argc != 3)
+		return CLI_SHOWUSAGE;
 	AST_LIST_LOCK(&peers);
 	dundi_eid_to_str(eid_str, sizeof(eid_str), &global_eid);
 	AST_LIST_UNLOCK(&peers);
-	ast_cli(fd, "Global EID for this system is '%s'\n", eid_str);
-	return RESULT_SUCCESS;
+	ast_cli(a->fd, "Global EID for this system is '%s'\n", eid_str);
+	return CLI_SUCCESS;
 }
 
-static int dundi_show_requests(int fd, int argc, char *argv[])
+static char *dundi_show_requests(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
 #define FORMAT2 "%-15s %-15s %-15s %-3.3s %-3.3s\n"
 #define FORMAT "%-15s %-15s %-15s %-3.3d %-3.3d\n"
 	struct dundi_request *req;
 	char eidstr[20];
-	if (argc != 3)
-		return RESULT_SHOWUSAGE;
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "dundi show requests";
+		e->usage = 
+			"Usage: dundi show requests\n"
+			"       Lists all known pending DUNDi requests.\n";
+		return NULL;
+	case CLI_GENERATE:
+		return NULL;
+	}
+	if (a->argc != 3)
+		return CLI_SHOWUSAGE;
 	AST_LIST_LOCK(&peers);
-	ast_cli(fd, FORMAT2, "Number", "Context", "Root", "Max", "Rsp");
+	ast_cli(a->fd, FORMAT2, "Number", "Context", "Root", "Max", "Rsp");
 	AST_LIST_TRAVERSE(&requests, req, list) {
-		ast_cli(fd, FORMAT, req->number, req->dcontext,
+		ast_cli(a->fd, FORMAT, req->number, req->dcontext,
 			dundi_eid_zero(&req->root_eid) ? "<unspecified>" : dundi_eid_to_str(eidstr, sizeof(eidstr), &req->root_eid), req->maxcount, req->respcount);
 	}
 	AST_LIST_UNLOCK(&peers);
-	return RESULT_SUCCESS;
+	return CLI_SUCCESS;
 #undef FORMAT
 #undef FORMAT2
 }
 
 /* Grok-a-dial DUNDi */
 
-static int dundi_show_mappings(int fd, int argc, char *argv[])
+static char *dundi_show_mappings(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
 #define FORMAT2 "%-12.12s %-7.7s %-12.12s %-10.10s %-5.5s %-25.25s\n"
 #define FORMAT "%-12.12s %-7s %-12.12s %-10.10s %-5.5s %-25.25s\n"
 	struct dundi_mapping *map;
 	char fs[256];
 	char weight[8];
-	if (argc != 3)
-		return RESULT_SHOWUSAGE;
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "dundi show mappings";
+		e->usage = 
+			"Usage: dundi show mappings\n"
+			"       Lists all known DUNDi mappings.\n";
+		return NULL;
+	case CLI_GENERATE:
+		return NULL;
+	}
+	if (a->argc != 3)
+		return CLI_SHOWUSAGE;
 	AST_LIST_LOCK(&peers);
-	ast_cli(fd, FORMAT2, "DUNDi Cntxt", "Weight", "Local Cntxt", "Options", "Tech", "Destination");
+	ast_cli(a->fd, FORMAT2, "DUNDi Cntxt", "Weight", "Local Cntxt", "Options", "Tech", "Destination");
 	AST_LIST_TRAVERSE(&mappings, map, list) {
 		snprintf(weight, sizeof(weight), "%d", get_mapping_weight(map));
-		ast_cli(fd, FORMAT, map->dcontext, weight,
+		ast_cli(a->fd, FORMAT, map->dcontext, weight,
 			ast_strlen_zero(map->lcontext) ? "<none>" : map->lcontext, 
 			dundi_flags2str(fs, sizeof(fs), map->options), tech2str(map->tech), map->dest);
 	}
 	AST_LIST_UNLOCK(&peers);
-	return RESULT_SUCCESS;
+	return CLI_SUCCESS;
 #undef FORMAT
 #undef FORMAT2
 }
 
-static int dundi_show_precache(int fd, int argc, char *argv[])
+static char *dundi_show_precache(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
 #define FORMAT2 "%-12.12s %-12.12s %-10.10s\n"
 #define FORMAT "%-12.12s %-12.12s %02d:%02d:%02d\n"
 	struct dundi_precache_queue *qe;
 	int h,m,s;
 	time_t now;
-	
-	if (argc != 3)
-		return RESULT_SHOWUSAGE;
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "dundi show precache";
+		e->usage = 
+			"Usage: dundi show precache\n"
+			"       Lists all known DUNDi scheduled precache updates.\n";
+		return NULL;
+	case CLI_GENERATE:
+		return NULL;
+	}
+	if (a->argc != 3)
+		return CLI_SHOWUSAGE;
 	time(&now);
-	ast_cli(fd, FORMAT2, "Number", "Context", "Expiration");
+	ast_cli(a->fd, FORMAT2, "Number", "Context", "Expiration");
 	AST_LIST_LOCK(&pcq);
 	AST_LIST_TRAVERSE(&pcq, qe, list) {
 		s = qe->expiration - now;
@@ -2699,145 +2854,31 @@ static int dundi_show_precache(int fd, int argc, char *argv[])
 		s = s % 3600;
 		m = s / 60;
 		s = s % 60;
-		ast_cli(fd, FORMAT, qe->number, qe->context, h,m,s);
+		ast_cli(a->fd, FORMAT, qe->number, qe->context, h,m,s);
 	}
 	AST_LIST_UNLOCK(&pcq);
 	
-	return RESULT_SUCCESS;
+	return CLI_SUCCESS;
 #undef FORMAT
 #undef FORMAT2
 }
 
-static const char debug_usage[] = 
-"Usage: dundi debug\n"
-"       Enables dumping of DUNDi packets for debugging purposes\n";
-
-static const char no_debug_usage[] = 
-"Usage: dundi no debug\n"
-"       Disables dumping of DUNDi packets for debugging purposes\n";
-
-static const char store_history_usage[] = 
-"Usage: dundi store history\n"
-"       Enables storing of DUNDi requests and times for debugging\n"
-"purposes\n";
-
-static const char no_store_history_usage[] = 
-"Usage: dundi no store history\n"
-"       Disables storing of DUNDi requests and times for debugging\n"
-"purposes\n";
-
-static const char show_peers_usage[] = 
-"Usage: dundi show peers\n"
-"       Lists all known DUNDi peers.\n";
-
-static const char show_trans_usage[] = 
-"Usage: dundi show trans\n"
-"       Lists all known DUNDi transactions.\n";
-
-static const char show_mappings_usage[] = 
-"Usage: dundi show mappings\n"
-"       Lists all known DUNDi mappings.\n";
-
-static const char show_precache_usage[] = 
-"Usage: dundi show precache\n"
-"       Lists all known DUNDi scheduled precache updates.\n";
-
-static const char show_entityid_usage[] = 
-"Usage: dundi show entityid\n"
-"       Displays the global entityid for this host.\n";
-
-static const char show_peer_usage[] = 
-"Usage: dundi show peer [peer]\n"
-"       Provide a detailed description of a specifid DUNDi peer.\n";
-
-static const char show_requests_usage[] = 
-"Usage: dundi show requests\n"
-"       Lists all known pending DUNDi requests.\n";
-
-static const char lookup_usage[] =
-"Usage: dundi lookup <number>[@context] [bypass]\n"
-"       Lookup the given number within the given DUNDi context\n"
-"(or e164 if none is specified).  Bypasses cache if 'bypass'\n"
-"keyword is specified.\n";
-
-static const char precache_usage[] =
-"Usage: dundi precache <number>[@context]\n"
-"       Lookup the given number within the given DUNDi context\n"
-"(or e164 if none is specified) and precaches the results to any\n"
-"upstream DUNDi push servers.\n";
-
-static const char query_usage[] =
-"Usage: dundi query <entity>[@context]\n"
-"       Attempts to retrieve contact information for a specific\n"
-"DUNDi entity identifier (EID) within a given DUNDi context (or\n"
-"e164 if none is specified).\n";
-
-static const char flush_usage[] =
-"Usage: dundi flush [stats]\n"
-"       Flushes DUNDi answer cache, used primarily for debug.  If\n"
-"'stats' is present, clears timer statistics instead of normal\n"
-"operation.\n";
-
 static struct ast_cli_entry cli_dundi[] = {
-	{ { "dundi", "debug", NULL },
-	dundi_do_debug, "Enable DUNDi debugging",
-	debug_usage },
-
-	{ { "dundi", "store", "history", NULL },
-	dundi_do_store_history, "Enable DUNDi historic records",
-	store_history_usage },
-
-	{ { "dundi", "no", "store", "history", NULL },
-	dundi_no_store_history, "Disable DUNDi historic records",
-	no_store_history_usage },
-
-	{ { "dundi", "flush", NULL },
-	dundi_flush, "Flush DUNDi cache",
-	flush_usage },
-
-	{ { "dundi", "no", "debug", NULL },
-	dundi_no_debug, "Disable DUNDi debugging",
-	no_debug_usage },
-
-	{ { "dundi", "show", "peers", NULL },
-	dundi_show_peers, "Show defined DUNDi peers",
-	show_peers_usage },
-
-	{ { "dundi", "show", "trans", NULL },
-	dundi_show_trans, "Show active DUNDi transactions",
-	show_trans_usage },
-
-	{ { "dundi", "show", "entityid", NULL },
-	dundi_show_entityid, "Display Global Entity ID",
-	show_entityid_usage },
-
-	{ { "dundi", "show", "mappings", NULL },
-	dundi_show_mappings, "Show DUNDi mappings",
-	show_mappings_usage },
-
-	{ { "dundi", "show", "precache", NULL },
-	dundi_show_precache, "Show DUNDi precache",
-	show_precache_usage },
-
-	{ { "dundi", "show", "requests", NULL },
-	dundi_show_requests, "Show DUNDi requests",
-	show_requests_usage },
-
-	{ { "dundi", "show", "peer", NULL },
-	dundi_show_peer, "Show info on a specific DUNDi peer",
-	show_peer_usage, complete_peer_4 },
-
-	{ { "dundi", "lookup", NULL },
-	dundi_do_lookup, "Lookup a number in DUNDi",
-	lookup_usage },
-
-	{ { "dundi", "precache", NULL },
-	dundi_do_precache, "Precache a number in DUNDi",
-	precache_usage },
-
-	{ { "dundi", "query", NULL },
-	dundi_do_query, "Query a DUNDi EID",
-	query_usage },
+	NEW_CLI(dundi_do_debug, "Enable DUNDi debugging"),
+	NEW_CLI(dundi_no_debug, "Disable DUNDi debugging"),
+	NEW_CLI(dundi_do_store_history, "Enable DUNDi historic records"),
+	NEW_CLI(dundi_no_store_history, "Disable DUNDi historic records"),
+	NEW_CLI(dundi_flush, "Flush DUNDi cache"),
+	NEW_CLI(dundi_show_peers, "Show defined DUNDi peers"),
+	NEW_CLI(dundi_show_trans, "Show active DUNDi transactions"),
+	NEW_CLI(dundi_show_entityid, "Display Global Entity ID"),
+	NEW_CLI(dundi_show_mappings, "Show DUNDi mappings"),
+	NEW_CLI(dundi_show_precache, "Show DUNDi precache"),
+	NEW_CLI(dundi_show_requests, "Show DUNDi requests"),
+	NEW_CLI(dundi_show_peer, "Show info on a specific DUNDi peer"),
+	NEW_CLI(dundi_do_precache, "Precache a number in DUNDi"),
+	NEW_CLI(dundi_do_lookup, "Lookup a number in DUNDi"),
+	NEW_CLI(dundi_do_query, "Query a DUNDi EID"),
 };
 
 static struct dundi_transaction *create_transaction(struct dundi_peer *p)
diff --git a/res/res_clioriginate.c b/res/res_clioriginate.c
index 8497f6387af4a0afe919d76b1151e37b325f0701..7a9245aba5d9c2fb0cfc609daeb348450f970ec0 100644
--- a/res/res_clioriginate.c
+++ b/res/res_clioriginate.c
@@ -43,61 +43,35 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$");
 /*! The timeout for originated calls, in seconds */
 #define TIMEOUT 30
 
-static char orig_help[] = 
-"  There are two ways to use this command. A call can be originated between a\n"
-"channel and a specific application, or between a channel and an extension in\n"
-"the dialplan. This is similar to call files or the manager originate action.\n"
-"Calls originated with this command are given a timeout of 30 seconds.\n\n"
-
-"Usage1: originate <tech/data> application <appname> [appdata]\n"
-"  This will originate a call between the specified channel tech/data and the\n"
-"given application. Arguments to the application are optional. If the given\n"
-"arguments to the application include spaces, all of the arguments to the\n"
-"application need to be placed in quotation marks.\n\n"
-
-"Usage2: originate <tech/data> extension [exten@][context]\n"
-"  This will originate a call between the specified channel tech/data and the\n"
-"given extension. If no context is specified, the 'default' context will be\n"
-"used. If no extension is given, the 's' extension will be used.\n";
-
-static int handle_orig(int fd, int argc, char *argv[]);
-static char *complete_orig(const char *line, const char *word, int pos, int state);
-
-struct ast_cli_entry cli_cliorig[] = {
-	{ { "originate", NULL },
-	handle_orig, "Originate a call",
-	orig_help, complete_orig },
-};
-
 /*!
  * \brief orginate a call from the CLI
  * \param fd file descriptor for cli
  * \param chan channel to create type/data
  * \param app application you want to run
  * \param appdata data for application
- * \retval RESULT_SUCCESS on success.
- * \retval RESULT_SHOWUSAGE on failure.
+ * \retval CLI_SUCCESS on success.
+ * \retval CLI_SHOWUSAGE on failure.
 */
-static int orig_app(int fd, const char *chan, const char *app, const char *appdata)
+static char *orig_app(int fd, const char *chan, const char *app, const char *appdata)
 {
 	char *chantech;
 	char *chandata;
 	int reason = 0;
 	
 	if (ast_strlen_zero(app))
-		return RESULT_SHOWUSAGE;
+		return CLI_SHOWUSAGE;
 
 	chandata = ast_strdupa(chan);
 	
 	chantech = strsep(&chandata, "/");
 	if (!chandata) {
 		ast_cli(fd, "*** No data provided after channel type! ***\n");
-		return RESULT_SHOWUSAGE;
+		return CLI_SHOWUSAGE;
 	}
 
 	ast_pbx_outgoing_app(chantech, AST_FORMAT_SLINEAR, chandata, TIMEOUT * 1000, app, appdata, &reason, 1, NULL, NULL, NULL, NULL, NULL);
 
-	return RESULT_SUCCESS;
+	return CLI_SUCCESS;
 }
 
 /*!
@@ -105,10 +79,10 @@ static int orig_app(int fd, const char *chan, const char *app, const char *appda
  * \param fd file descriptor for cli
  * \param chan channel to create type/data
  * \param data contains exten\@context
- * \retval RESULT_SUCCESS on success.
- * \retval RESULT_SHOWUSAGE on failure.
+ * \retval CLI_SUCCESS on success.
+ * \retval CLI_SHOWUSAGE on failure.
 */
-static int orig_exten(int fd, const char *chan, const char *data)
+static char *orig_exten(int fd, const char *chan, const char *data)
 {
 	char *chantech;
 	char *chandata;
@@ -121,7 +95,7 @@ static int orig_exten(int fd, const char *chan, const char *data)
 	chantech = strsep(&chandata, "/");
 	if (!chandata) {
 		ast_cli(fd, "*** No data provided after channel type! ***\n");
-		return RESULT_SHOWUSAGE;
+		return CLI_SHOWUSAGE;
 	}
 
 	if (!ast_strlen_zero(data)) {
@@ -136,63 +110,74 @@ static int orig_exten(int fd, const char *chan, const char *data)
 	
 	ast_pbx_outgoing_exten(chantech, AST_FORMAT_SLINEAR, chandata, TIMEOUT * 1000, context, exten, 1, &reason, 1, NULL, NULL, NULL, NULL, NULL);
 
-	return RESULT_SUCCESS;
+	return CLI_SUCCESS;
 }
 
 /*!
  * \brief handle for orgination app or exten.
- * \param fd file descriptor
- * \param argc no of arguements
- * \param argv contains either application or extension arguements
- * \retval RESULT_SUCCESS on success.
- * \retval RESULT_SHOWUSAGE on failure.
+ * \param e pointer to the CLI structure to initialize
+ * \param cmd operation to execute
+ * \param a structure that contains either application or extension arguements
+ * \retval CLI_SUCCESS on success.
+ * \retval CLI_SHOWUSAGE  on failure.
 */
-static int handle_orig(int fd, int argc, char *argv[])
+static char *handle_orig(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
-	int res;
+	static char *choices[] = { "application", "extension", NULL };
+	char *res;
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "originate";
+		e->usage = 
+			"  There are two ways to use this command. A call can be originated between a\n"
+			"channel and a specific application, or between a channel and an extension in\n"
+			"the dialplan. This is similar to call files or the manager originate action.\n"
+			"Calls originated with this command are given a timeout of 30 seconds.\n\n"
+
+			"Usage1: originate <tech/data> application <appname> [appdata]\n"
+			"  This will originate a call between the specified channel tech/data and the\n"
+			"given application. Arguments to the application are optional. If the given\n"
+			"arguments to the application include spaces, all of the arguments to the\n"
+			"application need to be placed in quotation marks.\n\n"
+
+			"Usage2: originate <tech/data> extension [exten@][context]\n"
+			"  This will originate a call between the specified channel tech/data and the\n"
+			"given extension. If no context is specified, the 'default' context will be\n"
+			"used. If no extension is given, the 's' extension will be used.\n";
+		return NULL;
+	case CLI_GENERATE:
+		if (a->pos != 2)
+			return NULL;
+
+		/* ugly, can be removed when CLI entries have ast_module pointers */
+		ast_module_ref(ast_module_info->self);
+		res = ast_cli_complete(a->word, choices, a->n);
+		ast_module_unref(ast_module_info->self);
 
-	if (ast_strlen_zero(argv[1]) || ast_strlen_zero(argv[2]))
-		return RESULT_SHOWUSAGE;
+		return res;
+	}
+
+	if (ast_strlen_zero(a->argv[1]) || ast_strlen_zero(a->argv[2]))
+		return CLI_SHOWUSAGE;
 
 	/* ugly, can be removed when CLI entries have ast_module pointers */
 	ast_module_ref(ast_module_info->self);
 
-	if (!strcasecmp("application", argv[2])) {
-		res = orig_app(fd, argv[1], argv[3], argv[4]);	
-	} else if (!strcasecmp("extension", argv[2])) {
-		res = orig_exten(fd, argv[1], argv[3]);
+	if (!strcasecmp("application", a->argv[2])) {
+		res = orig_app(a->fd, a->argv[1], a->argv[3], a->argv[4]);	
+	} else if (!strcasecmp("extension", a->argv[2])) {
+		res = orig_exten(a->fd, a->argv[1], a->argv[3]);
 	} else
-		res = RESULT_SHOWUSAGE;
+		res = CLI_SHOWUSAGE;
 
 	ast_module_unref(ast_module_info->self);
 
 	return res;
 }
 
-/*!
- * \brief complete suggestions for orginate command
- * \param line 
- * \param word to be completed word
- * \param pos position
- * \param state
- * \retval completed word
- * \retval NULL on failure
-*/
-static char *complete_orig(const char *line, const char *word, int pos, int state)
-{
-	static char *choices[] = { "application", "extension", NULL };
-	char *ret;
-
-	if (pos != 2)
-		return NULL;
-
-	/* ugly, can be removed when CLI entries have ast_module pointers */
-	ast_module_ref(ast_module_info->self);
-	ret = ast_cli_complete(word, choices, state);
-	ast_module_unref(ast_module_info->self);
-
-	return ret;
-}
+static struct ast_cli_entry cli_cliorig[] = {
+	NEW_CLI(handle_orig, "Originate a call"),
+};
 
 /*! \brief Unload orginate module */
 static int unload_module(void)
diff --git a/res/res_convert.c b/res/res_convert.c
index 34606ac24688c87bb2178009d3b5cd12550f0ec4..2e514b111abc23809ba4bddaa2bda9e07fe5038d 100644
--- a/res/res_convert.c
+++ b/res/res_convert.c
@@ -61,45 +61,60 @@ static int split_ext(char *filename, char **name, char **ext)
  * \param fd file descriptor
  * \param argc no arguements
  * \param argv list of arguements
- * \retval RESULT_SUCCESS on success.
- * \retval RESULT_SHOWUSAGE on failure.
+ * \retval CLI_SUCCESS on success.
+ * \retval CLI_SHOWUSAGE or CLI_FAILURE on failure.
 */
-static int cli_audio_convert(int fd, int argc, char *argv[])
+static char *handle_cli_file_convert(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
-	int ret = RESULT_FAILURE;
+	char *ret = CLI_FAILURE;
 	struct ast_filestream *fs_in = NULL, *fs_out = NULL;
 	struct ast_frame *f;
 	struct timeval start;
 	int cost;
 	char *file_in = NULL, *file_out = NULL;
 	char *name_in, *ext_in, *name_out, *ext_out;
+
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "file convert";
+		e->usage =
+			"Usage: file convert <file_in> <file_out>\n"
+			"       Convert from file_in to file_out. If an absolute path\n"
+			"       is not given, the default Asterisk sounds directory\n"
+			"       will be used.\n\n"
+			"       Example:\n"
+			"           file convert tt-weasels.gsm tt-weasels.ulaw\n";
+		return NULL;
+	case CLI_GENERATE:
+		return NULL;
+	}
 	
 	/* ugly, can be removed when CLI entries have ast_module pointers */
 	ast_module_ref(ast_module_info->self);
 
-	if (argc != 4 || ast_strlen_zero(argv[2]) || ast_strlen_zero(argv[3])) {
-		ret = RESULT_SHOWUSAGE;
+	if (a->argc != 4 || ast_strlen_zero(a->argv[2]) || ast_strlen_zero(a->argv[3])) {
+		ret = CLI_SHOWUSAGE;
 		goto fail_out;	
 	}
 
-	file_in = ast_strdupa(argv[2]);
-	file_out = ast_strdupa(argv[3]);
+	file_in = ast_strdupa(a->argv[2]);
+	file_out = ast_strdupa(a->argv[3]);
 
 	if (split_ext(file_in, &name_in, &ext_in)) {
-		ast_cli(fd, "'%s' is an invalid filename!\n", argv[2]);
+		ast_cli(a->fd, "'%s' is an invalid filename!\n", a->argv[2]);
 		goto fail_out;
 	}
 	if (!(fs_in = ast_readfile(name_in, ext_in, NULL, O_RDONLY, 0, 0))) {
-		ast_cli(fd, "Unable to open input file: %s\n", argv[2]);
+		ast_cli(a->fd, "Unable to open input file: %s\n", a->argv[2]);
 		goto fail_out;
 	}
 	
 	if (split_ext(file_out, &name_out, &ext_out)) {
-		ast_cli(fd, "'%s' is an invalid filename!\n", argv[3]);
+		ast_cli(a->fd, "'%s' is an invalid filename!\n", a->argv[3]);
 		goto fail_out;
 	}
 	if (!(fs_out = ast_writefile(name_out, ext_out, NULL, O_CREAT|O_TRUNC|O_WRONLY, 0, AST_FILE_MODE))) {
-		ast_cli(fd, "Unable to open output file: %s\n", argv[3]);
+		ast_cli(a->fd, "Unable to open output file: %s\n", a->argv[3]);
 		goto fail_out;
 	}
 
@@ -107,19 +122,19 @@ static int cli_audio_convert(int fd, int argc, char *argv[])
 	
 	while ((f = ast_readframe(fs_in))) {
 		if (ast_writestream(fs_out, f)) {
-			ast_cli(fd, "Failed to convert %s.%s to %s.%s!\n", name_in, ext_in, name_out, ext_out);
+			ast_cli(a->fd, "Failed to convert %s.%s to %s.%s!\n", name_in, ext_in, name_out, ext_out);
 			goto fail_out;
 		}
 	}
 
 	cost = ast_tvdiff_ms(ast_tvnow(), start);
-	ast_cli(fd, "Converted %s.%s to %s.%s in %dms\n", name_in, ext_in, name_out, ext_out, cost);
-	ret = RESULT_SUCCESS;
+	ast_cli(a->fd, "Converted %s.%s to %s.%s in %dms\n", name_in, ext_in, name_out, ext_out, cost);
+	ret = CLI_SUCCESS;
 
 fail_out:
 	if (fs_out) {
 		ast_closestream(fs_out);
-		if (ret != RESULT_SUCCESS)
+		if (ret != CLI_SUCCESS)
 			ast_filedelete(name_out, ext_out);
 	}
 
@@ -131,17 +146,8 @@ fail_out:
 	return ret;
 }
 
-static char usage_audio_convert[] =
-"Usage: file convert <file_in> <file_out>\n"
-"    Convert from file_in to file_out. If an absolute path is not given, the\n"
-"default Asterisk sounds directory will be used.\n\n"
-"Example:\n"
-"    file convert tt-weasels.gsm tt-weasels.ulaw\n";
-
 static struct ast_cli_entry cli_convert[] = {
-	{ { "file", "convert" , NULL },
-	cli_audio_convert, "Convert audio file",
-	usage_audio_convert },
+	NEW_CLI(handle_cli_file_convert, "Convert audio file")
 };
 
 static int unload_module(void)
diff --git a/res/res_crypto.c b/res/res_crypto.c
index 65c5b768dbbfada5b4925d1440c8712f6b49c01f..b0b34bd7c78f82598bcaf8b48f80a60c860449f3 100644
--- a/res/res_crypto.c
+++ b/res/res_crypto.c
@@ -499,27 +499,43 @@ static void md52sum(char *sum, unsigned char *md5)
  * \param argv list of arguements
  * \return RESULT_SUCCESS
 */
-static int show_keys(int fd, int argc, char *argv[])
+static char *handle_cli_keys_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
+#define FORMAT "%-18s %-8s %-16s %-33s\n"
+
 	struct ast_key *key;
 	char sum[16 * 2 + 1];
 	int count_keys = 0;
 
-	ast_cli(fd, "%-18s %-8s %-16s %-33s\n", "Key Name", "Type", "Status", "Sum");
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "keys show";
+		e->usage =
+			"Usage: keys show\n"
+			"       Displays information about RSA keys known by Asterisk\n";
+		return NULL;
+	case CLI_GENERATE:
+		return NULL;
+	}
+
+	ast_cli(a->fd, FORMAT, "Key Name", "Type", "Status", "Sum");
+	ast_cli(a->fd, FORMAT, "------------------", "--------", "----------------", "--------------------------------");
 
 	AST_RWLIST_RDLOCK(&keys);
 	AST_RWLIST_TRAVERSE(&keys, key, list) {
 		md52sum(sum, key->digest);
-		ast_cli(fd, "%-18s %-8s %-16s %-33s\n", key->name, 
+		ast_cli(a->fd, FORMAT, key->name, 
 			(key->ktype & 0xf) == AST_KEY_PUBLIC ? "PUBLIC" : "PRIVATE",
 			key->ktype & KEY_NEEDS_PASSCODE ? "[Needs Passcode]" : "[Loaded]", sum);
 		count_keys++;
 	}
 	AST_RWLIST_UNLOCK(&keys);
 
-	ast_cli(fd, "%d known RSA keys.\n", count_keys);
+	ast_cli(a->fd, "\n%d known RSA keys.\n", count_keys);
+
+	return CLI_SUCCESS;
 
-	return RESULT_SUCCESS;
+#undef FORMAT
 }
 
 /*! 
@@ -529,43 +545,45 @@ static int show_keys(int fd, int argc, char *argv[])
  * \param argv list of arguements
  * \return RESULT_SUCCESS
 */
-static int init_keys(int fd, int argc, char *argv[])
+static char *handle_cli_keys_init(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
 	struct ast_key *key;
 	int ign;
 	char *kn, tmp[256] = "";
 
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "keys init";
+		e->usage =
+			"Usage: keys init\n"
+			"       Initializes private keys (by reading in pass code from\n"
+			"       the user)\n";
+		return NULL;
+	case CLI_GENERATE:
+		return NULL;
+	}
+
+	if (a->argc != 2)
+		return CLI_SHOWUSAGE;
+
 	AST_RWLIST_WRLOCK(&keys);
 	AST_RWLIST_TRAVERSE_SAFE_BEGIN(&keys, key, list) {
 		/* Reload keys that need pass codes now */
 		if (key->ktype & KEY_NEEDS_PASSCODE) {
 			kn = key->fn + strlen(ast_config_AST_KEY_DIR) + 1;
 			ast_copy_string(tmp, kn, sizeof(tmp));
-			try_load_key((char *)ast_config_AST_KEY_DIR, tmp, fd, fd, &ign);
+			try_load_key((char *) ast_config_AST_KEY_DIR, tmp, a->fd, a->fd, &ign);
 		}
 	}
 	AST_RWLIST_TRAVERSE_SAFE_END
 	AST_RWLIST_UNLOCK(&keys);
 
-	return RESULT_SUCCESS;
+	return CLI_SUCCESS;
 }
 
-static const char show_key_usage[] =
-"Usage: keys show\n"
-"       Displays information about RSA keys known by Asterisk\n";
-
-static const char init_keys_usage[] =
-"Usage: keys init\n"
-"       Initializes private keys (by reading in pass code from the user)\n";
-
 static struct ast_cli_entry cli_crypto[] = {
-	{ { "keys", "show", NULL },
-	show_keys, "Displays RSA key information",
-	show_key_usage },
-
-	{ { "keys", "init", NULL },
-	init_keys, "Initialize RSA key passcodes",
-	init_keys_usage },
+	NEW_CLI(handle_cli_keys_show, "Displays RSA key information"),
+	NEW_CLI(handle_cli_keys_init, "Initialize RSA key passcodes")
 };
 
 /*! \brief initialise the res_crypto module */
diff --git a/res/res_limit.c b/res/res_limit.c
index ca22118363c416edde22581f6692482ab1824939..fcaf03b8620aab5d2a1c9815dd7d7293a59577a1 100644
--- a/res/res_limit.c
+++ b/res/res_limit.c
@@ -49,21 +49,21 @@ static struct limits {
 	char limit[3];
 	char desc[40];
 } limits[] = {
-	{ RLIMIT_CPU, "-t", "cpu time" },
-	{ RLIMIT_FSIZE, "-f", "file size" },
-	{ RLIMIT_DATA, "-d", "program data segment" },
-	{ RLIMIT_STACK, "-s", "program stack size" },
-	{ RLIMIT_CORE, "-c", "core file size" },
+	{ RLIMIT_CPU,     "-t", "cpu time" },
+	{ RLIMIT_FSIZE,   "-f", "file size" },
+	{ RLIMIT_DATA,    "-d", "program data segment" },
+	{ RLIMIT_STACK,   "-s", "program stack size" },
+	{ RLIMIT_CORE,    "-c", "core file size" },
 #ifdef RLIMIT_RSS
-	{ RLIMIT_RSS, "-m", "resident memory" },
+	{ RLIMIT_RSS,     "-m", "resident memory" },
 	{ RLIMIT_MEMLOCK, "-l", "amount of memory locked into RAM" },
 #endif
 #ifdef RLIMIT_NPROC
-	{ RLIMIT_NPROC, "-u", "number of processes" },
+	{ RLIMIT_NPROC,   "-u", "number of processes" },
 #endif
-	{ RLIMIT_NOFILE, "-n", "number of file descriptors" },
+	{ RLIMIT_NOFILE,  "-n", "number of file descriptors" },
 #ifdef VMEM_DEF
-	{ VMEM_DEF, "-v", "virtual memory" },
+	{ VMEM_DEF,       "-v", "virtual memory" },
 #endif
 };
 
@@ -87,43 +87,105 @@ static const char *str2desc(const char *string)
 	return "<unknown>";
 }
 
-static int my_ulimit(int fd, int argc, char **argv)
+static char *complete_ulimit(struct ast_cli_args *a)
+{
+	int which = 0, i;
+	int wordlen = strlen(a->word);
+
+	if (a->pos > 1)
+		return NULL;
+	for (i = 0; i < sizeof(limits) / sizeof(limits[0]); i++) {
+		if (!strncasecmp(limits[i].limit, a->word, wordlen)) {
+			if (++which > a->n)
+				return ast_strdup(limits[i].limit);
+		}
+	}
+	return NULL;
+}
+
+static char *handle_cli_ulimit(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
 	int resource;
 	struct rlimit rlimit = { 0, 0 };
-	if (argc > 3)
-		return RESULT_SHOWUSAGE;
 
-	if (argc == 1) {
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "ulimit";
+		e->usage =
+			"Usage: ulimit {-d|"
+#ifdef RLIMIT_RSS
+			"-l|"
+#endif
+			"-f|"
+#ifdef RLIMIT_RSS
+			"-m|"
+#endif
+			"-s|-t|"
+#ifdef RLIMIT_NPROC
+			"-u|"
+#endif
+#ifdef VMEM_DEF
+			"-v|"
+#endif
+			"-c|-n} [<num>]\n"
+			"       Shows or sets the corresponding resource limit.\n"
+			"         -d  Process data segment [readonly]\n"
+#ifdef RLIMIT_RSS
+			"         -l  Memory lock size [readonly]\n"
+#endif
+			"         -f  File size\n"
+#ifdef RLIMIT_RSS
+			"         -m  Process resident memory [readonly]\n"
+#endif
+			"         -s  Process stack size [readonly]\n"
+			"         -t  CPU usage [readonly]\n"
+#ifdef RLIMIT_NPROC
+			"         -u  Child processes\n"
+#endif
+#ifdef VMEM_DEF
+			"         -v  Process virtual memory [readonly]\n"
+#endif
+			"         -c  Core dump file size\n"
+			"         -n  Number of file descriptors\n";
+		return NULL;
+	case CLI_GENERATE:
+		return complete_ulimit(a);
+	}
+
+	if (a->argc > 3)
+		return CLI_SHOWUSAGE;
+
+	if (a->argc == 1) {
 		char arg2[3];
 		char *newargv[2] = { "ulimit", arg2 };
 		for (resource = 0; resource < sizeof(limits) / sizeof(limits[0]); resource++) {
+			struct ast_cli_args newArgs = { .argv = newargv, .argc = 2 };
 			ast_copy_string(arg2, limits[resource].limit, sizeof(arg2));
-			my_ulimit(fd, 2, newargv);
+			handle_cli_ulimit(e, CLI_HANDLER, &newArgs);
 		}
-		return RESULT_SUCCESS;
+		return CLI_SUCCESS;
 	} else {
-		resource = str2limit(argv[1]);
+		resource = str2limit(a->argv[1]);
 		if (resource == -1) {
-			ast_cli(fd, "Unknown resource\n");
-			return RESULT_FAILURE;
+			ast_cli(a->fd, "Unknown resource\n");
+			return CLI_FAILURE;
 		}
 
-		if (argc == 3) {
+		if (a->argc == 3) {
 			int x;
 #ifdef RLIMIT_NPROC
 			if (resource != RLIMIT_NOFILE && resource != RLIMIT_CORE && resource != RLIMIT_NPROC && resource != RLIMIT_FSIZE) {
 #else
-			  if (resource != RLIMIT_NOFILE && resource != RLIMIT_CORE && resource != RLIMIT_FSIZE) {
+			if (resource != RLIMIT_NOFILE && resource != RLIMIT_CORE && resource != RLIMIT_FSIZE) {
 #endif
-				ast_cli(fd, "Resource not permitted to be set\n");
-				return RESULT_FAILURE;
+				ast_cli(a->fd, "Resource not permitted to be set\n");
+				return CLI_FAILURE;
 			}
 
-			sscanf(argv[2], "%d", &x);
+			sscanf(a->argv[2], "%d", &x);
 			rlimit.rlim_max = rlimit.rlim_cur = x;
 			setrlimit(resource, &rlimit);
-			return RESULT_SUCCESS;
+			return CLI_SUCCESS;
 		} else {
 			if (!getrlimit(resource, &rlimit)) {
 				char printlimit[32];
@@ -131,51 +193,18 @@ static int my_ulimit(int fd, int argc, char **argv)
 				if (rlimit.rlim_max == RLIM_INFINITY)
 					ast_copy_string(printlimit, "effectively unlimited", sizeof(printlimit));
 				else
-					snprintf(printlimit, sizeof(printlimit), "limited to %d", (int)rlimit.rlim_cur);
-				desc = str2desc(argv[1]);
-				ast_cli(fd, "%c%s (%s) is %s.\n", toupper(desc[0]), desc + 1, argv[1], printlimit);
+					snprintf(printlimit, sizeof(printlimit), "limited to %d", (int) rlimit.rlim_cur);
+				desc = str2desc(a->argv[1]);
+				ast_cli(a->fd, "%c%s (%s) is %s.\n", toupper(desc[0]), desc + 1, a->argv[1], printlimit);
 			} else
-				ast_cli(fd, "Could not retrieve resource limits for %s: %s\n", str2desc(argv[1]), strerror(errno));
-			return RESULT_SUCCESS;
-		}
-	}
-}
-
-static char *complete_ulimit(const char *line, const char *word, int pos, int state)
-{
-	int which = 0, i;
-	int wordlen = strlen(word);
-
-	if (pos > 2)
-		return NULL;
-	for (i = 0; i < sizeof(limits) / sizeof(limits[0]); i++) {
-		if (!strncasecmp(limits[i].limit, word, wordlen)) {
-			if (++which > state)
-				return ast_strdup(limits[i].limit);
+				ast_cli(a->fd, "Could not retrieve resource limits for %s: %s\n", str2desc(a->argv[1]), strerror(errno));
+			return CLI_SUCCESS;
 		}
 	}
-	return NULL;
 }
 
-static const char ulimit_usage[] =
-"Usage: ulimit {-d|-l|-f|-m|-s|-t|-u|-v|-c|-n} [<num>]\n"
-"       Shows or sets the corresponding resource limit.\n"
-"         -d  Process data segment [readonly]\n"
-"         -l  Memory lock size [readonly]\n"
-"         -f  File size\n"
-"         -m  Process resident memory [readonly]\n"
-"         -s  Process stack size [readonly]\n"
-"         -t  CPU usage [readonly]\n"
-"         -u  Child processes\n"
-#ifdef VMEM_DEF
-"         -v  Process virtual memory [readonly]\n"
-#endif
-"         -c  Core dump file size\n"
-"         -n  Number of file descriptors\n";
-
-static struct ast_cli_entry cli_ulimit = {
-	{ "ulimit", NULL }, my_ulimit,
-	"Set or show process resource limits", ulimit_usage, complete_ulimit };
+static struct ast_cli_entry cli_ulimit =
+	NEW_CLI(handle_cli_ulimit, "Set or show process resource limits");
 
 static int unload_module(void)
 {
@@ -184,7 +213,7 @@ static int unload_module(void)
 
 static int load_module(void)
 {
-	return ast_cli_register(&cli_ulimit)? AST_MODULE_LOAD_FAILURE: AST_MODULE_LOAD_SUCCESS;
+	return ast_cli_register(&cli_ulimit) ? AST_MODULE_LOAD_FAILURE : AST_MODULE_LOAD_SUCCESS;
 }
 
 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Resource limits");