[asterisk-commits] rizzo: branch rizzo/astobj2 r47653 - in /team/rizzo/astobj2: include/asterisk...

asterisk-commits at lists.digium.com asterisk-commits at lists.digium.com
Wed Nov 15 07:12:53 MST 2006


Author: rizzo
Date: Wed Nov 15 08:12:52 2006
New Revision: 47653

URL: http://svn.digium.com/view/asterisk?view=rev&rev=47653
Log:
update the internal cli interface to the one in trunk.


Modified:
    team/rizzo/astobj2/include/asterisk/cli.h
    team/rizzo/astobj2/main/astobj2.c
    team/rizzo/astobj2/main/cli.c

Modified: team/rizzo/astobj2/include/asterisk/cli.h
URL: http://svn.digium.com/view/asterisk/team/rizzo/astobj2/include/asterisk/cli.h?view=diff&rev=47653&r1=47652&r2=47653
==============================================================================
--- team/rizzo/astobj2/include/asterisk/cli.h (original)
+++ team/rizzo/astobj2/include/asterisk/cli.h Wed Nov 15 08:12:52 2006
@@ -38,15 +38,21 @@
 #define RESULT_SHOWUSAGE	1
 #define RESULT_FAILURE		2
 
+#define CLI_SUCCESS	(char *)RESULT_SUCCESS
+#define CLI_SHOWUSAGE	(char *)RESULT_SHOWUSAGE
+#define CLI_FAILURE	(char *)RESULT_FAILURE
+
 #define AST_MAX_CMD_LEN 	16
 
 #define AST_MAX_ARGS 64
 
 #define AST_CLI_COMPLETE_EOF	"_EOF_"
 
-/*!
+/*! \page CLI_command_api CLI command API
+
    CLI commands are described by a struct ast_cli_entry that contains
    all the components for their implementation.
+
    In the "old-style" format, the record must contain:
    - a NULL-terminated array of words constituting the command, e.g.
 	{ "set", "debug", "on", NULL },
@@ -65,85 +71,82 @@
 
    In the "new-style" format, all the above functionalities are implemented
    by a single function, and the arguments tell which output is required.
-
-   NOTE: ideally, the new-style handler would have a different prototype,
-   i.e. something like
-	int new_setdebug(const struct ast_cli *e, int function,
-	    int fd, int argc, char *argv[],	// handler args
-	    int n, int pos, const char *line, const char *word // -complete args)
-   but at this moment we want to help the transition from old-style to new-style
-   functions so we keep the same interface and override some of the traditional
-   arguments.
-
-   To help the transition, a new-style entry has the same interface as the old one,
-   but it is declared as follows:
-
-	int new_setdebug(int fd, int argc, char *argv[]);
+   The prototype is the following:
+
+	char *new_setdebug(const struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
 
 	...
-	// this is how we create the entry to register
+	// this is how we create the entry to register 
 	NEW_CLI(new_setdebug, "short description")
 	...
 
-   Called with the default arguments (argc > 0), the new_handler implements
-   the command as before.
-   A negative argc indicates one of the other functions, namely
-   generate the usage string, the full command, or implement the generator.
-   As a trick to extend the interface while being backward compatible,
-   argv[-1] points to a struct ast_cli_args, and, for the generator,
-   argv[0] is really a pointer to a struct ast_cli_args.
-   The return string is obtained by casting the result to char *
+   To help the transition, we make the pointer to the struct ast_cli_entry
+   available to old-style handlers via argv[-1].
 
    An example of new-style handler is the following
 
 \code
-static int test_new_cli(int fd, int argc, char *argv[])
+static char *test_new_cli(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
-        struct ast_cli_entry *e = (struct ast_cli_entry *)argv[-1];
-        struct ast_cli_args *a;
 	static char *choices = { "one", "two", "three", NULL };
 
-        switch(argc) {
-        case CLI_USAGE:
-                return (int)
+        switch (cmd) {
+        case CLI_INIT:
+		e->command = "do this well";
+                e->usage =
 			"Usage: do this well <arg>\n"
 			"	typically multiline with body indented\n";
-
-        case CLI_CMD_STRING:
-                return (int)"do this well";
+		return NULL;
 
         case CLI_GENERATE:
-                a = (struct ast_cli_args *)argv[0];
                 if (a->pos > e->args)
                         return NULL;
         	return ast_cli_complete(a->word, choices, a->n);
 
         default:        
                 // we are guaranteed to be called with argc >= e->args;
-                if (argc > e->args + 1) // we accept one extra argument
-                        return RESULT_SHOWUSAGE;
-                ast_cli(fd, "done this well for %s\n", e->args[argc-1]);
-                return RESULT_SUCCESS;
+                if (a->argc > e->args + 1) // we accept one extra argument
+                        return CLI_SHOWUSAGE;
+                ast_cli(a->fd, "done this well for %s\n", e->args[argc-1]);
+                return CLI_SUCCESS;
         }
 }
 
 \endcode
- *
- */
-
-/*! \brief calling arguments for new-style handlers */
+ 
+ */
+
+/*! \brief calling arguments for new-style handlers 
+	See \ref CLI_command_API
+*/
 enum ast_cli_fn {
-	CLI_USAGE = -1,		/* return the usage string */
-	CLI_CMD_STRING = -2,	/* return the command string */
+	CLI_INIT = -2,		/* return the usage string */
 	CLI_GENERATE = -3,	/* behave as 'generator', remap argv to struct ast_cli_args */
+	CLI_HANDLER = -4,	/* run the normal handler */
 };
 
