diff --git a/CHANGELOG.md b/CHANGELOG.md index e96c1bf9..f378b287 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -34,8 +34,19 @@ ## 5.4.0 Expected: November, 2021 +### API changes on existing protocol/config features + +Users may have to change how they access the system + +* NETCONF hello errors, such as wrong session-id, prefix, namespace terminates session + * Instead of returning an rpc-error reply + ### Minor features +* Restconf YANG PATCH according to RFC 8072 + * Changed YANG PATCH enabling: + * Now: `./configure --enable-yang-patch` + * Before: set YANG_PATCH constant in `include/clixon_custom.h` * Refactored Makefile for static linking ## 5.3.0 diff --git a/apps/netconf/netconf_main.c b/apps/netconf/netconf_main.c index 7add4dfd..86b0b713 100644 --- a/apps/netconf/netconf_main.c +++ b/apps/netconf/netconf_main.c @@ -48,6 +48,8 @@ #include #include #include +#include +#include #include #include #include @@ -56,9 +58,7 @@ #include #include #include -#include #include -#include /* cligen */ #include @@ -119,7 +119,7 @@ netconf_add_request_attr(cxobj *xrpc, return retval; } -/* +/*! Process netconf hello message * A server receiving a message with a element MUST * terminate the NETCONF session. */ @@ -309,22 +309,20 @@ netconf_input_packet(clicon_handle h, goto done; } else if (strcmp(rpcname, "hello") == 0){ - /* Only accept resolved NETCONF base namespace */ + /* Only accept resolved NETCONF base namespace -> terminate*/ if (namespace == NULL || strcmp(namespace, NETCONF_BASE_NAMESPACE) != 0){ - clicon_err(OE_XML, EFAULT, "No appropriate namespace associated with prefix:%s", rpcprefix); + cc_closed++; + clicon_err(OE_XML, EFAULT, "No appropriate namespace associated with namespace:%s", + namespace); goto done; } if (netconf_hello_msg(h, xreq) < 0) goto done; } - else{ - if ((cbret = cbuf_new()) == NULL){ - clicon_err(OE_XML, errno, "cbuf_new"); - goto done; - } - if (netconf_unknown_element(cbret, "protocol", rpcname, "Unrecognized netconf operation")< 0) - goto done; - netconf_output_encap(1, cbret, "rpc-error"); + else{ /* Shouldnt happen should be caught by yang bind check in netconf_input_frame */ + cc_closed++; + clicon_err(OE_NETCONF, 0, "Unrecognized netconf operation %s", rpcname); + goto done; } ok: retval = 0; diff --git a/apps/restconf/restconf_main_fcgi.c b/apps/restconf/restconf_main_fcgi.c index e9d3bd6e..bb4ce85c 100644 --- a/apps/restconf/restconf_main_fcgi.c +++ b/apps/restconf/restconf_main_fcgi.c @@ -421,11 +421,11 @@ main(int argc, if (yang_spec_parse_module(h, "ietf-restconf", NULL, yspec)< 0) goto done; -#ifdef YANG_PATCH +#ifdef CLIXON_YANG_PATCH /* Load yang restconf patch module */ if (yang_spec_parse_module(h, "ietf-yang-patch", NULL, yspec)< 0) goto done; -#endif // YANG_PATCH +#endif /* Add netconf yang spec, used as internal protocol */ if (netconf_module_load(h) < 0) diff --git a/apps/restconf/restconf_main_native.c b/apps/restconf/restconf_main_native.c index fdfdc630..ddad2d71 100644 --- a/apps/restconf/restconf_main_native.c +++ b/apps/restconf/restconf_main_native.c @@ -1770,11 +1770,11 @@ restconf_clixon_init(clicon_handle h, if (yang_spec_parse_module(h, "ietf-restconf", NULL, yspec)< 0) goto done; -#ifdef YANG_PATCH +#ifdef CLIXON_YANG_PATCH /* Load yang restconf patch module */ if (yang_spec_parse_module(h, "ietf-yang-patch", NULL, yspec)< 0) goto done; -#endif // YANG_PATCH +#endif /* Add netconf yang spec, used as internal protocol */ if (netconf_module_load(h) < 0) diff --git a/apps/restconf/restconf_methods.c b/apps/restconf/restconf_methods.c index ef1d7611..b634c293 100644 --- a/apps/restconf/restconf_methods.c +++ b/apps/restconf/restconf_methods.c @@ -677,7 +677,7 @@ api_data_patch(clicon_handle h, break; case YANG_PATCH_JSON: /* RFC 8072 patch */ case YANG_PATCH_XML: -#ifdef YANG_PATCH +#ifdef CLIXON_YANG_PATCH ret = api_data_yang_patch(h, req, api_path0, pcvec, pi, qvec, data, pretty, media_in, media_out, ds); #else diff --git a/apps/restconf/restconf_methods_patch.c b/apps/restconf/restconf_methods_patch.c index 98e963c4..60e800d2 100644 --- a/apps/restconf/restconf_methods_patch.c +++ b/apps/restconf/restconf_methods_patch.c @@ -67,7 +67,7 @@ #include "restconf_methods_post.h" #include "restconf_methods_patch.h" -#ifdef YANG_PATCH +#ifdef CLIXON_YANG_PATCH enum yang_patch_op{ YANG_PATCH_OP_CREATE, @@ -124,7 +124,7 @@ yang_patch_xml2json_modified_cbuf(cxobj *x_simple_patch) // Insert a '[' after the first '{' to get the JSON to match what api_data_post/write() expect json_simple_patch_tmp = cbuf_get(cb); len = strlen(json_simple_patch_tmp); - for (int l = 0; l < strlen(len); l++) { + for (int l = 0; l < len; l++) { char c = json_simple_patch_tmp[l]; if (c == '{') { brace_count++; @@ -848,7 +848,7 @@ api_data_yang_patch(clicon_handle h, return retval; } -#else // YANG_PATCH +#else // CLIXON_YANG_PATCH int api_data_yang_patch(clicon_handle h, @@ -866,4 +866,4 @@ api_data_yang_patch(clicon_handle h, clicon_err(OE_RESTCONF, 0, "Not implemented"); return -1; } -#endif // YANG_PATCH +#endif // CLIXON_YANG_PATCH diff --git a/configure b/configure index 1a980958..267e86aa 100755 --- a/configure +++ b/configure @@ -635,6 +635,7 @@ CXXFLAGS CXX CPP wwwdir +CLIXON_YANG_PATCH enable_optyangs with_libxml2 HAVE_LIBNGHTTP2 @@ -650,6 +651,11 @@ INSTALL_DATA INSTALL_SCRIPT INSTALL_PROGRAM INCLUDES +CLIGEN_PREFIX +CLIXON_VERSION_MINOR +CLIXON_VERSION_MAJOR +CLIXON_VERSION_STRING +CLIXON_VERSION target_os target_vendor target_cpu @@ -662,11 +668,6 @@ build_os build_vendor build_cpu build -CLIGEN_PREFIX -CLIXON_VERSION_MINOR -CLIXON_VERSION_MAJOR -CLIXON_VERSION_STRING -CLIXON_VERSION OBJEXT EXEEXT ac_ct_CC @@ -719,6 +720,7 @@ enable_option_checking enable_debug with_cligen enable_optyangs +enable_yang_patch enable_publish with_restconf enable_evhtp @@ -1369,6 +1371,7 @@ Optional Features: --enable-debug Build with debug symbols, default: no --enable-optyangs Include optional yang files for examples and testing in clixon install, default: no + --enable-yang-patch Enable YANG patch, RFC 8072, default: no --enable-publish Enable publish of notification streams using SSE and curl --disable-evhtp Disable evhtp for native restconf http/1, default: @@ -2231,10 +2234,10 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu # Default CFLAGS and INSTALLFLAGS unless set by environment -: ${CFLAGS="-O2 -Wall"} : ${INSTALLFLAGS="-s"} : ${LINKAGE=dynamic} + # where autotool scripts are: install-sh, config.sub, config.guess ac_aux_dir= for ac_dir in config-aux "$srcdir"/config-aux; do @@ -2271,6 +2274,31 @@ CLIXON_VERSION_MINOR="4" CLIXON_VERSION_PATCH="0" CLIXON_VERSION="\"${CLIXON_VERSION_MAJOR}.${CLIXON_VERSION_MINOR}.${CLIXON_VERSION_PATCH}.PRE\"" +# Debug flag +# Check whether --enable-debug was given. +if test "${enable_debug+set}" = set; then : + enableval=$enable_debug; + if test "$enableval" = no; then + ac_enable_debug=no + else + ac_enable_debug=yes + fi + +else + ac_enable_debug=no +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: debug is $ac_enable_debug" >&5 +$as_echo "debug is $ac_enable_debug" >&6; } +if test "$ac_enable_debug" = "yes"; then + : ${CFLAGS="-g -Wall"} + INSTALLFLAGS="" +else + : ${CFLAGS="-O2 -Wall"} +fi + + # Check CLIgen if test "$prefix" = "NONE"; then CLIGEN_PREFIX="$ac_default_prefix" @@ -3132,17 +3160,6 @@ _ACEOF fi -# AC_SUBST(var) makes @var@ appear in makefiles. -# clixon versions spread to Makefile's (.so files) and variable in build.c - - - - - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: CLIXON version is ${CLIXON_VERSION}" >&5 -$as_echo "CLIXON version is ${CLIXON_VERSION}" >&6; } - # Make sure we can run config.sub. $SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5 @@ -3254,6 +3271,17 @@ test -n "$target_alias" && NONENONEs,x,x, && program_prefix=${target_alias}- +# AC_SUBST(var) makes @var@ appear in makefiles. +# clixon versions spread to Makefile's (.so files) and variable in build.c + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: CLIXON version is ${CLIXON_VERSION}" >&5 +$as_echo "CLIXON version is ${CLIXON_VERSION}" >&6; } + @@ -3368,6 +3396,9 @@ HAVE_LIBNGHTTP2=false # consider using neutral constant such as with-http2 + + + # Home dir for web user, such as nginx fcgi sockets wwwdir=/www-data @@ -4311,27 +4342,6 @@ CPPFLAGS="-DHAVE_CONFIG_H ${CPPFLAGS}" { $as_echo "$as_me:${as_lineno-$LINENO}: result: compiler is $CC" >&5 $as_echo "compiler is $CC" >&6; } -# Debug flag -# Check whether --enable-debug was given. -if test "${enable_debug+set}" = set; then : - enableval=$enable_debug; - if test "$enableval" = no; then - ac_enable_debug=no - else - ac_enable_debug=yes - fi - -else - ac_enable_debug=no -fi - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: debug is $ac_enable_debug" >&5 -$as_echo "debug is $ac_enable_debug" >&6; } -if test "$ac_enable_debug" = "yes"; then - CFLAGS="$CFLAGS -g -Wall" - INSTALLFLAGS="" -fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: CPPFLAGS is $CPPFLAGS" >&5 $as_echo "CPPFLAGS is $CPPFLAGS" >&6; } @@ -4601,6 +4611,30 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: optyangs is $enable_optyangs" >&5 $as_echo "optyangs is $enable_optyangs" >&6; } +# Disable/enable yang patch +# Check whether --enable-yang-patch was given. +if test "${enable_yang_patch+set}" = set; then : + enableval=$enable_yang_patch; + if test "$enableval" = no; then + enable_yang_patch=no + else + enable_yang_patch=yes + fi + +else + enable_yang_patch=no +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: enable-yang-patch is ${enable_yang_patch}" >&5 +$as_echo "enable-yang-patch is ${enable_yang_patch}" >&6; } +if test "${enable_yang_patch}" = "yes"; then + CLIXON_YANG_PATCH=1 + +$as_echo "#define CLIXON_YANG_PATCH 1" >>confdefs.h + +fi + # Experimental: Curl publish notification stream to eg Nginx nchan. # Check whether --enable-publish was given. if test "${enable_publish+set}" = set; then : diff --git a/configure.ac b/configure.ac index 3bd702f6..f46e7af2 100644 --- a/configure.ac +++ b/configure.ac @@ -41,10 +41,10 @@ AC_INIT(lib/clixon/clixon.h.in) # Default CFLAGS and INSTALLFLAGS unless set by environment -: ${CFLAGS="-O2 -Wall"} : ${INSTALLFLAGS="-s"} : ${LINKAGE=dynamic} + # where autotool scripts are: install-sh, config.sub, config.guess AC_CONFIG_AUX_DIR(config-aux) @@ -53,6 +53,24 @@ CLIXON_VERSION_MINOR="4" CLIXON_VERSION_PATCH="0" CLIXON_VERSION="\"${CLIXON_VERSION_MAJOR}.${CLIXON_VERSION_MINOR}.${CLIXON_VERSION_PATCH}.PRE\"" +# Debug flag +AC_ARG_ENABLE(debug, AS_HELP_STRING([--enable-debug],[Build with debug symbols, default: no]),[ + if test "$enableval" = no; then + ac_enable_debug=no + else + ac_enable_debug=yes + fi + ], + [ ac_enable_debug=no]) + +AC_MSG_RESULT(debug is $ac_enable_debug) +if test "$ac_enable_debug" = "yes"; then + : ${CFLAGS="-g -Wall"} + INSTALLFLAGS="" +else + : ${CFLAGS="-O2 -Wall"} +fi + # Check CLIgen if test "$prefix" = "NONE"; then CLIGEN_PREFIX="$ac_default_prefix" @@ -69,6 +87,8 @@ AC_DEFINE_UNQUOTED(CLIXON_VERSION_PATCH, $CLIXON_VERSION_PATCH, [Clixon path ver AC_CHECK_LIB(m, main) +AC_CANONICAL_TARGET + # AC_SUBST(var) makes @var@ appear in makefiles. # clixon versions spread to Makefile's (.so files) and variable in build.c AC_SUBST(CLIXON_VERSION) @@ -79,8 +99,6 @@ AC_SUBST(CLIGEN_PREFIX) AC_MSG_RESULT(CLIXON version is ${CLIXON_VERSION}) -AC_CANONICAL_TARGET - AC_SUBST(CC) AC_SUBST(CFLAGS) AC_SUBST(LDFLAGS) @@ -100,7 +118,10 @@ AC_SUBST(with_restconf) # Set to native or fcgi -> compile apps/restconf AC_SUBST(HAVE_LIBEVHTP,false) # consider using neutral constant such as with-http1 AC_SUBST(HAVE_LIBNGHTTP2,false) # consider using neutral constant such as with-http2 AC_SUBST(with_libxml2) -AC_SUBST(enable_optyangs) +AC_SUBST(enable_optyangs) +AC_SUBST(CLIXON_YANG_PATCH) + + # Home dir for web user, such as nginx fcgi sockets AC_SUBST(wwwdir,/www-data) @@ -112,21 +133,6 @@ AC_PROG_CXX CPPFLAGS="-DHAVE_CONFIG_H ${CPPFLAGS}" AC_MSG_RESULT(compiler is $CC) -# Debug flag -AC_ARG_ENABLE(debug, AS_HELP_STRING([--enable-debug],[Build with debug symbols, default: no]),[ - if test "$enableval" = no; then - ac_enable_debug=no - else - ac_enable_debug=yes - fi - ], - [ ac_enable_debug=no]) - -AC_MSG_RESULT(debug is $ac_enable_debug) -if test "$ac_enable_debug" = "yes"; then - CFLAGS="$CFLAGS -g -Wall" - INSTALLFLAGS="" -fi AC_MSG_RESULT(CPPFLAGS is $CPPFLAGS) AC_MSG_RESULT(CFLAGS is $CFLAGS) @@ -179,7 +185,23 @@ AC_ARG_ENABLE(optyangs, AS_HELP_STRING([--enable-optyangs],[Include optional yan ], [ enable_optyangs=no]) -AC_MSG_RESULT(optyangs is $enable_optyangs) +AC_MSG_RESULT(optyangs is $enable_optyangs) + +# Disable/enable yang patch +AC_ARG_ENABLE(yang-patch, AS_HELP_STRING([--enable-yang-patch],[Enable YANG patch, RFC 8072, default: no]),[ + if test "$enableval" = no; then + enable_yang_patch=no + else + enable_yang_patch=yes + fi + ], + [ enable_yang_patch=no]) + +AC_MSG_RESULT(enable-yang-patch is ${enable_yang_patch}) +if test "${enable_yang_patch}" = "yes"; then + CLIXON_YANG_PATCH=1 + AC_DEFINE(CLIXON_YANG_PATCH, 1, [Enable YANG patch, RFC 8072]) +fi # Experimental: Curl publish notification stream to eg Nginx nchan. AC_ARG_ENABLE(publish, AS_HELP_STRING([--enable-publish],[Enable publish of notification streams using SSE and curl]),[ diff --git a/include/clixon_config.h.in b/include/clixon_config.h.in index 2820bd59..28e6f78e 100644 --- a/include/clixon_config.h.in +++ b/include/clixon_config.h.in @@ -18,6 +18,9 @@ /* Clixon version string */ #undef CLIXON_VERSION_STRING +/* Enable YANG patch, RFC 8072 */ +#undef CLIXON_YANG_PATCH + /* Define to 1 if you have the `alphasort' function. */ #undef HAVE_ALPHASORT diff --git a/include/clixon_custom.h b/include/clixon_custom.h index 5a613859..779df211 100644 --- a/include/clixon_custom.h +++ b/include/clixon_custom.h @@ -113,11 +113,6 @@ */ #define XML_PARENT_CANDIDATE -/*! Enable yang patch RFC 8072 - * Remove this when regression test - */ -#undef YANG_PATCH - /*! Enable "remaining" attribute (sub-feature of list pagination) * As defined in draft-wwlh-netconf-list-pagination-00 using Yang metadata value [RFC7952] */ diff --git a/test/config.sh.in b/test/config.sh.in index 358005a8..9201a873 100755 --- a/test/config.sh.in +++ b/test/config.sh.in @@ -32,6 +32,7 @@ # # Generated from autotools, ie from the ./configure run, # See configure.ac for source +# See also site.sh # This is for RESTCONF. There are three options: # --without-restconf No restconf support @@ -78,3 +79,5 @@ CERTKEYLEN=2048 LINKAGE=@LINKAGE@ SH_SUFFIX=@SH_SUFFIX@ LIBSTATIC_SUFFIX=@LIBSTATIC_SUFFIX@ +CLIXON_YANG_PATCH=@CLIXON_YANG_PATCH@ + diff --git a/test/test_netconf_hello.sh b/test/test_netconf_hello.sh index a0b23ac5..8fdcb958 100755 --- a/test/test_netconf_hello.sh +++ b/test/test_netconf_hello.sh @@ -56,36 +56,38 @@ wait_backend # Hello new "Netconf snd hello with xmldecl" -expecteof "$clixon_netconf -qf $cfg" 0 "urn:ietf:params:netconf:base:1.1]]>]]>" '^$' '^$' +expecteof "$clixon_netconf -qf $cfg" 0 "urn:ietf:params:netconf:base:1.1]]>]]>" '^$' # Hello, lowercase encoding new "Netconf snd hello with xmldecl (lowercase encoding)" -expecteof "$clixon_netconf -qf $cfg" 0 "urn:ietf:params:netconf:base:1.1]]>]]>" '^$' '^$' +expecteof "$clixon_netconf -qf $cfg" 0 "urn:ietf:params:netconf:base:1.1]]>]]>" '^$' new "Netconf snd hello without xmldecl" -expecteof "$clixon_netconf -qf $cfg" 0 "urn:ietf:params:netconf:base:1.1]]>]]>" '^$' '^$' +expecteof "$clixon_netconf -qf $cfg" 0 "urn:ietf:params:netconf:base:1.1]]>]]>" '^$' new "Netconf snd hello with RFC 4741 base capability" -expecteof "$clixon_netconf -qf $cfg" 0 "urn:ietf:params:netconf:base:1.0]]>]]>" '^$' '^$' +expecteof "$clixon_netconf -qf $cfg" 0 "urn:ietf:params:netconf:base:1.0]]>]]>" '^$' new "Netconf snd hello with wrong base capability" expecteof "$clixon_netconf -qf $cfg" 0 "urn:ietf:params:netconf:base:1.2]]>]]>" '^$' 'Server received hello without netconf base capability urn:ietf:params:netconf:base:1.1' -# This is a case where hello error gets an rpc-error back. Not strictly correct. -new "Netconf hello with session-id is wrong" -expecteof "$clixon_netconf -qf $cfg" 0 "42urn:ietf:params:netconf:base:1.2]]>]]>" '^protocolunknown-elementsession-iderrorUnrecognized hello/capabilities element]]>]]>$' '^$' +new "Netconf hello with MUST NOT have a session-id, terminate" +expecteof "$clixon_netconf -qf $cfg" 0 "42urn:ietf:params:netconf:base:1.2]]>]]>" '^$' # When comparing protocol version capability URIs, only the base part is used, in the event any # parameters are encoded at the end of the URI string. new "Netconf snd hello with base capability with extra arguments" -expecteof "$clixon_netconf -qf $cfg" 0 "urn:ietf:params:netconf:base:1.1?arg=val]]>]]>" '^$' '^$' +expecteof "$clixon_netconf -qf $cfg" 0 "urn:ietf:params:netconf:base:1.1?arg=val]]>]]>" '^$' + +new "Netconf hello with wrong namespace -> terminate" +expecteof "$clixon_netconf -qf $cfg" 0 "urn:ietf:params:netconf:base:1.1]]>]]>" '^$' 2> /dev/null # This is hello - shouldnt really get rpc back? new "Netconf snd hello with wrong prefix" -expecteof "$clixon_netconf -qf $cfg" 0 "urn:ietf:params:netconf:base:1.1]]>]]>" '^$' 'XML error: No appropriate namespace associated with prefix:xx: Bad address' +expecteof "$clixon_netconf -qf $cfg" 0 "urn:ietf:params:netconf:base:1.1]]>]]>" '^$' 2> /dev/null new "Netconf snd hello with prefix" -expecteof "$clixon_netconf -qf $cfg" 0 "urn:ietf:params:netconf:base:1.1]]>]]>" '^$' '^$' +expecteof "$clixon_netconf -qf $cfg" 0 "urn:ietf:params:netconf:base:1.1]]>]]>" '^$' new "netconf snd + rcv hello" expecteof "$clixon_netconf -f $cfg" 0 "urn:ietf:params:netconf:base:1.1]]>]]>" "^urn:ietf:params:netconf:base:1.1urn:ietf:params:netconf:base:1.0urn:ietf:params:netconf:capability:yang-library:1.0?revision=2019-01-04&module-set-id=42urn:ietf:params:netconf:capability:candidate:1.0urn:ietf:params:netconf:capability:validate:1.1urn:ietf:params:netconf:capability:startup:1.0urn:ietf:params:netconf:capability:xpath:1.0urn:ietf:params:netconf:capability:notification:1.0[0-9]*]]>]]>$" '^$' diff --git a/test/test_restconf_yang_patch_json.sh b/test/test_restconf_yang_patch_json.sh index 377066a7..8feddd95 100755 --- a/test/test_restconf_yang_patch_json.sh +++ b/test/test_restconf_yang_patch_json.sh @@ -9,8 +9,8 @@ s="$_" ; . ./lib.sh || if [ "$s" = $0 ]; then exit 0; else return 0; fi # Enable if YANG_PATCH echo "...skipped: YANG_PATCH JSON NYI" -if [ "$s" = $0 ]; then exit 0; else return 0; fi - +if [ -z "${CLIXON_YANG_PATCH}" -a "$s" = $0 ]; then exit 0; else return 0; fi + APPNAME=example cfg=$dir/conf.xml diff --git a/test/test_restconf_yang_patch_xml.sh b/test/test_restconf_yang_patch_xml.sh index 58b16c40..32a233fc 100755 --- a/test/test_restconf_yang_patch_xml.sh +++ b/test/test_restconf_yang_patch_xml.sh @@ -8,7 +8,7 @@ s="$_" ; . ./lib.sh || if [ "$s" = $0 ]; then exit 0; else return 0; fi echo "...skipped: YANG_PATCH XML NYI" -if [ "$s" = $0 ]; then exit 0; else return 0; fi +if [ -z "${CLIXON_YANG_PATCH}" -a "$s" = $0 ]; then exit 0; else return 0; fi APPNAME=example