Inital commit
This commit is contained in:
parent
edc5e091bb
commit
d6e393ea58
145 changed files with 58117 additions and 0 deletions
134
apps/cli/Makefile.in
Normal file
134
apps/cli/Makefile.in
Normal file
|
|
@ -0,0 +1,134 @@
|
|||
#
|
||||
# Makefile
|
||||
#
|
||||
# Copyright (C) 2009-2016 Olof Hagsand and Benny Holmgren
|
||||
#
|
||||
# This file is part of CLICON.
|
||||
#
|
||||
# CLICON 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 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# CLICON 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 CLICON; see the file COPYING. If not, see
|
||||
# <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
#
|
||||
|
||||
VPATH = @srcdir@
|
||||
srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
CC = @CC@
|
||||
CFLAGS = @CFLAGS@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
|
||||
prefix = @prefix@
|
||||
datarootdir = @datarootdir@
|
||||
exec_prefix = @exec_prefix@
|
||||
bindir = @bindir@
|
||||
libdir = @libdir@
|
||||
mandir = @mandir@
|
||||
libexecdir = @libexecdir@
|
||||
localstatedir = @localstatedir@
|
||||
sysconfdir = @sysconfdir@
|
||||
includedir = @includedir@
|
||||
|
||||
SH_SUFFIX = @SH_SUFFIX@
|
||||
CLICON_MAJOR = @CLICON_VERSION_MAJOR@
|
||||
CLICON_MINOR = @CLICON_VERSION_MINOR@
|
||||
|
||||
# Use this clicon lib for linking
|
||||
CLICON_LIB = libclicon.so.$(CLICON_MAJOR).$(CLICON_MINOR)
|
||||
# Location of system plugins
|
||||
CLICON_CLI_SYSDIR = $(libdir)/clicon/plugins/cli
|
||||
|
||||
# For dependency. A little strange that we rely on it being built in the src dir
|
||||
# even though it may exist in $(libdir). But the new version may not have been installed yet.
|
||||
LIBDEPS = $(top_srcdir)/lib/src/$(CLICON_LIB)
|
||||
|
||||
LIBS = -L$(top_srcdir)/lib/src @LIBS@ -l:$(CLICON_LIB) -lpthread
|
||||
CPPFLAGS = @CPPFLAGS@ -fPIC
|
||||
INCLUDES = -I. -I$(top_srcdir)/lib -I$(top_srcdir)/include -I$(top_srcdir) @INCLUDES@
|
||||
|
||||
APPL = clicon_cli
|
||||
SRC = cli_main.c
|
||||
OBJS = $(SRC:.c=.o)
|
||||
|
||||
MYNAME = clicon_cli
|
||||
MYLIBLINK = lib$(MYNAME)$(SH_SUFFIX)
|
||||
MYLIB = $(MYLIBLINK).$(CLICON_MAJOR).$(CLICON_MINOR)
|
||||
MYLIBSO = $(MYLIBLINK).$(CLICON_MAJOR)
|
||||
|
||||
LIBSRC = cli_plugin.c cli_common.c cli_handle.c cli_generate.c
|
||||
LIBOBJS = $(LIBSRC:.c=.o)
|
||||
|
||||
all: $(MYLIB) $(APPL) test
|
||||
|
||||
clean:
|
||||
rm -f $(OBJS) $(LIBOBJS) *.core $(APPL) $(MYLIB) $(MYLIBSO) $(MYLIBLINK)
|
||||
|
||||
distclean: clean
|
||||
rm -f Makefile *~ .depend
|
||||
|
||||
# Put daemon in bin
|
||||
# Put other executables in libexec/
|
||||
# Also create a libexec/ directory for writeable/temporary files.
|
||||
# Put config file in etc/
|
||||
install: install-lib $(APPL)
|
||||
install -d $(DESTDIR)$(bindir)
|
||||
install $(APPL) $(DESTDIR)$(bindir)
|
||||
|
||||
install-lib: $(MYLIB)
|
||||
install -d $(DESTDIR)$(libdir)
|
||||
install $(MYLIB) $(DESTDIR)$(libdir)
|
||||
ln -sf $(MYLIB) $(DESTDIR)$(libdir)/$(MYLIBSO) # -l:libclicon_cli.so.2
|
||||
ln -sf $(MYLIBSO) $(DESTDIR)$(libdir)/$(MYLIBLINK) # -l:libclicon_cli.so
|
||||
install -d $(DESTDIR)$(libdir)/clicon/plugins/cli
|
||||
|
||||
install-include: clicon_cli.h clicon_cli_api.h
|
||||
install -d $(DESTDIR)$(includedir)/clicon
|
||||
install -m 644 $^ $(DESTDIR)$(includedir)/clicon
|
||||
|
||||
uninstall:
|
||||
rm -f $(bindir)/$(APPL)
|
||||
rm -f $(libdir)/$(MYLIB)
|
||||
rm -f $(includedir)/clicon/*
|
||||
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .c .o
|
||||
|
||||
.c.o:
|
||||
$(CC) $(INCLUDES) $(CPPFLAGS) -D__PROGRAM__=\"$(APPL)\" -DCLICON_CLI_SYSDIR=\"$(CLICON_CLI_SYSDIR)\" $(CFLAGS) -c $<
|
||||
|
||||
# Just link test programs
|
||||
test.c :
|
||||
echo "main(){}" > $@
|
||||
|
||||
test: test.c $(LIBOBJ)
|
||||
$(CC) $(INCLUDES) $(LDFLAGS) $< $(LIBOBJ) -L. -l:$(MYLIB) $(LIBS) -o $@
|
||||
|
||||
$(APPL): $(OBJS) $(MYLIBLINK) $(LIBDEPS)
|
||||
$(CC) $(LDFLAGS) $(OBJS) -L. -l:$(MYLIB) $(LIBS) -o $@
|
||||
|
||||
$(MYLIB) : $(LIBOBJS)
|
||||
$(CC) -shared -Wl,-soname,$(MYLIBSO) -o $@ $(LIBOBJS) $(LIBS) -Wl,-soname=$(MYLIBSO)
|
||||
|
||||
# link-name is needed for application linking, eg for clicon_cli and clicon_config
|
||||
$(MYLIBLINK) : $(MYLIB)
|
||||
# ln -sf $(MYLIB) $(MYLIBSO)
|
||||
# ln -sf $(MYLIB) $@
|
||||
|
||||
TAGS:
|
||||
find . -name '*.[chyl]' -print | etags -
|
||||
|
||||
depend:
|
||||
$(CC) $(DEPENDFLAGS) @DEFS@ $(INCLUDES) $(CFLAGS) -MM $(SRC) $(APPSRC) > .depend
|
||||
|
||||
#include .depend
|
||||
|
||||
1930
apps/cli/cli_common.c
Normal file
1930
apps/cli/cli_common.c
Normal file
File diff suppressed because it is too large
Load diff
33
apps/cli/cli_common.h
Normal file
33
apps/cli/cli_common.h
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
*
|
||||
Copyright (C) 2009-2016 Olof Hagsand and Benny Holmgren
|
||||
|
||||
This file is part of CLICON.
|
||||
|
||||
CLICON 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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
CLICON 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 CLICON; see the file COPYING. If not, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _CLI_COMMON_H_
|
||||
#define _CLI_COMMON_H_
|
||||
|
||||
void cli_signal_block(clicon_handle h);
|
||||
void cli_signal_unblock(clicon_handle h);
|
||||
|
||||
/* If you do not find a function here it may be in clicon_cli_api.h which is
|
||||
the external API */
|
||||
|
||||
#endif /* _CLI_COMMON_H_ */
|
||||
689
apps/cli/cli_generate.c
Normal file
689
apps/cli/cli_generate.c
Normal file
|
|
@ -0,0 +1,689 @@
|
|||
/*
|
||||
*
|
||||
Copyright (C) 2009-2016 Olof Hagsand and Benny Holmgren
|
||||
|
||||
This file is part of CLICON.
|
||||
|
||||
CLICON 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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
CLICON 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 CLICON; see the file COPYING. If not, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
|
||||
*
|
||||
* Translation between database specs
|
||||
* dbspec_key yang_spec CLIgen parse_tree
|
||||
* +-------------+ key2yang +-------------+ yang2cli +-------------+
|
||||
* | keyspec | -------------> | | ------------> | cli |
|
||||
* | A[].B !$a | yang2key | list{key A;}| | syntax |
|
||||
* +-------------+ <------------ +-------------+ +-------------+
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "clicon_config.h" /* generated by config & autoconf */
|
||||
#endif
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
|
||||
/* cligen */
|
||||
#include <cligen/cligen.h>
|
||||
|
||||
/* clicon */
|
||||
#include <clicon/clicon.h>
|
||||
|
||||
#include "clicon_cli_api.h"
|
||||
#include "cli_plugin.h"
|
||||
#include "cli_generate.h"
|
||||
|
||||
/* This is the default callback function. But this is typically overwritten */
|
||||
#define GENERATE_CALLBACK "cli_set"
|
||||
|
||||
/* variable expand function */
|
||||
#define GENERATE_EXPAND_LVEC "expand_dbvar_auto"
|
||||
#define GENERATE_EXPAND_XMLDB "expand_dbvar_dbxml"
|
||||
|
||||
/*=====================================================================
|
||||
* YANG generate CLI
|
||||
*=====================================================================*/
|
||||
#if 0 /* examples/ntp */
|
||||
ntp("Network Time Protocol"),cli_set("ntp");{
|
||||
logging("Configure NTP message logging"),cli_set("ntp.logging");{
|
||||
status (<status:bool>),cli_set("ntp.logging $status:bool");
|
||||
}
|
||||
server("Configure NTP Server") (<ipv4addr:ipv4addr>("IPv4 address of peer")),cli_set("ntp.server[] $!ipv4addr:ipv4addr");
|
||||
}
|
||||
#endif
|
||||
#if 0 /* examples/datamodel */
|
||||
|
||||
WITH COMPLETION:
|
||||
a (<x:number>|<x:number expand_dbvar_auto("candidate a[] $!x")>),cli_set("a[] $!x");{
|
||||
b,cli_set("a[].b $!x");{
|
||||
y (<y:string>|<y:string expand_dbvar_auto("candidate a[].b $!x $y")>),cli_set("a[].b $!x $y");
|
||||
}
|
||||
z (<z:string>|<z:string expand_dbvar_auto("candidate a[] $!x $z")>),cli_set("a[] $!x $z");
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_CLIGEN_MAX2STR /* XXX cligen 3.6 feature */
|
||||
|
||||
/*! Print max value of a CLIgen variable type as string
|
||||
* @param[in] type CLIgen variable type
|
||||
* @param[out] str Max value printed in this string
|
||||
* @param[in] size Length of 'str'
|
||||
* @retval len How many bytes printed
|
||||
* @see cvtype_max2str_dup
|
||||
* You can use str=NULL to get the expected length.
|
||||
* The number of (potentially if str=NULL) written bytes is returned.
|
||||
*/
|
||||
static int
|
||||
cvtype_max2str(enum cv_type type, char *str, size_t size)
|
||||
{
|
||||
int len = 0;
|
||||
|
||||
switch (type){
|
||||
case CGV_INT8:
|
||||
len = snprintf(str, size, "%" PRId8, INT8_MAX);
|
||||
break;
|
||||
case CGV_INT16:
|
||||
len = snprintf(str, size, "%" PRId16, INT16_MAX);
|
||||
break;
|
||||
case CGV_INT32:
|
||||
len = snprintf(str, size, "%" PRId32, INT32_MAX);
|
||||
break;
|
||||
case CGV_INT64:
|
||||
len = snprintf(str, size, "%" PRId64, INT64_MAX);
|
||||
break;
|
||||
case CGV_UINT8:
|
||||
len = snprintf(str, size, "%" PRIu8, UINT8_MAX);
|
||||
break;
|
||||
case CGV_UINT16:
|
||||
len = snprintf(str, size, "%" PRIu16, UINT16_MAX);
|
||||
break;
|
||||
case CGV_UINT32:
|
||||
len = snprintf(str, size, "%" PRIu32, UINT32_MAX);
|
||||
break;
|
||||
case CGV_UINT64:
|
||||
len = snprintf(str, size, "%" PRIu64, UINT64_MAX);
|
||||
break;
|
||||
case CGV_DEC64:
|
||||
len = snprintf(str, size, "%" PRId64 ".0", INT64_MAX);
|
||||
break;
|
||||
case CGV_BOOL:
|
||||
len = snprintf(str, size, "true");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
/*! Print max value of a CLIgen variable type as string
|
||||
*
|
||||
* The string should be freed after use.
|
||||
* @param[in] type CLIgen variable type
|
||||
* @retval str Malloced string containing value. Should be freed after use.
|
||||
* @see cvtype_max2str
|
||||
*/
|
||||
static char *
|
||||
cvtype_max2str_dup(enum cv_type type)
|
||||
{
|
||||
int len;
|
||||
char *str;
|
||||
|
||||
if ((len = cvtype_max2str(type, NULL, 0)) < 0)
|
||||
return NULL;
|
||||
if ((str = (char *)malloc (len+1)) == NULL)
|
||||
return NULL;
|
||||
memset (str, '\0', len+1);
|
||||
if ((cvtype_max2str(type, str, len+1)) < 0){
|
||||
free(str);
|
||||
return NULL;
|
||||
}
|
||||
return str;
|
||||
}
|
||||
#endif /* HAVE_CLIGEN_MAX2STR */
|
||||
|
||||
/*! Create cligen variable expand entry with xmlkey format string as argument
|
||||
* @param[in] h clicon handle
|
||||
* @param[in] ys yang_stmt of the node at hand
|
||||
* @param[in] cvtype Type of the cligen variable
|
||||
* @param[in] cb0 The string where the result format string is inserted.
|
||||
* @see expand_dbvar_dbxml This is where the expand string is used
|
||||
*/
|
||||
static int
|
||||
cli_expand_var_generate(clicon_handle h,
|
||||
yang_stmt *ys,
|
||||
enum cv_type cvtype,
|
||||
cbuf *cb0)
|
||||
{
|
||||
int retval = -1;
|
||||
char *xkfmt = NULL;
|
||||
|
||||
if (yang2xmlkeyfmt(ys, &xkfmt) < 0)
|
||||
goto done;
|
||||
cprintf(cb0, "|<%s:%s %s(\"candidate %s\")>",
|
||||
ys->ys_argument,
|
||||
cv_type2str(cvtype),
|
||||
GENERATE_EXPAND_XMLDB,
|
||||
xkfmt);
|
||||
retval = 0;
|
||||
done:
|
||||
if (xkfmt)
|
||||
free(xkfmt);
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*! Create callback with xmlkey format string as argument
|
||||
* @param[in] h clicon handle
|
||||
* @param[in] ys yang_stmt of the node at hand
|
||||
* @param[in] cb0 The string where the result format string is inserted.
|
||||
* @see cli_dbxml This is where the xmlkeyfmt string is used
|
||||
*/
|
||||
static int
|
||||
cli_callback_generate(clicon_handle h,
|
||||
yang_stmt *ys,
|
||||
cbuf *cb0)
|
||||
{
|
||||
int retval = -1;
|
||||
char *xkfmt = NULL;
|
||||
|
||||
if (yang2xmlkeyfmt(ys, &xkfmt) < 0)
|
||||
goto done;
|
||||
cprintf(cb0, ",%s(\"%s\")", GENERATE_CALLBACK, xkfmt);
|
||||
retval = 0;
|
||||
done:
|
||||
if (xkfmt)
|
||||
free(xkfmt);
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int yang2cli_stmt(clicon_handle h, yang_stmt *ys,
|
||||
cbuf *cb0,
|
||||
enum genmodel_type gt,
|
||||
int level);
|
||||
|
||||
/*
|
||||
* Check for completion (of already existent values), ranges (eg range[min:max]) and
|
||||
* patterns, (eg regexp:"[0.9]*").
|
||||
*/
|
||||
static int
|
||||
yang2cli_var_sub(clicon_handle h,
|
||||
yang_stmt *ys,
|
||||
cbuf *cb0,
|
||||
char *description,
|
||||
enum cv_type cvtype,
|
||||
yang_stmt *ytype, /* resolved type */
|
||||
int options,
|
||||
cg_var *mincv,
|
||||
cg_var *maxcv,
|
||||
char *pattern,
|
||||
uint8_t fraction_digits
|
||||
)
|
||||
{
|
||||
int retval = -1;
|
||||
char *type;
|
||||
char *r;
|
||||
yang_stmt *yi = NULL;
|
||||
int i = 0;
|
||||
char *cvtypestr;
|
||||
int completion;
|
||||
|
||||
/* enumeration already gives completion */
|
||||
if (cvtype == CGV_VOID){
|
||||
retval = 0;
|
||||
goto done;
|
||||
}
|
||||
type = ytype?ytype->ys_argument:NULL;
|
||||
if (type)
|
||||
completion = clicon_cli_genmodel_completion(h) &&
|
||||
strcmp(type, "enumeration") != 0 &&
|
||||
strcmp(type, "bits") != 0;
|
||||
else
|
||||
completion = clicon_cli_genmodel_completion(h);
|
||||
|
||||
if (completion)
|
||||
cprintf(cb0, "(");
|
||||
cvtypestr = cv_type2str(cvtype);
|
||||
cprintf(cb0, "<%s:%s", ys->ys_argument, cvtypestr);
|
||||
#if 0
|
||||
if (type && (strcmp(type, "identityref") == 0)){
|
||||
yang_stmt *ybase;
|
||||
if ((ybase = yang_find((yang_node*)ytype, Y_BASE, NULL)) != NULL){
|
||||
cprintf(cb0, " choice:");
|
||||
i = 0;
|
||||
/* for every found identity derived from base-type , do: */
|
||||
{
|
||||
if (yi->ys_keyword != Y_ENUM && yi->ys_keyword != Y_BIT)
|
||||
continue;
|
||||
if (i)
|
||||
cprintf(cb0, "|");
|
||||
cprintf(cb0, "%s", yi->ys_argument);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
if (type && (strcmp(type, "enumeration") == 0 || strcmp(type, "bits") == 0)){
|
||||
cprintf(cb0, " choice:");
|
||||
i = 0;
|
||||
while ((yi = yn_each((yang_node*)ytype, yi)) != NULL){
|
||||
if (yi->ys_keyword != Y_ENUM && yi->ys_keyword != Y_BIT)
|
||||
continue;
|
||||
if (i)
|
||||
cprintf(cb0, "|");
|
||||
cprintf(cb0, "%s", yi->ys_argument);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
if (options & YANG_OPTIONS_FRACTION_DIGITS)
|
||||
cprintf(cb0, " fraction-digits:%u", fraction_digits);
|
||||
if (options & (YANG_OPTIONS_RANGE|YANG_OPTIONS_LENGTH)){
|
||||
cprintf(cb0, " %s[", (options&YANG_OPTIONS_RANGE)?"range":"length");
|
||||
if (mincv){
|
||||
if ((r = cv2str_dup(mincv)) == NULL){
|
||||
clicon_err(OE_UNIX, errno, "cv2str_dup");
|
||||
goto done;
|
||||
}
|
||||
cprintf(cb0, "%s:", r);
|
||||
free(r);
|
||||
}
|
||||
if (maxcv != NULL){
|
||||
if ((r = cv2str_dup(maxcv)) == NULL){
|
||||
clicon_err(OE_UNIX, errno, "cv2str_dup");
|
||||
goto done;
|
||||
}
|
||||
|
||||
}
|
||||
else{ /* Cligen does not have 'max' keyword in range so need to find actual
|
||||
max value of type if yang range expression is 0..max */
|
||||
if ((r = cvtype_max2str_dup(cvtype)) == NULL){
|
||||
clicon_err(OE_UNIX, errno, "cvtype_max2str");
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
cprintf(cb0, "%s]", r);
|
||||
free(r);
|
||||
}
|
||||
if (options & YANG_OPTIONS_PATTERN)
|
||||
cprintf(cb0, " regexp:\"%s\"", pattern);
|
||||
|
||||
cprintf(cb0, ">");
|
||||
if (description)
|
||||
cprintf(cb0, "(\"%s\")", description);
|
||||
if (completion){
|
||||
if (cli_expand_var_generate(h, ys, cvtype, cb0) < 0)
|
||||
goto done;
|
||||
if (description)
|
||||
cprintf(cb0, "(\"%s\")", description);
|
||||
cprintf(cb0, ")");
|
||||
}
|
||||
retval = 0;
|
||||
done:
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*! Translate a yang leaf to cligen variable
|
||||
* Make a type lookup and complete a cligen variable expression such as <a:string>.
|
||||
* One complication is yang union, that needs a recursion since it consists of sub-types.
|
||||
* eg type union{ type int32; type string } --> (<x:int32>| <x:string>)
|
||||
*/
|
||||
static int
|
||||
yang2cli_var(clicon_handle h,
|
||||
yang_stmt *ys,
|
||||
cbuf *cb0,
|
||||
char *description)
|
||||
{
|
||||
int retval = -1;
|
||||
char *type; /* orig type */
|
||||
yang_stmt *yrestype; /* resolved type */
|
||||
char *restype; /* resolved type */
|
||||
cg_var *mincv = NULL;
|
||||
cg_var *maxcv = NULL;
|
||||
char *pattern = NULL;
|
||||
yang_stmt *yt = NULL;
|
||||
yang_stmt *yrt;
|
||||
uint8_t fraction_digits = 0;
|
||||
enum cv_type cvtype;
|
||||
int options = 0;
|
||||
int i;
|
||||
|
||||
if (yang_type_get(ys, &type, &yrestype,
|
||||
&options, &mincv, &maxcv, &pattern, &fraction_digits) < 0)
|
||||
goto done;
|
||||
restype = yrestype?yrestype->ys_argument:NULL;
|
||||
if (clicon_type2cv(type, restype, &cvtype) < 0)
|
||||
goto done;
|
||||
/* Note restype can be NULL here for example with unresolved hardcoded uuid */
|
||||
if (restype && strcmp(restype, "union") == 0){
|
||||
/* Union: loop over resolved type's sub-types */
|
||||
cprintf(cb0, "(");
|
||||
yt = NULL;
|
||||
i = 0;
|
||||
while ((yt = yn_each((yang_node*)yrestype, yt)) != NULL){
|
||||
if (yt->ys_keyword != Y_TYPE)
|
||||
continue;
|
||||
if (i++)
|
||||
cprintf(cb0, "|");
|
||||
if (yang_type_resolve(ys, yt, &yrt,
|
||||
&options, &mincv, &maxcv, &pattern, &fraction_digits) < 0)
|
||||
goto done;
|
||||
restype = yrt?yrt->ys_argument:NULL;
|
||||
if (clicon_type2cv(type, restype, &cvtype) < 0)
|
||||
goto done;
|
||||
if ((retval = yang2cli_var_sub(h, ys, cb0, description, cvtype, yrt,
|
||||
options, mincv, maxcv, pattern, fraction_digits)) < 0)
|
||||
|
||||
goto done;
|
||||
|
||||
}
|
||||
cprintf(cb0, ")");
|
||||
}
|
||||
else
|
||||
if ((retval = yang2cli_var_sub(h, ys, cb0, description, cvtype, yrestype,
|
||||
options, mincv, maxcv, pattern, fraction_digits)) < 0)
|
||||
goto done;
|
||||
|
||||
retval = 0;
|
||||
done:
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @param[in] h Clicon handle
|
||||
* @param[in] callback If set, include a "; cli_set()" callback, otherwise not.
|
||||
*/
|
||||
static int
|
||||
yang2cli_leaf(clicon_handle h,
|
||||
yang_stmt *ys,
|
||||
cbuf *cbuf,
|
||||
enum genmodel_type gt,
|
||||
int level,
|
||||
int callback)
|
||||
{
|
||||
yang_stmt *yd; /* description */
|
||||
int retval = -1;
|
||||
char *description = NULL;
|
||||
|
||||
/* description */
|
||||
if ((yd = yang_find((yang_node*)ys, Y_DESCRIPTION, NULL)) != NULL)
|
||||
description = yd->ys_argument;
|
||||
cprintf(cbuf, "%*s", level*3, "");
|
||||
if (gt == GT_VARS|| gt == GT_ALL){
|
||||
cprintf(cbuf, "%s", ys->ys_argument);
|
||||
if (yd != NULL)
|
||||
cprintf(cbuf, "(\"%s\")", yd->ys_argument);
|
||||
cprintf(cbuf, " ");
|
||||
yang2cli_var(h, ys, cbuf, description);
|
||||
}
|
||||
else
|
||||
yang2cli_var(h, ys, cbuf, description);
|
||||
if (callback){
|
||||
if (cli_callback_generate(h, ys, cbuf) < 0)
|
||||
goto done;
|
||||
cprintf(cbuf, ";\n");
|
||||
}
|
||||
|
||||
retval = 0;
|
||||
done:
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
yang2cli_container(clicon_handle h,
|
||||
yang_stmt *ys,
|
||||
cbuf *cbuf,
|
||||
enum genmodel_type gt,
|
||||
int level)
|
||||
{
|
||||
yang_stmt *yc;
|
||||
yang_stmt *yd;
|
||||
int i;
|
||||
int retval = -1;
|
||||
|
||||
cprintf(cbuf, "%*s%s", level*3, "", ys->ys_argument);
|
||||
if ((yd = yang_find((yang_node*)ys, Y_DESCRIPTION, NULL)) != NULL)
|
||||
cprintf(cbuf, "(\"%s\")", yd->ys_argument);
|
||||
if (cli_callback_generate(h, ys, cbuf) < 0)
|
||||
goto done;
|
||||
cprintf(cbuf, ";{\n");
|
||||
for (i=0; i<ys->ys_len; i++)
|
||||
if ((yc = ys->ys_stmt[i]) != NULL)
|
||||
if (yang2cli_stmt(h, yc, cbuf, gt, level+1) < 0)
|
||||
goto done;
|
||||
cprintf(cbuf, "%*s}\n", level*3, "");
|
||||
retval = 0;
|
||||
done:
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int
|
||||
yang2cli_list(clicon_handle h,
|
||||
yang_stmt *ys,
|
||||
cbuf *cbuf,
|
||||
enum genmodel_type gt,
|
||||
int level)
|
||||
{
|
||||
yang_stmt *yc;
|
||||
yang_stmt *yd;
|
||||
yang_stmt *ykey;
|
||||
yang_stmt *yleaf;
|
||||
int i;
|
||||
cg_var *cvi;
|
||||
char *keyname;
|
||||
cvec *cvk = NULL; /* vector of index keys */
|
||||
int retval = -1;
|
||||
|
||||
cprintf(cbuf, "%*s%s", level*3, "", ys->ys_argument);
|
||||
if ((yd = yang_find((yang_node*)ys, Y_DESCRIPTION, NULL)) != NULL)
|
||||
cprintf(cbuf, "(\"%s\")", yd->ys_argument);
|
||||
/* Loop over all key variables */
|
||||
if ((ykey = yang_find((yang_node*)ys, Y_KEY, NULL)) == NULL){
|
||||
clicon_err(OE_XML, 0, "List statement \"%s\" has no key", ys->ys_argument);
|
||||
goto done;
|
||||
}
|
||||
/* The value is a list of keys: <key>[ <key>]* */
|
||||
if ((cvk = yang_arg2cvec(ykey, " ")) == NULL)
|
||||
goto done;
|
||||
cvi = NULL;
|
||||
/* Iterate over individual keys */
|
||||
while ((cvi = cvec_each(cvk, cvi)) != NULL) {
|
||||
keyname = cv_string_get(cvi);
|
||||
if ((yleaf = yang_find((yang_node*)ys, Y_LEAF, keyname)) == NULL){
|
||||
clicon_err(OE_XML, 0, "List statement \"%s\" has no key leaf \"%s\"",
|
||||
ys->ys_argument, keyname);
|
||||
goto done;
|
||||
}
|
||||
/* Print key variable now, and skip it in loop below
|
||||
Note, only print callback on last statement
|
||||
*/
|
||||
if (yang2cli_leaf(h, yleaf, cbuf, gt==GT_VARS?GT_NONE:gt, level+1,
|
||||
cvec_next(cvk, cvi)?0:1) < 0)
|
||||
goto done;
|
||||
}
|
||||
|
||||
cprintf(cbuf, "{\n");
|
||||
for (i=0; i<ys->ys_len; i++)
|
||||
if ((yc = ys->ys_stmt[i]) != NULL){
|
||||
/* cvk is a cvec of strings containing variable names
|
||||
yc is a leaf that may match one of the values of cvk.
|
||||
*/
|
||||
cvi = NULL;
|
||||
while ((cvi = cvec_each(cvk, cvi)) != NULL) {
|
||||
keyname = cv_string_get(cvi);
|
||||
if (strcmp(keyname, yc->ys_argument) == 0)
|
||||
break;
|
||||
}
|
||||
if (cvi != NULL)
|
||||
continue;
|
||||
if (yang2cli_stmt(h, yc, cbuf, gt, level+1) < 0)
|
||||
goto done;
|
||||
}
|
||||
cprintf(cbuf, "%*s}\n", level*3, "");
|
||||
retval = 0;
|
||||
done:
|
||||
if (cvk)
|
||||
cvec_free(cvk);
|
||||
return retval;
|
||||
}
|
||||
/*! Generate cli code for yang choice statement
|
||||
|
||||
Example:
|
||||
choice interface-type {
|
||||
container ethernet { ... }
|
||||
container fddi { ... }
|
||||
}
|
||||
@Note Removes 'meta-syntax' from cli syntax. They are not shown when xml is
|
||||
translated to cli. and therefore input-syntax != output syntax. Which is bad
|
||||
*/
|
||||
static int
|
||||
yang2cli_choice(clicon_handle h,
|
||||
yang_stmt *ys,
|
||||
cbuf *cbuf,
|
||||
enum genmodel_type gt,
|
||||
int level)
|
||||
{
|
||||
int retval = -1;
|
||||
yang_stmt *yc;
|
||||
int i;
|
||||
|
||||
for (i=0; i<ys->ys_len; i++)
|
||||
if ((yc = ys->ys_stmt[i]) != NULL){
|
||||
switch (yc->ys_keyword){
|
||||
case Y_CASE:
|
||||
if (yang2cli_stmt(h, yc, cbuf, gt, level+2) < 0)
|
||||
goto done;
|
||||
break;
|
||||
case Y_CONTAINER:
|
||||
case Y_LEAF:
|
||||
case Y_LEAF_LIST:
|
||||
case Y_LIST:
|
||||
default:
|
||||
if (yang2cli_stmt(h, yc, cbuf, gt, level+1) < 0)
|
||||
goto done;
|
||||
break;
|
||||
}
|
||||
}
|
||||
retval = 0;
|
||||
done:
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
/*! Translate yang-stmt to CLIgen syntax.
|
||||
*/
|
||||
static int
|
||||
yang2cli_stmt(clicon_handle h,
|
||||
yang_stmt *ys,
|
||||
cbuf *cbuf,
|
||||
enum genmodel_type gt,
|
||||
int level /* indentation level for pretty-print */
|
||||
)
|
||||
{
|
||||
yang_stmt *yc;
|
||||
int retval = -1;
|
||||
int i;
|
||||
|
||||
if (yang_config(ys)){
|
||||
switch (ys->ys_keyword){
|
||||
case Y_GROUPING:
|
||||
case Y_RPC:
|
||||
case Y_AUGMENT:
|
||||
return 0;
|
||||
break;
|
||||
case Y_CONTAINER:
|
||||
if (yang2cli_container(h, ys, cbuf, gt, level) < 0)
|
||||
goto done;
|
||||
break;
|
||||
case Y_LIST:
|
||||
if (yang2cli_list(h, ys, cbuf, gt, level) < 0)
|
||||
goto done;
|
||||
break;
|
||||
case Y_CHOICE:
|
||||
if (yang2cli_choice(h, ys, cbuf, gt, level) < 0)
|
||||
goto done;
|
||||
break;
|
||||
case Y_LEAF_LIST:
|
||||
case Y_LEAF:
|
||||
if (yang2cli_leaf(h, ys, cbuf, gt, level, 1) < 0)
|
||||
goto done;
|
||||
break;
|
||||
default:
|
||||
for (i=0; i<ys->ys_len; i++)
|
||||
if ((yc = ys->ys_stmt[i]) != NULL)
|
||||
if (yang2cli_stmt(h, yc, cbuf, gt, level+1) < 0)
|
||||
goto done;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
retval = 0;
|
||||
done:
|
||||
return retval;
|
||||
|
||||
}
|
||||
|
||||
/*! Translate from a yang specification into a CLIgen syntax.
|
||||
*
|
||||
* Print a CLIgen syntax to cbuf string, then parse it.
|
||||
* @param gt - how to generate CLI:
|
||||
* VARS: generate keywords for regular vars only not index
|
||||
* ALL: generate keywords for all variables including index
|
||||
*/
|
||||
int
|
||||
yang2cli(clicon_handle h,
|
||||
yang_spec *yspec,
|
||||
parse_tree *ptnew,
|
||||
enum genmodel_type gt)
|
||||
{
|
||||
cbuf *cbuf;
|
||||
int i;
|
||||
int retval = -1;
|
||||
yang_stmt *ymod = NULL;
|
||||
cvec *globals; /* global variables from syntax */
|
||||
|
||||
if ((cbuf = cbuf_new()) == NULL){
|
||||
clicon_err(OE_XML, errno, "%s: cbuf_new", __FUNCTION__);
|
||||
goto done;
|
||||
}
|
||||
/* Traverse YANG specification: loop through statements */
|
||||
for (i=0; i<yspec->yp_len; i++)
|
||||
if ((ymod = yspec->yp_stmt[i]) != NULL){
|
||||
if (yang2cli_stmt(h, ymod, cbuf, gt, 0) < 0)
|
||||
goto done;
|
||||
}
|
||||
clicon_debug(1, "%s: buf\n%s\n", __FUNCTION__, cbuf_get(cbuf));
|
||||
/* Parse the buffer using cligen parser. XXX why this?*/
|
||||
if ((globals = cvec_new(0)) == NULL)
|
||||
goto done;
|
||||
/* load cli syntax */
|
||||
if (cligen_parse_str(cli_cligen(h), cbuf_get(cbuf),
|
||||
"yang2cli", ptnew, globals) < 0)
|
||||
goto done;
|
||||
cvec_free(globals);
|
||||
/* handle=NULL for global namespace, this means expand callbacks must be in
|
||||
CLICON namespace, not in a cli frontend plugin. */
|
||||
if (cligen_expand_str2fn(*ptnew, expand_str2fn, NULL) < 0)
|
||||
goto done;
|
||||
retval = 0;
|
||||
done:
|
||||
cbuf_free(cbuf);
|
||||
return retval;
|
||||
}
|
||||
32
apps/cli/cli_generate.h
Normal file
32
apps/cli/cli_generate.h
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
*
|
||||
Copyright (C) 2009-2016 Olof Hagsand and Benny Holmgren
|
||||
|
||||
This file is part of CLICON.
|
||||
|
||||
CLICON 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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
CLICON 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 CLICON; see the file COPYING. If not, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef _CLI_GENERATE_H_
|
||||
#define _CLI_GENERATE_H_
|
||||
|
||||
/*
|
||||
* Prototypes
|
||||
*/
|
||||
int yang2cli(clicon_handle h, yang_spec *yspec, parse_tree *ptnew,
|
||||
enum genmodel_type gt);
|
||||
|
||||
#endif /* _CLI_GENERATE_H_ */
|
||||
295
apps/cli/cli_handle.c
Normal file
295
apps/cli/cli_handle.c
Normal file
|
|
@ -0,0 +1,295 @@
|
|||
/*
|
||||
*
|
||||
Copyright (C) 2009-2016 Olof Hagsand and Benny Holmgren
|
||||
|
||||
This file is part of CLICON.
|
||||
|
||||
CLICON 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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
CLICON 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 CLICON; see the file COPYING. If not, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "clicon_config.h" /* generated by config & autoconf */
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <stdarg.h>
|
||||
#include <syslog.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
#include <dlfcn.h>
|
||||
#include <dirent.h>
|
||||
#include <grp.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/param.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
/* cligen */
|
||||
#include <cligen/cligen.h>
|
||||
|
||||
/* clicon */
|
||||
#include <clicon/clicon.h>
|
||||
|
||||
#include "clicon_cli_api.h"
|
||||
#include "cli_plugin.h"
|
||||
#include "cli_handle.h"
|
||||
|
||||
#define CLICON_MAGIC 0x99aafabe
|
||||
|
||||
#define handle(h) (assert(clicon_handle_check(h)==0),(struct cli_handle *)(h))
|
||||
#define cligen(h) (handle(h)->cl_cligen)
|
||||
|
||||
/*
|
||||
* cli_handle
|
||||
* first part of this is header, same for clicon_handle and config_handle.
|
||||
* Access functions for common fields are found in clicon lib: clicon_options.[ch]
|
||||
* This file should only contain access functions for the _specific_
|
||||
* entries in the struct below.
|
||||
*/
|
||||
struct cli_handle {
|
||||
int cl_magic; /* magic (HDR)*/
|
||||
clicon_hash_t *cl_copt; /* clicon option list (HDR) */
|
||||
clicon_hash_t *cl_data; /* internal clicon data (HDR) */
|
||||
/* ------ end of common handle ------ */
|
||||
cligen_handle cl_cligen; /* cligen handle */
|
||||
|
||||
int cl_send2backend; /* Send changes to configuration daemon */
|
||||
enum candidate_db_type cl_candidate_type;
|
||||
cli_syntax_t *cl_stx; /* syntax structure */
|
||||
|
||||
};
|
||||
|
||||
/*
|
||||
* cli_handle_init
|
||||
* returns a clicon handle for other CLICON API calls
|
||||
*/
|
||||
clicon_handle
|
||||
cli_handle_init(void)
|
||||
{
|
||||
struct cli_handle *cl;
|
||||
cligen_handle clih = NULL;
|
||||
clicon_handle h = NULL;
|
||||
|
||||
if ((cl = (struct cli_handle *)clicon_handle_init0(sizeof(struct cli_handle))) == NULL)
|
||||
return NULL;
|
||||
|
||||
if ((clih = cligen_init()) == NULL){
|
||||
clicon_handle_exit((clicon_handle)cl);
|
||||
goto done;
|
||||
}
|
||||
cligen_userhandle_set(clih, cl);
|
||||
cl->cl_cligen = clih;
|
||||
cl->cl_candidate_type = CANDIDATE_DB_SHARED;
|
||||
h = (clicon_handle)cl;
|
||||
done:
|
||||
return h;
|
||||
}
|
||||
|
||||
/*
|
||||
* cli_handle_exit
|
||||
* frees clicon handle
|
||||
*/
|
||||
int
|
||||
cli_handle_exit(clicon_handle h)
|
||||
{
|
||||
cligen_handle ch = cligen(h);
|
||||
|
||||
clicon_handle_exit(h); /* frees h and options */
|
||||
cligen_exit(ch);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------
|
||||
* cli-specific handle access functions
|
||||
*----------------------------------------------------------*/
|
||||
/*! Send changes to configuration daemon or let client handle it itself. Default is 1 */
|
||||
int
|
||||
cli_set_send2backend(clicon_handle h, int send2backend)
|
||||
{
|
||||
struct cli_handle *cl = handle(h);
|
||||
|
||||
cl->cl_send2backend = send2backend;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*! Get status of whether to send changes to configuration daemon. */
|
||||
int
|
||||
cli_send2backend(clicon_handle h)
|
||||
{
|
||||
struct cli_handle *cl = handle(h);
|
||||
|
||||
return cl->cl_send2backend;
|
||||
}
|
||||
|
||||
enum candidate_db_type
|
||||
cli_candidate_type(clicon_handle h)
|
||||
{
|
||||
struct cli_handle *cl = handle(h);
|
||||
|
||||
return cl->cl_candidate_type;
|
||||
}
|
||||
|
||||
int
|
||||
cli_set_candidate_type(clicon_handle h, enum candidate_db_type type)
|
||||
{
|
||||
struct cli_handle *cl = handle(h);
|
||||
|
||||
cl->cl_candidate_type = type;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Current syntax-group */
|
||||
cli_syntax_t *
|
||||
cli_syntax(clicon_handle h)
|
||||
{
|
||||
struct cli_handle *cl = handle(h);
|
||||
return cl->cl_stx;
|
||||
}
|
||||
|
||||
int
|
||||
cli_syntax_set(clicon_handle h, cli_syntax_t *stx)
|
||||
{
|
||||
struct cli_handle *cl = handle(h);
|
||||
cl->cl_stx = stx;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------
|
||||
* cligen access functions
|
||||
*----------------------------------------------------------*/
|
||||
cligen_handle
|
||||
cli_cligen(clicon_handle h)
|
||||
{
|
||||
return cligen(h);
|
||||
}
|
||||
|
||||
/*
|
||||
* cli_interactive and clicon_eval
|
||||
*/
|
||||
int
|
||||
cli_exiting(clicon_handle h)
|
||||
{
|
||||
cligen_handle ch = cligen(h);
|
||||
|
||||
return cligen_exiting(ch);
|
||||
}
|
||||
/*
|
||||
* cli_common.c: cli_quit
|
||||
* cli_interactive()
|
||||
*/
|
||||
int
|
||||
cli_set_exiting(clicon_handle h, int exiting)
|
||||
{
|
||||
cligen_handle ch = cligen(h);
|
||||
|
||||
return cligen_exiting_set(ch, exiting);
|
||||
}
|
||||
|
||||
char
|
||||
cli_comment(clicon_handle h)
|
||||
{
|
||||
cligen_handle ch = cligen(h);
|
||||
|
||||
return cligen_comment(ch);
|
||||
}
|
||||
|
||||
char
|
||||
cli_set_comment(clicon_handle h, char c)
|
||||
{
|
||||
cligen_handle ch = cligen(h);
|
||||
|
||||
return cligen_comment_set(ch, c);
|
||||
}
|
||||
|
||||
char
|
||||
cli_tree_add(clicon_handle h, char *tree, parse_tree pt)
|
||||
{
|
||||
cligen_handle ch = cligen(h);
|
||||
|
||||
return cligen_tree_add(ch, tree, pt);
|
||||
}
|
||||
|
||||
char *
|
||||
cli_tree_active(clicon_handle h)
|
||||
{
|
||||
cligen_handle ch = cligen(h);
|
||||
|
||||
return cligen_tree_active(ch);
|
||||
}
|
||||
|
||||
int
|
||||
cli_tree_active_set(clicon_handle h, char *treename)
|
||||
{
|
||||
cligen_handle ch = cligen(h);
|
||||
|
||||
return cligen_tree_active_set(ch, treename);
|
||||
}
|
||||
|
||||
parse_tree *
|
||||
cli_tree(clicon_handle h, char *name)
|
||||
{
|
||||
cligen_handle ch = cligen(h);
|
||||
|
||||
return cligen_tree(ch, name);
|
||||
}
|
||||
|
||||
int
|
||||
cli_parse_file(clicon_handle h,
|
||||
FILE *f,
|
||||
char *name, /* just for errs */
|
||||
parse_tree *pt,
|
||||
cvec *globals)
|
||||
{
|
||||
cligen_handle ch = cligen(h);
|
||||
|
||||
return cligen_parse_file(ch, f, name, pt, globals);
|
||||
}
|
||||
|
||||
int
|
||||
cli_susp_hook(clicon_handle h, cli_susphook_t *fn)
|
||||
{
|
||||
cligen_handle ch = cligen(h);
|
||||
|
||||
/* This assume first arg of fn can be treated as void* */
|
||||
return cligen_susp_hook(ch, (cligen_susp_cb_t*)fn);
|
||||
}
|
||||
|
||||
char *
|
||||
cli_nomatch(clicon_handle h)
|
||||
{
|
||||
cligen_handle ch = cligen(h);
|
||||
|
||||
return cligen_nomatch(ch);
|
||||
}
|
||||
|
||||
int
|
||||
cli_prompt_set(clicon_handle h, char *prompt)
|
||||
{
|
||||
cligen_handle ch = cligen(h);
|
||||
return cligen_prompt_set(ch, prompt);
|
||||
}
|
||||
|
||||
int
|
||||
cli_logsyntax_set(clicon_handle h, int status)
|
||||
{
|
||||
cligen_handle ch = cligen(h);
|
||||
return cligen_logsyntax_set(ch, status);
|
||||
}
|
||||
58
apps/cli/cli_handle.h
Normal file
58
apps/cli/cli_handle.h
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
*
|
||||
Copyright (C) 2009-2016 Olof Hagsand and Benny Holmgren
|
||||
|
||||
This file is part of CLICON.
|
||||
|
||||
CLICON 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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
CLICON 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 CLICON; see the file COPYING. If not, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _CLI_HANDLE_H_
|
||||
#define _CLI_HANDLE_H_
|
||||
|
||||
/*
|
||||
* Prototypes
|
||||
* Internal prototypes. For exported functions see clicon_cli_api.h
|
||||
*/
|
||||
char cli_tree_add(clicon_handle h, char *tree, parse_tree pt);
|
||||
|
||||
int cli_parse_file(clicon_handle h,
|
||||
FILE *f,
|
||||
char *name, /* just for errs */
|
||||
parse_tree *pt,
|
||||
cvec *globals);
|
||||
|
||||
char *cli_tree_active(clicon_handle h);
|
||||
|
||||
int cli_tree_active_set(clicon_handle h, char *treename);
|
||||
|
||||
parse_tree *cli_tree(clicon_handle h, char *name);
|
||||
|
||||
int cli_susp_hook(clicon_handle h, cli_susphook_t *fn);
|
||||
|
||||
char *cli_nomatch(clicon_handle h);
|
||||
|
||||
int cli_prompt_set(clicon_handle h, char *prompt);
|
||||
|
||||
int cli_logsyntax_set(clicon_handle h, int status);
|
||||
|
||||
/* Internal functions for handling cli groups */
|
||||
|
||||
cli_syntax_t *cli_syntax(clicon_handle h);
|
||||
int cli_syntax_set(clicon_handle h, cli_syntax_t *stx);
|
||||
|
||||
#endif /* _CLI_HANDLE_H_ */
|
||||
407
apps/cli/cli_main.c
Normal file
407
apps/cli/cli_main.c
Normal file
|
|
@ -0,0 +1,407 @@
|
|||
/*
|
||||
*
|
||||
Copyright (C) 2009-2016 Olof Hagsand and Benny Holmgren
|
||||
|
||||
This file is part of CLICON.
|
||||
|
||||
CLICON 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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
CLICON 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 CLICON; see the file COPYING. If not, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "clicon_config.h" /* generated by config & autoconf */
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#define __USE_GNU /* strverscmp */
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <dlfcn.h>
|
||||
#include <dirent.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
#include <syslog.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/param.h>
|
||||
#include <netinet/in.h>
|
||||
#include <assert.h>
|
||||
|
||||
/* cligen */
|
||||
#include <cligen/cligen.h>
|
||||
|
||||
/* clicon */
|
||||
#include <clicon/clicon.h>
|
||||
|
||||
#include "clicon_cli_api.h"
|
||||
|
||||
#include "cli_plugin.h"
|
||||
#include "cli_generate.h"
|
||||
#include "cli_common.h"
|
||||
#include "cli_handle.h"
|
||||
|
||||
/* Command line options to be passed to getopt(3) */
|
||||
#define CLI_OPTS "hD:f:F:1u:d:m:cP:qpGLl:"
|
||||
|
||||
static int
|
||||
cli_terminate(clicon_handle h)
|
||||
{
|
||||
yang_spec *yspec;
|
||||
|
||||
if ((yspec = clicon_dbspec_yang(h)) != NULL)
|
||||
yspec_free(yspec);
|
||||
cli_plugin_finish(h);
|
||||
exit_candidate_db(h);
|
||||
cli_handle_exit(h);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* cli_sig_term
|
||||
* Unlink pidfile and quit
|
||||
*/
|
||||
static void
|
||||
cli_sig_term(int arg)
|
||||
{
|
||||
clicon_log(LOG_NOTICE, "%s: %u Terminated (killed by sig %d)",
|
||||
__PROGRAM__, getpid(), arg);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Setup signal handlers
|
||||
*/
|
||||
static void
|
||||
cli_signal_init (clicon_handle h)
|
||||
{
|
||||
cli_signal_block(h);
|
||||
set_signal(SIGTERM, cli_sig_term, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
cli_interactive(clicon_handle h)
|
||||
{
|
||||
int res;
|
||||
char *cmd;
|
||||
char *new_mode;
|
||||
int result;
|
||||
|
||||
/* Loop through all commands */
|
||||
while(!cli_exiting(h)) {
|
||||
// save_mode =
|
||||
new_mode = cli_syntax_mode(h);
|
||||
if ((cmd = clicon_cliread(h)) == NULL) {
|
||||
cli_set_exiting(h, 1); /* EOF */
|
||||
break;
|
||||
}
|
||||
if ((res = clicon_parse(h, cmd, &new_mode, &result)) < 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
usage(char *argv0, clicon_handle h)
|
||||
{
|
||||
char *confsock = clicon_sock(h);
|
||||
char *plgdir = clicon_cli_dir(h);
|
||||
|
||||
fprintf(stderr, "usage:%s [options] [commands]\n"
|
||||
"where commands is a CLI command or options passed to the main plugin\n"
|
||||
"where options are\n"
|
||||
"\t-h \t\tHelp\n"
|
||||
"\t-D <level> \tDebug\n"
|
||||
"\t-f <file> \tConfig-file (mandatory)\n"
|
||||
"\t-F <file> \tRead commands from file (default stdin)\n"
|
||||
"\t-1\t\tDo not enter interactive mode\n"
|
||||
"\t-u <sockpath>\tconfig UNIX domain path (default: %s)\n"
|
||||
"\t-d <dir>\tSpecify plugin directory (default: %s)\n"
|
||||
"\t-m <mode>\tSpecify plugin syntax mode\n"
|
||||
"\t-c \t\tWrite to candidate db directly, not via config backend\n"
|
||||
"\t-P <dbname> \tWrite to private database\n"
|
||||
"\t-q \t\tQuiet mode, dont print greetings or prompt, terminate on ctrl-C\n"
|
||||
"\t-p \t\tPrint database yang specification\n"
|
||||
"\t-G \t\tPrint CLI syntax generated from dbspec (if CLICON_CLI_GENMODEL enabled)\n"
|
||||
"\t-L \t\tDebug print dynamic CLI syntax including completions and expansions\n"
|
||||
"\t-l <s|e|o> \tLog on (s)yslog, std(e)rr or std(o)ut (stderr is default)\n",
|
||||
argv0,
|
||||
confsock ? confsock : "none",
|
||||
plgdir ? plgdir : "none"
|
||||
);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/*
|
||||
*/
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
char c;
|
||||
enum candidate_db_type dbtype;
|
||||
char private_db[MAXPATHLEN];
|
||||
int once;
|
||||
char *tmp;
|
||||
char *argv0 = argv[0];
|
||||
clicon_handle h;
|
||||
int printspec = 0;
|
||||
int printgen = 0;
|
||||
int logclisyntax = 0;
|
||||
int help = 0;
|
||||
char *treename;
|
||||
char *running_db;
|
||||
int logdst = CLICON_LOG_STDERR;
|
||||
|
||||
/* Defaults */
|
||||
|
||||
/* In the startup, logs to stderr & debug flag set later */
|
||||
clicon_log_init(__PROGRAM__, LOG_INFO, logdst);
|
||||
/* Initiate CLICON handle */
|
||||
if ((h = cli_handle_init()) == NULL)
|
||||
goto done;
|
||||
if (cli_plugin_init(h) != 0)
|
||||
goto done;
|
||||
dbtype = CANDIDATE_DB_SHARED;
|
||||
once = 0;
|
||||
private_db[0] = '\0';
|
||||
cli_set_send2backend(h, 1); /* send changes to config daemon */
|
||||
cli_set_comment(h, '#'); /* Default to handle #! clicon_cli scripts */
|
||||
|
||||
/*
|
||||
* First-step command-line options for help, debug, config-file and log,
|
||||
*/
|
||||
optind = 1;
|
||||
opterr = 0;
|
||||
while ((c = getopt(argc, argv, CLI_OPTS)) != -1)
|
||||
switch (c) {
|
||||
case '?':
|
||||
case 'h':
|
||||
/* Defer the call to usage() to later. Reason is that for helpful
|
||||
text messages, default dirs, etc, are not set until later.
|
||||
But this means that we need to check if 'help' is set before
|
||||
exiting, and then call usage() before exit.
|
||||
*/
|
||||
help = 1;
|
||||
break;
|
||||
case 'D' : /* debug */
|
||||
if (sscanf(optarg, "%d", &debug) != 1)
|
||||
usage(argv[0], h);
|
||||
break;
|
||||
case 'f': /* config file */
|
||||
if (!strlen(optarg))
|
||||
usage(argv[0], h);
|
||||
clicon_option_str_set(h, "CLICON_CONFIGFILE", optarg);
|
||||
break;
|
||||
case 'l': /* Log destination: s|e|o */
|
||||
switch (optarg[0]){
|
||||
case 's':
|
||||
logdst = CLICON_LOG_SYSLOG;
|
||||
break;
|
||||
case 'e':
|
||||
logdst = CLICON_LOG_STDERR;
|
||||
break;
|
||||
case 'o':
|
||||
logdst = CLICON_LOG_STDOUT;
|
||||
break;
|
||||
default:
|
||||
usage(argv[0], h);
|
||||
}
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* Logs, error and debug to stderr or syslog, set debug level
|
||||
*/
|
||||
clicon_log_init(__PROGRAM__, debug?LOG_DEBUG:LOG_INFO, logdst);
|
||||
|
||||
clicon_debug_init(debug, NULL);
|
||||
|
||||
/* Find and read configfile */
|
||||
if (clicon_options_main(h) < 0){
|
||||
if (help)
|
||||
usage(argv[0], h);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Now rest of options */
|
||||
opterr = 0;
|
||||
optind = 1;
|
||||
while ((c = getopt(argc, argv, CLI_OPTS)) != -1){
|
||||
switch (c) {
|
||||
case 'D' : /* debug */
|
||||
case 'f': /* config file */
|
||||
case 'l': /* Log destination */
|
||||
break; /* see above */
|
||||
case 'F': /* read commands from file */
|
||||
if (freopen(optarg, "r", stdin) == NULL){
|
||||
cli_output(stderr, "freopen: %s\n", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case '1' : /* Quit after reading database once - dont wait for events */
|
||||
once = 1;
|
||||
break;
|
||||
case 'u': /* config unix domain path/ ip host */
|
||||
if (!strlen(optarg))
|
||||
usage(argv[0], h);
|
||||
clicon_option_str_set(h, "CLICON_SOCK", optarg);
|
||||
break;
|
||||
case 'd': /* Plugin directory: overrides configfile */
|
||||
if (!strlen(optarg))
|
||||
usage(argv[0], h);
|
||||
clicon_option_str_set(h, "CLICON_CLI_DIR", optarg);
|
||||
break;
|
||||
case 'm': /* CLI syntax mode */
|
||||
if (!strlen(optarg))
|
||||
usage(argv[0], h);
|
||||
clicon_option_str_set(h, "CLICON_CLI_MODE", optarg);
|
||||
break;
|
||||
case 'c' : /* No config daemon (used in bootstrapping and file load) */
|
||||
cli_set_send2backend(h, 0);
|
||||
break;
|
||||
case 'P' : /* load to private database with given name */
|
||||
dbtype = CANDIDATE_DB_PRIVATE;
|
||||
clicon_option_str_set(h, "CLICON_CANDIDATE_DB", optarg); /* override default */
|
||||
break;
|
||||
case 'q' : /* Quiet mode */
|
||||
clicon_option_str_set(h, "CLICON_QUIET", "on");
|
||||
break;
|
||||
case 'p' : /* Print spec */
|
||||
printspec++;
|
||||
break;
|
||||
case 'G' : /* Print generated CLI syntax */
|
||||
printgen++;
|
||||
break;
|
||||
case 'L' : /* Debug print dynamic CLI syntax */
|
||||
logclisyntax++;
|
||||
break;
|
||||
default:
|
||||
usage(argv[0], h);
|
||||
break;
|
||||
}
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
/* Defer: Wait to the last minute to print help message */
|
||||
if (help)
|
||||
usage(argv[0], h);
|
||||
|
||||
/* Setup signal handlers */
|
||||
cli_signal_init(h);
|
||||
|
||||
/* Backward compatible mode, do not include keys in cgv-arrays in callbacks.
|
||||
Should be 0 but default is 1 since all legacy apps use 1
|
||||
Test legacy before shifting default to 0
|
||||
*/
|
||||
cv_exclude_keys(clicon_cli_varonly(h));
|
||||
|
||||
/* Parse db specification as cli*/
|
||||
if (yang_spec_main(h, stdout, printspec) < 0)
|
||||
goto done;
|
||||
|
||||
/* Check plugin directory */
|
||||
if (clicon_cli_dir(h) == NULL){
|
||||
clicon_err(OE_PLUGIN, 0, "clicon_cli_dir not defined");
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Create tree generated from dataspec */
|
||||
if (clicon_cli_genmodel(h)){
|
||||
yang_spec *yspec; /* yang spec */
|
||||
parse_tree pt = {0,}; /* cli parse tree */
|
||||
|
||||
if ((yspec = clicon_dbspec_yang(h)) == NULL){
|
||||
clicon_err(OE_FATAL, 0, "No YANG DB_SPEC");
|
||||
goto done;
|
||||
}
|
||||
/* Create cli command tree from dbspec */
|
||||
if (yang2cli(h, yspec, &pt, clicon_cli_genmodel_type(h)) < 0)
|
||||
goto done;
|
||||
|
||||
treename = chunk_sprintf(__FUNCTION__, "datamodel:%s", clicon_dbspec_name(h));
|
||||
cli_tree_add(h, treename, pt);
|
||||
if (printgen)
|
||||
cligen_print(stdout, pt, 1);
|
||||
}
|
||||
|
||||
/* Initialize cli syntax */
|
||||
if (cli_syntax_load(h) < 0)
|
||||
goto done;
|
||||
|
||||
/* Set syntax mode if specified from command-line or config-file. */
|
||||
if (clicon_option_exists(h, "CLICON_CLI_MODE"))
|
||||
if ((tmp = clicon_cli_mode(h)) != NULL)
|
||||
if (cli_set_syntax_mode(h, tmp) == 0) {
|
||||
fprintf(stderr, "FATAL: Failed to set syntax mode '%s'\n", tmp);
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (!cli_syntax_mode(h)){
|
||||
fprintf (stderr, "FATAL: No cli mode set (use -m or CLICON_CLI_MODE)\n");
|
||||
goto done;
|
||||
}
|
||||
if (cli_tree(h, cli_syntax_mode(h)) == NULL){
|
||||
fprintf (stderr, "FATAL: No such cli mode: %s\n", cli_syntax_mode(h));
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Initialize databases */
|
||||
if ((running_db = clicon_running_db(h)) == NULL)
|
||||
goto done;
|
||||
|
||||
if (strlen(private_db))
|
||||
clicon_option_str_set(h, "CLICON_CANDIDATE_DB", private_db);
|
||||
|
||||
if (!cli_send2backend(h))
|
||||
if (db_init(running_db) < 0){
|
||||
fprintf (stderr, "FATAL: Could not init running_db. (Run as root?)\n");
|
||||
goto done;
|
||||
}
|
||||
/* A client does not have access to the candidate (and running)
|
||||
databases if both these conditions are true:
|
||||
1. clicon_sock_family(h) == AF_INET[6]
|
||||
2. cli_send2backend(h) == 1
|
||||
*/
|
||||
if (clicon_sock_family(h) == AF_UNIX || cli_send2backend(h)==0)
|
||||
if (init_candidate_db(h, dbtype) < 0)
|
||||
return -1;
|
||||
|
||||
if (logclisyntax)
|
||||
cli_logsyntax_set(h, logclisyntax);
|
||||
|
||||
if (debug)
|
||||
clicon_option_dump(h, debug);
|
||||
|
||||
/* Call start function in all plugins before we go interactive
|
||||
Pass all args after the standard options to plugin_start
|
||||
*/
|
||||
|
||||
tmp = *(argv-1);
|
||||
*(argv-1) = argv0;
|
||||
cli_plugin_start(h, argc+1, argv-1);
|
||||
*(argv-1) = tmp;
|
||||
|
||||
/* Launch interfactive event loop, unless -1 */
|
||||
if (once == 0)
|
||||
cli_interactive(h);
|
||||
done:
|
||||
// Gets in your face if we log on stderr
|
||||
clicon_log_init(__PROGRAM__, LOG_INFO, 0); /* Log on syslog no stderr */
|
||||
clicon_log(LOG_NOTICE, "%s: %u Terminated\n", __PROGRAM__, getpid());
|
||||
cli_terminate(h);
|
||||
|
||||
return 0;
|
||||
}
|
||||
1153
apps/cli/cli_plugin.c
Normal file
1153
apps/cli/cli_plugin.c
Normal file
File diff suppressed because it is too large
Load diff
90
apps/cli/cli_plugin.h
Normal file
90
apps/cli/cli_plugin.h
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
*
|
||||
Copyright (C) 2009-2016 Olof Hagsand and Benny Holmgren
|
||||
|
||||
This file is part of CLICON.
|
||||
|
||||
CLICON 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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
CLICON 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 CLICON; see the file COPYING. If not, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef _CLI_PLUGIN_H_
|
||||
#define _CLI_PLUGIN_H_
|
||||
|
||||
#include <stdio.h>
|
||||
#include <inttypes.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
/* clicon generic callback pointer */
|
||||
typedef void (clicon_callback_t)(clicon_handle h);
|
||||
|
||||
/* clicon_set value callback */
|
||||
typedef int (cli_valcb_t)(cvec *vars, cg_var *cgv, cg_var *arg);
|
||||
|
||||
/* specific to cli. For common see clicon_plugin.h */
|
||||
/* Hook to get prompt format before each getline */
|
||||
typedef char *(cli_prompthook_t)(clicon_handle, char *mode);
|
||||
|
||||
/* Ctrl-Z hook from getline() */
|
||||
typedef int (cli_susphook_t)(clicon_handle, char *, int, int *);
|
||||
|
||||
/* CLIgen parse failure hook. Retry other mode? */
|
||||
typedef char *(cli_parsehook_t)(clicon_handle, char *, char *);
|
||||
|
||||
typedef struct {
|
||||
qelem_t csm_qelem; /* List header */
|
||||
char csm_name[256]; /* Syntax mode name */
|
||||
char csm_prompt[CLI_PROMPT_LEN]; /* Prompt for mode */
|
||||
int csm_nsyntax; /* Num syntax specs registered by plugin */
|
||||
parse_tree csm_pt; /* CLIgen parse tree */
|
||||
|
||||
} cli_syntaxmode_t;
|
||||
|
||||
/* A plugin list object */
|
||||
struct cli_plugin {
|
||||
qelem_t cp_qelem; /* List header */
|
||||
char cp_name[256]; /* Plugin name */
|
||||
void *cp_handle; /* Dynamic object handle */
|
||||
};
|
||||
|
||||
/* Plugin group object */
|
||||
typedef struct {
|
||||
char stx_cnklbl[128]; /* Plugin group name */
|
||||
int stx_nplugins; /* Number of plugins */
|
||||
struct cli_plugin *stx_plugins; /* List of plugins */
|
||||
int stx_nmodes; /* Number of syntax modes */
|
||||
cli_syntaxmode_t *stx_active_mode; /* Current active syntax mode */
|
||||
cli_syntaxmode_t *stx_modes; /* List of syntax modes */
|
||||
cli_prompthook_t *stx_prompt_hook; /* Prompt hook */
|
||||
cli_parsehook_t *stx_parse_hook; /* Parse mode hook */
|
||||
cli_susphook_t *stx_susp_hook; /* Ctrl-Z hook from getline() */
|
||||
} cli_syntax_t;
|
||||
|
||||
|
||||
expand_cb *expand_str2fn(char *name, void *handle, char **error);
|
||||
|
||||
int cli_plugin_start(clicon_handle, int argc, char **argv);
|
||||
|
||||
int cli_plugin_init(clicon_handle h);
|
||||
|
||||
int clicon_eval(clicon_handle h, char *cmd, cg_obj *match_obj, cvec *vr);
|
||||
|
||||
int clicon_parse(clicon_handle h, char *cmd, char **mode, int *result);
|
||||
|
||||
char *clicon_cliread(clicon_handle h);
|
||||
|
||||
int cli_plugin_finish(clicon_handle h);
|
||||
|
||||
#endif /* _CLI_PLUGIN_H_ */
|
||||
59
apps/cli/clicon_cli.h
Normal file
59
apps/cli/clicon_cli.h
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
*
|
||||
Copyright (C) 2009-2016 Olof Hagsand and Benny Holmgren
|
||||
|
||||
This file is part of CLICON.
|
||||
|
||||
CLICON 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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
CLICON 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 CLICON; see the file COPYING. If not, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef _CLICON_CLI_H_
|
||||
#define _CLICON_CLI_H_
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#/* Common code (API and clicon_cli) */
|
||||
include <clicon/clicon_cli_api.h>
|
||||
|
||||
/*! Clicon Cli plugin callbacks: use these in your cli plugin code
|
||||
*/
|
||||
|
||||
/*! Called when plugin loaded. Only mandadory callback. All others optional
|
||||
* @see plginit_t
|
||||
*/
|
||||
int plugin_init(clicon_handle h);
|
||||
|
||||
/* Called when backend started with cmd-line arguments from daemon call.
|
||||
* @see plgstart_t
|
||||
*/
|
||||
int plugin_start(clicon_handle h, int argc, char **argv);
|
||||
|
||||
/* Called just before plugin unloaded.
|
||||
* @see plgexit_t
|
||||
*/
|
||||
int plugin_exit(clicon_handle h);
|
||||
|
||||
|
||||
/* Called before prompt is printed, return a customized prompt. */
|
||||
char *plugin_prompt_hook(clicon_handle h, char *mode);
|
||||
|
||||
/* Called if a command is not matched w current mode. Return name of next syntax mode to check until NULL */
|
||||
char *plugin_parse_hook(clicon_handle h, char *cmd, char *name);
|
||||
|
||||
/* Called if ^Z entered. Can modify cli command buffer and position */
|
||||
int plugin_susp_hook(clicon_handle h, char *buf, int prompt_width, int *cursor_loc);
|
||||
|
||||
#endif /* _CLICON_CLI_H_ */
|
||||
113
apps/cli/clicon_cli_api.h
Normal file
113
apps/cli/clicon_cli_api.h
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
/*
|
||||
*
|
||||
Copyright (C) 2009-2016 Olof Hagsand and Benny Holmgren
|
||||
|
||||
This file is part of CLICON.
|
||||
|
||||
CLICON 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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
CLICON 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 CLICON; see the file COPYING. If not, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
|
||||
* Note, this is a CLICON API file, only exprorted function prototypes should appear here
|
||||
*/
|
||||
|
||||
#ifndef _CLICON_CLI_API_H_
|
||||
#define _CLICON_CLI_API_H_
|
||||
|
||||
/*
|
||||
* Constants
|
||||
*/
|
||||
/* Max prompt length */
|
||||
#define CLI_PROMPT_LEN 64
|
||||
#define CLI_DEFAULT_PROMPT ">"
|
||||
|
||||
/*
|
||||
* Types
|
||||
*/
|
||||
//typedef void *cli_handle; /* clicon cli handle, see struct cli_handle */
|
||||
enum candidate_db_type{
|
||||
CANDIDATE_DB_NONE, /* No candidate */
|
||||
CANDIDATE_DB_PRIVATE, /* Create a private candidate_db */
|
||||
CANDIDATE_DB_SHARED, /* Share the candidate with everyone else */
|
||||
CANDIDATE_DB_CURRENT /* Dont create candidate, use current directly */
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Function Declarations
|
||||
*/
|
||||
/* cli_plugin.c */
|
||||
int cli_set_syntax_mode(clicon_handle h, const char *mode);
|
||||
char *cli_syntax_mode(clicon_handle h);
|
||||
int cli_syntax_load(clicon_handle h);
|
||||
int cli_handler_err(FILE *fd);
|
||||
int cli_set_prompt(clicon_handle h, const char *mode, const char *prompt);
|
||||
char *cli_prompt(char *fmt);
|
||||
int cli_exec(clicon_handle h, char *cmd, char **mode, int *result);
|
||||
int cli_ptpush(clicon_handle h, char *mode, char *string, char *op);
|
||||
int cli_ptpop(clicon_handle h, char *mode, char *op);
|
||||
|
||||
/* cli_handle.c */
|
||||
char cli_set_comment(clicon_handle h, char c);
|
||||
char cli_comment(clicon_handle h);
|
||||
int cli_set_exiting(clicon_handle h, int exiting);
|
||||
int cli_exiting(clicon_handle h);
|
||||
int cli_set_send2backend(clicon_handle h, int send2backend);
|
||||
int cli_send2backend(clicon_handle h);
|
||||
clicon_handle cli_handle_init(void);
|
||||
int cli_handle_exit(clicon_handle h);
|
||||
cligen_handle cli_cligen(clicon_handle h);
|
||||
enum candidate_db_type cli_candidate_type(clicon_handle h);
|
||||
int cli_set_candidate_type(clicon_handle h, enum candidate_db_type type);
|
||||
|
||||
/* cli_common.c */
|
||||
int init_candidate_db(clicon_handle h, enum candidate_db_type type);
|
||||
int exit_candidate_db(clicon_handle h);
|
||||
#define cli_output cligen_output
|
||||
int cli_set (clicon_handle h, cvec *vars, cg_var *arg);
|
||||
int cli_merge (clicon_handle h, cvec *vars, cg_var *arg);
|
||||
int cli_del(clicon_handle h, cvec *vars, cg_var *argv);
|
||||
int cli_debug(clicon_handle h, cvec *vars, cg_var *argv);
|
||||
int cli_record(clicon_handle h, cvec *vars, cg_var *argv);
|
||||
int isrecording(void);
|
||||
int record_command(char *str);
|
||||
int cli_set_mode(clicon_handle h, cvec *vars, cg_var *argv);
|
||||
int cli_start_shell(clicon_handle h, cvec *vars, cg_var *argv);
|
||||
int cli_quit(clicon_handle h, cvec *vars, cg_var *arg);
|
||||
int cli_commit(clicon_handle h, cvec *vars, cg_var *arg);
|
||||
int cli_validate(clicon_handle h, cvec *vars, cg_var *arg);
|
||||
int expand_dbvar(void *h, char *name, cvec *vars, cg_var *arg,
|
||||
int *nr, char ***commands, char ***helptexts);
|
||||
int expand_dbvar_auto(void *h, char *name, cvec *vars, cg_var *arg,
|
||||
int *nr, char ***commands, char ***helptexts);
|
||||
int expand_db_variable(clicon_handle h, char *dbname, char *basekey, char *variable, int *nr, char ***commands);
|
||||
int expand_db_symbol(clicon_handle h, char *symbol, int element, int *nr, char ***commands);
|
||||
int expand_dir(char *dir, int *nr, char ***commands, mode_t flags, int detail);
|
||||
int compare_dbs(clicon_handle h, cvec *vars, cg_var *arg);
|
||||
|
||||
int load_config_file(clicon_handle h, cvec *vars, cg_var *arg);
|
||||
int save_config_file(clicon_handle h, cvec *vars, cg_var *arg);
|
||||
int delete_all(clicon_handle h, cvec *vars, cg_var *arg);
|
||||
int discard_changes(clicon_handle h, cvec *vars, cg_var *arg);
|
||||
int show_conf_as_xml(clicon_handle h, cvec *vars, cg_var *arg);
|
||||
int show_conf_as_netconf(clicon_handle h, cvec *vars, cg_var *arg);
|
||||
int show_conf_as_json(clicon_handle h, cvec *vars, cg_var *arg);
|
||||
int show_conf_as_text(clicon_handle h, cvec *vars, cg_var *arg);
|
||||
int show_conf_as_cli(clicon_handle h, cvec *vars, cg_var *arg);
|
||||
int show_conf_as_csv(clicon_handle h, cvec *vars, cg_var *arg);
|
||||
int show_yang(clicon_handle h, cvec *vars, cg_var *arg);
|
||||
int cli_notification_register(clicon_handle h, char *stream, enum format_enum format,
|
||||
char *filter, int status,
|
||||
int (*fn)(int, void*), void *arg);
|
||||
|
||||
#endif /* _CLICON_CLI_API_H_ */
|
||||
Loading…
Add table
Add a link
Reference in a new issue