+/* argument for new-style CLI handler */
+struct ast_cli_args {
+	int fd;
+	int argc;
+	char **argv;
+	const char *line;	/* the current input line */
+	const char *word;	/* the word we want to complete */
+	int pos;		/* position of the word to complete */
+	int n;			/* the iteration count (n-th entry we generate) */
+};
+
+struct ast_cli_entry;
 typedef int (*old_cli_fn)(int fd, int argc, char *argv[]);
-
-/*! \brief descriptor for a cli entry */
+typedef char *(*new_cli_fn)(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
+
+/*! \brief descriptor for a cli entry 
+	See \ref CLI_command_API
+ */
 struct ast_cli_entry {
 	char * const cmda[AST_MAX_CMD_LEN];	/*!< words making up the command.
 		* set the first entry to NULL for a new-style entry. */
+
 	/*! Handler for the command (fd for output, # of args, argument list).
 	  Returns RESULT_SHOWUSAGE for improper arguments.
 	  argv[] has argc 'useful' entries, and an additional NULL entry
@@ -152,9 +155,11 @@
 	  You can overwrite argv or the strings it points to, but remember
 	  that this memory is deallocated after the handler returns.
 	 */
-	int (*handler)(int fd, int argc, char *argv[]);
+	old_cli_fn handler;
+
 	const char *summary; /*!< Summary of the command (< 60 characters) */
-	const char *usage; /*!< Detailed usage information */
+	char *usage; /*!< Detailed usage information */
+
 	/*! Generate the n-th (starting from 0) possible completion
 	  for a given 'word' following 'line' in position 'pos'.
 	  'line' and 'word' must not be modified.
@@ -165,31 +170,25 @@
 	 */
 	char *(*generator)(const char *line, const char *word, int pos, int n);
 	struct ast_cli_entry *deprecate_cmd;
+
 	int inuse; /*!< For keeping track of usage */
 	struct module *module;	/*!< module this belongs to */
-	char *_full_cmd;	/* built at load time from cmda[] */
-	/* This gets set in ast_cli_register()
+	char *_full_cmd;	/*!< built at load time from cmda[] */
+
+	/*! \brief This gets set in ast_cli_register()
 	  It then gets set to something different when the deprecated command
 	  is run for the first time (ie; after we warn the user that it's deprecated)
 	 */
 	int args;		/*!< number of non-null entries in cmda */
 	char *command;		/*!< command, non-null for new-style entries */
 	int deprecated;
-	char *_deprecated_by;	/* copied from the "parent" _full_cmd, on deprecated commands */
+	new_cli_fn new_handler;
+	char *_deprecated_by;	/*!< copied from the "parent" _full_cmd, on deprecated commands */
 	/*! For linking */
 	AST_LIST_ENTRY(ast_cli_entry) list;
 };
 
-#define NEW_CLI(fn, txt)	{ .handler = (old_cli_fn)fn, .summary = txt }
-
-/* argument for new-style CLI handler */
-struct ast_cli_args {
-	char fake[4];		/* a fake string, in the first position, for safety */
-	const char *line;	/* the current input line */
-	const char *word;	/* the word we want to complete */
-	int pos;		/* position of the word to complete */
-	int n;			/* the iteration count (n-th entry we generate) */
-};
+#define NEW_CLI(fn, txt)	{ .new_handler = fn, .summary = txt }
 
 /*!
  * Helper function to generate cli entries from a NULL-terminated array.

Modified: team/rizzo/astobj2/main/astobj2.c
URL: http://svn.digium.com/view/asterisk/team/rizzo/astobj2/main/astobj2.c?view=diff&rev=47653&r1=47652&r2=47653
==============================================================================
--- team/rizzo/astobj2/main/astobj2.c (original)
+++ team/rizzo/astobj2/main/astobj2.c Wed Nov 15 08:12:52 2006
@@ -666,35 +666,30 @@
 }
 
 #if 1
-static int test_new_cli(int fd, int argc, char *argv[])
-{
-	struct ast_cli_entry *e = (struct ast_cli_entry *)argv[-1];
-	struct ast_cli_args *a;
-
-	switch(argc) {
-	case CLI_USAGE:
-		return (int)"this is the usage string for astobj2 foo bar <n>\n";
-
-	case CLI_CMD_STRING:
-		return (int)"astobj2 foo bar";
+static char *test_new_cli(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+{
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "astobj2 foo bar";
+		e->usage = "this is the usage string for astobj2 foo bar <n>\n";
+		return NULL;
 
 	case CLI_GENERATE:
-		a = (struct ast_cli_args *)argv[0];
 		if (a->pos > e->args)	/* only extend one word */
-			return (int)NULL;
+			return NULL;
 		if (a->n < 10) {
 			char *buf;
 			asprintf(&buf, "%d", a->n);
-			return (int)buf;
+			return buf;
 		}
-		return (int)NULL;
+		return NULL;
 
 	default:	/* regular handler */
 		/* we are guaranteed to be called with argc >= e->args; */
-		if (argc > e->args + 1)	/* we only accept one extra field */
-			return RESULT_SHOWUSAGE;
-	        ast_cli(fd, "this is test_new_cli %d for [%d] %s\n", argc, e->args, e->_full_cmd);
-		return RESULT_SUCCESS;
+		if (a->argc > e->args + 1)	/* we only accept one extra field */
+			return CLI_SHOWUSAGE;
+	        ast_cli(a->fd, "this is test_new_cli %d for [%d] %s\n", a->argc, e->args, e->_full_cmd);
+		return CLI_SUCCESS;
 	}
 }
 #endif

