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