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 /* dont check permissions while passing this option as a 'uid' 00036 * to the cli_has_permissions() function. */ 00037 #define CLI_NO_PERMS -1 00038 00039 #define RESULT_SUCCESS 0 00040 #define RESULT_SHOWUSAGE 1 00041 #define RESULT_FAILURE 2 00042 00043 #define CLI_SUCCESS (char *)RESULT_SUCCESS 00044 #define CLI_SHOWUSAGE (char *)RESULT_SHOWUSAGE 00045 #define CLI_FAILURE (char *)RESULT_FAILURE 00046 00047 #define AST_MAX_CMD_LEN 16 00048 00049 #define AST_MAX_ARGS 64 00050 00051 #define AST_CLI_COMPLETE_EOF "_EOF_" 00052 00053 /*! 00054 * In many cases we need to print singular or plural 00055 * words depending on a count. This macro helps us e.g. 00056 * printf("we have %d object%s", n, ESS(n)); 00057 */ 00058 #define ESS(x) ((x) == 1 ? "" : "s") 00059 00060 /*! \brief return Yes or No depending on the argument. 00061 * This is used in many places in CLI command, having a function to generate 00062 * this helps maintaining a consistent output (and possibly emitting the 00063 * output in other languages, at some point). 00064 */ 00065 #define AST_CLI_YESNO(x) (x) ? "Yes" : "No" 00066 00067 /*! \brief return On or Off depending on the argument. 00068 * This is used in many places in CLI command, having a function to generate 00069 * this helps maintaining a consistent output (and possibly emitting the 00070 * output in other languages, at some point). 00071 */ 00072 #define AST_CLI_ONOFF(x) (x) ? "On" : "Off" 00073 00074 /*! \page CLI_command_API CLI command API 00075 00076 CLI commands are described by a struct ast_cli_entry that contains 00077 all the components for their implementation. 00078 00079 In the "old-style" format, the record must contain: 00080 - a NULL-terminated array of words constituting the command, e.g. 00081 { "set", "debug", "on", NULL }, 00082 - a summary string (short) and a usage string (longer); 00083 - a handler which implements the command itself, invoked with 00084 a file descriptor and argc/argv as typed by the user 00085 - a 'generator' function which, given a partial string, can 00086 generate legal completions for it. 00087 An example is 00088 00089 int old_setdebug(int fd, int argc, char *argv[]); 00090 char *dbg_complete(const char *line, const char *word, int pos, int n); 00091 00092 { { "set", "debug", "on", NULL }, do_setdebug, "Enable debugging", 00093 set_debug_usage, dbg_complete }, 00094 00095 In the "new-style" format, all the above functionalities are implemented 00096 by a single function, and the arguments tell which output is required. 00097 The prototype is the following: 00098 00099 char *new_setdebug(const struct ast_cli_entry *e, int cmd, struct ast_cli_args *a); 00100 00101 ... 00102 // this is how we create the entry to register 00103 AST_CLI_DEFINE(new_setdebug, "short description") 00104 ... 00105 00106 To help the transition, we make the pointer to the struct ast_cli_entry 00107 available to old-style handlers via argv[-1]. 00108 00109 An example of new-style handler is the following 00110 00111 \code 00112 static char *test_new_cli(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) 00113 { 00114 static const char * const choices[] = { "one", "two", "three", NULL }; 00115 00116 switch (cmd) { 00117 case CLI_INIT: 00118 e->command = "do this well"; 00119 e->usage = 00120 "Usage: do this well <arg>\n" 00121 " typically multiline with body indented\n"; 00122 return NULL; 00123 00124 case CLI_GENERATE: 00125 if (a->pos > e->args) 00126 return NULL; 00127 return ast_cli_complete(a->word, choices, a->n); 00128 00129 default: 00130 // we are guaranteed to be called with argc >= e->args; 00131 if (a->argc > e->args + 1) // we accept one extra argument 00132 return CLI_SHOWUSAGE; 00133 ast_cli(a->fd, "done this well for %s\n", e->args[argc-1]); 00134 return CLI_SUCCESS; 00135 } 00136 } 00137 00138 \endcode 00139 00140 */ 00141 00142 /*! \brief calling arguments for new-style handlers. 00143 * \arg \ref CLI_command_API 00144 */ 00145 enum ast_cli_command { 00146 CLI_INIT = -2, /* return the usage string */ 00147 CLI_GENERATE = -3, /* behave as 'generator', remap argv to struct ast_cli_args */ 00148 CLI_HANDLER = -4, /* run the normal handler */ 00149 }; 00150 00151 /* argument for new-style CLI handler */ 00152 struct ast_cli_args { 00153 const int fd; 00154 const int argc; 00155 const char * const *argv; 00156 const char *line; /* the current input line */ 00157 const char *word; /* the word we want to complete */ 00158 const int pos; /* position of the word to complete */ 00159 const int n; /* the iteration count (n-th entry we generate) */ 00160 }; 00161 00162 /*! \brief descriptor for a cli entry. 00163 * \arg \ref CLI_command_API 00164 */ 00165 struct ast_cli_entry { 00166 const char * const cmda[AST_MAX_CMD_LEN]; /*!< words making up the command. 00167 * set the first entry to NULL for a new-style entry. 00168 */ 00169 00170 const char * const summary; /*!< Summary of the command (< 60 characters) */ 00171 const char * usage; /*!< Detailed usage information */ 00172 00173 int inuse; /*!< For keeping track of usage */ 00174 struct module *module; /*!< module this belongs to */ 00175 char *_full_cmd; /*!< built at load time from cmda[] */ 00176 int cmdlen; /*!< len up to the first invalid char [<{% */ 00177 /*! \brief This gets set in ast_cli_register() 00178 */ 00179 int args; /*!< number of non-null entries in cmda */ 00180 char *command; /*!< command, non-null for new-style entries */ 00181 char *(*handler)(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a); 00182 /*! For linking */ 00183 AST_LIST_ENTRY(ast_cli_entry) list; 00184 }; 00185 00186 #if defined(__cplusplus) || defined(c_plusplus) 00187 #define AST_CLI_DEFINE(fn, txt) { { "" }, txt, NULL, 0, NULL, NULL, 0, 0, NULL, fn } 00188 #else 00189 /* XXX the parser in gcc 2.95 gets confused if you don't put a space 00190 * between the last arg before VA_ARGS and the comma */ 00191 #define AST_CLI_DEFINE(fn, txt , ... ) { .handler = fn, .summary = txt, ## __VA_ARGS__ } 00192 #endif 00193 00194 /*! 00195 * Helper function to generate cli entries from a NULL-terminated array. 00196 * Returns the n-th matching entry from the array, or NULL if not found. 00197 * Can be used to implement generate() for static entries as below 00198 * (in this example we complete the word in position 2): 00199 \code 00200 char *my_generate(const char *line, const char *word, int pos, int n) 00201 { 00202 static const char * const choices[] = { "one", "two", "three", NULL }; 00203 if (pos == 2) 00204 return ast_cli_complete(word, choices, n); 00205 else 00206 return NULL; 00207 } 00208 \endcode 00209 */ 00210 char *ast_cli_complete(const char *word, const char * const choices[], int pos); 00211 00212 /*! 00213 * \brief Interprets a command 00214 * Interpret a command s, sending output to fd if uid:gid has permissions 00215 * to run this command. uid = CLI_NO_PERMS to avoid checking user permissions 00216 * gid = CLI_NO_PERMS to avoid checking group permissions. 00217 * \param uid User ID that is trying to run the command. 00218 * \param gid Group ID that is trying to run the command. 00219 * \param fd pipe 00220 * \param s incoming string 00221 * \retval 0 on success 00222 * \retval -1 on failure 00223 */ 00224 int ast_cli_command_full(int uid, int gid, int fd, const char *s); 00225 00226 #define ast_cli_command(fd,s) ast_cli_command_full(CLI_NO_PERMS, CLI_NO_PERMS, fd, s) 00227 00228 /*! 00229 * \brief Executes multiple CLI commands 00230 * Interpret strings separated by NULL and execute each one, sending output to fd 00231 * if uid has permissions, uid = CLI_NO_PERMS to avoid checking users permissions. 00232 * gid = CLI_NO_PERMS to avoid checking group permissions. 00233 * \param uid User ID that is trying to run the command. 00234 * \param gid Group ID that is trying to run the command. 00235 * \param fd pipe 00236 * \param size is the total size of the string 00237 * \param s incoming string 00238 * \retval number of commands executed 00239 */ 00240 int ast_cli_command_multiple_full(int uid, int gid, int fd, size_t size, const char *s); 00241 00242 #define ast_cli_command_multiple(fd,size,s) ast_cli_command_multiple_full(CLI_NO_PERMS, CLI_NO_PERMS, fd, size, s) 00243 00244 /*! \brief Registers a command or an array of commands 00245 * \param e which cli entry to register. 00246 * Register your own command 00247 * \retval 0 on success 00248 * \retval -1 on failure 00249 */ 00250 int ast_cli_register(struct ast_cli_entry *e); 00251 00252 /*! 00253 * \brief Register multiple commands 00254 * \param e pointer to first cli entry to register 00255 * \param len number of entries to register 00256 */ 00257 int ast_cli_register_multiple(struct ast_cli_entry *e, int len); 00258 00259 /*! 00260 * \brief Unregisters a command or an array of commands 00261 * \param e which cli entry to unregister 00262 * Unregister your own command. You must pass a completed ast_cli_entry structure 00263 * \return 0 00264 */ 00265 int ast_cli_unregister(struct ast_cli_entry *e); 00266 00267 /*! 00268 * \brief Unregister multiple commands 00269 * \param e pointer to first cli entry to unregister 00270 * \param len number of entries to unregister 00271 */ 00272 int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len); 00273 00274 /*! 00275 * \brief Readline madness 00276 * Useful for readline, that's about it 00277 * \retval 0 on success 00278 * \retval -1 on failure 00279 */ 00280 char *ast_cli_generator(const char *, const char *, int); 00281 00282 int ast_cli_generatornummatches(const char *, const char *); 00283 00284 /*! 00285 * \brief Generates a NULL-terminated array of strings that 00286 * 1) begin with the string in the second parameter, and 00287 * 2) are valid in a command after the string in the first parameter. 00288 * 00289 * The first entry (offset 0) of the result is the longest common substring 00290 * in the results, useful to extend the string that has been completed. 00291 * Subsequent entries are all possible values, followed by a NULL. 00292 * All strings and the array itself are malloc'ed and must be freed 00293 * by the caller. 00294 */ 00295 char **ast_cli_completion_matches(const char *, const char *); 00296 00297 /*! 00298 * \brief Command completion for the list of active channels. 00299 * 00300 * This can be called from a CLI command completion function that wants to 00301 * complete from the list of active channels. 'rpos' is the required 00302 * position in the command. This function will return NULL immediately if 00303 * 'rpos' is not the same as the current position, 'pos'. 00304 */ 00305 char *ast_complete_channels(const char *line, const char *word, int pos, int state, int rpos); 00306 00307 #if defined(__cplusplus) || defined(c_plusplus) 00308 } 00309 #endif 00310 00311 #endif /* _ASTERISK_CLI_H */