Modified: team/rizzo/astobj2/main/cli.c
URL: http://svn.digium.com/view/asterisk/team/rizzo/astobj2/main/cli.c?view=diff&rev=47653&r1=47652&r2=47653
==============================================================================
--- team/rizzo/astobj2/main/cli.c (original)
+++ team/rizzo/astobj2/main/cli.c Wed Nov 15 08:12:52 2006
@@ -76,11 +76,11 @@
 static AST_LIST_HEAD_STATIC(helpers, ast_cli_entry);
 
 static char load_help[] = 
-"Usage: load <module name>\n"
+"Usage: module load <module name>\n"
 "       Loads the specified module into Asterisk.\n";
 
 static char unload_help[] = 
-"Usage: unload [-f|-h] <module name>\n"
+"Usage: module unload [-f|-h] <module name>\n"
 "       Unloads the specified module from Asterisk. The -f\n"
 "       option causes the module to be unloaded even if it is\n"
 "       in use (may cause a crash) and the -h module causes the\n"
@@ -101,19 +101,9 @@
 "       more and longer fields.\n";
 
 static char reload_help[] = 
-"Usage: reload [module ...]\n"
+"Usage: module reload [module ...]\n"
 "       Reloads configuration files for all listed modules which support\n"
 "       reloading, or for all supported modules if none are listed.\n";
-
-static char verbose_help[] = 
-"Usage: core set verbose <level>\n"
-"       Sets level of verbose messages to be displayed.  0 means\n"
-"       no messages should be displayed. Equivalent to -v[v[v...]]\n"
-"       on startup\n";
-
-static char nodebug_help[] = 
-"Usage: core set no debug\n"
-"       Turns off core debug messages.\n";
 
 static char logger_mute_help[] = 
 "Usage: logger mute\n"
