00001 /* 00002 * Asterisk -- An open source telephony toolkit. 00003 * 00004 * Copyright (C) 1999 - 2005, Digium, Inc. 00005 * 00006 * Mark Spencer <markster@digium.com> 00007 * 00008 * See http://www.asterisk.org for more information about 00009 * the Asterisk project. Please do not directly contact 00010 * any of the maintainers of this project for assistance; 00011 * the project provides a web site, mailing lists and IRC 00012 * channels for your use. 00013 * 00014 * This program is free software, distributed under the terms of 00015 * the GNU General Public License Version 2. See the LICENSE file 00016 * at the top of the source tree. 00017 */ 00018 00019 /*! \file 00020 * \brief Standard Command Line Interface 00021 */ 00022 00023 #ifndef _ASTERISK_CLI_H 00024 #define _ASTERISK_CLI_H 00025 00026 #if defined(__cplusplus) || defined(c_plusplus) 00027 extern "C" { 00028 #endif 00029 00030 #include "asterisk/linkedlists.h" 00031 00032 void ast_cli(int fd, const char *fmt, ...) 00033 __attribute__((format(printf, 2, 3))); 00034 00035 #define RESULT_SUCCESS 0 00036 #define RESULT_SHOWUSAGE 1 00037 #define RESULT_FAILURE 2 00038 00039 #define CLI_SUCCESS (char *)RESULT_SUCCESS 00040 #define CLI_SHOWUSAGE (char *)RESULT_SHOWUSAGE 00041 #define CLI_FAILURE (char *)RESULT_FAILURE 00042 00043 #define AST_MAX_CMD_LEN 16 00044 00045 #define AST_MAX_ARGS 64 00046 00047 #define AST_CLI_COMPLETE_EOF "_EOF_" 00048 00049 /*! 00050 * In many cases we need to print singular or plural 00051 * words depending on a count. This macro helps us e.g. 00052 * printf("we have %d object%s", n, ESS(n)); 00053 */ 00054 #define ESS(x) ((x) == 1 ? "" : "s") 00055 00056 /*! \page CLI_command_API CLI command API 00057 00058 CLI commands are described by a struct ast_cli_entry that contains 00059 all the components for their implementation. 00060 00061 In the "old-style" format, the record must contain: 00062 - a NULL-terminated array of words constituting the command, e.g. 00063 { "set", "debug", "on", NULL }, 00064 - a summary string (short) and a usage string (longer); 00065 - a handler which implements the command itself, invoked with 00066 a file descriptor and argc/argv as typed by the user 00067 - a 'generator' function which, given a partial string, can 00068 generate legal completions for it. 00069 An example is 00070 00071 int old_setdebug(int fd, int argc, char *argv[]); 00072 char *dbg_complete(const char *line, const char *word, int pos, int n); 00073 00074 { { "set", "debug", "on", NULL }, do_setdebug, "Enable debugging", 00075 set_debug_usage, dbg_complete }, 00076 00077 In the "new-style" format, all the above functionalities are implemented 00078 by a single function, and the arguments tell which output is required. 00079 The prototype is the following: 00080 00081 char *new_setdebug(const struct ast_cli_entry *e, int cmd, struct ast_cli_args *a); 00082 00083 ... 00084 // this is how we create the entry to register 00085 AST_CLI_DEFINE(new_setdebug, "short description") 00086 ... 00087 00088 To help the transition, we make the pointer to the struct ast_cli_entry 00089 available to old-style handlers via argv[-1]. 00090 00091 An example of new-style handler is the following 00092 00093 \code 00094 static char *test_new_cli(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) 00095 { 00096 static char *choices = { "one", "two", "three", NULL }; 00097 00098 switch (cmd) { 00099 case CLI_INIT: 00100 e->command = "do this well"; 00101 e->usage = 00102 "Usage: do this well <arg>\n" 00103 " typically multiline with body indented\n"; 00104 return NULL; 00105 00106 case CLI_GENERATE: 00107 if (a->pos > e->args) 00108 return NULL; 00109 return ast_cli_complete(a->word, choices, a->n); 00110 00111 default: 00112 // we are guaranteed to be called with argc >= e->args; 00113 if (a->argc > e->args + 1) // we accept one extra argument 00114 return CLI_SHOWUSAGE; 00115 ast_cli(a->fd, "done this well for %s\n", e->args[argc-1]); 00116 return CLI_SUCCESS; 00117 } 00118 } 00119 00120 \endcode 00121 00122 */ 00123 00124 /*! \brief calling arguments for new-style handlers. 00125 * \arg \ref CLI_command_API 00126 */ 00127 enum ast_cli_fn { 00128 CLI_INIT = -2, /* return the usage string */ 00129 CLI_GENERATE = -3, /* behave as 'generator', remap argv to struct ast_cli_args */ 00130 CLI_HANDLER = -4, /* run the normal handler */ 00131 }; 00132 00133 /* argument for new-style CLI handler */ 00134 struct ast_cli_args { 00135 int fd; 00136 int argc; 00137 char **argv; 00138 const char *line; /* the current input line */ 00139 const char *word; /* the word we want to complete */ 00140 int pos; /* position of the word to complete */ 00141 int n; /* the iteration count (n-th entry we generate) */ 00142 }; 00143 00144 struct ast_cli_entry; 00145 typedef char *(*cli_fn)(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a); 00146 00147 /*! \brief descriptor for a cli entry. 00148 * \arg \ref CLI_command_API 00149 */ 00150 struct ast_cli_entry { 00151 char * const cmda[AST_MAX_CMD_LEN]; /*!< words making up the command. 00152 * set the first entry to NULL for a new-style entry. */ 00153 00154 const char *summary; /*!< Summary of the command (< 60 characters) */ 00155 const char *usage; /*!< Detailed usage information */ 00156 00157 struct ast_cli_entry *deprecate_cmd; 00158 00159 int inuse; /*!< For keeping track of usage */ 00160 struct module *module; /*!< module this belongs to */ 00161 char *_full_cmd; /*!< built at load time from cmda[] */ 00162 int cmdlen; /*!< len up to the first invalid char [<{% */ 00163 /*! \brief This gets set in ast_cli_register() 00164 It then gets set to something different when the deprecated command 00165 is run for the first time (ie; after we warn the user that it's deprecated) 00166 */ 00167 int args; /*!< number of non-null entries in cmda */ 00168 char *command; /*!< command, non-null for new-style entries */ 00169 int deprecated; 00170 cli_fn handler; 00171 char *_deprecated_by; /*!< copied from the "parent" _full_cmd, on deprecated commands */ 00172 /*! For linking */ 00173 AST_LIST_ENTRY(ast_cli_entry) list; 00174 }; 00175 00176 /* XXX the parser in gcc 2.95 gets confused if you don't put a space 00177 * between the last arg before VA_ARGS and the comma */ 00178 #define AST_CLI_DEFINE(fn, txt , ... ) { .handler = fn, .summary = txt, ## __VA_ARGS__ } 00179 00180 /*! 00181 * Helper function to generate cli entries from a NULL-terminated array. 00182 * Returns the n-th matching entry from the array, or NULL if not found. 00183 * Can be used to implement generate() for static entries as below 00184 * (in this example we complete the word in position 2): 00185 \code 00186 char *my_generate(const char *line, const char *word, int pos, int n) 00187 { 00188 static char *choices = { "one", "two", "three", NULL }; 00189 if (pos == 2) 00190 return ast_cli_complete(word, choices, n); 00191 else 00192 return NULL; 00193 } 00194 \endcode 00195 */ 00196 char *ast_cli_complete(const char *word, char *const choices[], int pos); 00197 00198 /*! 00199 * \brief Interprets a command 00200 * Interpret a command s, sending output to fd 00201 * \param fd pipe 00202 * \param s incoming string 00203 * \retval 0 on success 00204 * \retval -1 on failure 00205 */ 00206 int ast_cli_command(int fd, const char *s); 00207 00208 /*! 00209 * \brief Executes multiple CLI commands 00210 * Interpret strings separated by NULL and execute each one, sending output to fd 00211 * \param fd pipe 00212 * \param size is the total size of the string 00213 * \param s incoming string 00214 * \retval number of commands executed 00215 */ 00216 int ast_cli_command_multiple(int fd, size_t size, const char *s); 00217 00218 /*! \brief Registers a command or an array of commands 00219 * \param e which cli entry to register. 00220 * Register your own command 00221 * \retval 0 on success 00222 * \retval -1 on failure 00223 */ 00224 int ast_cli_register(struct ast_cli_entry *e); 00225 00226 /*! 00227 * \brief Register multiple commands 00228 * \param e pointer to first cli entry to register 00229 * \param len number of entries to register 00230 */ 00231 int ast_cli_register_multiple(struct ast_cli_entry *e, int len); 00232 00233 /*! 00234 * \brief Unregisters a command or an array of commands 00235 * \param e which cli entry to unregister 00236 * Unregister your own command. You must pass a completed ast_cli_entry structure 00237 * \return 0 00238 */ 00239 int ast_cli_unregister(struct ast_cli_entry *e); 00240 00241 /*! 00242 * \brief Unregister multiple commands 00243 * \param e pointer to first cli entry to unregister 00244 * \param len number of entries to unregister 00245 */ 00246 int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len); 00247 00248 /*! 00249 * \brief Readline madness 00250 * Useful for readline, that's about it 00251 * \retval 0 on success 00252 * \retval -1 on failure 00253 */ 00254 char *ast_cli_generator(const char *, const char *, int); 00255 00256 int ast_cli_generatornummatches(const char *, const char *); 00257 00258 /*! 00259 * \brief Generates a NULL-terminated array of strings that 00260 * 1) begin with the string in the second parameter, and 00261 * 2) are valid in a command after the string in the first parameter. 00262 * 00263 * The first entry (offset 0) of the result is the longest common substring 00264 * in the results, useful to extend the string that has been completed. 00265 * Subsequent entries are all possible values, followed by a NULL. 00266 * All strings and the array itself are malloc'ed and must be freed 00267 * by the caller. 00268 */ 00269 char **ast_cli_completion_matches(const char *, const char *); 00270 00271 /*! 00272 * \brief Command completion for the list of active channels. 00273 * 00274 * This can be called from a CLI command completion function that wants to 00275 * complete from the list of active channels. 'rpos' is the required 00276 * position in the command. This function will return NULL immediately if 00277 * 'rpos' is not the same as the current position, 'pos'. 00278 */ 00279 char *ast_complete_channels(const char *line, const char *word, int pos, int state, int rpos); 00280 00281 #if defined(__cplusplus) || defined(c_plusplus) 00282 } 00283 #endif 00284 00285 #endif /* _ASTERISK_CLI_H */