yangcli-pro Interface
The yangcli-pro client application supports external yangcli functions.
The external callback functions must be registered with yangcli-pro.
External Show Callback Functions
The function 'ycli_show_extern_register_callbacks' in 'yangcli/yangcli_show_extern.h' is used by the external code to register its own show callback functions. The show functions are used by the yangcli-pro.
/********************************************************************
* FUNCTION ycli_show_extern_register_callbacks
*
* Register the external callbacks for show implementation
*
* INPUTS:
* module == YANG module used for this function
* showfn_keyword == key word used for this function.
* showfn == show function callback
* cookie == context pointer (may be null)
* RETURNS:
* status of the function registration.
*
*********************************************************************/
extern status_t ycli_show_extern_register_callbacks(
const xmlChar* module,
const xmlChar* keyword,
ycli_show_extern_fn_t showfn,
void *cookie);
If the external method is selected in the yangcli-pro initialization then the callback function MUST be provided.
The function must be registered:
show fn: Invoke the a vendor specific function. The yangcli_show_extern_fn_t template is used for this callback.
The following code snippet shows the API template definitions from yangcli/yangcli_show_extern.h.
/********************************************************************
*
* Callback yangcli_show_extern_fn_t to handle external show
* functions.
*
* INPUTS:
* server_name == The current server name.
* rpc == RPC method for the show command being processed.
* line == CLI line input.
* session_name == The name of the current session.
* valset == valset filled in with parameters for the specified RPC
* mode == help_mode_t(none, brief, normal, full)
* cookie == context pointer passed in register time, (may be null)
*
* RETURNS:
* Status: NO_ERR or error.
*********************************************************************/
typedef status_t
(*yangcli_show_extern_fn_t) (const xmlChar *server_name
obj_temp_t *rpc,
const xmlChar *line,
const xmlChar *session_name
const val_value_t *valset,
help_mode_t mode,
void *cookie);
Example External yangcli Command
The following example code is available in 'example-show.cpp'. It shows some dummy external functions and how they are registered during initialization.
/*
* Copyright (c) 2012 - 2017, YumaWorks, Inc., All Rights Reserved.
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
/* FILE: example-show.c
Example External Show Library
*********************************************************************
* *
* I N C L U D E F I L E S *
* *
*********************************************************************/
#include <string.h>
#include <stdlib.h>
#include <xmlstring.h>
/* always include procdefs.h before all other YumaPro files */
#include "procdefs.h"
/* these H files can be in any order */
#include "example-show.h"
#include "log.h"
#include "ncx.h"
#include "ncxmod.h"
#include "ncxtypes.h"
#include "obj.h"
#include "status.h"
#include "val.h"
#include "xml_util.h"
#include "yangcli.h"
#include "yangcli_cmd.h"
#include "yangcli_control.h"
#include "yangcli_libshow.h"
#include "yangcli_session_cb.h"
#include "yangcli_term.h"
#define MODNAME (const xmlChar *)"example-fan"
#define FAN (const xmlChar *)"fan"
#define DIAGNOSTICS (const xmlChar *)"diagnostics"
#define EXAMPLE_CMDSTR (const xmlChar *)"example-cmd"
/* comment out to disable show fan command */
#define SHOW_FAN 1
/* comment out to disable show version command */
#define SHOW_VER 1
/* remove comment to enable term display hook example */
// #define TERM_API 1
/* comment out to disable top-level command example-cmd */
#define EXAMPLE_CMD 1
static ncx_module_t *mymod = NULL;
/************ Example External Yangcli external call Hooks ****************/
#ifdef SHOW_FAN
/********************************************************************
* FUNCTION show_fan
*
* INPUTS:
* server_name == the server name.
* rpc == RPC method for the show command
* line == CLI input in progress
* session_name == the current session name.
* valset == value set to check if not NULL
* mode == HELP_MODE_NONE, HELP_MODE_BRIEF, HELP_MODE_NORMAL,
* HELP_MODE_DETAIL
* cookie == context pointer (may be null)
* RETURNS:
* status
*********************************************************************/
static status_t
show_fan (
const xmlChar *server_name,
obj_template_t *rpc,
const xmlChar *line,
const xmlChar *session_name,
val_value_t *valset,
help_mode_t mode,
void *cookie)
{
/* parms not used */
(void)server_name;
(void)rpc;
(void)line;
(void)session_name;
(void)cookie;
/* get the fan number
* yangcli returns a union type as a string!
*/
const xmlChar *fan_num = (const xmlChar *)"1";
val_value_t *fanval = val_find_child(valset, MODNAME, FAN);
if (fanval) {
if (VAL_TYPE(fanval) == NCX_BT_STRING) {
if (!val_all_whitespace(VAL_STR(fanval))) {
/* fan_num should be a valid number string */
fan_num = VAL_STR(fanval);
}
} else {
// some sort of error
;
}
} // else error mandatory parm
/* get the value, there is no value to get for 'empty' */
val_value_t *diagval =
val_find_child(valset, MODNAME, DIAGNOSTICS);
/* print banner for fan */
log_write("\nReport for Fan %s", fan_num);
log_write("\n put fan status here...");
if (mode != HELP_MODE_BRIEF) {
/* only normal of full modes print diagnostics */
log_write("\n put more fan status here...");
if (mode == HELP_MODE_FULL) {
log_write("\n put even more fan status here...");
}
if (diagval) {
/* print last diagnostics report */
log_write("\nLast Diagnostics Report for Fan %s:", fan_num);
}
}
log_write("\n");
server_cb_t *server_cb = get_default_server_cb();
if (server_cb == NULL) {
return ERR_NCX_OPERATION_FAILED;
}
session_cb_t *session_cb = get_cur_session_cb(server_cb);
if (session_cb == NULL) {
return ERR_NCX_OPERATION_FAILED;
}
if (!session_connected(session_cb)) {
/* cannot send commands to server */
return NO_ERR;
}
/* get data from the server */
xmlChar *getstring =
xml_strdup((const xmlChar *)"sget /modules-state/module-set-id");
if (!getstring) {
return ERR_INTERNAL_MEM;
}
status_t res =
conn_command(server_cb, session_cb, getstring, FALSE, FALSE);
if (res != NO_ERR) {
log_error("\nError: send %s failed %s",
getstring, get_error_string(res));
}
m__free(getstring);
getstring =
xml_strdup((const xmlChar *)"sget /netconf-state/sessions --nofill");
if (!getstring) {
return ERR_INTERNAL_MEM;
}
res = conn_command(server_cb, session_cb, getstring, FALSE, FALSE);
if (res != NO_ERR) {
log_error("\nError: send %s failed %s",
getstring, get_error_string(res));
}
m__free(getstring);
return res;
} /* show_fan */
#endif // SHOW_FAN
#ifdef SHOW_VER
/********************************************************************
* FUNCTION show_version
*
* INPUTS:
* server_name == the server name.
* rpc == RPC method for the show command
* line == CLI input in progress
* session_name == the current session name.
* valset == value set to check if not NULL
* mode == HELP_MODE_NONE, HELP_MODE_BRIEF, HELP_MODE_NORMAL,
* HELP_MODE_DETAIL
* cookie == context pointer (may be null)
* RETURNS:
* status
*********************************************************************/
static status_t
show_version (
const xmlChar *server_name,
obj_template_t *rpc,
const xmlChar *line,
const xmlChar *session_name,
val_value_t *valset,
help_mode_t mode,
void *cookie)
{
/* parms not used */
(void)server_name;
(void)rpc;
(void)line;
(void)session_name;
(void)cookie;
/* no input to get for <version> leaf
* just print version line
*/
log_write("\nExample Version: 10.1");
if (mode != HELP_MODE_BRIEF) {
/* only normal of full modes print diagnostics */
log_write("\n Release: A4");
if (mode == HELP_MODE_FULL) {
log_write("\n Firmware: R12.4.001");
}
}
log_write("\n");
return NO_ERR;
} /* show_version */
#endif // SHOW_VER
#ifdef TERM_API
/* example terminal output test API
*/
static boolean
term_api_test_fn (void *session_cb,
const char *command_name,
boolean reply_output)
{
/* current session control block if needed */
session_cb_t *cb = (session_cb_t *)session_cb;
(void)cb;
if (reply_output == FALSE) {
return FALSE;
}
if (!strcmp(command_name, "get") ||
!strcmp(command_name, "get-config")) {
return TRUE;
}
return FALSE;
} /* term_api_test_fn */
/* example terminal output API
* This API alters the command or server output so
* yangcli_term can process the More and Pipe commands
*/
static status_t
term_api_fn (void *session_cb,
const char *in_filespec,
const char *out_filespec)
{
/* current session control block if needed */
session_cb_t *cb = (session_cb_t *)session_cb;
(void)cb;
/* get file into a buffer
* this is just one way to process the input;
* a line-by-line approach could be used to save memory
*/
xmlChar *in_buff = NULL;
status_t res = ncx_file_to_buffer(in_filespec, &in_buff);
if (in_buff == NULL || res != NO_ERR) {
m__free(in_buff);
return res;
}
/* change all the '{' and '}' chars to spaces just
* as an example of altering the output
*/
xmlChar *p = in_buff;
while (*p) {
if (*p == '{' || *p == '}') {
*p = ' ';
}
p++;
}
/* write altered buffer out to a file */
res = ncx_buffer_to_file(out_filespec, in_buff);
m__free(in_buff);
return res;
} /* term_api_fn */
#endif // TERM_API
#ifdef EXAMPLE_CMD
/********************************************************************
* FUNCTION do_example_cmd (local RPC)
*
* Do Example Command
*
* INPUTS:
* server_cb == server control block to use
* session_cb == session control block to use
* rpc == RPC method for the example-cmd command
* line == CLI input in progress
* len == offset into line buffer to start parsing
*
* RETURNS:
* status
*********************************************************************/
static status_t
do_example_cmd (server_cb_t *server_cb,
session_cb_t *session_cb,
obj_template_t *rpc,
const xmlChar *line,
uint32 len)
{
(void)rpc;
status_t res = NO_ERR;
val_value_t *valset =
get_valset(server_cb, session_cb, rpc, &line[len], &res);
if (valset && (res == NO_ERR)) {
val_value_t *parm1 =
val_find_child(valset, MODNAME, (const xmlChar *)"parm1");
if (parm1) {
log_debug("\nGot parm1=%s", VAL_STR(parm1));
}
val_value_t *parm2 =
val_find_child(valset, MODNAME, (const xmlChar *)"parm2");
if (parm2) {
log_debug("\nGot parm2=%d", VAL_INT32(parm2));
}
/* do something with the parameters */
}
val_free_value(valset);
return res;
} /* do_example_cmd */
#endif // EXAMPLE_CMD
/**************** Required Show Library Hooks *******************/
/* show init callback
* init show call
* INPUTS: void
* RETURNS:
* status; error will abort startup
*/
extern "C" status_t yp_show_init (void)
{
status_t res = NO_ERR;
log_debug("\nyp_show init\n");
#ifdef TERM_API
ycli_register_term_callback(term_api_test_fn, term_api_fn);
#endif // TERM_API
#if defined(SHOW_FAN) || defined(SHOW_VER) || defined(EXAMPLE_CMD)
/*
* Example: load a fan module for show fan function.
*/
res = ncxmod_load_module(MODNAME,
NULL, // revision
NULL, // savedevQ
&mymod);
#endif // SHOW_FAN or SHOW_VER or EXAMPLE_CMD
/*
* Example: Register a show function with yangcli-pro
* module name: example-fan for example-fan.yang
* key word: fan
* function: show_fan
*/
if (res == NO_ERR) {
#ifdef SHOW_FAN
/* Create a cookie context if any or NULL */
void *cookie_show_fan = NULL;
ycli_show_extern_register_callbacks(MODNAME,
(const xmlChar *)"fan",
show_fan,
cookie_show_fan);
#endif // SHOW_FAN
#ifdef SHOW_VER
/* Create a cookie context if any or NULL */
void *cookie_show_ver = NULL;
ycli_show_extern_register_callbacks(MODNAME,
(const xmlChar *)"version",
show_version,
cookie_show_ver);
#endif // SHOW_VER
#ifdef EXAMPLE_CMD
server_cb_t *server_cb = get_default_server_cb();
if (server_cb == NULL){
res = ERR_NCX_NOT_FOUND;
} else {
res = register_command(server_cb,
MODNAME,
(const xmlChar *)"example-cmd",
do_example_cmd,
TRUE, // is_top_cmd
TRUE, // yangcli_ok
TRUE, // ypshell_ok
FALSE); // ypserver_ok (not used)
}
#endif // EXAMPLE_CMD
} else {
log_debug("\nyp_show_init: return ERROR\n");
}
return res;
} /* yp_show_init */
/* show cleanup callback
* this callback is invoked once during yancli_cleanup
*/
extern "C" void yp_show_cleanup (void)
{
log_debug("\nyp_show cleanup\n");
} /* yp_show_cleanup */
/* END example-show.c */