@@ -133,24 +123,33 @@
 
 static int handle_load(int fd, int argc, char *argv[])
 {
-	if (argc != 2)
+	/* "module load <mod>" */
+	if (argc != 3)
 		return RESULT_SHOWUSAGE;
-	if (ast_load_resource(argv[1])) {
-		ast_cli(fd, "Unable to load module %s\n", argv[1]);
+	if (ast_load_resource(argv[2])) {
+		ast_cli(fd, "Unable to load module %s\n", argv[2]);
 		return RESULT_FAILURE;
 	}
 	return RESULT_SUCCESS;
 }
 
+static int handle_load_deprecated(int fd, int argc, char *argv[])
+{
+	/* I know it is nasty, but they do look very similar, and we never access argv[0] */
+	return handle_load(fd, argc+1, argv - 1);
+}
+
 static int handle_reload(int fd, int argc, char *argv[])
 {
-	int x;
-	int res;
-	if (argc < 1)
-		return RESULT_SHOWUSAGE;
-	if (argc > 1) { 
-		for (x=1;x<argc;x++) {
-			res = ast_module_reload(argv[x]);
+	/* "module reload [mod_1 ... mod_N]" */
+	struct ast_cli_entry *e = (struct ast_cli_entry *)argv[-1];
+
+	if (argc == e->args)
+		ast_module_reload(NULL);
+	else {
+		int x;
+		for (x = e->args; x < argc; x++) {
+			int res = ast_module_reload(argv[x]);
 			switch(res) {
 			case 0:
 				ast_cli(fd, "No such module '%s'\n", argv[x]);
@@ -160,36 +159,62 @@
 				break;
 			}
 		}
-	} else
-		ast_module_reload(NULL);
+	}
 	return RESULT_SUCCESS;
 }
 
-static int handle_verbose(int fd, int argc, char *argv[])
+static int handle_reload_deprecated(int fd, int argc, char *argv[])
+{
+	return handle_reload(fd, argc+1, argv-1);	/* see comment in handle_load_deprecated() */
+}
+
+static char *handle_verbose(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
 	int oldval = option_verbose;
 	int newlevel;
 	int atleast = 0;
-
-	if ((argc < 4) || (argc > 5))
-		return RESULT_SHOWUSAGE;
-
-	if (!strcasecmp(argv[3], "atleast"))
+	static char *choices[] = { "off", "atleast", NULL };
+	int fd = a->fd;
+	int argc = a->argc;
+	char **argv = a->argv;
+
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "core set verbose";
+		e->usage =
+			"Usage: core set verbose [atleast] <level>\n"
+			"       core set verbose off\n"
+			"       Sets level of verbose messages to be displayed.  0 or off means\n"
+			"       no messages should be displayed. Equivalent to -v[v[v...]]\n"
+			"       on startup\n";
+		return NULL;
+
+	case CLI_GENERATE:
+		if (a->pos > e->args)
+			return NULL;
+		return ast_cli_complete(a->word, choices, a->n);
+	}
+	/* all the above return, so we proceed with the handler.
+	 * we are guaranteed to be called with argc >= e->args;
+	 */
+
+	if (argc < e->args + 1)
+		return CLI_SHOWUSAGE;
+
+	if (argc == e->args + 1 && !strcasecmp(argv[e->args], "off")) {
+		newlevel = 0;
+		goto done;
+	}
+	if (!strcasecmp(argv[e->args], "atleast"))
 		atleast = 1;
-
-	if (!atleast) {
-		if (argc > 4)
-			return RESULT_SHOWUSAGE;
-
-		option_verbose = atoi(argv[3]);
-	} else {
-		if (argc < 5)
-			return RESULT_SHOWUSAGE;
-
-		newlevel = atoi(argv[4]);
-		if (newlevel > option_verbose)
-			option_verbose = newlevel;
-        }
+	if (argc != e->args + atleast + 1)
+		return CLI_SHOWUSAGE;
+	if (sscanf(argv[e->args + atleast], "%d", &newlevel) != 1)
+		return CLI_SHOWUSAGE;
+
+done:
+	if (!atleast || newlevel > option_verbose)
+		option_verbose = newlevel;
 	if (oldval > 0 && option_verbose == 0)
 		ast_cli(fd, "Verbosity is now OFF\n");
 	else if (option_verbose > 0) {
@@ -199,88 +224,82 @@
 			ast_cli(fd, "Verbosity was %d and is now %d\n", oldval, option_verbose);
 	}
 
-	return RESULT_SUCCESS;
-}
-
-static int handle_debug(int fd, int argc, char *argv[])
-{
-	struct ast_cli_entry *e = (struct ast_cli_entry *)argv[-1];
+	return CLI_SUCCESS;
+}
+
+static char *handle_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+{
 	int oldval = option_debug;
 	int newlevel;
 	int atleast = 0;
 	char *filename = '\0';
-
-	switch(argc) {
-	case CLI_CMD_STRING:
-		return (int)"core set debug";
-
-	case CLI_USAGE:
-		return (int)
+	static char *choices[] = { "off", "atleast", NULL };
+	int fd = a->fd;
+	int argc = a->argc;
+	char **argv = a->argv;
+
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "core set debug";
+		e->usage =
 			"Usage: core set debug [atleast] <level> [filename]\n"
-			"       Sets level of core debug messages to be displayed.  0 means\n"
+			"       core set debug off\n"
+			"       Sets level of core debug messages to be displayed. 0 or 'off' means\n"
 			"       no messages should be displayed.  Equivalent to -d[d[d...]]\n"
 			"       on startup.  If filename is specified, debugging will be\n"
 			"       limited to just that file.\n";
+		return NULL;
 
 	case CLI_GENERATE:
-		/* at the moment don't do anything, though could well explode the
-		 * list of available filenames
-		 */
-		return (int)NULL;
-
-	default: /* we are guaranteed to be called with argc >= e->args; */
-
-		if (argc < e->args + 1)
-			return RESULT_SHOWUSAGE;
-
-		if (!strcasecmp(argv[e->args], "atleast"))
-			atleast = 1;
-		if (argc > e->args + atleast + 2)
-			return RESULT_SHOWUSAGE;
-		if (sscanf(argv[e->args + atleast], "%d", &newlevel) != 1)
-			return RESULT_SHOWUSAGE;
-
-		if (argc == e->args + atleast + 1) {
-			debug_filename[0] = '\0';
+		if (a->pos > e->args)
+			return NULL;
+		return ast_cli_complete(a->word, choices, a->n);
+	}
+	/* all the above return, so we proceed with the handler.
+	 * we are guaranteed to be called with argc >= e->args;
+	 */
+
+	if (argc < e->args + 1)
+		return CLI_SHOWUSAGE;
+
+	if (argc == e->args + 1 && !strcasecmp(argv[e->args], "off")) {
+		newlevel = 0;
+		goto done;
+	}
+	if (!strcasecmp(argv[e->args], "atleast"))
+		atleast = 1;
+	if (argc < e->args + atleast + 1 || argc > e->args + atleast + 2)
+		return CLI_SHOWUSAGE;
+	if (sscanf(argv[e->args + atleast], "%d", &newlevel) != 1)
+		return CLI_SHOWUSAGE;
+
+	if (argc == e->args + atleast + 1) {
+		debug_filename[0] = '\0';
+	} else {
+		ast_copy_string(debug_filename, argv[e->args + atleast + 1], sizeof(debug_filename));
+	}
+
+done:
+	if (!atleast || newlevel > option_debug)
+		option_debug = newlevel;
+
+	if (oldval > 0 && option_debug == 0)
+		ast_cli(fd, "Core debug is now OFF\n");
+	else if (option_debug > 0) {
+		if (filename) {
+			if (oldval == option_debug)
+				ast_cli(fd, "Core debug is at least %d, file '%s'\n", option_debug, filename);
+			else
+				ast_cli(fd, "Core debug was %d and is now %d, file '%s'\n", oldval, option_debug, filename);
 		} else {
-			ast_copy_string(debug_filename, argv[e->args + atleast + 1], sizeof(debug_filename));
-		}
-
-		if (!atleast || newlevel > option_debug)
-			option_debug = newlevel;
-
-		if (oldval > 0 && option_debug == 0)
-			ast_cli(fd, "Core debug is now OFF\n");
-		else if (option_debug > 0) {
-			if (filename) {
-				if (oldval == option_debug)
-					ast_cli(fd, "Core debug is at least %d, file '%s'\n", option_debug, filename);
-				else
-					ast_cli(fd, "Core debug was %d and is now %d, file '%s'\n", oldval, option_debug, filename);
-			} else {
-				if (oldval == option_debug)
-					ast_cli(fd, "Core debug is at least %d\n", option_debug);
-				else
-					ast_cli(fd, "Core debug was %d and is now %d\n", oldval, option_debug);
-			}
-		}
-
-		return RESULT_SUCCESS;
-	}
-}
-
-static int handle_nodebug(int fd, int argc, char *argv[])
-{
-	int oldval = option_debug;
-	if (argc != 2)
-		return RESULT_SHOWUSAGE;
-
-	option_debug = 0;
-	debug_filename[0] = '\0';
-
-	if (oldval > 0)
-		ast_cli(fd, "Core debug is now OFF\n");
-	return RESULT_SUCCESS;
+			if (oldval == option_debug)
+				ast_cli(fd, "Core debug is at least %d\n", option_debug);
+			else
+				ast_cli(fd, "Core debug was %d and is now %d\n", oldval, option_debug);
+		}
+	}
+
+	return CLI_SUCCESS;
 }
 
 static int handle_logger_mute(int fd, int argc, char *argv[])
