Codename Pineapple

Home page | Mailing list | Docs

Last updated: Sat Feb 3 05:00:47 2007

Asterisk developer's documentation :: Codename Pineapple


cli.h

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

Asterisk is a trademark for Digium, inc.. | Edvina.net | Asterisk.org | This documentation was generated with Doxygen