blob: a91fb3de25af2deb0feaec78f157066f54d435eb [file] [log] [blame]
/* $Id$ */
/*
* Copyright (C) 2010 Teluu Inc. (http://www.teluu.com)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __PJLIB_UTIL_CLI_H__
#define __PJLIB_UTIL_CLI_H__
/**
* @file cli.h
* @brief Command Line Interface
*/
#include <pjlib-util/types.h>
#include <pj/list.h>
PJ_BEGIN_DECL
/**
* @defgroup PJLIB_UTIL_CLI Command Line Interface Framework
* @{
* A CLI framework features an interface for defining command specification,
* parsing, and executing a command.
* It also features an interface to communicate with various front-ends,
* such as console, telnet.
* Application normally needs only one CLI instance to be created.
* On special cases, application could also create multiple CLI
* instances, with each instance has specific command structure.
*
\verbatim
| vid help Show this help screen |
| vid enable|disable Enable or disable video in next offer/answer |
| vid call add Add video stream for current call |
| vid call cap N ID Set capture dev ID for stream #N in current call |
| disable_codec g711|g722 Show this help screen |
<CMD name='vid' id='0' desc="">
<CMD name='help' id='0' desc='' />
<CMD name='enable' id='0' desc='' />
<CMD name='disable' id='0' desc='' />
<CMD name='call' id='0' desc='' >
<CMD name='add' id='101' desc='...' />
<CMD name='cap' id='102' desc='...' >
<ARG name='streamno' type='int' desc='...' id='1'/>
<ARG name='devid' type='int' optional='1' id='2'/>
</CMD>
</CMD>
</CMD>
<CMD name='disable_codec' id=0 desc="">
<ARG name='codec_list' type='choice' id='3'>
<CHOICE value='g711'/>
<CHOICE value='g722'/>
</ARG>
</CMD>
\endverbatim
*/
/**
* This opaque structure represents a CLI application. A CLI application is
* the root placeholder of other CLI objects. In an application, one (and
* normally only one) CLI application instance needs to be created.
*/
typedef struct pj_cli_t pj_cli_t;
/**
* Type of command id.
*/
typedef int pj_cli_cmd_id;
/**
* This describes the parameters to be specified when creating a CLI
* application with pj_cli_create(). Application MUST initialize this
* structure by calling pj_cli_cfg_default() before using it.
*/
typedef struct pj_cli_cfg
{
/**
* The application name, which will be used in places such as logs.
* This field is mandatory.
*/
pj_str_t name;
/**
* Optional application title, which will be used in places such as
* window title. If not specified, the application name will be used
* as the title.
*/
pj_str_t title;
/**
* The pool factory where all memory allocations will be taken from.
* This field is mandatory.
*/
pj_pool_factory *pf;
} pj_cli_cfg;
/**
* Type of argument id.
*/
typedef int pj_cli_arg_id;
/**
* Forward declaration of pj_cli_cmd_spec structure.
*/
typedef struct pj_cli_cmd_spec pj_cli_cmd_spec;
/**
* Forward declaration for pj_cli_sess, which will be declared in cli_imp.h.
*/
typedef struct pj_cli_sess pj_cli_sess;
/**
* Forward declaration for CLI front-end.
*/
typedef struct pj_cli_front_end pj_cli_front_end;
/**
* Forward declaration for CLI argument spec structure.
*/
typedef struct pj_cli_arg_spec pj_cli_arg_spec;
/**
* This structure contains the command to be executed by command handler.
*/
typedef struct pj_cli_cmd_val
{
/** The session on which the command was executed on. */
pj_cli_sess *sess;
/** The command specification being executed. */
const pj_cli_cmd_spec *cmd;
/** Number of argvs. */
int argc;
/** Array of args, with argv[0] specifies the name of the cmd. */
pj_str_t argv[PJ_CLI_MAX_ARGS];
} pj_cli_cmd_val;
/**
* This structure contains the hints information for the end user.
* This structure could contain either command or argument information.
* The front-end will format the information and present it to the user.
*/
typedef struct pj_cli_hint_info
{
/**
* The hint value.
*/
pj_str_t name;
/**
* The hint type.
*/
pj_str_t type;
/**
* Helpful description of the hint value.
*/
pj_str_t desc;
} pj_cli_hint_info;
/**
* This structure contains extra information returned by pj_cli_sess_exec()/
* pj_cli_sess_parse().
* Upon return from the function, various other fields in this structure will
* be set by the function.
*/
typedef struct pj_cli_exec_info
{
/**
* If command parsing failed, on return this will point to the location
* where the failure occurs, otherwise the value will be set to -1.
*/
int err_pos;
/**
* If a command matching the command in the cmdline was found, on return
* this will be set to the command id of the command, otherwise it will be
* set to PJ_CLI_INVALID_CMD_ID.
*/
pj_cli_cmd_id cmd_id;
/**
* If a command was executed, on return this will be set to the return
* value of the command, otherwise it will contain PJ_SUCCESS.
*/
pj_status_t cmd_ret;
/**
* The number of hint elements
**/
unsigned hint_cnt;
/**
* If pj_cli_sess_parse() fails because of a missing argument or ambigous
* command/argument, the function returned PJ_CLI_EMISSINGARG or
* PJ_CLI_EAMBIGUOUS error.
* This field will contain the hint information. This is useful to give
* helpful information to the end_user.
*/
pj_cli_hint_info hint[PJ_CLI_MAX_HINTS];
} pj_cli_exec_info;
/**
* This structure contains the information returned from the dynamic
* argument callback.
*/
typedef struct pj_cli_arg_choice_val
{
/**
* The argument choice value
*/
pj_str_t value;
/**
* Helpful description of the choice value. This text will be used when
* displaying the help texts for the choice value
*/
pj_str_t desc;
} pj_cli_arg_choice_val;
/**
* This structure contains the parameters for pj_cli_get_dyn_choice
*/
typedef struct pj_cli_dyn_choice_param
{
/**
* The session on which the command was executed on.
*/
pj_cli_sess *sess;
/**
* The command being processed.
*/
pj_cli_cmd_spec *cmd;
/**
* The argument id.
*/
pj_cli_arg_id arg_id;
/**
* The maximum number of values that the choice can hold.
*/
unsigned max_cnt;
/**
* The pool to allocate memory from.
*/
pj_pool_t *pool;
/**
* The choice values count.
*/
unsigned cnt;
/**
* Array containing the valid choice values.
*/
pj_cli_arg_choice_val choice[PJ_CLI_MAX_CHOICE_VAL];
} pj_cli_dyn_choice_param;
/**
* This specifies the callback type for argument handlers, which will be
* called to get the valid values of the choice type arguments.
*/
typedef void (*pj_cli_get_dyn_choice) (pj_cli_dyn_choice_param *param);
/**
* This specifies the callback type for command handlers, which will be
* executed when the specified command is invoked.
*
* @param cmd_val The command that is specified by the user.
*
* @return Return the status of the command execution.
*/
typedef pj_status_t (*pj_cli_cmd_handler)(pj_cli_cmd_val *cval);
/**
* Write a log message to the CLI application. The CLI application
* will send the log message to all the registered front-ends.
*
* @param cli The CLI application instance.
* @param level Verbosity level of this message message.
* @param buffer The message itself.
* @param len Length of this message.
*/
PJ_DECL(void) pj_cli_write_log(pj_cli_t *cli,
int level,
const char *buffer,
int len);
/**
* Create a new CLI application instance.
*
* @param cfg CLI application creation parameters.
* @param p_cli Pointer to receive the returned instance.
*
* @return PJ_SUCCESS on success, or the appropriate error code.
*/
PJ_DECL(pj_status_t) pj_cli_create(pj_cli_cfg *cfg,
pj_cli_t **p_cli);
/**
* This specifies the function to get the id of the specified command
*
* @param cmd The specified command.
*
* @return The command id
*/
PJ_DECL(pj_cli_cmd_id) pj_cli_get_cmd_id(const pj_cli_cmd_spec *cmd);
/**
* Get the internal parameter of the CLI instance.
*
* @param cli The CLI application instance.
*
* @return CLI parameter instance.
*/
PJ_DECL(pj_cli_cfg*) pj_cli_get_param(pj_cli_t *cli);
/**
* Call this to signal application shutdown. Typically application would
* call this from it's "Quit" menu or similar command to quit the
* application.
*
* See also pj_cli_sess_end_session() to end a session instead of quitting the
* whole application.
*
* @param cli The CLI application instance.
* @param req The session on which the shutdown request is
* received.
* @param restart Indicate whether application restart is wanted.
*/
PJ_DECL(void) pj_cli_quit(pj_cli_t *cli, pj_cli_sess *req,
pj_bool_t restart);
/**
* Check if application shutdown or restart has been requested.
*
* @param cli The CLI application instance.
*
* @return PJ_TRUE if pj_cli_quit() has been called.
*/
PJ_DECL(pj_bool_t) pj_cli_is_quitting(pj_cli_t *cli);
/**
* Check if application restart has been requested.
*
* @param cli The CLI application instance.
*
* @return PJ_TRUE if pj_cli_quit() has been called with
* restart parameter set.
*/
PJ_DECL(pj_bool_t) pj_cli_is_restarting(pj_cli_t *cli);
/**
* Destroy a CLI application instance. This would also close all sessions
* currently running for this CLI application.
*
* @param cli The CLI application.
*/
PJ_DECL(void) pj_cli_destroy(pj_cli_t *cli);
/**
* Initialize a pj_cli_cfg with its default values.
*
* @param param The instance to be initialized.
*/
PJ_DECL(void) pj_cli_cfg_default(pj_cli_cfg *param);
/**
* Register a front end to the CLI application.
*
* @param CLI The CLI application.
* @param fe The CLI front end to be registered.
*/
PJ_DECL(void) pj_cli_register_front_end(pj_cli_t *cli,
pj_cli_front_end *fe);
/**
* Create a new complete command specification from an XML node text and
* register it to the CLI application.
*
* @param cli The CLI application.
* @param group Optional group to which this command will be added
* to, or specify NULL if this command is a root
* command.
* @param xml Input string containing XML node text for the
* command.
* @param handler Function handler for the command. This must be NULL
* if the command specifies a command group.
* @param p_cmd Optional pointer to store the newly created
* specification.
* @param get_choice Function handler for the argument. Specify this for
* dynamic choice type arguments.
*
* @return PJ_SUCCESS on success, or the appropriate error code.
*/
PJ_DECL(pj_status_t) pj_cli_add_cmd_from_xml(pj_cli_t *cli,
pj_cli_cmd_spec *group,
const pj_str_t *xml,
pj_cli_cmd_handler handler,
pj_cli_cmd_spec **p_cmd,
pj_cli_get_dyn_choice get_choice);
/**
* Initialize pj_cli_exec_info with its default values.
*
* @param param The param to be initialized.
*/
PJ_DECL(void) pj_cli_exec_info_default(pj_cli_exec_info *param);
/**
* Write a log message to the specific CLI session.
*
* @param sess The CLI active session.
* @param buffer The message itself.
* @param len Length of this message.
*/
PJ_DECL(void) pj_cli_sess_write_msg(pj_cli_sess *sess,
const char *buffer,
pj_size_t len);
/**
* Parse an input cmdline string. The first word of the command line is the
* command itself, which will be matched against command specifications
* registered in the CLI application.
*
* Zero or more arguments follow the command name. Arguments are separated by
* one or more whitespaces. Argument may be placed inside a pair of quotes,
* double quotes, '{' and '}', or '[' and ']' pairs. This is useful when the
* argument itself contains whitespaces or other restricted characters. If
* the quote character itself is to appear in the argument, the argument then
* must be quoted with different quote characters. There is no character
* escaping facility provided by this function (such as the use of backslash
* '\' character).
*
* The cmdline may be followed by an extra newline (LF or CR-LF characters),
* which will be removed by the function. However any more characters
* following this newline will cause an error to be returned.
*
* @param sess The CLI session.
* @param cmdline The command line string to be parsed.
* @param val Structure to store the parsing result.
* @param pool The pool to allocate memory from.
* @param info Additional info to be returned regarding the parsing.
*
* @return This function returns the status of the parsing,
* which can be one of the following :
* - PJ_SUCCESS: a command was executed successfully.
* - PJ_EINVAL: invalid parameter to this function.
* - PJ_ENOTFOUND: command is not found.
* - PJ_CLI_EAMBIGUOUS: command/argument is ambiguous.
* - PJ_CLI_EMISSINGARG: missing argument.
* - PJ_CLI_EINVARG: invalid command argument.
* - PJ_CLI_EEXIT: "exit" has been called to end
* the current session. This is a signal for the
* application to end it's main loop.
*/
PJ_DECL(pj_status_t) pj_cli_sess_parse(pj_cli_sess *sess,
char *cmdline,
pj_cli_cmd_val *val,
pj_pool_t *pool,
pj_cli_exec_info *info);
/**
* End the specified session, and destroy it to release all resources used
* by the session.
*
* See also pj_cli_sess and pj_cli_front_end for more info regarding the
* creation process.
* See also pj_cli_quit() to quit the whole application instead.
*
* @param sess The CLI session to be destroyed.
*/
PJ_DECL(void) pj_cli_sess_end_session(pj_cli_sess *sess);
/**
* Execute a command line. This function will parse the input string to find
* the appropriate command and verify whether the string matches the command
* specifications. If matches, the command will be executed, and the return
* value of the command will be set in the \a cmd_ret field of the \a info
* argument, if specified.
*
* See also pj_cli_sess_parse() for more info regarding the cmdline format.
*
* @param sess The CLI session.
* @param cmdline The command line string to be executed.
* @param pool The pool to allocate memory from.
* @param info Optional pointer to receive additional information
* related to the execution of the command (such as
* the command return value).
*
* @return This function returns the status of the command
* parsing and execution (note that the return value
* of the handler itself will be returned in \a info
* argument, if specified). Please see the return value
* of pj_cli_sess_parse() for possible return values.
*/
PJ_DECL(pj_status_t) pj_cli_sess_exec(pj_cli_sess *sess,
char *cmdline,
pj_pool_t *pool,
pj_cli_exec_info *info);
/**
* @}
*/
PJ_END_DECL
#endif /* __PJLIB_UTIL_CLI_H__ */