@@ -293,11 +312,12 @@
 
 static int handle_unload(int fd, int argc, char *argv[])
 {
+	/* "module unload mod_1 [mod_2 .. mod_N]" */
 	int x;
-	int force=AST_FORCE_SOFT;
-	if (argc < 2)
+	int force = AST_FORCE_SOFT;
+	if (argc < 3)
 		return RESULT_SHOWUSAGE;
-	for (x=1;x<argc;x++) {
+	for (x = 2; x < argc; x++) {
 		if (argv[x][0] == '-') {
 			switch(argv[x][1]) {
 			case 'f':
@@ -309,7 +329,7 @@
 			default:
 				return RESULT_SHOWUSAGE;
 			}
-		} else if (x !=  argc - 1) 
+		} else if (x != argc - 1) 
 			return RESULT_SHOWUSAGE;
 		else if (ast_unload_resource(argv[x], force)) {
 			ast_cli(fd, "Unable to unload resource %s\n", argv[x]);
@@ -317,6 +337,11 @@
 		}
 	}
 	return RESULT_SUCCESS;
+}
+
+static int handle_unload_deprecated(int fd, int argc, char *argv[])
+{
+	return handle_unload(fd, argc+1, argv - 1); /* see commment in handle_load_deprecated() */
 }
 
 #define MODLIST_FORMAT  "%-30s %-40.40s %-10d\n"
@@ -334,11 +359,6 @@
 	} 
 	return 0;
 }
-
-static char uptime_help[] =
-"Usage: core show uptime [seconds]\n"
-"       Shows Asterisk uptime information.\n"
-"       The seconds word returns the uptime in seconds only.\n";
 
 static void print_uptimestr(int fd, time_t timeval, const char *prefix, int printsec)
 {
@@ -392,62 +412,75 @@
 		ast_cli(fd, "%s: %s\n", prefix, timestr);
 }
 
-static int handle_showuptime(int fd, int argc, char *argv[])
-{
-	/* 'show uptime [seconds]' */
-	time_t curtime = time(NULL);
-	int printsec = (argc == 3 && !strcasecmp(argv[2],"seconds"));
-
-	if (argc != 2 && !printsec)
-		return RESULT_SHOWUSAGE;
+static char * handle_showuptime(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+{
+	time_t curtime;
+	int printsec;
+
+	switch (cmd) {
+        case CLI_INIT:
+		e->command = "core show uptime";
+		e->usage =
+			"Usage: core show uptime [seconds]\n"
+			"       Shows Asterisk uptime information.\n"
+			"       The seconds word returns the uptime in seconds only.\n";
+		return NULL;
+
+	case CLI_GENERATE:
+		return (a->pos > e->args || a->n > 0) ? NULL : "seconds";
+	}
+	/* regular handler */
+	if (a->argc == e->args+1 && !strcasecmp(a->argv[e->args],"seconds"))
+		printsec = 1;
+	else if (a->argc == e->args)
+		printsec = 0;
+	else
+		return CLI_SHOWUSAGE;
+	curtime = time(NULL);
 	if (ast_startuptime)
-		print_uptimestr(fd, curtime - ast_startuptime, "System uptime", printsec);
+		print_uptimestr(a->fd, curtime - ast_startuptime, "System uptime", printsec);
 	if (ast_lastreloadtime)
-		print_uptimestr(fd, curtime - ast_lastreloadtime, "Last reload", printsec);
+		print_uptimestr(a->fd, curtime - ast_lastreloadtime, "Last reload", printsec);
+	return CLI_SUCCESS;
+}
+
+static char *handle_modlist(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+{
+	char *like;
+
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "module show";
+		e->usage =
+			"Usage: module show [like keyword]\n"
+			"       Shows Asterisk modules currently in use, and usage statistics.\n";
+		return NULL;
+
+	case CLI_GENERATE:
+		if (a->pos == e->args)
+			return a->n == 0 ? strdup("like") : NULL;
+		else if (a->pos == e->args+1 && strcasestr(a->line," like "))
+			return ast_module_helper(a->line, a->word, a->pos, a->n, a->pos, 0);
+		else
+			return NULL;
+	}
+	/* all the above return, so we proceed with the handler.
+	 * we are guaranteed to have argc >= e->args
+	 */
+	if (a->argc == e->args)
+		like = "";
+	else if (a->argc == e->args + 2 && !strcmp(a->argv[e->args],"like"))
+		like = a->argv[e->args + 1];
+	else
+		return CLI_SHOWUSAGE;
+		
+	ast_mutex_lock(&climodentrylock);
+	climodentryfd = a->fd; /* global, protected by climodentrylock */
+	ast_cli(a->fd, MODLIST_FORMAT2, "Module", "Description", "Use Count");
+	ast_cli(a->fd,"%d modules loaded\n", ast_update_module_list(modlist_modentry, like));
+	climodentryfd = -1;
+	ast_mutex_unlock(&climodentrylock);
 	return RESULT_SUCCESS;
-}
-
-/* core show modules [like keyword] */
-static int handle_modlist(int fd, int argc, char *argv[])
-{
-	struct ast_cli_entry *e = (struct ast_cli_entry *)argv[-1];
-	char *like;
-	struct ast_cli_args *a;
-
-	switch(argc) {
-	case CLI_CMD_STRING:
-		return (int)"core show modules";
-
-	case CLI_USAGE:
-		return (int)
-			"Usage: core show modules [like keyword]\n"
-			"       Shows Asterisk modules currently in use, and usage statistics.\n";
-
-	case CLI_GENERATE:
-		a = (struct ast_cli_args *)argv[0];
-		if (a->pos == e->args)
-			return (int)(a->n == 0 ? strdup("like") : NULL);
-		else if (a->pos == e->args+1 && strcasestr(a->line," like "))
-			return (int)ast_module_helper(a->line, a->word, a->pos, a->n, a->pos, 0);
-		else
-			return (int)NULL;
-
-	default:	/* we are guaranteed to have argc >= e->args */
-		if (argc == e->args)
-			like = "";
-		else if (argc == e->args + 2 && !strcmp(argv[e->args],"like"))
-			like = argv[e->args + 1];
-		else
-			return RESULT_SHOWUSAGE;
-		
-		ast_mutex_lock(&climodentrylock);
-		climodentryfd = fd; /* global, protected by climodentrylock */
-		ast_cli(fd, MODLIST_FORMAT2, "Module", "Description", "Use Count");
-		ast_cli(fd,"%d modules loaded\n", ast_update_module_list(modlist_modentry, like));
-		climodentryfd = -1;
-		ast_mutex_unlock(&climodentrylock);
-		return RESULT_SUCCESS;
-	}
 }
 #undef MODLIST_FORMAT
 #undef MODLIST_FORMAT2
@@ -469,10 +502,8 @@
 	int durh, durm, durs;
 	int numchans = 0, concise = 0, verbose = 0;
 
-	if (argc == 4) {
-		concise = !strcasecmp(argv[2],"concise");
-		verbose = !strcasecmp(argv[2],"verbose");
-	}
+	concise = (argc == 4 && (!strcasecmp(argv[3],"concise")));
+	verbose = (argc == 4 && (!strcasecmp(argv[3],"verbose")));
 
 	if (argc < 3 || argc > 4 || (argc == 4 && !concise && !verbose))
 		return RESULT_SHOWUSAGE;
@@ -548,16 +579,12 @@
 }
 
 static char showchan_help[] = 
-"Usage: channel show <channel>\n"
+"Usage: core show channel <channel>\n"
 "       Shows lots of information about the specified channel.\n";
 
 static char debugchan_help[] = 
-"Usage: channel debug <channel>\n"
-"       Enables debugging on a specific channel.\n";
-
-static char nodebugchan_help[] = 
-"Usage: channel nodebug <channel>\n"
-"       Disables debugging on a specific channel.\n";
+"Usage: core set debug channel <channel> [off]\n"
+"       Enables/disables debugging on a specific channel.\n";
 
 static char commandcomplete_help[] = 
 "Usage: _command complete \"<line>\" text state\n"
@@ -663,25 +690,24 @@
 	return RESULT_SUCCESS;
 }
 
-/* XXX todo: merge next two functions!!! */
-static int handle_debugchan(int fd, int argc, char *argv[])
+static int handle_debugchan_deprecated(int fd, int argc, char *argv[])
 {
 	struct ast_channel *c=NULL;
 	int is_all;
 
 	/* 'debug channel {all|chan_id}' */
-	if (argc != 3)
+	if (argc != 4)
 		return RESULT_SHOWUSAGE;
 
-	is_all = !strcasecmp("all", argv[2]);
+	is_all = !strcasecmp("all", argv[3]);
 	if (is_all) {
 		global_fin |= DEBUGCHAN_FLAG;
 		global_fout |= DEBUGCHAN_FLAG;
 		c = ast_channel_walk_locked(NULL);
 	} else {
-		c = ast_get_channel_by_name_locked(argv[2]);
+		c = ast_get_channel_by_name_locked(argv[3]);
 		if (c == NULL)
-			ast_cli(fd, "No such channel %s\n", argv[2]);
+			ast_cli(fd, "No such channel %s\n", argv[3]);
 	}
 	while (c) {
 		if (!(c->fin & DEBUGCHAN_FLAG) || !(c->fout & DEBUGCHAN_FLAG)) {
@@ -698,22 +724,68 @@
 	return RESULT_SUCCESS;
 }
 
-static int handle_nodebugchan(int fd, int argc, char *argv[])
+static int handle_core_set_debug_channel(int fd, int argc, char *argv[])
+{
+	struct ast_channel *c = NULL;
+	int is_all, is_off = 0;
+
+	/* 'core set debug channel {all|chan_id}' */
+	if (argc == 6 && strcmp(argv[5], "off") == 0)
+		is_off = 1;
+	else if (argc != 5)
+		return RESULT_SHOWUSAGE;
+
+	is_all = !strcasecmp("all", argv[4]);
+	if (is_all) {
+		if (is_off) {
+			global_fin &= ~DEBUGCHAN_FLAG;
+			global_fout &= ~DEBUGCHAN_FLAG;
+		} else {
+			global_fin |= DEBUGCHAN_FLAG;
+			global_fout |= DEBUGCHAN_FLAG;
+		}
+		c = ast_channel_walk_locked(NULL);
+	} else {
+		c = ast_get_channel_by_name_locked(argv[4]);
+		if (c == NULL)
+			ast_cli(fd, "No such channel %s\n", argv[4]);
+	}
+	while (c) {
+		if (!(c->fin & DEBUGCHAN_FLAG) || !(c->fout & DEBUGCHAN_FLAG)) {
+			if (is_off) {
+				c->fin &= ~DEBUGCHAN_FLAG;
+				c->fout &= ~DEBUGCHAN_FLAG;
+			} else {
+				c->fin |= DEBUGCHAN_FLAG;
+				c->fout |= DEBUGCHAN_FLAG;
+			}
+			ast_cli(fd, "Debugging %s on channel %s\n", is_off ? "disabled" : "enabled", c->name);
+		}
+		ast_channel_unlock(c);
+		if (!is_all)
+			break;
+		c = ast_channel_walk_locked(c);
+	}
+	ast_cli(fd, "Debugging on new channels is %s\n", is_off ? "disabled" : "enabled");
+	return RESULT_SUCCESS;
+}
+
+static int handle_nodebugchan_deprecated(int fd, int argc, char *argv[])
 {
 	struct ast_channel *c=NULL;
 	int is_all;
 	/* 'no debug channel {all|chan_id}' */
-	if (argc != 3)
+	if (argc != 4)
 		return RESULT_SHOWUSAGE;
-	is_all = !strcasecmp("all", argv[2]);
+	is_all = !strcasecmp("all", argv[3]);
 	if (is_all) {
 		global_fin &= ~DEBUGCHAN_FLAG;
 		global_fout &= ~DEBUGCHAN_FLAG;
 		c = ast_channel_walk_locked(NULL);
 	} else {
-		c = ast_get_channel_by_name_locked(argv[2]);
+		c = ast_get_channel_by_name_locked(argv[3]);
 		if (c == NULL)
-			ast_cli(fd, "No such channel %s\n", argv[2]);
+			ast_cli(fd, "No such channel %s\n", argv[3]);
 	}
 	while(c) {
 		if ((c->fin & DEBUGCHAN_FLAG) || (c->fout & DEBUGCHAN_FLAG)) {
@@ -740,12 +812,12 @@
 	long elapsed_seconds=0;
 	int hour=0, min=0, sec=0;
 	
-	if (argc != 3)
+	if (argc != 4)
 		return RESULT_SHOWUSAGE;
 	now = ast_tvnow();
-	c = ast_get_channel_by_name_locked(argv[2]);
+	c = ast_get_channel_by_name_locked(argv[3]);
 	if (!c) {
-		ast_cli(fd, "%s is not a known channel\n", argv[2]);
+		ast_cli(fd, "%s is not a known channel\n", argv[3]);
 		return RESULT_SUCCESS;
 	}
 	if(c->cdr) {
@@ -834,7 +906,7 @@
 {
 	static char *choices[] = { "concise", "verbose", NULL };
 
-	return (pos != 2) ? NULL : ast_cli_complete(word, choices, state);
+	return (pos != 3) ? NULL : ast_cli_complete(word, choices, state);
 }
 
 char *ast_complete_channels(const char *line, const char *word, int pos, int state, int rpos)
@@ -863,6 +935,21 @@
 	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 char *complete_ch_5(const char *line, const char *word, int pos, int state)
+{
+	return ast_complete_channels(line, word, pos, state, 4);
+}
+
+static char *complete_mod_2(const char *line, const char *word, int pos, int state)
+{
+	return ast_module_helper(line, word, pos, state, 1, 1);
+}
+
 static char *complete_mod_3_nr(const char *line, const char *word, int pos, int state)
 {
 	return ast_module_helper(line, word, pos, state, 2, 0);
@@ -870,7 +957,9 @@
 
 static char *complete_mod_3(const char *line, const char *word, int pos, int state)
 {
-	return ast_module_helper(line, word, pos, state, 2, 1);
+	if (pos < 2)
+		return NULL;
+	return ast_module_helper(line, word, pos, state, pos, 1);
 }
 
 static char *complete_fn(const char *line, const char *word, int pos, int state)
@@ -978,32 +1067,47 @@
 	{ { NULL }, NULL, NULL, NULL }
 };
 
+static struct ast_cli_entry cli_debug_channel_deprecated = {
+	{ "debug", "channel", NULL },
+	handle_debugchan_deprecated, NULL,
+	NULL, complete_ch_3 };
+
+static struct ast_cli_entry cli_module_load_deprecated = {
+	{ "load", NULL },
+	handle_load_deprecated, NULL,
+	NULL, complete_fn };
+
+static struct ast_cli_entry cli_module_reload_deprecated = {
+	{ "reload", NULL },
+	handle_reload_deprecated, NULL,
+	NULL, complete_mod_2 };
+
+static struct ast_cli_entry cli_module_unload_deprecated = {
+	{ "unload", NULL },
+	handle_unload_deprecated, NULL,
+	NULL, complete_mod_2 };
+
 static struct ast_cli_entry cli_cli[] = {
+	/* Deprecated, but preferred command is now consolidated (and already has a deprecated command for it). */
+	{ { "no", "debug", "channel", NULL },
+	handle_nodebugchan_deprecated, NULL,
+	NULL, complete_ch_4 },
+
 	{ { "core", "show", "channels", NULL },
 	handle_chanlist, "Display information on channels",
 	chanlist_help, complete_show_channels },
 
 	{ { "core", "show", "channel", NULL },
 	handle_showchan, "Display information on a specific channel",
-	showchan_help, complete_ch_3 },
-
-	{ { "core", "debug", "channel", NULL },
-	handle_debugchan, "Enable debugging on a channel",
-	debugchan_help, complete_ch_3 },
-
-	{ { "core", "no", "debug", "channel", NULL },
-	handle_nodebugchan, "Disable debugging on a channel",
-	nodebugchan_help, complete_ch_3 },
-
-	NEW_CLI(handle_debug, "Set level of debug chattiness"),
-
-	{ { "core", "set", "no", "debug", NULL },
-	handle_nodebug, "Turns off debug chattiness",
-	nodebug_help },
-
-	{ { "core", "set", "verbose", NULL },
-	handle_verbose, "Set level of verboseness",
-	verbose_help },
+	showchan_help, complete_ch_4 },
+
+	{ { "core", "set", "debug", "channel", NULL },
+	handle_core_set_debug_channel, "Enable/disable debugging on a channel",
+	debugchan_help, complete_ch_5, &cli_debug_channel_deprecated },
+
+	NEW_CLI(handle_set_debug, "Set level of debug chattiness"),
+
+	NEW_CLI(handle_verbose, "Set level of verboseness"),
 
 	{ { "group", "show", "channels", NULL },
 	group_show_channels, "Display active channels with group(s)",
@@ -1019,21 +1123,19 @@
 
 	NEW_CLI(handle_modlist, "List modules and info"),
 
-	{ { "load", NULL },
+	{ { "module", "load", NULL },
 	handle_load, "Load a module by name",
-	load_help, complete_fn },
-
-	{ { "reload", NULL },
+	load_help, complete_fn, &cli_module_load_deprecated },
+
+	{ { "module", "reload", NULL },
 	handle_reload, "Reload configuration",
-	reload_help, complete_mod_3 },
-
-	{ { "unload", NULL },
+	reload_help, complete_mod_3, &cli_module_reload_deprecated },
+
+	{ { "module", "unload", NULL },
 	handle_unload, "Unload a module by name",
-	unload_help, complete_mod_3_nr },
-
- 	{ { "core", "show", "uptime", NULL },
-	handle_showuptime, "Show uptime information",
-	uptime_help },
+	unload_help, complete_mod_3_nr, &cli_module_unload_deprecated },
+
+	NEW_CLI(handle_showuptime, "Show uptime information"),
 
 	{ { "soft", "hangup", NULL },
 	handle_softhangup, "Request a hangup on a given channel",
@@ -1168,9 +1270,9 @@
 		AST_LIST_UNLOCK(&helpers);
 		free(e->_full_cmd);
 		e->_full_cmd = NULL;
-		if (e->command) {
+		if (e->new_handler) {
 			/* this is a new-style entry. Reset fields and free memory. */
-			((char **)e->cmda)[0] = NULL;
+			bzero((char **)(e->cmda), sizeof(e->cmda));
 			free(e->command);
 			e->command = NULL;
 			e->usage = NULL;
@@ -1185,12 +1287,15 @@
 	char fulle[80] ="";
 	int i, lf, ret = -1;
 
-	if (e->cmda[0] == NULL) {	/* new style entry, run the handler to init fields */
-		char *args[2] = { (char *)e, NULL };
-		char *s = (char *)(e->handler(-1, CLI_CMD_STRING, args+1));
+	if (e->handler == NULL) {	/* new style entry, run the handler to init fields */
+		struct ast_cli_args a;	/* fake argument */
 		char **dst = (char **)e->cmda;	/* need to cast as the entry is readonly */
-
-		s = ast_skip_blanks(s);
+		char *s;
+
+		bzero (&a, sizeof(a));
+		e->new_handler(e, CLI_INIT, &a);
+		/* XXX check that usage and command are filled up */
+		s = ast_skip_blanks(e->command);
 		s = e->command = ast_strdup(s);
 		for (i=0; !ast_strlen_zero(s) && i < AST_MAX_CMD_LEN-1; i++) {
 			*dst++ = s;	/* store string */
@@ -1201,7 +1306,6 @@
 			s = ast_skip_blanks(s);
 		}
 		*dst++ = NULL;
-		e->usage = (char *)(e->handler(-1, CLI_USAGE, args+1));
 	}
 	for (i = 0; e->cmda[i]; i++)
 		;
@@ -1524,23 +1628,16 @@
 			 * Run the generator if one is available. In any case we are done.
 			 */
 			if (e->generator)
-				ret = e->generator(matchstr, word, argindex, state);
-			else if (e->command) {	/* new style command */
-				/* prepare fake arguments for the generator.
-				 * argv[-1] is the cli entry we use,
-				 * argv[0] is a pointer to the generator arguments,
-				 *   with a fake string '-' at the beginning so we can
-				 *   dereference it as a string with no trouble,
-				 *   and then the usual NULL terminator.
-				 */
+				ret = e->generator(matchstr, word, argindex, state - matchnum);
+			else if (e->new_handler) {	/* new style command */
 				struct ast_cli_args a = {
-					.fake = "-",
 					.line = matchstr, .word = word,
-					.pos = argindex, .n = state };
-				char *args[] = { (char *)e, (char *)&a, NULL };
-				ret = (char *)e->handler(-1, CLI_GENERATE, args + 1);
+					.pos = argindex,
+					.n = state - matchnum };
+				ret = e->new_handler(e, CLI_GENERATE, &a);
 			}
-			break;
+			if (ret)
+				break;
 		}
 	}
 	if (lock)
@@ -1573,11 +1670,19 @@
 			e->inuse++;
 		AST_LIST_UNLOCK(&helpers);
 		if (e) {
+			int res;
 			/* within calling the handler, argv[-1] contains a pointer
 			 * to the cli entry, and the array is null-terminated
 			 */
 			args[0] = (char *)e;
-			switch(e->handler(fd, x, args + 1)) {
+			if (e->new_handler) {	/* new style */
+				struct ast_cli_args a = {
+					.fd = fd, .argc = x, .argv = args+1 };
+				res = (int)e->new_handler(e, CLI_HANDLER, &a);
+			} else {		/* old style */
+				res = e->handler(fd, x, args + 1);
+			}
+			switch (res) {
 			case RESULT_SHOWUSAGE:
 				if (e->usage)
 					ast_cli(fd, "%s", e->usage);



More information about the asterisk-commits mailing list